@shepai/cli 1.72.6 → 1.72.7

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 (244) hide show
  1. package/dist/packages/core/src/application/use-cases/features/delete-feature.use-case.d.ts +4 -0
  2. package/dist/packages/core/src/application/use-cases/features/delete-feature.use-case.d.ts.map +1 -1
  3. package/dist/packages/core/src/application/use-cases/features/delete-feature.use-case.js +20 -12
  4. package/dist/packages/core/src/application/use-cases/repositories/delete-repository.use-case.d.ts +8 -3
  5. package/dist/packages/core/src/application/use-cases/repositories/delete-repository.use-case.d.ts.map +1 -1
  6. package/dist/packages/core/src/application/use-cases/repositories/delete-repository.use-case.js +17 -4
  7. package/dist/packages/core/src/infrastructure/repositories/sqlite-feature.repository.js +1 -1
  8. package/dist/src/presentation/web/app/(dashboard)/get-graph-data.d.ts.map +1 -1
  9. package/dist/src/presentation/web/app/(dashboard)/get-graph-data.js +2 -6
  10. package/dist/src/presentation/web/app/build-graph-nodes.js +11 -1
  11. package/dist/src/presentation/web/components/common/base-drawer/base-drawer.d.ts +3 -1
  12. package/dist/src/presentation/web/components/common/base-drawer/base-drawer.d.ts.map +1 -1
  13. package/dist/src/presentation/web/components/common/base-drawer/base-drawer.js +8 -4
  14. package/dist/src/presentation/web/components/common/control-center-drawer/create-drawer-client.d.ts.map +1 -1
  15. package/dist/src/presentation/web/components/common/control-center-drawer/create-drawer-client.js +12 -3
  16. package/dist/src/presentation/web/components/common/control-center-drawer/feature-drawer-client.d.ts.map +1 -1
  17. package/dist/src/presentation/web/components/common/control-center-drawer/feature-drawer-client.js +6 -2
  18. package/dist/src/presentation/web/components/common/drawer-action-bar/drawer-action-bar.d.ts.map +1 -1
  19. package/dist/src/presentation/web/components/common/drawer-action-bar/drawer-action-bar.js +1 -1
  20. package/dist/src/presentation/web/components/common/feature-create-drawer/feature-create-drawer.d.ts.map +1 -1
  21. package/dist/src/presentation/web/components/common/feature-create-drawer/feature-create-drawer.js +1 -1
  22. package/dist/src/presentation/web/components/common/feature-node/feature-node.d.ts.map +1 -1
  23. package/dist/src/presentation/web/components/common/feature-node/feature-node.js +7 -2
  24. package/dist/src/presentation/web/components/common/repository-node/repository-node.d.ts.map +1 -1
  25. package/dist/src/presentation/web/components/common/repository-node/repository-node.js +6 -2
  26. package/dist/src/presentation/web/components/features/control-center/control-center-inner.d.ts.map +1 -1
  27. package/dist/src/presentation/web/components/features/control-center/control-center-inner.js +14 -2
  28. package/dist/src/presentation/web/components/features/control-center/use-control-center-state.d.ts +3 -5
  29. package/dist/src/presentation/web/components/features/control-center/use-control-center-state.d.ts.map +1 -1
  30. package/dist/src/presentation/web/components/features/control-center/use-control-center-state.js +131 -196
  31. package/dist/src/presentation/web/components/ui/alert-dialog.d.ts +1 -1
  32. package/dist/src/presentation/web/components/ui/alert-dialog.d.ts.map +1 -1
  33. package/dist/src/presentation/web/components/ui/alert-dialog.js +7 -2
  34. package/dist/src/presentation/web/components/ui/dialog.d.ts.map +1 -1
  35. package/dist/src/presentation/web/components/ui/dialog.js +6 -1
  36. package/dist/src/presentation/web/lib/layout-with-dagre.d.ts +2 -0
  37. package/dist/src/presentation/web/lib/layout-with-dagre.d.ts.map +1 -1
  38. package/dist/src/presentation/web/lib/layout-with-dagre.js +86 -4
  39. package/dist/tsconfig.build.tsbuildinfo +1 -1
  40. package/package.json +1 -1
  41. package/web/.next/BUILD_ID +1 -1
  42. package/web/.next/build-manifest.json +2 -2
  43. package/web/.next/cache/.previewinfo +1 -1
  44. package/web/.next/cache/.rscinfo +1 -1
  45. package/web/.next/cache/.tsbuildinfo +1 -1
  46. package/web/.next/cache/config.json +3 -3
  47. package/web/.next/fallback-build-manifest.json +2 -2
  48. package/web/.next/prerender-manifest.json +3 -3
  49. package/web/.next/required-server-files.js +1 -1
  50. package/web/.next/required-server-files.json +1 -1
  51. package/web/.next/server/app/(dashboard)/@drawer/create/page/server-reference-manifest.json +14 -14
  52. package/web/.next/server/app/(dashboard)/@drawer/create/page.js.nft.json +1 -1
  53. package/web/.next/server/app/(dashboard)/@drawer/create/page_client-reference-manifest.js +1 -1
  54. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page/server-reference-manifest.json +17 -17
  55. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page.js.nft.json +1 -1
  56. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page_client-reference-manifest.js +1 -1
  57. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page/server-reference-manifest.json +12 -12
  58. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page.js.nft.json +1 -1
  59. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page_client-reference-manifest.js +1 -1
  60. package/web/.next/server/app/(dashboard)/create/page/server-reference-manifest.json +14 -14
  61. package/web/.next/server/app/(dashboard)/create/page.js.nft.json +1 -1
  62. package/web/.next/server/app/(dashboard)/create/page_client-reference-manifest.js +1 -1
  63. package/web/.next/server/app/(dashboard)/feature/[featureId]/page/server-reference-manifest.json +17 -17
  64. package/web/.next/server/app/(dashboard)/feature/[featureId]/page.js.nft.json +1 -1
  65. package/web/.next/server/app/(dashboard)/feature/[featureId]/page_client-reference-manifest.js +1 -1
  66. package/web/.next/server/app/(dashboard)/page/server-reference-manifest.json +12 -12
  67. package/web/.next/server/app/(dashboard)/page.js.nft.json +1 -1
  68. package/web/.next/server/app/(dashboard)/page_client-reference-manifest.js +1 -1
  69. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page/server-reference-manifest.json +12 -12
  70. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page.js.nft.json +1 -1
  71. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page_client-reference-manifest.js +1 -1
  72. package/web/.next/server/app/_global-error.html +2 -2
  73. package/web/.next/server/app/_global-error.rsc +1 -1
  74. package/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  75. package/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  76. package/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  77. package/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  78. package/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  79. package/web/.next/server/app/_not-found/page/server-reference-manifest.json +1 -1
  80. package/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  81. package/web/.next/server/app/skills/page/server-reference-manifest.json +6 -6
  82. package/web/.next/server/app/skills/page_client-reference-manifest.js +1 -1
  83. package/web/.next/server/app/tools/page/server-reference-manifest.json +1 -1
  84. package/web/.next/server/app/tools/page_client-reference-manifest.js +1 -1
  85. package/web/.next/server/app/version/page/server-reference-manifest.json +1 -1
  86. package/web/.next/server/app/version/page_client-reference-manifest.js +1 -1
  87. package/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_create-drawer-client_tsx_5e26fc0a._.js +1 -1
  88. package/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_create-drawer-client_tsx_5e26fc0a._.js.map +1 -1
  89. package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_@drawer_repository_[repositoryId]_page_actions_2b7834f6.js +1 -1
  90. package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_@drawer_repository_[repositoryId]_page_actions_2b7834f6.js.map +1 -1
  91. package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_repository_[repositoryId]_page_actions_6923c575.js +1 -1
  92. package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_repository_[repositoryId]_page_actions_6923c575.js.map +1 -1
  93. package/web/.next/server/chunks/ssr/[root-of-the-server]__07385073._.js +2 -2
  94. package/web/.next/server/chunks/ssr/[root-of-the-server]__07385073._.js.map +1 -1
  95. package/web/.next/server/chunks/ssr/[root-of-the-server]__08ba9bd3._.js +1 -1
  96. package/web/.next/server/chunks/ssr/[root-of-the-server]__08ba9bd3._.js.map +1 -1
  97. package/web/.next/server/chunks/ssr/[root-of-the-server]__249c74f6._.js +1 -1
  98. package/web/.next/server/chunks/ssr/[root-of-the-server]__6b17a22d._.js +1 -1
  99. package/web/.next/server/chunks/ssr/[root-of-the-server]__6b17a22d._.js.map +1 -1
  100. package/web/.next/server/chunks/ssr/[root-of-the-server]__6bb00d90._.js +1 -1
  101. package/web/.next/server/chunks/ssr/[root-of-the-server]__6bb00d90._.js.map +1 -1
  102. package/web/.next/server/chunks/ssr/[root-of-the-server]__6db85a66._.js +2 -2
  103. package/web/.next/server/chunks/ssr/[root-of-the-server]__804c006d._.js +1 -1
  104. package/web/.next/server/chunks/ssr/[root-of-the-server]__804c006d._.js.map +1 -1
  105. package/web/.next/server/chunks/ssr/[root-of-the-server]__8fcb9132._.js +2 -2
  106. package/web/.next/server/chunks/ssr/_00e6c698._.js +1 -1
  107. package/web/.next/server/chunks/ssr/_00e6c698._.js.map +1 -1
  108. package/web/.next/server/chunks/ssr/_07c2a32a._.js +1 -1
  109. package/web/.next/server/chunks/ssr/_07c2a32a._.js.map +1 -1
  110. package/web/.next/server/chunks/ssr/_34a58db8._.js +1 -1
  111. package/web/.next/server/chunks/ssr/_34a58db8._.js.map +1 -1
  112. package/web/.next/server/chunks/ssr/_37259405._.js +1 -1
  113. package/web/.next/server/chunks/ssr/_37259405._.js.map +1 -1
  114. package/web/.next/server/chunks/ssr/{_85d0351b._.js → _63bfa7dd._.js} +2 -2
  115. package/web/.next/server/chunks/ssr/_63bfa7dd._.js.map +1 -0
  116. package/web/.next/{standalone/src/presentation/web/.next/server/chunks/ssr/_e50484ec._.js → server/chunks/ssr/_7215bb0f._.js} +2 -2
  117. package/web/.next/server/chunks/ssr/{_e50484ec._.js.map → _7215bb0f._.js.map} +1 -1
  118. package/web/.next/server/chunks/ssr/_cb5b3951._.js +1 -1
  119. package/web/.next/server/chunks/ssr/_cb5b3951._.js.map +1 -1
  120. package/web/.next/server/chunks/ssr/_fc3a6895._.js +1 -1
  121. package/web/.next/server/chunks/ssr/_fc3a6895._.js.map +1 -1
  122. package/web/.next/server/chunks/ssr/src_presentation_web_1a32dbcb._.js +2 -2
  123. package/web/.next/server/chunks/ssr/src_presentation_web_1a32dbcb._.js.map +1 -1
  124. package/web/.next/server/chunks/ssr/src_presentation_web_398553b0._.js +1 -1
  125. package/web/.next/server/chunks/ssr/src_presentation_web_398553b0._.js.map +1 -1
  126. package/web/.next/server/chunks/ssr/src_presentation_web_5c87e8e4._.js +1 -1
  127. package/web/.next/server/chunks/ssr/src_presentation_web_5c87e8e4._.js.map +1 -1
  128. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_f4952172.js +1 -1
  129. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_f4952172.js.map +1 -1
  130. package/web/.next/server/chunks/ssr/src_presentation_web_c1bc6240._.js +2 -2
  131. package/web/.next/server/chunks/ssr/src_presentation_web_c1bc6240._.js.map +1 -1
  132. package/web/.next/server/chunks/ssr/src_presentation_web_ca99d62d._.js +1 -1
  133. package/web/.next/server/chunks/ssr/src_presentation_web_ca99d62d._.js.map +1 -1
  134. package/web/.next/server/chunks/ssr/src_presentation_web_components_features_control-center_7ac3562e._.js +1 -1
  135. package/web/.next/server/chunks/ssr/src_presentation_web_components_features_control-center_7ac3562e._.js.map +1 -1
  136. package/web/.next/server/pages/500.html +2 -2
  137. package/web/.next/server/server-reference-manifest.js +1 -1
  138. package/web/.next/server/server-reference-manifest.json +20 -20
  139. package/web/.next/standalone/src/presentation/web/.next/BUILD_ID +1 -1
  140. package/web/.next/standalone/src/presentation/web/.next/build-manifest.json +2 -2
  141. package/web/.next/standalone/src/presentation/web/.next/prerender-manifest.json +3 -3
  142. package/web/.next/standalone/src/presentation/web/.next/required-server-files.json +1 -1
  143. package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/@drawer/create/page/server-reference-manifest.json +14 -14
  144. package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/@drawer/create/page.js.nft.json +1 -1
  145. package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/@drawer/create/page_client-reference-manifest.js +1 -1
  146. package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page/server-reference-manifest.json +17 -17
  147. package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page.js.nft.json +1 -1
  148. package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page_client-reference-manifest.js +1 -1
  149. package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page/server-reference-manifest.json +12 -12
  150. package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page.js.nft.json +1 -1
  151. package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page_client-reference-manifest.js +1 -1
  152. package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/create/page/server-reference-manifest.json +14 -14
  153. package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/create/page.js.nft.json +1 -1
  154. package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/create/page_client-reference-manifest.js +1 -1
  155. package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/feature/[featureId]/page/server-reference-manifest.json +17 -17
  156. package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/feature/[featureId]/page.js.nft.json +1 -1
  157. package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/feature/[featureId]/page_client-reference-manifest.js +1 -1
  158. package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/page/server-reference-manifest.json +12 -12
  159. package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/page.js.nft.json +1 -1
  160. package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/page_client-reference-manifest.js +1 -1
  161. package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/repository/[repositoryId]/page/server-reference-manifest.json +12 -12
  162. package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/repository/[repositoryId]/page.js.nft.json +1 -1
  163. package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/repository/[repositoryId]/page_client-reference-manifest.js +1 -1
  164. package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.html +2 -2
  165. package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.rsc +1 -1
  166. package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  167. package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  168. package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  169. package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  170. package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  171. package/web/.next/standalone/src/presentation/web/.next/server/app/_not-found/page/server-reference-manifest.json +1 -1
  172. package/web/.next/standalone/src/presentation/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  173. package/web/.next/standalone/src/presentation/web/.next/server/app/skills/page/server-reference-manifest.json +6 -6
  174. package/web/.next/standalone/src/presentation/web/.next/server/app/skills/page_client-reference-manifest.js +1 -1
  175. package/web/.next/standalone/src/presentation/web/.next/server/app/tools/page/server-reference-manifest.json +1 -1
  176. package/web/.next/standalone/src/presentation/web/.next/server/app/tools/page_client-reference-manifest.js +1 -1
  177. package/web/.next/standalone/src/presentation/web/.next/server/app/version/page/server-reference-manifest.json +1 -1
  178. package/web/.next/standalone/src/presentation/web/.next/server/app/version/page_client-reference-manifest.js +1 -1
  179. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_create-drawer-client_tsx_5e26fc0a._.js +1 -1
  180. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_@drawer_repository_[repositoryId]_page_actions_2b7834f6.js +1 -1
  181. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_repository_[repositoryId]_page_actions_6923c575.js +1 -1
  182. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__07385073._.js +2 -2
  183. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__08ba9bd3._.js +1 -1
  184. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__249c74f6._.js +1 -1
  185. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__6b17a22d._.js +1 -1
  186. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__6bb00d90._.js +1 -1
  187. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__6db85a66._.js +2 -2
  188. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__804c006d._.js +1 -1
  189. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__8fcb9132._.js +2 -2
  190. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/_00e6c698._.js +1 -1
  191. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/_07c2a32a._.js +1 -1
  192. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/_34a58db8._.js +1 -1
  193. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/_37259405._.js +1 -1
  194. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/{_85d0351b._.js → _63bfa7dd._.js} +2 -2
  195. package/web/.next/{server/chunks/ssr/_e50484ec._.js → standalone/src/presentation/web/.next/server/chunks/ssr/_7215bb0f._.js} +2 -2
  196. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/_cb5b3951._.js +1 -1
  197. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/_fc3a6895._.js +1 -1
  198. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/src_presentation_web_1a32dbcb._.js +2 -2
  199. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/src_presentation_web_398553b0._.js +1 -1
  200. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/src_presentation_web_5c87e8e4._.js +1 -1
  201. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_f4952172.js +1 -1
  202. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/src_presentation_web_c1bc6240._.js +2 -2
  203. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/src_presentation_web_ca99d62d._.js +1 -1
  204. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/src_presentation_web_components_features_control-center_7ac3562e._.js +1 -1
  205. package/web/.next/standalone/src/presentation/web/.next/server/pages/500.html +2 -2
  206. package/web/.next/standalone/src/presentation/web/.next/server/server-reference-manifest.js +1 -1
  207. package/web/.next/standalone/src/presentation/web/.next/server/server-reference-manifest.json +20 -20
  208. package/web/.next/standalone/src/presentation/web/app/(dashboard)/get-graph-data.ts +2 -6
  209. package/web/.next/standalone/src/presentation/web/app/build-graph-nodes.ts +14 -1
  210. package/web/.next/standalone/src/presentation/web/components/common/base-drawer/base-drawer.tsx +10 -8
  211. package/web/.next/standalone/src/presentation/web/components/common/control-center-drawer/create-drawer-client.tsx +13 -3
  212. package/web/.next/standalone/src/presentation/web/components/common/control-center-drawer/feature-drawer-client.tsx +6 -2
  213. package/web/.next/standalone/src/presentation/web/components/common/drawer-action-bar/drawer-action-bar.tsx +2 -0
  214. package/web/.next/standalone/src/presentation/web/components/common/feature-create-drawer/feature-create-drawer.tsx +8 -5
  215. package/web/.next/standalone/src/presentation/web/components/common/feature-node/feature-node.tsx +30 -24
  216. package/web/.next/standalone/src/presentation/web/components/common/repository-node/repository-node.tsx +33 -25
  217. package/web/.next/standalone/src/presentation/web/components/features/control-center/control-center-inner.tsx +25 -3
  218. package/web/.next/standalone/src/presentation/web/components/features/control-center/use-control-center-state.ts +184 -230
  219. package/web/.next/standalone/src/presentation/web/components/ui/alert-dialog.tsx +7 -0
  220. package/web/.next/standalone/src/presentation/web/components/ui/dialog.tsx +7 -1
  221. package/web/.next/standalone/src/presentation/web/lib/layout-with-dagre.ts +93 -4
  222. package/web/.next/standalone/src/presentation/web/server.js +1 -1
  223. package/web/.next/static/chunks/0c54314c8c9c9739.js +7 -0
  224. package/web/.next/static/chunks/{5f5c607ffae8b918.js → 304c8593d0a6525d.js} +1 -1
  225. package/web/.next/static/chunks/4558d1663c6f4d2c.js +1 -0
  226. package/web/.next/static/chunks/{32957ff277daec59.js → 4df07e765b233622.js} +1 -1
  227. package/web/.next/static/chunks/{fc07834e422b1caa.js → 585ae19c520e8b72.js} +1 -1
  228. package/web/.next/static/chunks/{ecb2130572a7fbe7.js → 6e14d8bd5c005e6e.js} +1 -1
  229. package/web/.next/static/chunks/{412a3ac70c529c5b.js → 8a1eb93510e54db0.js} +1 -1
  230. package/web/.next/static/chunks/{550bf3cb8220cbf0.js → b143c7d78a6888e9.js} +1 -1
  231. package/web/.next/static/chunks/{8b36e07129a1471f.js → b45344579a43cbb8.js} +1 -1
  232. package/web/.next/static/chunks/dec13bccb136ef7c.css +2 -0
  233. package/web/.next/static/chunks/e4522f7d3134eefe.js +1 -0
  234. package/web/.next/static/chunks/{d4ecce2ac7795bd9.js → fe83a799663fd3cc.js} +1 -1
  235. package/web/.next/trace +1 -1
  236. package/web/.next/trace-build +1 -1
  237. package/web/.next/server/chunks/ssr/_85d0351b._.js.map +0 -1
  238. package/web/.next/static/chunks/06b6b02bab76aee7.js +0 -1
  239. package/web/.next/static/chunks/06dfd668334ffb4e.js +0 -7
  240. package/web/.next/static/chunks/224ed5f5dbd33154.css +0 -2
  241. package/web/.next/static/chunks/e44849eb58a3335f.js +0 -1
  242. /package/web/.next/static/{7K6dTYQIJ7__PLUYLLfZV → 9bO_bJBssG0NRxEG03iM5}/_buildManifest.js +0 -0
  243. /package/web/.next/static/{7K6dTYQIJ7__PLUYLLfZV → 9bO_bJBssG0NRxEG03iM5}/_clientMiddlewareManifest.json +0 -0
  244. /package/web/.next/static/{7K6dTYQIJ7__PLUYLLfZV → 9bO_bJBssG0NRxEG03iM5}/_ssgManifest.js +0 -0
