@circuitwall/jarela 2.2.1 → 2.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (651) hide show
  1. package/.next/standalone/.next/BUILD_ID +1 -1
  2. package/.next/standalone/.next/app-path-routes-manifest.json +6 -5
  3. package/.next/standalone/.next/build-manifest.json +2 -2
  4. package/.next/standalone/.next/prerender-manifest.json +3 -3
  5. package/.next/standalone/.next/routes-manifest.json +8 -0
  6. package/.next/standalone/.next/server/app/_global-error/page.js +68 -68
  7. package/.next/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  8. package/.next/standalone/.next/server/app/_global-error.html +1 -1
  9. package/.next/standalone/.next/server/app/_global-error.rsc +1 -1
  10. package/.next/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  11. package/.next/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  12. package/.next/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  13. package/.next/standalone/.next/server/app/_not-found/page.js +76 -76
  14. package/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  15. package/.next/standalone/.next/server/app/_not-found.html +2 -2
  16. package/.next/standalone/.next/server/app/_not-found.rsc +2 -2
  17. package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +2 -2
  18. package/.next/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +2 -2
  19. package/.next/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  20. package/.next/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  21. package/.next/standalone/.next/server/app/api/v1/access/[identity]/route.js +93 -93
  22. package/.next/standalone/.next/server/app/api/v1/access/route.js +169 -169
  23. package/.next/standalone/.next/server/app/api/v1/agents/[id]/compact/route.js +82 -56
  24. package/.next/standalone/.next/server/app/api/v1/agents/[id]/compact/route.js.nft.json +1 -1
  25. package/.next/standalone/.next/server/app/api/v1/agents/[id]/display-filters/route.js +122 -122
  26. package/.next/standalone/.next/server/app/api/v1/agents/[id]/route.js +100 -100
  27. package/.next/standalone/.next/server/app/api/v1/agents/[id]/thread/route.js +753 -753
  28. package/.next/standalone/.next/server/app/api/v1/agents/route.js +65 -65
  29. package/.next/standalone/.next/server/app/api/v1/allowed-sites/[hostname]/route.js +364 -364
  30. package/.next/standalone/.next/server/app/api/v1/allowed-sites/route.js +802 -802
  31. package/.next/standalone/.next/server/app/api/v1/artifacts/lifecycle/route.js +2 -2
  32. package/.next/standalone/.next/server/app/api/v1/attachments/files/route.js +49 -49
  33. package/.next/standalone/.next/server/app/api/v1/attachments/images/route.js +910 -910
  34. package/.next/standalone/.next/server/app/api/v1/bridges/[id]/chats/route.js +589 -16
  35. package/.next/standalone/.next/server/app/api/v1/bridges/[id]/chats/route.js.nft.json +1 -1
  36. package/.next/standalone/.next/server/app/api/v1/bridges/[id]/ignores/[remote_jid]/route.js +23 -23
  37. package/.next/standalone/.next/server/app/api/v1/bridges/[id]/ignores/route.js +30 -30
  38. package/.next/standalone/.next/server/app/api/v1/bridges/[id]/lookup/route.js +703 -130
  39. package/.next/standalone/.next/server/app/api/v1/bridges/[id]/lookup/route.js.nft.json +1 -1
  40. package/.next/standalone/.next/server/app/api/v1/bridges/[id]/pair/route.js +708 -135
  41. package/.next/standalone/.next/server/app/api/v1/bridges/[id]/pair/route.js.nft.json +1 -1
  42. package/.next/standalone/.next/server/app/api/v1/bridges/[id]/route.js +802 -229
  43. package/.next/standalone/.next/server/app/api/v1/bridges/[id]/route.js.nft.json +1 -1
  44. package/.next/standalone/.next/server/app/api/v1/bridges/[id]/routes/[route_id]/route.js +739 -739
  45. package/.next/standalone/.next/server/app/api/v1/bridges/[id]/routes/route.js +1035 -1035
  46. package/.next/standalone/.next/server/app/api/v1/bridges/[id]/status/route.js +679 -106
  47. package/.next/standalone/.next/server/app/api/v1/bridges/[id]/status/route.js.nft.json +1 -1
  48. package/.next/standalone/.next/server/app/api/v1/bridges/kinds/route.js +804 -804
  49. package/.next/standalone/.next/server/app/api/v1/bridges/route.js +700 -700
  50. package/.next/standalone/.next/server/app/api/v1/builtin-tools/route.js +9 -9
  51. package/.next/standalone/.next/server/app/api/v1/builtin-tools/route.js.nft.json +1 -1
  52. package/.next/standalone/.next/server/app/api/v1/config/route.js +85 -85
  53. package/.next/standalone/.next/server/app/api/v1/credentials/[id]/route.js +709 -709
  54. package/.next/standalone/.next/server/app/api/v1/credentials/[id]/route.js.nft.json +1 -1
  55. package/.next/standalone/.next/server/app/api/v1/credentials/route.js +2 -2
  56. package/.next/standalone/.next/server/app/api/v1/credentials/route.js.nft.json +1 -1
  57. package/.next/standalone/.next/server/app/api/v1/dashboard/currency/route.js +10 -10
  58. package/.next/standalone/.next/server/app/api/v1/dashboard/metrics/route.js +784 -784
  59. package/.next/standalone/.next/server/app/api/v1/dashboard/pricing/route.js +23 -23
  60. package/.next/standalone/.next/server/app/api/v1/dashboard/pricing-task/route.js +86 -86
  61. package/.next/standalone/.next/server/app/api/v1/dashboard/pricing-task/route.js.nft.json +1 -1
  62. package/.next/standalone/.next/server/app/api/v1/delegations/codex/[job_id]/route.js +57 -57
  63. package/.next/standalone/.next/server/app/api/v1/delegations/codex/[job_id]/route.js.nft.json +1 -1
  64. package/.next/standalone/.next/server/app/api/v1/documents/search/route.js +523 -523
  65. package/.next/standalone/.next/server/app/api/v1/documents/settings/route.js +44 -44
  66. package/.next/standalone/.next/server/app/api/v1/documents/sources/[id]/reindex/route.js +65 -65
  67. package/.next/standalone/.next/server/app/api/v1/documents/sources/[id]/reindex/route.js.nft.json +1 -1
  68. package/.next/standalone/.next/server/app/api/v1/documents/sources/[id]/route.js +122 -122
  69. package/.next/standalone/.next/server/app/api/v1/documents/sources/[id]/route.js.nft.json +1 -1
  70. package/.next/standalone/.next/server/app/api/v1/documents/sources/route.js +37 -37
  71. package/.next/standalone/.next/server/app/api/v1/documents/sources/route.js.nft.json +1 -1
  72. package/.next/standalone/.next/server/app/api/v1/env/route.js +9 -9
  73. package/.next/standalone/.next/server/app/api/v1/env-sync/allowlist/route.js +368 -368
  74. package/.next/standalone/.next/server/app/api/v1/env-sync/route.js +44 -44
  75. package/.next/standalone/.next/server/app/api/v1/events/route.js +751 -178
  76. package/.next/standalone/.next/server/app/api/v1/events/route.js.nft.json +1 -1
  77. package/.next/standalone/.next/server/app/api/v1/events/test/route.js +77 -77
  78. package/.next/standalone/.next/server/app/api/v1/extension/agents/route.js +763 -763
  79. package/.next/standalone/.next/server/app/api/v1/extension/agents/route.js.nft.json +1 -1
  80. package/.next/standalone/.next/server/app/api/v1/extension/browser/activate/route.js +44 -44
  81. package/.next/standalone/.next/server/app/api/v1/extension/browser/foreground/route.js +9 -9
  82. package/.next/standalone/.next/server/app/api/v1/extension/browser/history/route.js +65 -65
  83. package/.next/standalone/.next/server/app/api/v1/extension/browser/poll/route.js +34 -34
  84. package/.next/standalone/.next/server/app/api/v1/extension/browser/progress/route.js +204 -204
  85. package/.next/standalone/.next/server/app/api/v1/extension/browser/result/route.js +133 -133
  86. package/.next/standalone/.next/server/app/api/v1/extension/browser/retry/route.js +106 -106
  87. package/.next/standalone/.next/server/app/api/v1/extension/browser/status/route.js +114 -114
  88. package/.next/standalone/.next/server/app/api/v1/extension/browser/tabs/route.js +134 -134
  89. package/.next/standalone/.next/server/app/api/v1/extension/fill/route.js +690 -690
  90. package/.next/standalone/.next/server/app/api/v1/extension/fill/route.js.nft.json +1 -1
  91. package/.next/standalone/.next/server/app/api/v1/extension/refine/route.js +93 -93
  92. package/.next/standalone/.next/server/app/api/v1/extension/refine/route.js.nft.json +1 -1
  93. package/.next/standalone/.next/server/app/api/v1/extension/turn/route.js +9 -9
  94. package/.next/standalone/.next/server/app/api/v1/extension/turn/route.js.nft.json +1 -1
  95. package/.next/standalone/.next/server/app/api/v1/extensions/route.js +185 -185
  96. package/.next/standalone/.next/server/app/api/v1/extensions/route.js.nft.json +1 -1
  97. package/.next/standalone/.next/server/app/api/v1/extensions/tools/[name]/config/route.js +171 -171
  98. package/.next/standalone/.next/server/app/api/v1/extensions/tools/[name]/config/route.js.nft.json +1 -1
  99. package/.next/standalone/.next/server/app/api/v1/extensions/tools/[name]/route.js +396 -396
  100. package/.next/standalone/.next/server/app/api/v1/extensions/tools/[name]/route.js.nft.json +1 -1
  101. package/.next/standalone/.next/server/app/api/v1/extensions/tools/[name]/secrets/route.js +212 -212
  102. package/.next/standalone/.next/server/app/api/v1/extensions/tools/[name]/secrets/route.js.nft.json +1 -1
  103. package/.next/standalone/.next/server/app/api/v1/files/[name]/route.js +235 -235
  104. package/.next/standalone/.next/server/app/api/v1/fs/browse/route.js +26 -26
  105. package/.next/standalone/.next/server/app/api/v1/harnesses/[id]/route.js +221 -221
  106. package/.next/standalone/.next/server/app/api/v1/harnesses/default/route.js +58 -58
  107. package/.next/standalone/.next/server/app/api/v1/harnesses/route.js +72 -72
  108. package/.next/standalone/.next/server/app/api/v1/health/probes/route.js +9 -9
  109. package/.next/standalone/.next/server/app/api/v1/health/probes/route.js.nft.json +1 -1
  110. package/.next/standalone/.next/server/app/api/v1/health/route.js +772 -772
  111. package/.next/standalone/.next/server/app/api/v1/integrations/[name]/route.js +133 -133
  112. package/.next/standalone/.next/server/app/api/v1/integrations/[name]/test/route.js +9 -9
  113. package/.next/standalone/.next/server/app/api/v1/integrations/[name]/test/route.js.nft.json +1 -1
  114. package/.next/standalone/.next/server/app/api/v1/integrations/gmail/oauth/callback/route.js +363 -363
  115. package/.next/standalone/.next/server/app/api/v1/integrations/gmail/oauth/start/route.js +233 -233
  116. package/.next/standalone/.next/server/app/api/v1/integrations/gmail/oauth/status/route.js +682 -682
  117. package/.next/standalone/.next/server/app/api/v1/integrations/outlook/oauth/callback/route.js +879 -879
  118. package/.next/standalone/.next/server/app/api/v1/integrations/outlook/oauth/start/route.js +108 -108
  119. package/.next/standalone/.next/server/app/api/v1/integrations/outlook/oauth/status/route.js +952 -952
  120. package/.next/standalone/.next/server/app/api/v1/integrations/route.js +216 -216
  121. package/.next/standalone/.next/server/app/api/v1/lifecycle/adoption/route.js +864 -847
  122. package/.next/standalone/.next/server/app/api/v1/lifecycle/adoption/route.js.nft.json +1 -1
  123. package/.next/standalone/.next/server/app/api/v1/local-file/route.js +26 -26
  124. package/.next/standalone/.next/server/app/api/v1/logs/route.js +70 -70
  125. package/.next/standalone/.next/server/app/api/v1/maps/embed/route.js +72 -72
  126. package/.next/standalone/.next/server/app/api/v1/mcp-servers/[name]/route.js +979 -979
  127. package/.next/standalone/.next/server/app/api/v1/mcp-servers/registry/route.js +196 -196
  128. package/.next/standalone/.next/server/app/api/v1/mcp-servers/route.js +2 -2
  129. package/.next/standalone/.next/server/app/api/v1/memory/[namespace]/[key]/route.js +381 -381
  130. package/.next/standalone/.next/server/app/api/v1/memory/policy/route.js +79 -79
  131. package/.next/standalone/.next/server/app/api/v1/memory/route.js +51 -51
  132. package/.next/standalone/.next/server/app/api/v1/memory/search/route.js +131 -131
  133. package/.next/standalone/.next/server/app/api/v1/models/[name]/compact-threads/route.js +374 -369
  134. package/.next/standalone/.next/server/app/api/v1/models/[name]/compact-threads/route.js.nft.json +1 -1
  135. package/.next/standalone/.next/server/app/api/v1/models/[name]/route.js +143 -143
  136. package/.next/standalone/.next/server/app/api/v1/models/route.js +543 -543
  137. package/.next/standalone/.next/server/app/api/v1/packages/catalog/route.js +445 -445
  138. package/.next/standalone/.next/server/app/api/v1/packages/defaults/[id]/route.js +120 -120
  139. package/.next/standalone/.next/server/app/api/v1/packages/defaults/[id]/route.js.nft.json +1 -1
  140. package/.next/standalone/.next/server/app/api/v1/packages/install/[id]/route.js +234 -234
  141. package/.next/standalone/.next/server/app/api/v1/packages/install/[id]/route.js.nft.json +1 -1
  142. package/.next/standalone/.next/server/app/api/v1/packages/install/route.js +407 -407
  143. package/.next/standalone/.next/server/app/api/v1/packages/install/route.js.nft.json +1 -1
  144. package/.next/standalone/.next/server/app/api/v1/packages/manifests/[name]/enabled/route.js +37 -37
  145. package/.next/standalone/.next/server/app/api/v1/packages/manifests/[name]/enabled/route.js.nft.json +1 -1
  146. package/.next/standalone/.next/server/app/api/v1/packages/manifests/[name]/route.js +107 -107
  147. package/.next/standalone/.next/server/app/api/v1/packages/manifests/[name]/route.js.nft.json +1 -1
  148. package/.next/standalone/.next/server/app/api/v1/packages/manifests/route.js +228 -228
  149. package/.next/standalone/.next/server/app/api/v1/packages/manifests/route.js.nft.json +1 -1
  150. package/.next/standalone/.next/server/app/api/v1/packages/reload/route.js +9 -9
  151. package/.next/standalone/.next/server/app/api/v1/packages/reload/route.js.nft.json +1 -1
  152. package/.next/standalone/.next/server/app/api/v1/packages/route.js +148 -148
  153. package/.next/standalone/.next/server/app/api/v1/packages/route.js.nft.json +1 -1
  154. package/.next/standalone/.next/server/app/api/v1/page-capture/route.js +787 -787
  155. package/.next/standalone/.next/server/app/api/v1/page-capture/route.js.nft.json +1 -1
  156. package/.next/standalone/.next/server/app/api/v1/pending-actions/[id]/approve/route.js +507 -507
  157. package/.next/standalone/.next/server/app/api/v1/pending-actions/[id]/approve/route.js.nft.json +1 -1
  158. package/.next/standalone/.next/server/app/api/v1/pending-actions/[id]/deny/route.js +181 -181
  159. package/.next/standalone/.next/server/app/api/v1/pending-actions/[id]/deny/route.js.nft.json +1 -1
  160. package/.next/standalone/.next/server/app/api/v1/pending-actions/route.js +258 -258
  161. package/.next/standalone/.next/server/app/api/v1/pending-actions/route.js.nft.json +1 -1
  162. package/.next/standalone/.next/server/app/api/v1/profile/location/route.js +30 -30
  163. package/.next/standalone/.next/server/app/api/v1/profile/route.js +164 -164
  164. package/.next/standalone/.next/server/app/api/v1/providers/[provider]/models/route.js +44 -44
  165. package/.next/standalone/.next/server/app/api/v1/providers/[provider]/probe/route.js +9 -9
  166. package/.next/standalone/.next/server/app/api/v1/providers/github-copilot/auth/route.js +164 -164
  167. package/.next/standalone/.next/server/app/api/v1/providers/route.js +94 -94
  168. package/.next/standalone/.next/server/app/api/v1/proxy-config/route.js +450 -450
  169. package/.next/standalone/.next/server/app/api/v1/redaction/init/route.js +37 -37
  170. package/.next/standalone/.next/server/app/api/v1/redaction/route.js +58 -58
  171. package/.next/standalone/.next/server/app/api/v1/scheduled-tasks/[id]/route.js +600 -600
  172. package/.next/standalone/.next/server/app/api/v1/scheduled-tasks/[id]/run/route.js +44 -44
  173. package/.next/standalone/.next/server/app/api/v1/scheduled-tasks/[id]/run/route.js.nft.json +1 -1
  174. package/.next/standalone/.next/server/app/api/v1/scheduled-tasks/route.js +732 -732
  175. package/.next/standalone/.next/server/app/api/v1/security/idle-timeout/route.js +359 -359
  176. package/.next/standalone/.next/server/app/api/v1/security/pin/route.js +197 -197
  177. package/.next/standalone/.next/server/app/api/v1/security/state/route.js +51 -51
  178. package/.next/standalone/.next/server/app/api/v1/security/unlock/route.js +176 -176
  179. package/.next/standalone/.next/server/app/api/v1/security/verify-pin/route.js +190 -190
  180. package/.next/standalone/.next/server/app/api/v1/setup/test-key/route.js +26 -26
  181. package/.next/standalone/.next/server/app/api/v1/skills/[id]/route.js +770 -770
  182. package/.next/standalone/.next/server/app/api/v1/skills/repos/[id]/route.js +115 -115
  183. package/.next/standalone/.next/server/app/api/v1/skills/repos/route.js +327 -327
  184. package/.next/standalone/.next/server/app/api/v1/skills/route.js +870 -870
  185. package/.next/standalone/.next/server/app/api/v1/system/abort/route.js +838 -808
  186. package/.next/standalone/.next/server/app/api/v1/system/restart/route.js +177 -177
  187. package/.next/standalone/.next/server/app/api/v1/system/restart/route.js.nft.json +1 -1
  188. package/.next/standalone/.next/server/app/api/v1/tailscale/route.js +164 -164
  189. package/.next/standalone/.next/server/app/api/v1/tasks/[agent_id]/route.js +115 -115
  190. package/.next/standalone/.next/server/app/api/v1/tasks/route.js +23 -23
  191. package/.next/standalone/.next/server/app/api/v1/threads/[thread_id]/activity/route.js +1429 -0
  192. package/.next/standalone/.next/server/app/api/v1/threads/[thread_id]/activity/route.js.nft.json +1 -0
  193. package/.next/standalone/.next/server/app/api/v1/threads/[thread_id]/activity/route_client-reference-manifest.js +1 -0
  194. package/.next/standalone/.next/server/app/api/v1/threads/[thread_id]/context-pin/route.js +635 -634
  195. package/.next/standalone/.next/server/app/api/v1/threads/[thread_id]/context-pin/route.js.nft.json +1 -1
  196. package/.next/standalone/.next/server/app/api/v1/threads/[thread_id]/route.js +53 -439
  197. package/.next/standalone/.next/server/app/api/v1/threads/[thread_id]/route.js.nft.json +1 -1
  198. package/.next/standalone/.next/server/app/api/v1/threads/[thread_id]/run/route.js +172 -172
  199. package/.next/standalone/.next/server/app/api/v1/threads/[thread_id]/run/route.js.nft.json +1 -1
  200. package/.next/standalone/.next/server/app/api/v1/threads/route.js +908 -908
  201. package/.next/standalone/.next/server/app/api/v1/tools/route.js +2 -2
  202. package/.next/standalone/.next/server/app/api/v1/tools/route.js.nft.json +1 -1
  203. package/.next/standalone/.next/server/app/api/v1/update/apply/route.js +17 -17
  204. package/.next/standalone/.next/server/app/api/v1/update/apply/route.js.nft.json +1 -1
  205. package/.next/standalone/.next/server/app/api/v1/update/route.js +570 -570
  206. package/.next/standalone/.next/server/app/api/v1/voice/transcribe/route.js +224 -224
  207. package/.next/standalone/.next/server/app/api/v1/voice/tts/route.js +975 -975
  208. package/.next/standalone/.next/server/app/api/v1/watchers/[id]/route.js +23 -23
  209. package/.next/standalone/.next/server/app/api/v1/watchers/[id]/run/route.js +72 -72
  210. package/.next/standalone/.next/server/app/api/v1/watchers/[id]/run/route.js.nft.json +1 -1
  211. package/.next/standalone/.next/server/app/api/v1/watchers/reaction-scripts/route.js +128 -128
  212. package/.next/standalone/.next/server/app/api/v1/watchers/route.js +164 -164
  213. package/.next/standalone/.next/server/app/api/v1/watchers/route.js.nft.json +1 -1
  214. package/.next/standalone/.next/server/app/icon.svg/route.js +62 -62
  215. package/.next/standalone/.next/server/app/manifest.webmanifest/route.js +436 -436
  216. package/.next/standalone/.next/server/app/page.js +1243 -854
  217. package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  218. package/.next/standalone/.next/server/app/setup/page.js +91 -91
  219. package/.next/standalone/.next/server/app/setup/page_client-reference-manifest.js +1 -1
  220. package/.next/standalone/.next/server/app-paths-manifest.json +6 -5
  221. package/.next/standalone/.next/server/chunks/{424.js → 1388.js} +335 -986
  222. package/.next/standalone/.next/server/chunks/1433.js +1 -1
  223. package/.next/standalone/.next/server/chunks/1638.js +1 -2
  224. package/.next/standalone/.next/server/chunks/1738.js +1 -1
  225. package/.next/standalone/.next/server/chunks/210.js +6 -6
  226. package/.next/standalone/.next/server/chunks/2151.js +31 -1
  227. package/.next/standalone/.next/server/chunks/2207.js +1 -0
  228. package/.next/standalone/.next/server/chunks/2471.js +28 -28
  229. package/.next/standalone/.next/server/chunks/2504.js +1 -1
  230. package/.next/standalone/.next/server/chunks/2695.js +17 -17
  231. package/.next/standalone/.next/server/chunks/3042.js +14 -8
  232. package/.next/standalone/.next/server/chunks/3399.js +1 -1
  233. package/.next/standalone/.next/server/chunks/3566.js +1 -1
  234. package/.next/standalone/.next/server/chunks/4189.js +946 -0
  235. package/.next/standalone/.next/server/chunks/{9590.js → 423.js} +8 -3
  236. package/.next/standalone/.next/server/chunks/4433.js +146 -146
  237. package/.next/standalone/.next/server/chunks/4508.js +1 -1
  238. package/.next/standalone/.next/server/chunks/4588.js +1 -0
  239. package/.next/standalone/.next/server/chunks/46.js +5 -0
  240. package/.next/standalone/.next/server/chunks/466.js +12 -0
  241. package/.next/standalone/.next/server/chunks/4868.js +206 -206
  242. package/.next/standalone/.next/server/chunks/4992.js +13 -0
  243. package/.next/standalone/.next/server/chunks/5120.js +963 -0
  244. package/.next/standalone/.next/server/chunks/5701.js +1 -1
  245. package/.next/standalone/.next/server/chunks/5900.js +1 -1
  246. package/.next/standalone/.next/server/chunks/6210.js +1 -0
  247. package/.next/standalone/.next/server/chunks/6213.js +1 -1
  248. package/.next/standalone/.next/server/chunks/6649.js +2 -2
  249. package/.next/standalone/.next/server/chunks/6703.js +3 -3
  250. package/.next/standalone/.next/server/chunks/7445.js +1 -0
  251. package/.next/standalone/.next/server/chunks/8067.js +12 -0
  252. package/.next/standalone/.next/server/chunks/8461.js +14 -9
  253. package/.next/standalone/.next/server/chunks/8558.js +1 -1
  254. package/.next/standalone/.next/server/chunks/8724.js +1 -1
  255. package/.next/standalone/.next/server/chunks/8849.js +91 -91
  256. package/.next/standalone/.next/server/chunks/9032.js +6 -5
  257. package/.next/standalone/.next/server/chunks/{2563.js → 9164.js} +33173 -31461
  258. package/.next/standalone/.next/server/chunks/9237.js +396 -396
  259. package/.next/standalone/.next/server/chunks/{9640.js → 9304.js} +1628 -570
  260. package/.next/standalone/.next/server/chunks/9406.js +1 -1
  261. package/.next/standalone/.next/server/chunks/9824.js +98 -98
  262. package/.next/standalone/.next/server/chunks/9826.js +1 -0
  263. package/.next/standalone/.next/server/middleware-build-manifest.js +2 -2
  264. package/.next/standalone/.next/server/middleware.js +415 -397
  265. package/.next/standalone/.next/server/pages/404.html +2 -2
  266. package/.next/standalone/.next/server/pages/500.html +1 -1
  267. package/.next/standalone/.next/server/preview-props.json +3 -3
  268. package/.next/standalone/.next/server/server-reference-manifest.json +1 -1
  269. package/.next/standalone/.next/static/chunks/{1395-a340fb0a345382a4.js → 1395-e4a99912b8f83044.js} +13 -1
  270. package/.next/standalone/.next/static/chunks/app/_global-error/{page-36cb8b428b38b26a.js → page-6fc5f8e744c81802.js} +1 -1
  271. package/.next/standalone/.next/static/chunks/app/api/v1/access/[identity]/{route-36cb8b428b38b26a.js → route-6fc5f8e744c81802.js} +1 -1
  272. package/.next/standalone/.next/static/chunks/app/api/v1/access/{route-36cb8b428b38b26a.js → route-6fc5f8e744c81802.js} +1 -1
  273. package/.next/standalone/.next/static/chunks/app/api/v1/agents/[id]/compact/{route-36cb8b428b38b26a.js → route-6fc5f8e744c81802.js} +1 -1
  274. package/.next/standalone/.next/static/chunks/app/api/v1/agents/[id]/display-filters/route-6fc5f8e744c81802.js +17 -0
  275. package/.next/standalone/.next/static/chunks/app/api/v1/agents/[id]/route-6fc5f8e744c81802.js +17 -0
  276. package/.next/standalone/.next/static/chunks/app/api/v1/agents/[id]/thread/route-6fc5f8e744c81802.js +17 -0
  277. package/.next/standalone/.next/static/chunks/app/api/v1/agents/route-6fc5f8e744c81802.js +17 -0
  278. package/.next/standalone/.next/static/chunks/app/api/v1/allowed-sites/[hostname]/route-6fc5f8e744c81802.js +17 -0
  279. package/.next/standalone/.next/static/chunks/app/api/v1/allowed-sites/route-6fc5f8e744c81802.js +17 -0
  280. package/.next/standalone/.next/static/chunks/app/api/v1/artifacts/lifecycle/route-6fc5f8e744c81802.js +17 -0
  281. package/.next/standalone/.next/static/chunks/app/api/v1/attachments/files/route-6fc5f8e744c81802.js +17 -0
  282. package/.next/standalone/.next/static/chunks/app/api/v1/attachments/images/route-6fc5f8e744c81802.js +17 -0
  283. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/[id]/chats/route-6fc5f8e744c81802.js +17 -0
  284. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/[id]/ignores/[remote_jid]/route-6fc5f8e744c81802.js +17 -0
  285. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/[id]/ignores/route-6fc5f8e744c81802.js +17 -0
  286. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/[id]/lookup/route-6fc5f8e744c81802.js +17 -0
  287. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/[id]/pair/route-6fc5f8e744c81802.js +17 -0
  288. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/[id]/route-6fc5f8e744c81802.js +17 -0
  289. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/[id]/routes/[route_id]/route-6fc5f8e744c81802.js +17 -0
  290. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/[id]/routes/route-6fc5f8e744c81802.js +17 -0
  291. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/[id]/status/route-6fc5f8e744c81802.js +17 -0
  292. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/kinds/route-6fc5f8e744c81802.js +17 -0
  293. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/route-6fc5f8e744c81802.js +17 -0
  294. package/.next/standalone/.next/static/chunks/app/api/v1/builtin-tools/route-6fc5f8e744c81802.js +17 -0
  295. package/.next/standalone/.next/static/chunks/app/api/v1/config/route-6fc5f8e744c81802.js +17 -0
  296. package/.next/standalone/.next/static/chunks/app/api/v1/credentials/[id]/route-6fc5f8e744c81802.js +17 -0
  297. package/.next/standalone/.next/static/chunks/app/api/v1/credentials/route-6fc5f8e744c81802.js +17 -0
  298. package/.next/standalone/.next/static/chunks/app/api/v1/dashboard/currency/route-6fc5f8e744c81802.js +17 -0
  299. package/.next/standalone/.next/static/chunks/app/api/v1/dashboard/metrics/route-6fc5f8e744c81802.js +17 -0
  300. package/.next/standalone/.next/static/chunks/app/api/v1/dashboard/pricing/route-6fc5f8e744c81802.js +17 -0
  301. package/.next/standalone/.next/static/chunks/app/api/v1/dashboard/pricing-task/route-6fc5f8e744c81802.js +17 -0
  302. package/.next/standalone/.next/static/chunks/app/api/v1/delegations/codex/[job_id]/route-6fc5f8e744c81802.js +17 -0
  303. package/.next/standalone/.next/static/chunks/app/api/v1/documents/search/route-6fc5f8e744c81802.js +17 -0
  304. package/.next/standalone/.next/static/chunks/app/api/v1/documents/settings/route-6fc5f8e744c81802.js +17 -0
  305. package/.next/standalone/.next/static/chunks/app/api/v1/documents/sources/[id]/reindex/route-6fc5f8e744c81802.js +17 -0
  306. package/.next/standalone/.next/static/chunks/app/api/v1/documents/sources/[id]/route-6fc5f8e744c81802.js +17 -0
  307. package/.next/standalone/.next/static/chunks/app/api/v1/documents/sources/route-6fc5f8e744c81802.js +17 -0
  308. package/.next/standalone/.next/static/chunks/app/api/v1/env/route-6fc5f8e744c81802.js +17 -0
  309. package/.next/standalone/.next/static/chunks/app/api/v1/env-sync/allowlist/route-6fc5f8e744c81802.js +17 -0
  310. package/.next/standalone/.next/static/chunks/app/api/v1/env-sync/route-6fc5f8e744c81802.js +17 -0
  311. package/.next/standalone/.next/static/chunks/app/api/v1/events/route-6fc5f8e744c81802.js +17 -0
  312. package/.next/standalone/.next/static/chunks/app/api/v1/events/test/route-6fc5f8e744c81802.js +17 -0
  313. package/.next/standalone/.next/static/chunks/app/api/v1/extension/agents/route-6fc5f8e744c81802.js +17 -0
  314. package/.next/standalone/.next/static/chunks/app/api/v1/extension/browser/activate/route-6fc5f8e744c81802.js +17 -0
  315. package/.next/standalone/.next/static/chunks/app/api/v1/extension/browser/foreground/route-6fc5f8e744c81802.js +17 -0
  316. package/.next/standalone/.next/static/chunks/app/api/v1/extension/browser/history/route-6fc5f8e744c81802.js +17 -0
  317. package/.next/standalone/.next/static/chunks/app/api/v1/extension/browser/poll/route-6fc5f8e744c81802.js +17 -0
  318. package/.next/standalone/.next/static/chunks/app/api/v1/extension/browser/progress/route-6fc5f8e744c81802.js +17 -0
  319. package/.next/standalone/.next/static/chunks/app/api/v1/extension/browser/result/route-6fc5f8e744c81802.js +17 -0
  320. package/.next/standalone/.next/static/chunks/app/api/v1/extension/browser/retry/route-6fc5f8e744c81802.js +17 -0
  321. package/.next/standalone/.next/static/chunks/app/api/v1/extension/browser/status/route-6fc5f8e744c81802.js +17 -0
  322. package/.next/standalone/.next/static/chunks/app/api/v1/extension/browser/tabs/route-6fc5f8e744c81802.js +17 -0
  323. package/.next/standalone/.next/static/chunks/app/api/v1/extension/fill/route-6fc5f8e744c81802.js +17 -0
  324. package/.next/standalone/.next/static/chunks/app/api/v1/extension/refine/route-6fc5f8e744c81802.js +17 -0
  325. package/.next/standalone/.next/static/chunks/app/api/v1/extension/turn/route-6fc5f8e744c81802.js +17 -0
  326. package/.next/standalone/.next/static/chunks/app/api/v1/extensions/route-6fc5f8e744c81802.js +17 -0
  327. package/.next/standalone/.next/static/chunks/app/api/v1/extensions/tools/[name]/config/route-6fc5f8e744c81802.js +17 -0
  328. package/.next/standalone/.next/static/chunks/app/api/v1/extensions/tools/[name]/route-6fc5f8e744c81802.js +17 -0
  329. package/.next/standalone/.next/static/chunks/app/api/v1/extensions/tools/[name]/secrets/route-6fc5f8e744c81802.js +17 -0
  330. package/.next/standalone/.next/static/chunks/app/api/v1/files/[name]/route-6fc5f8e744c81802.js +17 -0
  331. package/.next/standalone/.next/static/chunks/app/api/v1/fs/browse/route-6fc5f8e744c81802.js +17 -0
  332. package/.next/standalone/.next/static/chunks/app/api/v1/harnesses/[id]/route-6fc5f8e744c81802.js +17 -0
  333. package/.next/standalone/.next/static/chunks/app/api/v1/harnesses/default/route-6fc5f8e744c81802.js +17 -0
  334. package/.next/standalone/.next/static/chunks/app/api/v1/harnesses/route-6fc5f8e744c81802.js +17 -0
  335. package/.next/standalone/.next/static/chunks/app/api/v1/health/probes/route-6fc5f8e744c81802.js +17 -0
  336. package/.next/standalone/.next/static/chunks/app/api/v1/health/route-6fc5f8e744c81802.js +17 -0
  337. package/.next/standalone/.next/static/chunks/app/api/v1/integrations/[name]/route-6fc5f8e744c81802.js +17 -0
  338. package/.next/standalone/.next/static/chunks/app/api/v1/integrations/[name]/test/route-6fc5f8e744c81802.js +17 -0
  339. package/.next/standalone/.next/static/chunks/app/api/v1/integrations/gmail/oauth/callback/route-6fc5f8e744c81802.js +17 -0
  340. package/.next/standalone/.next/static/chunks/app/api/v1/integrations/gmail/oauth/start/route-6fc5f8e744c81802.js +17 -0
  341. package/.next/standalone/.next/static/chunks/app/api/v1/integrations/gmail/oauth/status/route-6fc5f8e744c81802.js +17 -0
  342. package/.next/standalone/.next/static/chunks/app/api/v1/integrations/outlook/oauth/callback/route-6fc5f8e744c81802.js +17 -0
  343. package/.next/standalone/.next/static/chunks/app/api/v1/integrations/outlook/oauth/start/route-6fc5f8e744c81802.js +17 -0
  344. package/.next/standalone/.next/static/chunks/app/api/v1/integrations/outlook/oauth/status/route-6fc5f8e744c81802.js +17 -0
  345. package/.next/standalone/.next/static/chunks/app/api/v1/integrations/route-6fc5f8e744c81802.js +17 -0
  346. package/.next/standalone/.next/static/chunks/app/api/v1/lifecycle/adoption/route-6fc5f8e744c81802.js +17 -0
  347. package/.next/standalone/.next/static/chunks/app/api/v1/local-file/route-6fc5f8e744c81802.js +17 -0
  348. package/.next/standalone/.next/static/chunks/app/api/v1/logs/route-6fc5f8e744c81802.js +17 -0
  349. package/.next/standalone/.next/static/chunks/app/api/v1/maps/embed/route-6fc5f8e744c81802.js +17 -0
  350. package/.next/standalone/.next/static/chunks/app/api/v1/mcp-servers/[name]/route-6fc5f8e744c81802.js +17 -0
  351. package/.next/standalone/.next/static/chunks/app/api/v1/mcp-servers/registry/route-6fc5f8e744c81802.js +17 -0
  352. package/.next/standalone/.next/static/chunks/app/api/v1/mcp-servers/route-6fc5f8e744c81802.js +17 -0
  353. package/.next/standalone/.next/static/chunks/app/api/v1/memory/[namespace]/[key]/route-6fc5f8e744c81802.js +17 -0
  354. package/.next/standalone/.next/static/chunks/app/api/v1/memory/policy/route-6fc5f8e744c81802.js +17 -0
  355. package/.next/standalone/.next/static/chunks/app/api/v1/memory/route-6fc5f8e744c81802.js +17 -0
  356. package/.next/standalone/.next/static/chunks/app/api/v1/memory/search/route-6fc5f8e744c81802.js +17 -0
  357. package/.next/standalone/.next/static/chunks/app/api/v1/models/[name]/compact-threads/route-6fc5f8e744c81802.js +17 -0
  358. package/.next/standalone/.next/static/chunks/app/api/v1/models/[name]/route-6fc5f8e744c81802.js +17 -0
  359. package/.next/standalone/.next/static/chunks/app/api/v1/models/route-6fc5f8e744c81802.js +17 -0
  360. package/.next/standalone/.next/static/chunks/app/api/v1/packages/catalog/route-6fc5f8e744c81802.js +17 -0
  361. package/.next/standalone/.next/static/chunks/app/api/v1/packages/defaults/[id]/route-6fc5f8e744c81802.js +17 -0
  362. package/.next/standalone/.next/static/chunks/app/api/v1/packages/install/[id]/route-6fc5f8e744c81802.js +17 -0
  363. package/.next/standalone/.next/static/chunks/app/api/v1/packages/install/route-6fc5f8e744c81802.js +17 -0
  364. package/.next/standalone/.next/static/chunks/app/api/v1/packages/manifests/[name]/enabled/route-6fc5f8e744c81802.js +17 -0
  365. package/.next/standalone/.next/static/chunks/app/api/v1/packages/manifests/[name]/route-6fc5f8e744c81802.js +17 -0
  366. package/.next/standalone/.next/static/chunks/app/api/v1/packages/manifests/route-6fc5f8e744c81802.js +17 -0
  367. package/.next/standalone/.next/static/chunks/app/api/v1/packages/reload/route-6fc5f8e744c81802.js +17 -0
  368. package/.next/standalone/.next/static/chunks/app/api/v1/packages/route-6fc5f8e744c81802.js +17 -0
  369. package/.next/standalone/.next/static/chunks/app/api/v1/page-capture/route-6fc5f8e744c81802.js +17 -0
  370. package/.next/standalone/.next/static/chunks/app/api/v1/pending-actions/[id]/approve/route-6fc5f8e744c81802.js +17 -0
  371. package/.next/standalone/.next/static/chunks/app/api/v1/pending-actions/[id]/deny/route-6fc5f8e744c81802.js +17 -0
  372. package/.next/standalone/.next/static/chunks/app/api/v1/pending-actions/route-6fc5f8e744c81802.js +17 -0
  373. package/.next/standalone/.next/static/chunks/app/api/v1/profile/location/route-6fc5f8e744c81802.js +17 -0
  374. package/.next/standalone/.next/static/chunks/app/api/v1/profile/route-6fc5f8e744c81802.js +17 -0
  375. package/.next/standalone/.next/static/chunks/app/api/v1/providers/[provider]/models/route-6fc5f8e744c81802.js +17 -0
  376. package/.next/standalone/.next/static/chunks/app/api/v1/providers/[provider]/probe/route-6fc5f8e744c81802.js +17 -0
  377. package/.next/standalone/.next/static/chunks/app/api/v1/providers/github-copilot/auth/route-6fc5f8e744c81802.js +17 -0
  378. package/.next/standalone/.next/static/chunks/app/api/v1/providers/route-6fc5f8e744c81802.js +17 -0
  379. package/.next/standalone/.next/static/chunks/app/api/v1/proxy-config/route-6fc5f8e744c81802.js +17 -0
  380. package/.next/standalone/.next/static/chunks/app/api/v1/redaction/init/route-6fc5f8e744c81802.js +17 -0
  381. package/.next/standalone/.next/static/chunks/app/api/v1/redaction/route-6fc5f8e744c81802.js +17 -0
  382. package/.next/standalone/.next/static/chunks/app/api/v1/scheduled-tasks/[id]/route-6fc5f8e744c81802.js +17 -0
  383. package/.next/standalone/.next/static/chunks/app/api/v1/scheduled-tasks/[id]/run/route-6fc5f8e744c81802.js +17 -0
  384. package/.next/standalone/.next/static/chunks/app/api/v1/scheduled-tasks/route-6fc5f8e744c81802.js +17 -0
  385. package/.next/standalone/.next/static/chunks/app/api/v1/security/idle-timeout/route-6fc5f8e744c81802.js +17 -0
  386. package/.next/standalone/.next/static/chunks/app/api/v1/security/pin/route-6fc5f8e744c81802.js +17 -0
  387. package/.next/standalone/.next/static/chunks/app/api/v1/security/state/route-6fc5f8e744c81802.js +17 -0
  388. package/.next/standalone/.next/static/chunks/app/api/v1/security/unlock/route-6fc5f8e744c81802.js +17 -0
  389. package/.next/standalone/.next/static/chunks/app/api/v1/security/verify-pin/route-6fc5f8e744c81802.js +17 -0
  390. package/.next/standalone/.next/static/chunks/app/api/v1/setup/test-key/route-6fc5f8e744c81802.js +17 -0
  391. package/.next/standalone/.next/static/chunks/app/api/v1/skills/[id]/route-6fc5f8e744c81802.js +17 -0
  392. package/.next/standalone/.next/static/chunks/app/api/v1/skills/repos/[id]/route-6fc5f8e744c81802.js +17 -0
  393. package/.next/standalone/.next/static/chunks/app/api/v1/skills/repos/route-6fc5f8e744c81802.js +17 -0
  394. package/.next/standalone/.next/static/chunks/app/api/v1/skills/route-6fc5f8e744c81802.js +17 -0
  395. package/.next/standalone/.next/static/chunks/app/api/v1/system/abort/route-6fc5f8e744c81802.js +17 -0
  396. package/.next/standalone/.next/static/chunks/app/api/v1/system/restart/route-6fc5f8e744c81802.js +17 -0
  397. package/.next/standalone/.next/static/chunks/app/api/v1/tailscale/route-6fc5f8e744c81802.js +17 -0
  398. package/.next/standalone/.next/static/chunks/app/api/v1/tasks/[agent_id]/route-6fc5f8e744c81802.js +17 -0
  399. package/.next/standalone/.next/static/chunks/app/api/v1/tasks/route-6fc5f8e744c81802.js +17 -0
  400. package/.next/standalone/.next/static/chunks/app/api/v1/threads/[thread_id]/activity/route-6fc5f8e744c81802.js +17 -0
  401. package/.next/standalone/.next/static/chunks/app/api/v1/threads/[thread_id]/context-pin/route-6fc5f8e744c81802.js +17 -0
  402. package/.next/standalone/.next/static/chunks/app/api/v1/threads/[thread_id]/route-6fc5f8e744c81802.js +17 -0
  403. package/.next/standalone/.next/static/chunks/app/api/v1/threads/[thread_id]/run/route-6fc5f8e744c81802.js +17 -0
  404. package/.next/standalone/.next/static/chunks/app/api/v1/threads/route-6fc5f8e744c81802.js +17 -0
  405. package/.next/standalone/.next/static/chunks/app/api/v1/tools/route-6fc5f8e744c81802.js +17 -0
  406. package/.next/standalone/.next/static/chunks/app/api/v1/update/apply/route-6fc5f8e744c81802.js +17 -0
  407. package/.next/standalone/.next/static/chunks/app/api/v1/update/route-6fc5f8e744c81802.js +17 -0
  408. package/.next/standalone/.next/static/chunks/app/api/v1/voice/transcribe/route-6fc5f8e744c81802.js +17 -0
  409. package/.next/standalone/.next/static/chunks/app/api/v1/voice/tts/route-6fc5f8e744c81802.js +17 -0
  410. package/.next/standalone/.next/static/chunks/app/api/v1/watchers/[id]/route-6fc5f8e744c81802.js +17 -0
  411. package/.next/standalone/.next/static/chunks/app/api/v1/watchers/[id]/run/route-6fc5f8e744c81802.js +17 -0
  412. package/.next/standalone/.next/static/chunks/app/api/v1/watchers/reaction-scripts/route-6fc5f8e744c81802.js +17 -0
  413. package/.next/standalone/.next/static/chunks/app/api/v1/watchers/route-6fc5f8e744c81802.js +17 -0
  414. package/.next/standalone/.next/static/chunks/app/manifest.webmanifest/route-6fc5f8e744c81802.js +17 -0
  415. package/.next/standalone/.next/static/chunks/app/{page-7017f07f8a7a083c.js → page-213a623b37226452.js} +1041 -652
  416. package/.next/standalone/.next/static/chunks/next/dist/client/components/builtin/app-error-6fc5f8e744c81802.js +17 -0
  417. package/.next/standalone/.next/static/chunks/next/dist/client/components/builtin/forbidden-6fc5f8e744c81802.js +17 -0
  418. package/.next/standalone/.next/static/chunks/next/dist/client/components/builtin/not-found-6fc5f8e744c81802.js +17 -0
  419. package/.next/standalone/.next/static/chunks/next/dist/client/components/builtin/unauthorized-6fc5f8e744c81802.js +17 -0
  420. package/.next/standalone/.next/static/css/{d80058f0b9b41c09.css → 312542a5725ba0d5.css} +2 -2
  421. package/.next/standalone/docs/adoption/changesets.json +309 -0
  422. package/.next/standalone/lib/skills/builtins/memory-organization/SKILL.md +16 -0
  423. package/.next/standalone/package.json +3 -3
  424. package/CHANGELOG.md +25 -0
  425. package/api/client.ts +9 -0
  426. package/api/types.ts +29 -0
  427. package/app/api/v1/lifecycle/adoption/route.ts +14 -2
  428. package/app/api/v1/models/[name]/compact-threads/route.ts +14 -11
  429. package/app/api/v1/threads/[thread_id]/activity/route.ts +19 -0
  430. package/app/api/v1/threads/[thread_id]/context-pin/route.test.ts +1 -0
  431. package/app/api/v1/threads/[thread_id]/context-pin/route.ts +2 -1
  432. package/app/api/v1/threads/[thread_id]/route.ts +5 -1
  433. package/components/chat/ChatView.tsx +52 -11
  434. package/components/chat/ContextBoundary.test.tsx +68 -1
  435. package/components/chat/ContextBoundary.tsx +92 -13
  436. package/components/chat/MessageList.test.tsx +31 -0
  437. package/components/chat/MessageList.tsx +49 -28
  438. package/components/chat/ToolList.test.tsx +92 -16
  439. package/components/chat/ToolList.tsx +59 -4
  440. package/components/chat/chat-helpers.test.tsx +24 -1
  441. package/components/chat/chat-helpers.ts +47 -4
  442. package/components/chat/useThreadActivity.test.tsx +113 -0
  443. package/components/chat/useThreadActivity.ts +94 -0
  444. package/components/chat/useThreadData.ts +16 -16
  445. package/components/chat/workflow-step-retry.ts +25 -0
  446. package/components/ui/BootScreen.tsx +17 -0
  447. package/components/ui/WorkflowChecklist.tsx +71 -33
  448. package/hooks/useSSE.ts +28 -3
  449. package/lib/agents/compaction-pipeline.test.ts +202 -0
  450. package/lib/agents/compaction-pipeline.ts +483 -0
  451. package/lib/agents/conversation-summary.ts +37 -21
  452. package/lib/agents/prepare/history-window.test.ts +18 -0
  453. package/lib/agents/prepare/history-window.ts +11 -2
  454. package/lib/agents/prepare/request.ts +4 -0
  455. package/lib/agents/prepare/system-prompt.test.ts +39 -0
  456. package/lib/agents/prepare/system-prompt.ts +8 -3
  457. package/lib/agents/prompt-registry.test.ts +5 -140
  458. package/lib/agents/prompt-registry.ts +45 -1
  459. package/lib/agents/prompt-variants.ts +146 -0
  460. package/lib/agents/run-registry.test.ts +22 -0
  461. package/lib/agents/run-registry.ts +29 -0
  462. package/lib/agents/run-thread.retry.test.ts +67 -1
  463. package/lib/agents/run-thread.ts +86 -1
  464. package/lib/agents/thread-activity.test.ts +31 -0
  465. package/lib/agents/thread-activity.ts +27 -0
  466. package/lib/agents/thread-compaction-state.test.ts +82 -0
  467. package/lib/agents/thread-compaction-state.ts +121 -0
  468. package/lib/agents/thread-compaction.test.ts +83 -4
  469. package/lib/agents/thread-compaction.ts +34 -11
  470. package/lib/agents/warm-summary-background.test.ts +219 -5
  471. package/lib/agents/warm-summary-background.ts +325 -142
  472. package/lib/agents/warm-topics.test.ts +37 -0
  473. package/lib/agents/warm-topics.ts +297 -0
  474. package/lib/agents/workflow-step-retry.test.ts +96 -0
  475. package/lib/agents/workflow-step-retry.ts +216 -0
  476. package/lib/api/browser-control.ts +0 -3
  477. package/lib/db/migrations.ts +5 -0
  478. package/lib/env/config.ts +2 -0
  479. package/lib/env/schema.ts +12 -0
  480. package/lib/lifecycle/changeset-build.test.ts +93 -0
  481. package/lib/lifecycle/changeset-build.ts +210 -0
  482. package/lib/lifecycle/changesets.test.ts +101 -0
  483. package/lib/lifecycle/changesets.ts +166 -0
  484. package/lib/lifecycle/surface-collect.test.ts +88 -0
  485. package/lib/lifecycle/surface-collect.ts +64 -0
  486. package/lib/lifecycle/surface-snapshot.test.ts +104 -0
  487. package/lib/lifecycle/surface-snapshot.ts +210 -0
  488. package/lib/memory/record.ts +0 -2
  489. package/lib/providers/external.ts +0 -2
  490. package/lib/skills/builtins/memory-organization/SKILL.md +16 -0
  491. package/lib/stores/threads.test.ts +9 -0
  492. package/lib/stores/threads.ts +21 -11
  493. package/lib/stores/version-adoption.test.ts +96 -0
  494. package/lib/stores/version-adoption.ts +239 -26
  495. package/lib/stores/workflow-progress.ts +3 -0
  496. package/lib/tools/communications/ms-todo.ts +0 -7
  497. package/lib/tools/general/memory.ts +1 -1
  498. package/lib/tools/general/workflow-progress.ts +2 -0
  499. package/lib/tools/runtime/catalog.ts +1 -25
  500. package/lib/triggers/registry.ts +0 -4
  501. package/package.json +3 -3
  502. package/scripts/install-to-system.ps1 +39 -11
  503. package/scripts/install-to-system.sh +37 -3
  504. package/.next/standalone/.next/server/chunks/3979.js +0 -581
  505. package/.next/standalone/.next/server/chunks/5936.js +0 -594
  506. package/.next/standalone/.next/static/chunks/app/api/v1/agents/[id]/display-filters/route-36cb8b428b38b26a.js +0 -17
  507. package/.next/standalone/.next/static/chunks/app/api/v1/agents/[id]/route-36cb8b428b38b26a.js +0 -17
  508. package/.next/standalone/.next/static/chunks/app/api/v1/agents/[id]/thread/route-36cb8b428b38b26a.js +0 -17
  509. package/.next/standalone/.next/static/chunks/app/api/v1/agents/route-36cb8b428b38b26a.js +0 -17
  510. package/.next/standalone/.next/static/chunks/app/api/v1/allowed-sites/[hostname]/route-36cb8b428b38b26a.js +0 -17
  511. package/.next/standalone/.next/static/chunks/app/api/v1/allowed-sites/route-36cb8b428b38b26a.js +0 -17
  512. package/.next/standalone/.next/static/chunks/app/api/v1/artifacts/lifecycle/route-36cb8b428b38b26a.js +0 -17
  513. package/.next/standalone/.next/static/chunks/app/api/v1/attachments/files/route-36cb8b428b38b26a.js +0 -17
  514. package/.next/standalone/.next/static/chunks/app/api/v1/attachments/images/route-36cb8b428b38b26a.js +0 -17
  515. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/[id]/chats/route-36cb8b428b38b26a.js +0 -17
  516. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/[id]/ignores/[remote_jid]/route-36cb8b428b38b26a.js +0 -17
  517. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/[id]/ignores/route-36cb8b428b38b26a.js +0 -17
  518. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/[id]/lookup/route-36cb8b428b38b26a.js +0 -17
  519. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/[id]/pair/route-36cb8b428b38b26a.js +0 -17
  520. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/[id]/route-36cb8b428b38b26a.js +0 -17
  521. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/[id]/routes/[route_id]/route-36cb8b428b38b26a.js +0 -17
  522. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/[id]/routes/route-36cb8b428b38b26a.js +0 -17
  523. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/[id]/status/route-36cb8b428b38b26a.js +0 -17
  524. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/kinds/route-36cb8b428b38b26a.js +0 -17
  525. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/route-36cb8b428b38b26a.js +0 -17
  526. package/.next/standalone/.next/static/chunks/app/api/v1/builtin-tools/route-36cb8b428b38b26a.js +0 -17
  527. package/.next/standalone/.next/static/chunks/app/api/v1/config/route-36cb8b428b38b26a.js +0 -17
  528. package/.next/standalone/.next/static/chunks/app/api/v1/credentials/[id]/route-36cb8b428b38b26a.js +0 -17
  529. package/.next/standalone/.next/static/chunks/app/api/v1/credentials/route-36cb8b428b38b26a.js +0 -17
  530. package/.next/standalone/.next/static/chunks/app/api/v1/dashboard/currency/route-36cb8b428b38b26a.js +0 -17
  531. package/.next/standalone/.next/static/chunks/app/api/v1/dashboard/metrics/route-36cb8b428b38b26a.js +0 -17
  532. package/.next/standalone/.next/static/chunks/app/api/v1/dashboard/pricing/route-36cb8b428b38b26a.js +0 -17
  533. package/.next/standalone/.next/static/chunks/app/api/v1/dashboard/pricing-task/route-36cb8b428b38b26a.js +0 -17
  534. package/.next/standalone/.next/static/chunks/app/api/v1/delegations/codex/[job_id]/route-36cb8b428b38b26a.js +0 -17
  535. package/.next/standalone/.next/static/chunks/app/api/v1/documents/search/route-36cb8b428b38b26a.js +0 -17
  536. package/.next/standalone/.next/static/chunks/app/api/v1/documents/settings/route-36cb8b428b38b26a.js +0 -17
  537. package/.next/standalone/.next/static/chunks/app/api/v1/documents/sources/[id]/reindex/route-36cb8b428b38b26a.js +0 -17
  538. package/.next/standalone/.next/static/chunks/app/api/v1/documents/sources/[id]/route-36cb8b428b38b26a.js +0 -17
  539. package/.next/standalone/.next/static/chunks/app/api/v1/documents/sources/route-36cb8b428b38b26a.js +0 -17
  540. package/.next/standalone/.next/static/chunks/app/api/v1/env/route-36cb8b428b38b26a.js +0 -17
  541. package/.next/standalone/.next/static/chunks/app/api/v1/env-sync/allowlist/route-36cb8b428b38b26a.js +0 -17
  542. package/.next/standalone/.next/static/chunks/app/api/v1/env-sync/route-36cb8b428b38b26a.js +0 -17
  543. package/.next/standalone/.next/static/chunks/app/api/v1/events/route-36cb8b428b38b26a.js +0 -17
  544. package/.next/standalone/.next/static/chunks/app/api/v1/events/test/route-36cb8b428b38b26a.js +0 -17
  545. package/.next/standalone/.next/static/chunks/app/api/v1/extension/agents/route-36cb8b428b38b26a.js +0 -17
  546. package/.next/standalone/.next/static/chunks/app/api/v1/extension/browser/activate/route-36cb8b428b38b26a.js +0 -17
  547. package/.next/standalone/.next/static/chunks/app/api/v1/extension/browser/foreground/route-36cb8b428b38b26a.js +0 -17
  548. package/.next/standalone/.next/static/chunks/app/api/v1/extension/browser/history/route-36cb8b428b38b26a.js +0 -17
  549. package/.next/standalone/.next/static/chunks/app/api/v1/extension/browser/poll/route-36cb8b428b38b26a.js +0 -17
  550. package/.next/standalone/.next/static/chunks/app/api/v1/extension/browser/progress/route-36cb8b428b38b26a.js +0 -17
  551. package/.next/standalone/.next/static/chunks/app/api/v1/extension/browser/result/route-36cb8b428b38b26a.js +0 -17
  552. package/.next/standalone/.next/static/chunks/app/api/v1/extension/browser/retry/route-36cb8b428b38b26a.js +0 -17
  553. package/.next/standalone/.next/static/chunks/app/api/v1/extension/browser/status/route-36cb8b428b38b26a.js +0 -17
  554. package/.next/standalone/.next/static/chunks/app/api/v1/extension/browser/tabs/route-36cb8b428b38b26a.js +0 -17
  555. package/.next/standalone/.next/static/chunks/app/api/v1/extension/fill/route-36cb8b428b38b26a.js +0 -17
  556. package/.next/standalone/.next/static/chunks/app/api/v1/extension/refine/route-36cb8b428b38b26a.js +0 -17
  557. package/.next/standalone/.next/static/chunks/app/api/v1/extension/turn/route-36cb8b428b38b26a.js +0 -17
  558. package/.next/standalone/.next/static/chunks/app/api/v1/extensions/route-36cb8b428b38b26a.js +0 -17
  559. package/.next/standalone/.next/static/chunks/app/api/v1/extensions/tools/[name]/config/route-36cb8b428b38b26a.js +0 -17
  560. package/.next/standalone/.next/static/chunks/app/api/v1/extensions/tools/[name]/route-36cb8b428b38b26a.js +0 -17
  561. package/.next/standalone/.next/static/chunks/app/api/v1/extensions/tools/[name]/secrets/route-36cb8b428b38b26a.js +0 -17
  562. package/.next/standalone/.next/static/chunks/app/api/v1/files/[name]/route-36cb8b428b38b26a.js +0 -17
  563. package/.next/standalone/.next/static/chunks/app/api/v1/fs/browse/route-36cb8b428b38b26a.js +0 -17
  564. package/.next/standalone/.next/static/chunks/app/api/v1/harnesses/[id]/route-36cb8b428b38b26a.js +0 -17
  565. package/.next/standalone/.next/static/chunks/app/api/v1/harnesses/default/route-36cb8b428b38b26a.js +0 -17
  566. package/.next/standalone/.next/static/chunks/app/api/v1/harnesses/route-36cb8b428b38b26a.js +0 -17
  567. package/.next/standalone/.next/static/chunks/app/api/v1/health/probes/route-36cb8b428b38b26a.js +0 -17
  568. package/.next/standalone/.next/static/chunks/app/api/v1/health/route-36cb8b428b38b26a.js +0 -17
  569. package/.next/standalone/.next/static/chunks/app/api/v1/integrations/[name]/route-36cb8b428b38b26a.js +0 -17
  570. package/.next/standalone/.next/static/chunks/app/api/v1/integrations/[name]/test/route-36cb8b428b38b26a.js +0 -17
  571. package/.next/standalone/.next/static/chunks/app/api/v1/integrations/gmail/oauth/callback/route-36cb8b428b38b26a.js +0 -17
  572. package/.next/standalone/.next/static/chunks/app/api/v1/integrations/gmail/oauth/start/route-36cb8b428b38b26a.js +0 -17
  573. package/.next/standalone/.next/static/chunks/app/api/v1/integrations/gmail/oauth/status/route-36cb8b428b38b26a.js +0 -17
  574. package/.next/standalone/.next/static/chunks/app/api/v1/integrations/outlook/oauth/callback/route-36cb8b428b38b26a.js +0 -17
  575. package/.next/standalone/.next/static/chunks/app/api/v1/integrations/outlook/oauth/start/route-36cb8b428b38b26a.js +0 -17
  576. package/.next/standalone/.next/static/chunks/app/api/v1/integrations/outlook/oauth/status/route-36cb8b428b38b26a.js +0 -17
  577. package/.next/standalone/.next/static/chunks/app/api/v1/integrations/route-36cb8b428b38b26a.js +0 -17
  578. package/.next/standalone/.next/static/chunks/app/api/v1/lifecycle/adoption/route-36cb8b428b38b26a.js +0 -17
  579. package/.next/standalone/.next/static/chunks/app/api/v1/local-file/route-36cb8b428b38b26a.js +0 -17
  580. package/.next/standalone/.next/static/chunks/app/api/v1/logs/route-36cb8b428b38b26a.js +0 -17
  581. package/.next/standalone/.next/static/chunks/app/api/v1/maps/embed/route-36cb8b428b38b26a.js +0 -17
  582. package/.next/standalone/.next/static/chunks/app/api/v1/mcp-servers/[name]/route-36cb8b428b38b26a.js +0 -17
  583. package/.next/standalone/.next/static/chunks/app/api/v1/mcp-servers/registry/route-36cb8b428b38b26a.js +0 -17
  584. package/.next/standalone/.next/static/chunks/app/api/v1/mcp-servers/route-36cb8b428b38b26a.js +0 -17
  585. package/.next/standalone/.next/static/chunks/app/api/v1/memory/[namespace]/[key]/route-36cb8b428b38b26a.js +0 -17
  586. package/.next/standalone/.next/static/chunks/app/api/v1/memory/policy/route-36cb8b428b38b26a.js +0 -17
  587. package/.next/standalone/.next/static/chunks/app/api/v1/memory/route-36cb8b428b38b26a.js +0 -17
  588. package/.next/standalone/.next/static/chunks/app/api/v1/memory/search/route-36cb8b428b38b26a.js +0 -17
  589. package/.next/standalone/.next/static/chunks/app/api/v1/models/[name]/compact-threads/route-36cb8b428b38b26a.js +0 -17
  590. package/.next/standalone/.next/static/chunks/app/api/v1/models/[name]/route-36cb8b428b38b26a.js +0 -17
  591. package/.next/standalone/.next/static/chunks/app/api/v1/models/route-36cb8b428b38b26a.js +0 -17
  592. package/.next/standalone/.next/static/chunks/app/api/v1/packages/catalog/route-36cb8b428b38b26a.js +0 -17
  593. package/.next/standalone/.next/static/chunks/app/api/v1/packages/defaults/[id]/route-36cb8b428b38b26a.js +0 -17
  594. package/.next/standalone/.next/static/chunks/app/api/v1/packages/install/[id]/route-36cb8b428b38b26a.js +0 -17
  595. package/.next/standalone/.next/static/chunks/app/api/v1/packages/install/route-36cb8b428b38b26a.js +0 -17
  596. package/.next/standalone/.next/static/chunks/app/api/v1/packages/manifests/[name]/enabled/route-36cb8b428b38b26a.js +0 -17
  597. package/.next/standalone/.next/static/chunks/app/api/v1/packages/manifests/[name]/route-36cb8b428b38b26a.js +0 -17
  598. package/.next/standalone/.next/static/chunks/app/api/v1/packages/manifests/route-36cb8b428b38b26a.js +0 -17
  599. package/.next/standalone/.next/static/chunks/app/api/v1/packages/reload/route-36cb8b428b38b26a.js +0 -17
  600. package/.next/standalone/.next/static/chunks/app/api/v1/packages/route-36cb8b428b38b26a.js +0 -17
  601. package/.next/standalone/.next/static/chunks/app/api/v1/page-capture/route-36cb8b428b38b26a.js +0 -17
  602. package/.next/standalone/.next/static/chunks/app/api/v1/pending-actions/[id]/approve/route-36cb8b428b38b26a.js +0 -17
  603. package/.next/standalone/.next/static/chunks/app/api/v1/pending-actions/[id]/deny/route-36cb8b428b38b26a.js +0 -17
  604. package/.next/standalone/.next/static/chunks/app/api/v1/pending-actions/route-36cb8b428b38b26a.js +0 -17
  605. package/.next/standalone/.next/static/chunks/app/api/v1/profile/location/route-36cb8b428b38b26a.js +0 -17
  606. package/.next/standalone/.next/static/chunks/app/api/v1/profile/route-36cb8b428b38b26a.js +0 -17
  607. package/.next/standalone/.next/static/chunks/app/api/v1/providers/[provider]/models/route-36cb8b428b38b26a.js +0 -17
  608. package/.next/standalone/.next/static/chunks/app/api/v1/providers/[provider]/probe/route-36cb8b428b38b26a.js +0 -17
  609. package/.next/standalone/.next/static/chunks/app/api/v1/providers/github-copilot/auth/route-36cb8b428b38b26a.js +0 -17
  610. package/.next/standalone/.next/static/chunks/app/api/v1/providers/route-36cb8b428b38b26a.js +0 -17
  611. package/.next/standalone/.next/static/chunks/app/api/v1/proxy-config/route-36cb8b428b38b26a.js +0 -17
  612. package/.next/standalone/.next/static/chunks/app/api/v1/redaction/init/route-36cb8b428b38b26a.js +0 -17
  613. package/.next/standalone/.next/static/chunks/app/api/v1/redaction/route-36cb8b428b38b26a.js +0 -17
  614. package/.next/standalone/.next/static/chunks/app/api/v1/scheduled-tasks/[id]/route-36cb8b428b38b26a.js +0 -17
  615. package/.next/standalone/.next/static/chunks/app/api/v1/scheduled-tasks/[id]/run/route-36cb8b428b38b26a.js +0 -17
  616. package/.next/standalone/.next/static/chunks/app/api/v1/scheduled-tasks/route-36cb8b428b38b26a.js +0 -17
  617. package/.next/standalone/.next/static/chunks/app/api/v1/security/idle-timeout/route-36cb8b428b38b26a.js +0 -17
  618. package/.next/standalone/.next/static/chunks/app/api/v1/security/pin/route-36cb8b428b38b26a.js +0 -17
  619. package/.next/standalone/.next/static/chunks/app/api/v1/security/state/route-36cb8b428b38b26a.js +0 -17
  620. package/.next/standalone/.next/static/chunks/app/api/v1/security/unlock/route-36cb8b428b38b26a.js +0 -17
  621. package/.next/standalone/.next/static/chunks/app/api/v1/security/verify-pin/route-36cb8b428b38b26a.js +0 -17
  622. package/.next/standalone/.next/static/chunks/app/api/v1/setup/test-key/route-36cb8b428b38b26a.js +0 -17
  623. package/.next/standalone/.next/static/chunks/app/api/v1/skills/[id]/route-36cb8b428b38b26a.js +0 -17
  624. package/.next/standalone/.next/static/chunks/app/api/v1/skills/repos/[id]/route-36cb8b428b38b26a.js +0 -17
  625. package/.next/standalone/.next/static/chunks/app/api/v1/skills/repos/route-36cb8b428b38b26a.js +0 -17
  626. package/.next/standalone/.next/static/chunks/app/api/v1/skills/route-36cb8b428b38b26a.js +0 -17
  627. package/.next/standalone/.next/static/chunks/app/api/v1/system/abort/route-36cb8b428b38b26a.js +0 -17
  628. package/.next/standalone/.next/static/chunks/app/api/v1/system/restart/route-36cb8b428b38b26a.js +0 -17
  629. package/.next/standalone/.next/static/chunks/app/api/v1/tailscale/route-36cb8b428b38b26a.js +0 -17
  630. package/.next/standalone/.next/static/chunks/app/api/v1/tasks/[agent_id]/route-36cb8b428b38b26a.js +0 -17
  631. package/.next/standalone/.next/static/chunks/app/api/v1/tasks/route-36cb8b428b38b26a.js +0 -17
  632. package/.next/standalone/.next/static/chunks/app/api/v1/threads/[thread_id]/context-pin/route-36cb8b428b38b26a.js +0 -17
  633. package/.next/standalone/.next/static/chunks/app/api/v1/threads/[thread_id]/route-36cb8b428b38b26a.js +0 -17
  634. package/.next/standalone/.next/static/chunks/app/api/v1/threads/[thread_id]/run/route-36cb8b428b38b26a.js +0 -17
  635. package/.next/standalone/.next/static/chunks/app/api/v1/threads/route-36cb8b428b38b26a.js +0 -17
  636. package/.next/standalone/.next/static/chunks/app/api/v1/tools/route-36cb8b428b38b26a.js +0 -17
  637. package/.next/standalone/.next/static/chunks/app/api/v1/update/apply/route-36cb8b428b38b26a.js +0 -17
  638. package/.next/standalone/.next/static/chunks/app/api/v1/update/route-36cb8b428b38b26a.js +0 -17
  639. package/.next/standalone/.next/static/chunks/app/api/v1/voice/transcribe/route-36cb8b428b38b26a.js +0 -17
  640. package/.next/standalone/.next/static/chunks/app/api/v1/voice/tts/route-36cb8b428b38b26a.js +0 -17
  641. package/.next/standalone/.next/static/chunks/app/api/v1/watchers/[id]/route-36cb8b428b38b26a.js +0 -17
  642. package/.next/standalone/.next/static/chunks/app/api/v1/watchers/[id]/run/route-36cb8b428b38b26a.js +0 -17
  643. package/.next/standalone/.next/static/chunks/app/api/v1/watchers/reaction-scripts/route-36cb8b428b38b26a.js +0 -17
  644. package/.next/standalone/.next/static/chunks/app/api/v1/watchers/route-36cb8b428b38b26a.js +0 -17
  645. package/.next/standalone/.next/static/chunks/app/manifest.webmanifest/route-36cb8b428b38b26a.js +0 -17
  646. package/.next/standalone/.next/static/chunks/next/dist/client/components/builtin/app-error-36cb8b428b38b26a.js +0 -17
  647. package/.next/standalone/.next/static/chunks/next/dist/client/components/builtin/forbidden-36cb8b428b38b26a.js +0 -17
  648. package/.next/standalone/.next/static/chunks/next/dist/client/components/builtin/not-found-36cb8b428b38b26a.js +0 -17
  649. package/.next/standalone/.next/static/chunks/next/dist/client/components/builtin/unauthorized-36cb8b428b38b26a.js +0 -17
  650. /package/.next/standalone/.next/static/{NUrC9xax1sp1Q70nlFqS6 → bMRK5y3ruT7c3WtBfCQOG}/_buildManifest.js +0 -0
  651. /package/.next/standalone/.next/static/{NUrC9xax1sp1Q70nlFqS6 → bMRK5y3ruT7c3WtBfCQOG}/_ssgManifest.js +0 -0
