@circuitwall/jarela 2.2.1 → 2.3.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 (651) hide show
  1. package/.next/standalone/.next/BUILD_ID +1 -1
  2. package/.next/standalone/.next/app-path-routes-manifest.json +6 -5
  3. package/.next/standalone/.next/build-manifest.json +2 -2
  4. package/.next/standalone/.next/prerender-manifest.json +3 -3
  5. package/.next/standalone/.next/routes-manifest.json +8 -0
  6. package/.next/standalone/.next/server/app/_global-error/page.js +68 -68
  7. package/.next/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  8. package/.next/standalone/.next/server/app/_global-error.html +1 -1
  9. package/.next/standalone/.next/server/app/_global-error.rsc +1 -1
  10. package/.next/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  11. package/.next/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  12. package/.next/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  13. package/.next/standalone/.next/server/app/_not-found/page.js +76 -76
  14. package/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  15. package/.next/standalone/.next/server/app/_not-found.html +2 -2
  16. package/.next/standalone/.next/server/app/_not-found.rsc +2 -2
  17. package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +2 -2
  18. package/.next/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +2 -2
  19. package/.next/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  20. package/.next/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  21. package/.next/standalone/.next/server/app/api/v1/access/[identity]/route.js +93 -93
  22. package/.next/standalone/.next/server/app/api/v1/access/route.js +169 -169
  23. package/.next/standalone/.next/server/app/api/v1/agents/[id]/compact/route.js +82 -56
  24. package/.next/standalone/.next/server/app/api/v1/agents/[id]/compact/route.js.nft.json +1 -1
  25. package/.next/standalone/.next/server/app/api/v1/agents/[id]/display-filters/route.js +122 -122
  26. package/.next/standalone/.next/server/app/api/v1/agents/[id]/route.js +100 -100
  27. package/.next/standalone/.next/server/app/api/v1/agents/[id]/thread/route.js +753 -753
  28. package/.next/standalone/.next/server/app/api/v1/agents/route.js +65 -65
  29. package/.next/standalone/.next/server/app/api/v1/allowed-sites/[hostname]/route.js +364 -364
  30. package/.next/standalone/.next/server/app/api/v1/allowed-sites/route.js +802 -802
  31. package/.next/standalone/.next/server/app/api/v1/artifacts/lifecycle/route.js +2 -2
  32. package/.next/standalone/.next/server/app/api/v1/attachments/files/route.js +49 -49
  33. package/.next/standalone/.next/server/app/api/v1/attachments/images/route.js +910 -910
  34. package/.next/standalone/.next/server/app/api/v1/bridges/[id]/chats/route.js +589 -16
  35. package/.next/standalone/.next/server/app/api/v1/bridges/[id]/chats/route.js.nft.json +1 -1
  36. package/.next/standalone/.next/server/app/api/v1/bridges/[id]/ignores/[remote_jid]/route.js +23 -23
  37. package/.next/standalone/.next/server/app/api/v1/bridges/[id]/ignores/route.js +30 -30
  38. package/.next/standalone/.next/server/app/api/v1/bridges/[id]/lookup/route.js +703 -130
  39. package/.next/standalone/.next/server/app/api/v1/bridges/[id]/lookup/route.js.nft.json +1 -1
  40. package/.next/standalone/.next/server/app/api/v1/bridges/[id]/pair/route.js +708 -135
  41. package/.next/standalone/.next/server/app/api/v1/bridges/[id]/pair/route.js.nft.json +1 -1
  42. package/.next/standalone/.next/server/app/api/v1/bridges/[id]/route.js +802 -229
  43. package/.next/standalone/.next/server/app/api/v1/bridges/[id]/route.js.nft.json +1 -1
  44. package/.next/standalone/.next/server/app/api/v1/bridges/[id]/routes/[route_id]/route.js +739 -739
  45. package/.next/standalone/.next/server/app/api/v1/bridges/[id]/routes/route.js +1035 -1035
  46. package/.next/standalone/.next/server/app/api/v1/bridges/[id]/status/route.js +679 -106
  47. package/.next/standalone/.next/server/app/api/v1/bridges/[id]/status/route.js.nft.json +1 -1
  48. package/.next/standalone/.next/server/app/api/v1/bridges/kinds/route.js +804 -804
  49. package/.next/standalone/.next/server/app/api/v1/bridges/route.js +700 -700
  50. package/.next/standalone/.next/server/app/api/v1/builtin-tools/route.js +9 -9
  51. package/.next/standalone/.next/server/app/api/v1/builtin-tools/route.js.nft.json +1 -1
  52. package/.next/standalone/.next/server/app/api/v1/config/route.js +85 -85
  53. package/.next/standalone/.next/server/app/api/v1/credentials/[id]/route.js +709 -709
  54. package/.next/standalone/.next/server/app/api/v1/credentials/[id]/route.js.nft.json +1 -1
  55. package/.next/standalone/.next/server/app/api/v1/credentials/route.js +2 -2
  56. package/.next/standalone/.next/server/app/api/v1/credentials/route.js.nft.json +1 -1
  57. package/.next/standalone/.next/server/app/api/v1/dashboard/currency/route.js +10 -10
  58. package/.next/standalone/.next/server/app/api/v1/dashboard/metrics/route.js +784 -784
  59. package/.next/standalone/.next/server/app/api/v1/dashboard/pricing/route.js +23 -23
  60. package/.next/standalone/.next/server/app/api/v1/dashboard/pricing-task/route.js +86 -86
  61. package/.next/standalone/.next/server/app/api/v1/dashboard/pricing-task/route.js.nft.json +1 -1
  62. package/.next/standalone/.next/server/app/api/v1/delegations/codex/[job_id]/route.js +57 -57
  63. package/.next/standalone/.next/server/app/api/v1/delegations/codex/[job_id]/route.js.nft.json +1 -1
  64. package/.next/standalone/.next/server/app/api/v1/documents/search/route.js +523 -523
  65. package/.next/standalone/.next/server/app/api/v1/documents/settings/route.js +44 -44
  66. package/.next/standalone/.next/server/app/api/v1/documents/sources/[id]/reindex/route.js +65 -65
  67. package/.next/standalone/.next/server/app/api/v1/documents/sources/[id]/reindex/route.js.nft.json +1 -1
  68. package/.next/standalone/.next/server/app/api/v1/documents/sources/[id]/route.js +122 -122
  69. package/.next/standalone/.next/server/app/api/v1/documents/sources/[id]/route.js.nft.json +1 -1
  70. package/.next/standalone/.next/server/app/api/v1/documents/sources/route.js +37 -37
  71. package/.next/standalone/.next/server/app/api/v1/documents/sources/route.js.nft.json +1 -1
  72. package/.next/standalone/.next/server/app/api/v1/env/route.js +9 -9
  73. package/.next/standalone/.next/server/app/api/v1/env-sync/allowlist/route.js +368 -368
  74. package/.next/standalone/.next/server/app/api/v1/env-sync/route.js +44 -44
  75. package/.next/standalone/.next/server/app/api/v1/events/route.js +751 -178
  76. package/.next/standalone/.next/server/app/api/v1/events/route.js.nft.json +1 -1
  77. package/.next/standalone/.next/server/app/api/v1/events/test/route.js +77 -77
  78. package/.next/standalone/.next/server/app/api/v1/extension/agents/route.js +763 -763
  79. package/.next/standalone/.next/server/app/api/v1/extension/agents/route.js.nft.json +1 -1
  80. package/.next/standalone/.next/server/app/api/v1/extension/browser/activate/route.js +44 -44
  81. package/.next/standalone/.next/server/app/api/v1/extension/browser/foreground/route.js +9 -9
  82. package/.next/standalone/.next/server/app/api/v1/extension/browser/history/route.js +65 -65
  83. package/.next/standalone/.next/server/app/api/v1/extension/browser/poll/route.js +34 -34
  84. package/.next/standalone/.next/server/app/api/v1/extension/browser/progress/route.js +204 -204
  85. package/.next/standalone/.next/server/app/api/v1/extension/browser/result/route.js +133 -133
  86. package/.next/standalone/.next/server/app/api/v1/extension/browser/retry/route.js +106 -106
  87. package/.next/standalone/.next/server/app/api/v1/extension/browser/status/route.js +114 -114
  88. package/.next/standalone/.next/server/app/api/v1/extension/browser/tabs/route.js +134 -134
  89. package/.next/standalone/.next/server/app/api/v1/extension/fill/route.js +690 -690
  90. package/.next/standalone/.next/server/app/api/v1/extension/fill/route.js.nft.json +1 -1
  91. package/.next/standalone/.next/server/app/api/v1/extension/refine/route.js +93 -93
  92. package/.next/standalone/.next/server/app/api/v1/extension/refine/route.js.nft.json +1 -1
  93. package/.next/standalone/.next/server/app/api/v1/extension/turn/route.js +9 -9
  94. package/.next/standalone/.next/server/app/api/v1/extension/turn/route.js.nft.json +1 -1
  95. package/.next/standalone/.next/server/app/api/v1/extensions/route.js +185 -185
  96. package/.next/standalone/.next/server/app/api/v1/extensions/route.js.nft.json +1 -1
  97. package/.next/standalone/.next/server/app/api/v1/extensions/tools/[name]/config/route.js +171 -171
  98. package/.next/standalone/.next/server/app/api/v1/extensions/tools/[name]/config/route.js.nft.json +1 -1
  99. package/.next/standalone/.next/server/app/api/v1/extensions/tools/[name]/route.js +396 -396
  100. package/.next/standalone/.next/server/app/api/v1/extensions/tools/[name]/route.js.nft.json +1 -1
  101. package/.next/standalone/.next/server/app/api/v1/extensions/tools/[name]/secrets/route.js +212 -212
  102. package/.next/standalone/.next/server/app/api/v1/extensions/tools/[name]/secrets/route.js.nft.json +1 -1
  103. package/.next/standalone/.next/server/app/api/v1/files/[name]/route.js +235 -235
  104. package/.next/standalone/.next/server/app/api/v1/fs/browse/route.js +26 -26
  105. package/.next/standalone/.next/server/app/api/v1/harnesses/[id]/route.js +221 -221
  106. package/.next/standalone/.next/server/app/api/v1/harnesses/default/route.js +58 -58
  107. package/.next/standalone/.next/server/app/api/v1/harnesses/route.js +72 -72
  108. package/.next/standalone/.next/server/app/api/v1/health/probes/route.js +9 -9
  109. package/.next/standalone/.next/server/app/api/v1/health/probes/route.js.nft.json +1 -1
  110. package/.next/standalone/.next/server/app/api/v1/health/route.js +772 -772
  111. package/.next/standalone/.next/server/app/api/v1/integrations/[name]/route.js +133 -133
  112. package/.next/standalone/.next/server/app/api/v1/integrations/[name]/test/route.js +9 -9
  113. package/.next/standalone/.next/server/app/api/v1/integrations/[name]/test/route.js.nft.json +1 -1
  114. package/.next/standalone/.next/server/app/api/v1/integrations/gmail/oauth/callback/route.js +363 -363
  115. package/.next/standalone/.next/server/app/api/v1/integrations/gmail/oauth/start/route.js +233 -233
  116. package/.next/standalone/.next/server/app/api/v1/integrations/gmail/oauth/status/route.js +682 -682
  117. package/.next/standalone/.next/server/app/api/v1/integrations/outlook/oauth/callback/route.js +879 -879
  118. package/.next/standalone/.next/server/app/api/v1/integrations/outlook/oauth/start/route.js +108 -108
  119. package/.next/standalone/.next/server/app/api/v1/integrations/outlook/oauth/status/route.js +952 -952
  120. package/.next/standalone/.next/server/app/api/v1/integrations/route.js +216 -216
  121. package/.next/standalone/.next/server/app/api/v1/lifecycle/adoption/route.js +864 -847
  122. package/.next/standalone/.next/server/app/api/v1/lifecycle/adoption/route.js.nft.json +1 -1
  123. package/.next/standalone/.next/server/app/api/v1/local-file/route.js +26 -26
  124. package/.next/standalone/.next/server/app/api/v1/logs/route.js +70 -70
  125. package/.next/standalone/.next/server/app/api/v1/maps/embed/route.js +72 -72
  126. package/.next/standalone/.next/server/app/api/v1/mcp-servers/[name]/route.js +979 -979
  127. package/.next/standalone/.next/server/app/api/v1/mcp-servers/registry/route.js +196 -196
  128. package/.next/standalone/.next/server/app/api/v1/mcp-servers/route.js +2 -2
  129. package/.next/standalone/.next/server/app/api/v1/memory/[namespace]/[key]/route.js +381 -381
  130. package/.next/standalone/.next/server/app/api/v1/memory/policy/route.js +79 -79
  131. package/.next/standalone/.next/server/app/api/v1/memory/route.js +51 -51
  132. package/.next/standalone/.next/server/app/api/v1/memory/search/route.js +131 -131
  133. package/.next/standalone/.next/server/app/api/v1/models/[name]/compact-threads/route.js +374 -369
  134. package/.next/standalone/.next/server/app/api/v1/models/[name]/compact-threads/route.js.nft.json +1 -1
  135. package/.next/standalone/.next/server/app/api/v1/models/[name]/route.js +143 -143
  136. package/.next/standalone/.next/server/app/api/v1/models/route.js +543 -543
  137. package/.next/standalone/.next/server/app/api/v1/packages/catalog/route.js +445 -445
  138. package/.next/standalone/.next/server/app/api/v1/packages/defaults/[id]/route.js +120 -120
  139. package/.next/standalone/.next/server/app/api/v1/packages/defaults/[id]/route.js.nft.json +1 -1
  140. package/.next/standalone/.next/server/app/api/v1/packages/install/[id]/route.js +234 -234
  141. package/.next/standalone/.next/server/app/api/v1/packages/install/[id]/route.js.nft.json +1 -1
  142. package/.next/standalone/.next/server/app/api/v1/packages/install/route.js +407 -407
  143. package/.next/standalone/.next/server/app/api/v1/packages/install/route.js.nft.json +1 -1
  144. package/.next/standalone/.next/server/app/api/v1/packages/manifests/[name]/enabled/route.js +37 -37
  145. package/.next/standalone/.next/server/app/api/v1/packages/manifests/[name]/enabled/route.js.nft.json +1 -1
  146. package/.next/standalone/.next/server/app/api/v1/packages/manifests/[name]/route.js +107 -107
  147. package/.next/standalone/.next/server/app/api/v1/packages/manifests/[name]/route.js.nft.json +1 -1
  148. package/.next/standalone/.next/server/app/api/v1/packages/manifests/route.js +228 -228
  149. package/.next/standalone/.next/server/app/api/v1/packages/manifests/route.js.nft.json +1 -1
  150. package/.next/standalone/.next/server/app/api/v1/packages/reload/route.js +9 -9
  151. package/.next/standalone/.next/server/app/api/v1/packages/reload/route.js.nft.json +1 -1
  152. package/.next/standalone/.next/server/app/api/v1/packages/route.js +148 -148
  153. package/.next/standalone/.next/server/app/api/v1/packages/route.js.nft.json +1 -1
  154. package/.next/standalone/.next/server/app/api/v1/page-capture/route.js +787 -787
  155. package/.next/standalone/.next/server/app/api/v1/page-capture/route.js.nft.json +1 -1
  156. package/.next/standalone/.next/server/app/api/v1/pending-actions/[id]/approve/route.js +507 -507
  157. package/.next/standalone/.next/server/app/api/v1/pending-actions/[id]/approve/route.js.nft.json +1 -1
  158. package/.next/standalone/.next/server/app/api/v1/pending-actions/[id]/deny/route.js +181 -181
  159. package/.next/standalone/.next/server/app/api/v1/pending-actions/[id]/deny/route.js.nft.json +1 -1
  160. package/.next/standalone/.next/server/app/api/v1/pending-actions/route.js +258 -258
  161. package/.next/standalone/.next/server/app/api/v1/pending-actions/route.js.nft.json +1 -1
  162. package/.next/standalone/.next/server/app/api/v1/profile/location/route.js +30 -30
  163. package/.next/standalone/.next/server/app/api/v1/profile/route.js +164 -164
  164. package/.next/standalone/.next/server/app/api/v1/providers/[provider]/models/route.js +44 -44
  165. package/.next/standalone/.next/server/app/api/v1/providers/[provider]/probe/route.js +9 -9
  166. package/.next/standalone/.next/server/app/api/v1/providers/github-copilot/auth/route.js +164 -164
  167. package/.next/standalone/.next/server/app/api/v1/providers/route.js +94 -94
  168. package/.next/standalone/.next/server/app/api/v1/proxy-config/route.js +450 -450
  169. package/.next/standalone/.next/server/app/api/v1/redaction/init/route.js +37 -37
  170. package/.next/standalone/.next/server/app/api/v1/redaction/route.js +58 -58
  171. package/.next/standalone/.next/server/app/api/v1/scheduled-tasks/[id]/route.js +600 -600
  172. package/.next/standalone/.next/server/app/api/v1/scheduled-tasks/[id]/run/route.js +44 -44
  173. package/.next/standalone/.next/server/app/api/v1/scheduled-tasks/[id]/run/route.js.nft.json +1 -1
  174. package/.next/standalone/.next/server/app/api/v1/scheduled-tasks/route.js +732 -732
  175. package/.next/standalone/.next/server/app/api/v1/security/idle-timeout/route.js +359 -359
  176. package/.next/standalone/.next/server/app/api/v1/security/pin/route.js +197 -197
  177. package/.next/standalone/.next/server/app/api/v1/security/state/route.js +51 -51
  178. package/.next/standalone/.next/server/app/api/v1/security/unlock/route.js +176 -176
  179. package/.next/standalone/.next/server/app/api/v1/security/verify-pin/route.js +190 -190
  180. package/.next/standalone/.next/server/app/api/v1/setup/test-key/route.js +26 -26
  181. package/.next/standalone/.next/server/app/api/v1/skills/[id]/route.js +770 -770
  182. package/.next/standalone/.next/server/app/api/v1/skills/repos/[id]/route.js +115 -115
  183. package/.next/standalone/.next/server/app/api/v1/skills/repos/route.js +327 -327
  184. package/.next/standalone/.next/server/app/api/v1/skills/route.js +870 -870
  185. package/.next/standalone/.next/server/app/api/v1/system/abort/route.js +838 -808
  186. package/.next/standalone/.next/server/app/api/v1/system/restart/route.js +177 -177
  187. package/.next/standalone/.next/server/app/api/v1/system/restart/route.js.nft.json +1 -1
  188. package/.next/standalone/.next/server/app/api/v1/tailscale/route.js +164 -164
  189. package/.next/standalone/.next/server/app/api/v1/tasks/[agent_id]/route.js +115 -115
  190. package/.next/standalone/.next/server/app/api/v1/tasks/route.js +23 -23
  191. package/.next/standalone/.next/server/app/api/v1/threads/[thread_id]/activity/route.js +1429 -0
  192. package/.next/standalone/.next/server/app/api/v1/threads/[thread_id]/activity/route.js.nft.json +1 -0
  193. package/.next/standalone/.next/server/app/api/v1/threads/[thread_id]/activity/route_client-reference-manifest.js +1 -0
  194. package/.next/standalone/.next/server/app/api/v1/threads/[thread_id]/context-pin/route.js +635 -634
  195. package/.next/standalone/.next/server/app/api/v1/threads/[thread_id]/context-pin/route.js.nft.json +1 -1
  196. package/.next/standalone/.next/server/app/api/v1/threads/[thread_id]/route.js +53 -439
  197. package/.next/standalone/.next/server/app/api/v1/threads/[thread_id]/route.js.nft.json +1 -1
  198. package/.next/standalone/.next/server/app/api/v1/threads/[thread_id]/run/route.js +172 -172
  199. package/.next/standalone/.next/server/app/api/v1/threads/[thread_id]/run/route.js.nft.json +1 -1
  200. package/.next/standalone/.next/server/app/api/v1/threads/route.js +908 -908
  201. package/.next/standalone/.next/server/app/api/v1/tools/route.js +2 -2
  202. package/.next/standalone/.next/server/app/api/v1/tools/route.js.nft.json +1 -1
  203. package/.next/standalone/.next/server/app/api/v1/update/apply/route.js +17 -17
  204. package/.next/standalone/.next/server/app/api/v1/update/apply/route.js.nft.json +1 -1
  205. package/.next/standalone/.next/server/app/api/v1/update/route.js +570 -570
  206. package/.next/standalone/.next/server/app/api/v1/voice/transcribe/route.js +224 -224
  207. package/.next/standalone/.next/server/app/api/v1/voice/tts/route.js +975 -975
  208. package/.next/standalone/.next/server/app/api/v1/watchers/[id]/route.js +23 -23
  209. package/.next/standalone/.next/server/app/api/v1/watchers/[id]/run/route.js +72 -72
  210. package/.next/standalone/.next/server/app/api/v1/watchers/[id]/run/route.js.nft.json +1 -1
  211. package/.next/standalone/.next/server/app/api/v1/watchers/reaction-scripts/route.js +128 -128
  212. package/.next/standalone/.next/server/app/api/v1/watchers/route.js +164 -164
  213. package/.next/standalone/.next/server/app/api/v1/watchers/route.js.nft.json +1 -1
  214. package/.next/standalone/.next/server/app/icon.svg/route.js +62 -62
  215. package/.next/standalone/.next/server/app/manifest.webmanifest/route.js +436 -436
  216. package/.next/standalone/.next/server/app/page.js +1243 -854
  217. package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  218. package/.next/standalone/.next/server/app/setup/page.js +91 -91
  219. package/.next/standalone/.next/server/app/setup/page_client-reference-manifest.js +1 -1
  220. package/.next/standalone/.next/server/app-paths-manifest.json +6 -5
  221. package/.next/standalone/.next/server/chunks/{424.js → 1388.js} +335 -986
  222. package/.next/standalone/.next/server/chunks/1433.js +1 -1
  223. package/.next/standalone/.next/server/chunks/1638.js +1 -2
  224. package/.next/standalone/.next/server/chunks/1738.js +1 -1
  225. package/.next/standalone/.next/server/chunks/210.js +6 -6
  226. package/.next/standalone/.next/server/chunks/2151.js +31 -1
  227. package/.next/standalone/.next/server/chunks/2207.js +1 -0
  228. package/.next/standalone/.next/server/chunks/2471.js +28 -28
  229. package/.next/standalone/.next/server/chunks/2504.js +1 -1
  230. package/.next/standalone/.next/server/chunks/2695.js +17 -17
  231. package/.next/standalone/.next/server/chunks/3042.js +14 -8
  232. package/.next/standalone/.next/server/chunks/3399.js +1 -1
  233. package/.next/standalone/.next/server/chunks/3566.js +1 -1
  234. package/.next/standalone/.next/server/chunks/4189.js +946 -0
  235. package/.next/standalone/.next/server/chunks/{9590.js → 423.js} +8 -3
  236. package/.next/standalone/.next/server/chunks/4433.js +146 -146
  237. package/.next/standalone/.next/server/chunks/4508.js +1 -1
  238. package/.next/standalone/.next/server/chunks/4588.js +1 -0
  239. package/.next/standalone/.next/server/chunks/46.js +5 -0
  240. package/.next/standalone/.next/server/chunks/466.js +12 -0
  241. package/.next/standalone/.next/server/chunks/4868.js +206 -206
  242. package/.next/standalone/.next/server/chunks/4992.js +13 -0
  243. package/.next/standalone/.next/server/chunks/5120.js +963 -0
  244. package/.next/standalone/.next/server/chunks/5701.js +1 -1
  245. package/.next/standalone/.next/server/chunks/5900.js +1 -1
  246. package/.next/standalone/.next/server/chunks/6210.js +1 -0
  247. package/.next/standalone/.next/server/chunks/6213.js +1 -1
  248. package/.next/standalone/.next/server/chunks/6649.js +2 -2
  249. package/.next/standalone/.next/server/chunks/6703.js +3 -3
  250. package/.next/standalone/.next/server/chunks/7445.js +1 -0
  251. package/.next/standalone/.next/server/chunks/8067.js +12 -0
  252. package/.next/standalone/.next/server/chunks/8461.js +14 -9
  253. package/.next/standalone/.next/server/chunks/8558.js +1 -1
  254. package/.next/standalone/.next/server/chunks/8724.js +1 -1
  255. package/.next/standalone/.next/server/chunks/8849.js +91 -91
  256. package/.next/standalone/.next/server/chunks/9032.js +6 -5
  257. package/.next/standalone/.next/server/chunks/{2563.js → 9164.js} +33173 -31461
  258. package/.next/standalone/.next/server/chunks/9237.js +396 -396
  259. package/.next/standalone/.next/server/chunks/{9640.js → 9304.js} +1628 -570
  260. package/.next/standalone/.next/server/chunks/9406.js +1 -1
  261. package/.next/standalone/.next/server/chunks/9824.js +98 -98
  262. package/.next/standalone/.next/server/chunks/9826.js +1 -0
  263. package/.next/standalone/.next/server/middleware-build-manifest.js +2 -2
  264. package/.next/standalone/.next/server/middleware.js +415 -397
  265. package/.next/standalone/.next/server/pages/404.html +2 -2
  266. package/.next/standalone/.next/server/pages/500.html +1 -1
  267. package/.next/standalone/.next/server/preview-props.json +3 -3
  268. package/.next/standalone/.next/server/server-reference-manifest.json +1 -1
  269. package/.next/standalone/.next/static/chunks/{1395-a340fb0a345382a4.js → 1395-e4a99912b8f83044.js} +13 -1
  270. package/.next/standalone/.next/static/chunks/app/_global-error/{page-36cb8b428b38b26a.js → page-6fc5f8e744c81802.js} +1 -1
  271. package/.next/standalone/.next/static/chunks/app/api/v1/access/[identity]/{route-36cb8b428b38b26a.js → route-6fc5f8e744c81802.js} +1 -1
  272. package/.next/standalone/.next/static/chunks/app/api/v1/access/{route-36cb8b428b38b26a.js → route-6fc5f8e744c81802.js} +1 -1
  273. package/.next/standalone/.next/static/chunks/app/api/v1/agents/[id]/compact/{route-36cb8b428b38b26a.js → route-6fc5f8e744c81802.js} +1 -1
  274. package/.next/standalone/.next/static/chunks/app/api/v1/agents/[id]/display-filters/route-6fc5f8e744c81802.js +17 -0
  275. package/.next/standalone/.next/static/chunks/app/api/v1/agents/[id]/route-6fc5f8e744c81802.js +17 -0
  276. package/.next/standalone/.next/static/chunks/app/api/v1/agents/[id]/thread/route-6fc5f8e744c81802.js +17 -0
  277. package/.next/standalone/.next/static/chunks/app/api/v1/agents/route-6fc5f8e744c81802.js +17 -0
  278. package/.next/standalone/.next/static/chunks/app/api/v1/allowed-sites/[hostname]/route-6fc5f8e744c81802.js +17 -0
  279. package/.next/standalone/.next/static/chunks/app/api/v1/allowed-sites/route-6fc5f8e744c81802.js +17 -0
  280. package/.next/standalone/.next/static/chunks/app/api/v1/artifacts/lifecycle/route-6fc5f8e744c81802.js +17 -0
  281. package/.next/standalone/.next/static/chunks/app/api/v1/attachments/files/route-6fc5f8e744c81802.js +17 -0
  282. package/.next/standalone/.next/static/chunks/app/api/v1/attachments/images/route-6fc5f8e744c81802.js +17 -0
  283. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/[id]/chats/route-6fc5f8e744c81802.js +17 -0
  284. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/[id]/ignores/[remote_jid]/route-6fc5f8e744c81802.js +17 -0
  285. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/[id]/ignores/route-6fc5f8e744c81802.js +17 -0
  286. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/[id]/lookup/route-6fc5f8e744c81802.js +17 -0
  287. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/[id]/pair/route-6fc5f8e744c81802.js +17 -0
  288. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/[id]/route-6fc5f8e744c81802.js +17 -0
  289. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/[id]/routes/[route_id]/route-6fc5f8e744c81802.js +17 -0
  290. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/[id]/routes/route-6fc5f8e744c81802.js +17 -0
  291. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/[id]/status/route-6fc5f8e744c81802.js +17 -0
  292. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/kinds/route-6fc5f8e744c81802.js +17 -0
  293. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/route-6fc5f8e744c81802.js +17 -0
  294. package/.next/standalone/.next/static/chunks/app/api/v1/builtin-tools/route-6fc5f8e744c81802.js +17 -0
  295. package/.next/standalone/.next/static/chunks/app/api/v1/config/route-6fc5f8e744c81802.js +17 -0
  296. package/.next/standalone/.next/static/chunks/app/api/v1/credentials/[id]/route-6fc5f8e744c81802.js +17 -0
  297. package/.next/standalone/.next/static/chunks/app/api/v1/credentials/route-6fc5f8e744c81802.js +17 -0
  298. package/.next/standalone/.next/static/chunks/app/api/v1/dashboard/currency/route-6fc5f8e744c81802.js +17 -0
  299. package/.next/standalone/.next/static/chunks/app/api/v1/dashboard/metrics/route-6fc5f8e744c81802.js +17 -0
  300. package/.next/standalone/.next/static/chunks/app/api/v1/dashboard/pricing/route-6fc5f8e744c81802.js +17 -0
  301. package/.next/standalone/.next/static/chunks/app/api/v1/dashboard/pricing-task/route-6fc5f8e744c81802.js +17 -0
  302. package/.next/standalone/.next/static/chunks/app/api/v1/delegations/codex/[job_id]/route-6fc5f8e744c81802.js +17 -0
  303. package/.next/standalone/.next/static/chunks/app/api/v1/documents/search/route-6fc5f8e744c81802.js +17 -0
  304. package/.next/standalone/.next/static/chunks/app/api/v1/documents/settings/route-6fc5f8e744c81802.js +17 -0
  305. package/.next/standalone/.next/static/chunks/app/api/v1/documents/sources/[id]/reindex/route-6fc5f8e744c81802.js +17 -0
  306. package/.next/standalone/.next/static/chunks/app/api/v1/documents/sources/[id]/route-6fc5f8e744c81802.js +17 -0
  307. package/.next/standalone/.next/static/chunks/app/api/v1/documents/sources/route-6fc5f8e744c81802.js +17 -0
  308. package/.next/standalone/.next/static/chunks/app/api/v1/env/route-6fc5f8e744c81802.js +17 -0
  309. package/.next/standalone/.next/static/chunks/app/api/v1/env-sync/allowlist/route-6fc5f8e744c81802.js +17 -0
  310. package/.next/standalone/.next/static/chunks/app/api/v1/env-sync/route-6fc5f8e744c81802.js +17 -0
  311. package/.next/standalone/.next/static/chunks/app/api/v1/events/route-6fc5f8e744c81802.js +17 -0
  312. package/.next/standalone/.next/static/chunks/app/api/v1/events/test/route-6fc5f8e744c81802.js +17 -0
  313. package/.next/standalone/.next/static/chunks/app/api/v1/extension/agents/route-6fc5f8e744c81802.js +17 -0
  314. package/.next/standalone/.next/static/chunks/app/api/v1/extension/browser/activate/route-6fc5f8e744c81802.js +17 -0
  315. package/.next/standalone/.next/static/chunks/app/api/v1/extension/browser/foreground/route-6fc5f8e744c81802.js +17 -0
  316. package/.next/standalone/.next/static/chunks/app/api/v1/extension/browser/history/route-6fc5f8e744c81802.js +17 -0
  317. package/.next/standalone/.next/static/chunks/app/api/v1/extension/browser/poll/route-6fc5f8e744c81802.js +17 -0
  318. package/.next/standalone/.next/static/chunks/app/api/v1/extension/browser/progress/route-6fc5f8e744c81802.js +17 -0
  319. package/.next/standalone/.next/static/chunks/app/api/v1/extension/browser/result/route-6fc5f8e744c81802.js +17 -0
  320. package/.next/standalone/.next/static/chunks/app/api/v1/extension/browser/retry/route-6fc5f8e744c81802.js +17 -0
  321. package/.next/standalone/.next/static/chunks/app/api/v1/extension/browser/status/route-6fc5f8e744c81802.js +17 -0
  322. package/.next/standalone/.next/static/chunks/app/api/v1/extension/browser/tabs/route-6fc5f8e744c81802.js +17 -0
  323. package/.next/standalone/.next/static/chunks/app/api/v1/extension/fill/route-6fc5f8e744c81802.js +17 -0
  324. package/.next/standalone/.next/static/chunks/app/api/v1/extension/refine/route-6fc5f8e744c81802.js +17 -0
  325. package/.next/standalone/.next/static/chunks/app/api/v1/extension/turn/route-6fc5f8e744c81802.js +17 -0
  326. package/.next/standalone/.next/static/chunks/app/api/v1/extensions/route-6fc5f8e744c81802.js +17 -0
  327. package/.next/standalone/.next/static/chunks/app/api/v1/extensions/tools/[name]/config/route-6fc5f8e744c81802.js +17 -0
  328. package/.next/standalone/.next/static/chunks/app/api/v1/extensions/tools/[name]/route-6fc5f8e744c81802.js +17 -0
  329. package/.next/standalone/.next/static/chunks/app/api/v1/extensions/tools/[name]/secrets/route-6fc5f8e744c81802.js +17 -0
  330. package/.next/standalone/.next/static/chunks/app/api/v1/files/[name]/route-6fc5f8e744c81802.js +17 -0
  331. package/.next/standalone/.next/static/chunks/app/api/v1/fs/browse/route-6fc5f8e744c81802.js +17 -0
  332. package/.next/standalone/.next/static/chunks/app/api/v1/harnesses/[id]/route-6fc5f8e744c81802.js +17 -0
  333. package/.next/standalone/.next/static/chunks/app/api/v1/harnesses/default/route-6fc5f8e744c81802.js +17 -0
  334. package/.next/standalone/.next/static/chunks/app/api/v1/harnesses/route-6fc5f8e744c81802.js +17 -0
  335. package/.next/standalone/.next/static/chunks/app/api/v1/health/probes/route-6fc5f8e744c81802.js +17 -0
  336. package/.next/standalone/.next/static/chunks/app/api/v1/health/route-6fc5f8e744c81802.js +17 -0
  337. package/.next/standalone/.next/static/chunks/app/api/v1/integrations/[name]/route-6fc5f8e744c81802.js +17 -0
  338. package/.next/standalone/.next/static/chunks/app/api/v1/integrations/[name]/test/route-6fc5f8e744c81802.js +17 -0
  339. package/.next/standalone/.next/static/chunks/app/api/v1/integrations/gmail/oauth/callback/route-6fc5f8e744c81802.js +17 -0
  340. package/.next/standalone/.next/static/chunks/app/api/v1/integrations/gmail/oauth/start/route-6fc5f8e744c81802.js +17 -0
  341. package/.next/standalone/.next/static/chunks/app/api/v1/integrations/gmail/oauth/status/route-6fc5f8e744c81802.js +17 -0
  342. package/.next/standalone/.next/static/chunks/app/api/v1/integrations/outlook/oauth/callback/route-6fc5f8e744c81802.js +17 -0
  343. package/.next/standalone/.next/static/chunks/app/api/v1/integrations/outlook/oauth/start/route-6fc5f8e744c81802.js +17 -0
  344. package/.next/standalone/.next/static/chunks/app/api/v1/integrations/outlook/oauth/status/route-6fc5f8e744c81802.js +17 -0
  345. package/.next/standalone/.next/static/chunks/app/api/v1/integrations/route-6fc5f8e744c81802.js +17 -0
  346. package/.next/standalone/.next/static/chunks/app/api/v1/lifecycle/adoption/route-6fc5f8e744c81802.js +17 -0
  347. package/.next/standalone/.next/static/chunks/app/api/v1/local-file/route-6fc5f8e744c81802.js +17 -0
  348. package/.next/standalone/.next/static/chunks/app/api/v1/logs/route-6fc5f8e744c81802.js +17 -0
  349. package/.next/standalone/.next/static/chunks/app/api/v1/maps/embed/route-6fc5f8e744c81802.js +17 -0
  350. package/.next/standalone/.next/static/chunks/app/api/v1/mcp-servers/[name]/route-6fc5f8e744c81802.js +17 -0
  351. package/.next/standalone/.next/static/chunks/app/api/v1/mcp-servers/registry/route-6fc5f8e744c81802.js +17 -0
  352. package/.next/standalone/.next/static/chunks/app/api/v1/mcp-servers/route-6fc5f8e744c81802.js +17 -0
  353. package/.next/standalone/.next/static/chunks/app/api/v1/memory/[namespace]/[key]/route-6fc5f8e744c81802.js +17 -0
  354. package/.next/standalone/.next/static/chunks/app/api/v1/memory/policy/route-6fc5f8e744c81802.js +17 -0
  355. package/.next/standalone/.next/static/chunks/app/api/v1/memory/route-6fc5f8e744c81802.js +17 -0
  356. package/.next/standalone/.next/static/chunks/app/api/v1/memory/search/route-6fc5f8e744c81802.js +17 -0
  357. package/.next/standalone/.next/static/chunks/app/api/v1/models/[name]/compact-threads/route-6fc5f8e744c81802.js +17 -0
  358. package/.next/standalone/.next/static/chunks/app/api/v1/models/[name]/route-6fc5f8e744c81802.js +17 -0
  359. package/.next/standalone/.next/static/chunks/app/api/v1/models/route-6fc5f8e744c81802.js +17 -0
  360. package/.next/standalone/.next/static/chunks/app/api/v1/packages/catalog/route-6fc5f8e744c81802.js +17 -0
  361. package/.next/standalone/.next/static/chunks/app/api/v1/packages/defaults/[id]/route-6fc5f8e744c81802.js +17 -0
  362. package/.next/standalone/.next/static/chunks/app/api/v1/packages/install/[id]/route-6fc5f8e744c81802.js +17 -0
  363. package/.next/standalone/.next/static/chunks/app/api/v1/packages/install/route-6fc5f8e744c81802.js +17 -0
  364. package/.next/standalone/.next/static/chunks/app/api/v1/packages/manifests/[name]/enabled/route-6fc5f8e744c81802.js +17 -0
  365. package/.next/standalone/.next/static/chunks/app/api/v1/packages/manifests/[name]/route-6fc5f8e744c81802.js +17 -0
  366. package/.next/standalone/.next/static/chunks/app/api/v1/packages/manifests/route-6fc5f8e744c81802.js +17 -0
  367. package/.next/standalone/.next/static/chunks/app/api/v1/packages/reload/route-6fc5f8e744c81802.js +17 -0
  368. package/.next/standalone/.next/static/chunks/app/api/v1/packages/route-6fc5f8e744c81802.js +17 -0
  369. package/.next/standalone/.next/static/chunks/app/api/v1/page-capture/route-6fc5f8e744c81802.js +17 -0
  370. package/.next/standalone/.next/static/chunks/app/api/v1/pending-actions/[id]/approve/route-6fc5f8e744c81802.js +17 -0
  371. package/.next/standalone/.next/static/chunks/app/api/v1/pending-actions/[id]/deny/route-6fc5f8e744c81802.js +17 -0
  372. package/.next/standalone/.next/static/chunks/app/api/v1/pending-actions/route-6fc5f8e744c81802.js +17 -0
  373. package/.next/standalone/.next/static/chunks/app/api/v1/profile/location/route-6fc5f8e744c81802.js +17 -0
  374. package/.next/standalone/.next/static/chunks/app/api/v1/profile/route-6fc5f8e744c81802.js +17 -0
  375. package/.next/standalone/.next/static/chunks/app/api/v1/providers/[provider]/models/route-6fc5f8e744c81802.js +17 -0
  376. package/.next/standalone/.next/static/chunks/app/api/v1/providers/[provider]/probe/route-6fc5f8e744c81802.js +17 -0
  377. package/.next/standalone/.next/static/chunks/app/api/v1/providers/github-copilot/auth/route-6fc5f8e744c81802.js +17 -0
  378. package/.next/standalone/.next/static/chunks/app/api/v1/providers/route-6fc5f8e744c81802.js +17 -0
  379. package/.next/standalone/.next/static/chunks/app/api/v1/proxy-config/route-6fc5f8e744c81802.js +17 -0
  380. package/.next/standalone/.next/static/chunks/app/api/v1/redaction/init/route-6fc5f8e744c81802.js +17 -0
  381. package/.next/standalone/.next/static/chunks/app/api/v1/redaction/route-6fc5f8e744c81802.js +17 -0
  382. package/.next/standalone/.next/static/chunks/app/api/v1/scheduled-tasks/[id]/route-6fc5f8e744c81802.js +17 -0
  383. package/.next/standalone/.next/static/chunks/app/api/v1/scheduled-tasks/[id]/run/route-6fc5f8e744c81802.js +17 -0
  384. package/.next/standalone/.next/static/chunks/app/api/v1/scheduled-tasks/route-6fc5f8e744c81802.js +17 -0
  385. package/.next/standalone/.next/static/chunks/app/api/v1/security/idle-timeout/route-6fc5f8e744c81802.js +17 -0
  386. package/.next/standalone/.next/static/chunks/app/api/v1/security/pin/route-6fc5f8e744c81802.js +17 -0
  387. package/.next/standalone/.next/static/chunks/app/api/v1/security/state/route-6fc5f8e744c81802.js +17 -0
  388. package/.next/standalone/.next/static/chunks/app/api/v1/security/unlock/route-6fc5f8e744c81802.js +17 -0
  389. package/.next/standalone/.next/static/chunks/app/api/v1/security/verify-pin/route-6fc5f8e744c81802.js +17 -0
  390. package/.next/standalone/.next/static/chunks/app/api/v1/setup/test-key/route-6fc5f8e744c81802.js +17 -0
  391. package/.next/standalone/.next/static/chunks/app/api/v1/skills/[id]/route-6fc5f8e744c81802.js +17 -0
  392. package/.next/standalone/.next/static/chunks/app/api/v1/skills/repos/[id]/route-6fc5f8e744c81802.js +17 -0
  393. package/.next/standalone/.next/static/chunks/app/api/v1/skills/repos/route-6fc5f8e744c81802.js +17 -0
  394. package/.next/standalone/.next/static/chunks/app/api/v1/skills/route-6fc5f8e744c81802.js +17 -0
  395. package/.next/standalone/.next/static/chunks/app/api/v1/system/abort/route-6fc5f8e744c81802.js +17 -0
  396. package/.next/standalone/.next/static/chunks/app/api/v1/system/restart/route-6fc5f8e744c81802.js +17 -0
  397. package/.next/standalone/.next/static/chunks/app/api/v1/tailscale/route-6fc5f8e744c81802.js +17 -0
  398. package/.next/standalone/.next/static/chunks/app/api/v1/tasks/[agent_id]/route-6fc5f8e744c81802.js +17 -0
  399. package/.next/standalone/.next/static/chunks/app/api/v1/tasks/route-6fc5f8e744c81802.js +17 -0
  400. package/.next/standalone/.next/static/chunks/app/api/v1/threads/[thread_id]/activity/route-6fc5f8e744c81802.js +17 -0
  401. package/.next/standalone/.next/static/chunks/app/api/v1/threads/[thread_id]/context-pin/route-6fc5f8e744c81802.js +17 -0
  402. package/.next/standalone/.next/static/chunks/app/api/v1/threads/[thread_id]/route-6fc5f8e744c81802.js +17 -0
  403. package/.next/standalone/.next/static/chunks/app/api/v1/threads/[thread_id]/run/route-6fc5f8e744c81802.js +17 -0
  404. package/.next/standalone/.next/static/chunks/app/api/v1/threads/route-6fc5f8e744c81802.js +17 -0
  405. package/.next/standalone/.next/static/chunks/app/api/v1/tools/route-6fc5f8e744c81802.js +17 -0
  406. package/.next/standalone/.next/static/chunks/app/api/v1/update/apply/route-6fc5f8e744c81802.js +17 -0
  407. package/.next/standalone/.next/static/chunks/app/api/v1/update/route-6fc5f8e744c81802.js +17 -0
  408. package/.next/standalone/.next/static/chunks/app/api/v1/voice/transcribe/route-6fc5f8e744c81802.js +17 -0
  409. package/.next/standalone/.next/static/chunks/app/api/v1/voice/tts/route-6fc5f8e744c81802.js +17 -0
  410. package/.next/standalone/.next/static/chunks/app/api/v1/watchers/[id]/route-6fc5f8e744c81802.js +17 -0
  411. package/.next/standalone/.next/static/chunks/app/api/v1/watchers/[id]/run/route-6fc5f8e744c81802.js +17 -0
  412. package/.next/standalone/.next/static/chunks/app/api/v1/watchers/reaction-scripts/route-6fc5f8e744c81802.js +17 -0
  413. package/.next/standalone/.next/static/chunks/app/api/v1/watchers/route-6fc5f8e744c81802.js +17 -0
  414. package/.next/standalone/.next/static/chunks/app/manifest.webmanifest/route-6fc5f8e744c81802.js +17 -0
  415. package/.next/standalone/.next/static/chunks/app/{page-7017f07f8a7a083c.js → page-213a623b37226452.js} +1041 -652
  416. package/.next/standalone/.next/static/chunks/next/dist/client/components/builtin/app-error-6fc5f8e744c81802.js +17 -0
  417. package/.next/standalone/.next/static/chunks/next/dist/client/components/builtin/forbidden-6fc5f8e744c81802.js +17 -0
  418. package/.next/standalone/.next/static/chunks/next/dist/client/components/builtin/not-found-6fc5f8e744c81802.js +17 -0
  419. package/.next/standalone/.next/static/chunks/next/dist/client/components/builtin/unauthorized-6fc5f8e744c81802.js +17 -0
  420. package/.next/standalone/.next/static/css/{d80058f0b9b41c09.css → 312542a5725ba0d5.css} +2 -2
  421. package/.next/standalone/docs/adoption/changesets.json +309 -0
  422. package/.next/standalone/lib/skills/builtins/memory-organization/SKILL.md +16 -0
  423. package/.next/standalone/package.json +3 -3
  424. package/CHANGELOG.md +25 -0
  425. package/api/client.ts +9 -0
  426. package/api/types.ts +29 -0
  427. package/app/api/v1/lifecycle/adoption/route.ts +14 -2
  428. package/app/api/v1/models/[name]/compact-threads/route.ts +14 -11
  429. package/app/api/v1/threads/[thread_id]/activity/route.ts +19 -0
  430. package/app/api/v1/threads/[thread_id]/context-pin/route.test.ts +1 -0
  431. package/app/api/v1/threads/[thread_id]/context-pin/route.ts +2 -1
  432. package/app/api/v1/threads/[thread_id]/route.ts +5 -1
  433. package/components/chat/ChatView.tsx +52 -11
  434. package/components/chat/ContextBoundary.test.tsx +68 -1
  435. package/components/chat/ContextBoundary.tsx +92 -13
  436. package/components/chat/MessageList.test.tsx +31 -0
  437. package/components/chat/MessageList.tsx +49 -28
  438. package/components/chat/ToolList.test.tsx +92 -16
  439. package/components/chat/ToolList.tsx +59 -4
  440. package/components/chat/chat-helpers.test.tsx +24 -1
  441. package/components/chat/chat-helpers.ts +47 -4
  442. package/components/chat/useThreadActivity.test.tsx +113 -0
  443. package/components/chat/useThreadActivity.ts +94 -0
  444. package/components/chat/useThreadData.ts +16 -16
  445. package/components/chat/workflow-step-retry.ts +25 -0
  446. package/components/ui/BootScreen.tsx +17 -0
  447. package/components/ui/WorkflowChecklist.tsx +71 -33
  448. package/hooks/useSSE.ts +28 -3
  449. package/lib/agents/compaction-pipeline.test.ts +202 -0
  450. package/lib/agents/compaction-pipeline.ts +483 -0
  451. package/lib/agents/conversation-summary.ts +37 -21
  452. package/lib/agents/prepare/history-window.test.ts +18 -0
  453. package/lib/agents/prepare/history-window.ts +11 -2
  454. package/lib/agents/prepare/request.ts +4 -0
  455. package/lib/agents/prepare/system-prompt.test.ts +39 -0
  456. package/lib/agents/prepare/system-prompt.ts +8 -3
  457. package/lib/agents/prompt-registry.test.ts +5 -140
  458. package/lib/agents/prompt-registry.ts +45 -1
  459. package/lib/agents/prompt-variants.ts +146 -0
  460. package/lib/agents/run-registry.test.ts +22 -0
  461. package/lib/agents/run-registry.ts +29 -0
  462. package/lib/agents/run-thread.retry.test.ts +67 -1
  463. package/lib/agents/run-thread.ts +86 -1
  464. package/lib/agents/thread-activity.test.ts +31 -0
  465. package/lib/agents/thread-activity.ts +27 -0
  466. package/lib/agents/thread-compaction-state.test.ts +82 -0
  467. package/lib/agents/thread-compaction-state.ts +121 -0
  468. package/lib/agents/thread-compaction.test.ts +83 -4
  469. package/lib/agents/thread-compaction.ts +34 -11
  470. package/lib/agents/warm-summary-background.test.ts +219 -5
  471. package/lib/agents/warm-summary-background.ts +325 -142
  472. package/lib/agents/warm-topics.test.ts +37 -0
  473. package/lib/agents/warm-topics.ts +297 -0
  474. package/lib/agents/workflow-step-retry.test.ts +96 -0
  475. package/lib/agents/workflow-step-retry.ts +216 -0
  476. package/lib/api/browser-control.ts +0 -3
  477. package/lib/db/migrations.ts +5 -0
  478. package/lib/env/config.ts +2 -0
  479. package/lib/env/schema.ts +12 -0
  480. package/lib/lifecycle/changeset-build.test.ts +93 -0
  481. package/lib/lifecycle/changeset-build.ts +210 -0
  482. package/lib/lifecycle/changesets.test.ts +101 -0
  483. package/lib/lifecycle/changesets.ts +166 -0
  484. package/lib/lifecycle/surface-collect.test.ts +88 -0
  485. package/lib/lifecycle/surface-collect.ts +64 -0
  486. package/lib/lifecycle/surface-snapshot.test.ts +104 -0
  487. package/lib/lifecycle/surface-snapshot.ts +210 -0
  488. package/lib/memory/record.ts +0 -2
  489. package/lib/providers/external.ts +0 -2
  490. package/lib/skills/builtins/memory-organization/SKILL.md +16 -0
  491. package/lib/stores/threads.test.ts +9 -0
  492. package/lib/stores/threads.ts +21 -11
  493. package/lib/stores/version-adoption.test.ts +96 -0
  494. package/lib/stores/version-adoption.ts +239 -26
  495. package/lib/stores/workflow-progress.ts +3 -0
  496. package/lib/tools/communications/ms-todo.ts +0 -7
  497. package/lib/tools/general/memory.ts +1 -1
  498. package/lib/tools/general/workflow-progress.ts +2 -0
  499. package/lib/tools/runtime/catalog.ts +1 -25
  500. package/lib/triggers/registry.ts +0 -4
  501. package/package.json +3 -3
  502. package/scripts/install-to-system.ps1 +39 -11
  503. package/scripts/install-to-system.sh +37 -3
  504. package/.next/standalone/.next/server/chunks/3979.js +0 -581
  505. package/.next/standalone/.next/server/chunks/5936.js +0 -594
  506. package/.next/standalone/.next/static/chunks/app/api/v1/agents/[id]/display-filters/route-36cb8b428b38b26a.js +0 -17
  507. package/.next/standalone/.next/static/chunks/app/api/v1/agents/[id]/route-36cb8b428b38b26a.js +0 -17
  508. package/.next/standalone/.next/static/chunks/app/api/v1/agents/[id]/thread/route-36cb8b428b38b26a.js +0 -17
  509. package/.next/standalone/.next/static/chunks/app/api/v1/agents/route-36cb8b428b38b26a.js +0 -17
  510. package/.next/standalone/.next/static/chunks/app/api/v1/allowed-sites/[hostname]/route-36cb8b428b38b26a.js +0 -17
  511. package/.next/standalone/.next/static/chunks/app/api/v1/allowed-sites/route-36cb8b428b38b26a.js +0 -17
  512. package/.next/standalone/.next/static/chunks/app/api/v1/artifacts/lifecycle/route-36cb8b428b38b26a.js +0 -17
  513. package/.next/standalone/.next/static/chunks/app/api/v1/attachments/files/route-36cb8b428b38b26a.js +0 -17
  514. package/.next/standalone/.next/static/chunks/app/api/v1/attachments/images/route-36cb8b428b38b26a.js +0 -17
  515. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/[id]/chats/route-36cb8b428b38b26a.js +0 -17
  516. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/[id]/ignores/[remote_jid]/route-36cb8b428b38b26a.js +0 -17
  517. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/[id]/ignores/route-36cb8b428b38b26a.js +0 -17
  518. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/[id]/lookup/route-36cb8b428b38b26a.js +0 -17
  519. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/[id]/pair/route-36cb8b428b38b26a.js +0 -17
  520. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/[id]/route-36cb8b428b38b26a.js +0 -17
  521. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/[id]/routes/[route_id]/route-36cb8b428b38b26a.js +0 -17
  522. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/[id]/routes/route-36cb8b428b38b26a.js +0 -17
  523. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/[id]/status/route-36cb8b428b38b26a.js +0 -17
  524. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/kinds/route-36cb8b428b38b26a.js +0 -17
  525. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/route-36cb8b428b38b26a.js +0 -17
  526. package/.next/standalone/.next/static/chunks/app/api/v1/builtin-tools/route-36cb8b428b38b26a.js +0 -17
  527. package/.next/standalone/.next/static/chunks/app/api/v1/config/route-36cb8b428b38b26a.js +0 -17
  528. package/.next/standalone/.next/static/chunks/app/api/v1/credentials/[id]/route-36cb8b428b38b26a.js +0 -17
  529. package/.next/standalone/.next/static/chunks/app/api/v1/credentials/route-36cb8b428b38b26a.js +0 -17
  530. package/.next/standalone/.next/static/chunks/app/api/v1/dashboard/currency/route-36cb8b428b38b26a.js +0 -17
  531. package/.next/standalone/.next/static/chunks/app/api/v1/dashboard/metrics/route-36cb8b428b38b26a.js +0 -17
  532. package/.next/standalone/.next/static/chunks/app/api/v1/dashboard/pricing/route-36cb8b428b38b26a.js +0 -17
  533. package/.next/standalone/.next/static/chunks/app/api/v1/dashboard/pricing-task/route-36cb8b428b38b26a.js +0 -17
  534. package/.next/standalone/.next/static/chunks/app/api/v1/delegations/codex/[job_id]/route-36cb8b428b38b26a.js +0 -17
  535. package/.next/standalone/.next/static/chunks/app/api/v1/documents/search/route-36cb8b428b38b26a.js +0 -17
  536. package/.next/standalone/.next/static/chunks/app/api/v1/documents/settings/route-36cb8b428b38b26a.js +0 -17
  537. package/.next/standalone/.next/static/chunks/app/api/v1/documents/sources/[id]/reindex/route-36cb8b428b38b26a.js +0 -17
  538. package/.next/standalone/.next/static/chunks/app/api/v1/documents/sources/[id]/route-36cb8b428b38b26a.js +0 -17
  539. package/.next/standalone/.next/static/chunks/app/api/v1/documents/sources/route-36cb8b428b38b26a.js +0 -17
  540. package/.next/standalone/.next/static/chunks/app/api/v1/env/route-36cb8b428b38b26a.js +0 -17
  541. package/.next/standalone/.next/static/chunks/app/api/v1/env-sync/allowlist/route-36cb8b428b38b26a.js +0 -17
  542. package/.next/standalone/.next/static/chunks/app/api/v1/env-sync/route-36cb8b428b38b26a.js +0 -17
  543. package/.next/standalone/.next/static/chunks/app/api/v1/events/route-36cb8b428b38b26a.js +0 -17
  544. package/.next/standalone/.next/static/chunks/app/api/v1/events/test/route-36cb8b428b38b26a.js +0 -17
  545. package/.next/standalone/.next/static/chunks/app/api/v1/extension/agents/route-36cb8b428b38b26a.js +0 -17
  546. package/.next/standalone/.next/static/chunks/app/api/v1/extension/browser/activate/route-36cb8b428b38b26a.js +0 -17
  547. package/.next/standalone/.next/static/chunks/app/api/v1/extension/browser/foreground/route-36cb8b428b38b26a.js +0 -17
  548. package/.next/standalone/.next/static/chunks/app/api/v1/extension/browser/history/route-36cb8b428b38b26a.js +0 -17
  549. package/.next/standalone/.next/static/chunks/app/api/v1/extension/browser/poll/route-36cb8b428b38b26a.js +0 -17
  550. package/.next/standalone/.next/static/chunks/app/api/v1/extension/browser/progress/route-36cb8b428b38b26a.js +0 -17
  551. package/.next/standalone/.next/static/chunks/app/api/v1/extension/browser/result/route-36cb8b428b38b26a.js +0 -17
  552. package/.next/standalone/.next/static/chunks/app/api/v1/extension/browser/retry/route-36cb8b428b38b26a.js +0 -17
  553. package/.next/standalone/.next/static/chunks/app/api/v1/extension/browser/status/route-36cb8b428b38b26a.js +0 -17
  554. package/.next/standalone/.next/static/chunks/app/api/v1/extension/browser/tabs/route-36cb8b428b38b26a.js +0 -17
  555. package/.next/standalone/.next/static/chunks/app/api/v1/extension/fill/route-36cb8b428b38b26a.js +0 -17
  556. package/.next/standalone/.next/static/chunks/app/api/v1/extension/refine/route-36cb8b428b38b26a.js +0 -17
  557. package/.next/standalone/.next/static/chunks/app/api/v1/extension/turn/route-36cb8b428b38b26a.js +0 -17
  558. package/.next/standalone/.next/static/chunks/app/api/v1/extensions/route-36cb8b428b38b26a.js +0 -17
  559. package/.next/standalone/.next/static/chunks/app/api/v1/extensions/tools/[name]/config/route-36cb8b428b38b26a.js +0 -17
  560. package/.next/standalone/.next/static/chunks/app/api/v1/extensions/tools/[name]/route-36cb8b428b38b26a.js +0 -17
  561. package/.next/standalone/.next/static/chunks/app/api/v1/extensions/tools/[name]/secrets/route-36cb8b428b38b26a.js +0 -17
  562. package/.next/standalone/.next/static/chunks/app/api/v1/files/[name]/route-36cb8b428b38b26a.js +0 -17
  563. package/.next/standalone/.next/static/chunks/app/api/v1/fs/browse/route-36cb8b428b38b26a.js +0 -17
  564. package/.next/standalone/.next/static/chunks/app/api/v1/harnesses/[id]/route-36cb8b428b38b26a.js +0 -17
  565. package/.next/standalone/.next/static/chunks/app/api/v1/harnesses/default/route-36cb8b428b38b26a.js +0 -17
  566. package/.next/standalone/.next/static/chunks/app/api/v1/harnesses/route-36cb8b428b38b26a.js +0 -17
  567. package/.next/standalone/.next/static/chunks/app/api/v1/health/probes/route-36cb8b428b38b26a.js +0 -17
  568. package/.next/standalone/.next/static/chunks/app/api/v1/health/route-36cb8b428b38b26a.js +0 -17
  569. package/.next/standalone/.next/static/chunks/app/api/v1/integrations/[name]/route-36cb8b428b38b26a.js +0 -17
  570. package/.next/standalone/.next/static/chunks/app/api/v1/integrations/[name]/test/route-36cb8b428b38b26a.js +0 -17
  571. package/.next/standalone/.next/static/chunks/app/api/v1/integrations/gmail/oauth/callback/route-36cb8b428b38b26a.js +0 -17
  572. package/.next/standalone/.next/static/chunks/app/api/v1/integrations/gmail/oauth/start/route-36cb8b428b38b26a.js +0 -17
  573. package/.next/standalone/.next/static/chunks/app/api/v1/integrations/gmail/oauth/status/route-36cb8b428b38b26a.js +0 -17
  574. package/.next/standalone/.next/static/chunks/app/api/v1/integrations/outlook/oauth/callback/route-36cb8b428b38b26a.js +0 -17
  575. package/.next/standalone/.next/static/chunks/app/api/v1/integrations/outlook/oauth/start/route-36cb8b428b38b26a.js +0 -17
  576. package/.next/standalone/.next/static/chunks/app/api/v1/integrations/outlook/oauth/status/route-36cb8b428b38b26a.js +0 -17
  577. package/.next/standalone/.next/static/chunks/app/api/v1/integrations/route-36cb8b428b38b26a.js +0 -17
  578. package/.next/standalone/.next/static/chunks/app/api/v1/lifecycle/adoption/route-36cb8b428b38b26a.js +0 -17
  579. package/.next/standalone/.next/static/chunks/app/api/v1/local-file/route-36cb8b428b38b26a.js +0 -17
  580. package/.next/standalone/.next/static/chunks/app/api/v1/logs/route-36cb8b428b38b26a.js +0 -17
  581. package/.next/standalone/.next/static/chunks/app/api/v1/maps/embed/route-36cb8b428b38b26a.js +0 -17
  582. package/.next/standalone/.next/static/chunks/app/api/v1/mcp-servers/[name]/route-36cb8b428b38b26a.js +0 -17
  583. package/.next/standalone/.next/static/chunks/app/api/v1/mcp-servers/registry/route-36cb8b428b38b26a.js +0 -17
  584. package/.next/standalone/.next/static/chunks/app/api/v1/mcp-servers/route-36cb8b428b38b26a.js +0 -17
  585. package/.next/standalone/.next/static/chunks/app/api/v1/memory/[namespace]/[key]/route-36cb8b428b38b26a.js +0 -17
  586. package/.next/standalone/.next/static/chunks/app/api/v1/memory/policy/route-36cb8b428b38b26a.js +0 -17
  587. package/.next/standalone/.next/static/chunks/app/api/v1/memory/route-36cb8b428b38b26a.js +0 -17
  588. package/.next/standalone/.next/static/chunks/app/api/v1/memory/search/route-36cb8b428b38b26a.js +0 -17
  589. package/.next/standalone/.next/static/chunks/app/api/v1/models/[name]/compact-threads/route-36cb8b428b38b26a.js +0 -17
  590. package/.next/standalone/.next/static/chunks/app/api/v1/models/[name]/route-36cb8b428b38b26a.js +0 -17
  591. package/.next/standalone/.next/static/chunks/app/api/v1/models/route-36cb8b428b38b26a.js +0 -17
  592. package/.next/standalone/.next/static/chunks/app/api/v1/packages/catalog/route-36cb8b428b38b26a.js +0 -17
  593. package/.next/standalone/.next/static/chunks/app/api/v1/packages/defaults/[id]/route-36cb8b428b38b26a.js +0 -17
  594. package/.next/standalone/.next/static/chunks/app/api/v1/packages/install/[id]/route-36cb8b428b38b26a.js +0 -17
  595. package/.next/standalone/.next/static/chunks/app/api/v1/packages/install/route-36cb8b428b38b26a.js +0 -17
  596. package/.next/standalone/.next/static/chunks/app/api/v1/packages/manifests/[name]/enabled/route-36cb8b428b38b26a.js +0 -17
  597. package/.next/standalone/.next/static/chunks/app/api/v1/packages/manifests/[name]/route-36cb8b428b38b26a.js +0 -17
  598. package/.next/standalone/.next/static/chunks/app/api/v1/packages/manifests/route-36cb8b428b38b26a.js +0 -17
  599. package/.next/standalone/.next/static/chunks/app/api/v1/packages/reload/route-36cb8b428b38b26a.js +0 -17
  600. package/.next/standalone/.next/static/chunks/app/api/v1/packages/route-36cb8b428b38b26a.js +0 -17
  601. package/.next/standalone/.next/static/chunks/app/api/v1/page-capture/route-36cb8b428b38b26a.js +0 -17
  602. package/.next/standalone/.next/static/chunks/app/api/v1/pending-actions/[id]/approve/route-36cb8b428b38b26a.js +0 -17
  603. package/.next/standalone/.next/static/chunks/app/api/v1/pending-actions/[id]/deny/route-36cb8b428b38b26a.js +0 -17
  604. package/.next/standalone/.next/static/chunks/app/api/v1/pending-actions/route-36cb8b428b38b26a.js +0 -17
  605. package/.next/standalone/.next/static/chunks/app/api/v1/profile/location/route-36cb8b428b38b26a.js +0 -17
  606. package/.next/standalone/.next/static/chunks/app/api/v1/profile/route-36cb8b428b38b26a.js +0 -17
  607. package/.next/standalone/.next/static/chunks/app/api/v1/providers/[provider]/models/route-36cb8b428b38b26a.js +0 -17
  608. package/.next/standalone/.next/static/chunks/app/api/v1/providers/[provider]/probe/route-36cb8b428b38b26a.js +0 -17
  609. package/.next/standalone/.next/static/chunks/app/api/v1/providers/github-copilot/auth/route-36cb8b428b38b26a.js +0 -17
  610. package/.next/standalone/.next/static/chunks/app/api/v1/providers/route-36cb8b428b38b26a.js +0 -17
  611. package/.next/standalone/.next/static/chunks/app/api/v1/proxy-config/route-36cb8b428b38b26a.js +0 -17
  612. package/.next/standalone/.next/static/chunks/app/api/v1/redaction/init/route-36cb8b428b38b26a.js +0 -17
  613. package/.next/standalone/.next/static/chunks/app/api/v1/redaction/route-36cb8b428b38b26a.js +0 -17
  614. package/.next/standalone/.next/static/chunks/app/api/v1/scheduled-tasks/[id]/route-36cb8b428b38b26a.js +0 -17
  615. package/.next/standalone/.next/static/chunks/app/api/v1/scheduled-tasks/[id]/run/route-36cb8b428b38b26a.js +0 -17
  616. package/.next/standalone/.next/static/chunks/app/api/v1/scheduled-tasks/route-36cb8b428b38b26a.js +0 -17
  617. package/.next/standalone/.next/static/chunks/app/api/v1/security/idle-timeout/route-36cb8b428b38b26a.js +0 -17
  618. package/.next/standalone/.next/static/chunks/app/api/v1/security/pin/route-36cb8b428b38b26a.js +0 -17
  619. package/.next/standalone/.next/static/chunks/app/api/v1/security/state/route-36cb8b428b38b26a.js +0 -17
  620. package/.next/standalone/.next/static/chunks/app/api/v1/security/unlock/route-36cb8b428b38b26a.js +0 -17
  621. package/.next/standalone/.next/static/chunks/app/api/v1/security/verify-pin/route-36cb8b428b38b26a.js +0 -17
  622. package/.next/standalone/.next/static/chunks/app/api/v1/setup/test-key/route-36cb8b428b38b26a.js +0 -17
  623. package/.next/standalone/.next/static/chunks/app/api/v1/skills/[id]/route-36cb8b428b38b26a.js +0 -17
  624. package/.next/standalone/.next/static/chunks/app/api/v1/skills/repos/[id]/route-36cb8b428b38b26a.js +0 -17
  625. package/.next/standalone/.next/static/chunks/app/api/v1/skills/repos/route-36cb8b428b38b26a.js +0 -17
  626. package/.next/standalone/.next/static/chunks/app/api/v1/skills/route-36cb8b428b38b26a.js +0 -17
  627. package/.next/standalone/.next/static/chunks/app/api/v1/system/abort/route-36cb8b428b38b26a.js +0 -17
  628. package/.next/standalone/.next/static/chunks/app/api/v1/system/restart/route-36cb8b428b38b26a.js +0 -17
  629. package/.next/standalone/.next/static/chunks/app/api/v1/tailscale/route-36cb8b428b38b26a.js +0 -17
  630. package/.next/standalone/.next/static/chunks/app/api/v1/tasks/[agent_id]/route-36cb8b428b38b26a.js +0 -17
  631. package/.next/standalone/.next/static/chunks/app/api/v1/tasks/route-36cb8b428b38b26a.js +0 -17
  632. package/.next/standalone/.next/static/chunks/app/api/v1/threads/[thread_id]/context-pin/route-36cb8b428b38b26a.js +0 -17
  633. package/.next/standalone/.next/static/chunks/app/api/v1/threads/[thread_id]/route-36cb8b428b38b26a.js +0 -17
  634. package/.next/standalone/.next/static/chunks/app/api/v1/threads/[thread_id]/run/route-36cb8b428b38b26a.js +0 -17
  635. package/.next/standalone/.next/static/chunks/app/api/v1/threads/route-36cb8b428b38b26a.js +0 -17
  636. package/.next/standalone/.next/static/chunks/app/api/v1/tools/route-36cb8b428b38b26a.js +0 -17
  637. package/.next/standalone/.next/static/chunks/app/api/v1/update/apply/route-36cb8b428b38b26a.js +0 -17
  638. package/.next/standalone/.next/static/chunks/app/api/v1/update/route-36cb8b428b38b26a.js +0 -17
  639. package/.next/standalone/.next/static/chunks/app/api/v1/voice/transcribe/route-36cb8b428b38b26a.js +0 -17
  640. package/.next/standalone/.next/static/chunks/app/api/v1/voice/tts/route-36cb8b428b38b26a.js +0 -17
  641. package/.next/standalone/.next/static/chunks/app/api/v1/watchers/[id]/route-36cb8b428b38b26a.js +0 -17
  642. package/.next/standalone/.next/static/chunks/app/api/v1/watchers/[id]/run/route-36cb8b428b38b26a.js +0 -17
  643. package/.next/standalone/.next/static/chunks/app/api/v1/watchers/reaction-scripts/route-36cb8b428b38b26a.js +0 -17
  644. package/.next/standalone/.next/static/chunks/app/api/v1/watchers/route-36cb8b428b38b26a.js +0 -17
  645. package/.next/standalone/.next/static/chunks/app/manifest.webmanifest/route-36cb8b428b38b26a.js +0 -17
  646. package/.next/standalone/.next/static/chunks/next/dist/client/components/builtin/app-error-36cb8b428b38b26a.js +0 -17
  647. package/.next/standalone/.next/static/chunks/next/dist/client/components/builtin/forbidden-36cb8b428b38b26a.js +0 -17
  648. package/.next/standalone/.next/static/chunks/next/dist/client/components/builtin/not-found-36cb8b428b38b26a.js +0 -17
  649. package/.next/standalone/.next/static/chunks/next/dist/client/components/builtin/unauthorized-36cb8b428b38b26a.js +0 -17
  650. /package/.next/standalone/.next/static/{NUrC9xax1sp1Q70nlFqS6 → bMRK5y3ruT7c3WtBfCQOG}/_buildManifest.js +0 -0
  651. /package/.next/standalone/.next/static/{NUrC9xax1sp1Q70nlFqS6 → bMRK5y3ruT7c3WtBfCQOG}/_ssgManifest.js +0 -0
