@shepai/cli 1.72.8 → 1.72.9-pr220.99e5e13
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/ports/output/agents/feature-agent-process.interface.d.ts +2 -1
- package/dist/packages/core/src/application/ports/output/agents/feature-agent-process.interface.d.ts.map +1 -1
- package/dist/packages/core/src/application/use-cases/agents/approve-agent-run.use-case.d.ts.map +1 -1
- package/dist/packages/core/src/application/use-cases/agents/approve-agent-run.use-case.js +1 -0
- package/dist/packages/core/src/application/use-cases/features/create/create-feature.use-case.d.ts +20 -1
- package/dist/packages/core/src/application/use-cases/features/create/create-feature.use-case.d.ts.map +1 -1
- package/dist/packages/core/src/application/use-cases/features/create/create-feature.use-case.js +68 -41
- package/dist/packages/core/src/application/use-cases/features/create/types.d.ts +10 -0
- package/dist/packages/core/src/application/use-cases/features/create/types.d.ts.map +1 -1
- package/dist/packages/core/src/application/use-cases/features/resume-feature.use-case.d.ts.map +1 -1
- package/dist/packages/core/src/application/use-cases/features/resume-feature.use-case.js +1 -0
- package/dist/packages/core/src/domain/factories/settings-defaults.factory.js +1 -1
- package/dist/packages/core/src/infrastructure/services/agents/common/executors/dev-executor.service.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/services/agents/common/executors/dev-executor.service.js +88 -13
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/feature-agent-graph.d.ts +1 -1
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/feature-agent-process.service.d.ts +2 -1
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/feature-agent-process.service.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/feature-agent-process.service.js +3 -0
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/feature-agent-worker.d.ts +2 -0
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/feature-agent-worker.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/feature-agent-worker.js +16 -3
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/merge/merge.node.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/merge/merge.node.js +5 -1
- package/dist/src/presentation/web/app/actions/create-feature.d.ts.map +1 -1
- package/dist/src/presentation/web/app/actions/create-feature.js +20 -2
- package/dist/src/presentation/web/app/actions/get-feature-metadata.d.ts +10 -0
- package/dist/src/presentation/web/app/actions/get-feature-metadata.d.ts.map +1 -0
- package/dist/src/presentation/web/app/actions/get-feature-metadata.js +14 -0
- package/dist/src/presentation/web/app/actions/get-graph-data.d.ts +10 -0
- package/dist/src/presentation/web/app/actions/get-graph-data.d.ts.map +1 -0
- package/dist/src/presentation/web/app/actions/get-graph-data.js +10 -0
- package/dist/src/presentation/web/app/api/agent-events/route.d.ts.map +1 -1
- package/dist/src/presentation/web/app/api/agent-events/route.js +18 -0
- package/dist/src/presentation/web/components/common/add-repository-button/add-repository-button.d.ts.map +1 -0
- package/dist/src/presentation/web/components/common/add-repository-button/index.d.ts +2 -0
- package/dist/src/presentation/web/components/common/add-repository-button/index.d.ts.map +1 -0
- package/dist/src/presentation/web/components/common/{add-repository-node → add-repository-button}/index.js +0 -1
- package/dist/src/presentation/web/components/common/add-repository-button/pick-folder.d.ts.map +1 -0
- 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 +21 -23
- 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 +35 -16
- package/dist/src/presentation/web/components/common/feature-node/derive-feature-state.d.ts.map +1 -1
- package/dist/src/presentation/web/components/common/feature-node/derive-feature-state.js +2 -0
- package/dist/src/presentation/web/components/common/index.d.ts +1 -2
- package/dist/src/presentation/web/components/common/index.d.ts.map +1 -1
- package/dist/src/presentation/web/components/common/index.js +1 -2
- package/dist/src/presentation/web/components/common/repository-node/repository-node.js +1 -1
- package/dist/src/presentation/web/components/common/sidebar-section-header/sidebar-section-header.d.ts +1 -3
- package/dist/src/presentation/web/components/common/sidebar-section-header/sidebar-section-header.d.ts.map +1 -1
- package/dist/src/presentation/web/components/common/sidebar-section-header/sidebar-section-header.js +3 -7
- package/dist/src/presentation/web/components/common/sidebar-section-header/sidebar-section-header.stories.d.ts +0 -1
- package/dist/src/presentation/web/components/common/sidebar-section-header/sidebar-section-header.stories.d.ts.map +1 -1
- package/dist/src/presentation/web/components/common/sidebar-section-header/sidebar-section-header.stories.js +0 -11
- package/dist/src/presentation/web/components/features/control-center/control-center-empty-state.js +1 -1
- 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 +25 -7
- package/dist/src/presentation/web/components/features/control-center/control-center.stories.d.ts +0 -11
- package/dist/src/presentation/web/components/features/control-center/control-center.stories.d.ts.map +1 -1
- package/dist/src/presentation/web/components/features/control-center/control-center.stories.js +2 -37
- package/dist/src/presentation/web/components/features/control-center/use-control-center-state.d.ts +8 -0
- 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 +145 -256
- package/dist/src/presentation/web/components/features/features-canvas/features-canvas.d.ts +2 -10
- package/dist/src/presentation/web/components/features/features-canvas/features-canvas.d.ts.map +1 -1
- package/dist/src/presentation/web/components/features/features-canvas/features-canvas.js +12 -44
- package/dist/src/presentation/web/components/features/features-canvas/features-canvas.stories.d.ts.map +1 -1
- package/dist/src/presentation/web/components/features/features-canvas/features-canvas.stories.js +0 -46
- package/dist/src/presentation/web/components/layouts/app-shell/app-shell.js +1 -1
- package/dist/src/presentation/web/components/layouts/app-sidebar/app-sidebar.d.ts +1 -3
- package/dist/src/presentation/web/components/layouts/app-sidebar/app-sidebar.d.ts.map +1 -1
- package/dist/src/presentation/web/components/layouts/app-sidebar/app-sidebar.js +2 -2
- package/dist/src/presentation/web/components/ui/scroll-area.js +1 -1
- package/dist/src/presentation/web/hooks/use-graph-state.d.ts +42 -0
- package/dist/src/presentation/web/hooks/use-graph-state.d.ts.map +1 -0
- package/dist/src/presentation/web/hooks/use-graph-state.js +257 -0
- package/dist/src/presentation/web/hooks/use-notifications.d.ts +1 -5
- package/dist/src/presentation/web/hooks/use-notifications.d.ts.map +1 -1
- package/dist/src/presentation/web/hooks/use-notifications.js +1 -26
- package/dist/src/presentation/web/hooks/use-notifications.stories.d.ts.map +1 -1
- package/dist/src/presentation/web/hooks/use-notifications.stories.js +28 -38
- package/dist/src/presentation/web/lib/derive-graph.d.ts +52 -0
- package/dist/src/presentation/web/lib/derive-graph.d.ts.map +1 -0
- package/dist/src/presentation/web/lib/derive-graph.js +126 -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 +1 -2
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/web/.next/BUILD_ID +1 -1
- package/web/.next/build-manifest.json +2 -2
- 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/server/app/(dashboard)/@drawer/create/page/server-reference-manifest.json +43 -28
- 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/server-reference-manifest.json +49 -34
- 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/server-reference-manifest.json +39 -24
- 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/server-reference-manifest.json +43 -28
- 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/server-reference-manifest.json +49 -34
- 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/server-reference-manifest.json +39 -24
- 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/server-reference-manifest.json +39 -24
- 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.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/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/skills/page/server-reference-manifest.json +6 -6
- 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/server-reference-manifest.json +6 -6
- 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/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/chunks/403f9_next_dist_esm_build_templates_app-route_4d623b8e.js +2 -2
- package/web/.next/server/chunks/403f9_next_dist_esm_build_templates_app-route_4d623b8e.js.map +1 -1
- 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_816618e2.js +3 -0
- package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_@drawer_repository_[repositoryId]_page_actions_816618e2.js.map +1 -0
- package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_repository_[repositoryId]_page_actions_ba2e050f.js +3 -0
- package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_repository_[repositoryId]_page_actions_ba2e050f.js.map +1 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__17a611f0._.js +2 -2
- package/web/.next/server/chunks/ssr/[root-of-the-server]__17a611f0._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__249c74f6._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__45dbf93d._.js +2 -2
- package/web/.next/server/chunks/ssr/[root-of-the-server]__45dbf93d._.js.map +1 -1
- package/web/.next/server/chunks/ssr/{[root-of-the-server]__cbae9863._.js → [root-of-the-server]__6258349c._.js} +2 -2
- package/web/.next/server/chunks/ssr/[root-of-the-server]__6258349c._.js.map +1 -0
- 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/server/chunks/ssr/[root-of-the-server]__6cbc1149._.js +2 -2
- package/web/.next/server/chunks/ssr/[root-of-the-server]__6cbc1149._.js.map +1 -1
- 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/{standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__e5e09f72._.js → server/chunks/ssr/[root-of-the-server]__94a6d275._.js} +2 -2
- package/web/.next/server/chunks/ssr/[root-of-the-server]__94a6d275._.js.map +1 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__aad040c0._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__aad040c0._.js.map +1 -1
- package/web/.next/server/chunks/ssr/_0e9d6bf7._.js +1 -1
- package/web/.next/server/chunks/ssr/_0e9d6bf7._.js.map +1 -1
- package/web/.next/server/chunks/ssr/_250a63ae._.js.map +1 -1
- package/web/.next/server/chunks/ssr/_61351ed3._.js +1 -1
- package/web/.next/server/chunks/ssr/_61351ed3._.js.map +1 -1
- package/web/.next/server/chunks/ssr/_8400c8bb._.js +1 -1
- package/web/.next/server/chunks/ssr/_8400c8bb._.js.map +1 -1
- package/web/.next/server/chunks/ssr/_9f940437._.js +1 -1
- package/web/.next/server/chunks/ssr/_9f940437._.js.map +1 -1
- package/web/.next/server/chunks/ssr/_9fd79ac5._.js +6 -0
- package/web/.next/server/chunks/ssr/_9fd79ac5._.js.map +1 -0
- package/web/.next/{standalone/src/presentation/web/.next/server/chunks/ssr/src_presentation_web_398553b0._.js → server/chunks/ssr/src_presentation_web_2b91e4ec._.js} +2 -2
- package/web/.next/server/chunks/ssr/{src_presentation_web_5c87e8e4._.js.map → src_presentation_web_2b91e4ec._.js.map} +1 -1
- package/web/.next/{standalone/src/presentation/web/.next/server/chunks/ssr/src_presentation_web_5c87e8e4._.js → server/chunks/ssr/src_presentation_web_5bcc1537._.js} +2 -2
- package/web/.next/server/chunks/ssr/{src_presentation_web_398553b0._.js.map → src_presentation_web_5bcc1537._.js.map} +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_5955c012.js +3 -0
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_5955c012.js.map +1 -0
- 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_e599bb8c._.js +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_components_e599bb8c._.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_d5b0cb86._.js +8 -0
- package/web/.next/server/chunks/ssr/src_presentation_web_d5b0cb86._.js.map +1 -0
- package/web/.next/server/chunks/ssr/src_presentation_web_e626b63c._.js +8 -0
- package/web/.next/server/chunks/ssr/src_presentation_web_e626b63c._.js.map +1 -0
- 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 +175 -118
- package/web/.next/standalone/src/presentation/web/.next/BUILD_ID +1 -1
- package/web/.next/standalone/src/presentation/web/.next/build-manifest.json +2 -2
- 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/server/app/(dashboard)/@drawer/create/page/server-reference-manifest.json +43 -28
- 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/server-reference-manifest.json +49 -34
- 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/server-reference-manifest.json +39 -24
- 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/server-reference-manifest.json +43 -28
- 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/server-reference-manifest.json +49 -34
- 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/server-reference-manifest.json +39 -24
- 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/server-reference-manifest.json +39 -24
- 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.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/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/skills/page/server-reference-manifest.json +6 -6
- 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/server-reference-manifest.json +6 -6
- 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/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/chunks/403f9_next_dist_esm_build_templates_app-route_4d623b8e.js +2 -2
- 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_816618e2.js +3 -0
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_repository_[repositoryId]_page_actions_ba2e050f.js +3 -0
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__17a611f0._.js +2 -2
- package/web/.next/standalone/src/presentation/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]__45dbf93d._.js +2 -2
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/{[root-of-the-server]__cbae9863._.js → [root-of-the-server]__6258349c._.js} +2 -2
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__6b17a22d._.js +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__6cbc1149._.js +2 -2
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__804c006d._.js +1 -1
- package/web/.next/{server/chunks/ssr/[root-of-the-server]__e5e09f72._.js → standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__94a6d275._.js} +2 -2
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__aad040c0._.js +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/_0e9d6bf7._.js +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/_61351ed3._.js +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/_8400c8bb._.js +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/_9f940437._.js +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/_9fd79ac5._.js +6 -0
- package/web/.next/{server/chunks/ssr/src_presentation_web_398553b0._.js → standalone/src/presentation/web/.next/server/chunks/ssr/src_presentation_web_2b91e4ec._.js} +2 -2
- package/web/.next/{server/chunks/ssr/src_presentation_web_5c87e8e4._.js → standalone/src/presentation/web/.next/server/chunks/ssr/src_presentation_web_5bcc1537._.js} +2 -2
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_5955c012.js +3 -0
- 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_e599bb8c._.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_d5b0cb86._.js +8 -0
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/src_presentation_web_e626b63c._.js +8 -0
- 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 +175 -118
- package/web/.next/standalone/src/presentation/web/CLAUDE.md +191 -0
- package/web/.next/standalone/src/presentation/web/app/actions/create-feature.ts +27 -2
- package/web/.next/standalone/src/presentation/web/app/actions/get-feature-metadata.ts +18 -0
- package/web/.next/standalone/src/presentation/web/app/actions/get-graph-data.ts +12 -0
- package/web/.next/standalone/src/presentation/web/app/api/agent-events/route.ts +21 -1
- package/web/.next/standalone/src/presentation/web/components/common/add-repository-button/index.ts +1 -0
- package/web/.next/standalone/src/presentation/web/components/common/control-center-drawer/create-drawer-client.tsx +23 -26
- package/web/.next/standalone/src/presentation/web/components/common/control-center-drawer/feature-drawer-client.tsx +44 -18
- package/web/.next/standalone/src/presentation/web/components/common/feature-node/derive-feature-state.ts +2 -0
- package/web/.next/standalone/src/presentation/web/components/common/index.ts +1 -6
- package/web/.next/standalone/src/presentation/web/components/common/repository-node/repository-node.tsx +2 -2
- package/web/.next/standalone/src/presentation/web/components/common/sidebar-section-header/sidebar-section-header.stories.tsx +0 -13
- package/web/.next/standalone/src/presentation/web/components/common/sidebar-section-header/sidebar-section-header.tsx +1 -45
- package/web/.next/standalone/src/presentation/web/components/features/control-center/control-center-empty-state.tsx +1 -1
- package/web/.next/standalone/src/presentation/web/components/features/control-center/control-center-inner.tsx +36 -29
- package/web/.next/standalone/src/presentation/web/components/features/control-center/control-center.stories.tsx +2 -41
- package/web/.next/standalone/src/presentation/web/components/features/control-center/use-control-center-state.ts +178 -325
- package/web/.next/standalone/src/presentation/web/components/features/features-canvas/features-canvas.stories.tsx +0 -48
- package/web/.next/standalone/src/presentation/web/components/features/features-canvas/features-canvas.tsx +34 -82
- package/web/.next/standalone/src/presentation/web/components/layouts/app-shell/app-shell.tsx +1 -1
- package/web/.next/standalone/src/presentation/web/components/layouts/app-sidebar/app-sidebar.tsx +2 -14
- package/web/.next/standalone/src/presentation/web/components/ui/scroll-area.tsx +1 -1
- package/web/.next/standalone/src/presentation/web/hooks/use-graph-state.ts +376 -0
- package/web/.next/standalone/src/presentation/web/hooks/use-notifications.stories.tsx +2 -30
- package/web/.next/standalone/src/presentation/web/hooks/use-notifications.ts +2 -36
- package/web/.next/standalone/src/presentation/web/lib/derive-graph.ts +178 -0
- package/web/.next/standalone/src/presentation/web/lib/layout-with-dagre.ts +1 -2
- package/web/.next/standalone/src/presentation/web/server.js +1 -1
- package/web/.next/static/chunks/{1c07b21eb8b32f25.js → 0b409f42a82665ec.js} +1 -1
- package/web/.next/static/chunks/0e035a073754dde7.js +1 -0
- package/web/.next/static/chunks/109d6898972d7b78.js +1 -0
- package/web/.next/static/chunks/{fcafb841e3860687.js → 5238c7e71fc81e4d.js} +1 -1
- package/web/.next/static/chunks/6b4899963367ea96.js +4 -0
- package/web/.next/static/chunks/71c9ecdceac1939f.css +2 -0
- package/web/.next/static/chunks/752846e217931a38.js +1 -0
- package/web/.next/static/chunks/9f9e6f5083600784.js +1 -0
- package/web/.next/static/chunks/{8682dcb376de62de.js → ae00da647a8354b9.js} +1 -1
- package/web/.next/static/chunks/cb41849bcfaa304e.js +1 -0
- package/web/.next/static/chunks/dc23a5773f5cd610.js +1 -0
- package/web/.next/trace +1 -1
- package/web/.next/trace-build +1 -1
- package/dist/src/presentation/web/components/common/add-repository-node/add-repository-button.d.ts.map +0 -1
- package/dist/src/presentation/web/components/common/add-repository-node/add-repository-node-config.d.ts +0 -7
- package/dist/src/presentation/web/components/common/add-repository-node/add-repository-node-config.d.ts.map +0 -1
- package/dist/src/presentation/web/components/common/add-repository-node/add-repository-node-config.js +0 -1
- package/dist/src/presentation/web/components/common/add-repository-node/add-repository-node.d.ts +0 -6
- package/dist/src/presentation/web/components/common/add-repository-node/add-repository-node.d.ts.map +0 -1
- package/dist/src/presentation/web/components/common/add-repository-node/add-repository-node.js +0 -23
- package/dist/src/presentation/web/components/common/add-repository-node/add-repository-node.stories.d.ts +0 -10
- package/dist/src/presentation/web/components/common/add-repository-node/add-repository-node.stories.d.ts.map +0 -1
- package/dist/src/presentation/web/components/common/add-repository-node/add-repository-node.stories.js +0 -33
- package/dist/src/presentation/web/components/common/add-repository-node/index.d.ts +0 -4
- package/dist/src/presentation/web/components/common/add-repository-node/index.d.ts.map +0 -1
- package/dist/src/presentation/web/components/common/add-repository-node/pick-folder.d.ts.map +0 -1
- package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_@drawer_repository_[repositoryId]_page_actions_2b7834f6.js +0 -3
- package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_@drawer_repository_[repositoryId]_page_actions_2b7834f6.js.map +0 -1
- package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_repository_[repositoryId]_page_actions_6923c575.js +0 -3
- package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_repository_[repositoryId]_page_actions_6923c575.js.map +0 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__cbae9863._.js.map +0 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__e5e09f72._.js.map +0 -1
- package/web/.next/server/chunks/ssr/_47ef589d._.js +0 -6
- package/web/.next/server/chunks/ssr/_47ef589d._.js.map +0 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_1a32dbcb._.js +0 -8
- package/web/.next/server/chunks/ssr/src_presentation_web_1a32dbcb._.js.map +0 -1
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_f4952172.js +0 -3
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_f4952172.js.map +0 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_c1bc6240._.js +0 -8
- package/web/.next/server/chunks/ssr/src_presentation_web_c1bc6240._.js.map +0 -1
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_@drawer_repository_[repositoryId]_page_actions_2b7834f6.js +0 -3
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_repository_[repositoryId]_page_actions_6923c575.js +0 -3
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/_47ef589d._.js +0 -6
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/src_presentation_web_1a32dbcb._.js +0 -8
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_f4952172.js +0 -3
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/src_presentation_web_c1bc6240._.js +0 -8
- package/web/.next/standalone/src/presentation/web/components/common/add-repository-node/add-repository-node-config.ts +0 -8
- package/web/.next/standalone/src/presentation/web/components/common/add-repository-node/add-repository-node.stories.tsx +0 -70
- package/web/.next/standalone/src/presentation/web/components/common/add-repository-node/add-repository-node.tsx +0 -49
- package/web/.next/standalone/src/presentation/web/components/common/add-repository-node/index.ts +0 -3
- package/web/.next/static/chunks/3c79bca4d3f18f66.js +0 -1
- package/web/.next/static/chunks/5cd24ca47061a21d.js +0 -4
- package/web/.next/static/chunks/67f2a7a5e8dc358a.css +0 -2
- package/web/.next/static/chunks/71cf72022f08a8c9.js +0 -1
- package/web/.next/static/chunks/991d4490d7a338d8.js +0 -1
- package/web/.next/static/chunks/c71589df79020ecb.js +0 -1
- package/web/.next/static/chunks/ebf172a84c9596ed.js +0 -1
- package/web/.next/static/chunks/fabfa54940973cc7.js +0 -1
- /package/dist/src/presentation/web/components/common/{add-repository-node → add-repository-button}/add-repository-button.d.ts +0 -0
- /package/dist/src/presentation/web/components/common/{add-repository-node → add-repository-button}/add-repository-button.js +0 -0
- /package/dist/src/presentation/web/components/common/{add-repository-node → add-repository-button}/pick-folder.d.ts +0 -0
- /package/dist/src/presentation/web/components/common/{add-repository-node → add-repository-button}/pick-folder.js +0 -0
- /package/web/.next/standalone/src/presentation/web/components/common/{add-repository-node → add-repository-button}/add-repository-button.tsx +0 -0
- /package/web/.next/standalone/src/presentation/web/components/common/{add-repository-node → add-repository-button}/pick-folder.ts +0 -0
- /package/web/.next/static/{IKuYPxAuMvc4BtwKHlj30 → JYBKfZ0ROsNn817Id2TJ7}/_buildManifest.js +0 -0
- /package/web/.next/static/{IKuYPxAuMvc4BtwKHlj30 → JYBKfZ0ROsNn817Id2TJ7}/_clientMiddlewareManifest.json +0 -0
- /package/web/.next/static/{IKuYPxAuMvc4BtwKHlj30 → JYBKfZ0ROsNn817Id2TJ7}/_ssgManifest.js +0 -0
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { useCallback, useEffect, useRef } from 'react';
|
|
4
4
|
import { useRouter } from 'next/navigation';
|
|
5
5
|
import { toast } from 'sonner';
|
|
6
|
-
import { applyNodeChanges } from '@xyflow/react';
|
|
7
6
|
import type { Connection, Edge, NodeChange } from '@xyflow/react';
|
|
8
7
|
import type { FeatureNodeData } from '@/components/common/feature-node';
|
|
8
|
+
import type { RepositoryNodeData } from '@/components/common/repository-node';
|
|
9
9
|
import type { CanvasNodeType } from '@/components/features/features-canvas';
|
|
10
10
|
import {
|
|
11
11
|
layoutWithDagre,
|
|
@@ -15,12 +15,16 @@ import {
|
|
|
15
15
|
import { deleteFeature } from '@/app/actions/delete-feature';
|
|
16
16
|
import { addRepository } from '@/app/actions/add-repository';
|
|
17
17
|
import { deleteRepository } from '@/app/actions/delete-repository';
|
|
18
|
+
import { getFeatureMetadata } from '@/app/actions/get-feature-metadata';
|
|
18
19
|
import { useAgentEventsContext } from '@/hooks/agent-events-provider';
|
|
19
20
|
import { useSoundAction } from '@/hooks/use-sound-action';
|
|
20
21
|
import {
|
|
21
22
|
mapEventTypeToState,
|
|
22
23
|
mapPhaseNameToLifecycle,
|
|
23
24
|
} from '@/components/common/feature-node/derive-feature-state';
|
|
25
|
+
import { NotificationEventType } from '@shepai/core/domain/generated/output';
|
|
26
|
+
import { useGraphState, type GraphCallbacks } from '@/hooks/use-graph-state';
|
|
27
|
+
import type { FeatureEntry } from '@/lib/derive-graph';
|
|
24
28
|
|
|
25
29
|
export interface ControlCenterState {
|
|
26
30
|
nodes: CanvasNodeType[];
|
|
@@ -36,8 +40,17 @@ export interface ControlCenterState {
|
|
|
36
40
|
dataOverride?: Partial<FeatureNodeData>,
|
|
37
41
|
edgeType?: string
|
|
38
42
|
) => string;
|
|
43
|
+
/** Stable lookup: repositoryPath for a feature node. */
|
|
44
|
+
getFeatureRepositoryPath: (featureNodeId: string) => string | undefined;
|
|
45
|
+
/** Stable lookup: repository data by nodeId. */
|
|
46
|
+
getRepositoryData: (nodeId: string) => RepositoryNodeData | undefined;
|
|
47
|
+
/** Sync callbacks into derived node data (does not trigger re-render). */
|
|
48
|
+
setCallbacks: (callbacks: GraphCallbacks) => void;
|
|
39
49
|
}
|
|
40
50
|
|
|
51
|
+
/** Must match the message string emitted by the SSE route in agent-events/route.ts */
|
|
52
|
+
const METADATA_UPDATED_MESSAGE = 'Feature metadata updated';
|
|
53
|
+
|
|
41
54
|
let nextFeatureId = 0;
|
|
42
55
|
|
|
43
56
|
export function useControlCenterState(
|
|
@@ -45,37 +58,31 @@ export function useControlCenterState(
|
|
|
45
58
|
initialEdges: Edge[]
|
|
46
59
|
): ControlCenterState {
|
|
47
60
|
const router = useRouter();
|
|
48
|
-
const [nodes, setNodes] = useState<CanvasNodeType[]>(initialNodes);
|
|
49
|
-
// eslint-disable-next-line react/hook-use-state -- raw setter renamed; public setEdges wrapper keeps edgesRef in sync
|
|
50
|
-
const [edges, setEdgesRaw] = useState<Edge[]>(initialEdges);
|
|
51
|
-
const edgesRef = useRef<Edge[]>(initialEdges);
|
|
52
|
-
|
|
53
|
-
// Wrapper that keeps edgesRef in sync with edges state, allowing
|
|
54
|
-
// createFeatureNode to read current edges without a closure dependency.
|
|
55
|
-
const setEdges = useCallback((update: Edge[] | ((prev: Edge[]) => Edge[])) => {
|
|
56
|
-
setEdgesRaw((prev) => {
|
|
57
|
-
const next = typeof update === 'function' ? update(prev) : update;
|
|
58
|
-
edgesRef.current = next;
|
|
59
|
-
return next;
|
|
60
|
-
});
|
|
61
|
-
}, []);
|
|
62
61
|
const deleteSound = useSoundAction('delete');
|
|
63
62
|
const createSound = useSoundAction('create');
|
|
64
63
|
|
|
65
|
-
|
|
64
|
+
const {
|
|
65
|
+
nodes,
|
|
66
|
+
edges,
|
|
67
|
+
reconcile,
|
|
68
|
+
updateFeature,
|
|
69
|
+
addPendingFeature,
|
|
70
|
+
removeFeature,
|
|
71
|
+
restoreFeature,
|
|
72
|
+
addRepository: addRepositoryToMap,
|
|
73
|
+
removeRepository,
|
|
74
|
+
replaceRepository,
|
|
75
|
+
getFeatureRepositoryPath,
|
|
76
|
+
getRepositoryData,
|
|
77
|
+
setCallbacks,
|
|
78
|
+
} = useGraphState(initialNodes, initialEdges);
|
|
79
|
+
|
|
80
|
+
// Sync server props into domain Maps when initialNodes/initialEdges change.
|
|
81
|
+
// Keyed by a stable string so we don't re-reconcile on every render.
|
|
66
82
|
const initialNodeKey = initialNodes
|
|
67
83
|
.map((n) => n.id)
|
|
68
84
|
.sort()
|
|
69
85
|
.join(',');
|
|
70
|
-
const initialEdgeKey = initialEdges
|
|
71
|
-
.map((e) => e.id)
|
|
72
|
-
.sort()
|
|
73
|
-
.join(',');
|
|
74
|
-
|
|
75
|
-
// Track previous feature states so we can detect transitions on server refresh
|
|
76
|
-
const prevFeatureStatesRef = useRef<Map<string, FeatureNodeData['state']>>(new Map());
|
|
77
|
-
|
|
78
|
-
// Stable key that changes when feature DATA changes (state/lifecycle), not just IDs.
|
|
79
86
|
const initialDataKey = initialNodes
|
|
80
87
|
.filter((n) => n.type === 'featureNode')
|
|
81
88
|
.map((n) => {
|
|
@@ -85,83 +92,31 @@ export function useControlCenterState(
|
|
|
85
92
|
.sort()
|
|
86
93
|
.join(',');
|
|
87
94
|
|
|
88
|
-
|
|
89
|
-
// to avoid infinite re-renders from unstable array references.
|
|
90
|
-
useEffect(() => {
|
|
91
|
-
setNodes((currentNodes) => {
|
|
92
|
-
// Build a lookup of current node positions by ID
|
|
93
|
-
const currentById = new Map(currentNodes.map((n) => [n.id, n]));
|
|
94
|
-
|
|
95
|
-
// Identify optimistic "creating" nodes (they have temp IDs not in server data)
|
|
96
|
-
const serverIds = new Set(initialNodes.map((n) => n.id));
|
|
97
|
-
const creatingNodes = currentNodes.filter(
|
|
98
|
-
(n) =>
|
|
99
|
-
n.type === 'featureNode' &&
|
|
100
|
-
(n.data as FeatureNodeData).state === 'creating' &&
|
|
101
|
-
!serverIds.has(n.id)
|
|
102
|
-
);
|
|
103
|
-
|
|
104
|
-
// Merge server nodes with client positions, tracking if relayout is needed
|
|
105
|
-
let needsRelayout = false;
|
|
106
|
-
const merged = initialNodes.map((serverNode) => {
|
|
107
|
-
// Node already exists on canvas — keep its position, update data
|
|
108
|
-
const existing = currentById.get(serverNode.id);
|
|
109
|
-
if (existing) {
|
|
110
|
-
return { ...serverNode, position: existing.position };
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
// New server node — inherit position from an optimistic creating node if available
|
|
114
|
-
if (serverNode.type === 'featureNode' && creatingNodes.length > 0) {
|
|
115
|
-
const donor = creatingNodes.shift()!;
|
|
116
|
-
return { ...serverNode, position: donor.position };
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
// Truly new node with no optimistic counterpart — needs relayout
|
|
120
|
-
needsRelayout = true;
|
|
121
|
-
return serverNode;
|
|
122
|
-
});
|
|
123
|
-
|
|
124
|
-
// Also check if non-creating nodes were removed (graph got smaller)
|
|
125
|
-
if (!needsRelayout) {
|
|
126
|
-
needsRelayout = currentNodes.some(
|
|
127
|
-
(cn) =>
|
|
128
|
-
!serverIds.has(cn.id) &&
|
|
129
|
-
!(cn.type === 'featureNode' && (cn.data as FeatureNodeData).state === 'creating')
|
|
130
|
-
);
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
if (needsRelayout) {
|
|
134
|
-
const layoutResult = layoutWithDagre(merged, initialEdges, CANVAS_LAYOUT_DEFAULTS);
|
|
135
|
-
setEdges(layoutResult.edges);
|
|
136
|
-
return layoutResult.nodes;
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
return merged;
|
|
140
|
-
});
|
|
141
|
-
}, [initialNodeKey, initialNodes, initialEdges, setEdges]);
|
|
95
|
+
const prevReconcileKey = useRef('');
|
|
142
96
|
|
|
143
97
|
useEffect(() => {
|
|
144
|
-
|
|
145
|
-
|
|
98
|
+
const key = `${initialNodeKey}|${initialDataKey}`;
|
|
99
|
+
if (key !== prevReconcileKey.current) {
|
|
100
|
+
prevReconcileKey.current = key;
|
|
101
|
+
reconcile(initialNodes, initialEdges);
|
|
102
|
+
}
|
|
103
|
+
}, [initialNodeKey, initialDataKey, initialNodes, initialEdges, reconcile]);
|
|
104
|
+
|
|
105
|
+
// Track previous feature states for fallback notifications
|
|
106
|
+
const prevFeatureStatesRef = useRef<Map<string, FeatureNodeData['state']>>(new Map());
|
|
146
107
|
|
|
147
|
-
// Fallback notifications from server-prop state transitions.
|
|
148
|
-
// Fires only when SSE didn't already deliver the matching event for a feature.
|
|
149
108
|
const { events } = useAgentEventsContext();
|
|
150
109
|
|
|
151
110
|
useEffect(() => {
|
|
152
111
|
const prevStates = prevFeatureStatesRef.current;
|
|
153
|
-
|
|
154
112
|
for (const node of initialNodes) {
|
|
155
113
|
if (node.type !== 'featureNode') continue;
|
|
156
114
|
const data = node.data as FeatureNodeData;
|
|
157
115
|
const prev = prevStates.get(node.id);
|
|
158
|
-
|
|
159
116
|
if (prev !== undefined && prev !== data.state) {
|
|
160
|
-
// Check if SSE already delivered a matching event for this feature
|
|
161
117
|
const sseAlreadyCovered = events.some(
|
|
162
118
|
(e) => e.featureId === data.featureId && mapEventTypeToState(e.eventType) === data.state
|
|
163
119
|
);
|
|
164
|
-
|
|
165
120
|
if (!sseAlreadyCovered) {
|
|
166
121
|
if (data.state === 'done') {
|
|
167
122
|
toast.success(data.name, { description: 'Feature completed!' });
|
|
@@ -170,9 +125,7 @@ export function useControlCenterState(
|
|
|
170
125
|
description: 'Waiting for your approval',
|
|
171
126
|
action: {
|
|
172
127
|
label: 'Review',
|
|
173
|
-
onClick: () => {
|
|
174
|
-
router.push(`/feature/${data.featureId}`);
|
|
175
|
-
},
|
|
128
|
+
onClick: () => router.push(`/feature/${data.featureId}`),
|
|
176
129
|
},
|
|
177
130
|
});
|
|
178
131
|
} else if (data.state === 'error') {
|
|
@@ -180,81 +133,83 @@ export function useControlCenterState(
|
|
|
180
133
|
}
|
|
181
134
|
}
|
|
182
135
|
}
|
|
183
|
-
|
|
184
136
|
prevStates.set(node.id, data.state);
|
|
185
137
|
}
|
|
186
138
|
}, [initialDataKey, initialNodes, events, router]);
|
|
187
139
|
|
|
188
|
-
//
|
|
189
|
-
// Uses `events` array (not `lastEvent`) so that React batching cannot silently
|
|
190
|
-
// drop events when multiple SSE messages arrive in the same tick.
|
|
140
|
+
// SSE effect: only state + lifecycle updates
|
|
191
141
|
const processedEventCountRef = useRef(0);
|
|
192
142
|
|
|
193
143
|
useEffect(() => {
|
|
194
144
|
if (events.length <= processedEventCountRef.current) return;
|
|
195
|
-
|
|
196
145
|
const newEvents = events.slice(processedEventCountRef.current);
|
|
197
146
|
processedEventCountRef.current = events.length;
|
|
198
147
|
|
|
148
|
+
// PhaseCompleted must NOT set state when WaitingApproval is in the same poll batch —
|
|
149
|
+
// they arrive together and PhaseCompleted → 'running' would revert 'action-required'.
|
|
150
|
+
// But when PhaseCompleted arrives WITHOUT WaitingApproval (e.g. after approval), we
|
|
151
|
+
// must allow it to update state as a fallback for any missed AgentStarted event.
|
|
152
|
+
const waitingApprovalFeatures = new Set(
|
|
153
|
+
newEvents
|
|
154
|
+
.filter((e) => e.eventType === NotificationEventType.WaitingApproval)
|
|
155
|
+
.map((e) => e.featureId)
|
|
156
|
+
);
|
|
157
|
+
|
|
199
158
|
for (const event of newEvents) {
|
|
200
|
-
const newState =
|
|
159
|
+
const newState =
|
|
160
|
+
event.eventType === NotificationEventType.PhaseCompleted &&
|
|
161
|
+
waitingApprovalFeatures.has(event.featureId)
|
|
162
|
+
? undefined
|
|
163
|
+
: mapEventTypeToState(event.eventType);
|
|
201
164
|
const newLifecycle = mapPhaseNameToLifecycle(event.phaseName);
|
|
202
165
|
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
...node,
|
|
211
|
-
data: {
|
|
212
|
-
...data,
|
|
213
|
-
state: newState,
|
|
214
|
-
...(newLifecycle !== undefined && { lifecycle: newLifecycle }),
|
|
215
|
-
},
|
|
216
|
-
};
|
|
217
|
-
})
|
|
218
|
-
);
|
|
166
|
+
const nodeId = `feat-${event.featureId}`;
|
|
167
|
+
if (newState !== undefined || newLifecycle !== undefined) {
|
|
168
|
+
updateFeature(nodeId, {
|
|
169
|
+
...(newState !== undefined && { state: newState }),
|
|
170
|
+
...(newLifecycle !== undefined && { lifecycle: newLifecycle }),
|
|
171
|
+
});
|
|
172
|
+
}
|
|
219
173
|
}
|
|
220
|
-
}, [events]);
|
|
174
|
+
}, [events, updateFeature]);
|
|
221
175
|
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
const handleConnect = useCallback(
|
|
227
|
-
(connection: Connection) => {
|
|
228
|
-
if (!connection.source || !connection.target) return;
|
|
176
|
+
// Separate effect: fetch metadata (name + description) when SSE reports it changed
|
|
177
|
+
const metadataFetchedRef = useRef<Set<string>>(new Set());
|
|
178
|
+
const processedMetadataCountRef = useRef(0);
|
|
229
179
|
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
180
|
+
useEffect(() => {
|
|
181
|
+
if (events.length <= processedMetadataCountRef.current) return;
|
|
182
|
+
const newEvents = events.slice(processedMetadataCountRef.current);
|
|
183
|
+
processedMetadataCountRef.current = events.length;
|
|
233
184
|
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
style: { strokeDasharray: '5 5' },
|
|
249
|
-
},
|
|
250
|
-
];
|
|
185
|
+
for (const event of newEvents) {
|
|
186
|
+
if (event.message !== METADATA_UPDATED_MESSAGE) continue;
|
|
187
|
+
if (metadataFetchedRef.current.has(event.featureId)) continue;
|
|
188
|
+
metadataFetchedRef.current.add(event.featureId);
|
|
189
|
+
|
|
190
|
+
const nodeId = `feat-${event.featureId}`;
|
|
191
|
+
getFeatureMetadata(event.featureId)
|
|
192
|
+
.then((meta) => {
|
|
193
|
+
if (meta) {
|
|
194
|
+
updateFeature(nodeId, { name: meta.name, description: meta.description });
|
|
195
|
+
}
|
|
196
|
+
})
|
|
197
|
+
.catch(() => {
|
|
198
|
+
// Silent: metadata fetch failure is non-critical
|
|
251
199
|
});
|
|
200
|
+
}
|
|
201
|
+
}, [events, updateFeature]);
|
|
252
202
|
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
203
|
+
// onNodesChange is a no-op: nodes are derived from domain Maps.
|
|
204
|
+
// Since nodesDraggable=false and elementsSelectable=false, only React Flow's
|
|
205
|
+
// internal replace/dimensions changes come through — we ignore them all.
|
|
206
|
+
const onNodesChange = useCallback((_changes: NodeChange<CanvasNodeType>[]) => {
|
|
207
|
+
// Intentional no-op: domain Maps are the source of truth.
|
|
208
|
+
}, []);
|
|
209
|
+
|
|
210
|
+
const handleConnect = useCallback((_connection: Connection) => {
|
|
211
|
+
// Connections are managed via domain operations, not direct edge manipulation.
|
|
212
|
+
}, []);
|
|
258
213
|
|
|
259
214
|
const createFeatureNode = useCallback(
|
|
260
215
|
(
|
|
@@ -262,11 +217,14 @@ export function useControlCenterState(
|
|
|
262
217
|
dataOverride?: Partial<FeatureNodeData>,
|
|
263
218
|
edgeType?: string
|
|
264
219
|
): string => {
|
|
265
|
-
|
|
220
|
+
// Use real feature ID when available (from server), otherwise temp ID
|
|
221
|
+
const id = dataOverride?.featureId
|
|
222
|
+
? `feat-${dataOverride.featureId}`
|
|
223
|
+
: `feature-${Date.now()}-${nextFeatureId++}`;
|
|
266
224
|
const newFeatureData: FeatureNodeData = {
|
|
267
225
|
name: dataOverride?.name ?? 'New Feature',
|
|
268
226
|
description: dataOverride?.description ?? 'Describe what this feature does',
|
|
269
|
-
featureId: `#${id.slice(-4)}`,
|
|
227
|
+
featureId: dataOverride?.featureId ?? `#${id.slice(-4)}`,
|
|
270
228
|
lifecycle: 'requirements',
|
|
271
229
|
state: dataOverride?.state ?? 'running',
|
|
272
230
|
progress: 0,
|
|
@@ -274,171 +232,114 @@ export function useControlCenterState(
|
|
|
274
232
|
branch: dataOverride?.branch ?? '',
|
|
275
233
|
};
|
|
276
234
|
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
type: 'featureNode' as const,
|
|
281
|
-
position: { x: 0, y: 0 },
|
|
282
|
-
data: newFeatureData,
|
|
283
|
-
} as CanvasNodeType;
|
|
284
|
-
|
|
285
|
-
const newEdge = sourceNodeId
|
|
286
|
-
? {
|
|
287
|
-
id:
|
|
288
|
-
edgeType === 'dependencyEdge'
|
|
289
|
-
? `dep-${sourceNodeId}-${id}`
|
|
290
|
-
: `edge-${sourceNodeId}-${id}`,
|
|
291
|
-
source: sourceNodeId,
|
|
292
|
-
target: id,
|
|
293
|
-
...(edgeType ? { type: edgeType } : { style: { strokeDasharray: '5 5' } }),
|
|
294
|
-
}
|
|
295
|
-
: null;
|
|
296
|
-
|
|
297
|
-
const allEdges = newEdge
|
|
298
|
-
? [...edgesRef.current.filter((e) => e.id !== newEdge.id), newEdge]
|
|
299
|
-
: edgesRef.current;
|
|
300
|
-
|
|
301
|
-
// Insert the new node after the last sibling connected to the same source,
|
|
302
|
-
// so dagre's input-order preservation keeps repo groups together.
|
|
303
|
-
let insertIndex = currentNodes.length;
|
|
304
|
-
if (sourceNodeId) {
|
|
305
|
-
const siblingIds = new Set(
|
|
306
|
-
allEdges.filter((e) => e.source === sourceNodeId).map((e) => e.target)
|
|
307
|
-
);
|
|
308
|
-
for (let i = currentNodes.length - 1; i >= 0; i--) {
|
|
309
|
-
if (siblingIds.has(currentNodes[i].id)) {
|
|
310
|
-
insertIndex = i + 1;
|
|
311
|
-
break;
|
|
312
|
-
}
|
|
313
|
-
}
|
|
314
|
-
}
|
|
315
|
-
const allNodes = [
|
|
316
|
-
...currentNodes.slice(0, insertIndex),
|
|
317
|
-
newNode,
|
|
318
|
-
...currentNodes.slice(insertIndex),
|
|
319
|
-
];
|
|
320
|
-
|
|
321
|
-
// Run dagre layout on the full graph so the new node is positioned consistently
|
|
322
|
-
const layoutResult = layoutWithDagre(allNodes, allEdges, CANVAS_LAYOUT_DEFAULTS);
|
|
323
|
-
setEdges(layoutResult.edges);
|
|
324
|
-
return layoutResult.nodes;
|
|
325
|
-
});
|
|
235
|
+
const parentNodeId = edgeType === 'dependencyEdge' && sourceNodeId ? sourceNodeId : undefined;
|
|
236
|
+
|
|
237
|
+
addPendingFeature(id, newFeatureData, parentNodeId);
|
|
326
238
|
|
|
327
239
|
return id;
|
|
328
240
|
},
|
|
329
|
-
[
|
|
241
|
+
[addPendingFeature]
|
|
330
242
|
);
|
|
331
243
|
|
|
332
244
|
const handleDeleteFeature = useCallback(
|
|
333
245
|
(featureId: string) => {
|
|
334
246
|
const nodeId = `feat-${featureId}`;
|
|
335
247
|
|
|
336
|
-
//
|
|
337
|
-
const
|
|
338
|
-
|
|
248
|
+
// Find the current entry for rollback
|
|
249
|
+
const prevEntry = nodes
|
|
250
|
+
.filter((n) => n.id === nodeId)
|
|
251
|
+
.map((n) => ({
|
|
252
|
+
nodeId: n.id,
|
|
253
|
+
data: n.data as FeatureNodeData,
|
|
254
|
+
}))[0];
|
|
339
255
|
|
|
340
|
-
// Optimistic removal
|
|
341
|
-
|
|
342
|
-
const remainingNodes = currentNodes.filter((n) => n.id !== nodeId);
|
|
343
|
-
const remainingEdges = edgesRef.current.filter(
|
|
344
|
-
(e) => e.source !== nodeId && e.target !== nodeId
|
|
345
|
-
);
|
|
346
|
-
const layoutResult = layoutWithDagre(
|
|
347
|
-
remainingNodes,
|
|
348
|
-
remainingEdges,
|
|
349
|
-
CANVAS_LAYOUT_DEFAULTS
|
|
350
|
-
);
|
|
351
|
-
setEdges(layoutResult.edges);
|
|
352
|
-
return layoutResult.nodes;
|
|
353
|
-
});
|
|
256
|
+
// Optimistic removal
|
|
257
|
+
removeFeature(nodeId);
|
|
354
258
|
deleteSound.play();
|
|
355
259
|
toast.success('Feature deleted successfully');
|
|
356
260
|
router.push('/');
|
|
357
261
|
|
|
358
|
-
// Persist in background — rollback on failure
|
|
359
262
|
deleteFeature(featureId)
|
|
360
263
|
.then((result) => {
|
|
361
264
|
if (result.error) {
|
|
362
|
-
|
|
363
|
-
setEdges(prevEdges);
|
|
265
|
+
if (prevEntry) restoreFeature(nodeId, prevEntry);
|
|
364
266
|
toast.error(result.error);
|
|
365
267
|
}
|
|
366
268
|
})
|
|
367
269
|
.catch(() => {
|
|
368
|
-
|
|
369
|
-
setEdges(prevEdges);
|
|
270
|
+
if (prevEntry) restoreFeature(nodeId, prevEntry);
|
|
370
271
|
toast.error('Failed to delete feature');
|
|
371
272
|
});
|
|
372
273
|
},
|
|
373
|
-
[nodes, router, deleteSound,
|
|
274
|
+
[nodes, router, deleteSound, removeFeature, restoreFeature]
|
|
374
275
|
);
|
|
375
276
|
|
|
376
277
|
const handleDeleteRepository = useCallback(
|
|
377
278
|
async (repositoryId: string) => {
|
|
378
279
|
const repoNodeId = `repo-${repositoryId}`;
|
|
379
280
|
|
|
281
|
+
// Find children of this repo via edges
|
|
282
|
+
const childFeatureIds = new Set(
|
|
283
|
+
edges.filter((e) => e.source === repoNodeId).map((e) => e.target)
|
|
284
|
+
);
|
|
285
|
+
|
|
380
286
|
// Snapshot for rollback
|
|
381
|
-
const
|
|
382
|
-
const
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
)
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
remainingEdges,
|
|
403
|
-
CANVAS_LAYOUT_DEFAULTS
|
|
404
|
-
);
|
|
405
|
-
setEdges(layoutResult.edges);
|
|
406
|
-
return layoutResult.nodes;
|
|
407
|
-
});
|
|
287
|
+
const prevRepoData = getRepositoryData(repoNodeId);
|
|
288
|
+
const childSnapshots = new Map<string, FeatureEntry>();
|
|
289
|
+
for (const childId of childFeatureIds) {
|
|
290
|
+
const childNode = nodes.find((n) => n.id === childId);
|
|
291
|
+
if (childNode) {
|
|
292
|
+
childSnapshots.set(childId, { nodeId: childId, data: childNode.data as FeatureNodeData });
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
const rollback = () => {
|
|
297
|
+
if (prevRepoData) addRepositoryToMap(repoNodeId, prevRepoData);
|
|
298
|
+
for (const [childId, entry] of childSnapshots) {
|
|
299
|
+
restoreFeature(childId, entry);
|
|
300
|
+
}
|
|
301
|
+
};
|
|
302
|
+
|
|
303
|
+
// Optimistic: remove repo + children
|
|
304
|
+
removeRepository(repoNodeId);
|
|
305
|
+
for (const childId of childFeatureIds) {
|
|
306
|
+
removeFeature(childId);
|
|
307
|
+
}
|
|
408
308
|
|
|
409
309
|
try {
|
|
410
310
|
const result = await deleteRepository(repositoryId);
|
|
411
|
-
|
|
412
311
|
if (!result.success) {
|
|
413
312
|
toast.error(result.error ?? 'Failed to remove repository');
|
|
414
|
-
|
|
415
|
-
setEdges(prevEdges);
|
|
313
|
+
rollback();
|
|
416
314
|
return;
|
|
417
315
|
}
|
|
418
|
-
|
|
419
316
|
deleteSound.play();
|
|
420
317
|
toast.success('Repository removed');
|
|
421
318
|
} catch {
|
|
422
319
|
toast.error('Failed to remove repository');
|
|
423
|
-
|
|
424
|
-
setEdges(prevEdges);
|
|
320
|
+
rollback();
|
|
425
321
|
}
|
|
426
322
|
},
|
|
427
|
-
[
|
|
323
|
+
[
|
|
324
|
+
edges,
|
|
325
|
+
nodes,
|
|
326
|
+
deleteSound,
|
|
327
|
+
removeRepository,
|
|
328
|
+
removeFeature,
|
|
329
|
+
addRepositoryToMap,
|
|
330
|
+
restoreFeature,
|
|
331
|
+
getRepositoryData,
|
|
332
|
+
]
|
|
428
333
|
);
|
|
429
334
|
|
|
430
335
|
const handleLayout = useCallback(
|
|
431
336
|
(direction: LayoutDirection) => {
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
});
|
|
437
|
-
setEdges(result.edges);
|
|
438
|
-
return result.nodes;
|
|
439
|
-
});
|
|
337
|
+
// Layout is applied via reconcile on next server prop update.
|
|
338
|
+
// For immediate re-layout, we apply dagre and trigger a reconcile-like update.
|
|
339
|
+
const result = layoutWithDagre(nodes, edges, { ...CANVAS_LAYOUT_DEFAULTS, direction });
|
|
340
|
+
reconcile(result.nodes, result.edges);
|
|
440
341
|
},
|
|
441
|
-
[
|
|
342
|
+
[nodes, edges, reconcile]
|
|
442
343
|
);
|
|
443
344
|
|
|
444
345
|
const handleAddRepository = useCallback(
|
|
@@ -450,81 +351,30 @@ export function useControlCenterState(
|
|
|
450
351
|
.split(/[\\/]/)
|
|
451
352
|
.pop() ?? path;
|
|
452
353
|
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
const newNode = {
|
|
456
|
-
id: tempId,
|
|
457
|
-
type: 'repositoryNode' as const,
|
|
458
|
-
position: { x: 0, y: 0 },
|
|
459
|
-
data: { name: repoName, repositoryPath: path, id: tempId },
|
|
460
|
-
} as CanvasNodeType;
|
|
461
|
-
|
|
462
|
-
const allNodes = [...currentNodes, newNode];
|
|
463
|
-
const layoutResult = layoutWithDagre(allNodes, edgesRef.current, CANVAS_LAYOUT_DEFAULTS);
|
|
464
|
-
setEdges(layoutResult.edges);
|
|
465
|
-
return layoutResult.nodes;
|
|
466
|
-
});
|
|
467
|
-
|
|
468
|
-
// Persist via server action
|
|
354
|
+
addRepositoryToMap(tempId, { name: repoName, repositoryPath: path, id: tempId });
|
|
355
|
+
|
|
469
356
|
addRepository({ path, name: repoName })
|
|
470
357
|
.then((result) => {
|
|
471
358
|
if (result.error) {
|
|
472
|
-
|
|
473
|
-
setNodes((prev) => {
|
|
474
|
-
const remaining = prev.filter((n) => n.id !== tempId);
|
|
475
|
-
const layoutResult = layoutWithDagre(
|
|
476
|
-
remaining,
|
|
477
|
-
edgesRef.current,
|
|
478
|
-
CANVAS_LAYOUT_DEFAULTS
|
|
479
|
-
);
|
|
480
|
-
setEdges(layoutResult.edges);
|
|
481
|
-
return layoutResult.nodes;
|
|
482
|
-
});
|
|
359
|
+
removeRepository(tempId);
|
|
483
360
|
toast.error(result.error);
|
|
484
361
|
return;
|
|
485
362
|
}
|
|
486
|
-
|
|
487
|
-
// Replace temp ID with real repository ID
|
|
488
363
|
const repo = result.repository!;
|
|
489
364
|
const realId = `repo-${repo.id}`;
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
id: realId,
|
|
496
|
-
data: { ...n.data, id: repo.id, repositoryPath: repo.path },
|
|
497
|
-
} as CanvasNodeType)
|
|
498
|
-
: n
|
|
499
|
-
)
|
|
500
|
-
);
|
|
501
|
-
setEdges((prev) =>
|
|
502
|
-
prev.map((e) => ({
|
|
503
|
-
...e,
|
|
504
|
-
source: e.source === tempId ? realId : e.source,
|
|
505
|
-
target: e.target === tempId ? realId : e.target,
|
|
506
|
-
id: e.id.replace(tempId, realId),
|
|
507
|
-
}))
|
|
508
|
-
);
|
|
509
|
-
|
|
365
|
+
replaceRepository(tempId, realId, {
|
|
366
|
+
name: repo.name,
|
|
367
|
+
repositoryPath: repo.path,
|
|
368
|
+
id: repo.id,
|
|
369
|
+
});
|
|
510
370
|
createSound.play();
|
|
511
371
|
})
|
|
512
372
|
.catch(() => {
|
|
513
|
-
|
|
514
|
-
setNodes((prev) => {
|
|
515
|
-
const remaining = prev.filter((n) => n.id !== tempId);
|
|
516
|
-
const layoutResult = layoutWithDagre(
|
|
517
|
-
remaining,
|
|
518
|
-
edgesRef.current,
|
|
519
|
-
CANVAS_LAYOUT_DEFAULTS
|
|
520
|
-
);
|
|
521
|
-
setEdges(layoutResult.edges);
|
|
522
|
-
return layoutResult.nodes;
|
|
523
|
-
});
|
|
373
|
+
removeRepository(tempId);
|
|
524
374
|
toast.error('Failed to add repository');
|
|
525
375
|
});
|
|
526
376
|
},
|
|
527
|
-
[
|
|
377
|
+
[addRepositoryToMap, removeRepository, replaceRepository, createSound]
|
|
528
378
|
);
|
|
529
379
|
|
|
530
380
|
return {
|
|
@@ -537,5 +387,8 @@ export function useControlCenterState(
|
|
|
537
387
|
handleDeleteFeature,
|
|
538
388
|
handleDeleteRepository,
|
|
539
389
|
createFeatureNode,
|
|
390
|
+
getFeatureRepositoryPath,
|
|
391
|
+
getRepositoryData,
|
|
392
|
+
setCallbacks,
|
|
540
393
|
};
|
|
541
394
|
}
|