@shepai/cli 1.167.0-pr505.5cf8222 → 1.168.0-pr505.7d2bb14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/packages/core/src/application/ports/output/agents/interactive-agent-executor.interface.d.ts +38 -2
- package/dist/packages/core/src/application/ports/output/agents/interactive-agent-executor.interface.d.ts.map +1 -1
- package/dist/packages/core/src/application/ports/output/services/interactive-session-service.interface.d.ts +16 -1
- package/dist/packages/core/src/application/ports/output/services/interactive-session-service.interface.d.ts.map +1 -1
- package/dist/packages/core/src/application/use-cases/interactive/index.d.ts +2 -0
- package/dist/packages/core/src/application/use-cases/interactive/index.d.ts.map +1 -1
- package/dist/packages/core/src/application/use-cases/interactive/index.js +1 -0
- package/dist/packages/core/src/application/use-cases/interactive/respond-to-interaction.use-case.d.ts +17 -0
- package/dist/packages/core/src/application/use-cases/interactive/respond-to-interaction.use-case.d.ts.map +1 -0
- package/dist/packages/core/src/application/use-cases/interactive/respond-to-interaction.use-case.js +34 -0
- package/dist/packages/core/src/application/use-cases/repositories/delete-repository.use-case.d.ts.map +1 -1
- package/dist/packages/core/src/application/use-cases/repositories/delete-repository.use-case.js +6 -2
- 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/repositories/sqlite-settings.repository.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/repositories/sqlite-settings.repository.js +12 -3
- package/dist/packages/core/src/infrastructure/services/agents/common/executors/claude-code-interactive-executor.service.d.ts +3 -0
- package/dist/packages/core/src/infrastructure/services/agents/common/executors/claude-code-interactive-executor.service.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/services/agents/common/executors/claude-code-interactive-executor.service.js +59 -6
- package/dist/packages/core/src/infrastructure/services/interactive/interactive-session.service.d.ts +7 -0
- package/dist/packages/core/src/infrastructure/services/interactive/interactive-session.service.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/services/interactive/interactive-session.service.js +101 -1
- package/dist/src/presentation/web/app/api/interactive/chat/[featureId]/respond/route.d.ts +19 -0
- package/dist/src/presentation/web/app/api/interactive/chat/[featureId]/respond/route.d.ts.map +1 -0
- package/dist/src/presentation/web/app/api/interactive/chat/[featureId]/respond/route.js +33 -0
- package/dist/src/presentation/web/app/api/interactive/chat/[featureId]/stream/route.d.ts.map +1 -1
- package/dist/src/presentation/web/app/api/interactive/chat/[featureId]/stream/route.js +7 -0
- package/dist/src/presentation/web/app/layout.d.ts +0 -1
- package/dist/src/presentation/web/app/layout.d.ts.map +1 -1
- package/dist/src/presentation/web/app/layout.js +0 -1
- package/dist/src/presentation/web/components/assistant-ui/thread.d.ts +3 -2
- package/dist/src/presentation/web/components/assistant-ui/thread.d.ts.map +1 -1
- package/dist/src/presentation/web/components/assistant-ui/thread.js +26 -3
- package/dist/src/presentation/web/components/common/react-file-manager-dialog/react-file-manager-dialog.d.ts.map +1 -1
- package/dist/src/presentation/web/components/common/react-file-manager-dialog/react-file-manager-dialog.js +68 -56
- package/dist/src/presentation/web/components/features/chat/ChatDotIndicator.d.ts +1 -0
- package/dist/src/presentation/web/components/features/chat/ChatDotIndicator.d.ts.map +1 -1
- package/dist/src/presentation/web/components/features/chat/ChatDotIndicator.js +7 -1
- package/dist/src/presentation/web/components/features/chat/ChatDotIndicator.stories.d.ts +1 -0
- package/dist/src/presentation/web/components/features/chat/ChatDotIndicator.stories.d.ts.map +1 -1
- package/dist/src/presentation/web/components/features/chat/ChatDotIndicator.stories.js +3 -0
- package/dist/src/presentation/web/components/features/chat/ChatSheet.d.ts.map +1 -1
- package/dist/src/presentation/web/components/features/chat/ChatSheet.js +3 -1
- package/dist/src/presentation/web/components/features/chat/ChatTab.d.ts.map +1 -1
- package/dist/src/presentation/web/components/features/chat/ChatTab.js +3 -2
- package/dist/src/presentation/web/components/features/chat/InteractionBubble.d.ts +33 -0
- package/dist/src/presentation/web/components/features/chat/InteractionBubble.d.ts.map +1 -0
- package/dist/src/presentation/web/components/features/chat/InteractionBubble.js +155 -0
- package/dist/src/presentation/web/components/features/chat/InteractionBubble.stories.d.ts +22 -0
- package/dist/src/presentation/web/components/features/chat/InteractionBubble.stories.d.ts.map +1 -0
- package/dist/src/presentation/web/components/features/chat/InteractionBubble.stories.js +107 -0
- package/dist/src/presentation/web/components/features/chat/useChatRuntime.d.ts +16 -0
- package/dist/src/presentation/web/components/features/chat/useChatRuntime.d.ts.map +1 -1
- package/dist/src/presentation/web/components/features/chat/useChatRuntime.js +62 -1
- 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 +18 -3
- 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 +1 -1
- package/dist/src/presentation/web/hooks/use-graph-state.d.ts.map +1 -1
- package/dist/src/presentation/web/hooks/use-graph-state.js +16 -0
- package/dist/src/presentation/web/hooks/use-turn-statuses.d.ts +1 -1
- package/dist/src/presentation/web/hooks/use-turn-statuses.d.ts.map +1 -1
- package/dist/src/presentation/web/hooks/use-turn-statuses.js +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/web/.next/BUILD_ID +1 -1
- package/web/.next/app-path-routes-manifest.json +1 -0
- package/web/.next/build-manifest.json +4 -4
- package/web/.next/fallback-build-manifest.json +2 -2
- package/web/.next/prerender-manifest.json +3 -3
- package/web/.next/required-server-files.js +2 -2
- package/web/.next/required-server-files.json +2 -2
- package/web/.next/routes-manifest.json +8 -0
- package/web/.next/server/app/(dashboard)/@drawer/adopt/page/build-manifest.json +2 -2
- package/web/.next/server/app/(dashboard)/@drawer/adopt/page/react-loadable-manifest.json +1 -8
- package/web/.next/server/app/(dashboard)/@drawer/adopt/page/server-reference-manifest.json +29 -29
- package/web/.next/server/app/(dashboard)/@drawer/adopt/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/adopt/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/chat/page/build-manifest.json +2 -2
- package/web/.next/server/app/(dashboard)/@drawer/chat/page/react-loadable-manifest.json +1 -8
- package/web/.next/server/app/(dashboard)/@drawer/chat/page/server-reference-manifest.json +27 -27
- package/web/.next/server/app/(dashboard)/@drawer/chat/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/chat/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/create/page/build-manifest.json +2 -2
- package/web/.next/server/app/(dashboard)/@drawer/create/page/react-loadable-manifest.json +1 -8
- package/web/.next/server/app/(dashboard)/@drawer/create/page/server-reference-manifest.json +30 -30
- 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/build-manifest.json +2 -2
- package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page/react-loadable-manifest.json +1 -8
- package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page/server-reference-manifest.json +38 -38
- 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/build-manifest.json +2 -2
- package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page/react-loadable-manifest.json +1 -8
- package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page/server-reference-manifest.json +38 -38
- 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]/[tab]/page/build-manifest.json +2 -2
- package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/[tab]/page/react-loadable-manifest.json +1 -8
- package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/[tab]/page/server-reference-manifest.json +28 -28
- package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/[tab]/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/[tab]/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page/build-manifest.json +2 -2
- package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page/react-loadable-manifest.json +1 -8
- package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page/server-reference-manifest.json +28 -28
- 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)/chat/page/build-manifest.json +2 -2
- package/web/.next/server/app/(dashboard)/chat/page/react-loadable-manifest.json +1 -8
- package/web/.next/server/app/(dashboard)/chat/page/server-reference-manifest.json +27 -27
- package/web/.next/server/app/(dashboard)/chat/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/chat/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/create/page/build-manifest.json +2 -2
- package/web/.next/server/app/(dashboard)/create/page/react-loadable-manifest.json +1 -8
- package/web/.next/server/app/(dashboard)/create/page/server-reference-manifest.json +30 -30
- 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/build-manifest.json +2 -2
- package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page/react-loadable-manifest.json +1 -8
- package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page/server-reference-manifest.json +38 -38
- 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/build-manifest.json +2 -2
- package/web/.next/server/app/(dashboard)/feature/[featureId]/page/react-loadable-manifest.json +1 -8
- package/web/.next/server/app/(dashboard)/feature/[featureId]/page/server-reference-manifest.json +38 -38
- 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/build-manifest.json +2 -2
- package/web/.next/server/app/(dashboard)/page/react-loadable-manifest.json +1 -8
- package/web/.next/server/app/(dashboard)/page/server-reference-manifest.json +27 -27
- 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]/[tab]/page/build-manifest.json +2 -2
- package/web/.next/server/app/(dashboard)/repository/[repositoryId]/[tab]/page/react-loadable-manifest.json +1 -8
- package/web/.next/server/app/(dashboard)/repository/[repositoryId]/[tab]/page/server-reference-manifest.json +28 -28
- package/web/.next/server/app/(dashboard)/repository/[repositoryId]/[tab]/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/repository/[repositoryId]/[tab]/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page/build-manifest.json +2 -2
- package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page/react-loadable-manifest.json +1 -8
- package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page/server-reference-manifest.json +28 -28
- 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/build-manifest.json +2 -2
- package/web/.next/server/app/_global-error/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 +7 -7
- package/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +2 -2
- package/web/.next/server/app/_global-error.segments/_full.segment.rsc +7 -7
- package/web/.next/server/app/_global-error.segments/_head.segment.rsc +3 -3
- package/web/.next/server/app/_global-error.segments/_index.segment.rsc +3 -3
- package/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/web/.next/server/app/_not-found/page/build-manifest.json +2 -2
- package/web/.next/server/app/_not-found/page/react-loadable-manifest.json +1 -8
- package/web/.next/server/app/_not-found/page/server-reference-manifest.json +6 -6
- 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/attachments/upload-from-path/route.js +1 -1
- package/web/.next/server/app/api/attachments/upload-from-path/route.js.nft.json +1 -1
- package/web/.next/server/app/api/evidence/route.js.nft.json +1 -1
- package/web/.next/server/app/api/graph-data/route.js.nft.json +1 -1
- package/web/.next/server/app/api/interactive/chat/[featureId]/messages/route.js.nft.json +1 -1
- package/web/.next/server/app/api/interactive/chat/[featureId]/respond/route/app-paths-manifest.json +3 -0
- package/web/.next/server/app/api/interactive/chat/[featureId]/respond/route/build-manifest.json +11 -0
- package/web/.next/server/app/api/interactive/chat/[featureId]/respond/route/server-reference-manifest.json +4 -0
- package/web/.next/server/app/api/interactive/chat/[featureId]/respond/route.js +7 -0
- package/web/.next/server/app/api/interactive/chat/[featureId]/respond/route.js.map +5 -0
- package/web/.next/server/app/api/interactive/chat/[featureId]/respond/route.js.nft.json +1 -0
- package/web/.next/server/app/api/interactive/chat/[featureId]/respond/route_client-reference-manifest.js +2 -0
- package/web/.next/server/app/features/page/build-manifest.json +2 -2
- package/web/.next/server/app/features/page/react-loadable-manifest.json +1 -8
- package/web/.next/server/app/features/page/server-reference-manifest.json +6 -6
- package/web/.next/server/app/features/page.js.nft.json +1 -1
- package/web/.next/server/app/features/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/settings/page/build-manifest.json +2 -2
- package/web/.next/server/app/settings/page/react-loadable-manifest.json +1 -8
- package/web/.next/server/app/settings/page/server-reference-manifest.json +9 -9
- 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/build-manifest.json +2 -2
- package/web/.next/server/app/skills/page/react-loadable-manifest.json +1 -8
- package/web/.next/server/app/skills/page/server-reference-manifest.json +11 -11
- 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/build-manifest.json +2 -2
- package/web/.next/server/app/tools/page/react-loadable-manifest.json +1 -8
- package/web/.next/server/app/tools/page/server-reference-manifest.json +11 -11
- 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/build-manifest.json +2 -2
- package/web/.next/server/app/version/page/react-loadable-manifest.json +1 -8
- package/web/.next/server/app/version/page/server-reference-manifest.json +6 -6
- package/web/.next/server/app/version/page.js.nft.json +1 -1
- package/web/.next/server/app/version/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app-paths-manifest.json +1 -0
- package/web/.next/server/chunks/8ba4b_server_app_api_interactive_chat_[featureId]_respond_route_actions_990d51bd.js +3 -0
- package/web/.next/server/chunks/8ba4b_server_app_api_interactive_chat_[featureId]_respond_route_actions_990d51bd.js.map +1 -0
- package/web/.next/server/chunks/[root-of-the-server]__31944fa2._.js +3 -0
- package/web/.next/server/chunks/[root-of-the-server]__31944fa2._.js.map +1 -0
- package/web/.next/server/chunks/[root-of-the-server]__8a281f8d._.js +9 -3
- package/web/.next/server/chunks/[root-of-the-server]__8a281f8d._.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]__a5879003._.js → [root-of-the-server]__ea653642._.js} +2 -2
- package/web/.next/server/chunks/{[root-of-the-server]__a5879003._.js.map → [root-of-the-server]__ea653642._.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/744ca_web_components_common_control-center-drawer_feature-drawer-client_tsx_e9755fc8._.js +2 -2
- package/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_feature-drawer-client_tsx_e9755fc8._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__1f389e5d._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__1f389e5d._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__20a36a42._.js +3 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__20a36a42._.js.map +1 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__357d99f9._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__4fb81977._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__4fb81977._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__6c7d3936._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__6c7d3936._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__7dcd0917._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__7dcd0917._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__7ffd3598._.js +2 -2
- package/web/.next/server/chunks/ssr/[root-of-the-server]__7ffd3598._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__86ff0bc5._.js +2 -2
- package/web/.next/server/chunks/ssr/[root-of-the-server]__86ff0bc5._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__b020c17d._.js +2 -2
- package/web/.next/server/chunks/ssr/[root-of-the-server]__b020c17d._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__b7b96453._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__b7b96453._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__ba7f5873._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__ba7f5873._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__c5e09f6f._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__c5e09f6f._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__e88da4ee._.js +1 -1
- package/web/.next/server/chunks/ssr/{_5f099575._.js → _004b47fc._.js} +2 -2
- package/web/.next/server/chunks/ssr/{_5f099575._.js.map → _004b47fc._.js.map} +1 -1
- package/web/.next/server/chunks/ssr/_02e01240._.js +1 -1
- package/web/.next/server/chunks/ssr/_02e01240._.js.map +1 -1
- package/web/.next/server/chunks/ssr/_05c23ad9._.js +1 -1
- package/web/.next/server/chunks/ssr/_05c23ad9._.js.map +1 -1
- package/web/.next/server/chunks/ssr/_0727935d._.js +1 -1
- package/web/.next/server/chunks/ssr/_0727935d._.js.map +1 -1
- package/web/.next/server/chunks/ssr/_16235e5e._.js +1 -1
- package/web/.next/server/chunks/ssr/_16235e5e._.js.map +1 -1
- package/web/.next/server/chunks/ssr/_16eb4fec._.js +1 -1
- package/web/.next/server/chunks/ssr/_16eb4fec._.js.map +1 -1
- package/web/.next/server/chunks/ssr/_18886033._.js +1 -1
- package/web/.next/server/chunks/ssr/_18886033._.js.map +1 -1
- package/web/.next/server/chunks/ssr/_1e08a336._.js.map +1 -1
- package/web/.next/server/chunks/ssr/_22e00a14._.js +1 -1
- package/web/.next/server/chunks/ssr/_22e00a14._.js.map +1 -1
- package/web/.next/server/chunks/ssr/_4cbb7f95._.js +3 -0
- package/web/.next/server/chunks/ssr/_4cbb7f95._.js.map +1 -0
- package/web/.next/server/chunks/ssr/_56b9d60f._.js +1 -1
- package/web/.next/server/chunks/ssr/_56b9d60f._.js.map +1 -1
- package/web/.next/server/chunks/ssr/{_cac860bb._.js → _58902d92._.js} +2 -2
- package/web/.next/server/chunks/ssr/{_cac860bb._.js.map → _58902d92._.js.map} +1 -1
- package/web/.next/server/chunks/ssr/{_cc936cdc._.js → _682fc996._.js} +2 -2
- package/web/.next/server/chunks/ssr/_682fc996._.js.map +1 -0
- package/web/.next/server/chunks/ssr/_6892e3b9._.js +3 -0
- package/web/.next/server/chunks/ssr/_6892e3b9._.js.map +1 -0
- package/web/.next/server/chunks/ssr/_a1068852._.js +3 -0
- package/web/.next/server/chunks/ssr/_a1068852._.js.map +1 -0
- package/web/.next/server/chunks/ssr/_a5a5901d._.js +1 -1
- package/web/.next/server/chunks/ssr/_a5a5901d._.js.map +1 -1
- package/web/.next/server/chunks/ssr/_ad09f271._.js +1 -1
- package/web/.next/server/chunks/ssr/_ad09f271._.js.map +1 -1
- package/web/.next/server/chunks/ssr/_b4a9122d._.js +3 -0
- package/web/.next/server/chunks/ssr/_b4a9122d._.js.map +1 -0
- package/web/.next/server/chunks/ssr/_c3f595c6._.js +1 -1
- package/web/.next/server/chunks/ssr/_c3f595c6._.js.map +1 -1
- package/web/.next/server/chunks/ssr/_ea9e1556._.js +1 -1
- package/web/.next/server/chunks/ssr/_ea9e1556._.js.map +1 -1
- package/web/.next/server/chunks/ssr/_f1ba9be6._.js +2 -2
- package/web/.next/server/chunks/ssr/_f1ba9be6._.js.map +1 -1
- package/web/.next/server/chunks/ssr/_f33cd07e._.js +2 -2
- package/web/.next/server/chunks/ssr/_f33cd07e._.js.map +1 -1
- package/web/.next/server/chunks/ssr/_f8b45233._.js +1 -1
- package/web/.next/server/chunks/ssr/_f8b45233._.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/f3a1f_components_common_control-center-drawer_repository-drawer-client_tsx_39a00c03._.js +1 -1
- package/web/.next/server/chunks/ssr/f3a1f_components_common_control-center-drawer_repository-drawer-client_tsx_39a00c03._.js.map +1 -1
- package/web/.next/server/chunks/ssr/node_modules__pnpm_12a7ede0._.js +3 -0
- package/web/.next/server/chunks/ssr/node_modules__pnpm_12a7ede0._.js.map +1 -0
- package/web/.next/server/chunks/ssr/src_presentation_web_app_actions_open-ide_ts_baaca5d5._.js +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_components_895e5bfa._.js +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_components_895e5bfa._.js.map +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_components_features_control-center_7ac3562e._.js +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_components_features_control-center_7ac3562e._.js.map +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_components_ui_select_tsx_45d6b8ae._.js +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_components_ui_select_tsx_45d6b8ae._.js.map +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_db9fa0c2._.js +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_db9fa0c2._.js.map +1 -1
- package/web/.next/server/middleware-build-manifest.js +2 -2
- 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 +48 -48
- package/web/.next/static/chunks/{fe70e73feb07bcfd.js → 08ec4c9ab61717aa.js} +1 -1
- package/web/.next/static/chunks/{dedf6ca63c5468fa.js → 09edd35d194bec06.js} +3 -3
- package/web/.next/static/chunks/{d4d8f0a137bd2eb4.js → 12803afee7d0afc8.js} +2 -2
- package/web/.next/static/chunks/{f0183c225f31840b.js → 352c5cb6ed572dc3.js} +1 -1
- package/web/.next/static/chunks/41b4082b079b3ede.js +1 -0
- package/web/.next/static/chunks/5a36922f56850850.js +1 -0
- package/web/.next/static/chunks/5b7275374d2696b3.css +1 -0
- package/web/.next/static/chunks/6d6f70ff5151b8cb.js +7 -0
- package/web/.next/static/chunks/{2615825711ac4e81.js → 7bbbe3273230d2a1.js} +3 -3
- package/web/.next/static/chunks/{9e2dcc66aa1e3ee7.js → 890a772551fc3962.js} +1 -1
- package/web/.next/static/chunks/982aef195c118996.js +1 -0
- package/web/.next/static/chunks/{612750555eb00a6c.js → a830880e642a6e01.js} +2 -2
- package/web/.next/static/chunks/c625deec577681f7.js +1 -0
- package/web/.next/static/chunks/dadf5909b2f15985.js +1 -0
- package/web/.next/static/chunks/{9c4927d092875708.js → e137a48b35703673.js} +1 -1
- package/web/.next/static/chunks/{4ba01cd71cfa981b.js → e26afac86ed33fa7.js} +1 -1
- package/web/.next/static/chunks/{4ac6f8c2bb39a6e4.js → f48af05c1bdb8aec.js} +1 -1
- package/web/.next/static/chunks/{328874065794ea9f.js → fac6bac55da705ea.js} +1 -1
- package/web/.next/static/chunks/{68127a29d87ba43a.js → fb9d76d30fa8f790.js} +1 -1
- package/web/.next/static/chunks/{turbopack-62782e656a49f322.js → turbopack-57bb0674e2cd1d31.js} +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__13fa44e4._.js +0 -3
- package/web/.next/server/chunks/ssr/[root-of-the-server]__13fa44e4._.js.map +0 -1
- package/web/.next/server/chunks/ssr/_5c76b6b5._.js +0 -3
- package/web/.next/server/chunks/ssr/_5c76b6b5._.js.map +0 -1
- package/web/.next/server/chunks/ssr/_a69efc34._.js +0 -3
- package/web/.next/server/chunks/ssr/_a69efc34._.js.map +0 -1
- package/web/.next/server/chunks/ssr/_cc936cdc._.js.map +0 -1
- package/web/.next/server/chunks/ssr/_df737cce._.js +0 -3
- package/web/.next/server/chunks/ssr/_df737cce._.js.map +0 -1
- package/web/.next/server/chunks/ssr/_f79e241b._.js +0 -3
- package/web/.next/server/chunks/ssr/_f79e241b._.js.map +0 -1
- package/web/.next/server/chunks/ssr/node_modules__pnpm_1300ae39._.js +0 -3
- package/web/.next/server/chunks/ssr/node_modules__pnpm_1300ae39._.js.map +0 -1
- package/web/.next/static/chunks/110a8827583ae5bb.js +0 -1
- package/web/.next/static/chunks/5d4a8552d5b6a4a8.js +0 -1
- package/web/.next/static/chunks/6d7b999c99d6d175.js +0 -9
- package/web/.next/static/chunks/8180973e9cd6a99e.css +0 -1
- package/web/.next/static/chunks/92c8c994d9ad0c81.js +0 -1
- package/web/.next/static/chunks/a262ab91e9288145.js +0 -1
- package/web/.next/static/chunks/a825ba5207a10722.js +0 -7
- package/web/.next/static/chunks/c4874941c93f4f77.js +0 -1
- package/web/.next/static/chunks/c5b3a8430ab26648.css +0 -1
- /package/web/.next/static/{xAhPAfLhIR5KWVO7DbsJR → 9dnSGRS5_ITgOmM09PgwP}/_buildManifest.js +0 -0
- /package/web/.next/static/{xAhPAfLhIR5KWVO7DbsJR → 9dnSGRS5_ITgOmM09PgwP}/_clientMiddlewareManifest.json +0 -0
- /package/web/.next/static/{xAhPAfLhIR5KWVO7DbsJR → 9dnSGRS5_ITgOmM09PgwP}/_ssgManifest.js +0 -0
|
@@ -11,6 +11,7 @@ import { composeUserInput } from '../../../app/actions/compose-user-input.js';
|
|
|
11
11
|
import { AgentModelPicker } from '../../features/settings/AgentModelPicker/index.js';
|
|
12
12
|
import { useChatRuntime } from './useChatRuntime.js';
|
|
13
13
|
import { ChatComposer } from './ChatComposer.js';
|
|
14
|
+
import { InteractionBubble } from './InteractionBubble.js';
|
|
14
15
|
const IS_DEV = process.env.NODE_ENV === 'development';
|
|
15
16
|
export function ChatTab({ featureId, worktreePath }) {
|
|
16
17
|
const [overrideAgent, setOverrideAgent] = useState(undefined);
|
|
@@ -18,7 +19,7 @@ export function ChatTab({ featureId, worktreePath }) {
|
|
|
18
19
|
const [debugMode, setDebugMode] = useState(false);
|
|
19
20
|
const att = useAttachments();
|
|
20
21
|
const contentTransform = useCallback((content) => composeUserInput(content, att.completedAttachments.map((a) => ({ path: a.path, name: a.name, notes: a.notes }))), [att.completedAttachments]);
|
|
21
|
-
const { runtime, status, clearChat, sessionInfo, isChatLoading } = useChatRuntime(featureId, worktreePath, {
|
|
22
|
+
const { runtime, status, clearChat, sessionInfo, isChatLoading, pendingInteraction, respondToInteraction, } = useChatRuntime(featureId, worktreePath, {
|
|
22
23
|
contentTransform,
|
|
23
24
|
onMessageSent: att.clearAttachments,
|
|
24
25
|
model: overrideModel,
|
|
@@ -54,7 +55,7 @@ export function ChatTab({ featureId, worktreePath }) {
|
|
|
54
55
|
setOverrideAgent(agent);
|
|
55
56
|
setOverrideModel(model);
|
|
56
57
|
}, className: "w-55" }) }));
|
|
57
|
-
return (_jsxs("div", { className: "flex h-full min-h-0 flex-col", children: [_jsx(ChatHeader, { sessionInfo: sessionInfo, isAgentActive: status.isRunning, onClear: clearChat, debugMode: debugMode, onDebugToggle: IS_DEV ? setDebugMode : undefined }), _jsx("div", { className: "flex min-h-0 flex-1 flex-col", children: isChatLoading ? (_jsx(ChatSkeleton, {})) : (_jsx(AssistantRuntimeProvider, { runtime: runtime, children: _jsx(Thread, { composer: composer }) })) })] }));
|
|
58
|
+
return (_jsxs("div", { className: "flex h-full min-h-0 flex-col", children: [_jsx(ChatHeader, { sessionInfo: sessionInfo, isAgentActive: status.isRunning, onClear: clearChat, debugMode: debugMode, onDebugToggle: IS_DEV ? setDebugMode : undefined }), _jsx("div", { className: "flex min-h-0 flex-1 flex-col", children: isChatLoading ? (_jsx(ChatSkeleton, {})) : (_jsx(AssistantRuntimeProvider, { runtime: runtime, children: _jsx(Thread, { composer: composer, afterMessages: pendingInteraction ? (_jsx(InteractionBubble, { interaction: pendingInteraction, onSubmit: respondToInteraction })) : undefined }) })) })] }));
|
|
58
59
|
}
|
|
59
60
|
// ── Loading skeleton ────────────────────────────────────────────────────────
|
|
60
61
|
function ChatSkeleton() {
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/** Shape matching UserQuestion from the agent executor interface. */
|
|
2
|
+
interface QuestionOption {
|
|
3
|
+
label: string;
|
|
4
|
+
description: string;
|
|
5
|
+
preview?: string;
|
|
6
|
+
}
|
|
7
|
+
interface Question {
|
|
8
|
+
question: string;
|
|
9
|
+
header: string;
|
|
10
|
+
options: QuestionOption[];
|
|
11
|
+
multiSelect: boolean;
|
|
12
|
+
}
|
|
13
|
+
export interface InteractionData {
|
|
14
|
+
toolCallId: string;
|
|
15
|
+
questions: Question[];
|
|
16
|
+
}
|
|
17
|
+
export interface InteractionBubbleProps {
|
|
18
|
+
interaction: InteractionData;
|
|
19
|
+
onSubmit: (answers: Record<string, string>) => void;
|
|
20
|
+
className?: string;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Renders an agent's AskUserQuestion interaction inline in the chat thread.
|
|
24
|
+
*
|
|
25
|
+
* - Single question: renders options directly
|
|
26
|
+
* - Multiple questions: tabbed interface with header chips as tabs
|
|
27
|
+
*
|
|
28
|
+
* After submission, the bubble disappears and a green summary message
|
|
29
|
+
* is persisted in the conversation history (rendered by InteractionResponseMessage in thread.tsx).
|
|
30
|
+
*/
|
|
31
|
+
export declare function InteractionBubble({ interaction, onSubmit, className }: InteractionBubbleProps): import("react/jsx-runtime").JSX.Element;
|
|
32
|
+
export {};
|
|
33
|
+
//# sourceMappingURL=InteractionBubble.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"InteractionBubble.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/chat/InteractionBubble.tsx"],"names":[],"mappings":"AAMA,qEAAqE;AACrE,UAAU,cAAc;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,UAAU,QAAQ;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,cAAc,EAAE,CAAC;IAC1B,WAAW,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,eAAe;IAC9B,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,QAAQ,EAAE,CAAC;CACvB;AAED,MAAM,WAAW,sBAAsB;IACrC,WAAW,EAAE,eAAe,CAAC;IAC7B,QAAQ,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,IAAI,CAAC;IACpD,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAAC,EAAE,WAAW,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE,sBAAsB,2CAsB7F"}
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useState, useCallback } from 'react';
|
|
4
|
+
import { Check, MessageCircleQuestion } from 'lucide-react';
|
|
5
|
+
import { cn } from '../../../lib/utils.js';
|
|
6
|
+
/**
|
|
7
|
+
* Renders an agent's AskUserQuestion interaction inline in the chat thread.
|
|
8
|
+
*
|
|
9
|
+
* - Single question: renders options directly
|
|
10
|
+
* - Multiple questions: tabbed interface with header chips as tabs
|
|
11
|
+
*
|
|
12
|
+
* After submission, the bubble disappears and a green summary message
|
|
13
|
+
* is persisted in the conversation history (rendered by InteractionResponseMessage in thread.tsx).
|
|
14
|
+
*/
|
|
15
|
+
export function InteractionBubble({ interaction, onSubmit, className }) {
|
|
16
|
+
const isMultiQuestion = interaction.questions.length > 1;
|
|
17
|
+
return (_jsxs("div", { className: cn('group flex w-full items-start gap-2.5 px-4 py-0.5', className), children: [_jsx("div", { className: "bg-muted flex h-6 w-6 shrink-0 items-center justify-center rounded-full", children: _jsx(MessageCircleQuestion, { className: "h-3.5 w-3.5 text-violet-600 dark:text-violet-400" }) }), _jsx("div", { className: "flex min-w-0 flex-1 flex-col gap-0.5", children: _jsx("div", { className: "text-foreground mt-px overflow-hidden rounded-2xl rounded-tl-sm border border-violet-200 bg-violet-50/50 text-sm leading-relaxed shadow-sm dark:border-violet-500/20 dark:bg-violet-950/20", children: isMultiQuestion ? (_jsx(TabbedQuestions, { questions: interaction.questions, onSubmit: onSubmit })) : (_jsx("div", { className: "px-4 py-3", children: _jsx(SingleQuestion, { question: interaction.questions[0], onSubmit: onSubmit }) })) }) })] }));
|
|
18
|
+
}
|
|
19
|
+
function TabbedQuestions({ questions, onSubmit, }) {
|
|
20
|
+
const [activeTab, setActiveTab] = useState(0);
|
|
21
|
+
// All per-question state lives here — indexed by question text
|
|
22
|
+
const [selections, setSelections] = useState(() => {
|
|
23
|
+
const init = {};
|
|
24
|
+
for (const q of questions) {
|
|
25
|
+
init[q.question] = { selectedOptions: new Set(), otherText: '', isOtherSelected: false };
|
|
26
|
+
}
|
|
27
|
+
return init;
|
|
28
|
+
});
|
|
29
|
+
const updateSelection = useCallback((questionText, updater) => {
|
|
30
|
+
setSelections((prev) => ({
|
|
31
|
+
...prev,
|
|
32
|
+
[questionText]: updater(prev[questionText]),
|
|
33
|
+
}));
|
|
34
|
+
}, []);
|
|
35
|
+
// Derive answers from selections
|
|
36
|
+
const answers = {};
|
|
37
|
+
for (const q of questions) {
|
|
38
|
+
const s = selections[q.question];
|
|
39
|
+
if (!s)
|
|
40
|
+
continue;
|
|
41
|
+
const parts = [...s.selectedOptions];
|
|
42
|
+
if (s.isOtherSelected && s.otherText.trim())
|
|
43
|
+
parts.push(s.otherText.trim());
|
|
44
|
+
if (parts.length > 0)
|
|
45
|
+
answers[q.question] = parts.join(', ');
|
|
46
|
+
}
|
|
47
|
+
const allAnswered = questions.every((q) => answers[q.question]);
|
|
48
|
+
const handleSubmit = useCallback(() => {
|
|
49
|
+
if (!allAnswered)
|
|
50
|
+
return;
|
|
51
|
+
onSubmit(answers);
|
|
52
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps -- answers is derived, stable enough
|
|
53
|
+
}, [allAnswered, onSubmit, selections]);
|
|
54
|
+
return (_jsxs("div", { children: [_jsx("div", { className: "flex border-b border-violet-200 dark:border-violet-500/20", children: questions.map((q, i) => {
|
|
55
|
+
const isActive = i === activeTab;
|
|
56
|
+
const hasAnswer = !!answers[q.question];
|
|
57
|
+
return (_jsxs("button", { type: "button", onClick: () => setActiveTab(i), className: cn('relative flex items-center gap-1.5 px-4 py-2 text-xs font-medium transition-colors', isActive
|
|
58
|
+
? 'text-violet-700 dark:text-violet-300'
|
|
59
|
+
: 'text-muted-foreground hover:text-foreground'), children: [hasAnswer ? (_jsx(Check, { className: "h-3 w-3 text-emerald-600 dark:text-emerald-400" })) : (_jsxs("span", { className: "text-muted-foreground/50 text-[10px]", children: [i + 1, "."] })), q.header, isActive ? (_jsx("span", { className: "absolute inset-x-0 -bottom-px h-0.5 rounded-full bg-violet-600 dark:bg-violet-400" })) : null] }, q.question));
|
|
60
|
+
}) }), questions.map((q, i) => (_jsx("div", { className: "px-4 py-3", style: { display: i === activeTab ? undefined : 'none' }, children: _jsx(QuestionPanel, { question: q, selection: selections[q.question], onSelectionChange: (updater) => updateSelection(q.question, updater) }) }, q.question))), _jsxs("div", { className: "flex items-center gap-3 border-t border-violet-200 px-4 py-2.5 dark:border-violet-500/20", children: [_jsxs("button", { type: "button", onClick: handleSubmit, disabled: !allAnswered, className: cn('inline-flex items-center gap-1.5 rounded-lg px-3 py-1.5 text-xs font-medium transition-all', allAnswered
|
|
61
|
+
? 'bg-violet-600 text-white shadow-sm hover:bg-violet-700 active:scale-[0.98] dark:bg-violet-600 dark:hover:bg-violet-500'
|
|
62
|
+
: 'bg-muted text-muted-foreground cursor-not-allowed opacity-50'), children: [_jsx(Check, { className: "h-3 w-3" }), "Submit all"] }), _jsxs("span", { className: "text-muted-foreground text-[10px]", children: [Object.keys(answers).length, "/", questions.length, " answered"] })] })] }));
|
|
63
|
+
}
|
|
64
|
+
// ── Question panel (used inside tabs) ───────────────────────────────────
|
|
65
|
+
function QuestionPanel({ question, selection, onSelectionChange, }) {
|
|
66
|
+
const handleOptionToggle = useCallback((label) => {
|
|
67
|
+
onSelectionChange((prev) => {
|
|
68
|
+
const next = new Set(prev.selectedOptions);
|
|
69
|
+
if (question.multiSelect) {
|
|
70
|
+
if (next.has(label))
|
|
71
|
+
next.delete(label);
|
|
72
|
+
else
|
|
73
|
+
next.add(label);
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
next.clear();
|
|
77
|
+
next.add(label);
|
|
78
|
+
return { ...prev, selectedOptions: next, isOtherSelected: false };
|
|
79
|
+
}
|
|
80
|
+
return { ...prev, selectedOptions: next };
|
|
81
|
+
});
|
|
82
|
+
}, [question.multiSelect, onSelectionChange]);
|
|
83
|
+
const handleOtherToggle = useCallback(() => {
|
|
84
|
+
onSelectionChange((prev) => {
|
|
85
|
+
if (question.multiSelect) {
|
|
86
|
+
return { ...prev, isOtherSelected: !prev.isOtherSelected };
|
|
87
|
+
}
|
|
88
|
+
return { selectedOptions: new Set(), otherText: prev.otherText, isOtherSelected: true };
|
|
89
|
+
});
|
|
90
|
+
}, [question.multiSelect, onSelectionChange]);
|
|
91
|
+
const handleOtherTextChange = useCallback((text) => {
|
|
92
|
+
onSelectionChange((prev) => ({ ...prev, otherText: text }));
|
|
93
|
+
}, [onSelectionChange]);
|
|
94
|
+
return (_jsxs("div", { children: [_jsxs("p", { className: "text-foreground mb-2 text-xs font-medium", children: [question.question, question.multiSelect ? (_jsx("span", { className: "text-muted-foreground ml-1 font-normal", children: "(select multiple)" })) : null] }), _jsxs("div", { className: "flex flex-col gap-1.5", children: [question.options.map((opt) => (_jsx(OptionRow, { option: opt, isSelected: selection.selectedOptions.has(opt.label), isMulti: question.multiSelect, onToggle: () => handleOptionToggle(opt.label) }, opt.label))), _jsx(OtherRow, { isSelected: selection.isOtherSelected, isMulti: question.multiSelect, text: selection.otherText, onToggle: handleOtherToggle, onTextChange: handleOtherTextChange })] })] }));
|
|
95
|
+
}
|
|
96
|
+
// ── Single question (no tabs) ───────────────────────────────────────────
|
|
97
|
+
function SingleQuestion({ question, onSubmit, }) {
|
|
98
|
+
const [selectedOptions, setSelectedOptions] = useState(new Set());
|
|
99
|
+
const [otherText, setOtherText] = useState('');
|
|
100
|
+
const [isOtherSelected, setIsOtherSelected] = useState(false);
|
|
101
|
+
const handleOptionToggle = useCallback((label) => {
|
|
102
|
+
setSelectedOptions((prev) => {
|
|
103
|
+
const next = new Set(prev);
|
|
104
|
+
if (question.multiSelect) {
|
|
105
|
+
if (next.has(label))
|
|
106
|
+
next.delete(label);
|
|
107
|
+
else
|
|
108
|
+
next.add(label);
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
next.clear();
|
|
112
|
+
next.add(label);
|
|
113
|
+
setIsOtherSelected(false);
|
|
114
|
+
}
|
|
115
|
+
return next;
|
|
116
|
+
});
|
|
117
|
+
if (!question.multiSelect)
|
|
118
|
+
setIsOtherSelected(false);
|
|
119
|
+
}, [question.multiSelect]);
|
|
120
|
+
const handleOtherToggle = useCallback(() => {
|
|
121
|
+
if (question.multiSelect) {
|
|
122
|
+
setIsOtherSelected((prev) => !prev);
|
|
123
|
+
}
|
|
124
|
+
else {
|
|
125
|
+
setSelectedOptions(new Set());
|
|
126
|
+
setIsOtherSelected(true);
|
|
127
|
+
}
|
|
128
|
+
}, [question.multiSelect]);
|
|
129
|
+
const handleSubmit = useCallback(() => {
|
|
130
|
+
const parts = [...selectedOptions];
|
|
131
|
+
if (isOtherSelected && otherText.trim())
|
|
132
|
+
parts.push(otherText.trim());
|
|
133
|
+
if (parts.length === 0)
|
|
134
|
+
return;
|
|
135
|
+
onSubmit({ [question.question]: parts.join(', ') });
|
|
136
|
+
}, [selectedOptions, isOtherSelected, otherText, onSubmit, question.question]);
|
|
137
|
+
const hasSelection = selectedOptions.size > 0 || (isOtherSelected && otherText.trim());
|
|
138
|
+
return (_jsxs("div", { children: [_jsxs("div", { className: "mb-2 flex items-start gap-2", children: [_jsx("span", { className: "inline-flex shrink-0 items-center rounded-full bg-violet-100 px-2 py-0.5 text-[10px] font-semibold tracking-wider text-violet-700 uppercase dark:bg-violet-900/50 dark:text-violet-300", children: question.header }), _jsx("span", { className: "font-medium", children: question.question })] }), _jsxs("div", { className: "ml-0.5 flex flex-col gap-1.5", children: [question.options.map((opt) => (_jsx(OptionRow, { option: opt, isSelected: selectedOptions.has(opt.label), isMulti: question.multiSelect, onToggle: () => handleOptionToggle(opt.label) }, opt.label))), _jsx(OtherRow, { isSelected: isOtherSelected, isMulti: question.multiSelect, text: otherText, onToggle: handleOtherToggle, onTextChange: setOtherText })] }), _jsxs("div", { className: "mt-3 flex items-center gap-2", children: [_jsxs("button", { type: "button", onClick: handleSubmit, disabled: !hasSelection, className: cn('inline-flex items-center gap-1.5 rounded-lg px-3 py-1.5 text-xs font-medium transition-all', hasSelection
|
|
139
|
+
? 'bg-violet-600 text-white shadow-sm hover:bg-violet-700 active:scale-[0.98] dark:bg-violet-600 dark:hover:bg-violet-500'
|
|
140
|
+
: 'bg-muted text-muted-foreground cursor-not-allowed opacity-50'), children: [_jsx(Check, { className: "h-3 w-3" }), "Submit"] }), question.multiSelect ? (_jsx("span", { className: "text-muted-foreground text-[10px]", children: "Select one or more" })) : null] })] }));
|
|
141
|
+
}
|
|
142
|
+
function OptionRow({ option, isSelected, isMulti, onToggle }) {
|
|
143
|
+
return (_jsxs("button", { type: "button", onClick: onToggle, className: cn('flex items-start gap-2.5 rounded-lg border px-3 py-2 text-left text-xs transition-all', isSelected
|
|
144
|
+
? 'border-violet-300 bg-violet-100/60 shadow-sm dark:border-violet-500/40 dark:bg-violet-900/30'
|
|
145
|
+
: 'border-border/50 hover:border-violet-300 hover:bg-violet-50 dark:hover:border-violet-500/30 dark:hover:bg-violet-900/10'), children: [_jsx("span", { className: cn('mt-0.5 flex h-4 w-4 shrink-0 items-center justify-center border transition-colors', isMulti ? 'rounded' : 'rounded-full', isSelected
|
|
146
|
+
? 'border-violet-600 bg-violet-600 dark:border-violet-500 dark:bg-violet-500'
|
|
147
|
+
: 'border-muted-foreground/30'), children: isSelected ? _jsx(Check, { className: "h-2.5 w-2.5 text-white", strokeWidth: 3 }) : null }), _jsxs("div", { className: "flex min-w-0 flex-col gap-0.5", children: [_jsx("span", { className: cn('font-medium', isSelected && 'text-violet-700 dark:text-violet-300'), children: option.label }), _jsx("span", { className: "text-muted-foreground text-[11px] leading-snug", children: option.description })] })] }));
|
|
148
|
+
}
|
|
149
|
+
function OtherRow({ isSelected, isMulti, text, onToggle, onTextChange }) {
|
|
150
|
+
return (_jsxs("div", { className: cn('flex items-start gap-2.5 rounded-lg border px-3 py-2 text-xs transition-all', isSelected
|
|
151
|
+
? 'border-violet-300 bg-violet-100/60 shadow-sm dark:border-violet-500/40 dark:bg-violet-900/30'
|
|
152
|
+
: 'border-border/50 hover:border-violet-300 dark:hover:border-violet-500/30'), children: [_jsx("button", { type: "button", onClick: onToggle, className: "mt-0.5 shrink-0", children: _jsx("span", { className: cn('flex h-4 w-4 items-center justify-center border transition-colors', isMulti ? 'rounded' : 'rounded-full', isSelected
|
|
153
|
+
? 'border-violet-600 bg-violet-600 dark:border-violet-500 dark:bg-violet-500'
|
|
154
|
+
: 'border-muted-foreground/30'), children: isSelected ? _jsx(Check, { className: "h-2.5 w-2.5 text-white", strokeWidth: 3 }) : null }) }), _jsxs("div", { className: "flex min-w-0 flex-1 flex-col gap-1", children: [_jsx("span", { className: cn('font-medium', isSelected && 'text-violet-700 dark:text-violet-300'), children: "Other" }), isSelected ? (_jsx("input", { type: "text", value: text, onChange: (e) => onTextChange(e.target.value), placeholder: "Type your answer...", className: "w-full rounded-md border border-violet-200 bg-white/80 px-2 py-1 text-xs outline-none focus:border-violet-400 focus:ring-1 focus:ring-violet-300/30 dark:border-violet-500/30 dark:bg-violet-950/30 dark:focus:border-violet-500/50 dark:focus:ring-violet-500/20", autoFocus: true })) : null] })] }));
|
|
155
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { StoryObj } from '@storybook/react';
|
|
2
|
+
import { InteractionBubble } from './InteractionBubble.js';
|
|
3
|
+
import type { InteractionData } from './InteractionBubble.js';
|
|
4
|
+
declare const meta: {
|
|
5
|
+
title: string;
|
|
6
|
+
component: typeof InteractionBubble;
|
|
7
|
+
parameters: {
|
|
8
|
+
layout: string;
|
|
9
|
+
};
|
|
10
|
+
decorators: ((Story: import("@storybook/core/csf").PartialStoryFn<import("@storybook/react").ReactRenderer, {
|
|
11
|
+
interaction: InteractionData;
|
|
12
|
+
onSubmit: (answers: Record<string, string>) => void;
|
|
13
|
+
className?: string | undefined;
|
|
14
|
+
}>) => import("react/jsx-runtime").JSX.Element)[];
|
|
15
|
+
};
|
|
16
|
+
export default meta;
|
|
17
|
+
type Story = StoryObj<typeof meta>;
|
|
18
|
+
export declare const SingleSelect: Story;
|
|
19
|
+
export declare const MultiSelect: Story;
|
|
20
|
+
export declare const TabbedMultiQuestion: Story;
|
|
21
|
+
export declare const Submitted: Story;
|
|
22
|
+
//# sourceMappingURL=InteractionBubble.stories.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"InteractionBubble.stories.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/chat/InteractionBubble.stories.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAQ,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAEvD,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAE3D,QAAA,MAAM,IAAI;;;;;;;;;;;CAWgC,CAAC;AAE3C,eAAe,IAAI,CAAC;AACpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,IAAI,CAAC,CAAC;AAsFnC,eAAO,MAAM,YAAY,EAAE,KAG1B,CAAC;AAEF,eAAO,MAAM,WAAW,EAAE,KAGzB,CAAC;AAEF,eAAO,MAAM,mBAAmB,EAAE,KAGjC,CAAC;AAEF,eAAO,MAAM,SAAS,EAAE,KAGvB,CAAC"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useState } from 'react';
|
|
3
|
+
import { InteractionBubble } from './InteractionBubble.js';
|
|
4
|
+
const meta = {
|
|
5
|
+
title: 'Features/Chat/InteractionBubble',
|
|
6
|
+
component: InteractionBubble,
|
|
7
|
+
parameters: { layout: 'padded' },
|
|
8
|
+
decorators: [
|
|
9
|
+
(Story) => (_jsx("div", { className: "bg-background mx-auto max-w-xl rounded-lg border p-4", children: _jsx(Story, {}) })),
|
|
10
|
+
],
|
|
11
|
+
};
|
|
12
|
+
export default meta;
|
|
13
|
+
const colorInteraction = {
|
|
14
|
+
toolCallId: 'toolu_color_1',
|
|
15
|
+
questions: [
|
|
16
|
+
{
|
|
17
|
+
question: 'What is your favorite color?',
|
|
18
|
+
header: 'Color',
|
|
19
|
+
multiSelect: false,
|
|
20
|
+
options: [
|
|
21
|
+
{ label: 'Red', description: 'The color red' },
|
|
22
|
+
{ label: 'Blue', description: 'The color blue' },
|
|
23
|
+
{ label: 'Green', description: 'The color green' },
|
|
24
|
+
{ label: 'Yellow', description: 'The color yellow' },
|
|
25
|
+
],
|
|
26
|
+
},
|
|
27
|
+
],
|
|
28
|
+
};
|
|
29
|
+
const multiSelectInteraction = {
|
|
30
|
+
toolCallId: 'toolu_features_1',
|
|
31
|
+
questions: [
|
|
32
|
+
{
|
|
33
|
+
question: 'Which features do you want to enable?',
|
|
34
|
+
header: 'Features',
|
|
35
|
+
multiSelect: true,
|
|
36
|
+
options: [
|
|
37
|
+
{ label: 'Dark mode', description: 'Enable dark theme support' },
|
|
38
|
+
{ label: 'Notifications', description: 'Push notifications for updates' },
|
|
39
|
+
{ label: 'Analytics', description: 'Usage analytics and reporting' },
|
|
40
|
+
],
|
|
41
|
+
},
|
|
42
|
+
],
|
|
43
|
+
};
|
|
44
|
+
const multiQuestionInteraction = {
|
|
45
|
+
toolCallId: 'toolu_setup_1',
|
|
46
|
+
questions: [
|
|
47
|
+
{
|
|
48
|
+
question: "What's your preferred coding environment?",
|
|
49
|
+
header: 'IDE',
|
|
50
|
+
multiSelect: false,
|
|
51
|
+
options: [
|
|
52
|
+
{
|
|
53
|
+
label: 'VS Code',
|
|
54
|
+
description: "Microsoft's popular editor with rich extension ecosystem.",
|
|
55
|
+
},
|
|
56
|
+
{ label: 'Neovim', description: 'Terminal-based, highly customizable.' },
|
|
57
|
+
{ label: 'JetBrains', description: 'Full-featured IDEs with deep language intelligence.' },
|
|
58
|
+
{ label: 'Cursor', description: 'AI-first fork of VS Code.' },
|
|
59
|
+
],
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
question: 'Which of these technologies do you actively use? (pick all that apply)',
|
|
63
|
+
header: 'Tech Stack',
|
|
64
|
+
multiSelect: true,
|
|
65
|
+
options: [
|
|
66
|
+
{ label: 'TypeScript', description: 'Statically typed JavaScript.' },
|
|
67
|
+
{ label: 'Python', description: 'Scripting, data science, ML, or backend.' },
|
|
68
|
+
{ label: 'Go', description: 'Fast, compiled, cloud-native tooling.' },
|
|
69
|
+
{ label: 'Rust', description: 'Systems programming with memory safety.' },
|
|
70
|
+
],
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
question: 'How would you describe your experience level?',
|
|
74
|
+
header: 'Level',
|
|
75
|
+
multiSelect: false,
|
|
76
|
+
options: [
|
|
77
|
+
{ label: 'Junior', description: 'Less than 2 years of experience.' },
|
|
78
|
+
{ label: 'Mid-level', description: '2-5 years of experience.' },
|
|
79
|
+
{ label: 'Senior', description: '5+ years of experience.' },
|
|
80
|
+
],
|
|
81
|
+
},
|
|
82
|
+
],
|
|
83
|
+
};
|
|
84
|
+
// ── Interactive wrapper ─────────────────────────────────────────────────
|
|
85
|
+
function InteractiveBubble({ interaction }) {
|
|
86
|
+
const [submitted, setSubmitted] = useState(false);
|
|
87
|
+
if (submitted)
|
|
88
|
+
return _jsx("p", { className: "text-muted-foreground px-4 text-xs", children: "Submitted!" });
|
|
89
|
+
return _jsx(InteractionBubble, { interaction: interaction, onSubmit: () => setSubmitted(true) });
|
|
90
|
+
}
|
|
91
|
+
const noop = () => undefined;
|
|
92
|
+
export const SingleSelect = {
|
|
93
|
+
args: { interaction: colorInteraction, onSubmit: noop },
|
|
94
|
+
render: () => _jsx(InteractiveBubble, { interaction: colorInteraction }),
|
|
95
|
+
};
|
|
96
|
+
export const MultiSelect = {
|
|
97
|
+
args: { interaction: multiSelectInteraction, onSubmit: noop },
|
|
98
|
+
render: () => _jsx(InteractiveBubble, { interaction: multiSelectInteraction }),
|
|
99
|
+
};
|
|
100
|
+
export const TabbedMultiQuestion = {
|
|
101
|
+
args: { interaction: multiQuestionInteraction, onSubmit: noop },
|
|
102
|
+
render: () => _jsx(InteractiveBubble, { interaction: multiQuestionInteraction }),
|
|
103
|
+
};
|
|
104
|
+
export const Submitted = {
|
|
105
|
+
args: { interaction: colorInteraction, onSubmit: noop },
|
|
106
|
+
render: () => _jsx(InteractiveBubble, { interaction: colorInteraction }),
|
|
107
|
+
};
|
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
/** Shape matching UserInteractionData from the agent executor interface. */
|
|
2
|
+
export interface InteractionData {
|
|
3
|
+
toolCallId: string;
|
|
4
|
+
questions: {
|
|
5
|
+
question: string;
|
|
6
|
+
header: string;
|
|
7
|
+
options: {
|
|
8
|
+
label: string;
|
|
9
|
+
description: string;
|
|
10
|
+
preview?: string;
|
|
11
|
+
}[];
|
|
12
|
+
multiSelect: boolean;
|
|
13
|
+
}[];
|
|
14
|
+
}
|
|
1
15
|
interface SessionInfo {
|
|
2
16
|
pid: number | null;
|
|
3
17
|
sessionId: string | null;
|
|
@@ -45,6 +59,8 @@ export declare function useChatRuntime(featureId: string, worktreePath?: string,
|
|
|
45
59
|
stopAgent: () => Promise<void>;
|
|
46
60
|
sessionInfo: SessionInfo | null;
|
|
47
61
|
isChatLoading: boolean;
|
|
62
|
+
pendingInteraction: InteractionData | null;
|
|
63
|
+
respondToInteraction: (answers: Record<string, string>) => Promise<void>;
|
|
48
64
|
};
|
|
49
65
|
export {};
|
|
50
66
|
//# sourceMappingURL=useChatRuntime.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useChatRuntime.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/chat/useChatRuntime.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"useChatRuntime.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/chat/useChatRuntime.ts"],"names":[],"mappings":"AASA,4EAA4E;AAC5E,MAAM,WAAW,eAAe;IAC9B,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE;QACT,QAAQ,EAAE,MAAM,CAAC;QACjB,MAAM,EAAE,MAAM,CAAC;QACf,OAAO,EAAE;YAAE,KAAK,EAAE,MAAM,CAAC;YAAC,WAAW,EAAE,MAAM,CAAC;YAAC,OAAO,CAAC,EAAE,MAAM,CAAA;SAAE,EAAE,CAAC;QACpE,WAAW,EAAE,OAAO,CAAC;KACtB,EAAE,CAAC;CACL;AAYD,UAAU,WAAW;IACnB,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;CAClC;AAkDD,MAAM,WAAW,UAAU;IACzB,4EAA4E;IAC5E,SAAS,EAAE,OAAO,CAAC;IACnB,qFAAqF;IACrF,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAID,MAAM,WAAW,kBAAkB;IACjC,8EAA8E;IAC9E,gBAAgB,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,MAAM,CAAC;IAC/C,4EAA4E;IAC5E,aAAa,CAAC,EAAE,MAAM,IAAI,CAAC;IAC3B,kEAAkE;IAClE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iEAAiE;IACjE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,6EAA6E;IAC7E,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,iEAAiE;AACjE,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,IAAI,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAC5B,SAAS,EAAE,MAAM,EACjB,YAAY,CAAC,EAAE,MAAM,EACrB,OAAO,CAAC,EAAE,kBAAkB;;;;;;;;oCAgXV,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;EAmDzC"}
|
|
@@ -100,6 +100,19 @@ export function useChatRuntime(featureId, worktreePath, options) {
|
|
|
100
100
|
const [awaitingResponse, setAwaitingResponse] = useState(false);
|
|
101
101
|
const awaitingTimerRef = useRef(null);
|
|
102
102
|
const eventSourceRef = useRef(null);
|
|
103
|
+
// ── Interaction state (AskUserQuestion) ─────────────────────────────
|
|
104
|
+
const [pendingInteraction, setPendingInteraction] = useState(null);
|
|
105
|
+
// Sync pending interaction from backend polling (fallback for missed SSE)
|
|
106
|
+
useEffect(() => {
|
|
107
|
+
const backendInteraction = chatState?.pendingInteraction ?? null;
|
|
108
|
+
if (backendInteraction) {
|
|
109
|
+
setPendingInteraction(backendInteraction);
|
|
110
|
+
}
|
|
111
|
+
else if (!backendInteraction && pendingInteraction) {
|
|
112
|
+
// Backend cleared it (e.g. agent continued) — clear local state
|
|
113
|
+
setPendingInteraction(null);
|
|
114
|
+
}
|
|
115
|
+
}, [chatState?.pendingInteraction, pendingInteraction]);
|
|
103
116
|
// Delayed awaiting — only show Thinking bubble after 600ms to avoid flash
|
|
104
117
|
const startAwaiting = useCallback(() => {
|
|
105
118
|
if (awaitingTimerRef.current)
|
|
@@ -163,10 +176,24 @@ export function useChatRuntime(featureId, worktreePath, options) {
|
|
|
163
176
|
// Ignore
|
|
164
177
|
}
|
|
165
178
|
});
|
|
179
|
+
es.addEventListener('interaction', (event) => {
|
|
180
|
+
try {
|
|
181
|
+
const data = JSON.parse(event.data);
|
|
182
|
+
if (data.interaction) {
|
|
183
|
+
cancelAwaiting();
|
|
184
|
+
setPendingInteraction(data.interaction);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
catch {
|
|
188
|
+
// Ignore
|
|
189
|
+
}
|
|
190
|
+
});
|
|
166
191
|
es.addEventListener('done', () => {
|
|
167
192
|
setStatusLog(null);
|
|
168
193
|
cancelAwaiting();
|
|
169
194
|
pushDebug('turn_done');
|
|
195
|
+
// Agent turn completed — clear any lingering interaction state
|
|
196
|
+
setPendingInteraction(null);
|
|
170
197
|
// Refetch first, THEN clear local streaming state so there's no gap
|
|
171
198
|
void queryClient.invalidateQueries({ queryKey: chatQueryKey(featureId) }).then(() => {
|
|
172
199
|
setStreamingText('');
|
|
@@ -335,6 +362,7 @@ export function useChatRuntime(featureId, worktreePath, options) {
|
|
|
335
362
|
setDebugEvents([]);
|
|
336
363
|
setStatusLog(null);
|
|
337
364
|
cancelAwaiting();
|
|
365
|
+
setPendingInteraction(null);
|
|
338
366
|
void queryClient.invalidateQueries({ queryKey: chatQueryKey(featureId) });
|
|
339
367
|
}, [featureId, queryClient, cancelAwaiting]);
|
|
340
368
|
// ── Stop agent ────────────────────────────────────────────────────────
|
|
@@ -347,6 +375,30 @@ export function useChatRuntime(featureId, worktreePath, options) {
|
|
|
347
375
|
cancelAwaiting();
|
|
348
376
|
void queryClient.invalidateQueries({ queryKey: chatQueryKey(featureId) });
|
|
349
377
|
}, [featureId, queryClient, cancelAwaiting]);
|
|
378
|
+
// ── Respond to interaction (AskUserQuestion) ───────────────────────────
|
|
379
|
+
const respondToInteraction = useCallback(async (answers) => {
|
|
380
|
+
// Clear the bubble and status log immediately — answers are persisted as
|
|
381
|
+
// a user message by the backend, shown in conversation history on refetch.
|
|
382
|
+
setPendingInteraction(null);
|
|
383
|
+
setStatusLog(null);
|
|
384
|
+
try {
|
|
385
|
+
const res = await fetch(`/api/interactive/chat/${featureId}/respond`, {
|
|
386
|
+
method: 'POST',
|
|
387
|
+
headers: { 'Content-Type': 'application/json' },
|
|
388
|
+
body: JSON.stringify({ answers }),
|
|
389
|
+
});
|
|
390
|
+
if (!res.ok) {
|
|
391
|
+
// eslint-disable-next-line no-console
|
|
392
|
+
console.error(`[respondToInteraction] failed: ${res.status}`);
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
catch (err) {
|
|
396
|
+
// eslint-disable-next-line no-console
|
|
397
|
+
console.error('[respondToInteraction] error:', err);
|
|
398
|
+
}
|
|
399
|
+
// Refetch to show the persisted user message with answers
|
|
400
|
+
void queryClient.invalidateQueries({ queryKey: chatQueryKey(featureId) });
|
|
401
|
+
}, [featureId, queryClient]);
|
|
350
402
|
// ── Build assistant-ui runtime ──────────────────────────────────────────
|
|
351
403
|
const runtime = useExternalStoreRuntime({
|
|
352
404
|
messages: threadMessages,
|
|
@@ -359,5 +411,14 @@ export function useChatRuntime(featureId, worktreePath, options) {
|
|
|
359
411
|
cancelAwaiting();
|
|
360
412
|
}, [cancelAwaiting]),
|
|
361
413
|
});
|
|
362
|
-
return {
|
|
414
|
+
return {
|
|
415
|
+
runtime,
|
|
416
|
+
status,
|
|
417
|
+
clearChat,
|
|
418
|
+
stopAgent,
|
|
419
|
+
sessionInfo,
|
|
420
|
+
isChatLoading,
|
|
421
|
+
pendingInteraction,
|
|
422
|
+
respondToInteraction,
|
|
423
|
+
};
|
|
363
424
|
}
|
package/dist/src/presentation/web/components/features/control-center/control-center-inner.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"control-center-inner.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/control-center/control-center-inner.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,IAAI,EAAY,MAAM,eAAe,CAAC;AAIpD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uCAAuC,CAAC;AAgC5E,UAAU,uBAAuB;IAC/B,YAAY,EAAE,cAAc,EAAE,CAAC;IAC/B,YAAY,EAAE,IAAI,EAAE,CAAC;CACtB;AAED,wBAAgB,kBAAkB,CAAC,EAAE,YAAY,EAAE,YAAY,EAAE,EAAE,uBAAuB,
|
|
1
|
+
{"version":3,"file":"control-center-inner.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/control-center/control-center-inner.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,IAAI,EAAY,MAAM,eAAe,CAAC;AAIpD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uCAAuC,CAAC;AAgC5E,UAAU,uBAAuB;IAC/B,YAAY,EAAE,cAAc,EAAE,CAAC;IAC/B,YAAY,EAAE,IAAI,EAAE,CAAC;CACtB;AAED,wBAAgB,kBAAkB,CAAC,EAAE,YAAY,EAAE,YAAY,EAAE,EAAE,uBAAuB,2CAiezF"}
|
package/dist/src/presentation/web/components/features/control-center/control-center-inner.js
CHANGED
|
@@ -143,13 +143,28 @@ export function ControlCenterInner({ initialNodes, initialEdges }) {
|
|
|
143
143
|
}, AUTO_FOCUS_DRAWER_DELAY_MS);
|
|
144
144
|
}, 0);
|
|
145
145
|
}, [fitView, guardedNavigate, router]);
|
|
146
|
-
//
|
|
146
|
+
// Smoothly pan/zoom to a specific node after it appears on canvas
|
|
147
|
+
const focusOnNode = useCallback((nodeId) => {
|
|
148
|
+
// Wait for next render so the node exists in the DOM
|
|
149
|
+
setTimeout(() => {
|
|
150
|
+
fitView({
|
|
151
|
+
nodes: [{ id: nodeId }],
|
|
152
|
+
maxZoom: 1.0,
|
|
153
|
+
padding: 0.4,
|
|
154
|
+
duration: 600,
|
|
155
|
+
});
|
|
156
|
+
}, 0);
|
|
157
|
+
}, [fitView]);
|
|
158
|
+
// Wrapper: add repo + auto-focus on the new node
|
|
147
159
|
const addRepoAndFocus = useCallback((path) => {
|
|
148
|
-
const { wasEmpty, repoPath } = handleAddRepository(path);
|
|
160
|
+
const { wasEmpty, repoPath, tempNodeId } = handleAddRepository(path);
|
|
149
161
|
if (wasEmpty) {
|
|
150
162
|
focusAndOpenDrawer(repoPath);
|
|
151
163
|
}
|
|
152
|
-
|
|
164
|
+
else {
|
|
165
|
+
focusOnNode(tempNodeId);
|
|
166
|
+
}
|
|
167
|
+
}, [handleAddRepository, focusAndOpenDrawer, focusOnNode]);
|
|
153
168
|
// Listen for global "add repository" events from the top bar button
|
|
154
169
|
useEffect(() => {
|
|
155
170
|
const handler = (e) => {
|
package/dist/src/presentation/web/components/features/control-center/use-control-center-state.d.ts
CHANGED
|
@@ -12,6 +12,7 @@ export interface ControlCenterState {
|
|
|
12
12
|
handleAddRepository: (path: string) => {
|
|
13
13
|
wasEmpty: boolean;
|
|
14
14
|
repoPath: string;
|
|
15
|
+
tempNodeId: string;
|
|
15
16
|
};
|
|
16
17
|
handleLayout: (direction: LayoutDirection) => void;
|
|
17
18
|
handleArchiveFeature: (featureId: string) => void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-control-center-state.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/control-center/use-control-center-state.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAClE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AACxE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,qCAAqC,CAAC;AAC9E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uCAAuC,CAAC;AAC5E,OAAO,EAGL,KAAK,eAAe,EACrB,MAAM,yBAAyB,CAAC;AAkBjC,OAAO,EAAiB,KAAK,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAM7E,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB,KAAK,EAAE,IAAI,EAAE,CAAC;IACd,aAAa,EAAE,CAAC,OAAO,EAAE,UAAU,CAAC,cAAc,CAAC,EAAE,KAAK,IAAI,CAAC;IAC/D,aAAa,EAAE,CAAC,UAAU,EAAE,UAAU,KAAK,IAAI,CAAC;IAChD,mBAAmB,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK;
|
|
1
|
+
{"version":3,"file":"use-control-center-state.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/control-center/use-control-center-state.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAClE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AACxE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,qCAAqC,CAAC;AAC9E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uCAAuC,CAAC;AAC5E,OAAO,EAGL,KAAK,eAAe,EACrB,MAAM,yBAAyB,CAAC;AAkBjC,OAAO,EAAiB,KAAK,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAM7E,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB,KAAK,EAAE,IAAI,EAAE,CAAC;IACd,aAAa,EAAE,CAAC,OAAO,EAAE,UAAU,CAAC,cAAc,CAAC,EAAE,KAAK,IAAI,CAAC;IAC/D,aAAa,EAAE,CAAC,UAAU,EAAE,UAAU,KAAK,IAAI,CAAC;IAChD,mBAAmB,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK;QACrC,QAAQ,EAAE,OAAO,CAAC;QAClB,QAAQ,EAAE,MAAM,CAAC;QACjB,UAAU,EAAE,MAAM,CAAC;KACpB,CAAC;IACF,YAAY,EAAE,CAAC,SAAS,EAAE,eAAe,KAAK,IAAI,CAAC;IACnD,oBAAoB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAClD,mBAAmB,EAAE,CACnB,SAAS,EAAE,MAAM,EACjB,OAAO,CAAC,EAAE,OAAO,EACjB,aAAa,CAAC,EAAE,OAAO,EACvB,OAAO,CAAC,EAAE,OAAO,KACd,IAAI,CAAC;IACV,kBAAkB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAChD,kBAAkB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAChD,iBAAiB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/C,sBAAsB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IACpD,sBAAsB,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAChE,iBAAiB,EAAE,CACjB,YAAY,EAAE,MAAM,GAAG,IAAI,EAC3B,YAAY,CAAC,EAAE,OAAO,CAAC,eAAe,CAAC,EACvC,QAAQ,CAAC,EAAE,MAAM,KACd,MAAM,CAAC;IACZ,yDAAyD;IACzD,YAAY,EAAE,OAAO,CAAC;IACtB,0CAA0C;IAC1C,eAAe,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACzC,wDAAwD;IACxD,wBAAwB,EAAE,CAAC,aAAa,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;IACxE,gDAAgD;IAChD,iBAAiB,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,kBAAkB,GAAG,SAAS,CAAC;IACtE,0EAA0E;IAC1E,YAAY,EAAE,CAAC,SAAS,EAAE,cAAc,KAAK,IAAI,CAAC;CACnD;AAQD,wBAAgB,qBAAqB,CACnC,YAAY,EAAE,cAAc,EAAE,EAC9B,YAAY,EAAE,IAAI,EAAE,GACnB,kBAAkB,CAilBpB"}
|
package/dist/src/presentation/web/components/features/control-center/use-control-center-state.js
CHANGED
|
@@ -486,7 +486,7 @@ export function useControlCenterState(initialNodes, initialEdges) {
|
|
|
486
486
|
toast.error('Failed to add repository');
|
|
487
487
|
})
|
|
488
488
|
.finally(() => endMutation());
|
|
489
|
-
return { wasEmpty, repoPath: path };
|
|
489
|
+
return { wasEmpty, repoPath: path, tempNodeId: tempId };
|
|
490
490
|
}, [
|
|
491
491
|
addRepositoryToMap,
|
|
492
492
|
removeRepository,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-graph-state.d.ts","sourceRoot":"","sources":["../../../../../src/presentation/web/hooks/use-graph-state.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,IAAI,EAAY,MAAM,eAAe,CAAC;AACpD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uCAAuC,CAAC;AAC5E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AACxE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,qCAAqC,CAAC;AAC9E,OAAO,EAEL,KAAK,YAAY,EAEjB,KAAK,cAAc,EACpB,MAAM,oBAAoB,CAAC;AAG5B,YAAY,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAEzD,MAAM,WAAW,mBAAmB;IAClC,mDAAmD;IACnD,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB,mDAAmD;IACnD,KAAK,EAAE,IAAI,EAAE,CAAC;IACd;;;;OAIG;IACH,SAAS,EAAE,CAAC,QAAQ,EAAE,cAAc,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,IAAI,CAAC;IAClE,uEAAuE;IACvE,aAAa,EAAE,CAAC,aAAa,EAAE,MAAM,EAAE,OAAO,EAAE,kBAAkB,KAAK,IAAI,CAAC;IAC5E,kEAAkE;IAClE,iBAAiB,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,eAAe,EAAE,YAAY,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1F,yDAAyD;IACzD,oBAAoB,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/C,sDAAsD;IACtD,aAAa,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,uDAAuD;IACvD,cAAc,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,KAAK,IAAI,CAAC;IAC9D,2DAA2D;IAC3D,aAAa,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,kBAAkB,KAAK,IAAI,CAAC;IAClE,gCAAgC;IAChC,gBAAgB,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3C,yDAAyD;IACzD,iBAAiB,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,kBAAkB,KAAK,IAAI,CAAC;IACtF,gEAAgE;IAChE,wBAAwB,EAAE,CAAC,aAAa,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;IACxE,yDAAyD;IACzD,iBAAiB,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,kBAAkB,GAAG,SAAS,CAAC;IACtE,+EAA+E;IAC/E,cAAc,EAAE,MAAM,MAAM,CAAC;IAC7B,6EAA6E;IAC7E,YAAY,EAAE,CAAC,SAAS,EAAE,cAAc,KAAK,IAAI,CAAC;IAClD;;;;OAIG;IACH,aAAa,EAAE,MAAM,IAAI,CAAC;IAC1B;;;OAGG;IACH,WAAW,EAAE,CAAC,UAAU,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3C,0EAA0E;IAC1E,UAAU,EAAE,MAAM,OAAO,CAAC;CAC3B;AAuCD,KAAK,kBAAkB,GAAG,OAAO,CAC/B,IAAI,CAAC,eAAe,EAAE,OAAO,GAAG,WAAW,GAAG,MAAM,GAAG,aAAa,CAAC,CACtE,CAAC;AA8BF,wBAAgB,aAAa,CAC3B,YAAY,EAAE,cAAc,EAAE,EAC9B,YAAY,EAAE,IAAI,EAAE,EACpB,YAAY,UAAQ,GACnB,mBAAmB,
|
|
1
|
+
{"version":3,"file":"use-graph-state.d.ts","sourceRoot":"","sources":["../../../../../src/presentation/web/hooks/use-graph-state.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,IAAI,EAAY,MAAM,eAAe,CAAC;AACpD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uCAAuC,CAAC;AAC5E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AACxE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,qCAAqC,CAAC;AAC9E,OAAO,EAEL,KAAK,YAAY,EAEjB,KAAK,cAAc,EACpB,MAAM,oBAAoB,CAAC;AAG5B,YAAY,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAEzD,MAAM,WAAW,mBAAmB;IAClC,mDAAmD;IACnD,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB,mDAAmD;IACnD,KAAK,EAAE,IAAI,EAAE,CAAC;IACd;;;;OAIG;IACH,SAAS,EAAE,CAAC,QAAQ,EAAE,cAAc,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,IAAI,CAAC;IAClE,uEAAuE;IACvE,aAAa,EAAE,CAAC,aAAa,EAAE,MAAM,EAAE,OAAO,EAAE,kBAAkB,KAAK,IAAI,CAAC;IAC5E,kEAAkE;IAClE,iBAAiB,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,eAAe,EAAE,YAAY,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1F,yDAAyD;IACzD,oBAAoB,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/C,sDAAsD;IACtD,aAAa,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,uDAAuD;IACvD,cAAc,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,KAAK,IAAI,CAAC;IAC9D,2DAA2D;IAC3D,aAAa,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,kBAAkB,KAAK,IAAI,CAAC;IAClE,gCAAgC;IAChC,gBAAgB,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3C,yDAAyD;IACzD,iBAAiB,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,kBAAkB,KAAK,IAAI,CAAC;IACtF,gEAAgE;IAChE,wBAAwB,EAAE,CAAC,aAAa,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;IACxE,yDAAyD;IACzD,iBAAiB,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,kBAAkB,GAAG,SAAS,CAAC;IACtE,+EAA+E;IAC/E,cAAc,EAAE,MAAM,MAAM,CAAC;IAC7B,6EAA6E;IAC7E,YAAY,EAAE,CAAC,SAAS,EAAE,cAAc,KAAK,IAAI,CAAC;IAClD;;;;OAIG;IACH,aAAa,EAAE,MAAM,IAAI,CAAC;IAC1B;;;OAGG;IACH,WAAW,EAAE,CAAC,UAAU,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3C,0EAA0E;IAC1E,UAAU,EAAE,MAAM,OAAO,CAAC;CAC3B;AAuCD,KAAK,kBAAkB,GAAG,OAAO,CAC/B,IAAI,CAAC,eAAe,EAAE,OAAO,GAAG,WAAW,GAAG,MAAM,GAAG,aAAa,CAAC,CACtE,CAAC;AA8BF,wBAAgB,aAAa,CAC3B,YAAY,EAAE,cAAc,EAAE,EAC9B,YAAY,EAAE,IAAI,EAAE,EACpB,YAAY,UAAQ,GACnB,mBAAmB,CAicrB"}
|
|
@@ -82,6 +82,9 @@ export function useGraphState(initialNodes, initialEdges, showArchived = false)
|
|
|
82
82
|
// Retained for one extra reconcile cycle so the user sees the deleting state
|
|
83
83
|
// before the node disappears from the canvas.
|
|
84
84
|
const deletingRetainedRef = useRef(new Set());
|
|
85
|
+
// Track deleted repo IDs so reconcile doesn't resurrect them from stale server data.
|
|
86
|
+
// Cleared once reconcile sees the repo is gone from server data.
|
|
87
|
+
const deletedRepoIdsRef = useRef(new Set());
|
|
85
88
|
// Callbacks stored in a ref so changing them doesn't trigger re-render.
|
|
86
89
|
// The stable wrapper object reads from the ref so node closures always use latest callbacks.
|
|
87
90
|
const callbacksRef = useRef({});
|
|
@@ -254,6 +257,17 @@ export function useGraphState(initialNodes, initialEdges, showArchived = false)
|
|
|
254
257
|
setRepoMap((currentRepoMap) => {
|
|
255
258
|
// Start with everything the server returned
|
|
256
259
|
const merged = new Map(newRepoMap);
|
|
260
|
+
// Remove repos that were deleted client-side but the server still returns
|
|
261
|
+
// (stale data). Once the server stops returning the repo, clear the tombstone.
|
|
262
|
+
for (const deletedId of deletedRepoIdsRef.current) {
|
|
263
|
+
if (merged.has(deletedId)) {
|
|
264
|
+
merged.delete(deletedId);
|
|
265
|
+
}
|
|
266
|
+
else {
|
|
267
|
+
// Server confirmed deletion — no longer need the tombstone
|
|
268
|
+
deletedRepoIdsRef.current.delete(deletedId);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
257
271
|
// Build a set of repositoryPaths present in server data for dedup
|
|
258
272
|
const serverPaths = new Set([...newRepoMap.values()].map((e) => e.data.repositoryPath));
|
|
259
273
|
for (const [id, entry] of currentRepoMap) {
|
|
@@ -343,6 +357,7 @@ export function useGraphState(initialNodes, initialEdges, showArchived = false)
|
|
|
343
357
|
}, []);
|
|
344
358
|
const addRepository = useCallback((nodeId, data) => {
|
|
345
359
|
protectedRepoIdsRef.current.add(nodeId);
|
|
360
|
+
deletedRepoIdsRef.current.delete(nodeId);
|
|
346
361
|
setRepoMap((prev) => {
|
|
347
362
|
const next = new Map(prev);
|
|
348
363
|
next.set(nodeId, { nodeId, data });
|
|
@@ -351,6 +366,7 @@ export function useGraphState(initialNodes, initialEdges, showArchived = false)
|
|
|
351
366
|
}, []);
|
|
352
367
|
const removeRepository = useCallback((nodeId) => {
|
|
353
368
|
protectedRepoIdsRef.current.delete(nodeId);
|
|
369
|
+
deletedRepoIdsRef.current.add(nodeId);
|
|
354
370
|
setRepoMap((prev) => {
|
|
355
371
|
if (!prev.has(nodeId))
|
|
356
372
|
return prev;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-turn-statuses.d.ts","sourceRoot":"","sources":["../../../../../src/presentation/web/hooks/use-turn-statuses.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,YAAY,GAAG,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"use-turn-statuses.d.ts","sourceRoot":"","sources":["../../../../../src/presentation/web/hooks/use-turn-statuses.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,YAAY,GAAG,QAAQ,GAAG,gBAAgB,CAAC;AAE7E;;;;GAIG;AACH,wBAAgB,kBAAkB,IAAI,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAY/D;AAED;;GAEG;AACH,wBAAsB,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAEnE"}
|