@@ -6,15 +6,18 @@ import { useSSE } from "@/hooks/useSSE";
6
6
  import { useMessageFilters } from "@/hooks/useMessageFilters";
7
7
  import { useAppContext } from "@/contexts/AppContext";
8
8
  import { useTrackLoading, useActivityWhile } from "@/lib/ui/loading";
9
+ import { pushToast } from "@/lib/ui/toasts";
10
+ import { pushErrorToast } from "@/lib/ui/error-report";
9
11
  import { ApprovalsBanner } from "@/components/proposals/ApprovalsBanner";
10
12
  import { AuthErrorBanner } from "./AuthErrorBanner";
11
13
  import { InputBar } from "./InputBar";
12
14
  import { MessageList } from "./MessageList";
13
- import { applyThreadMeta, makeQueuedId, parseWarmSummaryTopics } from "./chat-helpers";
15
+ import { applyThreadMeta, compactionOutcomeToast, makeQueuedId, parseWarmSummaryTopics, type CompactionOutcome } from "./chat-helpers";
14
16
  import { useChatErrorReporting } from "./useChatErrorReporting";
15
17
  import { useChatQueue, type ChatQueueApi } from "./useChatQueue";
16
18
  import { useThreadCrossDeviceSync } from "./useThreadCrossDeviceSync";
