@shepai/cli 1.72.9-pr220.f17b60a → 1.73.0-pr222.ef53005
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/agent-executor-provider.interface.d.ts +1 -1
- package/dist/packages/core/src/application/ports/output/agents/agent-executor-provider.interface.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/di/container.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/di/container.js +2 -1
- package/dist/packages/core/src/infrastructure/services/agents/common/agent-executor-provider.service.d.ts +4 -2
- package/dist/packages/core/src/infrastructure/services/agents/common/agent-executor-provider.service.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/services/agents/common/agent-executor-provider.service.js +8 -4
- package/dist/packages/core/src/infrastructure/services/agents/common/agent-runner.service.js +1 -1
- package/dist/packages/core/src/infrastructure/services/agents/common/structured-agent-caller.service.js +1 -1
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/feature-agent-worker.js +1 -1
- package/dist/src/presentation/web/app/layout.js +1 -1
- 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 +54 -124
- package/dist/src/presentation/web/components/common/control-center-drawer/use-artifact-fetch.d.ts +13 -0
- package/dist/src/presentation/web/components/common/control-center-drawer/use-artifact-fetch.d.ts.map +1 -0
- package/dist/src/presentation/web/components/common/control-center-drawer/use-artifact-fetch.js +46 -0
- package/dist/src/presentation/web/components/common/feature-drawer/use-feature-actions.d.ts.map +1 -1
- package/dist/src/presentation/web/components/common/feature-drawer/use-feature-actions.js +7 -10
- package/dist/src/presentation/web/components/common/repository-node/use-repository-actions.d.ts.map +1 -1
- package/dist/src/presentation/web/components/common/repository-node/use-repository-actions.js +14 -39
- package/dist/src/presentation/web/components/features/control-center/control-center-inner.js +6 -7
- 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 +45 -8
- package/dist/src/presentation/web/hooks/agent-events-provider.d.ts.map +1 -1
- package/dist/src/presentation/web/hooks/agent-events-provider.js +3 -2
- package/dist/src/presentation/web/hooks/use-agent-events.d.ts.map +1 -1
- package/dist/src/presentation/web/hooks/use-agent-events.js +13 -2
- package/dist/src/presentation/web/hooks/use-deploy-action.d.ts.map +1 -1
- package/dist/src/presentation/web/hooks/use-deploy-action.js +10 -13
- package/dist/src/presentation/web/lib/logger.d.ts +7 -0
- package/dist/src/presentation/web/lib/logger.d.ts.map +1 -0
- package/dist/src/presentation/web/lib/logger.js +11 -0
- 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 +45 -30
- 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 +51 -36
- 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 +41 -26
- 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 +45 -30
- 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 +51 -36
- 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 +41 -26
- 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 +41 -26
- 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.js.nft.json +1 -1
- package/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/skills/page/server-reference-manifest.json +6 -6
- package/web/.next/server/app/skills/page.js.nft.json +1 -1
- package/web/.next/server/app/skills/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/tools/page/server-reference-manifest.json +6 -6
- package/web/.next/server/app/tools/page.js.nft.json +1 -1
- package/web/.next/server/app/tools/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/version/page/server-reference-manifest.json +1 -1
- package/web/.next/server/app/version/page.js.nft.json +1 -1
- package/web/.next/server/app/version/page_client-reference-manifest.js +1 -1
- package/web/.next/server/chunks/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_da7eef33.js +3 -0
- package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_@drawer_repository_[repositoryId]_page_actions_da7eef33.js.map +1 -0
- package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_repository_[repositoryId]_page_actions_0a9251aa.js +3 -0
- package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_repository_[repositoryId]_page_actions_0a9251aa.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]__6258349c._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__6258349c._.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]__94a6d275._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__94a6d275._.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/_0e9d6bf7._.js +1 -1
- package/web/.next/server/chunks/ssr/_0e9d6bf7._.js.map +1 -1
- package/web/.next/server/chunks/ssr/{_8e87c87b._.js → _4f7c70c9._.js} +2 -2
- package/web/.next/server/chunks/ssr/{_8e87c87b._.js.map → _4f7c70c9._.js.map} +1 -1
- package/web/.next/server/chunks/ssr/{_1978f325._.js → _5ee4f5a7._.js} +2 -2
- package/web/.next/server/chunks/ssr/_5ee4f5a7._.js.map +1 -0
- 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_d5b0cb86._.js → server/chunks/ssr/src_presentation_web_163038ba._.js} +3 -3
- package/web/.next/server/chunks/ssr/{src_presentation_web_d5b0cb86._.js.map → src_presentation_web_163038ba._.js.map} +1 -1
- package/web/.next/server/chunks/ssr/{src_presentation_web_2b91e4ec._.js → src_presentation_web_30d7eeda._.js} +2 -2
- package/web/.next/server/chunks/ssr/{src_presentation_web_5bcc1537._.js.map → src_presentation_web_30d7eeda._.js.map} +1 -1
- package/web/.next/server/chunks/ssr/{src_presentation_web_d5b0cb86._.js → src_presentation_web_459cb687._.js} +3 -3
- package/web/.next/server/chunks/ssr/{src_presentation_web_e626b63c._.js.map → src_presentation_web_459cb687._.js.map} +1 -1
- package/web/.next/server/chunks/ssr/{src_presentation_web_5bcc1537._.js → src_presentation_web_565a14f8._.js} +2 -2
- package/web/.next/server/chunks/ssr/{src_presentation_web_2b91e4ec._.js.map → src_presentation_web_565a14f8._.js.map} +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_67178b88._.js +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_67178b88._.js.map +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_021a05f2.js +3 -0
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_021a05f2.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 +183 -126
- 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 +45 -30
- 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 +51 -36
- 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 +41 -26
- 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 +45 -30
- 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 +51 -36
- 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 +41 -26
- 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 +41 -26
- 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.js.nft.json +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/skills/page/server-reference-manifest.json +6 -6
- package/web/.next/standalone/src/presentation/web/.next/server/app/skills/page.js.nft.json +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/skills/page_client-reference-manifest.js +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/tools/page/server-reference-manifest.json +6 -6
- package/web/.next/standalone/src/presentation/web/.next/server/app/tools/page.js.nft.json +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/tools/page_client-reference-manifest.js +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/version/page/server-reference-manifest.json +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/version/page.js.nft.json +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/version/page_client-reference-manifest.js +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/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_da7eef33.js +3 -0
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_repository_[repositoryId]_page_actions_0a9251aa.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]__6258349c._.js +1 -1
- 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]__94a6d275._.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/_0e9d6bf7._.js +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/{_8e87c87b._.js → _4f7c70c9._.js} +2 -2
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/{_1978f325._.js → _5ee4f5a7._.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_e626b63c._.js → standalone/src/presentation/web/.next/server/chunks/ssr/src_presentation_web_163038ba._.js} +3 -3
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/{src_presentation_web_2b91e4ec._.js → src_presentation_web_30d7eeda._.js} +2 -2
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/{src_presentation_web_e626b63c._.js → src_presentation_web_459cb687._.js} +3 -3
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/{src_presentation_web_5bcc1537._.js → src_presentation_web_565a14f8._.js} +2 -2
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/src_presentation_web_67178b88._.js +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_021a05f2.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 +183 -126
- package/web/.next/standalone/src/presentation/web/app/layout.tsx +1 -1
- package/web/.next/standalone/src/presentation/web/components/common/control-center-drawer/feature-drawer-client.tsx +80 -115
- package/web/.next/standalone/src/presentation/web/components/common/control-center-drawer/use-artifact-fetch.ts +56 -0
- package/web/.next/standalone/src/presentation/web/components/common/feature-drawer/use-feature-actions.ts +6 -7
- package/web/.next/standalone/src/presentation/web/components/common/repository-node/use-repository-actions.ts +29 -54
- package/web/.next/standalone/src/presentation/web/components/features/control-center/control-center-inner.tsx +7 -7
- package/web/.next/standalone/src/presentation/web/components/features/control-center/use-control-center-state.ts +50 -8
- package/web/.next/standalone/src/presentation/web/hooks/agent-events-provider.tsx +7 -2
- package/web/.next/standalone/src/presentation/web/hooks/use-agent-events.ts +13 -2
- package/web/.next/standalone/src/presentation/web/hooks/use-deploy-action.ts +13 -13
- package/web/.next/standalone/src/presentation/web/lib/logger.ts +12 -0
- package/web/.next/standalone/src/presentation/web/server.js +1 -1
- package/web/.next/static/chunks/{98ca891a5c156aa5.js → 0cfed3c69c312c09.js} +3 -3
- package/web/.next/static/chunks/{c92e1360ada8ca94.js → 1f5c93a8b939416d.js} +2 -2
- package/web/.next/static/chunks/4c63764a2d06e45e.js +1 -0
- package/web/.next/static/chunks/{792aac476adb5875.js → 89e74b1c3eb43b03.js} +1 -1
- package/web/.next/static/chunks/{9b1770f05f1d95e5.js → 937d7d4d58942872.js} +1 -1
- package/web/.next/static/chunks/95e3f47abe8032e5.js +1 -0
- package/web/.next/static/chunks/{83463b63971f5723.js → b835e88cdc8c63d2.js} +1 -1
- package/web/.next/static/chunks/{d5e95c4482029a39.js → e2342af6b68c94c1.js} +1 -1
- package/web/.next/static/chunks/{a7f52757dff0cea0.js → ed69d6b172ae2bfe.js} +1 -1
- package/web/.next/static/chunks/fd46753cd16664a9.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_816618e2.js +0 -3
- package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_@drawer_repository_[repositoryId]_page_actions_816618e2.js.map +0 -1
- package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_repository_[repositoryId]_page_actions_ba2e050f.js +0 -3
- package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_repository_[repositoryId]_page_actions_ba2e050f.js.map +0 -1
- package/web/.next/server/chunks/ssr/_1978f325._.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_5955c012.js +0 -3
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_5955c012.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_816618e2.js +0 -3
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_repository_[repositoryId]_page_actions_ba2e050f.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_5955c012.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/76827713cb2b7333.js +0 -1
- package/web/.next/static/chunks/7c8adcfd920a8f74.js +0 -1
- package/web/.next/static/chunks/b6becf0de992842a.js +0 -1
- /package/web/.next/static/{eg0FTlsA4z_7CXbFfMgAr → 0yTXyENV4ko7rpM4-3vV8}/_buildManifest.js +0 -0
- /package/web/.next/static/{eg0FTlsA4z_7CXbFfMgAr → 0yTXyENV4ko7rpM4-3vV8}/_clientMiddlewareManifest.json +0 -0
- /package/web/.next/static/{eg0FTlsA4z_7CXbFfMgAr → 0yTXyENV4ko7rpM4-3vV8}/_ssgManifest.js +0 -0
|
@@ -56,6 +56,7 @@ import type { MergeReviewData } from '@/components/common/merge-review';
|
|
|
56
56
|
import { resolveSseEventUpdates } from '@/components/common/feature-node/derive-feature-state';
|
|
57
57
|
import { deriveFeatureViewType } from './drawer-view';
|
|
58
58
|
import type { DrawerView } from './drawer-view';
|
|
59
|
+
import { useArtifactFetch } from './use-artifact-fetch';
|
|
59
60
|
|
|
60
61
|
export interface FeatureDrawerClientProps {
|
|
61
62
|
view: DrawerView;
|
|
@@ -87,6 +88,10 @@ export function FeatureDrawerClient({ view: initialView }: FeatureDrawerClientPr
|
|
|
87
88
|
const processedCountRef = useRef(0);
|
|
88
89
|
|
|
89
90
|
useEffect(() => {
|
|
91
|
+
// Clamp cursor if events were pruned
|
|
92
|
+
if (processedCountRef.current > events.length) {
|
|
93
|
+
processedCountRef.current = 0;
|
|
94
|
+
}
|
|
90
95
|
if (!featureNode || events.length <= processedCountRef.current) return;
|
|
91
96
|
|
|
92
97
|
const newEvents = events.slice(processedCountRef.current);
|
|
@@ -96,9 +101,9 @@ export function FeatureDrawerClient({ view: initialView }: FeatureDrawerClientPr
|
|
|
96
101
|
if (update.featureId !== featureNode.featureId) continue;
|
|
97
102
|
|
|
98
103
|
// Trigger a server refresh to get the latest drawer view,
|
|
99
|
-
// but skip when the user has unsaved changes
|
|
100
|
-
//
|
|
101
|
-
if (!isDirtyRef.current && !isRejectingRef.current) router.refresh();
|
|
104
|
+
// but skip when the drawer is closed, the user has unsaved changes,
|
|
105
|
+
// or a rejection is in-flight to avoid unnecessary refreshes.
|
|
106
|
+
if (isOpenRef.current && !isDirtyRef.current && !isRejectingRef.current) router.refresh();
|
|
102
107
|
|
|
103
108
|
if (update.state !== undefined || update.lifecycle !== undefined) {
|
|
104
109
|
// Optimistically update the node data AND re-derive the view type so the
|
|
@@ -129,6 +134,19 @@ export function FeatureDrawerClient({ view: initialView }: FeatureDrawerClientPr
|
|
|
129
134
|
// the close animation when the path no longer matches a feature route.
|
|
130
135
|
const pathname = usePathname();
|
|
131
136
|
const isOpen = pathname.startsWith('/feature/');
|
|
137
|
+
const isOpenRef = useRef(isOpen);
|
|
138
|
+
const wasOpenRef = useRef(isOpen);
|
|
139
|
+
|
|
140
|
+
// When the drawer re-opens, force a server refresh so the view is always fresh.
|
|
141
|
+
// SSE skips router.refresh() while the drawer is closed, so data can go stale.
|
|
142
|
+
useEffect(() => {
|
|
143
|
+
if (isOpen && !wasOpenRef.current) {
|
|
144
|
+
router.refresh();
|
|
145
|
+
}
|
|
146
|
+
wasOpenRef.current = isOpen;
|
|
147
|
+
}, [isOpen, router]);
|
|
148
|
+
|
|
149
|
+
isOpenRef.current = isOpen;
|
|
132
150
|
|
|
133
151
|
const onClose = useCallback(() => {
|
|
134
152
|
router.push('/');
|
|
@@ -141,21 +159,17 @@ export function FeatureDrawerClient({ view: initialView }: FeatureDrawerClientPr
|
|
|
141
159
|
const [prdData, setPrdData] = useState<PrdQuestionnaireData | null>(null);
|
|
142
160
|
const [prdSelections, setPrdSelections] = useState<Record<string, string>>({});
|
|
143
161
|
const [prdDefaultSelections, setPrdDefaultSelections] = useState<Record<string, string>>({});
|
|
144
|
-
const [isLoadingPrd, setIsLoadingPrd] = useState(false);
|
|
145
162
|
|
|
146
163
|
// ── Tech state ─────────────────────────────────────────────────────────
|
|
147
164
|
const [techData, setTechData] = useState<TechDecisionsReviewData | null>(null);
|
|
148
|
-
const [isLoadingTech, setIsLoadingTech] = useState(false);
|
|
149
165
|
|
|
150
166
|
// ── Product decisions state (for tech review Product tab) ─────────────
|
|
151
167
|
const [techProductData, setTechProductData] = useState<
|
|
152
168
|
ProductDecisionsSummaryData | null | undefined
|
|
153
169
|
>(undefined);
|
|
154
|
-
const [isLoadingTechProduct, setIsLoadingTechProduct] = useState(false);
|
|
155
170
|
|
|
156
171
|
// ── Merge state ────────────────────────────────────────────────────────
|
|
157
172
|
const [mergeData, setMergeData] = useState<MergeReviewData | null>(null);
|
|
158
|
-
const [isLoadingMerge, setIsLoadingMerge] = useState(false);
|
|
159
173
|
|
|
160
174
|
// ── Delete state ───────────────────────────────────────────────────────
|
|
161
175
|
const [isDeleting, setIsDeleting] = useState(false);
|
|
@@ -173,120 +187,71 @@ export function FeatureDrawerClient({ view: initialView }: FeatureDrawerClientPr
|
|
|
173
187
|
// ── Data fetching ─────────────────────────────────────────────────────
|
|
174
188
|
|
|
175
189
|
const prdFeatureId = view.type === 'prd-review' ? view.node.featureId : null;
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
}
|
|
191
|
-
if (result.questionnaire) {
|
|
192
|
-
setPrdData(result.questionnaire);
|
|
193
|
-
const defaults: Record<string, string> = {};
|
|
194
|
-
for (const q of result.questionnaire.questions) {
|
|
195
|
-
const recommended = q.options.find((o) => o.recommended);
|
|
196
|
-
if (recommended) defaults[q.id] = recommended.id;
|
|
197
|
-
}
|
|
198
|
-
setPrdSelections(defaults);
|
|
199
|
-
setPrdDefaultSelections(defaults);
|
|
190
|
+
const isLoadingPrd = useArtifactFetch(
|
|
191
|
+
prdFeatureId,
|
|
192
|
+
getFeatureArtifact,
|
|
193
|
+
(result) => {
|
|
194
|
+
if (result.error) {
|
|
195
|
+
toast.error(result.error);
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
if (result.questionnaire) {
|
|
199
|
+
setPrdData(result.questionnaire);
|
|
200
|
+
const defaults: Record<string, string> = {};
|
|
201
|
+
for (const q of result.questionnaire.questions) {
|
|
202
|
+
const recommended = q.options.find((o) => o.recommended);
|
|
203
|
+
if (recommended) defaults[q.id] = recommended.id;
|
|
200
204
|
}
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
});
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
205
|
+
setPrdSelections(defaults);
|
|
206
|
+
setPrdDefaultSelections(defaults);
|
|
207
|
+
}
|
|
208
|
+
},
|
|
209
|
+
() => {
|
|
210
|
+
setPrdSelections({});
|
|
211
|
+
setPrdDefaultSelections({});
|
|
212
|
+
setPrdData(null);
|
|
213
|
+
},
|
|
214
|
+
'Failed to load questionnaire'
|
|
215
|
+
);
|
|
212
216
|
|
|
213
217
|
const techFeatureId = view.type === 'tech-review' ? view.node.featureId : null;
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
if (result.techDecisions) setTechData(result.techDecisions);
|
|
228
|
-
})
|
|
229
|
-
.catch(() => {
|
|
230
|
-
if (!cancelled) toast.error('Failed to load tech decisions');
|
|
231
|
-
})
|
|
232
|
-
.finally(() => {
|
|
233
|
-
if (!cancelled) setIsLoadingTech(false);
|
|
234
|
-
});
|
|
235
|
-
return () => {
|
|
236
|
-
cancelled = true;
|
|
237
|
-
};
|
|
238
|
-
}, [techFeatureId]);
|
|
218
|
+
const isLoadingTech = useArtifactFetch(
|
|
219
|
+
techFeatureId,
|
|
220
|
+
getResearchArtifact,
|
|
221
|
+
(result) => {
|
|
222
|
+
if (result.error) {
|
|
223
|
+
toast.error(result.error);
|
|
224
|
+
return;
|
|
225
|
+
}
|
|
226
|
+
if (result.techDecisions) setTechData(result.techDecisions);
|
|
227
|
+
},
|
|
228
|
+
() => setTechData(null),
|
|
229
|
+
'Failed to load tech decisions'
|
|
230
|
+
);
|
|
239
231
|
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
if (cancelled) return;
|
|
249
|
-
if (result.productDecisions) {
|
|
250
|
-
setTechProductData(result.productDecisions);
|
|
251
|
-
}
|
|
252
|
-
})
|
|
253
|
-
.catch(() => {
|
|
254
|
-
// Silent failure — the product tab is supplementary
|
|
255
|
-
})
|
|
256
|
-
.finally(() => {
|
|
257
|
-
if (!cancelled) setIsLoadingTechProduct(false);
|
|
258
|
-
});
|
|
259
|
-
return () => {
|
|
260
|
-
cancelled = true;
|
|
261
|
-
};
|
|
262
|
-
}, [techFeatureId]);
|
|
232
|
+
const isLoadingTechProduct = useArtifactFetch(
|
|
233
|
+
techFeatureId,
|
|
234
|
+
getFeatureArtifact,
|
|
235
|
+
(result) => {
|
|
236
|
+
if (result.productDecisions) setTechProductData(result.productDecisions);
|
|
237
|
+
},
|
|
238
|
+
() => setTechProductData(undefined)
|
|
239
|
+
);
|
|
263
240
|
|
|
264
241
|
const mergeFeatureId = view.type === 'merge-review' ? view.node.featureId : null;
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
setMergeData(result);
|
|
279
|
-
})
|
|
280
|
-
.catch(() => {
|
|
281
|
-
if (!cancelled) toast.error('Failed to load merge review data');
|
|
282
|
-
})
|
|
283
|
-
.finally(() => {
|
|
284
|
-
if (!cancelled) setIsLoadingMerge(false);
|
|
285
|
-
});
|
|
286
|
-
return () => {
|
|
287
|
-
cancelled = true;
|
|
288
|
-
};
|
|
289
|
-
}, [mergeFeatureId]);
|
|
242
|
+
const isLoadingMerge = useArtifactFetch(
|
|
243
|
+
mergeFeatureId,
|
|
244
|
+
getMergeReviewData,
|
|
245
|
+
(result) => {
|
|
246
|
+
if ('error' in result) {
|
|
247
|
+
toast.error(result.error);
|
|
248
|
+
return;
|
|
249
|
+
}
|
|
250
|
+
setMergeData(result);
|
|
251
|
+
},
|
|
252
|
+
() => setMergeData(null),
|
|
253
|
+
'Failed to load merge review data'
|
|
254
|
+
);
|
|
290
255
|
|
|
291
256
|
// ── Close guard ──────────────────────────────────────────────────────
|
|
292
257
|
const isChatDirty = chatInput.trim().length > 0;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { useState, useEffect, useRef } from 'react';
|
|
4
|
+
import { toast } from 'sonner';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Generic hook for fetching drawer artifact data when a feature ID changes.
|
|
8
|
+
* Handles loading state, cancellation on unmount/re-fetch, and error toasting.
|
|
9
|
+
*
|
|
10
|
+
* @param featureId - The feature ID to fetch for, or null to reset.
|
|
11
|
+
* @param fetcher - Async function that fetches the artifact data.
|
|
12
|
+
* @param onSuccess - Called with the fetch result when successful and not cancelled.
|
|
13
|
+
* @param onReset - Called immediately when featureId changes (before fetching).
|
|
14
|
+
* @param errorMessage - Optional toast message shown on fetch failure.
|
|
15
|
+
* @returns Whether the fetch is currently in progress.
|
|
16
|
+
*/
|
|
17
|
+
export function useArtifactFetch<TResult>(
|
|
18
|
+
featureId: string | null,
|
|
19
|
+
fetcher: (id: string) => Promise<TResult>,
|
|
20
|
+
onSuccess: (result: TResult) => void,
|
|
21
|
+
onReset: () => void,
|
|
22
|
+
errorMessage?: string
|
|
23
|
+
): boolean {
|
|
24
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
25
|
+
|
|
26
|
+
// Use refs to avoid stale callbacks in the effect without triggering re-runs.
|
|
27
|
+
const onSuccessRef = useRef(onSuccess);
|
|
28
|
+
const onResetRef = useRef(onReset);
|
|
29
|
+
onSuccessRef.current = onSuccess;
|
|
30
|
+
onResetRef.current = onReset;
|
|
31
|
+
|
|
32
|
+
useEffect(() => {
|
|
33
|
+
onResetRef.current();
|
|
34
|
+
if (!featureId) return;
|
|
35
|
+
|
|
36
|
+
let cancelled = false;
|
|
37
|
+
setIsLoading(true);
|
|
38
|
+
|
|
39
|
+
fetcher(featureId)
|
|
40
|
+
.then((result) => {
|
|
41
|
+
if (!cancelled) onSuccessRef.current(result);
|
|
42
|
+
})
|
|
43
|
+
.catch(() => {
|
|
44
|
+
if (!cancelled && errorMessage) toast.error(errorMessage);
|
|
45
|
+
})
|
|
46
|
+
.finally(() => {
|
|
47
|
+
if (!cancelled) setIsLoading(false);
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
return () => {
|
|
51
|
+
cancelled = true;
|
|
52
|
+
};
|
|
53
|
+
}, [featureId, fetcher, errorMessage]);
|
|
54
|
+
|
|
55
|
+
return isLoading;
|
|
56
|
+
}
|
|
@@ -37,15 +37,14 @@ export function useFeatureActions(input: FeatureActionsInput | null): FeatureAct
|
|
|
37
37
|
const shellTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
|
|
38
38
|
const specsTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
|
|
39
39
|
|
|
40
|
-
// Clear timers on unmount
|
|
40
|
+
// Clear timers on unmount — read .current inside cleanup so we get the
|
|
41
|
+
// actual timer value at teardown time, not the always-null value at mount.
|
|
41
42
|
useEffect(() => {
|
|
42
|
-
const
|
|
43
|
-
const shellTimer = shellTimerRef.current;
|
|
44
|
-
const specsTimer = specsTimerRef.current;
|
|
43
|
+
const refs = [ideTimerRef, shellTimerRef, specsTimerRef];
|
|
45
44
|
return () => {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
45
|
+
for (const ref of refs) {
|
|
46
|
+
if (ref.current) clearTimeout(ref.current);
|
|
47
|
+
}
|
|
49
48
|
};
|
|
50
49
|
}, []);
|
|
51
50
|
|
|
@@ -37,22 +37,19 @@ export function useRepositoryActions(input: RepositoryActionsInput | null): Repo
|
|
|
37
37
|
|
|
38
38
|
// Clear timers on unmount
|
|
39
39
|
useEffect(() => {
|
|
40
|
-
const
|
|
41
|
-
const
|
|
42
|
-
const
|
|
40
|
+
const ideRef = ideTimerRef;
|
|
41
|
+
const shellRef = shellTimerRef;
|
|
42
|
+
const folderRef = folderTimerRef;
|
|
43
43
|
return () => {
|
|
44
|
-
if (
|
|
45
|
-
if (
|
|
46
|
-
if (
|
|
44
|
+
if (ideRef.current) clearTimeout(ideRef.current);
|
|
45
|
+
if (shellRef.current) clearTimeout(shellRef.current);
|
|
46
|
+
if (folderRef.current) clearTimeout(folderRef.current);
|
|
47
47
|
};
|
|
48
48
|
}, []);
|
|
49
49
|
|
|
50
|
-
const
|
|
50
|
+
const performAction = useCallback(
|
|
51
51
|
async (
|
|
52
|
-
action: (
|
|
53
|
-
success: boolean;
|
|
54
|
-
error?: string;
|
|
55
|
-
}>,
|
|
52
|
+
action: () => Promise<{ success: boolean; error?: string }>,
|
|
56
53
|
setLoading: (v: boolean) => void,
|
|
57
54
|
setError: (v: string | null) => void,
|
|
58
55
|
timerRef: React.RefObject<ReturnType<typeof setTimeout> | null>,
|
|
@@ -60,48 +57,13 @@ export function useRepositoryActions(input: RepositoryActionsInput | null): Repo
|
|
|
60
57
|
) => {
|
|
61
58
|
if (!input || isLoading) return;
|
|
62
59
|
|
|
63
|
-
// Clear any existing timer
|
|
64
60
|
if (timerRef.current) clearTimeout(timerRef.current);
|
|
65
61
|
|
|
66
62
|
setLoading(true);
|
|
67
63
|
setError(null);
|
|
68
64
|
|
|
69
65
|
try {
|
|
70
|
-
const result = await action(
|
|
71
|
-
|
|
72
|
-
if (!result.success) {
|
|
73
|
-
const errorMessage = result.error ?? 'An unexpected error occurred';
|
|
74
|
-
setError(errorMessage);
|
|
75
|
-
timerRef.current = setTimeout(() => setError(null), ERROR_CLEAR_DELAY);
|
|
76
|
-
}
|
|
77
|
-
} catch (err: unknown) {
|
|
78
|
-
const errorMessage = err instanceof Error ? err.message : 'An unexpected error occurred';
|
|
79
|
-
setError(errorMessage);
|
|
80
|
-
timerRef.current = setTimeout(() => setError(null), ERROR_CLEAR_DELAY);
|
|
81
|
-
} finally {
|
|
82
|
-
setLoading(false);
|
|
83
|
-
}
|
|
84
|
-
},
|
|
85
|
-
[input]
|
|
86
|
-
);
|
|
87
|
-
|
|
88
|
-
const performFolderAction = useCallback(
|
|
89
|
-
async (
|
|
90
|
-
action: (repositoryPath: string) => Promise<{ success: boolean; error?: string }>,
|
|
91
|
-
setLoading: (v: boolean) => void,
|
|
92
|
-
setError: (v: string | null) => void,
|
|
93
|
-
timerRef: React.RefObject<ReturnType<typeof setTimeout> | null>,
|
|
94
|
-
isLoading: boolean
|
|
95
|
-
) => {
|
|
96
|
-
if (!input || isLoading) return;
|
|
97
|
-
|
|
98
|
-
if (timerRef.current) clearTimeout(timerRef.current);
|
|
99
|
-
|
|
100
|
-
setLoading(true);
|
|
101
|
-
setError(null);
|
|
102
|
-
|
|
103
|
-
try {
|
|
104
|
-
const result = await action(input.repositoryPath);
|
|
66
|
+
const result = await action();
|
|
105
67
|
|
|
106
68
|
if (!result.success) {
|
|
107
69
|
const errorMessage = result.error ?? 'An unexpected error occurred';
|
|
@@ -120,26 +82,39 @@ export function useRepositoryActions(input: RepositoryActionsInput | null): Repo
|
|
|
120
82
|
);
|
|
121
83
|
|
|
122
84
|
const handleOpenIde = useCallback(
|
|
123
|
-
() =>
|
|
124
|
-
|
|
85
|
+
() =>
|
|
86
|
+
performAction(
|
|
87
|
+
() => openIde({ repositoryPath: input!.repositoryPath }),
|
|
88
|
+
setIdeLoading,
|
|
89
|
+
setIdeError,
|
|
90
|
+
ideTimerRef,
|
|
91
|
+
ideLoading
|
|
92
|
+
),
|
|
93
|
+
[performAction, ideLoading, input]
|
|
125
94
|
);
|
|
126
95
|
|
|
127
96
|
const handleOpenShell = useCallback(
|
|
128
97
|
() =>
|
|
129
|
-
|
|
130
|
-
|
|
98
|
+
performAction(
|
|
99
|
+
() => openShell({ repositoryPath: input!.repositoryPath }),
|
|
100
|
+
setShellLoading,
|
|
101
|
+
setShellError,
|
|
102
|
+
shellTimerRef,
|
|
103
|
+
shellLoading
|
|
104
|
+
),
|
|
105
|
+
[performAction, shellLoading, input]
|
|
131
106
|
);
|
|
132
107
|
|
|
133
108
|
const handleOpenFolder = useCallback(
|
|
134
109
|
() =>
|
|
135
|
-
|
|
136
|
-
openFolder,
|
|
110
|
+
performAction(
|
|
111
|
+
() => openFolder(input!.repositoryPath),
|
|
137
112
|
setFolderLoading,
|
|
138
113
|
setFolderError,
|
|
139
114
|
folderTimerRef,
|
|
140
115
|
folderLoading
|
|
141
116
|
),
|
|
142
|
-
[
|
|
117
|
+
[performAction, folderLoading, input]
|
|
143
118
|
);
|
|
144
119
|
|
|
145
120
|
return {
|
|
@@ -44,20 +44,20 @@ export function ControlCenterInner({ initialNodes, initialEdges }: ControlCenter
|
|
|
44
44
|
// Publish sidebar features to context whenever feature node data changes
|
|
45
45
|
const { setFeatures: setSidebarFeatures } = useSidebarFeaturesContext();
|
|
46
46
|
|
|
47
|
+
const featureNodes = useMemo(() => nodes.filter((n) => n.type === 'featureNode'), [nodes]);
|
|
48
|
+
|
|
47
49
|
const sidebarKey = useMemo(() => {
|
|
48
|
-
return
|
|
49
|
-
.filter((n) => n.type === 'featureNode')
|
|
50
|
+
return featureNodes
|
|
50
51
|
.map((n) => {
|
|
51
52
|
const d = n.data as FeatureNodeData;
|
|
52
|
-
return `${d.featureId}:${d.state}:${d.
|
|
53
|
+
return `${d.featureId}:${d.state}:${d.name}`;
|
|
53
54
|
})
|
|
54
55
|
.sort()
|
|
55
56
|
.join(',');
|
|
56
|
-
}, [
|
|
57
|
+
}, [featureNodes]);
|
|
57
58
|
|
|
58
59
|
useEffect(() => {
|
|
59
|
-
const sidebarItems =
|
|
60
|
-
.filter((n) => n.type === 'featureNode')
|
|
60
|
+
const sidebarItems = featureNodes
|
|
61
61
|
.map((n) => {
|
|
62
62
|
const d = n.data as FeatureNodeData;
|
|
63
63
|
const status = mapNodeStateToSidebarStatus(d.state);
|
|
@@ -79,7 +79,7 @@ export function ControlCenterInner({ initialNodes, initialEdges }: ControlCenter
|
|
|
79
79
|
}[];
|
|
80
80
|
|
|
81
81
|
setSidebarFeatures(sidebarItems);
|
|
82
|
-
}, [sidebarKey,
|
|
82
|
+
}, [sidebarKey, featureNodes, setSidebarFeatures]);
|
|
83
83
|
|
|
84
84
|
// ── URL-based navigation handlers ────────────────────────────────────
|
|
85
85
|
|
|
@@ -16,8 +16,11 @@ 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
18
|
import { getFeatureMetadata } from '@/app/actions/get-feature-metadata';
|
|
19
|
+
import { fetchGraphData } from '@/app/actions/get-graph-data';
|
|
19
20
|
import { useAgentEventsContext } from '@/hooks/agent-events-provider';
|
|
20
21
|
import { useSoundAction } from '@/hooks/use-sound-action';
|
|
22
|
+
import { createLogger } from '@/lib/logger';
|
|
23
|
+
|
|
21
24
|
import {
|
|
22
25
|
mapEventTypeToState,
|
|
23
26
|
resolveSseEventUpdates,
|
|
@@ -25,6 +28,9 @@ import {
|
|
|
25
28
|
import { useGraphState, type GraphCallbacks } from '@/hooks/use-graph-state';
|
|
26
29
|
import type { FeatureEntry } from '@/lib/derive-graph';
|
|
27
30
|
|
|
31
|
+
const log = createLogger('[Polling]');
|
|
32
|
+
const POLL_INTERVAL_MS = 3_000;
|
|
33
|
+
|
|
28
34
|
export interface ControlCenterState {
|
|
29
35
|
nodes: CanvasNodeType[];
|
|
30
36
|
edges: Edge[];
|
|
@@ -76,6 +82,14 @@ export function useControlCenterState(
|
|
|
76
82
|
setCallbacks,
|
|
77
83
|
} = useGraphState(initialNodes, initialEdges);
|
|
78
84
|
|
|
85
|
+
// Refs for stable access to latest nodes/edges without callback recreation
|
|
86
|
+
const nodesRef = useRef(nodes);
|
|
87
|
+
const edgesRef = useRef(edges);
|
|
88
|
+
useEffect(() => {
|
|
89
|
+
nodesRef.current = nodes;
|
|
90
|
+
edgesRef.current = edges;
|
|
91
|
+
}, [nodes, edges]);
|
|
92
|
+
|
|
79
93
|
// Sync server props into domain Maps when initialNodes/initialEdges change.
|
|
80
94
|
// Keyed by a stable string so we don't re-reconcile on every render.
|
|
81
95
|
const initialNodeKey = useMemo(
|
|
@@ -148,6 +162,10 @@ export function useControlCenterState(
|
|
|
148
162
|
const processedEventCountRef = useRef(0);
|
|
149
163
|
|
|
150
164
|
useEffect(() => {
|
|
165
|
+
// Clamp cursor if events were pruned
|
|
166
|
+
if (processedEventCountRef.current > events.length) {
|
|
167
|
+
processedEventCountRef.current = 0;
|
|
168
|
+
}
|
|
151
169
|
if (events.length <= processedEventCountRef.current) return;
|
|
152
170
|
const newEvents = events.slice(processedEventCountRef.current);
|
|
153
171
|
processedEventCountRef.current = events.length;
|
|
@@ -177,6 +195,10 @@ export function useControlCenterState(
|
|
|
177
195
|
const processedMetadataCountRef = useRef(0);
|
|
178
196
|
|
|
179
197
|
useEffect(() => {
|
|
198
|
+
// Clamp cursor if events were pruned
|
|
199
|
+
if (processedMetadataCountRef.current > events.length) {
|
|
200
|
+
processedMetadataCountRef.current = 0;
|
|
201
|
+
}
|
|
180
202
|
if (events.length <= processedMetadataCountRef.current) return;
|
|
181
203
|
const newEvents = events.slice(processedMetadataCountRef.current);
|
|
182
204
|
processedMetadataCountRef.current = events.length;
|
|
@@ -199,6 +221,25 @@ export function useControlCenterState(
|
|
|
199
221
|
}
|
|
200
222
|
}, [events, updateFeature]);
|
|
201
223
|
|
|
224
|
+
// --- Polling fallback: catch any SSE events that were missed ---
|
|
225
|
+
useEffect(() => {
|
|
226
|
+
log.debug(`polling enabled (${POLL_INTERVAL_MS}ms interval)`);
|
|
227
|
+
|
|
228
|
+
const timer = setInterval(async () => {
|
|
229
|
+
try {
|
|
230
|
+
const { nodes: freshNodes, edges: freshEdges } = await fetchGraphData();
|
|
231
|
+
reconcile(freshNodes, freshEdges);
|
|
232
|
+
} catch {
|
|
233
|
+
log.warn('poll fetch failed — will retry next interval');
|
|
234
|
+
}
|
|
235
|
+
}, POLL_INTERVAL_MS);
|
|
236
|
+
|
|
237
|
+
return () => {
|
|
238
|
+
log.debug('polling disabled');
|
|
239
|
+
clearInterval(timer);
|
|
240
|
+
};
|
|
241
|
+
}, [reconcile]);
|
|
242
|
+
|
|
202
243
|
// onNodesChange is a no-op: nodes are derived from domain Maps.
|
|
203
244
|
// Since nodesDraggable=false and elementsSelectable=false, only React Flow's
|
|
204
245
|
// internal replace/dimensions changes come through — we ignore them all.
|
|
@@ -245,7 +286,7 @@ export function useControlCenterState(
|
|
|
245
286
|
const nodeId = `feat-${featureId}`;
|
|
246
287
|
|
|
247
288
|
// Find the current entry for rollback
|
|
248
|
-
const prevEntry =
|
|
289
|
+
const prevEntry = nodesRef.current
|
|
249
290
|
.filter((n) => n.id === nodeId)
|
|
250
291
|
.map((n) => ({
|
|
251
292
|
nodeId: n.id,
|
|
@@ -270,7 +311,7 @@ export function useControlCenterState(
|
|
|
270
311
|
toast.error('Failed to delete feature');
|
|
271
312
|
});
|
|
272
313
|
},
|
|
273
|
-
[
|
|
314
|
+
[router, deleteSound, removeFeature, restoreFeature]
|
|
274
315
|
);
|
|
275
316
|
|
|
276
317
|
const handleDeleteRepository = useCallback(
|
|
@@ -279,14 +320,14 @@ export function useControlCenterState(
|
|
|
279
320
|
|
|
280
321
|
// Find children of this repo via edges
|
|
281
322
|
const childFeatureIds = new Set(
|
|
282
|
-
|
|
323
|
+
edgesRef.current.filter((e) => e.source === repoNodeId).map((e) => e.target)
|
|
283
324
|
);
|
|
284
325
|
|
|
285
326
|
// Snapshot for rollback
|
|
286
327
|
const prevRepoData = getRepositoryData(repoNodeId);
|
|
287
328
|
const childSnapshots = new Map<string, FeatureEntry>();
|
|
288
329
|
for (const childId of childFeatureIds) {
|
|
289
|
-
const childNode =
|
|
330
|
+
const childNode = nodesRef.current.find((n) => n.id === childId);
|
|
290
331
|
if (childNode) {
|
|
291
332
|
childSnapshots.set(childId, { nodeId: childId, data: childNode.data as FeatureNodeData });
|
|
292
333
|
}
|
|
@@ -320,8 +361,6 @@ export function useControlCenterState(
|
|
|
320
361
|
}
|
|
321
362
|
},
|
|
322
363
|
[
|
|
323
|
-
edges,
|
|
324
|
-
nodes,
|
|
325
364
|
deleteSound,
|
|
326
365
|
removeRepository,
|
|
327
366
|
removeFeature,
|
|
@@ -335,10 +374,13 @@ export function useControlCenterState(
|
|
|
335
374
|
(direction: LayoutDirection) => {
|
|
336
375
|
// Layout is applied via reconcile on next server prop update.
|
|
337
376
|
// For immediate re-layout, we apply dagre and trigger a reconcile-like update.
|
|
338
|
-
const result = layoutWithDagre(
|
|
377
|
+
const result = layoutWithDagre(nodesRef.current, edgesRef.current, {
|
|
378
|
+
...CANVAS_LAYOUT_DEFAULTS,
|
|
379
|
+
direction,
|
|
380
|
+
});
|
|
339
381
|
reconcile(result.nodes, result.edges);
|
|
340
382
|
},
|
|
341
|
-
[
|
|
383
|
+
[reconcile]
|
|
342
384
|
);
|
|
343
385
|
|
|
344
386
|
const handleAddRepository = useCallback(
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
|
-
import { createContext, useContext, type ReactNode } from 'react';
|
|
3
|
+
import { createContext, useContext, useMemo, type ReactNode } from 'react';
|
|
4
4
|
import {
|
|
5
5
|
useAgentEvents,
|
|
6
6
|
type UseAgentEventsOptions,
|
|
@@ -18,7 +18,12 @@ interface AgentEventsProviderProps extends UseAgentEventsOptions {
|
|
|
18
18
|
* Wrap the app once; use `useAgentEventsContext()` to read.
|
|
19
19
|
*/
|
|
20
20
|
export function AgentEventsProvider({ children, runId }: AgentEventsProviderProps) {
|
|
21
|
-
const
|
|
21
|
+
const { events, lastEvent, connectionStatus } = useAgentEvents({ runId });
|
|
22
|
+
|
|
23
|
+
const value = useMemo<UseAgentEventsResult>(
|
|
24
|
+
() => ({ events, lastEvent, connectionStatus }),
|
|
25
|
+
[events, lastEvent, connectionStatus]
|
|
26
|
+
);
|
|
22
27
|
|
|
23
28
|
return <AgentEventsContext.Provider value={value}>{children}</AgentEventsContext.Provider>;
|
|
24
29
|
}
|