@shepai/cli 1.177.0 → 1.178.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 (334) hide show
  1. package/apis/json-schema/Language.yaml +1 -0
  2. package/dist/packages/core/src/application/ports/output/services/agent-auth-detector.interface.d.ts +23 -0
  3. package/dist/packages/core/src/application/ports/output/services/agent-auth-detector.interface.d.ts.map +1 -0
  4. package/dist/packages/core/src/application/ports/output/services/agent-auth-detector.interface.js +13 -0
  5. package/dist/packages/core/src/application/ports/output/services/file-system-service.interface.d.ts +18 -0
  6. package/dist/packages/core/src/application/ports/output/services/file-system-service.interface.d.ts.map +1 -0
  7. package/dist/packages/core/src/application/ports/output/services/file-system-service.interface.js +7 -0
  8. package/dist/packages/core/src/application/ports/output/services/index.d.ts +3 -0
  9. package/dist/packages/core/src/application/ports/output/services/index.d.ts.map +1 -1
  10. package/dist/packages/core/src/application/ports/output/services/project-scaffold-service.interface.d.ts +33 -0
  11. package/dist/packages/core/src/application/ports/output/services/project-scaffold-service.interface.d.ts.map +1 -0
  12. package/dist/packages/core/src/application/ports/output/services/project-scaffold-service.interface.js +9 -0
  13. package/dist/packages/core/src/application/use-cases/agents/check-agent-auth.use-case.d.ts +42 -0
  14. package/dist/packages/core/src/application/use-cases/agents/check-agent-auth.use-case.d.ts.map +1 -0
  15. package/dist/packages/core/src/application/use-cases/agents/check-agent-auth.use-case.js +134 -0
  16. package/dist/packages/core/src/application/use-cases/projects/create-project.use-case.d.ts +43 -0
  17. package/dist/packages/core/src/application/use-cases/projects/create-project.use-case.d.ts.map +1 -0
  18. package/dist/packages/core/src/application/use-cases/projects/create-project.use-case.js +84 -0
  19. package/dist/packages/core/src/application/use-cases/repositories/delete-repository.use-case.d.ts +13 -2
  20. package/dist/packages/core/src/application/use-cases/repositories/delete-repository.use-case.d.ts.map +1 -1
  21. package/dist/packages/core/src/application/use-cases/repositories/delete-repository.use-case.js +14 -3
  22. package/dist/packages/core/src/infrastructure/di/container.d.ts.map +1 -1
  23. package/dist/packages/core/src/infrastructure/di/container.js +16 -0
  24. package/dist/packages/core/src/infrastructure/services/agent-auth-detector/platform-agent-auth-detector.service.d.ts +35 -0
  25. package/dist/packages/core/src/infrastructure/services/agent-auth-detector/platform-agent-auth-detector.service.d.ts.map +1 -0
  26. package/dist/packages/core/src/infrastructure/services/agent-auth-detector/platform-agent-auth-detector.service.js +165 -0
  27. package/dist/packages/core/src/infrastructure/services/file-system.service.d.ts +10 -0
  28. package/dist/packages/core/src/infrastructure/services/file-system.service.d.ts.map +1 -0
  29. package/dist/packages/core/src/infrastructure/services/file-system.service.js +22 -0
  30. package/dist/packages/core/src/infrastructure/services/project-scaffold/fs-project-scaffold.service.d.ts +22 -0
  31. package/dist/packages/core/src/infrastructure/services/project-scaffold/fs-project-scaffold.service.d.ts.map +1 -0
  32. package/dist/packages/core/src/infrastructure/services/project-scaffold/fs-project-scaffold.service.js +74 -0
  33. package/dist/src/presentation/web/app/actions/check-agent-auth.d.ts +10 -2
  34. package/dist/src/presentation/web/app/actions/check-agent-auth.d.ts.map +1 -1
  35. package/dist/src/presentation/web/app/actions/check-agent-auth.js +7 -199
  36. package/dist/src/presentation/web/app/actions/create-project-folder.d.ts +16 -0
  37. package/dist/src/presentation/web/app/actions/create-project-folder.d.ts.map +1 -0
  38. package/dist/src/presentation/web/app/actions/create-project-folder.js +18 -0
  39. package/dist/src/presentation/web/app/actions/delete-repository.d.ts +4 -1
  40. package/dist/src/presentation/web/app/actions/delete-repository.d.ts.map +1 -1
  41. package/dist/src/presentation/web/app/actions/delete-repository.js +2 -2
  42. package/dist/src/presentation/web/components/common/feature-node/feature-node.d.ts.map +1 -1
  43. package/dist/src/presentation/web/components/common/feature-node/feature-node.js +2 -2
  44. package/dist/src/presentation/web/components/common/repository-node/repository-node-config.d.ts +3 -1
  45. package/dist/src/presentation/web/components/common/repository-node/repository-node-config.d.ts.map +1 -1
  46. package/dist/src/presentation/web/components/common/repository-node/repository-node.d.ts.map +1 -1
  47. package/dist/src/presentation/web/components/common/repository-node/repository-node.js +13 -4
  48. package/dist/src/presentation/web/components/features/control-center/control-center-empty-state.d.ts.map +1 -1
  49. package/dist/src/presentation/web/components/features/control-center/control-center-empty-state.js +5 -3
  50. package/dist/src/presentation/web/components/features/control-center/control-center-inner.d.ts.map +1 -1
  51. package/dist/src/presentation/web/components/features/control-center/control-center-inner.js +134 -124
  52. package/dist/src/presentation/web/components/features/control-center/new-project-dialog.d.ts +8 -0
  53. package/dist/src/presentation/web/components/features/control-center/new-project-dialog.d.ts.map +1 -0
  54. package/dist/src/presentation/web/components/features/control-center/new-project-dialog.js +43 -0
  55. package/dist/src/presentation/web/components/features/control-center/use-canvas-event-listeners.d.ts +27 -0
  56. package/dist/src/presentation/web/components/features/control-center/use-canvas-event-listeners.d.ts.map +1 -0
  57. package/dist/src/presentation/web/components/features/control-center/use-canvas-event-listeners.js +84 -0
  58. package/dist/src/presentation/web/components/features/control-center/use-control-center-state.d.ts +3 -1
  59. package/dist/src/presentation/web/components/features/control-center/use-control-center-state.d.ts.map +1 -1
  60. package/dist/src/presentation/web/components/features/control-center/use-control-center-state.js +4 -2
  61. package/dist/src/presentation/web/components/features/control-center/use-fab-actions.d.ts +21 -0
  62. package/dist/src/presentation/web/components/features/control-center/use-fab-actions.d.ts.map +1 -0
  63. package/dist/src/presentation/web/components/features/control-center/use-fab-actions.js +70 -0
  64. package/dist/src/presentation/web/components/features/control-center/use-workspace-fit-view.d.ts +27 -0
  65. package/dist/src/presentation/web/components/features/control-center/use-workspace-fit-view.d.ts.map +1 -0
  66. package/dist/src/presentation/web/components/features/control-center/use-workspace-fit-view.js +48 -0
  67. package/dist/src/presentation/web/components/features/control-center/welcome-agent-setup.d.ts.map +1 -1
  68. package/dist/src/presentation/web/components/features/control-center/welcome-agent-setup.js +8 -1
  69. package/dist/src/presentation/web/components/features/features-canvas/canvas-toolbar.d.ts +3 -1
  70. package/dist/src/presentation/web/components/features/features-canvas/canvas-toolbar.d.ts.map +1 -1
  71. package/dist/src/presentation/web/components/features/features-canvas/canvas-toolbar.js +3 -3
  72. package/dist/src/presentation/web/components/features/features-canvas/features-canvas.d.ts.map +1 -1
  73. package/dist/src/presentation/web/components/features/features-canvas/features-canvas.js +1 -1
  74. package/dist/src/presentation/web/components/features/features-canvas/manage-workspace-dialog.d.ts +15 -0
  75. package/dist/src/presentation/web/components/features/features-canvas/manage-workspace-dialog.d.ts.map +1 -0
  76. package/dist/src/presentation/web/components/features/features-canvas/manage-workspace-dialog.js +74 -0
  77. package/dist/src/presentation/web/components/features/features-canvas/workspace-name-dialog.d.ts +11 -0
  78. package/dist/src/presentation/web/components/features/features-canvas/workspace-name-dialog.d.ts.map +1 -0
  79. package/dist/src/presentation/web/components/features/features-canvas/workspace-name-dialog.js +22 -0
  80. package/dist/src/presentation/web/components/features/features-canvas/workspace-selector.d.ts +13 -0
  81. package/dist/src/presentation/web/components/features/features-canvas/workspace-selector.d.ts.map +1 -0
  82. package/dist/src/presentation/web/components/features/features-canvas/workspace-selector.js +21 -0
  83. package/dist/src/presentation/web/hooks/use-workspaces.d.ts +37 -0
  84. package/dist/src/presentation/web/hooks/use-workspaces.d.ts.map +1 -0
  85. package/dist/src/presentation/web/hooks/use-workspaces.js +219 -0
  86. package/dist/src/presentation/web/lib/derive-graph.d.ts +3 -1
  87. package/dist/src/presentation/web/lib/derive-graph.d.ts.map +1 -1
  88. package/dist/translations/ar/web.json +4 -1
  89. package/dist/translations/de/web.json +4 -1
  90. package/dist/translations/en/web.json +4 -1
  91. package/dist/translations/es/web.json +4 -1
  92. package/dist/translations/fr/web.json +4 -1
  93. package/dist/translations/he/web.json +4 -1
  94. package/dist/translations/pt/web.json +4 -1
  95. package/dist/translations/ru/web.json +4 -1
  96. package/dist/translations/uk/web.json +3 -0
  97. package/dist/tsconfig.build.tsbuildinfo +1 -1
  98. package/package.json +1 -1
  99. package/web/.next/BUILD_ID +1 -1
  100. package/web/.next/build-manifest.json +2 -2
  101. package/web/.next/fallback-build-manifest.json +2 -2
  102. package/web/.next/prerender-manifest.json +3 -3
  103. package/web/.next/required-server-files.js +2 -2
  104. package/web/.next/required-server-files.json +2 -2
  105. package/web/.next/server/app/(dashboard)/@drawer/adopt/page/server-reference-manifest.json +73 -58
  106. package/web/.next/server/app/(dashboard)/@drawer/adopt/page.js +1 -2
  107. package/web/.next/server/app/(dashboard)/@drawer/adopt/page.js.nft.json +1 -1
  108. package/web/.next/server/app/(dashboard)/@drawer/adopt/page_client-reference-manifest.js +1 -1
  109. package/web/.next/server/app/(dashboard)/@drawer/chat/page/server-reference-manifest.json +69 -54
  110. package/web/.next/server/app/(dashboard)/@drawer/chat/page.js +1 -2
  111. package/web/.next/server/app/(dashboard)/@drawer/chat/page.js.nft.json +1 -1
  112. package/web/.next/server/app/(dashboard)/@drawer/chat/page_client-reference-manifest.js +1 -1
  113. package/web/.next/server/app/(dashboard)/@drawer/create/page/server-reference-manifest.json +75 -60
  114. package/web/.next/server/app/(dashboard)/@drawer/create/page.js +1 -2
  115. package/web/.next/server/app/(dashboard)/@drawer/create/page.js.nft.json +1 -1
  116. package/web/.next/server/app/(dashboard)/@drawer/create/page_client-reference-manifest.js +1 -1
  117. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page/server-reference-manifest.json +91 -76
  118. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page.js +1 -2
  119. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page.js.nft.json +1 -1
  120. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page_client-reference-manifest.js +1 -1
  121. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page/server-reference-manifest.json +91 -76
  122. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page.js +1 -2
  123. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page.js.nft.json +1 -1
  124. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page_client-reference-manifest.js +1 -1
  125. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/[tab]/page/server-reference-manifest.json +71 -56
  126. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/[tab]/page.js +1 -2
  127. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/[tab]/page.js.nft.json +1 -1
  128. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/[tab]/page_client-reference-manifest.js +1 -1
  129. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page/server-reference-manifest.json +71 -56
  130. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page.js +1 -2
  131. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page.js.nft.json +1 -1
  132. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page_client-reference-manifest.js +1 -1
  133. package/web/.next/server/app/(dashboard)/chat/page/server-reference-manifest.json +69 -54
  134. package/web/.next/server/app/(dashboard)/chat/page.js +1 -2
  135. package/web/.next/server/app/(dashboard)/chat/page.js.nft.json +1 -1
  136. package/web/.next/server/app/(dashboard)/chat/page_client-reference-manifest.js +1 -1
  137. package/web/.next/server/app/(dashboard)/create/page/server-reference-manifest.json +75 -60
  138. package/web/.next/server/app/(dashboard)/create/page.js +1 -2
  139. package/web/.next/server/app/(dashboard)/create/page.js.nft.json +1 -1
  140. package/web/.next/server/app/(dashboard)/create/page_client-reference-manifest.js +1 -1
  141. package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page/server-reference-manifest.json +91 -76
  142. package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page.js +1 -2
  143. package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page.js.nft.json +1 -1
  144. package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page_client-reference-manifest.js +1 -1
  145. package/web/.next/server/app/(dashboard)/feature/[featureId]/page/server-reference-manifest.json +91 -76
  146. package/web/.next/server/app/(dashboard)/feature/[featureId]/page.js +1 -2
  147. package/web/.next/server/app/(dashboard)/feature/[featureId]/page.js.nft.json +1 -1
  148. package/web/.next/server/app/(dashboard)/feature/[featureId]/page_client-reference-manifest.js +1 -1
  149. package/web/.next/server/app/(dashboard)/page/server-reference-manifest.json +69 -54
  150. package/web/.next/server/app/(dashboard)/page.js +1 -2
  151. package/web/.next/server/app/(dashboard)/page.js.nft.json +1 -1
  152. package/web/.next/server/app/(dashboard)/page_client-reference-manifest.js +1 -1
  153. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/[tab]/page/server-reference-manifest.json +71 -56
  154. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/[tab]/page.js +1 -2
  155. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/[tab]/page.js.nft.json +1 -1
  156. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/[tab]/page_client-reference-manifest.js +1 -1
  157. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page/server-reference-manifest.json +71 -56
  158. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page.js +1 -2
  159. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page.js.nft.json +1 -1
  160. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page_client-reference-manifest.js +1 -1
  161. package/web/.next/server/app/_global-error.html +2 -2
  162. package/web/.next/server/app/_global-error.rsc +1 -1
  163. package/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  164. package/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  165. package/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  166. package/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  167. package/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  168. package/web/.next/server/app/_not-found/page/server-reference-manifest.json +6 -6
  169. package/web/.next/server/app/_not-found/page.js.nft.json +1 -1
  170. package/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  171. package/web/.next/server/app/api/attachments/preview/route.js.nft.json +1 -1
  172. package/web/.next/server/app/api/evidence/route.js.nft.json +1 -1
  173. package/web/.next/server/app/api/graph-data/route.js.nft.json +1 -1
  174. package/web/.next/server/app/api/interactive/chat/[featureId]/messages/route.js.nft.json +1 -1
  175. package/web/.next/server/app/features/page/server-reference-manifest.json +6 -6
  176. package/web/.next/server/app/features/page.js.nft.json +1 -1
  177. package/web/.next/server/app/features/page_client-reference-manifest.js +1 -1
  178. package/web/.next/server/app/settings/page/server-reference-manifest.json +9 -9
  179. package/web/.next/server/app/settings/page.js.nft.json +1 -1
  180. package/web/.next/server/app/settings/page_client-reference-manifest.js +1 -1
  181. package/web/.next/server/app/skills/page/server-reference-manifest.json +13 -13
  182. package/web/.next/server/app/skills/page.js.nft.json +1 -1
  183. package/web/.next/server/app/skills/page_client-reference-manifest.js +1 -1
  184. package/web/.next/server/app/tools/page/server-reference-manifest.json +11 -11
  185. package/web/.next/server/app/tools/page.js.nft.json +1 -1
  186. package/web/.next/server/app/tools/page_client-reference-manifest.js +1 -1
  187. package/web/.next/server/app/version/page/server-reference-manifest.json +6 -6
  188. package/web/.next/server/app/version/page.js.nft.json +1 -1
  189. package/web/.next/server/app/version/page_client-reference-manifest.js +1 -1
  190. package/web/.next/server/chunks/[root-of-the-server]__a402b567._.js +1 -1
  191. package/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_create-drawer-client_tsx_5e26fc0a._.js +1 -1
  192. package/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_create-drawer-client_tsx_5e26fc0a._.js.map +1 -1
  193. package/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_feature-drawer-client_tsx_e9755fc8._.js +2 -2
  194. package/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_feature-drawer-client_tsx_e9755fc8._.js.map +1 -1
  195. package/web/.next/server/chunks/ssr/[root-of-the-server]__1cd4327c._.js +1 -1
  196. package/web/.next/server/chunks/ssr/[root-of-the-server]__1cd4327c._.js.map +1 -1
  197. package/web/.next/server/chunks/ssr/[root-of-the-server]__1f389e5d._.js +1 -1
  198. package/web/.next/server/chunks/ssr/[root-of-the-server]__1f389e5d._.js.map +1 -1
  199. package/web/.next/server/chunks/ssr/[root-of-the-server]__23b5ca2c._.js +1 -1
  200. package/web/.next/server/chunks/ssr/[root-of-the-server]__357d99f9._.js +1 -1
  201. package/web/.next/server/chunks/ssr/[root-of-the-server]__46b10380._.js +3 -0
  202. package/web/.next/server/chunks/ssr/[root-of-the-server]__46b10380._.js.map +1 -0
  203. package/web/.next/server/chunks/ssr/[root-of-the-server]__540c615f._.js +2 -2
  204. package/web/.next/server/chunks/ssr/[root-of-the-server]__6c7d3936._.js +1 -1
  205. package/web/.next/server/chunks/ssr/[root-of-the-server]__6c7d3936._.js.map +1 -1
  206. package/web/.next/server/chunks/ssr/[root-of-the-server]__7528eb6f._.js +1 -1
  207. package/web/.next/server/chunks/ssr/[root-of-the-server]__8b512877._.js +3 -0
  208. package/web/.next/server/chunks/ssr/[root-of-the-server]__8b512877._.js.map +1 -0
  209. package/web/.next/server/chunks/ssr/[root-of-the-server]__990dba2d._.js +3 -0
  210. package/web/.next/server/chunks/ssr/[root-of-the-server]__990dba2d._.js.map +1 -0
  211. package/web/.next/server/chunks/ssr/[root-of-the-server]__b7b96453._.js +1 -1
  212. package/web/.next/server/chunks/ssr/[root-of-the-server]__b7b96453._.js.map +1 -1
  213. package/web/.next/server/chunks/ssr/[root-of-the-server]__cc9c7bbb._.js +3 -0
  214. package/web/.next/server/chunks/ssr/[root-of-the-server]__cc9c7bbb._.js.map +1 -0
  215. package/web/.next/server/chunks/ssr/_05c23ad9._.js +1 -1
  216. package/web/.next/server/chunks/ssr/_05c23ad9._.js.map +1 -1
  217. package/web/.next/server/chunks/ssr/_16eb4fec._.js +1 -1
  218. package/web/.next/server/chunks/ssr/_16eb4fec._.js.map +1 -1
  219. package/web/.next/server/chunks/ssr/_35b56ded._.js +3 -0
  220. package/web/.next/server/chunks/ssr/_35b56ded._.js.map +1 -0
  221. package/web/.next/server/chunks/ssr/{_4cbb7f95._.js → _496c9117._.js} +2 -2
  222. package/web/.next/server/chunks/ssr/{_4cbb7f95._.js.map → _496c9117._.js.map} +1 -1
  223. package/web/.next/server/chunks/ssr/{_3fc2374c._.js → _49b9ba41._.js} +2 -2
  224. package/web/.next/server/chunks/ssr/_49b9ba41._.js.map +1 -0
  225. package/web/.next/server/chunks/ssr/_56b9d60f._.js +1 -1
  226. package/web/.next/server/chunks/ssr/_56b9d60f._.js.map +1 -1
  227. package/web/.next/server/chunks/ssr/_64efdf53._.js +3 -0
  228. package/web/.next/server/chunks/ssr/_64efdf53._.js.map +1 -0
  229. package/web/.next/server/chunks/ssr/_6abfa39e._.js +1 -1
  230. package/web/.next/server/chunks/ssr/{_19a779c6._.js → _83e1c526._.js} +2 -2
  231. package/web/.next/server/chunks/ssr/{_19a779c6._.js.map → _83e1c526._.js.map} +1 -1
  232. package/web/.next/server/chunks/ssr/_f8c55130._.js +1 -1
  233. package/web/.next/server/chunks/ssr/b1a17_presentation_web_components_features_settings_settings-page-client_tsx_6ed9d5f8._.js +1 -1
  234. package/web/.next/server/chunks/ssr/b1a17_presentation_web_components_features_settings_settings-page-client_tsx_6ed9d5f8._.js.map +1 -1
  235. package/web/.next/server/chunks/ssr/f3a1f_components_common_control-center-drawer_repository-drawer-client_tsx_39a00c03._.js +1 -1
  236. package/web/.next/server/chunks/ssr/f3a1f_components_common_control-center-drawer_repository-drawer-client_tsx_39a00c03._.js.map +1 -1
  237. package/web/.next/server/chunks/ssr/src_presentation_web_06109d28._.js +5 -0
  238. package/web/.next/server/chunks/ssr/src_presentation_web_06109d28._.js.map +1 -0
  239. package/web/.next/server/chunks/ssr/src_presentation_web_0bca70f8._.js +3 -0
  240. package/web/.next/server/chunks/ssr/src_presentation_web_0bca70f8._.js.map +1 -0
  241. package/web/.next/server/chunks/ssr/src_presentation_web_367cdbe0._.js +3 -0
  242. package/web/.next/server/chunks/ssr/src_presentation_web_367cdbe0._.js.map +1 -0
  243. package/web/.next/server/chunks/ssr/src_presentation_web_57fed7fd._.js +3 -0
  244. package/web/.next/server/chunks/ssr/src_presentation_web_57fed7fd._.js.map +1 -0
  245. package/web/.next/server/chunks/ssr/src_presentation_web_7f567f6d._.js +3 -0
  246. package/web/.next/server/chunks/ssr/src_presentation_web_7f567f6d._.js.map +1 -0
  247. package/web/.next/server/chunks/ssr/src_presentation_web_972f58d5._.js +3 -0
  248. package/web/.next/server/chunks/ssr/src_presentation_web_972f58d5._.js.map +1 -0
  249. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_skills_page_actions_4ce30db7.js +1 -1
  250. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_skills_page_actions_4ce30db7.js.map +1 -1
  251. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_tools_page_actions_e4032193.js +1 -1
  252. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_tools_page_actions_e4032193.js.map +1 -1
  253. package/web/.next/server/chunks/ssr/src_presentation_web_a71b18a2._.js +3 -0
  254. package/web/.next/server/chunks/ssr/src_presentation_web_a71b18a2._.js.map +1 -0
  255. package/web/.next/server/chunks/ssr/src_presentation_web_app_features_feature-tree-page-client_tsx_34c5cbbf._.js +2 -2
  256. package/web/.next/server/chunks/ssr/src_presentation_web_app_features_feature-tree-page-client_tsx_34c5cbbf._.js.map +1 -1
  257. package/web/.next/server/chunks/ssr/src_presentation_web_bebe675e._.js +3 -0
  258. package/web/.next/server/chunks/ssr/src_presentation_web_bebe675e._.js.map +1 -0
  259. package/web/.next/server/chunks/ssr/src_presentation_web_c93e8bc6._.js +3 -0
  260. package/web/.next/server/chunks/ssr/src_presentation_web_c93e8bc6._.js.map +1 -0
  261. package/web/.next/server/chunks/ssr/src_presentation_web_components_895e5bfa._.js +1 -1
  262. package/web/.next/server/chunks/ssr/src_presentation_web_components_895e5bfa._.js.map +1 -1
  263. package/web/.next/server/chunks/ssr/src_presentation_web_components_features_control-center_7ac3562e._.js +1 -1
  264. package/web/.next/server/chunks/ssr/src_presentation_web_components_features_control-center_7ac3562e._.js.map +1 -1
  265. package/web/.next/server/chunks/ssr/src_presentation_web_components_features_skills_8a174cac._.js +1 -1
  266. package/web/.next/server/chunks/ssr/src_presentation_web_components_features_skills_8a174cac._.js.map +1 -1
  267. package/web/.next/server/chunks/ssr/src_presentation_web_e729f44a._.js +5 -0
  268. package/web/.next/server/chunks/ssr/src_presentation_web_e729f44a._.js.map +1 -0
  269. package/web/.next/server/chunks/ssr/translations_23dd5e7e._.js +1 -1
  270. package/web/.next/server/chunks/ssr/translations_23dd5e7e._.js.map +1 -1
  271. package/web/.next/server/pages/500.html +2 -2
  272. package/web/.next/server/server-reference-manifest.js +1 -1
  273. package/web/.next/server/server-reference-manifest.json +590 -484
  274. package/web/.next/static/chunks/{18f429029d702545.js → 0b7251e5d717dd17.js} +1 -1
  275. package/web/.next/static/chunks/0fd39d549d277843.js +1 -0
  276. package/web/.next/static/chunks/124b79a5d2a760fb.css +1 -0
  277. package/web/.next/static/chunks/{b5a916fec4cdc897.js → 25a0d3f50b0a26c1.js} +1 -1
  278. package/web/.next/static/chunks/{829d2f8ef2715f2f.js → 2cc487403c107f3f.js} +3 -3
  279. package/web/.next/static/chunks/{0d0e2661bd167e0f.js → 35bf9838f21d1818.js} +1 -1
  280. package/web/.next/static/chunks/{b5d355eb59916926.js → 36e3d626ed8defca.js} +2 -2
  281. package/web/.next/static/chunks/4052a4971fbbac9c.js +1 -0
  282. package/web/.next/static/chunks/{c0e4cd44851a9293.js → 5df9da8b40e298ee.js} +1 -1
  283. package/web/.next/static/chunks/{efd57b6ffc7cbd54.js → 5f57f0d80d3db147.js} +1 -1
  284. package/web/.next/static/chunks/{bb479c31b5b53bac.js → 74c37f189bc83156.js} +2 -2
  285. package/web/.next/static/chunks/8057357cf1f9b4ef.js +1 -0
  286. package/web/.next/static/chunks/{eaa1b979d63d322b.js → 8286914ac835a1cc.js} +1 -1
  287. package/web/.next/static/chunks/{0a706f8508eae0a8.js → 8777b2a0a2e85fd1.js} +2 -2
  288. package/web/.next/static/chunks/{77d6506c7d1f711f.js → 9e9cddf8e38342e8.js} +1 -1
  289. package/web/.next/static/chunks/ac586c86d71187fc.js +1 -0
  290. package/web/.next/static/chunks/{ef897f150084ef85.js → c6fdd161a9e5b554.js} +1 -1
  291. package/web/.next/static/chunks/{4c20d4cd4786a0c8.js → e167803ac69c66c7.js} +1 -1
  292. package/web/.next/server/chunks/ssr/744ca_web__next-internal_server_app_(dashboard)_@drawer_adopt_page_actions_ad0071c9.js +0 -3
  293. package/web/.next/server/chunks/ssr/744ca_web__next-internal_server_app_(dashboard)_@drawer_adopt_page_actions_ad0071c9.js.map +0 -1
  294. package/web/.next/server/chunks/ssr/744ca_web__next-internal_server_app_(dashboard)_@drawer_chat_page_actions_90d98b2b.js +0 -3
  295. package/web/.next/server/chunks/ssr/744ca_web__next-internal_server_app_(dashboard)_@drawer_chat_page_actions_90d98b2b.js.map +0 -1
  296. package/web/.next/server/chunks/ssr/744ca_web__next-internal_server_app_(dashboard)_chat_page_actions_d3828105.js +0 -3
  297. package/web/.next/server/chunks/ssr/744ca_web__next-internal_server_app_(dashboard)_chat_page_actions_d3828105.js.map +0 -1
  298. package/web/.next/server/chunks/ssr/[root-of-the-server]__51ec77a8._.js +0 -3
  299. package/web/.next/server/chunks/ssr/[root-of-the-server]__51ec77a8._.js.map +0 -1
  300. package/web/.next/server/chunks/ssr/[root-of-the-server]__66047a1b._.js +0 -3
  301. package/web/.next/server/chunks/ssr/[root-of-the-server]__66047a1b._.js.map +0 -1
  302. package/web/.next/server/chunks/ssr/[root-of-the-server]__a932cd3a._.js +0 -3
  303. package/web/.next/server/chunks/ssr/[root-of-the-server]__a932cd3a._.js.map +0 -1
  304. package/web/.next/server/chunks/ssr/[root-of-the-server]__aa72e794._.js +0 -3
  305. package/web/.next/server/chunks/ssr/[root-of-the-server]__aa72e794._.js.map +0 -1
  306. package/web/.next/server/chunks/ssr/_073183f4._.js +0 -3
  307. package/web/.next/server/chunks/ssr/_073183f4._.js.map +0 -1
  308. package/web/.next/server/chunks/ssr/_3fc2374c._.js.map +0 -1
  309. package/web/.next/server/chunks/ssr/_57b1af27._.js +0 -3
  310. package/web/.next/server/chunks/ssr/_57b1af27._.js.map +0 -1
  311. package/web/.next/server/chunks/ssr/src_presentation_web_17d39233._.js +0 -3
  312. package/web/.next/server/chunks/ssr/src_presentation_web_17d39233._.js.map +0 -1
  313. package/web/.next/server/chunks/ssr/src_presentation_web_54b02639._.js +0 -5
  314. package/web/.next/server/chunks/ssr/src_presentation_web_54b02639._.js.map +0 -1
  315. package/web/.next/server/chunks/ssr/src_presentation_web_7b7b9e3b._.js +0 -5
  316. package/web/.next/server/chunks/ssr/src_presentation_web_7b7b9e3b._.js.map +0 -1
  317. package/web/.next/server/chunks/ssr/src_presentation_web_807cba76._.js +0 -3
  318. package/web/.next/server/chunks/ssr/src_presentation_web_807cba76._.js.map +0 -1
  319. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_90b5e66e.js +0 -3
  320. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_90b5e66e.js.map +0 -1
  321. package/web/.next/server/chunks/ssr/src_presentation_web_app_actions_open-ide_ts_baaca5d5._.js +0 -3
  322. package/web/.next/server/chunks/ssr/src_presentation_web_app_actions_open-ide_ts_baaca5d5._.js.map +0 -1
  323. package/web/.next/server/chunks/ssr/src_presentation_web_e1cd1869._.js +0 -3
  324. package/web/.next/server/chunks/ssr/src_presentation_web_e1cd1869._.js.map +0 -1
  325. package/web/.next/server/chunks/ssr/src_presentation_web_e3a30e30._.js +0 -3
  326. package/web/.next/server/chunks/ssr/src_presentation_web_e3a30e30._.js.map +0 -1
  327. package/web/.next/static/chunks/3fc5b2287f192799.js +0 -1
  328. package/web/.next/static/chunks/a20f2d6f76f469b7.css +0 -1
  329. package/web/.next/static/chunks/ddd34e939acc204f.js +0 -1
  330. package/web/.next/static/chunks/f9d948464ed409cb.js +0 -1
  331. package/web/.next/static/chunks/fc0232384ec2b48d.js +0 -1
  332. /package/web/.next/static/{UZ2czjiAnEl1RF-HTzHyA → sfBZvlx-erv7S1C49vRSU}/_buildManifest.js +0 -0
  333. /package/web/.next/static/{UZ2czjiAnEl1RF-HTzHyA → sfBZvlx-erv7S1C49vRSU}/_clientMiddlewareManifest.json +0 -0
  334. /package/web/.next/static/{UZ2czjiAnEl1RF-HTzHyA → sfBZvlx-erv7S1C49vRSU}/_ssgManifest.js +0 -0
