@shepai/cli 1.122.2-pr390.b1ef40f → 1.122.2-pr392.a8f2b76
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/presentation/web/app/(dashboard)/get-graph-data.d.ts +0 -6
- package/dist/src/presentation/web/app/(dashboard)/get-graph-data.d.ts.map +1 -1
- package/dist/src/presentation/web/app/(dashboard)/get-graph-data.js +0 -60
- package/dist/src/presentation/web/app/actions/get-feature-phase-timings.d.ts +2 -0
- package/dist/src/presentation/web/app/actions/get-feature-phase-timings.d.ts.map +1 -1
- package/dist/src/presentation/web/app/actions/get-feature-phase-timings.js +2 -0
- package/dist/src/presentation/web/app/build-graph-nodes.d.ts +0 -7
- package/dist/src/presentation/web/app/build-graph-nodes.d.ts.map +1 -1
- package/dist/src/presentation/web/app/build-graph-nodes.js +0 -7
- package/dist/src/presentation/web/components/common/feature-create-drawer/feature-create-drawer.d.ts.map +1 -1
- package/dist/src/presentation/web/components/common/feature-create-drawer/feature-create-drawer.js +20 -9
- package/dist/src/presentation/web/components/common/feature-drawer-tabs/activity-tab.d.ts.map +1 -1
- package/dist/src/presentation/web/components/common/feature-drawer-tabs/activity-tab.js +130 -31
- 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 +13 -0
- package/dist/src/presentation/web/components/common/feature-drawer-tabs/use-tab-data-fetch.d.ts.map +1 -1
- package/dist/src/presentation/web/components/common/feature-drawer-tabs/use-tab-data-fetch.js +18 -9
- package/dist/src/presentation/web/components/common/repository-node/repository-node-config.d.ts +0 -8
- package/dist/src/presentation/web/components/common/repository-node/repository-node-config.d.ts.map +1 -1
- package/dist/src/presentation/web/components/common/repository-node/repository-node.d.ts.map +1 -1
- package/dist/src/presentation/web/components/common/repository-node/repository-node.js +6 -6
- package/dist/src/presentation/web/components/common/repository-node/repository-node.stories.d.ts +0 -2
- package/dist/src/presentation/web/components/common/repository-node/repository-node.stories.d.ts.map +1 -1
- package/dist/src/presentation/web/components/common/repository-node/repository-node.stories.js +17 -107
- package/dist/src/presentation/web/components/features/control-center/control-center-empty-state.d.ts.map +1 -1
- package/dist/src/presentation/web/components/features/control-center/control-center-empty-state.js +18 -18
- 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 +31 -17
- package/dist/src/presentation/web/components/features/control-center/welcome-agent-setup.d.ts.map +1 -1
- package/dist/src/presentation/web/components/features/control-center/welcome-agent-setup.js +29 -22
- package/dist/src/presentation/web/components/features/features-canvas/features-canvas.js +1 -1
- package/dist/src/presentation/web/components/layouts/app-shell/app-shell.d.ts.map +1 -1
- package/dist/src/presentation/web/components/layouts/app-shell/app-shell.js +2 -2
- package/dist/src/presentation/web/hooks/sidebar-features-context.d.ts +2 -0
- package/dist/src/presentation/web/hooks/sidebar-features-context.d.ts.map +1 -1
- package/dist/src/presentation/web/hooks/sidebar-features-context.js +2 -1
- package/dist/src/presentation/web/lib/layout-with-dagre.js +1 -1
- 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/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 +22 -22
- package/web/.next/server/app/(dashboard)/@drawer/create/page.js +2 -2
- 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 +28 -28
- package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page.js +3 -3
- 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 +28 -28
- 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 +20 -20
- package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page.js +2 -2
- 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 +22 -22
- package/web/.next/server/app/(dashboard)/create/page.js +2 -2
- 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 +28 -28
- package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page.js +3 -3
- 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 +28 -28
- 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 +20 -20
- package/web/.next/server/app/(dashboard)/page.js +2 -2
- 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 +20 -20
- package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page.js +2 -2
- 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/graph-data/route.js +1 -1
- package/web/.next/server/app/api/graph-data/route.js.nft.json +1 -1
- package/web/.next/server/app/settings/page/server-reference-manifest.json +6 -6
- 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_client-reference-manifest.js +1 -1
- package/web/.next/server/app/tools/page/server-reference-manifest.json +6 -6
- package/web/.next/server/app/tools/page.js.nft.json +1 -1
- package/web/.next/server/app/tools/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/version/page/server-reference-manifest.json +1 -1
- package/web/.next/server/app/version/page_client-reference-manifest.js +1 -1
- package/web/.next/server/chunks/403f9_next_dist_esm_build_templates_app-route_370c43b1.js +1 -1
- package/web/.next/server/chunks/403f9_next_dist_esm_build_templates_app-route_370c43b1.js.map +1 -1
- package/web/.next/server/chunks/[root-of-the-server]__42b7ab55._.js +3 -0
- package/web/.next/server/chunks/{[root-of-the-server]__dcd4f847._.js.map → [root-of-the-server]__42b7ab55._.js.map} +1 -1
- package/web/.next/server/chunks/[root-of-the-server]__a402b567._.js +1 -1
- package/web/.next/server/chunks/ssr/403f9_next_dist_31ea46d3._.js +1 -1
- package/web/.next/server/chunks/ssr/403f9_next_dist_c9d9b4d7._.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_f30d0343.js +1 -1
- package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_@drawer_repository_[repositoryId]_page_actions_f30d0343.js.map +1 -1
- package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_repository_[repositoryId]_page_actions_9f1775bb.js +1 -1
- package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_repository_[repositoryId]_page_actions_9f1775bb.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__06fef644._.js +1 -1
- package/web/.next/server/chunks/ssr/{[root-of-the-server]__9e8b25ad._.js → [root-of-the-server]__2698e9f4._.js} +2 -2
- package/web/.next/server/chunks/ssr/[root-of-the-server]__2698e9f4._.js.map +1 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__545792ab._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__545792ab._.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]__6bb00d90._.js +2 -2
- package/web/.next/server/chunks/ssr/[root-of-the-server]__6bb00d90._.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]__8c553503._.js +2 -2
- package/web/.next/server/chunks/ssr/{[root-of-the-server]__7cbda1ea._.js → [root-of-the-server]__8e3bf5d7._.js} +2 -2
- package/web/.next/server/chunks/ssr/[root-of-the-server]__8e3bf5d7._.js.map +1 -0
- package/web/.next/server/chunks/ssr/{[root-of-the-server]__14664e9b._.js → [root-of-the-server]__a022445f._.js} +3 -3
- package/web/.next/server/chunks/ssr/{[root-of-the-server]__14664e9b._.js.map → [root-of-the-server]__a022445f._.js.map} +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__a7de2711._.js +2 -2
- package/web/.next/server/chunks/ssr/[root-of-the-server]__b724df9e._.js +3 -0
- package/web/.next/server/chunks/ssr/{[root-of-the-server]__6677a82c._.js.map → [root-of-the-server]__b724df9e._.js.map} +1 -1
- package/web/.next/server/chunks/ssr/{[root-of-the-server]__aed1d6f8._.js → [root-of-the-server]__c07f9f79._.js} +2 -2
- package/web/.next/server/chunks/ssr/[root-of-the-server]__c07f9f79._.js.map +1 -0
- package/web/.next/server/chunks/ssr/{[root-of-the-server]__ce6057f6._.js → [root-of-the-server]__c605a375._.js} +2 -2
- package/web/.next/server/chunks/ssr/[root-of-the-server]__c605a375._.js.map +1 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__f646b99a._.js +3 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__f646b99a._.js.map +1 -0
- package/web/.next/server/chunks/ssr/{_e9703421._.js → _0dc2cfd3._.js} +2 -2
- package/web/.next/server/chunks/ssr/_0dc2cfd3._.js.map +1 -0
- 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/_2f6f48b8._.js +1 -1
- package/web/.next/server/chunks/ssr/_2f6f48b8._.js.map +1 -1
- package/web/.next/server/chunks/ssr/{_15fe9326._.js → _36dccae9._.js} +2 -2
- package/web/.next/server/chunks/ssr/_36dccae9._.js.map +1 -0
- package/web/.next/server/chunks/ssr/_3a4c94e3._.js +1 -1
- package/web/.next/server/chunks/ssr/_75f4ccb3._.js +3 -0
- package/web/.next/server/chunks/ssr/_75f4ccb3._.js.map +1 -0
- 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/_d99705a5._.js +3 -0
- package/web/.next/server/chunks/ssr/_d99705a5._.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/node_modules__pnpm_b59e4b16._.js +3 -0
- package/web/.next/server/chunks/ssr/node_modules__pnpm_b59e4b16._.js.map +1 -0
- package/web/.next/server/chunks/ssr/src_presentation_web_5f039db1._.js +2 -2
- package/web/.next/server/chunks/ssr/src_presentation_web_5f039db1._.js.map +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_60c91521._.js +3 -0
- package/web/.next/server/chunks/ssr/src_presentation_web_60c91521._.js.map +1 -0
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_2a52b697.js +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_2a52b697.js.map +1 -1
- 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_c4337169._.js +2 -2
- package/web/.next/server/chunks/ssr/src_presentation_web_c4337169._.js.map +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_ca99d62d._.js +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_ca99d62d._.js.map +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_components_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_e599bb8c._.js +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_components_e599bb8c._.js.map +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_components_features_control-center_7ac3562e._.js +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_components_features_control-center_7ac3562e._.js.map +1 -1
- package/web/.next/server/pages/500.html +2 -2
- package/web/.next/server/server-reference-manifest.js +1 -1
- package/web/.next/server/server-reference-manifest.json +34 -34
- package/web/.next/static/chunks/{2c0cf874cda01236.js → 1c19bf1f99269544.js} +1 -1
- package/web/.next/static/chunks/275f0d403059b5b4.js +1 -0
- package/web/.next/static/chunks/3911a7175044e784.js +1 -0
- package/web/.next/static/chunks/61df7e9671cf4e76.css +1 -0
- package/web/.next/static/chunks/{fadc79bbbae100a7.js → 6272719b144b6c1a.js} +1 -1
- package/web/.next/static/chunks/691a93561029b01b.js +2 -0
- package/web/.next/static/chunks/6db4aa6aed9e6545.js +1 -0
- package/web/.next/static/chunks/{9fba6bb38ff0cb38.js → 816ee0f2c6b490a4.js} +2 -2
- package/web/.next/static/chunks/845d8e58a91014e6.js +1 -0
- package/web/.next/static/chunks/{24a0b215d72d8f26.js → 90e7434ef9395b62.js} +1 -1
- package/web/.next/static/chunks/a92706d178a3fa6c.js +1 -0
- package/web/.next/static/chunks/bf479173877b0a2f.js +1 -0
- package/web/.next/static/chunks/{96eeeb28e06de78c.js → dbbb446493f21874.js} +1 -1
- package/web/.next/static/chunks/f90f55b8e972bd8e.js +1 -0
- package/web/.next/server/chunks/[root-of-the-server]__dcd4f847._.js +0 -3
- package/web/.next/server/chunks/ssr/[root-of-the-server]__6677a82c._.js +0 -3
- package/web/.next/server/chunks/ssr/[root-of-the-server]__7cbda1ea._.js.map +0 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__9e8b25ad._.js.map +0 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__aed1d6f8._.js.map +0 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__ce6057f6._.js.map +0 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__e7258841._.js +0 -3
- package/web/.next/server/chunks/ssr/[root-of-the-server]__e7258841._.js.map +0 -1
- package/web/.next/server/chunks/ssr/_15fe9326._.js.map +0 -1
- package/web/.next/server/chunks/ssr/_90a34ae9._.js +0 -3
- package/web/.next/server/chunks/ssr/_90a34ae9._.js.map +0 -1
- package/web/.next/server/chunks/ssr/_b56e7571._.js +0 -3
- package/web/.next/server/chunks/ssr/_b56e7571._.js.map +0 -1
- package/web/.next/server/chunks/ssr/_e9703421._.js.map +0 -1
- package/web/.next/server/chunks/ssr/_f096ab6a._.js +0 -3
- package/web/.next/server/chunks/ssr/_f096ab6a._.js.map +0 -1
- package/web/.next/server/chunks/ssr/node_modules__pnpm_bc66dcc6._.js +0 -3
- package/web/.next/server/chunks/ssr/node_modules__pnpm_bc66dcc6._.js.map +0 -1
- package/web/.next/static/chunks/4232eb19944a519e.js +0 -1
- package/web/.next/static/chunks/4443ee9c7733399b.js +0 -1
- package/web/.next/static/chunks/6b8c3e3d8d4ee08e.js +0 -1
- package/web/.next/static/chunks/a58429fc5be52aad.js +0 -1
- package/web/.next/static/chunks/b200a40ffcc15eb7.css +0 -1
- package/web/.next/static/chunks/b67d183d3c074a4c.js +0 -2
- package/web/.next/static/chunks/ca946dcbfbb2df74.js +0 -1
- package/web/.next/static/chunks/cd2bb43fe9138791.js +0 -1
- package/web/.next/static/chunks/d2bfdee31e1a7d8d.js +0 -1
- /package/web/.next/static/{Fr059mDxLxW71ARoHnB8W → x39t_TXToqcf-uNwPMhq8}/_buildManifest.js +0 -0
- /package/web/.next/static/{Fr059mDxLxW71ARoHnB8W → x39t_TXToqcf-uNwPMhq8}/_clientMiddlewareManifest.json +0 -0
- /package/web/.next/static/{Fr059mDxLxW71ARoHnB8W → x39t_TXToqcf-uNwPMhq8}/_ssgManifest.js +0 -0
package/dist/src/presentation/web/components/common/feature-drawer-tabs/use-tab-data-fetch.js
CHANGED
|
@@ -54,11 +54,16 @@ export function useTabDataFetch(featureId, fetchers) {
|
|
|
54
54
|
const currentFeatureId = featureIdRef.current;
|
|
55
55
|
if (!fetcher)
|
|
56
56
|
return;
|
|
57
|
+
// Only show loading spinner when there's no existing data.
|
|
58
|
+
// On refresh (data already present), keep showing stale data while fetching
|
|
59
|
+
// to avoid flickering the entire tab on every poll cycle.
|
|
57
60
|
if (mountedRef.current) {
|
|
58
|
-
setTabStates((prev) =>
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
61
|
+
setTabStates((prev) => {
|
|
62
|
+
const hasData = prev[tab]?.data !== null;
|
|
63
|
+
if (hasData)
|
|
64
|
+
return prev; // Keep stale data visible — no loading flash
|
|
65
|
+
return { ...prev, [tab]: { ...prev[tab], loading: true, error: null } };
|
|
66
|
+
});
|
|
62
67
|
}
|
|
63
68
|
try {
|
|
64
69
|
const data = await fetcher(currentFeatureId);
|
|
@@ -71,11 +76,15 @@ export function useTabDataFetch(featureId, fetchers) {
|
|
|
71
76
|
}
|
|
72
77
|
catch (error) {
|
|
73
78
|
if (mountedRef.current) {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
[tab]
|
|
78
|
-
|
|
79
|
+
setTabStates((prev) => {
|
|
80
|
+
const message = error instanceof Error ? error.message : 'Failed to fetch tab data';
|
|
81
|
+
// On refresh failure, keep existing data instead of clearing it
|
|
82
|
+
const existingData = prev[tab]?.data ?? null;
|
|
83
|
+
return {
|
|
84
|
+
...prev,
|
|
85
|
+
[tab]: { data: existingData, loading: false, error: existingData ? null : message },
|
|
86
|
+
};
|
|
87
|
+
});
|
|
79
88
|
}
|
|
80
89
|
}
|
|
81
90
|
}, []);
|
package/dist/src/presentation/web/components/common/repository-node/repository-node-config.d.ts
CHANGED
|
@@ -9,14 +9,6 @@ export interface RepositoryNodeData {
|
|
|
9
9
|
repositoryPath?: string;
|
|
10
10
|
/** Creation timestamp (epoch ms) — used for stable vertical ordering. */
|
|
11
11
|
createdAt?: number;
|
|
12
|
-
/** Current git branch name (e.g. "main", "feat/my-feature") */
|
|
13
|
-
branch?: string;
|
|
14
|
-
/** Commit message of the branch HEAD (first line only) */
|
|
15
|
-
commitMessage?: string;
|
|
16
|
-
/** Name of the person who made the latest commit */
|
|
17
|
-
committer?: string;
|
|
18
|
-
/** Number of commits the current branch is behind the default branch. null if on default branch or unknown. */
|
|
19
|
-
behindCount?: number | null;
|
|
20
12
|
onClick?: () => void;
|
|
21
13
|
onAdd?: () => void;
|
|
22
14
|
onDelete?: (repositoryId: string) => void;
|
package/dist/src/presentation/web/components/common/repository-node/repository-node-config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"repository-node-config.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/repository-node/repository-node-config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAE1C,MAAM,WAAW,kBAAkB;IACjC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;IACvB,qEAAqE;IACrE,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,0CAA0C;IAC1C,IAAI,EAAE,MAAM,CAAC;IACb,uEAAuE;IACvE,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,yEAAyE;IACzE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB
|
|
1
|
+
{"version":3,"file":"repository-node-config.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/repository-node/repository-node-config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAE1C,MAAM,WAAW,kBAAkB;IACjC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;IACvB,qEAAqE;IACrE,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,0CAA0C;IAC1C,IAAI,EAAE,MAAM,CAAC;IACb,uEAAuE;IACvE,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,yEAAyE;IACzE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,IAAI,CAAC;IACnB,QAAQ,CAAC,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1C,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,+EAA+E;IAC/E,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,MAAM,kBAAkB,GAAG,IAAI,CAAC,kBAAkB,EAAE,gBAAgB,CAAC,CAAC"}
|
package/dist/src/presentation/web/components/common/repository-node/repository-node.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"repository-node.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/repository-node/repository-node.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"repository-node.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/repository-node/repository-node.tsx"],"names":[],"mappings":"AAsBA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAOnE,wBAAgB,cAAc,CAAC,EAAE,IAAI,EAAE,EAAE;IAAE,IAAI,EAAE,kBAAkB,CAAC;IAAC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CAAE,2CAyR5F"}
|
|
@@ -3,7 +3,7 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
|
|
|
3
3
|
import { useState, useCallback } from 'react';
|
|
4
4
|
import { Handle, Position } from '@xyflow/react';
|
|
5
5
|
import { useRouter } from 'next/navigation';
|
|
6
|
-
import { Github, Plus, Code2, Terminal, FolderOpen, Trash2, Play, Square
|
|
6
|
+
import { Github, Plus, Code2, Terminal, FolderOpen, Trash2, Play, Square } from 'lucide-react';
|
|
7
7
|
import { cn } from '../../../lib/utils.js';
|
|
8
8
|
import { ActionButton } from '../../common/action-button/index.js';
|
|
9
9
|
import { Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from '../../ui/dialog.js';
|
|
@@ -72,9 +72,9 @@ export function RepositoryNode({ data }) {
|
|
|
72
72
|
e.stopPropagation();
|
|
73
73
|
data.onClick?.();
|
|
74
74
|
}
|
|
75
|
-
}, className: "nodrag bg-card flex w-[
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
75
|
+
}, className: "nodrag bg-card flex min-w-[18rem] cursor-pointer items-center gap-3 rounded-full border px-4 py-3 shadow-sm", children: [_jsx(Github, { className: "text-muted-foreground h-5 w-5 shrink-0" }), _jsx("span", { "data-testid": "repository-node-name", className: "min-w-0 truncate text-sm font-medium", children: data.name }), _jsxs("div", { className: cn('flex shrink-0 items-center gap-2', (data.repositoryPath ?? data.onAdd) && 'ml-auto'), onClick: (e) => e.stopPropagation(), children: [data.repositoryPath ? (_jsxs(_Fragment, { children: [_jsx(TooltipProvider, { children: _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("span", { className: "flex items-center", children: _jsx(ActionButton, { label: "Open in IDE", onClick: actions.openInIde, loading: actions.ideLoading, error: !!actions.ideError, icon: Code2, iconOnly: true, variant: "ghost", size: "icon-xs" }) }) }), _jsx(TooltipContent, { children: "Open in IDE" })] }) }), _jsx(TooltipProvider, { children: _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("span", { className: "flex items-center", children: _jsx(ActionButton, { label: "Open in Shell", onClick: actions.openInShell, loading: actions.shellLoading, error: !!actions.shellError, icon: Terminal, iconOnly: true, variant: "ghost", size: "icon-xs" }) }) }), _jsx(TooltipContent, { children: "Open in Shell" })] }) }), _jsx(TooltipProvider, { children: _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("span", { className: "flex items-center", children: _jsx(ActionButton, { label: "Open Folder", onClick: actions.openFolder, loading: actions.folderLoading, error: !!actions.folderError, icon: FolderOpen, iconOnly: true, variant: "ghost", size: "icon-xs" }) }) }), _jsx(TooltipContent, { children: "Open Folder" })] }) }), _jsx(FeatureSessionsDropdown, { repositoryPath: data.repositoryPath, onCreateFromSession: handleCreateFromSession }), featureFlags.envDeploy ? (_jsxs(_Fragment, { children: [_jsx(TooltipProvider, { children: _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("span", { className: "flex items-center", children: _jsx(ActionButton, { label: isDeploymentActive ? 'Stop Dev Server' : 'Start Dev Server', onClick: isDeploymentActive ? deployAction.stop : deployAction.deploy, loading: deployAction.deployLoading || deployAction.stopLoading, error: !!deployAction.deployError, icon: isDeploymentActive ? Square : Play, iconOnly: true, variant: "ghost", size: "icon-xs" }) }) }), _jsx(TooltipContent, { children: isDeploymentActive ? 'Stop Dev Server' : 'Start Dev Server' })] }) }), isDeploymentActive ? (_jsx(DeploymentStatusBadge, { status: deployAction.status, url: deployAction.url, targetId: data.repositoryPath })) : null] })) : null] })) : null, data.onAdd ? (_jsx(TooltipProvider, { children: _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("button", { "aria-label": "Add feature", "data-testid": "repository-node-add-button", onClick: (e) => {
|
|
76
|
+
e.stopPropagation();
|
|
77
|
+
data.onAdd?.();
|
|
78
|
+
}, className: cn('text-muted-foreground hover:bg-accent dark:hover:bg-accent/50 flex h-6 w-6 shrink-0 cursor-pointer items-center justify-center rounded-full transition-colors hover:text-blue-500', data.pulseAdd &&
|
|
79
|
+
'animate-pulse-cta bg-blue-100 text-blue-500 dark:bg-blue-900/40'), children: _jsx(Plus, { className: "h-3.5 w-3.5" }) }) }), _jsx(TooltipContent, { children: "Add feature" })] }) })) : null] })] }), data.onAdd || data.showHandles ? (_jsx(Handle, { type: "source", position: Position.Right, isConnectable: !data.showHandles, className: "opacity-0!" })) : null] }));
|
|
80
80
|
}
|
package/dist/src/presentation/web/components/common/repository-node/repository-node.stories.d.ts
CHANGED
|
@@ -14,6 +14,4 @@ export declare const WithActions: Story;
|
|
|
14
14
|
export declare const WithActionsAndAddButton: Story;
|
|
15
15
|
export declare const WithDeleteButton: Story;
|
|
16
16
|
export declare const MultipleWithActions: Story;
|
|
17
|
-
export declare const WithGitInfo: Story;
|
|
18
|
-
export declare const WithGitInfoBehind: Story;
|
|
19
17
|
//# sourceMappingURL=repository-node.stories.d.ts.map
|
package/dist/src/presentation/web/components/common/repository-node/repository-node.stories.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"repository-node.stories.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/repository-node/repository-node.stories.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAGvD,OAAO,KAAK,EAAE,kBAAkB,EAAsB,MAAM,0BAA0B,CAAC;AAgCvF,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,kBAAkB,
|
|
1
|
+
{"version":3,"file":"repository-node.stories.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/repository-node/repository-node.stories.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAGvD,OAAO,KAAK,EAAE,kBAAkB,EAAsB,MAAM,0BAA0B,CAAC;AAgCvF,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,kBAAkB,CASlC,CAAC;AAEF,eAAe,IAAI,CAAC;AACpB,KAAK,KAAK,GAAG,QAAQ,CAAC,kBAAkB,CAAC,CAAC;AAE1C,eAAO,MAAM,OAAO,EAAE,KAErB,CAAC;AAEF,eAAO,MAAM,aAAa,EAAE,KAK3B,CAAC;AAEF,eAAO,MAAM,WAAW,EAAE,KAKzB,CAAC;AAEF,eAAO,MAAM,QAAQ,EAAE,KAKtB,CAAC;AAWF,eAAO,MAAM,QAAQ,EAAE,KAwBtB,CAAC;AASF,eAAO,MAAM,kBAAkB,EAAE,KAwBhC,CAAC;AAEF,eAAO,MAAM,YAAY,EAAE,KAS1B,CAAC;AAEF,eAAO,MAAM,WAAW,EAAE,KAKzB,CAAC;AAEF,eAAO,MAAM,uBAAuB,EAAE,KAQrC,CAAC;AAIF,eAAO,MAAM,gBAAgB,EAAE,KAS9B,CAAC;AA2BF,eAAO,MAAM,mBAAmB,EAAE,KAwBjC,CAAC"}
|
package/dist/src/presentation/web/components/common/repository-node/repository-node.stories.js
CHANGED
|
@@ -3,7 +3,7 @@ import { useMemo } from 'react';
|
|
|
3
3
|
import { ReactFlowProvider, ReactFlow } from '@xyflow/react';
|
|
4
4
|
import { RepositoryNode } from './repository-node.js';
|
|
5
5
|
const nodeTypes = { repositoryNode: RepositoryNode };
|
|
6
|
-
function RepositoryNodeCanvas({ data, style = { width:
|
|
6
|
+
function RepositoryNodeCanvas({ data, style = { width: 500, height: 250 }, }) {
|
|
7
7
|
const nodes = useMemo(() => [{ id: 'node-1', type: 'repositoryNode', position: { x: 0, y: 0 }, data }], [data]);
|
|
8
8
|
return (_jsx("div", { style: style, children: _jsx(ReactFlowProvider, { children: _jsx(ReactFlow, { nodes: nodes, nodeTypes: nodeTypes, nodesDraggable: false, nodesConnectable: false, proOptions: { hideAttribution: true }, fitView: true }) }) }));
|
|
9
9
|
}
|
|
@@ -15,9 +15,6 @@ const meta = {
|
|
|
15
15
|
},
|
|
16
16
|
args: {
|
|
17
17
|
name: 'shep-ai/cli',
|
|
18
|
-
branch: 'main',
|
|
19
|
-
commitMessage: 'feat: add dark mode toggle',
|
|
20
|
-
committer: 'Jane Doe',
|
|
21
18
|
},
|
|
22
19
|
};
|
|
23
20
|
export default meta;
|
|
@@ -44,84 +41,37 @@ export const LongName = {
|
|
|
44
41
|
};
|
|
45
42
|
const onAdd = () => undefined;
|
|
46
43
|
const multipleRepos = [
|
|
47
|
-
{
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
committer: 'Jane Doe',
|
|
52
|
-
},
|
|
53
|
-
{
|
|
54
|
-
name: 'vercel/edge-runtime',
|
|
55
|
-
branch: 'feat/streaming',
|
|
56
|
-
commitMessage: 'fix: handle edge cases in streaming',
|
|
57
|
-
committer: 'John Smith',
|
|
58
|
-
behindCount: 3,
|
|
59
|
-
},
|
|
60
|
-
{
|
|
61
|
-
name: 'acme-corp/web-dashboard-v2',
|
|
62
|
-
branch: 'develop',
|
|
63
|
-
commitMessage: 'chore: update dependencies',
|
|
64
|
-
committer: 'Bot',
|
|
65
|
-
behindCount: 12,
|
|
66
|
-
},
|
|
67
|
-
{
|
|
68
|
-
name: 'openai/tiktoken',
|
|
69
|
-
branch: 'main',
|
|
70
|
-
commitMessage: 'perf: optimize token encoding',
|
|
71
|
-
committer: 'Alice Chen',
|
|
72
|
-
},
|
|
44
|
+
{ name: 'shep-ai/cli' },
|
|
45
|
+
{ name: 'vercel/edge-runtime' },
|
|
46
|
+
{ name: 'acme-corp/web-dashboard-v2' },
|
|
47
|
+
{ name: 'openai/tiktoken' },
|
|
73
48
|
];
|
|
74
49
|
export const Multiple = {
|
|
75
50
|
render: () => {
|
|
76
51
|
const nodes = multipleRepos.map((data, i) => ({
|
|
77
52
|
id: `repo-${i}`,
|
|
78
53
|
type: 'repositoryNode',
|
|
79
|
-
position: { x: 0, y: i *
|
|
54
|
+
position: { x: 0, y: i * 80 },
|
|
80
55
|
data,
|
|
81
56
|
}));
|
|
82
|
-
return (_jsx("div", { style: { width:
|
|
57
|
+
return (_jsx("div", { style: { width: 500, height: 500 }, children: _jsx(ReactFlowProvider, { children: _jsx(ReactFlow, { nodes: nodes, nodeTypes: nodeTypes, nodesDraggable: false, nodesConnectable: false, proOptions: { hideAttribution: true }, fitView: true }) }) }));
|
|
83
58
|
},
|
|
84
59
|
};
|
|
85
60
|
const multipleReposWithButton = [
|
|
86
|
-
{
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
commitMessage: 'feat: add dark mode toggle',
|
|
91
|
-
committer: 'Jane Doe',
|
|
92
|
-
},
|
|
93
|
-
{
|
|
94
|
-
name: 'vercel/edge-runtime',
|
|
95
|
-
onAdd,
|
|
96
|
-
branch: 'feat/streaming',
|
|
97
|
-
commitMessage: 'fix: handle edge cases in streaming',
|
|
98
|
-
committer: 'John Smith',
|
|
99
|
-
behindCount: 3,
|
|
100
|
-
},
|
|
101
|
-
{
|
|
102
|
-
name: 'acme-corp/web-dashboard-v2',
|
|
103
|
-
onAdd,
|
|
104
|
-
branch: 'develop',
|
|
105
|
-
commitMessage: 'chore: update dependencies',
|
|
106
|
-
committer: 'Bot',
|
|
107
|
-
},
|
|
108
|
-
{
|
|
109
|
-
name: 'openai/tiktoken',
|
|
110
|
-
onAdd,
|
|
111
|
-
branch: 'main',
|
|
112
|
-
commitMessage: 'perf: optimize token encoding',
|
|
113
|
-
committer: 'Alice Chen',
|
|
114
|
-
},
|
|
61
|
+
{ name: 'shep-ai/cli', onAdd },
|
|
62
|
+
{ name: 'vercel/edge-runtime', onAdd },
|
|
63
|
+
{ name: 'acme-corp/web-dashboard-v2', onAdd },
|
|
64
|
+
{ name: 'openai/tiktoken', onAdd },
|
|
115
65
|
];
|
|
116
66
|
export const MultipleWithButton = {
|
|
117
67
|
render: () => {
|
|
118
68
|
const nodes = multipleReposWithButton.map((data, i) => ({
|
|
119
69
|
id: `repo-${i}`,
|
|
120
70
|
type: 'repositoryNode',
|
|
121
|
-
position: { x: 0, y: i *
|
|
71
|
+
position: { x: 0, y: i * 80 },
|
|
122
72
|
data,
|
|
123
73
|
}));
|
|
124
|
-
return (_jsx("div", { style: { width:
|
|
74
|
+
return (_jsx("div", { style: { width: 500, height: 500 }, children: _jsx(ReactFlowProvider, { children: _jsx(ReactFlow, { nodes: nodes, nodeTypes: nodeTypes, nodesDraggable: false, nodesConnectable: false, proOptions: { hideAttribution: true }, fitView: true }) }) }));
|
|
125
75
|
},
|
|
126
76
|
};
|
|
127
77
|
export const WithPulseAdd = {
|
|
@@ -158,29 +108,16 @@ export const WithDeleteButton = {
|
|
|
158
108
|
argTypes: {
|
|
159
109
|
onDelete: { action: 'onDelete' },
|
|
160
110
|
},
|
|
161
|
-
render: (args) => _jsx(RepositoryNodeCanvas, { data: args, style: { width:
|
|
111
|
+
render: (args) => _jsx(RepositoryNodeCanvas, { data: args, style: { width: 550, height: 250 } }),
|
|
162
112
|
};
|
|
163
113
|
const multipleReposWithActions = [
|
|
164
|
-
{
|
|
165
|
-
id: 'r1',
|
|
166
|
-
name: 'shep-ai/cli',
|
|
167
|
-
repositoryPath: '/home/user/shep-ai/cli',
|
|
168
|
-
onAdd,
|
|
169
|
-
onDelete,
|
|
170
|
-
branch: 'main',
|
|
171
|
-
commitMessage: 'feat(web): enrich repository node with branch and commit info',
|
|
172
|
-
committer: 'Ariel Shadkhan',
|
|
173
|
-
},
|
|
114
|
+
{ id: 'r1', name: 'shep-ai/cli', repositoryPath: '/home/user/shep-ai/cli', onAdd, onDelete },
|
|
174
115
|
{
|
|
175
116
|
id: 'r2',
|
|
176
117
|
name: 'vercel/edge-runtime',
|
|
177
118
|
repositoryPath: '/home/user/vercel/edge-runtime',
|
|
178
119
|
onAdd,
|
|
179
120
|
onDelete,
|
|
180
|
-
branch: 'feat/streaming-v2',
|
|
181
|
-
commitMessage: 'fix: handle edge cases in streaming response',
|
|
182
|
-
committer: 'John Smith',
|
|
183
|
-
behindCount: 5,
|
|
184
121
|
},
|
|
185
122
|
{
|
|
186
123
|
id: 'r3',
|
|
@@ -188,10 +125,6 @@ const multipleReposWithActions = [
|
|
|
188
125
|
repositoryPath: '/home/user/acme-corp/web-dashboard-v2',
|
|
189
126
|
onAdd,
|
|
190
127
|
onDelete,
|
|
191
|
-
branch: 'develop',
|
|
192
|
-
commitMessage: 'chore(deps): update all dependencies to latest',
|
|
193
|
-
committer: 'Renovate Bot',
|
|
194
|
-
behindCount: 23,
|
|
195
128
|
},
|
|
196
129
|
{
|
|
197
130
|
id: 'r4',
|
|
@@ -199,9 +132,6 @@ const multipleReposWithActions = [
|
|
|
199
132
|
repositoryPath: '/home/user/openai/tiktoken',
|
|
200
133
|
onAdd,
|
|
201
134
|
onDelete,
|
|
202
|
-
branch: 'main',
|
|
203
|
-
commitMessage: 'perf: optimize token encoding for large inputs',
|
|
204
|
-
committer: 'Alice Chen',
|
|
205
135
|
},
|
|
206
136
|
];
|
|
207
137
|
export const MultipleWithActions = {
|
|
@@ -209,29 +139,9 @@ export const MultipleWithActions = {
|
|
|
209
139
|
const nodes = multipleReposWithActions.map((data, i) => ({
|
|
210
140
|
id: `repo-${i}`,
|
|
211
141
|
type: 'repositoryNode',
|
|
212
|
-
position: { x: 0, y: i *
|
|
142
|
+
position: { x: 0, y: i * 80 },
|
|
213
143
|
data,
|
|
214
144
|
}));
|
|
215
|
-
return (_jsx("div", { style: { width:
|
|
216
|
-
},
|
|
217
|
-
};
|
|
218
|
-
export const WithGitInfo = {
|
|
219
|
-
args: {
|
|
220
|
-
repositoryPath: '/home/user/shep-ai/cli',
|
|
221
|
-
branch: 'feat/repo-node-enrichment',
|
|
222
|
-
commitMessage: 'feat(web): enrich repository node with branch and commit info',
|
|
223
|
-
committer: 'Ariel Shadkhan',
|
|
224
|
-
behindCount: 0,
|
|
145
|
+
return (_jsx("div", { style: { width: 500, height: 500 }, children: _jsx(ReactFlowProvider, { children: _jsx(ReactFlow, { nodes: nodes, nodeTypes: nodeTypes, nodesDraggable: false, nodesConnectable: false, proOptions: { hideAttribution: true }, fitView: true }) }) }));
|
|
225
146
|
},
|
|
226
|
-
render: (args) => _jsx(RepositoryNodeCanvas, { data: args }),
|
|
227
|
-
};
|
|
228
|
-
export const WithGitInfoBehind = {
|
|
229
|
-
args: {
|
|
230
|
-
repositoryPath: '/home/user/shep-ai/cli',
|
|
231
|
-
branch: 'feat/old-feature-branch',
|
|
232
|
-
commitMessage: 'fix: resolve merge conflict in auth module',
|
|
233
|
-
committer: 'Jane Doe',
|
|
234
|
-
behindCount: 7,
|
|
235
|
-
},
|
|
236
|
-
render: (args) => _jsx(RepositoryNodeCanvas, { data: args }),
|
|
237
147
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"control-center-empty-state.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/control-center/control-center-empty-state.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"control-center-empty-state.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/control-center/control-center-empty-state.tsx"],"names":[],"mappings":"AAoBA,MAAM,WAAW,4BAA4B;IAC3C,kBAAkB,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5C,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAID,wBAAgB,uBAAuB,CAAC,EACtC,kBAAkB,EAClB,SAAS,GACV,EAAE,4BAA4B,kDA8J9B"}
|
package/dist/src/presentation/web/components/features/control-center/control-center-empty-state.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use client';
|
|
2
|
-
import { jsx as _jsx, jsxs as _jsxs
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { useState, useCallback, useEffect } from 'react';
|
|
4
|
-
import {
|
|
4
|
+
import { FolderOpen, Copy, Check, Loader2, CheckCircle2, AlertCircle, Terminal, ChevronDown, } from 'lucide-react';
|
|
5
5
|
import { cn } from '../../../lib/utils.js';
|
|
6
6
|
import { pickFolder } from '../../common/add-repository-button/pick-folder.js';
|
|
7
7
|
import { isAgentSetupComplete } from '../../../app/actions/agent-setup-flag.js';
|
|
@@ -13,12 +13,12 @@ export function ControlCenterEmptyState({ onRepositorySelect, className, }) {
|
|
|
13
13
|
const [loading, setLoading] = useState(false);
|
|
14
14
|
const [agentReady, setAgentReady] = useState(null);
|
|
15
15
|
const [authStatus, setAuthStatus] = useState(null);
|
|
16
|
+
const [cliExpanded, setCliExpanded] = useState(false);
|
|
16
17
|
useEffect(() => {
|
|
17
18
|
isAgentSetupComplete().then((done) => {
|
|
18
19
|
setAgentReady(done);
|
|
19
20
|
});
|
|
20
21
|
}, []);
|
|
21
|
-
// Background auth check — runs after agent setup is complete
|
|
22
22
|
useEffect(() => {
|
|
23
23
|
if (!agentReady)
|
|
24
24
|
return;
|
|
@@ -52,28 +52,28 @@ export function ControlCenterEmptyState({ onRepositorySelect, className, }) {
|
|
|
52
52
|
}, []);
|
|
53
53
|
if (agentReady === null)
|
|
54
54
|
return null;
|
|
55
|
-
return (
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
55
|
+
return (_jsxs("div", { "data-testid": "control-center-empty-state", className: cn('relative flex h-full w-full flex-col items-center justify-center px-8', className), children: [!agentReady ? (
|
|
56
|
+
/* Agent setup wizard — owns its own hero */
|
|
57
|
+
_jsx(WelcomeAgentSetup, { onComplete: handleAgentSetupComplete })) : (
|
|
58
|
+
/* Repository step — fade in to match wizard transitions */
|
|
59
|
+
_jsxs("div", { className: "animate-in fade-in flex w-full max-w-md flex-col items-center duration-300", children: [_jsx("h1", { className: "text-foreground/90 text-center text-5xl font-extralight tracking-tight", children: "Add a project" }), _jsxs("p", { className: "text-muted-foreground mt-3 text-center text-lg leading-relaxed font-light", children: ["Add your project folder to unlock feature creation.", _jsx("br", {}), "Describe what you need \u2014 Shep handles the rest."] }), _jsx("div", { className: "mt-8", children: _jsx(AgentAuthBanner, { status: authStatus, onRetry: handleRetryAuth }) }), _jsxs("button", { type: "button", "data-testid": "empty-state-add-repository", onClick: handlePickerClick, disabled: loading, className: "bg-foreground text-background hover:bg-foreground/90 mt-10 flex w-full cursor-pointer items-center justify-center gap-2.5 rounded-xl px-6 py-4 text-base font-medium shadow-lg transition-all duration-200 hover:shadow-xl active:scale-[0.98] disabled:cursor-wait disabled:opacity-50", children: [loading ? (_jsx(Loader2, { className: "h-5 w-5 animate-spin" })) : (_jsx(FolderOpen, { className: "h-5 w-5" })), loading ? 'Opening…' : 'Choose a Folder'] }), _jsx("p", { className: "text-muted-foreground/60 mt-3 text-center text-sm", children: "Any folder works \u2014 git will be initialized automatically if needed." })] })), agentReady ? (_jsxs("div", { className: "absolute bottom-8 flex flex-col items-center", style: {
|
|
60
|
+
animationDelay: '400ms',
|
|
61
|
+
animationDuration: '600ms',
|
|
62
|
+
animationFillMode: 'both',
|
|
63
|
+
}, children: [_jsxs("button", { type: "button", onClick: () => setCliExpanded(!cliExpanded), className: "text-muted-foreground hover:text-foreground flex cursor-pointer items-center gap-1.5 transition-colors duration-200", children: [_jsx(Terminal, { className: "h-3.5 w-3.5" }), _jsx("span", { className: "text-sm", children: "or use the CLI" }), _jsx(ChevronDown, { className: cn('h-3.5 w-3.5 transition-transform duration-200', cliExpanded ? '' : 'rotate-180') })] }), cliExpanded ? (_jsx("div", { className: "animate-in fade-in slide-in-from-top-1 mt-3 w-80 duration-200", children: _jsxs("div", { "data-testid": "cli-code-block", className: "relative rounded-xl bg-zinc-900 px-5 py-4 font-mono text-[13px] leading-relaxed text-zinc-400", children: [_jsx("button", { type: "button", "data-testid": "cli-code-block-copy", onClick: handleCopy, className: "absolute top-3 right-3 cursor-pointer rounded-md p-1.5 text-zinc-600 transition-colors hover:bg-zinc-800 hover:text-zinc-300", "aria-label": "Copy commands", children: copied ? (_jsx(Check, { className: "h-3.5 w-3.5 text-emerald-400" })) : (_jsx(Copy, { className: "h-3.5 w-3.5" })) }), _jsx("div", { className: "space-y-1", children: commands.map((cmd) => (_jsxs("div", { className: "whitespace-nowrap", children: [_jsx("span", { className: "text-zinc-600 select-none", children: "$ " }), _jsx("span", { className: "text-zinc-300", children: cmd })] }, cmd))) })] }) })) : null] })) : null] }));
|
|
60
64
|
}
|
|
61
|
-
/**
|
|
65
|
+
/** Inline status pill — minimal, no background box */
|
|
62
66
|
function AgentAuthBanner({ status, onRetry, }) {
|
|
63
|
-
// Still checking — show subtle spinner
|
|
64
67
|
if (!status) {
|
|
65
|
-
return (_jsxs("div", { className: "
|
|
68
|
+
return (_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Loader2, { className: "text-muted-foreground/50 h-3.5 w-3.5 animate-spin" }), _jsx("span", { className: "text-muted-foreground/50 text-sm", children: "Checking setup\u2026" })] }));
|
|
66
69
|
}
|
|
67
|
-
// All good — compact success, auto-fades
|
|
68
70
|
if (status.installed && status.authenticated) {
|
|
69
|
-
return (_jsxs("div", { className: "animate-in fade-in flex
|
|
71
|
+
return (_jsxs("div", { className: "animate-in fade-in flex items-center gap-2", children: [_jsx(CheckCircle2, { className: "h-4 w-4 text-emerald-500" }), _jsxs("span", { className: "text-sm text-emerald-600 dark:text-emerald-400", children: [status.label, " ready"] })] }));
|
|
70
72
|
}
|
|
71
|
-
// Not installed
|
|
72
73
|
if (!status.installed) {
|
|
73
|
-
return (_jsxs("div", { className: "flex
|
|
74
|
+
return (_jsxs("div", { className: "flex flex-col items-center gap-3", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(AlertCircle, { className: "h-4 w-4 text-amber-500" }), _jsxs("span", { className: "text-sm font-medium text-amber-600 dark:text-amber-400", children: [status.label, " not installed"] })] }), status.binaryName ? (_jsxs("code", { className: "rounded-lg bg-zinc-100 px-3 py-1.5 text-xs text-zinc-600 dark:bg-zinc-800 dark:text-zinc-400", children: ["npm install -g ", status.binaryName] })) : null, _jsx("button", { type: "button", onClick: onRetry, className: "text-xs text-amber-600 underline underline-offset-2 hover:text-amber-800 dark:text-amber-400", children: "Re-check" })] }));
|
|
74
75
|
}
|
|
75
|
-
|
|
76
|
-
return (_jsxs("div", { className: "flex w-full flex-col gap-2 rounded-md bg-amber-500/10 px-3 py-2", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(AlertCircle, { className: "h-3 w-3 text-amber-600 dark:text-amber-400" }), _jsxs("span", { className: "text-[10px] font-medium text-amber-700 dark:text-amber-300", children: [status.label, " needs authentication"] })] }), status.authCommand ? (_jsxs("div", { className: "rounded bg-zinc-900 px-2 py-1 font-mono text-[10px] text-zinc-300", children: [_jsx("span", { className: "text-zinc-500 select-none", children: "$ " }), status.authCommand] })) : null, _jsxs("div", { className: "flex items-center gap-2", children: [status.binaryName ? (_jsxs("button", { type: "button", "data-testid": "auth-banner-open-terminal", onClick: async () => {
|
|
76
|
+
return (_jsxs("div", { className: "flex flex-col items-center gap-3", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(AlertCircle, { className: "h-4 w-4 text-amber-500" }), _jsxs("span", { className: "text-sm font-medium text-amber-600 dark:text-amber-400", children: [status.label, " needs authentication"] })] }), status.authCommand ? (_jsx("code", { className: "rounded-lg bg-zinc-100 px-3 py-1.5 text-xs text-zinc-600 dark:bg-zinc-800 dark:text-zinc-400", children: status.authCommand })) : null, _jsxs("div", { className: "flex items-center gap-3", children: [status.binaryName ? (_jsxs("button", { type: "button", "data-testid": "auth-banner-open-terminal", onClick: async () => {
|
|
77
77
|
try {
|
|
78
78
|
const toolId = status.agentType === 'claude-code' ? 'claude-code' : status.agentType;
|
|
79
79
|
await fetch(`/api/tools/${toolId}/launch`, { method: 'POST' });
|
|
@@ -81,5 +81,5 @@ function AgentAuthBanner({ status, onRetry, }) {
|
|
|
81
81
|
catch {
|
|
82
82
|
// best effort
|
|
83
83
|
}
|
|
84
|
-
}, className: "flex items-center gap-1
|
|
84
|
+
}, className: "flex items-center gap-1.5 text-xs font-medium text-amber-600 underline underline-offset-2 hover:text-amber-800 dark:text-amber-400", children: [_jsx(Terminal, { className: "h-3 w-3" }), "Open ", status.label] })) : null, _jsx("button", { type: "button", onClick: onRetry, className: "text-xs text-amber-600 underline underline-offset-2 hover:text-amber-800 dark:text-amber-400", children: "Re-check" })] })] }));
|
|
85
85
|
}
|
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;AAuB5E,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;AAuB5E,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,2CAkWzF"}
|
package/dist/src/presentation/web/components/features/control-center/control-center-inner.js
CHANGED
|
@@ -27,8 +27,8 @@ export function ControlCenterInner({ initialNodes, initialEdges }) {
|
|
|
27
27
|
const drawerTimerRef = useRef(null);
|
|
28
28
|
const { defaultViewport, onMoveEnd: handleViewportChange, resetViewport, } = useViewportPersistence();
|
|
29
29
|
const { nodes, edges, onNodesChange, handleConnect, handleAddRepository, handleDeleteFeature, handleRetryFeature, handleStartFeature, handleStopFeature, handleDeleteRepository, createFeatureNode, setCallbacks, } = useControlCenterState(initialNodes, initialEdges);
|
|
30
|
-
// Publish sidebar features
|
|
31
|
-
const { setFeatures: setSidebarFeatures } = useSidebarFeaturesContext();
|
|
30
|
+
// Publish sidebar features + repo state to context
|
|
31
|
+
const { setFeatures: setSidebarFeatures, setHasRepositories: setSidebarHasRepos } = useSidebarFeaturesContext();
|
|
32
32
|
const featureNodes = useMemo(() => nodes.filter((n) => n.type === 'featureNode'), [nodes]);
|
|
33
33
|
const sidebarKey = useMemo(() => {
|
|
34
34
|
return featureNodes
|
|
@@ -119,21 +119,29 @@ export function ControlCenterInner({ initialNodes, initialEdges }) {
|
|
|
119
119
|
guardedNavigate(() => router.push('/'));
|
|
120
120
|
}
|
|
121
121
|
}, [router, pathname, guardedNavigate]);
|
|
122
|
+
// Shared: after adding first repo, center canvas and open create drawer
|
|
123
|
+
const focusAndOpenDrawer = useCallback((repoPath) => {
|
|
124
|
+
// Wait for next render so the repo node exists in the DOM
|
|
125
|
+
setTimeout(() => {
|
|
126
|
+
fitView(AUTO_FOCUS_OPTIONS);
|
|
127
|
+
// Open the create-feature drawer after the fitView animation completes
|
|
128
|
+
drawerTimerRef.current = setTimeout(() => {
|
|
129
|
+
guardedNavigate(() => router.push(`/create?repo=${encodeURIComponent(repoPath)}`));
|
|
130
|
+
}, AUTO_FOCUS_DRAWER_DELAY_MS);
|
|
131
|
+
}, 0);
|
|
132
|
+
}, [fitView, guardedNavigate, router]);
|
|
133
|
+
// Wrapper: add repo + auto-focus if canvas was empty
|
|
134
|
+
const addRepoAndFocus = useCallback((path) => {
|
|
135
|
+
const { wasEmpty, repoPath } = handleAddRepository(path);
|
|
136
|
+
if (wasEmpty) {
|
|
137
|
+
focusAndOpenDrawer(repoPath);
|
|
138
|
+
}
|
|
139
|
+
}, [handleAddRepository, focusAndOpenDrawer]);
|
|
122
140
|
// Listen for global "add repository" events from the top bar button
|
|
123
141
|
useEffect(() => {
|
|
124
142
|
const handler = (e) => {
|
|
125
143
|
const path = e.detail.path;
|
|
126
|
-
|
|
127
|
-
if (wasEmpty) {
|
|
128
|
-
// Wait for next render so the repo node exists in the DOM, then auto-focus
|
|
129
|
-
setTimeout(() => {
|
|
130
|
-
fitView(AUTO_FOCUS_OPTIONS);
|
|
131
|
-
// Open the create-feature drawer after the fitView animation completes
|
|
132
|
-
drawerTimerRef.current = setTimeout(() => {
|
|
133
|
-
guardedNavigate(() => router.push(`/create?repo=${encodeURIComponent(repoPath)}`));
|
|
134
|
-
}, AUTO_FOCUS_DRAWER_DELAY_MS);
|
|
135
|
-
}, 0);
|
|
136
|
-
}
|
|
144
|
+
addRepoAndFocus(path);
|
|
137
145
|
};
|
|
138
146
|
window.addEventListener('shep:add-repository', handler);
|
|
139
147
|
return () => {
|
|
@@ -142,7 +150,7 @@ export function ControlCenterInner({ initialNodes, initialEdges }) {
|
|
|
142
150
|
clearTimeout(drawerTimerRef.current);
|
|
143
151
|
}
|
|
144
152
|
};
|
|
145
|
-
}, [
|
|
153
|
+
}, [addRepoAndFocus]);
|
|
146
154
|
// Listen for create events from the create drawer (with real feature ID from server)
|
|
147
155
|
useEffect(() => {
|
|
148
156
|
const handler = (e) => {
|
|
@@ -212,6 +220,10 @@ export function ControlCenterInner({ initialNodes, initialEdges }) {
|
|
|
212
220
|
handleViewportChange(viewport);
|
|
213
221
|
}, [handleViewportChange]);
|
|
214
222
|
const hasRepositories = nodes.some((n) => n.type === 'repositoryNode');
|
|
223
|
+
// Publish repo state to sidebar context so AppShell can hide FAB during onboarding
|
|
224
|
+
useEffect(() => {
|
|
225
|
+
setSidebarHasRepos(hasRepositories);
|
|
226
|
+
}, [hasRepositories, setSidebarHasRepos]);
|
|
215
227
|
// Debounced latch: prevent empty-state flicker during brief reconcile gaps
|
|
216
228
|
// (e.g. stale poll momentarily drops repos), but allow the empty state to
|
|
217
229
|
// return after a real delete once repos stay gone past the debounce window.
|
|
@@ -227,7 +239,9 @@ export function ControlCenterInner({ initialNodes, initialEdges }) {
|
|
|
227
239
|
setShowCanvas(true);
|
|
228
240
|
}
|
|
229
241
|
else if (showCanvas) {
|
|
230
|
-
// Repos gone —
|
|
242
|
+
// Repos gone — clear saved viewport so next add starts centered,
|
|
243
|
+
// then wait before showing empty state (debounce stale polls)
|
|
244
|
+
resetViewport();
|
|
231
245
|
latchTimerRef.current = setTimeout(() => {
|
|
232
246
|
setShowCanvas(false);
|
|
233
247
|
latchTimerRef.current = null;
|
|
@@ -237,7 +251,7 @@ export function ControlCenterInner({ initialNodes, initialEdges }) {
|
|
|
237
251
|
if (latchTimerRef.current)
|
|
238
252
|
clearTimeout(latchTimerRef.current);
|
|
239
253
|
};
|
|
240
|
-
}, [hasRepositories, showCanvas]);
|
|
254
|
+
}, [hasRepositories, showCanvas, resetViewport]);
|
|
241
255
|
// Pulse the "+" button when there's a single repo with no features and the
|
|
242
256
|
// create-feature drawer is not open — draws attention to the next action.
|
|
243
257
|
const isCreateDrawerOpen = pathname.startsWith('/create');
|
|
@@ -249,5 +263,5 @@ export function ControlCenterInner({ initialNodes, initialEdges }) {
|
|
|
249
263
|
return nodes;
|
|
250
264
|
return nodes.map((n) => n.type === 'repositoryNode' ? { ...n, data: { ...n.data, pulseAdd: true } } : n);
|
|
251
265
|
}, [nodes, isCreateDrawerOpen]);
|
|
252
|
-
return (_jsx(FeaturesCanvas, { nodes: showCanvas ? displayNodes : [], edges: showCanvas ? edges : [], selectedFeatureId: selectedFeatureId, defaultViewport: defaultViewport, onNodesChange: onNodesChange, onConnect: handleConnect, onAddFeature: handleAddFeature, onNodeClick: handleNodeClick, onPaneClick: handleClearDrawers, onMoveEnd: handleMoveEnd, onResetViewport: resetViewport, emptyState: _jsx(ControlCenterEmptyState, { onRepositorySelect:
|
|
266
|
+
return (_jsx(FeaturesCanvas, { nodes: showCanvas ? displayNodes : [], edges: showCanvas ? edges : [], selectedFeatureId: selectedFeatureId, defaultViewport: defaultViewport, onNodesChange: onNodesChange, onConnect: handleConnect, onAddFeature: handleAddFeature, onNodeClick: handleNodeClick, onPaneClick: handleClearDrawers, onMoveEnd: handleMoveEnd, onResetViewport: resetViewport, emptyState: _jsx(ControlCenterEmptyState, { onRepositorySelect: addRepoAndFocus }) }));
|
|
253
267
|
}
|
package/dist/src/presentation/web/components/features/control-center/welcome-agent-setup.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"welcome-agent-setup.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/control-center/welcome-agent-setup.tsx"],"names":[],"mappings":"AAWA,MAAM,WAAW,sBAAsB;IACrC,UAAU,EAAE,MAAM,IAAI,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;
|
|
1
|
+
{"version":3,"file":"welcome-agent-setup.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/control-center/welcome-agent-setup.tsx"],"names":[],"mappings":"AAWA,MAAM,WAAW,sBAAsB;IACrC,UAAU,EAAE,MAAM,IAAI,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAMD,wBAAgB,iBAAiB,CAAC,EAAE,UAAU,EAAE,SAAS,EAAE,EAAE,sBAAsB,2CA4NlF"}
|