@shepai/cli 1.151.2-pr460.ba381d8 → 1.151.2-pr460.d6300bd

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 (259) hide show
  1. package/dist/packages/core/src/application/ports/output/repositories/interactive-session-repository.interface.d.ts +19 -0
  2. package/dist/packages/core/src/application/ports/output/repositories/interactive-session-repository.interface.d.ts.map +1 -1
  3. package/dist/packages/core/src/application/ports/output/services/interactive-session-service.interface.d.ts +13 -0
  4. package/dist/packages/core/src/application/ports/output/services/interactive-session-service.interface.d.ts.map +1 -1
  5. package/dist/packages/core/src/infrastructure/persistence/sqlite/mappers/interactive-session.mapper.d.ts +2 -0
  6. package/dist/packages/core/src/infrastructure/persistence/sqlite/mappers/interactive-session.mapper.d.ts.map +1 -1
  7. package/dist/packages/core/src/infrastructure/persistence/sqlite/mappers/interactive-session.mapper.js +2 -0
  8. package/dist/packages/core/src/infrastructure/persistence/sqlite/migrations/047-add-agent-session-id.d.ts +15 -0
  9. package/dist/packages/core/src/infrastructure/persistence/sqlite/migrations/047-add-agent-session-id.d.ts.map +1 -0
  10. package/dist/packages/core/src/infrastructure/persistence/sqlite/migrations/047-add-agent-session-id.js +27 -0
  11. package/dist/packages/core/src/infrastructure/persistence/sqlite/migrations/048-add-turn-status.d.ts +15 -0
  12. package/dist/packages/core/src/infrastructure/persistence/sqlite/migrations/048-add-turn-status.d.ts.map +1 -0
  13. package/dist/packages/core/src/infrastructure/persistence/sqlite/migrations/048-add-turn-status.js +20 -0
  14. package/dist/packages/core/src/infrastructure/repositories/sqlite-interactive-session.repository.d.ts +4 -0
  15. package/dist/packages/core/src/infrastructure/repositories/sqlite-interactive-session.repository.d.ts.map +1 -1
  16. package/dist/packages/core/src/infrastructure/repositories/sqlite-interactive-session.repository.js +37 -0
  17. package/dist/packages/core/src/infrastructure/services/interactive/interactive-session.service.d.ts +4 -2
  18. package/dist/packages/core/src/infrastructure/services/interactive/interactive-session.service.d.ts.map +1 -1
  19. package/dist/packages/core/src/infrastructure/services/interactive/interactive-session.service.js +89 -32
  20. package/dist/src/presentation/web/app/api/interactive/chat/[featureId]/mark-read/route.d.ts +19 -0
  21. package/dist/src/presentation/web/app/api/interactive/chat/[featureId]/mark-read/route.d.ts.map +1 -0
  22. package/dist/src/presentation/web/app/api/interactive/chat/[featureId]/mark-read/route.js +24 -0
  23. package/dist/src/presentation/web/app/api/interactive/chat/turn-statuses/route.d.ts +13 -0
  24. package/dist/src/presentation/web/app/api/interactive/chat/turn-statuses/route.d.ts.map +1 -0
  25. package/dist/src/presentation/web/app/api/interactive/chat/turn-statuses/route.js +36 -0
  26. package/dist/src/presentation/web/components/common/feature-node/feature-node.d.ts.map +1 -1
  27. package/dist/src/presentation/web/components/common/feature-node/feature-node.js +5 -2
  28. package/dist/src/presentation/web/components/common/repository-node/repository-node.d.ts.map +1 -1
  29. package/dist/src/presentation/web/components/common/repository-node/repository-node.js +7 -2
  30. package/dist/src/presentation/web/components/features/chat/ChatDotIndicator.d.ts +14 -0
  31. package/dist/src/presentation/web/components/features/chat/ChatDotIndicator.d.ts.map +1 -0
  32. package/dist/src/presentation/web/components/features/chat/ChatDotIndicator.js +13 -0
  33. package/dist/src/presentation/web/components/features/chat/ChatDotIndicator.stories.d.ts +9 -0
  34. package/dist/src/presentation/web/components/features/chat/ChatDotIndicator.stories.d.ts.map +1 -0
  35. package/dist/src/presentation/web/components/features/chat/ChatDotIndicator.stories.js +19 -0
  36. package/dist/src/presentation/web/components/features/chat/ChatSheet.d.ts.map +1 -1
  37. package/dist/src/presentation/web/components/features/chat/ChatSheet.js +4 -1
  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 +6 -0
  40. package/dist/src/presentation/web/components/layouts/app-shell/app-shell.d.ts.map +1 -1
  41. package/dist/src/presentation/web/components/layouts/app-shell/app-shell.js +9 -2
  42. package/dist/src/presentation/web/hooks/turn-statuses-provider.d.ts +19 -0
  43. package/dist/src/presentation/web/hooks/turn-statuses-provider.d.ts.map +1 -0
  44. package/dist/src/presentation/web/hooks/turn-statuses-provider.js +26 -0
  45. package/dist/src/presentation/web/hooks/use-turn-statuses.d.ts +13 -0
  46. package/dist/src/presentation/web/hooks/use-turn-statuses.d.ts.map +1 -0
  47. package/dist/src/presentation/web/hooks/use-turn-statuses.js +31 -0
  48. package/dist/tsconfig.build.tsbuildinfo +1 -1
  49. package/package.json +1 -1
  50. package/web/.next/BUILD_ID +1 -1
  51. package/web/.next/app-path-routes-manifest.json +2 -0
  52. package/web/.next/build-manifest.json +2 -2
  53. package/web/.next/fallback-build-manifest.json +2 -2
  54. package/web/.next/prerender-manifest.json +3 -3
  55. package/web/.next/required-server-files.js +1 -1
  56. package/web/.next/required-server-files.json +1 -1
  57. package/web/.next/routes-manifest.json +14 -0
  58. package/web/.next/server/app/(dashboard)/@drawer/adopt/page/server-reference-manifest.json +28 -28
  59. package/web/.next/server/app/(dashboard)/@drawer/adopt/page.js.nft.json +1 -1
  60. package/web/.next/server/app/(dashboard)/@drawer/adopt/page_client-reference-manifest.js +1 -1
  61. package/web/.next/server/app/(dashboard)/@drawer/chat/page/server-reference-manifest.json +26 -26
  62. package/web/.next/server/app/(dashboard)/@drawer/chat/page.js.nft.json +1 -1
  63. package/web/.next/server/app/(dashboard)/@drawer/chat/page_client-reference-manifest.js +1 -1
  64. package/web/.next/server/app/(dashboard)/@drawer/create/page/server-reference-manifest.json +29 -29
  65. package/web/.next/server/app/(dashboard)/@drawer/create/page.js.nft.json +1 -1
  66. package/web/.next/server/app/(dashboard)/@drawer/create/page_client-reference-manifest.js +1 -1
  67. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page/server-reference-manifest.json +36 -36
  68. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page.js.nft.json +1 -1
  69. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page_client-reference-manifest.js +1 -1
  70. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page/server-reference-manifest.json +36 -36
  71. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page.js.nft.json +1 -1
  72. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page_client-reference-manifest.js +1 -1
  73. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/[tab]/page/server-reference-manifest.json +26 -26
  74. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/[tab]/page.js.nft.json +1 -1
  75. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/[tab]/page_client-reference-manifest.js +1 -1
  76. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page/server-reference-manifest.json +26 -26
  77. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page.js.nft.json +1 -1
  78. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page_client-reference-manifest.js +1 -1
  79. package/web/.next/server/app/(dashboard)/chat/page/server-reference-manifest.json +26 -26
  80. package/web/.next/server/app/(dashboard)/chat/page.js.nft.json +1 -1
  81. package/web/.next/server/app/(dashboard)/chat/page_client-reference-manifest.js +1 -1
  82. package/web/.next/server/app/(dashboard)/create/page/server-reference-manifest.json +29 -29
  83. package/web/.next/server/app/(dashboard)/create/page.js.nft.json +1 -1
  84. package/web/.next/server/app/(dashboard)/create/page_client-reference-manifest.js +1 -1
  85. package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page/server-reference-manifest.json +36 -36
  86. package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page.js.nft.json +1 -1
  87. package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page_client-reference-manifest.js +1 -1
  88. package/web/.next/server/app/(dashboard)/feature/[featureId]/page/server-reference-manifest.json +36 -36
  89. package/web/.next/server/app/(dashboard)/feature/[featureId]/page.js.nft.json +1 -1
  90. package/web/.next/server/app/(dashboard)/feature/[featureId]/page_client-reference-manifest.js +1 -1
  91. package/web/.next/server/app/(dashboard)/page/server-reference-manifest.json +26 -26
  92. package/web/.next/server/app/(dashboard)/page.js.nft.json +1 -1
  93. package/web/.next/server/app/(dashboard)/page_client-reference-manifest.js +1 -1
  94. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/[tab]/page/server-reference-manifest.json +26 -26
  95. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/[tab]/page.js.nft.json +1 -1
  96. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/[tab]/page_client-reference-manifest.js +1 -1
  97. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page/server-reference-manifest.json +26 -26
  98. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page.js.nft.json +1 -1
  99. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page_client-reference-manifest.js +1 -1
  100. package/web/.next/server/app/_global-error.html +2 -2
  101. package/web/.next/server/app/_global-error.rsc +1 -1
  102. package/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  103. package/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  104. package/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  105. package/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  106. package/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  107. package/web/.next/server/app/_not-found/page/server-reference-manifest.json +5 -5
  108. package/web/.next/server/app/_not-found/page.js.nft.json +1 -1
  109. package/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  110. package/web/.next/server/app/api/attachments/preview/route.js.nft.json +1 -1
  111. package/web/.next/server/app/api/attachments/upload-from-path/route.js +1 -1
  112. package/web/.next/server/app/api/attachments/upload-from-path/route.js.nft.json +1 -1
  113. package/web/.next/server/app/api/evidence/route.js.nft.json +1 -1
  114. package/web/.next/server/app/api/graph-data/route.js.nft.json +1 -1
  115. package/web/.next/server/app/api/interactive/chat/[featureId]/mark-read/route/app-paths-manifest.json +3 -0
  116. package/web/.next/server/app/api/interactive/chat/[featureId]/mark-read/route/build-manifest.json +11 -0
  117. package/web/.next/server/app/api/interactive/chat/[featureId]/mark-read/route/server-reference-manifest.json +4 -0
  118. package/web/.next/server/app/api/interactive/chat/[featureId]/mark-read/route.js +7 -0
  119. package/web/.next/server/app/api/interactive/chat/[featureId]/mark-read/route.js.map +5 -0
  120. package/web/.next/server/app/api/interactive/chat/[featureId]/mark-read/route.js.nft.json +1 -0
  121. package/web/.next/server/app/api/interactive/chat/[featureId]/mark-read/route_client-reference-manifest.js +2 -0
  122. package/web/.next/server/app/api/interactive/chat/[featureId]/messages/route.js.nft.json +1 -1
  123. package/web/.next/server/app/api/interactive/chat/turn-statuses/route/app-paths-manifest.json +3 -0
  124. package/web/.next/server/app/api/interactive/chat/turn-statuses/route/build-manifest.json +11 -0
  125. package/web/.next/server/app/api/interactive/chat/turn-statuses/route/server-reference-manifest.json +4 -0
  126. package/web/.next/server/app/api/interactive/chat/turn-statuses/route.js +7 -0
  127. package/web/.next/server/app/api/interactive/chat/turn-statuses/route.js.map +5 -0
  128. package/web/.next/server/app/api/interactive/chat/turn-statuses/route.js.nft.json +1 -0
  129. package/web/.next/server/app/api/interactive/chat/turn-statuses/route_client-reference-manifest.js +2 -0
  130. package/web/.next/server/app/api/sessions-batch/route.js +1 -1
  131. package/web/.next/server/app/api/sessions-batch/route.js.nft.json +1 -1
  132. package/web/.next/server/app/settings/page/server-reference-manifest.json +8 -8
  133. package/web/.next/server/app/settings/page.js.nft.json +1 -1
  134. package/web/.next/server/app/settings/page_client-reference-manifest.js +1 -1
  135. package/web/.next/server/app/skills/page/server-reference-manifest.json +10 -10
  136. package/web/.next/server/app/skills/page.js.nft.json +1 -1
  137. package/web/.next/server/app/skills/page_client-reference-manifest.js +1 -1
  138. package/web/.next/server/app/tools/page/server-reference-manifest.json +10 -10
  139. package/web/.next/server/app/tools/page.js.nft.json +1 -1
  140. package/web/.next/server/app/tools/page_client-reference-manifest.js +1 -1
  141. package/web/.next/server/app/version/page/server-reference-manifest.json +5 -5
  142. package/web/.next/server/app/version/page.js.nft.json +1 -1
  143. package/web/.next/server/app/version/page_client-reference-manifest.js +1 -1
  144. package/web/.next/server/app-paths-manifest.json +2 -0
  145. package/web/.next/server/chunks/8ba4b_server_app_api_interactive_chat_[featureId]_mark-read_route_actions_ce79c730.js +3 -0
  146. package/web/.next/server/chunks/8ba4b_server_app_api_interactive_chat_[featureId]_mark-read_route_actions_ce79c730.js.map +1 -0
  147. package/web/.next/server/chunks/8ba4b_server_app_api_interactive_chat_turn-statuses_route_actions_f97e4de7.js +3 -0
  148. package/web/.next/server/chunks/8ba4b_server_app_api_interactive_chat_turn-statuses_route_actions_f97e4de7.js.map +1 -0
  149. package/web/.next/server/chunks/{[root-of-the-server]__0d33c29e._.js → [root-of-the-server]__31598852._.js} +2 -2
  150. package/web/.next/server/chunks/{[root-of-the-server]__0d33c29e._.js.map → [root-of-the-server]__31598852._.js.map} +1 -1
  151. package/web/.next/server/chunks/[root-of-the-server]__32b04219._.js +3 -0
  152. package/web/.next/server/chunks/[root-of-the-server]__32b04219._.js.map +1 -0
  153. package/web/.next/server/chunks/[root-of-the-server]__a402b567._.js +1 -1
  154. package/web/.next/server/chunks/[root-of-the-server]__ab4951b1._.js +3 -0
  155. package/web/.next/server/chunks/[root-of-the-server]__ab4951b1._.js.map +1 -0
  156. package/web/.next/server/chunks/{[root-of-the-server]__a5879003._.js → [root-of-the-server]__ea653642._.js} +2 -2
  157. package/web/.next/server/chunks/{[root-of-the-server]__a5879003._.js.map → [root-of-the-server]__ea653642._.js.map} +1 -1
  158. package/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_create-drawer-client_tsx_5e26fc0a._.js +1 -1
  159. package/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_create-drawer-client_tsx_5e26fc0a._.js.map +1 -1
  160. package/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_feature-drawer-client_tsx_e9755fc8._.js +2 -2
  161. package/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_feature-drawer-client_tsx_e9755fc8._.js.map +1 -1
  162. package/web/.next/server/chunks/ssr/[root-of-the-server]__17ed7ed1._.js +1 -1
  163. package/web/.next/server/chunks/ssr/[root-of-the-server]__17ed7ed1._.js.map +1 -1
  164. package/web/.next/server/chunks/ssr/[root-of-the-server]__28d0d265._.js +2 -2
  165. package/web/.next/server/chunks/ssr/[root-of-the-server]__357d99f9._.js +1 -1
  166. package/web/.next/server/chunks/ssr/[root-of-the-server]__42bf1807._.js +1 -1
  167. package/web/.next/server/chunks/ssr/[root-of-the-server]__42bf1807._.js.map +1 -1
  168. package/web/.next/server/chunks/ssr/[root-of-the-server]__563f2f7a._.js +3 -0
  169. package/web/.next/server/chunks/ssr/[root-of-the-server]__563f2f7a._.js.map +1 -0
  170. package/web/.next/server/chunks/ssr/[root-of-the-server]__56b70465._.js +1 -1
  171. package/web/.next/server/chunks/ssr/[root-of-the-server]__56b70465._.js.map +1 -1
  172. package/web/.next/server/chunks/ssr/[root-of-the-server]__88f7e8e6._.js +1 -1
  173. package/web/.next/server/chunks/ssr/[root-of-the-server]__88f7e8e6._.js.map +1 -1
  174. package/web/.next/server/chunks/ssr/[root-of-the-server]__8b0aac03._.js +1 -1
  175. package/web/.next/server/chunks/ssr/[root-of-the-server]__c30f1f82._.js +1 -1
  176. package/web/.next/server/chunks/ssr/[root-of-the-server]__c30f1f82._.js.map +1 -1
  177. package/web/.next/server/chunks/ssr/{[root-of-the-server]__31f1c3b0._.js → [root-of-the-server]__e91ffd5e._.js} +3 -3
  178. package/web/.next/server/chunks/ssr/[root-of-the-server]__e91ffd5e._.js.map +1 -0
  179. package/web/.next/server/chunks/ssr/[root-of-the-server]__f80bfc75._.js +1 -1
  180. package/web/.next/server/chunks/ssr/[root-of-the-server]__f80bfc75._.js.map +1 -1
  181. package/web/.next/server/chunks/ssr/_05c23ad9._.js +1 -1
  182. package/web/.next/server/chunks/ssr/_05c23ad9._.js.map +1 -1
  183. package/web/.next/server/chunks/ssr/_16eb4fec._.js +1 -1
  184. package/web/.next/server/chunks/ssr/_16eb4fec._.js.map +1 -1
  185. package/web/.next/server/chunks/ssr/_3a0b989f._.js +2 -2
  186. package/web/.next/server/chunks/ssr/_3a0b989f._.js.map +1 -1
  187. package/web/.next/server/chunks/ssr/_56b9d60f._.js +1 -1
  188. package/web/.next/server/chunks/ssr/_56b9d60f._.js.map +1 -1
  189. package/web/.next/server/chunks/ssr/_5f69c13f._.js +1 -1
  190. package/web/.next/server/chunks/ssr/_5f69c13f._.js.map +1 -1
  191. package/web/.next/server/chunks/ssr/_6f48569b._.js +3 -0
  192. package/web/.next/server/chunks/ssr/{_de71404e._.js.map → _6f48569b._.js.map} +1 -1
  193. package/web/.next/server/chunks/ssr/_7c5b97c6._.js +1 -1
  194. package/web/.next/server/chunks/ssr/_7c5b97c6._.js.map +1 -1
  195. package/web/.next/server/chunks/ssr/_82c57f10._.js +1 -1
  196. package/web/.next/server/chunks/ssr/_82c57f10._.js.map +1 -1
  197. package/web/.next/server/chunks/ssr/_9495d50b._.js +1 -1
  198. package/web/.next/server/chunks/ssr/_9495d50b._.js.map +1 -1
  199. package/web/.next/server/chunks/ssr/{_4c42590e._.js → _9ab5e836._.js} +2 -2
  200. package/web/.next/server/chunks/ssr/{_4c42590e._.js.map → _9ab5e836._.js.map} +1 -1
  201. package/web/.next/server/chunks/ssr/{_eb9467e9._.js → _9ecb7d6d._.js} +2 -2
  202. package/web/.next/server/chunks/ssr/{_eb9467e9._.js.map → _9ecb7d6d._.js.map} +1 -1
  203. package/web/.next/server/chunks/ssr/_a0e3f7e4._.js +1 -1
  204. package/web/.next/server/chunks/ssr/_a0e3f7e4._.js.map +1 -1
  205. package/web/.next/server/chunks/ssr/_ac4a3873._.js +1 -1
  206. package/web/.next/server/chunks/ssr/_ca0aa7f0._.js +1 -1
  207. package/web/.next/server/chunks/ssr/_ca0aa7f0._.js.map +1 -1
  208. package/web/.next/server/chunks/ssr/_cb5a021e._.js +1 -1
  209. package/web/.next/server/chunks/ssr/_cb5a021e._.js.map +1 -1
  210. package/web/.next/server/chunks/ssr/_d86175ae._.js +1 -1
  211. package/web/.next/server/chunks/ssr/_d86175ae._.js.map +1 -1
  212. package/web/.next/server/chunks/ssr/_d8bedf13._.js +1 -1
  213. package/web/.next/server/chunks/ssr/_d8bedf13._.js.map +1 -1
  214. package/web/.next/server/chunks/ssr/{_48e5757d._.js → _e9a73a63._.js} +2 -2
  215. package/web/.next/server/chunks/ssr/_e9a73a63._.js.map +1 -0
  216. package/web/.next/server/chunks/ssr/_fa7efce3._.js +2 -2
  217. package/web/.next/server/chunks/ssr/_fa7efce3._.js.map +1 -1
  218. package/web/.next/server/chunks/ssr/b1a17_presentation_web_components_features_settings_settings-page-client_tsx_6ed9d5f8._.js +1 -1
  219. package/web/.next/server/chunks/ssr/b1a17_presentation_web_components_features_settings_settings-page-client_tsx_6ed9d5f8._.js.map +1 -1
  220. package/web/.next/server/chunks/ssr/node_modules__pnpm_ef15a0bd._.js +3 -0
  221. package/web/.next/server/chunks/ssr/node_modules__pnpm_ef15a0bd._.js.map +1 -0
  222. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_skills_page_actions_cdc632e3.js +1 -1
  223. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_skills_page_actions_cdc632e3.js.map +1 -1
  224. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_tools_page_actions_39ca0924.js +1 -1
  225. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_tools_page_actions_39ca0924.js.map +1 -1
  226. package/web/.next/server/chunks/ssr/src_presentation_web_app_actions_open-ide_ts_baaca5d5._.js +1 -1
  227. package/web/.next/server/chunks/ssr/src_presentation_web_components_357e3eb0._.js +1 -1
  228. package/web/.next/server/chunks/ssr/src_presentation_web_components_357e3eb0._.js.map +1 -1
  229. package/web/.next/server/chunks/ssr/src_presentation_web_components_features_control-center_7ac3562e._.js +1 -1
  230. package/web/.next/server/chunks/ssr/src_presentation_web_components_features_control-center_7ac3562e._.js.map +1 -1
  231. package/web/.next/server/pages/500.html +2 -2
  232. package/web/.next/server/server-reference-manifest.js +1 -1
  233. package/web/.next/server/server-reference-manifest.json +45 -45
  234. package/web/.next/static/chunks/{e51493c981deb9fd.js → 00ddf2682e26248f.js} +1 -1
  235. package/web/.next/static/chunks/{6a5c79587318fe1e.js → 0d07a524b56a91ae.js} +1 -1
  236. package/web/.next/static/chunks/{73b5be3394d27358.js → 3011d2b0e84898b9.js} +2 -2
  237. package/web/.next/static/chunks/{c80523e4d172cdea.js → 3d780d0c67e9c6d7.js} +2 -2
  238. package/web/.next/static/chunks/{9dd319c237b73197.js → 3f314c0cfed1a31f.js} +1 -1
  239. package/web/.next/static/chunks/{b546fac6810f555b.js → 4dcd3fddd166e847.js} +1 -1
  240. package/web/.next/static/chunks/{ce18a48f7d5d53c0.js → 6b96db4c6afb337c.js} +1 -1
  241. package/web/.next/static/chunks/8ba1c07ef18b15a9.js +1 -0
  242. package/web/.next/static/chunks/91ca5103e9d37ecf.js +7 -0
  243. package/web/.next/static/chunks/a919a9df4ab12a5c.css +1 -0
  244. package/web/.next/static/chunks/afc4212532319046.js +1 -0
  245. package/web/.next/static/chunks/{feed0046c419c228.js → b4cde06eff374c59.js} +3 -3
  246. package/web/.next/static/chunks/{ec7cd7e136a1b320.js → c9d93e106e541ea5.js} +1 -1
  247. package/web/.next/static/chunks/{0e73b25a355804a2.js → d1beeb17dc36ae56.js} +2 -2
  248. package/web/.next/static/chunks/{487a3d47f76ba2ce.js → dd72af4aa0e5a751.js} +1 -1
  249. package/web/.next/server/chunks/ssr/[root-of-the-server]__31f1c3b0._.js.map +0 -1
  250. package/web/.next/server/chunks/ssr/[root-of-the-server]__ede6df1f._.js +0 -3
  251. package/web/.next/server/chunks/ssr/[root-of-the-server]__ede6df1f._.js.map +0 -1
  252. package/web/.next/server/chunks/ssr/_48e5757d._.js.map +0 -1
  253. package/web/.next/server/chunks/ssr/_de71404e._.js +0 -3
  254. package/web/.next/static/chunks/16f6471485cbfed1.css +0 -1
  255. package/web/.next/static/chunks/476ebad4abb27ee8.js +0 -7
  256. package/web/.next/static/chunks/f0b1a5ded6ab6885.js +0 -1
  257. /package/web/.next/static/{VIJH9LQh8Ro1-nip3v-Am → Pz2jBHo89UcoWoV7z5vJp}/_buildManifest.js +0 -0
  258. /package/web/.next/static/{VIJH9LQh8Ro1-nip3v-Am → Pz2jBHo89UcoWoV7z5vJp}/_clientMiddlewareManifest.json +0 -0
  259. /package/web/.next/static/{VIJH9LQh8Ro1-nip3v-Am → Pz2jBHo89UcoWoV7z5vJp}/_ssgManifest.js +0 -0
