devchain-cli 0.24.0 → 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.
Files changed (432) hide show
  1. package/README.md +1 -4
  2. package/dist/build-info.json +2 -2
  3. package/dist/cli.js +66 -11
  4. package/dist/host-install/devchain-host-bootstrap.tgz +0 -0
  5. package/dist/host-install/pins.json +31 -2
  6. package/dist/lib/exclusive-run.js +51 -3
  7. package/dist/lib/git-owner.js +284 -0
  8. package/dist/lib/host-install.js +19 -151
  9. package/dist/lib/local-api.js +175 -0
  10. package/dist/server/common/config/env.config.d.ts +3 -0
  11. package/dist/server/common/config/env.config.js +1 -0
  12. package/dist/server/common/config/env.config.js.map +1 -1
  13. package/dist/server/common/config/host-image.json +3 -3
  14. package/dist/server/common/constants/syncthing-markers.d.ts +1 -0
  15. package/dist/server/common/constants/syncthing-markers.js +6 -1
  16. package/dist/server/common/constants/syncthing-markers.js.map +1 -1
  17. package/dist/server/common/filesystem/vm-home-path.d.ts +11 -0
  18. package/dist/server/common/filesystem/vm-home-path.js +48 -0
  19. package/dist/server/common/filesystem/vm-home-path.js.map +1 -0
  20. package/dist/server/common/process-ids-env.d.ts +1 -0
  21. package/dist/server/common/process-ids-env.js +13 -0
  22. package/dist/server/common/process-ids-env.js.map +1 -0
  23. package/dist/server/common/test/api-test-app.d.ts +12 -0
  24. package/dist/server/common/test/api-test-app.js +76 -0
  25. package/dist/server/common/test/api-test-app.js.map +1 -0
  26. package/dist/server/common/test/app-bootstrap.helper.js +8 -1
  27. package/dist/server/common/test/app-bootstrap.helper.js.map +1 -1
  28. package/dist/server/common/test/fake-bootstrap.server.js +3 -2
  29. package/dist/server/common/test/fake-bootstrap.server.js.map +1 -1
  30. package/dist/server/common/test/fake-docker-engine.server.d.ts +24 -6
  31. package/dist/server/common/test/fake-docker-engine.server.js +123 -25
  32. package/dist/server/common/test/fake-docker-engine.server.js.map +1 -1
  33. package/dist/server/common/test/fake-proxmox.server.js +4 -4
  34. package/dist/server/common/test/fake-ssh.server.js +6 -6
  35. package/dist/server/common/test/fake-ssh.server.js.map +1 -1
  36. package/dist/server/common/test/test-database.helper.d.ts +6 -0
  37. package/dist/server/common/test/test-database.helper.js +29 -0
  38. package/dist/server/common/test/test-database.helper.js.map +1 -0
  39. package/dist/server/modules/cloud-tunnel/services/mobile-chat-rpc.service.d.ts +1 -0
  40. package/dist/server/modules/cloud-tunnel/services/mobile-chat-rpc.service.js +9 -3
  41. package/dist/server/modules/cloud-tunnel/services/mobile-chat-rpc.service.js.map +1 -1
  42. package/dist/server/modules/cloud-tunnel/services/mobile-transcript-projection.d.ts +6 -0
  43. package/dist/server/modules/cloud-tunnel/services/mobile-transcript-projection.js +88 -0
  44. package/dist/server/modules/cloud-tunnel/services/mobile-transcript-projection.js.map +1 -0
  45. package/dist/server/modules/cloud-tunnel/services/tunnel-event-forwarder.service.js +7 -1
  46. package/dist/server/modules/cloud-tunnel/services/tunnel-event-forwarder.service.js.map +1 -1
  47. package/dist/server/modules/core/controllers/docker-archive.d.ts +9 -2
  48. package/dist/server/modules/core/controllers/docker-archive.js +22 -6
  49. package/dist/server/modules/core/controllers/docker-archive.js.map +1 -1
  50. package/dist/server/modules/core/controllers/docker-engine.client.d.ts +2 -1
  51. package/dist/server/modules/core/controllers/docker-engine.client.js +57 -4
  52. package/dist/server/modules/core/controllers/docker-engine.client.js.map +1 -1
  53. package/dist/server/modules/core/controllers/docker-image-metadata.d.ts +248 -0
  54. package/dist/server/modules/core/controllers/docker-image-metadata.js +161 -0
  55. package/dist/server/modules/core/controllers/docker-image-metadata.js.map +1 -0
  56. package/dist/server/modules/core/controllers/docker-settings.d.ts +13 -2
  57. package/dist/server/modules/core/controllers/docker-settings.js +49 -11
  58. package/dist/server/modules/core/controllers/docker-settings.js.map +1 -1
  59. package/dist/server/modules/core/controllers/host-user-identity.d.ts +34 -0
  60. package/dist/server/modules/core/controllers/host-user-identity.js +23 -0
  61. package/dist/server/modules/core/controllers/host-user-identity.js.map +1 -0
  62. package/dist/server/modules/core/controllers/runtime.controller.d.ts +11 -4
  63. package/dist/server/modules/core/controllers/runtime.controller.js +2 -0
  64. package/dist/server/modules/core/controllers/runtime.controller.js.map +1 -1
  65. package/dist/server/modules/file-sync/build-exclusion-suggestions.d.ts +15 -0
  66. package/dist/server/modules/file-sync/build-exclusion-suggestions.js +402 -0
  67. package/dist/server/modules/file-sync/build-exclusion-suggestions.js.map +1 -0
  68. package/dist/server/modules/file-sync/file-sync-auto-fix.dto.d.ts +102 -0
  69. package/dist/server/modules/file-sync/file-sync-auto-fix.dto.js +22 -0
  70. package/dist/server/modules/file-sync/file-sync-auto-fix.dto.js.map +1 -0
  71. package/dist/server/modules/file-sync/file-sync-auto-fix.store.d.ts +12 -0
  72. package/dist/server/modules/file-sync/file-sync-auto-fix.store.js +73 -0
  73. package/dist/server/modules/file-sync/file-sync-auto-fix.store.js.map +1 -0
  74. package/dist/server/modules/file-sync/file-sync-conflicts.d.ts +3 -0
  75. package/dist/server/modules/file-sync/file-sync-conflicts.js +191 -0
  76. package/dist/server/modules/file-sync/file-sync-conflicts.js.map +1 -0
  77. package/dist/server/modules/file-sync/file-sync-ignores.store.d.ts +5 -1
  78. package/dist/server/modules/file-sync/file-sync-ignores.store.js +39 -8
  79. package/dist/server/modules/file-sync/file-sync-ignores.store.js.map +1 -1
  80. package/dist/server/modules/file-sync/file-sync.controller.d.ts +1 -3
  81. package/dist/server/modules/file-sync/file-sync.controller.js +5 -14
  82. package/dist/server/modules/file-sync/file-sync.controller.js.map +1 -1
  83. package/dist/server/modules/file-sync/file-sync.dto.d.ts +220 -1
  84. package/dist/server/modules/file-sync/file-sync.dto.js +70 -4
  85. package/dist/server/modules/file-sync/file-sync.dto.js.map +1 -1
  86. package/dist/server/modules/file-sync/file-sync.module.js +16 -1
  87. package/dist/server/modules/file-sync/file-sync.module.js.map +1 -1
  88. package/dist/server/modules/file-sync/file-sync.service.d.ts +20 -5
  89. package/dist/server/modules/file-sync/file-sync.service.js +173 -37
  90. package/dist/server/modules/file-sync/file-sync.service.js.map +1 -1
  91. package/dist/server/modules/file-sync/git-guard.dto.d.ts +61 -0
  92. package/dist/server/modules/file-sync/git-guard.dto.js +26 -0
  93. package/dist/server/modules/file-sync/git-guard.dto.js.map +1 -0
  94. package/dist/server/modules/file-sync/home-git-guard.service.d.ts +4 -2
  95. package/dist/server/modules/file-sync/home-git-guard.service.js +50 -25
  96. package/dist/server/modules/file-sync/home-git-guard.service.js.map +1 -1
  97. package/dist/server/modules/file-sync/host-git-guard.controller.d.ts +10 -0
  98. package/dist/server/modules/file-sync/host-git-guard.controller.js +64 -0
  99. package/dist/server/modules/file-sync/host-git-guard.controller.js.map +1 -0
  100. package/dist/server/modules/file-sync/host-git-index.controller.d.ts +9 -0
  101. package/dist/server/modules/file-sync/host-git-index.controller.js +67 -0
  102. package/dist/server/modules/file-sync/host-git-index.controller.js.map +1 -0
  103. package/dist/server/modules/file-sync/host-sync.controller.d.ts +15 -2
  104. package/dist/server/modules/file-sync/host-sync.controller.js +122 -14
  105. package/dist/server/modules/file-sync/host-sync.controller.js.map +1 -1
  106. package/dist/server/modules/file-sync/ignore-pattern-matcher.d.ts +30 -0
  107. package/dist/server/modules/file-sync/ignore-pattern-matcher.js +183 -0
  108. package/dist/server/modules/file-sync/ignore-pattern-matcher.js.map +1 -0
  109. package/dist/server/modules/file-sync/project-repository.d.ts +2 -0
  110. package/dist/server/modules/file-sync/project-repository.js +20 -0
  111. package/dist/server/modules/file-sync/project-repository.js.map +1 -0
  112. package/dist/server/modules/file-sync/sync-chown.dto.d.ts +99 -0
  113. package/dist/server/modules/file-sync/sync-chown.dto.js +46 -0
  114. package/dist/server/modules/file-sync/sync-chown.dto.js.map +1 -0
  115. package/dist/server/modules/file-sync/sync-chown.service.d.ts +12 -0
  116. package/dist/server/modules/file-sync/sync-chown.service.js +230 -0
  117. package/dist/server/modules/file-sync/sync-chown.service.js.map +1 -0
  118. package/dist/server/modules/file-sync/sync-path-inspection.dto.d.ts +626 -0
  119. package/dist/server/modules/file-sync/sync-path-inspection.dto.js +108 -0
  120. package/dist/server/modules/file-sync/sync-path-inspection.dto.js.map +1 -0
  121. package/dist/server/modules/file-sync/sync-path-inspector.d.ts +12 -0
  122. package/dist/server/modules/file-sync/sync-path-inspector.js +413 -0
  123. package/dist/server/modules/file-sync/sync-path-inspector.js.map +1 -0
  124. package/dist/server/modules/file-sync/syncthing-rest.client.d.ts +1 -1
  125. package/dist/server/modules/file-sync/syncthing-rest.client.js +9 -4
  126. package/dist/server/modules/file-sync/syncthing-rest.client.js.map +1 -1
  127. package/dist/server/modules/file-sync/testing/fake-file-sync.service.d.ts +28 -5
  128. package/dist/server/modules/file-sync/testing/fake-file-sync.service.js +68 -5
  129. package/dist/server/modules/file-sync/testing/fake-file-sync.service.js.map +1 -1
  130. package/dist/server/modules/file-sync/translate-git-ignore-rule.d.ts +3 -0
  131. package/dist/server/modules/file-sync/translate-git-ignore-rule.js +30 -0
  132. package/dist/server/modules/file-sync/translate-git-ignore-rule.js.map +1 -0
  133. package/dist/server/modules/hooks/dtos/hook-event.dto.d.ts +86 -0
  134. package/dist/server/modules/hooks/dtos/hook-event.dto.js +15 -1
  135. package/dist/server/modules/hooks/dtos/hook-event.dto.js.map +1 -1
  136. package/dist/server/modules/hooks/services/hooks-config.service.js +29 -0
  137. package/dist/server/modules/hooks/services/hooks-config.service.js.map +1 -1
  138. package/dist/server/modules/hooks/services/hooks.service.d.ts +5 -1
  139. package/dist/server/modules/hooks/services/hooks.service.js +27 -5
  140. package/dist/server/modules/hooks/services/hooks.service.js.map +1 -1
  141. package/dist/server/modules/hooks/services/pending-ask-user-question.service.d.ts +2 -2
  142. package/dist/server/modules/hooks/services/pending-ask-user-question.service.js +9 -12
  143. package/dist/server/modules/hooks/services/pending-ask-user-question.service.js.map +1 -1
  144. package/dist/server/modules/mcp/services/handlers/skill-tools.js +2 -2
  145. package/dist/server/modules/mcp/services/handlers/skill-tools.js.map +1 -1
  146. package/dist/server/modules/metrics/services/metrics.service.js +1 -1
  147. package/dist/server/modules/metrics/services/metrics.service.js.map +1 -1
  148. package/dist/server/modules/providers/adapters/claude.adapter.d.ts +3 -1
  149. package/dist/server/modules/providers/adapters/claude.adapter.js +4 -1
  150. package/dist/server/modules/providers/adapters/claude.adapter.js.map +1 -1
  151. package/dist/server/modules/remotes/connect-choices.controller.d.ts +9 -0
  152. package/dist/server/modules/remotes/connect-choices.controller.js +54 -0
  153. package/dist/server/modules/remotes/connect-choices.controller.js.map +1 -0
  154. package/dist/server/modules/remotes/connect-choices.dto.d.ts +52 -0
  155. package/dist/server/modules/remotes/connect-choices.dto.js +19 -0
  156. package/dist/server/modules/remotes/connect-choices.dto.js.map +1 -0
  157. package/dist/server/modules/remotes/connect-choices.store.d.ts +12 -0
  158. package/dist/server/modules/remotes/connect-choices.store.js +95 -0
  159. package/dist/server/modules/remotes/connect-choices.store.js.map +1 -0
  160. package/dist/server/modules/remotes/controllers/remotes.controller.d.ts +3 -0
  161. package/dist/server/modules/remotes/controllers/remotes.controller.js +9 -1
  162. package/dist/server/modules/remotes/controllers/remotes.controller.js.map +1 -1
  163. package/dist/server/modules/remotes/docker/docker-copy-back.d.ts +1 -0
  164. package/dist/server/modules/remotes/docker/docker-copy-back.js +70 -31
  165. package/dist/server/modules/remotes/docker/docker-copy-back.js.map +1 -1
  166. package/dist/server/modules/remotes/docker/docker-handoff.d.ts +5 -3
  167. package/dist/server/modules/remotes/docker/docker-handoff.js +221 -53
  168. package/dist/server/modules/remotes/docker/docker-handoff.js.map +1 -1
  169. package/dist/server/modules/remotes/docker/docker-handoff.store.d.ts +5 -0
  170. package/dist/server/modules/remotes/docker/docker-handoff.store.js.map +1 -1
  171. package/dist/server/modules/remotes/docker/docker-plan-fit.d.ts +4 -1
  172. package/dist/server/modules/remotes/docker/docker-plan-fit.js +19 -6
  173. package/dist/server/modules/remotes/docker/docker-plan-fit.js.map +1 -1
  174. package/dist/server/modules/remotes/docker/docker-plan-policy.d.ts +6 -2
  175. package/dist/server/modules/remotes/docker/docker-plan-policy.js +191 -38
  176. package/dist/server/modules/remotes/docker/docker-plan-policy.js.map +1 -1
  177. package/dist/server/modules/remotes/docker/docker-plan-source.service.d.ts +55 -6
  178. package/dist/server/modules/remotes/docker/docker-plan-source.service.js +284 -52
  179. package/dist/server/modules/remotes/docker/docker-plan-source.service.js.map +1 -1
  180. package/dist/server/modules/remotes/docker/docker-plan.controller.d.ts +2 -1
  181. package/dist/server/modules/remotes/docker/docker-plan.controller.js +15 -1
  182. package/dist/server/modules/remotes/docker/docker-plan.controller.js.map +1 -1
  183. package/dist/server/modules/remotes/docker/docker-plan.dto.d.ts +47 -1
  184. package/dist/server/modules/remotes/docker/docker-plan.dto.js +1 -0
  185. package/dist/server/modules/remotes/docker/docker-plan.dto.js.map +1 -1
  186. package/dist/server/modules/remotes/docker/docker-plan.service.d.ts +15 -6
  187. package/dist/server/modules/remotes/docker/docker-plan.service.js +83 -20
  188. package/dist/server/modules/remotes/docker/docker-plan.service.js.map +1 -1
  189. package/dist/server/modules/remotes/docker/docker-project-compose.d.ts +7 -0
  190. package/dist/server/modules/remotes/docker/docker-project-compose.js +30 -0
  191. package/dist/server/modules/remotes/docker/docker-project-compose.js.map +1 -0
  192. package/dist/server/modules/remotes/dtos/remote.dto.d.ts +2 -0
  193. package/dist/server/modules/remotes/dtos/remote.dto.js.map +1 -1
  194. package/dist/server/modules/remotes/git-owner.store.d.ts +13 -0
  195. package/dist/server/modules/remotes/git-owner.store.js +69 -0
  196. package/dist/server/modules/remotes/git-owner.store.js.map +1 -0
  197. package/dist/server/modules/remotes/host/host-docker.controller.d.ts +14 -1
  198. package/dist/server/modules/remotes/host/host-docker.controller.js +28 -9
  199. package/dist/server/modules/remotes/host/host-docker.controller.js.map +1 -1
  200. package/dist/server/modules/remotes/host/host-docker.dto.d.ts +640 -3
  201. package/dist/server/modules/remotes/host/host-docker.dto.js +66 -9
  202. package/dist/server/modules/remotes/host/host-docker.dto.js.map +1 -1
  203. package/dist/server/modules/remotes/host/host-docker.service.d.ts +18 -6
  204. package/dist/server/modules/remotes/host/host-docker.service.js +184 -81
  205. package/dist/server/modules/remotes/host/host-docker.service.js.map +1 -1
  206. package/dist/server/modules/remotes/host/host-ipv4-routes.d.ts +4 -0
  207. package/dist/server/modules/remotes/host/host-ipv4-routes.js +43 -0
  208. package/dist/server/modules/remotes/host/host-ipv4-routes.js.map +1 -0
  209. package/dist/server/modules/remotes/host-image.d.ts +1 -1
  210. package/dist/server/modules/remotes/host-image.js +1 -1
  211. package/dist/server/modules/remotes/host-install/host-install-block.d.ts +1 -0
  212. package/dist/server/modules/remotes/host-install/host-install-block.js +76 -2
  213. package/dist/server/modules/remotes/host-install/host-install-block.js.map +1 -1
  214. package/dist/server/modules/remotes/host-install/host-install.service.d.ts +0 -1
  215. package/dist/server/modules/remotes/host-install/host-install.service.js +9 -26
  216. package/dist/server/modules/remotes/host-install/host-install.service.js.map +1 -1
  217. package/dist/server/modules/remotes/operations/attach.operation.d.ts +5 -1
  218. package/dist/server/modules/remotes/operations/attach.operation.js +41 -5
  219. package/dist/server/modules/remotes/operations/attach.operation.js.map +1 -1
  220. package/dist/server/modules/remotes/operations/claim.operation.d.ts +1 -0
  221. package/dist/server/modules/remotes/operations/claim.operation.js +6 -1
  222. package/dist/server/modules/remotes/operations/claim.operation.js.map +1 -1
  223. package/dist/server/modules/remotes/operations/detach.operation.d.ts +4 -1
  224. package/dist/server/modules/remotes/operations/detach.operation.js +10 -2
  225. package/dist/server/modules/remotes/operations/detach.operation.js.map +1 -1
  226. package/dist/server/modules/remotes/operations/docker-import-inventory.store.d.ts +10 -0
  227. package/dist/server/modules/remotes/operations/docker-import-inventory.store.js +17 -0
  228. package/dist/server/modules/remotes/operations/docker-import-inventory.store.js.map +1 -1
  229. package/dist/server/modules/remotes/operations/file-sync-handoff.d.ts +30 -2
  230. package/dist/server/modules/remotes/operations/file-sync-handoff.js +498 -57
  231. package/dist/server/modules/remotes/operations/file-sync-handoff.js.map +1 -1
  232. package/dist/server/modules/remotes/operations/force-sync.operation.d.ts +39 -0
  233. package/dist/server/modules/remotes/operations/force-sync.operation.js +177 -0
  234. package/dist/server/modules/remotes/operations/force-sync.operation.js.map +1 -0
  235. package/dist/server/modules/remotes/operations/git-owner.dto.d.ts +83 -0
  236. package/dist/server/modules/remotes/operations/git-owner.dto.js +25 -0
  237. package/dist/server/modules/remotes/operations/git-owner.dto.js.map +1 -0
  238. package/dist/server/modules/remotes/operations/git-owner.operation.d.ts +35 -0
  239. package/dist/server/modules/remotes/operations/git-owner.operation.js +216 -0
  240. package/dist/server/modules/remotes/operations/git-owner.operation.js.map +1 -0
  241. package/dist/server/modules/remotes/operations/remote-host.client.d.ts +72 -8
  242. package/dist/server/modules/remotes/operations/remote-host.client.js +162 -28
  243. package/dist/server/modules/remotes/operations/remote-host.client.js.map +1 -1
  244. package/dist/server/modules/remotes/operations/remote-operation.dto.d.ts +19 -0
  245. package/dist/server/modules/remotes/operations/remote-operation.dto.js +5 -1
  246. package/dist/server/modules/remotes/operations/remote-operation.dto.js.map +1 -1
  247. package/dist/server/modules/remotes/operations/remote-operation.runner.d.ts +3 -1
  248. package/dist/server/modules/remotes/operations/remote-operation.runner.js +59 -21
  249. package/dist/server/modules/remotes/operations/remote-operation.runner.js.map +1 -1
  250. package/dist/server/modules/remotes/operations/remote-operation.types.d.ts +4 -1
  251. package/dist/server/modules/remotes/operations/remote-operation.types.js +4 -2
  252. package/dist/server/modules/remotes/operations/remote-operation.types.js.map +1 -1
  253. package/dist/server/modules/remotes/operations/remote-operations.controller.d.ts +5 -0
  254. package/dist/server/modules/remotes/operations/remote-operations.controller.js +56 -0
  255. package/dist/server/modules/remotes/operations/remote-operations.controller.js.map +1 -1
  256. package/dist/server/modules/remotes/operations/remote-operations.service.d.ts +16 -1
  257. package/dist/server/modules/remotes/operations/remote-operations.service.js +155 -5
  258. package/dist/server/modules/remotes/operations/remote-operations.service.js.map +1 -1
  259. package/dist/server/modules/remotes/operations/update-logins.operation.d.ts +1 -3
  260. package/dist/server/modules/remotes/operations/update-logins.operation.js +3 -18
  261. package/dist/server/modules/remotes/operations/update-logins.operation.js.map +1 -1
  262. package/dist/server/modules/remotes/ports/remote-health.port.d.ts +2 -0
  263. package/dist/server/modules/remotes/ports/remote-health.port.js.map +1 -1
  264. package/dist/server/modules/remotes/remotes.module.js +18 -0
  265. package/dist/server/modules/remotes/remotes.module.js.map +1 -1
  266. package/dist/server/modules/remotes/replica/__fixtures__/replica-seed.d.ts +2 -2
  267. package/dist/server/modules/remotes/replica/__fixtures__/replica-seed.js +2 -13
  268. package/dist/server/modules/remotes/replica/__fixtures__/replica-seed.js.map +1 -1
  269. package/dist/server/modules/remotes/services/remote-health.service.js +5 -0
  270. package/dist/server/modules/remotes/services/remote-health.service.js.map +1 -1
  271. package/dist/server/modules/remotes/sync/file-sync-failures.service.d.ts +18 -0
  272. package/dist/server/modules/remotes/sync/file-sync-failures.service.js +157 -0
  273. package/dist/server/modules/remotes/sync/file-sync-failures.service.js.map +1 -0
  274. package/dist/server/modules/remotes/sync/file-sync-pattern-preview.service.d.ts +14 -0
  275. package/dist/server/modules/remotes/sync/file-sync-pattern-preview.service.js +99 -0
  276. package/dist/server/modules/remotes/sync/file-sync-pattern-preview.service.js.map +1 -0
  277. package/dist/server/modules/remotes/sync/file-sync-suggestions.service.d.ts +15 -0
  278. package/dist/server/modules/remotes/sync/file-sync-suggestions.service.js +90 -0
  279. package/dist/server/modules/remotes/sync/file-sync-suggestions.service.js.map +1 -0
  280. package/dist/server/modules/remotes/sync/project-file-sync.controller.d.ts +29 -0
  281. package/dist/server/modules/remotes/sync/project-file-sync.controller.js +160 -0
  282. package/dist/server/modules/remotes/sync/project-file-sync.controller.js.map +1 -0
  283. package/dist/server/modules/remotes/sync/remote-file-sync.dto.d.ts +72 -0
  284. package/dist/server/modules/remotes/sync/remote-file-sync.dto.js +16 -0
  285. package/dist/server/modules/remotes/sync/remote-file-sync.dto.js.map +1 -0
  286. package/dist/server/modules/remotes/sync/remote-file-sync.service.d.ts +32 -1
  287. package/dist/server/modules/remotes/sync/remote-file-sync.service.js +499 -38
  288. package/dist/server/modules/remotes/sync/remote-file-sync.service.js.map +1 -1
  289. package/dist/server/modules/remotes/sync/remote-live-sync.service.d.ts +2 -0
  290. package/dist/server/modules/remotes/sync/remote-live-sync.service.js +26 -12
  291. package/dist/server/modules/remotes/sync/remote-live-sync.service.js.map +1 -1
  292. package/dist/server/modules/remotes/vm-user-identity.d.ts +29 -0
  293. package/dist/server/modules/remotes/vm-user-identity.js +45 -0
  294. package/dist/server/modules/remotes/vm-user-identity.js.map +1 -0
  295. package/dist/server/modules/runtime-context-capture/codex-plugin-profile-materializer.service.js +5 -1
  296. package/dist/server/modules/runtime-context-capture/codex-plugin-profile-materializer.service.js.map +1 -1
  297. package/dist/server/modules/session-reader/adapters/claude-session-reader.adapter.d.ts +5 -0
  298. package/dist/server/modules/session-reader/adapters/claude-session-reader.adapter.js +9 -0
  299. package/dist/server/modules/session-reader/adapters/claude-session-reader.adapter.js.map +1 -1
  300. package/dist/server/modules/session-reader/adapters/session-reader-adapter.interface.d.ts +1 -0
  301. package/dist/server/modules/session-reader/adapters/utils/coalesce-turns.js +1 -0
  302. package/dist/server/modules/session-reader/adapters/utils/coalesce-turns.js.map +1 -1
  303. package/dist/server/modules/session-reader/builders/semantic-step-extractor.js +1 -1
  304. package/dist/server/modules/session-reader/builders/semantic-step-extractor.js.map +1 -1
  305. package/dist/server/modules/session-reader/controllers/session-reader.controller.js +1 -1
  306. package/dist/server/modules/session-reader/controllers/session-reader.controller.js.map +1 -1
  307. package/dist/server/modules/session-reader/data/pricing.json +89 -12
  308. package/dist/server/modules/session-reader/dtos/unified-message.types.d.ts +1 -0
  309. package/dist/server/modules/session-reader/parsers/claude-jsonl.parser.d.ts +3 -0
  310. package/dist/server/modules/session-reader/parsers/claude-jsonl.parser.js +10 -1
  311. package/dist/server/modules/session-reader/parsers/claude-jsonl.parser.js.map +1 -1
  312. package/dist/server/modules/session-reader/parsers/claude-turn-evidence.d.ts +11 -0
  313. package/dist/server/modules/session-reader/parsers/claude-turn-evidence.js +50 -0
  314. package/dist/server/modules/session-reader/parsers/claude-turn-evidence.js.map +1 -0
  315. package/dist/server/modules/session-reader/parsers/codex-jsonl.parser.js +8 -2
  316. package/dist/server/modules/session-reader/parsers/codex-jsonl.parser.js.map +1 -1
  317. package/dist/server/modules/session-reader/services/bounded-anchor-proof.d.ts +7 -0
  318. package/dist/server/modules/session-reader/services/bounded-anchor-proof.js +31 -2
  319. package/dist/server/modules/session-reader/services/bounded-anchor-proof.js.map +1 -1
  320. package/dist/server/modules/session-reader/services/session-cache.service.d.ts +8 -2
  321. package/dist/server/modules/session-reader/services/session-cache.service.js +80 -21
  322. package/dist/server/modules/session-reader/services/session-cache.service.js.map +1 -1
  323. package/dist/server/modules/session-reader/services/session-reader.service.d.ts +4 -0
  324. package/dist/server/modules/session-reader/services/session-reader.service.js +40 -8
  325. package/dist/server/modules/session-reader/services/session-reader.service.js.map +1 -1
  326. package/dist/server/modules/session-reader/services/transcript-cursor.d.ts +16 -4
  327. package/dist/server/modules/session-reader/services/transcript-cursor.js +65 -6
  328. package/dist/server/modules/session-reader/services/transcript-cursor.js.map +1 -1
  329. package/dist/server/modules/session-reader/services/transcript-serialization.js +2 -1
  330. package/dist/server/modules/session-reader/services/transcript-serialization.js.map +1 -1
  331. package/dist/server/modules/session-reader/services/transcript-turn-state.d.ts +4 -0
  332. package/dist/server/modules/session-reader/services/transcript-turn-state.js +20 -0
  333. package/dist/server/modules/session-reader/services/transcript-turn-state.js.map +1 -0
  334. package/dist/server/modules/session-reader/services/transcript-watcher.service.d.ts +4 -1
  335. package/dist/server/modules/session-reader/services/transcript-watcher.service.js +43 -18
  336. package/dist/server/modules/session-reader/services/transcript-watcher.service.js.map +1 -1
  337. package/dist/server/modules/sessions/services/provider-launch-config/provider-launch-config.service.js +5 -0
  338. package/dist/server/modules/sessions/services/provider-launch-config/provider-launch-config.service.js.map +1 -1
  339. package/dist/server/modules/sessions/services/session-runtime/__test-utils__/pipeline-harness.d.ts +36 -17
  340. package/dist/server/modules/sessions/services/session-runtime/__test-utils__/pipeline-harness.js +26 -9
  341. package/dist/server/modules/sessions/services/session-runtime/__test-utils__/pipeline-harness.js.map +1 -1
  342. package/dist/server/modules/sessions/services/session-runtime/ensure-mcp-readiness.d.ts +19 -0
  343. package/dist/server/modules/sessions/services/session-runtime/ensure-mcp-readiness.js +26 -0
  344. package/dist/server/modules/sessions/services/session-runtime/ensure-mcp-readiness.js.map +1 -0
  345. package/dist/server/modules/sessions/services/session-runtime/session-launch-pipeline.service.js +10 -18
  346. package/dist/server/modules/sessions/services/session-runtime/session-launch-pipeline.service.js.map +1 -1
  347. package/dist/server/modules/sessions/services/session-runtime/session-restore-pipeline.service.d.ts +5 -1
  348. package/dist/server/modules/sessions/services/session-runtime/session-restore-pipeline.service.js +20 -2
  349. package/dist/server/modules/sessions/services/session-runtime/session-restore-pipeline.service.js.map +1 -1
  350. package/dist/server/modules/settings/local/delegates/skills-settings.delegate.d.ts +6 -0
  351. package/dist/server/modules/settings/local/delegates/skills-settings.delegate.js +26 -0
  352. package/dist/server/modules/settings/local/delegates/skills-settings.delegate.js.map +1 -1
  353. package/dist/server/modules/settings/services/settings.service.d.ts +3 -1
  354. package/dist/server/modules/settings/services/settings.service.js +6 -0
  355. package/dist/server/modules/settings/services/settings.service.js.map +1 -1
  356. package/dist/server/modules/skills/adapters/anthropic-skill-source.adapter.js +5 -5
  357. package/dist/server/modules/skills/adapters/anthropic-skill-source.adapter.js.map +1 -1
  358. package/dist/server/modules/skills/adapters/github-directory-skill-source.adapter.js +5 -5
  359. package/dist/server/modules/skills/adapters/github-directory-skill-source.adapter.js.map +1 -1
  360. package/dist/server/modules/skills/adapters/github-skill-source.base.js +4 -3
  361. package/dist/server/modules/skills/adapters/github-skill-source.base.js.map +1 -1
  362. package/dist/server/modules/skills/adapters/local-skill-source.adapter.js +5 -5
  363. package/dist/server/modules/skills/adapters/local-skill-source.adapter.js.map +1 -1
  364. package/dist/server/modules/skills/adapters/microsoft-skill-source.adapter.js +5 -5
  365. package/dist/server/modules/skills/adapters/microsoft-skill-source.adapter.js.map +1 -1
  366. package/dist/server/modules/skills/adapters/openai-skill-source.adapter.js +5 -5
  367. package/dist/server/modules/skills/adapters/openai-skill-source.adapter.js.map +1 -1
  368. package/dist/server/modules/skills/adapters/skill-source.adapter.d.ts +5 -0
  369. package/dist/server/modules/skills/adapters/skill-sync-temp-cleanup.d.ts +5 -0
  370. package/dist/server/modules/skills/adapters/skill-sync-temp-cleanup.js +75 -0
  371. package/dist/server/modules/skills/adapters/skill-sync-temp-cleanup.js.map +1 -0
  372. package/dist/server/modules/skills/adapters/trailofbits-skill-source.adapter.js +5 -5
  373. package/dist/server/modules/skills/adapters/trailofbits-skill-source.adapter.js.map +1 -1
  374. package/dist/server/modules/skills/adapters/vercel-skill-source.adapter.js +5 -5
  375. package/dist/server/modules/skills/adapters/vercel-skill-source.adapter.js.map +1 -1
  376. package/dist/server/modules/skills/controllers/skills.controller.js +2 -2
  377. package/dist/server/modules/skills/controllers/skills.controller.js.map +1 -1
  378. package/dist/server/modules/skills/services/skill-source-lifecycle.service.d.ts +3 -3
  379. package/dist/server/modules/skills/services/skill-source-lifecycle.service.js +9 -4
  380. package/dist/server/modules/skills/services/skill-source-lifecycle.service.js.map +1 -1
  381. package/dist/server/modules/skills/services/skill-sync.service.d.ts +3 -3
  382. package/dist/server/modules/skills/services/skill-sync.service.js +32 -6
  383. package/dist/server/modules/skills/services/skill-sync.service.js.map +1 -1
  384. package/dist/server/modules/skills/services/skill-sync.types.d.ts +3 -0
  385. package/dist/server/modules/storage/db/schema.d.ts +2 -2
  386. package/dist/server/modules/storage/db/schema.js +2 -0
  387. package/dist/server/modules/storage/db/schema.js.map +1 -1
  388. package/dist/server/modules/storage/models/domain.models.d.ts +1 -1
  389. package/dist/server/modules/storage/models/domain.models.js +2 -0
  390. package/dist/server/modules/storage/models/domain.models.js.map +1 -1
  391. package/dist/server/modules/teams/storage/teams.store.d.ts +1 -0
  392. package/dist/server/modules/teams/storage/teams.store.js +19 -3
  393. package/dist/server/modules/teams/storage/teams.store.js.map +1 -1
  394. package/dist/server/modules/terminal/gateways/terminal.gateway.d.ts +3 -1
  395. package/dist/server/modules/terminal/gateways/terminal.gateway.js +9 -4
  396. package/dist/server/modules/terminal/gateways/terminal.gateway.js.map +1 -1
  397. package/dist/server/modules/terminal/services/session-turn-signals.d.ts +18 -0
  398. package/dist/server/modules/terminal/services/session-turn-signals.js +6 -0
  399. package/dist/server/modules/terminal/services/session-turn-signals.js.map +1 -0
  400. package/dist/server/modules/terminal/services/terminal-activity.service.d.ts +32 -5
  401. package/dist/server/modules/terminal/services/terminal-activity.service.js +322 -40
  402. package/dist/server/modules/terminal/services/terminal-activity.service.js.map +1 -1
  403. package/dist/server/modules/terminal/services/terminal-io/lifecycle.js +15 -3
  404. package/dist/server/modules/terminal/services/terminal-io/lifecycle.js.map +1 -1
  405. package/dist/server/modules/terminal/terminal.module.js +2 -0
  406. package/dist/server/modules/terminal/terminal.module.js.map +1 -1
  407. package/dist/server/modules/terminal/utils/ansi-sanitizer.d.ts +0 -1
  408. package/dist/server/modules/terminal/utils/ansi-sanitizer.js +0 -4
  409. package/dist/server/modules/terminal/utils/ansi-sanitizer.js.map +1 -1
  410. package/dist/server/templates/teams-dev.json +14 -14
  411. package/dist/server/test-setup-node.js +4 -3
  412. package/dist/server/test-setup-node.js.map +1 -1
  413. package/dist/server/test-setup.js +7 -0
  414. package/dist/server/test-setup.js.map +1 -1
  415. package/dist/server/tsconfig.tsbuildinfo +1 -1
  416. package/dist/server/ui/assets/{ExternalRichEditor--kNXs-Eb.js → ExternalRichEditor-CIZPhssf.js} +24 -24
  417. package/dist/server/ui/assets/ReviewDetailPage-winyLSQ7.js +6 -0
  418. package/dist/server/ui/assets/ReviewsPage-BYKBReMp.js +6 -0
  419. package/dist/server/ui/assets/index-CiDJX6Hn.js +1191 -0
  420. package/dist/server/ui/assets/index-f1WOAqXB.css +32 -0
  421. package/dist/server/ui/assets/useReviewSubscription-v3Cto0y4.js +69 -0
  422. package/dist/server/ui/index.html +2 -2
  423. package/dist/templates/teams-dev.json +14 -14
  424. package/package.json +15 -1
  425. package/dist/server/modules/reviews/utils/notification-formatter.d.ts +0 -12
  426. package/dist/server/modules/reviews/utils/notification-formatter.js +0 -60
  427. package/dist/server/modules/reviews/utils/notification-formatter.js.map +0 -1
  428. package/dist/server/ui/assets/ReviewDetailPage-DMgP5fKn.js +0 -6
  429. package/dist/server/ui/assets/ReviewsPage-CkyFUJr6.js +0 -6
  430. package/dist/server/ui/assets/index-CVUaAlP4.css +0 -32
  431. package/dist/server/ui/assets/index-CqRufKpA.js +0 -994
  432. package/dist/server/ui/assets/useReviewSubscription-CU70CzwG.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,22 +34,236 @@ 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;
