@circuitwall/jarela 2.2.0 → 2.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (683) hide show
  1. package/.next/standalone/.next/BUILD_ID +1 -1
  2. package/.next/standalone/.next/app-path-routes-manifest.json +4 -3
  3. package/.next/standalone/.next/build-manifest.json +2 -2
  4. package/.next/standalone/.next/prerender-manifest.json +3 -3
  5. package/.next/standalone/.next/routes-manifest.json +8 -0
  6. package/.next/standalone/.next/server/app/_global-error/page.js +68 -68
  7. package/.next/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  8. package/.next/standalone/.next/server/app/_global-error.html +1 -1
  9. package/.next/standalone/.next/server/app/_global-error.rsc +1 -1
  10. package/.next/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  11. package/.next/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  12. package/.next/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  13. package/.next/standalone/.next/server/app/_not-found/page.js +76 -76
  14. package/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  15. package/.next/standalone/.next/server/app/_not-found.html +2 -2
  16. package/.next/standalone/.next/server/app/_not-found.rsc +2 -2
  17. package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +2 -2
  18. package/.next/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +2 -2
  19. package/.next/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  20. package/.next/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  21. package/.next/standalone/.next/server/app/api/v1/access/[identity]/route.js +93 -93
  22. package/.next/standalone/.next/server/app/api/v1/access/route.js +169 -169
  23. package/.next/standalone/.next/server/app/api/v1/agents/[id]/compact/route.js +82 -56
  24. package/.next/standalone/.next/server/app/api/v1/agents/[id]/compact/route.js.nft.json +1 -1
  25. package/.next/standalone/.next/server/app/api/v1/agents/[id]/display-filters/route.js +122 -122
  26. package/.next/standalone/.next/server/app/api/v1/agents/[id]/route.js +100 -100
  27. package/.next/standalone/.next/server/app/api/v1/agents/[id]/thread/route.js +753 -753
  28. package/.next/standalone/.next/server/app/api/v1/agents/route.js +65 -65
  29. package/.next/standalone/.next/server/app/api/v1/allowed-sites/[hostname]/route.js +364 -364
  30. package/.next/standalone/.next/server/app/api/v1/allowed-sites/route.js +802 -802
  31. package/.next/standalone/.next/server/app/api/v1/artifacts/lifecycle/route.js +2 -2
  32. package/.next/standalone/.next/server/app/api/v1/attachments/files/route.js +49 -49
  33. package/.next/standalone/.next/server/app/api/v1/attachments/images/route.js +910 -910
  34. package/.next/standalone/.next/server/app/api/v1/bridges/[id]/chats/route.js +589 -16
  35. package/.next/standalone/.next/server/app/api/v1/bridges/[id]/chats/route.js.nft.json +1 -1
  36. package/.next/standalone/.next/server/app/api/v1/bridges/[id]/ignores/[remote_jid]/route.js +23 -23
  37. package/.next/standalone/.next/server/app/api/v1/bridges/[id]/ignores/route.js +30 -30
  38. package/.next/standalone/.next/server/app/api/v1/bridges/[id]/lookup/route.js +703 -130
  39. package/.next/standalone/.next/server/app/api/v1/bridges/[id]/lookup/route.js.nft.json +1 -1
  40. package/.next/standalone/.next/server/app/api/v1/bridges/[id]/pair/route.js +708 -135
  41. package/.next/standalone/.next/server/app/api/v1/bridges/[id]/pair/route.js.nft.json +1 -1
  42. package/.next/standalone/.next/server/app/api/v1/bridges/[id]/route.js +802 -229
  43. package/.next/standalone/.next/server/app/api/v1/bridges/[id]/route.js.nft.json +1 -1
  44. package/.next/standalone/.next/server/app/api/v1/bridges/[id]/routes/[route_id]/route.js +739 -739
  45. package/.next/standalone/.next/server/app/api/v1/bridges/[id]/routes/route.js +1035 -1035
  46. package/.next/standalone/.next/server/app/api/v1/bridges/[id]/status/route.js +679 -106
  47. package/.next/standalone/.next/server/app/api/v1/bridges/[id]/status/route.js.nft.json +1 -1
  48. package/.next/standalone/.next/server/app/api/v1/bridges/kinds/route.js +804 -804
  49. package/.next/standalone/.next/server/app/api/v1/bridges/route.js +700 -700
  50. package/.next/standalone/.next/server/app/api/v1/builtin-tools/route.js +9 -9
  51. package/.next/standalone/.next/server/app/api/v1/builtin-tools/route.js.nft.json +1 -1
  52. package/.next/standalone/.next/server/app/api/v1/config/route.js +85 -85
  53. package/.next/standalone/.next/server/app/api/v1/credentials/[id]/route.js +709 -709
  54. package/.next/standalone/.next/server/app/api/v1/credentials/[id]/route.js.nft.json +1 -1
  55. package/.next/standalone/.next/server/app/api/v1/credentials/route.js +2 -2
  56. package/.next/standalone/.next/server/app/api/v1/credentials/route.js.nft.json +1 -1
  57. package/.next/standalone/.next/server/app/api/v1/dashboard/currency/route.js +10 -10
  58. package/.next/standalone/.next/server/app/api/v1/dashboard/metrics/route.js +784 -784
  59. package/.next/standalone/.next/server/app/api/v1/dashboard/pricing/route.js +23 -23
  60. package/.next/standalone/.next/server/app/api/v1/dashboard/pricing-task/route.js +86 -86
  61. package/.next/standalone/.next/server/app/api/v1/dashboard/pricing-task/route.js.nft.json +1 -1
  62. package/.next/standalone/.next/server/app/api/v1/delegations/codex/[job_id]/route.js +57 -57
  63. package/.next/standalone/.next/server/app/api/v1/delegations/codex/[job_id]/route.js.nft.json +1 -1
  64. package/.next/standalone/.next/server/app/api/v1/documents/search/route.js +523 -523
  65. package/.next/standalone/.next/server/app/api/v1/documents/settings/route.js +44 -44
  66. package/.next/standalone/.next/server/app/api/v1/documents/sources/[id]/reindex/route.js +65 -65
  67. package/.next/standalone/.next/server/app/api/v1/documents/sources/[id]/reindex/route.js.nft.json +1 -1
  68. package/.next/standalone/.next/server/app/api/v1/documents/sources/[id]/route.js +122 -122
  69. package/.next/standalone/.next/server/app/api/v1/documents/sources/[id]/route.js.nft.json +1 -1
  70. package/.next/standalone/.next/server/app/api/v1/documents/sources/route.js +37 -37
  71. package/.next/standalone/.next/server/app/api/v1/documents/sources/route.js.nft.json +1 -1
  72. package/.next/standalone/.next/server/app/api/v1/env/route.js +9 -9
  73. package/.next/standalone/.next/server/app/api/v1/env-sync/allowlist/route.js +368 -368
  74. package/.next/standalone/.next/server/app/api/v1/env-sync/route.js +44 -44
  75. package/.next/standalone/.next/server/app/api/v1/events/route.js +751 -178
  76. package/.next/standalone/.next/server/app/api/v1/events/route.js.nft.json +1 -1
  77. package/.next/standalone/.next/server/app/api/v1/events/test/route.js +77 -77
  78. package/.next/standalone/.next/server/app/api/v1/extension/agents/route.js +763 -763
  79. package/.next/standalone/.next/server/app/api/v1/extension/agents/route.js.nft.json +1 -1
  80. package/.next/standalone/.next/server/app/api/v1/extension/browser/activate/route.js +44 -44
  81. package/.next/standalone/.next/server/app/api/v1/extension/browser/foreground/route.js +9 -9
  82. package/.next/standalone/.next/server/app/api/v1/extension/browser/history/route.js +65 -65
  83. package/.next/standalone/.next/server/app/api/v1/extension/browser/poll/route.js +34 -34
  84. package/.next/standalone/.next/server/app/api/v1/extension/browser/progress/route.js +204 -204
  85. package/.next/standalone/.next/server/app/api/v1/extension/browser/result/route.js +133 -133
  86. package/.next/standalone/.next/server/app/api/v1/extension/browser/retry/route.js +106 -106
  87. package/.next/standalone/.next/server/app/api/v1/extension/browser/status/route.js +114 -114
  88. package/.next/standalone/.next/server/app/api/v1/extension/browser/tabs/route.js +134 -134
  89. package/.next/standalone/.next/server/app/api/v1/extension/fill/route.js +690 -690
  90. package/.next/standalone/.next/server/app/api/v1/extension/fill/route.js.nft.json +1 -1
  91. package/.next/standalone/.next/server/app/api/v1/extension/refine/route.js +93 -93
  92. package/.next/standalone/.next/server/app/api/v1/extension/refine/route.js.nft.json +1 -1
  93. package/.next/standalone/.next/server/app/api/v1/extension/turn/route.js +9 -9
  94. package/.next/standalone/.next/server/app/api/v1/extension/turn/route.js.nft.json +1 -1
  95. package/.next/standalone/.next/server/app/api/v1/extensions/route.js +185 -185
  96. package/.next/standalone/.next/server/app/api/v1/extensions/route.js.nft.json +1 -1
  97. package/.next/standalone/.next/server/app/api/v1/extensions/tools/[name]/config/route.js +171 -171
  98. package/.next/standalone/.next/server/app/api/v1/extensions/tools/[name]/config/route.js.nft.json +1 -1
  99. package/.next/standalone/.next/server/app/api/v1/extensions/tools/[name]/route.js +396 -396
  100. package/.next/standalone/.next/server/app/api/v1/extensions/tools/[name]/route.js.nft.json +1 -1
  101. package/.next/standalone/.next/server/app/api/v1/extensions/tools/[name]/secrets/route.js +212 -212
  102. package/.next/standalone/.next/server/app/api/v1/extensions/tools/[name]/secrets/route.js.nft.json +1 -1
  103. package/.next/standalone/.next/server/app/api/v1/files/[name]/route.js +235 -235
  104. package/.next/standalone/.next/server/app/api/v1/fs/browse/route.js +26 -26
  105. package/.next/standalone/.next/server/app/api/v1/harnesses/[id]/route.js +221 -221
  106. package/.next/standalone/.next/server/app/api/v1/harnesses/default/route.js +58 -58
  107. package/.next/standalone/.next/server/app/api/v1/harnesses/route.js +72 -72
  108. package/.next/standalone/.next/server/app/api/v1/health/probes/route.js +9 -9
  109. package/.next/standalone/.next/server/app/api/v1/health/probes/route.js.nft.json +1 -1
  110. package/.next/standalone/.next/server/app/api/v1/health/route.js +772 -772
  111. package/.next/standalone/.next/server/app/api/v1/integrations/[name]/route.js +133 -133
  112. package/.next/standalone/.next/server/app/api/v1/integrations/[name]/test/route.js +9 -9
  113. package/.next/standalone/.next/server/app/api/v1/integrations/[name]/test/route.js.nft.json +1 -1
  114. package/.next/standalone/.next/server/app/api/v1/integrations/gmail/oauth/callback/route.js +363 -363
  115. package/.next/standalone/.next/server/app/api/v1/integrations/gmail/oauth/start/route.js +233 -233
  116. package/.next/standalone/.next/server/app/api/v1/integrations/gmail/oauth/status/route.js +682 -682
  117. package/.next/standalone/.next/server/app/api/v1/integrations/outlook/oauth/callback/route.js +879 -879
  118. package/.next/standalone/.next/server/app/api/v1/integrations/outlook/oauth/start/route.js +108 -108
  119. package/.next/standalone/.next/server/app/api/v1/integrations/outlook/oauth/status/route.js +952 -952
  120. package/.next/standalone/.next/server/app/api/v1/integrations/route.js +216 -216
  121. package/.next/standalone/.next/server/app/api/v1/lifecycle/adoption/route.js +864 -847
  122. package/.next/standalone/.next/server/app/api/v1/lifecycle/adoption/route.js.nft.json +1 -1
  123. package/.next/standalone/.next/server/app/api/v1/local-file/route.js +26 -26
  124. package/.next/standalone/.next/server/app/api/v1/logs/route.js +70 -70
  125. package/.next/standalone/.next/server/app/api/v1/maps/embed/route.js +72 -72
  126. package/.next/standalone/.next/server/app/api/v1/mcp-servers/[name]/route.js +979 -979
  127. package/.next/standalone/.next/server/app/api/v1/mcp-servers/registry/route.js +196 -196
  128. package/.next/standalone/.next/server/app/api/v1/mcp-servers/route.js +2 -2
  129. package/.next/standalone/.next/server/app/api/v1/memory/[namespace]/[key]/route.js +381 -381
  130. package/.next/standalone/.next/server/app/api/v1/memory/policy/route.js +79 -79
  131. package/.next/standalone/.next/server/app/api/v1/memory/route.js +51 -51
  132. package/.next/standalone/.next/server/app/api/v1/memory/search/route.js +131 -131
  133. package/.next/standalone/.next/server/app/api/v1/models/[name]/compact-threads/route.js +374 -369
  134. package/.next/standalone/.next/server/app/api/v1/models/[name]/compact-threads/route.js.nft.json +1 -1
  135. package/.next/standalone/.next/server/app/api/v1/models/[name]/route.js +204 -163
  136. package/.next/standalone/.next/server/app/api/v1/models/route.js +548 -546
  137. package/.next/standalone/.next/server/app/api/v1/packages/catalog/route.js +445 -445
  138. package/.next/standalone/.next/server/app/api/v1/packages/defaults/[id]/route.js +120 -120
  139. package/.next/standalone/.next/server/app/api/v1/packages/defaults/[id]/route.js.nft.json +1 -1
  140. package/.next/standalone/.next/server/app/api/v1/packages/install/[id]/route.js +234 -234
  141. package/.next/standalone/.next/server/app/api/v1/packages/install/[id]/route.js.nft.json +1 -1
  142. package/.next/standalone/.next/server/app/api/v1/packages/install/route.js +407 -407
  143. package/.next/standalone/.next/server/app/api/v1/packages/install/route.js.nft.json +1 -1
  144. package/.next/standalone/.next/server/app/api/v1/packages/manifests/[name]/enabled/route.js +37 -37
  145. package/.next/standalone/.next/server/app/api/v1/packages/manifests/[name]/enabled/route.js.nft.json +1 -1
  146. package/.next/standalone/.next/server/app/api/v1/packages/manifests/[name]/route.js +107 -107
  147. package/.next/standalone/.next/server/app/api/v1/packages/manifests/[name]/route.js.nft.json +1 -1
  148. package/.next/standalone/.next/server/app/api/v1/packages/manifests/route.js +228 -228
  149. package/.next/standalone/.next/server/app/api/v1/packages/manifests/route.js.nft.json +1 -1
  150. package/.next/standalone/.next/server/app/api/v1/packages/reload/route.js +9 -9
  151. package/.next/standalone/.next/server/app/api/v1/packages/reload/route.js.nft.json +1 -1
  152. package/.next/standalone/.next/server/app/api/v1/packages/route.js +148 -148
  153. package/.next/standalone/.next/server/app/api/v1/packages/route.js.nft.json +1 -1
  154. package/.next/standalone/.next/server/app/api/v1/page-capture/route.js +787 -787
  155. package/.next/standalone/.next/server/app/api/v1/page-capture/route.js.nft.json +1 -1
  156. package/.next/standalone/.next/server/app/api/v1/pending-actions/[id]/approve/route.js +507 -507
  157. package/.next/standalone/.next/server/app/api/v1/pending-actions/[id]/approve/route.js.nft.json +1 -1
  158. package/.next/standalone/.next/server/app/api/v1/pending-actions/[id]/deny/route.js +181 -181
  159. package/.next/standalone/.next/server/app/api/v1/pending-actions/[id]/deny/route.js.nft.json +1 -1
  160. package/.next/standalone/.next/server/app/api/v1/pending-actions/route.js +258 -258
  161. package/.next/standalone/.next/server/app/api/v1/pending-actions/route.js.nft.json +1 -1
  162. package/.next/standalone/.next/server/app/api/v1/profile/location/route.js +30 -30
  163. package/.next/standalone/.next/server/app/api/v1/profile/route.js +164 -164
  164. package/.next/standalone/.next/server/app/api/v1/providers/[provider]/models/route.js +71 -68
  165. package/.next/standalone/.next/server/app/api/v1/providers/[provider]/probe/route.js +9 -9
  166. package/.next/standalone/.next/server/app/api/v1/providers/github-copilot/auth/route.js +164 -164
  167. package/.next/standalone/.next/server/app/api/v1/providers/route.js +94 -94
  168. package/.next/standalone/.next/server/app/api/v1/proxy-config/route.js +450 -450
  169. package/.next/standalone/.next/server/app/api/v1/redaction/init/route.js +37 -37
  170. package/.next/standalone/.next/server/app/api/v1/redaction/route.js +58 -58
  171. package/.next/standalone/.next/server/app/api/v1/scheduled-tasks/[id]/route.js +600 -600
  172. package/.next/standalone/.next/server/app/api/v1/scheduled-tasks/[id]/run/route.js +44 -44
  173. package/.next/standalone/.next/server/app/api/v1/scheduled-tasks/[id]/run/route.js.nft.json +1 -1
  174. package/.next/standalone/.next/server/app/api/v1/scheduled-tasks/route.js +732 -732
  175. package/.next/standalone/.next/server/app/api/v1/security/idle-timeout/route.js +359 -359
  176. package/.next/standalone/.next/server/app/api/v1/security/pin/route.js +197 -197
  177. package/.next/standalone/.next/server/app/api/v1/security/state/route.js +51 -51
  178. package/.next/standalone/.next/server/app/api/v1/security/unlock/route.js +176 -176
  179. package/.next/standalone/.next/server/app/api/v1/security/verify-pin/route.js +190 -190
  180. package/.next/standalone/.next/server/app/api/v1/setup/test-key/route.js +26 -26
  181. package/.next/standalone/.next/server/app/api/v1/skills/[id]/route.js +770 -770
  182. package/.next/standalone/.next/server/app/api/v1/skills/repos/[id]/route.js +115 -115
  183. package/.next/standalone/.next/server/app/api/v1/skills/repos/route.js +327 -327
  184. package/.next/standalone/.next/server/app/api/v1/skills/route.js +870 -870
  185. package/.next/standalone/.next/server/app/api/v1/system/abort/route.js +838 -808
  186. package/.next/standalone/.next/server/app/api/v1/system/restart/route.js +177 -177
  187. package/.next/standalone/.next/server/app/api/v1/system/restart/route.js.nft.json +1 -1
  188. package/.next/standalone/.next/server/app/api/v1/tailscale/route.js +164 -164
  189. package/.next/standalone/.next/server/app/api/v1/tasks/[agent_id]/route.js +115 -115
  190. package/.next/standalone/.next/server/app/api/v1/tasks/route.js +23 -23
  191. package/.next/standalone/.next/server/app/api/v1/threads/[thread_id]/activity/route.js +1429 -0
  192. package/.next/standalone/.next/server/app/api/v1/threads/[thread_id]/activity/route.js.nft.json +1 -0
  193. package/.next/standalone/.next/server/app/api/v1/threads/[thread_id]/activity/route_client-reference-manifest.js +1 -0
  194. package/.next/standalone/.next/server/app/api/v1/threads/[thread_id]/context-pin/route.js +635 -634
  195. package/.next/standalone/.next/server/app/api/v1/threads/[thread_id]/context-pin/route.js.nft.json +1 -1
  196. package/.next/standalone/.next/server/app/api/v1/threads/[thread_id]/route.js +53 -439
  197. package/.next/standalone/.next/server/app/api/v1/threads/[thread_id]/route.js.nft.json +1 -1
  198. package/.next/standalone/.next/server/app/api/v1/threads/[thread_id]/run/route.js +172 -172
  199. package/.next/standalone/.next/server/app/api/v1/threads/[thread_id]/run/route.js.nft.json +1 -1
  200. package/.next/standalone/.next/server/app/api/v1/threads/route.js +908 -908
  201. package/.next/standalone/.next/server/app/api/v1/tools/route.js +2 -2
  202. package/.next/standalone/.next/server/app/api/v1/tools/route.js.nft.json +1 -1
  203. package/.next/standalone/.next/server/app/api/v1/update/apply/route.js +17 -17
  204. package/.next/standalone/.next/server/app/api/v1/update/apply/route.js.nft.json +1 -1
  205. package/.next/standalone/.next/server/app/api/v1/update/route.js +570 -570
  206. package/.next/standalone/.next/server/app/api/v1/voice/transcribe/route.js +224 -224
  207. package/.next/standalone/.next/server/app/api/v1/voice/tts/route.js +975 -975
  208. package/.next/standalone/.next/server/app/api/v1/watchers/[id]/route.js +23 -23
  209. package/.next/standalone/.next/server/app/api/v1/watchers/[id]/run/route.js +72 -72
  210. package/.next/standalone/.next/server/app/api/v1/watchers/[id]/run/route.js.nft.json +1 -1
  211. package/.next/standalone/.next/server/app/api/v1/watchers/reaction-scripts/route.js +128 -128
  212. package/.next/standalone/.next/server/app/api/v1/watchers/route.js +164 -164
  213. package/.next/standalone/.next/server/app/api/v1/watchers/route.js.nft.json +1 -1
  214. package/.next/standalone/.next/server/app/icon.svg/route.js +62 -62
  215. package/.next/standalone/.next/server/app/manifest.webmanifest/route.js +436 -436
  216. package/.next/standalone/.next/server/app/page.js +1170 -719
  217. package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  218. package/.next/standalone/.next/server/app/setup/page.js +91 -91
  219. package/.next/standalone/.next/server/app/setup/page_client-reference-manifest.js +1 -1
  220. package/.next/standalone/.next/server/app-paths-manifest.json +4 -3
  221. package/.next/standalone/.next/server/chunks/{424.js → 1388.js} +345 -991
  222. package/.next/standalone/.next/server/chunks/1433.js +1 -1
  223. package/.next/standalone/.next/server/chunks/1638.js +1 -2
  224. package/.next/standalone/.next/server/chunks/1738.js +1 -1
  225. package/.next/standalone/.next/server/chunks/210.js +6 -6
  226. package/.next/standalone/.next/server/chunks/2151.js +31 -1
  227. package/.next/standalone/.next/server/chunks/2207.js +1 -0
  228. package/.next/standalone/.next/server/chunks/2471.js +45 -45
  229. package/.next/standalone/.next/server/chunks/2504.js +1 -1
  230. package/.next/standalone/.next/server/chunks/2695.js +17 -17
  231. package/.next/standalone/.next/server/chunks/3042.js +14 -8
  232. package/.next/standalone/.next/server/chunks/3399.js +10695 -10695
  233. package/.next/standalone/.next/server/chunks/3524.js +5 -33
  234. package/.next/standalone/.next/server/chunks/3566.js +1 -1
  235. package/.next/standalone/.next/server/chunks/4189.js +946 -0
  236. package/.next/standalone/.next/server/chunks/{9590.js → 423.js} +116 -49
  237. package/.next/standalone/.next/server/chunks/4433.js +146 -146
  238. package/.next/standalone/.next/server/chunks/4508.js +3 -3
  239. package/.next/standalone/.next/server/chunks/4588.js +1 -0
  240. package/.next/standalone/.next/server/chunks/46.js +116 -46
  241. package/.next/standalone/.next/server/chunks/466.js +100 -13
  242. package/.next/standalone/.next/server/chunks/4868.js +206 -206
  243. package/.next/standalone/.next/server/chunks/4992.js +13 -0
  244. package/.next/standalone/.next/server/chunks/5120.js +963 -0
  245. package/.next/standalone/.next/server/chunks/5701.js +1 -1
  246. package/.next/standalone/.next/server/chunks/5900.js +1 -1
  247. package/.next/standalone/.next/server/chunks/6210.js +1 -0
  248. package/.next/standalone/.next/server/chunks/6213.js +1 -1
  249. package/.next/standalone/.next/server/chunks/6649.js +3 -3
  250. package/.next/standalone/.next/server/chunks/6703.js +3 -3
  251. package/.next/standalone/.next/server/chunks/7445.js +1 -0
  252. package/.next/standalone/.next/server/chunks/8067.js +12 -0
  253. package/.next/standalone/.next/server/chunks/8461.js +14 -9
  254. package/.next/standalone/.next/server/chunks/8558.js +1 -1
  255. package/.next/standalone/.next/server/chunks/8724.js +1 -1
  256. package/.next/standalone/.next/server/chunks/8849.js +91 -91
  257. package/.next/standalone/.next/server/chunks/9032.js +6 -5
  258. package/.next/standalone/.next/server/chunks/{2563.js → 9164.js} +33106 -31420
  259. package/.next/standalone/.next/server/chunks/9237.js +396 -396
  260. package/.next/standalone/.next/server/chunks/{9640.js → 9304.js} +1628 -573
  261. package/.next/standalone/.next/server/chunks/9406.js +1 -1
  262. package/.next/standalone/.next/server/chunks/9824.js +98 -98
  263. package/.next/standalone/.next/server/chunks/9826.js +1 -0
  264. package/.next/standalone/.next/server/middleware-build-manifest.js +2 -2
  265. package/.next/standalone/.next/server/middleware.js +519 -442
  266. package/.next/standalone/.next/server/pages/404.html +2 -2
  267. package/.next/standalone/.next/server/pages/500.html +1 -1
  268. package/.next/standalone/.next/server/preview-props.json +3 -3
  269. package/.next/standalone/.next/server/server-reference-manifest.json +1 -1
  270. package/.next/standalone/.next/static/chunks/{1395-f201e3e2e1f57715.js → 1395-e4a99912b8f83044.js} +101 -14
  271. package/.next/standalone/.next/static/chunks/{4576-13f7546a145a3624.js → 7045-8bc2f14e430ca661.js} +58 -2
  272. package/.next/standalone/.next/static/chunks/app/_global-error/{page-36cb8b428b38b26a.js → page-6fc5f8e744c81802.js} +1 -1
  273. package/.next/standalone/.next/static/chunks/app/api/v1/access/[identity]/{route-36cb8b428b38b26a.js → route-6fc5f8e744c81802.js} +1 -1
  274. package/.next/standalone/.next/static/chunks/app/api/v1/access/{route-36cb8b428b38b26a.js → route-6fc5f8e744c81802.js} +1 -1
  275. package/.next/standalone/.next/static/chunks/app/api/v1/agents/[id]/compact/{route-36cb8b428b38b26a.js → route-6fc5f8e744c81802.js} +1 -1
  276. package/.next/standalone/.next/static/chunks/app/api/v1/agents/[id]/display-filters/route-6fc5f8e744c81802.js +17 -0
  277. package/.next/standalone/.next/static/chunks/app/api/v1/agents/[id]/route-6fc5f8e744c81802.js +17 -0
  278. package/.next/standalone/.next/static/chunks/app/api/v1/agents/[id]/thread/route-6fc5f8e744c81802.js +17 -0
  279. package/.next/standalone/.next/static/chunks/app/api/v1/agents/route-6fc5f8e744c81802.js +17 -0
  280. package/.next/standalone/.next/static/chunks/app/api/v1/allowed-sites/[hostname]/route-6fc5f8e744c81802.js +17 -0
  281. package/.next/standalone/.next/static/chunks/app/api/v1/allowed-sites/route-6fc5f8e744c81802.js +17 -0
  282. package/.next/standalone/.next/static/chunks/app/api/v1/artifacts/lifecycle/route-6fc5f8e744c81802.js +17 -0
  283. package/.next/standalone/.next/static/chunks/app/api/v1/attachments/files/route-6fc5f8e744c81802.js +17 -0
  284. package/.next/standalone/.next/static/chunks/app/api/v1/attachments/images/route-6fc5f8e744c81802.js +17 -0
  285. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/[id]/chats/route-6fc5f8e744c81802.js +17 -0
  286. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/[id]/ignores/[remote_jid]/route-6fc5f8e744c81802.js +17 -0
  287. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/[id]/ignores/route-6fc5f8e744c81802.js +17 -0
  288. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/[id]/lookup/route-6fc5f8e744c81802.js +17 -0
  289. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/[id]/pair/route-6fc5f8e744c81802.js +17 -0
  290. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/[id]/route-6fc5f8e744c81802.js +17 -0
  291. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/[id]/routes/[route_id]/route-6fc5f8e744c81802.js +17 -0
  292. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/[id]/routes/route-6fc5f8e744c81802.js +17 -0
  293. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/[id]/status/route-6fc5f8e744c81802.js +17 -0
  294. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/kinds/route-6fc5f8e744c81802.js +17 -0
  295. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/route-6fc5f8e744c81802.js +17 -0
  296. package/.next/standalone/.next/static/chunks/app/api/v1/builtin-tools/route-6fc5f8e744c81802.js +17 -0
  297. package/.next/standalone/.next/static/chunks/app/api/v1/config/route-6fc5f8e744c81802.js +17 -0
  298. package/.next/standalone/.next/static/chunks/app/api/v1/credentials/[id]/route-6fc5f8e744c81802.js +17 -0
  299. package/.next/standalone/.next/static/chunks/app/api/v1/credentials/route-6fc5f8e744c81802.js +17 -0
  300. package/.next/standalone/.next/static/chunks/app/api/v1/dashboard/currency/route-6fc5f8e744c81802.js +17 -0
  301. package/.next/standalone/.next/static/chunks/app/api/v1/dashboard/metrics/route-6fc5f8e744c81802.js +17 -0
  302. package/.next/standalone/.next/static/chunks/app/api/v1/dashboard/pricing/route-6fc5f8e744c81802.js +17 -0
  303. package/.next/standalone/.next/static/chunks/app/api/v1/dashboard/pricing-task/route-6fc5f8e744c81802.js +17 -0
  304. package/.next/standalone/.next/static/chunks/app/api/v1/delegations/codex/[job_id]/route-6fc5f8e744c81802.js +17 -0
  305. package/.next/standalone/.next/static/chunks/app/api/v1/documents/search/route-6fc5f8e744c81802.js +17 -0
  306. package/.next/standalone/.next/static/chunks/app/api/v1/documents/settings/route-6fc5f8e744c81802.js +17 -0
  307. package/.next/standalone/.next/static/chunks/app/api/v1/documents/sources/[id]/reindex/route-6fc5f8e744c81802.js +17 -0
  308. package/.next/standalone/.next/static/chunks/app/api/v1/documents/sources/[id]/route-6fc5f8e744c81802.js +17 -0
  309. package/.next/standalone/.next/static/chunks/app/api/v1/documents/sources/route-6fc5f8e744c81802.js +17 -0
  310. package/.next/standalone/.next/static/chunks/app/api/v1/env/route-6fc5f8e744c81802.js +17 -0
  311. package/.next/standalone/.next/static/chunks/app/api/v1/env-sync/allowlist/route-6fc5f8e744c81802.js +17 -0
  312. package/.next/standalone/.next/static/chunks/app/api/v1/env-sync/route-6fc5f8e744c81802.js +17 -0
  313. package/.next/standalone/.next/static/chunks/app/api/v1/events/route-6fc5f8e744c81802.js +17 -0
  314. package/.next/standalone/.next/static/chunks/app/api/v1/events/test/route-6fc5f8e744c81802.js +17 -0
  315. package/.next/standalone/.next/static/chunks/app/api/v1/extension/agents/route-6fc5f8e744c81802.js +17 -0
  316. package/.next/standalone/.next/static/chunks/app/api/v1/extension/browser/activate/route-6fc5f8e744c81802.js +17 -0
  317. package/.next/standalone/.next/static/chunks/app/api/v1/extension/browser/foreground/route-6fc5f8e744c81802.js +17 -0
  318. package/.next/standalone/.next/static/chunks/app/api/v1/extension/browser/history/route-6fc5f8e744c81802.js +17 -0
  319. package/.next/standalone/.next/static/chunks/app/api/v1/extension/browser/poll/route-6fc5f8e744c81802.js +17 -0
  320. package/.next/standalone/.next/static/chunks/app/api/v1/extension/browser/progress/route-6fc5f8e744c81802.js +17 -0
  321. package/.next/standalone/.next/static/chunks/app/api/v1/extension/browser/result/route-6fc5f8e744c81802.js +17 -0
  322. package/.next/standalone/.next/static/chunks/app/api/v1/extension/browser/retry/route-6fc5f8e744c81802.js +17 -0
  323. package/.next/standalone/.next/static/chunks/app/api/v1/extension/browser/status/route-6fc5f8e744c81802.js +17 -0
  324. package/.next/standalone/.next/static/chunks/app/api/v1/extension/browser/tabs/route-6fc5f8e744c81802.js +17 -0
  325. package/.next/standalone/.next/static/chunks/app/api/v1/extension/fill/route-6fc5f8e744c81802.js +17 -0
  326. package/.next/standalone/.next/static/chunks/app/api/v1/extension/refine/route-6fc5f8e744c81802.js +17 -0
  327. package/.next/standalone/.next/static/chunks/app/api/v1/extension/turn/route-6fc5f8e744c81802.js +17 -0
  328. package/.next/standalone/.next/static/chunks/app/api/v1/extensions/route-6fc5f8e744c81802.js +17 -0
  329. package/.next/standalone/.next/static/chunks/app/api/v1/extensions/tools/[name]/config/route-6fc5f8e744c81802.js +17 -0
  330. package/.next/standalone/.next/static/chunks/app/api/v1/extensions/tools/[name]/route-6fc5f8e744c81802.js +17 -0
  331. package/.next/standalone/.next/static/chunks/app/api/v1/extensions/tools/[name]/secrets/route-6fc5f8e744c81802.js +17 -0
  332. package/.next/standalone/.next/static/chunks/app/api/v1/files/[name]/route-6fc5f8e744c81802.js +17 -0
  333. package/.next/standalone/.next/static/chunks/app/api/v1/fs/browse/route-6fc5f8e744c81802.js +17 -0
  334. package/.next/standalone/.next/static/chunks/app/api/v1/harnesses/[id]/route-6fc5f8e744c81802.js +17 -0
  335. package/.next/standalone/.next/static/chunks/app/api/v1/harnesses/default/route-6fc5f8e744c81802.js +17 -0
  336. package/.next/standalone/.next/static/chunks/app/api/v1/harnesses/route-6fc5f8e744c81802.js +17 -0
  337. package/.next/standalone/.next/static/chunks/app/api/v1/health/probes/route-6fc5f8e744c81802.js +17 -0
  338. package/.next/standalone/.next/static/chunks/app/api/v1/health/route-6fc5f8e744c81802.js +17 -0
  339. package/.next/standalone/.next/static/chunks/app/api/v1/integrations/[name]/route-6fc5f8e744c81802.js +17 -0
  340. package/.next/standalone/.next/static/chunks/app/api/v1/integrations/[name]/test/route-6fc5f8e744c81802.js +17 -0
  341. package/.next/standalone/.next/static/chunks/app/api/v1/integrations/gmail/oauth/callback/route-6fc5f8e744c81802.js +17 -0
  342. package/.next/standalone/.next/static/chunks/app/api/v1/integrations/gmail/oauth/start/route-6fc5f8e744c81802.js +17 -0
  343. package/.next/standalone/.next/static/chunks/app/api/v1/integrations/gmail/oauth/status/route-6fc5f8e744c81802.js +17 -0
  344. package/.next/standalone/.next/static/chunks/app/api/v1/integrations/outlook/oauth/callback/route-6fc5f8e744c81802.js +17 -0
  345. package/.next/standalone/.next/static/chunks/app/api/v1/integrations/outlook/oauth/start/route-6fc5f8e744c81802.js +17 -0
  346. package/.next/standalone/.next/static/chunks/app/api/v1/integrations/outlook/oauth/status/route-6fc5f8e744c81802.js +17 -0
  347. package/.next/standalone/.next/static/chunks/app/api/v1/integrations/route-6fc5f8e744c81802.js +17 -0
  348. package/.next/standalone/.next/static/chunks/app/api/v1/lifecycle/adoption/route-6fc5f8e744c81802.js +17 -0
  349. package/.next/standalone/.next/static/chunks/app/api/v1/local-file/route-6fc5f8e744c81802.js +17 -0
  350. package/.next/standalone/.next/static/chunks/app/api/v1/logs/route-6fc5f8e744c81802.js +17 -0
  351. package/.next/standalone/.next/static/chunks/app/api/v1/maps/embed/route-6fc5f8e744c81802.js +17 -0
  352. package/.next/standalone/.next/static/chunks/app/api/v1/mcp-servers/[name]/route-6fc5f8e744c81802.js +17 -0
  353. package/.next/standalone/.next/static/chunks/app/api/v1/mcp-servers/registry/route-6fc5f8e744c81802.js +17 -0
  354. package/.next/standalone/.next/static/chunks/app/api/v1/mcp-servers/route-6fc5f8e744c81802.js +17 -0
  355. package/.next/standalone/.next/static/chunks/app/api/v1/memory/[namespace]/[key]/route-6fc5f8e744c81802.js +17 -0
  356. package/.next/standalone/.next/static/chunks/app/api/v1/memory/policy/route-6fc5f8e744c81802.js +17 -0
  357. package/.next/standalone/.next/static/chunks/app/api/v1/memory/route-6fc5f8e744c81802.js +17 -0
  358. package/.next/standalone/.next/static/chunks/app/api/v1/memory/search/route-6fc5f8e744c81802.js +17 -0
  359. package/.next/standalone/.next/static/chunks/app/api/v1/models/[name]/compact-threads/route-6fc5f8e744c81802.js +17 -0
  360. package/.next/standalone/.next/static/chunks/app/api/v1/models/[name]/route-6fc5f8e744c81802.js +17 -0
  361. package/.next/standalone/.next/static/chunks/app/api/v1/models/route-6fc5f8e744c81802.js +17 -0
  362. package/.next/standalone/.next/static/chunks/app/api/v1/packages/catalog/route-6fc5f8e744c81802.js +17 -0
  363. package/.next/standalone/.next/static/chunks/app/api/v1/packages/defaults/[id]/route-6fc5f8e744c81802.js +17 -0
  364. package/.next/standalone/.next/static/chunks/app/api/v1/packages/install/[id]/route-6fc5f8e744c81802.js +17 -0
  365. package/.next/standalone/.next/static/chunks/app/api/v1/packages/install/route-6fc5f8e744c81802.js +17 -0
  366. package/.next/standalone/.next/static/chunks/app/api/v1/packages/manifests/[name]/enabled/route-6fc5f8e744c81802.js +17 -0
  367. package/.next/standalone/.next/static/chunks/app/api/v1/packages/manifests/[name]/route-6fc5f8e744c81802.js +17 -0
  368. package/.next/standalone/.next/static/chunks/app/api/v1/packages/manifests/route-6fc5f8e744c81802.js +17 -0
  369. package/.next/standalone/.next/static/chunks/app/api/v1/packages/reload/route-6fc5f8e744c81802.js +17 -0
  370. package/.next/standalone/.next/static/chunks/app/api/v1/packages/route-6fc5f8e744c81802.js +17 -0
  371. package/.next/standalone/.next/static/chunks/app/api/v1/page-capture/route-6fc5f8e744c81802.js +17 -0
  372. package/.next/standalone/.next/static/chunks/app/api/v1/pending-actions/[id]/approve/route-6fc5f8e744c81802.js +17 -0
  373. package/.next/standalone/.next/static/chunks/app/api/v1/pending-actions/[id]/deny/route-6fc5f8e744c81802.js +17 -0
  374. package/.next/standalone/.next/static/chunks/app/api/v1/pending-actions/route-6fc5f8e744c81802.js +17 -0
  375. package/.next/standalone/.next/static/chunks/app/api/v1/profile/location/route-6fc5f8e744c81802.js +17 -0
  376. package/.next/standalone/.next/static/chunks/app/api/v1/profile/route-6fc5f8e744c81802.js +17 -0
  377. package/.next/standalone/.next/static/chunks/app/api/v1/providers/[provider]/models/route-6fc5f8e744c81802.js +17 -0
  378. package/.next/standalone/.next/static/chunks/app/api/v1/providers/[provider]/probe/route-6fc5f8e744c81802.js +17 -0
  379. package/.next/standalone/.next/static/chunks/app/api/v1/providers/github-copilot/auth/route-6fc5f8e744c81802.js +17 -0
  380. package/.next/standalone/.next/static/chunks/app/api/v1/providers/route-6fc5f8e744c81802.js +17 -0
  381. package/.next/standalone/.next/static/chunks/app/api/v1/proxy-config/route-6fc5f8e744c81802.js +17 -0
  382. package/.next/standalone/.next/static/chunks/app/api/v1/redaction/init/route-6fc5f8e744c81802.js +17 -0
  383. package/.next/standalone/.next/static/chunks/app/api/v1/redaction/route-6fc5f8e744c81802.js +17 -0
  384. package/.next/standalone/.next/static/chunks/app/api/v1/scheduled-tasks/[id]/route-6fc5f8e744c81802.js +17 -0
  385. package/.next/standalone/.next/static/chunks/app/api/v1/scheduled-tasks/[id]/run/route-6fc5f8e744c81802.js +17 -0
  386. package/.next/standalone/.next/static/chunks/app/api/v1/scheduled-tasks/route-6fc5f8e744c81802.js +17 -0
  387. package/.next/standalone/.next/static/chunks/app/api/v1/security/idle-timeout/route-6fc5f8e744c81802.js +17 -0
  388. package/.next/standalone/.next/static/chunks/app/api/v1/security/pin/route-6fc5f8e744c81802.js +17 -0
  389. package/.next/standalone/.next/static/chunks/app/api/v1/security/state/route-6fc5f8e744c81802.js +17 -0
  390. package/.next/standalone/.next/static/chunks/app/api/v1/security/unlock/route-6fc5f8e744c81802.js +17 -0
  391. package/.next/standalone/.next/static/chunks/app/api/v1/security/verify-pin/route-6fc5f8e744c81802.js +17 -0
  392. package/.next/standalone/.next/static/chunks/app/api/v1/setup/test-key/route-6fc5f8e744c81802.js +17 -0
  393. package/.next/standalone/.next/static/chunks/app/api/v1/skills/[id]/route-6fc5f8e744c81802.js +17 -0
  394. package/.next/standalone/.next/static/chunks/app/api/v1/skills/repos/[id]/route-6fc5f8e744c81802.js +17 -0
  395. package/.next/standalone/.next/static/chunks/app/api/v1/skills/repos/route-6fc5f8e744c81802.js +17 -0
  396. package/.next/standalone/.next/static/chunks/app/api/v1/skills/route-6fc5f8e744c81802.js +17 -0
  397. package/.next/standalone/.next/static/chunks/app/api/v1/system/abort/route-6fc5f8e744c81802.js +17 -0
  398. package/.next/standalone/.next/static/chunks/app/api/v1/system/restart/route-6fc5f8e744c81802.js +17 -0
  399. package/.next/standalone/.next/static/chunks/app/api/v1/tailscale/route-6fc5f8e744c81802.js +17 -0
  400. package/.next/standalone/.next/static/chunks/app/api/v1/tasks/[agent_id]/route-6fc5f8e744c81802.js +17 -0
  401. package/.next/standalone/.next/static/chunks/app/api/v1/tasks/route-6fc5f8e744c81802.js +17 -0
  402. package/.next/standalone/.next/static/chunks/app/api/v1/threads/[thread_id]/activity/route-6fc5f8e744c81802.js +17 -0
  403. package/.next/standalone/.next/static/chunks/app/api/v1/threads/[thread_id]/context-pin/route-6fc5f8e744c81802.js +17 -0
  404. package/.next/standalone/.next/static/chunks/app/api/v1/threads/[thread_id]/route-6fc5f8e744c81802.js +17 -0
  405. package/.next/standalone/.next/static/chunks/app/api/v1/threads/[thread_id]/run/route-6fc5f8e744c81802.js +17 -0
  406. package/.next/standalone/.next/static/chunks/app/api/v1/threads/route-6fc5f8e744c81802.js +17 -0
  407. package/.next/standalone/.next/static/chunks/app/api/v1/tools/route-6fc5f8e744c81802.js +17 -0
  408. package/.next/standalone/.next/static/chunks/app/api/v1/update/apply/route-6fc5f8e744c81802.js +17 -0
  409. package/.next/standalone/.next/static/chunks/app/api/v1/update/route-6fc5f8e744c81802.js +17 -0
  410. package/.next/standalone/.next/static/chunks/app/api/v1/voice/transcribe/route-6fc5f8e744c81802.js +17 -0
  411. package/.next/standalone/.next/static/chunks/app/api/v1/voice/tts/route-6fc5f8e744c81802.js +17 -0
  412. package/.next/standalone/.next/static/chunks/app/api/v1/watchers/[id]/route-6fc5f8e744c81802.js +17 -0
  413. package/.next/standalone/.next/static/chunks/app/api/v1/watchers/[id]/run/route-6fc5f8e744c81802.js +17 -0
  414. package/.next/standalone/.next/static/chunks/app/api/v1/watchers/reaction-scripts/route-6fc5f8e744c81802.js +17 -0
  415. package/.next/standalone/.next/static/chunks/app/api/v1/watchers/route-6fc5f8e744c81802.js +17 -0
  416. package/.next/standalone/.next/static/chunks/app/manifest.webmanifest/route-6fc5f8e744c81802.js +17 -0
  417. package/.next/standalone/.next/static/chunks/app/{page-c6e972a7fd13dae8.js → page-213a623b37226452.js} +1012 -604
  418. package/.next/standalone/.next/static/chunks/next/dist/client/components/builtin/app-error-6fc5f8e744c81802.js +17 -0
  419. package/.next/standalone/.next/static/chunks/next/dist/client/components/builtin/forbidden-6fc5f8e744c81802.js +17 -0
  420. package/.next/standalone/.next/static/chunks/next/dist/client/components/builtin/not-found-6fc5f8e744c81802.js +17 -0
  421. package/.next/standalone/.next/static/chunks/next/dist/client/components/builtin/unauthorized-6fc5f8e744c81802.js +17 -0
  422. package/.next/standalone/.next/static/css/{d80058f0b9b41c09.css → 312542a5725ba0d5.css} +2 -2
  423. package/.next/standalone/docs/adoption/changesets.json +309 -0
  424. package/.next/standalone/lib/skills/builtins/memory-organization/SKILL.md +16 -0
  425. package/.next/standalone/package.json +3 -3
  426. package/CHANGELOG.md +33 -0
  427. package/api/client.models.test.ts +31 -0
  428. package/api/client.ts +25 -1
  429. package/api/types.ts +37 -0
  430. package/app/api/v1/lifecycle/adoption/route.ts +14 -2
  431. package/app/api/v1/models/[name]/compact-threads/route.ts +14 -11
  432. package/app/api/v1/models/[name]/route.test.ts +89 -0
  433. package/app/api/v1/models/[name]/route.ts +54 -3
  434. package/app/api/v1/models/route.ts +4 -2
  435. package/app/api/v1/providers/[provider]/models/route.test.ts +53 -0
  436. package/app/api/v1/providers/[provider]/models/route.ts +27 -16
  437. package/app/api/v1/threads/[thread_id]/activity/route.ts +19 -0
  438. package/app/api/v1/threads/[thread_id]/context-pin/route.test.ts +1 -0
  439. package/app/api/v1/threads/[thread_id]/context-pin/route.ts +2 -1
  440. package/app/api/v1/threads/[thread_id]/route.ts +5 -1
  441. package/components/agents/agent-editor/AdvancedSection.tsx +8 -2
  442. package/components/agents/agent-editor/ModelSection.tsx +6 -3
  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/MessageList.test.tsx +31 -0
  447. package/components/chat/MessageList.tsx +49 -28
  448. package/components/chat/ToolList.test.tsx +92 -16
  449. package/components/chat/ToolList.tsx +59 -4
  450. package/components/chat/chat-helpers.test.tsx +24 -1
  451. package/components/chat/chat-helpers.ts +47 -4
  452. package/components/chat/useThreadActivity.test.tsx +113 -0
  453. package/components/chat/useThreadActivity.ts +94 -0
  454. package/components/chat/useThreadData.ts +16 -16
  455. package/components/chat/workflow-step-retry.ts +25 -0
  456. package/components/models/ModelEditor.tsx +1 -1
  457. package/components/models/ModelsPanel.tsx +34 -8
  458. package/components/models/model-editor/GitHubCopilotAuth.tsx +1 -1
  459. package/components/models/model-editor/save-helpers.ts +2 -2
  460. package/components/models/model-editor/useModelEditorForm.ts +1 -1
  461. package/components/models/model-editor/useModelSaveHandlers.ts +1 -1
  462. package/components/setup/wizard/StepCredentials.tsx +1 -1
  463. package/components/setup/wizard/StepModel.tsx +3 -8
  464. package/components/ui/BootScreen.tsx +17 -0
  465. package/components/ui/WorkflowChecklist.tsx +71 -33
  466. package/hooks/useModels.ts +17 -1
  467. package/hooks/useSSE.ts +28 -3
  468. package/lib/agents/compaction-pipeline.test.ts +202 -0
  469. package/lib/agents/compaction-pipeline.ts +483 -0
  470. package/lib/agents/conversation-summary.ts +37 -21
  471. package/lib/agents/effective-model.test.ts +45 -0
  472. package/lib/agents/effective-model.ts +11 -5
  473. package/lib/agents/llm.ts +2 -2
  474. package/lib/agents/prepare/history-window.test.ts +18 -0
  475. package/lib/agents/prepare/history-window.ts +11 -2
  476. package/lib/agents/prepare/request.ts +4 -0
  477. package/lib/agents/prepare/system-prompt.test.ts +39 -0
  478. package/lib/agents/prepare/system-prompt.ts +8 -3
  479. package/lib/agents/prompt-registry.test.ts +5 -140
  480. package/lib/agents/prompt-registry.ts +45 -1
  481. package/lib/agents/prompt-variants.ts +146 -0
  482. package/lib/agents/run-registry.test.ts +22 -0
  483. package/lib/agents/run-registry.ts +29 -0
  484. package/lib/agents/run-thread.retry.test.ts +67 -1
  485. package/lib/agents/run-thread.ts +96 -6
  486. package/lib/agents/thread-activity.test.ts +31 -0
  487. package/lib/agents/thread-activity.ts +27 -0
  488. package/lib/agents/thread-compaction-state.test.ts +82 -0
  489. package/lib/agents/thread-compaction-state.ts +121 -0
  490. package/lib/agents/thread-compaction.test.ts +83 -4
  491. package/lib/agents/thread-compaction.ts +34 -11
  492. package/lib/agents/warm-summary-background.test.ts +220 -7
  493. package/lib/agents/warm-summary-background.ts +329 -149
  494. package/lib/agents/warm-topics.test.ts +37 -0
  495. package/lib/agents/warm-topics.ts +297 -0
  496. package/lib/agents/workflow-step-retry.test.ts +96 -0
  497. package/lib/agents/workflow-step-retry.ts +216 -0
  498. package/lib/api/browser-control.ts +0 -3
  499. package/lib/db/migrations.ts +15 -0
  500. package/lib/env/config.ts +2 -0
  501. package/lib/env/schema.ts +12 -0
  502. package/lib/health/probes.test.ts +8 -11
  503. package/lib/health/probes.ts +5 -31
  504. package/lib/lifecycle/changeset-build.test.ts +93 -0
  505. package/lib/lifecycle/changeset-build.ts +210 -0
  506. package/lib/lifecycle/changesets.test.ts +101 -0
  507. package/lib/lifecycle/changesets.ts +166 -0
  508. package/lib/lifecycle/surface-collect.test.ts +88 -0
  509. package/lib/lifecycle/surface-collect.ts +64 -0
  510. package/lib/lifecycle/surface-snapshot.test.ts +104 -0
  511. package/lib/lifecycle/surface-snapshot.ts +210 -0
  512. package/lib/memory/record.ts +0 -2
  513. package/lib/models/editor-payload.ts +1 -1
  514. package/lib/providers/external.ts +0 -2
  515. package/lib/providers/github-copilot-auth.ts +2 -3
  516. package/lib/providers/github-copilot.test.ts +27 -0
  517. package/lib/providers/github-copilot.ts +21 -44
  518. package/lib/skills/builtins/memory-organization/SKILL.md +16 -0
  519. package/lib/stores/integrations.test.ts +7 -0
  520. package/lib/stores/integrations.ts +4 -4
  521. package/lib/stores/model-config.test.ts +88 -0
  522. package/lib/stores/model-config.ts +90 -8
  523. package/lib/stores/threads.test.ts +9 -0
  524. package/lib/stores/threads.ts +21 -11
  525. package/lib/stores/version-adoption.test.ts +96 -0
  526. package/lib/stores/version-adoption.ts +239 -26
  527. package/lib/stores/workflow-progress.ts +3 -0
  528. package/lib/tools/communications/ms-todo.ts +0 -7
  529. package/lib/tools/general/memory.ts +1 -1
  530. package/lib/tools/general/workflow-progress.ts +2 -0
  531. package/lib/tools/runtime/catalog.ts +1 -25
  532. package/lib/triggers/registry.ts +0 -4
  533. package/package.json +3 -3
  534. package/scripts/install-to-system.ps1 +39 -11
  535. package/scripts/install-to-system.sh +37 -3
  536. package/.next/standalone/.next/server/chunks/3979.js +0 -581
  537. package/.next/standalone/.next/server/chunks/5936.js +0 -594
  538. package/.next/standalone/.next/static/chunks/app/api/v1/agents/[id]/display-filters/route-36cb8b428b38b26a.js +0 -17
  539. package/.next/standalone/.next/static/chunks/app/api/v1/agents/[id]/route-36cb8b428b38b26a.js +0 -17
  540. package/.next/standalone/.next/static/chunks/app/api/v1/agents/[id]/thread/route-36cb8b428b38b26a.js +0 -17
  541. package/.next/standalone/.next/static/chunks/app/api/v1/agents/route-36cb8b428b38b26a.js +0 -17
  542. package/.next/standalone/.next/static/chunks/app/api/v1/allowed-sites/[hostname]/route-36cb8b428b38b26a.js +0 -17
  543. package/.next/standalone/.next/static/chunks/app/api/v1/allowed-sites/route-36cb8b428b38b26a.js +0 -17
  544. package/.next/standalone/.next/static/chunks/app/api/v1/artifacts/lifecycle/route-36cb8b428b38b26a.js +0 -17
  545. package/.next/standalone/.next/static/chunks/app/api/v1/attachments/files/route-36cb8b428b38b26a.js +0 -17
  546. package/.next/standalone/.next/static/chunks/app/api/v1/attachments/images/route-36cb8b428b38b26a.js +0 -17
  547. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/[id]/chats/route-36cb8b428b38b26a.js +0 -17
  548. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/[id]/ignores/[remote_jid]/route-36cb8b428b38b26a.js +0 -17
  549. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/[id]/ignores/route-36cb8b428b38b26a.js +0 -17
  550. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/[id]/lookup/route-36cb8b428b38b26a.js +0 -17
  551. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/[id]/pair/route-36cb8b428b38b26a.js +0 -17
  552. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/[id]/route-36cb8b428b38b26a.js +0 -17
  553. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/[id]/routes/[route_id]/route-36cb8b428b38b26a.js +0 -17
  554. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/[id]/routes/route-36cb8b428b38b26a.js +0 -17
  555. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/[id]/status/route-36cb8b428b38b26a.js +0 -17
  556. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/kinds/route-36cb8b428b38b26a.js +0 -17
  557. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/route-36cb8b428b38b26a.js +0 -17
  558. package/.next/standalone/.next/static/chunks/app/api/v1/builtin-tools/route-36cb8b428b38b26a.js +0 -17
  559. package/.next/standalone/.next/static/chunks/app/api/v1/config/route-36cb8b428b38b26a.js +0 -17
  560. package/.next/standalone/.next/static/chunks/app/api/v1/credentials/[id]/route-36cb8b428b38b26a.js +0 -17
  561. package/.next/standalone/.next/static/chunks/app/api/v1/credentials/route-36cb8b428b38b26a.js +0 -17
  562. package/.next/standalone/.next/static/chunks/app/api/v1/dashboard/currency/route-36cb8b428b38b26a.js +0 -17
  563. package/.next/standalone/.next/static/chunks/app/api/v1/dashboard/metrics/route-36cb8b428b38b26a.js +0 -17
  564. package/.next/standalone/.next/static/chunks/app/api/v1/dashboard/pricing/route-36cb8b428b38b26a.js +0 -17
  565. package/.next/standalone/.next/static/chunks/app/api/v1/dashboard/pricing-task/route-36cb8b428b38b26a.js +0 -17
  566. package/.next/standalone/.next/static/chunks/app/api/v1/delegations/codex/[job_id]/route-36cb8b428b38b26a.js +0 -17
  567. package/.next/standalone/.next/static/chunks/app/api/v1/documents/search/route-36cb8b428b38b26a.js +0 -17
  568. package/.next/standalone/.next/static/chunks/app/api/v1/documents/settings/route-36cb8b428b38b26a.js +0 -17
  569. package/.next/standalone/.next/static/chunks/app/api/v1/documents/sources/[id]/reindex/route-36cb8b428b38b26a.js +0 -17
  570. package/.next/standalone/.next/static/chunks/app/api/v1/documents/sources/[id]/route-36cb8b428b38b26a.js +0 -17
  571. package/.next/standalone/.next/static/chunks/app/api/v1/documents/sources/route-36cb8b428b38b26a.js +0 -17
  572. package/.next/standalone/.next/static/chunks/app/api/v1/env/route-36cb8b428b38b26a.js +0 -17
  573. package/.next/standalone/.next/static/chunks/app/api/v1/env-sync/allowlist/route-36cb8b428b38b26a.js +0 -17
  574. package/.next/standalone/.next/static/chunks/app/api/v1/env-sync/route-36cb8b428b38b26a.js +0 -17
  575. package/.next/standalone/.next/static/chunks/app/api/v1/events/route-36cb8b428b38b26a.js +0 -17
  576. package/.next/standalone/.next/static/chunks/app/api/v1/events/test/route-36cb8b428b38b26a.js +0 -17
  577. package/.next/standalone/.next/static/chunks/app/api/v1/extension/agents/route-36cb8b428b38b26a.js +0 -17
  578. package/.next/standalone/.next/static/chunks/app/api/v1/extension/browser/activate/route-36cb8b428b38b26a.js +0 -17
  579. package/.next/standalone/.next/static/chunks/app/api/v1/extension/browser/foreground/route-36cb8b428b38b26a.js +0 -17
  580. package/.next/standalone/.next/static/chunks/app/api/v1/extension/browser/history/route-36cb8b428b38b26a.js +0 -17
  581. package/.next/standalone/.next/static/chunks/app/api/v1/extension/browser/poll/route-36cb8b428b38b26a.js +0 -17
  582. package/.next/standalone/.next/static/chunks/app/api/v1/extension/browser/progress/route-36cb8b428b38b26a.js +0 -17
  583. package/.next/standalone/.next/static/chunks/app/api/v1/extension/browser/result/route-36cb8b428b38b26a.js +0 -17
  584. package/.next/standalone/.next/static/chunks/app/api/v1/extension/browser/retry/route-36cb8b428b38b26a.js +0 -17
  585. package/.next/standalone/.next/static/chunks/app/api/v1/extension/browser/status/route-36cb8b428b38b26a.js +0 -17
  586. package/.next/standalone/.next/static/chunks/app/api/v1/extension/browser/tabs/route-36cb8b428b38b26a.js +0 -17
  587. package/.next/standalone/.next/static/chunks/app/api/v1/extension/fill/route-36cb8b428b38b26a.js +0 -17
  588. package/.next/standalone/.next/static/chunks/app/api/v1/extension/refine/route-36cb8b428b38b26a.js +0 -17
  589. package/.next/standalone/.next/static/chunks/app/api/v1/extension/turn/route-36cb8b428b38b26a.js +0 -17
  590. package/.next/standalone/.next/static/chunks/app/api/v1/extensions/route-36cb8b428b38b26a.js +0 -17
  591. package/.next/standalone/.next/static/chunks/app/api/v1/extensions/tools/[name]/config/route-36cb8b428b38b26a.js +0 -17
  592. package/.next/standalone/.next/static/chunks/app/api/v1/extensions/tools/[name]/route-36cb8b428b38b26a.js +0 -17
  593. package/.next/standalone/.next/static/chunks/app/api/v1/extensions/tools/[name]/secrets/route-36cb8b428b38b26a.js +0 -17
  594. package/.next/standalone/.next/static/chunks/app/api/v1/files/[name]/route-36cb8b428b38b26a.js +0 -17
  595. package/.next/standalone/.next/static/chunks/app/api/v1/fs/browse/route-36cb8b428b38b26a.js +0 -17
  596. package/.next/standalone/.next/static/chunks/app/api/v1/harnesses/[id]/route-36cb8b428b38b26a.js +0 -17
  597. package/.next/standalone/.next/static/chunks/app/api/v1/harnesses/default/route-36cb8b428b38b26a.js +0 -17
  598. package/.next/standalone/.next/static/chunks/app/api/v1/harnesses/route-36cb8b428b38b26a.js +0 -17
  599. package/.next/standalone/.next/static/chunks/app/api/v1/health/probes/route-36cb8b428b38b26a.js +0 -17
  600. package/.next/standalone/.next/static/chunks/app/api/v1/health/route-36cb8b428b38b26a.js +0 -17
  601. package/.next/standalone/.next/static/chunks/app/api/v1/integrations/[name]/route-36cb8b428b38b26a.js +0 -17
  602. package/.next/standalone/.next/static/chunks/app/api/v1/integrations/[name]/test/route-36cb8b428b38b26a.js +0 -17
  603. package/.next/standalone/.next/static/chunks/app/api/v1/integrations/gmail/oauth/callback/route-36cb8b428b38b26a.js +0 -17
  604. package/.next/standalone/.next/static/chunks/app/api/v1/integrations/gmail/oauth/start/route-36cb8b428b38b26a.js +0 -17
  605. package/.next/standalone/.next/static/chunks/app/api/v1/integrations/gmail/oauth/status/route-36cb8b428b38b26a.js +0 -17
  606. package/.next/standalone/.next/static/chunks/app/api/v1/integrations/outlook/oauth/callback/route-36cb8b428b38b26a.js +0 -17
  607. package/.next/standalone/.next/static/chunks/app/api/v1/integrations/outlook/oauth/start/route-36cb8b428b38b26a.js +0 -17
  608. package/.next/standalone/.next/static/chunks/app/api/v1/integrations/outlook/oauth/status/route-36cb8b428b38b26a.js +0 -17
  609. package/.next/standalone/.next/static/chunks/app/api/v1/integrations/route-36cb8b428b38b26a.js +0 -17
  610. package/.next/standalone/.next/static/chunks/app/api/v1/lifecycle/adoption/route-36cb8b428b38b26a.js +0 -17
  611. package/.next/standalone/.next/static/chunks/app/api/v1/local-file/route-36cb8b428b38b26a.js +0 -17
  612. package/.next/standalone/.next/static/chunks/app/api/v1/logs/route-36cb8b428b38b26a.js +0 -17
  613. package/.next/standalone/.next/static/chunks/app/api/v1/maps/embed/route-36cb8b428b38b26a.js +0 -17
  614. package/.next/standalone/.next/static/chunks/app/api/v1/mcp-servers/[name]/route-36cb8b428b38b26a.js +0 -17
  615. package/.next/standalone/.next/static/chunks/app/api/v1/mcp-servers/registry/route-36cb8b428b38b26a.js +0 -17
  616. package/.next/standalone/.next/static/chunks/app/api/v1/mcp-servers/route-36cb8b428b38b26a.js +0 -17
  617. package/.next/standalone/.next/static/chunks/app/api/v1/memory/[namespace]/[key]/route-36cb8b428b38b26a.js +0 -17
  618. package/.next/standalone/.next/static/chunks/app/api/v1/memory/policy/route-36cb8b428b38b26a.js +0 -17
  619. package/.next/standalone/.next/static/chunks/app/api/v1/memory/route-36cb8b428b38b26a.js +0 -17
  620. package/.next/standalone/.next/static/chunks/app/api/v1/memory/search/route-36cb8b428b38b26a.js +0 -17
  621. package/.next/standalone/.next/static/chunks/app/api/v1/models/[name]/compact-threads/route-36cb8b428b38b26a.js +0 -17
  622. package/.next/standalone/.next/static/chunks/app/api/v1/models/[name]/route-36cb8b428b38b26a.js +0 -17
  623. package/.next/standalone/.next/static/chunks/app/api/v1/models/route-36cb8b428b38b26a.js +0 -17
  624. package/.next/standalone/.next/static/chunks/app/api/v1/packages/catalog/route-36cb8b428b38b26a.js +0 -17
  625. package/.next/standalone/.next/static/chunks/app/api/v1/packages/defaults/[id]/route-36cb8b428b38b26a.js +0 -17
  626. package/.next/standalone/.next/static/chunks/app/api/v1/packages/install/[id]/route-36cb8b428b38b26a.js +0 -17
  627. package/.next/standalone/.next/static/chunks/app/api/v1/packages/install/route-36cb8b428b38b26a.js +0 -17
  628. package/.next/standalone/.next/static/chunks/app/api/v1/packages/manifests/[name]/enabled/route-36cb8b428b38b26a.js +0 -17
  629. package/.next/standalone/.next/static/chunks/app/api/v1/packages/manifests/[name]/route-36cb8b428b38b26a.js +0 -17
  630. package/.next/standalone/.next/static/chunks/app/api/v1/packages/manifests/route-36cb8b428b38b26a.js +0 -17
  631. package/.next/standalone/.next/static/chunks/app/api/v1/packages/reload/route-36cb8b428b38b26a.js +0 -17
  632. package/.next/standalone/.next/static/chunks/app/api/v1/packages/route-36cb8b428b38b26a.js +0 -17
  633. package/.next/standalone/.next/static/chunks/app/api/v1/page-capture/route-36cb8b428b38b26a.js +0 -17
  634. package/.next/standalone/.next/static/chunks/app/api/v1/pending-actions/[id]/approve/route-36cb8b428b38b26a.js +0 -17
  635. package/.next/standalone/.next/static/chunks/app/api/v1/pending-actions/[id]/deny/route-36cb8b428b38b26a.js +0 -17
  636. package/.next/standalone/.next/static/chunks/app/api/v1/pending-actions/route-36cb8b428b38b26a.js +0 -17
  637. package/.next/standalone/.next/static/chunks/app/api/v1/profile/location/route-36cb8b428b38b26a.js +0 -17
  638. package/.next/standalone/.next/static/chunks/app/api/v1/profile/route-36cb8b428b38b26a.js +0 -17
  639. package/.next/standalone/.next/static/chunks/app/api/v1/providers/[provider]/models/route-36cb8b428b38b26a.js +0 -17
  640. package/.next/standalone/.next/static/chunks/app/api/v1/providers/[provider]/probe/route-36cb8b428b38b26a.js +0 -17
  641. package/.next/standalone/.next/static/chunks/app/api/v1/providers/github-copilot/auth/route-36cb8b428b38b26a.js +0 -17
  642. package/.next/standalone/.next/static/chunks/app/api/v1/providers/route-36cb8b428b38b26a.js +0 -17
  643. package/.next/standalone/.next/static/chunks/app/api/v1/proxy-config/route-36cb8b428b38b26a.js +0 -17
  644. package/.next/standalone/.next/static/chunks/app/api/v1/redaction/init/route-36cb8b428b38b26a.js +0 -17
  645. package/.next/standalone/.next/static/chunks/app/api/v1/redaction/route-36cb8b428b38b26a.js +0 -17
  646. package/.next/standalone/.next/static/chunks/app/api/v1/scheduled-tasks/[id]/route-36cb8b428b38b26a.js +0 -17
  647. package/.next/standalone/.next/static/chunks/app/api/v1/scheduled-tasks/[id]/run/route-36cb8b428b38b26a.js +0 -17
  648. package/.next/standalone/.next/static/chunks/app/api/v1/scheduled-tasks/route-36cb8b428b38b26a.js +0 -17
  649. package/.next/standalone/.next/static/chunks/app/api/v1/security/idle-timeout/route-36cb8b428b38b26a.js +0 -17
  650. package/.next/standalone/.next/static/chunks/app/api/v1/security/pin/route-36cb8b428b38b26a.js +0 -17
  651. package/.next/standalone/.next/static/chunks/app/api/v1/security/state/route-36cb8b428b38b26a.js +0 -17
  652. package/.next/standalone/.next/static/chunks/app/api/v1/security/unlock/route-36cb8b428b38b26a.js +0 -17
  653. package/.next/standalone/.next/static/chunks/app/api/v1/security/verify-pin/route-36cb8b428b38b26a.js +0 -17
  654. package/.next/standalone/.next/static/chunks/app/api/v1/setup/test-key/route-36cb8b428b38b26a.js +0 -17
  655. package/.next/standalone/.next/static/chunks/app/api/v1/skills/[id]/route-36cb8b428b38b26a.js +0 -17
  656. package/.next/standalone/.next/static/chunks/app/api/v1/skills/repos/[id]/route-36cb8b428b38b26a.js +0 -17
  657. package/.next/standalone/.next/static/chunks/app/api/v1/skills/repos/route-36cb8b428b38b26a.js +0 -17
  658. package/.next/standalone/.next/static/chunks/app/api/v1/skills/route-36cb8b428b38b26a.js +0 -17
  659. package/.next/standalone/.next/static/chunks/app/api/v1/system/abort/route-36cb8b428b38b26a.js +0 -17
  660. package/.next/standalone/.next/static/chunks/app/api/v1/system/restart/route-36cb8b428b38b26a.js +0 -17
  661. package/.next/standalone/.next/static/chunks/app/api/v1/tailscale/route-36cb8b428b38b26a.js +0 -17
  662. package/.next/standalone/.next/static/chunks/app/api/v1/tasks/[agent_id]/route-36cb8b428b38b26a.js +0 -17
  663. package/.next/standalone/.next/static/chunks/app/api/v1/tasks/route-36cb8b428b38b26a.js +0 -17
  664. package/.next/standalone/.next/static/chunks/app/api/v1/threads/[thread_id]/context-pin/route-36cb8b428b38b26a.js +0 -17
  665. package/.next/standalone/.next/static/chunks/app/api/v1/threads/[thread_id]/route-36cb8b428b38b26a.js +0 -17
  666. package/.next/standalone/.next/static/chunks/app/api/v1/threads/[thread_id]/run/route-36cb8b428b38b26a.js +0 -17
  667. package/.next/standalone/.next/static/chunks/app/api/v1/threads/route-36cb8b428b38b26a.js +0 -17
  668. package/.next/standalone/.next/static/chunks/app/api/v1/tools/route-36cb8b428b38b26a.js +0 -17
  669. package/.next/standalone/.next/static/chunks/app/api/v1/update/apply/route-36cb8b428b38b26a.js +0 -17
  670. package/.next/standalone/.next/static/chunks/app/api/v1/update/route-36cb8b428b38b26a.js +0 -17
  671. package/.next/standalone/.next/static/chunks/app/api/v1/voice/transcribe/route-36cb8b428b38b26a.js +0 -17
  672. package/.next/standalone/.next/static/chunks/app/api/v1/voice/tts/route-36cb8b428b38b26a.js +0 -17
  673. package/.next/standalone/.next/static/chunks/app/api/v1/watchers/[id]/route-36cb8b428b38b26a.js +0 -17
  674. package/.next/standalone/.next/static/chunks/app/api/v1/watchers/[id]/run/route-36cb8b428b38b26a.js +0 -17
  675. package/.next/standalone/.next/static/chunks/app/api/v1/watchers/reaction-scripts/route-36cb8b428b38b26a.js +0 -17
  676. package/.next/standalone/.next/static/chunks/app/api/v1/watchers/route-36cb8b428b38b26a.js +0 -17
  677. package/.next/standalone/.next/static/chunks/app/manifest.webmanifest/route-36cb8b428b38b26a.js +0 -17
  678. package/.next/standalone/.next/static/chunks/next/dist/client/components/builtin/app-error-36cb8b428b38b26a.js +0 -17
  679. package/.next/standalone/.next/static/chunks/next/dist/client/components/builtin/forbidden-36cb8b428b38b26a.js +0 -17
  680. package/.next/standalone/.next/static/chunks/next/dist/client/components/builtin/not-found-36cb8b428b38b26a.js +0 -17
  681. package/.next/standalone/.next/static/chunks/next/dist/client/components/builtin/unauthorized-36cb8b428b38b26a.js +0 -17
  682. /package/.next/standalone/.next/static/{e2NV1wk6mWg3SIeELXevg → bMRK5y3ruT7c3WtBfCQOG}/_buildManifest.js +0 -0
  683. /package/.next/standalone/.next/static/{e2NV1wk6mWg3SIeELXevg → bMRK5y3ruT7c3WtBfCQOG}/_ssgManifest.js +0 -0
