@shepai/cli 1.106.4 → 1.106.5
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/src/presentation/web/app/(dashboard)/@drawer/feature/[featureId]/page.d.ts.map +1 -1
- package/dist/src/presentation/web/app/(dashboard)/@drawer/feature/[featureId]/page.js +5 -48
- package/dist/src/presentation/web/app/actions/get-feature-drawer-data.d.ts +8 -0
- package/dist/src/presentation/web/app/actions/get-feature-drawer-data.d.ts.map +1 -0
- package/dist/src/presentation/web/app/actions/get-feature-drawer-data.js +67 -0
- package/dist/src/presentation/web/app/api/graph-data/route.d.ts +14 -0
- package/dist/src/presentation/web/app/api/graph-data/route.d.ts.map +1 -0
- package/dist/src/presentation/web/app/api/graph-data/route.js +14 -0
- 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 +9 -25
- package/dist/src/presentation/web/components/common/control-center-drawer/use-drawer-sync.d.ts +12 -0
- package/dist/src/presentation/web/components/common/control-center-drawer/use-drawer-sync.d.ts.map +1 -0
- package/dist/src/presentation/web/components/common/control-center-drawer/use-drawer-sync.js +75 -0
- package/dist/src/presentation/web/components/common/feature-drawer-tabs/feature-drawer-tabs.d.ts.map +1 -1
- package/dist/src/presentation/web/components/common/feature-drawer-tabs/feature-drawer-tabs.js +3 -1
- 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 +6 -2
- package/dist/src/presentation/web/hooks/use-graph-state.d.ts.map +1 -1
- package/dist/src/presentation/web/hooks/use-graph-state.js +26 -0
- package/dist/src/presentation/web/hooks/use-sound.d.ts.map +1 -1
- package/dist/src/presentation/web/hooks/use-sound.js +13 -3
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/web/.next/BUILD_ID +1 -1
- package/web/.next/app-path-routes-manifest.json +1 -0
- package/web/.next/build-manifest.json +2 -2
- package/web/.next/fallback-build-manifest.json +2 -2
- package/web/.next/prerender-manifest.json +3 -3
- package/web/.next/required-server-files.js +2 -2
- package/web/.next/required-server-files.json +2 -2
- package/web/.next/routes-manifest.json +6 -0
- package/web/.next/server/app/(dashboard)/@drawer/create/page/server-reference-manifest.json +38 -53
- 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]/[tab]/page/server-reference-manifest.json +63 -63
- package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page.js +4 -4
- package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page/server-reference-manifest.json +63 -63
- package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page.js +4 -4
- 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 +34 -49
- 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 +38 -53
- 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]/[tab]/page/server-reference-manifest.json +63 -63
- package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page.js +4 -4
- package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/feature/[featureId]/page/server-reference-manifest.json +63 -63
- package/web/.next/server/app/(dashboard)/feature/[featureId]/page.js +4 -4
- 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 +34 -49
- 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 +34 -49
- 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/api/agent-events/route.js +1 -2
- package/web/.next/server/app/api/agent-events/route.js.nft.json +1 -1
- package/web/.next/server/app/api/attachments/preview/route.js.nft.json +1 -1
- package/web/.next/server/app/api/attachments/upload-from-path/route.js +1 -1
- package/web/.next/server/app/api/attachments/upload-from-path/route.js.nft.json +1 -1
- package/web/.next/server/app/api/evidence/route.js.nft.json +1 -1
- package/web/.next/server/app/api/feature-logs/route.js +1 -1
- package/web/.next/server/app/api/feature-logs/route.js.nft.json +1 -1
- package/web/.next/server/app/api/graph-data/route/app-paths-manifest.json +3 -0
- package/web/.next/server/app/api/graph-data/route/build-manifest.json +11 -0
- package/web/.next/server/app/api/graph-data/route/server-reference-manifest.json +4 -0
- package/web/.next/server/app/api/graph-data/route.js +8 -0
- package/web/.next/server/app/api/graph-data/route.js.map +5 -0
- package/web/.next/server/app/api/graph-data/route.js.nft.json +1 -0
- package/web/.next/server/app/api/graph-data/route_client-reference-manifest.js +2 -0
- package/web/.next/server/app/settings/page/server-reference-manifest.json +5 -5
- package/web/.next/server/app/settings/page.js.nft.json +1 -1
- package/web/.next/server/app/settings/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/app-paths-manifest.json +1 -0
- package/web/.next/server/chunks/403f9_next_dist_esm_build_templates_app-route_370c43b1.js +3 -0
- package/web/.next/server/chunks/403f9_next_dist_esm_build_templates_app-route_370c43b1.js.map +1 -0
- package/web/.next/server/chunks/744ca_web__next-internal_server_app_api_graph-data_route_actions_26df8a4e.js +3 -0
- package/web/.next/server/chunks/744ca_web__next-internal_server_app_api_graph-data_route_actions_26df8a4e.js.map +1 -0
- package/web/.next/server/chunks/[root-of-the-server]__7d5492a0._.js +3 -0
- package/web/.next/server/chunks/[root-of-the-server]__7d5492a0._.js.map +1 -0
- package/web/.next/server/chunks/{[root-of-the-server]__db04ed44._.js → [root-of-the-server]__a5879003._.js} +2 -2
- package/web/.next/server/chunks/[root-of-the-server]__aae14de3._.js +6 -0
- package/web/.next/server/chunks/[root-of-the-server]__aae14de3._.js.map +1 -0
- package/web/.next/server/chunks/{[root-of-the-server]__91d44424._.js → [root-of-the-server]__d8037e14._.js} +2 -2
- package/web/.next/server/chunks/[root-of-the-server]__f47bb8a5._.js +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_7fc19e0a.js +3 -0
- package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_@drawer_repository_[repositoryId]_page_actions_7fc19e0a.js.map +1 -0
- package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_repository_[repositoryId]_page_actions_c3aca900.js +3 -0
- package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_repository_[repositoryId]_page_actions_c3aca900.js.map +1 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__11033878._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__11033878._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__13dc8e37._.js +3 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__13dc8e37._.js.map +1 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__24dd0927._.js +2 -2
- package/web/.next/server/chunks/ssr/[root-of-the-server]__24dd0927._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__357d99f9._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__3a2d3067._.js +3 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__3a2d3067._.js.map +1 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__5d87af2e._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__5f776c10._.js +3 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__5f776c10._.js.map +1 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__684a868c._.js +3 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__684a868c._.js.map +1 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__845a9d2a._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__845a9d2a._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__89e8a5cc._.js +2 -2
- package/web/.next/server/chunks/ssr/[root-of-the-server]__aad040c0._.js +2 -2
- 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]__c03a4370._.js +3 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__c03a4370._.js.map +1 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__c16bf5de._.js +3 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__c16bf5de._.js.map +1 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__fdc75809._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__fdc75809._.js.map +1 -1
- package/web/.next/server/chunks/ssr/_135edb9c._.js +1 -1
- package/web/.next/server/chunks/ssr/_135edb9c._.js.map +1 -1
- package/web/.next/server/chunks/ssr/{_6e08ce21._.js → _250a63ae._.js} +2 -2
- package/web/.next/server/chunks/ssr/_250a63ae._.js.map +1 -0
- package/web/.next/server/chunks/ssr/{_0619c65b._.js → _3bae8e09._.js} +2 -2
- package/web/.next/server/chunks/ssr/{_0619c65b._.js.map → _3bae8e09._.js.map} +1 -1
- package/web/.next/server/chunks/ssr/{_4059434a._.js → _4a13fd24._.js} +2 -2
- package/web/.next/server/chunks/ssr/{_4059434a._.js.map → _4a13fd24._.js.map} +1 -1
- package/web/.next/server/chunks/ssr/_8dacd1e7._.js +1 -1
- package/web/.next/server/chunks/ssr/_8dacd1e7._.js.map +1 -1
- package/web/.next/server/chunks/ssr/{_a8d9cc2f._.js → _c98e033f._.js} +2 -2
- package/web/.next/server/chunks/ssr/{_a8d9cc2f._.js.map → _c98e033f._.js.map} +1 -1
- package/web/.next/server/chunks/ssr/_cc77a143._.js +1 -1
- package/web/.next/server/chunks/ssr/_cc77a143._.js.map +1 -1
- package/web/.next/server/chunks/ssr/_e6f2da4f._.js.map +1 -1
- package/web/.next/server/chunks/ssr/b1a17_presentation_web_components_features_settings_settings-page-client_tsx_6ed9d5f8._.js +1 -1
- package/web/.next/server/chunks/ssr/b1a17_presentation_web_components_features_settings_settings-page-client_tsx_6ed9d5f8._.js.map +1 -1
- package/web/.next/server/chunks/ssr/{src_presentation_web_758dfa10._.js → src_presentation_web_9f444130._.js} +3 -3
- package/web/.next/server/chunks/ssr/{src_presentation_web_7275ce5d._.js.map → src_presentation_web_9f444130._.js.map} +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_85d37ebe.js +3 -0
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_85d37ebe.js.map +1 -0
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_skills_page_actions_1fa8042e.js +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_skills_page_actions_1fa8042e.js.map +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_tools_page_actions_24684200.js +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_tools_page_actions_24684200.js.map +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_ca99d62d._.js +3 -0
- package/web/.next/server/chunks/ssr/src_presentation_web_ca99d62d._.js.map +1 -0
- package/web/.next/server/chunks/ssr/src_presentation_web_components_bf50c527._.js +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_components_de814675._.js +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_7275ce5d._.js → src_presentation_web_d7392251._.js} +3 -3
- package/web/.next/server/chunks/ssr/{src_presentation_web_758dfa10._.js.map → src_presentation_web_d7392251._.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 +250 -285
- package/web/.next/static/chunks/{9144d63a39898da5.js → 26d9daaa8e7ae994.js} +1 -1
- package/web/.next/static/chunks/{7f3823482bd3f594.js → 6fc75f45a90afaca.js} +1 -1
- package/web/.next/static/chunks/{229caf9bd06f0c45.js → 772fe887bd3200e4.js} +2 -2
- package/web/.next/static/chunks/{524307fe3f73c1cf.js → 78f37724b73daecc.js} +2 -2
- package/web/.next/static/chunks/{abb2cdec13050512.js → 7f53af94820dd254.js} +1 -1
- package/web/.next/static/chunks/{15e6c83214978e2a.js → 8f29c6159bf2ace9.js} +1 -1
- package/web/.next/static/chunks/{cacd384748cf0bd2.js → 9294c44a23259725.js} +1 -1
- package/web/.next/static/chunks/{71733e636d34974a.js → a941aad50e999afb.js} +1 -1
- package/web/.next/static/chunks/{a5bcb76c9dcfaee6.js → abe8df9f7d2e0ea2.js} +2 -2
- package/web/.next/static/chunks/{8a2e6fabcbb6720d.js → dcaecc4f31b2a9cf.js} +1 -1
- package/dist/src/presentation/web/app/actions/get-graph-data.d.ts +0 -10
- package/dist/src/presentation/web/app/actions/get-graph-data.d.ts.map +0 -1
- package/dist/src/presentation/web/app/actions/get-graph-data.js +0 -10
- package/web/.next/server/chunks/403f9_next_dist_esm_build_templates_app-route_4d623b8e.js +0 -6
- package/web/.next/server/chunks/403f9_next_dist_esm_build_templates_app-route_4d623b8e.js.map +0 -1
- package/web/.next/server/chunks/[root-of-the-server]__3b22a1eb._.js +0 -3
- package/web/.next/server/chunks/[root-of-the-server]__3b22a1eb._.js.map +0 -1
- package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_@drawer_repository_[repositoryId]_page_actions_0a7546ed.js +0 -3
- package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_@drawer_repository_[repositoryId]_page_actions_0a7546ed.js.map +0 -1
- package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_repository_[repositoryId]_page_actions_978cbb4c.js +0 -3
- package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_repository_[repositoryId]_page_actions_978cbb4c.js.map +0 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__51fc98b0._.js +0 -3
- package/web/.next/server/chunks/ssr/[root-of-the-server]__51fc98b0._.js.map +0 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__57f37786._.js +0 -3
- package/web/.next/server/chunks/ssr/[root-of-the-server]__57f37786._.js.map +0 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__708dcad1._.js +0 -3
- package/web/.next/server/chunks/ssr/[root-of-the-server]__708dcad1._.js.map +0 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__8e002910._.js +0 -3
- package/web/.next/server/chunks/ssr/[root-of-the-server]__8e002910._.js.map +0 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__94128fa9._.js +0 -3
- package/web/.next/server/chunks/ssr/[root-of-the-server]__94128fa9._.js.map +0 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__9bfb8e7c._.js +0 -3
- package/web/.next/server/chunks/ssr/[root-of-the-server]__9bfb8e7c._.js.map +0 -1
- package/web/.next/server/chunks/ssr/_6e08ce21._.js.map +0 -1
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_84803221.js +0 -3
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_84803221.js.map +0 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_app_(dashboard)_get-graph-data_ts_b018483e._.js +0 -3
- package/web/.next/server/chunks/ssr/src_presentation_web_app_(dashboard)_get-graph-data_ts_b018483e._.js.map +0 -1
- /package/web/.next/server/chunks/{[root-of-the-server]__db04ed44._.js.map → [root-of-the-server]__a5879003._.js.map} +0 -0
- /package/web/.next/server/chunks/{[root-of-the-server]__91d44424._.js.map → [root-of-the-server]__d8037e14._.js.map} +0 -0
- /package/web/.next/static/{ORc-CcNcyS9ide_AZZ8ay → znGgra8ySC0iYcFiYbyxv}/_buildManifest.js +0 -0
- /package/web/.next/static/{ORc-CcNcyS9ide_AZZ8ay → znGgra8ySC0iYcFiYbyxv}/_clientMiddlewareManifest.json +0 -0
- /package/web/.next/static/{ORc-CcNcyS9ide_AZZ8ay → znGgra8ySC0iYcFiYbyxv}/_ssgManifest.js +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"page.d.ts","sourceRoot":"","sources":["../../../../../../../../../src/presentation/web/app/(dashboard)/@drawer/feature/[featureId]/page.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"page.d.ts","sourceRoot":"","sources":["../../../../../../../../../src/presentation/web/app/(dashboard)/@drawer/feature/[featureId]/page.tsx"],"names":[],"mappings":"AAOA,oEAAoE;AACpE,eAAO,MAAM,OAAO,kBAAkB,CAAC;AAEvC,UAAU,sBAAsB;IAC9B,MAAM,EAAE,OAAO,CAAC;QAAE,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACxC;AAED,wBAA8B,iBAAiB,CAAC,EAAE,MAAM,EAAE,EAAE,sBAAsB,2DAmCjF"}
|
|
@@ -1,14 +1,8 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { resolve } from '../../../../../lib/server-container.js';
|
|
3
|
-
import { CiStatus } from '../../../../../../../../packages/core/src/domain/generated/output.js';
|
|
4
3
|
import { buildFeatureNodeData } from '../../../../build-feature-node-data.js';
|
|
5
4
|
import { computeDrawerView } from '../../../../../components/common/control-center-drawer/drawer-view.js';
|
|
6
5
|
import { FeatureDrawerClient } from '../../../../../components/common/control-center-drawer/feature-drawer-client.js';
|
|
7
|
-
const CI_STATUS_MAP = {
|
|
8
|
-
success: CiStatus.Success,
|
|
9
|
-
failure: CiStatus.Failure,
|
|
10
|
-
pending: CiStatus.Pending,
|
|
11
|
-
};
|
|
12
6
|
/** Skip static pre-rendering since we need runtime DI container. */
|
|
13
7
|
export const dynamic = 'force-dynamic';
|
|
14
8
|
export default async function FeatureDrawerPage({ params }) {
|
|
@@ -16,52 +10,15 @@ export default async function FeatureDrawerPage({ params }) {
|
|
|
16
10
|
try {
|
|
17
11
|
const featureRepo = resolve('IFeatureRepository');
|
|
18
12
|
const agentRunRepo = resolve('IAgentRunRepository');
|
|
19
|
-
|
|
20
|
-
|
|
13
|
+
// Critical path only: feature + agent run (fast DB lookups).
|
|
14
|
+
// Expensive operations (git remote URL, GitHub CI/mergeable status,
|
|
15
|
+
// artifact, repo name, base branch) are deferred to useDrawerSync
|
|
16
|
+
// which runs client-side after the drawer is already visible.
|
|
21
17
|
const feature = await featureRepo.findById(featureId);
|
|
22
18
|
if (!feature)
|
|
23
19
|
return null;
|
|
24
20
|
const run = feature.agentRunId ? await agentRunRepo.findById(feature.agentRunId) : null;
|
|
25
|
-
|
|
26
|
-
const getArtifact = resolve('GetFeatureArtifactUseCase');
|
|
27
|
-
const [repo, baseBranch, artifact, remoteUrl, liveMergeable, liveCiResult] = await Promise.all([
|
|
28
|
-
repoRepo.findByPath(feature.repositoryPath).catch(() => null),
|
|
29
|
-
gitPrService.getDefaultBranch(feature.repositoryPath).catch(() => 'main'),
|
|
30
|
-
getArtifact.execute(featureId).catch(() => null),
|
|
31
|
-
gitPrService.getRemoteUrl(feature.repositoryPath).catch(() => null),
|
|
32
|
-
feature.pr?.number
|
|
33
|
-
? gitPrService
|
|
34
|
-
.getMergeableStatus(feature.repositoryPath, feature.pr.number)
|
|
35
|
-
.catch(() => undefined)
|
|
36
|
-
: Promise.resolve(undefined),
|
|
37
|
-
feature.branch
|
|
38
|
-
? gitPrService.getCiStatus(feature.repositoryPath, feature.branch).catch(() => undefined)
|
|
39
|
-
: Promise.resolve(undefined),
|
|
40
|
-
]);
|
|
41
|
-
// Merge live PR status into feature data so the UI always reflects
|
|
42
|
-
// the current GitHub state, even if the background watcher hasn't polled yet.
|
|
43
|
-
if (feature.pr) {
|
|
44
|
-
const liveCiStatus = liveCiResult
|
|
45
|
-
? (CI_STATUS_MAP[liveCiResult.status] ?? CiStatus.Pending)
|
|
46
|
-
: undefined;
|
|
47
|
-
const updates = {};
|
|
48
|
-
if (liveMergeable !== undefined)
|
|
49
|
-
updates.mergeable = liveMergeable;
|
|
50
|
-
if (liveCiStatus !== undefined)
|
|
51
|
-
updates.ciStatus = liveCiStatus;
|
|
52
|
-
if (Object.keys(updates).length > 0) {
|
|
53
|
-
feature.pr = { ...feature.pr, ...updates };
|
|
54
|
-
featureRepo.update(feature).catch(() => {
|
|
55
|
-
/* best-effort persist */
|
|
56
|
-
});
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
const nodeData = buildFeatureNodeData(feature, run, {
|
|
60
|
-
repositoryName: repo?.name,
|
|
61
|
-
baseBranch,
|
|
62
|
-
oneLiner: artifact?.oneLiner,
|
|
63
|
-
remoteUrl: remoteUrl ?? undefined,
|
|
64
|
-
});
|
|
21
|
+
const nodeData = buildFeatureNodeData(feature, run);
|
|
65
22
|
const view = computeDrawerView({
|
|
66
23
|
selectedNode: nodeData,
|
|
67
24
|
isCreateDrawerOpen: false,
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { FeatureNodeData } from '../../components/common/feature-node/index.js';
|
|
2
|
+
/**
|
|
3
|
+
* Fetches full FeatureNodeData for a given feature ID.
|
|
4
|
+
* Used by the drawer for targeted data syncing without triggering
|
|
5
|
+
* a full router.refresh() / server component re-render.
|
|
6
|
+
*/
|
|
7
|
+
export declare function getFeatureDrawerData(featureId: string): Promise<FeatureNodeData | null>;
|
|
8
|
+
//# sourceMappingURL=get-feature-drawer-data.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-feature-drawer-data.d.ts","sourceRoot":"","sources":["../../../../../../src/presentation/web/app/actions/get-feature-drawer-data.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AAQxE;;;;GAIG;AACH,wBAAsB,oBAAoB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAsD7F"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
'use server';
|
|
2
|
+
import { resolve } from '../../lib/server-container.js';
|
|
3
|
+
import { CiStatus } from '../../../../../packages/core/src/domain/generated/output.js';
|
|
4
|
+
import { buildFeatureNodeData } from '../build-feature-node-data.js';
|
|
5
|
+
const CI_STATUS_MAP = {
|
|
6
|
+
success: CiStatus.Success,
|
|
7
|
+
failure: CiStatus.Failure,
|
|
8
|
+
pending: CiStatus.Pending,
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* Fetches full FeatureNodeData for a given feature ID.
|
|
12
|
+
* Used by the drawer for targeted data syncing without triggering
|
|
13
|
+
* a full router.refresh() / server component re-render.
|
|
14
|
+
*/
|
|
15
|
+
export async function getFeatureDrawerData(featureId) {
|
|
16
|
+
try {
|
|
17
|
+
const featureRepo = resolve('IFeatureRepository');
|
|
18
|
+
const agentRunRepo = resolve('IAgentRunRepository');
|
|
19
|
+
const repoRepo = resolve('IRepositoryRepository');
|
|
20
|
+
const gitPrService = resolve('IGitPrService');
|
|
21
|
+
const getArtifact = resolve('GetFeatureArtifactUseCase');
|
|
22
|
+
const feature = await featureRepo.findById(featureId);
|
|
23
|
+
if (!feature)
|
|
24
|
+
return null;
|
|
25
|
+
const run = feature.agentRunId ? await agentRunRepo.findById(feature.agentRunId) : null;
|
|
26
|
+
const [repo, baseBranch, artifact, remoteUrl, liveMergeable, liveCiResult] = await Promise.all([
|
|
27
|
+
repoRepo.findByPath(feature.repositoryPath).catch(() => null),
|
|
28
|
+
gitPrService.getDefaultBranch(feature.repositoryPath).catch(() => 'main'),
|
|
29
|
+
getArtifact.execute(featureId).catch(() => null),
|
|
30
|
+
gitPrService.getRemoteUrl(feature.repositoryPath).catch(() => null),
|
|
31
|
+
feature.pr?.number
|
|
32
|
+
? gitPrService
|
|
33
|
+
.getMergeableStatus(feature.repositoryPath, feature.pr.number)
|
|
34
|
+
.catch(() => undefined)
|
|
35
|
+
: Promise.resolve(undefined),
|
|
36
|
+
feature.branch
|
|
37
|
+
? gitPrService.getCiStatus(feature.repositoryPath, feature.branch).catch(() => undefined)
|
|
38
|
+
: Promise.resolve(undefined),
|
|
39
|
+
]);
|
|
40
|
+
// Merge live PR status into feature data
|
|
41
|
+
if (feature.pr) {
|
|
42
|
+
const liveCiStatus = liveCiResult
|
|
43
|
+
? (CI_STATUS_MAP[liveCiResult.status] ?? CiStatus.Pending)
|
|
44
|
+
: undefined;
|
|
45
|
+
const updates = {};
|
|
46
|
+
if (liveMergeable !== undefined)
|
|
47
|
+
updates.mergeable = liveMergeable;
|
|
48
|
+
if (liveCiStatus !== undefined)
|
|
49
|
+
updates.ciStatus = liveCiStatus;
|
|
50
|
+
if (Object.keys(updates).length > 0) {
|
|
51
|
+
feature.pr = { ...feature.pr, ...updates };
|
|
52
|
+
featureRepo.update(feature).catch(() => {
|
|
53
|
+
/* best-effort persist */
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return buildFeatureNodeData(feature, run, {
|
|
58
|
+
repositoryName: repo?.name,
|
|
59
|
+
baseBranch,
|
|
60
|
+
oneLiner: artifact?.oneLiner,
|
|
61
|
+
remoteUrl: remoteUrl ?? undefined,
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
catch {
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { NextResponse } from 'next/server';
|
|
2
|
+
/** Prevent Next.js from statically prerendering this route at build time. */
|
|
3
|
+
export declare const dynamic = "force-dynamic";
|
|
4
|
+
/**
|
|
5
|
+
* Returns fresh graph nodes and edges for the control-center canvas.
|
|
6
|
+
*
|
|
7
|
+
* Used by the client-side polling fallback instead of a server action
|
|
8
|
+
* so that periodic syncs don't trigger the Next.js "Rendering…" indicator.
|
|
9
|
+
*/
|
|
10
|
+
export declare function GET(): Promise<NextResponse<{
|
|
11
|
+
nodes: import("../../../components/features/features-canvas/index.js").CanvasNodeType[];
|
|
12
|
+
edges: import("@xyflow/react").Edge[];
|
|
13
|
+
}>>;
|
|
14
|
+
//# sourceMappingURL=route.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/app/api/graph-data/route.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAG3C,6EAA6E;AAC7E,eAAO,MAAM,OAAO,kBAAkB,CAAC;AAEvC;;;;;GAKG;AACH,wBAAsB,GAAG;;;IAGxB"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { NextResponse } from 'next/server';
|
|
2
|
+
import { getGraphData } from '../../(dashboard)/get-graph-data.js';
|
|
3
|
+
/** Prevent Next.js from statically prerendering this route at build time. */
|
|
4
|
+
export const dynamic = 'force-dynamic';
|
|
5
|
+
/**
|
|
6
|
+
* Returns fresh graph nodes and edges for the control-center canvas.
|
|
7
|
+
*
|
|
8
|
+
* Used by the client-side polling fallback instead of a server action
|
|
9
|
+
* so that periodic syncs don't trigger the Next.js "Rendering…" indicator.
|
|
10
|
+
*/
|
|
11
|
+
export async function GET() {
|
|
12
|
+
const data = await getGraphData();
|
|
13
|
+
return NextResponse.json(data);
|
|
14
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"feature-drawer-client.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/control-center-drawer/feature-drawer-client.tsx"],"names":[],"mappings":"AAsCA,OAAO,KAAK,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"feature-drawer-client.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/control-center-drawer/feature-drawer-client.tsx"],"names":[],"mappings":"AAsCA,OAAO,KAAK,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAI/D,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,UAAU,CAAC;IACjB,8FAA8F;IAC9F,MAAM,CAAC,EAAE,aAAa,CAAC;CACxB;AAED,wBAAgB,mBAAmB,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,EAAE,EAAE,wBAAwB,2CA0hB1F"}
|
package/dist/src/presentation/web/components/common/control-center-drawer/feature-drawer-client.js
CHANGED
|
@@ -28,6 +28,7 @@ import { useFeatureActions } from '../../common/feature-drawer/use-feature-actio
|
|
|
28
28
|
import { resolveSseEventUpdates } from '../../common/feature-node/derive-feature-state.js';
|
|
29
29
|
import { deriveInitialTab } from './drawer-view.js';
|
|
30
30
|
import { useArtifactFetch } from './use-artifact-fetch.js';
|
|
31
|
+
import { useDrawerSync } from './use-drawer-sync.js';
|
|
31
32
|
export function FeatureDrawerClient({ view: initialView, urlTab }) {
|
|
32
33
|
const featureFlags = useFeatureFlags();
|
|
33
34
|
const router = useRouter();
|
|
@@ -35,7 +36,7 @@ export function FeatureDrawerClient({ view: initialView, urlTab }) {
|
|
|
35
36
|
const rejectSound = useSoundAction('reject');
|
|
36
37
|
// Track the view locally so SSE events can update the drawer type in real-time
|
|
37
38
|
const [view, setView] = useState(initialView);
|
|
38
|
-
// Sync when server re-renders with new props (e.g. after
|
|
39
|
+
// Sync when server re-renders with new props (e.g. after navigation)
|
|
39
40
|
useEffect(() => {
|
|
40
41
|
setView(initialView);
|
|
41
42
|
}, [initialView]);
|
|
@@ -60,15 +61,9 @@ export function FeatureDrawerClient({ view: initialView, urlTab }) {
|
|
|
60
61
|
// fetches (which would fail with "not found" for soft-deleted features).
|
|
61
62
|
if (featureNode.state === 'deleting')
|
|
62
63
|
continue;
|
|
63
|
-
// Trigger a server refresh to get the latest drawer view,
|
|
64
|
-
// but skip when the drawer is closed, the user has unsaved changes,
|
|
65
|
-
// or a rejection is in-flight to avoid unnecessary refreshes.
|
|
66
|
-
if (isOpenRef.current && !isDirtyRef.current && !isRejectingRef.current)
|
|
67
|
-
router.refresh();
|
|
68
64
|
if (update.state !== undefined || update.lifecycle !== undefined) {
|
|
69
|
-
//
|
|
70
|
-
//
|
|
71
|
-
// without waiting for the router.refresh() round-trip.
|
|
65
|
+
// Update the node data AND re-derive the initial tab so the drawer
|
|
66
|
+
// switches immediately (e.g. prd-review → overview when agent resumes).
|
|
72
67
|
setView((prev) => {
|
|
73
68
|
if (prev.type !== 'feature')
|
|
74
69
|
return prev;
|
|
@@ -81,24 +76,17 @@ export function FeatureDrawerClient({ view: initialView, urlTab }) {
|
|
|
81
76
|
});
|
|
82
77
|
}
|
|
83
78
|
}
|
|
84
|
-
}, [events, featureNode
|
|
79
|
+
}, [events, featureNode]);
|
|
85
80
|
// Derive open state from the URL. Next.js parallel routes preserve slot
|
|
86
81
|
// content during soft navigation, so this component is NOT unmounted when
|
|
87
82
|
// navigating to `/`. Instead, we watch the pathname and let Vaul handle
|
|
88
83
|
// the close animation when the path no longer matches a feature route.
|
|
89
84
|
const pathname = usePathname();
|
|
90
85
|
const isOpen = pathname.startsWith('/feature/');
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
//
|
|
94
|
-
|
|
95
|
-
useEffect(() => {
|
|
96
|
-
if (isOpen && !wasOpenRef.current) {
|
|
97
|
-
router.refresh();
|
|
98
|
-
}
|
|
99
|
-
wasOpenRef.current = isOpen;
|
|
100
|
-
}, [isOpen, router]);
|
|
101
|
-
isOpenRef.current = isOpen;
|
|
86
|
+
// Targeted data sync: fetches fresh FeatureNodeData on drawer open and
|
|
87
|
+
// periodically while open. Replaces router.refresh() to avoid full-page
|
|
88
|
+
// re-renders that cause visible flashing and can reset form state.
|
|
89
|
+
useDrawerSync(isOpen, featureNode?.featureId ?? null, setView);
|
|
102
90
|
const onClose = useCallback(() => {
|
|
103
91
|
router.push('/');
|
|
104
92
|
}, [router]);
|
|
@@ -182,10 +170,6 @@ export function FeatureDrawerClient({ view: initialView, urlTab }) {
|
|
|
182
170
|
featureNode?.state === 'action-required' &&
|
|
183
171
|
Object.keys(prdDefaultSelections).some((k) => prdDefaultSelections[k] !== prdSelections[k]);
|
|
184
172
|
const isDirty = isChatDirty || isPrdDirty;
|
|
185
|
-
// Keep dirty state in a ref so the SSE handler can read the latest value
|
|
186
|
-
// without re-running the effect on every keystroke.
|
|
187
|
-
const isDirtyRef = useRef(isDirty);
|
|
188
|
-
isDirtyRef.current = isDirty;
|
|
189
173
|
const onReset = useCallback(() => {
|
|
190
174
|
setChatInput('');
|
|
191
175
|
setPrdSelections({ ...prdDefaultSelections });
|
package/dist/src/presentation/web/components/common/control-center-drawer/use-drawer-sync.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { DrawerView } from './drawer-view.js';
|
|
2
|
+
/**
|
|
3
|
+
* Targeted drawer data synchronization — replaces router.refresh() for
|
|
4
|
+
* keeping the feature drawer in sync with the server.
|
|
5
|
+
*
|
|
6
|
+
* - On drawer open: fetches fresh FeatureNodeData via server action
|
|
7
|
+
* - Background sync: every 15s while open, merges fresh data into view
|
|
8
|
+
* - SSE-driven state/lifecycle updates are handled separately (not here)
|
|
9
|
+
* - Never affects form state (chatInput, prdSelections, attachments)
|
|
10
|
+
*/
|
|
11
|
+
export declare function useDrawerSync(isOpen: boolean, featureId: string | null, setView: React.Dispatch<React.SetStateAction<DrawerView>>): void;
|
|
12
|
+
//# sourceMappingURL=use-drawer-sync.d.ts.map
|
package/dist/src/presentation/web/components/common/control-center-drawer/use-drawer-sync.d.ts.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-drawer-sync.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/control-center-drawer/use-drawer-sync.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAKhD;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAC3B,MAAM,EAAE,OAAO,EACf,SAAS,EAAE,MAAM,GAAG,IAAI,EACxB,OAAO,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC,GACxD,IAAI,CAwCN"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { useEffect, useRef, useCallback } from 'react';
|
|
3
|
+
import { getFeatureDrawerData } from '../../../app/actions/get-feature-drawer-data.js';
|
|
4
|
+
import { deriveInitialTab } from './drawer-view.js';
|
|
5
|
+
/** How often (ms) to run a background sync while the drawer is open. */
|
|
6
|
+
const BACKGROUND_SYNC_INTERVAL_MS = 15_000;
|
|
7
|
+
/**
|
|
8
|
+
* Targeted drawer data synchronization — replaces router.refresh() for
|
|
9
|
+
* keeping the feature drawer in sync with the server.
|
|
10
|
+
*
|
|
11
|
+
* - On drawer open: fetches fresh FeatureNodeData via server action
|
|
12
|
+
* - Background sync: every 15s while open, merges fresh data into view
|
|
13
|
+
* - SSE-driven state/lifecycle updates are handled separately (not here)
|
|
14
|
+
* - Never affects form state (chatInput, prdSelections, attachments)
|
|
15
|
+
*/
|
|
16
|
+
export function useDrawerSync(isOpen, featureId, setView) {
|
|
17
|
+
const wasOpenRef = useRef(isOpen);
|
|
18
|
+
const isFetchingRef = useRef(false);
|
|
19
|
+
const syncFromServer = useCallback(async () => {
|
|
20
|
+
if (!featureId || isFetchingRef.current)
|
|
21
|
+
return;
|
|
22
|
+
isFetchingRef.current = true;
|
|
23
|
+
try {
|
|
24
|
+
const data = await getFeatureDrawerData(featureId);
|
|
25
|
+
if (!data)
|
|
26
|
+
return;
|
|
27
|
+
setView((prev) => mergeFeatureData(prev, data));
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
// Silent — background sync failure is non-critical
|
|
31
|
+
}
|
|
32
|
+
finally {
|
|
33
|
+
isFetchingRef.current = false;
|
|
34
|
+
}
|
|
35
|
+
}, [featureId, setView]);
|
|
36
|
+
// Fetch full data when drawer opens (either on mount or closed→open transition).
|
|
37
|
+
// The server component only provides minimal data (feature + agent run);
|
|
38
|
+
// expensive fields (repo name, remote URL, CI status, etc.) are loaded here.
|
|
39
|
+
const hasFetchedOnMountRef = useRef(false);
|
|
40
|
+
useEffect(() => {
|
|
41
|
+
if (isOpen && (!wasOpenRef.current || !hasFetchedOnMountRef.current)) {
|
|
42
|
+
hasFetchedOnMountRef.current = true;
|
|
43
|
+
void syncFromServer();
|
|
44
|
+
}
|
|
45
|
+
wasOpenRef.current = isOpen;
|
|
46
|
+
}, [isOpen, syncFromServer]);
|
|
47
|
+
// Background sync: throttled interval while drawer is open
|
|
48
|
+
useEffect(() => {
|
|
49
|
+
if (!isOpen || !featureId)
|
|
50
|
+
return;
|
|
51
|
+
const timer = setInterval(() => {
|
|
52
|
+
void syncFromServer();
|
|
53
|
+
}, BACKGROUND_SYNC_INTERVAL_MS);
|
|
54
|
+
return () => clearInterval(timer);
|
|
55
|
+
}, [isOpen, featureId, syncFromServer]);
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Merges fresh server data into the current drawer view.
|
|
59
|
+
* Preserves the view type and only updates the feature node data,
|
|
60
|
+
* keeping all client-side state (form inputs, selections) untouched.
|
|
61
|
+
*/
|
|
62
|
+
function mergeFeatureData(prev, freshData) {
|
|
63
|
+
if (prev.type !== 'feature')
|
|
64
|
+
return prev;
|
|
65
|
+
const merged = { ...prev.node, ...freshData };
|
|
66
|
+
// Only re-derive initialTab when state or lifecycle actually changed.
|
|
67
|
+
// Re-deriving on every background sync would reset the chat input
|
|
68
|
+
// (which clears on initialTab change) even when nothing meaningful changed.
|
|
69
|
+
const tabChanged = merged.state !== prev.node.state || merged.lifecycle !== prev.node.lifecycle;
|
|
70
|
+
return {
|
|
71
|
+
...prev,
|
|
72
|
+
node: merged,
|
|
73
|
+
initialTab: tabChanged ? deriveInitialTab(merged) : prev.initialTab,
|
|
74
|
+
};
|
|
75
|
+
}
|
package/dist/src/presentation/web/components/common/feature-drawer-tabs/feature-drawer-tabs.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"feature-drawer-tabs.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/feature-drawer-tabs/feature-drawer-tabs.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sCAAsC,CAAC;AAS9E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AACxE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,uCAAuC,CAAC;AAClF,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,2CAA2C,CAAC;AACzF,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,+CAA+C,CAAC;AACjG,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AAMxE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uCAAuC,CAAC;AAQ9E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uDAAuD,CAAC;AAiD3F,MAAM,WAAW,sBAAsB;IACrC,WAAW,EAAE,eAAe,CAAC;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,aAAa,CAAC;IAC3B,gFAAgF;IAChF,MAAM,CAAC,EAAE,aAAa,CAAC;IACvB,mFAAmF;IACnF,SAAS,CAAC,EAAE,SAAS,iBAAiB,EAAE,CAAC;IAGzC,OAAO,CAAC,EAAE,oBAAoB,GAAG,IAAI,CAAC;IACtC,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACvC,WAAW,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7D,YAAY,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1C,WAAW,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,gBAAgB,EAAE,KAAK,IAAI,CAAC;IAC1E,YAAY,CAAC,EAAE,OAAO,CAAC;IAGvB,QAAQ,CAAC,EAAE,uBAAuB,GAAG,IAAI,CAAC;IAC1C,aAAa,CAAC,EAAE,MAAM,IAAI,CAAC;IAC3B,YAAY,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,gBAAgB,EAAE,KAAK,IAAI,CAAC;IAC3E,aAAa,CAAC,EAAE,OAAO,CAAC;IAGxB,WAAW,CAAC,EAAE,2BAA2B,GAAG,IAAI,CAAC;IAGjD,SAAS,CAAC,EAAE,eAAe,GAAG,IAAI,CAAC;IACnC,cAAc,CAAC,EAAE,MAAM,IAAI,CAAC;IAC5B,aAAa,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,gBAAgB,EAAE,KAAK,IAAI,CAAC;IAC5E,cAAc,CAAC,EAAE,OAAO,CAAC;IAGzB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iBAAiB,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CAC7C;AAwBD,wBAAgB,iBAAiB,CAAC,EAChC,WAAW,EACX,SAAS,EACT,UAAU,EACV,MAAM,EACN,OAAO,EACP,aAAa,EACb,WAAW,EACX,YAAY,EACZ,WAAW,EACX,YAAY,EACZ,QAAQ,EACR,aAAa,EACb,YAAY,EACZ,aAAa,EACb,WAAW,EACX,SAAS,EACT,cAAc,EACd,aAAa,EACb,cAAc,EACd,WAAW,EACX,SAAS,EACT,iBAAiB,EACjB,SAAS,GACV,EAAE,sBAAsB,
|
|
1
|
+
{"version":3,"file":"feature-drawer-tabs.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/feature-drawer-tabs/feature-drawer-tabs.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sCAAsC,CAAC;AAS9E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AACxE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,uCAAuC,CAAC;AAClF,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,2CAA2C,CAAC;AACzF,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,+CAA+C,CAAC;AACjG,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AAMxE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uCAAuC,CAAC;AAQ9E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uDAAuD,CAAC;AAiD3F,MAAM,WAAW,sBAAsB;IACrC,WAAW,EAAE,eAAe,CAAC;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,aAAa,CAAC;IAC3B,gFAAgF;IAChF,MAAM,CAAC,EAAE,aAAa,CAAC;IACvB,mFAAmF;IACnF,SAAS,CAAC,EAAE,SAAS,iBAAiB,EAAE,CAAC;IAGzC,OAAO,CAAC,EAAE,oBAAoB,GAAG,IAAI,CAAC;IACtC,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACvC,WAAW,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7D,YAAY,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1C,WAAW,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,gBAAgB,EAAE,KAAK,IAAI,CAAC;IAC1E,YAAY,CAAC,EAAE,OAAO,CAAC;IAGvB,QAAQ,CAAC,EAAE,uBAAuB,GAAG,IAAI,CAAC;IAC1C,aAAa,CAAC,EAAE,MAAM,IAAI,CAAC;IAC3B,YAAY,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,gBAAgB,EAAE,KAAK,IAAI,CAAC;IAC3E,aAAa,CAAC,EAAE,OAAO,CAAC;IAGxB,WAAW,CAAC,EAAE,2BAA2B,GAAG,IAAI,CAAC;IAGjD,SAAS,CAAC,EAAE,eAAe,GAAG,IAAI,CAAC;IACnC,cAAc,CAAC,EAAE,MAAM,IAAI,CAAC;IAC5B,aAAa,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,gBAAgB,EAAE,KAAK,IAAI,CAAC;IAC5E,cAAc,CAAC,EAAE,OAAO,CAAC;IAGzB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iBAAiB,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CAC7C;AAwBD,wBAAgB,iBAAiB,CAAC,EAChC,WAAW,EACX,SAAS,EACT,UAAU,EACV,MAAM,EACN,OAAO,EACP,aAAa,EACb,WAAW,EACX,YAAY,EACZ,WAAW,EACX,YAAY,EACZ,QAAQ,EACR,aAAa,EACb,YAAY,EACZ,aAAa,EACb,WAAW,EACX,SAAS,EACT,cAAc,EACd,aAAa,EACb,cAAc,EACd,WAAW,EACX,SAAS,EACT,iBAAiB,EACjB,SAAS,GACV,EAAE,sBAAsB,2CA2TxB"}
|
package/dist/src/presentation/web/components/common/feature-drawer-tabs/feature-drawer-tabs.js
CHANGED
|
@@ -66,7 +66,6 @@ const TAB_FETCHERS = {
|
|
|
66
66
|
};
|
|
67
67
|
export function FeatureDrawerTabs({ featureNode, featureId, initialTab, urlTab, prdData, prdSelections, onPrdSelect, onPrdApprove, onPrdReject, isPrdLoading, techData, onTechApprove, onTechReject, isTechLoading, productData, mergeData, onMergeApprove, onMergeReject, isMergeLoading, isRejecting, chatInput, onChatInputChange, sseEvents, }) {
|
|
68
68
|
const pathname = usePathname();
|
|
69
|
-
const featureLogs = useFeatureLogs(featureId);
|
|
70
69
|
const visibleTabs = useMemo(() => computeVisibleTabs(featureNode), [featureNode]);
|
|
71
70
|
const visibleTabDefs = useMemo(() => ALL_TABS.filter((t) => visibleTabs.includes(t.key)), [visibleTabs]);
|
|
72
71
|
// Derive the base path (without tab segment) from the current pathname.
|
|
@@ -86,6 +85,9 @@ export function FeatureDrawerTabs({ featureNode, featureId, initialTab, urlTab,
|
|
|
86
85
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
87
86
|
}, []);
|
|
88
87
|
const [activeTab, setActiveTab] = useState(effectiveInitial);
|
|
88
|
+
// Only subscribe to log SSE when the log tab is active to avoid
|
|
89
|
+
// opening an EventSource connection on every drawer open.
|
|
90
|
+
const featureLogs = useFeatureLogs(activeTab === 'log' ? featureId : null);
|
|
89
91
|
const { tabs, fetchTab, refreshTab } = useTabDataFetch(featureId, TAB_FETCHERS);
|
|
90
92
|
// Sync URL when active tab changes via user interaction.
|
|
91
93
|
// Use window.history.pushState instead of router.push to avoid triggering a
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-control-center-state.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/control-center/use-control-center-state.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAClE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AACxE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,qCAAqC,CAAC;AAC9E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uCAAuC,CAAC;AAC5E,OAAO,EAGL,KAAK,eAAe,EACrB,MAAM,yBAAyB,CAAC;
|
|
1
|
+
{"version":3,"file":"use-control-center-state.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/control-center/use-control-center-state.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAClE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AACxE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,qCAAqC,CAAC;AAC9E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uCAAuC,CAAC;AAC5E,OAAO,EAGL,KAAK,eAAe,EACrB,MAAM,yBAAyB,CAAC;AAajC,OAAO,EAAiB,KAAK,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAM7E,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB,KAAK,EAAE,IAAI,EAAE,CAAC;IACd,aAAa,EAAE,CAAC,OAAO,EAAE,UAAU,CAAC,cAAc,CAAC,EAAE,KAAK,IAAI,CAAC;IAC/D,aAAa,EAAE,CAAC,UAAU,EAAE,UAAU,KAAK,IAAI,CAAC;IAChD,mBAAmB,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK;QAAE,QAAQ,EAAE,OAAO,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;IAC/E,YAAY,EAAE,CAAC,SAAS,EAAE,eAAe,KAAK,IAAI,CAAC;IACnD,mBAAmB,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;IACpE,sBAAsB,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAChE,iBAAiB,EAAE,CACjB,YAAY,EAAE,MAAM,GAAG,IAAI,EAC3B,YAAY,CAAC,EAAE,OAAO,CAAC,eAAe,CAAC,EACvC,QAAQ,CAAC,EAAE,MAAM,KACd,MAAM,CAAC;IACZ,wDAAwD;IACxD,wBAAwB,EAAE,CAAC,aAAa,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;IACxE,gDAAgD;IAChD,iBAAiB,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,kBAAkB,GAAG,SAAS,CAAC;IACtE,0EAA0E;IAC1E,YAAY,EAAE,CAAC,SAAS,EAAE,cAAc,KAAK,IAAI,CAAC;CACnD;AAQD,wBAAgB,qBAAqB,CACnC,YAAY,EAAE,cAAc,EAAE,EAC9B,YAAY,EAAE,IAAI,EAAE,GACnB,kBAAkB,CAqapB"}
|
package/dist/src/presentation/web/components/features/control-center/use-control-center-state.js
CHANGED
|
@@ -7,7 +7,6 @@ import { deleteFeature } from '../../../app/actions/delete-feature.js';
|
|
|
7
7
|
import { addRepository } from '../../../app/actions/add-repository.js';
|
|
8
8
|
import { deleteRepository } from '../../../app/actions/delete-repository.js';
|
|
9
9
|
import { getFeatureMetadata } from '../../../app/actions/get-feature-metadata.js';
|
|
10
|
-
import { fetchGraphData } from '../../../app/actions/get-graph-data.js';
|
|
11
10
|
import { useAgentEventsContext } from '../../../hooks/agent-events-provider.js';
|
|
12
11
|
import { useSoundAction } from '../../../hooks/use-sound-action.js';
|
|
13
12
|
import { createLogger } from '../../../lib/logger.js';
|
|
@@ -157,7 +156,12 @@ export function useControlCenterState(initialNodes, initialEdges) {
|
|
|
157
156
|
log.debug(`polling enabled (${POLL_INTERVAL_MS}ms interval)`);
|
|
158
157
|
const timer = setInterval(async () => {
|
|
159
158
|
try {
|
|
160
|
-
|
|
159
|
+
// Use a plain fetch instead of a server action so the poll
|
|
160
|
+
// doesn't trigger the Next.js "Rendering…" indicator.
|
|
161
|
+
const res = await fetch('/api/graph-data');
|
|
162
|
+
if (!res.ok)
|
|
163
|
+
throw new Error(`status ${res.status}`);
|
|
164
|
+
const { nodes: freshNodes, edges: freshEdges } = await res.json();
|
|
161
165
|
reconcile(freshNodes, freshEdges);
|
|
162
166
|
}
|
|
163
167
|
catch {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-graph-state.d.ts","sourceRoot":"","sources":["../../../../../src/presentation/web/hooks/use-graph-state.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,IAAI,EAAY,MAAM,eAAe,CAAC;AACpD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uCAAuC,CAAC;AAC5E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AACxE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,qCAAqC,CAAC;AAC9E,OAAO,EAEL,KAAK,YAAY,EAEjB,KAAK,cAAc,EACpB,MAAM,oBAAoB,CAAC;AAG5B,YAAY,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAEzD,MAAM,WAAW,mBAAmB;IAClC,mDAAmD;IACnD,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB,mDAAmD;IACnD,KAAK,EAAE,IAAI,EAAE,CAAC;IACd;;;OAGG;IACH,SAAS,EAAE,CAAC,QAAQ,EAAE,cAAc,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,IAAI,CAAC;IAClE,uEAAuE;IACvE,aAAa,EAAE,CAAC,aAAa,EAAE,MAAM,EAAE,OAAO,EAAE,kBAAkB,KAAK,IAAI,CAAC;IAC5E,kEAAkE;IAClE,iBAAiB,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,eAAe,EAAE,YAAY,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1F,yDAAyD;IACzD,oBAAoB,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/C,sDAAsD;IACtD,aAAa,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,uDAAuD;IACvD,cAAc,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,KAAK,IAAI,CAAC;IAC9D,2DAA2D;IAC3D,aAAa,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,kBAAkB,KAAK,IAAI,CAAC;IAClE,gCAAgC;IAChC,gBAAgB,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3C,yDAAyD;IACzD,iBAAiB,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,kBAAkB,KAAK,IAAI,CAAC;IACtF,gEAAgE;IAChE,wBAAwB,EAAE,CAAC,aAAa,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;IACxE,yDAAyD;IACzD,iBAAiB,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,kBAAkB,GAAG,SAAS,CAAC;IACtE,+EAA+E;IAC/E,cAAc,EAAE,MAAM,MAAM,CAAC;IAC7B,6EAA6E;IAC7E,YAAY,EAAE,CAAC,SAAS,EAAE,cAAc,KAAK,IAAI,CAAC;CACnD;AAuCD,KAAK,kBAAkB,GAAG,OAAO,CAC/B,IAAI,CAAC,eAAe,EAAE,OAAO,GAAG,WAAW,GAAG,MAAM,GAAG,aAAa,CAAC,CACtE,CAAC;
|
|
1
|
+
{"version":3,"file":"use-graph-state.d.ts","sourceRoot":"","sources":["../../../../../src/presentation/web/hooks/use-graph-state.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,IAAI,EAAY,MAAM,eAAe,CAAC;AACpD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uCAAuC,CAAC;AAC5E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AACxE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,qCAAqC,CAAC;AAC9E,OAAO,EAEL,KAAK,YAAY,EAEjB,KAAK,cAAc,EACpB,MAAM,oBAAoB,CAAC;AAG5B,YAAY,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAEzD,MAAM,WAAW,mBAAmB;IAClC,mDAAmD;IACnD,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB,mDAAmD;IACnD,KAAK,EAAE,IAAI,EAAE,CAAC;IACd;;;OAGG;IACH,SAAS,EAAE,CAAC,QAAQ,EAAE,cAAc,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,IAAI,CAAC;IAClE,uEAAuE;IACvE,aAAa,EAAE,CAAC,aAAa,EAAE,MAAM,EAAE,OAAO,EAAE,kBAAkB,KAAK,IAAI,CAAC;IAC5E,kEAAkE;IAClE,iBAAiB,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,eAAe,EAAE,YAAY,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1F,yDAAyD;IACzD,oBAAoB,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/C,sDAAsD;IACtD,aAAa,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,uDAAuD;IACvD,cAAc,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,KAAK,IAAI,CAAC;IAC9D,2DAA2D;IAC3D,aAAa,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,kBAAkB,KAAK,IAAI,CAAC;IAClE,gCAAgC;IAChC,gBAAgB,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3C,yDAAyD;IACzD,iBAAiB,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,kBAAkB,KAAK,IAAI,CAAC;IACtF,gEAAgE;IAChE,wBAAwB,EAAE,CAAC,aAAa,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;IACxE,yDAAyD;IACzD,iBAAiB,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,kBAAkB,GAAG,SAAS,CAAC;IACtE,+EAA+E;IAC/E,cAAc,EAAE,MAAM,MAAM,CAAC;IAC7B,6EAA6E;IAC7E,YAAY,EAAE,CAAC,SAAS,EAAE,cAAc,KAAK,IAAI,CAAC;CACnD;AAuCD,KAAK,kBAAkB,GAAG,OAAO,CAC/B,IAAI,CAAC,eAAe,EAAE,OAAO,GAAG,WAAW,GAAG,MAAM,GAAG,aAAa,CAAC,CACtE,CAAC;AA8BF,wBAAgB,aAAa,CAC3B,YAAY,EAAE,cAAc,EAAE,EAC9B,YAAY,EAAE,IAAI,EAAE,GACnB,mBAAmB,CAsXrB"}
|
|
@@ -36,6 +36,26 @@ function isFeatureDataUnchanged(data, updates) {
|
|
|
36
36
|
(updates.name === undefined || updates.name === data.name) &&
|
|
37
37
|
(updates.description === undefined || updates.description === data.description));
|
|
38
38
|
}
|
|
39
|
+
/**
|
|
40
|
+
* Shallow-compare two Maps by key set and entry data (JSON equality).
|
|
41
|
+
* Returns true if they are structurally identical, avoiding unnecessary re-renders.
|
|
42
|
+
*/
|
|
43
|
+
function mapsEqual(a, b) {
|
|
44
|
+
if (a.size !== b.size)
|
|
45
|
+
return false;
|
|
46
|
+
for (const [key, aEntry] of a) {
|
|
47
|
+
const bEntry = b.get(key);
|
|
48
|
+
if (!bEntry)
|
|
49
|
+
return false;
|
|
50
|
+
if (aEntry.parentNodeId !== bEntry.parentNodeId)
|
|
51
|
+
return false;
|
|
52
|
+
if (aEntry.data === bEntry.data)
|
|
53
|
+
continue;
|
|
54
|
+
if (JSON.stringify(aEntry.data) !== JSON.stringify(bEntry.data))
|
|
55
|
+
return false;
|
|
56
|
+
}
|
|
57
|
+
return true;
|
|
58
|
+
}
|
|
39
59
|
export function useGraphState(initialNodes, initialEdges) {
|
|
40
60
|
// eslint-disable-next-line react-hooks/exhaustive-deps -- intentional: parse only on mount (like useState initializer)
|
|
41
61
|
const init = useMemo(() => parseMaps(initialNodes, initialEdges), []);
|
|
@@ -178,6 +198,9 @@ export function useGraphState(initialNodes, initialEdges) {
|
|
|
178
198
|
pendingUpdatesRef.current.delete(nodeId);
|
|
179
199
|
}
|
|
180
200
|
}
|
|
201
|
+
// Avoid re-render when polling returns identical data
|
|
202
|
+
if (mapsEqual(currentFeatureMap, merged))
|
|
203
|
+
return currentFeatureMap;
|
|
181
204
|
return merged;
|
|
182
205
|
});
|
|
183
206
|
// Clean pendingMap entries that now have a real counterpart in server data
|
|
@@ -220,6 +243,9 @@ export function useGraphState(initialNodes, initialEdges) {
|
|
|
220
243
|
merged.set(id, entry);
|
|
221
244
|
}
|
|
222
245
|
}
|
|
246
|
+
// Avoid re-render when polling returns identical data
|
|
247
|
+
if (mapsEqual(currentRepoMap, merged))
|
|
248
|
+
return currentRepoMap;
|
|
223
249
|
return merged;
|
|
224
250
|
});
|
|
225
251
|
}, []);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-sound.d.ts","sourceRoot":"","sources":["../../../../../src/presentation/web/hooks/use-sound.ts"],"names":[],"mappings":"AAKA,QAAA,MAAM,WAAW,oWA6BP,CAAC;AAEX,MAAM,MAAM,SAAS,GAAG,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,CAAC,CAAC;AAErD,MAAM,WAAW,eAAe;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,IAAI,CAAC;IACjB,IAAI,EAAE,MAAM,IAAI,CAAC;IACjB,SAAS,EAAE,OAAO,CAAC;CACpB;
|
|
1
|
+
{"version":3,"file":"use-sound.d.ts","sourceRoot":"","sources":["../../../../../src/presentation/web/hooks/use-sound.ts"],"names":[],"mappings":"AAKA,QAAA,MAAM,WAAW,oWA6BP,CAAC;AAEX,MAAM,MAAM,SAAS,GAAG,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,CAAC,CAAC;AAErD,MAAM,WAAW,eAAe;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,IAAI,CAAC;IACjB,IAAI,EAAE,MAAM,IAAI,CAAC;IACjB,SAAS,EAAE,OAAO,CAAC;CACpB;AAgBD,wBAAgB,QAAQ,CAAC,IAAI,EAAE,SAAS,EAAE,OAAO,GAAE,eAAoB,GAAG,cAAc,CA8CvF;AAED,qEAAqE;AACrE,OAAO,EAAE,WAAW,EAAE,CAAC"}
|
|
@@ -31,6 +31,18 @@ const SOUND_NAMES = [
|
|
|
31
31
|
'type_04',
|
|
32
32
|
'type_05',
|
|
33
33
|
];
|
|
34
|
+
// Module-level cache: Audio objects are created once per sound name and reused
|
|
35
|
+
// across component mounts to avoid re-downloading WAV files on every drawer open.
|
|
36
|
+
const audioCache = new Map();
|
|
37
|
+
function getOrCreateAudio(name) {
|
|
38
|
+
let audio = audioCache.get(name);
|
|
39
|
+
if (!audio) {
|
|
40
|
+
audio = new Audio(`/sounds/${name}.wav`);
|
|
41
|
+
audio.preload = 'auto';
|
|
42
|
+
audioCache.set(name, audio);
|
|
43
|
+
}
|
|
44
|
+
return audio;
|
|
45
|
+
}
|
|
34
46
|
export function useSound(name, options = {}) {
|
|
35
47
|
const { volume = 1, loop = false } = options;
|
|
36
48
|
const { enabled } = useSoundEnabled();
|
|
@@ -39,8 +51,7 @@ export function useSound(name, options = {}) {
|
|
|
39
51
|
useEffect(() => {
|
|
40
52
|
if (typeof window === 'undefined')
|
|
41
53
|
return;
|
|
42
|
-
const audio =
|
|
43
|
-
audio.preload = 'auto';
|
|
54
|
+
const audio = getOrCreateAudio(name);
|
|
44
55
|
audio.loop = loop;
|
|
45
56
|
audio.volume = Math.max(0, Math.min(1, volume));
|
|
46
57
|
audio.addEventListener('ended', () => {
|
|
@@ -49,7 +60,6 @@ export function useSound(name, options = {}) {
|
|
|
49
60
|
audioRef.current = audio;
|
|
50
61
|
return () => {
|
|
51
62
|
audio.pause();
|
|
52
|
-
audio.removeAttribute('src');
|
|
53
63
|
audioRef.current = null;
|
|
54
64
|
isPlayingRef.current = false;
|
|
55
65
|
};
|