@@ -21,7 +21,9 @@ export interface RepositoryNodeData {
21
21
  gitInfoStatus?: 'loading' | 'ready' | 'not-a-repo';
22
22
  onClick?: () => void;
23
23
  onAdd?: () => void;
24
- onDelete?: (repositoryId: string) => void;
24
+ onDelete?: (repositoryId: string, options?: {
25
+ deleteFromDisk?: boolean;
26
+ }) => void;
25
27
  showHandles?: boolean;
26
28
  /** When true, the "+" add-feature button shows a pulse attention animation. */
27
29
  pulseAdd?: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"repository-node-config.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/repository-node/repository-node-config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAE1C,MAAM,WAAW,kBAAkB;IACjC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;IACvB,qEAAqE;IACrE,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,2CAA2C;IAC3C,IAAI,EAAE,MAAM,CAAC;IACb,uEAAuE;IACvE,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,yEAAyE;IACzE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,+DAA+D;IAC/D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,0DAA0D;IAC1D,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,oDAAoD;IACpD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,+GAA+G;IAC/G,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,oHAAoH;IACpH,aAAa,CAAC,EAAE,SAAS,GAAG,OAAO,GAAG,YAAY,CAAC;IACnD,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,IAAI,CAAC;IACnB,QAAQ,CAAC,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1C,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,+EAA+E;IAC/E,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,MAAM,kBAAkB,GAAG,IAAI,CAAC,kBAAkB,EAAE,gBAAgB,CAAC,CAAC"}
