@shepai/cli 1.116.3 → 1.117.0-pr376.0b9d7e1
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/apis/json-schema/AnalyzeRepoTimeouts.yaml +10 -0
- package/apis/json-schema/EnvironmentConfig.yaml +5 -0
- package/apis/json-schema/SdlcLifecycle.yaml +1 -0
- package/apis/json-schema/StageTimeouts.yaml +35 -0
- package/apis/json-schema/TerminalType.yaml +10 -0
- package/apis/json-schema/WorkflowConfig.yaml +6 -0
- package/dist/packages/core/src/application/use-cases/features/create/create-feature.use-case.d.ts.map +1 -1
- package/dist/packages/core/src/application/use-cases/features/create/create-feature.use-case.js +17 -8
- package/dist/packages/core/src/application/use-cases/features/create/types.d.ts +2 -0
- package/dist/packages/core/src/application/use-cases/features/create/types.d.ts.map +1 -1
- package/dist/packages/core/src/application/use-cases/features/start-feature.use-case.d.ts +25 -0
- package/dist/packages/core/src/application/use-cases/features/start-feature.use-case.d.ts.map +1 -0
- package/dist/packages/core/src/application/use-cases/features/start-feature.use-case.js +116 -0
- package/dist/packages/core/src/domain/factories/settings-defaults.factory.d.ts.map +1 -1
- package/dist/packages/core/src/domain/factories/settings-defaults.factory.js +7 -1
- package/dist/packages/core/src/domain/generated/output.d.ts +58 -0
- package/dist/packages/core/src/domain/generated/output.d.ts.map +1 -1
- package/dist/packages/core/src/domain/generated/output.js +9 -0
- package/dist/packages/core/src/domain/lifecycle-gates.d.ts +3 -0
- package/dist/packages/core/src/domain/lifecycle-gates.d.ts.map +1 -1
- package/dist/packages/core/src/domain/lifecycle-gates.js +3 -0
- package/dist/packages/core/src/infrastructure/di/container.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/di/container.js +5 -0
- package/dist/packages/core/src/infrastructure/persistence/sqlite/mappers/settings.mapper.d.ts +8 -0
- package/dist/packages/core/src/infrastructure/persistence/sqlite/mappers/settings.mapper.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/persistence/sqlite/mappers/settings.mapper.js +46 -0
- package/dist/packages/core/src/infrastructure/persistence/sqlite/migrations/035-add-stage-timeout-ms.d.ts +22 -0
- package/dist/packages/core/src/infrastructure/persistence/sqlite/migrations/035-add-stage-timeout-ms.d.ts.map +1 -0
- package/dist/packages/core/src/infrastructure/persistence/sqlite/migrations/035-add-stage-timeout-ms.js +53 -0
- package/dist/packages/core/src/infrastructure/persistence/sqlite/migrations/036-add-terminal-preference.d.ts +11 -0
- package/dist/packages/core/src/infrastructure/persistence/sqlite/migrations/036-add-terminal-preference.d.ts.map +1 -0
- package/dist/packages/core/src/infrastructure/persistence/sqlite/migrations/036-add-terminal-preference.js +13 -0
- package/dist/packages/core/src/infrastructure/persistence/sqlite/migrations.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/persistence/sqlite/migrations.js +15 -6
- package/dist/packages/core/src/infrastructure/repositories/sqlite-settings.repository.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/repositories/sqlite-settings.repository.js +18 -2
- package/dist/packages/core/src/infrastructure/services/agents/analyze-repo/analyze-repository-graph.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/services/agents/analyze-repo/analyze-repository-graph.js +15 -0
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/node-helpers.d.ts +11 -1
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/node-helpers.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/node-helpers.js +42 -3
- package/dist/packages/core/src/infrastructure/services/tool-installer/tool-metadata.d.ts +5 -0
- package/dist/packages/core/src/infrastructure/services/tool-installer/tool-metadata.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/services/tool-installer/tool-metadata.js +7 -0
- package/dist/packages/core/src/infrastructure/services/tool-installer/tools/system-terminal.json +24 -0
- package/dist/src/presentation/cli/commands/feat/index.d.ts.map +1 -1
- package/dist/src/presentation/cli/commands/feat/index.js +2 -0
- package/dist/src/presentation/cli/commands/feat/ls.command.d.ts.map +1 -1
- package/dist/src/presentation/cli/commands/feat/ls.command.js +3 -0
- package/dist/src/presentation/cli/commands/feat/new.command.d.ts.map +1 -1
- package/dist/src/presentation/cli/commands/feat/new.command.js +9 -1
- package/dist/src/presentation/cli/commands/feat/start.command.d.ts +12 -0
- package/dist/src/presentation/cli/commands/feat/start.command.d.ts.map +1 -0
- package/dist/src/presentation/cli/commands/feat/start.command.js +43 -0
- package/dist/src/presentation/web/app/actions/create-feature.d.ts +2 -0
- package/dist/src/presentation/web/app/actions/create-feature.d.ts.map +1 -1
- package/dist/src/presentation/web/app/actions/create-feature.js +3 -1
- package/dist/src/presentation/web/app/actions/get-available-terminals.d.ts +12 -0
- package/dist/src/presentation/web/app/actions/get-available-terminals.d.ts.map +1 -0
- package/dist/src/presentation/web/app/actions/get-available-terminals.js +53 -0
- package/dist/src/presentation/web/app/actions/open-shell.d.ts.map +1 -1
- package/dist/src/presentation/web/app/actions/open-shell.js +47 -3
- package/dist/src/presentation/web/app/actions/start-feature.d.ts +5 -0
- package/dist/src/presentation/web/app/actions/start-feature.d.ts.map +1 -0
- package/dist/src/presentation/web/app/actions/start-feature.js +16 -0
- package/dist/src/presentation/web/app/api/agent-events/route.d.ts.map +1 -1
- package/dist/src/presentation/web/app/api/agent-events/route.js +1 -0
- package/dist/src/presentation/web/app/settings/page.d.ts.map +1 -1
- package/dist/src/presentation/web/app/settings/page.js +6 -2
- package/dist/src/presentation/web/components/common/base-drawer/base-drawer.js +1 -1
- package/dist/src/presentation/web/components/common/base-drawer/base-drawer.stories.js +1 -1
- package/dist/src/presentation/web/components/common/control-center-drawer/feature-drawer-client.d.ts.map +1 -1
- package/dist/src/presentation/web/components/common/control-center-drawer/feature-drawer-client.js +20 -1
- package/dist/src/presentation/web/components/common/feature-create-drawer/feature-create-drawer.d.ts +2 -0
- 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 +6 -2
- package/dist/src/presentation/web/components/common/feature-node/derive-feature-state.d.ts.map +1 -1
- package/dist/src/presentation/web/components/common/feature-node/derive-feature-state.js +6 -0
- package/dist/src/presentation/web/components/common/feature-node/feature-node-state-config.d.ts +3 -2
- package/dist/src/presentation/web/components/common/feature-node/feature-node-state-config.d.ts.map +1 -1
- package/dist/src/presentation/web/components/common/feature-node/feature-node-state-config.js +13 -1
- package/dist/src/presentation/web/components/common/feature-node/feature-node.d.ts.map +1 -1
- package/dist/src/presentation/web/components/common/feature-node/feature-node.js +12 -3
- package/dist/src/presentation/web/components/common/feature-node/feature-node.stories.d.ts +2 -0
- package/dist/src/presentation/web/components/common/feature-node/feature-node.stories.d.ts.map +1 -1
- package/dist/src/presentation/web/components/common/feature-node/feature-node.stories.js +36 -2
- package/dist/src/presentation/web/components/features/control-center/control-center-inner.d.ts.map +1 -1
- package/dist/src/presentation/web/components/features/control-center/control-center-inner.js +3 -1
- package/dist/src/presentation/web/components/features/control-center/use-control-center-state.d.ts +1 -0
- package/dist/src/presentation/web/components/features/control-center/use-control-center-state.d.ts.map +1 -1
- package/dist/src/presentation/web/components/features/control-center/use-control-center-state.js +23 -0
- package/dist/src/presentation/web/components/features/settings/environment-settings-section.d.ts +3 -1
- package/dist/src/presentation/web/components/features/settings/environment-settings-section.d.ts.map +1 -1
- package/dist/src/presentation/web/components/features/settings/environment-settings-section.js +32 -5
- package/dist/src/presentation/web/components/features/settings/environment-settings-section.stories.d.ts +2 -0
- package/dist/src/presentation/web/components/features/settings/environment-settings-section.stories.d.ts.map +1 -1
- package/dist/src/presentation/web/components/features/settings/environment-settings-section.stories.js +34 -1
- package/dist/src/presentation/web/components/features/settings/settings-page-client.d.ts +3 -1
- 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 +120 -15
- package/dist/src/presentation/web/components/features/settings/settings-page-client.stories.d.ts +1 -0
- 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 +23 -0
- package/dist/src/presentation/web/components/features/settings/timeout-slider.d.ts +11 -0
- package/dist/src/presentation/web/components/features/settings/timeout-slider.d.ts.map +1 -0
- package/dist/src/presentation/web/components/features/settings/timeout-slider.js +63 -0
- package/dist/src/presentation/web/components/features/settings/timeout-slider.stories.d.ts +10 -0
- package/dist/src/presentation/web/components/features/settings/timeout-slider.stories.d.ts.map +1 -0
- package/dist/src/presentation/web/components/features/settings/timeout-slider.stories.js +24 -0
- package/dist/src/presentation/web/components/features/settings/workflow-settings-section.d.ts.map +1 -1
- package/dist/src/presentation/web/components/features/settings/workflow-settings-section.js +97 -2
- package/dist/src/presentation/web/components/features/settings/workflow-settings-section.stories.d.ts.map +1 -1
- package/dist/src/presentation/web/components/features/settings/workflow-settings-section.stories.js +22 -0
- package/dist/src/presentation/web/components/ui/slider.d.ts +5 -0
- package/dist/src/presentation/web/components/ui/slider.d.ts.map +1 -0
- package/dist/src/presentation/web/components/ui/slider.js +10 -0
- package/dist/src/presentation/web/components/ui/slider.stories.d.ts +7 -0
- package/dist/src/presentation/web/components/ui/slider.stories.d.ts.map +1 -0
- package/dist/src/presentation/web/components/ui/slider.stories.js +15 -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 +1 -0
- package/dist/src/presentation/web/hooks/use-graph-state.d.ts.map +1 -1
- package/dist/src/presentation/web/hooks/use-graph-state.js +1 -0
- package/dist/src/presentation/web/lib/derive-graph.d.ts +2 -0
- package/dist/src/presentation/web/lib/derive-graph.d.ts.map +1 -1
- package/dist/src/presentation/web/lib/derive-graph.js +5 -0
- package/dist/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 +3 -3
- package/web/.next/required-server-files.json +3 -3
- package/web/.next/server/app/(dashboard)/@drawer/create/page/server-reference-manifest.json +55 -40
- package/web/.next/server/app/(dashboard)/@drawer/create/page.js +3 -3
- package/web/.next/server/app/(dashboard)/@drawer/create/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/create/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page/server-reference-manifest.json +67 -52
- 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 +67 -52
- 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 +51 -36
- package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page.js +3 -3
- package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/create/page/server-reference-manifest.json +55 -40
- package/web/.next/server/app/(dashboard)/create/page.js +3 -3
- package/web/.next/server/app/(dashboard)/create/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/create/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page/server-reference-manifest.json +67 -52
- 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 +67 -52
- 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 +51 -36
- package/web/.next/server/app/(dashboard)/page.js +3 -3
- package/web/.next/server/app/(dashboard)/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page/server-reference-manifest.json +51 -36
- package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page.js +3 -3
- package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/_global-error/page.js +1 -1
- package/web/.next/server/app/_global-error/page.js.nft.json +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 +2 -2
- 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/api/attachments/preview/route.js.nft.json +1 -1
- package/web/.next/server/app/api/evidence/route.js.nft.json +1 -1
- package/web/.next/server/app/settings/page/server-reference-manifest.json +25 -10
- package/web/.next/server/app/settings/page.js +3 -3
- 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 +2 -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 +2 -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 +2 -2
- 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/403f9_next_dist_esm_build_templates_app-route_4d623b8e.js +2 -2
- package/web/.next/server/chunks/403f9_next_dist_esm_build_templates_app-route_4d623b8e.js.map +1 -1
- package/web/.next/server/chunks/[root-of-the-server]__7d5492a0._.js +1 -1
- package/web/.next/server/chunks/[root-of-the-server]__7d5492a0._.js.map +1 -1
- package/web/.next/server/chunks/[root-of-the-server]__a402b567._.js +1 -1
- package/web/.next/server/chunks/[root-of-the-server]__cd67a84c._.js +1 -1
- package/web/.next/server/chunks/[root-of-the-server]__cd67a84c._.js.map +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_ed372306.js +3 -0
- package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_@drawer_repository_[repositoryId]_page_actions_ed372306.js.map +1 -0
- package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_repository_[repositoryId]_page_actions_32e26434.js +3 -0
- package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_repository_[repositoryId]_page_actions_32e26434.js.map +1 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__07a39ff2._.js +1 -1
- package/web/.next/server/chunks/ssr/{[root-of-the-server]__4af0afe0._.js → [root-of-the-server]__2dddfea9._.js} +2 -2
- package/web/.next/server/chunks/ssr/{[root-of-the-server]__4af0afe0._.js.map → [root-of-the-server]__2dddfea9._.js.map} +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__2ff2daf6._.js +4 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__2ff2daf6._.js.map +1 -0
- package/web/.next/server/chunks/ssr/{[root-of-the-server]__039967e3._.js → [root-of-the-server]__3155add4._.js} +2 -2
- package/web/.next/server/chunks/ssr/{[root-of-the-server]__039967e3._.js.map → [root-of-the-server]__3155add4._.js.map} +1 -1
- package/web/.next/server/chunks/ssr/{[root-of-the-server]__9bc1434f._.js → [root-of-the-server]__4c7486cb._.js} +2 -2
- package/web/.next/server/chunks/ssr/{[root-of-the-server]__9bc1434f._.js.map → [root-of-the-server]__4c7486cb._.js.map} +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__6367aea0._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__6367aea0._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__6b17a22d._.js +4 -0
- package/web/.next/server/chunks/ssr/{[root-of-the-server]__11033878._.js.map → [root-of-the-server]__6b17a22d._.js.map} +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__6bb00d90._.js +4 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__6bb00d90._.js.map +1 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__6eb2a2b0._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__6eb2a2b0._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__7b707feb._.js +4 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__7b707feb._.js.map +1 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__804c006d._.js +4 -0
- package/web/.next/server/chunks/ssr/{[root-of-the-server]__fdc75809._.js.map → [root-of-the-server]__804c006d._.js.map} +1 -1
- package/web/.next/server/chunks/ssr/{[root-of-the-server]__89e8a5cc._.js → [root-of-the-server]__8763fd7a._.js} +3 -3
- package/web/.next/server/chunks/ssr/[root-of-the-server]__8763fd7a._.js.map +1 -0
- package/web/.next/server/chunks/ssr/{[root-of-the-server]__e70c5627._.js → [root-of-the-server]__9c56d724._.js} +2 -2
- package/web/.next/server/chunks/ssr/{[root-of-the-server]__cbd8062c._.js.map → [root-of-the-server]__9c56d724._.js.map} +1 -1
- package/web/.next/server/chunks/ssr/{[root-of-the-server]__2773312c._.js → [root-of-the-server]__cfc116d5._.js} +2 -2
- package/web/.next/server/chunks/ssr/{[root-of-the-server]__2773312c._.js.map → [root-of-the-server]__cfc116d5._.js.map} +1 -1
- package/web/.next/server/chunks/ssr/{[root-of-the-server]__cbd8062c._.js → [root-of-the-server]__d3841d9e._.js} +2 -2
- package/web/.next/server/chunks/ssr/{[root-of-the-server]__e70c5627._.js.map → [root-of-the-server]__d3841d9e._.js.map} +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__db9afe04._.js +3 -0
- package/web/.next/server/chunks/ssr/{[root-of-the-server]__b1e68e34._.js.map → [root-of-the-server]__db9afe04._.js.map} +1 -1
- package/web/.next/server/chunks/ssr/_135edb9c._.js +1 -1
- package/web/.next/server/chunks/ssr/_135edb9c._.js.map +1 -1
- package/web/.next/server/chunks/ssr/_1bb131c4._.js +1 -1
- package/web/.next/server/chunks/ssr/_1bb131c4._.js.map +1 -1
- package/web/.next/server/chunks/ssr/_250a63ae._.js +1 -1
- package/web/.next/server/chunks/ssr/_250a63ae._.js.map +1 -1
- package/web/.next/server/chunks/ssr/_2eea2048._.js +3 -0
- package/web/.next/server/chunks/ssr/{_c5f84841._.js.map → _2eea2048._.js.map} +1 -1
- package/web/.next/server/chunks/ssr/{_8dacd1e7._.js → _2f6f48b8._.js} +2 -2
- package/web/.next/server/chunks/ssr/{_8dacd1e7._.js.map → _2f6f48b8._.js.map} +1 -1
- package/web/.next/server/chunks/ssr/{_6f0118a0._.js → _3d260002._.js} +2 -2
- package/web/.next/server/chunks/ssr/_3d260002._.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/_f5a1a9b8._.js +3 -0
- package/web/.next/server/chunks/ssr/_f5a1a9b8._.js.map +1 -0
- package/web/.next/server/chunks/ssr/b1a17_presentation_web_components_features_settings_settings-page-client_tsx_6ed9d5f8._.js +1 -1
- package/web/.next/server/chunks/ssr/b1a17_presentation_web_components_features_settings_settings-page-client_tsx_6ed9d5f8._.js.map +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_0835b28e._.js +5 -0
- package/web/.next/server/chunks/ssr/src_presentation_web_0835b28e._.js.map +1 -0
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_e99d78dd.js +3 -0
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_e99d78dd.js.map +1 -0
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_skills_page_actions_1fa8042e.js +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_skills_page_actions_1fa8042e.js.map +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_tools_page_actions_24684200.js +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_tools_page_actions_24684200.js.map +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_components_bf50c527._.js +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_components_de814675._.js +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_components_features_control-center_7ac3562e._.js +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_components_features_control-center_7ac3562e._.js.map +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_e8034a29._.js +5 -0
- package/web/.next/server/chunks/ssr/src_presentation_web_e8034a29._.js.map +1 -0
- 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 +320 -234
- package/web/.next/static/chunks/{18de73b2f14204d3.js → 09528d327a2bb15a.js} +1 -1
- package/web/.next/static/chunks/{e12f41ac3d49a7b5.js → 261a4f0c60d9e4ba.js} +1 -1
- package/web/.next/static/chunks/304a3dced97f4f68.js +2 -0
- package/web/.next/static/chunks/62a8173911f8f130.css +1 -0
- package/web/.next/static/chunks/{52285fdb39925ad5.js → 6a2f770718cd585d.js} +1 -1
- package/web/.next/static/chunks/{5de387864b89e64c.js → 8748274a8d9400da.js} +2 -2
- package/web/.next/static/chunks/a6d2916a7b4b2633.js +1 -0
- package/web/.next/static/chunks/bba38aefe51cfdfc.js +1 -0
- package/web/.next/static/chunks/bf6bd3385f65bed8.js +1 -0
- package/web/.next/static/chunks/{2babc8e3ae9ba6e8.js → c039476485c8b4e8.js} +1 -1
- package/web/.next/static/chunks/d363520c26e1cd08.js +1 -0
- package/web/.next/static/chunks/{fcde0cbb2976b933.js → e2ef95d904c360f3.js} +1 -1
- package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_@drawer_repository_[repositoryId]_page_actions_a1104008.js +0 -3
- package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_@drawer_repository_[repositoryId]_page_actions_a1104008.js.map +0 -1
- package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_repository_[repositoryId]_page_actions_92642200.js +0 -3
- package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_repository_[repositoryId]_page_actions_92642200.js.map +0 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__11033878._.js +0 -4
- package/web/.next/server/chunks/ssr/[root-of-the-server]__24dd0927._.js +0 -4
- package/web/.next/server/chunks/ssr/[root-of-the-server]__24dd0927._.js.map +0 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__5d87af2e._.js +0 -4
- package/web/.next/server/chunks/ssr/[root-of-the-server]__5d87af2e._.js.map +0 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__89e8a5cc._.js.map +0 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__aad040c0._.js +0 -4
- package/web/.next/server/chunks/ssr/[root-of-the-server]__aad040c0._.js.map +0 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__b1e68e34._.js +0 -3
- package/web/.next/server/chunks/ssr/[root-of-the-server]__fdc75809._.js +0 -4
- package/web/.next/server/chunks/ssr/_6f0118a0._.js.map +0 -1
- package/web/.next/server/chunks/ssr/_c5f84841._.js +0 -3
- package/web/.next/server/chunks/ssr/_d2e408a9._.js +0 -3
- package/web/.next/server/chunks/ssr/_d2e408a9._.js.map +0 -1
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_888633e1.js +0 -3
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_888633e1.js.map +0 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_ce7cbc3c._.js +0 -5
- package/web/.next/server/chunks/ssr/src_presentation_web_ce7cbc3c._.js.map +0 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_e2604413._.js +0 -5
- package/web/.next/server/chunks/ssr/src_presentation_web_e2604413._.js.map +0 -1
- package/web/.next/static/chunks/0b3ab176958a8286.js +0 -1
- package/web/.next/static/chunks/242446982e8d196e.js +0 -1
- package/web/.next/static/chunks/552e0f129144b54d.js +0 -1
- package/web/.next/static/chunks/57b45edf86522369.css +0 -1
- package/web/.next/static/chunks/7b924c47dd2a5a53.js +0 -2
- package/web/.next/static/chunks/c172f4a6010cb5b5.js +0 -1
- /package/web/.next/static/{CStnC7-QgiTd6U99YUc1N → nIxRprL30XWZ36yCODJqc}/_buildManifest.js +0 -0
- /package/web/.next/static/{CStnC7-QgiTd6U99YUc1N → nIxRprL30XWZ36yCODJqc}/_clientMiddlewareManifest.json +0 -0
- /package/web/.next/static/{CStnC7-QgiTd6U99YUc1N → nIxRprL30XWZ36yCODJqc}/_ssgManifest.js +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
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 { Eye, EyeOff, Check, Bot, Terminal, GitBranch, Activity, Bell, Flag, Database, Minus, Plus, ExternalLink, Settings2, } from 'lucide-react';
|
|
4
|
+
import { Eye, EyeOff, 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';
|
|
@@ -11,9 +11,10 @@ import { Switch } from '../../ui/switch.js';
|
|
|
11
11
|
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '../../ui/tooltip.js';
|
|
12
12
|
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from '../../ui/select.js';
|
|
13
13
|
import { updateSettingsAction } from '../../../app/actions/update-settings.js';
|
|
14
|
-
import { AgentAuthMethod, EditorType } from '../../../../../../packages/core/src/domain/generated/output.js';
|
|
14
|
+
import { AgentAuthMethod, EditorType, TerminalType, } from '../../../../../../packages/core/src/domain/generated/output.js';
|
|
15
15
|
import { getEditorTypeIcon } from '../../common/editor-type-icons.js';
|
|
16
16
|
import { AgentModelPicker } from '../../features/settings/AgentModelPicker/index.js';
|
|
17
|
+
import { TimeoutSlider } from '../../features/settings/timeout-slider.js';
|
|
17
18
|
const AUTH_METHOD_OPTIONS = [
|
|
18
19
|
{ value: AgentAuthMethod.Session, label: 'Session' },
|
|
19
20
|
{ value: AgentAuthMethod.Token, label: 'Token' },
|
|
@@ -25,11 +26,17 @@ const EDITOR_OPTIONS = [
|
|
|
25
26
|
{ value: EditorType.Zed, label: 'Zed' },
|
|
26
27
|
{ value: EditorType.Antigravity, label: 'Antigravity' },
|
|
27
28
|
];
|
|
29
|
+
const SHELL_OPTIONS = [
|
|
30
|
+
{ value: 'bash', label: 'Bash' },
|
|
31
|
+
{ value: 'zsh', label: 'Zsh' },
|
|
32
|
+
{ value: 'fish', label: 'Fish' },
|
|
33
|
+
];
|
|
28
34
|
const SECTIONS = [
|
|
29
35
|
{ id: 'agent', label: 'Agent', icon: Bot },
|
|
30
36
|
{ id: 'environment', label: 'Environment', icon: Terminal },
|
|
31
37
|
{ id: 'workflow', label: 'Workflow', icon: GitBranch },
|
|
32
38
|
{ id: 'ci', label: 'CI', icon: Activity },
|
|
39
|
+
{ id: 'stage-timeouts', label: 'Timeouts', icon: Timer },
|
|
33
40
|
{ id: 'notifications', label: 'Notifications', icon: Bell },
|
|
34
41
|
{ id: 'feature-flags', label: 'Flags', icon: Flag },
|
|
35
42
|
{ id: 'database', label: 'Database', icon: Database },
|
|
@@ -113,7 +120,7 @@ function SectionHint({ children, links, }) {
|
|
|
113
120
|
return (_jsxs("div", { className: "hidden pt-2 lg:block", children: [_jsx("p", { className: "text-muted-foreground/70 text-[11px] leading-relaxed", children: children }), links != null && links.length > 0 ? (_jsx("div", { className: "mt-2 flex flex-col gap-1", children: links.map((link) => (_jsxs("a", { href: link.href, target: "_blank", rel: "noopener noreferrer", className: "text-muted-foreground hover:text-foreground inline-flex items-center gap-1 text-[10px] transition-colors", children: [_jsx(ExternalLink, { className: "h-2.5 w-2.5" }), link.label] }, link.href))) })) : null] }));
|
|
114
121
|
}
|
|
115
122
|
/* ── Main component ── */
|
|
116
|
-
export function SettingsPageClient({ settings, shepHome, dbFileSize }) {
|
|
123
|
+
export function SettingsPageClient({ settings, shepHome, dbFileSize, availableTerminals, }) {
|
|
117
124
|
const { showSaving, showSaved, save } = useSaveIndicator();
|
|
118
125
|
const featureFlags = settings.featureFlags ?? { skills: false, envDeploy: false, debug: false };
|
|
119
126
|
// Agent state
|
|
@@ -123,7 +130,12 @@ export function SettingsPageClient({ settings, shepHome, dbFileSize }) {
|
|
|
123
130
|
const [showToken, setShowToken] = useState(false);
|
|
124
131
|
// Environment state
|
|
125
132
|
const [editor, setEditor] = useState(settings.environment.defaultEditor);
|
|
126
|
-
const shell = settings.environment.shellPreference;
|
|
133
|
+
const [shell, setShell] = useState(settings.environment.shellPreference);
|
|
134
|
+
const [terminal, setTerminal] = useState(settings.environment.terminalPreference ?? TerminalType.System);
|
|
135
|
+
// Filter to only show installed terminals
|
|
136
|
+
const terminalOptions = availableTerminals
|
|
137
|
+
? availableTerminals.filter((t) => t.available)
|
|
138
|
+
: [{ id: TerminalType.System, name: 'System Terminal', available: true }];
|
|
127
139
|
// Workflow state
|
|
128
140
|
const [openPr, setOpenPr] = useState(settings.workflow.openPrOnImplementationComplete);
|
|
129
141
|
const [pushOnComplete, setPushOnComplete] = useState(settings.workflow.approvalGateDefaults.pushOnImplementationComplete);
|
|
@@ -137,6 +149,18 @@ export function SettingsPageClient({ settings, shepHome, dbFileSize }) {
|
|
|
137
149
|
? String(Math.round(settings.workflow.ciWatchTimeoutMs / 1000))
|
|
138
150
|
: '');
|
|
139
151
|
const [ciLogMax, setCiLogMax] = useState(settings.workflow.ciLogMaxChars != null ? String(settings.workflow.ciLogMaxChars) : '');
|
|
152
|
+
// Feature agent per-stage timeout states (stored in seconds for display, converted to ms on save)
|
|
153
|
+
// Defaults: feature agent stages = 1_800_000 ms (1800s), analyze-repo = 600_000 ms (600s)
|
|
154
|
+
const stageTimeoutsConfig = settings.workflow.stageTimeouts;
|
|
155
|
+
const [analyzeTimeout, setAnalyzeTimeout] = useState(String(Math.round((stageTimeoutsConfig?.analyzeMs ?? 1_800_000) / 1000)));
|
|
156
|
+
const [requirementsTimeout, setRequirementsTimeout] = useState(String(Math.round((stageTimeoutsConfig?.requirementsMs ?? 1_800_000) / 1000)));
|
|
157
|
+
const [researchTimeout, setResearchTimeout] = useState(String(Math.round((stageTimeoutsConfig?.researchMs ?? 1_800_000) / 1000)));
|
|
158
|
+
const [planTimeout, setPlanTimeout] = useState(String(Math.round((stageTimeoutsConfig?.planMs ?? 1_800_000) / 1000)));
|
|
159
|
+
const [implementTimeout, setImplementTimeout] = useState(String(Math.round((stageTimeoutsConfig?.implementMs ?? 1_800_000) / 1000)));
|
|
160
|
+
const [mergeTimeout, setMergeTimeout] = useState(String(Math.round((stageTimeoutsConfig?.mergeMs ?? 1_800_000) / 1000)));
|
|
161
|
+
// Analyze-repo agent timeout state
|
|
162
|
+
const analyzeRepoConfig = settings.workflow.analyzeRepoTimeouts;
|
|
163
|
+
const [analyzeRepoTimeout, setAnalyzeRepoTimeout] = useState(String(Math.round((analyzeRepoConfig?.analyzeMs ?? 600_000) / 1000)));
|
|
140
164
|
// Notification state
|
|
141
165
|
const [inApp, setInApp] = useState(settings.notifications.inApp.enabled);
|
|
142
166
|
const [browser, setBrowser] = useState(settings.notifications.browser.enabled);
|
|
@@ -150,6 +174,27 @@ export function SettingsPageClient({ settings, shepHome, dbFileSize }) {
|
|
|
150
174
|
? String(Math.round(settings.workflow.ciWatchTimeoutMs / 1000))
|
|
151
175
|
: '';
|
|
152
176
|
const originalCiLogMax = settings.workflow.ciLogMaxChars != null ? String(settings.workflow.ciLogMaxChars) : '';
|
|
177
|
+
const originalAnalyzeTimeout = stageTimeoutsConfig?.analyzeMs != null
|
|
178
|
+
? String(Math.round(stageTimeoutsConfig.analyzeMs / 1000))
|
|
179
|
+
: '';
|
|
180
|
+
const originalRequirementsTimeout = stageTimeoutsConfig?.requirementsMs != null
|
|
181
|
+
? String(Math.round(stageTimeoutsConfig.requirementsMs / 1000))
|
|
182
|
+
: '';
|
|
183
|
+
const originalResearchTimeout = stageTimeoutsConfig?.researchMs != null
|
|
184
|
+
? String(Math.round(stageTimeoutsConfig.researchMs / 1000))
|
|
185
|
+
: '';
|
|
186
|
+
const originalPlanTimeout = stageTimeoutsConfig?.planMs != null
|
|
187
|
+
? String(Math.round(stageTimeoutsConfig.planMs / 1000))
|
|
188
|
+
: '';
|
|
189
|
+
const originalImplementTimeout = stageTimeoutsConfig?.implementMs != null
|
|
190
|
+
? String(Math.round(stageTimeoutsConfig.implementMs / 1000))
|
|
191
|
+
: '';
|
|
192
|
+
const originalMergeTimeout = stageTimeoutsConfig?.mergeMs != null
|
|
193
|
+
? String(Math.round(stageTimeoutsConfig.mergeMs / 1000))
|
|
194
|
+
: '';
|
|
195
|
+
const originalAnalyzeRepoTimeout = analyzeRepoConfig?.analyzeMs != null
|
|
196
|
+
? String(Math.round(analyzeRepoConfig.analyzeMs / 1000))
|
|
197
|
+
: '';
|
|
153
198
|
function parseOptionalInt(value) {
|
|
154
199
|
if (value === '')
|
|
155
200
|
return undefined;
|
|
@@ -165,6 +210,12 @@ export function SettingsPageClient({ settings, shepHome, dbFileSize }) {
|
|
|
165
210
|
}
|
|
166
211
|
return { agent: result };
|
|
167
212
|
}
|
|
213
|
+
function secondsToMs(val) {
|
|
214
|
+
if (val === undefined)
|
|
215
|
+
return undefined;
|
|
216
|
+
const n = parseOptionalInt(val);
|
|
217
|
+
return n != null ? n * 1000 : undefined;
|
|
218
|
+
}
|
|
168
219
|
// Workflow helpers
|
|
169
220
|
function buildWorkflowPayload(overrides = {}) {
|
|
170
221
|
const timeoutSeconds = parseOptionalInt(overrides.ciTimeout ?? ciTimeout);
|
|
@@ -182,6 +233,17 @@ export function SettingsPageClient({ settings, shepHome, dbFileSize }) {
|
|
|
182
233
|
ciMaxFixAttempts: parseOptionalInt(overrides.ciMaxFix ?? ciMaxFix),
|
|
183
234
|
ciWatchTimeoutMs: timeoutSeconds != null ? timeoutSeconds * 1000 : undefined,
|
|
184
235
|
ciLogMaxChars: parseOptionalInt(overrides.ciLogMax ?? ciLogMax),
|
|
236
|
+
stageTimeouts: {
|
|
237
|
+
analyzeMs: secondsToMs(overrides.analyzeTimeout ?? analyzeTimeout),
|
|
238
|
+
requirementsMs: secondsToMs(overrides.requirementsTimeout ?? requirementsTimeout),
|
|
239
|
+
researchMs: secondsToMs(overrides.researchTimeout ?? researchTimeout),
|
|
240
|
+
planMs: secondsToMs(overrides.planTimeout ?? planTimeout),
|
|
241
|
+
implementMs: secondsToMs(overrides.implementTimeout ?? implementTimeout),
|
|
242
|
+
mergeMs: secondsToMs(overrides.mergeTimeout ?? mergeTimeout),
|
|
243
|
+
},
|
|
244
|
+
analyzeRepoTimeouts: {
|
|
245
|
+
analyzeMs: secondsToMs(overrides.analyzeRepoTimeout ?? analyzeRepoTimeout),
|
|
246
|
+
},
|
|
185
247
|
},
|
|
186
248
|
};
|
|
187
249
|
}
|
|
@@ -247,20 +309,42 @@ export function SettingsPageClient({ settings, shepHome, dbFileSize }) {
|
|
|
247
309
|
label: 'Configuration guide',
|
|
248
310
|
href: 'https://github.com/shep-ai/cli/blob/main/docs/guides/configuration.md',
|
|
249
311
|
},
|
|
250
|
-
], children: "Choose which AI coding agent powers your features. Each agent supports different models and capabilities. Authentication is resolved automatically via your active session." })] }), _jsxs("div", { id: "section-environment", className: "grid scroll-mt-18 grid-cols-1 gap-x-5 rounded-lg lg:grid-cols-[1fr_280px]", children: [
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
})
|
|
312
|
+
], children: "Choose which AI coding agent powers your features. Each agent supports different models and capabilities. Authentication is resolved automatically via your active session." })] }), _jsxs("div", { id: "section-environment", className: "grid scroll-mt-18 grid-cols-1 gap-x-5 rounded-lg lg:grid-cols-[1fr_280px]", children: [_jsxs(SettingsSection, { icon: Terminal, title: "Environment", description: "Editor, shell, and terminal preferences", testId: "environment-settings-section", children: [_jsx(SettingsRow, { label: "Default Editor", description: "Editor launched for file operations", htmlFor: "default-editor", children: _jsxs(Select, { value: editor, onValueChange: (v) => {
|
|
313
|
+
setEditor(v);
|
|
314
|
+
save({
|
|
315
|
+
environment: {
|
|
316
|
+
defaultEditor: v,
|
|
317
|
+
shellPreference: shell,
|
|
318
|
+
terminalPreference: terminal,
|
|
319
|
+
},
|
|
320
|
+
});
|
|
321
|
+
}, children: [_jsx(SelectTrigger, { id: "default-editor", "data-testid": "editor-select", className: "w-55 cursor-pointer text-xs", children: _jsx(SelectValue, {}) }), _jsx(SelectContent, { children: EDITOR_OPTIONS.map((opt) => {
|
|
322
|
+
const Icon = getEditorTypeIcon(opt.value);
|
|
323
|
+
return (_jsx(SelectItem, { value: opt.value, children: _jsxs("span", { className: "flex items-center gap-2 text-xs", children: [_jsx(Icon, { className: "h-4 w-4 shrink-0" }), opt.label] }) }, opt.value));
|
|
324
|
+
}) })] }) }), _jsx(SettingsRow, { label: "Shell", description: "Default shell for generated scripts", htmlFor: "shell-preference", children: _jsxs(Select, { value: shell, onValueChange: (v) => {
|
|
325
|
+
setShell(v);
|
|
326
|
+
save({
|
|
327
|
+
environment: {
|
|
328
|
+
defaultEditor: editor,
|
|
329
|
+
shellPreference: v,
|
|
330
|
+
terminalPreference: terminal,
|
|
331
|
+
},
|
|
332
|
+
});
|
|
333
|
+
}, children: [_jsx(SelectTrigger, { id: "shell-preference", "data-testid": "shell-select", className: "w-55 cursor-pointer text-xs", children: _jsx(SelectValue, {}) }), _jsx(SelectContent, { children: SHELL_OPTIONS.map((opt) => (_jsx(SelectItem, { value: opt.value, children: opt.label }, opt.value))) })] }) }), _jsx(SettingsRow, { label: "Terminal", description: "Terminal emulator for shell sessions", htmlFor: "terminal-preference", children: _jsxs(Select, { value: terminal, onValueChange: (v) => {
|
|
334
|
+
setTerminal(v);
|
|
335
|
+
save({
|
|
336
|
+
environment: {
|
|
337
|
+
defaultEditor: editor,
|
|
338
|
+
shellPreference: shell,
|
|
339
|
+
terminalPreference: v,
|
|
340
|
+
},
|
|
341
|
+
});
|
|
342
|
+
}, children: [_jsx(SelectTrigger, { id: "terminal-preference", "data-testid": "terminal-select", className: "w-55 cursor-pointer text-xs", children: _jsx(SelectValue, {}) }), _jsx(SelectContent, { children: terminalOptions.map((opt) => (_jsx(SelectItem, { value: opt.id, children: opt.name }, opt.id))) })] }) })] }), _jsx(SectionHint, { links: [
|
|
259
343
|
{
|
|
260
344
|
label: 'Configuration guide',
|
|
261
345
|
href: 'https://github.com/shep-ai/cli/blob/main/docs/guides/configuration.md',
|
|
262
346
|
},
|
|
263
|
-
], children: "Your preferred editor is
|
|
347
|
+
], children: "Your preferred editor opens files for review. The shell setting controls generated scripts. The terminal emulator is launched when opening shell sessions from the web UI." })] }), _jsxs("div", { id: "section-workflow", className: "grid scroll-mt-18 grid-cols-1 gap-x-5 rounded-lg lg:grid-cols-[1fr_280px]", children: [_jsxs(SettingsSection, { icon: GitBranch, title: "Workflow", description: "Automation behavior after implementation", testId: "workflow-settings-section", children: [_jsx(SubsectionLabel, { children: "Approve" }), _jsx(SwitchRow, { label: "Auto-approve PRD", description: "Skip manual review of requirements", id: "allow-prd", testId: "switch-allow-prd", checked: allowPrd, onChange: (v) => {
|
|
264
348
|
setAllowPrd(v);
|
|
265
349
|
save(buildWorkflowPayload({ allowPrd: v }));
|
|
266
350
|
} }), _jsx(SwitchRow, { label: "Auto-approve Plan", description: "Skip manual review of implementation plan", id: "allow-plan", testId: "switch-allow-plan", checked: allowPlan, onChange: (v) => {
|
|
@@ -320,7 +404,28 @@ export function SettingsPageClient({ settings, shepHome, dbFileSize }) {
|
|
|
320
404
|
label: 'CI security gates',
|
|
321
405
|
href: 'https://github.com/shep-ai/cli/blob/main/specs/003-cicd-security-gates/spec.md',
|
|
322
406
|
},
|
|
323
|
-
], children: "When a feature completes, the agent can watch CI and auto-fix failures. These limits prevent runaway retries and control how much log output is sent to the agent for analysis." })] }), _jsxs("div", { id: "section-
|
|
407
|
+
], children: "When a feature completes, the agent can watch CI and auto-fix failures. These limits prevent runaway retries and control how much log output is sent to the agent for analysis." })] }), _jsxs("div", { id: "section-stage-timeouts", className: "grid scroll-mt-18 grid-cols-1 gap-x-5 rounded-lg lg:grid-cols-[1fr_280px]", children: [_jsxs(SettingsSection, { icon: Timer, title: "Stage Timeouts", description: "Maximum execution time per agent stage", testId: "stage-timeouts-settings-section", children: [_jsx(SubsectionLabel, { children: "Feature Agent" }), _jsx(SettingsRow, { label: "Analyze", description: "Repository analysis timeout", htmlFor: "timeout-analyze", children: _jsx(TimeoutSlider, { id: "timeout-analyze", testId: "timeout-analyze-input", value: analyzeTimeout, onChange: setAnalyzeTimeout, onBlur: () => {
|
|
408
|
+
if (analyzeTimeout !== originalAnalyzeTimeout)
|
|
409
|
+
save(buildWorkflowPayload({ analyzeTimeout }));
|
|
410
|
+
}, defaultSeconds: 1800 }) }), _jsx(SettingsRow, { label: "Requirements", description: "Requirements gathering timeout", htmlFor: "timeout-requirements", children: _jsx(TimeoutSlider, { id: "timeout-requirements", testId: "timeout-requirements-input", value: requirementsTimeout, onChange: setRequirementsTimeout, onBlur: () => {
|
|
411
|
+
if (requirementsTimeout !== originalRequirementsTimeout)
|
|
412
|
+
save(buildWorkflowPayload({ requirementsTimeout }));
|
|
413
|
+
}, defaultSeconds: 1800 }) }), _jsx(SettingsRow, { label: "Research", description: "Technical research timeout", htmlFor: "timeout-research", children: _jsx(TimeoutSlider, { id: "timeout-research", testId: "timeout-research-input", value: researchTimeout, onChange: setResearchTimeout, onBlur: () => {
|
|
414
|
+
if (researchTimeout !== originalResearchTimeout)
|
|
415
|
+
save(buildWorkflowPayload({ researchTimeout }));
|
|
416
|
+
}, defaultSeconds: 1800 }) }), _jsx(SettingsRow, { label: "Plan", description: "Implementation planning timeout", htmlFor: "timeout-plan", children: _jsx(TimeoutSlider, { id: "timeout-plan", testId: "timeout-plan-input", value: planTimeout, onChange: setPlanTimeout, onBlur: () => {
|
|
417
|
+
if (planTimeout !== originalPlanTimeout)
|
|
418
|
+
save(buildWorkflowPayload({ planTimeout }));
|
|
419
|
+
}, defaultSeconds: 1800 }) }), _jsx(SettingsRow, { label: "Implement", description: "Code implementation timeout", htmlFor: "timeout-implement", children: _jsx(TimeoutSlider, { id: "timeout-implement", testId: "timeout-implement-input", value: implementTimeout, onChange: setImplementTimeout, onBlur: () => {
|
|
420
|
+
if (implementTimeout !== originalImplementTimeout)
|
|
421
|
+
save(buildWorkflowPayload({ implementTimeout }));
|
|
422
|
+
}, defaultSeconds: 1800 }) }), _jsx(SettingsRow, { label: "Merge", description: "PR creation and merge timeout", htmlFor: "timeout-merge", children: _jsx(TimeoutSlider, { id: "timeout-merge", testId: "timeout-merge-input", value: mergeTimeout, onChange: setMergeTimeout, onBlur: () => {
|
|
423
|
+
if (mergeTimeout !== originalMergeTimeout)
|
|
424
|
+
save(buildWorkflowPayload({ mergeTimeout }));
|
|
425
|
+
}, defaultSeconds: 1800 }) }), _jsx(SubsectionLabel, { children: "Analyze Repository Agent" }), _jsx(SettingsRow, { label: "Analyze", description: "Repository analysis timeout", htmlFor: "timeout-analyze-repo", children: _jsx(TimeoutSlider, { id: "timeout-analyze-repo", testId: "timeout-analyze-repo-input", value: analyzeRepoTimeout, onChange: setAnalyzeRepoTimeout, onBlur: () => {
|
|
426
|
+
if (analyzeRepoTimeout !== originalAnalyzeRepoTimeout)
|
|
427
|
+
save(buildWorkflowPayload({ analyzeRepoTimeout }));
|
|
428
|
+
}, 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) => {
|
|
324
429
|
setInApp(v);
|
|
325
430
|
save(buildNotificationPayload({ inApp: v }));
|
|
326
431
|
} }), _jsx(SwitchRow, { label: "Browser", description: "Push notifications via the browser", id: "notif-browser", testId: "switch-browser", checked: browser, onChange: (v) => {
|
package/dist/src/presentation/web/components/features/settings/settings-page-client.stories.d.ts
CHANGED
|
@@ -13,4 +13,5 @@ type Story = StoryObj<typeof meta>;
|
|
|
13
13
|
export declare const Default: Story;
|
|
14
14
|
export declare const AllSections: Story;
|
|
15
15
|
export declare const EvidenceEnabled: Story;
|
|
16
|
+
export declare const CustomTimeouts: Story;
|
|
16
17
|
//# sourceMappingURL=settings-page-client.stories.d.ts.map
|
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,KAkBzB,CAAC;AAEF,eAAO,MAAM,eAAe,EAAE,KAa7B,CAAC"}
|
|
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,KAkBzB,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
|
@@ -51,3 +51,26 @@ export const EvidenceEnabled = {
|
|
|
51
51
|
dbFileSize: '2.4 MB',
|
|
52
52
|
},
|
|
53
53
|
};
|
|
54
|
+
export const CustomTimeouts = {
|
|
55
|
+
args: {
|
|
56
|
+
settings: {
|
|
57
|
+
...defaultSettings,
|
|
58
|
+
workflow: {
|
|
59
|
+
...defaultSettings.workflow,
|
|
60
|
+
stageTimeouts: {
|
|
61
|
+
analyzeMs: 300000,
|
|
62
|
+
requirementsMs: 600000,
|
|
63
|
+
researchMs: 900000,
|
|
64
|
+
planMs: 600000,
|
|
65
|
+
implementMs: 1800000,
|
|
66
|
+
mergeMs: 600000,
|
|
67
|
+
},
|
|
68
|
+
analyzeRepoTimeouts: {
|
|
69
|
+
analyzeMs: 300000,
|
|
70
|
+
},
|
|
71
|
+
},
|
|
72
|
+
},
|
|
73
|
+
shepHome: '/home/user/.shep',
|
|
74
|
+
dbFileSize: '2.4 MB',
|
|
75
|
+
},
|
|
76
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export interface TimeoutSliderProps {
|
|
2
|
+
id: string;
|
|
3
|
+
testId: string;
|
|
4
|
+
/** Current value in seconds (as a string for form compatibility) */
|
|
5
|
+
value: string;
|
|
6
|
+
onChange: (value: string) => void;
|
|
7
|
+
onBlur: () => void;
|
|
8
|
+
defaultSeconds?: number;
|
|
9
|
+
}
|
|
10
|
+
export declare function TimeoutSlider({ id, testId, value, onChange, onBlur, defaultSeconds, }: TimeoutSliderProps): import("react/jsx-runtime").JSX.Element;
|
|
11
|
+
//# sourceMappingURL=timeout-slider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"timeout-slider.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/settings/timeout-slider.tsx"],"names":[],"mappings":"AAwCA,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,oEAAoE;IACpE,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAWD,wBAAgB,aAAa,CAAC,EAC5B,EAAE,EACF,MAAM,EACN,KAAK,EACL,QAAQ,EACR,MAAM,EACN,cAAqB,GACtB,EAAE,kBAAkB,2CAyCpB"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useState, useCallback } from 'react';
|
|
4
|
+
import { Slider } from '../../ui/slider.js';
|
|
5
|
+
/** Fixed duration presets in seconds — slider snaps to these values */
|
|
6
|
+
const PRESETS = [
|
|
7
|
+
60, // 1m
|
|
8
|
+
120, // 2m
|
|
9
|
+
300, // 5m
|
|
10
|
+
600, // 10m
|
|
11
|
+
900, // 15m
|
|
12
|
+
1800, // 30m
|
|
13
|
+
2700, // 45m
|
|
14
|
+
3600, // 1h
|
|
15
|
+
7200, // 2h
|
|
16
|
+
10800, // 3h
|
|
17
|
+
14400, // 4h
|
|
18
|
+
21600, // 6h
|
|
19
|
+
28800, // 8h
|
|
20
|
+
43200, // 12h
|
|
21
|
+
86400, // 24h
|
|
22
|
+
];
|
|
23
|
+
const SLIDER_MAX = PRESETS.length - 1;
|
|
24
|
+
/** Find the closest preset index for a given seconds value */
|
|
25
|
+
function secondsToIndex(seconds) {
|
|
26
|
+
let closest = 0;
|
|
27
|
+
let minDiff = Math.abs(seconds - PRESETS[0]);
|
|
28
|
+
for (let i = 1; i < PRESETS.length; i++) {
|
|
29
|
+
const diff = Math.abs(seconds - PRESETS[i]);
|
|
30
|
+
if (diff < minDiff) {
|
|
31
|
+
minDiff = diff;
|
|
32
|
+
closest = i;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return closest;
|
|
36
|
+
}
|
|
37
|
+
function formatDuration(totalSeconds) {
|
|
38
|
+
const hours = Math.floor(totalSeconds / 3600);
|
|
39
|
+
const minutes = Math.round((totalSeconds % 3600) / 60);
|
|
40
|
+
if (hours === 0)
|
|
41
|
+
return `${minutes}m`;
|
|
42
|
+
if (minutes === 0)
|
|
43
|
+
return `${hours}h`;
|
|
44
|
+
return `${hours}h ${minutes}m`;
|
|
45
|
+
}
|
|
46
|
+
export function TimeoutSlider({ id, testId, value, onChange, onBlur, defaultSeconds = 1800, }) {
|
|
47
|
+
const numValue = value === '' ? defaultSeconds : parseInt(value, 10);
|
|
48
|
+
const seconds = numValue || defaultSeconds;
|
|
49
|
+
// Local index state prevents snap-back during drag — updates immediately
|
|
50
|
+
// without waiting for the parent to re-render with the new value.
|
|
51
|
+
const [localIndex, setLocalIndex] = useState(() => secondsToIndex(seconds));
|
|
52
|
+
// Sync from props only when the resolved index actually differs
|
|
53
|
+
// (e.g. external reset or server push). Avoids overwriting during drag.
|
|
54
|
+
const propsIndex = secondsToIndex(seconds);
|
|
55
|
+
if (propsIndex !== localIndex && PRESETS[localIndex] !== seconds) {
|
|
56
|
+
setLocalIndex(propsIndex);
|
|
57
|
+
}
|
|
58
|
+
const handleChange = useCallback(([i]) => {
|
|
59
|
+
setLocalIndex(i);
|
|
60
|
+
onChange(String(PRESETS[i]));
|
|
61
|
+
}, [onChange]);
|
|
62
|
+
return (_jsxs("div", { className: "flex w-55 items-center gap-2", children: [_jsx(Slider, { id: id, "data-testid": testId, min: 0, max: SLIDER_MAX, step: 1, value: [localIndex], onValueChange: handleChange, onValueCommit: () => onBlur(), className: "min-w-0 flex-1" }), _jsx("span", { className: "text-muted-foreground shrink-0 text-right text-xs tabular-nums", children: formatDuration(PRESETS[localIndex]) })] }));
|
|
63
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
2
|
+
import { TimeoutSlider } from './timeout-slider.js';
|
|
3
|
+
declare const meta: Meta<typeof TimeoutSlider>;
|
|
4
|
+
export default meta;
|
|
5
|
+
type Story = StoryObj<typeof TimeoutSlider>;
|
|
6
|
+
export declare const Default: Story;
|
|
7
|
+
export declare const ShortTimeout: Story;
|
|
8
|
+
export declare const LongTimeout: Story;
|
|
9
|
+
export declare const AllStages: Story;
|
|
10
|
+
//# sourceMappingURL=timeout-slider.stories.d.ts.map
|
package/dist/src/presentation/web/components/features/settings/timeout-slider.stories.d.ts.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"timeout-slider.stories.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/settings/timeout-slider.stories.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEjD,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,OAAO,aAAa,CAGpC,CAAC;AAEF,eAAe,IAAI,CAAC;AACpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,aAAa,CAAC,CAAC;AA6B5C,eAAO,MAAM,OAAO,EAAE,KAErB,CAAC;AAEF,eAAO,MAAM,YAAY,EAAE,KAE1B,CAAC;AAEF,eAAO,MAAM,WAAW,EAAE,KAEzB,CAAC;AAEF,eAAO,MAAM,SAAS,EAAE,KAWvB,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useState } from 'react';
|
|
3
|
+
import { TimeoutSlider } from './timeout-slider.js';
|
|
4
|
+
const meta = {
|
|
5
|
+
title: 'Features/Settings/TimeoutSlider',
|
|
6
|
+
component: TimeoutSlider,
|
|
7
|
+
};
|
|
8
|
+
export default meta;
|
|
9
|
+
function TimeoutSliderDemo({ label = 'Analyze', defaultSeconds = 1800, }) {
|
|
10
|
+
const [value, setValue] = useState(String(defaultSeconds));
|
|
11
|
+
return (_jsx("div", { style: { maxWidth: 500 }, children: _jsxs("div", { style: { display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 16 }, children: [_jsx("span", { style: { fontSize: 14 }, children: label }), _jsx(TimeoutSlider, { id: "demo-slider", testId: "demo-slider-input", value: value, onChange: setValue, onBlur: () => undefined, defaultSeconds: defaultSeconds })] }) }));
|
|
12
|
+
}
|
|
13
|
+
export const Default = {
|
|
14
|
+
render: () => _jsx(TimeoutSliderDemo, {}),
|
|
15
|
+
};
|
|
16
|
+
export const ShortTimeout = {
|
|
17
|
+
render: () => _jsx(TimeoutSliderDemo, { label: "Analyze Repo", defaultSeconds: 600 }),
|
|
18
|
+
};
|
|
19
|
+
export const LongTimeout = {
|
|
20
|
+
render: () => _jsx(TimeoutSliderDemo, { label: "Implement", defaultSeconds: 5400 }),
|
|
21
|
+
};
|
|
22
|
+
export const AllStages = {
|
|
23
|
+
render: () => (_jsxs("div", { style: { maxWidth: 500, display: 'flex', flexDirection: 'column', gap: 16 }, children: [_jsx(TimeoutSliderDemo, { label: "Analyze", defaultSeconds: 1800 }), _jsx(TimeoutSliderDemo, { label: "Requirements", defaultSeconds: 1800 }), _jsx(TimeoutSliderDemo, { label: "Research", defaultSeconds: 1800 }), _jsx(TimeoutSliderDemo, { label: "Plan", defaultSeconds: 1800 }), _jsx(TimeoutSliderDemo, { label: "Implement", defaultSeconds: 1800 }), _jsx(TimeoutSliderDemo, { label: "Merge", defaultSeconds: 1800 })] })),
|
|
24
|
+
};
|
package/dist/src/presentation/web/components/features/settings/workflow-settings-section.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workflow-settings-section.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/settings/workflow-settings-section.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"workflow-settings-section.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/settings/workflow-settings-section.tsx"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sCAAsC,CAAC;AAE3E,MAAM,WAAW,4BAA4B;IAC3C,QAAQ,EAAE,cAAc,CAAC;CAC1B;AAED,wBAAgB,uBAAuB,CAAC,EAAE,QAAQ,EAAE,EAAE,4BAA4B,2CA0ajF"}
|
|
@@ -9,6 +9,7 @@ import { Input } from '../../ui/input.js';
|
|
|
9
9
|
import { Switch } from '../../ui/switch.js';
|
|
10
10
|
import { Separator } from '../../ui/separator.js';
|
|
11
11
|
import { updateSettingsAction } from '../../../app/actions/update-settings.js';
|
|
12
|
+
import { TimeoutSlider } from '../../features/settings/timeout-slider.js';
|
|
12
13
|
export function WorkflowSettingsSection({ workflow }) {
|
|
13
14
|
const [openPr, setOpenPr] = useState(workflow.openPrOnImplementationComplete);
|
|
14
15
|
const [pushOnComplete, setPushOnComplete] = useState(workflow.approvalGateDefaults.pushOnImplementationComplete);
|
|
@@ -18,6 +19,18 @@ export function WorkflowSettingsSection({ workflow }) {
|
|
|
18
19
|
const [ciMaxFix, setCiMaxFix] = useState(workflow.ciMaxFixAttempts != null ? String(workflow.ciMaxFixAttempts) : '');
|
|
19
20
|
const [ciTimeout, setCiTimeout] = useState(workflow.ciWatchTimeoutMs != null ? String(Math.round(workflow.ciWatchTimeoutMs / 1000)) : '');
|
|
20
21
|
const [ciLogMax, setCiLogMax] = useState(workflow.ciLogMaxChars != null ? String(workflow.ciLogMaxChars) : '');
|
|
22
|
+
// Per-stage timeout states (seconds for display)
|
|
23
|
+
// Defaults: feature agent stages = 1_800_000 ms (1800s), analyze-repo = 600_000 ms (600s)
|
|
24
|
+
const st = workflow.stageTimeouts;
|
|
25
|
+
const [analyzeTimeout, setAnalyzeTimeout] = useState(String(Math.round((st?.analyzeMs ?? 1_800_000) / 1000)));
|
|
26
|
+
const [requirementsTimeout, setRequirementsTimeout] = useState(String(Math.round((st?.requirementsMs ?? 1_800_000) / 1000)));
|
|
27
|
+
const [researchTimeout, setResearchTimeout] = useState(String(Math.round((st?.researchMs ?? 1_800_000) / 1000)));
|
|
28
|
+
const [planTimeout, setPlanTimeout] = useState(String(Math.round((st?.planMs ?? 1_800_000) / 1000)));
|
|
29
|
+
const [implementTimeout, setImplementTimeout] = useState(String(Math.round((st?.implementMs ?? 1_800_000) / 1000)));
|
|
30
|
+
const [mergeTimeout, setMergeTimeout] = useState(String(Math.round((st?.mergeMs ?? 1_800_000) / 1000)));
|
|
31
|
+
// Analyze-repo agent timeout state
|
|
32
|
+
const art = workflow.analyzeRepoTimeouts;
|
|
33
|
+
const [analyzeRepoTimeout, setAnalyzeRepoTimeout] = useState(String(Math.round((art?.analyzeMs ?? 600_000) / 1000)));
|
|
21
34
|
const [isPending, startTransition] = useTransition();
|
|
22
35
|
const [showSaved, setShowSaved] = useState(false);
|
|
23
36
|
const prevPendingRef = useRef(false);
|
|
@@ -35,6 +48,10 @@ export function WorkflowSettingsSection({ workflow }) {
|
|
|
35
48
|
const n = parseInt(value, 10);
|
|
36
49
|
return Number.isNaN(n) || n <= 0 ? undefined : n;
|
|
37
50
|
}
|
|
51
|
+
function secondsToMs(val) {
|
|
52
|
+
const n = parseOptionalInt(val);
|
|
53
|
+
return n != null ? n * 1000 : undefined;
|
|
54
|
+
}
|
|
38
55
|
function buildPayload(overrides = {}) {
|
|
39
56
|
const timeoutSeconds = parseOptionalInt(overrides.ciTimeout ?? ciTimeout);
|
|
40
57
|
return {
|
|
@@ -49,6 +66,17 @@ export function WorkflowSettingsSection({ workflow }) {
|
|
|
49
66
|
ciMaxFixAttempts: parseOptionalInt(overrides.ciMaxFix ?? ciMaxFix),
|
|
50
67
|
ciWatchTimeoutMs: timeoutSeconds != null ? timeoutSeconds * 1000 : undefined,
|
|
51
68
|
ciLogMaxChars: parseOptionalInt(overrides.ciLogMax ?? ciLogMax),
|
|
69
|
+
stageTimeouts: {
|
|
70
|
+
analyzeMs: secondsToMs(overrides.analyzeTimeout ?? analyzeTimeout),
|
|
71
|
+
requirementsMs: secondsToMs(overrides.requirementsTimeout ?? requirementsTimeout),
|
|
72
|
+
researchMs: secondsToMs(overrides.researchTimeout ?? researchTimeout),
|
|
73
|
+
planMs: secondsToMs(overrides.planTimeout ?? planTimeout),
|
|
74
|
+
implementMs: secondsToMs(overrides.implementTimeout ?? implementTimeout),
|
|
75
|
+
mergeMs: secondsToMs(overrides.mergeTimeout ?? mergeTimeout),
|
|
76
|
+
},
|
|
77
|
+
analyzeRepoTimeouts: {
|
|
78
|
+
analyzeMs: secondsToMs(overrides.analyzeRepoTimeout ?? analyzeRepoTimeout),
|
|
79
|
+
},
|
|
52
80
|
},
|
|
53
81
|
};
|
|
54
82
|
}
|
|
@@ -64,7 +92,7 @@ export function WorkflowSettingsSection({ workflow }) {
|
|
|
64
92
|
setter(value);
|
|
65
93
|
save({ [key]: value });
|
|
66
94
|
}
|
|
67
|
-
function
|
|
95
|
+
function handleFieldBlur(key, currentValue, originalValue) {
|
|
68
96
|
if (currentValue !== originalValue) {
|
|
69
97
|
save({ [key]: currentValue });
|
|
70
98
|
}
|
|
@@ -72,5 +100,72 @@ export function WorkflowSettingsSection({ workflow }) {
|
|
|
72
100
|
const originalCiMaxFix = workflow.ciMaxFixAttempts != null ? String(workflow.ciMaxFixAttempts) : '';
|
|
73
101
|
const originalCiTimeout = workflow.ciWatchTimeoutMs != null ? String(Math.round(workflow.ciWatchTimeoutMs / 1000)) : '';
|
|
74
102
|
const originalCiLogMax = workflow.ciLogMaxChars != null ? String(workflow.ciLogMaxChars) : '';
|
|
75
|
-
|
|
103
|
+
const originalAnalyzeTimeout = st?.analyzeMs != null ? String(Math.round(st.analyzeMs / 1000)) : '';
|
|
104
|
+
const originalRequirementsTimeout = st?.requirementsMs != null ? String(Math.round(st.requirementsMs / 1000)) : '';
|
|
105
|
+
const originalResearchTimeout = st?.researchMs != null ? String(Math.round(st.researchMs / 1000)) : '';
|
|
106
|
+
const originalPlanTimeout = st?.planMs != null ? String(Math.round(st.planMs / 1000)) : '';
|
|
107
|
+
const originalImplementTimeout = st?.implementMs != null ? String(Math.round(st.implementMs / 1000)) : '';
|
|
108
|
+
const originalMergeTimeout = st?.mergeMs != null ? String(Math.round(st.mergeMs / 1000)) : '';
|
|
109
|
+
const originalAnalyzeRepoTimeout = art?.analyzeMs != null ? String(Math.round(art.analyzeMs / 1000)) : '';
|
|
110
|
+
const FEATURE_AGENT_FIELDS = [
|
|
111
|
+
{
|
|
112
|
+
key: 'analyzeTimeout',
|
|
113
|
+
label: 'Analyze',
|
|
114
|
+
defaultSeconds: 1800,
|
|
115
|
+
state: analyzeTimeout,
|
|
116
|
+
setter: setAnalyzeTimeout,
|
|
117
|
+
original: originalAnalyzeTimeout,
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
key: 'requirementsTimeout',
|
|
121
|
+
label: 'Requirements',
|
|
122
|
+
defaultSeconds: 1800,
|
|
123
|
+
state: requirementsTimeout,
|
|
124
|
+
setter: setRequirementsTimeout,
|
|
125
|
+
original: originalRequirementsTimeout,
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
key: 'researchTimeout',
|
|
129
|
+
label: 'Research',
|
|
130
|
+
defaultSeconds: 1800,
|
|
131
|
+
state: researchTimeout,
|
|
132
|
+
setter: setResearchTimeout,
|
|
133
|
+
original: originalResearchTimeout,
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
key: 'planTimeout',
|
|
137
|
+
label: 'Plan',
|
|
138
|
+
defaultSeconds: 1800,
|
|
139
|
+
state: planTimeout,
|
|
140
|
+
setter: setPlanTimeout,
|
|
141
|
+
original: originalPlanTimeout,
|
|
142
|
+
},
|
|
143
|
+
{
|
|
144
|
+
key: 'implementTimeout',
|
|
145
|
+
label: 'Implement',
|
|
146
|
+
defaultSeconds: 1800,
|
|
147
|
+
state: implementTimeout,
|
|
148
|
+
setter: setImplementTimeout,
|
|
149
|
+
original: originalImplementTimeout,
|
|
150
|
+
},
|
|
151
|
+
{
|
|
152
|
+
key: 'mergeTimeout',
|
|
153
|
+
label: 'Merge',
|
|
154
|
+
defaultSeconds: 1800,
|
|
155
|
+
state: mergeTimeout,
|
|
156
|
+
setter: setMergeTimeout,
|
|
157
|
+
original: originalMergeTimeout,
|
|
158
|
+
},
|
|
159
|
+
];
|
|
160
|
+
const ANALYZE_REPO_FIELDS = [
|
|
161
|
+
{
|
|
162
|
+
key: 'analyzeRepoTimeout',
|
|
163
|
+
label: 'Analyze',
|
|
164
|
+
defaultSeconds: 600,
|
|
165
|
+
state: analyzeRepoTimeout,
|
|
166
|
+
setter: setAnalyzeRepoTimeout,
|
|
167
|
+
original: originalAnalyzeRepoTimeout,
|
|
168
|
+
},
|
|
169
|
+
];
|
|
170
|
+
return (_jsxs(Card, { id: "workflow", className: "scroll-mt-6", "data-testid": "workflow-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(GitBranch, { className: "text-muted-foreground h-4 w-4" }), _jsx(CardTitle, { children: "Workflow" })] }), 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 PR behavior, approval gates, and CI settings" })] }), _jsxs(CardContent, { className: "space-y-4", children: [_jsxs("div", { className: "space-y-3", children: [_jsxs("div", { className: "flex items-center justify-between gap-4", children: [_jsxs("div", { className: "space-y-0.5", children: [_jsx(Label, { htmlFor: "open-pr", children: "Open PR on implementation complete" }), _jsx("p", { className: "text-muted-foreground text-xs", children: "Automatically create a pull request when the agent finishes" })] }), _jsx(Switch, { id: "open-pr", "data-testid": "switch-open-pr", checked: openPr, onCheckedChange: (v) => handleSwitchChange('openPr', setOpenPr, v) })] }), _jsxs("div", { className: "flex items-center justify-between gap-4", children: [_jsxs("div", { className: "space-y-0.5", children: [_jsx(Label, { htmlFor: "push-on-complete", children: "Push on implementation complete" }), _jsx("p", { className: "text-muted-foreground text-xs", children: "Push the branch to remote when implementation is done" })] }), _jsx(Switch, { id: "push-on-complete", "data-testid": "switch-push-on-complete", checked: pushOnComplete, onCheckedChange: (v) => handleSwitchChange('pushOnComplete', setPushOnComplete, v) })] })] }), _jsx(Separator, {}), _jsxs("div", { className: "space-y-3", children: [_jsx("h3", { className: "text-sm font-semibold", children: "Approval Gates" }), _jsxs("div", { className: "flex items-center justify-between gap-4", children: [_jsxs("div", { className: "space-y-0.5", children: [_jsx(Label, { htmlFor: "allow-prd", children: "PRD auto-approval" }), _jsx("p", { className: "text-muted-foreground text-xs", children: "Skip manual approval for product requirement documents" })] }), _jsx(Switch, { id: "allow-prd", "data-testid": "switch-allow-prd", checked: allowPrd, onCheckedChange: (v) => handleSwitchChange('allowPrd', setAllowPrd, v) })] }), _jsxs("div", { className: "flex items-center justify-between gap-4", children: [_jsxs("div", { className: "space-y-0.5", children: [_jsx(Label, { htmlFor: "allow-plan", children: "Plan auto-approval" }), _jsx("p", { className: "text-muted-foreground text-xs", children: "Skip manual approval for implementation plans" })] }), _jsx(Switch, { id: "allow-plan", "data-testid": "switch-allow-plan", checked: allowPlan, onCheckedChange: (v) => handleSwitchChange('allowPlan', setAllowPlan, v) })] }), _jsxs("div", { className: "flex items-center justify-between gap-4", children: [_jsxs("div", { className: "space-y-0.5", children: [_jsx(Label, { htmlFor: "allow-merge", children: "Merge auto-approval" }), _jsx("p", { className: "text-muted-foreground text-xs", children: "Skip manual approval for PR merges" })] }), _jsx(Switch, { id: "allow-merge", "data-testid": "switch-allow-merge", checked: allowMerge, onCheckedChange: (v) => handleSwitchChange('allowMerge', setAllowMerge, v) })] })] }), _jsx(Separator, {}), _jsxs("div", { className: "space-y-3", children: [_jsx("h3", { className: "text-sm font-semibold", children: "CI Settings" }), _jsxs("div", { className: "space-y-1.5", children: [_jsx(Label, { htmlFor: "ci-max-fix", children: "Max fix attempts" }), _jsx(Input, { id: "ci-max-fix", "data-testid": "ci-max-fix-input", type: "text", inputMode: "numeric", pattern: "[0-9]*", min: 1, max: 10, placeholder: "e.g., 3", value: ciMaxFix, onChange: (e) => setCiMaxFix(e.target.value), onBlur: () => handleFieldBlur('ciMaxFix', ciMaxFix, originalCiMaxFix) }), _jsx("p", { className: "text-muted-foreground text-xs", children: "How many times the agent retries fixing CI failures" })] }), _jsxs("div", { className: "space-y-1.5", children: [_jsx(Label, { htmlFor: "ci-timeout", children: "Watch timeout (seconds)" }), _jsx(Input, { id: "ci-timeout", "data-testid": "ci-timeout-input", type: "text", inputMode: "numeric", pattern: "[0-9]*", placeholder: "e.g., 300", value: ciTimeout, onChange: (e) => setCiTimeout(e.target.value), onBlur: () => handleFieldBlur('ciTimeout', ciTimeout, originalCiTimeout) }), _jsx("p", { className: "text-muted-foreground text-xs", children: "How long to wait for CI to complete before timing out" })] }), _jsxs("div", { className: "space-y-1.5", children: [_jsx(Label, { htmlFor: "ci-log-max", children: "Max log characters" }), _jsx(Input, { id: "ci-log-max", "data-testid": "ci-log-max-input", type: "text", inputMode: "numeric", pattern: "[0-9]*", placeholder: "e.g., 50000", value: ciLogMax, onChange: (e) => setCiLogMax(e.target.value), onBlur: () => handleFieldBlur('ciLogMax', ciLogMax, originalCiLogMax) }), _jsx("p", { className: "text-muted-foreground text-xs", children: "Maximum characters to capture from CI logs" })] })] }), _jsx(Separator, {}), _jsxs("div", { className: "space-y-3", children: [_jsx("h3", { className: "text-sm font-semibold", children: "Stage Timeouts" }), _jsx("p", { className: "text-muted-foreground text-xs", children: "Maximum execution time per agent stage" }), _jsx("h4", { className: "text-muted-foreground text-xs font-semibold tracking-wider uppercase", children: "Feature Agent" }), FEATURE_AGENT_FIELDS.map((field) => (_jsxs("div", { className: "flex items-center justify-between gap-4", children: [_jsx(Label, { htmlFor: `stage-timeout-${field.key}`, children: field.label }), _jsx(TimeoutSlider, { id: `stage-timeout-${field.key}`, testId: `stage-timeout-${field.key}-input`, value: field.state, onChange: field.setter, onBlur: () => handleFieldBlur(field.key, field.state, field.original), defaultSeconds: field.defaultSeconds })] }, field.key))), _jsx("h4", { className: "text-muted-foreground pt-2 text-xs font-semibold tracking-wider uppercase", children: "Analyze Repository Agent" }), ANALYZE_REPO_FIELDS.map((field) => (_jsxs("div", { className: "flex items-center justify-between gap-4", children: [_jsx(Label, { htmlFor: `stage-timeout-${field.key}`, children: field.label }), _jsx(TimeoutSlider, { id: `stage-timeout-${field.key}`, testId: `stage-timeout-${field.key}-input`, value: field.state, onChange: field.setter, onBlur: () => handleFieldBlur(field.key, field.state, field.original), defaultSeconds: field.defaultSeconds })] }, field.key)))] })] })] }));
|
|
76
171
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workflow-settings-section.stories.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/settings/workflow-settings-section.stories.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAQ,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAE,uBAAuB,EAAE,MAAM,6BAA6B,CAAC;AAEtE,QAAA,MAAM,IAAI;;;;;;;CAOsC,CAAC;AAEjD,eAAe,IAAI,CAAC;AACpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,IAAI,CAAC,CAAC;AAEnC,eAAO,MAAM,OAAO,EAAE,KAcrB,CAAC;AAEF,eAAO,MAAM,UAAU,EAAE,
|
|
1
|
+
{"version":3,"file":"workflow-settings-section.stories.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/settings/workflow-settings-section.stories.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAQ,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAE,uBAAuB,EAAE,MAAM,6BAA6B,CAAC;AAEtE,QAAA,MAAM,IAAI;;;;;;;CAOsC,CAAC;AAEjD,eAAe,IAAI,CAAC;AACpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,IAAI,CAAC,CAAC;AAEnC,eAAO,MAAM,OAAO,EAAE,KAcrB,CAAC;AAEF,eAAO,MAAM,UAAU,EAAE,KA4BxB,CAAC;AAEF,eAAO,MAAM,cAAc,EAAE,KA4B5B,CAAC"}
|
package/dist/src/presentation/web/components/features/settings/workflow-settings-section.stories.js
CHANGED
|
@@ -36,6 +36,17 @@ export const AllEnabled = {
|
|
|
36
36
|
ciMaxFixAttempts: 3,
|
|
37
37
|
ciWatchTimeoutMs: 300000,
|
|
38
38
|
ciLogMaxChars: 50000,
|
|
39
|
+
stageTimeouts: {
|
|
40
|
+
analyzeMs: 600000,
|
|
41
|
+
requirementsMs: 600000,
|
|
42
|
+
researchMs: 600000,
|
|
43
|
+
planMs: 600000,
|
|
44
|
+
implementMs: 600000,
|
|
45
|
+
mergeMs: 600000,
|
|
46
|
+
},
|
|
47
|
+
analyzeRepoTimeouts: {
|
|
48
|
+
analyzeMs: 600000,
|
|
49
|
+
},
|
|
39
50
|
enableEvidence: true,
|
|
40
51
|
commitEvidence: true,
|
|
41
52
|
},
|
|
@@ -54,6 +65,17 @@ export const WithCiSettings = {
|
|
|
54
65
|
ciMaxFixAttempts: 5,
|
|
55
66
|
ciWatchTimeoutMs: 600000,
|
|
56
67
|
ciLogMaxChars: 100000,
|
|
68
|
+
stageTimeouts: {
|
|
69
|
+
analyzeMs: 1200000,
|
|
70
|
+
requirementsMs: 1200000,
|
|
71
|
+
researchMs: 1200000,
|
|
72
|
+
planMs: 1200000,
|
|
73
|
+
implementMs: 1200000,
|
|
74
|
+
mergeMs: 1200000,
|
|
75
|
+
},
|
|
76
|
+
analyzeRepoTimeouts: {
|
|
77
|
+
analyzeMs: 1200000,
|
|
78
|
+
},
|
|
57
79
|
enableEvidence: false,
|
|
58
80
|
commitEvidence: false,
|
|
59
81
|
},
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { Slider as SliderPrimitive } from 'radix-ui';
|
|
3
|
+
declare function Slider({ className, defaultValue, value, min, max, ...props }: React.ComponentProps<typeof SliderPrimitive.Root>): import("react/jsx-runtime").JSX.Element;
|
|
4
|
+
export { Slider };
|
|
5
|
+
//# sourceMappingURL=slider.d.ts.map
|