38
- constructor(fileSync, host, managedExclusions, guard) {
52
+ processExecutor;
53
+ gitOwner;
54
+ active = new Map();
55
+ constructor(fileSync, host, managedExclusions, guard, processExecutor, gitOwner) {
39
56
  this.fileSync = fileSync;
40
57
  this.host = host;
41
58
  this.managedExclusions = managedExclusions;
42
59
  this.guard = guard;
60
+ this.processExecutor = processExecutor;
61
+ this.gitOwner = gitOwner;
62
+ }
63
+ interrupt(operationId, reason = 'The Connect was cancelled.') {
64
+ this.active.get(operationId)?.abort(new Error(reason));
43
65
  }
44
66
  async initial(run, projectId) {
67
+ const controller = new AbortController();
68
+ this.active.set(run.operation.id, controller);
69
+ try {
70
+ const { remoteId } = run.operation;
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';
88
+ const devices = await this.pair(remoteId, controller.signal);
89
+ const folders = await this.fileSync.initialFolders(projectId);
90
+ for (const folder of folders) {
91
+ const request = {
92
+ projectId,
93
+ kind: folder.kind,
94
+ ignores: folder.kind === 'code' ? ignores : (0, file_sync_dto_1.gitIgnores)(false),
95
+ paused: true,
96
+ };
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
+ });
106
+ await this.host.syncFolders(remoteId, {
107
+ ...request,
108
+ type: mergeCode ? 'sendreceive' : 'receiveonly',
109
+ peerDeviceId: devices.home,
110
+ });
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
+ }
145
+ await this.unpauseAll(remoteId, 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
+ }
156
+ }
157
+ finally {
158
+ if (this.active.get(run.operation.id) === controller)
159
+ this.active.delete(run.operation.id);
160
+ }
161
+ }
162
+ async ensureAvailable() {
163
+ await this.fileSync.ensureAvailable();
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
+ }
182
+ async flipToHost(run, projectId) {
45
183
  const { remoteId } = run.operation;
46
- const ignores = this.syncIgnores(projectId);
184
+ const folders = await this.fileSync.projectFolders(projectId);
185
+ await this.hostDirections(remoteId, folders, 'vm', false);
186
+ if (folders.some((folder) => folder.kind === 'git')) {
187
+ const guardWarning = await this.guard.install(projectId, remoteId);
188
+ if (guardWarning)
189
+ await run.progress({ guardWarning });
190
+ }
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
+ }
47
265
  const devices = await this.pair(remoteId);