@@ -7,7 +7,11 @@ import { applyNodeChanges } from '@xyflow/react';
7
7
  import type { Connection, Edge, NodeChange } from '@xyflow/react';
8
8
  import type { FeatureNodeData } from '@/components/common/feature-node';
9
9
  import type { CanvasNodeType } from '@/components/features/features-canvas';
10
- import { layoutWithDagre, type LayoutDirection } from '@/lib/layout-with-dagre';
10
+ import {
11
+ layoutWithDagre,
12
+ CANVAS_LAYOUT_DEFAULTS,
13
+ type LayoutDirection,
14
+ } from '@/lib/layout-with-dagre';
11
15
  import { deleteFeature } from '@/app/actions/delete-feature';
12
16
  import { addRepository } from '@/app/actions/add-repository';
13
17
  import { deleteRepository } from '@/app/actions/delete-repository';
@@ -25,11 +29,12 @@ export interface ControlCenterState {
25
29
  handleConnect: (connection: Connection) => void;
26
30
  handleAddRepository: (path: string) => void;
27
31
  handleLayout: (direction: LayoutDirection) => void;
28
- handleDeleteFeature: (featureId: string) => Promise<void>;
32
+ handleDeleteFeature: (featureId: string) => void;
29
33
  handleDeleteRepository: (repositoryId: string) => Promise<void>;
30
34
  createFeatureNode: (
31
35
  sourceNodeId: string | null,
32
- dataOverride?: Partial<FeatureNodeData>
36
+ dataOverride?: Partial<FeatureNodeData>,
37
+ edgeType?: string
33
38
  ) => string;
34
39
  }
