@shepai/cli 1.72.6 → 1.72.7-pr187.86f6440
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.
- package/dist/packages/core/src/application/use-cases/features/delete-feature.use-case.d.ts +4 -0
- package/dist/packages/core/src/application/use-cases/features/delete-feature.use-case.d.ts.map +1 -1
- package/dist/packages/core/src/application/use-cases/features/delete-feature.use-case.js +20 -12
- package/dist/packages/core/src/application/use-cases/repositories/delete-repository.use-case.d.ts +8 -3
- package/dist/packages/core/src/application/use-cases/repositories/delete-repository.use-case.d.ts.map +1 -1
- package/dist/packages/core/src/application/use-cases/repositories/delete-repository.use-case.js +17 -4
- package/dist/packages/core/src/infrastructure/repositories/sqlite-feature.repository.js +1 -1
- package/dist/packages/core/src/infrastructure/services/tool-installer/tool-installer.service.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/services/tool-installer/tool-installer.service.js +9 -1
- package/dist/packages/core/src/infrastructure/services/tool-installer/tool-metadata.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/services/tool-installer/tool-metadata.js +5 -0
- package/dist/packages/core/src/infrastructure/services/tool-installer/tools/alacritty.json +2 -2
- package/dist/packages/core/src/infrastructure/services/tool-installer/tools/kitty.json +2 -2
- package/dist/packages/core/src/infrastructure/services/tool-installer/tools/tmux.json +1 -1
- package/dist/packages/core/src/infrastructure/services/tool-installer/tools/vscode.json +1 -1
- package/dist/packages/core/src/infrastructure/services/tool-installer/tools/windsurf.json +1 -1
- package/dist/src/presentation/web/app/(dashboard)/get-graph-data.d.ts.map +1 -1
- package/dist/src/presentation/web/app/(dashboard)/get-graph-data.js +2 -6
- package/dist/src/presentation/web/app/api/tools/[id]/install/route.d.ts.map +1 -1
- package/dist/src/presentation/web/app/api/tools/[id]/install/route.js +9 -4
- package/dist/src/presentation/web/app/api/tools/[id]/install/stream/route.d.ts +7 -0
- package/dist/src/presentation/web/app/api/tools/[id]/install/stream/route.d.ts.map +1 -0
- package/dist/src/presentation/web/app/api/tools/[id]/install/stream/route.js +32 -0
- package/dist/src/presentation/web/app/build-graph-nodes.js +11 -1
- package/dist/src/presentation/web/components/common/base-drawer/base-drawer.d.ts +3 -1
- package/dist/src/presentation/web/components/common/base-drawer/base-drawer.d.ts.map +1 -1
- package/dist/src/presentation/web/components/common/base-drawer/base-drawer.js +8 -4
- package/dist/src/presentation/web/components/common/control-center-drawer/create-drawer-client.d.ts.map +1 -1
- package/dist/src/presentation/web/components/common/control-center-drawer/create-drawer-client.js +12 -3
- package/dist/src/presentation/web/components/common/control-center-drawer/feature-drawer-client.d.ts.map +1 -1
- package/dist/src/presentation/web/components/common/control-center-drawer/feature-drawer-client.js +6 -2
- package/dist/src/presentation/web/components/common/drawer-action-bar/drawer-action-bar.d.ts.map +1 -1
- package/dist/src/presentation/web/components/common/drawer-action-bar/drawer-action-bar.js +1 -1
- package/dist/src/presentation/web/components/common/feature-create-drawer/feature-create-drawer.d.ts.map +1 -1
- package/dist/src/presentation/web/components/common/feature-create-drawer/feature-create-drawer.js +1 -1
- package/dist/src/presentation/web/components/common/feature-node/feature-node.d.ts.map +1 -1
- package/dist/src/presentation/web/components/common/feature-node/feature-node.js +7 -2
- package/dist/src/presentation/web/components/common/repository-node/repository-node.d.ts.map +1 -1
- package/dist/src/presentation/web/components/common/repository-node/repository-node.js +6 -2
- package/dist/src/presentation/web/components/features/control-center/control-center-inner.d.ts.map +1 -1
- package/dist/src/presentation/web/components/features/control-center/control-center-inner.js +14 -2
- package/dist/src/presentation/web/components/features/control-center/use-control-center-state.d.ts +3 -5
- package/dist/src/presentation/web/components/features/control-center/use-control-center-state.d.ts.map +1 -1
- package/dist/src/presentation/web/components/features/control-center/use-control-center-state.js +131 -196
- package/dist/src/presentation/web/components/features/index.d.ts +1 -1
- package/dist/src/presentation/web/components/features/index.d.ts.map +1 -1
- package/dist/src/presentation/web/components/features/index.js +1 -1
- package/dist/src/presentation/web/components/features/tools/index.d.ts +1 -1
- package/dist/src/presentation/web/components/features/tools/index.d.ts.map +1 -1
- package/dist/src/presentation/web/components/features/tools/index.js +1 -1
- package/dist/src/presentation/web/components/features/tools/tool-card.d.ts.map +1 -1
- package/dist/src/presentation/web/components/features/tools/tool-card.js +11 -12
- package/dist/src/presentation/web/components/features/tools/tool-detail-drawer.d.ts +10 -0
- package/dist/src/presentation/web/components/features/tools/tool-detail-drawer.d.ts.map +1 -0
- package/dist/src/presentation/web/components/features/tools/tool-detail-drawer.js +88 -0
- package/dist/src/presentation/web/components/features/tools/tool-detail-drawer.stories.d.ts +12 -0
- package/dist/src/presentation/web/components/features/tools/tool-detail-drawer.stories.d.ts.map +1 -0
- package/dist/src/presentation/web/components/features/tools/tool-detail-drawer.stories.js +116 -0
- package/dist/src/presentation/web/components/ui/alert-dialog.d.ts +1 -1
- package/dist/src/presentation/web/components/ui/alert-dialog.d.ts.map +1 -1
- package/dist/src/presentation/web/components/ui/alert-dialog.js +7 -2
- package/dist/src/presentation/web/components/ui/dialog.d.ts.map +1 -1
- package/dist/src/presentation/web/components/ui/dialog.js +6 -1
- package/dist/src/presentation/web/hooks/use-tool-install-stream.d.ts +10 -0
- package/dist/src/presentation/web/hooks/use-tool-install-stream.d.ts.map +1 -0
- package/dist/src/presentation/web/hooks/use-tool-install-stream.js +38 -0
- package/dist/src/presentation/web/lib/layout-with-dagre.d.ts +2 -0
- package/dist/src/presentation/web/lib/layout-with-dagre.d.ts.map +1 -1
- package/dist/src/presentation/web/lib/layout-with-dagre.js +86 -4
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/web/.next/BUILD_ID +1 -1
- package/web/.next/app-path-routes-manifest.json +1 -0
- package/web/.next/build-manifest.json +7 -7
- package/web/.next/cache/.previewinfo +1 -1
- package/web/.next/cache/.rscinfo +1 -1
- package/web/.next/cache/.tsbuildinfo +1 -1
- package/web/.next/cache/config.json +3 -3
- package/web/.next/fallback-build-manifest.json +2 -2
- package/web/.next/prerender-manifest.json +3 -3
- package/web/.next/required-server-files.js +1 -1
- package/web/.next/required-server-files.json +1 -1
- package/web/.next/routes-manifest.json +8 -0
- package/web/.next/server/app/(dashboard)/@drawer/create/page/build-manifest.json +5 -5
- package/web/.next/server/app/(dashboard)/@drawer/create/page/server-reference-manifest.json +14 -14
- package/web/.next/server/app/(dashboard)/@drawer/create/page.js +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/create/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/create/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page/build-manifest.json +5 -5
- package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page/server-reference-manifest.json +17 -17
- package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page.js +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page/build-manifest.json +5 -5
- package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page/server-reference-manifest.json +12 -12
- package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page.js +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/create/page/build-manifest.json +5 -5
- package/web/.next/server/app/(dashboard)/create/page/server-reference-manifest.json +14 -14
- package/web/.next/server/app/(dashboard)/create/page.js +1 -1
- package/web/.next/server/app/(dashboard)/create/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/create/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/feature/[featureId]/page/build-manifest.json +5 -5
- package/web/.next/server/app/(dashboard)/feature/[featureId]/page/server-reference-manifest.json +17 -17
- package/web/.next/server/app/(dashboard)/feature/[featureId]/page.js +1 -1
- package/web/.next/server/app/(dashboard)/feature/[featureId]/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/feature/[featureId]/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/page/build-manifest.json +5 -5
- package/web/.next/server/app/(dashboard)/page/server-reference-manifest.json +12 -12
- package/web/.next/server/app/(dashboard)/page.js +1 -1
- package/web/.next/server/app/(dashboard)/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page/build-manifest.json +5 -5
- package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page/server-reference-manifest.json +12 -12
- package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page.js +1 -1
- package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/_global-error/page/build-manifest.json +5 -5
- package/web/.next/server/app/_global-error.html +2 -2
- package/web/.next/server/app/_global-error.rsc +1 -1
- package/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
- package/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/web/.next/server/app/_not-found/page/build-manifest.json +5 -5
- package/web/.next/server/app/_not-found/page/server-reference-manifest.json +1 -1
- package/web/.next/server/app/_not-found/page.js.nft.json +1 -1
- package/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/api/tools/[id]/install/route.js +1 -1
- package/web/.next/server/app/api/tools/[id]/install/route.js.nft.json +1 -1
- package/web/.next/server/app/api/tools/[id]/install/stream/route/app-paths-manifest.json +3 -0
- package/web/.next/server/app/api/tools/[id]/install/stream/route/build-manifest.json +11 -0
- package/web/.next/server/app/api/tools/[id]/install/stream/route/server-reference-manifest.json +4 -0
- package/web/.next/server/app/api/tools/[id]/install/stream/route.js +6 -0
- package/web/.next/server/app/api/tools/[id]/install/stream/route.js.map +5 -0
- package/web/.next/server/app/api/tools/[id]/install/stream/route.js.nft.json +1 -0
- package/web/.next/server/app/api/tools/[id]/install/stream/route_client-reference-manifest.js +2 -0
- package/web/.next/server/app/skills/page/build-manifest.json +5 -5
- package/web/.next/server/app/skills/page/server-reference-manifest.json +6 -6
- package/web/.next/server/app/skills/page.js +1 -1
- package/web/.next/server/app/skills/page.js.nft.json +1 -1
- package/web/.next/server/app/skills/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/tools/page/build-manifest.json +5 -5
- package/web/.next/server/app/tools/page/server-reference-manifest.json +77 -2
- package/web/.next/server/app/tools/page.js +2 -2
- package/web/.next/server/app/tools/page.js.nft.json +1 -1
- package/web/.next/server/app/tools/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/version/page/build-manifest.json +5 -5
- package/web/.next/server/app/version/page/server-reference-manifest.json +1 -1
- package/web/.next/server/app/version/page.js.nft.json +1 -1
- package/web/.next/server/app/version/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app-paths-manifest.json +1 -0
- package/web/.next/server/chunks/[root-of-the-server]__0866d2b5._.js +3 -0
- package/web/.next/server/chunks/[root-of-the-server]__0866d2b5._.js.map +1 -0
- package/web/.next/server/chunks/[root-of-the-server]__e247a485._.js +11 -0
- package/web/.next/server/chunks/[root-of-the-server]__e247a485._.js.map +1 -0
- package/web/.next/server/chunks/f3a1f__next-internal_server_app_api_tools_[id]_install_stream_route_actions_1fe5bd5d.js +3 -0
- package/web/.next/server/chunks/f3a1f__next-internal_server_app_api_tools_[id]_install_stream_route_actions_1fe5bd5d.js.map +1 -0
- package/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_create-drawer-client_tsx_5e26fc0a._.js +1 -1
- package/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_create-drawer-client_tsx_5e26fc0a._.js.map +1 -1
- package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_@drawer_repository_[repositoryId]_page_actions_2b7834f6.js +1 -1
- package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_@drawer_repository_[repositoryId]_page_actions_2b7834f6.js.map +1 -1
- package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_repository_[repositoryId]_page_actions_6923c575.js +1 -1
- package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_repository_[repositoryId]_page_actions_6923c575.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__17a611f0._.js +4 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__17a611f0._.js.map +1 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__249c74f6._.js +1 -1
- package/web/.next/{standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__07385073._.js → server/chunks/ssr/[root-of-the-server]__45dbf93d._.js} +3 -3
- package/web/.next/server/chunks/ssr/{[root-of-the-server]__07385073._.js.map → [root-of-the-server]__45dbf93d._.js.map} +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__6b17a22d._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__6b17a22d._.js.map +1 -1
- package/web/.next/{standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__8fcb9132._.js → server/chunks/ssr/[root-of-the-server]__6cbc1149._.js} +3 -3
- package/web/.next/server/chunks/ssr/[root-of-the-server]__6cbc1149._.js.map +1 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__804c006d._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__804c006d._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__aad040c0._.js +3 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__aad040c0._.js.map +1 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__aef6b3cd._.js +3 -0
- package/web/.next/server/chunks/ssr/{[root-of-the-server]__8c1a3d66._.js.map → [root-of-the-server]__aef6b3cd._.js.map} +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__c04c8ff2._.js +3 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__c04c8ff2._.js.map +1 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__c134fc13._.js +3 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__c134fc13._.js.map +1 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__c18f84a4._.js +3 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__c18f84a4._.js.map +1 -0
- package/web/.next/server/chunks/ssr/_07c2a32a._.js +1 -1
- package/web/.next/server/chunks/ssr/_07c2a32a._.js.map +1 -1
- package/web/.next/server/chunks/ssr/_0e9d6bf7._.js +3 -0
- package/web/.next/server/chunks/ssr/_0e9d6bf7._.js.map +1 -0
- package/web/.next/server/chunks/ssr/_3197d5cb._.js +3 -0
- package/web/.next/server/chunks/ssr/_3197d5cb._.js.map +1 -0
- package/web/.next/server/chunks/ssr/_4e5db14b._.js +7 -0
- package/web/.next/server/chunks/ssr/_4e5db14b._.js.map +1 -0
- package/web/.next/server/chunks/ssr/_61351ed3._.js +3 -0
- package/web/.next/server/chunks/ssr/_61351ed3._.js.map +1 -0
- package/web/.next/server/chunks/ssr/_797dbf60._.js +3 -0
- package/web/.next/server/chunks/ssr/_797dbf60._.js.map +1 -0
- package/web/.next/server/chunks/ssr/_8400c8bb._.js +3 -0
- package/web/.next/server/chunks/ssr/_8400c8bb._.js.map +1 -0
- package/web/.next/server/chunks/ssr/_a29296f0._.js +3 -0
- package/web/.next/server/chunks/ssr/_a29296f0._.js.map +1 -0
- package/web/.next/{standalone/src/presentation/web/.next/server/chunks/ssr/_e50484ec._.js → server/chunks/ssr/_a2a86eed._.js} +2 -2
- package/web/.next/server/chunks/ssr/{_e50484ec._.js.map → _a2a86eed._.js.map} +1 -1
- package/web/.next/server/chunks/ssr/_dd1c549f._.js +3 -0
- package/web/.next/server/chunks/ssr/_dd1c549f._.js.map +1 -0
- package/web/.next/server/chunks/ssr/src_presentation_web_1a32dbcb._.js +2 -2
- package/web/.next/server/chunks/ssr/src_presentation_web_1a32dbcb._.js.map +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_398553b0._.js +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_398553b0._.js.map +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_5c87e8e4._.js +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_5c87e8e4._.js.map +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_f4952172.js +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_f4952172.js.map +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_c1bc6240._.js +2 -2
- package/web/.next/server/chunks/ssr/src_presentation_web_c1bc6240._.js.map +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_ca99d62d._.js +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_ca99d62d._.js.map +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_components_features_control-center_7ac3562e._.js +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_components_features_control-center_7ac3562e._.js.map +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_components_features_tools_tools-page-client_tsx_3d0aa70c._.js +3 -0
- package/web/.next/server/chunks/ssr/src_presentation_web_components_features_tools_tools-page-client_tsx_3d0aa70c._.js.map +1 -0
- package/web/.next/server/middleware-build-manifest.js +5 -5
- package/web/.next/server/pages/500.html +2 -2
- package/web/.next/server/server-reference-manifest.js +1 -1
- package/web/.next/server/server-reference-manifest.json +61 -26
- package/web/.next/standalone/src/presentation/web/.next/BUILD_ID +1 -1
- package/web/.next/standalone/src/presentation/web/.next/app-path-routes-manifest.json +1 -0
- package/web/.next/standalone/src/presentation/web/.next/build-manifest.json +7 -7
- package/web/.next/standalone/src/presentation/web/.next/prerender-manifest.json +3 -3
- package/web/.next/standalone/src/presentation/web/.next/required-server-files.json +1 -1
- package/web/.next/standalone/src/presentation/web/.next/routes-manifest.json +8 -0
- package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/@drawer/create/page/build-manifest.json +5 -5
- package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/@drawer/create/page/server-reference-manifest.json +14 -14
- package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/@drawer/create/page.js +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/@drawer/create/page.js.nft.json +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/@drawer/create/page_client-reference-manifest.js +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page/build-manifest.json +5 -5
- package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page/server-reference-manifest.json +17 -17
- package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page.js +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page.js.nft.json +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page_client-reference-manifest.js +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page/build-manifest.json +5 -5
- package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page/server-reference-manifest.json +12 -12
- package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page.js +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page.js.nft.json +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page_client-reference-manifest.js +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/create/page/build-manifest.json +5 -5
- package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/create/page/server-reference-manifest.json +14 -14
- package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/create/page.js +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/create/page.js.nft.json +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/create/page_client-reference-manifest.js +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/feature/[featureId]/page/build-manifest.json +5 -5
- package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/feature/[featureId]/page/server-reference-manifest.json +17 -17
- package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/feature/[featureId]/page.js +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/feature/[featureId]/page.js.nft.json +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/feature/[featureId]/page_client-reference-manifest.js +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/page/build-manifest.json +5 -5
- package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/page/server-reference-manifest.json +12 -12
- package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/page.js +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/page.js.nft.json +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/page_client-reference-manifest.js +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/repository/[repositoryId]/page/build-manifest.json +5 -5
- package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/repository/[repositoryId]/page/server-reference-manifest.json +12 -12
- package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/repository/[repositoryId]/page.js +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/repository/[repositoryId]/page.js.nft.json +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/repository/[repositoryId]/page_client-reference-manifest.js +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error/page/build-manifest.json +5 -5
- package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.html +2 -2
- package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.rsc +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/_not-found/page/build-manifest.json +5 -5
- package/web/.next/standalone/src/presentation/web/.next/server/app/_not-found/page/server-reference-manifest.json +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/_not-found/page.js.nft.json +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/api/tools/[id]/install/route.js +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/api/tools/[id]/install/route.js.nft.json +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/api/tools/[id]/install/stream/route/app-paths-manifest.json +3 -0
- package/web/.next/standalone/src/presentation/web/.next/server/app/api/tools/[id]/install/stream/route/build-manifest.json +11 -0
- package/web/.next/standalone/src/presentation/web/.next/server/app/api/tools/[id]/install/stream/route/server-reference-manifest.json +4 -0
- package/web/.next/standalone/src/presentation/web/.next/server/app/api/tools/[id]/install/stream/route.js +6 -0
- package/web/.next/standalone/src/presentation/web/.next/server/app/api/tools/[id]/install/stream/route.js.map +5 -0
- package/web/.next/standalone/src/presentation/web/.next/server/app/api/tools/[id]/install/stream/route.js.nft.json +1 -0
- package/web/.next/standalone/src/presentation/web/.next/server/app/api/tools/[id]/install/stream/route_client-reference-manifest.js +2 -0
- package/web/.next/standalone/src/presentation/web/.next/server/app/skills/page/build-manifest.json +5 -5
- package/web/.next/standalone/src/presentation/web/.next/server/app/skills/page/server-reference-manifest.json +6 -6
- package/web/.next/standalone/src/presentation/web/.next/server/app/skills/page.js +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/skills/page.js.nft.json +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/skills/page_client-reference-manifest.js +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/tools/page/build-manifest.json +5 -5
- package/web/.next/standalone/src/presentation/web/.next/server/app/tools/page/server-reference-manifest.json +77 -2
- package/web/.next/standalone/src/presentation/web/.next/server/app/tools/page.js +2 -2
- package/web/.next/standalone/src/presentation/web/.next/server/app/tools/page.js.nft.json +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/tools/page_client-reference-manifest.js +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/version/page/build-manifest.json +5 -5
- package/web/.next/standalone/src/presentation/web/.next/server/app/version/page/server-reference-manifest.json +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/version/page.js.nft.json +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/version/page_client-reference-manifest.js +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app-paths-manifest.json +1 -0
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/[root-of-the-server]__0866d2b5._.js +3 -0
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/[root-of-the-server]__e247a485._.js +11 -0
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/f3a1f__next-internal_server_app_api_tools_[id]_install_stream_route_actions_1fe5bd5d.js +3 -0
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_create-drawer-client_tsx_5e26fc0a._.js +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_@drawer_repository_[repositoryId]_page_actions_2b7834f6.js +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_repository_[repositoryId]_page_actions_6923c575.js +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__17a611f0._.js +4 -0
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__249c74f6._.js +1 -1
- package/web/.next/{server/chunks/ssr/[root-of-the-server]__07385073._.js → standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__45dbf93d._.js} +3 -3
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__6b17a22d._.js +1 -1
- package/web/.next/{server/chunks/ssr/[root-of-the-server]__8fcb9132._.js → standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__6cbc1149._.js} +3 -3
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__804c006d._.js +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__aad040c0._.js +3 -0
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__aef6b3cd._.js +3 -0
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__c04c8ff2._.js +3 -0
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__c134fc13._.js +3 -0
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__c18f84a4._.js +3 -0
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/_07c2a32a._.js +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/_0e9d6bf7._.js +3 -0
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/_3197d5cb._.js +3 -0
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/_4e5db14b._.js +7 -0
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/_61351ed3._.js +3 -0
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/_797dbf60._.js +3 -0
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/_8400c8bb._.js +3 -0
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/_a29296f0._.js +3 -0
- package/web/.next/{server/chunks/ssr/_e50484ec._.js → standalone/src/presentation/web/.next/server/chunks/ssr/_a2a86eed._.js} +2 -2
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/_dd1c549f._.js +3 -0
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/src_presentation_web_1a32dbcb._.js +2 -2
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/src_presentation_web_398553b0._.js +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/src_presentation_web_5c87e8e4._.js +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_f4952172.js +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/src_presentation_web_c1bc6240._.js +2 -2
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/src_presentation_web_ca99d62d._.js +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/src_presentation_web_components_features_control-center_7ac3562e._.js +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/src_presentation_web_components_features_tools_tools-page-client_tsx_3d0aa70c._.js +3 -0
- package/web/.next/standalone/src/presentation/web/.next/server/middleware-build-manifest.js +5 -5
- package/web/.next/standalone/src/presentation/web/.next/server/pages/500.html +2 -2
- package/web/.next/standalone/src/presentation/web/.next/server/server-reference-manifest.js +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/server-reference-manifest.json +61 -26
- package/web/.next/standalone/src/presentation/web/app/(dashboard)/get-graph-data.ts +2 -6
- package/web/.next/standalone/src/presentation/web/app/api/tools/[id]/install/route.ts +14 -6
- package/web/.next/standalone/src/presentation/web/app/api/tools/[id]/install/stream/route.ts +42 -0
- package/web/.next/standalone/src/presentation/web/app/build-graph-nodes.ts +14 -1
- package/web/.next/standalone/src/presentation/web/components/common/base-drawer/base-drawer.tsx +10 -8
- package/web/.next/standalone/src/presentation/web/components/common/control-center-drawer/create-drawer-client.tsx +13 -3
- package/web/.next/standalone/src/presentation/web/components/common/control-center-drawer/feature-drawer-client.tsx +6 -2
- package/web/.next/standalone/src/presentation/web/components/common/drawer-action-bar/drawer-action-bar.tsx +2 -0
- package/web/.next/standalone/src/presentation/web/components/common/feature-create-drawer/feature-create-drawer.tsx +8 -5
- package/web/.next/standalone/src/presentation/web/components/common/feature-node/feature-node.tsx +30 -24
- package/web/.next/standalone/src/presentation/web/components/common/repository-node/repository-node.tsx +33 -25
- package/web/.next/standalone/src/presentation/web/components/features/control-center/control-center-inner.tsx +25 -3
- package/web/.next/standalone/src/presentation/web/components/features/control-center/use-control-center-state.ts +184 -230
- package/web/.next/standalone/src/presentation/web/components/features/index.ts +1 -1
- package/web/.next/standalone/src/presentation/web/components/features/tools/index.ts +1 -1
- package/web/.next/standalone/src/presentation/web/components/features/tools/tool-card.tsx +52 -56
- package/web/.next/standalone/src/presentation/web/components/features/tools/tool-detail-drawer.stories.tsx +129 -0
- package/web/.next/standalone/src/presentation/web/components/features/tools/tool-detail-drawer.tsx +277 -0
- package/web/.next/standalone/src/presentation/web/components/ui/alert-dialog.tsx +7 -0
- package/web/.next/standalone/src/presentation/web/components/ui/dialog.tsx +7 -1
- package/web/.next/standalone/src/presentation/web/hooks/use-tool-install-stream.ts +58 -0
- package/web/.next/standalone/src/presentation/web/lib/layout-with-dagre.ts +93 -4
- package/web/.next/standalone/src/presentation/web/server.js +1 -1
- package/web/.next/static/chunks/0c54314c8c9c9739.js +7 -0
- package/web/.next/static/chunks/3969f00d871743f5.js +1 -0
- package/web/.next/static/chunks/5d0a6417c4e4e545.js +1 -0
- package/web/.next/static/chunks/603dfc7302d69eea.js +1 -0
- package/web/.next/static/chunks/6059a88955f582cc.js +1 -0
- package/web/.next/static/chunks/6a97d80f8c80abea.js +5 -0
- package/web/.next/static/chunks/84a181ff3270fd9f.js +1 -0
- package/web/.next/static/chunks/b1ac668fe8c3cfe7.css +2 -0
- package/web/.next/static/chunks/bc08901495944d5d.js +1 -0
- package/web/.next/static/chunks/bfa8014b2e37a6e3.js +1 -0
- package/web/.next/static/chunks/{d4ecce2ac7795bd9.js → c81a2c46730b4afb.js} +1 -1
- package/web/.next/static/chunks/{8b36e07129a1471f.js → ccdb4b72cf686304.js} +1 -1
- package/web/.next/static/chunks/edbd674102e897b4.js +1 -0
- package/web/.next/static/chunks/{412a3ac70c529c5b.js → f089dd8f35a6d79c.js} +1 -1
- package/web/.next/static/chunks/f5a543a8ccb7e8b9.js +1 -0
- package/web/.next/static/chunks/{fc07834e422b1caa.js → fe2a7112664de6d7.js} +1 -1
- package/web/.next/static/chunks/{turbopack-3a8fe0e18e69b0ab.js → turbopack-05820f781f3ffc22.js} +1 -1
- package/web/.next/trace +1 -1
- package/web/.next/trace-build +1 -1
- package/web/.next/types/link.d.ts +1 -0
- package/web/.next/types/routes.d.ts +2 -1
- package/web/.next/types/validator.ts +9 -0
- package/dist/src/presentation/web/components/features/tools/install-instructions.d.ts +0 -9
- package/dist/src/presentation/web/components/features/tools/install-instructions.d.ts.map +0 -1
- package/dist/src/presentation/web/components/features/tools/install-instructions.js +0 -19
- package/dist/src/presentation/web/components/features/tools/install-instructions.stories.d.ts +0 -12
- package/dist/src/presentation/web/components/features/tools/install-instructions.stories.d.ts.map +0 -1
- package/dist/src/presentation/web/components/features/tools/install-instructions.stories.js +0 -77
- package/web/.next/server/chunks/[root-of-the-server]__b1f03347._.js +0 -3
- package/web/.next/server/chunks/[root-of-the-server]__b1f03347._.js.map +0 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__08ba9bd3._.js +0 -4
- package/web/.next/server/chunks/ssr/[root-of-the-server]__08ba9bd3._.js.map +0 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__6bb00d90._.js +0 -3
- package/web/.next/server/chunks/ssr/[root-of-the-server]__6bb00d90._.js.map +0 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__6db85a66._.js +0 -4
- package/web/.next/server/chunks/ssr/[root-of-the-server]__6db85a66._.js.map +0 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__8c1a3d66._.js +0 -3
- package/web/.next/server/chunks/ssr/[root-of-the-server]__8fcb9132._.js.map +0 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__9d14479b._.js +0 -3
- package/web/.next/server/chunks/ssr/[root-of-the-server]__9d14479b._.js.map +0 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__d4e51258._.js +0 -3
- package/web/.next/server/chunks/ssr/[root-of-the-server]__d4e51258._.js.map +0 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__fe2a7deb._.js +0 -3
- package/web/.next/server/chunks/ssr/[root-of-the-server]__fe2a7deb._.js.map +0 -1
- package/web/.next/server/chunks/ssr/_00e6c698._.js +0 -3
- package/web/.next/server/chunks/ssr/_00e6c698._.js.map +0 -1
- package/web/.next/server/chunks/ssr/_13566ff3._.js +0 -3
- package/web/.next/server/chunks/ssr/_13566ff3._.js.map +0 -1
- package/web/.next/server/chunks/ssr/_26129e04._.js +0 -3
- package/web/.next/server/chunks/ssr/_26129e04._.js.map +0 -1
- package/web/.next/server/chunks/ssr/_34a58db8._.js +0 -3
- package/web/.next/server/chunks/ssr/_34a58db8._.js.map +0 -1
- package/web/.next/server/chunks/ssr/_37259405._.js +0 -3
- package/web/.next/server/chunks/ssr/_37259405._.js.map +0 -1
- package/web/.next/server/chunks/ssr/_85d0351b._.js +0 -3
- package/web/.next/server/chunks/ssr/_85d0351b._.js.map +0 -1
- package/web/.next/server/chunks/ssr/_cb5b3951._.js +0 -3
- package/web/.next/server/chunks/ssr/_cb5b3951._.js.map +0 -1
- package/web/.next/server/chunks/ssr/_fc3a6895._.js +0 -3
- package/web/.next/server/chunks/ssr/_fc3a6895._.js.map +0 -1
- package/web/.next/server/chunks/ssr/node_modules__pnpm_3288606c._.js +0 -7
- package/web/.next/server/chunks/ssr/node_modules__pnpm_3288606c._.js.map +0 -1
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/[root-of-the-server]__b1f03347._.js +0 -3
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__08ba9bd3._.js +0 -4
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__6bb00d90._.js +0 -3
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__6db85a66._.js +0 -4
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__8c1a3d66._.js +0 -3
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__9d14479b._.js +0 -3
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__d4e51258._.js +0 -3
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__fe2a7deb._.js +0 -3
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/_00e6c698._.js +0 -3
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/_13566ff3._.js +0 -3
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/_26129e04._.js +0 -3
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/_34a58db8._.js +0 -3
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/_37259405._.js +0 -3
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/_85d0351b._.js +0 -3
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/_cb5b3951._.js +0 -3
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/_fc3a6895._.js +0 -3
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/node_modules__pnpm_3288606c._.js +0 -7
- package/web/.next/standalone/src/presentation/web/components/features/tools/install-instructions.stories.tsx +0 -89
- package/web/.next/standalone/src/presentation/web/components/features/tools/install-instructions.tsx +0 -109
- package/web/.next/static/chunks/06b6b02bab76aee7.js +0 -1
- package/web/.next/static/chunks/06dfd668334ffb4e.js +0 -7
- package/web/.next/static/chunks/07fcc6d17357e905.js +0 -1
- package/web/.next/static/chunks/224ed5f5dbd33154.css +0 -2
- package/web/.next/static/chunks/32957ff277daec59.js +0 -1
- package/web/.next/static/chunks/3e1227e02ef8bcc6.js +0 -5
- package/web/.next/static/chunks/550bf3cb8220cbf0.js +0 -1
- package/web/.next/static/chunks/5f5c607ffae8b918.js +0 -1
- package/web/.next/static/chunks/64d73952a0291431.js +0 -1
- package/web/.next/static/chunks/c7e793951b20a67f.js +0 -1
- package/web/.next/static/chunks/e44849eb58a3335f.js +0 -1
- package/web/.next/static/chunks/ecb2130572a7fbe7.js +0 -1
- /package/web/.next/static/{7K6dTYQIJ7__PLUYLLfZV → 5-_wERRI1P-m4Tl0xR0UI}/_buildManifest.js +0 -0
- /package/web/.next/static/{7K6dTYQIJ7__PLUYLLfZV → 5-_wERRI1P-m4Tl0xR0UI}/_clientMiddlewareManifest.json +0 -0
- /package/web/.next/static/{7K6dTYQIJ7__PLUYLLfZV → 5-_wERRI1P-m4Tl0xR0UI}/_ssgManifest.js +0 -0
package/dist/src/presentation/web/components/common/feature-create-drawer/feature-create-drawer.js
CHANGED
|
@@ -114,7 +114,7 @@ export function FeatureCreateDrawer({ open, onClose, onSubmit, repositoryPath, i
|
|
|
114
114
|
setAttachments((prev) => prev.filter((f) => f.path !== path));
|
|
115
115
|
}, []);
|
|
116
116
|
const hasFeatures = features && features.length > 0;
|
|
117
|
-
return (_jsx(BaseDrawer, { open: open, onClose: attemptClose, size: "md", modal: false, "data-testid": "feature-create-drawer", header: _jsxs(_Fragment, { children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("div", { className: "h-2.5 w-2.5 shrink-0 rounded-full bg-blue-500" }), _jsx(DrawerTitle, { children: "NEW FEATURE" })] }), _jsx(DrawerDescription, { asChild: true, children: _jsx("div", { children: _jsx(Badge, { variant: "secondary", children: "Creating..." }) }) })] }), footer: _jsxs("div", { className: "flex flex-row justify-end gap-2", children: [_jsx(Button, { variant: "outline", onClick: attemptClose, disabled: isSubmitting, children: "Cancel" }), _jsx(Button, { type: "submit", form: "create-feature-form", disabled: !name.trim() || isSubmitting, children: isSubmitting ? 'Creating...' : '+ Create Feature' })] }), children: _jsx("div", { className: "overflow-y-auto p-4", children: _jsxs("form", { id: "create-feature-form", onSubmit: handleSubmit, className: "flex flex-col gap-4", children: [_jsxs("div", { className: "flex flex-col gap-1.5", children: [_jsx(Label, { htmlFor: "feature-name", className: "text-muted-foreground text-xs font-semibold tracking-wider", children: "FEATURE NAME" }), _jsx(Input, { id: "feature-name", placeholder: "e.g. GitHub OAuth Login", value: name, onChange: (e) => setName(e.target.value), required: true, disabled: isSubmitting })] }), _jsxs("div", { className: "flex flex-col gap-1.5", children: [_jsx(Label, { htmlFor: "feature-description", className: "text-muted-foreground text-xs font-semibold tracking-wider", children: "DESCRIPTION" }), _jsx(Textarea, { id: "feature-description", placeholder: "Describe what this feature does...", value: description, onChange: (e) => setDescription(e.target.value), rows: 4, disabled: isSubmitting })] }), hasFeatures ? (_jsxs("div", { className: "flex flex-col gap-1.5", children: [_jsx(Label, { htmlFor: "parent-feature", className: "text-muted-foreground text-xs font-semibold tracking-wider", children: "PARENT FEATURE" }), _jsx(ParentFeatureCombobox, { features: features, value: parentId, onChange: setParentId, disabled: isSubmitting })] })) : null, _jsxs("div", { className: "flex flex-col gap-1.5", children: [_jsx(Label, { className: "text-muted-foreground text-xs font-semibold tracking-wider", children: "APPROVE" }), _jsx(CheckboxGroup, { label: "Autonomous Mode", description: "YOLO!", parentAriaLabel: "Auto approve all", options: AUTO_APPROVE_OPTIONS, value: approvalGates, onValueChange: setApprovalGates, disabled: isSubmitting })] }), _jsxs("div", { className: "flex flex-col gap-1.5", children: [_jsx(Label, { className: "text-muted-foreground text-xs font-semibold tracking-wider", children: "GIT" }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(CheckboxGroupItem, { id: "push", label: "Push", description: "Push branch to remote after implementation.", checked: push || openPr, onCheckedChange: setPush, disabled: openPr || isSubmitting }), _jsx(CheckboxGroupItem, { id: "open-pr", label: "Create PR", description: "Open a pull request after pushing.", checked: openPr, onCheckedChange: setOpenPr, disabled: isSubmitting })] })] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsxs("div", { className: "flex items-center justify-between", children: [_jsxs(Label, { className: "text-muted-foreground text-xs font-semibold tracking-wider", children: ["ATTACHMENTS", attachments.length > 0 && (_jsxs("span", { className: "text-muted-foreground/60 ml-1.5", children: ["(", attachments.length, ")"] }))] }), _jsxs(Button, { type: "button", variant: "outline", size: "xs", onClick: handleAddFiles, disabled: isSubmitting, children: [_jsx(PlusIcon, { className: "size-3" }), "Add Files"] })] }), attachments.length > 0 && (_jsx("div", { className: "flex flex-col gap-2", children: attachments.map((file) => (_jsx(AttachmentCard, { file: file, onRemove: () => handleRemoveFile(file.path), disabled: isSubmitting }, file.path))) }))] })] }) }) }));
|
|
117
|
+
return (_jsx(BaseDrawer, { open: open, onClose: attemptClose, size: "md", modal: false, dismissOnOutsideClick: true, "data-testid": "feature-create-drawer", header: _jsxs(_Fragment, { children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("div", { className: "h-2.5 w-2.5 shrink-0 rounded-full bg-blue-500" }), _jsx(DrawerTitle, { children: "NEW FEATURE" })] }), isSubmitting ? (_jsx(DrawerDescription, { asChild: true, children: _jsx("div", { children: _jsx(Badge, { variant: "secondary", children: "Creating..." }) }) })) : null] }), footer: _jsxs("div", { className: "flex flex-row justify-end gap-2", children: [_jsx(Button, { variant: "outline", onClick: attemptClose, disabled: isSubmitting, children: "Cancel" }), _jsx(Button, { type: "submit", form: "create-feature-form", disabled: !name.trim() || isSubmitting, children: isSubmitting ? 'Creating...' : '+ Create Feature' })] }), children: _jsx("div", { className: "overflow-y-auto p-4", children: _jsxs("form", { id: "create-feature-form", onSubmit: handleSubmit, className: "flex flex-col gap-4", children: [_jsxs("div", { className: "flex flex-col gap-1.5", children: [_jsx(Label, { htmlFor: "feature-name", className: "text-muted-foreground text-xs font-semibold tracking-wider", children: "FEATURE NAME" }), _jsx(Input, { id: "feature-name", placeholder: "e.g. GitHub OAuth Login", value: name, onChange: (e) => setName(e.target.value), required: true, disabled: isSubmitting })] }), _jsxs("div", { className: "flex flex-col gap-1.5", children: [_jsx(Label, { htmlFor: "feature-description", className: "text-muted-foreground text-xs font-semibold tracking-wider", children: "DESCRIPTION" }), _jsx(Textarea, { id: "feature-description", placeholder: "Describe what this feature does...", value: description, onChange: (e) => setDescription(e.target.value), rows: 4, disabled: isSubmitting })] }), hasFeatures ? (_jsxs("div", { className: "flex flex-col gap-1.5", children: [_jsx(Label, { htmlFor: "parent-feature", className: "text-muted-foreground text-xs font-semibold tracking-wider", children: "PARENT FEATURE" }), _jsx(ParentFeatureCombobox, { features: features, value: parentId, onChange: setParentId, disabled: isSubmitting })] })) : null, _jsxs("div", { className: "flex flex-col gap-1.5", children: [_jsx(Label, { className: "text-muted-foreground text-xs font-semibold tracking-wider", children: "APPROVE" }), _jsx(CheckboxGroup, { label: "Autonomous Mode", description: "YOLO!", parentAriaLabel: "Auto approve all", options: AUTO_APPROVE_OPTIONS, value: approvalGates, onValueChange: setApprovalGates, disabled: isSubmitting })] }), _jsxs("div", { className: "flex flex-col gap-1.5", children: [_jsx(Label, { className: "text-muted-foreground text-xs font-semibold tracking-wider", children: "GIT" }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(CheckboxGroupItem, { id: "push", label: "Push", description: "Push branch to remote after implementation.", checked: push || openPr, onCheckedChange: setPush, disabled: openPr || isSubmitting }), _jsx(CheckboxGroupItem, { id: "open-pr", label: "Create PR", description: "Open a pull request after pushing.", checked: openPr, onCheckedChange: setOpenPr, disabled: isSubmitting })] })] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsxs("div", { className: "flex items-center justify-between", children: [_jsxs(Label, { className: "text-muted-foreground text-xs font-semibold tracking-wider", children: ["ATTACHMENTS", attachments.length > 0 && (_jsxs("span", { className: "text-muted-foreground/60 ml-1.5", children: ["(", attachments.length, ")"] }))] }), _jsxs(Button, { type: "button", variant: "outline", size: "xs", onClick: handleAddFiles, disabled: isSubmitting, children: [_jsx(PlusIcon, { className: "size-3" }), "Add Files"] })] }), attachments.length > 0 && (_jsx("div", { className: "flex flex-col gap-2", children: attachments.map((file) => (_jsx(AttachmentCard, { file: file, onRemove: () => handleRemoveFile(file.path), disabled: isSubmitting }, file.path))) }))] })] }) }) }));
|
|
118
118
|
}
|
|
119
119
|
function ParentFeatureCombobox({ features, value, onChange, disabled, }) {
|
|
120
120
|
const [open, setOpen] = useState(false);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"feature-node.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/feature-node/feature-node.tsx"],"names":[],"mappings":"AAsBA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAwDnE,wBAAgB,WAAW,CAAC,EAC1B,IAAI,EACJ,QAAQ,GACT,EAAE;IACD,IAAI,EAAE,eAAe,CAAC;IACtB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB,
|
|
1
|
+
{"version":3,"file":"feature-node.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/feature-node/feature-node.tsx"],"names":[],"mappings":"AAsBA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAwDnE,wBAAgB,WAAW,CAAC,EAC1B,IAAI,EACJ,QAAQ,GACT,EAAE;IACD,IAAI,EAAE,eAAe,CAAC;IACtB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB,2CAkOA"}
|
|
@@ -4,7 +4,8 @@ import { useState } from 'react';
|
|
|
4
4
|
import { Handle, Position } from '@xyflow/react';
|
|
5
5
|
import { Settings, Plus, FileText, Wrench, GitMerge, Trash2 } from 'lucide-react';
|
|
6
6
|
import { cn } from '../../../lib/utils.js';
|
|
7
|
-
import {
|
|
7
|
+
import { Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from '../../ui/dialog.js';
|
|
8
|
+
import { Button } from '../../ui/button.js';
|
|
8
9
|
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '../../ui/tooltip.js';
|
|
9
10
|
import { featureNodeStateConfig, lifecycleDisplayLabels, lifecycleRunningVerbs, } from './feature-node-state-config.js';
|
|
10
11
|
import { getAgentTypeIcon } from './agent-type-icons.js';
|
|
@@ -68,7 +69,11 @@ export function FeatureNode({ data, selected, }) {
|
|
|
68
69
|
return (_jsxs("div", { className: "group relative", children: [data.showHandles ? (_jsx(Handle, { type: "target", position: Position.Left, isConnectable: false, className: "opacity-0!" })) : null, data.onDelete && data.featureId ? (_jsxs(_Fragment, { children: [_jsx("div", { className: "absolute top-1/2 -left-10 -translate-y-1/2 opacity-0 transition-opacity group-hover:opacity-100", children: _jsx(TooltipProvider, { children: _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("button", { "aria-label": "Delete feature", "data-testid": "feature-node-delete-button", onClick: (e) => {
|
|
69
70
|
e.stopPropagation();
|
|
70
71
|
setConfirmOpen(true);
|
|
71
|
-
}, className: "bg-card text-muted-foreground hover:border-destructive hover:text-destructive flex h-7 w-7 cursor-pointer items-center justify-center rounded-full border shadow-sm transition-colors", children: _jsx(Trash2, { className: "h-3.5 w-3.5" }) }) }), _jsx(TooltipContent, { children: "Delete feature" })] }) }) }), _jsx(
|
|
72
|
+
}, className: "bg-card text-muted-foreground hover:border-destructive hover:text-destructive flex h-7 w-7 cursor-pointer items-center justify-center rounded-full border shadow-sm transition-colors", children: _jsx(Trash2, { className: "h-3.5 w-3.5" }) }) }), _jsx(TooltipContent, { children: "Delete feature" })] }) }) }), _jsx(Dialog, { open: confirmOpen, onOpenChange: setConfirmOpen, children: _jsxs(DialogContent, { className: "max-w-xs", children: [_jsxs(DialogHeader, { children: [_jsx(DialogTitle, { children: "Delete feature?" }), _jsxs(DialogDescription, { children: ["This will permanently delete ", _jsx("strong", { children: data.name }), " and all associated data including specs, branches, and progress."] })] }), _jsxs(DialogFooter, { className: "grid grid-cols-2 gap-2 sm:flex-none", children: [_jsx(DialogClose, { asChild: true, children: _jsx(Button, { variant: "outline", children: "Cancel" }) }), _jsx(Button, { variant: "destructive", onClick: (e) => {
|
|
73
|
+
e.stopPropagation();
|
|
74
|
+
setConfirmOpen(false);
|
|
75
|
+
data.onDelete?.(data.featureId);
|
|
76
|
+
}, children: "Delete" })] })] }) })] })) : null, _jsxs("div", { "data-testid": "feature-node-card", "aria-busy": data.state === 'creating' ? 'true' : undefined, className: cn('bg-card flex min-h-35 w-72 flex-col rounded-lg border p-3 shadow-sm', selected && 'ring-primary ring-2'), children: [_jsxs("div", { className: "flex items-center justify-between", children: [_jsx("span", { "data-testid": "feature-node-lifecycle-label", className: cn('text-[10px] font-semibold tracking-wider'), children: data.state === 'blocked' ? 'BLOCKED' : lifecycleDisplayLabels[data.lifecycle] }), data.onSettings ? (_jsx("button", { type: "button", "aria-label": "Settings", "data-testid": "feature-node-settings-button", onClick: (e) => {
|
|
72
77
|
e.stopPropagation();
|
|
73
78
|
data.onSettings?.();
|
|
74
79
|
}, className: "nodrag text-muted-foreground hover:text-foreground -mt-1 -mr-1 p-1", children: _jsx(Settings, { className: "h-3.5 w-3.5" }) })) : null] }), _jsx("h3", { className: "mt-1 truncate text-sm font-bold", children: data.name }), data.description ? (_jsx("p", { "data-testid": "feature-node-description", className: "text-muted-foreground mt-0.5 truncate text-xs", children: data.description })) : null, _jsx("div", { className: "mt-auto pt-2", children: data.state === 'creating' ? (_jsxs(_Fragment, { children: [_jsxs("div", { className: "mt-1.5 flex items-center gap-1.5 text-xs", children: [_jsx(Icon, { className: "h-3.5 w-3.5 shrink-0 animate-spin" }), _jsx("span", { className: "text-muted-foreground", children: getBadgeText(data) })] }), _jsx("div", { "data-testid": "feature-node-progress-bar", className: "bg-muted mt-1.5 h-1 w-full overflow-hidden rounded-full", children: _jsx("div", { className: "motion-safe:animate-indeterminate-progress bg-foreground/30 h-full w-1/3 rounded-full" }) })] })) : data.state === 'running' ? (_jsxs(_Fragment, { children: [_jsxs("div", { className: "mt-1.5 flex items-center gap-1.5 text-xs", children: [_jsx(AgentIcon, { agentType: data.agentType, className: "h-3.5 w-3.5 shrink-0" }), _jsx("span", { className: "text-muted-foreground", children: getBadgeText(data) })] }), _jsx("div", { "data-testid": "feature-node-progress-bar", className: "bg-muted mt-1.5 h-1 w-full overflow-hidden rounded-full", children: _jsx("div", { className: "animate-indeterminate-progress bg-foreground/30 h-full w-1/3 rounded-full" }) })] })) : config.showProgressBar ? (_jsxs(_Fragment, { children: [_jsx("div", { className: "text-muted-foreground flex items-center justify-end text-[10px]", children: _jsxs("span", { children: [data.progress, "%"] }) }), _jsx("div", { "data-testid": "feature-node-progress-bar", className: "bg-muted mt-1.5 h-1 w-full overflow-hidden rounded-full", children: _jsx("div", { className: cn('h-full rounded-full transition-all', config.progressClass), style: { width: `${data.progress}%` } }) })] })) : (_jsxs(_Fragment, { children: [_jsx("div", { className: "text-muted-foreground text-[10px]", children: _jsx("span", { children: data.featureId }) }), _jsxs("div", { "data-testid": "feature-node-badge", className: (() => {
|
package/dist/src/presentation/web/components/common/repository-node/repository-node.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"repository-node.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/repository-node/repository-node.tsx"],"names":[],"mappings":"AAqBA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAGnE,wBAAgB,cAAc,CAAC,EAAE,IAAI,EAAE,EAAE;IAAE,IAAI,EAAE,kBAAkB,CAAC;IAAC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CAAE,
|
|
1
|
+
{"version":3,"file":"repository-node.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/repository-node/repository-node.tsx"],"names":[],"mappings":"AAqBA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAGnE,wBAAgB,cAAc,CAAC,EAAE,IAAI,EAAE,EAAE;IAAE,IAAI,EAAE,kBAAkB,CAAC;IAAC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CAAE,2CA6O5F"}
|
|
@@ -5,7 +5,8 @@ import { Handle, Position } from '@xyflow/react';
|
|
|
5
5
|
import { Github, Plus, Code2, Terminal, FolderOpen, Trash2, Play, Square } from 'lucide-react';
|
|
6
6
|
import { cn } from '../../../lib/utils.js';
|
|
7
7
|
import { ActionButton } from '../../common/action-button/index.js';
|
|
8
|
-
import {
|
|
8
|
+
import { Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from '../../ui/dialog.js';
|
|
9
|
+
import { Button } from '../../ui/button.js';
|
|
9
10
|
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '../../ui/tooltip.js';
|
|
10
11
|
import { DeploymentStatusBadge } from '../../common/deployment-status-badge/index.js';
|
|
11
12
|
import { useDeployAction } from '../../../hooks/use-deploy-action.js';
|
|
@@ -25,7 +26,10 @@ export function RepositoryNode({ data }) {
|
|
|
25
26
|
return (_jsxs("div", { className: "group relative", children: [data.showHandles ? (_jsx(Handle, { type: "target", position: Position.Left, isConnectable: false, className: "opacity-0!" })) : null, data.onDelete && data.id ? (_jsxs(_Fragment, { children: [_jsx("div", { className: "absolute top-1/2 -left-10 -translate-y-1/2 opacity-0 transition-opacity group-hover:opacity-100", children: _jsx(TooltipProvider, { children: _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("button", { "aria-label": "Remove repository", "data-testid": "repository-node-delete-button", onClick: (e) => {
|
|
26
27
|
e.stopPropagation();
|
|
27
28
|
setConfirmOpen(true);
|
|
28
|
-
}, className: "bg-card text-muted-foreground hover:border-destructive hover:text-destructive flex h-7 w-7 cursor-pointer items-center justify-center rounded-full border shadow-sm transition-colors", children: _jsx(Trash2, { className: "h-3.5 w-3.5" }) }) }), _jsx(TooltipContent, { children: "Remove repository" })] }) }) }), _jsx(
|
|
29
|
+
}, className: "bg-card text-muted-foreground hover:border-destructive hover:text-destructive flex h-7 w-7 cursor-pointer items-center justify-center rounded-full border shadow-sm transition-colors", children: _jsx(Trash2, { className: "h-3.5 w-3.5" }) }) }), _jsx(TooltipContent, { children: "Remove repository" })] }) }) }), _jsx(Dialog, { open: confirmOpen, onOpenChange: setConfirmOpen, children: _jsxs(DialogContent, { className: "max-w-xs", children: [_jsxs(DialogHeader, { children: [_jsx(DialogTitle, { children: "Remove repository?" }), _jsxs(DialogDescription, { children: ["This will remove ", _jsx("strong", { children: data.name }), " and all its features from your workspace. The repository files on disk won't be affected."] })] }), _jsxs(DialogFooter, { className: "grid grid-cols-2 gap-2 sm:flex-none", children: [_jsx(DialogClose, { asChild: true, children: _jsx(Button, { variant: "outline", children: "Cancel" }) }), _jsx(Button, { variant: "destructive", onClick: () => {
|
|
30
|
+
setConfirmOpen(false);
|
|
31
|
+
data.onDelete?.(data.id);
|
|
32
|
+
}, children: "Remove" })] })] }) })] })) : null, _jsxs("div", { role: "button", tabIndex: 0, "data-testid": "repository-node-card", "data-repo-name": data.name, onClick: (e) => {
|
|
29
33
|
e.stopPropagation();
|
|
30
34
|
data.onClick?.();
|
|
31
35
|
}, onKeyDown: (e) => {
|
package/dist/src/presentation/web/components/features/control-center/control-center-inner.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"control-center-inner.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/control-center/control-center-inner.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAE1C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uCAAuC,CAAC;AAc5E,UAAU,uBAAuB;IAC/B,YAAY,EAAE,cAAc,EAAE,CAAC;IAC/B,YAAY,EAAE,IAAI,EAAE,CAAC;CACtB;AAED,wBAAgB,kBAAkB,CAAC,EAAE,YAAY,EAAE,YAAY,EAAE,EAAE,uBAAuB,
|
|
1
|
+
{"version":3,"file":"control-center-inner.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/control-center/control-center-inner.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAE1C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uCAAuC,CAAC;AAc5E,UAAU,uBAAuB;IAC/B,YAAY,EAAE,cAAc,EAAE,CAAC;IAC/B,YAAY,EAAE,IAAI,EAAE,CAAC;CACtB;AAED,wBAAgB,kBAAkB,CAAC,EAAE,YAAY,EAAE,YAAY,EAAE,EAAE,uBAAuB,2CA4NzF"}
|
package/dist/src/presentation/web/components/features/control-center/control-center-inner.js
CHANGED
|
@@ -15,8 +15,8 @@ export function ControlCenterInner({ initialNodes, initialEdges }) {
|
|
|
15
15
|
const pathname = usePathname();
|
|
16
16
|
const selectedFeatureId = useSelectedFeatureId();
|
|
17
17
|
const clickSound = useSoundAction('click');
|
|
18
|
-
const { guardedNavigate
|
|
19
|
-
const { nodes, edges, onNodesChange, handleConnect, handleAddRepository, handleDeleteFeature, handleDeleteRepository, createFeatureNode, } = useControlCenterState(initialNodes, initialEdges
|
|
18
|
+
const { guardedNavigate } = useDrawerCloseGuard();
|
|
19
|
+
const { nodes, edges, onNodesChange, handleConnect, handleAddRepository, handleDeleteFeature, handleDeleteRepository, createFeatureNode, } = useControlCenterState(initialNodes, initialEdges);
|
|
20
20
|
// Publish sidebar features to context whenever feature node data changes
|
|
21
21
|
const { setFeatures: setSidebarFeatures } = useSidebarFeaturesContext();
|
|
22
22
|
const sidebarKey = useMemo(() => {
|
|
@@ -116,6 +116,18 @@ export function ControlCenterInner({ initialNodes, initialEdges }) {
|
|
|
116
116
|
useEffect(() => {
|
|
117
117
|
const handler = (e) => {
|
|
118
118
|
const detail = e.detail;
|
|
119
|
+
// When a parentId is provided, connect to the parent feature node
|
|
120
|
+
// via a dependency edge instead of the repo node.
|
|
121
|
+
if (detail.parentId) {
|
|
122
|
+
const parentNodeId = `feat-${detail.parentId}`;
|
|
123
|
+
createFeatureNode(parentNodeId, {
|
|
124
|
+
state: 'creating',
|
|
125
|
+
name: detail.name,
|
|
126
|
+
description: detail.description,
|
|
127
|
+
repositoryPath: detail.repositoryPath,
|
|
128
|
+
}, 'dependencyEdge');
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
119
131
|
// Find the repo node to connect to
|
|
120
132
|
const repoNode = nodes.find((n) => n.type === 'repositoryNode' &&
|
|
121
133
|
n.data.repositoryPath === detail.repositoryPath);
|
package/dist/src/presentation/web/components/features/control-center/use-control-center-state.d.ts
CHANGED
|
@@ -9,11 +9,9 @@ export interface ControlCenterState {
|
|
|
9
9
|
handleConnect: (connection: Connection) => void;
|
|
10
10
|
handleAddRepository: (path: string) => void;
|
|
11
11
|
handleLayout: (direction: LayoutDirection) => void;
|
|
12
|
-
handleDeleteFeature: (featureId: string) =>
|
|
12
|
+
handleDeleteFeature: (featureId: string) => void;
|
|
13
13
|
handleDeleteRepository: (repositoryId: string) => Promise<void>;
|
|
14
|
-
createFeatureNode: (sourceNodeId: string | null, dataOverride?: Partial<FeatureNodeData
|
|
14
|
+
createFeatureNode: (sourceNodeId: string | null, dataOverride?: Partial<FeatureNodeData>, edgeType?: string) => string;
|
|
15
15
|
}
|
|
16
|
-
export declare function useControlCenterState(initialNodes: CanvasNodeType[], initialEdges: Edge[]
|
|
17
|
-
/** When true, background router.refresh() calls (polling / SSE debounce) are suppressed. */
|
|
18
|
-
isRefreshBlocked?: () => boolean): ControlCenterState;
|
|
16
|
+
export declare function useControlCenterState(initialNodes: CanvasNodeType[], initialEdges: Edge[]): ControlCenterState;
|
|
19
17
|
//# sourceMappingURL=use-control-center-state.d.ts.map
|
|
@@ -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":"AAMA,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,cAAc,EAAE,MAAM,uCAAuC,CAAC;AAC5E,OAAO,
|
|
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":"AAMA,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,cAAc,EAAE,MAAM,uCAAuC,CAAC;AAC5E,OAAO,EAGL,KAAK,eAAe,EACrB,MAAM,yBAAyB,CAAC;AAWjC,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,IAAI,CAAC;IAC5C,YAAY,EAAE,CAAC,SAAS,EAAE,eAAe,KAAK,IAAI,CAAC;IACnD,mBAAmB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IACjD,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;CACb;AAID,wBAAgB,qBAAqB,CACnC,YAAY,EAAE,cAAc,EAAE,EAC9B,YAAY,EAAE,IAAI,EAAE,GACnB,kBAAkB,CA+epB"}
|
package/dist/src/presentation/web/components/features/control-center/use-control-center-state.js
CHANGED
|
@@ -3,7 +3,7 @@ import { useState, useCallback, useEffect, useRef } from 'react';
|
|
|
3
3
|
import { useRouter } from 'next/navigation';
|
|
4
4
|
import { toast } from 'sonner';
|
|
5
5
|
import { applyNodeChanges } from '@xyflow/react';
|
|
6
|
-
import { layoutWithDagre } from '../../../lib/layout-with-dagre.js';
|
|
6
|
+
import { layoutWithDagre, CANVAS_LAYOUT_DEFAULTS, } from '../../../lib/layout-with-dagre.js';
|
|
7
7
|
import { deleteFeature } from '../../../app/actions/delete-feature.js';
|
|
8
8
|
import { addRepository } from '../../../app/actions/add-repository.js';
|
|
9
9
|
import { deleteRepository } from '../../../app/actions/delete-repository.js';
|
|
@@ -11,9 +11,7 @@ import { useAgentEventsContext } from '../../../hooks/agent-events-provider.js';
|
|
|
11
11
|
import { useSoundAction } from '../../../hooks/use-sound-action.js';
|
|
12
12
|
import { mapEventTypeToState, mapPhaseNameToLifecycle, } from '../../common/feature-node/derive-feature-state.js';
|
|
13
13
|
let nextFeatureId = 0;
|
|
14
|
-
export function useControlCenterState(initialNodes, initialEdges
|
|
15
|
-
/** When true, background router.refresh() calls (polling / SSE debounce) are suppressed. */
|
|
16
|
-
isRefreshBlocked) {
|
|
14
|
+
export function useControlCenterState(initialNodes, initialEdges) {
|
|
17
15
|
const router = useRouter();
|
|
18
16
|
const [nodes, setNodes] = useState(initialNodes);
|
|
19
17
|
// eslint-disable-next-line react/hook-use-state -- raw setter renamed; public setEdges wrapper keeps edgesRef in sync
|
|
@@ -30,7 +28,7 @@ isRefreshBlocked) {
|
|
|
30
28
|
}, []);
|
|
31
29
|
const deleteSound = useSoundAction('delete');
|
|
32
30
|
const createSound = useSoundAction('create');
|
|
33
|
-
// Sync server props into local state when
|
|
31
|
+
// Sync server props into local state when parent re-renders with new data
|
|
34
32
|
const initialNodeKey = initialNodes
|
|
35
33
|
.map((n) => n.id)
|
|
36
34
|
.sort()
|
|
@@ -61,8 +59,9 @@ isRefreshBlocked) {
|
|
|
61
59
|
const creatingNodes = currentNodes.filter((n) => n.type === 'featureNode' &&
|
|
62
60
|
n.data.state === 'creating' &&
|
|
63
61
|
!serverIds.has(n.id));
|
|
64
|
-
// Merge server nodes with client positions
|
|
65
|
-
|
|
62
|
+
// Merge server nodes with client positions, tracking if relayout is needed
|
|
63
|
+
let needsRelayout = false;
|
|
64
|
+
const merged = initialNodes.map((serverNode) => {
|
|
66
65
|
// Node already exists on canvas — keep its position, update data
|
|
67
66
|
const existing = currentById.get(serverNode.id);
|
|
68
67
|
if (existing) {
|
|
@@ -73,17 +72,28 @@ isRefreshBlocked) {
|
|
|
73
72
|
const donor = creatingNodes.shift();
|
|
74
73
|
return { ...serverNode, position: donor.position };
|
|
75
74
|
}
|
|
76
|
-
// Truly new node with no optimistic counterpart —
|
|
75
|
+
// Truly new node with no optimistic counterpart — needs relayout
|
|
76
|
+
needsRelayout = true;
|
|
77
77
|
return serverNode;
|
|
78
78
|
});
|
|
79
|
+
// Also check if non-creating nodes were removed (graph got smaller)
|
|
80
|
+
if (!needsRelayout) {
|
|
81
|
+
needsRelayout = currentNodes.some((cn) => !serverIds.has(cn.id) &&
|
|
82
|
+
!(cn.type === 'featureNode' && cn.data.state === 'creating'));
|
|
83
|
+
}
|
|
84
|
+
if (needsRelayout) {
|
|
85
|
+
const layoutResult = layoutWithDagre(merged, initialEdges, CANVAS_LAYOUT_DEFAULTS);
|
|
86
|
+
setEdges(layoutResult.edges);
|
|
87
|
+
return layoutResult.nodes;
|
|
88
|
+
}
|
|
89
|
+
return merged;
|
|
79
90
|
});
|
|
80
|
-
}, [initialNodeKey, initialNodes]);
|
|
91
|
+
}, [initialNodeKey, initialNodes, initialEdges, setEdges]);
|
|
81
92
|
useEffect(() => {
|
|
82
93
|
setEdges(initialEdges);
|
|
83
94
|
}, [initialEdgeKey, initialEdges, setEdges]);
|
|
84
|
-
// Fallback notifications from server-
|
|
85
|
-
// Fires only when SSE didn't already deliver the matching event for a feature
|
|
86
|
-
// e.g. when the SSE connection was down or the event was seeded into the cache.
|
|
95
|
+
// Fallback notifications from server-prop state transitions.
|
|
96
|
+
// Fires only when SSE didn't already deliver the matching event for a feature.
|
|
87
97
|
const { events } = useAgentEventsContext();
|
|
88
98
|
useEffect(() => {
|
|
89
99
|
const prevStates = prevFeatureStatesRef.current;
|
|
@@ -118,14 +128,10 @@ isRefreshBlocked) {
|
|
|
118
128
|
prevStates.set(node.id, data.state);
|
|
119
129
|
}
|
|
120
130
|
}, [initialDataKey, initialNodes, events, router]);
|
|
121
|
-
// Targeted optimistic updates from SSE agent events
|
|
131
|
+
// Targeted optimistic updates from SSE agent events.
|
|
122
132
|
// Uses `events` array (not `lastEvent`) so that React batching cannot silently
|
|
123
133
|
// drop events when multiple SSE messages arrive in the same tick.
|
|
124
134
|
const processedEventCountRef = useRef(0);
|
|
125
|
-
const reconcileTimerRef = useRef(undefined);
|
|
126
|
-
useEffect(() => {
|
|
127
|
-
return () => clearTimeout(reconcileTimerRef.current);
|
|
128
|
-
}, []);
|
|
129
135
|
useEffect(() => {
|
|
130
136
|
if (events.length <= processedEventCountRef.current)
|
|
131
137
|
return;
|
|
@@ -151,31 +157,7 @@ isRefreshBlocked) {
|
|
|
151
157
|
};
|
|
152
158
|
}));
|
|
153
159
|
}
|
|
154
|
-
|
|
155
|
-
clearTimeout(reconcileTimerRef.current);
|
|
156
|
-
reconcileTimerRef.current = setTimeout(() => {
|
|
157
|
-
if (!isRefreshBlocked?.())
|
|
158
|
-
router.refresh();
|
|
159
|
-
}, 3000);
|
|
160
|
-
}, [events, router, isRefreshBlocked]);
|
|
161
|
-
// Periodic polling fallback: refresh server data every 5s when any feature
|
|
162
|
-
// is in an active state (running/action-required). This ensures the UI stays
|
|
163
|
-
// current even if the SSE connection drops — belt-and-suspenders alongside SSE.
|
|
164
|
-
useEffect(() => {
|
|
165
|
-
const hasActiveFeature = nodes.some((n) => {
|
|
166
|
-
if (n.type !== 'featureNode')
|
|
167
|
-
return false;
|
|
168
|
-
const data = n.data;
|
|
169
|
-
return (data.state === 'running' || data.state === 'action-required' || data.state === 'creating');
|
|
170
|
-
});
|
|
171
|
-
if (!hasActiveFeature)
|
|
172
|
-
return;
|
|
173
|
-
const interval = setInterval(() => {
|
|
174
|
-
if (!isRefreshBlocked?.())
|
|
175
|
-
router.refresh();
|
|
176
|
-
}, 5_000);
|
|
177
|
-
return () => clearInterval(interval);
|
|
178
|
-
}, [nodes, router, isRefreshBlocked]);
|
|
160
|
+
}, [events]);
|
|
179
161
|
const onNodesChange = useCallback((changes) => {
|
|
180
162
|
setNodes((ns) => applyNodeChanges(changes, ns));
|
|
181
163
|
}, []);
|
|
@@ -220,202 +202,155 @@ isRefreshBlocked) {
|
|
|
220
202
|
branch: dataOverride?.branch ?? '',
|
|
221
203
|
};
|
|
222
204
|
setNodes((currentNodes) => {
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
:
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
// Place below the bottom-most sibling, matching X
|
|
232
|
-
const sortedYs = siblings.map((n) => n.position.y).sort((a, b) => a - b);
|
|
233
|
-
const maxY = sortedYs[sortedYs.length - 1];
|
|
234
|
-
// Derive gap from existing spacing between siblings, or use default
|
|
235
|
-
const gap = sortedYs.length > 1 ? sortedYs[1] - sortedYs[0] : 160;
|
|
236
|
-
position = { x: siblings[0].position.x, y: maxY + gap };
|
|
237
|
-
}
|
|
238
|
-
else if (sourceNodeId) {
|
|
239
|
-
// First child — position to the right of parent
|
|
240
|
-
const parent = currentNodes.find((n) => n.id === sourceNodeId);
|
|
241
|
-
// Parent width (288) + 200px gap matching dagre ranksep
|
|
242
|
-
const xOffset = 488;
|
|
243
|
-
position = parent
|
|
244
|
-
? { x: parent.position.x + xOffset, y: parent.position.y }
|
|
245
|
-
: { x: 400, y: 200 };
|
|
246
|
-
}
|
|
247
|
-
else {
|
|
248
|
-
// Standalone feature — place below all existing nodes
|
|
249
|
-
const maxY = currentNodes.length > 0 ? Math.max(...currentNodes.map((n) => n.position.y)) : 0;
|
|
250
|
-
position = { x: 400, y: currentNodes.length > 0 ? maxY + 160 : 200 };
|
|
251
|
-
}
|
|
252
|
-
// The new node's bottom edge (featureNode height = 140)
|
|
253
|
-
const newBottom = position.y + 140;
|
|
254
|
-
// Find the old group bottom before adding the new node
|
|
255
|
-
const groupNodeIds = new Set([sourceNodeId, ...siblingIds]);
|
|
256
|
-
const oldGroupBottom = currentNodes
|
|
257
|
-
.filter((n) => groupNodeIds.has(n.id))
|
|
258
|
-
.reduce((max, n) => {
|
|
259
|
-
const h = n.type === 'featureNode' ? 140 : 50;
|
|
260
|
-
return Math.max(max, n.position.y + h);
|
|
261
|
-
}, 0);
|
|
262
|
-
// Shift amount: how much the group grew past its old bottom
|
|
263
|
-
const shift = Math.max(0, newBottom - oldGroupBottom);
|
|
264
|
-
// Push down all nodes that are below the old group bottom
|
|
265
|
-
const shifted = shift > 0
|
|
266
|
-
? currentNodes.map((n) => {
|
|
267
|
-
if (groupNodeIds.has(n.id) || siblingIds.has(n.id))
|
|
268
|
-
return n;
|
|
269
|
-
if (n.position.y >= oldGroupBottom) {
|
|
270
|
-
return { ...n, position: { ...n.position, y: n.position.y + shift } };
|
|
271
|
-
}
|
|
272
|
-
return n;
|
|
273
|
-
})
|
|
274
|
-
: currentNodes;
|
|
275
|
-
// Re-center the parent node vertically to its children
|
|
276
|
-
const recentered = sourceNodeId
|
|
277
|
-
? shifted.map((n) => {
|
|
278
|
-
if (n.id !== sourceNodeId)
|
|
279
|
-
return n;
|
|
280
|
-
const allChildYs = [...siblings.map((s) => s.position.y), position.y];
|
|
281
|
-
const groupCenter = (Math.min(...allChildYs) + Math.max(...allChildYs) + 140) / 2;
|
|
282
|
-
const parentHeight = n.type === 'featureNode' ? 140 : 50;
|
|
283
|
-
return {
|
|
284
|
-
...n,
|
|
285
|
-
position: { ...n.position, y: groupCenter - parentHeight / 2 },
|
|
286
|
-
};
|
|
287
|
-
})
|
|
288
|
-
: shifted;
|
|
289
|
-
return [
|
|
290
|
-
...recentered,
|
|
291
|
-
{
|
|
292
|
-
id,
|
|
293
|
-
type: 'featureNode',
|
|
294
|
-
position,
|
|
295
|
-
data: newFeatureData,
|
|
296
|
-
},
|
|
297
|
-
];
|
|
298
|
-
});
|
|
299
|
-
if (sourceNodeId) {
|
|
300
|
-
setEdges((currentEdges) => [
|
|
301
|
-
...currentEdges,
|
|
302
|
-
{
|
|
205
|
+
const newNode = {
|
|
206
|
+
id,
|
|
207
|
+
type: 'featureNode',
|
|
208
|
+
position: { x: 0, y: 0 },
|
|
209
|
+
data: newFeatureData,
|
|
210
|
+
};
|
|
211
|
+
const newEdge = sourceNodeId
|
|
212
|
+
? {
|
|
303
213
|
id: edgeType === 'dependencyEdge'
|
|
304
214
|
? `dep-${sourceNodeId}-${id}`
|
|
305
215
|
: `edge-${sourceNodeId}-${id}`,
|
|
306
216
|
source: sourceNodeId,
|
|
307
217
|
target: id,
|
|
308
218
|
...(edgeType ? { type: edgeType } : { style: { strokeDasharray: '5 5' } }),
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
|
|
219
|
+
}
|
|
220
|
+
: null;
|
|
221
|
+
const allEdges = newEdge
|
|
222
|
+
? [...edgesRef.current.filter((e) => e.id !== newEdge.id), newEdge]
|
|
223
|
+
: edgesRef.current;
|
|
224
|
+
// Insert the new node after the last sibling connected to the same source,
|
|
225
|
+
// so dagre's input-order preservation keeps repo groups together.
|
|
226
|
+
let insertIndex = currentNodes.length;
|
|
227
|
+
if (sourceNodeId) {
|
|
228
|
+
const siblingIds = new Set(allEdges.filter((e) => e.source === sourceNodeId).map((e) => e.target));
|
|
229
|
+
for (let i = currentNodes.length - 1; i >= 0; i--) {
|
|
230
|
+
if (siblingIds.has(currentNodes[i].id)) {
|
|
231
|
+
insertIndex = i + 1;
|
|
232
|
+
break;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
const allNodes = [
|
|
237
|
+
...currentNodes.slice(0, insertIndex),
|
|
238
|
+
newNode,
|
|
239
|
+
...currentNodes.slice(insertIndex),
|
|
240
|
+
];
|
|
241
|
+
// Run dagre layout on the full graph so the new node is positioned consistently
|
|
242
|
+
const layoutResult = layoutWithDagre(allNodes, allEdges, CANVAS_LAYOUT_DEFAULTS);
|
|
243
|
+
setEdges(layoutResult.edges);
|
|
244
|
+
return layoutResult.nodes;
|
|
245
|
+
});
|
|
312
246
|
return id;
|
|
313
247
|
}, [setEdges]);
|
|
314
|
-
const handleDeleteFeature = useCallback(
|
|
315
|
-
|
|
316
|
-
|
|
248
|
+
const handleDeleteFeature = useCallback((featureId) => {
|
|
249
|
+
const nodeId = `feat-${featureId}`;
|
|
250
|
+
// Snapshot current state for rollback
|
|
251
|
+
const prevNodes = nodes;
|
|
252
|
+
const prevEdges = edgesRef.current;
|
|
253
|
+
// Optimistic removal — update UI immediately
|
|
254
|
+
setNodes((currentNodes) => {
|
|
255
|
+
const remainingNodes = currentNodes.filter((n) => n.id !== nodeId);
|
|
256
|
+
const remainingEdges = edgesRef.current.filter((e) => e.source !== nodeId && e.target !== nodeId);
|
|
257
|
+
const layoutResult = layoutWithDagre(remainingNodes, remainingEdges, CANVAS_LAYOUT_DEFAULTS);
|
|
258
|
+
setEdges(layoutResult.edges);
|
|
259
|
+
return layoutResult.nodes;
|
|
260
|
+
});
|
|
261
|
+
deleteSound.play();
|
|
262
|
+
toast.success('Feature deleted successfully');
|
|
263
|
+
router.push('/');
|
|
264
|
+
// Persist in background — rollback on failure
|
|
265
|
+
deleteFeature(featureId)
|
|
266
|
+
.then((result) => {
|
|
317
267
|
if (result.error) {
|
|
268
|
+
setNodes(prevNodes);
|
|
269
|
+
setEdges(prevEdges);
|
|
318
270
|
toast.error(result.error);
|
|
319
|
-
return;
|
|
320
271
|
}
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
direction: 'LR',
|
|
326
|
-
ranksep: 200,
|
|
327
|
-
nodesep: 60,
|
|
328
|
-
});
|
|
329
|
-
setEdges(layoutResult.edges);
|
|
330
|
-
return layoutResult.nodes;
|
|
331
|
-
});
|
|
332
|
-
deleteSound.play();
|
|
333
|
-
toast.success('Feature deleted successfully');
|
|
334
|
-
router.refresh();
|
|
335
|
-
}
|
|
336
|
-
catch {
|
|
272
|
+
})
|
|
273
|
+
.catch(() => {
|
|
274
|
+
setNodes(prevNodes);
|
|
275
|
+
setEdges(prevEdges);
|
|
337
276
|
toast.error('Failed to delete feature');
|
|
338
|
-
}
|
|
339
|
-
}, [
|
|
277
|
+
});
|
|
278
|
+
}, [nodes, router, deleteSound, setEdges]);
|
|
340
279
|
const handleDeleteRepository = useCallback(async (repositoryId) => {
|
|
341
280
|
const repoNodeId = `repo-${repositoryId}`;
|
|
342
|
-
//
|
|
343
|
-
|
|
344
|
-
|
|
281
|
+
// Snapshot for rollback
|
|
282
|
+
const prevNodes = nodes;
|
|
283
|
+
const prevEdges = edgesRef.current;
|
|
284
|
+
// Optimistic: remove repo node, its child feature nodes, and all related edges
|
|
285
|
+
setNodes((currentNodes) => {
|
|
286
|
+
// Find feature node IDs connected to this repo via edges
|
|
287
|
+
const childFeatureIds = new Set(edgesRef.current.filter((e) => e.source === repoNodeId).map((e) => e.target));
|
|
288
|
+
const remainingNodes = currentNodes.filter((n) => n.id !== repoNodeId && !childFeatureIds.has(n.id));
|
|
289
|
+
const remainingEdges = edgesRef.current.filter((e) => e.source !== repoNodeId &&
|
|
290
|
+
e.target !== repoNodeId &&
|
|
291
|
+
!childFeatureIds.has(e.source) &&
|
|
292
|
+
!childFeatureIds.has(e.target));
|
|
293
|
+
const layoutResult = layoutWithDagre(remainingNodes, remainingEdges, CANVAS_LAYOUT_DEFAULTS);
|
|
294
|
+
setEdges(layoutResult.edges);
|
|
295
|
+
return layoutResult.nodes;
|
|
296
|
+
});
|
|
345
297
|
try {
|
|
346
298
|
const result = await deleteRepository(repositoryId);
|
|
347
299
|
if (!result.success) {
|
|
348
300
|
toast.error(result.error ?? 'Failed to remove repository');
|
|
349
|
-
|
|
301
|
+
setNodes(prevNodes);
|
|
302
|
+
setEdges(prevEdges);
|
|
350
303
|
return;
|
|
351
304
|
}
|
|
352
305
|
deleteSound.play();
|
|
353
306
|
toast.success('Repository removed');
|
|
354
|
-
router.refresh();
|
|
355
307
|
}
|
|
356
308
|
catch {
|
|
357
309
|
toast.error('Failed to remove repository');
|
|
358
|
-
|
|
310
|
+
setNodes(prevNodes);
|
|
311
|
+
setEdges(prevEdges);
|
|
359
312
|
}
|
|
360
|
-
}, [
|
|
313
|
+
}, [nodes, deleteSound, setEdges]);
|
|
361
314
|
const handleLayout = useCallback((direction) => {
|
|
362
315
|
setNodes((currentNodes) => {
|
|
363
|
-
const
|
|
364
|
-
|
|
316
|
+
const result = layoutWithDagre(currentNodes, edgesRef.current, {
|
|
317
|
+
...CANVAS_LAYOUT_DEFAULTS,
|
|
365
318
|
direction,
|
|
366
|
-
ranksep: 60,
|
|
367
|
-
nodesep: 20,
|
|
368
319
|
});
|
|
369
320
|
setEdges(result.edges);
|
|
370
321
|
return result.nodes;
|
|
371
322
|
});
|
|
372
|
-
}, [
|
|
323
|
+
}, [setEdges]);
|
|
373
324
|
const handleAddRepository = useCallback((path) => {
|
|
374
325
|
const tempId = `repo-temp-${Date.now()}`;
|
|
375
326
|
const repoName = path
|
|
376
327
|
.replace(/[\\/]+$/, '')
|
|
377
328
|
.split(/[\\/]/)
|
|
378
329
|
.pop() ?? path;
|
|
379
|
-
// Optimistic UI: add node immediately
|
|
380
|
-
let savedAddRepoY = 0;
|
|
330
|
+
// Optimistic UI: add node and re-layout immediately
|
|
381
331
|
setNodes((currentNodes) => {
|
|
382
|
-
const repoNodes = currentNodes.filter((n) => n.type === 'repositoryNode');
|
|
383
|
-
const addRepoNode = currentNodes.find((n) => n.type === 'addRepositoryNode');
|
|
384
|
-
// Save addRepoNode's original Y for rollback on error
|
|
385
|
-
if (addRepoNode)
|
|
386
|
-
savedAddRepoY = addRepoNode.position.y;
|
|
387
|
-
// Place in the repo column, at the addRepoNode's current position
|
|
388
|
-
const repoX = repoNodes[0]?.position.x ?? addRepoNode?.position.x ?? 50;
|
|
389
|
-
const repoHeight = 50; // repositoryNode height
|
|
390
|
-
const gap = 15; // match dagre nodesep
|
|
391
|
-
const position = {
|
|
392
|
-
x: repoX,
|
|
393
|
-
y: addRepoNode ? addRepoNode.position.y : 0,
|
|
394
|
-
};
|
|
395
332
|
const newNode = {
|
|
396
333
|
id: tempId,
|
|
397
334
|
type: 'repositoryNode',
|
|
398
|
-
position,
|
|
335
|
+
position: { x: 0, y: 0 },
|
|
399
336
|
data: { name: repoName, repositoryPath: path, id: tempId },
|
|
400
337
|
};
|
|
401
|
-
|
|
402
|
-
const
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
return currentNodes
|
|
406
|
-
.map((n) => n.type === 'addRepositoryNode' ? { ...n, position: { ...n.position, y: addRepoY } } : n)
|
|
407
|
-
.concat(newNode);
|
|
338
|
+
const allNodes = [...currentNodes, newNode];
|
|
339
|
+
const layoutResult = layoutWithDagre(allNodes, edgesRef.current, CANVAS_LAYOUT_DEFAULTS);
|
|
340
|
+
setEdges(layoutResult.edges);
|
|
341
|
+
return layoutResult.nodes;
|
|
408
342
|
});
|
|
409
343
|
// Persist via server action
|
|
410
344
|
addRepository({ path, name: repoName })
|
|
411
345
|
.then((result) => {
|
|
412
346
|
if (result.error) {
|
|
413
|
-
// Rollback optimistic node and
|
|
414
|
-
setNodes((prev) =>
|
|
415
|
-
.filter((n) => n.id !== tempId)
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
347
|
+
// Rollback optimistic node and re-layout
|
|
348
|
+
setNodes((prev) => {
|
|
349
|
+
const remaining = prev.filter((n) => n.id !== tempId);
|
|
350
|
+
const layoutResult = layoutWithDagre(remaining, edgesRef.current, CANVAS_LAYOUT_DEFAULTS);
|
|
351
|
+
setEdges(layoutResult.edges);
|
|
352
|
+
return layoutResult.nodes;
|
|
353
|
+
});
|
|
419
354
|
toast.error(result.error);
|
|
420
355
|
return;
|
|
421
356
|
}
|
|
@@ -436,18 +371,18 @@ isRefreshBlocked) {
|
|
|
436
371
|
id: e.id.replace(tempId, realId),
|
|
437
372
|
})));
|
|
438
373
|
createSound.play();
|
|
439
|
-
router.refresh();
|
|
440
374
|
})
|
|
441
375
|
.catch(() => {
|
|
442
|
-
// Rollback optimistic node and
|
|
443
|
-
setNodes((prev) =>
|
|
444
|
-
.filter((n) => n.id !== tempId)
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
376
|
+
// Rollback optimistic node and re-layout
|
|
377
|
+
setNodes((prev) => {
|
|
378
|
+
const remaining = prev.filter((n) => n.id !== tempId);
|
|
379
|
+
const layoutResult = layoutWithDagre(remaining, edgesRef.current, CANVAS_LAYOUT_DEFAULTS);
|
|
380
|
+
setEdges(layoutResult.edges);
|
|
381
|
+
return layoutResult.nodes;
|
|
382
|
+
});
|
|
448
383
|
toast.error('Failed to add repository');
|
|
449
384
|
});
|
|
450
|
-
}, [
|
|
385
|
+
}, [createSound, setEdges]);
|
|
451
386
|
return {
|
|
452
387
|
nodes,
|
|
453
388
|
edges,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { FeaturesCanvas, type FeaturesCanvasProps } from './features-canvas/index.js';
|
|
2
2
|
export { ToolsPageClient, type ToolsPageClientProps } from './tools/index.js';
|
|
3
3
|
export { ToolCard, type ToolCardProps } from './tools/index.js';
|
|
4
|
-
export {
|
|
4
|
+
export { ToolDetailDrawer, type ToolDetailDrawerProps } from './tools/index.js';
|
|
5
5
|
//# sourceMappingURL=index.d.ts.map
|