conductor-oss 0.2.14 → 0.2.16

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 (714) hide show
  1. package/dist/commands/start.d.ts.map +1 -1
  2. package/dist/commands/start.js +50 -13
  3. package/dist/commands/start.js.map +1 -1
  4. package/node_modules/@conductor-oss/plugin-agent-amp/package.json +1 -1
  5. package/node_modules/@conductor-oss/plugin-agent-ccr/package.json +1 -1
  6. package/node_modules/@conductor-oss/plugin-agent-claude-code/package.json +1 -1
  7. package/node_modules/@conductor-oss/plugin-agent-codex/package.json +1 -1
  8. package/node_modules/@conductor-oss/plugin-agent-cursor-cli/package.json +1 -1
  9. package/node_modules/@conductor-oss/plugin-agent-droid/package.json +1 -1
  10. package/node_modules/@conductor-oss/plugin-agent-gemini/package.json +1 -1
  11. package/node_modules/@conductor-oss/plugin-agent-github-copilot/package.json +1 -1
  12. package/node_modules/@conductor-oss/plugin-agent-opencode/package.json +1 -1
  13. package/node_modules/@conductor-oss/plugin-agent-qwen-code/package.json +1 -1
  14. package/node_modules/@conductor-oss/plugin-mcp-server/package.json +1 -1
  15. package/node_modules/@conductor-oss/plugin-notifier-desktop/package.json +1 -1
  16. package/node_modules/@conductor-oss/plugin-notifier-discord/package.json +1 -1
  17. package/node_modules/@conductor-oss/plugin-runtime-tmux/package.json +1 -1
  18. package/node_modules/@conductor-oss/plugin-scm-github/package.json +1 -1
  19. package/node_modules/@conductor-oss/plugin-terminal-web/package.json +1 -1
  20. package/node_modules/@conductor-oss/plugin-tracker-github/package.json +1 -1
  21. package/node_modules/@conductor-oss/plugin-webhook/package.json +1 -1
  22. package/node_modules/@conductor-oss/plugin-workspace-worktree/package.json +1 -1
  23. package/package.json +21 -21
  24. package/web/.next/standalone/packages/web/.env.example +16 -0
  25. package/web/.next/standalone/packages/web/.next/BUILD_ID +1 -1
  26. package/web/.next/standalone/packages/web/.next/app-path-routes-manifest.json +30 -0
  27. package/web/.next/standalone/packages/web/.next/build-manifest.json +2 -2
  28. package/web/.next/standalone/packages/web/.next/prerender-manifest.json +3 -3
  29. package/web/.next/standalone/packages/web/.next/routes-manifest.json +204 -0
  30. package/web/.next/standalone/packages/web/.next/server/app/_global-error/page.js +2 -2
  31. package/web/.next/standalone/packages/web/.next/server/app/_global-error/page.js.nft.json +1 -1
  32. package/web/.next/standalone/packages/web/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  33. package/web/.next/standalone/packages/web/.next/server/app/_global-error.html +2 -2
  34. package/web/.next/standalone/packages/web/.next/server/app/_global-error.rsc +1 -1
  35. package/web/.next/standalone/packages/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  36. package/web/.next/standalone/packages/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  37. package/web/.next/standalone/packages/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  38. package/web/.next/standalone/packages/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  39. package/web/.next/standalone/packages/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  40. package/web/.next/standalone/packages/web/.next/server/app/_not-found/page/server-reference-manifest.json +7 -7
  41. package/web/.next/standalone/packages/web/.next/server/app/_not-found/page.js +2 -2
  42. package/web/.next/standalone/packages/web/.next/server/app/_not-found/page.js.nft.json +1 -1
  43. package/web/.next/standalone/packages/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  44. package/web/.next/standalone/packages/web/.next/server/app/_not-found.html +1 -1
  45. package/web/.next/standalone/packages/web/.next/server/app/_not-found.rsc +3 -3
  46. package/web/.next/standalone/packages/web/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
  47. package/web/.next/standalone/packages/web/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  48. package/web/.next/standalone/packages/web/.next/server/app/_not-found.segments/_index.segment.rsc +3 -3
  49. package/web/.next/standalone/packages/web/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  50. package/web/.next/standalone/packages/web/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  51. package/web/.next/standalone/packages/web/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  52. package/web/.next/standalone/packages/web/.next/server/app/api/access/route/app-paths-manifest.json +3 -0
  53. package/web/.next/standalone/packages/web/.next/server/app/api/access/route/build-manifest.json +11 -0
  54. package/web/.next/standalone/packages/web/.next/server/app/api/access/route/server-reference-manifest.json +4 -0
  55. package/web/.next/standalone/packages/web/.next/server/app/api/access/route.js +11 -0
  56. package/web/.next/standalone/packages/web/.next/server/app/api/access/route.js.map +5 -0
  57. package/web/.next/standalone/packages/web/.next/server/app/api/access/route.js.nft.json +1 -0
  58. package/web/.next/standalone/packages/web/.next/server/app/api/access/route_client-reference-manifest.js +2 -0
  59. package/web/.next/standalone/packages/web/.next/server/app/api/agents/route.js +4 -3
  60. package/web/.next/standalone/packages/web/.next/server/app/api/agents/route.js.nft.json +1 -1
  61. package/web/.next/standalone/packages/web/.next/server/app/api/attachments/route/app-paths-manifest.json +3 -0
  62. package/web/.next/standalone/packages/web/.next/server/app/api/attachments/route/build-manifest.json +11 -0
  63. package/web/.next/standalone/packages/web/.next/server/app/api/attachments/route/server-reference-manifest.json +4 -0
  64. package/web/.next/standalone/packages/web/.next/server/app/api/attachments/route.js +10 -0
  65. package/web/.next/standalone/packages/web/.next/server/app/api/attachments/route.js.map +5 -0
  66. package/web/.next/standalone/packages/web/.next/server/app/api/attachments/route.js.nft.json +1 -0
  67. package/web/.next/standalone/packages/web/.next/server/app/api/attachments/route_client-reference-manifest.js +2 -0
  68. package/web/.next/standalone/packages/web/.next/server/app/api/auth/session/route/app-paths-manifest.json +3 -0
  69. package/web/.next/standalone/packages/web/.next/server/app/api/auth/session/route/build-manifest.json +11 -0
  70. package/web/.next/standalone/packages/web/.next/server/app/api/auth/session/route/server-reference-manifest.json +4 -0
  71. package/web/.next/standalone/packages/web/.next/server/app/api/auth/session/route.js +8 -0
  72. package/web/.next/standalone/packages/web/.next/server/app/api/auth/session/route.js.map +5 -0
  73. package/web/.next/standalone/packages/web/.next/server/app/api/auth/session/route.js.nft.json +1 -0
  74. package/web/.next/standalone/packages/web/.next/server/app/api/auth/session/route_client-reference-manifest.js +2 -0
  75. package/web/.next/standalone/packages/web/.next/server/app/api/boards/route/app-paths-manifest.json +3 -0
  76. package/web/.next/standalone/packages/web/.next/server/app/api/boards/route/build-manifest.json +11 -0
  77. package/web/.next/standalone/packages/web/.next/server/app/api/boards/route/server-reference-manifest.json +4 -0
  78. package/web/.next/standalone/packages/web/.next/server/app/api/boards/route.js +12 -0
  79. package/web/.next/standalone/packages/web/.next/server/app/api/boards/route.js.map +5 -0
  80. package/web/.next/standalone/packages/web/.next/server/app/api/boards/route.js.nft.json +1 -0
  81. package/web/.next/standalone/packages/web/.next/server/app/api/boards/route_client-reference-manifest.js +2 -0
  82. package/web/.next/standalone/packages/web/.next/server/app/api/config/route/app-paths-manifest.json +3 -0
  83. package/web/.next/standalone/packages/web/.next/server/app/api/config/route/build-manifest.json +11 -0
  84. package/web/.next/standalone/packages/web/.next/server/app/api/config/route/server-reference-manifest.json +4 -0
  85. package/web/.next/standalone/packages/web/.next/server/app/api/config/route.js +10 -0
  86. package/web/.next/standalone/packages/web/.next/server/app/api/config/route.js.map +5 -0
  87. package/web/.next/standalone/packages/web/.next/server/app/api/config/route.js.nft.json +1 -0
  88. package/web/.next/standalone/packages/web/.next/server/app/api/config/route_client-reference-manifest.js +2 -0
  89. package/web/.next/standalone/packages/web/.next/server/app/api/context-files/route/app-paths-manifest.json +3 -0
  90. package/web/.next/standalone/packages/web/.next/server/app/api/context-files/route/build-manifest.json +11 -0
  91. package/web/.next/standalone/packages/web/.next/server/app/api/context-files/route/server-reference-manifest.json +4 -0
  92. package/web/.next/standalone/packages/web/.next/server/app/api/context-files/route.js +10 -0
  93. package/web/.next/standalone/packages/web/.next/server/app/api/context-files/route.js.map +5 -0
  94. package/web/.next/standalone/packages/web/.next/server/app/api/context-files/route.js.nft.json +1 -0
  95. package/web/.next/standalone/packages/web/.next/server/app/api/context-files/route_client-reference-manifest.js +2 -0
  96. package/web/.next/standalone/packages/web/.next/server/app/api/events/route/app-paths-manifest.json +3 -0
  97. package/web/.next/standalone/packages/web/.next/server/app/api/events/route/build-manifest.json +11 -0
  98. package/web/.next/standalone/packages/web/.next/server/app/api/events/route/server-reference-manifest.json +4 -0
  99. package/web/.next/standalone/packages/web/.next/server/app/api/events/route.js +10 -0
  100. package/web/.next/standalone/packages/web/.next/server/app/api/events/route.js.map +5 -0
  101. package/web/.next/standalone/packages/web/.next/server/app/api/events/route.js.nft.json +1 -0
  102. package/web/.next/standalone/packages/web/.next/server/app/api/events/route_client-reference-manifest.js +2 -0
  103. package/web/.next/standalone/packages/web/.next/server/app/api/filesystem/directory/route/app-paths-manifest.json +3 -0
  104. package/web/.next/standalone/packages/web/.next/server/app/api/filesystem/directory/route/build-manifest.json +11 -0
  105. package/web/.next/standalone/packages/web/.next/server/app/api/filesystem/directory/route/server-reference-manifest.json +4 -0
  106. package/web/.next/standalone/packages/web/.next/server/app/api/filesystem/directory/route.js +10 -0
  107. package/web/.next/standalone/packages/web/.next/server/app/api/filesystem/directory/route.js.map +5 -0
  108. package/web/.next/standalone/packages/web/.next/server/app/api/filesystem/directory/route.js.nft.json +1 -0
  109. package/web/.next/standalone/packages/web/.next/server/app/api/filesystem/directory/route_client-reference-manifest.js +2 -0
  110. package/web/.next/standalone/packages/web/.next/server/app/api/github/repos/route/app-paths-manifest.json +3 -0
  111. package/web/.next/standalone/packages/web/.next/server/app/api/github/repos/route/build-manifest.json +11 -0
  112. package/web/.next/standalone/packages/web/.next/server/app/api/github/repos/route/server-reference-manifest.json +4 -0
  113. package/web/.next/standalone/packages/web/.next/server/app/api/github/repos/route.js +10 -0
  114. package/web/.next/standalone/packages/web/.next/server/app/api/github/repos/route.js.map +5 -0
  115. package/web/.next/standalone/packages/web/.next/server/app/api/github/repos/route.js.nft.json +1 -0
  116. package/web/.next/standalone/packages/web/.next/server/app/api/github/repos/route_client-reference-manifest.js +2 -0
  117. package/web/.next/standalone/packages/web/.next/server/app/api/health/boards/route/app-paths-manifest.json +3 -0
  118. package/web/.next/standalone/packages/web/.next/server/app/api/health/boards/route/build-manifest.json +11 -0
  119. package/web/.next/standalone/packages/web/.next/server/app/api/health/boards/route/server-reference-manifest.json +4 -0
  120. package/web/.next/standalone/packages/web/.next/server/app/api/health/boards/route.js +10 -0
  121. package/web/.next/standalone/packages/web/.next/server/app/api/health/boards/route.js.map +5 -0
  122. package/web/.next/standalone/packages/web/.next/server/app/api/health/boards/route.js.nft.json +1 -0
  123. package/web/.next/standalone/packages/web/.next/server/app/api/health/boards/route_client-reference-manifest.js +2 -0
  124. package/web/.next/standalone/packages/web/.next/server/app/api/health/sessions/route/app-paths-manifest.json +3 -0
  125. package/web/.next/standalone/packages/web/.next/server/app/api/health/sessions/route/build-manifest.json +11 -0
  126. package/web/.next/standalone/packages/web/.next/server/app/api/health/sessions/route/server-reference-manifest.json +4 -0
  127. package/web/.next/standalone/packages/web/.next/server/app/api/health/sessions/route.js +10 -0
  128. package/web/.next/standalone/packages/web/.next/server/app/api/health/sessions/route.js.map +5 -0
  129. package/web/.next/standalone/packages/web/.next/server/app/api/health/sessions/route.js.nft.json +1 -0
  130. package/web/.next/standalone/packages/web/.next/server/app/api/health/sessions/route_client-reference-manifest.js +2 -0
  131. package/web/.next/standalone/packages/web/.next/server/app/api/notifications/route/app-paths-manifest.json +3 -0
  132. package/web/.next/standalone/packages/web/.next/server/app/api/notifications/route/build-manifest.json +11 -0
  133. package/web/.next/standalone/packages/web/.next/server/app/api/notifications/route/server-reference-manifest.json +4 -0
  134. package/web/.next/standalone/packages/web/.next/server/app/api/notifications/route.js +10 -0
  135. package/web/.next/standalone/packages/web/.next/server/app/api/notifications/route.js.map +5 -0
  136. package/web/.next/standalone/packages/web/.next/server/app/api/notifications/route.js.nft.json +1 -0
  137. package/web/.next/standalone/packages/web/.next/server/app/api/notifications/route_client-reference-manifest.js +2 -0
  138. package/web/.next/standalone/packages/web/.next/server/app/api/preferences/route/app-paths-manifest.json +3 -0
  139. package/web/.next/standalone/packages/web/.next/server/app/api/preferences/route/build-manifest.json +11 -0
  140. package/web/.next/standalone/packages/web/.next/server/app/api/preferences/route/server-reference-manifest.json +4 -0
  141. package/web/.next/standalone/packages/web/.next/server/app/api/preferences/route.js +11 -0
  142. package/web/.next/standalone/packages/web/.next/server/app/api/preferences/route.js.map +5 -0
  143. package/web/.next/standalone/packages/web/.next/server/app/api/preferences/route.js.nft.json +1 -0
  144. package/web/.next/standalone/packages/web/.next/server/app/api/preferences/route_client-reference-manifest.js +2 -0
  145. package/web/.next/standalone/packages/web/.next/server/app/api/repositories/route/app-paths-manifest.json +3 -0
  146. package/web/.next/standalone/packages/web/.next/server/app/api/repositories/route/build-manifest.json +11 -0
  147. package/web/.next/standalone/packages/web/.next/server/app/api/repositories/route/server-reference-manifest.json +4 -0
  148. package/web/.next/standalone/packages/web/.next/server/app/api/repositories/route.js +12 -0
  149. package/web/.next/standalone/packages/web/.next/server/app/api/repositories/route.js.map +5 -0
  150. package/web/.next/standalone/packages/web/.next/server/app/api/repositories/route.js.nft.json +1 -0
  151. package/web/.next/standalone/packages/web/.next/server/app/api/repositories/route_client-reference-manifest.js +2 -0
  152. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/actions/route/app-paths-manifest.json +3 -0
  153. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/actions/route/build-manifest.json +11 -0
  154. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/actions/route/server-reference-manifest.json +4 -0
  155. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/actions/route.js +10 -0
  156. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/actions/route.js.map +5 -0
  157. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/actions/route.js.nft.json +1 -0
  158. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/actions/route_client-reference-manifest.js +2 -0
  159. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/checks/route/app-paths-manifest.json +3 -0
  160. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/checks/route/build-manifest.json +11 -0
  161. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/checks/route/server-reference-manifest.json +4 -0
  162. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/checks/route.js +10 -0
  163. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/checks/route.js.map +5 -0
  164. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/checks/route.js.nft.json +1 -0
  165. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/checks/route_client-reference-manifest.js +2 -0
  166. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/diff/route/app-paths-manifest.json +3 -0
  167. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/diff/route/build-manifest.json +11 -0
  168. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/diff/route/server-reference-manifest.json +4 -0
  169. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/diff/route.js +11 -0
  170. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/diff/route.js.map +5 -0
  171. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/diff/route.js.nft.json +1 -0
  172. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/diff/route_client-reference-manifest.js +2 -0
  173. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/feedback/route/app-paths-manifest.json +3 -0
  174. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/feedback/route/build-manifest.json +11 -0
  175. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/feedback/route/server-reference-manifest.json +4 -0
  176. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/feedback/route.js +10 -0
  177. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/feedback/route.js.map +5 -0
  178. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/feedback/route.js.nft.json +1 -0
  179. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/feedback/route_client-reference-manifest.js +2 -0
  180. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/files/route/app-paths-manifest.json +3 -0
  181. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/files/route/build-manifest.json +11 -0
  182. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/files/route/server-reference-manifest.json +4 -0
  183. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/files/route.js +10 -0
  184. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/files/route.js.map +5 -0
  185. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/files/route.js.nft.json +1 -0
  186. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/files/route_client-reference-manifest.js +2 -0
  187. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/keys/route/app-paths-manifest.json +3 -0
  188. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/keys/route/build-manifest.json +11 -0
  189. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/keys/route/server-reference-manifest.json +4 -0
  190. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/keys/route.js +10 -0
  191. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/keys/route.js.map +5 -0
  192. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/keys/route.js.nft.json +1 -0
  193. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/keys/route_client-reference-manifest.js +2 -0
  194. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/kill/route/app-paths-manifest.json +3 -0
  195. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/kill/route/build-manifest.json +11 -0
  196. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/kill/route/server-reference-manifest.json +4 -0
  197. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/kill/route.js +10 -0
  198. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/kill/route.js.map +5 -0
  199. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/kill/route.js.nft.json +1 -0
  200. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/kill/route_client-reference-manifest.js +2 -0
  201. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/output/route/app-paths-manifest.json +3 -0
  202. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/output/route/build-manifest.json +11 -0
  203. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/output/route/server-reference-manifest.json +4 -0
  204. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/output/route.js +10 -0
  205. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/output/route.js.map +5 -0
  206. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/output/route.js.nft.json +1 -0
  207. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/output/route_client-reference-manifest.js +2 -0
  208. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/output/stream/route/app-paths-manifest.json +3 -0
  209. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/output/stream/route/build-manifest.json +11 -0
  210. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/output/stream/route/server-reference-manifest.json +4 -0
  211. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/output/stream/route.js +10 -0
  212. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/output/stream/route.js.map +5 -0
  213. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/output/stream/route.js.nft.json +1 -0
  214. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/output/stream/route_client-reference-manifest.js +2 -0
  215. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/restore/route/app-paths-manifest.json +3 -0
  216. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/restore/route/build-manifest.json +11 -0
  217. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/restore/route/server-reference-manifest.json +4 -0
  218. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/restore/route.js +10 -0
  219. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/restore/route.js.map +5 -0
  220. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/restore/route.js.nft.json +1 -0
  221. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/restore/route_client-reference-manifest.js +2 -0
  222. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/route/app-paths-manifest.json +3 -0
  223. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/route/build-manifest.json +11 -0
  224. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/route/server-reference-manifest.json +4 -0
  225. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/route.js +10 -0
  226. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/route.js.map +5 -0
  227. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/route.js.nft.json +1 -0
  228. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/route_client-reference-manifest.js +2 -0
  229. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/send/route/app-paths-manifest.json +3 -0
  230. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/send/route/build-manifest.json +11 -0
  231. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/send/route/server-reference-manifest.json +4 -0
  232. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/send/route.js +10 -0
  233. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/send/route.js.map +5 -0
  234. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/send/route.js.nft.json +1 -0
  235. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/send/route_client-reference-manifest.js +2 -0
  236. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/route/app-paths-manifest.json +3 -0
  237. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/route/build-manifest.json +11 -0
  238. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/route/server-reference-manifest.json +4 -0
  239. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/route.js +10 -0
  240. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/route.js.map +5 -0
  241. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/route.js.nft.json +1 -0
  242. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/route_client-reference-manifest.js +2 -0
  243. package/web/.next/standalone/packages/web/.next/server/app/api/spawn/route/app-paths-manifest.json +3 -0
  244. package/web/.next/standalone/packages/web/.next/server/app/api/spawn/route/build-manifest.json +11 -0
  245. package/web/.next/standalone/packages/web/.next/server/app/api/spawn/route/server-reference-manifest.json +4 -0
  246. package/web/.next/standalone/packages/web/.next/server/app/api/spawn/route.js +11 -0
  247. package/web/.next/standalone/packages/web/.next/server/app/api/spawn/route.js.map +5 -0
  248. package/web/.next/standalone/packages/web/.next/server/app/api/spawn/route.js.nft.json +1 -0
  249. package/web/.next/standalone/packages/web/.next/server/app/api/spawn/route_client-reference-manifest.js +2 -0
  250. package/web/.next/standalone/packages/web/.next/server/app/api/workspaces/branches/route/app-paths-manifest.json +3 -0
  251. package/web/.next/standalone/packages/web/.next/server/app/api/workspaces/branches/route/build-manifest.json +11 -0
  252. package/web/.next/standalone/packages/web/.next/server/app/api/workspaces/branches/route/server-reference-manifest.json +4 -0
  253. package/web/.next/standalone/packages/web/.next/server/app/api/workspaces/branches/route.js +10 -0
  254. package/web/.next/standalone/packages/web/.next/server/app/api/workspaces/branches/route.js.map +5 -0
  255. package/web/.next/standalone/packages/web/.next/server/app/api/workspaces/branches/route.js.nft.json +1 -0
  256. package/web/.next/standalone/packages/web/.next/server/app/api/workspaces/branches/route_client-reference-manifest.js +2 -0
  257. package/web/.next/standalone/packages/web/.next/server/app/api/workspaces/route/app-paths-manifest.json +3 -0
  258. package/web/.next/standalone/packages/web/.next/server/app/api/workspaces/route/build-manifest.json +11 -0
  259. package/web/.next/standalone/packages/web/.next/server/app/api/workspaces/route/server-reference-manifest.json +4 -0
  260. package/web/.next/standalone/packages/web/.next/server/app/api/workspaces/route.js +12 -0
  261. package/web/.next/standalone/packages/web/.next/server/app/api/workspaces/route.js.map +5 -0
  262. package/web/.next/standalone/packages/web/.next/server/app/api/workspaces/route.js.nft.json +1 -0
  263. package/web/.next/standalone/packages/web/.next/server/app/api/workspaces/route_client-reference-manifest.js +2 -0
  264. package/web/.next/standalone/packages/web/.next/server/app/auth/grant/route.js +4 -2
  265. package/web/.next/standalone/packages/web/.next/server/app/auth/grant/route.js.nft.json +1 -1
  266. package/web/.next/standalone/packages/web/.next/server/app/icon.svg/route.js +3 -1
  267. package/web/.next/standalone/packages/web/.next/server/app/icon.svg/route.js.nft.json +1 -1
  268. package/web/.next/standalone/packages/web/.next/server/app/index.html +1 -1
  269. package/web/.next/standalone/packages/web/.next/server/app/index.rsc +4 -4
  270. package/web/.next/standalone/packages/web/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  271. package/web/.next/standalone/packages/web/.next/server/app/index.segments/_full.segment.rsc +4 -4
  272. package/web/.next/standalone/packages/web/.next/server/app/index.segments/_head.segment.rsc +1 -1
  273. package/web/.next/standalone/packages/web/.next/server/app/index.segments/_index.segment.rsc +3 -3
  274. package/web/.next/standalone/packages/web/.next/server/app/index.segments/_tree.segment.rsc +2 -2
  275. package/web/.next/standalone/packages/web/.next/server/app/page/react-loadable-manifest.json +1 -1
  276. package/web/.next/standalone/packages/web/.next/server/app/page/server-reference-manifest.json +7 -7
  277. package/web/.next/standalone/packages/web/.next/server/app/page.js +2 -2
  278. package/web/.next/standalone/packages/web/.next/server/app/page.js.nft.json +1 -1
  279. package/web/.next/standalone/packages/web/.next/server/app/page_client-reference-manifest.js +1 -1
  280. package/web/.next/standalone/packages/web/.next/server/app/sessions/[id]/page/server-reference-manifest.json +7 -7
  281. package/web/.next/standalone/packages/web/.next/server/app/sessions/[id]/page.js +2 -2
  282. package/web/.next/standalone/packages/web/.next/server/app/sessions/[id]/page.js.nft.json +1 -1
  283. package/web/.next/standalone/packages/web/.next/server/app/sessions/[id]/page_client-reference-manifest.js +1 -1
  284. package/web/.next/standalone/packages/web/.next/server/app/sign-in/[[...sign-in]]/page/server-reference-manifest.json +7 -7
  285. package/web/.next/standalone/packages/web/.next/server/app/sign-in/[[...sign-in]]/page.js +2 -2
  286. package/web/.next/standalone/packages/web/.next/server/app/sign-in/[[...sign-in]]/page.js.nft.json +1 -1
  287. package/web/.next/standalone/packages/web/.next/server/app/sign-in/[[...sign-in]]/page_client-reference-manifest.js +1 -1
  288. package/web/.next/standalone/packages/web/.next/server/app/unlock/page/server-reference-manifest.json +7 -7
  289. package/web/.next/standalone/packages/web/.next/server/app/unlock/page.js +2 -2
  290. package/web/.next/standalone/packages/web/.next/server/app/unlock/page.js.nft.json +1 -1
  291. package/web/.next/standalone/packages/web/.next/server/app/unlock/page_client-reference-manifest.js +1 -1
  292. package/web/.next/standalone/packages/web/.next/server/app-paths-manifest.json +30 -0
  293. package/web/.next/standalone/packages/web/.next/server/chunks/43d70_next-internal_server_app_api_sessions_[id]_output_stream_route_actions_9bfa500e.js +3 -0
  294. package/web/.next/standalone/packages/web/.next/server/chunks/730ea_web__next-internal_server_app_api_filesystem_directory_route_actions_b1ce53b0.js +3 -0
  295. package/web/.next/standalone/packages/web/.next/server/chunks/730ea_web__next-internal_server_app_api_health_sessions_route_actions_0e6610db.js +3 -0
  296. package/web/.next/standalone/packages/web/.next/server/chunks/730ea_web__next-internal_server_app_api_sessions_[id]_actions_route_actions_e73b30eb.js +3 -0
  297. package/web/.next/standalone/packages/web/.next/server/chunks/730ea_web__next-internal_server_app_api_sessions_[id]_checks_route_actions_a3dedc1e.js +3 -0
  298. package/web/.next/standalone/packages/web/.next/server/chunks/730ea_web__next-internal_server_app_api_sessions_[id]_diff_route_actions_b95fa63b.js +3 -0
  299. package/web/.next/standalone/packages/web/.next/server/chunks/730ea_web__next-internal_server_app_api_sessions_[id]_feedback_route_actions_cb4b8489.js +3 -0
  300. package/web/.next/standalone/packages/web/.next/server/chunks/730ea_web__next-internal_server_app_api_sessions_[id]_files_route_actions_22820f6c.js +3 -0
  301. package/web/.next/standalone/packages/web/.next/server/chunks/730ea_web__next-internal_server_app_api_sessions_[id]_keys_route_actions_2c93e9dc.js +3 -0
  302. package/web/.next/standalone/packages/web/.next/server/chunks/730ea_web__next-internal_server_app_api_sessions_[id]_kill_route_actions_2b9b61d1.js +3 -0
  303. package/web/.next/standalone/packages/web/.next/server/chunks/730ea_web__next-internal_server_app_api_sessions_[id]_output_route_actions_e0641c75.js +3 -0
  304. package/web/.next/standalone/packages/web/.next/server/chunks/730ea_web__next-internal_server_app_api_sessions_[id]_restore_route_actions_41a4c356.js +3 -0
  305. package/web/.next/standalone/packages/web/.next/server/chunks/730ea_web__next-internal_server_app_api_sessions_[id]_send_route_actions_5c1d0b47.js +3 -0
  306. package/web/.next/standalone/packages/web/.next/server/chunks/730ea_web__next-internal_server_app_api_workspaces_branches_route_actions_324a72cd.js +3 -0
  307. package/web/.next/standalone/packages/web/.next/server/chunks/[externals]__f25f12d4._.js +3 -0
  308. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__005aa909._.js +3 -0
  309. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__008d962e._.js +3 -0
  310. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__00cf28e7._.js +3 -0
  311. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__03ff76ee._.js +3 -0
  312. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__06365513._.js +3 -0
  313. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__075f8697._.js +3 -0
  314. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__097be5a7._.js +3 -0
  315. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__09c3bdaf._.js +7 -0
  316. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__0a0f0f01._.js +3 -0
  317. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__1003246b._.js +3 -0
  318. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__11918223._.js +3 -0
  319. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__13ad088c._.js +3 -0
  320. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__1458f8ec._.js +3 -0
  321. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__14b1d4a3._.js +3 -0
  322. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__1741fb8a._.js +3 -0
  323. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__1875f00e._.js +3 -0
  324. package/web/.next/standalone/packages/web/.next/server/chunks/{[root-of-the-server]__9fa7727e._.js → [root-of-the-server]__1aa339ea._.js} +2 -2
  325. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__1beced71._.js +3 -0
  326. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__1ed2e6c1._.js +226 -0
  327. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__1f626a16._.js +129 -0
  328. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__2062aaab._.js +3 -0
  329. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__206c3d8a._.js +3 -0
  330. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__22f8f0d6._.js +129 -0
  331. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__23bebaf9._.js +3 -0
  332. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__2556a816._.js +3 -0
  333. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__25788ed3._.js +54 -0
  334. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__29be362d._.js +3 -0
  335. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__2a83553a._.js +3 -0
  336. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__2c3f6397._.js +3 -0
  337. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__2c909fe3._.js +3 -0
  338. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__2ce39d51._.js +3 -0
  339. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__30921756._.js +3 -0
  340. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__31eea08c._.js +3 -0
  341. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__3d7ad620._.js +3 -0
  342. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__3edd3509._.js +3 -0
  343. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__3f8b49ba._.js +3 -0
  344. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__3f8e82c2._.js +3 -0
  345. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__44d59fd0._.js +3 -0
  346. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__48875cbb._.js +7 -0
  347. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__49c6a20e._.js +3 -0
  348. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__4ac9d639._.js +3 -0
  349. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__4c3fb752._.js +3 -0
  350. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__4ca8b259._.js +3 -0
  351. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__4dab6a6a._.js +3 -0
  352. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__544326ac._.js +3 -0
  353. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__54a218f0._.js +54 -0
  354. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__55e337f7._.js +3 -0
  355. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__5661ca72._.js +3 -0
  356. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__5cd49624._.js +3 -0
  357. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__5e0533de._.js +3 -0
  358. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__5e161db4._.js +3 -0
  359. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__5ebcb223._.js +3 -0
  360. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__5fd609c9._.js +3 -0
  361. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__6023a748._.js +3 -0
  362. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__60cf7bf4._.js +3 -0
  363. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__60ee4897._.js +3 -0
  364. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__6559c1a4._.js +3 -0
  365. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__659938b1._.js +3 -0
  366. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__6712f45a._.js +3 -0
  367. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__69227de6._.js +3 -0
  368. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__6ab08a39._.js +129 -0
  369. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__6cd54de1._.js +3 -0
  370. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__6ce2b5d7._.js +3 -0
  371. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__6cfd00d2._.js +3 -0
  372. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__6d62709d._.js +129 -0
  373. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__6e08e4e4._.js +3 -0
  374. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__749331b0._.js +54 -0
  375. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__74a53184._.js +3 -0
  376. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__7633d324._.js +4 -0
  377. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__76c16426._.js +3 -0
  378. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__778e46a1._.js +129 -0
  379. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__7a26e452._.js +3 -0
  380. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__7ba96fa5._.js +3 -0
  381. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__7e684560._.js +3 -0
  382. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__848eb266._.js +3 -0
  383. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__8596d782._.js +7 -0
  384. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__85d8966b._.js +3 -0
  385. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__86aff2b8._.js +3 -0
  386. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__879cf4d2._.js +3 -0
  387. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__881858fa._.js +3 -0
  388. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__885e3a00._.js +54 -0
  389. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__887ea436._.js +3 -0
  390. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__893f6b3b._.js +3 -0
  391. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__89dfcd05._.js +3 -0
  392. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__8cc5826f._.js +3 -0
  393. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__913af875._.js +3 -0
  394. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__91b42119._.js +3 -0
  395. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__93ce1b75._.js +3 -0
  396. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__96633022._.js +3 -0
  397. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__96951362._.js +3 -0
  398. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__971fcc75._.js +9 -0
  399. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__98c6a6f3._.js +3 -0
  400. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__99da6324._.js +3 -0
  401. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__9c1d09aa._.js +3 -0
  402. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__9f07930d._.js +3 -0
  403. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__9f36b7ec._.js +129 -0
  404. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__9fd08bbc._.js +3 -0
  405. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__a05953cc._.js +3 -0
  406. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__a3766ac1._.js +3 -0
  407. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__a3bfaabf._.js +3 -0
  408. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__a420e374._.js +3 -0
  409. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__a4a33247._.js +54 -0
  410. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__ac544bb5._.js +3 -0
  411. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__ad84d2e0._.js +54 -0
  412. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__b3095e9d._.js +3 -0
  413. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__b59abfbd._.js +3 -0
  414. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__b9692a3c._.js +3 -0
  415. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__bcc08c70._.js +3 -0
  416. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__be051d52._.js +3 -0
  417. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__bea07e07._.js +3 -0
  418. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__bf8faac8._.js +4 -0
  419. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__c1759514._.js +3 -0
  420. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__c2ef2bfc._.js +3 -0
  421. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__c3c6a7bf._.js +3 -0
  422. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__c8618cb1._.js +3 -0
  423. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__ca8a18f8._.js +3 -0
  424. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__cafd7bb3._.js +3 -0
  425. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__cb112606._.js +3 -0
  426. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__cc74ea40._.js +3 -0
  427. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__cd3692a0._.js +3 -0
  428. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__cf3cdecd._.js +3 -0
  429. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__d09e7a99._.js +3 -0
  430. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__d40b50e7._.js +3 -0
  431. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__d4721d30._.js +3 -0
  432. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__d538c110._.js +3 -0
  433. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__d73ea818._.js +3 -0
  434. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__db3d0133._.js +3 -0
  435. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__dd0cf085._.js +3 -0
  436. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__de0f2533._.js +7 -0
  437. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__e113f6df._.js +3 -0
  438. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__e1a418bc._.js +3 -0
  439. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__e6c1d827._.js +3 -0
  440. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__ea69c4ce._.js +3 -0
  441. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__eac16890._.js +3 -0
  442. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__eb1dfcc6._.js +3 -0
  443. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__ee75d43a._.js +3 -0
  444. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__ef773ea6._.js +3 -0
  445. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__f0d15920._.js +3 -0
  446. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__f15cbcfc._.js +3 -0
  447. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__f48eb2d4._.js +3 -0
  448. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__fb6ab669._.js +3 -0
  449. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__fe8419b5._.js +129 -0
  450. package/web/.next/standalone/packages/web/.next/server/chunks/{[root-of-the-server]__667a63ee._.js → node_modules_07d85415._.js} +2 -2
  451. package/web/.next/standalone/packages/web/.next/server/chunks/node_modules_f0726c19._.js +52 -0
  452. package/web/.next/standalone/packages/web/.next/server/chunks/{[root-of-the-server]__d94cee69._.js → node_modules_next_9a15df2c._.js} +2 -2
  453. package/web/.next/standalone/packages/web/.next/server/chunks/node_modules_next_dist_79f1aee4._.js +6 -0
  454. package/web/.next/standalone/packages/web/.next/server/chunks/node_modules_next_dist_esm_build_templates_app-route_0e4dc4f7.js +3 -0
  455. package/web/.next/standalone/packages/web/.next/server/chunks/node_modules_next_dist_esm_build_templates_app-route_dd27f857.js +3 -0
  456. package/web/.next/standalone/packages/web/.next/server/chunks/node_modules_next_dist_esm_build_templates_app-route_e445b36c.js +3 -0
  457. package/web/.next/standalone/packages/web/.next/server/chunks/node_modules_next_dist_esm_build_templates_app-route_f375f3c4.js +28 -0
  458. package/web/.next/standalone/packages/web/.next/server/chunks/node_modules_next_f2da0d3e._.js +14 -0
  459. package/web/.next/standalone/packages/web/.next/server/chunks/node_modules_next_f5199d09._.js +3 -0
  460. package/web/.next/standalone/packages/web/.next/server/chunks/packages_core_dist_index_cdd30418.js +3 -0
  461. package/web/.next/standalone/packages/web/.next/server/chunks/packages_plugins_agent-amp_dist_index_bf3d8239.js +3 -0
  462. package/web/.next/standalone/packages/web/.next/server/chunks/packages_plugins_agent-ccr_dist_index_69cbf726.js +3 -0
  463. package/web/.next/standalone/packages/web/.next/server/chunks/packages_plugins_agent-claude-code_dist_index_31314e43.js +125 -0
  464. package/web/.next/standalone/packages/web/.next/server/chunks/packages_plugins_agent-cursor-cli_dist_index_8d5cc426.js +3 -0
  465. package/web/.next/standalone/packages/web/.next/server/chunks/packages_plugins_agent-droid_dist_index_f731227a.js +3 -0
  466. package/web/.next/standalone/packages/web/.next/server/chunks/packages_plugins_agent-gemini_dist_index_b2d219e8.js +54 -0
  467. package/web/.next/standalone/packages/web/.next/server/chunks/packages_plugins_agent-github-copilot_dist_index_9f80cb45.js +3 -0
  468. package/web/.next/standalone/packages/web/.next/server/chunks/packages_plugins_agent-opencode_dist_index_7c7015da.js +3 -0
  469. package/web/.next/standalone/packages/web/.next/server/chunks/packages_plugins_agent-qwen-code_dist_index_46dd8653.js +3 -0
  470. package/web/.next/standalone/packages/web/.next/server/chunks/packages_plugins_notifier-desktop_dist_index_ef3473f0.js +3 -0
  471. package/web/.next/standalone/packages/web/.next/server/chunks/packages_plugins_notifier-discord_dist_index_34257226.js +3 -0
  472. package/web/.next/standalone/packages/web/.next/server/chunks/packages_plugins_scm-github_dist_index_3b5a621e.js +3 -0
  473. package/web/.next/standalone/packages/web/.next/server/chunks/packages_plugins_terminal-web_dist_index_1e0706d3.js +3 -0
  474. package/web/.next/standalone/packages/web/.next/server/chunks/packages_plugins_tracker-github_dist_index_2d7af62f.js +3 -0
  475. package/web/.next/standalone/packages/web/.next/server/chunks/packages_web__next-internal_server_app_api_access_route_actions_06740e99.js +3 -0
  476. package/web/.next/standalone/packages/web/.next/server/chunks/packages_web__next-internal_server_app_api_attachments_route_actions_4dcb6bab.js +3 -0
  477. package/web/.next/standalone/packages/web/.next/server/chunks/packages_web__next-internal_server_app_api_auth_session_route_actions_078c0ee4.js +3 -0
  478. package/web/.next/standalone/packages/web/.next/server/chunks/packages_web__next-internal_server_app_api_boards_route_actions_160005aa.js +3 -0
  479. package/web/.next/standalone/packages/web/.next/server/chunks/packages_web__next-internal_server_app_api_config_route_actions_ee96617d.js +3 -0
  480. package/web/.next/standalone/packages/web/.next/server/chunks/packages_web__next-internal_server_app_api_context-files_route_actions_e0f9c4a1.js +3 -0
  481. package/web/.next/standalone/packages/web/.next/server/chunks/packages_web__next-internal_server_app_api_events_route_actions_bde0da23.js +3 -0
  482. package/web/.next/standalone/packages/web/.next/server/chunks/packages_web__next-internal_server_app_api_github_repos_route_actions_7eab8e08.js +3 -0
  483. package/web/.next/standalone/packages/web/.next/server/chunks/packages_web__next-internal_server_app_api_health_boards_route_actions_7a65c06e.js +3 -0
  484. package/web/.next/standalone/packages/web/.next/server/chunks/packages_web__next-internal_server_app_api_notifications_route_actions_c5e4154e.js +3 -0
  485. package/web/.next/standalone/packages/web/.next/server/chunks/packages_web__next-internal_server_app_api_preferences_route_actions_858fa484.js +3 -0
  486. package/web/.next/standalone/packages/web/.next/server/chunks/packages_web__next-internal_server_app_api_repositories_route_actions_0232075d.js +3 -0
  487. package/web/.next/standalone/packages/web/.next/server/chunks/packages_web__next-internal_server_app_api_sessions_[id]_route_actions_6fdcb5a6.js +3 -0
  488. package/web/.next/standalone/packages/web/.next/server/chunks/packages_web__next-internal_server_app_api_sessions_route_actions_c6df1747.js +3 -0
  489. package/web/.next/standalone/packages/web/.next/server/chunks/packages_web__next-internal_server_app_api_spawn_route_actions_befa67f2.js +3 -0
  490. package/web/.next/standalone/packages/web/.next/server/chunks/packages_web__next-internal_server_app_api_workspaces_route_actions_795ab8d9.js +3 -0
  491. package/web/.next/standalone/packages/web/.next/server/chunks/packages_web_src_lib_13fee5eb._.js +3 -0
  492. package/web/.next/standalone/packages/web/.next/server/chunks/packages_web_src_lib_d64596cc._.js +3 -0
  493. package/web/.next/standalone/packages/web/.next/server/chunks/ssr/[root-of-the-server]__09178ceb._.js +3 -0
  494. package/web/.next/standalone/packages/web/.next/server/chunks/ssr/{[root-of-the-server]__2b5e3ef2._.js → [root-of-the-server]__504277b5._.js} +2 -2
  495. package/web/.next/standalone/packages/web/.next/server/chunks/ssr/{[root-of-the-server]__b07a94f8._.js → [root-of-the-server]__525ee5d4._.js} +2 -2
  496. package/web/.next/standalone/packages/web/.next/server/chunks/ssr/[root-of-the-server]__6622b514._.js +4 -0
  497. package/web/.next/standalone/packages/web/.next/server/chunks/ssr/[root-of-the-server]__869d9ac0._.js +4 -0
  498. package/web/.next/standalone/packages/web/.next/server/chunks/ssr/{[root-of-the-server]__8b0f5149._.js → [root-of-the-server]__9726f664._.js} +2 -2
  499. package/web/.next/standalone/packages/web/.next/server/chunks/ssr/[root-of-the-server]__b3463b25._.js +3 -0
  500. package/web/.next/standalone/packages/web/.next/server/chunks/ssr/[root-of-the-server]__ca05f4a0._.js +4 -0
  501. package/web/.next/standalone/packages/web/.next/server/chunks/ssr/[root-of-the-server]__dd8d1ff5._.js +3 -0
  502. package/web/.next/standalone/packages/web/.next/server/chunks/ssr/_0e1412de._.js +1 -1
  503. package/web/.next/standalone/packages/web/.next/server/chunks/ssr/_69e05fca._.js +1 -1
  504. package/web/.next/standalone/packages/web/.next/server/chunks/ssr/_80efe193._.js +1 -1
  505. package/web/.next/standalone/packages/web/.next/server/chunks/ssr/_b6d31783._.js +1 -1
  506. package/web/.next/standalone/packages/web/.next/server/chunks/ssr/_c0f0e227._.js +1 -1
  507. package/web/.next/standalone/packages/web/.next/server/chunks/ssr/_f36ddaa9._.js +1 -1
  508. package/web/.next/standalone/packages/web/.next/server/chunks/ssr/node_modules_@clerk_nextjs_dist_esm_app-router_8a444735._.js +3 -0
  509. package/web/.next/standalone/packages/web/.next/server/chunks/ssr/{node_modules_@clerk_nextjs_dist_esm_app-router_e6149c9a._.js → node_modules_@clerk_nextjs_dist_esm_app-router_bf11b471._.js} +2 -2
  510. package/web/.next/standalone/packages/web/.next/server/chunks/ssr/node_modules_f2ebd7a9._.js +1 -1
  511. package/web/.next/standalone/packages/web/.next/server/chunks/ssr/{packages_web_src_components_c5066942._.js → packages_web_src_components_dd296b40._.js} +1 -1
  512. package/web/.next/standalone/packages/web/.next/server/middleware.js +2 -2
  513. package/web/.next/standalone/packages/web/.next/server/pages/404.html +1 -1
  514. package/web/.next/standalone/packages/web/.next/server/pages/500.html +2 -2
  515. package/web/.next/standalone/packages/web/.next/server/server-reference-manifest.js +1 -1
  516. package/web/.next/standalone/packages/web/.next/server/server-reference-manifest.json +8 -8
  517. package/web/.next/standalone/packages/web/.next/static/chunks/19d7d4e2cfe3261a.js +1 -0
  518. package/web/.next/standalone/packages/web/.next/static/chunks/{fb2aaa0b70c75a5e.js → 86bce89c37cf6212.js} +1 -1
  519. package/web/.next/standalone/packages/web/.next/static/chunks/{9b34f9af98cb77d6.js → ab8ef6c7dfc78082.js} +1 -1
  520. package/web/.next/standalone/packages/web/.next/static/chunks/{8d30faf57f99d301.js → e8283780c26eaa91.js} +1 -1
  521. package/web/.next/{static/chunks/89cba525f11c75a6.js → standalone/packages/web/.next/static/chunks/e88fa6d41d743b9e.js} +2 -2
  522. package/web/.next/{static/chunks/c0b1f9af564807f3.css → standalone/packages/web/.next/static/chunks/fe557eb4039d8a8d.css} +1 -1
  523. package/web/.next/standalone/packages/web/next.config.ts +33 -0
  524. package/web/.next/standalone/packages/web/postcss.config.mjs +5 -0
  525. package/web/.next/standalone/packages/web/public/agents/amp-dark.svg +13 -0
  526. package/web/.next/standalone/packages/web/public/agents/amp-light.svg +13 -0
  527. package/web/.next/standalone/packages/web/public/agents/claude-dark.svg +3 -0
  528. package/web/.next/standalone/packages/web/public/agents/claude-light.svg +3 -0
  529. package/web/.next/standalone/packages/web/public/agents/codex-dark.svg +13 -0
  530. package/web/.next/standalone/packages/web/public/agents/codex-light.svg +13 -0
  531. package/web/.next/standalone/packages/web/public/agents/copilot-dark.svg +3 -0
  532. package/web/.next/standalone/packages/web/public/agents/copilot-light.svg +3 -0
  533. package/web/.next/standalone/packages/web/public/agents/cursor-dark.svg +10 -0
  534. package/web/.next/standalone/packages/web/public/agents/cursor-light.svg +10 -0
  535. package/web/.next/standalone/packages/web/public/agents/droid-dark.svg +16 -0
  536. package/web/.next/standalone/packages/web/public/agents/droid-light.svg +16 -0
  537. package/web/.next/standalone/packages/web/public/agents/gemini-dark.svg +13 -0
  538. package/web/.next/standalone/packages/web/public/agents/gemini-light.svg +13 -0
  539. package/web/.next/standalone/packages/web/public/agents/opencode-dark.svg +21 -0
  540. package/web/.next/standalone/packages/web/public/agents/opencode-light.svg +21 -0
  541. package/web/.next/standalone/packages/web/public/agents/qwen-dark.svg +3 -0
  542. package/web/.next/standalone/packages/web/public/agents/qwen-light.svg +3 -0
  543. package/web/.next/standalone/packages/web/public/icons/editors/logseq.svg +1 -0
  544. package/web/.next/standalone/packages/web/public/icons/editors/typora-32.png +0 -0
  545. package/web/.next/standalone/packages/web/public/icons/editors/typora.png +0 -0
  546. package/web/.next/standalone/packages/web/public/icons/ide/antigravity-dark.svg +4 -0
  547. package/web/.next/standalone/packages/web/public/icons/ide/antigravity-light.svg +4 -0
  548. package/web/.next/standalone/packages/web/public/icons/ide/cursor-dark.svg +12 -0
  549. package/web/.next/standalone/packages/web/public/icons/ide/cursor-light.svg +12 -0
  550. package/web/.next/standalone/packages/web/public/icons/ide/intellij.svg +19 -0
  551. package/web/.next/standalone/packages/web/public/icons/ide/vscode-dark.svg +57 -0
  552. package/web/.next/standalone/packages/web/public/icons/ide/vscode-insiders.svg +2 -0
  553. package/web/.next/standalone/packages/web/public/icons/ide/vscode-light.svg +41 -0
  554. package/web/.next/standalone/packages/web/public/icons/ide/windsurf-dark.svg +3 -0
  555. package/web/.next/standalone/packages/web/public/icons/ide/windsurf-light.svg +3 -0
  556. package/web/.next/standalone/packages/web/public/icons/ide/xcode.svg +1 -0
  557. package/web/.next/standalone/packages/web/public/icons/ide/zed-dark.svg +3 -0
  558. package/web/.next/standalone/packages/web/public/icons/ide/zed-light.svg +3 -0
  559. package/web/.next/standalone/packages/web/src/app/api/access/route.ts +214 -0
  560. package/web/.next/standalone/packages/web/src/app/api/agents/route.ts +223 -0
  561. package/web/.next/standalone/packages/web/src/app/api/attachments/route.ts +169 -0
  562. package/web/.next/standalone/packages/web/src/app/api/auth/session/route.ts +54 -0
  563. package/web/.next/standalone/packages/web/src/app/api/boards/route.ts +520 -0
  564. package/web/.next/standalone/packages/web/src/app/api/config/route.ts +81 -0
  565. package/web/.next/standalone/packages/web/src/app/api/context-files/route.ts +201 -0
  566. package/web/.next/standalone/packages/web/src/app/api/events/route.ts +125 -0
  567. package/web/.next/standalone/packages/web/src/app/api/filesystem/directory/route.ts +145 -0
  568. package/web/.next/standalone/packages/web/src/app/api/github/repos/route.ts +106 -0
  569. package/web/.next/standalone/packages/web/src/app/api/health/boards/route.ts +72 -0
  570. package/web/.next/standalone/packages/web/src/app/api/health/sessions/route.ts +77 -0
  571. package/web/.next/standalone/packages/web/src/app/api/notifications/route.ts +91 -0
  572. package/web/.next/standalone/packages/web/src/app/api/preferences/route.ts +194 -0
  573. package/web/.next/standalone/packages/web/src/app/api/repositories/route.ts +419 -0
  574. package/web/.next/standalone/packages/web/src/app/api/sessions/[id]/actions/route.ts +80 -0
  575. package/web/.next/standalone/packages/web/src/app/api/sessions/[id]/checks/route.ts +175 -0
  576. package/web/.next/standalone/packages/web/src/app/api/sessions/[id]/diff/route.ts +426 -0
  577. package/web/.next/standalone/packages/web/src/app/api/sessions/[id]/feedback/route.ts +47 -0
  578. package/web/.next/standalone/packages/web/src/app/api/sessions/[id]/files/route.ts +197 -0
  579. package/web/.next/standalone/packages/web/src/app/api/sessions/[id]/keys/route.ts +140 -0
  580. package/web/.next/standalone/packages/web/src/app/api/sessions/[id]/kill/route.ts +45 -0
  581. package/web/.next/standalone/packages/web/src/app/api/sessions/[id]/output/route.ts +262 -0
  582. package/web/.next/standalone/packages/web/src/app/api/sessions/[id]/output/stream/route.ts +111 -0
  583. package/web/.next/standalone/packages/web/src/app/api/sessions/[id]/restore/route.ts +49 -0
  584. package/web/.next/standalone/packages/web/src/app/api/sessions/[id]/route.ts +206 -0
  585. package/web/.next/standalone/packages/web/src/app/api/sessions/[id]/send/route.ts +58 -0
  586. package/web/.next/standalone/packages/web/src/app/api/sessions/route.ts +105 -0
  587. package/web/.next/standalone/packages/web/src/app/api/spawn/route.ts +216 -0
  588. package/web/.next/standalone/packages/web/src/app/api/workspaces/branches/route.ts +233 -0
  589. package/web/.next/standalone/packages/web/src/app/api/workspaces/route.ts +592 -0
  590. package/web/.next/standalone/packages/web/src/app/auth/grant/route.ts +37 -0
  591. package/web/.next/standalone/packages/web/src/app/globals.css +206 -0
  592. package/web/.next/standalone/packages/web/src/app/icon.svg +11 -0
  593. package/web/.next/standalone/packages/web/src/app/layout.tsx +65 -0
  594. package/web/.next/standalone/packages/web/src/app/page.tsx +4559 -0
  595. package/web/.next/standalone/packages/web/src/app/sessions/[id]/page.tsx +120 -0
  596. package/web/.next/standalone/packages/web/src/app/sign-in/[[...sign-in]]/page.tsx +11 -0
  597. package/web/.next/standalone/packages/web/src/app/unlock/UnlockForm.tsx +77 -0
  598. package/web/.next/standalone/packages/web/src/app/unlock/page.tsx +41 -0
  599. package/web/.next/standalone/packages/web/src/components/ActivityDot.tsx +93 -0
  600. package/web/.next/standalone/packages/web/src/components/AgentTileIcon.tsx +193 -0
  601. package/web/.next/standalone/packages/web/src/components/Dashboard.tsx +3444 -0
  602. package/web/.next/standalone/packages/web/src/components/EmptyState.tsx +58 -0
  603. package/web/.next/standalone/packages/web/src/components/SessionCard.tsx +377 -0
  604. package/web/.next/standalone/packages/web/src/components/TerminalView.tsx +184 -0
  605. package/web/.next/standalone/packages/web/src/components/ThemeProvider.tsx +55 -0
  606. package/web/.next/standalone/packages/web/src/components/agents/AgentGrid.tsx +95 -0
  607. package/web/.next/standalone/packages/web/src/components/board/WorkspaceKanban.tsx +1316 -0
  608. package/web/.next/standalone/packages/web/src/components/layout/AppShell.tsx +74 -0
  609. package/web/.next/standalone/packages/web/src/components/layout/EmptyState.tsx +53 -0
  610. package/web/.next/standalone/packages/web/src/components/layout/Sidebar.tsx +318 -0
  611. package/web/.next/standalone/packages/web/src/components/layout/TopBar.tsx +34 -0
  612. package/web/.next/standalone/packages/web/src/components/layout/WorkspaceSidebarPanel.tsx +93 -0
  613. package/web/.next/standalone/packages/web/src/components/sessions/ChatPanel.tsx +1559 -0
  614. package/web/.next/standalone/packages/web/src/components/sessions/SessionDetail.tsx +132 -0
  615. package/web/.next/standalone/packages/web/src/components/sessions/SessionDiff.tsx +1197 -0
  616. package/web/.next/standalone/packages/web/src/components/sessions/SessionOverview.tsx +314 -0
  617. package/web/.next/standalone/packages/web/src/components/ui/Badge.tsx +33 -0
  618. package/web/.next/standalone/packages/web/src/components/ui/Button.tsx +53 -0
  619. package/web/.next/standalone/packages/web/src/components/ui/Card.tsx +35 -0
  620. package/web/.next/standalone/packages/web/src/components/ui/RunningDots.tsx +22 -0
  621. package/web/.next/standalone/packages/web/src/components/ui/ScrollArea.tsx +43 -0
  622. package/web/.next/standalone/packages/web/src/components/ui/Separator.tsx +23 -0
  623. package/web/.next/standalone/packages/web/src/components/ui/StatusDot.tsx +30 -0
  624. package/web/.next/standalone/packages/web/src/components/ui/Tabs.tsx +48 -0
  625. package/web/.next/standalone/packages/web/src/components/ui/Tooltip.tsx +44 -0
  626. package/web/.next/standalone/packages/web/src/hooks/useAgents.ts +155 -0
  627. package/web/.next/standalone/packages/web/src/hooks/useConfig.ts +116 -0
  628. package/web/.next/standalone/packages/web/src/hooks/usePreferences.ts +95 -0
  629. package/web/.next/standalone/packages/web/src/hooks/useSession.ts +191 -0
  630. package/web/.next/standalone/packages/web/src/hooks/useSessionFeed.ts +265 -0
  631. package/web/.next/standalone/packages/web/src/hooks/useSessionOutputStream.ts +155 -0
  632. package/web/.next/standalone/packages/web/src/hooks/useSessions.ts +123 -0
  633. package/web/.next/standalone/packages/web/src/lib/accessControl.test.ts +46 -0
  634. package/web/.next/standalone/packages/web/src/lib/accessControl.ts +115 -0
  635. package/web/.next/standalone/packages/web/src/lib/agentUtils.ts +4 -0
  636. package/web/.next/standalone/packages/web/src/lib/auth.ts +457 -0
  637. package/web/.next/standalone/packages/web/src/lib/chatFeed.ts +196 -0
  638. package/web/.next/standalone/packages/web/src/lib/cn.ts +6 -0
  639. package/web/.next/standalone/packages/web/src/lib/edgeAuth.test.ts +91 -0
  640. package/web/.next/standalone/packages/web/src/lib/edgeAuth.ts +205 -0
  641. package/web/.next/standalone/packages/web/src/lib/editorLinks.ts +51 -0
  642. package/web/.next/standalone/packages/web/src/lib/event-bus-singleton.ts +50 -0
  643. package/web/.next/standalone/packages/web/src/lib/liveEvents.ts +49 -0
  644. package/web/.next/standalone/packages/web/src/lib/modelAccess.ts +40 -0
  645. package/web/.next/standalone/packages/web/src/lib/projectConfigSync.ts +144 -0
  646. package/web/.next/standalone/packages/web/src/lib/remoteAuth.ts +104 -0
  647. package/web/.next/standalone/packages/web/src/lib/runtimeAgentModels.test.ts +78 -0
  648. package/web/.next/standalone/packages/web/src/lib/runtimeAgentModels.ts +788 -0
  649. package/web/.next/standalone/packages/web/src/lib/runtimeAgentModelsShared.ts +65 -0
  650. package/web/.next/standalone/packages/web/src/lib/serialize.ts +128 -0
  651. package/web/.next/standalone/packages/web/src/lib/services.ts +319 -0
  652. package/web/.next/standalone/packages/web/src/lib/types.ts +182 -0
  653. package/web/.next/standalone/packages/web/src/proxy.ts +141 -0
  654. package/web/.next/standalone/packages/web/tsconfig.json +42 -0
  655. package/web/.next/standalone/public/agents/amp-dark.svg +13 -0
  656. package/web/.next/standalone/public/agents/amp-light.svg +13 -0
  657. package/web/.next/standalone/public/agents/claude-dark.svg +3 -0
  658. package/web/.next/standalone/public/agents/claude-light.svg +3 -0
  659. package/web/.next/standalone/public/agents/codex-dark.svg +13 -0
  660. package/web/.next/standalone/public/agents/codex-light.svg +13 -0
  661. package/web/.next/standalone/public/agents/copilot-dark.svg +3 -0
  662. package/web/.next/standalone/public/agents/copilot-light.svg +3 -0
  663. package/web/.next/standalone/public/agents/cursor-dark.svg +10 -0
  664. package/web/.next/standalone/public/agents/cursor-light.svg +10 -0
  665. package/web/.next/standalone/public/agents/droid-dark.svg +16 -0
  666. package/web/.next/standalone/public/agents/droid-light.svg +16 -0
  667. package/web/.next/standalone/public/agents/gemini-dark.svg +13 -0
  668. package/web/.next/standalone/public/agents/gemini-light.svg +13 -0
  669. package/web/.next/standalone/public/agents/opencode-dark.svg +21 -0
  670. package/web/.next/standalone/public/agents/opencode-light.svg +21 -0
  671. package/web/.next/standalone/public/agents/qwen-dark.svg +3 -0
  672. package/web/.next/standalone/public/agents/qwen-light.svg +3 -0
  673. package/web/.next/standalone/public/icons/editors/logseq.svg +1 -0
  674. package/web/.next/standalone/public/icons/editors/typora-32.png +0 -0
  675. package/web/.next/standalone/public/icons/editors/typora.png +0 -0
  676. package/web/.next/standalone/public/icons/ide/antigravity-dark.svg +4 -0
  677. package/web/.next/standalone/public/icons/ide/antigravity-light.svg +4 -0
  678. package/web/.next/standalone/public/icons/ide/cursor-dark.svg +12 -0
  679. package/web/.next/standalone/public/icons/ide/cursor-light.svg +12 -0
  680. package/web/.next/standalone/public/icons/ide/intellij.svg +19 -0
  681. package/web/.next/standalone/public/icons/ide/vscode-dark.svg +57 -0
  682. package/web/.next/standalone/public/icons/ide/vscode-insiders.svg +2 -0
  683. package/web/.next/standalone/public/icons/ide/vscode-light.svg +41 -0
  684. package/web/.next/standalone/public/icons/ide/windsurf-dark.svg +3 -0
  685. package/web/.next/standalone/public/icons/ide/windsurf-light.svg +3 -0
  686. package/web/.next/standalone/public/icons/ide/xcode.svg +1 -0
  687. package/web/.next/standalone/public/icons/ide/zed-dark.svg +3 -0
  688. package/web/.next/standalone/public/icons/ide/zed-light.svg +3 -0
  689. package/web/.next/static/chunks/19d7d4e2cfe3261a.js +1 -0
  690. package/web/.next/static/chunks/{fb2aaa0b70c75a5e.js → 86bce89c37cf6212.js} +1 -1
  691. package/web/.next/static/chunks/{9b34f9af98cb77d6.js → ab8ef6c7dfc78082.js} +1 -1
  692. package/web/.next/static/chunks/{8d30faf57f99d301.js → e8283780c26eaa91.js} +1 -1
  693. package/web/.next/{standalone/packages/web/.next/static/chunks/89cba525f11c75a6.js → static/chunks/e88fa6d41d743b9e.js} +2 -2
  694. package/web/.next/{standalone/packages/web/.next/static/chunks/c0b1f9af564807f3.css → static/chunks/fe557eb4039d8a8d.css} +1 -1
  695. package/web/.next/standalone/packages/web/.next/server/chunks/[externals]__0d8e2e8d._.js +0 -3
  696. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__273dc5fd._.js +0 -3
  697. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__30b98e6f._.js +0 -4
  698. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__bbaa7179._.js +0 -3
  699. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__f408c708._.js +0 -21
  700. package/web/.next/standalone/packages/web/.next/server/chunks/ssr/[root-of-the-server]__434b20a4._.js +0 -3
  701. package/web/.next/standalone/packages/web/.next/server/chunks/ssr/[root-of-the-server]__90837659._.js +0 -3
  702. package/web/.next/standalone/packages/web/.next/server/chunks/ssr/[root-of-the-server]__977a17ba._.js +0 -3
  703. package/web/.next/standalone/packages/web/.next/server/chunks/ssr/[root-of-the-server]__bce4b756._.js +0 -4
  704. package/web/.next/standalone/packages/web/.next/server/chunks/ssr/[root-of-the-server]__cb11b5eb._.js +0 -4
  705. package/web/.next/standalone/packages/web/.next/server/chunks/ssr/[root-of-the-server]__d1edf1ae._.js +0 -4
  706. package/web/.next/standalone/packages/web/.next/server/chunks/ssr/node_modules_@clerk_nextjs_dist_esm_app-router_7f2f0b6a._.js +0 -3
  707. package/web/.next/standalone/packages/web/.next/static/chunks/14d26168e413797c.js +0 -1
  708. package/web/.next/static/chunks/14d26168e413797c.js +0 -1
  709. /package/web/.next/standalone/packages/web/.next/static/{l0RhKSC1DfqfJaFwcAKMB → 7KQ5wRS3BC3qvrkz8yxuS}/_buildManifest.js +0 -0
  710. /package/web/.next/standalone/packages/web/.next/static/{l0RhKSC1DfqfJaFwcAKMB → 7KQ5wRS3BC3qvrkz8yxuS}/_clientMiddlewareManifest.json +0 -0
  711. /package/web/.next/standalone/packages/web/.next/static/{l0RhKSC1DfqfJaFwcAKMB → 7KQ5wRS3BC3qvrkz8yxuS}/_ssgManifest.js +0 -0
  712. /package/web/.next/static/{l0RhKSC1DfqfJaFwcAKMB → 7KQ5wRS3BC3qvrkz8yxuS}/_buildManifest.js +0 -0
  713. /package/web/.next/static/{l0RhKSC1DfqfJaFwcAKMB → 7KQ5wRS3BC3qvrkz8yxuS}/_clientMiddlewareManifest.json +0 -0
  714. /package/web/.next/static/{l0RhKSC1DfqfJaFwcAKMB → 7KQ5wRS3BC3qvrkz8yxuS}/_ssgManifest.js +0 -0
