@shepai/cli 1.164.0 → 1.164.1-pr516.5c85bb4

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.
Files changed (241) hide show
  1. package/apis/json-schema/StageTimeouts.yaml +7 -2
  2. package/dist/packages/core/src/application/ports/output/agents/interactive-agent-executor.interface.d.ts +3 -1
  3. package/dist/packages/core/src/application/ports/output/agents/interactive-agent-executor.interface.d.ts.map +1 -1
  4. package/dist/packages/core/src/application/ports/output/repositories/interactive-session-repository.interface.d.ts +19 -0
  5. package/dist/packages/core/src/application/ports/output/repositories/interactive-session-repository.interface.d.ts.map +1 -1
  6. package/dist/packages/core/src/application/ports/output/services/interactive-session-service.interface.d.ts +7 -1
  7. package/dist/packages/core/src/application/ports/output/services/interactive-session-service.interface.d.ts.map +1 -1
  8. package/dist/packages/core/src/application/use-cases/interactive/send-interactive-message.use-case.d.ts +2 -0
  9. package/dist/packages/core/src/application/use-cases/interactive/send-interactive-message.use-case.d.ts.map +1 -1
  10. package/dist/packages/core/src/application/use-cases/interactive/send-interactive-message.use-case.js +1 -1
  11. package/dist/packages/core/src/domain/generated/output.d.ts +6 -2
  12. package/dist/packages/core/src/domain/generated/output.d.ts.map +1 -1
  13. package/dist/packages/core/src/infrastructure/persistence/sqlite/mappers/settings.mapper.d.ts +1 -0
  14. package/dist/packages/core/src/infrastructure/persistence/sqlite/mappers/settings.mapper.d.ts.map +1 -1
  15. package/dist/packages/core/src/infrastructure/persistence/sqlite/mappers/settings.mapper.js +3 -0
  16. package/dist/packages/core/src/infrastructure/persistence/sqlite/migrations/051-add-session-usage-tracking.d.ts +18 -0
  17. package/dist/packages/core/src/infrastructure/persistence/sqlite/migrations/051-add-session-usage-tracking.d.ts.map +1 -0
  18. package/dist/packages/core/src/infrastructure/persistence/sqlite/migrations/051-add-session-usage-tracking.js +32 -0
  19. package/dist/packages/core/src/infrastructure/persistence/sqlite/migrations/052-add-stage-timeout-fast-implement-ms.d.ts +15 -0
  20. package/dist/packages/core/src/infrastructure/persistence/sqlite/migrations/052-add-stage-timeout-fast-implement-ms.d.ts.map +1 -0
  21. package/dist/packages/core/src/infrastructure/persistence/sqlite/migrations/052-add-stage-timeout-fast-implement-ms.js +22 -0
  22. package/dist/packages/core/src/infrastructure/repositories/sqlite-interactive-session.repository.d.ts +12 -0
  23. package/dist/packages/core/src/infrastructure/repositories/sqlite-interactive-session.repository.d.ts.map +1 -1
  24. package/dist/packages/core/src/infrastructure/repositories/sqlite-interactive-session.repository.js +31 -0
  25. package/dist/packages/core/src/infrastructure/services/agents/common/executors/claude-code-interactive-executor.service.d.ts +38 -7
  26. package/dist/packages/core/src/infrastructure/services/agents/common/executors/claude-code-interactive-executor.service.d.ts.map +1 -1
  27. package/dist/packages/core/src/infrastructure/services/agents/common/executors/claude-code-interactive-executor.service.js +152 -45
  28. package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/node-helpers.js +2 -2
  29. package/dist/packages/core/src/infrastructure/services/interactive/interactive-session.service.d.ts +17 -1
  30. package/dist/packages/core/src/infrastructure/services/interactive/interactive-session.service.d.ts.map +1 -1
  31. package/dist/packages/core/src/infrastructure/services/interactive/interactive-session.service.js +131 -47
  32. package/dist/src/presentation/web/app/api/interactive/chat/[featureId]/messages/route.d.ts.map +1 -1
  33. package/dist/src/presentation/web/app/api/interactive/chat/[featureId]/messages/route.js +3 -1
  34. package/dist/src/presentation/web/components/assistant-ui/thread.js +8 -1
  35. package/dist/src/presentation/web/components/features/chat/ChatTab.d.ts.map +1 -1
  36. package/dist/src/presentation/web/components/features/chat/ChatTab.js +13 -7
  37. package/dist/src/presentation/web/components/features/chat/useChatRuntime.d.ts +16 -0
  38. package/dist/src/presentation/web/components/features/chat/useChatRuntime.d.ts.map +1 -1
  39. package/dist/src/presentation/web/components/features/chat/useChatRuntime.js +98 -7
  40. package/dist/src/presentation/web/components/features/settings/AgentModelPicker/index.d.ts.map +1 -1
  41. package/dist/src/presentation/web/components/features/settings/AgentModelPicker/index.js +1 -1
  42. package/dist/src/presentation/web/components/features/settings/settings-page-client.d.ts.map +1 -1
  43. package/dist/src/presentation/web/components/features/settings/settings-page-client.js +8 -0
  44. package/dist/src/presentation/web/components/features/settings/settings-page-client.stories.d.ts.map +1 -1
  45. package/dist/src/presentation/web/components/features/settings/settings-page-client.stories.js +1 -0
  46. package/dist/src/presentation/web/components/features/settings/workflow-settings-section.d.ts.map +1 -1
  47. package/dist/src/presentation/web/components/features/settings/workflow-settings-section.js +11 -0
  48. package/dist/src/presentation/web/components/features/settings/workflow-settings-section.stories.d.ts.map +1 -1
  49. package/dist/src/presentation/web/components/features/settings/workflow-settings-section.stories.js +2 -0
  50. package/dist/translations/ar/web.json +2 -0
  51. package/dist/translations/de/web.json +2 -0
  52. package/dist/translations/en/web.json +2 -0
  53. package/dist/translations/es/web.json +2 -0
  54. package/dist/translations/fr/web.json +2 -0
  55. package/dist/translations/he/web.json +2 -0
  56. package/dist/translations/pt/web.json +2 -0
  57. package/dist/translations/ru/web.json +2 -0
  58. package/dist/tsconfig.build.tsbuildinfo +1 -1
  59. package/package.json +2 -2
  60. package/web/.next/BUILD_ID +1 -1
  61. package/web/.next/build-manifest.json +2 -2
  62. package/web/.next/fallback-build-manifest.json +2 -2
  63. package/web/.next/prerender-manifest.json +3 -3
  64. package/web/.next/required-server-files.js +3 -3
  65. package/web/.next/required-server-files.json +3 -3
  66. package/web/.next/server/app/(dashboard)/@drawer/adopt/page/server-reference-manifest.json +29 -29
  67. package/web/.next/server/app/(dashboard)/@drawer/adopt/page.js.nft.json +1 -1
  68. package/web/.next/server/app/(dashboard)/@drawer/adopt/page_client-reference-manifest.js +1 -1
  69. package/web/.next/server/app/(dashboard)/@drawer/chat/page/server-reference-manifest.json +27 -27
  70. package/web/.next/server/app/(dashboard)/@drawer/chat/page.js.nft.json +1 -1
  71. package/web/.next/server/app/(dashboard)/@drawer/chat/page_client-reference-manifest.js +1 -1
  72. package/web/.next/server/app/(dashboard)/@drawer/create/page/server-reference-manifest.json +30 -30
  73. package/web/.next/server/app/(dashboard)/@drawer/create/page.js.nft.json +1 -1
  74. package/web/.next/server/app/(dashboard)/@drawer/create/page_client-reference-manifest.js +1 -1
  75. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page/server-reference-manifest.json +37 -37
  76. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page.js.nft.json +1 -1
  77. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page_client-reference-manifest.js +1 -1
  78. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page/server-reference-manifest.json +37 -37
  79. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page.js.nft.json +1 -1
  80. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page_client-reference-manifest.js +1 -1
  81. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/[tab]/page/server-reference-manifest.json +28 -28
  82. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/[tab]/page.js.nft.json +1 -1
  83. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/[tab]/page_client-reference-manifest.js +1 -1
  84. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page/server-reference-manifest.json +28 -28
  85. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page.js.nft.json +1 -1
  86. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page_client-reference-manifest.js +1 -1
  87. package/web/.next/server/app/(dashboard)/chat/page/server-reference-manifest.json +27 -27
  88. package/web/.next/server/app/(dashboard)/chat/page.js.nft.json +1 -1
  89. package/web/.next/server/app/(dashboard)/chat/page_client-reference-manifest.js +1 -1
  90. package/web/.next/server/app/(dashboard)/create/page/server-reference-manifest.json +30 -30
  91. package/web/.next/server/app/(dashboard)/create/page.js.nft.json +1 -1
  92. package/web/.next/server/app/(dashboard)/create/page_client-reference-manifest.js +1 -1
  93. package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page/server-reference-manifest.json +37 -37
  94. package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page.js.nft.json +1 -1
  95. package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page_client-reference-manifest.js +1 -1
  96. package/web/.next/server/app/(dashboard)/feature/[featureId]/page/server-reference-manifest.json +37 -37
  97. package/web/.next/server/app/(dashboard)/feature/[featureId]/page.js.nft.json +1 -1
  98. package/web/.next/server/app/(dashboard)/feature/[featureId]/page_client-reference-manifest.js +1 -1
  99. package/web/.next/server/app/(dashboard)/page/server-reference-manifest.json +27 -27
  100. package/web/.next/server/app/(dashboard)/page.js.nft.json +1 -1
  101. package/web/.next/server/app/(dashboard)/page_client-reference-manifest.js +1 -1
  102. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/[tab]/page/server-reference-manifest.json +28 -28
  103. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/[tab]/page.js.nft.json +1 -1
  104. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/[tab]/page_client-reference-manifest.js +1 -1
  105. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page/server-reference-manifest.json +28 -28
  106. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page.js.nft.json +1 -1
  107. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page_client-reference-manifest.js +1 -1
  108. package/web/.next/server/app/_global-error.html +2 -2
  109. package/web/.next/server/app/_global-error.rsc +1 -1
  110. package/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  111. package/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  112. package/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  113. package/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  114. package/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  115. package/web/.next/server/app/_not-found/page/server-reference-manifest.json +6 -6
  116. package/web/.next/server/app/_not-found/page.js.nft.json +1 -1
  117. package/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  118. package/web/.next/server/app/settings/page/server-reference-manifest.json +9 -9
  119. package/web/.next/server/app/settings/page.js.nft.json +1 -1
  120. package/web/.next/server/app/settings/page_client-reference-manifest.js +1 -1
  121. package/web/.next/server/app/skills/page/server-reference-manifest.json +11 -11
  122. package/web/.next/server/app/skills/page.js.nft.json +1 -1
  123. package/web/.next/server/app/skills/page_client-reference-manifest.js +1 -1
  124. package/web/.next/server/app/tools/page/server-reference-manifest.json +11 -11
  125. package/web/.next/server/app/tools/page.js.nft.json +1 -1
  126. package/web/.next/server/app/tools/page_client-reference-manifest.js +1 -1
  127. package/web/.next/server/app/version/page/server-reference-manifest.json +6 -6
  128. package/web/.next/server/app/version/page.js.nft.json +1 -1
  129. package/web/.next/server/app/version/page_client-reference-manifest.js +1 -1
  130. package/web/.next/server/chunks/[root-of-the-server]__2b71641f._.js +1 -1
  131. package/web/.next/server/chunks/[root-of-the-server]__2b71641f._.js.map +1 -1
  132. package/web/.next/server/chunks/[root-of-the-server]__a402b567._.js +1 -1
  133. package/web/.next/server/chunks/[root-of-the-server]__c78383b1._.js.map +1 -1
  134. package/web/.next/server/chunks/[root-of-the-server]__cd67a84c._.js.map +1 -1
  135. package/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_create-drawer-client_tsx_5e26fc0a._.js +1 -1
  136. package/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_create-drawer-client_tsx_5e26fc0a._.js.map +1 -1
  137. package/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_feature-drawer-client_tsx_e9755fc8._.js +2 -2
  138. package/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_feature-drawer-client_tsx_e9755fc8._.js.map +1 -1
  139. package/web/.next/server/chunks/ssr/[root-of-the-server]__1abe77bb._.js +2 -2
  140. package/web/.next/server/chunks/ssr/[root-of-the-server]__1abe77bb._.js.map +1 -1
  141. package/web/.next/server/chunks/ssr/[root-of-the-server]__1f389e5d._.js +1 -1
  142. package/web/.next/server/chunks/ssr/[root-of-the-server]__1f389e5d._.js.map +1 -1
  143. package/web/.next/server/chunks/ssr/[root-of-the-server]__357d99f9._.js +1 -1
  144. package/web/.next/server/chunks/ssr/[root-of-the-server]__563e4faf._.js +1 -1
  145. package/web/.next/server/chunks/ssr/[root-of-the-server]__563e4faf._.js.map +1 -1
  146. package/web/.next/server/chunks/ssr/[root-of-the-server]__7562afc6._.js +2 -2
  147. package/web/.next/server/chunks/ssr/[root-of-the-server]__7562afc6._.js.map +1 -1
  148. package/web/.next/server/chunks/ssr/[root-of-the-server]__821a11c1._.js +1 -1
  149. package/web/.next/server/chunks/ssr/[root-of-the-server]__821a11c1._.js.map +1 -1
  150. package/web/.next/server/chunks/ssr/[root-of-the-server]__86ff0bc5._.js +2 -2
  151. package/web/.next/server/chunks/ssr/[root-of-the-server]__86ff0bc5._.js.map +1 -1
  152. package/web/.next/server/chunks/ssr/[root-of-the-server]__8b0aac03._.js +1 -1
  153. package/web/.next/server/chunks/ssr/[root-of-the-server]__98740ee4._.js +1 -1
  154. package/web/.next/server/chunks/ssr/[root-of-the-server]__98740ee4._.js.map +1 -1
  155. package/web/.next/server/chunks/ssr/[root-of-the-server]__b7b96453._.js +1 -1
  156. package/web/.next/server/chunks/ssr/[root-of-the-server]__b7b96453._.js.map +1 -1
  157. package/web/.next/server/chunks/ssr/[root-of-the-server]__ba9f9e11._.js +1 -1
  158. package/web/.next/server/chunks/ssr/[root-of-the-server]__ba9f9e11._.js.map +1 -1
  159. package/web/.next/server/chunks/ssr/[root-of-the-server]__e0be67c7._.js +1 -1
  160. package/web/.next/server/chunks/ssr/[root-of-the-server]__e0be67c7._.js.map +1 -1
  161. package/web/.next/server/chunks/ssr/{_8b57edb8._.js → _0020fddd._.js} +2 -2
  162. package/web/.next/server/chunks/ssr/_0020fddd._.js.map +1 -0
  163. package/web/.next/server/chunks/ssr/_02e01240._.js +1 -1
  164. package/web/.next/server/chunks/ssr/_02e01240._.js.map +1 -1
  165. package/web/.next/server/chunks/ssr/_05c23ad9._.js +1 -1
  166. package/web/.next/server/chunks/ssr/_05c23ad9._.js.map +1 -1
  167. package/web/.next/server/chunks/ssr/_0727935d._.js +1 -1
  168. package/web/.next/server/chunks/ssr/_0727935d._.js.map +1 -1
  169. package/web/.next/server/chunks/ssr/_0dc06d07._.js.map +1 -1
  170. package/web/.next/server/chunks/ssr/_16eb4fec._.js +1 -1
  171. package/web/.next/server/chunks/ssr/_16eb4fec._.js.map +1 -1
  172. package/web/.next/server/chunks/ssr/{_c9f903f2._.js → _17b886d9._.js} +2 -2
  173. package/web/.next/server/chunks/ssr/{_c9f903f2._.js.map → _17b886d9._.js.map} +1 -1
  174. package/web/.next/server/chunks/ssr/_18886033._.js +1 -1
  175. package/web/.next/server/chunks/ssr/_18886033._.js.map +1 -1
  176. package/web/.next/server/chunks/ssr/_22e00a14._.js +1 -1
  177. package/web/.next/server/chunks/ssr/_22e00a14._.js.map +1 -1
  178. package/web/.next/server/chunks/ssr/_5119a3df._.js.map +1 -1
  179. package/web/.next/server/chunks/ssr/_56b9d60f._.js +1 -1
  180. package/web/.next/server/chunks/ssr/_56b9d60f._.js.map +1 -1
  181. package/web/.next/server/chunks/ssr/{_52403a07._.js → _841e9be8._.js} +2 -2
  182. package/web/.next/server/chunks/ssr/{_52403a07._.js.map → _841e9be8._.js.map} +1 -1
  183. package/web/.next/server/chunks/ssr/_9215e9ec._.js +1 -1
  184. package/web/.next/server/chunks/ssr/_9215e9ec._.js.map +1 -1
  185. package/web/.next/server/chunks/ssr/_a5a5901d._.js +1 -1
  186. package/web/.next/server/chunks/ssr/_a5a5901d._.js.map +1 -1
  187. package/web/.next/server/chunks/ssr/_ad09f271._.js +1 -1
  188. package/web/.next/server/chunks/ssr/_ad09f271._.js.map +1 -1
  189. package/web/.next/server/chunks/ssr/_baff78d8._.js +3 -0
  190. package/web/.next/server/chunks/ssr/{_2f8f89fb._.js.map → _baff78d8._.js.map} +1 -1
  191. package/web/.next/server/chunks/ssr/_c3f595c6._.js +1 -1
  192. package/web/.next/server/chunks/ssr/_c3f595c6._.js.map +1 -1
  193. package/web/.next/server/chunks/ssr/_ea9e1556._.js +1 -1
  194. package/web/.next/server/chunks/ssr/_ea9e1556._.js.map +1 -1
  195. package/web/.next/server/chunks/ssr/_f1ba9be6._.js +2 -2
  196. package/web/.next/server/chunks/ssr/_f1ba9be6._.js.map +1 -1
  197. package/web/.next/server/chunks/ssr/_f33cd07e._.js +2 -2
  198. package/web/.next/server/chunks/ssr/_f33cd07e._.js.map +1 -1
  199. package/web/.next/server/chunks/ssr/_f8b45233._.js +1 -1
  200. package/web/.next/server/chunks/ssr/_f8b45233._.js.map +1 -1
  201. package/web/.next/server/chunks/ssr/b1a17_presentation_web_components_features_settings_settings-page-client_tsx_6ed9d5f8._.js +1 -1
  202. package/web/.next/server/chunks/ssr/b1a17_presentation_web_components_features_settings_settings-page-client_tsx_6ed9d5f8._.js.map +1 -1
  203. package/web/.next/server/chunks/ssr/f3a1f_components_common_control-center-drawer_repository-drawer-client_tsx_39a00c03._.js +1 -1
  204. package/web/.next/server/chunks/ssr/f3a1f_components_common_control-center-drawer_repository-drawer-client_tsx_39a00c03._.js.map +1 -1
  205. package/web/.next/server/chunks/ssr/src_presentation_web_app_actions_open-ide_ts_baaca5d5._.js +1 -1
  206. package/web/.next/server/chunks/ssr/src_presentation_web_components_895e5bfa._.js +1 -1
  207. package/web/.next/server/chunks/ssr/src_presentation_web_components_895e5bfa._.js.map +1 -1
  208. package/web/.next/server/chunks/ssr/src_presentation_web_components_features_control-center_7ac3562e._.js +1 -1
  209. package/web/.next/server/chunks/ssr/src_presentation_web_components_features_control-center_7ac3562e._.js.map +1 -1
  210. package/web/.next/server/chunks/ssr/translations_23dd5e7e._.js +1 -1
  211. package/web/.next/server/chunks/ssr/translations_23dd5e7e._.js.map +1 -1
  212. package/web/.next/server/pages/500.html +2 -2
  213. package/web/.next/server/server-reference-manifest.js +1 -1
  214. package/web/.next/server/server-reference-manifest.json +47 -47
  215. package/web/.next/static/chunks/{dc21cf85bfa262a7.js → 09f442ecfccd5e0d.js} +2 -2
  216. package/web/.next/static/chunks/{29f0d874b1fde3d6.js → 16eea21868510afd.js} +2 -2
  217. package/web/.next/static/chunks/{cf75fade434602c6.js → 213188d0bd7e41ea.js} +2 -2
  218. package/web/.next/static/chunks/32a9e594b4ec7c60.js +1 -0
  219. package/web/.next/static/chunks/4989e6b776fe69a4.js +1 -0
  220. package/web/.next/static/chunks/{cf000ba1a3f11439.js → 638b1a351176914f.js} +1 -1
  221. package/web/.next/static/chunks/{498e45f8e05a5491.js → 70a6aa0e6eb56f2d.js} +1 -1
  222. package/web/.next/static/chunks/{d9e4d90ef254da84.js → 76f5ca4fa9ec1883.js} +1 -1
  223. package/web/.next/static/chunks/{ce0316338f7e01e6.js → 97bda8f4052ed0b1.js} +1 -1
  224. package/web/.next/static/chunks/9dc9295e81ddd7f9.js +1 -0
  225. package/web/.next/static/chunks/{25e894a1de46b5fb.js → 9ed313bf5401f956.js} +1 -1
  226. package/web/.next/static/chunks/{ce87ded6cc38b4de.js → a0220f989d9eb10f.js} +1 -1
  227. package/web/.next/static/chunks/c0e13e7d1601bc5d.js +1 -0
  228. package/web/.next/static/chunks/{56955fa252a9f3ed.js → d2ee0c7987eb906e.js} +2 -2
  229. package/web/.next/static/chunks/{a8243f8d06bdcef0.js → dedf6ca63c5468fa.js} +2 -2
  230. package/web/.next/static/chunks/eeadf13c0ea6cbe0.css +1 -0
  231. package/web/.next/static/chunks/{2609c8fc6f14cb26.js → ffc2783191dfcea4.js} +1 -1
  232. package/web/.next/server/chunks/ssr/_2f8f89fb._.js +0 -3
  233. package/web/.next/server/chunks/ssr/_8b57edb8._.js.map +0 -1
  234. package/web/.next/static/chunks/28ae5046faef6cec.js +0 -1
  235. package/web/.next/static/chunks/400e93efac983a76.css +0 -1
  236. package/web/.next/static/chunks/7f491899a2fe2fd7.js +0 -1
  237. package/web/.next/static/chunks/e6398f94cffe9bc2.js +0 -1
  238. package/web/.next/static/chunks/ecfd93d61bf4d933.js +0 -1
  239. /package/web/.next/static/{rav6zzO3q2NtCKwg9XZXP → 5SA0DJ6o7rNc22_hO-cTT}/_buildManifest.js +0 -0
  240. /package/web/.next/static/{rav6zzO3q2NtCKwg9XZXP → 5SA0DJ6o7rNc22_hO-cTT}/_clientMiddlewareManifest.json +0 -0
  241. /package/web/.next/static/{rav6zzO3q2NtCKwg9XZXP → 5SA0DJ6o7rNc22_hO-cTT}/_ssgManifest.js +0 -0
