@shepai/cli 1.163.0 → 1.164.0-pr514.db33061
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/README.md +12 -0
- package/dist/packages/core/src/application/ports/output/agents/interactive-agent-executor.interface.d.ts +3 -1
- 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/repositories/interactive-session-repository.interface.d.ts +19 -0
- package/dist/packages/core/src/application/ports/output/repositories/interactive-session-repository.interface.d.ts.map +1 -1
- package/dist/packages/core/src/application/ports/output/services/interactive-session-service.interface.d.ts +7 -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/send-interactive-message.use-case.d.ts +2 -0
- package/dist/packages/core/src/application/use-cases/interactive/send-interactive-message.use-case.d.ts.map +1 -1
- package/dist/packages/core/src/application/use-cases/interactive/send-interactive-message.use-case.js +1 -1
- package/dist/packages/core/src/infrastructure/persistence/sqlite/migrations/051-add-session-usage-tracking.d.ts +18 -0
- package/dist/packages/core/src/infrastructure/persistence/sqlite/migrations/051-add-session-usage-tracking.d.ts.map +1 -0
- package/dist/packages/core/src/infrastructure/persistence/sqlite/migrations/051-add-session-usage-tracking.js +32 -0
- package/dist/packages/core/src/infrastructure/repositories/sqlite-interactive-session.repository.d.ts +12 -0
- package/dist/packages/core/src/infrastructure/repositories/sqlite-interactive-session.repository.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/repositories/sqlite-interactive-session.repository.js +31 -0
- package/dist/packages/core/src/infrastructure/services/agents/common/executors/claude-code-interactive-executor.service.d.ts +38 -7
- 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 +152 -45
- package/dist/packages/core/src/infrastructure/services/interactive/interactive-session.service.d.ts +17 -1
- 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 +131 -47
- package/dist/src/presentation/web/app/actions/get-git-log.d.ts +44 -0
- package/dist/src/presentation/web/app/actions/get-git-log.d.ts.map +1 -0
- package/dist/src/presentation/web/app/actions/get-git-log.js +125 -0
- package/dist/src/presentation/web/app/actions/open-folder.d.ts.map +1 -1
- package/dist/src/presentation/web/app/actions/open-folder.js +5 -2
- package/dist/src/presentation/web/app/api/interactive/chat/[featureId]/messages/route.d.ts.map +1 -1
- package/dist/src/presentation/web/app/api/interactive/chat/[featureId]/messages/route.js +3 -1
- package/dist/src/presentation/web/components/assistant-ui/thread.js +8 -1
- package/dist/src/presentation/web/components/common/base-drawer/base-drawer.js +1 -1
- package/dist/src/presentation/web/components/common/control-center-drawer/feature-drawer-client.d.ts.map +1 -1
- package/dist/src/presentation/web/components/common/control-center-drawer/feature-drawer-client.js +46 -15
- package/dist/src/presentation/web/components/common/control-center-drawer/repository-drawer-client.d.ts.map +1 -1
- package/dist/src/presentation/web/components/common/control-center-drawer/repository-drawer-client.js +77 -5
- package/dist/src/presentation/web/components/common/control-center-drawer/use-drawer-sync.d.ts.map +1 -1
- package/dist/src/presentation/web/components/common/control-center-drawer/use-drawer-sync.js +11 -0
- package/dist/src/presentation/web/components/common/deployment-status-badge/deployment-status-badge.d.ts.map +1 -1
- package/dist/src/presentation/web/components/common/deployment-status-badge/deployment-status-badge.js +10 -9
- package/dist/src/presentation/web/components/common/feature-drawer-tabs/feature-drawer-tabs.d.ts +5 -1
- package/dist/src/presentation/web/components/common/feature-drawer-tabs/feature-drawer-tabs.d.ts.map +1 -1
- package/dist/src/presentation/web/components/common/feature-drawer-tabs/feature-drawer-tabs.js +24 -13
- package/dist/src/presentation/web/components/common/feature-drawer-tabs/overview-tab.d.ts.map +1 -1
- package/dist/src/presentation/web/components/common/feature-drawer-tabs/overview-tab.js +56 -81
- package/dist/src/presentation/web/components/common/open-action-menu/open-action-menu.d.ts.map +1 -1
- package/dist/src/presentation/web/components/common/open-action-menu/open-action-menu.js +11 -6
- package/dist/src/presentation/web/components/common/repository-node/repository-node.d.ts.map +1 -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 +13 -7
- 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 +98 -7
- package/dist/src/presentation/web/components/features/settings/AgentModelPicker/index.d.ts.map +1 -1
- package/dist/src/presentation/web/components/features/settings/AgentModelPicker/index.js +1 -1
- package/dist/src/presentation/web/components/layouts/app-sidebar/app-sidebar.d.ts.map +1 -1
- package/dist/src/presentation/web/components/layouts/app-sidebar/app-sidebar.js +7 -2
- package/dist/src/presentation/web/hooks/use-animations-enabled.d.ts +6 -0
- package/dist/src/presentation/web/hooks/use-animations-enabled.d.ts.map +1 -0
- package/dist/src/presentation/web/hooks/use-animations-enabled.js +30 -0
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +2 -2
- package/web/.next/BUILD_ID +1 -1
- package/web/.next/build-manifest.json +2 -2
- package/web/.next/fallback-build-manifest.json +2 -2
- package/web/.next/prerender-manifest.json +3 -3
- package/web/.next/required-server-files.js +3 -3
- package/web/.next/required-server-files.json +3 -3
- package/web/.next/server/app/(dashboard)/@drawer/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/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/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/server-reference-manifest.json +37 -37
- 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 +37 -37
- 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/server-reference-manifest.json +69 -54
- package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/[tab]/page.js +1 -1
- 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/server-reference-manifest.json +69 -54
- package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page.js +1 -1
- 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/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/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/server-reference-manifest.json +37 -37
- 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 +37 -37
- 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 +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/server-reference-manifest.json +69 -54
- package/web/.next/server/app/(dashboard)/repository/[repositoryId]/[tab]/page.js +1 -1
- 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/server-reference-manifest.json +69 -54
- package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page.js +1 -1
- 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_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 +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/evidence/route.js.nft.json +1 -1
- package/web/.next/server/app/api/graph-data/route.js +1 -1
- package/web/.next/server/app/api/graph-data/route.js.nft.json +1 -1
- package/web/.next/server/app/api/interactive/chat/[featureId]/messages/route.js.nft.json +1 -1
- 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/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/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/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/chunks/[root-of-the-server]__2b71641f._.js +1 -1
- package/web/.next/server/chunks/[root-of-the-server]__2b71641f._.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]__beda892a._.js → [root-of-the-server]__c78383b1._.js} +2 -2
- package/web/.next/server/chunks/{[root-of-the-server]__beda892a._.js.map → [root-of-the-server]__c78383b1._.js.map} +1 -1
- package/web/.next/server/chunks/ssr/403f9_next_dist_esm_ceb2fa1e._.js +1 -1
- package/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_create-drawer-client_tsx_5e26fc0a._.js +1 -1
- package/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_create-drawer-client_tsx_5e26fc0a._.js.map +1 -1
- package/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_feature-drawer-client_tsx_e9755fc8._.js +3 -3
- 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/{7f428_lucide-react_dist_esm_icons_4b319ae6._.js → 7f428_lucide-react_dist_esm_icons_281e0ef8._.js} +2 -2
- package/web/.next/server/chunks/ssr/7f428_lucide-react_dist_esm_icons_281e0ef8._.js.map +1 -0
- package/web/.next/server/chunks/ssr/7f428_lucide-react_dist_esm_icons_a593f310._.js +3 -0
- package/web/.next/server/chunks/ssr/7f428_lucide-react_dist_esm_icons_a593f310._.js.map +1 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__1abe77bb._.js +2 -2
- package/web/.next/server/chunks/ssr/[root-of-the-server]__1abe77bb._.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]__23b5ca2c._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__357d99f9._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__563e4faf._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__563e4faf._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__7528eb6f._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__7562afc6._.js +2 -2
- package/web/.next/server/chunks/ssr/[root-of-the-server]__7562afc6._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__821a11c1._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__821a11c1._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__86ff0bc5._.js +7 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__86ff0bc5._.js.map +1 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__8b0aac03._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__98740ee4._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__98740ee4._.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]__ba9f9e11._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__ba9f9e11._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__c9777776._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__c9777776._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__e0be67c7._.js +3 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__e0be67c7._.js.map +1 -0
- package/web/.next/server/chunks/ssr/{_8b57edb8._.js → _0020fddd._.js} +2 -2
- package/web/.next/server/chunks/ssr/_0020fddd._.js.map +1 -0
- package/web/.next/server/chunks/ssr/_02e01240._.js +4 -0
- package/web/.next/server/chunks/ssr/_02e01240._.js.map +1 -0
- 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/_16eb4fec._.js +1 -1
- package/web/.next/server/chunks/ssr/_16eb4fec._.js.map +1 -1
- package/web/.next/server/chunks/ssr/_18886033._.js +4 -0
- package/web/.next/server/chunks/ssr/_18886033._.js.map +1 -0
- 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/_4d49a312._.js +3 -0
- package/web/.next/server/chunks/ssr/_4d49a312._.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/_7a6f6a76._.js +3 -0
- package/web/.next/server/chunks/ssr/_7a6f6a76._.js.map +1 -0
- package/web/.next/server/chunks/ssr/{_def82237._.js → _8276397a._.js} +2 -2
- package/web/.next/server/chunks/ssr/{_def82237._.js.map → _8276397a._.js.map} +1 -1
- package/web/.next/server/chunks/ssr/_9215e9ec._.js +3 -0
- package/web/.next/server/chunks/ssr/_9215e9ec._.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 +4 -0
- package/web/.next/server/chunks/ssr/_ad09f271._.js.map +1 -0
- package/web/.next/server/chunks/ssr/_b7a43c05._.js +3 -0
- package/web/.next/server/chunks/ssr/_b7a43c05._.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/_c45aee16._.js +3 -0
- package/web/.next/server/chunks/ssr/_c45aee16._.js.map +1 -0
- package/web/.next/server/chunks/ssr/{_ce97386b._.js → _cc654b75._.js} +3 -3
- package/web/.next/server/chunks/ssr/_cc654b75._.js.map +1 -0
- package/web/.next/server/chunks/ssr/_ea9e1556._.js +4 -0
- package/web/.next/server/chunks/ssr/_ea9e1556._.js.map +1 -0
- 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/{_b881a389._.js → _fdc356bf._.js} +2 -2
- package/web/.next/server/chunks/ssr/_fdc356bf._.js.map +1 -0
- package/web/.next/server/chunks/ssr/b1a17_presentation_web_components_features_settings_settings-page-client_tsx_6ed9d5f8._.js +1 -1
- package/web/.next/server/chunks/ssr/b1a17_presentation_web_components_features_settings_settings-page-client_tsx_6ed9d5f8._.js.map +1 -1
- package/web/.next/server/chunks/ssr/f3a1f_components_common_control-center-drawer_repository-drawer-client_tsx_39a00c03._.js +3 -0
- package/web/.next/server/chunks/ssr/f3a1f_components_common_control-center-drawer_repository-drawer-client_tsx_39a00c03._.js.map +1 -0
- package/web/.next/server/chunks/ssr/node_modules__pnpm_1300ae39._.js +3 -0
- package/web/.next/server/chunks/ssr/node_modules__pnpm_1300ae39._.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_app_actions_open-ide_ts_baaca5d5._.js.map +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_features_tools_tools-page-client_tsx_3d0aa70c._.js +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_components_features_tools_tools-page-client_tsx_3d0aa70c._.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 +190 -154
- package/web/.next/static/chunks/16eea21868510afd.js +5 -0
- package/web/.next/static/chunks/1ad664f7081cf4c0.js +1 -0
- package/web/.next/static/chunks/{0613d3829ce90fe9.js → 4788a37d8c608e30.js} +1 -1
- package/web/.next/static/chunks/4f7d9c08a205bc4e.js +1 -0
- package/web/.next/static/chunks/5d8c83c576ec1a7b.js +1 -0
- package/web/.next/static/chunks/779b5c49587b074e.js +1 -0
- package/web/.next/static/chunks/7cec51e9bd7d1f4f.js +1 -0
- package/web/.next/static/chunks/{780f688b8568331d.js → 7d40e79e524c8d18.js} +2 -2
- package/web/.next/static/chunks/{5f40b5c4f859b573.js → 8094762f5cda4934.js} +1 -1
- package/web/.next/static/chunks/9162bb869b3543e2.js +7 -0
- package/web/.next/static/chunks/940bca62e44f3e90.js +5 -0
- package/web/.next/static/chunks/966eb2688300b7f5.js +1 -0
- package/web/.next/static/chunks/971e52f3f386ccfd.js +1 -0
- package/web/.next/static/chunks/a760d5829014058d.js +1 -0
- package/web/.next/static/chunks/b63e6727c84f30e2.js +1 -0
- package/web/.next/static/chunks/d6a1a06ee3c12489.js +1 -0
- package/web/.next/static/chunks/dedf6ca63c5468fa.js +5 -0
- package/web/.next/static/chunks/e77d053610055e0c.js +1 -0
- package/web/.next/static/chunks/{0d9e3aa7e10cf6e6.js → ee9fe376b60c3cab.js} +2 -2
- package/web/.next/static/chunks/eeadf13c0ea6cbe0.css +1 -0
- package/web/.next/server/chunks/ssr/7f428_lucide-react_dist_esm_icons_4b319ae6._.js.map +0 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__e5ceba65._.js +0 -3
- package/web/.next/server/chunks/ssr/[root-of-the-server]__e5ceba65._.js.map +0 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__e91ffd5e._.js +0 -7
- package/web/.next/server/chunks/ssr/[root-of-the-server]__e91ffd5e._.js.map +0 -1
- package/web/.next/server/chunks/ssr/_075fae20._.js +0 -4
- package/web/.next/server/chunks/ssr/_075fae20._.js.map +0 -1
- package/web/.next/server/chunks/ssr/_125c55af._.js +0 -4
- package/web/.next/server/chunks/ssr/_125c55af._.js.map +0 -1
- package/web/.next/server/chunks/ssr/_391e499a._.js +0 -3
- package/web/.next/server/chunks/ssr/_391e499a._.js.map +0 -1
- package/web/.next/server/chunks/ssr/_573caadf._.js +0 -3
- package/web/.next/server/chunks/ssr/_573caadf._.js.map +0 -1
- package/web/.next/server/chunks/ssr/_628621c7._.js +0 -4
- package/web/.next/server/chunks/ssr/_628621c7._.js.map +0 -1
- package/web/.next/server/chunks/ssr/_68996e5b._.js +0 -3
- package/web/.next/server/chunks/ssr/_68996e5b._.js.map +0 -1
- package/web/.next/server/chunks/ssr/_8b57edb8._.js.map +0 -1
- package/web/.next/server/chunks/ssr/_9412b27f._.js +0 -4
- package/web/.next/server/chunks/ssr/_9412b27f._.js.map +0 -1
- package/web/.next/server/chunks/ssr/_ac4a3873._.js +0 -3
- package/web/.next/server/chunks/ssr/_ac4a3873._.js.map +0 -1
- package/web/.next/server/chunks/ssr/_b881a389._.js.map +0 -1
- package/web/.next/server/chunks/ssr/_ce97386b._.js.map +0 -1
- package/web/.next/server/chunks/ssr/_cfbd1d7e._.js +0 -3
- package/web/.next/server/chunks/ssr/_cfbd1d7e._.js.map +0 -1
- package/web/.next/server/chunks/ssr/node_modules__pnpm_8ec2c790._.js +0 -3
- package/web/.next/server/chunks/ssr/node_modules__pnpm_8ec2c790._.js.map +0 -1
- package/web/.next/static/chunks/0a79dfbb8486b66e.js +0 -5
- package/web/.next/static/chunks/14d9d9181bb4e337.js +0 -1
- package/web/.next/static/chunks/4581eaf51543601d.js +0 -1
- package/web/.next/static/chunks/47477ed4c5871747.js +0 -1
- package/web/.next/static/chunks/74db65fa7bfb80bd.js +0 -1
- package/web/.next/static/chunks/8b64414cdb4a4dc7.js +0 -1
- package/web/.next/static/chunks/bf55fb50a69f7350.js +0 -5
- package/web/.next/static/chunks/c04ada25ace6f30c.js +0 -1
- package/web/.next/static/chunks/c3a67566f78b5bc3.js +0 -1
- package/web/.next/static/chunks/ca8752df0e809c1b.js +0 -7
- package/web/.next/static/chunks/d2cbeefbc8967b16.js +0 -1
- package/web/.next/static/chunks/d39ae882d080aa52.js +0 -1
- package/web/.next/static/chunks/d6e702c209c413ce.js +0 -5
- package/web/.next/static/chunks/dbfbd9d9ee5eb2d0.js +0 -1
- package/web/.next/static/chunks/dc39dd4276779dec.js +0 -1
- package/web/.next/static/chunks/e779296e738a812b.css +0 -1
- /package/web/.next/static/{qfCnoWSr4qmt2_dT28B-O → lQkUWQQS5aR4vq6WUZ2yr}/_buildManifest.js +0 -0
- /package/web/.next/static/{qfCnoWSr4qmt2_dT28B-O → lQkUWQQS5aR4vq6WUZ2yr}/_clientMiddlewareManifest.json +0 -0
- /package/web/.next/static/{qfCnoWSr4qmt2_dT28B-O → lQkUWQQS5aR4vq6WUZ2yr}/_ssgManifest.js +0 -0
package/dist/packages/core/src/infrastructure/services/interactive/interactive-session.service.js
CHANGED
|
@@ -44,6 +44,14 @@ export class InteractiveSessionService {
|
|
|
44
44
|
sessions = new Map();
|
|
45
45
|
/** Cached agentSessionIds from stopped sessions, keyed by featureId. */
|
|
46
46
|
stoppedAgentSessionIds = new Map();
|
|
47
|
+
/**
|
|
48
|
+
* Feature-level subscribers that survive session restarts.
|
|
49
|
+
*
|
|
50
|
+
* Unlike session-level subscribers (in SessionState.subscribers), these
|
|
51
|
+
* persist when a session dies and a new one boots. SSE connections
|
|
52
|
+
* subscribe here so they continue receiving events from new sessions.
|
|
53
|
+
*/
|
|
54
|
+
featureSubscribers = new Map();
|
|
47
55
|
constructor(sessionRepo, messageRepo, executorFactory, featureRepo, contextBuilder) {
|
|
48
56
|
this.sessionRepo = sessionRepo;
|
|
49
57
|
this.messageRepo = messageRepo;
|
|
@@ -181,9 +189,10 @@ export class InteractiveSessionService {
|
|
|
181
189
|
// Create the interactive executor and session
|
|
182
190
|
const executor = this.executorFactory.createInteractiveExecutor(resolvedAgentType, authConfig);
|
|
183
191
|
let handle;
|
|
184
|
-
|
|
192
|
+
const previousAgentSessionId = state.agentSessionId;
|
|
193
|
+
if (previousAgentSessionId) {
|
|
185
194
|
// Resume existing SDK session
|
|
186
|
-
handle = await executor.resumeSession(
|
|
195
|
+
handle = await executor.resumeSession(previousAgentSessionId, {
|
|
187
196
|
cwd: worktreePath,
|
|
188
197
|
model: state.model,
|
|
189
198
|
systemPrompt: context,
|
|
@@ -218,7 +227,7 @@ export class InteractiveSessionService {
|
|
|
218
227
|
if (event.content) {
|
|
219
228
|
greetingText += event.content;
|
|
220
229
|
state.currentAssistantBuffer += event.content;
|
|
221
|
-
|
|
230
|
+
this.notify(state, { delta: event.content, done: false });
|
|
222
231
|
}
|
|
223
232
|
break;
|
|
224
233
|
case 'tool_use':
|
|
@@ -226,12 +235,12 @@ export class InteractiveSessionService {
|
|
|
226
235
|
const toolLabel = event.label;
|
|
227
236
|
const toolDetail = event.detail;
|
|
228
237
|
void this.persistToolEvent(state, toolLabel, toolDetail);
|
|
229
|
-
|
|
238
|
+
this.notify(state, {
|
|
230
239
|
delta: '',
|
|
231
240
|
done: false,
|
|
232
241
|
log: `Using tool: ${toolLabel}`,
|
|
233
242
|
activity: { kind: 'tool_use', label: toolLabel, detail: toolDetail },
|
|
234
|
-
})
|
|
243
|
+
});
|
|
235
244
|
}
|
|
236
245
|
break;
|
|
237
246
|
case 'tool_result':
|
|
@@ -239,18 +248,18 @@ export class InteractiveSessionService {
|
|
|
239
248
|
const resultLabel = event.label;
|
|
240
249
|
const resultDetail = event.detail;
|
|
241
250
|
void this.persistToolEvent(state, resultLabel, resultDetail);
|
|
242
|
-
|
|
251
|
+
this.notify(state, {
|
|
243
252
|
delta: '',
|
|
244
253
|
done: false,
|
|
245
254
|
log: `Completed: ${resultLabel}`,
|
|
246
255
|
activity: { kind: 'tool_result', label: resultLabel, detail: resultDetail },
|
|
247
|
-
})
|
|
256
|
+
});
|
|
248
257
|
}
|
|
249
258
|
break;
|
|
250
259
|
case 'status':
|
|
251
260
|
if (event.content) {
|
|
252
261
|
const statusContent = event.content;
|
|
253
|
-
|
|
262
|
+
this.notify(state, { delta: '', done: false, log: statusContent });
|
|
254
263
|
}
|
|
255
264
|
break;
|
|
256
265
|
case 'done': {
|
|
@@ -259,6 +268,15 @@ export class InteractiveSessionService {
|
|
|
259
268
|
// Capture the SDK session ID (available after first message exchange)
|
|
260
269
|
const sdkSessionId = handle.sessionId;
|
|
261
270
|
if (sdkSessionId) {
|
|
271
|
+
// Detect CWD mismatch: if we tried to resume but got a different
|
|
272
|
+
// session ID, the SDK silently created a fresh session (typically
|
|
273
|
+
// because the cwd changed or session JSONL was lost).
|
|
274
|
+
if (previousAgentSessionId && sdkSessionId !== previousAgentSessionId) {
|
|
275
|
+
// eslint-disable-next-line no-console
|
|
276
|
+
console.warn(`[InteractiveSession] Session resume mismatch for feature ${featureId}: ` +
|
|
277
|
+
`expected ${previousAgentSessionId}, got ${sdkSessionId}. ` +
|
|
278
|
+
`SDK created a fresh session (likely cwd changed or session expired).`);
|
|
279
|
+
}
|
|
262
280
|
state.agentSessionId = sdkSessionId;
|
|
263
281
|
// Persist to DB so it survives service restarts
|
|
264
282
|
void this.sessionRepo.updateAgentSessionId(state.sessionId, sdkSessionId);
|
|
@@ -283,7 +301,7 @@ export class InteractiveSessionService {
|
|
|
283
301
|
state.currentAssistantBuffer = '';
|
|
284
302
|
state.toolEventsLog = [];
|
|
285
303
|
// Notify subscribers of end-of-turn
|
|
286
|
-
|
|
304
|
+
this.notify(state, { delta: '', done: true });
|
|
287
305
|
// Start idle timer now that the session is live
|
|
288
306
|
this.resetTimer(state);
|
|
289
307
|
return; // Boot complete
|
|
@@ -434,7 +452,7 @@ export class InteractiveSessionService {
|
|
|
434
452
|
if (event.content) {
|
|
435
453
|
responseText += event.content;
|
|
436
454
|
state.currentAssistantBuffer += event.content;
|
|
437
|
-
|
|
455
|
+
this.notify(state, { delta: event.content, done: false });
|
|
438
456
|
}
|
|
439
457
|
break;
|
|
440
458
|
case 'tool_use':
|
|
@@ -442,12 +460,12 @@ export class InteractiveSessionService {
|
|
|
442
460
|
const toolLabel = event.label;
|
|
443
461
|
const toolDetail = event.detail;
|
|
444
462
|
void this.persistToolEvent(state, toolLabel, toolDetail);
|
|
445
|
-
|
|
463
|
+
this.notify(state, {
|
|
446
464
|
delta: '',
|
|
447
465
|
done: false,
|
|
448
466
|
log: `Using tool: ${toolLabel}`,
|
|
449
467
|
activity: { kind: 'tool_use', label: toolLabel, detail: toolDetail },
|
|
450
|
-
})
|
|
468
|
+
});
|
|
451
469
|
}
|
|
452
470
|
break;
|
|
453
471
|
case 'tool_result':
|
|
@@ -455,18 +473,18 @@ export class InteractiveSessionService {
|
|
|
455
473
|
const resultLabel = event.label;
|
|
456
474
|
const resultDetail = event.detail;
|
|
457
475
|
void this.persistToolEvent(state, resultLabel, resultDetail);
|
|
458
|
-
|
|
476
|
+
this.notify(state, {
|
|
459
477
|
delta: '',
|
|
460
478
|
done: false,
|
|
461
479
|
log: `Completed: ${resultLabel}`,
|
|
462
480
|
activity: { kind: 'tool_result', label: resultLabel, detail: resultDetail },
|
|
463
|
-
})
|
|
481
|
+
});
|
|
464
482
|
}
|
|
465
483
|
break;
|
|
466
484
|
case 'status':
|
|
467
485
|
if (event.content) {
|
|
468
486
|
const statusContent = event.content;
|
|
469
|
-
|
|
487
|
+
this.notify(state, { delta: '', done: false, log: statusContent });
|
|
470
488
|
}
|
|
471
489
|
break;
|
|
472
490
|
case 'done': {
|
|
@@ -486,17 +504,39 @@ export class InteractiveSessionService {
|
|
|
486
504
|
await this.messageRepo.create(msg);
|
|
487
505
|
state.currentAssistantBuffer = '';
|
|
488
506
|
state.toolEventsLog = [];
|
|
507
|
+
// Accumulate usage from this turn
|
|
508
|
+
if (event.usage) {
|
|
509
|
+
void this.sessionRepo.accumulateUsage(state.sessionId, {
|
|
510
|
+
costUsd: event.usage.costUsd ?? 0,
|
|
511
|
+
inputTokens: event.usage.inputTokens ?? 0,
|
|
512
|
+
outputTokens: event.usage.outputTokens ?? 0,
|
|
513
|
+
turns: event.usage.numTurns ?? 1,
|
|
514
|
+
});
|
|
515
|
+
}
|
|
489
516
|
// Mark as unread — if user has the chat open, the frontend
|
|
490
517
|
// will immediately call markRead to clear it
|
|
491
518
|
void this.sessionRepo.updateTurnStatus(state.sessionId, 'unread');
|
|
492
519
|
// Notify subscribers of end-of-turn
|
|
493
|
-
|
|
520
|
+
this.notify(state, { delta: '', done: true });
|
|
494
521
|
return; // Turn complete
|
|
495
522
|
}
|
|
496
523
|
case 'error':
|
|
497
524
|
// eslint-disable-next-line no-console
|
|
498
525
|
console.error(`[InteractiveSession] agent error during turn for session ${state.sessionId}:`, event.content);
|
|
499
|
-
|
|
526
|
+
// Accumulate usage even on errors — cost was still incurred
|
|
527
|
+
if (event.usage) {
|
|
528
|
+
void this.sessionRepo.accumulateUsage(state.sessionId, {
|
|
529
|
+
costUsd: event.usage.costUsd ?? 0,
|
|
530
|
+
inputTokens: event.usage.inputTokens ?? 0,
|
|
531
|
+
outputTokens: event.usage.outputTokens ?? 0,
|
|
532
|
+
turns: event.usage.numTurns ?? 1,
|
|
533
|
+
});
|
|
534
|
+
}
|
|
535
|
+
this.notify(state, {
|
|
536
|
+
delta: '',
|
|
537
|
+
done: true,
|
|
538
|
+
log: `Error: ${event.content ?? 'unknown'}`,
|
|
539
|
+
});
|
|
500
540
|
break;
|
|
501
541
|
case 'init':
|
|
502
542
|
// The SDK emits init on every turn, but we only show "Session started"
|
|
@@ -504,32 +544,36 @@ export class InteractiveSessionService {
|
|
|
504
544
|
// spamming the chat with repeated session-started messages.
|
|
505
545
|
break;
|
|
506
546
|
case 'api_retry':
|
|
507
|
-
|
|
547
|
+
this.notify(state, {
|
|
548
|
+
delta: '',
|
|
549
|
+
done: false,
|
|
550
|
+
log: event.content ?? 'Retrying API call...',
|
|
551
|
+
});
|
|
508
552
|
break;
|
|
509
553
|
case 'rate_limit':
|
|
510
|
-
|
|
554
|
+
this.notify(state, { delta: '', done: false, log: event.content ?? 'Rate limited' });
|
|
511
555
|
break;
|
|
512
556
|
case 'task_started':
|
|
513
557
|
if (event.content) {
|
|
514
558
|
void this.persistToolEvent(state, 'Subtask started', event.content);
|
|
515
|
-
|
|
559
|
+
this.notify(state, {
|
|
516
560
|
delta: '',
|
|
517
561
|
done: false,
|
|
518
562
|
log: `Subtask: ${event.content}`,
|
|
519
563
|
activity: { kind: 'system', label: 'Subtask started', detail: event.content },
|
|
520
|
-
})
|
|
564
|
+
});
|
|
521
565
|
}
|
|
522
566
|
break;
|
|
523
567
|
case 'task_progress':
|
|
524
568
|
if (event.content) {
|
|
525
|
-
|
|
569
|
+
this.notify(state, { delta: '', done: false, log: `Subtask: ${event.content}` });
|
|
526
570
|
}
|
|
527
571
|
break;
|
|
528
572
|
case 'task_done':
|
|
529
573
|
if (event.content) {
|
|
530
574
|
const taskStatus = event.detail ?? 'completed';
|
|
531
575
|
void this.persistToolEvent(state, `Subtask ${taskStatus}`, event.content);
|
|
532
|
-
|
|
576
|
+
this.notify(state, {
|
|
533
577
|
delta: '',
|
|
534
578
|
done: false,
|
|
535
579
|
log: `Subtask ${taskStatus}: ${event.content}`,
|
|
@@ -538,7 +582,7 @@ export class InteractiveSessionService {
|
|
|
538
582
|
label: `Subtask ${taskStatus}`,
|
|
539
583
|
detail: event.content,
|
|
540
584
|
},
|
|
541
|
-
})
|
|
585
|
+
});
|
|
542
586
|
}
|
|
543
587
|
break;
|
|
544
588
|
}
|
|
@@ -563,14 +607,18 @@ export class InteractiveSessionService {
|
|
|
563
607
|
await this.messageRepo.create(msg);
|
|
564
608
|
state.currentAssistantBuffer = '';
|
|
565
609
|
state.toolEventsLog = [];
|
|
566
|
-
|
|
610
|
+
this.notify(state, { delta: '', done: true });
|
|
567
611
|
}
|
|
568
612
|
else if (!responseText) {
|
|
569
613
|
// Stream ended without any response — SDK session likely died.
|
|
570
614
|
// Mark as error so the next message triggers a fresh session.
|
|
571
615
|
// eslint-disable-next-line no-console
|
|
572
616
|
console.error(`[InteractiveSession] stream ended without response for session ${state.sessionId} — session may have died`);
|
|
573
|
-
|
|
617
|
+
this.notify(state, {
|
|
618
|
+
delta: '',
|
|
619
|
+
done: true,
|
|
620
|
+
log: 'Session disconnected — will restart on next message',
|
|
621
|
+
});
|
|
574
622
|
if (state.agentSessionId) {
|
|
575
623
|
this.stoppedAgentSessionIds.set(state.featureId, state.agentSessionId);
|
|
576
624
|
}
|
|
@@ -629,7 +677,7 @@ export class InteractiveSessionService {
|
|
|
629
677
|
// ---------------------------------------------------------------------------
|
|
630
678
|
// Feature-scoped API (frontend doesn't manage sessions)
|
|
631
679
|
// ---------------------------------------------------------------------------
|
|
632
|
-
async sendUserMessage(featureId, content, worktreePath) {
|
|
680
|
+
async sendUserMessage(featureId, content, worktreePath, model, agentType) {
|
|
633
681
|
// 1. Persist user message to DB immediately — this is the source of truth
|
|
634
682
|
const now = new Date();
|
|
635
683
|
const userMsg = {
|
|
@@ -642,7 +690,21 @@ export class InteractiveSessionService {
|
|
|
642
690
|
};
|
|
643
691
|
await this.messageRepo.create(userMsg);
|
|
644
692
|
// 2. Find active session for this feature
|
|
645
|
-
|
|
693
|
+
let state = this.findActiveStateForFeature(featureId);
|
|
694
|
+
// If the caller requested a different model/agent than the running session,
|
|
695
|
+
// silently stop the current session so a new one boots with the new config.
|
|
696
|
+
// Also clear the cached agentSessionId so we create a fresh SDK session
|
|
697
|
+
// instead of resuming the old one (which would keep the old model).
|
|
698
|
+
if (state && model && state.model !== model) {
|
|
699
|
+
await this.stopSession(state.sessionId);
|
|
700
|
+
this.stoppedAgentSessionIds.delete(featureId);
|
|
701
|
+
state = undefined;
|
|
702
|
+
}
|
|
703
|
+
else if (state && agentType && state.agentType !== agentType) {
|
|
704
|
+
await this.stopSession(state.sessionId);
|
|
705
|
+
this.stoppedAgentSessionIds.delete(featureId);
|
|
706
|
+
state = undefined;
|
|
707
|
+
}
|
|
646
708
|
if (state) {
|
|
647
709
|
const dbSession = await this.sessionRepo.findById(state.sessionId);
|
|
648
710
|
if (dbSession?.status === InteractiveSessionStatus.ready) {
|
|
@@ -674,7 +736,7 @@ export class InteractiveSessionService {
|
|
|
674
736
|
await this.sessionRepo.updateStatus(dbSession.id, InteractiveSessionStatus.stopped, new Date());
|
|
675
737
|
}
|
|
676
738
|
// Boot a new session — startSession will find the agentSessionId from DB
|
|
677
|
-
const session = await this.startSession(featureId, worktreePath);
|
|
739
|
+
const session = await this.startSession(featureId, worktreePath, model, agentType);
|
|
678
740
|
const newState = this.sessions.get(session.id);
|
|
679
741
|
if (newState) {
|
|
680
742
|
newState.pendingUserContent = content;
|
|
@@ -698,6 +760,7 @@ export class InteractiveSessionService {
|
|
|
698
760
|
}
|
|
699
761
|
// Resolve model display: explicit override > default
|
|
700
762
|
const displayModel = state.model ?? 'claude-sonnet-4-6';
|
|
763
|
+
const usage = await this.sessionRepo.getUsage(state.sessionId);
|
|
701
764
|
sessionInfo = {
|
|
702
765
|
pid: null, // SDK manages process internally
|
|
703
766
|
sessionId: state.agentSessionId ?? state.sessionId,
|
|
@@ -709,6 +772,9 @@ export class InteractiveSessionService {
|
|
|
709
772
|
lastActivityAt: dbSession?.lastActivityAt
|
|
710
773
|
? new Date(dbSession.lastActivityAt).toISOString()
|
|
711
774
|
: new Date().toISOString(),
|
|
775
|
+
totalCostUsd: usage?.totalCostUsd ?? null,
|
|
776
|
+
totalInputTokens: usage?.totalInputTokens ?? null,
|
|
777
|
+
totalOutputTokens: usage?.totalOutputTokens ?? null,
|
|
712
778
|
};
|
|
713
779
|
}
|
|
714
780
|
else {
|
|
@@ -719,6 +785,7 @@ export class InteractiveSessionService {
|
|
|
719
785
|
// Show DB info even without live process (process was lost on restart)
|
|
720
786
|
if (latest.status !== InteractiveSessionStatus.stopped &&
|
|
721
787
|
latest.status !== InteractiveSessionStatus.error) {
|
|
788
|
+
const latestUsage = await this.sessionRepo.getUsage(latest.id);
|
|
722
789
|
sessionInfo = {
|
|
723
790
|
pid: null,
|
|
724
791
|
sessionId: latest.id,
|
|
@@ -730,6 +797,9 @@ export class InteractiveSessionService {
|
|
|
730
797
|
lastActivityAt: latest.lastActivityAt
|
|
731
798
|
? new Date(latest.lastActivityAt).toISOString()
|
|
732
799
|
: new Date().toISOString(),
|
|
800
|
+
totalCostUsd: latestUsage?.totalCostUsd ?? null,
|
|
801
|
+
totalInputTokens: latestUsage?.totalInputTokens ?? null,
|
|
802
|
+
totalOutputTokens: latestUsage?.totalOutputTokens ?? null,
|
|
733
803
|
};
|
|
734
804
|
}
|
|
735
805
|
}
|
|
@@ -752,29 +822,26 @@ export class InteractiveSessionService {
|
|
|
752
822
|
return { messages, sessionStatus, streamingText, sessionInfo, turnStatus };
|
|
753
823
|
}
|
|
754
824
|
subscribeByFeature(featureId, onChunk) {
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
825
|
+
// Subscribe at the feature level so the callback survives session restarts.
|
|
826
|
+
// When a session dies (idle timeout, error) and a new one boots, the SSE
|
|
827
|
+
// connection keeps receiving events from the new session automatically.
|
|
828
|
+
let subs = this.featureSubscribers.get(featureId);
|
|
829
|
+
if (!subs) {
|
|
830
|
+
subs = new Set();
|
|
831
|
+
this.featureSubscribers.set(featureId, subs);
|
|
832
|
+
}
|
|
833
|
+
subs.add(onChunk);
|
|
834
|
+
return () => {
|
|
835
|
+
subs.delete(onChunk);
|
|
836
|
+
if (subs.size === 0) {
|
|
837
|
+
this.featureSubscribers.delete(featureId);
|
|
838
|
+
}
|
|
839
|
+
};
|
|
762
840
|
}
|
|
763
841
|
async stopByFeature(featureId) {
|
|
764
842
|
const state = this.findActiveStateForFeature(featureId);
|
|
765
843
|
if (!state)
|
|
766
844
|
return;
|
|
767
|
-
// Persist a system message before killing
|
|
768
|
-
const msg = {
|
|
769
|
-
id: crypto.randomUUID(),
|
|
770
|
-
featureId,
|
|
771
|
-
sessionId: state.sessionId,
|
|
772
|
-
role: InteractiveMessageRole.assistant,
|
|
773
|
-
content: '**Session stopped by user**',
|
|
774
|
-
createdAt: new Date(),
|
|
775
|
-
updatedAt: new Date(),
|
|
776
|
-
};
|
|
777
|
-
await this.messageRepo.create(msg);
|
|
778
845
|
await this.stopSession(state.sessionId);
|
|
779
846
|
}
|
|
780
847
|
async markRead(featureId) {
|
|
@@ -854,6 +921,23 @@ export class InteractiveSessionService {
|
|
|
854
921
|
}
|
|
855
922
|
}
|
|
856
923
|
// ---------------------------------------------------------------------------
|
|
924
|
+
// Event dispatch
|
|
925
|
+
// ---------------------------------------------------------------------------
|
|
926
|
+
/**
|
|
927
|
+
* Dispatch a StreamChunk to all subscribers for a session.
|
|
928
|
+
*
|
|
929
|
+
* Sends to both session-level subscribers (legacy, for sessionId-based
|
|
930
|
+
* subscribe()) and feature-level subscribers (for SSE connections that
|
|
931
|
+
* must survive session restarts).
|
|
932
|
+
*/
|
|
933
|
+
notify(state, chunk) {
|
|
934
|
+
state.subscribers.forEach((sub) => sub(chunk));
|
|
935
|
+
const featureSubs = this.featureSubscribers.get(state.featureId);
|
|
936
|
+
if (featureSubs) {
|
|
937
|
+
featureSubs.forEach((sub) => sub(chunk));
|
|
938
|
+
}
|
|
939
|
+
}
|
|
940
|
+
// ---------------------------------------------------------------------------
|
|
857
941
|
// Timer helpers
|
|
858
942
|
// ---------------------------------------------------------------------------
|
|
859
943
|
/** Start or restart the idle timeout timer for a session. */
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
export interface GitLogEntry {
|
|
2
|
+
hash: string;
|
|
3
|
+
shortHash: string;
|
|
4
|
+
subject: string;
|
|
5
|
+
author: string;
|
|
6
|
+
relativeDate: string;
|
|
7
|
+
branch?: string;
|
|
8
|
+
}
|
|
9
|
+
export interface GitBranchInfo {
|
|
10
|
+
name: string;
|
|
11
|
+
isCurrent: boolean;
|
|
12
|
+
lastCommitDate: string;
|
|
13
|
+
}
|
|
14
|
+
export interface GitRemoteInfo {
|
|
15
|
+
name: string;
|
|
16
|
+
url: string;
|
|
17
|
+
}
|
|
18
|
+
export interface GitWorkingTreeStatus {
|
|
19
|
+
staged: number;
|
|
20
|
+
modified: number;
|
|
21
|
+
untracked: number;
|
|
22
|
+
}
|
|
23
|
+
export interface GitDiffStats {
|
|
24
|
+
filesChanged: number;
|
|
25
|
+
insertions: number;
|
|
26
|
+
deletions: number;
|
|
27
|
+
}
|
|
28
|
+
export interface GitRepoInfo {
|
|
29
|
+
commits: GitLogEntry[];
|
|
30
|
+
branches: GitBranchInfo[];
|
|
31
|
+
remotes: GitRemoteInfo[];
|
|
32
|
+
tags: string[];
|
|
33
|
+
stashCount: number;
|
|
34
|
+
currentBranch: string;
|
|
35
|
+
diffStats: GitDiffStats | null;
|
|
36
|
+
workingTree: GitWorkingTreeStatus;
|
|
37
|
+
error?: string;
|
|
38
|
+
}
|
|
39
|
+
export declare function getGitRepoInfo(repositoryPath: string, commitLimit?: number): Promise<GitRepoInfo>;
|
|
40
|
+
export declare function getGitLog(repositoryPath: string, limit?: number): Promise<{
|
|
41
|
+
entries: GitLogEntry[];
|
|
42
|
+
error?: string;
|
|
43
|
+
}>;
|
|
44
|
+
//# sourceMappingURL=get-git-log.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-git-log.d.ts","sourceRoot":"","sources":["../../../../../../src/presentation/web/app/actions/get-git-log.ts"],"names":[],"mappings":"AAYA,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,OAAO,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,YAAY;IAC3B,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,WAAW,EAAE,CAAC;IACvB,QAAQ,EAAE,aAAa,EAAE,CAAC;IAC1B,OAAO,EAAE,aAAa,EAAE,CAAC;IACzB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,YAAY,GAAG,IAAI,CAAC;IAC/B,WAAW,EAAE,oBAAoB,CAAC;IAClC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,wBAAsB,cAAc,CAClC,cAAc,EAAE,MAAM,EACtB,WAAW,SAAI,GACd,OAAO,CAAC,WAAW,CAAC,CAwHtB;AAGD,wBAAsB,SAAS,CAC7B,cAAc,EAAE,MAAM,EACtB,KAAK,SAAK,GACT,OAAO,CAAC;IAAE,OAAO,EAAE,WAAW,EAAE,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAGrD"}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
'use server';
|
|
2
|
+
import { execFile } from 'node:child_process';
|
|
3
|
+
import { promisify } from 'node:util';
|
|
4
|
+
const execFileAsync = promisify(execFile);
|
|
5
|
+
async function git(cwd, args) {
|
|
6
|
+
const { stdout } = await execFileAsync('git', args, { cwd, timeout: 5000 });
|
|
7
|
+
return stdout.trim();
|
|
8
|
+
}
|
|
9
|
+
export async function getGitRepoInfo(repositoryPath, commitLimit = 8) {
|
|
10
|
+
const empty = {
|
|
11
|
+
commits: [],
|
|
12
|
+
branches: [],
|
|
13
|
+
remotes: [],
|
|
14
|
+
tags: [],
|
|
15
|
+
stashCount: 0,
|
|
16
|
+
currentBranch: '',
|
|
17
|
+
diffStats: null,
|
|
18
|
+
workingTree: { staged: 0, modified: 0, untracked: 0 },
|
|
19
|
+
};
|
|
20
|
+
if (!repositoryPath.trim()) {
|
|
21
|
+
return { ...empty, error: 'Repository path is required' };
|
|
22
|
+
}
|
|
23
|
+
const results = await Promise.allSettled([
|
|
24
|
+
// 0: commits
|
|
25
|
+
git(repositoryPath, [
|
|
26
|
+
'log',
|
|
27
|
+
`--max-count=${commitLimit}`,
|
|
28
|
+
'--format=%H%x00%h%x00%s%x00%an%x00%cr',
|
|
29
|
+
'--no-color',
|
|
30
|
+
]),
|
|
31
|
+
// 1: current branch
|
|
32
|
+
git(repositoryPath, ['branch', '--show-current']),
|
|
33
|
+
// 2: branches with dates
|
|
34
|
+
git(repositoryPath, [
|
|
35
|
+
'branch',
|
|
36
|
+
'--sort=-committerdate',
|
|
37
|
+
'--format=%(HEAD)%(refname:short)%00%(committerdate:relative)',
|
|
38
|
+
'--no-color',
|
|
39
|
+
]),
|
|
40
|
+
// 3: remotes
|
|
41
|
+
git(repositoryPath, ['remote', '-v']),
|
|
42
|
+
// 4: tags (recent 5)
|
|
43
|
+
git(repositoryPath, ['tag', '--sort=-creatordate', '-l', '--format=%(refname:short)']),
|
|
44
|
+
// 5: stash count
|
|
45
|
+
git(repositoryPath, ['stash', 'list']),
|
|
46
|
+
// 6: working tree status
|
|
47
|
+
git(repositoryPath, ['status', '--porcelain']),
|
|
48
|
+
// 7: diff stats (uncommitted)
|
|
49
|
+
git(repositoryPath, ['diff', '--shortstat']),
|
|
50
|
+
]);
|
|
51
|
+
const val = (i) => (results[i].status === 'fulfilled' ? results[i].value : '');
|
|
52
|
+
// Parse commits
|
|
53
|
+
const commits = val(0)
|
|
54
|
+
.split('\n')
|
|
55
|
+
.filter(Boolean)
|
|
56
|
+
.map((line) => {
|
|
57
|
+
const [hash, shortHash, subject, author, relativeDate] = line.split('\0');
|
|
58
|
+
return { hash, shortHash, subject, author, relativeDate };
|
|
59
|
+
});
|
|
60
|
+
const currentBranch = val(1);
|
|
61
|
+
if (commits.length > 0 && currentBranch) {
|
|
62
|
+
commits[0].branch = currentBranch;
|
|
63
|
+
}
|
|
64
|
+
// Parse branches
|
|
65
|
+
const branches = val(2)
|
|
66
|
+
.split('\n')
|
|
67
|
+
.filter(Boolean)
|
|
68
|
+
.slice(0, 10)
|
|
69
|
+
.map((line) => {
|
|
70
|
+
const isCurrent = line.startsWith('*');
|
|
71
|
+
const clean = isCurrent ? line.slice(1) : line;
|
|
72
|
+
const [name, lastCommitDate] = clean.split('\0');
|
|
73
|
+
return { name: name.trim(), isCurrent, lastCommitDate: lastCommitDate?.trim() ?? '' };
|
|
74
|
+
});
|
|
75
|
+
// Parse remotes (dedup fetch/push)
|
|
76
|
+
const remoteMap = new Map();
|
|
77
|
+
val(3)
|
|
78
|
+
.split('\n')
|
|
79
|
+
.filter(Boolean)
|
|
80
|
+
.forEach((line) => {
|
|
81
|
+
const match = line.match(/^(\S+)\s+(\S+)\s+\(fetch\)/);
|
|
82
|
+
if (match) {
|
|
83
|
+
// Strip credentials/tokens from URL before sending to client
|
|
84
|
+
const sanitized = match[2].replace(/\/\/[^@]+@/, '//').replace(/x-access-token:[^@]+@/, '');
|
|
85
|
+
remoteMap.set(match[1], sanitized);
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
const remotes = Array.from(remoteMap, ([name, url]) => ({ name, url }));
|
|
89
|
+
// Parse tags (top 5)
|
|
90
|
+
const tags = val(4).split('\n').filter(Boolean).slice(0, 5);
|
|
91
|
+
// Stash count
|
|
92
|
+
const stashCount = val(5).split('\n').filter(Boolean).length;
|
|
93
|
+
// Working tree status
|
|
94
|
+
const statusLines = val(6).split('\n').filter(Boolean);
|
|
95
|
+
const workingTree = { staged: 0, modified: 0, untracked: 0 };
|
|
96
|
+
for (const line of statusLines) {
|
|
97
|
+
const x = line[0];
|
|
98
|
+
const y = line[1];
|
|
99
|
+
if (x === '?' && y === '?')
|
|
100
|
+
workingTree.untracked++;
|
|
101
|
+
else if (x !== ' ' && x !== '?')
|
|
102
|
+
workingTree.staged++;
|
|
103
|
+
if (y !== ' ' && y !== '?')
|
|
104
|
+
workingTree.modified++;
|
|
105
|
+
}
|
|
106
|
+
// Diff stats
|
|
107
|
+
let diffStats = null;
|
|
108
|
+
const diffLine = val(7);
|
|
109
|
+
if (diffLine) {
|
|
110
|
+
const files = diffLine.match(/(\d+) file/);
|
|
111
|
+
const ins = diffLine.match(/(\d+) insertion/);
|
|
112
|
+
const del = diffLine.match(/(\d+) deletion/);
|
|
113
|
+
diffStats = {
|
|
114
|
+
filesChanged: files ? parseInt(files[1], 10) : 0,
|
|
115
|
+
insertions: ins ? parseInt(ins[1], 10) : 0,
|
|
116
|
+
deletions: del ? parseInt(del[1], 10) : 0,
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
return { commits, branches, remotes, tags, stashCount, currentBranch, diffStats, workingTree };
|
|
120
|
+
}
|
|
121
|
+
// Keep backward compat
|
|
122
|
+
export async function getGitLog(repositoryPath, limit = 10) {
|
|
123
|
+
const info = await getGitRepoInfo(repositoryPath, limit);
|
|
124
|
+
return { entries: info.commits, error: info.error };
|
|
125
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"open-folder.d.ts","sourceRoot":"","sources":["../../../../../../src/presentation/web/app/actions/open-folder.ts"],"names":[],"mappings":"AAiBA,wBAAsB,UAAU,CAC9B,cAAc,EAAE,MAAM,GACrB,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,
|
|
1
|
+
{"version":3,"file":"open-folder.d.ts","sourceRoot":"","sources":["../../../../../../src/presentation/web/app/actions/open-folder.ts"],"names":[],"mappings":"AAiBA,wBAAsB,UAAU,CAC9B,cAAc,EAAE,MAAM,GACrB,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAkC9D"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use server';
|
|
2
2
|
import { existsSync } from 'node:fs';
|
|
3
3
|
import { platform } from 'node:os';
|
|
4
|
-
import { isAbsolute } from 'node:path';
|
|
4
|
+
import { isAbsolute, normalize } from 'node:path';
|
|
5
5
|
import { spawn } from 'node:child_process';
|
|
6
6
|
// Use a record lookup instead of if/else to prevent the bundler from
|
|
7
7
|
// tree-shaking platform branches at build time. Turbopack evaluates
|
|
@@ -27,7 +27,10 @@ export async function openFolder(repositoryPath) {
|
|
|
27
27
|
error: `Unsupported platform: ${platform()}`,
|
|
28
28
|
};
|
|
29
29
|
}
|
|
30
|
-
|
|
30
|
+
// Normalize to platform-native separators — explorer.exe on Windows
|
|
31
|
+
// does not understand forward-slash paths and falls back to Documents.
|
|
32
|
+
const nativePath = normalize(repositoryPath);
|
|
33
|
+
const child = spawn(entry.cmd, entry.args(nativePath), {
|
|
31
34
|
detached: true,
|
|
32
35
|
stdio: 'ignore',
|
|
33
36
|
});
|
package/dist/src/presentation/web/app/api/interactive/chat/[featureId]/messages/route.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../../../../../../../../../src/presentation/web/app/api/interactive/chat/[featureId]/messages/route.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAO3C,eAAO,MAAM,OAAO,kBAAkB,CAAC;AAIvC,UAAU,WAAW;IACnB,MAAM,EAAE,OAAO,CAAC;QAAE,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACxC;AAED,wBAAsB,IAAI,CAAC,OAAO,EAAE,WAAW,EAAE,EAAE,MAAM,EAAE,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC,
|
|
1
|
+
{"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../../../../../../../../../src/presentation/web/app/api/interactive/chat/[featureId]/messages/route.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAO3C,eAAO,MAAM,OAAO,kBAAkB,CAAC;AAIvC,UAAU,WAAW;IACnB,MAAM,EAAE,OAAO,CAAC;QAAE,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACxC;AAED,wBAAsB,IAAI,CAAC,OAAO,EAAE,WAAW,EAAE,EAAE,MAAM,EAAE,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC,CA8C/F;AAED,wBAAsB,MAAM,CAC1B,QAAQ,EAAE,WAAW,EACrB,EAAE,MAAM,EAAE,EAAE,WAAW,GACtB,OAAO,CAAC,YAAY,CAAC,CAgBvB;AAED,wBAAsB,GAAG,CAAC,QAAQ,EAAE,WAAW,EAAE,EAAE,MAAM,EAAE,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC,CAe/F"}
|
|
@@ -18,7 +18,7 @@ export async function POST(request, { params }) {
|
|
|
18
18
|
try {
|
|
19
19
|
const { featureId } = await params;
|
|
20
20
|
const body = (await request.json());
|
|
21
|
-
const { content, worktreePath } = body;
|
|
21
|
+
const { content, worktreePath, model, agentType } = body;
|
|
22
22
|
if (!content || typeof content !== 'string' || content.trim().length === 0) {
|
|
23
23
|
return NextResponse.json({ error: 'content must be a non-empty string' }, { status: 400 });
|
|
24
24
|
}
|
|
@@ -35,6 +35,8 @@ export async function POST(request, { params }) {
|
|
|
35
35
|
featureId,
|
|
36
36
|
content,
|
|
37
37
|
worktreePath: resolvedWorktreePath,
|
|
38
|
+
model: typeof model === 'string' ? model : undefined,
|
|
39
|
+
agentType: typeof agentType === 'string' ? agentType : undefined,
|
|
38
40
|
});
|
|
39
41
|
return NextResponse.json({ message }, { status: 201 });
|
|
40
42
|
}
|
|
@@ -152,6 +152,12 @@ function ThinkingIndicator({ booting }) {
|
|
|
152
152
|
// ── Message metadata (timestamp + relative time) ────────────────────────────
|
|
153
153
|
function MessageMeta() {
|
|
154
154
|
const message = useMessage();
|
|
155
|
+
// Tick every 30s so relative timestamps stay fresh
|
|
156
|
+
const [tick, setTick] = useState(0);
|
|
157
|
+
useEffect(() => {
|
|
158
|
+
const id = setInterval(() => setTick((t) => t + 1), 30_000);
|
|
159
|
+
return () => clearInterval(id);
|
|
160
|
+
}, []);
|
|
155
161
|
const meta = useMemo(() => {
|
|
156
162
|
if (!message?.createdAt)
|
|
157
163
|
return null;
|
|
@@ -162,7 +168,8 @@ function MessageMeta() {
|
|
|
162
168
|
time: date.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }),
|
|
163
169
|
relative: formatRelativeTime(date),
|
|
164
170
|
};
|
|
165
|
-
|
|
171
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
172
|
+
}, [message?.createdAt, tick]);
|
|
166
173
|
if (!meta)
|
|
167
174
|
return null;
|
|
168
175
|
return (_jsx("span", { className: "text-muted-foreground/60 text-[10px]", title: meta.time, children: meta.relative }));
|