@@ -230,85 +230,6 @@ if ((typeof exports.default === 'function' || typeof exports.default === 'object
230
230
  } //# sourceMappingURL=link.js.map
231
231
 
232
232
 
233
- /***/ }),
234
-
235
- /***/ 3067:
236
- /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
237
-
238
- "use strict";
239
- __webpack_require__.r(__webpack_exports__);
240
- /* harmony export */ __webpack_require__.d(__webpack_exports__, {
241
- /* harmony export */ __next_app__: () => (/* binding */ __next_app__),
242
- /* harmony export */ handler: () => (/* binding */ handler),
243
- /* harmony export */ routeModule: () => (/* binding */ routeModule)
244
- /* harmony export */ });
245
- /* harmony import */ var next_dist_server_app_render_module_loading_instrument_module_getter__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(21635);
246
- /* harmony import */ var next_dist_build_templates_app_page_runtime__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(86315);
247
- /* harmony import */ var next_dist_server_app_render_interop_default__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(1020);
248
- /* harmony import */ var next_dist_server_app_render_entry_base__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(61287);
249
- /* harmony import */ var next_dist_server_app_render_entry_base__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(next_dist_server_app_render_entry_base__WEBPACK_IMPORTED_MODULE_3__);
250
- /* harmony reexport (unknown) */ var __WEBPACK_REEXPORT_OBJECT__ = {};
251
- /* harmony reexport (unknown) */ for(const __WEBPACK_IMPORT_KEY__ in next_dist_server_app_render_entry_base__WEBPACK_IMPORTED_MODULE_3__) if(["default","__next_app__","routeModule","handler"].indexOf(__WEBPACK_IMPORT_KEY__) < 0) __WEBPACK_REEXPORT_OBJECT__[__WEBPACK_IMPORT_KEY__] = () => next_dist_server_app_render_entry_base__WEBPACK_IMPORTED_MODULE_3__[__WEBPACK_IMPORT_KEY__]
252
- /* harmony reexport (unknown) */ __webpack_require__.d(__webpack_exports__, __WEBPACK_REEXPORT_OBJECT__);
253
-
254
- const module0 = (0,next_dist_server_app_render_module_loading_instrument_module_getter__WEBPACK_IMPORTED_MODULE_0__/* .instrumentModuleGetter */ .p)(() => Promise.resolve(/* import() eager */).then(__webpack_require__.bind(__webpack_require__, 32056)));
255
- const module1 = (0,next_dist_server_app_render_module_loading_instrument_module_getter__WEBPACK_IMPORTED_MODULE_0__/* .instrumentModuleGetter */ .p)(() => Promise.resolve(/* import() eager */).then(__webpack_require__.t.bind(__webpack_require__, 95547, 23)));
256
- const module2 = (0,next_dist_server_app_render_module_loading_instrument_module_getter__WEBPACK_IMPORTED_MODULE_0__/* .instrumentModuleGetter */ .p)(() => Promise.resolve(/* import() eager */).then(__webpack_require__.t.bind(__webpack_require__, 55091, 23)));
257
- const module3 = (0,next_dist_server_app_render_module_loading_instrument_module_getter__WEBPACK_IMPORTED_MODULE_0__/* .instrumentModuleGetter */ .p)(() => Promise.resolve(/* import() eager */).then(__webpack_require__.t.bind(__webpack_require__, 45270, 23)));
258
- const module4 = (0,next_dist_server_app_render_module_loading_instrument_module_getter__WEBPACK_IMPORTED_MODULE_0__/* .instrumentModuleGetter */ .p)(() => Promise.resolve(/* import() eager */).then(__webpack_require__.t.bind(__webpack_require__, 28193, 23)));
259
- const page5 = (0,next_dist_server_app_render_module_loading_instrument_module_getter__WEBPACK_IMPORTED_MODULE_0__/* .instrumentModuleGetter */ .p)(() => Promise.resolve(/* import() eager */).then(__webpack_require__.bind(__webpack_require__, 99647)));
260
-
261
-
262
- const tree = {
263
- children: [
264
- '',
265
- {
266
- children: ['__PAGE__', {}, {
267
- page: [page5, "/home/runner/work/jarela/jarela/app/page.tsx"],
268
- metadata: {
269
- icon: [(async (props) => (await (0,next_dist_server_app_render_module_loading_instrument_module_getter__WEBPACK_IMPORTED_MODULE_0__/* .instrumentModuleGetter */ .p)(() => Promise.resolve(/* import() eager */).then(__webpack_require__.bind(__webpack_require__, 86364)))()).default(props))],
270
- apple: [],
271
- openGraph: [],
272
- twitter: [],
273
- manifest: "/manifest.webmanifest"
274
- }
275
- }]
276
- },
277
- {
278
- 'layout': [module0, "/home/runner/work/jarela/jarela/app/layout.tsx"],
279
- 'global-error': [module1, "next/dist/client/components/builtin/global-error.js"],
280
- 'not-found': [module2, "next/dist/client/components/builtin/not-found.js"],
281
- 'forbidden': [module3, "next/dist/client/components/builtin/forbidden.js"],
282
- 'unauthorized': [module4, "next/dist/client/components/builtin/unauthorized.js"],
283
- metadata: {
284
- icon: [(async (props) => (await (0,next_dist_server_app_render_module_loading_instrument_module_getter__WEBPACK_IMPORTED_MODULE_0__/* .instrumentModuleGetter */ .p)(() => Promise.resolve(/* import() eager */).then(__webpack_require__.bind(__webpack_require__, 86364)))()).default(props))],
285
- apple: [],
286
- openGraph: [],
287
- twitter: [],
288
- manifest: "/manifest.webmanifest"
289
- }
290
- },
291
- []
292
- ]
293
- }.children;
294
- const __next_app_require__ = __webpack_require__
295
- const __next_app_load_chunk__ = () => Promise.resolve()
296
- const entrypoint = (0,next_dist_build_templates_app_page_runtime__WEBPACK_IMPORTED_MODULE_1__/* .createAppPageEntrypoint */ .H)({
297
- tree,
298
- page: "/page",
299
- pathname: "/",
300
- require: __next_app_require__,
301
- loadChunk: __next_app_load_chunk__,
302
- interopDefault: next_dist_server_app_render_interop_default__WEBPACK_IMPORTED_MODULE_2__/* .interopDefault */ .T
303
- });
304
- const __next_app__ = entrypoint.__next_app__;
305
- const routeModule = entrypoint.routeModule;
306
- const handler = entrypoint.handler;
307
-
308
-
309
- //# sourceMappingURL=app-page.js.map
310
-
311
-
312
233
  /***/ }),