@@ -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
- if (state.agentSessionId) {
192
+ const previousAgentSessionId = state.agentSessionId;
193
+ if (previousAgentSessionId) {
185
194
  // Resume existing SDK session
186
- handle = await executor.resumeSession(state.agentSessionId, {
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
- state.subscribers.forEach((sub) => sub({ delta: event.content, done: false }));
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
- state.subscribers.forEach((sub) => sub({
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
- state.subscribers.forEach((sub) => sub({
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
- state.subscribers.forEach((sub) => sub({ delta: '', done: false, log: statusContent }));
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
- state.subscribers.forEach((sub) => sub({ delta: '', done: true }));
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
- state.subscribers.forEach((sub) => sub({ delta: event.content, done: false }));
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
- state.subscribers.forEach((sub) => sub({
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
- state.subscribers.forEach((sub) => sub({
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
- state.subscribers.forEach((sub) => sub({ delta: '', done: false, log: statusContent }));
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
- state.subscribers.forEach((sub) => sub({ delta: '', done: true }));
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
- state.subscribers.forEach((sub) => sub({ delta: '', done: true, log: `Error: ${event.content ?? 'unknown'}` }));
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
- state.subscribers.forEach((sub) => sub({ delta: '', done: false, log: event.content ?? 'Retrying API call...' }));
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
- state.subscribers.forEach((sub) => sub({ delta: '', done: false, log: event.content ?? 'Rate limited' }));
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
- state.subscribers.forEach((sub) => sub({
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
- state.subscribers.forEach((sub) => sub({ delta: '', done: false, log: `Subtask: ${event.content}` }));
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
- state.subscribers.forEach((sub) => sub({
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
- state.subscribers.forEach((sub) => sub({ delta: '', done: true }));
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
- state.subscribers.forEach((sub) => sub({ delta: '', done: true, log: 'Session disconnected — will restart on next message' }));
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
- const state = this.findActiveStateForFeature(featureId);
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
- const state = this.findActiveStateForFeature(featureId);
756
- if (!state) {
757
- // eslint-disable-next-line @typescript-eslint/no-empty-function
758
- return () => { };
759
- }
760
- state.subscribers.add(onChunk);
761
- return () => state.subscribers.delete(onChunk);
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. */
@@ -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,CAuC/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"}
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
- }, [message?.createdAt]);
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 }));
@@ -1 +1 @@
1
- {"version":3,"file":"ChatTab.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/chat/ChatTab.tsx"],"names":[],"mappings":"AAcA,MAAM,WAAW,YAAY;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,wBAAgB,OAAO,CAAC,EAAE,SAAS,EAAE,YAAY,EAAE,EAAE,YAAY,2CAgGhE"}
1
+ {"version":3,"file":"ChatTab.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/chat/ChatTab.tsx"],"names":[],"mappings":"AAcA,MAAM,WAAW,YAAY;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAID,wBAAgB,OAAO,CAAC,EAAE,SAAS,EAAE,YAAY,EAAE,EAAE,YAAY,2CAwGhE"}
@@ -3,7 +3,7 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
3
3
  import { useCallback, useState } from 'react';
4
4
  import { useTranslation } from 'react-i18next';
5
5
  import { AssistantRuntimeProvider } from '@assistant-ui/react';
6
- import { Trash2, Square, Cpu } from 'lucide-react';
6
+ import { Trash2, Cpu } from 'lucide-react';
7
7
  import { cn } from '../../../lib/utils.js';
8
8
  import { Thread } from '../../assistant-ui/thread.js';
9
9
  import { useAttachments } from '../../../hooks/use-attachments.js';
@@ -11,12 +11,20 @@ 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
+ const IS_DEV = process.env.NODE_ENV === 'development';
14
15
  export function ChatTab({ featureId, worktreePath }) {
15
16
  const [overrideAgent, setOverrideAgent] = useState(undefined);
16
17
  const [overrideModel, setOverrideModel] = useState(undefined);
18
+ const [debugMode, setDebugMode] = useState(false);
17
19
  const att = useAttachments();
18
20
  const contentTransform = useCallback((content) => composeUserInput(content, att.completedAttachments.map((a) => ({ path: a.path, name: a.name, notes: a.notes }))), [att.completedAttachments]);
19
- const { runtime, status, clearChat, stopAgent, sessionInfo, isChatLoading } = useChatRuntime(featureId, worktreePath, { contentTransform, onMessageSent: att.clearAttachments });
21
+ const { runtime, status, clearChat, sessionInfo, isChatLoading } = useChatRuntime(featureId, worktreePath, {
22
+ contentTransform,
23
+ onMessageSent: att.clearAttachments,
24
+ model: overrideModel,
25
+ agentType: overrideAgent,
26
+ debugMode,
27
+ });
20
28
  const handlePickFiles = useCallback(async () => {
21
29
  try {
22
30
  const res = await fetch('/api/dialog/pick-files');
@@ -46,18 +54,16 @@ export function ChatTab({ featureId, worktreePath }) {
46
54
  setOverrideAgent(agent);
47
55
  setOverrideModel(model);
48
56
  }, className: "w-55" }) }));
49
- return (_jsxs("div", { className: "flex h-full min-h-0 flex-col", children: [_jsx(ChatHeader, { sessionInfo: sessionInfo, isAgentActive: status.isRunning, onClear: clearChat, onStop: stopAgent }), _jsx("div", { className: "flex min-h-0 flex-1 flex-col", children: isChatLoading ? (_jsx(ChatSkeleton, {})) : (_jsx(AssistantRuntimeProvider, { runtime: runtime, children: _jsx(Thread, { composer: composer }) })) })] }));
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 }) })) })] }));
50
58
  }
51
59
  // ── Loading skeleton ────────────────────────────────────────────────────────
52
60
  function ChatSkeleton() {
53
61
  return (_jsxs("div", { className: "flex flex-1 flex-col gap-3 p-4 pt-6", children: [_jsxs("div", { className: "flex items-start gap-2.5", children: [_jsx("div", { className: "bg-muted h-6 w-6 animate-pulse rounded-full" }), _jsxs("div", { className: "flex flex-col gap-1.5", children: [_jsx("div", { className: "bg-muted h-4 w-48 animate-pulse rounded-lg" }), _jsx("div", { className: "bg-muted h-4 w-72 animate-pulse rounded-lg" }), _jsx("div", { className: "bg-muted h-4 w-36 animate-pulse rounded-lg" })] })] }), _jsxs("div", { className: "flex items-start gap-2.5", children: [_jsx("div", { className: "bg-muted h-6 w-6 animate-pulse rounded-full" }), _jsx("div", { className: "bg-muted h-4 w-32 animate-pulse rounded-lg" })] }), _jsxs("div", { className: "flex items-start gap-2.5", children: [_jsx("div", { className: "bg-muted h-6 w-6 animate-pulse rounded-full" }), _jsxs("div", { className: "flex flex-col gap-1.5", children: [_jsx("div", { className: "bg-muted h-4 w-56 animate-pulse rounded-lg" }), _jsx("div", { className: "bg-muted h-4 w-64 animate-pulse rounded-lg" })] })] })] }));
54
62
  }
55
63
  // ── Chat header — compact session info + actions ─────────────────────────────
56
- function ChatHeader({ sessionInfo, isAgentActive, onClear, onStop, }) {
64
+ function ChatHeader({ sessionInfo, isAgentActive, onClear, debugMode, onDebugToggle, }) {
57
65
  const { t } = useTranslation('web');
58
- return (_jsxs("div", { className: "flex h-8 shrink-0 items-center border-b px-3", children: [_jsx("div", { className: "flex min-w-0 flex-1 items-center gap-2", children: sessionInfo ? (_jsxs(_Fragment, { children: [isAgentActive ? (_jsx("span", { className: "h-1.5 w-1.5 shrink-0 animate-pulse rounded-full bg-emerald-500" })) : (_jsx(Cpu, { className: "text-muted-foreground/40 h-3 w-3 shrink-0" })), _jsxs("span", { className: "text-muted-foreground font-mono text-[10px]", children: [sessionInfo.model ?? 'agent', sessionInfo.sessionId ? ` · ${sessionInfo.sessionId.slice(0, 8)}` : ''] })] })) : (_jsx("span", { className: "text-muted-foreground/40 text-[11px]", children: t('chat.noSession') })) }), _jsxs("div", { className: "flex items-center gap-1 ps-2", children: [sessionInfo ? (_jsxs(_Fragment, { children: [_jsxs(ToolbarButton, { onClick: () => {
59
- void onStop();
60
- }, title: t('chat.forceStopAgent'), variant: "danger", children: [_jsx(Square, { className: "h-2.5 w-2.5 fill-current" }), _jsx("span", { children: t('chat.stop') })] }), _jsx("span", { className: "text-border mx-0.5", children: "|" })] })) : null, _jsxs(ToolbarButton, { onClick: () => {
66
+ return (_jsxs("div", { className: "flex h-8 shrink-0 items-center border-b px-3", children: [_jsx("div", { className: "flex min-w-0 flex-1 items-center gap-2", children: sessionInfo ? (_jsxs(_Fragment, { children: [isAgentActive ? (_jsx("span", { className: "h-1.5 w-1.5 shrink-0 animate-pulse rounded-full bg-emerald-500" })) : (_jsx(Cpu, { className: "text-muted-foreground/40 h-3 w-3 shrink-0" })), _jsxs("span", { className: "text-muted-foreground font-mono text-[10px]", children: [sessionInfo.model ?? 'agent', sessionInfo.sessionId ? ` · ${sessionInfo.sessionId.slice(0, 8)}` : ''] })] })) : (_jsx("span", { className: "text-muted-foreground/40 text-[11px]", children: t('chat.noSession') })) }), _jsxs("div", { className: "flex items-center gap-1 ps-2", children: [onDebugToggle ? (_jsxs("label", { className: "text-muted-foreground/60 flex cursor-pointer items-center gap-1 text-[10px]", children: [_jsx("input", { type: "checkbox", checked: debugMode, onChange: (e) => onDebugToggle(e.target.checked), className: "h-3 w-3 cursor-pointer rounded" }), "Debug"] })) : null, _jsxs(ToolbarButton, { onClick: () => {
61
67
  void onClear();
62
68
  }, title: t('chat.clearChatHistory'), children: [_jsx(Trash2, { className: "h-2.5 w-2.5" }), _jsx("span", { children: t('chat.clear') })] })] })] }));
63
69
  }
@@ -5,6 +5,9 @@ interface SessionInfo {
5
5
  startedAt: string;
6
6
  idleTimeoutMinutes: number;
7
7
  lastActivityAt: string;
8
+ totalCostUsd: number | null;
9
+ totalInputTokens: number | null;
10
+ totalOutputTokens: number | null;
8
11
  }
9
12
  export interface ChatStatus {
10
13
  /** Whether the agent is actively working (booting, thinking, streaming). */
@@ -17,6 +20,19 @@ export interface ChatRuntimeOptions {
17
20
  contentTransform?: (content: string) => string;
18
21
  /** Called after a message is successfully sent (e.g. clear attachments). */
19
22
  onMessageSent?: () => void;
23
+ /** Override model for new sessions (e.g. 'claude-sonnet-4-6'). */
24
+ model?: string;
25
+ /** Override agent type for new sessions (e.g. 'claude-code'). */
26
+ agentType?: string;
27
+ /** When true, inject debug bubbles showing SSE events, session info, etc. */
28
+ debugMode?: boolean;
29
+ }
30
+ /** A debug event captured from SSE for display in debug mode. */
31
+ export interface DebugEvent {
32
+ id: string;
33
+ timestamp: Date;
34
+ label: string;
35
+ detail?: string;
20
36
  }
21
37
  /**
22
38
  * `featureId` is a polymorphic scope key: a feature UUID, "repo-<id>", or "global".
@@ -1 +1 @@
1
- {"version":3,"file":"useChatRuntime.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/chat/useChatRuntime.ts"],"names":[],"mappings":"AAkBA,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;CACxB;AAgDD,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;CAC5B;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAC5B,SAAS,EAAE,MAAM,EACjB,YAAY,CAAC,EAAE,MAAM,EACrB,OAAO,CAAC,EAAE,kBAAkB;;;;;;;EAiQ7B"}
1
+ {"version":3,"file":"useChatRuntime.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/chat/useChatRuntime.ts"],"names":[],"mappings":"AAkBA,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;;;;;;;EAgW7B"}