@desplega.ai/agent-swarm 2.4.3 → 2.4.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (270) hide show
  1. package/dist/{acp-adapter-1885dpr7.js → acp-adapter-2wdkktv6.js} +1 -2
  2. package/dist/{actions-pn76n32q.js → actions-c40ebcm4.js} +18 -18
  3. package/dist/{amp-adapter-af84rx1d.js → amp-adapter-wb67m95z.js} +2 -2
  4. package/dist/{app-6sv8mhzm.js → app-353vre8g.js} +3 -3
  5. package/dist/{assistant-sc2tf825.js → assistant-sj1njh23.js} +21 -21
  6. package/dist/{boot-reembed-y3m0ydzj.js → boot-reembed-b9c3az3c.js} +1 -1
  7. package/dist/{boot-reembed-gvxjs2py.js → boot-reembed-qdkvxeem.js} +1 -1
  8. package/dist/{boot-scrub-sweep-1j9mk05f.js → boot-scrub-sweep-m3wh8eks.js} +2 -2
  9. package/dist/{boot-seeds-37sp626b.js → boot-seeds-j2273s54.js} +4 -4
  10. package/dist/{claude-adapter-rp0jtnwr.js → claude-adapter-m7q0a085.js} +2 -2
  11. package/dist/{claude-managed-adapter-h2y889ge.js → claude-managed-adapter-5ptb6tzs.js} +2 -2
  12. package/dist/{claude-managed-setup-rdt248k7.js → claude-managed-setup-smrqk5j5.js} +3 -3
  13. package/dist/{claude-sdk-session-53rcw5we.js → claude-sdk-session-38xnz21e.js} +8284 -8267
  14. package/dist/{cli-6eyncg0y.js → cli-018r4jq6.js} +34 -6
  15. package/dist/{cli-sds5zzs8.js → cli-1f3qzw6y.js} +78 -12
  16. package/dist/{cli-f0p0f6ja.js → cli-1sp861s4.js} +7 -7
  17. package/dist/{cli-dm8p2dpf.js → cli-1syn2xy1.js} +10 -10
  18. package/dist/{cli-tkf4x6ha.js → cli-37j04k05.js} +11 -11
  19. package/dist/{cli-v87dr6e3.js → cli-3a45zcgm.js} +1 -1
  20. package/dist/{cli-1n9gdg56.js → cli-43x64hv3.js} +4 -4
  21. package/dist/{cli-p0qerd2r.js → cli-4zfqgjc5.js} +2 -2
  22. package/dist/{cli-aa3tb29r.js → cli-7c9qs530.js} +1 -1
  23. package/dist/{cli-9qtjfd60.js → cli-848hxdwj.js} +1 -1
  24. package/dist/{cli-1xsraagq.js → cli-94gwyg7m.js} +8 -8
  25. package/dist/{cli-0dxxwfkt.js → cli-9hstj09h.js} +17 -14
  26. package/dist/{cli-1012xb7j.js → cli-9yqgm9nd.js} +22 -22
  27. package/dist/{cli-pygdsgh8.js → cli-a92r1127.js} +1 -1
  28. package/dist/{cli-8vverzf7.js → cli-ba8ne1es.js} +5 -0
  29. package/dist/{cli-bxrqvpg5.js → cli-be2161h1.js} +7 -7
  30. package/dist/{cli-npfe9t1s.js → cli-bnes4z6b.js} +2 -2
  31. package/dist/{cli-aypbg9r2.js → cli-cxxe61f6.js} +1 -1
  32. package/dist/{cli-vq9gqarq.js → cli-dk44dxec.js} +1 -1
  33. package/dist/{cli-836ehxmt.js → cli-eww120g8.js} +3 -2
  34. package/dist/{cli-a0kcty51.js → cli-f01h25yt.js} +1 -1
  35. package/dist/{cli-mzkwkbdy.js → cli-f0g3pgvf.js} +1 -1
  36. package/dist/{cli-1ma335fz.js → cli-ftc1g5tj.js} +2 -2
  37. package/dist/{cli-4yef8ghv.js → cli-fv5hepyy.js} +3 -3
  38. package/dist/{cli-58vwn100.js → cli-g35m2xwm.js} +4 -4
  39. package/dist/{cli-qje9k2nh.js → cli-g9ypd5en.js} +12 -2
  40. package/dist/{cli-gx0j2khs.js → cli-j99azg3g.js} +3 -3
  41. package/dist/{cli-er83cjbn.js → cli-k8g16gz3.js} +416 -116
  42. package/dist/{cli-qp2m4btv.js → cli-kpw04va0.js} +2 -2
  43. package/dist/{cli-8y99kfey.js → cli-ms85309d.js} +33 -15
  44. package/dist/{cli-kgnkyabk.js → cli-n72rg53p.js} +1555 -645
  45. package/dist/{cli-e4d78xsv.js → cli-p14m2cnp.js} +1 -1
  46. package/dist/{cli-1eszr343.js → cli-qfxc84gh.js} +1 -1
  47. package/dist/{cli-wk28hzqn.js → cli-qwhy2qma.js} +1 -1
  48. package/dist/{cli-73ezfhha.js → cli-st8aw1m6.js} +228 -11
  49. package/dist/{cli-zvbb4n0e.js → cli-tw4p90jb.js} +92 -192
  50. package/dist/{cli-038fga5k.js → cli-v0yrfmdh.js} +148 -183
  51. package/dist/{cli-6aen3ezb.js → cli-v8fjakwf.js} +1 -1
  52. package/dist/{cli-99jez72r.js → cli-w9etnnxk.js} +6 -1
  53. package/dist/{cli-vcgscaan.js → cli-wt0jf9hm.js} +217 -80
  54. package/dist/{cli-s9rr4gr2.js → cli-xpa64rek.js} +1065 -305
  55. package/dist/{cli-h0mgxann.js → cli-z7d29rw9.js} +2 -2
  56. package/dist/cli.js +45 -20
  57. package/dist/{codex-adapter-2zrmab9b.js → codex-adapter-tn6k5mkg.js} +1 -1
  58. package/dist/{codex-session-runner-kbkz62vc.js → codex-session-runner-7vjt7jbw.js} +1 -1
  59. package/dist/{commands-hd574th6.js → commands-t7rz9146.js} +2 -2
  60. package/dist/{controller-pz5mcfg4.js → controller-m2jasma5.js} +2 -2
  61. package/dist/{controllers-connect-5rgq2hfk.js → controllers-connect-9ftpex99.js} +19 -19
  62. package/dist/{cursor-adapter-mgaprq0j.js → cursor-adapter-mjv79e4z.js} +1 -1
  63. package/dist/{db-6nf1207q.js → db-6sfrn9g3.js} +1 -1
  64. package/dist/{db-h06dxp05.js → db-rn673r06.js} +3 -3
  65. package/dist/{dispatcher-zthpy4m1.js → dispatcher-c155xz0p.js} +17 -17
  66. package/dist/{dsh-adapter-64dhw0j7.js → dsh-adapter-3mmszc1x.js} +1 -1
  67. package/dist/{external-channel-x01t7ke6.js → external-channel-35k6tkv8.js} +2 -2
  68. package/dist/{grok-adapter-h21jv594.js → grok-adapter-tfrq7tg1.js} +2 -3
  69. package/dist/handlers-7gw64dxw.js +39 -0
  70. package/dist/{heartbeat-zzfksckz.js → heartbeat-dyg4npkp.js} +20 -20
  71. package/dist/{hook-z4zhzj1f.js → hook-drspbwpe.js} +1 -1
  72. package/dist/{hook-3xfqhh2s.js → hook-x26b31bg.js} +1 -1
  73. package/dist/{http-q813tmya.js → http-pk972xyw.js} +571 -294
  74. package/dist/{index-va3y63es.js → index-6srwvd5b.js} +1 -2
  75. package/dist/{index-x8xbyn1t.js → index-arytgj5q.js} +1 -1
  76. package/dist/{index-wbbs14c5.js → index-bgdyvcnv.js} +17 -17
  77. package/dist/{index-s98037v0.js → index-cbxkmfc5.js} +1 -2
  78. package/dist/{index-c4ykd0f1.js → index-dr94zbnh.js} +13348 -11611
  79. package/dist/{index-m0a4ydqj.js → index-gabbcdn2.js} +17 -17
  80. package/dist/{index-220tk9bw.js → index-jwxkkex2.js} +139 -76
  81. package/dist/index-tfb26zhy.js +41 -0
  82. package/dist/{keepalive-y5t1my7m.js → keepalive-7yrng7px.js} +3 -3
  83. package/dist/{lead-2xwtq66b.js → lead-7e02z839.js} +29 -30
  84. package/dist/{maintenance-ybfsaedv.js → maintenance-e6cemdqt.js} +1 -1
  85. package/dist/{node-3v3f08f7.js → node-de6akczr.js} +10 -9
  86. package/dist/{oauth-refresh-sweep-909jmn12.js → oauth-refresh-sweep-yw3xdbcj.js} +2 -2
  87. package/dist/{onboard-xn6fkkys.js → onboard-0a9y5yrc.js} +2 -2
  88. package/dist/{otel-impl-e6mn0z13.js → otel-impl-trjpkfb7.js} +1 -1
  89. package/dist/{pricing-refresh-ygd362ep.js → pricing-refresh-d2b5my0y.js} +3 -3
  90. package/dist/{rbac-roles-mb470p4e.js → rbac-roles-hey3yv9d.js} +2 -2
  91. package/dist/{rbac-roles-c9axvfnz.js → rbac-roles-nxh5ahwk.js} +2 -2
  92. package/dist/{registry-rxw10xzg.js → registry-ajhexe44.js} +1 -1
  93. package/dist/{render-v2-g0306nh1.js → render-v2-rr3p2atg.js} +3 -3
  94. package/dist/{resume-v315hnq6.js → resume-2efkf1s1.js} +5 -5
  95. package/dist/{session-access-2zg285a1.js → session-access-s2mttxpw.js} +6 -4
  96. package/dist/{setup-a4mtf02k.js → setup-vypma5yt.js} +1 -1
  97. package/dist/{work-objects-9fr0fgtn.js → work-objects-rvhckdkp.js} +20 -20
  98. package/dist/{worker-qae22jeb.js → worker-5snytpbd.js} +29 -30
  99. package/dist/worker-token-xf11yyds.js +136 -0
  100. package/openapi.json +303 -13
  101. package/package.json +8 -8
  102. package/src/apps/action-runner.ts +4 -0
  103. package/src/apps/catalog.generated.json +209 -4
  104. package/src/apps/page-validator.ts +21 -3
  105. package/src/be/chunking.ts +42 -9
  106. package/src/be/db/tasks/draft-text.ts +15 -0
  107. package/src/be/db/tasks/read.ts +14 -1
  108. package/src/be/db.ts +5 -1
  109. package/src/be/memory/index-content.ts +36 -17
  110. package/src/be/memory/providers/openai-embedding.ts +115 -61
  111. package/src/be/memory/providers/sqlite-store.ts +69 -23
  112. package/src/be/memory/reranker.ts +31 -1
  113. package/src/be/memory/search-candidates.ts +47 -0
  114. package/src/be/memory/types.ts +14 -0
  115. package/src/be/migrations/232_agent_session_tokens.sql +41 -0
  116. package/src/be/scripts/typecheck.ts +2 -0
  117. package/src/be/seed-scripts/catalog/heartbeat-jev-gate.ts +116 -55
  118. package/src/be/seed-scripts/index.ts +2 -2
  119. package/src/be/swarm-config-guard.ts +40 -1
  120. package/src/be/task-attachment-store.ts +30 -0
  121. package/src/be/users.ts +169 -12
  122. package/src/cli.tsx +24 -0
  123. package/src/commands/worker-token.ts +164 -0
  124. package/src/extensions/catalog.generated.json +4 -4
  125. package/src/extensions/contract-types.generated.ts +1 -1
  126. package/src/extensions/contract.ts +7 -0
  127. package/src/fs/provider.ts +13 -1
  128. package/src/heartbeat/heartbeat.ts +31 -11
  129. package/src/http/apps.ts +43 -5
  130. package/src/http/codex-oauth-keep-warm.ts +27 -9
  131. package/src/http/config.ts +5 -3
  132. package/src/http/core.ts +2 -0
  133. package/src/http/fs.ts +54 -34
  134. package/src/http/mcp-body.ts +37 -0
  135. package/src/http/mcp-user.ts +3 -5
  136. package/src/http/mcp.ts +6 -7
  137. package/src/http/memory.ts +26 -15
  138. package/src/http/page-proxy.ts +61 -5
  139. package/src/http/pages-public.ts +27 -44
  140. package/src/http/pages.ts +4 -4
  141. package/src/http/script-runs.ts +2 -0
  142. package/src/http/session-access.ts +51 -2
  143. package/src/http/sessions.ts +249 -10
  144. package/src/http/tasks.ts +4 -32
  145. package/src/http/users.ts +12 -1
  146. package/src/integrations/chat-sdk/adapters.ts +7 -3
  147. package/src/integrations/chat-sdk/attachments.ts +90 -12
  148. package/src/integrations/chat-sdk/facts.ts +120 -0
  149. package/src/integrations/chat-sdk/inbound.ts +156 -8
  150. package/src/integrations/chat-sdk/limits.ts +24 -0
  151. package/src/integrations/chat-sdk/outbound-files.ts +186 -0
  152. package/src/integrations/chat-sdk/outbound.ts +234 -4
  153. package/src/integrations/chat-sdk/relay.ts +4 -1
  154. package/src/integrations/chat-sdk/router.ts +28 -2
  155. package/src/integrations/chat-sdk/steering.ts +9 -0
  156. package/src/integrations/chat-sdk/templates.ts +14 -0
  157. package/src/integrations/chat-sdk/thread-buffer.ts +4 -0
  158. package/src/mcp-limits.ts +20 -0
  159. package/src/pages/browser-sdk.ts +8 -3
  160. package/src/pages/feedback-overlay.ts +1 -1
  161. package/src/providers/acp-adapter.ts +33 -13
  162. package/src/providers/acp-swarm-events.ts +1 -1
  163. package/src/providers/amp-adapter.ts +1 -1
  164. package/src/providers/codex-adapter.ts +106 -119
  165. package/src/providers/codex-agents-md.ts +35 -229
  166. package/src/providers/codex-oauth/storage.ts +1 -1
  167. package/src/providers/cursor-adapter.ts +1 -1
  168. package/src/rbac/legacy-policy.ts +3 -1
  169. package/src/rbac/permissions.ts +4 -0
  170. package/src/realtime/transport.ts +1 -2
  171. package/src/script-workflows/workflow-ctx.ts +1 -0
  172. package/src/scripts-runtime/types/stdlib.d.ts +2 -0
  173. package/src/scripts-runtime/types/swarm-extension.d.ts +8 -0
  174. package/src/scripts-runtime/types/swarm-sdk.d.ts +2 -0
  175. package/src/server-user.ts +2 -0
  176. package/src/server.ts +2 -0
  177. package/src/slack/assistant.ts +2 -2
  178. package/src/slack/files.ts +2 -0
  179. package/src/slack/handlers.ts +4 -4
  180. package/src/slack/inbound-files.ts +39 -6
  181. package/src/slack/thread-buffer.ts +2 -1
  182. package/src/tasks/task-terminal-effects.ts +21 -17
  183. package/src/tests/acp-adapter.test.ts +10 -23
  184. package/src/tests/acp-fake-agent.ts +36 -0
  185. package/src/tests/acp-swarm-events.test.ts +1 -1
  186. package/src/tests/agent-session-tokens.test.ts +452 -0
  187. package/src/tests/apps-action-parent-task.test.ts +295 -0
  188. package/src/tests/apps-card-grid.test.ts +197 -0
  189. package/src/tests/apps-catalog-additions.test.ts +120 -0
  190. package/src/tests/apps-tree.test.ts +129 -0
  191. package/src/tests/chat-sdk-attachments-reply.test.ts +52 -0
  192. package/src/tests/chat-sdk-config.test.ts +11 -0
  193. package/src/tests/chat-sdk-facts.test.ts +23 -0
  194. package/src/tests/chat-sdk-inbound.test.ts +558 -4
  195. package/src/tests/chat-sdk-outbound-files.test.ts +652 -0
  196. package/src/tests/codex-adapter.test.ts +167 -242
  197. package/src/tests/codex-oauth-keep-warm.test.ts +85 -1
  198. package/src/tests/config-api-only-keys.test.ts +9 -0
  199. package/src/tests/config-session-auth.test.ts +14 -0
  200. package/src/tests/cors-allowlist.test.ts +1 -1
  201. package/src/tests/docs-index-footprint.test.js +2 -2
  202. package/src/tests/extensions-example-slack-reply-gate.test.ts +262 -91
  203. package/src/tests/grok-adapter.test.ts +3 -3
  204. package/src/tests/heartbeat-checklist.test.ts +33 -0
  205. package/src/tests/heartbeat-jev-gate-credentials.test.ts +44 -0
  206. package/src/tests/heartbeat-jev-gate.test.ts +265 -1
  207. package/src/tests/kv-page-proxy.test.ts +91 -5
  208. package/src/tests/launch-password-rejection.test.ts +2 -2
  209. package/src/tests/mcp-input-caps.test.ts +294 -0
  210. package/src/tests/memory-chunked-search-starvation.test.ts +200 -0
  211. package/src/tests/memory-embedding-input-cap.test.ts +114 -0
  212. package/src/tests/memory.test.ts +14 -0
  213. package/src/tests/migration-232-agent-session-tokens.test.ts +67 -0
  214. package/src/tests/page-guest-session.test.ts +19 -8
  215. package/src/tests/page-proxy-authed.test.ts +1 -1
  216. package/src/tests/page-proxy.test.ts +17 -10
  217. package/src/tests/page-session.test.ts +102 -1
  218. package/src/tests/pages-authed-mode.test.ts +82 -12
  219. package/src/tests/pages-password-mode.test.ts +5 -5
  220. package/src/tests/rbac-engine.test.ts +1 -0
  221. package/src/tests/realtime-transport.test.ts +13 -7
  222. package/src/tests/runtime-child-token-cleanup.test.ts +3 -3
  223. package/src/tests/script-connections.test.ts +2 -0
  224. package/src/tests/script-runs-http.test.ts +84 -0
  225. package/src/tests/scripts-http.test.ts +10 -1
  226. package/src/tests/session-route-posture.test.ts +2 -0
  227. package/src/tests/swarm-config-export-to-env.test.ts +22 -3
  228. package/src/tests/task-audio-transcription.test.ts +299 -0
  229. package/src/tests/task-completion-memory-chunking.test.ts +434 -0
  230. package/src/tests/task-terminal-secret-scrub.test.ts +6 -1
  231. package/src/tests/transcription.test.ts +299 -0
  232. package/src/tests/worker-token-cli.test.ts +76 -0
  233. package/src/tests/workflow-executors.test.ts +4 -2
  234. package/src/tests/workflow-system-one-decision-providers.test.ts +98 -1
  235. package/src/tests/workflow-system-one-decision.test.ts +2 -1
  236. package/src/tests/workflow-system-one-extraction.test.ts +805 -0
  237. package/src/tools/chat-access.ts +10 -0
  238. package/src/tools/chat-post.ts +31 -11
  239. package/src/tools/chat-reply.ts +32 -10
  240. package/src/tools/memory-search.ts +3 -1
  241. package/src/tools/system-one-decide.ts +17 -4
  242. package/src/types.ts +8 -1
  243. package/src/utils/config-env-export.ts +3 -1
  244. package/src/utils/page-session.ts +133 -20
  245. package/src/utils/request-auth-context.ts +2 -1
  246. package/src/utils/transcription.ts +246 -0
  247. package/src/workflows/definition.ts +7 -1
  248. package/src/workflows/engine.ts +18 -12
  249. package/src/workflows/executors/index.ts +1 -0
  250. package/src/workflows/executors/registry.ts +2 -0
  251. package/src/workflows/executors/system-one-decision.ts +84 -262
  252. package/src/workflows/executors/system-one-extract-wire.ts +57 -0
  253. package/src/workflows/executors/system-one-extraction.ts +830 -0
  254. package/src/workflows/executors/system-one-providers.ts +316 -114
  255. package/src/workflows/executors/system-one-transport.ts +264 -0
  256. package/templates/extensions/slack-reply-gate/README.md +24 -22
  257. package/templates/extensions/slack-reply-gate/hooks.ts +146 -95
  258. package/templates/extensions/slack-reply-gate/manifest.json +2 -2
  259. package/templates/official/lead/HEARTBEAT.md +1 -1
  260. package/templates/skills/apps/SKILL.md +31 -7
  261. package/templates/skills/apps/content.md +31 -7
  262. package/templates/skills/chat-sdk/content.md +6 -2
  263. package/templates/skills/code-quality/content.md +2 -1
  264. package/templates/skills/heartbeat-runbook/content.md +8 -8
  265. package/templates/skills/pages/content.md +6 -4
  266. package/templates/skills/swarm-scripts/SKILL.md +2 -2
  267. package/templates/skills/swarm-scripts/content.md +2 -2
  268. package/dist/cli-v1sjhn52.js +0 -7
  269. package/dist/handlers-2qjw434w.js +0 -39
  270. package/dist/index-d0g18bax.js +0 -41