313
234
 
314
235
  /***/ 3295:
@@ -2948,6 +2869,85 @@ module.exports = require("undici");
2948
2869
  "use strict";
2949
2870
  module.exports = require("next/dist/compiled/next-server/app-page.runtime.prod.js");
2950
2871
 
2872
+ /***/ }),
2873
+
2874
+ /***/ 13297:
2875
+ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
2876
+
2877
+ "use strict";
2878
+ __webpack_require__.r(__webpack_exports__);
2879
+ /* harmony export */ __webpack_require__.d(__webpack_exports__, {
2880
+ /* harmony export */ __next_app__: () => (/* binding */ __next_app__),
2881
+ /* harmony export */ handler: () => (/* binding */ handler),
2882
+ /* harmony export */ routeModule: () => (/* binding */ routeModule)
2883
+ /* harmony export */ });
2884
+ /* harmony import */ var next_dist_server_app_render_module_loading_instrument_module_getter__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(21635);
2885
+ /* harmony import */ var next_dist_build_templates_app_page_runtime__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(86315);
2886
+ /* harmony import */ var next_dist_server_app_render_interop_default__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(1020);
2887
+ /* harmony import */ var next_dist_server_app_render_entry_base__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(61287);
2888
+ /* harmony import */ var next_dist_server_app_render_entry_base__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(next_dist_server_app_render_entry_base__WEBPACK_IMPORTED_MODULE_3__);
2889
+ /* harmony reexport (unknown) */ var __WEBPACK_REEXPORT_OBJECT__ = {};
2890
+ /* harmony reexport (unknown) */ for(const __WEBPACK_IMPORT_KEY__ in next_dist_server_app_render_entry_base__WEBPACK_IMPORTED_MODULE_3__) if(["default","__next_app__","routeModule","handler"].indexOf(__WEBPACK_IMPORT_KEY__) < 0) __WEBPACK_REEXPORT_OBJECT__[__WEBPACK_IMPORT_KEY__] = () => next_dist_server_app_render_entry_base__WEBPACK_IMPORTED_MODULE_3__[__WEBPACK_IMPORT_KEY__]
2891
+ /* harmony reexport (unknown) */ __webpack_require__.d(__webpack_exports__, __WEBPACK_REEXPORT_OBJECT__);
2892
+
2893
+ const module0 = (0,next_dist_server_app_render_module_loading_instrument_module_getter__WEBPACK_IMPORTED_MODULE_0__/* .instrumentModuleGetter */ .p)(() => Promise.resolve(/* import() eager */).then(__webpack_require__.bind(__webpack_require__, 32056)));
2894
+ const module1 = (0,next_dist_server_app_render_module_loading_instrument_module_getter__WEBPACK_IMPORTED_MODULE_0__/* .instrumentModuleGetter */ .p)(() => Promise.resolve(/* import() eager */).then(__webpack_require__.t.bind(__webpack_require__, 95547, 23)));
2895
+ const module2 = (0,next_dist_server_app_render_module_loading_instrument_module_getter__WEBPACK_IMPORTED_MODULE_0__/* .instrumentModuleGetter */ .p)(() => Promise.resolve(/* import() eager */).then(__webpack_require__.t.bind(__webpack_require__, 55091, 23)));
2896
+ const module3 = (0,next_dist_server_app_render_module_loading_instrument_module_getter__WEBPACK_IMPORTED_MODULE_0__/* .instrumentModuleGetter */ .p)(() => Promise.resolve(/* import() eager */).then(__webpack_require__.t.bind(__webpack_require__, 45270, 23)));
2897
+ const module4 = (0,next_dist_server_app_render_module_loading_instrument_module_getter__WEBPACK_IMPORTED_MODULE_0__/* .instrumentModuleGetter */ .p)(() => Promise.resolve(/* import() eager */).then(__webpack_require__.t.bind(__webpack_require__, 28193, 23)));
2898
+ const page5 = (0,next_dist_server_app_render_module_loading_instrument_module_getter__WEBPACK_IMPORTED_MODULE_0__/* .instrumentModuleGetter */ .p)(() => Promise.resolve(/* import() eager */).then(__webpack_require__.bind(__webpack_require__, 99647)));
2899
+
2900
+
2901
+ const tree = {
2902
+ children: [
2903
+ '',
2904
+ {
2905
+ children: ['__PAGE__', {}, {
2906
+ page: [page5, "/home/runner/work/jarela/jarela/app/page.tsx"],
2907
+ metadata: {
2908
+ icon: [(async (props) => (await (0,next_dist_server_app_render_module_loading_instrument_module_getter__WEBPACK_IMPORTED_MODULE_0__/* .instrumentModuleGetter */ .p)(() => Promise.resolve(/* import() eager */).then(__webpack_require__.bind(__webpack_require__, 86364)))()).default(props))],
2909
+ apple: [],
2910
+ openGraph: [],
2911
+ twitter: [],
2912
+ manifest: "/manifest.webmanifest"
2913
+ }
2914
+ }]
2915
+ },
2916
+ {
2917
+ 'layout': [module0, "/home/runner/work/jarela/jarela/app/layout.tsx"],
2918
+ 'global-error': [module1, "next/dist/client/components/builtin/global-error.js"],
2919
+ 'not-found': [module2, "next/dist/client/components/builtin/not-found.js"],
2920
+ 'forbidden': [module3, "next/dist/client/components/builtin/forbidden.js"],
2921
+ 'unauthorized': [module4, "next/dist/client/components/builtin/unauthorized.js"],
2922
+ metadata: {
2923
+ icon: [(async (props) => (await (0,next_dist_server_app_render_module_loading_instrument_module_getter__WEBPACK_IMPORTED_MODULE_0__/* .instrumentModuleGetter */ .p)(() => Promise.resolve(/* import() eager */).then(__webpack_require__.bind(__webpack_require__, 86364)))()).default(props))],
2924
+ apple: [],
2925
+ openGraph: [],
2926
+ twitter: [],
2927
+ manifest: "/manifest.webmanifest"
2928
+ }
2929
+ },
2930
+ []
2931
+ ]
2932
+ }.children;
2933
+ const __next_app_require__ = __webpack_require__
2934
+ const __next_app_load_chunk__ = () => Promise.resolve()
2935
+ const entrypoint = (0,next_dist_build_templates_app_page_runtime__WEBPACK_IMPORTED_MODULE_1__/* .createAppPageEntrypoint */ .H)({
2936
+ tree,
2937
+ page: "/page",
2938
+ pathname: "/",
2939
+ require: __next_app_require__,
2940
+ loadChunk: __next_app_load_chunk__,
2941
+ interopDefault: next_dist_server_app_render_interop_default__WEBPACK_IMPORTED_MODULE_2__/* .interopDefault */ .T
2942
+ });
2943
+ const __next_app__ = entrypoint.__next_app__;
2944
+ const routeModule = entrypoint.routeModule;
2945
+ const handler = entrypoint.handler;
2946
+
2947
+
2948
+ //# sourceMappingURL=app-page.js.map
2949
+
2950
+
2951
2951
  /***/ }),