1
+ {"version":3,"file":"repository-node-config.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/repository-node/repository-node-config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAE1C,MAAM,WAAW,kBAAkB;IACjC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;IACvB,qEAAqE;IACrE,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,2CAA2C;IAC3C,IAAI,EAAE,MAAM,CAAC;IACb,uEAAuE;IACvE,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,yEAAyE;IACzE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,+DAA+D;IAC/D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,0DAA0D;IAC1D,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,oDAAoD;IACpD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,+GAA+G;IAC/G,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,oHAAoH;IACpH,aAAa,CAAC,EAAE,SAAS,GAAG,OAAO,GAAG,YAAY,CAAC;IACnD,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,IAAI,CAAC;IACnB,QAAQ,CAAC,EAAE,CAAC,YAAY,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,cAAc,CAAC,EAAE,OAAO,CAAA;KAAE,KAAK,IAAI,CAAC;IAClF,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,+EAA+E;IAC/E,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,MAAM,kBAAkB,GAAG,IAAI,CAAC,kBAAkB,EAAE,gBAAgB,CAAC,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"repository-node.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/repository-node/repository-node.tsx"],"names":[],"mappings":"AAqCA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AASnE,wBAAgB,cAAc,CAAC,EAC7B,IAAI,EACJ,QAAQ,GACT,EAAE;IACD,IAAI,EAAE,kBAAkB,CAAC;IACzB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB,2CA2cA"}
1
+ {"version":3,"file":"repository-node.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/repository-node/repository-node.tsx"],"names":[],"mappings":"AAuCA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AASnE,wBAAgB,cAAc,CAAC,EAC7B,IAAI,EACJ,QAAQ,GACT,EAAE;IACD,IAAI,EAAE,kBAAkB,CAAC;IACzB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB,2CAueA"}
@@ -1,14 +1,16 @@
1
1
  'use client';