@@ -50,5 +50,24 @@ export interface IInteractiveSessionRepository {
50
50
  * Used to enforce the concurrent session cap.
51
51
  */
52
52
  countActiveSessions(): Promise<number>;
53
+ /**
54
+ * Persist the agent SDK session ID for resumption across service restarts.
55
+ * Agent-agnostic: works with Claude, Cursor, Codex, or any future agent.
56
+ */
57
+ updateAgentSessionId(id: string, agentSessionId: string): Promise<void>;
58
+ /**
59
+ * Retrieve the agent SDK session ID for a given session.
60
+ */
61
+ getAgentSessionId(id: string): Promise<string | null>;
62
+ /**
63
+ * Update the turn status for a session.
64
+ * Values: 'idle' | 'processing' | 'unread'
65
+ */
66
+ updateTurnStatus(id: string, turnStatus: string): Promise<void>;
67
+ /**
68
+ * Get turn statuses for multiple feature IDs in a single query.
69
+ * Returns a map of featureId → turnStatus for features that have an active session.
70
+ */
71
+ getTurnStatuses(featureIds: string[]): Promise<Map<string, string>>;
53
72
  }
54
73
  //# sourceMappingURL=interactive-session-repository.interface.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"interactive-session-repository.interface.d.ts","sourceRoot":"","sources":["../../../../../../../../packages/core/src/application/ports/output/repositories/interactive-session-repository.interface.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EACV,kBAAkB,EAClB,wBAAwB,EACzB,MAAM,wCAAwC,CAAC;AAEhD;;GAEG;AACH,MAAM,WAAW,6BAA6B;IAC5C;;OAEG;IACH,MAAM,CAAC,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEnD;;OAEG;IACH,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC,CAAC;IAEzD;;;;;OAKG;IACH,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC,CAAC;IAEvE;;;OAGG;IACH,aAAa,IAAI,OAAO,CAAC,kBAAkB,EAAE,CAAC,CAAC;IAE/C;;OAEG;IACH,YAAY,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,wBAAwB,EAAE,SAAS,CAAC,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE5F;;OAEG;IACH,kBAAkB,CAAC,EAAE,EAAE,MAAM,EAAE,cAAc,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEpE;;;OAGG;IACH,oBAAoB,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAEtC;;;OAGG;IACH,mBAAmB,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;CACxC"}