35
40
 
@@ -37,9 +42,7 @@ let nextFeatureId = 0;
37
42
 
38
43
  export function useControlCenterState(
39
44
  initialNodes: CanvasNodeType[],
40
- initialEdges: Edge[],
41
- /** When true, background router.refresh() calls (polling / SSE debounce) are suppressed. */
42
- isRefreshBlocked?: () => boolean
45
+ initialEdges: Edge[]
43
46
  ): ControlCenterState {
44
47
  const router = useRouter();
45
48
  const [nodes, setNodes] = useState<CanvasNodeType[]>(initialNodes);
@@ -59,7 +62,7 @@ export function useControlCenterState(
59
62
  const deleteSound = useSoundAction('delete');
60
63
  const createSound = useSoundAction('create');
61
64
 
62
- // Sync server props into local state when router.refresh() delivers new data
65
+ // Sync server props into local state when parent re-renders with new data
63
66
  const initialNodeKey = initialNodes
64
67
  .map((n) => n.id)
65
68
  .sort()
@@ -98,8 +101,9 @@ export function useControlCenterState(
98
101
  !serverIds.has(n.id)
99
102
  );
100
103
 
101
- // Merge server nodes with client positions
102
- return initialNodes.map((serverNode) => {
104
+ // Merge server nodes with client positions, tracking if relayout is needed
105
+ let needsRelayout = false;
106
+ const merged = initialNodes.map((serverNode) => {
103
107
  // Node already exists on canvas — keep its position, update data
104
108
  const existing = currentById.get(serverNode.id);
105
109
  if (existing) {
@@ -112,19 +116,36 @@ export function useControlCenterState(
112
116
  return { ...serverNode, position: donor.position };
113
117
  }
114
118
 
115
- // Truly new node with no optimistic counterpart — use server position
119
+ // Truly new node with no optimistic counterpart — needs relayout
120
+ needsRelayout = true;
116
121
  return serverNode;
117
122
  });
123
+
124
+ // Also check if non-creating nodes were removed (graph got smaller)
125
+ if (!needsRelayout) {
126
+ needsRelayout = currentNodes.some(
127
+ (cn) =>
128
+ !serverIds.has(cn.id) &&
129
+ !(cn.type === 'featureNode' && (cn.data as FeatureNodeData).state === 'creating')
130
+ );
131
+ }
132
+
133
+ if (needsRelayout) {
134
+ const layoutResult = layoutWithDagre(merged, initialEdges, CANVAS_LAYOUT_DEFAULTS);
135
+ setEdges(layoutResult.edges);
136
+ return layoutResult.nodes;
137
+ }
138
+
139
+ return merged;
118
140
  });
119
- }, [initialNodeKey, initialNodes]);
141
+ }, [initialNodeKey, initialNodes, initialEdges, setEdges]);
120
142
 