2
2
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
- import { useState, useCallback } from 'react';
3
+ import { useState, useCallback, useEffect } from 'react';
4
4
  import { Handle, Position } from '@xyflow/react';
5
5
  import { useRouter } from 'next/navigation';
6
6
  import { Github, Plus, Code2, Terminal, FolderOpen, Trash2, Play, Square, GitBranch, GitCommitHorizontal, ArrowDown, User, RotateCcw, MessageSquare, } from 'lucide-react';
7
- import { useTranslation } from 'react-i18next';
7
+ import { Trans, useTranslation } from 'react-i18next';
8
8
  import { cn } from '../../../lib/utils.js';
9
9
  import { ActionButton } from '../../common/action-button/index.js';
10
10
  import { Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from '../../ui/dialog.js';
11
11
  import { Button } from '../../ui/button.js';
12
+ import { Checkbox } from '../../ui/checkbox.js';
13
+ import { Label } from '../../ui/label.js';
12
14
  import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '../../ui/tooltip.js';
13
15
  import { useDeployAction } from '../../../hooks/use-deploy-action.js';
14
16
  import { useFeatureFlags } from '../../../hooks/feature-flags-context.js';
@@ -24,6 +26,11 @@ export function RepositoryNode({ data, selected, }) {
24
26
  const sourceHandlePos = isRtl ? Position.Left : Position.Right;
25
27
  const featureFlags = useFeatureFlags();
26
28
  const [confirmOpen, setConfirmOpen] = useState(false);
29
+ const [deleteFromDisk, setDeleteFromDisk] = useState(false);
30
+ useEffect(() => {
31
+ if (confirmOpen)
32
+ setDeleteFromDisk(false);
33
+ }, [confirmOpen]);
27
34
  const repoScopeId = data.id ? `repo-${data.id}` : `repo-${data.name}`;
28
35
  const chatTurnStatus = useTurnStatus(repoScopeId);
29
36
  const actions = useRepositoryActions(data.repositoryPath ? { repositoryId: data.id, repositoryPath: data.repositoryPath } : null);
@@ -68,9 +75,11 @@ export function RepositoryNode({ data, selected, }) {
68
75
  return (_jsxs("div", { className: cn('group relative', data.onDelete && data.id && 'ps-10'), style: { direction: isRtl ? 'rtl' : 'ltr' }, children: [data.showHandles ? (_jsx(Handle, { type: "target", position: targetHandlePos, isConnectable: false, className: "opacity-0!", style: { top: 70 } })) : null, data.onDelete && data.id ? (_jsxs(_Fragment, { children: [_jsx("div", { className: "absolute -start-3 top-1/2 -translate-y-1/2 opacity-0 transition-opacity group-hover:opacity-100", children: _jsx(TooltipProvider, { children: _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("button", { "aria-label": t('repositoryNode.removeRepository'), "data-testid": "repository-node-delete-button", onClick: (e) => {
69
76
  e.stopPropagation();
70
77
  setConfirmOpen(true);
71
- }, className: "bg-card text-muted-foreground hover:border-destructive hover:text-destructive flex h-7 w-7 cursor-pointer items-center justify-center rounded-full border shadow-sm transition-colors", children: _jsx(Trash2, { className: "h-3.5 w-3.5" }) }) }), _jsx(TooltipContent, { children: t('repositoryNode.removeRepository') })] }) }) }), _jsx(Dialog, { open: confirmOpen, onOpenChange: setConfirmOpen, children: _jsxs(DialogContent, { className: "max-w-xs", children: [_jsxs(DialogHeader, { children: [_jsx(DialogTitle, { children: t('repositoryNode.removeConfirmTitle') }), _jsx(DialogDescription, { children: t('repositoryNode.removeConfirmDescription', { name: data.name }) })] }), _jsxs(DialogFooter, { className: "grid grid-cols-2 gap-2 sm:flex-none", children: [_jsx(DialogClose, { asChild: true, children: _jsx(Button, { variant: "outline", children: t('repositoryNode.cancel') }) }), _jsx(Button, { variant: "destructive", onClick: () => {
78
+ }, className: "bg-card text-muted-foreground hover:border-destructive hover:text-destructive flex h-7 w-7 cursor-pointer items-center justify-center rounded-full border shadow-sm transition-colors", children: _jsx(Trash2, { className: "h-3.5 w-3.5" }) }) }), _jsx(TooltipContent, { children: t('repositoryNode.removeRepository') })] }) }) }), _jsx(Dialog, { open: confirmOpen, onOpenChange: setConfirmOpen, children: _jsxs(DialogContent, { className: "max-w-sm", children: [_jsxs(DialogHeader, { children: [_jsx(DialogTitle, { children: t('repositoryNode.removeConfirmTitle') }), _jsxs(DialogDescription, { children: [_jsx(Trans, { t: t, i18nKey: "repositoryNode.removeConfirmDescription", values: { name: data.name }, components: { strong: _jsx("strong", {}) } }), ' ', deleteFromDisk
79
+ ? t('repositoryNode.removeConfirmDescriptionDeleteFiles')
80
+ : t('repositoryNode.removeConfirmDescriptionKeepFiles')] })] }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Checkbox, { id: "repository-delete-from-disk", checked: deleteFromDisk, onCheckedChange: (checked) => setDeleteFromDisk(checked === true), "data-testid": "repository-node-delete-from-disk-checkbox", "aria-label": t('repositoryNode.deleteFromDiskLabel') }), _jsx(Label, { htmlFor: "repository-delete-from-disk", className: "cursor-pointer text-sm font-normal", children: t('repositoryNode.deleteFromDiskLabel') })] }), _jsxs(DialogFooter, { className: "grid grid-cols-2 gap-2 sm:flex-none", children: [_jsx(DialogClose, { asChild: true, children: _jsx(Button, { variant: "outline", children: t('repositoryNode.cancel') }) }), _jsx(Button, { variant: "destructive", "data-testid": "repository-node-delete-confirm-button", onClick: () => {
72
81
  setConfirmOpen(false);
73
- data.onDelete?.(data.id);
82
+ data.onDelete?.(data.id, { deleteFromDisk });
74
83
  }, children: t('repositoryNode.remove') })] })] }) })] })) : null, _jsxs("div", { role: "button", tabIndex: 0, "data-testid": "repository-node-card", "data-repo-name": data.name, onClick: (e) => {
75
84
  e.stopPropagation();
76
85
  data.onClick?.();
@@ -1 +1 @@
1
- {"version":3,"file":"control-center-empty-state.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/control-center/control-center-empty-state.tsx"],"names":[],"mappings":"AA0BA,MAAM,WAAW,4BAA4B;IAC3C,kBAAkB,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5C,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAID,wBAAgB,uBAAuB,CAAC,EACtC,kBAAkB,EAClB,SAAS,GACV,EAAE,4BAA4B,kDAoM9B"}
1
+ {"version":3,"file":"control-center-empty-state.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/control-center/control-center-empty-state.tsx"],"names":[],"mappings":"AA4BA,MAAM,WAAW,4BAA4B;IAC3C,kBAAkB,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5C,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAID,wBAAgB,uBAAuB,CAAC,EACtC,kBAAkB,EAClB,SAAS,GACV,EAAE,4BAA4B,kDAsN9B"}
@@ -1,7 +1,7 @@
1
1
  'use client';
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { useState, useCallback, useEffect } from 'react';
4
- import { FolderOpen, Copy, Check, Loader2, CheckCircle2, AlertCircle, Terminal, ChevronDown, ExternalLink, } from 'lucide-react';
4
+ import { FolderOpen, FolderPlus, Copy, Check, Loader2, CheckCircle2, AlertCircle, Terminal, ChevronDown, ExternalLink, } from 'lucide-react';
5
5
  import { useTranslation } from 'react-i18next';
6
6
  import { cn } from '../../../lib/utils.js';
7
7
  import { pickFolder } from '../../common/add-repository-button/pick-folder.js';
@@ -11,6 +11,7 @@ import { isAgentSetupComplete } from '../../../app/actions/agent-setup-flag.js';
11
11
  import { checkAgentAuth } from '../../../app/actions/check-agent-auth.js';
12
12
  import { checkToolStatus } from '../../../app/actions/check-tool-status.js';
13
13
  import { WelcomeAgentSetup } from './welcome-agent-setup.js';
14
+ import { NewProjectDialog } from './new-project-dialog.js';
14
15
  const commands = ['cd ~/my-repo', 'shep feat new "sleek dashboard"'];
15
16
  export function ControlCenterEmptyState({ onRepositorySelect, className, }) {
16
17
  const { t } = useTranslation('web');
@@ -21,6 +22,7 @@ export function ControlCenterEmptyState({ onRepositorySelect, className, }) {
21
22
  const [authStatus, setAuthStatus] = useState(null);
22
23
  const [cliExpanded, setCliExpanded] = useState(false);
23
24
  const [toolStatus, setToolStatus] = useState(null);
25
+ const [newProjectOpen, setNewProjectOpen] = useState(false);
24
26
  const { reactFileManager: useReactFileManager } = useFeatureFlags();
25
27
  useEffect(() => {
26
28
  isAgentSetupComplete().then((done) => {
@@ -79,14 +81,14 @@ export function ControlCenterEmptyState({ onRepositorySelect, className, }) {
79
81
  /* Agent setup wizard — owns its own hero */
80
82
  _jsx(WelcomeAgentSetup, { onComplete: handleAgentSetupComplete })) : (
81
83
  /* Repository step — fade in to match wizard transitions */
82
- _jsxs("div", { className: "animate-in fade-in flex w-full max-w-md flex-col items-center duration-300", children: [_jsx("h1", { className: "text-foreground/90 text-center text-5xl font-extralight tracking-tight", children: t('emptyState.addProject') }), _jsxs("p", { className: "text-muted-foreground mt-3 text-center text-lg leading-relaxed font-light", children: [t('emptyState.addProjectDescription'), _jsx("br", {}), t('emptyState.addProjectDescriptionLine2')] }), _jsxs("div", { className: "mt-8 flex w-full flex-col gap-3", children: [_jsx(AgentAuthBanner, { status: authStatus, onRetry: handleRetryAuth }), _jsx(ToolStatusRow, { label: t('emptyState.git'), status: toolStatus?.git ?? null, missingHint: t('emptyState.gitRequired') }), _jsx(ToolStatusRow, { label: t('emptyState.githubCli'), status: toolStatus?.gh ?? null, missingHint: t('emptyState.githubCliRequired') })] }), _jsxs("button", { type: "button", "data-testid": "empty-state-add-repository", onClick: handlePickerClick, disabled: loading, className: "bg-foreground text-background hover:bg-foreground/90 mt-10 flex w-full cursor-pointer items-center justify-center gap-2.5 rounded-xl px-6 py-4 text-base font-medium shadow-lg transition-all duration-200 hover:shadow-xl active:scale-[0.98] disabled:cursor-wait disabled:opacity-50", children: [loading ? (_jsx(Loader2, { className: "h-5 w-5 animate-spin" })) : (_jsx(FolderOpen, { className: "h-5 w-5" })), loading ? t('emptyState.opening') : t('emptyState.chooseFolder')] }), _jsx("p", { className: "text-muted-foreground/60 mt-3 text-center text-sm", children: t('emptyState.folderHint') })] })), agentReady ? (_jsxs("div", { className: "absolute bottom-8 flex flex-col items-center", style: {
84
+ _jsxs("div", { className: "animate-in fade-in flex w-full max-w-md flex-col items-center duration-300", children: [_jsx("h1", { className: "text-foreground/90 text-center text-5xl font-extralight tracking-tight", children: t('emptyState.addProject') }), _jsxs("p", { className: "text-muted-foreground mt-3 text-center text-lg leading-relaxed font-light", children: [t('emptyState.addProjectDescription'), _jsx("br", {}), t('emptyState.addProjectDescriptionLine2')] }), _jsxs("div", { className: "mt-8 flex w-full flex-col gap-3", children: [_jsx(AgentAuthBanner, { status: authStatus, onRetry: handleRetryAuth }), _jsx(ToolStatusRow, { label: t('emptyState.git'), status: toolStatus?.git ?? null, missingHint: t('emptyState.gitRequired') }), _jsx(ToolStatusRow, { label: t('emptyState.githubCli'), status: toolStatus?.gh ?? null, missingHint: t('emptyState.githubCliRequired') })] }), _jsxs("button", { type: "button", "data-testid": "empty-state-add-repository", onClick: handlePickerClick, disabled: loading, className: "bg-foreground text-background hover:bg-foreground/90 mt-10 flex w-full cursor-pointer items-center justify-center gap-2.5 rounded-xl px-6 py-4 text-base font-medium shadow-lg transition-all duration-200 hover:shadow-xl active:scale-[0.98] disabled:cursor-wait disabled:opacity-50", children: [loading ? (_jsx(Loader2, { className: "h-5 w-5 animate-spin" })) : (_jsx(FolderOpen, { className: "h-5 w-5" })), loading ? t('emptyState.opening') : t('emptyState.chooseFolder')] }), _jsxs("button", { type: "button", "data-testid": "empty-state-new-project", onClick: () => setNewProjectOpen(true), disabled: loading, className: "border-foreground/15 text-foreground/80 hover:bg-foreground/5 hover:border-foreground/25 mt-3 flex w-full cursor-pointer items-center justify-center gap-2.5 rounded-xl border px-6 py-3.5 text-sm font-medium transition-all duration-200 active:scale-[0.98] disabled:cursor-not-allowed disabled:opacity-50", children: [_jsx(FolderPlus, { className: "h-4 w-4" }), "New Project"] }), _jsx("p", { className: "text-muted-foreground/60 mt-3 text-center text-sm", children: t('emptyState.folderHint') })] })), agentReady ? (_jsxs("div", { className: "absolute bottom-8 flex flex-col items-center", style: {
83
85
  animationDelay: '400ms',
84
86
  animationDuration: '600ms',
85
87
  animationFillMode: 'both',
86
88
  }, children: [_jsxs("button", { type: "button", onClick: () => setCliExpanded(!cliExpanded), className: "text-muted-foreground hover:text-foreground flex cursor-pointer items-center gap-1.5 transition-colors duration-200", children: [_jsx(Terminal, { className: "h-3.5 w-3.5" }), _jsx("span", { className: "text-sm", children: t('emptyState.orUseCli') }), _jsx(ChevronDown, { className: cn('h-3.5 w-3.5 transition-transform duration-200', cliExpanded ? '' : 'rotate-180') })] }), cliExpanded ? (_jsx("div", { className: "animate-in fade-in slide-in-from-top-1 mt-3 w-80 duration-200", children: _jsxs("div", { "data-testid": "cli-code-block", className: "relative rounded-xl bg-zinc-900 px-5 py-4 font-mono text-[13px] leading-relaxed text-zinc-400", children: [_jsx("button", { type: "button", "data-testid": "cli-code-block-copy", onClick: handleCopy, className: "absolute top-3 right-3 cursor-pointer rounded-md p-1.5 text-zinc-600 transition-colors hover:bg-zinc-800 hover:text-zinc-300", "aria-label": t('emptyState.copyCommands'), children: copied ? (_jsx(Check, { className: "h-3.5 w-3.5 text-emerald-400" })) : (_jsx(Copy, { className: "h-3.5 w-3.5" })) }), _jsx("div", { className: "space-y-1", children: commands.map((cmd) => (_jsxs("div", { className: "whitespace-nowrap", children: [_jsx("span", { className: "text-zinc-600 select-none", children: "$ " }), _jsx("span", { className: "text-zinc-300", children: cmd })] }, cmd))) })] }) })) : null] })) : null, _jsx(ReactFileManagerDialog, { open: showReactPicker, onOpenChange: (open) => {
87
89
  if (!open)
88
90
  setShowReactPicker(false);
89
- }, onSelect: handleReactPickerSelect })] }));
91
+ }, onSelect: handleReactPickerSelect }), _jsx(NewProjectDialog, { open: newProjectOpen, onOpenChange: setNewProjectOpen, onCreated: (path) => onRepositorySelect?.(path) })] }));
90
92
  }
