devchain-cli 0.24.1 → 0.24.2
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/dist/build-info.json +2 -2
- package/dist/cli.js +40 -10
- package/dist/host-install/devchain-host-bootstrap.tgz +0 -0
- package/dist/host-install/pins.json +31 -2
- package/dist/lib/exclusive-run.js +51 -3
- package/dist/lib/git-owner.js +284 -0
- package/dist/lib/host-install.js +19 -151
- package/dist/lib/local-api.js +175 -0
- package/dist/server/common/config/env.config.d.ts +3 -0
- package/dist/server/common/config/env.config.js +1 -0
- package/dist/server/common/config/env.config.js.map +1 -1
- package/dist/server/common/config/host-image.json +3 -3
- package/dist/server/common/constants/syncthing-markers.d.ts +1 -0
- package/dist/server/common/constants/syncthing-markers.js +6 -1
- package/dist/server/common/constants/syncthing-markers.js.map +1 -1
- package/dist/server/common/filesystem/vm-home-path.d.ts +11 -0
- package/dist/server/common/filesystem/vm-home-path.js +48 -0
- package/dist/server/common/filesystem/vm-home-path.js.map +1 -0
- package/dist/server/common/process-ids-env.d.ts +1 -0
- package/dist/server/common/process-ids-env.js +13 -0
- package/dist/server/common/process-ids-env.js.map +1 -0
- package/dist/server/common/test/api-test-app.d.ts +12 -0
- package/dist/server/common/test/api-test-app.js +76 -0
- package/dist/server/common/test/api-test-app.js.map +1 -0
- package/dist/server/common/test/app-bootstrap.helper.js +8 -1
- package/dist/server/common/test/app-bootstrap.helper.js.map +1 -1
- package/dist/server/common/test/fake-bootstrap.server.js +3 -2
- package/dist/server/common/test/fake-bootstrap.server.js.map +1 -1
- package/dist/server/common/test/fake-docker-engine.server.d.ts +17 -6
- package/dist/server/common/test/fake-docker-engine.server.js +77 -33
- package/dist/server/common/test/fake-docker-engine.server.js.map +1 -1
- package/dist/server/common/test/fake-proxmox.server.js +4 -4
- package/dist/server/common/test/fake-ssh.server.js +6 -6
- package/dist/server/common/test/fake-ssh.server.js.map +1 -1
- package/dist/server/common/test/test-database.helper.d.ts +6 -0
- package/dist/server/common/test/test-database.helper.js +29 -0
- package/dist/server/common/test/test-database.helper.js.map +1 -0
- package/dist/server/modules/core/controllers/docker-archive.js +1 -1
- package/dist/server/modules/core/controllers/docker-archive.js.map +1 -1
- package/dist/server/modules/core/controllers/docker-engine.client.d.ts +2 -1
- package/dist/server/modules/core/controllers/docker-engine.client.js +8 -4
- package/dist/server/modules/core/controllers/docker-engine.client.js.map +1 -1
- package/dist/server/modules/core/controllers/docker-image-metadata.d.ts +248 -0
- package/dist/server/modules/core/controllers/docker-image-metadata.js +161 -0
- package/dist/server/modules/core/controllers/docker-image-metadata.js.map +1 -0
- package/dist/server/modules/core/controllers/docker-settings.d.ts +13 -2
- package/dist/server/modules/core/controllers/docker-settings.js +49 -11
- package/dist/server/modules/core/controllers/docker-settings.js.map +1 -1
- package/dist/server/modules/core/controllers/host-user-identity.d.ts +34 -0
- package/dist/server/modules/core/controllers/host-user-identity.js +23 -0
- package/dist/server/modules/core/controllers/host-user-identity.js.map +1 -0
- package/dist/server/modules/core/controllers/runtime.controller.d.ts +11 -4
- package/dist/server/modules/core/controllers/runtime.controller.js +2 -0
- package/dist/server/modules/core/controllers/runtime.controller.js.map +1 -1
- package/dist/server/modules/file-sync/build-exclusion-suggestions.d.ts +15 -0
- package/dist/server/modules/file-sync/build-exclusion-suggestions.js +402 -0
- package/dist/server/modules/file-sync/build-exclusion-suggestions.js.map +1 -0
- package/dist/server/modules/file-sync/file-sync-auto-fix.dto.d.ts +102 -0
- package/dist/server/modules/file-sync/file-sync-auto-fix.dto.js +22 -0
- package/dist/server/modules/file-sync/file-sync-auto-fix.dto.js.map +1 -0
- package/dist/server/modules/file-sync/file-sync-auto-fix.store.d.ts +12 -0
- package/dist/server/modules/file-sync/file-sync-auto-fix.store.js +73 -0
- package/dist/server/modules/file-sync/file-sync-auto-fix.store.js.map +1 -0
- package/dist/server/modules/file-sync/file-sync-conflicts.d.ts +3 -0
- package/dist/server/modules/file-sync/file-sync-conflicts.js +191 -0
- package/dist/server/modules/file-sync/file-sync-conflicts.js.map +1 -0
- package/dist/server/modules/file-sync/file-sync-ignores.store.d.ts +5 -1
- package/dist/server/modules/file-sync/file-sync-ignores.store.js +39 -8
- package/dist/server/modules/file-sync/file-sync-ignores.store.js.map +1 -1
- package/dist/server/modules/file-sync/file-sync.controller.d.ts +1 -3
- package/dist/server/modules/file-sync/file-sync.controller.js +5 -14
- package/dist/server/modules/file-sync/file-sync.controller.js.map +1 -1
- package/dist/server/modules/file-sync/file-sync.dto.d.ts +220 -1
- package/dist/server/modules/file-sync/file-sync.dto.js +70 -4
- package/dist/server/modules/file-sync/file-sync.dto.js.map +1 -1
- package/dist/server/modules/file-sync/file-sync.module.js +16 -1
- package/dist/server/modules/file-sync/file-sync.module.js.map +1 -1
- package/dist/server/modules/file-sync/file-sync.service.d.ts +18 -4
- package/dist/server/modules/file-sync/file-sync.service.js +166 -34
- package/dist/server/modules/file-sync/file-sync.service.js.map +1 -1
- package/dist/server/modules/file-sync/git-guard.dto.d.ts +61 -0
- package/dist/server/modules/file-sync/git-guard.dto.js +26 -0
- package/dist/server/modules/file-sync/git-guard.dto.js.map +1 -0
- package/dist/server/modules/file-sync/home-git-guard.service.d.ts +4 -2
- package/dist/server/modules/file-sync/home-git-guard.service.js +50 -25
- package/dist/server/modules/file-sync/home-git-guard.service.js.map +1 -1
- package/dist/server/modules/file-sync/host-git-guard.controller.d.ts +10 -0
- package/dist/server/modules/file-sync/host-git-guard.controller.js +64 -0
- package/dist/server/modules/file-sync/host-git-guard.controller.js.map +1 -0
- package/dist/server/modules/file-sync/host-git-index.controller.d.ts +9 -0
- package/dist/server/modules/file-sync/host-git-index.controller.js +67 -0
- package/dist/server/modules/file-sync/host-git-index.controller.js.map +1 -0
- package/dist/server/modules/file-sync/host-sync.controller.d.ts +15 -2
- package/dist/server/modules/file-sync/host-sync.controller.js +122 -14
- package/dist/server/modules/file-sync/host-sync.controller.js.map +1 -1
- package/dist/server/modules/file-sync/ignore-pattern-matcher.d.ts +30 -0
- package/dist/server/modules/file-sync/ignore-pattern-matcher.js +183 -0
- package/dist/server/modules/file-sync/ignore-pattern-matcher.js.map +1 -0
- package/dist/server/modules/file-sync/project-repository.d.ts +2 -0
- package/dist/server/modules/file-sync/project-repository.js +20 -0
- package/dist/server/modules/file-sync/project-repository.js.map +1 -0
- package/dist/server/modules/file-sync/sync-chown.dto.d.ts +99 -0
- package/dist/server/modules/file-sync/sync-chown.dto.js +46 -0
- package/dist/server/modules/file-sync/sync-chown.dto.js.map +1 -0
- package/dist/server/modules/file-sync/sync-chown.service.d.ts +12 -0
- package/dist/server/modules/file-sync/sync-chown.service.js +230 -0
- package/dist/server/modules/file-sync/sync-chown.service.js.map +1 -0
- package/dist/server/modules/file-sync/sync-path-inspection.dto.d.ts +626 -0
- package/dist/server/modules/file-sync/sync-path-inspection.dto.js +108 -0
- package/dist/server/modules/file-sync/sync-path-inspection.dto.js.map +1 -0
- package/dist/server/modules/file-sync/sync-path-inspector.d.ts +12 -0
- package/dist/server/modules/file-sync/sync-path-inspector.js +413 -0
- package/dist/server/modules/file-sync/sync-path-inspector.js.map +1 -0
- package/dist/server/modules/file-sync/testing/fake-file-sync.service.d.ts +27 -4
- package/dist/server/modules/file-sync/testing/fake-file-sync.service.js +66 -4
- package/dist/server/modules/file-sync/testing/fake-file-sync.service.js.map +1 -1
- package/dist/server/modules/file-sync/translate-git-ignore-rule.d.ts +3 -0
- package/dist/server/modules/file-sync/translate-git-ignore-rule.js +30 -0
- package/dist/server/modules/file-sync/translate-git-ignore-rule.js.map +1 -0
- package/dist/server/modules/mcp/services/handlers/skill-tools.js +2 -2
- package/dist/server/modules/mcp/services/handlers/skill-tools.js.map +1 -1
- package/dist/server/modules/remotes/connect-choices.controller.d.ts +9 -0
- package/dist/server/modules/remotes/connect-choices.controller.js +54 -0
- package/dist/server/modules/remotes/connect-choices.controller.js.map +1 -0
- package/dist/server/modules/remotes/connect-choices.dto.d.ts +52 -0
- package/dist/server/modules/remotes/connect-choices.dto.js +19 -0
- package/dist/server/modules/remotes/connect-choices.dto.js.map +1 -0
- package/dist/server/modules/remotes/connect-choices.store.d.ts +12 -0
- package/dist/server/modules/remotes/connect-choices.store.js +95 -0
- package/dist/server/modules/remotes/connect-choices.store.js.map +1 -0
- package/dist/server/modules/remotes/controllers/remotes.controller.d.ts +3 -0
- package/dist/server/modules/remotes/controllers/remotes.controller.js +9 -1
- package/dist/server/modules/remotes/controllers/remotes.controller.js.map +1 -1
- package/dist/server/modules/remotes/docker/docker-copy-back.js +40 -16
- package/dist/server/modules/remotes/docker/docker-copy-back.js.map +1 -1
- package/dist/server/modules/remotes/docker/docker-handoff.d.ts +5 -3
- package/dist/server/modules/remotes/docker/docker-handoff.js +146 -42
- package/dist/server/modules/remotes/docker/docker-handoff.js.map +1 -1
- package/dist/server/modules/remotes/docker/docker-handoff.store.d.ts +3 -0
- package/dist/server/modules/remotes/docker/docker-handoff.store.js.map +1 -1
- package/dist/server/modules/remotes/docker/docker-plan-fit.d.ts +4 -1
- package/dist/server/modules/remotes/docker/docker-plan-fit.js +19 -6
- package/dist/server/modules/remotes/docker/docker-plan-fit.js.map +1 -1
- package/dist/server/modules/remotes/docker/docker-plan-policy.d.ts +6 -2
- package/dist/server/modules/remotes/docker/docker-plan-policy.js +191 -38
- package/dist/server/modules/remotes/docker/docker-plan-policy.js.map +1 -1
- package/dist/server/modules/remotes/docker/docker-plan-source.service.d.ts +52 -8
- package/dist/server/modules/remotes/docker/docker-plan-source.service.js +273 -50
- package/dist/server/modules/remotes/docker/docker-plan-source.service.js.map +1 -1
- package/dist/server/modules/remotes/docker/docker-plan.controller.d.ts +2 -1
- package/dist/server/modules/remotes/docker/docker-plan.controller.js +14 -0
- package/dist/server/modules/remotes/docker/docker-plan.controller.js.map +1 -1
- package/dist/server/modules/remotes/docker/docker-plan.dto.d.ts +46 -1
- package/dist/server/modules/remotes/docker/docker-plan.dto.js +1 -0
- package/dist/server/modules/remotes/docker/docker-plan.dto.js.map +1 -1
- package/dist/server/modules/remotes/docker/docker-plan.service.d.ts +13 -7
- package/dist/server/modules/remotes/docker/docker-plan.service.js +57 -13
- package/dist/server/modules/remotes/docker/docker-plan.service.js.map +1 -1
- package/dist/server/modules/remotes/docker/docker-project-compose.d.ts +7 -0
- package/dist/server/modules/remotes/docker/docker-project-compose.js +30 -0
- package/dist/server/modules/remotes/docker/docker-project-compose.js.map +1 -0
- package/dist/server/modules/remotes/dtos/remote.dto.d.ts +2 -0
- package/dist/server/modules/remotes/dtos/remote.dto.js.map +1 -1
- package/dist/server/modules/remotes/git-owner.store.d.ts +13 -0
- package/dist/server/modules/remotes/git-owner.store.js +69 -0
- package/dist/server/modules/remotes/git-owner.store.js.map +1 -0
- package/dist/server/modules/remotes/host/host-docker.controller.d.ts +8 -0
- package/dist/server/modules/remotes/host/host-docker.controller.js +22 -6
- package/dist/server/modules/remotes/host/host-docker.controller.js.map +1 -1
- package/dist/server/modules/remotes/host/host-docker.dto.d.ts +606 -0
- package/dist/server/modules/remotes/host/host-docker.dto.js +47 -7
- package/dist/server/modules/remotes/host/host-docker.dto.js.map +1 -1
- package/dist/server/modules/remotes/host/host-docker.service.d.ts +16 -4
- package/dist/server/modules/remotes/host/host-docker.service.js +157 -82
- package/dist/server/modules/remotes/host/host-docker.service.js.map +1 -1
- package/dist/server/modules/remotes/host/host-ipv4-routes.d.ts +4 -0
- package/dist/server/modules/remotes/host/host-ipv4-routes.js +43 -0
- package/dist/server/modules/remotes/host/host-ipv4-routes.js.map +1 -0
- package/dist/server/modules/remotes/host-image.d.ts +1 -1
- package/dist/server/modules/remotes/host-image.js +1 -1
- package/dist/server/modules/remotes/host-install/host-install-block.d.ts +1 -0
- package/dist/server/modules/remotes/host-install/host-install-block.js +76 -2
- package/dist/server/modules/remotes/host-install/host-install-block.js.map +1 -1
- package/dist/server/modules/remotes/host-install/host-install.service.d.ts +0 -1
- package/dist/server/modules/remotes/host-install/host-install.service.js +9 -26
- package/dist/server/modules/remotes/host-install/host-install.service.js.map +1 -1
- package/dist/server/modules/remotes/operations/attach.operation.d.ts +5 -1
- package/dist/server/modules/remotes/operations/attach.operation.js +40 -5
- package/dist/server/modules/remotes/operations/attach.operation.js.map +1 -1
- package/dist/server/modules/remotes/operations/claim.operation.d.ts +1 -0
- package/dist/server/modules/remotes/operations/claim.operation.js +6 -1
- package/dist/server/modules/remotes/operations/claim.operation.js.map +1 -1
- package/dist/server/modules/remotes/operations/detach.operation.d.ts +4 -1
- package/dist/server/modules/remotes/operations/detach.operation.js +10 -2
- package/dist/server/modules/remotes/operations/detach.operation.js.map +1 -1
- package/dist/server/modules/remotes/operations/docker-import-inventory.store.d.ts +4 -0
- package/dist/server/modules/remotes/operations/docker-import-inventory.store.js +11 -0
- package/dist/server/modules/remotes/operations/docker-import-inventory.store.js.map +1 -1
- package/dist/server/modules/remotes/operations/file-sync-handoff.d.ts +29 -3
- package/dist/server/modules/remotes/operations/file-sync-handoff.js +477 -50
- package/dist/server/modules/remotes/operations/file-sync-handoff.js.map +1 -1
- package/dist/server/modules/remotes/operations/force-sync.operation.d.ts +39 -0
- package/dist/server/modules/remotes/operations/force-sync.operation.js +177 -0
- package/dist/server/modules/remotes/operations/force-sync.operation.js.map +1 -0
- package/dist/server/modules/remotes/operations/git-owner.dto.d.ts +83 -0
- package/dist/server/modules/remotes/operations/git-owner.dto.js +25 -0
- package/dist/server/modules/remotes/operations/git-owner.dto.js.map +1 -0
- package/dist/server/modules/remotes/operations/git-owner.operation.d.ts +35 -0
- package/dist/server/modules/remotes/operations/git-owner.operation.js +216 -0
- package/dist/server/modules/remotes/operations/git-owner.operation.js.map +1 -0
- package/dist/server/modules/remotes/operations/remote-host.client.d.ts +71 -7
- package/dist/server/modules/remotes/operations/remote-host.client.js +141 -11
- package/dist/server/modules/remotes/operations/remote-host.client.js.map +1 -1
- package/dist/server/modules/remotes/operations/remote-operation.dto.d.ts +19 -0
- package/dist/server/modules/remotes/operations/remote-operation.dto.js +5 -1
- package/dist/server/modules/remotes/operations/remote-operation.dto.js.map +1 -1
- package/dist/server/modules/remotes/operations/remote-operation.runner.d.ts +3 -1
- package/dist/server/modules/remotes/operations/remote-operation.runner.js +52 -21
- package/dist/server/modules/remotes/operations/remote-operation.runner.js.map +1 -1
- package/dist/server/modules/remotes/operations/remote-operation.types.d.ts +4 -1
- package/dist/server/modules/remotes/operations/remote-operation.types.js.map +1 -1
- package/dist/server/modules/remotes/operations/remote-operations.controller.d.ts +5 -0
- package/dist/server/modules/remotes/operations/remote-operations.controller.js +56 -0
- package/dist/server/modules/remotes/operations/remote-operations.controller.js.map +1 -1
- package/dist/server/modules/remotes/operations/remote-operations.service.d.ts +16 -1
- package/dist/server/modules/remotes/operations/remote-operations.service.js +155 -5
- package/dist/server/modules/remotes/operations/remote-operations.service.js.map +1 -1
- package/dist/server/modules/remotes/operations/update-logins.operation.d.ts +1 -3
- package/dist/server/modules/remotes/operations/update-logins.operation.js +3 -18
- package/dist/server/modules/remotes/operations/update-logins.operation.js.map +1 -1
- package/dist/server/modules/remotes/ports/remote-health.port.d.ts +2 -0
- package/dist/server/modules/remotes/ports/remote-health.port.js.map +1 -1
- package/dist/server/modules/remotes/remotes.module.js +18 -0
- package/dist/server/modules/remotes/remotes.module.js.map +1 -1
- package/dist/server/modules/remotes/replica/__fixtures__/replica-seed.d.ts +2 -2
- package/dist/server/modules/remotes/replica/__fixtures__/replica-seed.js +2 -13
- package/dist/server/modules/remotes/replica/__fixtures__/replica-seed.js.map +1 -1
- package/dist/server/modules/remotes/services/remote-health.service.js +5 -0
- package/dist/server/modules/remotes/services/remote-health.service.js.map +1 -1
- package/dist/server/modules/remotes/sync/file-sync-failures.service.d.ts +18 -0
- package/dist/server/modules/remotes/sync/file-sync-failures.service.js +157 -0
- package/dist/server/modules/remotes/sync/file-sync-failures.service.js.map +1 -0
- package/dist/server/modules/remotes/sync/file-sync-pattern-preview.service.d.ts +14 -0
- package/dist/server/modules/remotes/sync/file-sync-pattern-preview.service.js +99 -0
- package/dist/server/modules/remotes/sync/file-sync-pattern-preview.service.js.map +1 -0
- package/dist/server/modules/remotes/sync/file-sync-suggestions.service.d.ts +15 -0
- package/dist/server/modules/remotes/sync/file-sync-suggestions.service.js +90 -0
- package/dist/server/modules/remotes/sync/file-sync-suggestions.service.js.map +1 -0
- package/dist/server/modules/remotes/sync/project-file-sync.controller.d.ts +29 -0
- package/dist/server/modules/remotes/sync/project-file-sync.controller.js +160 -0
- package/dist/server/modules/remotes/sync/project-file-sync.controller.js.map +1 -0
- package/dist/server/modules/remotes/sync/remote-file-sync.dto.d.ts +72 -0
- package/dist/server/modules/remotes/sync/remote-file-sync.dto.js +16 -0
- package/dist/server/modules/remotes/sync/remote-file-sync.dto.js.map +1 -0
- package/dist/server/modules/remotes/sync/remote-file-sync.service.d.ts +32 -1
- package/dist/server/modules/remotes/sync/remote-file-sync.service.js +499 -38
- package/dist/server/modules/remotes/sync/remote-file-sync.service.js.map +1 -1
- package/dist/server/modules/remotes/sync/remote-live-sync.service.d.ts +2 -0
- package/dist/server/modules/remotes/sync/remote-live-sync.service.js +26 -12
- package/dist/server/modules/remotes/sync/remote-live-sync.service.js.map +1 -1
- package/dist/server/modules/remotes/vm-user-identity.d.ts +29 -0
- package/dist/server/modules/remotes/vm-user-identity.js +45 -0
- package/dist/server/modules/remotes/vm-user-identity.js.map +1 -0
- package/dist/server/modules/runtime-context-capture/codex-plugin-profile-materializer.service.js +5 -1
- package/dist/server/modules/runtime-context-capture/codex-plugin-profile-materializer.service.js.map +1 -1
- package/dist/server/modules/session-reader/data/pricing.json +55 -7
- package/dist/server/modules/sessions/services/provider-launch-config/provider-launch-config.service.js +5 -0
- package/dist/server/modules/sessions/services/provider-launch-config/provider-launch-config.service.js.map +1 -1
- package/dist/server/modules/settings/local/delegates/skills-settings.delegate.d.ts +6 -0
- package/dist/server/modules/settings/local/delegates/skills-settings.delegate.js +26 -0
- package/dist/server/modules/settings/local/delegates/skills-settings.delegate.js.map +1 -1
- package/dist/server/modules/settings/services/settings.service.d.ts +3 -1
- package/dist/server/modules/settings/services/settings.service.js +6 -0
- package/dist/server/modules/settings/services/settings.service.js.map +1 -1
- package/dist/server/modules/skills/adapters/anthropic-skill-source.adapter.js +5 -5
- package/dist/server/modules/skills/adapters/anthropic-skill-source.adapter.js.map +1 -1
- package/dist/server/modules/skills/adapters/github-directory-skill-source.adapter.js +5 -5
- package/dist/server/modules/skills/adapters/github-directory-skill-source.adapter.js.map +1 -1
- package/dist/server/modules/skills/adapters/github-skill-source.base.js +4 -3
- package/dist/server/modules/skills/adapters/github-skill-source.base.js.map +1 -1
- package/dist/server/modules/skills/adapters/local-skill-source.adapter.js +5 -5
- package/dist/server/modules/skills/adapters/local-skill-source.adapter.js.map +1 -1
- package/dist/server/modules/skills/adapters/microsoft-skill-source.adapter.js +5 -5
- package/dist/server/modules/skills/adapters/microsoft-skill-source.adapter.js.map +1 -1
- package/dist/server/modules/skills/adapters/openai-skill-source.adapter.js +5 -5
- package/dist/server/modules/skills/adapters/openai-skill-source.adapter.js.map +1 -1
- package/dist/server/modules/skills/adapters/skill-source.adapter.d.ts +5 -0
- package/dist/server/modules/skills/adapters/skill-sync-temp-cleanup.d.ts +5 -0
- package/dist/server/modules/skills/adapters/skill-sync-temp-cleanup.js +75 -0
- package/dist/server/modules/skills/adapters/skill-sync-temp-cleanup.js.map +1 -0
- package/dist/server/modules/skills/adapters/trailofbits-skill-source.adapter.js +5 -5
- package/dist/server/modules/skills/adapters/trailofbits-skill-source.adapter.js.map +1 -1
- package/dist/server/modules/skills/adapters/vercel-skill-source.adapter.js +5 -5
- package/dist/server/modules/skills/adapters/vercel-skill-source.adapter.js.map +1 -1
- package/dist/server/modules/skills/controllers/skills.controller.js +2 -2
- package/dist/server/modules/skills/controllers/skills.controller.js.map +1 -1
- package/dist/server/modules/skills/services/skill-source-lifecycle.service.d.ts +3 -3
- package/dist/server/modules/skills/services/skill-source-lifecycle.service.js +9 -4
- package/dist/server/modules/skills/services/skill-source-lifecycle.service.js.map +1 -1
- package/dist/server/modules/skills/services/skill-sync.service.d.ts +3 -3
- package/dist/server/modules/skills/services/skill-sync.service.js +32 -6
- package/dist/server/modules/skills/services/skill-sync.service.js.map +1 -1
- package/dist/server/modules/skills/services/skill-sync.types.d.ts +3 -0
- package/dist/server/modules/storage/db/schema.d.ts +2 -2
- package/dist/server/modules/storage/db/schema.js +2 -0
- package/dist/server/modules/storage/db/schema.js.map +1 -1
- package/dist/server/modules/storage/models/domain.models.d.ts +1 -1
- package/dist/server/modules/storage/models/domain.models.js +2 -0
- package/dist/server/modules/storage/models/domain.models.js.map +1 -1
- package/dist/server/modules/terminal/gateways/terminal.gateway.d.ts +3 -1
- package/dist/server/modules/terminal/gateways/terminal.gateway.js +9 -4
- package/dist/server/modules/terminal/gateways/terminal.gateway.js.map +1 -1
- package/dist/server/modules/terminal/services/terminal-activity.service.d.ts +0 -1
- package/dist/server/modules/terminal/services/terminal-activity.service.js +0 -3
- package/dist/server/modules/terminal/services/terminal-activity.service.js.map +1 -1
- package/dist/server/modules/terminal/services/terminal-io/lifecycle.js +15 -3
- package/dist/server/modules/terminal/services/terminal-io/lifecycle.js.map +1 -1
- package/dist/server/modules/terminal/utils/ansi-sanitizer.d.ts +0 -1
- package/dist/server/modules/terminal/utils/ansi-sanitizer.js +0 -4
- package/dist/server/modules/terminal/utils/ansi-sanitizer.js.map +1 -1
- package/dist/server/templates/teams-dev.json +11 -11
- package/dist/server/test-setup-node.js +4 -3
- package/dist/server/test-setup-node.js.map +1 -1
- package/dist/server/test-setup.js +7 -0
- package/dist/server/test-setup.js.map +1 -1
- package/dist/server/tsconfig.tsbuildinfo +1 -1
- package/dist/server/ui/assets/{ExternalRichEditor-DtNvrV0F.js → ExternalRichEditor-CIZPhssf.js} +24 -24
- package/dist/server/ui/assets/ReviewDetailPage-winyLSQ7.js +6 -0
- package/dist/server/ui/assets/ReviewsPage-BYKBReMp.js +6 -0
- package/dist/server/ui/assets/index-CiDJX6Hn.js +1191 -0
- package/dist/server/ui/assets/index-f1WOAqXB.css +32 -0
- package/dist/server/ui/assets/useReviewSubscription-v3Cto0y4.js +69 -0
- package/dist/server/ui/index.html +2 -2
- package/dist/templates/teams-dev.json +11 -11
- package/package.json +8 -1
- package/dist/server/modules/reviews/utils/notification-formatter.d.ts +0 -12
- package/dist/server/modules/reviews/utils/notification-formatter.js +0 -60
- package/dist/server/modules/reviews/utils/notification-formatter.js.map +0 -1
- package/dist/server/ui/assets/ReviewDetailPage-DJzEoM0x.js +0 -6
- package/dist/server/ui/assets/ReviewsPage-z2O8MNEw.js +0 -6
- package/dist/server/ui/assets/index-CC4P3V8L.js +0 -994
- package/dist/server/ui/assets/index-LsJe1ZTS.css +0 -32
- package/dist/server/ui/assets/useReviewSubscription-B7AdJBO2.js +0 -69
|
@@ -11,13 +11,17 @@ var __metadata = (this && this.__metadata) || function (k, v) {
|
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
12
|
exports.FileSyncHandoff = exports.FileSyncNotConnectedError = void 0;
|
|
13
13
|
const common_1 = require("@nestjs/common");
|
|
14
|
+
const git_owner_store_1 = require("../git-owner.store");
|
|
15
|
+
const node_os_1 = require("node:os");
|
|
14
16
|
const error_types_1 = require("../../../common/errors/error-types");
|
|
15
17
|
const logger_1 = require("../../../common/logging/logger");
|
|
16
18
|
const file_sync_dto_1 = require("../../file-sync/file-sync.dto");
|
|
17
19
|
const file_sync_service_1 = require("../../file-sync/file-sync.service");
|
|
18
20
|
const file_sync_managed_exclusions_store_1 = require("../../file-sync/file-sync-managed-exclusions.store");
|
|
19
21
|
const home_git_guard_service_1 = require("../../file-sync/home-git-guard.service");
|
|
22
|
+
const project_repository_1 = require("../../file-sync/project-repository");
|
|
20
23
|
const syncthing_rest_client_1 = require("../../file-sync/syncthing-rest.client");
|
|
24
|
+
const process_executor_port_1 = require("../../terminal/services/process-executor/process-executor.port");
|
|
21
25
|
const remote_host_client_1 = require("./remote-host.client");
|
|
22
26
|
const syncthing_temp_cleanup_1 = require("./syncthing-temp-cleanup");
|
|
23
27
|
const logger = (0, logger_1.createLogger)('FileSyncHandoff');
|
|
@@ -30,20 +34,34 @@ class FileSyncNotConnectedError extends error_types_1.AppError {
|
|
|
30
34
|
}
|
|
31
35
|
}
|
|
32
36
|
exports.FileSyncNotConnectedError = FileSyncNotConnectedError;
|
|
37
|
+
const SIDE_NAMES = { home: 'this PC', host: 'the VM' };
|
|
38
|
+
function forceErrors(status) {
|
|
39
|
+
const failures = (status.fileErrors ?? []).filter((file) => !(0, file_sync_dto_1.isTransientSyncError)(file.error));
|
|
40
|
+
return {
|
|
41
|
+
failures,
|
|
42
|
+
failed: failures.length > 0 ||
|
|
43
|
+
(status.errors ?? 0) > (status.fileErrors?.length ?? 0) ||
|
|
44
|
+
(!!status.error && !(0, file_sync_dto_1.isTransientSyncError)(status.error)),
|
|
45
|
+
};
|
|
46
|
+
}
|
|
33
47
|
let FileSyncHandoff = class FileSyncHandoff {
|
|
34
48
|
fileSync;
|
|
35
49
|
host;
|
|
36
50
|
managedExclusions;
|
|
37
51
|
guard;
|
|
52
|
+
processExecutor;
|
|
53
|
+
gitOwner;
|
|
38
54
|
active = new Map();
|
|
39
|
-
constructor(fileSync, host, managedExclusions, guard) {
|
|
55
|
+
constructor(fileSync, host, managedExclusions, guard, processExecutor, gitOwner) {
|
|
40
56
|
this.fileSync = fileSync;
|
|
41
57
|
this.host = host;
|
|
42
58
|
this.managedExclusions = managedExclusions;
|
|
43
59
|
this.guard = guard;
|
|
60
|
+
this.processExecutor = processExecutor;
|
|
61
|
+
this.gitOwner = gitOwner;
|
|
44
62
|
}
|
|
45
|
-
interrupt(operationId) {
|
|
46
|
-
this.active.get(operationId)?.abort(new Error(
|
|
63
|
+
interrupt(operationId, reason = 'The Connect was cancelled.') {
|
|
64
|
+
this.active.get(operationId)?.abort(new Error(reason));
|
|
47
65
|
}
|
|
48
66
|
async initial(run, projectId) {
|
|
49
67
|
const controller = new AbortController();
|
|
@@ -51,6 +69,22 @@ let FileSyncHandoff = class FileSyncHandoff {
|
|
|
51
69
|
try {
|
|
52
70
|
const { remoteId } = run.operation;
|
|
53
71
|
const ignores = this.syncIgnores(projectId);
|
|
72
|
+
const { removed } = await this.host.removeGitGuard(remoteId, projectId);
|
|
73
|
+
if (removed)
|
|
74
|
+
await run.progress({ vmGuardRemoved: true });
|
|
75
|
+
controller.signal.throwIfAborted();
|
|
76
|
+
const codeId = (0, file_sync_service_1.codeFolderId)(projectId);
|
|
77
|
+
if (run.details.fileSyncMode !== 'merge' && run.details.fileSyncMode !== 'reset') {
|
|
78
|
+
const [homeFolders, hostExists] = await Promise.all([
|
|
79
|
+
this.fileSync.projectFolders(projectId),
|
|
80
|
+
this.host.syncFolderExists(remoteId, codeId),
|
|
81
|
+
]);
|
|
82
|
+
await run.progress({
|
|
83
|
+
fileSyncMode: hostExists && homeFolders.some((folder) => folder.id === codeId) ? 'merge' : 'reset',
|
|
84
|
+
}, { durable: true });
|
|
85
|
+
}
|
|
86
|
+
controller.signal.throwIfAborted();
|
|
87
|
+
const merge = run.details.fileSyncMode === 'merge';
|
|
54
88
|
const devices = await this.pair(remoteId, controller.signal);
|
|
55
89
|
const folders = await this.fileSync.initialFolders(projectId);
|
|
56
90
|
for (const folder of folders) {
|
|
@@ -60,19 +94,65 @@ let FileSyncHandoff = class FileSyncHandoff {
|
|
|
60
94
|
ignores: folder.kind === 'code' ? ignores : (0, file_sync_dto_1.gitIgnores)(false),
|
|
61
95
|
paused: true,
|
|
62
96
|
};
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
97
|
+
const mergeCode = merge && folder.kind === 'code';
|
|
98
|
+
if (mergeCode)
|
|
99
|
+
await this.fileSync.updateFolder(folder.id, { paused: true });
|
|
100
|
+
else
|
|
101
|
+
await this.fileSync.ensureFolder({
|
|
102
|
+
...request,
|
|
103
|
+
type: 'sendonly',
|
|
104
|
+
peerDeviceId: devices.host,
|
|
105
|
+
});
|
|
68
106
|
await this.host.syncFolders(remoteId, {
|
|
69
107
|
...request,
|
|
70
|
-
type: 'receiveonly',
|
|
108
|
+
type: mergeCode ? 'sendreceive' : 'receiveonly',
|
|
71
109
|
peerDeviceId: devices.home,
|
|
72
110
|
});
|
|
73
111
|
}
|
|
112
|
+
if (merge) {
|
|
113
|
+
await this.host.syncFolderType(remoteId, codeId, { paused: false });
|
|
114
|
+
await this.host.syncScan(remoteId, codeId);
|
|
115
|
+
await this.waitHostIdle(remoteId, codeId, controller.signal);
|
|
116
|
+
if (run.details.vmEdits === undefined &&
|
|
117
|
+
run.details.fileSyncConflictBaseline === undefined) {
|
|
118
|
+
const vmEdits = await this.host.syncRemoteNeed(remoteId, codeId, devices.home);
|
|
119
|
+
const homeBaseline = await this.fileSync.conflictBaseline(projectId, ignores, controller.signal);
|
|
120
|
+
const paths = new Set([
|
|
121
|
+
...vmEdits.conflictPaths,
|
|
122
|
+
...(homeBaseline.baselineOverCap ? [] : homeBaseline.paths),
|
|
123
|
+
]);
|
|
124
|
+
const fileSyncConflictBaseline = homeBaseline.baselineOverCap ||
|
|
125
|
+
vmEdits.conflictsOverCap ||
|
|
126
|
+
paths.size > file_sync_dto_1.CONFLICT_BASELINE_MAX
|
|
127
|
+
? { baselineOverCap: true }
|
|
128
|
+
: { baselineOverCap: false, paths: [...paths] };
|
|
129
|
+
await run.progress({ vmEdits, fileSyncConflictBaseline }, { durable: true });
|
|
130
|
+
}
|
|
131
|
+
else {
|
|
132
|
+
file_sync_dto_1.RemoteNeedSchema.parse(run.details.vmEdits);
|
|
133
|
+
file_sync_dto_1.ConflictBaselineSchema.parse(run.details.fileSyncConflictBaseline);
|
|
134
|
+
}
|
|
135
|
+
controller.signal.throwIfAborted();
|
|
136
|
+
await this.fileSync.ensureFolder({
|
|
137
|
+
projectId,
|
|
138
|
+
kind: 'code',
|
|
139
|
+
ignores,
|
|
140
|
+
paused: true,
|
|
141
|
+
type: 'sendreceive',
|
|
142
|
+
peerDeviceId: devices.host,
|
|
143
|
+
});
|
|
144
|
+
}
|
|
74
145
|
await this.unpauseAll(remoteId, folders);
|
|
75
|
-
await this.waitAll(run, folders, {
|
|
146
|
+
await this.waitAll(run, folders, {
|
|
147
|
+
sender: 'home',
|
|
148
|
+
devices,
|
|
149
|
+
symmetricCode: merge,
|
|
150
|
+
signal: controller.signal,
|
|
151
|
+
});
|
|
152
|
+
if (merge) {
|
|
153
|
+
const fileSyncConflicts = await this.fileSync.conflicts(projectId, file_sync_dto_1.ConflictBaselineSchema.parse(run.details.fileSyncConflictBaseline), ignores, controller.signal);
|
|
154
|
+
await run.progress({ fileSyncConflicts });
|
|
155
|
+
}
|
|
76
156
|
}
|
|
77
157
|
finally {
|
|
78
158
|
if (this.active.get(run.operation.id) === controller)
|
|
@@ -82,18 +162,278 @@ let FileSyncHandoff = class FileSyncHandoff {
|
|
|
82
162
|
async ensureAvailable() {
|
|
83
163
|
await this.fileSync.ensureAvailable();
|
|
84
164
|
}
|
|
165
|
+
async ensureRepository(projectId) {
|
|
166
|
+
const root = await this.fileSync.folderPath(projectId);
|
|
167
|
+
if ((await (0, project_repository_1.projectRepository)(root)) !== 'missing')
|
|
168
|
+
return false;
|
|
169
|
+
const result = await this.processExecutor.run({
|
|
170
|
+
argv: ['git', 'init'],
|
|
171
|
+
mode: 'pipe',
|
|
172
|
+
cwd: root,
|
|
173
|
+
timeout: 30_000,
|
|
174
|
+
});
|
|
175
|
+
if (!result.success) {
|
|
176
|
+
throw new error_types_1.AppError(result.stderr.trim() ||
|
|
177
|
+
result.stdout.trim() ||
|
|
178
|
+
'Could not create a Git repository on this PC.', 'GIT_INIT_FAILED', 500);
|
|
179
|
+
}
|
|
180
|
+
return true;
|
|
181
|
+
}
|
|
85
182
|
async flipToHost(run, projectId) {
|
|
86
183
|
const { remoteId } = run.operation;
|
|
87
184
|
const folders = await this.fileSync.projectFolders(projectId);
|
|
88
|
-
await this.hostDirections(remoteId, folders, false);
|
|
185
|
+
await this.hostDirections(remoteId, folders, 'vm', false);
|
|
89
186
|
if (folders.some((folder) => folder.kind === 'git')) {
|
|
90
187
|
const guardWarning = await this.guard.install(projectId, remoteId);
|
|
91
188
|
if (guardWarning)
|
|
92
189
|
await run.progress({ guardWarning });
|
|
93
190
|
}
|
|
94
191
|
}
|
|
192
|
+
async settleGit(run, projectId, owner) {
|
|
193
|
+
const controller = new AbortController();
|
|
194
|
+
const { remoteId, id } = run.operation;
|
|
195
|
+
this.active.set(id, controller);
|
|
196
|
+
try {
|
|
197
|
+
const devices = await this.pair(remoteId, controller.signal);
|
|
198
|
+
const folders = (0, file_sync_service_1.projectFolderList)(projectId, ['git']);
|
|
199
|
+
const config = owner === 'vm'
|
|
200
|
+
? await this.fileSync.folderConfiguration(folders[0].id)
|
|
201
|
+
: await this.host.syncFolderConfiguration(remoteId, folders[0].id);
|
|
202
|
+
controller.signal.throwIfAborted();
|
|
203
|
+
if (config.type !== 'receiveonly' || config.paused)
|
|
204
|
+
throw new error_types_1.AppError('The receiving Git folder is not ready. Retry the switch.', 'GIT_SWITCH_RECEIVER_NOT_READY', 409);
|
|
205
|
+
await this.waitAll(run, folders, {
|
|
206
|
+
sender: owner === 'vm' ? 'host' : 'home',
|
|
207
|
+
devices,
|
|
208
|
+
requireNoReceiveOnlyChanges: true,
|
|
209
|
+
revertAfterComplete: true,
|
|
210
|
+
signal: controller.signal,
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
finally {
|
|
214
|
+
if (this.active.get(id) === controller)
|
|
215
|
+
this.active.delete(id);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
async flipGit(run, projectId, owner) {
|
|
219
|
+
const { remoteId } = run.operation;
|
|
220
|
+
const folderId = (0, file_sync_service_1.projectFolderId)(projectId, 'git');
|
|
221
|
+
const ignores = (0, file_sync_dto_1.gitIgnores)(true);
|
|
222
|
+
if (owner === 'home') {
|
|
223
|
+
await this.host.syncFolderType(remoteId, folderId, { type: 'receiveonly', ignores });
|
|
224
|
+
await this.fileSync.updateFolder(folderId, { type: 'sendonly', ignores });
|
|
225
|
+
}
|
|
226
|
+
else {
|
|
227
|
+
await this.fileSync.updateFolder(folderId, { type: 'receiveonly', ignores });
|
|
228
|
+
await this.host.syncFolderType(remoteId, folderId, { type: 'sendonly', ignores });
|
|
229
|
+
}
|
|
230
|
+
this.gitOwner.set(projectId, owner);
|
|
231
|
+
await this.host.syncFolderType(remoteId, folderId, { paused: false });
|
|
232
|
+
await this.fileSync.updateFolder(folderId, { paused: false });
|
|
233
|
+
}
|
|
234
|
+
async forceCopy(run, projectId, source, kinds) {
|
|
235
|
+
const { remoteId, id: operationId } = run.operation;
|
|
236
|
+
const folders = (0, file_sync_service_1.projectFolderList)(projectId, kinds);
|
|
237
|
+
const sender = source === 'home' ? 'home' : 'host';
|
|
238
|
+
const receiver = sender === 'home' ? 'host' : 'home';
|
|
239
|
+
const backups = [];
|
|
240
|
+
for (const folder of folders) {
|
|
241
|
+
const request = { projectId, kind: folder.kind, forceCopy: { operationId } };
|
|
242
|
+
const { path } = receiver === 'home'
|
|
243
|
+
? await this.fileSync.forceCopyBackup(request)
|
|
244
|
+
: await this.host.syncForceCopyBackup(remoteId, request);
|
|
245
|
+
backups.push({ side: receiver === 'home' ? 'home' : 'vm', kind: folder.kind, path });
|
|
246
|
+
}
|
|
247
|
+
await this.forceProgress(run, { backups, verified: false });
|
|
248
|
+
await this.guard.remove(projectId, { refreshIndex: false });
|
|
249
|
+
await this.host.removeGitGuard(remoteId, projectId);
|
|
250
|
+
for (const folder of folders) {
|
|
251
|
+
for (const side of ['home', 'host']) {
|
|
252
|
+
try {
|
|
253
|
+
if (side === 'home')
|
|
254
|
+
await this.fileSync.removeFolder(folder.id);
|
|
255
|
+
else
|
|
256
|
+
await this.host.syncRemoveFolder(remoteId, folder.id);
|
|
257
|
+
}
|
|
258
|
+
catch (error) {
|
|
259
|
+
if (!((error instanceof syncthing_rest_client_1.SyncthingRestError || error instanceof remote_host_client_1.RemoteHostRequestError) &&
|
|
260
|
+
error.status === 404))
|
|
261
|
+
throw error;
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
const devices = await this.pair(remoteId);
|
|
266
|
+
const ignores = this.syncIgnores(projectId);
|
|
267
|
+
for (const folder of folders) {
|
|
268
|
+
const request = {
|
|
269
|
+
projectId,
|
|
270
|
+
kind: folder.kind,
|
|
271
|
+
ignores: folder.kind === 'code' ? ignores : (0, file_sync_dto_1.gitIgnores)(false),
|
|
272
|
+
paused: true,
|
|
273
|
+
};
|
|
274
|
+
await this.fileSync.ensureFolder({
|
|
275
|
+
...request,
|
|
276
|
+
type: sender === 'home' ? 'sendonly' : 'receiveonly',
|
|
277
|
+
peerDeviceId: devices.host,
|
|
278
|
+
...(receiver === 'home' && { forceCopy: { operationId } }),
|
|
279
|
+
});
|
|
280
|
+
await this.host.syncFolders(remoteId, {
|
|
281
|
+
...request,
|
|
282
|
+
type: sender === 'host' ? 'sendonly' : 'receiveonly',
|
|
283
|
+
peerDeviceId: devices.home,
|
|
284
|
+
...(receiver === 'host' && { forceCopy: { operationId } }),
|
|
285
|
+
});
|
|
286
|
+
}
|
|
287
|
+
await this.unpauseAll(remoteId, folders);
|
|
288
|
+
for (const folder of folders) {
|
|
289
|
+
await Promise.all([
|
|
290
|
+
this.scan(sender, remoteId, folder.id),
|
|
291
|
+
this.scan(receiver, remoteId, folder.id),
|
|
292
|
+
]);
|
|
293
|
+
}
|
|
294
|
+
for (const folder of folders) {
|
|
295
|
+
await this.waitBarrier(remoteId, folder.id, sender);
|
|
296
|
+
if (sender === 'home')
|
|
297
|
+
await this.fileSync.override(folder.id);
|
|
298
|
+
else
|
|
299
|
+
await this.host.syncOverride(remoteId, folder.id);
|
|
300
|
+
}
|
|
301
|
+
const replaced = { count: 0, sample: [] };
|
|
302
|
+
for (const folder of folders) {
|
|
303
|
+
const changed = receiver === 'home'
|
|
304
|
+
? await this.fileSync.localChanges(folder.id)
|
|
305
|
+
: await this.host.syncLocalChanges(remoteId, folder.id);
|
|
306
|
+
replaced.count += changed.count;
|
|
307
|
+
replaced.sample.push(...changed.sample
|
|
308
|
+
.slice(0, file_sync_dto_1.RECEIVE_ONLY_SAMPLE_MAX - replaced.sample.length)
|
|
309
|
+
.map((name) => (folder.kind === 'git' ? `.git/${name}` : name)));
|
|
310
|
+
}
|
|
311
|
+
const earlier = this.forceDetails(run).replaced;
|
|
312
|
+
if (earlier) {
|
|
313
|
+
replaced.count = Math.max(replaced.count, earlier.count);
|
|
314
|
+
replaced.sample = [...new Set([...earlier.sample, ...replaced.sample])].slice(0, file_sync_dto_1.RECEIVE_ONLY_SAMPLE_MAX);
|
|
315
|
+
}
|
|
316
|
+
await this.forceProgress(run, { replaced });
|
|
317
|
+
let waitError;
|
|
318
|
+
try {
|
|
319
|
+
await this.waitAll(run, folders, {
|
|
320
|
+
sender,
|
|
321
|
+
devices,
|
|
322
|
+
symmetricCode: false,
|
|
323
|
+
requireNoReceiveOnlyChanges: true,
|
|
324
|
+
});
|
|
325
|
+
}
|
|
326
|
+
catch (error) {
|
|
327
|
+
waitError = error;
|
|
328
|
+
}
|
|
329
|
+
await this.verifyForceCopy(remoteId, folders, sender, devices);
|
|
330
|
+
if (waitError)
|
|
331
|
+
throw waitError;
|
|
332
|
+
await this.forceProgress(run, { verified: true });
|
|
333
|
+
}
|
|
334
|
+
async restoreConnected(run, projectId, kinds) {
|
|
335
|
+
if (this.forceDetails(run).verified !== true)
|
|
336
|
+
throw new error_types_1.AppError('Force sync has not verified the copy.', 'FORCE_SYNC_NOT_VERIFIED', 409);
|
|
337
|
+
const { remoteId } = run.operation;
|
|
338
|
+
const owner = this.gitOwner.get(projectId);
|
|
339
|
+
const devices = await this.pair(remoteId);
|
|
340
|
+
const folders = (0, file_sync_service_1.projectFolderList)(projectId, kinds);
|
|
341
|
+
const ignores = this.syncIgnores(projectId);
|
|
342
|
+
for (const folder of folders) {
|
|
343
|
+
const request = {
|
|
344
|
+
projectId,
|
|
345
|
+
kind: folder.kind,
|
|
346
|
+
ignores: folder.kind === 'code' ? ignores : (0, file_sync_dto_1.gitIgnores)(true),
|
|
347
|
+
paused: true,
|
|
348
|
+
};
|
|
349
|
+
const ensureHome = () => this.fileSync.ensureFolder({
|
|
350
|
+
...request,
|
|
351
|
+
type: folder.kind === 'code' ? 'sendreceive' : owner === 'home' ? 'sendonly' : 'receiveonly',
|
|
352
|
+
peerDeviceId: devices.host,
|
|
353
|
+
});
|
|
354
|
+
const ensureHost = () => this.host.syncFolders(remoteId, {
|
|
355
|
+
...request,
|
|
356
|
+
type: folder.kind === 'code' ? 'sendreceive' : owner === 'vm' ? 'sendonly' : 'receiveonly',
|
|
357
|
+
peerDeviceId: devices.home,
|
|
358
|
+
});
|
|
359
|
+
if (folder.kind === 'git' && owner === 'home') {
|
|
360
|
+
await ensureHost();
|
|
361
|
+
await ensureHome();
|
|
362
|
+
}
|
|
363
|
+
else {
|
|
364
|
+
await ensureHome();
|
|
365
|
+
await ensureHost();
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
await this.unpauseAll(remoteId, folders);
|
|
369
|
+
if (kinds.includes('git')) {
|
|
370
|
+
if (owner === 'vm') {
|
|
371
|
+
const guardWarning = await this.guard.install(projectId, remoteId);
|
|
372
|
+
if (guardWarning)
|
|
373
|
+
await run.progress({ guardWarning });
|
|
374
|
+
}
|
|
375
|
+
else {
|
|
376
|
+
const { warning } = await this.host.installGitGuard(remoteId, projectId, {
|
|
377
|
+
homeName: (0, node_os_1.hostname)(),
|
|
378
|
+
reason: 'pc-git',
|
|
379
|
+
});
|
|
380
|
+
await run.progress({ vmGuardWarning: warning });
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
forceDetails(run) {
|
|
385
|
+
const value = run.details.forceSync;
|
|
386
|
+
return value && typeof value === 'object' && !Array.isArray(value)
|
|
387
|
+
? value
|
|
388
|
+
: {};
|
|
389
|
+
}
|
|
390
|
+
forceProgress(run, patch) {
|
|
391
|
+
return run.progress({ forceSync: { ...this.forceDetails(run), ...patch } }, { durable: true });
|
|
392
|
+
}
|
|
393
|
+
async waitBarrier(remoteId, folderId, sender) {
|
|
394
|
+
const receiver = sender === 'home' ? 'host' : 'home';
|
|
395
|
+
const deadline = Date.now() + SYNC_TIMEOUT_MS;
|
|
396
|
+
for (;;) {
|
|
397
|
+
const [source, target] = await Promise.all([
|
|
398
|
+
this.status(sender, remoteId, folderId),
|
|
399
|
+
this.status(receiver, remoteId, folderId),
|
|
400
|
+
]);
|
|
401
|
+
if ((0, file_sync_service_1.senderIndexReached)(source, target))
|
|
402
|
+
return;
|
|
403
|
+
if (Date.now() >= deadline)
|
|
404
|
+
throw new file_sync_service_1.FileSyncTimeoutError(folderId, null, 'The source index did not reach the receiver.');
|
|
405
|
+
await sleep(POLL_MS);
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
async verifyForceCopy(remoteId, folders, sender, devices) {
|
|
409
|
+
const receiver = sender === 'home' ? 'host' : 'home';
|
|
410
|
+
const problems = [];
|
|
411
|
+
const failedFiles = [];
|
|
412
|
+
for (const folder of folders) {
|
|
413
|
+
const [source, target] = await Promise.all([
|
|
414
|
+
this.status(sender, remoteId, folder.id, devices[receiver], { allErrors: true }),
|
|
415
|
+
this.status(receiver, remoteId, folder.id, undefined, { allErrors: true }),
|
|
416
|
+
]);
|
|
417
|
+
const targetErrors = forceErrors(target);
|
|
418
|
+
failedFiles.push(...targetErrors.failures
|
|
419
|
+
.slice(0, 3 - failedFiles.length)
|
|
420
|
+
.map((file) => `${folder.id}/${file.path}: ${file.error}`));
|
|
421
|
+
if (!(0, file_sync_service_1.evaluateCompletion)(source, target).done ||
|
|
422
|
+
target.receiveOnlyChangedFiles !== 0 ||
|
|
423
|
+
forceErrors(source).failed ||
|
|
424
|
+
targetErrors.failed) {
|
|
425
|
+
const reason = target.error ||
|
|
426
|
+
source.error ||
|
|
427
|
+
'The copies are not in sync or still have receive-only changes.';
|
|
428
|
+
problems.push(`${folder.id}: ${reason}`);
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
if (problems.length)
|
|
432
|
+
throw new error_types_1.AppError(`Force sync failed: ${[...problems, ...failedFiles].join('; ')}`, 'FORCE_SYNC_INCOMPLETE', 500);
|
|
433
|
+
}
|
|
95
434
|
async final(run, projectId) {
|
|
96
435
|
const { remoteId } = run.operation;
|
|
436
|
+
const owner = this.gitOwner.get(projectId);
|
|
97
437
|
const ignores = this.syncIgnores(projectId);
|
|
98
438
|
const devices = await this.pair(remoteId);
|
|
99
439
|
const folders = await this.fileSync.projectFolders(projectId);
|
|
@@ -105,19 +445,31 @@ let FileSyncHandoff = class FileSyncHandoff {
|
|
|
105
445
|
ignores: folder.kind === 'code' ? ignores : (0, file_sync_dto_1.gitIgnores)(true),
|
|
106
446
|
paused: true,
|
|
107
447
|
};
|
|
108
|
-
|
|
448
|
+
const ensureHost = () => this.host.syncFolders(remoteId, {
|
|
109
449
|
...request,
|
|
110
|
-
type: folder.kind === 'code' ? 'sendreceive' : 'sendonly',
|
|
450
|
+
type: folder.kind === 'code' ? 'sendreceive' : owner === 'vm' ? 'sendonly' : 'receiveonly',
|
|
111
451
|
peerDeviceId: devices.home,
|
|
112
452
|
});
|
|
113
|
-
|
|
453
|
+
const ensureHome = () => this.fileSync.ensureFolder({
|
|
114
454
|
...request,
|
|
115
|
-
type: folder.kind === 'code' ? 'sendreceive' : 'receiveonly',
|
|
455
|
+
type: folder.kind === 'code' ? 'sendreceive' : owner === 'home' ? 'sendonly' : 'receiveonly',
|
|
116
456
|
peerDeviceId: devices.host,
|
|
117
457
|
});
|
|
458
|
+
if (folder.kind === 'git' && owner === 'vm') {
|
|
459
|
+
await ensureHome();
|
|
460
|
+
await ensureHost();
|
|
461
|
+
}
|
|
462
|
+
else {
|
|
463
|
+
await ensureHost();
|
|
464
|
+
await ensureHome();
|
|
465
|
+
}
|
|
118
466
|
}
|
|
119
467
|
await this.unpauseAll(remoteId, folders);
|
|
120
|
-
await this.waitAll(run, folders, {
|
|
468
|
+
await this.waitAll(run, folders, {
|
|
469
|
+
sender: (folder) => (folder.kind === 'git' && owner === 'home' ? 'home' : 'host'),
|
|
470
|
+
devices,
|
|
471
|
+
symmetricCode: true,
|
|
472
|
+
});
|
|
121
473
|
}
|
|
122
474
|
async flipToHome(run, projectId, force) {
|
|
123
475
|
const { remoteId } = run.operation;
|
|
@@ -127,8 +479,25 @@ let FileSyncHandoff = class FileSyncHandoff {
|
|
|
127
479
|
}
|
|
128
480
|
await this.update('home', remoteId, folder.id, { type: 'sendonly', paused: true });
|
|
129
481
|
}
|
|
482
|
+
if (force) {
|
|
483
|
+
await run.progress({
|
|
484
|
+
vmGuardSkipped: 'VM guard skipped: the forced Disconnect cannot reach the VM.',
|
|
485
|
+
});
|
|
486
|
+
}
|
|
487
|
+
else {
|
|
488
|
+
await run.progress({ vmGuardInstalled: true }, { durable: true });
|
|
489
|
+
const { warning } = await this.host.installGitGuard(remoteId, projectId, {
|
|
490
|
+
homeName: (0, node_os_1.hostname)(),
|
|
491
|
+
reason: 'disconnect',
|
|
492
|
+
});
|
|
493
|
+
await run.progress({ vmGuardWarning: warning, vmGuardInstalled: warning === null });
|
|
494
|
+
}
|
|
130
495
|
await this.deleteHomeTempFiles(projectId);
|
|
131
|
-
await this.guard.remove(projectId, {
|
|
496
|
+
const { warning } = await this.guard.remove(projectId, {
|
|
497
|
+
refreshIndex: this.gitOwner.get(projectId) === 'vm',
|
|
498
|
+
});
|
|
499
|
+
if (warning)
|
|
500
|
+
await run.progress({ guardWarning: warning });
|
|
132
501
|
}
|
|
133
502
|
async removeFolders(remoteId, projectId) {
|
|
134
503
|
const folders = (0, file_sync_service_1.projectFolderList)(projectId);
|
|
@@ -148,23 +517,38 @@ let FileSyncHandoff = class FileSyncHandoff {
|
|
|
148
517
|
}
|
|
149
518
|
}
|
|
150
519
|
async flipBackToHost(remoteId, projectId, force) {
|
|
520
|
+
const owner = this.gitOwner.get(projectId);
|
|
151
521
|
const folders = await this.fileSync.projectFolders(projectId);
|
|
152
|
-
await this.hostDirections(remoteId, folders, force, false);
|
|
522
|
+
await this.hostDirections(remoteId, folders, owner, force, false);
|
|
153
523
|
if (folders.some((folder) => folder.kind === 'git')) {
|
|
154
|
-
const guardWarning =
|
|
524
|
+
const guardWarning = owner === 'vm'
|
|
525
|
+
? await this.guard.reinstall(projectId, remoteId)
|
|
526
|
+
: force
|
|
527
|
+
? null
|
|
528
|
+
: (await this.host.installGitGuard(remoteId, projectId, {
|
|
529
|
+
homeName: (0, node_os_1.hostname)(),
|
|
530
|
+
reason: 'pc-git',
|
|
531
|
+
})).warning;
|
|
155
532
|
if (guardWarning) {
|
|
156
533
|
logger.warn({ projectId, remoteId, guardWarning }, 'Remote git guard not reinstalled');
|
|
157
534
|
}
|
|
158
535
|
}
|
|
159
536
|
}
|
|
160
|
-
async hostDirections(remoteId, folders, force, paused) {
|
|
537
|
+
async hostDirections(remoteId, folders, owner, force, paused) {
|
|
161
538
|
for (const folder of folders) {
|
|
162
539
|
const pause = paused === undefined ? {} : { paused };
|
|
163
540
|
if (folder.kind === 'git') {
|
|
164
541
|
const ignores = (0, file_sync_dto_1.gitIgnores)(true);
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
542
|
+
const receiver = owner === 'vm' ? 'home' : 'host';
|
|
543
|
+
const sender = owner === 'vm' ? 'host' : 'home';
|
|
544
|
+
if (receiver === 'home' || !force)
|
|
545
|
+
await this.update(receiver, remoteId, folder.id, {
|
|
546
|
+
type: 'receiveonly',
|
|
547
|
+
ignores,
|
|
548
|
+
...pause,
|
|
549
|
+
});
|
|
550
|
+
if (sender === 'home' || !force)
|
|
551
|
+
await this.update(sender, remoteId, folder.id, { type: 'sendonly', ignores, ...pause });
|
|
168
552
|
}
|
|
169
553
|
else {
|
|
170
554
|
if (!force)
|
|
@@ -208,40 +592,77 @@ let FileSyncHandoff = class FileSyncHandoff {
|
|
|
208
592
|
await this.update('home', remoteId, folder.id, { paused: false });
|
|
209
593
|
}
|
|
210
594
|
}
|
|
595
|
+
async waitHostIdle(remoteId, folderId, signal) {
|
|
596
|
+
const deadline = Date.now() + SYNC_TIMEOUT_MS;
|
|
597
|
+
for (;;) {
|
|
598
|
+
signal.throwIfAborted();
|
|
599
|
+
const status = await this.host.syncStatus(remoteId, folderId);
|
|
600
|
+
signal.throwIfAborted();
|
|
601
|
+
if (status.error || status.errors)
|
|
602
|
+
throw new file_sync_service_1.FileSyncTimeoutError(folderId, null, status.error ?? 'VM scan failed');
|
|
603
|
+
if (status.state === 'idle')
|
|
604
|
+
return;
|
|
605
|
+
if (Date.now() >= deadline)
|
|
606
|
+
throw new file_sync_service_1.FileSyncTimeoutError(folderId, null, 'The VM scan did not become idle.');
|
|
607
|
+
await sleep(POLL_MS);
|
|
608
|
+
}
|
|
609
|
+
}
|
|
211
610
|
async waitAll(run, folders, options) {
|
|
212
611
|
const { remoteId } = run.operation;
|
|
213
|
-
const receiver = options.sender === 'home' ? 'host' : 'home';
|
|
214
|
-
const receiverDevice = receiver === 'home' ? options.devices.home : options.devices.host;
|
|
215
612
|
const progress = {};
|
|
216
613
|
const report = () => run.progress({ fileSync: { folders: { ...progress } } });
|
|
217
614
|
for (const folder of folders) {
|
|
218
615
|
progress[folder.id] = { completion: 0, needItems: 0, needBytes: 0 };
|
|
219
616
|
}
|
|
220
617
|
await report();
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
symmetric
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
618
|
+
const stop = new AbortController();
|
|
619
|
+
const signal = options.signal ? AbortSignal.any([options.signal, stop.signal]) : stop.signal;
|
|
620
|
+
await Promise.allSettled(folders.map(async (folder) => {
|
|
621
|
+
try {
|
|
622
|
+
const sender = typeof options.sender === 'function' ? options.sender(folder) : options.sender;
|
|
623
|
+
const receiver = sender === 'home' ? 'host' : 'home';
|
|
624
|
+
const receiverDevice = options.devices[receiver];
|
|
625
|
+
const symmetric = options.symmetricCode === true && folder.kind === 'code';
|
|
626
|
+
await Promise.all([
|
|
627
|
+
this.scan(sender, remoteId, folder.id, options.signal),
|
|
628
|
+
...(symmetric ? [this.scan(receiver, remoteId, folder.id)] : []),
|
|
629
|
+
]);
|
|
630
|
+
progress[folder.id] = await this.fileSync.waitForComplete(folder.id, {
|
|
631
|
+
symmetric,
|
|
632
|
+
requireNoReceiveOnlyChanges: options.requireNoReceiveOnlyChanges,
|
|
633
|
+
sender: () => this.status(sender, remoteId, folder.id, receiverDevice),
|
|
634
|
+
receiver: async () => {
|
|
635
|
+
const status = await this.status(receiver, remoteId, folder.id, symmetric ? options.devices[sender] : undefined);
|
|
636
|
+
if (!symmetric && status.receiveOnlyChangedFiles > 0) {
|
|
637
|
+
signal.throwIfAborted();
|
|
638
|
+
const source = await this.status(sender, remoteId, folder.id, options.revertAfterComplete ? receiverDevice : undefined);
|
|
639
|
+
signal.throwIfAborted();
|
|
640
|
+
const transferred = (0, file_sync_service_1.senderIndexReached)(source, status) &&
|
|
641
|
+
source.peer?.completion === 100 &&
|
|
642
|
+
source.peer.needItems === 0 &&
|
|
643
|
+
source.peer.remoteState === 'valid' &&
|
|
644
|
+
status.needTotalItems === 0;
|
|
645
|
+
if (options.revertAfterComplete ? transferred : (0, file_sync_service_1.senderIndexReached)(source, status))
|
|
646
|
+
await this.revert(receiver, remoteId, folder.id);
|
|
647
|
+
}
|
|
648
|
+
return status;
|
|
649
|
+
},
|
|
650
|
+
timeoutMs: SYNC_TIMEOUT_MS,
|
|
651
|
+
sides: { sender: SIDE_NAMES[sender], receiver: SIDE_NAMES[receiver] },
|
|
652
|
+
onProgress: (current) => {
|
|
653
|
+
progress[folder.id] = current;
|
|
654
|
+
void report();
|
|
655
|
+
},
|
|
656
|
+
signal,
|
|
657
|
+
});
|
|
658
|
+
}
|
|
659
|
+
catch (error) {
|
|
660
|
+
stop.abort(error);
|
|
661
|
+
throw error;
|
|
662
|
+
}
|
|
244
663
|
}));
|
|
664
|
+
if (stop.signal.aborted)
|
|
665
|
+
throw stop.signal.reason;
|
|
245
666
|
await report();
|
|
246
667
|
}
|
|
247
668
|
async update(side, remoteId, folderId, patch) {
|
|
@@ -258,7 +679,11 @@ let FileSyncHandoff = class FileSyncHandoff {
|
|
|
258
679
|
throw error;
|
|
259
680
|
}
|
|
260
681
|
}
|
|
261
|
-
status(side, remoteId, folderId, peerDeviceId) {
|
|
682
|
+
status(side, remoteId, folderId, peerDeviceId, options) {
|
|
683
|
+
if (options)
|
|
684
|
+
return side === 'home'
|
|
685
|
+
? this.fileSync.status(folderId, peerDeviceId, options)
|
|
686
|
+
: this.host.syncStatus(remoteId, folderId, peerDeviceId, options);
|
|
262
687
|
return side === 'home'
|
|
263
688
|
? this.fileSync.status(folderId, peerDeviceId)
|
|
264
689
|
: this.host.syncStatus(remoteId, folderId, peerDeviceId);
|
|
@@ -280,7 +705,9 @@ exports.FileSyncHandoff = FileSyncHandoff = __decorate([
|
|
|
280
705
|
__metadata("design:paramtypes", [file_sync_service_1.FileSyncService,
|
|
281
706
|
remote_host_client_1.RemoteHostClient,
|
|
282
707
|
file_sync_managed_exclusions_store_1.FileSyncManagedExclusionsStore,
|
|
283
|
-
home_git_guard_service_1.HomeGitGuardService
|
|
708
|
+
home_git_guard_service_1.HomeGitGuardService,
|
|
709
|
+
process_executor_port_1.ProcessExecutor,
|
|
710
|
+
git_owner_store_1.GitOwnerStore])
|
|
284
711
|
], FileSyncHandoff);
|
|
285
712
|
function sleep(ms) {
|
|
286
713
|
return new Promise((resolve) => setTimeout(resolve, ms));
|