@circuitwall/jarela 2.2.1 → 2.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (651) hide show
  1. package/.next/standalone/.next/BUILD_ID +1 -1
  2. package/.next/standalone/.next/app-path-routes-manifest.json +6 -5
  3. package/.next/standalone/.next/build-manifest.json +2 -2
  4. package/.next/standalone/.next/prerender-manifest.json +3 -3
  5. package/.next/standalone/.next/routes-manifest.json +8 -0
  6. package/.next/standalone/.next/server/app/_global-error/page.js +68 -68
  7. package/.next/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  8. package/.next/standalone/.next/server/app/_global-error.html +1 -1
  9. package/.next/standalone/.next/server/app/_global-error.rsc +1 -1
  10. package/.next/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  11. package/.next/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  12. package/.next/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  13. package/.next/standalone/.next/server/app/_not-found/page.js +76 -76
  14. package/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  15. package/.next/standalone/.next/server/app/_not-found.html +2 -2
  16. package/.next/standalone/.next/server/app/_not-found.rsc +2 -2
  17. package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +2 -2
  18. package/.next/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +2 -2
  19. package/.next/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  20. package/.next/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  21. package/.next/standalone/.next/server/app/api/v1/access/[identity]/route.js +93 -93
  22. package/.next/standalone/.next/server/app/api/v1/access/route.js +169 -169
  23. package/.next/standalone/.next/server/app/api/v1/agents/[id]/compact/route.js +82 -56
  24. package/.next/standalone/.next/server/app/api/v1/agents/[id]/compact/route.js.nft.json +1 -1
  25. package/.next/standalone/.next/server/app/api/v1/agents/[id]/display-filters/route.js +122 -122
  26. package/.next/standalone/.next/server/app/api/v1/agents/[id]/route.js +100 -100
  27. package/.next/standalone/.next/server/app/api/v1/agents/[id]/thread/route.js +753 -753
  28. package/.next/standalone/.next/server/app/api/v1/agents/route.js +65 -65
  29. package/.next/standalone/.next/server/app/api/v1/allowed-sites/[hostname]/route.js +364 -364
  30. package/.next/standalone/.next/server/app/api/v1/allowed-sites/route.js +802 -802
  31. package/.next/standalone/.next/server/app/api/v1/artifacts/lifecycle/route.js +2 -2
  32. package/.next/standalone/.next/server/app/api/v1/attachments/files/route.js +49 -49
  33. package/.next/standalone/.next/server/app/api/v1/attachments/images/route.js +910 -910
  34. package/.next/standalone/.next/server/app/api/v1/bridges/[id]/chats/route.js +589 -16
  35. package/.next/standalone/.next/server/app/api/v1/bridges/[id]/chats/route.js.nft.json +1 -1
  36. package/.next/standalone/.next/server/app/api/v1/bridges/[id]/ignores/[remote_jid]/route.js +23 -23
  37. package/.next/standalone/.next/server/app/api/v1/bridges/[id]/ignores/route.js +30 -30
  38. package/.next/standalone/.next/server/app/api/v1/bridges/[id]/lookup/route.js +703 -130
  39. package/.next/standalone/.next/server/app/api/v1/bridges/[id]/lookup/route.js.nft.json +1 -1
  40. package/.next/standalone/.next/server/app/api/v1/bridges/[id]/pair/route.js +708 -135
  41. package/.next/standalone/.next/server/app/api/v1/bridges/[id]/pair/route.js.nft.json +1 -1
  42. package/.next/standalone/.next/server/app/api/v1/bridges/[id]/route.js +802 -229
  43. package/.next/standalone/.next/server/app/api/v1/bridges/[id]/route.js.nft.json +1 -1
  44. package/.next/standalone/.next/server/app/api/v1/bridges/[id]/routes/[route_id]/route.js +739 -739
  45. package/.next/standalone/.next/server/app/api/v1/bridges/[id]/routes/route.js +1035 -1035
  46. package/.next/standalone/.next/server/app/api/v1/bridges/[id]/status/route.js +679 -106
  47. package/.next/standalone/.next/server/app/api/v1/bridges/[id]/status/route.js.nft.json +1 -1
  48. package/.next/standalone/.next/server/app/api/v1/bridges/kinds/route.js +804 -804
  49. package/.next/standalone/.next/server/app/api/v1/bridges/route.js +700 -700
  50. package/.next/standalone/.next/server/app/api/v1/builtin-tools/route.js +9 -9
  51. package/.next/standalone/.next/server/app/api/v1/builtin-tools/route.js.nft.json +1 -1
  52. package/.next/standalone/.next/server/app/api/v1/config/route.js +85 -85
  53. package/.next/standalone/.next/server/app/api/v1/credentials/[id]/route.js +709 -709
  54. package/.next/standalone/.next/server/app/api/v1/credentials/[id]/route.js.nft.json +1 -1
  55. package/.next/standalone/.next/server/app/api/v1/credentials/route.js +2 -2
  56. package/.next/standalone/.next/server/app/api/v1/credentials/route.js.nft.json +1 -1
  57. package/.next/standalone/.next/server/app/api/v1/dashboard/currency/route.js +10 -10
  58. package/.next/standalone/.next/server/app/api/v1/dashboard/metrics/route.js +784 -784
  59. package/.next/standalone/.next/server/app/api/v1/dashboard/pricing/route.js +23 -23
  60. package/.next/standalone/.next/server/app/api/v1/dashboard/pricing-task/route.js +86 -86
  61. package/.next/standalone/.next/server/app/api/v1/dashboard/pricing-task/route.js.nft.json +1 -1
  62. package/.next/standalone/.next/server/app/api/v1/delegations/codex/[job_id]/route.js +57 -57
  63. package/.next/standalone/.next/server/app/api/v1/delegations/codex/[job_id]/route.js.nft.json +1 -1
  64. package/.next/standalone/.next/server/app/api/v1/documents/search/route.js +523 -523
  65. package/.next/standalone/.next/server/app/api/v1/documents/settings/route.js +44 -44
  66. package/.next/standalone/.next/server/app/api/v1/documents/sources/[id]/reindex/route.js +65 -65
  67. package/.next/standalone/.next/server/app/api/v1/documents/sources/[id]/reindex/route.js.nft.json +1 -1
  68. package/.next/standalone/.next/server/app/api/v1/documents/sources/[id]/route.js +122 -122
  69. package/.next/standalone/.next/server/app/api/v1/documents/sources/[id]/route.js.nft.json +1 -1
  70. package/.next/standalone/.next/server/app/api/v1/documents/sources/route.js +37 -37
  71. package/.next/standalone/.next/server/app/api/v1/documents/sources/route.js.nft.json +1 -1
  72. package/.next/standalone/.next/server/app/api/v1/env/route.js +9 -9
  73. package/.next/standalone/.next/server/app/api/v1/env-sync/allowlist/route.js +368 -368
  74. package/.next/standalone/.next/server/app/api/v1/env-sync/route.js +44 -44
  75. package/.next/standalone/.next/server/app/api/v1/events/route.js +751 -178
  76. package/.next/standalone/.next/server/app/api/v1/events/route.js.nft.json +1 -1
  77. package/.next/standalone/.next/server/app/api/v1/events/test/route.js +77 -77
  78. package/.next/standalone/.next/server/app/api/v1/extension/agents/route.js +763 -763
  79. package/.next/standalone/.next/server/app/api/v1/extension/agents/route.js.nft.json +1 -1
  80. package/.next/standalone/.next/server/app/api/v1/extension/browser/activate/route.js +44 -44
  81. package/.next/standalone/.next/server/app/api/v1/extension/browser/foreground/route.js +9 -9
  82. package/.next/standalone/.next/server/app/api/v1/extension/browser/history/route.js +65 -65
  83. package/.next/standalone/.next/server/app/api/v1/extension/browser/poll/route.js +34 -34
  84. package/.next/standalone/.next/server/app/api/v1/extension/browser/progress/route.js +204 -204
  85. package/.next/standalone/.next/server/app/api/v1/extension/browser/result/route.js +133 -133
  86. package/.next/standalone/.next/server/app/api/v1/extension/browser/retry/route.js +106 -106
  87. package/.next/standalone/.next/server/app/api/v1/extension/browser/status/route.js +114 -114
  88. package/.next/standalone/.next/server/app/api/v1/extension/browser/tabs/route.js +134 -134
  89. package/.next/standalone/.next/server/app/api/v1/extension/fill/route.js +690 -690
  90. package/.next/standalone/.next/server/app/api/v1/extension/fill/route.js.nft.json +1 -1
  91. package/.next/standalone/.next/server/app/api/v1/extension/refine/route.js +93 -93
  92. package/.next/standalone/.next/server/app/api/v1/extension/refine/route.js.nft.json +1 -1
  93. package/.next/standalone/.next/server/app/api/v1/extension/turn/route.js +9 -9
  94. package/.next/standalone/.next/server/app/api/v1/extension/turn/route.js.nft.json +1 -1
  95. package/.next/standalone/.next/server/app/api/v1/extensions/route.js +185 -185
  96. package/.next/standalone/.next/server/app/api/v1/extensions/route.js.nft.json +1 -1
  97. package/.next/standalone/.next/server/app/api/v1/extensions/tools/[name]/config/route.js +171 -171
  98. package/.next/standalone/.next/server/app/api/v1/extensions/tools/[name]/config/route.js.nft.json +1 -1
  99. package/.next/standalone/.next/server/app/api/v1/extensions/tools/[name]/route.js +396 -396
  100. package/.next/standalone/.next/server/app/api/v1/extensions/tools/[name]/route.js.nft.json +1 -1
  101. package/.next/standalone/.next/server/app/api/v1/extensions/tools/[name]/secrets/route.js +212 -212
  102. package/.next/standalone/.next/server/app/api/v1/extensions/tools/[name]/secrets/route.js.nft.json +1 -1
  103. package/.next/standalone/.next/server/app/api/v1/files/[name]/route.js +235 -235
  104. package/.next/standalone/.next/server/app/api/v1/fs/browse/route.js +26 -26
  105. package/.next/standalone/.next/server/app/api/v1/harnesses/[id]/route.js +221 -221
  106. package/.next/standalone/.next/server/app/api/v1/harnesses/default/route.js +58 -58
  107. package/.next/standalone/.next/server/app/api/v1/harnesses/route.js +72 -72
  108. package/.next/standalone/.next/server/app/api/v1/health/probes/route.js +9 -9
  109. package/.next/standalone/.next/server/app/api/v1/health/probes/route.js.nft.json +1 -1
  110. package/.next/standalone/.next/server/app/api/v1/health/route.js +772 -772
  111. package/.next/standalone/.next/server/app/api/v1/integrations/[name]/route.js +133 -133
  112. package/.next/standalone/.next/server/app/api/v1/integrations/[name]/test/route.js +9 -9
  113. package/.next/standalone/.next/server/app/api/v1/integrations/[name]/test/route.js.nft.json +1 -1
  114. package/.next/standalone/.next/server/app/api/v1/integrations/gmail/oauth/callback/route.js +363 -363
  115. package/.next/standalone/.next/server/app/api/v1/integrations/gmail/oauth/start/route.js +233 -233
  116. package/.next/standalone/.next/server/app/api/v1/integrations/gmail/oauth/status/route.js +682 -682
  117. package/.next/standalone/.next/server/app/api/v1/integrations/outlook/oauth/callback/route.js +879 -879
  118. package/.next/standalone/.next/server/app/api/v1/integrations/outlook/oauth/start/route.js +108 -108
  119. package/.next/standalone/.next/server/app/api/v1/integrations/outlook/oauth/status/route.js +952 -952
  120. package/.next/standalone/.next/server/app/api/v1/integrations/route.js +216 -216
  121. package/.next/standalone/.next/server/app/api/v1/lifecycle/adoption/route.js +864 -847
  122. package/.next/standalone/.next/server/app/api/v1/lifecycle/adoption/route.js.nft.json +1 -1
  123. package/.next/standalone/.next/server/app/api/v1/local-file/route.js +26 -26
  124. package/.next/standalone/.next/server/app/api/v1/logs/route.js +70 -70
  125. package/.next/standalone/.next/server/app/api/v1/maps/embed/route.js +72 -72
  126. package/.next/standalone/.next/server/app/api/v1/mcp-servers/[name]/route.js +979 -979
  127. package/.next/standalone/.next/server/app/api/v1/mcp-servers/registry/route.js +196 -196
  128. package/.next/standalone/.next/server/app/api/v1/mcp-servers/route.js +2 -2
  129. package/.next/standalone/.next/server/app/api/v1/memory/[namespace]/[key]/route.js +381 -381
  130. package/.next/standalone/.next/server/app/api/v1/memory/policy/route.js +79 -79
  131. package/.next/standalone/.next/server/app/api/v1/memory/route.js +51 -51
  132. package/.next/standalone/.next/server/app/api/v1/memory/search/route.js +131 -131
  133. package/.next/standalone/.next/server/app/api/v1/models/[name]/compact-threads/route.js +374 -369
  134. package/.next/standalone/.next/server/app/api/v1/models/[name]/compact-threads/route.js.nft.json +1 -1
  135. package/.next/standalone/.next/server/app/api/v1/models/[name]/route.js +143 -143
  136. package/.next/standalone/.next/server/app/api/v1/models/route.js +543 -543
  137. package/.next/standalone/.next/server/app/api/v1/packages/catalog/route.js +445 -445
  138. package/.next/standalone/.next/server/app/api/v1/packages/defaults/[id]/route.js +120 -120
  139. package/.next/standalone/.next/server/app/api/v1/packages/defaults/[id]/route.js.nft.json +1 -1
  140. package/.next/standalone/.next/server/app/api/v1/packages/install/[id]/route.js +234 -234
  141. package/.next/standalone/.next/server/app/api/v1/packages/install/[id]/route.js.nft.json +1 -1
  142. package/.next/standalone/.next/server/app/api/v1/packages/install/route.js +407 -407
  143. package/.next/standalone/.next/server/app/api/v1/packages/install/route.js.nft.json +1 -1
  144. package/.next/standalone/.next/server/app/api/v1/packages/manifests/[name]/enabled/route.js +37 -37
  145. package/.next/standalone/.next/server/app/api/v1/packages/manifests/[name]/enabled/route.js.nft.json +1 -1
  146. package/.next/standalone/.next/server/app/api/v1/packages/manifests/[name]/route.js +107 -107
  147. package/.next/standalone/.next/server/app/api/v1/packages/manifests/[name]/route.js.nft.json +1 -1
  148. package/.next/standalone/.next/server/app/api/v1/packages/manifests/route.js +228 -228
  149. package/.next/standalone/.next/server/app/api/v1/packages/manifests/route.js.nft.json +1 -1
  150. package/.next/standalone/.next/server/app/api/v1/packages/reload/route.js +9 -9
  151. package/.next/standalone/.next/server/app/api/v1/packages/reload/route.js.nft.json +1 -1
  152. package/.next/standalone/.next/server/app/api/v1/packages/route.js +148 -148
  153. package/.next/standalone/.next/server/app/api/v1/packages/route.js.nft.json +1 -1
  154. package/.next/standalone/.next/server/app/api/v1/page-capture/route.js +787 -787
  155. package/.next/standalone/.next/server/app/api/v1/page-capture/route.js.nft.json +1 -1
  156. package/.next/standalone/.next/server/app/api/v1/pending-actions/[id]/approve/route.js +507 -507
  157. package/.next/standalone/.next/server/app/api/v1/pending-actions/[id]/approve/route.js.nft.json +1 -1
  158. package/.next/standalone/.next/server/app/api/v1/pending-actions/[id]/deny/route.js +181 -181
  159. package/.next/standalone/.next/server/app/api/v1/pending-actions/[id]/deny/route.js.nft.json +1 -1
  160. package/.next/standalone/.next/server/app/api/v1/pending-actions/route.js +258 -258
  161. package/.next/standalone/.next/server/app/api/v1/pending-actions/route.js.nft.json +1 -1
  162. package/.next/standalone/.next/server/app/api/v1/profile/location/route.js +30 -30
  163. package/.next/standalone/.next/server/app/api/v1/profile/route.js +164 -164
  164. package/.next/standalone/.next/server/app/api/v1/providers/[provider]/models/route.js +44 -44
  165. package/.next/standalone/.next/server/app/api/v1/providers/[provider]/probe/route.js +9 -9
  166. package/.next/standalone/.next/server/app/api/v1/providers/github-copilot/auth/route.js +164 -164
  167. package/.next/standalone/.next/server/app/api/v1/providers/route.js +94 -94
  168. package/.next/standalone/.next/server/app/api/v1/proxy-config/route.js +450 -450
  169. package/.next/standalone/.next/server/app/api/v1/redaction/init/route.js +37 -37
  170. package/.next/standalone/.next/server/app/api/v1/redaction/route.js +58 -58
  171. package/.next/standalone/.next/server/app/api/v1/scheduled-tasks/[id]/route.js +600 -600
  172. package/.next/standalone/.next/server/app/api/v1/scheduled-tasks/[id]/run/route.js +44 -44
  173. package/.next/standalone/.next/server/app/api/v1/scheduled-tasks/[id]/run/route.js.nft.json +1 -1
  174. package/.next/standalone/.next/server/app/api/v1/scheduled-tasks/route.js +732 -732
  175. package/.next/standalone/.next/server/app/api/v1/security/idle-timeout/route.js +359 -359
  176. package/.next/standalone/.next/server/app/api/v1/security/pin/route.js +197 -197
  177. package/.next/standalone/.next/server/app/api/v1/security/state/route.js +51 -51
  178. package/.next/standalone/.next/server/app/api/v1/security/unlock/route.js +176 -176
  179. package/.next/standalone/.next/server/app/api/v1/security/verify-pin/route.js +190 -190
  180. package/.next/standalone/.next/server/app/api/v1/setup/test-key/route.js +26 -26
  181. package/.next/standalone/.next/server/app/api/v1/skills/[id]/route.js +770 -770
  182. package/.next/standalone/.next/server/app/api/v1/skills/repos/[id]/route.js +115 -115
  183. package/.next/standalone/.next/server/app/api/v1/skills/repos/route.js +327 -327
  184. package/.next/standalone/.next/server/app/api/v1/skills/route.js +870 -870
  185. package/.next/standalone/.next/server/app/api/v1/system/abort/route.js +838 -808
  186. package/.next/standalone/.next/server/app/api/v1/system/restart/route.js +177 -177
  187. package/.next/standalone/.next/server/app/api/v1/system/restart/route.js.nft.json +1 -1
  188. package/.next/standalone/.next/server/app/api/v1/tailscale/route.js +164 -164
  189. package/.next/standalone/.next/server/app/api/v1/tasks/[agent_id]/route.js +115 -115
  190. package/.next/standalone/.next/server/app/api/v1/tasks/route.js +23 -23
  191. package/.next/standalone/.next/server/app/api/v1/threads/[thread_id]/activity/route.js +1429 -0
  192. package/.next/standalone/.next/server/app/api/v1/threads/[thread_id]/activity/route.js.nft.json +1 -0
  193. package/.next/standalone/.next/server/app/api/v1/threads/[thread_id]/activity/route_client-reference-manifest.js +1 -0
  194. package/.next/standalone/.next/server/app/api/v1/threads/[thread_id]/context-pin/route.js +635 -634
  195. package/.next/standalone/.next/server/app/api/v1/threads/[thread_id]/context-pin/route.js.nft.json +1 -1
  196. package/.next/standalone/.next/server/app/api/v1/threads/[thread_id]/route.js +53 -439
  197. package/.next/standalone/.next/server/app/api/v1/threads/[thread_id]/route.js.nft.json +1 -1
  198. package/.next/standalone/.next/server/app/api/v1/threads/[thread_id]/run/route.js +172 -172
  199. package/.next/standalone/.next/server/app/api/v1/threads/[thread_id]/run/route.js.nft.json +1 -1
  200. package/.next/standalone/.next/server/app/api/v1/threads/route.js +908 -908
  201. package/.next/standalone/.next/server/app/api/v1/tools/route.js +2 -2
  202. package/.next/standalone/.next/server/app/api/v1/tools/route.js.nft.json +1 -1
  203. package/.next/standalone/.next/server/app/api/v1/update/apply/route.js +17 -17
  204. package/.next/standalone/.next/server/app/api/v1/update/apply/route.js.nft.json +1 -1
  205. package/.next/standalone/.next/server/app/api/v1/update/route.js +570 -570
  206. package/.next/standalone/.next/server/app/api/v1/voice/transcribe/route.js +224 -224
  207. package/.next/standalone/.next/server/app/api/v1/voice/tts/route.js +975 -975
  208. package/.next/standalone/.next/server/app/api/v1/watchers/[id]/route.js +23 -23
  209. package/.next/standalone/.next/server/app/api/v1/watchers/[id]/run/route.js +72 -72
  210. package/.next/standalone/.next/server/app/api/v1/watchers/[id]/run/route.js.nft.json +1 -1
  211. package/.next/standalone/.next/server/app/api/v1/watchers/reaction-scripts/route.js +128 -128
  212. package/.next/standalone/.next/server/app/api/v1/watchers/route.js +164 -164
  213. package/.next/standalone/.next/server/app/api/v1/watchers/route.js.nft.json +1 -1
  214. package/.next/standalone/.next/server/app/icon.svg/route.js +62 -62
  215. package/.next/standalone/.next/server/app/manifest.webmanifest/route.js +436 -436
  216. package/.next/standalone/.next/server/app/page.js +1243 -854
  217. package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  218. package/.next/standalone/.next/server/app/setup/page.js +91 -91
  219. package/.next/standalone/.next/server/app/setup/page_client-reference-manifest.js +1 -1
  220. package/.next/standalone/.next/server/app-paths-manifest.json +6 -5
  221. package/.next/standalone/.next/server/chunks/{424.js → 1388.js} +335 -986
  222. package/.next/standalone/.next/server/chunks/1433.js +1 -1
  223. package/.next/standalone/.next/server/chunks/1638.js +1 -2
  224. package/.next/standalone/.next/server/chunks/1738.js +1 -1
  225. package/.next/standalone/.next/server/chunks/210.js +6 -6
  226. package/.next/standalone/.next/server/chunks/2151.js +31 -1
  227. package/.next/standalone/.next/server/chunks/2207.js +1 -0
  228. package/.next/standalone/.next/server/chunks/2471.js +28 -28
  229. package/.next/standalone/.next/server/chunks/2504.js +1 -1
  230. package/.next/standalone/.next/server/chunks/2695.js +17 -17
  231. package/.next/standalone/.next/server/chunks/3042.js +14 -8
  232. package/.next/standalone/.next/server/chunks/3399.js +1 -1
  233. package/.next/standalone/.next/server/chunks/3566.js +1 -1
  234. package/.next/standalone/.next/server/chunks/4189.js +946 -0
  235. package/.next/standalone/.next/server/chunks/{9590.js → 423.js} +8 -3
  236. package/.next/standalone/.next/server/chunks/4433.js +146 -146
  237. package/.next/standalone/.next/server/chunks/4508.js +1 -1
  238. package/.next/standalone/.next/server/chunks/4588.js +1 -0
  239. package/.next/standalone/.next/server/chunks/46.js +5 -0
  240. package/.next/standalone/.next/server/chunks/466.js +12 -0
  241. package/.next/standalone/.next/server/chunks/4868.js +206 -206
  242. package/.next/standalone/.next/server/chunks/4992.js +13 -0
  243. package/.next/standalone/.next/server/chunks/5120.js +963 -0
  244. package/.next/standalone/.next/server/chunks/5701.js +1 -1
  245. package/.next/standalone/.next/server/chunks/5900.js +1 -1
  246. package/.next/standalone/.next/server/chunks/6210.js +1 -0
  247. package/.next/standalone/.next/server/chunks/6213.js +1 -1
  248. package/.next/standalone/.next/server/chunks/6649.js +2 -2
  249. package/.next/standalone/.next/server/chunks/6703.js +3 -3
  250. package/.next/standalone/.next/server/chunks/7445.js +1 -0
  251. package/.next/standalone/.next/server/chunks/8067.js +12 -0
  252. package/.next/standalone/.next/server/chunks/8461.js +14 -9
  253. package/.next/standalone/.next/server/chunks/8558.js +1 -1
  254. package/.next/standalone/.next/server/chunks/8724.js +1 -1
  255. package/.next/standalone/.next/server/chunks/8849.js +91 -91
  256. package/.next/standalone/.next/server/chunks/9032.js +6 -5
  257. package/.next/standalone/.next/server/chunks/{2563.js → 9164.js} +33173 -31461
  258. package/.next/standalone/.next/server/chunks/9237.js +396 -396
  259. package/.next/standalone/.next/server/chunks/{9640.js → 9304.js} +1628 -570
  260. package/.next/standalone/.next/server/chunks/9406.js +1 -1
  261. package/.next/standalone/.next/server/chunks/9824.js +98 -98
  262. package/.next/standalone/.next/server/chunks/9826.js +1 -0
  263. package/.next/standalone/.next/server/middleware-build-manifest.js +2 -2
  264. package/.next/standalone/.next/server/middleware.js +415 -397
  265. package/.next/standalone/.next/server/pages/404.html +2 -2
  266. package/.next/standalone/.next/server/pages/500.html +1 -1
  267. package/.next/standalone/.next/server/preview-props.json +3 -3
  268. package/.next/standalone/.next/server/server-reference-manifest.json +1 -1
  269. package/.next/standalone/.next/static/chunks/{1395-a340fb0a345382a4.js → 1395-e4a99912b8f83044.js} +13 -1
  270. package/.next/standalone/.next/static/chunks/app/_global-error/{page-36cb8b428b38b26a.js → page-6fc5f8e744c81802.js} +1 -1
  271. package/.next/standalone/.next/static/chunks/app/api/v1/access/[identity]/{route-36cb8b428b38b26a.js → route-6fc5f8e744c81802.js} +1 -1
  272. package/.next/standalone/.next/static/chunks/app/api/v1/access/{route-36cb8b428b38b26a.js → route-6fc5f8e744c81802.js} +1 -1
  273. package/.next/standalone/.next/static/chunks/app/api/v1/agents/[id]/compact/{route-36cb8b428b38b26a.js → route-6fc5f8e744c81802.js} +1 -1
  274. package/.next/standalone/.next/static/chunks/app/api/v1/agents/[id]/display-filters/route-6fc5f8e744c81802.js +17 -0
  275. package/.next/standalone/.next/static/chunks/app/api/v1/agents/[id]/route-6fc5f8e744c81802.js +17 -0
  276. package/.next/standalone/.next/static/chunks/app/api/v1/agents/[id]/thread/route-6fc5f8e744c81802.js +17 -0
  277. package/.next/standalone/.next/static/chunks/app/api/v1/agents/route-6fc5f8e744c81802.js +17 -0
  278. package/.next/standalone/.next/static/chunks/app/api/v1/allowed-sites/[hostname]/route-6fc5f8e744c81802.js +17 -0
  279. package/.next/standalone/.next/static/chunks/app/api/v1/allowed-sites/route-6fc5f8e744c81802.js +17 -0
  280. package/.next/standalone/.next/static/chunks/app/api/v1/artifacts/lifecycle/route-6fc5f8e744c81802.js +17 -0
  281. package/.next/standalone/.next/static/chunks/app/api/v1/attachments/files/route-6fc5f8e744c81802.js +17 -0
  282. package/.next/standalone/.next/static/chunks/app/api/v1/attachments/images/route-6fc5f8e744c81802.js +17 -0
  283. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/[id]/chats/route-6fc5f8e744c81802.js +17 -0
  284. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/[id]/ignores/[remote_jid]/route-6fc5f8e744c81802.js +17 -0
  285. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/[id]/ignores/route-6fc5f8e744c81802.js +17 -0
  286. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/[id]/lookup/route-6fc5f8e744c81802.js +17 -0
  287. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/[id]/pair/route-6fc5f8e744c81802.js +17 -0
  288. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/[id]/route-6fc5f8e744c81802.js +17 -0
  289. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/[id]/routes/[route_id]/route-6fc5f8e744c81802.js +17 -0
  290. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/[id]/routes/route-6fc5f8e744c81802.js +17 -0
  291. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/[id]/status/route-6fc5f8e744c81802.js +17 -0
  292. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/kinds/route-6fc5f8e744c81802.js +17 -0
  293. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/route-6fc5f8e744c81802.js +17 -0
  294. package/.next/standalone/.next/static/chunks/app/api/v1/builtin-tools/route-6fc5f8e744c81802.js +17 -0
  295. package/.next/standalone/.next/static/chunks/app/api/v1/config/route-6fc5f8e744c81802.js +17 -0
  296. package/.next/standalone/.next/static/chunks/app/api/v1/credentials/[id]/route-6fc5f8e744c81802.js +17 -0
  297. package/.next/standalone/.next/static/chunks/app/api/v1/credentials/route-6fc5f8e744c81802.js +17 -0
  298. package/.next/standalone/.next/static/chunks/app/api/v1/dashboard/currency/route-6fc5f8e744c81802.js +17 -0
  299. package/.next/standalone/.next/static/chunks/app/api/v1/dashboard/metrics/route-6fc5f8e744c81802.js +17 -0
  300. package/.next/standalone/.next/static/chunks/app/api/v1/dashboard/pricing/route-6fc5f8e744c81802.js +17 -0
  301. package/.next/standalone/.next/static/chunks/app/api/v1/dashboard/pricing-task/route-6fc5f8e744c81802.js +17 -0
  302. package/.next/standalone/.next/static/chunks/app/api/v1/delegations/codex/[job_id]/route-6fc5f8e744c81802.js +17 -0
  303. package/.next/standalone/.next/static/chunks/app/api/v1/documents/search/route-6fc5f8e744c81802.js +17 -0
  304. package/.next/standalone/.next/static/chunks/app/api/v1/documents/settings/route-6fc5f8e744c81802.js +17 -0
  305. package/.next/standalone/.next/static/chunks/app/api/v1/documents/sources/[id]/reindex/route-6fc5f8e744c81802.js +17 -0
  306. package/.next/standalone/.next/static/chunks/app/api/v1/documents/sources/[id]/route-6fc5f8e744c81802.js +17 -0
  307. package/.next/standalone/.next/static/chunks/app/api/v1/documents/sources/route-6fc5f8e744c81802.js +17 -0
  308. package/.next/standalone/.next/static/chunks/app/api/v1/env/route-6fc5f8e744c81802.js +17 -0
  309. package/.next/standalone/.next/static/chunks/app/api/v1/env-sync/allowlist/route-6fc5f8e744c81802.js +17 -0
  310. package/.next/standalone/.next/static/chunks/app/api/v1/env-sync/route-6fc5f8e744c81802.js +17 -0
  311. package/.next/standalone/.next/static/chunks/app/api/v1/events/route-6fc5f8e744c81802.js +17 -0
  312. package/.next/standalone/.next/static/chunks/app/api/v1/events/test/route-6fc5f8e744c81802.js +17 -0
  313. package/.next/standalone/.next/static/chunks/app/api/v1/extension/agents/route-6fc5f8e744c81802.js +17 -0
  314. package/.next/standalone/.next/static/chunks/app/api/v1/extension/browser/activate/route-6fc5f8e744c81802.js +17 -0
  315. package/.next/standalone/.next/static/chunks/app/api/v1/extension/browser/foreground/route-6fc5f8e744c81802.js +17 -0
  316. package/.next/standalone/.next/static/chunks/app/api/v1/extension/browser/history/route-6fc5f8e744c81802.js +17 -0
  317. package/.next/standalone/.next/static/chunks/app/api/v1/extension/browser/poll/route-6fc5f8e744c81802.js +17 -0
  318. package/.next/standalone/.next/static/chunks/app/api/v1/extension/browser/progress/route-6fc5f8e744c81802.js +17 -0
  319. package/.next/standalone/.next/static/chunks/app/api/v1/extension/browser/result/route-6fc5f8e744c81802.js +17 -0
  320. package/.next/standalone/.next/static/chunks/app/api/v1/extension/browser/retry/route-6fc5f8e744c81802.js +17 -0
  321. package/.next/standalone/.next/static/chunks/app/api/v1/extension/browser/status/route-6fc5f8e744c81802.js +17 -0
  322. package/.next/standalone/.next/static/chunks/app/api/v1/extension/browser/tabs/route-6fc5f8e744c81802.js +17 -0
  323. package/.next/standalone/.next/static/chunks/app/api/v1/extension/fill/route-6fc5f8e744c81802.js +17 -0
  324. package/.next/standalone/.next/static/chunks/app/api/v1/extension/refine/route-6fc5f8e744c81802.js +17 -0
  325. package/.next/standalone/.next/static/chunks/app/api/v1/extension/turn/route-6fc5f8e744c81802.js +17 -0
  326. package/.next/standalone/.next/static/chunks/app/api/v1/extensions/route-6fc5f8e744c81802.js +17 -0
  327. package/.next/standalone/.next/static/chunks/app/api/v1/extensions/tools/[name]/config/route-6fc5f8e744c81802.js +17 -0
  328. package/.next/standalone/.next/static/chunks/app/api/v1/extensions/tools/[name]/route-6fc5f8e744c81802.js +17 -0
  329. package/.next/standalone/.next/static/chunks/app/api/v1/extensions/tools/[name]/secrets/route-6fc5f8e744c81802.js +17 -0
  330. package/.next/standalone/.next/static/chunks/app/api/v1/files/[name]/route-6fc5f8e744c81802.js +17 -0
  331. package/.next/standalone/.next/static/chunks/app/api/v1/fs/browse/route-6fc5f8e744c81802.js +17 -0
  332. package/.next/standalone/.next/static/chunks/app/api/v1/harnesses/[id]/route-6fc5f8e744c81802.js +17 -0
  333. package/.next/standalone/.next/static/chunks/app/api/v1/harnesses/default/route-6fc5f8e744c81802.js +17 -0
  334. package/.next/standalone/.next/static/chunks/app/api/v1/harnesses/route-6fc5f8e744c81802.js +17 -0
  335. package/.next/standalone/.next/static/chunks/app/api/v1/health/probes/route-6fc5f8e744c81802.js +17 -0
  336. package/.next/standalone/.next/static/chunks/app/api/v1/health/route-6fc5f8e744c81802.js +17 -0
  337. package/.next/standalone/.next/static/chunks/app/api/v1/integrations/[name]/route-6fc5f8e744c81802.js +17 -0
  338. package/.next/standalone/.next/static/chunks/app/api/v1/integrations/[name]/test/route-6fc5f8e744c81802.js +17 -0
  339. package/.next/standalone/.next/static/chunks/app/api/v1/integrations/gmail/oauth/callback/route-6fc5f8e744c81802.js +17 -0
  340. package/.next/standalone/.next/static/chunks/app/api/v1/integrations/gmail/oauth/start/route-6fc5f8e744c81802.js +17 -0
  341. package/.next/standalone/.next/static/chunks/app/api/v1/integrations/gmail/oauth/status/route-6fc5f8e744c81802.js +17 -0
  342. package/.next/standalone/.next/static/chunks/app/api/v1/integrations/outlook/oauth/callback/route-6fc5f8e744c81802.js +17 -0
  343. package/.next/standalone/.next/static/chunks/app/api/v1/integrations/outlook/oauth/start/route-6fc5f8e744c81802.js +17 -0
  344. package/.next/standalone/.next/static/chunks/app/api/v1/integrations/outlook/oauth/status/route-6fc5f8e744c81802.js +17 -0
  345. package/.next/standalone/.next/static/chunks/app/api/v1/integrations/route-6fc5f8e744c81802.js +17 -0
  346. package/.next/standalone/.next/static/chunks/app/api/v1/lifecycle/adoption/route-6fc5f8e744c81802.js +17 -0
  347. package/.next/standalone/.next/static/chunks/app/api/v1/local-file/route-6fc5f8e744c81802.js +17 -0
  348. package/.next/standalone/.next/static/chunks/app/api/v1/logs/route-6fc5f8e744c81802.js +17 -0
  349. package/.next/standalone/.next/static/chunks/app/api/v1/maps/embed/route-6fc5f8e744c81802.js +17 -0
  350. package/.next/standalone/.next/static/chunks/app/api/v1/mcp-servers/[name]/route-6fc5f8e744c81802.js +17 -0
  351. package/.next/standalone/.next/static/chunks/app/api/v1/mcp-servers/registry/route-6fc5f8e744c81802.js +17 -0
  352. package/.next/standalone/.next/static/chunks/app/api/v1/mcp-servers/route-6fc5f8e744c81802.js +17 -0
  353. package/.next/standalone/.next/static/chunks/app/api/v1/memory/[namespace]/[key]/route-6fc5f8e744c81802.js +17 -0
  354. package/.next/standalone/.next/static/chunks/app/api/v1/memory/policy/route-6fc5f8e744c81802.js +17 -0
  355. package/.next/standalone/.next/static/chunks/app/api/v1/memory/route-6fc5f8e744c81802.js +17 -0
  356. package/.next/standalone/.next/static/chunks/app/api/v1/memory/search/route-6fc5f8e744c81802.js +17 -0
  357. package/.next/standalone/.next/static/chunks/app/api/v1/models/[name]/compact-threads/route-6fc5f8e744c81802.js +17 -0
  358. package/.next/standalone/.next/static/chunks/app/api/v1/models/[name]/route-6fc5f8e744c81802.js +17 -0
  359. package/.next/standalone/.next/static/chunks/app/api/v1/models/route-6fc5f8e744c81802.js +17 -0
  360. package/.next/standalone/.next/static/chunks/app/api/v1/packages/catalog/route-6fc5f8e744c81802.js +17 -0
  361. package/.next/standalone/.next/static/chunks/app/api/v1/packages/defaults/[id]/route-6fc5f8e744c81802.js +17 -0
  362. package/.next/standalone/.next/static/chunks/app/api/v1/packages/install/[id]/route-6fc5f8e744c81802.js +17 -0
  363. package/.next/standalone/.next/static/chunks/app/api/v1/packages/install/route-6fc5f8e744c81802.js +17 -0
  364. package/.next/standalone/.next/static/chunks/app/api/v1/packages/manifests/[name]/enabled/route-6fc5f8e744c81802.js +17 -0
  365. package/.next/standalone/.next/static/chunks/app/api/v1/packages/manifests/[name]/route-6fc5f8e744c81802.js +17 -0
  366. package/.next/standalone/.next/static/chunks/app/api/v1/packages/manifests/route-6fc5f8e744c81802.js +17 -0
  367. package/.next/standalone/.next/static/chunks/app/api/v1/packages/reload/route-6fc5f8e744c81802.js +17 -0
  368. package/.next/standalone/.next/static/chunks/app/api/v1/packages/route-6fc5f8e744c81802.js +17 -0
  369. package/.next/standalone/.next/static/chunks/app/api/v1/page-capture/route-6fc5f8e744c81802.js +17 -0
  370. package/.next/standalone/.next/static/chunks/app/api/v1/pending-actions/[id]/approve/route-6fc5f8e744c81802.js +17 -0
  371. package/.next/standalone/.next/static/chunks/app/api/v1/pending-actions/[id]/deny/route-6fc5f8e744c81802.js +17 -0
  372. package/.next/standalone/.next/static/chunks/app/api/v1/pending-actions/route-6fc5f8e744c81802.js +17 -0
  373. package/.next/standalone/.next/static/chunks/app/api/v1/profile/location/route-6fc5f8e744c81802.js +17 -0
  374. package/.next/standalone/.next/static/chunks/app/api/v1/profile/route-6fc5f8e744c81802.js +17 -0
  375. package/.next/standalone/.next/static/chunks/app/api/v1/providers/[provider]/models/route-6fc5f8e744c81802.js +17 -0
  376. package/.next/standalone/.next/static/chunks/app/api/v1/providers/[provider]/probe/route-6fc5f8e744c81802.js +17 -0
  377. package/.next/standalone/.next/static/chunks/app/api/v1/providers/github-copilot/auth/route-6fc5f8e744c81802.js +17 -0
  378. package/.next/standalone/.next/static/chunks/app/api/v1/providers/route-6fc5f8e744c81802.js +17 -0
  379. package/.next/standalone/.next/static/chunks/app/api/v1/proxy-config/route-6fc5f8e744c81802.js +17 -0
  380. package/.next/standalone/.next/static/chunks/app/api/v1/redaction/init/route-6fc5f8e744c81802.js +17 -0
  381. package/.next/standalone/.next/static/chunks/app/api/v1/redaction/route-6fc5f8e744c81802.js +17 -0
  382. package/.next/standalone/.next/static/chunks/app/api/v1/scheduled-tasks/[id]/route-6fc5f8e744c81802.js +17 -0
  383. package/.next/standalone/.next/static/chunks/app/api/v1/scheduled-tasks/[id]/run/route-6fc5f8e744c81802.js +17 -0
  384. package/.next/standalone/.next/static/chunks/app/api/v1/scheduled-tasks/route-6fc5f8e744c81802.js +17 -0
  385. package/.next/standalone/.next/static/chunks/app/api/v1/security/idle-timeout/route-6fc5f8e744c81802.js +17 -0
  386. package/.next/standalone/.next/static/chunks/app/api/v1/security/pin/route-6fc5f8e744c81802.js +17 -0
  387. package/.next/standalone/.next/static/chunks/app/api/v1/security/state/route-6fc5f8e744c81802.js +17 -0
  388. package/.next/standalone/.next/static/chunks/app/api/v1/security/unlock/route-6fc5f8e744c81802.js +17 -0
  389. package/.next/standalone/.next/static/chunks/app/api/v1/security/verify-pin/route-6fc5f8e744c81802.js +17 -0
  390. package/.next/standalone/.next/static/chunks/app/api/v1/setup/test-key/route-6fc5f8e744c81802.js +17 -0
  391. package/.next/standalone/.next/static/chunks/app/api/v1/skills/[id]/route-6fc5f8e744c81802.js +17 -0
  392. package/.next/standalone/.next/static/chunks/app/api/v1/skills/repos/[id]/route-6fc5f8e744c81802.js +17 -0
  393. package/.next/standalone/.next/static/chunks/app/api/v1/skills/repos/route-6fc5f8e744c81802.js +17 -0
  394. package/.next/standalone/.next/static/chunks/app/api/v1/skills/route-6fc5f8e744c81802.js +17 -0
  395. package/.next/standalone/.next/static/chunks/app/api/v1/system/abort/route-6fc5f8e744c81802.js +17 -0
  396. package/.next/standalone/.next/static/chunks/app/api/v1/system/restart/route-6fc5f8e744c81802.js +17 -0
  397. package/.next/standalone/.next/static/chunks/app/api/v1/tailscale/route-6fc5f8e744c81802.js +17 -0
  398. package/.next/standalone/.next/static/chunks/app/api/v1/tasks/[agent_id]/route-6fc5f8e744c81802.js +17 -0
  399. package/.next/standalone/.next/static/chunks/app/api/v1/tasks/route-6fc5f8e744c81802.js +17 -0
  400. package/.next/standalone/.next/static/chunks/app/api/v1/threads/[thread_id]/activity/route-6fc5f8e744c81802.js +17 -0
  401. package/.next/standalone/.next/static/chunks/app/api/v1/threads/[thread_id]/context-pin/route-6fc5f8e744c81802.js +17 -0
  402. package/.next/standalone/.next/static/chunks/app/api/v1/threads/[thread_id]/route-6fc5f8e744c81802.js +17 -0
  403. package/.next/standalone/.next/static/chunks/app/api/v1/threads/[thread_id]/run/route-6fc5f8e744c81802.js +17 -0
  404. package/.next/standalone/.next/static/chunks/app/api/v1/threads/route-6fc5f8e744c81802.js +17 -0
  405. package/.next/standalone/.next/static/chunks/app/api/v1/tools/route-6fc5f8e744c81802.js +17 -0
  406. package/.next/standalone/.next/static/chunks/app/api/v1/update/apply/route-6fc5f8e744c81802.js +17 -0
  407. package/.next/standalone/.next/static/chunks/app/api/v1/update/route-6fc5f8e744c81802.js +17 -0
  408. package/.next/standalone/.next/static/chunks/app/api/v1/voice/transcribe/route-6fc5f8e744c81802.js +17 -0
  409. package/.next/standalone/.next/static/chunks/app/api/v1/voice/tts/route-6fc5f8e744c81802.js +17 -0
  410. package/.next/standalone/.next/static/chunks/app/api/v1/watchers/[id]/route-6fc5f8e744c81802.js +17 -0
  411. package/.next/standalone/.next/static/chunks/app/api/v1/watchers/[id]/run/route-6fc5f8e744c81802.js +17 -0
  412. package/.next/standalone/.next/static/chunks/app/api/v1/watchers/reaction-scripts/route-6fc5f8e744c81802.js +17 -0
  413. package/.next/standalone/.next/static/chunks/app/api/v1/watchers/route-6fc5f8e744c81802.js +17 -0
  414. package/.next/standalone/.next/static/chunks/app/manifest.webmanifest/route-6fc5f8e744c81802.js +17 -0
  415. package/.next/standalone/.next/static/chunks/app/{page-7017f07f8a7a083c.js → page-213a623b37226452.js} +1041 -652
  416. package/.next/standalone/.next/static/chunks/next/dist/client/components/builtin/app-error-6fc5f8e744c81802.js +17 -0
  417. package/.next/standalone/.next/static/chunks/next/dist/client/components/builtin/forbidden-6fc5f8e744c81802.js +17 -0
  418. package/.next/standalone/.next/static/chunks/next/dist/client/components/builtin/not-found-6fc5f8e744c81802.js +17 -0
  419. package/.next/standalone/.next/static/chunks/next/dist/client/components/builtin/unauthorized-6fc5f8e744c81802.js +17 -0
  420. package/.next/standalone/.next/static/css/{d80058f0b9b41c09.css → 312542a5725ba0d5.css} +2 -2
  421. package/.next/standalone/docs/adoption/changesets.json +309 -0
  422. package/.next/standalone/lib/skills/builtins/memory-organization/SKILL.md +16 -0
  423. package/.next/standalone/package.json +3 -3
  424. package/CHANGELOG.md +25 -0
  425. package/api/client.ts +9 -0
  426. package/api/types.ts +29 -0
  427. package/app/api/v1/lifecycle/adoption/route.ts +14 -2
  428. package/app/api/v1/models/[name]/compact-threads/route.ts +14 -11
  429. package/app/api/v1/threads/[thread_id]/activity/route.ts +19 -0
  430. package/app/api/v1/threads/[thread_id]/context-pin/route.test.ts +1 -0
  431. package/app/api/v1/threads/[thread_id]/context-pin/route.ts +2 -1
  432. package/app/api/v1/threads/[thread_id]/route.ts +5 -1
  433. package/components/chat/ChatView.tsx +52 -11
  434. package/components/chat/ContextBoundary.test.tsx +68 -1
  435. package/components/chat/ContextBoundary.tsx +92 -13
  436. package/components/chat/MessageList.test.tsx +31 -0
  437. package/components/chat/MessageList.tsx +49 -28
  438. package/components/chat/ToolList.test.tsx +92 -16
  439. package/components/chat/ToolList.tsx +59 -4
  440. package/components/chat/chat-helpers.test.tsx +24 -1
  441. package/components/chat/chat-helpers.ts +47 -4
  442. package/components/chat/useThreadActivity.test.tsx +113 -0
  443. package/components/chat/useThreadActivity.ts +94 -0
  444. package/components/chat/useThreadData.ts +16 -16
  445. package/components/chat/workflow-step-retry.ts +25 -0
  446. package/components/ui/BootScreen.tsx +17 -0
  447. package/components/ui/WorkflowChecklist.tsx +71 -33
  448. package/hooks/useSSE.ts +28 -3
  449. package/lib/agents/compaction-pipeline.test.ts +202 -0
  450. package/lib/agents/compaction-pipeline.ts +483 -0
  451. package/lib/agents/conversation-summary.ts +37 -21
  452. package/lib/agents/prepare/history-window.test.ts +18 -0
  453. package/lib/agents/prepare/history-window.ts +11 -2
  454. package/lib/agents/prepare/request.ts +4 -0
  455. package/lib/agents/prepare/system-prompt.test.ts +39 -0
  456. package/lib/agents/prepare/system-prompt.ts +8 -3
  457. package/lib/agents/prompt-registry.test.ts +5 -140
  458. package/lib/agents/prompt-registry.ts +45 -1
  459. package/lib/agents/prompt-variants.ts +146 -0
  460. package/lib/agents/run-registry.test.ts +22 -0
  461. package/lib/agents/run-registry.ts +29 -0
  462. package/lib/agents/run-thread.retry.test.ts +67 -1
  463. package/lib/agents/run-thread.ts +86 -1
  464. package/lib/agents/thread-activity.test.ts +31 -0
  465. package/lib/agents/thread-activity.ts +27 -0
  466. package/lib/agents/thread-compaction-state.test.ts +82 -0
  467. package/lib/agents/thread-compaction-state.ts +121 -0
  468. package/lib/agents/thread-compaction.test.ts +83 -4
  469. package/lib/agents/thread-compaction.ts +34 -11
  470. package/lib/agents/warm-summary-background.test.ts +219 -5
  471. package/lib/agents/warm-summary-background.ts +325 -142
  472. package/lib/agents/warm-topics.test.ts +37 -0
  473. package/lib/agents/warm-topics.ts +297 -0
  474. package/lib/agents/workflow-step-retry.test.ts +96 -0
  475. package/lib/agents/workflow-step-retry.ts +216 -0
  476. package/lib/api/browser-control.ts +0 -3
  477. package/lib/db/migrations.ts +5 -0
  478. package/lib/env/config.ts +2 -0
  479. package/lib/env/schema.ts +12 -0
  480. package/lib/lifecycle/changeset-build.test.ts +93 -0
  481. package/lib/lifecycle/changeset-build.ts +210 -0
  482. package/lib/lifecycle/changesets.test.ts +101 -0
  483. package/lib/lifecycle/changesets.ts +166 -0
  484. package/lib/lifecycle/surface-collect.test.ts +88 -0
  485. package/lib/lifecycle/surface-collect.ts +64 -0
  486. package/lib/lifecycle/surface-snapshot.test.ts +104 -0
  487. package/lib/lifecycle/surface-snapshot.ts +210 -0
  488. package/lib/memory/record.ts +0 -2
  489. package/lib/providers/external.ts +0 -2
  490. package/lib/skills/builtins/memory-organization/SKILL.md +16 -0
  491. package/lib/stores/threads.test.ts +9 -0
  492. package/lib/stores/threads.ts +21 -11
  493. package/lib/stores/version-adoption.test.ts +96 -0
  494. package/lib/stores/version-adoption.ts +239 -26
  495. package/lib/stores/workflow-progress.ts +3 -0
  496. package/lib/tools/communications/ms-todo.ts +0 -7
  497. package/lib/tools/general/memory.ts +1 -1
  498. package/lib/tools/general/workflow-progress.ts +2 -0
  499. package/lib/tools/runtime/catalog.ts +1 -25
  500. package/lib/triggers/registry.ts +0 -4
  501. package/package.json +3 -3
  502. package/scripts/install-to-system.ps1 +39 -11
  503. package/scripts/install-to-system.sh +37 -3
  504. package/.next/standalone/.next/server/chunks/3979.js +0 -581
  505. package/.next/standalone/.next/server/chunks/5936.js +0 -594
  506. package/.next/standalone/.next/static/chunks/app/api/v1/agents/[id]/display-filters/route-36cb8b428b38b26a.js +0 -17
  507. package/.next/standalone/.next/static/chunks/app/api/v1/agents/[id]/route-36cb8b428b38b26a.js +0 -17
  508. package/.next/standalone/.next/static/chunks/app/api/v1/agents/[id]/thread/route-36cb8b428b38b26a.js +0 -17
  509. package/.next/standalone/.next/static/chunks/app/api/v1/agents/route-36cb8b428b38b26a.js +0 -17
  510. package/.next/standalone/.next/static/chunks/app/api/v1/allowed-sites/[hostname]/route-36cb8b428b38b26a.js +0 -17
  511. package/.next/standalone/.next/static/chunks/app/api/v1/allowed-sites/route-36cb8b428b38b26a.js +0 -17
  512. package/.next/standalone/.next/static/chunks/app/api/v1/artifacts/lifecycle/route-36cb8b428b38b26a.js +0 -17
  513. package/.next/standalone/.next/static/chunks/app/api/v1/attachments/files/route-36cb8b428b38b26a.js +0 -17
  514. package/.next/standalone/.next/static/chunks/app/api/v1/attachments/images/route-36cb8b428b38b26a.js +0 -17
  515. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/[id]/chats/route-36cb8b428b38b26a.js +0 -17
  516. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/[id]/ignores/[remote_jid]/route-36cb8b428b38b26a.js +0 -17
  517. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/[id]/ignores/route-36cb8b428b38b26a.js +0 -17
  518. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/[id]/lookup/route-36cb8b428b38b26a.js +0 -17
  519. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/[id]/pair/route-36cb8b428b38b26a.js +0 -17
  520. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/[id]/route-36cb8b428b38b26a.js +0 -17
  521. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/[id]/routes/[route_id]/route-36cb8b428b38b26a.js +0 -17
  522. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/[id]/routes/route-36cb8b428b38b26a.js +0 -17
  523. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/[id]/status/route-36cb8b428b38b26a.js +0 -17
  524. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/kinds/route-36cb8b428b38b26a.js +0 -17
  525. package/.next/standalone/.next/static/chunks/app/api/v1/bridges/route-36cb8b428b38b26a.js +0 -17
  526. package/.next/standalone/.next/static/chunks/app/api/v1/builtin-tools/route-36cb8b428b38b26a.js +0 -17
  527. package/.next/standalone/.next/static/chunks/app/api/v1/config/route-36cb8b428b38b26a.js +0 -17
  528. package/.next/standalone/.next/static/chunks/app/api/v1/credentials/[id]/route-36cb8b428b38b26a.js +0 -17
  529. package/.next/standalone/.next/static/chunks/app/api/v1/credentials/route-36cb8b428b38b26a.js +0 -17
  530. package/.next/standalone/.next/static/chunks/app/api/v1/dashboard/currency/route-36cb8b428b38b26a.js +0 -17
  531. package/.next/standalone/.next/static/chunks/app/api/v1/dashboard/metrics/route-36cb8b428b38b26a.js +0 -17
  532. package/.next/standalone/.next/static/chunks/app/api/v1/dashboard/pricing/route-36cb8b428b38b26a.js +0 -17
  533. package/.next/standalone/.next/static/chunks/app/api/v1/dashboard/pricing-task/route-36cb8b428b38b26a.js +0 -17
  534. package/.next/standalone/.next/static/chunks/app/api/v1/delegations/codex/[job_id]/route-36cb8b428b38b26a.js +0 -17
  535. package/.next/standalone/.next/static/chunks/app/api/v1/documents/search/route-36cb8b428b38b26a.js +0 -17
  536. package/.next/standalone/.next/static/chunks/app/api/v1/documents/settings/route-36cb8b428b38b26a.js +0 -17
  537. package/.next/standalone/.next/static/chunks/app/api/v1/documents/sources/[id]/reindex/route-36cb8b428b38b26a.js +0 -17
  538. package/.next/standalone/.next/static/chunks/app/api/v1/documents/sources/[id]/route-36cb8b428b38b26a.js +0 -17
  539. package/.next/standalone/.next/static/chunks/app/api/v1/documents/sources/route-36cb8b428b38b26a.js +0 -17
  540. package/.next/standalone/.next/static/chunks/app/api/v1/env/route-36cb8b428b38b26a.js +0 -17
  541. package/.next/standalone/.next/static/chunks/app/api/v1/env-sync/allowlist/route-36cb8b428b38b26a.js +0 -17
  542. package/.next/standalone/.next/static/chunks/app/api/v1/env-sync/route-36cb8b428b38b26a.js +0 -17
  543. package/.next/standalone/.next/static/chunks/app/api/v1/events/route-36cb8b428b38b26a.js +0 -17
  544. package/.next/standalone/.next/static/chunks/app/api/v1/events/test/route-36cb8b428b38b26a.js +0 -17
  545. package/.next/standalone/.next/static/chunks/app/api/v1/extension/agents/route-36cb8b428b38b26a.js +0 -17
  546. package/.next/standalone/.next/static/chunks/app/api/v1/extension/browser/activate/route-36cb8b428b38b26a.js +0 -17
  547. package/.next/standalone/.next/static/chunks/app/api/v1/extension/browser/foreground/route-36cb8b428b38b26a.js +0 -17
  548. package/.next/standalone/.next/static/chunks/app/api/v1/extension/browser/history/route-36cb8b428b38b26a.js +0 -17
  549. package/.next/standalone/.next/static/chunks/app/api/v1/extension/browser/poll/route-36cb8b428b38b26a.js +0 -17
  550. package/.next/standalone/.next/static/chunks/app/api/v1/extension/browser/progress/route-36cb8b428b38b26a.js +0 -17
  551. package/.next/standalone/.next/static/chunks/app/api/v1/extension/browser/result/route-36cb8b428b38b26a.js +0 -17
  552. package/.next/standalone/.next/static/chunks/app/api/v1/extension/browser/retry/route-36cb8b428b38b26a.js +0 -17
  553. package/.next/standalone/.next/static/chunks/app/api/v1/extension/browser/status/route-36cb8b428b38b26a.js +0 -17
  554. package/.next/standalone/.next/static/chunks/app/api/v1/extension/browser/tabs/route-36cb8b428b38b26a.js +0 -17
  555. package/.next/standalone/.next/static/chunks/app/api/v1/extension/fill/route-36cb8b428b38b26a.js +0 -17
  556. package/.next/standalone/.next/static/chunks/app/api/v1/extension/refine/route-36cb8b428b38b26a.js +0 -17
  557. package/.next/standalone/.next/static/chunks/app/api/v1/extension/turn/route-36cb8b428b38b26a.js +0 -17
  558. package/.next/standalone/.next/static/chunks/app/api/v1/extensions/route-36cb8b428b38b26a.js +0 -17
  559. package/.next/standalone/.next/static/chunks/app/api/v1/extensions/tools/[name]/config/route-36cb8b428b38b26a.js +0 -17
  560. package/.next/standalone/.next/static/chunks/app/api/v1/extensions/tools/[name]/route-36cb8b428b38b26a.js +0 -17
  561. package/.next/standalone/.next/static/chunks/app/api/v1/extensions/tools/[name]/secrets/route-36cb8b428b38b26a.js +0 -17
  562. package/.next/standalone/.next/static/chunks/app/api/v1/files/[name]/route-36cb8b428b38b26a.js +0 -17
  563. package/.next/standalone/.next/static/chunks/app/api/v1/fs/browse/route-36cb8b428b38b26a.js +0 -17
  564. package/.next/standalone/.next/static/chunks/app/api/v1/harnesses/[id]/route-36cb8b428b38b26a.js +0 -17
  565. package/.next/standalone/.next/static/chunks/app/api/v1/harnesses/default/route-36cb8b428b38b26a.js +0 -17
  566. package/.next/standalone/.next/static/chunks/app/api/v1/harnesses/route-36cb8b428b38b26a.js +0 -17
  567. package/.next/standalone/.next/static/chunks/app/api/v1/health/probes/route-36cb8b428b38b26a.js +0 -17
  568. package/.next/standalone/.next/static/chunks/app/api/v1/health/route-36cb8b428b38b26a.js +0 -17
  569. package/.next/standalone/.next/static/chunks/app/api/v1/integrations/[name]/route-36cb8b428b38b26a.js +0 -17
  570. package/.next/standalone/.next/static/chunks/app/api/v1/integrations/[name]/test/route-36cb8b428b38b26a.js +0 -17
  571. package/.next/standalone/.next/static/chunks/app/api/v1/integrations/gmail/oauth/callback/route-36cb8b428b38b26a.js +0 -17
  572. package/.next/standalone/.next/static/chunks/app/api/v1/integrations/gmail/oauth/start/route-36cb8b428b38b26a.js +0 -17
  573. package/.next/standalone/.next/static/chunks/app/api/v1/integrations/gmail/oauth/status/route-36cb8b428b38b26a.js +0 -17
  574. package/.next/standalone/.next/static/chunks/app/api/v1/integrations/outlook/oauth/callback/route-36cb8b428b38b26a.js +0 -17
  575. package/.next/standalone/.next/static/chunks/app/api/v1/integrations/outlook/oauth/start/route-36cb8b428b38b26a.js +0 -17
  576. package/.next/standalone/.next/static/chunks/app/api/v1/integrations/outlook/oauth/status/route-36cb8b428b38b26a.js +0 -17
  577. package/.next/standalone/.next/static/chunks/app/api/v1/integrations/route-36cb8b428b38b26a.js +0 -17
  578. package/.next/standalone/.next/static/chunks/app/api/v1/lifecycle/adoption/route-36cb8b428b38b26a.js +0 -17
  579. package/.next/standalone/.next/static/chunks/app/api/v1/local-file/route-36cb8b428b38b26a.js +0 -17
  580. package/.next/standalone/.next/static/chunks/app/api/v1/logs/route-36cb8b428b38b26a.js +0 -17
  581. package/.next/standalone/.next/static/chunks/app/api/v1/maps/embed/route-36cb8b428b38b26a.js +0 -17
  582. package/.next/standalone/.next/static/chunks/app/api/v1/mcp-servers/[name]/route-36cb8b428b38b26a.js +0 -17
  583. package/.next/standalone/.next/static/chunks/app/api/v1/mcp-servers/registry/route-36cb8b428b38b26a.js +0 -17
  584. package/.next/standalone/.next/static/chunks/app/api/v1/mcp-servers/route-36cb8b428b38b26a.js +0 -17
  585. package/.next/standalone/.next/static/chunks/app/api/v1/memory/[namespace]/[key]/route-36cb8b428b38b26a.js +0 -17
  586. package/.next/standalone/.next/static/chunks/app/api/v1/memory/policy/route-36cb8b428b38b26a.js +0 -17
  587. package/.next/standalone/.next/static/chunks/app/api/v1/memory/route-36cb8b428b38b26a.js +0 -17
  588. package/.next/standalone/.next/static/chunks/app/api/v1/memory/search/route-36cb8b428b38b26a.js +0 -17
  589. package/.next/standalone/.next/static/chunks/app/api/v1/models/[name]/compact-threads/route-36cb8b428b38b26a.js +0 -17
  590. package/.next/standalone/.next/static/chunks/app/api/v1/models/[name]/route-36cb8b428b38b26a.js +0 -17
  591. package/.next/standalone/.next/static/chunks/app/api/v1/models/route-36cb8b428b38b26a.js +0 -17
  592. package/.next/standalone/.next/static/chunks/app/api/v1/packages/catalog/route-36cb8b428b38b26a.js +0 -17
  593. package/.next/standalone/.next/static/chunks/app/api/v1/packages/defaults/[id]/route-36cb8b428b38b26a.js +0 -17
  594. package/.next/standalone/.next/static/chunks/app/api/v1/packages/install/[id]/route-36cb8b428b38b26a.js +0 -17
  595. package/.next/standalone/.next/static/chunks/app/api/v1/packages/install/route-36cb8b428b38b26a.js +0 -17
  596. package/.next/standalone/.next/static/chunks/app/api/v1/packages/manifests/[name]/enabled/route-36cb8b428b38b26a.js +0 -17
  597. package/.next/standalone/.next/static/chunks/app/api/v1/packages/manifests/[name]/route-36cb8b428b38b26a.js +0 -17
  598. package/.next/standalone/.next/static/chunks/app/api/v1/packages/manifests/route-36cb8b428b38b26a.js +0 -17
  599. package/.next/standalone/.next/static/chunks/app/api/v1/packages/reload/route-36cb8b428b38b26a.js +0 -17
  600. package/.next/standalone/.next/static/chunks/app/api/v1/packages/route-36cb8b428b38b26a.js +0 -17
  601. package/.next/standalone/.next/static/chunks/app/api/v1/page-capture/route-36cb8b428b38b26a.js +0 -17
  602. package/.next/standalone/.next/static/chunks/app/api/v1/pending-actions/[id]/approve/route-36cb8b428b38b26a.js +0 -17
  603. package/.next/standalone/.next/static/chunks/app/api/v1/pending-actions/[id]/deny/route-36cb8b428b38b26a.js +0 -17
  604. package/.next/standalone/.next/static/chunks/app/api/v1/pending-actions/route-36cb8b428b38b26a.js +0 -17
  605. package/.next/standalone/.next/static/chunks/app/api/v1/profile/location/route-36cb8b428b38b26a.js +0 -17
  606. package/.next/standalone/.next/static/chunks/app/api/v1/profile/route-36cb8b428b38b26a.js +0 -17
  607. package/.next/standalone/.next/static/chunks/app/api/v1/providers/[provider]/models/route-36cb8b428b38b26a.js +0 -17
  608. package/.next/standalone/.next/static/chunks/app/api/v1/providers/[provider]/probe/route-36cb8b428b38b26a.js +0 -17
  609. package/.next/standalone/.next/static/chunks/app/api/v1/providers/github-copilot/auth/route-36cb8b428b38b26a.js +0 -17
  610. package/.next/standalone/.next/static/chunks/app/api/v1/providers/route-36cb8b428b38b26a.js +0 -17
  611. package/.next/standalone/.next/static/chunks/app/api/v1/proxy-config/route-36cb8b428b38b26a.js +0 -17
  612. package/.next/standalone/.next/static/chunks/app/api/v1/redaction/init/route-36cb8b428b38b26a.js +0 -17
  613. package/.next/standalone/.next/static/chunks/app/api/v1/redaction/route-36cb8b428b38b26a.js +0 -17
  614. package/.next/standalone/.next/static/chunks/app/api/v1/scheduled-tasks/[id]/route-36cb8b428b38b26a.js +0 -17
  615. package/.next/standalone/.next/static/chunks/app/api/v1/scheduled-tasks/[id]/run/route-36cb8b428b38b26a.js +0 -17
  616. package/.next/standalone/.next/static/chunks/app/api/v1/scheduled-tasks/route-36cb8b428b38b26a.js +0 -17
  617. package/.next/standalone/.next/static/chunks/app/api/v1/security/idle-timeout/route-36cb8b428b38b26a.js +0 -17
  618. package/.next/standalone/.next/static/chunks/app/api/v1/security/pin/route-36cb8b428b38b26a.js +0 -17
  619. package/.next/standalone/.next/static/chunks/app/api/v1/security/state/route-36cb8b428b38b26a.js +0 -17
  620. package/.next/standalone/.next/static/chunks/app/api/v1/security/unlock/route-36cb8b428b38b26a.js +0 -17
  621. package/.next/standalone/.next/static/chunks/app/api/v1/security/verify-pin/route-36cb8b428b38b26a.js +0 -17
  622. package/.next/standalone/.next/static/chunks/app/api/v1/setup/test-key/route-36cb8b428b38b26a.js +0 -17
  623. package/.next/standalone/.next/static/chunks/app/api/v1/skills/[id]/route-36cb8b428b38b26a.js +0 -17
  624. package/.next/standalone/.next/static/chunks/app/api/v1/skills/repos/[id]/route-36cb8b428b38b26a.js +0 -17
  625. package/.next/standalone/.next/static/chunks/app/api/v1/skills/repos/route-36cb8b428b38b26a.js +0 -17
  626. package/.next/standalone/.next/static/chunks/app/api/v1/skills/route-36cb8b428b38b26a.js +0 -17
  627. package/.next/standalone/.next/static/chunks/app/api/v1/system/abort/route-36cb8b428b38b26a.js +0 -17
  628. package/.next/standalone/.next/static/chunks/app/api/v1/system/restart/route-36cb8b428b38b26a.js +0 -17
  629. package/.next/standalone/.next/static/chunks/app/api/v1/tailscale/route-36cb8b428b38b26a.js +0 -17
  630. package/.next/standalone/.next/static/chunks/app/api/v1/tasks/[agent_id]/route-36cb8b428b38b26a.js +0 -17
  631. package/.next/standalone/.next/static/chunks/app/api/v1/tasks/route-36cb8b428b38b26a.js +0 -17
  632. package/.next/standalone/.next/static/chunks/app/api/v1/threads/[thread_id]/context-pin/route-36cb8b428b38b26a.js +0 -17
  633. package/.next/standalone/.next/static/chunks/app/api/v1/threads/[thread_id]/route-36cb8b428b38b26a.js +0 -17
  634. package/.next/standalone/.next/static/chunks/app/api/v1/threads/[thread_id]/run/route-36cb8b428b38b26a.js +0 -17
  635. package/.next/standalone/.next/static/chunks/app/api/v1/threads/route-36cb8b428b38b26a.js +0 -17
  636. package/.next/standalone/.next/static/chunks/app/api/v1/tools/route-36cb8b428b38b26a.js +0 -17
  637. package/.next/standalone/.next/static/chunks/app/api/v1/update/apply/route-36cb8b428b38b26a.js +0 -17
  638. package/.next/standalone/.next/static/chunks/app/api/v1/update/route-36cb8b428b38b26a.js +0 -17
  639. package/.next/standalone/.next/static/chunks/app/api/v1/voice/transcribe/route-36cb8b428b38b26a.js +0 -17
  640. package/.next/standalone/.next/static/chunks/app/api/v1/voice/tts/route-36cb8b428b38b26a.js +0 -17
  641. package/.next/standalone/.next/static/chunks/app/api/v1/watchers/[id]/route-36cb8b428b38b26a.js +0 -17
  642. package/.next/standalone/.next/static/chunks/app/api/v1/watchers/[id]/run/route-36cb8b428b38b26a.js +0 -17
  643. package/.next/standalone/.next/static/chunks/app/api/v1/watchers/reaction-scripts/route-36cb8b428b38b26a.js +0 -17
  644. package/.next/standalone/.next/static/chunks/app/api/v1/watchers/route-36cb8b428b38b26a.js +0 -17
  645. package/.next/standalone/.next/static/chunks/app/manifest.webmanifest/route-36cb8b428b38b26a.js +0 -17
  646. package/.next/standalone/.next/static/chunks/next/dist/client/components/builtin/app-error-36cb8b428b38b26a.js +0 -17
  647. package/.next/standalone/.next/static/chunks/next/dist/client/components/builtin/forbidden-36cb8b428b38b26a.js +0 -17
  648. package/.next/standalone/.next/static/chunks/next/dist/client/components/builtin/not-found-36cb8b428b38b26a.js +0 -17
  649. package/.next/standalone/.next/static/chunks/next/dist/client/components/builtin/unauthorized-36cb8b428b38b26a.js +0 -17
  650. /package/.next/standalone/.next/static/{NUrC9xax1sp1Q70nlFqS6 → bMRK5y3ruT7c3WtBfCQOG}/_buildManifest.js +0 -0
  651. /package/.next/standalone/.next/static/{NUrC9xax1sp1Q70nlFqS6 → bMRK5y3ruT7c3WtBfCQOG}/_ssgManifest.js +0 -0
