@circuitwall/jarela 2.2.1 → 2.4.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 (703) hide show
  1. package/.next/standalone/.next/BUILD_ID +1 -1
  2. package/.next/standalone/.next/app-path-routes-manifest.json +2 -1
  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 +100 -93
  22. package/.next/standalone/.next/server/app/api/v1/access/route.js +176 -169
  23. package/.next/standalone/.next/server/app/api/v1/agents/[id]/compact/route.js +89 -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 +139 -127
  26. package/.next/standalone/.next/server/app/api/v1/agents/[id]/route.js +107 -100
  27. package/.next/standalone/.next/server/app/api/v1/agents/[id]/thread/route.js +765 -753
  28. package/.next/standalone/.next/server/app/api/v1/agents/route.js +72 -65
  29. package/.next/standalone/.next/server/app/api/v1/allowed-sites/[hostname]/route.js +371 -364
  30. package/.next/standalone/.next/server/app/api/v1/allowed-sites/route.js +809 -802
  31. package/.next/standalone/.next/server/app/api/v1/artifacts/lifecycle/route.js +9 -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 +583 -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 +41 -30
  37. package/.next/standalone/.next/server/app/api/v1/bridges/[id]/ignores/route.js +48 -37
  38. package/.next/standalone/.next/server/app/api/v1/bridges/[id]/lookup/route.js +697 -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 +703 -136
  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 +796 -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 +762 -746
  45. package/.next/standalone/.next/server/app/api/v1/bridges/[id]/routes/route.js +1050 -1034
  46. package/.next/standalone/.next/server/app/api/v1/bridges/[id]/status/route.js +673 -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 +811 -804
  49. package/.next/standalone/.next/server/app/api/v1/bridges/kinds/route.js.nft.json +1 -1
  50. package/.next/standalone/.next/server/app/api/v1/bridges/route.js +718 -706
  51. package/.next/standalone/.next/server/app/api/v1/bridges/route.js.nft.json +1 -1
  52. package/.next/standalone/.next/server/app/api/v1/builtin-tools/route.js +9 -9
  53. package/.next/standalone/.next/server/app/api/v1/builtin-tools/route.js.nft.json +1 -1
  54. package/.next/standalone/.next/server/app/api/v1/config/route.js +85 -85
  55. package/.next/standalone/.next/server/app/api/v1/credentials/[id]/route.js +709 -709
  56. package/.next/standalone/.next/server/app/api/v1/credentials/[id]/route.js.nft.json +1 -1
  57. package/.next/standalone/.next/server/app/api/v1/credentials/route.js +2 -2
  58. package/.next/standalone/.next/server/app/api/v1/credentials/route.js.nft.json +1 -1
  59. package/.next/standalone/.next/server/app/api/v1/dashboard/currency/route.js +10 -10
  60. package/.next/standalone/.next/server/app/api/v1/dashboard/metrics/route.js +796 -784
  61. package/.next/standalone/.next/server/app/api/v1/dashboard/pricing/route.js +30 -23
  62. package/.next/standalone/.next/server/app/api/v1/dashboard/pricing-task/route.js +86 -86
  63. package/.next/standalone/.next/server/app/api/v1/dashboard/pricing-task/route.js.nft.json +1 -1
  64. package/.next/standalone/.next/server/app/api/v1/delegations/codex/[job_id]/route.js +57 -57
  65. package/.next/standalone/.next/server/app/api/v1/delegations/codex/[job_id]/route.js.nft.json +1 -1
  66. package/.next/standalone/.next/server/app/api/v1/documents/search/route.js +385 -378
  67. package/.next/standalone/.next/server/app/api/v1/documents/settings/route.js +51 -44
  68. package/.next/standalone/.next/server/app/api/v1/documents/sources/[id]/reindex/route.js +65 -65
  69. package/.next/standalone/.next/server/app/api/v1/documents/sources/[id]/reindex/route.js.nft.json +1 -1
  70. package/.next/standalone/.next/server/app/api/v1/documents/sources/[id]/route.js +122 -122
  71. package/.next/standalone/.next/server/app/api/v1/documents/sources/[id]/route.js.nft.json +1 -1
  72. package/.next/standalone/.next/server/app/api/v1/documents/sources/route.js +37 -37
  73. package/.next/standalone/.next/server/app/api/v1/documents/sources/route.js.nft.json +1 -1
  74. package/.next/standalone/.next/server/app/api/v1/env/route.js +9 -9
  75. package/.next/standalone/.next/server/app/api/v1/env-sync/allowlist/route.js +375 -368
  76. package/.next/standalone/.next/server/app/api/v1/env-sync/route.js +51 -44
  77. package/.next/standalone/.next/server/app/api/v1/events/route.js +745 -178
  78. package/.next/standalone/.next/server/app/api/v1/events/route.js.nft.json +1 -1
  79. package/.next/standalone/.next/server/app/api/v1/events/test/route.js +77 -77
  80. package/.next/standalone/.next/server/app/api/v1/extension/agents/route.js +763 -763
  81. package/.next/standalone/.next/server/app/api/v1/extension/agents/route.js.nft.json +1 -1
  82. package/.next/standalone/.next/server/app/api/v1/extension/browser/activate/route.js +51 -44
  83. package/.next/standalone/.next/server/app/api/v1/extension/browser/foreground/route.js +16 -9
  84. package/.next/standalone/.next/server/app/api/v1/extension/browser/history/route.js +72 -65
  85. package/.next/standalone/.next/server/app/api/v1/extension/browser/poll/route.js +41 -34
  86. package/.next/standalone/.next/server/app/api/v1/extension/browser/progress/route.js +211 -204
  87. package/.next/standalone/.next/server/app/api/v1/extension/browser/result/route.js +140 -133
  88. package/.next/standalone/.next/server/app/api/v1/extension/browser/retry/route.js +113 -106
  89. package/.next/standalone/.next/server/app/api/v1/extension/browser/status/route.js +121 -114
  90. package/.next/standalone/.next/server/app/api/v1/extension/browser/tabs/route.js +141 -134
  91. package/.next/standalone/.next/server/app/api/v1/extension/fill/route.js +690 -690
  92. package/.next/standalone/.next/server/app/api/v1/extension/fill/route.js.nft.json +1 -1
  93. package/.next/standalone/.next/server/app/api/v1/extension/refine/route.js +93 -93
  94. package/.next/standalone/.next/server/app/api/v1/extension/refine/route.js.nft.json +1 -1
  95. package/.next/standalone/.next/server/app/api/v1/extension/turn/route.js +9 -9
  96. package/.next/standalone/.next/server/app/api/v1/extension/turn/route.js.nft.json +1 -1
  97. package/.next/standalone/.next/server/app/api/v1/extensions/route.js +185 -185
  98. package/.next/standalone/.next/server/app/api/v1/extensions/route.js.nft.json +1 -1
  99. package/.next/standalone/.next/server/app/api/v1/extensions/tools/[name]/config/route.js +171 -171
  100. package/.next/standalone/.next/server/app/api/v1/extensions/tools/[name]/config/route.js.nft.json +1 -1
  101. package/.next/standalone/.next/server/app/api/v1/extensions/tools/[name]/route.js +396 -396
  102. package/.next/standalone/.next/server/app/api/v1/extensions/tools/[name]/route.js.nft.json +1 -1
  103. package/.next/standalone/.next/server/app/api/v1/extensions/tools/[name]/secrets/route.js +212 -212
  104. package/.next/standalone/.next/server/app/api/v1/extensions/tools/[name]/secrets/route.js.nft.json +1 -1
  105. package/.next/standalone/.next/server/app/api/v1/files/[name]/route.js +235 -235
  106. package/.next/standalone/.next/server/app/api/v1/fs/browse/route.js +26 -26
  107. package/.next/standalone/.next/server/app/api/v1/harnesses/[id]/route.js +228 -221
  108. package/.next/standalone/.next/server/app/api/v1/harnesses/default/route.js +65 -58
  109. package/.next/standalone/.next/server/app/api/v1/harnesses/route.js +79 -72
  110. package/.next/standalone/.next/server/app/api/v1/health/probes/route.js +9 -9
  111. package/.next/standalone/.next/server/app/api/v1/health/probes/route.js.nft.json +1 -1
  112. package/.next/standalone/.next/server/app/api/v1/health/route.js +783 -771
  113. package/.next/standalone/.next/server/app/api/v1/integrations/[name]/route.js +140 -133
  114. package/.next/standalone/.next/server/app/api/v1/integrations/[name]/test/route.js +9 -9
  115. package/.next/standalone/.next/server/app/api/v1/integrations/[name]/test/route.js.nft.json +1 -1
  116. package/.next/standalone/.next/server/app/api/v1/integrations/gmail/oauth/callback/route.js +370 -363
  117. package/.next/standalone/.next/server/app/api/v1/integrations/gmail/oauth/start/route.js +240 -233
  118. package/.next/standalone/.next/server/app/api/v1/integrations/gmail/oauth/status/route.js +689 -682
  119. package/.next/standalone/.next/server/app/api/v1/integrations/outlook/oauth/callback/route.js +886 -879
  120. package/.next/standalone/.next/server/app/api/v1/integrations/outlook/oauth/start/route.js +115 -108
  121. package/.next/standalone/.next/server/app/api/v1/integrations/outlook/oauth/status/route.js +955 -948
  122. package/.next/standalone/.next/server/app/api/v1/integrations/route.js +223 -216
  123. package/.next/standalone/.next/server/app/api/v1/lifecycle/adoption/route.js +876 -847
  124. package/.next/standalone/.next/server/app/api/v1/lifecycle/adoption/route.js.nft.json +1 -1
  125. package/.next/standalone/.next/server/app/api/v1/local-file/route.js +26 -26
  126. package/.next/standalone/.next/server/app/api/v1/logs/route.js +70 -70
  127. package/.next/standalone/.next/server/app/api/v1/maps/embed/route.js +79 -72
  128. package/.next/standalone/.next/server/app/api/v1/mcp-servers/[name]/route.js +991 -979
  129. package/.next/standalone/.next/server/app/api/v1/mcp-servers/registry/route.js +196 -196
  130. package/.next/standalone/.next/server/app/api/v1/mcp-servers/route.js +19 -7
  131. package/.next/standalone/.next/server/app/api/v1/memory/[namespace]/[key]/route.js +539 -532
  132. package/.next/standalone/.next/server/app/api/v1/memory/policy/route.js +86 -79
  133. package/.next/standalone/.next/server/app/api/v1/memory/route.js +58 -51
  134. package/.next/standalone/.next/server/app/api/v1/memory/search/route.js +138 -131
  135. package/.next/standalone/.next/server/app/api/v1/models/[name]/compact-threads/route.js +381 -369
  136. package/.next/standalone/.next/server/app/api/v1/models/[name]/compact-threads/route.js.nft.json +1 -1
  137. package/.next/standalone/.next/server/app/api/v1/models/[name]/route.js +150 -143
  138. package/.next/standalone/.next/server/app/api/v1/models/route.js +634 -627
  139. package/.next/standalone/.next/server/app/api/v1/packages/catalog/route.js +445 -445
  140. package/.next/standalone/.next/server/app/api/v1/packages/defaults/[id]/route.js +120 -120
  141. package/.next/standalone/.next/server/app/api/v1/packages/defaults/[id]/route.js.nft.json +1 -1
  142. package/.next/standalone/.next/server/app/api/v1/packages/install/[id]/route.js +234 -234
  143. package/.next/standalone/.next/server/app/api/v1/packages/install/[id]/route.js.nft.json +1 -1
  144. package/.next/standalone/.next/server/app/api/v1/packages/install/route.js +407 -407
  145. package/.next/standalone/.next/server/app/api/v1/packages/install/route.js.nft.json +1 -1
  146. package/.next/standalone/.next/server/app/api/v1/packages/manifests/[name]/enabled/route.js +37 -37
  147. package/.next/standalone/.next/server/app/api/v1/packages/manifests/[name]/enabled/route.js.nft.json +1 -1
  148. package/.next/standalone/.next/server/app/api/v1/packages/manifests/[name]/route.js +107 -107
  149. package/.next/standalone/.next/server/app/api/v1/packages/manifests/[name]/route.js.nft.json +1 -1
  150. package/.next/standalone/.next/server/app/api/v1/packages/manifests/route.js +228 -228
  151. package/.next/standalone/.next/server/app/api/v1/packages/manifests/route.js.nft.json +1 -1
  152. package/.next/standalone/.next/server/app/api/v1/packages/reload/route.js +9 -9
  153. package/.next/standalone/.next/server/app/api/v1/packages/reload/route.js.nft.json +1 -1
  154. package/.next/standalone/.next/server/app/api/v1/packages/route.js +148 -148
  155. package/.next/standalone/.next/server/app/api/v1/packages/route.js.nft.json +1 -1
  156. package/.next/standalone/.next/server/app/api/v1/page-capture/route.js +787 -787
  157. package/.next/standalone/.next/server/app/api/v1/page-capture/route.js.nft.json +1 -1
  158. package/.next/standalone/.next/server/app/api/v1/pending-actions/[id]/approve/route.js +529 -514
  159. package/.next/standalone/.next/server/app/api/v1/pending-actions/[id]/approve/route.js.nft.json +1 -1
  160. package/.next/standalone/.next/server/app/api/v1/pending-actions/[id]/deny/route.js +181 -181
  161. package/.next/standalone/.next/server/app/api/v1/pending-actions/[id]/deny/route.js.nft.json +1 -1
  162. package/.next/standalone/.next/server/app/api/v1/pending-actions/route.js +258 -258
  163. package/.next/standalone/.next/server/app/api/v1/pending-actions/route.js.nft.json +1 -1
  164. package/.next/standalone/.next/server/app/api/v1/profile/location/route.js +37 -30
  165. package/.next/standalone/.next/server/app/api/v1/profile/route.js +171 -164
  166. package/.next/standalone/.next/server/app/api/v1/providers/[provider]/models/route.js +51 -44
  167. package/.next/standalone/.next/server/app/api/v1/providers/[provider]/probe/route.js +15 -8
  168. package/.next/standalone/.next/server/app/api/v1/providers/github-copilot/auth/route.js +171 -164
  169. package/.next/standalone/.next/server/app/api/v1/providers/route.js +101 -94
  170. package/.next/standalone/.next/server/app/api/v1/proxy-config/route.js +457 -450
  171. package/.next/standalone/.next/server/app/api/v1/redaction/init/route.js +44 -37
  172. package/.next/standalone/.next/server/app/api/v1/redaction/route.js +65 -58
  173. package/.next/standalone/.next/server/app/api/v1/scheduled-tasks/[id]/route.js +617 -605
  174. package/.next/standalone/.next/server/app/api/v1/scheduled-tasks/[id]/run/route.js +44 -44
  175. package/.next/standalone/.next/server/app/api/v1/scheduled-tasks/[id]/run/route.js.nft.json +1 -1
  176. package/.next/standalone/.next/server/app/api/v1/scheduled-tasks/route.js +739 -732
  177. package/.next/standalone/.next/server/app/api/v1/security/idle-timeout/route.js +329 -322
  178. package/.next/standalone/.next/server/app/api/v1/security/pin/route.js +204 -197
  179. package/.next/standalone/.next/server/app/api/v1/security/state/route.js +58 -51
  180. package/.next/standalone/.next/server/app/api/v1/security/unlock/route.js +183 -176
  181. package/.next/standalone/.next/server/app/api/v1/security/verify-pin/route.js +194 -187
  182. package/.next/standalone/.next/server/app/api/v1/setup/test-key/route.js +26 -26
  183. package/.next/standalone/.next/server/app/api/v1/skills/[id]/route.js +776 -769
  184. package/.next/standalone/.next/server/app/api/v1/skills/repos/[id]/route.js +122 -115
  185. package/.next/standalone/.next/server/app/api/v1/skills/repos/route.js +334 -327
  186. package/.next/standalone/.next/server/app/api/v1/skills/route.js +873 -866
  187. package/.next/standalone/.next/server/app/api/v1/system/abort/route.js +838 -808
  188. package/.next/standalone/.next/server/app/api/v1/system/restart/route.js +177 -177
  189. package/.next/standalone/.next/server/app/api/v1/system/restart/route.js.nft.json +1 -1
  190. package/.next/standalone/.next/server/app/api/v1/tailscale/route.js +164 -164
  191. package/.next/standalone/.next/server/app/api/v1/tasks/[agent_id]/route.js +122 -115
  192. package/.next/standalone/.next/server/app/api/v1/tasks/route.js +30 -23
  193. package/.next/standalone/.next/server/app/api/v1/threads/[thread_id]/activity/route.js +1436 -0
  194. package/.next/standalone/.next/server/app/api/v1/threads/[thread_id]/activity/route.js.nft.json +1 -0
  195. package/.next/standalone/.next/server/app/api/v1/threads/[thread_id]/activity/route_client-reference-manifest.js +1 -0
  196. package/.next/standalone/.next/server/app/api/v1/threads/[thread_id]/context-pin/route.js +638 -631
  197. package/.next/standalone/.next/server/app/api/v1/threads/[thread_id]/context-pin/route.js.nft.json +1 -1
  198. package/.next/standalone/.next/server/app/api/v1/threads/[thread_id]/route.js +60 -439
  199. package/.next/standalone/.next/server/app/api/v1/threads/[thread_id]/route.js.nft.json +1 -1
  200. package/.next/standalone/.next/server/app/api/v1/threads/[thread_id]/run/route.js +172 -173
  201. package/.next/standalone/.next/server/app/api/v1/threads/[thread_id]/run/route.js.nft.json +1 -1
  202. package/.next/standalone/.next/server/app/api/v1/threads/route.js +925 -913
  203. package/.next/standalone/.next/server/app/api/v1/tools/route.js +2 -2
  204. package/.next/standalone/.next/server/app/api/v1/tools/route.js.nft.json +1 -1
  205. package/.next/standalone/.next/server/app/api/v1/update/apply/route.js +17 -17
  206. package/.next/standalone/.next/server/app/api/v1/update/apply/route.js.nft.json +1 -1
  207. package/.next/standalone/.next/server/app/api/v1/update/route.js +570 -570
  208. package/.next/standalone/.next/server/app/api/v1/voice/transcribe/route.js +241 -229
  209. package/.next/standalone/.next/server/app/api/v1/voice/tts/route.js +989 -977
  210. package/.next/standalone/.next/server/app/api/v1/watchers/[id]/route.js +40 -28
  211. package/.next/standalone/.next/server/app/api/v1/watchers/[id]/run/route.js +72 -72
  212. package/.next/standalone/.next/server/app/api/v1/watchers/[id]/run/route.js.nft.json +1 -1
  213. package/.next/standalone/.next/server/app/api/v1/watchers/reaction-scripts/route.js +128 -128
  214. package/.next/standalone/.next/server/app/api/v1/watchers/route.js +164 -164
  215. package/.next/standalone/.next/server/app/api/v1/watchers/route.js.nft.json +1 -1
  216. package/.next/standalone/.next/server/app/icon.svg/route.js +62 -62
  217. package/.next/standalone/.next/server/app/manifest.webmanifest/route.js +436 -436
  218. package/.next/standalone/.next/server/app/page.js +1179 -743
  219. package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  220. package/.next/standalone/.next/server/app/setup/page.js +99 -91
  221. package/.next/standalone/.next/server/app/setup/page_client-reference-manifest.js +1 -1
  222. package/.next/standalone/.next/server/app-paths-manifest.json +2 -1
  223. package/.next/standalone/.next/server/chunks/{424.js → 1388.js} +441 -1022
  224. package/.next/standalone/.next/server/chunks/1433.js +1 -1
  225. package/.next/standalone/.next/server/chunks/1638.js +1 -2
  226. package/.next/standalone/.next/server/chunks/1738.js +1 -1
  227. package/.next/standalone/.next/server/chunks/2068.js +47 -10
  228. package/.next/standalone/.next/server/chunks/210.js +3 -3
  229. package/.next/standalone/.next/server/chunks/2151.js +31 -1
  230. package/.next/standalone/.next/server/chunks/2207.js +1 -0
  231. package/.next/standalone/.next/server/chunks/2447.js +10 -5
  232. package/.next/standalone/.next/server/chunks/2471.js +45 -45
  233. package/.next/standalone/.next/server/chunks/2504.js +1 -1
  234. package/.next/standalone/.next/server/chunks/2695.js +17 -17
  235. package/.next/standalone/.next/server/chunks/3042.js +24 -16
  236. package/.next/standalone/.next/server/chunks/{4540.js → 309.js} +104 -38
  237. package/.next/standalone/.next/server/chunks/{2350.js → 3272.js} +104 -37
  238. package/.next/standalone/.next/server/chunks/3399.js +526 -526
  239. package/.next/standalone/.next/server/chunks/3524.js +150 -67
  240. package/.next/standalone/.next/server/chunks/3566.js +1 -1
  241. package/.next/standalone/.next/server/chunks/4189.js +946 -0
  242. package/.next/standalone/.next/server/chunks/4433.js +146 -146
  243. package/.next/standalone/.next/server/chunks/4508.js +3 -3
  244. package/.next/standalone/.next/server/chunks/4588.js +1 -0
  245. package/.next/standalone/.next/server/chunks/46.js +78 -28
  246. package/.next/standalone/.next/server/chunks/466.js +12 -0
  247. package/.next/standalone/.next/server/chunks/4868.js +206 -206
  248. package/.next/standalone/.next/server/chunks/4992.js +13 -0
  249. package/.next/standalone/.next/server/chunks/5120.js +963 -0
  250. package/.next/standalone/.next/server/chunks/5701.js +1 -1
  251. package/.next/standalone/.next/server/chunks/5900.js +1 -1
  252. package/.next/standalone/.next/server/chunks/5908.js +63 -42
  253. package/.next/standalone/.next/server/chunks/6142.js +10 -2
  254. package/.next/standalone/.next/server/chunks/6210.js +1 -0
  255. package/.next/standalone/.next/server/chunks/6213.js +1 -1
  256. package/.next/standalone/.next/server/chunks/6649.js +3 -3
  257. package/.next/standalone/.next/server/chunks/6703.js +3 -3
  258. package/.next/standalone/.next/server/chunks/7445.js +1 -0
  259. package/.next/standalone/.next/server/chunks/8067.js +12 -0
  260. package/.next/standalone/.next/server/chunks/8461.js +24 -17
  261. package/.next/standalone/.next/server/chunks/8558.js +1 -1
  262. package/.next/standalone/.next/server/chunks/8724.js +1 -1
  263. package/.next/standalone/.next/server/chunks/8849.js +91 -91
  264. package/.next/standalone/.next/server/chunks/9032.js +4 -3
  265. package/.next/standalone/.next/server/chunks/{2563.js → 9164.js} +33389 -31418
  266. package/.next/standalone/.next/server/chunks/9237.js +396 -396
  267. package/.next/standalone/.next/server/chunks/{9640.js → 9304.js} +1672 -575
  268. package/.next/standalone/.next/server/chunks/9406.js +1 -1
  269. package/.next/standalone/.next/server/chunks/9590.js +68 -18
  270. package/.next/standalone/.next/server/chunks/9824.js +98 -98
  271. package/.next/standalone/.next/server/chunks/9826.js +1 -0
  272. package/.next/standalone/.next/server/middleware-build-manifest.js +2 -2
  273. package/.next/standalone/.next/server/middleware.js +486 -415
  274. package/.next/standalone/.next/server/pages/404.html +2 -2
  275. package/.next/standalone/.next/server/pages/500.html +1 -1
  276. package/.next/standalone/.next/server/preview-props.json +3 -3
  277. package/.next/standalone/.next/server/server-reference-manifest.json +1 -1
  278. package/.next/standalone/.next/static/chunks/{1395-a340fb0a345382a4.js → 1395-e4a99912b8f83044.js} +13 -1
  279. package/.next/standalone/.next/static/chunks/app/_global-error/{page-36cb8b428b38b26a.js → page-6fc5f8e744c81802.js} +1 -1
  280. package/.next/standalone/.next/static/chunks/app/api/v1/access/[identity]/{route-36cb8b428b38b26a.js → route-6fc5f8e744c81802.js} +1 -1
  281. package/.next/standalone/.next/static/chunks/app/api/v1/access/{route-36cb8b428b38b26a.js → route-6fc5f8e744c81802.js} +1 -1
  282. package/.next/standalone/.next/static/chunks/app/api/v1/agents/[id]/compact/{route-36cb8b428b38b26a.js → route-6fc5f8e744c81802.js} +1 -1
  283. package/.next/standalone/.next/static/chunks/app/api/v1/agents/[id]/display-filters/route-6fc5f8e744c81802.js +17 -0
  284. package/.next/standalone/.next/static/chunks/app/api/v1/agents/[id]/route-6fc5f8e744c81802.js +17 -0
  285. package/.next/standalone/.next/static/chunks/app/api/v1/agents/[id]/thread/route-6fc5f8e744c81802.js +17 -0
  286. package/.next/standalone/.next/static/chunks/app/api/v1/agents/route-6fc5f8e744c81802.js +17 -0
  287. package/.next/standalone/.next/static/chunks/app/api/v1/allowed-sites/[hostname]/route-6fc5f8e744c81802.js +17 -0
  288. package/.next/standalone/.next/static/chunks/app/api/v1/allowed-sites/route-6fc5f8e744c81802.js +17 -0
  289. package/.next/standalone/.next/static/chunks/app/api/v1/artifacts/lifecycle/route-6fc5f8e744c81802.js +17 -0
  290. package/.next/standalone/.next/static/chunks/app/api/v1/attachments/files/route-6fc5f8e744c81802.js +17 -0
  291. package/.next/standalone/.next/static/chunks/app/api/v1/attachments/images/route-6fc5f8e744c81802.js +17 -0
  292. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/[id]/chats/route-6fc5f8e744c81802.js +17 -0
  293. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/[id]/ignores/[remote_jid]/route-6fc5f8e744c81802.js +17 -0
  294. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/[id]/ignores/route-6fc5f8e744c81802.js +17 -0
  295. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/[id]/lookup/route-6fc5f8e744c81802.js +17 -0
  296. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/[id]/pair/route-6fc5f8e744c81802.js +17 -0
  297. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/[id]/route-6fc5f8e744c81802.js +17 -0
  298. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/[id]/routes/[route_id]/route-6fc5f8e744c81802.js +17 -0
  299. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/[id]/routes/route-6fc5f8e744c81802.js +17 -0
  300. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/[id]/status/route-6fc5f8e744c81802.js +17 -0
  301. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/kinds/route-6fc5f8e744c81802.js +17 -0
  302. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/route-6fc5f8e744c81802.js +17 -0
  303. package/.next/standalone/.next/static/chunks/app/api/v1/builtin-tools/route-6fc5f8e744c81802.js +17 -0
  304. package/.next/standalone/.next/static/chunks/app/api/v1/config/route-6fc5f8e744c81802.js +17 -0
  305. package/.next/standalone/.next/static/chunks/app/api/v1/credentials/[id]/route-6fc5f8e744c81802.js +17 -0
  306. package/.next/standalone/.next/static/chunks/app/api/v1/credentials/route-6fc5f8e744c81802.js +17 -0
  307. package/.next/standalone/.next/static/chunks/app/api/v1/dashboard/currency/route-6fc5f8e744c81802.js +17 -0
  308. package/.next/standalone/.next/static/chunks/app/api/v1/dashboard/metrics/route-6fc5f8e744c81802.js +17 -0
  309. package/.next/standalone/.next/static/chunks/app/api/v1/dashboard/pricing/route-6fc5f8e744c81802.js +17 -0
  310. package/.next/standalone/.next/static/chunks/app/api/v1/dashboard/pricing-task/route-6fc5f8e744c81802.js +17 -0
  311. package/.next/standalone/.next/static/chunks/app/api/v1/delegations/codex/[job_id]/route-6fc5f8e744c81802.js +17 -0
  312. package/.next/standalone/.next/static/chunks/app/api/v1/documents/search/route-6fc5f8e744c81802.js +17 -0
  313. package/.next/standalone/.next/static/chunks/app/api/v1/documents/settings/route-6fc5f8e744c81802.js +17 -0
  314. package/.next/standalone/.next/static/chunks/app/api/v1/documents/sources/[id]/reindex/route-6fc5f8e744c81802.js +17 -0
  315. package/.next/standalone/.next/static/chunks/app/api/v1/documents/sources/[id]/route-6fc5f8e744c81802.js +17 -0
  316. package/.next/standalone/.next/static/chunks/app/api/v1/documents/sources/route-6fc5f8e744c81802.js +17 -0
  317. package/.next/standalone/.next/static/chunks/app/api/v1/env/route-6fc5f8e744c81802.js +17 -0
  318. package/.next/standalone/.next/static/chunks/app/api/v1/env-sync/allowlist/route-6fc5f8e744c81802.js +17 -0
  319. package/.next/standalone/.next/static/chunks/app/api/v1/env-sync/route-6fc5f8e744c81802.js +17 -0
  320. package/.next/standalone/.next/static/chunks/app/api/v1/events/route-6fc5f8e744c81802.js +17 -0
  321. package/.next/standalone/.next/static/chunks/app/api/v1/events/test/route-6fc5f8e744c81802.js +17 -0
  322. package/.next/standalone/.next/static/chunks/app/api/v1/extension/agents/route-6fc5f8e744c81802.js +17 -0
  323. package/.next/standalone/.next/static/chunks/app/api/v1/extension/browser/activate/route-6fc5f8e744c81802.js +17 -0
  324. package/.next/standalone/.next/static/chunks/app/api/v1/extension/browser/foreground/route-6fc5f8e744c81802.js +17 -0
  325. package/.next/standalone/.next/static/chunks/app/api/v1/extension/browser/history/route-6fc5f8e744c81802.js +17 -0
  326. package/.next/standalone/.next/static/chunks/app/api/v1/extension/browser/poll/route-6fc5f8e744c81802.js +17 -0
  327. package/.next/standalone/.next/static/chunks/app/api/v1/extension/browser/progress/route-6fc5f8e744c81802.js +17 -0
  328. package/.next/standalone/.next/static/chunks/app/api/v1/extension/browser/result/route-6fc5f8e744c81802.js +17 -0
  329. package/.next/standalone/.next/static/chunks/app/api/v1/extension/browser/retry/route-6fc5f8e744c81802.js +17 -0
  330. package/.next/standalone/.next/static/chunks/app/api/v1/extension/browser/status/route-6fc5f8e744c81802.js +17 -0
  331. package/.next/standalone/.next/static/chunks/app/api/v1/extension/browser/tabs/route-6fc5f8e744c81802.js +17 -0
  332. package/.next/standalone/.next/static/chunks/app/api/v1/extension/fill/route-6fc5f8e744c81802.js +17 -0
  333. package/.next/standalone/.next/static/chunks/app/api/v1/extension/refine/route-6fc5f8e744c81802.js +17 -0
  334. package/.next/standalone/.next/static/chunks/app/api/v1/extension/turn/route-6fc5f8e744c81802.js +17 -0
  335. package/.next/standalone/.next/static/chunks/app/api/v1/extensions/route-6fc5f8e744c81802.js +17 -0
  336. package/.next/standalone/.next/static/chunks/app/api/v1/extensions/tools/[name]/config/route-6fc5f8e744c81802.js +17 -0
  337. package/.next/standalone/.next/static/chunks/app/api/v1/extensions/tools/[name]/route-6fc5f8e744c81802.js +17 -0
  338. package/.next/standalone/.next/static/chunks/app/api/v1/extensions/tools/[name]/secrets/route-6fc5f8e744c81802.js +17 -0
  339. package/.next/standalone/.next/static/chunks/app/api/v1/files/[name]/route-6fc5f8e744c81802.js +17 -0
  340. package/.next/standalone/.next/static/chunks/app/api/v1/fs/browse/route-6fc5f8e744c81802.js +17 -0
  341. package/.next/standalone/.next/static/chunks/app/api/v1/harnesses/[id]/route-6fc5f8e744c81802.js +17 -0
  342. package/.next/standalone/.next/static/chunks/app/api/v1/harnesses/default/route-6fc5f8e744c81802.js +17 -0
  343. package/.next/standalone/.next/static/chunks/app/api/v1/harnesses/route-6fc5f8e744c81802.js +17 -0
  344. package/.next/standalone/.next/static/chunks/app/api/v1/health/probes/route-6fc5f8e744c81802.js +17 -0
  345. package/.next/standalone/.next/static/chunks/app/api/v1/health/route-6fc5f8e744c81802.js +17 -0
  346. package/.next/standalone/.next/static/chunks/app/api/v1/integrations/[name]/route-6fc5f8e744c81802.js +17 -0
  347. package/.next/standalone/.next/static/chunks/app/api/v1/integrations/[name]/test/route-6fc5f8e744c81802.js +17 -0
  348. package/.next/standalone/.next/static/chunks/app/api/v1/integrations/gmail/oauth/callback/route-6fc5f8e744c81802.js +17 -0
  349. package/.next/standalone/.next/static/chunks/app/api/v1/integrations/gmail/oauth/start/route-6fc5f8e744c81802.js +17 -0
  350. package/.next/standalone/.next/static/chunks/app/api/v1/integrations/gmail/oauth/status/route-6fc5f8e744c81802.js +17 -0
  351. package/.next/standalone/.next/static/chunks/app/api/v1/integrations/outlook/oauth/callback/route-6fc5f8e744c81802.js +17 -0
  352. package/.next/standalone/.next/static/chunks/app/api/v1/integrations/outlook/oauth/start/route-6fc5f8e744c81802.js +17 -0
  353. package/.next/standalone/.next/static/chunks/app/api/v1/integrations/outlook/oauth/status/route-6fc5f8e744c81802.js +17 -0
  354. package/.next/standalone/.next/static/chunks/app/api/v1/integrations/route-6fc5f8e744c81802.js +17 -0
  355. package/.next/standalone/.next/static/chunks/app/api/v1/lifecycle/adoption/route-6fc5f8e744c81802.js +17 -0
  356. package/.next/standalone/.next/static/chunks/app/api/v1/local-file/route-6fc5f8e744c81802.js +17 -0
  357. package/.next/standalone/.next/static/chunks/app/api/v1/logs/route-6fc5f8e744c81802.js +17 -0
  358. package/.next/standalone/.next/static/chunks/app/api/v1/maps/embed/route-6fc5f8e744c81802.js +17 -0
  359. package/.next/standalone/.next/static/chunks/app/api/v1/mcp-servers/[name]/route-6fc5f8e744c81802.js +17 -0
  360. package/.next/standalone/.next/static/chunks/app/api/v1/mcp-servers/registry/route-6fc5f8e744c81802.js +17 -0
  361. package/.next/standalone/.next/static/chunks/app/api/v1/mcp-servers/route-6fc5f8e744c81802.js +17 -0
  362. package/.next/standalone/.next/static/chunks/app/api/v1/memory/[namespace]/[key]/route-6fc5f8e744c81802.js +17 -0
  363. package/.next/standalone/.next/static/chunks/app/api/v1/memory/policy/route-6fc5f8e744c81802.js +17 -0
  364. package/.next/standalone/.next/static/chunks/app/api/v1/memory/route-6fc5f8e744c81802.js +17 -0
  365. package/.next/standalone/.next/static/chunks/app/api/v1/memory/search/route-6fc5f8e744c81802.js +17 -0
  366. package/.next/standalone/.next/static/chunks/app/api/v1/models/[name]/compact-threads/route-6fc5f8e744c81802.js +17 -0
  367. package/.next/standalone/.next/static/chunks/app/api/v1/models/[name]/route-6fc5f8e744c81802.js +17 -0
  368. package/.next/standalone/.next/static/chunks/app/api/v1/models/route-6fc5f8e744c81802.js +17 -0
  369. package/.next/standalone/.next/static/chunks/app/api/v1/packages/catalog/route-6fc5f8e744c81802.js +17 -0
  370. package/.next/standalone/.next/static/chunks/app/api/v1/packages/defaults/[id]/route-6fc5f8e744c81802.js +17 -0
  371. package/.next/standalone/.next/static/chunks/app/api/v1/packages/install/[id]/route-6fc5f8e744c81802.js +17 -0
  372. package/.next/standalone/.next/static/chunks/app/api/v1/packages/install/route-6fc5f8e744c81802.js +17 -0
  373. package/.next/standalone/.next/static/chunks/app/api/v1/packages/manifests/[name]/enabled/route-6fc5f8e744c81802.js +17 -0
  374. package/.next/standalone/.next/static/chunks/app/api/v1/packages/manifests/[name]/route-6fc5f8e744c81802.js +17 -0
  375. package/.next/standalone/.next/static/chunks/app/api/v1/packages/manifests/route-6fc5f8e744c81802.js +17 -0
  376. package/.next/standalone/.next/static/chunks/app/api/v1/packages/reload/route-6fc5f8e744c81802.js +17 -0
  377. package/.next/standalone/.next/static/chunks/app/api/v1/packages/route-6fc5f8e744c81802.js +17 -0
  378. package/.next/standalone/.next/static/chunks/app/api/v1/page-capture/route-6fc5f8e744c81802.js +17 -0
  379. package/.next/standalone/.next/static/chunks/app/api/v1/pending-actions/[id]/approve/route-6fc5f8e744c81802.js +17 -0
  380. package/.next/standalone/.next/static/chunks/app/api/v1/pending-actions/[id]/deny/route-6fc5f8e744c81802.js +17 -0
  381. package/.next/standalone/.next/static/chunks/app/api/v1/pending-actions/route-6fc5f8e744c81802.js +17 -0
  382. package/.next/standalone/.next/static/chunks/app/api/v1/profile/location/route-6fc5f8e744c81802.js +17 -0
  383. package/.next/standalone/.next/static/chunks/app/api/v1/profile/route-6fc5f8e744c81802.js +17 -0
  384. package/.next/standalone/.next/static/chunks/app/api/v1/providers/[provider]/models/route-6fc5f8e744c81802.js +17 -0
  385. package/.next/standalone/.next/static/chunks/app/api/v1/providers/[provider]/probe/route-6fc5f8e744c81802.js +17 -0
  386. package/.next/standalone/.next/static/chunks/app/api/v1/providers/github-copilot/auth/route-6fc5f8e744c81802.js +17 -0
  387. package/.next/standalone/.next/static/chunks/app/api/v1/providers/route-6fc5f8e744c81802.js +17 -0
  388. package/.next/standalone/.next/static/chunks/app/api/v1/proxy-config/route-6fc5f8e744c81802.js +17 -0
  389. package/.next/standalone/.next/static/chunks/app/api/v1/redaction/init/route-6fc5f8e744c81802.js +17 -0
  390. package/.next/standalone/.next/static/chunks/app/api/v1/redaction/route-6fc5f8e744c81802.js +17 -0
  391. package/.next/standalone/.next/static/chunks/app/api/v1/scheduled-tasks/[id]/route-6fc5f8e744c81802.js +17 -0
  392. package/.next/standalone/.next/static/chunks/app/api/v1/scheduled-tasks/[id]/run/route-6fc5f8e744c81802.js +17 -0
  393. package/.next/standalone/.next/static/chunks/app/api/v1/scheduled-tasks/route-6fc5f8e744c81802.js +17 -0
  394. package/.next/standalone/.next/static/chunks/app/api/v1/security/idle-timeout/route-6fc5f8e744c81802.js +17 -0
  395. package/.next/standalone/.next/static/chunks/app/api/v1/security/pin/route-6fc5f8e744c81802.js +17 -0
  396. package/.next/standalone/.next/static/chunks/app/api/v1/security/state/route-6fc5f8e744c81802.js +17 -0
  397. package/.next/standalone/.next/static/chunks/app/api/v1/security/unlock/route-6fc5f8e744c81802.js +17 -0
  398. package/.next/standalone/.next/static/chunks/app/api/v1/security/verify-pin/route-6fc5f8e744c81802.js +17 -0
  399. package/.next/standalone/.next/static/chunks/app/api/v1/setup/test-key/route-6fc5f8e744c81802.js +17 -0
  400. package/.next/standalone/.next/static/chunks/app/api/v1/skills/[id]/route-6fc5f8e744c81802.js +17 -0
  401. package/.next/standalone/.next/static/chunks/app/api/v1/skills/repos/[id]/route-6fc5f8e744c81802.js +17 -0
  402. package/.next/standalone/.next/static/chunks/app/api/v1/skills/repos/route-6fc5f8e744c81802.js +17 -0
  403. package/.next/standalone/.next/static/chunks/app/api/v1/skills/route-6fc5f8e744c81802.js +17 -0
  404. package/.next/standalone/.next/static/chunks/app/api/v1/system/abort/route-6fc5f8e744c81802.js +17 -0
  405. package/.next/standalone/.next/static/chunks/app/api/v1/system/restart/route-6fc5f8e744c81802.js +17 -0
  406. package/.next/standalone/.next/static/chunks/app/api/v1/tailscale/route-6fc5f8e744c81802.js +17 -0
  407. package/.next/standalone/.next/static/chunks/app/api/v1/tasks/[agent_id]/route-6fc5f8e744c81802.js +17 -0
  408. package/.next/standalone/.next/static/chunks/app/api/v1/tasks/route-6fc5f8e744c81802.js +17 -0
  409. package/.next/standalone/.next/static/chunks/app/api/v1/threads/[thread_id]/activity/route-6fc5f8e744c81802.js +17 -0
  410. package/.next/standalone/.next/static/chunks/app/api/v1/threads/[thread_id]/context-pin/route-6fc5f8e744c81802.js +17 -0
  411. package/.next/standalone/.next/static/chunks/app/api/v1/threads/[thread_id]/route-6fc5f8e744c81802.js +17 -0
  412. package/.next/standalone/.next/static/chunks/app/api/v1/threads/[thread_id]/run/route-6fc5f8e744c81802.js +17 -0
  413. package/.next/standalone/.next/static/chunks/app/api/v1/threads/route-6fc5f8e744c81802.js +17 -0
  414. package/.next/standalone/.next/static/chunks/app/api/v1/tools/route-6fc5f8e744c81802.js +17 -0
  415. package/.next/standalone/.next/static/chunks/app/api/v1/update/apply/route-6fc5f8e744c81802.js +17 -0
  416. package/.next/standalone/.next/static/chunks/app/api/v1/update/route-6fc5f8e744c81802.js +17 -0
  417. package/.next/standalone/.next/static/chunks/app/api/v1/voice/transcribe/route-6fc5f8e744c81802.js +17 -0
  418. package/.next/standalone/.next/static/chunks/app/api/v1/voice/tts/route-6fc5f8e744c81802.js +17 -0
  419. package/.next/standalone/.next/static/chunks/app/api/v1/watchers/[id]/route-6fc5f8e744c81802.js +17 -0
  420. package/.next/standalone/.next/static/chunks/app/api/v1/watchers/[id]/run/route-6fc5f8e744c81802.js +17 -0
  421. package/.next/standalone/.next/static/chunks/app/api/v1/watchers/reaction-scripts/route-6fc5f8e744c81802.js +17 -0
  422. package/.next/standalone/.next/static/chunks/app/api/v1/watchers/route-6fc5f8e744c81802.js +17 -0
  423. package/.next/standalone/.next/static/chunks/app/manifest.webmanifest/route-6fc5f8e744c81802.js +17 -0
  424. package/.next/standalone/.next/static/chunks/app/{page-7017f07f8a7a083c.js → page-04748847c6ff866f.js} +1013 -585
  425. package/.next/standalone/.next/static/chunks/next/dist/client/components/builtin/app-error-6fc5f8e744c81802.js +17 -0
  426. package/.next/standalone/.next/static/chunks/next/dist/client/components/builtin/forbidden-6fc5f8e744c81802.js +17 -0
  427. package/.next/standalone/.next/static/chunks/next/dist/client/components/builtin/not-found-6fc5f8e744c81802.js +17 -0
  428. package/.next/standalone/.next/static/chunks/next/dist/client/components/builtin/unauthorized-6fc5f8e744c81802.js +17 -0
  429. package/.next/standalone/.next/static/css/{d80058f0b9b41c09.css → 2669e8744cc8c212.css} +2 -2
  430. package/.next/standalone/docs/adoption/changesets.json +358 -0
  431. package/.next/standalone/lib/skills/builtins/memory-organization/SKILL.md +16 -0
  432. package/.next/standalone/package.json +3 -3
  433. package/CHANGELOG.md +44 -0
  434. package/api/client.ts +9 -0
  435. package/api/types.ts +29 -0
  436. package/app/api/v1/lifecycle/adoption/route.ts +14 -2
  437. package/app/api/v1/models/[name]/compact-threads/route.ts +14 -11
  438. package/app/api/v1/threads/[thread_id]/activity/route.ts +19 -0
  439. package/app/api/v1/threads/[thread_id]/context-pin/route.test.ts +1 -0
  440. package/app/api/v1/threads/[thread_id]/context-pin/route.ts +2 -1
  441. package/app/api/v1/threads/[thread_id]/route.ts +5 -1
  442. package/app/api/v1/threads/[thread_id]/run/route.ts +0 -1
  443. package/components/chat/ChatView.tsx +52 -11
  444. package/components/chat/ContextBoundary.test.tsx +68 -1
  445. package/components/chat/ContextBoundary.tsx +92 -13
  446. package/components/chat/MessageBubble.tsx +12 -0
  447. package/components/chat/MessageList.test.tsx +31 -0
  448. package/components/chat/MessageList.tsx +49 -28
  449. package/components/chat/ToolList.test.tsx +92 -16
  450. package/components/chat/ToolList.tsx +59 -4
  451. package/components/chat/chat-helpers.test.tsx +24 -1
  452. package/components/chat/chat-helpers.ts +47 -4
  453. package/components/chat/useThreadActivity.test.tsx +113 -0
  454. package/components/chat/useThreadActivity.ts +94 -0
  455. package/components/chat/useThreadData.ts +16 -16
  456. package/components/chat/workflow-step-retry.ts +25 -0
  457. package/components/integrations/NetworkSection.tsx +2 -2
  458. package/components/ui/BootScreen.tsx +17 -0
  459. package/components/ui/WorkflowChecklist.tsx +71 -33
  460. package/hooks/useSSE.ts +28 -3
  461. package/lib/agents/citation-checker.test.ts +40 -2
  462. package/lib/agents/citation-checker.ts +56 -11
  463. package/lib/agents/compaction-pipeline.test.ts +202 -0
  464. package/lib/agents/compaction-pipeline.ts +483 -0
  465. package/lib/agents/context-boundary.ts +5 -6
  466. package/lib/agents/conversation-summary.ts +37 -21
  467. package/lib/agents/instruction-edits.test.ts +120 -0
  468. package/lib/agents/instruction-edits.ts +65 -42
  469. package/lib/agents/prepare/history-window.test.ts +18 -0
  470. package/lib/agents/prepare/history-window.ts +11 -2
  471. package/lib/agents/prepare/request.ts +4 -2
  472. package/lib/agents/prepare/system-prompt.test.ts +49 -0
  473. package/lib/agents/prepare/system-prompt.ts +16 -5
  474. package/lib/agents/prompt-registry.test.ts +5 -140
  475. package/lib/agents/prompt-registry.ts +45 -1
  476. package/lib/agents/prompt-variants.ts +146 -0
  477. package/lib/agents/proposals.test.ts +76 -0
  478. package/lib/agents/proposals.ts +13 -5
  479. package/lib/agents/run-registry.test.ts +22 -0
  480. package/lib/agents/run-registry.ts +29 -0
  481. package/lib/agents/run-thread.auto-boundary.test.ts +125 -5
  482. package/lib/agents/run-thread.retry.test.ts +67 -1
  483. package/lib/agents/run-thread.ts +110 -10
  484. package/lib/agents/sqlite-checkpoint-saver.test.ts +91 -0
  485. package/lib/agents/thread-activity.test.ts +31 -0
  486. package/lib/agents/thread-activity.ts +27 -0
  487. package/lib/agents/thread-compaction-state.test.ts +82 -0
  488. package/lib/agents/thread-compaction-state.ts +121 -0
  489. package/lib/agents/thread-compaction.test.ts +83 -4
  490. package/lib/agents/thread-compaction.ts +34 -11
  491. package/lib/agents/warm-summary-background.test.ts +219 -5
  492. package/lib/agents/warm-summary-background.ts +346 -143
  493. package/lib/agents/warm-topics.test.ts +191 -0
  494. package/lib/agents/warm-topics.ts +317 -0
  495. package/lib/agents/workflow-step-retry.test.ts +96 -0
  496. package/lib/agents/workflow-step-retry.ts +216 -0
  497. package/lib/api/browser-control.ts +0 -3
  498. package/lib/bridges/dispatcher.ts +1 -0
  499. package/lib/bridges/message-role.test.ts +81 -0
  500. package/lib/bridges/message-role.ts +23 -10
  501. package/lib/bridges/types.ts +6 -0
  502. package/lib/bridges/whatsapp-link.test.ts +32 -0
  503. package/lib/bridges/whatsapp-link.ts +21 -0
  504. package/lib/bridges/whatsapp.inbound.test.ts +239 -0
  505. package/lib/bridges/whatsapp.sender.test.ts +80 -1
  506. package/lib/bridges/whatsapp.ts +76 -38
  507. package/lib/db/migrations.ts +5 -0
  508. package/lib/env/config.ts +2 -0
  509. package/lib/env/schema.ts +12 -0
  510. package/lib/lifecycle/changeset-build.test.ts +93 -0
  511. package/lib/lifecycle/changeset-build.ts +210 -0
  512. package/lib/lifecycle/changesets.test.ts +101 -0
  513. package/lib/lifecycle/changesets.ts +166 -0
  514. package/lib/lifecycle/surface-collect.test.ts +88 -0
  515. package/lib/lifecycle/surface-collect.ts +64 -0
  516. package/lib/lifecycle/surface-snapshot.test.ts +104 -0
  517. package/lib/lifecycle/surface-snapshot.ts +210 -0
  518. package/lib/memory/record.ts +0 -2
  519. package/lib/pricing/snapshot.test.ts +70 -0
  520. package/lib/pricing/snapshot.ts +10 -2
  521. package/lib/providers/external.ts +0 -2
  522. package/lib/proxy/dispatcher.test.ts +119 -1
  523. package/lib/proxy/dispatcher.ts +22 -9
  524. package/lib/skills/builtins/memory-organization/SKILL.md +16 -0
  525. package/lib/stores/agent-configs.ts +10 -5
  526. package/lib/stores/bridges.test.ts +81 -0
  527. package/lib/stores/bridges.ts +9 -8
  528. package/lib/stores/proxy-config.test.ts +120 -0
  529. package/lib/stores/proxy-config.ts +22 -4
  530. package/lib/stores/threads.test.ts +9 -0
  531. package/lib/stores/threads.ts +33 -19
  532. package/lib/stores/version-adoption.test.ts +96 -0
  533. package/lib/stores/version-adoption.ts +239 -26
  534. package/lib/stores/workflow-progress.ts +3 -0
  535. package/lib/tools/communications/calendar.test.ts +43 -2
  536. package/lib/tools/communications/calendar.ts +2 -0
  537. package/lib/tools/communications/gmail.test.ts +51 -1
  538. package/lib/tools/communications/gmail.ts +44 -2
  539. package/lib/tools/communications/ms-todo.ts +0 -7
  540. package/lib/tools/communications/outlook-calendar.ts +2 -0
  541. package/lib/tools/communications/outlook.test.ts +33 -2
  542. package/lib/tools/communications/outlook.ts +2 -0
  543. package/lib/tools/filesystem/edit-match.test.ts +133 -0
  544. package/lib/tools/filesystem/edit-match.ts +7 -2
  545. package/lib/tools/general/memory.ts +1 -1
  546. package/lib/tools/general/workflow-progress.ts +2 -0
  547. package/lib/tools/runtime/catalog.ts +1 -25
  548. package/lib/tools/support/result-refs.test.ts +131 -0
  549. package/lib/tools/support/result-refs.ts +41 -9
  550. package/lib/triggers/registry.ts +0 -4
  551. package/lib/utils/source-link.test.ts +51 -0
  552. package/lib/utils/source-link.ts +45 -0
  553. package/package.json +3 -3
  554. package/scripts/install-to-system.ps1 +39 -11
  555. package/scripts/install-to-system.sh +37 -3
  556. package/.next/standalone/.next/server/chunks/3979.js +0 -581
  557. package/.next/standalone/.next/server/chunks/5936.js +0 -594
  558. package/.next/standalone/.next/static/chunks/app/api/v1/agents/[id]/display-filters/route-36cb8b428b38b26a.js +0 -17
  559. package/.next/standalone/.next/static/chunks/app/api/v1/agents/[id]/route-36cb8b428b38b26a.js +0 -17
  560. package/.next/standalone/.next/static/chunks/app/api/v1/agents/[id]/thread/route-36cb8b428b38b26a.js +0 -17
  561. package/.next/standalone/.next/static/chunks/app/api/v1/agents/route-36cb8b428b38b26a.js +0 -17
  562. package/.next/standalone/.next/static/chunks/app/api/v1/allowed-sites/[hostname]/route-36cb8b428b38b26a.js +0 -17
  563. package/.next/standalone/.next/static/chunks/app/api/v1/allowed-sites/route-36cb8b428b38b26a.js +0 -17
  564. package/.next/standalone/.next/static/chunks/app/api/v1/artifacts/lifecycle/route-36cb8b428b38b26a.js +0 -17
  565. package/.next/standalone/.next/static/chunks/app/api/v1/attachments/files/route-36cb8b428b38b26a.js +0 -17
  566. package/.next/standalone/.next/static/chunks/app/api/v1/attachments/images/route-36cb8b428b38b26a.js +0 -17
  567. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/[id]/chats/route-36cb8b428b38b26a.js +0 -17
  568. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/[id]/ignores/[remote_jid]/route-36cb8b428b38b26a.js +0 -17
  569. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/[id]/ignores/route-36cb8b428b38b26a.js +0 -17
  570. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/[id]/lookup/route-36cb8b428b38b26a.js +0 -17
  571. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/[id]/pair/route-36cb8b428b38b26a.js +0 -17
  572. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/[id]/route-36cb8b428b38b26a.js +0 -17
  573. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/[id]/routes/[route_id]/route-36cb8b428b38b26a.js +0 -17
  574. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/[id]/routes/route-36cb8b428b38b26a.js +0 -17
  575. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/[id]/status/route-36cb8b428b38b26a.js +0 -17
  576. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/kinds/route-36cb8b428b38b26a.js +0 -17
  577. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/route-36cb8b428b38b26a.js +0 -17
  578. package/.next/standalone/.next/static/chunks/app/api/v1/builtin-tools/route-36cb8b428b38b26a.js +0 -17
  579. package/.next/standalone/.next/static/chunks/app/api/v1/config/route-36cb8b428b38b26a.js +0 -17
  580. package/.next/standalone/.next/static/chunks/app/api/v1/credentials/[id]/route-36cb8b428b38b26a.js +0 -17
  581. package/.next/standalone/.next/static/chunks/app/api/v1/credentials/route-36cb8b428b38b26a.js +0 -17
  582. package/.next/standalone/.next/static/chunks/app/api/v1/dashboard/currency/route-36cb8b428b38b26a.js +0 -17
  583. package/.next/standalone/.next/static/chunks/app/api/v1/dashboard/metrics/route-36cb8b428b38b26a.js +0 -17
  584. package/.next/standalone/.next/static/chunks/app/api/v1/dashboard/pricing/route-36cb8b428b38b26a.js +0 -17
  585. package/.next/standalone/.next/static/chunks/app/api/v1/dashboard/pricing-task/route-36cb8b428b38b26a.js +0 -17
  586. package/.next/standalone/.next/static/chunks/app/api/v1/delegations/codex/[job_id]/route-36cb8b428b38b26a.js +0 -17
  587. package/.next/standalone/.next/static/chunks/app/api/v1/documents/search/route-36cb8b428b38b26a.js +0 -17
  588. package/.next/standalone/.next/static/chunks/app/api/v1/documents/settings/route-36cb8b428b38b26a.js +0 -17
  589. package/.next/standalone/.next/static/chunks/app/api/v1/documents/sources/[id]/reindex/route-36cb8b428b38b26a.js +0 -17
  590. package/.next/standalone/.next/static/chunks/app/api/v1/documents/sources/[id]/route-36cb8b428b38b26a.js +0 -17
  591. package/.next/standalone/.next/static/chunks/app/api/v1/documents/sources/route-36cb8b428b38b26a.js +0 -17
  592. package/.next/standalone/.next/static/chunks/app/api/v1/env/route-36cb8b428b38b26a.js +0 -17
  593. package/.next/standalone/.next/static/chunks/app/api/v1/env-sync/allowlist/route-36cb8b428b38b26a.js +0 -17
  594. package/.next/standalone/.next/static/chunks/app/api/v1/env-sync/route-36cb8b428b38b26a.js +0 -17
  595. package/.next/standalone/.next/static/chunks/app/api/v1/events/route-36cb8b428b38b26a.js +0 -17
  596. package/.next/standalone/.next/static/chunks/app/api/v1/events/test/route-36cb8b428b38b26a.js +0 -17
  597. package/.next/standalone/.next/static/chunks/app/api/v1/extension/agents/route-36cb8b428b38b26a.js +0 -17
  598. package/.next/standalone/.next/static/chunks/app/api/v1/extension/browser/activate/route-36cb8b428b38b26a.js +0 -17
  599. package/.next/standalone/.next/static/chunks/app/api/v1/extension/browser/foreground/route-36cb8b428b38b26a.js +0 -17
  600. package/.next/standalone/.next/static/chunks/app/api/v1/extension/browser/history/route-36cb8b428b38b26a.js +0 -17
  601. package/.next/standalone/.next/static/chunks/app/api/v1/extension/browser/poll/route-36cb8b428b38b26a.js +0 -17
  602. package/.next/standalone/.next/static/chunks/app/api/v1/extension/browser/progress/route-36cb8b428b38b26a.js +0 -17
  603. package/.next/standalone/.next/static/chunks/app/api/v1/extension/browser/result/route-36cb8b428b38b26a.js +0 -17
  604. package/.next/standalone/.next/static/chunks/app/api/v1/extension/browser/retry/route-36cb8b428b38b26a.js +0 -17
  605. package/.next/standalone/.next/static/chunks/app/api/v1/extension/browser/status/route-36cb8b428b38b26a.js +0 -17
  606. package/.next/standalone/.next/static/chunks/app/api/v1/extension/browser/tabs/route-36cb8b428b38b26a.js +0 -17
  607. package/.next/standalone/.next/static/chunks/app/api/v1/extension/fill/route-36cb8b428b38b26a.js +0 -17
  608. package/.next/standalone/.next/static/chunks/app/api/v1/extension/refine/route-36cb8b428b38b26a.js +0 -17
  609. package/.next/standalone/.next/static/chunks/app/api/v1/extension/turn/route-36cb8b428b38b26a.js +0 -17
  610. package/.next/standalone/.next/static/chunks/app/api/v1/extensions/route-36cb8b428b38b26a.js +0 -17
  611. package/.next/standalone/.next/static/chunks/app/api/v1/extensions/tools/[name]/config/route-36cb8b428b38b26a.js +0 -17
  612. package/.next/standalone/.next/static/chunks/app/api/v1/extensions/tools/[name]/route-36cb8b428b38b26a.js +0 -17
  613. package/.next/standalone/.next/static/chunks/app/api/v1/extensions/tools/[name]/secrets/route-36cb8b428b38b26a.js +0 -17
  614. package/.next/standalone/.next/static/chunks/app/api/v1/files/[name]/route-36cb8b428b38b26a.js +0 -17
  615. package/.next/standalone/.next/static/chunks/app/api/v1/fs/browse/route-36cb8b428b38b26a.js +0 -17
  616. package/.next/standalone/.next/static/chunks/app/api/v1/harnesses/[id]/route-36cb8b428b38b26a.js +0 -17
  617. package/.next/standalone/.next/static/chunks/app/api/v1/harnesses/default/route-36cb8b428b38b26a.js +0 -17
  618. package/.next/standalone/.next/static/chunks/app/api/v1/harnesses/route-36cb8b428b38b26a.js +0 -17
  619. package/.next/standalone/.next/static/chunks/app/api/v1/health/probes/route-36cb8b428b38b26a.js +0 -17
  620. package/.next/standalone/.next/static/chunks/app/api/v1/health/route-36cb8b428b38b26a.js +0 -17
  621. package/.next/standalone/.next/static/chunks/app/api/v1/integrations/[name]/route-36cb8b428b38b26a.js +0 -17
  622. package/.next/standalone/.next/static/chunks/app/api/v1/integrations/[name]/test/route-36cb8b428b38b26a.js +0 -17
  623. package/.next/standalone/.next/static/chunks/app/api/v1/integrations/gmail/oauth/callback/route-36cb8b428b38b26a.js +0 -17
  624. package/.next/standalone/.next/static/chunks/app/api/v1/integrations/gmail/oauth/start/route-36cb8b428b38b26a.js +0 -17
  625. package/.next/standalone/.next/static/chunks/app/api/v1/integrations/gmail/oauth/status/route-36cb8b428b38b26a.js +0 -17
  626. package/.next/standalone/.next/static/chunks/app/api/v1/integrations/outlook/oauth/callback/route-36cb8b428b38b26a.js +0 -17
  627. package/.next/standalone/.next/static/chunks/app/api/v1/integrations/outlook/oauth/start/route-36cb8b428b38b26a.js +0 -17
  628. package/.next/standalone/.next/static/chunks/app/api/v1/integrations/outlook/oauth/status/route-36cb8b428b38b26a.js +0 -17
  629. package/.next/standalone/.next/static/chunks/app/api/v1/integrations/route-36cb8b428b38b26a.js +0 -17
  630. package/.next/standalone/.next/static/chunks/app/api/v1/lifecycle/adoption/route-36cb8b428b38b26a.js +0 -17
  631. package/.next/standalone/.next/static/chunks/app/api/v1/local-file/route-36cb8b428b38b26a.js +0 -17
  632. package/.next/standalone/.next/static/chunks/app/api/v1/logs/route-36cb8b428b38b26a.js +0 -17
  633. package/.next/standalone/.next/static/chunks/app/api/v1/maps/embed/route-36cb8b428b38b26a.js +0 -17
  634. package/.next/standalone/.next/static/chunks/app/api/v1/mcp-servers/[name]/route-36cb8b428b38b26a.js +0 -17
  635. package/.next/standalone/.next/static/chunks/app/api/v1/mcp-servers/registry/route-36cb8b428b38b26a.js +0 -17
  636. package/.next/standalone/.next/static/chunks/app/api/v1/mcp-servers/route-36cb8b428b38b26a.js +0 -17
  637. package/.next/standalone/.next/static/chunks/app/api/v1/memory/[namespace]/[key]/route-36cb8b428b38b26a.js +0 -17
  638. package/.next/standalone/.next/static/chunks/app/api/v1/memory/policy/route-36cb8b428b38b26a.js +0 -17
  639. package/.next/standalone/.next/static/chunks/app/api/v1/memory/route-36cb8b428b38b26a.js +0 -17
  640. package/.next/standalone/.next/static/chunks/app/api/v1/memory/search/route-36cb8b428b38b26a.js +0 -17
  641. package/.next/standalone/.next/static/chunks/app/api/v1/models/[name]/compact-threads/route-36cb8b428b38b26a.js +0 -17
  642. package/.next/standalone/.next/static/chunks/app/api/v1/models/[name]/route-36cb8b428b38b26a.js +0 -17
  643. package/.next/standalone/.next/static/chunks/app/api/v1/models/route-36cb8b428b38b26a.js +0 -17
  644. package/.next/standalone/.next/static/chunks/app/api/v1/packages/catalog/route-36cb8b428b38b26a.js +0 -17
  645. package/.next/standalone/.next/static/chunks/app/api/v1/packages/defaults/[id]/route-36cb8b428b38b26a.js +0 -17
  646. package/.next/standalone/.next/static/chunks/app/api/v1/packages/install/[id]/route-36cb8b428b38b26a.js +0 -17
  647. package/.next/standalone/.next/static/chunks/app/api/v1/packages/install/route-36cb8b428b38b26a.js +0 -17
  648. package/.next/standalone/.next/static/chunks/app/api/v1/packages/manifests/[name]/enabled/route-36cb8b428b38b26a.js +0 -17
  649. package/.next/standalone/.next/static/chunks/app/api/v1/packages/manifests/[name]/route-36cb8b428b38b26a.js +0 -17
  650. package/.next/standalone/.next/static/chunks/app/api/v1/packages/manifests/route-36cb8b428b38b26a.js +0 -17
  651. package/.next/standalone/.next/static/chunks/app/api/v1/packages/reload/route-36cb8b428b38b26a.js +0 -17
  652. package/.next/standalone/.next/static/chunks/app/api/v1/packages/route-36cb8b428b38b26a.js +0 -17
  653. package/.next/standalone/.next/static/chunks/app/api/v1/page-capture/route-36cb8b428b38b26a.js +0 -17
  654. package/.next/standalone/.next/static/chunks/app/api/v1/pending-actions/[id]/approve/route-36cb8b428b38b26a.js +0 -17
  655. package/.next/standalone/.next/static/chunks/app/api/v1/pending-actions/[id]/deny/route-36cb8b428b38b26a.js +0 -17
  656. package/.next/standalone/.next/static/chunks/app/api/v1/pending-actions/route-36cb8b428b38b26a.js +0 -17
  657. package/.next/standalone/.next/static/chunks/app/api/v1/profile/location/route-36cb8b428b38b26a.js +0 -17
  658. package/.next/standalone/.next/static/chunks/app/api/v1/profile/route-36cb8b428b38b26a.js +0 -17
  659. package/.next/standalone/.next/static/chunks/app/api/v1/providers/[provider]/models/route-36cb8b428b38b26a.js +0 -17
  660. package/.next/standalone/.next/static/chunks/app/api/v1/providers/[provider]/probe/route-36cb8b428b38b26a.js +0 -17
  661. package/.next/standalone/.next/static/chunks/app/api/v1/providers/github-copilot/auth/route-36cb8b428b38b26a.js +0 -17
  662. package/.next/standalone/.next/static/chunks/app/api/v1/providers/route-36cb8b428b38b26a.js +0 -17
  663. package/.next/standalone/.next/static/chunks/app/api/v1/proxy-config/route-36cb8b428b38b26a.js +0 -17
  664. package/.next/standalone/.next/static/chunks/app/api/v1/redaction/init/route-36cb8b428b38b26a.js +0 -17
  665. package/.next/standalone/.next/static/chunks/app/api/v1/redaction/route-36cb8b428b38b26a.js +0 -17
  666. package/.next/standalone/.next/static/chunks/app/api/v1/scheduled-tasks/[id]/route-36cb8b428b38b26a.js +0 -17
  667. package/.next/standalone/.next/static/chunks/app/api/v1/scheduled-tasks/[id]/run/route-36cb8b428b38b26a.js +0 -17
  668. package/.next/standalone/.next/static/chunks/app/api/v1/scheduled-tasks/route-36cb8b428b38b26a.js +0 -17
  669. package/.next/standalone/.next/static/chunks/app/api/v1/security/idle-timeout/route-36cb8b428b38b26a.js +0 -17
  670. package/.next/standalone/.next/static/chunks/app/api/v1/security/pin/route-36cb8b428b38b26a.js +0 -17
  671. package/.next/standalone/.next/static/chunks/app/api/v1/security/state/route-36cb8b428b38b26a.js +0 -17
  672. package/.next/standalone/.next/static/chunks/app/api/v1/security/unlock/route-36cb8b428b38b26a.js +0 -17
  673. package/.next/standalone/.next/static/chunks/app/api/v1/security/verify-pin/route-36cb8b428b38b26a.js +0 -17
  674. package/.next/standalone/.next/static/chunks/app/api/v1/setup/test-key/route-36cb8b428b38b26a.js +0 -17
  675. package/.next/standalone/.next/static/chunks/app/api/v1/skills/[id]/route-36cb8b428b38b26a.js +0 -17
  676. package/.next/standalone/.next/static/chunks/app/api/v1/skills/repos/[id]/route-36cb8b428b38b26a.js +0 -17
  677. package/.next/standalone/.next/static/chunks/app/api/v1/skills/repos/route-36cb8b428b38b26a.js +0 -17
  678. package/.next/standalone/.next/static/chunks/app/api/v1/skills/route-36cb8b428b38b26a.js +0 -17
  679. package/.next/standalone/.next/static/chunks/app/api/v1/system/abort/route-36cb8b428b38b26a.js +0 -17
  680. package/.next/standalone/.next/static/chunks/app/api/v1/system/restart/route-36cb8b428b38b26a.js +0 -17
  681. package/.next/standalone/.next/static/chunks/app/api/v1/tailscale/route-36cb8b428b38b26a.js +0 -17
  682. package/.next/standalone/.next/static/chunks/app/api/v1/tasks/[agent_id]/route-36cb8b428b38b26a.js +0 -17
  683. package/.next/standalone/.next/static/chunks/app/api/v1/tasks/route-36cb8b428b38b26a.js +0 -17
  684. package/.next/standalone/.next/static/chunks/app/api/v1/threads/[thread_id]/context-pin/route-36cb8b428b38b26a.js +0 -17
  685. package/.next/standalone/.next/static/chunks/app/api/v1/threads/[thread_id]/route-36cb8b428b38b26a.js +0 -17
  686. package/.next/standalone/.next/static/chunks/app/api/v1/threads/[thread_id]/run/route-36cb8b428b38b26a.js +0 -17
  687. package/.next/standalone/.next/static/chunks/app/api/v1/threads/route-36cb8b428b38b26a.js +0 -17
  688. package/.next/standalone/.next/static/chunks/app/api/v1/tools/route-36cb8b428b38b26a.js +0 -17
  689. package/.next/standalone/.next/static/chunks/app/api/v1/update/apply/route-36cb8b428b38b26a.js +0 -17
  690. package/.next/standalone/.next/static/chunks/app/api/v1/update/route-36cb8b428b38b26a.js +0 -17
  691. package/.next/standalone/.next/static/chunks/app/api/v1/voice/transcribe/route-36cb8b428b38b26a.js +0 -17
  692. package/.next/standalone/.next/static/chunks/app/api/v1/voice/tts/route-36cb8b428b38b26a.js +0 -17
  693. package/.next/standalone/.next/static/chunks/app/api/v1/watchers/[id]/route-36cb8b428b38b26a.js +0 -17
  694. package/.next/standalone/.next/static/chunks/app/api/v1/watchers/[id]/run/route-36cb8b428b38b26a.js +0 -17
  695. package/.next/standalone/.next/static/chunks/app/api/v1/watchers/reaction-scripts/route-36cb8b428b38b26a.js +0 -17
  696. package/.next/standalone/.next/static/chunks/app/api/v1/watchers/route-36cb8b428b38b26a.js +0 -17
  697. package/.next/standalone/.next/static/chunks/app/manifest.webmanifest/route-36cb8b428b38b26a.js +0 -17
  698. package/.next/standalone/.next/static/chunks/next/dist/client/components/builtin/app-error-36cb8b428b38b26a.js +0 -17
  699. package/.next/standalone/.next/static/chunks/next/dist/client/components/builtin/forbidden-36cb8b428b38b26a.js +0 -17
  700. package/.next/standalone/.next/static/chunks/next/dist/client/components/builtin/not-found-36cb8b428b38b26a.js +0 -17
  701. package/.next/standalone/.next/static/chunks/next/dist/client/components/builtin/unauthorized-36cb8b428b38b26a.js +0 -17
  702. /package/.next/standalone/.next/static/{NUrC9xax1sp1Q70nlFqS6 → hwujW4hR1b-r3k5WdMxZO}/_buildManifest.js +0 -0
  703. /package/.next/standalone/.next/static/{NUrC9xax1sp1Q70nlFqS6 → hwujW4hR1b-r3k5WdMxZO}/_ssgManifest.js +0 -0