2952
2952
 
2953
2953
  /***/ 14116:
@@ -3042,7 +3042,7 @@ module.exports = require("node:http");
3042
3042
  /***/ 38084:
3043
3043
  /***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {
3044
3044
 
3045
- Promise.resolve(/* import() eager */).then(__webpack_require__.bind(__webpack_require__, 96190));
3045
+ Promise.resolve(/* import() eager */).then(__webpack_require__.bind(__webpack_require__, 90801));
3046
3046
  ;
3047
3047
  Promise.resolve(/* import() eager */).then(__webpack_require__.bind(__webpack_require__, 26751));
3048
3048
 
@@ -3498,15 +3498,7 @@ module.exports = require("http");
3498
3498
 
3499
3499
  /***/ }),
3500
3500
 
3501
- /***/ 94735:
3502
- /***/ ((module) => {
3503
-
3504
- "use strict";
3505
- module.exports = require("events");
3506
-
3507
- /***/ }),
3508
-
3509
- /***/ 96190:
3501
+ /***/ 90801:
3510
3502
  /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
3511
3503
 
3512
3504
  "use strict";
@@ -4256,40 +4248,8 @@ function useUrlSync() {
4256
4248
  };
4257
4249
  }
4258
4250
 
4259
- ;// ./lib/agents/effective-model.ts
4260
- /**
4261
- * Resolve which `ModelConfig` will actually be used for an agent at runtime.
4262
- *
4263
- * Mirrors what `lib/agents/llm.ts` does server-side: when an agent has
4264
- * `model_config_name` set, that wins; otherwise the workspace-wide default
4265
- * model is used. Both client (BridgeEditor, AgentEditor capability hints)
4266
- * and server need the same logic — this is the single source of truth.
4267
- *
4268
- * Returns `null` only when neither the requested config nor the default
4269
- * exists in the provided list (typically: no models configured yet).
4270
- */ function resolveAgentModel(agent, models) {
4271
- const defaultModel = models.find((m)=>m.is_default) ?? models[0] ?? null;
4272
- if (!agent?.model_config_name) return defaultModel;
4273
- return models.find((m)=>m.name === agent.model_config_name) ?? defaultModel;
4274
- }
4275
- /**
4276
- * Diagnose whether an agent has a runnable model RIGHT NOW. Used by the
4277
- * Scheduled Tasks and Watchers panels to surface model-availability issues
4278
- * before an unattended run silently no-ops with `no_model`.
4279
- */ function agentModelStatus(agent, models) {
4280
- if (!agent) return {
4281
- state: "no-agent"
4282
- };
4283
- const effectiveModel = resolveAgentModel(agent, models);
4284
- if (effectiveModel) return {
4285
- state: "ok",
4286
- model: effectiveModel
4287
- };
4288
- return {
4289
- state: "no-model"
4290
- };
4291
- }
4292
-
4251
+ // EXTERNAL MODULE: ./lib/agents/effective-model.ts
4252
+ var effective_model = __webpack_require__(3872);
4293
4253
  ;// ./hooks/useConfigurationIssues.ts
4294
4254
  /* __next_internal_client_entry_do_not_use__ useConfigurationIssues auto */
4295
4255
 
@@ -4345,7 +4305,7 @@ function useUrlSync() {
4345
4305
  pushIssue("no-default-model", "info", "No default model set", "Agents without an explicit model will fail. Pick one default.", "?tab=models", "Open Models →");
4346
4306
  }
4347
4307
  for (const a of agents){
4348
- const status = agentModelStatus(a, models);
4308
+ const status = (0,effective_model/* agentModelStatus */.xu)(a, models);
4349
4309
  if (status.state === "no-model") {
4350
4310
  pushIssue(`agent-no-model:${a.id}`, "error", `Agent "${a.name}" has no model`, "Pick a model or set a workspace default.", `?tab=agents&item=${encodeURIComponent(a.id)}`, "Fix in Agents →");
4351
4311
  }
@@ -4675,6 +4635,26 @@ function useSSE(onDone) {
4675
4635
  // Cleared on every new start()/attach().
4676
4636
  const [authError, setAuthError] = (0,react.useState)(null);
4677
4637
  const abortRef = (0,react.useRef)(null);
4638
+ // Synchronous view of whether start()/attach() owns a live stream, and when
4639
+ // the last one settled. React's `streaming` lags a render behind, so the
4640
+ // activity poller reads this to avoid aborting a stream that just opened
4641
+ // or re-attaching a run whose stream has only just ended.
4642
+ const liveRef = (0,react.useRef)({
4643
+ busy: false,
4644
+ settledAt: 0
4645
+ });
4646
+ const markLive = (0,react.useCallback)(()=>{
4647
+ liveRef.current.busy = true;
4648
+ }, []);
4649
+ const markSettled = (0,react.useCallback)((ctrl)=>{
4650
+ if (ctrl && abortRef.current !== ctrl) return;
4651
+ liveRef.current = {
4652
+ busy: false,
4653
+ settledAt: Date.now()
4654
+ };
4655
+ }, []);
4656
+ const isLive = (0,react.useCallback)(()=>liveRef.current.busy, []);
4657
+ const lastSettledAt = (0,react.useCallback)(()=>liveRef.current.settledAt, []);
4678
4658
  const threadIdRef = (0,react.useRef)(null);
4679
4659
  // ADR-0080 — id of the steering message currently armed for a possible
4680
4660
  // continuation break, or null. Set eagerly (before the steer PATCH
@@ -4836,6 +4816,7 @@ function useSSE(onDone) {
4836
4816
  abortRef.current?.abort();
4837
4817
  const ctrl = new AbortController();
4838
4818
  abortRef.current = ctrl;
4819
+ markLive();
4839
4820
  threadIdRef.current = threadId;
4840
4821
  resetBuffer();
4841
4822
  setStreaming(true);
@@ -4883,10 +4864,13 @@ function useSSE(onDone) {
4883
4864
  // them.
4884
4865
  setStreaming(false);
4885
4866
  closeActivity();
4867
+ markSettled(ctrl);
4886
4868
  }
4887
4869
  }, [
4888
4870
  closeActivity,
4889
4871
  consume,
4872
+ markLive,
4873
+ markSettled,
4890
4874
  openActivity,
4891
4875
  resetBuffer
4892
4876
  ]);
@@ -4911,11 +4895,13 @@ function useSSE(onDone) {
4911
4895
  // start()/attach() — same pattern as the `done` branch in consume().
4912
4896
  closeActivity();
4913
4897
  abortRef.current?.abort();
4898
+ markSettled(null);
4914
4899
  steeredContinuationIdRef.current = null;
4915
4900
  onDone?.();
4916
4901
  }, [
4917
4902
  closeActivity,
4918
4903
  flushPending,
4904
+ markSettled,
4919
4905
  onDone
4920
4906
  ]);
4921
4907
  // Attach to an in-flight run for the given thread (server-side run kept
