devchain-cli 0.16.2 → 0.17.0

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 (289) hide show
  1. package/dist/drizzle/0066_provider_efforts_and_overrides.sql +29 -0
  2. package/dist/drizzle/meta/0066_snapshot.json +5803 -0
  3. package/dist/drizzle/meta/_journal.json +7 -0
  4. package/dist/node_modules/@devchain/codebase-overview/tsconfig.tsbuildinfo +1 -1
  5. package/dist/node_modules/@devchain/shared/schemas/export-schema.d.ts +55 -4
  6. package/dist/node_modules/@devchain/shared/schemas/export-schema.d.ts.map +1 -1
  7. package/dist/node_modules/@devchain/shared/schemas/export-schema.js +12 -0
  8. package/dist/node_modules/@devchain/shared/schemas/export-schema.js.map +1 -1
  9. package/dist/node_modules/@devchain/shared/tsconfig.tsbuildinfo +1 -1
  10. package/dist/server/modules/agent-message-delivery/agent-message-delivery.service.js +6 -1
  11. package/dist/server/modules/agent-message-delivery/agent-message-delivery.service.js.map +1 -1
  12. package/dist/server/modules/agent-message-delivery/dtos/delivery.types.d.ts +2 -0
  13. package/dist/server/modules/agents/controllers/agents.controller.d.ts +3 -0
  14. package/dist/server/modules/agents/controllers/agents.controller.js +6 -0
  15. package/dist/server/modules/agents/controllers/agents.controller.js.map +1 -1
  16. package/dist/server/modules/cloud-tunnel/cloud-tunnel.module.js +4 -0
  17. package/dist/server/modules/cloud-tunnel/cloud-tunnel.module.js.map +1 -1
  18. package/dist/server/modules/cloud-tunnel/services/mobile-chat-rpc.service.d.ts +6 -1
  19. package/dist/server/modules/cloud-tunnel/services/mobile-chat-rpc.service.js +18 -2
  20. package/dist/server/modules/cloud-tunnel/services/mobile-chat-rpc.service.js.map +1 -1
  21. package/dist/server/modules/cloud-tunnel/services/tunnel-handler.service.d.ts +7 -1
  22. package/dist/server/modules/cloud-tunnel/services/tunnel-handler.service.js +63 -2
  23. package/dist/server/modules/cloud-tunnel/services/tunnel-handler.service.js.map +1 -1
  24. package/dist/server/modules/events/catalog/claude.hooks.session.started.d.ts +2 -2
  25. package/dist/server/modules/events/catalog/index.d.ts +2 -2
  26. package/dist/server/modules/hooks/dtos/hook-event.dto.d.ts +16 -16
  27. package/dist/server/modules/orchestrator/docker/docker.module.js +2 -1
  28. package/dist/server/modules/orchestrator/docker/docker.module.js.map +1 -1
  29. package/dist/server/modules/orchestrator/docker/services/docker.service.d.ts +3 -9
  30. package/dist/server/modules/orchestrator/docker/services/docker.service.js +19 -170
  31. package/dist/server/modules/orchestrator/docker/services/docker.service.js.map +1 -1
  32. package/dist/server/modules/orchestrator/docker/services/worktree-mount-discovery.service.d.ts +20 -0
  33. package/dist/server/modules/orchestrator/docker/services/worktree-mount-discovery.service.js +191 -0
  34. package/dist/server/modules/orchestrator/docker/services/worktree-mount-discovery.service.js.map +1 -0
  35. package/dist/server/modules/orchestrator/worktrees/runtime/container-runtime.d.ts +17 -0
  36. package/dist/server/modules/orchestrator/worktrees/runtime/container-runtime.js +58 -0
  37. package/dist/server/modules/orchestrator/worktrees/runtime/container-runtime.js.map +1 -0
  38. package/dist/server/modules/orchestrator/worktrees/runtime/process-runtime.d.ts +38 -0
  39. package/dist/server/modules/orchestrator/worktrees/runtime/process-runtime.js +295 -0
  40. package/dist/server/modules/orchestrator/worktrees/runtime/process-runtime.js.map +1 -0
  41. package/dist/server/modules/orchestrator/worktrees/runtime/worktree-runtime.d.ts +15 -0
  42. package/dist/server/modules/orchestrator/worktrees/runtime/worktree-runtime.js +3 -0
  43. package/dist/server/modules/orchestrator/worktrees/runtime/worktree-runtime.js.map +1 -0
  44. package/dist/server/modules/orchestrator/worktrees/services/worktrees.service.d.ts +12 -17
  45. package/dist/server/modules/orchestrator/worktrees/services/worktrees.service.js +83 -304
  46. package/dist/server/modules/orchestrator/worktrees/services/worktrees.service.js.map +1 -1
  47. package/dist/server/modules/orchestrator/worktrees/worktrees.module.js +4 -0
  48. package/dist/server/modules/orchestrator/worktrees/worktrees.module.js.map +1 -1
  49. package/dist/server/modules/profiles/controllers/profiles.controller.js +2 -0
  50. package/dist/server/modules/profiles/controllers/profiles.controller.js.map +1 -1
  51. package/dist/server/modules/profiles/controllers/provider-configs.controller.js +6 -0
  52. package/dist/server/modules/profiles/controllers/provider-configs.controller.js.map +1 -1
  53. package/dist/server/modules/profiles/dto.d.ts +24 -6
  54. package/dist/server/modules/profiles/dto.js +14 -0
  55. package/dist/server/modules/profiles/dto.js.map +1 -1
  56. package/dist/server/modules/projects/controllers/projects.controller.d.ts +60 -35
  57. package/dist/server/modules/projects/controllers/projects.controller.js +90 -8
  58. package/dist/server/modules/projects/controllers/projects.controller.js.map +1 -1
  59. package/dist/server/modules/projects/dtos/export.dto.d.ts +7 -0
  60. package/dist/server/modules/projects/dtos/export.dto.js +1 -0
  61. package/dist/server/modules/projects/dtos/export.dto.js.map +1 -1
  62. package/dist/server/modules/projects/dtos/setup-preview.dto.d.ts +28 -0
  63. package/dist/server/modules/projects/dtos/setup-preview.dto.js +3 -0
  64. package/dist/server/modules/projects/dtos/setup-preview.dto.js.map +1 -0
  65. package/dist/server/modules/projects/helpers/profile-mapping.helpers.d.ts +26 -2
  66. package/dist/server/modules/projects/helpers/profile-mapping.helpers.js +140 -4
  67. package/dist/server/modules/projects/helpers/profile-mapping.helpers.js.map +1 -1
  68. package/dist/server/modules/projects/helpers/project-export.d.ts +26 -17
  69. package/dist/server/modules/projects/helpers/project-export.js +36 -323
  70. package/dist/server/modules/projects/helpers/project-export.js.map +1 -1
  71. package/dist/server/modules/projects/helpers/project-import.d.ts +13 -16
  72. package/dist/server/modules/projects/helpers/project-import.js +56 -354
  73. package/dist/server/modules/projects/helpers/project-import.js.map +1 -1
  74. package/dist/server/modules/projects/helpers/project-presets.helpers.d.ts +5 -0
  75. package/dist/server/modules/projects/helpers/project-presets.helpers.js +32 -14
  76. package/dist/server/modules/projects/helpers/project-presets.helpers.js.map +1 -1
  77. package/dist/server/modules/projects/helpers/team-overrides.helpers.d.ts +26 -0
  78. package/dist/server/modules/projects/helpers/team-overrides.helpers.js +53 -0
  79. package/dist/server/modules/projects/helpers/team-overrides.helpers.js.map +1 -0
  80. package/dist/server/modules/projects/helpers/template-loader.d.ts +16 -4
  81. package/dist/server/modules/projects/helpers/template-loader.js +93 -308
  82. package/dist/server/modules/projects/helpers/template-loader.js.map +1 -1
  83. package/dist/server/modules/projects/projects.module.js +2 -0
  84. package/dist/server/modules/projects/projects.module.js.map +1 -1
  85. package/dist/server/modules/projects/services/projects.service.d.ts +41 -21
  86. package/dist/server/modules/projects/services/projects.service.js +69 -7
  87. package/dist/server/modules/projects/services/projects.service.js.map +1 -1
  88. package/dist/server/modules/projects/template-codec/codec-registry.d.ts +3 -0
  89. package/dist/server/modules/projects/template-codec/codec-registry.js +33 -0
  90. package/dist/server/modules/projects/template-codec/codec-registry.js.map +1 -0
  91. package/dist/server/modules/projects/template-codec/codecs/agents.codec.d.ts +40 -0
  92. package/dist/server/modules/projects/template-codec/codecs/agents.codec.js +96 -0
  93. package/dist/server/modules/projects/template-codec/codecs/agents.codec.js.map +1 -0
  94. package/dist/server/modules/projects/template-codec/codecs/presets.codec.d.ts +16 -0
  95. package/dist/server/modules/projects/template-codec/codecs/presets.codec.js +34 -0
  96. package/dist/server/modules/projects/template-codec/codecs/presets.codec.js.map +1 -0
  97. package/dist/server/modules/projects/template-codec/codecs/profiles.codec.d.ts +71 -0
  98. package/dist/server/modules/projects/template-codec/codecs/profiles.codec.js +152 -0
  99. package/dist/server/modules/projects/template-codec/codecs/profiles.codec.js.map +1 -0
  100. package/dist/server/modules/projects/template-codec/codecs/project-settings.codec.d.ts +42 -0
  101. package/dist/server/modules/projects/template-codec/codecs/project-settings.codec.js +68 -0
  102. package/dist/server/modules/projects/template-codec/codecs/project-settings.codec.js.map +1 -0
  103. package/dist/server/modules/projects/template-codec/codecs/prompts.codec.d.ts +31 -0
  104. package/dist/server/modules/projects/template-codec/codecs/prompts.codec.js +53 -0
  105. package/dist/server/modules/projects/template-codec/codecs/prompts.codec.js.map +1 -0
  106. package/dist/server/modules/projects/template-codec/codecs/provider-efforts.codec.d.ts +23 -0
  107. package/dist/server/modules/projects/template-codec/codecs/provider-efforts.codec.js +73 -0
  108. package/dist/server/modules/projects/template-codec/codecs/provider-efforts.codec.js.map +1 -0
  109. package/dist/server/modules/projects/template-codec/codecs/provider-models.codec.d.ts +23 -0
  110. package/dist/server/modules/projects/template-codec/codecs/provider-models.codec.js +73 -0
  111. package/dist/server/modules/projects/template-codec/codecs/provider-models.codec.js.map +1 -0
  112. package/dist/server/modules/projects/template-codec/codecs/provider-settings.codec.d.ts +36 -0
  113. package/dist/server/modules/projects/template-codec/codecs/provider-settings.codec.js +138 -0
  114. package/dist/server/modules/projects/template-codec/codecs/provider-settings.codec.js.map +1 -0
  115. package/dist/server/modules/projects/template-codec/codecs/scheduled-epics.codec.d.ts +46 -0
  116. package/dist/server/modules/projects/template-codec/codecs/scheduled-epics.codec.js +120 -0
  117. package/dist/server/modules/projects/template-codec/codecs/scheduled-epics.codec.js.map +1 -0
  118. package/dist/server/modules/projects/template-codec/codecs/statuses.codec.d.ts +32 -0
  119. package/dist/server/modules/projects/template-codec/codecs/statuses.codec.js +101 -0
  120. package/dist/server/modules/projects/template-codec/codecs/statuses.codec.js.map +1 -0
  121. package/dist/server/modules/projects/template-codec/codecs/subscribers.codec.d.ts +65 -0
  122. package/dist/server/modules/projects/template-codec/codecs/subscribers.codec.js +47 -0
  123. package/dist/server/modules/projects/template-codec/codecs/subscribers.codec.js.map +1 -0
  124. package/dist/server/modules/projects/template-codec/codecs/teams.codec.d.ts +83 -0
  125. package/dist/server/modules/projects/template-codec/codecs/teams.codec.js +297 -0
  126. package/dist/server/modules/projects/template-codec/codecs/teams.codec.js.map +1 -0
  127. package/dist/server/modules/projects/template-codec/codecs/watchers.codec.d.ts +62 -0
  128. package/dist/server/modules/projects/template-codec/codecs/watchers.codec.js +78 -0
  129. package/dist/server/modules/projects/template-codec/codecs/watchers.codec.js.map +1 -0
  130. package/dist/server/modules/projects/template-codec/import-context.d.ts +38 -0
  131. package/dist/server/modules/projects/template-codec/import-context.js +49 -0
  132. package/dist/server/modules/projects/template-codec/import-context.js.map +1 -0
  133. package/dist/server/modules/projects/template-codec/template-pipeline.d.ts +17 -0
  134. package/dist/server/modules/projects/template-codec/template-pipeline.js +159 -0
  135. package/dist/server/modules/projects/template-codec/template-pipeline.js.map +1 -0
  136. package/dist/server/modules/projects/template-codec/template-section-codec.d.ts +93 -0
  137. package/dist/server/modules/projects/template-codec/template-section-codec.js +3 -0
  138. package/dist/server/modules/projects/template-codec/template-section-codec.js.map +1 -0
  139. package/dist/server/modules/providers/adapters/capabilities/effort.capability.d.ts +8 -0
  140. package/dist/server/modules/providers/adapters/capabilities/effort.capability.js +3 -0
  141. package/dist/server/modules/providers/adapters/capabilities/effort.capability.js.map +1 -0
  142. package/dist/server/modules/providers/adapters/capabilities/index.d.ts +2 -2
  143. package/dist/server/modules/providers/adapters/capabilities/index.js +2 -1
  144. package/dist/server/modules/providers/adapters/capabilities/index.js.map +1 -1
  145. package/dist/server/modules/providers/adapters/capabilities/type-guards.d.ts +3 -0
  146. package/dist/server/modules/providers/adapters/capabilities/type-guards.js +4 -0
  147. package/dist/server/modules/providers/adapters/capabilities/type-guards.js.map +1 -1
  148. package/dist/server/modules/providers/adapters/claude.adapter.d.ts +7 -2
  149. package/dist/server/modules/providers/adapters/claude.adapter.js +5 -0
  150. package/dist/server/modules/providers/adapters/claude.adapter.js.map +1 -1
  151. package/dist/server/modules/providers/adapters/codex.adapter.d.ts +9 -2
  152. package/dist/server/modules/providers/adapters/codex.adapter.js +26 -0
  153. package/dist/server/modules/providers/adapters/codex.adapter.js.map +1 -1
  154. package/dist/server/modules/providers/adapters/copilot.adapter.d.ts +7 -2
  155. package/dist/server/modules/providers/adapters/copilot.adapter.js +7 -0
  156. package/dist/server/modules/providers/adapters/copilot.adapter.js.map +1 -1
  157. package/dist/server/modules/providers/adapters/opencode.adapter.d.ts +8 -1
  158. package/dist/server/modules/providers/adapters/opencode.adapter.js +54 -0
  159. package/dist/server/modules/providers/adapters/opencode.adapter.js.map +1 -1
  160. package/dist/server/modules/providers/controllers/provider-efforts.controller.d.ts +20 -0
  161. package/dist/server/modules/providers/controllers/provider-efforts.controller.js +128 -0
  162. package/dist/server/modules/providers/controllers/provider-efforts.controller.js.map +1 -0
  163. package/dist/server/modules/providers/controllers/providers.controller.d.ts +3 -1
  164. package/dist/server/modules/providers/controllers/providers.controller.js +11 -2
  165. package/dist/server/modules/providers/controllers/providers.controller.js.map +1 -1
  166. package/dist/server/modules/providers/providers.module.js +4 -1
  167. package/dist/server/modules/providers/providers.module.js.map +1 -1
  168. package/dist/server/modules/providers/services/provider-effort-seeding.module.d.ts +2 -0
  169. package/dist/server/modules/providers/services/provider-effort-seeding.module.js +24 -0
  170. package/dist/server/modules/providers/services/provider-effort-seeding.module.js.map +1 -0
  171. package/dist/server/modules/providers/services/provider-effort-seeding.service.d.ts +19 -0
  172. package/dist/server/modules/providers/services/provider-effort-seeding.service.js +64 -0
  173. package/dist/server/modules/providers/services/provider-effort-seeding.service.js.map +1 -0
  174. package/dist/server/modules/providers/services/provider-project-sync.service.js +34 -3
  175. package/dist/server/modules/providers/services/provider-project-sync.service.js.map +1 -1
  176. package/dist/server/modules/providers/services/provider-state-manager.service.d.ts +4 -1
  177. package/dist/server/modules/providers/services/provider-state-manager.service.js +14 -2
  178. package/dist/server/modules/providers/services/provider-state-manager.service.js.map +1 -1
  179. package/dist/server/modules/registry/controllers/templates.controller.d.ts +10 -1
  180. package/dist/server/modules/seeders/seeders/0010_seed_provider_effort_defaults.d.ts +3 -0
  181. package/dist/server/modules/seeders/seeders/0010_seed_provider_effort_defaults.js +21 -0
  182. package/dist/server/modules/seeders/seeders/0010_seed_provider_effort_defaults.js.map +1 -0
  183. package/dist/server/modules/seeders/seeders.module.js +2 -1
  184. package/dist/server/modules/seeders/seeders.module.js.map +1 -1
  185. package/dist/server/modules/seeders/services/data-seeder.service.d.ts +3 -1
  186. package/dist/server/modules/seeders/services/data-seeder.service.js +10 -4
  187. package/dist/server/modules/seeders/services/data-seeder.service.js.map +1 -1
  188. package/dist/server/modules/seeders/types/seeder.types.d.ts +2 -0
  189. package/dist/server/modules/session-reader/adapters/codex-session-reader.adapter.d.ts +3 -2
  190. package/dist/server/modules/session-reader/adapters/codex-session-reader.adapter.js +22 -14
  191. package/dist/server/modules/session-reader/adapters/codex-session-reader.adapter.js.map +1 -1
  192. package/dist/server/modules/session-reader/adapters/session-reader-adapter.interface.d.ts +7 -0
  193. package/dist/server/modules/session-reader/data/pricing.json +40 -40
  194. package/dist/server/modules/session-reader/services/transcript-persistence.listener.d.ts +1 -0
  195. package/dist/server/modules/session-reader/services/transcript-persistence.listener.js +41 -33
  196. package/dist/server/modules/session-reader/services/transcript-persistence.listener.js.map +1 -1
  197. package/dist/server/modules/sessions/services/message-enqueue.service.d.ts +1 -0
  198. package/dist/server/modules/sessions/services/message-enqueue.service.js +1 -0
  199. package/dist/server/modules/sessions/services/message-enqueue.service.js.map +1 -1
  200. package/dist/server/modules/sessions/services/message-log.service.d.ts +3 -0
  201. package/dist/server/modules/sessions/services/message-log.service.js +35 -3
  202. package/dist/server/modules/sessions/services/message-log.service.js.map +1 -1
  203. package/dist/server/modules/sessions/services/message-pool.types.d.ts +4 -0
  204. package/dist/server/modules/sessions/services/provider-launch-config/provider-launch-config.service.d.ts +1 -0
  205. package/dist/server/modules/sessions/services/provider-launch-config/provider-launch-config.service.js +6 -0
  206. package/dist/server/modules/sessions/services/provider-launch-config/provider-launch-config.service.js.map +1 -1
  207. package/dist/server/modules/sessions/services/session-runtime/__test-utils__/pipeline-harness.d.ts +7 -0
  208. package/dist/server/modules/sessions/services/session-runtime/__test-utils__/pipeline-harness.js +7 -0
  209. package/dist/server/modules/sessions/services/session-runtime/__test-utils__/pipeline-harness.js.map +1 -1
  210. package/dist/server/modules/sessions/services/session-runtime/session-launch-pipeline.service.js +9 -1
  211. package/dist/server/modules/sessions/services/session-runtime/session-launch-pipeline.service.js.map +1 -1
  212. package/dist/server/modules/sessions/services/session-runtime/session-restore-pipeline.service.js +14 -1
  213. package/dist/server/modules/sessions/services/session-runtime/session-restore-pipeline.service.js.map +1 -1
  214. package/dist/server/modules/sessions/services/sessions-message-log-read.facade.d.ts +16 -0
  215. package/dist/server/modules/sessions/services/sessions-message-log-read.facade.js +40 -0
  216. package/dist/server/modules/sessions/services/sessions-message-log-read.facade.js.map +1 -0
  217. package/dist/server/modules/sessions/services/sessions-message-pool.service.js +21 -4
  218. package/dist/server/modules/sessions/services/sessions-message-pool.service.js.map +1 -1
  219. package/dist/server/modules/sessions/services/sessions.service.js +4 -0
  220. package/dist/server/modules/sessions/services/sessions.service.js.map +1 -1
  221. package/dist/server/modules/sessions/sessions-message-log-read.module.d.ts +2 -0
  222. package/dist/server/modules/sessions/sessions-message-log-read.module.js +23 -0
  223. package/dist/server/modules/sessions/sessions-message-log-read.module.js.map +1 -0
  224. package/dist/server/modules/sessions/utils/profile-options.d.ts +1 -0
  225. package/dist/server/modules/sessions/utils/profile-options.js +18 -0
  226. package/dist/server/modules/sessions/utils/profile-options.js.map +1 -1
  227. package/dist/server/modules/settings/dtos/settings.dto.d.ts +15 -0
  228. package/dist/server/modules/settings/dtos/settings.dto.js +1 -0
  229. package/dist/server/modules/settings/dtos/settings.dto.js.map +1 -1
  230. package/dist/server/modules/storage/db/schema.d.ts +176 -0
  231. package/dist/server/modules/storage/db/schema.js +18 -2
  232. package/dist/server/modules/storage/db/schema.js.map +1 -1
  233. package/dist/server/modules/storage/interfaces/storage.interface.d.ts +13 -62
  234. package/dist/server/modules/storage/interfaces/storage.interface.js.map +1 -1
  235. package/dist/server/modules/storage/local/delegates/agent.delegate.js +3 -0
  236. package/dist/server/modules/storage/local/delegates/agent.delegate.js.map +1 -1
  237. package/dist/server/modules/storage/local/delegates/profile-provider-config.delegate.d.ts +2 -0
  238. package/dist/server/modules/storage/local/delegates/profile-provider-config.delegate.js +24 -0
  239. package/dist/server/modules/storage/local/delegates/profile-provider-config.delegate.js.map +1 -1
  240. package/dist/server/modules/storage/local/delegates/project.delegate.d.ts +3 -2
  241. package/dist/server/modules/storage/local/delegates/project.delegate.js +25 -198
  242. package/dist/server/modules/storage/local/delegates/project.delegate.js.map +1 -1
  243. package/dist/server/modules/storage/local/delegates/provider-effort.delegate.d.ts +15 -0
  244. package/dist/server/modules/storage/local/delegates/provider-effort.delegate.js +200 -0
  245. package/dist/server/modules/storage/local/delegates/provider-effort.delegate.js.map +1 -0
  246. package/dist/server/modules/storage/local/local-storage.service.d.ts +12 -2
  247. package/dist/server/modules/storage/local/local-storage.service.js +22 -2
  248. package/dist/server/modules/storage/local/local-storage.service.js.map +1 -1
  249. package/dist/server/modules/storage/models/domain.models.d.ts +18 -1
  250. package/dist/server/modules/teams/services/teams.service.d.ts +0 -5
  251. package/dist/server/modules/teams/services/teams.service.js +22 -131
  252. package/dist/server/modules/teams/services/teams.service.js.map +1 -1
  253. package/dist/server/modules/teams/services/teams.validators.d.ts +14 -0
  254. package/dist/server/modules/teams/services/teams.validators.js +94 -0
  255. package/dist/server/modules/teams/services/teams.validators.js.map +1 -0
  256. package/dist/server/modules/terminal/gateways/terminal.gateway.d.ts +1 -0
  257. package/dist/server/modules/terminal/gateways/terminal.gateway.js +39 -10
  258. package/dist/server/modules/terminal/gateways/terminal.gateway.js.map +1 -1
  259. package/dist/server/modules/terminal/services/terminal-key-input/terminal-key-input.facade.d.ts +10 -0
  260. package/dist/server/modules/terminal/services/terminal-key-input/terminal-key-input.facade.js +73 -0
  261. package/dist/server/modules/terminal/services/terminal-key-input/terminal-key-input.facade.js.map +1 -0
  262. package/dist/server/modules/terminal/services/terminal-registry-rehydrator.service.js +1 -0
  263. package/dist/server/modules/terminal/services/terminal-registry-rehydrator.service.js.map +1 -1
  264. package/dist/server/modules/terminal/services/terminal-session/terminal-session.d.ts +2 -0
  265. package/dist/server/modules/terminal/services/terminal-session/terminal-session.js +15 -0
  266. package/dist/server/modules/terminal/services/terminal-session/terminal-session.js.map +1 -1
  267. package/dist/server/modules/terminal/terminal-key-input.module.d.ts +2 -0
  268. package/dist/server/modules/terminal/terminal-key-input.module.js +23 -0
  269. package/dist/server/modules/terminal/terminal-key-input.module.js.map +1 -0
  270. package/dist/server/modules/watchers/services/watcher-runner.service.d.ts +2 -16
  271. package/dist/server/modules/watchers/services/watcher-runner.service.js +11 -125
  272. package/dist/server/modules/watchers/services/watcher-runner.service.js.map +1 -1
  273. package/dist/server/modules/watchers/services/watcher-trigger-state.d.ts +23 -0
  274. package/dist/server/modules/watchers/services/watcher-trigger-state.js +136 -0
  275. package/dist/server/modules/watchers/services/watcher-trigger-state.js.map +1 -0
  276. package/dist/server/templates/3-agents-dev.json +144 -85
  277. package/dist/server/templates/teams-dev.json +305 -208
  278. package/dist/server/tsconfig.tsbuildinfo +1 -1
  279. package/dist/server/ui/assets/{ReviewDetailPage-BDisSE9l.js → ReviewDetailPage-Dd40lXMW.js} +1 -1
  280. package/dist/server/ui/assets/{ReviewsPage-3puoJiOQ.js → ReviewsPage-CBSbsimJ.js} +1 -1
  281. package/dist/server/ui/assets/index-COvyD_66.css +32 -0
  282. package/dist/server/ui/assets/index-DtIjl-Lt.js +1113 -0
  283. package/dist/server/ui/assets/{useReviewSubscription-wTrdkdi0.js → useReviewSubscription-CpDyx3vJ.js} +1 -1
  284. package/dist/server/ui/index.html +2 -2
  285. package/dist/templates/3-agents-dev.json +144 -85
  286. package/dist/templates/teams-dev.json +305 -208
  287. package/package.json +8 -1
  288. package/dist/server/ui/assets/index-CzMrWNAV.css +0 -32
  289. package/dist/server/ui/assets/index-zlQ1ekQ2.js +0 -1103
