@shepai/cli 1.95.0 → 1.96.0-pr281.fcbc0cd

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 (264) hide show
  1. package/README.md +132 -348
  2. package/apis/json-schema/Feature.yaml +1 -1
  3. package/apis/json-schema/SdlcLifecycle.yaml +1 -0
  4. package/dist/packages/core/src/application/ports/output/repositories/feature-repository.interface.d.ts +16 -4
  5. package/dist/packages/core/src/application/ports/output/repositories/feature-repository.interface.d.ts.map +1 -1
  6. package/dist/packages/core/src/application/use-cases/features/delete-feature.use-case.d.ts +17 -12
  7. package/dist/packages/core/src/application/use-cases/features/delete-feature.use-case.d.ts.map +1 -1
  8. package/dist/packages/core/src/application/use-cases/features/delete-feature.use-case.js +64 -31
  9. package/dist/packages/core/src/application/use-cases/settings/complete-web-onboarding.use-case.d.ts +19 -0
  10. package/dist/packages/core/src/application/use-cases/settings/complete-web-onboarding.use-case.d.ts.map +1 -0
  11. package/dist/packages/core/src/application/use-cases/settings/complete-web-onboarding.use-case.js +52 -0
  12. package/dist/packages/core/src/application/use-cases/settings/index.d.ts +2 -0
  13. package/dist/packages/core/src/application/use-cases/settings/index.d.ts.map +1 -1
  14. package/dist/packages/core/src/application/use-cases/settings/index.js +1 -0
  15. package/dist/packages/core/src/domain/generated/output.d.ts +3 -2
  16. package/dist/packages/core/src/domain/generated/output.d.ts.map +1 -1
  17. package/dist/packages/core/src/domain/generated/output.js +1 -0
  18. package/dist/packages/core/src/infrastructure/di/container.d.ts.map +1 -1
  19. package/dist/packages/core/src/infrastructure/di/container.js +5 -0
  20. package/dist/packages/core/src/infrastructure/persistence/sqlite/mappers/feature.mapper.d.ts +1 -0
  21. package/dist/packages/core/src/infrastructure/persistence/sqlite/mappers/feature.mapper.d.ts.map +1 -1
  22. package/dist/packages/core/src/infrastructure/persistence/sqlite/mappers/feature.mapper.js +4 -0
  23. package/dist/packages/core/src/infrastructure/persistence/sqlite/migrations.d.ts.map +1 -1
  24. package/dist/packages/core/src/infrastructure/persistence/sqlite/migrations.js +12 -0
  25. package/dist/packages/core/src/infrastructure/repositories/sqlite-feature.repository.d.ts +2 -0
  26. package/dist/packages/core/src/infrastructure/repositories/sqlite-feature.repository.d.ts.map +1 -1
  27. package/dist/packages/core/src/infrastructure/repositories/sqlite-feature.repository.js +13 -3
  28. package/dist/src/presentation/cli/commands/feat/ls.command.d.ts.map +1 -1
  29. package/dist/src/presentation/cli/commands/feat/ls.command.js +9 -2
  30. package/dist/src/presentation/cli/commands/feat/new.command.d.ts.map +1 -1
  31. package/dist/src/presentation/cli/commands/feat/new.command.js +9 -0
  32. package/dist/src/presentation/cli/index.js +0 -12
  33. package/dist/src/presentation/web/app/actions/agent-setup-flag.d.ts +6 -0
  34. package/dist/src/presentation/web/app/actions/agent-setup-flag.d.ts.map +1 -0
  35. package/dist/src/presentation/web/app/actions/agent-setup-flag.js +14 -0
  36. package/dist/src/presentation/web/app/actions/check-agent-tool.d.ts +11 -0
  37. package/dist/src/presentation/web/app/actions/check-agent-tool.d.ts.map +1 -0
  38. package/dist/src/presentation/web/app/actions/check-agent-tool.js +35 -0
  39. package/dist/src/presentation/web/app/actions/update-agent-and-model.d.ts.map +1 -1
  40. package/dist/src/presentation/web/app/actions/update-agent-and-model.js +6 -12
  41. package/dist/src/presentation/web/app/api/agent-events/route.d.ts.map +1 -1
  42. package/dist/src/presentation/web/app/api/agent-events/route.js +1 -0
  43. package/dist/src/presentation/web/components/common/control-center-drawer/feature-drawer-client.d.ts.map +1 -1
  44. package/dist/src/presentation/web/components/common/control-center-drawer/feature-drawer-client.js +5 -0
  45. package/dist/src/presentation/web/components/common/feature-node/derive-feature-state.d.ts.map +1 -1
  46. package/dist/src/presentation/web/components/common/feature-node/derive-feature-state.js +4 -0
  47. package/dist/src/presentation/web/components/common/feature-node/feature-node-state-config.d.ts +1 -1
  48. package/dist/src/presentation/web/components/common/feature-node/feature-node-state-config.d.ts.map +1 -1
  49. package/dist/src/presentation/web/components/common/feature-node/feature-node-state-config.js +11 -1
  50. package/dist/src/presentation/web/components/common/feature-node/feature-node.d.ts.map +1 -1
  51. package/dist/src/presentation/web/components/common/feature-node/feature-node.js +4 -4
  52. package/dist/src/presentation/web/components/common/feature-node/feature-node.stories.d.ts +1 -0
  53. package/dist/src/presentation/web/components/common/feature-node/feature-node.stories.d.ts.map +1 -1
  54. package/dist/src/presentation/web/components/common/feature-node/feature-node.stories.js +21 -0
  55. package/dist/src/presentation/web/components/features/control-center/control-center-empty-state.d.ts.map +1 -1
  56. package/dist/src/presentation/web/components/features/control-center/control-center-empty-state.js +20 -4
  57. package/dist/src/presentation/web/components/features/control-center/use-control-center-state.d.ts.map +1 -1
  58. package/dist/src/presentation/web/components/features/control-center/use-control-center-state.js +53 -16
  59. package/dist/src/presentation/web/components/features/control-center/welcome-agent-setup.d.ts +6 -0
  60. package/dist/src/presentation/web/components/features/control-center/welcome-agent-setup.d.ts.map +1 -0
  61. package/dist/src/presentation/web/components/features/control-center/welcome-agent-setup.js +222 -0
  62. package/dist/src/presentation/web/components/features/control-center/welcome-agent-setup.stories.d.ts +7 -0
  63. package/dist/src/presentation/web/components/features/control-center/welcome-agent-setup.stories.d.ts.map +1 -0
  64. package/dist/src/presentation/web/components/features/control-center/welcome-agent-setup.stories.js +20 -0
  65. package/dist/src/presentation/web/components/layouts/app-shell/app-shell.js +1 -1
  66. package/dist/src/presentation/web/hooks/sidebar-features-context.d.ts.map +1 -1
  67. package/dist/src/presentation/web/hooks/sidebar-features-context.js +1 -0
  68. package/dist/src/presentation/web/hooks/use-graph-state.d.ts.map +1 -1
  69. package/dist/src/presentation/web/hooks/use-graph-state.js +27 -0
  70. package/dist/tsconfig.build.tsbuildinfo +1 -1
  71. package/package.json +1 -1
  72. package/web/.next/BUILD_ID +1 -1
  73. package/web/.next/build-manifest.json +2 -2
  74. package/web/.next/fallback-build-manifest.json +2 -2
  75. package/web/.next/prerender-manifest.json +3 -3
  76. package/web/.next/required-server-files.js +3 -3
  77. package/web/.next/required-server-files.json +3 -3
  78. package/web/.next/server/app/(dashboard)/@drawer/create/page/server-reference-manifest.json +92 -62
  79. package/web/.next/server/app/(dashboard)/@drawer/create/page.js +2 -2
  80. package/web/.next/server/app/(dashboard)/@drawer/create/page.js.nft.json +1 -1
  81. package/web/.next/server/app/(dashboard)/@drawer/create/page_client-reference-manifest.js +1 -1
  82. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page/server-reference-manifest.json +102 -42
  83. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page.js +2 -2
  84. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page.js.nft.json +1 -1
  85. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page_client-reference-manifest.js +1 -1
  86. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page/server-reference-manifest.json +102 -42
  87. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page.js +2 -2
  88. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page.js.nft.json +1 -1
  89. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page_client-reference-manifest.js +1 -1
  90. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page/server-reference-manifest.json +88 -28
  91. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page.js +2 -2
  92. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page.js.nft.json +1 -1
  93. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page_client-reference-manifest.js +1 -1
  94. package/web/.next/server/app/(dashboard)/create/page/server-reference-manifest.json +92 -62
  95. package/web/.next/server/app/(dashboard)/create/page.js +2 -2
  96. package/web/.next/server/app/(dashboard)/create/page.js.nft.json +1 -1
  97. package/web/.next/server/app/(dashboard)/create/page_client-reference-manifest.js +1 -1
  98. package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page/server-reference-manifest.json +102 -42
  99. package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page.js +2 -2
  100. package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page.js.nft.json +1 -1
  101. package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page_client-reference-manifest.js +1 -1
  102. package/web/.next/server/app/(dashboard)/feature/[featureId]/page/server-reference-manifest.json +102 -42
  103. package/web/.next/server/app/(dashboard)/feature/[featureId]/page.js +2 -2
  104. package/web/.next/server/app/(dashboard)/feature/[featureId]/page.js.nft.json +1 -1
  105. package/web/.next/server/app/(dashboard)/feature/[featureId]/page_client-reference-manifest.js +1 -1
  106. package/web/.next/server/app/(dashboard)/page/server-reference-manifest.json +88 -28
  107. package/web/.next/server/app/(dashboard)/page.js +2 -2
  108. package/web/.next/server/app/(dashboard)/page.js.nft.json +1 -1
  109. package/web/.next/server/app/(dashboard)/page_client-reference-manifest.js +1 -1
  110. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page/server-reference-manifest.json +88 -28
  111. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page.js +2 -2
  112. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page.js.nft.json +1 -1
  113. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page_client-reference-manifest.js +1 -1
  114. package/web/.next/server/app/_global-error.html +2 -2
  115. package/web/.next/server/app/_global-error.rsc +1 -1
  116. package/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  117. package/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  118. package/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  119. package/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  120. package/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  121. package/web/.next/server/app/_not-found/page/server-reference-manifest.json +1 -1
  122. package/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  123. package/web/.next/server/app/api/attachments/preview/route.js.nft.json +1 -1
  124. package/web/.next/server/app/settings/page/server-reference-manifest.json +5 -5
  125. package/web/.next/server/app/settings/page.js.nft.json +1 -1
  126. package/web/.next/server/app/settings/page_client-reference-manifest.js +1 -1
  127. package/web/.next/server/app/skills/page/server-reference-manifest.json +6 -6
  128. package/web/.next/server/app/skills/page.js.nft.json +1 -1
  129. package/web/.next/server/app/skills/page_client-reference-manifest.js +1 -1
  130. package/web/.next/server/app/tools/page/server-reference-manifest.json +6 -6
  131. package/web/.next/server/app/tools/page.js.nft.json +1 -1
  132. package/web/.next/server/app/tools/page_client-reference-manifest.js +1 -1
  133. package/web/.next/server/app/version/page/server-reference-manifest.json +1 -1
  134. package/web/.next/server/app/version/page_client-reference-manifest.js +1 -1
  135. package/web/.next/server/chunks/403f9_next_dist_esm_build_templates_app-route_4d623b8e.js +1 -1
  136. package/web/.next/server/chunks/403f9_next_dist_esm_build_templates_app-route_4d623b8e.js.map +1 -1
  137. package/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_create-drawer-client_tsx_5e26fc0a._.js +1 -1
  138. package/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_create-drawer-client_tsx_5e26fc0a._.js.map +1 -1
  139. package/web/.next/server/chunks/ssr/7f428_lucide-react_dist_esm_icons_2b65878f._.js +3 -0
  140. package/web/.next/server/chunks/ssr/7f428_lucide-react_dist_esm_icons_2b65878f._.js.map +1 -0
  141. package/web/.next/server/chunks/ssr/7f428_lucide-react_dist_esm_icons_6ba7eb21._.js +3 -0
  142. package/web/.next/server/chunks/ssr/7f428_lucide-react_dist_esm_icons_6ba7eb21._.js.map +1 -0
  143. package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_@drawer_repository_[repositoryId]_page_actions_c757eb00.js +3 -0
  144. package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_@drawer_repository_[repositoryId]_page_actions_c757eb00.js.map +1 -0
  145. package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_repository_[repositoryId]_page_actions_7eb49631.js +3 -0
  146. package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_repository_[repositoryId]_page_actions_7eb49631.js.map +1 -0
  147. package/web/.next/server/chunks/ssr/[root-of-the-server]__11033878._.js +1 -1
  148. package/web/.next/server/chunks/ssr/[root-of-the-server]__11033878._.js.map +1 -1
  149. package/web/.next/server/chunks/ssr/{[root-of-the-server]__17143953._.js → [root-of-the-server]__19fb0bfe._.js} +2 -2
  150. package/web/.next/server/chunks/ssr/{[root-of-the-server]__5cc4752a._.js.map → [root-of-the-server]__19fb0bfe._.js.map} +1 -1
  151. package/web/.next/server/chunks/ssr/[root-of-the-server]__24dd0927._.js +4 -0
  152. package/web/.next/server/chunks/ssr/[root-of-the-server]__24dd0927._.js.map +1 -0
  153. package/web/.next/server/chunks/ssr/[root-of-the-server]__357d99f9._.js +1 -1
  154. package/web/.next/server/chunks/ssr/{[root-of-the-server]__45aad79d._.js → [root-of-the-server]__3d6f6b0e._.js} +2 -2
  155. package/web/.next/server/chunks/ssr/{[root-of-the-server]__17143953._.js.map → [root-of-the-server]__3d6f6b0e._.js.map} +1 -1
  156. package/web/.next/server/chunks/ssr/{[root-of-the-server]__5cc4752a._.js → [root-of-the-server]__42020c54._.js} +2 -2
  157. package/web/.next/server/chunks/ssr/{[root-of-the-server]__9de266fa._.js.map → [root-of-the-server]__42020c54._.js.map} +1 -1
  158. package/web/.next/server/chunks/ssr/[root-of-the-server]__5d87af2e._.js +1 -1
  159. package/web/.next/server/chunks/ssr/[root-of-the-server]__5d87af2e._.js.map +1 -1
  160. package/web/.next/server/chunks/ssr/[root-of-the-server]__7b49fcb3._.js +3 -0
  161. package/web/.next/server/chunks/ssr/[root-of-the-server]__7b49fcb3._.js.map +1 -0
  162. package/web/.next/server/chunks/ssr/[root-of-the-server]__845a9d2a._.js +1 -1
  163. package/web/.next/server/chunks/ssr/[root-of-the-server]__845a9d2a._.js.map +1 -1
  164. package/web/.next/server/chunks/ssr/[root-of-the-server]__89e8a5cc._.js +2 -2
  165. package/web/.next/server/chunks/ssr/[root-of-the-server]__89e8a5cc._.js.map +1 -1
  166. package/web/.next/server/chunks/ssr/{[root-of-the-server]__9de266fa._.js → [root-of-the-server]__9cb60e1e._.js} +2 -2
  167. package/web/.next/server/chunks/ssr/{[root-of-the-server]__45aad79d._.js.map → [root-of-the-server]__9cb60e1e._.js.map} +1 -1
  168. package/web/.next/server/chunks/ssr/[root-of-the-server]__aad040c0._.js +1 -1
  169. package/web/.next/server/chunks/ssr/[root-of-the-server]__aad040c0._.js.map +1 -1
  170. package/web/.next/server/chunks/ssr/[root-of-the-server]__fdc75809._.js +1 -1
  171. package/web/.next/server/chunks/ssr/[root-of-the-server]__fdc75809._.js.map +1 -1
  172. package/web/.next/server/chunks/ssr/_135edb9c._.js +1 -1
  173. package/web/.next/server/chunks/ssr/_135edb9c._.js.map +1 -1
  174. package/web/.next/server/chunks/ssr/_1bb131c4._.js.map +1 -1
  175. package/web/.next/server/chunks/ssr/_501b06da._.js +3 -0
  176. package/web/.next/server/chunks/ssr/_501b06da._.js.map +1 -0
  177. package/web/.next/server/chunks/ssr/_5e112f82._.js +3 -0
  178. package/web/.next/server/chunks/ssr/_5e112f82._.js.map +1 -0
  179. package/web/.next/server/chunks/ssr/_6e08ce21._.js +1 -1
  180. package/web/.next/server/chunks/ssr/_6e08ce21._.js.map +1 -1
  181. package/web/.next/server/chunks/ssr/{_3533fed7._.js → _7f1598ce._.js} +2 -2
  182. package/web/.next/server/chunks/ssr/_7f1598ce._.js.map +1 -0
  183. package/web/.next/server/chunks/ssr/_8dacd1e7._.js +1 -1
  184. package/web/.next/server/chunks/ssr/_8dacd1e7._.js.map +1 -1
  185. package/web/.next/server/chunks/ssr/{_c2399eb5._.js → _c1e8bc5a._.js} +2 -2
  186. package/web/.next/server/chunks/ssr/{_c2399eb5._.js.map → _c1e8bc5a._.js.map} +1 -1
  187. package/web/.next/server/chunks/ssr/_cc77a143._.js +1 -1
  188. package/web/.next/server/chunks/ssr/_cc77a143._.js.map +1 -1
  189. package/web/.next/server/chunks/ssr/b1a17_presentation_web_components_features_settings_settings-page-client_tsx_6ed9d5f8._.js +1 -1
  190. package/web/.next/server/chunks/ssr/b1a17_presentation_web_components_features_settings_settings-page-client_tsx_6ed9d5f8._.js.map +1 -1
  191. package/web/.next/server/chunks/ssr/src_presentation_web_3c53a23d._.js +5 -0
  192. package/web/.next/server/chunks/ssr/src_presentation_web_3c53a23d._.js.map +1 -0
  193. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_befd865a.js +3 -0
  194. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_befd865a.js.map +1 -0
  195. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_skills_page_actions_1fa8042e.js +1 -1
  196. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_skills_page_actions_1fa8042e.js.map +1 -1
  197. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_tools_page_actions_24684200.js +1 -1
  198. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_tools_page_actions_24684200.js.map +1 -1
  199. package/web/.next/server/chunks/ssr/src_presentation_web_components_bf50c527._.js +1 -1
  200. package/web/.next/server/chunks/ssr/src_presentation_web_components_bf50c527._.js.map +1 -1
  201. package/web/.next/server/chunks/ssr/src_presentation_web_components_de814675._.js +1 -1
  202. package/web/.next/server/chunks/ssr/src_presentation_web_components_de814675._.js.map +1 -1
  203. package/web/.next/server/chunks/ssr/src_presentation_web_components_e599bb8c._.js +1 -1
  204. package/web/.next/server/chunks/ssr/src_presentation_web_components_e599bb8c._.js.map +1 -1
  205. package/web/.next/server/chunks/ssr/src_presentation_web_components_features_control-center_7ac3562e._.js +1 -1
  206. package/web/.next/server/chunks/ssr/src_presentation_web_components_features_control-center_7ac3562e._.js.map +1 -1
  207. package/web/.next/server/chunks/ssr/src_presentation_web_components_features_tools_tools-page-client_tsx_3d0aa70c._.js +1 -1
  208. package/web/.next/server/chunks/ssr/src_presentation_web_components_features_tools_tools-page-client_tsx_3d0aa70c._.js.map +1 -1
  209. package/web/.next/server/chunks/ssr/src_presentation_web_ec8c7a4f._.js +5 -0
  210. package/web/.next/server/chunks/ssr/src_presentation_web_ec8c7a4f._.js.map +1 -0
  211. package/web/.next/server/pages/500.html +2 -2
  212. package/web/.next/server/server-reference-manifest.js +1 -1
  213. package/web/.next/server/server-reference-manifest.json +482 -242
  214. package/web/.next/static/chunks/0043b0813128e1ff.js +1 -0
  215. package/web/.next/static/chunks/158f9d833716f8e0.js +1 -0
  216. package/web/.next/static/chunks/{465f63a101981da8.js → 1e45f54397cd5d7f.js} +1 -1
  217. package/web/.next/static/chunks/{c4bbbfcfc008cba4.js → 275e1e0c565cc109.js} +1 -1
  218. package/web/.next/static/chunks/71d785d1de4b86f6.css +1 -0
  219. package/web/.next/static/chunks/7268e1087af4eaa0.js +1 -0
  220. package/web/.next/static/chunks/86a559935e43c119.js +1 -0
  221. package/web/.next/static/chunks/8bd300e88a189928.js +1 -0
  222. package/web/.next/static/chunks/{98767389c1aad0b2.js → 8d943a1a82db483d.js} +1 -1
  223. package/web/.next/static/chunks/a262fb8cb5f35ce3.js +1 -0
  224. package/web/.next/static/chunks/ae4e669485fb8d72.js +1 -0
  225. package/web/.next/static/chunks/b272ac93b52dceeb.js +1 -0
  226. package/web/.next/static/chunks/{f0bbc2f086d7d996.js → b42e2cd6fe3896c3.js} +2 -2
  227. package/web/.next/static/chunks/{59b988d41943386c.js → c4e8e94e8c2800b0.js} +1 -1
  228. package/web/.next/server/chunks/ssr/7f428_lucide-react_dist_esm_icons_81a06555._.js +0 -3
  229. package/web/.next/server/chunks/ssr/7f428_lucide-react_dist_esm_icons_81a06555._.js.map +0 -1
  230. package/web/.next/server/chunks/ssr/7f428_lucide-react_dist_esm_icons_rocket_1575cd4d.js +0 -3
  231. package/web/.next/server/chunks/ssr/7f428_lucide-react_dist_esm_icons_rocket_1575cd4d.js.map +0 -1
  232. package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_@drawer_repository_[repositoryId]_page_actions_da7eef33.js +0 -3
  233. package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_@drawer_repository_[repositoryId]_page_actions_da7eef33.js.map +0 -1
  234. package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_repository_[repositoryId]_page_actions_0a9251aa.js +0 -3
  235. package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_repository_[repositoryId]_page_actions_0a9251aa.js.map +0 -1
  236. package/web/.next/server/chunks/ssr/[root-of-the-server]__4be9a9bb._.js +0 -4
  237. package/web/.next/server/chunks/ssr/[root-of-the-server]__4be9a9bb._.js.map +0 -1
  238. package/web/.next/server/chunks/ssr/[root-of-the-server]__9dc40036._.js +0 -3
  239. package/web/.next/server/chunks/ssr/[root-of-the-server]__9dc40036._.js.map +0 -1
  240. package/web/.next/server/chunks/ssr/_3533fed7._.js.map +0 -1
  241. package/web/.next/server/chunks/ssr/_364346ad._.js +0 -3
  242. package/web/.next/server/chunks/ssr/_364346ad._.js.map +0 -1
  243. package/web/.next/server/chunks/ssr/_df15bd24._.js +0 -3
  244. package/web/.next/server/chunks/ssr/_df15bd24._.js.map +0 -1
  245. package/web/.next/server/chunks/ssr/_f50485a5._.js +0 -3
  246. package/web/.next/server/chunks/ssr/_f50485a5._.js.map +0 -1
  247. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_021a05f2.js +0 -3
  248. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_021a05f2.js.map +0 -1
  249. package/web/.next/server/chunks/ssr/src_presentation_web_c4348b8a._.js +0 -5
  250. package/web/.next/server/chunks/ssr/src_presentation_web_c4348b8a._.js.map +0 -1
  251. package/web/.next/server/chunks/ssr/src_presentation_web_e4510d10._.js +0 -5
  252. package/web/.next/server/chunks/ssr/src_presentation_web_e4510d10._.js.map +0 -1
  253. package/web/.next/static/chunks/2536dce61f55daad.js +0 -1
  254. package/web/.next/static/chunks/35b142afe3405da9.js +0 -1
  255. package/web/.next/static/chunks/3c68b85c9dd7f200.js +0 -1
  256. package/web/.next/static/chunks/42040482bd2ec9aa.js +0 -1
  257. package/web/.next/static/chunks/490407527f8234cb.js +0 -1
  258. package/web/.next/static/chunks/6d61b6eaca9f925a.js +0 -1
  259. package/web/.next/static/chunks/8ec10587d1c608a2.css +0 -1
  260. package/web/.next/static/chunks/d9247a52ae260218.js +0 -1
  261. package/web/.next/static/chunks/eb981f9e02a74f15.js +0 -1
  262. /package/web/.next/static/{AT8BmALAnMpq68TlqG9FY → mF-tWwVmRA3ztS3klC9lR}/_buildManifest.js +0 -0
  263. /package/web/.next/static/{AT8BmALAnMpq68TlqG9FY → mF-tWwVmRA3ztS3klC9lR}/_clientMiddlewareManifest.json +0 -0
  264. /package/web/.next/static/{AT8BmALAnMpq68TlqG9FY → mF-tWwVmRA3ztS3klC9lR}/_ssgManifest.js +0 -0