@@ -1,6 +1,6 @@
1
1
  (self["webpackChunk_N_E"] = self["webpackChunk_N_E"] || []).push([[8974],{
2
2
 
3
- /***/ 9024:
3
+ /***/ 11362:
4
4
  /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
5
5
 
6
6
  "use strict";
@@ -1114,6 +1114,26 @@ function useSSE(onDone) {
1114
1114
  // Cleared on every new start()/attach().
1115
1115
  const [authError, setAuthError] = (0,react.useState)(null);
1116
1116
  const abortRef = (0,react.useRef)(null);
1117
+ // Synchronous view of whether start()/attach() owns a live stream, and when
1118
+ // the last one settled. React's `streaming` lags a render behind, so the
1119
+ // activity poller reads this to avoid aborting a stream that just opened
1120
+ // or re-attaching a run whose stream has only just ended.
1121
+ const liveRef = (0,react.useRef)({
1122
+ busy: false,
1123
+ settledAt: 0
1124
+ });
1125
+ const markLive = (0,react.useCallback)(()=>{
1126
+ liveRef.current.busy = true;
1127
+ }, []);
1128
+ const markSettled = (0,react.useCallback)((ctrl)=>{
1129
+ if (ctrl && abortRef.current !== ctrl) return;
1130
+ liveRef.current = {
1131
+ busy: false,
1132
+ settledAt: Date.now()
1133
+ };
1134
+ }, []);
1135
+ const isLive = (0,react.useCallback)(()=>liveRef.current.busy, []);
1136
+ const lastSettledAt = (0,react.useCallback)(()=>liveRef.current.settledAt, []);
1117
1137
  const threadIdRef = (0,react.useRef)(null);
1118
1138
  // ADR-0080 — id of the steering message currently armed for a possible
1119
1139
  // continuation break, or null. Set eagerly (before the steer PATCH
@@ -1275,6 +1295,7 @@ function useSSE(onDone) {
1275
1295
  abortRef.current?.abort();
1276
1296
  const ctrl = new AbortController();
1277
1297
  abortRef.current = ctrl;
1298
+ markLive();
1278
1299
  threadIdRef.current = threadId;
1279
1300
  resetBuffer();
1280
1301
  setStreaming(true);
@@ -1322,10 +1343,13 @@ function useSSE(onDone) {
1322
1343
  // them.
1323
1344
  setStreaming(false);
1324
1345
  closeActivity();
1346
+ markSettled(ctrl);
1325
1347
  }
1326
1348
  }, [
1327
1349
  closeActivity,
1328
1350
  consume,
1351
+ markLive,
1352
+ markSettled,
1329
1353
  openActivity,
1330
1354
  resetBuffer
1331
1355
  ]);
@@ -1350,11 +1374,13 @@ function useSSE(onDone) {
1350
1374
  // start()/attach() — same pattern as the `done` branch in consume().
1351
1375
  closeActivity();
1352
1376
  abortRef.current?.abort();
1377
+ markSettled(null);
1353
1378
  steeredContinuationIdRef.current = null;
1354
1379
  onDone?.();
1355
1380
  }, [
1356
1381
  closeActivity,
1357
1382
  flushPending,
1383
+ markSettled,
1358
1384
  onDone
1359
1385
  ]);
1360
1386
  // Attach to an in-flight run for the given thread (server-side run kept
@@ -1368,6 +1394,7 @@ function useSSE(onDone) {
1368
1394
  abortRef.current?.abort();
1369
1395
  const ctrl = new AbortController();
1370
1396
  abortRef.current = ctrl;
1397
+ markLive();
1371
1398
  threadIdRef.current = threadId;
1372
1399
  resetBuffer();
1373
1400
  setStreaming(true);
@@ -1395,10 +1422,13 @@ function useSSE(onDone) {
1395
1422
  // hangs in the composer and the "Reconnecting…" badge never clears.
1396
1423
  setStreaming(false);
1397
1424
  closeActivity();
1425
+ markSettled(ctrl);
1398
1426
  }
1399
1427
  }, [
1400
1428
  closeActivity,
1401
1429
  consume,
1430
+ markLive,
1431
+ markSettled,
1402
1432
  onDone,
1403
1433
  openActivity,
1404
1434
  resetBuffer
@@ -1443,6 +1473,8 @@ function useSSE(onDone) {
1443
1473
  start,
1444
1474
  stop,
1445
1475
  attach,
1476
+ isLive,
1477
+ lastSettledAt,
1446
1478
  clearStreamingContent,
1447
1479
  clearToolEvents,
1448
1480
  armSteeredContinuation,
@@ -1462,6 +1494,8 @@ function useSSE(onDone) {
1462
1494
  start,
1463
1495
  stop,
1464
1496
  attach,
1497
+ isLive,
1498
+ lastSettledAt,
1465
1499
  clearStreamingContent,
1466
1500
  clearToolEvents,
1467
1501
  armSteeredContinuation,
@@ -1682,6 +1716,8 @@ function readLegacyGlobal() {
1682
1716
  };
1683
1717
  }
1684
1718
 
1719
+ // EXTERNAL MODULE: ./lib/ui/error-report.ts
1720
+ var error_report = __webpack_require__(11856);
1685
1721
  // EXTERNAL MODULE: ./node_modules/lucide-react/dist/esm/icons/shield-alert.mjs
1686
1722
  var shield_alert = __webpack_require__(69203);
1687
1723
  // EXTERNAL MODULE: ./node_modules/lucide-react/dist/esm/icons/chevron-up.mjs
@@ -2919,9 +2955,24 @@ var loader_circle = __webpack_require__(92571);
2919
2955
  var triangle_alert = __webpack_require__(11012);
2920
2956
  // EXTERNAL MODULE: ./node_modules/lucide-react/dist/esm/icons/minus.mjs
2921
2957
  var minus = __webpack_require__(36565);
2958
+ // EXTERNAL MODULE: ./node_modules/lucide-react/dist/esm/icons/rotate-ccw.mjs
2959
+ var rotate_ccw = __webpack_require__(92298);
2922
2960
  ;// ./components/ui/WorkflowChecklist.tsx
2923
2961
 
2924
2962
 
2963
+ const RETRYABLE_STATUSES = new Set([
2964
+ "done",
2965
+ "needs_attention",
2966
+ "skipped"
2967
+ ]);
2968
+ function isWorkflowItemRetryable(item) {
2969
+ return RETRYABLE_STATUSES.has(item.status);
2970
+ }
2971
+ function statusLabel(status) {
2972
+ if (status === "done") return "verified";
2973
+ if (status === "needs_attention") return "needs attention";
2974
+ return status;
2975
+ }
2925
2976
  function StatusIcon({ status }) {
2926
2977
  if (status === "done") return /*#__PURE__*/ (0,jsx_runtime.jsx)(check/* default */.A, {
2927
2978
  className: "h-3 w-3",
@@ -2951,11 +3002,15 @@ function statusClass(status) {
2951
3002
  if (status === "skipped") return "border-border/60 bg-surface text-fg-faint";
2952
3003
  return "border-border/60 bg-surface text-fg-faint";
2953
3004
  }
2954
- function WorkflowChecklist({ eyebrow, title, phaseLabel, summary, items, error, compact = false, children }) {
3005
+ function itemTooltip(item) {
3006
+ const note = item.status === "done" ? item.validation_evidence : item.reason;
3007
+ return note ? `${item.label}\n${statusLabel(item.status)}: ${note}` : item.label;
3008
+ }
3009
+ function WorkflowChecklist({ eyebrow, title, phaseLabel, summary, items, error, compact = false, onRetryItem, canRetryItem, retryDisabled = false, children }) {
2955
3010
  return /*#__PURE__*/ (0,jsx_runtime.jsxs)("div", {
2956
3011
  className: compact ? "flex flex-col gap-1.5" : "absolute inset-x-0 top-0 flex flex-col gap-2 transition-opacity duration-300",
2957
3012
  children: [
2958
- /*#__PURE__*/ (0,jsx_runtime.jsx)("p", {
3013
+ !compact && /*#__PURE__*/ (0,jsx_runtime.jsx)("p", {
2959
3014
  className: "text-[10px] text-fg-faint uppercase tracking-wider text-center",
2960
3015
  children: eyebrow
2961
3016
  }),
@@ -2975,99 +3030,59 @@ function WorkflowChecklist({ eyebrow, title, phaseLabel, summary, items, error,
2975
3030
  })
2976
3031
  ]
2977
3032
  }),
2978
- /*#__PURE__*/ (0,jsx_runtime.jsx)("p", {
3033
+ !compact && summary && /*#__PURE__*/ (0,jsx_runtime.jsx)("p", {
2979
3034
  className: "mt-1 text-[11px] leading-snug text-fg-muted line-clamp-2",
2980
3035
  children: summary
2981
3036
  }),
2982
- /*#__PURE__*/ (0,jsx_runtime.jsx)("div", {
2983
- className: compact ? "mt-1.5 flex max-h-32 flex-col gap-1 overflow-y-auto pr-1" : "mt-2 flex max-h-32 flex-col gap-1 overflow-y-auto pr-1",
2984
- children: items.map((item)=>/*#__PURE__*/ (0,jsx_runtime.jsxs)("div", {
2985
- className: compact ? "rounded border border-border/30 bg-surface-2/40 px-1.5 py-1 text-[10px] leading-tight text-fg-muted" : "text-[10px] leading-tight text-fg-muted",
3037
+ /*#__PURE__*/ (0,jsx_runtime.jsx)("ul", {
3038
+ className: compact ? "mt-1.5 flex max-h-48 flex-col gap-0.5 overflow-y-auto pr-1" : "mt-2 flex max-h-32 flex-col gap-1 overflow-y-auto pr-1",
3039
+ children: items.map((item)=>{
3040
+ const retryable = !!onRetryItem && isWorkflowItemRetryable(item) && (canRetryItem ? canRetryItem(item) : true);
3041
+ return /*#__PURE__*/ (0,jsx_runtime.jsxs)("li", {
3042
+ className: "group flex items-center gap-1.5 text-[10px] leading-tight text-fg-muted",
2986
3043
  children: [
2987
- /*#__PURE__*/ (0,jsx_runtime.jsxs)("div", {
2988
- className: "flex items-start gap-1.5",
2989
- children: [
2990
- /*#__PURE__*/ (0,jsx_runtime.jsx)("span", {
2991
- "aria-label": item.status,
2992
- className: [
2993
- "mt-0.5 flex h-4 w-4 shrink-0 items-center justify-center rounded border",
2994
- statusClass(item.status)
2995
- ].join(" "),
2996
- children: /*#__PURE__*/ (0,jsx_runtime.jsx)(StatusIcon, {
2997
- status: item.status
2998
- })
2999
- }),
3000
- /*#__PURE__*/ (0,jsx_runtime.jsx)("span", {
3001
- className: compact ? "min-w-0 flex-1 truncate" : "line-clamp-2",
3002
- title: item.label,
3003
- children: item.label
3004
- })
3005
- ]
3044
+ /*#__PURE__*/ (0,jsx_runtime.jsx)("span", {
3045
+ role: "img",
3046
+ "aria-label": statusLabel(item.status),
3047
+ className: [
3048
+ "flex h-4 w-4 shrink-0 items-center justify-center rounded border",
3049
+ statusClass(item.status)
3050
+ ].join(" "),
3051
+ children: /*#__PURE__*/ (0,jsx_runtime.jsx)(StatusIcon, {
3052
+ status: item.status
3053
+ })
3006
3054
  }),
3007
- (item.input || item.output || item.validation || item.validation_evidence) && /*#__PURE__*/ (0,jsx_runtime.jsxs)("details", {
3008
- className: "mt-1 pl-5",
3055
+ /*#__PURE__*/ (0,jsx_runtime.jsx)("span", {
3056
+ className: compact ? "min-w-0 flex-1 truncate" : "min-w-0 flex-1 line-clamp-2",
3057
+ title: itemTooltip(item),
3058
+ children: item.label
3059
+ }),
3060
+ (item.attempts ?? 0) > 1 && /*#__PURE__*/ (0,jsx_runtime.jsxs)("span", {
3061
+ className: "shrink-0 text-[9px] tabular-nums text-fg-faint",
3062
+ title: `Attempt ${item.attempts}`,
3009
3063
  children: [
3010
- /*#__PURE__*/ (0,jsx_runtime.jsx)("summary", {
3011
- className: "cursor-pointer text-fg-faint",
3012
- children: "Step contract"
3013
- }),
3014
- /*#__PURE__*/ (0,jsx_runtime.jsxs)("dl", {
3015
- className: "mt-1 grid grid-cols-[auto_minmax(0,1fr)] gap-x-2 gap-y-1",
3016
- children: [
3017
- item.input && /*#__PURE__*/ (0,jsx_runtime.jsxs)(jsx_runtime.Fragment, {
3018
- children: [
3019
- /*#__PURE__*/ (0,jsx_runtime.jsx)("dt", {
3020
- className: "text-fg-faint",
3021
- children: "Input"
3022
- }),
3023
- /*#__PURE__*/ (0,jsx_runtime.jsx)("dd", {
3024
- className: "break-words",
3025
- children: item.input
3026
- })
3027
- ]
3028
- }),
3029
- item.output && /*#__PURE__*/ (0,jsx_runtime.jsxs)(jsx_runtime.Fragment, {
3030
- children: [
3031
- /*#__PURE__*/ (0,jsx_runtime.jsx)("dt", {
3032
- className: "text-fg-faint",
3033
- children: "Output"
3034
- }),
3035
- /*#__PURE__*/ (0,jsx_runtime.jsx)("dd", {
3036
- className: "break-words",
3037
- children: item.output
3038
- })
3039
- ]
3040
- }),
3041
- item.validation && /*#__PURE__*/ (0,jsx_runtime.jsxs)(jsx_runtime.Fragment, {
3042
- children: [
3043
- /*#__PURE__*/ (0,jsx_runtime.jsx)("dt", {
3044
- className: "text-fg-faint",
3045
- children: "Validation"
3046
- }),
3047
- /*#__PURE__*/ (0,jsx_runtime.jsx)("dd", {
3048
- className: "break-words",
3049
- children: item.validation
3050
- })
3051
- ]
3052
- }),
3053
- item.validation_evidence && /*#__PURE__*/ (0,jsx_runtime.jsxs)(jsx_runtime.Fragment, {
3054
- children: [
3055
- /*#__PURE__*/ (0,jsx_runtime.jsx)("dt", {
3056
- className: "text-fg-faint",
3057
- children: "Evidence"
3058
- }),
3059
- /*#__PURE__*/ (0,jsx_runtime.jsx)("dd", {
3060
- className: "break-words",
3061
- children: item.validation_evidence
3062
- })
3063
- ]
3064
- })
3065
- ]
3066
- })
3064
+ "attempt ",
3065
+ item.attempts
3067
3066
  ]
3067
+ }),
3068
+ retryable && /*#__PURE__*/ (0,jsx_runtime.jsx)("button", {
3069
+ type: "button",
3070
+ onClick: ()=>onRetryItem(item),
3071
+ disabled: retryDisabled,
3072
+ "aria-label": `Retry ${item.label}`,
3073
+ title: `Retry ${item.label}`,
3074
+ className: [
3075
+ "flex h-4 w-4 shrink-0 items-center justify-center rounded text-fg-faint hover:bg-surface-3 hover:text-fg disabled:opacity-40",
3076
+ item.status === "needs_attention" ? "" : "opacity-0 focus:opacity-100 group-hover:opacity-100"
3077
+ ].join(" "),
3078
+ children: /*#__PURE__*/ (0,jsx_runtime.jsx)(rotate_ccw/* default */.A, {
3079
+ className: "h-3 w-3",
3080
+ "aria-hidden": true
3081
+ })
3068
3082
  })
3069
3083
  ]
3070
- }, item.id))
3084
+ }, item.id);
3085
+ })
3071
3086
  }),
3072
3087
  error && /*#__PURE__*/ (0,jsx_runtime.jsx)("p", {
3073
3088
  className: "mt-2 text-[10px] leading-tight text-red-400",
@@ -3080,6 +3095,21 @@ function WorkflowChecklist({ eyebrow, title, phaseLabel, summary, items, error,
3080
3095
  });
3081
3096
  }
3082
3097
 
3098
+ ;// ./components/chat/workflow-step-retry.ts
3099
+
3100
+ /** Sends a retry request for one workflow step; null when the surface cannot send messages. */ const WorkflowStepRetryContext = (0,react.createContext)(null);
3101
+ function useWorkflowStepRetry() {
3102
+ return (0,react.useContext)(WorkflowStepRetryContext);
3103
+ }
3104
+ function workflowStepRetryMessage({ workflowId, itemId, label }) {
3105
+ const progressUpdate = workflowId === "version_adoption" ? `Call \`workflow_progress\` with \`workflow_id: "version_adoption"\`, \`item_id: "${itemId}"\`, and \`status: "checking"\`` : `Call \`workflow_progress\` for workflow \`${workflowId}\` with the complete items snapshot, setting this step to \`checking\``;
3106
+ return [
3107
+ `Retry workflow step "${label}" (item \`${itemId}\`) in workflow \`${workflowId}\`.`,
3108
+ `${progressUpdate}, then redo the step from its stated input and run its validation again.`,
3109
+ "Finally mark it `done` with newly observed `validation_evidence`, or `needs_attention` with the reason. Leave the other steps unchanged."
3110
+ ].join(" ");
3111
+ }
3112
+
3083
3113
  // EXTERNAL MODULE: ./node_modules/lucide-react/dist/esm/icons/clock.mjs
3084
3114
  var clock = __webpack_require__(6923);
3085
3115
  // EXTERNAL MODULE: ./node_modules/lucide-react/dist/esm/icons/message-circle.mjs
@@ -3268,6 +3298,7 @@ var ProviderLogo = __webpack_require__(85516);
3268
3298
 
3269
3299
 
3270
3300
 
3301
+
3271
3302
  // Distinct lucide glyph per internal tool family so the chat transcript
3272
3303
  // is glanceable — operator can tell a file write from a web fetch from a
3273
3304
  // schedule from a memory read without reading the tool name.
@@ -3705,7 +3736,34 @@ function groupByCallId(events) {
3705
3736
  }
3706
3737
  g.absorbed = true;
3707
3738
  }
3708
- return order.map((id)=>map.get(id)).filter((g)=>!g.absorbed);
3739
+ const groups = order.map((id)=>map.get(id)).filter((g)=>!g.absorbed);
3740
+ annotateWorkflowAttempts(groups);
3741
+ return groups;
3742
+ }
3743
+ // Counts each workflow step's transitions into `checking` across the
3744
+ // message's workflow_progress calls, so auto-retried steps show "attempt N".
3745
+ // Rejected updates (ok:false) changed nothing and are not counted.
3746
+ function annotateWorkflowAttempts(groups) {
3747
+ const lastStatus = new Map();
3748
+ const attempts = new Map();
3749
+ for (const group of groups){
3750
+ if (group.name !== "workflow_progress") continue;
3751
+ if (coerceObject(unwrapLangChainSerializable(group.result))?.ok === false) continue;
3752
+ const view = workflowViewFor(group);
3753
+ if (!view) continue;
3754
+ const counts = {
3755
+ ...attempts.get(view.workflow_id) ?? {}
3756
+ };
3757
+ for (const item of view.items){
3758
+ const key = `${view.workflow_id}:${item.id}`;
3759
+ if (item.status === "checking" && lastStatus.get(key) !== "checking") {
3760
+ counts[item.id] = (counts[item.id] ?? 0) + 1;
3761
+ }
3762
+ lastStatus.set(key, item.status);
3763
+ }
3764
+ attempts.set(view.workflow_id, counts);
3765
+ group.workflowAttempts = counts;
3766
+ }
3709
3767
  }
3710
3768
  function ToolCallCard({ group, startedAt }) {
3711
3769
  const [open, setOpen] = (0,react.useState)(false);
@@ -3818,23 +3876,27 @@ function ToolCallCard({ group, startedAt }) {
3818
3876
  /*#__PURE__*/ (0,jsx_runtime.jsx)(WorkflowProgressDetails, {
3819
3877
  group: group
3820
3878
  }),
3821
- hasVisibleArgs(group.args) ? /*#__PURE__*/ (0,jsx_runtime.jsx)(DetailSection, {
3822
- label: "arguments",
3823
- value: group.args
3824
- }) : hasArgs ? /*#__PURE__*/ (0,jsx_runtime.jsx)(DetailSection, {
3825
- label: "arguments (inferred from result)",
3826
- value: effectiveArgs
3827
- }) : null,
3828
- group.status !== "running" && group.status !== "async" && (isToolResultRefEnvelope(group.result) ? /*#__PURE__*/ (0,jsx_runtime.jsx)(ToolResultRefDetails, {
3829
- value: group.result
3830
- }) : /*#__PURE__*/ (0,jsx_runtime.jsx)(DetailSection, {
3831
- label: group.status === "error" ? "error" : "result",
3832
- value: group.result,
3833
- tone: group.status === "error" ? "error" : "default"
3834
- })),
3835
- group.status === "async" && /*#__PURE__*/ (0,jsx_runtime.jsx)(DetailSection, {
3836
- label: "background handoff",
3837
- value: group.result
3879
+ !hasWorkflowView(group) && /*#__PURE__*/ (0,jsx_runtime.jsxs)(jsx_runtime.Fragment, {
3880
+ children: [
3881
+ hasVisibleArgs(group.args) ? /*#__PURE__*/ (0,jsx_runtime.jsx)(DetailSection, {
3882
+ label: "arguments",
3883
+ value: group.args
3884
+ }) : hasArgs ? /*#__PURE__*/ (0,jsx_runtime.jsx)(DetailSection, {
3885
+ label: "arguments (inferred from result)",
3886
+ value: effectiveArgs
3887
+ }) : null,
3888
+ group.status !== "running" && group.status !== "async" && (isToolResultRefEnvelope(group.result) ? /*#__PURE__*/ (0,jsx_runtime.jsx)(ToolResultRefDetails, {
3889
+ value: group.result
3890
+ }) : /*#__PURE__*/ (0,jsx_runtime.jsx)(DetailSection, {
3891
+ label: group.status === "error" ? "error" : "result",
3892
+ value: group.result,
3893
+ tone: group.status === "error" ? "error" : "default"
3894
+ })),
3895
+ group.status === "async" && /*#__PURE__*/ (0,jsx_runtime.jsx)(DetailSection, {
3896
+ label: "background handoff",
3897
+ value: group.result
3898
+ })
3899
+ ]
3838
3900
  })
3839
3901
  ]
3840
3902
  })
@@ -3969,18 +4031,47 @@ function ToolResultRefDetails({ value }) {
3969
4031
  ]
3970
4032
  });
3971
4033
  }
3972
- function WorkflowProgressDetails({ group }) {
4034
+ function workflowViewFor(group) {
3973
4035
  if (group.name !== "workflow_progress") return null;
3974
- const workflow = workflowProgressFrom(group.result) ?? workflowProgressPreviewFrom(group.args);
4036
+ const view = workflowProgressFrom(group.result) ?? workflowProgressPreviewFrom(group.args);
4037
+ const result = coerceObject(unwrapLangChainSerializable(group.result));
4038
+ const attempts = group.workflowAttempts;
4039
+ const withAttempts = view && attempts ? {
4040
+ ...view,
4041
+ items: view.items.map((item)=>attempts[item.id] ? {
4042
+ ...item,
4043
+ attempts: attempts[item.id]
4044
+ } : item)
4045
+ } : view;
4046
+ if (withAttempts && result?.ok === false && typeof result.error === "string") {
4047
+ return {
4048
+ ...withAttempts,
4049
+ error: `Update rejected: ${result.error}`
4050
+ };
4051
+ }
4052
+ return withAttempts;
4053
+ }
4054
+ /** Workflow rows show only their work items; raw payloads stay visible when the call failed. */ function hasWorkflowView(group) {
4055
+ return group.status !== "error" && workflowViewFor(group) !== null;
4056
+ }
4057
+ function WorkflowProgressDetails({ group }) {
4058
+ const retryStep = useWorkflowStepRetry();
4059
+ const workflow = workflowViewFor(group);
3975
4060
  if (!workflow) return null;
4061
+ const workflowId = workflow.workflow_id;
3976
4062
  return /*#__PURE__*/ (0,jsx_runtime.jsx)(WorkflowChecklist, {
3977
4063
  compact: true,
3978
4064
  eyebrow: "workflow",
3979
- title: workflow.workflow_id.replace(/[_-]/g, " "),
4065
+ title: workflowId.replace(/[_-]/g, " "),
3980
4066
  phaseLabel: workflow.phase ?? "in progress",
3981
4067
  summary: workflow.summary ?? "",
3982
4068
  items: workflow.items,
3983
- error: workflow.error
4069
+ error: workflow.error,
4070
+ onRetryItem: retryStep ? (item)=>retryStep({
4071
+ workflowId,
4072
+ itemId: item.id,
4073
+ label: item.label
4074
+ }) : undefined
3984
4075
  });
3985
4076
  }
3986
4077
  function workflowProgressFrom(payload) {
@@ -4966,8 +5057,6 @@ var shield_check = __webpack_require__(50981);
4966
5057
  var copy = __webpack_require__(99314);
4967
5058
  // EXTERNAL MODULE: ./node_modules/lucide-react/dist/esm/icons/link-2.mjs
4968
5059
  var link_2 = __webpack_require__(51128);
4969
- // EXTERNAL MODULE: ./node_modules/lucide-react/dist/esm/icons/rotate-ccw.mjs
4970
- var rotate_ccw = __webpack_require__(92298);
4971
5060
  // EXTERNAL MODULE: ./node_modules/lucide-react/dist/esm/icons/pause.mjs
4972
5061
  var pause = __webpack_require__(79267);
4973
5062
  // EXTERNAL MODULE: ./node_modules/lucide-react/dist/esm/icons/play.mjs
@@ -5311,6 +5400,41 @@ function formatRoutingDuration(durationMs) {
5311
5400
  return `${seconds.toFixed(seconds >= 10 ? 0 : 1)}s`;
5312
5401
  }
5313
5402
 
5403
+ ;// ./lib/utils/source-link.ts
5404
+ /**
5405
+ * Source-link fields for tool results, so an agent can link a reply back to
5406
+ * the email, calendar event, or chat it came from without building URLs.
5407
+ *
5408
+ * `cite_as` is a ready-made markdown link the system prompt tells agents to
5409
+ * paste verbatim. Building it in code keeps the label and URL well-formed:
5410
+ * a stray `]` in a subject or `)` in a URL would otherwise break the link.
5411
+ */ const MAX_LABEL_CHARS = 80;
5412
+ /** Returns `url` when it is an absolute https URL, otherwise null. */ function source_link_httpsUrlOrNull(url) {
5413
+ if (!url) return null;
5414
+ try {
5415
+ const parsed = new URL(url);
5416
+ return parsed.protocol === "https:" ? parsed.href : null;
5417
+ } catch {
5418
+ return null;
5419
+ }
5420
+ }
5421
+ function markdownLabel(label, fallback) {
5422
+ const flat = (label ?? "").replace(/\s+/g, " ").trim();
5423
+ const capped = flat.length > MAX_LABEL_CHARS ? `${flat.slice(0, MAX_LABEL_CHARS - 1).trimEnd()}…` : flat;
5424
+ return (capped || fallback).replace(/[\\[\]]/g, (c)=>`\\${c}`);
5425
+ }
5426
+ function markdownDestination(url) {
5427
+ return url.replace(/[()\s<>]/g, (c)=>`%${c.charCodeAt(0).toString(16).toUpperCase().padStart(2, "0")}`);
5428
+ }
5429
+ /**
5430
+ * Pre-built markdown link for `cite_as`, or null when there is no usable URL.
5431
+ * Only https URLs qualify: the chat renderer drops other schemes.
5432
+ */ function citeAs(label, url, fallbackLabel = "source") {
5433
+ const safe = source_link_httpsUrlOrNull(url);
5434
+ if (!safe) return null;
5435
+ return `[${markdownLabel(label, fallbackLabel)}](${markdownDestination(safe)})`;
5436
+ }
5437
+
5314
5438
  ;// ./lib/bridges/message-role.ts
5315
5439
  /**
5316
5440
  * Cross-adapter framing for bridge inbound messages.
@@ -5328,25 +5452,8 @@ function formatRoutingDuration(durationMs) {
5328
5452
  * sees. Adding a new adapter is a matter of mapping its platform-specific
5329
5453
  * "who sent this" signal onto `MessageRole`; the framing code does not need
5330
5454
  * to change.
5331
- */ /**
5332
- * Who sent the message from the agent's perspective.
5333
- *
5334
- * - `user`: the paired account holder themselves — typed on their phone,
5335
- * in their browser, etc. The agent treats these as the user's own
5336
- * reaction/input to the conversation. Useful as an intent signal but
5337
- * NOT a direct command to the agent (the user is talking to the
5338
- * counterpart, not the agent).
5339
- *
5340
- * - `counterpart`: another participant in the chat — 1:1 partner in a DM,
5341
- * or another member in a group chat. The agent treats these as
5342
- * conversation context the user has not yet reacted to. Not a request
5343
- * directed at the agent.
5344
- *
5345
- * - `agent`: the agent's own prior output, surfaced inbound when the
5346
- * adapter cannot suppress its echo (rare). Adapters with reliable
5347
- * echo-filtering (e.g. WhatsApp's `sentIdsSet`) should never emit this
5348
- * value; it exists for adapters where deduplication is best-effort.
5349
- */ /**
5455
+ */
5456
+ /**
5350
5457
  * Build the prompt prefix the agent receives for one bridge-inbound message.
5351
5458
  *
5352
5459
  * Output shape:
@@ -5360,6 +5467,7 @@ function formatRoutingDuration(durationMs) {
5360
5467
  * [message_role:user|counterpart|agent]
5361
5468
  * [sender_id:<id>]
5362
5469
  * [sender_name:<label>]
5470
+ * ([chat_link:<https url>] when the platform has a permalink for the chat)
5363
5471
  * ([group_name:<label>] [participant_id:<id>] [participant_name:<label>] for groups)
5364
5472
  *
5365
5473
  * <raw text>
@@ -5369,23 +5477,29 @@ function formatRoutingDuration(durationMs) {
5369
5477
  * convention. Both are stable across adapters.
5370
5478
  */ function formatBridgePrompt(input) {
5371
5479
  const note = roleNote(input.role, input.is_group, input.silent === true, input.event);
5480
+ // Header values come from the platform (display names, group subjects) and
5481
+ // are sender-controlled: a line break would forge extra headers or end the
5482
+ // header block early, so every value is flattened onto one line.
5483
+ const h = (value)=>String(value ?? "").replace(/[\r\n\u0085\u2028\u2029]+/g, " ");
5372
5484
  const lines = [
5373
- `[bridge:${input.bridge_id}]`,
5374
- `[chat_id:${input.chat_id}]`,
5375
- `[chat_name:${input.chat_name}]`,
5485
+ `[bridge:${h(input.bridge_id)}]`,
5486
+ `[chat_id:${h(input.chat_id)}]`,
5487
+ `[chat_name:${h(input.chat_name)}]`,
5376
5488
  `[chat_type:${input.is_group ? "group" : "dm"}]`,
5377
5489
  `[message_role:${input.role}]`,
5378
- `[sender_id:${input.sender_id}]`,
5379
- `[sender_name:${input.sender_name}]`
5490
+ `[sender_id:${h(input.sender_id)}]`,
5491
+ `[sender_name:${h(input.sender_name)}]`
5380
5492
  ];
5493
+ const chatLink = httpsUrlOrNull(input.chat_link);
5494
+ if (chatLink) lines.push(`[chat_link:${chatLink}]`);
5381
5495
  if (input.event) {
5382
5496
  lines.push(`[event_type:${input.event.type}]`);
5383
- lines.push(`[event_subtype:${input.event.subtype}]`);
5497
+ lines.push(`[event_subtype:${h(input.event.subtype)}]`);
5384
5498
  }
5385
5499
  if (input.is_group) {
5386
- lines.push(`[group_name:${input.chat_name}]`);
5387
- lines.push(`[participant_id:${input.sender_id}]`);
5388
- lines.push(`[participant_name:${input.sender_name}]`);
5500
+ lines.push(`[group_name:${h(input.chat_name)}]`);
5501
+ lines.push(`[participant_id:${h(input.sender_id)}]`);
5502
+ lines.push(`[participant_name:${h(input.sender_name)}]`);
5389
5503
  }
5390
5504
  return `${note}\n\n${lines.join("\n")}\n\n${input.text}`;
5391
5505
  }
@@ -5400,7 +5514,7 @@ function parseBridgePrompt(raw) {
5400
5514
  const lines = src.split("\n");
5401
5515
  let i = 0;
5402
5516
  for(; i < lines.length; i++){
5403
- const line = lines[i];
5517
+ const line = lines[i].replace(/\r$/, "");
5404
5518
  if (line === "") {
5405
5519
  i++;
5406
5520
  break;
@@ -5419,6 +5533,7 @@ function parseBridgePrompt(raw) {
5419
5533
  isGroup: headers.chat_type === "group",
5420
5534
  senderJid: senderId,
5421
5535
  senderName: headers.sender_name || senderId || "Unknown",
5536
+ chatLink: source_link_httpsUrlOrNull(headers.chat_link),
5422
5537
  body: lines.slice(i).join("\n").trimEnd()
5423
5538
  };
5424
5539
  }
@@ -6550,6 +6665,19 @@ function BridgeMessageCard({ ctx, activity }) {
6550
6665
  activityStatus(activity).copy,
6551
6666
  activity.occurrence_count > 1 ? ` · ${activity.occurrence_count} checks` : ""
6552
6667
  ]
6668
+ }) : null,
6669
+ ctx.chatLink ? /*#__PURE__*/ (0,jsx_runtime.jsxs)("a", {
6670
+ href: ctx.chatLink,
6671
+ target: "_blank",
6672
+ rel: "noopener noreferrer",
6673
+ className: "inline-flex items-center gap-1 px-1.5 py-0.5 rounded-full bg-white/15 hover:bg-white/25 text-[9.5px] shrink-0",
6674
+ title: `Open this chat (${ctx.chatLink})`,
6675
+ children: [
6676
+ /*#__PURE__*/ (0,jsx_runtime.jsx)(external_link/* default */.A, {
6677
+ size: 9
6678
+ }),
6679
+ "open chat"
6680
+ ]
6553
6681
  }) : null
6554
6682
  ]
6555
6683
  });
@@ -8346,7 +8474,7 @@ function StatusDot({ tone = "neutral", size = "xs", pulse, className, style, lab
8346
8474
  }
8347
8475
 
8348
8476
  ;// ./components/chat/ContextBoundary.tsx
8349
- /* __next_internal_client_entry_do_not_use__ WarmSummaryCard,ContextBoundaryDivider auto */
8477
+ /* __next_internal_client_entry_do_not_use__ WarmSummaryCard,ContextBoundaryDivider,topicsFromSummarySections auto */
8350
8478
  // Inline visual artefacts for ADR-0042: the warm-summary card and the
8351
8479
  // context-boundary divider that sits below it. Rendered by MessageList in
8352
8480
  // the message stream — between summarised history (above) and the active
@@ -8358,17 +8486,25 @@ function StatusDot({ tone = "neutral", size = "xs", pulse, className, style, lab
8358
8486
 
8359
8487
 
8360
8488
 
8361
- function WarmSummaryCard({ olderCount, summary, summaryBeforeSeq, hotSinceSeq, computedAt, streaming, topics }) {
8489
+ const CHANNEL_LABELS = {
8490
+ bridge: "Bridge",
8491
+ watcher: "Watchers",
8492
+ scheduled_task: "Scheduled tasks"
8493
+ };
8494
+ function WarmSummaryCard({ olderCount, summary, summaryBeforeSeq, hotSinceSeq, computedAt, streaming, topics, channelSummaries = [] }) {
8362
8495
  const [expanded, setExpanded] = (0,react.useState)(false);
8363
- const fresh = !!summary && hotSinceSeq != null && summaryBeforeSeq === hotSinceSeq;
8496
+ const committed = hotSinceSeq != null && summaryBeforeSeq === hotSinceSeq;
8497
+ const fresh = !!summary && committed;
8364
8498
  const stale = !!summary && !fresh;
8365
8499
  const computing = stale && streaming;
8366
- const summaryTopics = summary && topics && topics.length > 0 ? topics : null;
8500
+ // Summaries stored before topic segmentation still read as topics: their
8501
+ // markdown sections render through the same collapsible rows.
8502
+ const summaryTopics = summary ? topics && topics.length > 0 ? topics : topicsFromSummarySections(summary) : null;
8367
8503
  return /*#__PURE__*/ (0,jsx_runtime.jsxs)("div", {
8368
8504
  className: [
8369
8505
  "relative my-4 rounded-2xl border bg-gradient-to-br shadow-sm",
8370
8506
  "from-accent/[0.06] via-surface-2 to-surface-2",
8371
- fresh ? "border-accent/30" : "border-border"
8507
+ fresh || committed ? "border-accent/30" : "border-border"
8372
8508
  ].join(" "),
8373
8509
  children: [
8374
8510
  /*#__PURE__*/ (0,jsx_runtime.jsxs)("div", {
@@ -8413,6 +8549,9 @@ function WarmSummaryCard({ olderCount, summary, summaryBeforeSeq, hotSinceSeq, c
8413
8549
  children: /*#__PURE__*/ (0,jsx_runtime.jsx)(lib/* Markdown */.oz, {
8414
8550
  children: stripWarmHeader(summary)
8415
8551
  })
8552
+ }) : !summary && committed ? channelSummaries.length === 0 && /*#__PURE__*/ (0,jsx_runtime.jsx)("div", {
8553
+ className: "text-xs text-fg-faint italic",
8554
+ children: "No earlier chat messages needed summarising."
8416
8555
  }) : !summary ? /*#__PURE__*/ (0,jsx_runtime.jsxs)("div", {
8417
8556
  className: "flex items-center gap-2 text-xs text-fg-faint italic",
8418
8557
  children: [
@@ -8426,6 +8565,9 @@ function WarmSummaryCard({ olderCount, summary, summaryBeforeSeq, hotSinceSeq, c
8426
8565
  })
8427
8566
  ]
8428
8567
  }) : null,
8568
+ channelSummaries.map((channel)=>/*#__PURE__*/ (0,jsx_runtime.jsx)(ChannelSummarySection, {
8569
+ channel: channel
8570
+ }, channel.channel)),
8429
8571
  stale && /*#__PURE__*/ (0,jsx_runtime.jsxs)("div", {
8430
8572
  className: "mt-2 inline-flex items-center gap-2 text-[11px] text-fg-faint",
8431
8573
  children: [
@@ -8467,6 +8609,32 @@ function WarmSummaryCard({ olderCount, summary, summaryBeforeSeq, hotSinceSeq, c
8467
8609
  ]
8468
8610
  });
8469
8611
  }
8612
+ function ChannelSummarySection({ channel }) {
8613
+ const topics = channel.topics && channel.topics.length > 0 ? channel.topics : topicsFromSummarySections(channel.summary) ?? [
8614
+ {
8615
+ title: "Recap",
8616
+ start_at: "",
8617
+ end_at: "",
8618
+ recap: stripWarmHeader(channel.summary),
8619
+ facts: []
8620
+ }
8621
+ ];
8622
+ return /*#__PURE__*/ (0,jsx_runtime.jsxs)("div", {
8623
+ className: "mt-2",
8624
+ children: [
8625
+ /*#__PURE__*/ (0,jsx_runtime.jsx)("div", {
8626
+ className: "mb-1 text-[9px] uppercase tracking-wide text-fg-faint",
8627
+ children: CHANNEL_LABELS[channel.channel] ?? channel.channel
8628
+ }),
8629
+ /*#__PURE__*/ (0,jsx_runtime.jsx)("div", {
8630
+ className: "flex flex-col gap-1",
8631
+ children: topics.map((topic, i)=>/*#__PURE__*/ (0,jsx_runtime.jsx)(TopicSegmentRow, {
8632
+ topic: topic
8633
+ }, `${channel.channel}-${topic.title}-${i}`))
8634
+ })
8635
+ ]
8636
+ });
8637
+ }
8470
8638
  function TopicSegmentRow({ topic }) {
8471
8639
  const [open, setOpen] = (0,react.useState)(false);
8472
8640
  const range = formatTopicRange(topic.start_at, topic.end_at);
@@ -8494,13 +8662,20 @@ function TopicSegmentRow({ topic }) {
8494
8662
  range
8495
8663
  ]
8496
8664
  }),
8665
+ typeof topic.message_count === "number" && topic.message_count > 0 && /*#__PURE__*/ (0,jsx_runtime.jsxs)("span", {
8666
+ className: "text-fg-faint shrink-0",
8667
+ children: [
8668
+ "\xb7 ",
8669
+ topic.message_count,
8670
+ " ",
8671
+ topic.message_count === 1 ? "msg" : "msgs"
8672
+ ]
8673
+ }),
8497
8674
  topic.facts.length > 0 && /*#__PURE__*/ (0,jsx_runtime.jsxs)("span", {
8498
8675
  className: "ml-auto shrink-0 text-[9px] uppercase tracking-wide text-accent",
8499
8676
  children: [
8500
8677
  topic.facts.length,
8501
- " ",
8502
- topic.facts.length === 1 ? "fact" : "facts",
8503
- " saved"
8678
+ " memorized"
8504
8679
  ]
8505
8680
  })
8506
8681
  ]
@@ -8520,22 +8695,34 @@ function TopicSegmentRow({ topic }) {
8520
8695
  children: topic.recap
8521
8696
  })
8522
8697
  }),
8523
- topic.facts.length > 0 && /*#__PURE__*/ (0,jsx_runtime.jsx)("ul", {
8524
- className: "space-y-0.5",
8525
- children: topic.facts.map((fact, i)=>/*#__PURE__*/ (0,jsx_runtime.jsxs)("li", {
8526
- className: "text-[11px] text-fg-faint",
8527
- children: [
8528
- /*#__PURE__*/ (0,jsx_runtime.jsxs)("span", {
8529
- className: "font-medium text-fg-muted",
8698
+ topic.facts.length > 0 && /*#__PURE__*/ (0,jsx_runtime.jsxs)("div", {
8699
+ children: [
8700
+ /*#__PURE__*/ (0,jsx_runtime.jsx)("div", {
8701
+ className: "text-[9px] uppercase tracking-wide text-fg-faint",
8702
+ children: "Memorized"
8703
+ }),
8704
+ /*#__PURE__*/ (0,jsx_runtime.jsx)("ul", {
8705
+ className: "space-y-0.5",
8706
+ children: topic.facts.map((fact, i)=>/*#__PURE__*/ (0,jsx_runtime.jsxs)("li", {
8707
+ className: "text-[11px] text-fg-faint",
8530
8708
  children: [
8531
- fact.subject,
8532
- ":"
8709
+ /*#__PURE__*/ (0,jsx_runtime.jsxs)("span", {
8710
+ className: "font-medium text-fg-muted",
8711
+ children: [
8712
+ fact.subject,
8713
+ ":"
8714
+ ]
8715
+ }),
8716
+ " ",
8717
+ fact.content,
8718
+ fact.key && /*#__PURE__*/ (0,jsx_runtime.jsx)("code", {
8719
+ className: "ml-1 text-[10px] text-fg-faint",
8720
+ children: fact.key
8721
+ })
8533
8722
  ]
8534
- }),
8535
- " ",
8536
- fact.content
8537
- ]
8538
- }, `${fact.subject}-${i}`))
8723
+ }, `${fact.key ?? fact.subject}-${i}`))
8724
+ })
8725
+ ]
8539
8726
  })
8540
8727
  ]
8541
8728
  })
@@ -8668,7 +8855,38 @@ function ContextBoundary_formatBytes(n) {
8668
8855
  // `buildWarmSummary` prepends a couple of plain-text header lines that read
8669
8856
  // awkwardly inside a card that already has its own header. Strip them.
8670
8857
  function stripWarmHeader(raw) {
8671
- return raw.replace(/^--- Warm context summary ---\n/, "").replace(/^Compressed recap of earlier messages outside the hot window:\n/, "").trimStart();
8858
+ return raw.replace(/\r\n/g, "\n").replace(/^\s*(<!--[\s\S]*?-->\s*)+/, "").replace(/^--- Warm context summary ---\n/, "").replace(/^Compressed recap of [^\n]*:\n/, "").trimStart();
8859
+ }
8860
+ /**
8861
+ * Splits a markdown summary into topic segments at its headings. Returns
8862
+ * null when there are fewer than two sections, so short or unstructured
8863
+ * summaries keep the plain prose rendering.
8864
+ */ function topicsFromSummarySections(raw) {
8865
+ const sections = [];
8866
+ let title = null;
8867
+ let body = [];
8868
+ const flush = ()=>{
8869
+ const recap = body.join("\n").trim();
8870
+ if (title !== null || recap) sections.push({
8871
+ title: title ?? "Overview",
8872
+ start_at: "",
8873
+ end_at: "",
8874
+ recap,
8875
+ facts: []
8876
+ });
8877
+ };
8878
+ for (const line of stripWarmHeader(raw).split("\n")){
8879
+ const heading = /^#{1,3}\s+(.+?)\s*#*\s*$/.exec(line);
8880
+ if (heading) {
8881
+ flush();
8882
+ title = heading[1];
8883
+ body = [];
8884
+ } else {
8885
+ body.push(line);
8886
+ }
8887
+ }
8888
+ flush();
8889
+ return sections.length >= 2 ? sections : null;
8672
8890
  }
8673
8891
  function summaryLong(raw) {
8674
8892
  // Heuristic: more than 6 lines or > 600 chars after the header strip.
@@ -8701,11 +8919,13 @@ function formatRelative(iso) {
8701
8919
 
8702
8920
 
8703
8921
 
8922
+
8704
8923
  const ALL_FILTERS_SHOWN = Object.fromEntries(MESSAGE_FILTER_KEYS.map((k)=>[
8705
8924
  k,
8706
8925
  true
8707
8926
  ]));
8708
- 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 = ()=>{} }) {
8927
+ const NO_CHANNEL_SUMMARIES = [];
8928
+ 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 = ()=>{} }) {
8709
8929
  const hostRef = (0,react.useRef)(null);
8710
8930
  const maskRegionRef = (0,react.useRef)(null);
8711
8931
  const scrollRef = (0,react.useRef)(null);
@@ -8730,6 +8950,9 @@ function MessageList({ threadId, messages, steeredSegments, notices, agentConfig
8730
8950
  const [pendingHotSinceSeq, setPendingHotSinceSeq] = (0,react.useState)(null);
8731
8951
  const [topControlsOpen, setTopControlsOpen] = (0,react.useState)(false);
8732
8952
  const [summaryPopoverOpen, setSummaryPopoverOpen] = (0,react.useState)(false);
8953
+ const retryWorkflowStep = (0,react.useMemo)(()=>onRetryMessage ? (request)=>onRetryMessage(workflowStepRetryMessage(request), []) : null, [
8954
+ onRetryMessage
8955
+ ]);
8733
8956
  // Apply category filter. Messages with no `category` (NULL = ordinary
8734
8957
  // chat) are always shown; tagged messages are gated by their toggle.
8735
8958
  // The `tool_use` and `thinking` filters do NOT remove whole messages —
@@ -9099,7 +9322,11 @@ function MessageList({ threadId, messages, steeredSegments, notices, agentConfig
9099
9322
  const nextHotCount = pendingBoundaryIndex < 0 ? null : visibleMessages.length - pendingBoundaryIndex;
9100
9323
  const removesFromRecent = currentHotCount !== null && nextHotCount !== null ? nextHotCount < currentHotCount : false;
9101
9324
  const hasWarmSummary = !!warmSummary;
9325
+ // A committed boundary whose chat range had nothing to summarise (e.g. a
9326
+ // bridge-only agent): the recap, if any, lives in the channel summaries.
9327
+ const summaryCommittedEmpty = !hasWarmSummary && effectiveHotSinceSeq !== null && warmSummaryBeforeSeq === effectiveHotSinceSeq;
9102
9328
  const summaryFresh = hasWarmSummary && effectiveHotSinceSeq !== null && warmSummaryBeforeSeq === effectiveHotSinceSeq;
9329
+ const summaryReady = summaryFresh || summaryCommittedEmpty;
9103
9330
  const summaryUpdating = hasWarmSummary && !summaryFresh && !!streaming;
9104
9331
  const summaryStale = hasWarmSummary && !summaryFresh && !summaryUpdating;
9105
9332
  (0,react.useEffect)(()=>{
@@ -9200,10 +9427,29 @@ function MessageList({ threadId, messages, steeredSegments, notices, agentConfig
9200
9427
  }
9201
9428
  boundaryAnchorRef.current = null;
9202
9429
  }, []);
9430
+ // While a programmatic smooth scroll (locate boundary, deep link) animates
9431
+ // away from the bottom, its first frames are still "near bottom". Without
9432
+ // this lock, scroll sync re-arms bottom-follow and the post-render snap
9433
+ // cancels the animation, so the target is never reached.
9434
+ const programmaticScrollUntilRef = (0,react.useRef)(0);
9203
9435
  const syncScrollButton = (0,react.useCallback)((el)=>{
9204
9436
  const isAtBottom = el.scrollHeight - el.scrollTop - el.clientHeight < 100;
9205
- atBottomRef.current = isAtBottom;
9206
- setShowScrollButton(!isAtBottom && hasScrollTarget);
9437
+ const locked = Date.now() < programmaticScrollUntilRef.current;
9438
+ atBottomRef.current = isAtBottom && !locked;
9439
+ setShowScrollButton(!atBottomRef.current && hasScrollTarget);
9440
+ }, [
9441
+ hasScrollTarget
9442
+ ]);
9443
+ const scrollTargetIntoView = (0,react.useCallback)((target)=>{
9444
+ programmaticScrollUntilRef.current = Date.now() + PROGRAMMATIC_SCROLL_LOCK_MS;
9445
+ atBottomRef.current = false;
9446
+ setShowScrollButton(hasScrollTarget);
9447
+ target.scrollIntoView({
9448
+ behavior: "smooth",
9449
+ block: "center"
9450
+ });
9451
+ target.classList.add("jarela-deep-link-flash");
9452
+ window.setTimeout(()=>target.classList.remove("jarela-deep-link-flash"), 1600);
9207
9453
  }, [
9208
9454
  hasScrollTarget
9209
9455
  ]);
@@ -9332,14 +9578,7 @@ function MessageList({ threadId, messages, steeredSegments, notices, agentConfig
9332
9578
  const safe = id.replace(/"/g, '\\"');
9333
9579
  const el = root.querySelector(`[data-message-id="${safe}"]`);
9334
9580
  if (!el) return;
9335
- atBottomRef.current = false;
9336
- setShowScrollButton(hasScrollTarget);
9337
- el.scrollIntoView({
9338
- behavior: "smooth",
9339
- block: "center"
9340
- });
9341
- el.classList.add("jarela-deep-link-flash");
9342
- setTimeout(()=>el.classList.remove("jarela-deep-link-flash"), 1600);
9581
+ scrollTargetIntoView(el);
9343
9582
  // Strip the hash so the next streaming message / list-length change
9344
9583
  // doesn't yank the view back to this anchor. replaceState avoids
9345
9584
  // triggering a hashchange event (which would re-enter this handler).
@@ -9352,7 +9591,7 @@ function MessageList({ threadId, messages, steeredSegments, notices, agentConfig
9352
9591
  return ()=>window.removeEventListener("hashchange", scrollToHashTarget);
9353
9592
  }, [
9354
9593
  messages.length,
9355
- hasScrollTarget
9594
+ scrollTargetIntoView
9356
9595
  ]);
9357
9596
  // Handle orientation changes and resizes to maintain scroll position
9358
9597
  (0,react.useEffect)(()=>{
@@ -9383,419 +9622,411 @@ function MessageList({ threadId, messages, steeredSegments, notices, agentConfig
9383
9622
  if (!root) return;
9384
9623
  const boundary = effectiveHotSinceSeq !== null ? document.getElementById(`context-boundary-${effectiveHotSinceSeq}`) : root.querySelector("[data-focus-boundary='1']");
9385
9624
  if (!boundary) return;
9386
- atBottomRef.current = false;
9387
- setShowScrollButton(hasScrollTarget);
9388
- boundary.scrollIntoView({
9389
- behavior: "smooth",
9390
- block: "center"
9391
- });
9625
+ scrollTargetIntoView(boundary);
9392
9626
  }
9393
- return /*#__PURE__*/ (0,jsx_runtime.jsxs)("div", {
9394
- ref: hostRef,
9395
- className: "flex-1 flex flex-col min-h-0 relative",
9396
- children: [
9397
- visibleMessages.length > 0 && /*#__PURE__*/ (0,jsx_runtime.jsx)("div", {
9398
- className: "shrink-0 px-4 pt-[calc(var(--app-safe-top)+3rem)] pb-1",
9399
- children: /*#__PURE__*/ (0,jsx_runtime.jsxs)("div", {
9400
- className: "w-full border-b border-border/45 bg-surface/30 px-2 py-1 backdrop-blur-sm",
9627
+ return /*#__PURE__*/ (0,jsx_runtime.jsx)(WorkflowStepRetryContext.Provider, {
9628
+ value: retryWorkflowStep,
9629
+ children: /*#__PURE__*/ (0,jsx_runtime.jsxs)("div", {
9630
+ ref: hostRef,
9631
+ className: "flex-1 flex flex-col min-h-0 relative",
9632
+ children: [
9633
+ visibleMessages.length > 0 && /*#__PURE__*/ (0,jsx_runtime.jsx)("div", {
9634
+ className: "shrink-0 px-4 pt-[calc(var(--app-safe-top)+3rem)] pb-1",
9635
+ children: /*#__PURE__*/ (0,jsx_runtime.jsxs)("div", {
9636
+ className: "w-full border-b border-border/45 bg-surface/30 px-2 py-1 backdrop-blur-sm",
9637
+ children: [
9638
+ /*#__PURE__*/ (0,jsx_runtime.jsxs)("button", {
9639
+ type: "button",
9640
+ onClick: ()=>setTopControlsOpen((v)=>!v),
9641
+ "aria-expanded": topControlsOpen,
9642
+ className: "w-full flex items-center gap-2 py-0.5 text-[11px] text-fg-faint hover:text-fg transition-colors",
9643
+ children: [
9644
+ /*#__PURE__*/ (0,jsx_runtime.jsx)(CollapseChevron, {
9645
+ open: topControlsOpen,
9646
+ size: 10
9647
+ }),
9648
+ /*#__PURE__*/ (0,jsx_runtime.jsx)("span", {
9649
+ className: "font-semibold uppercase tracking-[0.16em]",
9650
+ children: "Filters & focus"
9651
+ }),
9652
+ hiddenCount > 0 && /*#__PURE__*/ (0,jsx_runtime.jsxs)("span", {
9653
+ className: "ml-auto text-[10px] text-fg-faint",
9654
+ "aria-live": "polite",
9655
+ children: [
9656
+ hiddenCount,
9657
+ " hidden"
9658
+ ]
9659
+ })
9660
+ ]
9661
+ }),
9662
+ topControlsOpen && /*#__PURE__*/ (0,jsx_runtime.jsxs)("div", {
9663
+ className: "mt-1 flex items-center gap-1.5 flex-wrap py-1",
9664
+ children: [
9665
+ availableChips.map((key)=>{
9666
+ const on = filters[key];
9667
+ const Icon = on ? eye/* default */.A : eye_off/* default */.A;
9668
+ return /*#__PURE__*/ (0,jsx_runtime.jsxs)("button", {
9669
+ type: "button",
9670
+ onClick: ()=>toggle(key),
9671
+ className: [
9672
+ "inline-flex items-center gap-1 rounded-none border px-2 py-0.5 text-[10px] leading-4 transition-colors",
9673
+ on ? "border-border/70 bg-surface-2/70 text-fg-muted hover:text-fg" : "border-border/35 bg-transparent text-fg-faint line-through decoration-fg-faint/60 hover:text-fg-muted"
9674
+ ].join(" "),
9675
+ title: // ADR-0044 — for the three channels the model's own
9676
+ // context is scoped by, the chip's meaning is dual:
9677
+ // it doesn't just show/hide rows here, it also
9678
+ // decides whether that channel's history is folded
9679
+ // into the next turn the agent sees.
9680
+ CHANNEL_SCOPED_FILTER_KEYS.has(key) ? on ? `Hide + exclude ${CHIP_LABELS[key]} from the next turn` : `Show + include ${CHIP_LABELS[key]} in the next turn` : on ? `Hide ${CHIP_LABELS[key]} messages` : `Show ${CHIP_LABELS[key]} messages`,
9681
+ "aria-pressed": on,
9682
+ children: [
9683
+ /*#__PURE__*/ (0,jsx_runtime.jsx)(Icon, {
9684
+ size: 10
9685
+ }),
9686
+ /*#__PURE__*/ (0,jsx_runtime.jsx)("span", {
9687
+ children: CHIP_LABELS[key]
9688
+ })
9689
+ ]
9690
+ }, key);
9691
+ }),
9692
+ onSetContextPin && /*#__PURE__*/ (0,jsx_runtime.jsx)("button", {
9693
+ type: "button",
9694
+ onClick: scrollToBoundaryLine,
9695
+ disabled: !hasContextPin,
9696
+ className: "control-tap ml-auto rounded-none border border-border/60 bg-surface-2/70 px-2 py-0.5 text-[10px] leading-4 text-fg-faint transition-colors hover:border-accent/40 hover:text-fg disabled:cursor-not-allowed disabled:opacity-40 disabled:hover:border-border/60 disabled:hover:text-fg-faint",
9697
+ title: hasContextPin ? "Locate the focus boundary in the message list" : "Set a focus boundary first (drag the divider or pin a message) to enable this",
9698
+ children: "Locate boundary line"
9699
+ })
9700
+ ]
9701
+ })
9702
+ ]
9703
+ })
9704
+ }),
9705
+ /*#__PURE__*/ (0,jsx_runtime.jsxs)("div", {
9706
+ ref: maskRegionRef,
9707
+ className: "relative flex-1 min-h-0 overflow-hidden",
9401
9708
  children: [
9402
- /*#__PURE__*/ (0,jsx_runtime.jsxs)("button", {
9403
- type: "button",
9404
- onClick: ()=>setTopControlsOpen((v)=>!v),
9405
- "aria-expanded": topControlsOpen,
9406
- className: "w-full flex items-center gap-2 py-0.5 text-[11px] text-fg-faint hover:text-fg transition-colors",
9709
+ /*#__PURE__*/ (0,jsx_runtime.jsxs)("div", {
9710
+ ref: scrollRef,
9711
+ onScroll: handleScroll,
9712
+ className: "flex-1 h-full overflow-y-auto overflow-x-hidden px-4 py-4 panel-scrollbar",
9713
+ style: {
9714
+ // Scroll-anchor jumps (deep-link to a message) land below the
9715
+ // floating header, not under it.
9716
+ scrollPaddingTop: "calc(3rem + var(--app-safe-top))"
9717
+ },
9407
9718
  children: [
9408
- /*#__PURE__*/ (0,jsx_runtime.jsx)(CollapseChevron, {
9409
- open: topControlsOpen,
9410
- size: 10
9411
- }),
9412
- /*#__PURE__*/ (0,jsx_runtime.jsx)("span", {
9413
- className: "font-semibold uppercase tracking-[0.16em]",
9414
- children: "Filters & focus"
9719
+ hasMore && /*#__PURE__*/ (0,jsx_runtime.jsx)("div", {
9720
+ className: "text-center py-1.5 text-[11px] text-fg-faint select-none",
9721
+ children: loadingMore ? "Loading earlier messages…" : "Scroll up for earlier messages"
9415
9722
  }),
9416
- hiddenCount > 0 && /*#__PURE__*/ (0,jsx_runtime.jsxs)("span", {
9417
- className: "ml-auto text-[10px] text-fg-faint",
9418
- "aria-live": "polite",
9723
+ compactionPending && /*#__PURE__*/ (0,jsx_runtime.jsxs)("div", {
9724
+ className: "my-2 flex items-center justify-center gap-2 rounded-lg border border-border bg-surface-2/70 px-3 py-1.5 text-[11px] text-fg-faint select-none",
9419
9725
  children: [
9420
- hiddenCount,
9421
- " hidden"
9726
+ /*#__PURE__*/ (0,jsx_runtime.jsx)(StatusDot, {
9727
+ tone: "accent",
9728
+ size: "sm",
9729
+ pulse: true
9730
+ }),
9731
+ /*#__PURE__*/ (0,jsx_runtime.jsx)("span", {
9732
+ children: "Summarising earlier messages… this turn still sees the full history."
9733
+ })
9422
9734
  ]
9423
- })
9424
- ]
9425
- }),
9426
- topControlsOpen && /*#__PURE__*/ (0,jsx_runtime.jsxs)("div", {
9427
- className: "mt-1 flex items-center gap-1.5 flex-wrap py-1",
9428
- children: [
9429
- availableChips.map((key)=>{
9430
- const on = filters[key];
9431
- const Icon = on ? eye/* default */.A : eye_off/* default */.A;
9432
- return /*#__PURE__*/ (0,jsx_runtime.jsxs)("button", {
9433
- type: "button",
9434
- onClick: ()=>toggle(key),
9435
- className: [
9436
- "inline-flex items-center gap-1 rounded-none border px-2 py-0.5 text-[10px] leading-4 transition-colors",
9437
- on ? "border-border/70 bg-surface-2/70 text-fg-muted hover:text-fg" : "border-border/35 bg-transparent text-fg-faint line-through decoration-fg-faint/60 hover:text-fg-muted"
9438
- ].join(" "),
9439
- title: // ADR-0044 — for the three channels the model's own
9440
- // context is scoped by, the chip's meaning is dual:
9441
- // it doesn't just show/hide rows here, it also
9442
- // decides whether that channel's history is folded
9443
- // into the next turn the agent sees.
9444
- CHANNEL_SCOPED_FILTER_KEYS.has(key) ? on ? `Hide + exclude ${CHIP_LABELS[key]} from the next turn` : `Show + include ${CHIP_LABELS[key]} in the next turn` : on ? `Hide ${CHIP_LABELS[key]} messages` : `Show ${CHIP_LABELS[key]} messages`,
9445
- "aria-pressed": on,
9735
+ }),
9736
+ visibleMessages.length === 0 && !streamingContent && /*#__PURE__*/ (0,jsx_runtime.jsx)("div", {
9737
+ className: "flex items-center justify-center h-full text-fg-faint text-sm select-none",
9738
+ children: messages.length === 0 ? /*#__PURE__*/ (0,jsx_runtime.jsx)("span", {
9739
+ children: "Send a message to begin"
9740
+ }) : /*#__PURE__*/ (0,jsx_runtime.jsxs)("div", {
9741
+ className: "flex flex-col items-center gap-2 text-center px-4",
9446
9742
  children: [
9447
- /*#__PURE__*/ (0,jsx_runtime.jsx)(Icon, {
9448
- size: 10
9743
+ /*#__PURE__*/ (0,jsx_runtime.jsxs)("span", {
9744
+ children: [
9745
+ hiddenCount,
9746
+ " message",
9747
+ hiddenCount === 1 ? " is" : "s are",
9748
+ " hidden by filters"
9749
+ ]
9449
9750
  }),
9450
- /*#__PURE__*/ (0,jsx_runtime.jsx)("span", {
9451
- children: CHIP_LABELS[key]
9751
+ /*#__PURE__*/ (0,jsx_runtime.jsx)("button", {
9752
+ type: "button",
9753
+ onClick: reset,
9754
+ className: "control-tap text-xs px-2.5 py-1 rounded-md border border-border bg-surface-2 text-fg-muted hover:text-fg hover:bg-surface-3 transition-colors",
9755
+ children: "Show all messages"
9452
9756
  })
9453
9757
  ]
9454
- }, key);
9758
+ })
9455
9759
  }),
9456
- onSetContextPin && /*#__PURE__*/ (0,jsx_runtime.jsx)("button", {
9457
- type: "button",
9458
- onClick: scrollToBoundaryLine,
9459
- disabled: !hasContextPin,
9460
- className: "control-tap ml-auto rounded-none border border-border/60 bg-surface-2/70 px-2 py-0.5 text-[10px] leading-4 text-fg-faint transition-colors hover:border-accent/40 hover:text-fg disabled:cursor-not-allowed disabled:opacity-40 disabled:hover:border-border/60 disabled:hover:text-fg-faint",
9461
- title: hasContextPin ? "Locate the focus boundary in the message list" : "Set a focus boundary first (drag the divider or pin a message) to enable this",
9462
- children: "Locate boundary line"
9760
+ (()=>{
9761
+ // ADR-0042. The boundary divider + warm summary card live INSIDE the
9762
+ // message stream so they scroll with content (not above as a fixed
9763
+ // banner). `boundaryIndex` is the index of the first hot message in
9764
+ // the visible list; everything before it is older-than-pin and gets
9765
+ // covered by the warm summary card sitting above the divider.
9766
+ //
9767
+ const hasPin = effectiveHotSinceSeq !== null;
9768
+ const boundaryIndex = hasPin ? boundaryIndexFor(effectiveHotSinceSeq) : -1;
9769
+ const pinAfterAll = hasPin && visibleMessages.length > 0 && boundaryIndex === visibleMessages.length;
9770
+ // The pin is the boundary's source of truth. Summary data can arrive
9771
+ // later (or be unavailable on an older thread), but hiding the line
9772
+ // in that interval makes a valid focus selection look like it vanished.
9773
+ const hasBoundary = hasPin && boundaryIndex >= 0;
9774
+ const olderInVisible = pinAfterAll ? visibleMessages.length : hasBoundary ? boundaryIndex : 0;
9775
+ // "+ N more we don't know about yet" — older pages are likely unloaded.
9776
+ const olderCountLabel = olderInVisible + (hasMore ? 1 : 0);
9777
+ const attachedActivities = new Map();
9778
+ const hiddenActivityIds = new Set();
9779
+ for(let i = 0; i < visibleMessages.length - 1; i++){
9780
+ const activityMessage = visibleMessages[i];
9781
+ const activity = activityMessage.metadata?.automation_activity;
9782
+ if (!activity) continue;
9783
+ const related = visibleMessages[i + 1];
9784
+ const matches = !related.metadata?.automation_activity && (activity.source_kind === "bridge" ? related.role === "user" && related.metadata?.bridge_conversation?.key === activity.source_id : related.role === "assistant" && related.category === activity.source_kind);
9785
+ if (!matches) continue;
9786
+ attachedActivities.set(related.id, activity);
9787
+ hiddenActivityIds.add(activityMessage.id);
9788
+ }
9789
+ const previousVisibleRoles = new Map();
9790
+ let previousVisibleRole = null;
9791
+ for (const message of visibleMessages){
9792
+ previousVisibleRoles.set(message.id, previousVisibleRole);
9793
+ if (!hiddenActivityIds.has(message.id)) previousVisibleRole = message.role;
9794
+ }
9795
+ const renderBoundary = (key)=>/*#__PURE__*/ (0,jsx_runtime.jsx)("div", {
9796
+ id: effectiveHotSinceSeq !== null ? `context-boundary-${effectiveHotSinceSeq}` : undefined,
9797
+ "data-focus-boundary": "1",
9798
+ "data-boundary-seq": effectiveHotSinceSeq ?? undefined,
9799
+ children: /*#__PURE__*/ (0,jsx_runtime.jsx)(ContextBoundaryDivider, {
9800
+ sourceMessages: warmSummarySourceMessages ?? null,
9801
+ sourceChars: warmSummarySourceChars ?? null,
9802
+ summaryChars: warmSummary ? warmSummary.length : null,
9803
+ lineStats: lineStatsForHotSince(effectiveHotSinceSeq),
9804
+ updating: warmSummaryPending && !summaryFresh,
9805
+ draggable: !!onSetContextPin,
9806
+ hidden: isDraggingFocus,
9807
+ disabled: !!streaming,
9808
+ onClick: handleBoundaryClick,
9809
+ onPointerDown: handleBoundaryPointerDown,
9810
+ onPointerMove: handleBoundaryPointerMove,
9811
+ onPointerUp: handleBoundaryPointerUp,
9812
+ onPointerCancel: handleBoundaryPointerCancel
9813
+ })
9814
+ }, key);
9815
+ const nodes = visibleMessages.flatMap((msg, i)=>{
9816
+ const out = [];
9817
+ if (hasBoundary && !pinAfterAll && i === boundaryIndex) {
9818
+ out.push(renderBoundary(`boundary-${msg.id}`));
9819
+ }
9820
+ if (hiddenActivityIds.has(msg.id)) return out;
9821
+ const previousRole = previousVisibleRoles.get(msg.id);
9822
+ const startsTurn = previousRole == null || previousRole !== msg.role;
9823
+ const steeredSegment = steeredSegments?.find((segment)=>segment.id === msg.id);
9824
+ if (steeredSegment) {
9825
+ out.push(/*#__PURE__*/ (0,jsx_runtime.jsx)(StreamingBubble, {
9826
+ content: steeredSegment.content,
9827
+ threadId: threadId ?? null,
9828
+ agentConfig: agentConfig ?? null,
9829
+ showAvatar: i === 0 || visibleMessages[i - 1].role !== "assistant"
9830
+ }, `steered-${steeredSegment.id}`));
9831
+ }
9832
+ out.push(/*#__PURE__*/ (0,jsx_runtime.jsx)("div", {
9833
+ id: typeof msg.seq === "number" ? String(msg.seq) : `msg-${msg.id}`,
9834
+ "data-message-id": msg.id,
9835
+ "data-hot-candidate": "1",
9836
+ "data-message-seq": msg.seq,
9837
+ "data-created-at": msg.created_at,
9838
+ className: startsTurn && i > 0 ? "mt-3" : undefined,
9839
+ children: /*#__PURE__*/ (0,jsx_runtime.jsx)(MessageBubble, {
9840
+ message: msg,
9841
+ attachedActivity: attachedActivities.get(msg.id),
9842
+ threadId: threadId ?? null,
9843
+ agentConfig: agentConfig,
9844
+ userProfile: userProfile,
9845
+ showAvatar: startsTurn,
9846
+ showToolEvents: filters.tool_use,
9847
+ contextWindowTokens: contextWindowTokens ?? null,
9848
+ isLatest: i === visibleMessages.length - 1 && !streamingContent,
9849
+ onRetry: onRetryMessage
9850
+ })
9851
+ }, msg.id));
9852
+ return out;
9853
+ });
9854
+ if (hasBoundary && pinAfterAll) nodes.push(renderBoundary("boundary-tail"));
9855
+ return nodes;
9856
+ })(),
9857
+ /*#__PURE__*/ (0,jsx_runtime.jsx)(LiveTurnActivity, {
9858
+ thinkingContent: thinkingContent,
9859
+ streamingContent: streamingContent,
9860
+ toolEvents: toolEvents,
9861
+ filters: filters,
9862
+ threadId: threadId ?? null,
9863
+ agentConfig: agentConfig ?? null,
9864
+ showStreamingAvatar: messages.length === 0 || messages[messages.length - 1].role !== "assistant",
9865
+ streaming: streaming
9866
+ }),
9867
+ queuedMessages && queuedMessages.length > 0 && /*#__PURE__*/ (0,jsx_runtime.jsx)("div", {
9868
+ className: "flex flex-col gap-1 mt-2 mb-1",
9869
+ children: queuedMessages.map((q)=>/*#__PURE__*/ (0,jsx_runtime.jsx)(QueuedBubble, {
9870
+ item: q,
9871
+ onRemove: onRemoveQueued
9872
+ }, q.id))
9463
9873
  })
9464
9874
  ]
9875
+ }),
9876
+ /*#__PURE__*/ (0,jsx_runtime.jsx)("div", {
9877
+ ref: dragMaskRef,
9878
+ className: "pointer-events-none absolute left-0 right-0 top-0 z-40 opacity-0 transition-opacity duration-75",
9879
+ style: {
9880
+ transform: "translateY(0px)",
9881
+ height: "0px",
9882
+ background: "linear-gradient(to top, rgba(82,82,91,0.24) 0%, rgba(82,82,91,0.2) 22%, rgba(82,82,91,0.14) 48%, rgba(82,82,91,0.08) 72%, rgba(82,82,91,0.03) 88%, rgba(82,82,91,0) 100%)",
9883
+ borderBottom: "0",
9884
+ backdropFilter: "grayscale(0.5) saturate(0.18) contrast(0.98)",
9885
+ WebkitBackdropFilter: "grayscale(0.5) saturate(0.18) contrast(0.98)",
9886
+ maskImage: "linear-gradient(to top, black 0%, rgba(0,0,0,0.88) 72%, rgba(0,0,0,0.32) 90%, transparent 100%)",
9887
+ WebkitMaskImage: "linear-gradient(to top, black 0%, rgba(0,0,0,0.88) 72%, rgba(0,0,0,0.32) 90%, transparent 100%)"
9888
+ }
9465
9889
  })
9466
9890
  ]
9467
- })
9468
- }),
9469
- /*#__PURE__*/ (0,jsx_runtime.jsxs)("div", {
9470
- ref: maskRegionRef,
9471
- className: "relative flex-1 min-h-0 overflow-hidden",
9472
- children: [
9473
- /*#__PURE__*/ (0,jsx_runtime.jsxs)("div", {
9474
- ref: scrollRef,
9475
- onScroll: handleScroll,
9476
- className: "flex-1 h-full overflow-y-auto overflow-x-hidden px-4 py-4 panel-scrollbar",
9891
+ }),
9892
+ showScrollButton && /*#__PURE__*/ (0,jsx_runtime.jsx)("button", {
9893
+ onClick: scrollToBottom,
9894
+ style: {
9895
+ bottom: "calc(1rem + var(--app-safe-bottom))"
9896
+ },
9897
+ className: "absolute right-4 p-2 rounded-full bg-accent/40 hover:bg-accent/80 text-white backdrop-blur-sm shadow-md transition-all animate-in fade-in slide-in-from-bottom-2 duration-200 z-20",
9898
+ title: "Auto-scroll paused — resume at latest message",
9899
+ "aria-label": "Resume auto-scroll to latest message",
9900
+ children: /*#__PURE__*/ (0,jsx_runtime.jsx)(arrow_down/* default */.A, {
9901
+ size: 18
9902
+ })
9903
+ }),
9904
+ isDraggingFocus && /*#__PURE__*/ (0,jsx_runtime.jsx)(jsx_runtime.Fragment, {
9905
+ children: /*#__PURE__*/ (0,jsx_runtime.jsxs)("div", {
9906
+ ref: dragGuideRef,
9907
+ className: "pointer-events-none absolute left-4 right-4 z-50 opacity-0",
9477
9908
  style: {
9478
- // Scroll-anchor jumps (deep-link to a message) land below the
9479
- // floating header, not under it.
9480
- scrollPaddingTop: "calc(3rem + var(--app-safe-top))"
9909
+ transform: "translateY(0px)"
9481
9910
  },
9482
9911
  children: [
9483
- hasMore && /*#__PURE__*/ (0,jsx_runtime.jsx)("div", {
9484
- className: "text-center py-1.5 text-[11px] text-fg-faint select-none",
9485
- children: loadingMore ? "Loading earlier messages…" : "Scroll up for earlier messages"
9486
- }),
9487
- compactionPending && /*#__PURE__*/ (0,jsx_runtime.jsxs)("div", {
9488
- className: "my-2 flex items-center justify-center gap-2 rounded-lg border border-border bg-surface-2/70 px-3 py-1.5 text-[11px] text-fg-faint select-none",
9489
- children: [
9490
- /*#__PURE__*/ (0,jsx_runtime.jsx)(StatusDot, {
9491
- tone: "accent",
9492
- size: "sm",
9493
- pulse: true
9494
- }),
9495
- /*#__PURE__*/ (0,jsx_runtime.jsx)("span", {
9496
- children: "Summarising earlier messages… this turn still sees the full history."
9497
- })
9498
- ]
9912
+ /*#__PURE__*/ (0,jsx_runtime.jsx)("div", {
9913
+ className: "h-[2px] bg-gradient-to-r from-transparent via-accent to-transparent opacity-95 shadow-[0_0_8px_rgba(59,130,246,0.55)]"
9499
9914
  }),
9500
- visibleMessages.length === 0 && !streamingContent && /*#__PURE__*/ (0,jsx_runtime.jsx)("div", {
9501
- className: "flex items-center justify-center h-full text-fg-faint text-sm select-none",
9502
- children: messages.length === 0 ? /*#__PURE__*/ (0,jsx_runtime.jsx)("span", {
9503
- children: "Send a message to begin"
9504
- }) : /*#__PURE__*/ (0,jsx_runtime.jsxs)("div", {
9505
- className: "flex flex-col items-center gap-2 text-center px-4",
9915
+ /*#__PURE__*/ (0,jsx_runtime.jsx)("span", {
9916
+ ref: dragGuideStatsRef,
9917
+ className: "absolute right-1 top-1/2 -translate-y-1/2 text-[10px] text-fg-faint bg-surface/75 px-1.5 rounded border border-border/60",
9918
+ children: lineStatsForHotSince(effectiveHotSinceSeq)
9919
+ })
9920
+ ]
9921
+ })
9922
+ }),
9923
+ summaryPopoverOpen && /*#__PURE__*/ (0,jsx_runtime.jsx)(Dialog/* Dialog */.l, {
9924
+ open: true,
9925
+ onClose: ()=>setSummaryPopoverOpen(false),
9926
+ title: "Earlier messages summary",
9927
+ size: "xl",
9928
+ align: "top",
9929
+ padded: false,
9930
+ children: /*#__PURE__*/ (0,jsx_runtime.jsxs)("div", {
9931
+ className: "p-4 space-y-3",
9932
+ children: [
9933
+ /*#__PURE__*/ (0,jsx_runtime.jsx)("div", {
9934
+ className: "flex items-center gap-2",
9935
+ children: /*#__PURE__*/ (0,jsx_runtime.jsxs)("span", {
9936
+ className: [
9937
+ "text-[10px] px-1.5 py-px rounded border inline-flex items-center gap-1",
9938
+ summaryUpdating ? "border-accent/40 bg-accent/10 text-accent" : summaryReady ? "border-emerald-500/30 bg-emerald-500/10 text-emerald-600 dark:text-emerald-400" : summaryStale ? "border-amber-500/30 bg-amber-500/10 text-amber-700 dark:text-amber-400" : "border-border bg-surface-2 text-fg-faint"
9939
+ ].join(" "),
9506
9940
  children: [
9507
- /*#__PURE__*/ (0,jsx_runtime.jsxs)("span", {
9508
- children: [
9509
- hiddenCount,
9510
- " message",
9511
- hiddenCount === 1 ? " is" : "s are",
9512
- " hidden by filters"
9513
- ]
9941
+ summaryUpdating && /*#__PURE__*/ (0,jsx_runtime.jsx)("span", {
9942
+ className: "h-2 w-2 rounded-full bg-accent animate-pulse",
9943
+ "aria-label": "Summary updating"
9514
9944
  }),
9515
- /*#__PURE__*/ (0,jsx_runtime.jsx)("button", {
9516
- type: "button",
9517
- onClick: reset,
9518
- className: "control-tap text-xs px-2.5 py-1 rounded-md border border-border bg-surface-2 text-fg-muted hover:text-fg hover:bg-surface-3 transition-colors",
9519
- children: "Show all messages"
9945
+ /*#__PURE__*/ (0,jsx_runtime.jsx)("span", {
9946
+ children: summaryUpdating ? "updating" : summaryReady ? "ready" : summaryStale ? "needs refresh" : "pending"
9520
9947
  })
9521
9948
  ]
9522
9949
  })
9523
9950
  }),
9524
- (()=>{
9525
- // ADR-0042. The boundary divider + warm summary card live INSIDE the
9526
- // message stream so they scroll with content (not above as a fixed
9527
- // banner). `boundaryIndex` is the index of the first hot message in
9528
- // the visible list; everything before it is older-than-pin and gets
9529
- // covered by the warm summary card sitting above the divider.
9530
- //
9531
- const hasPin = effectiveHotSinceSeq !== null;
9532
- const boundaryIndex = hasPin ? boundaryIndexFor(effectiveHotSinceSeq) : -1;
9533
- const pinAfterAll = hasPin && visibleMessages.length > 0 && boundaryIndex === visibleMessages.length;
9534
- // The pin is the boundary's source of truth. Summary data can arrive
9535
- // later (or be unavailable on an older thread), but hiding the line
9536
- // in that interval makes a valid focus selection look like it vanished.
9537
- const hasBoundary = hasPin && boundaryIndex >= 0;
9538
- const olderInVisible = pinAfterAll ? visibleMessages.length : hasBoundary ? boundaryIndex : 0;
9539
- // "+ N more we don't know about yet" — older pages are likely unloaded.
9540
- const olderCountLabel = olderInVisible + (hasMore ? 1 : 0);
9541
- const attachedActivities = new Map();
9542
- const hiddenActivityIds = new Set();
9543
- for(let i = 0; i < visibleMessages.length - 1; i++){
9544
- const activityMessage = visibleMessages[i];
9545
- const activity = activityMessage.metadata?.automation_activity;
9546
- if (!activity) continue;
9547
- const related = visibleMessages[i + 1];
9548
- const matches = !related.metadata?.automation_activity && (activity.source_kind === "bridge" ? related.role === "user" && related.metadata?.bridge_conversation?.key === activity.source_id : related.role === "assistant" && related.category === activity.source_kind);
9549
- if (!matches) continue;
9550
- attachedActivities.set(related.id, activity);
9551
- hiddenActivityIds.add(activityMessage.id);
9552
- }
9553
- const previousVisibleRoles = new Map();
9554
- let previousVisibleRole = null;
9555
- for (const message of visibleMessages){
9556
- previousVisibleRoles.set(message.id, previousVisibleRole);
9557
- if (!hiddenActivityIds.has(message.id)) previousVisibleRole = message.role;
9558
- }
9559
- const renderBoundary = (key)=>/*#__PURE__*/ (0,jsx_runtime.jsx)("div", {
9560
- id: effectiveHotSinceSeq !== null ? `context-boundary-${effectiveHotSinceSeq}` : undefined,
9561
- "data-focus-boundary": "1",
9562
- "data-boundary-seq": effectiveHotSinceSeq ?? undefined,
9563
- children: /*#__PURE__*/ (0,jsx_runtime.jsx)(ContextBoundaryDivider, {
9564
- sourceMessages: warmSummarySourceMessages ?? null,
9565
- sourceChars: warmSummarySourceChars ?? null,
9566
- summaryChars: warmSummary ? warmSummary.length : null,
9567
- lineStats: lineStatsForHotSince(effectiveHotSinceSeq),
9568
- updating: warmSummaryPending && !summaryFresh,
9569
- draggable: !!onSetContextPin,
9570
- hidden: isDraggingFocus,
9571
- disabled: !!streaming,
9572
- onClick: handleBoundaryClick,
9573
- onPointerDown: handleBoundaryPointerDown,
9574
- onPointerMove: handleBoundaryPointerMove,
9575
- onPointerUp: handleBoundaryPointerUp,
9576
- onPointerCancel: handleBoundaryPointerCancel
9577
- })
9578
- }, key);
9579
- const nodes = visibleMessages.flatMap((msg, i)=>{
9580
- const out = [];
9581
- if (hasBoundary && !pinAfterAll && i === boundaryIndex) {
9582
- out.push(renderBoundary(`boundary-${msg.id}`));
9583
- }
9584
- if (hiddenActivityIds.has(msg.id)) return out;
9585
- const previousRole = previousVisibleRoles.get(msg.id);
9586
- const startsTurn = previousRole == null || previousRole !== msg.role;
9587
- const steeredSegment = steeredSegments?.find((segment)=>segment.id === msg.id);
9588
- if (steeredSegment) {
9589
- out.push(/*#__PURE__*/ (0,jsx_runtime.jsx)(StreamingBubble, {
9590
- content: steeredSegment.content,
9591
- threadId: threadId ?? null,
9592
- agentConfig: agentConfig ?? null,
9593
- showAvatar: i === 0 || visibleMessages[i - 1].role !== "assistant"
9594
- }, `steered-${steeredSegment.id}`));
9595
- }
9596
- out.push(/*#__PURE__*/ (0,jsx_runtime.jsx)("div", {
9597
- id: typeof msg.seq === "number" ? String(msg.seq) : `msg-${msg.id}`,
9598
- "data-message-id": msg.id,
9599
- "data-hot-candidate": "1",
9600
- "data-message-seq": msg.seq,
9601
- "data-created-at": msg.created_at,
9602
- className: startsTurn && i > 0 ? "mt-3" : undefined,
9603
- children: /*#__PURE__*/ (0,jsx_runtime.jsx)(MessageBubble, {
9604
- message: msg,
9605
- attachedActivity: attachedActivities.get(msg.id),
9606
- threadId: threadId ?? null,
9607
- agentConfig: agentConfig,
9608
- userProfile: userProfile,
9609
- showAvatar: startsTurn,
9610
- showToolEvents: filters.tool_use,
9611
- contextWindowTokens: contextWindowTokens ?? null,
9612
- isLatest: i === visibleMessages.length - 1 && !streamingContent,
9613
- onRetry: onRetryMessage
9614
- })
9615
- }, msg.id));
9616
- return out;
9617
- });
9618
- if (hasBoundary && pinAfterAll) nodes.push(renderBoundary("boundary-tail"));
9619
- return nodes;
9620
- })(),
9621
- /*#__PURE__*/ (0,jsx_runtime.jsx)(LiveTurnActivity, {
9622
- thinkingContent: thinkingContent,
9623
- streamingContent: streamingContent,
9624
- toolEvents: toolEvents,
9625
- filters: filters,
9626
- threadId: threadId ?? null,
9627
- agentConfig: agentConfig ?? null,
9628
- showStreamingAvatar: messages.length === 0 || messages[messages.length - 1].role !== "assistant",
9629
- streaming: streaming
9630
- }),
9631
- queuedMessages && queuedMessages.length > 0 && /*#__PURE__*/ (0,jsx_runtime.jsx)("div", {
9632
- className: "flex flex-col gap-1 mt-2 mb-1",
9633
- children: queuedMessages.map((q)=>/*#__PURE__*/ (0,jsx_runtime.jsx)(QueuedBubble, {
9634
- item: q,
9635
- onRemove: onRemoveQueued
9636
- }, q.id))
9637
- }),
9638
- notices?.map((n)=>/*#__PURE__*/ (0,jsx_runtime.jsx)("div", {
9639
- className: "flex justify-center my-3",
9640
- children: /*#__PURE__*/ (0,jsx_runtime.jsx)("span", {
9641
- className: "text-xs italic text-fg-faint bg-surface-2 px-3 py-1 rounded-full border border-border",
9642
- children: n.text
9643
- })
9644
- }, n.id))
9951
+ !summaryUpdating && /*#__PURE__*/ (0,jsx_runtime.jsx)("p", {
9952
+ className: "text-[11px] text-fg-faint",
9953
+ children: summaryFresh ? "Showing the latest summary for messages above the boundary line." : summaryCommittedEmpty ? warmChannelSummaries.length > 0 ? "No chat messages above the boundary line; automation activity there is summarised below." : "Nothing above the boundary line needed summarising." : summaryStale ? "This summary is from an older focus and will refresh after the next reply." : "No summary yet. It will appear after the next reply."
9954
+ }),
9955
+ /*#__PURE__*/ (0,jsx_runtime.jsx)(WarmSummaryCard, {
9956
+ olderCount: countOlderForHotSince(effectiveHotSinceSeq) + (hasMore ? 1 : 0),
9957
+ summary: warmSummary ?? null,
9958
+ summaryBeforeSeq: warmSummaryBeforeSeq ?? null,
9959
+ hotSinceSeq: effectiveHotSinceSeq,
9960
+ computedAt: warmSummaryComputedAt ?? null,
9961
+ streaming: !!streaming,
9962
+ topics: warmSummaryTopics ?? null,
9963
+ channelSummaries: warmChannelSummaries
9964
+ })
9645
9965
  ]
9646
- }),
9647
- /*#__PURE__*/ (0,jsx_runtime.jsx)("div", {
9648
- ref: dragMaskRef,
9649
- className: "pointer-events-none absolute left-0 right-0 top-0 z-40 opacity-0 transition-opacity duration-75",
9650
- style: {
9651
- transform: "translateY(0px)",
9652
- height: "0px",
9653
- background: "linear-gradient(to top, rgba(82,82,91,0.24) 0%, rgba(82,82,91,0.2) 22%, rgba(82,82,91,0.14) 48%, rgba(82,82,91,0.08) 72%, rgba(82,82,91,0.03) 88%, rgba(82,82,91,0) 100%)",
9654
- borderBottom: "0",
9655
- backdropFilter: "grayscale(0.5) saturate(0.18) contrast(0.98)",
9656
- WebkitBackdropFilter: "grayscale(0.5) saturate(0.18) contrast(0.98)",
9657
- maskImage: "linear-gradient(to top, black 0%, rgba(0,0,0,0.88) 72%, rgba(0,0,0,0.32) 90%, transparent 100%)",
9658
- WebkitMaskImage: "linear-gradient(to top, black 0%, rgba(0,0,0,0.88) 72%, rgba(0,0,0,0.32) 90%, transparent 100%)"
9659
- }
9660
9966
  })
9661
- ]
9662
- }),
9663
- showScrollButton && /*#__PURE__*/ (0,jsx_runtime.jsx)("button", {
9664
- onClick: scrollToBottom,
9665
- style: {
9666
- bottom: "calc(1rem + var(--app-safe-bottom))"
9667
- },
9668
- className: "absolute right-4 p-2 rounded-full bg-accent/40 hover:bg-accent/80 text-white backdrop-blur-sm shadow-md transition-all animate-in fade-in slide-in-from-bottom-2 duration-200 z-20",
9669
- title: "Auto-scroll paused — resume at latest message",
9670
- "aria-label": "Resume auto-scroll to latest message",
9671
- children: /*#__PURE__*/ (0,jsx_runtime.jsx)(arrow_down/* default */.A, {
9672
- size: 18
9673
- })
9674
- }),
9675
- isDraggingFocus && /*#__PURE__*/ (0,jsx_runtime.jsx)(jsx_runtime.Fragment, {
9676
- children: /*#__PURE__*/ (0,jsx_runtime.jsxs)("div", {
9677
- ref: dragGuideRef,
9678
- className: "pointer-events-none absolute left-4 right-4 z-50 opacity-0",
9679
- style: {
9680
- transform: "translateY(0px)"
9967
+ }),
9968
+ /*#__PURE__*/ (0,jsx_runtime.jsxs)(Dialog/* Dialog */.l, {
9969
+ open: confirmOpen,
9970
+ onClose: ()=>{
9971
+ setConfirmOpen(false);
9972
+ setPendingHotSinceSeq(null);
9681
9973
  },
9974
+ size: "sm",
9975
+ align: "center",
9976
+ dismissOnBackdrop: false,
9682
9977
  children: [
9683
- /*#__PURE__*/ (0,jsx_runtime.jsx)("div", {
9684
- className: "h-[2px] bg-gradient-to-r from-transparent via-accent to-transparent opacity-95 shadow-[0_0_8px_rgba(59,130,246,0.55)]"
9978
+ /*#__PURE__*/ (0,jsx_runtime.jsx)("h4", {
9979
+ className: "text-sm font-semibold text-fg",
9980
+ children: "Move conversation focus here?"
9685
9981
  }),
9686
- /*#__PURE__*/ (0,jsx_runtime.jsx)("span", {
9687
- ref: dragGuideStatsRef,
9688
- className: "absolute right-1 top-1/2 -translate-y-1/2 text-[10px] text-fg-faint bg-surface/75 px-1.5 rounded border border-border/60",
9689
- children: lineStatsForHotSince(effectiveHotSinceSeq)
9690
- })
9691
- ]
9692
- })
9693
- }),
9694
- summaryPopoverOpen && /*#__PURE__*/ (0,jsx_runtime.jsx)(Dialog/* Dialog */.l, {
9695
- open: true,
9696
- onClose: ()=>setSummaryPopoverOpen(false),
9697
- title: "Earlier messages summary",
9698
- size: "xl",
9699
- align: "top",
9700
- padded: false,
9701
- children: /*#__PURE__*/ (0,jsx_runtime.jsxs)("div", {
9702
- className: "p-4 space-y-3",
9703
- children: [
9704
- /*#__PURE__*/ (0,jsx_runtime.jsx)("div", {
9705
- className: "flex items-center gap-2",
9706
- children: /*#__PURE__*/ (0,jsx_runtime.jsxs)("span", {
9707
- className: [
9708
- "text-[10px] px-1.5 py-px rounded border inline-flex items-center gap-1",
9709
- summaryUpdating ? "border-accent/40 bg-accent/10 text-accent" : summaryFresh ? "border-emerald-500/30 bg-emerald-500/10 text-emerald-600 dark:text-emerald-400" : summaryStale ? "border-amber-500/30 bg-amber-500/10 text-amber-700 dark:text-amber-400" : "border-border bg-surface-2 text-fg-faint"
9710
- ].join(" "),
9711
- children: [
9712
- summaryUpdating && /*#__PURE__*/ (0,jsx_runtime.jsx)("span", {
9713
- className: "h-2 w-2 rounded-full bg-accent animate-pulse",
9714
- "aria-label": "Summary updating"
9715
- }),
9716
- /*#__PURE__*/ (0,jsx_runtime.jsx)("span", {
9717
- children: summaryUpdating ? "updating" : summaryFresh ? "ready" : summaryStale ? "needs refresh" : "pending"
9718
- })
9719
- ]
9720
- })
9982
+ /*#__PURE__*/ (0,jsx_runtime.jsx)("p", {
9983
+ className: "text-xs text-fg-muted leading-relaxed",
9984
+ children: "Start a new conversation context from this point. New replies will prioritize recent messages below this line."
9721
9985
  }),
9722
- !summaryUpdating && /*#__PURE__*/ (0,jsx_runtime.jsx)("p", {
9986
+ nextHotCount !== null && /*#__PURE__*/ (0,jsx_runtime.jsxs)("p", {
9723
9987
  className: "text-[11px] text-fg-faint",
9724
- children: summaryFresh ? "Showing the latest summary for messages above the boundary line." : summaryStale ? "This summary is from an older focus and will refresh after the next reply." : "No summary yet. It will appear after the next reply."
9988
+ children: [
9989
+ "Recent in focus: ",
9990
+ nextHotCount,
9991
+ " loaded message",
9992
+ nextHotCount === 1 ? "" : "s",
9993
+ "; earlier loaded summary: ",
9994
+ Math.max(0, visibleMessages.length - nextHotCount),
9995
+ "."
9996
+ ]
9997
+ }),
9998
+ removesFromRecent && /*#__PURE__*/ (0,jsx_runtime.jsx)("p", {
9999
+ className: "text-[11px] text-amber-600 dark:text-amber-400",
10000
+ children: "This reduces recent in-focus messages. You can drag upward later to add history back."
9725
10001
  }),
9726
- /*#__PURE__*/ (0,jsx_runtime.jsx)(WarmSummaryCard, {
9727
- olderCount: countOlderForHotSince(effectiveHotSinceSeq) + (hasMore ? 1 : 0),
9728
- summary: warmSummary ?? null,
9729
- summaryBeforeSeq: warmSummaryBeforeSeq ?? null,
9730
- hotSinceSeq: effectiveHotSinceSeq,
9731
- computedAt: warmSummaryComputedAt ?? null,
9732
- streaming: !!streaming,
9733
- topics: warmSummaryTopics ?? null
10002
+ /*#__PURE__*/ (0,jsx_runtime.jsxs)("div", {
10003
+ className: "flex justify-end gap-2 pt-1",
10004
+ children: [
10005
+ /*#__PURE__*/ (0,jsx_runtime.jsx)("button", {
10006
+ type: "button",
10007
+ onClick: ()=>{
10008
+ setConfirmOpen(false);
10009
+ setPendingHotSinceSeq(null);
10010
+ },
10011
+ className: "px-3 py-1.5 text-xs text-fg-subtle hover:text-fg transition-colors",
10012
+ children: "Cancel"
10013
+ }),
10014
+ /*#__PURE__*/ (0,jsx_runtime.jsx)("button", {
10015
+ type: "button",
10016
+ onClick: ()=>{
10017
+ if (pendingHotSinceSeq !== null && onSetContextPin) onSetContextPin(pendingHotSinceSeq);
10018
+ setConfirmOpen(false);
10019
+ setPendingHotSinceSeq(null);
10020
+ },
10021
+ className: "px-3 py-1.5 rounded-md text-xs border border-accent/40 bg-accent text-white hover:opacity-95 transition-opacity",
10022
+ children: "Move focus"
10023
+ })
10024
+ ]
9734
10025
  })
9735
10026
  ]
9736
10027
  })
9737
- }),
9738
- /*#__PURE__*/ (0,jsx_runtime.jsxs)(Dialog/* Dialog */.l, {
9739
- open: confirmOpen,
9740
- onClose: ()=>{
9741
- setConfirmOpen(false);
9742
- setPendingHotSinceSeq(null);
9743
- },
9744
- size: "sm",
9745
- align: "center",
9746
- dismissOnBackdrop: false,
9747
- children: [
9748
- /*#__PURE__*/ (0,jsx_runtime.jsx)("h4", {
9749
- className: "text-sm font-semibold text-fg",
9750
- children: "Move conversation focus here?"
9751
- }),
9752
- /*#__PURE__*/ (0,jsx_runtime.jsx)("p", {
9753
- className: "text-xs text-fg-muted leading-relaxed",
9754
- children: "Start a new conversation context from this point. New replies will prioritize recent messages below this line."
9755
- }),
9756
- nextHotCount !== null && /*#__PURE__*/ (0,jsx_runtime.jsxs)("p", {
9757
- className: "text-[11px] text-fg-faint",
9758
- children: [
9759
- "Recent in focus: ",
9760
- nextHotCount,
9761
- " loaded message",
9762
- nextHotCount === 1 ? "" : "s",
9763
- "; earlier loaded summary: ",
9764
- Math.max(0, visibleMessages.length - nextHotCount),
9765
- "."
9766
- ]
9767
- }),
9768
- removesFromRecent && /*#__PURE__*/ (0,jsx_runtime.jsx)("p", {
9769
- className: "text-[11px] text-amber-600 dark:text-amber-400",
9770
- children: "This reduces recent in-focus messages. You can drag upward later to add history back."
9771
- }),
9772
- /*#__PURE__*/ (0,jsx_runtime.jsxs)("div", {
9773
- className: "flex justify-end gap-2 pt-1",
9774
- children: [
9775
- /*#__PURE__*/ (0,jsx_runtime.jsx)("button", {
9776
- type: "button",
9777
- onClick: ()=>{
9778
- setConfirmOpen(false);
9779
- setPendingHotSinceSeq(null);
9780
- },
9781
- className: "px-3 py-1.5 text-xs text-fg-subtle hover:text-fg transition-colors",
9782
- children: "Cancel"
9783
- }),
9784
- /*#__PURE__*/ (0,jsx_runtime.jsx)("button", {
9785
- type: "button",
9786
- onClick: ()=>{
9787
- if (pendingHotSinceSeq !== null && onSetContextPin) onSetContextPin(pendingHotSinceSeq);
9788
- setConfirmOpen(false);
9789
- setPendingHotSinceSeq(null);
9790
- },
9791
- className: "px-3 py-1.5 rounded-md text-xs border border-accent/40 bg-accent text-white hover:opacity-95 transition-opacity",
9792
- children: "Move focus"
9793
- })
9794
- ]
9795
- })
9796
- ]
9797
- })
9798
- ]
10028
+ ]
10029
+ })
9799
10030
  });
9800
10031
  }
9801
10032
  // ADR-0044 — the subset of MESSAGE_FILTER_KEYS that also map to a
@@ -9807,6 +10038,7 @@ const CHANNEL_SCOPED_FILTER_KEYS = new Set([
9807
10038
  "watcher",
9808
10039
  "bridge"
9809
10040
  ]);
10041
+ const PROGRAMMATIC_SCROLL_LOCK_MS = 1500;
9810
10042
  const CHIP_LABELS = {
9811
10043
  scheduled_task: "scheduled",
9812
10044
  watcher: "watcher",
@@ -9976,7 +10208,46 @@ function QueuedBubble({ item, onRemove }) {
9976
10208
  }
9977
10209
 
9978
10210
  ;// ./components/chat/chat-helpers.ts
9979
- /* __next_internal_client_entry_do_not_use__ isUnconfirmed,appendUnique,applyThreadMeta,makeQueuedId,parseWarmSummaryTopics auto */ // Append-with-reconcile. Merges server-persisted rows into the local list
10211
+ /* __next_internal_client_entry_do_not_use__ compactionOutcomeToast,isUnconfirmed,appendUnique,applyThreadMeta,makeQueuedId,parseWarmSummaryTopics auto */ // Maps the /compact response to the toast the user sees. The server's reason
10212
+ // decides the text: "nothing to compact" means the thread is empty, anything
10213
+ // else means there were messages but no summary came out of them.
10214
+ function compactionOutcomeToast(result) {
10215
+ if (result.compacted) {
10216
+ const n = result.message_count ?? 0;
10217
+ return {
10218
+ kind: "success",
10219
+ title: "Context compacted",
10220
+ body: n > 0 ? `Summarised ${n} message${n === 1 ? "" : "s"} into warm context.` : "Started a fresh context window."
10221
+ };
10222
+ }
10223
+ if (result.reason === "nothing to compact") {
10224
+ return {
10225
+ kind: "info",
10226
+ title: "Nothing to compact",
10227
+ body: "This conversation has no messages yet."
10228
+ };
10229
+ }
10230
+ if (result.reason === "already compacting") {
10231
+ return {
10232
+ kind: "info",
10233
+ title: "Already compacting",
10234
+ body: "A compaction for this conversation is still running."
10235
+ };
10236
+ }
10237
+ if (result.reason === "timed out") {
10238
+ return {
10239
+ kind: "error",
10240
+ title: "Compaction timed out",
10241
+ body: "The summary took too long and was discarded. Context is unchanged."
10242
+ };
10243
+ }
10244
+ return {
10245
+ kind: "info",
10246
+ title: "Nothing was compacted",
10247
+ body: "There was too little to summarise, or the model returned no usable summary. Context is unchanged."
10248
+ };
10249
+ }
10250
+ // Append-with-reconcile. Merges server-persisted rows into the local list
9980
10251
  // with three rules, applied in order for each incoming message:
9981
10252
  //
9982
10253
  // 1. Already present by server id → update in place (handles the
@@ -10061,10 +10332,12 @@ function applyThreadMeta(meta, payload) {
10061
10332
  meta.setWarmSummarySourceMessages(payload.warm_summary_source_messages ?? null);
10062
10333
  meta.setWarmSummarySourceChars(payload.warm_summary_source_chars ?? null);
10063
10334
  meta.setWarmSummaryTopics?.(payload.warm_summary_topics ?? null);
10335
+ meta.setWarmChannelSummaries?.(payload.warm_channel_summaries ?? []);
10064
10336
  meta.setContextWindowTokens(payload.context_window_tokens ?? null);
10065
10337
  const summaryFresh = hotSinceSeq !== null && summaryBeforeSeq === hotSinceSeq;
10066
10338
  meta.setWarmSummaryPending?.(hotSinceSeq !== null && !summaryFresh);
10067
10339
  meta.setCompactionPending?.(payload.pending_hot_since_seq != null);
10340
+ meta.setManualCompactionPending?.(payload.manual_compaction_pending === true);
10068
10341
  }
10069
10342
  function makeQueuedId(prefix = "q") {
10070
10343
  return `${prefix}-${Date.now()}-${Math.random().toString(36).slice(2, 6)}`;
@@ -10080,8 +10353,6 @@ function makeQueuedId(prefix = "q") {
10080
10353
  }
10081
10354
  }
10082
10355
 
10083
- // EXTERNAL MODULE: ./lib/ui/error-report.ts
10084
- var error_report = __webpack_require__(11856);
10085
10356
  ;// ./lib/ui/error-message.ts
10086
10357
  /* __next_internal_client_entry_do_not_use__ friendlyErrorTitle,reportError auto */ // Centralized human-friendly error-title mapping. Used by pushErrorToast
10087
10358
  // callers so the headline a user sees is consistent across the UI:
@@ -10412,7 +10683,6 @@ function useThreadCrossDeviceSync({ threadId, streamingRef, messagesRef, setMess
10412
10683
 
10413
10684
  function useThreadData({ threadId, attach }) {
10414
10685
  const [messages, setMessages] = (0,react.useState)([]);
10415
- const [notices, setNotices] = (0,react.useState)([]);
10416
10686
  const [hasMore, setHasMore] = (0,react.useState)(false);
10417
10687
  const [loadingMore, setLoadingMore] = (0,react.useState)(false);
10418
10688
  const [messagesLoading, setMessagesLoading] = (0,react.useState)(false);
@@ -10426,8 +10696,10 @@ function useThreadData({ threadId, attach }) {
10426
10696
  const [warmSummarySourceMessages, setWarmSummarySourceMessages] = (0,react.useState)(null);
10427
10697
  const [warmSummarySourceChars, setWarmSummarySourceChars] = (0,react.useState)(null);
10428
10698
  const [warmSummaryTopics, setWarmSummaryTopics] = (0,react.useState)(null);
10699
+ const [warmChannelSummaries, setWarmChannelSummaries] = (0,react.useState)([]);
10429
10700
  const [warmSummaryPending, setWarmSummaryPending] = (0,react.useState)(false);
10430
10701
  const [compactionPending, setCompactionPending] = (0,react.useState)(false);
10702
+ const [manualCompactionPending, setManualCompactionPending] = (0,react.useState)(false);
10431
10703
  const [contextWindowTokens, setContextWindowTokens] = (0,react.useState)(null);
10432
10704
  const messagesRef = (0,react.useRef)([]);
10433
10705
  messagesRef.current = messages;
@@ -10444,22 +10716,14 @@ function useThreadData({ threadId, attach }) {
10444
10716
  setContextWindowTokens,
10445
10717
  setWarmSummaryPending,
10446
10718
  setCompactionPending,
10447
- setWarmSummaryTopics
10719
+ setManualCompactionPending,
10720
+ setWarmSummaryTopics,
10721
+ setWarmChannelSummaries
10448
10722
  };
10449
- const addNotice = (0,react.useCallback)((text)=>{
10450
- setNotices((p)=>[
10451
- ...p,
10452
- {
10453
- id: `notice-${Date.now()}`,
10454
- text
10455
- }
10456
- ]);
10457
- }, []);
10458
10723
  (0,react.useEffect)(()=>{
10459
10724
  if (!threadId) {
10460
10725
  setMetadataThreadId(null);
10461
10726
  setMessages([]);
10462
- setNotices([]);
10463
10727
  setHasMore(false);
10464
10728
  setMessagesLoading(false);
10465
10729
  setHotSince(null);
@@ -10471,8 +10735,10 @@ function useThreadData({ threadId, attach }) {
10471
10735
  setWarmSummarySourceMessages(null);
10472
10736
  setWarmSummarySourceChars(null);
10473
10737
  setWarmSummaryTopics(null);
10738
+ setWarmChannelSummaries([]);
10474
10739
  setWarmSummaryPending(false);
10475
10740
  setCompactionPending(false);
10741
+ setManualCompactionPending(false);
10476
10742
  setContextWindowTokens(null);
10477
10743
  return;
10478
10744
  }
@@ -10490,8 +10756,10 @@ function useThreadData({ threadId, attach }) {
10490
10756
  setWarmSummarySourceMessages(null);
10491
10757
  setWarmSummarySourceChars(null);
10492
10758
  setWarmSummaryTopics(null);
10759
+ setWarmChannelSummaries([]);
10493
10760
  setWarmSummaryPending(false);
10494
10761
  setCompactionPending(false);
10762
+ setManualCompactionPending(false);
10495
10763
  setContextWindowTokens(null);
10496
10764
  client/* api */.FH.threads.get(threadId).then((d)=>{
10497
10765
  if (cancelled) return;
@@ -10537,6 +10805,7 @@ function useThreadData({ threadId, attach }) {
10537
10805
  setWarmSummarySourceMessages(updated.warm_summary_source_messages);
10538
10806
  setWarmSummarySourceChars(updated.warm_summary_source_chars);
10539
10807
  setWarmSummaryTopics(updated.warm_summary_topics);
10808
+ setWarmChannelSummaries(updated.warm_channel_summaries ?? []);
10540
10809
  setCompactionPending(updated.pending_hot_since_seq != null);
10541
10810
  const summaryFresh = updated.hot_since_seq != null && updated.warm_summary_before_seq === updated.hot_since_seq;
10542
10811
  if (!updated.pending_hot_since_seq && (!updated.hot_since_seq || summaryFresh)) {
@@ -10554,7 +10823,7 @@ function useThreadData({ threadId, attach }) {
10554
10823
  if (!threadId) return;
10555
10824
  const summaryFresh = hotSinceSeq !== null && warmSummaryBeforeSeq === hotSinceSeq;
10556
10825
  const summaryStale = warmSummaryPending && hotSinceSeq !== null && !summaryFresh;
10557
- if (!summaryStale && !compactionPending) {
10826
+ if (!summaryStale && !compactionPending && !manualCompactionPending) {
10558
10827
  if (warmSummaryPending && hotSinceSeq !== null && summaryFresh) setWarmSummaryPending(false);
10559
10828
  return;
10560
10829
  }
@@ -10580,6 +10849,7 @@ function useThreadData({ threadId, attach }) {
10580
10849
  threadId,
10581
10850
  warmSummaryPending,
10582
10851
  compactionPending,
10852
+ manualCompactionPending,
10583
10853
  hotSince,
10584
10854
  hotSinceSeq,
10585
10855
  warmSummaryBefore,
@@ -10617,9 +10887,6 @@ function useThreadData({ threadId, attach }) {
10617
10887
  messages,
10618
10888
  setMessages,
10619
10889
  messagesRef,
10620
- notices,
10621
- setNotices,
10622
- addNotice,
10623
10890
  hasMore,
10624
10891
  setHasMore,
10625
10892
  loadingMore,
@@ -10634,8 +10901,10 @@ function useThreadData({ threadId, attach }) {
10634
10901
  warmSummarySourceMessages,
10635
10902
  warmSummarySourceChars,
10636
10903
  warmSummaryTopics,
10904
+ warmChannelSummaries,
10637
10905
  warmSummaryPending,
10638
10906
  compactionPending,
10907
+ manualCompactionPending,
10639
10908
  contextWindowTokens,
10640
10909
  metaApplier,
10641
10910
  loadOlder,
@@ -10643,6 +10912,96 @@ function useThreadData({ threadId, attach }) {
10643
10912
  };
10644
10913
  }
10645
10914
 
10915
+ ;// ./components/chat/useThreadActivity.ts
10916
+ /* __next_internal_client_entry_do_not_use__ useThreadActivity auto */
10917
+
10918
+
10919
+ const BUSY_POLL_MS = 1500;
10920
+ const IDLE_POLL_MS = 5000;
10921
+ // A run's stream ends a moment before the registry marks it finished; a
10922
+ // snapshot inside this window may still report the run that just ended.
10923
+ const SETTLE_GRACE_MS = 2000;
10924
+ /**
10925
+ * Poll what the thread is doing on the server and keep the chat in step:
10926
+ * re-attach to a turn started elsewhere (scheduler, watcher, bridge, another
10927
+ * device), restore compaction flags after a remount, and refresh the thread
10928
+ * metadata once a compaction finishes.
10929
+ */ function useThreadActivity({ threadId, attach, isLive, lastSettledAt, metaApplier }) {
10930
+ const [activity, setActivity] = (0,react.useState)(null);
10931
+ const deps = (0,react.useRef)({
10932
+ attach,
10933
+ isLive,
10934
+ lastSettledAt,
10935
+ metaApplier
10936
+ });
10937
+ deps.current = {
10938
+ attach,
10939
+ isLive,
10940
+ lastSettledAt,
10941
+ metaApplier
10942
+ };
10943
+ (0,react.useEffect)(()=>{
10944
+ setActivity(null);
10945
+ if (!threadId) return;
10946
+ let cancelled = false;
10947
+ let timer = null;
10948
+ let hadCompaction = false;
10949
+ const schedule = (ms)=>{
10950
+ if (!cancelled) timer = window.setTimeout(tick, ms);
10951
+ };
10952
+ async function tick() {
10953
+ if (cancelled || !threadId) return;
10954
+ if (typeof document !== "undefined" && document.hidden) {
10955
+ schedule(IDLE_POLL_MS);
10956
+ return;
10957
+ }
10958
+ let next;
10959
+ try {
10960
+ next = await client/* api */.FH.threads.activity(threadId);
10961
+ } catch {
10962
+ schedule(IDLE_POLL_MS);
10963
+ return;
10964
+ }
10965
+ if (cancelled) return;
10966
+ setActivity(next);
10967
+ const d = deps.current;
10968
+ const serverRunning = next.run !== null || next.queue_depth > 0;
10969
+ const recentlySettled = Date.now() - d.lastSettledAt() < SETTLE_GRACE_MS;
10970
+ if (serverRunning && !d.isLive() && !recentlySettled) {
10971
+ d.attach(threadId).catch(()=>{});
10972
+ }
10973
+ if (next.compaction) {
10974
+ if (next.compaction.kind !== "refresh") d.metaApplier.setCompactionPending?.(true);
10975
+ if (next.compaction.kind === "manual") d.metaApplier.setManualCompactionPending?.(true);
10976
+ hadCompaction = true;
10977
+ } else if (hadCompaction) {
10978
+ hadCompaction = false;
10979
+ // The compaction just finished. Clear the flags from the snapshot
10980
+ // itself so a failed refresh below can't leave the chat locked, then
10981
+ // pull the new boundary and recap.
10982
+ d.metaApplier.setCompactionPending?.(false);
10983
+ d.metaApplier.setManualCompactionPending?.(false);
10984
+ client/* api */.FH.threads.get(threadId, {
10985
+ limit: 1
10986
+ }).then((meta)=>{
10987
+ if (!cancelled) applyThreadMeta(deps.current.metaApplier, meta);
10988
+ }).catch(()=>{});
10989
+ }
10990
+ schedule(next.busy ? BUSY_POLL_MS : IDLE_POLL_MS);
10991
+ }
10992
+ // The thread load attaches to any in-flight run itself; give it a beat
10993
+ // so this poller doesn't race it with a second attach.
10994
+ schedule(BUSY_POLL_MS);
10995
+ return ()=>{
10996
+ cancelled = true;
10997
+ if (timer !== null) window.clearTimeout(timer);
10998
+ };
10999
+ }, [
11000
+ threadId
11001
+ ]);
11002
+ return activity;
11003
+ }
11004
+
10646
11005
  ;// ./components/chat/useUserProfileAndAgent.ts
10647
11006
  /* __next_internal_client_entry_do_not_use__ useUserProfileAndAgent auto */
10648
11007
 
@@ -10850,6 +11209,9 @@ function useChatSubmitHandlers({ agentId, steerRun, attachments, setAttachments,
10850
11209
 
10851
11210
 
10852
11211
 
11212
+
11213
+
11214
+
10853
11215
 
10854
11216
  function ChatView({ threadId, agentId, sessionLoading, sessionError, onMessageSent }) {
10855
11217
  const { state } = (0,AppContext/* useAppContext */.U)();
@@ -10906,6 +11268,19 @@ function ChatView({ threadId, agentId, sessionLoading, sessionError, onMessageSe
10906
11268
  attachRef.current = sse.attach;
10907
11269
  clearStreamingRef.current = sse.clearStreamingContent;
10908
11270
  clearToolEventsRef.current = sse.clearToolEvents;
11271
+ // `compacting` lives in this component, which remounts per agent; the
11272
+ // server flag keeps a /compact started before an agent switch visible.
11273
+ const sessionCompacting = compacting || thread.manualCompactionPending;
11274
+ const activity = useThreadActivity({
11275
+ threadId,
11276
+ attach: stableAttach,
11277
+ isLive: sse.isLive,
11278
+ lastSettledAt: sse.lastSettledAt,
11279
+ metaApplier: thread.metaApplier
11280
+ });
11281
+ // Run phases come through the attached stream; background compaction
11282
+ // outside a run has no stream, so label it from the polled activity.
11283
+ const backgroundCompaction = !sse.streaming && !sessionCompacting ? activity?.compaction?.kind ?? null : null;
10909
11284
  useChatErrorReporting({
10910
11285
  sessionError,
10911
11286
  streamError: sse.error,
@@ -10915,6 +11290,8 @@ function ChatView({ threadId, agentId, sessionLoading, sessionError, onMessageSe
10915
11290
  });
10916
11291
  const streamingRef = (0,react.useRef)(false);
10917
11292
  streamingRef.current = sse.streaming;
11293
+ const currentThreadIdRef = (0,react.useRef)(threadId);
11294
+ currentThreadIdRef.current = threadId;
10918
11295
  // Auto compaction starts server-side during a run; poll so the banner shows live.
10919
11296
  (0,react.useEffect)(()=>{
10920
11297
  if (!threadId || !sse.streaming) return;
@@ -10945,10 +11322,13 @@ function ChatView({ threadId, agentId, sessionLoading, sessionError, onMessageSe
10945
11322
  });
10946
11323
  useTrackLoading(!!sessionLoading);
10947
11324
  useTrackLoading(sse.streaming);
10948
- useTrackLoading(compacting);
11325
+ useTrackLoading(sessionCompacting);
10949
11326
  useTrackLoading(thread.loadingMore);
10950
11327
  useTrackLoading(thread.messagesLoading);
10951
11328
  useTrackLoading(agentConfigLoading);
11329
+ useActivityWhile(sessionCompacting, "Compacting session…");
11330
+ useActivityWhile(backgroundCompaction === "auto", "Compacting earlier messages…");
11331
+ useActivityWhile(backgroundCompaction === "refresh", "Updating summary…");
10952
11332
  useActivityWhile(thread.messagesLoading, "Loading chat history…");
10953
11333
  useActivityWhile(agentConfigLoading, "Loading agent…");
10954
11334
  useActivityWhile(profileLoading, "Loading profile…");
@@ -11052,19 +11432,35 @@ function ChatView({ threadId, agentId, sessionLoading, sessionError, onMessageSe
11052
11432
  const queue = useChatQueue({
11053
11433
  threadId,
11054
11434
  streaming: sse.streaming,
11055
- compacting,
11435
+ compacting: sessionCompacting,
11056
11436
  launchRun
11057
11437
  });
11058
11438
  queueApiRef.current = queue;
11059
11439
  drainQueueRef.current = queue.drainQueueRef.current;
11060
11440
  async function handleCompact() {
11061
11441
  if (!agentId) return;
11442
+ const notifyCompaction = (result)=>{
11443
+ const toast = compactionOutcomeToast(result);
11444
+ (0,ui_toasts/* pushToast */.Iz)({
11445
+ ...toast,
11446
+ source: "system",
11447
+ sourceLabel: "Chat",
11448
+ agent_id: agentId,
11449
+ thread_id: threadId,
11450
+ ttl: 5000,
11451
+ dedupeKey: `compact:${agentId}`
11452
+ });
11453
+ };
11062
11454
  setCompacting(true);
11063
11455
  try {
11064
11456
  const result = await client/* api */.FH.agents.compact(agentId, {
11065
11457
  resetContext: true
11066
11458
  });
11067
- if (result.compacted) {
11459
+ // The thread may have changed while compaction ran; never apply its
11460
+ // result to a different thread's view.
11461
+ const compactedThreadId = threadId;
11462
+ const stillCurrent = ()=>compactedThreadId !== null && currentThreadIdRef.current === compactedThreadId;
11463
+ if (result.compacted && compactedThreadId !== null && stillCurrent()) {
11068
11464
  // Server moved the hot/warm pin to just after the last existing
11069
11465
  // message and persisted the warm summary. Mirror that in-place so
11070
11466
  // the warm card shows the fresh summary without wiping the visible
@@ -11076,16 +11472,29 @@ function ChatView({ threadId, agentId, sessionLoading, sessionError, onMessageSe
11076
11472
  thread.metaApplier.setWarmSummary(result.warm_summary ?? null);
11077
11473
  thread.metaApplier.setWarmSummaryBefore(result.warm_summary_before ?? null);
11078
11474
  thread.metaApplier.setWarmSummaryBeforeSeq(result.warm_summary_before_seq ?? null);
11079
- thread.metaApplier.setWarmSummaryBeforeSeq(result.warm_summary_before_seq ?? null);
11080
11475
  thread.metaApplier.setWarmSummaryComputedAt(result.warm_summary_computed_at ?? null);
11081
11476
  thread.metaApplier.setWarmSummarySourceMessages(result.warm_summary_source_messages ?? null);
11082
11477
  thread.metaApplier.setWarmSummarySourceChars(result.warm_summary_source_chars ?? null);
11083
11478
  thread.metaApplier.setWarmSummaryTopics?.(parseWarmSummaryTopics(result.warm_summary_topics));
11084
- } else {
11085
- thread.addNotice("Nothing to compact yet — send some messages first.");
11479
+ // The compact response carries only the chat recap; channel recaps
11480
+ // (bridge, watcher, scheduled task) come with the thread metadata.
11481
+ void client/* api */.FH.threads.get(compactedThreadId, {
11482
+ limit: 1
11483
+ }).then((d)=>{
11484
+ if (stillCurrent()) applyThreadMeta(thread.metaApplier, d);
11485
+ }).catch(()=>{});
11086
11486
  }
11487
+ notifyCompaction(result);
11087
11488
  } catch (err) {
11088
- thread.addNotice(`Compaction failed: ${String(err)}`);
11489
+ (0,error_report/* pushErrorToast */.uS)({
11490
+ title: "Compaction failed",
11491
+ error: err,
11492
+ context: {
11493
+ panel: "chat",
11494
+ action: "compact",
11495
+ agent_id: agentId
11496
+ }
11497
+ });
11089
11498
  } finally{
11090
11499
  setCompacting(false);
11091
11500
  queue.drainQueueRef.current();
@@ -11111,7 +11520,6 @@ function ChatView({ threadId, agentId, sessionLoading, sessionError, onMessageSe
11111
11520
  threadId: threadId,
11112
11521
  messages: thread.messages,
11113
11522
  steeredSegments: sse.steeredSegments,
11114
- notices: thread.notices,
11115
11523
  agentConfig: agentConfig,
11116
11524
  userProfile: userProfile,
11117
11525
  // streamingContent stays visible past `streaming=false` so the bubble
@@ -11138,8 +11546,9 @@ function ChatView({ threadId, agentId, sessionLoading, sessionError, onMessageSe
11138
11546
  warmSummarySourceMessages: thread.warmSummarySourceMessages,
11139
11547
  warmSummarySourceChars: thread.warmSummarySourceChars,
11140
11548
  warmSummaryTopics: thread.warmSummaryTopics,
11549
+ warmChannelSummaries: thread.warmChannelSummaries,
11141
11550
  warmSummaryPending: thread.warmSummaryPending,
11142
- compactionPending: thread.compactionPending || compacting,
11551
+ compactionPending: thread.compactionPending || sessionCompacting,
11143
11552
  onSetContextPin: thread.setContextPin,
11144
11553
  streaming: sse.streaming,
11145
11554
  contextWindowTokens: thread.contextWindowTokens,
@@ -11167,7 +11576,7 @@ function ChatView({ threadId, agentId, sessionLoading, sessionError, onMessageSe
11167
11576
  onVoiceTranscript: handleVoiceTranscript,
11168
11577
  disabled: !agentId,
11169
11578
  placeholder: composerPlaceholder({
11170
- compacting,
11579
+ compacting: sessionCompacting,
11171
11580
  sessionLoading: !!sessionLoading,
11172
11581
  streaming: sse.streaming
11173
11582
  })
@@ -12851,12 +13260,12 @@ function NetworkSection() {
12851
13260
  /*#__PURE__*/ (0,jsx_runtime.jsxs)("label", {
12852
13261
  className: "block text-xs text-fg-subtle",
12853
13262
  children: [
12854
- "No proxy (comma-separated, optional)",
13263
+ "No proxy (comma-separated, optional; localhost is always direct)",
12855
13264
  /*#__PURE__*/ (0,jsx_runtime.jsx)("input", {
12856
13265
  type: "text",
12857
13266
  value: noProxy,
12858
13267
  onChange: (e)=>setNoProxy(e.target.value),
12859
- placeholder: "localhost,127.0.0.1,.internal",
13268
+ placeholder: ".internal,corp.example",
12860
13269
  className: "mt-1 w-full px-2 py-1.5 text-sm rounded border border-border bg-surface-3 text-fg font-mono"
12861
13270
  })
12862
13271
  ]
@@ -29901,6 +30310,22 @@ function BootScreen({ agents, agentsLoaded, activeAgentId, onPickAgent, suppress
29901
30310
  setAdoptionBusy(null);
29902
30311
  }
29903
30312
  }
30313
+ async function handleAdoptionItemRetry(itemId) {
30314
+ if (adoptionBusy || adoption?.status === "running") return;
30315
+ setAdoptionBusy("retry");
30316
+ try {
30317
+ const next = await client/* api */.FH.lifecycle.adoption.retryItem(itemId);
30318
+ setAdoption(next);
30319
+ adoptionRunStartedRef.current = null;
30320
+ } catch {
30321
+ setAdoption((prev)=>prev ? {
30322
+ ...prev,
30323
+ error: "Could not retry that step."
30324
+ } : prev);
30325
+ } finally{
30326
+ setAdoptionBusy(null);
30327
+ }
30328
+ }
29904
30329
  // The agent rendered in the centered tile. During `loading` and
29905
30330
  // `pick` it's the default (so the user sees the same artwork as soon
29906
30331
  // as agents resolve). During `opening` it's whatever was picked.
@@ -30043,6 +30468,9 @@ function BootScreen({ agents, agentsLoaded, activeAgentId, onPickAgent, suppress
30043
30468
  summary: adoptionLiveLabel ?? adoption.summary,
30044
30469
  items: adoption.checklist,
30045
30470
  error: adoption.error,
30471
+ onRetryItem: (item)=>void handleAdoptionItemRetry(item.id),
30472
+ canRetryItem: (item)=>item.id !== "fetch-changes",
30473
+ retryDisabled: adoptionBusy !== null || adoption.status === "running",
30046
30474
  children: [
30047
30475
  adoption.status === "done" && /*#__PURE__*/ (0,jsx_runtime.jsx)("p", {
30048
30476
  className: "mt-2 rounded-lg border border-border/50 bg-surface px-2 py-1 text-[10px] leading-snug text-fg-muted",
@@ -33492,7 +33920,7 @@ function useTheme() {
33492
33920
  /***/ 39852:
33493
33921
  /***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {
33494
33922
 
33495
- Promise.resolve(/* import() eager */).then(__webpack_require__.bind(__webpack_require__, 9024));
33923
+ Promise.resolve(/* import() eager */).then(__webpack_require__.bind(__webpack_require__, 11362));
33496
33924
  ;
33497
33925
  Promise.resolve(/* import() eager */).then(__webpack_require__.bind(__webpack_require__, 12283));
33498
33926
 
@@ -33507,4 +33935,4 @@ Promise.resolve(/* import() eager */).then(__webpack_require__.bind(__webpack_re
33507
33935
  /******/ _N_E = __webpack_exports__;
33508
33936
  /******/ }
33509
33937
  ]);
33510
- //# sourceMappingURL=page-7017f07f8a7a083c.js.map
33938
+ //# sourceMappingURL=page-04748847c6ff866f.js.map