@@ -1,6 +1,105 @@
1
1
  (self["webpackChunk_N_E"] = self["webpackChunk_N_E"] || []).push([[8974],{
2
2
 
3
- /***/ 9024:
3
+ /***/ 30737:
4
+ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
5
+
6
+ "use strict";
7
+ /* harmony export */ __webpack_require__.d(__webpack_exports__, {
8
+ /* harmony export */ D: () => (/* binding */ useTheme),
9
+ /* harmony export */ ThemeProvider: () => (/* binding */ ThemeProvider)
10
+ /* harmony export */ });
11
+ /* harmony import */ var react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(95155);
12
+ /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(12115);
13
+ /* __next_internal_client_entry_do_not_use__ ThemeProvider,useTheme auto */
14
+
15
+ const STORAGE_KEY = "jarela-theme";
16
+ function isTheme(v) {
17
+ return v === "light" || v === "dark" || v === "system";
18
+ }
19
+ function readStored() {
20
+ if (false) {}
21
+ try {
22
+ const v = window.localStorage.getItem(STORAGE_KEY);
23
+ return isTheme(v) ? v : "system";
24
+ } catch {
25
+ return "system";
26
+ }
27
+ }
28
+ const LIGHT_CHROME = "#ffffff";
29
+ const DARK_CHROME = "#09090b";
30
+ function resolveChrome(theme) {
31
+ if (theme === "light") return LIGHT_CHROME;
32
+ if (theme === "dark") return DARK_CHROME;
33
+ if (false) {}
34
+ return window.matchMedia("(prefers-color-scheme: dark)").matches ? DARK_CHROME : LIGHT_CHROME;
35
+ }
36
+ // Keep the single <meta name="theme-color"> tag (installed by the pre-paint
37
+ // script in app/layout.tsx) aligned with the active surface so the PWA's
38
+ // desktop title bar and mobile address bar match the theme.
39
+ function syncChrome(theme) {
40
+ if (typeof document === "undefined") return;
41
+ const meta = document.querySelector('meta[name="theme-color"]');
42
+ if (meta) meta.setAttribute("content", resolveChrome(theme));
43
+ }
44
+ function apply(theme) {
45
+ if (typeof document === "undefined") return;
46
+ document.documentElement.setAttribute("data-theme", theme);
47
+ syncChrome(theme);
48
+ }
49
+ const ThemeContext = /*#__PURE__*/ (0,react__WEBPACK_IMPORTED_MODULE_1__.createContext)(null);
50
+ function ThemeProvider({ children }) {
51
+ // Initial state stays "system" on the server to match the pre-paint script,
52
+ // which writes data-theme before React hydrates. The effect below syncs the
53
+ // React state to whatever the script (or localStorage) decided.
54
+ const [theme, setThemeState] = (0,react__WEBPACK_IMPORTED_MODULE_1__.useState)("system");
55
+ (0,react__WEBPACK_IMPORTED_MODULE_1__.useEffect)(()=>{
56
+ const stored = readStored();
57
+ setThemeState(stored);
58
+ // When in "system" mode, mirror OS-level changes into the PWA chrome.
59
+ if (false) {}
60
+ const mq = window.matchMedia("(prefers-color-scheme: dark)");
61
+ const onChange = ()=>{
62
+ if (readStored() === "system") syncChrome("system");
63
+ };
64
+ mq.addEventListener?.("change", onChange);
65
+ return ()=>mq.removeEventListener?.("change", onChange);
66
+ }, []);
67
+ const setTheme = (0,react__WEBPACK_IMPORTED_MODULE_1__.useCallback)((t)=>{
68
+ setThemeState(t);
69
+ apply(t);
70
+ try {
71
+ window.localStorage.setItem(STORAGE_KEY, t);
72
+ } catch {
73
+ /* ignore quota / private-mode errors */ }
74
+ }, []);
75
+ return /*#__PURE__*/ (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(ThemeContext.Provider, {
76
+ value: {
77
+ theme,
78
+ setTheme
79
+ },
80
+ children: children
81
+ });
82
+ }
83
+ function useTheme() {
84
+ const ctx = (0,react__WEBPACK_IMPORTED_MODULE_1__.useContext)(ThemeContext);
85
+ if (!ctx) throw new Error("useTheme must be used within ThemeProvider");
86
+ return ctx;
87
+ }
88
+
89
+
90
+ /***/ }),
91
+
92
+ /***/ 39852:
93
+ /***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {
94
+
95
+ Promise.resolve(/* import() eager */).then(__webpack_require__.bind(__webpack_require__, 54986));
96
+ ;
97
+ Promise.resolve(/* import() eager */).then(__webpack_require__.bind(__webpack_require__, 12283));
98
+
99
+
100
+ /***/ }),
101
+
102
+ /***/ 54986:
4
103
  /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
