conductor-oss 0.7.1 → 0.9.0

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 (381) hide show
  1. package/README.md +173 -134
  2. package/dist/backend.d.ts.map +1 -1
  3. package/dist/backend.js +18 -2
  4. package/dist/backend.js.map +1 -1
  5. package/dist/commands/dashboard.d.ts.map +1 -1
  6. package/dist/commands/dashboard.js +13 -7
  7. package/dist/commands/dashboard.js.map +1 -1
  8. package/node_modules/@conductor-oss/core/dist/config.d.ts.map +1 -1
  9. package/node_modules/@conductor-oss/core/dist/config.js +6 -1
  10. package/node_modules/@conductor-oss/core/dist/config.js.map +1 -1
  11. package/package.json +8 -6
  12. package/web/.next/standalone/packages/web/.next/BUILD_ID +1 -1
  13. package/web/.next/standalone/packages/web/.next/app-path-routes-manifest.json +2 -0
  14. package/web/.next/standalone/packages/web/.next/build-manifest.json +7 -7
  15. package/web/.next/standalone/packages/web/.next/prerender-manifest.json +3 -3
  16. package/web/.next/standalone/packages/web/.next/routes-manifest.json +44 -1
  17. package/web/.next/standalone/packages/web/.next/server/app/_global-error/page/build-manifest.json +5 -5
  18. package/web/.next/standalone/packages/web/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  19. package/web/.next/standalone/packages/web/.next/server/app/_global-error.html +2 -2
  20. package/web/.next/standalone/packages/web/.next/server/app/_global-error.rsc +7 -7
  21. package/web/.next/standalone/packages/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +2 -2
  22. package/web/.next/standalone/packages/web/.next/server/app/_global-error.segments/_full.segment.rsc +7 -7
  23. package/web/.next/standalone/packages/web/.next/server/app/_global-error.segments/_head.segment.rsc +3 -3
  24. package/web/.next/standalone/packages/web/.next/server/app/_global-error.segments/_index.segment.rsc +3 -3
  25. package/web/.next/standalone/packages/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  26. package/web/.next/standalone/packages/web/.next/server/app/_not-found/page/build-manifest.json +5 -5
  27. package/web/.next/standalone/packages/web/.next/server/app/_not-found/page/server-reference-manifest.json +7 -7
  28. package/web/.next/standalone/packages/web/.next/server/app/_not-found/page.js +2 -2
  29. package/web/.next/standalone/packages/web/.next/server/app/_not-found/page.js.nft.json +1 -1
  30. package/web/.next/standalone/packages/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  31. package/web/.next/standalone/packages/web/.next/server/app/_not-found.html +1 -1
  32. package/web/.next/standalone/packages/web/.next/server/app/_not-found.rsc +11 -11
  33. package/web/.next/standalone/packages/web/.next/server/app/_not-found.segments/_full.segment.rsc +11 -11
  34. package/web/.next/standalone/packages/web/.next/server/app/_not-found.segments/_head.segment.rsc +4 -4
  35. package/web/.next/standalone/packages/web/.next/server/app/_not-found.segments/_index.segment.rsc +6 -6
  36. package/web/.next/standalone/packages/web/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +2 -2
  37. package/web/.next/standalone/packages/web/.next/server/app/_not-found.segments/_not-found.segment.rsc +3 -3
  38. package/web/.next/standalone/packages/web/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  39. package/web/.next/standalone/packages/web/.next/server/app/api/access/route.js +2 -2
  40. package/web/.next/standalone/packages/web/.next/server/app/api/access/route.js.nft.json +1 -1
  41. package/web/.next/standalone/packages/web/.next/server/app/api/agents/route.js +2 -2
  42. package/web/.next/standalone/packages/web/.next/server/app/api/agents/route.js.nft.json +1 -1
  43. package/web/.next/standalone/packages/web/.next/server/app/api/app-update/route.js +2 -2
  44. package/web/.next/standalone/packages/web/.next/server/app/api/app-update/route.js.nft.json +1 -1
  45. package/web/.next/standalone/packages/web/.next/server/app/api/attachments/route.js +2 -2
  46. package/web/.next/standalone/packages/web/.next/server/app/api/attachments/route.js.nft.json +1 -1
  47. package/web/.next/standalone/packages/web/.next/server/app/api/auth/session/route.js +2 -2
  48. package/web/.next/standalone/packages/web/.next/server/app/api/auth/session/route.js.nft.json +1 -1
  49. package/web/.next/standalone/packages/web/.next/server/app/api/boards/comments/route.js +2 -2
  50. package/web/.next/standalone/packages/web/.next/server/app/api/boards/comments/route.js.nft.json +1 -1
  51. package/web/.next/standalone/packages/web/.next/server/app/api/boards/route.js +2 -2
  52. package/web/.next/standalone/packages/web/.next/server/app/api/boards/route.js.nft.json +1 -1
  53. package/web/.next/standalone/packages/web/.next/server/app/api/config/route.js +2 -2
  54. package/web/.next/standalone/packages/web/.next/server/app/api/config/route.js.nft.json +1 -1
  55. package/web/.next/standalone/packages/web/.next/server/app/api/context-files/open/route.js +2 -2
  56. package/web/.next/standalone/packages/web/.next/server/app/api/context-files/open/route.js.nft.json +1 -1
  57. package/web/.next/standalone/packages/web/.next/server/app/api/context-files/route.js +2 -2
  58. package/web/.next/standalone/packages/web/.next/server/app/api/context-files/route.js.nft.json +1 -1
  59. package/web/.next/standalone/packages/web/.next/server/app/api/events/route.js +2 -2
  60. package/web/.next/standalone/packages/web/.next/server/app/api/events/route.js.nft.json +1 -1
  61. package/web/.next/standalone/packages/web/.next/server/app/api/executor/health/route.js +2 -2
  62. package/web/.next/standalone/packages/web/.next/server/app/api/executor/health/route.js.nft.json +1 -1
  63. package/web/.next/standalone/packages/web/.next/server/app/api/filesystem/directory/route.js +2 -2
  64. package/web/.next/standalone/packages/web/.next/server/app/api/filesystem/directory/route.js.nft.json +1 -1
  65. package/web/.next/standalone/packages/web/.next/server/app/api/filesystem/pick-directory/route.js +2 -2
  66. package/web/.next/standalone/packages/web/.next/server/app/api/filesystem/pick-directory/route.js.nft.json +1 -1
  67. package/web/.next/standalone/packages/web/.next/server/app/api/github/repos/route.js +2 -2
  68. package/web/.next/standalone/packages/web/.next/server/app/api/github/repos/route.js.nft.json +1 -1
  69. package/web/.next/standalone/packages/web/.next/server/app/api/github/webhook/route.js +2 -2
  70. package/web/.next/standalone/packages/web/.next/server/app/api/github/webhook/route.js.nft.json +1 -1
  71. package/web/.next/standalone/packages/web/.next/server/app/api/health/boards/route.js +2 -2
  72. package/web/.next/standalone/packages/web/.next/server/app/api/health/boards/route.js.nft.json +1 -1
  73. package/web/.next/standalone/packages/web/.next/server/app/api/health/sessions/route.js +2 -2
  74. package/web/.next/standalone/packages/web/.next/server/app/api/health/sessions/route.js.nft.json +1 -1
  75. package/web/.next/standalone/packages/web/.next/server/app/api/notifications/route.js +2 -2
  76. package/web/.next/standalone/packages/web/.next/server/app/api/notifications/route.js.nft.json +1 -1
  77. package/web/.next/standalone/packages/web/.next/server/app/api/preferences/route.js +2 -2
  78. package/web/.next/standalone/packages/web/.next/server/app/api/preferences/route.js.nft.json +1 -1
  79. package/web/.next/standalone/packages/web/.next/server/app/api/remote-access/route.js +2 -2
  80. package/web/.next/standalone/packages/web/.next/server/app/api/remote-access/route.js.nft.json +1 -1
  81. package/web/.next/standalone/packages/web/.next/server/app/api/repositories/[id]/route.js +2 -2
  82. package/web/.next/standalone/packages/web/.next/server/app/api/repositories/[id]/route.js.nft.json +1 -1
  83. package/web/.next/standalone/packages/web/.next/server/app/api/repositories/route.js +2 -2
  84. package/web/.next/standalone/packages/web/.next/server/app/api/repositories/route.js.nft.json +1 -1
  85. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/actions/route.js +2 -2
  86. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/actions/route.js.nft.json +1 -1
  87. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/archive/route.js +2 -2
  88. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/archive/route.js.nft.json +1 -1
  89. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/checks/route.js +2 -2
  90. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/checks/route.js.nft.json +1 -1
  91. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/diff/route.js +2 -2
  92. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/diff/route.js.nft.json +1 -1
  93. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/feed/route.js +2 -2
  94. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/feed/route.js.nft.json +1 -1
  95. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/feed/stream/route.js +2 -2
  96. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/feed/stream/route.js.nft.json +1 -1
  97. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/feedback/route.js +2 -2
  98. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/feedback/route.js.nft.json +1 -1
  99. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/files/route.js +2 -2
  100. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/files/route.js.nft.json +1 -1
  101. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/interrupt/route.js +2 -2
  102. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/interrupt/route.js.nft.json +1 -1
  103. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/keys/route.js +2 -2
  104. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/keys/route.js.nft.json +1 -1
  105. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/kill/route.js +2 -2
  106. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/kill/route.js.nft.json +1 -1
  107. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/output/route.js +2 -2
  108. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/output/route.js.nft.json +1 -1
  109. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/output/stream/route.js +2 -2
  110. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/output/stream/route.js.nft.json +1 -1
  111. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/preview/dom/route.js +1 -1
  112. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/preview/dom/route.js.nft.json +1 -1
  113. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/preview/route.js +1 -1
  114. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/preview/route.js.nft.json +1 -1
  115. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/preview/screenshot/route.js +1 -1
  116. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/preview/screenshot/route.js.nft.json +1 -1
  117. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/restore/route.js +2 -2
  118. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/restore/route.js.nft.json +1 -1
  119. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/route.js +2 -2
  120. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/route.js.nft.json +1 -1
  121. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/send/route.js +2 -2
  122. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/send/route.js.nft.json +1 -1
  123. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/terminal/connection/route/app-paths-manifest.json +3 -0
  124. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/terminal/connection/route/build-manifest.json +11 -0
  125. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/terminal/connection/route/server-reference-manifest.json +4 -0
  126. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/terminal/connection/route.js +10 -0
  127. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/terminal/connection/route.js.map +5 -0
  128. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/terminal/connection/route.js.nft.json +1 -0
  129. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/terminal/connection/route_client-reference-manifest.js +2 -0
  130. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/terminal/snapshot/route/app-paths-manifest.json +3 -0
  131. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/terminal/snapshot/route/build-manifest.json +11 -0
  132. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/terminal/snapshot/route/server-reference-manifest.json +4 -0
  133. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/terminal/snapshot/route.js +10 -0
  134. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/terminal/snapshot/route.js.map +5 -0
  135. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/terminal/snapshot/route.js.nft.json +1 -0
  136. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/[id]/terminal/snapshot/route_client-reference-manifest.js +2 -0
  137. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/route.js +2 -2
  138. package/web/.next/standalone/packages/web/.next/server/app/api/sessions/route.js.nft.json +1 -1
  139. package/web/.next/standalone/packages/web/.next/server/app/api/spawn/route.js +2 -2
  140. package/web/.next/standalone/packages/web/.next/server/app/api/spawn/route.js.nft.json +1 -1
  141. package/web/.next/standalone/packages/web/.next/server/app/api/workspaces/branches/route.js +2 -2
  142. package/web/.next/standalone/packages/web/.next/server/app/api/workspaces/branches/route.js.nft.json +1 -1
  143. package/web/.next/standalone/packages/web/.next/server/app/api/workspaces/route.js +2 -2
  144. package/web/.next/standalone/packages/web/.next/server/app/api/workspaces/route.js.nft.json +1 -1
  145. package/web/.next/standalone/packages/web/.next/server/app/page/build-manifest.json +5 -5
  146. package/web/.next/standalone/packages/web/.next/server/app/page/react-loadable-manifest.json +4 -4
  147. package/web/.next/standalone/packages/web/.next/server/app/page/server-reference-manifest.json +7 -7
  148. package/web/.next/standalone/packages/web/.next/server/app/page.js +2 -2
  149. package/web/.next/standalone/packages/web/.next/server/app/page.js.nft.json +1 -1
  150. package/web/.next/standalone/packages/web/.next/server/app/page_client-reference-manifest.js +1 -1
  151. package/web/.next/standalone/packages/web/.next/server/app/sessions/[id]/page/build-manifest.json +5 -5
  152. package/web/.next/standalone/packages/web/.next/server/app/sessions/[id]/page/server-reference-manifest.json +7 -7
  153. package/web/.next/standalone/packages/web/.next/server/app/sessions/[id]/page.js +2 -2
  154. package/web/.next/standalone/packages/web/.next/server/app/sessions/[id]/page.js.nft.json +1 -1
  155. package/web/.next/standalone/packages/web/.next/server/app/sessions/[id]/page_client-reference-manifest.js +1 -1
  156. package/web/.next/standalone/packages/web/.next/server/app/sign-in/[[...sign-in]]/page/build-manifest.json +5 -5
  157. package/web/.next/standalone/packages/web/.next/server/app/sign-in/[[...sign-in]]/page/server-reference-manifest.json +7 -7
  158. package/web/.next/standalone/packages/web/.next/server/app/sign-in/[[...sign-in]]/page.js.nft.json +1 -1
  159. package/web/.next/standalone/packages/web/.next/server/app/sign-in/[[...sign-in]]/page_client-reference-manifest.js +1 -1
  160. package/web/.next/standalone/packages/web/.next/server/app/unlock/page/build-manifest.json +5 -5
  161. package/web/.next/standalone/packages/web/.next/server/app/unlock/page/server-reference-manifest.json +14 -14
  162. package/web/.next/standalone/packages/web/.next/server/app/unlock/page.js.nft.json +1 -1
  163. package/web/.next/standalone/packages/web/.next/server/app/unlock/page_client-reference-manifest.js +1 -1
  164. package/web/.next/standalone/packages/web/.next/server/app-paths-manifest.json +2 -0
  165. package/web/.next/standalone/packages/web/.next/server/chunks/26076_server_app_api_sessions_[id]_terminal_connection_route_actions_46c114ee.js +3 -0
  166. package/web/.next/standalone/packages/web/.next/server/chunks/26076_server_app_api_sessions_[id]_terminal_snapshot_route_actions_cfb4de43.js +3 -0
  167. package/web/.next/standalone/packages/web/.next/server/chunks/730ea_web__next-internal_server_app_api_sessions_[id]_restore_route_actions_41a4c356.js +1 -1
  168. package/web/.next/standalone/packages/web/.next/server/chunks/{[root-of-the-server]__b716459f._.js → [root-of-the-server]__08556fc3._.js} +2 -2
  169. package/web/.next/standalone/packages/web/.next/server/chunks/{[root-of-the-server]__624bcdc9._.js → [root-of-the-server]__0e496df1._.js} +2 -2
  170. package/web/.next/standalone/packages/web/.next/server/chunks/{[root-of-the-server]__9bf61231._.js → [root-of-the-server]__115b433b._.js} +2 -2
  171. package/web/.next/standalone/packages/web/.next/server/chunks/{[root-of-the-server]__70929198._.js → [root-of-the-server]__120a0868._.js} +2 -2
  172. package/web/.next/standalone/packages/web/.next/server/chunks/{[root-of-the-server]__17d710ef._.js → [root-of-the-server]__1a623333._.js} +2 -2
  173. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__262e987e._.js +1 -1
  174. package/web/.next/standalone/packages/web/.next/server/chunks/{[root-of-the-server]__31053ac2._.js → [root-of-the-server]__2713bac9._.js} +2 -2
  175. package/web/.next/standalone/packages/web/.next/server/chunks/{[root-of-the-server]__8c576b6a._.js → [root-of-the-server]__2798ac7c._.js} +2 -2
  176. package/web/.next/standalone/packages/web/.next/server/chunks/{[root-of-the-server]__747e6415._.js → [root-of-the-server]__27b2bd14._.js} +2 -2
  177. package/web/.next/standalone/packages/web/.next/server/chunks/{[root-of-the-server]__a4b1a94c._.js → [root-of-the-server]__29d94573._.js} +2 -2
  178. package/web/.next/standalone/packages/web/.next/server/chunks/{[root-of-the-server]__732fc06e._.js → [root-of-the-server]__2b59cba9._.js} +2 -2
  179. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__2ce39d51._.js +1 -1
  180. package/web/.next/standalone/packages/web/.next/server/chunks/{[root-of-the-server]__3e507276._.js → [root-of-the-server]__2fea4a4c._.js} +2 -2
  181. package/web/.next/standalone/packages/web/.next/server/chunks/{[root-of-the-server]__59635ca5._.js → [root-of-the-server]__36559d88._.js} +2 -2
  182. package/web/.next/standalone/packages/web/.next/server/chunks/{[root-of-the-server]__f0ec1021._.js → [root-of-the-server]__4117784b._.js} +2 -2
  183. package/web/.next/standalone/packages/web/.next/server/chunks/{[root-of-the-server]__543bc377._.js → [root-of-the-server]__43b35d39._.js} +2 -2
  184. package/web/.next/standalone/packages/web/.next/server/chunks/{[root-of-the-server]__ba70a88e._.js → [root-of-the-server]__444bf146._.js} +2 -2
  185. package/web/.next/standalone/packages/web/.next/server/chunks/{[root-of-the-server]__fd0a681b._.js → [root-of-the-server]__45483f4b._.js} +2 -2
  186. package/web/.next/standalone/packages/web/.next/server/chunks/{[root-of-the-server]__98f4a7bd._.js → [root-of-the-server]__4644a89e._.js} +2 -2
  187. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__4c78886c._.js +3 -0
  188. package/web/.next/standalone/packages/web/.next/server/chunks/{[root-of-the-server]__e7aaee2d._.js → [root-of-the-server]__4cea5dca._.js} +2 -2
  189. package/web/.next/standalone/packages/web/.next/server/chunks/{[root-of-the-server]__33494588._.js → [root-of-the-server]__575c7392._.js} +2 -2
  190. package/web/.next/standalone/packages/web/.next/server/chunks/{[root-of-the-server]__eae97345._.js → [root-of-the-server]__57605af7._.js} +2 -2
  191. package/web/.next/standalone/packages/web/.next/server/chunks/{[root-of-the-server]__be233a9f._.js → [root-of-the-server]__57c8ca1a._.js} +2 -2
  192. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__5e2b35cd._.js +3 -0
  193. package/web/.next/standalone/packages/web/.next/server/chunks/{[root-of-the-server]__8ace49d1._.js → [root-of-the-server]__5f5433df._.js} +2 -2
  194. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__6313c91e._.js +3 -3
  195. package/web/.next/standalone/packages/web/.next/server/chunks/{[root-of-the-server]__3dc4c761._.js → [root-of-the-server]__6a8b5dc7._.js} +2 -2
  196. package/web/.next/standalone/packages/web/.next/server/chunks/{[root-of-the-server]__3318d8a1._.js → [root-of-the-server]__717081d9._.js} +2 -2
  197. package/web/.next/standalone/packages/web/.next/server/chunks/{[root-of-the-server]__ae73aa49._.js → [root-of-the-server]__75668566._.js} +2 -2
  198. package/web/.next/standalone/packages/web/.next/server/chunks/{[root-of-the-server]__b4039db5._.js → [root-of-the-server]__7a6210dc._.js} +2 -2
  199. package/web/.next/standalone/packages/web/.next/server/chunks/{[root-of-the-server]__34e636e5._.js → [root-of-the-server]__7ca5b93b._.js} +2 -2
  200. package/web/.next/standalone/packages/web/.next/server/chunks/{[root-of-the-server]__b53b70e7._.js → [root-of-the-server]__8462ddf1._.js} +2 -2
  201. package/web/.next/standalone/packages/web/.next/server/chunks/{[root-of-the-server]__3937a996._.js → [root-of-the-server]__9e363e9c._.js} +2 -2
  202. package/web/.next/standalone/packages/web/.next/server/chunks/{[root-of-the-server]__4c5f7cab._.js → [root-of-the-server]__a0467c5b._.js} +2 -2
  203. package/web/.next/standalone/packages/web/.next/server/chunks/{[root-of-the-server]__9576223c._.js → [root-of-the-server]__a8d68307._.js} +2 -2
  204. package/web/.next/standalone/packages/web/.next/server/chunks/{[root-of-the-server]__82e86bb6._.js → [root-of-the-server]__ac79a67b._.js} +2 -2
  205. package/web/.next/standalone/packages/web/.next/server/chunks/{[root-of-the-server]__bcd0c846._.js → [root-of-the-server]__af5be1d9._.js} +2 -2
  206. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__b3cd93ca._.js +3 -0
  207. package/web/.next/standalone/packages/web/.next/server/chunks/{[root-of-the-server]__540ebc7f._.js → [root-of-the-server]__b7314f2a._.js} +2 -2
  208. package/web/.next/standalone/packages/web/.next/server/chunks/{[root-of-the-server]__bb2675cd._.js → [root-of-the-server]__bcbc6330._.js} +2 -2
  209. package/web/.next/standalone/packages/web/.next/server/chunks/{[root-of-the-server]__fe4c1384._.js → [root-of-the-server]__bfbdd808._.js} +2 -2
  210. package/web/.next/standalone/packages/web/.next/server/chunks/{[root-of-the-server]__b00db558._.js → [root-of-the-server]__c205eff4._.js} +2 -2
  211. package/web/.next/standalone/packages/web/.next/server/chunks/{[root-of-the-server]__c455995a._.js → [root-of-the-server]__c39ceb71._.js} +2 -2
  212. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__c9cb9ac6._.js +3 -0
  213. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__cff9ddef._.js +1 -1
  214. package/web/.next/standalone/packages/web/.next/server/chunks/{[root-of-the-server]__7c87a52f._.js → [root-of-the-server]__d65b8403._.js} +2 -2
  215. package/web/.next/standalone/packages/web/.next/server/chunks/{[root-of-the-server]__eb6e6bb9._.js → [root-of-the-server]__d7b9cb55._.js} +2 -2
  216. package/web/.next/standalone/packages/web/.next/server/chunks/{[root-of-the-server]__53daf5c6._.js → [root-of-the-server]__df103a4a._.js} +2 -2
  217. package/web/.next/standalone/packages/web/.next/server/chunks/[root-of-the-server]__ea845f9f._.js +1 -1
  218. package/web/.next/standalone/packages/web/.next/server/chunks/{[root-of-the-server]__8ee7749b._.js → [root-of-the-server]__f5a16619._.js} +2 -2
  219. package/web/.next/standalone/packages/web/.next/server/chunks/{[root-of-the-server]__9940de77._.js → [root-of-the-server]__f62d8a1f._.js} +2 -2
  220. package/web/.next/standalone/packages/web/.next/server/chunks/{[root-of-the-server]__5df70a62._.js → [root-of-the-server]__f7c7ed71._.js} +2 -2
  221. package/web/.next/standalone/packages/web/.next/server/chunks/{[root-of-the-server]__520aa408._.js → [root-of-the-server]__fa5bbdc8._.js} +2 -2
  222. package/web/.next/standalone/packages/web/.next/server/chunks/{[root-of-the-server]__e385846c._.js → [root-of-the-server]__fed9223f._.js} +2 -2
  223. package/web/.next/standalone/packages/web/.next/server/chunks/_2c837d66._.js +5 -5
  224. package/web/.next/standalone/packages/web/.next/server/chunks/node_modules_next_dist_esm_build_templates_app-route_eaad1f33.js +1 -1
  225. package/web/.next/standalone/packages/web/.next/server/chunks/ssr/[root-of-the-server]__000b8c99._.js +1 -1
  226. package/web/.next/standalone/packages/web/.next/server/chunks/ssr/{[root-of-the-server]__4f387f9d._.js → [root-of-the-server]__10a850c6._.js} +2 -2
  227. package/web/.next/standalone/packages/web/.next/server/chunks/ssr/{[root-of-the-server]__7829c78d._.js → [root-of-the-server]__17f5cb6a._.js} +2 -2
  228. package/web/.next/standalone/packages/web/.next/server/chunks/ssr/[root-of-the-server]__29d8d063._.js +1 -1
  229. package/web/.next/standalone/packages/web/.next/server/chunks/ssr/[root-of-the-server]__3ea76517._.js +3 -0
  230. package/web/.next/standalone/packages/web/.next/server/chunks/ssr/{[root-of-the-server]__99387ae7._.js → [root-of-the-server]__6647f7ec._.js} +2 -2
  231. package/web/.next/standalone/packages/web/.next/server/chunks/ssr/{[root-of-the-server]__a509d17d._.js → [root-of-the-server]__9f45b36b._.js} +2 -2
  232. package/web/.next/standalone/packages/web/.next/server/chunks/ssr/{[root-of-the-server]__bc8d015f._.js → [root-of-the-server]__f8f50c0b._.js} +2 -2
  233. package/web/.next/standalone/packages/web/.next/server/chunks/ssr/_0e1412de._.js +1 -1
  234. package/web/.next/standalone/packages/web/.next/server/chunks/ssr/_230c0c14._.js +4 -4
  235. package/web/.next/standalone/packages/web/.next/server/chunks/ssr/_2b5578a1._.js +3 -0
  236. package/web/.next/standalone/packages/web/.next/server/chunks/ssr/{_b6d31783._.js → _532f707d._.js} +3 -3
  237. package/web/.next/standalone/packages/web/.next/server/chunks/ssr/_5571204d._.js +3 -0
  238. package/web/.next/standalone/packages/web/.next/server/chunks/ssr/_69e05fca._.js +1 -1
  239. package/web/.next/standalone/packages/web/.next/server/chunks/ssr/_6cfd06c2._.js +1 -1
  240. package/web/.next/standalone/packages/web/.next/server/chunks/ssr/_80efe193._.js +1 -1
  241. package/web/.next/standalone/packages/web/.next/server/chunks/ssr/{_a4a4deb7._.js → _9e7585e3._.js} +2 -2
  242. package/web/.next/standalone/packages/web/.next/server/chunks/ssr/_b214b154._.js +1 -1
  243. package/web/.next/standalone/packages/web/.next/server/chunks/ssr/_b8358e63._.js +3 -0
  244. package/web/.next/standalone/packages/web/.next/server/chunks/ssr/_c0f0e227._.js +1 -1
  245. package/web/.next/standalone/packages/web/.next/server/chunks/ssr/{_8982bbf3._.js → _de3b7194._.js} +2 -2
  246. package/web/.next/standalone/packages/web/.next/server/chunks/ssr/_f36ddaa9._.js +1 -1
  247. package/web/.next/standalone/packages/web/.next/server/chunks/ssr/{node_modules_@clerk_nextjs_dist_esm_app-router_743f164d._.js → node_modules_@clerk_nextjs_dist_esm_app-router_a9e633d8._.js} +2 -2
  248. package/web/.next/standalone/packages/web/.next/server/chunks/ssr/node_modules_@clerk_nextjs_dist_esm_app-router_f33d83e6._.js +3 -0
  249. package/web/.next/standalone/packages/web/.next/server/chunks/ssr/node_modules_@radix-ui_d03fdd57._.js +3 -0
  250. package/web/.next/standalone/packages/web/.next/server/chunks/ssr/node_modules_@xterm_addon-fit_lib_addon-fit_mjs_9b7cb17b._.js +3 -0
  251. package/web/.next/standalone/packages/web/.next/server/chunks/ssr/node_modules_@xterm_addon-search_lib_addon-search_mjs_8d69d9d7._.js +11 -0
  252. package/web/.next/standalone/packages/web/.next/server/chunks/ssr/node_modules_@xterm_xterm_lib_xterm_mjs_a1a7b9e9._.js +20 -0
  253. package/web/.next/standalone/packages/web/.next/server/chunks/ssr/node_modules_afb6e107._.js +3 -0
  254. package/web/.next/standalone/packages/web/.next/server/chunks/ssr/node_modules_lucide-react_dist_esm_icons_refresh-cw_50f1c1e7.js +3 -0
  255. package/web/.next/standalone/packages/web/.next/server/chunks/ssr/node_modules_next_dist_2df23979._.js +1 -1
  256. package/web/.next/standalone/packages/web/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_cd51dad4.js +2 -2
  257. package/web/.next/standalone/packages/web/.next/server/chunks/ssr/packages_web_src_components_board_WorkspaceKanban_tsx_735b7999._.js +1 -1
  258. package/web/.next/standalone/packages/web/.next/server/chunks/ssr/packages_web_src_components_sessions_SessionDetail_tsx_5fcad270._.js +6 -0
  259. package/web/.next/standalone/packages/web/.next/server/chunks/ssr/packages_web_src_features_dashboard_DashboardClient_tsx_81ae42b0._.js +1 -1
  260. package/web/.next/standalone/packages/web/.next/server/functions-config-manifest.json +3 -1
  261. package/web/.next/standalone/packages/web/.next/server/middleware-build-manifest.js +5 -5
  262. package/web/.next/standalone/packages/web/.next/server/pages/404.html +1 -1
  263. package/web/.next/standalone/packages/web/.next/server/pages/500.html +2 -2
  264. package/web/.next/standalone/packages/web/.next/server/server-reference-manifest.js +1 -1
  265. package/web/.next/standalone/packages/web/.next/server/server-reference-manifest.json +15 -15
  266. package/web/.next/standalone/packages/web/.next/static/chunks/07be250784a6a689.js +1 -0
  267. package/web/.next/standalone/packages/web/.next/static/chunks/0866f5c380851a16.js +1 -0
  268. package/web/.next/standalone/packages/web/.next/static/chunks/0cdc18649f440c71.js +1 -0
  269. package/web/.next/standalone/packages/web/.next/static/chunks/0f7eb6d5a59ee3ae.js +1 -0
  270. package/web/.next/standalone/packages/web/.next/static/chunks/144b356fe7daff8d.js +1 -0
  271. package/web/.next/standalone/packages/web/.next/static/chunks/{c4c79d5d0b280aeb.js → 2f236954d6a65e12.js} +1 -1
  272. package/web/.next/standalone/packages/web/.next/static/chunks/3cdf839644f79d43.js +18 -0
  273. package/web/.next/standalone/packages/web/.next/static/chunks/5a4c4d4d5f30829b.css +3 -0
  274. package/web/.next/standalone/packages/web/.next/static/chunks/6850a6cda159c98d.js +1 -0
  275. package/web/.next/{static/chunks/06bdd070b8d25946.js → standalone/packages/web/.next/static/chunks/69be39811437728d.js} +1 -1
  276. package/web/.next/standalone/packages/web/.next/static/chunks/6cec31da5f555e99.js +1 -0
  277. package/web/.next/standalone/packages/web/.next/static/chunks/70d1e7a526f0f4e2.js +9 -0
  278. package/web/.next/standalone/packages/web/.next/static/chunks/{ba2aa8b54e912820.js → 723acbe92d3f9e7e.js} +1 -1
  279. package/web/.next/standalone/packages/web/.next/static/chunks/739c6f71243d76d8.js +1 -0
  280. package/web/.next/standalone/packages/web/.next/static/chunks/a6ec1ab37eb7b410.js +1 -0
  281. package/web/.next/standalone/packages/web/.next/static/chunks/af8bfb72187b7cbf.js +1 -0
  282. package/web/.next/standalone/packages/web/.next/static/chunks/b86b8884ddf84717.js +1 -0
  283. package/web/.next/standalone/packages/web/.next/static/chunks/c1b8a2d2c623a0dc.js +6 -0
  284. package/web/.next/standalone/packages/web/.next/static/chunks/c993a1a4204fce88.js +4 -0
  285. package/web/.next/standalone/packages/web/.next/static/chunks/ca3e38b4495a3d39.js +1 -0
  286. package/web/.next/standalone/packages/web/.next/static/chunks/{45bd2451c2b0790c.js → caf02f8136b16992.js} +2 -2
  287. package/web/.next/standalone/packages/web/.next/static/chunks/d4269c59429734ad.js +1 -0
  288. package/web/.next/{static/chunks/28eac764d6544827.js → standalone/packages/web/.next/static/chunks/e5bcec03f80af56a.js} +1 -1
  289. package/web/.next/standalone/packages/web/.next/static/chunks/{turbopack-49f4119854e8206e.js → turbopack-26870d017b23fcf0.js} +1 -1
  290. package/web/.next/standalone/packages/web/next.config.ts +16 -0
  291. package/web/.next/standalone/packages/web/package.json +3 -1
  292. package/web/.next/standalone/packages/web/src/app/api/sessions/[id]/terminal/connection/route.ts +64 -0
  293. package/web/.next/standalone/packages/web/src/app/api/sessions/[id]/terminal/snapshot/route.ts +14 -0
  294. package/web/.next/standalone/packages/web/src/app/globals.css +12 -4
  295. package/web/.next/standalone/packages/web/src/components/Dashboard.tsx +1 -5
  296. package/web/.next/standalone/packages/web/src/components/TerminalView.tsx +528 -100
  297. package/web/.next/standalone/packages/web/src/components/board/WorkspaceKanban.tsx +3 -3
  298. package/web/.next/standalone/packages/web/src/components/layout/AppShell.tsx +3 -3
  299. package/web/.next/standalone/packages/web/src/components/layout/Sidebar.tsx +29 -18
  300. package/web/.next/standalone/packages/web/src/components/layout/TopBar.tsx +3 -3
  301. package/web/.next/standalone/packages/web/src/components/sessions/ChatPanel.tsx +61 -5
  302. package/web/.next/standalone/packages/web/src/components/sessions/SessionDetail.tsx +99 -46
  303. package/web/.next/standalone/packages/web/src/components/sessions/SessionPreview.tsx +231 -233
  304. package/web/.next/standalone/packages/web/src/components/sessions/SessionTerminal.tsx +1212 -0
  305. package/web/.next/standalone/packages/web/src/components/sessions/terminalInsert.ts +6 -0
  306. package/web/.next/standalone/packages/web/src/components/terminal/xtermTheme.ts +70 -0
  307. package/web/.next/standalone/packages/web/src/components/ui/Tabs.tsx +2 -2
  308. package/web/.next/standalone/packages/web/src/features/dashboard/DashboardClient.tsx +104 -31
  309. package/web/.next/standalone/packages/web/src/features/sessions/SessionPageClient.tsx +2 -2
  310. package/web/.next/standalone/packages/web/src/lib/devPreviewBrowser.ts +15 -3
  311. package/web/.next/static/chunks/07be250784a6a689.js +1 -0
  312. package/web/.next/static/chunks/0866f5c380851a16.js +1 -0
  313. package/web/.next/static/chunks/0cdc18649f440c71.js +1 -0
  314. package/web/.next/static/chunks/0f7eb6d5a59ee3ae.js +1 -0
  315. package/web/.next/static/chunks/144b356fe7daff8d.js +1 -0
  316. package/web/.next/static/chunks/{c4c79d5d0b280aeb.js → 2f236954d6a65e12.js} +1 -1
  317. package/web/.next/static/chunks/3cdf839644f79d43.js +18 -0
  318. package/web/.next/static/chunks/5a4c4d4d5f30829b.css +3 -0
  319. package/web/.next/static/chunks/6850a6cda159c98d.js +1 -0
  320. package/web/.next/{standalone/packages/web/.next/static/chunks/06bdd070b8d25946.js → static/chunks/69be39811437728d.js} +1 -1
  321. package/web/.next/static/chunks/6cec31da5f555e99.js +1 -0
  322. package/web/.next/static/chunks/70d1e7a526f0f4e2.js +9 -0
  323. package/web/.next/static/chunks/{ba2aa8b54e912820.js → 723acbe92d3f9e7e.js} +1 -1
  324. package/web/.next/static/chunks/739c6f71243d76d8.js +1 -0
  325. package/web/.next/static/chunks/a6ec1ab37eb7b410.js +1 -0
  326. package/web/.next/static/chunks/af8bfb72187b7cbf.js +1 -0
  327. package/web/.next/static/chunks/b86b8884ddf84717.js +1 -0
  328. package/web/.next/static/chunks/c1b8a2d2c623a0dc.js +6 -0
  329. package/web/.next/static/chunks/c993a1a4204fce88.js +4 -0
  330. package/web/.next/static/chunks/ca3e38b4495a3d39.js +1 -0
  331. package/web/.next/static/chunks/{45bd2451c2b0790c.js → caf02f8136b16992.js} +2 -2
  332. package/web/.next/static/chunks/d4269c59429734ad.js +1 -0
  333. package/web/.next/{standalone/packages/web/.next/static/chunks/28eac764d6544827.js → static/chunks/e5bcec03f80af56a.js} +1 -1
  334. package/web/.next/static/chunks/{turbopack-49f4119854e8206e.js → turbopack-26870d017b23fcf0.js} +1 -1
  335. package/web/.next/standalone/packages/web/.next/server/chunks/ssr/[root-of-the-server]__29091976._.js +0 -3
  336. package/web/.next/standalone/packages/web/.next/server/chunks/ssr/[root-of-the-server]__784e6aef._.js +0 -3
  337. package/web/.next/standalone/packages/web/.next/server/chunks/ssr/[root-of-the-server]__b388693f._.js +0 -3
  338. package/web/.next/standalone/packages/web/.next/server/chunks/ssr/[root-of-the-server]__d1efcbf0._.js +0 -3
  339. package/web/.next/standalone/packages/web/.next/server/chunks/ssr/_e1c18705._.js +0 -3
  340. package/web/.next/standalone/packages/web/.next/server/chunks/ssr/node_modules_@clerk_nextjs_dist_esm_app-router_2a090a71._.js +0 -3
  341. package/web/.next/standalone/packages/web/.next/server/chunks/ssr/node_modules_@radix-ui_02f0d3f0._.js +0 -3
  342. package/web/.next/standalone/packages/web/.next/server/chunks/ssr/node_modules_lucide-react_dist_esm_icons_message-square_2e76b8d9.js +0 -3
  343. package/web/.next/standalone/packages/web/.next/server/chunks/ssr/packages_web_src_components_ui_Tooltip_tsx_6becc8ca._.js +0 -3
  344. package/web/.next/standalone/packages/web/.next/static/chunks/07f3b9a104ce0ff4.js +0 -1
  345. package/web/.next/standalone/packages/web/.next/static/chunks/1004422d31074d62.js +0 -1
  346. package/web/.next/standalone/packages/web/.next/static/chunks/25afa19789883705.js +0 -6
  347. package/web/.next/standalone/packages/web/.next/static/chunks/2bc11b604b131190.js +0 -1
  348. package/web/.next/standalone/packages/web/.next/static/chunks/30ababddac1b82dc.js +0 -1
  349. package/web/.next/standalone/packages/web/.next/static/chunks/64f0033534ca1ad3.css +0 -3
  350. package/web/.next/standalone/packages/web/.next/static/chunks/902a6ba5837e1e57.js +0 -1
  351. package/web/.next/standalone/packages/web/.next/static/chunks/a28bcda8dd6b68ee.js +0 -1
  352. package/web/.next/standalone/packages/web/.next/static/chunks/aabc80195233b4da.js +0 -1
  353. package/web/.next/standalone/packages/web/.next/static/chunks/b6069d0eb07a978f.js +0 -1
  354. package/web/.next/standalone/packages/web/.next/static/chunks/c2caa064748bb0b5.js +0 -1
  355. package/web/.next/standalone/packages/web/.next/static/chunks/c5f8e486166298c2.js +0 -1
  356. package/web/.next/standalone/packages/web/.next/static/chunks/d6a81d2f8b98b4be.js +0 -1
  357. package/web/.next/standalone/packages/web/.next/static/chunks/dfa8ef24e636ca14.js +0 -1
  358. package/web/.next/standalone/packages/web/.next/static/chunks/e9d0e95bbaa0f4fb.js +0 -1
  359. package/web/.next/standalone/packages/web/.next/static/chunks/ebaa0c535c4135f1.js +0 -1
  360. package/web/.next/static/chunks/07f3b9a104ce0ff4.js +0 -1
  361. package/web/.next/static/chunks/1004422d31074d62.js +0 -1
  362. package/web/.next/static/chunks/25afa19789883705.js +0 -6
  363. package/web/.next/static/chunks/2bc11b604b131190.js +0 -1
  364. package/web/.next/static/chunks/30ababddac1b82dc.js +0 -1
  365. package/web/.next/static/chunks/64f0033534ca1ad3.css +0 -3
  366. package/web/.next/static/chunks/902a6ba5837e1e57.js +0 -1
  367. package/web/.next/static/chunks/a28bcda8dd6b68ee.js +0 -1
  368. package/web/.next/static/chunks/aabc80195233b4da.js +0 -1
  369. package/web/.next/static/chunks/b6069d0eb07a978f.js +0 -1
  370. package/web/.next/static/chunks/c2caa064748bb0b5.js +0 -1
  371. package/web/.next/static/chunks/c5f8e486166298c2.js +0 -1
  372. package/web/.next/static/chunks/d6a81d2f8b98b4be.js +0 -1
  373. package/web/.next/static/chunks/dfa8ef24e636ca14.js +0 -1
  374. package/web/.next/static/chunks/e9d0e95bbaa0f4fb.js +0 -1
  375. package/web/.next/static/chunks/ebaa0c535c4135f1.js +0 -1
  376. /package/web/.next/standalone/packages/web/.next/static/{EKHFeqSnbpFbCnV8AGVjm → dzgjDKuem6HLwWyK0KMG4}/_buildManifest.js +0 -0
  377. /package/web/.next/standalone/packages/web/.next/static/{EKHFeqSnbpFbCnV8AGVjm → dzgjDKuem6HLwWyK0KMG4}/_clientMiddlewareManifest.json +0 -0
  378. /package/web/.next/standalone/packages/web/.next/static/{EKHFeqSnbpFbCnV8AGVjm → dzgjDKuem6HLwWyK0KMG4}/_ssgManifest.js +0 -0
  379. /package/web/.next/static/{EKHFeqSnbpFbCnV8AGVjm → dzgjDKuem6HLwWyK0KMG4}/_buildManifest.js +0 -0
  380. /package/web/.next/static/{EKHFeqSnbpFbCnV8AGVjm → dzgjDKuem6HLwWyK0KMG4}/_clientMiddlewareManifest.json +0 -0
  381. /package/web/.next/static/{EKHFeqSnbpFbCnV8AGVjm → dzgjDKuem6HLwWyK0KMG4}/_ssgManifest.js +0 -0