48
- const folders = await this.fileSync.initialFolders(projectId);
266
+ const ignores = this.syncIgnores(projectId);
49
267
  for (const folder of folders) {
50
268
  const request = {
51
269
  projectId,
@@ -55,33 +273,167 @@ let FileSyncHandoff = class FileSyncHandoff {
55
273
  };
56
274
  await this.fileSync.ensureFolder({
57
275
  ...request,
58
- type: 'sendonly',
276
+ type: sender === 'home' ? 'sendonly' : 'receiveonly',
59
277
  peerDeviceId: devices.host,
278
+ ...(receiver === 'home' && { forceCopy: { operationId } }),
60
279
  });
61
280
  await this.host.syncFolders(remoteId, {
62
281
  ...request,
63
- type: 'receiveonly',
282
+ type: sender === 'host' ? 'sendonly' : 'receiveonly',
64
283
  peerDeviceId: devices.home,
284
+ ...(receiver === 'host' && { forceCopy: { operationId } }),
65
285
  });
66
286
  }
67
287
  await this.unpauseAll(remoteId, folders);
68
- await this.waitAll(run, folders, { sender: 'home', devices });
69
- }
70
- async ensureAvailable() {
71
- await this.fileSync.ensureAvailable();
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 });
72
333
  }
73
- async flipToHost(run, projectId) {
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);
74
337
  const { remoteId } = run.operation;
