@shepai/cli 1.72.8 → 1.72.9
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/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/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 +3 -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 +9 -8
- 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/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 +95 -1
- 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 +2 -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 +3 -3
- 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 +3 -3
- 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 +3 -3
- 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 +3 -3
- 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 +3 -3
- 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 +3 -3
- 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 +3 -3
- 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_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_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_3a02d8a5.js +3 -0
- package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_@drawer_repository_[repositoryId]_page_actions_3a02d8a5.js.map +1 -0
- package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_repository_[repositoryId]_page_actions_a3044852.js +3 -0
- package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_repository_[repositoryId]_page_actions_a3044852.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]__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/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/[root-of-the-server]__cbae9863._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__cbae9863._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__e5e09f72._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__e5e09f72._.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/{_47ef589d._.js → _38d24563._.js} +2 -2
- package/web/.next/server/chunks/ssr/{_47ef589d._.js.map → _38d24563._.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/_6e08ce21._.js +3 -0
- package/web/.next/server/chunks/ssr/_6e08ce21._.js.map +1 -0
- 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/{standalone/src/presentation/web/.next/server/chunks/ssr/src_presentation_web_1a32dbcb._.js → server/chunks/ssr/src_presentation_web_0a49d9ee._.js} +3 -3
- package/web/.next/server/chunks/ssr/{src_presentation_web_1a32dbcb._.js.map → src_presentation_web_0a49d9ee._.js.map} +1 -1
- package/web/.next/server/chunks/ssr/{src_presentation_web_398553b0._.js → src_presentation_web_5ea689db._.js} +2 -2
- package/web/.next/server/chunks/ssr/{src_presentation_web_398553b0._.js.map → src_presentation_web_5ea689db._.js.map} +1 -1
- package/web/.next/{standalone/src/presentation/web/.next/server/chunks/ssr/src_presentation_web_398553b0._.js → server/chunks/ssr/src_presentation_web_7188a290._.js} +2 -2
- package/web/.next/server/chunks/ssr/{src_presentation_web_5c87e8e4._.js.map → src_presentation_web_7188a290._.js.map} +1 -1
- package/web/.next/server/chunks/ssr/{src_presentation_web_1a32dbcb._.js → src_presentation_web_79b0305a._.js} +3 -3
- package/web/.next/server/chunks/ssr/{src_presentation_web_c1bc6240._.js.map → src_presentation_web_79b0305a._.js.map} +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_cc16bd01.js +3 -0
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_cc16bd01.js.map +1 -0
- package/web/.next/server/chunks/ssr/src_presentation_web_app_(dashboard)_get-graph-data_ts_b018483e._.js +3 -0
- package/web/.next/server/chunks/ssr/src_presentation_web_app_(dashboard)_get-graph-data_ts_b018483e._.js.map +1 -0
- 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/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 +3 -3
- 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 +3 -3
- 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 +3 -3
- 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 +3 -3
- 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 +3 -3
- 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 +3 -3
- 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 +3 -3
- 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_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_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_3a02d8a5.js +3 -0
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_repository_[repositoryId]_page_actions_a3044852.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]__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/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/[root-of-the-server]__cbae9863._.js +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__e5e09f72._.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/{_47ef589d._.js → _38d24563._.js} +2 -2
- 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/_6e08ce21._.js +3 -0
- 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/{server/chunks/ssr/src_presentation_web_c1bc6240._.js → standalone/src/presentation/web/.next/server/chunks/ssr/src_presentation_web_0a49d9ee._.js} +3 -3
- package/web/.next/{server/chunks/ssr/src_presentation_web_5c87e8e4._.js → standalone/src/presentation/web/.next/server/chunks/ssr/src_presentation_web_5ea689db._.js} +2 -2
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/{src_presentation_web_5c87e8e4._.js → src_presentation_web_7188a290._.js} +2 -2
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/{src_presentation_web_c1bc6240._.js → src_presentation_web_79b0305a._.js} +3 -3
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_cc16bd01.js +3 -0
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/src_presentation_web_app_(dashboard)_get-graph-data_ts_b018483e._.js +3 -0
- 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/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 +147 -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 +4 -1
- package/web/.next/standalone/src/presentation/web/components/common/control-center-drawer/create-drawer-client.tsx +9 -8
- 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/features/control-center/use-control-center-state.ts +107 -1
- package/web/.next/standalone/src/presentation/web/components/features/features-canvas/features-canvas.tsx +21 -23
- package/web/.next/standalone/src/presentation/web/server.js +1 -1
- package/web/.next/static/chunks/{ebf172a84c9596ed.js → 10cd08dae8c210ff.js} +1 -1
- package/web/.next/static/chunks/{5cd24ca47061a21d.js → 15bf7ee1da91eb46.js} +1 -1
- package/web/.next/static/chunks/{8682dcb376de62de.js → 64850cf4081a2950.js} +1 -1
- package/web/.next/static/chunks/{71cf72022f08a8c9.js → 6cc840197626843b.js} +1 -1
- package/web/.next/static/chunks/{1c07b21eb8b32f25.js → c83897e9213881bf.js} +1 -1
- package/web/.next/static/chunks/{fcafb841e3860687.js → d4492cd12fdf0891.js} +1 -1
- package/web/.next/static/chunks/{c71589df79020ecb.js → e3239b6c18cf8b96.js} +1 -1
- package/web/.next/static/chunks/{fabfa54940973cc7.js → e9cc53ce8a7bdea6.js} +1 -1
- package/web/.next/static/chunks/ef916db8c537211a.js +1 -0
- package/web/.next/trace +1 -1
- package/web/.next/trace-build +1 -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/_250a63ae._.js +0 -3
- package/web/.next/server/chunks/ssr/_250a63ae._.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_ca99d62d._.js +0 -3
- package/web/.next/server/chunks/ssr/src_presentation_web_ca99d62d._.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/_250a63ae._.js +0 -3
- 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_ca99d62d._.js +0 -3
- package/web/.next/static/chunks/991d4490d7a338d8.js +0 -1
- /package/web/.next/static/{IKuYPxAuMvc4BtwKHlj30 → Atrl1oUfRQej2kgJ972uS}/_buildManifest.js +0 -0
- /package/web/.next/static/{IKuYPxAuMvc4BtwKHlj30 → Atrl1oUfRQej2kgJ972uS}/_clientMiddlewareManifest.json +0 -0
- /package/web/.next/static/{IKuYPxAuMvc4BtwKHlj30 → Atrl1oUfRQej2kgJ972uS}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
# Web UI Development Notes
|
|
2
|
+
|
|
3
|
+
## Running the UI
|
|
4
|
+
|
|
5
|
+
There are two distinct ways to run the web UI. **Always test in BOTH modes.**
|
|
6
|
+
|
|
7
|
+
### 1. Dev Mode (local development)
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
pnpm dev:web
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
- Uses `dev-server.ts` which initializes the DI container and starts Next.js in dev mode
|
|
14
|
+
- Turbopack HMR enabled
|
|
15
|
+
- Runs on port 3000 by default
|
|
16
|
+
|
|
17
|
+
### 2. Production Mode (how users run it)
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
shep ui
|
|
21
|
+
# or
|
|
22
|
+
pnpm dev:cli ui
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
- The CLI bootstraps the DI container (`src/presentation/cli/index.ts`), then starts Next.js via `WebServerService`
|
|
26
|
+
- Runs on port 4050 by default
|
|
27
|
+
- This is how real users experience the UI
|
|
28
|
+
- **IMPORTANT**: Always test real-time features in this mode, not just dev mode
|
|
29
|
+
|
|
30
|
+
### Key Differences Between Modes
|
|
31
|
+
|
|
32
|
+
| Aspect | Dev Mode (`pnpm dev:web`) | Production Mode (`shep ui`) |
|
|
33
|
+
| ------------------ | ------------------------------------------------------- | ------------------------------------------------------- |
|
|
34
|
+
| Entry point | `dev-server.ts` | `cli/index.ts` -> `ui.command.ts` -> `WebServerService` |
|
|
35
|
+
| Port | 3000 | 4050 |
|
|
36
|
+
| DI container | Set on `globalThis.__shepContainer` in dev-server.ts:73 | Set in cli/index.ts:76 |
|
|
37
|
+
| WebSocket upgrades | Forwarded (HMR works) | NOT forwarded in `WebServerService` |
|
|
38
|
+
| Next.js mode | Always dev | dev when run from source, prod when installed |
|
|
39
|
+
|
|
40
|
+
## SSE / Real-Time Update Architecture
|
|
41
|
+
|
|
42
|
+
```
|
|
43
|
+
DB polling (500ms) -> /api/agent-events (SSE route)
|
|
44
|
+
-> Service Worker (public/agent-events-sw.js, single connection)
|
|
45
|
+
-> postMessage to all browser tabs
|
|
46
|
+
-> useAgentEvents hook (hooks/use-agent-events.ts)
|
|
47
|
+
-> AgentEventsProvider context (hooks/agent-events-provider.tsx)
|
|
48
|
+
-> useControlCenterState (optimistic node updates via setNodes)
|
|
49
|
+
-> React state updates -> sidebar + React Flow canvas
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### SSE Key Files
|
|
53
|
+
|
|
54
|
+
| File | Purpose |
|
|
55
|
+
| ---------------------------------------------------------------- | ------------------------------------------------------ |
|
|
56
|
+
| `app/api/agent-events/route.ts` | SSE endpoint, polls DB every 500ms, emits delta events |
|
|
57
|
+
| `app/api/agent-events/health/route.ts` | Health check: `/api/agent-events/health` |
|
|
58
|
+
| `public/agent-events-sw.js` | Service Worker: multiplexes single SSE to all tabs |
|
|
59
|
+
| `hooks/use-agent-events.ts` | Client hook: registers with SW, receives events |
|
|
60
|
+
| `hooks/agent-events-provider.tsx` | React context wrapping `useAgentEvents` |
|
|
61
|
+
| `components/features/control-center/use-control-center-state.ts` | Processes SSE events into React Flow node updates |
|
|
62
|
+
| `components/common/feature-node/derive-feature-state.ts` | Maps event types/phases to UI state/lifecycle |
|
|
63
|
+
|
|
64
|
+
### SSE Event Flow Details
|
|
65
|
+
|
|
66
|
+
1. **SSE route** seeds a per-connection cache on first poll (no events emitted for initial state)
|
|
67
|
+
2. Subsequent polls compare DB state against cache, emit only deltas
|
|
68
|
+
3. **Service Worker** connects to `/api/agent-events` via EventSource on first subscriber
|
|
69
|
+
4. SW broadcasts `{ type: 'notification', data }` to all tabs via `clients.matchAll()`
|
|
70
|
+
5. **useControlCenterState** effect processes new events, calls `setNodes()` to update node state/lifecycle
|
|
71
|
+
6. **Polling fallback** (5s interval) fetches via `fetchGraphData()` server action for active features
|
|
72
|
+
|
|
73
|
+
### SSE Lifecycle Mappings
|
|
74
|
+
|
|
75
|
+
The SSE route maps `SdlcLifecycle` enum -> agent graph node names -> client `FeatureLifecyclePhase`:
|
|
76
|
+
|
|
77
|
+
```
|
|
78
|
+
SdlcLifecycle.Started -> 'requirements' -> 'requirements'
|
|
79
|
+
SdlcLifecycle.Analyze -> 'analyze' -> 'requirements'
|
|
80
|
+
SdlcLifecycle.Requirements-> 'requirements' -> 'requirements'
|
|
81
|
+
SdlcLifecycle.Research -> 'research' -> 'research'
|
|
82
|
+
SdlcLifecycle.Planning -> 'plan' -> 'implementation'
|
|
83
|
+
SdlcLifecycle.Implementation -> 'implement' -> 'implementation'
|
|
84
|
+
SdlcLifecycle.Review -> 'merge' -> 'review'
|
|
85
|
+
SdlcLifecycle.Maintain -> 'maintain' -> 'maintain'
|
|
86
|
+
SdlcLifecycle.Blocked -> 'blocked' -> 'requirements'
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## React Flow Rendering (CRITICAL)
|
|
90
|
+
|
|
91
|
+
React Flow v12 (`@xyflow/react` ^12.10.0) has specific behaviors that affect real-time updates:
|
|
92
|
+
|
|
93
|
+
- **Controlled mode**: `<ReactFlow nodes={nodes}>` passes nodes as props
|
|
94
|
+
- **Internal Zustand store**: React Flow syncs props to an internal `nodeLookup` Map via `StoreUpdater`
|
|
95
|
+
- **Memoized NodeWrapper**: Each node is wrapped in `memo(NodeWrapper)` which subscribes to store via `useStore(selector, shallow)`
|
|
96
|
+
- **NodeWrapper gets node from store**, NOT from props directly. It does `s.nodeLookup.get(id)` with `shallow` comparison
|
|
97
|
+
- **Single ReactFlowProvider**: There must be exactly ONE `ReactFlowProvider` ancestor. Multiple nested providers create separate stores, causing the outer one's `StoreUpdater` to sync nodes to a store that the inner components don't read from
|
|
98
|
+
|
|
99
|
+
### Circular Update Loop (FIXED — do not reintroduce)
|
|
100
|
+
|
|
101
|
+
In controlled mode, `enrichedNodes` (useMemo in FeaturesCanvas) creates new node objects every render
|
|
102
|
+
(adding callbacks to `data`). StoreUpdater sees different references and emits `replace` changes via
|
|
103
|
+
`onNodesChange`. If `onNodesChange` applies these 'replace' changes back to state via `applyNodeChanges`,
|
|
104
|
+
it overwrites SSE-driven state updates with stale data from the previous render, AND triggers another
|
|
105
|
+
`enrichedNodes` recalculation → infinite loop (110+ renders on page load).
|
|
106
|
+
|
|
107
|
+
**Fix**: `onNodesChange` in `use-control-center-state.ts` filters out `replace` changes. Only `dimensions`,
|
|
108
|
+
`position`, `select`, etc. are applied. StoreUpdater still syncs props to its internal store regardless —
|
|
109
|
+
our state remains the source of truth.
|
|
110
|
+
|
|
111
|
+
**NEVER** remove the `c.type !== 'replace'` filter from `onNodesChange`.
|
|
112
|
+
|
|
113
|
+
## Testing Real-Time Updates
|
|
114
|
+
|
|
115
|
+
1. Start the UI in the mode you want to test
|
|
116
|
+
2. Check SSE health: `curl http://localhost:<port>/api/agent-events/health`
|
|
117
|
+
3. Check SW status in browser: `navigator.serviceWorker.controller?.state` should be "activated"
|
|
118
|
+
4. Trigger state changes: `pnpm dev:cli feat approve <id>` or start a new feature run
|
|
119
|
+
5. Watch both **sidebar** and **canvas nodes** - they should both update
|
|
120
|
+
6. Check browser console for errors
|
|
121
|
+
7. Check server logs for `[SSE] emit:` messages confirming events are sent
|
|
122
|
+
|
|
123
|
+
## Optimistic Feature Creation Flow
|
|
124
|
+
|
|
125
|
+
When a user creates a feature, the UI uses optimistic updates:
|
|
126
|
+
|
|
127
|
+
1. **Create drawer** dispatches `shep:feature-created` → canvas adds a temp node (`feature-<ts>` ID, state `creating`)
|
|
128
|
+
2. Drawer closes immediately via `router.push('/')`
|
|
129
|
+
3. Server action `createFeature` runs in background → agent starts
|
|
130
|
+
4. SSE events arrive with real feature ID (`feat-<uuid>`) — **these won't match the temp node**
|
|
131
|
+
5. **Polling fallback** (5s) detects new server node → replaces temp `creating` node in-place
|
|
132
|
+
|
|
133
|
+
### Key constraints
|
|
134
|
+
|
|
135
|
+
- **Temp node IDs don't match SSE events**: Optimistic nodes use `feature-<ts>` IDs, server uses `feat-<uuid>`.
|
|
136
|
+
SSE-driven `setNodes()` can't find the temp node. The polling fallback handles the swap.
|
|
137
|
+
- **Create drawer `isSubmitting`**: Must NOT reset until pathname leaves `/create`. Resetting in `.finally()`
|
|
138
|
+
causes the drawer to flash open because `router.push('/')` is async and pathname hasn't changed yet.
|
|
139
|
+
- **Parallel routes preserve state**: The `CreateDrawerClient` component is NOT unmounted on navigation.
|
|
140
|
+
`isOpen` is derived from pathname, not mount/unmount lifecycle.
|
|
141
|
+
|
|
142
|
+
## Common Pitfalls
|
|
143
|
+
|
|
144
|
+
- **No events when nothing changes**: SSE only emits deltas. If no feature state changes, no events are sent. This is correct behavior.
|
|
145
|
+
- **Polling fallback dependency**: The 5s polling `useEffect` depends on a derived `hasActiveFeature` boolean (not `nodes` directly). Using `[nodes]` as a dependency would reset the interval on every node change, potentially preventing it from ever firing.
|
|
146
|
+
- **Storybook mocks**: New server actions need mocks in `.storybook/mocks/app/actions/` or Storybook build breaks.
|
|
147
|
+
- **`output: 'standalone'`** in next.config.ts: Production builds use standalone mode. Route handlers are bundled differently.
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
'use server';
|
|
2
|
+
|
|
3
|
+
import { getGraphData } from '@/app/(dashboard)/get-graph-data';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Server action that fetches fresh graph nodes and edges.
|
|
7
|
+
* Used as a lightweight polling fallback for active features,
|
|
8
|
+
* avoiding full router.refresh() page re-renders.
|
|
9
|
+
*/
|
|
10
|
+
export async function fetchGraphData() {
|
|
11
|
+
return getGraphData();
|
|
12
|
+
}
|
|
@@ -44,13 +44,16 @@ interface CachedFeatureState {
|
|
|
44
44
|
* Maps SdlcLifecycle values to agent graph node names so the client
|
|
45
45
|
* can derive the correct FeatureLifecyclePhase via mapPhaseNameToLifecycle().
|
|
46
46
|
*/
|
|
47
|
-
const LIFECYCLE_TO_NODE:
|
|
47
|
+
const LIFECYCLE_TO_NODE: Record<SdlcLifecycle, string> = {
|
|
48
|
+
[SdlcLifecycle.Started]: 'requirements',
|
|
48
49
|
[SdlcLifecycle.Analyze]: 'analyze',
|
|
49
50
|
[SdlcLifecycle.Requirements]: 'requirements',
|
|
50
51
|
[SdlcLifecycle.Research]: 'research',
|
|
51
52
|
[SdlcLifecycle.Planning]: 'plan',
|
|
52
53
|
[SdlcLifecycle.Implementation]: 'implement',
|
|
53
54
|
[SdlcLifecycle.Review]: 'merge',
|
|
55
|
+
[SdlcLifecycle.Maintain]: 'maintain',
|
|
56
|
+
[SdlcLifecycle.Blocked]: 'blocked',
|
|
54
57
|
};
|
|
55
58
|
|
|
56
59
|
const STATUS_TO_EVENT: Partial<
|
|
@@ -34,15 +34,17 @@ export function CreateDrawerClient({
|
|
|
34
34
|
// When submitting, force the drawer closed immediately — router.push('/')
|
|
35
35
|
// is async and the pathname may not update before the next render.
|
|
36
36
|
const pathname = usePathname();
|
|
37
|
-
const
|
|
37
|
+
const isOnCreateRoute = pathname.startsWith('/create');
|
|
38
|
+
const isOpen = !isSubmitting && isOnCreateRoute;
|
|
38
39
|
|
|
39
|
-
//
|
|
40
|
-
//
|
|
40
|
+
// Reset isSubmitting once the route has actually changed away from /create,
|
|
41
|
+
// so the drawer can reopen on future visits. Without this, isSubmitting
|
|
42
|
+
// would stay true forever since parallel routes preserve component state.
|
|
41
43
|
useEffect(() => {
|
|
42
|
-
if (!
|
|
43
|
-
|
|
44
|
+
if (!isOnCreateRoute && isSubmitting) {
|
|
45
|
+
setIsSubmitting(false);
|
|
44
46
|
}
|
|
45
|
-
}, [
|
|
47
|
+
}, [isOnCreateRoute, isSubmitting]);
|
|
46
48
|
|
|
47
49
|
const onClose = useCallback(() => {
|
|
48
50
|
router.push('/');
|
|
@@ -81,8 +83,7 @@ export function CreateDrawerClient({
|
|
|
81
83
|
.catch(() => {
|
|
82
84
|
toast.error('Failed to create feature');
|
|
83
85
|
window.dispatchEvent(new CustomEvent('shep:feature-create-failed'));
|
|
84
|
-
|
|
85
|
-
.finally(() => {
|
|
86
|
+
// Reset on error so the user can retry without navigating away
|
|
86
87
|
setIsSubmitting(false);
|
|
87
88
|
});
|
|
88
89
|
},
|
|
@@ -120,6 +120,8 @@ const phaseNameToLifecycle: Record<string, FeatureLifecyclePhase> = {
|
|
|
120
120
|
plan: 'implementation',
|
|
121
121
|
implement: 'implementation',
|
|
122
122
|
merge: 'review',
|
|
123
|
+
maintain: 'maintain',
|
|
124
|
+
blocked: 'requirements',
|
|
123
125
|
};
|
|
124
126
|
|
|
125
127
|
export function mapPhaseNameToLifecycle(
|
|
@@ -15,6 +15,7 @@ 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 { fetchGraphData } from '@/app/actions/get-graph-data';
|
|
18
19
|
import { useAgentEventsContext } from '@/hooks/agent-events-provider';
|
|
19
20
|
import { useSoundAction } from '@/hooks/use-sound-action';
|
|
20
21
|
import {
|
|
@@ -206,6 +207,7 @@ export function useControlCenterState(
|
|
|
206
207
|
if (node.type !== 'featureNode') return node;
|
|
207
208
|
const data = node.data as FeatureNodeData;
|
|
208
209
|
if (data.featureId !== event.featureId) return node;
|
|
210
|
+
|
|
209
211
|
return {
|
|
210
212
|
...node,
|
|
211
213
|
data: {
|
|
@@ -219,8 +221,112 @@ export function useControlCenterState(
|
|
|
219
221
|
}
|
|
220
222
|
}, [events]);
|
|
221
223
|
|
|
224
|
+
// Lightweight server-action polling fallback: fetches fresh graph data every 5s
|
|
225
|
+
// when any feature is in an active state. This avoids full router.refresh() while
|
|
226
|
+
// ensuring the UI stays in sync even if SSE events are missed.
|
|
227
|
+
//
|
|
228
|
+
// We derive a stable boolean so the interval isn't torn down on every node change.
|
|
229
|
+
const hasActiveFeature = nodes.some((n) => {
|
|
230
|
+
if (n.type !== 'featureNode') return false;
|
|
231
|
+
const data = n.data as FeatureNodeData;
|
|
232
|
+
return (
|
|
233
|
+
data.state === 'running' || data.state === 'action-required' || data.state === 'creating'
|
|
234
|
+
);
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
useEffect(() => {
|
|
238
|
+
if (!hasActiveFeature) return;
|
|
239
|
+
|
|
240
|
+
const interval = setInterval(async () => {
|
|
241
|
+
try {
|
|
242
|
+
const { nodes: serverNodes } = await fetchGraphData();
|
|
243
|
+
setNodes((currentNodes) => {
|
|
244
|
+
const serverById = new Map(serverNodes.map((n) => [n.id, n]));
|
|
245
|
+
let changed = false;
|
|
246
|
+
|
|
247
|
+
const merged = currentNodes.map((node) => {
|
|
248
|
+
const serverNode = serverById.get(node.id);
|
|
249
|
+
if (!serverNode || node.type !== 'featureNode') return node;
|
|
250
|
+
const currentData = node.data as FeatureNodeData;
|
|
251
|
+
const serverData = serverNode.data as FeatureNodeData;
|
|
252
|
+
|
|
253
|
+
// Only update if server data has different state or lifecycle
|
|
254
|
+
if (
|
|
255
|
+
currentData.state === serverData.state &&
|
|
256
|
+
currentData.lifecycle === serverData.lifecycle
|
|
257
|
+
) {
|
|
258
|
+
return node;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
changed = true;
|
|
262
|
+
return {
|
|
263
|
+
...node,
|
|
264
|
+
data: {
|
|
265
|
+
...currentData,
|
|
266
|
+
state: serverData.state,
|
|
267
|
+
lifecycle: serverData.lifecycle,
|
|
268
|
+
progress: serverData.progress,
|
|
269
|
+
...(serverData.errorMessage && { errorMessage: serverData.errorMessage }),
|
|
270
|
+
...(serverData.runtime && { runtime: serverData.runtime }),
|
|
271
|
+
...(serverData.agentType && { agentType: serverData.agentType }),
|
|
272
|
+
...(serverData.pr && { pr: serverData.pr }),
|
|
273
|
+
...(serverData.blockedBy && { blockedBy: serverData.blockedBy }),
|
|
274
|
+
},
|
|
275
|
+
};
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
// Find new server nodes not yet on the client
|
|
279
|
+
const clientIds = new Set(currentNodes.map((n) => n.id));
|
|
280
|
+
const newServerNodes = serverNodes.filter((n) => !clientIds.has(n.id));
|
|
281
|
+
|
|
282
|
+
// Replace optimistic "creating" temp nodes with their real server
|
|
283
|
+
// counterparts. Temp nodes have IDs like "feature-<ts>" while real
|
|
284
|
+
// nodes use "feat-<uuid>". Match by repositoryPath + name.
|
|
285
|
+
if (newServerNodes.length > 0) {
|
|
286
|
+
const creatingIndices: number[] = [];
|
|
287
|
+
merged.forEach((n, i) => {
|
|
288
|
+
if (n.type === 'featureNode' && (n.data as FeatureNodeData).state === 'creating') {
|
|
289
|
+
creatingIndices.push(i);
|
|
290
|
+
}
|
|
291
|
+
});
|
|
292
|
+
|
|
293
|
+
for (const serverNode of newServerNodes) {
|
|
294
|
+
if (serverNode.type !== 'featureNode' || creatingIndices.length === 0) continue;
|
|
295
|
+
const idx = creatingIndices.shift()!;
|
|
296
|
+
// Replace the temp node in-place, keeping its position
|
|
297
|
+
merged[idx] = { ...serverNode, position: merged[idx].position };
|
|
298
|
+
changed = true;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
// Any remaining new server nodes that didn't replace a temp node
|
|
302
|
+
const replacedIds = new Set(merged.map((n) => n.id));
|
|
303
|
+
const trueNewNodes = newServerNodes.filter((n) => !replacedIds.has(n.id));
|
|
304
|
+
if (trueNewNodes.length > 0) {
|
|
305
|
+
changed = true;
|
|
306
|
+
return [...merged, ...trueNewNodes];
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
return changed ? merged : currentNodes;
|
|
311
|
+
});
|
|
312
|
+
} catch {
|
|
313
|
+
// Silently ignore polling errors — SSE is the primary mechanism
|
|
314
|
+
}
|
|
315
|
+
}, 5_000);
|
|
316
|
+
|
|
317
|
+
return () => clearInterval(interval);
|
|
318
|
+
}, [hasActiveFeature]);
|
|
319
|
+
|
|
222
320
|
const onNodesChange = useCallback((changes: NodeChange<CanvasNodeType>[]) => {
|
|
223
|
-
|
|
321
|
+
// Filter out 'replace' changes — in controlled mode these come from
|
|
322
|
+
// React Flow's StoreUpdater syncing the nodes prop back into state.
|
|
323
|
+
// Applying them creates a circular update loop (nodes → enrichedNodes →
|
|
324
|
+
// StoreUpdater → onNodesChange → setNodes → nodes → …) that both causes
|
|
325
|
+
// excessive re-renders and overwrites SSE-driven state changes with stale data.
|
|
326
|
+
const applicable = changes.filter((c) => c.type !== 'replace');
|
|
327
|
+
if (applicable.length > 0) {
|
|
328
|
+
setNodes((ns) => applyNodeChanges(applicable, ns));
|
|
329
|
+
}
|
|
224
330
|
}, []);
|
|
225
331
|
|
|
226
332
|
const handleConnect = useCallback(
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
3
|
import { useCallback, useMemo } from 'react';
|
|
4
|
-
import { ReactFlow, Background, Controls
|
|
4
|
+
import { ReactFlow, Background, Controls } from '@xyflow/react';
|
|
5
5
|
import type { Connection, Edge, NodeChange } from '@xyflow/react';
|
|
6
6
|
import { Plus } from 'lucide-react';
|
|
7
7
|
import { Button } from '@/components/ui/button';
|
|
@@ -163,28 +163,26 @@ export function FeaturesCanvas({
|
|
|
163
163
|
data-no-drawer-close
|
|
164
164
|
className="pointer-events-auto h-full w-full"
|
|
165
165
|
>
|
|
166
|
-
<
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
</ReactFlow>
|
|
187
|
-
</ReactFlowProvider>
|
|
166
|
+
<ReactFlow
|
|
167
|
+
nodes={enrichedNodes}
|
|
168
|
+
edges={edges}
|
|
169
|
+
nodeTypes={nodeTypes}
|
|
170
|
+
edgeTypes={edgeTypes}
|
|
171
|
+
isValidConnection={isValidConnection}
|
|
172
|
+
onConnect={onConnect}
|
|
173
|
+
onNodesChange={onNodesChange}
|
|
174
|
+
onNodeClick={onNodeClick}
|
|
175
|
+
onPaneClick={onPaneClick}
|
|
176
|
+
onMoveStart={onCanvasDrag}
|
|
177
|
+
defaultViewport={{ x: 30, y: 30, zoom: 0.85 }}
|
|
178
|
+
nodesDraggable={false}
|
|
179
|
+
nodesConnectable={false}
|
|
180
|
+
elementsSelectable={false}
|
|
181
|
+
>
|
|
182
|
+
<Background />
|
|
183
|
+
<Controls />
|
|
184
|
+
{toolbar}
|
|
185
|
+
</ReactFlow>
|
|
188
186
|
</div>
|
|
189
187
|
);
|
|
190
188
|
}
|
|
@@ -15,7 +15,7 @@ const currentPort = parseInt(process.env.PORT, 10) || 3000
|
|
|
15
15
|
const hostname = process.env.HOSTNAME || '0.0.0.0'
|
|
16
16
|
|
|
17
17
|
let keepAliveTimeout = parseInt(process.env.KEEP_ALIVE_TIMEOUT, 10)
|
|
18
|
-
const nextConfig = {"env":{"NEXT_PUBLIC_SHEP_VERSION":"1.72.
|
|
18
|
+
const nextConfig = {"env":{"NEXT_PUBLIC_SHEP_VERSION":"1.72.8","NEXT_PUBLIC_SHEP_PACKAGE_NAME":"@shepai/cli","NEXT_PUBLIC_SHEP_DESCRIPTION":"Autonomous AI Native SDLC Platform - Automate the development cycle from idea to deploy"},"webpack":null,"typescript":{"ignoreBuildErrors":false},"typedRoutes":true,"distDir":"./.next","cleanDistDir":true,"assetPrefix":"","cacheMaxMemorySize":52428800,"configOrigin":"next.config.ts","useFileSystemPublicRoutes":true,"generateEtags":true,"pageExtensions":["tsx","ts","jsx","js"],"poweredByHeader":true,"compress":true,"images":{"deviceSizes":[640,750,828,1080,1200,1920,2048,3840],"imageSizes":[32,48,64,96,128,256,384],"path":"/_next/image","loader":"default","loaderFile":"","domains":[],"disableStaticImages":false,"minimumCacheTTL":14400,"formats":["image/webp"],"maximumRedirects":3,"maximumResponseBody":50000000,"dangerouslyAllowLocalIP":false,"dangerouslyAllowSVG":false,"contentSecurityPolicy":"script-src 'none'; frame-src 'none'; sandbox;","contentDispositionType":"attachment","localPatterns":[{"pathname":"**","search":""}],"remotePatterns":[],"qualities":[75],"unoptimized":false},"devIndicators":{"position":"bottom-left"},"onDemandEntries":{"maxInactiveAge":60000,"pagesBufferLength":5},"basePath":"","sassOptions":{},"trailingSlash":false,"i18n":null,"productionBrowserSourceMaps":false,"excludeDefaultMomentLocales":true,"reactProductionProfiling":false,"reactStrictMode":null,"reactMaxHeadersLength":6000,"httpAgentOptions":{"keepAlive":true},"logging":{},"compiler":{},"expireTime":31536000,"staticPageGenerationTimeout":60,"output":"standalone","modularizeImports":{"@mui/icons-material":{"transform":"@mui/icons-material/{{member}}"},"lodash":{"transform":"lodash/{{member}}"}},"outputFileTracingRoot":"/home/runner/work/cli/cli","cacheComponents":false,"cacheLife":{"default":{"stale":300,"revalidate":900,"expire":4294967294},"seconds":{"stale":30,"revalidate":1,"expire":60},"minutes":{"stale":300,"revalidate":60,"expire":3600},"hours":{"stale":300,"revalidate":3600,"expire":86400},"days":{"stale":300,"revalidate":86400,"expire":604800},"weeks":{"stale":300,"revalidate":604800,"expire":2592000},"max":{"stale":300,"revalidate":2592000,"expire":31536000}},"cacheHandlers":{},"experimental":{"useSkewCookie":false,"cssChunking":true,"multiZoneDraftMode":false,"appNavFailHandling":false,"prerenderEarlyExit":true,"serverMinification":true,"linkNoTouchStart":false,"caseSensitiveRoutes":false,"dynamicOnHover":false,"preloadEntriesOnStart":true,"clientRouterFilter":true,"clientRouterFilterRedirects":false,"fetchCacheKeyPrefix":"","proxyPrefetch":"flexible","optimisticClientCache":true,"manualClientBasePath":false,"cpus":3,"memoryBasedWorkersCount":false,"imgOptConcurrency":null,"imgOptTimeoutInSeconds":7,"imgOptMaxInputPixels":268402689,"imgOptSequentialRead":null,"imgOptSkipMetadata":null,"isrFlushToDisk":true,"workerThreads":false,"optimizeCss":false,"nextScriptWorkers":false,"scrollRestoration":false,"externalDir":false,"disableOptimizedLoading":false,"gzipSize":true,"craCompat":false,"esmExternals":true,"fullySpecified":false,"swcTraceProfiling":false,"forceSwcTransforms":false,"largePageDataBytes":128000,"typedEnv":false,"parallelServerCompiles":false,"parallelServerBuildTraces":false,"ppr":false,"authInterrupts":false,"webpackMemoryOptimizations":false,"optimizeServerReact":true,"viewTransition":false,"removeUncaughtErrorAndRejectionListeners":false,"validateRSCRequestHeaders":false,"staleTimes":{"dynamic":0,"static":300},"reactDebugChannel":false,"serverComponentsHmrCache":true,"staticGenerationMaxConcurrency":8,"staticGenerationMinPagesPerWorker":25,"transitionIndicator":false,"inlineCss":false,"useCache":false,"globalNotFound":false,"browserDebugInfoInTerminal":false,"lockDistDir":true,"isolatedDevBuild":true,"proxyClientMaxBodySize":10485760,"hideLogsAfterAbort":false,"mcpServer":true,"turbopackFileSystemCacheForDev":true,"turbopackFileSystemCacheForBuild":false,"turbopackInferModuleSideEffects":false,"optimizePackageImports":["lucide-react","date-fns","lodash-es","ramda","antd","react-bootstrap","ahooks","@ant-design/icons","@headlessui/react","@headlessui-float/react","@heroicons/react/20/solid","@heroicons/react/24/solid","@heroicons/react/24/outline","@visx/visx","@tremor/react","rxjs","@mui/material","@mui/icons-material","recharts","react-use","effect","@effect/schema","@effect/platform","@effect/platform-node","@effect/platform-browser","@effect/platform-bun","@effect/sql","@effect/sql-mssql","@effect/sql-mysql2","@effect/sql-pg","@effect/sql-sqlite-node","@effect/sql-sqlite-bun","@effect/sql-sqlite-wasm","@effect/sql-sqlite-react-native","@effect/rpc","@effect/rpc-http","@effect/typeclass","@effect/experimental","@effect/opentelemetry","@material-ui/core","@material-ui/icons","@tabler/icons-react","mui-core","react-icons/ai","react-icons/bi","react-icons/bs","react-icons/cg","react-icons/ci","react-icons/di","react-icons/fa","react-icons/fa6","react-icons/fc","react-icons/fi","react-icons/gi","react-icons/go","react-icons/gr","react-icons/hi","react-icons/hi2","react-icons/im","react-icons/io","react-icons/io5","react-icons/lia","react-icons/lib","react-icons/lu","react-icons/md","react-icons/pi","react-icons/ri","react-icons/rx","react-icons/si","react-icons/sl","react-icons/tb","react-icons/tfi","react-icons/ti","react-icons/vsc","react-icons/wi"],"trustHostHeader":false,"isExperimentalCompile":false},"htmlLimitedBots":"[\\w-]+-Google|Google-[\\w-]+|Chrome-Lighthouse|Slurp|DuckDuckBot|baiduspider|yandex|sogou|bitlybot|tumblr|vkShare|quora link preview|redditbot|ia_archiver|Bingbot|BingPreview|applebot|facebookexternalhit|facebookcatalog|Twitterbot|LinkedInBot|Slackbot|Discordbot|WhatsApp|SkypeUriPreview|Yeti|googleweblight","bundlePagesRouterDependencies":false,"configFileName":"next.config.ts","turbopack":{"root":"/home/runner/work/cli/cli"},"serverExternalPackages":["tsyringe","reflect-metadata","better-sqlite3","node:os","node:child_process","node:fs"],"distDirRoot":".next"}
|
|
19
19
|
|
|
20
20
|
process.env.__NEXT_PRIVATE_STANDALONE_CONFIG = JSON.stringify(nextConfig)
|
|
21
21
|
|