@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
@@ -0,0 +1,84 @@
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 { useEffect } from 'react';
16
+ export function useCanvasEventListeners(handlers) {
17
+ const { addRepoAndFocus, createFeatureNode, nodes, handleDeleteFeature, handleArchiveFeature, handleUnarchiveFeature, } = handlers;
18
+ // shep:add-repository — top-bar "add folder" button
19
+ useEffect(() => {
20
+ const handler = (e) => {
21
+ const path = e.detail.path;
22
+ addRepoAndFocus(path);
23
+ };
24
+ window.addEventListener('shep:add-repository', handler);
25
+ return () => window.removeEventListener('shep:add-repository', handler);
26
+ }, [addRepoAndFocus]);
27
+ // shep:feature-created — fired by the create drawer with the real server feature ID
28
+ useEffect(() => {
29
+ const handler = (e) => {
30
+ const detail = e.detail;
31
+ // When parentId is provided, attach to the parent feature node via a
32
+ // dependency edge instead of the repo node.
33
+ if (detail.parentId) {
34
+ const parentNodeId = `feat-${detail.parentId}`;
35
+ createFeatureNode(parentNodeId, {
36
+ state: 'creating',
37
+ featureId: detail.featureId,
38
+ name: detail.name,
39
+ description: detail.description,
40
+ repositoryPath: detail.repositoryPath,
41
+ }, 'dependencyEdge');
42
+ return;
43
+ }
44
+ const repoNode = nodes.find((n) => n.type === 'repositoryNode' &&
45
+ n.data.repositoryPath === detail.repositoryPath);
46
+ createFeatureNode(repoNode?.id ?? null, {
47
+ state: 'running',
48
+ featureId: detail.featureId,
49
+ name: detail.name,
50
+ description: detail.description,
51
+ repositoryPath: detail.repositoryPath,
52
+ });
53
+ };
54
+ window.addEventListener('shep:feature-created', handler);
55
+ return () => window.removeEventListener('shep:feature-created', handler);
56
+ }, [nodes, createFeatureNode]);
57
+ // shep:feature-delete-requested — fired from the feature drawer
58
+ useEffect(() => {
59
+ const handler = (e) => {
60
+ const { featureId, cleanup, cascadeDelete, closePr } = e.detail;
61
+ handleDeleteFeature(featureId, cleanup, cascadeDelete, closePr);
62
+ };
63
+ window.addEventListener('shep:feature-delete-requested', handler);
64
+ return () => window.removeEventListener('shep:feature-delete-requested', handler);
65
+ }, [handleDeleteFeature]);
66
+ // shep:feature-archive-requested — fired from the feature drawer
67
+ useEffect(() => {
68
+ const handler = (e) => {
69
+ const { featureId } = e.detail;
70
+ handleArchiveFeature(featureId);
71
+ };
72
+ window.addEventListener('shep:feature-archive-requested', handler);
73
+ return () => window.removeEventListener('shep:feature-archive-requested', handler);
74
+ }, [handleArchiveFeature]);
75
+ // shep:feature-unarchive-requested — fired from the feature drawer
76
+ useEffect(() => {
77
+ const handler = (e) => {
78
+ const { featureId } = e.detail;
79
+ handleUnarchiveFeature(featureId);
80
+ };
81
+ window.addEventListener('shep:feature-unarchive-requested', handler);
82
+ return () => window.removeEventListener('shep:feature-unarchive-requested', handler);
83
+ }, [handleUnarchiveFeature]);
84
+ }
@@ -21,7 +21,9 @@ export interface ControlCenterState {
21
21
  handleStartFeature: (featureId: string) => void;
22
22
  handleStopFeature: (featureId: string) => void;
23
23
  handleUnarchiveFeature: (featureId: string) => void;
24
- handleDeleteRepository: (repositoryId: string) => Promise<void>;
24
+ handleDeleteRepository: (repositoryId: string, options?: {
25
+ deleteFromDisk?: boolean;
26
+ }) => Promise<void>;
25
27
  createFeatureNode: (sourceNodeId: string | null, dataOverride?: Partial<FeatureNodeData>, edgeType?: string) => string;
26
28
  /** Whether archived features are shown on the canvas. */
27
29
  showArchived: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"use-control-center-state.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/control-center/use-control-center-state.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAClE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AACxE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,qCAAqC,CAAC;AAC9E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uCAAuC,CAAC;AAC5E,OAAO,EAGL,KAAK,eAAe,EACrB,MAAM,yBAAyB,CAAC;AAkBjC,OAAO,EAAiB,KAAK,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAM7E,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB,KAAK,EAAE,IAAI,EAAE,CAAC;IACd,aAAa,EAAE,CAAC,OAAO,EAAE,UAAU,CAAC,cAAc,CAAC,EAAE,KAAK,IAAI,CAAC;IAC/D,aAAa,EAAE,CAAC,UAAU,EAAE,UAAU,KAAK,IAAI,CAAC;IAChD,mBAAmB,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK;QACrC,QAAQ,EAAE,OAAO,CAAC;QAClB,QAAQ,EAAE,MAAM,CAAC;QACjB,UAAU,EAAE,MAAM,CAAC;KACpB,CAAC;IACF,YAAY,EAAE,CAAC,SAAS,EAAE,eAAe,KAAK,IAAI,CAAC;IACnD,oBAAoB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAClD,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,kBAAkB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAChD,kBAAkB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAChD,iBAAiB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/C,sBAAsB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IACpD,sBAAsB,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAChE,iBAAiB,EAAE,CACjB,YAAY,EAAE,MAAM,GAAG,IAAI,EAC3B,YAAY,CAAC,EAAE,OAAO,CAAC,eAAe,CAAC,EACvC,QAAQ,CAAC,EAAE,MAAM,KACd,MAAM,CAAC;IACZ,yDAAyD;IACzD,YAAY,EAAE,OAAO,CAAC;IACtB,0CAA0C;IAC1C,eAAe,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACzC,wDAAwD;IACxD,wBAAwB,EAAE,CAAC,aAAa,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;IACxE,gDAAgD;IAChD,iBAAiB,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,kBAAkB,GAAG,SAAS,CAAC;IACtE,0EAA0E;IAC1E,YAAY,EAAE,CAAC,SAAS,EAAE,cAAc,KAAK,IAAI,CAAC;CACnD;AAQD,wBAAgB,qBAAqB,CACnC,YAAY,EAAE,cAAc,EAAE,EAC9B,YAAY,EAAE,IAAI,EAAE,GACnB,kBAAkB,CAilBpB"}