@@ -148,6 +148,45 @@ describe("buildSystemPrompt self-configuration", () => {
148
148
  });
149
149
  });
150
150
 
151
+ describe("buildSystemPrompt proactive memory saving", () => {
152
+ const build = () => buildSystemPrompt({
153
+ agentCfg: agentCfg(),
154
+ trimmedMessage: "I prefer short answers",
155
+ budget,
156
+ recallCtx: "",
157
+ warmSummaryCtx: "",
158
+ factsCtx: "",
159
+ experienceMode: "full",
160
+ delegateRosterLines: [],
161
+ });
162
+
163
+ it("orders the save procedure as trigger, check, write, validate, cite", () => {
164
+ const prompt = build();
165
+ const steps = ["1. Trigger:", "2. Check:", "3. Write:", "4. Validate:", "5. Cite:"].map((s) => prompt.indexOf(s));
166
+ expect(steps.every((i) => i >= 0)).toBe(true);
167
+ expect([...steps].sort((a, b) => a - b)).toEqual(steps);
168
+ expect(prompt).toContain("backstop, not your save step");
169
+ });
170
+
171
+ it("keeps the save procedure in the cached agent-stable block", () => {
172
+ const prompt = build();
173
+ const split = prompt.indexOf(CACHE_SPLIT_SENTINEL);
174
+ expect(split).toBeGreaterThan(0);
175
+ expect(prompt.indexOf("Proactive save procedure")).toBeLessThan(split);
176
+ });
177
+
178
+ it("only names memory tools that are registered", async () => {
179
+ const memory = await import("@/lib/tools/general/memory");
180
+ const registered = new Set(Object.values(memory)
181
+ .filter((v): v is { name: string } => typeof v === "object" && v !== null && "name" in v)
182
+ .map((t) => t.name));
183
+ const block = build().split("--- Memory & recall ---")[1]?.split("\n---")[0] ?? "";
184
+ const named = new Set(block.match(/\bmemory_[a-z]+\b/g) ?? []);
185
+ expect(named.size).toBeGreaterThan(0);
186
+ for (const name of named) expect(registered).toContain(name);
187
+ });
188
+ });
189
+
151
190
  const permissionMapFixture = [
152
191
  {
153
192
  name: "file_read",
@@ -272,7 +272,7 @@ export function buildSharedToolCatalogContext(): string {
272
272
  return [
273
273
  "--- Tool usage SOP ---",
274
274
  "Static cross-agent procedure. The per-turn bound list and counts appear later under \"Enabled tools\".",
275
- `0. Classify the request. Informational answers may be direct; read/retrieve requests need a read tool; write/change requests need a state-changing tool; destructive requests also need the required confirmation. ${formatActionVocabularyInstruction()} For substantial tasks with several dependent phases, likely cross-turn progress, or explicit verification, use workflow_progress to create and update a concise checklist; skip simple tasks and work already covered by native tool progress. This contract applies to every built-in Jarela workflow and every workflow you create or follow: each step must state its input, expected output, and concrete validation criteria; validate each output before passing it to a later step. Prefer executable checks whenever code can verify the result, and record observed validation_evidence before marking an item done. Keep a stable workflow_id, send the complete current item list on each update, and keep secrets or private data out of checklist fields. Use needs_attention for blockers; set phase=complete only when all items are done or skipped. Never claim an output or validation result that you did not observe.`,
275
+ `0. Classify the request. Informational answers may be direct; read/retrieve requests need a read tool; write/change requests need a state-changing tool; destructive requests also need the required confirmation. ${formatActionVocabularyInstruction()} For substantial tasks with several dependent phases, likely cross-turn progress, or explicit verification, use workflow_progress to create and update a concise checklist; skip simple tasks and work already covered by native tool progress. This contract applies to every built-in Jarela workflow and every workflow you create or follow: each step must state its input, expected output, and concrete validation criteria; validate each output before passing it to a later step. Prefer executable checks whenever code can verify the result, and record observed validation_evidence before marking an item done. Keep a stable workflow_id, send the complete current item list on each update, and keep secrets or private data out of checklist fields. Use needs_attention for blockers, with needs_user=true when only the user can unblock the step; a rejected update or a step you leave checking or needs_attention without needs_user is retried automatically, up to 3 attempts per step. Set phase=complete only when all items are done or skipped. Never claim an output or validation result that you did not observe.`,
276
276
  "1. Bound first. If a tool listed under \"Enabled tools\" fits the task, call it directly.",
277
277
  "2. Otherwise look it up. Names of permitted tools that are not bound this turn are listed after the bound tools under \"Enabled tools\", capped, with no definitions. A name that is not listed there may still exist, so never conclude a capability does not exist from the bound list alone. Call list_tools with service/object/action keywords: scope=\"enabled\" searches executable tools, scope=\"all\" also returns disabled, unavailable and cap-omitted tools with flags.",
278
278
  "3. Named target. When a skill, harness or instruction names an exact tool, call list_tools names=[\"exact_name\"] include_schema=true instead of a keyword query. Exact lookup ignores every other filter, so it also describes tools you cannot currently execute.",
@@ -603,11 +603,16 @@ function buildMemoryContext(budget: ContextBudget): string {
603
603
  : "Store explicit preferences, verified facts, durable decisions, constraints, and project context. Store task details only when they will matter across sessions.";
604
604
  return [
605
605
  "--- Memory & recall ---",
606
- "You have long-term memory across sessions.",
606
+ "You have long-term memory across sessions, shared with every other Jarela agent. A record you save is available to other agents immediately. Background compaction also extracts facts later, but it runs late and can miss details, so it is a backstop, not your save step.",
607
607
  `- Hot conversation history is budgeted by model context size: ${formatContextBudgetSummary(budget)}.`,
608
608
  `- Active memory policy: ${policy}. ${writeGuidance}`,
609
- "- Use memory_upsert proactively for structured records. Use namespace='facts', concise tags, confidence='explicit' for user-stated information, observed_at when the information was true, and expires_at for temporary facts. Keep memory_write only for legacy/free-form notes.",
610
609
  "- Use memory_search proactively when relevant saved facts or prior conversations could help. Use memory_read / memory_list to inspect known entries.",
610
+ "Proactive save procedure — run it whenever information fits the active memory policy, without waiting to be asked:",
611
+ "1. Trigger: the user states a preference, a fact about themselves or their work, a decision, a constraint, or a correction to something saved; or a tool result verifies a durable fact. Routine status, one-off chatter, secrets, credentials, and raw transcripts never qualify.",
612
+ "2. Check: memory_search (or memory_read for a known key) for an existing record on the same subject. Update that stable key rather than creating a duplicate or contradictory copy.",
613
+ "3. Write: call memory_upsert in the same turn, before your final reply, with namespace='facts', a stable descriptive key, standalone content, concise tags, confidence='explicit' for user-stated information ('verified' when tool-backed, 'inferred' only when useful and reversible), observed_at when the information became true, and expires_at for temporary facts. Keep memory_write only for legacy/free-form notes.",
614
+ "4. Validate: the memory_upsert result must contain ok:true and the key you sent. If it failed, correct the arguments and retry once; if it still fails, tell the user it was not saved.",
615
+ "5. Cite: end your reply with one short line naming each saved key, for example 'Saved to memory: facts/answer-format-preference'. Omit the line when nothing was saved.",
611
616
  ].join("\n");
612
617
  }
613
618
 
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Assembles every prompt Jarela can send and checks it for completeness and
3
- * correctness. Reading the builders is not enough — the bugs found so far
3
+ * correctness. Reading the builders is not enough — the bugs found so far
4
4
  * (contradictory tool counts, undocumented denial reasons) were only visible
5
5
  * in the assembled text.
6
6
  *
@@ -16,151 +16,15 @@ const tmpRoot = mkdtempSync(join(tmpdir(), "jarela-prompt-verify-"));
16
16
  process.env.JARELA_DB_DIR = tmpRoot;
17
17
 
18
18
  const { buildSystemPrompt, CACHE_SHARED_SPLIT_SENTINEL, CACHE_SPLIT_SENTINEL } = await import("./prepare/system-prompt");
19
- const { getUsageStrategyProfile } = await import("./usage-strategy");
20
19
  const { listStaticPrompts, promptsAffectedBy, SYSTEM_PROMPT_SOURCE_PREFIXES } = await import("./prompt-registry");
21
- const { getAllToolCatalogAsync, applyAgentPermissionsToCatalog, markProxyOnlyTools } = await import("@/lib/tools");
20
+ const { getAllToolCatalogAsync, applyAgentPermissionsToCatalog } = await import("@/lib/tools");
22
21
  import type { AgentConfigRow } from "@/lib/stores/agent-configs";
23
- import type { ContextBudget } from "@/lib/agents/context-budget";
24
22
 
25
23
  afterAll(() => {
26
24
  try { rmSync(tmpRoot, { recursive: true, force: true }); } catch { /* held open */ }
27
25
  });
28
26
 
29
- const budget: ContextBudget = {
30
- contextWindowTokens: 200000,
31
- outputReserveTokens: 8000,
32
- inputBudgetTokens: 120000,
33
- overheadTokens: 4000,
34
- tierPriority: ["hot", "warm", "facts"],
35
- tierBudgets: { hot: 60000, warm: 40000, facts: 20000 },
36
- };
37
-
38
- function agentCfg(overrides: Partial<AgentConfigRow> = {}): AgentConfigRow {
39
- return {
40
- id: "verify-agent",
41
- name: "Verify",
42
- icon: null,
43
- identity: "You are Jarela, a local assistant.",
44
- instructions: "Be terse.",
45
- tools: "[]",
46
- model_config_name: null,
47
- is_default: 1,
48
- history_limit: 50,
49
- history_window_hours: 8,
50
- never_reply: 0,
51
- adaptive_persona_enabled: 0,
52
- adaptive_persona_strength: 0,
53
- adaptive_empathy: 50,
54
- adaptive_expressiveness: 50,
55
- adaptive_verbosity: 50,
56
- adaptive_mbti: "INTJ",
57
- voice_enabled: 0,
58
- voice_model: "",
59
- voice_name: "",
60
- voice_stt_model: "",
61
- voice_auto_speak: 0,
62
- display_filters: null,
63
- harness_id: null,
64
- delegate_targets: null,
65
- context_tier_proportions: null,
66
- anti_hallucination_mode: null,
67
- ...overrides,
68
- } as AgentConfigRow;
69
- }
70
-
71
- interface Variant {
72
- id: string;
73
- prompt: string;
74
- /** Counts derived from the permission map, to check the prompt's own arithmetic. */
75
- expected?: { bound: number; proxy: number; denied: number; unavailable: number };
76
- }
77
-
78
- async function buildVariants(): Promise<Variant[]> {
79
- const catalog = await getAllToolCatalogAsync();
80
- const pinned = ["gmail_search", "gmail_send_email"];
81
- const cfg = agentCfg({ tools: JSON.stringify(pinned) });
82
- const permissions = applyAgentPermissionsToCatalog(catalog, cfg);
83
- const permitted = permissions.filter((t) => t.permission === "enabled").map((t) => t.name);
84
-
85
- // Bind everything permitted: no proxy_only, the common case today.
86
- const allBound = markProxyOnlyTools(permissions, permitted, permitted);
87
- // Bind only the self-config tools so the rest becomes proxy_only.
88
- const narrowBound = permitted.filter((n) => n === "invoke_tool" || n === "list_tools");
89
- const withProxy = markProxyOnlyTools(permissions, narrowBound, permitted);
90
- // Simulate a provider cap displacing tools.
91
- const withCap = withProxy.map((t) =>
92
- t.name === "web_search"
93
- ? { ...t, permission: "disabled" as const, permission_reason: "provider_tool_limit" }
94
- : t);
95
-
96
- const base = {
97
- trimmedMessage: "check my unread mail",
98
- budget,
99
- recallCtx: "",
100
- warmSummaryCtx: "",
101
- factsCtx: "",
102
- delegateRosterLines: [],
103
- runtimeInstanceId: "verify-instance",
104
- usageStrategyInstruction: getUsageStrategyProfile("cost_saving").promptInstruction,
105
- systemSignals: [{
106
- seq: 1, id: "verify-signal", kind: "runtime.restart.completed" as const, schema_version: 1,
107
- operation_id: "verify-operation", agent_id: cfg.id, thread_id: "verify-thread",
108
- payload: '{"restarted":true,"protected_state_available":true}', created_at: 1,
109
- }],
110
- };
111
-
112
- const expectedFor = (map: readonly { permission?: string; permission_reason?: string | null }[]) => {
113
- const reachable = new Set(["proxy_only", "provider_tool_limit"]);
114
- return {
115
- bound: map.filter((t) => t.permission === "enabled").length,
116
- proxy: map.filter((t) => t.permission_reason && reachable.has(t.permission_reason)).length,
117
- denied: map.filter((t) =>
118
- t.permission === "disabled" && !(t.permission_reason && reachable.has(t.permission_reason))).length,
119
- unavailable: map.filter((t) => t.permission === "unavailable").length,
120
- };
121
- };
122
-
123
- return [
124
- {
125
- id: "minimal-agent",
126
- prompt: buildSystemPrompt({ ...base, agentCfg: agentCfg(), experienceMode: "essential" }),
127
- },
128
- {
129
- id: "pinned-tools-all-bound",
130
- prompt: buildSystemPrompt({
131
- ...base,
132
- agentCfg: cfg,
133
- experienceMode: "full",
134
- allowedTools: permitted,
135
- toolPermissionMap: allBound,
136
- }),
137
- expected: expectedFor(allBound),
138
- },
139
- {
140
- id: "proxy-only-and-provider-cap",
141
- prompt: buildSystemPrompt({
142
- ...base,
143
- agentCfg: cfg,
144
- experienceMode: "full",
145
- allowedTools: narrowBound,
146
- toolPermissionMap: withCap,
147
- }),
148
- expected: expectedFor(withCap),
149
- },
150
- {
151
- id: "delivery-channel",
152
- prompt: buildSystemPrompt({
153
- ...base,
154
- agentCfg: cfg,
155
- experienceMode: "full",
156
- deliveryChannel: { kind: "whatsapp" },
157
- allowedTools: permitted,
158
- toolPermissionMap: allBound,
159
- }),
160
- expected: expectedFor(allBound),
161
- },
162
- ];
163
- }
27
+ const { agentCfg, budget, buildVariants } = await import("./prompt-variants");
164
28
 
165
29
  const variants = await buildVariants();
166
30
  const staticPrompts = listStaticPrompts();
@@ -198,7 +62,7 @@ if (process.env.JARELA_PROMPT_DUMP === "1") {
198
62
  ...variants.map((v) => `- \`system-prompt.${v.id}.txt\` (${v.prompt.length} chars)`),
199
63
  "",
200
64
  "## Static prompts",
201
- ...staticPrompts.map((p) => `- \`static.${p.id}.txt\` — ${p.purpose}`),
65
+ ...staticPrompts.map((p) => `- \`static.${p.id}.txt\` — ${p.purpose}`),
202
66
  ].join("\n"),
203
67
  "utf8",
204
68
  );
@@ -267,6 +131,7 @@ describe("prompt registry coverage", () => {
267
131
  "lib/agents/citation-checker.ts",
268
132
  "lib/agents/hallucination-classifier.ts",
269
133
  "lib/agents/conversation-summary.ts",
134
+ "lib/agents/compaction-pipeline.ts",
270
135
  "lib/pricing/llm-extract.ts",
271
136
  "lib/tools/claude-delegate.ts",
272
137
  "lib/agents/prepare/system-prompt.ts",
@@ -16,7 +16,9 @@ import { DESIGN_QA_PROMPT } from "@/lib/tools/delegation/claude-delegate";
16
16
  import { buildSharedToolCatalogContext } from "@/lib/agents/prepare/system-prompt";
17
17
  import { BUILTIN_HARNESSES } from "@/lib/agents/harness/presets";
18
18
  import { SYSTEM_SIGNAL_WAKE_PROMPT } from "@/lib/lifecycle/system-signals";
19
- import { buildConversationSummaryMessages } from "@/lib/agents/conversation-summary";
19
+ import { buildConversationSummaryMessages, type SummaryTopicSegment } from "@/lib/agents/conversation-summary";
20
+ import { buildTopicGroupingMessages, buildTopicRecapMessages } from "@/lib/agents/compaction-pipeline";
21
+ import type { ProviderMessage } from "@/lib/providers/types";
20
22
 
21
23
  export interface StaticPrompt {
22
24
  id: string;
@@ -36,6 +38,24 @@ export function listStaticPrompts(): StaticPrompt[] {
36
38
  const conversationSummary = buildConversationSummaryMessages(
37
39
  "[seq=42] [2026-10-09T10:00:00.000Z] User: Example transcript row.",
38
40
  ).map((message) => `${message.role.toUpperCase()}\n${typeof message.content === "string" ? message.content : JSON.stringify(message.content)}`).join("\n\n");
41
+ const renderMessages = (messages: ProviderMessage[]) => messages
42
+ .map((message) => `${message.role.toUpperCase()}\n${typeof message.content === "string" ? message.content : JSON.stringify(message.content)}`)
43
+ .join("\n\n");
44
+ const sampleTopic: SummaryTopicSegment = {
45
+ title: "Example earlier topic",
46
+ start_seq: 40,
47
+ end_seq: 44,
48
+ start_at: "2026-10-09T10:00:00.000Z",
49
+ end_at: "2026-10-09T10:05:00.000Z",
50
+ recap: "Example recap of the earlier topic.",
51
+ facts: [{ subject: "Example preference", content: "The user prefers examples.", tags: [], confidence: "explicit", key: "facts/example-preference" }],
52
+ message_count: 4,
53
+ };
54
+ const sampleNewMessages = "[seq=50] [2026-10-09T11:00:00.000Z] User: Example newer message.\n\n[seq=51] [2026-10-09T11:00:05.000Z] Assistant: Example reply.";
55
+ const compactionGroup = renderMessages(buildTopicGroupingMessages(sampleNewMessages, [sampleTopic]));
56
+ const compactionRecap = renderMessages(buildTopicRecapMessages({ title: sampleTopic.title, continues: "t1", seqs: [50, 51] }, sampleTopic, sampleNewMessages));
57
+ const channelGroup = renderMessages(buildTopicGroupingMessages(sampleNewMessages, [sampleTopic], "scheduled_task"));
58
+ const channelRecap = renderMessages(buildTopicRecapMessages({ title: sampleTopic.title, continues: "t1", seqs: [50, 51] }, sampleTopic, sampleNewMessages, "scheduled_task"));
39
59
  const prompts: StaticPrompt[] = [
40
60
  {
41
61
  id: "agent.system-signal-wakeup",
@@ -55,6 +75,30 @@ export function listStaticPrompts(): StaticPrompt[] {
55
75
  purpose: "Compress warm chat context while preserving source seq boundaries for topic alignment.",
56
76
  text: conversationSummary,
57
77
  },
78
+ {
79
+ id: "agent.compaction-group",
80
+ source: "lib/agents/compaction-pipeline.ts",
81
+ purpose: "Compaction step 1: group newly aged-out messages into topics, each new or continuing a stored warm topic.",
82
+ text: compactionGroup,
83
+ },
84
+ {
85
+ id: "agent.compaction-topic-recap",
86
+ source: "lib/agents/compaction-pipeline.ts",
87
+ purpose: "Compaction step 2: recap one topic, newest detail first, merging its stored recap and listing durable facts.",
88
+ text: compactionRecap,
89
+ },
90
+ {
91
+ id: "agent.compaction-group-automation",
92
+ source: "lib/agents/compaction-pipeline.ts",
93
+ purpose: "Compaction step 1 for an automation channel (scheduled_task shown; watcher and bridge differ only in wording).",
94
+ text: channelGroup,
95
+ },
96
+ {
97
+ id: "agent.compaction-topic-recap-automation",
98
+ source: "lib/agents/compaction-pipeline.ts",
99
+ purpose: "Compaction step 2 for an automation channel (scheduled_task shown); recap focuses on runs, outcomes and failures.",
100
+ text: channelRecap,
101
+ },
58
102
  {
59
103
  id: "audit.citation-checker",
60
104
  source: "lib/agents/citation-checker.ts",
@@ -0,0 +1,146 @@
1
+ /**
2
+ * Deterministic agent system prompt variants used to verify prompts
3
+ * (prompt-registry.test.ts) and to snapshot the prompt surface for release
4
+ * changesets (lib/lifecycle/surface-collect.ts). Callers must set
5
+ * JARELA_DB_DIR to a scratch directory before importing this module.
6
+ */
7
+ import { buildSystemPrompt } from "./prepare/system-prompt";
8
+ import { getUsageStrategyProfile } from "./usage-strategy";
9
+ import { getAllToolCatalogAsync, applyAgentPermissionsToCatalog, markProxyOnlyTools } from "@/lib/tools";
10
+ import type { AgentConfigRow } from "@/lib/stores/agent-configs";
11
+ import type { ContextBudget } from "@/lib/agents/context-budget";
12
+ export const budget: ContextBudget = {
13
+ contextWindowTokens: 200000,
14
+ outputReserveTokens: 8000,
15
+ inputBudgetTokens: 120000,
16
+ overheadTokens: 4000,
17
+ tierPriority: ["hot", "warm", "facts"],
18
+ tierBudgets: { hot: 60000, warm: 40000, facts: 20000 },
19
+ };
20
+
21
+ export function agentCfg(overrides: Partial<AgentConfigRow> = {}): AgentConfigRow {
22
+ return {
23
+ id: "verify-agent",
24
+ name: "Verify",
25
+ icon: null,
26
+ identity: "You are Jarela, a local assistant.",
27
+ instructions: "Be terse.",
28
+ tools: "[]",
29
+ model_config_name: null,
30
+ is_default: 1,
31
+ history_limit: 50,
32
+ history_window_hours: 8,
33
+ never_reply: 0,
34
+ adaptive_persona_enabled: 0,
35
+ adaptive_persona_strength: 0,
36
+ adaptive_empathy: 50,
37
+ adaptive_expressiveness: 50,
38
+ adaptive_verbosity: 50,
39
+ adaptive_mbti: "INTJ",
40
+ voice_enabled: 0,
41
+ voice_model: "",
42
+ voice_name: "",
43
+ voice_stt_model: "",
44
+ voice_auto_speak: 0,
45
+ display_filters: null,
46
+ harness_id: null,
47
+ delegate_targets: null,
48
+ context_tier_proportions: null,
49
+ anti_hallucination_mode: null,
50
+ ...overrides,
51
+ } as AgentConfigRow;
52
+ }
53
+
54
+ export interface Variant {
55
+ id: string;
56
+ prompt: string;
57
+ /** Counts derived from the permission map, to check the prompt's own arithmetic. */
58
+ expected?: { bound: number; proxy: number; denied: number; unavailable: number };
59
+ }
60
+
61
+ export async function buildVariants(): Promise<Variant[]> {
62
+ const catalog = await getAllToolCatalogAsync();
63
+ const pinned = ["gmail_search", "gmail_send_email"];
64
+ const cfg = agentCfg({ tools: JSON.stringify(pinned) });
65
+ const permissions = applyAgentPermissionsToCatalog(catalog, cfg);
66
+ const permitted = permissions.filter((t) => t.permission === "enabled").map((t) => t.name);
67
+
68
+ // Bind everything permitted: no proxy_only, the common case today.
69
+ const allBound = markProxyOnlyTools(permissions, permitted, permitted);
70
+ // Bind only the self-config tools so the rest becomes proxy_only.
71
+ const narrowBound = permitted.filter((n) => n === "invoke_tool" || n === "list_tools");
72
+ const withProxy = markProxyOnlyTools(permissions, narrowBound, permitted);
73
+ // Simulate a provider cap displacing tools.
74
+ const withCap = withProxy.map((t) =>
75
+ t.name === "web_search"
76
+ ? { ...t, permission: "disabled" as const, permission_reason: "provider_tool_limit" }
77
+ : t);
78
+
79
+ const base = {
80
+ trimmedMessage: "check my unread mail",
81
+ budget,
82
+ recallCtx: "",
83
+ warmSummaryCtx: "",
84
+ factsCtx: "",
85
+ delegateRosterLines: [],
86
+ runtimeInstanceId: "verify-instance",
87
+ usageStrategyInstruction: getUsageStrategyProfile("cost_saving").promptInstruction,
88
+ systemSignals: [{
89
+ seq: 1, id: "verify-signal", kind: "runtime.restart.completed" as const, schema_version: 1,
90
+ operation_id: "verify-operation", agent_id: cfg.id, thread_id: "verify-thread",
91
+ payload: '{"restarted":true,"protected_state_available":true}', created_at: 1,
92
+ }],
93
+ };
94
+
95
+ const expectedFor = (map: readonly { permission?: string; permission_reason?: string | null }[]) => {
96
+ const reachable = new Set(["proxy_only", "provider_tool_limit"]);
97
+ return {
98
+ bound: map.filter((t) => t.permission === "enabled").length,
99
+ proxy: map.filter((t) => t.permission_reason && reachable.has(t.permission_reason)).length,
100
+ denied: map.filter((t) =>
101
+ t.permission === "disabled" && !(t.permission_reason && reachable.has(t.permission_reason))).length,
102
+ unavailable: map.filter((t) => t.permission === "unavailable").length,
103
+ };
104
+ };
105
+
106
+ return [
107
+ {
108
+ id: "minimal-agent",
109
+ prompt: buildSystemPrompt({ ...base, agentCfg: agentCfg(), experienceMode: "essential" }),
110
+ },
111
+ {
112
+ id: "pinned-tools-all-bound",
113
+ prompt: buildSystemPrompt({
114
+ ...base,
115
+ agentCfg: cfg,
116
+ experienceMode: "full",
117
+ allowedTools: permitted,
118
+ toolPermissionMap: allBound,
119
+ }),
120
+ expected: expectedFor(allBound),
121
+ },
122
+ {
123
+ id: "proxy-only-and-provider-cap",
124
+ prompt: buildSystemPrompt({
125
+ ...base,
126
+ agentCfg: cfg,
127
+ experienceMode: "full",
128
+ allowedTools: narrowBound,
129
+ toolPermissionMap: withCap,
130
+ }),
131
+ expected: expectedFor(withCap),
132
+ },
133
+ {
134
+ id: "delivery-channel",
135
+ prompt: buildSystemPrompt({
136
+ ...base,
137
+ agentCfg: cfg,
138
+ experienceMode: "full",
139
+ deliveryChannel: { kind: "whatsapp" },
140
+ allowedTools: permitted,
141
+ toolPermissionMap: allBound,
142
+ }),
143
+ expected: expectedFor(allBound),
144
+ },
145
+ ];
146
+ }
@@ -406,3 +406,25 @@ describe("steering queue (ADR-0080)", () => {
406
406
  finishRun(run, "done");
407
407
  });
408
408
  });
409
+
410
+ describe("run-registry phase", () => {
411
+ it("tracks what the run is doing from the broadcast chunks", () => {
412
+ const tid = `t-phase-${Date.now()}`;
413
+ const run = startRun(tid, null);
414
+ expect([run.phase, run.phase_label]).toEqual(["starting", "Starting…"]);
415
+ broadcast(run, { type: "status", data: { phase: "compacting", label: "Compacting earlier messages…" } });
416
+ expect([run.phase, run.phase_label]).toEqual(["compacting", "Compacting earlier messages…"]);
417
+ broadcast(run, { type: "thinking_delta", data: { delta: "hm" } });
418
+ expect(run.phase).toBe("thinking");
419
+ broadcast(run, { type: "tool_call", data: { id: "c1", name: "web_search", args: {} } });
420
+ expect([run.phase, run.phase_label]).toEqual(["tool", "Using web_search…"]);
421
+ // Reasoning between parallel tool calls must not hide the running tool.
422
+ broadcast(run, { type: "thinking_delta", data: { delta: "…" } });
423
+ expect(run.phase).toBe("tool");
424
+ broadcast(run, { type: "tool_result", data: { id: "c1", result: "ok" } });
425
+ expect([run.phase, run.phase_label]).toEqual(["thinking", "Thinking…"]);
426
+ broadcast(run, { type: "text_delta", data: { delta: "Hi" } });
427
+ expect([run.phase, run.phase_label]).toEqual(["responding", "Responding…"]);
428
+ finishRun(run, "done");
429
+ });
430
+ });
@@ -64,6 +64,11 @@ export interface ActiveRun {
64
64
  // by the agent's preModelHook before the next model call, so steering
65
65
  // reaches the model together with the tool results it should react to.
66
66
  steering: string[];
67
+ // What the run is doing right now ("preparing", "compacting", "thinking",
68
+ // "responding", "tool"), with the label the chat shows for it. Lets a
69
+ // client that is not attached to the stream still report the activity.
70
+ phase: string;
71
+ phase_label: string;
67
72
  }
68
73
 
69
74
  const registryState = getOrCreateGlobal("__jarela_active_run_registry", () => ({
@@ -126,6 +131,8 @@ export function startRun(thread_id: string, agent_id: string | null): ActiveRun
126
131
  tool_started_at: new Map<string, number>(),
127
132
  tool_time_ms_done: 0,
128
133
  steering: [],
134
+ phase: "starting",
135
+ phase_label: "Starting…",
129
136
  };
130
137
  runs.set(thread_id, run);
131
138
  // Wake any GET subscribers that attached before the run was registered.
@@ -251,6 +258,27 @@ function scheduleMaxWatchdog(run: ActiveRun): void {
251
258
  }, fireIn).unref?.();
252
259
  }
253
260
 
261
+ // Mirrors the labels hooks/useSSE.ts derives from the same chunks.
262
+ function trackPhase(run: ActiveRun, chunk: StreamChunk): void {
263
+ const data = (chunk.data ?? {}) as { phase?: unknown; label?: unknown; name?: unknown; id?: unknown };
264
+ const set = (phase: string, label: string) => { run.phase = phase; run.phase_label = label; };
265
+ if (chunk.type === "status") {
266
+ const phase = typeof data.phase === "string" && data.phase ? data.phase : run.phase;
267
+ const label = typeof data.label === "string" && data.label.trim() ? data.label : "Thinking…";
268
+ set(phase, label);
269
+ } else if (chunk.type === "text_delta") {
270
+ set("responding", "Responding…");
271
+ } else if (chunk.type === "thinking_delta") {
272
+ if (run.inflight_tools.size === 0) set("thinking", "Thinking…");
273
+ } else if (chunk.type === "tool_call") {
274
+ const name = typeof data.name === "string" && data.name ? data.name : "tool";
275
+ set("tool", `Using ${name}…`);
276
+ } else if (chunk.type === "tool_result") {
277
+ const remaining = typeof data.id === "string" ? [...run.inflight_tools].filter((id) => id !== data.id) : [...run.inflight_tools];
278
+ if (remaining.length === 0) set("thinking", "Thinking…");
279
+ }
280
+ }
281
+
254
282
  export function broadcast(run: ActiveRun, chunk: StreamChunk): void {
255
283
  // Identity-check: a superseded run must not smear trailing chunks onto
256
284
  // the replacement entry in the registry.
@@ -263,6 +291,7 @@ export function broadcast(run: ActiveRun, chunk: StreamChunk): void {
263
291
  // buffer, don't fan out to subscribers, or the SSE wire would carry
264
292
  // meaningless tick events.
265
293
  if (chunk.type === "heartbeat") return;
294
+ trackPhase(run, chunk);
266
295
  if (chunk.type === "text_delta") {
267
296
  run.final_text += (chunk.data.delta as string) ?? "";
268
297
  } else if (chunk.type === "reset_text") {
@@ -918,4 +918,70 @@ describe("prepareThreadRun transient retry", () => {
918
918
  expect(chunkTypes).toContain("text_delta");
919
919
  expect(collected.assistantContent).toBe("I patched the file to fix the bug.");
920
920
  });
921
- });
921
+
922
+ describe("workflow step contract auto-retry", () => {
923
+ const done = (id: string): StreamChunk => ({
924
+ type: "done",
925
+ data: { message_id: id, usage: { input_tokens: 1, output_tokens: 1, source: "estimate" }, provider: "openai", model_id: "gpt-4o-mini", model_config_name: "default" },
926
+ });
927
+ const step = (status: string, evidence?: string) => ({
928
+ id: "run-tests", label: "Run tests", input: "Diff", output: "Results", validation: "Run the suite", status,
929
+ ...(evidence ? { validation_evidence: evidence } : {}),
930
+ });
931
+ const rejectedTurn = (n: number) => chunks(
932
+ { type: "tool_call", data: { id: `wf-${n}`, name: "workflow_progress", arguments: { workflow_id: "release_check", items: [step("done")] } } },
933
+ { type: "tool_result", data: { id: `wf-${n}`, name: "workflow_progress", result: JSON.stringify({ ok: false, workflow_id: "release_check", error: "Every completed workflow item requires observed validation_evidence." }) } },
934
+ { type: "text_delta", data: { delta: `Turn ${n}.` } },
935
+ done(`done-wf-${n}`),
936
+ );
937
+ const setup = async (agentId: string) => {
938
+ upsertModelConfig("default", "openai", "gpt-4o-mini", { api_key: "sk-test" }, true);
939
+ upsertAgentConfig({ id: agentId, name: "Workflow Agent", identity: "helper", instructions: "Be helpful.", tools: ["workflow_progress"], model_config_name: null });
940
+ const thread = createThread(agentId);
941
+ return prepareThreadRun({
942
+ thread_id: thread.thread_id,
943
+ message: "Check the release",
944
+ context_profile: { include_hot: true, include_warm: false, include_facts: false, include_recall: false },
945
+ });
946
+ };
947
+ const lastUserText = (callIndex: number) => {
948
+ const messages = streamWithConfigMock.mock.calls[callIndex][1] as Array<{ role?: string; content?: unknown }>;
949
+ return JSON.stringify(messages[messages.length - 1]);
950
+ };
951
+
952
+ it("retries a step whose update was rejected and stops once the contract is met", async () => {
953
+ streamWithConfigMock
954
+ .mockImplementationOnce(() => rejectedTurn(1))
955
+ .mockImplementationOnce(() => chunks(
956
+ { type: "tool_call", data: { id: "wf-2", name: "workflow_progress", arguments: { workflow_id: "release_check", items: [step("done", "npm test: 120 passed")] } } },
957
+ { type: "tool_result", data: { id: "wf-2", name: "workflow_progress", result: JSON.stringify({ ok: true, workflow_id: "release_check", state: { phase: null, summary: "", error: null, checklist: [step("done", "npm test: 120 passed")] } }) } },
958
+ { type: "text_delta", data: { delta: "Verified." } },
959
+ done("done-wf-2"),
960
+ ));
961
+
962
+ const collected = await collectStream((await setup("agent-workflow-retry")).stream);
963
+
964
+ expect(collected.terminal).toBe("done");
965
+ expect(streamWithConfigMock).toHaveBeenCalledTimes(2);
966
+ expect(lastUserText(1)).toContain("attempt 2 of 3");
967
+ expect(lastUserText(1)).toContain("Run tests");
968
+ expect(collected.assistantContent).toContain("Turn 1.");
969
+ expect(collected.assistantContent).toContain("Verified.");
970
+ });
971
+
972
+ it("gives up after three attempts and tells the user the step still fails", async () => {
973
+ streamWithConfigMock
974
+ .mockImplementationOnce(() => rejectedTurn(1))
975
+ .mockImplementationOnce(() => rejectedTurn(2))
976
+ .mockImplementationOnce(() => rejectedTurn(3))
977
+ .mockImplementationOnce(() => rejectedTurn(4));
978
+
979
+ const collected = await collectStream((await setup("agent-workflow-retry-exhausted")).stream);
980
+
981
+ expect(collected.terminal).toBe("done");
982
+ expect(streamWithConfigMock).toHaveBeenCalledTimes(3);
983
+ expect(lastUserText(2)).toContain("attempt 3 of 3");
984
+ expect(collected.assistantContent).toContain("still failing the step contract after automatic retries");
985
+ });
986
+ });
987
+ });