121
143
  useEffect(() => {
122
144
  setEdges(initialEdges);
123
145
  }, [initialEdgeKey, initialEdges, setEdges]);
124
146
 
125
- // Fallback notifications from server-refresh state transitions.
126
- // Fires only when SSE didn't already deliver the matching event for a feature,
127
- // e.g. when the SSE connection was down or the event was seeded into the cache.
147
+ // Fallback notifications from server-prop state transitions.
148
+ // Fires only when SSE didn't already deliver the matching event for a feature.
128
149
  const { events } = useAgentEventsContext();
129
150
 
130
151
  useEffect(() => {
@@ -164,15 +185,10 @@ export function useControlCenterState(
164
185
  }
165
186
  }, [initialDataKey, initialNodes, events, router]);
166
187
 
167
- // Targeted optimistic updates from SSE agent events + debounced reconciliation.
188
+ // Targeted optimistic updates from SSE agent events.
168
189
  // Uses `events` array (not `lastEvent`) so that React batching cannot silently
169
190
  // drop events when multiple SSE messages arrive in the same tick.
170
191
  const processedEventCountRef = useRef(0);
171
- const reconcileTimerRef = useRef<ReturnType<typeof setTimeout>>(undefined);
172
-
173
- useEffect(() => {
174
- return () => clearTimeout(reconcileTimerRef.current);
175
- }, []);
176
192
 