17
19
  import { useThreadData } from "./useThreadData";
20
+ import { useThreadActivity } from "./useThreadActivity";
18
21
  import { useUserProfileAndAgent } from "./useUserProfileAndAgent";
19
22
  import { composerPlaceholder, finalizeRunFromServer } from "./chat-run-utils";
20
23
  import { useChatSubmitHandlers } from "./useChatSubmitHandlers";
@@ -84,11 +87,27 @@ export function ChatView({ threadId, agentId, sessionLoading, sessionError, onMe
84
87
  attachRef.current = sse.attach;
85
88
  clearStreamingRef.current = sse.clearStreamingContent;
86
89
  clearToolEventsRef.current = sse.clearToolEvents;
90
+ // `compacting` lives in this component, which remounts per agent; the
91
+ // server flag keeps a /compact started before an agent switch visible.
92
+ const sessionCompacting = compacting || thread.manualCompactionPending;
93
+
94
+ const activity = useThreadActivity({
95
+ threadId,
96
+ attach: stableAttach,
97
+ isLive: sse.isLive,
98
+ lastSettledAt: sse.lastSettledAt,
99
+ metaApplier: thread.metaApplier,
100
+ });
101
+ // Run phases come through the attached stream; background compaction
102
+ // outside a run has no stream, so label it from the polled activity.
103
+ const backgroundCompaction = !sse.streaming && !sessionCompacting ? activity?.compaction?.kind ?? null : null;
87
104
 
88
105
  useChatErrorReporting({ sessionError, streamError: sse.error, authError: sse.authError, agentId, threadId });
89
106
 
90
107
  const streamingRef = useRef(false);
91
108
  streamingRef.current = sse.streaming;
109
+ const currentThreadIdRef = useRef(threadId);
110
+ currentThreadIdRef.current = threadId;
92
111
 
93
112
  // Auto compaction starts server-side during a run; poll so the banner shows live.
94
113
  useEffect(() => {
@@ -117,11 +136,14 @@ export function ChatView({ threadId, agentId, sessionLoading, sessionError, onMe
117
136
 
118
137
  useTrackLoading(!!sessionLoading);
119
138
  useTrackLoading(sse.streaming);
120
- useTrackLoading(compacting);
139
+ useTrackLoading(sessionCompacting);
121
140
  useTrackLoading(thread.loadingMore);
122
141
  useTrackLoading(thread.messagesLoading);
123
142
  useTrackLoading(agentConfigLoading);
124
143
 
144
+ useActivityWhile(sessionCompacting, "Compacting session…");
145
+ useActivityWhile(backgroundCompaction === "auto", "Compacting earlier messages…");
146
+ useActivityWhile(backgroundCompaction === "refresh", "Updating summary…");
125
147
  useActivityWhile(thread.messagesLoading, "Loading chat history…");
126
148
  useActivityWhile(agentConfigLoading, "Loading agent…");
127
149
  useActivityWhile(profileLoading, "Loading profile…");
@@ -197,16 +219,32 @@ export function ChatView({ threadId, agentId, sessionLoading, sessionError, onMe
197
219
  // eslint-disable-next-line react-hooks/exhaustive-deps
198
220
  }, [threadId]);
199
221
 
200
- const queue = useChatQueue({ threadId, streaming: sse.streaming, compacting, launchRun });
222
+ const queue = useChatQueue({ threadId, streaming: sse.streaming, compacting: sessionCompacting, launchRun });
201
223
  queueApiRef.current = queue;
202
224
  drainQueueRef.current = queue.drainQueueRef.current;
203
225
 
204
226
  async function handleCompact() {
205
227
  if (!agentId) return;
228
+ const notifyCompaction = (result: CompactionOutcome) => {
229
+ const toast = compactionOutcomeToast(result);
230
+ pushToast({
231
+ ...toast,
232
+ source: "system",
233
+ sourceLabel: "Chat",
234
+ agent_id: agentId,
235
+ thread_id: threadId,
236
+ ttl: 5000,
237
+ dedupeKey: `compact:${agentId}`,
238
+ });
239
+ };
206
240
  setCompacting(true);
207
241
  try {
208
242
  const result = await api.agents.compact(agentId, { resetContext: true });
209
- if (result.compacted) {
243
+ // The thread may have changed while compaction ran; never apply its
244
+ // result to a different thread's view.
245
+ const compactedThreadId = threadId;
246
+ const stillCurrent = () => compactedThreadId !== null && currentThreadIdRef.current === compactedThreadId;
247
+ if (result.compacted && compactedThreadId !== null && stillCurrent()) {
210
248
  // Server moved the hot/warm pin to just after the last existing
211
249
  // message and persisted the warm summary. Mirror that in-place so
212
250
  // the warm card shows the fresh summary without wiping the visible
@@ -218,16 +256,19 @@ export function ChatView({ threadId, agentId, sessionLoading, sessionError, onMe
218
256
  thread.metaApplier.setWarmSummary(result.warm_summary ?? null);
219
257
  thread.metaApplier.setWarmSummaryBefore(result.warm_summary_before ?? null);
220
258
  thread.metaApplier.setWarmSummaryBeforeSeq(result.warm_summary_before_seq ?? null);
221
- thread.metaApplier.setWarmSummaryBeforeSeq(result.warm_summary_before_seq ?? null);
222
259
  thread.metaApplier.setWarmSummaryComputedAt(result.warm_summary_computed_at ?? null);
223
260
  thread.metaApplier.setWarmSummarySourceMessages(result.warm_summary_source_messages ?? null);
224
261
  thread.metaApplier.setWarmSummarySourceChars(result.warm_summary_source_chars ?? null);
225
262
  thread.metaApplier.setWarmSummaryTopics?.(parseWarmSummaryTopics(result.warm_summary_topics));
226
- } else {
227
- thread.addNotice("Nothing to compact yet — send some messages first.");
263
+ // The compact response carries only the chat recap; channel recaps
264
+ // (bridge, watcher, scheduled task) come with the thread metadata.
265
+ void api.threads.get(compactedThreadId, { limit: 1 })
266
+ .then((d) => { if (stillCurrent()) applyThreadMeta(thread.metaApplier, d); })
267
+ .catch(() => { /* best-effort */ });
228
268
  }
269
+ notifyCompaction(result);
229
270
  } catch (err) {
230
- thread.addNotice(`Compaction failed: ${String(err)}`);
271
+ pushErrorToast({ title: "Compaction failed", error: err, context: { panel: "chat", action: "compact", agent_id: agentId } });
231
272
  } finally {
232
273
  setCompacting(false);
233
274
  queue.drainQueueRef.current();
@@ -260,7 +301,6 @@ export function ChatView({ threadId, agentId, sessionLoading, sessionError, onMe
260
301
  threadId={threadId}
261
302
  messages={thread.messages}
262
303
  steeredSegments={sse.steeredSegments}
263
- notices={thread.notices}
264
304
  agentConfig={agentConfig}
265
305
  userProfile={userProfile}
266
306
  // streamingContent stays visible past `streaming=false` so the bubble
@@ -287,8 +327,9 @@ export function ChatView({ threadId, agentId, sessionLoading, sessionError, onMe
287
327
  warmSummarySourceMessages={thread.warmSummarySourceMessages}
288
328
  warmSummarySourceChars={thread.warmSummarySourceChars}
289
329
  warmSummaryTopics={thread.warmSummaryTopics}
330
+ warmChannelSummaries={thread.warmChannelSummaries}
290
331
  warmSummaryPending={thread.warmSummaryPending}
291
- compactionPending={thread.compactionPending || compacting}
332
+ compactionPending={thread.compactionPending || sessionCompacting}
292
333
  onSetContextPin={thread.setContextPin}
293
334
  streaming={sse.streaming}
294
335
  contextWindowTokens={thread.contextWindowTokens}
@@ -313,7 +354,7 @@ export function ChatView({ threadId, agentId, sessionLoading, sessionError, onMe
313
354
  onVoiceTranscript={handleVoiceTranscript}
314
355
  disabled={!agentId}
315
356
  placeholder={composerPlaceholder({
316
- compacting,
357
+ compacting: sessionCompacting,
317
358
  sessionLoading: !!sessionLoading,
318
359
  streaming: sse.streaming,
319
360
  })}
@@ -1,7 +1,7 @@
1
1
  // @vitest-environment jsdom
2
2
  import { describe, expect, it } from "vitest";
3
3
  import { fireEvent, render, screen } from "@testing-library/react";
4
- import { WarmSummaryCard } from "./ContextBoundary";
4
+ import { topicsFromSummarySections, WarmSummaryCard } from "./ContextBoundary";
5
5
  import type { SummaryTopicSegment } from "@/api/types";
6
6
 
7
7
  const topics: SummaryTopicSegment[] = [
@@ -66,4 +66,71 @@ describe("WarmSummaryCard topic preview", () => {
66
66
  expect(screen.getByText("Flat prose fallback.")).toBeTruthy();
67
67
  expect(screen.queryByRole("button", { name: /Pricing extraction/ })).toBeNull();
68
68
  });
69
+
70
+ it("groups a sectioned summary without stored topics into collapsed topic rows", () => {
71
+ const legacy = [
72
+ "<!-- jarela:warm-scope=foreground -->",
73
+ "--- Warm context summary ---",
74
+ "Compressed recap of recent messages immediately before the hot window:",
75
+ "## Context",
76
+ "Weighing **three offers** against each other.",
77
+ "## User facts & preferences",
78
+ "- Will not relocate",
79
+ "- Wants numerical answers",
80
+ ].join("\n");
81
+ render(<WarmSummaryCard olderCount={46} summary={legacy} summaryBeforeSeq={10} hotSinceSeq={10} computedAt={null} streaming={false} topics={null} />);
82
+
83
+ expect(screen.queryByText(/jarela:warm-scope/)).toBeNull();
84
+ expect(screen.queryByText(/Warm context summary/)).toBeNull();
85
+ const context = screen.getByRole("button", { name: /^Context/ });
86
+ expect(context.getAttribute("aria-expanded")).toBe("false");
87
+ expect(screen.getByRole("button", { name: /User facts & preferences/ })).toBeTruthy();
88
+ expect(screen.getByText("three offers").tagName).toBe("STRONG");
89
+ expect(screen.queryByRole("button", { name: /Show more/ })).toBeNull();
90
+
91
+ fireEvent.click(screen.getByRole("button", { name: /User facts & preferences/ }));
92
+ expect(screen.getAllByText("Will not relocate")).toHaveLength(1);
93
+ });
94
+ });
95
+
96
+ describe("WarmSummaryCard automation-only boundary", () => {
97
+ const bridgeRecap = {
98
+ channel: "bridge",
99
+ summary: "<!-- jarela:warm-scope=bridge -->\nRelayed **deployment alerts** from the ops channel.",
100
+ computed_at: "2026-10-14T09:30:00.000Z",
101
+ topics: null,
102
+ };
103
+
104
+ it("shows the bridge recap instead of a never-arriving chat summary", () => {
105
+ render(<WarmSummaryCard olderCount={50} summary="" summaryBeforeSeq={10} hotSinceSeq={10} computedAt="2026-10-14T09:30:00.000Z" streaming={false} topics={null} channelSummaries={[bridgeRecap]} />);
106
+
107
+ expect(screen.getByText("Bridge")).toBeTruthy();
108
+ expect(screen.getByRole("button", { name: /Recap/ }).getAttribute("aria-expanded")).toBe("false");
109
+ expect(screen.getByText("deployment alerts").tagName).toBe("STRONG");
110
+ expect(screen.queryByText(/jarela:warm-scope/)).toBeNull();
111
+ expect(screen.queryByText(/Summary will appear/)).toBeNull();
112
+ });
113
+
114
+ it("says nothing needed summarising when the committed boundary has no recaps at all", () => {
115
+ render(<WarmSummaryCard olderCount={3} summary="" summaryBeforeSeq={10} hotSinceSeq={10} computedAt="2026-10-14T09:30:00.000Z" streaming={false} topics={null} />);
116
+ expect(screen.getByText("No earlier chat messages needed summarising.")).toBeTruthy();
117
+ expect(screen.queryByText(/Summary will appear/)).toBeNull();
118
+ });
119
+
120
+ it("keeps the placeholder while the boundary has no committed summary yet", () => {
121
+ render(<WarmSummaryCard olderCount={3} summary={null} summaryBeforeSeq={null} hotSinceSeq={10} computedAt={null} streaming={false} topics={null} />);
122
+ expect(screen.getByText("Summary will appear after your next reply.")).toBeTruthy();
123
+ });
124
+ });
125
+
126
+ describe("topicsFromSummarySections", () => {
127
+ it("keeps unstructured or single-section summaries as prose", () => {
128
+ expect(topicsFromSummarySections("Just a short recap.")).toBeNull();
129
+ expect(topicsFromSummarySections("## Only\nOne section.")).toBeNull();
130
+ });
131
+
132
+ it("keeps intro text before the first heading as an overview section", () => {
133
+ const sections = topicsFromSummarySections("Intro line.\n## Decisions\n- Chose A");
134
+ expect(sections?.map((s) => [s.title, s.recap])).toEqual([["Overview", "Intro line."], ["Decisions", "- Chose A"]]);
135
+ });
69
136
  });
@@ -11,7 +11,7 @@ import ReactMarkdown from "react-markdown";
11
11
  import { StatusDot } from "@/components/ui/StatusDot";
12
12
  import { MetaRow } from "@/components/ui/MetaRow";
13
13
  import { CollapseChevron } from "@/components/ui/CollapseChevron";
14
- import type { SummaryTopicSegment } from "@/api/types";
14
+ import type { SummaryTopicSegment, WarmChannelSummary } from "@/api/types";
15
15
 
16
16
  interface WarmSummaryCardProps {
17
17
  /** Number of messages older than the boundary that the summary covers. */
@@ -26,8 +26,16 @@ interface WarmSummaryCardProps {
26
26
  streaming: boolean;
27
27
  /** Per-topic segmentation of the same warm range, if the summarizer returned one. */
28
28
  topics?: SummaryTopicSegment[] | null;
29
+ /** Automation-channel recaps (bridge, watcher, scheduled task) at this boundary. */
30
+ channelSummaries?: WarmChannelSummary[];
29
31
  }
30
32
 
33
+ const CHANNEL_LABELS: Record<string, string> = {
34
+ bridge: "Bridge",
35
+ watcher: "Watchers",
36
+ scheduled_task: "Scheduled tasks",
37
+ };
38
+
31
39
  export function WarmSummaryCard({
32
40
  olderCount,
33
41
  summary,
@@ -36,19 +44,25 @@ export function WarmSummaryCard({
36
44
  computedAt,
37
45
  streaming,
38
46
  topics,
47
+ channelSummaries = [],
39
48
  }: WarmSummaryCardProps) {
40
49
  const [expanded, setExpanded] = useState(false);
41
- const fresh = !!summary && hotSinceSeq != null && summaryBeforeSeq === hotSinceSeq;
50
+ const committed = hotSinceSeq != null && summaryBeforeSeq === hotSinceSeq;
51
+ const fresh = !!summary && committed;
42
52
  const stale = !!summary && !fresh;
43
53
  const computing = stale && streaming;
44
- const summaryTopics = summary && topics && topics.length > 0 ? topics : null;
54
+ // Summaries stored before topic segmentation still read as topics: their
55
+ // markdown sections render through the same collapsible rows.
56
+ const summaryTopics = summary
57
+ ? (topics && topics.length > 0 ? topics : topicsFromSummarySections(summary))
58
+ : null;
45
59
 
46
60
  return (
47
61
  <div
48
62
  className={[
49
63
  "relative my-4 rounded-2xl border bg-gradient-to-br shadow-sm",
50
64
  "from-accent/[0.06] via-surface-2 to-surface-2",
51
- fresh ? "border-accent/30" : "border-border",
65
+ fresh || committed ? "border-accent/30" : "border-border",
52
66
  ].join(" ")}
53
67
  >
54
68
  <div className="flex items-center gap-2 px-4 pt-3 pb-1.5">
@@ -82,6 +96,10 @@ export function WarmSummaryCard({
82
96
  >
83
97
  <ReactMarkdown>{stripWarmHeader(summary!)}</ReactMarkdown>
84
98
  </div>
99
+ ) : !summary && committed ? (
100
+ channelSummaries.length === 0 && (
101
+ <div className="text-xs text-fg-faint italic">No earlier chat messages needed summarising.</div>
102
+ )
85
103
  ) : !summary ? (
86
104
  <div className="flex items-center gap-2 text-xs text-fg-faint italic">
87
105
  {computing && (
@@ -95,6 +113,10 @@ export function WarmSummaryCard({
95
113
  </div>
96
114
  ) : null}
97
115
 
116
+ {channelSummaries.map((channel) => (
117
+ <ChannelSummarySection key={channel.channel} channel={channel} />
118
+ ))}
119
+
98
120
  {stale && (
99
121
  <div className="mt-2 inline-flex items-center gap-2 text-[11px] text-fg-faint">
100
122
  {computing ? <StatusDot tone="accent" size="sm" pulse /> : <StatusDot tone="neutral" size="sm" />}
@@ -121,6 +143,25 @@ export function WarmSummaryCard({
121
143
  );
122
144
  }
123
145
 
146
+ function ChannelSummarySection({ channel }: { channel: WarmChannelSummary }) {
147
+ const topics = channel.topics && channel.topics.length > 0
148
+ ? channel.topics
149
+ : topicsFromSummarySections(channel.summary)
150
+ ?? [{ title: "Recap", start_at: "", end_at: "", recap: stripWarmHeader(channel.summary), facts: [] }];
151
+ return (
152
+ <div className="mt-2">
153
+ <div className="mb-1 text-[9px] uppercase tracking-wide text-fg-faint">
154
+ {CHANNEL_LABELS[channel.channel] ?? channel.channel}
155
+ </div>
156
+ <div className="flex flex-col gap-1">
157
+ {topics.map((topic, i) => (
158
+ <TopicSegmentRow key={`${channel.channel}-${topic.title}-${i}`} topic={topic} />
159
+ ))}
160
+ </div>
161
+ </div>
162
+ );
163
+ }
164
+
124
165
  function TopicSegmentRow({ topic }: { topic: SummaryTopicSegment }) {
125
166
  const [open, setOpen] = useState(false);
126
167
  const range = formatTopicRange(topic.start_at, topic.end_at);
@@ -130,9 +171,14 @@ function TopicSegmentRow({ topic }: { topic: SummaryTopicSegment }) {
130
171
  <CollapseChevron open={open} size={9} />
131
172
  <span className="font-medium text-fg-muted truncate">{topic.title}</span>
132
173
  {range && <span className="text-fg-faint shrink-0">· {range}</span>}
174
+ {typeof topic.message_count === "number" && topic.message_count > 0 && (
175
+ <span className="text-fg-faint shrink-0">
176
+ · {topic.message_count} {topic.message_count === 1 ? "msg" : "msgs"}
177
+ </span>
178
+ )}
133
179
  {topic.facts.length > 0 && (
134
180
  <span className="ml-auto shrink-0 text-[9px] uppercase tracking-wide text-accent">
135
- {topic.facts.length} {topic.facts.length === 1 ? "fact" : "facts"} saved
181
+ {topic.facts.length} memorized
136
182
  </span>
137
183
  )}
138
184
  </MetaRow>
@@ -149,13 +195,17 @@ function TopicSegmentRow({ topic }: { topic: SummaryTopicSegment }) {
149
195
  </div>
150
196
  )}
151
197
  {topic.facts.length > 0 && (
152
- <ul className="space-y-0.5">
153
- {topic.facts.map((fact, i) => (
154
- <li key={`${fact.subject}-${i}`} className="text-[11px] text-fg-faint">
155
- <span className="font-medium text-fg-muted">{fact.subject}:</span> {fact.content}
156
- </li>
157
- ))}
158
- </ul>
198
+ <div>
199
+ <div className="text-[9px] uppercase tracking-wide text-fg-faint">Memorized</div>
200
+ <ul className="space-y-0.5">
201
+ {topic.facts.map((fact, i) => (
202
+ <li key={`${fact.key ?? fact.subject}-${i}`} className="text-[11px] text-fg-faint">
203
+ <span className="font-medium text-fg-muted">{fact.subject}:</span> {fact.content}
204
+ {fact.key && <code className="ml-1 text-[10px] text-fg-faint">{fact.key}</code>}
205
+ </li>
206
+ ))}
207
+ </ul>
208
+ </div>
159
209
  )}
160
210
  </div>
161
211
  )}
@@ -313,11 +363,40 @@ function formatBytes(n: number): string {
313
363
  // awkwardly inside a card that already has its own header. Strip them.
314
364
  function stripWarmHeader(raw: string): string {
315
365
  return raw
366
+ .replace(/\r\n/g, "\n")
367
+ .replace(/^\s*(<!--[\s\S]*?-->\s*)+/, "")
316
368
  .replace(/^--- Warm context summary ---\n/, "")
317
- .replace(/^Compressed recap of earlier messages outside the hot window:\n/, "")
369
+ .replace(/^Compressed recap of [^\n]*:\n/, "")
318
370
  .trimStart();
319
371
  }
320
372
 
373
+ /**
374
+ * Splits a markdown summary into topic segments at its headings. Returns
375
+ * null when there are fewer than two sections, so short or unstructured
376
+ * summaries keep the plain prose rendering.
377
+ */
378
+ export function topicsFromSummarySections(raw: string): SummaryTopicSegment[] | null {
379
+ const sections: SummaryTopicSegment[] = [];
380
+ let title: string | null = null;
381
+ let body: string[] = [];
382
+ const flush = () => {
383
+ const recap = body.join("\n").trim();
384
+ if (title !== null || recap) sections.push({ title: title ?? "Overview", start_at: "", end_at: "", recap, facts: [] });
385
+ };
386
+ for (const line of stripWarmHeader(raw).split("\n")) {
387
+ const heading = /^#{1,3}\s+(.+?)\s*#*\s*$/.exec(line);
388
+ if (heading) {
389
+ flush();
390
+ title = heading[1];
391
+ body = [];
392
+ } else {
393
+ body.push(line);
394
+ }
395
+ }
396
+ flush();
397
+ return sections.length >= 2 ? sections : null;
398
+ }
399
+
321
400
  function summaryLong(raw: string): boolean {
322
401
  // Heuristic: more than 6 lines or > 600 chars after the header strip.
323
402
  const stripped = stripWarmHeader(raw);
@@ -584,4 +584,35 @@ describe("MessageList conversation focus", () => {
584
584
  fireEvent.click(enabledButton);
585
585
  expect(scrollIntoView).toHaveBeenCalled();
586
586
  });
587
+
588
+ it("keeps a near-bottom boundary locate from snapping back to the bottom", () => {
589
+ const messages = [
590
+ mkMessage("m1", "user", "older", "2026-08-09T10:00:00.000Z"),
591
+ mkMessage("m2", "assistant", "newer", "2026-08-09T10:00:01.000Z"),
592
+ mkMessage("m3", "assistant", "latest", "2026-08-09T10:00:02.000Z"),
593
+ ];
594
+ const props = { threadId: "thread-1", onSetContextPin: vi.fn(), hotSinceSeq: 2 };
595
+ const { container, rerender } = render(<MessageList {...props} messages={messages} />);
596
+
597
+ const scroller = container.querySelector(".panel-scrollbar") as HTMLDivElement;
598
+ Object.defineProperty(scroller, "scrollHeight", { configurable: true, value: 2000 });
599
+ Object.defineProperty(scroller, "clientHeight", { configurable: true, value: 500 });
600
+ Object.defineProperty(scroller, "scrollTop", { configurable: true, writable: true, value: 1500 });
601
+ fireEvent.scroll(scroller);
602
+
603
+ // Simulate the first smooth-scroll frame: still within 100px of the bottom.
604
+ const boundaryEl = document.querySelector("[data-focus-boundary='1']") as HTMLElement;
605
+ boundaryEl.scrollIntoView = vi.fn(() => {
606
+ scroller.scrollTop = 1450;
607
+ fireEvent.scroll(scroller);
608
+ });
609
+
610
+ fireEvent.click(screen.getByRole("button", { name: /filters & focus/i }));
611
+ fireEvent.click(screen.getByRole("button", { name: "Locate boundary line" }));
612
+ expect(boundaryEl.scrollIntoView).toHaveBeenCalledWith({ behavior: "smooth", block: "center" });
613
+ expect(boundaryEl.classList.contains("jarela-deep-link-flash")).toBe(true);
614
+
615
+ rerender(<MessageList {...props} messages={[...messages]} />);
616
+ expect(scroller.scrollTop).toBe(1450);
617
+ });
587
618
  });
@@ -1,21 +1,17 @@
1
1
  "use client";
2
2
  import { memo, useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from "react";
3
3
  import { Brain, ChevronRight, Hourglass, X, ArrowDown, Eye, EyeOff } from "lucide-react";
4
- import type { AgentConfig, AutomationActivityMetadata, ContentPart, Message, SummaryTopicSegment, UserProfile } from "@/api/types";
4
+ import type { AgentConfig, AutomationActivityMetadata, ContentPart, Message, SummaryTopicSegment, UserProfile, WarmChannelSummary } from "@/api/types";
5
5
  import { ToolList, type ToolEvent } from "./ToolList";
6
6
  import { MessageBubble } from "./MessageBubble";
7
7
  import { ContextBoundaryDivider, WarmSummaryCard } from "./ContextBoundary";
8
+ import { WorkflowStepRetryContext, workflowStepRetryMessage, type WorkflowStepRetryRequest } from "./workflow-step-retry";
8
9
  import { MESSAGE_FILTER_KEYS, type MessageFilterKey } from "@/hooks/useMessageFilters";
9
10
  import { CollapseChevron } from "@/components/ui/CollapseChevron";
10
11
  import { MetaRow } from "@/components/ui/MetaRow";
11
12
  import { StatusDot } from "@/components/ui/StatusDot";
12
13
  import { Dialog } from "@/components/ui/Dialog";
13
14
 
14
- interface SystemNotice {
15
- id: string;
16
- text: string;
17
- }
18
-
19
15
  interface QueuedMessageView {
20
16
  id: string;
21
17
  text: string;
@@ -31,7 +27,6 @@ interface Props {
31
27
  threadId?: string | null;
32
28
  messages: Message[];
33
29
  steeredSegments?: SteeredSegment[];
34
- notices?: SystemNotice[];
35
30
  agentConfig?: AgentConfig | null;
36
31
  userProfile?: UserProfile | null;
37
32
  streamingContent?: string;
@@ -53,6 +48,8 @@ interface Props {
53
48
  warmSummarySourceMessages?: number | null;
54
49
  warmSummarySourceChars?: number | null;
55
50
  warmSummaryTopics?: SummaryTopicSegment[] | null;
51
+ /** Automation-channel recaps committed at the current boundary. */
52
+ warmChannelSummaries?: WarmChannelSummary[];
56
53
  warmSummaryPending?: boolean;
57
54
  /** An automatic compaction is summarising earlier messages right now. */
58
55
  compactionPending?: boolean;
@@ -78,8 +75,9 @@ interface Props {
78
75
  const ALL_FILTERS_SHOWN: Record<MessageFilterKey, boolean> = Object.fromEntries(
79
76
  MESSAGE_FILTER_KEYS.map((k) => [k, true]),
80
77
  ) as Record<MessageFilterKey, boolean>;
78
+ const NO_CHANNEL_SUMMARIES: WarmChannelSummary[] = [];
81
79
 
82
- export function MessageList({ threadId, messages, steeredSegments, notices, agentConfig, userProfile, streamingContent, thinkingContent, toolEvents, hasMore, loadingMore, onLoadMore, queuedMessages, onRemoveQueued, hotSinceSeq, warmSummary, warmSummaryBeforeSeq, warmSummaryComputedAt, warmSummarySourceMessages, warmSummarySourceChars, warmSummaryTopics, warmSummaryPending = false, compactionPending = false, onSetContextPin, streaming, contextWindowTokens, onRetryMessage, filters = ALL_FILTERS_SHOWN, onToggleFilter: toggle = () => {}, onResetFilters: reset = () => {} }: Props) {
80
+ export function MessageList({ threadId, messages, steeredSegments, agentConfig, userProfile, streamingContent, thinkingContent, toolEvents, hasMore, loadingMore, onLoadMore, queuedMessages, onRemoveQueued, hotSinceSeq, warmSummary, warmSummaryBeforeSeq, warmSummaryComputedAt, warmSummarySourceMessages, warmSummarySourceChars, warmSummaryTopics, warmChannelSummaries = NO_CHANNEL_SUMMARIES, warmSummaryPending = false, compactionPending = false, onSetContextPin, streaming, contextWindowTokens, onRetryMessage, filters = ALL_FILTERS_SHOWN, onToggleFilter: toggle = () => {}, onResetFilters: reset = () => {} }: Props) {
83
81
  const hostRef = useRef<HTMLDivElement>(null);
84
82
  const maskRegionRef = useRef<HTMLDivElement>(null);
85
83
  const scrollRef = useRef<HTMLDivElement>(null);
@@ -104,6 +102,13 @@ export function MessageList({ threadId, messages, steeredSegments, notices, agen
104
102
  const [pendingHotSinceSeq, setPendingHotSinceSeq] = useState<number | null>(null);
105
103
  const [topControlsOpen, setTopControlsOpen] = useState(false);
106
104
  const [summaryPopoverOpen, setSummaryPopoverOpen] = useState(false);
105
+
106
+ const retryWorkflowStep = useMemo(
107
+ () => onRetryMessage
108
+ ? (request: WorkflowStepRetryRequest) => onRetryMessage(workflowStepRetryMessage(request), [])
109
+ : null,
110
+ [onRetryMessage],
111
+ );
107
112
 
108
113
  // Apply category filter. Messages with no `category` (NULL = ordinary
109
114
  // chat) are always shown; tagged messages are gated by their toggle.
@@ -503,9 +508,15 @@ export function MessageList({ threadId, messages, steeredSegments, notices, agen
503
508
  ? nextHotCount < currentHotCount
504
509
  : false;
505
510
  const hasWarmSummary = !!warmSummary;
511
+ // A committed boundary whose chat range had nothing to summarise (e.g. a
512
+ // bridge-only agent): the recap, if any, lives in the channel summaries.
513
+ const summaryCommittedEmpty = !hasWarmSummary
514
+ && effectiveHotSinceSeq !== null
515
+ && warmSummaryBeforeSeq === effectiveHotSinceSeq;
506
516
  const summaryFresh = hasWarmSummary
507
517
  && effectiveHotSinceSeq !== null
508
518
  && warmSummaryBeforeSeq === effectiveHotSinceSeq;
519
+ const summaryReady = summaryFresh || summaryCommittedEmpty;
509
520
  const summaryUpdating = hasWarmSummary && !summaryFresh && !!streaming;
510
521
  const summaryStale = hasWarmSummary && !summaryFresh && !summaryUpdating;
511
522
 
@@ -593,10 +604,25 @@ export function MessageList({ threadId, messages, steeredSegments, notices, agen
593
604
  boundaryAnchorRef.current = null;
594
605
  }, []);
595
606
 
607
+ // While a programmatic smooth scroll (locate boundary, deep link) animates
608
+ // away from the bottom, its first frames are still "near bottom". Without
609
+ // this lock, scroll sync re-arms bottom-follow and the post-render snap
610
+ // cancels the animation, so the target is never reached.
611
+ const programmaticScrollUntilRef = useRef(0);
596
612
  const syncScrollButton = useCallback((el: HTMLDivElement) => {
597
613
  const isAtBottom = el.scrollHeight - el.scrollTop - el.clientHeight < 100;
598
- atBottomRef.current = isAtBottom;
599
- setShowScrollButton(!isAtBottom && hasScrollTarget);
614
+ const locked = Date.now() < programmaticScrollUntilRef.current;
615
+ atBottomRef.current = isAtBottom && !locked;
616
+ setShowScrollButton(!atBottomRef.current && hasScrollTarget);
617
+ }, [hasScrollTarget]);
618
+
619
+ const scrollTargetIntoView = useCallback((target: HTMLElement) => {
620
+ programmaticScrollUntilRef.current = Date.now() + PROGRAMMATIC_SCROLL_LOCK_MS;
621
+ atBottomRef.current = false;
622
+ setShowScrollButton(hasScrollTarget);
623
+ target.scrollIntoView({ behavior: "smooth", block: "center" });
624
+ target.classList.add("jarela-deep-link-flash");
625
+ window.setTimeout(() => target.classList.remove("jarela-deep-link-flash"), 1600);
600
626
  }, [hasScrollTarget]);
601
627
 
602
628
  // Anchor for older-message pagination. When the user scrolls near the top
@@ -715,11 +741,7 @@ export function MessageList({ threadId, messages, steeredSegments, notices, agen
715
741
  const safe = id.replace(/"/g, '\\"');
716
742
  const el = root.querySelector(`[data-message-id="${safe}"]`) as HTMLElement | null;
717
743
  if (!el) return;
718
- atBottomRef.current = false;
719
- setShowScrollButton(hasScrollTarget);
720
- el.scrollIntoView({ behavior: "smooth", block: "center" });
721
- el.classList.add("jarela-deep-link-flash");
722
- setTimeout(() => el.classList.remove("jarela-deep-link-flash"), 1600);
744
+ scrollTargetIntoView(el);
723
745
  // Strip the hash so the next streaming message / list-length change
724
746
  // doesn't yank the view back to this anchor. replaceState avoids
725
747
  // triggering a hashchange event (which would re-enter this handler).
@@ -730,7 +752,7 @@ export function MessageList({ threadId, messages, steeredSegments, notices, agen
730
752
  scrollToHashTarget();
731
753
  window.addEventListener("hashchange", scrollToHashTarget);
732
754
  return () => window.removeEventListener("hashchange", scrollToHashTarget);
733
- }, [messages.length, hasScrollTarget]);
755
+ }, [messages.length, scrollTargetIntoView]);
734
756
 
735
757
  // Handle orientation changes and resizes to maintain scroll position
736
758
  useEffect(() => {
@@ -765,12 +787,11 @@ export function MessageList({ threadId, messages, steeredSegments, notices, agen
765
787
  ? document.getElementById(`context-boundary-${effectiveHotSinceSeq}`)
766
788
  : root.querySelector("[data-focus-boundary='1']") as HTMLElement | null;
767
789
  if (!boundary) return;
768
- atBottomRef.current = false;
769
- setShowScrollButton(hasScrollTarget);
770
- boundary.scrollIntoView({ behavior: "smooth", block: "center" });
790
+ scrollTargetIntoView(boundary);
771
791
  }
772
792
 
773
793
  return (
794
+ <WorkflowStepRetryContext.Provider value={retryWorkflowStep}>
774
795
  <div ref={hostRef} className="flex-1 flex flex-col min-h-0 relative">
775
796
  {visibleMessages.length > 0 && (
776
797
  <div className="shrink-0 px-4 pt-[calc(var(--app-safe-top)+3rem)] pb-1">
@@ -1014,13 +1035,6 @@ export function MessageList({ threadId, messages, steeredSegments, notices, agen
1014
1035
  ))}
1015
1036
  </div>
1016
1037
  )}
1017
- {notices?.map((n) => (
1018
- <div key={n.id} className="flex justify-center my-3">
1019
- <span className="text-xs italic text-fg-faint bg-surface-2 px-3 py-1 rounded-full border border-border">
1020
- {n.text}
1021
- </span>
1022
- </div>
1023
- ))}
1024
1038
  </div>
1025
1039
 
1026
1040
  <div
@@ -1079,7 +1093,7 @@ export function MessageList({ threadId, messages, steeredSegments, notices, agen
1079
1093
  className={[
1080
1094
  "text-[10px] px-1.5 py-px rounded border inline-flex items-center gap-1",
1081
1095
  summaryUpdating ? "border-accent/40 bg-accent/10 text-accent" :
1082
- summaryFresh ? "border-emerald-500/30 bg-emerald-500/10 text-emerald-600 dark:text-emerald-400" :
1096
+ summaryReady ? "border-emerald-500/30 bg-emerald-500/10 text-emerald-600 dark:text-emerald-400" :
1083
1097
  summaryStale ? "border-amber-500/30 bg-amber-500/10 text-amber-700 dark:text-amber-400" :
1084
1098
  "border-border bg-surface-2 text-fg-faint",
1085
1099
  ].join(" ")}
@@ -1088,7 +1102,7 @@ export function MessageList({ threadId, messages, steeredSegments, notices, agen
1088
1102
  <span className="h-2 w-2 rounded-full bg-accent animate-pulse" aria-label="Summary updating" />
1089
1103
  )}
1090
1104
  <span>
1091
- {summaryUpdating ? "updating" : summaryFresh ? "ready" : summaryStale ? "needs refresh" : "pending"}
1105
+ {summaryUpdating ? "updating" : summaryReady ? "ready" : summaryStale ? "needs refresh" : "pending"}
1092
1106
  </span>
1093
1107
  </span>
1094
1108
  </div>
@@ -1096,6 +1110,10 @@ export function MessageList({ threadId, messages, steeredSegments, notices, agen
1096
1110
  <p className="text-[11px] text-fg-faint">
1097
1111
  {summaryFresh
1098
1112
  ? "Showing the latest summary for messages above the boundary line."
1113
+ : summaryCommittedEmpty
1114
+ ? (warmChannelSummaries.length > 0
1115
+ ? "No chat messages above the boundary line; automation activity there is summarised below."
1116
+ : "Nothing above the boundary line needed summarising.")
1099
1117
  : summaryStale
1100
1118
  ? "This summary is from an older focus and will refresh after the next reply."
1101
1119
  : "No summary yet. It will appear after the next reply."}
@@ -1109,6 +1127,7 @@ export function MessageList({ threadId, messages, steeredSegments, notices, agen
1109
1127
  computedAt={warmSummaryComputedAt ?? null}
1110
1128
  streaming={!!streaming}
1111
1129
  topics={warmSummaryTopics ?? null}
1130
+ channelSummaries={warmChannelSummaries}
1112
1131
  />
1113
1132
  </div>
1114
1133
  </Dialog>
@@ -1157,6 +1176,7 @@ export function MessageList({ threadId, messages, steeredSegments, notices, agen
1157
1176
  </div>
1158
1177
  </Dialog>
1159
1178
  </div>
1179
+ </WorkflowStepRetryContext.Provider>
1160
1180
  );
1161
1181
  }
1162
1182
 
@@ -1165,6 +1185,7 @@ export function MessageList({ threadId, messages, steeredSegments, notices, agen
1165
1185
  // activeChannels + lib/agents/prepare/history-window.ts). The rest
1166
1186
  // (extension, page_capture, synthetic, tool_use, thinking) are display-only.
1167
1187
  const CHANNEL_SCOPED_FILTER_KEYS = new Set<MessageFilterKey>(["scheduled_task", "watcher", "bridge"]);
1188
+ const PROGRAMMATIC_SCROLL_LOCK_MS = 1500;
1168
1189
 
1169
1190
  const CHIP_LABELS: Record<MessageFilterKey, string> = {
1170
1191
  scheduled_task: "scheduled",