5
104
 
6
105
  "use strict";
@@ -1114,6 +1213,26 @@ function useSSE(onDone) {
1114
1213
  // Cleared on every new start()/attach().
1115
1214
  const [authError, setAuthError] = (0,react.useState)(null);
1116
1215
  const abortRef = (0,react.useRef)(null);
1216
+ // Synchronous view of whether start()/attach() owns a live stream, and when
1217
+ // the last one settled. React's `streaming` lags a render behind, so the
1218
+ // activity poller reads this to avoid aborting a stream that just opened
1219
+ // or re-attaching a run whose stream has only just ended.
1220
+ const liveRef = (0,react.useRef)({
1221
+ busy: false,
1222
+ settledAt: 0
1223
+ });
1224
+ const markLive = (0,react.useCallback)(()=>{
1225
+ liveRef.current.busy = true;
1226
+ }, []);
1227
+ const markSettled = (0,react.useCallback)((ctrl)=>{
1228
+ if (ctrl && abortRef.current !== ctrl) return;
1229
+ liveRef.current = {
1230
+ busy: false,
1231
+ settledAt: Date.now()
1232
+ };
1233
+ }, []);
1234
+ const isLive = (0,react.useCallback)(()=>liveRef.current.busy, []);
1235
+ const lastSettledAt = (0,react.useCallback)(()=>liveRef.current.settledAt, []);
1117
1236
  const threadIdRef = (0,react.useRef)(null);
1118
1237
  // ADR-0080 — id of the steering message currently armed for a possible
1119
1238
  // continuation break, or null. Set eagerly (before the steer PATCH
@@ -1275,6 +1394,7 @@ function useSSE(onDone) {
1275
1394
  abortRef.current?.abort();
1276
1395
  const ctrl = new AbortController();
1277
1396
  abortRef.current = ctrl;
1397
+ markLive();
1278
1398
  threadIdRef.current = threadId;
1279
1399
  resetBuffer();
1280
1400
  setStreaming(true);
@@ -1322,10 +1442,13 @@ function useSSE(onDone) {
1322
1442
  // them.
1323
1443
  setStreaming(false);
1324
1444
  closeActivity();
1445
+ markSettled(ctrl);
1325
1446
  }
1326
1447
  }, [
1327
1448
  closeActivity,
1328
1449
  consume,
1450
+ markLive,
1451
+ markSettled,
1329
1452
  openActivity,
1330
1453
  resetBuffer
1331
1454
  ]);