@@ -0,0 +1,1559 @@
1
+ "use client";
2
+
3
+ import { useRouter } from "next/navigation";
4
+ import {
5
+ useCallback,
6
+ useEffect,
7
+ useMemo,
8
+ useRef,
9
+ useState,
10
+ type ChangeEvent,
11
+ type ComponentProps,
12
+ type KeyboardEvent,
13
+ } from "react";
14
+ import ReactMarkdown from "react-markdown";
15
+ import remarkGfm from "remark-gfm";
16
+ import {
17
+ BrainCircuit,
18
+ ChevronDown,
19
+ ChevronRight,
20
+ Code2,
21
+ FileSearch2,
22
+ FileText,
23
+ Globe,
24
+ ListTodo,
25
+ Loader2,
26
+ Paperclip,
27
+ PencilLine,
28
+ Search,
29
+ Shield,
30
+ TerminalSquare,
31
+ UserRound,
32
+ Wrench,
33
+ type LucideIcon,
34
+ } from "lucide-react";
35
+ import { AgentTileIcon } from "@/components/AgentTileIcon";
36
+ import { useAgents } from "@/hooks/useAgents";
37
+ import { useSessionFeed } from "@/hooks/useSessionFeed";
38
+ import type { NormalizedChatEntry } from "@/lib/chatFeed";
39
+ import { normalizeAgentName } from "@/lib/agentUtils";
40
+
41
+ interface ChatPanelProps {
42
+ sessionId: string;
43
+ agentName?: string | null;
44
+ projectId?: string | null;
45
+ sessionModel?: string | null;
46
+ sessionReasoningEffort?: string | null;
47
+ }
48
+
49
+ interface AttachmentDraft {
50
+ file: File;
51
+ }
52
+
53
+ interface ModelOption {
54
+ id: string;
55
+ label: string;
56
+ helper: string;
57
+ }
58
+
59
+ interface SlashCommandOption {
60
+ command: string;
61
+ label: string;
62
+ description: string;
63
+ exact?: boolean;
64
+ }
65
+
66
+ const COMMON_SLASH_COMMANDS: SlashCommandOption[] = [
67
+ {
68
+ command: "/help",
69
+ label: "/help",
70
+ description: "Show the agent help and available commands.",
71
+ },
72
+ {
73
+ command: "/model",
74
+ label: "/model",
75
+ description: "Inspect or switch the active model.",
76
+ },
77
+ {
78
+ command: "/clear",
79
+ label: "/clear",
80
+ description: "Clear the current agent conversation context.",
81
+ },
82
+ {
83
+ command: "/review",
84
+ label: "/review",
85
+ description: "Ask the agent to review current changes.",
86
+ },
87
+ {
88
+ command: "/diff",
89
+ label: "/diff",
90
+ description: "Inspect the current diff from inside the agent.",
91
+ },
92
+ ];
93
+
94
+ function formatCurrentModelLabel(agentName: string, modelId: string): string {
95
+ const normalizedModel = modelId.trim();
96
+ const normalizedAgent = normalizeAgentName(agentName);
97
+ if (!normalizedModel) return normalizedModel;
98
+
99
+ if (normalizedAgent === "claude-code") {
100
+ const lower = normalizedModel.toLowerCase();
101
+ if (lower === "opus") return "Claude Opus";
102
+ if (lower === "sonnet") return "Claude Sonnet";
103
+ if (lower === "haiku") return "Claude Haiku";
104
+ const match = lower.match(/^claude-(sonnet|opus|haiku)-(\d+)-(\d+)(?:-\d{8})?$/);
105
+ if (match) {
106
+ const family = match[1];
107
+ return `Claude ${family[0]?.toUpperCase() + family.slice(1)} ${match[2]}.${match[3]}`;
108
+ }
109
+ }
110
+
111
+ return normalizedModel
112
+ .split(/[-_]+/g)
113
+ .filter(Boolean)
114
+ .map((segment) => {
115
+ const lower = segment.toLowerCase();
116
+ if (lower === "gpt") return "GPT";
117
+ if (/^\d+(?:\.\d+)?$/.test(segment)) return segment;
118
+ return segment[0]?.toUpperCase() + segment.slice(1);
119
+ })
120
+ .join("-");
121
+ }
122
+
123
+ function getModelOptions(
124
+ agents: ReturnType<typeof useAgents>["agents"],
125
+ agentName: string,
126
+ currentModel: string,
127
+ ): ModelOption[] {
128
+ const options = new Map<string, ModelOption>();
129
+ const normalizedAgentName = normalizeAgentName(agentName);
130
+
131
+ for (const agent of agents) {
132
+ if (normalizedAgentName && normalizeAgentName(agent.name) !== normalizedAgentName) {
133
+ continue;
134
+ }
135
+ const catalog = agent.runtimeModelCatalog;
136
+ if (!catalog) continue;
137
+
138
+ const modelsByAccess = catalog.modelsByAccess;
139
+ if (!modelsByAccess) continue;
140
+
141
+ for (const modelList of Object.values(modelsByAccess)) {
142
+ if (!Array.isArray(modelList)) continue;
143
+ for (const model of modelList) {
144
+ const id = typeof model.id === "string" ? model.id.trim() : "";
145
+ if (!id || options.has(id)) continue;
146
+ const label = typeof model.label === "string" && model.label.trim().length > 0 ? model.label.trim() : id;
147
+ const helper = typeof agent.name === "string" && agent.name.trim().length > 0 ? agent.name.trim() : "Runtime catalog";
148
+ options.set(id, { id, label, helper });
149
+ }
150
+ }
151
+ }
152
+
153
+ if (currentModel.trim() && !options.has(currentModel.trim())) {
154
+ options.set(currentModel.trim(), {
155
+ id: currentModel.trim(),
156
+ label: formatCurrentModelLabel(agentName, currentModel),
157
+ helper: "Current session model",
158
+ });
159
+ }
160
+
161
+ return [...options.values()].sort((left, right) => left.label.localeCompare(right.label));
162
+ }
163
+
164
+ function getSlashCommandOptions(agentName: string, message: string): SlashCommandOption[] {
165
+ const normalizedMessage = message.trimStart();
166
+ if (!normalizedMessage.startsWith("/")) {
167
+ return [];
168
+ }
169
+
170
+ const normalizedAgent = agentName.trim() || "agent";
171
+ const query = normalizedMessage.toLowerCase();
172
+ const options = new Map<string, SlashCommandOption>();
173
+
174
+ options.set(normalizedMessage, {
175
+ command: normalizedMessage,
176
+ label: normalizedMessage,
177
+ description: `Send this raw slash command directly to ${normalizedAgent}.`,
178
+ exact: true,
179
+ });
180
+
181
+ for (const option of COMMON_SLASH_COMMANDS) {
182
+ const haystack = `${option.command} ${option.label} ${option.description}`.toLowerCase();
183
+ if (!query || haystack.includes(query)) {
184
+ options.set(option.command, option);
185
+ }
186
+ }
187
+
188
+ return [...options.values()];
189
+ }
190
+
191
+ function formatTimestamp(value: string | null): string | null {
192
+ if (!value) return null;
193
+ const timestamp = Date.parse(value);
194
+ if (Number.isNaN(timestamp)) return null;
195
+ return new Intl.DateTimeFormat(undefined, {
196
+ hour: "numeric",
197
+ minute: "2-digit",
198
+ month: "short",
199
+ day: "numeric",
200
+ }).format(new Date(timestamp));
201
+ }
202
+
203
+ function getStatusPresentation(text: string): {
204
+ Icon: LucideIcon;
205
+ compact: boolean;
206
+ showDot: boolean;
207
+ } {
208
+ const normalizedText = text.trim();
209
+
210
+ if (/^thinking\b/i.test(normalizedText)) {
211
+ return { Icon: Code2, compact: true, showDot: false };
212
+ }
213
+
214
+ if (/^searched\b/i.test(normalizedText)) {
215
+ return { Icon: Search, compact: true, showDot: true };
216
+ }
217
+
218
+ if (
219
+ /^(git|pnpm|npm|npx|yarn|cargo|bun|node|ls|cd|cat|rg|find|sed|touch|mkdir|rm|cp|mv|gh|python|uv)\b/i.test(normalizedText)
220
+ || normalizedText.includes("&&")
221
+ ) {
222
+ return { Icon: TerminalSquare, compact: true, showDot: true };
223
+ }
224
+
225
+ if (/session status:/i.test(normalizedText)) {
226
+ return { Icon: Code2, compact: true, showDot: false };
227
+ }
228
+
229
+ return { Icon: Code2, compact: false, showDot: false };
230
+ }
231
+
232
+ function isCommandLikeStatus(text: string): boolean {
233
+ return /^(git|pnpm|npm|npx|yarn|cargo|bun|node|ls|cd|cat|rg|find|sed|touch|mkdir|rm|cp|mv|gh|python|uv)\b/i.test(text.trim())
234
+ || text.includes("&&");
235
+ }
236
+
237
+ function extractComposerSummary(entries: NormalizedChatEntry[]): string | null {
238
+ const candidates = [
239
+ ...entries.map((entry) => entry.text),
240
+ ].map((value) => value.trim()).filter(Boolean);
241
+
242
+ return candidates.find((value) => /files changed/i.test(value) || (/\+\d+/.test(value) && /-\d+/.test(value))) ?? null;
243
+ }
244
+
245
+ function parseComposerSummary(summary: string): {
246
+ label: string;
247
+ additions: string | null;
248
+ deletions: string | null;
249
+ } {
250
+ const match = summary.match(/^(.*?files changed)(?:\s+(\+\d+))?(?:\s+(-\d+))?$/i);
251
+ if (!match) {
252
+ return {
253
+ label: summary,
254
+ additions: null,
255
+ deletions: null,
256
+ };
257
+ }
258
+
259
+ return {
260
+ label: match[1]?.trim() || summary,
261
+ additions: match[2] ?? null,
262
+ deletions: match[3] ?? null,
263
+ };
264
+ }
265
+
266
+ const markdownComponents = {
267
+ a: (props: ComponentProps<"a">) => (
268
+ <a
269
+ {...props}
270
+ target="_blank"
271
+ rel="noreferrer"
272
+ className="text-[#ea7a2a] underline underline-offset-2"
273
+ />
274
+ ),
275
+ p: (props: ComponentProps<"p">) => (
276
+ <p
277
+ {...props}
278
+ className={[props.className, "whitespace-pre-wrap"].filter(Boolean).join(" ")}
279
+ />
280
+ ),
281
+ li: (props: ComponentProps<"li">) => (
282
+ <li
283
+ {...props}
284
+ className={[props.className, "whitespace-pre-wrap"].filter(Boolean).join(" ")}
285
+ />
286
+ ),
287
+ };
288
+
289
+ function SetupScriptHint() {
290
+ return (
291
+ <div className="flex items-start gap-3 rounded-[3px] px-2 py-1 text-[#8f8f8f]">
292
+ <div className="flex h-[21px] w-[21px] items-center justify-center pt-[1px] text-[#8f8f8f]">
293
+ <TerminalSquare className="h-[15px] w-[15px]" strokeWidth={1.6} />
294
+ </div>
295
+ <div className="min-w-0 space-y-[2px]">
296
+ <p className="text-[14px] leading-[21px] text-[#8f8f8f]">Setup Script</p>
297
+ <p className="text-[12px] leading-[18px] text-[#c4c4c4]">
298
+ No setup script configured. Setup scripts run before the coding agent starts.
299
+ </p>
300
+ </div>
301
+ </div>
302
+ );
303
+ }
304
+
305
+ function MarkdownBlock({ text, className }: { text: string; className: string }) {
306
+ return (
307
+ <ReactMarkdown
308
+ className={className}
309
+ remarkPlugins={[remarkGfm]}
310
+ components={markdownComponents}
311
+ >
312
+ {text}
313
+ </ReactMarkdown>
314
+ );
315
+ }
316
+
317
+ type ParsedReviewFinding = {
318
+ id: string;
319
+ severity: "critical" | "high" | "medium" | "low" | "neutral";
320
+ title: string;
321
+ body: string;
322
+ };
323
+
324
+ type ParsedReviewContent = {
325
+ intro: string | null;
326
+ findingsHeading: string;
327
+ findings: ParsedReviewFinding[];
328
+ closing: string | null;
329
+ };
330
+
331
+ type ParsedOutlineSection = {
332
+ id: string;
333
+ title: string;
334
+ items: string[];
335
+ };
336
+
337
+ function parseReviewContent(text: string): ParsedReviewContent | null {
338
+ const normalized = text.replace(/\r/g, "");
339
+ const lines = normalized.split("\n");
340
+ const findingsIndex = lines.findIndex((line) => /^(?:#{1,6}\s*)?findings\b/i.test(line.trim()));
341
+ if (findingsIndex < 0) {
342
+ return null;
343
+ }
344
+
345
+ const intro = lines.slice(0, findingsIndex).join("\n").trim() || null;
346
+ const findingsHeading = lines[findingsIndex]?.replace(/^#{1,6}\s*/, "").trim() || "Findings";
347
+ const remaining = lines.slice(findingsIndex + 1);
348
+
349
+ const trailingHeadingIndex = remaining.findIndex((line) =>
350
+ /^(?:#{1,6}\s*)?(assumptions|open questions|assumptions\s*\/\s*open questions|next steps)\b/i.test(line.trim())
351
+ );
352
+
353
+ const findingsLines = trailingHeadingIndex >= 0 ? remaining.slice(0, trailingHeadingIndex) : remaining;
354
+ const closing = trailingHeadingIndex >= 0 ? remaining.slice(trailingHeadingIndex).join("\n").trim() || null : null;
355
+
356
+ const chunks: string[][] = [];
357
+ let current: string[] = [];
358
+
359
+ for (const line of findingsLines) {
360
+ if (/^\s*\d+[.)]\s+/.test(line)) {
361
+ if (current.length > 0) {
362
+ chunks.push(current);
363
+ }
364
+ current = [line];
365
+ } else if (current.length > 0) {
366
+ current.push(line);
367
+ }
368
+ }
369
+
370
+ if (current.length > 0) {
371
+ chunks.push(current);
372
+ }
373
+
374
+ const findings = chunks
375
+ .map((chunk, index) => {
376
+ const [firstLine, ...rest] = chunk;
377
+ const cleanedFirst = firstLine.replace(/^\s*\d+[.)]\s+/, "").replace(/\*\*/g, "").trim();
378
+ const severityMatch = cleanedFirst.match(/\b(critical|high|medium|low)\b/i);
379
+ const severity = (severityMatch?.[1]?.toLowerCase() ?? "neutral") as ParsedReviewFinding["severity"];
380
+ const title = cleanedFirst
381
+ .replace(/\b(critical|high|medium|low)\b\s*[—:-]\s*/i, "")
382
+ .replace(/\b(critical|high|medium|low)\b/i, "")
383
+ .trim();
384
+ const body = rest.join("\n").trim();
385
+
386
+ return {
387
+ id: `finding-${index}`,
388
+ severity,
389
+ title: title || cleanedFirst,
390
+ body,
391
+ };
392
+ })
393
+ .filter((finding) => finding.title.length > 0);
394
+
395
+ if (findings.length === 0) {
396
+ return null;
397
+ }
398
+
399
+ return {
400
+ intro,
401
+ findingsHeading,
402
+ findings,
403
+ closing,
404
+ };
405
+ }
406
+
407
+ function isLikelyOutlineTitle(line: string): boolean {
408
+ const trimmed = line.trim();
409
+ if (!trimmed) return false;
410
+ if (/^[-*+]\s|^\d+[.)]\s|^#{1,6}\s|^>\s|^```/.test(trimmed)) return false;
411
+ if (trimmed.length > 72) return false;
412
+ if (/[.!?;]$/.test(trimmed)) return false;
413
+ const wordCount = trimmed.split(/\s+/).length;
414
+ return wordCount <= 8;
415
+ }
416
+
417
+ function parseOutlineContent(text: string): ParsedOutlineSection[] | null {
418
+ const normalized = text.replace(/\r/g, "");
419
+ const lines = normalized.split("\n");
420
+ if (lines.some((line) => /^\s*[-*+]\s|^\s*\d+[.)]\s|^\s*#{1,6}\s/.test(line))) {
421
+ return null;
422
+ }
423
+
424
+ const titleIndices = lines
425
+ .map((line, index) => ({ line, index }))
426
+ .filter(({ line, index }) => {
427
+ const next = lines[index + 1]?.trim() ?? "";
428
+ return isLikelyOutlineTitle(line) && next.length > 0 && !isLikelyOutlineTitle(next);
429
+ })
430
+ .map(({ index }) => index);
431
+
432
+ if (titleIndices.length < 2) {
433
+ return null;
434
+ }
435
+
436
+ const sections: ParsedOutlineSection[] = [];
437
+ for (let i = 0; i < titleIndices.length; i += 1) {
438
+ const start = titleIndices[i];
439
+ const end = titleIndices[i + 1] ?? lines.length;
440
+ const title = lines[start]!.trim().replace(/:$/, "");
441
+ const items = lines
442
+ .slice(start + 1, end)
443
+ .map((line) => line.trim())
444
+ .filter((line) => line.length > 0);
445
+
446
+ if (title.length === 0 || items.length === 0) {
447
+ continue;
448
+ }
449
+
450
+ sections.push({
451
+ id: `outline-${i}`,
452
+ title,
453
+ items,
454
+ });
455
+ }
456
+
457
+ return sections.length >= 2 ? sections : null;
458
+ }
459
+
460
+ function getFindingTone(finding: ParsedReviewFinding): { badge: string; border: string; surface: string } {
461
+ switch (finding.severity) {
462
+ case "critical":
463
+ case "high":
464
+ return {
465
+ badge: "bg-[rgba(210,81,81,0.14)] text-[#f1b0b0]",
466
+ border: "border-[rgba(210,81,81,0.22)]",
467
+ surface: "bg-[rgba(210,81,81,0.05)]",
468
+ };
469
+ case "medium":
470
+ return {
471
+ badge: "bg-[rgba(214,164,60,0.14)] text-[#f0d28b]",
472
+ border: "border-[rgba(214,164,60,0.2)]",
473
+ surface: "bg-[rgba(214,164,60,0.05)]",
474
+ };
475
+ case "low":
476
+ return {
477
+ badge: "bg-[rgba(84,176,79,0.14)] text-[#b8dfb5]",
478
+ border: "border-[rgba(84,176,79,0.2)]",
479
+ surface: "bg-[rgba(84,176,79,0.05)]",
480
+ };
481
+ default:
482
+ return {
483
+ badge: "bg-[rgba(143,143,143,0.14)] text-[#c4c4c4]",
484
+ border: "border-[var(--vk-border)]",
485
+ surface: "bg-[rgba(255,255,255,0.03)]",
486
+ };
487
+ }
488
+ }
489
+
490
+ function ReviewFindingsBlock({ text }: { text: string }) {
491
+ const parsed = parseReviewContent(text);
492
+ if (!parsed) {
493
+ return null;
494
+ }
495
+
496
+ return (
497
+ <div className="space-y-5">
498
+ {parsed.intro ? (
499
+ <MarkdownBlock
500
+ text={parsed.intro}
501
+ className="prose prose-invert max-w-none text-[16px] leading-[28px] text-[#cfcfcf] prose-headings:mb-3 prose-headings:mt-6 prose-headings:text-[#f1f1f1] prose-p:my-4 prose-p:text-[#cfcfcf] prose-strong:text-[#f1f1f1] prose-ol:my-4 prose-ol:pl-6 prose-ul:my-4 prose-ul:pl-6 prose-li:my-2 prose-li:text-[#cfcfcf] prose-pre:my-4 prose-pre:overflow-x-auto prose-pre:rounded-[6px] prose-pre:border prose-pre:border-[#333] prose-pre:bg-[#1c1c1c] prose-code:text-[#d7d7d7]"
502
+ />
503
+ ) : null}
504
+
505
+ <div className="overflow-hidden rounded-[8px] border border-[var(--vk-border)] bg-[rgba(255,255,255,0.03)]">
506
+ <div className="border-b border-[var(--vk-border)] px-4 py-3">
507
+ <p className="text-[12px] uppercase tracking-[0.16em] text-[#8f8f8f]">{parsed.findingsHeading}</p>
508
+ </div>
509
+ <div className="space-y-4 p-4">
510
+ {parsed.findings.map((finding, index) => {
511
+ const tone = getFindingTone(finding);
512
+ return (
513
+ <div
514
+ key={finding.id}
515
+ className={`rounded-[6px] border px-4 py-3 ${tone.border} ${tone.surface}`}
516
+ >
517
+ <div className="flex flex-wrap items-center gap-3">
518
+ <span className="text-[13px] font-medium leading-[20px] text-[#8f8f8f]">
519
+ {index + 1}.
520
+ </span>
521
+ <span className={`rounded-full px-2 py-[3px] text-[11px] font-medium uppercase tracking-[0.12em] ${tone.badge}`}>
522
+ {finding.severity}
523
+ </span>
524
+ <p className="min-w-0 flex-1 text-[16px] leading-[24px] text-[#f1f1f1]">
525
+ {finding.title}
526
+ </p>
527
+ </div>
528
+ {finding.body ? (
529
+ <MarkdownBlock
530
+ text={finding.body}
531
+ className="prose prose-invert mt-3 max-w-none text-[14px] leading-[24px] text-[#c9c9c9] prose-p:my-3 prose-p:text-[#c9c9c9] prose-strong:text-[#f1f1f1] prose-ul:my-3 prose-ul:pl-5 prose-ol:my-3 prose-ol:pl-5 prose-li:my-1.5 prose-li:text-[#c9c9c9] prose-code:text-[#d7d7d7] prose-pre:my-3 prose-pre:overflow-x-auto prose-pre:rounded-[6px] prose-pre:border prose-pre:border-[#333] prose-pre:bg-[#1c1c1c]"
532
+ />
533
+ ) : null}
534
+ </div>
535
+ );
536
+ })}
537
+ </div>
538
+ </div>
539
+
540
+ {parsed.closing ? (
541
+ <div className="rounded-[8px] border border-[var(--vk-border)] bg-[rgba(255,255,255,0.03)] px-4 py-4">
542
+ <MarkdownBlock
543
+ text={parsed.closing}
544
+ className="prose prose-invert max-w-none text-[15px] leading-[25px] text-[#c9c9c9] prose-headings:mb-2 prose-headings:mt-5 prose-headings:text-[#f1f1f1] prose-p:my-3 prose-p:text-[#c9c9c9] prose-strong:text-[#f1f1f1] prose-ol:my-3 prose-ol:pl-5 prose-ul:my-3 prose-ul:pl-5 prose-li:my-1.5 prose-li:text-[#c9c9c9] prose-code:text-[#d7d7d7]"
545
+ />
546
+ </div>
547
+ ) : null}
548
+ </div>
549
+ );
550
+ }
551
+
552
+ function OutlineSummaryBlock({ sections }: { sections: ParsedOutlineSection[] }) {
553
+ return (
554
+ <div className="space-y-6">
555
+ {sections.map((section) => (
556
+ <section key={section.id} className="space-y-3">
557
+ <h3 className="text-[22px] font-medium leading-[30px] text-[#f1f1f1]">
558
+ {section.title}
559
+ </h3>
560
+ <div className="space-y-3">
561
+ {section.items.map((item, index) => (
562
+ <div
563
+ key={`${section.id}-item-${index}`}
564
+ className="rounded-[6px] border border-[rgba(255,255,255,0.05)] bg-[rgba(255,255,255,0.02)] px-4 py-3"
565
+ >
566
+ <MarkdownBlock
567
+ text={item}
568
+ className="prose prose-invert max-w-none text-[16px] leading-[28px] text-[#cfcfcf] prose-p:my-0 prose-p:text-[#cfcfcf] prose-strong:text-[#f1f1f1] prose-code:text-[#d7d7d7]"
569
+ />
570
+ </div>
571
+ ))}
572
+ </div>
573
+ </section>
574
+ ))}
575
+ </div>
576
+ );
577
+ }
578
+
579
+ function extractToolContent(entry: NormalizedChatEntry): string[] {
580
+ const raw = entry.metadata?.toolContent;
581
+ if (Array.isArray(raw)) {
582
+ return raw.filter((value): value is string => typeof value === "string" && value.trim().length > 0);
583
+ }
584
+ return entry.text.trim().length > 0 ? [entry.text.trim()] : [];
585
+ }
586
+
587
+ function getToolInlineSummary(entry: NormalizedChatEntry, content: string[]): string | null {
588
+ const title = typeof entry.metadata?.toolTitle === "string" ? entry.metadata.toolTitle.trim() : "";
589
+ const first = content[0]?.trim() ?? "";
590
+ if (!first) return null;
591
+ if (title && first.toLowerCase() === title.toLowerCase()) {
592
+ return null;
593
+ }
594
+ return first.length > 84 ? `${first.slice(0, 81)}...` : first;
595
+ }
596
+
597
+ function getToolStatusTone(status: string | null | undefined): "pending" | "running" | "success" | "error" | "cancelled" {
598
+ const lower = status?.trim().toLowerCase() ?? "";
599
+ if (lower.includes("complete") || lower.includes("success") || lower.includes("done")) {
600
+ return "success";
601
+ }
602
+ if (lower.includes("error") || lower.includes("fail")) {
603
+ return "error";
604
+ }
605
+ if (lower.includes("cancel")) {
606
+ return "cancelled";
607
+ }
608
+ if (lower.includes("running") || lower.includes("progress")) {
609
+ return "running";
610
+ }
611
+ return "pending";
612
+ }
613
+
614
+ function getToolIcon(entry: NormalizedChatEntry): LucideIcon {
615
+ const toolKind = typeof entry.metadata?.toolKind === "string" ? entry.metadata.toolKind.toLowerCase() : "";
616
+ const title = (typeof entry.metadata?.toolTitle === "string" ? entry.metadata.toolTitle : entry.text).toLowerCase();
617
+ if (toolKind.includes("thinking") || title.includes("thinking")) {
618
+ return BrainCircuit;
619
+ }
620
+ if (toolKind.includes("web") || title.includes("web search") || title.includes("web fetch")) {
621
+ return Globe;
622
+ }
623
+ if (
624
+ toolKind.includes("grep")
625
+ || toolKind.includes("glob")
626
+ || toolKind.includes("search")
627
+ || toolKind.includes("find")
628
+ || title.includes("search")
629
+ || title.includes("grep")
630
+ || title.includes("glob")
631
+ || title.includes("find")
632
+ ) {
633
+ return FileSearch2;
634
+ }
635
+ if (toolKind.includes("read") || title.includes("read")) {
636
+ return FileText;
637
+ }
638
+ if (
639
+ toolKind.includes("edit")
640
+ || toolKind.includes("write")
641
+ || toolKind.includes("multiedit")
642
+ || title.includes("edit")
643
+ || title.includes("write")
644
+ ) {
645
+ return PencilLine;
646
+ }
647
+ if (toolKind.includes("task") || toolKind.includes("todo") || title.includes("todo")) {
648
+ return ListTodo;
649
+ }
650
+ if (toolKind.includes("search") || title.includes("search") || title.includes("rg ") || title.includes("find ")) {
651
+ return Search;
652
+ }
653
+ if (toolKind.includes("permission") || title.includes("permission") || title.includes("auth")) {
654
+ return Shield;
655
+ }
656
+ if (toolKind.includes("command") || title.includes("bash") || title.includes("git ") || title.includes("bun ")) {
657
+ return TerminalSquare;
658
+ }
659
+ return Wrench;
660
+ }
661
+
662
+ function AttachmentPills({
663
+ attachments,
664
+ onRemove,
665
+ }: {
666
+ attachments: string[];
667
+ onRemove?: (index: number) => void;
668
+ }) {
669
+ if (!attachments.length) return null;
670
+
671
+ return (
672
+ <div className="mt-3 flex flex-wrap gap-2">
673
+ {attachments.map((attachment, index) => {
674
+ const label = attachment.split("/").pop() || attachment;
675
+
676
+ if (onRemove) {
677
+ return (
678
+ <button
679
+ key={`${attachment}-${index}`}
680
+ type="button"
681
+ onClick={() => onRemove(index)}
682
+ className="rounded-[3px] border border-[#333] bg-[#1c1c1c] px-2 py-1 text-[12px] leading-[18px] text-[#c4c4c4] transition hover:bg-[#292929]"
683
+ >
684
+ {label}
685
+ </button>
686
+ );
687
+ }
688
+
689
+ return (
690
+ <span
691
+ key={`${attachment}-${index}`}
692
+ className="rounded-[3px] border border-[#333] bg-[#1c1c1c] px-2 py-1 text-[12px] leading-[18px] text-[#c4c4c4]"
693
+ >
694
+ {label}
695
+ </span>
696
+ );
697
+ })}
698
+ </div>
699
+ );
700
+ }
701
+
702
+ function SummaryChip({ summary }: { summary: string }) {
703
+ const parsed = parseComposerSummary(summary);
704
+
705
+ return (
706
+ <div className="inline-flex min-h-[29px] items-center gap-1 rounded-[3px] bg-[#292929] px-3 py-[5px] text-[14px] leading-[21px] text-[#c4c4c4]">
707
+ <span>{parsed.label}</span>
708
+ {parsed.additions ? <span className="text-[#54b04f]">{parsed.additions}</span> : null}
709
+ {parsed.deletions ? <span className="text-[#d25151]">{parsed.deletions}</span> : null}
710
+ </div>
711
+ );
712
+ }
713
+
714
+ function ParserStateBanner({
715
+ kind,
716
+ message,
717
+ command,
718
+ }: {
719
+ kind: string;
720
+ message: string;
721
+ command: string | null;
722
+ }) {
723
+ const title = kind === "auth_required"
724
+ ? "Authentication required"
725
+ : kind === "interactive_required"
726
+ ? "Terminal interaction required"
727
+ : "Waiting for input";
728
+ const border = kind === "auth_required" ? "border-[#6b5533] bg-[rgba(234,122,42,0.12)] text-[#f1c49f]" : "border-[#36506b] bg-[rgba(68,114,164,0.12)] text-[#bfd5ee]";
729
+
730
+ return (
731
+ <div className={`rounded-[3px] border px-3 py-2 ${border}`}>
732
+ <div className="flex items-start gap-3">
733
+ <div className="flex h-[20px] w-[20px] items-center justify-center pt-[1px]">
734
+ <TerminalSquare className="h-[15px] w-[15px]" strokeWidth={1.6} />
735
+ </div>
736
+ <div className="min-w-0 space-y-1">
737
+ <p className="text-[13px] font-medium leading-[20px]">{title}</p>
738
+ <p className="whitespace-pre-wrap break-words text-[13px] leading-[20px]">{message}</p>
739
+ {command ? (
740
+ <p className="text-[12px] leading-[18px] text-[#c4c4c4]">
741
+ Run locally: <code className="rounded bg-[rgba(0,0,0,0.22)] px-1 py-[1px] text-[#f1f1f1]">{command}</code>
742
+ </p>
743
+ ) : null}
744
+ </div>
745
+ </div>
746
+ </div>
747
+ );
748
+ }
749
+
750
+ function UserEntryCard({ entry }: { entry: NormalizedChatEntry }) {
751
+ const timestamp = formatTimestamp(entry.createdAt);
752
+
753
+ return (
754
+ <div className="space-y-3">
755
+ <div className="flex items-center gap-2">
756
+ <UserRound className="h-[15px] w-[15px] shrink-0 text-[#8f8f8f]" strokeWidth={1.7} />
757
+ <span className="text-[14px] leading-[21px] text-[#c4c4c4]">You</span>
758
+ {timestamp ? (
759
+ <span className="text-[12px] leading-[18px] text-[#5f5f5f]">{timestamp}</span>
760
+ ) : null}
761
+ </div>
762
+ <MarkdownBlock
763
+ text={entry.text}
764
+ className="prose prose-invert max-w-none text-[16px] leading-[24px] text-[#c4c4c4] prose-headings:text-[#c4c4c4] prose-p:my-0 prose-p:text-[#c4c4c4] prose-pre:my-3 prose-pre:overflow-x-auto prose-pre:rounded-[3px] prose-pre:border prose-pre:border-[#333] prose-pre:bg-[#1c1c1c] prose-code:text-[#c4c4c4]"
765
+ />
766
+ <AttachmentPills attachments={entry.attachments} />
767
+ </div>
768
+ );
769
+ }
770
+
771
+ function StatusEntry({ entry }: { entry: NormalizedChatEntry }) {
772
+ const presentation = getStatusPresentation(entry.text);
773
+ const commandLike = isCommandLikeStatus(entry.text);
774
+
775
+ if (!presentation.compact) {
776
+ return (
777
+ <div className="space-y-3">
778
+ <MarkdownBlock
779
+ text={entry.text}
780
+ className="prose prose-invert max-w-none text-[16px] leading-[24px] text-[#c4c4c4] prose-headings:text-[#c4c4c4] prose-p:my-0 prose-p:text-[#c4c4c4] prose-pre:my-3 prose-pre:overflow-x-auto prose-pre:rounded-[3px] prose-pre:border prose-pre:border-[#333] prose-pre:bg-[#1c1c1c] prose-code:text-[#c4c4c4]"
781
+ />
782
+ </div>
783
+ );
784
+ }
785
+
786
+ const { Icon } = presentation;
787
+
788
+ return (
789
+ <div className="flex items-start gap-2 py-[2px]">
790
+ <div className="relative flex h-[22px] w-[20px] items-start pt-[2px] text-[#8f8f8f]">
791
+ <Icon className="h-[20px] w-[20px]" strokeWidth={1.6} />
792
+ {presentation.showDot ? (
793
+ <span className="absolute bottom-0 left-[-2px] h-[6px] w-[6px] rounded-full bg-[#54b04f]" />
794
+ ) : null}
795
+ </div>
796
+ <p className={`min-w-0 flex-1 whitespace-pre-wrap break-words text-[#8f8f8f] ${commandLike ? "font-mono text-[13px] leading-[20px]" : "text-[14px] leading-[21px]"}`}>
797
+ {entry.text}
798
+ </p>
799
+ </div>
800
+ );
801
+ }
802
+
803
+ function ToolEntry({ entry }: { entry: NormalizedChatEntry }) {
804
+ const [expanded, setExpanded] = useState(false);
805
+ const content = extractToolContent(entry);
806
+ const inlineSummary = getToolInlineSummary(entry, content);
807
+ const toolTitle = typeof entry.metadata?.toolTitle === "string" && entry.metadata.toolTitle.trim().length > 0
808
+ ? entry.metadata.toolTitle.trim()
809
+ : entry.text.trim() || "Tool call";
810
+ const toolStatus = typeof entry.metadata?.toolStatus === "string" ? entry.metadata.toolStatus : null;
811
+ const statusTone = getToolStatusTone(toolStatus);
812
+ const Icon = getToolIcon(entry);
813
+ const statusIndicator = statusTone === "running"
814
+ ? (
815
+ <span
816
+ className="h-[9px] w-[9px] shrink-0 rounded-full border-2 border-[rgba(148,163,184,0.35)] border-t-[rgba(148,163,184,0.95)] animate-spin"
817
+ aria-hidden="true"
818
+ />
819
+ )
820
+ : (
821
+ <span
822
+ className={[
823
+ "h-[9px] w-[9px] shrink-0 rounded-full",
824
+ statusTone === "success"
825
+ ? "bg-[var(--vk-green)]"
826
+ : statusTone === "error"
827
+ ? "bg-[var(--vk-red)]"
828
+ : statusTone === "cancelled"
829
+ ? "bg-[var(--vk-text-muted)]"
830
+ : "bg-[rgba(148,163,184,0.7)]",
831
+ ].join(" ")}
832
+ aria-hidden="true"
833
+ />
834
+ );
835
+
836
+ return (
837
+ <div className={`group ${expanded ? "is-expanded" : ""}`}>
838
+ <button
839
+ type="button"
840
+ onClick={() => setExpanded((current) => !current)}
841
+ className="flex w-full items-start gap-2 py-1 text-left text-[var(--vk-text-muted)] transition hover:text-[var(--vk-text-normal)]"
842
+ >
843
+ {statusIndicator}
844
+ <Icon className="mt-[2px] h-[14px] w-[14px] shrink-0 text-[var(--vk-text-muted)]" strokeWidth={1.7} />
845
+ <div className="min-w-0 flex-1">
846
+ <div className="flex min-w-0 flex-wrap items-center gap-2">
847
+ <span className="shrink-0 text-[14px] font-medium leading-[21px] text-[#d0d0d0]">
848
+ {toolTitle}
849
+ </span>
850
+ {inlineSummary ? (
851
+ <span className="min-w-0 max-w-full truncate rounded-[3px] bg-[rgba(255,255,255,0.06)] px-2 py-[2px] font-mono text-[12px] leading-[18px] text-[#a9a9a9]">
852
+ {inlineSummary}
853
+ </span>
854
+ ) : null}
855
+ </div>
856
+ </div>
857
+ <ChevronRight
858
+ className={`mt-[2px] h-[14px] w-[14px] shrink-0 text-[var(--vk-text-muted)] transition-all duration-200 ${
859
+ expanded ? "rotate-90 opacity-100" : "opacity-0 group-hover:opacity-100"
860
+ }`}
861
+ strokeWidth={1.8}
862
+ />
863
+ </button>
864
+ {expanded ? (
865
+ <div className="mt-2 max-h-[300px] overflow-y-auto border-t border-[var(--vk-border)] bg-[var(--vk-bg-surface)] px-3 py-3">
866
+ {content.length > 0 ? (
867
+ <div className="space-y-2">
868
+ {content
869
+ .filter((line, index) => !(inlineSummary && index === 0 && line.trim() === inlineSummary))
870
+ .map((line, index) => (
871
+ <p
872
+ key={`${entry.id}-tool-line-${index}`}
873
+ className="whitespace-pre-wrap break-words font-mono text-[12px] leading-[18px] text-[var(--vk-text-normal)]"
874
+ >
875
+ {line}
876
+ </p>
877
+ ))}
878
+ </div>
879
+ ) : null}
880
+ </div>
881
+ ) : null}
882
+ </div>
883
+ );
884
+ }
885
+
886
+ type FeedRenderItem =
887
+ | { kind: "entry"; entry: NormalizedChatEntry }
888
+ | { kind: "tool-group"; id: string; entries: NormalizedChatEntry[] };
889
+
890
+ function buildFeedRenderItems(entries: NormalizedChatEntry[]): FeedRenderItem[] {
891
+ const items: FeedRenderItem[] = [];
892
+ let toolBuffer: NormalizedChatEntry[] = [];
893
+
894
+ const flushTools = () => {
895
+ if (toolBuffer.length === 0) return;
896
+ items.push({
897
+ kind: "tool-group",
898
+ id: `tool-group-${toolBuffer[0]?.id ?? items.length}`,
899
+ entries: toolBuffer,
900
+ });
901
+ toolBuffer = [];
902
+ };
903
+
904
+ for (const entry of entries) {
905
+ if (entry.kind === "tool") {
906
+ toolBuffer.push(entry);
907
+ continue;
908
+ }
909
+
910
+ flushTools();
911
+ items.push({ kind: "entry", entry });
912
+ }
913
+
914
+ flushTools();
915
+ return items;
916
+ }
917
+
918
+ function ToolGroup({
919
+ entries,
920
+ autoCollapsed,
921
+ }: {
922
+ entries: NormalizedChatEntry[];
923
+ autoCollapsed: boolean;
924
+ }) {
925
+ const [expanded, setExpanded] = useState(!autoCollapsed);
926
+ const countLabel = `${entries.length} tool call${entries.length === 1 ? "" : "s"}`;
927
+
928
+ useEffect(() => {
929
+ if (autoCollapsed) {
930
+ setExpanded(false);
931
+ }
932
+ }, [autoCollapsed]);
933
+
934
+ return (
935
+ <div className="space-y-3">
936
+ <button
937
+ type="button"
938
+ onClick={() => setExpanded((current) => !current)}
939
+ className="flex items-center gap-2 text-[15px] leading-[22px] text-[#9b9b9b] transition hover:text-[#c4c4c4]"
940
+ >
941
+ <ChevronDown
942
+ className={`h-[14px] w-[14px] transition-transform ${expanded ? "" : "-rotate-90"}`}
943
+ strokeWidth={1.8}
944
+ />
945
+ <span>{countLabel}</span>
946
+ </button>
947
+ {expanded ? (
948
+ <div className="space-y-1 pl-5">
949
+ {entries.map((entry) => (
950
+ <ToolEntry key={entry.id} entry={entry} />
951
+ ))}
952
+ </div>
953
+ ) : null}
954
+ </div>
955
+ );
956
+ }
957
+
958
+ function AssistantEntry({
959
+ entry,
960
+ agentName,
961
+ }: {
962
+ entry: NormalizedChatEntry;
963
+ agentName: string;
964
+ }) {
965
+ const timestamp = formatTimestamp(entry.createdAt);
966
+ const reviewBlock = parseReviewContent(entry.text);
967
+ const outlineSections = reviewBlock ? null : parseOutlineContent(entry.text);
968
+
969
+ return (
970
+ <div className="space-y-4">
971
+ {entry.streaming ? (
972
+ <div className="flex items-center gap-2 text-[#8f8f8f]">
973
+ {agentName ? (
974
+ <AgentTileIcon seed={{ label: agentName }} className="h-[20px] w-[20px] border-none bg-transparent" />
975
+ ) : (
976
+ <Code2 className="h-[20px] w-[20px]" strokeWidth={1.6} />
977
+ )}
978
+ <span className="text-[14px] leading-[21px]">Thinking</span>
979
+ </div>
980
+ ) : null}
981
+ {reviewBlock ? (
982
+ <ReviewFindingsBlock text={entry.text} />
983
+ ) : outlineSections ? (
984
+ <OutlineSummaryBlock sections={outlineSections} />
985
+ ) : (
986
+ <MarkdownBlock
987
+ text={entry.text}
988
+ className="prose prose-invert max-w-none text-[16px] leading-[28px] text-[#cfcfcf] prose-headings:mb-3 prose-headings:mt-6 prose-headings:text-[#f1f1f1] prose-p:my-4 prose-p:text-[#cfcfcf] prose-strong:text-[#f1f1f1] prose-ol:my-4 prose-ol:pl-6 prose-ul:my-4 prose-ul:pl-6 prose-li:my-2 prose-li:text-[#cfcfcf] prose-pre:my-4 prose-pre:overflow-x-auto prose-pre:rounded-[6px] prose-pre:border prose-pre:border-[#333] prose-pre:bg-[#1c1c1c] prose-code:text-[#d7d7d7] prose-blockquote:border-l prose-blockquote:border-[#333] prose-blockquote:pl-4 prose-blockquote:text-[#b7b7b7]"
989
+ />
990
+ )}
991
+ <AttachmentPills attachments={entry.attachments} />
992
+ {timestamp ? (
993
+ <p className="text-[12px] leading-[18px] text-[#5f5f5f]">{timestamp}</p>
994
+ ) : null}
995
+ </div>
996
+ );
997
+ }
998
+
999
+ function SystemEntry({ entry }: { entry: NormalizedChatEntry }) {
1000
+ return (
1001
+ <div className="rounded-[3px] border border-[#315434] bg-[rgba(84,176,79,0.08)] px-3 py-2">
1002
+ <p className="text-[12px] uppercase tracking-[0.18em] text-[#8bc886]">System</p>
1003
+ <MarkdownBlock
1004
+ text={entry.text}
1005
+ className="prose prose-invert mt-2 max-w-none text-[14px] leading-[21px] text-[#d8ead6] prose-p:my-0 prose-p:text-[#d8ead6] prose-strong:text-white prose-code:text-[#d8ead6]"
1006
+ />
1007
+ <AttachmentPills attachments={entry.attachments} />
1008
+ </div>
1009
+ );
1010
+ }
1011
+
1012
+ function FeedEntry({
1013
+ entry,
1014
+ agentName,
1015
+ }: {
1016
+ entry: NormalizedChatEntry;
1017
+ agentName: string;
1018
+ }) {
1019
+ switch (entry.kind) {
1020
+ case "user":
1021
+ return <UserEntryCard entry={entry} />;
1022
+ case "assistant":
1023
+ return <AssistantEntry entry={entry} agentName={agentName} />;
1024
+ case "tool":
1025
+ return <ToolEntry entry={entry} />;
1026
+ case "system":
1027
+ return <SystemEntry entry={entry} />;
1028
+ default:
1029
+ return <StatusEntry entry={entry} />;
1030
+ }
1031
+ }
1032
+
1033
+ async function uploadAttachments(files: File[]): Promise<string[]> {
1034
+ if (!files.length) return [];
1035
+
1036
+ const uploadedPaths = await Promise.all(files.map(async (file) => {
1037
+ const formData = new FormData();
1038
+ formData.append("file", file);
1039
+
1040
+ const response = await fetch("/api/attachments", {
1041
+ method: "POST",
1042
+ body: formData,
1043
+ });
1044
+
1045
+ if (!response.ok) {
1046
+ throw new Error(`Failed to upload ${file.name}`);
1047
+ }
1048
+
1049
+ const payload = await response.json();
1050
+ const record = payload && typeof payload === "object" ? payload as Record<string, unknown> : null;
1051
+ const nested = record?.attachment && typeof record.attachment === "object"
1052
+ ? record.attachment as Record<string, unknown>
1053
+ : null;
1054
+
1055
+ for (const candidate of [
1056
+ record?.absolutePath,
1057
+ record?.path,
1058
+ record?.filePath,
1059
+ nested?.absolutePath,
1060
+ nested?.path,
1061
+ nested?.filePath,
1062
+ ]) {
1063
+ if (typeof candidate === "string" && candidate.trim().length > 0) {
1064
+ return candidate.trim();
1065
+ }
1066
+ }
1067
+
1068
+ throw new Error(`Attachment response for ${file.name} did not include a file path`);
1069
+ }));
1070
+
1071
+ return uploadedPaths.filter(Boolean);
1072
+ }
1073
+
1074
+ export function ChatPanel({
1075
+ sessionId,
1076
+ agentName,
1077
+ projectId,
1078
+ sessionModel,
1079
+ sessionReasoningEffort,
1080
+ }: ChatPanelProps) {
1081
+ const { agents } = useAgents();
1082
+ const { entries, error, loading, parserState, sessionStatus, refresh } = useSessionFeed(sessionId);
1083
+
1084
+ const [message, setMessage] = useState("");
1085
+ const [sending, setSending] = useState(false);
1086
+ const [interrupting, setInterrupting] = useState(false);
1087
+ const [sendError, setSendError] = useState<string | null>(null);
1088
+ const [modelMenuOpen, setModelMenuOpen] = useState(false);
1089
+ const [selectedModel, setSelectedModel] = useState(sessionModel?.trim() || "");
1090
+ const [attachments, setAttachments] = useState<AttachmentDraft[]>([]);
1091
+ const [selectedSlashIndex, setSelectedSlashIndex] = useState(0);
1092
+
1093
+ const endRef = useRef<HTMLDivElement | null>(null);
1094
+ const fileInputRef = useRef<HTMLInputElement | null>(null);
1095
+ const modelMenuRef = useRef<HTMLDivElement | null>(null);
1096
+ const normalizedAgentName = agentName?.trim() || "";
1097
+ const normalizedSessionStatus = sessionStatus?.trim().toLowerCase() ?? "";
1098
+ const modelOptions = useMemo(
1099
+ () => getModelOptions(agents, normalizedAgentName, sessionModel?.trim() || ""),
1100
+ [agents, normalizedAgentName, sessionModel],
1101
+ );
1102
+ const router = useRouter();
1103
+
1104
+ useEffect(() => {
1105
+ setSelectedModel(sessionModel?.trim() || "");
1106
+ }, [sessionModel]);
1107
+
1108
+ // Clear transient error state when the session changes.
1109
+ useEffect(() => {
1110
+ setSendError(null);
1111
+ }, [sessionId]);
1112
+
1113
+ // Close model menu on click outside.
1114
+ useEffect(() => {
1115
+ if (!modelMenuOpen) return;
1116
+ function onClickOutside(event: globalThis.MouseEvent) {
1117
+ if (modelMenuRef.current && !modelMenuRef.current.contains(event.target as Node)) {
1118
+ setModelMenuOpen(false);
1119
+ }
1120
+ }
1121
+ document.addEventListener("mousedown", onClickOutside);
1122
+ return () => document.removeEventListener("mousedown", onClickOutside);
1123
+ }, [modelMenuOpen]);
1124
+
1125
+ const displayEntries = useMemo(
1126
+ () => {
1127
+ if (normalizedSessionStatus !== "working" && normalizedSessionStatus !== "running") {
1128
+ return entries;
1129
+ }
1130
+ return entries.filter((entry) => !(entry.kind === "status" && entry.source === "session-status"));
1131
+ },
1132
+ [entries, normalizedSessionStatus],
1133
+ );
1134
+
1135
+ const hasStreamingEntry = displayEntries.some((entry) => entry.streaming);
1136
+ const isSessionRunning = normalizedSessionStatus === "running" || normalizedSessionStatus === "working" || hasStreamingEntry;
1137
+ const composerSummary = useMemo(
1138
+ () => extractComposerSummary(displayEntries),
1139
+ [displayEntries],
1140
+ );
1141
+ const slashCommandOptions = useMemo(
1142
+ () => getSlashCommandOptions(normalizedAgentName, message),
1143
+ [message, normalizedAgentName],
1144
+ );
1145
+ const showSlashCommandMenu = slashCommandOptions.length > 0;
1146
+ const feedItems = useMemo(
1147
+ () => buildFeedRenderItems(displayEntries),
1148
+ [displayEntries],
1149
+ );
1150
+
1151
+ const prevEntryCountRef = useRef(0);
1152
+ useEffect(() => {
1153
+ const count = displayEntries.length;
1154
+ // Only auto-scroll when entries are added or while streaming — not on every poll.
1155
+ if (count !== prevEntryCountRef.current || hasStreamingEntry || sending) {
1156
+ endRef.current?.scrollIntoView({ behavior: hasStreamingEntry ? "auto" : "smooth", block: "end" });
1157
+ }
1158
+ prevEntryCountRef.current = count;
1159
+ }, [displayEntries, hasStreamingEntry, sending]);
1160
+
1161
+ useEffect(() => {
1162
+ if (!showSlashCommandMenu) {
1163
+ setSelectedSlashIndex(0);
1164
+ return;
1165
+ }
1166
+ setSelectedSlashIndex((current) => Math.min(current, Math.max(slashCommandOptions.length - 1, 0)));
1167
+ }, [showSlashCommandMenu, slashCommandOptions.length]);
1168
+
1169
+ const selectedModelLabel = useMemo(() => {
1170
+ if (!selectedModel) return "Latest";
1171
+ return modelOptions.find((option) => option.id === selectedModel)?.label ?? selectedModel;
1172
+ }, [modelOptions, selectedModel]);
1173
+
1174
+ const handleInterrupt = useCallback(async () => {
1175
+ if (!isSessionRunning || interrupting) return;
1176
+
1177
+ setInterrupting(true);
1178
+ setSendError(null);
1179
+
1180
+ try {
1181
+ const response = await fetch(`/api/sessions/${encodeURIComponent(sessionId)}/kill`, {
1182
+ method: "POST",
1183
+ });
1184
+
1185
+ const data = (await response.json().catch(() => null)) as
1186
+ | { error?: string }
1187
+ | null;
1188
+
1189
+ if (!response.ok) {
1190
+ throw new Error(data?.error ?? `Failed to stop agent: ${response.status}`);
1191
+ }
1192
+
1193
+ await refresh();
1194
+ } catch (err) {
1195
+ setSendError(err instanceof Error ? err.message : "Failed to stop agent");
1196
+ } finally {
1197
+ setInterrupting(false);
1198
+ }
1199
+ }, [isSessionRunning, interrupting, sessionId, refresh]);
1200
+
1201
+ const handleSend = useCallback(async () => {
1202
+ if (isSessionRunning || interrupting) return;
1203
+ const trimmedMessage = message.trim();
1204
+ if (!trimmedMessage && attachments.length === 0) return;
1205
+
1206
+ setSending(true);
1207
+ setSendError(null);
1208
+
1209
+ try {
1210
+ const attachmentPaths = await uploadAttachments(attachments.map((attachment) => attachment.file));
1211
+
1212
+ const response = await fetch(`/api/sessions/${encodeURIComponent(sessionId)}/send`, {
1213
+ method: "POST",
1214
+ headers: {
1215
+ "Content-Type": "application/json",
1216
+ },
1217
+ body: JSON.stringify({
1218
+ message: trimmedMessage,
1219
+ attachments: attachmentPaths,
1220
+ model: selectedModel || null,
1221
+ reasoningEffort: sessionReasoningEffort || null,
1222
+ projectId: projectId || null,
1223
+ }),
1224
+ });
1225
+
1226
+ const data = (await response.json().catch(() => null)) as
1227
+ | { error?: string; sessionId?: string | null }
1228
+ | null;
1229
+
1230
+ if (!response.ok) {
1231
+ throw new Error(data?.error ?? `Failed to send message: ${response.status}`);
1232
+ }
1233
+
1234
+ setMessage("");
1235
+ setAttachments([]);
1236
+ if (data?.sessionId && data.sessionId !== sessionId) {
1237
+ router.push(`/sessions/${encodeURIComponent(data.sessionId)}?tab=chat`);
1238
+ return;
1239
+ }
1240
+ await refresh();
1241
+ } catch (err) {
1242
+ setSendError(err instanceof Error ? err.message : "Failed to send message");
1243
+ } finally {
1244
+ setSending(false);
1245
+ }
1246
+ }, [isSessionRunning, interrupting, message, attachments, sessionId, selectedModel, sessionReasoningEffort, projectId, router, refresh]);
1247
+
1248
+ function applySlashCommand(option: SlashCommandOption) {
1249
+ setMessage(option.command);
1250
+ setSendError(null);
1251
+ }
1252
+
1253
+ function handleComposerKeyDown(event: KeyboardEvent<HTMLTextAreaElement>) {
1254
+ if (showSlashCommandMenu && event.key === "ArrowDown") {
1255
+ event.preventDefault();
1256
+ setSelectedSlashIndex((current) => (
1257
+ current >= slashCommandOptions.length - 1 ? 0 : current + 1
1258
+ ));
1259
+ return;
1260
+ }
1261
+
1262
+ if (showSlashCommandMenu && event.key === "ArrowUp") {
1263
+ event.preventDefault();
1264
+ setSelectedSlashIndex((current) => (
1265
+ current <= 0 ? Math.max(slashCommandOptions.length - 1, 0) : current - 1
1266
+ ));
1267
+ return;
1268
+ }
1269
+
1270
+ if (event.key === "Escape" && isSessionRunning) {
1271
+ event.preventDefault();
1272
+ void handleInterrupt();
1273
+ return;
1274
+ }
1275
+
1276
+ if (event.key === "Enter" && !event.shiftKey) {
1277
+ event.preventDefault();
1278
+ if (showSlashCommandMenu) {
1279
+ const selectedOption = slashCommandOptions[selectedSlashIndex];
1280
+ if (selectedOption) {
1281
+ if (selectedOption.exact && !isSessionRunning) {
1282
+ void handleSend();
1283
+ } else {
1284
+ applySlashCommand(selectedOption);
1285
+ }
1286
+ return;
1287
+ }
1288
+ }
1289
+ if (!isSessionRunning) {
1290
+ void handleSend();
1291
+ }
1292
+ }
1293
+ }
1294
+
1295
+ useEffect(() => {
1296
+ if (!isSessionRunning) return;
1297
+
1298
+ const onKeyDown = (event: globalThis.KeyboardEvent) => {
1299
+ if (
1300
+ event.key !== "Escape"
1301
+ || event.defaultPrevented
1302
+ || event.metaKey
1303
+ || event.ctrlKey
1304
+ || event.altKey
1305
+ || event.shiftKey
1306
+ ) {
1307
+ return;
1308
+ }
1309
+
1310
+ event.preventDefault();
1311
+ void handleInterrupt();
1312
+ };
1313
+
1314
+ window.addEventListener("keydown", onKeyDown);
1315
+ return () => window.removeEventListener("keydown", onKeyDown);
1316
+ }, [handleInterrupt, isSessionRunning]);
1317
+
1318
+ function handleAttachmentChange(event: ChangeEvent<HTMLInputElement>) {
1319
+ const MAX_FILE_SIZE = 10 * 1024 * 1024; // 10 MB
1320
+ const files = Array.from(event.target.files ?? []);
1321
+ if (!files.length) return;
1322
+
1323
+ const validFiles: File[] = [];
1324
+ for (const file of files) {
1325
+ if (file.size > MAX_FILE_SIZE) {
1326
+ setSendError(`File "${file.name}" exceeds 10 MB limit`);
1327
+ continue;
1328
+ }
1329
+ validFiles.push(file);
1330
+ }
1331
+
1332
+ if (validFiles.length > 0) {
1333
+ setAttachments((current) => [
1334
+ ...current,
1335
+ ...validFiles.map((file) => ({ file })),
1336
+ ]);
1337
+ }
1338
+
1339
+ event.target.value = "";
1340
+ }
1341
+
1342
+ return (
1343
+ <div className="relative flex h-full min-h-0 flex-col overflow-hidden bg-[radial-gradient(circle_at_top,rgba(45,45,45,0.32),rgba(33,33,33,1)_40%)] text-[#c4c4c4]">
1344
+ <div className="mx-auto flex h-full min-h-0 w-full max-w-[855px] flex-col">
1345
+ <div className="flex-1 overflow-y-auto px-3 pt-3 sm:px-4">
1346
+ <div className="mx-auto flex w-full max-w-[768px] flex-col gap-5 pb-6">
1347
+ {loading && displayEntries.length === 0 ? (
1348
+ <div className="flex items-center gap-2 px-4 text-[#8f8f8f]">
1349
+ <Loader2 className="h-4 w-4 animate-spin" />
1350
+ <span className="text-[14px] leading-[21px]">Loading conversation</span>
1351
+ </div>
1352
+ ) : null}
1353
+
1354
+ {!loading && displayEntries.length === 0 ? (
1355
+ <div className="px-4 py-2 text-[16px] leading-[24px] text-[#8f8f8f]">
1356
+ Start the next turn to stream follow-up work into this panel.
1357
+ </div>
1358
+ ) : null}
1359
+
1360
+ {feedItems.map((item) => (
1361
+ item.kind === "tool-group" ? (
1362
+ <ToolGroup key={item.id} entries={item.entries} autoCollapsed={!isSessionRunning} />
1363
+ ) : (
1364
+ <FeedEntry key={item.entry.id} entry={item.entry} agentName={normalizedAgentName} />
1365
+ )
1366
+ ))}
1367
+
1368
+ {error ? (
1369
+ <div className="rounded-[3px] border border-[#603535] bg-[rgba(210,81,81,0.12)] px-3 py-2 text-[13px] leading-[20px] text-[#f0b5b5]">
1370
+ {error}
1371
+ </div>
1372
+ ) : null}
1373
+
1374
+ {sendError ? (
1375
+ <div className="rounded-[3px] border border-[#603535] bg-[rgba(210,81,81,0.12)] px-3 py-2 text-[13px] leading-[20px] text-[#f0b5b5]">
1376
+ {sendError}
1377
+ </div>
1378
+ ) : null}
1379
+
1380
+ {parserState ? (
1381
+ <ParserStateBanner
1382
+ kind={parserState.kind}
1383
+ message={parserState.message}
1384
+ command={parserState.command}
1385
+ />
1386
+ ) : null}
1387
+
1388
+ <div ref={endRef} />
1389
+ </div>
1390
+ </div>
1391
+
1392
+ <div className="shrink-0 px-3 pb-4 pt-0 sm:px-4">
1393
+ <div className="mx-auto w-full max-w-[768px]">
1394
+ <div className="rounded-[3px] border border-[#333] bg-[#1c1c1c] shadow-[0_12px_40px_rgba(0,0,0,0.22)]">
1395
+ <div className="flex flex-wrap items-center gap-2 border-b border-[#333] px-2 py-2">
1396
+ {composerSummary ? <SummaryChip summary={composerSummary} /> : <div className="min-h-[29px]" />}
1397
+ <div className="ml-auto flex min-w-0 items-center gap-2">
1398
+ {normalizedAgentName ? (
1399
+ <div className="hidden items-center overflow-hidden sm:flex">
1400
+ <AgentTileIcon seed={{ label: normalizedAgentName }} className="h-[25px] w-[25px] border-none bg-transparent" />
1401
+ </div>
1402
+ ) : null}
1403
+ <div className="hidden h-[20px] w-[20px] items-center justify-center text-[#8f8f8f] sm:flex">
1404
+ <Code2 className="h-[15px] w-[15px]" strokeWidth={1.7} />
1405
+ </div>
1406
+ <div className="relative" ref={modelMenuRef}>
1407
+ <button
1408
+ type="button"
1409
+ onClick={() => setModelMenuOpen((open) => !open)}
1410
+ className="inline-flex min-h-[31px] items-center gap-2 rounded-[3px] border border-[#333] bg-[#1c1c1c] px-[9px] py-[5px] text-[14px] leading-[21px] text-[#c4c4c4] transition hover:bg-[#292929]"
1411
+ >
1412
+ <span className="max-w-[140px] truncate">{selectedModelLabel}</span>
1413
+ <ChevronDown className="h-[10px] w-[10px] text-[#8f8f8f]" strokeWidth={1.8} />
1414
+ </button>
1415
+
1416
+ {modelMenuOpen ? (
1417
+ <div className="absolute bottom-[calc(100%+8px)] right-0 z-20 max-h-80 w-[280px] overflow-y-auto rounded-[4px] border border-[#333] bg-[#1c1c1c] p-1 shadow-[0_18px_50px_rgba(0,0,0,0.35)]">
1418
+ <button
1419
+ type="button"
1420
+ onClick={() => {
1421
+ setSelectedModel(sessionModel?.trim() || "");
1422
+ setModelMenuOpen(false);
1423
+ }}
1424
+ className="flex w-full flex-col rounded-[3px] px-3 py-2 text-left transition hover:bg-[#292929]"
1425
+ >
1426
+ <span className="text-[14px] leading-[21px] text-[#c4c4c4]">Session default</span>
1427
+ <span className="text-[12px] leading-[18px] text-[#8f8f8f]">
1428
+ Keep using the model configured on this session.
1429
+ </span>
1430
+ </button>
1431
+
1432
+ {modelOptions.map((option) => (
1433
+ <button
1434
+ key={option.id}
1435
+ type="button"
1436
+ onClick={() => {
1437
+ setSelectedModel(option.id);
1438
+ setModelMenuOpen(false);
1439
+ }}
1440
+ className={`flex w-full flex-col rounded-[3px] px-3 py-2 text-left transition hover:bg-[#292929] ${selectedModel === option.id ? "bg-[#292929]" : ""}`}
1441
+ >
1442
+ <span className="text-[14px] leading-[21px] text-[#c4c4c4]">{option.label}</span>
1443
+ <span className="text-[12px] leading-[18px] text-[#8f8f8f]">{option.helper}</span>
1444
+ </button>
1445
+ ))}
1446
+ </div>
1447
+ ) : null}
1448
+ </div>
1449
+ </div>
1450
+ </div>
1451
+
1452
+ <div className="px-2 py-2">
1453
+ <textarea
1454
+ value={message}
1455
+ onChange={(event) => setMessage(event.target.value)}
1456
+ onKeyDown={handleComposerKeyDown}
1457
+ placeholder="Continue working on this task..."
1458
+ rows={1}
1459
+ className="min-h-[24px] w-full resize-none bg-transparent px-1 py-0 text-[16px] leading-[24px] text-[#8f8f8f] outline-none placeholder:text-[#8f8f8f]"
1460
+ />
1461
+
1462
+ {showSlashCommandMenu ? (
1463
+ <div className="mt-3 overflow-hidden rounded-[3px] border border-[#333] bg-[#171717]">
1464
+ <div className="border-b border-[#333] px-3 py-2 text-[11px] uppercase tracking-[0.18em] text-[#8f8f8f]">
1465
+ Slash commands
1466
+ </div>
1467
+ <div className="max-h-[220px] overflow-y-auto py-1">
1468
+ {slashCommandOptions.map((option, index) => (
1469
+ <button
1470
+ key={option.command}
1471
+ type="button"
1472
+ onClick={() => applySlashCommand(option)}
1473
+ className={`flex w-full flex-col gap-1 px-3 py-2 text-left transition ${
1474
+ index === selectedSlashIndex ? "bg-[#242424]" : "hover:bg-[#1f1f1f]"
1475
+ }`}
1476
+ >
1477
+ <span className="text-[14px] leading-[21px] text-[#f1f1f1]">{option.label}</span>
1478
+ <span className="text-[12px] leading-[18px] text-[#8f8f8f]">{option.description}</span>
1479
+ </button>
1480
+ ))}
1481
+ </div>
1482
+ <div className="border-t border-[#333] px-3 py-2 text-[12px] leading-[18px] text-[#8f8f8f]">
1483
+ Slash commands are passed straight to the live agent session under the chat UI.
1484
+ </div>
1485
+ </div>
1486
+ ) : null}
1487
+
1488
+ <AttachmentPills
1489
+ attachments={attachments.map((attachment) => attachment.file.name)}
1490
+ onRemove={(index) => {
1491
+ setAttachments((current) => {
1492
+ const next = [...current];
1493
+ next.splice(index, 1);
1494
+ return next;
1495
+ });
1496
+ }}
1497
+ />
1498
+
1499
+ <div className="mt-3 flex items-end justify-between gap-3">
1500
+ <div className="flex min-w-0 flex-wrap items-center gap-2">
1501
+ <input
1502
+ ref={fileInputRef}
1503
+ type="file"
1504
+ multiple
1505
+ className="hidden"
1506
+ onChange={handleAttachmentChange}
1507
+ />
1508
+ <button
1509
+ type="button"
1510
+ onClick={() => fileInputRef.current?.click()}
1511
+ className="inline-flex h-[29px] w-[33px] items-center justify-center rounded-[3px] border border-[#333] bg-[#1c1c1c] text-[#c4c4c4] transition hover:bg-[#292929]"
1512
+ aria-label="Add attachment"
1513
+ >
1514
+ <Paperclip className="h-[15px] w-[15px]" strokeWidth={1.7} />
1515
+ </button>
1516
+ <div className="inline-flex h-[29px] items-center justify-center rounded-[3px] border border-[#333] bg-[#1c1c1c] px-[9px] text-[#8f8f8f]">
1517
+ <Code2 className="h-[15px] w-[15px]" strokeWidth={1.7} />
1518
+ </div>
1519
+ {sessionReasoningEffort ? (
1520
+ <div className="hidden min-h-[29px] items-center rounded-[3px] bg-[#1c1c1c] px-[9px] py-[5px] text-[12px] leading-[18px] text-[#8f8f8f] sm:inline-flex">
1521
+ {sessionReasoningEffort}
1522
+ </div>
1523
+ ) : null}
1524
+ </div>
1525
+
1526
+ <button
1527
+ type="button"
1528
+ onClick={() => void (isSessionRunning ? handleInterrupt() : handleSend())}
1529
+ disabled={interrupting || (!isSessionRunning && (sending || (!message.trim() && attachments.length === 0)))}
1530
+ className={`inline-flex min-h-[29px] items-center justify-center rounded-[3px] px-4 py-[6px] text-[16px] leading-[16px] transition disabled:cursor-not-allowed disabled:opacity-40 ${
1531
+ isSessionRunning
1532
+ ? "border border-[#603535] bg-[rgba(210,81,81,0.12)] text-[#f0b5b5] hover:bg-[rgba(210,81,81,0.18)]"
1533
+ : "bg-[#292929] text-[#c4c4c4] hover:bg-[#313131]"
1534
+ }`}
1535
+ >
1536
+ {interrupting ? (
1537
+ <Loader2 className="h-4 w-4 animate-spin" />
1538
+ ) : isSessionRunning ? (
1539
+ <span className="inline-flex items-center gap-2">
1540
+ <span>Stop</span>
1541
+ <span className="hidden text-[11px] leading-[11px] text-[#8f8f8f] sm:inline">Esc</span>
1542
+ </span>
1543
+ ) : sending ? (
1544
+ <Loader2 className="h-4 w-4 animate-spin" />
1545
+ ) : (
1546
+ "Send"
1547
+ )}
1548
+ </button>
1549
+ </div>
1550
+ </div>
1551
+ </div>
1552
+ </div>
1553
+ </div>
1554
+ </div>
1555
+ </div>
1556
+ );
1557
+ }
1558
+
1559
+ export default ChatPanel;