@@ -4929,6 +4915,7 @@ function useSSE(onDone) {
4929
4915
  abortRef.current?.abort();
4930
4916
  const ctrl = new AbortController();
4931
4917
  abortRef.current = ctrl;
4918
+ markLive();
4932
4919
  threadIdRef.current = threadId;
4933
4920
  resetBuffer();
4934
4921
  setStreaming(true);
@@ -4956,10 +4943,13 @@ function useSSE(onDone) {
4956
4943
  // hangs in the composer and the "Reconnecting…" badge never clears.
4957
4944
  setStreaming(false);
4958
4945
  closeActivity();
4946
+ markSettled(ctrl);
4959
4947
  }
4960
4948
  }, [
4961
4949
  closeActivity,
4962
4950
  consume,
4951
+ markLive,
4952
+ markSettled,
4963
4953
  onDone,
4964
4954
  openActivity,
4965
4955
  resetBuffer
@@ -5004,6 +4994,8 @@ function useSSE(onDone) {
5004
4994
  start,
5005
4995
  stop,
5006
4996
  attach,
4997
+ isLive,
4998
+ lastSettledAt,
5007
4999
  clearStreamingContent,
5008
5000
  clearToolEvents,
5009
5001
  armSteeredContinuation,
@@ -5023,6 +5015,8 @@ function useSSE(onDone) {
5023
5015
  start,
5024
5016
  stop,
5025
5017
  attach,
5018
+ isLive,
5019
+ lastSettledAt,
5026
5020
  clearStreamingContent,
5027
5021
  clearToolEvents,
5028
5022
  armSteeredContinuation,
@@ -5243,6 +5237,8 @@ function readLegacyGlobal() {
5243
5237
  };
5244
5238
  }
5245
5239
 
5240
+ // EXTERNAL MODULE: ./lib/ui/error-report.ts
5241
+ var error_report = __webpack_require__(10778);
5246
5242
  ;// ./node_modules/lucide-react/dist/esm/icons/shield-alert.mjs
5247
5243
  /**
5248
5244
  * @license lucide-react v1.47.0 - ISC
@@ -7342,9 +7338,53 @@ minus_iconData.node;
7342
7338
  const Minus = (0,createLucideIcon/* default */.A)(minus_iconData);
7343
7339
  //# sourceMappingURL=minus.mjs.map
7344
7340
 
7341
+ ;// ./node_modules/lucide-react/dist/esm/icons/rotate-ccw.mjs
7342
+ /**
7343
+ * @license lucide-react v1.47.0 - ISC
7344
+ *
7345
+ * This source code is licensed under the ISC license.
7346
+ * See the LICENSE file in the root directory of this source tree.
7347
+ */
7348
+ const rotate_ccw_iconData = {
7349
+ name: "rotate-ccw",
7350
+ size: 24,
7351
+ node: [
7352
+ [
7353
+ "path",
7354
+ {
7355
+ d: "M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8",
7356
+ key: "1357e3"
7357
+ }
7358
+ ],
7359
+ [
7360
+ "path",
7361
+ {
7362
+ d: "M3 3v5h5",
7363
+ key: "1xhq8a"
7364
+ }
7365
+ ]
7366
+ ]
7367
+ };
7368
+ rotate_ccw_iconData.node;
7369
+ const RotateCcw = (0,createLucideIcon/* default */.A)(rotate_ccw_iconData);
7370
+ //# sourceMappingURL=rotate-ccw.mjs.map
7371
+
7345
7372
  ;// ./components/ui/WorkflowChecklist.tsx
7346
7373
 
7347
7374
 
7375
+ const RETRYABLE_STATUSES = new Set([
7376
+ "done",
7377
+ "needs_attention",
7378
+ "skipped"
7379
+ ]);
7380
+ function isWorkflowItemRetryable(item) {
7381
+ return RETRYABLE_STATUSES.has(item.status);
7382
+ }
7383
+ function statusLabel(status) {
7384
+ if (status === "done") return "verified";
7385
+ if (status === "needs_attention") return "needs attention";
7386
+ return status;
7387
+ }
7348
7388
  function StatusIcon({ status }) {
7349
7389
  if (status === "done") return /*#__PURE__*/ (0,react_jsx_runtime.jsx)(check/* default */.A, {
7350
7390
  className: "h-3 w-3",
@@ -7374,11 +7414,15 @@ function statusClass(status) {
7374
7414
  if (status === "skipped") return "border-border/60 bg-surface text-fg-faint";
7375
7415
  return "border-border/60 bg-surface text-fg-faint";
7376
7416
  }
7377
- function WorkflowChecklist({ eyebrow, title, phaseLabel, summary, items, error, compact = false, children }) {
7417
+ function itemTooltip(item) {
7418
+ const note = item.status === "done" ? item.validation_evidence : item.reason;
7419
+ return note ? `${item.label}\n${statusLabel(item.status)}: ${note}` : item.label;
7420
+ }
7421
+ function WorkflowChecklist({ eyebrow, title, phaseLabel, summary, items, error, compact = false, onRetryItem, canRetryItem, retryDisabled = false, children }) {
7378
7422
  return /*#__PURE__*/ (0,react_jsx_runtime.jsxs)("div", {
7379
7423
  className: compact ? "flex flex-col gap-1.5" : "absolute inset-x-0 top-0 flex flex-col gap-2 transition-opacity duration-300",
7380
7424
  children: [
7381
- /*#__PURE__*/ (0,react_jsx_runtime.jsx)("p", {
7425
+ !compact && /*#__PURE__*/ (0,react_jsx_runtime.jsx)("p", {
7382
7426
  className: "text-[10px] text-fg-faint uppercase tracking-wider text-center",
7383
7427
  children: eyebrow
7384
7428
  }),
@@ -7398,99 +7442,59 @@ function WorkflowChecklist({ eyebrow, title, phaseLabel, summary, items, error,
7398
7442
  })
7399
7443
  ]
7400
7444
  }),
7401
- /*#__PURE__*/ (0,react_jsx_runtime.jsx)("p", {
7445
+ !compact && summary && /*#__PURE__*/ (0,react_jsx_runtime.jsx)("p", {
7402
7446
  className: "mt-1 text-[11px] leading-snug text-fg-muted line-clamp-2",
7403
7447
  children: summary
7404
7448
  }),
7405
- /*#__PURE__*/ (0,react_jsx_runtime.jsx)("div", {
7406
- 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",
7407
- children: items.map((item)=>/*#__PURE__*/ (0,react_jsx_runtime.jsxs)("div", {
7408
- 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",
7449
+ /*#__PURE__*/ (0,react_jsx_runtime.jsx)("ul", {
7450
+ 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",
7451
+ children: items.map((item)=>{
7452
+ const retryable = !!onRetryItem && isWorkflowItemRetryable(item) && (canRetryItem ? canRetryItem(item) : true);
7453
+ return /*#__PURE__*/ (0,react_jsx_runtime.jsxs)("li", {
7454
+ className: "group flex items-center gap-1.5 text-[10px] leading-tight text-fg-muted",
7409
7455
  children: [
7410
- /*#__PURE__*/ (0,react_jsx_runtime.jsxs)("div", {
7411
- className: "flex items-start gap-1.5",
7412
- children: [
7413
- /*#__PURE__*/ (0,react_jsx_runtime.jsx)("span", {
7414
- "aria-label": item.status,
7415
- className: [
7416
- "mt-0.5 flex h-4 w-4 shrink-0 items-center justify-center rounded border",
7417
- statusClass(item.status)
7418
- ].join(" "),
7419
- children: /*#__PURE__*/ (0,react_jsx_runtime.jsx)(StatusIcon, {
7420
- status: item.status
7421
- })
7422
- }),
7423
- /*#__PURE__*/ (0,react_jsx_runtime.jsx)("span", {
7424
- className: compact ? "min-w-0 flex-1 truncate" : "line-clamp-2",
7425
- title: item.label,
7426
- children: item.label
7427
- })
7428
- ]
7456
+ /*#__PURE__*/ (0,react_jsx_runtime.jsx)("span", {
7457
+ role: "img",
7458
+ "aria-label": statusLabel(item.status),
7459
+ className: [
7460
+ "flex h-4 w-4 shrink-0 items-center justify-center rounded border",
7461
+ statusClass(item.status)
7462
+ ].join(" "),
7463
+ children: /*#__PURE__*/ (0,react_jsx_runtime.jsx)(StatusIcon, {
7464
+ status: item.status
7465
+ })
7466
+ }),
7467
+ /*#__PURE__*/ (0,react_jsx_runtime.jsx)("span", {
7468
+ className: compact ? "min-w-0 flex-1 truncate" : "min-w-0 flex-1 line-clamp-2",
7469
+ title: itemTooltip(item),
7470
+ children: item.label
7429
7471
  }),
7430
- (item.input || item.output || item.validation || item.validation_evidence) && /*#__PURE__*/ (0,react_jsx_runtime.jsxs)("details", {
7431
- className: "mt-1 pl-5",
7472
+ (item.attempts ?? 0) > 1 && /*#__PURE__*/ (0,react_jsx_runtime.jsxs)("span", {
7473
+ className: "shrink-0 text-[9px] tabular-nums text-fg-faint",
7474
+ title: `Attempt ${item.attempts}`,
7432
7475
  children: [
7433
- /*#__PURE__*/ (0,react_jsx_runtime.jsx)("summary", {
7434
- className: "cursor-pointer text-fg-faint",
7435
- children: "Step contract"
7436
- }),
7437
- /*#__PURE__*/ (0,react_jsx_runtime.jsxs)("dl", {
7438
- className: "mt-1 grid grid-cols-[auto_minmax(0,1fr)] gap-x-2 gap-y-1",
7439
- children: [
7440
- item.input && /*#__PURE__*/ (0,react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, {
7441
- children: [
7442
- /*#__PURE__*/ (0,react_jsx_runtime.jsx)("dt", {
7443
- className: "text-fg-faint",
7444
- children: "Input"
7445
- }),
7446
- /*#__PURE__*/ (0,react_jsx_runtime.jsx)("dd", {
7447
- className: "break-words",
7448
- children: item.input
7449
- })
7450
- ]
7451
- }),
7452
- item.output && /*#__PURE__*/ (0,react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, {
7453
- children: [
7454
- /*#__PURE__*/ (0,react_jsx_runtime.jsx)("dt", {
7455
- className: "text-fg-faint",
7456
- children: "Output"
7457
- }),
7458
- /*#__PURE__*/ (0,react_jsx_runtime.jsx)("dd", {
7459
- className: "break-words",
7460
- children: item.output
7461
- })
7462
- ]
7463
- }),
7464
- item.validation && /*#__PURE__*/ (0,react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, {
7465
- children: [
7466
- /*#__PURE__*/ (0,react_jsx_runtime.jsx)("dt", {
7467
- className: "text-fg-faint",
7468
- children: "Validation"
7469
- }),
7470
- /*#__PURE__*/ (0,react_jsx_runtime.jsx)("dd", {
7471
- className: "break-words",
7472
- children: item.validation
7473
- })
7474
- ]
7475
- }),
7476
- item.validation_evidence && /*#__PURE__*/ (0,react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, {
7477
- children: [
7478
- /*#__PURE__*/ (0,react_jsx_runtime.jsx)("dt", {
7479
- className: "text-fg-faint",
7480
- children: "Evidence"
7481
- }),
7482
- /*#__PURE__*/ (0,react_jsx_runtime.jsx)("dd", {
7483
- className: "break-words",
7484
- children: item.validation_evidence
7485
- })
7486
- ]
7487
- })
7488
- ]
7489
- })
7476
+ "attempt ",
7477
+ item.attempts
7490
7478
  ]
7479
+ }),
7480
+ retryable && /*#__PURE__*/ (0,react_jsx_runtime.jsx)("button", {
7481
+ type: "button",
7482
+ onClick: ()=>onRetryItem(item),
7483
+ disabled: retryDisabled,
7484
+ "aria-label": `Retry ${item.label}`,
7485
+ title: `Retry ${item.label}`,
7486
+ className: [
7487
+ "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",
7488
+ item.status === "needs_attention" ? "" : "opacity-0 focus:opacity-100 group-hover:opacity-100"
7489
+ ].join(" "),
7490
+ children: /*#__PURE__*/ (0,react_jsx_runtime.jsx)(RotateCcw, {
7491
+ className: "h-3 w-3",
7492
+ "aria-hidden": true
7493
+ })
7491
7494
  })
7492
7495
  ]
7493
- }, item.id))
7496
+ }, item.id);
7497
+ })
7494
7498
  }),
7495
7499
  error && /*#__PURE__*/ (0,react_jsx_runtime.jsx)("p", {
7496
7500
  className: "mt-2 text-[10px] leading-tight text-red-400",
@@ -7503,6 +7507,21 @@ function WorkflowChecklist({ eyebrow, title, phaseLabel, summary, items, error,
7503
7507
  });
7504
7508
  }
7505
7509
 
7510
+ ;// ./components/chat/workflow-step-retry.ts
7511
+
7512
+ /** Sends a retry request for one workflow step; null when the surface cannot send messages. */ const WorkflowStepRetryContext = (0,react.createContext)(null);
7513
+ function useWorkflowStepRetry() {
7514
+ return (0,react.useContext)(WorkflowStepRetryContext);
7515
+ }
7516
+ function workflowStepRetryMessage({ workflowId, itemId, label }) {
7517
+ 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\``;
7518
+ return [
7519
+ `Retry workflow step "${label}" (item \`${itemId}\`) in workflow \`${workflowId}\`.`,
7520
+ `${progressUpdate}, then redo the step from its stated input and run its validation again.`,
7521
+ "Finally mark it `done` with newly observed `validation_evidence`, or `needs_attention` with the reason. Leave the other steps unchanged."
7522
+ ].join(" ");
7523
+ }
7524
+
7506
7525
  ;// ./node_modules/lucide-react/dist/esm/icons/clock.mjs
7507
7526
  /**
7508
7527
  * @license lucide-react v1.47.0 - ISC
@@ -7744,6 +7763,7 @@ var ProviderLogo = __webpack_require__(17838);
7744
7763
 
7745
7764
 
7746
7765
 
7766
+
7747
7767
  // Distinct lucide glyph per internal tool family so the chat transcript
7748
7768
  // is glanceable — operator can tell a file write from a web fetch from a
7749
7769
  // schedule from a memory read without reading the tool name.
@@ -8181,7 +8201,34 @@ function groupByCallId(events) {
8181
8201
  }
8182
8202
  g.absorbed = true;
8183
8203
  }
8184
- return order.map((id)=>map.get(id)).filter((g)=>!g.absorbed);
8204
+ const groups = order.map((id)=>map.get(id)).filter((g)=>!g.absorbed);
8205
+ annotateWorkflowAttempts(groups);
8206
+ return groups;
8207
+ }
8208
+ // Counts each workflow step's transitions into `checking` across the
8209
+ // message's workflow_progress calls, so auto-retried steps show "attempt N".
8210
+ // Rejected updates (ok:false) changed nothing and are not counted.
8211
+ function annotateWorkflowAttempts(groups) {
8212
+ const lastStatus = new Map();
8213
+ const attempts = new Map();
8214
+ for (const group of groups){
8215
+ if (group.name !== "workflow_progress") continue;
8216
+ if (coerceObject(unwrapLangChainSerializable(group.result))?.ok === false) continue;
8217
+ const view = workflowViewFor(group);
8218
+ if (!view) continue;
8219
+ const counts = {
8220
+ ...attempts.get(view.workflow_id) ?? {}
8221
+ };
8222
+ for (const item of view.items){
8223
+ const key = `${view.workflow_id}:${item.id}`;
8224
+ if (item.status === "checking" && lastStatus.get(key) !== "checking") {
8225
+ counts[item.id] = (counts[item.id] ?? 0) + 1;
8226
+ }
8227
+ lastStatus.set(key, item.status);
8228
+ }
8229
+ attempts.set(view.workflow_id, counts);
8230
+ group.workflowAttempts = counts;
8231
+ }
8185
8232
  }
8186
8233
  function ToolCallCard({ group, startedAt }) {
8187
8234
  const [open, setOpen] = (0,react.useState)(false);
@@ -8294,23 +8341,27 @@ function ToolCallCard({ group, startedAt }) {
8294
8341
  /*#__PURE__*/ (0,react_jsx_runtime.jsx)(WorkflowProgressDetails, {
8295
8342
  group: group
8296
8343
  }),
8297
- hasVisibleArgs(group.args) ? /*#__PURE__*/ (0,react_jsx_runtime.jsx)(DetailSection, {
8298
- label: "arguments",
8299
- value: group.args
8300
- }) : hasArgs ? /*#__PURE__*/ (0,react_jsx_runtime.jsx)(DetailSection, {
8301
- label: "arguments (inferred from result)",
8302
- value: effectiveArgs
8303
- }) : null,
8304
- group.status !== "running" && group.status !== "async" && (isToolResultRefEnvelope(group.result) ? /*#__PURE__*/ (0,react_jsx_runtime.jsx)(ToolResultRefDetails, {
8305
- value: group.result
8306
- }) : /*#__PURE__*/ (0,react_jsx_runtime.jsx)(DetailSection, {
8307
- label: group.status === "error" ? "error" : "result",
8308
- value: group.result,
8309
- tone: group.status === "error" ? "error" : "default"
8310
- })),
8311
- group.status === "async" && /*#__PURE__*/ (0,react_jsx_runtime.jsx)(DetailSection, {
8312
- label: "background handoff",
8313
- value: group.result
8344
+ !hasWorkflowView(group) && /*#__PURE__*/ (0,react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, {
8345
+ children: [
8346
+ hasVisibleArgs(group.args) ? /*#__PURE__*/ (0,react_jsx_runtime.jsx)(DetailSection, {
8347
+ label: "arguments",
8348
+ value: group.args
8349
+ }) : hasArgs ? /*#__PURE__*/ (0,react_jsx_runtime.jsx)(DetailSection, {
8350
+ label: "arguments (inferred from result)",
8351
+ value: effectiveArgs
8352
+ }) : null,
8353
+ group.status !== "running" && group.status !== "async" && (isToolResultRefEnvelope(group.result) ? /*#__PURE__*/ (0,react_jsx_runtime.jsx)(ToolResultRefDetails, {
8354
+ value: group.result
8355
+ }) : /*#__PURE__*/ (0,react_jsx_runtime.jsx)(DetailSection, {
8356
+ label: group.status === "error" ? "error" : "result",
8357
+ value: group.result,
8358
+ tone: group.status === "error" ? "error" : "default"
8359
+ })),
8360
+ group.status === "async" && /*#__PURE__*/ (0,react_jsx_runtime.jsx)(DetailSection, {
8361
+ label: "background handoff",
8362
+ value: group.result
8363
+ })
8364
+ ]
8314
8365
  })
8315
8366
  ]
8316
8367
  })
@@ -8445,18 +8496,47 @@ function ToolResultRefDetails({ value }) {
8445
8496
  ]
8446
8497
  });
8447
8498
  }
8448
- function WorkflowProgressDetails({ group }) {
8499
+ function workflowViewFor(group) {
8449
8500
  if (group.name !== "workflow_progress") return null;
8450
- const workflow = workflowProgressFrom(group.result) ?? workflowProgressPreviewFrom(group.args);
8501
+ const view = workflowProgressFrom(group.result) ?? workflowProgressPreviewFrom(group.args);
8502
+ const result = coerceObject(unwrapLangChainSerializable(group.result));
8503
+ const attempts = group.workflowAttempts;
8504
+ const withAttempts = view && attempts ? {
8505
+ ...view,
8506
+ items: view.items.map((item)=>attempts[item.id] ? {
8507
+ ...item,
8508
+ attempts: attempts[item.id]
8509
+ } : item)
8510
+ } : view;
8511
+ if (withAttempts && result?.ok === false && typeof result.error === "string") {
8512
+ return {
8513
+ ...withAttempts,
8514
+ error: `Update rejected: ${result.error}`
8515
+ };
8516
+ }
8517
+ return withAttempts;
8518
+ }
8519
+ /** Workflow rows show only their work items; raw payloads stay visible when the call failed. */ function hasWorkflowView(group) {
8520
+ return group.status !== "error" && workflowViewFor(group) !== null;
8521
+ }
8522
+ function WorkflowProgressDetails({ group }) {
8523
+ const retryStep = useWorkflowStepRetry();
8524
+ const workflow = workflowViewFor(group);
8451
8525
  if (!workflow) return null;
8526
+ const workflowId = workflow.workflow_id;
8452
8527
  return /*#__PURE__*/ (0,react_jsx_runtime.jsx)(WorkflowChecklist, {
8453
8528
  compact: true,
8454
8529
  eyebrow: "workflow",
8455
- title: workflow.workflow_id.replace(/[_-]/g, " "),
8530
+ title: workflowId.replace(/[_-]/g, " "),
8456
8531
  phaseLabel: workflow.phase ?? "in progress",
8457
8532
  summary: workflow.summary ?? "",
8458
8533
  items: workflow.items,
8459
- error: workflow.error
8534
+ error: workflow.error,
8535
+ onRetryItem: retryStep ? (item)=>retryStep({
8536
+ workflowId,
8537
+ itemId: item.id,
8538
+ label: item.label
8539
+ }) : undefined
8460
8540
  });
8461
8541
  }
8462
8542
  function workflowProgressFrom(payload) {
@@ -37650,37 +37730,6 @@ link_2_iconData.node;
37650
37730
  const Link2 = (0,createLucideIcon/* default */.A)(link_2_iconData);
37651
37731
  //# sourceMappingURL=link-2.mjs.map
37652
37732
 
37653
- ;// ./node_modules/lucide-react/dist/esm/icons/rotate-ccw.mjs
37654
- /**
37655
- * @license lucide-react v1.47.0 - ISC
37656
- *
37657
- * This source code is licensed under the ISC license.
37658
- * See the LICENSE file in the root directory of this source tree.
37659
- */
37660
- const rotate_ccw_iconData = {
37661
- name: "rotate-ccw",
37662
- size: 24,
37663
- node: [
37664
- [
37665
- "path",
37666
- {
37667
- d: "M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8",
37668
- key: "1357e3"
37669
- }
37670
- ],
37671
- [
37672
- "path",
37673
- {
37674
- d: "M3 3v5h5",
37675
- key: "1xhq8a"
37676
- }
37677
- ]
37678
- ]
37679
- };
37680
- rotate_ccw_iconData.node;
37681
- const RotateCcw = (0,createLucideIcon/* default */.A)(rotate_ccw_iconData);
37682
- //# sourceMappingURL=rotate-ccw.mjs.map
37683
-
37684
37733
  ;// ./node_modules/lucide-react/dist/esm/icons/pause.mjs
37685
37734
  /**
37686
37735
  * @license lucide-react v1.47.0 - ISC
@@ -50759,7 +50808,7 @@ function StatusDot({ tone = "neutral", size = "xs", pulse, className, style, lab
50759
50808
  }
50760
50809
 
50761
50810
  ;// ./components/chat/ContextBoundary.tsx
50762
- /* __next_internal_client_entry_do_not_use__ WarmSummaryCard,ContextBoundaryDivider auto */
50811
+ /* __next_internal_client_entry_do_not_use__ WarmSummaryCard,ContextBoundaryDivider,topicsFromSummarySections auto */
50763
50812
  // Inline visual artefacts for ADR-0042: the warm-summary card and the
50764
50813
  // context-boundary divider that sits below it. Rendered by MessageList in
50765
50814
  // the message stream — between summarised history (above) and the active
@@ -50771,17 +50820,25 @@ function StatusDot({ tone = "neutral", size = "xs", pulse, className, style, lab
50771
50820
 
50772
50821
 
50773
50822
 
50774
- function WarmSummaryCard({ olderCount, summary, summaryBeforeSeq, hotSinceSeq, computedAt, streaming, topics }) {
50823
+ const CHANNEL_LABELS = {
50824
+ bridge: "Bridge",
50825
+ watcher: "Watchers",
50826
+ scheduled_task: "Scheduled tasks"
50827
+ };
50828
+ function WarmSummaryCard({ olderCount, summary, summaryBeforeSeq, hotSinceSeq, computedAt, streaming, topics, channelSummaries = [] }) {
50775
50829
  const [expanded, setExpanded] = (0,react.useState)(false);
50776
- const fresh = !!summary && hotSinceSeq != null && summaryBeforeSeq === hotSinceSeq;
50830
+ const committed = hotSinceSeq != null && summaryBeforeSeq === hotSinceSeq;
50831
+ const fresh = !!summary && committed;
50777
50832
  const stale = !!summary && !fresh;
50778
50833
  const computing = stale && streaming;
50779
- const summaryTopics = summary && topics && topics.length > 0 ? topics : null;
50834
+ // Summaries stored before topic segmentation still read as topics: their
50835
+ // markdown sections render through the same collapsible rows.
50836
+ const summaryTopics = summary ? topics && topics.length > 0 ? topics : topicsFromSummarySections(summary) : null;
50780
50837
  return /*#__PURE__*/ (0,react_jsx_runtime.jsxs)("div", {
50781
50838
  className: [
50782
50839
  "relative my-4 rounded-2xl border bg-gradient-to-br shadow-sm",
50783
50840
  "from-accent/[0.06] via-surface-2 to-surface-2",
50784
- fresh ? "border-accent/30" : "border-border"
50841
+ fresh || committed ? "border-accent/30" : "border-border"
50785
50842
  ].join(" "),
50786
50843
  children: [
50787
50844
  /*#__PURE__*/ (0,react_jsx_runtime.jsxs)("div", {
@@ -50826,6 +50883,9 @@ function WarmSummaryCard({ olderCount, summary, summaryBeforeSeq, hotSinceSeq, c
50826
50883
  children: /*#__PURE__*/ (0,react_jsx_runtime.jsx)(lib/* Markdown */.oz, {
50827
50884
  children: stripWarmHeader(summary)
50828
50885
  })
50886
+ }) : !summary && committed ? channelSummaries.length === 0 && /*#__PURE__*/ (0,react_jsx_runtime.jsx)("div", {
50887
+ className: "text-xs text-fg-faint italic",
50888
+ children: "No earlier chat messages needed summarising."
50829
50889
  }) : !summary ? /*#__PURE__*/ (0,react_jsx_runtime.jsxs)("div", {
50830
50890
  className: "flex items-center gap-2 text-xs text-fg-faint italic",
50831
50891
  children: [
@@ -50839,6 +50899,9 @@ function WarmSummaryCard({ olderCount, summary, summaryBeforeSeq, hotSinceSeq, c
50839
50899
  })
50840
50900
  ]
50841
50901
  }) : null,
50902
+ channelSummaries.map((channel)=>/*#__PURE__*/ (0,react_jsx_runtime.jsx)(ChannelSummarySection, {
50903
+ channel: channel
50904
+ }, channel.channel)),
50842
50905
  stale && /*#__PURE__*/ (0,react_jsx_runtime.jsxs)("div", {
50843
50906
  className: "mt-2 inline-flex items-center gap-2 text-[11px] text-fg-faint",
50844
50907
  children: [
@@ -50880,6 +50943,32 @@ function WarmSummaryCard({ olderCount, summary, summaryBeforeSeq, hotSinceSeq, c
50880
50943
  ]
50881
50944
  });
50882
50945
  }
50946
+ function ChannelSummarySection({ channel }) {
50947
+ const topics = channel.topics && channel.topics.length > 0 ? channel.topics : topicsFromSummarySections(channel.summary) ?? [
50948
+ {
50949
+ title: "Recap",
50950
+ start_at: "",
50951
+ end_at: "",
50952
+ recap: stripWarmHeader(channel.summary),
50953
+ facts: []
50954
+ }
50955
+ ];
50956
+ return /*#__PURE__*/ (0,react_jsx_runtime.jsxs)("div", {
50957
+ className: "mt-2",
50958
+ children: [
50959
+ /*#__PURE__*/ (0,react_jsx_runtime.jsx)("div", {
50960
+ className: "mb-1 text-[9px] uppercase tracking-wide text-fg-faint",
50961
+ children: CHANNEL_LABELS[channel.channel] ?? channel.channel
50962
+ }),
50963
+ /*#__PURE__*/ (0,react_jsx_runtime.jsx)("div", {
50964
+ className: "flex flex-col gap-1",
50965
+ children: topics.map((topic, i)=>/*#__PURE__*/ (0,react_jsx_runtime.jsx)(TopicSegmentRow, {
50966
+ topic: topic
50967
+ }, `${channel.channel}-${topic.title}-${i}`))
50968
+ })
50969
+ ]
50970
+ });
50971
+ }
50883
50972
  function TopicSegmentRow({ topic }) {
50884
50973
  const [open, setOpen] = (0,react.useState)(false);
50885
50974
  const range = formatTopicRange(topic.start_at, topic.end_at);
@@ -50907,13 +50996,20 @@ function TopicSegmentRow({ topic }) {
50907
50996
  range
50908
50997
  ]
50909
50998
  }),
50999
+ typeof topic.message_count === "number" && topic.message_count > 0 && /*#__PURE__*/ (0,react_jsx_runtime.jsxs)("span", {
51000
+ className: "text-fg-faint shrink-0",
51001
+ children: [
51002
+ "\xb7 ",
51003
+ topic.message_count,
51004
+ " ",
51005
+ topic.message_count === 1 ? "msg" : "msgs"
51006
+ ]
51007
+ }),
50910
51008
  topic.facts.length > 0 && /*#__PURE__*/ (0,react_jsx_runtime.jsxs)("span", {
50911
51009
  className: "ml-auto shrink-0 text-[9px] uppercase tracking-wide text-accent",
50912
51010
  children: [
50913
51011
  topic.facts.length,
50914
- " ",
50915
- topic.facts.length === 1 ? "fact" : "facts",
50916
- " saved"
51012
+ " memorized"
50917
51013
  ]
50918
51014
  })
50919
51015
  ]
@@ -50933,22 +51029,34 @@ function TopicSegmentRow({ topic }) {
50933
51029
  children: topic.recap
50934
51030
  })
50935
51031
  }),
50936
- topic.facts.length > 0 && /*#__PURE__*/ (0,react_jsx_runtime.jsx)("ul", {
50937
- className: "space-y-0.5",
50938
- children: topic.facts.map((fact, i)=>/*#__PURE__*/ (0,react_jsx_runtime.jsxs)("li", {
50939
- className: "text-[11px] text-fg-faint",
50940
- children: [
50941
- /*#__PURE__*/ (0,react_jsx_runtime.jsxs)("span", {
50942
- className: "font-medium text-fg-muted",
51032
+ topic.facts.length > 0 && /*#__PURE__*/ (0,react_jsx_runtime.jsxs)("div", {
51033
+ children: [
51034
+ /*#__PURE__*/ (0,react_jsx_runtime.jsx)("div", {
51035
+ className: "text-[9px] uppercase tracking-wide text-fg-faint",
51036
+ children: "Memorized"
51037
+ }),
51038
+ /*#__PURE__*/ (0,react_jsx_runtime.jsx)("ul", {
51039
+ className: "space-y-0.5",
51040
+ children: topic.facts.map((fact, i)=>/*#__PURE__*/ (0,react_jsx_runtime.jsxs)("li", {
51041
+ className: "text-[11px] text-fg-faint",
50943
51042
  children: [
50944
- fact.subject,
50945
- ":"
51043
+ /*#__PURE__*/ (0,react_jsx_runtime.jsxs)("span", {
51044
+ className: "font-medium text-fg-muted",
51045
+ children: [
51046
+ fact.subject,
51047
+ ":"
51048
+ ]
51049
+ }),
51050
+ " ",
51051
+ fact.content,
51052
+ fact.key && /*#__PURE__*/ (0,react_jsx_runtime.jsx)("code", {
51053
+ className: "ml-1 text-[10px] text-fg-faint",
51054
+ children: fact.key
51055
+ })
50946
51056
  ]
50947
- }),
50948
- " ",
50949
- fact.content
50950
- ]
50951
- }, `${fact.subject}-${i}`))
51057
+ }, `${fact.key ?? fact.subject}-${i}`))
51058
+ })
51059
+ ]
50952
51060
  })
50953
51061
  ]
50954
51062
  })
@@ -51081,7 +51189,38 @@ function ContextBoundary_formatBytes(n) {
51081
51189
  // `buildWarmSummary` prepends a couple of plain-text header lines that read
51082
51190
  // awkwardly inside a card that already has its own header. Strip them.
51083
51191
  function stripWarmHeader(raw) {
51084
- return raw.replace(/^--- Warm context summary ---\n/, "").replace(/^Compressed recap of earlier messages outside the hot window:\n/, "").trimStart();
51192
+ return raw.replace(/\r\n/g, "\n").replace(/^\s*(<!--[\s\S]*?-->\s*)+/, "").replace(/^--- Warm context summary ---\n/, "").replace(/^Compressed recap of [^\n]*:\n/, "").trimStart();
51193
+ }
51194
+ /**
51195
+ * Splits a markdown summary into topic segments at its headings. Returns
51196
+ * null when there are fewer than two sections, so short or unstructured
51197
+ * summaries keep the plain prose rendering.
51198
+ */ function topicsFromSummarySections(raw) {
51199
+ const sections = [];
51200
+ let title = null;
51201
+ let body = [];
51202
+ const flush = ()=>{
51203
+ const recap = body.join("\n").trim();
51204
+ if (title !== null || recap) sections.push({
51205
+ title: title ?? "Overview",
51206
+ start_at: "",
51207
+ end_at: "",
51208
+ recap,
51209
+ facts: []
51210
+ });
51211
+ };
51212
+ for (const line of stripWarmHeader(raw).split("\n")){
51213
+ const heading = /^#{1,3}\s+(.+?)\s*#*\s*$/.exec(line);
51214
+ if (heading) {
51215
+ flush();
51216
+ title = heading[1];
51217
+ body = [];
51218
+ } else {
51219
+ body.push(line);
51220
+ }
51221
+ }
51222
+ flush();
51223
+ return sections.length >= 2 ? sections : null;
51085
51224
  }
51086
51225
  function summaryLong(raw) {
51087
51226
  // Heuristic: more than 6 lines or > 600 chars after the header strip.
@@ -51114,11 +51253,13 @@ function formatRelative(iso) {
51114
51253
 
51115
51254
 
51116
51255
 
51256
+
51117
51257
  const ALL_FILTERS_SHOWN = Object.fromEntries(MESSAGE_FILTER_KEYS.map((k)=>[
51118
51258
  k,
51119
51259
  true
51120
51260
  ]));
51121
- 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 = ()=>{} }) {
51261
+ const NO_CHANNEL_SUMMARIES = [];
51262
+ 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 = ()=>{} }) {
51122
51263
  const hostRef = (0,react.useRef)(null);
51123
51264
  const maskRegionRef = (0,react.useRef)(null);
51124
51265
  const scrollRef = (0,react.useRef)(null);
@@ -51143,6 +51284,9 @@ function MessageList({ threadId, messages, steeredSegments, notices, agentConfig
51143
51284
  const [pendingHotSinceSeq, setPendingHotSinceSeq] = (0,react.useState)(null);
51144
51285
  const [topControlsOpen, setTopControlsOpen] = (0,react.useState)(false);
51145
51286
  const [summaryPopoverOpen, setSummaryPopoverOpen] = (0,react.useState)(false);
51287
+ const retryWorkflowStep = (0,react.useMemo)(()=>onRetryMessage ? (request)=>onRetryMessage(workflowStepRetryMessage(request), []) : null, [
51288
+ onRetryMessage
51289
+ ]);
51146
51290
  // Apply category filter. Messages with no `category` (NULL = ordinary
51147
51291
  // chat) are always shown; tagged messages are gated by their toggle.
51148
51292
  // The `tool_use` and `thinking` filters do NOT remove whole messages —
@@ -51512,7 +51656,11 @@ function MessageList({ threadId, messages, steeredSegments, notices, agentConfig
51512
51656
  const nextHotCount = pendingBoundaryIndex < 0 ? null : visibleMessages.length - pendingBoundaryIndex;
51513
51657
  const removesFromRecent = currentHotCount !== null && nextHotCount !== null ? nextHotCount < currentHotCount : false;
51514
51658
  const hasWarmSummary = !!warmSummary;
51659
+ // A committed boundary whose chat range had nothing to summarise (e.g. a
51660
+ // bridge-only agent): the recap, if any, lives in the channel summaries.
51661
+ const summaryCommittedEmpty = !hasWarmSummary && effectiveHotSinceSeq !== null && warmSummaryBeforeSeq === effectiveHotSinceSeq;
51515
51662
  const summaryFresh = hasWarmSummary && effectiveHotSinceSeq !== null && warmSummaryBeforeSeq === effectiveHotSinceSeq;
51663
+ const summaryReady = summaryFresh || summaryCommittedEmpty;
51516
51664
  const summaryUpdating = hasWarmSummary && !summaryFresh && !!streaming;
51517
51665
  const summaryStale = hasWarmSummary && !summaryFresh && !summaryUpdating;
51518
51666
  process.env.__NEXT_PRIVATE_MINIMIZE_MACRO_FALSE && (0,react.useEffect)(()=>{
@@ -51613,10 +51761,29 @@ function MessageList({ threadId, messages, steeredSegments, notices, agentConfig
51613
51761
  }
51614
51762
  boundaryAnchorRef.current = null;
51615
51763
  }, []);
51764
+ // While a programmatic smooth scroll (locate boundary, deep link) animates
51765
+ // away from the bottom, its first frames are still "near bottom". Without
51766
+ // this lock, scroll sync re-arms bottom-follow and the post-render snap
51767
+ // cancels the animation, so the target is never reached.
51768
+ const programmaticScrollUntilRef = (0,react.useRef)(0);
51616
51769
  const syncScrollButton = (0,react.useCallback)((el)=>{
51617
51770
  const isAtBottom = el.scrollHeight - el.scrollTop - el.clientHeight < 100;
51618
- atBottomRef.current = isAtBottom;
51619
- setShowScrollButton(!isAtBottom && hasScrollTarget);
51771
+ const locked = Date.now() < programmaticScrollUntilRef.current;
51772
+ atBottomRef.current = isAtBottom && !locked;
51773
+ setShowScrollButton(!atBottomRef.current && hasScrollTarget);
51774
+ }, [
51775
+ hasScrollTarget
51776
+ ]);
51777
+ const scrollTargetIntoView = (0,react.useCallback)((target)=>{
51778
+ programmaticScrollUntilRef.current = Date.now() + PROGRAMMATIC_SCROLL_LOCK_MS;
51779
+ atBottomRef.current = false;
51780
+ setShowScrollButton(hasScrollTarget);
51781
+ target.scrollIntoView({
51782
+ behavior: "smooth",
51783
+ block: "center"
51784
+ });
51785
+ target.classList.add("jarela-deep-link-flash");
51786
+ window.setTimeout(()=>target.classList.remove("jarela-deep-link-flash"), 1600);
51620
51787
  }, [
51621
51788
  hasScrollTarget
51622
51789
  ]);
@@ -51745,14 +51912,7 @@ function MessageList({ threadId, messages, steeredSegments, notices, agentConfig
51745
51912
  const safe = id.replace(/"/g, '\\"');
51746
51913
  const el = root.querySelector(`[data-message-id="${safe}"]`);
51747
51914
  if (!el) return;
51748
- atBottomRef.current = false;
51749
- setShowScrollButton(hasScrollTarget);
51750
- el.scrollIntoView({
51751
- behavior: "smooth",
51752
- block: "center"
51753
- });
51754
- el.classList.add("jarela-deep-link-flash");
51755
- setTimeout(()=>el.classList.remove("jarela-deep-link-flash"), 1600);
51915
+ scrollTargetIntoView(el);
51756
51916
  // Strip the hash so the next streaming message / list-length change
51757
51917
  // doesn't yank the view back to this anchor. replaceState avoids
51758
51918
  // triggering a hashchange event (which would re-enter this handler).
@@ -51765,7 +51925,7 @@ function MessageList({ threadId, messages, steeredSegments, notices, agentConfig
51765
51925
  return ()=>window.removeEventListener("hashchange", scrollToHashTarget);
51766
51926
  }, [
51767
51927
  messages.length,
51768
- hasScrollTarget
51928
+ scrollTargetIntoView
51769
51929
  ]);
51770
51930
  // Handle orientation changes and resizes to maintain scroll position
51771
51931
  process.env.__NEXT_PRIVATE_MINIMIZE_MACRO_FALSE && (0,react.useEffect)(()=>{
@@ -51796,419 +51956,411 @@ function MessageList({ threadId, messages, steeredSegments, notices, agentConfig
51796
51956
  if (!root) return;
51797
51957
  const boundary = effectiveHotSinceSeq !== null ? document.getElementById(`context-boundary-${effectiveHotSinceSeq}`) : root.querySelector("[data-focus-boundary='1']");
51798
51958
  if (!boundary) return;
51799
- atBottomRef.current = false;
51800
- setShowScrollButton(hasScrollTarget);
51801
- boundary.scrollIntoView({
51802
- behavior: "smooth",
51803
- block: "center"
51804
- });
51959
+ scrollTargetIntoView(boundary);
51805
51960
  }
51806
- return /*#__PURE__*/ (0,react_jsx_runtime.jsxs)("div", {
51807
- ref: hostRef,
51808
- className: "flex-1 flex flex-col min-h-0 relative",
51809
- children: [
51810
- visibleMessages.length > 0 && /*#__PURE__*/ (0,react_jsx_runtime.jsx)("div", {
51811
- className: "shrink-0 px-4 pt-[calc(var(--app-safe-top)+3rem)] pb-1",
51812
- children: /*#__PURE__*/ (0,react_jsx_runtime.jsxs)("div", {
51813
- className: "w-full border-b border-border/45 bg-surface/30 px-2 py-1 backdrop-blur-sm",
51961
+ return /*#__PURE__*/ (0,react_jsx_runtime.jsx)(WorkflowStepRetryContext.Provider, {
51962
+ value: retryWorkflowStep,
51963
+ children: /*#__PURE__*/ (0,react_jsx_runtime.jsxs)("div", {
51964
+ ref: hostRef,
51965
+ className: "flex-1 flex flex-col min-h-0 relative",
51966
+ children: [
51967
+ visibleMessages.length > 0 && /*#__PURE__*/ (0,react_jsx_runtime.jsx)("div", {
51968
+ className: "shrink-0 px-4 pt-[calc(var(--app-safe-top)+3rem)] pb-1",
51969
+ children: /*#__PURE__*/ (0,react_jsx_runtime.jsxs)("div", {
51970
+ className: "w-full border-b border-border/45 bg-surface/30 px-2 py-1 backdrop-blur-sm",
51971
+ children: [
51972
+ /*#__PURE__*/ (0,react_jsx_runtime.jsxs)("button", {
51973
+ type: "button",
51974
+ onClick: ()=>setTopControlsOpen((v)=>!v),
51975
+ "aria-expanded": topControlsOpen,
51976
+ className: "w-full flex items-center gap-2 py-0.5 text-[11px] text-fg-faint hover:text-fg transition-colors",
51977
+ children: [
51978
+ /*#__PURE__*/ (0,react_jsx_runtime.jsx)(CollapseChevron, {
51979
+ open: topControlsOpen,
51980
+ size: 10
51981
+ }),
51982
+ /*#__PURE__*/ (0,react_jsx_runtime.jsx)("span", {
51983
+ className: "font-semibold uppercase tracking-[0.16em]",
51984
+ children: "Filters & focus"
51985
+ }),
51986
+ hiddenCount > 0 && /*#__PURE__*/ (0,react_jsx_runtime.jsxs)("span", {
51987
+ className: "ml-auto text-[10px] text-fg-faint",
51988
+ "aria-live": "polite",
51989
+ children: [
51990
+ hiddenCount,
51991
+ " hidden"
51992
+ ]
51993
+ })
51994
+ ]
51995
+ }),
51996
+ topControlsOpen && /*#__PURE__*/ (0,react_jsx_runtime.jsxs)("div", {
51997
+ className: "mt-1 flex items-center gap-1.5 flex-wrap py-1",
51998
+ children: [
51999
+ availableChips.map((key)=>{
52000
+ const on = filters[key];
52001
+ const Icon = on ? eye/* default */.A : EyeOff;
52002
+ return /*#__PURE__*/ (0,react_jsx_runtime.jsxs)("button", {
52003
+ type: "button",
52004
+ onClick: ()=>toggle(key),
52005
+ className: [
52006
+ "inline-flex items-center gap-1 rounded-none border px-2 py-0.5 text-[10px] leading-4 transition-colors",
52007
+ 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"
52008
+ ].join(" "),
52009
+ title: // ADR-0044 — for the three channels the model's own
52010
+ // context is scoped by, the chip's meaning is dual:
52011
+ // it doesn't just show/hide rows here, it also
52012
+ // decides whether that channel's history is folded
52013
+ // into the next turn the agent sees.
52014
+ 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`,
52015
+ "aria-pressed": on,
52016
+ children: [
52017
+ /*#__PURE__*/ (0,react_jsx_runtime.jsx)(Icon, {
52018
+ size: 10
52019
+ }),
52020
+ /*#__PURE__*/ (0,react_jsx_runtime.jsx)("span", {
52021
+ children: CHIP_LABELS[key]
52022
+ })
52023
+ ]
52024
+ }, key);
52025
+ }),
52026
+ onSetContextPin && /*#__PURE__*/ (0,react_jsx_runtime.jsx)("button", {
52027
+ type: "button",
52028
+ onClick: scrollToBoundaryLine,
52029
+ disabled: !hasContextPin,
52030
+ 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",
52031
+ 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",
52032
+ children: "Locate boundary line"
52033
+ })
52034
+ ]
52035
+ })
52036
+ ]
52037
+ })
52038
+ }),
52039
+ /*#__PURE__*/ (0,react_jsx_runtime.jsxs)("div", {
52040
+ ref: maskRegionRef,
52041
+ className: "relative flex-1 min-h-0 overflow-hidden",
51814
52042
  children: [
51815
- /*#__PURE__*/ (0,react_jsx_runtime.jsxs)("button", {
51816
- type: "button",
51817
- onClick: ()=>setTopControlsOpen((v)=>!v),
51818
- "aria-expanded": topControlsOpen,
51819
- className: "w-full flex items-center gap-2 py-0.5 text-[11px] text-fg-faint hover:text-fg transition-colors",
52043
+ /*#__PURE__*/ (0,react_jsx_runtime.jsxs)("div", {
52044
+ ref: scrollRef,
52045
+ onScroll: handleScroll,
52046
+ className: "flex-1 h-full overflow-y-auto overflow-x-hidden px-4 py-4 panel-scrollbar",
52047
+ style: {
52048
+ // Scroll-anchor jumps (deep-link to a message) land below the
52049
+ // floating header, not under it.
52050
+ scrollPaddingTop: "calc(3rem + var(--app-safe-top))"
52051
+ },
51820
52052
  children: [
51821
- /*#__PURE__*/ (0,react_jsx_runtime.jsx)(CollapseChevron, {
51822
- open: topControlsOpen,
51823
- size: 10
52053
+ hasMore && /*#__PURE__*/ (0,react_jsx_runtime.jsx)("div", {
52054
+ className: "text-center py-1.5 text-[11px] text-fg-faint select-none",
52055
+ children: loadingMore ? "Loading earlier messages…" : "Scroll up for earlier messages"
51824
52056
  }),
51825
- /*#__PURE__*/ (0,react_jsx_runtime.jsx)("span", {
51826
- className: "font-semibold uppercase tracking-[0.16em]",
51827
- children: "Filters & focus"
51828
- }),
51829
- hiddenCount > 0 && /*#__PURE__*/ (0,react_jsx_runtime.jsxs)("span", {
51830
- className: "ml-auto text-[10px] text-fg-faint",
51831
- "aria-live": "polite",
52057
+ compactionPending && /*#__PURE__*/ (0,react_jsx_runtime.jsxs)("div", {
52058
+ 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",
51832
52059
  children: [
51833
- hiddenCount,
51834
- " hidden"
52060
+ /*#__PURE__*/ (0,react_jsx_runtime.jsx)(StatusDot, {
52061
+ tone: "accent",
52062
+ size: "sm",
52063
+ pulse: true
52064
+ }),
52065
+ /*#__PURE__*/ (0,react_jsx_runtime.jsx)("span", {
52066
+ children: "Summarising earlier messages… this turn still sees the full history."
52067
+ })
51835
52068
  ]
51836
- })
51837
- ]
51838
- }),
51839
- topControlsOpen && /*#__PURE__*/ (0,react_jsx_runtime.jsxs)("div", {
51840
- className: "mt-1 flex items-center gap-1.5 flex-wrap py-1",
51841
- children: [
51842
- availableChips.map((key)=>{
51843
- const on = filters[key];
51844
- const Icon = on ? eye/* default */.A : EyeOff;
51845
- return /*#__PURE__*/ (0,react_jsx_runtime.jsxs)("button", {
51846
- type: "button",
51847
- onClick: ()=>toggle(key),
51848
- className: [
51849
- "inline-flex items-center gap-1 rounded-none border px-2 py-0.5 text-[10px] leading-4 transition-colors",
51850
- 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"
51851
- ].join(" "),
51852
- title: // ADR-0044 — for the three channels the model's own
51853
- // context is scoped by, the chip's meaning is dual:
51854
- // it doesn't just show/hide rows here, it also
51855
- // decides whether that channel's history is folded
51856
- // into the next turn the agent sees.
51857
- 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`,
51858
- "aria-pressed": on,
52069
+ }),
52070
+ visibleMessages.length === 0 && !streamingContent && /*#__PURE__*/ (0,react_jsx_runtime.jsx)("div", {
52071
+ className: "flex items-center justify-center h-full text-fg-faint text-sm select-none",
52072
+ children: messages.length === 0 ? /*#__PURE__*/ (0,react_jsx_runtime.jsx)("span", {
52073
+ children: "Send a message to begin"
52074
+ }) : /*#__PURE__*/ (0,react_jsx_runtime.jsxs)("div", {
52075
+ className: "flex flex-col items-center gap-2 text-center px-4",
51859
52076
  children: [
51860
- /*#__PURE__*/ (0,react_jsx_runtime.jsx)(Icon, {
51861
- size: 10
52077
+ /*#__PURE__*/ (0,react_jsx_runtime.jsxs)("span", {
52078
+ children: [
52079
+ hiddenCount,
52080
+ " message",
52081
+ hiddenCount === 1 ? " is" : "s are",
52082
+ " hidden by filters"
52083
+ ]
51862
52084
  }),
51863
- /*#__PURE__*/ (0,react_jsx_runtime.jsx)("span", {
51864
- children: CHIP_LABELS[key]
52085
+ /*#__PURE__*/ (0,react_jsx_runtime.jsx)("button", {
52086
+ type: "button",
52087
+ onClick: reset,
52088
+ 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",
52089
+ children: "Show all messages"
51865
52090
  })
51866
52091
  ]
51867
- }, key);
52092
+ })
51868
52093
  }),
51869
- onSetContextPin && /*#__PURE__*/ (0,react_jsx_runtime.jsx)("button", {
51870
- type: "button",
51871
- onClick: scrollToBoundaryLine,
51872
- disabled: !hasContextPin,
51873
- 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",
51874
- 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",
51875
- children: "Locate boundary line"
52094
+ (()=>{
52095
+ // ADR-0042. The boundary divider + warm summary card live INSIDE the
52096
+ // message stream so they scroll with content (not above as a fixed
52097
+ // banner). `boundaryIndex` is the index of the first hot message in
52098
+ // the visible list; everything before it is older-than-pin and gets
52099
+ // covered by the warm summary card sitting above the divider.
52100
+ //
52101
+ const hasPin = effectiveHotSinceSeq !== null;
52102
+ const boundaryIndex = hasPin ? boundaryIndexFor(effectiveHotSinceSeq) : -1;
52103
+ const pinAfterAll = hasPin && visibleMessages.length > 0 && boundaryIndex === visibleMessages.length;
52104
+ // The pin is the boundary's source of truth. Summary data can arrive
52105
+ // later (or be unavailable on an older thread), but hiding the line
52106
+ // in that interval makes a valid focus selection look like it vanished.
52107
+ const hasBoundary = hasPin && boundaryIndex >= 0;
52108
+ const olderInVisible = pinAfterAll ? visibleMessages.length : hasBoundary ? boundaryIndex : 0;
52109
+ // "+ N more we don't know about yet" — older pages are likely unloaded.
52110
+ const olderCountLabel = olderInVisible + (hasMore ? 1 : 0);
52111
+ const attachedActivities = new Map();
52112
+ const hiddenActivityIds = new Set();
52113
+ for(let i = 0; i < visibleMessages.length - 1; i++){
52114
+ const activityMessage = visibleMessages[i];
52115
+ const activity = activityMessage.metadata?.automation_activity;
52116
+ if (!activity) continue;
52117
+ const related = visibleMessages[i + 1];
52118
+ 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);
52119
+ if (!matches) continue;
52120
+ attachedActivities.set(related.id, activity);
52121
+ hiddenActivityIds.add(activityMessage.id);
52122
+ }
52123
+ const previousVisibleRoles = new Map();
52124
+ let previousVisibleRole = null;
52125
+ for (const message of visibleMessages){
52126
+ previousVisibleRoles.set(message.id, previousVisibleRole);
52127
+ if (!hiddenActivityIds.has(message.id)) previousVisibleRole = message.role;
52128
+ }
52129
+ const renderBoundary = (key)=>/*#__PURE__*/ (0,react_jsx_runtime.jsx)("div", {
52130
+ id: effectiveHotSinceSeq !== null ? `context-boundary-${effectiveHotSinceSeq}` : undefined,
52131
+ "data-focus-boundary": "1",
52132
+ "data-boundary-seq": effectiveHotSinceSeq ?? undefined,
52133
+ children: /*#__PURE__*/ (0,react_jsx_runtime.jsx)(ContextBoundaryDivider, {
52134
+ sourceMessages: warmSummarySourceMessages ?? null,
52135
+ sourceChars: warmSummarySourceChars ?? null,
52136
+ summaryChars: warmSummary ? warmSummary.length : null,
52137
+ lineStats: lineStatsForHotSince(effectiveHotSinceSeq),
52138
+ updating: warmSummaryPending && !summaryFresh,
52139
+ draggable: !!onSetContextPin,
52140
+ hidden: isDraggingFocus,
52141
+ disabled: !!streaming,
52142
+ onClick: handleBoundaryClick,
52143
+ onPointerDown: handleBoundaryPointerDown,
52144
+ onPointerMove: handleBoundaryPointerMove,
52145
+ onPointerUp: handleBoundaryPointerUp,
52146
+ onPointerCancel: handleBoundaryPointerCancel
52147
+ })
52148
+ }, key);
52149
+ const nodes = visibleMessages.flatMap((msg, i)=>{
52150
+ const out = [];
52151
+ if (hasBoundary && !pinAfterAll && i === boundaryIndex) {
52152
+ out.push(renderBoundary(`boundary-${msg.id}`));
52153
+ }
52154
+ if (hiddenActivityIds.has(msg.id)) return out;
52155
+ const previousRole = previousVisibleRoles.get(msg.id);
52156
+ const startsTurn = previousRole == null || previousRole !== msg.role;
52157
+ const steeredSegment = steeredSegments?.find((segment)=>segment.id === msg.id);
52158
+ if (steeredSegment) {
52159
+ out.push(/*#__PURE__*/ (0,react_jsx_runtime.jsx)(StreamingBubble, {
52160
+ content: steeredSegment.content,
52161
+ threadId: threadId ?? null,
52162
+ agentConfig: agentConfig ?? null,
52163
+ showAvatar: i === 0 || visibleMessages[i - 1].role !== "assistant"
52164
+ }, `steered-${steeredSegment.id}`));
52165
+ }
52166
+ out.push(/*#__PURE__*/ (0,react_jsx_runtime.jsx)("div", {
52167
+ id: typeof msg.seq === "number" ? String(msg.seq) : `msg-${msg.id}`,
52168
+ "data-message-id": msg.id,
52169
+ "data-hot-candidate": "1",
52170
+ "data-message-seq": msg.seq,
52171
+ "data-created-at": msg.created_at,
52172
+ className: startsTurn && i > 0 ? "mt-3" : undefined,
52173
+ children: /*#__PURE__*/ (0,react_jsx_runtime.jsx)(MessageBubble, {
52174
+ message: msg,
52175
+ attachedActivity: attachedActivities.get(msg.id),
52176
+ threadId: threadId ?? null,
52177
+ agentConfig: agentConfig,
52178
+ userProfile: userProfile,
52179
+ showAvatar: startsTurn,
52180
+ showToolEvents: filters.tool_use,
52181
+ contextWindowTokens: contextWindowTokens ?? null,
52182
+ isLatest: i === visibleMessages.length - 1 && !streamingContent,
52183
+ onRetry: onRetryMessage
52184
+ })
52185
+ }, msg.id));
52186
+ return out;
52187
+ });
52188
+ if (hasBoundary && pinAfterAll) nodes.push(renderBoundary("boundary-tail"));
52189
+ return nodes;
52190
+ })(),
52191
+ /*#__PURE__*/ (0,react_jsx_runtime.jsx)(LiveTurnActivity, {
52192
+ thinkingContent: thinkingContent,
52193
+ streamingContent: streamingContent,
52194
+ toolEvents: toolEvents,
52195
+ filters: filters,
52196
+ threadId: threadId ?? null,
52197
+ agentConfig: agentConfig ?? null,
52198
+ showStreamingAvatar: messages.length === 0 || messages[messages.length - 1].role !== "assistant",
52199
+ streaming: streaming
52200
+ }),
52201
+ queuedMessages && queuedMessages.length > 0 && /*#__PURE__*/ (0,react_jsx_runtime.jsx)("div", {
52202
+ className: "flex flex-col gap-1 mt-2 mb-1",
52203
+ children: queuedMessages.map((q)=>/*#__PURE__*/ (0,react_jsx_runtime.jsx)(QueuedBubble, {
52204
+ item: q,
52205
+ onRemove: onRemoveQueued
52206
+ }, q.id))
51876
52207
  })
51877
52208
  ]
52209
+ }),
52210
+ /*#__PURE__*/ (0,react_jsx_runtime.jsx)("div", {
52211
+ ref: dragMaskRef,
52212
+ className: "pointer-events-none absolute left-0 right-0 top-0 z-40 opacity-0 transition-opacity duration-75",
52213
+ style: {
52214
+ transform: "translateY(0px)",
52215
+ height: "0px",
52216
+ 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%)",
52217
+ borderBottom: "0",
52218
+ backdropFilter: "grayscale(0.5) saturate(0.18) contrast(0.98)",
52219
+ WebkitBackdropFilter: "grayscale(0.5) saturate(0.18) contrast(0.98)",
52220
+ maskImage: "linear-gradient(to top, black 0%, rgba(0,0,0,0.88) 72%, rgba(0,0,0,0.32) 90%, transparent 100%)",
52221
+ WebkitMaskImage: "linear-gradient(to top, black 0%, rgba(0,0,0,0.88) 72%, rgba(0,0,0,0.32) 90%, transparent 100%)"
52222
+ }
51878
52223
  })
51879
52224
  ]
51880
- })
51881
- }),
51882
- /*#__PURE__*/ (0,react_jsx_runtime.jsxs)("div", {
51883
- ref: maskRegionRef,
51884
- className: "relative flex-1 min-h-0 overflow-hidden",
51885
- children: [
51886
- /*#__PURE__*/ (0,react_jsx_runtime.jsxs)("div", {
51887
- ref: scrollRef,
51888
- onScroll: handleScroll,
51889
- className: "flex-1 h-full overflow-y-auto overflow-x-hidden px-4 py-4 panel-scrollbar",
52225
+ }),
52226
+ showScrollButton && /*#__PURE__*/ (0,react_jsx_runtime.jsx)("button", {
52227
+ onClick: scrollToBottom,
52228
+ style: {
52229
+ bottom: "calc(1rem + var(--app-safe-bottom))"
52230
+ },
52231
+ 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",
52232
+ title: "Auto-scroll paused — resume at latest message",
52233
+ "aria-label": "Resume auto-scroll to latest message",
52234
+ children: /*#__PURE__*/ (0,react_jsx_runtime.jsx)(ArrowDown, {
52235
+ size: 18
52236
+ })
52237
+ }),
52238
+ isDraggingFocus && /*#__PURE__*/ (0,react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, {
52239
+ children: /*#__PURE__*/ (0,react_jsx_runtime.jsxs)("div", {
52240
+ ref: dragGuideRef,
52241
+ className: "pointer-events-none absolute left-4 right-4 z-50 opacity-0",
51890
52242
  style: {
51891
- // Scroll-anchor jumps (deep-link to a message) land below the
51892
- // floating header, not under it.
51893
- scrollPaddingTop: "calc(3rem + var(--app-safe-top))"
52243
+ transform: "translateY(0px)"
51894
52244
  },
51895
52245
  children: [
51896
- hasMore && /*#__PURE__*/ (0,react_jsx_runtime.jsx)("div", {
51897
- className: "text-center py-1.5 text-[11px] text-fg-faint select-none",
51898
- children: loadingMore ? "Loading earlier messages…" : "Scroll up for earlier messages"
51899
- }),
51900
- compactionPending && /*#__PURE__*/ (0,react_jsx_runtime.jsxs)("div", {
51901
- 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",
51902
- children: [
51903
- /*#__PURE__*/ (0,react_jsx_runtime.jsx)(StatusDot, {
51904
- tone: "accent",
51905
- size: "sm",
51906
- pulse: true
51907
- }),
51908
- /*#__PURE__*/ (0,react_jsx_runtime.jsx)("span", {
51909
- children: "Summarising earlier messages… this turn still sees the full history."
51910
- })
51911
- ]
52246
+ /*#__PURE__*/ (0,react_jsx_runtime.jsx)("div", {
52247
+ 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)]"
51912
52248
  }),
51913
- visibleMessages.length === 0 && !streamingContent && /*#__PURE__*/ (0,react_jsx_runtime.jsx)("div", {
51914
- className: "flex items-center justify-center h-full text-fg-faint text-sm select-none",
51915
- children: messages.length === 0 ? /*#__PURE__*/ (0,react_jsx_runtime.jsx)("span", {
51916
- children: "Send a message to begin"
51917
- }) : /*#__PURE__*/ (0,react_jsx_runtime.jsxs)("div", {
51918
- className: "flex flex-col items-center gap-2 text-center px-4",
52249
+ /*#__PURE__*/ (0,react_jsx_runtime.jsx)("span", {
52250
+ ref: dragGuideStatsRef,
52251
+ 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",
52252
+ children: lineStatsForHotSince(effectiveHotSinceSeq)
52253
+ })
52254
+ ]
52255
+ })
52256
+ }),
52257
+ summaryPopoverOpen && /*#__PURE__*/ (0,react_jsx_runtime.jsx)(Dialog/* Dialog */.l, {
52258
+ open: true,
52259
+ onClose: ()=>setSummaryPopoverOpen(false),
52260
+ title: "Earlier messages summary",
52261
+ size: "xl",
52262
+ align: "top",
52263
+ padded: false,
52264
+ children: /*#__PURE__*/ (0,react_jsx_runtime.jsxs)("div", {
52265
+ className: "p-4 space-y-3",
52266
+ children: [
52267
+ /*#__PURE__*/ (0,react_jsx_runtime.jsx)("div", {
52268
+ className: "flex items-center gap-2",
52269
+ children: /*#__PURE__*/ (0,react_jsx_runtime.jsxs)("span", {
52270
+ className: [
52271
+ "text-[10px] px-1.5 py-px rounded border inline-flex items-center gap-1",
52272
+ 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"
52273
+ ].join(" "),
51919
52274
  children: [
51920
- /*#__PURE__*/ (0,react_jsx_runtime.jsxs)("span", {
51921
- children: [
51922
- hiddenCount,
51923
- " message",
51924
- hiddenCount === 1 ? " is" : "s are",
51925
- " hidden by filters"
51926
- ]
52275
+ summaryUpdating && /*#__PURE__*/ (0,react_jsx_runtime.jsx)("span", {
52276
+ className: "h-2 w-2 rounded-full bg-accent animate-pulse",
52277
+ "aria-label": "Summary updating"
51927
52278
  }),
51928
- /*#__PURE__*/ (0,react_jsx_runtime.jsx)("button", {
51929
- type: "button",
51930
- onClick: reset,
51931
- 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",
51932
- children: "Show all messages"
52279
+ /*#__PURE__*/ (0,react_jsx_runtime.jsx)("span", {
52280
+ children: summaryUpdating ? "updating" : summaryReady ? "ready" : summaryStale ? "needs refresh" : "pending"
51933
52281
  })
51934
52282
  ]
51935
52283
  })
51936
52284
  }),
51937
- (()=>{
51938
- // ADR-0042. The boundary divider + warm summary card live INSIDE the
51939
- // message stream so they scroll with content (not above as a fixed
51940
- // banner). `boundaryIndex` is the index of the first hot message in
51941
- // the visible list; everything before it is older-than-pin and gets
51942
- // covered by the warm summary card sitting above the divider.
51943
- //
51944
- const hasPin = effectiveHotSinceSeq !== null;
51945
- const boundaryIndex = hasPin ? boundaryIndexFor(effectiveHotSinceSeq) : -1;
51946
- const pinAfterAll = hasPin && visibleMessages.length > 0 && boundaryIndex === visibleMessages.length;
51947
- // The pin is the boundary's source of truth. Summary data can arrive
51948
- // later (or be unavailable on an older thread), but hiding the line
51949
- // in that interval makes a valid focus selection look like it vanished.
51950
- const hasBoundary = hasPin && boundaryIndex >= 0;
51951
- const olderInVisible = pinAfterAll ? visibleMessages.length : hasBoundary ? boundaryIndex : 0;
51952
- // "+ N more we don't know about yet" — older pages are likely unloaded.
51953
- const olderCountLabel = olderInVisible + (hasMore ? 1 : 0);
51954
- const attachedActivities = new Map();
51955
- const hiddenActivityIds = new Set();
51956
- for(let i = 0; i < visibleMessages.length - 1; i++){
51957
- const activityMessage = visibleMessages[i];
51958
- const activity = activityMessage.metadata?.automation_activity;
51959
- if (!activity) continue;
51960
- const related = visibleMessages[i + 1];
51961
- 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);
51962
- if (!matches) continue;
51963
- attachedActivities.set(related.id, activity);
51964
- hiddenActivityIds.add(activityMessage.id);
51965
- }
51966
- const previousVisibleRoles = new Map();
51967
- let previousVisibleRole = null;
51968
- for (const message of visibleMessages){
51969
- previousVisibleRoles.set(message.id, previousVisibleRole);
51970
- if (!hiddenActivityIds.has(message.id)) previousVisibleRole = message.role;
51971
- }
51972
- const renderBoundary = (key)=>/*#__PURE__*/ (0,react_jsx_runtime.jsx)("div", {
51973
- id: effectiveHotSinceSeq !== null ? `context-boundary-${effectiveHotSinceSeq}` : undefined,
51974
- "data-focus-boundary": "1",
51975
- "data-boundary-seq": effectiveHotSinceSeq ?? undefined,
51976
- children: /*#__PURE__*/ (0,react_jsx_runtime.jsx)(ContextBoundaryDivider, {
51977
- sourceMessages: warmSummarySourceMessages ?? null,
51978
- sourceChars: warmSummarySourceChars ?? null,
51979
- summaryChars: warmSummary ? warmSummary.length : null,
51980
- lineStats: lineStatsForHotSince(effectiveHotSinceSeq),
51981
- updating: warmSummaryPending && !summaryFresh,
51982
- draggable: !!onSetContextPin,
51983
- hidden: isDraggingFocus,
51984
- disabled: !!streaming,
51985
- onClick: handleBoundaryClick,
51986
- onPointerDown: handleBoundaryPointerDown,
51987
- onPointerMove: handleBoundaryPointerMove,
51988
- onPointerUp: handleBoundaryPointerUp,
51989
- onPointerCancel: handleBoundaryPointerCancel
51990
- })
51991
- }, key);
51992
- const nodes = visibleMessages.flatMap((msg, i)=>{
51993
- const out = [];
51994
- if (hasBoundary && !pinAfterAll && i === boundaryIndex) {
51995
- out.push(renderBoundary(`boundary-${msg.id}`));
51996
- }
51997
- if (hiddenActivityIds.has(msg.id)) return out;
51998
- const previousRole = previousVisibleRoles.get(msg.id);
51999
- const startsTurn = previousRole == null || previousRole !== msg.role;
52000
- const steeredSegment = steeredSegments?.find((segment)=>segment.id === msg.id);
52001
- if (steeredSegment) {
52002
- out.push(/*#__PURE__*/ (0,react_jsx_runtime.jsx)(StreamingBubble, {
52003
- content: steeredSegment.content,
52004
- threadId: threadId ?? null,
52005
- agentConfig: agentConfig ?? null,
52006
- showAvatar: i === 0 || visibleMessages[i - 1].role !== "assistant"
52007
- }, `steered-${steeredSegment.id}`));
52008
- }
52009
- out.push(/*#__PURE__*/ (0,react_jsx_runtime.jsx)("div", {
52010
- id: typeof msg.seq === "number" ? String(msg.seq) : `msg-${msg.id}`,
52011
- "data-message-id": msg.id,
52012
- "data-hot-candidate": "1",
52013
- "data-message-seq": msg.seq,
52014
- "data-created-at": msg.created_at,
52015
- className: startsTurn && i > 0 ? "mt-3" : undefined,
52016
- children: /*#__PURE__*/ (0,react_jsx_runtime.jsx)(MessageBubble, {
52017
- message: msg,
52018
- attachedActivity: attachedActivities.get(msg.id),
52019
- threadId: threadId ?? null,
52020
- agentConfig: agentConfig,
52021
- userProfile: userProfile,
52022
- showAvatar: startsTurn,
52023
- showToolEvents: filters.tool_use,
52024
- contextWindowTokens: contextWindowTokens ?? null,
52025
- isLatest: i === visibleMessages.length - 1 && !streamingContent,
52026
- onRetry: onRetryMessage
52027
- })
52028
- }, msg.id));
52029
- return out;
52030
- });
52031
- if (hasBoundary && pinAfterAll) nodes.push(renderBoundary("boundary-tail"));
52032
- return nodes;
52033
- })(),
52034
- /*#__PURE__*/ (0,react_jsx_runtime.jsx)(LiveTurnActivity, {
52035
- thinkingContent: thinkingContent,
52036
- streamingContent: streamingContent,
52037
- toolEvents: toolEvents,
52038
- filters: filters,
52039
- threadId: threadId ?? null,
52040
- agentConfig: agentConfig ?? null,
52041
- showStreamingAvatar: messages.length === 0 || messages[messages.length - 1].role !== "assistant",
52042
- streaming: streaming
52043
- }),
52044
- queuedMessages && queuedMessages.length > 0 && /*#__PURE__*/ (0,react_jsx_runtime.jsx)("div", {
52045
- className: "flex flex-col gap-1 mt-2 mb-1",
52046
- children: queuedMessages.map((q)=>/*#__PURE__*/ (0,react_jsx_runtime.jsx)(QueuedBubble, {
52047
- item: q,
52048
- onRemove: onRemoveQueued
52049
- }, q.id))
52285
+ !summaryUpdating && /*#__PURE__*/ (0,react_jsx_runtime.jsx)("p", {
52286
+ className: "text-[11px] text-fg-faint",
52287
+ 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."
52050
52288
  }),
52051
- notices?.map((n)=>/*#__PURE__*/ (0,react_jsx_runtime.jsx)("div", {
52052
- className: "flex justify-center my-3",
52053
- children: /*#__PURE__*/ (0,react_jsx_runtime.jsx)("span", {
52054
- className: "text-xs italic text-fg-faint bg-surface-2 px-3 py-1 rounded-full border border-border",
52055
- children: n.text
52056
- })
52057
- }, n.id))
52289
+ /*#__PURE__*/ (0,react_jsx_runtime.jsx)(WarmSummaryCard, {
52290
+ olderCount: countOlderForHotSince(effectiveHotSinceSeq) + (hasMore ? 1 : 0),
52291
+ summary: warmSummary ?? null,
52292
+ summaryBeforeSeq: warmSummaryBeforeSeq ?? null,
52293
+ hotSinceSeq: effectiveHotSinceSeq,
52294
+ computedAt: warmSummaryComputedAt ?? null,
52295
+ streaming: !!streaming,
52296
+ topics: warmSummaryTopics ?? null,
52297
+ channelSummaries: warmChannelSummaries
52298
+ })
52058
52299
  ]
52059
- }),
52060
- /*#__PURE__*/ (0,react_jsx_runtime.jsx)("div", {
52061
- ref: dragMaskRef,
52062
- className: "pointer-events-none absolute left-0 right-0 top-0 z-40 opacity-0 transition-opacity duration-75",
52063
- style: {
52064
- transform: "translateY(0px)",
52065
- height: "0px",
52066
- 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%)",
52067
- borderBottom: "0",
52068
- backdropFilter: "grayscale(0.5) saturate(0.18) contrast(0.98)",
52069
- WebkitBackdropFilter: "grayscale(0.5) saturate(0.18) contrast(0.98)",
52070
- maskImage: "linear-gradient(to top, black 0%, rgba(0,0,0,0.88) 72%, rgba(0,0,0,0.32) 90%, transparent 100%)",
52071
- WebkitMaskImage: "linear-gradient(to top, black 0%, rgba(0,0,0,0.88) 72%, rgba(0,0,0,0.32) 90%, transparent 100%)"
52072
- }
52073
52300
  })
52074
- ]
52075
- }),
52076
- showScrollButton && /*#__PURE__*/ (0,react_jsx_runtime.jsx)("button", {
52077
- onClick: scrollToBottom,
52078
- style: {
52079
- bottom: "calc(1rem + var(--app-safe-bottom))"
52080
- },
52081
- 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",
52082
- title: "Auto-scroll paused — resume at latest message",
52083
- "aria-label": "Resume auto-scroll to latest message",
52084
- children: /*#__PURE__*/ (0,react_jsx_runtime.jsx)(ArrowDown, {
52085
- size: 18
52086
- })
52087
- }),
52088
- isDraggingFocus && /*#__PURE__*/ (0,react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, {
52089
- children: /*#__PURE__*/ (0,react_jsx_runtime.jsxs)("div", {
52090
- ref: dragGuideRef,
52091
- className: "pointer-events-none absolute left-4 right-4 z-50 opacity-0",
52092
- style: {
52093
- transform: "translateY(0px)"
52301
+ }),
52302
+ /*#__PURE__*/ (0,react_jsx_runtime.jsxs)(Dialog/* Dialog */.l, {
52303
+ open: confirmOpen,
52304
+ onClose: ()=>{
52305
+ setConfirmOpen(false);
52306
+ setPendingHotSinceSeq(null);
52094
52307
  },
52308
+ size: "sm",
52309
+ align: "center",
52310
+ dismissOnBackdrop: false,
52095
52311
  children: [
52096
- /*#__PURE__*/ (0,react_jsx_runtime.jsx)("div", {
52097
- 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)]"
52312
+ /*#__PURE__*/ (0,react_jsx_runtime.jsx)("h4", {
52313
+ className: "text-sm font-semibold text-fg",
52314
+ children: "Move conversation focus here?"
52098
52315
  }),
52099
- /*#__PURE__*/ (0,react_jsx_runtime.jsx)("span", {
52100
- ref: dragGuideStatsRef,
52101
- 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",
52102
- children: lineStatsForHotSince(effectiveHotSinceSeq)
52103
- })
52104
- ]
52105
- })
52106
- }),
52107
- summaryPopoverOpen && /*#__PURE__*/ (0,react_jsx_runtime.jsx)(Dialog/* Dialog */.l, {
52108
- open: true,
52109
- onClose: ()=>setSummaryPopoverOpen(false),
52110
- title: "Earlier messages summary",
52111
- size: "xl",
52112
- align: "top",
52113
- padded: false,
52114
- children: /*#__PURE__*/ (0,react_jsx_runtime.jsxs)("div", {
52115
- className: "p-4 space-y-3",
52116
- children: [
52117
- /*#__PURE__*/ (0,react_jsx_runtime.jsx)("div", {
52118
- className: "flex items-center gap-2",
52119
- children: /*#__PURE__*/ (0,react_jsx_runtime.jsxs)("span", {
52120
- className: [
52121
- "text-[10px] px-1.5 py-px rounded border inline-flex items-center gap-1",
52122
- 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"
52123
- ].join(" "),
52124
- children: [
52125
- summaryUpdating && /*#__PURE__*/ (0,react_jsx_runtime.jsx)("span", {
52126
- className: "h-2 w-2 rounded-full bg-accent animate-pulse",
52127
- "aria-label": "Summary updating"
52128
- }),
52129
- /*#__PURE__*/ (0,react_jsx_runtime.jsx)("span", {
52130
- children: summaryUpdating ? "updating" : summaryFresh ? "ready" : summaryStale ? "needs refresh" : "pending"
52131
- })
52132
- ]
52133
- })
52316
+ /*#__PURE__*/ (0,react_jsx_runtime.jsx)("p", {
52317
+ className: "text-xs text-fg-muted leading-relaxed",
52318
+ children: "Start a new conversation context from this point. New replies will prioritize recent messages below this line."
52134
52319
  }),
52135
- !summaryUpdating && /*#__PURE__*/ (0,react_jsx_runtime.jsx)("p", {
52320
+ nextHotCount !== null && /*#__PURE__*/ (0,react_jsx_runtime.jsxs)("p", {
52136
52321
  className: "text-[11px] text-fg-faint",
52137
- 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."
52322
+ children: [
52323
+ "Recent in focus: ",
52324
+ nextHotCount,
52325
+ " loaded message",
52326
+ nextHotCount === 1 ? "" : "s",
52327
+ "; earlier loaded summary: ",
52328
+ Math.max(0, visibleMessages.length - nextHotCount),
52329
+ "."
52330
+ ]
52331
+ }),
52332
+ removesFromRecent && /*#__PURE__*/ (0,react_jsx_runtime.jsx)("p", {
52333
+ className: "text-[11px] text-amber-600 dark:text-amber-400",
52334
+ children: "This reduces recent in-focus messages. You can drag upward later to add history back."
52138
52335
  }),
52139
- /*#__PURE__*/ (0,react_jsx_runtime.jsx)(WarmSummaryCard, {
52140
- olderCount: countOlderForHotSince(effectiveHotSinceSeq) + (hasMore ? 1 : 0),
52141
- summary: warmSummary ?? null,
52142
- summaryBeforeSeq: warmSummaryBeforeSeq ?? null,
52143
- hotSinceSeq: effectiveHotSinceSeq,
52144
- computedAt: warmSummaryComputedAt ?? null,
52145
- streaming: !!streaming,
52146
- topics: warmSummaryTopics ?? null
52336
+ /*#__PURE__*/ (0,react_jsx_runtime.jsxs)("div", {
52337
+ className: "flex justify-end gap-2 pt-1",
52338
+ children: [
52339
+ /*#__PURE__*/ (0,react_jsx_runtime.jsx)("button", {
52340
+ type: "button",
52341
+ onClick: ()=>{
52342
+ setConfirmOpen(false);
52343
+ setPendingHotSinceSeq(null);
52344
+ },
52345
+ className: "px-3 py-1.5 text-xs text-fg-subtle hover:text-fg transition-colors",
52346
+ children: "Cancel"
52347
+ }),
52348
+ /*#__PURE__*/ (0,react_jsx_runtime.jsx)("button", {
52349
+ type: "button",
52350
+ onClick: ()=>{
52351
+ if (pendingHotSinceSeq !== null && onSetContextPin) onSetContextPin(pendingHotSinceSeq);
52352
+ setConfirmOpen(false);
52353
+ setPendingHotSinceSeq(null);
52354
+ },
52355
+ className: "px-3 py-1.5 rounded-md text-xs border border-accent/40 bg-accent text-white hover:opacity-95 transition-opacity",
52356
+ children: "Move focus"
52357
+ })
52358
+ ]
52147
52359
  })
52148
52360
  ]
52149
52361
  })
52150
- }),
52151
- /*#__PURE__*/ (0,react_jsx_runtime.jsxs)(Dialog/* Dialog */.l, {
52152
- open: confirmOpen,
52153
- onClose: ()=>{
52154
- setConfirmOpen(false);
52155
- setPendingHotSinceSeq(null);
52156
- },
52157
- size: "sm",
52158
- align: "center",
52159
- dismissOnBackdrop: false,
52160
- children: [
52161
- /*#__PURE__*/ (0,react_jsx_runtime.jsx)("h4", {
52162
- className: "text-sm font-semibold text-fg",
52163
- children: "Move conversation focus here?"
52164
- }),
52165
- /*#__PURE__*/ (0,react_jsx_runtime.jsx)("p", {
52166
- className: "text-xs text-fg-muted leading-relaxed",
52167
- children: "Start a new conversation context from this point. New replies will prioritize recent messages below this line."
52168
- }),
52169
- nextHotCount !== null && /*#__PURE__*/ (0,react_jsx_runtime.jsxs)("p", {
52170
- className: "text-[11px] text-fg-faint",
52171
- children: [
52172
- "Recent in focus: ",
52173
- nextHotCount,
52174
- " loaded message",
52175
- nextHotCount === 1 ? "" : "s",
52176
- "; earlier loaded summary: ",
52177
- Math.max(0, visibleMessages.length - nextHotCount),
52178
- "."
52179
- ]
52180
- }),
52181
- removesFromRecent && /*#__PURE__*/ (0,react_jsx_runtime.jsx)("p", {
52182
- className: "text-[11px] text-amber-600 dark:text-amber-400",
52183
- children: "This reduces recent in-focus messages. You can drag upward later to add history back."
52184
- }),
52185
- /*#__PURE__*/ (0,react_jsx_runtime.jsxs)("div", {
52186
- className: "flex justify-end gap-2 pt-1",
52187
- children: [
52188
- /*#__PURE__*/ (0,react_jsx_runtime.jsx)("button", {
52189
- type: "button",
52190
- onClick: ()=>{
52191
- setConfirmOpen(false);
52192
- setPendingHotSinceSeq(null);
52193
- },
52194
- className: "px-3 py-1.5 text-xs text-fg-subtle hover:text-fg transition-colors",
52195
- children: "Cancel"
52196
- }),
52197
- /*#__PURE__*/ (0,react_jsx_runtime.jsx)("button", {
52198
- type: "button",
52199
- onClick: ()=>{
52200
- if (pendingHotSinceSeq !== null && onSetContextPin) onSetContextPin(pendingHotSinceSeq);
52201
- setConfirmOpen(false);
52202
- setPendingHotSinceSeq(null);
52203
- },
52204
- className: "px-3 py-1.5 rounded-md text-xs border border-accent/40 bg-accent text-white hover:opacity-95 transition-opacity",
52205
- children: "Move focus"
52206
- })
52207
- ]
52208
- })
52209
- ]
52210
- })
52211
- ]
52362
+ ]
52363
+ })
52212
52364
  });
52213
52365
  }
52214
52366
  // ADR-0044 — the subset of MESSAGE_FILTER_KEYS that also map to a
@@ -52220,6 +52372,7 @@ const CHANNEL_SCOPED_FILTER_KEYS = new Set([
52220
52372
  "watcher",
52221
52373
  "bridge"
52222
52374
  ]);
52375
+ const PROGRAMMATIC_SCROLL_LOCK_MS = 1500;
52223
52376
  const CHIP_LABELS = {
52224
52377
  scheduled_task: "scheduled",
52225
52378
  watcher: "watcher",
@@ -52389,7 +52542,46 @@ function QueuedBubble({ item, onRemove }) {
52389
52542
  }
52390
52543
 
52391
52544
  ;// ./components/chat/chat-helpers.ts
52392
- /* __next_internal_client_entry_do_not_use__ isUnconfirmed,appendUnique,applyThreadMeta,makeQueuedId,parseWarmSummaryTopics auto */ // Append-with-reconcile. Merges server-persisted rows into the local list
52545
+ /* __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
52546
+ // decides the text: "nothing to compact" means the thread is empty, anything
52547
+ // else means there were messages but no summary came out of them.
52548
+ function compactionOutcomeToast(result) {
52549
+ if (result.compacted) {
52550
+ const n = result.message_count ?? 0;
52551
+ return {
52552
+ kind: "success",
52553
+ title: "Context compacted",
52554
+ body: n > 0 ? `Summarised ${n} message${n === 1 ? "" : "s"} into warm context.` : "Started a fresh context window."
52555
+ };
52556
+ }
52557
+ if (result.reason === "nothing to compact") {
52558
+ return {
52559
+ kind: "info",
52560
+ title: "Nothing to compact",
52561
+ body: "This conversation has no messages yet."
52562
+ };
52563
+ }
52564
+ if (result.reason === "already compacting") {
52565
+ return {
52566
+ kind: "info",
52567
+ title: "Already compacting",
52568
+ body: "A compaction for this conversation is still running."
52569
+ };
52570
+ }
52571
+ if (result.reason === "timed out") {
52572
+ return {
52573
+ kind: "error",
52574
+ title: "Compaction timed out",
52575
+ body: "The summary took too long and was discarded. Context is unchanged."
52576
+ };
52577
+ }
52578
+ return {
52579
+ kind: "info",
52580
+ title: "Nothing was compacted",
52581
+ body: "There was too little to summarise, or the model returned no usable summary. Context is unchanged."
52582
+ };
52583
+ }
52584
+ // Append-with-reconcile. Merges server-persisted rows into the local list
52393
52585
  // with three rules, applied in order for each incoming message:
52394
52586
  //
52395
52587
  // 1. Already present by server id → update in place (handles the
@@ -52474,10 +52666,12 @@ function applyThreadMeta(meta, payload) {
52474
52666
  meta.setWarmSummarySourceMessages(payload.warm_summary_source_messages ?? null);
52475
52667
  meta.setWarmSummarySourceChars(payload.warm_summary_source_chars ?? null);
52476
52668
  meta.setWarmSummaryTopics?.(payload.warm_summary_topics ?? null);
52669
+ meta.setWarmChannelSummaries?.(payload.warm_channel_summaries ?? []);
52477
52670
  meta.setContextWindowTokens(payload.context_window_tokens ?? null);
52478
52671
  const summaryFresh = hotSinceSeq !== null && summaryBeforeSeq === hotSinceSeq;
52479
52672
  meta.setWarmSummaryPending?.(hotSinceSeq !== null && !summaryFresh);
52480
52673
  meta.setCompactionPending?.(payload.pending_hot_since_seq != null);
52674
+ meta.setManualCompactionPending?.(payload.manual_compaction_pending === true);
52481
52675
  }
52482
52676
  function makeQueuedId(prefix = "q") {
52483
52677
  return `${prefix}-${Date.now()}-${Math.random().toString(36).slice(2, 6)}`;
@@ -52493,8 +52687,6 @@ function makeQueuedId(prefix = "q") {
52493
52687
  }
52494
52688
  }
52495
52689
 
52496
- // EXTERNAL MODULE: ./lib/ui/error-report.ts
52497
- var error_report = __webpack_require__(10778);
52498
52690
  ;// ./lib/ui/error-message.ts
52499
52691
  /* __next_internal_client_entry_do_not_use__ friendlyErrorTitle,reportError auto */ // Centralized human-friendly error-title mapping. Used by pushErrorToast
52500
52692
  // callers so the headline a user sees is consistent across the UI:
@@ -52825,7 +53017,6 @@ function useThreadCrossDeviceSync({ threadId, streamingRef, messagesRef, setMess
52825
53017
 
52826
53018
  function useThreadData({ threadId, attach }) {
52827
53019
  const [messages, setMessages] = (0,react.useState)([]);
52828
- const [notices, setNotices] = (0,react.useState)([]);
52829
53020
  const [hasMore, setHasMore] = (0,react.useState)(false);
52830
53021
  const [loadingMore, setLoadingMore] = (0,react.useState)(false);
52831
53022
  const [messagesLoading, setMessagesLoading] = (0,react.useState)(false);
@@ -52839,8 +53030,10 @@ function useThreadData({ threadId, attach }) {
52839
53030
  const [warmSummarySourceMessages, setWarmSummarySourceMessages] = (0,react.useState)(null);
52840
53031
  const [warmSummarySourceChars, setWarmSummarySourceChars] = (0,react.useState)(null);
52841
53032
  const [warmSummaryTopics, setWarmSummaryTopics] = (0,react.useState)(null);
53033
+ const [warmChannelSummaries, setWarmChannelSummaries] = (0,react.useState)([]);
52842
53034
  const [warmSummaryPending, setWarmSummaryPending] = (0,react.useState)(false);
52843
53035
  const [compactionPending, setCompactionPending] = (0,react.useState)(false);
53036
+ const [manualCompactionPending, setManualCompactionPending] = (0,react.useState)(false);
52844
53037
  const [contextWindowTokens, setContextWindowTokens] = (0,react.useState)(null);
52845
53038
  const messagesRef = (0,react.useRef)([]);
52846
53039
  messagesRef.current = messages;
@@ -52857,22 +53050,14 @@ function useThreadData({ threadId, attach }) {
52857
53050
  setContextWindowTokens,
52858
53051
  setWarmSummaryPending,
52859
53052
  setCompactionPending,
52860
- setWarmSummaryTopics
53053
+ setManualCompactionPending,
53054
+ setWarmSummaryTopics,
53055
+ setWarmChannelSummaries
52861
53056
  };
52862
- const addNotice = (0,react.useCallback)((text)=>{
52863
- setNotices((p)=>[
52864
- ...p,
52865
- {
52866
- id: `notice-${Date.now()}`,
52867
- text
52868
- }
52869
- ]);
52870
- }, []);
52871
53057
  process.env.__NEXT_PRIVATE_MINIMIZE_MACRO_FALSE && (0,react.useEffect)(()=>{
52872
53058
  if (!threadId) {
52873
53059
  setMetadataThreadId(null);
52874
53060
  setMessages([]);
52875
- setNotices([]);
52876
53061
  setHasMore(false);
52877
53062
  setMessagesLoading(false);
52878
53063
  setHotSince(null);
@@ -52884,8 +53069,10 @@ function useThreadData({ threadId, attach }) {
52884
53069
  setWarmSummarySourceMessages(null);
52885
53070
  setWarmSummarySourceChars(null);
52886
53071
  setWarmSummaryTopics(null);
53072
+ setWarmChannelSummaries([]);
52887
53073
  setWarmSummaryPending(false);
52888
53074
  setCompactionPending(false);
53075
+ setManualCompactionPending(false);
52889
53076
  setContextWindowTokens(null);
52890
53077
  return;
52891
53078
  }
@@ -52903,8 +53090,10 @@ function useThreadData({ threadId, attach }) {
52903
53090
  setWarmSummarySourceMessages(null);
52904
53091
  setWarmSummarySourceChars(null);
52905
53092
  setWarmSummaryTopics(null);
53093
+ setWarmChannelSummaries([]);
52906
53094
  setWarmSummaryPending(false);
52907
53095
  setCompactionPending(false);
53096
+ setManualCompactionPending(false);
52908
53097
  setContextWindowTokens(null);
52909
53098
  client/* api */.FH.threads.get(threadId).then((d)=>{
52910
53099
  if (cancelled) return;
@@ -52950,6 +53139,7 @@ function useThreadData({ threadId, attach }) {
52950
53139
  setWarmSummarySourceMessages(updated.warm_summary_source_messages);
52951
53140
  setWarmSummarySourceChars(updated.warm_summary_source_chars);
52952
53141
  setWarmSummaryTopics(updated.warm_summary_topics);
53142
+ setWarmChannelSummaries(updated.warm_channel_summaries ?? []);
52953
53143
  setCompactionPending(updated.pending_hot_since_seq != null);
52954
53144
  const summaryFresh = updated.hot_since_seq != null && updated.warm_summary_before_seq === updated.hot_since_seq;
52955
53145
  if (!updated.pending_hot_since_seq && (!updated.hot_since_seq || summaryFresh)) {
@@ -52967,7 +53157,7 @@ function useThreadData({ threadId, attach }) {
52967
53157
  if (!threadId) return;
52968
53158
  const summaryFresh = hotSinceSeq !== null && warmSummaryBeforeSeq === hotSinceSeq;
52969
53159
  const summaryStale = warmSummaryPending && hotSinceSeq !== null && !summaryFresh;
52970
- if (!summaryStale && !compactionPending) {
53160
+ if (!summaryStale && !compactionPending && !manualCompactionPending) {
52971
53161
  if (warmSummaryPending && hotSinceSeq !== null && summaryFresh) setWarmSummaryPending(false);
52972
53162
  return;
52973
53163
  }
@@ -52993,6 +53183,7 @@ function useThreadData({ threadId, attach }) {
52993
53183
  threadId,
52994
53184
  warmSummaryPending,
52995
53185
  compactionPending,
53186
+ manualCompactionPending,
52996
53187
  hotSince,
52997
53188
  hotSinceSeq,
52998
53189
  warmSummaryBefore,
@@ -53030,9 +53221,6 @@ function useThreadData({ threadId, attach }) {
53030
53221
  messages,
53031
53222
  setMessages,
53032
53223
  messagesRef,
53033
- notices,
53034
- setNotices,
53035
- addNotice,
53036
53224
  hasMore,
53037
53225
  setHasMore,
53038
53226
  loadingMore,
@@ -53047,8 +53235,10 @@ function useThreadData({ threadId, attach }) {
53047
53235
  warmSummarySourceMessages,
53048
53236
  warmSummarySourceChars,
53049
53237
  warmSummaryTopics,
53238
+ warmChannelSummaries,
53050
53239
  warmSummaryPending,
53051
53240
  compactionPending,
53241
+ manualCompactionPending,
53052
53242
  contextWindowTokens,
53053
53243
  metaApplier,
53054
53244
  loadOlder,
@@ -53056,6 +53246,96 @@ function useThreadData({ threadId, attach }) {
53056
53246
  };
53057
53247
  }
53058
53248
 
53249
+ ;// ./components/chat/useThreadActivity.ts
53250
+ /* __next_internal_client_entry_do_not_use__ useThreadActivity auto */
53251
+
53252
+
53253
+ const BUSY_POLL_MS = 1500;
53254
+ const IDLE_POLL_MS = 5000;
53255
+ // A run's stream ends a moment before the registry marks it finished; a
53256
+ // snapshot inside this window may still report the run that just ended.
53257
+ const SETTLE_GRACE_MS = 2000;
53258
+ /**
53259
+ * Poll what the thread is doing on the server and keep the chat in step:
53260
+ * re-attach to a turn started elsewhere (scheduler, watcher, bridge, another
53261
+ * device), restore compaction flags after a remount, and refresh the thread
53262
+ * metadata once a compaction finishes.
53263
+ */ function useThreadActivity({ threadId, attach, isLive, lastSettledAt, metaApplier }) {
53264
+ const [activity, setActivity] = (0,react.useState)(null);
53265
+ const deps = (0,react.useRef)({
53266
+ attach,
53267
+ isLive,
53268
+ lastSettledAt,
53269
+ metaApplier
53270
+ });
53271
+ deps.current = {
53272
+ attach,
53273
+ isLive,
53274
+ lastSettledAt,
53275
+ metaApplier
53276
+ };
53277
+ process.env.__NEXT_PRIVATE_MINIMIZE_MACRO_FALSE && (0,react.useEffect)(()=>{
53278
+ setActivity(null);
53279
+ if (!threadId) return;
53280
+ let cancelled = false;
53281
+ let timer = null;
53282
+ let hadCompaction = false;
53283
+ const schedule = (ms)=>{
53284
+ if (!cancelled) timer = window.setTimeout(tick, ms);
53285
+ };
53286
+ async function tick() {
53287
+ if (cancelled || !threadId) return;
53288
+ if (typeof document !== "undefined" && document.hidden) {
53289
+ schedule(IDLE_POLL_MS);
53290
+ return;
53291
+ }
53292
+ let next;
53293
+ try {
53294
+ next = await client/* api */.FH.threads.activity(threadId);
53295
+ } catch {
53296
+ schedule(IDLE_POLL_MS);
53297
+ return;
53298
+ }
53299
+ if (cancelled) return;
53300
+ setActivity(next);
53301
+ const d = deps.current;
53302
+ const serverRunning = next.run !== null || next.queue_depth > 0;
53303
+ const recentlySettled = Date.now() - d.lastSettledAt() < SETTLE_GRACE_MS;
53304
+ if (serverRunning && !d.isLive() && !recentlySettled) {
53305
+ d.attach(threadId).catch(()=>{});
53306
+ }
53307
+ if (next.compaction) {
53308
+ if (next.compaction.kind !== "refresh") d.metaApplier.setCompactionPending?.(true);
53309
+ if (next.compaction.kind === "manual") d.metaApplier.setManualCompactionPending?.(true);
53310
+ hadCompaction = true;
53311
+ } else if (hadCompaction) {
53312
+ hadCompaction = false;
53313
+ // The compaction just finished. Clear the flags from the snapshot
53314
+ // itself so a failed refresh below can't leave the chat locked, then
53315
+ // pull the new boundary and recap.
53316
+ d.metaApplier.setCompactionPending?.(false);
53317
+ d.metaApplier.setManualCompactionPending?.(false);
53318
+ client/* api */.FH.threads.get(threadId, {
53319
+ limit: 1
53320
+ }).then((meta)=>{
53321
+ if (!cancelled) applyThreadMeta(deps.current.metaApplier, meta);
53322
+ }).catch(()=>{});
53323
+ }
53324
+ schedule(next.busy ? BUSY_POLL_MS : IDLE_POLL_MS);
53325
+ }
53326
+ // The thread load attaches to any in-flight run itself; give it a beat
53327
+ // so this poller doesn't race it with a second attach.
53328
+ schedule(BUSY_POLL_MS);
53329
+ return ()=>{
53330
+ cancelled = true;
53331
+ if (timer !== null) window.clearTimeout(timer);
53332
+ };
53333
+ }, [
53334
+ threadId
53335
+ ]);
53336
+ return activity;
53337
+ }
53338
+
53059
53339
  ;// ./components/chat/useUserProfileAndAgent.ts
53060
53340
  /* __next_internal_client_entry_do_not_use__ useUserProfileAndAgent auto */
53061
53341
 
@@ -53255,6 +53535,9 @@ function useChatSubmitHandlers({ agentId, steerRun, attachments, setAttachments,
53255
53535
 
53256
53536
 
53257
53537
 
53538
+
53539
+
53540
+
53258
53541
 
53259
53542
  function ChatView({ threadId, agentId, sessionLoading, sessionError, onMessageSent }) {
53260
53543
  const { state } = (0,AppContext/* useAppContext */.U)();
@@ -53311,6 +53594,19 @@ function ChatView({ threadId, agentId, sessionLoading, sessionError, onMessageSe
53311
53594
  attachRef.current = sse.attach;
53312
53595
  clearStreamingRef.current = sse.clearStreamingContent;
53313
53596
  clearToolEventsRef.current = sse.clearToolEvents;
53597
+ // `compacting` lives in this component, which remounts per agent; the
53598
+ // server flag keeps a /compact started before an agent switch visible.
53599
+ const sessionCompacting = compacting || thread.manualCompactionPending;
53600
+ const activity = useThreadActivity({
53601
+ threadId,
53602
+ attach: stableAttach,
53603
+ isLive: sse.isLive,
53604
+ lastSettledAt: sse.lastSettledAt,
53605
+ metaApplier: thread.metaApplier
53606
+ });
53607
+ // Run phases come through the attached stream; background compaction
53608
+ // outside a run has no stream, so label it from the polled activity.
53609
+ const backgroundCompaction = !sse.streaming && !sessionCompacting ? activity?.compaction?.kind ?? null : null;
53314
53610
  useChatErrorReporting({
53315
53611
  sessionError,
53316
53612
  streamError: sse.error,
@@ -53320,6 +53616,8 @@ function ChatView({ threadId, agentId, sessionLoading, sessionError, onMessageSe
53320
53616
  });
53321
53617
  const streamingRef = (0,react.useRef)(false);
53322
53618
  streamingRef.current = sse.streaming;
53619
+ const currentThreadIdRef = (0,react.useRef)(threadId);
53620
+ currentThreadIdRef.current = threadId;
53323
53621
  // Auto compaction starts server-side during a run; poll so the banner shows live.
53324
53622
  process.env.__NEXT_PRIVATE_MINIMIZE_MACRO_FALSE && (0,react.useEffect)(()=>{
53325
53623
  if (!threadId || !sse.streaming) return;
@@ -53350,10 +53648,13 @@ function ChatView({ threadId, agentId, sessionLoading, sessionError, onMessageSe
53350
53648
  });
53351
53649
  useTrackLoading(!!sessionLoading);
53352
53650
  useTrackLoading(sse.streaming);
53353
- useTrackLoading(compacting);
53651
+ useTrackLoading(sessionCompacting);
53354
53652
  useTrackLoading(thread.loadingMore);
53355
53653
  useTrackLoading(thread.messagesLoading);
53356
53654
  useTrackLoading(agentConfigLoading);
53655
+ useActivityWhile(sessionCompacting, "Compacting session…");
53656
+ useActivityWhile(backgroundCompaction === "auto", "Compacting earlier messages…");
53657
+ useActivityWhile(backgroundCompaction === "refresh", "Updating summary…");
53357
53658
  useActivityWhile(thread.messagesLoading, "Loading chat history…");
53358
53659
  useActivityWhile(agentConfigLoading, "Loading agent…");
53359
53660
  useActivityWhile(profileLoading, "Loading profile…");
@@ -53457,19 +53758,35 @@ function ChatView({ threadId, agentId, sessionLoading, sessionError, onMessageSe
53457
53758
  const queue = useChatQueue({
53458
53759
  threadId,
53459
53760
  streaming: sse.streaming,
53460
- compacting,
53761
+ compacting: sessionCompacting,
53461
53762
  launchRun
53462
53763
  });
53463
53764
  queueApiRef.current = queue;
53464
53765
  drainQueueRef.current = queue.drainQueueRef.current;
53465
53766
  async function handleCompact() {
53466
53767
  if (!agentId) return;
53768
+ const notifyCompaction = (result)=>{
53769
+ const toast = compactionOutcomeToast(result);
53770
+ (0,ui_toasts/* pushToast */.Iz)({
53771
+ ...toast,
53772
+ source: "system",
53773
+ sourceLabel: "Chat",
53774
+ agent_id: agentId,
53775
+ thread_id: threadId,
53776
+ ttl: 5000,
53777
+ dedupeKey: `compact:${agentId}`
53778
+ });
53779
+ };
53467
53780
  setCompacting(true);
53468
53781
  try {
53469
53782
  const result = await client/* api */.FH.agents.compact(agentId, {
53470
53783
  resetContext: true
53471
53784
  });
53472
- if (result.compacted) {
53785
+ // The thread may have changed while compaction ran; never apply its
53786
+ // result to a different thread's view.
53787
+ const compactedThreadId = threadId;
53788
+ const stillCurrent = ()=>compactedThreadId !== null && currentThreadIdRef.current === compactedThreadId;
53789
+ if (result.compacted && compactedThreadId !== null && stillCurrent()) {
53473
53790
  // Server moved the hot/warm pin to just after the last existing
53474
53791
  // message and persisted the warm summary. Mirror that in-place so
53475
53792
  // the warm card shows the fresh summary without wiping the visible
@@ -53481,16 +53798,29 @@ function ChatView({ threadId, agentId, sessionLoading, sessionError, onMessageSe
53481
53798
  thread.metaApplier.setWarmSummary(result.warm_summary ?? null);
53482
53799
  thread.metaApplier.setWarmSummaryBefore(result.warm_summary_before ?? null);
53483
53800
  thread.metaApplier.setWarmSummaryBeforeSeq(result.warm_summary_before_seq ?? null);
53484
- thread.metaApplier.setWarmSummaryBeforeSeq(result.warm_summary_before_seq ?? null);
53485
53801
  thread.metaApplier.setWarmSummaryComputedAt(result.warm_summary_computed_at ?? null);
53486
53802
  thread.metaApplier.setWarmSummarySourceMessages(result.warm_summary_source_messages ?? null);
53487
53803
  thread.metaApplier.setWarmSummarySourceChars(result.warm_summary_source_chars ?? null);
53488
53804
  thread.metaApplier.setWarmSummaryTopics?.(parseWarmSummaryTopics(result.warm_summary_topics));
53489
- } else {
53490
- thread.addNotice("Nothing to compact yet — send some messages first.");
53491
- }
53805
+ // The compact response carries only the chat recap; channel recaps
53806
+ // (bridge, watcher, scheduled task) come with the thread metadata.
53807
+ void client/* api */.FH.threads.get(compactedThreadId, {
53808
+ limit: 1
53809
+ }).then((d)=>{
53810
+ if (stillCurrent()) applyThreadMeta(thread.metaApplier, d);
53811
+ }).catch(()=>{});
53812
+ }
53813
+ notifyCompaction(result);
53492
53814
  } catch (err) {
53493
- thread.addNotice(`Compaction failed: ${String(err)}`);
53815
+ (0,error_report/* pushErrorToast */.uS)({
53816
+ title: "Compaction failed",
53817
+ error: err,
53818
+ context: {
53819
+ panel: "chat",
53820
+ action: "compact",
53821
+ agent_id: agentId
53822
+ }
53823
+ });
53494
53824
  } finally{
53495
53825
  setCompacting(false);
53496
53826
  queue.drainQueueRef.current();
@@ -53516,7 +53846,6 @@ function ChatView({ threadId, agentId, sessionLoading, sessionError, onMessageSe
53516
53846
  threadId: threadId,
53517
53847
  messages: thread.messages,
53518
53848
  steeredSegments: sse.steeredSegments,
53519
- notices: thread.notices,
53520
53849
  agentConfig: agentConfig,
53521
53850
  userProfile: userProfile,
53522
53851
  // streamingContent stays visible past `streaming=false` so the bubble
@@ -53543,8 +53872,9 @@ function ChatView({ threadId, agentId, sessionLoading, sessionError, onMessageSe
53543
53872
  warmSummarySourceMessages: thread.warmSummarySourceMessages,
53544
53873
  warmSummarySourceChars: thread.warmSummarySourceChars,
53545
53874
  warmSummaryTopics: thread.warmSummaryTopics,
53875
+ warmChannelSummaries: thread.warmChannelSummaries,
53546
53876
  warmSummaryPending: thread.warmSummaryPending,
53547
- compactionPending: thread.compactionPending || compacting,
53877
+ compactionPending: thread.compactionPending || sessionCompacting,
53548
53878
  onSetContextPin: thread.setContextPin,
53549
53879
  streaming: sse.streaming,
53550
53880
  contextWindowTokens: thread.contextWindowTokens,
@@ -53572,7 +53902,7 @@ function ChatView({ threadId, agentId, sessionLoading, sessionError, onMessageSe
53572
53902
  onVoiceTranscript: handleVoiceTranscript,
53573
53903
  disabled: !agentId,
53574
53904
  placeholder: composerPlaceholder({
53575
- compacting,
53905
+ compacting: sessionCompacting,
53576
53906
  sessionLoading: !!sessionLoading,
53577
53907
  streaming: sse.streaming
53578
53908
  })
@@ -53618,6 +53948,51 @@ const ArrowUpRight = (0,createLucideIcon/* default */.A)(arrow_up_right_iconData
53618
53948
 
53619
53949
  // EXTERNAL MODULE: ./node_modules/lucide-react/dist/esm/icons/star.mjs
53620
53950
  var star = __webpack_require__(53053);
53951
+ ;// ./node_modules/lucide-react/dist/esm/icons/power-off.mjs
53952
+ /**
53953
+ * @license lucide-react v1.47.0 - ISC
53954
+ *
53955
+ * This source code is licensed under the ISC license.
53956
+ * See the LICENSE file in the root directory of this source tree.
53957
+ */
53958
+ const power_off_iconData = {
53959
+ name: "power-off",
53960
+ size: 24,
53961
+ node: [
53962
+ [
53963
+ "path",
53964
+ {
53965
+ d: "M18.36 6.64A9 9 0 0 1 20.77 15",
53966
+ key: "dxknvb"
53967
+ }
53968
+ ],
53969
+ [
53970
+ "path",
53971
+ {
53972
+ d: "M6.16 6.16a9 9 0 1 0 12.68 12.68",
53973
+ key: "1x7qb5"
53974
+ }
53975
+ ],
53976
+ [
53977
+ "path",
53978
+ {
53979
+ d: "M12 2v4",
53980
+ key: "3427ic"
53981
+ }
53982
+ ],
53983
+ [
53984
+ "path",
53985
+ {
53986
+ d: "m2 2 20 20",
53987
+ key: "1ooewy"
53988
+ }
53989
+ ]
53990
+ ]
53991
+ };
53992
+ power_off_iconData.node;
53993
+ const PowerOff = (0,createLucideIcon/* default */.A)(power_off_iconData);
53994
+ //# sourceMappingURL=power-off.mjs.map
53995
+
53621
53996
  // EXTERNAL MODULE: ./node_modules/lucide-react/dist/esm/icons/trash.mjs
53622
53997
  var trash = __webpack_require__(61422);
53623
53998
  ;// ./components/ui/PanelHeader.tsx
@@ -53699,6 +54074,24 @@ function useModels() {
53699
54074
  }, [
53700
54075
  refreshModels
53701
54076
  ]);
54077
+ const setDefault = (0,react.useCallback)(async (name)=>{
54078
+ const m = await client/* api */.FH.models.patch(name, {
54079
+ is_default: true
54080
+ });
54081
+ await refreshModels();
54082
+ return m;
54083
+ }, [
54084
+ refreshModels
54085
+ ]);
54086
+ const setEnabled = (0,react.useCallback)(async (name, enabled)=>{
54087
+ const m = await client/* api */.FH.models.patch(name, {
54088
+ enabled
54089
+ });
54090
+ await refreshModels();
54091
+ return m;
54092
+ }, [
54093
+ refreshModels
54094
+ ]);
53702
54095
  const remove = (0,react.useCallback)(async (name)=>{
53703
54096
  await client/* api */.FH.models.delete(name);
53704
54097
  await refreshModels();
@@ -53736,6 +54129,8 @@ function useModels() {
53736
54129
  refresh,
53737
54130
  create,
53738
54131
  update,
54132
+ setDefault,
54133
+ setEnabled,
53739
54134
  remove,
53740
54135
  assign,
53741
54136
  unassign
@@ -53750,6 +54145,8 @@ function useModels() {
53750
54145
  refresh,
53751
54146
  create,
53752
54147
  update,
54148
+ setDefault,
54149
+ setEnabled,
53753
54150
  remove,
53754
54151
  assign,
53755
54152
  unassign
@@ -54260,7 +54657,7 @@ const PROVIDER_COLORS = {
54260
54657
  "github-copilot": "bg-purple-900/40 text-purple-300 border-purple-700"
54261
54658
  };
54262
54659
  function ModelsPanel() {
54263
- const { models, assignments, loading, create, update, remove, refresh } = useModels();
54660
+ const { models, assignments, loading, create, update, setDefault, setEnabled, remove, refresh } = useModels();
54264
54661
  const { agents, loading: agentsLoading } = useAgents();
54265
54662
  const strategyOverrides = agents.filter((agent)=>agent.usage_strategy != null);
54266
54663
  const [editing, setEditing] = (0,react.useState)(null);
@@ -54308,12 +54705,20 @@ function ModelsPanel() {
54308
54705
  refresh();
54309
54706
  }
54310
54707
  async function handleSetDefault(m) {
54311
- await update(m.name, {
54312
- provider: m.provider,
54313
- model_id: m.model_id,
54314
- params: m.params,
54315
- is_default: true
54316
- });
54708
+ setDeleteError(null);
54709
+ try {
54710
+ await setDefault(m.name);
54711
+ } catch (e) {
54712
+ setDeleteError(`Could not set "${m.name}" as default: ${(0,utils_error/* errorMessage */.g)(e)}`);
54713
+ }
54714
+ }
54715
+ async function handleToggleEnabled(m) {
54716
+ setDeleteError(null);
54717
+ try {
54718
+ await setEnabled(m.name, !m.enabled);
54719
+ } catch (e) {
54720
+ setDeleteError(`Could not ${m.enabled ? "disable" : "enable"} "${m.name}": ${(0,utils_error/* errorMessage */.g)(e)}`);
54721
+ }
54317
54722
  }
54318
54723
  async function handleRemove(name) {
54319
54724
  const affectedAgents = assignments.filter((assignment)=>assignment.model_config_name === name).map((assignment)=>agents.find((agent)=>agent.id === assignment.agent_id)?.name ?? assignment.agent_id);
@@ -54589,7 +54994,7 @@ function ModelsPanel() {
54589
54994
  return /*#__PURE__*/ (0,react_jsx_runtime.jsxs)("div", {
54590
54995
  "data-deep-link-id": m.name,
54591
54996
  onClick: ()=>setEditing(m),
54592
- className: "flex items-center gap-3 py-2.5 border-b border-border/60 group cursor-pointer hover:bg-surface-3/30 transition-colors",
54997
+ className: `flex items-center gap-3 py-2.5 border-b border-border/60 group cursor-pointer hover:bg-surface-3/30 transition-colors ${m.enabled ? "" : "opacity-60"}`,
54593
54998
  children: [
54594
54999
  /*#__PURE__*/ (0,react_jsx_runtime.jsx)("span", {
54595
55000
  className: "shrink-0 text-fg-subtle",
@@ -54605,13 +55010,17 @@ function ModelsPanel() {
54605
55010
  className: "flex items-center gap-2 mb-0.5",
54606
55011
  children: [
54607
55012
  /*#__PURE__*/ (0,react_jsx_runtime.jsx)("span", {
54608
- className: "text-sm font-medium text-fg",
55013
+ className: `text-sm font-medium ${m.enabled ? "text-fg" : "text-fg-subtle line-through"}`,
54609
55014
  children: m.name
54610
55015
  }),
54611
55016
  m.is_default && /*#__PURE__*/ (0,react_jsx_runtime.jsx)(star/* default */.A, {
54612
55017
  size: 11,
54613
55018
  className: "text-yellow-700 dark:text-yellow-400 fill-yellow-400 shrink-0"
54614
55019
  }),
55020
+ !m.enabled && /*#__PURE__*/ (0,react_jsx_runtime.jsx)("span", {
55021
+ className: "text-xs px-1.5 py-0.5 rounded border bg-surface-2 text-fg-muted border-border",
55022
+ children: "disabled"
55023
+ }),
54615
55024
  /*#__PURE__*/ (0,react_jsx_runtime.jsx)("span", {
54616
55025
  className: `text-xs px-1.5 py-0.5 rounded border ${PROVIDER_COLORS[m.provider] ?? "bg-surface-2 text-fg-muted border-border"}`,
54617
55026
  children: m.provider
@@ -54634,10 +55043,10 @@ function ModelsPanel() {
54634
55043
  /*#__PURE__*/ (0,react_jsx_runtime.jsxs)("div", {
54635
55044
  className: "flex gap-1 opacity-40 group-hover:opacity-100 pointer-coarse:opacity-100 transition-opacity shrink-0",
54636
55045
  children: [
54637
- !m.is_default && /*#__PURE__*/ (0,react_jsx_runtime.jsx)("button", {
55046
+ !m.is_default && m.enabled && /*#__PURE__*/ (0,react_jsx_runtime.jsx)("button", {
54638
55047
  onClick: (e)=>{
54639
55048
  e.stopPropagation();
54640
- handleSetDefault(m);
55049
+ void handleSetDefault(m);
54641
55050
  },
54642
55051
  className: "p-1 text-fg-subtle hover:text-yellow-700 dark:hover:text-yellow-400 transition-colors",
54643
55052
  title: "Set as default",
@@ -54645,6 +55054,21 @@ function ModelsPanel() {
54645
55054
  size: 13
54646
55055
  })
54647
55056
  }),
55057
+ /*#__PURE__*/ (0,react_jsx_runtime.jsx)("button", {
55058
+ onClick: (e)=>{
55059
+ e.stopPropagation();
55060
+ void handleToggleEnabled(m);
55061
+ },
55062
+ className: "p-1 text-fg-subtle hover:text-fg transition-colors",
55063
+ title: m.enabled ? "Disable; hide from model selection" : "Enable; show in model selection",
55064
+ "aria-label": m.enabled ? `Disable ${m.name}` : `Enable ${m.name}`,
55065
+ "aria-pressed": !m.enabled,
55066
+ children: m.enabled ? /*#__PURE__*/ (0,react_jsx_runtime.jsx)(Power, {
55067
+ size: 13
55068
+ }) : /*#__PURE__*/ (0,react_jsx_runtime.jsx)(PowerOff, {
55069
+ size: 13
55070
+ })
55071
+ }),
54648
55072
  /*#__PURE__*/ (0,react_jsx_runtime.jsx)("button", {
54649
55073
  onClick: (e)=>{
54650
55074
  e.stopPropagation();
@@ -62750,7 +63174,7 @@ function RouteTable({ bridge_id, module }) {
62750
63174
  client/* api */.FH.models.list().then(setModels).catch(()=>{});
62751
63175
  }, []);
62752
63176
  /** Vision capability of an agent (resolves via its model_config_name, with default fallback). */ function agentVisionState(a) {
62753
- const cfg = resolveAgentModel(a, models);
63177
+ const cfg = (0,effective_model/* resolveAgentModel */.Fu)(a, models);
62754
63178
  if (!cfg) return {
62755
63179
  supported: false,
62756
63180
  classified: false,
@@ -68154,7 +68578,7 @@ function WatcherCard({ watcher, agent, agents, models, onCancel, onRunNow, onCha
68154
68578
  const overdue = !watcher.last_error && new Date(watcher.next_run_at).getTime() < Date.now() - 60000;
68155
68579
  // Pre-flight model availability for the assigned agent; only relevant
68156
68580
  // when the watcher reacts via an agent prompt (not a pure script).
68157
- const modelStatus = watcher.reaction_kind === "agent_prompt" ? agentModelStatus(agent ?? null, models) : null;
68581
+ const modelStatus = watcher.reaction_kind === "agent_prompt" ? (0,effective_model/* agentModelStatus */.xu)(agent ?? null, models) : null;
68158
68582
  return /*#__PURE__*/ (0,react_jsx_runtime.jsxs)("div", {
68159
68583
  "data-deep-link-id": watcher.id,
68160
68584
  className: "mb-2 rounded-lg border border-border bg-surface-2 overflow-hidden",
@@ -68886,7 +69310,7 @@ function TaskCard({ task, agent, agents, models, onCancel, onRunNow, onChanged }
68886
69310
  collapseSeconds: true
68887
69311
  });
68888
69312
  const overdue = !task.last_error && new Date(task.next_run_at).getTime() < Date.now() - 60000;
68889
- const modelStatus = task.reaction_kind === "agent_prompt" ? agentModelStatus(agent ?? null, models) : null;
69313
+ const modelStatus = task.reaction_kind === "agent_prompt" ? (0,effective_model/* agentModelStatus */.xu)(agent ?? null, models) : null;
68890
69314
  return /*#__PURE__*/ (0,react_jsx_runtime.jsxs)("div", {
68891
69315
  "data-deep-link-id": task.id,
68892
69316
  className: "mb-2 rounded-lg border border-border bg-surface-2 overflow-hidden group",
@@ -73763,6 +74187,22 @@ function BootScreen({ agents, agentsLoaded, activeAgentId, onPickAgent, suppress
73763
74187
  setAdoptionBusy(null);
73764
74188
  }
73765
74189
  }
74190
+ async function handleAdoptionItemRetry(itemId) {
74191
+ if (adoptionBusy || adoption?.status === "running") return;
74192
+ setAdoptionBusy("retry");
74193
+ try {
74194
+ const next = await client/* api */.FH.lifecycle.adoption.retryItem(itemId);
74195
+ setAdoption(next);
74196
+ adoptionRunStartedRef.current = null;
74197
+ } catch {
74198
+ setAdoption((prev)=>prev ? {
74199
+ ...prev,
74200
+ error: "Could not retry that step."
74201
+ } : prev);
74202
+ } finally{
74203
+ setAdoptionBusy(null);
74204
+ }
74205
+ }
73766
74206
  // The agent rendered in the centered tile. During `loading` and
73767
74207
  // `pick` it's the default (so the user sees the same artwork as soon
73768
74208
  // as agents resolve). During `opening` it's whatever was picked.
@@ -73905,6 +74345,9 @@ function BootScreen({ agents, agentsLoaded, activeAgentId, onPickAgent, suppress
73905
74345
  summary: adoptionLiveLabel ?? adoption.summary,
73906
74346
  items: adoption.checklist,
73907
74347
  error: adoption.error,
74348
+ onRetryItem: (item)=>void handleAdoptionItemRetry(item.id),
74349
+ canRetryItem: (item)=>item.id !== "fetch-changes",
74350
+ retryDisabled: adoptionBusy !== null || adoption.status === "running",
73908
74351
  children: [
73909
74352
  adoption.status === "done" && /*#__PURE__*/ (0,react_jsx_runtime.jsx)("p", {
73910
74353
  className: "mt-2 rounded-lg border border-border/50 bg-surface px-2 py-1 text-[10px] leading-snug text-fg-muted",
@@ -77532,6 +77975,14 @@ function AppShell() {
77532
77975
  }
77533
77976
 
77534
77977
 
77978
+ /***/ }),
77979
+
77980
+ /***/ 94735:
77981
+ /***/ ((module) => {
77982
+
77983
+ "use strict";
77984
+ module.exports = require("events");
77985
+
77535
77986
  /***/ }),
77536
77987
 
77537
77988
  /***/ 99253:
@@ -77596,7 +78047,7 @@ function Home() {
77596
78047
  var __webpack_require__ = require("../webpack-runtime.js");
77597
78048
  __webpack_require__.C(exports);
77598
78049
  var __webpack_exec__ = (moduleId) => (__webpack_require__(__webpack_require__.s = moduleId))
77599
- var __webpack_exports__ = __webpack_require__.X(0, [2970,7377,7981,2430,1427,4992,46,2653,466], () => (__webpack_exec__(3067)));
78050
+ var __webpack_exports__ = __webpack_require__.X(0, [2970,7377,7981,2430,1427,4992,46,2653,466], () => (__webpack_exec__(13297)));
77600
78051
  module.exports = __webpack_exports__;
77601
78052
 
77602
78053
  })();