@@ -1350,11 +1473,13 @@ function useSSE(onDone) {
1350
1473
  // start()/attach() — same pattern as the `done` branch in consume().
1351
1474
  closeActivity();
1352
1475
  abortRef.current?.abort();
1476
+ markSettled(null);
1353
1477
  steeredContinuationIdRef.current = null;
1354
1478
  onDone?.();
1355
1479
  }, [
1356
1480
  closeActivity,
1357
1481
  flushPending,
1482
+ markSettled,
1358
1483
  onDone
1359
1484
  ]);
1360
1485
  // Attach to an in-flight run for the given thread (server-side run kept
@@ -1368,6 +1493,7 @@ function useSSE(onDone) {
1368
1493
  abortRef.current?.abort();
1369
1494
  const ctrl = new AbortController();
1370
1495
  abortRef.current = ctrl;
1496
+ markLive();
1371
1497
  threadIdRef.current = threadId;
1372
1498
  resetBuffer();
1373
1499
  setStreaming(true);
@@ -1395,10 +1521,13 @@ function useSSE(onDone) {
1395
1521
  // hangs in the composer and the "Reconnecting…" badge never clears.
1396
1522
  setStreaming(false);
1397
1523
  closeActivity();
1524
+ markSettled(ctrl);
1398
1525
  }
1399
1526
  }, [
1400
1527
  closeActivity,
1401
1528
  consume,
1529
+ markLive,
1530
+ markSettled,
1402
1531
  onDone,
1403
1532
  openActivity,
1404
1533
  resetBuffer
@@ -1443,6 +1572,8 @@ function useSSE(onDone) {
1443
1572
  start,
1444
1573
  stop,
1445
1574
  attach,
1575
+ isLive,
1576
+ lastSettledAt,
1446
1577
  clearStreamingContent,
1447
1578
  clearToolEvents,
1448
1579
  armSteeredContinuation,
@@ -1462,6 +1593,8 @@ function useSSE(onDone) {
1462
1593
  start,
1463
1594
  stop,
1464
1595
  attach,
1596
+ isLive,
1597
+ lastSettledAt,
1465
1598
  clearStreamingContent,
1466
1599
  clearToolEvents,
1467
1600
  armSteeredContinuation,
@@ -1682,6 +1815,8 @@ function readLegacyGlobal() {
1682
1815
  };
1683
1816
  }
1684
1817
 
1818
+ // EXTERNAL MODULE: ./lib/ui/error-report.ts
1819
+ var error_report = __webpack_require__(11856);
1685
1820
  // EXTERNAL MODULE: ./node_modules/lucide-react/dist/esm/icons/shield-alert.mjs
1686
1821
  var shield_alert = __webpack_require__(69203);
1687
1822
  // EXTERNAL MODULE: ./node_modules/lucide-react/dist/esm/icons/chevron-up.mjs
@@ -2919,9 +3054,24 @@ var loader_circle = __webpack_require__(92571);
2919
3054
  var triangle_alert = __webpack_require__(11012);
2920
3055
  // EXTERNAL MODULE: ./node_modules/lucide-react/dist/esm/icons/minus.mjs
2921
3056
  var minus = __webpack_require__(36565);
3057
+ // EXTERNAL MODULE: ./node_modules/lucide-react/dist/esm/icons/rotate-ccw.mjs
3058
+ var rotate_ccw = __webpack_require__(92298);
2922
3059
  ;// ./components/ui/WorkflowChecklist.tsx
2923
3060
 
2924
3061
 
3062
+ const RETRYABLE_STATUSES = new Set([
3063
+ "done",
3064
+ "needs_attention",
3065
+ "skipped"
3066
+ ]);
3067
+ function isWorkflowItemRetryable(item) {
3068
+ return RETRYABLE_STATUSES.has(item.status);
3069
+ }
3070
+ function statusLabel(status) {
3071
+ if (status === "done") return "verified";
3072
+ if (status === "needs_attention") return "needs attention";
3073
+ return status;
3074
+ }
2925
3075
  function StatusIcon({ status }) {
2926
3076
  if (status === "done") return /*#__PURE__*/ (0,jsx_runtime.jsx)(check/* default */.A, {
2927
3077
  className: "h-3 w-3",
@@ -2951,11 +3101,15 @@ function statusClass(status) {
2951
3101
  if (status === "skipped") return "border-border/60 bg-surface text-fg-faint";
2952
3102
  return "border-border/60 bg-surface text-fg-faint";
2953
3103
  }
2954
- function WorkflowChecklist({ eyebrow, title, phaseLabel, summary, items, error, compact = false, children }) {
3104
+ function itemTooltip(item) {
3105
+ const note = item.status === "done" ? item.validation_evidence : item.reason;
3106
+ return note ? `${item.label}\n${statusLabel(item.status)}: ${note}` : item.label;
3107
+ }
3108
+ function WorkflowChecklist({ eyebrow, title, phaseLabel, summary, items, error, compact = false, onRetryItem, canRetryItem, retryDisabled = false, children }) {
2955
3109
  return /*#__PURE__*/ (0,jsx_runtime.jsxs)("div", {
2956
3110
  className: compact ? "flex flex-col gap-1.5" : "absolute inset-x-0 top-0 flex flex-col gap-2 transition-opacity duration-300",
2957
3111
  children: [
2958
- /*#__PURE__*/ (0,jsx_runtime.jsx)("p", {
3112
+ !compact && /*#__PURE__*/ (0,jsx_runtime.jsx)("p", {
2959
3113
  className: "text-[10px] text-fg-faint uppercase tracking-wider text-center",
2960
3114
  children: eyebrow
2961
3115
  }),
@@ -2975,99 +3129,59 @@ function WorkflowChecklist({ eyebrow, title, phaseLabel, summary, items, error,
2975
3129
  })
2976
3130
  ]
2977
3131
  }),
2978
- /*#__PURE__*/ (0,jsx_runtime.jsx)("p", {
3132
+ !compact && summary && /*#__PURE__*/ (0,jsx_runtime.jsx)("p", {
2979
3133
  className: "mt-1 text-[11px] leading-snug text-fg-muted line-clamp-2",
2980
3134
  children: summary
2981
3135
  }),
2982
- /*#__PURE__*/ (0,jsx_runtime.jsx)("div", {
2983
- className: compact ? "mt-1.5 flex max-h-32 flex-col gap-1 overflow-y-auto pr-1" : "mt-2 flex max-h-32 flex-col gap-1 overflow-y-auto pr-1",
2984
- children: items.map((item)=>/*#__PURE__*/ (0,jsx_runtime.jsxs)("div", {
2985
- className: compact ? "rounded border border-border/30 bg-surface-2/40 px-1.5 py-1 text-[10px] leading-tight text-fg-muted" : "text-[10px] leading-tight text-fg-muted",
3136
+ /*#__PURE__*/ (0,jsx_runtime.jsx)("ul", {
3137
+ 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",
3138
+ children: items.map((item)=>{
3139
+ const retryable = !!onRetryItem && isWorkflowItemRetryable(item) && (canRetryItem ? canRetryItem(item) : true);
3140
+ return /*#__PURE__*/ (0,jsx_runtime.jsxs)("li", {
3141
+ className: "group flex items-center gap-1.5 text-[10px] leading-tight text-fg-muted",
2986
3142
  children: [
2987
- /*#__PURE__*/ (0,jsx_runtime.jsxs)("div", {
2988
- className: "flex items-start gap-1.5",
2989
- children: [
2990
- /*#__PURE__*/ (0,jsx_runtime.jsx)("span", {
2991
- "aria-label": item.status,
2992
- className: [
2993
- "mt-0.5 flex h-4 w-4 shrink-0 items-center justify-center rounded border",
2994
- statusClass(item.status)
2995
- ].join(" "),
2996
- children: /*#__PURE__*/ (0,jsx_runtime.jsx)(StatusIcon, {
2997
- status: item.status
2998
- })
2999
- }),
3000
- /*#__PURE__*/ (0,jsx_runtime.jsx)("span", {
3001
- className: compact ? "min-w-0 flex-1 truncate" : "line-clamp-2",
3002
- title: item.label,
3003
- children: item.label
3004
- })
3005
- ]
3143
+ /*#__PURE__*/ (0,jsx_runtime.jsx)("span", {
3144
+ role: "img",
3145
+ "aria-label": statusLabel(item.status),
3146
+ className: [
3147
+ "flex h-4 w-4 shrink-0 items-center justify-center rounded border",
3148
+ statusClass(item.status)
3149
+ ].join(" "),
3150
+ children: /*#__PURE__*/ (0,jsx_runtime.jsx)(StatusIcon, {
3151
+ status: item.status
3152
+ })
3153
+ }),
3154
+ /*#__PURE__*/ (0,jsx_runtime.jsx)("span", {
3155
+ className: compact ? "min-w-0 flex-1 truncate" : "min-w-0 flex-1 line-clamp-2",
3156
+ title: itemTooltip(item),
3157
+ children: item.label
3006
3158
  }),
3007
- (item.input || item.output || item.validation || item.validation_evidence) && /*#__PURE__*/ (0,jsx_runtime.jsxs)("details", {
3008
- className: "mt-1 pl-5",
3159
+ (item.attempts ?? 0) > 1 && /*#__PURE__*/ (0,jsx_runtime.jsxs)("span", {
3160
+ className: "shrink-0 text-[9px] tabular-nums text-fg-faint",
3161
+ title: `Attempt ${item.attempts}`,
3009
3162
  children: [
3010
- /*#__PURE__*/ (0,jsx_runtime.jsx)("summary", {
3011
- className: "cursor-pointer text-fg-faint",
3012
- children: "Step contract"
3013
- }),
3014
- /*#__PURE__*/ (0,jsx_runtime.jsxs)("dl", {
3015
- className: "mt-1 grid grid-cols-[auto_minmax(0,1fr)] gap-x-2 gap-y-1",
3016
- children: [
3017
- item.input && /*#__PURE__*/ (0,jsx_runtime.jsxs)(jsx_runtime.Fragment, {
3018
- children: [
3019
- /*#__PURE__*/ (0,jsx_runtime.jsx)("dt", {
3020
- className: "text-fg-faint",
3021
- children: "Input"
3022
- }),
3023
- /*#__PURE__*/ (0,jsx_runtime.jsx)("dd", {
3024
- className: "break-words",
3025
- children: item.input
3026
- })
3027
- ]
3028
- }),
3029
- item.output && /*#__PURE__*/ (0,jsx_runtime.jsxs)(jsx_runtime.Fragment, {
3030
- children: [
3031
- /*#__PURE__*/ (0,jsx_runtime.jsx)("dt", {
3032
- className: "text-fg-faint",
3033
- children: "Output"
3034
- }),
3035
- /*#__PURE__*/ (0,jsx_runtime.jsx)("dd", {
3036
- className: "break-words",
3037
- children: item.output
3038
- })
3039
- ]
3040
- }),
3041
- item.validation && /*#__PURE__*/ (0,jsx_runtime.jsxs)(jsx_runtime.Fragment, {
3042
- children: [
3043
- /*#__PURE__*/ (0,jsx_runtime.jsx)("dt", {
3044
- className: "text-fg-faint",
3045
- children: "Validation"
3046
- }),
3047
- /*#__PURE__*/ (0,jsx_runtime.jsx)("dd", {
3048
- className: "break-words",
3049
- children: item.validation
3050
- })
3051
- ]
3052
- }),
3053
- item.validation_evidence && /*#__PURE__*/ (0,jsx_runtime.jsxs)(jsx_runtime.Fragment, {
3054
- children: [
3055
- /*#__PURE__*/ (0,jsx_runtime.jsx)("dt", {
3056
- className: "text-fg-faint",
3057
- children: "Evidence"
3058
- }),
3059
- /*#__PURE__*/ (0,jsx_runtime.jsx)("dd", {
3060
- className: "break-words",
3061
- children: item.validation_evidence
3062
- })
3063
- ]
3064
- })
3065
- ]
3066
- })
3163
+ "attempt ",
3164
+ item.attempts
3067
3165
  ]
3166
+ }),
3167
+ retryable && /*#__PURE__*/ (0,jsx_runtime.jsx)("button", {
3168
+ type: "button",
3169
+ onClick: ()=>onRetryItem(item),
3170
+ disabled: retryDisabled,
3171
+ "aria-label": `Retry ${item.label}`,
3172
+ title: `Retry ${item.label}`,
3173
+ className: [
3174
+ "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",
3175
+ item.status === "needs_attention" ? "" : "opacity-0 focus:opacity-100 group-hover:opacity-100"
3176
+ ].join(" "),
3177
+ children: /*#__PURE__*/ (0,jsx_runtime.jsx)(rotate_ccw/* default */.A, {
3178
+ className: "h-3 w-3",
3179
+ "aria-hidden": true
3180
+ })
3068
3181
  })
3069
3182
  ]
3070
- }, item.id))
3183
+ }, item.id);
3184
+ })
3071
3185
  }),
3072
3186
  error && /*#__PURE__*/ (0,jsx_runtime.jsx)("p", {
3073
3187
  className: "mt-2 text-[10px] leading-tight text-red-400",
@@ -3080,6 +3194,21 @@ function WorkflowChecklist({ eyebrow, title, phaseLabel, summary, items, error,
3080
3194
  });
3081
3195
  }
3082
3196
 
3197
+ ;// ./components/chat/workflow-step-retry.ts
3198
+
3199
+ /** Sends a retry request for one workflow step; null when the surface cannot send messages. */ const WorkflowStepRetryContext = (0,react.createContext)(null);
3200
+ function useWorkflowStepRetry() {
3201
+ return (0,react.useContext)(WorkflowStepRetryContext);
3202
+ }
3203
+ function workflowStepRetryMessage({ workflowId, itemId, label }) {
3204
+ 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\``;
3205
+ return [
3206
+ `Retry workflow step "${label}" (item \`${itemId}\`) in workflow \`${workflowId}\`.`,
3207
+ `${progressUpdate}, then redo the step from its stated input and run its validation again.`,
3208
+ "Finally mark it `done` with newly observed `validation_evidence`, or `needs_attention` with the reason. Leave the other steps unchanged."
3209
+ ].join(" ");
3210
+ }
3211
+
3083
3212
  // EXTERNAL MODULE: ./node_modules/lucide-react/dist/esm/icons/clock.mjs
3084
3213
  var clock = __webpack_require__(6923);
3085
3214
  // EXTERNAL MODULE: ./node_modules/lucide-react/dist/esm/icons/message-circle.mjs
@@ -3268,6 +3397,7 @@ var ProviderLogo = __webpack_require__(85516);
3268
3397
 
3269
3398
 
3270
3399
 
3400
+
3271
3401
  // Distinct lucide glyph per internal tool family so the chat transcript
3272
3402
  // is glanceable — operator can tell a file write from a web fetch from a
3273
3403
  // schedule from a memory read without reading the tool name.
@@ -3705,7 +3835,34 @@ function groupByCallId(events) {
3705
3835
  }
3706
3836
  g.absorbed = true;
3707
3837
  }
3708
- return order.map((id)=>map.get(id)).filter((g)=>!g.absorbed);
3838
+ const groups = order.map((id)=>map.get(id)).filter((g)=>!g.absorbed);
3839
+ annotateWorkflowAttempts(groups);
3840
+ return groups;
3841
+ }
3842
+ // Counts each workflow step's transitions into `checking` across the
3843
+ // message's workflow_progress calls, so auto-retried steps show "attempt N".
3844
+ // Rejected updates (ok:false) changed nothing and are not counted.
3845
+ function annotateWorkflowAttempts(groups) {
3846
+ const lastStatus = new Map();
3847
+ const attempts = new Map();
3848
+ for (const group of groups){
3849
+ if (group.name !== "workflow_progress") continue;
3850
+ if (coerceObject(unwrapLangChainSerializable(group.result))?.ok === false) continue;
3851
+ const view = workflowViewFor(group);
3852
+ if (!view) continue;
3853
+ const counts = {
3854
+ ...attempts.get(view.workflow_id) ?? {}
3855
+ };
3856
+ for (const item of view.items){
3857
+ const key = `${view.workflow_id}:${item.id}`;
3858
+ if (item.status === "checking" && lastStatus.get(key) !== "checking") {
3859
+ counts[item.id] = (counts[item.id] ?? 0) + 1;
3860
+ }
3861
+ lastStatus.set(key, item.status);
3862
+ }
3863
+ attempts.set(view.workflow_id, counts);
3864
+ group.workflowAttempts = counts;
3865
+ }
3709
3866
  }
3710
3867
  function ToolCallCard({ group, startedAt }) {
3711
3868
  const [open, setOpen] = (0,react.useState)(false);
@@ -3818,23 +3975,27 @@ function ToolCallCard({ group, startedAt }) {
3818
3975
  /*#__PURE__*/ (0,jsx_runtime.jsx)(WorkflowProgressDetails, {
3819
3976
  group: group
3820
3977
  }),
3821
- hasVisibleArgs(group.args) ? /*#__PURE__*/ (0,jsx_runtime.jsx)(DetailSection, {
3822
- label: "arguments",
3823
- value: group.args
3824
- }) : hasArgs ? /*#__PURE__*/ (0,jsx_runtime.jsx)(DetailSection, {
3825
- label: "arguments (inferred from result)",
3826
- value: effectiveArgs
3827
- }) : null,
3828
- group.status !== "running" && group.status !== "async" && (isToolResultRefEnvelope(group.result) ? /*#__PURE__*/ (0,jsx_runtime.jsx)(ToolResultRefDetails, {
3829
- value: group.result
3830
- }) : /*#__PURE__*/ (0,jsx_runtime.jsx)(DetailSection, {
3831
- label: group.status === "error" ? "error" : "result",
3832
- value: group.result,
3833
- tone: group.status === "error" ? "error" : "default"
3834
- })),
3835
- group.status === "async" && /*#__PURE__*/ (0,jsx_runtime.jsx)(DetailSection, {
3836
- label: "background handoff",
3837
- value: group.result
3978
+ !hasWorkflowView(group) && /*#__PURE__*/ (0,jsx_runtime.jsxs)(jsx_runtime.Fragment, {
3979
+ children: [
3980
+ hasVisibleArgs(group.args) ? /*#__PURE__*/ (0,jsx_runtime.jsx)(DetailSection, {
3981
+ label: "arguments",
3982
+ value: group.args
3983
+ }) : hasArgs ? /*#__PURE__*/ (0,jsx_runtime.jsx)(DetailSection, {
3984
+ label: "arguments (inferred from result)",
3985
+ value: effectiveArgs
3986
+ }) : null,
3987
+ group.status !== "running" && group.status !== "async" && (isToolResultRefEnvelope(group.result) ? /*#__PURE__*/ (0,jsx_runtime.jsx)(ToolResultRefDetails, {
3988
+ value: group.result
3989
+ }) : /*#__PURE__*/ (0,jsx_runtime.jsx)(DetailSection, {
3990
+ label: group.status === "error" ? "error" : "result",
3991
+ value: group.result,
3992
+ tone: group.status === "error" ? "error" : "default"
3993
+ })),
3994
+ group.status === "async" && /*#__PURE__*/ (0,jsx_runtime.jsx)(DetailSection, {
3995
+ label: "background handoff",
3996
+ value: group.result
3997
+ })
3998
+ ]
3838
3999
  })
3839
4000
  ]
3840
4001
  })
@@ -3969,18 +4130,47 @@ function ToolResultRefDetails({ value }) {
3969
4130
  ]
3970
4131
  });
3971
4132
  }
3972
- function WorkflowProgressDetails({ group }) {
4133
+ function workflowViewFor(group) {
3973
4134
  if (group.name !== "workflow_progress") return null;
3974
- const workflow = workflowProgressFrom(group.result) ?? workflowProgressPreviewFrom(group.args);
4135
+ const view = workflowProgressFrom(group.result) ?? workflowProgressPreviewFrom(group.args);
4136
+ const result = coerceObject(unwrapLangChainSerializable(group.result));
4137
+ const attempts = group.workflowAttempts;
4138
+ const withAttempts = view && attempts ? {
4139
+ ...view,
4140
+ items: view.items.map((item)=>attempts[item.id] ? {
4141
+ ...item,
4142
+ attempts: attempts[item.id]
4143
+ } : item)
4144
+ } : view;
4145
+ if (withAttempts && result?.ok === false && typeof result.error === "string") {
4146
+ return {
4147
+ ...withAttempts,
4148
+ error: `Update rejected: ${result.error}`
4149
+ };
4150
+ }
4151
+ return withAttempts;
4152
+ }
4153
+ /** Workflow rows show only their work items; raw payloads stay visible when the call failed. */ function hasWorkflowView(group) {
4154
+ return group.status !== "error" && workflowViewFor(group) !== null;
4155
+ }
4156
+ function WorkflowProgressDetails({ group }) {
4157
+ const retryStep = useWorkflowStepRetry();
4158
+ const workflow = workflowViewFor(group);
3975
4159
  if (!workflow) return null;
4160
+ const workflowId = workflow.workflow_id;
3976
4161
  return /*#__PURE__*/ (0,jsx_runtime.jsx)(WorkflowChecklist, {
3977
4162
  compact: true,
3978
4163
  eyebrow: "workflow",
3979
- title: workflow.workflow_id.replace(/[_-]/g, " "),
4164
+ title: workflowId.replace(/[_-]/g, " "),
3980
4165
  phaseLabel: workflow.phase ?? "in progress",
3981
4166
  summary: workflow.summary ?? "",
3982
4167
  items: workflow.items,
3983
- error: workflow.error
4168
+ error: workflow.error,
4169
+ onRetryItem: retryStep ? (item)=>retryStep({
4170
+ workflowId,
4171
+ itemId: item.id,
4172
+ label: item.label
4173
+ }) : undefined
3984
4174
  });
3985
4175
  }
3986
4176
  function workflowProgressFrom(payload) {
@@ -4966,8 +5156,6 @@ var shield_check = __webpack_require__(50981);
4966
5156
  var copy = __webpack_require__(99314);
4967
5157
  // EXTERNAL MODULE: ./node_modules/lucide-react/dist/esm/icons/link-2.mjs
4968
5158
  var link_2 = __webpack_require__(51128);
4969
- // EXTERNAL MODULE: ./node_modules/lucide-react/dist/esm/icons/rotate-ccw.mjs
4970
- var rotate_ccw = __webpack_require__(92298);
4971
5159
  // EXTERNAL MODULE: ./node_modules/lucide-react/dist/esm/icons/pause.mjs
4972
5160
  var pause = __webpack_require__(79267);
4973
5161
  // EXTERNAL MODULE: ./node_modules/lucide-react/dist/esm/icons/play.mjs
@@ -8346,7 +8534,7 @@ function StatusDot({ tone = "neutral", size = "xs", pulse, className, style, lab
8346
8534
  }
8347
8535
 
8348
8536
  ;// ./components/chat/ContextBoundary.tsx
8349
- /* __next_internal_client_entry_do_not_use__ WarmSummaryCard,ContextBoundaryDivider auto */
8537
+ /* __next_internal_client_entry_do_not_use__ WarmSummaryCard,ContextBoundaryDivider,topicsFromSummarySections auto */
8350
8538
  // Inline visual artefacts for ADR-0042: the warm-summary card and the
8351
8539
  // context-boundary divider that sits below it. Rendered by MessageList in
8352
8540
  // the message stream — between summarised history (above) and the active
@@ -8358,17 +8546,25 @@ function StatusDot({ tone = "neutral", size = "xs", pulse, className, style, lab
8358
8546
 
8359
8547
 
8360
8548
 
8361
- function WarmSummaryCard({ olderCount, summary, summaryBeforeSeq, hotSinceSeq, computedAt, streaming, topics }) {
8549
+ const CHANNEL_LABELS = {
8550
+ bridge: "Bridge",
8551
+ watcher: "Watchers",
8552
+ scheduled_task: "Scheduled tasks"
8553
+ };
8554
+ function WarmSummaryCard({ olderCount, summary, summaryBeforeSeq, hotSinceSeq, computedAt, streaming, topics, channelSummaries = [] }) {
8362
8555
  const [expanded, setExpanded] = (0,react.useState)(false);
8363
- const fresh = !!summary && hotSinceSeq != null && summaryBeforeSeq === hotSinceSeq;
8556
+ const committed = hotSinceSeq != null && summaryBeforeSeq === hotSinceSeq;
8557
+ const fresh = !!summary && committed;
8364
8558
  const stale = !!summary && !fresh;
8365
8559
  const computing = stale && streaming;
8366
- const summaryTopics = summary && topics && topics.length > 0 ? topics : null;
8560
+ // Summaries stored before topic segmentation still read as topics: their
8561
+ // markdown sections render through the same collapsible rows.
8562
+ const summaryTopics = summary ? topics && topics.length > 0 ? topics : topicsFromSummarySections(summary) : null;
8367
8563
  return /*#__PURE__*/ (0,jsx_runtime.jsxs)("div", {
8368
8564
  className: [
8369
8565
  "relative my-4 rounded-2xl border bg-gradient-to-br shadow-sm",
8370
8566
  "from-accent/[0.06] via-surface-2 to-surface-2",
8371
- fresh ? "border-accent/30" : "border-border"
8567
+ fresh || committed ? "border-accent/30" : "border-border"
8372
8568
  ].join(" "),
8373
8569
  children: [
8374
8570
  /*#__PURE__*/ (0,jsx_runtime.jsxs)("div", {
@@ -8413,6 +8609,9 @@ function WarmSummaryCard({ olderCount, summary, summaryBeforeSeq, hotSinceSeq, c
8413
8609
  children: /*#__PURE__*/ (0,jsx_runtime.jsx)(lib/* Markdown */.oz, {
8414
8610
  children: stripWarmHeader(summary)
8415
8611
  })
8612
+ }) : !summary && committed ? channelSummaries.length === 0 && /*#__PURE__*/ (0,jsx_runtime.jsx)("div", {
8613
+ className: "text-xs text-fg-faint italic",
8614
+ children: "No earlier chat messages needed summarising."
8416
8615
  }) : !summary ? /*#__PURE__*/ (0,jsx_runtime.jsxs)("div", {
8417
8616
  className: "flex items-center gap-2 text-xs text-fg-faint italic",
8418
8617
  children: [
@@ -8426,6 +8625,9 @@ function WarmSummaryCard({ olderCount, summary, summaryBeforeSeq, hotSinceSeq, c
8426
8625
  })
8427
8626
  ]
8428
8627
  }) : null,
8628
+ channelSummaries.map((channel)=>/*#__PURE__*/ (0,jsx_runtime.jsx)(ChannelSummarySection, {
8629
+ channel: channel
8630
+ }, channel.channel)),
8429
8631
  stale && /*#__PURE__*/ (0,jsx_runtime.jsxs)("div", {
8430
8632
  className: "mt-2 inline-flex items-center gap-2 text-[11px] text-fg-faint",
8431
8633
  children: [
@@ -8467,6 +8669,32 @@ function WarmSummaryCard({ olderCount, summary, summaryBeforeSeq, hotSinceSeq, c
8467
8669
  ]
8468
8670
  });
8469
8671
  }
8672
+ function ChannelSummarySection({ channel }) {
8673
+ const topics = channel.topics && channel.topics.length > 0 ? channel.topics : topicsFromSummarySections(channel.summary) ?? [
8674
+ {
8675
+ title: "Recap",
8676
+ start_at: "",
8677
+ end_at: "",
8678
+ recap: stripWarmHeader(channel.summary),
8679
+ facts: []
8680
+ }
8681
+ ];
8682
+ return /*#__PURE__*/ (0,jsx_runtime.jsxs)("div", {
8683
+ className: "mt-2",
8684
+ children: [
8685
+ /*#__PURE__*/ (0,jsx_runtime.jsx)("div", {
8686
+ className: "mb-1 text-[9px] uppercase tracking-wide text-fg-faint",
8687
+ children: CHANNEL_LABELS[channel.channel] ?? channel.channel
8688
+ }),
8689
+ /*#__PURE__*/ (0,jsx_runtime.jsx)("div", {
8690
+ className: "flex flex-col gap-1",
8691
+ children: topics.map((topic, i)=>/*#__PURE__*/ (0,jsx_runtime.jsx)(TopicSegmentRow, {
8692
+ topic: topic
8693
+ }, `${channel.channel}-${topic.title}-${i}`))
8694
+ })
8695
+ ]
8696
+ });
8697
+ }
8470
8698
  function TopicSegmentRow({ topic }) {
8471
8699
  const [open, setOpen] = (0,react.useState)(false);
8472
8700
  const range = formatTopicRange(topic.start_at, topic.end_at);
@@ -8494,13 +8722,20 @@ function TopicSegmentRow({ topic }) {
8494
8722
  range
8495
8723
  ]
8496
8724
  }),
8725
+ typeof topic.message_count === "number" && topic.message_count > 0 && /*#__PURE__*/ (0,jsx_runtime.jsxs)("span", {
8726
+ className: "text-fg-faint shrink-0",
8727
+ children: [
8728
+ "\xb7 ",
8729
+ topic.message_count,
8730
+ " ",
8731
+ topic.message_count === 1 ? "msg" : "msgs"
8732
+ ]
8733
+ }),
8497
8734
  topic.facts.length > 0 && /*#__PURE__*/ (0,jsx_runtime.jsxs)("span", {
8498
8735
  className: "ml-auto shrink-0 text-[9px] uppercase tracking-wide text-accent",
8499
8736
  children: [
8500
8737
  topic.facts.length,
8501
- " ",
8502
- topic.facts.length === 1 ? "fact" : "facts",
8503
- " saved"
8738
+ " memorized"
8504
8739
  ]
8505
8740
  })
8506
8741
  ]
@@ -8520,22 +8755,34 @@ function TopicSegmentRow({ topic }) {
8520
8755
  children: topic.recap
8521
8756
  })
8522
8757
  }),
8523
- topic.facts.length > 0 && /*#__PURE__*/ (0,jsx_runtime.jsx)("ul", {
8524
- className: "space-y-0.5",
8525
- children: topic.facts.map((fact, i)=>/*#__PURE__*/ (0,jsx_runtime.jsxs)("li", {
8526
- className: "text-[11px] text-fg-faint",
8527
- children: [
8528
- /*#__PURE__*/ (0,jsx_runtime.jsxs)("span", {
8529
- className: "font-medium text-fg-muted",
8758
+ topic.facts.length > 0 && /*#__PURE__*/ (0,jsx_runtime.jsxs)("div", {
8759
+ children: [
8760
+ /*#__PURE__*/ (0,jsx_runtime.jsx)("div", {
8761
+ className: "text-[9px] uppercase tracking-wide text-fg-faint",
8762
+ children: "Memorized"
8763
+ }),
8764
+ /*#__PURE__*/ (0,jsx_runtime.jsx)("ul", {
8765
+ className: "space-y-0.5",
8766
+ children: topic.facts.map((fact, i)=>/*#__PURE__*/ (0,jsx_runtime.jsxs)("li", {
8767
+ className: "text-[11px] text-fg-faint",
8530
8768
  children: [
8531
- fact.subject,
8532
- ":"
8769
+ /*#__PURE__*/ (0,jsx_runtime.jsxs)("span", {
8770
+ className: "font-medium text-fg-muted",
8771
+ children: [
8772
+ fact.subject,
8773
+ ":"
8774
+ ]
8775
+ }),
8776
+ " ",
8777
+ fact.content,
8778
+ fact.key && /*#__PURE__*/ (0,jsx_runtime.jsx)("code", {
8779
+ className: "ml-1 text-[10px] text-fg-faint",
8780
+ children: fact.key
8781
+ })
8533
8782
  ]
8534
- }),
8535
- " ",
8536
- fact.content
8537
- ]
8538
- }, `${fact.subject}-${i}`))
8783
+ }, `${fact.key ?? fact.subject}-${i}`))
8784
+ })
8785
+ ]
8539
8786
  })
8540
8787
  ]
8541
8788
  })
@@ -8668,7 +8915,38 @@ function ContextBoundary_formatBytes(n) {
8668
8915
  // `buildWarmSummary` prepends a couple of plain-text header lines that read
8669
8916
  // awkwardly inside a card that already has its own header. Strip them.
8670
8917
  function stripWarmHeader(raw) {
8671
- return raw.replace(/^--- Warm context summary ---\n/, "").replace(/^Compressed recap of earlier messages outside the hot window:\n/, "").trimStart();
8918
+ return raw.replace(/\r\n/g, "\n").replace(/^\s*(<!--[\s\S]*?-->\s*)+/, "").replace(/^--- Warm context summary ---\n/, "").replace(/^Compressed recap of [^\n]*:\n/, "").trimStart();
8919
+ }
8920
+ /**
8921
+ * Splits a markdown summary into topic segments at its headings. Returns
8922
+ * null when there are fewer than two sections, so short or unstructured
8923
+ * summaries keep the plain prose rendering.
8924
+ */ function topicsFromSummarySections(raw) {
8925
+ const sections = [];
8926
+ let title = null;
8927
+ let body = [];
8928
+ const flush = ()=>{
8929
+ const recap = body.join("\n").trim();
8930
+ if (title !== null || recap) sections.push({
8931
+ title: title ?? "Overview",
8932
+ start_at: "",
8933
+ end_at: "",
8934
+ recap,
8935
+ facts: []
8936
+ });
8937
+ };
8938
+ for (const line of stripWarmHeader(raw).split("\n")){
8939
+ const heading = /^#{1,3}\s+(.+?)\s*#*\s*$/.exec(line);
8940
+ if (heading) {
8941
+ flush();
8942
+ title = heading[1];
8943
+ body = [];
8944
+ } else {
8945
+ body.push(line);
8946
+ }
8947
+ }
8948
+ flush();
8949
+ return sections.length >= 2 ? sections : null;
8672
8950
  }
8673
8951
  function summaryLong(raw) {
8674
8952
  // Heuristic: more than 6 lines or > 600 chars after the header strip.
@@ -8701,11 +8979,13 @@ function formatRelative(iso) {
8701
8979
 
8702
8980
 
8703
8981
 
8982
+
8704
8983
  const ALL_FILTERS_SHOWN = Object.fromEntries(MESSAGE_FILTER_KEYS.map((k)=>[
8705
8984
  k,
8706
8985
  true
8707
8986
  ]));
8708
- function MessageList({ threadId, messages, steeredSegments, notices, agentConfig, userProfile, streamingContent, thinkingContent, toolEvents, hasMore, loadingMore, onLoadMore, queuedMessages, onRemoveQueued, hotSinceSeq, warmSummary, warmSummaryBeforeSeq, warmSummaryComputedAt, warmSummarySourceMessages, warmSummarySourceChars, warmSummaryTopics, warmSummaryPending = false, compactionPending = false, onSetContextPin, streaming, contextWindowTokens, onRetryMessage, filters = ALL_FILTERS_SHOWN, onToggleFilter: toggle = ()=>{}, onResetFilters: reset = ()=>{} }) {
8987
+ const NO_CHANNEL_SUMMARIES = [];
8988
+ function MessageList({ threadId, messages, steeredSegments, agentConfig, userProfile, streamingContent, thinkingContent, toolEvents, hasMore, loadingMore, onLoadMore, queuedMessages, onRemoveQueued, hotSinceSeq, warmSummary, warmSummaryBeforeSeq, warmSummaryComputedAt, warmSummarySourceMessages, warmSummarySourceChars, warmSummaryTopics, warmChannelSummaries = NO_CHANNEL_SUMMARIES, warmSummaryPending = false, compactionPending = false, onSetContextPin, streaming, contextWindowTokens, onRetryMessage, filters = ALL_FILTERS_SHOWN, onToggleFilter: toggle = ()=>{}, onResetFilters: reset = ()=>{} }) {
8709
8989
  const hostRef = (0,react.useRef)(null);
8710
8990
  const maskRegionRef = (0,react.useRef)(null);
8711
8991
  const scrollRef = (0,react.useRef)(null);
@@ -8730,6 +9010,9 @@ function MessageList({ threadId, messages, steeredSegments, notices, agentConfig
8730
9010
  const [pendingHotSinceSeq, setPendingHotSinceSeq] = (0,react.useState)(null);
8731
9011
  const [topControlsOpen, setTopControlsOpen] = (0,react.useState)(false);
8732
9012
  const [summaryPopoverOpen, setSummaryPopoverOpen] = (0,react.useState)(false);
9013
+ const retryWorkflowStep = (0,react.useMemo)(()=>onRetryMessage ? (request)=>onRetryMessage(workflowStepRetryMessage(request), []) : null, [
9014
+ onRetryMessage
9015
+ ]);
8733
9016
  // Apply category filter. Messages with no `category` (NULL = ordinary
8734
9017
  // chat) are always shown; tagged messages are gated by their toggle.
8735
9018
  // The `tool_use` and `thinking` filters do NOT remove whole messages —
@@ -9099,7 +9382,11 @@ function MessageList({ threadId, messages, steeredSegments, notices, agentConfig
9099
9382
  const nextHotCount = pendingBoundaryIndex < 0 ? null : visibleMessages.length - pendingBoundaryIndex;
9100
9383
  const removesFromRecent = currentHotCount !== null && nextHotCount !== null ? nextHotCount < currentHotCount : false;
9101
9384
  const hasWarmSummary = !!warmSummary;
9385
+ // A committed boundary whose chat range had nothing to summarise (e.g. a
9386
+ // bridge-only agent): the recap, if any, lives in the channel summaries.
9387
+ const summaryCommittedEmpty = !hasWarmSummary && effectiveHotSinceSeq !== null && warmSummaryBeforeSeq === effectiveHotSinceSeq;
9102
9388
  const summaryFresh = hasWarmSummary && effectiveHotSinceSeq !== null && warmSummaryBeforeSeq === effectiveHotSinceSeq;
9389
+ const summaryReady = summaryFresh || summaryCommittedEmpty;
9103
9390
  const summaryUpdating = hasWarmSummary && !summaryFresh && !!streaming;
9104
9391
  const summaryStale = hasWarmSummary && !summaryFresh && !summaryUpdating;
9105
9392
  (0,react.useEffect)(()=>{
@@ -9200,10 +9487,29 @@ function MessageList({ threadId, messages, steeredSegments, notices, agentConfig
9200
9487
  }
9201
9488
  boundaryAnchorRef.current = null;
9202
9489
  }, []);
9490
+ // While a programmatic smooth scroll (locate boundary, deep link) animates
9491
+ // away from the bottom, its first frames are still "near bottom". Without
9492
+ // this lock, scroll sync re-arms bottom-follow and the post-render snap
9493
+ // cancels the animation, so the target is never reached.
9494
+ const programmaticScrollUntilRef = (0,react.useRef)(0);
9203
9495
  const syncScrollButton = (0,react.useCallback)((el)=>{
9204
9496
  const isAtBottom = el.scrollHeight - el.scrollTop - el.clientHeight < 100;
9205
- atBottomRef.current = isAtBottom;
9206
- setShowScrollButton(!isAtBottom && hasScrollTarget);
9497
+ const locked = Date.now() < programmaticScrollUntilRef.current;
9498
+ atBottomRef.current = isAtBottom && !locked;
9499
+ setShowScrollButton(!atBottomRef.current && hasScrollTarget);
9500
+ }, [
9501
+ hasScrollTarget
9502
+ ]);
9503
+ const scrollTargetIntoView = (0,react.useCallback)((target)=>{
9504
+ programmaticScrollUntilRef.current = Date.now() + PROGRAMMATIC_SCROLL_LOCK_MS;
9505
+ atBottomRef.current = false;
9506
+ setShowScrollButton(hasScrollTarget);
9507
+ target.scrollIntoView({
9508
+ behavior: "smooth",
9509
+ block: "center"
9510
+ });
9511
+ target.classList.add("jarela-deep-link-flash");
9512
+ window.setTimeout(()=>target.classList.remove("jarela-deep-link-flash"), 1600);
9207
9513
  }, [
9208
9514
  hasScrollTarget
9209
9515
  ]);
@@ -9332,14 +9638,7 @@ function MessageList({ threadId, messages, steeredSegments, notices, agentConfig
9332
9638
  const safe = id.replace(/"/g, '\\"');
9333
9639
  const el = root.querySelector(`[data-message-id="${safe}"]`);
9334
9640
  if (!el) return;
9335
- atBottomRef.current = false;
9336
- setShowScrollButton(hasScrollTarget);
9337
- el.scrollIntoView({
9338
- behavior: "smooth",
9339
- block: "center"
9340
- });
9341
- el.classList.add("jarela-deep-link-flash");
9342
- setTimeout(()=>el.classList.remove("jarela-deep-link-flash"), 1600);
9641
+ scrollTargetIntoView(el);
9343
9642
  // Strip the hash so the next streaming message / list-length change
9344
9643
  // doesn't yank the view back to this anchor. replaceState avoids
9345
9644
  // triggering a hashchange event (which would re-enter this handler).
@@ -9352,7 +9651,7 @@ function MessageList({ threadId, messages, steeredSegments, notices, agentConfig
9352
9651
  return ()=>window.removeEventListener("hashchange", scrollToHashTarget);
9353
9652
  }, [
9354
9653
  messages.length,
9355
- hasScrollTarget
9654
+ scrollTargetIntoView
9356
9655
  ]);
9357
9656
  // Handle orientation changes and resizes to maintain scroll position
9358
9657
  (0,react.useEffect)(()=>{
@@ -9383,419 +9682,411 @@ function MessageList({ threadId, messages, steeredSegments, notices, agentConfig
9383
9682
  if (!root) return;
9384
9683
  const boundary = effectiveHotSinceSeq !== null ? document.getElementById(`context-boundary-${effectiveHotSinceSeq}`) : root.querySelector("[data-focus-boundary='1']");
9385
9684
  if (!boundary) return;
9386
- atBottomRef.current = false;
9387
- setShowScrollButton(hasScrollTarget);
9388
- boundary.scrollIntoView({
9389
- behavior: "smooth",
9390
- block: "center"
9391
- });
9685
+ scrollTargetIntoView(boundary);
9392
9686
  }
9393
- return /*#__PURE__*/ (0,jsx_runtime.jsxs)("div", {
9394
- ref: hostRef,
9395
- className: "flex-1 flex flex-col min-h-0 relative",
9396
- children: [
9397
- visibleMessages.length > 0 && /*#__PURE__*/ (0,jsx_runtime.jsx)("div", {
9398
- className: "shrink-0 px-4 pt-[calc(var(--app-safe-top)+3rem)] pb-1",
9399
- children: /*#__PURE__*/ (0,jsx_runtime.jsxs)("div", {
9400
- className: "w-full border-b border-border/45 bg-surface/30 px-2 py-1 backdrop-blur-sm",
9687
+ return /*#__PURE__*/ (0,jsx_runtime.jsx)(WorkflowStepRetryContext.Provider, {
9688
+ value: retryWorkflowStep,
9689
+ children: /*#__PURE__*/ (0,jsx_runtime.jsxs)("div", {
9690
+ ref: hostRef,
9691
+ className: "flex-1 flex flex-col min-h-0 relative",
9692
+ children: [
9693
+ visibleMessages.length > 0 && /*#__PURE__*/ (0,jsx_runtime.jsx)("div", {
9694
+ className: "shrink-0 px-4 pt-[calc(var(--app-safe-top)+3rem)] pb-1",
9695
+ children: /*#__PURE__*/ (0,jsx_runtime.jsxs)("div", {
9696
+ className: "w-full border-b border-border/45 bg-surface/30 px-2 py-1 backdrop-blur-sm",
9697
+ children: [
9698
+ /*#__PURE__*/ (0,jsx_runtime.jsxs)("button", {
9699
+ type: "button",
9700
+ onClick: ()=>setTopControlsOpen((v)=>!v),
9701
+ "aria-expanded": topControlsOpen,
9702
+ className: "w-full flex items-center gap-2 py-0.5 text-[11px] text-fg-faint hover:text-fg transition-colors",
9703
+ children: [
9704
+ /*#__PURE__*/ (0,jsx_runtime.jsx)(CollapseChevron, {
9705
+ open: topControlsOpen,
9706
+ size: 10
9707
+ }),
9708
+ /*#__PURE__*/ (0,jsx_runtime.jsx)("span", {
9709
+ className: "font-semibold uppercase tracking-[0.16em]",
9710
+ children: "Filters & focus"
9711
+ }),
9712
+ hiddenCount > 0 && /*#__PURE__*/ (0,jsx_runtime.jsxs)("span", {
9713
+ className: "ml-auto text-[10px] text-fg-faint",
9714
+ "aria-live": "polite",
9715
+ children: [
9716
+ hiddenCount,
9717
+ " hidden"
9718
+ ]
9719
+ })
9720
+ ]
9721
+ }),
9722
+ topControlsOpen && /*#__PURE__*/ (0,jsx_runtime.jsxs)("div", {
9723
+ className: "mt-1 flex items-center gap-1.5 flex-wrap py-1",
9724
+ children: [
9725
+ availableChips.map((key)=>{
9726
+ const on = filters[key];
9727
+ const Icon = on ? eye/* default */.A : eye_off/* default */.A;
9728
+ return /*#__PURE__*/ (0,jsx_runtime.jsxs)("button", {
9729
+ type: "button",
9730
+ onClick: ()=>toggle(key),
9731
+ className: [
9732
+ "inline-flex items-center gap-1 rounded-none border px-2 py-0.5 text-[10px] leading-4 transition-colors",
9733
+ 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"
9734
+ ].join(" "),
9735
+ title: // ADR-0044 — for the three channels the model's own
9736
+ // context is scoped by, the chip's meaning is dual:
9737
+ // it doesn't just show/hide rows here, it also
9738
+ // decides whether that channel's history is folded
9739
+ // into the next turn the agent sees.
9740
+ 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`,
9741
+ "aria-pressed": on,
9742
+ children: [
9743
+ /*#__PURE__*/ (0,jsx_runtime.jsx)(Icon, {
9744
+ size: 10
9745
+ }),
9746
+ /*#__PURE__*/ (0,jsx_runtime.jsx)("span", {
9747
+ children: CHIP_LABELS[key]
9748
+ })
9749
+ ]
9750
+ }, key);
9751
+ }),
9752
+ onSetContextPin && /*#__PURE__*/ (0,jsx_runtime.jsx)("button", {
9753
+ type: "button",
9754
+ onClick: scrollToBoundaryLine,
9755
+ disabled: !hasContextPin,
9756
+ 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",
9757
+ 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",
9758
+ children: "Locate boundary line"
9759
+ })
9760
+ ]
9761
+ })
9762
+ ]
9763
+ })
9764
+ }),
9765
+ /*#__PURE__*/ (0,jsx_runtime.jsxs)("div", {
9766
+ ref: maskRegionRef,
9767
+ className: "relative flex-1 min-h-0 overflow-hidden",
9401
9768
  children: [
9402
- /*#__PURE__*/ (0,jsx_runtime.jsxs)("button", {
9403
- type: "button",
9404
- onClick: ()=>setTopControlsOpen((v)=>!v),
9405
- "aria-expanded": topControlsOpen,
9406
- className: "w-full flex items-center gap-2 py-0.5 text-[11px] text-fg-faint hover:text-fg transition-colors",
9769
+ /*#__PURE__*/ (0,jsx_runtime.jsxs)("div", {
9770
+ ref: scrollRef,
9771
+ onScroll: handleScroll,
9772
+ className: "flex-1 h-full overflow-y-auto overflow-x-hidden px-4 py-4 panel-scrollbar",
9773
+ style: {
9774
+ // Scroll-anchor jumps (deep-link to a message) land below the
9775
+ // floating header, not under it.
9776
+ scrollPaddingTop: "calc(3rem + var(--app-safe-top))"
9777
+ },
9407
9778
  children: [
9408
- /*#__PURE__*/ (0,jsx_runtime.jsx)(CollapseChevron, {
9409
- open: topControlsOpen,
9410
- size: 10
9411
- }),
9412
- /*#__PURE__*/ (0,jsx_runtime.jsx)("span", {
9413
- className: "font-semibold uppercase tracking-[0.16em]",
9414
- children: "Filters & focus"
9779
+ hasMore && /*#__PURE__*/ (0,jsx_runtime.jsx)("div", {
9780
+ className: "text-center py-1.5 text-[11px] text-fg-faint select-none",
9781
+ children: loadingMore ? "Loading earlier messages…" : "Scroll up for earlier messages"
9415
9782
  }),
9416
- hiddenCount > 0 && /*#__PURE__*/ (0,jsx_runtime.jsxs)("span", {
9417
- className: "ml-auto text-[10px] text-fg-faint",
9418
- "aria-live": "polite",
9783
+ compactionPending && /*#__PURE__*/ (0,jsx_runtime.jsxs)("div", {
9784
+ className: "my-2 flex items-center justify-center gap-2 rounded-lg border border-border bg-surface-2/70 px-3 py-1.5 text-[11px] text-fg-faint select-none",
9419
9785
  children: [
9420
- hiddenCount,
9421
- " hidden"
9786
+ /*#__PURE__*/ (0,jsx_runtime.jsx)(StatusDot, {
9787
+ tone: "accent",
9788
+ size: "sm",
9789
+ pulse: true
9790
+ }),
9791
+ /*#__PURE__*/ (0,jsx_runtime.jsx)("span", {
9792
+ children: "Summarising earlier messages… this turn still sees the full history."
9793
+ })
9422
9794
  ]
9423
- })
9424
- ]
9425
- }),
9426
- topControlsOpen && /*#__PURE__*/ (0,jsx_runtime.jsxs)("div", {
9427
- className: "mt-1 flex items-center gap-1.5 flex-wrap py-1",
9428
- children: [
9429
- availableChips.map((key)=>{
9430
- const on = filters[key];
9431
- const Icon = on ? eye/* default */.A : eye_off/* default */.A;
9432
- return /*#__PURE__*/ (0,jsx_runtime.jsxs)("button", {
9433
- type: "button",
9434
- onClick: ()=>toggle(key),
9435
- className: [
9436
- "inline-flex items-center gap-1 rounded-none border px-2 py-0.5 text-[10px] leading-4 transition-colors",
9437
- on ? "border-border/70 bg-surface-2/70 text-fg-muted hover:text-fg" : "border-border/35 bg-transparent text-fg-faint line-through decoration-fg-faint/60 hover:text-fg-muted"
9438
- ].join(" "),
9439
- title: // ADR-0044 — for the three channels the model's own
9440
- // context is scoped by, the chip's meaning is dual:
9441
- // it doesn't just show/hide rows here, it also
9442
- // decides whether that channel's history is folded
9443
- // into the next turn the agent sees.
9444
- CHANNEL_SCOPED_FILTER_KEYS.has(key) ? on ? `Hide + exclude ${CHIP_LABELS[key]} from the next turn` : `Show + include ${CHIP_LABELS[key]} in the next turn` : on ? `Hide ${CHIP_LABELS[key]} messages` : `Show ${CHIP_LABELS[key]} messages`,
9445
- "aria-pressed": on,
9795
+ }),
9796
+ visibleMessages.length === 0 && !streamingContent && /*#__PURE__*/ (0,jsx_runtime.jsx)("div", {
9797
+ className: "flex items-center justify-center h-full text-fg-faint text-sm select-none",
9798
+ children: messages.length === 0 ? /*#__PURE__*/ (0,jsx_runtime.jsx)("span", {
9799
+ children: "Send a message to begin"
9800
+ }) : /*#__PURE__*/ (0,jsx_runtime.jsxs)("div", {
9801
+ className: "flex flex-col items-center gap-2 text-center px-4",
9446
9802
  children: [
9447
- /*#__PURE__*/ (0,jsx_runtime.jsx)(Icon, {
9448
- size: 10
9803
+ /*#__PURE__*/ (0,jsx_runtime.jsxs)("span", {
9804
+ children: [
9805
+ hiddenCount,
9806
+ " message",
9807
+ hiddenCount === 1 ? " is" : "s are",
9808
+ " hidden by filters"
9809
+ ]
9449
9810
  }),
9450
- /*#__PURE__*/ (0,jsx_runtime.jsx)("span", {
9451
- children: CHIP_LABELS[key]
9811
+ /*#__PURE__*/ (0,jsx_runtime.jsx)("button", {
9812
+ type: "button",
9813
+ onClick: reset,
9814
+ 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",
9815
+ children: "Show all messages"
9452
9816
  })
9453
9817
  ]
9454
- }, key);
9818
+ })
9455
9819
  }),
9456
- onSetContextPin && /*#__PURE__*/ (0,jsx_runtime.jsx)("button", {
9457
- type: "button",
9458
- onClick: scrollToBoundaryLine,
9459
- disabled: !hasContextPin,
9460
- className: "control-tap ml-auto rounded-none border border-border/60 bg-surface-2/70 px-2 py-0.5 text-[10px] leading-4 text-fg-faint transition-colors hover:border-accent/40 hover:text-fg disabled:cursor-not-allowed disabled:opacity-40 disabled:hover:border-border/60 disabled:hover:text-fg-faint",
9461
- title: hasContextPin ? "Locate the focus boundary in the message list" : "Set a focus boundary first (drag the divider or pin a message) to enable this",
9462
- children: "Locate boundary line"
9820
+ (()=>{
9821
+ // ADR-0042. The boundary divider + warm summary card live INSIDE the
9822
+ // message stream so they scroll with content (not above as a fixed
9823
+ // banner). `boundaryIndex` is the index of the first hot message in
9824
+ // the visible list; everything before it is older-than-pin and gets
9825
+ // covered by the warm summary card sitting above the divider.
9826
+ //
9827
+ const hasPin = effectiveHotSinceSeq !== null;
9828
+ const boundaryIndex = hasPin ? boundaryIndexFor(effectiveHotSinceSeq) : -1;
9829
+ const pinAfterAll = hasPin && visibleMessages.length > 0 && boundaryIndex === visibleMessages.length;
9830
+ // The pin is the boundary's source of truth. Summary data can arrive
9831
+ // later (or be unavailable on an older thread), but hiding the line
9832
+ // in that interval makes a valid focus selection look like it vanished.
9833
+ const hasBoundary = hasPin && boundaryIndex >= 0;
9834
+ const olderInVisible = pinAfterAll ? visibleMessages.length : hasBoundary ? boundaryIndex : 0;
9835
+ // "+ N more we don't know about yet" — older pages are likely unloaded.
9836
+ const olderCountLabel = olderInVisible + (hasMore ? 1 : 0);
9837
+ const attachedActivities = new Map();
9838
+ const hiddenActivityIds = new Set();
9839
+ for(let i = 0; i < visibleMessages.length - 1; i++){
9840
+ const activityMessage = visibleMessages[i];
9841
+ const activity = activityMessage.metadata?.automation_activity;
9842
+ if (!activity) continue;
9843
+ const related = visibleMessages[i + 1];
9844
+ 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);
9845
+ if (!matches) continue;
9846
+ attachedActivities.set(related.id, activity);
9847
+ hiddenActivityIds.add(activityMessage.id);
9848
+ }
9849
+ const previousVisibleRoles = new Map();
9850
+ let previousVisibleRole = null;
9851
+ for (const message of visibleMessages){
9852
+ previousVisibleRoles.set(message.id, previousVisibleRole);
9853
+ if (!hiddenActivityIds.has(message.id)) previousVisibleRole = message.role;
9854
+ }
9855
+ const renderBoundary = (key)=>/*#__PURE__*/ (0,jsx_runtime.jsx)("div", {
9856
+ id: effectiveHotSinceSeq !== null ? `context-boundary-${effectiveHotSinceSeq}` : undefined,
9857
+ "data-focus-boundary": "1",
9858
+ "data-boundary-seq": effectiveHotSinceSeq ?? undefined,
9859
+ children: /*#__PURE__*/ (0,jsx_runtime.jsx)(ContextBoundaryDivider, {
9860
+ sourceMessages: warmSummarySourceMessages ?? null,
9861
+ sourceChars: warmSummarySourceChars ?? null,
9862
+ summaryChars: warmSummary ? warmSummary.length : null,
9863
+ lineStats: lineStatsForHotSince(effectiveHotSinceSeq),
9864
+ updating: warmSummaryPending && !summaryFresh,
9865
+ draggable: !!onSetContextPin,
9866
+ hidden: isDraggingFocus,
9867
+ disabled: !!streaming,
9868
+ onClick: handleBoundaryClick,
9869
+ onPointerDown: handleBoundaryPointerDown,
9870
+ onPointerMove: handleBoundaryPointerMove,
9871
+ onPointerUp: handleBoundaryPointerUp,
9872
+ onPointerCancel: handleBoundaryPointerCancel
9873
+ })
9874
+ }, key);
9875
+ const nodes = visibleMessages.flatMap((msg, i)=>{
9876
+ const out = [];
9877
+ if (hasBoundary && !pinAfterAll && i === boundaryIndex) {
9878
+ out.push(renderBoundary(`boundary-${msg.id}`));
9879
+ }
9880
+ if (hiddenActivityIds.has(msg.id)) return out;
9881
+ const previousRole = previousVisibleRoles.get(msg.id);
9882
+ const startsTurn = previousRole == null || previousRole !== msg.role;
9883
+ const steeredSegment = steeredSegments?.find((segment)=>segment.id === msg.id);
9884
+ if (steeredSegment) {
9885
+ out.push(/*#__PURE__*/ (0,jsx_runtime.jsx)(StreamingBubble, {
9886
+ content: steeredSegment.content,
9887
+ threadId: threadId ?? null,
9888
+ agentConfig: agentConfig ?? null,
9889
+ showAvatar: i === 0 || visibleMessages[i - 1].role !== "assistant"
9890
+ }, `steered-${steeredSegment.id}`));
9891
+ }
9892
+ out.push(/*#__PURE__*/ (0,jsx_runtime.jsx)("div", {
9893
+ id: typeof msg.seq === "number" ? String(msg.seq) : `msg-${msg.id}`,
9894
+ "data-message-id": msg.id,
9895
+ "data-hot-candidate": "1",
9896
+ "data-message-seq": msg.seq,
9897
+ "data-created-at": msg.created_at,
9898
+ className: startsTurn && i > 0 ? "mt-3" : undefined,
9899
+ children: /*#__PURE__*/ (0,jsx_runtime.jsx)(MessageBubble, {
9900
+ message: msg,
9901
+ attachedActivity: attachedActivities.get(msg.id),
9902
+ threadId: threadId ?? null,
9903
+ agentConfig: agentConfig,
9904
+ userProfile: userProfile,
9905
+ showAvatar: startsTurn,
9906
+ showToolEvents: filters.tool_use,
9907
+ contextWindowTokens: contextWindowTokens ?? null,
9908
+ isLatest: i === visibleMessages.length - 1 && !streamingContent,
9909
+ onRetry: onRetryMessage
9910
+ })
9911
+ }, msg.id));
9912
+ return out;
9913
+ });
9914
+ if (hasBoundary && pinAfterAll) nodes.push(renderBoundary("boundary-tail"));
9915
+ return nodes;
9916
+ })(),
9917
+ /*#__PURE__*/ (0,jsx_runtime.jsx)(LiveTurnActivity, {
9918
+ thinkingContent: thinkingContent,
9919
+ streamingContent: streamingContent,
9920
+ toolEvents: toolEvents,
9921
+ filters: filters,
9922
+ threadId: threadId ?? null,
9923
+ agentConfig: agentConfig ?? null,
9924
+ showStreamingAvatar: messages.length === 0 || messages[messages.length - 1].role !== "assistant",
9925
+ streaming: streaming
9926
+ }),
9927
+ queuedMessages && queuedMessages.length > 0 && /*#__PURE__*/ (0,jsx_runtime.jsx)("div", {
9928
+ className: "flex flex-col gap-1 mt-2 mb-1",
9929
+ children: queuedMessages.map((q)=>/*#__PURE__*/ (0,jsx_runtime.jsx)(QueuedBubble, {
9930
+ item: q,
9931
+ onRemove: onRemoveQueued
9932
+ }, q.id))
9463
9933
  })
9464
9934
  ]
9935
+ }),
9936
+ /*#__PURE__*/ (0,jsx_runtime.jsx)("div", {
9937
+ ref: dragMaskRef,
9938
+ className: "pointer-events-none absolute left-0 right-0 top-0 z-40 opacity-0 transition-opacity duration-75",
9939
+ style: {
9940
+ transform: "translateY(0px)",
9941
+ height: "0px",
9942
+ 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%)",
9943
+ borderBottom: "0",
9944
+ backdropFilter: "grayscale(0.5) saturate(0.18) contrast(0.98)",
9945
+ WebkitBackdropFilter: "grayscale(0.5) saturate(0.18) contrast(0.98)",
9946
+ maskImage: "linear-gradient(to top, black 0%, rgba(0,0,0,0.88) 72%, rgba(0,0,0,0.32) 90%, transparent 100%)",
9947
+ WebkitMaskImage: "linear-gradient(to top, black 0%, rgba(0,0,0,0.88) 72%, rgba(0,0,0,0.32) 90%, transparent 100%)"
9948
+ }
9465
9949
  })
9466
9950
  ]
9467
- })
9468
- }),
9469
- /*#__PURE__*/ (0,jsx_runtime.jsxs)("div", {
9470
- ref: maskRegionRef,
9471
- className: "relative flex-1 min-h-0 overflow-hidden",
9472
- children: [
9473
- /*#__PURE__*/ (0,jsx_runtime.jsxs)("div", {
9474
- ref: scrollRef,
9475
- onScroll: handleScroll,
9476
- className: "flex-1 h-full overflow-y-auto overflow-x-hidden px-4 py-4 panel-scrollbar",
9951
+ }),
9952
+ showScrollButton && /*#__PURE__*/ (0,jsx_runtime.jsx)("button", {
9953
+ onClick: scrollToBottom,
9954
+ style: {
9955
+ bottom: "calc(1rem + var(--app-safe-bottom))"
9956
+ },
9957
+ 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",
9958
+ title: "Auto-scroll paused — resume at latest message",
9959
+ "aria-label": "Resume auto-scroll to latest message",
9960
+ children: /*#__PURE__*/ (0,jsx_runtime.jsx)(arrow_down/* default */.A, {
9961
+ size: 18
9962
+ })
9963
+ }),
9964
+ isDraggingFocus && /*#__PURE__*/ (0,jsx_runtime.jsx)(jsx_runtime.Fragment, {
9965
+ children: /*#__PURE__*/ (0,jsx_runtime.jsxs)("div", {
9966
+ ref: dragGuideRef,
9967
+ className: "pointer-events-none absolute left-4 right-4 z-50 opacity-0",
9477
9968
  style: {
9478
- // Scroll-anchor jumps (deep-link to a message) land below the
9479
- // floating header, not under it.
9480
- scrollPaddingTop: "calc(3rem + var(--app-safe-top))"
9969
+ transform: "translateY(0px)"
9481
9970
  },
9482
9971
  children: [
9483
- hasMore && /*#__PURE__*/ (0,jsx_runtime.jsx)("div", {
9484
- className: "text-center py-1.5 text-[11px] text-fg-faint select-none",
9485
- children: loadingMore ? "Loading earlier messages…" : "Scroll up for earlier messages"
9486
- }),
9487
- compactionPending && /*#__PURE__*/ (0,jsx_runtime.jsxs)("div", {
9488
- className: "my-2 flex items-center justify-center gap-2 rounded-lg border border-border bg-surface-2/70 px-3 py-1.5 text-[11px] text-fg-faint select-none",
9489
- children: [
9490
- /*#__PURE__*/ (0,jsx_runtime.jsx)(StatusDot, {
9491
- tone: "accent",
9492
- size: "sm",
9493
- pulse: true
9494
- }),
9495
- /*#__PURE__*/ (0,jsx_runtime.jsx)("span", {
9496
- children: "Summarising earlier messages… this turn still sees the full history."
9497
- })
9498
- ]
9972
+ /*#__PURE__*/ (0,jsx_runtime.jsx)("div", {
9973
+ className: "h-[2px] bg-gradient-to-r from-transparent via-accent to-transparent opacity-95 shadow-[0_0_8px_rgba(59,130,246,0.55)]"
9499
9974
  }),
9500
- visibleMessages.length === 0 && !streamingContent && /*#__PURE__*/ (0,jsx_runtime.jsx)("div", {
9501
- className: "flex items-center justify-center h-full text-fg-faint text-sm select-none",
9502
- children: messages.length === 0 ? /*#__PURE__*/ (0,jsx_runtime.jsx)("span", {
9503
- children: "Send a message to begin"
9504
- }) : /*#__PURE__*/ (0,jsx_runtime.jsxs)("div", {
9505
- className: "flex flex-col items-center gap-2 text-center px-4",
9975
+ /*#__PURE__*/ (0,jsx_runtime.jsx)("span", {
9976
+ ref: dragGuideStatsRef,
9977
+ 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",
9978
+ children: lineStatsForHotSince(effectiveHotSinceSeq)
9979
+ })
9980
+ ]
9981
+ })
9982
+ }),
9983
+ summaryPopoverOpen && /*#__PURE__*/ (0,jsx_runtime.jsx)(Dialog/* Dialog */.l, {
9984
+ open: true,
9985
+ onClose: ()=>setSummaryPopoverOpen(false),
9986
+ title: "Earlier messages summary",
9987
+ size: "xl",
9988
+ align: "top",
9989
+ padded: false,
9990
+ children: /*#__PURE__*/ (0,jsx_runtime.jsxs)("div", {
9991
+ className: "p-4 space-y-3",
9992
+ children: [
9993
+ /*#__PURE__*/ (0,jsx_runtime.jsx)("div", {
9994
+ className: "flex items-center gap-2",
9995
+ children: /*#__PURE__*/ (0,jsx_runtime.jsxs)("span", {
9996
+ className: [
9997
+ "text-[10px] px-1.5 py-px rounded border inline-flex items-center gap-1",
9998
+ 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"
9999
+ ].join(" "),
9506
10000
  children: [
9507
- /*#__PURE__*/ (0,jsx_runtime.jsxs)("span", {
9508
- children: [
9509
- hiddenCount,
9510
- " message",
9511
- hiddenCount === 1 ? " is" : "s are",
9512
- " hidden by filters"
9513
- ]
10001
+ summaryUpdating && /*#__PURE__*/ (0,jsx_runtime.jsx)("span", {
10002
+ className: "h-2 w-2 rounded-full bg-accent animate-pulse",
10003
+ "aria-label": "Summary updating"
9514
10004
  }),
9515
- /*#__PURE__*/ (0,jsx_runtime.jsx)("button", {
9516
- type: "button",
9517
- onClick: reset,
9518
- className: "control-tap text-xs px-2.5 py-1 rounded-md border border-border bg-surface-2 text-fg-muted hover:text-fg hover:bg-surface-3 transition-colors",
9519
- children: "Show all messages"
10005
+ /*#__PURE__*/ (0,jsx_runtime.jsx)("span", {
10006
+ children: summaryUpdating ? "updating" : summaryReady ? "ready" : summaryStale ? "needs refresh" : "pending"
9520
10007
  })
9521
10008
  ]
9522
10009
  })
9523
10010
  }),
9524
- (()=>{
9525
- // ADR-0042. The boundary divider + warm summary card live INSIDE the
9526
- // message stream so they scroll with content (not above as a fixed
9527
- // banner). `boundaryIndex` is the index of the first hot message in
9528
- // the visible list; everything before it is older-than-pin and gets
9529
- // covered by the warm summary card sitting above the divider.
9530
- //
9531
- const hasPin = effectiveHotSinceSeq !== null;
9532
- const boundaryIndex = hasPin ? boundaryIndexFor(effectiveHotSinceSeq) : -1;
9533
- const pinAfterAll = hasPin && visibleMessages.length > 0 && boundaryIndex === visibleMessages.length;
9534
- // The pin is the boundary's source of truth. Summary data can arrive
9535
- // later (or be unavailable on an older thread), but hiding the line
9536
- // in that interval makes a valid focus selection look like it vanished.
9537
- const hasBoundary = hasPin && boundaryIndex >= 0;
9538
- const olderInVisible = pinAfterAll ? visibleMessages.length : hasBoundary ? boundaryIndex : 0;
9539
- // "+ N more we don't know about yet" — older pages are likely unloaded.
9540
- const olderCountLabel = olderInVisible + (hasMore ? 1 : 0);
9541
- const attachedActivities = new Map();
9542
- const hiddenActivityIds = new Set();
9543
- for(let i = 0; i < visibleMessages.length - 1; i++){
9544
- const activityMessage = visibleMessages[i];
9545
- const activity = activityMessage.metadata?.automation_activity;
9546
- if (!activity) continue;
9547
- const related = visibleMessages[i + 1];
9548
- const matches = !related.metadata?.automation_activity && (activity.source_kind === "bridge" ? related.role === "user" && related.metadata?.bridge_conversation?.key === activity.source_id : related.role === "assistant" && related.category === activity.source_kind);
9549
- if (!matches) continue;
9550
- attachedActivities.set(related.id, activity);
9551
- hiddenActivityIds.add(activityMessage.id);
9552
- }
9553
- const previousVisibleRoles = new Map();
9554
- let previousVisibleRole = null;
9555
- for (const message of visibleMessages){
9556
- previousVisibleRoles.set(message.id, previousVisibleRole);
9557
- if (!hiddenActivityIds.has(message.id)) previousVisibleRole = message.role;
9558
- }
9559
- const renderBoundary = (key)=>/*#__PURE__*/ (0,jsx_runtime.jsx)("div", {
9560
- id: effectiveHotSinceSeq !== null ? `context-boundary-${effectiveHotSinceSeq}` : undefined,
9561
- "data-focus-boundary": "1",
9562
- "data-boundary-seq": effectiveHotSinceSeq ?? undefined,
9563
- children: /*#__PURE__*/ (0,jsx_runtime.jsx)(ContextBoundaryDivider, {
9564
- sourceMessages: warmSummarySourceMessages ?? null,
9565
- sourceChars: warmSummarySourceChars ?? null,
9566
- summaryChars: warmSummary ? warmSummary.length : null,
9567
- lineStats: lineStatsForHotSince(effectiveHotSinceSeq),
9568
- updating: warmSummaryPending && !summaryFresh,
9569
- draggable: !!onSetContextPin,
9570
- hidden: isDraggingFocus,
9571
- disabled: !!streaming,
9572
- onClick: handleBoundaryClick,
9573
- onPointerDown: handleBoundaryPointerDown,
9574
- onPointerMove: handleBoundaryPointerMove,
9575
- onPointerUp: handleBoundaryPointerUp,
9576
- onPointerCancel: handleBoundaryPointerCancel
9577
- })
9578
- }, key);
9579
- const nodes = visibleMessages.flatMap((msg, i)=>{
9580
- const out = [];
9581
- if (hasBoundary && !pinAfterAll && i === boundaryIndex) {
9582
- out.push(renderBoundary(`boundary-${msg.id}`));
9583
- }
9584
- if (hiddenActivityIds.has(msg.id)) return out;
9585
- const previousRole = previousVisibleRoles.get(msg.id);
9586
- const startsTurn = previousRole == null || previousRole !== msg.role;
9587
- const steeredSegment = steeredSegments?.find((segment)=>segment.id === msg.id);
9588
- if (steeredSegment) {
9589
- out.push(/*#__PURE__*/ (0,jsx_runtime.jsx)(StreamingBubble, {
9590
- content: steeredSegment.content,
9591
- threadId: threadId ?? null,
9592
- agentConfig: agentConfig ?? null,
9593
- showAvatar: i === 0 || visibleMessages[i - 1].role !== "assistant"
9594
- }, `steered-${steeredSegment.id}`));
9595
- }
9596
- out.push(/*#__PURE__*/ (0,jsx_runtime.jsx)("div", {
9597
- id: typeof msg.seq === "number" ? String(msg.seq) : `msg-${msg.id}`,
9598
- "data-message-id": msg.id,
9599
- "data-hot-candidate": "1",
9600
- "data-message-seq": msg.seq,
9601
- "data-created-at": msg.created_at,
9602
- className: startsTurn && i > 0 ? "mt-3" : undefined,
9603
- children: /*#__PURE__*/ (0,jsx_runtime.jsx)(MessageBubble, {
9604
- message: msg,
9605
- attachedActivity: attachedActivities.get(msg.id),
9606
- threadId: threadId ?? null,
9607
- agentConfig: agentConfig,
9608
- userProfile: userProfile,
9609
- showAvatar: startsTurn,
9610
- showToolEvents: filters.tool_use,
9611
- contextWindowTokens: contextWindowTokens ?? null,
9612
- isLatest: i === visibleMessages.length - 1 && !streamingContent,
9613
- onRetry: onRetryMessage
9614
- })
9615
- }, msg.id));
9616
- return out;
9617
- });
9618
- if (hasBoundary && pinAfterAll) nodes.push(renderBoundary("boundary-tail"));
9619
- return nodes;
9620
- })(),
9621
- /*#__PURE__*/ (0,jsx_runtime.jsx)(LiveTurnActivity, {
9622
- thinkingContent: thinkingContent,
9623
- streamingContent: streamingContent,
9624
- toolEvents: toolEvents,
9625
- filters: filters,
9626
- threadId: threadId ?? null,
9627
- agentConfig: agentConfig ?? null,
9628
- showStreamingAvatar: messages.length === 0 || messages[messages.length - 1].role !== "assistant",
9629
- streaming: streaming
9630
- }),
9631
- queuedMessages && queuedMessages.length > 0 && /*#__PURE__*/ (0,jsx_runtime.jsx)("div", {
9632
- className: "flex flex-col gap-1 mt-2 mb-1",
9633
- children: queuedMessages.map((q)=>/*#__PURE__*/ (0,jsx_runtime.jsx)(QueuedBubble, {
9634
- item: q,
9635
- onRemove: onRemoveQueued
9636
- }, q.id))
9637
- }),
9638
- notices?.map((n)=>/*#__PURE__*/ (0,jsx_runtime.jsx)("div", {
9639
- className: "flex justify-center my-3",
9640
- children: /*#__PURE__*/ (0,jsx_runtime.jsx)("span", {
9641
- className: "text-xs italic text-fg-faint bg-surface-2 px-3 py-1 rounded-full border border-border",
9642
- children: n.text
9643
- })
9644
- }, n.id))
10011
+ !summaryUpdating && /*#__PURE__*/ (0,jsx_runtime.jsx)("p", {
10012
+ className: "text-[11px] text-fg-faint",
10013
+ 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."
10014
+ }),
10015
+ /*#__PURE__*/ (0,jsx_runtime.jsx)(WarmSummaryCard, {
10016
+ olderCount: countOlderForHotSince(effectiveHotSinceSeq) + (hasMore ? 1 : 0),
10017
+ summary: warmSummary ?? null,
10018
+ summaryBeforeSeq: warmSummaryBeforeSeq ?? null,
10019
+ hotSinceSeq: effectiveHotSinceSeq,
10020
+ computedAt: warmSummaryComputedAt ?? null,
10021
+ streaming: !!streaming,
10022
+ topics: warmSummaryTopics ?? null,
10023
+ channelSummaries: warmChannelSummaries
10024
+ })
9645
10025
  ]
9646
- }),
9647
- /*#__PURE__*/ (0,jsx_runtime.jsx)("div", {
9648
- ref: dragMaskRef,
9649
- className: "pointer-events-none absolute left-0 right-0 top-0 z-40 opacity-0 transition-opacity duration-75",
9650
- style: {
9651
- transform: "translateY(0px)",
9652
- height: "0px",
9653
- background: "linear-gradient(to top, rgba(82,82,91,0.24) 0%, rgba(82,82,91,0.2) 22%, rgba(82,82,91,0.14) 48%, rgba(82,82,91,0.08) 72%, rgba(82,82,91,0.03) 88%, rgba(82,82,91,0) 100%)",
9654
- borderBottom: "0",
9655
- backdropFilter: "grayscale(0.5) saturate(0.18) contrast(0.98)",
9656
- WebkitBackdropFilter: "grayscale(0.5) saturate(0.18) contrast(0.98)",
9657
- maskImage: "linear-gradient(to top, black 0%, rgba(0,0,0,0.88) 72%, rgba(0,0,0,0.32) 90%, transparent 100%)",
9658
- WebkitMaskImage: "linear-gradient(to top, black 0%, rgba(0,0,0,0.88) 72%, rgba(0,0,0,0.32) 90%, transparent 100%)"
9659
- }
9660
10026
  })
9661
- ]
9662
- }),
9663
- showScrollButton && /*#__PURE__*/ (0,jsx_runtime.jsx)("button", {
9664
- onClick: scrollToBottom,
9665
- style: {
9666
- bottom: "calc(1rem + var(--app-safe-bottom))"
9667
- },
9668
- className: "absolute right-4 p-2 rounded-full bg-accent/40 hover:bg-accent/80 text-white backdrop-blur-sm shadow-md transition-all animate-in fade-in slide-in-from-bottom-2 duration-200 z-20",
9669
- title: "Auto-scroll paused — resume at latest message",
9670
- "aria-label": "Resume auto-scroll to latest message",
9671
- children: /*#__PURE__*/ (0,jsx_runtime.jsx)(arrow_down/* default */.A, {
9672
- size: 18
9673
- })
9674
- }),
9675
- isDraggingFocus && /*#__PURE__*/ (0,jsx_runtime.jsx)(jsx_runtime.Fragment, {
9676
- children: /*#__PURE__*/ (0,jsx_runtime.jsxs)("div", {
9677
- ref: dragGuideRef,
9678
- className: "pointer-events-none absolute left-4 right-4 z-50 opacity-0",
9679
- style: {
9680
- transform: "translateY(0px)"
10027
+ }),
10028
+ /*#__PURE__*/ (0,jsx_runtime.jsxs)(Dialog/* Dialog */.l, {
10029
+ open: confirmOpen,
10030
+ onClose: ()=>{
10031
+ setConfirmOpen(false);
10032
+ setPendingHotSinceSeq(null);
9681
10033
  },
10034
+ size: "sm",
10035
+ align: "center",
10036
+ dismissOnBackdrop: false,
9682
10037
  children: [
9683
- /*#__PURE__*/ (0,jsx_runtime.jsx)("div", {
9684
- className: "h-[2px] bg-gradient-to-r from-transparent via-accent to-transparent opacity-95 shadow-[0_0_8px_rgba(59,130,246,0.55)]"
10038
+ /*#__PURE__*/ (0,jsx_runtime.jsx)("h4", {
10039
+ className: "text-sm font-semibold text-fg",
10040
+ children: "Move conversation focus here?"
9685
10041
  }),
9686
- /*#__PURE__*/ (0,jsx_runtime.jsx)("span", {
9687
- ref: dragGuideStatsRef,
9688
- className: "absolute right-1 top-1/2 -translate-y-1/2 text-[10px] text-fg-faint bg-surface/75 px-1.5 rounded border border-border/60",
9689
- children: lineStatsForHotSince(effectiveHotSinceSeq)
9690
- })
9691
- ]
9692
- })
9693
- }),
9694
- summaryPopoverOpen && /*#__PURE__*/ (0,jsx_runtime.jsx)(Dialog/* Dialog */.l, {
9695
- open: true,
9696
- onClose: ()=>setSummaryPopoverOpen(false),
9697
- title: "Earlier messages summary",
9698
- size: "xl",
9699
- align: "top",
9700
- padded: false,
9701
- children: /*#__PURE__*/ (0,jsx_runtime.jsxs)("div", {
9702
- className: "p-4 space-y-3",
9703
- children: [
9704
- /*#__PURE__*/ (0,jsx_runtime.jsx)("div", {
9705
- className: "flex items-center gap-2",
9706
- children: /*#__PURE__*/ (0,jsx_runtime.jsxs)("span", {
9707
- className: [
9708
- "text-[10px] px-1.5 py-px rounded border inline-flex items-center gap-1",
9709
- summaryUpdating ? "border-accent/40 bg-accent/10 text-accent" : summaryFresh ? "border-emerald-500/30 bg-emerald-500/10 text-emerald-600 dark:text-emerald-400" : summaryStale ? "border-amber-500/30 bg-amber-500/10 text-amber-700 dark:text-amber-400" : "border-border bg-surface-2 text-fg-faint"
9710
- ].join(" "),
9711
- children: [
9712
- summaryUpdating && /*#__PURE__*/ (0,jsx_runtime.jsx)("span", {
9713
- className: "h-2 w-2 rounded-full bg-accent animate-pulse",
9714
- "aria-label": "Summary updating"
9715
- }),
9716
- /*#__PURE__*/ (0,jsx_runtime.jsx)("span", {
9717
- children: summaryUpdating ? "updating" : summaryFresh ? "ready" : summaryStale ? "needs refresh" : "pending"
9718
- })
9719
- ]
9720
- })
10042
+ /*#__PURE__*/ (0,jsx_runtime.jsx)("p", {
10043
+ className: "text-xs text-fg-muted leading-relaxed",
10044
+ children: "Start a new conversation context from this point. New replies will prioritize recent messages below this line."
9721
10045
  }),
9722
- !summaryUpdating && /*#__PURE__*/ (0,jsx_runtime.jsx)("p", {
10046
+ nextHotCount !== null && /*#__PURE__*/ (0,jsx_runtime.jsxs)("p", {
9723
10047
  className: "text-[11px] text-fg-faint",
9724
- children: summaryFresh ? "Showing the latest summary for messages above the boundary line." : summaryStale ? "This summary is from an older focus and will refresh after the next reply." : "No summary yet. It will appear after the next reply."
10048
+ children: [
10049
+ "Recent in focus: ",
10050
+ nextHotCount,
10051
+ " loaded message",
10052
+ nextHotCount === 1 ? "" : "s",
10053
+ "; earlier loaded summary: ",
10054
+ Math.max(0, visibleMessages.length - nextHotCount),
10055
+ "."
10056
+ ]
9725
10057
  }),
9726
- /*#__PURE__*/ (0,jsx_runtime.jsx)(WarmSummaryCard, {
9727
- olderCount: countOlderForHotSince(effectiveHotSinceSeq) + (hasMore ? 1 : 0),
9728
- summary: warmSummary ?? null,
9729
- summaryBeforeSeq: warmSummaryBeforeSeq ?? null,
9730
- hotSinceSeq: effectiveHotSinceSeq,
9731
- computedAt: warmSummaryComputedAt ?? null,
9732
- streaming: !!streaming,
9733
- topics: warmSummaryTopics ?? null
10058
+ removesFromRecent && /*#__PURE__*/ (0,jsx_runtime.jsx)("p", {
10059
+ className: "text-[11px] text-amber-600 dark:text-amber-400",
10060
+ children: "This reduces recent in-focus messages. You can drag upward later to add history back."
10061
+ }),
10062
+ /*#__PURE__*/ (0,jsx_runtime.jsxs)("div", {
10063
+ className: "flex justify-end gap-2 pt-1",
10064
+ children: [
10065
+ /*#__PURE__*/ (0,jsx_runtime.jsx)("button", {
10066
+ type: "button",
10067
+ onClick: ()=>{
10068
+ setConfirmOpen(false);
10069
+ setPendingHotSinceSeq(null);
10070
+ },
10071
+ className: "px-3 py-1.5 text-xs text-fg-subtle hover:text-fg transition-colors",
10072
+ children: "Cancel"
10073
+ }),
10074
+ /*#__PURE__*/ (0,jsx_runtime.jsx)("button", {
10075
+ type: "button",
10076
+ onClick: ()=>{
10077
+ if (pendingHotSinceSeq !== null && onSetContextPin) onSetContextPin(pendingHotSinceSeq);
10078
+ setConfirmOpen(false);
10079
+ setPendingHotSinceSeq(null);
10080
+ },
10081
+ className: "px-3 py-1.5 rounded-md text-xs border border-accent/40 bg-accent text-white hover:opacity-95 transition-opacity",
10082
+ children: "Move focus"
10083
+ })
10084
+ ]
9734
10085
  })
9735
10086
  ]
9736
10087
  })
9737
- }),
9738
- /*#__PURE__*/ (0,jsx_runtime.jsxs)(Dialog/* Dialog */.l, {
9739
- open: confirmOpen,
9740
- onClose: ()=>{
9741
- setConfirmOpen(false);
9742
- setPendingHotSinceSeq(null);
9743
- },
9744
- size: "sm",
9745
- align: "center",
9746
- dismissOnBackdrop: false,
9747
- children: [
9748
- /*#__PURE__*/ (0,jsx_runtime.jsx)("h4", {
9749
- className: "text-sm font-semibold text-fg",
9750
- children: "Move conversation focus here?"
9751
- }),
9752
- /*#__PURE__*/ (0,jsx_runtime.jsx)("p", {
9753
- className: "text-xs text-fg-muted leading-relaxed",
9754
- children: "Start a new conversation context from this point. New replies will prioritize recent messages below this line."
9755
- }),
9756
- nextHotCount !== null && /*#__PURE__*/ (0,jsx_runtime.jsxs)("p", {
9757
- className: "text-[11px] text-fg-faint",
9758
- children: [
9759
- "Recent in focus: ",
9760
- nextHotCount,
9761
- " loaded message",
9762
- nextHotCount === 1 ? "" : "s",
9763
- "; earlier loaded summary: ",
9764
- Math.max(0, visibleMessages.length - nextHotCount),
9765
- "."
9766
- ]
9767
- }),
9768
- removesFromRecent && /*#__PURE__*/ (0,jsx_runtime.jsx)("p", {
9769
- className: "text-[11px] text-amber-600 dark:text-amber-400",
9770
- children: "This reduces recent in-focus messages. You can drag upward later to add history back."
9771
- }),
9772
- /*#__PURE__*/ (0,jsx_runtime.jsxs)("div", {
9773
- className: "flex justify-end gap-2 pt-1",
9774
- children: [
9775
- /*#__PURE__*/ (0,jsx_runtime.jsx)("button", {
9776
- type: "button",
9777
- onClick: ()=>{
9778
- setConfirmOpen(false);
9779
- setPendingHotSinceSeq(null);
9780
- },
9781
- className: "px-3 py-1.5 text-xs text-fg-subtle hover:text-fg transition-colors",
9782
- children: "Cancel"
9783
- }),
9784
- /*#__PURE__*/ (0,jsx_runtime.jsx)("button", {
9785
- type: "button",
9786
- onClick: ()=>{
9787
- if (pendingHotSinceSeq !== null && onSetContextPin) onSetContextPin(pendingHotSinceSeq);
9788
- setConfirmOpen(false);
9789
- setPendingHotSinceSeq(null);
9790
- },
9791
- className: "px-3 py-1.5 rounded-md text-xs border border-accent/40 bg-accent text-white hover:opacity-95 transition-opacity",
9792
- children: "Move focus"
9793
- })
9794
- ]
9795
- })
9796
- ]
9797
- })
9798
- ]
10088
+ ]
10089
+ })
9799
10090
  });
9800
10091
  }
9801
10092
  // ADR-0044 — the subset of MESSAGE_FILTER_KEYS that also map to a
@@ -9807,6 +10098,7 @@ const CHANNEL_SCOPED_FILTER_KEYS = new Set([
9807
10098
  "watcher",
9808
10099
  "bridge"
9809
10100
  ]);
10101
+ const PROGRAMMATIC_SCROLL_LOCK_MS = 1500;
9810
10102
  const CHIP_LABELS = {
9811
10103
  scheduled_task: "scheduled",
9812
10104
  watcher: "watcher",
@@ -9976,7 +10268,46 @@ function QueuedBubble({ item, onRemove }) {
9976
10268
  }
9977
10269
 
9978
10270
  ;// ./components/chat/chat-helpers.ts
9979
- /* __next_internal_client_entry_do_not_use__ isUnconfirmed,appendUnique,applyThreadMeta,makeQueuedId,parseWarmSummaryTopics auto */ // Append-with-reconcile. Merges server-persisted rows into the local list
10271
+ /* __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
10272
+ // decides the text: "nothing to compact" means the thread is empty, anything
10273
+ // else means there were messages but no summary came out of them.
10274
+ function compactionOutcomeToast(result) {
10275
+ if (result.compacted) {
10276
+ const n = result.message_count ?? 0;
10277
+ return {
10278
+ kind: "success",
10279
+ title: "Context compacted",
10280
+ body: n > 0 ? `Summarised ${n} message${n === 1 ? "" : "s"} into warm context.` : "Started a fresh context window."
10281
+ };
10282
+ }
10283
+ if (result.reason === "nothing to compact") {
10284
+ return {
10285
+ kind: "info",
10286
+ title: "Nothing to compact",
10287
+ body: "This conversation has no messages yet."
10288
+ };
10289
+ }
10290
+ if (result.reason === "already compacting") {
10291
+ return {
10292
+ kind: "info",
10293
+ title: "Already compacting",
10294
+ body: "A compaction for this conversation is still running."
10295
+ };
10296
+ }
10297
+ if (result.reason === "timed out") {
10298
+ return {
10299
+ kind: "error",
10300
+ title: "Compaction timed out",
10301
+ body: "The summary took too long and was discarded. Context is unchanged."
10302
+ };
10303
+ }
10304
+ return {
10305
+ kind: "info",
10306
+ title: "Nothing was compacted",
10307
+ body: "There was too little to summarise, or the model returned no usable summary. Context is unchanged."
10308
+ };
10309
+ }
10310
+ // Append-with-reconcile. Merges server-persisted rows into the local list
9980
10311
  // with three rules, applied in order for each incoming message:
9981
10312
  //
9982
10313
  // 1. Already present by server id → update in place (handles the
@@ -10061,10 +10392,12 @@ function applyThreadMeta(meta, payload) {
10061
10392
  meta.setWarmSummarySourceMessages(payload.warm_summary_source_messages ?? null);
10062
10393
  meta.setWarmSummarySourceChars(payload.warm_summary_source_chars ?? null);
10063
10394
  meta.setWarmSummaryTopics?.(payload.warm_summary_topics ?? null);
10395
+ meta.setWarmChannelSummaries?.(payload.warm_channel_summaries ?? []);
10064
10396
  meta.setContextWindowTokens(payload.context_window_tokens ?? null);
10065
10397
  const summaryFresh = hotSinceSeq !== null && summaryBeforeSeq === hotSinceSeq;
10066
10398
  meta.setWarmSummaryPending?.(hotSinceSeq !== null && !summaryFresh);
10067
10399
  meta.setCompactionPending?.(payload.pending_hot_since_seq != null);
10400
+ meta.setManualCompactionPending?.(payload.manual_compaction_pending === true);
10068
10401
  }
10069
10402
  function makeQueuedId(prefix = "q") {
10070
10403
  return `${prefix}-${Date.now()}-${Math.random().toString(36).slice(2, 6)}`;
@@ -10080,8 +10413,6 @@ function makeQueuedId(prefix = "q") {
10080
10413
  }
10081
10414
  }
10082
10415
 
10083
- // EXTERNAL MODULE: ./lib/ui/error-report.ts
10084
- var error_report = __webpack_require__(11856);
10085
10416
  ;// ./lib/ui/error-message.ts
10086
10417
  /* __next_internal_client_entry_do_not_use__ friendlyErrorTitle,reportError auto */ // Centralized human-friendly error-title mapping. Used by pushErrorToast
10087
10418
  // callers so the headline a user sees is consistent across the UI:
@@ -10412,7 +10743,6 @@ function useThreadCrossDeviceSync({ threadId, streamingRef, messagesRef, setMess
10412
10743
 
10413
10744
  function useThreadData({ threadId, attach }) {
10414
10745
  const [messages, setMessages] = (0,react.useState)([]);
10415
- const [notices, setNotices] = (0,react.useState)([]);
10416
10746
  const [hasMore, setHasMore] = (0,react.useState)(false);
10417
10747
  const [loadingMore, setLoadingMore] = (0,react.useState)(false);
10418
10748
  const [messagesLoading, setMessagesLoading] = (0,react.useState)(false);
@@ -10426,8 +10756,10 @@ function useThreadData({ threadId, attach }) {
10426
10756
  const [warmSummarySourceMessages, setWarmSummarySourceMessages] = (0,react.useState)(null);
10427
10757
  const [warmSummarySourceChars, setWarmSummarySourceChars] = (0,react.useState)(null);
10428
10758
  const [warmSummaryTopics, setWarmSummaryTopics] = (0,react.useState)(null);
10759
+ const [warmChannelSummaries, setWarmChannelSummaries] = (0,react.useState)([]);
10429
10760
  const [warmSummaryPending, setWarmSummaryPending] = (0,react.useState)(false);
10430
10761
  const [compactionPending, setCompactionPending] = (0,react.useState)(false);
10762
+ const [manualCompactionPending, setManualCompactionPending] = (0,react.useState)(false);
10431
10763
  const [contextWindowTokens, setContextWindowTokens] = (0,react.useState)(null);
10432
10764
  const messagesRef = (0,react.useRef)([]);
10433
10765
  messagesRef.current = messages;
@@ -10444,22 +10776,14 @@ function useThreadData({ threadId, attach }) {
10444
10776
  setContextWindowTokens,
10445
10777
  setWarmSummaryPending,
10446
10778
  setCompactionPending,
10447
- setWarmSummaryTopics
10779
+ setManualCompactionPending,
10780
+ setWarmSummaryTopics,
10781
+ setWarmChannelSummaries
10448
10782
  };
10449
- const addNotice = (0,react.useCallback)((text)=>{
10450
- setNotices((p)=>[
10451
- ...p,
10452
- {
10453
- id: `notice-${Date.now()}`,
10454
- text
10455
- }
10456
- ]);
10457
- }, []);
10458
10783
  (0,react.useEffect)(()=>{
10459
10784
  if (!threadId) {
10460
10785
  setMetadataThreadId(null);
10461
10786
  setMessages([]);
10462
- setNotices([]);
10463
10787
  setHasMore(false);
10464
10788
  setMessagesLoading(false);
10465
10789
  setHotSince(null);
@@ -10471,8 +10795,10 @@ function useThreadData({ threadId, attach }) {
10471
10795
  setWarmSummarySourceMessages(null);
10472
10796
  setWarmSummarySourceChars(null);
10473
10797
  setWarmSummaryTopics(null);
10798
+ setWarmChannelSummaries([]);
10474
10799
  setWarmSummaryPending(false);
10475
10800
  setCompactionPending(false);
10801
+ setManualCompactionPending(false);
10476
10802
  setContextWindowTokens(null);
10477
10803
  return;
10478
10804
  }
@@ -10490,8 +10816,10 @@ function useThreadData({ threadId, attach }) {
10490
10816
  setWarmSummarySourceMessages(null);
10491
10817
  setWarmSummarySourceChars(null);
10492
10818
  setWarmSummaryTopics(null);
10819
+ setWarmChannelSummaries([]);
10493
10820
  setWarmSummaryPending(false);
10494
10821
  setCompactionPending(false);
10822
+ setManualCompactionPending(false);
10495
10823
  setContextWindowTokens(null);
10496
10824
  client/* api */.FH.threads.get(threadId).then((d)=>{
10497
10825
  if (cancelled) return;
@@ -10537,6 +10865,7 @@ function useThreadData({ threadId, attach }) {
10537
10865
  setWarmSummarySourceMessages(updated.warm_summary_source_messages);
10538
10866
  setWarmSummarySourceChars(updated.warm_summary_source_chars);
10539
10867
  setWarmSummaryTopics(updated.warm_summary_topics);
10868
+ setWarmChannelSummaries(updated.warm_channel_summaries ?? []);
10540
10869
  setCompactionPending(updated.pending_hot_since_seq != null);
10541
10870
  const summaryFresh = updated.hot_since_seq != null && updated.warm_summary_before_seq === updated.hot_since_seq;
10542
10871
  if (!updated.pending_hot_since_seq && (!updated.hot_since_seq || summaryFresh)) {
@@ -10554,7 +10883,7 @@ function useThreadData({ threadId, attach }) {
10554
10883
  if (!threadId) return;
10555
10884
  const summaryFresh = hotSinceSeq !== null && warmSummaryBeforeSeq === hotSinceSeq;
10556
10885
  const summaryStale = warmSummaryPending && hotSinceSeq !== null && !summaryFresh;
10557
- if (!summaryStale && !compactionPending) {
10886
+ if (!summaryStale && !compactionPending && !manualCompactionPending) {
10558
10887
  if (warmSummaryPending && hotSinceSeq !== null && summaryFresh) setWarmSummaryPending(false);
10559
10888
  return;
10560
10889
  }
@@ -10580,6 +10909,7 @@ function useThreadData({ threadId, attach }) {
10580
10909
  threadId,
10581
10910
  warmSummaryPending,
10582
10911
  compactionPending,
10912
+ manualCompactionPending,
10583
10913
  hotSince,
10584
10914
  hotSinceSeq,
10585
10915
  warmSummaryBefore,
@@ -10617,9 +10947,6 @@ function useThreadData({ threadId, attach }) {
10617
10947
  messages,
10618
10948
  setMessages,
10619
10949
  messagesRef,
10620
- notices,
10621
- setNotices,
10622
- addNotice,
10623
10950
  hasMore,
10624
10951
  setHasMore,
10625
10952
  loadingMore,
@@ -10634,8 +10961,10 @@ function useThreadData({ threadId, attach }) {
10634
10961
  warmSummarySourceMessages,
10635
10962
  warmSummarySourceChars,
10636
10963
  warmSummaryTopics,
10964
+ warmChannelSummaries,
10637
10965
  warmSummaryPending,
10638
10966
  compactionPending,
10967
+ manualCompactionPending,
10639
10968
  contextWindowTokens,
10640
10969
  metaApplier,
10641
10970
  loadOlder,
@@ -10643,6 +10972,96 @@ function useThreadData({ threadId, attach }) {
10643
10972
  };
10644
10973
  }
10645
10974
 
10975
+ ;// ./components/chat/useThreadActivity.ts
10976
+ /* __next_internal_client_entry_do_not_use__ useThreadActivity auto */
10977
+
10978
+
10979
+ const BUSY_POLL_MS = 1500;
10980
+ const IDLE_POLL_MS = 5000;
10981
+ // A run's stream ends a moment before the registry marks it finished; a
10982
+ // snapshot inside this window may still report the run that just ended.
10983
+ const SETTLE_GRACE_MS = 2000;
10984
+ /**
10985
+ * Poll what the thread is doing on the server and keep the chat in step:
10986
+ * re-attach to a turn started elsewhere (scheduler, watcher, bridge, another
10987
+ * device), restore compaction flags after a remount, and refresh the thread
10988
+ * metadata once a compaction finishes.
10989
+ */ function useThreadActivity({ threadId, attach, isLive, lastSettledAt, metaApplier }) {
10990
+ const [activity, setActivity] = (0,react.useState)(null);
10991
+ const deps = (0,react.useRef)({
10992
+ attach,
10993
+ isLive,
10994
+ lastSettledAt,
10995
+ metaApplier
10996
+ });
10997
+ deps.current = {
10998
+ attach,
10999
+ isLive,
11000
+ lastSettledAt,
11001
+ metaApplier
11002
+ };
11003
+ (0,react.useEffect)(()=>{
11004
+ setActivity(null);
11005
+ if (!threadId) return;
11006
+ let cancelled = false;
11007
+ let timer = null;
11008
+ let hadCompaction = false;
11009
+ const schedule = (ms)=>{
11010
+ if (!cancelled) timer = window.setTimeout(tick, ms);
11011
+ };
11012
+ async function tick() {
11013
+ if (cancelled || !threadId) return;
11014
+ if (typeof document !== "undefined" && document.hidden) {
11015
+ schedule(IDLE_POLL_MS);
11016
+ return;
11017
+ }
11018
+ let next;
11019
+ try {
11020
+ next = await client/* api */.FH.threads.activity(threadId);
11021
+ } catch {
11022
+ schedule(IDLE_POLL_MS);
11023
+ return;
11024
+ }
11025
+ if (cancelled) return;
11026
+ setActivity(next);
11027
+ const d = deps.current;
11028
+ const serverRunning = next.run !== null || next.queue_depth > 0;
11029
+ const recentlySettled = Date.now() - d.lastSettledAt() < SETTLE_GRACE_MS;
11030
+ if (serverRunning && !d.isLive() && !recentlySettled) {
11031
+ d.attach(threadId).catch(()=>{});
11032
+ }
11033
+ if (next.compaction) {
11034
+ if (next.compaction.kind !== "refresh") d.metaApplier.setCompactionPending?.(true);
11035
+ if (next.compaction.kind === "manual") d.metaApplier.setManualCompactionPending?.(true);
11036
+ hadCompaction = true;
11037
+ } else if (hadCompaction) {
11038
+ hadCompaction = false;
11039
+ // The compaction just finished. Clear the flags from the snapshot
11040
+ // itself so a failed refresh below can't leave the chat locked, then
11041
+ // pull the new boundary and recap.
11042
+ d.metaApplier.setCompactionPending?.(false);
11043
+ d.metaApplier.setManualCompactionPending?.(false);
11044
+ client/* api */.FH.threads.get(threadId, {
11045
+ limit: 1
11046
+ }).then((meta)=>{
11047
+ if (!cancelled) applyThreadMeta(deps.current.metaApplier, meta);
11048
+ }).catch(()=>{});
11049
+ }
11050
+ schedule(next.busy ? BUSY_POLL_MS : IDLE_POLL_MS);
11051
+ }
11052
+ // The thread load attaches to any in-flight run itself; give it a beat
11053
+ // so this poller doesn't race it with a second attach.
11054
+ schedule(BUSY_POLL_MS);
11055
+ return ()=>{
11056
+ cancelled = true;
11057
+ if (timer !== null) window.clearTimeout(timer);
11058
+ };
11059
+ }, [
11060
+ threadId
11061
+ ]);
11062
+ return activity;
11063
+ }
11064
+
10646
11065
  ;// ./components/chat/useUserProfileAndAgent.ts
10647
11066
  /* __next_internal_client_entry_do_not_use__ useUserProfileAndAgent auto */
10648
11067
 
@@ -10850,6 +11269,9 @@ function useChatSubmitHandlers({ agentId, steerRun, attachments, setAttachments,
10850
11269
 
10851
11270
 
10852
11271
 
11272
+
11273
+
11274
+
10853
11275
 
10854
11276
  function ChatView({ threadId, agentId, sessionLoading, sessionError, onMessageSent }) {
10855
11277
  const { state } = (0,AppContext/* useAppContext */.U)();
@@ -10906,6 +11328,19 @@ function ChatView({ threadId, agentId, sessionLoading, sessionError, onMessageSe
10906
11328
  attachRef.current = sse.attach;
10907
11329
  clearStreamingRef.current = sse.clearStreamingContent;
10908
11330
  clearToolEventsRef.current = sse.clearToolEvents;
11331
+ // `compacting` lives in this component, which remounts per agent; the
11332
+ // server flag keeps a /compact started before an agent switch visible.
11333
+ const sessionCompacting = compacting || thread.manualCompactionPending;
11334
+ const activity = useThreadActivity({
11335
+ threadId,
11336
+ attach: stableAttach,
11337
+ isLive: sse.isLive,
11338
+ lastSettledAt: sse.lastSettledAt,
11339
+ metaApplier: thread.metaApplier
11340
+ });
11341
+ // Run phases come through the attached stream; background compaction
11342
+ // outside a run has no stream, so label it from the polled activity.
11343
+ const backgroundCompaction = !sse.streaming && !sessionCompacting ? activity?.compaction?.kind ?? null : null;
10909
11344
  useChatErrorReporting({
10910
11345
  sessionError,
10911
11346
  streamError: sse.error,
@@ -10915,6 +11350,8 @@ function ChatView({ threadId, agentId, sessionLoading, sessionError, onMessageSe
10915
11350
  });
10916
11351
  const streamingRef = (0,react.useRef)(false);
10917
11352
  streamingRef.current = sse.streaming;
11353
+ const currentThreadIdRef = (0,react.useRef)(threadId);
11354
+ currentThreadIdRef.current = threadId;
10918
11355
  // Auto compaction starts server-side during a run; poll so the banner shows live.
10919
11356
  (0,react.useEffect)(()=>{
10920
11357
  if (!threadId || !sse.streaming) return;
@@ -10945,10 +11382,13 @@ function ChatView({ threadId, agentId, sessionLoading, sessionError, onMessageSe
10945
11382
  });
10946
11383
  useTrackLoading(!!sessionLoading);
10947
11384
  useTrackLoading(sse.streaming);
10948
- useTrackLoading(compacting);
11385
+ useTrackLoading(sessionCompacting);
10949
11386
  useTrackLoading(thread.loadingMore);
10950
11387
  useTrackLoading(thread.messagesLoading);
10951
11388
  useTrackLoading(agentConfigLoading);
11389
+ useActivityWhile(sessionCompacting, "Compacting session…");
11390
+ useActivityWhile(backgroundCompaction === "auto", "Compacting earlier messages…");
11391
+ useActivityWhile(backgroundCompaction === "refresh", "Updating summary…");
10952
11392
  useActivityWhile(thread.messagesLoading, "Loading chat history…");
10953
11393
  useActivityWhile(agentConfigLoading, "Loading agent…");
10954
11394
  useActivityWhile(profileLoading, "Loading profile…");
@@ -11052,19 +11492,35 @@ function ChatView({ threadId, agentId, sessionLoading, sessionError, onMessageSe
11052
11492
  const queue = useChatQueue({
11053
11493
  threadId,
11054
11494
  streaming: sse.streaming,
11055
- compacting,
11495
+ compacting: sessionCompacting,
11056
11496
  launchRun
11057
11497
  });
11058
11498
  queueApiRef.current = queue;
11059
11499
  drainQueueRef.current = queue.drainQueueRef.current;
11060
11500
  async function handleCompact() {
11061
11501
  if (!agentId) return;
11502
+ const notifyCompaction = (result)=>{
11503
+ const toast = compactionOutcomeToast(result);
11504
+ (0,ui_toasts/* pushToast */.Iz)({
11505
+ ...toast,
11506
+ source: "system",
11507
+ sourceLabel: "Chat",
11508
+ agent_id: agentId,
11509
+ thread_id: threadId,
11510
+ ttl: 5000,
11511
+ dedupeKey: `compact:${agentId}`
11512
+ });
11513
+ };
11062
11514
  setCompacting(true);
11063
11515
  try {
11064
11516
  const result = await client/* api */.FH.agents.compact(agentId, {
11065
11517
  resetContext: true
11066
11518
  });
11067
- if (result.compacted) {
11519
+ // The thread may have changed while compaction ran; never apply its
11520
+ // result to a different thread's view.
11521
+ const compactedThreadId = threadId;
11522
+ const stillCurrent = ()=>compactedThreadId !== null && currentThreadIdRef.current === compactedThreadId;
11523
+ if (result.compacted && compactedThreadId !== null && stillCurrent()) {
11068
11524
  // Server moved the hot/warm pin to just after the last existing
11069
11525
  // message and persisted the warm summary. Mirror that in-place so
11070
11526
  // the warm card shows the fresh summary without wiping the visible
@@ -11076,16 +11532,29 @@ function ChatView({ threadId, agentId, sessionLoading, sessionError, onMessageSe
11076
11532
  thread.metaApplier.setWarmSummary(result.warm_summary ?? null);
11077
11533
  thread.metaApplier.setWarmSummaryBefore(result.warm_summary_before ?? null);
11078
11534
  thread.metaApplier.setWarmSummaryBeforeSeq(result.warm_summary_before_seq ?? null);
11079
- thread.metaApplier.setWarmSummaryBeforeSeq(result.warm_summary_before_seq ?? null);
11080
11535
  thread.metaApplier.setWarmSummaryComputedAt(result.warm_summary_computed_at ?? null);
11081
11536
  thread.metaApplier.setWarmSummarySourceMessages(result.warm_summary_source_messages ?? null);
11082
11537
  thread.metaApplier.setWarmSummarySourceChars(result.warm_summary_source_chars ?? null);
11083
11538
  thread.metaApplier.setWarmSummaryTopics?.(parseWarmSummaryTopics(result.warm_summary_topics));
11084
- } else {
11085
- thread.addNotice("Nothing to compact yet — send some messages first.");
11539
+ // The compact response carries only the chat recap; channel recaps
11540
+ // (bridge, watcher, scheduled task) come with the thread metadata.
11541
+ void client/* api */.FH.threads.get(compactedThreadId, {
11542
+ limit: 1
11543
+ }).then((d)=>{
11544
+ if (stillCurrent()) applyThreadMeta(thread.metaApplier, d);
11545
+ }).catch(()=>{});
11086
11546
  }
11547
+ notifyCompaction(result);
11087
11548
  } catch (err) {
11088
- thread.addNotice(`Compaction failed: ${String(err)}`);
11549
+ (0,error_report/* pushErrorToast */.uS)({
11550
+ title: "Compaction failed",
11551
+ error: err,
11552
+ context: {
11553
+ panel: "chat",
11554
+ action: "compact",
11555
+ agent_id: agentId
11556
+ }
11557
+ });
11089
11558
  } finally{
11090
11559
  setCompacting(false);
11091
11560
  queue.drainQueueRef.current();
@@ -11111,7 +11580,6 @@ function ChatView({ threadId, agentId, sessionLoading, sessionError, onMessageSe
11111
11580
  threadId: threadId,
11112
11581
  messages: thread.messages,
11113
11582
  steeredSegments: sse.steeredSegments,
11114
- notices: thread.notices,
11115
11583
  agentConfig: agentConfig,
11116
11584
  userProfile: userProfile,
11117
11585
  // streamingContent stays visible past `streaming=false` so the bubble
@@ -11138,8 +11606,9 @@ function ChatView({ threadId, agentId, sessionLoading, sessionError, onMessageSe
11138
11606
  warmSummarySourceMessages: thread.warmSummarySourceMessages,
11139
11607
  warmSummarySourceChars: thread.warmSummarySourceChars,
11140
11608
  warmSummaryTopics: thread.warmSummaryTopics,
11609
+ warmChannelSummaries: thread.warmChannelSummaries,
11141
11610
  warmSummaryPending: thread.warmSummaryPending,
11142
- compactionPending: thread.compactionPending || compacting,
11611
+ compactionPending: thread.compactionPending || sessionCompacting,
11143
11612
  onSetContextPin: thread.setContextPin,
11144
11613
  streaming: sse.streaming,
11145
11614
  contextWindowTokens: thread.contextWindowTokens,
@@ -11167,7 +11636,7 @@ function ChatView({ threadId, agentId, sessionLoading, sessionError, onMessageSe
11167
11636
  onVoiceTranscript: handleVoiceTranscript,
11168
11637
  disabled: !agentId,
11169
11638
  placeholder: composerPlaceholder({
11170
- compacting,
11639
+ compacting: sessionCompacting,
11171
11640
  sessionLoading: !!sessionLoading,
11172
11641
  streaming: sse.streaming
11173
11642
  })
@@ -29901,6 +30370,22 @@ function BootScreen({ agents, agentsLoaded, activeAgentId, onPickAgent, suppress
29901
30370
  setAdoptionBusy(null);
29902
30371
  }
29903
30372
  }
30373
+ async function handleAdoptionItemRetry(itemId) {
30374
+ if (adoptionBusy || adoption?.status === "running") return;
30375
+ setAdoptionBusy("retry");
30376
+ try {
30377
+ const next = await client/* api */.FH.lifecycle.adoption.retryItem(itemId);
30378
+ setAdoption(next);
30379
+ adoptionRunStartedRef.current = null;
30380
+ } catch {
30381
+ setAdoption((prev)=>prev ? {
30382
+ ...prev,
30383
+ error: "Could not retry that step."
30384
+ } : prev);
30385
+ } finally{
30386
+ setAdoptionBusy(null);
30387
+ }
30388
+ }
29904
30389
  // The agent rendered in the centered tile. During `loading` and
29905
30390
  // `pick` it's the default (so the user sees the same artwork as soon
29906
30391
  // as agents resolve). During `opening` it's whatever was picked.
@@ -30043,6 +30528,9 @@ function BootScreen({ agents, agentsLoaded, activeAgentId, onPickAgent, suppress
30043
30528
  summary: adoptionLiveLabel ?? adoption.summary,
30044
30529
  items: adoption.checklist,
30045
30530
  error: adoption.error,
30531
+ onRetryItem: (item)=>void handleAdoptionItemRetry(item.id),
30532
+ canRetryItem: (item)=>item.id !== "fetch-changes",
30533
+ retryDisabled: adoptionBusy !== null || adoption.status === "running",
30046
30534
  children: [
30047
30535
  adoption.status === "done" && /*#__PURE__*/ (0,jsx_runtime.jsx)("p", {
30048
30536
  className: "mt-2 rounded-lg border border-border/50 bg-surface px-2 py-1 text-[10px] leading-snug text-fg-muted",
@@ -33398,105 +33886,6 @@ function AppShell() {
33398
33886
  }
33399
33887
 
33400
33888
 
33401
- /***/ }),
33402
-
33403
- /***/ 30737:
33404
- /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
33405
-
33406
- "use strict";
33407
- /* harmony export */ __webpack_require__.d(__webpack_exports__, {
33408
- /* harmony export */ D: () => (/* binding */ useTheme),
33409
- /* harmony export */ ThemeProvider: () => (/* binding */ ThemeProvider)
33410
- /* harmony export */ });
33411
- /* harmony import */ var react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(95155);
33412
- /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(12115);
33413
- /* __next_internal_client_entry_do_not_use__ ThemeProvider,useTheme auto */
33414
-
33415
- const STORAGE_KEY = "jarela-theme";
33416
- function isTheme(v) {
33417
- return v === "light" || v === "dark" || v === "system";
33418
- }
33419
- function readStored() {
33420
- if (false) {}
33421
- try {
33422
- const v = window.localStorage.getItem(STORAGE_KEY);
33423
- return isTheme(v) ? v : "system";
33424
- } catch {
33425
- return "system";
33426
- }
33427
- }
33428
- const LIGHT_CHROME = "#ffffff";
33429
- const DARK_CHROME = "#09090b";
33430
- function resolveChrome(theme) {
33431
- if (theme === "light") return LIGHT_CHROME;
33432
- if (theme === "dark") return DARK_CHROME;
33433
- if (false) {}
33434
- return window.matchMedia("(prefers-color-scheme: dark)").matches ? DARK_CHROME : LIGHT_CHROME;
33435
- }
33436
- // Keep the single <meta name="theme-color"> tag (installed by the pre-paint
33437
- // script in app/layout.tsx) aligned with the active surface so the PWA's
33438
- // desktop title bar and mobile address bar match the theme.
33439
- function syncChrome(theme) {
33440
- if (typeof document === "undefined") return;
33441
- const meta = document.querySelector('meta[name="theme-color"]');
33442
- if (meta) meta.setAttribute("content", resolveChrome(theme));
33443
- }
33444
- function apply(theme) {
33445
- if (typeof document === "undefined") return;
33446
- document.documentElement.setAttribute("data-theme", theme);
33447
- syncChrome(theme);
33448
- }
33449
- const ThemeContext = /*#__PURE__*/ (0,react__WEBPACK_IMPORTED_MODULE_1__.createContext)(null);
33450
- function ThemeProvider({ children }) {
33451
- // Initial state stays "system" on the server to match the pre-paint script,
33452
- // which writes data-theme before React hydrates. The effect below syncs the
33453
- // React state to whatever the script (or localStorage) decided.
33454
- const [theme, setThemeState] = (0,react__WEBPACK_IMPORTED_MODULE_1__.useState)("system");
33455
- (0,react__WEBPACK_IMPORTED_MODULE_1__.useEffect)(()=>{
33456
- const stored = readStored();
33457
- setThemeState(stored);
33458
- // When in "system" mode, mirror OS-level changes into the PWA chrome.
33459
- if (false) {}
33460
- const mq = window.matchMedia("(prefers-color-scheme: dark)");
33461
- const onChange = ()=>{
33462
- if (readStored() === "system") syncChrome("system");
33463
- };
33464
- mq.addEventListener?.("change", onChange);
33465
- return ()=>mq.removeEventListener?.("change", onChange);
33466
- }, []);
33467
- const setTheme = (0,react__WEBPACK_IMPORTED_MODULE_1__.useCallback)((t)=>{
33468
- setThemeState(t);
33469
- apply(t);
33470
- try {
33471
- window.localStorage.setItem(STORAGE_KEY, t);
33472
- } catch {
33473
- /* ignore quota / private-mode errors */ }
33474
- }, []);
33475
- return /*#__PURE__*/ (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(ThemeContext.Provider, {
33476
- value: {
33477
- theme,
33478
- setTheme
33479
- },
33480
- children: children
33481
- });
33482
- }
33483
- function useTheme() {
33484
- const ctx = (0,react__WEBPACK_IMPORTED_MODULE_1__.useContext)(ThemeContext);
33485
- if (!ctx) throw new Error("useTheme must be used within ThemeProvider");
33486
- return ctx;
33487
- }
33488
-
33489
-
33490
- /***/ }),
33491
-
33492
- /***/ 39852:
33493
- /***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {
33494
-
33495
- Promise.resolve(/* import() eager */).then(__webpack_require__.bind(__webpack_require__, 9024));
33496
- ;
33497
- Promise.resolve(/* import() eager */).then(__webpack_require__.bind(__webpack_require__, 12283));
33498
-
33499
-
33500
33889
  /***/ })
33501
33890
 
33502
33891
  },
@@ -33507,4 +33896,4 @@ Promise.resolve(/* import() eager */).then(__webpack_require__.bind(__webpack_re
33507
33896
  /******/ _N_E = __webpack_exports__;
33508
33897
  /******/ }
33509
33898
  ]);
33510
- //# sourceMappingURL=page-7017f07f8a7a083c.js.map
33899
+ //# sourceMappingURL=page-213a623b37226452.js.map