@@ -155,6 +155,8 @@ import {
155
155
  computeScore,
156
156
  rerank,
157
157
  init_reranker,
158
+ searchMemoryCandidates,
159
+ init_search_candidates,
158
160
  rowToCandidate,
159
161
  init_sqlite_store,
160
162
  getEmbeddingProvider2,
@@ -332,19 +334,19 @@ import {
332
334
  recordInlineScriptRun2,
333
335
  exports_db,
334
336
  init_db3
335
- } from "./cli-vcgscaan.js";
337
+ } from "./cli-wt0jf9hm.js";
336
338
  import {
337
339
  getUserGrant2,
338
340
  init_rbac_roles
339
- } from "./cli-qp2m4btv.js";
341
+ } from "./cli-kpw04va0.js";
340
342
  import {
341
343
  ensurePricingSeeded2,
342
344
  ensureRbacSeeded2,
343
345
  ensureModelProfilesSeeded2
344
- } from "./cli-1n9gdg56.js";
346
+ } from "./cli-43x64hv3.js";
345
347
  import {
346
348
  loadModelsDevCache
347
- } from "./cli-vq9gqarq.js";
349
+ } from "./cli-dk44dxec.js";
348
350
  import {
349
351
  buildCatalogEntries,
350
352
  listModelCatalog,
@@ -354,12 +356,12 @@ import {
354
356
  loadModelsCatalog,
355
357
  requestModelCatalogRefresh2,
356
358
  startPricingRefreshLoop2
357
- } from "./cli-npfe9t1s.js";
359
+ } from "./cli-bnes4z6b.js";
358
360
  import {
359
361
  ampPinProviderError,
360
362
  ampPinCatalogError,
361
363
  ampModelError
362
- } from "./cli-1eszr343.js";
364
+ } from "./cli-qfxc84gh.js";
363
365
  import {
364
366
  notifyAutomationPreflightFailure,
365
367
  isNeedsSetupFailure,
@@ -411,7 +413,7 @@ import {
411
413
  buildNodeInterpolationCtx,
412
414
  interpolateNodeConfig,
413
415
  scriptBodyInterpolationError
414
- } from "./cli-0dxxwfkt.js";
416
+ } from "./cli-9hstj09h.js";
415
417
  import {
416
418
  require_dist2,
417
419
  publicEndpointSsrfOptions,
@@ -471,14 +473,14 @@ import {
471
473
  deleteApp,
472
474
  typecheckScript,
473
475
  parseSkillContent
474
- } from "./cli-73ezfhha.js";
476
+ } from "./cli-st8aw1m6.js";
475
477
  import {
476
478
  buildAuthorizationUrl,
477
479
  onAuthorizationRefreshed,
478
480
  ensureAuthorizationTokenOrThrow,
479
481
  ensureToken,
480
482
  ensureTokenOrThrow
481
- } from "./cli-pygdsgh8.js";
483
+ } from "./cli-a92r1127.js";
482
484
  import {
483
485
  detachedProcessGroup,
484
486
  registerProcessGroup,
@@ -508,14 +510,14 @@ import {
508
510
  getSlackApp2,
509
511
  startSlackApp2,
510
512
  stopSlackApp2
511
- } from "./cli-tkf4x6ha.js";
513
+ } from "./cli-37j04k05.js";
512
514
  import {
513
515
  slackCode,
514
516
  slackMissingScopeMessage,
515
517
  withAutoJoin,
516
518
  externalChannelToolError2,
517
519
  getChannelBlockReason2
518
- } from "./cli-v87dr6e3.js";
520
+ } from "./cli-3a45zcgm.js";
519
521
  import {
520
522
  BaseExecutor,
521
523
  postApprovalCancellationUpdates,
@@ -523,6 +525,7 @@ import {
523
525
  HumanInTheLoopExecutor,
524
526
  resolveWorkflowLlmConfig,
525
527
  SYSTEM_ONE_PROVIDER_IDS,
528
+ SystemOneExtractionExecutor,
526
529
  SYSTEM_ONE_DECISION_NODE_TYPE,
527
530
  SystemOneDecisionConfigSchema,
528
531
  SystemOneDecisionExecutor,
@@ -532,7 +535,7 @@ import {
532
535
  definitionNodeIds,
533
536
  validateDefinition,
534
537
  applyDefinitionPatch
535
- } from "./cli-s9rr4gr2.js";
538
+ } from "./cli-xpa64rek.js";
536
539
  import {
537
540
  workflowEventBus2,
538
541
  init_event_bus
@@ -554,26 +557,30 @@ import {
554
557
  SESSION_READ_DENIED2,
555
558
  canReadSession2,
556
559
  readableByFor2,
560
+ denyParentAttach2,
557
561
  pathSessionDenial2,
558
562
  userAgentIdentityDenial2,
559
563
  runtimeInstanceHeader,
564
+ bodyTask,
560
565
  routeRegistry,
561
566
  isPublicRoute,
562
567
  findRoute,
563
568
  route
564
- } from "./cli-6eyncg0y.js";
569
+ } from "./cli-018r4jq6.js";
565
570
  import {
566
571
  isMultiRuntimeEnabled
567
572
  } from "./cli-e8xyjvfc.js";
568
573
  import {
574
+ FilesError,
569
575
  providerPath,
576
+ normalizeStoredKey,
570
577
  AgentFsProvider,
571
578
  getFileStorageProvider2
572
- } from "./cli-qje9k2nh.js";
579
+ } from "./cli-g9ypd5en.js";
573
580
  import {
574
581
  getRuntimePool2,
575
582
  init_db
576
- } from "./cli-gx0j2khs.js";
583
+ } from "./cli-j99azg3g.js";
577
584
  import {
578
585
  getMemoryRaterNames,
579
586
  REFERENCES_SOURCE_MAX_LENGTH,
@@ -614,7 +621,7 @@ import {
614
621
  resolveSessionToken,
615
622
  fingerprintApiKey,
616
623
  init_users
617
- } from "./cli-sds5zzs8.js";
624
+ } from "./cli-1f3qzw6y.js";
618
625
  import {
619
626
  isRbacEnabled,
620
627
  decideAdmission,
@@ -623,7 +630,7 @@ import {
623
630
  init_elevated_agents,
624
631
  can,
625
632
  init_rbac
626
- } from "./cli-8vverzf7.js";
633
+ } from "./cli-ba8ne1es.js";
627
634
  import {
628
635
  normalizeAssetKey,
629
636
  parseAssetKey,
@@ -683,7 +690,7 @@ import {
683
690
  KvNamespaceSchema,
684
691
  KvKeySchema,
685
692
  init_types
686
- } from "./cli-836ehxmt.js";
693
+ } from "./cli-eww120g8.js";
687
694
  import {
688
695
  generateDefaultClaudeMd2,
689
696
  generateDefaultSoulMd2,
@@ -754,7 +761,7 @@ import {
754
761
  import {
755
762
  init_package,
756
763
  package_default
757
- } from "./cli-1xsraagq.js";
764
+ } from "./cli-94gwyg7m.js";
758
765
  import {
759
766
  realtimeBus,
760
767
  init_bus
@@ -783,6 +790,7 @@ import {
783
790
  import {
784
791
  scrubSecrets,
785
792
  scrubObject,
793
+ createValueScrubber,
786
794
  refreshSecretScrubberCache,
787
795
  registerVolatileSecret,
788
796
  registerSensitiveKeyName,
@@ -16806,6 +16814,9 @@ class Protocol {
16806
16814
  this.setRequestHandler(GetTaskPayloadRequestSchema, async (request, extra) => {
16807
16815
  const handleTaskResult = async () => {
16808
16816
  const taskId = request.params.taskId;
16817
+ if (!await this._taskStore.getTask(taskId, extra.sessionId)) {
16818
+ throw new McpError(ErrorCode.InvalidParams, `Task not found: ${taskId}`);
16819
+ }
16809
16820
  if (this._taskMessageQueue) {
16810
16821
  let queuedMessage;
16811
16822
  while (queuedMessage = await this._taskMessageQueue.dequeue(taskId, extra.sessionId)) {
@@ -16836,12 +16847,12 @@ class Protocol {
16836
16847
  throw new McpError(ErrorCode.InvalidParams, `Task not found: ${taskId}`);
16837
16848
  }
16838
16849
  if (!isTerminal(task.status)) {
16839
- await this._waitForTaskUpdate(taskId, extra.signal);
16850
+ await this._waitForTaskUpdate(taskId, extra.signal, extra.sessionId);
16840
16851
  return await handleTaskResult();
16841
16852
  }
16842
16853
  if (isTerminal(task.status)) {
16843
16854
  const result = await this._taskStore.getTaskResult(taskId, extra.sessionId);
16844
- this._clearTaskQueue(taskId);
16855
+ this._clearTaskQueue(taskId, extra.sessionId);
16845
16856
  return {
16846
16857
  ...result,
16847
16858
  _meta: {
@@ -16878,7 +16889,7 @@ class Protocol {
16878
16889
  throw new McpError(ErrorCode.InvalidParams, `Cannot cancel task in terminal status: ${task.status}`);
16879
16890
  }
16880
16891
  await this._taskStore.updateTaskStatus(request.params.taskId, "cancelled", "Client cancelled task execution.", extra.sessionId);
16881
- this._clearTaskQueue(request.params.taskId);
16892
+ this._clearTaskQueue(request.params.taskId, extra.sessionId);
16882
16893
  const cancelledTask = await this._taskStore.getTask(request.params.taskId, extra.sessionId);
16883
16894
  if (!cancelledTask) {
16884
16895
  throw new McpError(ErrorCode.InvalidParams, `Task not found after cancellation: ${request.params.taskId}`);
@@ -17001,6 +17012,19 @@ class Protocol {
17001
17012
  const handler = this._requestHandlers.get(request.method) ?? this.fallbackRequestHandler;
17002
17013
  const capturedTransport = this._transport;
17003
17014
  const relatedTaskId = request.params?._meta?.[RELATED_TASK_META_KEY]?.taskId;
17015
+ const sessionId = capturedTransport?.sessionId;
17016
+ const store = this._taskStore;
17017
+ let relatedTaskFound = true;
17018
+ let relatedTaskLookup;
17019
+ if (relatedTaskId && store && this._taskMessageQueue && sessionId !== undefined) {
17020
+ relatedTaskFound = false;
17021
+ relatedTaskLookup = (async () => {
17022
+ if (!await store.getTask(relatedTaskId, sessionId)) {
17023
+ throw new McpError(ErrorCode.InvalidParams, `Task not found: ${relatedTaskId}`);
17024
+ }
17025
+ relatedTaskFound = true;
17026
+ })();
17027
+ }
17004
17028
  if (handler === undefined) {
17005
17029
  const errorResponse = {
17006
17030
  jsonrpc: "2.0",
@@ -17010,7 +17034,10 @@ class Protocol {
17010
17034
  message: "Method not found"
17011
17035
  }
17012
17036
  };
17013
- if (relatedTaskId && this._taskMessageQueue) {
17037
+ if (relatedTaskId && relatedTaskLookup) {
17038
+ const queuedError = { type: "error", message: errorResponse, timestamp: Date.now() };
17039
+ relatedTaskLookup.then(() => this._enqueueTaskMessage(relatedTaskId, queuedError, sessionId), () => capturedTransport?.send(errorResponse)).catch((error) => this._onerror(new Error(`Failed to send an error response: ${error}`)));
17040
+ } else if (relatedTaskId && this._taskMessageQueue) {
17014
17041
  this._enqueueTaskMessage(relatedTaskId, {
17015
17042
  type: "error",
17016
17043
  message: errorResponse,
@@ -17061,7 +17088,10 @@ class Protocol {
17061
17088
  closeSSEStream: extra?.closeSSEStream,
17062
17089
  closeStandaloneSSEStream: extra?.closeStandaloneSSEStream
17063
17090
  };
17064
- Promise.resolve().then(() => {
17091
+ (relatedTaskLookup ?? Promise.resolve()).then(() => {
17092
+ if (relatedTaskLookup && abortController.signal.aborted) {
17093
+ throw new McpError(ErrorCode.ConnectionClosed, "Request was cancelled");
17094
+ }
17065
17095
  if (taskCreationParams) {
17066
17096
  this.assertTaskHandlerCapability(request.method);
17067
17097
  }
@@ -17096,7 +17126,7 @@ class Protocol {
17096
17126
  ...error["data"] !== undefined && { data: error["data"] }
17097
17127
  }
17098
17128
  };
17099
- if (relatedTaskId && this._taskMessageQueue) {
17129
+ if (relatedTaskId && this._taskMessageQueue && relatedTaskFound) {
17100
17130
  await this._enqueueTaskMessage(relatedTaskId, {
17101
17131
  type: "error",
17102
17132
  message: errorResponse,
@@ -17484,7 +17514,7 @@ class Protocol {
17484
17514
  throw new Error("Cannot enqueue task message: taskStore and taskMessageQueue are not configured");
17485
17515
  }
17486
17516
  const maxQueueSize = this._options?.maxTaskQueueSize;
17487
- await this._taskMessageQueue.enqueue(taskId, message, sessionId, maxQueueSize);
17517
+ await this._taskMessageQueue.enqueue(taskId, message, sessionId ?? this._transport?.sessionId, maxQueueSize);
17488
17518
  }
17489
17519
  async _clearTaskQueue(taskId, sessionId) {
17490
17520
  if (this._taskMessageQueue) {
@@ -17503,10 +17533,10 @@ class Protocol {
17503
17533
  }
17504
17534
  }
17505
17535
  }
17506
- async _waitForTaskUpdate(taskId, signal) {
17536
+ async _waitForTaskUpdate(taskId, signal, sessionId) {
17507
17537
  let interval = this._options?.defaultTaskPollInterval ?? 1000;
17508
17538
  try {
17509
- const task = await this._taskStore?.getTask(taskId);
17539
+ const task = await this._taskStore?.getTask(taskId, sessionId);
17510
17540
  if (task?.pollInterval) {
17511
17541
  interval = task.pollInterval;
17512
17542
  }
@@ -18175,6 +18205,42 @@ class ExperimentalMcpServerTasks {
18175
18205
 
18176
18206
  // node_modules/@modelcontextprotocol/sdk/dist/esm/server/mcp.js
18177
18207
  init_zod();
18208
+ function toolInputElementCount(value, max) {
18209
+ let count = 0;
18210
+ const stack = [value];
18211
+ while (stack.length > 0) {
18212
+ const node = stack.pop();
18213
+ if (node === null || typeof node !== "object")
18214
+ continue;
18215
+ if (Array.isArray(node)) {
18216
+ for (const child of node) {
18217
+ if (++count > max)
18218
+ return count;
18219
+ if (child !== null && typeof child === "object")
18220
+ stack.push(child);
18221
+ }
18222
+ } else {
18223
+ for (const key in node) {
18224
+ if (!Object.prototype.hasOwnProperty.call(node, key))
18225
+ continue;
18226
+ if (++count > max)
18227
+ return count;
18228
+ const child = node[key];
18229
+ if (child !== null && typeof child === "object")
18230
+ stack.push(child);
18231
+ }
18232
+ }
18233
+ }
18234
+ return count;
18235
+ }
18236
+ function resolveMaxToolInputElements(value) {
18237
+ if (value === undefined || value === Infinity)
18238
+ return;
18239
+ if (typeof value !== "number" || Number.isNaN(value) || value < 1) {
18240
+ throw new RangeError(`maxToolInputElements must be a number of at least 1, or Infinity, got ${String(value)}`);
18241
+ }
18242
+ return value;
18243
+ }
18178
18244
 
18179
18245
  class McpServer {
18180
18246
  constructor(serverInfo, options) {
@@ -18187,6 +18253,7 @@ class McpServer {
18187
18253
  this._resourceHandlersInitialized = false;
18188
18254
  this._promptHandlersInitialized = false;
18189
18255
  this.server = new Server(serverInfo, options);
18256
+ this._maxToolInputElements = resolveMaxToolInputElements(options?.maxToolInputElements);
18190
18257
  }
18191
18258
  get experimental() {
18192
18259
  if (!this._experimental) {
@@ -18293,12 +18360,15 @@ class McpServer {
18293
18360
  };
18294
18361
  }
18295
18362
  async validateToolInput(tool, args, toolName) {
18363
+ if (this._maxToolInputElements !== undefined && toolInputElementCount(args, this._maxToolInputElements) > this._maxToolInputElements) {
18364
+ throw new McpError(ErrorCode.InvalidParams, `Invalid arguments for tool ${toolName}: arguments contain more than the maximum of ${this._maxToolInputElements} elements`);
18365
+ }
18296
18366
  if (!tool.inputSchema) {
18297
18367
  return;
18298
18368
  }
18299
18369
  const inputObj = normalizeObjectSchema(tool.inputSchema);
18300
18370
  const schemaToParse = inputObj ?? tool.inputSchema;
18301
- const parseResult = await safeParseAsync2(schemaToParse, args);
18371
+ const parseResult = await safeParseAsync2(schemaToParse, args ?? {});
18302
18372
  if (!parseResult.success) {
18303
18373
  const error = "error" in parseResult ? parseResult.error : "Unknown error";
18304
18374
  const errorMessage = getParseErrorMessage(error);
@@ -18523,7 +18593,7 @@ class McpServer {
18523
18593
  }
18524
18594
  if (prompt.argsSchema) {
18525
18595
  const argsObj = normalizeObjectSchema(prompt.argsSchema);
18526
- const parseResult = await safeParseAsync2(argsObj, request.params.arguments);
18596
+ const parseResult = await safeParseAsync2(argsObj, request.params.arguments ?? {});
18527
18597
  if (!parseResult.success) {
18528
18598
  const error = "error" in parseResult ? parseResult.error : "Unknown error";
18529
18599
  const errorMessage = getParseErrorMessage(error);
@@ -21146,7 +21216,7 @@ class NotifyExecutor extends BaseExecutor {
21146
21216
  }
21147
21217
  }
21148
21218
  case "slack": {
21149
- const { getSlackApp } = await import("./app-6sv8mhzm.js");
21219
+ const { getSlackApp } = await import("./app-353vre8g.js");
21150
21220
  const app = getSlackApp();
21151
21221
  if (!app) {
21152
21222
  return {
@@ -21272,7 +21342,7 @@ var RawLlmOutputSchema = object2({
21272
21342
  async function executeRawLlm(config) {
21273
21343
  let modelName = config.model ?? "google/gemini-3-flash-preview";
21274
21344
  try {
21275
- const { createOpenAI } = await import("./index-va3y63es.js");
21345
+ const { createOpenAI } = await import("./index-6srwvd5b.js");
21276
21346
  const llmConfig = await resolveWorkflowLlmConfig(config.model);
21277
21347
  modelName = llmConfig.model;
21278
21348
  const provider = createOpenAI({
@@ -21282,7 +21352,7 @@ async function executeRawLlm(config) {
21282
21352
  });
21283
21353
  const model = provider(llmConfig.model);
21284
21354
  if (config.schema) {
21285
- const { generateObject, jsonSchema } = await import("./index-s98037v0.js");
21355
+ const { generateObject, jsonSchema } = await import("./index-cbxkmfc5.js");
21286
21356
  const { object } = await generateObject({
21287
21357
  model,
21288
21358
  schema: jsonSchema(config.schema),
@@ -21296,7 +21366,7 @@ async function executeRawLlm(config) {
21296
21366
  output: { result: object, model: modelName }
21297
21367
  };
21298
21368
  }
21299
- const { generateText } = await import("./index-s98037v0.js");
21369
+ const { generateText } = await import("./index-cbxkmfc5.js");
21300
21370
  const { text } = await generateText({
21301
21371
  model,
21302
21372
  prompt: config.prompt
@@ -21736,8 +21806,8 @@ class ValidateExecutor extends BaseExecutor {
21736
21806
  const interpolatedPrompt = this.deps.interpolate(prompt, context);
21737
21807
  const outputStr = typeof targetOutput === "string" ? targetOutput : JSON.stringify(targetOutput);
21738
21808
  try {
21739
- const { createOpenAI } = await import("./index-va3y63es.js");
21740
- const { generateObject, jsonSchema } = await import("./index-s98037v0.js");
21809
+ const { createOpenAI } = await import("./index-6srwvd5b.js");
21810
+ const { generateObject, jsonSchema } = await import("./index-cbxkmfc5.js");
21741
21811
  const llmConfig = await resolveWorkflowLlmConfig();
21742
21812
  const provider = createOpenAI({
21743
21813
  baseURL: llmConfig.baseURL,
@@ -21909,6 +21979,7 @@ function createExecutorRegistry(deps) {
21909
21979
  registry.register(new NotifyExecutor(deps));
21910
21980
  registry.register(new RawLlmExecutor(deps));
21911
21981
  registry.register(new SystemOneDecisionExecutor(deps));
21982
+ registry.register(new SystemOneExtractionExecutor(deps));
21912
21983
  registry.register(new ScriptExecutor(deps));
21913
21984
  registry.register(new SwarmScriptExecutor(deps));
21914
21985
  registry.register(new VcsExecutor(deps));
@@ -24508,7 +24579,7 @@ function setPreloadedTools(server, names) {
24508
24579
  async function applyPreToolCall(name, args, requestInfo, inputSchema) {
24509
24580
  if (requestInfo.callOrigin !== "mcp")
24510
24581
  return { args };
24511
- const dispatcher = await import("./dispatcher-zthpy4m1.js");
24582
+ const dispatcher = await import("./dispatcher-c155xz0p.js");
24512
24583
  const result = await dispatcher.dispatchPre("pre.tool.call", { tool: name, args, requestInfo }, inputSchema ? {
24513
24584
  validateModify: async (data) => {
24514
24585
  const schema = normalizeObjectSchema(inputSchema) ?? inputSchema;
@@ -31264,7 +31335,11 @@ async function loadAdapter(name, config, logger) {
31264
31335
  switch (name) {
31265
31336
  case "telegram": {
31266
31337
  const { createTelegramAdapter } = await import("./index-g216q6jr.js");
31267
- return createTelegramAdapter({ ...base, allowUnverifiedWebhooks: false });
31338
+ return createTelegramAdapter({
31339
+ ...base,
31340
+ allowUnverifiedWebhooks: false,
31341
+ mentionOnReply: true
31342
+ });
31268
31343
  }
31269
31344
  case "slack": {
31270
31345
  const { createSlackAdapter } = await import("./index-zgvqzjsw.js");
@@ -31866,6 +31941,43 @@ function resetDiscordGatewayHealth() {
31866
31941
  // src/integrations/chat-sdk/inbound.ts
31867
31942
  init_zod();
31868
31943
  init_db3();
31944
+
31945
+ // src/be/unmapped-identities.ts
31946
+ init_db3();
31947
+ var TTL_MS = 30 * 24 * 60 * 60 * 1000;
31948
+ function namespace(kind) {
31949
+ return `integration:unmapped:${kind}`;
31950
+ }
31951
+ async function recordUnmappedIdentity(kind, externalId, meta) {
31952
+ const ns = namespace(kind);
31953
+ const now = new Date().toISOString();
31954
+ const expiresAt = Date.now() + TTL_MS;
31955
+ const countKey = `${externalId}:count`;
31956
+ const countBefore = await getKv2(ns, countKey);
31957
+ await upsertKv2({
31958
+ namespace: ns,
31959
+ key: `${externalId}:meta`,
31960
+ value: {
31961
+ lastSeenAt: now,
31962
+ sampleEventType: meta.sampleEventType,
31963
+ sampleContext: meta.sampleContext.slice(0, 100)
31964
+ },
31965
+ valueType: "json",
31966
+ expiresAt
31967
+ });
31968
+ const incremented = await incrKv2(ns, countKey, 1);
31969
+ if (countBefore === null) {
31970
+ await upsertKv2({
31971
+ namespace: ns,
31972
+ key: countKey,
31973
+ value: Number(incremented.value),
31974
+ valueType: "integer",
31975
+ expiresAt
31976
+ });
31977
+ }
31978
+ }
31979
+
31980
+ // src/integrations/chat-sdk/inbound.ts
31869
31981
  init_resolver();
31870
31982
  init_context_key();
31871
31983
  init_secret_scrubber();
@@ -31914,10 +32026,191 @@ async function recordTaskAttachmentUpload(input) {
31914
32026
  throw error;
31915
32027
  }
31916
32028
  }
32029
+ function scopeFromAttachment(attachment) {
32030
+ const storedKey = attachment.providerKey ?? attachment.path ?? "";
32031
+ return {
32032
+ taskId: attachment.taskId,
32033
+ name: attachment.name,
32034
+ key: storedKey.trim() ? storedKey : undefined,
32035
+ orgId: attachment.orgId,
32036
+ driveId: attachment.driveId
32037
+ };
32038
+ }
32039
+ function backingProviderId(attachment) {
32040
+ if (attachment.kind === "agent-fs")
32041
+ return attachment.providerId ?? "agent-fs";
32042
+ if (attachment.providerId === "local-fs")
32043
+ return "local-fs";
32044
+ return null;
32045
+ }
32046
+
32047
+ // src/utils/transcription.ts
32048
+ init_secret_scrubber();
32049
+ var TRANSCRIPTION_TIMEOUT_MS = 60000;
32050
+ var TRANSCRIPTION_API_KEY_ENV = "TRANSCRIPTION_API_KEY";
32051
+ var openAIShape = {
32052
+ path: "/audio/transcriptions",
32053
+ modelField: "model",
32054
+ authHeaders: (apiKey) => ({ authorization: `Bearer ${apiKey}` })
32055
+ };
32056
+ var PROVIDERS = {
32057
+ openai: {
32058
+ keyEnv: "OPENAI_API_KEY",
32059
+ defaultBaseUrl: "https://api.openai.com/v1",
32060
+ defaultModel: "whisper-1",
32061
+ ...openAIShape
32062
+ },
32063
+ groq: {
32064
+ keyEnv: "GROQ_API_KEY",
32065
+ defaultBaseUrl: "https://api.groq.com/openai/v1",
32066
+ defaultModel: "whisper-large-v3-turbo",
32067
+ ...openAIShape
32068
+ },
32069
+ elevenlabs: {
32070
+ keyEnv: "ELEVENLABS_API_KEY",
32071
+ defaultBaseUrl: "https://api.elevenlabs.io/v1",
32072
+ defaultModel: "scribe_v2",
32073
+ path: "/speech-to-text",
32074
+ modelField: "model_id",
32075
+ authHeaders: (apiKey) => ({ "xi-api-key": apiKey })
32076
+ }
32077
+ };
32078
+ var AUTO_DETECT_ORDER = ["elevenlabs", "openai", "groq"];
32079
+ var TRANSCRIPTION_ENV_KEYS = [
32080
+ TRANSCRIPTION_API_KEY_ENV,
32081
+ "TRANSCRIPTION_PROVIDER",
32082
+ "TRANSCRIPTION_BASE_URL",
32083
+ "TRANSCRIPTION_MODEL",
32084
+ ...AUTO_DETECT_ORDER.map((name) => PROVIDERS[name].keyEnv)
32085
+ ];
32086
+
32087
+ class TranscriptionError extends Error {
32088
+ constructor(message) {
32089
+ super(message);
32090
+ this.name = "TranscriptionError";
32091
+ }
32092
+ }
32093
+ function envValue(key) {
32094
+ return process.env[key]?.trim() || undefined;
32095
+ }
32096
+ function resolveTranscriptionConfig() {
32097
+ const pinned = envValue("TRANSCRIPTION_PROVIDER")?.toLowerCase();
32098
+ const explicitKey = envValue(TRANSCRIPTION_API_KEY_ENV);
32099
+ if (explicitKey) {
32100
+ return {
32101
+ provider: pinned ?? "openai",
32102
+ apiKey: explicitKey,
32103
+ keyEnv: TRANSCRIPTION_API_KEY_ENV,
32104
+ source: "explicit"
32105
+ };
32106
+ }
32107
+ const candidates = pinned ? AUTO_DETECT_ORDER.filter((name) => name === pinned) : AUTO_DETECT_ORDER;
32108
+ for (const name of candidates) {
32109
+ const { keyEnv } = PROVIDERS[name];
32110
+ const apiKey = envValue(keyEnv);
32111
+ if (apiKey)
32112
+ return { provider: name, apiKey, keyEnv, source: "auto" };
32113
+ }
32114
+ return null;
32115
+ }
32116
+ function isTranscriptionConfigured() {
32117
+ return resolveTranscriptionConfig() !== null;
32118
+ }
32119
+ function providerSpec(name) {
32120
+ if (!Object.hasOwn(PROVIDERS, name)) {
32121
+ throw new TranscriptionError(`TRANSCRIPTION_PROVIDER "${name}" is not supported (use ${Object.keys(PROVIDERS).join(", ")})`);
32122
+ }
32123
+ return PROVIDERS[name];
32124
+ }
32125
+ function errorDetail(payload, status) {
32126
+ const error = payload?.error;
32127
+ if (typeof error?.message === "string")
32128
+ return error.message;
32129
+ const detail = payload?.detail;
32130
+ if (typeof detail === "string")
32131
+ return detail;
32132
+ if (typeof detail?.message === "string")
32133
+ return detail.message;
32134
+ return `HTTP ${status}`;
32135
+ }
32136
+ async function transcribeAudio(input) {
32137
+ const config = resolveTranscriptionConfig();
32138
+ if (!config)
32139
+ throw new TranscriptionError("no transcription provider key is set");
32140
+ const { apiKey } = config;
32141
+ const provider = providerSpec(config.provider);
32142
+ const baseUrlOverride = config.source === "explicit" ? process.env.TRANSCRIPTION_BASE_URL?.trim() : undefined;
32143
+ const baseUrl = (baseUrlOverride || provider.defaultBaseUrl).replace(/\/+$/, "");
32144
+ const keyScrubber = createValueScrubber([{ value: apiKey, name: config.keyEnv }]);
32145
+ const scrub = (text) => scrubSecrets(keyScrubber.text(text));
32146
+ const form = new FormData;
32147
+ const type = input.mimeType ?? input.data.type;
32148
+ form.append("file", type ? new Blob([input.data], { type }) : input.data, input.filename);
32149
+ form.append(provider.modelField, process.env.TRANSCRIPTION_MODEL?.trim() || provider.defaultModel);
32150
+ let response;
32151
+ try {
32152
+ response = await fetch(`${baseUrl}${provider.path}`, {
32153
+ method: "POST",
32154
+ headers: provider.authHeaders(apiKey),
32155
+ body: form,
32156
+ signal: AbortSignal.timeout(TRANSCRIPTION_TIMEOUT_MS)
32157
+ });
32158
+ } catch (error) {
32159
+ if (error instanceof Error && error.name === "TimeoutError") {
32160
+ throw new TranscriptionError(`no answer within ${TRANSCRIPTION_TIMEOUT_MS / 1000} s`);
32161
+ }
32162
+ throw new TranscriptionError(scrub(error instanceof Error ? error.message : String(error)));
32163
+ }
32164
+ const payload = await response.json().catch(() => null);
32165
+ if (!response.ok || typeof payload?.text !== "string") {
32166
+ throw new TranscriptionError(scrub(errorDetail(payload, response.status)));
32167
+ }
32168
+ return payload.text.trim();
32169
+ }
32170
+ var NOT_TRANSCRIBED_NOTE = `(not transcribed: no transcription provider configured, set ${TRANSCRIPTION_API_KEY_ENV} or one of ${AUTO_DETECT_ORDER.map((name) => PROVIDERS[name].keyEnv).join(", ")})`;
32171
+ var AUDIO_EXTENSIONS = {
32172
+ "audio/ogg": "ogg",
32173
+ "audio/opus": "ogg",
32174
+ "audio/mpeg": "mp3",
32175
+ "audio/mp4": "m4a",
32176
+ "audio/x-m4a": "m4a",
32177
+ "audio/wav": "wav",
32178
+ "audio/x-wav": "wav",
32179
+ "audio/webm": "webm"
32180
+ };
32181
+ async function transcribeAudioNotes(files, logPrefix) {
32182
+ const notes = new Map;
32183
+ if (files.length === 0)
32184
+ return notes;
32185
+ if (!isTranscriptionConfigured()) {
32186
+ for (const file of files)
32187
+ notes.set(file.key, NOT_TRANSCRIBED_NOTE);
32188
+ return notes;
32189
+ }
32190
+ for (const file of files) {
32191
+ const extension = AUDIO_EXTENSIONS[file.mimeType ?? ""] ?? "ogg";
32192
+ const filename = /\.\w+$/.test(file.name) ? file.name : `${file.name}.${extension}`;
32193
+ try {
32194
+ const text = await transcribeAudio({ data: file.data, filename, mimeType: file.mimeType });
32195
+ notes.set(file.key, `[Transcript of ${file.name}]
32196
+ ${text || "(no speech recognized)"}`);
32197
+ } catch (error) {
32198
+ const reason = scrubSecrets(error instanceof Error ? error.message : String(error));
32199
+ console.warn(`${logPrefix} could not transcribe file ${file.key}: ${reason}`);
32200
+ notes.set(file.key, `(transcription failed: ${reason})`);
32201
+ }
32202
+ }
32203
+ return notes;
32204
+ }
31917
32205
 
31918
32206
  // src/integrations/chat-sdk/attachments.ts
31919
32207
  var DRAFT_LEASE_REFRESH_MS = 60000;
31920
32208
  var SHARED_FILE_INTENT = "user-upload";
32209
+ var MB = 1024 * 1024;
32210
+ var CHAT_INBOUND_FILE_LIMITS = { telegram: 20 * MB };
32211
+ function chatInboundFileLimit(adapter) {
32212
+ return Math.min(CHAT_INBOUND_FILE_LIMITS[adapter] ?? MAX_TASK_ATTACHMENT_BYTES, MAX_TASK_ATTACHMENT_BYTES);
32213
+ }
31921
32214
  function formatFileSize(bytes) {
31922
32215
  if (bytes < 1024)
31923
32216
  return `${bytes} B`;
@@ -31938,16 +32231,42 @@ function toChatFiles(adapter, messageId, attachments) {
31938
32231
  attachment
31939
32232
  }));
31940
32233
  }
31941
- function buildChatAttachmentText(files, failed = []) {
32234
+ function buildChatAttachmentText(files, failed = [], notes = new Map) {
31942
32235
  const reasons = new Map(failed.map((f) => [f.file.id, f.reason]));
31943
32236
  return files.map((f) => {
31944
32237
  const size = typeof f.size === "number" ? formatFileSize(f.size) : "unknown size";
31945
32238
  const line = `[File: ${f.name} (${f.mimeType ?? "unknown type"}, ${size}) id=${f.id}]`;
31946
32239
  const reason = reasons.get(f.id);
31947
- return reason ? `${line} (not attached: ${reason})` : line;
32240
+ const note = notes.get(f.id);
32241
+ return [reason ? `${line} (not attached: ${reason})` : line, note].filter(Boolean).join(`
32242
+ `);
31948
32243
  }).join(`
31949
32244
  `);
31950
32245
  }
32246
+ function markdownLiteral(value) {
32247
+ const text = value.replace(/[\r\n]+/g, " ");
32248
+ const longestRun = Math.max(0, ...(text.match(/`+/g) ?? []).map((run) => run.length));
32249
+ const fence = "`".repeat(longestRun + 1);
32250
+ const pad = /^[` ]|[` ]$/.test(text) ? " " : "";
32251
+ return `${fence}${pad}${text}${pad}${fence}`;
32252
+ }
32253
+ function formatTooLargeReply(failed) {
32254
+ const lines = failed.map((f) => `- ${markdownLiteral(f.file.name)}: ${f.reason}`);
32255
+ return [
32256
+ `Too large to read, so the swarm did not get ${failed.length === 1 ? "this file" : "these files"}:`,
32257
+ ...lines,
32258
+ "Send a smaller file or a link."
32259
+ ].join(`
32260
+ `);
32261
+ }
32262
+ async function transcribeChatAudio(fetched) {
32263
+ return transcribeAudioNotes(fetched.filter(({ file }) => file.attachment.type === "audio").map(({ file, path }) => ({
32264
+ key: file.id,
32265
+ name: file.name,
32266
+ data: Bun.file(path),
32267
+ mimeType: file.mimeType
32268
+ })), "[chat-sdk]");
32269
+ }
31951
32270
  async function readAttachment(attachment) {
31952
32271
  if (attachment.data instanceof Blob)
31953
32272
  return new Uint8Array(await attachment.data.arrayBuffer());
@@ -31971,17 +32290,25 @@ async function fetchChatFiles(files) {
31971
32290
  };
31972
32291
  if (files.length === 0)
31973
32292
  return result;
31974
- const limit = `larger than the ${MAX_TASK_ATTACHMENT_BYTES / (1024 * 1024)} MB limit`;
32293
+ const tooLarge = (file, size) => {
32294
+ const limit = chatInboundFileLimit(file.adapter);
32295
+ const platform = file.adapter.charAt(0).toUpperCase() + file.adapter.slice(1);
32296
+ return {
32297
+ file,
32298
+ reason: `too large (${formatFileSize(size)}, the limit for files sent to the ${platform} bot is ${formatFileSize(limit)})`,
32299
+ tooLarge: true
32300
+ };
32301
+ };
31975
32302
  dir = await mkdtemp(join(tmpdir2(), "chat-files-"));
31976
32303
  for (const [index, file] of files.entries()) {
31977
- if (typeof file.size === "number" && file.size > MAX_TASK_ATTACHMENT_BYTES) {
31978
- result.failed.push({ file, reason: limit });
32304
+ if (typeof file.size === "number" && file.size > chatInboundFileLimit(file.adapter)) {
32305
+ result.failed.push(tooLarge(file, file.size));
31979
32306
  continue;
31980
32307
  }
31981
32308
  try {
31982
32309
  const bytes = await readAttachment(file.attachment);
31983
- if (bytes.byteLength > MAX_TASK_ATTACHMENT_BYTES) {
31984
- result.failed.push({ file, reason: limit });
32310
+ if (bytes.byteLength > chatInboundFileLimit(file.adapter)) {
32311
+ result.failed.push(tooLarge(file, bytes.byteLength));
31985
32312
  continue;
31986
32313
  }
31987
32314
  const path = join(dir, String(index));
@@ -32056,6 +32383,63 @@ async function attachChatFilesToTask(taskId, fetched) {
32056
32383
  return unattached;
32057
32384
  }
32058
32385
 
32386
+ // src/integrations/chat-sdk/facts.ts
32387
+ var SNIPPET_MAX = 80;
32388
+ function snippet2(text) {
32389
+ const flat = text?.replace(/\s+/g, " ").trim();
32390
+ if (!flat)
32391
+ return;
32392
+ return flat.length > SNIPPET_MAX ? `${flat.slice(0, SNIPPET_MAX)}...` : flat;
32393
+ }
32394
+ function personLabel(name, username, fallback) {
32395
+ if (name && username && name !== username)
32396
+ return `${name} (@${username})`;
32397
+ if (username)
32398
+ return `@${username}`;
32399
+ return name || fallback;
32400
+ }
32401
+ function telegramFacts(raw, message, botUserId) {
32402
+ const reply = raw.reply_to_message;
32403
+ const replyIsTopicRoot = reply !== undefined && (reply.forum_topic_created !== undefined || raw.is_topic_message === true && reply.message_id === raw.message_thread_id);
32404
+ const realReply = reply && !replyIsTopicRoot ? reply : undefined;
32405
+ const topicName = replyIsTopicRoot ? reply?.forum_topic_created?.name : undefined;
32406
+ const name = [raw.from?.first_name, raw.from?.last_name].filter(Boolean).join(" ").trim();
32407
+ return {
32408
+ chatType: raw.chat?.type,
32409
+ isForum: raw.chat?.is_forum === true ? true : undefined,
32410
+ title: raw.chat?.title,
32411
+ topic: raw.is_topic_message === true && raw.message_thread_id !== undefined ? topicName ? `"${topicName}"` : `#${raw.message_thread_id}` : undefined,
32412
+ from: personLabel(name || undefined, raw.from?.username, message.author.userId),
32413
+ replyToBot: realReply?.from?.id !== undefined && botUserId !== undefined && String(realReply.from.id) === botUserId,
32414
+ replyToSnippet: snippet2(realReply?.text ?? realReply?.caption)
32415
+ };
32416
+ }
32417
+ function readChatMessageFacts(thread, message) {
32418
+ const raw = message.raw;
32419
+ if (thread.adapter.name === "telegram" && raw && typeof raw === "object") {
32420
+ return telegramFacts(raw, message, thread.adapter.botUserId);
32421
+ }
32422
+ const { fullName, userName, userId } = message.author;
32423
+ return {
32424
+ chatType: thread.isDM ? "dm" : undefined,
32425
+ from: personLabel(fullName || undefined, userName || undefined, userId),
32426
+ replyToBot: message.replyTo?.author.isMe === true,
32427
+ replyToSnippet: snippet2(message.replyTo?.text)
32428
+ };
32429
+ }
32430
+ function formatChatHeaderFacts(adapter, facts, addressed) {
32431
+ const oneLine = (text) => text.replace(/\s+/g, " ").trim();
32432
+ const parts = [adapter];
32433
+ if (facts.chatType)
32434
+ parts.push(facts.title ? `${facts.chatType} "${oneLine(facts.title)}"` : facts.chatType);
32435
+ if (facts.isForum)
32436
+ parts.push(facts.topic ? `forum topic ${oneLine(facts.topic)}` : "forum");
32437
+ parts.push(`from: ${oneLine(facts.from)}`, `addressed: ${addressed}`);
32438
+ if (facts.replyToSnippet)
32439
+ parts.push(`reply-to: "${facts.replyToSnippet}"`);
32440
+ return parts.join(" · ");
32441
+ }
32442
+
32059
32443
  // src/integrations/chat-sdk/outbound.ts
32060
32444
  init_secret_scrubber();
32061
32445
  init_event_bus();
@@ -32071,6 +32455,17 @@ var FALLBACK_LIMIT = 2000;
32071
32455
  function chatMessageLimit(adapter) {
32072
32456
  return CHAT_MESSAGE_LIMITS[adapter] ?? FALLBACK_LIMIT;
32073
32457
  }
32458
+ var MB2 = 1024 * 1024;
32459
+ var CHAT_UPLOAD_LIMITS = {
32460
+ telegram: 50 * MB2,
32461
+ discord: 10 * MB2
32462
+ };
32463
+ var FALLBACK_UPLOAD_LIMIT = 50 * MB2;
32464
+ var TELEGRAM_PHOTO_LIMIT = 10 * MB2;
32465
+ function chatUploadLimit(adapter) {
32466
+ return CHAT_UPLOAD_LIMITS[adapter] ?? FALLBACK_UPLOAD_LIMIT;
32467
+ }
32468
+ var CHAT_FILES_PER_MESSAGE = 10;
32074
32469
  function splitChatMessage(text, limit) {
32075
32470
  if (limit <= 0)
32076
32471
  throw new Error("splitChatMessage: limit must be positive");
@@ -32111,6 +32506,15 @@ function adapterOfChatId(id) {
32111
32506
  const index = id.indexOf(":");
32112
32507
  return index === -1 ? id : id.slice(0, index);
32113
32508
  }
32509
+
32510
+ class ChatFileTooLargeError extends Error {
32511
+ sizeBytes;
32512
+ constructor(sizeBytes) {
32513
+ super(`file is ${formatFileSize(sizeBytes)}`);
32514
+ this.sizeBytes = sizeBytes;
32515
+ this.name = "ChatFileTooLargeError";
32516
+ }
32517
+ }
32114
32518
  async function postChunks(adapter, target, text) {
32115
32519
  const messageIds = [];
32116
32520
  let threadId;
@@ -32121,6 +32525,125 @@ async function postChunks(adapter, target, text) {
32121
32525
  }
32122
32526
  return { messageIds, threadId };
32123
32527
  }
32528
+ function resolveMimeType(name, ...candidates) {
32529
+ for (const candidate of candidates) {
32530
+ const type = candidate?.split(";")[0]?.trim().toLowerCase();
32531
+ if (type && type !== "application/octet-stream")
32532
+ return type;
32533
+ }
32534
+ return Bun.file(name).type.split(";")[0] ?? "application/octet-stream";
32535
+ }
32536
+ function telegramAttachmentType(mimeType, sizeBytes) {
32537
+ if ((mimeType === "image/jpeg" || mimeType === "image/png") && sizeBytes <= TELEGRAM_PHOTO_LIMIT) {
32538
+ return "image";
32539
+ }
32540
+ if (mimeType === "video/mp4")
32541
+ return "video";
32542
+ if (mimeType === "audio/mpeg" || mimeType === "audio/mp4" || mimeType === "audio/x-m4a") {
32543
+ return "audio";
32544
+ }
32545
+ return "file";
32546
+ }
32547
+ function fileGroupKey(adapter, file) {
32548
+ if (adapter !== "telegram")
32549
+ return "files";
32550
+ const type = telegramAttachmentType(file.mimeType, file.data.byteLength);
32551
+ return type === "image" || type === "video" ? "visual" : type;
32552
+ }
32553
+ function fileMessage(adapter, files) {
32554
+ if (adapter === "telegram") {
32555
+ return {
32556
+ markdown: "",
32557
+ attachments: files.map((file) => ({
32558
+ type: telegramAttachmentType(file.mimeType, file.data.byteLength),
32559
+ name: file.name,
32560
+ mimeType: file.mimeType,
32561
+ size: file.data.byteLength,
32562
+ data: file.data
32563
+ }))
32564
+ };
32565
+ }
32566
+ return {
32567
+ markdown: "",
32568
+ files: files.map((file) => ({ data: file.data, filename: file.name, mimeType: file.mimeType }))
32569
+ };
32570
+ }
32571
+ function platformName(adapter) {
32572
+ return adapter.charAt(0).toUpperCase() + adapter.slice(1);
32573
+ }
32574
+ async function postFiles(adapter, target, files) {
32575
+ const limit = chatUploadLimit(adapter);
32576
+ const tooLarge = (size) => `${formatFileSize(size)}, over the ${formatFileSize(limit)} upload limit of ${platformName(adapter)}`;
32577
+ const messageIds = [];
32578
+ const unsent = [];
32579
+ const groups = new Map;
32580
+ const send = async (group) => {
32581
+ try {
32582
+ const sent = await target.post(fileMessage(adapter, group));
32583
+ messageIds.push(sent.id);
32584
+ } catch (error) {
32585
+ const reason = `refused by ${platformName(adapter)} (${scrubSecrets(errorMessage(error))})`;
32586
+ for (const file of group)
32587
+ unsent.push({ name: file.name, reason });
32588
+ }
32589
+ };
32590
+ for (const file of files) {
32591
+ if (file.sizeBytes !== undefined && file.sizeBytes > limit) {
32592
+ unsent.push({ name: file.name, reason: tooLarge(file.sizeBytes) });
32593
+ continue;
32594
+ }
32595
+ let loaded;
32596
+ try {
32597
+ const { data, mimeType } = await file.load(limit);
32598
+ if (data.byteLength > limit)
32599
+ throw new ChatFileTooLargeError(data.byteLength);
32600
+ loaded = {
32601
+ name: file.name,
32602
+ mimeType: resolveMimeType(file.name, file.mimeType, mimeType),
32603
+ data: Buffer.from(data.buffer, data.byteOffset, data.byteLength)
32604
+ };
32605
+ } catch (error) {
32606
+ unsent.push({
32607
+ name: file.name,
32608
+ reason: error instanceof ChatFileTooLargeError ? tooLarge(error.sizeBytes) : `could not be read (${scrubSecrets(errorMessage(error))})`
32609
+ });
32610
+ continue;
32611
+ }
32612
+ const key = fileGroupKey(adapter, loaded);
32613
+ const group = [...groups.get(key) ?? [], loaded];
32614
+ if (group.length === CHAT_FILES_PER_MESSAGE) {
32615
+ groups.delete(key);
32616
+ await send(group);
32617
+ } else {
32618
+ groups.set(key, group);
32619
+ }
32620
+ }
32621
+ for (const group of groups.values())
32622
+ await send(group);
32623
+ return { messageIds, unsent };
32624
+ }
32625
+ function unsentFilesSummary(unsent) {
32626
+ return unsent.length === 0 ? "" : ` ${formatUnsentFilesNote(unsent)}`;
32627
+ }
32628
+ function singleLine(text) {
32629
+ return text.replace(/[\u0000-\u001f\u007f\u2028\u2029]+/g, " ").trim();
32630
+ }
32631
+ function breakMentions(text) {
32632
+ return text.replace(/@/g, "@​").replace(/<!/g, "<​!");
32633
+ }
32634
+ function codeSpan(text) {
32635
+ const value = breakMentions(singleLine(text)) || "(unnamed)";
32636
+ const longestRun = Math.max(0, ...(value.match(/`+/g) ?? []).map((run) => run.length));
32637
+ const fence = "`".repeat(longestRun + 1);
32638
+ const pad = value.startsWith("`") || value.endsWith("`") ? " " : "";
32639
+ return `${fence}${pad}${value}${pad}${fence}`;
32640
+ }
32641
+ function formatUnsentFilesNote(unsent) {
32642
+ const lines = unsent.map((file) => `- ${codeSpan(file.name)}: ${breakMentions(singleLine(file.reason))}`);
32643
+ const count = unsent.length === 1 ? "1 file" : `${unsent.length} files`;
32644
+ return [`Could not send ${count}:`, ...lines].join(`
32645
+ `);
32646
+ }
32124
32647
  async function postChatMessage(args) {
32125
32648
  assertTrustedChatTarget(args.threadId ?? args.channelId ?? "");
32126
32649
  const chat = getChatInstance(args.adapter);
@@ -32128,27 +32651,42 @@ async function postChatMessage(args) {
32128
32651
  throw new ChatAdapterUnavailableError(args.adapter);
32129
32652
  const text = scrubSecrets(args.text);
32130
32653
  let result;
32654
+ let target;
32131
32655
  if (args.threadId) {
32132
32656
  const thread = chat.thread(args.threadId);
32657
+ target = thread;
32133
32658
  const sent = await postChunks(args.adapter, thread, text);
32134
32659
  result = {
32135
32660
  adapter: args.adapter,
32136
32661
  threadId: thread.id,
32137
32662
  channelId: thread.channelId,
32138
- messageIds: sent.messageIds
32663
+ messageIds: sent.messageIds,
32664
+ unsentFiles: []
32139
32665
  };
32140
32666
  } else if (args.channelId) {
32141
32667
  const channel = chat.channel(args.channelId);
32668
+ target = channel;
32142
32669
  const sent = await postChunks(args.adapter, channel, text);
32143
32670
  result = {
32144
32671
  adapter: args.adapter,
32145
32672
  threadId: sent.threadId ?? channel.id,
32146
32673
  channelId: channel.id,
32147
- messageIds: sent.messageIds
32674
+ messageIds: sent.messageIds,
32675
+ unsentFiles: []
32148
32676
  };
32149
32677
  } else {
32150
32678
  throw new Error("postChatMessage needs a threadId or a channelId");
32151
32679
  }
32680
+ if (args.files?.length) {
32681
+ const sent = await postFiles(args.adapter, target, args.files);
32682
+ result.messageIds.push(...sent.messageIds);
32683
+ result.unsentFiles = sent.unsent;
32684
+ if (sent.unsent.length > 0) {
32685
+ const note = formatUnsentFilesNote(sent.unsent);
32686
+ const noted = await postChunks(args.adapter, target, scrubSecrets(note));
32687
+ result.messageIds.push(...noted.messageIds);
32688
+ }
32689
+ }
32152
32690
  emitChatMessageSent({
32153
32691
  adapter: result.adapter,
32154
32692
  channelId: result.channelId,
@@ -32214,9 +32752,19 @@ async function putChatChannelMapping(adapter, channelId, mapping) {
32214
32752
  async function deleteChatChannelMapping(adapter, channelId) {
32215
32753
  return deleteKv2(CHAT_CHANNELS_NAMESPACE, chatChannelKey(adapter, channelId));
32216
32754
  }
32755
+ function hasRoutingToken(text) {
32756
+ return /swarm#(?:[a-f0-9-]{36}|all)/i.test(text);
32757
+ }
32217
32758
  function stripRoutingTokens(text) {
32218
32759
  return text.replace(/swarm#[a-f0-9-]{36}/gi, "").replace(/swarm#all/gi, "").trim();
32219
32760
  }
32761
+ var DEFAULT_OWNER_WINDOW_MINUTES = 15;
32762
+ function chatOwnerWindowStart(now = Date.now()) {
32763
+ const raw = process.env.CHAT_SDK_OWNER_WINDOW_MIN?.trim();
32764
+ const value = raw ? Number(raw) : Number.NaN;
32765
+ const minutes = Number.isFinite(value) && value >= 0 ? value : DEFAULT_OWNER_WINDOW_MINUTES;
32766
+ return new Date(now - minutes * 60000).toISOString();
32767
+ }
32220
32768
  async function leadMatch(reachable, matchedText) {
32221
32769
  const lead = reachable.find((agent) => agent.isLead) ?? await getLeadAgent2();
32222
32770
  return { agent: lead, reason: "skill", matchedText };
@@ -32258,7 +32806,7 @@ async function routeChatMessage(text, ctx) {
32258
32806
  }
32259
32807
  console.warn(scrubSecrets(`[chat-sdk] Channel mapping for ${ctx.channelId} names unknown agent ${mapping.agentId}; using the default route`));
32260
32808
  }
32261
- const owner = await getAgentWorkingOnContextKey2(chatSdkContextKey(ctx.threadId), "chat");
32809
+ const owner = await getAgentWorkingOnContextKey2(chatSdkContextKey(ctx.threadId), "chat", ctx.adapter === "telegram" && !ctx.isDirectMessage ? chatOwnerWindowStart() : undefined);
32262
32810
  if (owner && await isAgentReachable(owner)) {
32263
32811
  return {
32264
32812
  kind: "agents",
@@ -32288,6 +32836,9 @@ async function requestChatThreadSteering(args) {
32288
32836
  const task = await getLatestLeadTaskByContextKey2(args.contextKey, "chat");
32289
32837
  if (!task || task.status !== "in_progress")
32290
32838
  return null;
32839
+ const senderUserId = await args.resolveSender();
32840
+ if (senderUserId !== task.requestedByUserId)
32841
+ return null;
32291
32842
  try {
32292
32843
  const result = await requestSteering({
32293
32844
  taskId: task.id,
@@ -32295,7 +32846,8 @@ async function requestChatThreadSteering(args) {
32295
32846
  mode: "queue",
32296
32847
  onUnsupported: "degrade",
32297
32848
  source: "chat",
32298
- createdByKind: "user"
32849
+ createdByKind: "user",
32850
+ createdByUserId: senderUserId
32299
32851
  });
32300
32852
  return { task, result };
32301
32853
  } catch (error) {
@@ -32389,6 +32941,18 @@ registerTemplate({
32389
32941
  ],
32390
32942
  category: "system"
32391
32943
  });
32944
+ registerTemplate({
32945
+ eventType: "chat.message.header",
32946
+ header: "",
32947
+ defaultBody: "[chat] {{chat_facts}}",
32948
+ variables: [
32949
+ {
32950
+ name: "chat_facts",
32951
+ description: "Adapter, chat type and title, forum topic, sender, why the message was taken (addressed) and the replied-to snippet, joined with ' · '"
32952
+ }
32953
+ ],
32954
+ category: "system"
32955
+ });
32392
32956
 
32393
32957
  // src/integrations/chat-sdk/inbound.ts
32394
32958
  var ChatRouteModifySchema = object2({
@@ -32433,10 +32997,24 @@ async function handleChatInbound(thread, message, kind) {
32433
32997
  if (immediate)
32434
32998
  text = text.replace(/^!now\s*/i, "").trim();
32435
32999
  const attachments = message.attachments ?? [];
33000
+ const facts = readChatMessageFacts(thread, message);
33001
+ const isDirectMessage = kind === "dm" || thread.isDM;
33002
+ const mentioned = kind === "mention" || message.isMention === true;
33003
+ let addressed = isDirectMessage ? "dm" : facts.replyToBot ? "reply-to-bot" : mentioned ? "mention" : "none";
33004
+ if (addressed === "none" && (facts.chatType === "group" || facts.chatType === "supergroup")) {
33005
+ const unaddressed = await classifyUnaddressedGroupMessage(thread, message.author.userId, text);
33006
+ if (unaddressed === "chatter") {
33007
+ console.log(`[chat-sdk] ${thread.id}: unaddressed group message from a non-requester, ignored`);
33008
+ return;
33009
+ }
33010
+ if (unaddressed === "requester-follow-up")
33011
+ addressed = unaddressed;
33012
+ }
32436
33013
  if (!immediate && attachments.length === 0 && text && !isChatThreadBuffered(thread.id)) {
32437
33014
  const steering = await requestChatThreadSteering({
32438
33015
  contextKey: chatSdkContextKey(thread.id),
32439
- message: text
33016
+ message: text,
33017
+ resolveSender: () => resolveChatSender(adapter, message.author.userId)
32440
33018
  });
32441
33019
  if (steering) {
32442
33020
  console.log(`[chat-sdk] ${adapter} message steered task ${steering.task.id} (${steering.result.outcome})`);
@@ -32465,8 +33043,10 @@ async function handleChatInbound(thread, message, kind) {
32465
33043
  text,
32466
33044
  userId: message.author.userId,
32467
33045
  userName: message.author.userName || undefined,
32468
- botMentioned: kind === "mention" || message.isMention === true,
32469
- isDirectMessage: kind === "dm" || thread.isDM,
33046
+ botMentioned: mentioned || facts.replyToBot,
33047
+ isDirectMessage,
33048
+ addressed,
33049
+ facts,
32470
33050
  attachments
32471
33051
  });
32472
33052
  if (kind !== "subscribed")
@@ -32475,6 +33055,47 @@ async function handleChatInbound(thread, message, kind) {
32475
33055
  if (immediate)
32476
33056
  await instantFlushChat(thread.id);
32477
33057
  }
33058
+ var REQUESTER_KEY_PREFIX = "swarm:requester:";
33059
+ var REQUESTER_TTL_MS = 30 * 24 * 60 * 60 * 1000;
33060
+ async function rememberChatThreadRequester(threadId, userId) {
33061
+ try {
33062
+ await new SqliteChatState().set(`${REQUESTER_KEY_PREFIX}${threadId}`, userId, REQUESTER_TTL_MS);
33063
+ } catch (error) {
33064
+ console.warn(`[chat-sdk] Could not store the thread requester: ${errorMessage(error)}`);
33065
+ }
33066
+ }
33067
+ async function classifyUnaddressedGroupMessage(thread, senderId, text) {
33068
+ if (hasRoutingToken(text))
33069
+ return "routable";
33070
+ if ((await getChatChannelMapping(thread.adapter.name, thread.channelId))?.agentId) {
33071
+ return "routable";
33072
+ }
33073
+ const owner = await getAgentWorkingOnContextKey2(chatSdkContextKey(thread.id), "chat", chatOwnerWindowStart());
33074
+ if (!owner)
33075
+ return "chatter";
33076
+ const requester = await new SqliteChatState().get(`${REQUESTER_KEY_PREFIX}${thread.id}`);
33077
+ return requester === senderId ? "requester-follow-up" : "chatter";
33078
+ }
33079
+ async function resolveChatRequester(adapter, item) {
33080
+ return resolveChatSender(adapter, item.userId, {
33081
+ sampleEventType: "chat.message",
33082
+ sampleContext: `${item.facts.from}: ${item.text}`
33083
+ });
33084
+ }
33085
+ async function resolveChatSender(adapter, userId, sample) {
33086
+ if (!userId || userId.startsWith("chat:"))
33087
+ return;
33088
+ try {
33089
+ const resolution = await resolveIdentity(adapter, userId);
33090
+ if (resolution.status === "resolved")
33091
+ return resolution.userId;
33092
+ if (sample)
33093
+ await recordUnmappedIdentity(adapter, userId, sample);
33094
+ } catch (error) {
33095
+ console.warn(`[chat-sdk] Could not resolve the requester: ${errorMessage(error)}`);
33096
+ }
33097
+ return;
33098
+ }
32478
33099
  async function getChatThreadContext(thread, exclude, since) {
32479
33100
  try {
32480
33101
  await thread.refresh();
@@ -32545,6 +33166,8 @@ async function flushChatThread(threadId, items, immediate) {
32545
33166
  `);
32546
33167
  const botMentioned = items.some((item) => item.botMentioned);
32547
33168
  const isDirectMessage = items.some((item) => item.isDirectMessage);
33169
+ const requester = items.find((item) => item.addressed !== "none") ?? first;
33170
+ const otherSenders = new Set(items.map((item) => item.userId)).size - 1;
32548
33171
  const resetAt = await getChatThreadResetAt(threadId);
32549
33172
  const previousTask = await getLatestTaskByContextKey2(contextKey);
32550
33173
  const mostRecentTask = previousTask && resetAt && new Date(previousTask.createdAt).getTime() <= resetAt.getTime() ? null : previousTask;
@@ -32557,6 +33180,9 @@ async function flushChatThread(threadId, items, immediate) {
32557
33180
  text: rawText,
32558
33181
  botMentioned,
32559
33182
  isDirectMessage,
33183
+ ...first.facts.chatType ? { chatType: first.facts.chatType } : {},
33184
+ ...first.facts.isForum ? { isForum: true } : {},
33185
+ replyToBot: items.some((item) => item.facts.replyToBot),
32560
33186
  ...mostRecentTask ? { threadContext: { adapter, threadId } } : {}
32561
33187
  }, {
32562
33188
  validateModify: (data) => {
@@ -32607,7 +33233,16 @@ async function flushChatThread(threadId, items, immediate) {
32607
33233
  const body = stripRoutingTokens(rawText);
32608
33234
  const files = items.flatMap((item) => toChatFiles(adapter, item.messageId, item.attachments));
32609
33235
  const inbound = __using(__stack, await fetchChatFiles(files), 1);
32610
- const fileText = buildChatAttachmentText(inbound.files, inbound.failed);
33236
+ const tooLarge = inbound.failed.filter((failure) => failure.tooLarge);
33237
+ if (tooLarge.length > 0) {
33238
+ try {
33239
+ await postChatMessage({ adapter, threadId, text: formatTooLargeReply(tooLarge) });
33240
+ } catch (error) {
33241
+ console.warn(`[chat-sdk] ${threadId}: could not post the too-large reply: ${errorMessage(error)}`);
33242
+ }
33243
+ }
33244
+ const notes = await transcribeChatAudio(inbound.fetched);
33245
+ const fileText = buildChatAttachmentText(inbound.files, inbound.failed, notes);
32611
33246
  const combined = [body, fileText].filter(Boolean).join(`
32612
33247
 
32613
33248
  `);
@@ -32615,9 +33250,17 @@ async function flushChatThread(threadId, items, immediate) {
32615
33250
 
32616
33251
  ${combined}` : combined;
32617
33252
  const threadContext = mostRecentTask && thread ? await getChatThreadContext(thread, new Set(items.map((item) => item.messageId)), resetAt) : "";
32618
- const description = threadContext ? `${resolveTemplate("chat.message.thread_context", { thread_messages: threadContext }).text}
33253
+ const header = resolveTemplate("chat.message.header", {
33254
+ chat_facts: formatChatHeaderFacts(adapter, otherSenders > 0 ? { ...requester.facts, from: `${requester.facts.from} +${otherSenders} more` } : requester.facts, requester.addressed)
33255
+ }).text;
33256
+ const description = [
33257
+ header,
33258
+ threadContext ? resolveTemplate("chat.message.thread_context", { thread_messages: threadContext }).text : "",
33259
+ marked
33260
+ ].filter(Boolean).join(`
32619
33261
 
32620
- ${marked}` : marked;
33262
+ `);
33263
+ const requestedByUserId = otherSenders > 0 ? undefined : await resolveChatRequester(adapter, requester);
32621
33264
  const latestActive = await getLatestActiveTaskByContextKey2(contextKey, "chat");
32622
33265
  const dependsOn = !immediate && latestActive ? [latestActive.id] : undefined;
32623
33266
  let created = 0;
@@ -32632,7 +33275,9 @@ ${marked}` : marked;
32632
33275
  priority: 70,
32633
33276
  contextKey,
32634
33277
  dependsOn,
33278
+ requestedByUserId,
32635
33279
  parentTaskId: mostRecentTask?.id,
33280
+ inheritParentRequester: false,
32636
33281
  inheritParentOutputSchema: false
32637
33282
  };
32638
33283
  try {
@@ -32648,6 +33293,7 @@ ${marked}` : marked;
32648
33293
  }
32649
33294
  }
32650
33295
  if (created > 0) {
33296
+ await rememberChatThreadRequester(threadId, requester.userId);
32651
33297
  await subscribe(thread);
32652
33298
  startTypingKeepalive(adapter, threadId);
32653
33299
  } else {
@@ -32693,6 +33339,127 @@ init_db3();
32693
33339
  init_context_key();
32694
33340
  init_secret_scrubber();
32695
33341
  init_event_bus();
33342
+
33343
+ // src/integrations/chat-sdk/outbound-files.ts
33344
+ init_db3();
33345
+ init_secret_scrubber();
33346
+ var UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
33347
+ async function download(scope, maxBytes, provider = getFileStorageProvider2()) {
33348
+ const response = await provider.download(scope);
33349
+ const length = Number(response.headers.get("content-length"));
33350
+ if (Number.isFinite(length) && length > maxBytes) {
33351
+ await response.body?.cancel();
33352
+ throw new ChatFileTooLargeError(length);
33353
+ }
33354
+ const data = new Uint8Array(await response.arrayBuffer());
33355
+ if (data.byteLength > maxBytes)
33356
+ throw new ChatFileTooLargeError(data.byteLength);
33357
+ return { data, mimeType: response.headers.get("content-type") ?? undefined };
33358
+ }
33359
+ function chatFileOfTaskAttachment(attachment) {
33360
+ if (backingProviderId(attachment) !== getFileStorageProvider2().id)
33361
+ return;
33362
+ return {
33363
+ name: attachment.name,
33364
+ mimeType: attachment.mimeType,
33365
+ sizeBytes: attachment.sizeBytes,
33366
+ load: (maxBytes) => download(scopeFromAttachment(attachment), maxBytes)
33367
+ };
33368
+ }
33369
+ function pathSegments(path) {
33370
+ return normalizeStoredKey(path).split("/").map((segment) => {
33371
+ let decoded = segment;
33372
+ try {
33373
+ decoded = decodeURIComponent(segment);
33374
+ } catch {}
33375
+ if (!decoded || decoded === "." || decoded === ".." || /[/\\\0]/.test(decoded)) {
33376
+ throw new FilesError("Provider", "Path must not contain empty, `.` or `..` segments, or encoded separators");
33377
+ }
33378
+ return decoded;
33379
+ });
33380
+ }
33381
+ async function callerAgentFs(agentId) {
33382
+ if (!agentId)
33383
+ return;
33384
+ const configs = await getResolvedConfig2(agentId);
33385
+ const value = (key) => configs.find((c) => c.key === key)?.value?.trim();
33386
+ const apiUrl = value("AGENT_FS_API_URL") || process.env.AGENT_FS_API_URL?.trim();
33387
+ const apiKey = value("AGENT_FS_API_KEY");
33388
+ const orgId = value("AGENT_FS_DEFAULT_ORG_ID");
33389
+ const driveId = value("AGENT_FS_DEFAULT_DRIVE_ID");
33390
+ return apiUrl && apiKey && orgId && driveId ? { apiUrl, apiKey, orgId, driveId } : undefined;
33391
+ }
33392
+ function chatFileOfPath(path, access) {
33393
+ const segments = pathSegments(path);
33394
+ const name = segments.at(-1);
33395
+ const key = segments.map(encodeURIComponent).join("/");
33396
+ const keyScrubber = createValueScrubber([{ value: access.apiKey, name: "AGENT_FS_API_KEY" }]);
33397
+ return {
33398
+ name,
33399
+ load: async (maxBytes) => {
33400
+ try {
33401
+ return await download({ taskId: "chat", name, key, orgId: access.orgId, driveId: access.driveId }, maxBytes, new AgentFsProvider(access));
33402
+ } catch (error) {
33403
+ if (error instanceof ChatFileTooLargeError)
33404
+ throw error;
33405
+ if (error instanceof FilesError && error.code === "Unauthorized") {
33406
+ throw new Error("your agent-fs credential cannot read this path");
33407
+ }
33408
+ throw new Error(keyScrubber.text(error instanceof Error ? error.message : String(error)));
33409
+ }
33410
+ }
33411
+ };
33412
+ }
33413
+ async function resolveChatAttachmentRefs(refs, taskId, agentId) {
33414
+ let taskAttachments;
33415
+ let access = null;
33416
+ const files = [];
33417
+ for (const ref of refs) {
33418
+ if (UUID_PATTERN.test(ref)) {
33419
+ if (!taskId)
33420
+ return { error: `Attachment ${ref}: no current task to look it up in.` };
33421
+ taskAttachments ??= await getTaskAttachments2(taskId);
33422
+ const attachment = taskAttachments.find((a) => a.id === ref);
33423
+ if (!attachment)
33424
+ return { error: `Attachment ${ref} is not an attachment of task ${taskId}.` };
33425
+ const file = chatFileOfTaskAttachment(attachment);
33426
+ if (!file) {
33427
+ return {
33428
+ error: `Attachment ${ref} (${attachment.kind}) is not stored in the swarm file provider, so it cannot be sent as a file. Post its link instead.`
33429
+ };
33430
+ }
33431
+ files.push(file);
33432
+ continue;
33433
+ }
33434
+ if (access === null)
33435
+ access = await callerAgentFs(agentId);
33436
+ if (!access) {
33437
+ return {
33438
+ error: `Path ${ref}: you have no agent-fs credential and drive to read it with. Attach the file to your task and send its attachment id.`
33439
+ };
33440
+ }
33441
+ try {
33442
+ files.push(chatFileOfPath(ref, access));
33443
+ } catch (error) {
33444
+ return { error: `Path ${ref}: ${errorMessage(error)}` };
33445
+ }
33446
+ }
33447
+ return { files };
33448
+ }
33449
+ var FETCHED_SLACK_FILE_INTENT = "slack-file";
33450
+ async function taskOutputChatFiles(taskId) {
33451
+ return (await getTaskAttachments2(taskId)).flatMap((attachment) => {
33452
+ if (attachment.agentId === null)
33453
+ return [];
33454
+ if (attachment.intent === SHARED_FILE_INTENT || attachment.intent === FETCHED_SLACK_FILE_INTENT) {
33455
+ return [];
33456
+ }
33457
+ const file = chatFileOfTaskAttachment(attachment);
33458
+ return file ? [file] : [];
33459
+ });
33460
+ }
33461
+
33462
+ // src/integrations/chat-sdk/relay.ts
32696
33463
  var RELAY_GIVE_UP_AFTER_MS = 24 * 60 * 60 * 1000;
32697
33464
  var SWEEP_EVERY_N_TICKS = 20;
32698
33465
  var EARLY_TICK_DEBOUNCE_MS = 250;
@@ -32742,7 +33509,8 @@ async function processPendingChatRelays(now = Date.now(), signal) {
32742
33509
  adapter: target.adapter,
32743
33510
  threadId: target.threadId,
32744
33511
  text: formatChatRelayText(task),
32745
- taskId: task.id
33512
+ taskId: task.id,
33513
+ files: await taskOutputChatFiles(task.id)
32746
33514
  });
32747
33515
  stopTypingKeepalive(target.threadId);
32748
33516
  await markChatRelayDelivered2(task.id, now);
@@ -33400,43 +34168,6 @@ Original issue: {{issue_key}} — {{issue_summary}}`,
33400
34168
  // src/jira/sync.ts
33401
34169
  init_db3();
33402
34170
  init_oauth();
33403
-
33404
- // src/be/unmapped-identities.ts
33405
- init_db3();
33406
- var TTL_MS = 30 * 24 * 60 * 60 * 1000;
33407
- function namespace(kind) {
33408
- return `integration:unmapped:${kind}`;
33409
- }
33410
- async function recordUnmappedIdentity(kind, externalId, meta) {
33411
- const ns = namespace(kind);
33412
- const now = new Date().toISOString();
33413
- const expiresAt = Date.now() + TTL_MS;
33414
- const countKey = `${externalId}:count`;
33415
- const countBefore = await getKv2(ns, countKey);
33416
- await upsertKv2({
33417
- namespace: ns,
33418
- key: `${externalId}:meta`,
33419
- value: {
33420
- lastSeenAt: now,
33421
- sampleEventType: meta.sampleEventType,
33422
- sampleContext: meta.sampleContext.slice(0, 100)
33423
- },
33424
- valueType: "json",
33425
- expiresAt
33426
- });
33427
- const incremented = await incrKv2(ns, countKey, 1);
33428
- if (countBefore === null) {
33429
- await upsertKv2({
33430
- namespace: ns,
33431
- key: countKey,
33432
- value: Number(incremented.value),
33433
- valueType: "integer",
33434
- expiresAt
33435
- });
33436
- }
33437
- }
33438
-
33439
- // src/jira/sync.ts
33440
34171
  init_users();
33441
34172
  init_resolver();
33442
34173
  init_context_key();
@@ -33822,7 +34553,7 @@ async function notifySlack(text) {
33822
34553
  return;
33823
34554
  }
33824
34555
  try {
33825
- const { getSlackApp } = await import("./app-6sv8mhzm.js");
34556
+ const { getSlackApp } = await import("./app-353vre8g.js");
33826
34557
  const app = getSlackApp();
33827
34558
  if (!app) {
33828
34559
  console.warn("[Jira webhook keepalive] Slack not available, cannot send notification");
@@ -33893,7 +34624,7 @@ async function deleteJiraWebhook(webhookId) {
33893
34624
  console.log(`[Jira webhook keepalive] Deleted webhook id=${webhookId}`);
33894
34625
  }
33895
34626
  async function overwriteWebhookIds(next) {
33896
- const { getDbClient } = await import("./db-6nf1207q.js");
34627
+ const { getDbClient } = await import("./db-6sfrn9g3.js");
33897
34628
  await getDbClient().transaction(async (tx) => {
33898
34629
  const row = await tx.get("SELECT metadata FROM oauth_apps WHERE provider = 'jira'");
33899
34630
  if (!row) {
@@ -106993,11 +107724,34 @@ function parseCookieHeader(cookieHeader, name) {
106993
107724
  const match = header.match(re);
106994
107725
  return match ? match[1] : undefined;
106995
107726
  }
106996
- async function extractAndVerifyCookie(req) {
106997
- const token = parseCookieHeader(req.headers.cookie, "page_session");
106998
- if (!token)
107727
+ var LEGACY_PAGE_SESSION_COOKIE = "page_session";
107728
+ var COOKIE_SAFE_PAGE_ID = /^[A-Za-z0-9_-]{1,64}$/;
107729
+ function isCookieSafePageId(pageId) {
107730
+ return COOKIE_SAFE_PAGE_ID.test(pageId);
107731
+ }
107732
+ function pageSessionCookieName(pageId) {
107733
+ return `${LEGACY_PAGE_SESSION_COOKIE}_${pageId}`;
107734
+ }
107735
+ async function verifyNamedCookie(req, name) {
107736
+ const token = parseCookieHeader(req.headers.cookie, name);
107737
+ const payload = await verifyPageSession(token);
107738
+ return payload && token ? { token, payload } : null;
107739
+ }
107740
+ async function extractPageSession(req, pageId) {
107741
+ if (!isCookieSafePageId(pageId))
106999
107742
  return null;
107000
- return verifyPageSession(token);
107743
+ for (const name of [pageSessionCookieName(pageId), LEGACY_PAGE_SESSION_COOKIE]) {
107744
+ const session = await verifyNamedCookie(req, name);
107745
+ if (session?.payload.pageId === pageId)
107746
+ return session;
107747
+ }
107748
+ return null;
107749
+ }
107750
+ async function extractLegacyPageSession(req) {
107751
+ return verifyNamedCookie(req, LEGACY_PAGE_SESSION_COOKIE);
107752
+ }
107753
+ async function extractAndVerifyCookie(req, pageId) {
107754
+ return (await extractPageSession(req, pageId))?.payload ?? null;
107001
107755
  }
107002
107756
  var PAGE_SESSION_TTL_SECONDS = 3600;
107003
107757
  async function issuePageSessionCookie(pageId, opts) {
@@ -107009,13 +107763,11 @@ async function issuePageSessionCookie(pageId, opts) {
107009
107763
  ...opts.name ? { name: opts.name } : {},
107010
107764
  ...opts.op ? { op: true } : {}
107011
107765
  });
107012
- const attrs = [
107013
- `page_session=${token}`,
107014
- "HttpOnly",
107015
- "Path=/",
107016
- `Max-Age=${PAGE_SESSION_TTL_SECONDS}`
107017
- ];
107018
- if (opts.dev) {
107766
+ return buildCookie(pageSessionCookieName(pageId), token, PAGE_SESSION_TTL_SECONDS, opts.dev);
107767
+ }
107768
+ function buildCookie(name, value, maxAge, dev) {
107769
+ const attrs = [`${name}=${value}`, "HttpOnly", "Path=/", `Max-Age=${maxAge}`];
107770
+ if (dev) {
107019
107771
  attrs.push("SameSite=Lax");
107020
107772
  } else {
107021
107773
  attrs.push("SameSite=None");
@@ -107023,6 +107775,30 @@ async function issuePageSessionCookie(pageId, opts) {
107023
107775
  }
107024
107776
  return attrs.join("; ");
107025
107777
  }
107778
+ var MAX_PAGE_SESSION_COOKIES = 20;
107779
+ var PAGE_SESSION_COOKIE_RE = new RegExp(`(?:^|;\\s*)(${LEGACY_PAGE_SESSION_COOKIE}_[A-Za-z0-9_-]{1,64})=([^;]*)`, "g");
107780
+ async function pageSessionSetCookies(req, pageId, opts) {
107781
+ const issued = await issuePageSessionCookie(pageId, opts);
107782
+ const header = Array.isArray(req.headers.cookie) ? req.headers.cookie.join("; ") : req.headers.cookie ?? "";
107783
+ const keep = [];
107784
+ const evict = new Set;
107785
+ const seen = new Set([pageSessionCookieName(pageId)]);
107786
+ for (const [, name, token] of header.matchAll(PAGE_SESSION_COOKIE_RE)) {
107787
+ if (!name || seen.has(name))
107788
+ continue;
107789
+ seen.add(name);
107790
+ const payload = await verifyPageSession(token);
107791
+ if (payload && name === pageSessionCookieName(payload.pageId)) {
107792
+ keep.push({ name, exp: payload.exp, order: keep.length });
107793
+ } else {
107794
+ evict.add(name);
107795
+ }
107796
+ }
107797
+ keep.sort((a, b) => b.exp - a.exp || b.order - a.order);
107798
+ for (const { name } of keep.slice(MAX_PAGE_SESSION_COOKIES - 1))
107799
+ evict.add(name);
107800
+ return [issued, ...[...evict].map((name) => buildCookie(name, "", 0, opts.dev))];
107801
+ }
107026
107802
 
107027
107803
  // src/http/auth.ts
107028
107804
  function extractBearer(req) {
@@ -107243,14 +108019,14 @@ async function reloadGlobalConfigsAndIntegrations() {
107243
108019
  return runWithoutRequestAuth(() => reloadGlobalConfigsAndIntegrationsInner());
107244
108020
  }
107245
108021
  async function reloadGlobalConfigsAndIntegrationsInner() {
107246
- const { getEmbeddingProvider, resetEmbeddingProvider } = await import("./index-x8xbyn1t.js");
108022
+ const { getEmbeddingProvider, resetEmbeddingProvider } = await import("./index-arytgj5q.js");
107247
108023
  const wasEmbeddingsConfigured = getEmbeddingProvider().isConfigured();
107248
108024
  const updated = await loadGlobalConfigsIntoEnv(true);
107249
108025
  await syncTelemetryEnabled("settings").catch((err) => {
107250
108026
  console.error("[config-reload] telemetry re-init failed (non-fatal):", err);
107251
108027
  });
107252
108028
  await stopSlackApp2();
107253
- const { resetFileStorageProvider } = await import("./registry-rxw10xzg.js");
108029
+ const { resetFileStorageProvider } = await import("./registry-ajhexe44.js");
107254
108030
  resetFileStorageProvider();
107255
108031
  resetEmbeddingProvider();
107256
108032
  const isEmbeddingsConfigured = getEmbeddingProvider().isConfigured();
@@ -107259,10 +108035,10 @@ async function reloadGlobalConfigsAndIntegrationsInner() {
107259
108035
  integrations.push("embeddings");
107260
108036
  }
107261
108037
  if (!wasEmbeddingsConfigured && isEmbeddingsConfigured) {
107262
- import("./boot-reembed-y3m0ydzj.js").then(({ runBootReembed }) => runBootReembed()).catch((err) => {
108038
+ import("./boot-reembed-b9c3az3c.js").then(({ runBootReembed }) => runBootReembed()).catch((err) => {
107263
108039
  console.error("[config-reload] memory backfill failed (non-fatal):", err);
107264
108040
  });
107265
- import("./boot-reembed-gvxjs2py.js").then(({ runBootReembedScripts }) => runBootReembedScripts()).catch((err) => {
108041
+ import("./boot-reembed-qdkvxeem.js").then(({ runBootReembedScripts }) => runBootReembedScripts()).catch((err) => {
107266
108042
  console.error("[config-reload] script backfill failed (non-fatal):", err);
107267
108043
  });
107268
108044
  }
@@ -107453,6 +108229,8 @@ async function handleCore(req, res, myAgentId, apiKey) {
107453
108229
  return true;
107454
108230
  }
107455
108231
  req.headers["x-runtime-instance-id"] = auth.runtimeId;
108232
+ }
108233
+ if (auth.tokenKind !== "task") {
107456
108234
  const sourceHeader = req.headers["x-source-task-id"];
107457
108235
  const taskId = Array.isArray(sourceHeader) ? sourceHeader[0] : sourceHeader;
107458
108236
  if (taskId !== undefined && (await getTaskById2(taskId))?.agentId !== auth.agentId) {
@@ -107672,6 +108450,10 @@ async function handleCore(req, res, myAgentId, apiKey) {
107672
108450
  return false;
107673
108451
  }
107674
108452
 
108453
+ // src/mcp-limits.ts
108454
+ var MCP_MAX_TOOL_INPUT_ELEMENTS = 25000;
108455
+ var MCP_MAX_REQUEST_BODY_BYTES = 4 * 1024 * 1024;
108456
+
107675
108457
  // src/server.ts
107676
108458
  init_resolver();
107677
108459
  init_rbac();
@@ -108788,6 +109570,7 @@ async function runAppAction({
108788
109570
  app,
108789
109571
  name,
108790
109572
  input = {},
109573
+ parentTaskId,
108791
109574
  caller,
108792
109575
  actor
108793
109576
  }) {
@@ -108874,7 +109657,8 @@ async function runAppAction({
108874
109657
  routingReason: action.agentId ? "human_pinned" : lead ? "skill" : undefined,
108875
109658
  routingSource: action.agentId || lead ? "engine_default" : undefined,
108876
109659
  key: normalizeAssetKey(`shared/app:${app.id}/action:${name}/`),
108877
- ...actor.startsWith("user:") ? { requestedByUserId: actor.slice("user:".length) } : {}
109660
+ ...actor.startsWith("user:") ? { requestedByUserId: actor.slice("user:".length) } : {},
109661
+ ...parentTaskId ? { parentTaskId } : {}
108878
109662
  }, { origin: "app" });
108879
109663
  return {
108880
109664
  status: 200,
@@ -110045,6 +110829,47 @@ init_rbac();
110045
110829
  init_types();
110046
110830
  init_request_auth_context();
110047
110831
  init_secret_scrubber();
110832
+
110833
+ // src/http/request-principal.ts
110834
+ init_db3();
110835
+ init_request_auth_context();
110836
+ async function requestPrincipal(req, myAgentId) {
110837
+ const auth = getRequestAuth(req);
110838
+ if (auth?.kind === "controller")
110839
+ return { kind: "guest" };
110840
+ if (auth?.kind === "operator")
110841
+ return { kind: "operator" };
110842
+ if (auth?.kind === "user")
110843
+ return { kind: "user", userId: auth.userId };
110844
+ if (auth?.kind === "guest")
110845
+ return { kind: "guest" };
110846
+ if (!myAgentId)
110847
+ return null;
110848
+ const agent = await getAgentById2(myAgentId);
110849
+ return { kind: "agent", agentId: myAgentId, isLead: agent?.isLead ?? false };
110850
+ }
110851
+ async function agentFirstPrincipal(req, myAgentId) {
110852
+ const auth = getRequestAuth(req);
110853
+ if (auth?.kind === "controller")
110854
+ return { kind: "guest" };
110855
+ if (auth?.kind === "user")
110856
+ return { kind: "user", userId: auth.userId };
110857
+ if (auth?.kind === "guest")
110858
+ return { kind: "guest" };
110859
+ const agentId = auth?.kind === "agent" ? auth.agentId : myAgentId;
110860
+ if (!agentId)
110861
+ return { kind: "operator" };
110862
+ const agent = await getAgentById2(agentId);
110863
+ return { kind: "agent", agentId, isLead: agent?.isLead === true };
110864
+ }
110865
+ function rejectGuest(req, res) {
110866
+ if (getRequestAuth(req)?.kind !== "guest")
110867
+ return false;
110868
+ jsonError(res, "Forbidden", 403);
110869
+ return true;
110870
+ }
110871
+
110872
+ // src/http/apps.ts
110048
110873
  var MAX_APP_BODY_BYTES = 5 * 1024 * 1024;
110049
110874
  var MAX_APP_ROW_BODY_BYTES = 1 * 1024 * 1024;
110050
110875
  var MAX_APP_BULK_ROWS_BODY_BYTES = 10 * 1024 * 1024;
@@ -110493,17 +111318,23 @@ var runActionRoute = route({
110493
111318
  method: "post",
110494
111319
  path: "/api/apps/{id}/actions/{name}",
110495
111320
  pattern: ["api", "apps", null, "actions", null],
111321
+ session: bodyTask("parentTaskId"),
110496
111322
  summary: "Run a custom app action",
110497
111323
  description: "Runs the saved script, or creates the agent task, named by the app definition.",
110498
111324
  tags: ["Apps"],
110499
111325
  params: object2({ id: string2().min(1), name: AppNameSchema }),
110500
- body: object2({ input: record2(string2(), unknown()).optional() }),
111326
+ body: object2({
111327
+ input: record2(string2(), unknown()).optional(),
111328
+ parentTaskId: string2().min(1).optional()
111329
+ }),
110501
111330
  responses: {
110502
111331
  200: { description: "Action invoked", schema: runActionResultSchema },
110503
- 400: { description: "Invalid action input or stale script reference" },
111332
+ 400: {
111333
+ description: "Invalid action input, stale script reference, or parentTaskId on a non-task action"
111334
+ },
110504
111335
  403: { description: "Permission denied" },
110505
111336
  409: { description: "App definition needs repair" },
110506
- 404: { description: "App or action not found" }
111337
+ 404: { description: "App, action, or parent task not found" }
110507
111338
  },
110508
111339
  rbac: { permission: "app.use" }
110509
111340
  });
@@ -111072,10 +111903,29 @@ async function handleApps(req, res, pathSegments, queryParams, myAgentId) {
111072
111903
  }
111073
111904
  if (definitionNeedsRepair(res, app))
111074
111905
  return true;
111906
+ if (parsed.body.parentTaskId) {
111907
+ const actions = app.definition.actions;
111908
+ const action = actions && Object.hasOwn(actions, parsed.params.name) ? actions[parsed.params.name] : undefined;
111909
+ if (action && action.kind !== "task") {
111910
+ jsonError(res, "parentTaskId is only supported for task-kind actions", 400);
111911
+ return true;
111912
+ }
111913
+ if (action) {
111914
+ const parentTask = await getTaskById2(parsed.body.parentTaskId);
111915
+ if (!parentTask) {
111916
+ jsonError(res, "parent task not found", 404);
111917
+ return true;
111918
+ }
111919
+ const principal = await agentFirstPrincipal(req, myAgentId);
111920
+ if (await denyParentAttach2(req, res, myAgentId, parentTask, principal))
111921
+ return true;
111922
+ }
111923
+ }
111075
111924
  const output = await runAppAction({
111076
111925
  app,
111077
111926
  name: parsed.params.name,
111078
111927
  input: parsed.body.input,
111928
+ parentTaskId: parsed.body.parentTaskId,
111079
111929
  caller,
111080
111930
  actor
111081
111931
  });
@@ -112652,9 +113502,11 @@ var registerCancelTaskTool = (server) => {
112652
113502
  init_zod();
112653
113503
 
112654
113504
  // src/tools/chat-access.ts
113505
+ init_zod();
112655
113506
  init_db3();
112656
113507
  init_rbac();
112657
113508
  init_context_key();
113509
+ var chatAttachmentsSchema = array2(string2().min(1)).max(10).optional().describe("Files to send after the text, up to 10: attachment ids of your current task (from get-task-details) or file paths in your agent-fs drive, such as thoughts/<agent-id>/report.pdf, read with your own agent-fs credential. Telegram shows JPEG and PNG as photos, MP4 as video, MP3 and M4A as audio, and anything else as a document. A file over the platform upload limit (Telegram 50 MB, Discord 10 MB) is not sent, and the thread gets a note naming it.");
112658
113510
  async function callerChatThread(requestInfo) {
112659
113511
  if (!requestInfo.agentId)
112660
113512
  return null;
@@ -112735,16 +113587,18 @@ var registerChatPostTool = (server) => {
112735
113587
  adapter: _enum2(CHAT_SDK_ADAPTER_NAMES).describe("Chat SDK adapter name."),
112736
113588
  threadId: string2().min(1).optional().describe("Full SDK thread id, such as telegram:12345 or slack:C123:1700000000.000100."),
112737
113589
  channelId: string2().min(1).optional().describe("Full SDK channel id, such as slack:C123. Ignored when threadId is set."),
112738
- text: string2().min(1).max(20000).describe("Markdown text to post.")
113590
+ text: string2().min(1).max(20000).describe("Markdown text to post."),
113591
+ attachments: chatAttachmentsSchema
112739
113592
  }),
112740
113593
  outputSchema: swarmToolOutputSchema({
112741
113594
  yourAgentId: string2().optional(),
112742
113595
  messageId: string2().optional(),
112743
113596
  adapter: string2().optional(),
112744
113597
  threadId: string2().optional(),
112745
- channelId: string2().optional()
113598
+ channelId: string2().optional(),
113599
+ unsentFiles: array2(looseObject({ name: string2().optional(), reason: string2().optional() })).optional()
112746
113600
  })
112747
- }, async ({ adapter, threadId, channelId, text }, requestInfo) => {
113601
+ }, async ({ adapter, threadId, channelId, text, attachments }, requestInfo) => {
112748
113602
  const data = { yourAgentId: requestInfo.agentId };
112749
113603
  const target = threadId ?? channelId;
112750
113604
  if (!target)
@@ -112755,20 +113609,25 @@ var registerChatPostTool = (server) => {
112755
113609
  if (!await canUseChatVerb(requestInfo, "integration.chat.post")) {
112756
113610
  return toolErr("Permission denied. Only the lead can post outside the thread of its task. Use chat-reply for the thread of your current task.", { data });
112757
113611
  }
113612
+ const resolved = await resolveChatAttachmentRefs(attachments ?? [], requestInfo.sourceTaskId, requestInfo.agentId);
113613
+ if ("error" in resolved)
113614
+ return toolErr(resolved.error, { data });
112758
113615
  try {
112759
113616
  const sent = await postChatMessage({
112760
113617
  adapter,
112761
113618
  ...threadId ? { threadId } : { channelId },
112762
113619
  text,
112763
- taskId: requestInfo.sourceTaskId
113620
+ taskId: requestInfo.sourceTaskId,
113621
+ files: resolved.files
112764
113622
  });
112765
- return toolOk(`Posted to ${adapter} ${threadId ? "thread" : "channel"} ${target}.`, {
113623
+ return toolOk(`Posted to ${adapter} ${threadId ? "thread" : "channel"} ${target}.${unsentFilesSummary(sent.unsentFiles)}`, {
112766
113624
  data: {
112767
113625
  ...data,
112768
113626
  messageId: sent.messageIds.at(-1),
112769
113627
  adapter: sent.adapter,
112770
113628
  threadId: sent.threadId,
112771
- channelId: sent.channelId
113629
+ channelId: sent.channelId,
113630
+ unsentFiles: sent.unsentFiles
112772
113631
  }
112773
113632
  });
112774
113633
  } catch (error) {
@@ -112849,18 +113708,20 @@ init_context_key();
112849
113708
  var registerChatReplyTool = (server) => {
112850
113709
  createToolRegistrar(server)("chat-reply", {
112851
113710
  title: "Reply in the chat thread of this task",
112852
- description: "Post a message to the Telegram, Slack, Discord or Teams thread your current task came from. Works only on a task whose contextKey starts with task:chat-sdk:. The task's final output is posted to the thread automatically when the task ends, so use this only for a question to the user or a short progress note on long work. Markdown is supported; long text is split into several messages.",
113711
+ description: "Post a message to the Telegram, Slack, Discord or Teams thread your current task came from. Works only on a task whose contextKey starts with task:chat-sdk:. The task's final output is posted to the thread automatically when the task ends, so use this only for a question to the user, a short progress note on long work, or to send files (attachments). Markdown is supported; long text is split into several messages. When the final output of a task is posted, the files attached to that task go with it.",
112853
113712
  annotations: { openWorldHint: true },
112854
113713
  inputSchema: object2({
112855
- text: string2().min(1).max(20000).describe("Markdown text to post to the thread.")
113714
+ text: string2().min(1).max(20000).describe("Markdown text to post to the thread."),
113715
+ attachments: chatAttachmentsSchema
112856
113716
  }),
112857
113717
  outputSchema: swarmToolOutputSchema({
112858
113718
  yourAgentId: string2().optional(),
112859
113719
  messageId: string2().optional(),
112860
113720
  adapter: string2().optional(),
112861
- threadId: string2().optional()
113721
+ threadId: string2().optional(),
113722
+ unsentFiles: array2(looseObject({ name: string2().optional(), reason: string2().optional() })).optional()
112862
113723
  })
112863
- }, async ({ text }, requestInfo) => {
113724
+ }, async ({ text, attachments }, requestInfo) => {
112864
113725
  if (!requestInfo.agentId)
112865
113726
  return toolErr("Agent ID not found.");
112866
113727
  const data = { yourAgentId: requestInfo.agentId };
@@ -112874,19 +113735,24 @@ var registerChatReplyTool = (server) => {
112874
113735
  if (!thread) {
112875
113736
  return toolErr(`Task ${task.id} did not come from a chat thread (no task:chat-sdk contextKey). Use the tool of the channel the task came from.`, { data });
112876
113737
  }
113738
+ const resolved = await resolveChatAttachmentRefs(attachments ?? [], task.id, requestInfo.agentId);
113739
+ if ("error" in resolved)
113740
+ return toolErr(resolved.error, { data });
112877
113741
  try {
112878
113742
  const sent = await postChatMessage({
112879
113743
  adapter: thread.adapter,
112880
113744
  threadId: thread.threadId,
112881
113745
  text,
112882
- taskId: task.id
113746
+ taskId: task.id,
113747
+ files: resolved.files
112883
113748
  });
112884
- return toolOk(`Posted to ${thread.adapter} thread ${sent.threadId}.`, {
113749
+ return toolOk(`Posted to ${thread.adapter} thread ${sent.threadId}.${unsentFilesSummary(sent.unsentFiles)}`, {
112885
113750
  data: {
112886
113751
  ...data,
112887
113752
  messageId: sent.messageIds.at(-1),
112888
113753
  adapter: sent.adapter,
112889
- threadId: sent.threadId
113754
+ threadId: sent.threadId,
113755
+ unsentFiles: sent.unsentFiles
112890
113756
  }
112891
113757
  });
112892
113758
  } catch (error) {
@@ -114374,8 +115240,523 @@ init_db3();
114374
115240
 
114375
115241
  // src/tasks/task-terminal-effects.ts
114376
115242
  init_db3();
115243
+
115244
+ // src/be/chunking.ts
115245
+ var MAX_CHUNK_SIZE = 2000;
115246
+ var CHUNK_OVERLAP = 100;
115247
+ var MIN_CHUNK_SIZE = 50;
115248
+ function chunkContent(text) {
115249
+ const trimmed = text.trim();
115250
+ if (!trimmed || trimmed.length < MIN_CHUNK_SIZE) {
115251
+ return [];
115252
+ }
115253
+ if (trimmed.length <= MAX_CHUNK_SIZE) {
115254
+ return [{ content: trimmed, chunkIndex: 0, totalChunks: 1, headings: [] }];
115255
+ }
115256
+ const sections = splitByHeaders(trimmed);
115257
+ const rawChunks = [];
115258
+ for (const section of sections) {
115259
+ if (section.content.length <= MAX_CHUNK_SIZE) {
115260
+ rawChunks.push(section);
115261
+ } else {
115262
+ const subChunks = recursiveSplit(section.content);
115263
+ for (const sub of subChunks) {
115264
+ rawChunks.push({ content: sub, headings: section.headings });
115265
+ }
115266
+ }
115267
+ }
115268
+ const packed = packSmallSections(rawChunks);
115269
+ return packed.map((c, i) => ({
115270
+ content: c.content,
115271
+ chunkIndex: i,
115272
+ totalChunks: packed.length,
115273
+ headings: c.headings
115274
+ }));
115275
+ }
115276
+ function renderSection(section) {
115277
+ return section.headings.length > 0 ? `${section.headings.join(" > ")}
115278
+
115279
+ ${section.content}` : section.content;
115280
+ }
115281
+ function packSmallSections(sections) {
115282
+ const out = [];
115283
+ let pending = null;
115284
+ const flush = () => {
115285
+ if (pending)
115286
+ out.push({ content: pending.parts.join(`
115287
+
115288
+ `), headings: pending.headings });
115289
+ pending = null;
115290
+ };
115291
+ for (const section of sections) {
115292
+ const rendered = renderSection(section);
115293
+ if (section.content.trim().length >= MIN_CHUNK_SIZE) {
115294
+ flush();
115295
+ out.push({ content: rendered, headings: section.headings });
115296
+ continue;
115297
+ }
115298
+ if (pending && pending.length + 2 + rendered.length > MAX_CHUNK_SIZE)
115299
+ flush();
115300
+ if (pending) {
115301
+ pending.parts.push(rendered);
115302
+ pending.length += 2 + rendered.length;
115303
+ } else {
115304
+ pending = { parts: [rendered], length: rendered.length, headings: section.headings };
115305
+ }
115306
+ }
115307
+ flush();
115308
+ return out;
115309
+ }
115310
+ function splitByHeaders(text) {
115311
+ const lines = text.split(`
115312
+ `);
115313
+ const sections = [];
115314
+ let currentContent = [];
115315
+ const headingStack = [];
115316
+ for (const line of lines) {
115317
+ const headingMatch = line.match(/^(#{1,3})\s+(.+)$/);
115318
+ if (headingMatch) {
115319
+ if (currentContent.length > 0) {
115320
+ const content = currentContent.join(`
115321
+ `).trim();
115322
+ if (content) {
115323
+ sections.push({ content, headings: [...headingStack] });
115324
+ }
115325
+ currentContent = [];
115326
+ }
115327
+ const level = headingMatch[1].length;
115328
+ const title = headingMatch[2].trim();
115329
+ while (headingStack.length >= level) {
115330
+ headingStack.pop();
115331
+ }
115332
+ headingStack.push(`${"#".repeat(level)} ${title}`);
115333
+ } else {
115334
+ currentContent.push(line);
115335
+ }
115336
+ }
115337
+ if (currentContent.length > 0) {
115338
+ const content = currentContent.join(`
115339
+ `).trim();
115340
+ if (content) {
115341
+ sections.push({ content, headings: [...headingStack] });
115342
+ }
115343
+ }
115344
+ if (sections.length === 0) {
115345
+ return [{ content: text, headings: [] }];
115346
+ }
115347
+ return sections;
115348
+ }
115349
+ var SEPARATORS = [`
115350
+
115351
+ `, `
115352
+ `, ". ", " "];
115353
+ function recursiveSplit(text) {
115354
+ return recursiveSplitWithSeparators(text, 0);
115355
+ }
115356
+ function recursiveSplitWithSeparators(text, separatorIndex) {
115357
+ if (text.length <= MAX_CHUNK_SIZE) {
115358
+ return [text.trim()].filter((s) => s.length > 0);
115359
+ }
115360
+ if (separatorIndex >= SEPARATORS.length) {
115361
+ return hardSplit(text);
115362
+ }
115363
+ const separator = SEPARATORS[separatorIndex];
115364
+ const parts = text.split(separator);
115365
+ if (parts.length <= 1) {
115366
+ return recursiveSplitWithSeparators(text, separatorIndex + 1);
115367
+ }
115368
+ const chunks = [];
115369
+ let current = "";
115370
+ for (const part of parts) {
115371
+ const candidate = current ? current + separator + part : part;
115372
+ if (candidate.length <= MAX_CHUNK_SIZE) {
115373
+ current = candidate;
115374
+ } else {
115375
+ if (current) {
115376
+ chunks.push(current.trim());
115377
+ }
115378
+ if (part.length > MAX_CHUNK_SIZE) {
115379
+ chunks.push(...recursiveSplitWithSeparators(part, separatorIndex + 1));
115380
+ current = "";
115381
+ } else {
115382
+ current = part;
115383
+ }
115384
+ }
115385
+ }
115386
+ if (current.trim()) {
115387
+ chunks.push(current.trim());
115388
+ }
115389
+ return addOverlap(chunks, text);
115390
+ }
115391
+ function hardSplit(text) {
115392
+ const chunks = [];
115393
+ let start = 0;
115394
+ while (start < text.length) {
115395
+ const end = Math.min(start + MAX_CHUNK_SIZE, text.length);
115396
+ chunks.push(text.slice(start, end).trim());
115397
+ if (end === text.length)
115398
+ break;
115399
+ start = end - CHUNK_OVERLAP;
115400
+ }
115401
+ return chunks.filter((c) => c.length > 0);
115402
+ }
115403
+ function addOverlap(chunks, _originalText) {
115404
+ if (chunks.length <= 1)
115405
+ return chunks;
115406
+ const result = [chunks[0]];
115407
+ for (let i = 1;i < chunks.length; i++) {
115408
+ const prevChunk = chunks[i - 1];
115409
+ const chunk = chunks[i];
115410
+ const overlapText = prevChunk.slice(-CHUNK_OVERLAP);
115411
+ if (overlapText.length + chunk.length <= MAX_CHUNK_SIZE + CHUNK_OVERLAP) {
115412
+ result.push(overlapText + chunk);
115413
+ } else {
115414
+ result.push(chunk);
115415
+ }
115416
+ }
115417
+ return result;
115418
+ }
115419
+
115420
+ // src/be/memory/index-content.ts
114377
115421
  init_memory();
114378
115422
 
115423
+ // src/be/memory/key-guard.ts
115424
+ init_rbac();
115425
+ init_key_paths();
115426
+
115427
+ class MemoryKeyError extends Error {
115428
+ reason;
115429
+ constructor(message, reason) {
115430
+ super(message);
115431
+ this.reason = reason;
115432
+ this.name = "MemoryKeyError";
115433
+ }
115434
+ }
115435
+ var NO_AUTHORITY = {
115436
+ principal: { kind: "agent", agentId: "", isLead: false },
115437
+ source: "http"
115438
+ };
115439
+ function shapeError(key, origin) {
115440
+ if (key.length <= MEMORY_KEY_MAX_LENGTH && MEMORY_KEY_PATTERN.test(key))
115441
+ return null;
115442
+ const subject = origin === "sourcePath" ? `sourcePath "${key}" starts with ${LONGTERM_ROOT}, so it is used as the key, but it is not a valid key.` : `Key "${key}" is not a valid key.`;
115443
+ return `${subject} ${MEMORY_KEY_PATTERN_MESSAGE}`;
115444
+ }
115445
+ function assertKeyWritable(key, origin, writer) {
115446
+ if (origin === "sourcePath" && !isLongtermKey(key))
115447
+ return;
115448
+ const shape = shapeError(key, origin);
115449
+ if (shape)
115450
+ throw new MemoryKeyError(shape, "invalid");
115451
+ const pathError = longtermKeyError(key);
115452
+ if (pathError)
115453
+ throw new MemoryKeyError(pathError, "invalid");
115454
+ if (!isConsolidatedKey(key))
115455
+ return;
115456
+ const { principal, source } = writer ?? NO_AUTHORITY;
115457
+ const decision = can({
115458
+ principal,
115459
+ verb: "memory.write.consolidated",
115460
+ resource: { kind: "none" },
115461
+ source
115462
+ });
115463
+ if (!decision.allow)
115464
+ throw new MemoryKeyError(consolidatedKeyMessage(key), "forbidden");
115465
+ }
115466
+
115467
+ // src/be/memory/link-resolver.ts
115468
+ init_db3();
115469
+ init_constants2();
115470
+ var WIKILINK_RE = /\[\[([^\]]+)\]\]/g;
115471
+ var PR_HASH_RE = /(?:^|[\s(])#(\d{1,5})(?=[\s,.)!?]|$)/gm;
115472
+ var PR_PREFIX_RE = /\bPR\s*#(\d{1,5})\b/gi;
115473
+ var GITHUB_PR_URL_RE = /https?:\/\/github\.com\/([\w.-]+)\/([\w.-]+)\/pull\/(\d+)/g;
115474
+ var AGENT_FS_LIVE_HOSTS = String.raw`agent-fs|live\.agent-fs\.dev`;
115475
+ var AGENT_FS_FILE_ROUTE = String.raw`\/file\/~\/([a-f0-9-]+)\/([a-f0-9-]+)\/([\w/.%-]+)`;
115476
+ var AGENT_UI_PAGE_RE = /(?:app\.[^/]+|localhost:\d+)\/pages\/([a-f0-9-]+)/g;
115477
+ var AGENT_UI_TASK_RE = /(?:app\.[^/]+|localhost:\d+)\/tasks\/([a-f0-9-]+)/g;
115478
+ var wikilinkMatcher = (content) => {
115479
+ const results = [];
115480
+ for (const match of content.matchAll(WIKILINK_RE)) {
115481
+ const name = match[1].trim();
115482
+ if (!name)
115483
+ continue;
115484
+ results.push({
115485
+ linkType: "wikilink",
115486
+ targetKind: "memory",
115487
+ targetId: name,
115488
+ sourceText: match[0],
115489
+ resolver: "wikilink"
115490
+ });
115491
+ }
115492
+ return results;
115493
+ };
115494
+ var prMatcher = (content) => {
115495
+ const results = [];
115496
+ const seen = new Set;
115497
+ for (const match of content.matchAll(GITHUB_PR_URL_RE)) {
115498
+ const id = `github:${match[1]}/${match[2]}#${match[3]}`;
115499
+ if (seen.has(id))
115500
+ continue;
115501
+ seen.add(id);
115502
+ results.push({
115503
+ linkType: "pr",
115504
+ targetKind: "pr",
115505
+ targetId: id,
115506
+ sourceText: match[0],
115507
+ resolver: "pr-url",
115508
+ metadata: { owner: match[1], repo: match[2], number: Number(match[3]) }
115509
+ });
115510
+ }
115511
+ for (const match of content.matchAll(PR_PREFIX_RE)) {
115512
+ const id = `pr:${match[1]}`;
115513
+ if (seen.has(id))
115514
+ continue;
115515
+ seen.add(id);
115516
+ results.push({
115517
+ linkType: "pr",
115518
+ targetKind: "pr",
115519
+ targetId: id,
115520
+ sourceText: match[0].trim(),
115521
+ resolver: "pr-prefix",
115522
+ metadata: { number: Number(match[1]) }
115523
+ });
115524
+ }
115525
+ for (const match of content.matchAll(PR_HASH_RE)) {
115526
+ const id = `pr:${match[1]}`;
115527
+ if (seen.has(id))
115528
+ continue;
115529
+ seen.add(id);
115530
+ results.push({
115531
+ linkType: "pr",
115532
+ targetKind: "pr",
115533
+ targetId: id,
115534
+ sourceText: `#${match[1]}`,
115535
+ resolver: "pr-hash",
115536
+ metadata: { number: Number(match[1]) }
115537
+ });
115538
+ }
115539
+ return results;
115540
+ };
115541
+ function escapeRegExp2(value) {
115542
+ return value.replace(/[.*+?^${}()|[\]\\/]/g, "\\$&");
115543
+ }
115544
+ function agentFsPathRegex() {
115545
+ const appHosts = getConfiguredAppUrls().flatMap((value) => {
115546
+ try {
115547
+ const url = new URL(value);
115548
+ return [escapeRegExp2(`${url.host}${url.pathname.replace(/\/+$/, "")}`)];
115549
+ } catch {
115550
+ return [];
115551
+ }
115552
+ });
115553
+ const hosts = [AGENT_FS_LIVE_HOSTS, ...appHosts, String.raw`localhost:\d+`].join("|");
115554
+ return new RegExp(`(?<![\\w.-])(?:${hosts})${AGENT_FS_FILE_ROUTE}`, "gi");
115555
+ }
115556
+ var agentFsMatcher = (content) => {
115557
+ const results = [];
115558
+ for (const match of content.matchAll(agentFsPathRegex())) {
115559
+ const orgId = match[1];
115560
+ const driveId = match[2];
115561
+ const path = match[3];
115562
+ results.push({
115563
+ linkType: "agent-fs-file",
115564
+ targetKind: "agent-fs-file",
115565
+ targetId: `${orgId}/${driveId}/${path}`,
115566
+ sourceText: match[0],
115567
+ resolver: "agent-fs-path",
115568
+ metadata: { orgId, driveId, path }
115569
+ });
115570
+ }
115571
+ return results;
115572
+ };
115573
+ var agentUiMatcher = (content) => {
115574
+ const results = [];
115575
+ for (const match of content.matchAll(AGENT_UI_PAGE_RE)) {
115576
+ results.push({
115577
+ linkType: "agent-ui",
115578
+ targetKind: "agent-ui",
115579
+ targetId: `page:${match[1]}`,
115580
+ sourceText: match[0],
115581
+ resolver: "agent-ui-page"
115582
+ });
115583
+ }
115584
+ for (const match of content.matchAll(AGENT_UI_TASK_RE)) {
115585
+ results.push({
115586
+ linkType: "agent-ui",
115587
+ targetKind: "agent-ui",
115588
+ targetId: `task:${match[1]}`,
115589
+ sourceText: match[0],
115590
+ resolver: "agent-ui-task"
115591
+ });
115592
+ }
115593
+ return results;
115594
+ };
115595
+ var MATCHERS = [wikilinkMatcher, prMatcher, agentFsMatcher, agentUiMatcher];
115596
+ function resolveLinks(content) {
115597
+ const results = [];
115598
+ for (const matcher of MATCHERS) {
115599
+ for (const link of matcher(content)) {
115600
+ results.push({ ...link, strength: 1 });
115601
+ }
115602
+ }
115603
+ return results;
115604
+ }
115605
+ async function resolveWikilinksToMemoryIds(agentId, links) {
115606
+ const db = getDbClient2();
115607
+ const resolved = [];
115608
+ for (const link of links) {
115609
+ if (link.linkType !== "wikilink") {
115610
+ resolved.push(link);
115611
+ continue;
115612
+ }
115613
+ const row = await db.get("SELECT id FROM agent_memory WHERE name = ? AND (agentId = ? OR scope = 'swarm') LIMIT 1", [link.targetId, agentId]);
115614
+ resolved.push(row ? { ...link, targetId: row.id } : link);
115615
+ }
115616
+ return resolved;
115617
+ }
115618
+ var INSERT_LINK_SQL = `INSERT OR IGNORE INTO memory_link
115619
+ (id, from_memory_id, linkType, targetKind, targetId, strength, resolver, sourceText, metadata, createdAt, updatedAt)
115620
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`;
115621
+ function insertLinkArgs(memoryId, link, now) {
115622
+ return [
115623
+ crypto.randomUUID(),
115624
+ memoryId,
115625
+ link.linkType,
115626
+ link.targetKind,
115627
+ link.targetId,
115628
+ link.strength,
115629
+ link.resolver,
115630
+ link.sourceText,
115631
+ link.metadata ? JSON.stringify(link.metadata) : null,
115632
+ now,
115633
+ now
115634
+ ];
115635
+ }
115636
+ async function storeLinks(memoryId, agentId, content) {
115637
+ const links = resolveLinks(content);
115638
+ if (links.length === 0)
115639
+ return;
115640
+ const resolved = await resolveWikilinksToMemoryIds(agentId, links);
115641
+ const now = new Date().toISOString();
115642
+ await getDbClient2().transaction(async (tx) => {
115643
+ for (const link of resolved) {
115644
+ await tx.run(INSERT_LINK_SQL, insertLinkArgs(memoryId, link, now));
115645
+ }
115646
+ });
115647
+ }
115648
+ function linkIdentity2(link) {
115649
+ return JSON.stringify([link.linkType, link.targetKind, link.targetId, link.sourceText ?? null]);
115650
+ }
115651
+ async function refreshLinks(memoryId, agentId, content) {
115652
+ const resolved = await resolveWikilinksToMemoryIds(agentId, resolveLinks(content));
115653
+ const nextIdentities = new Set(resolved.map((link) => linkIdentity2(link)));
115654
+ const now = new Date().toISOString();
115655
+ await getDbClient2().transaction(async (tx) => {
115656
+ const existing = await tx.query(`SELECT id, linkType, targetKind, targetId, sourceText
115657
+ FROM memory_link
115658
+ WHERE from_memory_id = ? AND linkType != 'sequel'`, [memoryId]);
115659
+ for (const row of existing) {
115660
+ if (!nextIdentities.has(linkIdentity2(row))) {
115661
+ await tx.run("DELETE FROM memory_link WHERE id = ?", [row.id]);
115662
+ }
115663
+ }
115664
+ for (const link of resolved) {
115665
+ await tx.run(INSERT_LINK_SQL, insertLinkArgs(memoryId, link, now));
115666
+ }
115667
+ });
115668
+ }
115669
+
115670
+ // src/be/memory/index-content.ts
115671
+ init_secret_scrubber();
115672
+ function taskCompletionMemoryKey(taskId) {
115673
+ return `/task-completions/${taskId.toLowerCase().replace(/[^a-z0-9._-]/g, "-")}`;
115674
+ }
115675
+ async function indexMemoryContent(params) {
115676
+ const { agentId, content, name, scope, source, sourceTaskId, sourcePath, tags } = params;
115677
+ const rowKey = params.key ?? (sourcePath || null);
115678
+ if (rowKey)
115679
+ assertKeyWritable(rowKey, params.key != null ? "key" : "sourcePath", params.writer);
115680
+ const contentChunks = chunkContent(content);
115681
+ if (contentChunks.length === 0) {
115682
+ contentChunks.push({
115683
+ content: content.trim(),
115684
+ chunkIndex: 0,
115685
+ totalChunks: 1,
115686
+ headings: []
115687
+ });
115688
+ }
115689
+ const store = getMemoryStore2();
115690
+ const provider = getEmbeddingProvider2();
115691
+ if (sourcePath && agentId && contentChunks.length === 1) {
115692
+ const existing = (await store.list(agentId, {
115693
+ scope,
115694
+ limit: 2,
115695
+ ownerAgentId: agentId,
115696
+ sourcePath
115697
+ })).filter((memory) => memory.sourcePath === sourcePath);
115698
+ if (existing.length === 1 && existing[0]?.totalChunks === 1) {
115699
+ const result = await store.edit({
115700
+ id: existing[0].id,
115701
+ mode: "replace",
115702
+ content: contentChunks[0].content,
115703
+ intent: "re-index memory source path",
115704
+ changedByAgentId: agentId
115705
+ });
115706
+ const embedding = await provider.embed(result.memory.content);
115707
+ if (embedding)
115708
+ await store.updateEmbedding(result.memory.id, embedding, provider.name);
115709
+ try {
115710
+ await refreshLinks(result.memory.id, agentId, result.memory.content);
115711
+ } catch (err) {
115712
+ console.error(`[memory] Link resolution failed for ${result.memory.id}:`, err.message);
115713
+ }
115714
+ return { queued: false, memoryIds: [result.memory.id], edited: result.changed, chunks: 1 };
115715
+ }
115716
+ }
115717
+ if (sourcePath && agentId) {
115718
+ await store.deleteBySourcePath(sourcePath, agentId);
115719
+ }
115720
+ const inputs = contentChunks.map((chunk) => ({
115721
+ agentId: agentId || null,
115722
+ content: chunk.content,
115723
+ name,
115724
+ scope,
115725
+ source,
115726
+ sourcePath: sourcePath || null,
115727
+ sourceTaskId: sourceTaskId || null,
115728
+ chunkIndex: chunk.chunkIndex,
115729
+ totalChunks: chunk.totalChunks,
115730
+ tags: tags || [],
115731
+ contextKey: params.contextKey ?? null,
115732
+ intent: params.intent ?? "index memory content",
115733
+ key: rowKey
115734
+ }));
115735
+ const memories = params.replaceExisting && params.key ? await store.replaceDocument({ key: params.key, scope, agentId: agentId || null, source }, inputs) : await store.storeBatch(inputs);
115736
+ if (agentId) {
115737
+ for (const memory of memories) {
115738
+ try {
115739
+ await storeLinks(memory.id, agentId, memory.content);
115740
+ } catch (err) {
115741
+ console.error(`[memory] Link resolution failed for ${memory.id}:`, err.message);
115742
+ }
115743
+ }
115744
+ }
115745
+ (async () => {
115746
+ try {
115747
+ const embeddings = await provider.embedBatch(memories.map((m) => m.content));
115748
+ for (let i = 0;i < embeddings.length; i++) {
115749
+ if (embeddings[i]) {
115750
+ await store.updateEmbedding(memories[i].id, embeddings[i], provider.name);
115751
+ }
115752
+ }
115753
+ } catch (err) {
115754
+ console.error("[memory] Batch embedding failed:", err.message);
115755
+ }
115756
+ })().catch((err) => console.error("[memory] batch embed failed:", scrubSecrets(err instanceof Error ? err.message : String(err))));
115757
+ return { queued: true, memoryIds: memories.map((m) => m.id), chunks: contentChunks.length };
115758
+ }
115759
+
114379
115760
  // src/be/memory/raters/retrieval.ts
114380
115761
  init_db3();
114381
115762
  function dedupeMemoryDocumentIds(memories) {
@@ -115131,40 +116512,39 @@ ${safeFailureReason || "No reason provided"}
115131
116512
  This task failed. Learn from this to avoid repeating the mistake.`;
115132
116513
  if (taskContent.length < 30)
115133
116514
  return;
115134
- const store = getMemoryStore2();
115135
- const provider = getEmbeddingProvider2();
115136
- const memory = await store.store({
116515
+ const key = taskCompletionMemoryKey(taskId);
116516
+ await indexMemoryContent({
115137
116517
  agentId: agentId ?? null,
115138
116518
  content: taskContent,
115139
116519
  name: `Task: ${safeTask.slice(0, 80)}`,
115140
116520
  scope: "agent",
115141
116521
  source: "task_completion",
115142
- sourceTaskId: taskId
116522
+ sourceTaskId: taskId,
116523
+ key,
116524
+ intent: "task completion memory",
116525
+ replaceExisting: true
115143
116526
  });
115144
- const embedding = await provider.embed(taskContent);
115145
- if (embedding) {
115146
- await store.updateEmbedding(memory.id, embedding, provider.name);
115147
- }
115148
116527
  const shouldShareWithSwarm = status === "completed" && (task.taskType === "research" || task.tags?.includes("knowledge") || task.tags?.includes("shared"));
115149
116528
  if (shouldShareWithSwarm) {
115150
116529
  try {
115151
- const swarmMemory = await store.store({
116530
+ await indexMemoryContent({
115152
116531
  agentId: agentId ?? null,
115153
- scope: "swarm",
115154
- name: `Shared: ${safeTask.slice(0, 80)}`,
115155
116532
  content: `Task completed by agent ${agentId}:
115156
116533
 
115157
116534
  ${taskContent}`,
116535
+ name: `Shared: ${safeTask.slice(0, 80)}`,
116536
+ scope: "swarm",
115158
116537
  source: "task_completion",
115159
- sourceTaskId: taskId
116538
+ sourceTaskId: taskId,
116539
+ key,
116540
+ intent: "task completion memory",
116541
+ replaceExisting: true
115160
116542
  });
115161
- const swarmEmbedding = await provider.embed(taskContent);
115162
- if (swarmEmbedding) {
115163
- await store.updateEmbedding(swarmMemory.id, swarmEmbedding, provider.name);
115164
- }
115165
116543
  } catch {}
115166
116544
  }
115167
- } catch {}
116545
+ } catch (err) {
116546
+ console.error("[task-terminal-effects] task completion memory write failed:", scrubSecrets(err instanceof Error ? err.message : String(err)));
116547
+ }
115168
116548
  })().catch((err) => console.error("[task-terminal-effects] task completion memory write failed:", scrubSecrets(err instanceof Error ? err.message : String(err))));
115169
116549
  }
115170
116550
  (async () => {
@@ -117855,258 +119235,7 @@ var registerMemoryDeleteTool = (server) => {
117855
119235
  init_zod();
117856
119236
  init_db3();
117857
119237
  init_memory();
117858
-
117859
- // src/be/memory/key-guard.ts
117860
- init_rbac();
117861
119238
  init_key_paths();
117862
-
117863
- class MemoryKeyError extends Error {
117864
- reason;
117865
- constructor(message, reason) {
117866
- super(message);
117867
- this.reason = reason;
117868
- this.name = "MemoryKeyError";
117869
- }
117870
- }
117871
- var NO_AUTHORITY = {
117872
- principal: { kind: "agent", agentId: "", isLead: false },
117873
- source: "http"
117874
- };
117875
- function shapeError(key, origin) {
117876
- if (key.length <= MEMORY_KEY_MAX_LENGTH && MEMORY_KEY_PATTERN.test(key))
117877
- return null;
117878
- const subject = origin === "sourcePath" ? `sourcePath "${key}" starts with ${LONGTERM_ROOT}, so it is used as the key, but it is not a valid key.` : `Key "${key}" is not a valid key.`;
117879
- return `${subject} ${MEMORY_KEY_PATTERN_MESSAGE}`;
117880
- }
117881
- function assertKeyWritable(key, origin, writer) {
117882
- if (origin === "sourcePath" && !isLongtermKey(key))
117883
- return;
117884
- const shape = shapeError(key, origin);
117885
- if (shape)
117886
- throw new MemoryKeyError(shape, "invalid");
117887
- const pathError = longtermKeyError(key);
117888
- if (pathError)
117889
- throw new MemoryKeyError(pathError, "invalid");
117890
- if (!isConsolidatedKey(key))
117891
- return;
117892
- const { principal, source } = writer ?? NO_AUTHORITY;
117893
- const decision = can({
117894
- principal,
117895
- verb: "memory.write.consolidated",
117896
- resource: { kind: "none" },
117897
- source
117898
- });
117899
- if (!decision.allow)
117900
- throw new MemoryKeyError(consolidatedKeyMessage(key), "forbidden");
117901
- }
117902
-
117903
- // src/tools/memory-edit.ts
117904
- init_key_paths();
117905
-
117906
- // src/be/memory/link-resolver.ts
117907
- init_db3();
117908
- init_constants2();
117909
- var WIKILINK_RE = /\[\[([^\]]+)\]\]/g;
117910
- var PR_HASH_RE = /(?:^|[\s(])#(\d{1,5})(?=[\s,.)!?]|$)/gm;
117911
- var PR_PREFIX_RE = /\bPR\s*#(\d{1,5})\b/gi;
117912
- var GITHUB_PR_URL_RE = /https?:\/\/github\.com\/([\w.-]+)\/([\w.-]+)\/pull\/(\d+)/g;
117913
- var AGENT_FS_LIVE_HOSTS = String.raw`agent-fs|live\.agent-fs\.dev`;
117914
- var AGENT_FS_FILE_ROUTE = String.raw`\/file\/~\/([a-f0-9-]+)\/([a-f0-9-]+)\/([\w/.%-]+)`;
117915
- var AGENT_UI_PAGE_RE = /(?:app\.[^/]+|localhost:\d+)\/pages\/([a-f0-9-]+)/g;
117916
- var AGENT_UI_TASK_RE = /(?:app\.[^/]+|localhost:\d+)\/tasks\/([a-f0-9-]+)/g;
117917
- var wikilinkMatcher = (content) => {
117918
- const results = [];
117919
- for (const match of content.matchAll(WIKILINK_RE)) {
117920
- const name = match[1].trim();
117921
- if (!name)
117922
- continue;
117923
- results.push({
117924
- linkType: "wikilink",
117925
- targetKind: "memory",
117926
- targetId: name,
117927
- sourceText: match[0],
117928
- resolver: "wikilink"
117929
- });
117930
- }
117931
- return results;
117932
- };
117933
- var prMatcher = (content) => {
117934
- const results = [];
117935
- const seen = new Set;
117936
- for (const match of content.matchAll(GITHUB_PR_URL_RE)) {
117937
- const id = `github:${match[1]}/${match[2]}#${match[3]}`;
117938
- if (seen.has(id))
117939
- continue;
117940
- seen.add(id);
117941
- results.push({
117942
- linkType: "pr",
117943
- targetKind: "pr",
117944
- targetId: id,
117945
- sourceText: match[0],
117946
- resolver: "pr-url",
117947
- metadata: { owner: match[1], repo: match[2], number: Number(match[3]) }
117948
- });
117949
- }
117950
- for (const match of content.matchAll(PR_PREFIX_RE)) {
117951
- const id = `pr:${match[1]}`;
117952
- if (seen.has(id))
117953
- continue;
117954
- seen.add(id);
117955
- results.push({
117956
- linkType: "pr",
117957
- targetKind: "pr",
117958
- targetId: id,
117959
- sourceText: match[0].trim(),
117960
- resolver: "pr-prefix",
117961
- metadata: { number: Number(match[1]) }
117962
- });
117963
- }
117964
- for (const match of content.matchAll(PR_HASH_RE)) {
117965
- const id = `pr:${match[1]}`;
117966
- if (seen.has(id))
117967
- continue;
117968
- seen.add(id);
117969
- results.push({
117970
- linkType: "pr",
117971
- targetKind: "pr",
117972
- targetId: id,
117973
- sourceText: `#${match[1]}`,
117974
- resolver: "pr-hash",
117975
- metadata: { number: Number(match[1]) }
117976
- });
117977
- }
117978
- return results;
117979
- };
117980
- function escapeRegExp2(value) {
117981
- return value.replace(/[.*+?^${}()|[\]\\/]/g, "\\$&");
117982
- }
117983
- function agentFsPathRegex() {
117984
- const appHosts = getConfiguredAppUrls().flatMap((value) => {
117985
- try {
117986
- const url = new URL(value);
117987
- return [escapeRegExp2(`${url.host}${url.pathname.replace(/\/+$/, "")}`)];
117988
- } catch {
117989
- return [];
117990
- }
117991
- });
117992
- const hosts = [AGENT_FS_LIVE_HOSTS, ...appHosts, String.raw`localhost:\d+`].join("|");
117993
- return new RegExp(`(?<![\\w.-])(?:${hosts})${AGENT_FS_FILE_ROUTE}`, "gi");
117994
- }
117995
- var agentFsMatcher = (content) => {
117996
- const results = [];
117997
- for (const match of content.matchAll(agentFsPathRegex())) {
117998
- const orgId = match[1];
117999
- const driveId = match[2];
118000
- const path = match[3];
118001
- results.push({
118002
- linkType: "agent-fs-file",
118003
- targetKind: "agent-fs-file",
118004
- targetId: `${orgId}/${driveId}/${path}`,
118005
- sourceText: match[0],
118006
- resolver: "agent-fs-path",
118007
- metadata: { orgId, driveId, path }
118008
- });
118009
- }
118010
- return results;
118011
- };
118012
- var agentUiMatcher = (content) => {
118013
- const results = [];
118014
- for (const match of content.matchAll(AGENT_UI_PAGE_RE)) {
118015
- results.push({
118016
- linkType: "agent-ui",
118017
- targetKind: "agent-ui",
118018
- targetId: `page:${match[1]}`,
118019
- sourceText: match[0],
118020
- resolver: "agent-ui-page"
118021
- });
118022
- }
118023
- for (const match of content.matchAll(AGENT_UI_TASK_RE)) {
118024
- results.push({
118025
- linkType: "agent-ui",
118026
- targetKind: "agent-ui",
118027
- targetId: `task:${match[1]}`,
118028
- sourceText: match[0],
118029
- resolver: "agent-ui-task"
118030
- });
118031
- }
118032
- return results;
118033
- };
118034
- var MATCHERS = [wikilinkMatcher, prMatcher, agentFsMatcher, agentUiMatcher];
118035
- function resolveLinks(content) {
118036
- const results = [];
118037
- for (const matcher of MATCHERS) {
118038
- for (const link of matcher(content)) {
118039
- results.push({ ...link, strength: 1 });
118040
- }
118041
- }
118042
- return results;
118043
- }
118044
- async function resolveWikilinksToMemoryIds(agentId, links) {
118045
- const db = getDbClient2();
118046
- const resolved = [];
118047
- for (const link of links) {
118048
- if (link.linkType !== "wikilink") {
118049
- resolved.push(link);
118050
- continue;
118051
- }
118052
- const row = await db.get("SELECT id FROM agent_memory WHERE name = ? AND (agentId = ? OR scope = 'swarm') LIMIT 1", [link.targetId, agentId]);
118053
- resolved.push(row ? { ...link, targetId: row.id } : link);
118054
- }
118055
- return resolved;
118056
- }
118057
- var INSERT_LINK_SQL = `INSERT OR IGNORE INTO memory_link
118058
- (id, from_memory_id, linkType, targetKind, targetId, strength, resolver, sourceText, metadata, createdAt, updatedAt)
118059
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`;
118060
- function insertLinkArgs(memoryId, link, now) {
118061
- return [
118062
- crypto.randomUUID(),
118063
- memoryId,
118064
- link.linkType,
118065
- link.targetKind,
118066
- link.targetId,
118067
- link.strength,
118068
- link.resolver,
118069
- link.sourceText,
118070
- link.metadata ? JSON.stringify(link.metadata) : null,
118071
- now,
118072
- now
118073
- ];
118074
- }
118075
- async function storeLinks(memoryId, agentId, content) {
118076
- const links = resolveLinks(content);
118077
- if (links.length === 0)
118078
- return;
118079
- const resolved = await resolveWikilinksToMemoryIds(agentId, links);
118080
- const now = new Date().toISOString();
118081
- await getDbClient2().transaction(async (tx) => {
118082
- for (const link of resolved) {
118083
- await tx.run(INSERT_LINK_SQL, insertLinkArgs(memoryId, link, now));
118084
- }
118085
- });
118086
- }
118087
- function linkIdentity2(link) {
118088
- return JSON.stringify([link.linkType, link.targetKind, link.targetId, link.sourceText ?? null]);
118089
- }
118090
- async function refreshLinks(memoryId, agentId, content) {
118091
- const resolved = await resolveWikilinksToMemoryIds(agentId, resolveLinks(content));
118092
- const nextIdentities = new Set(resolved.map((link) => linkIdentity2(link)));
118093
- const now = new Date().toISOString();
118094
- await getDbClient2().transaction(async (tx) => {
118095
- const existing = await tx.query(`SELECT id, linkType, targetKind, targetId, sourceText
118096
- FROM memory_link
118097
- WHERE from_memory_id = ? AND linkType != 'sequel'`, [memoryId]);
118098
- for (const row of existing) {
118099
- if (!nextIdentities.has(linkIdentity2(row))) {
118100
- await tx.run("DELETE FROM memory_link WHERE id = ?", [row.id]);
118101
- }
118102
- }
118103
- for (const link of resolved) {
118104
- await tx.run(INSERT_LINK_SQL, insertLinkArgs(memoryId, link, now));
118105
- }
118106
- });
118107
- }
118108
-
118109
- // src/tools/memory-edit.ts
118110
119239
  init_rbac();
118111
119240
  init_types();
118112
119241
  var agentMemoryOutputSchema = looseObject({
@@ -118670,6 +119799,7 @@ async function expandCandidatesWithGraph(candidates, agentId, options = {}) {
118670
119799
  // src/tools/memory-search.ts
118671
119800
  init_key_paths();
118672
119801
  init_reranker();
119802
+ init_search_candidates();
118673
119803
  init_types();
118674
119804
  var NUDGE_ELIGIBLE_SOURCES2 = new Set(["manual", "file_index"]);
118675
119805
  function rateHintFor(memoryId) {
@@ -118725,7 +119855,7 @@ var registerMemorySearchTool = (server) => {
118725
119855
  const store = getMemoryStore2();
118726
119856
  const queryEmbedding = await provider.embed(query);
118727
119857
  const candidateLimit = limit * CANDIDATE_SET_MULTIPLIER;
118728
- const candidates = await store.search(queryEmbedding ?? new Float32Array(0), requestInfo.agentId, {
119858
+ const candidates = await searchMemoryCandidates(store, queryEmbedding ?? new Float32Array(0), requestInfo.agentId, {
118729
119859
  scope,
118730
119860
  limit: candidateLimit,
118731
119861
  source,
@@ -118813,242 +119943,6 @@ var registerMemorySearchTool = (server) => {
118813
119943
  // src/tools/memory-store.ts
118814
119944
  init_zod();
118815
119945
  init_db3();
118816
-
118817
- // src/be/chunking.ts
118818
- var MAX_CHUNK_SIZE = 2000;
118819
- var CHUNK_OVERLAP = 100;
118820
- var MIN_CHUNK_SIZE = 50;
118821
- function chunkContent(text) {
118822
- const trimmed = text.trim();
118823
- if (!trimmed || trimmed.length < MIN_CHUNK_SIZE) {
118824
- return [];
118825
- }
118826
- if (trimmed.length <= MAX_CHUNK_SIZE) {
118827
- return [{ content: trimmed, chunkIndex: 0, totalChunks: 1, headings: [] }];
118828
- }
118829
- const sections = splitByHeaders(trimmed);
118830
- const rawChunks = [];
118831
- for (const section of sections) {
118832
- if (section.content.length <= MAX_CHUNK_SIZE) {
118833
- rawChunks.push(section);
118834
- } else {
118835
- const subChunks = recursiveSplit(section.content);
118836
- for (const sub of subChunks) {
118837
- rawChunks.push({ content: sub, headings: section.headings });
118838
- }
118839
- }
118840
- }
118841
- const filtered = rawChunks.filter((c) => c.content.trim().length >= MIN_CHUNK_SIZE);
118842
- if (filtered.length === 0) {
118843
- return [{ content: trimmed, chunkIndex: 0, totalChunks: 1, headings: [] }];
118844
- }
118845
- return filtered.map((c, i) => ({
118846
- content: c.headings.length > 0 ? `${c.headings.join(" > ")}
118847
-
118848
- ${c.content}` : c.content,
118849
- chunkIndex: i,
118850
- totalChunks: filtered.length,
118851
- headings: c.headings
118852
- }));
118853
- }
118854
- function splitByHeaders(text) {
118855
- const lines = text.split(`
118856
- `);
118857
- const sections = [];
118858
- let currentContent = [];
118859
- const headingStack = [];
118860
- for (const line of lines) {
118861
- const headingMatch = line.match(/^(#{1,3})\s+(.+)$/);
118862
- if (headingMatch) {
118863
- if (currentContent.length > 0) {
118864
- const content = currentContent.join(`
118865
- `).trim();
118866
- if (content) {
118867
- sections.push({ content, headings: [...headingStack] });
118868
- }
118869
- currentContent = [];
118870
- }
118871
- const level = headingMatch[1].length;
118872
- const title = headingMatch[2].trim();
118873
- while (headingStack.length >= level) {
118874
- headingStack.pop();
118875
- }
118876
- headingStack.push(`${"#".repeat(level)} ${title}`);
118877
- } else {
118878
- currentContent.push(line);
118879
- }
118880
- }
118881
- if (currentContent.length > 0) {
118882
- const content = currentContent.join(`
118883
- `).trim();
118884
- if (content) {
118885
- sections.push({ content, headings: [...headingStack] });
118886
- }
118887
- }
118888
- if (sections.length === 0) {
118889
- return [{ content: text, headings: [] }];
118890
- }
118891
- return sections;
118892
- }
118893
- var SEPARATORS = [`
118894
-
118895
- `, `
118896
- `, ". ", " "];
118897
- function recursiveSplit(text) {
118898
- return recursiveSplitWithSeparators(text, 0);
118899
- }
118900
- function recursiveSplitWithSeparators(text, separatorIndex) {
118901
- if (text.length <= MAX_CHUNK_SIZE) {
118902
- return [text.trim()].filter((s) => s.length > 0);
118903
- }
118904
- if (separatorIndex >= SEPARATORS.length) {
118905
- return hardSplit(text);
118906
- }
118907
- const separator = SEPARATORS[separatorIndex];
118908
- const parts = text.split(separator);
118909
- if (parts.length <= 1) {
118910
- return recursiveSplitWithSeparators(text, separatorIndex + 1);
118911
- }
118912
- const chunks = [];
118913
- let current = "";
118914
- for (const part of parts) {
118915
- const candidate = current ? current + separator + part : part;
118916
- if (candidate.length <= MAX_CHUNK_SIZE) {
118917
- current = candidate;
118918
- } else {
118919
- if (current) {
118920
- chunks.push(current.trim());
118921
- }
118922
- if (part.length > MAX_CHUNK_SIZE) {
118923
- chunks.push(...recursiveSplitWithSeparators(part, separatorIndex + 1));
118924
- current = "";
118925
- } else {
118926
- current = part;
118927
- }
118928
- }
118929
- }
118930
- if (current.trim()) {
118931
- chunks.push(current.trim());
118932
- }
118933
- return addOverlap(chunks, text);
118934
- }
118935
- function hardSplit(text) {
118936
- const chunks = [];
118937
- let start = 0;
118938
- while (start < text.length) {
118939
- const end = Math.min(start + MAX_CHUNK_SIZE, text.length);
118940
- chunks.push(text.slice(start, end).trim());
118941
- if (end === text.length)
118942
- break;
118943
- start = end - CHUNK_OVERLAP;
118944
- }
118945
- return chunks.filter((c) => c.length > 0);
118946
- }
118947
- function addOverlap(chunks, _originalText) {
118948
- if (chunks.length <= 1)
118949
- return chunks;
118950
- const result = [chunks[0]];
118951
- for (let i = 1;i < chunks.length; i++) {
118952
- const prevChunk = chunks[i - 1];
118953
- const chunk = chunks[i];
118954
- const overlapText = prevChunk.slice(-CHUNK_OVERLAP);
118955
- if (overlapText.length + chunk.length <= MAX_CHUNK_SIZE + CHUNK_OVERLAP) {
118956
- result.push(overlapText + chunk);
118957
- } else {
118958
- result.push(chunk);
118959
- }
118960
- }
118961
- return result;
118962
- }
118963
-
118964
- // src/be/memory/index-content.ts
118965
- init_memory();
118966
- init_secret_scrubber();
118967
- async function indexMemoryContent(params) {
118968
- const { agentId, content, name, scope, source, sourceTaskId, sourcePath, tags } = params;
118969
- const rowKey = params.key ?? (sourcePath || null);
118970
- if (rowKey)
118971
- assertKeyWritable(rowKey, params.key != null ? "key" : "sourcePath", params.writer);
118972
- const contentChunks = chunkContent(content);
118973
- if (contentChunks.length === 0) {
118974
- contentChunks.push({
118975
- content: content.trim(),
118976
- chunkIndex: 0,
118977
- totalChunks: 1,
118978
- headings: []
118979
- });
118980
- }
118981
- const store = getMemoryStore2();
118982
- const provider = getEmbeddingProvider2();
118983
- if (sourcePath && agentId && contentChunks.length === 1) {
118984
- const existing = (await store.list(agentId, {
118985
- scope,
118986
- limit: 2,
118987
- ownerAgentId: agentId,
118988
- sourcePath
118989
- })).filter((memory) => memory.sourcePath === sourcePath);
118990
- if (existing.length === 1 && existing[0]?.totalChunks === 1) {
118991
- const result = await store.edit({
118992
- id: existing[0].id,
118993
- mode: "replace",
118994
- content: contentChunks[0].content,
118995
- intent: "re-index memory source path",
118996
- changedByAgentId: agentId
118997
- });
118998
- const embedding = await provider.embed(result.memory.content);
118999
- if (embedding)
119000
- await store.updateEmbedding(result.memory.id, embedding, provider.name);
119001
- try {
119002
- await refreshLinks(result.memory.id, agentId, result.memory.content);
119003
- } catch (err) {
119004
- console.error(`[memory] Link resolution failed for ${result.memory.id}:`, err.message);
119005
- }
119006
- return { queued: false, memoryIds: [result.memory.id], edited: result.changed, chunks: 1 };
119007
- }
119008
- }
119009
- if (sourcePath && agentId) {
119010
- await store.deleteBySourcePath(sourcePath, agentId);
119011
- }
119012
- const memories = await store.storeBatch(contentChunks.map((chunk) => ({
119013
- agentId: agentId || null,
119014
- content: chunk.content,
119015
- name,
119016
- scope,
119017
- source,
119018
- sourcePath: sourcePath || null,
119019
- sourceTaskId: sourceTaskId || null,
119020
- chunkIndex: chunk.chunkIndex,
119021
- totalChunks: chunk.totalChunks,
119022
- tags: tags || [],
119023
- contextKey: params.contextKey ?? null,
119024
- intent: params.intent ?? "index memory content",
119025
- key: rowKey
119026
- })));
119027
- if (agentId) {
119028
- for (const memory of memories) {
119029
- try {
119030
- await storeLinks(memory.id, agentId, memory.content);
119031
- } catch (err) {
119032
- console.error(`[memory] Link resolution failed for ${memory.id}:`, err.message);
119033
- }
119034
- }
119035
- }
119036
- (async () => {
119037
- try {
119038
- const embeddings = await provider.embedBatch(memories.map((m) => m.content));
119039
- for (let i = 0;i < embeddings.length; i++) {
119040
- if (embeddings[i]) {
119041
- await store.updateEmbedding(memories[i].id, embeddings[i], provider.name);
119042
- }
119043
- }
119044
- } catch (err) {
119045
- console.error("[memory] Batch embedding failed:", err.message);
119046
- }
119047
- })().catch((err) => console.error("[memory] batch embed failed:", scrubSecrets(err instanceof Error ? err.message : String(err))));
119048
- return { queued: true, memoryIds: memories.map((m) => m.id), chunks: contentChunks.length };
119049
- }
119050
-
119051
- // src/tools/memory-store.ts
119052
119946
  init_key_paths();
119053
119947
  init_types();
119054
119948
  var registerMemoryStoreTool = (server) => {
@@ -131584,33 +132478,35 @@ function formatFileSize2(bytes) {
131584
132478
  return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
131585
132479
  return `${(bytes / (1024 * 1024 * 1024)).toFixed(1)} GB`;
131586
132480
  }
131587
- function buildAttachmentText(files, failed = []) {
132481
+ function buildAttachmentText(files, failed = [], notes = new Map) {
131588
132482
  const reasons = new Map(failed.map((f) => [f.file.id, f.reason]));
131589
132483
  return files.map((f) => {
131590
132484
  const size = typeof f.size === "number" ? formatFileSize2(f.size) : "unknown size";
131591
132485
  const line = `[File: ${f.name ?? f.id} (${f.mimetype ?? "unknown type"}, ${size}) id=${f.id}]`;
131592
132486
  const reason = reasons.get(f.id);
131593
- return reason ? `${line} (not attached: ${reason})` : line;
132487
+ const note = notes.get(f.id);
132488
+ return [reason ? `${line} (not attached: ${reason})` : line, note].filter(Boolean).join(`
132489
+ `);
131594
132490
  }).join(`
131595
132491
  `);
131596
132492
  }
131597
- function buildEffectiveText(text, files, failed) {
132493
+ function buildEffectiveText(text, files, failed, notes) {
131598
132494
  const hasText = !!text?.trim();
131599
132495
  const hasFiles = files && files.length > 0;
131600
132496
  if (hasText && hasFiles) {
131601
132497
  return `${text}
131602
132498
 
131603
- ${buildAttachmentText(files, failed)}`;
132499
+ ${buildAttachmentText(files, failed, notes)}`;
131604
132500
  }
131605
132501
  if (hasFiles) {
131606
- return buildAttachmentText(files, failed);
132502
+ return buildAttachmentText(files, failed, notes);
131607
132503
  }
131608
132504
  return text || "";
131609
132505
  }
131610
132506
  function bufferedFileFailures(files) {
131611
132507
  return (files ?? []).map((file) => ({ file, reason: BUFFERED_REASON }));
131612
132508
  }
131613
- async function fetchSlackFiles(client, files) {
132509
+ async function fetchSlackFiles(client, files, options = {}) {
131614
132510
  let dir;
131615
132511
  const result = {
131616
132512
  files: [],
@@ -131636,8 +132532,19 @@ async function fetchSlackFiles(client, files) {
131636
132532
  result.fetched.push({ file, ...outcome });
131637
132533
  }
131638
132534
  }
132535
+ if (options.transcribe) {
132536
+ result.notes = await transcribeAudioNotes(result.fetched.filter(({ file }) => isSlackAudio(file)).map(({ file, path }) => ({
132537
+ key: file.id,
132538
+ name: file.name ?? file.id,
132539
+ data: Bun.file(path),
132540
+ mimeType: file.mimetype
132541
+ })), "[Slack]");
132542
+ }
131639
132543
  return result;
131640
132544
  }
132545
+ function isSlackAudio(file) {
132546
+ return file.subtype === "slack_audio" || Boolean(file.mimetype?.startsWith("audio/"));
132547
+ }
131641
132548
  function looksLikeSignIn(head) {
131642
132549
  const joined = new Uint8Array(head.reduce((total, part) => total + part.byteLength, 0));
131643
132550
  let offset = 0;
@@ -133851,9 +134758,9 @@ var registerSystemOneDecideTool = (server) => {
133851
134758
  createToolRegistrar(server)("system-one-decide", {
133852
134759
  title: "Ask a SystemOne decision model",
133853
134760
  annotations: { destructiveHint: false, openWorldHint: true },
133854
- description: "Send a state and typed questions (noul, choice, score) to a SystemOne decision host such as Jev, and return the validated answers. " + "Same request, provider list, credentials and validation as the `system-one-decision` workflow node, without its human review band. " + "The provider credential is a global secret that stays on the server; this tool never returns it.",
134761
+ description: "Send a state and typed questions (noul, choice, score) to a SystemOne decision host such as Jev or Clef, and return the validated answers. " + "Same request, provider list, credentials and validation as the `system-one-decision` workflow node, without its human review band. " + "The provider credential is a global secret that stays on the server; this tool never returns it.",
133855
134762
  inputSchema: object2({
133856
- provider: _enum2(SYSTEM_ONE_PROVIDER_IDS).optional().describe("Decision host (default typesafe)"),
134763
+ provider: _enum2(SYSTEM_ONE_PROVIDER_IDS).optional().describe("Decision host (default: the SYSTEM_ONE_DEFAULT_PROVIDER global config, typesafe when unset)"),
133857
134764
  model: string2().min(1).optional().describe("Provider model id (default: the provider's)"),
133858
134765
  state: union2([string2(), array2(string2()), record2(string2(), unknown())]).describe("The state to decide on"),
133859
134766
  questions: record2(string2(), record2(string2(), unknown())).describe("Questions by id, each `{ type: 'noul' | 'choice' | 'score', instructions, criteria }`"),
@@ -133864,7 +134771,8 @@ var registerSystemOneDecideTool = (server) => {
133864
134771
  model: string2().optional(),
133865
134772
  answers: record2(string2(), unknown()).optional(),
133866
134773
  usage: record2(string2(), unknown()).optional(),
133867
- requestId: string2().optional()
134774
+ requestId: string2().optional(),
134775
+ providerUnavailable: boolean().optional().describe("On an error: true when this deployment refuses the provider (e.g. OpenRouter behind a gateway) and no request was sent, so a caller choosing automatically can try its next provider")
133868
134776
  })
133869
134777
  }, async ({ provider, model, state, questions, timeoutMs, maxRetries }, requestInfo) => {
133870
134778
  if (!requestInfo.agentId) {
@@ -133889,8 +134797,9 @@ var registerSystemOneDecideTool = (server) => {
133889
134797
  return toolErr("The system-one-decision executor is not available");
133890
134798
  }
133891
134799
  const decided = await executor.decide(parsed.data);
133892
- if (!decided.ok)
133893
- return toolErr(decided.error);
134800
+ if (!decided.ok) {
134801
+ return toolErr(decided.error, decided.deploymentRefused ? { data: { providerUnavailable: true } } : {});
134802
+ }
133894
134803
  const { output } = decided;
133895
134804
  return toolOk(`Decision from ${output.model}`, {
133896
134805
  data: {
@@ -135887,7 +136796,8 @@ async function createServer(opts = {}) {
135887
136796
  ...opts.preloadedTools?.length ? { instructions: resolveTemplate("system.agent.tool_preload", {}).text } : {},
135888
136797
  capabilities: {
135889
136798
  logging: {}
135890
- }
136799
+ },
136800
+ maxToolInputElements: MCP_MAX_TOOL_INPUT_ELEMENTS
135891
136801
  });
135892
136802
  if (opts.preloadedTools?.length)
135893
136803
  setPreloadedTools(server, opts.preloadedTools);
@@ -136122,4 +137032,4 @@ async function createServer(opts = {}) {
136122
137032
  return server;
136123
137033
  }
136124
137034
 
136125
- export { DEFAULT_NEGOTIATED_PROTOCOL_VERSION, SUPPORTED_PROTOCOL_VERSIONS, isJSONRPCRequest, isJSONRPCResultResponse, isJSONRPCErrorResponse, JSONRPCMessageSchema, isInitializeRequest, McpServer, isGitHubEnabled, initGitHub, verifyWebhookSignature, isAgentMailEnabled, initAgentMail, verifyAgentMailWebhook, resolveIdentity, renderIdentity, createAdditiveBuffer, taskModelPin, resumedTaskModelSelection, listHarnessModelSupport, recordHarnessModelSupport, agentRanModel, getAgentHarnessCliVersion, setAgentHarnessCliVersion, sanitizeModelTierOverrides, parseModelTierOverridesHeader, setAgentModelTierOverrides, previewModelTiers, recordClaimModelResolution, harnessModelErrorFor, poolTaskRunsOnHarness, explicitModelError, explicitModelErrorForAgent, referencedBundlePaths, skillDirs, TaskCreationBlockedError, recordUnmappedIdentity, MAX_TASK_ATTACHMENT_BYTES, recordTaskAttachmentUpload, buildEffectiveText, bufferedFileFailures, fetchSlackFiles, createSlackTaskWithFiles, notifySlackFileFailures, isRuntimePoolWakeable, isAgentReachable, hasOtherUserMention, broadcastMatches, routeMessage, extractTaskFromMessage, extractSlackMessageText, recoverIncompleteRuns, handleWebhookTrigger, verifyHmacSignature, WebhookError, snapshotAndUpdateWorkflow, RawLlmConfigSchema, RawLlmOutputSchema, executeRawLlm, getExecutorRegistry2, initWorkflows2, dispatchScheduleTarget, calculateNextRun2, startScheduler2, stopScheduler2, runScheduleNow2, ExtensionAssetConflictError, ExtensionOwnershipError, getExtensionFiles, getExtensionById, getExtensionByName, listExtensions, listExtensionVersions, updateExtensionMeta, listExtensionRuns, SDK_ALLOWLIST, mcpToolNameForSdkMethod, mcpOverflowAuthError, hasKvViewArgs, resolveKvView, toolErr, createToolRegistrar, handleMcpBridge, Redacted, SCRIPT_SDK_RESPONSE_LIMIT_BYTES, readScriptSdkJsonResponse, ExtensionConfigError, ExtensionLifecycleError, setExtensionLoopbackBaseUrl, enableExtension, disableExtension, activateVersion, ExtensionAssetsInvalidError, installExtensionWithAssets, uninstallExtension, reloadExtension, loadEnabledExtensions, stopExtensionRuntime, ExtensionAbortedError2, isRegistered2, isExtensionAgentId2, getExtensionBridgeToken2, resolveBridgeCallOrigin2, extensionIdForAgent2, runContext2, registerLoaded2, unregister2, listRegistered2, dispatchPre2, dispatchPost2, stripSiblingBlock, createTaskWithSiblingAwareness, isInboxAllowed, isSenderAllowed, handleMessageReceived, isAzureDevOpsEnabled, initAzureDevOps, verifyAzureDevOpsWebhook, repointTrackerSyncBySwarmId, isAzureDevOpsUrl, canonicalAzureDevOpsRepoUrl, parseAzureDevOpsRepoUrl, createdPullRequestOf, commentedPayloadOf, handlePullRequestCreated, handlePullRequestCommented, handleWorkItemCreated, handleWorkItemUpdated, handleWorkItemCommented, handleWorkItemDeleted, handleWorkItemRestored, initAzureDevOpsOutbound, AGENT_MAX_TASKS_CONFIG_KEY, reconcileAgentMaxTasksPolicy, resetAgentMaxTasksMirror, upsertSwarmConfigWithPolicyMirror, runtimeStaleThresholdMinutes, upsertRuntimeInstance, getRuntimeInstanceById, insertProvisioningRuntime, markRuntimeTerminated, touchRuntimeInstance, countActiveRuntimeInstancesForAgent, listRuntimeInstancesForAgent, setRuntimeCredentialReady, reconcileAgentStatusFromRuntimes, agentsWithLiveRuntime, expireStaleRuntimeInstances, listRuntimeInstancesForPool, enqueueAuditRow, enqueueAdmissionRow, flushAuditBuffer, startAuditWriter, stopAuditWriter, startAuditGc, stopAuditGc, getTelemetryIngestAnchor, initApiTelemetry, syncTelemetryEnabled, handlePullRequest, handleIssue, handleComment, handlePullRequestReview, handleCheckRun, handleCheckSuite, handleWorkflowRun, isGitLabEnabled, initGitLab, verifyGitLabWebhook, handleMergeRequest, handleIssue2, handleNote, handlePipeline, isChatSdkEnabled, getChatSdkConfig, errorMessage, resolveAdapterApiUrl, trackBackground, TelegramBotApiError, callTelegramBotApi, isTrustedTeamsServiceUrl, isChatSdkStopping, startChatSdk, getChatInstance, isChatAdapterConfigured, getChatSdkHealth, stopChatSdk, getJiraMetadata, updateJiraMetadata, clearJiraMetadata, registerJiraWebhook, deleteJiraWebhook, isJiraEnabled, initJira, handleJiraWebhook, handleAgentSessionEvent, handleIssueUpdate, handleIssueDelete, handleAgentSessionPrompted, isLinearEnabled, initLinear, parseCookieHeader, extractAndVerifyCookie, issuePageSessionCookie, resolveHttpRequestAuth, loadGlobalConfigsIntoEnv, reloadGlobalConfigsAndIntegrations, scheduleIntegrationsReload, handleCore, userCtx, handleApps, cancelApprovalRequest, cancelApprovalRequestAndRun, getUserCommsPrefs, getTaskDetailsInputSchema, getTaskDetailsOutputSchema, getTaskDetailsHandler, cancelTaskInputSchema, cancelTaskOutputSchema, cancelTaskHandler, executeReadOnlyQuery, assertSelectOnlyQuery, handleDbQuery, snapshotMetric, AssetKeyAuthorizationError, authorizeAssetKeyWrite, getPageEditCounter, snapshotPage, assertOAuthAppUrlsSafe, assertOAuthEgressUrlSafe, listOAuthPresets, listOAuthPresetIds, getOAuthPreset, hydrateOAuthAppFromPreset, scopedResourceScopeIdSchema, resolveScopedResourceId, dedupeMemoryDocumentIds, recordMemoryAccesses, recordRetrievals, ExplicitSelfDuplicateError, applyRating, shouldPersistAutomaticTaskMemory, REBOOT_RETRY_PIN_TAG, getPinCandidateAgent, resolveLeadOnlyRecoveryAssignment, getResumeGeneration, getNextResumeGeneration, inheritedModelSelection, createWorkerTaskFollowUp, createResumeFollowUp, createRerouteDecisionTask, createPoolStarvationDecisionTask, guardTerminalTaskResultWrite, getTasksInputSchema, getTasksOutputSchema, getTasksHandler, reservedNamespaceError, reservedRoomKeyError, updateMcpServerChecked, updateTouchesStdioExecution, MemoryKeyError, refreshLinks, canReadMemory, getLinksForMemory, expandCandidatesWithGraph, indexMemoryContent, isApiDraining, drainApi, markKapsoMessageRead, sendKapsoReaction, getKapsoConfig, getKapsoNumberMapping, markKapsoMessageSeen, changesAllowMerge, updateSwarmRepoChecked, getCombConfig, resolveRoomNamespace, roomRequestInfo, authorizeRoomNamespace, sessionAccessTopic, sessionPresenceRoot, RoomOperationSchema, removeAwarenessStates, roomTopic, decodeRoomSnapshot, roomView, getRoom, changeRoom, applyRoomUpdate, resetRoom, sweepRooms, closeRooms, removeNamespaceRooms, MEMORY_KEYS_DEFAULT_PREFIX, MEMORY_KEYS_MAX_LIMIT, estimateTokens, posteriorMean, listMemoryKeys, checkChunkIntegrity, getMemoryChunks, getPosteriorsByIds, createEvent, createEventsBatch, getEventCountsFiltered, getEventsFiltered, mergeScheduleTiming, validateRecurringTiming, checkOutputSchemaShape, sendTaskOutputSchema, sendTaskHandler, steerTaskUserInputSchema, steerTaskOutputSchema, steerTaskHandler, canClaim, emitBudgetRefusalSideEffects, workflowModelErrors, patchWorkflowDefinition, resolveScriptsOnlyMode, ALL_CAPABILITIES, hasCapability, getEnabledCapabilities, createServer };
137035
+ export { DEFAULT_NEGOTIATED_PROTOCOL_VERSION, SUPPORTED_PROTOCOL_VERSIONS, isJSONRPCRequest, isJSONRPCResultResponse, isJSONRPCErrorResponse, JSONRPCMessageSchema, isInitializeRequest, McpServer, isGitHubEnabled, initGitHub, verifyWebhookSignature, isAgentMailEnabled, initAgentMail, verifyAgentMailWebhook, resolveIdentity, renderIdentity, createAdditiveBuffer, taskModelPin, resumedTaskModelSelection, listHarnessModelSupport, recordHarnessModelSupport, agentRanModel, getAgentHarnessCliVersion, setAgentHarnessCliVersion, sanitizeModelTierOverrides, parseModelTierOverridesHeader, setAgentModelTierOverrides, previewModelTiers, recordClaimModelResolution, harnessModelErrorFor, poolTaskRunsOnHarness, explicitModelError, explicitModelErrorForAgent, referencedBundlePaths, skillDirs, TaskCreationBlockedError, recordUnmappedIdentity, MAX_TASK_ATTACHMENT_BYTES, recordTaskAttachmentUpload, scopeFromAttachment, backingProviderId, transcribeAudioNotes, buildEffectiveText, bufferedFileFailures, fetchSlackFiles, createSlackTaskWithFiles, notifySlackFileFailures, isRuntimePoolWakeable, isAgentReachable, hasOtherUserMention, broadcastMatches, routeMessage, extractTaskFromMessage, extractSlackMessageText, recoverIncompleteRuns, handleWebhookTrigger, verifyHmacSignature, WebhookError, snapshotAndUpdateWorkflow, RawLlmConfigSchema, RawLlmOutputSchema, executeRawLlm, getExecutorRegistry2, initWorkflows2, dispatchScheduleTarget, calculateNextRun2, startScheduler2, stopScheduler2, runScheduleNow2, ExtensionAssetConflictError, ExtensionOwnershipError, getExtensionFiles, getExtensionById, getExtensionByName, listExtensions, listExtensionVersions, updateExtensionMeta, listExtensionRuns, SDK_ALLOWLIST, mcpToolNameForSdkMethod, mcpOverflowAuthError, hasKvViewArgs, resolveKvView, toolErr, createToolRegistrar, handleMcpBridge, Redacted, SCRIPT_SDK_RESPONSE_LIMIT_BYTES, readScriptSdkJsonResponse, ExtensionConfigError, ExtensionLifecycleError, setExtensionLoopbackBaseUrl, enableExtension, disableExtension, activateVersion, ExtensionAssetsInvalidError, installExtensionWithAssets, uninstallExtension, reloadExtension, loadEnabledExtensions, stopExtensionRuntime, ExtensionAbortedError2, isRegistered2, isExtensionAgentId2, getExtensionBridgeToken2, resolveBridgeCallOrigin2, extensionIdForAgent2, runContext2, registerLoaded2, unregister2, listRegistered2, dispatchPre2, dispatchPost2, stripSiblingBlock, createTaskWithSiblingAwareness, isInboxAllowed, isSenderAllowed, handleMessageReceived, isAzureDevOpsEnabled, initAzureDevOps, verifyAzureDevOpsWebhook, repointTrackerSyncBySwarmId, isAzureDevOpsUrl, canonicalAzureDevOpsRepoUrl, parseAzureDevOpsRepoUrl, createdPullRequestOf, commentedPayloadOf, handlePullRequestCreated, handlePullRequestCommented, handleWorkItemCreated, handleWorkItemUpdated, handleWorkItemCommented, handleWorkItemDeleted, handleWorkItemRestored, initAzureDevOpsOutbound, AGENT_MAX_TASKS_CONFIG_KEY, reconcileAgentMaxTasksPolicy, resetAgentMaxTasksMirror, upsertSwarmConfigWithPolicyMirror, runtimeStaleThresholdMinutes, upsertRuntimeInstance, getRuntimeInstanceById, insertProvisioningRuntime, markRuntimeTerminated, touchRuntimeInstance, countActiveRuntimeInstancesForAgent, listRuntimeInstancesForAgent, setRuntimeCredentialReady, reconcileAgentStatusFromRuntimes, agentsWithLiveRuntime, expireStaleRuntimeInstances, listRuntimeInstancesForPool, enqueueAuditRow, enqueueAdmissionRow, flushAuditBuffer, startAuditWriter, stopAuditWriter, startAuditGc, stopAuditGc, getTelemetryIngestAnchor, initApiTelemetry, syncTelemetryEnabled, handlePullRequest, handleIssue, handleComment, handlePullRequestReview, handleCheckRun, handleCheckSuite, handleWorkflowRun, isGitLabEnabled, initGitLab, verifyGitLabWebhook, handleMergeRequest, handleIssue2, handleNote, handlePipeline, isChatSdkEnabled, getChatSdkConfig, errorMessage, resolveAdapterApiUrl, trackBackground, TelegramBotApiError, callTelegramBotApi, isTrustedTeamsServiceUrl, isChatSdkStopping, startChatSdk, getChatInstance, isChatAdapterConfigured, getChatSdkHealth, stopChatSdk, getJiraMetadata, updateJiraMetadata, clearJiraMetadata, registerJiraWebhook, deleteJiraWebhook, isJiraEnabled, initJira, handleJiraWebhook, handleAgentSessionEvent, handleIssueUpdate, handleIssueDelete, handleAgentSessionPrompted, isLinearEnabled, initLinear, isCookieSafePageId, extractPageSession, extractLegacyPageSession, extractAndVerifyCookie, pageSessionSetCookies, resolveHttpRequestAuth, loadGlobalConfigsIntoEnv, reloadGlobalConfigsAndIntegrations, scheduleIntegrationsReload, handleCore, MCP_MAX_TOOL_INPUT_ELEMENTS, MCP_MAX_REQUEST_BODY_BYTES, userCtx, requestPrincipal, agentFirstPrincipal, rejectGuest, handleApps, cancelApprovalRequest, cancelApprovalRequestAndRun, getUserCommsPrefs, getTaskDetailsInputSchema, getTaskDetailsOutputSchema, getTaskDetailsHandler, cancelTaskInputSchema, cancelTaskOutputSchema, cancelTaskHandler, executeReadOnlyQuery, assertSelectOnlyQuery, handleDbQuery, snapshotMetric, AssetKeyAuthorizationError, authorizeAssetKeyWrite, getPageEditCounter, snapshotPage, assertOAuthAppUrlsSafe, assertOAuthEgressUrlSafe, listOAuthPresets, listOAuthPresetIds, getOAuthPreset, hydrateOAuthAppFromPreset, scopedResourceScopeIdSchema, resolveScopedResourceId, MemoryKeyError, refreshLinks, indexMemoryContent, dedupeMemoryDocumentIds, recordMemoryAccesses, recordRetrievals, ExplicitSelfDuplicateError, applyRating, shouldPersistAutomaticTaskMemory, REBOOT_RETRY_PIN_TAG, getPinCandidateAgent, resolveLeadOnlyRecoveryAssignment, getResumeGeneration, getNextResumeGeneration, inheritedModelSelection, createWorkerTaskFollowUp, createResumeFollowUp, createRerouteDecisionTask, createPoolStarvationDecisionTask, guardTerminalTaskResultWrite, getTasksInputSchema, getTasksOutputSchema, getTasksHandler, reservedNamespaceError, reservedRoomKeyError, updateMcpServerChecked, updateTouchesStdioExecution, canReadMemory, getLinksForMemory, expandCandidatesWithGraph, isApiDraining, drainApi, markKapsoMessageRead, sendKapsoReaction, getKapsoConfig, getKapsoNumberMapping, markKapsoMessageSeen, changesAllowMerge, updateSwarmRepoChecked, getCombConfig, resolveRoomNamespace, roomRequestInfo, authorizeRoomNamespace, sessionAccessTopic, sessionPresenceRoot, RoomOperationSchema, removeAwarenessStates, roomTopic, decodeRoomSnapshot, roomView, getRoom, changeRoom, applyRoomUpdate, resetRoom, sweepRooms, closeRooms, removeNamespaceRooms, MEMORY_KEYS_DEFAULT_PREFIX, MEMORY_KEYS_MAX_LIMIT, estimateTokens, posteriorMean, listMemoryKeys, checkChunkIntegrity, getMemoryChunks, getPosteriorsByIds, createEvent, createEventsBatch, getEventCountsFiltered, getEventsFiltered, mergeScheduleTiming, validateRecurringTiming, checkOutputSchemaShape, sendTaskOutputSchema, sendTaskHandler, steerTaskUserInputSchema, steerTaskOutputSchema, steerTaskHandler, canClaim, emitBudgetRefusalSideEffects, workflowModelErrors, patchWorkflowDefinition, resolveScriptsOnlyMode, ALL_CAPABILITIES, hasCapability, getEnabledCapabilities, createServer };