177
193
  useEffect(() => {
178
194
  if (events.length <= processedEventCountRef.current) return;
@@ -201,33 +217,7 @@ export function useControlCenterState(
201
217
  })
202
218
  );
203
219
  }
204
-
205
- // Debounced background reconciliation (3s after last SSE event)
206
- clearTimeout(reconcileTimerRef.current);
207
- reconcileTimerRef.current = setTimeout(() => {
208
- if (!isRefreshBlocked?.()) router.refresh();
209
- }, 3000);
210
- }, [events, router, isRefreshBlocked]);
211
-
212
- // Periodic polling fallback: refresh server data every 5s when any feature
213
- // is in an active state (running/action-required). This ensures the UI stays
214
- // current even if the SSE connection drops — belt-and-suspenders alongside SSE.
215
- useEffect(() => {
216
- const hasActiveFeature = nodes.some((n) => {
217
- if (n.type !== 'featureNode') return false;
218
- const data = n.data as FeatureNodeData;
219
- return (
220
- data.state === 'running' || data.state === 'action-required' || data.state === 'creating'
221
- );
222
- });
223
-
224
- if (!hasActiveFeature) return;
225
-
226
- const interval = setInterval(() => {
227
- if (!isRefreshBlocked?.()) router.refresh();
228
- }, 5_000);
229
- return () => clearInterval(interval);
230
- }, [nodes, router, isRefreshBlocked]);
220
+ }, [events]);
231
221
 
