@circuitwall/jarela 2.2.1 → 2.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (703) hide show
  1. package/.next/standalone/.next/BUILD_ID +1 -1
  2. package/.next/standalone/.next/app-path-routes-manifest.json +2 -1
  3. package/.next/standalone/.next/build-manifest.json +2 -2
  4. package/.next/standalone/.next/prerender-manifest.json +3 -3
  5. package/.next/standalone/.next/routes-manifest.json +8 -0
  6. package/.next/standalone/.next/server/app/_global-error/page.js +68 -68
  7. package/.next/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  8. package/.next/standalone/.next/server/app/_global-error.html +1 -1
  9. package/.next/standalone/.next/server/app/_global-error.rsc +1 -1
  10. package/.next/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  11. package/.next/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  12. package/.next/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  13. package/.next/standalone/.next/server/app/_not-found/page.js +76 -76
  14. package/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  15. package/.next/standalone/.next/server/app/_not-found.html +2 -2
  16. package/.next/standalone/.next/server/app/_not-found.rsc +2 -2
  17. package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +2 -2
  18. package/.next/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +2 -2
  19. package/.next/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  20. package/.next/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  21. package/.next/standalone/.next/server/app/api/v1/access/[identity]/route.js +100 -93
  22. package/.next/standalone/.next/server/app/api/v1/access/route.js +176 -169
  23. package/.next/standalone/.next/server/app/api/v1/agents/[id]/compact/route.js +89 -56
  24. package/.next/standalone/.next/server/app/api/v1/agents/[id]/compact/route.js.nft.json +1 -1
  25. package/.next/standalone/.next/server/app/api/v1/agents/[id]/display-filters/route.js +139 -127
  26. package/.next/standalone/.next/server/app/api/v1/agents/[id]/route.js +107 -100
  27. package/.next/standalone/.next/server/app/api/v1/agents/[id]/thread/route.js +765 -753
  28. package/.next/standalone/.next/server/app/api/v1/agents/route.js +72 -65
  29. package/.next/standalone/.next/server/app/api/v1/allowed-sites/[hostname]/route.js +371 -364
  30. package/.next/standalone/.next/server/app/api/v1/allowed-sites/route.js +809 -802
  31. package/.next/standalone/.next/server/app/api/v1/artifacts/lifecycle/route.js +9 -2
  32. package/.next/standalone/.next/server/app/api/v1/attachments/files/route.js +49 -49
  33. package/.next/standalone/.next/server/app/api/v1/attachments/images/route.js +910 -910
  34. package/.next/standalone/.next/server/app/api/v1/bridges/[id]/chats/route.js +583 -16
  35. package/.next/standalone/.next/server/app/api/v1/bridges/[id]/chats/route.js.nft.json +1 -1
  36. package/.next/standalone/.next/server/app/api/v1/bridges/[id]/ignores/[remote_jid]/route.js +41 -30
  37. package/.next/standalone/.next/server/app/api/v1/bridges/[id]/ignores/route.js +48 -37
  38. package/.next/standalone/.next/server/app/api/v1/bridges/[id]/lookup/route.js +697 -130
  39. package/.next/standalone/.next/server/app/api/v1/bridges/[id]/lookup/route.js.nft.json +1 -1
  40. package/.next/standalone/.next/server/app/api/v1/bridges/[id]/pair/route.js +703 -136
  41. package/.next/standalone/.next/server/app/api/v1/bridges/[id]/pair/route.js.nft.json +1 -1
  42. package/.next/standalone/.next/server/app/api/v1/bridges/[id]/route.js +796 -229
  43. package/.next/standalone/.next/server/app/api/v1/bridges/[id]/route.js.nft.json +1 -1
  44. package/.next/standalone/.next/server/app/api/v1/bridges/[id]/routes/[route_id]/route.js +762 -746
  45. package/.next/standalone/.next/server/app/api/v1/bridges/[id]/routes/route.js +1050 -1034
  46. package/.next/standalone/.next/server/app/api/v1/bridges/[id]/status/route.js +673 -106
  47. package/.next/standalone/.next/server/app/api/v1/bridges/[id]/status/route.js.nft.json +1 -1
  48. package/.next/standalone/.next/server/app/api/v1/bridges/kinds/route.js +811 -804
  49. package/.next/standalone/.next/server/app/api/v1/bridges/kinds/route.js.nft.json +1 -1
  50. package/.next/standalone/.next/server/app/api/v1/bridges/route.js +718 -706
  51. package/.next/standalone/.next/server/app/api/v1/bridges/route.js.nft.json +1 -1
  52. package/.next/standalone/.next/server/app/api/v1/builtin-tools/route.js +9 -9
  53. package/.next/standalone/.next/server/app/api/v1/builtin-tools/route.js.nft.json +1 -1
  54. package/.next/standalone/.next/server/app/api/v1/config/route.js +85 -85
  55. package/.next/standalone/.next/server/app/api/v1/credentials/[id]/route.js +709 -709
  56. package/.next/standalone/.next/server/app/api/v1/credentials/[id]/route.js.nft.json +1 -1
  57. package/.next/standalone/.next/server/app/api/v1/credentials/route.js +2 -2
  58. package/.next/standalone/.next/server/app/api/v1/credentials/route.js.nft.json +1 -1
  59. package/.next/standalone/.next/server/app/api/v1/dashboard/currency/route.js +10 -10
  60. package/.next/standalone/.next/server/app/api/v1/dashboard/metrics/route.js +796 -784
  61. package/.next/standalone/.next/server/app/api/v1/dashboard/pricing/route.js +30 -23
  62. package/.next/standalone/.next/server/app/api/v1/dashboard/pricing-task/route.js +86 -86
  63. package/.next/standalone/.next/server/app/api/v1/dashboard/pricing-task/route.js.nft.json +1 -1
  64. package/.next/standalone/.next/server/app/api/v1/delegations/codex/[job_id]/route.js +57 -57
  65. package/.next/standalone/.next/server/app/api/v1/delegations/codex/[job_id]/route.js.nft.json +1 -1
  66. package/.next/standalone/.next/server/app/api/v1/documents/search/route.js +385 -378
  67. package/.next/standalone/.next/server/app/api/v1/documents/settings/route.js +51 -44
  68. package/.next/standalone/.next/server/app/api/v1/documents/sources/[id]/reindex/route.js +65 -65
  69. package/.next/standalone/.next/server/app/api/v1/documents/sources/[id]/reindex/route.js.nft.json +1 -1
  70. package/.next/standalone/.next/server/app/api/v1/documents/sources/[id]/route.js +122 -122
  71. package/.next/standalone/.next/server/app/api/v1/documents/sources/[id]/route.js.nft.json +1 -1
  72. package/.next/standalone/.next/server/app/api/v1/documents/sources/route.js +37 -37
  73. package/.next/standalone/.next/server/app/api/v1/documents/sources/route.js.nft.json +1 -1
  74. package/.next/standalone/.next/server/app/api/v1/env/route.js +9 -9
  75. package/.next/standalone/.next/server/app/api/v1/env-sync/allowlist/route.js +375 -368
  76. package/.next/standalone/.next/server/app/api/v1/env-sync/route.js +51 -44
  77. package/.next/standalone/.next/server/app/api/v1/events/route.js +745 -178
  78. package/.next/standalone/.next/server/app/api/v1/events/route.js.nft.json +1 -1
  79. package/.next/standalone/.next/server/app/api/v1/events/test/route.js +77 -77
  80. package/.next/standalone/.next/server/app/api/v1/extension/agents/route.js +763 -763
  81. package/.next/standalone/.next/server/app/api/v1/extension/agents/route.js.nft.json +1 -1
  82. package/.next/standalone/.next/server/app/api/v1/extension/browser/activate/route.js +51 -44
  83. package/.next/standalone/.next/server/app/api/v1/extension/browser/foreground/route.js +16 -9
  84. package/.next/standalone/.next/server/app/api/v1/extension/browser/history/route.js +72 -65
  85. package/.next/standalone/.next/server/app/api/v1/extension/browser/poll/route.js +41 -34
  86. package/.next/standalone/.next/server/app/api/v1/extension/browser/progress/route.js +211 -204
  87. package/.next/standalone/.next/server/app/api/v1/extension/browser/result/route.js +140 -133
  88. package/.next/standalone/.next/server/app/api/v1/extension/browser/retry/route.js +113 -106
  89. package/.next/standalone/.next/server/app/api/v1/extension/browser/status/route.js +121 -114
  90. package/.next/standalone/.next/server/app/api/v1/extension/browser/tabs/route.js +141 -134
  91. package/.next/standalone/.next/server/app/api/v1/extension/fill/route.js +690 -690
  92. package/.next/standalone/.next/server/app/api/v1/extension/fill/route.js.nft.json +1 -1
  93. package/.next/standalone/.next/server/app/api/v1/extension/refine/route.js +93 -93
  94. package/.next/standalone/.next/server/app/api/v1/extension/refine/route.js.nft.json +1 -1
  95. package/.next/standalone/.next/server/app/api/v1/extension/turn/route.js +9 -9
  96. package/.next/standalone/.next/server/app/api/v1/extension/turn/route.js.nft.json +1 -1
  97. package/.next/standalone/.next/server/app/api/v1/extensions/route.js +185 -185
  98. package/.next/standalone/.next/server/app/api/v1/extensions/route.js.nft.json +1 -1
  99. package/.next/standalone/.next/server/app/api/v1/extensions/tools/[name]/config/route.js +171 -171
  100. package/.next/standalone/.next/server/app/api/v1/extensions/tools/[name]/config/route.js.nft.json +1 -1
  101. package/.next/standalone/.next/server/app/api/v1/extensions/tools/[name]/route.js +396 -396
  102. package/.next/standalone/.next/server/app/api/v1/extensions/tools/[name]/route.js.nft.json +1 -1
  103. package/.next/standalone/.next/server/app/api/v1/extensions/tools/[name]/secrets/route.js +212 -212
  104. package/.next/standalone/.next/server/app/api/v1/extensions/tools/[name]/secrets/route.js.nft.json +1 -1
  105. package/.next/standalone/.next/server/app/api/v1/files/[name]/route.js +235 -235
  106. package/.next/standalone/.next/server/app/api/v1/fs/browse/route.js +26 -26
  107. package/.next/standalone/.next/server/app/api/v1/harnesses/[id]/route.js +228 -221
  108. package/.next/standalone/.next/server/app/api/v1/harnesses/default/route.js +65 -58
  109. package/.next/standalone/.next/server/app/api/v1/harnesses/route.js +79 -72
  110. package/.next/standalone/.next/server/app/api/v1/health/probes/route.js +9 -9
  111. package/.next/standalone/.next/server/app/api/v1/health/probes/route.js.nft.json +1 -1
  112. package/.next/standalone/.next/server/app/api/v1/health/route.js +783 -771
  113. package/.next/standalone/.next/server/app/api/v1/integrations/[name]/route.js +140 -133
  114. package/.next/standalone/.next/server/app/api/v1/integrations/[name]/test/route.js +9 -9
  115. package/.next/standalone/.next/server/app/api/v1/integrations/[name]/test/route.js.nft.json +1 -1
  116. package/.next/standalone/.next/server/app/api/v1/integrations/gmail/oauth/callback/route.js +370 -363
  117. package/.next/standalone/.next/server/app/api/v1/integrations/gmail/oauth/start/route.js +240 -233
  118. package/.next/standalone/.next/server/app/api/v1/integrations/gmail/oauth/status/route.js +689 -682
  119. package/.next/standalone/.next/server/app/api/v1/integrations/outlook/oauth/callback/route.js +886 -879
  120. package/.next/standalone/.next/server/app/api/v1/integrations/outlook/oauth/start/route.js +115 -108
  121. package/.next/standalone/.next/server/app/api/v1/integrations/outlook/oauth/status/route.js +955 -948
  122. package/.next/standalone/.next/server/app/api/v1/integrations/route.js +223 -216
  123. package/.next/standalone/.next/server/app/api/v1/lifecycle/adoption/route.js +876 -847
  124. package/.next/standalone/.next/server/app/api/v1/lifecycle/adoption/route.js.nft.json +1 -1
  125. package/.next/standalone/.next/server/app/api/v1/local-file/route.js +26 -26
  126. package/.next/standalone/.next/server/app/api/v1/logs/route.js +70 -70
  127. package/.next/standalone/.next/server/app/api/v1/maps/embed/route.js +79 -72
  128. package/.next/standalone/.next/server/app/api/v1/mcp-servers/[name]/route.js +991 -979
  129. package/.next/standalone/.next/server/app/api/v1/mcp-servers/registry/route.js +196 -196
  130. package/.next/standalone/.next/server/app/api/v1/mcp-servers/route.js +19 -7
  131. package/.next/standalone/.next/server/app/api/v1/memory/[namespace]/[key]/route.js +539 -532
  132. package/.next/standalone/.next/server/app/api/v1/memory/policy/route.js +86 -79
  133. package/.next/standalone/.next/server/app/api/v1/memory/route.js +58 -51
  134. package/.next/standalone/.next/server/app/api/v1/memory/search/route.js +138 -131
  135. package/.next/standalone/.next/server/app/api/v1/models/[name]/compact-threads/route.js +381 -369
  136. package/.next/standalone/.next/server/app/api/v1/models/[name]/compact-threads/route.js.nft.json +1 -1
  137. package/.next/standalone/.next/server/app/api/v1/models/[name]/route.js +150 -143
  138. package/.next/standalone/.next/server/app/api/v1/models/route.js +634 -627
  139. package/.next/standalone/.next/server/app/api/v1/packages/catalog/route.js +445 -445
  140. package/.next/standalone/.next/server/app/api/v1/packages/defaults/[id]/route.js +120 -120
  141. package/.next/standalone/.next/server/app/api/v1/packages/defaults/[id]/route.js.nft.json +1 -1
  142. package/.next/standalone/.next/server/app/api/v1/packages/install/[id]/route.js +234 -234
  143. package/.next/standalone/.next/server/app/api/v1/packages/install/[id]/route.js.nft.json +1 -1
  144. package/.next/standalone/.next/server/app/api/v1/packages/install/route.js +407 -407
  145. package/.next/standalone/.next/server/app/api/v1/packages/install/route.js.nft.json +1 -1
  146. package/.next/standalone/.next/server/app/api/v1/packages/manifests/[name]/enabled/route.js +37 -37
  147. package/.next/standalone/.next/server/app/api/v1/packages/manifests/[name]/enabled/route.js.nft.json +1 -1
  148. package/.next/standalone/.next/server/app/api/v1/packages/manifests/[name]/route.js +107 -107
  149. package/.next/standalone/.next/server/app/api/v1/packages/manifests/[name]/route.js.nft.json +1 -1
  150. package/.next/standalone/.next/server/app/api/v1/packages/manifests/route.js +228 -228
  151. package/.next/standalone/.next/server/app/api/v1/packages/manifests/route.js.nft.json +1 -1
  152. package/.next/standalone/.next/server/app/api/v1/packages/reload/route.js +9 -9
  153. package/.next/standalone/.next/server/app/api/v1/packages/reload/route.js.nft.json +1 -1
  154. package/.next/standalone/.next/server/app/api/v1/packages/route.js +148 -148
  155. package/.next/standalone/.next/server/app/api/v1/packages/route.js.nft.json +1 -1
  156. package/.next/standalone/.next/server/app/api/v1/page-capture/route.js +787 -787
  157. package/.next/standalone/.next/server/app/api/v1/page-capture/route.js.nft.json +1 -1
  158. package/.next/standalone/.next/server/app/api/v1/pending-actions/[id]/approve/route.js +529 -514
  159. package/.next/standalone/.next/server/app/api/v1/pending-actions/[id]/approve/route.js.nft.json +1 -1
  160. package/.next/standalone/.next/server/app/api/v1/pending-actions/[id]/deny/route.js +181 -181
  161. package/.next/standalone/.next/server/app/api/v1/pending-actions/[id]/deny/route.js.nft.json +1 -1
  162. package/.next/standalone/.next/server/app/api/v1/pending-actions/route.js +258 -258
  163. package/.next/standalone/.next/server/app/api/v1/pending-actions/route.js.nft.json +1 -1
  164. package/.next/standalone/.next/server/app/api/v1/profile/location/route.js +37 -30
  165. package/.next/standalone/.next/server/app/api/v1/profile/route.js +171 -164
  166. package/.next/standalone/.next/server/app/api/v1/providers/[provider]/models/route.js +51 -44
  167. package/.next/standalone/.next/server/app/api/v1/providers/[provider]/probe/route.js +15 -8
  168. package/.next/standalone/.next/server/app/api/v1/providers/github-copilot/auth/route.js +171 -164
  169. package/.next/standalone/.next/server/app/api/v1/providers/route.js +101 -94
  170. package/.next/standalone/.next/server/app/api/v1/proxy-config/route.js +457 -450
  171. package/.next/standalone/.next/server/app/api/v1/redaction/init/route.js +44 -37
  172. package/.next/standalone/.next/server/app/api/v1/redaction/route.js +65 -58
  173. package/.next/standalone/.next/server/app/api/v1/scheduled-tasks/[id]/route.js +617 -605
  174. package/.next/standalone/.next/server/app/api/v1/scheduled-tasks/[id]/run/route.js +44 -44
  175. package/.next/standalone/.next/server/app/api/v1/scheduled-tasks/[id]/run/route.js.nft.json +1 -1
  176. package/.next/standalone/.next/server/app/api/v1/scheduled-tasks/route.js +739 -732
  177. package/.next/standalone/.next/server/app/api/v1/security/idle-timeout/route.js +329 -322
  178. package/.next/standalone/.next/server/app/api/v1/security/pin/route.js +204 -197
  179. package/.next/standalone/.next/server/app/api/v1/security/state/route.js +58 -51
  180. package/.next/standalone/.next/server/app/api/v1/security/unlock/route.js +183 -176
  181. package/.next/standalone/.next/server/app/api/v1/security/verify-pin/route.js +194 -187
  182. package/.next/standalone/.next/server/app/api/v1/setup/test-key/route.js +26 -26
  183. package/.next/standalone/.next/server/app/api/v1/skills/[id]/route.js +776 -769
  184. package/.next/standalone/.next/server/app/api/v1/skills/repos/[id]/route.js +122 -115
  185. package/.next/standalone/.next/server/app/api/v1/skills/repos/route.js +334 -327
  186. package/.next/standalone/.next/server/app/api/v1/skills/route.js +873 -866
  187. package/.next/standalone/.next/server/app/api/v1/system/abort/route.js +838 -808
  188. package/.next/standalone/.next/server/app/api/v1/system/restart/route.js +177 -177
  189. package/.next/standalone/.next/server/app/api/v1/system/restart/route.js.nft.json +1 -1
  190. package/.next/standalone/.next/server/app/api/v1/tailscale/route.js +164 -164
  191. package/.next/standalone/.next/server/app/api/v1/tasks/[agent_id]/route.js +122 -115
  192. package/.next/standalone/.next/server/app/api/v1/tasks/route.js +30 -23
  193. package/.next/standalone/.next/server/app/api/v1/threads/[thread_id]/activity/route.js +1436 -0
  194. package/.next/standalone/.next/server/app/api/v1/threads/[thread_id]/activity/route.js.nft.json +1 -0
  195. package/.next/standalone/.next/server/app/api/v1/threads/[thread_id]/activity/route_client-reference-manifest.js +1 -0
  196. package/.next/standalone/.next/server/app/api/v1/threads/[thread_id]/context-pin/route.js +638 -631
  197. package/.next/standalone/.next/server/app/api/v1/threads/[thread_id]/context-pin/route.js.nft.json +1 -1
  198. package/.next/standalone/.next/server/app/api/v1/threads/[thread_id]/route.js +60 -439
  199. package/.next/standalone/.next/server/app/api/v1/threads/[thread_id]/route.js.nft.json +1 -1
  200. package/.next/standalone/.next/server/app/api/v1/threads/[thread_id]/run/route.js +172 -173
  201. package/.next/standalone/.next/server/app/api/v1/threads/[thread_id]/run/route.js.nft.json +1 -1
  202. package/.next/standalone/.next/server/app/api/v1/threads/route.js +925 -913
  203. package/.next/standalone/.next/server/app/api/v1/tools/route.js +2 -2
  204. package/.next/standalone/.next/server/app/api/v1/tools/route.js.nft.json +1 -1
  205. package/.next/standalone/.next/server/app/api/v1/update/apply/route.js +17 -17
  206. package/.next/standalone/.next/server/app/api/v1/update/apply/route.js.nft.json +1 -1
  207. package/.next/standalone/.next/server/app/api/v1/update/route.js +570 -570
  208. package/.next/standalone/.next/server/app/api/v1/voice/transcribe/route.js +241 -229
  209. package/.next/standalone/.next/server/app/api/v1/voice/tts/route.js +989 -977
  210. package/.next/standalone/.next/server/app/api/v1/watchers/[id]/route.js +40 -28
  211. package/.next/standalone/.next/server/app/api/v1/watchers/[id]/run/route.js +72 -72
  212. package/.next/standalone/.next/server/app/api/v1/watchers/[id]/run/route.js.nft.json +1 -1
  213. package/.next/standalone/.next/server/app/api/v1/watchers/reaction-scripts/route.js +128 -128
  214. package/.next/standalone/.next/server/app/api/v1/watchers/route.js +164 -164
  215. package/.next/standalone/.next/server/app/api/v1/watchers/route.js.nft.json +1 -1
  216. package/.next/standalone/.next/server/app/icon.svg/route.js +62 -62
  217. package/.next/standalone/.next/server/app/manifest.webmanifest/route.js +436 -436
  218. package/.next/standalone/.next/server/app/page.js +1179 -743
  219. package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  220. package/.next/standalone/.next/server/app/setup/page.js +99 -91
  221. package/.next/standalone/.next/server/app/setup/page_client-reference-manifest.js +1 -1
  222. package/.next/standalone/.next/server/app-paths-manifest.json +2 -1
  223. package/.next/standalone/.next/server/chunks/{424.js → 1388.js} +441 -1022
  224. package/.next/standalone/.next/server/chunks/1433.js +1 -1
  225. package/.next/standalone/.next/server/chunks/1638.js +1 -2
  226. package/.next/standalone/.next/server/chunks/1738.js +1 -1
  227. package/.next/standalone/.next/server/chunks/2068.js +47 -10
  228. package/.next/standalone/.next/server/chunks/210.js +3 -3
  229. package/.next/standalone/.next/server/chunks/2151.js +31 -1
  230. package/.next/standalone/.next/server/chunks/2207.js +1 -0
  231. package/.next/standalone/.next/server/chunks/2447.js +10 -5
  232. package/.next/standalone/.next/server/chunks/2471.js +45 -45
  233. package/.next/standalone/.next/server/chunks/2504.js +1 -1
  234. package/.next/standalone/.next/server/chunks/2695.js +17 -17
  235. package/.next/standalone/.next/server/chunks/3042.js +24 -16
  236. package/.next/standalone/.next/server/chunks/{4540.js → 309.js} +104 -38
  237. package/.next/standalone/.next/server/chunks/{2350.js → 3272.js} +104 -37
  238. package/.next/standalone/.next/server/chunks/3399.js +526 -526
  239. package/.next/standalone/.next/server/chunks/3524.js +150 -67
  240. package/.next/standalone/.next/server/chunks/3566.js +1 -1
  241. package/.next/standalone/.next/server/chunks/4189.js +946 -0
  242. package/.next/standalone/.next/server/chunks/4433.js +146 -146
  243. package/.next/standalone/.next/server/chunks/4508.js +3 -3
  244. package/.next/standalone/.next/server/chunks/4588.js +1 -0
  245. package/.next/standalone/.next/server/chunks/46.js +78 -28
  246. package/.next/standalone/.next/server/chunks/466.js +12 -0
  247. package/.next/standalone/.next/server/chunks/4868.js +206 -206
  248. package/.next/standalone/.next/server/chunks/4992.js +13 -0
  249. package/.next/standalone/.next/server/chunks/5120.js +963 -0
  250. package/.next/standalone/.next/server/chunks/5701.js +1 -1
  251. package/.next/standalone/.next/server/chunks/5900.js +1 -1
  252. package/.next/standalone/.next/server/chunks/5908.js +63 -42
  253. package/.next/standalone/.next/server/chunks/6142.js +10 -2
  254. package/.next/standalone/.next/server/chunks/6210.js +1 -0
  255. package/.next/standalone/.next/server/chunks/6213.js +1 -1
  256. package/.next/standalone/.next/server/chunks/6649.js +3 -3
  257. package/.next/standalone/.next/server/chunks/6703.js +3 -3
  258. package/.next/standalone/.next/server/chunks/7445.js +1 -0
  259. package/.next/standalone/.next/server/chunks/8067.js +12 -0
  260. package/.next/standalone/.next/server/chunks/8461.js +24 -17
  261. package/.next/standalone/.next/server/chunks/8558.js +1 -1
  262. package/.next/standalone/.next/server/chunks/8724.js +1 -1
  263. package/.next/standalone/.next/server/chunks/8849.js +91 -91
  264. package/.next/standalone/.next/server/chunks/9032.js +4 -3
  265. package/.next/standalone/.next/server/chunks/{2563.js → 9164.js} +33389 -31418
  266. package/.next/standalone/.next/server/chunks/9237.js +396 -396
  267. package/.next/standalone/.next/server/chunks/{9640.js → 9304.js} +1672 -575
  268. package/.next/standalone/.next/server/chunks/9406.js +1 -1
  269. package/.next/standalone/.next/server/chunks/9590.js +68 -18
  270. package/.next/standalone/.next/server/chunks/9824.js +98 -98
  271. package/.next/standalone/.next/server/chunks/9826.js +1 -0
  272. package/.next/standalone/.next/server/middleware-build-manifest.js +2 -2
  273. package/.next/standalone/.next/server/middleware.js +486 -415
  274. package/.next/standalone/.next/server/pages/404.html +2 -2
  275. package/.next/standalone/.next/server/pages/500.html +1 -1
  276. package/.next/standalone/.next/server/preview-props.json +3 -3
  277. package/.next/standalone/.next/server/server-reference-manifest.json +1 -1
  278. package/.next/standalone/.next/static/chunks/{1395-a340fb0a345382a4.js → 1395-e4a99912b8f83044.js} +13 -1
  279. package/.next/standalone/.next/static/chunks/app/_global-error/{page-36cb8b428b38b26a.js → page-6fc5f8e744c81802.js} +1 -1
  280. package/.next/standalone/.next/static/chunks/app/api/v1/access/[identity]/{route-36cb8b428b38b26a.js → route-6fc5f8e744c81802.js} +1 -1
  281. package/.next/standalone/.next/static/chunks/app/api/v1/access/{route-36cb8b428b38b26a.js → route-6fc5f8e744c81802.js} +1 -1
  282. package/.next/standalone/.next/static/chunks/app/api/v1/agents/[id]/compact/{route-36cb8b428b38b26a.js → route-6fc5f8e744c81802.js} +1 -1
  283. package/.next/standalone/.next/static/chunks/app/api/v1/agents/[id]/display-filters/route-6fc5f8e744c81802.js +17 -0
  284. package/.next/standalone/.next/static/chunks/app/api/v1/agents/[id]/route-6fc5f8e744c81802.js +17 -0
  285. package/.next/standalone/.next/static/chunks/app/api/v1/agents/[id]/thread/route-6fc5f8e744c81802.js +17 -0
  286. package/.next/standalone/.next/static/chunks/app/api/v1/agents/route-6fc5f8e744c81802.js +17 -0
  287. package/.next/standalone/.next/static/chunks/app/api/v1/allowed-sites/[hostname]/route-6fc5f8e744c81802.js +17 -0
  288. package/.next/standalone/.next/static/chunks/app/api/v1/allowed-sites/route-6fc5f8e744c81802.js +17 -0
  289. package/.next/standalone/.next/static/chunks/app/api/v1/artifacts/lifecycle/route-6fc5f8e744c81802.js +17 -0
  290. package/.next/standalone/.next/static/chunks/app/api/v1/attachments/files/route-6fc5f8e744c81802.js +17 -0
  291. package/.next/standalone/.next/static/chunks/app/api/v1/attachments/images/route-6fc5f8e744c81802.js +17 -0
  292. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/[id]/chats/route-6fc5f8e744c81802.js +17 -0
  293. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/[id]/ignores/[remote_jid]/route-6fc5f8e744c81802.js +17 -0
  294. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/[id]/ignores/route-6fc5f8e744c81802.js +17 -0
  295. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/[id]/lookup/route-6fc5f8e744c81802.js +17 -0
  296. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/[id]/pair/route-6fc5f8e744c81802.js +17 -0
  297. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/[id]/route-6fc5f8e744c81802.js +17 -0
  298. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/[id]/routes/[route_id]/route-6fc5f8e744c81802.js +17 -0
  299. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/[id]/routes/route-6fc5f8e744c81802.js +17 -0
  300. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/[id]/status/route-6fc5f8e744c81802.js +17 -0
  301. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/kinds/route-6fc5f8e744c81802.js +17 -0
  302. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/route-6fc5f8e744c81802.js +17 -0
  303. package/.next/standalone/.next/static/chunks/app/api/v1/builtin-tools/route-6fc5f8e744c81802.js +17 -0
  304. package/.next/standalone/.next/static/chunks/app/api/v1/config/route-6fc5f8e744c81802.js +17 -0
  305. package/.next/standalone/.next/static/chunks/app/api/v1/credentials/[id]/route-6fc5f8e744c81802.js +17 -0
  306. package/.next/standalone/.next/static/chunks/app/api/v1/credentials/route-6fc5f8e744c81802.js +17 -0
  307. package/.next/standalone/.next/static/chunks/app/api/v1/dashboard/currency/route-6fc5f8e744c81802.js +17 -0
  308. package/.next/standalone/.next/static/chunks/app/api/v1/dashboard/metrics/route-6fc5f8e744c81802.js +17 -0
  309. package/.next/standalone/.next/static/chunks/app/api/v1/dashboard/pricing/route-6fc5f8e744c81802.js +17 -0
  310. package/.next/standalone/.next/static/chunks/app/api/v1/dashboard/pricing-task/route-6fc5f8e744c81802.js +17 -0
  311. package/.next/standalone/.next/static/chunks/app/api/v1/delegations/codex/[job_id]/route-6fc5f8e744c81802.js +17 -0
  312. package/.next/standalone/.next/static/chunks/app/api/v1/documents/search/route-6fc5f8e744c81802.js +17 -0
  313. package/.next/standalone/.next/static/chunks/app/api/v1/documents/settings/route-6fc5f8e744c81802.js +17 -0
  314. package/.next/standalone/.next/static/chunks/app/api/v1/documents/sources/[id]/reindex/route-6fc5f8e744c81802.js +17 -0
  315. package/.next/standalone/.next/static/chunks/app/api/v1/documents/sources/[id]/route-6fc5f8e744c81802.js +17 -0
  316. package/.next/standalone/.next/static/chunks/app/api/v1/documents/sources/route-6fc5f8e744c81802.js +17 -0
  317. package/.next/standalone/.next/static/chunks/app/api/v1/env/route-6fc5f8e744c81802.js +17 -0
  318. package/.next/standalone/.next/static/chunks/app/api/v1/env-sync/allowlist/route-6fc5f8e744c81802.js +17 -0
  319. package/.next/standalone/.next/static/chunks/app/api/v1/env-sync/route-6fc5f8e744c81802.js +17 -0
  320. package/.next/standalone/.next/static/chunks/app/api/v1/events/route-6fc5f8e744c81802.js +17 -0
  321. package/.next/standalone/.next/static/chunks/app/api/v1/events/test/route-6fc5f8e744c81802.js +17 -0
  322. package/.next/standalone/.next/static/chunks/app/api/v1/extension/agents/route-6fc5f8e744c81802.js +17 -0
  323. package/.next/standalone/.next/static/chunks/app/api/v1/extension/browser/activate/route-6fc5f8e744c81802.js +17 -0
  324. package/.next/standalone/.next/static/chunks/app/api/v1/extension/browser/foreground/route-6fc5f8e744c81802.js +17 -0
  325. package/.next/standalone/.next/static/chunks/app/api/v1/extension/browser/history/route-6fc5f8e744c81802.js +17 -0
  326. package/.next/standalone/.next/static/chunks/app/api/v1/extension/browser/poll/route-6fc5f8e744c81802.js +17 -0
  327. package/.next/standalone/.next/static/chunks/app/api/v1/extension/browser/progress/route-6fc5f8e744c81802.js +17 -0
  328. package/.next/standalone/.next/static/chunks/app/api/v1/extension/browser/result/route-6fc5f8e744c81802.js +17 -0
  329. package/.next/standalone/.next/static/chunks/app/api/v1/extension/browser/retry/route-6fc5f8e744c81802.js +17 -0
  330. package/.next/standalone/.next/static/chunks/app/api/v1/extension/browser/status/route-6fc5f8e744c81802.js +17 -0
  331. package/.next/standalone/.next/static/chunks/app/api/v1/extension/browser/tabs/route-6fc5f8e744c81802.js +17 -0
  332. package/.next/standalone/.next/static/chunks/app/api/v1/extension/fill/route-6fc5f8e744c81802.js +17 -0
  333. package/.next/standalone/.next/static/chunks/app/api/v1/extension/refine/route-6fc5f8e744c81802.js +17 -0
  334. package/.next/standalone/.next/static/chunks/app/api/v1/extension/turn/route-6fc5f8e744c81802.js +17 -0
  335. package/.next/standalone/.next/static/chunks/app/api/v1/extensions/route-6fc5f8e744c81802.js +17 -0
  336. package/.next/standalone/.next/static/chunks/app/api/v1/extensions/tools/[name]/config/route-6fc5f8e744c81802.js +17 -0
  337. package/.next/standalone/.next/static/chunks/app/api/v1/extensions/tools/[name]/route-6fc5f8e744c81802.js +17 -0
  338. package/.next/standalone/.next/static/chunks/app/api/v1/extensions/tools/[name]/secrets/route-6fc5f8e744c81802.js +17 -0
  339. package/.next/standalone/.next/static/chunks/app/api/v1/files/[name]/route-6fc5f8e744c81802.js +17 -0
  340. package/.next/standalone/.next/static/chunks/app/api/v1/fs/browse/route-6fc5f8e744c81802.js +17 -0
  341. package/.next/standalone/.next/static/chunks/app/api/v1/harnesses/[id]/route-6fc5f8e744c81802.js +17 -0
  342. package/.next/standalone/.next/static/chunks/app/api/v1/harnesses/default/route-6fc5f8e744c81802.js +17 -0
  343. package/.next/standalone/.next/static/chunks/app/api/v1/harnesses/route-6fc5f8e744c81802.js +17 -0
  344. package/.next/standalone/.next/static/chunks/app/api/v1/health/probes/route-6fc5f8e744c81802.js +17 -0
  345. package/.next/standalone/.next/static/chunks/app/api/v1/health/route-6fc5f8e744c81802.js +17 -0
  346. package/.next/standalone/.next/static/chunks/app/api/v1/integrations/[name]/route-6fc5f8e744c81802.js +17 -0
  347. package/.next/standalone/.next/static/chunks/app/api/v1/integrations/[name]/test/route-6fc5f8e744c81802.js +17 -0
  348. package/.next/standalone/.next/static/chunks/app/api/v1/integrations/gmail/oauth/callback/route-6fc5f8e744c81802.js +17 -0
  349. package/.next/standalone/.next/static/chunks/app/api/v1/integrations/gmail/oauth/start/route-6fc5f8e744c81802.js +17 -0
  350. package/.next/standalone/.next/static/chunks/app/api/v1/integrations/gmail/oauth/status/route-6fc5f8e744c81802.js +17 -0
  351. package/.next/standalone/.next/static/chunks/app/api/v1/integrations/outlook/oauth/callback/route-6fc5f8e744c81802.js +17 -0
  352. package/.next/standalone/.next/static/chunks/app/api/v1/integrations/outlook/oauth/start/route-6fc5f8e744c81802.js +17 -0
  353. package/.next/standalone/.next/static/chunks/app/api/v1/integrations/outlook/oauth/status/route-6fc5f8e744c81802.js +17 -0
  354. package/.next/standalone/.next/static/chunks/app/api/v1/integrations/route-6fc5f8e744c81802.js +17 -0
  355. package/.next/standalone/.next/static/chunks/app/api/v1/lifecycle/adoption/route-6fc5f8e744c81802.js +17 -0
  356. package/.next/standalone/.next/static/chunks/app/api/v1/local-file/route-6fc5f8e744c81802.js +17 -0
  357. package/.next/standalone/.next/static/chunks/app/api/v1/logs/route-6fc5f8e744c81802.js +17 -0
  358. package/.next/standalone/.next/static/chunks/app/api/v1/maps/embed/route-6fc5f8e744c81802.js +17 -0
  359. package/.next/standalone/.next/static/chunks/app/api/v1/mcp-servers/[name]/route-6fc5f8e744c81802.js +17 -0
  360. package/.next/standalone/.next/static/chunks/app/api/v1/mcp-servers/registry/route-6fc5f8e744c81802.js +17 -0
  361. package/.next/standalone/.next/static/chunks/app/api/v1/mcp-servers/route-6fc5f8e744c81802.js +17 -0
  362. package/.next/standalone/.next/static/chunks/app/api/v1/memory/[namespace]/[key]/route-6fc5f8e744c81802.js +17 -0
  363. package/.next/standalone/.next/static/chunks/app/api/v1/memory/policy/route-6fc5f8e744c81802.js +17 -0
  364. package/.next/standalone/.next/static/chunks/app/api/v1/memory/route-6fc5f8e744c81802.js +17 -0
  365. package/.next/standalone/.next/static/chunks/app/api/v1/memory/search/route-6fc5f8e744c81802.js +17 -0
  366. package/.next/standalone/.next/static/chunks/app/api/v1/models/[name]/compact-threads/route-6fc5f8e744c81802.js +17 -0
  367. package/.next/standalone/.next/static/chunks/app/api/v1/models/[name]/route-6fc5f8e744c81802.js +17 -0
  368. package/.next/standalone/.next/static/chunks/app/api/v1/models/route-6fc5f8e744c81802.js +17 -0
  369. package/.next/standalone/.next/static/chunks/app/api/v1/packages/catalog/route-6fc5f8e744c81802.js +17 -0
  370. package/.next/standalone/.next/static/chunks/app/api/v1/packages/defaults/[id]/route-6fc5f8e744c81802.js +17 -0
  371. package/.next/standalone/.next/static/chunks/app/api/v1/packages/install/[id]/route-6fc5f8e744c81802.js +17 -0
  372. package/.next/standalone/.next/static/chunks/app/api/v1/packages/install/route-6fc5f8e744c81802.js +17 -0
  373. package/.next/standalone/.next/static/chunks/app/api/v1/packages/manifests/[name]/enabled/route-6fc5f8e744c81802.js +17 -0
  374. package/.next/standalone/.next/static/chunks/app/api/v1/packages/manifests/[name]/route-6fc5f8e744c81802.js +17 -0
  375. package/.next/standalone/.next/static/chunks/app/api/v1/packages/manifests/route-6fc5f8e744c81802.js +17 -0
  376. package/.next/standalone/.next/static/chunks/app/api/v1/packages/reload/route-6fc5f8e744c81802.js +17 -0
  377. package/.next/standalone/.next/static/chunks/app/api/v1/packages/route-6fc5f8e744c81802.js +17 -0
  378. package/.next/standalone/.next/static/chunks/app/api/v1/page-capture/route-6fc5f8e744c81802.js +17 -0
  379. package/.next/standalone/.next/static/chunks/app/api/v1/pending-actions/[id]/approve/route-6fc5f8e744c81802.js +17 -0
  380. package/.next/standalone/.next/static/chunks/app/api/v1/pending-actions/[id]/deny/route-6fc5f8e744c81802.js +17 -0
  381. package/.next/standalone/.next/static/chunks/app/api/v1/pending-actions/route-6fc5f8e744c81802.js +17 -0
  382. package/.next/standalone/.next/static/chunks/app/api/v1/profile/location/route-6fc5f8e744c81802.js +17 -0
  383. package/.next/standalone/.next/static/chunks/app/api/v1/profile/route-6fc5f8e744c81802.js +17 -0
  384. package/.next/standalone/.next/static/chunks/app/api/v1/providers/[provider]/models/route-6fc5f8e744c81802.js +17 -0
  385. package/.next/standalone/.next/static/chunks/app/api/v1/providers/[provider]/probe/route-6fc5f8e744c81802.js +17 -0
  386. package/.next/standalone/.next/static/chunks/app/api/v1/providers/github-copilot/auth/route-6fc5f8e744c81802.js +17 -0
  387. package/.next/standalone/.next/static/chunks/app/api/v1/providers/route-6fc5f8e744c81802.js +17 -0
  388. package/.next/standalone/.next/static/chunks/app/api/v1/proxy-config/route-6fc5f8e744c81802.js +17 -0
  389. package/.next/standalone/.next/static/chunks/app/api/v1/redaction/init/route-6fc5f8e744c81802.js +17 -0
  390. package/.next/standalone/.next/static/chunks/app/api/v1/redaction/route-6fc5f8e744c81802.js +17 -0
  391. package/.next/standalone/.next/static/chunks/app/api/v1/scheduled-tasks/[id]/route-6fc5f8e744c81802.js +17 -0
  392. package/.next/standalone/.next/static/chunks/app/api/v1/scheduled-tasks/[id]/run/route-6fc5f8e744c81802.js +17 -0
  393. package/.next/standalone/.next/static/chunks/app/api/v1/scheduled-tasks/route-6fc5f8e744c81802.js +17 -0
  394. package/.next/standalone/.next/static/chunks/app/api/v1/security/idle-timeout/route-6fc5f8e744c81802.js +17 -0
  395. package/.next/standalone/.next/static/chunks/app/api/v1/security/pin/route-6fc5f8e744c81802.js +17 -0
  396. package/.next/standalone/.next/static/chunks/app/api/v1/security/state/route-6fc5f8e744c81802.js +17 -0
  397. package/.next/standalone/.next/static/chunks/app/api/v1/security/unlock/route-6fc5f8e744c81802.js +17 -0
  398. package/.next/standalone/.next/static/chunks/app/api/v1/security/verify-pin/route-6fc5f8e744c81802.js +17 -0
  399. package/.next/standalone/.next/static/chunks/app/api/v1/setup/test-key/route-6fc5f8e744c81802.js +17 -0
  400. package/.next/standalone/.next/static/chunks/app/api/v1/skills/[id]/route-6fc5f8e744c81802.js +17 -0
  401. package/.next/standalone/.next/static/chunks/app/api/v1/skills/repos/[id]/route-6fc5f8e744c81802.js +17 -0
  402. package/.next/standalone/.next/static/chunks/app/api/v1/skills/repos/route-6fc5f8e744c81802.js +17 -0
  403. package/.next/standalone/.next/static/chunks/app/api/v1/skills/route-6fc5f8e744c81802.js +17 -0
  404. package/.next/standalone/.next/static/chunks/app/api/v1/system/abort/route-6fc5f8e744c81802.js +17 -0
  405. package/.next/standalone/.next/static/chunks/app/api/v1/system/restart/route-6fc5f8e744c81802.js +17 -0
  406. package/.next/standalone/.next/static/chunks/app/api/v1/tailscale/route-6fc5f8e744c81802.js +17 -0
  407. package/.next/standalone/.next/static/chunks/app/api/v1/tasks/[agent_id]/route-6fc5f8e744c81802.js +17 -0
  408. package/.next/standalone/.next/static/chunks/app/api/v1/tasks/route-6fc5f8e744c81802.js +17 -0
  409. package/.next/standalone/.next/static/chunks/app/api/v1/threads/[thread_id]/activity/route-6fc5f8e744c81802.js +17 -0
  410. package/.next/standalone/.next/static/chunks/app/api/v1/threads/[thread_id]/context-pin/route-6fc5f8e744c81802.js +17 -0
  411. package/.next/standalone/.next/static/chunks/app/api/v1/threads/[thread_id]/route-6fc5f8e744c81802.js +17 -0
  412. package/.next/standalone/.next/static/chunks/app/api/v1/threads/[thread_id]/run/route-6fc5f8e744c81802.js +17 -0
  413. package/.next/standalone/.next/static/chunks/app/api/v1/threads/route-6fc5f8e744c81802.js +17 -0
  414. package/.next/standalone/.next/static/chunks/app/api/v1/tools/route-6fc5f8e744c81802.js +17 -0
  415. package/.next/standalone/.next/static/chunks/app/api/v1/update/apply/route-6fc5f8e744c81802.js +17 -0
  416. package/.next/standalone/.next/static/chunks/app/api/v1/update/route-6fc5f8e744c81802.js +17 -0
  417. package/.next/standalone/.next/static/chunks/app/api/v1/voice/transcribe/route-6fc5f8e744c81802.js +17 -0
  418. package/.next/standalone/.next/static/chunks/app/api/v1/voice/tts/route-6fc5f8e744c81802.js +17 -0
  419. package/.next/standalone/.next/static/chunks/app/api/v1/watchers/[id]/route-6fc5f8e744c81802.js +17 -0
  420. package/.next/standalone/.next/static/chunks/app/api/v1/watchers/[id]/run/route-6fc5f8e744c81802.js +17 -0
  421. package/.next/standalone/.next/static/chunks/app/api/v1/watchers/reaction-scripts/route-6fc5f8e744c81802.js +17 -0
  422. package/.next/standalone/.next/static/chunks/app/api/v1/watchers/route-6fc5f8e744c81802.js +17 -0
  423. package/.next/standalone/.next/static/chunks/app/manifest.webmanifest/route-6fc5f8e744c81802.js +17 -0
  424. package/.next/standalone/.next/static/chunks/app/{page-7017f07f8a7a083c.js → page-04748847c6ff866f.js} +1013 -585
  425. package/.next/standalone/.next/static/chunks/next/dist/client/components/builtin/app-error-6fc5f8e744c81802.js +17 -0
  426. package/.next/standalone/.next/static/chunks/next/dist/client/components/builtin/forbidden-6fc5f8e744c81802.js +17 -0
  427. package/.next/standalone/.next/static/chunks/next/dist/client/components/builtin/not-found-6fc5f8e744c81802.js +17 -0
  428. package/.next/standalone/.next/static/chunks/next/dist/client/components/builtin/unauthorized-6fc5f8e744c81802.js +17 -0
  429. package/.next/standalone/.next/static/css/{d80058f0b9b41c09.css → 2669e8744cc8c212.css} +2 -2
  430. package/.next/standalone/docs/adoption/changesets.json +358 -0
  431. package/.next/standalone/lib/skills/builtins/memory-organization/SKILL.md +16 -0
  432. package/.next/standalone/package.json +3 -3
  433. package/CHANGELOG.md +44 -0
  434. package/api/client.ts +9 -0
  435. package/api/types.ts +29 -0
  436. package/app/api/v1/lifecycle/adoption/route.ts +14 -2
  437. package/app/api/v1/models/[name]/compact-threads/route.ts +14 -11
  438. package/app/api/v1/threads/[thread_id]/activity/route.ts +19 -0
  439. package/app/api/v1/threads/[thread_id]/context-pin/route.test.ts +1 -0
  440. package/app/api/v1/threads/[thread_id]/context-pin/route.ts +2 -1
  441. package/app/api/v1/threads/[thread_id]/route.ts +5 -1
  442. package/app/api/v1/threads/[thread_id]/run/route.ts +0 -1
  443. package/components/chat/ChatView.tsx +52 -11
  444. package/components/chat/ContextBoundary.test.tsx +68 -1
  445. package/components/chat/ContextBoundary.tsx +92 -13
  446. package/components/chat/MessageBubble.tsx +12 -0
  447. package/components/chat/MessageList.test.tsx +31 -0
  448. package/components/chat/MessageList.tsx +49 -28
  449. package/components/chat/ToolList.test.tsx +92 -16
  450. package/components/chat/ToolList.tsx +59 -4
  451. package/components/chat/chat-helpers.test.tsx +24 -1
  452. package/components/chat/chat-helpers.ts +47 -4
  453. package/components/chat/useThreadActivity.test.tsx +113 -0
  454. package/components/chat/useThreadActivity.ts +94 -0
  455. package/components/chat/useThreadData.ts +16 -16
  456. package/components/chat/workflow-step-retry.ts +25 -0
  457. package/components/integrations/NetworkSection.tsx +2 -2
  458. package/components/ui/BootScreen.tsx +17 -0
  459. package/components/ui/WorkflowChecklist.tsx +71 -33
  460. package/hooks/useSSE.ts +28 -3
  461. package/lib/agents/citation-checker.test.ts +40 -2
  462. package/lib/agents/citation-checker.ts +56 -11
  463. package/lib/agents/compaction-pipeline.test.ts +202 -0
  464. package/lib/agents/compaction-pipeline.ts +483 -0
  465. package/lib/agents/context-boundary.ts +5 -6
  466. package/lib/agents/conversation-summary.ts +37 -21
  467. package/lib/agents/instruction-edits.test.ts +120 -0
  468. package/lib/agents/instruction-edits.ts +65 -42
  469. package/lib/agents/prepare/history-window.test.ts +18 -0
  470. package/lib/agents/prepare/history-window.ts +11 -2
  471. package/lib/agents/prepare/request.ts +4 -2
  472. package/lib/agents/prepare/system-prompt.test.ts +49 -0
  473. package/lib/agents/prepare/system-prompt.ts +16 -5
  474. package/lib/agents/prompt-registry.test.ts +5 -140
  475. package/lib/agents/prompt-registry.ts +45 -1
  476. package/lib/agents/prompt-variants.ts +146 -0
  477. package/lib/agents/proposals.test.ts +76 -0
  478. package/lib/agents/proposals.ts +13 -5
  479. package/lib/agents/run-registry.test.ts +22 -0
  480. package/lib/agents/run-registry.ts +29 -0
  481. package/lib/agents/run-thread.auto-boundary.test.ts +125 -5
  482. package/lib/agents/run-thread.retry.test.ts +67 -1
  483. package/lib/agents/run-thread.ts +110 -10
  484. package/lib/agents/sqlite-checkpoint-saver.test.ts +91 -0
  485. package/lib/agents/thread-activity.test.ts +31 -0
  486. package/lib/agents/thread-activity.ts +27 -0
  487. package/lib/agents/thread-compaction-state.test.ts +82 -0
  488. package/lib/agents/thread-compaction-state.ts +121 -0
  489. package/lib/agents/thread-compaction.test.ts +83 -4
  490. package/lib/agents/thread-compaction.ts +34 -11
  491. package/lib/agents/warm-summary-background.test.ts +219 -5
  492. package/lib/agents/warm-summary-background.ts +346 -143
  493. package/lib/agents/warm-topics.test.ts +191 -0
  494. package/lib/agents/warm-topics.ts +317 -0
  495. package/lib/agents/workflow-step-retry.test.ts +96 -0
  496. package/lib/agents/workflow-step-retry.ts +216 -0
  497. package/lib/api/browser-control.ts +0 -3
  498. package/lib/bridges/dispatcher.ts +1 -0
  499. package/lib/bridges/message-role.test.ts +81 -0
  500. package/lib/bridges/message-role.ts +23 -10
  501. package/lib/bridges/types.ts +6 -0
  502. package/lib/bridges/whatsapp-link.test.ts +32 -0
  503. package/lib/bridges/whatsapp-link.ts +21 -0
  504. package/lib/bridges/whatsapp.inbound.test.ts +239 -0
  505. package/lib/bridges/whatsapp.sender.test.ts +80 -1
  506. package/lib/bridges/whatsapp.ts +76 -38
  507. package/lib/db/migrations.ts +5 -0
  508. package/lib/env/config.ts +2 -0
  509. package/lib/env/schema.ts +12 -0
  510. package/lib/lifecycle/changeset-build.test.ts +93 -0
  511. package/lib/lifecycle/changeset-build.ts +210 -0
  512. package/lib/lifecycle/changesets.test.ts +101 -0
  513. package/lib/lifecycle/changesets.ts +166 -0
  514. package/lib/lifecycle/surface-collect.test.ts +88 -0
  515. package/lib/lifecycle/surface-collect.ts +64 -0
  516. package/lib/lifecycle/surface-snapshot.test.ts +104 -0
  517. package/lib/lifecycle/surface-snapshot.ts +210 -0
  518. package/lib/memory/record.ts +0 -2
  519. package/lib/pricing/snapshot.test.ts +70 -0
  520. package/lib/pricing/snapshot.ts +10 -2
  521. package/lib/providers/external.ts +0 -2
  522. package/lib/proxy/dispatcher.test.ts +119 -1
  523. package/lib/proxy/dispatcher.ts +22 -9
  524. package/lib/skills/builtins/memory-organization/SKILL.md +16 -0
  525. package/lib/stores/agent-configs.ts +10 -5
  526. package/lib/stores/bridges.test.ts +81 -0
  527. package/lib/stores/bridges.ts +9 -8
  528. package/lib/stores/proxy-config.test.ts +120 -0
  529. package/lib/stores/proxy-config.ts +22 -4
  530. package/lib/stores/threads.test.ts +9 -0
  531. package/lib/stores/threads.ts +33 -19
  532. package/lib/stores/version-adoption.test.ts +96 -0
  533. package/lib/stores/version-adoption.ts +239 -26
  534. package/lib/stores/workflow-progress.ts +3 -0
  535. package/lib/tools/communications/calendar.test.ts +43 -2
  536. package/lib/tools/communications/calendar.ts +2 -0
  537. package/lib/tools/communications/gmail.test.ts +51 -1
  538. package/lib/tools/communications/gmail.ts +44 -2
  539. package/lib/tools/communications/ms-todo.ts +0 -7
  540. package/lib/tools/communications/outlook-calendar.ts +2 -0
  541. package/lib/tools/communications/outlook.test.ts +33 -2
  542. package/lib/tools/communications/outlook.ts +2 -0
  543. package/lib/tools/filesystem/edit-match.test.ts +133 -0
  544. package/lib/tools/filesystem/edit-match.ts +7 -2
  545. package/lib/tools/general/memory.ts +1 -1
  546. package/lib/tools/general/workflow-progress.ts +2 -0
  547. package/lib/tools/runtime/catalog.ts +1 -25
  548. package/lib/tools/support/result-refs.test.ts +131 -0
  549. package/lib/tools/support/result-refs.ts +41 -9
  550. package/lib/triggers/registry.ts +0 -4
  551. package/lib/utils/source-link.test.ts +51 -0
  552. package/lib/utils/source-link.ts +45 -0
  553. package/package.json +3 -3
  554. package/scripts/install-to-system.ps1 +39 -11
  555. package/scripts/install-to-system.sh +37 -3
  556. package/.next/standalone/.next/server/chunks/3979.js +0 -581
  557. package/.next/standalone/.next/server/chunks/5936.js +0 -594
  558. package/.next/standalone/.next/static/chunks/app/api/v1/agents/[id]/display-filters/route-36cb8b428b38b26a.js +0 -17
  559. package/.next/standalone/.next/static/chunks/app/api/v1/agents/[id]/route-36cb8b428b38b26a.js +0 -17
  560. package/.next/standalone/.next/static/chunks/app/api/v1/agents/[id]/thread/route-36cb8b428b38b26a.js +0 -17
  561. package/.next/standalone/.next/static/chunks/app/api/v1/agents/route-36cb8b428b38b26a.js +0 -17
  562. package/.next/standalone/.next/static/chunks/app/api/v1/allowed-sites/[hostname]/route-36cb8b428b38b26a.js +0 -17
  563. package/.next/standalone/.next/static/chunks/app/api/v1/allowed-sites/route-36cb8b428b38b26a.js +0 -17
  564. package/.next/standalone/.next/static/chunks/app/api/v1/artifacts/lifecycle/route-36cb8b428b38b26a.js +0 -17
  565. package/.next/standalone/.next/static/chunks/app/api/v1/attachments/files/route-36cb8b428b38b26a.js +0 -17
  566. package/.next/standalone/.next/static/chunks/app/api/v1/attachments/images/route-36cb8b428b38b26a.js +0 -17
  567. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/[id]/chats/route-36cb8b428b38b26a.js +0 -17
  568. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/[id]/ignores/[remote_jid]/route-36cb8b428b38b26a.js +0 -17
  569. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/[id]/ignores/route-36cb8b428b38b26a.js +0 -17
  570. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/[id]/lookup/route-36cb8b428b38b26a.js +0 -17
  571. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/[id]/pair/route-36cb8b428b38b26a.js +0 -17
  572. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/[id]/route-36cb8b428b38b26a.js +0 -17
  573. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/[id]/routes/[route_id]/route-36cb8b428b38b26a.js +0 -17
  574. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/[id]/routes/route-36cb8b428b38b26a.js +0 -17
  575. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/[id]/status/route-36cb8b428b38b26a.js +0 -17
  576. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/kinds/route-36cb8b428b38b26a.js +0 -17
  577. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/route-36cb8b428b38b26a.js +0 -17
  578. package/.next/standalone/.next/static/chunks/app/api/v1/builtin-tools/route-36cb8b428b38b26a.js +0 -17
  579. package/.next/standalone/.next/static/chunks/app/api/v1/config/route-36cb8b428b38b26a.js +0 -17
  580. package/.next/standalone/.next/static/chunks/app/api/v1/credentials/[id]/route-36cb8b428b38b26a.js +0 -17
  581. package/.next/standalone/.next/static/chunks/app/api/v1/credentials/route-36cb8b428b38b26a.js +0 -17
  582. package/.next/standalone/.next/static/chunks/app/api/v1/dashboard/currency/route-36cb8b428b38b26a.js +0 -17
  583. package/.next/standalone/.next/static/chunks/app/api/v1/dashboard/metrics/route-36cb8b428b38b26a.js +0 -17
  584. package/.next/standalone/.next/static/chunks/app/api/v1/dashboard/pricing/route-36cb8b428b38b26a.js +0 -17
  585. package/.next/standalone/.next/static/chunks/app/api/v1/dashboard/pricing-task/route-36cb8b428b38b26a.js +0 -17
  586. package/.next/standalone/.next/static/chunks/app/api/v1/delegations/codex/[job_id]/route-36cb8b428b38b26a.js +0 -17
  587. package/.next/standalone/.next/static/chunks/app/api/v1/documents/search/route-36cb8b428b38b26a.js +0 -17
  588. package/.next/standalone/.next/static/chunks/app/api/v1/documents/settings/route-36cb8b428b38b26a.js +0 -17
  589. package/.next/standalone/.next/static/chunks/app/api/v1/documents/sources/[id]/reindex/route-36cb8b428b38b26a.js +0 -17
  590. package/.next/standalone/.next/static/chunks/app/api/v1/documents/sources/[id]/route-36cb8b428b38b26a.js +0 -17
  591. package/.next/standalone/.next/static/chunks/app/api/v1/documents/sources/route-36cb8b428b38b26a.js +0 -17
  592. package/.next/standalone/.next/static/chunks/app/api/v1/env/route-36cb8b428b38b26a.js +0 -17
  593. package/.next/standalone/.next/static/chunks/app/api/v1/env-sync/allowlist/route-36cb8b428b38b26a.js +0 -17
  594. package/.next/standalone/.next/static/chunks/app/api/v1/env-sync/route-36cb8b428b38b26a.js +0 -17
  595. package/.next/standalone/.next/static/chunks/app/api/v1/events/route-36cb8b428b38b26a.js +0 -17
  596. package/.next/standalone/.next/static/chunks/app/api/v1/events/test/route-36cb8b428b38b26a.js +0 -17
  597. package/.next/standalone/.next/static/chunks/app/api/v1/extension/agents/route-36cb8b428b38b26a.js +0 -17
  598. package/.next/standalone/.next/static/chunks/app/api/v1/extension/browser/activate/route-36cb8b428b38b26a.js +0 -17
  599. package/.next/standalone/.next/static/chunks/app/api/v1/extension/browser/foreground/route-36cb8b428b38b26a.js +0 -17
  600. package/.next/standalone/.next/static/chunks/app/api/v1/extension/browser/history/route-36cb8b428b38b26a.js +0 -17
  601. package/.next/standalone/.next/static/chunks/app/api/v1/extension/browser/poll/route-36cb8b428b38b26a.js +0 -17
  602. package/.next/standalone/.next/static/chunks/app/api/v1/extension/browser/progress/route-36cb8b428b38b26a.js +0 -17
  603. package/.next/standalone/.next/static/chunks/app/api/v1/extension/browser/result/route-36cb8b428b38b26a.js +0 -17
  604. package/.next/standalone/.next/static/chunks/app/api/v1/extension/browser/retry/route-36cb8b428b38b26a.js +0 -17
  605. package/.next/standalone/.next/static/chunks/app/api/v1/extension/browser/status/route-36cb8b428b38b26a.js +0 -17
  606. package/.next/standalone/.next/static/chunks/app/api/v1/extension/browser/tabs/route-36cb8b428b38b26a.js +0 -17
  607. package/.next/standalone/.next/static/chunks/app/api/v1/extension/fill/route-36cb8b428b38b26a.js +0 -17
  608. package/.next/standalone/.next/static/chunks/app/api/v1/extension/refine/route-36cb8b428b38b26a.js +0 -17
  609. package/.next/standalone/.next/static/chunks/app/api/v1/extension/turn/route-36cb8b428b38b26a.js +0 -17
  610. package/.next/standalone/.next/static/chunks/app/api/v1/extensions/route-36cb8b428b38b26a.js +0 -17
  611. package/.next/standalone/.next/static/chunks/app/api/v1/extensions/tools/[name]/config/route-36cb8b428b38b26a.js +0 -17
  612. package/.next/standalone/.next/static/chunks/app/api/v1/extensions/tools/[name]/route-36cb8b428b38b26a.js +0 -17
  613. package/.next/standalone/.next/static/chunks/app/api/v1/extensions/tools/[name]/secrets/route-36cb8b428b38b26a.js +0 -17
  614. package/.next/standalone/.next/static/chunks/app/api/v1/files/[name]/route-36cb8b428b38b26a.js +0 -17
  615. package/.next/standalone/.next/static/chunks/app/api/v1/fs/browse/route-36cb8b428b38b26a.js +0 -17
  616. package/.next/standalone/.next/static/chunks/app/api/v1/harnesses/[id]/route-36cb8b428b38b26a.js +0 -17
  617. package/.next/standalone/.next/static/chunks/app/api/v1/harnesses/default/route-36cb8b428b38b26a.js +0 -17
  618. package/.next/standalone/.next/static/chunks/app/api/v1/harnesses/route-36cb8b428b38b26a.js +0 -17
  619. package/.next/standalone/.next/static/chunks/app/api/v1/health/probes/route-36cb8b428b38b26a.js +0 -17
  620. package/.next/standalone/.next/static/chunks/app/api/v1/health/route-36cb8b428b38b26a.js +0 -17
  621. package/.next/standalone/.next/static/chunks/app/api/v1/integrations/[name]/route-36cb8b428b38b26a.js +0 -17
  622. package/.next/standalone/.next/static/chunks/app/api/v1/integrations/[name]/test/route-36cb8b428b38b26a.js +0 -17
  623. package/.next/standalone/.next/static/chunks/app/api/v1/integrations/gmail/oauth/callback/route-36cb8b428b38b26a.js +0 -17
  624. package/.next/standalone/.next/static/chunks/app/api/v1/integrations/gmail/oauth/start/route-36cb8b428b38b26a.js +0 -17
  625. package/.next/standalone/.next/static/chunks/app/api/v1/integrations/gmail/oauth/status/route-36cb8b428b38b26a.js +0 -17
  626. package/.next/standalone/.next/static/chunks/app/api/v1/integrations/outlook/oauth/callback/route-36cb8b428b38b26a.js +0 -17
  627. package/.next/standalone/.next/static/chunks/app/api/v1/integrations/outlook/oauth/start/route-36cb8b428b38b26a.js +0 -17
  628. package/.next/standalone/.next/static/chunks/app/api/v1/integrations/outlook/oauth/status/route-36cb8b428b38b26a.js +0 -17
  629. package/.next/standalone/.next/static/chunks/app/api/v1/integrations/route-36cb8b428b38b26a.js +0 -17
  630. package/.next/standalone/.next/static/chunks/app/api/v1/lifecycle/adoption/route-36cb8b428b38b26a.js +0 -17
  631. package/.next/standalone/.next/static/chunks/app/api/v1/local-file/route-36cb8b428b38b26a.js +0 -17
  632. package/.next/standalone/.next/static/chunks/app/api/v1/logs/route-36cb8b428b38b26a.js +0 -17
  633. package/.next/standalone/.next/static/chunks/app/api/v1/maps/embed/route-36cb8b428b38b26a.js +0 -17
  634. package/.next/standalone/.next/static/chunks/app/api/v1/mcp-servers/[name]/route-36cb8b428b38b26a.js +0 -17
  635. package/.next/standalone/.next/static/chunks/app/api/v1/mcp-servers/registry/route-36cb8b428b38b26a.js +0 -17
  636. package/.next/standalone/.next/static/chunks/app/api/v1/mcp-servers/route-36cb8b428b38b26a.js +0 -17
  637. package/.next/standalone/.next/static/chunks/app/api/v1/memory/[namespace]/[key]/route-36cb8b428b38b26a.js +0 -17
  638. package/.next/standalone/.next/static/chunks/app/api/v1/memory/policy/route-36cb8b428b38b26a.js +0 -17
  639. package/.next/standalone/.next/static/chunks/app/api/v1/memory/route-36cb8b428b38b26a.js +0 -17
  640. package/.next/standalone/.next/static/chunks/app/api/v1/memory/search/route-36cb8b428b38b26a.js +0 -17
  641. package/.next/standalone/.next/static/chunks/app/api/v1/models/[name]/compact-threads/route-36cb8b428b38b26a.js +0 -17
  642. package/.next/standalone/.next/static/chunks/app/api/v1/models/[name]/route-36cb8b428b38b26a.js +0 -17
  643. package/.next/standalone/.next/static/chunks/app/api/v1/models/route-36cb8b428b38b26a.js +0 -17
  644. package/.next/standalone/.next/static/chunks/app/api/v1/packages/catalog/route-36cb8b428b38b26a.js +0 -17
  645. package/.next/standalone/.next/static/chunks/app/api/v1/packages/defaults/[id]/route-36cb8b428b38b26a.js +0 -17
  646. package/.next/standalone/.next/static/chunks/app/api/v1/packages/install/[id]/route-36cb8b428b38b26a.js +0 -17
  647. package/.next/standalone/.next/static/chunks/app/api/v1/packages/install/route-36cb8b428b38b26a.js +0 -17
  648. package/.next/standalone/.next/static/chunks/app/api/v1/packages/manifests/[name]/enabled/route-36cb8b428b38b26a.js +0 -17
  649. package/.next/standalone/.next/static/chunks/app/api/v1/packages/manifests/[name]/route-36cb8b428b38b26a.js +0 -17
  650. package/.next/standalone/.next/static/chunks/app/api/v1/packages/manifests/route-36cb8b428b38b26a.js +0 -17
  651. package/.next/standalone/.next/static/chunks/app/api/v1/packages/reload/route-36cb8b428b38b26a.js +0 -17
  652. package/.next/standalone/.next/static/chunks/app/api/v1/packages/route-36cb8b428b38b26a.js +0 -17
  653. package/.next/standalone/.next/static/chunks/app/api/v1/page-capture/route-36cb8b428b38b26a.js +0 -17
  654. package/.next/standalone/.next/static/chunks/app/api/v1/pending-actions/[id]/approve/route-36cb8b428b38b26a.js +0 -17
  655. package/.next/standalone/.next/static/chunks/app/api/v1/pending-actions/[id]/deny/route-36cb8b428b38b26a.js +0 -17
  656. package/.next/standalone/.next/static/chunks/app/api/v1/pending-actions/route-36cb8b428b38b26a.js +0 -17
  657. package/.next/standalone/.next/static/chunks/app/api/v1/profile/location/route-36cb8b428b38b26a.js +0 -17
  658. package/.next/standalone/.next/static/chunks/app/api/v1/profile/route-36cb8b428b38b26a.js +0 -17
  659. package/.next/standalone/.next/static/chunks/app/api/v1/providers/[provider]/models/route-36cb8b428b38b26a.js +0 -17
  660. package/.next/standalone/.next/static/chunks/app/api/v1/providers/[provider]/probe/route-36cb8b428b38b26a.js +0 -17
  661. package/.next/standalone/.next/static/chunks/app/api/v1/providers/github-copilot/auth/route-36cb8b428b38b26a.js +0 -17
  662. package/.next/standalone/.next/static/chunks/app/api/v1/providers/route-36cb8b428b38b26a.js +0 -17
  663. package/.next/standalone/.next/static/chunks/app/api/v1/proxy-config/route-36cb8b428b38b26a.js +0 -17
  664. package/.next/standalone/.next/static/chunks/app/api/v1/redaction/init/route-36cb8b428b38b26a.js +0 -17
  665. package/.next/standalone/.next/static/chunks/app/api/v1/redaction/route-36cb8b428b38b26a.js +0 -17
  666. package/.next/standalone/.next/static/chunks/app/api/v1/scheduled-tasks/[id]/route-36cb8b428b38b26a.js +0 -17
  667. package/.next/standalone/.next/static/chunks/app/api/v1/scheduled-tasks/[id]/run/route-36cb8b428b38b26a.js +0 -17
  668. package/.next/standalone/.next/static/chunks/app/api/v1/scheduled-tasks/route-36cb8b428b38b26a.js +0 -17
  669. package/.next/standalone/.next/static/chunks/app/api/v1/security/idle-timeout/route-36cb8b428b38b26a.js +0 -17
  670. package/.next/standalone/.next/static/chunks/app/api/v1/security/pin/route-36cb8b428b38b26a.js +0 -17
  671. package/.next/standalone/.next/static/chunks/app/api/v1/security/state/route-36cb8b428b38b26a.js +0 -17
  672. package/.next/standalone/.next/static/chunks/app/api/v1/security/unlock/route-36cb8b428b38b26a.js +0 -17
  673. package/.next/standalone/.next/static/chunks/app/api/v1/security/verify-pin/route-36cb8b428b38b26a.js +0 -17
  674. package/.next/standalone/.next/static/chunks/app/api/v1/setup/test-key/route-36cb8b428b38b26a.js +0 -17
  675. package/.next/standalone/.next/static/chunks/app/api/v1/skills/[id]/route-36cb8b428b38b26a.js +0 -17
  676. package/.next/standalone/.next/static/chunks/app/api/v1/skills/repos/[id]/route-36cb8b428b38b26a.js +0 -17
  677. package/.next/standalone/.next/static/chunks/app/api/v1/skills/repos/route-36cb8b428b38b26a.js +0 -17
  678. package/.next/standalone/.next/static/chunks/app/api/v1/skills/route-36cb8b428b38b26a.js +0 -17
  679. package/.next/standalone/.next/static/chunks/app/api/v1/system/abort/route-36cb8b428b38b26a.js +0 -17
  680. package/.next/standalone/.next/static/chunks/app/api/v1/system/restart/route-36cb8b428b38b26a.js +0 -17
  681. package/.next/standalone/.next/static/chunks/app/api/v1/tailscale/route-36cb8b428b38b26a.js +0 -17
  682. package/.next/standalone/.next/static/chunks/app/api/v1/tasks/[agent_id]/route-36cb8b428b38b26a.js +0 -17
  683. package/.next/standalone/.next/static/chunks/app/api/v1/tasks/route-36cb8b428b38b26a.js +0 -17
  684. package/.next/standalone/.next/static/chunks/app/api/v1/threads/[thread_id]/context-pin/route-36cb8b428b38b26a.js +0 -17
  685. package/.next/standalone/.next/static/chunks/app/api/v1/threads/[thread_id]/route-36cb8b428b38b26a.js +0 -17
  686. package/.next/standalone/.next/static/chunks/app/api/v1/threads/[thread_id]/run/route-36cb8b428b38b26a.js +0 -17
  687. package/.next/standalone/.next/static/chunks/app/api/v1/threads/route-36cb8b428b38b26a.js +0 -17
  688. package/.next/standalone/.next/static/chunks/app/api/v1/tools/route-36cb8b428b38b26a.js +0 -17
  689. package/.next/standalone/.next/static/chunks/app/api/v1/update/apply/route-36cb8b428b38b26a.js +0 -17
  690. package/.next/standalone/.next/static/chunks/app/api/v1/update/route-36cb8b428b38b26a.js +0 -17
  691. package/.next/standalone/.next/static/chunks/app/api/v1/voice/transcribe/route-36cb8b428b38b26a.js +0 -17
  692. package/.next/standalone/.next/static/chunks/app/api/v1/voice/tts/route-36cb8b428b38b26a.js +0 -17
  693. package/.next/standalone/.next/static/chunks/app/api/v1/watchers/[id]/route-36cb8b428b38b26a.js +0 -17
  694. package/.next/standalone/.next/static/chunks/app/api/v1/watchers/[id]/run/route-36cb8b428b38b26a.js +0 -17
  695. package/.next/standalone/.next/static/chunks/app/api/v1/watchers/reaction-scripts/route-36cb8b428b38b26a.js +0 -17
  696. package/.next/standalone/.next/static/chunks/app/api/v1/watchers/route-36cb8b428b38b26a.js +0 -17
  697. package/.next/standalone/.next/static/chunks/app/manifest.webmanifest/route-36cb8b428b38b26a.js +0 -17
  698. package/.next/standalone/.next/static/chunks/next/dist/client/components/builtin/app-error-36cb8b428b38b26a.js +0 -17
  699. package/.next/standalone/.next/static/chunks/next/dist/client/components/builtin/forbidden-36cb8b428b38b26a.js +0 -17
  700. package/.next/standalone/.next/static/chunks/next/dist/client/components/builtin/not-found-36cb8b428b38b26a.js +0 -17
  701. package/.next/standalone/.next/static/chunks/next/dist/client/components/builtin/unauthorized-36cb8b428b38b26a.js +0 -17
  702. /package/.next/standalone/.next/static/{NUrC9xax1sp1Q70nlFqS6 → hwujW4hR1b-r3k5WdMxZO}/_buildManifest.js +0 -0
  703. /package/.next/standalone/.next/static/{NUrC9xax1sp1Q70nlFqS6 → hwujW4hR1b-r3k5WdMxZO}/_ssgManifest.js +0 -0