91
93
  /** Status row for the AI agent (Claude Code, etc.) */
92
94
  function AgentAuthBanner({ status, onRetry, }) {
@@ -1 +1 @@
1
- {"version":3,"file":"control-center-inner.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/control-center/control-center-inner.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,IAAI,EAAY,MAAM,eAAe,CAAC;AAIpD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uCAAuC,CAAC;AAgC5E,UAAU,uBAAuB;IAC/B,YAAY,EAAE,cAAc,EAAE,CAAC;IAC/B,YAAY,EAAE,IAAI,EAAE,CAAC;CACtB;AAED,wBAAgB,kBAAkB,CAAC,EAAE,YAAY,EAAE,YAAY,EAAE,EAAE,uBAAuB,2CAiezF"}
1
+ {"version":3,"file":"control-center-inner.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/control-center/control-center-inner.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,IAAI,EAAY,MAAM,eAAe,CAAC;AAoBpD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uCAAuC,CAAC;AAoC5E,UAAU,uBAAuB;IAC/B,YAAY,EAAE,cAAc,EAAE,CAAC;IAC/B,YAAY,EAAE,IAAI,EAAE,CAAC;CACtB;AAED,wBAAgB,kBAAkB,CAAC,EAAE,YAAY,EAAE,YAAY,EAAE,EAAE,uBAAuB,2CA2iBzF"}
@@ -1,11 +1,18 @@
1
1
  'use client';
2
- import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
3
  import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
4
4
  import { useRouter, usePathname } from 'next/navigation';
5
- import { Sparkles, FolderPlus, Github, GitBranch } from 'lucide-react';
5
+ import { FolderPlus } from 'lucide-react';
6
6
  import { useReactFlow } from '@xyflow/react';
7
7
  import { FeaturesCanvas } from '../../features/features-canvas/index.js';
8
8
  import { CanvasToolbar } from '../../features/features-canvas/canvas-toolbar.js';
9
+ import { WorkspaceSelector } from '../../features/features-canvas/workspace-selector.js';
10
+ import { ManageWorkspaceDialog } from '../../features/features-canvas/manage-workspace-dialog.js';
11
+ import { WorkspaceNameDialog } from '../../features/features-canvas/workspace-name-dialog.js';
12
+ import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, } from '../../ui/alert-dialog.js';
13
+ import { useWorkspaces, DEFAULT_WORKSPACE_ID } from '../../../hooks/use-workspaces.js';
14
+ import { Layers, Plus } from 'lucide-react';
15
+ import { Button } from '../../ui/button.js';
9
16
  import { FloatingActionButton, } from '../../common/floating-action-button/index.js';