232
222
  const onNodesChange = useCallback((changes: NodeChange<CanvasNodeType>[]) => {
233
223
  setNodes((ns) => applyNodeChanges(changes, ns));
@@ -285,103 +275,54 @@ export function useControlCenterState(
285
275
  };
286
276
 
287
277
  setNodes((currentNodes) => {
288
- // Read edges from ref to avoid closure dependency on `edges` state.
289
- // edgesRef is kept in sync by the setEdges wrapper.
290
- const siblingIds = sourceNodeId
291
- ? new Set(edgesRef.current.filter((e) => e.source === sourceNodeId).map((e) => e.target))
292
- : new Set<string>();
293
- const siblings = currentNodes.filter((n) => siblingIds.has(n.id));
294
-
295
- let position: { x: number; y: number };
296
-
297
- if (siblings.length > 0) {
298
- // Place below the bottom-most sibling, matching X
299
- const sortedYs = siblings.map((n) => n.position.y).sort((a, b) => a - b);
300
- const maxY = sortedYs[sortedYs.length - 1];
301
- // Derive gap from existing spacing between siblings, or use default
302
- const gap = sortedYs.length > 1 ? sortedYs[1] - sortedYs[0] : 160;
303
- position = { x: siblings[0].position.x, y: maxY + gap };
304
- } else if (sourceNodeId) {
305
- // First child — position to the right of parent
306
- const parent = currentNodes.find((n) => n.id === sourceNodeId);
307
- // Parent width (288) + 200px gap matching dagre ranksep
308
- const xOffset = 488;
309
- position = parent
310
- ? { x: parent.position.x + xOffset, y: parent.position.y }
311
- : { x: 400, y: 200 };
312
- } else {
313
- // Standalone feature — place below all existing nodes
314
- const maxY =
315
- currentNodes.length > 0 ? Math.max(...currentNodes.map((n) => n.position.y)) : 0;
316
- position = { x: 400, y: currentNodes.length > 0 ? maxY + 160 : 200 };
317
- }
278
+ const newNode = {
279
+ id,
280
+ type: 'featureNode' as const,
281
+ position: { x: 0, y: 0 },
282
+ data: newFeatureData,
283
+ } as CanvasNodeType;
318
284
 
319
- // The new node's bottom edge (featureNode height = 140)
320
- const newBottom = position.y + 140;
321
-
322
- // Find the old group bottom before adding the new node
323
- const groupNodeIds = new Set([sourceNodeId, ...siblingIds]);
324
- const oldGroupBottom = currentNodes
325
- .filter((n) => groupNodeIds.has(n.id))
326
- .reduce((max, n) => {
327
- const h = n.type === 'featureNode' ? 140 : 50;
328
- return Math.max(max, n.position.y + h);
329
- }, 0);
330
-
331
- // Shift amount: how much the group grew past its old bottom
332
- const shift = Math.max(0, newBottom - oldGroupBottom);
333
-
334
- // Push down all nodes that are below the old group bottom
335
- const shifted =
336
- shift > 0
337
- ? currentNodes.map((n) => {
338
- if (groupNodeIds.has(n.id) || siblingIds.has(n.id)) return n;
339
- if (n.position.y >= oldGroupBottom) {
340
- return { ...n, position: { ...n.position, y: n.position.y + shift } };
341
- }
342
- return n;
343
- })
344
- : currentNodes;
345
-
346
- // Re-center the parent node vertically to its children
347
- const recentered = sourceNodeId
348
- ? shifted.map((n) => {
349
- if (n.id !== sourceNodeId) return n;
350
- const allChildYs = [...siblings.map((s) => s.position.y), position.y];
351
- const groupCenter = (Math.min(...allChildYs) + Math.max(...allChildYs) + 140) / 2;
352
- const parentHeight = n.type === 'featureNode' ? 140 : 50;
353
- return {
354
- ...n,
355
- position: { ...n.position, y: groupCenter - parentHeight / 2 },
356
- };
357
- })
358
- : shifted;
359
-
360
- return [
361
- ...recentered,
362
- {
363
- id,
364
- type: 'featureNode' as const,
365
- position,
366
- data: newFeatureData,
367
- } as CanvasNodeType,
285
+ const newEdge = sourceNodeId
286
+ ? {
287
+ id:
288
+ edgeType === 'dependencyEdge'
289
+ ? `dep-${sourceNodeId}-${id}`
290
+ : `edge-${sourceNodeId}-${id}`,
291
+ source: sourceNodeId,
292
+ target: id,
293
+ ...(edgeType ? { type: edgeType } : { style: { strokeDasharray: '5 5' } }),
294
+ }
295
+ : null;
296
+
297
+ const allEdges = newEdge
298
+ ? [...edgesRef.current.filter((e) => e.id !== newEdge.id), newEdge]
299
+ : edgesRef.current;
300
+
301
+ // Insert the new node after the last sibling connected to the same source,
302
+ // so dagre's input-order preservation keeps repo groups together.
303
+ let insertIndex = currentNodes.length;
304
+ if (sourceNodeId) {
305
+ const siblingIds = new Set(
306
+ allEdges.filter((e) => e.source === sourceNodeId).map((e) => e.target)
307
+ );
308
+ for (let i = currentNodes.length - 1; i >= 0; i--) {
309
+ if (siblingIds.has(currentNodes[i].id)) {
310
+ insertIndex = i + 1;
311
+ break;
312
+ }
313
+ }
314
+ }
315
+ const allNodes = [
316
+ ...currentNodes.slice(0, insertIndex),
317
+ newNode,
318
+ ...currentNodes.slice(insertIndex),
368
319
  ];
369
- });
370
320
 
371
- if (sourceNodeId) {
372
- setEdges((currentEdges) => [
373
- ...currentEdges,
374
- {
375
- id:
376
- edgeType === 'dependencyEdge'
377
- ? `dep-${sourceNodeId}-${id}`
378
- : `edge-${sourceNodeId}-${id}`,
379
- source: sourceNodeId,
380
- target: id,
381
- ...(edgeType ? { type: edgeType } : { style: { strokeDasharray: '5 5' } }),
382
- },
383
- ]);
384
- }
321
+ // Run dagre layout on the full graph so the new node is positioned consistently
322
+ const layoutResult = layoutWithDagre(allNodes, allEdges, CANVAS_LAYOUT_DEFAULTS);
323
+ setEdges(layoutResult.edges);
324
+ return layoutResult.nodes;
325
+ });
385
326
 
386
327
  return id;
387
328
  },
@@ -389,80 +330,115 @@ export function useControlCenterState(
389
330
  );
390
331
 