@@ -99,7 +99,14 @@ export function useControlCenterState(initialNodes, initialEdges) {
99
99
  processedEventCountRef.current = events.length;
100
100
  for (const { featureId, state, lifecycle } of resolveSseEventUpdates(newEvents)) {
101
101
  if (state !== undefined || lifecycle !== undefined) {
102
- updateFeature(`feat-${featureId}`, {
102
+ const nodeId = `feat-${featureId}`;
103
+ // Skip SSE updates for features in 'deleting' state — the optimistic
104
+ // delete state must not be overwritten by stale SSE events (e.g. agent
105
+ // cancellation emitting AgentFailed during the soft-delete window).
106
+ const existingNode = nodesRef.current.find((n) => n.id === nodeId);
107
+ if (existingNode && existingNode.data.state === 'deleting')
108
+ continue;
109
+ updateFeature(nodeId, {
103
110
  ...(state !== undefined && { state }),
104
111
  ...(lifecycle !== undefined && { lifecycle }),
105
112
  });
@@ -192,32 +199,62 @@ export function useControlCenterState(initialNodes, initialEdges) {
192
199
  }, [addPendingFeature]);
193
200
  const handleDeleteFeature = useCallback((featureId, cleanup) => {
194
201
  const nodeId = `feat-${featureId}`;
195
- // Find the current entry for rollback
196
- const prevEntry = nodesRef.current
197
- .filter((n) => n.id === nodeId)
198
- .map((n) => ({
199
- nodeId: n.id,
200
- data: n.data,
201
- }))[0];
202
- // Optimistic removal
203
- removeFeature(nodeId);
202
+ // Collect all descendant feature node IDs (children, grandchildren, etc.)
203
+ const descendants = [];
204
+ const queue = [nodeId];
205
+ while (queue.length > 0) {
206
+ const current = queue.shift();
207
+ for (const edge of edgesRef.current) {
208
+ if (edge.type === 'dependencyEdge' && edge.source === current) {
209
+ descendants.push(edge.target);
210
+ queue.push(edge.target);
211
+ }
212
+ }
213
+ }
214
+ // Snapshot current states for rollback (parent + descendants)
215
+ const prevStates = new Map();
216
+ for (const nid of [nodeId, ...descendants]) {
217
+ const node = nodesRef.current.find((n) => n.id === nid);
218
+ if (node) {
219
+ prevStates.set(nid, node.data.state);
220
+ }
221
+ }
222
+ // Optimistic: show "deleting" state on parent AND all descendants
223
+ updateFeature(nodeId, { state: 'deleting' });
224
+ for (const childId of descendants) {
225
+ updateFeature(childId, { state: 'deleting' });
226
+ }
204
227
  deleteSound.play();
205
- toast.success('Feature deleted successfully');
228
+ toast.success('Deleting feature…');
206
229
  router.push('/');
207
230
  deleteFeature(featureId, cleanup)
208
231
  .then((result) => {
209
232
  if (result.error) {
210
- if (prevEntry)
211
- restoreFeature(nodeId, prevEntry);
233
+ // Rollback all to previous states
234
+ for (const [nid, prevState] of prevStates) {
235
+ if (prevState)
236
+ updateFeature(nid, { state: prevState });
237
+ }
212
238
  toast.error(result.error);
213
239
  }
240
+ else {
241
+ // Delete succeeded — remove features from the canvas. The polling
242
+ // reconcile would eventually clean them up, but we remove them
243
+ // explicitly so the user sees them disappear promptly.
244
+ removeFeature(nodeId);
245
+ for (const childId of descendants) {
246
+ removeFeature(childId);
247
+ }
248
+ }
214
249
  })
215
250
  .catch(() => {
216
- if (prevEntry)
217
- restoreFeature(nodeId, prevEntry);
251
+ for (const [nid, prevState] of prevStates) {
252
+ if (prevState)
253
+ updateFeature(nid, { state: prevState });
254
+ }
218
255
  toast.error('Failed to delete feature');
219
256
  });
220
- }, [router, deleteSound, removeFeature, restoreFeature]);
257
+ }, [router, deleteSound, updateFeature, removeFeature]);
221
258
  const handleDeleteRepository = useCallback(async (repositoryId) => {
222
259
  const repoNodeId = `repo-${repositoryId}`;
223
260
  // Find children of this repo via edges
@@ -0,0 +1,6 @@
1
+ export interface WelcomeAgentSetupProps {
2
+ onComplete: () => void;
3
+ className?: string;
4
+ }
5
+ export declare function WelcomeAgentSetup({ onComplete, className }: WelcomeAgentSetupProps): import("react/jsx-runtime").JSX.Element;
6
+ //# sourceMappingURL=welcome-agent-setup.d.ts.map
@@ -0,0 +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":"AA0BA,MAAM,WAAW,sBAAsB;IACrC,UAAU,EAAE,MAAM,IAAI,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AASD,wBAAgB,iBAAiB,CAAC,EAAE,UAAU,EAAE,SAAS,EAAE,EAAE,sBAAsB,2CAoTlF"}
@@ -0,0 +1,222 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
+ import { useState, useEffect, useCallback, useRef } from 'react';
4
+ import { Check, ChevronRight, ChevronLeft, Download, Loader2, CheckCircle2, Circle, AlertCircle, Bot, Terminal, ExternalLink, } from 'lucide-react';
5
+ import { getAllAgentModels } from '../../../app/actions/get-all-agent-models.js';
6
+ import { checkAgentTool } from '../../../app/actions/check-agent-tool.js';
7
+ import { updateAgentAndModel } from '../../../app/actions/update-agent-and-model.js';
8
+ import { getAgentTypeIcon } from '../../common/feature-node/agent-type-icons.js';
9
+ import { getModelMeta } from '../../../lib/model-metadata.js';
10
+ import { useToolInstallStream } from '../../../hooks/use-tool-install-stream.js';
11
+ import { cn } from '../../../lib/utils.js';
12
+ const STEPS = ['select-agent', 'select-model', 'check-tool', 'authenticate'];
13
+ /** Fixed width for the wizard content area to prevent layout jumps */
14
+ const WIZARD_WIDTH = 'w-72';
15
+ export function WelcomeAgentSetup({ onComplete, className }) {
16
+ const [groups, setGroups] = useState([]);
17
+ const [loading, setLoading] = useState(true);
18
+ const [step, setStep] = useState('select-agent');
19
+ const [selectedAgent, setSelectedAgent] = useState(null);
20
+ const [selectedModel, setSelectedModel] = useState(null);
21
+ const [toolStatus, setToolStatus] = useState(null);
22
+ const [checkingTool, setCheckingTool] = useState(false);
23
+ const [saving, setSaving] = useState(false);
24
+ const [transitioning, setTransitioning] = useState(false);
25
+ const [visible, setVisible] = useState(true);
26
+ const timeoutRef = useRef(undefined);
27
+ useEffect(() => {
28
+ getAllAgentModels()
29
+ .then(setGroups)
30
+ .finally(() => setLoading(false));
31
+ }, []);
32
+ const activeGroup = selectedAgent ? groups.find((g) => g.agentType === selectedAgent) : null;
33
+ /** Animate step transition: fade out → change step → fade in */
34
+ const transitionTo = useCallback((nextStep, setup) => {
35
+ setTransitioning(true);
36
+ setVisible(false);
37
+ if (timeoutRef.current)
38
+ clearTimeout(timeoutRef.current);
39
+ timeoutRef.current = setTimeout(() => {
40
+ setup?.();
41
+ setStep(nextStep);
42
+ // Small delay to let React render the new content before fading in
43
+ requestAnimationFrame(() => {
44
+ setVisible(true);
45
+ setTransitioning(false);
46
+ });
47
+ }, 150);
48
+ }, []);
49
+ useEffect(() => {
50
+ return () => {
51
+ if (timeoutRef.current)
52
+ clearTimeout(timeoutRef.current);
53
+ };
54
+ }, []);
55
+ const handleAgentSelect = useCallback((agentType) => {
56
+ const group = groups.find((g) => g.agentType === agentType);
57
+ if (group && group.models.length > 0) {
58
+ transitionTo('select-model', () => {
59
+ setSelectedAgent(agentType);
60
+ });
61
+ }
62
+ else {
63
+ transitionTo('check-tool', () => {
64
+ setSelectedAgent(agentType);
65
+ setSelectedModel('');
66
+ });
67
+ }
68
+ }, [groups, transitionTo]);
69
+ const handleModelSelect = useCallback((model) => {
70
+ transitionTo('check-tool', () => {
71
+ setSelectedModel(model);
72
+ });
73
+ }, [transitionTo]);
74
+ const handleProceedToAuth = useCallback(() => {
75
+ transitionTo('authenticate');
76
+ }, [transitionTo]);
77
+ const handleBack = useCallback(() => {
78
+ if (step === 'select-model') {
79
+ transitionTo('select-agent', () => {
80
+ setSelectedAgent(null);
81
+ });
82
+ }
83
+ else if (step === 'check-tool') {
84
+ if (activeGroup && activeGroup.models.length > 0) {
85
+ transitionTo('select-model', () => {
86
+ setSelectedModel(null);
87
+ });
88
+ }
89
+ else {
90
+ transitionTo('select-agent', () => {
91
+ setSelectedAgent(null);
92
+ });
93
+ }
94
+ }
95
+ else if (step === 'authenticate') {
96
+ // If tool needed install, go back to check-tool; otherwise skip to model/agent
97
+ if (toolStatus && !toolStatus.installed && toolStatus.toolId) {
98
+ transitionTo('check-tool');
99
+ }
100
+ else if (activeGroup && activeGroup.models.length > 0) {
101
+ transitionTo('select-model', () => {
102
+ setSelectedModel(null);
103
+ });
104
+ }
105
+ else {
106
+ transitionTo('select-agent', () => {
107
+ setSelectedAgent(null);
108
+ });
109
+ }
110
+ }
111
+ }, [step, activeGroup, toolStatus, transitionTo]);
112
+ useEffect(() => {
113
+ if (step !== 'check-tool' || !selectedAgent)
114
+ return;
115
+ setCheckingTool(true);
116
+ checkAgentTool(selectedAgent)
117
+ .then((status) => {
118
+ setToolStatus(status);
119
+ // Auto-skip to authenticate when tool is already available or not required
120
+ if (status.installed || !status.toolId) {
121
+ transitionTo('authenticate');
122
+ }
123
+ })
124
+ .finally(() => setCheckingTool(false));
125
+ }, [step, selectedAgent, transitionTo]);
126
+ const handleConfirm = useCallback(async () => {
127
+ if (!selectedAgent)
128
+ return;
129
+ setSaving(true);
130
+ try {
131
+ await updateAgentAndModel(selectedAgent, selectedModel ?? null);
132
+ onComplete();
133
+ }
134
+ finally {
135
+ setSaving(false);
136
+ }
137
+ }, [selectedAgent, selectedModel, onComplete]);
138
+ if (loading) {
139
+ return (_jsxs("div", { "data-testid": "welcome-agent-setup", className: cn('flex flex-col items-center justify-center gap-3', className), children: [_jsx(Loader2, { className: "text-muted-foreground h-4 w-4 animate-spin" }), _jsx("p", { className: "text-muted-foreground text-xs", children: "Loading agents\u2026" })] }));
140
+ }
141
+ const stepIndex = STEPS.indexOf(step);
142
+ return (_jsxs("div", { "data-testid": "welcome-agent-setup", className: cn('flex flex-col items-center gap-4', WIZARD_WIDTH, className), children: [_jsx("div", { className: "flex flex-col items-center gap-1", children: _jsxs("div", { className: "text-muted-foreground flex items-center gap-2", children: [step === 'select-agent' && (_jsxs(_Fragment, { children: [_jsx(Bot, { className: "h-3.5 w-3.5" }), _jsx("span", { className: "text-[10px] font-semibold tracking-widest uppercase", children: "Choose your agent" })] })), step === 'select-model' && activeGroup
143
+ ? (() => {
144
+ const AgentIcon = getAgentTypeIcon(activeGroup.agentType);
145
+ return (_jsxs(_Fragment, { children: [_jsx(AgentIcon, { className: "h-3.5 w-3.5" }), _jsxs("span", { className: "text-[10px] font-semibold tracking-widest uppercase", children: [activeGroup.label, " \u2014 Pick a model"] })] }));
146
+ })()
147
+ : null, step === 'check-tool' && (_jsxs(_Fragment, { children: [_jsx(Bot, { className: "h-3.5 w-3.5" }), _jsx("span", { className: "text-[10px] font-semibold tracking-widest uppercase", children: "Verifying setup" })] })), step === 'authenticate' && activeGroup
148
+ ? (() => {
149
+ const AgentIcon = getAgentTypeIcon(activeGroup.agentType);
150
+ return (_jsxs(_Fragment, { children: [_jsx(AgentIcon, { className: "h-3.5 w-3.5" }), _jsx("span", { className: "text-[10px] font-semibold tracking-widest uppercase", children: "Authenticate" })] }));
151
+ })()
152
+ : null] }) }), _jsx("div", { className: "flex w-32 items-center gap-1", children: STEPS.map((s, i) => (_jsx("div", { className: cn('h-0.5 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-150', visible && !transitioning ? 'opacity-100' : 'opacity-0'), children: [step === 'select-agent' && (_jsx("div", { "data-testid": "agent-list", className: "flex w-full flex-col gap-1.5", children: groups.map((group) => {
153
+ const GroupIcon = getAgentTypeIcon(group.agentType);
154
+ return (_jsxs("button", { type: "button", "data-testid": `agent-option-${group.agentType}`, className: "border-border hover:border-foreground/40 flex w-full cursor-pointer items-center gap-2.5 rounded-md border border-dashed px-4 py-2.5 transition-colors", onClick: () => handleAgentSelect(group.agentType), children: [_jsx(GroupIcon, { className: "text-muted-foreground h-4 w-4 shrink-0" }), _jsx("span", { className: "flex-1 text-left text-xs font-medium", children: group.label }), _jsx(ChevronRight, { className: "text-muted-foreground h-3 w-3" })] }, group.agentType));
155
+ }) })), step === 'select-model' && activeGroup ? (_jsxs("div", { "data-testid": "model-list", className: "flex w-full flex-col gap-1.5", children: [_jsxs("button", { type: "button", className: "text-muted-foreground hover:text-foreground mb-0.5 flex cursor-pointer items-center gap-1 self-start text-[10px] font-medium transition-colors", onClick: handleBack, children: [_jsx(ChevronLeft, { className: "h-3 w-3" }), "Back"] }), _jsx("div", { className: "flex max-h-48 w-full flex-col gap-1.5 overflow-y-auto", children: activeGroup.models.map((m) => {
156
+ const meta = getModelMeta(m.id);
157
+ return (_jsxs("button", { type: "button", "data-testid": `model-option-${m.id}`, className: "border-border hover:border-foreground/40 flex w-full cursor-pointer items-center gap-2.5 rounded-md border border-dashed px-4 py-2.5 text-left transition-colors", onClick: () => handleModelSelect(m.id), children: [_jsxs("div", { className: "flex min-w-0 flex-1 flex-col gap-0.5", children: [_jsx("span", { className: "text-xs font-medium", children: meta.displayName || m.displayName }), _jsx("span", { className: "text-muted-foreground text-[10px] leading-tight", children: meta.description || m.description })] }), _jsx(ChevronRight, { className: "text-muted-foreground h-3 w-3 shrink-0" })] }, m.id));
158
+ }) })] })) : null, step === 'check-tool' && (_jsx(ToolCheckStep, { toolStatus: toolStatus, checking: checkingTool, saving: false, onConfirm: handleProceedToAuth, onBack: handleBack, onToolInstalled: () => {
159
+ if (selectedAgent) {
160
+ setCheckingTool(true);
161
+ checkAgentTool(selectedAgent)
162
+ .then(setToolStatus)
163
+ .finally(() => setCheckingTool(false));
164
+ }
165
+ } })), step === 'authenticate' && toolStatus ? (_jsx(AuthenticateStep, { toolStatus: toolStatus, agentLabel: activeGroup?.label ?? selectedAgent ?? 'Agent', saving: saving, onConfirm: handleConfirm, onBack: handleBack })) : null] })] }));
166
+ }
167
+ /** Sub-component for the tool verification step */
168
+ function ToolCheckStep({ toolStatus, checking, saving, onConfirm, onBack, onToolInstalled, }) {
169
+ if (checking || !toolStatus) {
170
+ return (_jsxs("div", { className: "flex flex-col items-center gap-2 py-4", children: [_jsx(Loader2, { className: "text-muted-foreground h-4 w-4 animate-spin" }), _jsx("p", { className: "text-muted-foreground text-[10px]", children: "Checking tool availability\u2026" })] }));
171
+ }
172
+ // Agent doesn't require a tool (e.g., dev/demo)
173
+ if (!toolStatus.toolId) {
174
+ return (_jsxs("div", { className: "flex w-full flex-col items-center gap-3", children: [_jsxs("div", { className: "text-muted-foreground flex items-center gap-1.5", children: [_jsx(CheckCircle2, { className: "h-3.5 w-3.5" }), _jsx("span", { className: "text-xs", children: "No additional tools required" })] }), _jsx(ConfirmRow, { saving: saving, onConfirm: onConfirm, onBack: onBack })] }));
175
+ }
176
+ if (toolStatus.installed) {
177
+ return (_jsxs("div", { className: "flex w-full flex-col items-center gap-3", children: [_jsxs("div", { className: "text-muted-foreground flex items-center gap-1.5", children: [_jsx(CheckCircle2, { className: "h-3.5 w-3.5" }), _jsxs("span", { className: "text-xs", children: [toolStatus.tool?.name ?? toolStatus.toolId, " is installed"] })] }), _jsx(ConfirmRow, { saving: saving, onConfirm: onConfirm, onBack: onBack })] }));
178
+ }
179
+ return (_jsx(ToolInstallInline, { toolStatus: toolStatus, saving: saving, onConfirm: onConfirm, onBack: onBack, onInstalled: onToolInstalled }));
180
+ }
181
+ /** Shared back + continue row */
182
+ function ConfirmRow({ saving, onConfirm, onBack, label = 'Continue', }) {
183
+ return (_jsxs("div", { className: "flex items-center gap-3", children: [_jsxs("button", { type: "button", className: "text-muted-foreground hover:text-foreground cursor-pointer text-[10px] transition-colors", onClick: onBack, children: [_jsx(ChevronLeft, { className: "mr-0.5 inline h-3 w-3" }), "Back"] }), _jsxs("button", { type: "button", "data-testid": "agent-setup-confirm", disabled: saving, className: "border-border hover:border-foreground/40 flex cursor-pointer items-center gap-1.5 rounded-md border border-dashed px-4 py-2 text-xs font-medium transition-colors disabled:opacity-50", onClick: onConfirm, children: [saving ? _jsx(Loader2, { className: "h-3 w-3 animate-spin" }) : _jsx(Check, { className: "h-3 w-3" }), label] })] }));
184
+ }
185
+ /** Authenticate step — optional agent launch for auth */
186
+ function AuthenticateStep({ toolStatus, agentLabel, saving, onConfirm, onBack, }) {
187
+ const [launching, setLaunching] = useState(false);
188
+ const [launched, setLaunched] = useState(false);
189
+ const handleLaunch = useCallback(async () => {
190
+ if (!toolStatus.toolId)
191
+ return;
192
+ setLaunching(true);
193
+ try {
194
+ const res = await fetch(`/api/tools/${toolStatus.toolId}/launch`, { method: 'POST' });
195
+ if (res.ok)
196
+ setLaunched(true);
197
+ }
198
+ finally {
199
+ setLaunching(false);
200
+ }
201
+ }, [toolStatus.toolId]);
202
+ // No tool = no auth needed, skip straight to confirm
203
+ if (!toolStatus.toolId) {
204
+ return (_jsxs("div", { className: "flex w-full flex-col items-center gap-3", children: [_jsx("p", { className: "text-muted-foreground text-[10px]", children: "No authentication required" }), _jsx(ConfirmRow, { saving: saving, onConfirm: onConfirm, onBack: onBack, label: "Done" })] }));
205
+ }
206
+ return (_jsxs("div", { className: "flex w-full flex-col items-center gap-3", children: [_jsxs("p", { className: "text-muted-foreground text-center text-[10px] leading-relaxed", children: ["Open ", agentLabel, " in a terminal to sign in.", _jsx("br", {}), "Follow the prompts, then come back here."] }), _jsxs("button", { type: "button", "data-testid": "agent-setup-launch", disabled: launching, onClick: handleLaunch, className: "border-border hover:border-foreground/40 flex w-full cursor-pointer items-center gap-2.5 rounded-md border border-dashed px-4 py-2.5 transition-colors disabled:opacity-50", children: [launching ? (_jsx(Loader2, { className: "text-muted-foreground h-4 w-4 animate-spin" })) : (_jsx(Terminal, { className: "text-muted-foreground h-4 w-4" })), _jsx("span", { className: "flex-1 text-left text-xs font-medium", children: launched ? 'Open again' : `Open ${agentLabel}` }), _jsx(ExternalLink, { className: "text-muted-foreground h-3 w-3" })] }), launched ? (_jsx("p", { className: "text-muted-foreground text-[10px]", children: "Terminal opened \u2014 complete sign-in there" })) : null, toolStatus.binaryName ? (_jsxs("div", { className: "flex w-full flex-col gap-1", children: [_jsx("p", { className: "text-muted-foreground text-[10px]", children: "Or run manually in any terminal:" }), _jsxs("div", { className: "w-full rounded-md bg-zinc-900 px-3 py-1.5 font-mono text-[11px] text-zinc-300", children: [_jsx("span", { className: "text-zinc-500 select-none", children: "$ " }), toolStatus.binaryName] })] })) : null, _jsxs("div", { className: "flex items-center gap-3", children: [_jsxs("button", { type: "button", className: "text-muted-foreground hover:text-foreground cursor-pointer text-[10px] transition-colors", onClick: onBack, children: [_jsx(ChevronLeft, { className: "mr-0.5 inline h-3 w-3" }), "Back"] }), _jsxs("button", { type: "button", "data-testid": "agent-setup-confirm", disabled: saving, className: "border-border hover:border-foreground/40 flex cursor-pointer items-center gap-1.5 rounded-md border border-dashed px-4 py-2 text-xs font-medium transition-colors disabled:opacity-50", onClick: onConfirm, children: [saving ? _jsx(Loader2, { className: "h-3 w-3 animate-spin" }) : _jsx(Check, { className: "h-3 w-3" }), launched ? 'Done' : 'Skip'] })] })] }));
207
+ }
208
+ /** Inline tool installer for the welcome wizard */
209
+ function ToolInstallInline({ toolStatus, saving, onConfirm, onBack, onInstalled, }) {
210
+ const toolId = toolStatus.toolId ?? '';
211
+ const { logs, status, startInstall } = useToolInstallStream(toolId);
212
+ const isInstallDone = status === 'done';
213
+ const isInstallError = status === 'error';
214
+ useEffect(() => {
215
+ if (isInstallDone) {
216
+ onInstalled();
217
+ }
218
+ }, [isInstallDone, onInstalled]);
219
+ return (_jsxs("div", { className: "flex w-full flex-col items-center gap-3", children: [_jsxs("div", { className: "flex items-center gap-1.5", children: [isInstallDone ? (_jsx(CheckCircle2, { className: "text-muted-foreground h-3.5 w-3.5" })) : isInstallError ? (_jsx(AlertCircle, { className: "text-destructive h-3.5 w-3.5" })) : (_jsx(Circle, { className: "text-muted-foreground h-3.5 w-3.5" })), _jsxs("span", { className: "text-xs", children: [toolStatus.tool?.name ?? toolId, ' ', isInstallDone ? 'installed' : isInstallError ? 'install failed' : 'is not installed'] })] }), toolStatus.tool?.installCommand && status === 'idle' ? (_jsxs("div", { className: "w-full rounded-md bg-zinc-900 px-3 py-2 font-mono text-[11px] text-zinc-300", children: [_jsx("span", { className: "text-zinc-500 select-none", children: "$ " }), toolStatus.tool.installCommand] })) : null, (status === 'streaming' || isInstallDone || isInstallError) && logs.length > 0 ? (_jsxs("div", { className: "max-h-28 w-full overflow-auto rounded-md bg-zinc-900 px-3 py-2 font-mono text-[10px] leading-relaxed text-zinc-400", children: [logs.map((line, idx) => (
220
+ // eslint-disable-next-line react/no-array-index-key -- logs are append-only, never reorder
221
+ _jsx("div", { className: "break-all whitespace-pre-wrap", children: line }, idx))), isInstallDone ? (_jsx("div", { className: "text-muted-foreground mt-1", children: "Installation complete" })) : null, isInstallError ? (_jsx("div", { className: "text-destructive mt-1", children: "Installation failed \u2014 try manually" })) : null] })) : null, _jsxs("div", { className: "flex items-center gap-3", children: [_jsxs("button", { type: "button", className: "text-muted-foreground hover:text-foreground cursor-pointer text-[10px] transition-colors", onClick: onBack, children: [_jsx(ChevronLeft, { className: "mr-0.5 inline h-3 w-3" }), "Back"] }), !isInstallDone && toolStatus.tool?.autoInstall ? (_jsxs("button", { type: "button", "data-testid": "agent-setup-install", disabled: status === 'streaming', className: "border-border hover:border-foreground/40 flex cursor-pointer items-center gap-1.5 rounded-md border border-dashed px-4 py-2 text-xs font-medium transition-colors disabled:opacity-50", onClick: startInstall, children: [status === 'streaming' ? (_jsx(Loader2, { className: "h-3 w-3 animate-spin" })) : (_jsx(Download, { className: "h-3 w-3" })), status === 'streaming' ? 'Installing…' : 'Install'] })) : null, isInstallDone ? (_jsxs("button", { type: "button", "data-testid": "agent-setup-confirm", disabled: saving, className: "border-border hover:border-foreground/40 flex cursor-pointer items-center gap-1.5 rounded-md border border-dashed px-4 py-2 text-xs font-medium transition-colors disabled:opacity-50", onClick: onConfirm, children: [saving ? _jsx(Loader2, { className: "h-3 w-3 animate-spin" }) : _jsx(Check, { className: "h-3 w-3" }), "Continue"] })) : null] })] }));
222
+ }
@@ -0,0 +1,7 @@
1
+ import type { Meta, StoryObj } from '@storybook/react';
2
+ import { WelcomeAgentSetup } from './welcome-agent-setup.js';
3
+ declare const meta: Meta<typeof WelcomeAgentSetup>;
4
+ export default meta;
5
+ type Story = StoryObj<typeof meta>;
6
+ export declare const Default: Story;
7
+ //# sourceMappingURL=welcome-agent-setup.stories.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"welcome-agent-setup.stories.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/control-center/welcome-agent-setup.stories.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAEvD,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAE1D,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,OAAO,iBAAiB,CAcxC,CAAC;AAEF,eAAe,IAAI,CAAC;AACpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,IAAI,CAAC,CAAC;AAEnC,eAAO,MAAM,OAAO,EAAE,KAIrB,CAAC"}
@@ -0,0 +1,20 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { fn } from '@storybook/test';
3
+ import { WelcomeAgentSetup } from './welcome-agent-setup.js';
4
+ const meta = {
5
+ title: 'Features/WelcomeAgentSetup',
6
+ component: WelcomeAgentSetup,
7
+ tags: ['autodocs'],
8
+ parameters: {
9
+ layout: 'centered',
10
+ },
11
+ decorators: [
12
+ (Story) => (_jsx("div", { style: { width: 480, padding: 48, display: 'flex', justifyContent: 'center' }, children: _jsx(Story, {}) })),
13
+ ],
14
+ };
15
+ export default meta;
16
+ export const Default = {
17
+ args: {
18
+ onComplete: fn(),
19
+ },
20
+ };
@@ -29,7 +29,7 @@ function AppShellInner({ children }) {
29
29
  const handleRepositorySelect = useCallback((path) => {
30
30
  window.dispatchEvent(new CustomEvent('shep:add-repository', { detail: { path } }));
31
31
  }, []);
32
- return (_jsxs(SidebarProvider, { children: [_jsx(AppSidebar, { features: features, featureFlags: featureFlags, onNewFeature: handleNewFeature, onFeatureClick: handleFeatureClick }), _jsx(SidebarInset, { children: _jsxs("div", { className: "relative h-full", children: [_jsxs("div", { className: "absolute top-3 right-3 z-50 flex gap-1", children: [_jsx(AddRepositoryButton, { onSelect: handleRepositorySelect }), _jsx(SoundToggle, {}), _jsx(ThemeToggle, {})] }), _jsx("main", { className: "h-full", children: children })] }) })] }));
32
+ return (_jsxs(SidebarProvider, { defaultOpen: false, children: [_jsx(AppSidebar, { features: features, featureFlags: featureFlags, onNewFeature: handleNewFeature, onFeatureClick: handleFeatureClick }), _jsx(SidebarInset, { children: _jsxs("div", { className: "relative h-full", children: [_jsxs("div", { className: "absolute top-3 right-3 z-50 flex gap-1", children: [_jsx(AddRepositoryButton, { onSelect: handleRepositorySelect }), _jsx(SoundToggle, {}), _jsx(ThemeToggle, {})] }), _jsx("main", { className: "h-full", children: children })] }) })] }));
33
33
  }
34
34
  export function AppShell({ children }) {
35
35
  return (_jsx(AgentEventsProvider, { children: _jsx(DrawerCloseGuardProvider, { children: _jsx(SidebarFeaturesProvider, { children: _jsx(AppShellInner, { children: children }) }) }) }));
@@ -1 +1 @@
1
- {"version":3,"file":"sidebar-features-context.d.ts","sourceRoot":"","sources":["../../../../../src/presentation/web/hooks/sidebar-features-context.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAgD,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AACrF,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,4DAA4D,CAAC;AACnG,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2CAA2C,CAAC;AAI/E,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,aAAa,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAeD;;;GAGG;AACH,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,gBAAgB,GAAG,aAAa,GAAG,IAAI,CAEzF;AAMD,UAAU,2BAA2B;IACnC,QAAQ,EAAE,kBAAkB,EAAE,CAAC;IAC/B,WAAW,EAAE,CAAC,QAAQ,EAAE,kBAAkB,EAAE,KAAK,IAAI,CAAC;CACvD;AAID,UAAU,4BAA4B;IACpC,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED,wBAAgB,uBAAuB,CAAC,EAAE,QAAQ,EAAE,EAAE,4BAA4B,2CAQjF;AAED,wBAAgB,yBAAyB,IAAI,2BAA2B,CAMvE"}
1
+ {"version":3,"file":"sidebar-features-context.d.ts","sourceRoot":"","sources":["../../../../../src/presentation/web/hooks/sidebar-features-context.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAgD,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AACrF,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,4DAA4D,CAAC;AACnG,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2CAA2C,CAAC;AAI/E,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,aAAa,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAgBD;;;GAGG;AACH,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,gBAAgB,GAAG,aAAa,GAAG,IAAI,CAEzF;AAMD,UAAU,2BAA2B;IACnC,QAAQ,EAAE,kBAAkB,EAAE,CAAC;IAC/B,WAAW,EAAE,CAAC,QAAQ,EAAE,kBAAkB,EAAE,KAAK,IAAI,CAAC;CACvD;AAID,UAAU,4BAA4B;IACpC,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED,wBAAgB,uBAAuB,CAAC,EAAE,QAAQ,EAAE,EAAE,4BAA4B,2CAQjF;AAED,wBAAgB,yBAAyB,IAAI,2BAA2B,CAMvE"}
@@ -11,6 +11,7 @@ const stateMapping = {
11
11
  blocked: 'blocked',
12
12
  error: 'error',
13
13
  creating: null,
14
+ deleting: null,
14
15
  };
15
16
  /**
16
17
  * Maps a canvas FeatureNodeState to the sidebar's 5-state FeatureStatus.
@@ -1 +1 @@
1
- {"version":3,"file":"use-graph-state.d.ts","sourceRoot":"","sources":["../../../../../src/presentation/web/hooks/use-graph-state.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,IAAI,EAAY,MAAM,eAAe,CAAC;AACpD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uCAAuC,CAAC;AAC5E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AACxE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,qCAAqC,CAAC;AAC9E,OAAO,EAEL,KAAK,YAAY,EAEjB,KAAK,cAAc,EACpB,MAAM,oBAAoB,CAAC;AAG5B,YAAY,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAEzD,MAAM,WAAW,mBAAmB;IAClC,mDAAmD;IACnD,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB,mDAAmD;IACnD,KAAK,EAAE,IAAI,EAAE,CAAC;IACd;;;OAGG;IACH,SAAS,EAAE,CAAC,QAAQ,EAAE,cAAc,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,IAAI,CAAC;IAClE,uEAAuE;IACvE,aAAa,EAAE,CAAC,aAAa,EAAE,MAAM,EAAE,OAAO,EAAE,kBAAkB,KAAK,IAAI,CAAC;IAC5E,kEAAkE;IAClE,iBAAiB,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,eAAe,EAAE,YAAY,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1F,yDAAyD;IACzD,oBAAoB,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/C,sDAAsD;IACtD,aAAa,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,uDAAuD;IACvD,cAAc,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,KAAK,IAAI,CAAC;IAC9D,2DAA2D;IAC3D,aAAa,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,kBAAkB,KAAK,IAAI,CAAC;IAClE,gCAAgC;IAChC,gBAAgB,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3C,yDAAyD;IACzD,iBAAiB,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,kBAAkB,KAAK,IAAI,CAAC;IACtF,gEAAgE;IAChE,wBAAwB,EAAE,CAAC,aAAa,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;IACxE,yDAAyD;IACzD,iBAAiB,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,kBAAkB,GAAG,SAAS,CAAC;IACtE,+EAA+E;IAC/E,cAAc,EAAE,MAAM,MAAM,CAAC;IAC7B,6EAA6E;IAC7E,YAAY,EAAE,CAAC,SAAS,EAAE,cAAc,KAAK,IAAI,CAAC;CACnD;AAuCD,KAAK,kBAAkB,GAAG,OAAO,CAC/B,IAAI,CAAC,eAAe,EAAE,OAAO,GAAG,WAAW,GAAG,MAAM,GAAG,aAAa,CAAC,CACtE,CAAC;AAWF,wBAAgB,aAAa,CAC3B,YAAY,EAAE,cAAc,EAAE,EAC9B,YAAY,EAAE,IAAI,EAAE,GACnB,mBAAmB,CAoRrB"}
1
+ {"version":3,"file":"use-graph-state.d.ts","sourceRoot":"","sources":["../../../../../src/presentation/web/hooks/use-graph-state.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,IAAI,EAAY,MAAM,eAAe,CAAC;AACpD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uCAAuC,CAAC;AAC5E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AACxE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,qCAAqC,CAAC;AAC9E,OAAO,EAEL,KAAK,YAAY,EAEjB,KAAK,cAAc,EACpB,MAAM,oBAAoB,CAAC;AAG5B,YAAY,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAEzD,MAAM,WAAW,mBAAmB;IAClC,mDAAmD;IACnD,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB,mDAAmD;IACnD,KAAK,EAAE,IAAI,EAAE,CAAC;IACd;;;OAGG;IACH,SAAS,EAAE,CAAC,QAAQ,EAAE,cAAc,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,IAAI,CAAC;IAClE,uEAAuE;IACvE,aAAa,EAAE,CAAC,aAAa,EAAE,MAAM,EAAE,OAAO,EAAE,kBAAkB,KAAK,IAAI,CAAC;IAC5E,kEAAkE;IAClE,iBAAiB,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,eAAe,EAAE,YAAY,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1F,yDAAyD;IACzD,oBAAoB,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/C,sDAAsD;IACtD,aAAa,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,uDAAuD;IACvD,cAAc,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,KAAK,IAAI,CAAC;IAC9D,2DAA2D;IAC3D,aAAa,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,kBAAkB,KAAK,IAAI,CAAC;IAClE,gCAAgC;IAChC,gBAAgB,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3C,yDAAyD;IACzD,iBAAiB,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,kBAAkB,KAAK,IAAI,CAAC;IACtF,gEAAgE;IAChE,wBAAwB,EAAE,CAAC,aAAa,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;IACxE,yDAAyD;IACzD,iBAAiB,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,kBAAkB,GAAG,SAAS,CAAC;IACtE,+EAA+E;IAC/E,cAAc,EAAE,MAAM,MAAM,CAAC;IAC7B,6EAA6E;IAC7E,YAAY,EAAE,CAAC,SAAS,EAAE,cAAc,KAAK,IAAI,CAAC;CACnD;AAuCD,KAAK,kBAAkB,GAAG,OAAO,CAC/B,IAAI,CAAC,eAAe,EAAE,OAAO,GAAG,WAAW,GAAG,MAAM,GAAG,aAAa,CAAC,CACtE,CAAC;AAWF,wBAAgB,aAAa,CAC3B,YAAY,EAAE,cAAc,EAAE,EAC9B,YAAY,EAAE,IAAI,EAAE,GACnB,mBAAmB,CAgTrB"}
@@ -45,6 +45,10 @@ export function useGraphState(initialNodes, initialEdges) {
45
45
  // Buffer for SSE updates that arrive before their feature is in featureMap.
46
46
  // When reconcile adds new features, buffered updates are applied automatically.
47
47
  const pendingUpdatesRef = useRef(new Map());
48
+ // Track 'deleting' features that the server no longer returns.
49
+ // Retained for one extra reconcile cycle so the user sees the deleting state
50
+ // before the node disappears from the canvas.
51
+ const deletingRetainedRef = useRef(new Set());
48
52
  // Callbacks stored in a ref so changing them doesn't trigger re-render.
49
53
  // The stable wrapper object reads from the ref so node closures always use latest callbacks.
50
54
  const callbacksRef = useRef({});
@@ -113,6 +117,29 @@ export function useGraphState(initialNodes, initialEdges) {
113
117
  merged.set(tempId, pendingEntry);
114
118
  }
115
119
  }
120
+ // Preserve 'deleting' state for features being deleted.
121
+ // If the server still returns the feature, override its state to 'deleting'.
122
+ // If the server no longer returns it (soft-deleted), retain it for one
123
+ // extra reconcile cycle so the user sees the deleting animation.
124
+ const nextRetained = new Set();
125
+ for (const [id, entry] of currentFeatureMap) {
126
+ if (entry.data.state === 'deleting') {
127
+ if (merged.has(id)) {
128
+ // Server still has it — override state to keep showing 'deleting'
129
+ merged.set(id, {
130
+ ...merged.get(id),
131
+ data: { ...merged.get(id).data, state: 'deleting' },
132
+ });
133
+ }
134
+ else if (!deletingRetainedRef.current.has(id)) {
135
+ // First reconcile after server removal — retain with deleting state
136
+ merged.set(id, entry);
137
+ nextRetained.add(id);
138
+ }
139
+ // else: already retained once — let it disappear
140
+ }
141
+ }
142
+ deletingRetainedRef.current = nextRetained;
116
143
  // Apply any buffered SSE updates to features that now exist in the map
117
144
  for (const [nodeId, updates] of pendingUpdatesRef.current) {
118
145
  const entry = merged.get(nodeId);