10
17
  import { useSidebarFeaturesContext, mapNodeStateToSidebarStatus, } from '../../../hooks/sidebar-features-context.js';
11
18
  import { useTranslation } from 'react-i18next';
@@ -18,7 +25,11 @@ import { useViewportPersistence } from '../../../hooks/use-viewport-persistence.
18
25
  import { useSidebar } from '../../ui/sidebar.js';
19
26
  import { useFabLayout } from '../../../hooks/fab-layout-context.js';
20
27
  import { ControlCenterEmptyState } from './control-center-empty-state.js';
28
+ import { NewProjectDialog } from './new-project-dialog.js';
21
29
  import { useControlCenterState } from './use-control-center-state.js';
30
+ import { useCanvasEventListeners } from './use-canvas-event-listeners.js';
31
+ import { useWorkspaceFitView } from './use-workspace-fit-view.js';
32
+ import { useFabActions } from './use-fab-actions.js';
22
33
  const AUTO_FOCUS_OPTIONS = {
23
34
  maxZoom: 1.0,
24
35
  padding: 0.5,
@@ -26,7 +37,6 @@ const AUTO_FOCUS_OPTIONS = {
26
37
  };
27
38
  const AUTO_FOCUS_DRAWER_DELAY_MS = 600;
28
39
  export function ControlCenterInner({ initialNodes, initialEdges }) {
29
- const { t } = useTranslation('web');
30
40
  const router = useRouter();
31
41
  const pathname = usePathname();
32
42
  const selectedFeatureId = useSelectedFeatureId();
@@ -37,6 +47,21 @@ export function ControlCenterInner({ initialNodes, initialEdges }) {
37
47
  const drawerTimerRef = useRef(null);
38
48
  const { defaultViewport, onMoveEnd: handleViewportChange, resetViewport, } = useViewportPersistence();
39
49
  const { nodes, edges, onNodesChange, handleConnect, handleAddRepository, handleArchiveFeature, handleDeleteFeature, handleRetryFeature, handleStartFeature, handleStopFeature, handleUnarchiveFeature, handleDeleteRepository, createFeatureNode, showArchived, setShowArchived, setCallbacks, } = useControlCenterState(initialNodes, initialEdges);
50
+ // ── Workspaces (client-only prototype) ────────────────────────────────
51
+ const { workspaces, activeWorkspace, isDefaultActive, setActiveWorkspace, createWorkspace, renameWorkspace, deleteWorkspace, setWorkspaceMembers, addToActiveWorkspace, } = useWorkspaces();
52
+ // Tracks the set of node ids we've already seen, so we can detect new
53
+ // repo/feature nodes appearing on the canvas and auto-include them in the
54
+ // active workspace (when it isn't the default).
55
+ const knownNodeIdsRef = useRef(new Set());
56
+ const [manageWorkspaceOpen, setManageWorkspaceOpen] = useState(false);
57
+ const [createWorkspaceOpen, setCreateWorkspaceOpen] = useState(false);
58
+ const [renameWorkspaceOpen, setRenameWorkspaceOpen] = useState(false);
59
+ const [deleteWorkspaceOpen, setDeleteWorkspaceOpen] = useState(false);
60
+ // Target of the delete confirmation dialog. Allows deleting any workspace
61
+ // (not just the active one) directly from the workspace dropdown.
62
+ const [pendingDeleteWorkspaceId, setPendingDeleteWorkspaceId] = useState(null);
63
+ // Inline "New Project" dialog launched from the empty-workspace state.
64
+ const [workspaceNewProjectOpen, setWorkspaceNewProjectOpen] = useState(false);
40
65
  // Publish sidebar features + repo state to context
41
66
  const { setFeatures: setSidebarFeatures, setHasRepositories: setSidebarHasRepos } = useSidebarFeaturesContext();
42
67
  const featureNodes = useMemo(() => nodes.filter((n) => n.type === 'featureNode'), [nodes]);
@@ -165,80 +190,26 @@ export function ControlCenterInner({ initialNodes, initialEdges }) {
165
190
  focusOnNode(tempNodeId);
166
191
  }
167
192
  }, [handleAddRepository, focusAndOpenDrawer, focusOnNode]);
168
- // Listen for global "add repository" events from the top bar button
193
+ // All five window-level CustomEvent listeners (add-repository, feature-
194
+ // created, delete/archive/unarchive requests) live in this hook so the
195
+ // parent component stays focused on graph state + rendering.
196
+ useCanvasEventListeners({
197
+ addRepoAndFocus,
198
+ createFeatureNode,
199
+ nodes,
200
+ handleDeleteFeature,
201
+ handleArchiveFeature,
202
+ handleUnarchiveFeature,
203
+ });
204
+ // Cleanup the drawer timer on unmount. Used to live inside the inlined
205
+ // shep:add-repository listener; now standalone since the listener moved.
169
206
  useEffect(() => {
170
- const handler = (e) => {
171
- const path = e.detail.path;
172
- addRepoAndFocus(path);
173
- };
174
- window.addEventListener('shep:add-repository', handler);
175
207
  return () => {
176
- window.removeEventListener('shep:add-repository', handler);
177
208
  if (drawerTimerRef.current != null) {
178
209
  clearTimeout(drawerTimerRef.current);
179
210
  }
180
211
  };
181
- }, [addRepoAndFocus]);
182
- // Listen for create events from the create drawer (with real feature ID from server)
183
- useEffect(() => {
184
- const handler = (e) => {
185
- const detail = e.detail;
186
- // When a parentId is provided, connect to the parent feature node
187
- // via a dependency edge instead of the repo node.
188
- if (detail.parentId) {
189
- const parentNodeId = `feat-${detail.parentId}`;
190
- createFeatureNode(parentNodeId, {
191
- state: 'creating',
192
- featureId: detail.featureId,
193
- name: detail.name,
194
- description: detail.description,
195
- repositoryPath: detail.repositoryPath,
196
- }, 'dependencyEdge');
197
- return;
198
- }
199
- // Find the repo node to connect to
200
- const repoNode = nodes.find((n) => n.type === 'repositoryNode' &&
201
- n.data.repositoryPath === detail.repositoryPath);
202
- createFeatureNode(repoNode?.id ?? null, {
203
- state: 'running',
204
- featureId: detail.featureId,
205
- name: detail.name,
206
- description: detail.description,
207
- repositoryPath: detail.repositoryPath,
208
- });
209
- };
210
- window.addEventListener('shep:feature-created', handler);
211
- return () => window.removeEventListener('shep:feature-created', handler);
212
- }, [nodes, createFeatureNode]);
213
- // Listen for delete requests from the feature drawer (fires when the user
214
- // confirms delete inside the drawer). Delegates to handleDeleteFeature so
215
- // the canvas gets optimistic state, mutation guard, and node removal.
216
- useEffect(() => {
217
- const handler = (e) => {
218
- const { featureId, cleanup, cascadeDelete, closePr } = e.detail;
219
- handleDeleteFeature(featureId, cleanup, cascadeDelete, closePr);
220
- };
221
- window.addEventListener('shep:feature-delete-requested', handler);
222
- return () => window.removeEventListener('shep:feature-delete-requested', handler);
223
- }, [handleDeleteFeature]);
224
- // Listen for archive requests from the feature drawer.
225
- useEffect(() => {
226
- const handler = (e) => {
227
- const { featureId } = e.detail;
228
- handleArchiveFeature(featureId);
229
- };
230
- window.addEventListener('shep:feature-archive-requested', handler);
231
- return () => window.removeEventListener('shep:feature-archive-requested', handler);
232
- }, [handleArchiveFeature]);
233
- // Listen for unarchive requests from the feature drawer.
234
- useEffect(() => {
235
- const handler = (e) => {
236
- const { featureId } = e.detail;
237
- handleUnarchiveFeature(featureId);
238
- };
239
- window.addEventListener('shep:feature-unarchive-requested', handler);
240
- return () => window.removeEventListener('shep:feature-unarchive-requested', handler);
241
- }, [handleUnarchiveFeature]);
212
+ }, []);
242
213
  // Wire callbacks into derived node data (via ref — no re-render).