391
332
  const handleDeleteFeature = useCallback(
392
- async (featureId: string) => {
393
- try {
394
- const result = await deleteFeature(featureId);
333
+ (featureId: string) => {
334
+ const nodeId = `feat-${featureId}`;
395
335
 
396
- if (result.error) {
397
- toast.error(result.error);
398
- return;
399
- }
336
+ // Snapshot current state for rollback
337
+ const prevNodes = nodes;
338
+ const prevEdges = edgesRef.current;
400
339
 
401
- setNodes((currentNodes) => {
402
- const remainingNodes = currentNodes.filter((n) => n.id !== featureId);
403
- const remainingEdges = edges.filter(
404
- (e) => e.source !== featureId && e.target !== featureId
405
- );
406
- const layoutResult = layoutWithDagre(remainingNodes, remainingEdges, {
407
- direction: 'LR',
408
- ranksep: 200,
409
- nodesep: 60,
410
- });
411
- setEdges(layoutResult.edges);
412
- return layoutResult.nodes;
340
+ // Optimistic removal — update UI immediately
341
+ setNodes((currentNodes) => {
342
+ const remainingNodes = currentNodes.filter((n) => n.id !== nodeId);
343
+ const remainingEdges = edgesRef.current.filter(
344
+ (e) => e.source !== nodeId && e.target !== nodeId
345
+ );
346
+ const layoutResult = layoutWithDagre(
347
+ remainingNodes,
348
+ remainingEdges,
349
+ CANVAS_LAYOUT_DEFAULTS
350
+ );
351
+ setEdges(layoutResult.edges);
352
+ return layoutResult.nodes;
353
+ });
354
+ deleteSound.play();
355
+ toast.success('Feature deleted successfully');
356
+ router.push('/');
357
+
358
+ // Persist in background — rollback on failure
359
+ deleteFeature(featureId)
360
+ .then((result) => {
361
+ if (result.error) {
362
+ setNodes(prevNodes);
363
+ setEdges(prevEdges);
364
+ toast.error(result.error);
365
+ }
366
+ })
367
+ .catch(() => {
368
+ setNodes(prevNodes);
369
+ setEdges(prevEdges);
370
+ toast.error('Failed to delete feature');
413
371
  });
414
- deleteSound.play();
415
- toast.success('Feature deleted successfully');
416
- router.refresh();
417
- } catch {
418
- toast.error('Failed to delete feature');
419
- }
420
372
  },
421
- [router, edges, deleteSound, setEdges]
373
+ [nodes, router, deleteSound, setEdges]
422
374
  );
423
375
 
424
376
  const handleDeleteRepository = useCallback(
425
377
  async (repositoryId: string) => {
426
378
  const repoNodeId = `repo-${repositoryId}`;
427
379
 
428
- // Optimistic: remove node and its edges immediately
429
- setNodes((prev) => prev.filter((n) => n.id !== repoNodeId));
430
- setEdges((prev) => prev.filter((e) => e.source !== repoNodeId && e.target !== repoNodeId));
380
+ // Snapshot for rollback
381
+ const prevNodes = nodes;
382
+ const prevEdges = edgesRef.current;
383
+
384
+ // Optimistic: remove repo node, its child feature nodes, and all related edges
385
+ setNodes((currentNodes) => {
386
+ // Find feature node IDs connected to this repo via edges
387
+ const childFeatureIds = new Set(
388
+ edgesRef.current.filter((e) => e.source === repoNodeId).map((e) => e.target)
389
+ );
390
+ const remainingNodes = currentNodes.filter(
391
+ (n) => n.id !== repoNodeId && !childFeatureIds.has(n.id)
392
+ );
393
+ const remainingEdges = edgesRef.current.filter(
394
+ (e) =>
395
+ e.source !== repoNodeId &&
396
+ e.target !== repoNodeId &&
397
+ !childFeatureIds.has(e.source) &&
398
+ !childFeatureIds.has(e.target)
399
+ );
400
+ const layoutResult = layoutWithDagre(
401
+ remainingNodes,
402
+ remainingEdges,
403
+ CANVAS_LAYOUT_DEFAULTS
404
+ );
405
+ setEdges(layoutResult.edges);
406
+ return layoutResult.nodes;
407
+ });
431
408
 
432
409
  try {
433
410
  const result = await deleteRepository(repositoryId);
434
411
 
435
412
  if (!result.success) {
436
413
  toast.error(result.error ?? 'Failed to remove repository');
437
- router.refresh();
414
+ setNodes(prevNodes);
415
+ setEdges(prevEdges);
438
416
  return;
439
417
  }
440
418
 
441
419
  deleteSound.play();
442
420
  toast.success('Repository removed');
443
- router.refresh();
444
421
  } catch {
445
422
  toast.error('Failed to remove repository');
446
- router.refresh();
423
+ setNodes(prevNodes);
424
+ setEdges(prevEdges);
447
425
  }
448
426
  },
449
- [router, deleteSound, setEdges]
427
+ [nodes, deleteSound, setEdges]
450
428
  );
451
429
 
452
430
  const handleLayout = useCallback(
453
431
  (direction: LayoutDirection) => {
454
432
  setNodes((currentNodes) => {
455
- const currentEdges = edges;
456
- const result = layoutWithDagre(currentNodes, currentEdges, {
433
+ const result = layoutWithDagre(currentNodes, edgesRef.current, {
434
+ ...CANVAS_LAYOUT_DEFAULTS,
457
435
  direction,
458
- ranksep: 60,
459
- nodesep: 20,
460
436
  });
461
437
  setEdges(result.edges);
462
438
  return result.nodes;
463
439
  });
464
440
  },
465
- [edges, setEdges]
441
+ [setEdges]
466
442
  );
467
443
 
468
444
  const handleAddRepository = useCallback(
@@ -474,58 +450,36 @@ export function useControlCenterState(
474
450
  .split(/[\\/]/)
475
451
  .pop() ?? path;
476
452
 
477
- // Optimistic UI: add node immediately
478
- let savedAddRepoY = 0;
453
+ // Optimistic UI: add node and re-layout immediately
479
454
  setNodes((currentNodes) => {
480
- const repoNodes = currentNodes.filter((n) => n.type === 'repositoryNode');
481
- const addRepoNode = currentNodes.find((n) => n.type === 'addRepositoryNode');
482
-
483
- // Save addRepoNode's original Y for rollback on error
484
- if (addRepoNode) savedAddRepoY = addRepoNode.position.y;
485
-
486
- // Place in the repo column, at the addRepoNode's current position
487
- const repoX = repoNodes[0]?.position.x ?? addRepoNode?.position.x ?? 50;
488
- const repoHeight = 50; // repositoryNode height
489
- const gap = 15; // match dagre nodesep
490
-
491
- const position = {
492
- x: repoX,
493
- y: addRepoNode ? addRepoNode.position.y : 0,
494
- };
495
-
496
455
  const newNode = {
497
456
  id: tempId,
498
457
  type: 'repositoryNode' as const,
499
- position,
458
+ position: { x: 0, y: 0 },
500
459
  data: { name: repoName, repositoryPath: path, id: tempId },
501
460
  } as CanvasNodeType;
502
461
 
503
- // Shift addRepo button down by exactly one slot
504
- const addRepoY = addRepoNode
505
- ? addRepoNode.position.y + repoHeight + gap
506
- : position.y + repoHeight + gap;
507
-
508
- return currentNodes
509
- .map((n) =>
510
- n.type === 'addRepositoryNode' ? { ...n, position: { ...n.position, y: addRepoY } } : n
511
- )
512
- .concat(newNode);
462
+ const allNodes = [...currentNodes, newNode];
463
+ const layoutResult = layoutWithDagre(allNodes, edgesRef.current, CANVAS_LAYOUT_DEFAULTS);
464
+ setEdges(layoutResult.edges);
465
+ return layoutResult.nodes;
513
466
  });
514
467
 
515
468
  // Persist via server action
516
469
  addRepository({ path, name: repoName })
517
470
  .then((result) => {
518
471
  if (result.error) {
519
- // Rollback optimistic node and restore addRepoNode position
520
- setNodes((prev) =>
521
- prev
522
- .filter((n) => n.id !== tempId)
523
- .map((n) =>
524
- n.type === 'addRepositoryNode'
525
- ? { ...n, position: { ...n.position, y: savedAddRepoY } }
526
- : n
527
- )
528
- );
472
+ // Rollback optimistic node and re-layout
473
+ setNodes((prev) => {
474
+ const remaining = prev.filter((n) => n.id !== tempId);
475
+ const layoutResult = layoutWithDagre(
476
+ remaining,
477
+ edgesRef.current,
478
+ CANVAS_LAYOUT_DEFAULTS
479
+ );
480
+ setEdges(layoutResult.edges);
481
+ return layoutResult.nodes;
482
+ });
529
483
  toast.error(result.error);
530
484
  return;
531
485
  }
@@ -554,23 +508,23 @@ export function useControlCenterState(
554
508
  );
555
509
 
556
510
  createSound.play();
557
- router.refresh();
558
511
  })
559
512
  .catch(() => {
560
- // Rollback optimistic node and restore addRepoNode position
561
- setNodes((prev) =>
562
- prev
563
- .filter((n) => n.id !== tempId)
564
- .map((n) =>
565
- n.type === 'addRepositoryNode'
566
- ? { ...n, position: { ...n.position, y: savedAddRepoY } }
567
- : n
568
- )
569
- );
513
+ // Rollback optimistic node and re-layout
514
+ setNodes((prev) => {
515
+ const remaining = prev.filter((n) => n.id !== tempId);
516
+ const layoutResult = layoutWithDagre(
517
+ remaining,
518
+ edgesRef.current,
519
+ CANVAS_LAYOUT_DEFAULTS
520
+ );
521
+ setEdges(layoutResult.edges);
522
+ return layoutResult.nodes;
523
+ });
570
524
  toast.error('Failed to add repository');
571
525
  });
572
526
  },
573
- [router, createSound, setEdges]
527
+ [createSound, setEdges]
574
528
  );
575
529
 
576
530
  return {
@@ -22,6 +22,7 @@ function AlertDialogPortal({ ...props }: React.ComponentProps<typeof AlertDialog
22
22
 
23
23
  function AlertDialogOverlay({
24
24
  className,
25
+ onClick,
25
26
  ...props
26
27
  }: React.ComponentProps<typeof AlertDialogPrimitive.Overlay>) {
27
28
  return (
@@ -31,6 +32,12 @@ function AlertDialogOverlay({
31
32
  'data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/50',
32
33
  className
33
34
  )}
35
+ onClick={(e) => {
36
+ // Prevent overlay clicks from propagating to document-level handlers
37
+ // (e.g. BaseDrawer outside-click) — only the dialog should dismiss.
38
+ e.stopPropagation();
39
+ onClick?.(e);
40
+ }}
34
41
  {...props}
35
42
  />
36
43
  );
@@ -17,13 +17,19 @@ const DialogClose = DialogPrimitive.Close;
17
17
  const DialogOverlay = React.forwardRef<
18
18
  React.ComponentRef<typeof DialogPrimitive.Overlay>,
19
19
  React.ComponentPropsWithoutRef<typeof DialogPrimitive.Overlay>
20
- >(({ className, ...props }, ref) => (
20
+ >(({ className, onClick, ...props }, ref) => (
21
21
  <DialogPrimitive.Overlay
22
22
  ref={ref}
23
23
  className={cn(
24
24
  'data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/80',
25
25
  className
26
26
  )}
27
+ onClick={(e) => {
28
+ // Prevent overlay clicks from propagating to document-level handlers
29
+ // (e.g. BaseDrawer outside-click) — only the dialog should dismiss.
30
+ e.stopPropagation();
31
+ onClick?.(e);
32
+ }}
27
33
  {...props}
28
34
  />
29
35
  ));