@@ -0,0 +1,239 @@
1
+ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
2
+ import type { InboundMessage } from "./types";
3
+
4
+ // Drives the real messages.upsert pipeline against a fake Baileys socket so
5
+ // routing, naming, dedupe and content extraction are tested together.
6
+
7
+ const handlers = new Map<string, (...args: unknown[]) => unknown>();
8
+ const downloadMediaMessage = vi.fn<(...args: unknown[]) => Promise<Buffer>>();
9
+ const storeCanonicalBridgeAttachment = vi.fn(async (input: { filename: string | null; media_type: string; buffer: Buffer }) => ({
10
+ type: "file_ref" as const,
11
+ media_type: input.media_type,
12
+ name: "stored.bin",
13
+ filename: (input.filename ?? "attachment").replace(/[\\/:*?"<>|\u0000-\u001f]/g, "_"),
14
+ sha256: "x",
15
+ size: input.buffer.length,
16
+ }));
17
+ let watermarks = new Map<string, number>();
18
+ const bumpRouteLastSeenTs = vi.fn();
19
+
20
+ vi.mock("@whiskeysockets/baileys", () => ({
21
+ default: () => ({
22
+ ev: { on: (event: string, fn: (...args: unknown[]) => unknown) => handlers.set(event, fn) },
23
+ sendMessage: vi.fn(),
24
+ }),
25
+ useMultiFileAuthState: async () => ({ state: {}, saveCreds: async () => {} }),
26
+ fetchLatestBaileysVersion: async () => ({ version: [2, 3000, 0] }),
27
+ DisconnectReason: { loggedOut: 401 },
28
+ downloadMediaMessage: (...args: unknown[]) => downloadMediaMessage(...args),
29
+ Browsers: { ubuntu: () => ["Ubuntu", "Chrome", "1"] },
30
+ }));
31
+ vi.mock("qrcode", () => ({ toDataURL: async () => "data:," }));
32
+ vi.mock("./modules/whatsapp/auth-state", () => ({
33
+ ensureWhatsAppAuthDir: () => "auth-dir",
34
+ removeWhatsAppAuth: () => {},
35
+ }));
36
+ vi.mock("@/lib/stores/bridges", () => ({
37
+ bumpRouteLastSeenTs: (...args: unknown[]) => bumpRouteLastSeenTs(...args),
38
+ findRoute: () => null,
39
+ getBridge: () => null,
40
+ getRouteLastSeenTsMap: () => new Map(watermarks),
41
+ }));
42
+ vi.mock("./attachment-store", () => ({
43
+ storeCanonicalBridgeAttachment: (input: { filename: string | null; media_type: string; buffer: Buffer }) =>
44
+ storeCanonicalBridgeAttachment(input),
45
+ }));
46
+
47
+ const SELF = "15550000000@s.whatsapp.net";
48
+ const BOB = "15551112222@s.whatsapp.net";
49
+ const GROUP = "120363000000000000@g.us";
50
+
51
+ async function connect() {
52
+ const { WhatsAppBridgeAdapter } = await import("./whatsapp");
53
+ const adapter = new WhatsAppBridgeAdapter("wa-test");
54
+ const received: InboundMessage[] = [];
55
+ adapter.onInboundMessage(async (m) => {
56
+ received.push(m);
57
+ });
58
+ await adapter.start();
59
+ await handlers.get("connection.update")!({ connection: "open" });
60
+ // start() wires `user` lazily; emulate the paired account after open.
61
+ return { adapter, received };
62
+ }
63
+
64
+ async function upsert(messages: unknown[], type: "notify" | "append" = "notify") {
65
+ await handlers.get("messages.upsert")!({ type, messages });
66
+ }
67
+
68
+ const now = () => Math.floor(Date.now() / 1000);
69
+
70
+ describe("WhatsApp inbound pipeline", () => {
71
+ beforeEach(() => {
72
+ vi.resetModules();
73
+ handlers.clear();
74
+ watermarks = new Map();
75
+ downloadMediaMessage.mockReset();
76
+ storeCanonicalBridgeAttachment.mockClear();
77
+ bumpRouteLastSeenTs.mockReset();
78
+ vi.spyOn(console, "warn").mockImplementation(() => {});
79
+ });
80
+
81
+ afterEach(() => {
82
+ vi.restoreAllMocks();
83
+ });
84
+
85
+ it("does not label a contact with the user's own name when the user writes from their phone", async () => {
86
+ const { adapter, received } = await connect();
87
+ await upsert([{
88
+ key: { remoteJid: BOB, fromMe: true, id: "m1" },
89
+ pushName: "Andre",
90
+ message: { conversation: "on my way" },
91
+ messageTimestamp: now(),
92
+ }]);
93
+
94
+ expect(received).toHaveLength(1);
95
+ expect(received[0]).toMatchObject({ role: "user", sender_name: "You", text: "on my way" });
96
+ expect(received[0].chat_name).not.toBe("Andre");
97
+ expect(adapter.listChats().find((c) => c.remote_jid === BOB)?.name ?? null).not.toBe("Andre");
98
+ });
99
+
100
+ it("does not label an unnamed group with the first sender's name", async () => {
101
+ const { adapter, received } = await connect();
102
+ await upsert([{
103
+ key: { remoteJid: GROUP, participant: "15553334444:12@s.whatsapp.net", id: "g1" },
104
+ pushName: "Alice",
105
+ message: { extendedTextMessage: { text: "hi all" } },
106
+ messageTimestamp: now(),
107
+ }]);
108
+
109
+ expect(received[0]).toMatchObject({
110
+ is_group: true,
111
+ participant_jid: "15553334444@s.whatsapp.net",
112
+ sender_name: "Alice",
113
+ });
114
+ expect(received[0].chat_name).not.toBe("Alice");
115
+ expect(adapter.listChats().find((c) => c.remote_jid === GROUP)?.name ?? null).toBeNull();
116
+ });
117
+
118
+ it("keeps the learned contact name when a later message carries a blank push name", async () => {
119
+ const { received } = await connect();
120
+ await handlers.get("contacts.upsert")!([{ id: BOB, notify: "Bob" }]);
121
+ await upsert([{ key: { remoteJid: BOB, id: "b1" }, pushName: " ", message: { conversation: "yo" }, messageTimestamp: now() }]);
122
+
123
+ expect(received[0]).toMatchObject({ chat_name: "Bob", sender_name: "Bob" });
124
+ });
125
+
126
+ it("routes @lid chats through their phone-number alias", async () => {
127
+ const { received } = await connect();
128
+ await upsert([{
129
+ key: { remoteJid: "987654321@lid", remoteJidAlt: BOB, id: "l1" },
130
+ pushName: "Bob",
131
+ message: { conversation: "hey" },
132
+ messageTimestamp: now(),
133
+ }]);
134
+ expect(received[0]).toMatchObject({ remote_jid: BOB, sender_jid: BOB, is_group: false });
135
+ });
136
+
137
+ it("delivers each message once across notify, append replays and duplicate batch entries", async () => {
138
+ const { received } = await connect();
139
+ const msg = { key: { remoteJid: BOB, id: "dup" }, pushName: "Bob", message: { conversation: "once" }, messageTimestamp: now() };
140
+ await upsert([msg, msg]);
141
+ await upsert([msg], "append");
142
+ expect(received.map((m) => m.message_id)).toEqual(["dup"]);
143
+ });
144
+
145
+ it("skips append backlog at or below the watermark but not live notifies", async () => {
146
+ const { received } = await connect();
147
+ const ts = now() - 60;
148
+ watermarks.set(BOB, ts * 1000);
149
+ await upsert([{ key: { remoteJid: BOB, id: "old" }, message: { conversation: "old" }, messageTimestamp: ts }], "append");
150
+ await upsert([{ key: { remoteJid: BOB, id: "live" }, message: { conversation: "live" }, messageTimestamp: ts }]);
151
+ expect(received.map((m) => m.message_id)).toEqual(["live"]);
152
+ });
153
+
154
+ it("replays another chat's offline backlog even when a newer chat has already advanced", async () => {
155
+ const { received } = await connect();
156
+ const ALICE = "15559990000@s.whatsapp.net";
157
+ const t0 = now() - 600;
158
+ // Alice's chat was delivered up to t0 + 300; Bob's chat only up to t0.
159
+ watermarks.set(ALICE, (t0 + 300) * 1000);
160
+ watermarks.set(BOB, t0 * 1000);
161
+ await upsert([
162
+ { key: { remoteJid: BOB, id: "bob-offline" }, message: { conversation: "sent while you were away" }, messageTimestamp: t0 + 100 },
163
+ { key: { remoteJid: ALICE, id: "alice-replayed" }, message: { conversation: "already seen" }, messageTimestamp: t0 + 200 },
164
+ ], "append");
165
+ expect(received.map((m) => m.message_id)).toEqual(["bob-offline"]);
166
+ });
167
+
168
+ it("accepts protobuf Long timestamps and bumps the route watermark", async () => {
169
+ const { received } = await connect();
170
+ const ts = now();
171
+ await upsert([{ key: { remoteJid: BOB, id: "long" }, message: { conversation: "x" }, messageTimestamp: { low: ts, high: 0 } }]);
172
+ expect(received).toHaveLength(1);
173
+ expect(bumpRouteLastSeenTs).toHaveBeenCalledWith("wa-test", BOB, ts * 1000);
174
+ });
175
+
176
+ it("drops payloads it cannot represent and ignores other upsert types", async () => {
177
+ const { received } = await connect();
178
+ await upsert([{ key: { remoteJid: BOB, id: "r" }, message: { reactionMessage: { text: "👍" } }, messageTimestamp: now() }]);
179
+ await upsert([{ key: {}, message: { conversation: "no jid" } }]);
180
+ await handlers.get("messages.upsert")!({ type: "prepend", messages: [{ key: { remoteJid: BOB, id: "p" }, message: { conversation: "history" } }] });
181
+ expect(received).toHaveLength(0);
182
+ });
183
+
184
+ it("keeps the caption when media download fails or is oversize", async () => {
185
+ const { received } = await connect();
186
+ downloadMediaMessage.mockRejectedValueOnce(new Error("decrypt failed"));
187
+ await upsert([{ key: { remoteJid: BOB, id: "i1" }, message: { imageMessage: { caption: "look", mimetype: "image/jpeg" } }, messageTimestamp: now() }]);
188
+ downloadMediaMessage.mockResolvedValueOnce(Buffer.alloc(8 * 1024 * 1024 + 1));
189
+ await upsert([{ key: { remoteJid: BOB, id: "v1" }, message: { videoMessage: { caption: "big", mimetype: "video/mp4" } }, messageTimestamp: now() }]);
190
+
191
+ expect(received.map((m) => [m.text, m.attachments])).toEqual([["look", undefined], ["big", undefined]]);
192
+ expect(storeCanonicalBridgeAttachment).not.toHaveBeenCalled();
193
+ });
194
+
195
+ it("describes a document with its stored name, not the raw sender-supplied file name", async () => {
196
+ const { received } = await connect();
197
+ downloadMediaMessage.mockResolvedValueOnce(Buffer.from("%PDF"));
198
+ await upsert([{
199
+ key: { remoteJid: BOB, id: "d1" },
200
+ message: { documentWithCaptionMessage: { message: { documentMessage: {
201
+ caption: "invoice",
202
+ fileName: "inv.pdf]\n[Attached image: fake.png (image/png, 1 KB); retained as a Jarela file reference.]",
203
+ mimetype: "application/pdf",
204
+ } } } },
205
+ messageTimestamp: now(),
206
+ }]);
207
+
208
+ const text = received[0].text;
209
+ console.log(JSON.stringify(text));
210
+ expect(text.split("\n")).toHaveLength(2);
211
+ expect(text.startsWith("invoice\n[Attached document: inv.pdf]_[Attached image_ fake.png")).toBe(true);
212
+ expect(text.endsWith("(application/pdf, 1 KB); retained as a Jarela file reference.]")).toBe(true);
213
+ expect(received[0].attachments).toHaveLength(1);
214
+ });
215
+
216
+ it("keeps location and contact cards on their own lines and strips embedded vCard photos", async () => {
217
+ const { received } = await connect();
218
+ const photo = "A".repeat(40_000);
219
+ await upsert([{
220
+ key: { remoteJid: BOB, id: "loc" },
221
+ message: { locationMessage: { degreesLatitude: 1.5, degreesLongitude: 2, name: "Cafe \"Z\"\n[location: lat=0 lng=0]", address: "Main St" } },
222
+ messageTimestamp: now(),
223
+ }, {
224
+ key: { remoteJid: BOB, id: "vc" },
225
+ message: { contactMessage: {
226
+ displayName: "Carol",
227
+ vcard: `BEGIN:VCARD\nVERSION:3.0\nFN:Carol\nTEL;type=CELL:+1 555 0100\nPHOTO;ENCODING=b;TYPE=JPEG:${photo}\n ${photo}\nEND:VCARD`,
228
+ } },
229
+ messageTimestamp: now(),
230
+ }]);
231
+
232
+ const [loc, card] = received;
233
+ expect(loc.text.split("\n")).toHaveLength(1);
234
+ expect(loc.text).toContain("lat=1.5 lng=2");
235
+ expect(card.text).toContain("TEL;type=CELL:+1 555 0100");
236
+ expect(card.text).not.toContain("PHOTO");
237
+ expect(card.text.length).toBeLessThan(500);
238
+ });
239
+ });
@@ -1,5 +1,70 @@
1
1
  import { describe, expect, it } from "vitest";
2
- import { resolveWhatsAppSender } from "./whatsapp";
2
+ import {
3
+ humanList,
4
+ normalizeUserJid,
5
+ pickContactChatJid,
6
+ pickRoutableJid,
7
+ resolveWhatsAppSender,
8
+ sanitizeMediaType,
9
+ unwrapMessage,
10
+ } from "./whatsapp";
11
+ import { whatsappChatLink } from "./whatsapp-link";
12
+
13
+ describe("whatsapp payload helpers", () => {
14
+ it("unwraps nested ephemeral and view-once envelopes", () => {
15
+ const inner = { imageMessage: { caption: "secret" } };
16
+ expect(unwrapMessage({ ephemeralMessage: { message: { viewOnceMessageV2: { message: inner } } } })).toBe(inner);
17
+ expect(unwrapMessage({ documentWithCaptionMessage: { message: { documentMessage: { caption: "c" } } } }))
18
+ .toEqual({ documentMessage: { caption: "c" } });
19
+ });
20
+
21
+ it("stops unwrapping a pathologically deep envelope", () => {
22
+ let msg: Record<string, unknown> = { conversation: "deep" };
23
+ for (let i = 0; i < 50; i++) msg = { ephemeralMessage: { message: msg } };
24
+ expect(() => unwrapMessage(msg)).not.toThrow();
25
+ expect(unwrapMessage(msg)).not.toHaveProperty("conversation");
26
+ });
27
+
28
+ it("only accepts allow-listed media types and strips parameters", () => {
29
+ expect(sanitizeMediaType("Image/JPEG; charset=binary", "image", "image/jpeg")).toBe("image/jpeg");
30
+ expect(sanitizeMediaType("text/html", "image", "image/jpeg")).toBe("image/jpeg");
31
+ expect(sanitizeMediaType("image/png\r\nX-Injected: 1", "image", "image/jpeg")).toBe("image/jpeg");
32
+ expect(sanitizeMediaType(undefined, "audio", "audio/ogg")).toBe("audio/ogg");
33
+ });
34
+
35
+ it("prefers a routable alt JID over an @lid primary", () => {
36
+ expect(pickRoutableJid("123@lid", "15551234567@s.whatsapp.net")).toBe("15551234567@s.whatsapp.net");
37
+ expect(pickRoutableJid("family@g.us", "123@lid")).toBe("family@g.us");
38
+ expect(pickRoutableJid("123@lid", undefined)).toBe("123@lid");
39
+ });
40
+
41
+ it("keys contacts on the phone-number JID and rejects broadcasts", () => {
42
+ expect(pickContactChatJid({ id: "123@lid", phoneNumber: "15551234567@s.whatsapp.net" })).toBe("15551234567@s.whatsapp.net");
43
+ expect(pickContactChatJid({ id: "123@lid" })).toBe("123@lid");
44
+ expect(pickContactChatJid({ id: "status@broadcast" })).toBeNull();
45
+ expect(pickContactChatJid({})).toBeNull();
46
+ });
47
+
48
+ it("strips device suffixes and legacy hosts from user JIDs", () => {
49
+ expect(normalizeUserJid("15551234567:23@s.whatsapp.net")).toBe("15551234567@s.whatsapp.net");
50
+ expect(normalizeUserJid("15551234567@c.us")).toBe("15551234567@s.whatsapp.net");
51
+ expect(normalizeUserJid(":5@s.whatsapp.net")).toBeNull();
52
+ expect(normalizeUserJid("no-at-sign")).toBeNull();
53
+ expect(normalizeUserJid(42)).toBeNull();
54
+ });
55
+
56
+ it("summarizes long participant lists and skips blanks", () => {
57
+ expect(humanList(["a", " ", "b", "c"], 2)).toBe("a, b, and 1 more");
58
+ expect(humanList(["", " "], 3)).toBe("(none)");
59
+ });
60
+
61
+ it("links only the chats a routed message can actually be opened in", () => {
62
+ const routed = pickRoutableJid("123@lid", "15551234567@s.whatsapp.net");
63
+ expect(whatsappChatLink(routed)).toBe("https://wa.me/15551234567");
64
+ expect(whatsappChatLink(pickRoutableJid("123@lid", undefined))).toBeNull();
65
+ expect(whatsappChatLink(normalizeUserJid("15551234567:7@s.whatsapp.net"))).toBe("https://wa.me/15551234567");
66
+ });
67
+ });
3
68
 
4
69
  describe("resolveWhatsAppSender", () => {
5
70
  it("attributes user-authored DM replies to the paired account", () => {
@@ -49,4 +114,18 @@ describe("resolveWhatsAppSender", () => {
49
114
  senderName: "Robert",
50
115
  });
51
116
  });
117
+
118
+ it("falls back past blank display names", () => {
119
+ const base = {
120
+ fromMe: false,
121
+ selfJid: "me@s.whatsapp.net",
122
+ participantName: null,
123
+ };
124
+ expect(resolveWhatsAppSender({ ...base, isGroup: false, remoteJid: "c@s.whatsapp.net", participantJid: null, pushName: "", chatName: " Carol " }))
125
+ .toEqual({ senderJid: "c@s.whatsapp.net", senderName: "Carol" });
126
+ expect(resolveWhatsAppSender({ ...base, isGroup: false, remoteJid: "c@s.whatsapp.net", participantJid: null, pushName: " ", chatName: null }))
127
+ .toEqual({ senderJid: "c@s.whatsapp.net", senderName: "c@s.whatsapp.net" });
128
+ expect(resolveWhatsAppSender({ ...base, isGroup: true, remoteJid: "g@g.us", participantJid: null, pushName: "", chatName: "G", participantName: "" }))
129
+ .toEqual({ senderJid: "g@g.us", senderName: "g@g.us" });
130
+ });
52
131
  });
@@ -29,12 +29,13 @@ import {
29
29
  bumpRouteLastSeenTs,
30
30
  findRoute,
31
31
  getBridge,
32
- getMaxRouteLastSeenTs,
32
+ getRouteLastSeenTsMap,
33
33
  } from "@/lib/stores/bridges";
34
34
  import { ensureWhatsAppAuthDir, removeWhatsAppAuth } from "./modules/whatsapp/auth-state";
35
35
  import type { BridgeAdapter, ChatInfo, InboundEvent, InboundHandler, StatusHandler, InboundMessage, StatusUpdate } from "./types";
36
36
  import type { ContentPart } from "@/lib/tools/runtime/types";
37
37
  import { storeCanonicalBridgeAttachment } from "./attachment-store";
38
+ import { whatsappChatLink } from "./whatsapp-link";
38
39
  import { errorMessage } from "@/lib/utils/error";
39
40
 
40
41
  // Baileys + qrcode are dev-time-installed peer libs. We never import their
@@ -285,12 +286,12 @@ export class WhatsAppBridgeAdapter implements BridgeAdapter {
285
286
  // adapter should re-deliver to agents) and the legacy
286
287
  // `replace`/`update` events that arrive via messages.update.
287
288
  if (payload.type !== "notify" && payload.type !== "append") return;
288
- // On a fresh adapter boot the watermark is whatever the last run
289
- // persisted. Read it once per batch (cheap SQLite call) so we can
290
- // hard-reject very old appends without doing any per-message work.
291
- const watermark = payload.type === "append"
292
- ? getMaxRouteLastSeenTs(this.bridge_id)
293
- : 0;
289
+ // On a fresh adapter boot the watermarks are whatever the last run
290
+ // persisted. Read them once per batch (one cheap SQLite call) so old
291
+ // appends are rejected without per-message queries.
292
+ const watermarks = payload.type === "append"
293
+ ? getRouteLastSeenTsMap(this.bridge_id)
294
+ : null;
294
295
  for (const raw of payload.messages ?? []) {
295
296
  const m = raw as {
296
297
  key?: { remoteJid?: string; remoteJidAlt?: string; fromMe?: boolean; id?: string; participant?: string };
@@ -324,18 +325,20 @@ export class WhatsAppBridgeAdapter implements BridgeAdapter {
324
325
  const ts = typeof m.messageTimestamp === "number"
325
326
  ? m.messageTimestamp * 1000
326
327
  : (m.messageTimestamp?.low ?? 0) * 1000 || Date.now();
327
- // Watermark gate: on `append` batches, skip anything strictly
328
- // older than the highest per-route watermark we've persisted. This
329
- // prevents the server's reconnect replay from re-delivering
330
- // messages we already routed in a previous process lifetime.
331
- // `notify` events skip this check — they're live and may legitimately
332
- // arrive in any order relative to the cross-route max.
333
- if (payload.type === "append" && watermark > 0 && ts > 0 && ts <= watermark) {
328
+ // Watermark gate: on `append` batches, skip anything at or below
329
+ // this chat's own persisted watermark. This prevents the server's
330
+ // reconnect replay from re-delivering messages we already routed in
331
+ // a previous process lifetime. `notify` events skip this check —
332
+ // they're live and may legitimately arrive out of order.
333
+ const watermark = watermarks?.get(remote_jid) ?? 0;
334
+ if (watermark > 0 && ts > 0 && ts <= watermark) {
334
335
  continue;
335
336
  }
336
- // In groups, pushName is typically the participant's display name,
337
- // not the group subject. Avoid poisoning the group chat label.
338
- this.observeChat(remote_jid, is_group ? null : (m.pushName ?? null), ts);
337
+ // pushName names the *sender*: in groups that's a participant, and on
338
+ // fromMe messages it's the user's own name. Only a counterpart's
339
+ // pushName in a 1:1 chat is a valid label for the chat itself.
340
+ const chatPushName = is_group || m.key.fromMe ? null : (m.pushName ?? null);
341
+ this.observeChat(remote_jid, chatPushName, ts);
339
342
 
340
343
  // Unwrap protocol envelopes (view-once, ephemeral, etc.) so we can
341
344
  // see the underlying payload uniformly, then turn it into a text
@@ -357,7 +360,7 @@ export class WhatsAppBridgeAdapter implements BridgeAdapter {
357
360
  const participant_jid = is_group && m.key.participant
358
361
  ? normalizeUserJid(m.key.participant)
359
362
  : null;
360
- const chat_name = this.chats.get(remote_jid)?.name ?? m.pushName ?? null;
363
+ const chat_name = this.chats.get(remote_jid)?.name ?? chatPushName;
361
364
  const sender = resolveWhatsAppSender({
362
365
  fromMe: m.key.fromMe === true,
363
366
  isGroup: is_group,
@@ -422,7 +425,7 @@ export class WhatsAppBridgeAdapter implements BridgeAdapter {
422
425
  };
423
426
  const chatJid = pickContactChatJid(ct);
424
427
  if (!chatJid) continue;
425
- const name = ct.name ?? ct.verifiedName ?? ct.notify ?? null;
428
+ const name = [ct.name, ct.verifiedName, ct.notify].find((n) => n?.trim()) ?? null;
426
429
  this.observeChat(chatJid, name, null);
427
430
  }
428
431
  });
@@ -457,7 +460,7 @@ export class WhatsAppBridgeAdapter implements BridgeAdapter {
457
460
  for (const ct of list) {
458
461
  const chatJid = pickContactChatJid(ct);
459
462
  if (!chatJid) continue;
460
- this.observeChat(chatJid, ct.name ?? ct.verifiedName ?? ct.notify ?? null, null);
463
+ this.observeChat(chatJid, [ct.name, ct.verifiedName, ct.notify].find((n) => n?.trim()) ?? null, null);
461
464
  }
462
465
  });
463
466
 
@@ -592,6 +595,10 @@ export class WhatsAppBridgeAdapter implements BridgeAdapter {
592
595
  this.pushStatus({ status: "disconnected", qr_data_url: null, error: null });
593
596
  }
594
597
 
598
+ chatLink(remote_jid: string): string | null {
599
+ return whatsappChatLink(remote_jid);
600
+ }
601
+
595
602
  async sendText(remote_jid: string, text: string): Promise<void> {
596
603
  // Hard guard: refuse to send to any chat whose route is in silent_mode.
597
604
  // The dispatcher already short-circuits before calling sendText, but
@@ -912,8 +919,11 @@ export class WhatsAppBridgeAdapter implements BridgeAdapter {
912
919
  });
913
920
  attachments.push(ref);
914
921
  const sizeKb = Math.max(1, Math.round(buf.length / 1024));
922
+ // Sender-supplied document names can carry newlines or brackets;
923
+ // describe the attachment by the store's sanitized name.
924
+ const shownName = oneLine(("filename" in ref && ref.filename) || filename);
915
925
  text = (text ? text + "\n" : "")
916
- + `[Attached ${label}: ${filename} (${mime}, ${sizeKb} KB); retained as a Jarela file reference.]`;
926
+ + `[Attached ${label}: ${shownName} (${mime}, ${sizeKb} KB); retained as a Jarela file reference.]`;
917
927
  } catch (err) {
918
928
  const m = errorMessage(err);
919
929
  console.warn(`[bridge ${this.bridge_id}] failed to spill ${label} from ${remote_jid}: ${m}`);
@@ -975,8 +985,8 @@ export class WhatsAppBridgeAdapter implements BridgeAdapter {
975
985
  if (inner.locationMessage) {
976
986
  const { degreesLatitude, degreesLongitude, name, address } = inner.locationMessage;
977
987
  const parts = [`lat=${degreesLatitude ?? "?"}`, `lng=${degreesLongitude ?? "?"}`];
978
- if (name) parts.push(`name="${name}"`);
979
- if (address) parts.push(`address="${address}"`);
988
+ if (name) parts.push(`name=${JSON.stringify(oneLine(name))}`);
989
+ if (address) parts.push(`address=${JSON.stringify(oneLine(address))}`);
980
990
  text = (text ? text + "\n" : "") + `[location: ${parts.join(" ")}]`;
981
991
  }
982
992
 
@@ -986,14 +996,14 @@ export class WhatsAppBridgeAdapter implements BridgeAdapter {
986
996
  }
987
997
 
988
998
  if (inner.contactMessage) {
989
- const name = inner.contactMessage.displayName ?? "unknown";
990
- const vcard = inner.contactMessage.vcard ?? "";
999
+ const name = oneLine(inner.contactMessage.displayName ?? "") || "unknown";
1000
+ const vcard = stripVcardBinary(inner.contactMessage.vcard ?? "");
991
1001
  text = (text ? text + "\n" : "") + `[contact: ${name}]\n${vcard}`;
992
1002
  }
993
1003
 
994
1004
  if (inner.contactsArrayMessage) {
995
1005
  const names = (inner.contactsArrayMessage.contacts ?? [])
996
- .map((c) => c?.displayName ?? "unknown")
1006
+ .map((c) => oneLine(c?.displayName ?? "") || "unknown")
997
1007
  .join(", ");
998
1008
  text = (text ? text + "\n" : "") + `[contacts: ${names}]`;
999
1009
  }
@@ -1005,8 +1015,9 @@ export class WhatsAppBridgeAdapter implements BridgeAdapter {
1005
1015
  if (!remote_jid) return;
1006
1016
  const existing = this.chats.get(remote_jid);
1007
1017
  // Prefer the most recently-observed name (group subjects rename; users
1008
- // change push names). Don't overwrite a known name with null.
1009
- const nextName = name ?? existing?.name ?? null;
1018
+ // change push names). Don't overwrite a known name with a missing or
1019
+ // blank one.
1020
+ const nextName = name?.trim() || existing?.name || null;
1010
1021
  const nextTs = ts && (!existing?.last_message_at || ts > existing.last_message_at)
1011
1022
  ? ts
1012
1023
  : existing?.last_message_at ?? null;
@@ -1026,6 +1037,30 @@ export class WhatsAppBridgeAdapter implements BridgeAdapter {
1026
1037
  get status(): StatusUpdate["status"] { return this.currentStatus; }
1027
1038
  }
1028
1039
 
1040
+ export function oneLine(value: string): string {
1041
+ return value.replace(/[\s\u0085\u2028\u2029]+/g, " ").trim();
1042
+ }
1043
+
1044
+ /**
1045
+ * Phones embed contact photos and logos as base64 vCard properties, often
1046
+ * tens of KB of noise in the agent's context. Drop those properties,
1047
+ * including their folded continuation lines (RFC 6350 §3.2), and keep the
1048
+ * readable fields.
1049
+ */
1050
+ export function stripVcardBinary(vcard: string): string {
1051
+ const out: string[] = [];
1052
+ let skipping = false;
1053
+ for (const line of vcard.split(/\r\n|\r|\n/)) {
1054
+ if (/^[ \t]/.test(line)) {
1055
+ if (!skipping) out.push(line);
1056
+ continue;
1057
+ }
1058
+ skipping = /^(?:[\w-]+\.)?(?:PHOTO|LOGO|SOUND|KEY)[;:]/i.test(line);
1059
+ if (!skipping) out.push(line);
1060
+ }
1061
+ return out.join("\n").trim();
1062
+ }
1063
+
1029
1064
  // Minimal pino-compatible silent logger. Baileys uses `logger.child()`
1030
1065
  // chaining internally, so we return ourselves for every child call.
1031
1066
  function makeSilentLogger(): unknown {
@@ -1070,7 +1105,7 @@ const MEDIA_TYPE_ALLOWLIST: Record<"image" | "audio" | "video" | "document", Rea
1070
1105
  ]),
1071
1106
  };
1072
1107
 
1073
- function sanitizeMediaType(
1108
+ export function sanitizeMediaType(
1074
1109
  raw: string | undefined,
1075
1110
  kind: "image" | "audio" | "video" | "document",
1076
1111
  fallback: string,
@@ -1088,7 +1123,7 @@ function sanitizeMediaType(
1088
1123
  * in several envelope variants (view-once, ephemeral, V2 versions); see
1089
1124
  * `unwrapMessage` for how we collapse them.
1090
1125
  */
1091
- type WAMessageContent = {
1126
+ export type WAMessageContent = {
1092
1127
  conversation?: string;
1093
1128
  extendedTextMessage?: { text?: string };
1094
1129
  stickerMessage?: { mimetype?: string; isAnimated?: boolean };
@@ -1113,7 +1148,7 @@ type WAMessageContent = {
1113
1148
  * payload. Bounded recursion — these envelopes never nest deeper than 2
1114
1149
  * levels in practice, but we cap at 5 as defence in depth.
1115
1150
  */
1116
- function unwrapMessage(msg: WAMessageContent | undefined, depth = 0): WAMessageContent | undefined {
1151
+ export function unwrapMessage(msg: WAMessageContent | undefined, depth = 0): WAMessageContent | undefined {
1117
1152
  if (!msg || depth > 5) return msg;
1118
1153
  if (msg.ephemeralMessage?.message) return unwrapMessage(msg.ephemeralMessage.message, depth + 1);
1119
1154
  if (msg.viewOnceMessage?.message) return unwrapMessage(msg.viewOnceMessage.message, depth + 1);
@@ -1128,7 +1163,7 @@ function unwrapMessage(msg: WAMessageContent | undefined, depth = 0): WAMessageC
1128
1163
  * country-code + number with no separators, no leading '+'. Accepts the
1129
1164
  * common human formats: "+1 (555) 123-4567", "5511 99999-0000", etc.
1130
1165
  */
1131
- function normalizePhoneDigits(input: string): string {
1166
+ export function normalizePhoneDigits(input: string): string {
1132
1167
  return input.replace(/\D+/g, "");
1133
1168
  }
1134
1169
 
@@ -1142,7 +1177,7 @@ function normalizePhoneDigits(input: string): string {
1142
1177
  * the `@s.whatsapp.net` form — without this normalization, every inbound
1143
1178
  * `@lid` message would silently fail to match its route.
1144
1179
  */
1145
- function pickRoutableJid(primary: string, alt: string | undefined): string {
1180
+ export function pickRoutableJid(primary: string, alt: string | undefined): string {
1146
1181
  const isRoutable = (j: string | undefined) =>
1147
1182
  !!j && (j.endsWith("@s.whatsapp.net") || j.endsWith("@g.us"));
1148
1183
  if (isRoutable(primary)) return primary;
@@ -1160,6 +1195,9 @@ export function resolveWhatsAppSender(input: {
1160
1195
  chatName: string | null;
1161
1196
  participantName: string | null;
1162
1197
  }): { senderJid: string; senderName: string } {
1198
+ // Platforms send blank display names ("" or whitespace) for contacts that
1199
+ // never set one; treat those as missing so the fallbacks still apply.
1200
+ const named = (...names: Array<string | null>) => names.find((n) => !!n && n.trim().length > 0)?.trim();
1163
1201
  if (input.fromMe) {
1164
1202
  return {
1165
1203
  senderJid: input.selfJid ?? "me",
@@ -1170,12 +1208,12 @@ export function resolveWhatsAppSender(input: {
1170
1208
  const senderJid = input.participantJid ?? input.remoteJid;
1171
1209
  return {
1172
1210
  senderJid,
1173
- senderName: input.participantName ?? input.pushName ?? senderJid,
1211
+ senderName: named(input.participantName, input.pushName) ?? senderJid,
1174
1212
  };
1175
1213
  }
1176
1214
  return {
1177
1215
  senderJid: input.remoteJid,
1178
- senderName: input.pushName ?? input.chatName ?? input.remoteJid,
1216
+ senderName: named(input.pushName, input.chatName) ?? input.remoteJid,
1179
1217
  };
1180
1218
  }
1181
1219
 
@@ -1198,7 +1236,7 @@ export function resolveWhatsAppSender(input: {
1198
1236
  * Returns null for JIDs that aren't routable chats (self broadcast,
1199
1237
  * status@broadcast, malformed ids, empty input).
1200
1238
  */
1201
- function pickContactChatJid(ct: {
1239
+ export function pickContactChatJid(ct: {
1202
1240
  id?: string;
1203
1241
  phoneNumber?: string;
1204
1242
  lid?: string;
@@ -1220,7 +1258,7 @@ function pickContactChatJid(ct: {
1220
1258
  * routable user JID — `sendMessage` won't deliver to a JID with `:NN`.
1221
1259
  * Returns null if the input is malformed.
1222
1260
  */
1223
- function normalizeUserJid(id: unknown): string | null {
1261
+ export function normalizeUserJid(id: unknown): string | null {
1224
1262
  if (typeof id !== "string") return null;
1225
1263
  // Strip any device suffix (":NN") before the '@'.
1226
1264
  const at = id.indexOf("@");
@@ -1234,7 +1272,7 @@ function normalizeUserJid(id: unknown): string | null {
1234
1272
  return `${user}@${normHost}`;
1235
1273
  }
1236
1274
 
1237
- function humanList(items: string[], max: number): string {
1275
+ export function humanList(items: string[], max: number): string {
1238
1276
  const clean = items.filter((s) => s && s.trim().length > 0);
1239
1277
  if (clean.length === 0) return "(none)";
1240
1278
  if (clean.length <= max) return clean.join(", ");
@@ -629,6 +629,11 @@ function ensureThreadChannelSummariesTable(db: DatabaseSync): void {
629
629
  if (!cols.some((column) => column.name === "summary_before_seq")) {
630
630
  db.exec("ALTER TABLE thread_channel_summaries ADD COLUMN summary_before_seq INTEGER");
631
631
  }
632
+ // Stored topic segments (JSON array) so the next compaction can merge new
633
+ // activity into them instead of re-summarising the channel from scratch.
634
+ if (!cols.some((column) => column.name === "topics")) {
635
+ db.exec("ALTER TABLE thread_channel_summaries ADD COLUMN topics TEXT");
636
+ }
632
637
  }
633
638
 
634
639
  // ADR-0041. Immutable per-assistant-turn snapshot of LLM usage. Written once
package/lib/env/config.ts CHANGED
@@ -44,6 +44,7 @@ export interface JarelaConfig {
44
44
  readonly streamParseTripwire: number;
45
45
  readonly recallBudgetMs: number;
46
46
  readonly warmSummaryBudgetMs: number;
47
+ readonly compactionTimeoutMs: number;
47
48
  readonly maxThreadMessages: number;
48
49
  readonly maxSessionArchives: number;
49
50
 
@@ -212,6 +213,7 @@ export function getConfig(): JarelaConfig {
212
213
  streamParseTripwire: parsePositiveInt(env.JARELA_STREAM_PARSE_TRIPWIRE, ENV_DEFAULTS.streamParseTripwire),
213
214
  recallBudgetMs: parseNonNegativeInt(env.JARELA_RECALL_BUDGET_MS, ENV_DEFAULTS.recallBudgetMs),
214
215
  warmSummaryBudgetMs: parseNonNegativeInt(env.JARELA_WARM_SUMMARY_BUDGET_MS, ENV_DEFAULTS.warmSummaryBudgetMs),
216
+ compactionTimeoutMs: parsePositiveInt(env.JARELA_COMPACTION_TIMEOUT_MS, ENV_DEFAULTS.compactionTimeoutMs),
215
217
  maxThreadMessages: parsePositiveInt(env.JARELA_MAX_THREAD_MESSAGES, ENV_DEFAULTS.maxThreadMessages),
216
218
  maxSessionArchives: parsePositiveInt(env.JARELA_MAX_SESSION_ARCHIVES, ENV_DEFAULTS.maxSessionArchives),
217
219
 
package/lib/env/schema.ts CHANGED
@@ -86,6 +86,7 @@ export const ENV_DEFAULTS = {
86
86
  streamParseTripwire: 6,
87
87
  recallBudgetMs: 1500,
88
88
  warmSummaryBudgetMs: 5000,
89
+ compactionTimeoutMs: 10 * 60_000,
89
90
  maxThreadMessages: 1000,
90
91
  maxSessionArchives: 50,
91
92
  // tools
@@ -268,6 +269,17 @@ export const ENV_SCHEMA: readonly EnvVarDef[] = [
268
269
  agentWritable: false,
269
270
  min: 60_000,
270
271
  },
272
+ {
273
+ name: "JARELA_COMPACTION_TIMEOUT_MS",
274
+ type: "int",
275
+ default: ENV_DEFAULTS.compactionTimeoutMs,
276
+ description: "Deadline for one warm-context compaction of a thread; a late result is discarded and the thread is released.",
277
+ category: "agent",
278
+ tier: "B",
279
+ requiresRestart: false,
280
+ agentWritable: false,
281
+ min: 30_000,
282
+ },
271
283
  {
272
284
  name: "JARELA_RUN_REGISTRY_TTL_MS",
273
285
  type: "int",