sparkecoder 0.1.97 → 0.1.99

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 (363) hide show
  1. package/dist/agent/index.d.ts +3 -3
  2. package/dist/agent/index.js +1258 -59
  3. package/dist/agent/index.js.map +1 -1
  4. package/dist/cli.js +10657 -8949
  5. package/dist/cli.js.map +1 -1
  6. package/dist/db/index.d.ts +2 -2
  7. package/dist/{index-BvIissiB.d.ts → index-D5l-DMGC.d.ts} +390 -6
  8. package/dist/index.d.ts +5 -5
  9. package/dist/index.js +9985 -8069
  10. package/dist/index.js.map +1 -1
  11. package/dist/{schema-CohdIL13.d.ts → schema-ecQSnCMz.d.ts} +41 -0
  12. package/dist/server/index.js +8615 -6707
  13. package/dist/server/index.js.map +1 -1
  14. package/dist/skills/default/manage-mcp.md +94 -0
  15. package/dist/skills/default/search-conversations.md +100 -0
  16. package/dist/tools/index.d.ts +2 -2
  17. package/dist/tools/index.js +111 -2
  18. package/dist/tools/index.js.map +1 -1
  19. package/package.json +5 -1
  20. package/src/skills/default/manage-mcp.md +94 -0
  21. package/src/skills/default/search-conversations.md +100 -0
  22. package/web/.next/BUILD_ID +1 -1
  23. package/web/.next/standalone/web/.next/BUILD_ID +1 -1
  24. package/web/.next/standalone/web/.next/app-path-routes-manifest.json +2 -1
  25. package/web/.next/standalone/web/.next/build-manifest.json +5 -5
  26. package/web/.next/standalone/web/.next/prerender-manifest.json +51 -3
  27. package/web/.next/standalone/web/.next/routes-manifest.json +13 -24
  28. package/web/.next/standalone/web/.next/server/app/(main)/agents/page/app-paths-manifest.json +3 -0
  29. package/web/.next/standalone/web/.next/server/app/{embed/[id] → (main)/agents}/page/build-manifest.json +3 -3
  30. package/web/.next/standalone/web/.next/server/app/(main)/agents/page/next-font-manifest.json +11 -0
  31. package/web/.next/standalone/web/.next/server/app/{embed/[id] → (main)/agents}/page.js +7 -6
  32. package/web/.next/standalone/web/.next/server/app/(main)/agents/page.js.nft.json +1 -0
  33. package/web/.next/standalone/web/.next/server/app/(main)/agents/page_client-reference-manifest.js +2 -0
  34. package/web/.next/standalone/web/.next/server/app/(main)/page/build-manifest.json +3 -3
  35. package/web/.next/standalone/web/.next/server/app/(main)/page/next-font-manifest.json +2 -2
  36. package/web/.next/standalone/web/.next/server/app/(main)/page.js.nft.json +1 -1
  37. package/web/.next/standalone/web/.next/server/app/(main)/page_client-reference-manifest.js +1 -1
  38. package/web/.next/standalone/web/.next/server/app/(main)/session/[id]/page/build-manifest.json +3 -3
  39. package/web/.next/standalone/web/.next/server/app/(main)/session/[id]/page/next-font-manifest.json +2 -2
  40. package/web/.next/standalone/web/.next/server/app/(main)/session/[id]/page.js.nft.json +1 -1
  41. package/web/.next/standalone/web/.next/server/app/(main)/session/[id]/page_client-reference-manifest.js +1 -1
  42. package/web/.next/standalone/web/.next/server/app/(main)/settings/page/app-paths-manifest.json +3 -0
  43. package/web/.next/standalone/web/.next/server/app/(main)/settings/page/build-manifest.json +18 -0
  44. package/web/.next/standalone/web/.next/server/app/(main)/settings/page/next-font-manifest.json +11 -0
  45. package/web/.next/standalone/web/.next/server/app/(main)/settings/page/react-loadable-manifest.json +1 -0
  46. package/web/.next/standalone/web/.next/server/app/(main)/settings/page/server-reference-manifest.json +4 -0
  47. package/web/.next/standalone/web/.next/server/app/(main)/settings/page.js +21 -0
  48. package/web/.next/standalone/web/.next/server/app/(main)/settings/page.js.map +5 -0
  49. package/web/.next/standalone/web/.next/server/app/(main)/settings/page.js.nft.json +1 -0
  50. package/web/.next/standalone/web/.next/server/app/(main)/settings/page_client-reference-manifest.js +2 -0
  51. package/web/.next/standalone/web/.next/server/app/_global-error/page/build-manifest.json +3 -3
  52. package/web/.next/standalone/web/.next/server/app/_global-error.html +2 -2
  53. package/web/.next/standalone/web/.next/server/app/_global-error.rsc +1 -1
  54. package/web/.next/standalone/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  55. package/web/.next/standalone/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  56. package/web/.next/standalone/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  57. package/web/.next/standalone/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  58. package/web/.next/standalone/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  59. package/web/.next/standalone/web/.next/server/app/_not-found/page/build-manifest.json +3 -3
  60. package/web/.next/standalone/web/.next/server/app/_not-found/page/next-font-manifest.json +2 -2
  61. package/web/.next/standalone/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  62. package/web/.next/standalone/web/.next/server/app/_not-found.html +1 -1
  63. package/web/.next/standalone/web/.next/server/app/_not-found.rsc +3 -3
  64. package/web/.next/standalone/web/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
  65. package/web/.next/standalone/web/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  66. package/web/.next/standalone/web/.next/server/app/_not-found.segments/_index.segment.rsc +3 -3
  67. package/web/.next/standalone/web/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  68. package/web/.next/standalone/web/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  69. package/web/.next/standalone/web/.next/server/app/_not-found.segments/_tree.segment.rsc +3 -3
  70. package/web/.next/standalone/web/.next/server/app/agents.html +1 -0
  71. package/web/.next/standalone/web/.next/server/app/agents.meta +16 -0
  72. package/web/.next/standalone/web/.next/server/app/agents.rsc +25 -0
  73. package/web/.next/standalone/web/.next/server/app/agents.segments/!KG1haW4p/agents/__PAGE__.segment.rsc +9 -0
  74. package/web/.next/standalone/web/.next/server/app/agents.segments/!KG1haW4p/agents.segment.rsc +4 -0
  75. package/web/.next/standalone/web/.next/server/app/agents.segments/!KG1haW4p.segment.rsc +7 -0
  76. package/web/.next/standalone/web/.next/server/app/agents.segments/_full.segment.rsc +25 -0
  77. package/web/.next/standalone/web/.next/server/app/agents.segments/_head.segment.rsc +6 -0
  78. package/web/.next/standalone/web/.next/server/app/agents.segments/_index.segment.rsc +7 -0
  79. package/web/.next/standalone/web/.next/server/app/agents.segments/_tree.segment.rsc +5 -0
  80. package/web/.next/standalone/web/.next/server/app/api/config/route.js.nft.json +1 -1
  81. package/web/.next/standalone/web/.next/server/app/api/health/route.js.nft.json +1 -1
  82. package/web/.next/standalone/web/.next/server/app/docs/installation/page/build-manifest.json +3 -3
  83. package/web/.next/standalone/web/.next/server/app/docs/installation/page/next-font-manifest.json +2 -2
  84. package/web/.next/standalone/web/.next/server/app/docs/installation/page_client-reference-manifest.js +1 -1
  85. package/web/.next/standalone/web/.next/server/app/docs/installation.html +2 -2
  86. package/web/.next/standalone/web/.next/server/app/docs/installation.rsc +3 -3
  87. package/web/.next/standalone/web/.next/server/app/docs/installation.segments/_full.segment.rsc +3 -3
  88. package/web/.next/standalone/web/.next/server/app/docs/installation.segments/_head.segment.rsc +1 -1
  89. package/web/.next/standalone/web/.next/server/app/docs/installation.segments/_index.segment.rsc +3 -3
  90. package/web/.next/standalone/web/.next/server/app/docs/installation.segments/_tree.segment.rsc +3 -3
  91. package/web/.next/standalone/web/.next/server/app/docs/installation.segments/docs/installation/__PAGE__.segment.rsc +1 -1
  92. package/web/.next/standalone/web/.next/server/app/docs/installation.segments/docs/installation.segment.rsc +1 -1
  93. package/web/.next/standalone/web/.next/server/app/docs/installation.segments/docs.segment.rsc +1 -1
  94. package/web/.next/standalone/web/.next/server/app/docs/page/build-manifest.json +3 -3
  95. package/web/.next/standalone/web/.next/server/app/docs/page/next-font-manifest.json +2 -2
  96. package/web/.next/standalone/web/.next/server/app/docs/page_client-reference-manifest.js +1 -1
  97. package/web/.next/standalone/web/.next/server/app/docs/skills/page/build-manifest.json +3 -3
  98. package/web/.next/standalone/web/.next/server/app/docs/skills/page/next-font-manifest.json +2 -2
  99. package/web/.next/standalone/web/.next/server/app/docs/skills/page_client-reference-manifest.js +1 -1
  100. package/web/.next/standalone/web/.next/server/app/docs/skills.html +2 -2
  101. package/web/.next/standalone/web/.next/server/app/docs/skills.rsc +3 -3
  102. package/web/.next/standalone/web/.next/server/app/docs/skills.segments/_full.segment.rsc +3 -3
  103. package/web/.next/standalone/web/.next/server/app/docs/skills.segments/_head.segment.rsc +1 -1
  104. package/web/.next/standalone/web/.next/server/app/docs/skills.segments/_index.segment.rsc +3 -3
  105. package/web/.next/standalone/web/.next/server/app/docs/skills.segments/_tree.segment.rsc +3 -3
  106. package/web/.next/standalone/web/.next/server/app/docs/skills.segments/docs/skills/__PAGE__.segment.rsc +1 -1
  107. package/web/.next/standalone/web/.next/server/app/docs/skills.segments/docs/skills.segment.rsc +1 -1
  108. package/web/.next/standalone/web/.next/server/app/docs/skills.segments/docs.segment.rsc +1 -1
  109. package/web/.next/standalone/web/.next/server/app/docs/tools/page/build-manifest.json +3 -3
  110. package/web/.next/standalone/web/.next/server/app/docs/tools/page/next-font-manifest.json +2 -2
  111. package/web/.next/standalone/web/.next/server/app/docs/tools/page_client-reference-manifest.js +1 -1
  112. package/web/.next/standalone/web/.next/server/app/docs/tools.html +2 -2
  113. package/web/.next/standalone/web/.next/server/app/docs/tools.rsc +3 -3
  114. package/web/.next/standalone/web/.next/server/app/docs/tools.segments/_full.segment.rsc +3 -3
  115. package/web/.next/standalone/web/.next/server/app/docs/tools.segments/_head.segment.rsc +1 -1
  116. package/web/.next/standalone/web/.next/server/app/docs/tools.segments/_index.segment.rsc +3 -3
  117. package/web/.next/standalone/web/.next/server/app/docs/tools.segments/_tree.segment.rsc +3 -3
  118. package/web/.next/standalone/web/.next/server/app/docs/tools.segments/docs/tools/__PAGE__.segment.rsc +1 -1
  119. package/web/.next/standalone/web/.next/server/app/docs/tools.segments/docs/tools.segment.rsc +1 -1
  120. package/web/.next/standalone/web/.next/server/app/docs/tools.segments/docs.segment.rsc +1 -1
  121. package/web/.next/standalone/web/.next/server/app/docs.html +2 -2
  122. package/web/.next/standalone/web/.next/server/app/docs.rsc +3 -3
  123. package/web/.next/standalone/web/.next/server/app/docs.segments/_full.segment.rsc +3 -3
  124. package/web/.next/standalone/web/.next/server/app/docs.segments/_head.segment.rsc +1 -1
  125. package/web/.next/standalone/web/.next/server/app/docs.segments/_index.segment.rsc +3 -3
  126. package/web/.next/standalone/web/.next/server/app/docs.segments/_tree.segment.rsc +3 -3
  127. package/web/.next/standalone/web/.next/server/app/docs.segments/docs/__PAGE__.segment.rsc +1 -1
  128. package/web/.next/standalone/web/.next/server/app/docs.segments/docs.segment.rsc +1 -1
  129. package/web/.next/standalone/web/.next/server/app/index.html +1 -1
  130. package/web/.next/standalone/web/.next/server/app/index.rsc +7 -7
  131. package/web/.next/standalone/web/.next/server/app/index.segments/!KG1haW4p/__PAGE__.segment.rsc +2 -2
  132. package/web/.next/standalone/web/.next/server/app/index.segments/!KG1haW4p.segment.rsc +2 -2
  133. package/web/.next/standalone/web/.next/server/app/index.segments/_full.segment.rsc +7 -7
  134. package/web/.next/standalone/web/.next/server/app/index.segments/_head.segment.rsc +1 -1
  135. package/web/.next/standalone/web/.next/server/app/index.segments/_index.segment.rsc +3 -3
  136. package/web/.next/standalone/web/.next/server/app/index.segments/_tree.segment.rsc +5 -5
  137. package/web/.next/standalone/web/.next/server/app/settings.html +1 -0
  138. package/web/.next/standalone/web/.next/server/app/settings.meta +16 -0
  139. package/web/.next/standalone/web/.next/server/app/settings.rsc +25 -0
  140. package/web/.next/standalone/web/.next/server/app/settings.segments/!KG1haW4p/settings/__PAGE__.segment.rsc +9 -0
  141. package/web/.next/standalone/web/.next/server/app/settings.segments/!KG1haW4p/settings.segment.rsc +4 -0
  142. package/web/.next/standalone/web/.next/server/app/settings.segments/!KG1haW4p.segment.rsc +7 -0
  143. package/web/.next/standalone/web/.next/server/app/settings.segments/_full.segment.rsc +25 -0
  144. package/web/.next/standalone/web/.next/server/app/settings.segments/_head.segment.rsc +6 -0
  145. package/web/.next/standalone/web/.next/server/app/settings.segments/_index.segment.rsc +7 -0
  146. package/web/.next/standalone/web/.next/server/app/settings.segments/_tree.segment.rsc +5 -0
  147. package/web/.next/standalone/web/.next/server/app-paths-manifest.json +2 -1
  148. package/web/.next/standalone/web/.next/server/chunks/ssr/{2374f_60d8842c._.js → 2374f_3b04c7b5._.js} +1 -1
  149. package/web/.next/standalone/web/.next/server/chunks/ssr/{2374f_2801b766._.js → 2374f_5ee1ee50._.js} +1 -1
  150. package/web/.next/standalone/web/.next/server/chunks/ssr/{2374f_c13c8f4f._.js → 2374f_7b7dd4c7._.js} +1 -1
  151. package/web/.next/standalone/web/.next/server/chunks/ssr/{2374f_b7f45fdf._.js → 2374f_9e444fb0._.js} +1 -1
  152. package/web/.next/standalone/web/.next/server/chunks/ssr/{2374f_a383a4d9._.js → 2374f_b57914d2._.js} +1 -1
  153. package/web/.next/standalone/web/.next/server/chunks/ssr/2374f_c2c47039._.js +3 -0
  154. package/web/.next/standalone/web/.next/server/chunks/ssr/{2374f_806bd012._.js → 2374f_db1d6704._.js} +1 -1
  155. package/web/.next/standalone/web/.next/server/chunks/ssr/{2374f_f363c084._.js → 2374f_e6dbbf5d._.js} +1 -1
  156. package/web/.next/standalone/web/.next/server/chunks/ssr/2374f_lucide-react_dist_esm_icons_50c2f239._.js +3 -0
  157. package/web/.next/standalone/web/.next/server/chunks/ssr/[root-of-the-server]__2ea52390._.js +3 -0
  158. package/web/.next/standalone/web/.next/server/chunks/ssr/[root-of-the-server]__6097da17._.js +15 -0
  159. package/web/.next/standalone/web/.next/server/chunks/ssr/[root-of-the-server]__9f149e88._.js +3 -0
  160. package/web/.next/standalone/web/.next/server/chunks/ssr/[root-of-the-server]__b050bb8f._.js +1 -1
  161. package/web/.next/standalone/web/.next/server/chunks/ssr/[root-of-the-server]__c94db61a._.js +3 -0
  162. package/web/.next/standalone/web/.next/server/chunks/ssr/web_4fe3c244._.js +3 -0
  163. package/web/.next/standalone/web/.next/server/chunks/ssr/{web_3c2b112b._.js → web_7ca56356._.js} +3 -3
  164. package/web/.next/standalone/web/.next/server/chunks/ssr/web_8e76ee8b._.js +8 -0
  165. package/web/.next/standalone/web/.next/server/chunks/ssr/web_90d4125e._.js +7 -0
  166. package/web/.next/standalone/web/.next/server/chunks/ssr/web__next-internal_server_app_(main)_agents_page_actions_30f6e448.js +3 -0
  167. package/web/.next/standalone/web/.next/server/chunks/ssr/web__next-internal_server_app_(main)_settings_page_actions_7285839d.js +3 -0
  168. package/web/.next/standalone/web/.next/server/chunks/ssr/web_b38a47ee._.js +4 -0
  169. package/web/.next/standalone/web/.next/server/chunks/ssr/web_f7cf6b63._.js +3 -0
  170. package/web/.next/standalone/web/.next/server/chunks/ssr/web_src_app_(main)_layout_tsx_453f6492._.js +3 -0
  171. package/web/.next/standalone/web/.next/server/chunks/ssr/web_src_app_(main)_page_tsx_5ac4794b._.js +1 -1
  172. package/web/.next/standalone/web/.next/server/chunks/ssr/web_src_app_(main)_settings_page_tsx_eb320e07._.js +33 -0
  173. package/web/.next/standalone/web/.next/server/middleware-build-manifest.js +3 -3
  174. package/web/.next/standalone/web/.next/server/next-font-manifest.js +1 -1
  175. package/web/.next/standalone/web/.next/server/next-font-manifest.json +22 -18
  176. package/web/.next/standalone/web/.next/server/pages/404.html +1 -1
  177. package/web/.next/standalone/web/.next/server/pages/500.html +2 -2
  178. package/web/.next/standalone/web/.next/server/server-reference-manifest.js +1 -1
  179. package/web/.next/standalone/web/.next/server/server-reference-manifest.json +1 -1
  180. package/web/.next/standalone/web/.next/static/chunks/03b5edce6d5b809e.js +1 -0
  181. package/web/.next/standalone/web/.next/static/chunks/29dcecc3c2ca92b0.js +1 -0
  182. package/web/.next/standalone/web/.next/static/chunks/344be859c2c8600b.css +1 -0
  183. package/web/.next/standalone/web/.next/static/chunks/545725e4c1237026.js +7 -0
  184. package/web/.next/standalone/web/.next/static/chunks/60359bdd369c0c72.js +1 -0
  185. package/web/.next/standalone/web/.next/static/chunks/699803c4fb2dd3fc.js +5 -0
  186. package/web/.next/standalone/web/.next/static/chunks/735a2408c315b2f0.js +1 -0
  187. package/web/.next/standalone/web/.next/static/chunks/a7d5d0791c8c6223.css +2 -0
  188. package/web/.next/standalone/web/.next/static/chunks/d54077a2bb8314ed.js +31 -0
  189. package/web/.next/standalone/web/.next/static/chunks/dc34aa94e57fa28e.js +3 -0
  190. package/web/.next/standalone/web/.next/static/chunks/ea89ca7892d8c557.js +1 -0
  191. package/web/.next/standalone/web/.next/static/chunks/f0f19357f3fb7cf8.js +1 -0
  192. package/web/.next/standalone/web/.next/static/chunks/f50a66c24c564585.js +13 -0
  193. package/web/.next/standalone/web/.next/static/chunks/f5fe518b79d1bf41.js +1 -0
  194. package/web/.next/standalone/web/.next/static/{static/chunks/turbopack-597558bb7b6982f6.js → chunks/turbopack-2c0905c7bbebae3f.js} +1 -1
  195. package/web/.next/standalone/web/.next/static/media/4fa387ec64143e14-s.c36e1862.woff2 +0 -0
  196. package/web/.next/standalone/web/.next/static/media/53b9e256198e5412-s.853d50a3.woff2 +0 -0
  197. package/web/.next/standalone/web/.next/static/media/5ce348bf30bf5439-s.ebceb24d.woff2 +0 -0
  198. package/web/.next/standalone/web/.next/static/media/6306c77e7c8268e4-s.ff4a2084.woff2 +0 -0
  199. package/web/.next/standalone/web/.next/static/media/7178b3e590c64307-s.55554cd0.woff2 +0 -0
  200. package/web/.next/standalone/web/.next/static/media/797e433ab948586e-s.p.479bea2b.woff2 +0 -0
  201. package/web/.next/standalone/web/.next/static/media/7d817b4c03b0c5f1-s.f377b9c4.woff2 +0 -0
  202. package/web/.next/standalone/web/.next/static/media/8a480f0b521d4e75-s.ea323500.woff2 +0 -0
  203. package/web/.next/standalone/web/.next/static/media/bbc41e54d2fcbd21-s.d1207556.woff2 +0 -0
  204. package/web/.next/standalone/web/.next/static/media/caa3a2e1cccd8315-s.p.3b6cae6d.woff2 +0 -0
  205. package/web/.next/standalone/web/.next/static/media/fef07dbb0973bf53-s.518e079e.woff2 +0 -0
  206. package/web/.next/standalone/web/.next/static/static/chunks/03b5edce6d5b809e.js +1 -0
  207. package/web/.next/standalone/web/.next/static/static/chunks/29dcecc3c2ca92b0.js +1 -0
  208. package/web/.next/standalone/web/.next/static/static/chunks/344be859c2c8600b.css +1 -0
  209. package/web/.next/standalone/web/.next/static/static/chunks/545725e4c1237026.js +7 -0
  210. package/web/.next/standalone/web/.next/static/static/chunks/60359bdd369c0c72.js +1 -0
  211. package/web/.next/standalone/web/.next/static/static/chunks/699803c4fb2dd3fc.js +5 -0
  212. package/web/.next/standalone/web/.next/static/static/chunks/735a2408c315b2f0.js +1 -0
  213. package/web/.next/standalone/web/.next/static/static/chunks/a7d5d0791c8c6223.css +2 -0
  214. package/web/.next/standalone/web/.next/static/static/chunks/d54077a2bb8314ed.js +31 -0
  215. package/web/.next/standalone/web/.next/static/static/chunks/dc34aa94e57fa28e.js +3 -0
  216. package/web/.next/standalone/web/.next/static/static/chunks/ea89ca7892d8c557.js +1 -0
  217. package/web/.next/standalone/web/.next/static/static/chunks/f0f19357f3fb7cf8.js +1 -0
  218. package/web/.next/standalone/web/.next/static/static/chunks/f50a66c24c564585.js +13 -0
  219. package/web/.next/standalone/web/.next/static/static/chunks/f5fe518b79d1bf41.js +1 -0
  220. package/web/.next/standalone/web/.next/static/{chunks/turbopack-597558bb7b6982f6.js → static/chunks/turbopack-2c0905c7bbebae3f.js} +1 -1
  221. package/web/.next/standalone/web/.next/static/static/media/4fa387ec64143e14-s.c36e1862.woff2 +0 -0
  222. package/web/.next/standalone/web/.next/static/static/media/53b9e256198e5412-s.853d50a3.woff2 +0 -0
  223. package/web/.next/standalone/web/.next/static/static/media/5ce348bf30bf5439-s.ebceb24d.woff2 +0 -0
  224. package/web/.next/standalone/web/.next/static/static/media/6306c77e7c8268e4-s.ff4a2084.woff2 +0 -0
  225. package/web/.next/standalone/web/.next/static/static/media/7178b3e590c64307-s.55554cd0.woff2 +0 -0
  226. package/web/.next/standalone/web/.next/static/static/media/797e433ab948586e-s.p.479bea2b.woff2 +0 -0
  227. package/web/.next/standalone/web/.next/static/static/media/7d817b4c03b0c5f1-s.f377b9c4.woff2 +0 -0
  228. package/web/.next/standalone/web/.next/static/static/media/8a480f0b521d4e75-s.ea323500.woff2 +0 -0
  229. package/web/.next/standalone/web/.next/static/static/media/bbc41e54d2fcbd21-s.d1207556.woff2 +0 -0
  230. package/web/.next/standalone/web/.next/static/static/media/caa3a2e1cccd8315-s.p.3b6cae6d.woff2 +0 -0
  231. package/web/.next/standalone/web/.next/static/static/media/fef07dbb0973bf53-s.518e079e.woff2 +0 -0
  232. package/web/.next/standalone/web/next.config.ts +0 -54
  233. package/web/.next/standalone/web/package-lock.json +7 -7
  234. package/web/.next/standalone/web/src/app/(main)/agents/page.tsx +222 -0
  235. package/web/.next/standalone/web/src/app/(main)/page.tsx +40 -1
  236. package/web/.next/standalone/web/src/app/(main)/session/[id]/page.tsx +9 -1
  237. package/web/.next/standalone/web/src/app/(main)/settings/page.tsx +1116 -0
  238. package/web/.next/standalone/web/src/components/chat-interface.tsx +222 -19
  239. package/web/.next/standalone/web/src/components/pending-question-banner.tsx +106 -0
  240. package/web/.next/standalone/web/src/components/sessions-sidebar.tsx +120 -50
  241. package/web/.next/standalone/web/src/lib/api.ts +61 -5
  242. package/web/.next/standalone/web/src/test/api.test.ts +17 -0
  243. package/web/.next/standalone/web/vitest.config.ts +13 -0
  244. package/web/.next/static/chunks/03b5edce6d5b809e.js +1 -0
  245. package/web/.next/static/chunks/29dcecc3c2ca92b0.js +1 -0
  246. package/web/.next/static/chunks/344be859c2c8600b.css +1 -0
  247. package/web/.next/static/chunks/545725e4c1237026.js +7 -0
  248. package/web/.next/static/chunks/60359bdd369c0c72.js +1 -0
  249. package/web/.next/static/chunks/699803c4fb2dd3fc.js +5 -0
  250. package/web/.next/static/chunks/735a2408c315b2f0.js +1 -0
  251. package/web/.next/static/chunks/a7d5d0791c8c6223.css +2 -0
  252. package/web/.next/static/chunks/d54077a2bb8314ed.js +31 -0
  253. package/web/.next/static/chunks/dc34aa94e57fa28e.js +3 -0
  254. package/web/.next/static/chunks/ea89ca7892d8c557.js +1 -0
  255. package/web/.next/static/chunks/f0f19357f3fb7cf8.js +1 -0
  256. package/web/.next/static/chunks/f50a66c24c564585.js +13 -0
  257. package/web/.next/static/chunks/f5fe518b79d1bf41.js +1 -0
  258. package/web/.next/static/chunks/{turbopack-597558bb7b6982f6.js → turbopack-2c0905c7bbebae3f.js} +1 -1
  259. package/web/.next/static/media/4fa387ec64143e14-s.c36e1862.woff2 +0 -0
  260. package/web/.next/static/media/53b9e256198e5412-s.853d50a3.woff2 +0 -0
  261. package/web/.next/static/media/5ce348bf30bf5439-s.ebceb24d.woff2 +0 -0
  262. package/web/.next/static/media/6306c77e7c8268e4-s.ff4a2084.woff2 +0 -0
  263. package/web/.next/static/media/7178b3e590c64307-s.55554cd0.woff2 +0 -0
  264. package/web/.next/static/media/797e433ab948586e-s.p.479bea2b.woff2 +0 -0
  265. package/web/.next/static/media/7d817b4c03b0c5f1-s.f377b9c4.woff2 +0 -0
  266. package/web/.next/static/media/8a480f0b521d4e75-s.ea323500.woff2 +0 -0
  267. package/web/.next/static/media/bbc41e54d2fcbd21-s.d1207556.woff2 +0 -0
  268. package/web/.next/static/media/caa3a2e1cccd8315-s.p.3b6cae6d.woff2 +0 -0
  269. package/web/.next/static/media/fef07dbb0973bf53-s.518e079e.woff2 +0 -0
  270. package/web/.next/standalone/web/.next/server/app/embed/[id]/page/app-paths-manifest.json +0 -3
  271. package/web/.next/standalone/web/.next/server/app/embed/[id]/page/next-font-manifest.json +0 -11
  272. package/web/.next/standalone/web/.next/server/app/embed/[id]/page.js.nft.json +0 -1
  273. package/web/.next/standalone/web/.next/server/app/embed/[id]/page_client-reference-manifest.js +0 -2
  274. package/web/.next/standalone/web/.next/server/chunks/ssr/2374f_317b1fef._.js +0 -3
  275. package/web/.next/standalone/web/.next/server/chunks/ssr/2374f_37dd9702._.js +0 -45
  276. package/web/.next/standalone/web/.next/server/chunks/ssr/2374f_4d44e4ed._.js +0 -26
  277. package/web/.next/standalone/web/.next/server/chunks/ssr/2374f_54ac917f._.js +0 -3
  278. package/web/.next/standalone/web/.next/server/chunks/ssr/2374f_86585101._.js +0 -3
  279. package/web/.next/standalone/web/.next/server/chunks/ssr/2374f_c59a35bb._.js +0 -3
  280. package/web/.next/standalone/web/.next/server/chunks/ssr/2374f_fdfc7f3d._.js +0 -31
  281. package/web/.next/standalone/web/.next/server/chunks/ssr/[root-of-the-server]__234f92d8._.js +0 -3
  282. package/web/.next/standalone/web/.next/server/chunks/ssr/[root-of-the-server]__9a826344._.js +0 -3
  283. package/web/.next/standalone/web/.next/server/chunks/ssr/[root-of-the-server]__9d3a7cbf._.js +0 -15
  284. package/web/.next/standalone/web/.next/server/chunks/ssr/[root-of-the-server]__de76483d._.js +0 -3
  285. package/web/.next/standalone/web/.next/server/chunks/ssr/web_08242997._.js +0 -3
  286. package/web/.next/standalone/web/.next/server/chunks/ssr/web_123ffe97._.js +0 -8
  287. package/web/.next/standalone/web/.next/server/chunks/ssr/web_5cca707f._.js +0 -7
  288. package/web/.next/standalone/web/.next/server/chunks/ssr/web_935e81f5._.js +0 -7
  289. package/web/.next/standalone/web/.next/server/chunks/ssr/web_99b01335._.js +0 -8
  290. package/web/.next/standalone/web/.next/server/chunks/ssr/web__next-internal_server_app_embed_[id]_page_actions_dd0b7fea.js +0 -3
  291. package/web/.next/standalone/web/.next/server/chunks/ssr/web_src_components_sessions-sidebar_tsx_92510070._.js +0 -3
  292. package/web/.next/standalone/web/.next/static/chunks/1ebba7ac024244f9.js +0 -5
  293. package/web/.next/standalone/web/.next/static/chunks/2473c16c0c2f6b5f.css +0 -2
  294. package/web/.next/standalone/web/.next/static/chunks/2624c966c288fd41.js +0 -13
  295. package/web/.next/standalone/web/.next/static/chunks/275e8268daf318b2.js +0 -7
  296. package/web/.next/standalone/web/.next/static/chunks/58fd0aaa2746b444.js +0 -1
  297. package/web/.next/standalone/web/.next/static/chunks/74b64476a24dd71e.css +0 -1
  298. package/web/.next/standalone/web/.next/static/chunks/767bcdfbabf0703e.js +0 -7
  299. package/web/.next/standalone/web/.next/static/chunks/8af263bc97c0c9ee.js +0 -3
  300. package/web/.next/standalone/web/.next/static/chunks/a888d448ceab1abe.js +0 -1
  301. package/web/.next/standalone/web/.next/static/chunks/b9ad1584d4e11d12.js +0 -1
  302. package/web/.next/standalone/web/.next/static/chunks/c6f40df16a9396b9.js +0 -1
  303. package/web/.next/standalone/web/.next/static/chunks/cfadc93a98190e5a.js +0 -3
  304. package/web/.next/standalone/web/.next/static/chunks/ea29be392100ab0f.js +0 -5
  305. package/web/.next/standalone/web/.next/static/media/4fa387ec64143e14-s.c1fdd6c2.woff2 +0 -0
  306. package/web/.next/standalone/web/.next/static/media/7178b3e590c64307-s.b97b3418.woff2 +0 -0
  307. package/web/.next/standalone/web/.next/static/media/797e433ab948586e-s.p.dbea232f.woff2 +0 -0
  308. package/web/.next/standalone/web/.next/static/media/8a480f0b521d4e75-s.8e0177b5.woff2 +0 -0
  309. package/web/.next/standalone/web/.next/static/media/bbc41e54d2fcbd21-s.799d8ef8.woff2 +0 -0
  310. package/web/.next/standalone/web/.next/static/media/caa3a2e1cccd8315-s.p.853070df.woff2 +0 -0
  311. package/web/.next/standalone/web/.next/static/static/chunks/1ebba7ac024244f9.js +0 -5
  312. package/web/.next/standalone/web/.next/static/static/chunks/2473c16c0c2f6b5f.css +0 -2
  313. package/web/.next/standalone/web/.next/static/static/chunks/2624c966c288fd41.js +0 -13
  314. package/web/.next/standalone/web/.next/static/static/chunks/275e8268daf318b2.js +0 -7
  315. package/web/.next/standalone/web/.next/static/static/chunks/58fd0aaa2746b444.js +0 -1
  316. package/web/.next/standalone/web/.next/static/static/chunks/74b64476a24dd71e.css +0 -1
  317. package/web/.next/standalone/web/.next/static/static/chunks/767bcdfbabf0703e.js +0 -7
  318. package/web/.next/standalone/web/.next/static/static/chunks/8af263bc97c0c9ee.js +0 -3
  319. package/web/.next/standalone/web/.next/static/static/chunks/a888d448ceab1abe.js +0 -1
  320. package/web/.next/standalone/web/.next/static/static/chunks/b9ad1584d4e11d12.js +0 -1
  321. package/web/.next/standalone/web/.next/static/static/chunks/c6f40df16a9396b9.js +0 -1
  322. package/web/.next/standalone/web/.next/static/static/chunks/cfadc93a98190e5a.js +0 -3
  323. package/web/.next/standalone/web/.next/static/static/chunks/ea29be392100ab0f.js +0 -5
  324. package/web/.next/standalone/web/.next/static/static/media/4fa387ec64143e14-s.c1fdd6c2.woff2 +0 -0
  325. package/web/.next/standalone/web/.next/static/static/media/7178b3e590c64307-s.b97b3418.woff2 +0 -0
  326. package/web/.next/standalone/web/.next/static/static/media/797e433ab948586e-s.p.dbea232f.woff2 +0 -0
  327. package/web/.next/standalone/web/.next/static/static/media/8a480f0b521d4e75-s.8e0177b5.woff2 +0 -0
  328. package/web/.next/standalone/web/.next/static/static/media/bbc41e54d2fcbd21-s.799d8ef8.woff2 +0 -0
  329. package/web/.next/standalone/web/.next/static/static/media/caa3a2e1cccd8315-s.p.853070df.woff2 +0 -0
  330. package/web/.next/standalone/web/src/app/embed/[id]/page.tsx +0 -77
  331. package/web/.next/standalone/web/src/lib/embed-bootstrap.ts +0 -108
  332. package/web/.next/static/chunks/1ebba7ac024244f9.js +0 -5
  333. package/web/.next/static/chunks/2473c16c0c2f6b5f.css +0 -2
  334. package/web/.next/static/chunks/2624c966c288fd41.js +0 -13
  335. package/web/.next/static/chunks/275e8268daf318b2.js +0 -7
  336. package/web/.next/static/chunks/58fd0aaa2746b444.js +0 -1
  337. package/web/.next/static/chunks/74b64476a24dd71e.css +0 -1
  338. package/web/.next/static/chunks/767bcdfbabf0703e.js +0 -7
  339. package/web/.next/static/chunks/8af263bc97c0c9ee.js +0 -3
  340. package/web/.next/static/chunks/a888d448ceab1abe.js +0 -1
  341. package/web/.next/static/chunks/b9ad1584d4e11d12.js +0 -1
  342. package/web/.next/static/chunks/c6f40df16a9396b9.js +0 -1
  343. package/web/.next/static/chunks/cfadc93a98190e5a.js +0 -3
  344. package/web/.next/static/chunks/ea29be392100ab0f.js +0 -5
  345. package/web/.next/static/media/4fa387ec64143e14-s.c1fdd6c2.woff2 +0 -0
  346. package/web/.next/static/media/7178b3e590c64307-s.b97b3418.woff2 +0 -0
  347. package/web/.next/static/media/797e433ab948586e-s.p.dbea232f.woff2 +0 -0
  348. package/web/.next/static/media/8a480f0b521d4e75-s.8e0177b5.woff2 +0 -0
  349. package/web/.next/static/media/bbc41e54d2fcbd21-s.799d8ef8.woff2 +0 -0
  350. package/web/.next/static/media/caa3a2e1cccd8315-s.p.853070df.woff2 +0 -0
  351. package/dist/{search-CCffrVJE.d.ts → search-DOzC4ojH.d.ts} +1 -1
  352. /package/web/.next/standalone/web/.next/server/app/{embed/[id] → (main)/agents}/page/react-loadable-manifest.json +0 -0
  353. /package/web/.next/standalone/web/.next/server/app/{embed/[id] → (main)/agents}/page/server-reference-manifest.json +0 -0
  354. /package/web/.next/standalone/web/.next/server/app/{embed/[id] → (main)/agents}/page.js.map +0 -0
  355. /package/web/.next/standalone/web/.next/static/{-npGTmVDA-oK8ZjRdKQf5 → static/yyzMTo2RYusiXE0e1_kdc}/_buildManifest.js +0 -0
  356. /package/web/.next/standalone/web/.next/static/{-npGTmVDA-oK8ZjRdKQf5 → static/yyzMTo2RYusiXE0e1_kdc}/_clientMiddlewareManifest.json +0 -0
  357. /package/web/.next/standalone/web/.next/static/{-npGTmVDA-oK8ZjRdKQf5 → static/yyzMTo2RYusiXE0e1_kdc}/_ssgManifest.js +0 -0
  358. /package/web/.next/standalone/web/.next/static/{static/-npGTmVDA-oK8ZjRdKQf5 → yyzMTo2RYusiXE0e1_kdc}/_buildManifest.js +0 -0
  359. /package/web/.next/standalone/web/.next/static/{static/-npGTmVDA-oK8ZjRdKQf5 → yyzMTo2RYusiXE0e1_kdc}/_clientMiddlewareManifest.json +0 -0
  360. /package/web/.next/standalone/web/.next/static/{static/-npGTmVDA-oK8ZjRdKQf5 → yyzMTo2RYusiXE0e1_kdc}/_ssgManifest.js +0 -0
  361. /package/web/.next/static/{-npGTmVDA-oK8ZjRdKQf5 → yyzMTo2RYusiXE0e1_kdc}/_buildManifest.js +0 -0
  362. /package/web/.next/static/{-npGTmVDA-oK8ZjRdKQf5 → yyzMTo2RYusiXE0e1_kdc}/_clientMiddlewareManifest.json +0 -0
  363. /package/web/.next/static/{-npGTmVDA-oK8ZjRdKQf5 → yyzMTo2RYusiXE0e1_kdc}/_ssgManifest.js +0 -0