75
- const folders = await this.fileSync.projectFolders(projectId);
76
- await this.hostDirections(remoteId, folders, false);
77
- if (folders.some((folder) => folder.kind === 'git')) {
78
- const guardWarning = await this.guard.install(projectId, remoteId);
79
- if (guardWarning)
80
- await run.progress({ guardWarning });
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
+ }
81
382
  }
82
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
+ }
83
434
  async final(run, projectId) {
84
435
  const { remoteId } = run.operation;
436
+ const owner = this.gitOwner.get(projectId);
85
437
  const ignores = this.syncIgnores(projectId);
86
438
  const devices = await this.pair(remoteId);
87
439
  const folders = await this.fileSync.projectFolders(projectId);
@@ -93,19 +445,31 @@ let FileSyncHandoff = class FileSyncHandoff {
93
445
  ignores: folder.kind === 'code' ? ignores : (0, file_sync_dto_1.gitIgnores)(true),
94
446
  paused: true,
95
447
  };
96
- await this.host.syncFolders(remoteId, {
448
+ const ensureHost = () => this.host.syncFolders(remoteId, {
97
449
  ...request,
98
- type: folder.kind === 'code' ? 'sendreceive' : 'sendonly',
450
+ type: folder.kind === 'code' ? 'sendreceive' : owner === 'vm' ? 'sendonly' : 'receiveonly',
99
451
  peerDeviceId: devices.home,
100
452
  });
101
- await this.fileSync.ensureFolder({
453
+ const ensureHome = () => this.fileSync.ensureFolder({
102
454
  ...request,
103
- type: folder.kind === 'code' ? 'sendreceive' : 'receiveonly',
455
+ type: folder.kind === 'code' ? 'sendreceive' : owner === 'home' ? 'sendonly' : 'receiveonly',
104
456
  peerDeviceId: devices.host,
105
457
  });
458
+ if (folder.kind === 'git' && owner === 'vm') {
459
+ await ensureHome();
460
+ await ensureHost();
461
+ }
462
+ else {
463
+ await ensureHost();
464
+ await ensureHome();
465
+ }
106
466
  }
107
467
  await this.unpauseAll(remoteId, folders);
108
- await this.waitAll(run, folders, { sender: 'host', devices, symmetricCode: true });
468
+ await this.waitAll(run, folders, {
469
+ sender: (folder) => (folder.kind === 'git' && owner === 'home' ? 'home' : 'host'),
470
+ devices,
471
+ symmetricCode: true,
472
+ });
109
473
  }
110
474
  async flipToHome(run, projectId, force) {
111
475
  const { remoteId } = run.operation;
@@ -115,8 +479,25 @@ let FileSyncHandoff = class FileSyncHandoff {
115
479
  }
116
480
  await this.update('home', remoteId, folder.id, { type: 'sendonly', paused: true });
117
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
+ }
118
495
  await this.deleteHomeTempFiles(projectId);
119
- await this.guard.remove(projectId, { refreshIndex: true });
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 });
120
501
  }