@@ -16,15 +16,15 @@ exports.WorktreesService = void 0;
16
16
  const common_1 = require("@nestjs/common");
17
17
  const event_emitter_1 = require("@nestjs/event-emitter");
18
18
  const crypto_1 = require("crypto");
19
- const fs_1 = require("fs");
20
19
  const logger_1 = require("../../../../common/logging/logger");
21
20
  const env_config_1 = require("../../../../common/config/env.config");
22
21
  const event_log_service_1 = require("../../../events/services/event-log.service");
23
22
  const worktree_dto_1 = require("../dtos/worktree.dto");
24
23
  const worktrees_store_1 = require("../worktrees.store");
25
24
  const git_worktree_service_1 = require("../../git/services/git-worktree.service");
26
- const docker_service_1 = require("../../docker/services/docker.service");
27
25
  const seed_preparation_service_1 = require("../../docker/services/seed-preparation.service");
26
+ const container_runtime_1 = require("../runtime/container-runtime");
27
+ const process_runtime_1 = require("../runtime/process-runtime");
28
28
  const task_merge_events_1 = require("../../sync/events/task-merge.events");
29
29
  const worktree_events_1 = require("../events/worktree.events");
30
30
  const promises_1 = require("fs/promises");
@@ -33,33 +33,26 @@ const worktree_validation_1 = require("../worktree-validation");
33
33
  const storage_interface_1 = require("../../../storage/interfaces/storage.interface");
