devchain-cli 0.9.2 → 0.10.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 (313) hide show
  1. package/dist/cli.js +985 -194
  2. package/dist/drizzle/0044_supreme_joshua_kane.sql +57 -0
  3. package/dist/drizzle/0045_provider_auto_compact_threshold.sql +11 -0
  4. package/dist/drizzle/0046_worktrees_owner_project_id.sql +3 -0
  5. package/dist/drizzle/meta/0044_snapshot.json +4620 -0
  6. package/dist/drizzle/meta/_journal.json +22 -1
  7. package/dist/node_modules/@devchain/shared/schemas/export-schema.d.ts +18 -0
  8. package/dist/node_modules/@devchain/shared/schemas/export-schema.d.ts.map +1 -1
  9. package/dist/node_modules/@devchain/shared/schemas/export-schema.js +6 -0
  10. package/dist/node_modules/@devchain/shared/schemas/export-schema.js.map +1 -1
  11. package/dist/node_modules/@devchain/shared/tsconfig.tsbuildinfo +1 -1
  12. package/dist/server/app.main.module.d.ts +4 -0
  13. package/dist/server/app.main.module.js +102 -0
  14. package/dist/server/app.main.module.js.map +1 -0
  15. package/dist/server/app.module.d.ts +1 -4
  16. package/dist/server/app.module.js +2 -78
  17. package/dist/server/app.module.js.map +1 -1
  18. package/dist/server/app.normal.module.d.ts +4 -0
  19. package/dist/server/app.normal.module.js +90 -0
  20. package/dist/server/app.normal.module.js.map +1 -0
  21. package/dist/server/common/config/env.config.d.ts +81 -1
  22. package/dist/server/common/config/env.config.js +52 -2
  23. package/dist/server/common/config/env.config.js.map +1 -1
  24. package/dist/server/common/templates-directory.d.ts +8 -0
  25. package/dist/server/common/templates-directory.js +56 -0
  26. package/dist/server/common/templates-directory.js.map +1 -0
  27. package/dist/server/main.js +58 -7
  28. package/dist/server/main.js.map +1 -1
  29. package/dist/server/modules/chat/dtos/chat.dto.d.ts +2 -2
  30. package/dist/server/modules/core/controllers/health.controller.d.ts +4 -0
  31. package/dist/server/modules/core/controllers/health.controller.js +22 -1
  32. package/dist/server/modules/core/controllers/health.controller.js.map +1 -1
  33. package/dist/server/modules/core/controllers/runtime.controller.d.ts +18 -0
  34. package/dist/server/modules/core/controllers/runtime.controller.js +130 -0
  35. package/dist/server/modules/core/controllers/runtime.controller.js.map +1 -0
  36. package/dist/server/modules/core/core-common.module.d.ts +2 -0
  37. package/dist/server/modules/core/core-common.module.js +24 -0
  38. package/dist/server/modules/core/core-common.module.js.map +1 -0
  39. package/dist/server/modules/core/core-main-health.module.d.ts +2 -0
  40. package/dist/server/modules/core/core-main-health.module.js +32 -0
  41. package/dist/server/modules/core/core-main-health.module.js.map +1 -0
  42. package/dist/server/modules/core/core-normal-health.module.d.ts +2 -0
  43. package/dist/server/modules/core/core-normal-health.module.js +29 -0
  44. package/dist/server/modules/core/core-normal-health.module.js.map +1 -0
  45. package/dist/server/modules/core/core-normal.module.d.ts +2 -0
  46. package/dist/server/modules/core/core-normal.module.js +28 -0
  47. package/dist/server/modules/core/core-normal.module.js.map +1 -0
  48. package/dist/server/modules/core/core.module.js +4 -11
  49. package/dist/server/modules/core/core.module.js.map +1 -1
  50. package/dist/server/modules/core/services/health.service.d.ts +13 -0
  51. package/dist/server/modules/core/services/health.service.js +39 -0
  52. package/dist/server/modules/core/services/health.service.js.map +1 -0
  53. package/dist/server/modules/core/services/main-readiness-checker.service.d.ts +14 -0
  54. package/dist/server/modules/core/services/main-readiness-checker.service.js +82 -0
  55. package/dist/server/modules/core/services/main-readiness-checker.service.js.map +1 -0
  56. package/dist/server/modules/core/services/normal-readiness-checker.service.d.ts +13 -0
  57. package/dist/server/modules/core/services/normal-readiness-checker.service.js +67 -0
  58. package/dist/server/modules/core/services/normal-readiness-checker.service.js.map +1 -0
  59. package/dist/server/modules/core/services/preflight.service.d.ts +1 -0
  60. package/dist/server/modules/core/services/preflight.service.js +18 -1
  61. package/dist/server/modules/core/services/preflight.service.js.map +1 -1
  62. package/dist/server/modules/core/services/provider-mcp-ensure.service.js +8 -0
  63. package/dist/server/modules/core/services/provider-mcp-ensure.service.js.map +1 -1
  64. package/dist/server/modules/epics/epics.module.js +2 -2
  65. package/dist/server/modules/epics/epics.module.js.map +1 -1
  66. package/dist/server/modules/events/catalog/claude.hooks.session.started.d.ts +39 -0
  67. package/dist/server/modules/events/catalog/claude.hooks.session.started.js +20 -0
  68. package/dist/server/modules/events/catalog/claude.hooks.session.started.js.map +1 -0
  69. package/dist/server/modules/events/catalog/epic.created.d.ts +2 -2
  70. package/dist/server/modules/events/catalog/index.d.ts +38 -4
  71. package/dist/server/modules/events/catalog/index.js +2 -0
  72. package/dist/server/modules/events/catalog/index.js.map +1 -1
  73. package/dist/server/modules/events/catalog/terminal.watcher.triggered.d.ts +2 -2
  74. package/dist/server/modules/events/controllers/event-log.controller.d.ts +1 -1
  75. package/dist/server/modules/events/controllers/event-log.controller.js +11 -9
  76. package/dist/server/modules/events/controllers/event-log.controller.js.map +1 -1
  77. package/dist/server/modules/events/dtos/event-log.dto.d.ts +1 -0
  78. package/dist/server/modules/events/events-domain.module.d.ts +2 -0
  79. package/dist/server/modules/events/events-domain.module.js +42 -0
  80. package/dist/server/modules/events/events-domain.module.js.map +1 -0
  81. package/dist/server/modules/events/events-infra.module.d.ts +2 -0
  82. package/dist/server/modules/events/events-infra.module.js +26 -0
  83. package/dist/server/modules/events/events-infra.module.js.map +1 -0
  84. package/dist/server/modules/events/events.module.js +4 -27
  85. package/dist/server/modules/events/events.module.js.map +1 -1
  86. package/dist/server/modules/events/index.d.ts +2 -0
  87. package/dist/server/modules/events/index.js +2 -0
  88. package/dist/server/modules/events/index.js.map +1 -1
  89. package/dist/server/modules/events/services/event-log.service.d.ts +8 -1
  90. package/dist/server/modules/events/services/event-log.service.js +41 -0
  91. package/dist/server/modules/events/services/event-log.service.js.map +1 -1
  92. package/dist/server/modules/events/subscribers/index.js +2 -0
  93. package/dist/server/modules/events/subscribers/index.js.map +1 -1
  94. package/dist/server/modules/events/subscribers/worktree-broadcaster.subscriber.d.ts +8 -0
  95. package/dist/server/modules/events/subscribers/worktree-broadcaster.subscriber.js +48 -0
  96. package/dist/server/modules/events/subscribers/worktree-broadcaster.subscriber.js.map +1 -0
  97. package/dist/server/modules/git/dtos/git.dto.d.ts +1 -1
  98. package/dist/server/modules/guests/guests.module.js +2 -2
  99. package/dist/server/modules/guests/guests.module.js.map +1 -1
  100. package/dist/server/modules/hooks/controllers/hooks.controller.d.ts +7 -0
  101. package/dist/server/modules/hooks/controllers/hooks.controller.js +49 -0
  102. package/dist/server/modules/hooks/controllers/hooks.controller.js.map +1 -0
  103. package/dist/server/modules/hooks/dtos/hook-event.dto.d.ts +41 -0
  104. package/dist/server/modules/hooks/dtos/hook-event.dto.js +19 -0
  105. package/dist/server/modules/hooks/dtos/hook-event.dto.js.map +1 -0
  106. package/dist/server/modules/hooks/hooks.module.d.ts +2 -0
  107. package/dist/server/modules/hooks/hooks.module.js +27 -0
  108. package/dist/server/modules/hooks/hooks.module.js.map +1 -0
  109. package/dist/server/modules/hooks/services/hooks-config.service.d.ts +5 -0
  110. package/dist/server/modules/hooks/services/hooks-config.service.js +215 -0
  111. package/dist/server/modules/hooks/services/hooks-config.service.js.map +1 -0
  112. package/dist/server/modules/hooks/services/hooks.service.d.ts +11 -0
  113. package/dist/server/modules/hooks/services/hooks.service.js +83 -0
  114. package/dist/server/modules/hooks/services/hooks.service.js.map +1 -0
  115. package/dist/server/modules/mcp/dtos/mcp.dto.d.ts +14 -14
  116. package/dist/server/modules/mcp/mcp.module.js +2 -2
  117. package/dist/server/modules/mcp/mcp.module.js.map +1 -1
  118. package/dist/server/modules/orchestrator/docker/docker.module.d.ts +2 -0
  119. package/dist/server/modules/orchestrator/docker/docker.module.js +22 -0
  120. package/dist/server/modules/orchestrator/docker/docker.module.js.map +1 -0
  121. package/dist/server/modules/orchestrator/docker/index.d.ts +3 -0
  122. package/dist/server/modules/orchestrator/docker/index.js +20 -0
  123. package/dist/server/modules/orchestrator/docker/index.js.map +1 -0
  124. package/dist/server/modules/orchestrator/docker/services/docker.service.d.ts +85 -0
  125. package/dist/server/modules/orchestrator/docker/services/docker.service.js +745 -0
  126. package/dist/server/modules/orchestrator/docker/services/docker.service.js.map +1 -0
  127. package/dist/server/modules/orchestrator/docker/services/seed-preparation.service.d.ts +11 -0
  128. package/dist/server/modules/orchestrator/docker/services/seed-preparation.service.js +181 -0
  129. package/dist/server/modules/orchestrator/docker/services/seed-preparation.service.js.map +1 -0
  130. package/dist/server/modules/orchestrator/git/controllers/git.controller.d.ts +8 -0
  131. package/dist/server/modules/orchestrator/git/controllers/git.controller.js +38 -0
  132. package/dist/server/modules/orchestrator/git/controllers/git.controller.js.map +1 -0
  133. package/dist/server/modules/orchestrator/git/git.module.d.ts +2 -0
  134. package/dist/server/modules/orchestrator/git/git.module.js +23 -0
  135. package/dist/server/modules/orchestrator/git/git.module.js.map +1 -0
  136. package/dist/server/modules/orchestrator/git/index.d.ts +3 -0
  137. package/dist/server/modules/orchestrator/git/index.js +20 -0
  138. package/dist/server/modules/orchestrator/git/index.js.map +1 -0
  139. package/dist/server/modules/orchestrator/git/services/git-worktree.service.d.ts +83 -0
  140. package/dist/server/modules/orchestrator/git/services/git-worktree.service.js +474 -0
  141. package/dist/server/modules/orchestrator/git/services/git-worktree.service.js.map +1 -0
  142. package/dist/server/modules/orchestrator/index.d.ts +6 -0
  143. package/dist/server/modules/orchestrator/index.js +23 -0
  144. package/dist/server/modules/orchestrator/index.js.map +1 -0
  145. package/dist/server/modules/orchestrator/orchestrator-storage/db/index.d.ts +1 -0
  146. package/dist/server/modules/orchestrator/orchestrator-storage/db/index.js +18 -0
  147. package/dist/server/modules/orchestrator/orchestrator-storage/db/index.js.map +1 -0
  148. package/dist/server/modules/orchestrator/orchestrator-storage/db/orchestrator.provider.d.ts +5 -0
  149. package/dist/server/modules/orchestrator/orchestrator-storage/db/orchestrator.provider.js +10 -0
  150. package/dist/server/modules/orchestrator/orchestrator-storage/db/orchestrator.provider.js.map +1 -0
  151. package/dist/server/modules/orchestrator/orchestrator-storage/index.d.ts +2 -0
  152. package/dist/server/modules/orchestrator/orchestrator-storage/index.js +19 -0
  153. package/dist/server/modules/orchestrator/orchestrator-storage/index.js.map +1 -0
  154. package/dist/server/modules/orchestrator/orchestrator-storage/orchestrator-storage.module.d.ts +2 -0
  155. package/dist/server/modules/orchestrator/orchestrator-storage/orchestrator-storage.module.js +23 -0
  156. package/dist/server/modules/orchestrator/orchestrator-storage/orchestrator-storage.module.js.map +1 -0
  157. package/dist/server/modules/orchestrator/proxy/index.d.ts +2 -0
  158. package/dist/server/modules/orchestrator/proxy/index.js +19 -0
  159. package/dist/server/modules/orchestrator/proxy/index.js.map +1 -0
  160. package/dist/server/modules/orchestrator/proxy/orchestrator-proxy.module.d.ts +2 -0
  161. package/dist/server/modules/orchestrator/proxy/orchestrator-proxy.module.js +22 -0
  162. package/dist/server/modules/orchestrator/proxy/orchestrator-proxy.module.js.map +1 -0
  163. package/dist/server/modules/orchestrator/proxy/services/orchestrator-proxy.service.d.ts +18 -0
  164. package/dist/server/modules/orchestrator/proxy/services/orchestrator-proxy.service.js +192 -0
  165. package/dist/server/modules/orchestrator/proxy/services/orchestrator-proxy.service.js.map +1 -0
  166. package/dist/server/modules/orchestrator/sync/controllers/overview.controller.d.ts +9 -0
  167. package/dist/server/modules/orchestrator/sync/controllers/overview.controller.js +66 -0
  168. package/dist/server/modules/orchestrator/sync/controllers/overview.controller.js.map +1 -0
  169. package/dist/server/modules/orchestrator/sync/dtos/overview.dto.d.ts +52 -0
  170. package/dist/server/modules/orchestrator/sync/dtos/overview.dto.js +3 -0
  171. package/dist/server/modules/orchestrator/sync/dtos/overview.dto.js.map +1 -0
  172. package/dist/server/modules/orchestrator/sync/dtos/task-merge.dto.d.ts +5 -0
  173. package/dist/server/modules/orchestrator/sync/dtos/task-merge.dto.js +3 -0
  174. package/dist/server/modules/orchestrator/sync/dtos/task-merge.dto.js.map +1 -0
  175. package/dist/server/modules/orchestrator/sync/events/task-merge.events.d.ts +4 -0
  176. package/dist/server/modules/orchestrator/sync/events/task-merge.events.js +5 -0
  177. package/dist/server/modules/orchestrator/sync/events/task-merge.events.js.map +1 -0
  178. package/dist/server/modules/orchestrator/sync/index.d.ts +7 -0
  179. package/dist/server/modules/orchestrator/sync/index.js +24 -0
  180. package/dist/server/modules/orchestrator/sync/index.js.map +1 -0
  181. package/dist/server/modules/orchestrator/sync/services/lazy-fetch.service.d.ts +31 -0
  182. package/dist/server/modules/orchestrator/sync/services/lazy-fetch.service.js +410 -0
  183. package/dist/server/modules/orchestrator/sync/services/lazy-fetch.service.js.map +1 -0
  184. package/dist/server/modules/orchestrator/sync/services/task-merge.service.d.ts +44 -0
  185. package/dist/server/modules/orchestrator/sync/services/task-merge.service.js +730 -0
  186. package/dist/server/modules/orchestrator/sync/services/task-merge.service.js.map +1 -0
  187. package/dist/server/modules/orchestrator/sync/sync.module.d.ts +2 -0
  188. package/dist/server/modules/orchestrator/sync/sync.module.js +36 -0
  189. package/dist/server/modules/orchestrator/sync/sync.module.js.map +1 -0
  190. package/dist/server/modules/orchestrator/ui/app/lib/worktrees.d.ts +118 -0
  191. package/dist/server/modules/orchestrator/ui/app/lib/worktrees.js +297 -0
  192. package/dist/server/modules/orchestrator/ui/app/lib/worktrees.js.map +1 -0
  193. package/dist/server/modules/orchestrator/ui/app/orchestrator-app.d.ts +17 -0
  194. package/dist/server/modules/orchestrator/ui/app/orchestrator-app.js +752 -0
  195. package/dist/server/modules/orchestrator/ui/app/orchestrator-app.js.map +1 -0
  196. package/dist/server/modules/orchestrator/worktrees/controllers/templates.controller.d.ts +15 -0
  197. package/dist/server/modules/orchestrator/worktrees/controllers/templates.controller.js +85 -0
  198. package/dist/server/modules/orchestrator/worktrees/controllers/templates.controller.js.map +1 -0
  199. package/dist/server/modules/orchestrator/worktrees/controllers/worktrees.controller.d.ts +29 -0
  200. package/dist/server/modules/orchestrator/worktrees/controllers/worktrees.controller.js +272 -0
  201. package/dist/server/modules/orchestrator/worktrees/controllers/worktrees.controller.js.map +1 -0
  202. package/dist/server/modules/orchestrator/worktrees/dtos/worktree.dto.d.ts +109 -0
  203. package/dist/server/modules/orchestrator/worktrees/dtos/worktree.dto.js +57 -0
  204. package/dist/server/modules/orchestrator/worktrees/dtos/worktree.dto.js.map +1 -0
  205. package/dist/server/modules/orchestrator/worktrees/events/worktree.events.d.ts +4 -0
  206. package/dist/server/modules/orchestrator/worktrees/events/worktree.events.js +5 -0
  207. package/dist/server/modules/orchestrator/worktrees/events/worktree.events.js.map +1 -0
  208. package/dist/server/modules/orchestrator/worktrees/index.d.ts +7 -0
  209. package/dist/server/modules/orchestrator/worktrees/index.js +24 -0
  210. package/dist/server/modules/orchestrator/worktrees/index.js.map +1 -0
  211. package/dist/server/modules/orchestrator/worktrees/local-worktrees.store.d.ts +18 -0
  212. package/dist/server/modules/orchestrator/worktrees/local-worktrees.store.js +198 -0
  213. package/dist/server/modules/orchestrator/worktrees/local-worktrees.store.js.map +1 -0
  214. package/dist/server/modules/orchestrator/worktrees/services/worktrees.service.d.ts +87 -0
  215. package/dist/server/modules/orchestrator/worktrees/services/worktrees.service.js +1380 -0
  216. package/dist/server/modules/orchestrator/worktrees/services/worktrees.service.js.map +1 -0
  217. package/dist/server/modules/orchestrator/worktrees/worktree-validation.d.ts +4 -0
  218. package/dist/server/modules/orchestrator/worktrees/worktree-validation.js +43 -0
  219. package/dist/server/modules/orchestrator/worktrees/worktree-validation.js.map +1 -0
  220. package/dist/server/modules/orchestrator/worktrees/worktrees.module.d.ts +2 -0
  221. package/dist/server/modules/orchestrator/worktrees/worktrees.module.js +44 -0
  222. package/dist/server/modules/orchestrator/worktrees/worktrees.module.js.map +1 -0
  223. package/dist/server/modules/orchestrator/worktrees/worktrees.store.d.ts +38 -0
  224. package/dist/server/modules/orchestrator/worktrees/worktrees.store.js +5 -0
  225. package/dist/server/modules/orchestrator/worktrees/worktrees.store.js.map +1 -0
  226. package/dist/server/modules/profiles/dto.d.ts +4 -4
  227. package/dist/server/modules/projects/controllers/projects.controller.d.ts +13 -3
  228. package/dist/server/modules/projects/controllers/projects.controller.js +55 -7
  229. package/dist/server/modules/projects/controllers/projects.controller.js.map +1 -1
  230. package/dist/server/modules/projects/projects.module.js +3 -2
  231. package/dist/server/modules/projects/projects.module.js.map +1 -1
  232. package/dist/server/modules/projects/services/main-project-bootstrap.service.d.ts +11 -0
  233. package/dist/server/modules/projects/services/main-project-bootstrap.service.js +76 -0
  234. package/dist/server/modules/projects/services/main-project-bootstrap.service.js.map +1 -0
  235. package/dist/server/modules/projects/services/projects.service.d.ts +8 -0
  236. package/dist/server/modules/projects/services/projects.service.js +115 -37
  237. package/dist/server/modules/projects/services/projects.service.js.map +1 -1
  238. package/dist/server/modules/providers/adapters/gemini.adapter.d.ts +1 -1
  239. package/dist/server/modules/providers/adapters/gemini.adapter.js +6 -4
  240. package/dist/server/modules/providers/adapters/gemini.adapter.js.map +1 -1
  241. package/dist/server/modules/providers/controllers/providers.controller.d.ts +3 -0
  242. package/dist/server/modules/providers/controllers/providers.controller.js +28 -0
  243. package/dist/server/modules/providers/controllers/providers.controller.js.map +1 -1
  244. package/dist/server/modules/providers/providers.module.js +2 -2
  245. package/dist/server/modules/providers/providers.module.js.map +1 -1
  246. package/dist/server/modules/registry/services/unified-template.service.js +6 -18
  247. package/dist/server/modules/registry/services/unified-template.service.js.map +1 -1
  248. package/dist/server/modules/reviews/dtos/review.dto.d.ts +4 -4
  249. package/dist/server/modules/reviews/reviews.module.js +2 -2
  250. package/dist/server/modules/reviews/reviews.module.js.map +1 -1
  251. package/dist/server/modules/seeders/seeders/0005_seed_renew_instructions_subscriber.d.ts +3 -0
  252. package/dist/server/modules/seeders/seeders/0005_seed_renew_instructions_subscriber.js +89 -0
  253. package/dist/server/modules/seeders/seeders/0005_seed_renew_instructions_subscriber.js.map +1 -0
  254. package/dist/server/modules/seeders/seeders/0006_seed_rename_template_slugs.d.ts +3 -0
  255. package/dist/server/modules/seeders/seeders/0006_seed_rename_template_slugs.js +60 -0
  256. package/dist/server/modules/seeders/seeders/0006_seed_rename_template_slugs.js.map +1 -0
  257. package/dist/server/modules/seeders/services/data-seeder.service.js +4 -0
  258. package/dist/server/modules/seeders/services/data-seeder.service.js.map +1 -1
  259. package/dist/server/modules/sessions/services/sessions.service.d.ts +3 -1
  260. package/dist/server/modules/sessions/services/sessions.service.js +79 -22
  261. package/dist/server/modules/sessions/services/sessions.service.js.map +1 -1
  262. package/dist/server/modules/sessions/sessions.module.js +6 -4
  263. package/dist/server/modules/sessions/sessions.module.js.map +1 -1
  264. package/dist/server/modules/sessions/utils/claude-config.d.ts +6 -2
  265. package/dist/server/modules/sessions/utils/claude-config.js +19 -6
  266. package/dist/server/modules/sessions/utils/claude-config.js.map +1 -1
  267. package/dist/server/modules/settings/dtos/settings.dto.d.ts +4 -4
  268. package/dist/server/modules/skills/dtos/community-sources.dto.d.ts +2 -2
  269. package/dist/server/modules/skills/dtos/local-sources.dto.d.ts +2 -2
  270. package/dist/server/modules/skills/dtos/skill.dto.d.ts +7 -7
  271. package/dist/server/modules/storage/db/schema.d.ts +811 -0
  272. package/dist/server/modules/storage/db/schema.js +63 -1
  273. package/dist/server/modules/storage/db/schema.js.map +1 -1
  274. package/dist/server/modules/storage/db/sqlite-json.d.ts +2 -0
  275. package/dist/server/modules/storage/db/sqlite-json.js +8 -0
  276. package/dist/server/modules/storage/db/sqlite-json.js.map +1 -0
  277. package/dist/server/modules/storage/interfaces/storage.interface.d.ts +4 -1
  278. package/dist/server/modules/storage/interfaces/storage.interface.js.map +1 -1
  279. package/dist/server/modules/storage/local/local-storage.service.d.ts +1 -1
  280. package/dist/server/modules/storage/local/local-storage.service.js +19 -2
  281. package/dist/server/modules/storage/local/local-storage.service.js.map +1 -1
  282. package/dist/server/modules/storage/models/domain.models.d.ts +2 -0
  283. package/dist/server/modules/subscribers/dtos/subscriber.dto.d.ts +16 -16
  284. package/dist/server/modules/subscribers/events/event-fields-catalog.js +18 -0
  285. package/dist/server/modules/subscribers/events/event-fields-catalog.js.map +1 -1
  286. package/dist/server/modules/subscribers/subscribers.module.js +2 -2
  287. package/dist/server/modules/subscribers/subscribers.module.js.map +1 -1
  288. package/dist/server/modules/terminal/gateways/terminal.gateway.js +7 -2
  289. package/dist/server/modules/terminal/gateways/terminal.gateway.js.map +1 -1
  290. package/dist/server/modules/terminal/services/tmux.service.d.ts +9 -0
  291. package/dist/server/modules/terminal/services/tmux.service.js +55 -5
  292. package/dist/server/modules/terminal/services/tmux.service.js.map +1 -1
  293. package/dist/server/modules/terminal/terminal.module.js +2 -2
  294. package/dist/server/modules/terminal/terminal.module.js.map +1 -1
  295. package/dist/server/modules/watchers/watchers.module.js +2 -2
  296. package/dist/server/modules/watchers/watchers.module.js.map +1 -1
  297. package/dist/server/templates/3-agents-dev.json +662 -0
  298. package/dist/server/templates/{dev-loop.json → 5-agents-dev.json} +174 -100
  299. package/dist/server/test-setup.js +7 -0
  300. package/dist/server/test-setup.js.map +1 -1
  301. package/dist/server/tsconfig.tsbuildinfo +1 -1
  302. package/dist/server/ui/assets/ReviewDetailPage-CZZQtaY7.js +1 -0
  303. package/dist/server/ui/assets/{ReviewsPage-MKT-vv59.js → ReviewsPage-C209GLQG.js} +1 -1
  304. package/dist/server/ui/assets/index-DvRuLfpZ.css +32 -0
  305. package/dist/server/ui/assets/index-Th1FDtKR.js +977 -0
  306. package/dist/server/ui/assets/{useReviewSubscription-Dc58i6Bk.js → useReviewSubscription-Dcabsa78.js} +1 -1
  307. package/dist/server/ui/index.html +2 -2
  308. package/dist/templates/3-agents-dev.json +662 -0
  309. package/dist/templates/{dev-loop.json → 5-agents-dev.json} +174 -100
  310. package/package.json +15 -1
  311. package/dist/server/ui/assets/ReviewDetailPage-BvSckWKj.js +0 -6
  312. package/dist/server/ui/assets/index-BtUq-Qxb.css +0 -32
  313. package/dist/server/ui/assets/index-kTb634Zp.js +0 -945