@@ -1,5 +1,6 @@
1
1
  'use client';
2
2
 
3
+ import * as React from 'react';
3
4
  import { useState, useRef, useEffect } from 'react';
4
5
  import Image from 'next/image';
5
6
  import { cn } from '@/lib/utils';
@@ -238,6 +239,167 @@ function stripDevtoolsContext(text: string): string {
238
239
  return text.replace(DEVTOOLS_CONTEXT_RE, '').trim();
239
240
  }
240
241
 
242
+ /** Channel pill at the start of an orchestrator user-message, e.g. "[SLACK #ops by @ryan]" or "[WEB]". */
243
+ interface ChannelPillInfo {
244
+ channel: string; // SLACK | WEB | SYSTEM | SCHEDULE | WEBHOOK
245
+ detail?: string; // remainder of the bracket, e.g. "#ops by @ryan"
246
+ }
247
+ function extractChannelPill(text: string): { pill: ChannelPillInfo | null; rest: string } {
248
+ const m = text.match(/^\[([A-Z]+)(?:\s+([^\]]*))?\]\s*([\s\S]*)$/);
249
+ if (!m) return { pill: null, rest: text };
250
+ const channel = m[1];
251
+ // Only treat as a channel pill if it's a known channel id.
252
+ if (!['WEB', 'SLACK', 'SYSTEM', 'SCHEDULE', 'WEBHOOK'].includes(channel)) {
253
+ return { pill: null, rest: text };
254
+ }
255
+ return { pill: { channel, detail: m[2]?.trim() || undefined }, rest: m[3] };
256
+ }
257
+
258
+ const CHANNEL_PALETTE: Record<string, string> = {
259
+ SLACK: 'bg-purple-500/10 text-purple-600 dark:text-purple-300 border-purple-500/30',
260
+ SYSTEM: 'bg-blue-500/10 text-blue-600 dark:text-blue-300 border-blue-500/30',
261
+ SCHEDULE: 'bg-amber-500/10 text-amber-600 dark:text-amber-300 border-amber-500/30',
262
+ WEBHOOK: 'bg-emerald-500/10 text-emerald-600 dark:text-emerald-300 border-emerald-500/30',
263
+ };
264
+
265
+ function ChannelPill({ channel, detail }: ChannelPillInfo) {
266
+ // Hide [WEB] pills — web is the default surface, showing a pill on
267
+ // every typed message is noise.
268
+ if (channel === 'WEB') return null;
269
+ const tone = CHANNEL_PALETTE[channel] || 'bg-muted text-muted-foreground border-border';
270
+ return (
271
+ <span className={`inline-flex items-center gap-1 text-[10px] font-medium uppercase tracking-wide px-1.5 py-0.5 rounded border mr-2 mb-1 ${tone}`}>
272
+ <span>{channel}</span>
273
+ {detail && <span className="font-normal normal-case opacity-80">{detail}</span>}
274
+ </span>
275
+ );
276
+ }
277
+
278
+ /** Channels that aren't direct human chat — render compactly with click-to-expand. */
279
+ const SYNTHETIC_CHANNELS = new Set(['SYSTEM', 'SCHEDULE', 'WEBHOOK']);
280
+
281
+ /**
282
+ * Inbound human message from a non-web channel (Slack today, others later).
283
+ * Renders the tag ABOVE a normal user bubble so the convo doesn't read like
284
+ * the channel pill is part of the message body.
285
+ */
286
+ function TaggedInboundUserMessage({
287
+ pill, body, attachmentsBlock, devtoolsTrail, footer,
288
+ }: {
289
+ pill: ChannelPillInfo;
290
+ body: string;
291
+ attachmentsBlock?: React.ReactNode;
292
+ devtoolsTrail?: React.ReactNode;
293
+ footer?: React.ReactNode;
294
+ }) {
295
+ const tone = CHANNEL_PALETTE[pill.channel] || 'bg-muted text-muted-foreground border-border';
296
+ return (
297
+ <div className="flex flex-col items-end gap-1 my-2">
298
+ <div className={`inline-flex items-center gap-1.5 text-[10px] font-medium uppercase tracking-wide px-2 py-0.5 rounded-md border self-end ${tone}`}>
299
+ <span>{pill.channel}</span>
300
+ {pill.detail && <span className="font-normal normal-case opacity-80">{pill.detail}</span>}
301
+ </div>
302
+ <Message from="user">
303
+ <MessageContent>
304
+ {attachmentsBlock}
305
+ {body && <p className="whitespace-pre-wrap">{body}</p>}
306
+ {devtoolsTrail}
307
+ </MessageContent>
308
+ {footer}
309
+ </Message>
310
+ </div>
311
+ );
312
+ }
313
+
314
+ /**
315
+ * Renders an outbound `messenger({action:'post', ...})` tool call as if it
316
+ * were a special assistant message: tag on top ("→ SENT VIA SLACK #ops"),
317
+ * the actual text bubble below, and a small status footer. So when a user
318
+ * comes back to the web later they can see exactly what was sent on other
319
+ * channels.
320
+ */
321
+ function SentMessengerCard({
322
+ input, output, status,
323
+ }: {
324
+ input: any;
325
+ output: any;
326
+ status: string;
327
+ }) {
328
+ if (!input || input.action !== 'post') return null;
329
+ const channel = String(input.channel || 'unknown').toUpperCase();
330
+ const tone = CHANNEL_PALETTE[channel] || 'bg-muted text-muted-foreground border-border';
331
+ const to = String(input.to || '');
332
+ const threadTs = input.threadTs ? String(input.threadTs) : null;
333
+ const text = String(input.text || '');
334
+ const ok = output && typeof output === 'object' && (output as any).ok !== false;
335
+ const errorText = output && typeof output === 'object' ? (output as any).error : undefined;
336
+ const pending = status === 'streaming' || status === 'running' || status === 'pending' || status === 'input-available';
337
+ return (
338
+ <div className="flex flex-col items-start gap-1 my-2 max-w-[80%]">
339
+ <div className={`inline-flex items-center gap-1.5 text-[10px] font-medium uppercase tracking-wide px-2 py-0.5 rounded-md border ${tone}`}>
340
+ <span>→ Sent via {channel}</span>
341
+ {to && <span className="font-normal normal-case opacity-80">to {to}</span>}
342
+ {threadTs && <span className="font-normal normal-case opacity-60">thread {threadTs}</span>}
343
+ </div>
344
+ <div className={`rounded-2xl border bg-card/40 px-3 py-2 ${pending ? 'opacity-60' : ''}`}>
345
+ {text ? (
346
+ <p className="text-sm whitespace-pre-wrap">{text}</p>
347
+ ) : (
348
+ <p className="text-xs italic text-muted-foreground">(empty message)</p>
349
+ )}
350
+ </div>
351
+ <div className="text-[10px] text-muted-foreground flex items-center gap-1">
352
+ {pending ? (
353
+ <span className="opacity-70">sending…</span>
354
+ ) : ok ? (
355
+ <span className="text-emerald-500">✓ delivered</span>
356
+ ) : (
357
+ <span className="text-rose-500">✗ failed{errorText ? `: ${errorText}` : ''}</span>
358
+ )}
359
+ </div>
360
+ </div>
361
+ );
362
+ }
363
+
364
+ /**
365
+ * Synthetic event row — a compact one-liner for SYSTEM/SCHEDULE/WEBHOOK
366
+ * messages so the chat doesn't get cluttered with every worker completion,
367
+ * cron tick, or webhook hit. Click to expand the full payload.
368
+ */
369
+ function SyntheticEventMessage({ pill, body }: { pill: ChannelPillInfo; body: string }) {
370
+ const [expanded, setExpanded] = React.useState(false);
371
+ const tone = CHANNEL_PALETTE[pill.channel] || 'bg-muted text-muted-foreground border-border';
372
+ // First non-empty line for the collapsed summary.
373
+ const firstLine = body.split('\n').find((l) => l.trim().length > 0) || '';
374
+ const truncated = firstLine.length > 140 ? firstLine.slice(0, 140) + '…' : firstLine;
375
+ const isMultiline = body.includes('\n') || body.length > 140;
376
+
377
+ return (
378
+ <div className="flex justify-center my-1.5">
379
+ <button
380
+ type="button"
381
+ onClick={() => isMultiline && setExpanded((v) => !v)}
382
+ className={`group max-w-[80%] text-left rounded-md border px-2 py-1 transition-colors ${tone} ${isMultiline ? 'cursor-pointer hover:opacity-90' : 'cursor-default'}`}
383
+ >
384
+ <div className="flex items-center gap-2 text-[10px] uppercase tracking-wide">
385
+ <span className="font-medium">{pill.channel}</span>
386
+ {pill.detail && <span className="font-normal normal-case opacity-80 truncate">{pill.detail}</span>}
387
+ {isMultiline && (
388
+ <ChevronDown
389
+ className={`h-3 w-3 ml-auto shrink-0 transition-transform ${expanded ? 'rotate-180' : ''}`}
390
+ />
391
+ )}
392
+ </div>
393
+ {expanded ? (
394
+ <pre className="mt-1 text-[11px] whitespace-pre-wrap font-mono opacity-90 max-h-[400px] overflow-y-auto">{body}</pre>
395
+ ) : (
396
+ <p className="mt-0.5 text-[11px] opacity-80 truncate">{truncated}</p>
397
+ )}
398
+ </button>
399
+ </div>
400
+ );
401
+ }
402
+
241
403
  /** Parse devtools context metadata from a user message */
