@shepai/cli 1.106.4 → 1.107.0-pr330.e164f47
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/packages/core/src/application/ports/output/agents/feature-agent-process.interface.d.ts +1 -0
- package/dist/packages/core/src/application/ports/output/agents/feature-agent-process.interface.d.ts.map +1 -1
- package/dist/packages/core/src/application/ports/output/services/git-pr-service.interface.d.ts +12 -1
- package/dist/packages/core/src/application/ports/output/services/git-pr-service.interface.d.ts.map +1 -1
- package/dist/packages/core/src/application/use-cases/features/resume-feature.use-case.d.ts.map +1 -1
- package/dist/packages/core/src/application/use-cases/features/resume-feature.use-case.js +2 -0
- package/dist/packages/core/src/infrastructure/di/container.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/di/container.js +3 -0
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/fast-feature-agent-graph.d.ts +5 -0
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/fast-feature-agent-graph.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/feature-agent-graph.d.ts +17 -0
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/feature-agent-graph.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/feature-agent-process.service.d.ts +1 -0
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/feature-agent-process.service.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/feature-agent-process.service.js +3 -0
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/feature-agent-worker.d.ts +1 -0
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/feature-agent-worker.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/feature-agent-worker.js +8 -1
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/merge/merge.node.d.ts +5 -1
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/merge/merge.node.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/merge/merge.node.js +4 -1
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/node-helpers.d.ts +7 -0
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/node-helpers.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/node-helpers.js +23 -1
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/state.d.ts +1 -0
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/state.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/state.js +5 -0
- package/dist/packages/core/src/infrastructure/services/git/git-pr.service.d.ts +2 -1
- package/dist/packages/core/src/infrastructure/services/git/git-pr.service.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/services/git/git-pr.service.js +22 -3
- package/dist/packages/core/src/infrastructure/services/process/is-process-alive.d.ts +8 -0
- package/dist/packages/core/src/infrastructure/services/process/is-process-alive.d.ts.map +1 -0
- package/dist/packages/core/src/infrastructure/services/process/is-process-alive.js +15 -0
- package/dist/src/presentation/cli/commands/status.command.d.ts +1 -1
- package/dist/src/presentation/cli/commands/status.command.d.ts.map +1 -1
- package/dist/src/presentation/cli/commands/status.command.js +2 -38
- 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/actions/resume-feature.d.ts +5 -0
- package/dist/src/presentation/web/app/actions/resume-feature.d.ts.map +1 -0
- package/dist/src/presentation/web/app/actions/resume-feature.js +16 -0
- package/dist/src/presentation/web/app/api/agent-events/route.d.ts.map +1 -1
- package/dist/src/presentation/web/app/api/agent-events/route.js +17 -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/app/api/version/route.d.ts +3 -6
- package/dist/src/presentation/web/app/api/version/route.d.ts.map +1 -1
- package/dist/src/presentation/web/app/api/version/route.js +29 -15
- package/dist/src/presentation/web/app/build-feature-node-data.d.ts.map +1 -1
- package/dist/src/presentation/web/app/build-feature-node-data.js +6 -1
- package/dist/src/presentation/web/app/build-graph-nodes.d.ts.map +1 -1
- package/dist/src/presentation/web/app/build-graph-nodes.js +6 -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 +30 -26
- 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/common/feature-drawer-tabs/overview-tab.d.ts.map +1 -1
- package/dist/src/presentation/web/components/common/feature-drawer-tabs/overview-tab.js +2 -2
- package/dist/src/presentation/web/components/common/feature-drawer-tabs/overview-tab.stories.d.ts +2 -0
- package/dist/src/presentation/web/components/common/feature-drawer-tabs/overview-tab.stories.d.ts.map +1 -1
- package/dist/src/presentation/web/components/common/feature-drawer-tabs/overview-tab.stories.js +9 -0
- package/dist/src/presentation/web/components/common/feature-node/derive-feature-state.d.ts +4 -2
- package/dist/src/presentation/web/components/common/feature-node/derive-feature-state.d.ts.map +1 -1
- package/dist/src/presentation/web/components/common/feature-node/derive-feature-state.js +5 -3
- package/dist/src/presentation/web/components/common/feature-node/feature-node-state-config.d.ts +1 -0
- package/dist/src/presentation/web/components/common/feature-node/feature-node-state-config.d.ts.map +1 -1
- package/dist/src/presentation/web/components/common/feature-node/feature-node.d.ts.map +1 -1
- package/dist/src/presentation/web/components/common/feature-node/feature-node.js +11 -8
- package/dist/src/presentation/web/components/common/feature-node/feature-node.stories.d.ts +1 -0
- package/dist/src/presentation/web/components/common/feature-node/feature-node.stories.d.ts.map +1 -1
- package/dist/src/presentation/web/components/common/feature-node/feature-node.stories.js +13 -0
- package/dist/src/presentation/web/components/features/control-center/control-center-inner.d.ts.map +1 -1
- package/dist/src/presentation/web/components/features/control-center/control-center-inner.js +3 -1
- package/dist/src/presentation/web/components/features/control-center/use-control-center-state.d.ts +1 -0
- package/dist/src/presentation/web/components/features/control-center/use-control-center-state.d.ts.map +1 -1
- package/dist/src/presentation/web/components/features/control-center/use-control-center-state.js +27 -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 +27 -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/src/presentation/web/lib/derive-graph.d.ts +2 -0
- package/dist/src/presentation/web/lib/derive-graph.d.ts.map +1 -1
- package/dist/src/presentation/web/lib/derive-graph.js +5 -0
- package/dist/src/presentation/web/lib/version.d.ts +5 -5
- package/dist/src/presentation/web/lib/version.d.ts.map +1 -1
- package/dist/src/presentation/web/lib/version.js +26 -12
- 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 +3 -3
- package/web/.next/required-server-files.json +3 -3
- package/web/.next/routes-manifest.json +6 -0
- package/web/.next/server/app/(dashboard)/@drawer/create/page/server-reference-manifest.json +53 -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 +78 -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 +78 -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 +49 -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 +53 -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 +78 -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 +78 -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 +49 -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 +49 -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 -1
- 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/api/version/route.js +1 -1
- package/web/.next/server/app/api/version/route.js.nft.json +1 -1
- 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.js +1 -1
- package/web/.next/server/app/version/page.js.nft.json +1 -1
- package/web/.next/server/app/version/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app-paths-manifest.json +1 -0
- package/web/.next/server/chunks/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/403f9_next_dist_esm_build_templates_app-route_4d623b8e.js +2 -2
- package/web/.next/server/chunks/403f9_next_dist_esm_build_templates_app-route_4d623b8e.js.map +1 -1
- package/web/.next/server/chunks/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]__a402b567._.js +3 -0
- package/web/.next/server/chunks/[root-of-the-server]__a402b567._.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]__cd67a84c._.js +3 -0
- package/web/.next/server/chunks/[root-of-the-server]__cd67a84c._.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/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_a1104008.js +3 -0
- package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_@drawer_repository_[repositoryId]_page_actions_a1104008.js.map +1 -0
- package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_repository_[repositoryId]_page_actions_92642200.js +3 -0
- package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_repository_[repositoryId]_page_actions_92642200.js.map +1 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__039967e3._.js +3 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__039967e3._.js.map +1 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__07a39ff2._.js +3 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__07a39ff2._.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]__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]__2773312c._.js +3 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__2773312c._.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]__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]__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]__cbd8062c._.js +3 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__cbd8062c._.js.map +1 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__e70c5627._.js +3 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__e70c5627._.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/{_a8d9cc2f._.js → _0f2b39f5._.js} +2 -2
- package/web/.next/server/chunks/ssr/{_a8d9cc2f._.js.map → _0f2b39f5._.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/_250a63ae._.js +3 -0
- package/web/.next/server/chunks/ssr/_250a63ae._.js.map +1 -0
- package/web/.next/server/chunks/ssr/{_4059434a._.js → _7cb5afad._.js} +2 -2
- package/web/.next/server/chunks/ssr/{_4059434a._.js.map → _7cb5afad._.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/_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/{_0619c65b._.js → _e8deff2b._.js} +2 -2
- package/web/.next/server/chunks/ssr/_e8deff2b._.js.map +1 -0
- 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__next-internal_server_app_(dashboard)_page_actions_888633e1.js +3 -0
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_888633e1.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_758dfa10._.js → src_presentation_web_ce7cbc3c._.js} +3 -3
- package/web/.next/server/chunks/ssr/{src_presentation_web_758dfa10._.js.map → src_presentation_web_ce7cbc3c._.js.map} +1 -1
- 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_e2604413._.js} +3 -3
- package/web/.next/server/chunks/ssr/{src_presentation_web_7275ce5d._.js.map → src_presentation_web_e2604413._.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 +321 -285
- package/web/.next/static/chunks/{15e6c83214978e2a.js → 0822ebbebff2718d.js} +1 -1
- package/web/.next/static/chunks/{8a2e6fabcbb6720d.js → 14a2cef371a9f42d.js} +1 -1
- package/web/.next/static/chunks/{abb2cdec13050512.js → 262f024806123251.js} +1 -1
- package/web/.next/static/chunks/505ff1e0712e80f9.js +2 -0
- package/web/.next/static/chunks/5558a658fa82a01f.css +1 -0
- package/web/.next/static/chunks/{7f3823482bd3f594.js → 606cf866494330d2.js} +1 -1
- package/web/.next/static/chunks/{524307fe3f73c1cf.js → 7e2854d3352f7f50.js} +2 -2
- package/web/.next/static/chunks/{71733e636d34974a.js → bc638bb542a3718b.js} +1 -1
- package/web/.next/static/chunks/{9144d63a39898da5.js → e7cd8862950038a6.js} +1 -1
- package/web/.next/static/chunks/{229caf9bd06f0c45.js → ee097d181dc97a5d.js} +2 -2
- package/web/.next/static/chunks/{cacd384748cf0bd2.js → f20192b3d50908b7.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/[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/[root-of-the-server]__f47bb8a5._.js +0 -3
- package/web/.next/server/chunks/[root-of-the-server]__f47bb8a5._.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]__357d99f9._.js +0 -3
- package/web/.next/server/chunks/ssr/[root-of-the-server]__357d99f9._.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/_0619c65b._.js.map +0 -1
- package/web/.next/server/chunks/ssr/_6e08ce21._.js +0 -3
- 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/static/chunks/a5bcb76c9dcfaee6.js +0 -2
- package/web/.next/static/chunks/db122a6247f69104.css +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 → cQ78pXvGiKF4oj7-Lefwt}/_buildManifest.js +0 -0
- /package/web/.next/static/{ORc-CcNcyS9ide_AZZ8ay → cQ78pXvGiKF4oj7-Lefwt}/_clientMiddlewareManifest.json +0 -0
- /package/web/.next/static/{ORc-CcNcyS9ide_AZZ8ay → cQ78pXvGiKF4oj7-Lefwt}/_ssgManifest.js +0 -0
package/dist/src/presentation/web/components/common/control-center-drawer/feature-drawer-client.js
CHANGED
|
@@ -5,6 +5,7 @@ import { useRouter, usePathname } from 'next/navigation';
|
|
|
5
5
|
import { toast } from 'sonner';
|
|
6
6
|
import { Loader2, Trash2, Play, Square, Copy, Check, Code2, ExternalLink } from 'lucide-react';
|
|
7
7
|
import { approveFeature } from '../../../app/actions/approve-feature.js';
|
|
8
|
+
import { resumeFeature } from '../../../app/actions/resume-feature.js';
|
|
8
9
|
import { rejectFeature } from '../../../app/actions/reject-feature.js';
|
|
9
10
|
import { getFeatureArtifact } from '../../../app/actions/get-feature-artifact.js';
|
|
10
11
|
import { getResearchArtifact } from '../../../app/actions/get-research-artifact.js';
|
|
@@ -28,6 +29,7 @@ import { useFeatureActions } from '../../common/feature-drawer/use-feature-actio
|
|
|
28
29
|
import { resolveSseEventUpdates } from '../../common/feature-node/derive-feature-state.js';
|
|
29
30
|
import { deriveInitialTab } from './drawer-view.js';
|
|
30
31
|
import { useArtifactFetch } from './use-artifact-fetch.js';
|
|
32
|
+
import { useDrawerSync } from './use-drawer-sync.js';
|
|
31
33
|
export function FeatureDrawerClient({ view: initialView, urlTab }) {
|
|
32
34
|
const featureFlags = useFeatureFlags();
|
|
33
35
|
const router = useRouter();
|
|
@@ -35,7 +37,7 @@ export function FeatureDrawerClient({ view: initialView, urlTab }) {
|
|
|
35
37
|
const rejectSound = useSoundAction('reject');
|
|
36
38
|
// Track the view locally so SSE events can update the drawer type in real-time
|
|
37
39
|
const [view, setView] = useState(initialView);
|
|
38
|
-
// Sync when server re-renders with new props (e.g. after
|
|
40
|
+
// Sync when server re-renders with new props (e.g. after navigation)
|
|
39
41
|
useEffect(() => {
|
|
40
42
|
setView(initialView);
|
|
41
43
|
}, [initialView]);
|
|
@@ -60,15 +62,9 @@ export function FeatureDrawerClient({ view: initialView, urlTab }) {
|
|
|
60
62
|
// fetches (which would fail with "not found" for soft-deleted features).
|
|
61
63
|
if (featureNode.state === 'deleting')
|
|
62
64
|
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
65
|
if (update.state !== undefined || update.lifecycle !== undefined) {
|
|
69
|
-
//
|
|
70
|
-
//
|
|
71
|
-
// without waiting for the router.refresh() round-trip.
|
|
66
|
+
// Update the node data AND re-derive the initial tab so the drawer
|
|
67
|
+
// switches immediately (e.g. prd-review → overview when agent resumes).
|
|
72
68
|
setView((prev) => {
|
|
73
69
|
if (prev.type !== 'feature')
|
|
74
70
|
return prev;
|
|
@@ -81,24 +77,17 @@ export function FeatureDrawerClient({ view: initialView, urlTab }) {
|
|
|
81
77
|
});
|
|
82
78
|
}
|
|
83
79
|
}
|
|
84
|
-
}, [events, featureNode
|
|
80
|
+
}, [events, featureNode]);
|
|
85
81
|
// Derive open state from the URL. Next.js parallel routes preserve slot
|
|
86
82
|
// content during soft navigation, so this component is NOT unmounted when
|
|
87
83
|
// navigating to `/`. Instead, we watch the pathname and let Vaul handle
|
|
88
84
|
// the close animation when the path no longer matches a feature route.
|
|
89
85
|
const pathname = usePathname();
|
|
90
86
|
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;
|
|
87
|
+
// Targeted data sync: fetches fresh FeatureNodeData on drawer open and
|
|
88
|
+
// periodically while open. Replaces router.refresh() to avoid full-page
|
|
89
|
+
// re-renders that cause visible flashing and can reset form state.
|
|
90
|
+
useDrawerSync(isOpen, featureNode?.featureId ?? null, setView);
|
|
102
91
|
const onClose = useCallback(() => {
|
|
103
92
|
router.push('/');
|
|
104
93
|
}, [router]);
|
|
@@ -182,10 +171,6 @@ export function FeatureDrawerClient({ view: initialView, urlTab }) {
|
|
|
182
171
|
featureNode?.state === 'action-required' &&
|
|
183
172
|
Object.keys(prdDefaultSelections).some((k) => prdDefaultSelections[k] !== prdSelections[k]);
|
|
184
173
|
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
174
|
const onReset = useCallback(() => {
|
|
190
175
|
setChatInput('');
|
|
191
176
|
setPrdSelections({ ...prdDefaultSelections });
|
|
@@ -288,6 +273,24 @@ export function FeatureDrawerClient({ view: initialView, urlTab }) {
|
|
|
288
273
|
setIsDeleting(false);
|
|
289
274
|
}
|
|
290
275
|
}, [router, deleteSound]);
|
|
276
|
+
const handleRetry = useCallback(async (featureId) => {
|
|
277
|
+
const result = await resumeFeature(featureId);
|
|
278
|
+
if (result.error) {
|
|
279
|
+
toast.error(result.error);
|
|
280
|
+
return;
|
|
281
|
+
}
|
|
282
|
+
toast.success('Feature resumed — agent restarting');
|
|
283
|
+
// Optimistically update canvas node
|
|
284
|
+
window.dispatchEvent(new CustomEvent('shep:feature-approved', {
|
|
285
|
+
detail: { featureId },
|
|
286
|
+
}));
|
|
287
|
+
// Optimistically update the drawer view
|
|
288
|
+
setView((prev) => {
|
|
289
|
+
if (prev.type !== 'feature')
|
|
290
|
+
return prev;
|
|
291
|
+
return { ...prev, node: { ...prev.node, state: 'running' } };
|
|
292
|
+
});
|
|
293
|
+
}, []);
|
|
291
294
|
// ── Hooks (always called unconditionally per Rules of Hooks) ──────────
|
|
292
295
|
const featureActionsInput = featureNode?.repositoryPath && featureNode?.branch
|
|
293
296
|
? {
|
|
@@ -329,7 +332,8 @@ export function FeatureDrawerClient({ view: initialView, urlTab }) {
|
|
|
329
332
|
// ── Body ──────────────────────────────────────────────────────────────
|
|
330
333
|
let body = null;
|
|
331
334
|
if (view.type === 'feature' && featureNode) {
|
|
332
|
-
|
|
335
|
+
const enrichedNode = featureNode.state === 'error' ? { ...featureNode, onRetry: handleRetry } : featureNode;
|
|
336
|
+
body = (_jsx(FeatureDrawerTabs, { featureNode: enrichedNode, featureId: featureNode.featureId, initialTab: view.initialTab, urlTab: urlTab, sseEvents: events, prdData: prdData, prdSelections: prdSelections, onPrdSelect: (qId, oId) => setPrdSelections((prev) => ({ ...prev, [qId]: oId })), onPrdApprove: handlePrdApprove, onPrdReject: handlePrdReject, isPrdLoading: isLoadingPrd, techData: techData, onTechApprove: handleTechApprove, onTechReject: handleTechReject, isTechLoading: isLoadingTech, productData: isLoadingTechProduct ? null : techProductData, mergeData: mergeData, onMergeApprove: handleMergeApprove, onMergeReject: handleMergeReject, isMergeLoading: isLoadingMerge, isRejecting: isRejecting, chatInput: chatInput, onChatInputChange: setChatInput }));
|
|
333
337
|
}
|
|
334
338
|
return (_jsx(BaseDrawer, { open: isOpen, onClose: attemptClose, size: "md", modal: false, header: header, "data-testid": view.type === 'feature' ? 'feature-drawer' : 'repository-drawer', children: body }));
|
|
335
339
|
}
|
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
|
package/dist/src/presentation/web/components/common/feature-drawer-tabs/overview-tab.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"overview-tab.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/feature-drawer-tabs/overview-tab.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"overview-tab.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/feature-drawer-tabs/overview-tab.tsx"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AAOxE,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,eAAe,CAAC;CACvB;AAED,wBAAgB,WAAW,CAAC,EAAE,IAAI,EAAE,EAAE,gBAAgB,2CAoDrD"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
3
|
import { useState, useEffect, useRef } from 'react';
|
|
4
|
-
import { AlertTriangle, ExternalLink, GitBranch, GitCommitHorizontal, Zap } from 'lucide-react';
|
|
4
|
+
import { AlertTriangle, ExternalLink, GitBranch, GitCommitHorizontal, RotateCcw, Zap, } from 'lucide-react';
|
|
5
5
|
import { InlineAttachments } from '../../common/inline-attachments/index.js';
|
|
6
6
|
import { PrStatus } from '../../../../../../packages/core/src/domain/generated/output.js';
|
|
7
7
|
import { cn } from '../../../lib/utils.js';
|
|
@@ -14,7 +14,7 @@ import { getAgentTypeIcon, agentTypeLabels, } from '../../common/feature-node/ag
|
|
|
14
14
|
import { formatDuration } from '../../../lib/format-duration.js';
|
|
15
15
|
export function OverviewTab({ data }) {
|
|
16
16
|
const isCompleted = data.lifecycle === 'maintain';
|
|
17
|
-
return (_jsxs(_Fragment, { children: [_jsxs("div", { "data-testid": "feature-drawer-status", className: "flex flex-col gap-3 p-4", children: [_jsx("div", { className: "text-muted-foreground text-xs font-semibold tracking-wider", children: lifecycleDisplayLabels[data.lifecycle] }), _jsx(FeatureStateBadge, { data: data }), !isCompleted && data.progress > 0 ? (_jsxs("div", { "data-testid": "feature-drawer-progress", className: "flex flex-col gap-1", children: [_jsxs("div", { className: "text-muted-foreground flex items-center justify-between text-xs", children: [_jsx("span", { children: "Progress" }), _jsxs("span", { children: [data.progress, "%"] })] }), _jsx("div", { className: "bg-muted h-2 w-full overflow-hidden rounded-full", children: _jsx("div", { className: cn('h-full rounded-full transition-all', featureNodeStateConfig[data.state].progressClass), style: { width: `${data.progress}%` } }) })] })) : null, isCompleted && data.pr ? _jsx(FeaturePrInfo, { pr: data.pr }) : null] }), _jsx(FeatureInfo, { data: data }), !isCompleted && data.pr ? (_jsxs(_Fragment, { children: [_jsx(Separator, {}), _jsx("div", { className: "p-4", children: _jsx(FeaturePrInfo, { pr: data.pr }) })] })) : null, _jsx(FeatureDetails, { data: data })] }));
|
|
17
|
+
return (_jsxs(_Fragment, { children: [_jsxs("div", { "data-testid": "feature-drawer-status", className: "flex flex-col gap-3 p-4", children: [_jsx("div", { className: "text-muted-foreground text-xs font-semibold tracking-wider", children: lifecycleDisplayLabels[data.lifecycle] }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsx(FeatureStateBadge, { data: data }), data.state === 'error' && data.onRetry ? (_jsxs("button", { "data-testid": "feature-drawer-retry-button", onClick: () => data.onRetry(data.featureId), className: "flex shrink-0 cursor-pointer items-center gap-1.5 rounded-full bg-red-50 px-3 py-1.5 text-sm font-medium text-red-700 transition-colors hover:bg-red-100", children: [_jsx(RotateCcw, { className: "h-3.5 w-3.5" }), "Retry"] })) : null] }), !isCompleted && data.progress > 0 ? (_jsxs("div", { "data-testid": "feature-drawer-progress", className: "flex flex-col gap-1", children: [_jsxs("div", { className: "text-muted-foreground flex items-center justify-between text-xs", children: [_jsx("span", { children: "Progress" }), _jsxs("span", { children: [data.progress, "%"] })] }), _jsx("div", { className: "bg-muted h-2 w-full overflow-hidden rounded-full", children: _jsx("div", { className: cn('h-full rounded-full transition-all', featureNodeStateConfig[data.state].progressClass), style: { width: `${data.progress}%` } }) })] })) : null, isCompleted && data.pr ? _jsx(FeaturePrInfo, { pr: data.pr }) : null] }), _jsx(FeatureInfo, { data: data }), !isCompleted && data.pr ? (_jsxs(_Fragment, { children: [_jsx(Separator, {}), _jsx("div", { className: "p-4", children: _jsx(FeaturePrInfo, { pr: data.pr }) })] })) : null, _jsx(FeatureDetails, { data: data })] }));
|
|
18
18
|
}
|
|
19
19
|
function FeatureStateBadge({ data }) {
|
|
20
20
|
const config = featureNodeStateConfig[data.state];
|
package/dist/src/presentation/web/components/common/feature-drawer-tabs/overview-tab.stories.d.ts
CHANGED
|
@@ -15,6 +15,8 @@ export declare const DoneWithMergedPr: Story;
|
|
|
15
15
|
export declare const Blocked: Story;
|
|
16
16
|
/** Error state showing error message detail. */
|
|
17
17
|
export declare const Error: Story;
|
|
18
|
+
/** Error state with retry button visible. */
|
|
19
|
+
export declare const ErrorWithRetry: Story;
|
|
18
20
|
/** Minimal data — only required fields, no optional details or PR. */
|
|
19
21
|
export declare const Minimal: Story;
|
|
20
22
|
/** Fast mode feature — shows lightning icon in details section. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"overview-tab.stories.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/feature-drawer-tabs/overview-tab.stories.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"overview-tab.stories.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/feature-drawer-tabs/overview-tab.stories.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAGvD,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAG7C,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,OAAO,WAAW,CAclC,CAAC;AAEF,eAAe,IAAI,CAAC;AACpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,WAAW,CAAC,CAAC;AA0G1C,uEAAuE;AACvE,eAAO,MAAM,OAAO,EAAE,KAErB,CAAC;AAEF,8CAA8C;AAC9C,eAAO,MAAM,IAAI,EAAE,KAElB,CAAC;AAEF,yDAAyD;AACzD,eAAO,MAAM,UAAU,EAAE,KAExB,CAAC;AAEF,wDAAwD;AACxD,eAAO,MAAM,gBAAgB,EAAE,KAE9B,CAAC;AAEF,iDAAiD;AACjD,eAAO,MAAM,OAAO,EAAE,KAErB,CAAC;AAEF,gDAAgD;AAChD,eAAO,MAAM,KAAK,EAAE,KAEnB,CAAC;AAOF,6CAA6C;AAC7C,eAAO,MAAM,cAAc,EAAE,KAE5B,CAAC;AAEF,sEAAsE;AACtE,eAAO,MAAM,OAAO,EAAE,KAErB,CAAC;AAwBF,mEAAmE;AACnE,eAAO,MAAM,QAAQ,EAAE,KAEtB,CAAC;AAMF,0BAA0B;AAC1B,eAAO,MAAM,iBAAiB,EAAE,KAE/B,CAAC;AAEF,sBAAsB;AACtB,eAAO,MAAM,aAAa,EAAE,KAE3B,CAAC;AAEF,oBAAoB;AACpB,eAAO,MAAM,WAAW,EAAE,KAEzB,CAAC;AAEF,sBAAsB;AACtB,eAAO,MAAM,aAAa,EAAE,KAE3B,CAAC;AAEF,gEAAgE;AAChE,eAAO,MAAM,oBAAoB,EAAE,KAclC,CAAC;AAqBF,4DAA4D;AAC5D,eAAO,MAAM,sBAAsB,EAAE,KAEpC,CAAC;AAEF,sDAAsD;AACtD,eAAO,MAAM,gBAAgB,EAAE,KAO9B,CAAC;AAEF,+FAA+F;AAC/F,eAAO,MAAM,eAAe,EAAE,KAgB7B,CAAC"}
|
package/dist/src/presentation/web/components/common/feature-drawer-tabs/overview-tab.stories.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { fn } from '@storybook/test';
|
|
2
3
|
import { PrStatus, CiStatus } from '../../../../../../packages/core/src/domain/generated/output.js';
|
|
3
4
|
import { OverviewTab } from './overview-tab.js';
|
|
4
5
|
const meta = {
|
|
@@ -132,6 +133,14 @@ export const Blocked = {
|
|
|
132
133
|
export const Error = {
|
|
133
134
|
args: { data: errorData },
|
|
134
135
|
};
|
|
136
|
+
const errorWithRetryData = {
|
|
137
|
+
...errorData,
|
|
138
|
+
onRetry: fn(),
|
|
139
|
+
};
|
|
140
|
+
/** Error state with retry button visible. */
|
|
141
|
+
export const ErrorWithRetry = {
|
|
142
|
+
args: { data: errorWithRetryData },
|
|
143
|
+
};
|
|
135
144
|
/** Minimal data — only required fields, no optional details or PR. */
|
|
136
145
|
export const Minimal = {
|
|
137
146
|
args: { data: minimalData },
|
|
@@ -13,12 +13,14 @@ import type { FeatureNodeState, FeatureLifecyclePhase } from './feature-node-sta
|
|
|
13
13
|
* Priority (mirrors CLI formatStatus):
|
|
14
14
|
* 1. Agent waiting_approval → action-required
|
|
15
15
|
* 2. Agent failed → error
|
|
16
|
-
* 3. Agent interrupted/cancelled →
|
|
16
|
+
* 3. Agent interrupted/cancelled → error
|
|
17
17
|
* 4. Agent completed + Maintain lifecycle → done
|
|
18
18
|
* 5. Agent running/pending → running
|
|
19
19
|
* 6. No agent run → fall back to plan tasks / lifecycle
|
|
20
20
|
*/
|
|
21
|
-
export declare function deriveNodeState(feature: Feature, agentRun?: AgentRun | null
|
|
21
|
+
export declare function deriveNodeState(feature: Feature, agentRun?: AgentRun | null, options?: {
|
|
22
|
+
isPidAlive?: boolean;
|
|
23
|
+
}): FeatureNodeState;
|
|
22
24
|
/**
|
|
23
25
|
* Derives progress percentage from Feature.plan.tasks.
|
|
24
26
|
*
|
package/dist/src/presentation/web/components/common/feature-node/derive-feature-state.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"derive-feature-state.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/feature-node/derive-feature-state.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAIL,qBAAqB,EACtB,MAAM,+BAA+B,CAAC;AACvC,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,+BAA+B,CAAC;AACvE,OAAO,KAAK,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,MAAM,6BAA6B,CAAC;AAE3F;;;;;;;;;;GAUG;AACH,wBAAgB,eAAe,
|
|
1
|
+
{"version":3,"file":"derive-feature-state.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/feature-node/derive-feature-state.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAIL,qBAAqB,EACtB,MAAM,+BAA+B,CAAC;AACvC,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,+BAA+B,CAAC;AACvE,OAAO,KAAK,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,MAAM,6BAA6B,CAAC;AAE3F;;;;;;;;;;GAUG;AACH,wBAAgB,eAAe,CAC7B,OAAO,EAAE,OAAO,EAChB,QAAQ,CAAC,EAAE,QAAQ,GAAG,IAAI,EAC1B,OAAO,CAAC,EAAE;IAAE,UAAU,CAAC,EAAE,OAAO,CAAA;CAAE,GACjC,gBAAgB,CAkDlB;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAYvD;AAED,oGAAoG;AACpG,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,qBAAqB,GAAG,gBAAgB,CAoBtF;AAED,wEAAwE;AACxE,eAAO,MAAM,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,qBAAqB,CAOlE,CAAC;AAcF;;;GAGG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,GAAG,IAAI,GAAG,qBAAqB,CAQ7F;AAED,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,gBAAgB,GAAG,SAAS,CAAC;IACpC,SAAS,EAAE,qBAAqB,GAAG,SAAS,CAAC;IAC7C,SAAS,EAAE,qBAAqB,CAAC;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,SAAS;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,qBAAqB,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,EAAE,GAC7F,cAAc,EAAE,CAmBlB;AAED,wBAAgB,uBAAuB,CACrC,SAAS,EAAE,MAAM,GAAG,SAAS,GAC5B,qBAAqB,GAAG,SAAS,CAGnC"}
|
|
@@ -11,12 +11,12 @@ import { SdlcLifecycle, AgentRunStatus, TaskState, NotificationEventType, } from
|
|
|
11
11
|
* Priority (mirrors CLI formatStatus):
|
|
12
12
|
* 1. Agent waiting_approval → action-required
|
|
13
13
|
* 2. Agent failed → error
|
|
14
|
-
* 3. Agent interrupted/cancelled →
|
|
14
|
+
* 3. Agent interrupted/cancelled → error
|
|
15
15
|
* 4. Agent completed + Maintain lifecycle → done
|
|
16
16
|
* 5. Agent running/pending → running
|
|
17
17
|
* 6. No agent run → fall back to plan tasks / lifecycle
|
|
18
18
|
*/
|
|
19
|
-
export function deriveNodeState(feature, agentRun) {
|
|
19
|
+
export function deriveNodeState(feature, agentRun, options) {
|
|
20
20
|
// Deleting lifecycle takes top priority — feature is being removed
|
|
21
21
|
if (feature.lifecycle === SdlcLifecycle.Deleting) {
|
|
22
22
|
return 'deleting';
|
|
@@ -33,11 +33,13 @@ export function deriveNodeState(feature, agentRun) {
|
|
|
33
33
|
return 'error';
|
|
34
34
|
case AgentRunStatus.interrupted:
|
|
35
35
|
case AgentRunStatus.cancelled:
|
|
36
|
-
return '
|
|
36
|
+
return 'error';
|
|
37
37
|
case AgentRunStatus.completed:
|
|
38
38
|
return 'done';
|
|
39
39
|
case AgentRunStatus.running:
|
|
40
40
|
case AgentRunStatus.pending:
|
|
41
|
+
if (options?.isPidAlive === false)
|
|
42
|
+
return 'error';
|
|
41
43
|
return 'running';
|
|
42
44
|
}
|
|
43
45
|
}
|
package/dist/src/presentation/web/components/common/feature-node/feature-node-state-config.d.ts
CHANGED
|
@@ -67,6 +67,7 @@ export interface FeatureNodeData {
|
|
|
67
67
|
onAction?: () => void;
|
|
68
68
|
onSettings?: () => void;
|
|
69
69
|
onDelete?: (featureId: string, cleanup?: boolean) => void;
|
|
70
|
+
onRetry?: (featureId: string) => void;
|
|
70
71
|
showHandles?: boolean;
|
|
71
72
|
}
|
|
72
73
|
export type FeatureNodeType = Node<FeatureNodeData, 'featureNode'>;
|
package/dist/src/presentation/web/components/common/feature-node/feature-node-state-config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"feature-node-state-config.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/feature-node/feature-node-state-config.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"feature-node-state-config.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/feature-node/feature-node-state-config.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"feature-node.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/feature-node/feature-node.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"feature-node.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/feature-node/feature-node.tsx"],"names":[],"mappings":"AAwBA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AA0DnE,wBAAgB,WAAW,CAAC,EAC1B,IAAI,EACJ,QAAQ,GACT,EAAE;IACD,IAAI,EAAE,eAAe,CAAC;IACtB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB,2CAqTA"}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
3
|
import { useState } from 'react';
|
|
4
4
|
import { Handle, Position } from '@xyflow/react';
|
|
5
|
-
import { Plus, FileText, Wrench, GitMerge, Trash2, Zap, Loader2, Globe, } from 'lucide-react';
|
|
5
|
+
import { Plus, FileText, Wrench, GitMerge, Trash2, Zap, Loader2, Globe, RotateCcw, } from 'lucide-react';
|
|
6
6
|
import { cn } from '../../../lib/utils.js';
|
|
7
7
|
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '../../ui/tooltip.js';
|
|
8
8
|
import { DeleteFeatureDialog } from '../../common/delete-feature-dialog/index.js';
|
|
@@ -82,13 +82,16 @@ export function FeatureNode({ data, selected, }) {
|
|
|
82
82
|
? 'bg-blue-50 text-blue-700'
|
|
83
83
|
: 'bg-green-50 text-green-700'), children: [data.deployment.status === DeploymentState.Booting ? (_jsx(Loader2, { className: "h-3 w-3 animate-spin" })) : (_jsx(Globe, { className: "h-3 w-3" })), _jsx("span", { className: "truncate", children: data.deployment.status === DeploymentState.Booting
|
|
84
84
|
? 'Deploying...'
|
|
85
|
-
: (data.deployment.url ?? 'Live') })] })) : null, _jsx("div", { className: "mt-auto pt-2", children: data.state === 'deleting' ? (_jsxs(_Fragment, { children: [_jsxs("div", { className: "mt-1.5 flex items-center gap-1.5 text-xs", children: [_jsx(Trash2, { className: "h-3.5 w-3.5 shrink-0 text-gray-400" }), _jsx("span", { className: "text-muted-foreground", children: "Deleting\u2026" })] }), _jsx("div", { "data-testid": "feature-node-progress-bar", className: "bg-muted mt-1.5 h-1 w-full overflow-hidden rounded-full", children: _jsx("div", { className: "motion-safe:animate-indeterminate-progress bg-foreground/30 h-full w-1/3 rounded-full" }) })] })) : data.state === 'creating' ? (_jsxs(_Fragment, { children: [_jsxs("div", { className: "mt-1.5 flex items-center gap-1.5 text-xs", children: [_jsx(Icon, { className: "h-3.5 w-3.5 shrink-0 animate-spin" }), _jsx("span", { className: "text-muted-foreground", children: getBadgeText(data) })] }), _jsx("div", { "data-testid": "feature-node-progress-bar", className: "bg-muted mt-1.5 h-1 w-full overflow-hidden rounded-full", children: _jsx("div", { className: "motion-safe:animate-indeterminate-progress bg-foreground/30 h-full w-1/3 rounded-full" }) })] })) : data.state === 'running' ? (_jsxs(_Fragment, { children: [_jsxs("div", { className: "mt-1.5 flex items-center gap-1.5 text-xs", children: [_jsx(AgentIcon, { agentType: data.agentType, className: "h-3.5 w-3.5 shrink-0" }), _jsx("span", { className: "text-muted-foreground", children: getBadgeText(data) })] }), _jsx("div", { "data-testid": "feature-node-progress-bar", className: "bg-muted mt-1.5 h-1 w-full overflow-hidden rounded-full", children: _jsx("div", { className: "animate-indeterminate-progress bg-foreground/30 h-full w-1/3 rounded-full" }) })] })) : config.showProgressBar ? (_jsxs(_Fragment, { children: [_jsx("div", { className: "text-muted-foreground flex items-center justify-end text-[10px]", children: _jsxs("span", { children: [data.progress, "%"] }) }), _jsx("div", { "data-testid": "feature-node-progress-bar", className: "bg-muted mt-1.5 h-1 w-full overflow-hidden rounded-full", children: _jsx("div", { className: cn('h-full rounded-full transition-all', config.progressClass), style: { width: `${data.progress}%` } }) })] })) : (_jsxs(_Fragment, { children: [_jsx("div", { className: "text-muted-foreground text-[10px]", children: _jsx("span", { children: data.featureId }) }), _jsxs("div", { "data-testid": "feature-node-badge", className: (() => {
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
85
|
+
: (data.deployment.url ?? 'Live') })] })) : null, _jsx("div", { className: "mt-auto pt-2", children: data.state === 'deleting' ? (_jsxs(_Fragment, { children: [_jsxs("div", { className: "mt-1.5 flex items-center gap-1.5 text-xs", children: [_jsx(Trash2, { className: "h-3.5 w-3.5 shrink-0 text-gray-400" }), _jsx("span", { className: "text-muted-foreground", children: "Deleting\u2026" })] }), _jsx("div", { "data-testid": "feature-node-progress-bar", className: "bg-muted mt-1.5 h-1 w-full overflow-hidden rounded-full", children: _jsx("div", { className: "motion-safe:animate-indeterminate-progress bg-foreground/30 h-full w-1/3 rounded-full" }) })] })) : data.state === 'creating' ? (_jsxs(_Fragment, { children: [_jsxs("div", { className: "mt-1.5 flex items-center gap-1.5 text-xs", children: [_jsx(Icon, { className: "h-3.5 w-3.5 shrink-0 animate-spin" }), _jsx("span", { className: "text-muted-foreground", children: getBadgeText(data) })] }), _jsx("div", { "data-testid": "feature-node-progress-bar", className: "bg-muted mt-1.5 h-1 w-full overflow-hidden rounded-full", children: _jsx("div", { className: "motion-safe:animate-indeterminate-progress bg-foreground/30 h-full w-1/3 rounded-full" }) })] })) : data.state === 'running' ? (_jsxs(_Fragment, { children: [_jsxs("div", { className: "mt-1.5 flex items-center gap-1.5 text-xs", children: [_jsx(AgentIcon, { agentType: data.agentType, className: "h-3.5 w-3.5 shrink-0" }), _jsx("span", { className: "text-muted-foreground", children: getBadgeText(data) })] }), _jsx("div", { "data-testid": "feature-node-progress-bar", className: "bg-muted mt-1.5 h-1 w-full overflow-hidden rounded-full", children: _jsx("div", { className: "animate-indeterminate-progress bg-foreground/30 h-full w-1/3 rounded-full" }) })] })) : config.showProgressBar ? (_jsxs(_Fragment, { children: [_jsx("div", { className: "text-muted-foreground flex items-center justify-end text-[10px]", children: _jsxs("span", { children: [data.progress, "%"] }) }), _jsx("div", { "data-testid": "feature-node-progress-bar", className: "bg-muted mt-1.5 h-1 w-full overflow-hidden rounded-full", children: _jsx("div", { className: cn('h-full rounded-full transition-all', config.progressClass), style: { width: `${data.progress}%` } }) })] })) : (_jsxs(_Fragment, { children: [_jsx("div", { className: "text-muted-foreground text-[10px]", children: _jsx("span", { children: data.featureId }) }), _jsxs("div", { className: "mt-1.5 flex items-center gap-1.5", children: [_jsxs("div", { "data-testid": "feature-node-badge", className: (() => {
|
|
86
|
+
const override = getActionRequiredBadgeClasses(data);
|
|
87
|
+
return cn('flex min-w-0 flex-1 items-center justify-center gap-1.5 rounded-full px-2.5 py-1 text-[11px] font-medium', override?.badgeBgClass ?? config.badgeBgClass, override?.badgeClass ?? config.badgeClass);
|
|
88
|
+
})(), children: [(() => {
|
|
89
|
+
const BadgeIcon = getBadgeIcon(data);
|
|
90
|
+
return _jsx(BadgeIcon, { className: "h-3.5 w-3.5 shrink-0" });
|
|
91
|
+
})(), _jsx("span", { className: "truncate", children: getBadgeText(data) })] }), data.state === 'error' && data.onRetry ? (_jsxs("button", { type: "button", "aria-label": "Retry feature", "data-testid": "feature-node-retry-button", onClick: (e) => {
|
|
92
|
+
e.stopPropagation();
|
|
93
|
+
data.onRetry(data.featureId);
|
|
94
|
+
}, className: "nodrag flex shrink-0 cursor-pointer items-center gap-1 rounded-full bg-red-100 px-2.5 py-1 text-[11px] font-medium text-red-700 transition-colors hover:bg-red-200", children: [_jsx(RotateCcw, { className: "h-3 w-3" }), "Retry"] })) : null] })] })) })] }), data.onAction && data.state !== 'deleting' ? (_jsx(Handle, { type: "source", position: Position.Right, className: "h-0! w-0! border-0! bg-transparent!", children: _jsx("button", { type: "button", "aria-label": "Add", "data-testid": "feature-node-action-button", onClick: (e) => {
|
|
92
95
|
e.stopPropagation();
|
|
93
96
|
data.onAction?.();
|
|
94
97
|
}, className: "nodrag absolute top-1/2 left-1/2 flex h-6 w-6 -translate-x-1/2 -translate-y-1/2 cursor-pointer items-center justify-center rounded-full bg-blue-500 text-white opacity-0 shadow-md transition-opacity group-hover:opacity-100 hover:bg-blue-600", children: _jsx(Plus, { className: "h-3.5 w-3.5" }) }) })) : data.showHandles ? (_jsx(Handle, { type: "source", position: Position.Right, isConnectable: false, className: "opacity-0!" })) : null] }));
|
|
@@ -15,6 +15,7 @@ export declare const Creating: Story;
|
|
|
15
15
|
export declare const MergeReviewActionRequired: Story;
|
|
16
16
|
export declare const Deleting: Story;
|
|
17
17
|
export declare const ErrorWithMessage: Story;
|
|
18
|
+
export declare const ErrorWithRetry: Story;
|
|
18
19
|
export declare const WithDeleteButton: Story;
|
|
19
20
|
export declare const FastMode: Story;
|
|
20
21
|
export declare const FastModeDone: Story;
|
package/dist/src/presentation/web/components/common/feature-node/feature-node.stories.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"feature-node.stories.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/feature-node/feature-node.stories.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAMvD,OAAO,KAAK,EACV,eAAe,EAIhB,MAAM,6BAA6B,CAAC;AAiCrC,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,eAAe,CAc/B,CAAC;AAEF,eAAe,IAAI,CAAC;AACpB,KAAK,KAAK,GAAG,QAAQ,CAAC,eAAe,CAAC,CAAC;AAEvC,eAAO,MAAM,OAAO,EAAE,KAErB,CAAC;AAgHF,eAAO,MAAM,SAAS,EAAE,KAQvB,CAAC;AAWF,eAAO,MAAM,aAAa,EAAE,KAqB3B,CAAC;AA2EF,eAAO,MAAM,aAAa,EAAE,KAQ3B,CAAC;AAEF,eAAO,MAAM,UAAU,EAAE,KAMxB,CAAC;AAEF,eAAO,MAAM,WAAW,EAAE,KAOzB,CAAC;AAEF,eAAO,MAAM,eAAe,EAAE,KAW7B,CAAC;AAEF,eAAO,MAAM,gBAAgB,EAAE,KAW9B,CAAC;AAEF,eAAO,MAAM,QAAQ,EAAE,KAUtB,CAAC;AAEF,eAAO,MAAM,yBAAyB,EAAE,KAUvC,CAAC;AAEF,eAAO,MAAM,QAAQ,EAAE,KAUtB,CAAC;AAEF,eAAO,MAAM,gBAAgB,EAAE,KAW9B,CAAC;AAEF,eAAO,MAAM,gBAAgB,EAAE,KAW9B,CAAC;AAEF,eAAO,MAAM,QAAQ,EAAE,KAatB,CAAC;AAEF,eAAO,MAAM,YAAY,EAAE,KAc1B,CAAC;AAEF,eAAO,MAAM,iBAAiB,EAAE,KAY/B,CAAC;AAEF,eAAO,MAAM,eAAe,EAAE,KAa7B,CAAC;AAEF,eAAO,MAAM,oBAAoB,EAAE,KAYlC,CAAC;AA4EF,eAAO,MAAM,WAAW,EAAE,KAOzB,CAAC"}
|
|
1
|
+
{"version":3,"file":"feature-node.stories.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/feature-node/feature-node.stories.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAMvD,OAAO,KAAK,EACV,eAAe,EAIhB,MAAM,6BAA6B,CAAC;AAiCrC,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,eAAe,CAc/B,CAAC;AAEF,eAAe,IAAI,CAAC;AACpB,KAAK,KAAK,GAAG,QAAQ,CAAC,eAAe,CAAC,CAAC;AAEvC,eAAO,MAAM,OAAO,EAAE,KAErB,CAAC;AAgHF,eAAO,MAAM,SAAS,EAAE,KAQvB,CAAC;AAWF,eAAO,MAAM,aAAa,EAAE,KAqB3B,CAAC;AA2EF,eAAO,MAAM,aAAa,EAAE,KAQ3B,CAAC;AAEF,eAAO,MAAM,UAAU,EAAE,KAMxB,CAAC;AAEF,eAAO,MAAM,WAAW,EAAE,KAOzB,CAAC;AAEF,eAAO,MAAM,eAAe,EAAE,KAW7B,CAAC;AAEF,eAAO,MAAM,gBAAgB,EAAE,KAW9B,CAAC;AAEF,eAAO,MAAM,QAAQ,EAAE,KAUtB,CAAC;AAEF,eAAO,MAAM,yBAAyB,EAAE,KAUvC,CAAC;AAEF,eAAO,MAAM,QAAQ,EAAE,KAUtB,CAAC;AAEF,eAAO,MAAM,gBAAgB,EAAE,KAW9B,CAAC;AAEF,eAAO,MAAM,cAAc,EAAE,KAY5B,CAAC;AAEF,eAAO,MAAM,gBAAgB,EAAE,KAW9B,CAAC;AAEF,eAAO,MAAM,QAAQ,EAAE,KAatB,CAAC;AAEF,eAAO,MAAM,YAAY,EAAE,KAc1B,CAAC;AAEF,eAAO,MAAM,iBAAiB,EAAE,KAY/B,CAAC;AAEF,eAAO,MAAM,eAAe,EAAE,KAa7B,CAAC;AAEF,eAAO,MAAM,oBAAoB,EAAE,KAYlC,CAAC;AA4EF,eAAO,MAAM,WAAW,EAAE,KAOzB,CAAC"}
|
|
@@ -319,6 +319,19 @@ export const ErrorWithMessage = {
|
|
|
319
319
|
},
|
|
320
320
|
render: (args) => _jsx(FeatureNodeCanvas, { data: args }),
|
|
321
321
|
};
|
|
322
|
+
export const ErrorWithRetry = {
|
|
323
|
+
args: {
|
|
324
|
+
name: 'Email Service',
|
|
325
|
+
description: 'Transactional email with SendGrid',
|
|
326
|
+
featureId: '#f5',
|
|
327
|
+
lifecycle: 'review',
|
|
328
|
+
state: 'error',
|
|
329
|
+
progress: 30,
|
|
330
|
+
errorMessage: 'Build failed: type mismatch',
|
|
331
|
+
onRetry: fn(),
|
|
332
|
+
},
|
|
333
|
+
render: (args) => _jsx(FeatureNodeCanvas, { data: args }),
|
|
334
|
+
};
|
|
322
335
|
export const WithDeleteButton = {
|
|
323
336
|
args: {
|
|
324
337
|
name: 'Auth Module',
|
package/dist/src/presentation/web/components/features/control-center/control-center-inner.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"control-center-inner.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/control-center/control-center-inner.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,IAAI,EAAY,MAAM,eAAe,CAAC;AAGpD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uCAAuC,CAAC;AAsB5E,UAAU,uBAAuB;IAC/B,YAAY,EAAE,cAAc,EAAE,CAAC;IAC/B,YAAY,EAAE,IAAI,EAAE,CAAC;CACtB;AAED,wBAAgB,kBAAkB,CAAC,EAAE,YAAY,EAAE,YAAY,EAAE,EAAE,uBAAuB,
|
|
1
|
+
{"version":3,"file":"control-center-inner.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/control-center/control-center-inner.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,IAAI,EAAY,MAAM,eAAe,CAAC;AAGpD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uCAAuC,CAAC;AAsB5E,UAAU,uBAAuB;IAC/B,YAAY,EAAE,cAAc,EAAE,CAAC;IAC/B,YAAY,EAAE,IAAI,EAAE,CAAC;CACtB;AAED,wBAAgB,kBAAkB,CAAC,EAAE,YAAY,EAAE,YAAY,EAAE,EAAE,uBAAuB,2CAuTzF"}
|
package/dist/src/presentation/web/components/features/control-center/control-center-inner.js
CHANGED
|
@@ -26,7 +26,7 @@ export function ControlCenterInner({ initialNodes, initialEdges }) {
|
|
|
26
26
|
const { fitView } = useReactFlow();
|
|
27
27
|
const drawerTimerRef = useRef(null);
|
|
28
28
|
const { defaultViewport, onMoveEnd: handleViewportChange, resetViewport, } = useViewportPersistence();
|
|
29
|
-
const { nodes, edges, onNodesChange, handleConnect, handleAddRepository, handleDeleteFeature, handleDeleteRepository, createFeatureNode, setCallbacks, } = useControlCenterState(initialNodes, initialEdges);
|
|
29
|
+
const { nodes, edges, onNodesChange, handleConnect, handleAddRepository, handleDeleteFeature, handleRetryFeature, handleDeleteRepository, createFeatureNode, setCallbacks, } = useControlCenterState(initialNodes, initialEdges);
|
|
30
30
|
// Publish sidebar features to context whenever feature node data changes
|
|
31
31
|
const { setFeatures: setSidebarFeatures } = useSidebarFeaturesContext();
|
|
32
32
|
const featureNodes = useMemo(() => nodes.filter((n) => n.type === 'featureNode'), [nodes]);
|
|
@@ -179,6 +179,7 @@ export function ControlCenterInner({ initialNodes, initialEdges }) {
|
|
|
179
179
|
setCallbacks({
|
|
180
180
|
onNodeAction: handleAddFeatureToFeature,
|
|
181
181
|
onFeatureDelete: handleDeleteFeature,
|
|
182
|
+
onRetryFeature: handleRetryFeature,
|
|
182
183
|
onRepositoryAdd: handleAddFeatureToRepo,
|
|
183
184
|
onRepositoryClick: handleRepositoryClick,
|
|
184
185
|
onRepositoryDelete: handleDeleteRepository,
|
|
@@ -187,6 +188,7 @@ export function ControlCenterInner({ initialNodes, initialEdges }) {
|
|
|
187
188
|
setCallbacks,
|
|
188
189
|
handleAddFeatureToFeature,
|
|
189
190
|
handleDeleteFeature,
|
|
191
|
+
handleRetryFeature,
|
|
190
192
|
handleAddFeatureToRepo,
|
|
191
193
|
handleRepositoryClick,
|
|
192
194
|
handleDeleteRepository,
|
package/dist/src/presentation/web/components/features/control-center/use-control-center-state.d.ts
CHANGED
|
@@ -15,6 +15,7 @@ export interface ControlCenterState {
|
|
|
15
15
|
};
|
|
16
16
|
handleLayout: (direction: LayoutDirection) => void;
|
|
17
17
|
handleDeleteFeature: (featureId: string, cleanup?: boolean) => void;
|
|
18
|
+
handleRetryFeature: (featureId: string) => void;
|
|
18
19
|
handleDeleteRepository: (repositoryId: string) => Promise<void>;
|
|
19
20
|
createFeatureNode: (sourceNodeId: string | null, dataOverride?: Partial<FeatureNodeData>, edgeType?: string) => string;
|
|
20
21
|
/** Stable lookup: repositoryPath for a feature node. */
|
|
@@ -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;AAcjC,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,
|
|
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;AAcjC,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,kBAAkB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAChD,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,CA6bpB"}
|
package/dist/src/presentation/web/components/features/control-center/use-control-center-state.js
CHANGED
|
@@ -4,10 +4,10 @@ import { useRouter } from 'next/navigation';
|
|
|
4
4
|
import { toast } from 'sonner';
|
|
5
5
|
import { layoutWithDagre, CANVAS_LAYOUT_DEFAULTS, } from '../../../lib/layout-with-dagre.js';
|
|
6
6
|
import { deleteFeature } from '../../../app/actions/delete-feature.js';
|
|
7
|
+
import { resumeFeature } from '../../../app/actions/resume-feature.js';
|
|
7
8
|
import { addRepository } from '../../../app/actions/add-repository.js';
|
|
8
9
|
import { deleteRepository } from '../../../app/actions/delete-repository.js';
|
|
9
10
|
import { getFeatureMetadata } from '../../../app/actions/get-feature-metadata.js';
|
|
10
|
-
import { fetchGraphData } from '../../../app/actions/get-graph-data.js';
|
|
11
11
|
import { useAgentEventsContext } from '../../../hooks/agent-events-provider.js';
|
|
12
12
|
import { useSoundAction } from '../../../hooks/use-sound-action.js';
|
|
13
13
|
import { createLogger } from '../../../lib/logger.js';
|
|
@@ -157,7 +157,12 @@ export function useControlCenterState(initialNodes, initialEdges) {
|
|
|
157
157
|
log.debug(`polling enabled (${POLL_INTERVAL_MS}ms interval)`);
|
|
158
158
|
const timer = setInterval(async () => {
|
|
159
159
|
try {
|
|
160
|
-
|
|
160
|
+
// Use a plain fetch instead of a server action so the poll
|
|
161
|
+
// doesn't trigger the Next.js "Rendering…" indicator.
|
|
162
|
+
const res = await fetch('/api/graph-data');
|
|
163
|
+
if (!res.ok)
|
|
164
|
+
throw new Error(`status ${res.status}`);
|
|
165
|
+
const { nodes: freshNodes, edges: freshEdges } = await res.json();
|
|
161
166
|
reconcile(freshNodes, freshEdges);
|
|
162
167
|
}
|
|
163
168
|
catch {
|
|
@@ -197,6 +202,25 @@ export function useControlCenterState(initialNodes, initialEdges) {
|
|
|
197
202
|
addPendingFeature(id, newFeatureData, parentNodeId);
|
|
198
203
|
return id;
|
|
199
204
|
}, [addPendingFeature]);
|
|
205
|
+
const handleRetryFeature = useCallback((featureId) => {
|
|
206
|
+
const nodeId = `feat-${featureId}`;
|
|
207
|
+
// Optimistic: switch to running state
|
|
208
|
+
updateFeature(nodeId, { state: 'running' });
|
|
209
|
+
resumeFeature(featureId)
|
|
210
|
+
.then((result) => {
|
|
211
|
+
if (result.error) {
|
|
212
|
+
updateFeature(nodeId, { state: 'error' });
|
|
213
|
+
toast.error(result.error);
|
|
214
|
+
}
|
|
215
|
+
else {
|
|
216
|
+
toast.success('Feature resumed');
|
|
217
|
+
}
|
|
218
|
+
})
|
|
219
|
+
.catch(() => {
|
|
220
|
+
updateFeature(nodeId, { state: 'error' });
|
|
221
|
+
toast.error('Failed to resume feature');
|
|
222
|
+
});
|
|
223
|
+
}, [updateFeature]);
|
|
200
224
|
const handleDeleteFeature = useCallback((featureId, cleanup) => {
|
|
201
225
|
const nodeId = `feat-${featureId}`;
|
|
202
226
|
// Collect all descendant feature node IDs (children, grandchildren, etc.)
|
|
@@ -353,6 +377,7 @@ export function useControlCenterState(initialNodes, initialEdges) {
|
|
|
353
377
|
handleAddRepository,
|
|
354
378
|
handleLayout,
|
|
355
379
|
handleDeleteFeature,
|
|
380
|
+
handleRetryFeature,
|
|
356
381
|
handleDeleteRepository,
|
|
357
382
|
createFeatureNode,
|
|
358
383
|
getFeatureRepositoryPath,
|