1
+ {"version":3,"file":"interactive-session-repository.interface.d.ts","sourceRoot":"","sources":["../../../../../../../../packages/core/src/application/ports/output/repositories/interactive-session-repository.interface.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EACV,kBAAkB,EAClB,wBAAwB,EACzB,MAAM,wCAAwC,CAAC;AAEhD;;GAEG;AACH,MAAM,WAAW,6BAA6B;IAC5C;;OAEG;IACH,MAAM,CAAC,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEnD;;OAEG;IACH,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC,CAAC;IAEzD;;;;;OAKG;IACH,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC,CAAC;IAEvE;;;OAGG;IACH,aAAa,IAAI,OAAO,CAAC,kBAAkB,EAAE,CAAC,CAAC;IAE/C;;OAEG;IACH,YAAY,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,wBAAwB,EAAE,SAAS,CAAC,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE5F;;OAEG;IACH,kBAAkB,CAAC,EAAE,EAAE,MAAM,EAAE,cAAc,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEpE;;;OAGG;IACH,oBAAoB,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAEtC;;;OAGG;IACH,mBAAmB,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;IAEvC;;;OAGG;IACH,oBAAoB,CAAC,EAAE,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAExE;;OAEG;IACH,iBAAiB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAEtD;;;OAGG;IACH,gBAAgB,CAAC,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEhE;;;OAGG;IACH,eAAe,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;CACrE"}
@@ -50,6 +50,8 @@ export interface ChatState {
50
50
  streamingText: string | null;
51
51
  /** Session info for the toolbar (null if no active session) */
52
52
  sessionInfo: SessionInfo | null;
53
+ /** Turn activity status: 'idle' | 'processing' | 'unread' (for dot indicators) */
54
+ turnStatus: string;
53
55
  }
54
56
  /** Live session metadata for the frontend toolbar. */
55
57
  export interface SessionInfo {
@@ -165,5 +167,16 @@ export interface IInteractiveSessionService {
165
167
  * Idempotent — no-op if no active session exists.
166
168
  */
167
169
  stopByFeature(featureId: string): Promise<void>;
170
+ /**
171
+ * Mark a feature's chat as read — clears the 'unread' turn status to 'idle'.
172
+ * Called when the user opens/views the chat tab.
173
+ */
174
+ markRead(featureId: string): Promise<void>;
175
+ /**
176
+ * Get turn statuses for multiple features in a single call.
177
+ * Returns a map of featureId → 'idle' | 'processing' | 'unread'.
178
+ * Used by UI to show dot indicators on all chat buttons.
179
+ */
180
+ getTurnStatuses(featureIds: string[]): Promise<Map<string, string>>;
168
181
  }
169
182
  //# sourceMappingURL=interactive-session-service.interface.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"interactive-session-service.interface.d.ts","sourceRoot":"","sources":["../../../../../../../../packages/core/src/application/ports/output/services/interactive-session-service.interface.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"interactive-session-service.interface.d.ts","sourceRoot":"","sources":["../../../../../../../../packages/core/src/application/ports/output/services/interactive-session-service.interface.ts"],"names":[],"mappings":"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"}
@@ -18,6 +18,8 @@ export interface InteractiveSessionRow {
18
18
  id: string;
19
19
  feature_id: string;
20
20
  status: string;
21
+ agent_session_id: string | null;
22
+ turn_status: string;
21
23
  started_at: number;
22
24
  stopped_at: number | null;
23
25
  last_activity_at: number;
@@ -1 +1 @@
1
- {"version":3,"file":"interactive-session.mapper.d.ts","sourceRoot":"","sources":["../../../../../../../../packages/core/src/infrastructure/persistence/sqlite/mappers/interactive-session.mapper.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,wCAAwC,CAAC;AAGjF;;;GAGG;AACH,MAAM,WAAW,qBAAqB;IACpC,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,gBAAgB,EAAE,MAAM,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,kBAAkB,GAAG,qBAAqB,CAe7E;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,qBAAqB,GAAG,kBAAkB,CAW3E"}
1
+ {"version":3,"file":"interactive-session.mapper.d.ts","sourceRoot":"","sources":["../../../../../../../../packages/core/src/infrastructure/persistence/sqlite/mappers/interactive-session.mapper.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,wCAAwC,CAAC;AAGjF;;;GAGG;AACH,MAAM,WAAW,qBAAqB;IACpC,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,gBAAgB,EAAE,MAAM,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,kBAAkB,GAAG,qBAAqB,CAiB7E;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,qBAAqB,GAAG,kBAAkB,CAW3E"}
@@ -18,6 +18,8 @@ export function toDatabase(session) {
18
18
  id: session.id,
19
19
  feature_id: session.featureId,
20
20
  status: session.status,
21
+ agent_session_id: null,
22
+ turn_status: 'idle',
21
23
  started_at: session.startedAt instanceof Date ? session.startedAt.getTime() : session.startedAt,
22
24
  stopped_at: session.stoppedAt instanceof Date ? session.stoppedAt.getTime() : (session.stoppedAt ?? null),
23
25
  last_activity_at: session.lastActivityAt instanceof Date
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Migration 047: Add agent_session_id column to interactive_sessions.
3
+ *
4
+ * Persists the agent SDK session ID so sessions can be resumed after
5
+ * service restarts (e.g. Next.js hot-reload, server restart). Previously
6
+ * this was only held in-memory, causing each message after a restart to
7
+ * spawn a brand new agent session instead of resuming the existing one.
8
+ *
9
+ * Agent-agnostic: works with Claude, Cursor, Codex, or any future agent.
10
+ */
11
+ import type { MigrationParams } from 'umzug';
12
+ import type Database from 'better-sqlite3';
13
+ export declare function up({ context: db }: MigrationParams<Database.Database>): Promise<void>;
14
+ export declare function down({ context: db }: MigrationParams<Database.Database>): Promise<void>;
15
+ //# sourceMappingURL=047-add-agent-session-id.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"047-add-agent-session-id.d.ts","sourceRoot":"","sources":["../../../../../../../../packages/core/src/infrastructure/persistence/sqlite/migrations/047-add-agent-session-id.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,OAAO,CAAC;AAC7C,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAE3C,wBAAsB,EAAE,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,EAAE,eAAe,CAAC,QAAQ,CAAC,QAAQ,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAO3F;AAED,wBAAsB,IAAI,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,EAAE,eAAe,CAAC,QAAQ,CAAC,QAAQ,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAS7F"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Migration 047: Add agent_session_id column to interactive_sessions.
3
+ *
4
+ * Persists the agent SDK session ID so sessions can be resumed after
5
+ * service restarts (e.g. Next.js hot-reload, server restart). Previously
6
+ * this was only held in-memory, causing each message after a restart to
7
+ * spawn a brand new agent session instead of resuming the existing one.
8
+ *
9
+ * Agent-agnostic: works with Claude, Cursor, Codex, or any future agent.
10
+ */
11
+ export async function up({ context: db }) {
12
+ const columns = db.pragma('table_info(interactive_sessions)');
13
+ const names = new Set(columns.map((c) => c.name));
14
+ if (!names.has('agent_session_id')) {
15
+ db.exec(`ALTER TABLE interactive_sessions ADD COLUMN agent_session_id TEXT`);
16
+ }
17
+ }
18
+ export async function down({ context: db }) {
19
+ // SQLite doesn't support DROP COLUMN before 3.35.0; recreate table
20
+ db.exec(`
21
+ CREATE TABLE interactive_sessions_backup AS SELECT
22
+ id, feature_id, status, started_at, stopped_at, last_activity_at, created_at, updated_at
23
+ FROM interactive_sessions
24
+ `);
25
+ db.exec('DROP TABLE interactive_sessions');
26
+ db.exec('ALTER TABLE interactive_sessions_backup RENAME TO interactive_sessions');
27
+ }
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Migration 048: Add turn_status column to interactive_sessions.
3
+ *
4
+ * Tracks per-session activity state for UI dot indicators:
5
+ * - idle: no active turn, nothing to show
6
+ * - processing: agent is actively working on a response
7
+ * - unread: agent finished responding but user hasn't seen it yet
8
+ *
9
+ * Used by chat buttons (global/repo/feature) to show activity dots.
10
+ */
11
+ import type { MigrationParams } from 'umzug';
12
+ import type Database from 'better-sqlite3';
13
+ export declare function up({ context: db }: MigrationParams<Database.Database>): Promise<void>;
14
+ export declare function down({ context: db }: MigrationParams<Database.Database>): Promise<void>;
15
+ //# sourceMappingURL=048-add-turn-status.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"048-add-turn-status.d.ts","sourceRoot":"","sources":["../../../../../../../../packages/core/src/infrastructure/persistence/sqlite/migrations/048-add-turn-status.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,OAAO,CAAC;AAC7C,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAE3C,wBAAsB,EAAE,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,EAAE,eAAe,CAAC,QAAQ,CAAC,QAAQ,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAO3F;AAED,wBAAsB,IAAI,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,EAAE,eAAe,CAAC,QAAQ,CAAC,QAAQ,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAE7F"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Migration 048: Add turn_status column to interactive_sessions.
3
+ *
4
+ * Tracks per-session activity state for UI dot indicators:
5
+ * - idle: no active turn, nothing to show
6
+ * - processing: agent is actively working on a response
7
+ * - unread: agent finished responding but user hasn't seen it yet
8
+ *
9
+ * Used by chat buttons (global/repo/feature) to show activity dots.
10
+ */
11
+ export async function up({ context: db }) {
12
+ const columns = db.pragma('table_info(interactive_sessions)');
13
+ const names = new Set(columns.map((c) => c.name));
14
+ if (!names.has('turn_status')) {
15
+ db.exec(`ALTER TABLE interactive_sessions ADD COLUMN turn_status TEXT NOT NULL DEFAULT 'idle'`);
16
+ }
17
+ }
18
+ export async function down({ context: db }) {
19
+ void db;
20
+ }
@@ -19,5 +19,9 @@ export declare class SQLiteInteractiveSessionRepository implements IInteractiveS
19
19
  updateLastActivity(id: string, lastActivityAt: Date): Promise<void>;
20
20
  markAllActiveStopped(): Promise<void>;
21
21
  countActiveSessions(): Promise<number>;
22
+ updateAgentSessionId(id: string, agentSessionId: string): Promise<void>;
23
+ getAgentSessionId(id: string): Promise<string | null>;
24
+ updateTurnStatus(id: string, turnStatus: string): Promise<void>;
25
+ getTurnStatuses(featureIds: string[]): Promise<Map<string, string>>;
22
26
  }
23
27
  //# sourceMappingURL=sqlite-interactive-session.repository.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"sqlite-interactive-session.repository.d.ts","sourceRoot":"","sources":["../../../../../../packages/core/src/infrastructure/repositories/sqlite-interactive-session.repository.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAE3C,OAAO,KAAK,EAAE,6BAA6B,EAAE,MAAM,yFAAyF,CAAC;AAC7I,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAC;AAC3E,OAAO,EAAE,wBAAwB,EAAE,MAAM,kCAAkC,CAAC;AAO5E,qBACa,kCAAmC,YAAW,6BAA6B;IAC1E,OAAO,CAAC,QAAQ,CAAC,EAAE;gBAAF,EAAE,EAAE,QAAQ,CAAC,QAAQ;IAE5C,MAAM,CAAC,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC;IAYlD,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC;IAOxD,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC;IAStE,aAAa,IAAI,OAAO,CAAC,kBAAkB,EAAE,CAAC;IAO9C,YAAY,CAChB,EAAE,EAAE,MAAM,EACV,MAAM,EAAE,wBAAwB,EAChC,SAAS,CAAC,EAAE,IAAI,GACf,OAAO,CAAC,IAAI,CAAC;IAeV,kBAAkB,CAAC,EAAE,EAAE,MAAM,EAAE,cAAc,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAUnE,oBAAoB,IAAI,OAAO,CAAC,IAAI,CAAC;IAUrC,mBAAmB,IAAI,OAAO,CAAC,MAAM,CAAC;CAQ7C"}
1
+ {"version":3,"file":"sqlite-interactive-session.repository.d.ts","sourceRoot":"","sources":["../../../../../../packages/core/src/infrastructure/repositories/sqlite-interactive-session.repository.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAE3C,OAAO,KAAK,EAAE,6BAA6B,EAAE,MAAM,yFAAyF,CAAC;AAC7I,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAC;AAC3E,OAAO,EAAE,wBAAwB,EAAE,MAAM,kCAAkC,CAAC;AAO5E,qBACa,kCAAmC,YAAW,6BAA6B;IAC1E,OAAO,CAAC,QAAQ,CAAC,EAAE;gBAAF,EAAE,EAAE,QAAQ,CAAC,QAAQ;IAE5C,MAAM,CAAC,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC;IAYlD,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC;IAOxD,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC;IAStE,aAAa,IAAI,OAAO,CAAC,kBAAkB,EAAE,CAAC;IAO9C,YAAY,CAChB,EAAE,EAAE,MAAM,EACV,MAAM,EAAE,wBAAwB,EAChC,SAAS,CAAC,EAAE,IAAI,GACf,OAAO,CAAC,IAAI,CAAC;IAeV,kBAAkB,CAAC,EAAE,EAAE,MAAM,EAAE,cAAc,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAUnE,oBAAoB,IAAI,OAAO,CAAC,IAAI,CAAC;IAUrC,mBAAmB,IAAI,OAAO,CAAC,MAAM,CAAC;IAStC,oBAAoB,CAAC,EAAE,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAQvE,iBAAiB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAOrD,gBAAgB,CAAC,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAQ/D,eAAe,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAwB1E"}
@@ -77,6 +77,43 @@ let SQLiteInteractiveSessionRepository = class SQLiteInteractiveSessionRepositor
77
77
  .get();
78
78
  return result.count;
79
79
  }
80
+ async updateAgentSessionId(id, agentSessionId) {
81
+ this.db
82
+ .prepare(`UPDATE interactive_sessions SET agent_session_id = @agent_session_id, updated_at = @updated_at WHERE id = @id`)
83
+ .run({ id, agent_session_id: agentSessionId, updated_at: Date.now() });
84
+ }
85
+ async getAgentSessionId(id) {
86
+ const row = this.db
87
+ .prepare('SELECT agent_session_id FROM interactive_sessions WHERE id = ?')
88
+ .get(id);
89
+ return row?.agent_session_id ?? null;
90
+ }
91
+ async updateTurnStatus(id, turnStatus) {
92
+ this.db
93
+ .prepare(`UPDATE interactive_sessions SET turn_status = @turn_status, updated_at = @updated_at WHERE id = @id`)
94
+ .run({ id, turn_status: turnStatus, updated_at: Date.now() });
95
+ }
96
+ async getTurnStatuses(featureIds) {
97
+ const result = new Map();
98
+ if (featureIds.length === 0)
99
+ return result;
100
+ // Use a single query with placeholders for all feature IDs.
101
+ // For each feature, get the most recent session's turn_status.
102
+ const placeholders = featureIds.map(() => '?').join(',');
103
+ const rows = this.db
104
+ .prepare(`SELECT feature_id, turn_status FROM interactive_sessions
105
+ WHERE feature_id IN (${placeholders})
106
+ AND status IN ('booting','ready')
107
+ ORDER BY created_at DESC`)
108
+ .all(...featureIds);
109
+ // First row per feature wins (most recent due to ORDER BY)
110
+ for (const row of rows) {
111
+ if (!result.has(row.feature_id)) {
112
+ result.set(row.feature_id, row.turn_status);
113
+ }
114
+ }
115
+ return result;
116
+ }
80
117
  };
81
118
  SQLiteInteractiveSessionRepository = __decorate([
82
119
  injectable(),
@@ -39,8 +39,8 @@ export declare class InteractiveSessionService implements IInteractiveSessionSer
39
39
  private readonly contextBuilder;
40
40
  /** Live sessions indexed by sessionId. */
41
41
  private sessions;
42
- /** Cached claudeSessionIds from stopped sessions, keyed by featureId. */
43
- private stoppedClaudeSessionIds;
42
+ /** Cached agentSessionIds from stopped sessions, keyed by featureId. */
43
+ private stoppedAgentSessionIds;
44
44
  constructor(sessionRepo: IInteractiveSessionRepository, messageRepo: IInteractiveMessageRepository, executorFactory: IAgentExecutorFactory, featureRepo: IFeatureRepository, contextBuilder: FeatureContextBuilder);
45
45
  startSession(featureId: string, worktreePath: string, model?: string, agentType?: string): Promise<InteractiveSession>;
46
46
  /**
@@ -64,6 +64,8 @@ export declare class InteractiveSessionService implements IInteractiveSessionSer
64
64
  getChatState(featureId: string): Promise<ChatState>;
65
65
  subscribeByFeature(featureId: string, onChunk: (chunk: StreamChunk) => void): UnsubscribeFn;
66
66
  stopByFeature(featureId: string): Promise<void>;
67
+ markRead(featureId: string): Promise<void>;
68
+ getTurnStatuses(featureIds: string[]): Promise<Map<string, string>>;
67
69
  /** Find the in-memory state for an active session for a feature. */
68
70
  private findActiveStateForFeature;
69
71
  /** Resolve the agent type from an explicit override or settings. */
@@ -1 +1 @@
1
- {"version":3,"file":"interactive-session.service.d.ts","sourceRoot":"","sources":["../../../../../../../packages/core/src/infrastructure/services/interactive/interactive-session.service.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"interactive-session.service.d.ts","sourceRoot":"","sources":["../../../../../../../packages/core/src/infrastructure/services/interactive/interactive-session.service.ts"],"names":[],"mappings":"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"}
@@ -42,8 +42,8 @@ export class InteractiveSessionService {
42
42
  contextBuilder;
43
43
  /** Live sessions indexed by sessionId. */
44
44
  sessions = new Map();
45
- /** Cached claudeSessionIds from stopped sessions, keyed by featureId. */
46
- stoppedClaudeSessionIds = new Map();
45
+ /** Cached agentSessionIds from stopped sessions, keyed by featureId. */
46
+ stoppedAgentSessionIds = new Map();
47
47
  constructor(sessionRepo, messageRepo, executorFactory, featureRepo, contextBuilder) {
48
48
  this.sessionRepo = sessionRepo;
49
49
  this.messageRepo = messageRepo;
@@ -72,16 +72,24 @@ export class InteractiveSessionService {
72
72
  updatedAt: now,
73
73
  };
74
74
  await this.sessionRepo.create(session);
75
- // Carry over claudeSessionId from previous session so resumption works
76
- let previousClaudeSessionId;
75
+ // Carry over agentSessionId from previous session so resumption works
76
+ let previousAgentSessionId;
77
77
  for (const [, s] of this.sessions) {
78
- if (s.featureId === featureId && s.claudeSessionId) {
79
- previousClaudeSessionId = s.claudeSessionId;
78
+ if (s.featureId === featureId && s.agentSessionId) {
79
+ previousAgentSessionId = s.agentSessionId;
80
80
  break;
81
81
  }
82
82
  }
83
83
  // Also check stoppedSessions cache (populated on stop)
84
- previousClaudeSessionId ??= this.stoppedClaudeSessionIds.get(featureId);
84
+ previousAgentSessionId ??= this.stoppedAgentSessionIds.get(featureId);
85
+ // Fall back to DB — the in-memory cache may be empty after service restart
86
+ if (!previousAgentSessionId) {
87
+ const latestDbSession = await this.sessionRepo.findByFeatureId(featureId);
88
+ if (latestDbSession) {
89
+ previousAgentSessionId =
90
+ (await this.sessionRepo.getAgentSessionId(latestDbSession.id)) ?? undefined;
91
+ }
92
+ }
85
93
  // Set up in-memory state
86
94
  const state = {
87
95
  sessionId: session.id,
@@ -90,7 +98,7 @@ export class InteractiveSessionService {
90
98
  model,
91
99
  agentType,
92
100
  handle: null,
93
- claudeSessionId: previousClaudeSessionId,
101
+ agentSessionId: previousAgentSessionId,
94
102
  timer: null,
95
103
  currentAssistantBuffer: '',
96
104
  toolEventsLog: [],
@@ -171,9 +179,9 @@ export class InteractiveSessionService {
171
179
  // Create the interactive executor and session
172
180
  const executor = this.executorFactory.createInteractiveExecutor(resolvedAgentType, authConfig);
173
181
  let handle;
174
- if (state.claudeSessionId) {
182
+ if (state.agentSessionId) {
175
183
  // Resume existing SDK session
176
- handle = await executor.resumeSession(state.claudeSessionId, {
184
+ handle = await executor.resumeSession(state.agentSessionId, {
177
185
  cwd: worktreePath,
178
186
  model: state.model,
179
187
  systemPrompt: context,
@@ -249,7 +257,9 @@ export class InteractiveSessionService {
249
257
  // Capture the SDK session ID (available after first message exchange)
250
258
  const sdkSessionId = handle.sessionId;
251
259
  if (sdkSessionId) {
252
- state.claudeSessionId = sdkSessionId;
260
+ state.agentSessionId = sdkSessionId;
261
+ // Persist to DB so it survives service restarts
262
+ void this.sessionRepo.updateAgentSessionId(state.sessionId, sdkSessionId);
253
263
  }
254
264
  // Persist greeting and mark session ready
255
265
  const greetingMsg = {
@@ -263,6 +273,11 @@ export class InteractiveSessionService {
263
273
  };
264
274
  await this.messageRepo.create(greetingMsg);
265
275
  await this.sessionRepo.updateStatus(state.sessionId, InteractiveSessionStatus.ready);
276
+ // If there's a pending user message, the next turn will set 'processing'.
277
+ // Otherwise boot greeting is expected — mark idle.
278
+ if (!state.pendingUserContent) {
279
+ void this.sessionRepo.updateTurnStatus(state.sessionId, 'idle');
280
+ }
266
281
  state.currentAssistantBuffer = '';
267
282
  state.toolEventsLog = [];
268
283
  // Notify subscribers of end-of-turn
@@ -294,6 +309,9 @@ export class InteractiveSessionService {
294
309
  await this.messageRepo.create(greetingMsg);
295
310
  }
296
311
  await this.sessionRepo.updateStatus(state.sessionId, InteractiveSessionStatus.ready);
312
+ if (!state.pendingUserContent) {
313
+ void this.sessionRepo.updateTurnStatus(state.sessionId, 'idle');
314
+ }
297
315
  state.currentAssistantBuffer = '';
298
316
  state.toolEventsLog = [];
299
317
  this.resetTimer(state);
@@ -311,8 +329,8 @@ export class InteractiveSessionService {
311
329
  catch {
312
330
  // Best-effort DB update
313
331
  }
314
- if (state.claudeSessionId) {
315
- this.stoppedClaudeSessionIds.set(state.featureId, state.claudeSessionId);
332
+ if (state.agentSessionId) {
333
+ this.stoppedAgentSessionIds.set(state.featureId, state.agentSessionId);
316
334
  }
317
335
  this.sessions.delete(state.sessionId);
318
336
  }
@@ -331,9 +349,9 @@ export class InteractiveSessionService {
331
349
  state.streamAbort = undefined;
332
350
  }
333
351
  this.clearTimer(state);
334
- // Cache claudeSessionId so resumption works when session restarts
335
- if (state.claudeSessionId) {
336
- this.stoppedClaudeSessionIds.set(state.featureId, state.claudeSessionId);
352
+ // Cache agentSessionId so resumption works when session restarts
353
+ if (state.agentSessionId) {
354
+ this.stoppedAgentSessionIds.set(state.featureId, state.agentSessionId);
337
355
  }
338
356
  this.sessions.delete(sessionId);
339
357
  // Close the SDK session handle
@@ -347,6 +365,7 @@ export class InteractiveSessionService {
347
365
  state.handle = null;
348
366
  }
349
367
  await this.sessionRepo.updateStatus(sessionId, InteractiveSessionStatus.stopped, new Date());
368
+ void this.sessionRepo.updateTurnStatus(sessionId, 'idle');
350
369
  }
351
370
  async sendMessage(sessionId, content) {
352
371
  const dbSession = await this.sessionRepo.findById(sessionId);
@@ -386,6 +405,8 @@ export class InteractiveSessionService {
386
405
  }
387
406
  state.currentAssistantBuffer = '';
388
407
  state.toolEventsLog = [];
408
+ // Mark turn as processing for dot indicator
409
+ void this.sessionRepo.updateTurnStatus(state.sessionId, 'processing');
389
410
  // Send the message to the SDK session
390
411
  await state.handle.send(prompt);
391
412
  // Set up abort controller for this stream
@@ -455,6 +476,9 @@ export class InteractiveSessionService {
455
476
  await this.messageRepo.create(msg);
456
477
  state.currentAssistantBuffer = '';
457
478
  state.toolEventsLog = [];
479
+ // Mark as unread — if user has the chat open, the frontend
480
+ // will immediately call markRead to clear it
481
+ void this.sessionRepo.updateTurnStatus(state.sessionId, 'unread');
458
482
  // Notify subscribers of end-of-turn
459
483
  state.subscribers.forEach((sub) => sub({ delta: '', done: true }));
460
484
  return; // Turn complete
@@ -465,17 +489,9 @@ export class InteractiveSessionService {
465
489
  state.subscribers.forEach((sub) => sub({ delta: '', done: true, log: `Error: ${event.content ?? 'unknown'}` }));
466
490
  break;
467
491
  case 'init':
468
- if (event.label) {
469
- const initDetail = [event.label, event.detail, event.content]
470
- .filter(Boolean)
471
- .join(' · ');
472
- void this.persistToolEvent(state, 'Session started', initDetail);
473
- state.subscribers.forEach((sub) => sub({
474
- delta: '',
475
- done: false,
476
- activity: { kind: 'system', label: 'Session started', detail: initDetail },
477
- }));
478
- }
492
+ // The SDK emits init on every turn, but we only show "Session started"
493
+ // during boot (handled in completeBootAsync). Ignore it here to avoid
494
+ // spamming the chat with repeated session-started messages.
479
495
  break;
480
496
  case 'api_retry':
481
497
  state.subscribers.forEach((sub) => sub({ delta: '', done: false, log: event.content ?? 'Retrying API call...' }));
@@ -557,8 +573,8 @@ export class InteractiveSessionService {
557
573
  if (state) {
558
574
  await this.stopSession(state.sessionId);
559
575
  }
560
- // Also clear the cached claudeSessionId so next session starts fresh
561
- this.stoppedClaudeSessionIds.delete(featureId);
576
+ // Also clear the cached agentSessionId so next session starts fresh
577
+ this.stoppedAgentSessionIds.delete(featureId);
562
578
  return this.messageRepo.deleteByFeatureId(featureId);
563
579
  }
564
580
  async getSession(sessionId) {
@@ -604,7 +620,17 @@ export class InteractiveSessionService {
604
620
  }
605
621
  }
606
622
  else {
607
- // No active session — boot one and queue the message
623
+ // No in-memory session — check DB for an orphaned active session (e.g. after
624
+ // service restart / hot-reload) and mark it stopped before booting a new one.
625
+ // The agentSessionId is persisted in DB so startSession will pick it up for
626
+ // SDK session resumption.
627
+ const dbSession = await this.sessionRepo.findByFeatureId(featureId);
628
+ if (dbSession &&
629
+ (dbSession.status === InteractiveSessionStatus.ready ||
630
+ dbSession.status === InteractiveSessionStatus.booting)) {
631
+ await this.sessionRepo.updateStatus(dbSession.id, InteractiveSessionStatus.stopped, new Date());
632
+ }
633
+ // Boot a new session — startSession will find the agentSessionId from DB
608
634
  const session = await this.startSession(featureId, worktreePath);
609
635
  const newState = this.sessions.get(session.id);
610
636
  if (newState) {
@@ -631,7 +657,7 @@ export class InteractiveSessionService {
631
657
  const displayModel = state.model ?? 'claude-sonnet-4-6';
632
658
  sessionInfo = {
633
659
  pid: null, // SDK manages process internally
634
- sessionId: state.claudeSessionId ?? state.sessionId,
660
+ sessionId: state.agentSessionId ?? state.sessionId,
635
661
  model: displayModel,
636
662
  startedAt: dbSession?.startedAt
637
663
  ? new Date(dbSession.startedAt).toISOString()
@@ -665,7 +691,22 @@ export class InteractiveSessionService {
665
691
  }
666
692
  }
667
693
  }
668
- return { messages, sessionStatus, streamingText, sessionInfo };
694
+ // Resolve turn status from DB
695
+ let turnStatus = 'idle';
696
+ const activeState = state;
697
+ if (activeState) {
698
+ const statuses = await this.sessionRepo.getTurnStatuses([featureId]);
699
+ turnStatus = statuses.get(featureId) ?? 'idle';
700
+ }
701
+ else {
702
+ // Check DB for the latest session's turn status
703
+ const latest = await this.sessionRepo.findByFeatureId(featureId);
704
+ if (latest) {
705
+ const statuses = await this.sessionRepo.getTurnStatuses([featureId]);
706
+ turnStatus = statuses.get(featureId) ?? 'idle';
707
+ }
708
+ }
709
+ return { messages, sessionStatus, streamingText, sessionInfo, turnStatus };
669
710
  }
670
711
  subscribeByFeature(featureId, onChunk) {
671
712
  const state = this.findActiveStateForFeature(featureId);
@@ -693,6 +734,22 @@ export class InteractiveSessionService {
693
734
  await this.messageRepo.create(msg);
694
735
  await this.stopSession(state.sessionId);
695
736
  }
737
+ async markRead(featureId) {
738
+ // Find the active session for this feature and clear unread status
739
+ const state = this.findActiveStateForFeature(featureId);
740
+ if (state) {
741
+ void this.sessionRepo.updateTurnStatus(state.sessionId, 'idle');
742
+ return;
743
+ }
744
+ // Fallback: check DB for the latest active session
745
+ const latest = await this.sessionRepo.findByFeatureId(featureId);
746
+ if (latest) {
747
+ void this.sessionRepo.updateTurnStatus(latest.id, 'idle');
748
+ }
749
+ }
750
+ async getTurnStatuses(featureIds) {
751
+ return this.sessionRepo.getTurnStatuses(featureIds);
752
+ }
696
753
  /** Find the in-memory state for an active session for a feature. */
697
754
  findActiveStateForFeature(featureId) {
698
755
  for (const state of this.sessions.values()) {
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Mark chat as read API.
3
+ *
4
+ * POST /api/interactive/chat/[featureId]/mark-read
5
+ *
6
+ * Clears the 'unread' turn status to 'idle'. Called when the user
7
+ * opens/views the chat tab for a feature.
8
+ */
9
+ import type { NextRequest } from 'next/server';
10
+ import { NextResponse } from 'next/server';
11
+ export declare const dynamic = "force-dynamic";
12
+ interface RouteParams {
13
+ params: Promise<{
14
+ featureId: string;
15
+ }>;
16
+ }
17
+ export declare function POST(_request: NextRequest, { params }: RouteParams): Promise<NextResponse>;
18
+ export {};
19
+ //# sourceMappingURL=route.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../../../../../../../../../src/presentation/web/app/api/interactive/chat/[featureId]/mark-read/route.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAI3C,eAAO,MAAM,OAAO,kBAAkB,CAAC;AAEvC,UAAU,WAAW;IACnB,MAAM,EAAE,OAAO,CAAC;QAAE,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACxC;AAED,wBAAsB,IAAI,CAAC,QAAQ,EAAE,WAAW,EAAE,EAAE,MAAM,EAAE,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC,CAchG"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Mark chat as read API.
3
+ *
4
+ * POST /api/interactive/chat/[featureId]/mark-read
5
+ *
6
+ * Clears the 'unread' turn status to 'idle'. Called when the user
7
+ * opens/views the chat tab for a feature.
8
+ */
9
+ import { NextResponse } from 'next/server';
10
+ import { resolve } from '../../../../../../lib/server-container.js';
11
+ export const dynamic = 'force-dynamic';
12
+ export async function POST(_request, { params }) {
13
+ try {
14
+ const { featureId } = await params;
15
+ const service = resolve('IInteractiveSessionService');
16
+ await service.markRead(featureId);
17
+ return NextResponse.json({ ok: true });
18
+ }
19
+ catch (error) {
20
+ // eslint-disable-next-line no-console
21
+ console.error('[POST /api/interactive/chat/:featureId/mark-read]', error);
22
+ return NextResponse.json({ error: error instanceof Error ? error.message : 'Internal server error' }, { status: 500 });
23
+ }
24
+ }
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Bulk turn-status API.
3
+ *
4
+ * GET /api/interactive/chat/turn-statuses?featureIds=id1,id2,...
5
+ *
6
+ * Returns a map of featureId → turnStatus ('idle' | 'processing' | 'unread')
7
+ * for all requested features. Used by UI dot indicators on chat buttons.
8
+ */
9
+ import type { NextRequest } from 'next/server';
10
+ import { NextResponse } from 'next/server';
11
+ export declare const dynamic = "force-dynamic";
12
+ export declare function GET(request: NextRequest): Promise<NextResponse>;
13
+ //# sourceMappingURL=route.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../../../../../../../../src/presentation/web/app/api/interactive/chat/turn-statuses/route.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAI3C,eAAO,MAAM,OAAO,kBAAkB,CAAC;AAEvC,wBAAsB,GAAG,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC,CA8BrE"}