@@ -0,0 +1,752 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CreateWorktreeDialog = CreateWorktreeDialog;
4
+ exports.OrchestratorApp = OrchestratorApp;
5
+ const jsx_runtime_1 = require("react/jsx-runtime");
6
+ const react_1 = require("react");
7
+ const react_query_1 = require("@tanstack/react-query");
8
+ const lucide_react_1 = require("lucide-react");
9
+ const badge_1 = require("../../../../ui/components/ui/badge");
10
+ const button_1 = require("../../../../ui/components/ui/button");
11
+ const card_1 = require("../../../../ui/components/ui/card");
12
+ const checkbox_1 = require("../../../../ui/components/ui/checkbox");
13
+ const dialog_1 = require("../../../../ui/components/ui/dialog");
14
+ const input_1 = require("../../../../ui/components/ui/input");
15
+ const label_1 = require("../../../../ui/components/ui/label");
16
+ const select_1 = require("../../../../ui/components/ui/select");
17
+ const separator_1 = require("../../../../ui/components/ui/separator");
18
+ const textarea_1 = require("../../../../ui/components/ui/textarea");
19
+ const runtime_1 = require("../../../../ui/lib/runtime");
20
+ const utils_1 = require("../../../../ui/lib/utils");
21
+ const worktrees_1 = require("./lib/worktrees");
22
+ const REFRESH_INTERVAL_MS = 15_000;
23
+ const ACTIVITY_REFRESH_INTERVAL_MS = 60_000;
24
+ const OVERVIEW_TAB_ID = 'overview';
25
+ const WORKTREE_NAME_PATTERN = /^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$/;
26
+ const INVALID_BRANCH_CONTROL_OR_SPACE = /[\x00-\x20\x7f]/;
27
+ const INVALID_BRANCH_CHARS = /[~^:?*\[]/;
28
+ function formatMaybeCount(value) {
29
+ if (value === null || value === undefined) {
30
+ return '--';
31
+ }
32
+ return String(value);
33
+ }
34
+ function getDerivedStatus(worktree, mergeInProgress = false) {
35
+ if (mergeInProgress) {
36
+ return { icon: '◔', label: 'Merging', iconClassName: 'text-amber-600' };
37
+ }
38
+ const normalized = worktree.status.toLowerCase();
39
+ if (normalized === 'merged') {
40
+ return { icon: '🔀', label: 'Merged', iconClassName: 'text-violet-600' };
41
+ }
42
+ if (normalized === 'completed') {
43
+ return { icon: '✓', label: 'Completed', iconClassName: 'text-emerald-600' };
44
+ }
45
+ if (normalized === 'stopped') {
46
+ return { icon: '■', label: 'Stopped', iconClassName: 'text-slate-500' };
47
+ }
48
+ if (normalized === 'error') {
49
+ return { icon: '✕', label: 'Error', iconClassName: 'text-red-600' };
50
+ }
51
+ if (normalized === 'running') {
52
+ const isIdle = (worktree.commitsAhead ?? 0) === 0 &&
53
+ (worktree.commitsBehind ?? 0) === 0 &&
54
+ !worktree.errorMessage;
55
+ if (isIdle) {
56
+ return { icon: '◌', label: 'Idle', iconClassName: 'text-amber-600' };
57
+ }
58
+ return { icon: '●', label: 'Running', iconClassName: 'text-blue-600' };
59
+ }
60
+ return { icon: '●', label: 'Creating', iconClassName: 'text-sky-500' };
61
+ }
62
+ function getRuntimeTypeLabel(runtimeType) {
63
+ return String(runtimeType).trim().toLowerCase() === 'process' ? 'Process' : 'Container';
64
+ }
65
+ function getRuntimeTypeBadgeClassName(runtimeType) {
66
+ return String(runtimeType).trim().toLowerCase() === 'process'
67
+ ? 'border-amber-500/30 bg-amber-500/10 text-amber-700 dark:text-amber-300'
68
+ : 'border-sky-500/30 bg-sky-500/10 text-sky-700 dark:text-sky-300';
69
+ }
70
+ function normalizeWorktreeName(value) {
71
+ return value
72
+ .trim()
73
+ .toLowerCase()
74
+ .replace(/[^a-z0-9-]+/g, '-')
75
+ .replace(/-{2,}/g, '-')
76
+ .replace(/^-+/, '')
77
+ .replace(/-+$/, '')
78
+ .slice(0, 63);
79
+ }
80
+ function deriveBranchName(worktreeName) {
81
+ return normalizeWorktreeName(worktreeName);
82
+ }
83
+ function isValidGitBranchName(name) {
84
+ if (name.length < 1 || name.length > 255) {
85
+ return false;
86
+ }
87
+ if (INVALID_BRANCH_CONTROL_OR_SPACE.test(name)) {
88
+ return false;
89
+ }
90
+ if (name.includes('..') ||
91
+ name.includes('@{') ||
92
+ name.includes('//') ||
93
+ name.includes('\\') ||
94
+ name.startsWith('/') ||
95
+ name.endsWith('/') ||
96
+ name.startsWith('.') ||
97
+ name.endsWith('.') ||
98
+ name.endsWith('.lock')) {
99
+ return false;
100
+ }
101
+ if (INVALID_BRANCH_CHARS.test(name)) {
102
+ return false;
103
+ }
104
+ const segments = name.split('/');
105
+ return !segments.some((segment) => segment.length === 0 || segment === '.' || segment === '..');
106
+ }
107
+ function toErrorMessage(error) {
108
+ if (error instanceof Error) {
109
+ return error.message;
110
+ }
111
+ return 'Request failed';
112
+ }
113
+ function isWorktreeApiError(error) {
114
+ return (error instanceof Error &&
115
+ 'status' in error &&
116
+ typeof error.status === 'number' &&
117
+ 'conflicts' in error &&
118
+ Array.isArray(error.conflicts));
119
+ }
120
+ function parseStoredMergeConflicts(raw) {
121
+ if (!raw) {
122
+ return [];
123
+ }
124
+ const files = raw
125
+ .split('\n')
126
+ .map((line) => line.trim())
127
+ .filter(Boolean);
128
+ return [...new Set(files)].map((file) => ({ file, type: 'merge' }));
129
+ }
130
+ function formatTimestamp(value) {
131
+ const date = new Date(value);
132
+ if (Number.isNaN(date.getTime())) {
133
+ return value;
134
+ }
135
+ return new Intl.DateTimeFormat(undefined, {
136
+ month: 'short',
137
+ day: '2-digit',
138
+ hour: '2-digit',
139
+ minute: '2-digit',
140
+ }).format(date);
141
+ }
142
+ function formatRelativeTimestamp(value) {
143
+ const date = new Date(value);
144
+ if (Number.isNaN(date.getTime())) {
145
+ return value;
146
+ }
147
+ const diffMs = Date.now() - date.getTime();
148
+ if (diffMs < 60_000) {
149
+ return 'just now';
150
+ }
151
+ const diffMinutes = Math.floor(diffMs / 60_000);
152
+ if (diffMinutes < 60) {
153
+ return `${diffMinutes}m ago`;
154
+ }
155
+ const diffHours = Math.floor(diffMinutes / 60);
156
+ if (diffHours < 24) {
157
+ return `${diffHours}h ago`;
158
+ }
159
+ const diffDays = Math.floor(diffHours / 24);
160
+ return `${diffDays}d ago`;
161
+ }
162
+ function getActivityIconVisual(type) {
163
+ const normalizedType = String(type).trim().toLowerCase();
164
+ if (normalizedType === 'started') {
165
+ return {
166
+ icon: (0, jsx_runtime_1.jsx)(lucide_react_1.Play, { className: "h-4 w-4" }),
167
+ className: 'text-emerald-600',
168
+ };
169
+ }
170
+ if (normalizedType === 'stopped') {
171
+ return {
172
+ icon: (0, jsx_runtime_1.jsx)(lucide_react_1.Square, { className: "h-4 w-4" }),
173
+ className: 'text-slate-500',
174
+ };
175
+ }
176
+ if (normalizedType === 'created') {
177
+ return {
178
+ icon: (0, jsx_runtime_1.jsx)(lucide_react_1.Plus, { className: "h-4 w-4" }),
179
+ className: 'text-sky-600',
180
+ };
181
+ }
182
+ if (normalizedType === 'deleted') {
183
+ return {
184
+ icon: (0, jsx_runtime_1.jsx)(lucide_react_1.Trash2, { className: "h-4 w-4" }),
185
+ className: 'text-rose-600',
186
+ };
187
+ }
188
+ if (normalizedType === 'merged') {
189
+ return {
190
+ icon: (0, jsx_runtime_1.jsx)(lucide_react_1.GitMerge, { className: "h-4 w-4" }),
191
+ className: 'text-violet-600',
192
+ };
193
+ }
194
+ if (normalizedType === 'error') {
195
+ return {
196
+ icon: (0, jsx_runtime_1.jsx)(lucide_react_1.AlertCircle, { className: "h-4 w-4" }),
197
+ className: 'text-red-600',
198
+ };
199
+ }
200
+ if (normalizedType === 'rebased') {
201
+ return {
202
+ icon: (0, jsx_runtime_1.jsx)(lucide_react_1.GitBranch, { className: "h-4 w-4" }),
203
+ className: 'text-amber-600',
204
+ };
205
+ }
206
+ return {
207
+ icon: (0, jsx_runtime_1.jsx)(lucide_react_1.AlertCircle, { className: "h-4 w-4" }),
208
+ className: 'text-muted-foreground',
209
+ };
210
+ }
211
+ function CreateWorktreeDialog({ open, onOpenChange, templates, baseBranchOptions, isBranchesLoading, branchesError, isTemplatesLoading, templatesError, dockerAvailable, isSubmitting, onSubmit, }) {
212
+ const [name, setName] = (0, react_1.useState)('');
213
+ const [branchName, setBranchName] = (0, react_1.useState)('');
214
+ const [baseBranch, setBaseBranch] = (0, react_1.useState)('');
215
+ const [templateSlug, setTemplateSlug] = (0, react_1.useState)('');
216
+ const [description, setDescription] = (0, react_1.useState)('');
217
+ const [useDockerContainer, setUseDockerContainer] = (0, react_1.useState)(dockerAvailable);
218
+ const [branchIsAutoDerived, setBranchIsAutoDerived] = (0, react_1.useState)(true);
219
+ const [selectedPreset, setSelectedPreset] = (0, react_1.useState)('');
220
+ const [error, setError] = (0, react_1.useState)(null);
221
+ (0, react_1.useEffect)(() => {
222
+ if (!open) {
223
+ return;
224
+ }
225
+ setName('');
226
+ setBranchName('');
227
+ setBaseBranch(baseBranchOptions[0] ?? '');
228
+ setTemplateSlug(templates[0]?.slug ?? '');
229
+ setDescription('');
230
+ setUseDockerContainer(dockerAvailable);
231
+ setBranchIsAutoDerived(true);
232
+ setSelectedPreset('');
233
+ setError(null);
234
+ }, [open, baseBranchOptions, dockerAvailable, templates]);
235
+ (0, react_1.useEffect)(() => {
236
+ if (!open) {
237
+ return;
238
+ }
239
+ if (!baseBranch.trim() && baseBranchOptions.length > 0) {
240
+ setBaseBranch(baseBranchOptions[0]);
241
+ }
242
+ }, [baseBranchOptions, baseBranch, open]);
243
+ (0, react_1.useEffect)(() => {
244
+ if (!open) {
245
+ return;
246
+ }
247
+ if (templates.length > 0 && !templates.some((template) => template.slug === templateSlug)) {
248
+ setTemplateSlug(templates[0].slug);
249
+ }
250
+ }, [open, templateSlug, templates]);
251
+ const { data: templateDetail } = (0, react_query_1.useQuery)({
252
+ queryKey: ['template-detail', templateSlug],
253
+ queryFn: () => (0, worktrees_1.fetchTemplate)(templateSlug),
254
+ enabled: Boolean(templateSlug),
255
+ staleTime: 5 * 60 * 1000,
256
+ });
257
+ const availablePresets = (0, react_1.useMemo)(() => {
258
+ const presets = templateDetail?.content?.presets;
259
+ if (!Array.isArray(presets) || presets.length === 0)
260
+ return [];
261
+ return presets.map((p) => p.name).reverse();
262
+ }, [templateDetail]);
263
+ (0, react_1.useEffect)(() => {
264
+ setSelectedPreset('');
265
+ }, [templateSlug]);
266
+ async function handleSubmit(event) {
267
+ event.preventDefault();
268
+ setError(null);
269
+ const resolvedName = normalizeWorktreeName(name);
270
+ const resolvedBranchName = branchName.trim();
271
+ const resolvedDescription = description.trim();
272
+ if (!WORKTREE_NAME_PATTERN.test(resolvedName)) {
273
+ setError('Name must use lowercase letters, numbers, and hyphens (1-63 chars, no leading/trailing hyphen).');
274
+ return;
275
+ }
276
+ if (!isValidGitBranchName(resolvedBranchName)) {
277
+ setError('Branch name is invalid.');
278
+ return;
279
+ }
280
+ const resolvedBaseBranch = baseBranch.trim();
281
+ if (!resolvedBaseBranch) {
282
+ setError('Base branch is required.');
283
+ return;
284
+ }
285
+ if (!templateSlug.trim()) {
286
+ setError('Template is required.');
287
+ return;
288
+ }
289
+ try {
290
+ await onSubmit({
291
+ name: resolvedName,
292
+ branchName: resolvedBranchName,
293
+ baseBranch: resolvedBaseBranch,
294
+ templateSlug,
295
+ description: resolvedDescription.length > 0 ? resolvedDescription : undefined,
296
+ runtimeType: useDockerContainer && dockerAvailable ? 'container' : 'process',
297
+ ...(selectedPreset && { presetName: selectedPreset }),
298
+ });
299
+ }
300
+ catch (submitError) {
301
+ setError(toErrorMessage(submitError));
302
+ }
303
+ }
304
+ const canSelectBaseBranch = baseBranchOptions.length > 0;
305
+ const showManualBaseBranchInput = Boolean(branchesError) || (!isBranchesLoading && baseBranchOptions.length === 0);
306
+ return ((0, jsx_runtime_1.jsx)(dialog_1.Dialog, { open: open, onOpenChange: onOpenChange, children: (0, jsx_runtime_1.jsxs)(dialog_1.DialogContent, { className: "sm:max-w-xl", children: [(0, jsx_runtime_1.jsxs)(dialog_1.DialogHeader, { children: [(0, jsx_runtime_1.jsx)(dialog_1.DialogTitle, { children: "Create New Worktree" }), (0, jsx_runtime_1.jsx)(dialog_1.DialogDescription, { children: "Create an isolated worktree runtime from a selected template." })] }), (0, jsx_runtime_1.jsxs)("form", { onSubmit: (event) => void handleSubmit(event), children: [(0, jsx_runtime_1.jsxs)("div", { className: "grid gap-4 py-2", children: [(0, jsx_runtime_1.jsxs)("div", { className: "grid gap-2", children: [(0, jsx_runtime_1.jsx)(label_1.Label, { htmlFor: "wt-name", children: "Name" }), (0, jsx_runtime_1.jsx)(input_1.Input, { id: "wt-name", value: name, placeholder: "feature-auth", onChange: (event) => {
307
+ const normalizedName = normalizeWorktreeName(event.target.value);
308
+ setName(normalizedName);
309
+ if (branchIsAutoDerived) {
310
+ setBranchName(deriveBranchName(normalizedName));
311
+ }
312
+ }, disabled: isSubmitting }), (0, jsx_runtime_1.jsx)("p", { className: "text-xs text-muted-foreground", children: "Used for worktree path and container name." })] }), (0, jsx_runtime_1.jsxs)("div", { className: "grid gap-2", children: [(0, jsx_runtime_1.jsx)(label_1.Label, { htmlFor: "wt-branch", children: "Branch Name" }), (0, jsx_runtime_1.jsx)(input_1.Input, { id: "wt-branch", value: branchName, placeholder: "feature-auth", onChange: (event) => {
313
+ const nextBranch = event.target.value;
314
+ setBranchName(nextBranch);
315
+ setBranchIsAutoDerived(nextBranch === deriveBranchName(name));
316
+ }, disabled: isSubmitting }), (0, jsx_runtime_1.jsx)("p", { className: "text-xs text-muted-foreground", children: "Auto-derived from name until manually edited." })] }), (0, jsx_runtime_1.jsxs)("div", { className: "grid gap-2 sm:grid-cols-2", children: [(0, jsx_runtime_1.jsxs)("div", { className: "grid gap-2", children: [(0, jsx_runtime_1.jsx)(label_1.Label, { htmlFor: "wt-base", children: "Base Branch" }), (0, jsx_runtime_1.jsxs)(select_1.Select, { value: canSelectBaseBranch && baseBranchOptions.includes(baseBranch) ? baseBranch : '', onValueChange: setBaseBranch, disabled: isSubmitting || isBranchesLoading || !canSelectBaseBranch, children: [(0, jsx_runtime_1.jsx)(select_1.SelectTrigger, { id: "wt-base", children: (0, jsx_runtime_1.jsx)(select_1.SelectValue, { placeholder: isBranchesLoading ? 'Loading branches...' : 'Select base branch' }) }), (0, jsx_runtime_1.jsx)(select_1.SelectContent, { children: baseBranchOptions.map((branch) => ((0, jsx_runtime_1.jsx)(select_1.SelectItem, { value: branch, children: branch }, branch))) })] }), isBranchesLoading && ((0, jsx_runtime_1.jsxs)("p", { className: "flex items-center gap-1 text-xs text-muted-foreground", children: [(0, jsx_runtime_1.jsx)(lucide_react_1.Loader2, { className: "h-3 w-3 animate-spin" }), "Loading branches..."] })), branchesError && ((0, jsx_runtime_1.jsx)("p", { className: "rounded-md border border-red-300 bg-red-50 p-2 text-xs text-red-700", children: branchesError })), showManualBaseBranchInput && ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(label_1.Label, { htmlFor: "wt-base-manual", className: "text-xs text-muted-foreground", children: "Enter base branch manually" }), (0, jsx_runtime_1.jsx)(input_1.Input, { id: "wt-base-manual", value: baseBranch, placeholder: "main", onChange: (event) => setBaseBranch(event.target.value), disabled: isSubmitting })] }))] }), (0, jsx_runtime_1.jsxs)("div", { className: "grid gap-2", children: [(0, jsx_runtime_1.jsx)(label_1.Label, { htmlFor: "wt-template", children: "Template" }), (0, jsx_runtime_1.jsxs)(select_1.Select, { value: templateSlug, onValueChange: setTemplateSlug, disabled: isSubmitting || isTemplatesLoading || templates.length === 0, children: [(0, jsx_runtime_1.jsx)(select_1.SelectTrigger, { id: "wt-template", children: (0, jsx_runtime_1.jsx)(select_1.SelectValue, { placeholder: isTemplatesLoading ? 'Loading templates...' : 'Select template' }) }), (0, jsx_runtime_1.jsx)(select_1.SelectContent, { children: templates.map((template) => ((0, jsx_runtime_1.jsx)(select_1.SelectItem, { value: template.slug, children: template.name }, template.slug))) })] }), isTemplatesLoading && ((0, jsx_runtime_1.jsxs)("p", { className: "flex items-center gap-1 text-xs text-muted-foreground", children: [(0, jsx_runtime_1.jsx)(lucide_react_1.Loader2, { className: "h-3 w-3 animate-spin" }), "Loading templates..."] })), templatesError && ((0, jsx_runtime_1.jsx)("p", { className: "rounded-md border border-red-300 bg-red-50 p-2 text-xs text-red-700", children: templatesError }))] })] }), availablePresets.length > 0 && ((0, jsx_runtime_1.jsxs)("div", { className: "grid gap-2", children: [(0, jsx_runtime_1.jsx)(label_1.Label, { htmlFor: "wt-preset", children: "Preset (Optional)" }), (0, jsx_runtime_1.jsxs)(select_1.Select, { value: selectedPreset || '__none__', onValueChange: (v) => setSelectedPreset(v === '__none__' ? '' : v), disabled: isSubmitting, children: [(0, jsx_runtime_1.jsx)(select_1.SelectTrigger, { id: "wt-preset", children: (0, jsx_runtime_1.jsx)(select_1.SelectValue, { placeholder: "Use default configuration" }) }), (0, jsx_runtime_1.jsxs)(select_1.SelectContent, { children: [(0, jsx_runtime_1.jsx)(select_1.SelectItem, { value: "__none__", children: "Default configuration" }), availablePresets.map((presetName) => ((0, jsx_runtime_1.jsx)(select_1.SelectItem, { value: presetName, children: presetName }, presetName)))] })] }), (0, jsx_runtime_1.jsx)("p", { className: "text-xs text-muted-foreground", children: "Optionally select a preset to pre-configure agent providers" })] })), (0, jsx_runtime_1.jsxs)("div", { className: "grid gap-2", children: [(0, jsx_runtime_1.jsx)(label_1.Label, { htmlFor: "wt-description", children: "Description" }), (0, jsx_runtime_1.jsx)(textarea_1.Textarea, { id: "wt-description", value: description, placeholder: "Describe the worktree goal and implementation scope...", rows: 4, onChange: (event) => setDescription(event.target.value), disabled: isSubmitting })] }), (0, jsx_runtime_1.jsxs)("div", { className: "grid gap-2 rounded-md border p-3", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-start gap-2", children: [(0, jsx_runtime_1.jsx)(checkbox_1.Checkbox, { id: "wt-use-docker", checked: useDockerContainer, onCheckedChange: (value) => setUseDockerContainer(value === true), disabled: isSubmitting || !dockerAvailable }), (0, jsx_runtime_1.jsxs)("div", { className: "grid gap-1", children: [(0, jsx_runtime_1.jsx)(label_1.Label, { htmlFor: "wt-use-docker", className: (0, utils_1.cn)(!dockerAvailable && 'text-muted-foreground'), children: "Use Docker container" }), (0, jsx_runtime_1.jsx)("p", { className: "text-xs text-muted-foreground", children: "Provides full process and filesystem isolation." })] })] }), !dockerAvailable && ((0, jsx_runtime_1.jsx)("p", { className: "text-xs text-muted-foreground", children: "Docker is required for container isolation. Worktree will run as a host process." }))] }), error && ((0, jsx_runtime_1.jsx)("p", { className: "rounded-md border border-red-300 bg-red-50 p-2 text-sm text-red-700", children: error }))] }), (0, jsx_runtime_1.jsxs)(dialog_1.DialogFooter, { children: [(0, jsx_runtime_1.jsx)(button_1.Button, { variant: "outline", onClick: () => onOpenChange(false), disabled: isSubmitting, children: "Cancel" }), (0, jsx_runtime_1.jsxs)(button_1.Button, { type: "submit", disabled: isSubmitting, children: [isSubmitting && (0, jsx_runtime_1.jsx)(lucide_react_1.Loader2, { className: "mr-2 h-4 w-4 animate-spin" }), "Create"] })] })] })] }) }));
317
+ }
318
+ function MergePreviewDialog({ open, onOpenChange, worktree, preview, isPreviewLoading, previewError, isMerging, onConfirmMerge, onResolveManually, }) {
319
+ const conflicts = preview?.conflicts ?? [];
320
+ const canMerge = Boolean(preview?.canMerge);
321
+ return ((0, jsx_runtime_1.jsx)(dialog_1.Dialog, { open: open, onOpenChange: onOpenChange, children: (0, jsx_runtime_1.jsxs)(dialog_1.DialogContent, { className: "sm:max-w-xl", children: [(0, jsx_runtime_1.jsxs)(dialog_1.DialogHeader, { children: [(0, jsx_runtime_1.jsx)(dialog_1.DialogTitle, { children: "Merge Preview" }), (0, jsx_runtime_1.jsx)(dialog_1.DialogDescription, { children: worktree
322
+ ? `Review merge changes for "${worktree.name}" before executing merge.`
323
+ : 'Review merge changes before executing merge.' })] }), isPreviewLoading ? ((0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2 rounded-md border p-3 text-sm text-muted-foreground", children: [(0, jsx_runtime_1.jsx)(lucide_react_1.Loader2, { className: "h-4 w-4 animate-spin" }), "Loading merge preview..."] })) : previewError ? ((0, jsx_runtime_1.jsx)("div", { className: "rounded-md border border-red-300 bg-red-50 p-3 text-sm text-red-700", children: previewError })) : preview ? ((0, jsx_runtime_1.jsxs)("div", { className: "space-y-3", children: [(0, jsx_runtime_1.jsxs)("div", { className: "grid gap-2 sm:grid-cols-3", children: [(0, jsx_runtime_1.jsx)(InfoCell, { label: "Ahead", value: String(preview.commitsAhead) }), (0, jsx_runtime_1.jsx)(InfoCell, { label: "Behind", value: String(preview.commitsBehind) }), (0, jsx_runtime_1.jsx)(InfoCell, { label: "Files Changed", value: String(preview.filesChanged) }), (0, jsx_runtime_1.jsx)(InfoCell, { label: "Insertions", value: String(preview.insertions) }), (0, jsx_runtime_1.jsx)(InfoCell, { label: "Deletions", value: String(preview.deletions) }), (0, jsx_runtime_1.jsx)(InfoCell, { label: "Conflicts", value: String(conflicts.length) })] }), conflicts.length > 0 && ((0, jsx_runtime_1.jsxs)("div", { className: "rounded-md border border-amber-300 bg-amber-50 p-3", children: [(0, jsx_runtime_1.jsx)("p", { className: "text-sm font-medium text-amber-800", children: "Conflicting files" }), (0, jsx_runtime_1.jsx)("ul", { className: "mt-2 space-y-1 text-sm text-amber-900", children: conflicts.map((conflict) => ((0, jsx_runtime_1.jsxs)("li", { className: "flex items-center gap-2", children: [(0, jsx_runtime_1.jsx)(lucide_react_1.FileWarning, { className: "h-4 w-4 shrink-0" }), (0, jsx_runtime_1.jsx)("span", { className: "font-mono text-xs", children: conflict.file })] }, `${conflict.type}:${conflict.file}`))) }), (0, jsx_runtime_1.jsx)("p", { className: "mt-2 text-xs text-amber-700", children: "Resolve conflicts manually or abort this merge attempt." })] })), preview.canMerge && ((0, jsx_runtime_1.jsx)("div", { className: "rounded-md border border-emerald-300 bg-emerald-50 p-3 text-sm text-emerald-800", children: "Merge can proceed cleanly." }))] })) : null, (0, jsx_runtime_1.jsxs)(dialog_1.DialogFooter, { children: [(0, jsx_runtime_1.jsx)(button_1.Button, { variant: "outline", onClick: () => onOpenChange(false), disabled: isMerging, children: "Abort" }), worktree && preview && !canMerge && ((0, jsx_runtime_1.jsxs)(button_1.Button, { variant: "secondary", onClick: () => void onResolveManually(worktree), disabled: isMerging, children: [(0, jsx_runtime_1.jsx)(lucide_react_1.FolderOpen, { className: "mr-2 h-4 w-4" }), "Resolve Manually"] })), worktree && preview && canMerge && ((0, jsx_runtime_1.jsxs)(button_1.Button, { variant: "default", onClick: () => void onConfirmMerge(worktree.id), disabled: isMerging, children: [isMerging && (0, jsx_runtime_1.jsx)(lucide_react_1.Loader2, { className: "mr-2 h-4 w-4 animate-spin" }), "Confirm Merge"] }))] })] }) }));
324
+ }
325
+ function DeleteWorktreeDialog({ open, onOpenChange, worktree, deleteBranch, onDeleteBranchChange, isDeleting, onConfirmDelete, }) {
326
+ return ((0, jsx_runtime_1.jsx)(dialog_1.Dialog, { open: open, onOpenChange: onOpenChange, children: (0, jsx_runtime_1.jsxs)(dialog_1.DialogContent, { children: [(0, jsx_runtime_1.jsxs)(dialog_1.DialogHeader, { children: [(0, jsx_runtime_1.jsx)(dialog_1.DialogTitle, { children: "Delete Worktree" }), (0, jsx_runtime_1.jsx)(dialog_1.DialogDescription, { children: worktree
327
+ ? `Delete worktree "${worktree.name}"? This action cannot be undone.`
328
+ : 'Delete this worktree? This action cannot be undone.' })] }), worktree && ((0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-3 rounded-md border p-3", children: [(0, jsx_runtime_1.jsx)(checkbox_1.Checkbox, { id: "delete-branch-checkbox", checked: deleteBranch, onCheckedChange: (checked) => onDeleteBranchChange(checked === true) }), (0, jsx_runtime_1.jsxs)(label_1.Label, { htmlFor: "delete-branch-checkbox", className: "text-sm font-normal", children: ["Also delete git branch ", (0, jsx_runtime_1.jsx)("span", { className: "font-mono", children: worktree.branchName })] })] })), (0, jsx_runtime_1.jsxs)(dialog_1.DialogFooter, { children: [(0, jsx_runtime_1.jsx)(button_1.Button, { variant: "outline", onClick: () => onOpenChange(false), disabled: isDeleting, children: "Cancel" }), (0, jsx_runtime_1.jsxs)(button_1.Button, { variant: "destructive", onClick: () => {
329
+ void onConfirmDelete();
330
+ }, disabled: isDeleting || !worktree, children: [isDeleting && (0, jsx_runtime_1.jsx)(lucide_react_1.Loader2, { className: "mr-2 h-4 w-4 animate-spin" }), "Delete Worktree"] })] })] }) }));
331
+ }
332
+ function OrchestratorApp({ ownerProjectId } = {}) {
333
+ const queryClient = (0, react_query_1.useQueryClient)();
334
+ const scopedWorktreesQueryKey = ['orchestrator-worktrees', ownerProjectId ?? null];
335
+ const scopedActivityQueryKey = [
336
+ 'orchestrator-worktree-activity',
337
+ ownerProjectId ?? null,
338
+ ];
339
+ const [activeTabId, setActiveTabId] = (0, react_1.useState)(OVERVIEW_TAB_ID);
340
+ const [createDialogOpen, setCreateDialogOpen] = (0, react_1.useState)(false);
341
+ const [actionError, setActionError] = (0, react_1.useState)(null);
342
+ const [actionInfo, setActionInfo] = (0, react_1.useState)(null);
343
+ const [mergeDialogWorktreeId, setMergeDialogWorktreeId] = (0, react_1.useState)(null);
344
+ const [deleteDialogWorktreeId, setDeleteDialogWorktreeId] = (0, react_1.useState)(null);
345
+ const [deleteBranch, setDeleteBranch] = (0, react_1.useState)(true);
346
+ const [deletingWorktreeIds, setDeletingWorktreeIds] = (0, react_1.useState)({});
347
+ const [deleteErrors, setDeleteErrors] = (0, react_1.useState)({});
348
+ const [mergeInProgressWorktreeId, setMergeInProgressWorktreeId] = (0, react_1.useState)(null);
349
+ const [dismissedMergedNoticeIds, setDismissedMergedNoticeIds] = (0, react_1.useState)([]);
350
+ const [mergeConflictMap, setMergeConflictMap] = (0, react_1.useState)({});
351
+ const worktreesQuery = (0, react_query_1.useQuery)({
352
+ queryKey: scopedWorktreesQueryKey,
353
+ queryFn: () => ownerProjectId
354
+ ? (0, worktrees_1.listWorktrees)({
355
+ ownerProjectId,
356
+ })
357
+ : (0, worktrees_1.listWorktrees)(),
358
+ refetchInterval: REFRESH_INTERVAL_MS,
359
+ refetchOnWindowFocus: true,
360
+ });
361
+ const overviewQuery = (0, react_query_1.useQuery)({
362
+ queryKey: ['orchestrator-worktree-overview', ownerProjectId ?? null],
363
+ queryFn: () => ownerProjectId
364
+ ? (0, worktrees_1.listWorktreeOverviews)({
365
+ ownerProjectId,
366
+ })
367
+ : (0, worktrees_1.listWorktreeOverviews)(),
368
+ enabled: activeTabId === OVERVIEW_TAB_ID,
369
+ refetchInterval: activeTabId === OVERVIEW_TAB_ID ? REFRESH_INTERVAL_MS : false,
370
+ refetchOnWindowFocus: true,
371
+ });
372
+ const activityQuery = (0, react_query_1.useQuery)({
373
+ queryKey: scopedActivityQueryKey,
374
+ queryFn: () => ownerProjectId
375
+ ? (0, worktrees_1.listWorktreeActivity)({
376
+ ownerProjectId,
377
+ })
378
+ : (0, worktrees_1.listWorktreeActivity)(),
379
+ enabled: activeTabId === OVERVIEW_TAB_ID,
380
+ refetchInterval: activeTabId === OVERVIEW_TAB_ID ? ACTIVITY_REFRESH_INTERVAL_MS : false,
381
+ refetchOnWindowFocus: true,
382
+ });
383
+ const templatesQuery = (0, react_query_1.useQuery)({
384
+ queryKey: ['orchestrator-worktree-templates'],
385
+ queryFn: worktrees_1.listTemplates,
386
+ enabled: createDialogOpen,
387
+ staleTime: 60_000,
388
+ });
389
+ const branchesQuery = (0, react_query_1.useQuery)({
390
+ queryKey: ['orchestrator-branches'],
391
+ queryFn: worktrees_1.listBranches,
392
+ enabled: createDialogOpen,
393
+ staleTime: 30_000,
394
+ });
395
+ const runtimeQuery = (0, react_query_1.useQuery)({
396
+ queryKey: ['orchestrator-runtime-info'],
397
+ queryFn: runtime_1.fetchRuntimeInfo,
398
+ staleTime: 60_000,
399
+ });
400
+ const createWorktreeMutation = (0, react_query_1.useMutation)({
401
+ mutationFn: worktrees_1.createWorktree,
402
+ onSuccess: (createdWorktree) => {
403
+ setCreateDialogOpen(false);
404
+ setActiveTabId(createdWorktree.id);
405
+ setActionError(null);
406
+ queryClient.setQueryData(scopedWorktreesQueryKey, (existing) => {
407
+ const items = existing ?? [];
408
+ const withoutCreated = items.filter((item) => item.id !== createdWorktree.id);
409
+ return [createdWorktree, ...withoutCreated];
410
+ });
411
+ void queryClient.invalidateQueries({ queryKey: ['orchestrator-worktrees'] });
412
+ void queryClient.invalidateQueries({ queryKey: ['orchestrator-worktree-overview'] });
413
+ void queryClient.invalidateQueries({ queryKey: ['orchestrator-worktree-activity'] });
414
+ },
415
+ });
416
+ const stopWorktreeMutation = (0, react_query_1.useMutation)({
417
+ mutationFn: worktrees_1.stopWorktree,
418
+ onSuccess: () => {
419
+ setActionError(null);
420
+ void queryClient.invalidateQueries({ queryKey: ['orchestrator-worktrees'] });
421
+ void queryClient.invalidateQueries({ queryKey: ['orchestrator-worktree-overview'] });
422
+ void queryClient.invalidateQueries({ queryKey: ['orchestrator-worktree-activity'] });
423
+ },
424
+ });
425
+ const deleteWorktreeMutation = (0, react_query_1.useMutation)({
426
+ mutationFn: ({ id, deleteBranch: shouldDeleteBranch }) => (0, worktrees_1.deleteWorktree)(id, { deleteBranch: shouldDeleteBranch }),
427
+ onSuccess: (_, variables) => {
428
+ if (activeTabId === variables.id) {
429
+ setActiveTabId(OVERVIEW_TAB_ID);
430
+ }
431
+ setActionError(null);
432
+ void queryClient.invalidateQueries({ queryKey: ['orchestrator-worktrees'] });
433
+ void queryClient.invalidateQueries({ queryKey: ['orchestrator-worktree-overview'] });
434
+ void queryClient.invalidateQueries({ queryKey: ['orchestrator-worktree-activity'] });
435
+ },
436
+ });
437
+ const mergeWorktreeMutation = (0, react_query_1.useMutation)({
438
+ mutationFn: worktrees_1.triggerMerge,
439
+ onMutate: async (worktreeId) => {
440
+ setMergeInProgressWorktreeId(worktreeId);
441
+ setActionError(null);
442
+ setActionInfo(null);
443
+ },
444
+ onSuccess: (mergedWorktree) => {
445
+ setMergeDialogWorktreeId(null);
446
+ setMergeConflictMap((current) => {
447
+ if (!current[mergedWorktree.id]) {
448
+ return current;
449
+ }
450
+ const next = { ...current };
451
+ delete next[mergedWorktree.id];
452
+ return next;
453
+ });
454
+ setDismissedMergedNoticeIds((current) => current.filter((id) => id !== mergedWorktree.id));
455
+ setActionError(null);
456
+ setActionInfo(`Merged "${mergedWorktree.name}". Keep or delete the worktree from its tab.`);
457
+ void queryClient.invalidateQueries({ queryKey: ['orchestrator-worktrees'] });
458
+ void queryClient.invalidateQueries({ queryKey: ['orchestrator-worktree-overview'] });
459
+ void queryClient.invalidateQueries({ queryKey: ['orchestrator-worktree-activity'] });
460
+ },
461
+ onError: (error, worktreeId) => {
462
+ if (isWorktreeApiError(error) && error.conflicts.length > 0) {
463
+ setMergeConflictMap((current) => ({ ...current, [worktreeId]: error.conflicts }));
464
+ }
465
+ setActionError(toErrorMessage(error));
466
+ },
467
+ onSettled: (_data, _error, worktreeId) => {
468
+ setMergeInProgressWorktreeId((current) => (current === worktreeId ? null : current));
469
+ },
470
+ });
471
+ const worktrees = worktreesQuery.data ?? [];
472
+ const overviewRows = overviewQuery.data ?? [];
473
+ const activityItems = activityQuery.data ?? [];
474
+ const templates = templatesQuery.data ?? [];
475
+ const selectedWorktree = (0, react_1.useMemo)(() => activeTabId === OVERVIEW_TAB_ID
476
+ ? null
477
+ : (worktrees.find((worktree) => worktree.id === activeTabId) ?? null), [activeTabId, worktrees]);
478
+ const selectedConflictFiles = (0, react_1.useMemo)(() => {
479
+ if (!selectedWorktree) {
480
+ return [];
481
+ }
482
+ const fromApiError = mergeConflictMap[selectedWorktree.id];
483
+ if (fromApiError && fromApiError.length > 0) {
484
+ return fromApiError;
485
+ }
486
+ return parseStoredMergeConflicts(selectedWorktree.mergeConflicts);
487
+ }, [mergeConflictMap, selectedWorktree]);
488
+ const mergeDialogWorktree = (0, react_1.useMemo)(() => mergeDialogWorktreeId
489
+ ? (worktrees.find((worktree) => worktree.id === mergeDialogWorktreeId) ?? null)
490
+ : null, [mergeDialogWorktreeId, worktrees]);
491
+ const deleteDialogWorktree = (0, react_1.useMemo)(() => deleteDialogWorktreeId
492
+ ? (worktrees.find((worktree) => worktree.id === deleteDialogWorktreeId) ?? null)
493
+ : null, [deleteDialogWorktreeId, worktrees]);
494
+ const mergePreviewQuery = (0, react_query_1.useQuery)({
495
+ queryKey: ['orchestrator-worktree-merge-preview', mergeDialogWorktreeId],
496
+ queryFn: async () => {
497
+ if (!mergeDialogWorktreeId) {
498
+ throw new Error('No worktree selected for merge preview');
499
+ }
500
+ return (0, worktrees_1.previewMerge)(mergeDialogWorktreeId);
501
+ },
502
+ enabled: Boolean(mergeDialogWorktreeId),
503
+ retry: false,
504
+ });
505
+ (0, react_1.useEffect)(() => {
506
+ const worktreeId = mergeDialogWorktreeId;
507
+ const preview = mergePreviewQuery.data;
508
+ if (!worktreeId || !preview || preview.conflicts.length > 0) {
509
+ return;
510
+ }
511
+ setMergeConflictMap((current) => {
512
+ if (!current[worktreeId]) {
513
+ return current;
514
+ }
515
+ const next = { ...current };
516
+ delete next[worktreeId];
517
+ return next;
518
+ });
519
+ queryClient.setQueryData(scopedWorktreesQueryKey, (existing) => {
520
+ if (!existing) {
521
+ return existing;
522
+ }
523
+ return existing.map((item) => item.id === worktreeId
524
+ ? {
525
+ ...item,
526
+ mergeConflicts: null,
527
+ }
528
+ : item);
529
+ });
530
+ }, [mergeDialogWorktreeId, mergePreviewQuery.data, queryClient, scopedWorktreesQueryKey]);
531
+ (0, react_1.useEffect)(() => {
532
+ if (worktrees.length === 0) {
533
+ setActiveTabId(OVERVIEW_TAB_ID);
534
+ return;
535
+ }
536
+ if (activeTabId !== OVERVIEW_TAB_ID &&
537
+ !worktrees.some((worktree) => worktree.id === activeTabId)) {
538
+ setActiveTabId(worktrees[0].id);
539
+ }
540
+ }, [activeTabId, worktrees]);
541
+ const baseBranchOptions = branchesQuery.data ?? [];
542
+ async function handleCreateWorktree(input) {
543
+ const resolvedOwnerProjectId = ownerProjectId?.trim();
544
+ if (!resolvedOwnerProjectId) {
545
+ throw new Error('Select a project before creating a worktree.');
546
+ }
547
+ await createWorktreeMutation.mutateAsync({
548
+ ...input,
549
+ ownerProjectId: resolvedOwnerProjectId,
550
+ });
551
+ }
552
+ async function handleStopWorktree(id) {
553
+ try {
554
+ await stopWorktreeMutation.mutateAsync(id);
555
+ setActionInfo(null);
556
+ }
557
+ catch (error) {
558
+ setActionError(toErrorMessage(error));
559
+ }
560
+ }
561
+ function handleOpenDeleteWorktreeDialog(worktree) {
562
+ setDeleteDialogWorktreeId(worktree.id);
563
+ setDeleteBranch(true);
564
+ if (deleteErrors[worktree.id]) {
565
+ setDeleteErrors((current) => {
566
+ const next = { ...current };
567
+ delete next[worktree.id];
568
+ return next;
569
+ });
570
+ }
571
+ setActionError(null);
572
+ setActionInfo(null);
573
+ }
574
+ async function handleDeleteWorktree() {
575
+ if (!deleteDialogWorktree) {
576
+ return;
577
+ }
578
+ const worktreeId = deleteDialogWorktree.id;
579
+ const shouldDeleteBranch = deleteBranch;
580
+ setDeleteDialogWorktreeId(null);
581
+ setDeleteBranch(true);
582
+ setActionInfo(null);
583
+ setDeletingWorktreeIds((current) => ({ ...current, [worktreeId]: true }));
584
+ if (deleteErrors[worktreeId]) {
585
+ setDeleteErrors((current) => {
586
+ const next = { ...current };
587
+ delete next[worktreeId];
588
+ return next;
589
+ });
590
+ }
591
+ deleteWorktreeMutation.mutate({
592
+ id: worktreeId,
593
+ deleteBranch: shouldDeleteBranch,
594
+ }, {
595
+ onError: (error) => {
596
+ setDeleteErrors((current) => ({
597
+ ...current,
598
+ [worktreeId]: toErrorMessage(error),
599
+ }));
600
+ },
601
+ onSettled: () => {
602
+ setDeletingWorktreeIds((current) => {
603
+ if (!current[worktreeId]) {
604
+ return current;
605
+ }
606
+ const next = { ...current };
607
+ delete next[worktreeId];
608
+ return next;
609
+ });
610
+ },
611
+ });
612
+ }
613
+ function handleOpenMergePreview(worktree) {
614
+ setMergeDialogWorktreeId(worktree.id);
615
+ setActionError(null);
616
+ setActionInfo(null);
617
+ }
618
+ async function handleMergeWorktree(id) {
619
+ try {
620
+ await mergeWorktreeMutation.mutateAsync(id);
621
+ }
622
+ catch (error) {
623
+ setActionError(toErrorMessage(error));
624
+ }
625
+ }
626
+ async function handleResolveManually(worktree) {
627
+ if (!worktree.worktreePath) {
628
+ setActionError('Cannot resolve manually: worktree path is unavailable.');
629
+ return;
630
+ }
631
+ const worktreePath = worktree.worktreePath;
632
+ const editorUri = `vscode://file/${encodeURI(worktreePath)}`;
633
+ let openedEditor = false;
634
+ try {
635
+ openedEditor = Boolean(window.open(editorUri, '_blank', 'noopener,noreferrer'));
636
+ }
637
+ catch {
638
+ openedEditor = false;
639
+ }
640
+ let copied = false;
641
+ if (navigator.clipboard && typeof navigator.clipboard.writeText === 'function') {
642
+ try {
643
+ await navigator.clipboard.writeText(worktreePath);
644
+ copied = true;
645
+ }
646
+ catch {
647
+ copied = false;
648
+ }
649
+ }
650
+ setActionError(null);
651
+ if (openedEditor && copied) {
652
+ setActionInfo('Opened editor and copied worktree path for manual conflict resolution.');
653
+ }
654
+ else if (openedEditor) {
655
+ setActionInfo('Opened worktree in editor for manual conflict resolution.');
656
+ }
657
+ else if (copied) {
658
+ setActionInfo('Worktree path copied. Open it in your editor to resolve conflicts.');
659
+ }
660
+ else {
661
+ setActionInfo(`Open your editor at: ${worktreePath}`);
662
+ }
663
+ }
664
+ async function handleAbortMerge(worktree) {
665
+ if (!worktree.worktreePath) {
666
+ setActionInfo('Merge aborted in UI. Resolve conflicts manually before retrying merge.');
667
+ setActionError(null);
668
+ setMergeDialogWorktreeId(null);
669
+ return;
670
+ }
671
+ const command = `git -C "${worktree.worktreePath}" merge --abort`;
672
+ let copied = false;
673
+ if (navigator.clipboard && typeof navigator.clipboard.writeText === 'function') {
674
+ try {
675
+ await navigator.clipboard.writeText(command);
676
+ copied = true;
677
+ }
678
+ catch {
679
+ copied = false;
680
+ }
681
+ }
682
+ if (copied) {
683
+ setActionInfo('Abort command copied. Run it in terminal to cancel in-progress merge state.');
684
+ }
685
+ else {
686
+ setActionInfo(`Run this command to abort merge: ${command}`);
687
+ }
688
+ setActionError(null);
689
+ setMergeDialogWorktreeId(null);
690
+ }
691
+ function handleKeepWorktree(id) {
692
+ setDismissedMergedNoticeIds((current) => (current.includes(id) ? current : [...current, id]));
693
+ setActionError(null);
694
+ setActionInfo('Keeping merged worktree.');
695
+ }
696
+ const selectedVisual = selectedWorktree
697
+ ? getDerivedStatus(selectedWorktree, mergeInProgressWorktreeId === selectedWorktree.id)
698
+ : null;
699
+ const selectedWorktreeId = selectedWorktree?.id ?? null;
700
+ const selectedIsDeleting = selectedWorktreeId
701
+ ? Boolean(deletingWorktreeIds[selectedWorktreeId])
702
+ : false;
703
+ const selectedDeleteError = selectedWorktreeId ? deleteErrors[selectedWorktreeId] : undefined;
704
+ const selectedIsMerged = String(selectedWorktree?.status ?? '').toLowerCase() === 'merged';
705
+ const showSelectedMergedNotice = Boolean(selectedWorktree) &&
706
+ selectedIsMerged &&
707
+ !dismissedMergedNoticeIds.includes(selectedWorktree?.id ?? '');
708
+ return ((0, jsx_runtime_1.jsxs)("main", { className: "min-h-screen bg-background text-foreground", children: [(0, jsx_runtime_1.jsxs)("div", { className: "mx-auto flex w-full max-w-7xl flex-col gap-4 p-4 sm:p-6", children: [(0, jsx_runtime_1.jsxs)("header", { className: "flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between", children: [(0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("p", { className: "text-xs uppercase tracking-[0.2em] text-muted-foreground", children: "Orchestrator" }), (0, jsx_runtime_1.jsx)("h1", { className: "text-2xl font-semibold", children: "Worktree Dashboard" })] }), (0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2", children: [(0, jsx_runtime_1.jsxs)(button_1.Button, { variant: "outline", size: "sm", onClick: () => worktreesQuery.refetch(), disabled: worktreesQuery.isLoading || worktreesQuery.isFetching, children: [(0, jsx_runtime_1.jsx)(lucide_react_1.RefreshCcw, { className: "mr-2 h-4 w-4" }), "Refresh"] }), (0, jsx_runtime_1.jsxs)(button_1.Button, { size: "sm", onClick: () => setCreateDialogOpen(true), children: [(0, jsx_runtime_1.jsx)(lucide_react_1.Plus, { className: "mr-2 h-4 w-4" }), "New Worktree"] })] })] }), (0, jsx_runtime_1.jsx)(card_1.Card, { children: (0, jsx_runtime_1.jsx)(card_1.CardContent, { className: "p-3", children: (0, jsx_runtime_1.jsxs)("div", { className: "flex gap-2 overflow-x-auto pb-1", children: [(0, jsx_runtime_1.jsxs)("button", { type: "button", onClick: () => setActiveTabId(OVERVIEW_TAB_ID), className: (0, utils_1.cn)('inline-flex min-w-max items-center gap-2 rounded-md border px-3 py-2 text-sm transition-colors', activeTabId === OVERVIEW_TAB_ID
709
+ ? 'border-primary bg-primary/10 text-primary'
710
+ : 'border-border bg-card hover:bg-accent hover:text-accent-foreground'), children: [(0, jsx_runtime_1.jsx)("span", { className: "text-base leading-none", children: "\u25EB" }), (0, jsx_runtime_1.jsx)("span", { className: "font-medium", children: "Overview" })] }), worktrees.map((worktree) => {
711
+ const visual = getDerivedStatus(worktree, mergeInProgressWorktreeId === worktree.id);
712
+ const selected = activeTabId === worktree.id;
713
+ return ((0, jsx_runtime_1.jsxs)("button", { type: "button", onClick: () => setActiveTabId(worktree.id), className: (0, utils_1.cn)('inline-flex min-w-max items-center gap-2 rounded-md border px-3 py-2 text-sm transition-colors', selected
714
+ ? 'border-primary bg-primary/10 text-primary'
715
+ : 'border-border bg-card hover:bg-accent hover:text-accent-foreground'), children: [(0, jsx_runtime_1.jsx)("span", { className: (0, utils_1.cn)('text-base leading-none', visual.iconClassName), children: visual.icon }), (0, jsx_runtime_1.jsx)("span", { className: "font-medium", children: worktree.name })] }, worktree.id));
716
+ }), worktrees.length === 0 && ((0, jsx_runtime_1.jsx)("p", { className: "px-2 py-2 text-sm text-muted-foreground", children: "No worktrees available yet." }))] }) }) }), worktreesQuery.error instanceof Error && ((0, jsx_runtime_1.jsx)(card_1.Card, { className: "border-red-300 bg-red-50/60 dark:bg-red-950/20", children: (0, jsx_runtime_1.jsxs)(card_1.CardContent, { className: "flex items-start gap-3 p-4", children: [(0, jsx_runtime_1.jsx)(lucide_react_1.AlertCircle, { className: "mt-0.5 h-4 w-4 text-red-600" }), (0, jsx_runtime_1.jsx)("p", { className: "text-sm text-red-700 dark:text-red-300", children: worktreesQuery.error.message })] }) })), actionError && ((0, jsx_runtime_1.jsx)(card_1.Card, { className: "border-red-300 bg-red-50/60 dark:bg-red-950/20", children: (0, jsx_runtime_1.jsxs)(card_1.CardContent, { className: "flex items-start gap-3 p-4", children: [(0, jsx_runtime_1.jsx)(lucide_react_1.AlertCircle, { className: "mt-0.5 h-4 w-4 text-red-600" }), (0, jsx_runtime_1.jsx)("p", { className: "text-sm text-red-700 dark:text-red-300", children: actionError })] }) })), actionInfo && ((0, jsx_runtime_1.jsx)(card_1.Card, { className: "border-emerald-300 bg-emerald-50/70", children: (0, jsx_runtime_1.jsxs)(card_1.CardContent, { className: "flex items-start gap-3 p-4", children: [(0, jsx_runtime_1.jsx)(lucide_react_1.CheckCircle2, { className: "mt-0.5 h-4 w-4 text-emerald-700" }), (0, jsx_runtime_1.jsx)("p", { className: "text-sm text-emerald-800", children: actionInfo })] }) })), activeTabId === OVERVIEW_TAB_ID ? ((0, jsx_runtime_1.jsxs)("div", { className: "grid gap-4 lg:grid-cols-[2fr_1fr]", children: [(0, jsx_runtime_1.jsxs)(card_1.Card, { children: [(0, jsx_runtime_1.jsxs)(card_1.CardHeader, { className: "space-y-3", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center justify-between", children: [(0, jsx_runtime_1.jsx)(card_1.CardTitle, { className: "text-base", children: "Worktree Overview" }), overviewQuery.isFetching && ((0, jsx_runtime_1.jsx)("p", { className: "text-xs text-muted-foreground", children: "Refreshing overview..." }))] }), (0, jsx_runtime_1.jsx)(separator_1.Separator, {})] }), (0, jsx_runtime_1.jsx)(card_1.CardContent, { children: overviewQuery.isLoading ? ((0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2 text-sm text-muted-foreground", children: [(0, jsx_runtime_1.jsx)(lucide_react_1.Loader2, { className: "h-4 w-4 animate-spin" }), "Loading overview data..."] })) : overviewQuery.error instanceof Error ? ((0, jsx_runtime_1.jsx)("p", { className: "text-sm text-red-700 dark:text-red-300", children: overviewQuery.error.message })) : overviewRows.length === 0 ? ((0, jsx_runtime_1.jsx)("p", { className: "text-sm text-muted-foreground", children: "No worktree overview data available." })) : ((0, jsx_runtime_1.jsx)("div", { className: "grid gap-3 md:grid-cols-2", children: overviewRows.map((overview) => {
717
+ const worktree = overview.worktree;
718
+ const isMergeInProgress = mergeInProgressWorktreeId === worktree.id;
719
+ const visual = getDerivedStatus(worktree, isMergeInProgress);
720
+ const normalizedStatus = String(worktree.status).toLowerCase();
721
+ const isDeleting = Boolean(deletingWorktreeIds[worktree.id]);
722
+ const deleteError = deleteErrors[worktree.id];
723
+ const isMerged = normalizedStatus === 'merged';
724
+ const stopDisabled = ['stopped', 'merged', 'creating'].includes(normalizedStatus);
725
+ const mergeDisabled = ['merged', 'creating'].includes(normalizedStatus);
726
+ return ((0, jsx_runtime_1.jsxs)("div", { className: "space-y-2", children: [(0, jsx_runtime_1.jsxs)(card_1.Card, { "aria-busy": isDeleting || undefined, className: (0, utils_1.cn)('relative border-border/80', isDeleting && 'opacity-70'), children: [isDeleting ? ((0, jsx_runtime_1.jsx)("div", { className: "absolute inset-0 z-10 flex items-center justify-center bg-background/60", children: (0, jsx_runtime_1.jsx)(lucide_react_1.Loader2, { className: "h-5 w-5 animate-spin text-muted-foreground" }) })) : null, (0, jsx_runtime_1.jsxs)(card_1.CardHeader, { className: "space-y-3", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-start justify-between gap-2", children: [(0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)(card_1.CardTitle, { className: "text-base", children: worktree.name }), (0, jsx_runtime_1.jsx)("p", { className: "text-sm text-muted-foreground", children: worktree.branchName })] }), (0, jsx_runtime_1.jsxs)("div", { className: "flex flex-wrap items-center justify-end gap-2", children: [(0, jsx_runtime_1.jsxs)(badge_1.Badge, { variant: "outline", className: (0, utils_1.cn)('font-medium', visual.iconClassName), children: [visual.icon, " ", visual.label] }), (0, jsx_runtime_1.jsx)(badge_1.Badge, { variant: "outline", className: (0, utils_1.cn)('font-medium', getRuntimeTypeBadgeClassName(worktree.runtimeType)), children: getRuntimeTypeLabel(worktree.runtimeType) })] })] }), (0, jsx_runtime_1.jsx)(separator_1.Separator, {}), (0, jsx_runtime_1.jsxs)("div", { className: "grid grid-cols-2 gap-2", children: [(0, jsx_runtime_1.jsx)(InfoCell, { label: "Template", value: worktree.templateSlug }), (0, jsx_runtime_1.jsx)(InfoCell, { label: "Epic Progress", value: overview.epics.total === null || overview.epics.done === null
727
+ ? '--'
728
+ : `${overview.epics.done}/${overview.epics.total}` }), (0, jsx_runtime_1.jsx)(InfoCell, { label: "Agents", value: overview.agents.total === null
729
+ ? '--'
730
+ : String(overview.agents.total) }), (0, jsx_runtime_1.jsx)(InfoCell, { label: "Ahead/Behind", value: `${formatMaybeCount(worktree.commitsAhead)} / ${formatMaybeCount(worktree.commitsBehind)}` })] }), (0, jsx_runtime_1.jsxs)("p", { className: "text-xs text-muted-foreground", children: ["Updated ", formatTimestamp(overview.fetchedAt)] }), (0, jsx_runtime_1.jsxs)("div", { className: "flex flex-wrap gap-2", children: [(0, jsx_runtime_1.jsx)(button_1.Button, { size: "sm", variant: "outline", disabled: isDeleting, onClick: () => setActiveTabId(worktree.id), children: "Open" }), (0, jsx_runtime_1.jsx)(button_1.Button, { size: "sm", variant: "outline", disabled: stopDisabled || isDeleting, onClick: () => void handleStopWorktree(worktree.id), children: "Stop" }), isMerged ? ((0, jsx_runtime_1.jsx)(button_1.Button, { size: "sm", variant: "secondary", disabled: isDeleting, onClick: () => handleKeepWorktree(worktree.id), children: "Keep Worktree" })) : ((0, jsx_runtime_1.jsx)(button_1.Button, { size: "sm", variant: "secondary", disabled: mergeDisabled || isMergeInProgress || isDeleting, onClick: () => handleOpenMergePreview(worktree), children: "Merge" })), (0, jsx_runtime_1.jsx)(button_1.Button, { size: "sm", variant: "destructive", disabled: isDeleting, onClick: () => handleOpenDeleteWorktreeDialog(worktree), children: "Delete" })] })] })] }), deleteError ? ((0, jsx_runtime_1.jsx)("p", { className: "text-xs text-destructive", children: deleteError })) : null] }, worktree.id));
731
+ }) })) })] }), (0, jsx_runtime_1.jsxs)(card_1.Card, { children: [(0, jsx_runtime_1.jsxs)(card_1.CardHeader, { className: "space-y-3", children: [(0, jsx_runtime_1.jsx)(card_1.CardTitle, { className: "text-base", children: "Lifecycle Activity" }), (0, jsx_runtime_1.jsx)(separator_1.Separator, {})] }), (0, jsx_runtime_1.jsxs)(card_1.CardContent, { children: [activityQuery.isLoading ? ((0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2 text-sm text-muted-foreground", children: [(0, jsx_runtime_1.jsx)(lucide_react_1.Loader2, { className: "h-4 w-4 animate-spin" }), "Loading activity..."] })) : activityItems.length === 0 ? ((0, jsx_runtime_1.jsx)("p", { className: "text-sm text-muted-foreground", children: "No activity yet." })) : ((0, jsx_runtime_1.jsx)("div", { className: "space-y-3", children: activityItems.map((item) => {
732
+ const visual = getActivityIconVisual(item.type);
733
+ return ((0, jsx_runtime_1.jsx)("div", { className: "rounded-md border p-3", children: (0, jsx_runtime_1.jsxs)("div", { className: "flex items-start gap-2", children: [(0, jsx_runtime_1.jsx)("span", { className: (0, utils_1.cn)('mt-0.5', visual.className), children: visual.icon }), (0, jsx_runtime_1.jsxs)("div", { className: "min-w-0", children: [(0, jsx_runtime_1.jsx)("p", { className: "text-sm font-medium", children: item.message }), (0, jsx_runtime_1.jsx)("p", { className: "mt-1 text-xs text-muted-foreground", children: item.worktreeName }), (0, jsx_runtime_1.jsx)("p", { className: "mt-1 text-xs text-muted-foreground", title: formatTimestamp(item.publishedAt), children: formatRelativeTimestamp(item.publishedAt) })] })] }) }, item.id));
734
+ }) })), activityQuery.error instanceof Error && ((0, jsx_runtime_1.jsx)("p", { className: "mt-3 text-sm text-red-700 dark:text-red-300", children: activityQuery.error.message }))] })] })] })) : ((0, jsx_runtime_1.jsxs)(card_1.Card, { children: [(0, jsx_runtime_1.jsxs)(card_1.CardHeader, { className: "space-y-4", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2", children: [(0, jsx_runtime_1.jsx)(lucide_react_1.GitBranch, { className: "h-4 w-4 text-muted-foreground" }), (0, jsx_runtime_1.jsx)(card_1.CardTitle, { className: "text-base", children: selectedWorktree ? selectedWorktree.branchName : 'Select a worktree' })] }), selectedWorktree && ((0, jsx_runtime_1.jsxs)("div", { className: "flex flex-wrap items-center gap-2", children: [(0, jsx_runtime_1.jsxs)(badge_1.Badge, { variant: "outline", className: (0, utils_1.cn)('font-medium', selectedVisual?.iconClassName), children: [selectedVisual?.icon, " ", selectedVisual?.label] }), (0, jsx_runtime_1.jsx)(badge_1.Badge, { variant: "outline", className: (0, utils_1.cn)('font-medium', getRuntimeTypeBadgeClassName(selectedWorktree.runtimeType)), children: getRuntimeTypeLabel(selectedWorktree.runtimeType) })] }))] }), (0, jsx_runtime_1.jsx)(separator_1.Separator, {}), (0, jsx_runtime_1.jsxs)("div", { className: "grid gap-3 sm:grid-cols-2 lg:grid-cols-5", children: [(0, jsx_runtime_1.jsx)(InfoCell, { label: "Branch", value: selectedWorktree?.branchName ?? '--' }), (0, jsx_runtime_1.jsx)(InfoCell, { label: "Base", value: selectedWorktree?.baseBranch ?? '--' }), (0, jsx_runtime_1.jsx)(InfoCell, { label: "Agent Count", value: selectedWorktree?.devchainProjectId ? '1' : '0' }), (0, jsx_runtime_1.jsx)(InfoCell, { label: "Commits Ahead", value: formatMaybeCount(selectedWorktree?.commitsAhead ?? null) }), (0, jsx_runtime_1.jsx)(InfoCell, { label: "Commits Behind", value: formatMaybeCount(selectedWorktree?.commitsBehind ?? null) })] }), (0, jsx_runtime_1.jsxs)("div", { className: "flex flex-wrap gap-2", children: [selectedWorktree && selectedIsMerged ? ((0, jsx_runtime_1.jsx)(button_1.Button, { size: "sm", variant: "secondary", onClick: () => handleKeepWorktree(selectedWorktree.id), children: "Keep Worktree" })) : ((0, jsx_runtime_1.jsx)(button_1.Button, { size: "sm", variant: "secondary", disabled: !selectedWorktree ||
735
+ selectedWorktree.status === 'merged' ||
736
+ mergeInProgressWorktreeId === selectedWorktree.id, onClick: () => selectedWorktree && handleOpenMergePreview(selectedWorktree), children: "Merge" })), (0, jsx_runtime_1.jsx)(button_1.Button, { size: "sm", variant: "outline", disabled: !selectedWorktree || selectedWorktree.status === 'stopped', onClick: () => selectedWorktree && void handleStopWorktree(selectedWorktree.id), children: "Stop" }), selectedWorktree && selectedIsMerged && ((0, jsx_runtime_1.jsxs)(button_1.Button, { size: "sm", variant: "destructive", disabled: selectedIsDeleting, onClick: () => handleOpenDeleteWorktreeDialog(selectedWorktree), children: [selectedIsDeleting ? (0, jsx_runtime_1.jsx)(lucide_react_1.Loader2, { className: "mr-2 h-4 w-4 animate-spin" }) : null, selectedIsDeleting ? 'Deleting...' : 'Delete Worktree'] }))] })] }), (0, jsx_runtime_1.jsxs)(card_1.CardContent, { children: [selectedDeleteError ? ((0, jsx_runtime_1.jsx)("p", { className: "mb-3 text-xs text-destructive", children: selectedDeleteError })) : null, showSelectedMergedNotice && selectedWorktree && ((0, jsx_runtime_1.jsxs)("div", { className: "mb-4 rounded-md border border-emerald-300 bg-emerald-50 p-3", children: [(0, jsx_runtime_1.jsx)("p", { className: "text-sm font-medium text-emerald-800", children: "This worktree is merged. Keep it for reference or delete it now." }), (0, jsx_runtime_1.jsxs)("div", { className: "mt-3 flex flex-wrap gap-2", children: [(0, jsx_runtime_1.jsx)(button_1.Button, { size: "sm", variant: "secondary", onClick: () => handleKeepWorktree(selectedWorktree.id), children: "Keep Worktree" }), (0, jsx_runtime_1.jsx)(button_1.Button, { size: "sm", variant: "destructive", disabled: selectedIsDeleting, onClick: () => handleOpenDeleteWorktreeDialog(selectedWorktree), children: "Delete Worktree" })] })] })), selectedWorktree && selectedConflictFiles.length > 0 && ((0, jsx_runtime_1.jsxs)("div", { className: "mb-4 rounded-md border border-amber-300 bg-amber-50 p-3", children: [(0, jsx_runtime_1.jsx)("p", { className: "text-sm font-medium text-amber-900", children: "Merge conflicts detected" }), (0, jsx_runtime_1.jsx)("ul", { className: "mt-2 space-y-1 text-sm text-amber-900", children: selectedConflictFiles.map((conflict) => ((0, jsx_runtime_1.jsxs)("li", { className: "flex items-center gap-2", children: [(0, jsx_runtime_1.jsx)(lucide_react_1.FileWarning, { className: "h-4 w-4 shrink-0" }), (0, jsx_runtime_1.jsx)("span", { className: "font-mono text-xs", children: conflict.file })] }, `${conflict.type}:${conflict.file}`))) }), (0, jsx_runtime_1.jsxs)("div", { className: "mt-3 flex flex-wrap gap-2", children: [(0, jsx_runtime_1.jsxs)(button_1.Button, { size: "sm", variant: "secondary", onClick: () => void handleResolveManually(selectedWorktree), children: [(0, jsx_runtime_1.jsx)(lucide_react_1.FolderOpen, { className: "mr-2 h-4 w-4" }), "Resolve Manually"] }), (0, jsx_runtime_1.jsx)(button_1.Button, { size: "sm", variant: "outline", onClick: () => void handleAbortMerge(selectedWorktree), children: "Abort Merge" })] })] })), (0, jsx_runtime_1.jsx)("div", { className: "rounded-lg border border-dashed border-border p-6 text-sm text-muted-foreground", children: selectedWorktree
737
+ ? `Proxy content area for "${selectedWorktree.name}" will mount here in Proxy module implementation.`
738
+ : 'Select a worktree tab to view container information and controls.' })] })] }))] }), (0, jsx_runtime_1.jsx)(CreateWorktreeDialog, { open: createDialogOpen, onOpenChange: setCreateDialogOpen, templates: templates, baseBranchOptions: baseBranchOptions, isBranchesLoading: branchesQuery.isLoading || (branchesQuery.isFetching && !branchesQuery.data), branchesError: branchesQuery.error instanceof Error ? branchesQuery.error.message : null, isTemplatesLoading: templatesQuery.isLoading || (templatesQuery.isFetching && !templatesQuery.data), templatesError: templatesQuery.error instanceof Error ? templatesQuery.error.message : null, dockerAvailable: runtimeQuery.data?.dockerAvailable ?? false, isSubmitting: createWorktreeMutation.isPending, onSubmit: handleCreateWorktree }), (0, jsx_runtime_1.jsx)(MergePreviewDialog, { open: Boolean(mergeDialogWorktreeId), onOpenChange: (value) => {
739
+ if (!value) {
740
+ setMergeDialogWorktreeId(null);
741
+ }
742
+ }, worktree: mergeDialogWorktree, preview: mergePreviewQuery.data ?? null, isPreviewLoading: mergePreviewQuery.isFetching || mergePreviewQuery.isLoading, previewError: mergePreviewQuery.error instanceof Error ? mergePreviewQuery.error.message : null, isMerging: mergeWorktreeMutation.isPending, onConfirmMerge: handleMergeWorktree, onResolveManually: handleResolveManually }), (0, jsx_runtime_1.jsx)(DeleteWorktreeDialog, { open: Boolean(deleteDialogWorktreeId), onOpenChange: (value) => {
743
+ if (!value) {
744
+ setDeleteDialogWorktreeId(null);
745
+ setDeleteBranch(true);
746
+ }
747
+ }, worktree: deleteDialogWorktree, deleteBranch: deleteBranch, onDeleteBranchChange: setDeleteBranch, isDeleting: deleteDialogWorktree ? Boolean(deletingWorktreeIds[deleteDialogWorktree.id]) : false, onConfirmDelete: handleDeleteWorktree })] }));
748
+ }
749
+ function InfoCell({ label, value }) {
750
+ return ((0, jsx_runtime_1.jsxs)("div", { className: "rounded-md border bg-card p-3", children: [(0, jsx_runtime_1.jsx)("p", { className: "text-xs uppercase tracking-[0.12em] text-muted-foreground", children: label }), (0, jsx_runtime_1.jsx)("p", { className: "mt-1 text-sm font-medium", children: value })] }));
751
+ }
752
+ //# sourceMappingURL=orchestrator-app.js.map