1
+ {"version":3,"file":"use-control-center-state.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/control-center/use-control-center-state.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAClE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AACxE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,qCAAqC,CAAC;AAC9E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uCAAuC,CAAC;AAC5E,OAAO,EAGL,KAAK,eAAe,EACrB,MAAM,yBAAyB,CAAC;AAkBjC,OAAO,EAAiB,KAAK,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAM7E,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB,KAAK,EAAE,IAAI,EAAE,CAAC;IACd,aAAa,EAAE,CAAC,OAAO,EAAE,UAAU,CAAC,cAAc,CAAC,EAAE,KAAK,IAAI,CAAC;IAC/D,aAAa,EAAE,CAAC,UAAU,EAAE,UAAU,KAAK,IAAI,CAAC;IAChD,mBAAmB,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK;QACrC,QAAQ,EAAE,OAAO,CAAC;QAClB,QAAQ,EAAE,MAAM,CAAC;QACjB,UAAU,EAAE,MAAM,CAAC;KACpB,CAAC;IACF,YAAY,EAAE,CAAC,SAAS,EAAE,eAAe,KAAK,IAAI,CAAC;IACnD,oBAAoB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAClD,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,kBAAkB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAChD,kBAAkB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAChD,iBAAiB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/C,sBAAsB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IACpD,sBAAsB,EAAE,CACtB,YAAY,EAAE,MAAM,EACpB,OAAO,CAAC,EAAE;QAAE,cAAc,CAAC,EAAE,OAAO,CAAA;KAAE,KACnC,OAAO,CAAC,IAAI,CAAC,CAAC;IACnB,iBAAiB,EAAE,CACjB,YAAY,EAAE,MAAM,GAAG,IAAI,EAC3B,YAAY,CAAC,EAAE,OAAO,CAAC,eAAe,CAAC,EACvC,QAAQ,CAAC,EAAE,MAAM,KACd,MAAM,CAAC;IACZ,yDAAyD;IACzD,YAAY,EAAE,OAAO,CAAC;IACtB,0CAA0C;IAC1C,eAAe,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACzC,wDAAwD;IACxD,wBAAwB,EAAE,CAAC,aAAa,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;IACxE,gDAAgD;IAChD,iBAAiB,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,kBAAkB,GAAG,SAAS,CAAC;IACtE,0EAA0E;IAC1E,YAAY,EAAE,CAAC,SAAS,EAAE,cAAc,KAAK,IAAI,CAAC;CACnD;AAQD,wBAAgB,qBAAqB,CACnC,YAAY,EAAE,cAAc,EAAE,EAC9B,YAAY,EAAE,IAAI,EAAE,GACnB,kBAAkB,CAmlBpB"}
@@ -388,7 +388,7 @@ export function useControlCenterState(initialNodes, initialEdges) {
388
388
  })
389
389
  .finally(() => endMutation());
390
390
  }, [router, deleteSound, updateFeature, removeFeature, beginMutation, endMutation]);