242
404
  function parseDevtoolsContext(text: string): DevtoolsContextMeta | null {
243
405
  const match = text.match(/<devtools-context>([\s\S]*?)<\/devtools-context>/);
@@ -2531,21 +2693,23 @@ export function ChatInterface({ session, isEmbed = false }: ChatInterfaceProps)
2531
2693
  </div>
2532
2694
 
2533
2695
  {/* Working Directory */}
2534
- <TooltipProvider>
2535
- <Tooltip>
2536
- <TooltipTrigger asChild>
2537
- <div className="flex items-center gap-1.5 px-2 py-1 rounded-md bg-muted/30 text-xs text-muted-foreground max-w-[200px]">
2538
- <FolderOpen className="size-3.5 shrink-0" />
2539
- <span className="truncate font-mono">
2540
- {session.workingDirectory.split('/').pop() || session.workingDirectory}
2541
- </span>
2542
- </div>
2543
- </TooltipTrigger>
2544
- <TooltipContent side="bottom" className="max-w-md">
2545
- <p className="font-mono text-xs">{session.workingDirectory}</p>
2546
- </TooltipContent>
2547
- </Tooltip>
2548
- </TooltipProvider>
2696
+ {session.workingDirectory ? (
2697
+ <TooltipProvider>
2698
+ <Tooltip>
2699
+ <TooltipTrigger asChild>
2700
+ <div className="flex items-center gap-1.5 px-2 py-1 rounded-md bg-muted/30 text-xs text-muted-foreground max-w-[200px]">
2701
+ <FolderOpen className="size-3.5 shrink-0" />
2702
+ <span className="truncate font-mono">
2703
+ {session.workingDirectory.split('/').pop() || session.workingDirectory}
2704
+ </span>
2705
+ </div>
2706
+ </TooltipTrigger>
2707
+ <TooltipContent side="bottom" className="max-w-md">
2708
+ <p className="font-mono text-xs">{session.workingDirectory}</p>
2709
+ </TooltipContent>
2710
+ </Tooltip>
2711
+ </TooltipProvider>
2712
+ ) : null}
2549
2713
  </div>
2550
2714
  <div className="flex items-center gap-2 shrink-0">
2551
2715
  {/* Browser recordings */}
@@ -2996,12 +3160,31 @@ export function ChatInterface({ session, isEmbed = false }: ChatInterfaceProps)
2996
3160
  })