243
214
  useEffect(() => {
244
215
  setCallbacks({
@@ -302,72 +273,111 @@ export function ControlCenterInner({ initialNodes, initialEdges }) {
302
273
  clearTimeout(latchTimerRef.current);
303
274
  };
304
275
  }, [hasRepositories, showCanvas, resetViewport]);
276
+ // Auto-include any newly-appearing repo/feature nodes in the active
277
+ // workspace (skipped when default is active — that workspace shows
278
+ // everything anyway). We diff the current node id list against the set
279
+ // we've already seen so we only add the deltas.
280
+ useEffect(() => {
281
+ const seen = knownNodeIdsRef.current;
282
+ const newRepoIds = [];
283
+ const newFeatureIds = [];
284
+ for (const n of nodes) {
285
+ if (seen.has(n.id))
286
+ continue;
287
+ seen.add(n.id);
288
+ if (n.type === 'repositoryNode')
289
+ newRepoIds.push(n.id);
290
+ else if (n.type === 'featureNode')
291
+ newFeatureIds.push(n.id);
292
+ }
293
+ if (isDefaultActive)
294
+ return;
295
+ if (newRepoIds.length === 0 && newFeatureIds.length === 0)
296
+ return;
297
+ addToActiveWorkspace({ repoIds: newRepoIds, featureIds: newFeatureIds });
298
+ }, [nodes, isDefaultActive, addToActiveWorkspace]);
299
+ // Filter nodes by the active workspace (default workspace = no filter).
300
+ // We always filter from the full `nodes` list so `displayNodes` already
301
+ // reflects workspace membership before pulse-add decoration runs.
302
+ const workspaceFilteredNodes = useMemo(() => {
303
+ if (isDefaultActive)
304
+ return nodes;
305
+ const allowedRepos = new Set(activeWorkspace.repoIds);
306
+ const allowedFeatures = new Set(activeWorkspace.featureIds);
307
+ return nodes.filter((n) => {
308
+ if (n.type === 'repositoryNode')
309
+ return allowedRepos.has(n.id);
310
+ if (n.type === 'featureNode')
311
+ return allowedFeatures.has(n.id);
312
+ return true;
313
+ });
314
+ }, [nodes, isDefaultActive, activeWorkspace]);
315
+ // Drop edges whose endpoints were filtered out.
316
+ const workspaceFilteredEdges = useMemo(() => {
317
+ if (isDefaultActive)
318
+ return edges;
319
+ const visibleIds = new Set(workspaceFilteredNodes.map((n) => n.id));
320
+ return edges.filter((e) => visibleIds.has(e.source) && visibleIds.has(e.target));
321
+ }, [edges, isDefaultActive, workspaceFilteredNodes]);
305
322
  // Pulse the "+" button when there's a single repo with no features and the
306
323
  // create-feature drawer is not open — draws attention to the next action.
307
324
  const isCreateDrawerOpen = pathname.startsWith('/create');
308
325
  const displayNodes = useMemo(() => {
309
- const repoNodes = nodes.filter((n) => n.type === 'repositoryNode');
310
- const hasFeatures = nodes.some((n) => n.type === 'featureNode');
326
+ const source = workspaceFilteredNodes;
327
+ const repoNodes = source.filter((n) => n.type === 'repositoryNode');
328
+ const hasFeatures = source.some((n) => n.type === 'featureNode');
311
329
  const shouldPulse = repoNodes.length === 1 && !hasFeatures && !isCreateDrawerOpen;
312
330
  if (!shouldPulse)
313
- return nodes;
314
- return nodes.map((n) => n.type === 'repositoryNode' ? { ...n, data: { ...n.data, pulseAdd: true } } : n);
315
- }, [nodes, isCreateDrawerOpen]);
331
+ return source;
332
+ return source.map((n) => n.type === 'repositoryNode' ? { ...n, data: { ...n.data, pulseAdd: true } } : n);
333
+ }, [workspaceFilteredNodes, isCreateDrawerOpen]);
316
334
  const handlePickFolder = useCallback(() => {
317
335
  window.dispatchEvent(new CustomEvent('shep:pick-folder'));
318
336
  }, []);
337
+ // Re-fit the viewport when the active workspace's visible node set changes.
338
+ // See use-workspace-fit-view.ts for the scoping rules.
339
+ useWorkspaceFitView({
340
+ activeWorkspace,
341
+ isDefaultActive,
342
+ workspaceFilteredNodes,
343
+ fitView,
344
+ });
345
+ // When the active (non-default) workspace has no members but real repos
346
+ // exist on the canvas, show a workspace-aware empty state instead of the
347
+ // welcome wizard. The wizard would imply "no repos at all", which is wrong
348
+ // here — and crucially, leaves the workspace selector visible via the
349
+ // toolbar so users can switch back to the default workspace.
350
+ const workspaceFilteredEmpty = hasRepositories && !isDefaultActive && workspaceFilteredNodes.length === 0;
351
+ const emptyStateNode = workspaceFilteredEmpty ? (_jsxs("div", { className: "pointer-events-auto flex h-full w-full flex-col items-center justify-center px-8", children: [_jsx("div", { className: "bg-primary/10 text-primary mb-5 flex h-12 w-12 items-center justify-center rounded-2xl", children: _jsx(Layers, { className: "h-6 w-6" }) }), _jsx("h2", { className: "text-foreground/90 text-center text-2xl font-light tracking-tight", children: "This workspace is empty" }), _jsx("p", { className: "text-muted-foreground mt-2 max-w-sm text-center text-sm leading-relaxed", children: "Add repositories or features from the canvas, or switch back to the default workspace to see everything." }), _jsxs("div", { className: "mt-6 flex items-center gap-2", children: [_jsxs(Button, { size: "sm", onClick: () => setWorkspaceNewProjectOpen(true), className: "bg-blue-500 text-white hover:bg-blue-600", children: [_jsx(FolderPlus, { className: "me-1.5 h-3.5 w-3.5" }), "New project"] }), _jsxs(Button, { variant: "outline", size: "sm", onClick: () => setManageWorkspaceOpen(true), children: [_jsx(Plus, { className: "me-1.5 h-3.5 w-3.5" }), "Manage items"] }), _jsx(Button, { variant: "ghost", size: "sm", onClick: () => setActiveWorkspace(DEFAULT_WORKSPACE_ID), children: "Switch to Default" })] })] })) : (_jsx(ControlCenterEmptyState, { onRepositorySelect: addRepoAndFocus }));
319
352
  const featureFlags = useFeatureFlags();