34
34
  const error_types_1 = require("../../../../common/errors/error-types");
35
35
  const path_validation_1 = require("../../../../common/validation/path-validation");
36
- const process_executor_port_1 = require("../../../terminal/services/process-executor/process-executor.port");
37
36
  const logger = (0, logger_1.createLogger)('OrchestratorWorktreesService');
38
37
  const CONTAINER_HEALTH_TIMEOUT_MS = 60_000;
39
38
  const HEALTH_MONITOR_INTERVAL_MS = 15_000;
40
39
  const HEALTH_MONITOR_PROBE_TIMEOUT_MS = 1_500;
41
40
  const MAX_CONSECUTIVE_HEALTH_FAILURES = 3;
42
41
  const OVERVIEW_FETCH_TIMEOUT_MS = 2_500;
43
- const PROCESS_SHUTDOWN_TIMEOUT_MS = 30_000;
44
- const PROCESS_KILL_TIMEOUT_MS = 5_000;
45
- const PROCESS_LOG_FILE_NAME = 'devchain.log';
46
- const PROCESS_DB_FILE_NAME = 'devchain.db';
47
- const PROCESS_RUNTIME_PORT_FILE = 'runtime-port.json';
48
- const PROCESS_HEALTH_POLL_INTERVAL_MS = 1_000;
49
- const PROCESS_RUNTIME_TIMEOUT_MS = 1_500;
50
42
  const WORKTREE_ACTIVITY_EVENT_NAME = 'orchestrator.worktree.activity';