121
502
  async removeFolders(remoteId, projectId) {
122
503
  const folders = (0, file_sync_service_1.projectFolderList)(projectId);
@@ -136,23 +517,38 @@ let FileSyncHandoff = class FileSyncHandoff {
136
517
  }
137
518
  }
138
519
  async flipBackToHost(remoteId, projectId, force) {
520
+ const owner = this.gitOwner.get(projectId);
139
521
  const folders = await this.fileSync.projectFolders(projectId);
140
- await this.hostDirections(remoteId, folders, force, false);
522
+ await this.hostDirections(remoteId, folders, owner, force, false);
141
523
  if (folders.some((folder) => folder.kind === 'git')) {
142
- const guardWarning = await this.guard.reinstall(projectId, remoteId);
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;
143
532
  if (guardWarning) {
144
533
  logger.warn({ projectId, remoteId, guardWarning }, 'Remote git guard not reinstalled');
145
534
  }
146
535
  }
147
536
  }
148
- async hostDirections(remoteId, folders, force, paused) {
537
+ async hostDirections(remoteId, folders, owner, force, paused) {
149
538
  for (const folder of folders) {
150
539
  const pause = paused === undefined ? {} : { paused };
151
540
  if (folder.kind === 'git') {
152
541
  const ignores = (0, file_sync_dto_1.gitIgnores)(true);
153
- await this.update('home', remoteId, folder.id, { type: 'receiveonly', ignores, ...pause });
154
- if (!force)
155
- await this.update('host', remoteId, folder.id, { type: 'sendonly', ignores, ...pause });
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 });
156
552
  }
157
553
  else {
158
554
  if (!force)
@@ -176,13 +572,14 @@ let FileSyncHandoff = class FileSyncHandoff {
176
572
  logger.warn({ projectId, error: error instanceof Error ? error.message : String(error) }, 'Syncthing temp-file cleanup skipped');
177
573
  }
178
574
  }
179
- async pair(remoteId) {
575
+ async pair(remoteId, signal) {
180
576
  const home = this.fileSync.device();
181
577
  const host = await this.host.syncDevice(remoteId);
182
578
  await this.fileSync.addPeer(host);
183
579
  await this.host.syncPeer(remoteId, home);
184
580
  const deadline = Date.now() + CONNECT_TIMEOUT_MS;
185
581
  while (!(await this.fileSync.isConnected(host.deviceId))) {
582
+ signal?.throwIfAborted();
186
583
  if (Date.now() >= deadline)
187
584
  throw new FileSyncNotConnectedError(host.address);
188
585
  await sleep(POLL_MS);
@@ -195,39 +592,77 @@ let FileSyncHandoff = class FileSyncHandoff {
195
592
  await this.update('home', remoteId, folder.id, { paused: false });
196
593
  }
197
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
+ }
198
610
  async waitAll(run, folders, options) {
199
611
  const { remoteId } = run.operation;
200
- const receiver = options.sender === 'home' ? 'host' : 'home';
201
- const receiverDevice = receiver === 'home' ? options.devices.home : options.devices.host;
202
612
  const progress = {};
203
613
  const report = () => run.progress({ fileSync: { folders: { ...progress } } });
204
614
  for (const folder of folders) {
205
615
  progress[folder.id] = { completion: 0, needItems: 0, needBytes: 0 };
206
616
  }
207
617
  await report();
208
- await Promise.all(folders.map(async (folder) => {
209
- const symmetric = options.symmetricCode === true && folder.kind === 'code';
210
- await Promise.all([
211
- this.scan(options.sender, remoteId, folder.id),
212
- ...(symmetric ? [this.scan(receiver, remoteId, folder.id)] : []),
213
- ]);
214
- progress[folder.id] = await this.fileSync.waitForComplete(folder.id, {
215
- symmetric,
216
- sender: () => this.status(options.sender, remoteId, folder.id, receiverDevice),
217
- receiver: async () => {
218
- const status = await this.status(receiver, remoteId, folder.id, symmetric ? options.devices[options.sender] : undefined);
219
- if (!symmetric && status.receiveOnlyChangedFiles > 0 && status.state === 'idle') {
220
- await this.revert(receiver, remoteId, folder.id);
221
- }
222
- return status;
223
- },
224
- timeoutMs: SYNC_TIMEOUT_MS,
225
- onProgress: (current) => {
226
- progress[folder.id] = current;
227
- void report();
228
- },
229
- });
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
+ }
230
663
  }));
664
+ if (stop.signal.aborted)
665
+ throw stop.signal.reason;
231
666
  await report();
232
667
  }
233
668
  async update(side, remoteId, folderId, patch) {
@@ -244,14 +679,18 @@ let FileSyncHandoff = class FileSyncHandoff {
244
679
  throw error;
245
680
  }
246
681
  }
247
- 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);
248
687
  return side === 'home'
249
688
  ? this.fileSync.status(folderId, peerDeviceId)
250
689
  : this.host.syncStatus(remoteId, folderId, peerDeviceId);
251
690
  }
252
- scan(side, remoteId, folderId) {
691
+ scan(side, remoteId, folderId, signal) {
253
692
  return side === 'home'
254
- ? this.fileSync.rescan(folderId)
693
+ ? this.fileSync.rescan(folderId, signal)
255
694
  : this.host.syncScan(remoteId, folderId);
256
695
  }
257
696
  revert(side, remoteId, folderId) {
@@ -266,7 +705,9 @@ exports.FileSyncHandoff = FileSyncHandoff = __decorate([
266
705
  __metadata("design:paramtypes", [file_sync_service_1.FileSyncService,
267
706
  remote_host_client_1.RemoteHostClient,
268
707
  file_sync_managed_exclusions_store_1.FileSyncManagedExclusionsStore,
269
- 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])
270
711
  ], FileSyncHandoff);
271
712
  function sleep(ms) {
272
713
  return new Promise((resolve) => setTimeout(resolve, ms));