320
- // (+) FAB actions — only visible on control center
321
- const fabActions = useMemo(() => {
322
- const actions = [
323
- {
324
- id: 'new-feature',
325
- label: t('fab.newFeature'),
326
- icon: _jsx(Sparkles, { className: "h-4 w-4" }),
327
- onClick: () => {
328
- clickSound.play();
329
- guardedNavigate(() => router.push('/create'));
330
- },
331
- },
332
- {
333
- id: 'add-local-repo',
334
- label: t('fab.localFolder'),
335
- icon: _jsx(FolderPlus, { className: "h-4 w-4" }),
336
- onClick: handlePickFolder,
337
- },
338
- ];
339
- if (featureFlags.adoptBranch) {
340
- actions.push({
341
- id: 'adopt-branch',
342
- label: t('fab.adoptBranch'),
343
- icon: _jsx(GitBranch, { className: "h-4 w-4" }),
344
- onClick: () => {
345
- guardedNavigate(() => router.push('/adopt'));
346
- },
347
- });
348
- }
349
- if (featureFlags.githubImport) {
350
- actions.push({
351
- id: 'add-github-repo',
352
- label: t('fab.fromGithub'),
353
- icon: _jsx(Github, { className: "h-4 w-4" }),
354
- onClick: () => {
355
- window.dispatchEvent(new CustomEvent('shep:open-github-import'));
356
- },
357
- });
358
- }
359
- return actions;
360
- }, [
361
- t,
353
+ // (+) FAB actions — only visible on control center. Action list lives in
354
+ // its own hook so this component stays focused on graph state + rendering.
355
+ const fabActions = useFabActions({
356
+ router,
362
357
  clickSound,
363
358
  guardedNavigate,
364
- router,
365
359
  handlePickFolder,
366
- featureFlags.adoptBranch,
367
- featureFlags.githubImport,
368
- ]);
369
- const canvasToolbar = (_jsx(CanvasToolbar, { showArchived: showArchived, onToggleArchived: () => setShowArchived(!showArchived), onResetViewport: resetViewport }));
370
- return (_jsxs(_Fragment, { children: [_jsx(FeaturesCanvas, { nodes: showCanvas ? displayNodes : [], edges: showCanvas ? edges : [], selectedFeatureId: selectedFeatureId, selectedRepository: selectedRepository, defaultViewport: defaultViewport, onNodesChange: onNodesChange, onConnect: handleConnect, onAddFeature: handleAddFeature, onNodeClick: handleNodeClick, onPaneClick: handleClearDrawers, onMoveEnd: handleMoveEnd, toolbar: canvasToolbar, emptyState: _jsx(ControlCenterEmptyState, { onRepositorySelect: addRepoAndFocus }) }), showCanvas ? _jsx(CreateFab, { actions: fabActions }) : null] }));
360
+ onNewProject: () => setWorkspaceNewProjectOpen(true),
361
+ featureFlags,
362
+ });
363
+ const canvasToolbar = (_jsx(CanvasToolbar, { showArchived: showArchived, onToggleArchived: () => setShowArchived(!showArchived), onResetViewport: resetViewport, startSlot: _jsx(WorkspaceSelector, { workspaces: workspaces, activeWorkspace: activeWorkspace, onSelect: setActiveWorkspace, onRequestCreate: () => setCreateWorkspaceOpen(true), onRequestRename: () => setRenameWorkspaceOpen(true), onRequestDelete: (id) => {
364
+ setPendingDeleteWorkspaceId(id);
365
+ setDeleteWorkspaceOpen(true);
366
+ }, onManage: () => setManageWorkspaceOpen(true) }) }));
367
+ return (_jsxs(_Fragment, { children: [_jsx(FeaturesCanvas, { nodes: showCanvas ? displayNodes : [], edges: showCanvas ? workspaceFilteredEdges : [], selectedFeatureId: selectedFeatureId, selectedRepository: selectedRepository, defaultViewport: defaultViewport, onNodesChange: onNodesChange, onConnect: handleConnect, onAddFeature: handleAddFeature, onNodeClick: handleNodeClick, onPaneClick: handleClearDrawers, onMoveEnd: handleMoveEnd, toolbar: canvasToolbar, emptyState: emptyStateNode }), showCanvas ? _jsx(CreateFab, { actions: fabActions }) : null, _jsx(NewProjectDialog, { open: workspaceNewProjectOpen, onOpenChange: setWorkspaceNewProjectOpen, onCreated: (path) => addRepoAndFocus(path) }), _jsx(ManageWorkspaceDialog, { open: manageWorkspaceOpen, onOpenChange: setManageWorkspaceOpen, workspace: activeWorkspace, allNodes: nodes, onSave: (members) => setWorkspaceMembers(activeWorkspace.id, members) }), _jsx(WorkspaceNameDialog, { open: createWorkspaceOpen, onOpenChange: setCreateWorkspaceOpen, title: "New workspace", description: "Create a workspace to filter the canvas to a specific set of repositories and features.", confirmLabel: "Create", onConfirm: (name) => {
368
+ createWorkspace(name);
369
+ setManageWorkspaceOpen(true);
370
+ } }), _jsx(WorkspaceNameDialog, { open: renameWorkspaceOpen, onOpenChange: setRenameWorkspaceOpen, title: "Rename workspace", initialValue: activeWorkspace.name, confirmLabel: "Rename", onConfirm: (name) => renameWorkspace(activeWorkspace.id, name) }), _jsx(AlertDialog, { open: deleteWorkspaceOpen, onOpenChange: (open) => {
371
+ setDeleteWorkspaceOpen(open);
372
+ if (!open)
373
+ setPendingDeleteWorkspaceId(null);
374
+ }, children: _jsxs(AlertDialogContent, { children: [_jsxs(AlertDialogHeader, { children: [_jsx(AlertDialogTitle, { children: "Delete workspace?" }), _jsxs(AlertDialogDescription, { children: ["This will permanently remove the workspace \u201C", workspaces.find((w) => w.id === pendingDeleteWorkspaceId)?.name ??
375
+ activeWorkspace.name, "\u201D. The repositories and features themselves are not affected."] })] }), _jsxs(AlertDialogFooter, { children: [_jsx(AlertDialogCancel, { children: "Cancel" }), _jsx(AlertDialogAction, { variant: "destructive", onClick: () => {
376
+ if (pendingDeleteWorkspaceId) {
377
+ deleteWorkspace(pendingDeleteWorkspaceId);
378
+ setPendingDeleteWorkspaceId(null);
379
+ }
380
+ }, children: "Delete" })] })] }) })] }));
371
381
  }
372
382
  /** (+) FAB that tracks sidebar width via CSS var + transition.
373
383
  * When fabLayout.swapPosition is true, moves to the end side (right in LTR). */
@@ -0,0 +1,8 @@
1
+ export interface NewProjectDialogProps {
2
+ open: boolean;
3
+ onOpenChange: (open: boolean) => void;
4
+ /** Called with the absolute path of the newly-created project folder. */
5
+ onCreated: (path: string) => void;
6
+ }
7
+ export declare function NewProjectDialog({ open, onOpenChange, onCreated }: NewProjectDialogProps): import("react/jsx-runtime").JSX.Element;
8
+ //# sourceMappingURL=new-project-dialog.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"new-project-dialog.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/control-center/new-project-dialog.tsx"],"names":[],"mappings":"AAgBA,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,OAAO,CAAC;IACd,YAAY,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACtC,yEAAyE;IACzE,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CACnC;AAED,wBAAgB,gBAAgB,CAAC,EAAE,IAAI,EAAE,YAAY,EAAE,SAAS,EAAE,EAAE,qBAAqB,2CAsFxF"}
@@ -0,0 +1,43 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
+ import { useEffect, useState } from 'react';
4
+ import { Loader2 } from 'lucide-react';
5
+ import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from '../../ui/dialog.js';
6
+ import { Input } from '../../ui/input.js';
7
+ import { Button } from '../../ui/button.js';
8
+ import { createProjectFolder } from '../../../app/actions/create-project-folder.js';
9
+ export function NewProjectDialog({ open, onOpenChange, onCreated }) {
10
+ const [name, setName] = useState('');
11
+ const [busy, setBusy] = useState(false);
12
+ const [error, setError] = useState(null);
13
+ // Reset state every time the dialog opens.
14
+ useEffect(() => {
15
+ if (open) {
16
+ setName('');
17
+ setBusy(false);
18
+ setError(null);
19
+ }
20
+ }, [open]);
21
+ const handleSubmit = async (e) => {
22
+ e.preventDefault();
23
+ const trimmed = name.trim();
24
+ if (!trimmed || busy)
25
+ return;
26
+ setBusy(true);
27
+ setError(null);
28
+ const result = await createProjectFolder(trimmed);
29
+ if (!result.ok || !result.path) {
30
+ setError(result.error ?? 'Failed to create project.');
31
+ setBusy(false);
32
+ return;
33
+ }
34
+ // Hand the new path off to the empty state's existing add-repo flow.
35
+ onCreated(result.path);
36
+ onOpenChange(false);
37
+ };
38
+ return (_jsx(Dialog, { open: open, onOpenChange: onOpenChange, children: _jsx(DialogContent, { className: "max-w-sm", children: _jsxs("form", { onSubmit: handleSubmit, children: [_jsxs(DialogHeader, { children: [_jsx(DialogTitle, { children: "New project" }), _jsx(DialogDescription, { children: "Create an empty project folder inside your Shep home directory. Git will be initialised automatically when the project is added." })] }), _jsxs("div", { className: "py-4", children: [_jsx(Input, { autoFocus: true, value: name, onChange: (e) => {
39
+ setName(e.target.value);
40
+ if (error)
41
+ setError(null);
42
+ }, placeholder: "my-prototype", disabled: busy, "data-testid": "new-project-name-input" }), error ? (_jsx("p", { className: "text-destructive mt-2 text-xs", role: "alert", children: error })) : null] }), _jsxs(DialogFooter, { children: [_jsx(Button, { type: "button", variant: "ghost", onClick: () => onOpenChange(false), disabled: busy, children: "Cancel" }), _jsx(Button, { type: "submit", disabled: !name.trim() || busy, children: busy ? (_jsxs(_Fragment, { children: [_jsx(Loader2, { className: "mr-2 h-4 w-4 animate-spin" }), "Creating\u2026"] })) : ('Create project') })] })] }) }) }));
43
+ }
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Wire global window events used by the control center canvas to the
3
+ * appropriate handlers. The canvas listens for cross-component requests
4
+ * dispatched as CustomEvents:
5
+ *
6
+ * - shep:add-repository → addRepoAndFocus(path)
7
+ * - shep:feature-created → createFeatureNode(...)
8
+ * - shep:feature-delete-requested → handleDeleteFeature(...)
9
+ * - shep:feature-archive-requested → handleArchiveFeature(...)
10
+ * - shep:feature-unarchive-requested → handleUnarchiveFeature(...)
11
+ *
12
+ * Extracted from control-center-inner.tsx so the parent component stays
13
+ * focused on graph state + rendering, not event-bus plumbing.
14
+ */
15
+ import type { CanvasNodeType } from '../../features/features-canvas/index.js';
16
+ import type { FeatureNodeData } from '../../common/feature-node/index.js';
17
+ export type CreateFeatureNodeFn = (sourceNodeId: string | null, dataOverride?: Partial<FeatureNodeData>, edgeType?: string) => string;
18
+ export interface CanvasEventListenerHandlers {
19
+ addRepoAndFocus: (path: string) => void;
20
+ createFeatureNode: CreateFeatureNodeFn;
21
+ nodes: CanvasNodeType[];
22
+ handleDeleteFeature: (featureId: string, cleanup?: boolean, cascadeDelete?: boolean, closePr?: boolean) => void;
23
+ handleArchiveFeature: (featureId: string) => void;
24
+ handleUnarchiveFeature: (featureId: string) => void;
25
+ }
26
+ export declare function useCanvasEventListeners(handlers: CanvasEventListenerHandlers): void;
27
+ //# sourceMappingURL=use-canvas-event-listeners.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-canvas-event-listeners.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/control-center/use-canvas-event-listeners.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAIH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uCAAuC,CAAC;AAC5E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AAExE,MAAM,MAAM,mBAAmB,GAAG,CAChC,YAAY,EAAE,MAAM,GAAG,IAAI,EAC3B,YAAY,CAAC,EAAE,OAAO,CAAC,eAAe,CAAC,EACvC,QAAQ,CAAC,EAAE,MAAM,KACd,MAAM,CAAC;AAEZ,MAAM,WAAW,2BAA2B;IAC1C,eAAe,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,iBAAiB,EAAE,mBAAmB,CAAC;IACvC,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB,mBAAmB,EAAE,CACnB,SAAS,EAAE,MAAM,EACjB,OAAO,CAAC,EAAE,OAAO,EACjB,aAAa,CAAC,EAAE,OAAO,EACvB,OAAO,CAAC,EAAE,OAAO,KACd,IAAI,CAAC;IACV,oBAAoB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAClD,sBAAsB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;CACrD;AAED,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,2BAA2B,GAAG,IAAI,CAyGnF"}