@shepai/cli 1.121.0-pr360.3389500 → 1.121.0-pr375.8009cc7
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/use-cases/features/resume-feature.use-case.d.ts +3 -1
- package/dist/packages/core/src/application/use-cases/features/resume-feature.use-case.d.ts.map +1 -1
- package/dist/packages/core/src/application/use-cases/features/resume-feature.use-case.js +4 -2
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/fast-implement.node.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/fast-implement.node.js +34 -1
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/prompts/fast-implement.prompt.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/prompts/fast-implement.prompt.js +4 -1
- package/dist/packages/core/src/infrastructure/services/tool-installer/tool-installer.service.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/services/tool-installer/tool-installer.service.js +3 -10
- package/dist/packages/core/src/infrastructure/services/tool-installer/tools/claude-code.json +4 -9
- package/dist/src/presentation/cli/commands/install.command.js +1 -8
- package/dist/src/presentation/tui/prompts/prd-review-question.prompt.d.ts +1 -1
- package/dist/src/presentation/tui/prompts/prd-review-question.prompt.d.ts.map +1 -1
- package/dist/src/presentation/tui/prompts/prd-review-question.prompt.js +5 -2
- package/dist/src/presentation/tui/wizards/prd-review.wizard.d.ts.map +1 -1
- package/dist/src/presentation/tui/wizards/prd-review.wizard.js +4 -2
- package/dist/src/presentation/web/app/(dashboard)/get-graph-data.d.ts.map +1 -1
- package/dist/src/presentation/web/app/(dashboard)/get-graph-data.js +2 -43
- package/dist/src/presentation/web/app/actions/approve-feature.d.ts.map +1 -1
- package/dist/src/presentation/web/app/actions/approve-feature.js +9 -0
- package/dist/src/presentation/web/app/actions/check-agent-auth.d.ts +0 -2
- package/dist/src/presentation/web/app/actions/check-agent-auth.d.ts.map +1 -1
- package/dist/src/presentation/web/app/actions/check-agent-auth.js +1 -8
- package/dist/src/presentation/web/app/actions/reject-feature.d.ts.map +1 -1
- package/dist/src/presentation/web/app/actions/reject-feature.js +9 -0
- package/dist/src/presentation/web/app/api/npm-version/route.d.ts.map +1 -1
- package/dist/src/presentation/web/app/api/npm-version/route.js +9 -1
- package/dist/src/presentation/web/app/api/sessions/route.d.ts.map +1 -1
- package/dist/src/presentation/web/app/api/sessions/route.js +43 -10
- package/dist/src/presentation/web/components/common/prd-questionnaire/prd-questionnaire.js +1 -1
- package/dist/src/presentation/web/components/features/control-center/control-center-empty-state.js +1 -1
- package/dist/src/presentation/web/components/features/tools/tool-card.stories.js +1 -1
- package/dist/src/presentation/web/components/features/tools/tools-page-client.stories.js +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +3 -5
- package/web/.next/BUILD_ID +1 -1
- package/web/.next/build-manifest.json +2 -2
- package/web/.next/fallback-build-manifest.json +2 -2
- package/web/.next/prerender-manifest.json +3 -3
- package/web/.next/required-server-files.js +1 -1
- package/web/.next/required-server-files.json +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/create/page/server-reference-manifest.json +22 -22
- package/web/.next/server/app/(dashboard)/@drawer/create/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/create/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page/server-reference-manifest.json +28 -28
- package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page.js +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page/server-reference-manifest.json +28 -28
- package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page.js +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page/server-reference-manifest.json +20 -20
- package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/create/page/server-reference-manifest.json +22 -22
- package/web/.next/server/app/(dashboard)/create/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/create/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page/server-reference-manifest.json +28 -28
- package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page.js +1 -1
- package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/feature/[featureId]/page/server-reference-manifest.json +28 -28
- package/web/.next/server/app/(dashboard)/feature/[featureId]/page.js +1 -1
- package/web/.next/server/app/(dashboard)/feature/[featureId]/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/feature/[featureId]/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/page/server-reference-manifest.json +20 -20
- package/web/.next/server/app/(dashboard)/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page/server-reference-manifest.json +20 -20
- package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/_global-error.html +2 -2
- package/web/.next/server/app/_global-error.rsc +1 -1
- package/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
- package/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/web/.next/server/app/_not-found/page/server-reference-manifest.json +1 -1
- package/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/api/sessions/route.js +1 -1
- package/web/.next/server/app/api/sessions/route.js.nft.json +1 -1
- package/web/.next/server/app/settings/page/server-reference-manifest.json +6 -6
- package/web/.next/server/app/settings/page.js.nft.json +1 -1
- package/web/.next/server/app/settings/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/skills/page/server-reference-manifest.json +6 -6
- package/web/.next/server/app/skills/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/tools/page/server-reference-manifest.json +6 -6
- package/web/.next/server/app/tools/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/version/page/server-reference-manifest.json +1 -1
- package/web/.next/server/app/version/page_client-reference-manifest.js +1 -1
- package/web/.next/server/chunks/403f9_next_dist_esm_build_templates_app-route_370c43b1.js +1 -1
- package/web/.next/server/chunks/403f9_next_dist_esm_build_templates_app-route_370c43b1.js.map +1 -1
- package/web/.next/server/chunks/[externals]_node:fs_ddf6f167._.js +3 -0
- package/web/.next/server/chunks/[externals]_node:fs_ddf6f167._.js.map +1 -0
- package/web/.next/server/chunks/[root-of-the-server]__3b72e8b0._.js +1 -1
- package/web/.next/server/chunks/[root-of-the-server]__3b72e8b0._.js.map +1 -1
- package/web/.next/server/chunks/[root-of-the-server]__42b7ab55._.js +1 -1
- package/web/.next/server/chunks/[root-of-the-server]__42b7ab55._.js.map +1 -1
- package/web/.next/server/chunks/[root-of-the-server]__a402b567._.js +1 -1
- package/web/.next/server/chunks/[root-of-the-server]__a62bd945._.js +3 -0
- package/web/.next/server/chunks/[root-of-the-server]__a62bd945._.js.map +1 -0
- 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_f30d0343.js +1 -1
- package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_@drawer_repository_[repositoryId]_page_actions_f30d0343.js.map +1 -1
- package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_repository_[repositoryId]_page_actions_9f1775bb.js +1 -1
- package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_repository_[repositoryId]_page_actions_9f1775bb.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__06fef644._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__2698e9f4._.js +3 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__2698e9f4._.js.map +1 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__545792ab._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__545792ab._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__6b17a22d._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__6b17a22d._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__6bb00d90._.js +2 -2
- package/web/.next/server/chunks/ssr/[root-of-the-server]__6bb00d90._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__804c006d._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__804c006d._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__8c553503._.js +2 -2
- package/web/.next/server/chunks/ssr/[root-of-the-server]__8e3bf5d7._.js +3 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__8e3bf5d7._.js.map +1 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__a022445f._.js +2 -2
- package/web/.next/server/chunks/ssr/[root-of-the-server]__a022445f._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__a7de2711._.js +2 -2
- package/web/.next/server/chunks/ssr/[root-of-the-server]__a7de2711._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__b724df9e._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__b724df9e._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__c07f9f79._.js +3 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__c07f9f79._.js.map +1 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__c605a375._.js +3 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__c605a375._.js.map +1 -0
- package/web/.next/server/chunks/ssr/_0dc2cfd3._.js +1 -1
- package/web/.next/server/chunks/ssr/_0dc2cfd3._.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/_2f6f48b8._.js +1 -1
- package/web/.next/server/chunks/ssr/_2f6f48b8._.js.map +1 -1
- package/web/.next/server/chunks/ssr/{_c9f9f066._.js → _53db828c._.js} +2 -2
- package/web/.next/server/chunks/ssr/{_c9f9f066._.js.map → _53db828c._.js.map} +1 -1
- package/web/.next/server/chunks/ssr/{_6adcca26._.js → _5764932e._.js} +2 -2
- package/web/.next/server/chunks/ssr/{_6adcca26._.js.map → _5764932e._.js.map} +1 -1
- package/web/.next/server/chunks/ssr/_cc77a143._.js +1 -1
- package/web/.next/server/chunks/ssr/_cc77a143._.js.map +1 -1
- package/web/.next/server/chunks/ssr/_d8fc93b2._.js +3 -0
- package/web/.next/server/chunks/ssr/{_01430df5._.js.map → _d8fc93b2._.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_5f039db1._.js +2 -2
- package/web/.next/server/chunks/ssr/src_presentation_web_5f039db1._.js.map +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_2a52b697.js +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_2a52b697.js.map +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_skills_page_actions_1fa8042e.js +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_skills_page_actions_1fa8042e.js.map +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_tools_page_actions_24684200.js +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_tools_page_actions_24684200.js.map +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_c4337169._.js +2 -2
- package/web/.next/server/chunks/ssr/src_presentation_web_c4337169._.js.map +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_ca99d62d._.js +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_ca99d62d._.js.map +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_components_bf50c527._.js +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_components_de814675._.js +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_components_features_control-center_7ac3562e._.js +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_components_features_control-center_7ac3562e._.js.map +1 -1
- package/web/.next/server/pages/500.html +2 -2
- package/web/.next/server/server-reference-manifest.js +1 -1
- package/web/.next/server/server-reference-manifest.json +34 -34
- package/web/.next/static/chunks/{e250fec851ac30f4.js → 0ddd3c5bdd31b657.js} +1 -1
- package/web/.next/static/chunks/163d6a459fbd4ca9.js +2 -0
- package/web/.next/static/chunks/{2c20b129a22101a7.js → 26f004e398a1cc47.js} +1 -1
- package/web/.next/static/chunks/{93c52fba27d59310.js → 44ab35cce93382c6.js} +1 -1
- package/web/.next/static/chunks/8648eef2b88ba722.js +1 -0
- package/web/.next/static/chunks/{5fe1cadeac80c82e.js → aa40e7080c580de0.js} +1 -1
- package/web/.next/static/chunks/{02d522e9112607a4.js → b8ad0dc86c98f19b.js} +1 -1
- package/web/.next/static/chunks/{c7501007ee7add77.js → c7de66a0adceba46.js} +1 -1
- package/web/.next/static/chunks/{394b72591bf6c3f9.js → e4c5025d3927266a.js} +1 -1
- package/web/.next/static/chunks/{180163cc1930dbd8.js → f6fdcb68b8db7962.js} +1 -1
- package/web/.next/server/chunks/[root-of-the-server]__0fe7788d._.js +0 -3
- package/web/.next/server/chunks/[root-of-the-server]__0fe7788d._.js.map +0 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__0424e9ef._.js +0 -3
- package/web/.next/server/chunks/ssr/[root-of-the-server]__0424e9ef._.js.map +0 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__580db3b8._.js +0 -3
- package/web/.next/server/chunks/ssr/[root-of-the-server]__580db3b8._.js.map +0 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__5d1a30fb._.js +0 -3
- package/web/.next/server/chunks/ssr/[root-of-the-server]__5d1a30fb._.js.map +0 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__7e95570f._.js +0 -3
- package/web/.next/server/chunks/ssr/[root-of-the-server]__7e95570f._.js.map +0 -1
- package/web/.next/server/chunks/ssr/_01430df5._.js +0 -3
- package/web/.next/static/chunks/08622689d65b4d39.js +0 -1
- package/web/.next/static/chunks/84ab8af59015ca72.js +0 -2
- /package/web/.next/static/{mBZK7AokkzzKYpu3ySb2v → evj2MTyodPYvffFcGF31H}/_buildManifest.js +0 -0
- /package/web/.next/static/{mBZK7AokkzzKYpu3ySb2v → evj2MTyodPYvffFcGF31H}/_clientMiddlewareManifest.json +0 -0
- /package/web/.next/static/{mBZK7AokkzzKYpu3ySb2v → evj2MTyodPYvffFcGF31H}/_ssgManifest.js +0 -0
|
@@ -19,6 +19,8 @@ export declare class ResumeFeatureUseCase {
|
|
|
19
19
|
private readonly processService;
|
|
20
20
|
private readonly worktreeService;
|
|
21
21
|
constructor(featureRepo: IFeatureRepository, runRepo: IAgentRunRepository, processService: IFeatureAgentProcessService, worktreeService: IWorktreeService);
|
|
22
|
-
execute(featureId: string
|
|
22
|
+
execute(featureId: string, options?: {
|
|
23
|
+
promptPrefix?: string;
|
|
24
|
+
}): Promise<ResumeFeatureResult>;
|
|
23
25
|
}
|
|
24
26
|
//# sourceMappingURL=resume-feature.use-case.d.ts.map
|
package/dist/packages/core/src/application/use-cases/features/resume-feature.use-case.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resume-feature.use-case.d.ts","sourceRoot":"","sources":["../../../../../../../packages/core/src/application/use-cases/features/resume-feature.use-case.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,qCAAqC,CAAC;AAE7E,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,iEAAiE,CAAC;AAC1G,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,6DAA6D,CAAC;AACvG,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,8DAA8D,CAAC;AAChH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,2DAA2D,CAAC;AAQlG,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,QAAQ,CAAC;CAClB;AAED,qBACa,oBAAoB;IAG7B,OAAO,CAAC,QAAQ,CAAC,WAAW;IAE5B,OAAO,CAAC,QAAQ,CAAC,OAAO;IAExB,OAAO,CAAC,QAAQ,CAAC,cAAc;IAE/B,OAAO,CAAC,QAAQ,CAAC,eAAe;gBANf,WAAW,EAAE,kBAAkB,EAE/B,OAAO,EAAE,mBAAmB,EAE5B,cAAc,EAAE,2BAA2B,EAE3C,eAAe,EAAE,gBAAgB;IAG9C,OAAO,
|
|
1
|
+
{"version":3,"file":"resume-feature.use-case.d.ts","sourceRoot":"","sources":["../../../../../../../packages/core/src/application/use-cases/features/resume-feature.use-case.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,qCAAqC,CAAC;AAE7E,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,iEAAiE,CAAC;AAC1G,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,6DAA6D,CAAC;AACvG,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,8DAA8D,CAAC;AAChH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,2DAA2D,CAAC;AAQlG,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,QAAQ,CAAC;CAClB;AAED,qBACa,oBAAoB;IAG7B,OAAO,CAAC,QAAQ,CAAC,WAAW;IAE5B,OAAO,CAAC,QAAQ,CAAC,OAAO;IAExB,OAAO,CAAC,QAAQ,CAAC,cAAc;IAE/B,OAAO,CAAC,QAAQ,CAAC,eAAe;gBANf,WAAW,EAAE,kBAAkB,EAE/B,OAAO,EAAE,mBAAmB,EAE5B,cAAc,EAAE,2BAA2B,EAE3C,eAAe,EAAE,gBAAgB;IAG9C,OAAO,CACX,SAAS,EAAE,MAAM,EACjB,OAAO,CAAC,EAAE;QAAE,YAAY,CAAC,EAAE,MAAM,CAAA;KAAE,GAClC,OAAO,CAAC,mBAAmB,CAAC;CAuGhC"}
|
|
@@ -35,7 +35,7 @@ let ResumeFeatureUseCase = class ResumeFeatureUseCase {
|
|
|
35
35
|
this.processService = processService;
|
|
36
36
|
this.worktreeService = worktreeService;
|
|
37
37
|
}
|
|
38
|
-
async execute(featureId) {
|
|
38
|
+
async execute(featureId, options) {
|
|
39
39
|
// Resolve feature by exact ID or prefix
|
|
40
40
|
const feature = (await this.featureRepo.findById(featureId)) ??
|
|
41
41
|
(await this.featureRepo.findByIdPrefix(featureId));
|
|
@@ -79,7 +79,9 @@ let ResumeFeatureUseCase = class ResumeFeatureUseCase {
|
|
|
79
79
|
agentType: lastRun.agentType,
|
|
80
80
|
agentName: lastRun.agentName,
|
|
81
81
|
status: AgentRunStatus.pending,
|
|
82
|
-
prompt:
|
|
82
|
+
prompt: options?.promptPrefix
|
|
83
|
+
? `${options.promptPrefix}\n\n${lastRun.prompt}`
|
|
84
|
+
: lastRun.prompt,
|
|
83
85
|
threadId: lastRun.threadId, // Same thread for checkpoint continuity
|
|
84
86
|
featureId: feature.id,
|
|
85
87
|
repositoryPath: feature.repositoryPath,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fast-implement.node.d.ts","sourceRoot":"","sources":["../../../../../../../../../packages/core/src/infrastructure/services/agents/feature-agent/nodes/fast-implement.node.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;
|
|
1
|
+
{"version":3,"file":"fast-implement.node.d.ts","sourceRoot":"","sources":["../../../../../../../../../packages/core/src/infrastructure/services/agents/feature-agent/nodes/fast-implement.node.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAMH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,+DAA+D,CAAC;AAEpG,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAgBrD;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,cAAc,IAGhD,OAAO,iBAAiB,KAAG,OAAO,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC,CA0E7E"}
|
|
@@ -9,10 +9,11 @@
|
|
|
9
9
|
* Follows the same factory pattern as other nodes: takes executor
|
|
10
10
|
* dependency, returns async (state) => Partial<FeatureAgentState>.
|
|
11
11
|
*/
|
|
12
|
+
import { execSync } from 'node:child_process';
|
|
12
13
|
import { mkdirSync, writeFileSync } from 'node:fs';
|
|
13
14
|
import { join, dirname } from 'node:path';
|
|
14
15
|
import { isGraphBubbleUp } from '@langchain/langgraph';
|
|
15
|
-
import { createNodeLogger, buildExecutorOptions, retryExecute } from './node-helpers.js';
|
|
16
|
+
import { createNodeLogger, buildExecutorOptions, retryExecute, getCompletedPhases, markPhaseComplete, } from './node-helpers.js';
|
|
16
17
|
import { reportNodeStart } from '../heartbeat.js';
|
|
17
18
|
import { recordPhaseStart, recordPhaseEnd } from '../phase-timing-context.js';
|
|
18
19
|
import { updateNodeLifecycle } from '../lifecycle-context.js';
|
|
@@ -33,6 +34,16 @@ export function createFastImplementNode(executor) {
|
|
|
33
34
|
log.info('Starting fast implementation');
|
|
34
35
|
reportNodeStart('fast-implement');
|
|
35
36
|
await updateNodeLifecycle('fast-implement');
|
|
37
|
+
// Skip if already completed (resume from error path)
|
|
38
|
+
const completedPhases = getCompletedPhases(state.specDir);
|
|
39
|
+
if (completedPhases.includes('fast-implement')) {
|
|
40
|
+
log.info('Phase already completed, skipping execution');
|
|
41
|
+
return {
|
|
42
|
+
currentNode: 'fast-implement',
|
|
43
|
+
messages: ['[fast-implement] already completed — skipping'],
|
|
44
|
+
_needsReexecution: false,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
36
47
|
const startTime = Date.now();
|
|
37
48
|
const timingId = await recordPhaseStart('fast-implement');
|
|
38
49
|
try {
|
|
@@ -44,6 +55,11 @@ export function createFastImplementNode(executor) {
|
|
|
44
55
|
const durationMs = Date.now() - startTime;
|
|
45
56
|
const elapsed = (durationMs / 1000).toFixed(1);
|
|
46
57
|
log.info(`Complete (${result.result.length} chars, ${elapsed}s)`);
|
|
58
|
+
// Validate that the executor actually produced file changes
|
|
59
|
+
const cwd = state.worktreePath || state.repositoryPath;
|
|
60
|
+
if (!hasWorktreeChanges(cwd)) {
|
|
61
|
+
throw new Error('[fast-implement] Agent produced no file changes — it may have entered plan mode or asked questions instead of implementing. Retrying.');
|
|
62
|
+
}
|
|
47
63
|
// --- Evidence sub-agent: capture proof of completion (settings-gated) ---
|
|
48
64
|
const evidenceEnabled = hasSettings() && getSettings().workflow.enableEvidence;
|
|
49
65
|
const evidence = evidenceEnabled ? await collectEvidence(executor, state, log) : [];
|
|
@@ -51,6 +67,8 @@ export function createFastImplementNode(executor) {
|
|
|
51
67
|
log.info('Evidence collection disabled via settings — skipping');
|
|
52
68
|
}
|
|
53
69
|
await recordPhaseEnd(timingId, durationMs);
|
|
70
|
+
// Mark phase complete so resume from error skips re-execution
|
|
71
|
+
markPhaseComplete(state.specDir, 'fast-implement', log);
|
|
54
72
|
return {
|
|
55
73
|
currentNode: 'fast-implement',
|
|
56
74
|
evidence,
|
|
@@ -107,6 +125,21 @@ async function collectEvidence(executor, state, log) {
|
|
|
107
125
|
return [];
|
|
108
126
|
}
|
|
109
127
|
}
|
|
128
|
+
/**
|
|
129
|
+
* Check whether the worktree has any uncommitted changes (new, modified, or deleted files).
|
|
130
|
+
* Uses `git status --porcelain` which outputs one line per changed file, or empty if clean.
|
|
131
|
+
* Returns false if the git command fails (e.g. not a git repo).
|
|
132
|
+
*/
|
|
133
|
+
function hasWorktreeChanges(cwd) {
|
|
134
|
+
try {
|
|
135
|
+
const output = execSync('git status --porcelain', { cwd, encoding: 'utf-8' });
|
|
136
|
+
return output.trim().length > 0;
|
|
137
|
+
}
|
|
138
|
+
catch {
|
|
139
|
+
// If git command fails, assume no changes (conservative — will trigger the error)
|
|
140
|
+
return false;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
110
143
|
/**
|
|
111
144
|
* Save evidence manifest to the shep home evidence folder so the
|
|
112
145
|
* merge review UI can read it without accessing graph state.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fast-implement.prompt.d.ts","sourceRoot":"","sources":["../../../../../../../../../../packages/core/src/infrastructure/services/agents/feature-agent/nodes/prompts/fast-implement.prompt.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAMH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAwIxD;;;;;;;;;;;GAWG;AACH,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,iBAAiB,GAAG,MAAM,
|
|
1
|
+
{"version":3,"file":"fast-implement.prompt.d.ts","sourceRoot":"","sources":["../../../../../../../../../../packages/core/src/infrastructure/services/agents/feature-agent/nodes/prompts/fast-implement.prompt.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAMH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAwIxD;;;;;;;;;;;GAWG;AACH,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,iBAAiB,GAAG,MAAM,CAuEzE"}
|
|
@@ -211,6 +211,9 @@ ${dirListing}
|
|
|
211
211
|
- Follow existing codebase conventions and patterns
|
|
212
212
|
- Do NOT commit, push, or create pull requests
|
|
213
213
|
- Do NOT modify any spec YAML files
|
|
214
|
-
- Keep changes focused and minimal
|
|
214
|
+
- Keep changes focused and minimal
|
|
215
|
+
- Do NOT enter plan mode — implement directly without planning phases
|
|
216
|
+
- Do NOT ask the user questions or use AskUserQuestion — make reasonable decisions and proceed
|
|
217
|
+
- You MUST create or modify actual code files — a plan or summary alone is not acceptable output`);
|
|
215
218
|
return sections.join('\n\n');
|
|
216
219
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tool-installer.service.d.ts","sourceRoot":"","sources":["../../../../../../../packages/core/src/infrastructure/services/tool-installer/tool-installer.service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAKH,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,sEAAsE,CAAC;AAClH,OAAO,KAAK,EACV,sBAAsB,EACtB,kBAAkB,EAEnB,MAAM,qCAAqC,CAAC;AA2B7C,qBACa,wBAAyB,YAAW,qBAAqB;IACpE;;;OAGG;IACG,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,sBAAsB,CAAC;IAoC1E;;;OAGG;IACH,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,kBAAkB,GAAG,IAAI;IAqB9D;;;OAGG;IACG,cAAc,CAClB,QAAQ,EAAE,MAAM,EAChB,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,GAChC,OAAO,CAAC,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"tool-installer.service.d.ts","sourceRoot":"","sources":["../../../../../../../packages/core/src/infrastructure/services/tool-installer/tool-installer.service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAKH,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,sEAAsE,CAAC;AAClH,OAAO,KAAK,EACV,sBAAsB,EACtB,kBAAkB,EAEnB,MAAM,qCAAqC,CAAC;AA2B7C,qBACa,wBAAyB,YAAW,qBAAqB;IACpE;;;OAGG;IACG,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,sBAAsB,CAAC;IAoC1E;;;OAGG;IACH,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,kBAAkB,GAAG,IAAI;IAqB9D;;;OAGG;IACG,cAAc,CAClB,QAAQ,EAAE,MAAM,EAChB,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,GAChC,OAAO,CAAC,sBAAsB,CAAC;IAgFlC;;OAEG;IACH,OAAO,CAAC,6BAA6B;CA4BtC"}
|
package/dist/packages/core/src/infrastructure/services/tool-installer/tool-installer.service.js
CHANGED
|
@@ -107,14 +107,9 @@ let ToolInstallerServiceImpl = class ToolInstallerServiceImpl {
|
|
|
107
107
|
}
|
|
108
108
|
return new Promise((resolve) => {
|
|
109
109
|
let output = '';
|
|
110
|
-
// Inherit stdin when running in an interactive terminal so that commands
|
|
111
|
-
// requiring sudo can prompt the user for a password. In non-interactive
|
|
112
|
-
// contexts (web UI, CI) stdin is piped and closed immediately to prevent
|
|
113
|
-
// the process from hanging waiting for input.
|
|
114
|
-
const isInteractive = process.stdin.isTTY === true;
|
|
115
110
|
const child = spawn(installCommand.command, [], {
|
|
116
111
|
shell: true,
|
|
117
|
-
stdio: [
|
|
112
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
118
113
|
env: {
|
|
119
114
|
...process.env,
|
|
120
115
|
DEBIAN_FRONTEND: 'noninteractive',
|
|
@@ -122,10 +117,8 @@ let ToolInstallerServiceImpl = class ToolInstallerServiceImpl {
|
|
|
122
117
|
GPG_TTY: '',
|
|
123
118
|
},
|
|
124
119
|
});
|
|
125
|
-
// Close stdin
|
|
126
|
-
|
|
127
|
-
child.stdin?.end();
|
|
128
|
-
}
|
|
120
|
+
// Close stdin immediately to prevent interactive prompts
|
|
121
|
+
child.stdin?.end();
|
|
129
122
|
// Stream output from stdout and stderr
|
|
130
123
|
const pipeOutput = (stream) => {
|
|
131
124
|
if (!stream)
|
package/dist/packages/core/src/infrastructure/services/tool-installer/tools/claude-code.json
CHANGED
|
@@ -12,17 +12,13 @@
|
|
|
12
12
|
"commands": {
|
|
13
13
|
"linux": "curl -fsSL https://claude.ai/install.sh | bash",
|
|
14
14
|
"darwin": "curl -fsSL https://claude.ai/install.sh | bash",
|
|
15
|
-
"win32": "
|
|
15
|
+
"win32": "npm install -g @anthropic-ai/claude-code"
|
|
16
16
|
},
|
|
17
17
|
"timeout": 300000,
|
|
18
|
-
"documentationUrl": "https://
|
|
18
|
+
"documentationUrl": "https://code.claude.com/docs/en/overview",
|
|
19
19
|
"verifyCommand": "claude --version",
|
|
20
20
|
"autoInstall": true,
|
|
21
|
-
"openDirectory": {
|
|
22
|
-
"linux": "cd {dir} && exec claude",
|
|
23
|
-
"darwin": "cd {dir} && exec claude",
|
|
24
|
-
"win32": "cd /d {dir} && claude"
|
|
25
|
-
},
|
|
21
|
+
"openDirectory": "cd {dir} && exec claude",
|
|
26
22
|
"spawnOptions": {
|
|
27
23
|
"shell": true,
|
|
28
24
|
"stdio": "inherit",
|
|
@@ -30,7 +26,6 @@
|
|
|
30
26
|
},
|
|
31
27
|
"terminalCommand": {
|
|
32
28
|
"linux": "x-terminal-emulator -e bash -c 'cd {dir} && exec claude'",
|
|
33
|
-
"darwin": "
|
|
34
|
-
"win32": "start cmd /k \"cd /d {dir} && claude\""
|
|
29
|
+
"darwin": "open -a Terminal.app bash -c 'cd {dir} && exec claude'"
|
|
35
30
|
}
|
|
36
31
|
}
|
|
@@ -117,14 +117,7 @@ function printInstallInstructions(metadata) {
|
|
|
117
117
|
// Print open directory command if available
|
|
118
118
|
if (metadata.openDirectory) {
|
|
119
119
|
console.log(fmt.heading('Open Directory'));
|
|
120
|
-
|
|
121
|
-
console.log(`${colors.muted('$')} ${metadata.openDirectory}`);
|
|
122
|
-
}
|
|
123
|
-
else {
|
|
124
|
-
for (const [platform, cmd] of Object.entries(metadata.openDirectory)) {
|
|
125
|
-
console.log(`${colors.muted(`[${platform}]`)} ${cmd}`);
|
|
126
|
-
}
|
|
127
|
-
}
|
|
120
|
+
console.log(`${colors.muted('$')} ${metadata.openDirectory}`);
|
|
128
121
|
console.log();
|
|
129
122
|
}
|
|
130
123
|
// Print documentation link
|
|
@@ -8,7 +8,7 @@ import type { QuestionOption } from '../../../../packages/core/src/domain/genera
|
|
|
8
8
|
/**
|
|
9
9
|
* Creates the @inquirer/select configuration for a single open question.
|
|
10
10
|
*/
|
|
11
|
-
export declare function createQuestionSelectConfig(question: string, options: QuestionOption[], currentAnswer?: string): {
|
|
11
|
+
export declare function createQuestionSelectConfig(question: string, options: QuestionOption[], currentAnswer?: string, questionNumber?: number, totalQuestions?: number): {
|
|
12
12
|
message: string;
|
|
13
13
|
choices: {
|
|
14
14
|
name: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prd-review-question.prompt.d.ts","sourceRoot":"","sources":["../../../../../src/presentation/tui/prompts/prd-review-question.prompt.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAEnE;;GAEG;AACH,wBAAgB,0BAA0B,CACxC,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,cAAc,EAAE,EACzB,aAAa,CAAC,EAAE,MAAM;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"prd-review-question.prompt.d.ts","sourceRoot":"","sources":["../../../../../src/presentation/tui/prompts/prd-review-question.prompt.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAEnE;;GAEG;AACH,wBAAgB,0BAA0B,CACxC,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,cAAc,EAAE,EACzB,aAAa,CAAC,EAAE,MAAM,EACtB,cAAc,CAAC,EAAE,MAAM,EACvB,cAAc,CAAC,EAAE,MAAM;;;;;;;;;;;;;;;;;;EAmBxB"}
|
|
@@ -8,14 +8,17 @@ import { shepTheme } from '../themes/shep.theme.js';
|
|
|
8
8
|
/**
|
|
9
9
|
* Creates the @inquirer/select configuration for a single open question.
|
|
10
10
|
*/
|
|
11
|
-
export function createQuestionSelectConfig(question, options, currentAnswer) {
|
|
11
|
+
export function createQuestionSelectConfig(question, options, currentAnswer, questionNumber, totalQuestions) {
|
|
12
12
|
const choices = options.map((opt) => ({
|
|
13
13
|
name: opt.option,
|
|
14
14
|
value: opt.option,
|
|
15
15
|
description: opt.description,
|
|
16
16
|
}));
|
|
17
|
+
const prefix = questionNumber != null && totalQuestions != null
|
|
18
|
+
? `[${questionNumber}/${totalQuestions}] `
|
|
19
|
+
: '';
|
|
17
20
|
return {
|
|
18
|
-
message: question
|
|
21
|
+
message: `${prefix}${question}`,
|
|
19
22
|
choices,
|
|
20
23
|
default: currentAnswer,
|
|
21
24
|
theme: shepTheme,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prd-review.wizard.d.ts","sourceRoot":"","sources":["../../../../../src/presentation/tui/wizards/prd-review.wizard.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,EAEL,KAAK,YAAY,EAClB,MAAM,yCAAyC,CAAC;AACjD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2DAA2D,CAAC;AAC9F,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;AAG5E,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,YAAY,CAAC;IACrB,iBAAiB,EAAE,uBAAuB,EAAE,CAAC;IAC7C,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;;GAQG;AACH,wBAAsB,eAAe,CAAC,SAAS,EAAE,YAAY,EAAE,GAAG,OAAO,CAAC,qBAAqB,CAAC,
|
|
1
|
+
{"version":3,"file":"prd-review.wizard.d.ts","sourceRoot":"","sources":["../../../../../src/presentation/tui/wizards/prd-review.wizard.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,EAEL,KAAK,YAAY,EAClB,MAAM,yCAAyC,CAAC;AACjD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2DAA2D,CAAC;AAC9F,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;AAG5E,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,YAAY,CAAC;IACrB,iBAAiB,EAAE,uBAAuB,EAAE,CAAC;IAC7C,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;;GAQG;AACH,wBAAsB,eAAe,CAAC,SAAS,EAAE,YAAY,EAAE,GAAG,OAAO,CAAC,qBAAqB,CAAC,CA8B/F"}
|
|
@@ -20,8 +20,10 @@ import { shepTheme } from '../themes/shep.theme.js';
|
|
|
20
20
|
*/
|
|
21
21
|
export async function prdReviewWizard(questions) {
|
|
22
22
|
const changedSelections = [];
|
|
23
|
-
|
|
24
|
-
|
|
23
|
+
const total = questions.length;
|
|
24
|
+
for (let i = 0; i < total; i++) {
|
|
25
|
+
const q = questions[i];
|
|
26
|
+
const selected = await select(createQuestionSelectConfig(q.question, q.options, q.selectedOption, i + 1, total));
|
|
25
27
|
if (selected !== q.selectedOption) {
|
|
26
28
|
changedSelections.push({
|
|
27
29
|
questionId: q.question,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"get-graph-data.d.ts","sourceRoot":"","sources":["../../../../../../src/presentation/web/app/(dashboard)/get-graph-data.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"get-graph-data.d.ts","sourceRoot":"","sources":["../../../../../../src/presentation/web/app/(dashboard)/get-graph-data.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uCAAuC,CAAC;AAE5E,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAE1C,wBAAsB,YAAY,IAAI,OAAO,CAAC;IAAE,KAAK,EAAE,cAAc,EAAE,CAAC;IAAC,KAAK,EAAE,IAAI,EAAE,CAAA;CAAE,CAAC,CA+CxF"}
|
|
@@ -1,55 +1,14 @@
|
|
|
1
1
|
import { resolve } from '../../lib/server-container.js';
|
|
2
|
-
import { CiStatus } from '../../../../../packages/core/src/domain/generated/output.js';
|
|
3
2
|
import { getSettings } from '../../../../../packages/core/src/infrastructure/services/settings.service.js';
|
|
4
3
|
import { layoutWithDagre, CANVAS_LAYOUT_DEFAULTS } from '../../lib/layout-with-dagre.js';
|
|
5
4
|
import { buildGraphNodes } from '../build-graph-nodes.js';
|
|
6
|
-
const CI_STATUS_MAP = {
|
|
7
|
-
success: CiStatus.Success,
|
|
8
|
-
failure: CiStatus.Failure,
|
|
9
|
-
pending: CiStatus.Pending,
|
|
10
|
-
};
|
|
11
5
|
export async function getGraphData() {
|
|
12
6
|
const listFeatures = resolve('ListFeaturesUseCase');
|
|
13
7
|
const listRepos = resolve('ListRepositoriesUseCase');
|
|
14
8
|
const agentRunRepo = resolve('IAgentRunRepository');
|
|
15
|
-
const gitPrService = resolve('IGitPrService');
|
|
16
|
-
const featureRepo = resolve('IFeatureRepository');
|
|
17
9
|
const [features, repositories] = await Promise.all([listFeatures.execute(), listRepos.execute()]);
|
|
18
|
-
//
|
|
19
|
-
//
|
|
20
|
-
await Promise.all(features
|
|
21
|
-
.filter((f) => f.pr?.number)
|
|
22
|
-
.map(async (feature) => {
|
|
23
|
-
try {
|
|
24
|
-
const updates = {};
|
|
25
|
-
// Live mergeable status (only if not yet known)
|
|
26
|
-
if (feature.pr.mergeable === undefined) {
|
|
27
|
-
const mergeable = await gitPrService.getMergeableStatus(feature.repositoryPath, feature.pr.number);
|
|
28
|
-
if (mergeable !== undefined)
|
|
29
|
-
updates.mergeable = mergeable;
|
|
30
|
-
}
|
|
31
|
-
// Live CI status
|
|
32
|
-
if (feature.branch) {
|
|
33
|
-
const ciResult = await gitPrService
|
|
34
|
-
.getCiStatus(feature.repositoryPath, feature.branch)
|
|
35
|
-
.catch(() => undefined);
|
|
36
|
-
if (ciResult) {
|
|
37
|
-
const ciStatus = CI_STATUS_MAP[ciResult.status] ?? CiStatus.Pending;
|
|
38
|
-
if (ciStatus !== feature.pr.ciStatus)
|
|
39
|
-
updates.ciStatus = ciStatus;
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
if (Object.keys(updates).length > 0) {
|
|
43
|
-
feature.pr = { ...feature.pr, ...updates };
|
|
44
|
-
featureRepo.update(feature).catch(() => {
|
|
45
|
-
/* best-effort persist */
|
|
46
|
-
});
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
catch {
|
|
50
|
-
// GitHub fetch failed — use cached value
|
|
51
|
-
}
|
|
52
|
-
}));
|
|
10
|
+
// PR/CI status is kept fresh by PrSyncWatcher (30s background poll).
|
|
11
|
+
// No live GitHub calls here — use cached DB values for fast response.
|
|
53
12
|
const featuresWithRuns = await Promise.all(features.map(async (feature) => {
|
|
54
13
|
const run = feature.agentRunId ? await agentRunRepo.findById(feature.agentRunId) : null;
|
|
55
14
|
return { feature, run };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"approve-feature.d.ts","sourceRoot":"","sources":["../../../../../../src/presentation/web/app/actions/approve-feature.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"approve-feature.d.ts","sourceRoot":"","sources":["../../../../../../src/presentation/web/app/actions/approve-feature.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,sCAAsC,CAAC;AAK/E,wBAAsB,cAAc,CAClC,SAAS,EAAE,MAAM,EACjB,OAAO,CAAC,EAAE,kBAAkB,GAC3B,OAAO,CAAC;IAAE,QAAQ,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAsChD"}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
'use server';
|
|
2
2
|
import { resolve } from '../../lib/server-container.js';
|
|
3
|
+
import { AgentRunStatus } from '../../../../../packages/core/src/domain/generated/output.js';
|
|
4
|
+
const ERROR_STATUSES = new Set([AgentRunStatus.failed, AgentRunStatus.interrupted]);
|
|
3
5
|
export async function approveFeature(featureId, payload) {
|
|
4
6
|
if (!featureId.trim()) {
|
|
5
7
|
return { approved: false, error: 'Feature id is required' };
|
|
@@ -13,6 +15,13 @@ export async function approveFeature(featureId, payload) {
|
|
|
13
15
|
if (!feature.agentRunId) {
|
|
14
16
|
return { approved: false, error: 'Feature has no agent run' };
|
|
15
17
|
}
|
|
18
|
+
const runRepo = resolve('IAgentRunRepository');
|
|
19
|
+
const run = await runRepo.findById(feature.agentRunId);
|
|
20
|
+
if (run && ERROR_STATUSES.has(run.status)) {
|
|
21
|
+
const resumeUseCase = resolve('ResumeFeatureUseCase');
|
|
22
|
+
await resumeUseCase.execute(featureId, { promptPrefix: 'User approved. Please continue.' });
|
|
23
|
+
return { approved: true };
|
|
24
|
+
}
|
|
16
25
|
const approveUseCase = resolve('ApproveAgentRunUseCase');
|
|
17
26
|
const result = await approveUseCase.execute(feature.agentRunId, payload);
|
|
18
27
|
if (!result.approved) {
|
|
@@ -10,8 +10,6 @@ export interface AgentAuthStatus {
|
|
|
10
10
|
binaryName: string | null;
|
|
11
11
|
/** Instructions to authenticate if not authenticated */
|
|
12
12
|
authCommand: string | null;
|
|
13
|
-
/** Platform-resolved install command (e.g. "npm install -g @google/gemini-cli") */
|
|
14
|
-
installCommand: string | null;
|
|
15
13
|
}
|
|
16
14
|
/**
|
|
17
15
|
* Check agent tool installation + auth status.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"check-agent-auth.d.ts","sourceRoot":"","sources":["../../../../../../src/presentation/web/app/actions/check-agent-auth.ts"],"names":[],"mappings":"AAUA,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,+CAA+C;IAC/C,SAAS,EAAE,OAAO,CAAC;IACnB,8CAA8C;IAC9C,aAAa,EAAE,OAAO,CAAC;IACvB,yCAAyC;IACzC,KAAK,EAAE,MAAM,CAAC;IACd,gDAAgD;IAChD,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,wDAAwD;IACxD,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"check-agent-auth.d.ts","sourceRoot":"","sources":["../../../../../../src/presentation/web/app/actions/check-agent-auth.ts"],"names":[],"mappings":"AAUA,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,+CAA+C;IAC/C,SAAS,EAAE,OAAO,CAAC;IACnB,8CAA8C;IAC9C,aAAa,EAAE,OAAO,CAAC;IACvB,yCAAyC;IACzC,KAAK,EAAE,MAAM,CAAC;IACd,gDAAgD;IAChD,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,wDAAwD;IACxD,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AA4FD;;;GAGG;AACH,wBAAsB,cAAc,IAAI,OAAO,CAAC,eAAe,CAAC,CAiF/D"}
|
|
@@ -20,7 +20,7 @@ const AGENT_TOOL_MAP = {
|
|
|
20
20
|
};
|
|
21
21
|
const AGENT_BINARY_MAP = {
|
|
22
22
|
'claude-code': 'claude',
|
|
23
|
-
cursor: '
|
|
23
|
+
cursor: 'agent',
|
|
24
24
|
'gemini-cli': 'gemini',
|
|
25
25
|
};
|
|
26
26
|
/**
|
|
@@ -113,7 +113,6 @@ export async function checkAgentAuth() {
|
|
|
113
113
|
label: 'Unknown',
|
|
114
114
|
binaryName: null,
|
|
115
115
|
authCommand: null,
|
|
116
|
-
installCommand: null,
|
|
117
116
|
};
|
|
118
117
|
}
|
|
119
118
|
const label = AGENT_LABELS[agentType] ?? agentType;
|
|
@@ -128,18 +127,15 @@ export async function checkAgentAuth() {
|
|
|
128
127
|
label,
|
|
129
128
|
binaryName: null,
|
|
130
129
|
authCommand: null,
|
|
131
|
-
installCommand: null,
|
|
132
130
|
};
|
|
133
131
|
}
|
|
134
132
|
// Check if tool is installed
|
|
135
133
|
let installed = false;
|
|
136
|
-
let installCommand = null;
|
|
137
134
|
try {
|
|
138
135
|
const useCase = resolve('ListToolsUseCase');
|
|
139
136
|
const tools = await useCase.execute();
|
|
140
137
|
const tool = tools.find((t) => t.id === toolId);
|
|
141
138
|
installed = tool?.status.status === 'available';
|
|
142
|
-
installCommand = tool?.installCommand ?? null;
|
|
143
139
|
}
|
|
144
140
|
catch {
|
|
145
141
|
installed = false;
|
|
@@ -152,7 +148,6 @@ export async function checkAgentAuth() {
|
|
|
152
148
|
label,
|
|
153
149
|
binaryName,
|
|
154
150
|
authCommand: binaryName ? `Install ${label} first` : null,
|
|
155
|
-
installCommand,
|
|
156
151
|
};
|
|
157
152
|
}
|
|
158
153
|
// Tier 1: instant file/env check
|
|
@@ -165,7 +160,6 @@ export async function checkAgentAuth() {
|
|
|
165
160
|
label,
|
|
166
161
|
binaryName,
|
|
167
162
|
authCommand: binaryName,
|
|
168
|
-
installCommand,
|
|
169
163
|
};
|
|
170
164
|
}
|
|
171
165
|
// Tier 2: subprocess verify (best effort, ~200ms)
|
|
@@ -180,6 +174,5 @@ export async function checkAgentAuth() {
|
|
|
180
174
|
label,
|
|
181
175
|
binaryName,
|
|
182
176
|
authCommand: authenticated ? null : binaryName,
|
|
183
|
-
installCommand,
|
|
184
177
|
};
|
|
185
178
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reject-feature.d.ts","sourceRoot":"","sources":["../../../../../../src/presentation/web/app/actions/reject-feature.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"reject-feature.d.ts","sourceRoot":"","sources":["../../../../../../src/presentation/web/app/actions/reject-feature.ts"],"names":[],"mappings":"AAWA,wBAAsB,aAAa,CACjC,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,EAChB,WAAW,CAAC,EAAE,MAAM,EAAE,GACrB,OAAO,CAAC;IACT,QAAQ,EAAE,OAAO,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC,CA8CD"}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
'use server';
|
|
2
2
|
import { resolve } from '../../lib/server-container.js';
|
|
3
|
+
import { AgentRunStatus } from '../../../../../packages/core/src/domain/generated/output.js';
|
|
4
|
+
const ERROR_STATUSES = new Set([AgentRunStatus.failed, AgentRunStatus.interrupted]);
|
|
3
5
|
export async function rejectFeature(featureId, feedback, attachments) {
|
|
4
6
|
if (!featureId.trim()) {
|
|
5
7
|
return { rejected: false, error: 'Feature id is required' };
|
|
@@ -16,6 +18,13 @@ export async function rejectFeature(featureId, feedback, attachments) {
|
|
|
16
18
|
if (!feature.agentRunId) {
|
|
17
19
|
return { rejected: false, error: 'Feature has no agent run' };
|
|
18
20
|
}
|
|
21
|
+
const runRepo = resolve('IAgentRunRepository');
|
|
22
|
+
const run = await runRepo.findById(feature.agentRunId);
|
|
23
|
+
if (run && ERROR_STATUSES.has(run.status)) {
|
|
24
|
+
const resumeUseCase = resolve('ResumeFeatureUseCase');
|
|
25
|
+
await resumeUseCase.execute(featureId, { promptPrefix: feedback });
|
|
26
|
+
return { rejected: true, iteration: 1 };
|
|
27
|
+
}
|
|
19
28
|
const rejectUseCase = resolve('RejectAgentRunUseCase');
|
|
20
29
|
const result = await rejectUseCase.execute(feature.agentRunId, feedback, attachments);
|
|
21
30
|
if (!result.rejected) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/app/api/npm-version/route.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/app/api/npm-version/route.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAK3C,wBAAsB,GAAG,IAAI,OAAO,CAAC,YAAY,CAAC,CAsBjD"}
|
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
import { NextResponse } from 'next/server';
|
|
2
|
+
const CACHE_TTL_MS = 5 * 60_000; // 5 minutes
|
|
3
|
+
let cachedVersion = null;
|
|
2
4
|
export async function GET() {
|
|
5
|
+
// Return cached value if fresh
|
|
6
|
+
if (cachedVersion && Date.now() - cachedVersion.fetchedAt < CACHE_TTL_MS) {
|
|
7
|
+
return NextResponse.json({ latest: cachedVersion.latest });
|
|
8
|
+
}
|
|
3
9
|
const packageName = '@shepai/cli';
|
|
4
10
|
try {
|
|
5
11
|
const res = await fetch(`https://registry.npmjs.org/${packageName}/latest`, {
|
|
@@ -9,7 +15,9 @@ export async function GET() {
|
|
|
9
15
|
return NextResponse.json({ error: `npm registry returned ${res.status}` }, { status: 502 });
|
|
10
16
|
}
|
|
11
17
|
const data = (await res.json());
|
|
12
|
-
|
|
18
|
+
const latest = data.version ?? null;
|
|
19
|
+
cachedVersion = { latest, fetchedAt: Date.now() };
|
|
20
|
+
return NextResponse.json({ latest });
|
|
13
21
|
}
|
|
14
22
|
catch (error) {
|
|
15
23
|
const message = error instanceof Error ? error.message : 'Failed to check npm version';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/app/api/sessions/route.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAK3C,eAAO,MAAM,OAAO,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/app/api/sessions/route.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAK3C,eAAO,MAAM,OAAO,kBAAkB,CAAC;AAgTvC;;;;;GAKG;AACH,wBAAsB,GAAG,CAAC,OAAO,EAAE,OAAO;;;;YAnTpC,MAAM;mBACC,MAAM;iBACR,MAAM,GAAG,IAAI;sBACR,MAAM;wBACJ,MAAM,GAAG,IAAI;uBACd,MAAM,GAAG,IAAI;mBACjB,MAAM,GAAG,IAAI;qBACX,MAAM;kBACT,MAAM;;IAwUjB"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { NextResponse } from 'next/server';
|
|
2
2
|
import { homedir } from 'node:os';
|
|
3
3
|
import { join } from 'node:path';
|
|
4
|
-
import { readdir, stat
|
|
4
|
+
import { readdir, stat } from 'node:fs/promises';
|
|
5
5
|
export const dynamic = 'force-dynamic';
|
|
6
6
|
// ── Path encoding helpers ─────────────────────────────────────────────
|
|
7
7
|
/**
|
|
@@ -49,14 +49,32 @@ async function scanClaudeSessions(repositoryPath, limit) {
|
|
|
49
49
|
.map((r) => r.value)
|
|
50
50
|
.filter((s) => s !== null);
|
|
51
51
|
}
|
|
52
|
+
/**
|
|
53
|
+
* Read the first N bytes of a file to extract preview and timestamps
|
|
54
|
+
* without loading the entire (potentially multi-MB) session file.
|
|
55
|
+
*/
|
|
56
|
+
const PREVIEW_READ_BYTES = 8_192; // 8KB is enough for first few messages
|
|
52
57
|
async function parseClaudeSession(filePath, fileName, mtime, repositoryPath) {
|
|
53
|
-
const
|
|
54
|
-
const lines = content.split('\n').filter((l) => l.trim());
|
|
58
|
+
const { createReadStream } = await import('node:fs');
|
|
55
59
|
const id = fileName.replace('.jsonl', '');
|
|
60
|
+
// Read only the first chunk to extract preview and first timestamp
|
|
56
61
|
let preview = null;
|
|
57
|
-
let messageCount = 0;
|
|
58
62
|
let firstTimestamp = null;
|
|
59
|
-
let
|
|
63
|
+
let messageCount = 0;
|
|
64
|
+
const head = await new Promise((resolve) => {
|
|
65
|
+
const chunks = [];
|
|
66
|
+
let size = 0;
|
|
67
|
+
const stream = createReadStream(filePath, { end: PREVIEW_READ_BYTES - 1 });
|
|
68
|
+
stream.on('data', (chunk) => {
|
|
69
|
+
chunks.push(chunk);
|
|
70
|
+
size += chunk.length;
|
|
71
|
+
});
|
|
72
|
+
stream.on('end', () => resolve(Buffer.concat(chunks, size).toString('utf-8')));
|
|
73
|
+
stream.on('error', () => resolve(''));
|
|
74
|
+
});
|
|
75
|
+
if (!head)
|
|
76
|
+
return null;
|
|
77
|
+
const lines = head.split('\n').filter((l) => l.trim());
|
|
60
78
|
for (const line of lines) {
|
|
61
79
|
try {
|
|
62
80
|
const entry = JSON.parse(line);
|
|
@@ -66,7 +84,6 @@ async function parseClaudeSession(filePath, fileName, mtime, repositoryPath) {
|
|
|
66
84
|
messageCount++;
|
|
67
85
|
if (entry.timestamp) {
|
|
68
86
|
firstTimestamp ??= entry.timestamp;
|
|
69
|
-
lastTimestamp = entry.timestamp;
|
|
70
87
|
}
|
|
71
88
|
if (role === 'user' && preview === null) {
|
|
72
89
|
preview = extractText(entry.message?.content);
|
|
@@ -80,14 +97,16 @@ async function parseClaudeSession(filePath, fileName, mtime, repositoryPath) {
|
|
|
80
97
|
}
|
|
81
98
|
if (messageCount === 0)
|
|
82
99
|
return null;
|
|
100
|
+
// Use mtime as lastMessageAt — avoids reading entire file for last line
|
|
101
|
+
const mtimeIso = new Date(mtime).toISOString();
|
|
83
102
|
return {
|
|
84
103
|
id,
|
|
85
104
|
agentType: 'claude-code',
|
|
86
105
|
preview,
|
|
87
106
|
messageCount,
|
|
88
107
|
firstMessageAt: firstTimestamp,
|
|
89
|
-
lastMessageAt:
|
|
90
|
-
createdAt: firstTimestamp ??
|
|
108
|
+
lastMessageAt: mtimeIso,
|
|
109
|
+
createdAt: firstTimestamp ?? mtimeIso,
|
|
91
110
|
projectPath: repositoryPath,
|
|
92
111
|
filePath,
|
|
93
112
|
_mtime: mtime,
|
|
@@ -144,11 +163,25 @@ async function scanCursorSessions(repositoryPath, limit) {
|
|
|
144
163
|
.filter((s) => s !== null);
|
|
145
164
|
}
|
|
146
165
|
async function parseCursorSession(filePath, fileName, mtime, repositoryPath) {
|
|
147
|
-
const
|
|
148
|
-
const lines = content.split('\n').filter((l) => l.trim());
|
|
166
|
+
const { createReadStream } = await import('node:fs');
|
|
149
167
|
const id = fileName.replace('.jsonl', '');
|
|
168
|
+
// Read only the first chunk for preview extraction
|
|
169
|
+
const head = await new Promise((resolve) => {
|
|
170
|
+
const chunks = [];
|
|
171
|
+
let size = 0;
|
|
172
|
+
const stream = createReadStream(filePath, { end: PREVIEW_READ_BYTES - 1 });
|
|
173
|
+
stream.on('data', (chunk) => {
|
|
174
|
+
chunks.push(chunk);
|
|
175
|
+
size += chunk.length;
|
|
176
|
+
});
|
|
177
|
+
stream.on('end', () => resolve(Buffer.concat(chunks, size).toString('utf-8')));
|
|
178
|
+
stream.on('error', () => resolve(''));
|
|
179
|
+
});
|
|
180
|
+
if (!head)
|
|
181
|
+
return null;
|
|
150
182
|
let preview = null;
|
|
151
183
|
let messageCount = 0;
|
|
184
|
+
const lines = head.split('\n').filter((l) => l.trim());
|
|
152
185
|
for (const line of lines) {
|
|
153
186
|
try {
|
|
154
187
|
const entry = JSON.parse(line);
|
|
@@ -27,7 +27,7 @@ export function PrdQuestionnaire({ data, selections, onSelect, onApprove, onReje
|
|
|
27
27
|
}, [onSelect, isLastStep, selectSound]);
|
|
28
28
|
if (total === 0)
|
|
29
29
|
return null;
|
|
30
|
-
return (_jsxs("div", { className: "flex min-h-0 flex-1 flex-col", children: [_jsxs("div", { className: "flex-1 space-y-4 overflow-y-auto p-4", children: [showHeader ? (_jsxs("div", { className: "border-border flex items-start gap-3 border-b pb-3", children: [_jsx("div", { className: "mt-1.5 h-2 w-2 shrink-0 rounded-full bg-amber-500" }), _jsxs("div", { className: "flex-1", children: [_jsx("h3", { className: "text-foreground mb-1.5 text-sm font-bold", children: question }), _jsx("p", { className: "text-muted-foreground text-xs leading-relaxed", children: context })] })] })) : null, _jsxs("div", { className: "space-y-3", children: [_jsxs("div", { className: "flex items-start gap-3", children: [
|
|
30
|
+
return (_jsxs("div", { className: "flex min-h-0 flex-1 flex-col", children: [_jsxs("div", { className: "flex-1 space-y-4 overflow-y-auto p-4", children: [showHeader ? (_jsxs("div", { className: "border-border flex items-start gap-3 border-b pb-3", children: [_jsx("div", { className: "mt-1.5 h-2 w-2 shrink-0 rounded-full bg-amber-500" }), _jsxs("div", { className: "flex-1", children: [_jsx("h3", { className: "text-foreground mb-1.5 text-sm font-bold", children: question }), _jsx("p", { className: "text-muted-foreground text-xs leading-relaxed", children: context })] })] })) : null, _jsxs("div", { className: "space-y-3", children: [_jsxs("div", { className: "flex items-start gap-3", children: [_jsxs("label", { className: "text-foreground min-w-0 flex-1 text-sm font-semibold", children: [currentStep + 1, ". ", currentQuestion.question] }), _jsx("div", { className: "mt-1.5 flex shrink-0 gap-1", children: questions.map((q, idx) => (_jsx("button", { type: "button", "aria-label": `Go to question ${idx + 1}`, className: cn('h-1.5 rounded-full transition-all duration-200', idx === currentStep ? 'bg-primary w-4' : 'w-1.5', idx !== currentStep && selections[q.id] ? 'bg-primary/50' : '', idx !== currentStep && !selections[q.id] ? 'bg-muted-foreground/25' : ''), onClick: () => {
|
|
31
31
|
navigateSound.play();
|
|
32
32
|
setCurrentStep(idx);
|
|
33
33
|
} }, q.id))) })] }), _jsx("div", { className: "space-y-2", children: currentQuestion.options.map((opt, optIdx) => {
|