2997
3161
  .map((item) => {
2998
3162
  if (item.type === 'user-message') {
3163
+ // Channel-aware rendering for orchestrator-bound user messages.
3164
+ // - SYSTEM/SCHEDULE/WEBHOOK → compact collapsible row
3165
+ // - SLACK and other non-web human channels → tag ABOVE the bubble,
3166
+ // clean body inside (so the chat doesn't read like the pill is
3167
+ // part of the message)
3168
+ // - WEB / no pill → normal user bubble (unchanged)
3169
+ const extracted = item.content ? extractChannelPill(item.content) : { pill: null, rest: item.content || '' };
3170
+ if (extracted.pill && SYNTHETIC_CHANNELS.has(extracted.pill.channel)) {
3171
+ return <SyntheticEventMessage key={item.id} pill={extracted.pill} body={extracted.rest} />;
3172
+ }
3173
+ const useTaggedAbove = !!extracted.pill && extracted.pill.channel !== 'WEB';
3174
+
2999
3175
  // Check if there's a checkpoint for this message (meaning we can revert to before it)
3000
3176
  const hasCheckpoint = item.messageSequence !== undefined &&
3001
3177
  checkpoints.some(cp => cp.messageSequence === item.messageSequence);
3002
3178
 
3003
3179
  return (
3004
- <Message key={item.id} from="user">
3180
+ <div key={item.id} className={useTaggedAbove ? 'flex flex-col items-end gap-1' : undefined}>
3181
+ {useTaggedAbove && extracted.pill && (
3182
+ <div className={`inline-flex items-center gap-1.5 text-[10px] font-medium uppercase tracking-wide px-2 py-0.5 rounded-md border self-end ${CHANNEL_PALETTE[extracted.pill.channel] || 'bg-muted text-muted-foreground border-border'}`}>
3183
+ <span>{extracted.pill.channel}</span>
3184
+ {extracted.pill.detail && <span className="font-normal normal-case opacity-80">{extracted.pill.detail}</span>}
3185
+ </div>
3186
+ )}
3187
+ <Message from="user">
3005
3188
  <MessageContent>
3006
3189
  {/* Display attachments if any */}
3007
3190
  {item.attachments && item.attachments.length > 0 && (
@@ -3030,10 +3213,15 @@ export function ChatInterface({ session, isEmbed = false }: ChatInterfaceProps)
3030
3213
  </div>
3031
3214
  )}
3032
3215
  {item.content && (() => {
3033
- const displayText = stripDevtoolsContext(item.content);
3034
- const devtoolsMeta = parseDevtoolsContext(item.content);
3216
+ // Use the already-extracted pill/rest from the parent
3217
+ // scope so we don't double-render the tag for tagged-above
3218
+ // messages.
3219
+ const rest = extracted.rest;
3220
+ const displayText = stripDevtoolsContext(rest);
3221
+ const devtoolsMeta = parseDevtoolsContext(rest);
3035
3222
  return (
3036
3223
  <>
3224
+ {!useTaggedAbove && extracted.pill && <ChannelPill {...extracted.pill} />}
3037
3225
  {displayText && (
3038
3226
  <p className="whitespace-pre-wrap">{displayText}</p>
3039
3227
  )}
@@ -3076,6 +3264,7 @@ export function ChatInterface({ session, isEmbed = false }: ChatInterfaceProps)
3076
3264
  </MessageActions>
3077
3265
  )}
3078
3266
  </Message>
3267
+ </div>
3079
3268
  );
3080
3269
  }
3081
3270
 
@@ -3124,7 +3313,21 @@ export function ChatInterface({ session, isEmbed = false }: ChatInterfaceProps)
3124
3313
  if (item.type === 'tool-call' && item.toolCall) {
3125
3314
  const tc = item.toolCall;
3126
3315
  const toolType = `tool-${tc.toolName}` as `tool-${string}`;
3127
-
3316
+
3317
+ // Render outbound `messenger({action:'post',...})` as a special
3318
+ // "Sent via SLACK #ops" card so anyone returning to the web can
3319
+ // see what the orchestrator actually pushed to external channels.
3320
+ if (tc.toolName === 'messenger' && (tc.input as any)?.action === 'post') {
3321
+ return (
3322
+ <SentMessengerCard
3323
+ key={item.id}
3324
+ input={tc.input}
3325
+ output={tc.output}
3326
+ status={tc.status}
3327
+ />
3328
+ );
3329
+ }
3330
+
3128
3331
  // Use dedicated WriteFileTool component for write_file
3129
3332
  if (tc.toolName === 'write_file') {
3130
3333
  return (
@@ -0,0 +1,106 @@
1
+ 'use client';
2
+
3
+ import { useEffect, useState, useCallback } from 'react';
4
+ import { MessageCircleQuestion, Loader2 } from 'lucide-react';
5
+ import { Button } from '@/components/ui/button';
6
+ import { getSession, answerAgentQuestion } from '@/lib/api';
7
+
8
+ /**
9
+ * Polls the session and shows a banner inside the chat surface when the
10
+ * worker agent has called `ask_question_to_user`. Lets the user answer
11
+ * inline so they don't have to leave the session.
12
+ */
13
+ export function PendingQuestionBanner({ sessionId }: { sessionId: string }) {
14
+ const [question, setQuestion] = useState<{
15
+ questionId: string;
16
+ question: string;
17
+ context?: string;
18
+ choices?: string[];
19
+ } | null>(null);
20
+ const [answer, setAnswer] = useState('');
21
+ const [sending, setSending] = useState(false);
22
+
23
+ const refresh = useCallback(async () => {
24
+ const s = await getSession(sessionId);
25
+ setQuestion(s?.pendingQuestion ?? null);
26
+ }, [sessionId]);
27
+
28
+ useEffect(() => {
29
+ let cancelled = false;
30
+ const tick = async () => {
31
+ if (cancelled) return;
32
+ await refresh();
33
+ };
34
+ tick();
35
+ const id = setInterval(tick, 3000);
36
+ return () => {
37
+ cancelled = true;
38
+ clearInterval(id);
39
+ };
40
+ }, [refresh]);
41
+
42
+ if (!question) return null;
43
+
44
+ const send = async () => {
45
+ if (!answer.trim() || sending) return;
46
+ setSending(true);
47
+ try {
48
+ await answerAgentQuestion(sessionId, question.questionId, answer.trim());
49
+ setAnswer('');
50
+ setQuestion(null);
51
+ // The worker will resume; the next poll will reflect that.
52
+ refresh();
53
+ } finally {
54
+ setSending(false);
55
+ }
56
+ };
57
+
58
+ return (
59
+ <div className="border-b border-amber-500/40 bg-amber-500/5 px-4 py-3">
60
+ <div className="flex items-start gap-3 max-w-3xl mx-auto">
61
+ <MessageCircleQuestion className="size-5 text-amber-500 shrink-0 mt-0.5" />
62
+ <div className="flex-1 min-w-0">
63
+ <p className="text-sm font-medium text-amber-800 dark:text-amber-200">
64
+ {question.question}
65
+ </p>
66
+ {question.context && (
67
+ <p className="text-xs text-muted-foreground mt-1">{question.context}</p>
68
+ )}
69
+ {question.choices && question.choices.length > 0 && (
70
+ <div className="flex flex-wrap gap-1.5 mt-2">
71
+ {question.choices.map((c) => (
72
+ <button
73
+ key={c}
74
+ type="button"
75
+ onClick={() => setAnswer(c)}
76
+ className="text-xs px-2 py-1 rounded bg-amber-500/10 hover:bg-amber-500/20 text-amber-800 dark:text-amber-200"
77
+ >
78
+ {c}
79
+ </button>
80
+ ))}
81
+ </div>
82
+ )}
83
+ <div className="flex gap-2 mt-2">
84
+ <input
85
+ type="text"
86
+ value={answer}
87
+ onChange={(e) => setAnswer(e.target.value)}
88
+ onKeyDown={(e) => {
89
+ if (e.key === 'Enter') {
90
+ e.preventDefault();
91
+ send();
92
+ }
93
+ }}
94
+ placeholder="Type your answer…"
95
+ className="flex-1 px-3 py-1.5 text-sm rounded border border-border bg-background focus:outline-none focus:ring-2 focus:ring-amber-500/40"
96
+ autoFocus
97
+ />
98
+ <Button size="sm" onClick={send} disabled={!answer.trim() || sending}>
99
+ {sending ? <Loader2 className="size-3.5 animate-spin" /> : 'Answer'}
100
+ </Button>
101
+ </div>
102
+ </div>
103
+ </div>
104
+ </div>
105
+ );
106
+ }
@@ -4,7 +4,7 @@ import { useState, useEffect, useRef } from 'react';
4
4
  import { useRouter, usePathname } from 'next/navigation';
5
5
  import Link from 'next/link';
6
6
  import Image from 'next/image';
7
- import { Plus, MessageSquare, Trash2, Loader2, Settings, PanelLeftClose, PanelLeft, Key, Check, X, Eye, EyeOff, Volume2, ListChecks, ChevronDown } from 'lucide-react';
7
+ import { Plus, MessageSquare, Trash2, Loader2, Settings, PanelLeftClose, PanelLeft, Key, Check, X, Eye, EyeOff, Volume2, ListChecks, ChevronDown, Bot, LayoutGrid, Sliders } from 'lucide-react';
8
8
  import { Badge } from '@/components/ui/badge';
9
9
  import {
10
10
  Sidebar,
@@ -106,18 +106,13 @@ export function SessionsSidebar() {
106
106
  // Notification sound setting
107
107
  const { enabled: soundEnabled, setEnabled: setSoundEnabled } = useNotificationSound();
108
108
 
109
- // Detect if we're in embed mode
110
- const isEmbedMode = pathname.startsWith('/embed/');
111
-
112
109
  // Get current session ID from pathname
113
- const currentSessionId = pathname.startsWith('/session/')
114
- ? pathname.split('/session/')[1]
115
- : pathname.startsWith('/embed/')
116
- ? pathname.split('/embed/')[1]
110
+ const currentSessionId = pathname.startsWith('/session/')
111
+ ? pathname.split('/session/')[1]
117
112
  : null;
118
-
113
+
119
114
  // Base path for session links
120
- const sessionBasePath = isEmbedMode ? '/embed' : '/session';
115
+ const sessionBasePath = '/session';
121
116
 
122
117
  // Determine if any session is actively running (for mascot animation)
123
118
  const isThinking = sessions.some(s => s.isStreaming);
@@ -306,7 +301,7 @@ export function SessionsSidebar() {
306
301
  const isCollapsed = state === 'collapsed';
307
302
 
308
303
  return (
309
- <Sidebar collapsible={isEmbedMode ? "offcanvas" : "icon"} className="border-r border-border/50">
304
+ <Sidebar collapsible="icon" className="border-r border-border/50">
310
305
  {/* Header */}
311
306
  <SidebarHeader className={cn(isCollapsed ? "p-2 space-y-2" : "p-3 space-y-3")}>
312
307
  {/* Expanded: Full header */}
@@ -359,6 +354,63 @@ export function SessionsSidebar() {
359
354
  </div>
360
355
  </div>
361
356
 
357
+ {(() => {
358
+ const orchestrator = sessions.find((s) => s.role === 'orchestrator');
359
+ const workers = sessions.filter((s) => s.role === 'worker');
360
+ const needsAttention = workers.filter((s) => s.agentStatus === 'needs_attention').length;
361
+ const running = workers.filter((s) => s.agentStatus === 'running').length;
362
+ return (
363
+ <div className="flex flex-col gap-1 w-full">
364
+ <Link
365
+ href={orchestrator ? `/session/${orchestrator.id}` : '#'}
366
+ className={cn(
367
+ 'flex items-center gap-2 px-2 py-1.5 rounded-md text-sm transition-colors',
368
+ pathname.startsWith('/session/') && orchestrator && pathname.includes(orchestrator.id)
369
+ ? 'bg-accent text-foreground'
370
+ : 'hover:bg-accent/60 text-foreground/80',
371
+ )}
372
+ >
373
+ <Bot className="size-4 text-primary shrink-0" />
374
+ <span className="flex-1 truncate">Orchestrator</span>
375
+ {orchestrator?.isStreaming && (
376
+ <span className="size-1.5 rounded-full bg-emerald-500 animate-pulse" />
377
+ )}
378
+ </Link>
379
+ <Link
380
+ href="/agents"
381
+ className={cn(
382
+ 'flex items-center gap-2 px-2 py-1.5 rounded-md text-sm transition-colors',
383
+ pathname === '/agents' ? 'bg-accent text-foreground' : 'hover:bg-accent/60 text-foreground/80',
384
+ )}
385
+ >
386
+ <LayoutGrid className="size-4 text-muted-foreground shrink-0" />
387
+ <span className="flex-1 truncate">Agents</span>
388
+ <span className="text-[10px] text-muted-foreground tabular-nums">
389
+ {workers.length}
390
+ </span>
391
+ {needsAttention > 0 && (
392
+ <span className="text-[10px] px-1 rounded bg-amber-500/20 text-amber-600 dark:text-amber-300 tabular-nums">
393
+ {needsAttention}!
394
+ </span>
395
+ )}
396
+ {running > 0 && needsAttention === 0 && (
397
+ <span className="size-1.5 rounded-full bg-emerald-500 animate-pulse" />
398
+ )}
399
+ </Link>
400
+ <Link
401
+ href="/settings"
402
+ className={cn(
403
+ 'flex items-center gap-2 px-2 py-1.5 rounded-md text-sm transition-colors',
404
+ pathname === '/settings' ? 'bg-accent text-foreground' : 'hover:bg-accent/60 text-foreground/80',
405
+ )}
406
+ >
407
+ <Sliders className="size-4 text-muted-foreground shrink-0" />
408
+ <span className="flex-1 truncate">Settings</span>
409
+ </Link>
410
+ </div>
411
+ );
412
+ })()}
413
+
362
414
  <div className="flex gap-2 w-full">
363
415
  <Button
364
416
  onClick={handleQuickCreate}
@@ -456,6 +508,56 @@ export function SessionsSidebar() {
456
508
  </Tooltip>
457
509
  </TooltipProvider>
458
510
 
511
+ {/* Orchestrator icon (collapsed) */}
512
+ {(() => {
513
+ const orchestrator = sessions.find((s) => s.role === 'orchestrator');
514
+ return (
515
+ <TooltipProvider>
516
+ <Tooltip>
517
+ <TooltipTrigger asChild>
518
+ <Link
519
+ href={orchestrator ? `/session/${orchestrator.id}` : '#'}
520
+ className="size-8 mx-auto inline-flex items-center justify-center rounded-md hover:bg-accent"
521
+ >
522
+ <Bot className="size-4 text-primary" />
523
+ </Link>
524
+ </TooltipTrigger>
525
+ <TooltipContent side="right">Orchestrator</TooltipContent>
526
+ </Tooltip>
527
+ </TooltipProvider>
528
+ );
529
+ })()}
530
+
531
+ {/* Agents board icon (collapsed) */}
532
+ <TooltipProvider>
533
+ <Tooltip>
534
+ <TooltipTrigger asChild>
535
+ <Link
536
+ href="/agents"
537
+ className="size-8 mx-auto inline-flex items-center justify-center rounded-md hover:bg-accent"
538
+ >
539
+ <LayoutGrid className="size-4" />
540
+ </Link>
541
+ </TooltipTrigger>
542
+ <TooltipContent side="right">Agents board</TooltipContent>
543
+ </Tooltip>
544
+ </TooltipProvider>
545
+
546
+ {/* Settings icon (collapsed) */}
547
+ <TooltipProvider>
548
+ <Tooltip>
549
+ <TooltipTrigger asChild>
550
+ <Link
551
+ href="/settings"
552
+ className="size-8 mx-auto inline-flex items-center justify-center rounded-md hover:bg-accent"
553
+ >
554
+ <Sliders className="size-4" />
555
+ </Link>
556
+ </TooltipTrigger>
557
+ <TooltipContent side="right">Settings</TooltipContent>
558
+ </Tooltip>
559
+ </TooltipProvider>
560
+
459
561
  {/* New Task button */}
460
562
  <TooltipProvider>
461
563
  <Tooltip>
@@ -711,7 +813,7 @@ export function SessionsSidebar() {
711
813
  <div className="flex justify-center py-8">
712
814
  <Loader2 className="size-5 animate-spin text-muted-foreground" />
713
815
  </div>
714
- ) : sessions.length === 0 ? (
816
+ ) : sessions.filter((s) => s.role !== 'orchestrator').length === 0 ? (
715
817
  !isCollapsed && (
716
818
  <div className="text-center py-8 px-4">
717
819
  <div className="relative overflow-hidden rounded-xl size-12 mx-auto mb-3 shadow-md ring-1 ring-white/10">
@@ -738,7 +840,7 @@ export function SessionsSidebar() {
738
840
  </div>
739
841
  )
740
842
  ) : (
741
- sessions.map((session) => {
843
+ sessions.filter((s) => s.role !== 'orchestrator').map((session) => {
742
844
  const isActive = session.id === currentSessionId;
743
845
  const isHovered = hoveredSession === session.id;
744
846
  const isRunning = session.isStreaming === true;
@@ -891,24 +993,11 @@ export function SessionsSidebar() {
891
993
  <span className="text-muted-foreground">{sessions.length}</span>
892
994
  </div>
893
995
 
894
- {/* Settings button */}
895
- <Dialog open={settingsOpen} onOpenChange={setSettingsOpen}>
896
- <TooltipProvider>
897
- <Tooltip>
898
- <TooltipTrigger asChild>
899
- <DialogTrigger asChild>
900
- <Button
901
- size="icon"
902
- variant="ghost"
903
- className="size-7 hover:bg-accent transition-colors"
904
- >
905
- <Settings className="size-4" />
906
- </Button>
907
- </DialogTrigger>
908
- </TooltipTrigger>
909
- <TooltipContent side="top">Settings</TooltipContent>
910
- </Tooltip>
911
- </TooltipProvider>
996
+ {/* The Settings page lives at /settings — accessed via the
997
+ top sidebar nav link. The legacy bottom-right gear is gone.
998
+ This hidden Dialog block remains only to preserve handlers
999
+ the rest of the file still references. */}
1000
+ <Dialog open={false} onOpenChange={setSettingsOpen}>
912
1001
  <DialogContent className="sm:max-w-md">
913
1002
  <DialogHeader>
914
1003
  <DialogTitle className="flex items-center gap-2">
@@ -1109,25 +1198,6 @@ export function SessionsSidebar() {
1109
1198
  </Tooltip>
1110
1199
  </TooltipProvider>
1111
1200
 
1112
- {/* Settings button collapsed */}
1113
- <Dialog open={settingsOpen} onOpenChange={setSettingsOpen}>
1114
- <TooltipProvider>
1115
- <Tooltip>
1116
- <TooltipTrigger asChild>
1117
- <DialogTrigger asChild>
1118
- <Button
1119
- size="icon"
1120
- variant="ghost"
1121
- className="size-8"
1122
- >
1123
- <Settings className="size-4" />
1124
- </Button>
1125
- </DialogTrigger>
1126
- </TooltipTrigger>
1127
- <TooltipContent side="right">Settings</TooltipContent>
1128
- </Tooltip>
1129
- </TooltipProvider>
1130
- </Dialog>
1131
1201
  </div>
1132
1202
  )}
1133
1203
  </div>