@shepai/cli 1.124.0 → 1.126.0
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/services/deployment-service.interface.d.ts +13 -2
- package/dist/packages/core/src/application/ports/output/services/deployment-service.interface.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/di/container.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/di/container.js +2 -0
- package/dist/packages/core/src/infrastructure/persistence/sqlite/migrations/040-create-dev-servers-table.d.ts +21 -0
- package/dist/packages/core/src/infrastructure/persistence/sqlite/migrations/040-create-dev-servers-table.d.ts.map +1 -0
- package/dist/packages/core/src/infrastructure/persistence/sqlite/migrations/040-create-dev-servers-table.js +32 -0
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/merge/ci-watch-fix-loop.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/merge/ci-watch-fix-loop.js +9 -0
- package/dist/packages/core/src/infrastructure/services/deployment/deployment.service.d.ts +24 -14
- package/dist/packages/core/src/infrastructure/services/deployment/deployment.service.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/services/deployment/deployment.service.js +203 -31
- package/dist/packages/core/src/infrastructure/services/deployment/parse-port.d.ts +0 -6
- package/dist/packages/core/src/infrastructure/services/deployment/parse-port.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/services/deployment/parse-port.js +6 -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 +7 -2
- package/dist/src/presentation/web/app/actions/deploy-feature.js +1 -1
- package/dist/src/presentation/web/app/actions/deploy-repository.js +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 +7 -4
- 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 +12 -3
- package/dist/src/presentation/web/components/features/settings/notification-settings-section.d.ts.map +1 -1
- package/dist/src/presentation/web/components/features/settings/notification-settings-section.js +4 -8
- package/dist/src/presentation/web/components/features/settings/notification-settings-section.stories.js +3 -3
- package/dist/src/presentation/web/components/features/settings/settings-page-client.d.ts.map +1 -1
- package/dist/src/presentation/web/components/features/settings/settings-page-client.js +12 -37
- package/dist/src/presentation/web/components/features/settings/settings-page-client.stories.d.ts.map +1 -1
- package/dist/src/presentation/web/components/features/settings/settings-page-client.stories.js +2 -3
- package/dist/src/presentation/web/hooks/use-deploy-action.d.ts.map +1 -1
- package/dist/src/presentation/web/hooks/use-deploy-action.js +69 -10
- package/dist/src/presentation/web/lib/layout-with-dagre.js +3 -3
- 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 +2 -2
- package/web/.next/required-server-files.json +2 -2
- package/web/.next/server/app/(dashboard)/@drawer/create/page/server-reference-manifest.json +57 -57
- 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 +69 -69
- package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page.js +2 -2
- 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 +69 -69
- package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page.js +2 -2
- 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 +53 -53
- 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 +57 -57
- 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 +69 -69
- package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page.js +2 -2
- 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 +69 -69
- package/web/.next/server/app/(dashboard)/feature/[featureId]/page.js +2 -2
- 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 +53 -53
- 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 +53 -53
- 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.js.nft.json +1 -1
- package/web/.next/server/app/_not-found/page_client-reference-manifest.js +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.js +1 -2
- 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 +1 -2
- package/web/.next/server/app/tools/page.js.nft.json +1 -1
- package/web/.next/server/app/tools/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/version/page/server-reference-manifest.json +1 -1
- package/web/.next/server/app/version/page.js.nft.json +1 -1
- package/web/.next/server/app/version/page_client-reference-manifest.js +1 -1
- package/web/.next/server/chunks/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]__a402b567._.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_fdfbf5cc.js +3 -0
- package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_@drawer_repository_[repositoryId]_page_actions_fdfbf5cc.js.map +1 -0
- package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_repository_[repositoryId]_page_actions_d8fa0b5f.js +3 -0
- package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_repository_[repositoryId]_page_actions_d8fa0b5f.js.map +1 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__06fef644._.js +1 -1
- package/web/.next/server/chunks/ssr/{[root-of-the-server]__ce6057f6._.js → [root-of-the-server]__248b9fc3._.js} +2 -2
- package/web/.next/server/chunks/ssr/{[root-of-the-server]__9e8b25ad._.js.map → [root-of-the-server]__248b9fc3._.js.map} +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__357de47c._.js +4 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__357de47c._.js.map +1 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__56ecbe40._.js +3 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__56ecbe40._.js.map +1 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__67fe07fe._.js +4 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__67fe07fe._.js.map +1 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__68c2d48e._.js +3 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__68c2d48e._.js.map +1 -0
- 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]__a50a7e39._.js +4 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__a50a7e39._.js.map +1 -0
- package/web/.next/server/chunks/ssr/{[root-of-the-server]__7cbda1ea._.js → [root-of-the-server]__dfc367f2._.js} +2 -2
- package/web/.next/server/chunks/ssr/{[root-of-the-server]__ce6057f6._.js.map → [root-of-the-server]__dfc367f2._.js.map} +1 -1
- package/web/.next/server/chunks/ssr/{[root-of-the-server]__9e8b25ad._.js → [root-of-the-server]__e7f61cc6._.js} +2 -2
- package/web/.next/server/chunks/ssr/{[root-of-the-server]__7cbda1ea._.js.map → [root-of-the-server]__e7f61cc6._.js.map} +1 -1
- package/web/.next/server/chunks/ssr/{[root-of-the-server]__aed1d6f8._.js → [root-of-the-server]__fe48d2dc._.js} +2 -2
- package/web/.next/server/chunks/ssr/{[root-of-the-server]__aed1d6f8._.js.map → [root-of-the-server]__fe48d2dc._.js.map} +1 -1
- package/web/.next/server/chunks/ssr/_243e3685._.js +3 -0
- package/web/.next/server/chunks/ssr/_243e3685._.js.map +1 -0
- 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/_7dca1882._.js +3 -0
- package/web/.next/server/chunks/ssr/_7dca1882._.js.map +1 -0
- package/web/.next/server/chunks/ssr/{_f84c16ab._.js → _821bbcc5._.js} +2 -2
- package/web/.next/server/chunks/ssr/{_f84c16ab._.js.map → _821bbcc5._.js.map} +1 -1
- package/web/.next/server/chunks/ssr/{_0e506641._.js → _918887c5._.js} +2 -2
- package/web/.next/server/chunks/ssr/_918887c5._.js.map +1 -0
- package/web/.next/server/chunks/ssr/{_1bb131c4._.js → _d4b20e29._.js} +2 -2
- package/web/.next/server/chunks/ssr/_d4b20e29._.js.map +1 -0
- package/web/.next/server/chunks/ssr/_e9703421._.js +1 -1
- package/web/.next/server/chunks/ssr/_e9703421._.js.map +1 -1
- package/web/.next/server/chunks/ssr/_f39a1adb._.js +3 -0
- package/web/.next/server/chunks/ssr/{_135edb9c._.js.map → _f39a1adb._.js.map} +1 -1
- package/web/.next/server/chunks/ssr/b1a17_presentation_web_components_features_settings_settings-page-client_tsx_6ed9d5f8._.js +1 -1
- package/web/.next/server/chunks/ssr/b1a17_presentation_web_components_features_settings_settings-page-client_tsx_6ed9d5f8._.js.map +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_9db47db7._.js +5 -0
- package/web/.next/server/chunks/ssr/{src_presentation_web_5f039db1._.js.map → src_presentation_web_9db47db7._.js.map} +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_f66cd328.js +3 -0
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_f66cd328.js.map +1 -0
- package/web/.next/server/chunks/ssr/src_presentation_web_aeddd007._.js +3 -0
- package/web/.next/server/chunks/ssr/{src_presentation_web_164fa933._.js.map → src_presentation_web_aeddd007._.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_bf50c527._.js.map +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_de814675._.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/chunks/ssr/src_presentation_web_ede4a227._.js +5 -0
- package/web/.next/server/chunks/ssr/{src_presentation_web_c4337169._.js.map → src_presentation_web_ede4a227._.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 +325 -325
- package/web/.next/static/chunks/01ba448cf76c6014.js +1 -0
- package/web/.next/static/chunks/044f4665499a9656.js +1 -0
- package/web/.next/static/chunks/112cf5891d1ca558.js +1 -0
- package/web/.next/static/chunks/1be7ac7a24009333.css +1 -0
- package/web/.next/static/chunks/37ada233462bcaec.js +11 -0
- package/web/.next/static/chunks/4ac11847f73b50d6.js +1 -0
- package/web/.next/static/chunks/{5b7726ff31c25338.js → 4ac4a43b7eb441e1.js} +2 -2
- package/web/.next/static/chunks/5fb66ee5a353a6c6.js +1 -0
- package/web/.next/static/chunks/6cfc75060a243290.js +1 -0
- package/web/.next/static/chunks/b70dd4985a814b27.js +1 -0
- package/web/.next/static/chunks/{9db7f24ddea15a4c.js → d60f93a1a25ab09d.js} +1 -1
- package/web/.next/static/chunks/dcfed2c9b7cd1cb4.js +1 -0
- package/web/.next/static/chunks/{ad076c0b68dd9971.js → de66f8d6a67c2361.js} +1 -1
- package/web/.next/static/chunks/{74fa59dbd04fdfcb.js → de8b0265f780e212.js} +2 -2
- package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_@drawer_repository_[repositoryId]_page_actions_f30d0343.js +0 -3
- package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_@drawer_repository_[repositoryId]_page_actions_f30d0343.js.map +0 -1
- package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_repository_[repositoryId]_page_actions_9f1775bb.js +0 -3
- package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_repository_[repositoryId]_page_actions_9f1775bb.js.map +0 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__14664e9b._.js +0 -4
- package/web/.next/server/chunks/ssr/[root-of-the-server]__14664e9b._.js.map +0 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__4993a47c._.js +0 -3
- package/web/.next/server/chunks/ssr/[root-of-the-server]__4993a47c._.js.map +0 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__545792ab._.js +0 -3
- package/web/.next/server/chunks/ssr/[root-of-the-server]__545792ab._.js.map +0 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__a7de2711._.js +0 -4
- package/web/.next/server/chunks/ssr/[root-of-the-server]__a7de2711._.js.map +0 -1
- package/web/.next/server/chunks/ssr/_0e506641._.js.map +0 -1
- package/web/.next/server/chunks/ssr/_135edb9c._.js +0 -3
- package/web/.next/server/chunks/ssr/_1bb131c4._.js.map +0 -1
- package/web/.next/server/chunks/ssr/_b89059c0._.js +0 -3
- package/web/.next/server/chunks/ssr/_b89059c0._.js.map +0 -1
- package/web/.next/server/chunks/ssr/_cc77a143._.js +0 -3
- package/web/.next/server/chunks/ssr/_cc77a143._.js.map +0 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_164fa933._.js +0 -3
- package/web/.next/server/chunks/ssr/src_presentation_web_5f039db1._.js +0 -5
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_2a52b697.js +0 -3
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_2a52b697.js.map +0 -1
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_skills_page_actions_1fa8042e.js +0 -3
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_skills_page_actions_1fa8042e.js.map +0 -1
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_tools_page_actions_24684200.js +0 -3
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_tools_page_actions_24684200.js.map +0 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_c4337169._.js +0 -5
- package/web/.next/static/chunks/0dc102ef519487f5.js +0 -1
- package/web/.next/static/chunks/10fc8c2e5ff44bb2.js +0 -1
- package/web/.next/static/chunks/3925626b99dcd57a.css +0 -1
- package/web/.next/static/chunks/76c038a9d55ca717.js +0 -1
- package/web/.next/static/chunks/9d7e0bb6dc2f88ae.js +0 -1
- package/web/.next/static/chunks/ac7251026c1e2cdf.js +0 -1
- package/web/.next/static/chunks/d72044b2826292fe.js +0 -1
- package/web/.next/static/chunks/e2ef95d904c360f3.js +0 -1
- package/web/.next/static/chunks/eaeabda870a35a9a.js +0 -11
- /package/web/.next/static/{Ap_0BUaFHzD8WxrlWsbMg → 4hN7Gtw--ruMbDn0FRI2-}/_buildManifest.js +0 -0
- /package/web/.next/static/{Ap_0BUaFHzD8WxrlWsbMg → 4hN7Gtw--ruMbDn0FRI2-}/_clientMiddlewareManifest.json +0 -0
- /package/web/.next/static/{Ap_0BUaFHzD8WxrlWsbMg → 4hN7Gtw--ruMbDn0FRI2-}/_ssgManifest.js +0 -0
|
@@ -38,12 +38,17 @@ const PORT_PATTERNS = [
|
|
|
38
38
|
* @param line - A single line of process output
|
|
39
39
|
* @returns The detected URL string, or null if no URL/port was found
|
|
40
40
|
*/
|
|
41
|
+
// Strip ANSI escape codes (colors, cursor movement, etc.)
|
|
42
|
+
// eslint-disable-next-line no-control-regex
|
|
43
|
+
const ANSI_REGEX = /\x1b\[[0-9;]*[a-zA-Z]/g;
|
|
41
44
|
export function parsePort(line) {
|
|
42
45
|
if (!line?.trim()) {
|
|
43
46
|
return null;
|
|
44
47
|
}
|
|
48
|
+
// Strip ANSI escape codes before matching — dev servers often emit colored output
|
|
49
|
+
const clean = line.replace(ANSI_REGEX, '');
|
|
45
50
|
for (const { regex, extract } of PORT_PATTERNS) {
|
|
46
|
-
const match =
|
|
51
|
+
const match = clean.match(regex);
|
|
47
52
|
if (match) {
|
|
48
53
|
return extract(match);
|
|
49
54
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"git-pr.service.d.ts","sourceRoot":"","sources":["../../../../../../../packages/core/src/infrastructure/services/git/git-pr.service.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wEAAwE,CAAC;AAC5G,OAAO,KAAK,EACV,cAAc,EAGd,WAAW,EACX,QAAQ,EACR,aAAa,EACb,cAAc,EACd,YAAY,EACb,MAAM,wEAAwE,CAAC;AAUhF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAE1D,qBACa,YAAa,YAAW,aAAa;IACZ,OAAO,CAAC,QAAQ,CAAC,QAAQ;gBAAR,QAAQ,EAAE,YAAY;IAErE,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAKxC,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAgBjD,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAgF9C,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAKnD,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAKpD,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAWxD,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAYvE,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAuClE,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,GAAE,aAAwB,GAAG,OAAO,CAAC,IAAI,CAAC;YA6BjF,eAAe;IASvB,gBAAgB,CACpB,GAAG,EAAE,MAAM,EACX,aAAa,EAAE,MAAM,EACrB,UAAU,EAAE,MAAM,EAClB,aAAa,EAAE,MAAM,EACrB,SAAS,UAAQ,GAChB,OAAO,CAAC,IAAI,CAAC;IA4EV,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAUnF,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAsBjE,OAAO,CACX,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,MAAM,EACd,SAAS,CAAC,EAAE,MAAM,EAClB,eAAe,CAAC,EAAE,MAAM,GACvB,OAAO,CAAC,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"git-pr.service.d.ts","sourceRoot":"","sources":["../../../../../../../packages/core/src/infrastructure/services/git/git-pr.service.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wEAAwE,CAAC;AAC5G,OAAO,KAAK,EACV,cAAc,EAGd,WAAW,EACX,QAAQ,EACR,aAAa,EACb,cAAc,EACd,YAAY,EACb,MAAM,wEAAwE,CAAC;AAUhF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAE1D,qBACa,YAAa,YAAW,aAAa;IACZ,OAAO,CAAC,QAAQ,CAAC,QAAQ;gBAAR,QAAQ,EAAE,YAAY;IAErE,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAKxC,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAgBjD,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAgF9C,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAKnD,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAKpD,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAWxD,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAYvE,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAuClE,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,GAAE,aAAwB,GAAG,OAAO,CAAC,IAAI,CAAC;YA6BjF,eAAe;IASvB,gBAAgB,CACpB,GAAG,EAAE,MAAM,EACX,aAAa,EAAE,MAAM,EACrB,UAAU,EAAE,MAAM,EAClB,aAAa,EAAE,MAAM,EACrB,SAAS,UAAQ,GAChB,OAAO,CAAC,IAAI,CAAC;IA4EV,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAUnF,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAsBjE,OAAO,CACX,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,MAAM,EACd,SAAS,CAAC,EAAE,MAAM,EAClB,eAAe,CAAC,EAAE,MAAM,GACvB,OAAO,CAAC,cAAc,CAAC;IAiEpB,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAWhF,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAevE,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC;IAaxE,OAAO,CAAC,gBAAgB;IAexB,OAAO,CAAC,aAAa;IAmFf,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;IAoCpD,kBAAkB,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,SAAS,CAAC;IAc/E,WAAW,CACf,GAAG,EAAE,MAAM,EACX,aAAa,EAAE,MAAM,EACrB,UAAU,EAAE,MAAM,EAClB,eAAe,CAAC,EAAE,MAAM,GACvB,OAAO,CAAC,OAAO,CAAC;IA6CnB;;;OAGG;YACW,UAAU;IAmBlB,cAAc,CAClB,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,EACf,WAAW,SAAS,GACnB,OAAO,CAAC,MAAM,CAAC;IAWlB,OAAO,CAAC,WAAW;IAQnB,OAAO,CAAC,cAAc;IAMtB,OAAO,CAAC,gBAAgB;IAKxB,OAAO,CAAC,aAAa;IAcrB,OAAO,CAAC,YAAY;IAepB,OAAO,CAAC,oBAAoB;IAK5B,OAAO,CAAC,aAAa;CAiBtB"}
|
|
@@ -308,15 +308,19 @@ let GitPrService = class GitPrService {
|
|
|
308
308
|
}
|
|
309
309
|
}
|
|
310
310
|
async watchCi(cwd, branch, timeoutMs, intervalSeconds) {
|
|
311
|
+
// Resolve the latest run for the branch BEFORE the try/catch so the
|
|
312
|
+
// runUrl is available in both success and failure return paths.
|
|
313
|
+
let runUrl;
|
|
311
314
|
try {
|
|
312
315
|
// gh run watch requires a run ID — it does not support --branch.
|
|
313
316
|
// First, resolve the latest run ID for the branch via gh run list.
|
|
314
|
-
const { stdout: listOut } = await this.execFile('gh', ['run', 'list', '--branch', branch, '--json', 'databaseId', '--limit', '1'], { cwd });
|
|
317
|
+
const { stdout: listOut } = await this.execFile('gh', ['run', 'list', '--branch', branch, '--json', 'databaseId,url', '--limit', '1'], { cwd });
|
|
315
318
|
const runs = JSON.parse(listOut);
|
|
316
319
|
if (runs.length === 0 || !runs[0].databaseId) {
|
|
317
320
|
return { status: 'pending' };
|
|
318
321
|
}
|
|
319
322
|
const runId = String(runs[0].databaseId);
|
|
323
|
+
runUrl = runs[0].url;
|
|
320
324
|
const interval = intervalSeconds ?? 30;
|
|
321
325
|
const args = [
|
|
322
326
|
'run',
|
|
@@ -335,6 +339,7 @@ let GitPrService = class GitPrService {
|
|
|
335
339
|
// If we reach here (no exception), CI passed — no need for fragile stdout parsing.
|
|
336
340
|
return {
|
|
337
341
|
status: 'success',
|
|
342
|
+
runUrl,
|
|
338
343
|
logExcerpt: stdout.trim(),
|
|
339
344
|
};
|
|
340
345
|
}
|
|
@@ -356,7 +361,7 @@ let GitPrService = class GitPrService {
|
|
|
356
361
|
// Build a useful log excerpt from stdout/stderr if available
|
|
357
362
|
const errObj = error;
|
|
358
363
|
const parts = [errObj.stdout, errObj.stderr, message].filter(Boolean);
|
|
359
|
-
return { status: 'failure', logExcerpt: parts.join('\n').trim() };
|
|
364
|
+
return { status: 'failure', runUrl, logExcerpt: parts.join('\n').trim() };
|
|
360
365
|
}
|
|
361
366
|
throw new GitPrError(message, GitPrErrorCode.GIT_ERROR, cause);
|
|
362
367
|
}
|
|
@@ -27,7 +27,7 @@ export async function deployFeature(featureId) {
|
|
|
27
27
|
}
|
|
28
28
|
log.info('worktree path exists, calling deploymentService.start()');
|
|
29
29
|
const deploymentService = resolve('IDeploymentService');
|
|
30
|
-
deploymentService.start(featureId, worktreePath);
|
|
30
|
+
deploymentService.start(featureId, worktreePath, 'feature');
|
|
31
31
|
log.info('start() returned successfully — state=Booting');
|
|
32
32
|
return { success: true, state: DeploymentState.Booting };
|
|
33
33
|
}
|
|
@@ -18,7 +18,7 @@ export async function deployRepository(repositoryPath) {
|
|
|
18
18
|
}
|
|
19
19
|
log.info('directory exists, calling deploymentService.start()');
|
|
20
20
|
const deploymentService = resolve('IDeploymentService');
|
|
21
|
-
deploymentService.start(repositoryPath, repositoryPath);
|
|
21
|
+
deploymentService.start(repositoryPath, repositoryPath, 'repository');
|
|
22
22
|
log.info('start() returned successfully — state=Booting');
|
|
23
23
|
return { success: true, state: DeploymentState.Booting };
|
|
24
24
|
}
|
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":"AAmCA,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,
|
|
1
|
+
{"version":3,"file":"repository-node.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/repository-node/repository-node.tsx"],"names":[],"mappings":"AAmCA,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,2CAkX5F"}
|
|
@@ -3,13 +3,12 @@ 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, GitBranch, GitCommitHorizontal, ArrowDown, User, } from 'lucide-react';
|
|
6
|
+
import { Github, Plus, Code2, Terminal, FolderOpen, Trash2, Play, Square, GitBranch, GitCommitHorizontal, ArrowDown, User, RotateCcw, } 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';
|
|
10
10
|
import { Button } from '../../ui/button.js';
|
|
11
11
|
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '../../ui/tooltip.js';
|
|
12
|
-
import { DeploymentStatusBadge } from '../../common/deployment-status-badge/index.js';
|
|
13
12
|
import { useDeployAction } from '../../../hooks/use-deploy-action.js';
|
|
14
13
|
import { useFeatureFlags } from '../../../hooks/feature-flags-context.js';
|
|
15
14
|
import { useRepositoryActions } from './use-repository-actions.js';
|
|
@@ -72,9 +71,13 @@ export function RepositoryNode({ data }) {
|
|
|
72
71
|
e.stopPropagation();
|
|
73
72
|
data.onClick?.();
|
|
74
73
|
}
|
|
75
|
-
}, className: "nodrag bg-card flex w-[26rem] cursor-pointer flex-col overflow-hidden rounded-xl border shadow-sm", children: [_jsxs("div", { className: "flex items-center gap-3 px-4 py-3", 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 })
|
|
74
|
+
}, className: "nodrag bg-card flex w-[26rem] cursor-pointer flex-col overflow-hidden rounded-xl border shadow-sm", children: [_jsxs("div", { className: "flex items-center gap-3 px-4 py-3", 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 })] })) : 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
75
|
e.stopPropagation();
|
|
77
76
|
data.onAdd?.();
|
|
78
77
|
}, 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.branch ? (_jsx("div", { "data-testid": "repository-node-git-info", className: "text-muted-foreground border-t px-4 py-2", children: _jsxs("div", { className: "flex items-center gap-3 text-xs", children: [_jsxs("span", { className: "flex items-center gap-1 truncate", "data-testid": "repository-node-branch", children: [_jsx(GitBranch, { className: "h-3 w-3 shrink-0" }), _jsx("span", { className: "truncate", children: data.branch })] }), data.behindCount != null && data.behindCount > 0 ? (_jsxs("span", { className: "flex shrink-0 items-center gap-1 whitespace-nowrap text-amber-500", "data-testid": "repository-node-behind", children: [_jsx(ArrowDown, { className: "h-3 w-3 shrink-0" }), data.behindCount, " behind"] })) : null] }) })) : null, data.commitMessage ? (_jsx("div", { "data-testid": "repository-node-commit-info", className: "text-muted-foreground border-t px-4 py-2", children: _jsxs("div", { className: "flex items-center gap-2 text-xs", children: [_jsx(GitCommitHorizontal, { className: "h-3 w-3 shrink-0" }), _jsx("span", { className: "min-w-0 truncate", "data-testid": "repository-node-commit-message", children: data.commitMessage }), data.committer ? (_jsxs("span", { className: "text-muted-foreground/70 ml-auto flex shrink-0 items-center gap-1", "data-testid": "repository-node-committer", children: [_jsx(User, { className: "h-3 w-3 shrink-0" }), _jsx("span", { children: data.committer })] })) : null] }) })) : null
|
|
78
|
+
'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.branch ? (_jsx("div", { "data-testid": "repository-node-git-info", className: "text-muted-foreground border-t px-4 py-2", children: _jsxs("div", { className: "flex items-center gap-3 text-xs", children: [_jsxs("span", { className: "flex items-center gap-1 truncate", "data-testid": "repository-node-branch", children: [_jsx(GitBranch, { className: "h-3 w-3 shrink-0" }), _jsx("span", { className: "truncate", children: data.branch })] }), data.behindCount != null && data.behindCount > 0 ? (_jsxs("span", { className: "flex shrink-0 items-center gap-1 whitespace-nowrap text-amber-500", "data-testid": "repository-node-behind", children: [_jsx(ArrowDown, { className: "h-3 w-3 shrink-0" }), data.behindCount, " behind"] })) : null] }) })) : null, data.commitMessage ? (_jsx("div", { "data-testid": "repository-node-commit-info", className: "text-muted-foreground border-t px-4 py-2", children: _jsxs("div", { className: "flex items-center gap-2 text-xs", children: [_jsx(GitCommitHorizontal, { className: "h-3 w-3 shrink-0" }), _jsx("span", { className: "min-w-0 truncate", "data-testid": "repository-node-commit-message", children: data.commitMessage }), data.committer ? (_jsxs("span", { className: "text-muted-foreground/70 ml-auto flex shrink-0 items-center gap-1", "data-testid": "repository-node-committer", children: [_jsx(User, { className: "h-3 w-3 shrink-0" }), _jsx("span", { children: data.committer })] })) : null] }) })) : null, featureFlags.envDeploy && data.repositoryPath ? (_jsx("div", { "data-testid": "repository-node-dev-preview", className: "border-t px-4 py-2", onClick: (e) => e.stopPropagation(), children: _jsxs("div", { className: "flex items-center gap-2 text-xs", children: [deployAction.deployError ? (_jsx("span", { className: "truncate text-xs text-red-500", children: deployAction.deployError })) : isDeploymentActive ? (_jsxs(_Fragment, { children: [_jsx("span", { className: "mr-0.5 inline-block h-2 w-2 shrink-0 rounded-full bg-green-500" }), deployAction.url ? (_jsx("a", { href: deployAction.url, target: "_blank", rel: "noopener noreferrer", className: "truncate text-green-700 hover:underline dark:text-green-400", children: deployAction.url })) : (_jsx("span", { className: "text-muted-foreground", children: "Starting..." }))] })) : (_jsxs("span", { className: "text-muted-foreground", children: ["Run", _jsx("span", { className: "text-muted-foreground/50 ml-2 text-[10px]", children: "start local environment" })] })), _jsx(TooltipProvider, { children: _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("span", { className: "ml-auto flex items-center", children: _jsx(ActionButton, { label: deployAction.deployError
|
|
79
|
+
? 'Retry'
|
|
80
|
+
: isDeploymentActive
|
|
81
|
+
? 'Stop Dev Server'
|
|
82
|
+
: 'Start Dev Server', onClick: isDeploymentActive ? deployAction.stop : deployAction.deploy, loading: deployAction.deployLoading || deployAction.stopLoading, error: false, icon: deployAction.deployError ? RotateCcw : isDeploymentActive ? Square : Play, iconOnly: true, variant: "ghost", size: "icon-xs" }) }) }), _jsx(TooltipContent, { children: isDeploymentActive ? 'Stop Dev Server' : 'Start Dev Server' })] }) })] }) })) : null] }), data.onAdd || data.showHandles ? (_jsx(Handle, { type: "source", position: Position.Right, isConnectable: !data.showHandles, className: "opacity-0!" })) : null] }));
|
|
80
83
|
}
|
|
@@ -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;AAgBjC,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,EAAE,aAAa,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;IAC7F,kBAAkB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAChD,kBAAkB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAChD,iBAAiB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/C,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;AAgBjC,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,EAAE,aAAa,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;IAC7F,kBAAkB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAChD,kBAAkB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAChD,iBAAiB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/C,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,CAuhBpB"}
|
package/dist/src/presentation/web/components/features/control-center/use-control-center-state.js
CHANGED
|
@@ -102,11 +102,20 @@ export function useControlCenterState(initialNodes, initialEdges) {
|
|
|
102
102
|
for (const { featureId, state, lifecycle } of resolveSseEventUpdates(newEvents)) {
|
|
103
103
|
if (state !== undefined || lifecycle !== undefined) {
|
|
104
104
|
const nodeId = `feat-${featureId}`;
|
|
105
|
+
const existingNode = nodesRef.current.find((n) => n.id === nodeId);
|
|
106
|
+
const existingState = existingNode
|
|
107
|
+
? existingNode.data.state
|
|
108
|
+
: undefined;
|
|
105
109
|
// Skip SSE updates for features in 'deleting' state — the optimistic
|
|
106
110
|
// delete state must not be overwritten by stale SSE events (e.g. agent
|
|
107
111
|
// cancellation emitting AgentFailed during the soft-delete window).
|
|
108
|
-
|
|
109
|
-
|
|
112
|
+
if (existingState === 'deleting')
|
|
113
|
+
continue;
|
|
114
|
+
// Skip SSE error events during mutation cooldown — after approve/reject
|
|
115
|
+
// the agent may still report AgentFailed from the previous run before
|
|
116
|
+
// the resume kicks in. The optimistic 'running' state must not be
|
|
117
|
+
// overwritten by stale error events during this transition window.
|
|
118
|
+
if (state === 'error' && isMutating() && existingState === 'running')
|
|
110
119
|
continue;
|
|
111
120
|
updateFeature(nodeId, {
|
|
112
121
|
...(state !== undefined && { state }),
|
|
@@ -114,7 +123,7 @@ export function useControlCenterState(initialNodes, initialEdges) {
|
|
|
114
123
|
});
|
|
115
124
|
}
|
|
116
125
|
}
|
|
117
|
-
}, [events, updateFeature]);
|
|
126
|
+
}, [events, updateFeature, isMutating]);
|
|
118
127
|
// Listen for optimistic approval/rejection events from the drawer (fires before SSE arrives).
|
|
119
128
|
// Uses beginMutation + endMutation to prevent stale poll/reconcile data from overwriting
|
|
120
129
|
// the optimistic 'running' state during the transition window (avoids brief "Something went wrong" flash).
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"notification-settings-section.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/settings/notification-settings-section.tsx"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,sCAAsC,CAAC;AAmBpF,MAAM,WAAW,gCAAgC;IAC/C,aAAa,EAAE,uBAAuB,CAAC;CACxC;AAED,wBAAgB,2BAA2B,CAAC,EAAE,aAAa,EAAE,EAAE,gCAAgC,
|
|
1
|
+
{"version":3,"file":"notification-settings-section.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/settings/notification-settings-section.tsx"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,sCAAsC,CAAC;AAmBpF,MAAM,WAAW,gCAAgC;IAC/C,aAAa,EAAE,uBAAuB,CAAC;CACxC;AAED,wBAAgB,2BAA2B,CAAC,EAAE,aAAa,EAAE,EAAE,gCAAgC,2CAsH9F"}
|
package/dist/src/presentation/web/components/features/settings/notification-settings-section.js
CHANGED
|
@@ -25,8 +25,6 @@ const PR_EVENT_TOGGLES = [
|
|
|
25
25
|
];
|
|
26
26
|
export function NotificationSettingsSection({ notifications }) {
|
|
27
27
|
const [inApp, setInApp] = useState(notifications.inApp.enabled);
|
|
28
|
-
const [browser, setBrowser] = useState(notifications.browser.enabled);
|
|
29
|
-
const [desktop, setDesktop] = useState(notifications.desktop.enabled);
|
|
30
28
|
const [events, setEvents] = useState({ ...notifications.events });
|
|
31
29
|
const [isPending, startTransition] = useTransition();
|
|
32
30
|
const [showSaved, setShowSaved] = useState(false);
|
|
@@ -51,20 +49,18 @@ export function NotificationSettingsSection({ notifications }) {
|
|
|
51
49
|
return {
|
|
52
50
|
notifications: {
|
|
53
51
|
inApp: { enabled: overrides.inApp ?? inApp },
|
|
54
|
-
browser: { enabled: overrides.browser ?? browser },
|
|
55
|
-
desktop: { enabled: overrides.desktop ?? desktop },
|
|
56
52
|
events: overrides.events ?? events,
|
|
57
53
|
},
|
|
58
54
|
};
|
|
59
55
|
}
|
|
60
|
-
function
|
|
61
|
-
|
|
62
|
-
save(buildFullPayload({
|
|
56
|
+
function handleInAppChange(value) {
|
|
57
|
+
setInApp(value);
|
|
58
|
+
save(buildFullPayload({ inApp: value }));
|
|
63
59
|
}
|
|
64
60
|
function handleEventChange(key, value) {
|
|
65
61
|
const newEvents = { ...events, [key]: value };
|
|
66
62
|
setEvents(newEvents);
|
|
67
63
|
save(buildFullPayload({ events: newEvents }));
|
|
68
64
|
}
|
|
69
|
-
return (_jsxs(Card, { id: "notifications", className: "scroll-mt-6", "data-testid": "notification-settings-section", children: [_jsxs(CardHeader, { children: [_jsxs("div", { className: "flex items-center justify-between", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Bell, { className: "text-muted-foreground h-4 w-4" }), _jsx(CardTitle, { children: "Notifications" })] }), isPending ? _jsx("span", { className: "text-muted-foreground text-xs", children: "Saving..." }) : null, showSaved && !isPending ? (_jsxs("span", { className: "flex items-center gap-1 text-xs text-green-600", children: [_jsx(Check, { className: "h-3 w-3" }), "Saved"] })) : null] }), _jsx(CardDescription, { children: "Configure notification channels and event preferences" })] }), _jsxs(CardContent, { className: "space-y-4", children: [_jsxs("div", { className: "space-y-3", children: [_jsx("h3", { className: "text-sm font-semibold", children: "Channels" }), _jsxs("div", { className: "flex items-center justify-between", children: [_jsx(Label, { htmlFor: "notif-in-app", children: "In-App" }), _jsx(Switch, { id: "notif-in-app", "data-testid": "switch-in-app", checked: inApp, onCheckedChange:
|
|
65
|
+
return (_jsxs(Card, { id: "notifications", className: "scroll-mt-6", "data-testid": "notification-settings-section", children: [_jsxs(CardHeader, { children: [_jsxs("div", { className: "flex items-center justify-between", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Bell, { className: "text-muted-foreground h-4 w-4" }), _jsx(CardTitle, { children: "Notifications" })] }), isPending ? _jsx("span", { className: "text-muted-foreground text-xs", children: "Saving..." }) : null, showSaved && !isPending ? (_jsxs("span", { className: "flex items-center gap-1 text-xs text-green-600", children: [_jsx(Check, { className: "h-3 w-3" }), "Saved"] })) : null] }), _jsx(CardDescription, { children: "Configure notification channels and event preferences" })] }), _jsxs(CardContent, { className: "space-y-4", children: [_jsxs("div", { className: "space-y-3", children: [_jsx("h3", { className: "text-sm font-semibold", children: "Channels" }), _jsxs("div", { className: "flex items-center justify-between", children: [_jsx(Label, { htmlFor: "notif-in-app", children: "In-App" }), _jsx(Switch, { id: "notif-in-app", "data-testid": "switch-in-app", checked: inApp, onCheckedChange: handleInAppChange })] })] }), _jsx(Separator, {}), _jsxs("div", { className: "space-y-3", children: [_jsx("h3", { className: "text-sm font-semibold", children: "Agent Events" }), AGENT_EVENT_TOGGLES.map(({ key, label }) => (_jsxs("div", { className: "flex items-center justify-between", children: [_jsx(Label, { htmlFor: `notif-event-${key}`, children: label }), _jsx(Switch, { id: `notif-event-${key}`, "data-testid": `switch-event-${key}`, checked: events[key], onCheckedChange: (v) => handleEventChange(key, v) })] }, key)))] }), _jsx(Separator, {}), _jsxs("div", { className: "space-y-3", children: [_jsx("h3", { className: "text-sm font-semibold", children: "PR Events" }), PR_EVENT_TOGGLES.map(({ key, label }) => (_jsxs("div", { className: "flex items-center justify-between", children: [_jsx(Label, { htmlFor: `notif-event-${key}`, children: label }), _jsx(Switch, { id: `notif-event-${key}`, "data-testid": `switch-event-${key}`, checked: events[key], onCheckedChange: (v) => handleEventChange(key, v) })] }, key)))] })] })] }));
|
|
70
66
|
}
|
|
@@ -38,7 +38,7 @@ export const Default = {
|
|
|
38
38
|
args: {
|
|
39
39
|
notifications: {
|
|
40
40
|
inApp: { enabled: true },
|
|
41
|
-
browser: { enabled:
|
|
41
|
+
browser: { enabled: false },
|
|
42
42
|
desktop: { enabled: false },
|
|
43
43
|
events: allEvents,
|
|
44
44
|
},
|
|
@@ -48,8 +48,8 @@ export const AllEnabled = {
|
|
|
48
48
|
args: {
|
|
49
49
|
notifications: {
|
|
50
50
|
inApp: { enabled: true },
|
|
51
|
-
browser: { enabled:
|
|
52
|
-
desktop: { enabled:
|
|
51
|
+
browser: { enabled: false },
|
|
52
|
+
desktop: { enabled: false },
|
|
53
53
|
events: allEvents,
|
|
54
54
|
},
|
|
55
55
|
},
|
package/dist/src/presentation/web/components/features/settings/settings-page-client.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"settings-page-client.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/settings/settings-page-client.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"settings-page-client.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/settings/settings-page-client.tsx"],"names":[],"mappings":"AAkCA,OAAO,KAAK,EACV,QAAQ,EAGT,MAAM,sCAAsC,CAAC;AAC9C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uCAAuC,CAAC;AA2B/E,MAAM,WAAW,uBAAuB;IACtC,QAAQ,EAAE,QAAQ,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,kBAAkB,CAAC,EAAE,iBAAiB,EAAE,CAAC;CAC1C;AA6QD,wBAAgB,kBAAkB,CAAC,EACjC,QAAQ,EACR,QAAQ,EACR,UAAU,EACV,kBAAkB,GACnB,EAAE,uBAAuB,2CAulCzB"}
|
|
@@ -1,24 +1,17 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { useState, useTransition, useRef, useEffect, useCallback } from 'react';
|
|
4
|
-
import {
|
|
4
|
+
import { Check, Bot, Terminal, GitBranch, Activity, Bell, Flag, Database, Minus, Plus, ExternalLink, Settings2, Timer, } from 'lucide-react';
|
|
5
5
|
import { toast } from 'sonner';
|
|
6
6
|
import { cn } from '../../../lib/utils.js';
|
|
7
7
|
import { Label } from '../../ui/label.js';
|
|
8
|
-
import { Input } from '../../ui/input.js';
|
|
9
|
-
import { Button } from '../../ui/button.js';
|
|
10
8
|
import { Switch } from '../../ui/switch.js';
|
|
11
|
-
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '../../ui/tooltip.js';
|
|
12
9
|
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from '../../ui/select.js';
|
|
13
10
|
import { updateSettingsAction } from '../../../app/actions/update-settings.js';
|
|
14
|
-
import {
|
|
11
|
+
import { EditorType, TerminalType } from '../../../../../../packages/core/src/domain/generated/output.js';
|
|
15
12
|
import { getEditorTypeIcon } from '../../common/editor-type-icons.js';
|
|
16
13
|
import { AgentModelPicker } from '../../features/settings/AgentModelPicker/index.js';
|
|
17
14
|
import { TimeoutSlider } from '../../features/settings/timeout-slider.js';
|
|
18
|
-
const AUTH_METHOD_OPTIONS = [
|
|
19
|
-
{ value: AgentAuthMethod.Session, label: 'Session' },
|
|
20
|
-
{ value: AgentAuthMethod.Token, label: 'Token' },
|
|
21
|
-
];
|
|
22
15
|
const EDITOR_OPTIONS = [
|
|
23
16
|
{ value: EditorType.VsCode, label: 'VS Code' },
|
|
24
17
|
{ value: EditorType.Cursor, label: 'Cursor' },
|
|
@@ -125,9 +118,6 @@ export function SettingsPageClient({ settings, shepHome, dbFileSize, availableTe
|
|
|
125
118
|
const featureFlags = settings.featureFlags ?? { skills: false, envDeploy: false, debug: false };
|
|
126
119
|
// Agent state
|
|
127
120
|
const [agentType, setAgentType] = useState(settings.agent.type);
|
|
128
|
-
const authMethod = settings.agent.authMethod;
|
|
129
|
-
const [token, setToken] = useState(settings.agent.token ?? '');
|
|
130
|
-
const [showToken, setShowToken] = useState(false);
|
|
131
121
|
// Environment state
|
|
132
122
|
const [editor, setEditor] = useState(settings.environment.defaultEditor);
|
|
133
123
|
const [shell, setShell] = useState(settings.environment.shellPreference);
|
|
@@ -167,8 +157,6 @@ export function SettingsPageClient({ settings, shepHome, dbFileSize, availableTe
|
|
|
167
157
|
const [analyzeRepoTimeout, setAnalyzeRepoTimeout] = useState(String(Math.round((analyzeRepoConfig?.analyzeMs ?? 600_000) / 1000)));
|
|
168
158
|
// Notification state
|
|
169
159
|
const [inApp, setInApp] = useState(settings.notifications.inApp.enabled);
|
|
170
|
-
const [browser, setBrowser] = useState(settings.notifications.browser.enabled);
|
|
171
|
-
const [desktop, setDesktop] = useState(settings.notifications.desktop.enabled);
|
|
172
160
|
const [events, setEvents] = useState({ ...settings.notifications.events });
|
|
173
161
|
// Feature flags state
|
|
174
162
|
const [flags, setFlags] = useState({ ...featureFlags });
|
|
@@ -208,15 +196,6 @@ export function SettingsPageClient({ settings, shepHome, dbFileSize, availableTe
|
|
|
208
196
|
const n = parseInt(value, 10);
|
|
209
197
|
return Number.isNaN(n) || n <= 0 ? undefined : n;
|
|
210
198
|
}
|
|
211
|
-
// Agent helpers
|
|
212
|
-
function buildAgentPayload(overrides = {}) {
|
|
213
|
-
const merged = { type: agentType, authMethod, ...overrides };
|
|
214
|
-
const result = { type: merged.type, authMethod: merged.authMethod };
|
|
215
|
-
if (merged.authMethod === AgentAuthMethod.Token) {
|
|
216
|
-
result.token = overrides.token ?? token;
|
|
217
|
-
}
|
|
218
|
-
return { agent: result };
|
|
219
|
-
}
|
|
220
199
|
function secondsToMs(val) {
|
|
221
200
|
if (val === undefined)
|
|
222
201
|
return undefined;
|
|
@@ -261,8 +240,6 @@ export function SettingsPageClient({ settings, shepHome, dbFileSize, availableTe
|
|
|
261
240
|
return {
|
|
262
241
|
notifications: {
|
|
263
242
|
inApp: { enabled: overrides.inApp ?? inApp },
|
|
264
|
-
browser: { enabled: overrides.browser ?? browser },
|
|
265
|
-
desktop: { enabled: overrides.desktop ?? desktop },
|
|
266
243
|
events: overrides.events ?? events,
|
|
267
244
|
},
|
|
268
245
|
};
|
|
@@ -301,11 +278,7 @@ export function SettingsPageClient({ settings, shepHome, dbFileSize, availableTe
|
|
|
301
278
|
return (_jsxs("button", { type: "button", onClick: () => scrollToSection(s.id), className: cn('flex cursor-pointer items-center gap-1 rounded-md px-1.5 py-1 text-[11px] transition-all', isActive
|
|
302
279
|
? 'bg-accent text-foreground font-medium'
|
|
303
280
|
: 'text-muted-foreground/60 hover:text-foreground hover:bg-accent/50'), children: [_jsx(SectionIcon, { className: "h-3 w-3" }), _jsx("span", { className: "hidden sm:inline", children: s.label })] }, s.id));
|
|
304
|
-
}) })] }) }), _jsxs("div", { className: "flex flex-col gap-3", children: [_jsxs("div", { id: "section-agent", className: "grid scroll-mt-18 grid-cols-1 gap-x-5 rounded-lg lg:grid-cols-[1fr_280px]", children: [
|
|
305
|
-
if (token !== (settings.agent.token ?? '')) {
|
|
306
|
-
save(buildAgentPayload({ token }));
|
|
307
|
-
}
|
|
308
|
-
}, placeholder: "Enter token", className: "pr-8" }), _jsx(Button, { type: "button", variant: "ghost", size: "sm", className: "absolute top-0 right-0 h-full px-2 hover:bg-transparent", onClick: () => setShowToken(!showToken), "data-testid": "toggle-token-visibility", "aria-label": showToken ? 'Hide token' : 'Show token', children: showToken ? _jsx(EyeOff, { className: "h-3 w-3" }) : _jsx(Eye, { className: "h-3 w-3" }) })] }) }))] }), _jsx(SectionHint, { links: [
|
|
281
|
+
}) })] }) }), _jsxs("div", { className: "flex flex-col gap-3", children: [_jsxs("div", { id: "section-agent", className: "grid scroll-mt-18 grid-cols-1 gap-x-5 rounded-lg lg:grid-cols-[1fr_280px]", children: [_jsx(SettingsSection, { icon: Bot, title: "Agent", description: "AI coding agent and authentication", testId: "agent-settings-section", children: _jsx(SettingsRow, { label: "Agent & Model", description: "Provider and model for all operations", htmlFor: "agent-model-picker", children: _jsx(AgentModelPicker, { initialAgentType: agentType, initialModel: settings.models.default, mode: "settings", onAgentModelChange: (newAgent) => setAgentType(newAgent), className: "w-55" }) }) }), _jsx(SectionHint, { links: [
|
|
309
282
|
{
|
|
310
283
|
label: 'Agent system',
|
|
311
284
|
href: 'https://github.com/shep-ai/cli/blob/main/docs/architecture/agent-system.md',
|
|
@@ -443,12 +416,6 @@ export function SettingsPageClient({ settings, shepHome, dbFileSize, availableTe
|
|
|
443
416
|
}, defaultSeconds: 600 }) })] }), _jsx(SectionHint, { children: "Each agent has independently configurable stage timeouts. When a stage exceeds its timeout, the agent is terminated. Longer timeouts are useful for complex implementations. Feature agent defaults to 30 minutes per stage. Analyze repository agent defaults to 10 minutes." })] }), _jsxs("div", { id: "section-notifications", className: "grid scroll-mt-18 grid-cols-1 gap-x-5 rounded-lg lg:grid-cols-[1fr_280px]", children: [_jsxs(SettingsSection, { icon: Bell, title: "Notifications", description: "How and when you get notified", testId: "notification-settings-section", children: [_jsx(SubsectionLabel, { children: "Channels" }), _jsx(SwitchRow, { label: "In-app", description: "Notifications inside the Shep UI", id: "notif-in-app", testId: "switch-in-app", checked: inApp, onChange: (v) => {
|
|
444
417
|
setInApp(v);
|
|
445
418
|
save(buildNotificationPayload({ inApp: v }));
|
|
446
|
-
} }), _jsx(SwitchRow, { label: "Browser", description: "Push notifications via the browser", id: "notif-browser", testId: "switch-browser", checked: browser, onChange: (v) => {
|
|
447
|
-
setBrowser(v);
|
|
448
|
-
save(buildNotificationPayload({ browser: v }));
|
|
449
|
-
} }), _jsx(SwitchRow, { label: "Desktop", description: "Native OS notifications", id: "notif-desktop", testId: "switch-desktop", checked: desktop, onChange: (v) => {
|
|
450
|
-
setDesktop(v);
|
|
451
|
-
save(buildNotificationPayload({ desktop: v }));
|
|
452
419
|
} }), _jsx(SubsectionLabel, { children: "Agent Events" }), _jsx(SwitchRow, { label: "Agent started", id: "notif-event-agentStarted", testId: "switch-event-agentStarted", checked: events.agentStarted, onChange: (v) => {
|
|
453
420
|
const newEvents = { ...events, agentStarted: v };
|
|
454
421
|
setEvents(newEvents);
|
|
@@ -485,12 +452,20 @@ export function SettingsPageClient({ settings, shepHome, dbFileSize, availableTe
|
|
|
485
452
|
const newEvents = { ...events, prChecksFailed: v };
|
|
486
453
|
setEvents(newEvents);
|
|
487
454
|
save(buildNotificationPayload({ events: newEvents }));
|
|
455
|
+
} }), _jsx(SwitchRow, { label: "PR blocked", id: "notif-event-prBlocked", testId: "switch-event-prBlocked", checked: events.prBlocked, onChange: (v) => {
|
|
456
|
+
const newEvents = { ...events, prBlocked: v };
|
|
457
|
+
setEvents(newEvents);
|
|
458
|
+
save(buildNotificationPayload({ events: newEvents }));
|
|
459
|
+
} }), _jsx(SwitchRow, { label: "Merge review ready", id: "notif-event-mergeReviewReady", testId: "switch-event-mergeReviewReady", checked: events.mergeReviewReady, onChange: (v) => {
|
|
460
|
+
const newEvents = { ...events, mergeReviewReady: v };
|
|
461
|
+
setEvents(newEvents);
|
|
462
|
+
save(buildNotificationPayload({ events: newEvents }));
|
|
488
463
|
} })] }), _jsx(SectionHint, { links: [
|
|
489
464
|
{
|
|
490
465
|
label: 'Notification system',
|
|
491
466
|
href: 'https://github.com/shep-ai/cli/blob/main/specs/021-agent-notifications/spec.yaml',
|
|
492
467
|
},
|
|
493
|
-
], children: "
|
|
468
|
+
], children: "In-app toast notifications keep you in the loop. Fine-tune which agent lifecycle events trigger a notification." })] }), _jsxs("div", { id: "section-feature-flags", className: "grid scroll-mt-18 grid-cols-1 gap-x-5 rounded-lg lg:grid-cols-[1fr_280px]", children: [_jsxs(SettingsSection, { icon: Flag, title: "Feature Flags", description: "Enable or disable experimental features", badge: "Experimental", testId: "feature-flags-settings-section", children: [_jsx(SwitchRow, { label: "Skills", description: "Enable the skills system for agent capabilities", id: "flag-skills", testId: "switch-flag-skills", checked: flags.skills, onChange: (v) => {
|
|
494
469
|
const newFlags = { ...flags, skills: v };
|
|
495
470
|
setFlags(newFlags);
|
|
496
471
|
save({ featureFlags: newFlags });
|
package/dist/src/presentation/web/components/features/settings/settings-page-client.stories.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"settings-page-client.stories.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/settings/settings-page-client.stories.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAQ,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAM5D,QAAA,MAAM,IAAI;;;;;;;CAOiC,CAAC;AAE5C,eAAe,IAAI,CAAC;AACpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,IAAI,CAAC,CAAC;AAEnC,eAAO,MAAM,OAAO,EAAE,KAMrB,CAAC;AAEF,eAAO,MAAM,WAAW,EAAE,
|
|
1
|
+
{"version":3,"file":"settings-page-client.stories.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/settings/settings-page-client.stories.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAQ,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAM5D,QAAA,MAAM,IAAI;;;;;;;CAOiC,CAAC;AAE5C,eAAe,IAAI,CAAC;AACpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,IAAI,CAAC,CAAC;AAEnC,eAAO,MAAM,OAAO,EAAE,KAMrB,CAAC;AAEF,eAAO,MAAM,WAAW,EAAE,KAiBzB,CAAC;AAEF,eAAO,MAAM,eAAe,EAAE,KAa7B,CAAC;AAEF,eAAO,MAAM,cAAc,EAAE,KAsB5B,CAAC"}
|
package/dist/src/presentation/web/components/features/settings/settings-page-client.stories.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { SettingsPageClient } from './settings-page-client.js';
|
|
2
2
|
import { createDefaultSettings } from '../../../../../../packages/core/src/domain/factories/settings-defaults.factory.js';
|
|
3
|
-
import { AgentType
|
|
3
|
+
import { AgentType } from '../../../../../../packages/core/src/domain/generated/output.js';
|
|
4
4
|
const defaultSettings = createDefaultSettings();
|
|
5
5
|
const meta = {
|
|
6
6
|
title: 'Features/Settings/SettingsPageClient',
|
|
@@ -23,9 +23,8 @@ export const AllSections = {
|
|
|
23
23
|
settings: {
|
|
24
24
|
...defaultSettings,
|
|
25
25
|
agent: {
|
|
26
|
+
...defaultSettings.agent,
|
|
26
27
|
type: AgentType.GeminiCli,
|
|
27
|
-
authMethod: AgentAuthMethod.Token,
|
|
28
|
-
token: 'sk-test-token-12345',
|
|
29
28
|
},
|
|
30
29
|
featureFlags: {
|
|
31
30
|
skills: true,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-deploy-action.d.ts","sourceRoot":"","sources":["../../../../../src/presentation/web/hooks/use-deploy-action.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sCAAsC,CAAC;AAM5E,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,SAAS,GAAG,YAAY,CAAC;IACrC,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5B,IAAI,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1B,aAAa,EAAE,OAAO,CAAC;IACvB,WAAW,EAAE,OAAO,CAAC;IACrB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,MAAM,EAAE,eAAe,GAAG,IAAI,CAAC;IAC/B,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;CACpB;
|
|
1
|
+
{"version":3,"file":"use-deploy-action.d.ts","sourceRoot":"","sources":["../../../../../src/presentation/web/hooks/use-deploy-action.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sCAAsC,CAAC;AAM5E,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,SAAS,GAAG,YAAY,CAAC;IACrC,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5B,IAAI,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1B,aAAa,EAAE,OAAO,CAAC;IACvB,WAAW,EAAE,OAAO,CAAC;IACrB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,MAAM,EAAE,eAAe,GAAG,IAAI,CAAC;IAC/B,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;CACpB;AAMD,wBAAgB,eAAe,CAAC,KAAK,EAAE,iBAAiB,GAAG,IAAI,GAAG,iBAAiB,CAmOlF"}
|
|
@@ -6,7 +6,6 @@ import { deployRepository } from '../app/actions/deploy-repository.js';
|
|
|
6
6
|
import { stopDeployment } from '../app/actions/stop-deployment.js';
|
|
7
7
|
import { getDeploymentStatus } from '../app/actions/get-deployment-status.js';
|
|
8
8
|
const log = createLogger('[useDeployAction]');
|
|
9
|
-
const ERROR_CLEAR_DELAY = 5000;
|
|
10
9
|
const POLL_INTERVAL = 3000;
|
|
11
10
|
export function useDeployAction(input) {
|
|
12
11
|
const [deployLoading, setDeployLoading] = useState(false);
|
|
@@ -14,7 +13,6 @@ export function useDeployAction(input) {
|
|
|
14
13
|
const [deployError, setDeployError] = useState(null);
|
|
15
14
|
const [status, setStatus] = useState(null);
|
|
16
15
|
const [url, setUrl] = useState(null);
|
|
17
|
-
const errorTimerRef = useRef(null);
|
|
18
16
|
const pollIntervalRef = useRef(null);
|
|
19
17
|
const mountedRef = useRef(true);
|
|
20
18
|
const statusRef = useRef(status);
|
|
@@ -29,11 +27,37 @@ export function useDeployAction(input) {
|
|
|
29
27
|
mountedRef.current = false;
|
|
30
28
|
};
|
|
31
29
|
}, []);
|
|
30
|
+
// Fetch status on mount — recover running dev servers after page reload
|
|
31
|
+
useEffect(() => {
|
|
32
|
+
if (!input)
|
|
33
|
+
return;
|
|
34
|
+
let cancelled = false;
|
|
35
|
+
(async () => {
|
|
36
|
+
try {
|
|
37
|
+
const result = await getDeploymentStatus(input.targetId);
|
|
38
|
+
if (cancelled || !mountedRef.current)
|
|
39
|
+
return;
|
|
40
|
+
if (result && result.state !== 'Stopped') {
|
|
41
|
+
log.info(`mount recovery: "${input.targetId}" state=${result.state}, url=${result.url}`);
|
|
42
|
+
setStatus(result.state);
|
|
43
|
+
setUrl(result.url);
|
|
44
|
+
startPolling(input.targetId);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
// Server container may not be available (e.g., in tests)
|
|
49
|
+
log.debug(`mount recovery failed for "${input.targetId}" — ignoring`);
|
|
50
|
+
}
|
|
51
|
+
})();
|
|
52
|
+
return () => {
|
|
53
|
+
cancelled = true;
|
|
54
|
+
};
|
|
55
|
+
// Only run on mount (input identity is stable from the caller)
|
|
56
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
57
|
+
}, [input?.targetId]);
|
|
32
58
|
// Cleanup on unmount
|
|
33
59
|
useEffect(() => {
|
|
34
60
|
return () => {
|
|
35
|
-
if (errorTimerRef.current)
|
|
36
|
-
clearTimeout(errorTimerRef.current);
|
|
37
61
|
if (pollIntervalRef.current)
|
|
38
62
|
clearInterval(pollIntervalRef.current);
|
|
39
63
|
};
|
|
@@ -53,7 +77,20 @@ export function useDeployAction(input) {
|
|
|
53
77
|
stopPolling();
|
|
54
78
|
return;
|
|
55
79
|
}
|
|
56
|
-
|
|
80
|
+
let result;
|
|
81
|
+
try {
|
|
82
|
+
result = await getDeploymentStatus(targetId);
|
|
83
|
+
}
|
|
84
|
+
catch (err) {
|
|
85
|
+
log.warn(`poll fetch failed for "${targetId}":`, err);
|
|
86
|
+
// Treat fetch failure as deployment gone — clear UI
|
|
87
|
+
if (mountedRef.current) {
|
|
88
|
+
setStatus(null);
|
|
89
|
+
setUrl(null);
|
|
90
|
+
stopPolling();
|
|
91
|
+
}
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
57
94
|
if (!mountedRef.current)
|
|
58
95
|
return;
|
|
59
96
|
if (!result || result.state === 'Stopped') {
|
|
@@ -71,6 +108,32 @@ export function useDeployAction(input) {
|
|
|
71
108
|
}
|
|
72
109
|
}, POLL_INTERVAL);
|
|
73
110
|
}, [stopPolling]);
|
|
111
|
+
// Idle poll — when no deployment is known, periodically check if one was
|
|
112
|
+
// started externally (e.g., from the drawer while the repo node is mounted).
|
|
113
|
+
const IDLE_POLL_INTERVAL = 5000;
|
|
114
|
+
useEffect(() => {
|
|
115
|
+
if (!input || status !== null)
|
|
116
|
+
return;
|
|
117
|
+
const timer = setInterval(async () => {
|
|
118
|
+
if (!mountedRef.current)
|
|
119
|
+
return;
|
|
120
|
+
try {
|
|
121
|
+
const result = await getDeploymentStatus(input.targetId);
|
|
122
|
+
if (!mountedRef.current)
|
|
123
|
+
return;
|
|
124
|
+
if (result && result.state !== 'Stopped') {
|
|
125
|
+
log.info(`idle poll: "${input.targetId}" state=${result.state}, url=${result.url}`);
|
|
126
|
+
setStatus(result.state);
|
|
127
|
+
setUrl(result.url);
|
|
128
|
+
startPolling(input.targetId);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
catch {
|
|
132
|
+
// ignore
|
|
133
|
+
}
|
|
134
|
+
}, IDLE_POLL_INTERVAL);
|
|
135
|
+
return () => clearInterval(timer);
|
|
136
|
+
}, [input, status, startPolling]);
|
|
74
137
|
const handleDeploy = useCallback(async () => {
|
|
75
138
|
if (!input) {
|
|
76
139
|
log.warn('deploy() called but input is null — no-op');
|
|
@@ -81,8 +144,6 @@ export function useDeployAction(input) {
|
|
|
81
144
|
return;
|
|
82
145
|
}
|
|
83
146
|
log.info(`deploy() — targetType="${input.targetType}", targetId="${input.targetId}", repositoryPath="${input.repositoryPath}"`);
|
|
84
|
-
if (errorTimerRef.current)
|
|
85
|
-
clearTimeout(errorTimerRef.current);
|
|
86
147
|
setDeployLoading(true);
|
|
87
148
|
setDeployError(null);
|
|
88
149
|
try {
|
|
@@ -96,9 +157,8 @@ export function useDeployAction(input) {
|
|
|
96
157
|
}
|
|
97
158
|
if (!result.success) {
|
|
98
159
|
const errorMessage = result.error ?? 'An unexpected error occurred';
|
|
99
|
-
log.
|
|
160
|
+
log.warn(`deploy failed: ${errorMessage}`);
|
|
100
161
|
setDeployError(errorMessage);
|
|
101
|
-
errorTimerRef.current = setTimeout(() => setDeployError(null), ERROR_CLEAR_DELAY);
|
|
102
162
|
}
|
|
103
163
|
else {
|
|
104
164
|
log.info(`deploy succeeded — initial state=${result.state}, starting polling`);
|
|
@@ -113,7 +173,6 @@ export function useDeployAction(input) {
|
|
|
113
173
|
const errorMessage = err instanceof Error ? err.message : 'An unexpected error occurred';
|
|
114
174
|
log.error(`deploy threw exception: ${errorMessage}`, err);
|
|
115
175
|
setDeployError(errorMessage);
|
|
116
|
-
errorTimerRef.current = setTimeout(() => setDeployError(null), ERROR_CLEAR_DELAY);
|
|
117
176
|
}
|
|
118
177
|
finally {
|
|
119
178
|
if (mountedRef.current) {
|
|
@@ -3,12 +3,12 @@ import dagre from '@dagrejs/dagre';
|
|
|
3
3
|
export const CANVAS_LAYOUT_DEFAULTS = {
|
|
4
4
|
direction: 'LR',
|
|
5
5
|
ranksep: 200,
|
|
6
|
-
nodesep:
|
|
6
|
+
nodesep: 30,
|
|
7
7
|
};
|
|
8
8
|
/** Known node-type dimensions for the canvas node types */
|
|
9
9
|
const NODE_DIMENSIONS = {
|
|
10
|
-
featureNode: { width: 288, height:
|
|
11
|
-
repositoryNode: { width: 400, height:
|
|
10
|
+
featureNode: { width: 288, height: 160 },
|
|
11
|
+
repositoryNode: { width: 400, height: 160 },
|
|
12
12
|
};
|
|
13
13
|
function getNodeSize(node, defaultSize) {
|
|
14
14
|
// Prefer per-node size from data, then type-based lookup, then default
|