391
- const handleDeleteRepository = useCallback(async (repositoryId) => {
391
+ const handleDeleteRepository = useCallback(async (repositoryId, options) => {
392
392
  const repoNodeId = `repo-${repositoryId}`;
393
393
  // Find children of this repo via edges
394
394
  const childFeatureIds = new Set(edgesRef.current.filter((e) => e.source === repoNodeId).map((e) => e.target));
@@ -415,7 +415,9 @@ export function useControlCenterState(initialNodes, initialEdges) {
415
415
  removeFeature(childId);
416
416
  }
417
417
  try {
418
- const result = await deleteRepository(repositoryId);
418
+ const result = await deleteRepository(repositoryId, {
419
+ deleteFromDisk: options?.deleteFromDisk === true,
420
+ });
419
421
  if (!result.success) {
420
422
  toast.error(result.error ?? 'Failed to remove repository');
421
423
  rollback();
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Build the action list for the (+) FloatingActionButton on the control
3
+ * center. Extracted from control-center-inner.tsx so the parent component
4
+ * stays focused on graph state + rendering.
5
+ */
6
+ import type { useRouter } from 'next/navigation';
7
+ import type { FloatingActionButtonAction } from '../../common/floating-action-button/index.js';
8
+ import type { useFeatureFlags } from '../../../hooks/feature-flags-context.js';
9
+ interface UseFabActionsParams {
10
+ router: ReturnType<typeof useRouter>;
11
+ clickSound: {
12
+ play: () => void;
13
+ };
14
+ guardedNavigate: (fn: () => void) => void;
15
+ handlePickFolder: () => void;
16
+ onNewProject: () => void;
17
+ featureFlags: ReturnType<typeof useFeatureFlags>;
18
+ }
19
+ export declare function useFabActions({ router, clickSound, guardedNavigate, handlePickFolder, onNewProject, featureFlags, }: UseFabActionsParams): FloatingActionButtonAction[];
20
+ export {};
21
+ //# sourceMappingURL=use-fab-actions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-fab-actions.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/control-center/use-fab-actions.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAGjD,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,4CAA4C,CAAC;AAC7F,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAIrE,UAAU,mBAAmB;IAC3B,MAAM,EAAE,UAAU,CAAC,OAAO,SAAS,CAAC,CAAC;IACrC,UAAU,EAAE;QAAE,IAAI,EAAE,MAAM,IAAI,CAAA;KAAE,CAAC;IACjC,eAAe,EAAE,CAAC,EAAE,EAAE,MAAM,IAAI,KAAK,IAAI,CAAC;IAC1C,gBAAgB,EAAE,MAAM,IAAI,CAAC;IAC7B,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB,YAAY,EAAE,UAAU,CAAC,OAAO,eAAe,CAAC,CAAC;CAClD;AAED,wBAAgB,aAAa,CAAC,EAC5B,MAAM,EACN,UAAU,EACV,eAAe,EACf,gBAAgB,EAChB,YAAY,EACZ,YAAY,GACb,EAAE,mBAAmB,GAAG,0BAA0B,EAAE,CA6DpD"}
@@ -0,0 +1,70 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ /**
3
+ * Build the action list for the (+) FloatingActionButton on the control
4
+ * center. Extracted from control-center-inner.tsx so the parent component
5
+ * stays focused on graph state + rendering.
6
+ */
7
+ import { useMemo } from 'react';
8
+ import { FolderOpen, FolderPlus, GitBranch, Github, Sparkles } from 'lucide-react';
9
+ import { useTranslation } from 'react-i18next';
10
+ export function useFabActions({ router, clickSound, guardedNavigate, handlePickFolder, onNewProject, featureFlags, }) {
11
+ const { t } = useTranslation('web');
12
+ return useMemo(() => {
13
+ const actions = [
14
+ {
15
+ id: 'new-project',
16
+ label: 'New project',
17
+ icon: _jsx(FolderPlus, { className: "h-4 w-4" }),
18
+ onClick: () => {
19
+ clickSound.play();
20
+ onNewProject();
21
+ },
22
+ },
23
+ {
24
+ id: 'new-feature',
25
+ label: t('fab.newFeature'),
26
+ icon: _jsx(Sparkles, { className: "h-4 w-4" }),
27
+ onClick: () => {
28
+ clickSound.play();
29
+ guardedNavigate(() => router.push('/create'));
30
+ },
31
+ },
32
+ {
33
+ id: 'add-local-repo',
34
+ label: t('fab.localFolder'),
35
+ icon: _jsx(FolderOpen, { className: "h-4 w-4" }),
36
+ onClick: handlePickFolder,
37
+ },
38
+ ];
39
+ if (featureFlags.adoptBranch) {
40
+ actions.push({
41
+ id: 'adopt-branch',
42
+ label: t('fab.adoptBranch'),
43
+ icon: _jsx(GitBranch, { className: "h-4 w-4" }),
44
+ onClick: () => {
45
+ guardedNavigate(() => router.push('/adopt'));
46
+ },
47
+ });
48
+ }
49
+ if (featureFlags.githubImport) {
50
+ actions.push({
51
+ id: 'add-github-repo',
52
+ label: t('fab.fromGithub'),
53
+ icon: _jsx(Github, { className: "h-4 w-4" }),
54
+ onClick: () => {
55
+ window.dispatchEvent(new CustomEvent('shep:open-github-import'));
56
+ },
57
+ });
58
+ }
59
+ return actions;
60
+ }, [
61
+ t,
62
+ clickSound,
63
+ guardedNavigate,
64
+ router,
65
+ handlePickFolder,
66
+ onNewProject,
67
+ featureFlags.adoptBranch,
68
+ featureFlags.githubImport,
69
+ ]);
70
+ }
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Re-fit the React Flow viewport when the active workspace's visible node
3
+ * set changes (switching workspaces, or changing the active workspace's
4
+ * membership via the Manage dialog).
5
+ *
6
+ * Intentionally scoped:
7
+ * - Skips the first run so we don't override the persisted viewport on mount.
8
+ * - Skips the default workspace, which shows everything and owns the
9
+ * persisted viewport via useViewportPersistence.
10
+ * - Skips empty workspaces — there's nothing to fit.
11
+ * - Defers fitView to the next tick so React Flow has committed the new
12
+ * node set before measuring.
13
+ */
14
+ import type { useReactFlow } from '@xyflow/react';
15
+ import type { CanvasNodeType } from '../../features/features-canvas/index.js';
16
+ type FitViewFn = ReturnType<typeof useReactFlow>['fitView'];
17
+ interface ActiveWorkspaceLike {
18
+ id: string;
19
+ }
20
+ export declare function useWorkspaceFitView(params: {
21
+ activeWorkspace: ActiveWorkspaceLike;
22
+ isDefaultActive: boolean;
23
+ workspaceFilteredNodes: CanvasNodeType[];
24
+ fitView: FitViewFn;
25
+ }): void;
26
+ export {};
27
+ //# sourceMappingURL=use-workspace-fit-view.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-workspace-fit-view.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/control-center/use-workspace-fit-view.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAElD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uCAAuC,CAAC;AAE5E,KAAK,SAAS,GAAG,UAAU,CAAC,OAAO,YAAY,CAAC,CAAC,SAAS,CAAC,CAAC;AAE5D,UAAU,mBAAmB;IAC3B,EAAE,EAAE,MAAM,CAAC;CACZ;AAQD,wBAAgB,mBAAmB,CAAC,MAAM,EAAE;IAC1C,eAAe,EAAE,mBAAmB,CAAC;IACrC,eAAe,EAAE,OAAO,CAAC;IACzB,sBAAsB,EAAE,cAAc,EAAE,CAAC;IACzC,OAAO,EAAE,SAAS,CAAC;CACpB,GAAG,IAAI,CA2BP"}
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Re-fit the React Flow viewport when the active workspace's visible node
3
+ * set changes (switching workspaces, or changing the active workspace's
4
+ * membership via the Manage dialog).
5
+ *
6
+ * Intentionally scoped:
7
+ * - Skips the first run so we don't override the persisted viewport on mount.
8
+ * - Skips the default workspace, which shows everything and owns the
9
+ * persisted viewport via useViewportPersistence.
10
+ * - Skips empty workspaces — there's nothing to fit.
11
+ * - Defers fitView to the next tick so React Flow has committed the new
12
+ * node set before measuring.
13
+ */
14
+ import { useEffect, useMemo, useRef } from 'react';
15
+ const AUTO_FOCUS_OPTIONS = {
16
+ maxZoom: 1.0,
17
+ padding: 0.5,
18
+ duration: 500,
19
+ };
20
+ export function useWorkspaceFitView(params) {
21
+ const { activeWorkspace, isDefaultActive, workspaceFilteredNodes, fitView } = params;
22
+ const fingerprint = useMemo(() => {
23
+ if (isDefaultActive)
24
+ return 'default';
25
+ const ids = workspaceFilteredNodes
26
+ .map((n) => n.id)
27
+ .sort()
28
+ .join(',');
29
+ return `${activeWorkspace.id}:${ids}`;
30
+ }, [isDefaultActive, activeWorkspace.id, workspaceFilteredNodes]);
31
+ const prevFingerprintRef = useRef(null);
32
+ useEffect(() => {
33
+ const prev = prevFingerprintRef.current;
34
+ prevFingerprintRef.current = fingerprint;
35
+ if (prev === null)
36
+ return;
37
+ if (prev === fingerprint)
38
+ return;
39
+ if (isDefaultActive)
40
+ return;
41
+ if (workspaceFilteredNodes.length === 0)
42
+ return;
43
+ const t = setTimeout(() => {
44
+ fitView(AUTO_FOCUS_OPTIONS);
45
+ }, 0);
46
+ return () => clearTimeout(t);
47
+ }, [fingerprint, isDefaultActive, workspaceFilteredNodes.length, fitView]);
48
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"welcome-agent-setup.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/control-center/welcome-agent-setup.tsx"],"names":[],"mappings":"AAYA,MAAM,WAAW,sBAAsB;IACrC,UAAU,EAAE,MAAM,IAAI,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAMD,wBAAgB,iBAAiB,CAAC,EAAE,UAAU,EAAE,SAAS,EAAE,EAAE,sBAAsB,2CAkPlF"}
1
+ {"version":3,"file":"welcome-agent-setup.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/control-center/welcome-agent-setup.tsx"],"names":[],"mappings":"AAaA,MAAM,WAAW,sBAAsB;IACrC,UAAU,EAAE,MAAM,IAAI,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAMD,wBAAgB,iBAAiB,CAAC,EAAE,UAAU,EAAE,SAAS,EAAE,EAAE,sBAAsB,2CAyPlF"}
@@ -5,6 +5,7 @@ import { ChevronLeft, Loader2, AlertTriangle } from 'lucide-react';
5
5
  import { useTranslation } from 'react-i18next';
6
6
  import { getAllAgentModels } from '../../../app/actions/get-all-agent-models.js';
7
7
  import { updateAgentAndModel } from '../../../app/actions/update-agent-and-model.js';
8
+ import { checkToolStatus } from '../../../app/actions/check-tool-status.js';
8
9
  import { getAgentTypeIcon } from '../../common/feature-node/agent-type-icons.js';
9
10
  import { getModelMeta } from '../../../lib/model-metadata.js';
10
11
  import { cn } from '../../../lib/utils.js';
@@ -13,6 +14,7 @@ export function WelcomeAgentSetup({ onComplete, className }) {
13
14
  const { t } = useTranslation('web');
14
15
  const [groups, setGroups] = useState([]);
15
16
  const [loading, setLoading] = useState(true);
17
+ const [ghInstalled, setGhInstalled] = useState(null);
16
18
  const [step, setStep] = useState('select-agent');
17
19
  const [selectedAgent, setSelectedAgent] = useState(null);
18
20
  const [saving, setSaving] = useState(false);
@@ -24,6 +26,11 @@ export function WelcomeAgentSetup({ onComplete, className }) {
24
26
  .then(setGroups)
25
27
  .finally(() => setLoading(false));
26
28
  }, []);
29
+ useEffect(() => {
30
+ checkToolStatus()
31
+ .then((status) => setGhInstalled(status.gh.installed))
32
+ .catch(() => setGhInstalled(null));
33
+ }, []);
27
34
  const activeGroup = selectedAgent ? groups.find((g) => g.agentType === selectedAgent) : null;
28
35
  const transitionTo = useCallback((nextStep, setup) => {
29
36
  setTransitioning(true);
@@ -95,7 +102,7 @@ export function WelcomeAgentSetup({ onComplete, className }) {
95
102
  : activeGroup
96
103
  ? t('welcome.chooseModelSubtitle', { label: activeGroup.label })
97
104
  : '';
98
- return (_jsxs("div", { "data-testid": "welcome-agent-setup", className: cn('flex w-full flex-col items-center', className), children: [_jsx("div", { className: "mb-8 flex w-full max-w-xs items-center gap-1.5", children: STEPS.map((s, i) => (_jsx("div", { className: cn('h-[3px] flex-1 rounded-full transition-colors duration-300', i <= stepIndex ? 'bg-foreground/60' : 'bg-muted') }, s))) }), _jsxs("div", { className: cn('flex w-full flex-col items-center transition-opacity duration-200', visible && !transitioning ? 'opacity-100' : 'opacity-0'), children: [_jsx("h1", { className: "text-foreground/90 text-center text-5xl font-extralight tracking-tight", children: heroTitle }), _jsx("p", { className: "text-muted-foreground mt-3 text-center text-lg leading-relaxed font-light", children: heroSubtitle }), step === 'select-agent' && (_jsxs("div", { "data-testid": "gh-cli-notice", className: "mt-5 flex items-start gap-2 rounded-lg border border-amber-200 bg-amber-50 px-4 py-3 dark:border-amber-900 dark:bg-amber-950/40", children: [_jsx(AlertTriangle, { className: "mt-0.5 h-4 w-4 shrink-0 text-amber-500" }), _jsxs("p", { className: "text-sm leading-relaxed text-amber-800 dark:text-amber-300", children: [_jsx("span", { className: "font-medium", children: t('welcome.ghCliRequired') }), ' ', t('welcome.ghCliRequiredText'), ' ', _jsx("a", { href: "https://cli.github.com/", target: "_blank", rel: "noopener noreferrer", className: "underline underline-offset-2 hover:text-amber-900 dark:hover:text-amber-200", children: t('welcome.installHere') }), "."] })] })), _jsxs("div", { className: "mt-8 flex w-full flex-col items-center", children: [step === 'select-agent' && (_jsx("div", { "data-testid": "agent-list", className: "grid w-full max-w-lg gap-3", style: {
105
+ return (_jsxs("div", { "data-testid": "welcome-agent-setup", className: cn('flex w-full flex-col items-center', className), children: [_jsx("div", { className: "mb-8 flex w-full max-w-xs items-center gap-1.5", children: STEPS.map((s, i) => (_jsx("div", { className: cn('h-[3px] flex-1 rounded-full transition-colors duration-300', i <= stepIndex ? 'bg-foreground/60' : 'bg-muted') }, s))) }), _jsxs("div", { className: cn('flex w-full flex-col items-center transition-opacity duration-200', visible && !transitioning ? 'opacity-100' : 'opacity-0'), children: [_jsx("h1", { className: "text-foreground/90 text-center text-5xl font-extralight tracking-tight", children: heroTitle }), _jsx("p", { className: "text-muted-foreground mt-3 text-center text-lg leading-relaxed font-light", children: heroSubtitle }), step === 'select-agent' && ghInstalled === false && (_jsxs("div", { "data-testid": "gh-cli-notice", className: "mt-5 flex items-start gap-2 rounded-lg border border-amber-200 bg-amber-50 px-4 py-3 dark:border-amber-900 dark:bg-amber-950/40", children: [_jsx(AlertTriangle, { className: "mt-0.5 h-4 w-4 shrink-0 text-amber-500" }), _jsxs("p", { className: "text-sm leading-relaxed text-amber-800 dark:text-amber-300", children: [_jsx("span", { className: "font-medium", children: t('welcome.ghCliRequired') }), ' ', t('welcome.ghCliRequiredText'), ' ', _jsx("a", { href: "https://cli.github.com/", target: "_blank", rel: "noopener noreferrer", className: "underline underline-offset-2 hover:text-amber-900 dark:hover:text-amber-200", children: t('welcome.installHere') }), "."] })] })), _jsxs("div", { className: "mt-8 flex w-full flex-col items-center", children: [step === 'select-agent' && (_jsx("div", { "data-testid": "agent-list", className: "grid w-full max-w-lg gap-3", style: {
99
106
  gridTemplateColumns: `repeat(${Math.min(groups.length, 4)}, minmax(0, 1fr))`,
100
107
  }, children: groups.map((group) => {
101
108
  const GroupIcon = getAgentTypeIcon(group.agentType);
@@ -3,6 +3,8 @@ export interface CanvasToolbarProps {
3
3
  showArchived: boolean;
4
4
  onToggleArchived: () => void;
5
5
  onResetViewport?: () => Viewport;
6
+ /** Optional slot rendered at the start of the toolbar (e.g. workspace selector). */
7
+ startSlot?: React.ReactNode;
6
8
  }
7
- export declare function CanvasToolbar({ showArchived, onToggleArchived, onResetViewport, }: CanvasToolbarProps): import("react/jsx-runtime").JSX.Element;
9
+ export declare function CanvasToolbar({ showArchived, onToggleArchived, onResetViewport, startSlot, }: CanvasToolbarProps): import("react/jsx-runtime").JSX.Element;
8
10
  //# sourceMappingURL=canvas-toolbar.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"canvas-toolbar.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/features-canvas/canvas-toolbar.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAK9C,MAAM,WAAW,kBAAkB;IACjC,YAAY,EAAE,OAAO,CAAC;IACtB,gBAAgB,EAAE,MAAM,IAAI,CAAC;IAC7B,eAAe,CAAC,EAAE,MAAM,QAAQ,CAAC;CAClC;AAED,wBAAgB,aAAa,CAAC,EAC5B,YAAY,EACZ,gBAAgB,EAChB,eAAe,GAChB,EAAE,kBAAkB,2CAsDpB"}
1
+ {"version":3,"file":"canvas-toolbar.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/features-canvas/canvas-toolbar.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAK9C,MAAM,WAAW,kBAAkB;IACjC,YAAY,EAAE,OAAO,CAAC;IACtB,gBAAgB,EAAE,MAAM,IAAI,CAAC;IAC7B,eAAe,CAAC,EAAE,MAAM,QAAQ,CAAC;IACjC,oFAAoF;IACpF,SAAS,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC7B;AAED,wBAAgB,aAAa,CAAC,EAC5B,YAAY,EACZ,gBAAgB,EAChB,eAAe,EACf,SAAS,GACV,EAAE,kBAAkB,2CA4DpB"}
@@ -1,11 +1,11 @@
1
1
  'use client';
2
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { useCallback } from 'react';
4
4
  import { useReactFlow } from '@xyflow/react';
5
5
  import { Eye, EyeOff, ZoomIn, ZoomOut, Maximize, RotateCcw } from 'lucide-react';
6
6
  import { useTranslation } from 'react-i18next';
7
7
  import { cn } from '../../../lib/utils.js';
8
- export function CanvasToolbar({ showArchived, onToggleArchived, onResetViewport, }) {
8
+ export function CanvasToolbar({ showArchived, onToggleArchived, onResetViewport, startSlot, }) {
9
9
  const { t } = useTranslation('web');
10
10
  const { zoomIn, zoomOut, fitView, setViewport } = useReactFlow();
11
11
  const handleZoomIn = useCallback(() => {
@@ -23,7 +23,7 @@ export function CanvasToolbar({ showArchived, onToggleArchived, onResetViewport,
23
23
  setViewport(viewport, { duration: 400 });
24
24
  }
25
25
  }, [onResetViewport, setViewport]);
26
- return (_jsxs("div", { className: "bg-background flex items-center gap-1 rounded-xl border px-2 py-1.5 shadow-md dark:bg-neutral-900", children: [_jsx(ToolbarButton, { onClick: onToggleArchived, title: showArchived ? t('canvas.hideArchived') : t('canvas.showArchived'), active: showArchived, label: showArchived ? t('canvas.hideArchivedLabel') : t('canvas.showArchivedLabel'), children: showArchived ? _jsx(Eye, { className: "h-4 w-4" }) : _jsx(EyeOff, { className: "h-4 w-4" }) }), _jsx("div", { className: "bg-border mx-1 h-5 w-px" }), _jsx(ToolbarButton, { onClick: handleZoomOut, title: t('canvas.zoomOut'), children: _jsx(ZoomOut, { className: "h-4 w-4" }) }), _jsx(ToolbarButton, { onClick: handleZoomIn, title: t('canvas.zoomIn'), children: _jsx(ZoomIn, { className: "h-4 w-4" }) }), _jsx(ToolbarButton, { onClick: handleFitView, title: t('canvas.fitView'), children: _jsx(Maximize, { className: "h-4 w-4" }) }), onResetViewport ? (_jsx(ToolbarButton, { onClick: handleReset, title: t('canvas.resetView'), children: _jsx(RotateCcw, { className: "h-4 w-4" }) })) : null] }));
26
+ return (_jsxs("div", { className: "bg-background flex items-center gap-1 rounded-xl border px-2 py-1.5 shadow-md dark:bg-neutral-900", children: [startSlot ? (_jsxs(_Fragment, { children: [startSlot, _jsx("div", { className: "bg-border mx-1 h-5 w-px" })] })) : null, _jsx(ToolbarButton, { onClick: onToggleArchived, title: showArchived ? t('canvas.hideArchived') : t('canvas.showArchived'), active: showArchived, label: showArchived ? t('canvas.hideArchivedLabel') : t('canvas.showArchivedLabel'), children: showArchived ? _jsx(Eye, { className: "h-4 w-4" }) : _jsx(EyeOff, { className: "h-4 w-4" }) }), _jsx("div", { className: "bg-border mx-1 h-5 w-px" }), _jsx(ToolbarButton, { onClick: handleZoomOut, title: t('canvas.zoomOut'), children: _jsx(ZoomOut, { className: "h-4 w-4" }) }), _jsx(ToolbarButton, { onClick: handleZoomIn, title: t('canvas.zoomIn'), children: _jsx(ZoomIn, { className: "h-4 w-4" }) }), _jsx(ToolbarButton, { onClick: handleFitView, title: t('canvas.fitView'), children: _jsx(Maximize, { className: "h-4 w-4" }) }), onResetViewport ? (_jsx(ToolbarButton, { onClick: handleReset, title: t('canvas.resetView'), children: _jsx(RotateCcw, { className: "h-4 w-4" }) })) : null] }));
27
27
  }
28
28
  // ── Internal button ──────────────────────────────────────────────────────
29
29
  function ToolbarButton({ children, onClick, title, label, active, }) {
@@ -1 +1 @@
1
- {"version":3,"file":"features-canvas.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/features-canvas/features-canvas.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,UAAU,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAOvF,OAAO,KAAK,EAAE,eAAe,EAAmB,MAAM,kCAAkC,CAAC;AAEzF,OAAO,KAAK,EAAE,kBAAkB,EAAsB,MAAM,qCAAqC,CAAC;AAGlG,MAAM,MAAM,cAAc,GAAG,eAAe,GAAG,kBAAkB,CAAC;AAElE,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB,KAAK,EAAE,IAAI,EAAE,CAAC;IACd,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,kBAAkB,CAAC,EAAE;QAAE,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC;IAChE,eAAe,CAAC,EAAE,QAAQ,CAAC;IAC3B,aAAa,CAAC,EAAE,CAAC,OAAO,EAAE,UAAU,CAAC,cAAc,CAAC,EAAE,KAAK,IAAI,CAAC;IAChE,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;IAC1B,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,UAAU,EAAE,IAAI,EAAE,cAAc,KAAK,IAAI,CAAC;IACtE,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,UAAU,KAAK,IAAI,CAAC;IAChD,SAAS,CAAC,EAAE,CAAC,UAAU,EAAE,UAAU,KAAK,IAAI,CAAC;IAC7C,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;IAC1B,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,OAAO,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,UAAU,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC9B;AAID,wBAAgB,cAAc,CAAC,EAC7B,KAAK,EACL,KAAK,EACL,iBAAiB,EACjB,kBAAkB,EAClB,eAAe,EACf,aAAa,EACb,YAAY,EACZ,SAAS,EACT,WAAW,EACX,WAAW,EACX,YAAY,EACZ,SAAS,EACT,OAAO,EACP,UAAU,GACX,EAAE,mBAAmB,2CA0IrB"}
1
+ {"version":3,"file":"features-canvas.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/features-canvas/features-canvas.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,UAAU,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAOvF,OAAO,KAAK,EAAE,eAAe,EAAmB,MAAM,kCAAkC,CAAC;AAEzF,OAAO,KAAK,EAAE,kBAAkB,EAAsB,MAAM,qCAAqC,CAAC;AAGlG,MAAM,MAAM,cAAc,GAAG,eAAe,GAAG,kBAAkB,CAAC;AAElE,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB,KAAK,EAAE,IAAI,EAAE,CAAC;IACd,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,kBAAkB,CAAC,EAAE;QAAE,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC;IAChE,eAAe,CAAC,EAAE,QAAQ,CAAC;IAC3B,aAAa,CAAC,EAAE,CAAC,OAAO,EAAE,UAAU,CAAC,cAAc,CAAC,EAAE,KAAK,IAAI,CAAC;IAChE,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;IAC1B,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,UAAU,EAAE,IAAI,EAAE,cAAc,KAAK,IAAI,CAAC;IACtE,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,UAAU,KAAK,IAAI,CAAC;IAChD,SAAS,CAAC,EAAE,CAAC,UAAU,EAAE,UAAU,KAAK,IAAI,CAAC;IAC7C,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;IAC1B,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,OAAO,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,UAAU,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC9B;AAID,wBAAgB,cAAc,CAAC,EAC7B,KAAK,EACL,KAAK,EACL,iBAAiB,EACjB,kBAAkB,EAClB,eAAe,EACf,aAAa,EACb,YAAY,EACZ,SAAS,EACT,WAAW,EACX,WAAW,EACX,YAAY,EACZ,SAAS,EACT,OAAO,EACP,UAAU,GACX,EAAE,mBAAmB,2CA+IrB"}
@@ -71,5 +71,5 @@ export function FeaturesCanvas({ nodes, edges, selectedFeatureId, selectedReposi
71
71
  }, [isEmpty]);
72
72
  const fallbackEmptyState = isEmpty && !emptyState ? (_jsx(EmptyState, { title: t('canvas.noFeatures'), description: t('canvas.noFeaturesDescription'), action: _jsxs(Button, { onClick: onAddFeature, children: [_jsx(Plus, { className: "me-2 h-4 w-4" }), t('canvas.newFeature')] }) })) : null;
73
73
  const overlayContent = emptyState ?? fallbackEmptyState;
74
- return (_jsxs("div", { "data-testid": isEmpty ? 'features-canvas-empty' : 'features-canvas', "data-no-drawer-close": true, className: "dark:bg-background pointer-events-auto relative h-full w-full bg-[#f6f7f8]", children: [_jsxs(ReactFlow, { nodes: enrichedNodes, edges: edges, nodeTypes: nodeTypes, edgeTypes: edgeTypes, onConnect: onConnect, onNodesChange: onNodesChange, onNodeClick: onNodeClick, onPaneClick: onPaneClick, onMoveStart: onCanvasDrag, onMoveEnd: onMoveEnd, defaultViewport: defaultViewport ?? FALLBACK_VIEWPORT, nodesDraggable: false, nodesConnectable: false, elementsSelectable: false, proOptions: { hideAttribution: true }, className: "[&_.react-flow__pane]:!cursor-default", children: [_jsx(Background, { variant: BackgroundVariant.Dots, gap: 24, size: 1, color: "#b8bcc4", className: "dark:[&_circle]:!fill-white/[0.1]" }), !isEmpty && toolbar ? (_jsx(Panel, { position: "top-right", className: "!me-3 !mt-3", children: toolbar })) : null] }), showOverlay && overlayContent ? (_jsx("div", { className: cn('pointer-events-none absolute inset-0 z-10 flex items-center justify-center transition-opacity duration-300', overlayExiting ? 'opacity-0' : 'animate-in fade-in opacity-100 duration-200'), children: _jsx("div", { className: "pointer-events-auto h-full w-full", children: overlayContent }) })) : null] }));
74
+ return (_jsxs("div", { "data-testid": isEmpty ? 'features-canvas-empty' : 'features-canvas', "data-no-drawer-close": true, className: "dark:bg-background pointer-events-auto relative h-full w-full bg-[#f6f7f8]", children: [_jsxs(ReactFlow, { nodes: enrichedNodes, edges: edges, nodeTypes: nodeTypes, edgeTypes: edgeTypes, onConnect: onConnect, onNodesChange: onNodesChange, onNodeClick: onNodeClick, onPaneClick: onPaneClick, onMoveStart: onCanvasDrag, onMoveEnd: onMoveEnd, defaultViewport: defaultViewport ?? FALLBACK_VIEWPORT, nodesDraggable: false, nodesConnectable: false, elementsSelectable: false, proOptions: { hideAttribution: true }, className: "[&_.react-flow__pane]:!cursor-default", children: [_jsx(Background, { variant: BackgroundVariant.Dots, gap: 24, size: 1, color: "#b8bcc4", className: "dark:[&_circle]:!fill-white/[0.1]" }), toolbar && !isEmpty ? (_jsx(Panel, { position: "top-right", className: "!me-3 !mt-3", children: toolbar })) : null] }), showOverlay && overlayContent ? (_jsx("div", { className: cn('pointer-events-none absolute inset-0 z-10 flex items-center justify-center transition-opacity duration-300', overlayExiting ? 'opacity-0' : 'animate-in fade-in opacity-100 duration-200'), children: _jsx("div", { className: "pointer-events-auto h-full w-full", children: overlayContent }) })) : null, toolbar && isEmpty ? (_jsx("div", { className: "pointer-events-auto absolute end-3 top-3 z-20", children: toolbar })) : null] }));
75
75
  }
@@ -0,0 +1,15 @@
1
+ import type { CanvasNodeType } from '../../features/features-canvas/index.js';
2
+ import type { Workspace } from '../../../hooks/use-workspaces.js';
3
+ export interface ManageWorkspaceDialogProps {
4
+ open: boolean;
5
+ onOpenChange: (open: boolean) => void;
6
+ workspace: Workspace;
7
+ /** All nodes currently on the canvas (unfiltered). */
8
+ allNodes: CanvasNodeType[];
9
+ onSave: (members: {
10
+ repoIds: string[];
11
+ featureIds: string[];
12
+ }) => void;
13
+ }
14
+ export declare function ManageWorkspaceDialog({ open, onOpenChange, workspace, allNodes, onSave, }: ManageWorkspaceDialogProps): import("react/jsx-runtime").JSX.Element;
15
+ //# sourceMappingURL=manage-workspace-dialog.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manage-workspace-dialog.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/features-canvas/manage-workspace-dialog.tsx"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uCAAuC,CAAC;AAG5E,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAExD,MAAM,WAAW,0BAA0B;IACzC,IAAI,EAAE,OAAO,CAAC;IACd,YAAY,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACtC,SAAS,EAAE,SAAS,CAAC;IACrB,sDAAsD;IACtD,QAAQ,EAAE,cAAc,EAAE,CAAC;IAC3B,MAAM,EAAE,CAAC,OAAO,EAAE;QAAE,OAAO,EAAE,MAAM,EAAE,CAAC;QAAC,UAAU,EAAE,MAAM,EAAE,CAAA;KAAE,KAAK,IAAI,CAAC;CACxE;AAQD,wBAAgB,qBAAqB,CAAC,EACpC,IAAI,EACJ,YAAY,EACZ,SAAS,EACT,QAAQ,EACR,MAAM,GACP,EAAE,0BAA0B,2CA8H5B"}
@@ -0,0 +1,74 @@
1
+ 'use client';
2
+ import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
3
+ import { useEffect, useMemo, useState } from 'react';
4
+ import { GitBranch, Sparkles } from 'lucide-react';
5
+ import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from '../../ui/dialog.js';
6
+ import { Checkbox } from '../../ui/checkbox.js';
7
+ import { Button } from '../../ui/button.js';
8
+ export function ManageWorkspaceDialog({ open, onOpenChange, workspace, allNodes, onSave, }) {
9
+ const [selectedRepoIds, setSelectedRepoIds] = useState(new Set());
10
+ const [selectedFeatureIds, setSelectedFeatureIds] = useState(new Set());
11
+ // Reset selection state whenever the dialog opens for a (possibly different) workspace.
12
+ useEffect(() => {
13
+ if (open) {
14
+ setSelectedRepoIds(new Set(workspace.repoIds));
15
+ setSelectedFeatureIds(new Set(workspace.featureIds));
16
+ }
17
+ }, [open, workspace]);
18
+ // Group features under their parent repo by repositoryPath.
19
+ const repoEntries = useMemo(() => {
20
+ const repos = [];
21
+ const byPath = new Map();
22
+ for (const node of allNodes) {
23
+ if (node.type !== 'repositoryNode')
24
+ continue;
25
+ const data = node.data;
26
+ const path = data.repositoryPath ?? '';
27
+ const entry = {
28
+ nodeId: node.id,
29
+ name: data.name ?? path.split('/').filter(Boolean).pop() ?? path,
30
+ features: [],
31
+ };
32
+ repos.push(entry);
33
+ byPath.set(path, entry);
34
+ }
35
+ for (const node of allNodes) {
36
+ if (node.type !== 'featureNode')
37
+ continue;
38
+ const data = node.data;
39
+ const repo = byPath.get(data.repositoryPath ?? '');
40
+ if (repo) {
41
+ repo.features.push({ nodeId: node.id, name: data.name });
42
+ }
43
+ }
44
+ return repos;
45
+ }, [allNodes]);
46
+ const toggleRepo = (id) => {
47
+ setSelectedRepoIds((prev) => {
48
+ const next = new Set(prev);
49
+ if (next.has(id))
50
+ next.delete(id);
51
+ else
52
+ next.add(id);
53
+ return next;
54
+ });
55
+ };
56
+ const toggleFeature = (id) => {
57
+ setSelectedFeatureIds((prev) => {
58
+ const next = new Set(prev);
59
+ if (next.has(id))
60
+ next.delete(id);
61
+ else
62
+ next.add(id);
63
+ return next;
64
+ });
65
+ };
66
+ const handleSave = () => {
67
+ onSave({
68
+ repoIds: Array.from(selectedRepoIds),
69
+ featureIds: Array.from(selectedFeatureIds),
70
+ });
71
+ onOpenChange(false);
72
+ };
73
+ return (_jsx(Dialog, { open: open, onOpenChange: onOpenChange, children: _jsxs(DialogContent, { className: "max-h-[80vh] max-w-lg overflow-hidden", children: [_jsxs(DialogHeader, { children: [_jsxs(DialogTitle, { children: ["Manage workspace: ", workspace.name] }), _jsx(DialogDescription, { children: "Select the repositories and features that should appear on this workspace's canvas." })] }), _jsx("div", { className: "-mx-6 max-h-[50vh] overflow-y-auto px-6", children: repoEntries.length === 0 ? (_jsx("p", { className: "text-muted-foreground py-8 text-center text-sm", children: "No repositories on the canvas yet." })) : (_jsx("ul", { className: "space-y-3 py-2", children: repoEntries.map((repo) => (_jsxs("li", { children: [_jsxs("label", { className: "hover:bg-accent/30 flex cursor-pointer items-center gap-2 rounded-md px-2 py-1.5", children: [_jsx(Checkbox, { checked: selectedRepoIds.has(repo.nodeId), onCheckedChange: () => toggleRepo(repo.nodeId) }), _jsx(GitBranch, { className: "text-muted-foreground h-4 w-4" }), _jsx("span", { className: "text-sm font-medium", children: repo.name })] }), repo.features.length > 0 ? (_jsx("ul", { className: "mt-1 ml-7 space-y-0.5", children: repo.features.map((feat) => (_jsx("li", { children: _jsxs("label", { className: "hover:bg-accent/30 flex cursor-pointer items-center gap-2 rounded-md px-2 py-1", children: [_jsx(Checkbox, { checked: selectedFeatureIds.has(feat.nodeId), onCheckedChange: () => toggleFeature(feat.nodeId) }), _jsx(Sparkles, { className: "text-muted-foreground h-3.5 w-3.5" }), _jsx("span", { className: "text-muted-foreground text-xs", children: feat.name })] }) }, feat.nodeId))) })) : null] }, repo.nodeId))) })) }), _jsxs(DialogFooter, { children: [_jsx(Button, { variant: "ghost", onClick: () => onOpenChange(false), children: "Cancel" }), _jsx(Button, { onClick: handleSave, children: "Save" })] })] }) }));
74
+ }
@@ -0,0 +1,11 @@
1
+ export interface WorkspaceNameDialogProps {
2
+ open: boolean;
3
+ onOpenChange: (open: boolean) => void;
4
+ title: string;
5
+ description?: string;
6
+ initialValue?: string;
7
+ confirmLabel: string;
8
+ onConfirm: (name: string) => void;
9
+ }
10
+ export declare function WorkspaceNameDialog({ open, onOpenChange, title, description, initialValue, confirmLabel, onConfirm, }: WorkspaceNameDialogProps): import("react/jsx-runtime").JSX.Element;
11
+ //# sourceMappingURL=workspace-name-dialog.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workspace-name-dialog.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/features-canvas/workspace-name-dialog.tsx"],"names":[],"mappings":"AAcA,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,OAAO,CAAC;IACd,YAAY,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACtC,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CACnC;AAED,wBAAgB,mBAAmB,CAAC,EAClC,IAAI,EACJ,YAAY,EACZ,KAAK,EACL,WAAW,EACX,YAAiB,EACjB,YAAY,EACZ,SAAS,GACV,EAAE,wBAAwB,2CA4C1B"}
@@ -0,0 +1,22 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { useEffect, useState } from 'react';
4
+ import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from '../../ui/dialog.js';
5
+ import { Input } from '../../ui/input.js';
6
+ import { Button } from '../../ui/button.js';
7
+ export function WorkspaceNameDialog({ open, onOpenChange, title, description, initialValue = '', confirmLabel, onConfirm, }) {
8
+ const [value, setValue] = useState(initialValue);
9
+ useEffect(() => {
10
+ if (open)
11
+ setValue(initialValue);
12
+ }, [open, initialValue]);
13
+ const handleSubmit = (e) => {
14
+ e.preventDefault();
15
+ const trimmed = value.trim();
16
+ if (!trimmed)
17
+ return;
18
+ onConfirm(trimmed);
19
+ onOpenChange(false);
20
+ };
21
+ 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: title }), description ? _jsx(DialogDescription, { children: description }) : null] }), _jsx("div", { className: "py-4", children: _jsx(Input, { autoFocus: true, value: value, onChange: (e) => setValue(e.target.value), placeholder: "Workspace name", "data-testid": "workspace-name-input" }) }), _jsxs(DialogFooter, { children: [_jsx(Button, { type: "button", variant: "ghost", onClick: () => onOpenChange(false), children: "Cancel" }), _jsx(Button, { type: "submit", disabled: !value.trim(), children: confirmLabel })] })] }) }) }));
22
+ }
@@ -0,0 +1,13 @@
1
+ import { type UseWorkspacesResult, type Workspace } from '../../../hooks/use-workspaces.js';
2
+ export interface WorkspaceSelectorProps {
3
+ workspaces: UseWorkspacesResult['workspaces'];
4
+ activeWorkspace: Workspace;
5
+ onSelect: (id: string) => void;
6
+ onRequestCreate: () => void;
7
+ onRequestRename: () => void;
8
+ /** Request deletion of a specific workspace by id. */
9
+ onRequestDelete: (id: string) => void;
10
+ onManage: () => void;
11
+ }
12
+ export declare function WorkspaceSelector({ workspaces, activeWorkspace, onSelect, onRequestCreate, onRequestRename, onRequestDelete, onManage, }: WorkspaceSelectorProps): import("react/jsx-runtime").JSX.Element;
13
+ //# sourceMappingURL=workspace-selector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workspace-selector.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/features-canvas/workspace-selector.tsx"],"names":[],"mappings":"AAaA,OAAO,EAEL,KAAK,mBAAmB,EACxB,KAAK,SAAS,EACf,MAAM,wBAAwB,CAAC;AAEhC,MAAM,WAAW,sBAAsB;IACrC,UAAU,EAAE,mBAAmB,CAAC,YAAY,CAAC,CAAC;IAC9C,eAAe,EAAE,SAAS,CAAC;IAC3B,QAAQ,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/B,eAAe,EAAE,MAAM,IAAI,CAAC;IAC5B,eAAe,EAAE,MAAM,IAAI,CAAC;IAC5B,sDAAsD;IACtD,eAAe,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IACtC,QAAQ,EAAE,MAAM,IAAI,CAAC;CACtB;AAED,wBAAgB,iBAAiB,CAAC,EAChC,UAAU,EACV,eAAe,EACf,QAAQ,EACR,eAAe,EACf,eAAe,EACf,eAAe,EACf,QAAQ,GACT,EAAE,sBAAsB,2CAwExB"}
@@ -0,0 +1,21 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { useState } from 'react';
4
+ import { Layers, Check, Plus, Pencil, Trash2, SlidersHorizontal } from 'lucide-react';
5
+ import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuTrigger, } from '../../ui/dropdown-menu.js';
6
+ import { cn } from '../../../lib/utils.js';
7
+ import { DEFAULT_WORKSPACE_ID, } from '../../../hooks/use-workspaces.js';
8
+ export function WorkspaceSelector({ workspaces, activeWorkspace, onSelect, onRequestCreate, onRequestRename, onRequestDelete, onManage, }) {
9
+ const [open, setOpen] = useState(false);
10
+ const isDefault = activeWorkspace.id === DEFAULT_WORKSPACE_ID;
11
+ return (_jsxs(DropdownMenu, { open: open, onOpenChange: setOpen, children: [_jsx(DropdownMenuTrigger, { asChild: true, children: _jsxs("button", { type: "button", "data-testid": "workspace-selector-trigger", className: cn('inline-flex items-center gap-1.5 rounded-lg px-2 py-1.5 text-xs font-medium transition-colors', 'hover:bg-accent hover:text-accent-foreground', isDefault ? 'text-muted-foreground' : 'text-primary bg-primary/10'), title: "Workspace", children: [_jsx(Layers, { className: "h-4 w-4" }), _jsx("span", { className: "max-w-[120px] truncate", children: activeWorkspace.name })] }) }), _jsxs(DropdownMenuContent, { align: "start", className: "min-w-[220px]", children: [_jsx(DropdownMenuLabel, { children: "Workspaces" }), _jsx(DropdownMenuSeparator, {}), workspaces.map((w) => {
12
+ const active = w.id === activeWorkspace.id;
13
+ const canDelete = w.id !== DEFAULT_WORKSPACE_ID;
14
+ return (_jsxs(DropdownMenuItem, { onSelect: () => onSelect(w.id), className: "group/ws-row flex items-center justify-between gap-2", children: [_jsx("span", { className: "truncate", children: w.name }), _jsxs("span", { className: "flex shrink-0 items-center gap-1", children: [active ? _jsx(Check, { className: "h-3.5 w-3.5" }) : null, canDelete ? (_jsx("button", { type: "button", "aria-label": `Delete workspace ${w.name}`, title: `Delete workspace ${w.name}`, onClick: (event) => {
15
+ event.preventDefault();
16
+ event.stopPropagation();
17
+ setOpen(false);
18
+ onRequestDelete(w.id);
19
+ }, className: "text-muted-foreground hover:bg-destructive/10 hover:text-destructive rounded p-0.5 opacity-0 transition-opacity group-hover/ws-row:opacity-100 focus-visible:opacity-100", children: _jsx(Trash2, { className: "h-3.5 w-3.5" }) })) : null] })] }, w.id));
20
+ }), _jsx(DropdownMenuSeparator, {}), _jsxs(DropdownMenuItem, { onSelect: onRequestCreate, children: [_jsx(Plus, { className: "mr-2 h-3.5 w-3.5" }), "New workspace\u2026"] }), _jsxs(DropdownMenuItem, { onSelect: onManage, disabled: isDefault, children: [_jsx(SlidersHorizontal, { className: "mr-2 h-3.5 w-3.5" }), "Manage items\u2026"] }), _jsxs(DropdownMenuItem, { onSelect: onRequestRename, disabled: isDefault, children: [_jsx(Pencil, { className: "mr-2 h-3.5 w-3.5" }), "Rename"] })] })] }));
21
+ }