51
43
  const WORKTREE_STATUS_VALUES = worktree_dto_1.WorktreeStatusSchema.options;
52
44
  let WorktreesService = class WorktreesService {
53
- constructor(store, dockerService, gitService, seedPreparationService, eventEmitter, eventLogService, storage, executor) {
45
+ constructor(store, containerRuntime, processRuntime, gitService, seedPreparationService, eventEmitter, eventLogService, storage) {
54
46
  this.store = store;
55
- this.dockerService = dockerService;
47
+ this.containerRuntime = containerRuntime;
48
+ this.processRuntime = processRuntime;
56
49
  this.gitService = gitService;
57
50
  this.seedPreparationService = seedPreparationService;
58
51
  this.eventEmitter = eventEmitter;
59
52
  this.eventLogService = eventLogService;
60
53
  this.storage = storage;
61
- this.executor = executor;
62
54
  this.consecutiveHealthFailures = new Map();
55
+ this.inFlightOperations = new Map();
63
56
  }
64
57
  async onModuleInit() {
65
58
  this.monitorTimer = setInterval(() => {
@@ -71,7 +64,7 @@ let WorktreesService = class WorktreesService {
71
64
  logger.warn({ error }, 'Failed process-runtime orphan detection on startup');
72
65
  });
73
66
  try {
74
- this.unsubscribeDockerEvents = await this.dockerService.subscribeToContainerEvents((event) => {
67
+ this.unsubscribeDockerEvents = await this.containerRuntime.subscribeToContainerEvents((event) => {
75
68
  this.handleContainerEvent(event).catch((error) => {
76
69
  logger.error({ error, event }, 'Failed handling docker container event');
77
70
  });
@@ -166,7 +159,7 @@ let WorktreesService = class WorktreesService {
166
159
  await (0, promises_1.mkdir)(dataPath, { recursive: true });
167
160
  await this.seedPreparationService.prepareSeedData(dataPath);
168
161
  if (runtimeType === 'process') {
169
- const runtime = await this.startProcessRuntime({
162
+ const runtime = await this.processRuntime.startProcessRuntime({
170
163
  worktreePath,
171
164
  dataPath,
172
165
  projectId,
@@ -192,7 +185,7 @@ let WorktreesService = class WorktreesService {
192
185
  }));
193
186
  }
194
187
  else {
195
- const container = await this.dockerService.createContainer({
188
+ const container = await this.containerRuntime.createContainer({
196
189
  name: containerName,
197
190
  worktreePath,
198
191
  dataPath,
@@ -205,10 +198,10 @@ let WorktreesService = class WorktreesService {
205
198
  },
206
199
  });
207
200
  containerId = container.id;
208
- await this.dockerService
201
+ await this.containerRuntime
209
202
  .ensureWorktreeOnComposeNetwork(input.name, container.id)
210
203
  .catch(() => undefined);
211
- const healthy = await this.dockerService.waitForHealthy(container.id, CONTAINER_HEALTH_TIMEOUT_MS);
204
+ const healthy = await this.containerRuntime.waitForHealthy(container.id, CONTAINER_HEALTH_TIMEOUT_MS);
212
205
  if (!healthy) {
213
206
  throw new Error('Container did not become healthy before timeout');
214
207
  }
@@ -251,10 +244,10 @@ let WorktreesService = class WorktreesService {
251
244
  errorMessage,
252
245
  });
253
246
  if (containerId) {
254
- await this.dockerService.removeContainer(containerId, true).catch(() => undefined);
247
+ await this.containerRuntime.removeContainer(containerId, true).catch(() => undefined);
255
248
  }
256
249
  if (processId) {
257
- await this.terminateProcess(processId).catch(() => undefined);
250
+ await this.processRuntime.terminateProcess(processId).catch(() => undefined);
258
251
  }
259
252
  if (gitWorktreeCreated) {
260
253
  await this.gitService.removeWorktree(worktreePath, repoPath, true).catch(() => undefined);
@@ -268,14 +261,9 @@ let WorktreesService = class WorktreesService {
268
261
  }, 'Failed to clean up branch after create-worktree error'));
269
262
  }
270
263
  }
271
- const logPath = this.resolveProcessLogPath(dataPath);
272
- try {
273
- const logContent = await (0, promises_1.readFile)(logPath, 'utf-8');
274
- if (logContent.trim()) {
275
- logger.error({ worktreeId: created.id, logContent: logContent.slice(-2000) }, 'Process runtime log before cleanup');
276
- }
277
- }
278
- catch {
264
+ const crashLog = await this.processRuntime.readRecentLog(dataPath);
265
+ if (crashLog) {
266
+ logger.error({ worktreeId: created.id, logContent: crashLog }, 'Process runtime log before cleanup');
279
267
  }
280
268
  await (0, promises_1.rm)(dataPath, { recursive: true, force: true }).catch(() => undefined);
281
269
  throw new common_1.BadRequestException(`Failed to create worktree: ${errorMessage}`);
@@ -307,6 +295,9 @@ let WorktreesService = class WorktreesService {
307
295
  return this.buildWorktreeOverview(row);
308
296
  }
309
297
  async deleteWorktree(id, options = {}) {
298
+ return this.withOperationGuard(id, 'delete', () => this.executeDelete(id, options));
299
+ }
300
+ async executeDelete(id, options) {
310
301
  const row = await this.requireWorktree(id);
311
302
  const runtimeType = this.resolveRuntimeType(row.runtimeType);
312
303
  const shouldDeleteBranch = options.deleteBranch ?? true;
@@ -317,19 +308,21 @@ let WorktreesService = class WorktreesService {
317
308
  : null;
318
309
  const dataPath = this.resolveDataPath(repoPath, row.name);
319
310
  if (runtimeType === 'container' || row.containerId) {
320
- await this.dockerService
311
+ await this.containerRuntime
321
312
  .cleanupWorktreeProjectContainers(row.name, row.containerId)
322
313
  .catch((error) => logger.warn({ error, worktreeId: row.id }, 'Failed cleaning project sub-containers'));
323
314
  if (row.containerId) {
324
- await this.dockerService.stopContainer(row.containerId).catch(() => undefined);
325
- await this.dockerService.removeContainer(row.containerId, true).catch(() => undefined);
315
+ await this.containerRuntime.stopContainer(row.containerId).catch(() => undefined);
316
+ await this.containerRuntime.removeContainer(row.containerId, true).catch(() => undefined);
326
317
  }
327
- await this.dockerService
318
+ await this.containerRuntime
328
319
  .removeWorktreeNetwork(row.name)
329
320
  .catch((error) => logger.warn({ error, worktreeId: row.id }, 'Failed removing worktree docker network'));
330
321
  }
331
322
  else {
332
- await this.terminateProcess(row.processId).catch((error) => logger.warn({ error, worktreeId: row.id }, 'Failed stopping worktree process during delete'));
323
+ await this.processRuntime
324
+ .terminateProcess(row.processId)
325
+ .catch((error) => logger.warn({ error, worktreeId: row.id }, 'Failed stopping worktree process during delete'));
333
326
  }
334
327
  if (worktreePath) {
335
328
  await this.gitService.removeWorktree(worktreePath, repoPath, true).catch(() => undefined);
@@ -357,6 +350,9 @@ let WorktreesService = class WorktreesService {
357
350
  return { success: true };
358
351
  }
359
352
  async startWorktree(id) {
353
+ return this.withOperationGuard(id, 'start', () => this.executeStart(id));
354
+ }
355
+ async executeStart(id) {
360
356
  const row = await this.requireWorktree(id);
361
357
  const runtimeType = this.resolveRuntimeType(row.runtimeType);
362
358
  if (runtimeType === 'process') {
@@ -369,7 +365,7 @@ let WorktreesService = class WorktreesService {
369
365
  const dataPath = this.resolveDataPath(repoPath, row.name);
370
366
  await (0, promises_1.mkdir)(dataPath, { recursive: true });
371
367
  try {
372
- const runtime = await this.startProcessRuntime({
368
+ const runtime = await this.processRuntime.startProcessRuntime({
373
369
  worktreePath,
374
370
  dataPath,
375
371
  projectId,
@@ -394,18 +390,18 @@ let WorktreesService = class WorktreesService {
394
390
  if (!row.containerId) {
395
391
  throw new common_1.BadRequestException('Worktree has no container to start');
396
392
  }
397
- await this.dockerService.startContainer(row.containerId);
398
- const healthy = await this.dockerService.waitForHealthy(row.containerId, CONTAINER_HEALTH_TIMEOUT_MS);
393
+ await this.containerRuntime.startContainer(row.containerId);
394
+ const healthy = await this.containerRuntime.waitForHealthy(row.containerId, CONTAINER_HEALTH_TIMEOUT_MS);
399
395
  if (!healthy) {
400
396
  await this.tryUpdateStatus(row.id, 'error', {
401
397
  errorMessage: 'Container failed readiness check after start',
402
398
  });
403
399
  throw new common_1.BadRequestException('Container started but failed readiness check');
404
400
  }
405
- await this.dockerService
401
+ await this.containerRuntime
406
402
  .ensureWorktreeOnComposeNetwork(row.name, row.containerId)
407
403
  .catch(() => undefined);
408
- const hostPort = await this.dockerService
404
+ const hostPort = await this.containerRuntime
409
405
  .getContainerHostPort(row.containerId)
410
406
  .catch(() => null);
411
407
  const updated = await this.tryUpdateStatus(row.id, 'running', {
@@ -415,10 +411,13 @@ let WorktreesService = class WorktreesService {
415
411
  return this.toResponse(updated ?? row);
416
412
  }
417
413
  async stopWorktree(id) {
414
+ return this.withOperationGuard(id, 'stop', () => this.executeStop(id));
415
+ }
416
+ async executeStop(id) {
418
417
  const row = await this.requireWorktree(id);
419
418
  const runtimeType = this.resolveRuntimeType(row.runtimeType);
420
419
  if (runtimeType === 'process') {
421
- await this.terminateProcess(row.processId);
420
+ await this.processRuntime.terminateProcess(row.processId);
422
421
  this.consecutiveHealthFailures.set(row.id, 0);
423
422
  const updated = await this.tryUpdateStatus(row.id, 'stopped', {
424
423
  processId: null,
@@ -432,7 +431,7 @@ let WorktreesService = class WorktreesService {
432
431
  if (!row.containerId) {
433
432
  throw new common_1.BadRequestException('Worktree has no container to stop');
434
433
  }
435
- await this.dockerService.stopContainer(row.containerId);
434
+ await this.containerRuntime.stopContainer(row.containerId);
436
435
  this.consecutiveHealthFailures.set(row.id, 0);
437
436
  const updated = await this.tryUpdateStatus(row.id, 'stopped');
438
437
  return this.toResponse(updated ?? row);
@@ -465,6 +464,9 @@ let WorktreesService = class WorktreesService {
465
464
  };
466
465
  }
467
466
  async mergeWorktree(id) {
467
+ return this.withOperationGuard(id, 'merge', () => this.executeMerge(id));
468
+ }
469
+ async executeMerge(id) {
468
470
  const row = await this.requireWorktree(id);
469
471
  const currentStatus = String(row.status).toLowerCase();
470
472
  if (currentStatus === 'merged') {
@@ -477,7 +479,7 @@ let WorktreesService = class WorktreesService {
477
479
  const extractionRow = currentStatus === 'running' ? row : await this.ensureContainerReadyForTaskExtraction(row);
478
480
  await this.extractTasksForMergedHistory(extractionRow);
479
481
  if (row.containerId) {
480
- await this.dockerService.stopContainer(row.containerId).catch(() => undefined);
482
+ await this.containerRuntime.stopContainer(row.containerId).catch(() => undefined);
481
483
  }
482
484
  const mergeResult = await this.gitService.executeMerge(row.repoPath, row.branchName, row.baseBranch, {
483
485
  message: this.buildMergeCommitMessage(row),
@@ -511,6 +513,9 @@ let WorktreesService = class WorktreesService {
511
513
  return this.toResponse(updated ?? row);
512
514
  }
513
515
  async rebaseWorktree(id) {
516
+ return this.withOperationGuard(id, 'rebase', () => this.executeRebase(id));
517
+ }
518
+ async executeRebase(id) {
514
519
  const row = await this.requireWorktree(id);
515
520
  const currentStatus = String(row.status).toLowerCase();
516
521
  if (currentStatus === 'merged') {
@@ -521,7 +526,7 @@ let WorktreesService = class WorktreesService {
521
526
  }
522
527
  await this.assertCleanWorkingTree(row.worktreePath ?? row.repoPath, 'Rebase');
523
528
  if (row.containerId) {
524
- await this.dockerService.stopContainer(row.containerId).catch(() => undefined);
529
+ await this.containerRuntime.stopContainer(row.containerId).catch(() => undefined);
525
530
  }
526
531
  const rebaseResult = await this.gitService.executeRebase(row.worktreePath ?? row.repoPath, row.branchName, row.baseBranch);
527
532
  if (!rebaseResult.success) {
@@ -544,8 +549,8 @@ let WorktreesService = class WorktreesService {
544
549
  throw new common_1.BadRequestException(`Rebase failed: ${message}`);
545
550
  }
546
551
  if (row.containerId) {
547
- await this.dockerService.startContainer(row.containerId).catch(() => undefined);
548
- const healthy = await this.dockerService.waitForHealthy(row.containerId, CONTAINER_HEALTH_TIMEOUT_MS);
552
+ await this.containerRuntime.startContainer(row.containerId).catch(() => undefined);
553
+ const healthy = await this.containerRuntime.waitForHealthy(row.containerId, CONTAINER_HEALTH_TIMEOUT_MS);
549
554
  if (!healthy) {
550
555
  await this.tryUpdateStatus(row.id, 'error', {
551
556
  errorMessage: 'Container failed readiness check after rebase',
@@ -631,8 +636,8 @@ let WorktreesService = class WorktreesService {
631
636
  return false;
632
637
  }
633
638
  try {
634
- await this.dockerService.startContainer(row.containerId).catch(() => undefined);
635
- const healthy = await this.dockerService.waitForHealthy(row.containerId, CONTAINER_HEALTH_TIMEOUT_MS);
639
+ await this.containerRuntime.startContainer(row.containerId).catch(() => undefined);
640
+ const healthy = await this.containerRuntime.waitForHealthy(row.containerId, CONTAINER_HEALTH_TIMEOUT_MS);
636
641
  if (!healthy) {
637
642
  return false;
638
643
  }
@@ -690,26 +695,13 @@ let WorktreesService = class WorktreesService {
690
695
  async getWorktreeLogs(id, query) {
691
696
  const row = await this.requireWorktree(id);
692
697
  if (this.resolveRuntimeType(row.runtimeType) === 'process') {
693
- const logPath = this.resolveProcessLogPath(this.resolveDataPath(row.repoPath, row.name));
694
- const content = await (0, promises_1.readFile)(logPath, 'utf8').catch((error) => {
695
- if (error?.code === 'ENOENT') {
696
- return '';
697
- }
698
- throw error;
699
- });
700
- const lines = content.split(/\r?\n/).filter((line, index, all) => {
701
- if (line.length > 0) {
702
- return true;
703
- }
704
- return index < all.length - 1;
705
- });
706
- const tailed = lines.slice(-query.tail).join('\n');
707
- return { logs: tailed ? `${tailed}\n` : '' };
698
+ const dataPath = this.resolveDataPath(row.repoPath, row.name);
699
+ return { logs: await this.processRuntime.readLogs(dataPath, query.tail) };
708
700
  }
709
701
  if (!row.containerId) {
710
702
  throw new common_1.BadRequestException('Worktree has no container');
711
703
  }
712
- const logs = await this.dockerService.getContainerLogs(row.containerId, query.tail);
704
+ const logs = await this.containerRuntime.getContainerLogs(row.containerId, query.tail);
713
705
  return { logs };
714
706
  }
715
707
  async buildWorktreeOverview(row) {
@@ -794,10 +786,10 @@ let WorktreesService = class WorktreesService {
794
786
  if (!row.containerId) {
795
787
  return;
796
788
  }
797
- await this.dockerService
789
+ await this.containerRuntime
798
790
  .ensureWorktreeOnComposeNetwork(row.name, row.containerId)
799
791
  .catch(() => undefined);
800
- const healthy = await this.dockerService.waitForHealthy(row.containerId, HEALTH_MONITOR_PROBE_TIMEOUT_MS);
792
+ const healthy = await this.containerRuntime.waitForHealthy(row.containerId, HEALTH_MONITOR_PROBE_TIMEOUT_MS);
801
793
  if (healthy) {
802
794
  this.consecutiveHealthFailures.set(row.id, 0);
803
795
  if (row.status === 'error') {
@@ -817,8 +809,12 @@ let WorktreesService = class WorktreesService {
817
809
  }));
818
810
  }
819
811
  async monitorProcessWorktree(row) {
820
- const pid = row.processId ?? null;
821
- if (!pid || !this.isProcessAlive(pid)) {
812
+ const verdict = await this.processRuntime.probeHealth({
813
+ pid: row.processId ?? null,
814
+ hostPort: row.containerPort ?? null,
815
+ runtimeToken: row.runtimeToken?.trim() || null,
816
+ });
817
+ if (verdict === 'dead' || verdict === 'token-mismatch') {
822
818
  this.consecutiveHealthFailures.set(row.id, 0);
823
819
  await this.tryUpdateStatus(row.id, 'stopped', {
824
820
  processId: null,
@@ -829,30 +825,10 @@ let WorktreesService = class WorktreesService {
829
825
  });
830
826
  return;
831
827
  }
832
- const hostPort = row.containerPort ?? null;
833
- const runtimeToken = row.runtimeToken?.trim() || null;
834
- if (!hostPort || !runtimeToken) {
828
+ if (verdict === 'unreachable') {
835
829
  await this.handleProcessProbeFailure(row.id, row.status);
836
830
  return;
837
831
  }
838
- const healthy = await this.checkRuntimeReady(hostPort);
839
- if (!healthy) {
840
- await this.handleProcessProbeFailure(row.id, row.status);
841
- return;
842
- }
843
- const runtimeMetadata = await this.fetchRuntimeMetadata(hostPort);
844
- const runtimeTokenMatches = runtimeMetadata?.runtimeToken === runtimeToken;
845
- if (!runtimeTokenMatches) {
846
- this.consecutiveHealthFailures.set(row.id, 0);
847
- await this.tryUpdateStatus(row.id, 'stopped', {
848
- processId: null,
849
- runtimeToken: null,
850
- startedAt: null,
851
- containerPort: null,
852
- errorMessage: null,
853
- });
854
- return;
855
- }
856
832
  this.consecutiveHealthFailures.set(row.id, 0);
857
833
  if (row.status === 'error') {
858
834
  await this.tryUpdateStatus(row.id, 'running', {
@@ -874,7 +850,7 @@ let WorktreesService = class WorktreesService {
874
850
  const candidates = rows.filter((row) => this.resolveRuntimeType(row.runtimeType) === 'process' && row.status === 'running');
875
851
  await Promise.all(candidates.map(async (row) => {
876
852
  const pid = row.processId ?? null;
877
- if (!pid || !this.isProcessAlive(pid)) {
853
+ if (!pid || !this.processRuntime.isProcessAlive(pid)) {
878
854
  await this.tryUpdateStatus(row.id, 'stopped', {
879
855
  processId: null,
880
856
  runtimeToken: null,
@@ -894,7 +870,7 @@ let WorktreesService = class WorktreesService {
894
870
  });
895
871
  return;
896
872
  }
897
- const metadata = await this.fetchRuntimeMetadata(row.containerPort);
873
+ const metadata = await this.processRuntime.fetchRuntimeMetadata(row.containerPort);
898
874
  if (!metadata || metadata.runtimeToken !== row.runtimeToken) {
899
875
  await this.tryUpdateStatus(row.id, 'stopped', {
900
876
  processId: null,
@@ -909,217 +885,6 @@ let WorktreesService = class WorktreesService {
909
885
  resolveRuntimeType(runtimeType) {
910
886
  return runtimeType === 'process' ? 'process' : 'container';
911
887
  }
912
- async startProcessRuntime(input) {
913
- const runtimeToken = (0, crypto_1.randomUUID)();
914
- const portFilePath = (0, path_1.join)(input.dataPath, PROCESS_RUNTIME_PORT_FILE);
915
- await (0, promises_1.rm)(portFilePath, { force: true }).catch(() => undefined);
916
- const processId = await this.spawnProcessRuntime({
917
- worktreePath: input.worktreePath,
918
- dataPath: input.dataPath,
919
- projectId: input.projectId,
920
- runtimeToken,
921
- });
922
- const portInfo = await this.waitForRuntimePortFile(portFilePath, CONTAINER_HEALTH_TIMEOUT_MS, processId);
923
- if (!portInfo) {
924
- await this.terminateProcess(processId).catch(() => undefined);
925
- throw new Error('Process runtime did not report its port before timeout');
926
- }
927
- if (portInfo.runtimeToken !== runtimeToken) {
928
- await this.terminateProcess(processId).catch(() => undefined);
929
- throw new Error(`Runtime port file token mismatch: expected ${runtimeToken}, ` +
930
- `got ${portInfo.runtimeToken ?? 'none'}`);
931
- }
932
- const hostPort = portInfo.port;
933
- const healthy = await this.waitForRuntimeHealthy(hostPort, CONTAINER_HEALTH_TIMEOUT_MS, processId);
934
- if (!healthy) {
935
- await this.terminateProcess(processId).catch(() => undefined);
936
- throw new Error('Process runtime did not become healthy before timeout');
937
- }
938
- return { processId, hostPort, runtimeToken, startedAt: new Date() };
939
- }
940
- async spawnProcessRuntime(input) {
941
- const cliPath = this.resolveCliPath();
942
- const logPath = this.resolveProcessLogPath(input.dataPath);
943
- const portFilePath = (0, path_1.join)(input.dataPath, PROCESS_RUNTIME_PORT_FILE);
944
- await (0, promises_1.mkdir)(input.dataPath, { recursive: true });
945
- const result = await this.executor.spawnDaemon({
946
- argv: [
947
- process.execPath,
948
- cliPath,
949
- 'start',
950
- '--foreground',
951
- '--worktree-runtime',
952
- 'process',
953
- '--port',
954
- '0',
955
- ],
956
- cwd: input.worktreePath,
957
- logPath,
958
- env: {
959
- ...process.env,
960
- PORT: '0',
961
- HOST: '127.0.0.1',
962
- NODE_ENV: 'production',
963
- DB_PATH: input.dataPath,
964
- DB_FILENAME: PROCESS_DB_FILE_NAME,
965
- DEVCHAIN_MODE: 'normal',
966
- CONTAINER_PROJECT_ID: input.projectId,
967
- RUNTIME_TOKEN: input.runtimeToken,
968
- RUNTIME_PORT_FILE: portFilePath,
969
- },
970
- });
971
- return result.pid;
972
- }
973
- async waitForRuntimeHealthy(hostPort, timeoutMs, pid) {
974
- if (timeoutMs <= 0) {
975
- return false;
976
- }
977
- const deadline = Date.now() + timeoutMs;
978
- while (Date.now() < deadline) {
979
- if (pid && !this.isProcessAlive(pid)) {
980
- logger.warn({ pid, hostPort }, 'Child process exited during health polling');
981
- return false;
982
- }
983
- const isReady = await this.checkRuntimeReady(hostPort);
984
- if (isReady) {
985
- return true;
986
- }
987
- await this.sleep(PROCESS_HEALTH_POLL_INTERVAL_MS);
988
- }
989
- return false;
990
- }
991
- async waitForRuntimePortFile(filePath, timeoutMs, pid) {
992
- if (timeoutMs <= 0) {
993
- return null;
994
- }
995
- const deadline = Date.now() + timeoutMs;
996
- while (Date.now() < deadline) {
997
- if (pid && !this.isProcessAlive(pid)) {
998
- logger.warn({ pid, filePath }, 'Child process exited before writing port file');
999
- return null;
1000
- }
1001
- try {
1002
- const raw = await (0, promises_1.readFile)(filePath, 'utf-8');
1003
- const parsed = JSON.parse(raw);
1004
- if (typeof parsed.port === 'number' && parsed.port > 0) {
1005
- return { port: parsed.port, runtimeToken: parsed.runtimeToken ?? null };
1006
- }
1007
- }
1008
- catch {
1009
- }
1010
- await this.sleep(PROCESS_HEALTH_POLL_INTERVAL_MS);
1011
- }
1012
- return null;
1013
- }
1014
- async checkRuntimeReady(hostPort) {
1015
- const controller = new AbortController();
1016
- const timeout = setTimeout(() => controller.abort(), PROCESS_RUNTIME_TIMEOUT_MS);
1017
- try {
1018
- const response = await fetch(`http://127.0.0.1:${hostPort}/health/ready`, {
1019
- signal: controller.signal,
1020
- });
1021
- return response.ok;
1022
- }
1023
- catch {
1024
- return false;
1025
- }
1026
- finally {
1027
- clearTimeout(timeout);
1028
- }
1029
- }
1030
- async fetchRuntimeMetadata(hostPort) {
1031
- const controller = new AbortController();
1032
- const timeout = setTimeout(() => controller.abort(), PROCESS_RUNTIME_TIMEOUT_MS);
1033
- try {
1034
- const response = await fetch(`http://127.0.0.1:${hostPort}/api/runtime`, {
1035
- headers: { accept: 'application/json' },
1036
- signal: controller.signal,
1037
- });
1038
- if (!response.ok) {
1039
- return null;
1040
- }
1041
- return (await response.json());
1042
- }
1043
- catch {
1044
- return null;
1045
- }
1046
- finally {
1047
- clearTimeout(timeout);
1048
- }
1049
- }
1050
- resolveCliPath() {
1051
- const candidates = [
1052
- (0, path_1.resolve)(process.cwd(), 'scripts', 'cli.js'),
1053
- (0, path_1.resolve)(__dirname, '../../../../../../../../scripts/cli.js'),
1054
- (0, path_1.resolve)(__dirname, '../../../../../../../scripts/cli.js'),
1055
- (0, path_1.resolve)(__dirname, '../../../../../cli.js'),
1056
- ];
1057
- if (process.argv[1] && !candidates.includes((0, path_1.resolve)(process.argv[1]))) {
1058
- candidates.push((0, path_1.resolve)(process.argv[1]));
1059
- }
1060
- for (const candidate of candidates) {
1061
- if ((0, fs_1.existsSync)(candidate)) {
1062
- return candidate;
1063
- }
1064
- }
1065
- throw new Error('Unable to locate CLI entry point for process runtime start. ' +
1066
- `Searched: ${candidates.join(', ')}`);
1067
- }
1068
- resolveProcessLogPath(dataPath) {
1069
- return (0, path_1.join)(dataPath, PROCESS_LOG_FILE_NAME);
1070
- }
1071
- async terminateProcess(pid) {
1072
- if (!pid) {
1073
- return;
1074
- }
1075
- const stillRunningAfterSigterm = await this.signalProcessAndAwaitExit(pid, 'SIGTERM', PROCESS_SHUTDOWN_TIMEOUT_MS);
1076
- if (!stillRunningAfterSigterm) {
1077
- return;
1078
- }
1079
- await this.signalProcessAndAwaitExit(pid, 'SIGKILL', PROCESS_KILL_TIMEOUT_MS).catch((error) => {
1080
- logger.warn({ error, pid }, 'Failed sending SIGKILL to worktree process');
1081
- });
1082
- }
1083
- async signalProcessAndAwaitExit(pid, signal, timeoutMs) {
1084
- const signalPid = process.platform === 'win32' ? pid : -pid;
1085
- try {
1086
- process.kill(signalPid, signal);
1087
- }
1088
- catch (error) {
1089
- const code = error.code;
1090
- if (code === 'ESRCH') {
1091
- return false;
1092
- }
1093
- throw error;
1094
- }
1095
- const deadline = Date.now() + timeoutMs;
1096
- while (Date.now() < deadline) {
1097
- if (!this.isProcessAlive(pid)) {
1098
- return false;
1099
- }
1100
- await this.sleep(200);
1101
- }
1102
- return this.isProcessAlive(pid);
1103
- }
1104
- isProcessAlive(pid) {
1105
- try {
1106
- process.kill(pid, 0);
1107
- return true;
1108
- }
1109
- catch (error) {
1110
- const code = error.code;
1111
- if (code === 'ESRCH') {
1112
- return false;
1113
- }
1114
- if (code === 'EPERM') {
1115
- return true;
1116
- }
1117
- return false;
1118
- }
1119
- }
1120
- async sleep(ms) {
1121
- await new Promise((resolvePromise) => setTimeout(resolvePromise, ms));
1122
- }
1123
888
  async handleContainerEvent(event) {
1124
889
  const containerId = event.id;
1125
890
  if (!containerId) {
@@ -1154,6 +919,20 @@ let WorktreesService = class WorktreesService {
1154
919
  }
1155
920
  return row;
1156
921
  }
922
+ withOperationGuard(worktreeId, operation, run) {
923
+ const inFlight = this.inFlightOperations.get(worktreeId);
924
+ if (inFlight) {
925
+ if (inFlight.operation === operation) {
926
+ return inFlight.promise;
927
+ }
928
+ throw new common_1.ConflictException(`Worktree is already running an in-flight "${inFlight.operation}" operation`);
929
+ }
930
+ const promise = run().finally(() => {
931
+ this.inFlightOperations.delete(worktreeId);
932
+ });
933
+ this.inFlightOperations.set(worktreeId, { operation, promise });
934
+ return promise;
935
+ }
1157
936
  async registerProjectInContainer(hostPort, input) {
1158
937
  if (!hostPort) {
1159
938
  throw new Error('Container did not expose a host port');
@@ -1475,13 +1254,13 @@ exports.WorktreesService = WorktreesService;
1475
1254
  exports.WorktreesService = WorktreesService = __decorate([
1476
1255
  (0, common_1.Injectable)(),
1477
1256
  __param(0, (0, common_1.Inject)(worktrees_store_1.WORKTREES_STORE)),
1478
- __param(6, (0, common_1.Optional)()),
1479
- __param(6, (0, common_1.Inject)(storage_interface_1.STORAGE_SERVICE)),
1480
1257
  __param(7, (0, common_1.Optional)()),
1481
- __metadata("design:paramtypes", [Object, docker_service_1.OrchestratorDockerService,
1258
+ __param(7, (0, common_1.Inject)(storage_interface_1.STORAGE_SERVICE)),
1259
+ __metadata("design:paramtypes", [Object, container_runtime_1.ContainerRuntime,
1260
+ process_runtime_1.ProcessRuntime,
1482
1261
  git_worktree_service_1.GitWorktreeService,
1483
1262
  seed_preparation_service_1.SeedPreparationService,
1484
1263
  event_emitter_1.EventEmitter2,
1485
- event_log_service_1.EventLogService, Object, process_executor_port_1.ProcessExecutor])
1264
+ event_log_service_1.EventLogService, Object])
1486
1265
  ], WorktreesService);
1487
1266
  //# sourceMappingURL=worktrees.service.js.map