@@ -31,11 +31,14 @@ import { Card, CardContent, CardHeader } from "@/components/ui/Card";
31
31
  import { ScrollArea } from "@/components/ui/ScrollArea";
32
32
  import { cn } from "@/lib/cn";
33
33
  import type {
34
+ PreviewElementSelection,
34
35
  PreviewCommandRequest,
35
36
  PreviewDomNode,
36
37
  PreviewDomResponse,
38
+ PreviewLogEntry,
37
39
  PreviewStatusResponse,
38
40
  } from "@/lib/previewTypes";
41
+ import type { TerminalInsertRequest } from "./terminalInsert";
39
42
 
40
43
  const STATUS_POLL_INTERVAL_MS = 4_000;
41
44
  const AUTO_CONNECT_RETRY_MS = 5_000;
@@ -62,7 +65,8 @@ const PREVIEW_SPECIAL_KEYS = new Map<string, string>([
62
65
 
63
66
  interface SessionPreviewProps {
64
67
  sessionId: string;
65
- projectId?: string | null;
68
+ onQueueTerminalInsert: (request: Omit<TerminalInsertRequest, "nonce">) => void;
69
+ onConnectionChange?: (connected: boolean) => void;
66
70
  }
67
71
 
68
72
  type PreviewSendTarget = "selection" | "console" | "network";
@@ -88,57 +92,106 @@ function truncate(value: string, max = 120): string {
88
92
  return `${value.slice(0, max - 1)}…`;
89
93
  }
90
94
 
91
- function pointWithinBounds(
92
- x: number,
93
- y: number,
94
- bounds: { x: number; y: number; width: number; height: number },
95
- ): boolean {
96
- return x >= bounds.x
97
- && x <= bounds.x + bounds.width
98
- && y >= bounds.y
99
- && y <= bounds.y + bounds.height;
95
+ function normalizeWhitespace(value: string | null | undefined): string {
96
+ return (value ?? "").replace(/\s+/g, " ").trim();
100
97
  }
101
98
 
102
- async function uploadPreviewAttachments(projectId: string, files: File[]): Promise<string[]> {
103
- if (!files.length) return [];
104
-
105
- const formData = new FormData();
106
- formData.append("projectId", projectId);
107
- for (const file of files) {
108
- formData.append("files", file);
109
- }
99
+ function quoteInline(value: string | null | undefined, max = 180): string | null {
100
+ const normalized = truncate(normalizeWhitespace(value), max);
101
+ if (!normalized) return null;
102
+ return `"${normalized.replace(/\\/g, "\\\\").replace(/"/g, '\\"')}"`;
103
+ }
110
104
 
111
- const response = await fetch("/api/attachments", {
112
- method: "POST",
113
- body: formData,
114
- });
105
+ function buildInlineInsert(parts: Array<string | null | undefined>): string {
106
+ return parts
107
+ .map((part) => part?.trim())
108
+ .filter((part): part is string => Boolean(part))
109
+ .join("; ");
110
+ }
115
111
 
116
- const payload = await response.json().catch(() => null) as
117
- | { error?: string; files?: Array<Record<string, unknown>> }
118
- | null;
112
+ function buildDraftInsert(title: string, lines: Array<string | null | undefined>): string {
113
+ return [
114
+ `[${title}]`,
115
+ ...lines
116
+ .map((line) => line?.trim())
117
+ .filter((line): line is string => Boolean(line)),
118
+ ].join("\n");
119
+ }
119
120
 
120
- if (!response.ok) {
121
- throw new Error(payload?.error ?? `Failed to upload preview attachments: ${response.status}`);
122
- }
121
+ function buildSelectionInsert(
122
+ selection: PreviewElementSelection,
123
+ currentUrl: string | null,
124
+ ): Omit<TerminalInsertRequest, "nonce"> {
125
+ return {
126
+ inlineText: buildInlineInsert([
127
+ "[Browser selection]",
128
+ `selector=${quoteInline(selection.selector, 220)}`,
129
+ `tag=${selection.tag}`,
130
+ selection.role ? `role=${selection.role}` : null,
131
+ selection.name ? `name=${quoteInline(selection.name, 140)}` : null,
132
+ selection.text ? `text=${quoteInline(selection.text, 180)}` : null,
133
+ selection.frameName ? `frame=${quoteInline(selection.frameName, 120)}` : null,
134
+ currentUrl ? `page=${quoteInline(currentUrl, 220)}` : null,
135
+ ]),
136
+ draftText: buildDraftInsert("Browser selection", [
137
+ currentUrl ? `Page: ${currentUrl}` : null,
138
+ `Frame: ${selection.frameName} (${selection.frameUrl})`,
139
+ `Selector: ${selection.selector}`,
140
+ `Tag: ${selection.tag}`,
141
+ selection.role ? `Role: ${selection.role}` : null,
142
+ selection.name ? `Name: ${selection.name}` : null,
143
+ selection.text ? `Text: ${selection.text}` : null,
144
+ selection.htmlPreview ? `HTML preview: ${selection.htmlPreview}` : null,
145
+ ]),
146
+ successMessage: "Queued the selected element for terminal input.",
147
+ };
148
+ }
123
149
 
124
- const fileRecords = Array.isArray(payload?.files) ? payload?.files : [];
125
- const paths = fileRecords.flatMap((record) => {
126
- const candidates = [
127
- record.absolutePath,
128
- record.path,
129
- record.filePath,
150
+ function buildLogInsert(
151
+ kind: "console" | "network",
152
+ entries: PreviewLogEntry[],
153
+ currentUrl: string | null,
154
+ selectedElement: PreviewElementSelection | null,
155
+ ): Omit<TerminalInsertRequest, "nonce"> {
156
+ const title = kind === "console" ? "Browser console logs" : "Browser network logs";
157
+ const recentEntries = entries.slice(kind === "console" ? -8 : -10);
158
+ const inlineEntries = recentEntries.map((entry) => {
159
+ const baseParts = [
160
+ entry.level,
161
+ quoteInline(entry.message, 120),
130
162
  ];
131
- return candidates.filter((candidate): candidate is string => typeof candidate === "string" && candidate.trim().length > 0);
163
+ if (kind === "network") {
164
+ baseParts.unshift(entry.method ?? "GET");
165
+ baseParts.push(typeof entry.status === "number" ? String(entry.status) : null);
166
+ baseParts.push(entry.url ? quoteInline(entry.url, 120) : null);
167
+ }
168
+ return baseParts.filter(Boolean).join(" ");
132
169
  });
133
170
 
134
- if (!paths.length) {
135
- throw new Error("Attachment upload did not return file paths");
136
- }
137
-
138
- return paths;
171
+ return {
172
+ inlineText: buildInlineInsert([
173
+ kind === "console" ? "[Browser console]" : "[Browser network]",
174
+ currentUrl ? `page=${quoteInline(currentUrl, 220)}` : null,
175
+ selectedElement ? `selected=${quoteInline(selectedElement.selector, 180)}` : null,
176
+ `entries=${quoteInline(inlineEntries.join(" | "), 520)}`,
177
+ ]),
178
+ draftText: buildDraftInsert(title, [
179
+ currentUrl ? `Page: ${currentUrl}` : null,
180
+ selectedElement ? `Selected element: ${selectedElement.selector}` : null,
181
+ ...recentEntries.map((entry) => {
182
+ if (kind === "console") {
183
+ return `- ${formatTime(entry.timestamp)} ${entry.level}: ${entry.message}`;
184
+ }
185
+ return `- ${formatTime(entry.timestamp)} ${entry.method ?? "GET"} ${entry.status ?? "-"} ${entry.url ?? entry.message}`;
186
+ }),
187
+ ]),
188
+ successMessage: kind === "console"
189
+ ? "Queued recent console logs for terminal input."
190
+ : "Queued recent network logs for terminal input.",
191
+ };
139
192
  }
140
193
 
141
- export function SessionPreview({ sessionId, projectId }: SessionPreviewProps) {
194
+ export function SessionPreview({ sessionId, onQueueTerminalInsert, onConnectionChange }: SessionPreviewProps) {
142
195
  const [status, setStatus] = useState<PreviewStatusResponse | null>(null);
143
196
  const [domNodes, setDomNodes] = useState<PreviewDomNode[]>([]);
144
197
  const [domLoading, setDomLoading] = useState(false);
@@ -152,7 +205,6 @@ export function SessionPreview({ sessionId, projectId }: SessionPreviewProps) {
152
205
  const [previewMode, setPreviewMode] = useState<PreviewInteractionMode>("navigate");
153
206
  const [selectionComposer, setSelectionComposer] = useState<SelectionComposerState | null>(null);
154
207
  const [urlInput, setUrlInput] = useState("");
155
- const [instruction, setInstruction] = useState("");
156
208
  const [imageMetrics, setImageMetrics] = useState({
157
209
  naturalWidth: 0,
158
210
  naturalHeight: 0,
@@ -163,7 +215,6 @@ export function SessionPreview({ sessionId, projectId }: SessionPreviewProps) {
163
215
  const autoConnectRef = useRef<{ candidate: string; attemptedAt: number } | null>(null);
164
216
  const previewCommandQueueRef = useRef<Promise<void>>(Promise.resolve());
165
217
  const imageRef = useRef<HTMLImageElement | null>(null);
166
- const instructionRef = useRef<HTMLTextAreaElement | null>(null);
167
218
  const previewSurfaceRef = useRef<HTMLDivElement | null>(null);
168
219
 
169
220
  const loadStatus = useCallback(async () => {
@@ -191,7 +242,7 @@ export function SessionPreview({ sessionId, projectId }: SessionPreviewProps) {
191
242
  });
192
243
  }, [sessionId, status?.currentUrl]);
193
244
 
194
- const runCommand = useCallback(async (command: PreviewCommandRequest) => {
245
+ const runCommand = useCallback(async (command: PreviewCommandRequest): Promise<PreviewStatusResponse> => {
195
246
  setBusy(true);
196
247
  setCommandError(null);
197
248
  try {
@@ -214,7 +265,9 @@ export function SessionPreview({ sessionId, projectId }: SessionPreviewProps) {
214
265
  throw new Error(payload && "error" in payload ? payload.error ?? "Preview command failed" : `Preview command failed: ${response.status}`);
215
266
  }
216
267
 
217
- setStatus(payload as PreviewStatusResponse);
268
+ const nextStatus = payload as PreviewStatusResponse;
269
+ setStatus(nextStatus);
270
+ return nextStatus;
218
271
  } finally {
219
272
  setBusy(false);
220
273
  }
@@ -324,6 +377,10 @@ export function SessionPreview({ sessionId, projectId }: SessionPreviewProps) {
324
377
  });
325
378
  }, [runCommand, status?.candidateUrls, status?.connected]);
326
379
 
380
+ useEffect(() => {
381
+ onConnectionChange?.(Boolean(status?.connected && status?.screenshotKey));
382
+ }, [onConnectionChange, status?.connected, status?.screenshotKey]);
383
+
327
384
  const screenshotUrl = useMemo(() => (
328
385
  status?.connected
329
386
  ? `/api/sessions/${encodeURIComponent(sessionId)}/preview/screenshot?ts=${encodeURIComponent(status.screenshotKey)}`
@@ -362,26 +419,6 @@ export function SessionPreview({ sessionId, projectId }: SessionPreviewProps) {
362
419
  };
363
420
  }, [imageMetrics, mainFrame, status?.selectedElement]);
364
421
 
365
- const selectedElementRenderedBounds = useMemo(() => {
366
- const bounds = status?.selectedElement?.bounds;
367
- if (!status?.selectedElement || !bounds || !mainFrame || status.selectedElement.frameId !== mainFrame.id) {
368
- return null;
369
- }
370
- if (!imageMetrics.naturalWidth || !imageMetrics.naturalHeight || !imageMetrics.renderedWidth || !imageMetrics.renderedHeight) {
371
- return null;
372
- }
373
-
374
- const scaleX = imageMetrics.renderedWidth / imageMetrics.naturalWidth;
375
- const scaleY = imageMetrics.renderedHeight / imageMetrics.naturalHeight;
376
-
377
- return {
378
- x: bounds.x * scaleX,
379
- y: bounds.y * scaleY,
380
- width: Math.max(bounds.width * scaleX, 2),
381
- height: Math.max(bounds.height * scaleY, 2),
382
- };
383
- }, [imageMetrics, mainFrame, status?.selectedElement]);
384
-
385
422
  const handleConnect = useCallback(async () => {
386
423
  const trimmed = urlInput.trim();
387
424
  if (!trimmed) return;
@@ -455,11 +492,6 @@ export function SessionPreview({ sessionId, projectId }: SessionPreviewProps) {
455
492
  };
456
493
  }, [imageMetrics.renderedHeight, imageMetrics.renderedWidth, selectionComposer]);
457
494
 
458
- useEffect(() => {
459
- if (!selectionComposer || selectionComposer.pending) return;
460
- instructionRef.current?.focus();
461
- }, [selectionComposer]);
462
-
463
495
  useEffect(() => {
464
496
  if (!selectionComposer) return;
465
497
 
@@ -475,18 +507,77 @@ export function SessionPreview({ sessionId, projectId }: SessionPreviewProps) {
475
507
  };
476
508
  }, [selectionComposer]);
477
509
 
478
- const handleImageClick = useCallback(async (event: ReactMouseEvent<HTMLImageElement>) => {
479
- if (!imageRef.current || busy) return;
510
+ const resolveImagePoint = useCallback((event: ReactMouseEvent<HTMLImageElement>) => {
511
+ if (!imageRef.current) {
512
+ return null;
513
+ }
480
514
 
481
515
  const rect = imageRef.current.getBoundingClientRect();
482
516
  if (!rect.width || !rect.height || !imageRef.current.naturalWidth || !imageRef.current.naturalHeight) {
483
- return;
517
+ return null;
484
518
  }
485
519
 
486
520
  const anchorX = event.clientX - rect.left;
487
521
  const anchorY = event.clientY - rect.top;
488
- const x = (anchorX / rect.width) * imageRef.current.naturalWidth;
489
- const y = (anchorY / rect.height) * imageRef.current.naturalHeight;
522
+ return {
523
+ anchorX,
524
+ anchorY,
525
+ x: (anchorX / rect.width) * imageRef.current.naturalWidth,
526
+ y: (anchorY / rect.height) * imageRef.current.naturalHeight,
527
+ };
528
+ }, []);
529
+
530
+ const queueContextInsert = useCallback((request: Omit<TerminalInsertRequest, "nonce">) => {
531
+ onQueueTerminalInsert(request);
532
+ setSendError(null);
533
+ setSendSuccess(request.successMessage);
534
+ }, [onQueueTerminalInsert]);
535
+
536
+ const selectElementAtPoint = useCallback(async (
537
+ x: number,
538
+ y: number,
539
+ anchorX: number,
540
+ anchorY: number,
541
+ ): Promise<PreviewStatusResponse> => {
542
+ openSelectionComposer(anchorX, anchorY, true);
543
+ try {
544
+ const nextStatus = await runCommand({ command: "selectAtPoint", x, y });
545
+ openSelectionComposer(anchorX, anchorY, false);
546
+ return nextStatus;
547
+ } catch (error) {
548
+ setSelectionComposer(null);
549
+ throw error;
550
+ }
551
+ }, [openSelectionComposer, runCommand]);
552
+
553
+ const selectDomNode = useCallback(async (
554
+ selector: string,
555
+ frameId?: string | null,
556
+ ): Promise<PreviewStatusResponse> => {
557
+ const anchorX = Math.max(imageMetrics.renderedWidth - 44, SELECTION_COMPOSER_MARGIN_PX);
558
+ const anchorY = SELECTION_COMPOSER_MARGIN_PX;
559
+ openSelectionComposer(anchorX, anchorY, true);
560
+ try {
561
+ const nextStatus = await runCommand({
562
+ command: "selectBySelector",
563
+ selector,
564
+ frameId,
565
+ });
566
+ openSelectionComposer(anchorX, anchorY, false);
567
+ return nextStatus;
568
+ } catch (error) {
569
+ setSelectionComposer(null);
570
+ throw error;
571
+ }
572
+ }, [imageMetrics.renderedWidth, openSelectionComposer, runCommand]);
573
+
574
+ const handleImageClick = useCallback(async (event: ReactMouseEvent<HTMLImageElement>) => {
575
+ if (busy) return;
576
+
577
+ const point = resolveImagePoint(event);
578
+ if (!point) {
579
+ return;
580
+ }
490
581
 
491
582
  setSelectionComposer(null);
492
583
  setSendError(null);
@@ -495,7 +586,7 @@ export function SessionPreview({ sessionId, projectId }: SessionPreviewProps) {
495
586
  if (previewMode === "navigate") {
496
587
  previewSurfaceRef.current?.focus({ preventScroll: true });
497
588
  try {
498
- await runCommand({ command: "clickAtPoint", x, y });
589
+ await runCommand({ command: "clickAtPoint", x: point.x, y: point.y });
499
590
  } catch (error) {
500
591
  setCommandError(error instanceof Error ? error.message : "Failed to interact with preview");
501
592
  }
@@ -504,30 +595,44 @@ export function SessionPreview({ sessionId, projectId }: SessionPreviewProps) {
504
595
 
505
596
  if (!canSelectByPoint) return;
506
597
 
507
- if (
508
- selectedElementRenderedBounds
509
- && !selectionComposer?.pending
510
- && pointWithinBounds(anchorX, anchorY, selectedElementRenderedBounds)
511
- ) {
512
- openSelectionComposer(anchorX, anchorY, false);
513
- return;
514
- }
515
-
516
598
  try {
517
- await runCommand({ command: "selectAtPoint", x, y });
599
+ await selectElementAtPoint(point.x, point.y, point.anchorX, point.anchorY);
518
600
  } catch (error) {
519
601
  setCommandError(error instanceof Error ? error.message : "Failed to select element");
520
602
  }
521
603
  }, [
522
604
  busy,
523
605
  canSelectByPoint,
524
- openSelectionComposer,
525
606
  previewMode,
607
+ resolveImagePoint,
526
608
  runCommand,
527
- selectedElementRenderedBounds,
528
- selectionComposer?.pending,
609
+ selectElementAtPoint,
529
610
  ]);
530
611
 
612
+ const handleImageDoubleClick = useCallback(async (event: ReactMouseEvent<HTMLImageElement>) => {
613
+ if (busy || previewMode !== "inspect" || !canSelectByPoint) {
614
+ return;
615
+ }
616
+
617
+ const point = resolveImagePoint(event);
618
+ if (!point) {
619
+ return;
620
+ }
621
+
622
+ setSendError(null);
623
+ setSendSuccess(null);
624
+
625
+ try {
626
+ const nextStatus = await selectElementAtPoint(point.x, point.y, point.anchorX, point.anchorY);
627
+ if (!nextStatus.selectedElement) {
628
+ throw new Error("No element found at the selected point");
629
+ }
630
+ queueContextInsert(buildSelectionInsert(nextStatus.selectedElement, nextStatus.currentUrl));
631
+ } catch (error) {
632
+ setCommandError(error instanceof Error ? error.message : "Failed to queue selected element");
633
+ }
634
+ }, [busy, canSelectByPoint, previewMode, queueContextInsert, resolveImagePoint, selectElementAtPoint]);
635
+
531
636
  const handlePreviewKeyDown = useCallback((event: ReactKeyboardEvent<HTMLDivElement>) => {
532
637
  if (previewMode !== "navigate" || !status?.connected) {
533
638
  return;
@@ -564,11 +669,7 @@ export function SessionPreview({ sessionId, projectId }: SessionPreviewProps) {
564
669
  queuePreviewCommand({ command: "typeText", text }, "Failed to paste into preview");
565
670
  }, [previewMode, queuePreviewCommand, status?.connected]);
566
671
 
567
- const handleSendContext = useCallback(async (target: PreviewSendTarget) => {
568
- if (!projectId) {
569
- setSendError("Preview attachments require a project-backed session.");
570
- return;
571
- }
672
+ const handleSendContext = useCallback((target: PreviewSendTarget) => {
572
673
  if (!status) {
573
674
  setSendError("Preview state is not loaded yet.");
574
675
  return;
@@ -578,7 +679,7 @@ export function SessionPreview({ sessionId, projectId }: SessionPreviewProps) {
578
679
  const recentNetworkLogs = status.networkLogs.slice(-80);
579
680
 
580
681
  if (target === "selection" && !status.selectedElement) {
581
- setSendError("Select an element before sending preview context to the agent.");
682
+ setSendError("Select an element before queueing preview context for terminal input.");
582
683
  return;
583
684
  }
584
685
 
@@ -595,115 +696,23 @@ export function SessionPreview({ sessionId, projectId }: SessionPreviewProps) {
595
696
  setSendingTarget(target);
596
697
  setSendError(null);
597
698
  setSendSuccess(null);
598
-
599
699
  try {
600
- const basePreviewPayload = {
601
- sessionId,
602
- currentUrl: status.currentUrl,
603
- activeFrameId: status.activeFrameId,
604
- selectedElement: status.selectedElement,
605
- frames: status.frames,
606
- };
607
-
608
- const payloadByTarget = {
609
- selection: {
610
- ...basePreviewPayload,
611
- recentConsoleLogs,
612
- recentNetworkLogs,
613
- },
614
- console: {
615
- ...basePreviewPayload,
616
- recentConsoleLogs,
617
- },
618
- network: {
619
- ...basePreviewPayload,
620
- recentNetworkLogs,
621
- },
622
- } satisfies Record<PreviewSendTarget, Record<string, unknown>>;
623
-
624
- const jsonPayload = {
625
- generatedAt: new Date().toISOString(),
626
- target,
627
- preview: payloadByTarget[target],
628
- };
629
-
630
- const files: File[] = [
631
- new File(
632
- [JSON.stringify(jsonPayload, null, 2)],
633
- `${sessionId}-preview-${target}.json`,
634
- { type: "application/json" },
635
- ),
636
- ];
637
-
638
- if (screenshotUrl) {
639
- const screenshotResponse = await fetch(screenshotUrl, { cache: "no-store" });
640
- if (screenshotResponse.ok) {
641
- const screenshotBlob = await screenshotResponse.blob();
642
- files.push(new File([screenshotBlob], `${sessionId}-preview-${target}.png`, { type: "image/png" }));
643
- }
644
- }
645
-
646
- const attachmentPaths = await uploadPreviewAttachments(projectId, files);
647
- const messageByTarget = {
648
- selection: [
649
- "Use the attached preview context JSON and screenshot to update the UI.",
650
- `Selected element selector: ${status.selectedElement?.selector ?? "n/a"}`,
651
- `Selected frame: ${status.selectedElement?.frameName ?? "n/a"} (${status.selectedElement?.frameUrl ?? "n/a"})`,
652
- instruction.trim() || "Apply the requested UI change to the selected element and surrounding layout as needed.",
653
- ],
654
- console: [
655
- "Use the attached preview console logs and screenshot to debug the current page state.",
656
- `Preview URL: ${status.currentUrl ?? "unavailable"}`,
657
- status.selectedElement ? `Current selected element: ${status.selectedElement.selector}` : null,
658
- instruction.trim() || "Investigate the console output, identify the root cause, and apply the needed fix.",
659
- ],
660
- network: [
661
- "Use the attached preview network logs and screenshot to debug failed or unexpected requests.",
662
- `Preview URL: ${status.currentUrl ?? "unavailable"}`,
663
- status.selectedElement ? `Current selected element: ${status.selectedElement.selector}` : null,
664
- instruction.trim() || "Investigate the network activity, identify the failing request or sequencing issue, and apply the needed fix.",
665
- ],
666
- } satisfies Record<PreviewSendTarget, Array<string | null>>;
667
-
668
- const successMessageByTarget = {
669
- selection: "Preview context sent to the session agent.",
670
- console: "Console logs sent to the session agent.",
671
- network: "Network logs sent to the session agent.",
672
- } satisfies Record<PreviewSendTarget, string>;
673
-
674
- const elementSummary = messageByTarget[target].filter((line): line is string => Boolean(line)).join("\n");
675
-
676
- const response = await fetch(`/api/sessions/${encodeURIComponent(sessionId)}/send`, {
677
- method: "POST",
678
- headers: {
679
- "Content-Type": "application/json",
680
- },
681
- body: JSON.stringify({
682
- message: elementSummary,
683
- attachments: attachmentPaths,
684
- }),
685
- });
686
-
687
- const payload = await response.json().catch(() => null) as { error?: string } | null;
688
- if (!response.ok) {
689
- throw new Error(payload?.error ?? `Failed to send preview context: ${response.status}`);
690
- }
691
-
692
- setInstruction("");
700
+ const request = target === "selection" && status.selectedElement
701
+ ? buildSelectionInsert(status.selectedElement, status.currentUrl)
702
+ : target === "console"
703
+ ? buildLogInsert("console", recentConsoleLogs, status.currentUrl, status.selectedElement)
704
+ : buildLogInsert("network", recentNetworkLogs, status.currentUrl, status.selectedElement);
705
+ queueContextInsert(request);
693
706
  if (target === "selection") {
694
707
  setSelectionComposer(null);
695
708
  }
696
- setSendSuccess(successMessageByTarget[target]);
697
709
  } catch (error) {
698
- setSendError(error instanceof Error ? error.message : "Failed to send preview context");
710
+ setSendError(error instanceof Error ? error.message : "Failed to queue preview context");
699
711
  } finally {
700
712
  setSendingTarget(null);
701
713
  }
702
714
  }, [
703
- instruction,
704
- projectId,
705
- screenshotUrl,
706
- sessionId,
715
+ queueContextInsert,
707
716
  status,
708
717
  ]);
709
718
 
@@ -842,7 +851,7 @@ export function SessionPreview({ sessionId, projectId }: SessionPreviewProps) {
842
851
  {previewMode === "navigate"
843
852
  ? "navigate mode: clicks interact with the page"
844
853
  : canSelectByPoint
845
- ? "inspect mode: click once to select, again to message"
854
+ ? "inspect mode: click once to select, double-click to queue for terminal input"
846
855
  : "inspect mode: use DOM list for this frame"}
847
856
  </Badge>
848
857
  </div>
@@ -876,6 +885,7 @@ export function SessionPreview({ sessionId, projectId }: SessionPreviewProps) {
876
885
  : "cursor-default",
877
886
  )}
878
887
  onClick={(event) => void handleImageClick(event)}
888
+ onDoubleClick={(event) => void handleImageDoubleClick(event)}
879
889
  onLoad={(event) => {
880
890
  const target = event.currentTarget;
881
891
  setImageMetrics({
@@ -899,9 +909,9 @@ export function SessionPreview({ sessionId, projectId }: SessionPreviewProps) {
899
909
  >
900
910
  <div className="flex items-start justify-between gap-3 border-b border-[var(--vk-border)] px-3 py-3">
901
911
  <div className="min-w-0">
902
- <div className="text-[10px] uppercase tracking-[0.16em] text-[var(--vk-text-muted)]">Current chat</div>
912
+ <div className="text-[10px] uppercase tracking-[0.16em] text-[var(--vk-text-muted)]">Terminal input</div>
903
913
  <div className="mt-1 text-[13px] font-medium text-[var(--vk-text-normal)]">
904
- {selectionComposer.pending ? "Selecting element…" : "Send to current agent"}
914
+ {selectionComposer.pending ? "Selecting element…" : "Queue selection for the terminal"}
905
915
  </div>
906
916
  </div>
907
917
  <div className="flex items-center gap-1">
@@ -944,17 +954,8 @@ export function SessionPreview({ sessionId, projectId }: SessionPreviewProps) {
944
954
  {status.selectedElement.selector}
945
955
  </div>
946
956
  </div>
947
- <div className="space-y-2">
948
- <label className="text-[11px] uppercase tracking-[0.14em] text-[var(--vk-text-muted)]">
949
- Instruction
950
- </label>
951
- <textarea
952
- ref={instructionRef}
953
- value={instruction}
954
- onChange={(event) => setInstruction(event.target.value)}
955
- placeholder="Describe the change and send it straight to this agent session…"
956
- className="min-h-[108px] w-full rounded-[6px] border border-[var(--vk-border)] bg-[var(--vk-bg-main)] px-3 py-2 text-[13px] text-[var(--vk-text-normal)] outline-none focus:border-[var(--vk-orange)]"
957
- />
957
+ <div className="rounded-[6px] border border-dashed border-[var(--vk-border)] px-3 py-2 text-[12px] text-[var(--vk-text-muted)]">
958
+ Double-click the element in the preview to queue it immediately, or use the button below. The text is inserted into terminal input instead of being sent to the agent, so you can add more context before submitting.
958
959
  </div>
959
960
  {sendError ? (
960
961
  <div className="text-[12px] text-[var(--vk-red)]">{sendError}</div>
@@ -967,12 +968,12 @@ export function SessionPreview({ sessionId, projectId }: SessionPreviewProps) {
967
968
  disabled={sending || !status.selectedElement}
968
969
  >
969
970
  {sendingTarget === "selection" ? <Loader2 className="h-4 w-4 animate-spin" /> : <Send className="h-4 w-4" />}
970
- Send to current agent
971
+ Queue for terminal input
971
972
  </Button>
972
973
  </>
973
974
  ) : (
974
975
  <div className="rounded-[6px] border border-dashed border-[var(--vk-border)] px-3 py-3 text-[12px] text-[var(--vk-text-muted)]">
975
- Click the current selection again to open the composer and send it into the current session chat.
976
+ Single-click an element to inspect it here. Double-click to queue it for terminal input.
976
977
  </div>
977
978
  )}
978
979
  </div>
@@ -981,7 +982,7 @@ export function SessionPreview({ sessionId, projectId }: SessionPreviewProps) {
981
982
  </div>
982
983
  ) : (
983
984
  <div className="max-w-md text-center text-[13px] text-[var(--vk-text-muted)]">
984
- Connect a local dev URL to start the preview browser. In Navigate mode, click the preview first, then type directly into the running app. Switch to Inspect mode to select an element and send it to the current agent.
985
+ Connect a local dev URL to start the preview browser. In Navigate mode, click the preview first, then type directly into the running app. Switch to Inspect mode to select UI elements and queue browser context into terminal input.
985
986
  </div>
986
987
  )}
987
988
  </div>
@@ -1050,7 +1051,7 @@ export function SessionPreview({ sessionId, projectId }: SessionPreviewProps) {
1050
1051
  <div className="space-y-1 p-2">
1051
1052
  {previewMode === "navigate" ? (
1052
1053
  <div className="rounded-[4px] border border-dashed border-[var(--vk-border)] px-2 py-2 text-[11px] text-[var(--vk-text-muted)]">
1053
- Switch to Inspect mode to pick DOM nodes or send selected UI context to the current agent.
1054
+ Switch to Inspect mode to pick DOM nodes. Single-click selects a node. Double-click queues it for terminal input.
1054
1055
  </div>
1055
1056
  ) : null}
1056
1057
  {domLoading ? (
@@ -1071,31 +1072,28 @@ export function SessionPreview({ sessionId, projectId }: SessionPreviewProps) {
1071
1072
  )}
1072
1073
  disabled={previewMode !== "inspect"}
1073
1074
  onClick={() => {
1074
- if (
1075
- status?.selectedElement
1076
- && status.selectedElement.selector === node.selector
1077
- && status.selectedElement.frameId === status.activeFrameId
1078
- ) {
1079
- openSelectionComposer(
1080
- Math.max(imageMetrics.renderedWidth - 44, SELECTION_COMPOSER_MARGIN_PX),
1081
- SELECTION_COMPOSER_MARGIN_PX,
1082
- false,
1083
- );
1084
- return;
1085
- }
1086
-
1087
1075
  setSelectionComposer(null);
1088
1076
  setSendError(null);
1089
1077
  setSendSuccess(null);
1090
- void runCommand({
1091
- command: "selectBySelector",
1092
- selector: node.selector,
1093
- frameId: status?.activeFrameId,
1094
- })
1078
+ void selectDomNode(node.selector, status?.activeFrameId)
1095
1079
  .catch((error: unknown) => {
1096
1080
  setCommandError(error instanceof Error ? error.message : "Failed to select DOM node");
1097
1081
  });
1098
1082
  }}
1083
+ onDoubleClick={() => {
1084
+ setSendError(null);
1085
+ setSendSuccess(null);
1086
+ void selectDomNode(node.selector, status?.activeFrameId)
1087
+ .then((nextStatus) => {
1088
+ if (!nextStatus.selectedElement) {
1089
+ throw new Error("Failed to resolve the selected DOM node");
1090
+ }
1091
+ queueContextInsert(buildSelectionInsert(nextStatus.selectedElement, nextStatus.currentUrl));
1092
+ })
1093
+ .catch((error: unknown) => {
1094
+ setCommandError(error instanceof Error ? error.message : "Failed to queue DOM node");
1095
+ });
1096
+ }}
1099
1097
  >
1100
1098
  <div className="flex items-center gap-2">
1101
1099
  <span className="font-mono text-[12px] text-[var(--vk-text-normal)]">{node.tag}</span>
@@ -1139,7 +1137,7 @@ export function SessionPreview({ sessionId, projectId }: SessionPreviewProps) {
1139
1137
  disabled={sending || !status?.consoleLogs.length}
1140
1138
  >
1141
1139
  {sendingTarget === "console" ? <Loader2 className="h-3.5 w-3.5 animate-spin" /> : <Send className="h-3.5 w-3.5" />}
1142
- Send to agent
1140
+ Queue for terminal
1143
1141
  </Button>
1144
1142
  </CardHeader>
1145
1143
  <CardContent>
@@ -1183,7 +1181,7 @@ export function SessionPreview({ sessionId, projectId }: SessionPreviewProps) {
1183
1181
  disabled={sending || !status?.networkLogs.length}
1184
1182
  >
1185
1183
  {sendingTarget === "network" ? <Loader2 className="h-3.5 w-3.5 animate-spin" /> : <Send className="h-3.5 w-3.5" />}
1186
- Send to agent
1184
+ Queue for terminal
1187
1185
  </Button>
1188
1186
  </CardHeader>
1189
1187
  <CardContent>