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