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
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/** `!!js` 表达式的内存形态(与 DSH / cordis 的 `{__jsExpr}` 逐字同形)。 */
|
|
2
|
+
export interface PatchJsExpr {
|
|
3
|
+
__jsExpr: string;
|
|
4
|
+
}
|
|
5
|
+
/** 与 cordis `isJsExpr` 同判据(`value instanceof Object && '__jsExpr' in value`)。 */
|
|
6
|
+
export declare function isPatchJsExpr(value: unknown): value is PatchJsExpr;
|
|
7
|
+
/** patch 文件的 YAML schema(= DSH 的 `entryListSchema` 同款)。 */
|
|
8
|
+
export declare const PATCH_YAML_SCHEMA: import("js-yaml").Schema;
|
|
9
|
+
/**
|
|
10
|
+
* 载入 patch 文档(任意 YAML 值)。
|
|
11
|
+
*
|
|
12
|
+
* 解析失败**抛出**(不吞):调用方要么把它转成可见告警,要么拒绝覆盖写入 —— 两条路都好过
|
|
13
|
+
* 「当作空文档、把用户的整层配置抹掉」。
|
|
14
|
+
*/
|
|
15
|
+
export declare function loadPatchDocument(text: string): unknown;
|
|
16
|
+
/** 写回 patch 文档:`{__jsExpr}` 还原成 `!!js`,其余按 DSH 的 schema 打印。 */
|
|
17
|
+
export declare function dumpPatchDocument(value: unknown): string;
|
|
18
|
+
/**
|
|
19
|
+
* 解析报错的**安全摘要**:只取首行。
|
|
20
|
+
*
|
|
21
|
+
* 为什么必须截断:js-yaml 的 `Error.message` 会在首行之后附带**出错处的源码片段**,而
|
|
22
|
+
* `cordis.patch.yml` 里可能内联字面量密钥(`!!js` 表达式旁会出现明文 token / API Key)。
|
|
23
|
+
* 这段摘要会流进启动日志、导出告警与浏览器回执 —— 片段一律不得带出去。
|
|
24
|
+
*/
|
|
25
|
+
export declare function describePatchYamlError(err: unknown): string;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `cordis.patch.yml` 的 YAML **方言**(issue #75)—— 宿主侧单一事实源。
|
|
3
|
+
*
|
|
4
|
+
* 为什么不能直接用 `yaml.load` / `yaml.dump`:这份文件不是普通 YAML。DSH 自己读它用的是
|
|
5
|
+
* 「JSON_SCHEMA + 一个自定义标量标签 `!!js`」的方言(`@deepseek-ai/dsh-app-boot`:
|
|
6
|
+
* `const entryListSchema = yaml.JSON_SCHEMA.extend(JsExpr)`,其中
|
|
7
|
+
* `JsExpr = new yaml.Type('tag:yaml.org,2002:js', { kind:'scalar', construct: (data) => ({ __jsExpr: data }), predicate: isJsExpr, represent: (data) => data['__jsExpr'] })`)
|
|
8
|
+
* —— `!!js` 承载的是**行内 JS 表达式**(真机例:`disabled: !!js (function(){ … })()`)。
|
|
9
|
+
*
|
|
10
|
+
* 缺省 schema 遇到 `!!js` 会直接抛 `unknown scalar tag !<tag:yaml.org,2002:js>`(js-yaml 5 实测)。
|
|
11
|
+
* 调用方若把它 catch 成「这一层没有 patch 行」,用户手写的整层配置就会在导出/同步/预览里凭空消失;
|
|
12
|
+
* 导入写回时更会把整份文件重写成「只剩本次导入的行」—— 这正是 issue #75 报告的数据丢失。
|
|
13
|
+
*
|
|
14
|
+
* 两个形状与 DSH 逐字对齐(**改这里等于改对外契约**,见 `docs/spec/bundle-format-v1.md`):
|
|
15
|
+
* - 载入:`!!js <源码>` → `{ __jsExpr: <源码> }`
|
|
16
|
+
* - 写回:`{ __jsExpr: <源码> }` → `!!js <源码>`
|
|
17
|
+
* 判据与 cordis 的 `isJsExpr`(`value instanceof Object && '__jsExpr' in value`)一致,于是 bundle 里
|
|
18
|
+
* 存的 `raw` 既是普通 JSON(可安全过 `JSON.stringify` / 分区 JSON),又能还原成 DSH 认的表达式。
|
|
19
|
+
*
|
|
20
|
+
* 用 `JSON_SCHEMA`(而不是 js-yaml 的缺省 schema)是刻意的:**读法必须与 DSH 一致**,否则同一个文件
|
|
21
|
+
* 我们和 DSH 会看到不同的值(例:`~` 在 YAML 1.2 Core 下是 null,在 JSON_SCHEMA 下是字符串 `"~"`,
|
|
22
|
+
* 而 DSH 用的是后者 —— 导出的 raw 必须与 DSH 读到的相同)。
|
|
23
|
+
*/
|
|
24
|
+
import { JSON_SCHEMA, NOT_RESOLVED, defineScalarTag, dump, load } from 'js-yaml';
|
|
25
|
+
/** 与 cordis `isJsExpr` 同判据(`value instanceof Object && '__jsExpr' in value`)。 */
|
|
26
|
+
export function isPatchJsExpr(value) {
|
|
27
|
+
return typeof value === 'object' && value !== null && '__jsExpr' in value;
|
|
28
|
+
}
|
|
29
|
+
/** `tag:yaml.org,2002:js`(`!!js`):只认显式标签,构造 `{__jsExpr}`,写回还原源码文本。 */
|
|
30
|
+
const jsExprTag = defineScalarTag('tag:yaml.org,2002:js', {
|
|
31
|
+
resolve: (source, isExplicit) => (isExplicit ? { __jsExpr: source } : NOT_RESOLVED),
|
|
32
|
+
identify: isPatchJsExpr,
|
|
33
|
+
represent: (data) => String(data.__jsExpr),
|
|
34
|
+
});
|
|
35
|
+
/** patch 文件的 YAML schema(= DSH 的 `entryListSchema` 同款)。 */
|
|
36
|
+
export const PATCH_YAML_SCHEMA = JSON_SCHEMA.withTags(jsExprTag);
|
|
37
|
+
/**
|
|
38
|
+
* 载入 patch 文档(任意 YAML 值)。
|
|
39
|
+
*
|
|
40
|
+
* 解析失败**抛出**(不吞):调用方要么把它转成可见告警,要么拒绝覆盖写入 —— 两条路都好过
|
|
41
|
+
* 「当作空文档、把用户的整层配置抹掉」。
|
|
42
|
+
*/
|
|
43
|
+
export function loadPatchDocument(text) {
|
|
44
|
+
return load(text, { schema: PATCH_YAML_SCHEMA });
|
|
45
|
+
}
|
|
46
|
+
/** 写回 patch 文档:`{__jsExpr}` 还原成 `!!js`,其余按 DSH 的 schema 打印。 */
|
|
47
|
+
export function dumpPatchDocument(value) {
|
|
48
|
+
return dump(value, { schema: PATCH_YAML_SCHEMA });
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* 解析报错的**安全摘要**:只取首行。
|
|
52
|
+
*
|
|
53
|
+
* 为什么必须截断:js-yaml 的 `Error.message` 会在首行之后附带**出错处的源码片段**,而
|
|
54
|
+
* `cordis.patch.yml` 里可能内联字面量密钥(`!!js` 表达式旁会出现明文 token / API Key)。
|
|
55
|
+
* 这段摘要会流进启动日志、导出告警与浏览器回执 —— 片段一律不得带出去。
|
|
56
|
+
*/
|
|
57
|
+
export function describePatchYamlError(err) {
|
|
58
|
+
const raw = err instanceof Error ? err.message : String(err);
|
|
59
|
+
const firstLine = raw.split('\n', 1)[0] ?? '';
|
|
60
|
+
return firstLine.trim().slice(0, 200);
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=patch-yaml.js.map
|
package/lib/utils/paths.d.ts
CHANGED
|
@@ -8,7 +8,11 @@ export declare function isAbsolutePath(p: string): boolean;
|
|
|
8
8
|
/** ZIP 条目名安全检查(Zip Slip / 绝对路径 / 盘符 / NUL,规范 §19.1-2)。
|
|
9
9
|
* 规则与 node:path 解耦:纯分段校验,跨平台无歧义。 */
|
|
10
10
|
export declare function isPathSafe(entryName: string): boolean;
|
|
11
|
-
/**
|
|
11
|
+
/** 候选目录是否位于父目录之内(含等于父目录)。
|
|
12
|
+
*
|
|
13
|
+
* 纯字符串语义(不碰文件系统):两侧必须是**同一种拼写**,调用方若混用
|
|
14
|
+
* realpath 结果与原路径(Windows 8.3 短名、macOS `/var`→`/private/var`)会误判为越界 ——
|
|
15
|
+
* `path.relative` 不会折叠短名,务必先各自 realpath 再调用。 */
|
|
12
16
|
export declare function isSameOrChild(p: string, parent: string): boolean;
|
|
13
17
|
/**
|
|
14
18
|
* 归一化并折叠 `.` / `..` 路径段(Reviewer B P0 修复)。
|
|
@@ -24,6 +28,11 @@ export declare function isReservedInternalRel(relPath: string): boolean;
|
|
|
24
28
|
/**
|
|
25
29
|
* 前缀批量映射(规范 §12):把对象内所有字符串值中匹配 oldPrefix 的路径
|
|
26
30
|
* 替换为 newPrefix(路径感知:必须落在段边界)。返回新对象(不改原对象)。
|
|
31
|
+
*
|
|
32
|
+
* **Windows 形状路径先折叠大小写再比较**(core-F4):Windows 文件系统大小写不敏感,
|
|
33
|
+
* 用户手输 / 两台机器用户名大小写不同都会让 oldPrefix 与真实值只差大小写 —— 只做逐字比较
|
|
34
|
+
* 会让整条映射**静默失效**(目标机保留源机绝对路径,workspace.path 与会话 cwd 对不上)。
|
|
35
|
+
* POSIX 路径仍逐字比较(/home/Alice 与 /home/alice 是不同目录,不得误匹配)。
|
|
27
36
|
*/
|
|
28
37
|
export declare function applyPrefixMappings(value: unknown, mappings: PathMapping[]): unknown;
|
|
29
38
|
/** 对对象内所有字符串叶节点做变换(迭代式,保留非字符串原样;二进制 Uint8Array 视为叶子) */
|
package/lib/utils/paths.js
CHANGED
|
@@ -47,7 +47,11 @@ export function isPathSafe(entryName) {
|
|
|
47
47
|
return false; // 目录穿越
|
|
48
48
|
return true;
|
|
49
49
|
}
|
|
50
|
-
/**
|
|
50
|
+
/** 候选目录是否位于父目录之内(含等于父目录)。
|
|
51
|
+
*
|
|
52
|
+
* 纯字符串语义(不碰文件系统):两侧必须是**同一种拼写**,调用方若混用
|
|
53
|
+
* realpath 结果与原路径(Windows 8.3 短名、macOS `/var`→`/private/var`)会误判为越界 ——
|
|
54
|
+
* `path.relative` 不会折叠短名,务必先各自 realpath 再调用。 */
|
|
51
55
|
export function isSameOrChild(p, parent) {
|
|
52
56
|
const rel = path.relative(parent, p);
|
|
53
57
|
return rel === '' || (!rel.startsWith('..') && !path.isAbsolute(rel));
|
|
@@ -109,9 +113,21 @@ export function isReservedInternalRel(relPath) {
|
|
|
109
113
|
}
|
|
110
114
|
return false;
|
|
111
115
|
}
|
|
116
|
+
/**
|
|
117
|
+
* Windows 语义路径(盘符 "C:/"、"C:\\";UNC 以两个斜杠或两个反斜杠开头)。
|
|
118
|
+
*
|
|
119
|
+
* 判据是**路径形状**而不是 process.platform:映射的来源可能是另一台机器导出的 Windows 路径
|
|
120
|
+
* (跨平台导入时在 Linux/macOS 上处理),形状决定它在自己的文件系统上大小写不敏感。
|
|
121
|
+
*/
|
|
122
|
+
const WINDOWS_STYLE_PATH_RE = /^[a-zA-Z]:[\\/]|^[\\/]{2}/;
|
|
112
123
|
/**
|
|
113
124
|
* 前缀批量映射(规范 §12):把对象内所有字符串值中匹配 oldPrefix 的路径
|
|
114
125
|
* 替换为 newPrefix(路径感知:必须落在段边界)。返回新对象(不改原对象)。
|
|
126
|
+
*
|
|
127
|
+
* **Windows 形状路径先折叠大小写再比较**(core-F4):Windows 文件系统大小写不敏感,
|
|
128
|
+
* 用户手输 / 两台机器用户名大小写不同都会让 oldPrefix 与真实值只差大小写 —— 只做逐字比较
|
|
129
|
+
* 会让整条映射**静默失效**(目标机保留源机绝对路径,workspace.path 与会话 cwd 对不上)。
|
|
130
|
+
* POSIX 路径仍逐字比较(/home/Alice 与 /home/alice 是不同目录,不得误匹配)。
|
|
115
131
|
*/
|
|
116
132
|
export function applyPrefixMappings(value, mappings) {
|
|
117
133
|
if (mappings.length === 0)
|
|
@@ -123,11 +139,16 @@ export function applyPrefixMappings(value, mappings) {
|
|
|
123
139
|
if (oldNorm === '')
|
|
124
140
|
continue;
|
|
125
141
|
const candidate = normalizePath(out);
|
|
126
|
-
|
|
142
|
+
// 只有两侧都是同一种大小写语义时才折叠:Windows 形状折叠,POSIX 保持逐字
|
|
143
|
+
const fold = WINDOWS_STYLE_PATH_RE.test(oldNorm) || WINDOWS_STYLE_PATH_RE.test(candidate);
|
|
144
|
+
const cmp = (v) => (fold ? v.toLowerCase() : v);
|
|
145
|
+
if (cmp(candidate) === cmp(oldNorm)) {
|
|
127
146
|
out = normalizePath(m.newPrefix);
|
|
128
147
|
continue;
|
|
129
148
|
}
|
|
130
|
-
|
|
149
|
+
// 段边界:先按**原串**切出等长头部再比较(折叠可能改变长度,避免切错位置)
|
|
150
|
+
const head = candidate.slice(0, oldNorm.length);
|
|
151
|
+
if (candidate.length > oldNorm.length && candidate[oldNorm.length] === '/' && cmp(head) === cmp(oldNorm)) {
|
|
131
152
|
const rest = candidate.slice(oldNorm.length); // 含前导 /
|
|
132
153
|
out = normalizePath(normalizePath(m.newPrefix) + rest);
|
|
133
154
|
}
|
|
@@ -15,19 +15,12 @@
|
|
|
15
15
|
*/
|
|
16
16
|
import fs from 'node:fs/promises';
|
|
17
17
|
import path from 'node:path';
|
|
18
|
+
import { isSameOrChild } from './paths.js';
|
|
18
19
|
/** 深度上限:防御病态目录树 / realpath 去重失效时的栈爆炸 */
|
|
19
20
|
const MAX_DEPTH = 64;
|
|
20
21
|
function normalizeSlashes(p) {
|
|
21
22
|
return p.split(path.sep).join('/');
|
|
22
23
|
}
|
|
23
|
-
/** current 是否等于 base 或位于其下(win32 折叠大小写) */
|
|
24
|
-
function isSameOrChild(current, base) {
|
|
25
|
-
const c = path.resolve(current);
|
|
26
|
-
const b = path.resolve(base);
|
|
27
|
-
const cl = process.platform === 'win32' ? c.toLowerCase() : c;
|
|
28
|
-
const bl = process.platform === 'win32' ? b.toLowerCase() : b;
|
|
29
|
-
return cl === bl || cl.startsWith(bl.endsWith(path.sep) ? bl : bl + path.sep);
|
|
30
|
-
}
|
|
31
24
|
async function realpathSafe(p) {
|
|
32
25
|
try {
|
|
33
26
|
return await fs.realpath(p);
|
|
@@ -44,6 +37,11 @@ async function realpathSafe(p) {
|
|
|
44
37
|
export async function listRecursiveFollowingLinks(baseDir, homeDir) {
|
|
45
38
|
const base = path.resolve(baseDir);
|
|
46
39
|
const home = path.resolve(homeDir);
|
|
40
|
+
// 边界判定专用基准:realpath 展开 Windows 8.3 短名(`C:\Users\IUUUUU~1\…` → `C:\Users\iuuuuuuuu\…`)
|
|
41
|
+
// 与 macOS 的 `/var` → `/private/var`,而 path.resolve 保留原拼写。两侧必须同为 realpath 形态,
|
|
42
|
+
// 否则「home 内的目标」会被误判成越界 —— issue #37 的链接跟随在 windows/macos 全红即此因。
|
|
43
|
+
// realpath 失败(路径不存在)时退回原拼写,保持「目录不存在视为空」的既有语义。
|
|
44
|
+
const homeReal = (await realpathSafe(home)) ?? home;
|
|
47
45
|
const paths = [];
|
|
48
46
|
const skippedLinks = [];
|
|
49
47
|
const unreadableDirs = [];
|
|
@@ -53,14 +51,15 @@ export async function listRecursiveFollowingLinks(baseDir, homeDir) {
|
|
|
53
51
|
const rel = (abs) => normalizeSlashes(path.relative(home, abs));
|
|
54
52
|
/** @returns 是否真的进入了该目录(false = 被边界/去重/IO 挡下) */
|
|
55
53
|
const walk = async (dir, depth, viaLink) => {
|
|
56
|
-
|
|
54
|
+
const real = await realpathSafe(dir);
|
|
55
|
+
if (!isSameOrChild(real ?? path.resolve(dir), homeReal))
|
|
57
56
|
return false;
|
|
58
57
|
if (depth > MAX_DEPTH) {
|
|
59
|
-
|
|
60
|
-
|
|
58
|
+
// 深度上限必须**可见**(cli-F2):此前只对链接记 too-deep —— **普通目录**超深时整块内容
|
|
59
|
+
// 被裁掉却既不在 skippedLinks 也不在 unreadableDirs 里,备份照样报成功(issue #37 同类症状)。
|
|
60
|
+
skippedLinks.push({ path: viaLink ?? rel(dir), reason: 'too-deep' });
|
|
61
61
|
return false;
|
|
62
62
|
}
|
|
63
|
-
const real = await realpathSafe(dir);
|
|
64
63
|
// 去重只针对**链接**:链接目标已经进过(自引用 / 两条链接指向同一处)→ 跳过。
|
|
65
64
|
// 普通目录永远遍历(否则「真实目录 + 指向它的链接」会有一边被静默吞掉)。
|
|
66
65
|
if (viaLink !== null && real !== null && visited.has(real)) {
|
|
@@ -108,7 +107,7 @@ export async function listRecursiveFollowingLinks(baseDir, homeDir) {
|
|
|
108
107
|
// 只对目录链接做这个检查会漏掉「skills/link.md → ~/外部文件」:
|
|
109
108
|
// 内容会被读进备份(T2-P3 实测就是这种文件链接,属真实越界读取)。
|
|
110
109
|
const target = await realpathSafe(abs);
|
|
111
|
-
if (target === null || !isSameOrChild(target,
|
|
110
|
+
if (target === null || !isSameOrChild(target, homeReal)) {
|
|
112
111
|
skippedLinks.push({ path: entryRel, reason: 'outside-home' });
|
|
113
112
|
continue;
|
|
114
113
|
}
|
|
@@ -10,13 +10,46 @@ export declare const MAX_PROBED_SESSION_LOGS = 200;
|
|
|
10
10
|
export declare function parseSessionFormatVersion(source: string): number | undefined;
|
|
11
11
|
/** 从 `<node_modules>/@deepseek-ai/dsh-session/lib/index.js` 读格式常量;读不到 → undefined。 */
|
|
12
12
|
export declare function readSessionFormatVersionAt(nodeModulesDir: string): number | undefined;
|
|
13
|
+
/** pnpm 段名 → 版本(`…@<version>[_<peerHash>]`);不是 dsh-session 段 → undefined。 */
|
|
14
|
+
export declare function pnpmSessionEntryVersion(entryName: string): string | undefined;
|
|
15
|
+
/** 从 startDir 起向上找最近的 `.pnpm` 存储目录;找不到 → undefined。 */
|
|
16
|
+
export declare function findPnpmStore(startDir: string): string | undefined;
|
|
17
|
+
/**
|
|
18
|
+
* pnpm 隔离布局下 dsh-session 的候选 node_modules 根(issue #74)。
|
|
19
|
+
*
|
|
20
|
+
* 为什么需要:pnpm 全局安装 DSH 时,installAnchor 落在
|
|
21
|
+
* `<…>/node_modules/.pnpm/@deepseek-ai+dsh@<ver>_<hash>/node_modules/@deepseek-ai/dsh/package.json`
|
|
22
|
+
* 而它的同级 @deepseek-ai 下**没有** dsh-session(`dsh` 的 dependencies 里也没有它,只有
|
|
23
|
+
* dsh-session-projection / -reference),`dsh/node_modules` 同样不存在 —— 「同级目录拼路径」
|
|
24
|
+
* 在隔离布局下必然落空。真实的 dsh-session 在**同一 store 的另一个段**里:
|
|
25
|
+
* `<store>/@deepseek-ai+dsh-session@<ver>_<hash>/node_modules/@deepseek-ai/dsh-session/lib/index.js`
|
|
26
|
+
*
|
|
27
|
+
* 多个版本共存时取「与本机 dsh 同版本」的那个(DSH 内部包按同一版本号一起发布);
|
|
28
|
+
* 同版本多份(peer 哈希不同)等价,全试。**版本读不出来且不止一个候选 → 返回空(不猜)**:
|
|
29
|
+
* 体检宁可整体跳过,也不能拿另一份 dsh-session 的常量谎报本机格式。
|
|
30
|
+
*/
|
|
31
|
+
export declare function pnpmSessionFormatRoots(nodeModulesDir: string, dshVersion?: string): string[];
|
|
32
|
+
/**
|
|
33
|
+
* 一个「同树」根展开成全部候选(顺序即真伪顺序):
|
|
34
|
+
* ① hoisted 同级 `<nm>/@deepseek-ai/dsh-session`
|
|
35
|
+
* ② dsh 自己的嵌套 `<nm>/@deepseek-ai/dsh/node_modules/@deepseek-ai/dsh-session`
|
|
36
|
+
* ③ pnpm 隔离 store(见 `pnpmSessionFormatRoots`)
|
|
37
|
+
*/
|
|
38
|
+
export declare function sessionFormatRoots(nodeModulesDir: string, dshVersion?: string): string[];
|
|
39
|
+
/** 在一棵(含 pnpm 存储的)依赖树里读格式常量;读不到 → undefined(不猜)。 */
|
|
40
|
+
export declare function readSessionFormatVersionInTree(nodeModulesDir: string, dshVersion?: string): number | undefined;
|
|
41
|
+
/** 读一个 package.json 的 version(只读;不可读 / 不是非空字符串 → undefined)。 */
|
|
42
|
+
export declare function readPackageVersionAt(packageJsonPath: string): string | undefined;
|
|
13
43
|
/**
|
|
14
44
|
* 按「@deepseek-ai/dsh/package.json 的路径」候选逐个找同树的会话格式常量。
|
|
15
45
|
*
|
|
16
46
|
* 顺序即真伪顺序(与 `resolveDshVersion` 同源):installAnchor(拉起本宿主的那份运行时,
|
|
17
|
-
* 桌面端在 app.asar
|
|
47
|
+
* 桌面端在 app.asar 内)优先,其次该档案自己的依赖树。每处再试三种布局(见 `sessionFormatRoots`)。
|
|
48
|
+
*
|
|
49
|
+
* `tried` 可选:收集**所有尝试过的路径**(解析失败时由调用方写进日志——真机排查看的是这个,
|
|
50
|
+
* 而不是一句「解析不到」)。
|
|
18
51
|
*/
|
|
19
|
-
export declare function resolveSessionFormatVersion(dshPackageJsonCandidates: readonly string[]): number | undefined;
|
|
52
|
+
export declare function resolveSessionFormatVersion(dshPackageJsonCandidates: readonly string[], tried?: string[]): number | undefined;
|
|
20
53
|
/** 体检输入:备份里 sessions 分区的条目(`data` 是归档内的原始字节)。 */
|
|
21
54
|
export interface SessionFormatProbeFile {
|
|
22
55
|
relativePath: string;
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
* 不显示,用户看到的就是「对话消失」。高版本能读低版本(DSH 自带 V0→V4 迁移链),
|
|
12
12
|
* 反向不可读,所以「桌面端(新)导出 → 旧 CLI 档案导入」必须在导入前说清楚。
|
|
13
13
|
*/
|
|
14
|
-
import { existsSync, readFileSync, statSync } from 'node:fs';
|
|
14
|
+
import { existsSync, readdirSync, readFileSync, statSync } from 'node:fs';
|
|
15
15
|
import { dirname, join } from 'node:path';
|
|
16
16
|
import { isSessionLogName, readLogHeaderFromBytes } from './session-log.js';
|
|
17
17
|
/** DSH 会话包(相对 node_modules)。 */
|
|
@@ -47,17 +47,143 @@ export function readSessionFormatVersionAt(nodeModulesDir) {
|
|
|
47
47
|
return undefined;
|
|
48
48
|
}
|
|
49
49
|
}
|
|
50
|
+
/* ------------------------------- 布局展开:hoisted / dsh 嵌套 / pnpm 隔离(issue #74) */
|
|
51
|
+
/** pnpm 隔离布局的存储目录名(`<node_modules>/.pnpm`)。 */
|
|
52
|
+
const PNPM_STORE_DIR = '.pnpm';
|
|
53
|
+
/**
|
|
54
|
+
* pnpm 段名前缀(`@deepseek-ai+dsh-session@<version>[_<peerHash>]`)。
|
|
55
|
+
* 末尾那个 `@` 是必须的:`@deepseek-ai+dsh-session-projection@…` 也以同名开头,但它**不是**我们要的包。
|
|
56
|
+
*/
|
|
57
|
+
const PNPM_SESSION_ENTRY_PREFIX = '@deepseek-ai+dsh-session@';
|
|
58
|
+
/** 向上找存储目录的最大层数(隔离安装下锚点本身就在 store 段内,最多要爬 4 层)。 */
|
|
59
|
+
const PNPM_UPWARD_LEVELS = 8;
|
|
60
|
+
/** pnpm 段名 → 版本(`…@<version>[_<peerHash>]`);不是 dsh-session 段 → undefined。 */
|
|
61
|
+
export function pnpmSessionEntryVersion(entryName) {
|
|
62
|
+
if (!entryName.startsWith(PNPM_SESSION_ENTRY_PREFIX))
|
|
63
|
+
return undefined;
|
|
64
|
+
const rest = entryName.slice(PNPM_SESSION_ENTRY_PREFIX.length);
|
|
65
|
+
if (rest === '')
|
|
66
|
+
return undefined;
|
|
67
|
+
// semver 标识符里不含 '_',pnpm 用它拼接 peer 后缀(如 @a@1.0.0_react@18.2.0)
|
|
68
|
+
const peerAt = rest.indexOf('_');
|
|
69
|
+
return peerAt === -1 ? rest : rest.slice(0, peerAt);
|
|
70
|
+
}
|
|
71
|
+
/** 从 startDir 起向上找最近的 `.pnpm` 存储目录;找不到 → undefined。 */
|
|
72
|
+
export function findPnpmStore(startDir) {
|
|
73
|
+
let dir = startDir;
|
|
74
|
+
for (let level = 0; level < PNPM_UPWARD_LEVELS; level++) {
|
|
75
|
+
const candidate = join(dir, PNPM_STORE_DIR);
|
|
76
|
+
try {
|
|
77
|
+
if (statSync(candidate).isDirectory())
|
|
78
|
+
return candidate;
|
|
79
|
+
}
|
|
80
|
+
catch {
|
|
81
|
+
/* 这一层没有 .pnpm(或读不到)→ 继续向上 */
|
|
82
|
+
}
|
|
83
|
+
const parent = dirname(dir);
|
|
84
|
+
if (parent === dir)
|
|
85
|
+
break;
|
|
86
|
+
dir = parent;
|
|
87
|
+
}
|
|
88
|
+
return undefined;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* pnpm 隔离布局下 dsh-session 的候选 node_modules 根(issue #74)。
|
|
92
|
+
*
|
|
93
|
+
* 为什么需要:pnpm 全局安装 DSH 时,installAnchor 落在
|
|
94
|
+
* `<…>/node_modules/.pnpm/@deepseek-ai+dsh@<ver>_<hash>/node_modules/@deepseek-ai/dsh/package.json`
|
|
95
|
+
* 而它的同级 @deepseek-ai 下**没有** dsh-session(`dsh` 的 dependencies 里也没有它,只有
|
|
96
|
+
* dsh-session-projection / -reference),`dsh/node_modules` 同样不存在 —— 「同级目录拼路径」
|
|
97
|
+
* 在隔离布局下必然落空。真实的 dsh-session 在**同一 store 的另一个段**里:
|
|
98
|
+
* `<store>/@deepseek-ai+dsh-session@<ver>_<hash>/node_modules/@deepseek-ai/dsh-session/lib/index.js`
|
|
99
|
+
*
|
|
100
|
+
* 多个版本共存时取「与本机 dsh 同版本」的那个(DSH 内部包按同一版本号一起发布);
|
|
101
|
+
* 同版本多份(peer 哈希不同)等价,全试。**版本读不出来且不止一个候选 → 返回空(不猜)**:
|
|
102
|
+
* 体检宁可整体跳过,也不能拿另一份 dsh-session 的常量谎报本机格式。
|
|
103
|
+
*/
|
|
104
|
+
export function pnpmSessionFormatRoots(nodeModulesDir, dshVersion) {
|
|
105
|
+
const store = findPnpmStore(nodeModulesDir);
|
|
106
|
+
if (store === undefined)
|
|
107
|
+
return [];
|
|
108
|
+
let entries;
|
|
109
|
+
try {
|
|
110
|
+
entries = readdirSync(store).filter((name) => name.startsWith(PNPM_SESSION_ENTRY_PREFIX));
|
|
111
|
+
}
|
|
112
|
+
catch {
|
|
113
|
+
return [];
|
|
114
|
+
}
|
|
115
|
+
if (entries.length === 0)
|
|
116
|
+
return [];
|
|
117
|
+
let chosen;
|
|
118
|
+
if (typeof dshVersion === 'string' && dshVersion !== '') {
|
|
119
|
+
const exact = entries.filter((name) => pnpmSessionEntryVersion(name) === dshVersion);
|
|
120
|
+
if (exact.length > 0)
|
|
121
|
+
chosen = exact;
|
|
122
|
+
else if (entries.length === 1)
|
|
123
|
+
chosen = entries;
|
|
124
|
+
else
|
|
125
|
+
return [];
|
|
126
|
+
}
|
|
127
|
+
else if (entries.length === 1) {
|
|
128
|
+
chosen = entries;
|
|
129
|
+
}
|
|
130
|
+
else {
|
|
131
|
+
return [];
|
|
132
|
+
}
|
|
133
|
+
return chosen.sort().map((name) => join(store, name, 'node_modules'));
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* 一个「同树」根展开成全部候选(顺序即真伪顺序):
|
|
137
|
+
* ① hoisted 同级 `<nm>/@deepseek-ai/dsh-session`
|
|
138
|
+
* ② dsh 自己的嵌套 `<nm>/@deepseek-ai/dsh/node_modules/@deepseek-ai/dsh-session`
|
|
139
|
+
* ③ pnpm 隔离 store(见 `pnpmSessionFormatRoots`)
|
|
140
|
+
*/
|
|
141
|
+
export function sessionFormatRoots(nodeModulesDir, dshVersion) {
|
|
142
|
+
return [
|
|
143
|
+
nodeModulesDir,
|
|
144
|
+
join(nodeModulesDir, '@deepseek-ai', 'dsh', 'node_modules'),
|
|
145
|
+
...pnpmSessionFormatRoots(nodeModulesDir, dshVersion),
|
|
146
|
+
];
|
|
147
|
+
}
|
|
148
|
+
/** 在一棵(含 pnpm 存储的)依赖树里读格式常量;读不到 → undefined(不猜)。 */
|
|
149
|
+
export function readSessionFormatVersionInTree(nodeModulesDir, dshVersion) {
|
|
150
|
+
for (const root of sessionFormatRoots(nodeModulesDir, dshVersion)) {
|
|
151
|
+
const version = readSessionFormatVersionAt(root);
|
|
152
|
+
if (version !== undefined)
|
|
153
|
+
return version;
|
|
154
|
+
}
|
|
155
|
+
return undefined;
|
|
156
|
+
}
|
|
157
|
+
/** 读一个 package.json 的 version(只读;不可读 / 不是非空字符串 → undefined)。 */
|
|
158
|
+
export function readPackageVersionAt(packageJsonPath) {
|
|
159
|
+
try {
|
|
160
|
+
const parsed = JSON.parse(readFileSync(packageJsonPath, 'utf8'));
|
|
161
|
+
if (parsed === null || typeof parsed !== 'object')
|
|
162
|
+
return undefined;
|
|
163
|
+
const version = parsed.version;
|
|
164
|
+
return typeof version === 'string' && version !== '' ? version : undefined;
|
|
165
|
+
}
|
|
166
|
+
catch {
|
|
167
|
+
return undefined;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
/* ------------------------------------------------------------- 解析入口 */
|
|
50
171
|
/**
|
|
51
172
|
* 按「@deepseek-ai/dsh/package.json 的路径」候选逐个找同树的会话格式常量。
|
|
52
173
|
*
|
|
53
174
|
* 顺序即真伪顺序(与 `resolveDshVersion` 同源):installAnchor(拉起本宿主的那份运行时,
|
|
54
|
-
* 桌面端在 app.asar
|
|
175
|
+
* 桌面端在 app.asar 内)优先,其次该档案自己的依赖树。每处再试三种布局(见 `sessionFormatRoots`)。
|
|
176
|
+
*
|
|
177
|
+
* `tried` 可选:收集**所有尝试过的路径**(解析失败时由调用方写进日志——真机排查看的是这个,
|
|
178
|
+
* 而不是一句「解析不到」)。
|
|
55
179
|
*/
|
|
56
|
-
export function resolveSessionFormatVersion(dshPackageJsonCandidates) {
|
|
180
|
+
export function resolveSessionFormatVersion(dshPackageJsonCandidates, tried = []) {
|
|
57
181
|
for (const candidate of dshPackageJsonCandidates) {
|
|
58
182
|
const nodeModulesDir = join(dirname(candidate), '..', '..');
|
|
59
|
-
|
|
60
|
-
|
|
183
|
+
// 本机 dsh 版本只用于在 pnpm store 的多个 dsh-session 之间挑同版本者;读不到就不挑(见上)。
|
|
184
|
+
const dshVersion = readPackageVersionAt(candidate);
|
|
185
|
+
for (const root of sessionFormatRoots(nodeModulesDir, dshVersion)) {
|
|
186
|
+
tried.push(root);
|
|
61
187
|
const version = readSessionFormatVersionAt(root);
|
|
62
188
|
if (version !== undefined)
|
|
63
189
|
return version;
|
|
@@ -12,7 +12,13 @@ export interface SessionHealthScanOptions {
|
|
|
12
12
|
targetFormatVersion?: number;
|
|
13
13
|
/** 本机工作区记录的 cwd 目录键(`projectKeyOf(path)`) */
|
|
14
14
|
workspaceKeys?: ReadonlySet<string>;
|
|
15
|
-
/**
|
|
15
|
+
/**
|
|
16
|
+
* 本机全部已知会话 id 的归一化键(父对话存在性判定)。
|
|
17
|
+
*
|
|
18
|
+
* **不传 = 未知**(调用方没有本机会话全量清单)→ 采集器**自证**:用本次遍历到的全部单元 id
|
|
19
|
+
* 作为已知集合(见 `scanSessionHealth`),绝不伪造成「确知为空集」;传了就用调用方的
|
|
20
|
+
* (UI 侧 `parentRelations` 更权威:它连注册表里的会话一起算)。
|
|
21
|
+
*/
|
|
16
22
|
knownSessionIds?: ReadonlySet<string>;
|
|
17
23
|
/** 出现在多个 projectKey 的会话 id(归一化键) */
|
|
18
24
|
duplicateSessionIds?: ReadonlySet<string>;
|