@agent-native/core 0.113.0 → 0.114.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (1508) hide show
  1. package/agent-native.eject.json +164 -0
  2. package/corpus/README.md +3 -3
  3. package/corpus/core/CHANGELOG.md +11 -0
  4. package/corpus/core/README.md +61 -174
  5. package/corpus/core/agent-native.eject.json +164 -0
  6. package/corpus/core/docs/content/agent-native-toolkit.mdx +38 -0
  7. package/corpus/core/docs/content/package-lifecycle.mdx +54 -4
  8. package/corpus/core/package.json +15 -2
  9. package/corpus/core/src/cli/eject.ts +1594 -0
  10. package/corpus/core/src/cli/index.ts +16 -0
  11. package/corpus/core/src/client/index.ts +4 -0
  12. package/corpus/core/src/client/resources/McpConnectionSuggestion.tsx +8 -2
  13. package/corpus/core/src/client/resources/McpIntegrationDialog.tsx +7 -2
  14. package/corpus/core/src/client/resources/ResourcesPanel.tsx +17 -3
  15. package/corpus/core/src/client/resources/index.ts +19 -0
  16. package/corpus/core/src/client/resources/mcp-integration-catalog.ts +9 -1
  17. package/corpus/core/src/client/resources/runtime.ts +1 -0
  18. package/corpus/core/src/client/setup-connections/catalog.ts +6 -0
  19. package/corpus/core/src/client/setup-connections/index.ts +1 -0
  20. package/corpus/core/src/client/setup-connections/runtime.ts +1 -0
  21. package/corpus/core/src/connections/catalog.ts +41 -24
  22. package/corpus/core/src/connections/index.ts +1 -0
  23. package/corpus/core/src/connections/runtime.ts +1 -0
  24. package/corpus/core/src/eject/provider-api-definitions.ts +193 -0
  25. package/corpus/core/src/eject/remote-mcp-presets.ts +137 -0
  26. package/corpus/core/src/eject/setup-readiness-ui.tsx +29 -0
  27. package/corpus/core/src/eject/workspace-connections.ts +92 -0
  28. package/corpus/core/src/index.ts +1 -0
  29. package/corpus/core/src/integrations/adapter-overrides.ts +12 -0
  30. package/corpus/core/src/integrations/eject/messaging-adapters.ts +85 -0
  31. package/corpus/core/src/integrations/index.ts +5 -1
  32. package/corpus/core/src/integrations/plugin.ts +34 -12
  33. package/corpus/core/src/integrations/runtime.ts +1 -0
  34. package/corpus/core/src/integrations/types.ts +3 -1
  35. package/corpus/core/src/package-lifecycle/eject-manifest.ts +345 -0
  36. package/corpus/core/src/package-lifecycle/index.ts +1 -0
  37. package/corpus/core/src/provider-api/index.ts +46 -12
  38. package/corpus/core/src/provider-api/runtime.ts +1 -0
  39. package/corpus/core/src/setup-connections/index.ts +1 -0
  40. package/corpus/core/src/shared/merge-by-id.ts +14 -0
  41. package/corpus/core/src/templates/default/.agents/skills/agent-native-docs/SKILL.md +15 -13
  42. package/corpus/core/src/templates/default/.agents/skills/customizing-agent-native/SKILL.md +63 -20
  43. package/corpus/core/src/templates/default/.agents/skills/self-modifying-code/SKILL.md +9 -6
  44. package/corpus/core/src/templates/default/AGENTS.md +6 -5
  45. package/corpus/core/src/templates/headless/.agents/skills/agent-native-docs/SKILL.md +15 -13
  46. package/corpus/core/src/templates/headless/.agents/skills/customizing-agent-native/SKILL.md +63 -20
  47. package/corpus/core/src/templates/headless/AGENTS.md +5 -4
  48. package/corpus/core/src/templates/workspace-core/.agents/skills/agent-native-docs/SKILL.md +15 -13
  49. package/corpus/core/src/templates/workspace-core/.agents/skills/agent-native-toolkit/SKILL.md +3 -2
  50. package/corpus/core/src/templates/workspace-core/.agents/skills/customizing-agent-native/SKILL.md +63 -20
  51. package/corpus/core/src/templates/workspace-core/.agents/skills/self-modifying-code/SKILL.md +9 -6
  52. package/corpus/core/src/templates/workspace-core/AGENTS.md +4 -4
  53. package/corpus/core/src/templates/workspace-root/AGENTS.md +4 -4
  54. package/corpus/core/src/vite/client.ts +25 -2
  55. package/corpus/templates/analytics/.agents/skills/customizing-agent-native/SKILL.md +63 -20
  56. package/corpus/templates/analytics/.agents/skills/self-modifying-code/SKILL.md +9 -6
  57. package/corpus/templates/assets/.agents/skills/customizing-agent-native/SKILL.md +63 -20
  58. package/corpus/templates/assets/.agents/skills/self-modifying-code/SKILL.md +9 -6
  59. package/corpus/templates/brain/.agents/skills/customizing-agent-native/SKILL.md +63 -20
  60. package/corpus/templates/brain/.agents/skills/self-modifying-code/SKILL.md +9 -6
  61. package/corpus/templates/brain/actions/remediate-legacy-capture-audiences.ts +167 -0
  62. package/corpus/templates/brain/app/lib/brain-chat-readiness.ts +6 -0
  63. package/corpus/templates/brain/app/routes/_index.tsx +8 -0
  64. package/corpus/templates/brain/app/routes.ts +1 -0
  65. package/corpus/templates/brain/changelog/2026-07-19-ask-starts-immediately-when-builder-s-managed-ai-connection-.md +6 -0
  66. package/corpus/templates/brain/changelog/2026-07-19-slack-and-granola-backfills-now-process-captures-concurrentl.md +6 -0
  67. package/corpus/templates/brain/changelog/2026-07-19-source-review-settings-now-control-knowledge-approval.md +6 -0
  68. package/corpus/templates/brain/changelog/2026-07-19-the-manage-agent-page-now-opens-correctly-from-brain-navigat.md +6 -0
  69. package/corpus/templates/brain/server/db/schema.ts +3 -0
  70. package/corpus/templates/brain/server/lib/brain.ts +41 -2
  71. package/corpus/templates/brain/server/lib/connectors.ts +379 -113
  72. package/corpus/templates/brain/server/lib/meeting-audience.ts +38 -0
  73. package/corpus/templates/brain/server/plugins/db.ts +10 -0
  74. package/corpus/templates/brain/server/routes/api/_agent-native/brain/ingest.post.ts +6 -4
  75. package/corpus/templates/calendar/.agents/skills/customizing-agent-native/SKILL.md +63 -20
  76. package/corpus/templates/calendar/.agents/skills/self-modifying-code/SKILL.md +9 -6
  77. package/corpus/templates/chat/.agents/skills/agent-native-docs/SKILL.md +15 -13
  78. package/corpus/templates/chat/.agents/skills/customizing-agent-native/SKILL.md +63 -20
  79. package/corpus/templates/chat/.agents/skills/self-modifying-code/SKILL.md +9 -6
  80. package/corpus/templates/chat/AGENTS.md +3 -2
  81. package/corpus/templates/clips/.agents/skills/customizing-agent-native/SKILL.md +63 -20
  82. package/corpus/templates/clips/.agents/skills/self-modifying-code/SKILL.md +9 -6
  83. package/corpus/templates/content/.agents/skills/customizing-agent-native/SKILL.md +63 -20
  84. package/corpus/templates/content/.agents/skills/self-modifying-code/SKILL.md +9 -6
  85. package/corpus/templates/design/.agents/skills/customizing-agent-native/SKILL.md +63 -20
  86. package/corpus/templates/design/.agents/skills/self-modifying-code/SKILL.md +9 -6
  87. package/corpus/templates/dispatch/.agents/skills/customizing-agent-native/SKILL.md +63 -20
  88. package/corpus/templates/dispatch/.agents/skills/self-modifying-code/SKILL.md +9 -6
  89. package/corpus/templates/forms/.agents/skills/customizing-agent-native/SKILL.md +63 -20
  90. package/corpus/templates/forms/.agents/skills/self-modifying-code/SKILL.md +9 -6
  91. package/corpus/templates/macros/.agents/skills/customizing-agent-native/SKILL.md +63 -20
  92. package/corpus/templates/mail/.agents/skills/customizing-agent-native/SKILL.md +63 -20
  93. package/corpus/templates/mail/.agents/skills/self-modifying-code/SKILL.md +9 -6
  94. package/corpus/templates/plan/.agents/skills/customizing-agent-native/SKILL.md +63 -20
  95. package/corpus/templates/plan/.agents/skills/self-modifying-code/SKILL.md +9 -6
  96. package/corpus/templates/slides/.agents/skills/customizing-agent-native/SKILL.md +63 -20
  97. package/corpus/templates/slides/.agents/skills/self-modifying-code/SKILL.md +9 -6
  98. package/corpus/templates/tasks/.agents/skills/agent-native-docs/SKILL.md +15 -13
  99. package/corpus/templates/tasks/.agents/skills/customizing-agent-native/SKILL.md +63 -20
  100. package/corpus/templates/tasks/.agents/skills/self-modifying-code/SKILL.md +9 -6
  101. package/corpus/toolkit/CHANGELOG.md +6 -0
  102. package/corpus/toolkit/agent-native.eject.json +411 -0
  103. package/corpus/toolkit/package.json +5 -2
  104. package/dist/cli/eject.d.ts +21 -0
  105. package/dist/cli/eject.d.ts.map +1 -0
  106. package/dist/cli/eject.js +1145 -0
  107. package/dist/cli/eject.js.map +1 -0
  108. package/dist/cli/index.js +15 -0
  109. package/dist/cli/index.js.map +1 -1
  110. package/dist/client/index.d.ts +1 -1
  111. package/dist/client/index.d.ts.map +1 -1
  112. package/dist/client/index.js +1 -1
  113. package/dist/client/index.js.map +1 -1
  114. package/dist/client/resources/McpConnectionSuggestion.d.ts +4 -3
  115. package/dist/client/resources/McpConnectionSuggestion.d.ts.map +1 -1
  116. package/dist/client/resources/McpConnectionSuggestion.js +3 -3
  117. package/dist/client/resources/McpConnectionSuggestion.js.map +1 -1
  118. package/dist/client/resources/McpIntegrationDialog.d.ts +4 -3
  119. package/dist/client/resources/McpIntegrationDialog.d.ts.map +1 -1
  120. package/dist/client/resources/McpIntegrationDialog.js +2 -2
  121. package/dist/client/resources/McpIntegrationDialog.js.map +1 -1
  122. package/dist/client/resources/ResourcesPanel.d.ts +4 -1
  123. package/dist/client/resources/ResourcesPanel.d.ts.map +1 -1
  124. package/dist/client/resources/ResourcesPanel.js +9 -7
  125. package/dist/client/resources/ResourcesPanel.js.map +1 -1
  126. package/dist/client/resources/index.d.ts +3 -0
  127. package/dist/client/resources/index.d.ts.map +1 -1
  128. package/dist/client/resources/index.js +3 -0
  129. package/dist/client/resources/index.js.map +1 -1
  130. package/dist/client/resources/mcp-integration-catalog.d.ts +2 -1
  131. package/dist/client/resources/mcp-integration-catalog.d.ts.map +1 -1
  132. package/dist/client/resources/mcp-integration-catalog.js +6 -2
  133. package/dist/client/resources/mcp-integration-catalog.js.map +1 -1
  134. package/dist/client/resources/runtime.d.ts +2 -0
  135. package/dist/client/resources/runtime.d.ts.map +1 -0
  136. package/dist/client/resources/runtime.js +2 -0
  137. package/dist/client/resources/runtime.js.map +1 -0
  138. package/dist/client/setup-connections/catalog.d.ts +2 -0
  139. package/dist/client/setup-connections/catalog.d.ts.map +1 -0
  140. package/dist/client/setup-connections/catalog.js +7 -0
  141. package/dist/client/setup-connections/catalog.js.map +1 -0
  142. package/dist/client/setup-connections/index.d.ts +1 -0
  143. package/dist/client/setup-connections/index.d.ts.map +1 -1
  144. package/dist/client/setup-connections/index.js +1 -0
  145. package/dist/client/setup-connections/index.js.map +1 -1
  146. package/dist/client/setup-connections/runtime.d.ts +2 -0
  147. package/dist/client/setup-connections/runtime.d.ts.map +1 -0
  148. package/dist/client/setup-connections/runtime.js +2 -0
  149. package/dist/client/setup-connections/runtime.js.map +1 -0
  150. package/dist/collab/awareness.d.ts +2 -2
  151. package/dist/collab/awareness.d.ts.map +1 -1
  152. package/dist/collab/routes.d.ts +1 -1
  153. package/dist/connections/catalog.d.ts +5 -3
  154. package/dist/connections/catalog.d.ts.map +1 -1
  155. package/dist/connections/catalog.js +16 -8
  156. package/dist/connections/catalog.js.map +1 -1
  157. package/dist/connections/index.d.ts +1 -1
  158. package/dist/connections/index.d.ts.map +1 -1
  159. package/dist/connections/index.js +1 -1
  160. package/dist/connections/index.js.map +1 -1
  161. package/dist/connections/runtime.d.ts +2 -0
  162. package/dist/connections/runtime.d.ts.map +1 -0
  163. package/dist/connections/runtime.js +2 -0
  164. package/dist/connections/runtime.js.map +1 -0
  165. package/dist/eject/provider-api-definitions.d.ts +34 -0
  166. package/dist/eject/provider-api-definitions.d.ts.map +1 -0
  167. package/dist/eject/provider-api-definitions.js +88 -0
  168. package/dist/eject/provider-api-definitions.js.map +1 -0
  169. package/dist/eject/remote-mcp-presets.d.ts +17 -0
  170. package/dist/eject/remote-mcp-presets.d.ts.map +1 -0
  171. package/dist/eject/remote-mcp-presets.js +81 -0
  172. package/dist/eject/remote-mcp-presets.js.map +1 -0
  173. package/dist/eject/setup-readiness-ui.d.ts +7 -0
  174. package/dist/eject/setup-readiness-ui.d.ts.map +1 -0
  175. package/dist/eject/setup-readiness-ui.js +13 -0
  176. package/dist/eject/setup-readiness-ui.js.map +1 -0
  177. package/dist/eject/workspace-connections.d.ts +11 -0
  178. package/dist/eject/workspace-connections.d.ts.map +1 -0
  179. package/dist/eject/workspace-connections.js +47 -0
  180. package/dist/eject/workspace-connections.js.map +1 -0
  181. package/dist/index.d.ts +1 -1
  182. package/dist/index.d.ts.map +1 -1
  183. package/dist/index.js +1 -1
  184. package/dist/index.js.map +1 -1
  185. package/dist/integrations/adapter-overrides.d.ts +3 -0
  186. package/dist/integrations/adapter-overrides.d.ts.map +1 -0
  187. package/dist/integrations/adapter-overrides.js +7 -0
  188. package/dist/integrations/adapter-overrides.js.map +1 -0
  189. package/dist/integrations/eject/messaging-adapters.d.ts +12 -0
  190. package/dist/integrations/eject/messaging-adapters.d.ts.map +1 -0
  191. package/dist/integrations/eject/messaging-adapters.js +49 -0
  192. package/dist/integrations/eject/messaging-adapters.js.map +1 -0
  193. package/dist/integrations/index.d.ts +3 -2
  194. package/dist/integrations/index.d.ts.map +1 -1
  195. package/dist/integrations/index.js +2 -1
  196. package/dist/integrations/index.js.map +1 -1
  197. package/dist/integrations/plugin.d.ts +32 -1
  198. package/dist/integrations/plugin.d.ts.map +1 -1
  199. package/dist/integrations/plugin.js +19 -12
  200. package/dist/integrations/plugin.js.map +1 -1
  201. package/dist/integrations/runtime.d.ts +2 -0
  202. package/dist/integrations/runtime.d.ts.map +1 -0
  203. package/dist/integrations/runtime.js +2 -0
  204. package/dist/integrations/runtime.js.map +1 -0
  205. package/dist/integrations/types.d.ts +3 -1
  206. package/dist/integrations/types.d.ts.map +1 -1
  207. package/dist/integrations/types.js.map +1 -1
  208. package/dist/notifications/routes.d.ts +3 -3
  209. package/dist/package-lifecycle/eject-manifest.d.ts +43 -0
  210. package/dist/package-lifecycle/eject-manifest.d.ts.map +1 -0
  211. package/dist/package-lifecycle/eject-manifest.js +219 -0
  212. package/dist/package-lifecycle/eject-manifest.js.map +1 -0
  213. package/dist/package-lifecycle/index.d.ts +1 -0
  214. package/dist/package-lifecycle/index.d.ts.map +1 -1
  215. package/dist/package-lifecycle/index.js +1 -0
  216. package/dist/package-lifecycle/index.js.map +1 -1
  217. package/dist/progress/routes.d.ts +1 -1
  218. package/dist/provider-api/actions/custom-provider-registration.d.ts +4 -4
  219. package/dist/provider-api/actions/provider-api.d.ts +8 -8
  220. package/dist/provider-api/corpus-jobs.d.ts +2 -2
  221. package/dist/provider-api/index.d.ts +6 -2
  222. package/dist/provider-api/index.d.ts.map +1 -1
  223. package/dist/provider-api/index.js +25 -12
  224. package/dist/provider-api/index.js.map +1 -1
  225. package/dist/provider-api/runtime.d.ts +2 -0
  226. package/dist/provider-api/runtime.d.ts.map +1 -0
  227. package/dist/provider-api/runtime.js +2 -0
  228. package/dist/provider-api/runtime.js.map +1 -0
  229. package/dist/secrets/routes.d.ts +9 -9
  230. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  231. package/dist/server/transcribe-voice.d.ts +1 -1
  232. package/dist/setup-connections/index.d.ts +1 -1
  233. package/dist/setup-connections/index.d.ts.map +1 -1
  234. package/dist/setup-connections/index.js +1 -1
  235. package/dist/setup-connections/index.js.map +1 -1
  236. package/dist/shared/merge-by-id.d.ts +5 -0
  237. package/dist/shared/merge-by-id.d.ts.map +1 -0
  238. package/dist/shared/merge-by-id.js +7 -0
  239. package/dist/shared/merge-by-id.js.map +1 -0
  240. package/dist/templates/chat/.agents/skills/agent-native-docs/SKILL.md +15 -13
  241. package/dist/templates/chat/.agents/skills/customizing-agent-native/SKILL.md +63 -20
  242. package/dist/templates/chat/.agents/skills/self-modifying-code/SKILL.md +9 -6
  243. package/dist/templates/chat/AGENTS.md +3 -2
  244. package/dist/templates/default/.agents/skills/agent-native-docs/SKILL.md +15 -13
  245. package/dist/templates/default/.agents/skills/customizing-agent-native/SKILL.md +63 -20
  246. package/dist/templates/default/.agents/skills/self-modifying-code/SKILL.md +9 -6
  247. package/dist/templates/default/AGENTS.md +6 -5
  248. package/dist/templates/headless/.agents/skills/agent-native-docs/SKILL.md +15 -13
  249. package/dist/templates/headless/.agents/skills/customizing-agent-native/SKILL.md +63 -20
  250. package/dist/templates/headless/AGENTS.md +5 -4
  251. package/dist/templates/workspace-core/.agents/skills/agent-native-docs/SKILL.md +15 -13
  252. package/dist/templates/workspace-core/.agents/skills/agent-native-toolkit/SKILL.md +3 -2
  253. package/dist/templates/workspace-core/.agents/skills/customizing-agent-native/SKILL.md +63 -20
  254. package/dist/templates/workspace-core/.agents/skills/self-modifying-code/SKILL.md +9 -6
  255. package/dist/templates/workspace-core/AGENTS.md +4 -4
  256. package/dist/templates/workspace-root/AGENTS.md +4 -4
  257. package/dist/vite/client.d.ts.map +1 -1
  258. package/dist/vite/client.js +22 -2
  259. package/dist/vite/client.js.map +1 -1
  260. package/docs/content/agent-native-toolkit.mdx +38 -0
  261. package/docs/content/package-lifecycle.mdx +54 -4
  262. package/package.json +15 -2
  263. package/src/a2a/agent-card.ts +83 -0
  264. package/src/a2a/artifact-response.ts +1648 -0
  265. package/src/a2a/auth-policy.ts +66 -0
  266. package/src/a2a/caller-auth.ts +102 -0
  267. package/src/a2a/client.ts +876 -0
  268. package/src/a2a/correlation.ts +50 -0
  269. package/src/a2a/handlers.ts +1285 -0
  270. package/src/a2a/index.ts +50 -0
  271. package/src/a2a/invoke.ts +348 -0
  272. package/src/a2a/response-text.ts +53 -0
  273. package/src/a2a/server.ts +586 -0
  274. package/src/a2a/task-store.ts +917 -0
  275. package/src/a2a/types.ts +221 -0
  276. package/src/a2a-claims.ts +52 -0
  277. package/src/action-change-marker.ts +74 -0
  278. package/src/action-ui.ts +38 -0
  279. package/src/action.ts +1406 -0
  280. package/src/adapters/cli/index.ts +6 -0
  281. package/src/adapters/cli/registry.ts +73 -0
  282. package/src/adapters/cli/shell-adapter.ts +92 -0
  283. package/src/adapters/cli/types.ts +27 -0
  284. package/src/agent/action-continuation-guidance.ts +38 -0
  285. package/src/agent/app-model-defaults.ts +201 -0
  286. package/src/agent/context-xray/actions/context-evict.ts +56 -0
  287. package/src/agent/context-xray/actions/context-manifest-get.ts +75 -0
  288. package/src/agent/context-xray/actions/context-pin.ts +56 -0
  289. package/src/agent/context-xray/actions/context-preview-get.ts +134 -0
  290. package/src/agent/context-xray/actions/context-report.ts +75 -0
  291. package/src/agent/context-xray/actions/context-restore.ts +51 -0
  292. package/src/agent/context-xray/actions/errors.ts +40 -0
  293. package/src/agent/context-xray/apply-directives.ts +137 -0
  294. package/src/agent/context-xray/directives-store.ts +178 -0
  295. package/src/agent/context-xray/identity.ts +37 -0
  296. package/src/agent/context-xray/manifest.ts +284 -0
  297. package/src/agent/context-xray/migrations.ts +32 -0
  298. package/src/agent/context-xray/plugin.ts +23 -0
  299. package/src/agent/context-xray/schema.ts +17 -0
  300. package/src/agent/context-xray/segments.ts +194 -0
  301. package/src/agent/context-xray/tokenize.ts +93 -0
  302. package/src/agent/default-model.ts +5 -0
  303. package/src/agent/durable-background.ts +547 -0
  304. package/src/agent/engine/ai-sdk-engine.ts +565 -0
  305. package/src/agent/engine/anthropic-engine.ts +320 -0
  306. package/src/agent/engine/builder-engine.ts +1110 -0
  307. package/src/agent/engine/builder-gateway-headers.ts +44 -0
  308. package/src/agent/engine/builtin.ts +122 -0
  309. package/src/agent/engine/context-directives-transform.ts +73 -0
  310. package/src/agent/engine/continuation-dispatch-retry.ts +168 -0
  311. package/src/agent/engine/credential-errors.ts +69 -0
  312. package/src/agent/engine/index.ts +54 -0
  313. package/src/agent/engine/openai-compatible-endpoint.ts +25 -0
  314. package/src/agent/engine/output-tokens.ts +181 -0
  315. package/src/agent/engine/provider-env-vars.ts +69 -0
  316. package/src/agent/engine/registry.ts +853 -0
  317. package/src/agent/engine/tool-call-journal-seed.ts +85 -0
  318. package/src/agent/engine/translate-ai-sdk.ts +407 -0
  319. package/src/agent/engine/translate-anthropic.ts +611 -0
  320. package/src/agent/engine/types.ts +310 -0
  321. package/src/agent/harness/acp-adapter.ts +893 -0
  322. package/src/agent/harness/acp-builtin.ts +70 -0
  323. package/src/agent/harness/ai-sdk-adapter.ts +509 -0
  324. package/src/agent/harness/background.ts +365 -0
  325. package/src/agent/harness/builtin.ts +50 -0
  326. package/src/agent/harness/index.ts +86 -0
  327. package/src/agent/harness/lifecycle.ts +498 -0
  328. package/src/agent/harness/registry.ts +97 -0
  329. package/src/agent/harness/runner.ts +182 -0
  330. package/src/agent/harness/store.ts +466 -0
  331. package/src/agent/harness/translate.ts +130 -0
  332. package/src/agent/harness/types.ts +129 -0
  333. package/src/agent/index.ts +32 -0
  334. package/src/agent/loop-settings.ts +186 -0
  335. package/src/agent/model-config.ts +363 -0
  336. package/src/agent/observational-memory/compactor.ts +78 -0
  337. package/src/agent/observational-memory/config.ts +78 -0
  338. package/src/agent/observational-memory/index.ts +79 -0
  339. package/src/agent/observational-memory/internal-run.ts +89 -0
  340. package/src/agent/observational-memory/message-text.ts +49 -0
  341. package/src/agent/observational-memory/migrations.ts +44 -0
  342. package/src/agent/observational-memory/observer.ts +128 -0
  343. package/src/agent/observational-memory/plugin.ts +35 -0
  344. package/src/agent/observational-memory/prompts.ts +53 -0
  345. package/src/agent/observational-memory/read.ts +131 -0
  346. package/src/agent/observational-memory/reflector.ts +119 -0
  347. package/src/agent/observational-memory/schema.ts +48 -0
  348. package/src/agent/observational-memory/store.ts +275 -0
  349. package/src/agent/observational-memory/types.ts +65 -0
  350. package/src/agent/processors.ts +209 -0
  351. package/src/agent/production-agent.ts +8254 -0
  352. package/src/agent/run-loop-with-resume.ts +394 -0
  353. package/src/agent/run-manager.ts +1825 -0
  354. package/src/agent/run-ownership.ts +75 -0
  355. package/src/agent/run-store.ts +2601 -0
  356. package/src/agent/runtime-context.ts +169 -0
  357. package/src/agent/thread-data-builder.ts +1584 -0
  358. package/src/agent/tool-call-journal.ts +368 -0
  359. package/src/agent/tool-error-redaction.ts +52 -0
  360. package/src/agent/tool-result-images.ts +178 -0
  361. package/src/agent/tool-search.ts +376 -0
  362. package/src/agent/types.ts +372 -0
  363. package/src/agent-native/index.ts +198 -0
  364. package/src/agent-web/config.ts +253 -0
  365. package/src/agent-web/generator.ts +382 -0
  366. package/src/agent-web/index.ts +36 -0
  367. package/src/appearance/actions/change-appearance.ts +35 -0
  368. package/src/application-state/emitter.ts +81 -0
  369. package/src/application-state/handlers.ts +121 -0
  370. package/src/application-state/index.ts +44 -0
  371. package/src/application-state/script-helpers.ts +155 -0
  372. package/src/application-state/store.ts +274 -0
  373. package/src/assets/branding/agent-native.icon/Assets/background.svg +3 -0
  374. package/src/assets/branding/agent-native.icon/Assets/foreground.svg +12 -0
  375. package/src/assets/branding/agent-native.icon/icon.json +49 -0
  376. package/src/assets/branding/favicon.png +0 -0
  377. package/src/assets/branding/favicon.svg +1 -0
  378. package/src/assets/branding/icon-on-dark.svg +10 -0
  379. package/src/assets/branding/icon-on-light.svg +10 -0
  380. package/src/assets/branding/mac-app-icon.svg +1 -0
  381. package/src/assets/branding/slack-bot/agent-native-1024.png +0 -0
  382. package/src/assets/branding/slack-bot/agent-native-512.png +0 -0
  383. package/src/assets/branding/tray-icon.svg +6 -0
  384. package/src/assets/branding/wordmark-on-dark.svg +21 -0
  385. package/src/assets/branding/wordmark-on-light.svg +21 -0
  386. package/src/assets/fonts/LICENSE_LIBERATION +96 -0
  387. package/src/assets/fonts/LICENSE_NOTO_NASKH_ARABIC +93 -0
  388. package/src/assets/fonts/LiberationSans-Bold.ttf +0 -0
  389. package/src/assets/fonts/LiberationSans-Regular.ttf +0 -0
  390. package/src/assets/fonts/NotoNaskhArabic-Variable.ttf +0 -0
  391. package/src/audit/actions/export-audit-events.ts +162 -0
  392. package/src/audit/actions/get-audit-event.ts +24 -0
  393. package/src/audit/actions/list-audit-events.ts +66 -0
  394. package/src/audit/cleanup-job.ts +100 -0
  395. package/src/audit/config.ts +90 -0
  396. package/src/audit/index.ts +43 -0
  397. package/src/audit/record.ts +180 -0
  398. package/src/audit/redact.ts +109 -0
  399. package/src/audit/store.ts +346 -0
  400. package/src/audit/types.ts +141 -0
  401. package/src/automation/index.ts +802 -0
  402. package/src/brand-kit/brand-signals.ts +124 -0
  403. package/src/brand-kit/fig/index.ts +64 -0
  404. package/src/brand-kit/index.ts +72 -0
  405. package/src/brand-kit/types.ts +113 -0
  406. package/src/browser-sessions/actions.ts +302 -0
  407. package/src/browser-sessions/routes.ts +234 -0
  408. package/src/browser-sessions/store.ts +679 -0
  409. package/src/browser-sessions/types.ts +84 -0
  410. package/src/changelog/parse.ts +328 -0
  411. package/src/chat-threads/emitter.ts +22 -0
  412. package/src/chat-threads/schema.ts +43 -0
  413. package/src/chat-threads/store.ts +1311 -0
  414. package/src/checkpoints/index.ts +15 -0
  415. package/src/checkpoints/service.ts +142 -0
  416. package/src/checkpoints/store.ts +153 -0
  417. package/src/cli/add.ts +425 -0
  418. package/src/cli/agent.ts +424 -0
  419. package/src/cli/agents.ts +122 -0
  420. package/src/cli/app-skill.ts +1455 -0
  421. package/src/cli/atomic-json-file.ts +324 -0
  422. package/src/cli/audit-agent-web.ts +324 -0
  423. package/src/cli/changelog.ts +199 -0
  424. package/src/cli/claude-code-participant.ts +515 -0
  425. package/src/cli/code-agent-commands.ts +270 -0
  426. package/src/cli/code-agent-connector.ts +1109 -0
  427. package/src/cli/code-agent-executor.ts +1970 -0
  428. package/src/cli/code-agent-output-smoother.ts +140 -0
  429. package/src/cli/code-agent-runs.concurrent-worker.ts +33 -0
  430. package/src/cli/code-agent-runs.ts +548 -0
  431. package/src/cli/code.ts +1805 -0
  432. package/src/cli/codex-cli-participant.ts +496 -0
  433. package/src/cli/connect.ts +2714 -0
  434. package/src/cli/content-local.ts +442 -0
  435. package/src/cli/context-xray-local.ts +2193 -0
  436. package/src/cli/create-workspace.ts +30 -0
  437. package/src/cli/create.ts +2247 -0
  438. package/src/cli/deploy-build.ts +50 -0
  439. package/src/cli/design-connect.ts +3187 -0
  440. package/src/cli/doctor.ts +472 -0
  441. package/src/cli/eject.ts +1594 -0
  442. package/src/cli/eval.ts +134 -0
  443. package/src/cli/gateway-helpers.ts +70 -0
  444. package/src/cli/index.ts +1217 -0
  445. package/src/cli/info.ts +105 -0
  446. package/src/cli/invoke.ts +288 -0
  447. package/src/cli/mcp-config-writers.ts +857 -0
  448. package/src/cli/mcp.ts +594 -0
  449. package/src/cli/migrate.ts +1813 -0
  450. package/src/cli/migration-codemod.ts +646 -0
  451. package/src/cli/multi-frontier-runs.ts +1952 -0
  452. package/src/cli/package-lifecycle.ts +823 -0
  453. package/src/cli/plan-blocks.ts +143 -0
  454. package/src/cli/plan-local.ts +3189 -0
  455. package/src/cli/plan-publish-store.ts +138 -0
  456. package/src/cli/pr-visual-recap-workflow.ts +2 -0
  457. package/src/cli/recap.ts +5 -0
  458. package/src/cli/setup-agents.ts +120 -0
  459. package/src/cli/skills-content/assets-skill.ts +83 -0
  460. package/src/cli/skills-content/canvas.ts +153 -0
  461. package/src/cli/skills-content/connection.ts +52 -0
  462. package/src/cli/skills-content/content-skill.ts +120 -0
  463. package/src/cli/skills-content/design-exploration-skill.ts +118 -0
  464. package/src/cli/skills-content/design-visual-edit-skill.ts +228 -0
  465. package/src/cli/skills-content/document-quality.ts +196 -0
  466. package/src/cli/skills-content/exemplar.ts +69 -0
  467. package/src/cli/skills-content/help.ts +77 -0
  468. package/src/cli/skills-content/index.ts +22 -0
  469. package/src/cli/skills-content/local-files.ts +100 -0
  470. package/src/cli/skills-content/plan-setup-auth.ts +80 -0
  471. package/src/cli/skills-content/visual-plan-skill.ts +493 -0
  472. package/src/cli/skills-content/visual-recap-skill.ts +553 -0
  473. package/src/cli/skills-content/visualize-repo-skill.ts +93 -0
  474. package/src/cli/skills-content/wireframe.ts +349 -0
  475. package/src/cli/skills.ts +4340 -0
  476. package/src/cli/sync-builder-starter-manifest.ts +631 -0
  477. package/src/cli/telemetry.ts +136 -0
  478. package/src/cli/templates-meta.ts +269 -0
  479. package/src/cli/upgrade.ts +956 -0
  480. package/src/cli/visualize-repo.ts +715 -0
  481. package/src/cli/workspace-dev.ts +1486 -0
  482. package/src/cli/workspacify.ts +258 -0
  483. package/src/client/AgentAskPopover.tsx +89 -0
  484. package/src/client/AgentChatHome.tsx +66 -0
  485. package/src/client/AgentNative.tsx +161 -0
  486. package/src/client/AgentNativeEmbedded.tsx +288 -0
  487. package/src/client/AgentNativeFrame.tsx +151 -0
  488. package/src/client/AgentPanel.tsx +3437 -0
  489. package/src/client/AgentTaskCard.tsx +273 -0
  490. package/src/client/AppearancePicker.tsx +79 -0
  491. package/src/client/AssistantChat.tsx +5793 -0
  492. package/src/client/ClientOnly.tsx +22 -0
  493. package/src/client/CommandMenu.tsx +726 -0
  494. package/src/client/ConnectBuilderCard.tsx +390 -0
  495. package/src/client/DefaultSpinner.tsx +47 -0
  496. package/src/client/ErrorBoundary.tsx +359 -0
  497. package/src/client/ErrorReportActions.tsx +69 -0
  498. package/src/client/FeedbackButton.tsx +553 -0
  499. package/src/client/HighlightedCodeBlock.tsx +173 -0
  500. package/src/client/IframeEmbed.tsx +151 -0
  501. package/src/client/KeepTabOpenNotice.tsx +181 -0
  502. package/src/client/MultiTabAssistantChat.tsx +2576 -0
  503. package/src/client/NewWorkspaceAppFlow.tsx +525 -0
  504. package/src/client/PoweredByBadge.tsx +284 -0
  505. package/src/client/RunStuckBanner.tsx +431 -0
  506. package/src/client/StarfieldBackground.tsx +466 -0
  507. package/src/client/Turnstile.tsx +125 -0
  508. package/src/client/active-run-state.ts +139 -0
  509. package/src/client/agent-chat/index.ts +279 -0
  510. package/src/client/agent-chat-adapter.ts +3692 -0
  511. package/src/client/agent-chat.ts +1233 -0
  512. package/src/client/agent-engine-key.ts +122 -0
  513. package/src/client/agent-page/AgentContextTab.tsx +487 -0
  514. package/src/client/agent-page/AgentEmptyState.tsx +44 -0
  515. package/src/client/agent-page/AgentJobsTab.tsx +441 -0
  516. package/src/client/agent-page/AgentTabFrame.tsx +39 -0
  517. package/src/client/agent-page/AgentTabsPage.tsx +1096 -0
  518. package/src/client/agent-page/types.ts +18 -0
  519. package/src/client/agent-page/use-jobs.ts +150 -0
  520. package/src/client/agent-sidebar-state.ts +166 -0
  521. package/src/client/analytics/index.ts +40 -0
  522. package/src/client/analytics-session.ts +70 -0
  523. package/src/client/analytics.ts +1757 -0
  524. package/src/client/api-path.ts +124 -0
  525. package/src/client/app-providers.tsx +230 -0
  526. package/src/client/appearance.ts +130 -0
  527. package/src/client/application-state.ts +154 -0
  528. package/src/client/assistant-ui-recovery.tsx +205 -0
  529. package/src/client/automation/index.ts +4 -0
  530. package/src/client/automation.ts +22 -0
  531. package/src/client/blocks/AiEditableField.tsx +30 -0
  532. package/src/client/blocks/BlockView.tsx +145 -0
  533. package/src/client/blocks/RegistryBlockDataProvider.tsx +121 -0
  534. package/src/client/blocks/SchemaBlockEditor.tsx +457 -0
  535. package/src/client/blocks/agent.ts +95 -0
  536. package/src/client/blocks/code-block-direction.ts +21 -0
  537. package/src/client/blocks/index.ts +308 -0
  538. package/src/client/blocks/library/AnnotatedCodeBlock.tsx +710 -0
  539. package/src/client/blocks/library/ApiEndpointBlock.tsx +1120 -0
  540. package/src/client/blocks/library/DataModelBlock.tsx +775 -0
  541. package/src/client/blocks/library/DiffBlock.tsx +1854 -0
  542. package/src/client/blocks/library/FileTreeBlock.tsx +868 -0
  543. package/src/client/blocks/library/HighlightedCode.tsx +260 -0
  544. package/src/client/blocks/library/JsonExplorerBlock.tsx +608 -0
  545. package/src/client/blocks/library/MermaidBlock.tsx +362 -0
  546. package/src/client/blocks/library/OpenApiSpecBlock.tsx +998 -0
  547. package/src/client/blocks/library/annotated-code.config.ts +101 -0
  548. package/src/client/blocks/library/annotation-rail.tsx +1020 -0
  549. package/src/client/blocks/library/api-endpoint.config.ts +207 -0
  550. package/src/client/blocks/library/block-copy.ts +399 -0
  551. package/src/client/blocks/library/callout.config.ts +57 -0
  552. package/src/client/blocks/library/callout.tsx +149 -0
  553. package/src/client/blocks/library/checklist.config.ts +56 -0
  554. package/src/client/blocks/library/checklist.tsx +208 -0
  555. package/src/client/blocks/library/code-filename-label.tsx +59 -0
  556. package/src/client/blocks/library/code-highlight.tsx +178 -0
  557. package/src/client/blocks/library/code-tabs.config.ts +70 -0
  558. package/src/client/blocks/library/code-tabs.tsx +606 -0
  559. package/src/client/blocks/library/code.config.ts +69 -0
  560. package/src/client/blocks/library/code.tsx +440 -0
  561. package/src/client/blocks/library/columns.config.ts +85 -0
  562. package/src/client/blocks/library/columns.tsx +334 -0
  563. package/src/client/blocks/library/data-model.config.ts +152 -0
  564. package/src/client/blocks/library/dev-doc-ui.tsx +191 -0
  565. package/src/client/blocks/library/diagram.config.ts +222 -0
  566. package/src/client/blocks/library/diagram.tsx +958 -0
  567. package/src/client/blocks/library/diff.config.ts +115 -0
  568. package/src/client/blocks/library/file-tree.config.ts +92 -0
  569. package/src/client/blocks/library/html.config.ts +79 -0
  570. package/src/client/blocks/library/html.tsx +258 -0
  571. package/src/client/blocks/library/json-explorer.config.ts +74 -0
  572. package/src/client/blocks/library/mermaid.config.ts +49 -0
  573. package/src/client/blocks/library/narrow-container.tsx +37 -0
  574. package/src/client/blocks/library/openapi-spec.config.ts +66 -0
  575. package/src/client/blocks/library/question-form.config.ts +127 -0
  576. package/src/client/blocks/library/question-form.tsx +944 -0
  577. package/src/client/blocks/library/sanitize-html.ts +343 -0
  578. package/src/client/blocks/library/server-specs.ts +338 -0
  579. package/src/client/blocks/library/specs.tsx +308 -0
  580. package/src/client/blocks/library/table.config.ts +61 -0
  581. package/src/client/blocks/library/table.tsx +449 -0
  582. package/src/client/blocks/library/tabs.config.ts +96 -0
  583. package/src/client/blocks/library/tabs.tsx +665 -0
  584. package/src/client/blocks/library/wireframe-icons.ts +210 -0
  585. package/src/client/blocks/library/wireframe-kit.tsx +1850 -0
  586. package/src/client/blocks/library/wireframe.config.ts +539 -0
  587. package/src/client/blocks/library/wireframe.tsx +535 -0
  588. package/src/client/blocks/mdx.ts +364 -0
  589. package/src/client/blocks/provider.tsx +51 -0
  590. package/src/client/blocks/registry.ts +83 -0
  591. package/src/client/blocks/schema-form/introspect.ts +201 -0
  592. package/src/client/blocks/server.ts +170 -0
  593. package/src/client/blocks/types.ts +415 -0
  594. package/src/client/browser-session-bridge.ts +548 -0
  595. package/src/client/browser-tab-id.ts +36 -0
  596. package/src/client/builder-frame.ts +194 -0
  597. package/src/client/builder-mark.tsx +21 -0
  598. package/src/client/changelog/Changelog.tsx +333 -0
  599. package/src/client/changelog/index.ts +1 -0
  600. package/src/client/chat/ChatHistoryList.tsx +7 -0
  601. package/src/client/chat/attachment-adapters.ts +426 -0
  602. package/src/client/chat/connectors.ts +1579 -0
  603. package/src/client/chat/index.ts +160 -0
  604. package/src/client/chat/markdown-renderer.tsx +693 -0
  605. package/src/client/chat/message-components.tsx +1326 -0
  606. package/src/client/chat/repo-helpers.ts +281 -0
  607. package/src/client/chat/run-recovery.tsx +994 -0
  608. package/src/client/chat/runtime.ts +1810 -0
  609. package/src/client/chat/tool-call-display.tsx +1270 -0
  610. package/src/client/chat/tool-render-registry.tsx +144 -0
  611. package/src/client/chat/use-agent-chat-lifecycle-tracking.ts +74 -0
  612. package/src/client/chat/use-reconnect-reader-owner.ts +28 -0
  613. package/src/client/chat/widgets/DataChartRenderer.tsx +242 -0
  614. package/src/client/chat/widgets/DataChartWidget.tsx +51 -0
  615. package/src/client/chat/widgets/DataInsightsWidget.tsx +59 -0
  616. package/src/client/chat/widgets/DataTableWidget.tsx +240 -0
  617. package/src/client/chat/widgets/InlineExtensionWidget.tsx +60 -0
  618. package/src/client/chat/widgets/builtin-tool-renderers.tsx +213 -0
  619. package/src/client/chat/widgets/data-widget-types.ts +1 -0
  620. package/src/client/chat/widgets/inline-extension-result.ts +86 -0
  621. package/src/client/chat-model-groups.ts +171 -0
  622. package/src/client/chat-thread-url.ts +11 -0
  623. package/src/client/chat-view-transition.ts +213 -0
  624. package/src/client/client-action.ts +21 -0
  625. package/src/client/client-bootstrap.ts +7 -0
  626. package/src/client/client-surface.ts +41 -0
  627. package/src/client/clipboard.ts +89 -0
  628. package/src/client/code-agent-chat-adapter.ts +537 -0
  629. package/src/client/collab/index.ts +60 -0
  630. package/src/client/command-navigation/index.ts +15 -0
  631. package/src/client/comments-review/index.ts +1 -0
  632. package/src/client/components/AgentPresenceChip.tsx +4 -0
  633. package/src/client/components/ApiKeySettings.tsx +309 -0
  634. package/src/client/components/CodeAgentIndicator.tsx +59 -0
  635. package/src/client/components/CodeRequiredDialog.tsx +470 -0
  636. package/src/client/components/LiveCursorOverlay.tsx +5 -0
  637. package/src/client/components/MissingKeyCard.tsx +61 -0
  638. package/src/client/components/PresenceBar.tsx +4 -0
  639. package/src/client/components/RecentEditHighlights.tsx +4 -0
  640. package/src/client/components/RemoteSelectionRings.tsx +5 -0
  641. package/src/client/components/icons/AgentNativeIcon.tsx +46 -0
  642. package/src/client/components/ui/dialog.tsx +1 -0
  643. package/src/client/components/ui/dropdown-menu.tsx +1 -0
  644. package/src/client/components/ui/hover-card.tsx +1 -0
  645. package/src/client/components/ui/message-scroller.tsx +131 -0
  646. package/src/client/components/ui/popover.tsx +1 -0
  647. package/src/client/components/ui/sheet.tsx +1 -0
  648. package/src/client/components/ui/tooltip.tsx +1 -0
  649. package/src/client/composer/index.ts +11 -0
  650. package/src/client/composer/runtime-adapters.tsx +123 -0
  651. package/src/client/composer/use-mention-search.ts +7 -0
  652. package/src/client/composer/wired-components.tsx +53 -0
  653. package/src/client/context-xray/ContextMeter.tsx +124 -0
  654. package/src/client/context-xray/ContextSegmentRow.tsx +27 -0
  655. package/src/client/context-xray/ContextTreemap.tsx +24 -0
  656. package/src/client/context-xray/ContextXRayPanel.tsx +59 -0
  657. package/src/client/context-xray/SegmentProvenancePopover.tsx +18 -0
  658. package/src/client/context-xray/format.ts +27 -0
  659. package/src/client/conversation/AgentConversation.tsx +555 -0
  660. package/src/client/conversation/code-agent-transcript.ts +283 -0
  661. package/src/client/conversation/index.ts +22 -0
  662. package/src/client/conversation/types.ts +85 -0
  663. package/src/client/conversation/use-near-bottom-autoscroll.ts +278 -0
  664. package/src/client/create-query-client.ts +86 -0
  665. package/src/client/db-admin/DataGrid.tsx +551 -0
  666. package/src/client/db-admin/DbAdminPage.tsx +218 -0
  667. package/src/client/db-admin/DevDatabaseLink.tsx +16 -0
  668. package/src/client/db-admin/EditableCell.tsx +451 -0
  669. package/src/client/db-admin/FilterBar.tsx +203 -0
  670. package/src/client/db-admin/ResultsGrid.tsx +114 -0
  671. package/src/client/db-admin/RowSidePanel.tsx +337 -0
  672. package/src/client/db-admin/SqlEditor.tsx +840 -0
  673. package/src/client/db-admin/TableBrowser.tsx +212 -0
  674. package/src/client/db-admin/TableEditor.tsx +760 -0
  675. package/src/client/db-admin/cell-format.ts +246 -0
  676. package/src/client/db-admin/changeset.ts +296 -0
  677. package/src/client/db-admin/export-utils.ts +78 -0
  678. package/src/client/db-admin/index.ts +33 -0
  679. package/src/client/db-admin/sql-storage.ts +134 -0
  680. package/src/client/db-admin/storage.ts +68 -0
  681. package/src/client/db-admin/useAgentSync.ts +226 -0
  682. package/src/client/db-admin/useDbAdmin.ts +294 -0
  683. package/src/client/dev-overlay/DevOverlay.tsx +576 -0
  684. package/src/client/dev-overlay/builtins.ts +40 -0
  685. package/src/client/dev-overlay/index.ts +23 -0
  686. package/src/client/dev-overlay/registry.ts +67 -0
  687. package/src/client/dev-overlay/types.ts +64 -0
  688. package/src/client/dev-overlay/use-dev-option.ts +78 -0
  689. package/src/client/dev-overlay/use-dev-overlay-shortcut.ts +31 -0
  690. package/src/client/dynamic-suggestions.ts +455 -0
  691. package/src/client/embed-auth.ts +544 -0
  692. package/src/client/embed.ts +54 -0
  693. package/src/client/error-capture.ts +690 -0
  694. package/src/client/error-format.ts +211 -0
  695. package/src/client/error-reporting.ts +100 -0
  696. package/src/client/extensions/AgentNativeExtensionFrame.e2e-host.tsx +136 -0
  697. package/src/client/extensions/AgentNativeExtensionFrame.tsx +708 -0
  698. package/src/client/extensions/EmbeddedExtension.tsx +604 -0
  699. package/src/client/extensions/ExtensionEditor.tsx +450 -0
  700. package/src/client/extensions/ExtensionQueryErrorState.tsx +47 -0
  701. package/src/client/extensions/ExtensionSlot.tsx +345 -0
  702. package/src/client/extensions/ExtensionViewer.tsx +1502 -0
  703. package/src/client/extensions/ExtensionViewerPage.tsx +32 -0
  704. package/src/client/extensions/ExtensionsListPage.tsx +432 -0
  705. package/src/client/extensions/ExtensionsSidebarSection.tsx +1259 -0
  706. package/src/client/extensions/InlineExtensionFrame.tsx +660 -0
  707. package/src/client/extensions/agent-native-extension-runtime.ts +495 -0
  708. package/src/client/extensions/delete-extension.ts +76 -0
  709. package/src/client/extensions/extension-load-error.ts +26 -0
  710. package/src/client/extensions/extension-order.ts +49 -0
  711. package/src/client/extensions/extension-popularity.ts +61 -0
  712. package/src/client/extensions/iframe-bridge.ts +377 -0
  713. package/src/client/extensions/index.ts +84 -0
  714. package/src/client/extensions/portable-extension.ts +712 -0
  715. package/src/client/feature-flags/FeatureFlagsPanel.tsx +519 -0
  716. package/src/client/feature-flags/helpers.ts +77 -0
  717. package/src/client/feature-flags/index.ts +13 -0
  718. package/src/client/feature-flags/types.ts +29 -0
  719. package/src/client/feature-flags/use-feature-flag.ts +26 -0
  720. package/src/client/feedback-context.ts +90 -0
  721. package/src/client/frame-protocol.ts +168 -0
  722. package/src/client/frame.ts +329 -0
  723. package/src/client/guided-questions.tsx +1152 -0
  724. package/src/client/history/VersionHistoryPanel.tsx +175 -0
  725. package/src/client/history/index.ts +21 -0
  726. package/src/client/history/use-history.ts +114 -0
  727. package/src/client/hooks/index.ts +46 -0
  728. package/src/client/host/index.ts +170 -0
  729. package/src/client/host-bridge.ts +1272 -0
  730. package/src/client/host-tools.ts +190 -0
  731. package/src/client/i18n.tsx +798 -0
  732. package/src/client/index.ts +370 -0
  733. package/src/client/integrations/IntegrationCard.tsx +186 -0
  734. package/src/client/integrations/IntegrationsPanel.tsx +633 -0
  735. package/src/client/integrations/api.ts +295 -0
  736. package/src/client/integrations/index.ts +29 -0
  737. package/src/client/integrations/useIntegrationStatus.ts +52 -0
  738. package/src/client/mcp-app-host.ts +720 -0
  739. package/src/client/mcp-apps/McpAppRenderer.tsx +760 -0
  740. package/src/client/navigation/index.ts +54 -0
  741. package/src/client/notifications/NotificationsBell.tsx +383 -0
  742. package/src/client/notifications/index.ts +1 -0
  743. package/src/client/observability/ObservabilityDashboard.tsx +890 -0
  744. package/src/client/observability/ThumbsFeedback.tsx +160 -0
  745. package/src/client/observability/index.ts +20 -0
  746. package/src/client/observability/useObservability.ts +266 -0
  747. package/src/client/onboarding/OnboardingBanner.tsx +73 -0
  748. package/src/client/onboarding/OnboardingPanel.tsx +1036 -0
  749. package/src/client/onboarding/SetupButton.tsx +64 -0
  750. package/src/client/onboarding/index.ts +25 -0
  751. package/src/client/onboarding/use-onboarding.ts +164 -0
  752. package/src/client/onboarding/use-preview-mode.ts +40 -0
  753. package/src/client/org/InvitationBanner.tsx +148 -0
  754. package/src/client/org/OrgSwitcher.tsx +754 -0
  755. package/src/client/org/RequireActiveOrg.tsx +337 -0
  756. package/src/client/org/TeamPage.tsx +1432 -0
  757. package/src/client/org/hooks.ts +359 -0
  758. package/src/client/org/index.ts +70 -0
  759. package/src/client/org/workspace-app-links.ts +367 -0
  760. package/src/client/org-team/index.ts +1 -0
  761. package/src/client/progress/RunsTray.tsx +680 -0
  762. package/src/client/progress/index.ts +1 -0
  763. package/src/client/require-session.tsx +142 -0
  764. package/src/client/resources/BuiltinCapabilityDetail.tsx +258 -0
  765. package/src/client/resources/McpConnectionSuggestion.tsx +276 -0
  766. package/src/client/resources/McpIntegrationDialog.tsx +808 -0
  767. package/src/client/resources/McpServerDetail.tsx +230 -0
  768. package/src/client/resources/ResourceEditor.tsx +872 -0
  769. package/src/client/resources/ResourceTree.tsx +860 -0
  770. package/src/client/resources/ResourcesPanel.tsx +1960 -0
  771. package/src/client/resources/index.ts +25 -0
  772. package/src/client/resources/mcp-integration-catalog.ts +771 -0
  773. package/src/client/resources/mcp-integration-logos.ts +108 -0
  774. package/src/client/resources/runtime.ts +1 -0
  775. package/src/client/resources/use-builtin-capabilities.ts +113 -0
  776. package/src/client/resources/use-mcp-servers.ts +217 -0
  777. package/src/client/resources/use-resources.ts +402 -0
  778. package/src/client/review/ReviewCommentComposer.tsx +123 -0
  779. package/src/client/review/ReviewStatusBadge.tsx +39 -0
  780. package/src/client/review/ReviewThreadPanel.tsx +625 -0
  781. package/src/client/review/index.ts +38 -0
  782. package/src/client/review/use-review.ts +186 -0
  783. package/src/client/route-chunk-recovery/index.ts +1 -0
  784. package/src/client/route-chunk-recovery.ts +331 -0
  785. package/src/client/route-state.ts +455 -0
  786. package/src/client/route-warmup.tsx +543 -0
  787. package/src/client/session-replay-iframe.e2e-host.tsx +100 -0
  788. package/src/client/session-replay.ts +3417 -0
  789. package/src/client/settings/AgentsSection.tsx +441 -0
  790. package/src/client/settings/AutomationsSection.tsx +516 -0
  791. package/src/client/settings/BackgroundAgentSection.tsx +189 -0
  792. package/src/client/settings/BrowserSection.tsx +110 -0
  793. package/src/client/settings/DemoModeSection.tsx +48 -0
  794. package/src/client/settings/SecretsSection.tsx +875 -0
  795. package/src/client/settings/SettingsPanel.tsx +3162 -0
  796. package/src/client/settings/SettingsSection.tsx +283 -0
  797. package/src/client/settings/SettingsTabsPage.tsx +592 -0
  798. package/src/client/settings/UsageSection.tsx +401 -0
  799. package/src/client/settings/VoiceTranscriptionSection.tsx +960 -0
  800. package/src/client/settings/agent-settings-search.ts +220 -0
  801. package/src/client/settings/index.ts +27 -0
  802. package/src/client/settings/useBuilderStatus.ts +1055 -0
  803. package/src/client/setup-connections/BuilderConnectCard.tsx +89 -0
  804. package/src/client/setup-connections/ProviderReadinessBadge.tsx +73 -0
  805. package/src/client/setup-connections/SetupConnectionsPage.tsx +94 -0
  806. package/src/client/setup-connections/catalog.ts +6 -0
  807. package/src/client/setup-connections/index.ts +47 -0
  808. package/src/client/setup-connections/runtime.ts +1 -0
  809. package/src/client/sharing/ShareButton.tsx +1748 -0
  810. package/src/client/sharing/ShareDialog.tsx +846 -0
  811. package/src/client/sharing/VisibilityBadge.tsx +4 -0
  812. package/src/client/sharing/index.ts +2 -0
  813. package/src/client/sse-event-processor.ts +2002 -0
  814. package/src/client/terminal/AgentTerminal.tsx +488 -0
  815. package/src/client/terminal/index.ts +7 -0
  816. package/src/client/theme.ts +27 -0
  817. package/src/client/tombstone/agent-presence-chip.ts +17 -0
  818. package/src/client/tombstone/editor.ts +265 -0
  819. package/src/client/tombstone/live-cursor-overlay.ts +21 -0
  820. package/src/client/tombstone/presence-bar.ts +17 -0
  821. package/src/client/tombstone/recent-edit-highlights.ts +17 -0
  822. package/src/client/tombstone/remote-selection-rings.ts +21 -0
  823. package/src/client/tombstone/rich-markdown-editor.ts +265 -0
  824. package/src/client/tombstone/ui-dialog.ts +49 -0
  825. package/src/client/tombstone/ui-dropdown-menu.ts +69 -0
  826. package/src/client/tombstone/ui-hover-card.ts +21 -0
  827. package/src/client/tombstone/ui-popover.ts +25 -0
  828. package/src/client/tombstone/ui-sheet.ts +49 -0
  829. package/src/client/tombstone/ui-tooltip.ts +29 -0
  830. package/src/client/tombstone/visual-style-controls.ts +61 -0
  831. package/src/client/tool-cells/BashCell.tsx +164 -0
  832. package/src/client/tool-cells/EditCell.tsx +303 -0
  833. package/src/client/tool-cells/FilesChangedSummary.tsx +208 -0
  834. package/src/client/tool-cells/WriteCell.tsx +145 -0
  835. package/src/client/tool-cells/index.ts +7 -0
  836. package/src/client/tool-display.ts +41 -0
  837. package/src/client/track.ts +57 -0
  838. package/src/client/transcription/BuilderTranscriptionCta.tsx +120 -0
  839. package/src/client/transcription/use-live-transcription.ts +292 -0
  840. package/src/client/ui/index.ts +55 -0
  841. package/src/client/uploads/index.ts +6 -0
  842. package/src/client/uploads/upload-editor-image.ts +79 -0
  843. package/src/client/uploads/use-upload-resource.ts +24 -0
  844. package/src/client/url-scrub.ts +51 -0
  845. package/src/client/use-action.ts +766 -0
  846. package/src/client/use-agent-chat-context.ts +63 -0
  847. package/src/client/use-agent-chat-home-handoff.ts +207 -0
  848. package/src/client/use-agent-chat.ts +53 -0
  849. package/src/client/use-agent-engine-configured.ts +211 -0
  850. package/src/client/use-avatar.ts +127 -0
  851. package/src/client/use-change-version.ts +150 -0
  852. package/src/client/use-chat-models.ts +252 -0
  853. package/src/client/use-chat-threads.ts +1262 -0
  854. package/src/client/use-db-sync.ts +1112 -0
  855. package/src/client/use-demo-mode-status.ts +30 -0
  856. package/src/client/use-dev-mode.ts +177 -0
  857. package/src/client/use-external-value.ts +40 -0
  858. package/src/client/use-pausing-interval.ts +65 -0
  859. package/src/client/use-pinch-zoom.ts +202 -0
  860. package/src/client/use-run-stuck-detection.ts +427 -0
  861. package/src/client/use-send-to-agent-chat.ts +85 -0
  862. package/src/client/use-session.ts +114 -0
  863. package/src/client/utils.ts +7 -0
  864. package/src/client/visual-style-controls.tsx +1 -0
  865. package/src/client/vite-dev-recovery-script.ts +226 -0
  866. package/src/client/voice-provider-status.ts +44 -0
  867. package/src/client/widgets/index.ts +41 -0
  868. package/src/code-agents/background-controller.ts +398 -0
  869. package/src/code-agents/background-run.ts +156 -0
  870. package/src/code-agents/index.ts +95 -0
  871. package/src/code-agents/prompt-attachments.ts +39 -0
  872. package/src/code-agents/transcript-normalizer.ts +750 -0
  873. package/src/code-agents/transcript-order.ts +73 -0
  874. package/src/coding-tools/index.ts +742 -0
  875. package/src/coding-tools/run-code.ts +1662 -0
  876. package/src/coding-tools/sandbox/adapter.ts +82 -0
  877. package/src/coding-tools/sandbox/background.ts +406 -0
  878. package/src/coding-tools/sandbox/executions-store.ts +517 -0
  879. package/src/coding-tools/sandbox/index.ts +132 -0
  880. package/src/coding-tools/sandbox/local-child-process-adapter.ts +217 -0
  881. package/src/collab/agent-identity.ts +5 -0
  882. package/src/collab/agent-presence.ts +341 -0
  883. package/src/collab/awareness-store.ts +196 -0
  884. package/src/collab/awareness.ts +317 -0
  885. package/src/collab/client-struct.ts +366 -0
  886. package/src/collab/client.ts +1205 -0
  887. package/src/collab/emitter.ts +31 -0
  888. package/src/collab/follow-mode.ts +107 -0
  889. package/src/collab/index.ts +151 -0
  890. package/src/collab/json-to-yjs.ts +504 -0
  891. package/src/collab/presence.ts +207 -0
  892. package/src/collab/recent-edits.ts +215 -0
  893. package/src/collab/routes.ts +191 -0
  894. package/src/collab/storage.ts +228 -0
  895. package/src/collab/struct-routes.ts +133 -0
  896. package/src/collab/text-to-yjs.ts +79 -0
  897. package/src/collab/undo.ts +432 -0
  898. package/src/collab/xml-ops.ts +68 -0
  899. package/src/collab/ydoc-manager.ts +544 -0
  900. package/src/command-navigation/actions.ts +100 -0
  901. package/src/command-navigation/index.ts +12 -0
  902. package/src/comments-review/index.ts +1 -0
  903. package/src/connections/catalog.ts +451 -0
  904. package/src/connections/index.ts +48 -0
  905. package/src/connections/reader.ts +911 -0
  906. package/src/connections/runtime.ts +1 -0
  907. package/src/credentials/index.ts +187 -0
  908. package/src/data-programs/actions.ts +335 -0
  909. package/src/data-programs/contract.ts +284 -0
  910. package/src/data-programs/execute.ts +693 -0
  911. package/src/data-programs/index.ts +72 -0
  912. package/src/data-programs/schema.ts +148 -0
  913. package/src/data-programs/store.ts +755 -0
  914. package/src/data-widgets/index.ts +376 -0
  915. package/src/db/client.ts +1627 -0
  916. package/src/db/create-get-db.ts +579 -0
  917. package/src/db/ddl-guard.ts +302 -0
  918. package/src/db/drizzle-config.ts +190 -0
  919. package/src/db/ensure-additive-columns.ts +430 -0
  920. package/src/db/index.ts +57 -0
  921. package/src/db/migrations.ts +691 -0
  922. package/src/db/request-telemetry.ts +154 -0
  923. package/src/db/runtime-diagnostics.ts +331 -0
  924. package/src/db/schema.ts +121 -0
  925. package/src/db/widen-columns.ts +75 -0
  926. package/src/db-admin/agent-tools.ts +202 -0
  927. package/src/db-admin/index.ts +26 -0
  928. package/src/db-admin/operations.ts +803 -0
  929. package/src/db-admin/routes.ts +174 -0
  930. package/src/db-admin/types.ts +110 -0
  931. package/src/demo/browser-state.ts +47 -0
  932. package/src/demo/fetch-interceptor.ts +175 -0
  933. package/src/demo/redact.ts +575 -0
  934. package/src/deploy/build.ts +3935 -0
  935. package/src/deploy/immutable-assets.ts +65 -0
  936. package/src/deploy/route-discovery.ts +458 -0
  937. package/src/deploy/workspace-core.ts +282 -0
  938. package/src/deploy/workspace-deploy.ts +1488 -0
  939. package/src/eject/provider-api-definitions.ts +193 -0
  940. package/src/eject/remote-mcp-presets.ts +137 -0
  941. package/src/eject/setup-readiness-ui.tsx +29 -0
  942. package/src/eject/workspace-connections.ts +92 -0
  943. package/src/embedding/agent.ts +159 -0
  944. package/src/embedding/bridge.ts +297 -0
  945. package/src/embedding/index.ts +43 -0
  946. package/src/embedding/protocol.ts +185 -0
  947. package/src/embedding/react.tsx +319 -0
  948. package/src/embeddings/index.ts +233 -0
  949. package/src/eval/agent-runner.ts +210 -0
  950. package/src/eval/define-eval.ts +55 -0
  951. package/src/eval/index.ts +49 -0
  952. package/src/eval/report.ts +75 -0
  953. package/src/eval/runner.ts +369 -0
  954. package/src/eval/scorer.ts +244 -0
  955. package/src/eval/types.ts +188 -0
  956. package/src/event-bus/bus.ts +140 -0
  957. package/src/event-bus/index.ts +3 -0
  958. package/src/event-bus/registry.ts +79 -0
  959. package/src/event-bus/types.ts +29 -0
  960. package/src/extensions/actions.ts +1636 -0
  961. package/src/extensions/change-marker.ts +54 -0
  962. package/src/extensions/content-patch.ts +468 -0
  963. package/src/extensions/fetch-tool.ts +461 -0
  964. package/src/extensions/html-shell.ts +803 -0
  965. package/src/extensions/local.ts +462 -0
  966. package/src/extensions/path.ts +40 -0
  967. package/src/extensions/proxy-security.ts +171 -0
  968. package/src/extensions/routes.ts +1080 -0
  969. package/src/extensions/schema.ts +269 -0
  970. package/src/extensions/session-replay-iframe.ts +131 -0
  971. package/src/extensions/slots/routes.ts +126 -0
  972. package/src/extensions/slots/schema.ts +87 -0
  973. package/src/extensions/slots/store.ts +450 -0
  974. package/src/extensions/store.ts +1347 -0
  975. package/src/extensions/theme.ts +114 -0
  976. package/src/extensions/url-safety.ts +316 -0
  977. package/src/extensions/web-content.ts +663 -0
  978. package/src/extensions/web-search-tool.ts +437 -0
  979. package/src/feature-flags/a2a-action-route.ts +56 -0
  980. package/src/feature-flags/actions/get-feature-flags.ts +24 -0
  981. package/src/feature-flags/actions/list-feature-flags.ts +69 -0
  982. package/src/feature-flags/actions/set-feature-flag.ts +89 -0
  983. package/src/feature-flags/index.ts +21 -0
  984. package/src/feature-flags/permissions.ts +53 -0
  985. package/src/feature-flags/plugin.ts +44 -0
  986. package/src/feature-flags/registry.ts +96 -0
  987. package/src/feature-flags/store.ts +176 -0
  988. package/src/file-upload/actions/upload-image.ts +213 -0
  989. package/src/file-upload/builder.ts +431 -0
  990. package/src/file-upload/index.ts +24 -0
  991. package/src/file-upload/pre-upload-attachments.ts +305 -0
  992. package/src/file-upload/registry.ts +125 -0
  993. package/src/file-upload/types.ts +89 -0
  994. package/src/guards/db-tool-scoping.ts +129 -0
  995. package/src/guards/index.ts +23 -0
  996. package/src/guards/no-drizzle-push.ts +116 -0
  997. package/src/guards/no-env-credentials.ts +229 -0
  998. package/src/guards/no-env-mutation.ts +114 -0
  999. package/src/guards/no-localhost-fallback.ts +124 -0
  1000. package/src/guards/no-unscoped-credentials.ts +227 -0
  1001. package/src/guards/no-unscoped-queries.ts +834 -0
  1002. package/src/guards/scan-utils.ts +105 -0
  1003. package/src/guards/types.ts +30 -0
  1004. package/src/history/actions/create-resource-version.ts +92 -0
  1005. package/src/history/actions/get-resource-version.ts +60 -0
  1006. package/src/history/actions/list-resource-history.ts +53 -0
  1007. package/src/history/actions/list-resource-versions.ts +43 -0
  1008. package/src/history/actions/restore-resource-version.ts +96 -0
  1009. package/src/history/index.ts +26 -0
  1010. package/src/history/registry.ts +111 -0
  1011. package/src/history/store.ts +379 -0
  1012. package/src/history/types.ts +69 -0
  1013. package/src/index.browser.ts +155 -0
  1014. package/src/index.ts +408 -0
  1015. package/src/ingestion/docx.ts +158 -0
  1016. package/src/ingestion/figma-node-to-html.ts +1860 -0
  1017. package/src/ingestion/figma.ts +548 -0
  1018. package/src/ingestion/index.ts +107 -0
  1019. package/src/ingestion/media.ts +264 -0
  1020. package/src/ingestion/notion.ts +121 -0
  1021. package/src/ingestion/office.ts +213 -0
  1022. package/src/ingestion/orchestration.ts +160 -0
  1023. package/src/ingestion/pptx.ts +331 -0
  1024. package/src/ingestion/selection.ts +81 -0
  1025. package/src/ingestion/website.ts +151 -0
  1026. package/src/integrations/a2a-continuation-marker.ts +2 -0
  1027. package/src/integrations/a2a-continuation-processor.ts +888 -0
  1028. package/src/integrations/a2a-continuations-store.ts +643 -0
  1029. package/src/integrations/adapter-overrides.ts +12 -0
  1030. package/src/integrations/adapters/discord.ts +364 -0
  1031. package/src/integrations/adapters/email.ts +1164 -0
  1032. package/src/integrations/adapters/google-docs.ts +371 -0
  1033. package/src/integrations/adapters/index.ts +29 -0
  1034. package/src/integrations/adapters/microsoft-teams.ts +413 -0
  1035. package/src/integrations/adapters/slack.ts +1914 -0
  1036. package/src/integrations/adapters/telegram.ts +386 -0
  1037. package/src/integrations/adapters/whatsapp.ts +358 -0
  1038. package/src/integrations/awaiting-input-store.ts +130 -0
  1039. package/src/integrations/catalog.ts +571 -0
  1040. package/src/integrations/computer-supervision-store.ts +423 -0
  1041. package/src/integrations/computer-supervision.ts +213 -0
  1042. package/src/integrations/config-store.ts +131 -0
  1043. package/src/integrations/controls-store.ts +187 -0
  1044. package/src/integrations/eject/messaging-adapters.ts +85 -0
  1045. package/src/integrations/google-docs-poller.ts +671 -0
  1046. package/src/integrations/identity-links-store.ts +210 -0
  1047. package/src/integrations/identity.ts +196 -0
  1048. package/src/integrations/index.ts +220 -0
  1049. package/src/integrations/installations-store.ts +677 -0
  1050. package/src/integrations/integration-memory.ts +187 -0
  1051. package/src/integrations/internal-token.ts +106 -0
  1052. package/src/integrations/pending-tasks-retry-job.ts +286 -0
  1053. package/src/integrations/pending-tasks-store.ts +468 -0
  1054. package/src/integrations/plugin.ts +3048 -0
  1055. package/src/integrations/remote-commands-store.ts +690 -0
  1056. package/src/integrations/remote-devices-store.ts +492 -0
  1057. package/src/integrations/remote-json-safety.ts +127 -0
  1058. package/src/integrations/remote-push-delivery-job.ts +48 -0
  1059. package/src/integrations/remote-push-delivery.ts +370 -0
  1060. package/src/integrations/remote-push-store.ts +664 -0
  1061. package/src/integrations/remote-retry-job.ts +55 -0
  1062. package/src/integrations/remote-run-events-store.ts +222 -0
  1063. package/src/integrations/remote-types.ts +186 -0
  1064. package/src/integrations/runtime.ts +1 -0
  1065. package/src/integrations/scope-store.ts +498 -0
  1066. package/src/integrations/slack-manifest.ts +78 -0
  1067. package/src/integrations/slack-oauth.ts +344 -0
  1068. package/src/integrations/task-queue-stats.ts +144 -0
  1069. package/src/integrations/thread-mapping-store.ts +134 -0
  1070. package/src/integrations/types.ts +485 -0
  1071. package/src/integrations/usage-budget-store.ts +906 -0
  1072. package/src/integrations/webhook-delivery.ts +55 -0
  1073. package/src/integrations/webhook-handler.ts +1939 -0
  1074. package/src/jobs/actions/list-recurring-jobs.ts +105 -0
  1075. package/src/jobs/actions/manage-recurring-job.ts +85 -0
  1076. package/src/jobs/cron.ts +126 -0
  1077. package/src/jobs/index.ts +9 -0
  1078. package/src/jobs/scheduler.ts +703 -0
  1079. package/src/jobs/tools.ts +367 -0
  1080. package/src/local-artifacts/index.ts +1372 -0
  1081. package/src/localization/actions/get-localization-preference.ts +24 -0
  1082. package/src/localization/actions/set-localization-preference.ts +32 -0
  1083. package/src/localization/default-messages.ts +1009 -0
  1084. package/src/localization/index.ts +2 -0
  1085. package/src/localization/server.ts +131 -0
  1086. package/src/localization/shared.ts +208 -0
  1087. package/src/mcp/actions/call-mcp-tool.ts +19 -0
  1088. package/src/mcp/actions/create-org-service-token.ts +87 -0
  1089. package/src/mcp/actions/list-mcp-tools.ts +18 -0
  1090. package/src/mcp/actions/list-org-service-tokens.ts +44 -0
  1091. package/src/mcp/actions/revoke-org-service-token.ts +30 -0
  1092. package/src/mcp/actions/service-token-access.ts +121 -0
  1093. package/src/mcp/ask-app-inline-tasks.ts +125 -0
  1094. package/src/mcp/build-server.ts +2356 -0
  1095. package/src/mcp/builtin-tools.ts +1506 -0
  1096. package/src/mcp/connect-route.ts +1460 -0
  1097. package/src/mcp/connect-store.ts +680 -0
  1098. package/src/mcp/embed-app.ts +2051 -0
  1099. package/src/mcp/embed-route.ts +84 -0
  1100. package/src/mcp/external-agent-policy.ts +18 -0
  1101. package/src/mcp/index.ts +47 -0
  1102. package/src/mcp/oauth-route.ts +1016 -0
  1103. package/src/mcp/oauth-store.ts +581 -0
  1104. package/src/mcp/oauth-token.ts +227 -0
  1105. package/src/mcp/org-directory.ts +343 -0
  1106. package/src/mcp/route-paths.ts +34 -0
  1107. package/src/mcp/screen-memory-stdio.ts +290 -0
  1108. package/src/mcp/server.ts +507 -0
  1109. package/src/mcp/stdio.ts +328 -0
  1110. package/src/mcp/workspace-resolve.ts +261 -0
  1111. package/src/mcp-client/app-api.ts +136 -0
  1112. package/src/mcp-client/app-result.ts +64 -0
  1113. package/src/mcp-client/builtin-capabilities.ts +146 -0
  1114. package/src/mcp-client/builtin-store.ts +93 -0
  1115. package/src/mcp-client/config.ts +281 -0
  1116. package/src/mcp-client/errors.ts +54 -0
  1117. package/src/mcp-client/hub-client.ts +172 -0
  1118. package/src/mcp-client/hub-routes.ts +198 -0
  1119. package/src/mcp-client/index.ts +504 -0
  1120. package/src/mcp-client/manager.ts +968 -0
  1121. package/src/mcp-client/oauth-client.ts +462 -0
  1122. package/src/mcp-client/oauth-routes.ts +307 -0
  1123. package/src/mcp-client/remote-store.ts +674 -0
  1124. package/src/mcp-client/remote-url.ts +97 -0
  1125. package/src/mcp-client/routes.ts +1093 -0
  1126. package/src/mcp-client/screen-memory-local.ts +461 -0
  1127. package/src/mcp-client/tool-policy.ts +182 -0
  1128. package/src/mcp-client/visibility.ts +56 -0
  1129. package/src/mcp-client/workspace-servers.ts +379 -0
  1130. package/src/navigation/index.ts +170 -0
  1131. package/src/notifications/actions.ts +151 -0
  1132. package/src/notifications/channels.ts +410 -0
  1133. package/src/notifications/index.ts +22 -0
  1134. package/src/notifications/registry.ts +216 -0
  1135. package/src/notifications/routes.ts +106 -0
  1136. package/src/notifications/store.ts +236 -0
  1137. package/src/notifications/types.ts +52 -0
  1138. package/src/oauth-tokens/google-refresh.ts +175 -0
  1139. package/src/oauth-tokens/index.ts +15 -0
  1140. package/src/oauth-tokens/store.ts +384 -0
  1141. package/src/observability/cleanup-job.ts +124 -0
  1142. package/src/observability/evals.ts +507 -0
  1143. package/src/observability/experiments.ts +359 -0
  1144. package/src/observability/feedback.ts +332 -0
  1145. package/src/observability/hosted-model-experiment.ts +118 -0
  1146. package/src/observability/index.ts +62 -0
  1147. package/src/observability/plugin.ts +31 -0
  1148. package/src/observability/routes.ts +431 -0
  1149. package/src/observability/sentiment.ts +261 -0
  1150. package/src/observability/store.ts +1347 -0
  1151. package/src/observability/traces.ts +789 -0
  1152. package/src/observability/tracing.ts +157 -0
  1153. package/src/observability/tracking-identity.ts +55 -0
  1154. package/src/observability/types.ts +211 -0
  1155. package/src/onboarding/default-steps.ts +428 -0
  1156. package/src/onboarding/index.ts +22 -0
  1157. package/src/onboarding/plugin.ts +262 -0
  1158. package/src/onboarding/registry.ts +47 -0
  1159. package/src/onboarding/types.ts +96 -0
  1160. package/src/org/accept-pending.ts +98 -0
  1161. package/src/org/auto-join-domain.ts +113 -0
  1162. package/src/org/context.ts +614 -0
  1163. package/src/org/free-email-providers.ts +124 -0
  1164. package/src/org/handlers.ts +1153 -0
  1165. package/src/org/index.ts +63 -0
  1166. package/src/org/migrations.ts +105 -0
  1167. package/src/org/permissions.ts +30 -0
  1168. package/src/org/plugin.ts +255 -0
  1169. package/src/org/schema.ts +28 -0
  1170. package/src/org/types.ts +57 -0
  1171. package/src/org-team/index.ts +1 -0
  1172. package/src/package-lifecycle/deprecated-imports.ts +179 -0
  1173. package/src/package-lifecycle/eject-manifest.ts +345 -0
  1174. package/src/package-lifecycle/index.ts +7 -0
  1175. package/src/package-lifecycle/manifest.ts +120 -0
  1176. package/src/package-lifecycle/migration-manifest.ts +159 -0
  1177. package/src/package-lifecycle/migration-message.ts +6 -0
  1178. package/src/package-lifecycle/tombstone.ts +58 -0
  1179. package/src/package-lifecycle/upgrade-error.ts +37 -0
  1180. package/src/private-blob/index.ts +18 -0
  1181. package/src/private-blob/registry.ts +242 -0
  1182. package/src/private-blob/types.ts +55 -0
  1183. package/src/progress/actions.ts +179 -0
  1184. package/src/progress/index.ts +16 -0
  1185. package/src/progress/registry.ts +127 -0
  1186. package/src/progress/routes.ts +89 -0
  1187. package/src/progress/store.ts +353 -0
  1188. package/src/progress/types.ts +59 -0
  1189. package/src/provider-api/actions/custom-provider-registration.ts +197 -0
  1190. package/src/provider-api/actions/delete-staged-dataset.ts +5 -0
  1191. package/src/provider-api/actions/github-repo-files.ts +266 -0
  1192. package/src/provider-api/actions/list-staged-datasets.ts +5 -0
  1193. package/src/provider-api/actions/provider-api-audit.ts +88 -0
  1194. package/src/provider-api/actions/provider-api.ts +460 -0
  1195. package/src/provider-api/actions/query-staged-dataset.ts +5 -0
  1196. package/src/provider-api/actions/staged-datasets.ts +359 -0
  1197. package/src/provider-api/corpus-jobs-store.ts +522 -0
  1198. package/src/provider-api/corpus-jobs.ts +1817 -0
  1199. package/src/provider-api/custom-registry.ts +456 -0
  1200. package/src/provider-api/github-repo.ts +675 -0
  1201. package/src/provider-api/gong.ts +108 -0
  1202. package/src/provider-api/index.ts +5444 -0
  1203. package/src/provider-api/quota-governor.ts +562 -0
  1204. package/src/provider-api/runtime.ts +1 -0
  1205. package/src/provider-api/staged-datasets-aggregate.ts +304 -0
  1206. package/src/provider-api/staged-datasets-store.ts +441 -0
  1207. package/src/provider-api/staging.ts +483 -0
  1208. package/src/resources/agents.ts +65 -0
  1209. package/src/resources/emitter.ts +54 -0
  1210. package/src/resources/handlers.ts +728 -0
  1211. package/src/resources/index.ts +4 -0
  1212. package/src/resources/metadata.ts +252 -0
  1213. package/src/resources/script-helpers.ts +160 -0
  1214. package/src/resources/store.ts +1618 -0
  1215. package/src/review/actions/consume-review-feedback.ts +48 -0
  1216. package/src/review/actions/create-review-comment.ts +108 -0
  1217. package/src/review/actions/delete-review-comment.ts +67 -0
  1218. package/src/review/actions/get-review-feedback.ts +49 -0
  1219. package/src/review/actions/list-review-comments.ts +87 -0
  1220. package/src/review/actions/reply-review-comment.ts +118 -0
  1221. package/src/review/actions/resolve-review-thread.ts +94 -0
  1222. package/src/review/actions/send-review-thread-to-agent.ts +62 -0
  1223. package/src/review/actions/set-review-status.ts +58 -0
  1224. package/src/review/identity.ts +101 -0
  1225. package/src/review/index.ts +45 -0
  1226. package/src/review/mentions.ts +44 -0
  1227. package/src/review/registry.ts +111 -0
  1228. package/src/review/store.ts +997 -0
  1229. package/src/review/types.ts +101 -0
  1230. package/src/router/index.ts +24 -0
  1231. package/src/scripts/agent-engines/list-agent-engines.ts +130 -0
  1232. package/src/scripts/agent-engines/manage-agent-engine.ts +197 -0
  1233. package/src/scripts/agent-engines/set-agent-engine.ts +84 -0
  1234. package/src/scripts/agent-engines/test-agent-engine.ts +174 -0
  1235. package/src/scripts/call-agent.ts +792 -0
  1236. package/src/scripts/chat/index.ts +8 -0
  1237. package/src/scripts/chat/open-chat.ts +56 -0
  1238. package/src/scripts/chat/search-chats.ts +121 -0
  1239. package/src/scripts/core-scripts.ts +22 -0
  1240. package/src/scripts/db/check-scoping.ts +212 -0
  1241. package/src/scripts/db/exec.ts +791 -0
  1242. package/src/scripts/db/index.ts +19 -0
  1243. package/src/scripts/db/migrate-encrypt-credentials.ts +223 -0
  1244. package/src/scripts/db/migrate-encrypt-oauth-tokens.ts +213 -0
  1245. package/src/scripts/db/migrate-user-api-keys.ts +257 -0
  1246. package/src/scripts/db/patch.ts +820 -0
  1247. package/src/scripts/db/query.ts +299 -0
  1248. package/src/scripts/db/reset-dev-owner.ts +285 -0
  1249. package/src/scripts/db/safety.ts +286 -0
  1250. package/src/scripts/db/schema.ts +364 -0
  1251. package/src/scripts/db/scoping.ts +341 -0
  1252. package/src/scripts/db/sqlite-client.ts +78 -0
  1253. package/src/scripts/db/tool-mode.ts +23 -0
  1254. package/src/scripts/db/tool-schemas.ts +31 -0
  1255. package/src/scripts/db/wipe-leaked-builder-keys.ts +201 -0
  1256. package/src/scripts/dev/index.ts +296 -0
  1257. package/src/scripts/dev/list-files.ts +119 -0
  1258. package/src/scripts/dev/read-file.ts +77 -0
  1259. package/src/scripts/dev/search-files.ts +151 -0
  1260. package/src/scripts/dev/shell.ts +111 -0
  1261. package/src/scripts/dev/write-file.ts +56 -0
  1262. package/src/scripts/dev-session.ts +96 -0
  1263. package/src/scripts/docs/index.ts +8 -0
  1264. package/src/scripts/docs/search.ts +274 -0
  1265. package/src/scripts/docs/source-search.ts +363 -0
  1266. package/src/scripts/index.ts +15 -0
  1267. package/src/scripts/manage-agent-loop-settings.ts +84 -0
  1268. package/src/scripts/parse-args.ts +46 -0
  1269. package/src/scripts/resources/delete-memory.ts +67 -0
  1270. package/src/scripts/resources/delete.ts +69 -0
  1271. package/src/scripts/resources/effective.ts +71 -0
  1272. package/src/scripts/resources/index.ts +18 -0
  1273. package/src/scripts/resources/list.ts +103 -0
  1274. package/src/scripts/resources/migrate-learnings.ts +40 -0
  1275. package/src/scripts/resources/read.ts +107 -0
  1276. package/src/scripts/resources/save-memory.ts +99 -0
  1277. package/src/scripts/resources/write.ts +158 -0
  1278. package/src/scripts/runner.ts +339 -0
  1279. package/src/scripts/utils.ts +130 -0
  1280. package/src/search/index.ts +413 -0
  1281. package/src/search-utils/index.ts +112 -0
  1282. package/src/secrets/crypto.ts +228 -0
  1283. package/src/secrets/index.ts +65 -0
  1284. package/src/secrets/onboarding.ts +101 -0
  1285. package/src/secrets/register-framework-secrets.ts +228 -0
  1286. package/src/secrets/register.ts +129 -0
  1287. package/src/secrets/routes.ts +697 -0
  1288. package/src/secrets/schema.ts +52 -0
  1289. package/src/secrets/storage.ts +561 -0
  1290. package/src/secrets/substitution.ts +305 -0
  1291. package/src/server/__snapshots__/agent-chat-plugin.surface.spec.ts.snap +150 -0
  1292. package/src/server/action-change.ts +66 -0
  1293. package/src/server/action-discovery.ts +774 -0
  1294. package/src/server/action-routes.ts +608 -0
  1295. package/src/server/agent-access.ts +72 -0
  1296. package/src/server/agent-chat/action-filters-a2a.ts +339 -0
  1297. package/src/server/agent-chat/browser-team-tools.ts +510 -0
  1298. package/src/server/agent-chat/context-tools.ts +599 -0
  1299. package/src/server/agent-chat/framework-prompts.ts +467 -0
  1300. package/src/server/agent-chat/lazy-fs.ts +11 -0
  1301. package/src/server/agent-chat/mcp-glue.ts +91 -0
  1302. package/src/server/agent-chat/plugin-options.ts +379 -0
  1303. package/src/server/agent-chat/process-run-failure.ts +62 -0
  1304. package/src/server/agent-chat/prompt-resources.ts +1004 -0
  1305. package/src/server/agent-chat/recurring-jobs-runtime.ts +80 -0
  1306. package/src/server/agent-chat/request-surface.ts +71 -0
  1307. package/src/server/agent-chat/run-code-tools.ts +67 -0
  1308. package/src/server/agent-chat/script-entries.ts +796 -0
  1309. package/src/server/agent-chat/shared-thread.ts +301 -0
  1310. package/src/server/agent-chat/skill-frontmatter.ts +41 -0
  1311. package/src/server/agent-chat-plugin.ts +5930 -0
  1312. package/src/server/agent-discovery.ts +706 -0
  1313. package/src/server/agent-engine-api-key-route.ts +236 -0
  1314. package/src/server/agent-run-context.ts +204 -0
  1315. package/src/server/agent-teams-run-queue.ts +344 -0
  1316. package/src/server/agent-teams.ts +2257 -0
  1317. package/src/server/agents-bundle.ts +464 -0
  1318. package/src/server/analytics.ts +105 -0
  1319. package/src/server/app-base-path.ts +79 -0
  1320. package/src/server/app-name.ts +53 -0
  1321. package/src/server/app-url.ts +184 -0
  1322. package/src/server/attachment-actions.ts +276 -0
  1323. package/src/server/attribution.ts +214 -0
  1324. package/src/server/auth-marketing.ts +260 -0
  1325. package/src/server/auth-plugin.ts +27 -0
  1326. package/src/server/auth.ts +3803 -0
  1327. package/src/server/better-auth-instance.ts +1197 -0
  1328. package/src/server/builder-browser.ts +1701 -0
  1329. package/src/server/builder-design-systems.ts +668 -0
  1330. package/src/server/builder-space.ts +176 -0
  1331. package/src/server/captcha.ts +63 -0
  1332. package/src/server/capture-error.ts +64 -0
  1333. package/src/server/cli-capture.ts +141 -0
  1334. package/src/server/collab-plugin.ts +391 -0
  1335. package/src/server/complete-text.ts +231 -0
  1336. package/src/server/cookie-namespace.ts +159 -0
  1337. package/src/server/core-routes-plugin.ts +4122 -0
  1338. package/src/server/cors-origins.ts +60 -0
  1339. package/src/server/create-server.ts +268 -0
  1340. package/src/server/credential-provider.ts +1202 -0
  1341. package/src/server/csrf.ts +229 -0
  1342. package/src/server/date-utils.ts +42 -0
  1343. package/src/server/deep-link.ts +119 -0
  1344. package/src/server/derived-secret.ts +32 -0
  1345. package/src/server/design-token-utils.ts +1032 -0
  1346. package/src/server/desktop-sso.ts +83 -0
  1347. package/src/server/edge.ts +69 -0
  1348. package/src/server/email-actions.ts +218 -0
  1349. package/src/server/email-template.ts +192 -0
  1350. package/src/server/email-templates.ts +148 -0
  1351. package/src/server/email.ts +219 -0
  1352. package/src/server/embed-route.ts +283 -0
  1353. package/src/server/embed-session.ts +805 -0
  1354. package/src/server/embedded.ts +252 -0
  1355. package/src/server/entry-server.tsx +154 -0
  1356. package/src/server/framework-request-handler.ts +848 -0
  1357. package/src/server/fusion-app.ts +447 -0
  1358. package/src/server/google-auth-mode.ts +34 -0
  1359. package/src/server/google-auth-plugin.ts +496 -0
  1360. package/src/server/google-oauth-credentials.ts +128 -0
  1361. package/src/server/google-oauth.ts +972 -0
  1362. package/src/server/google-realtime-session.ts +182 -0
  1363. package/src/server/h3-helpers.ts +174 -0
  1364. package/src/server/http-response-telemetry.ts +396 -0
  1365. package/src/server/identity-sso-store.ts +304 -0
  1366. package/src/server/identity-sso.ts +514 -0
  1367. package/src/server/index.ts +593 -0
  1368. package/src/server/missing-key.ts +36 -0
  1369. package/src/server/oauth-helpers.ts +44 -0
  1370. package/src/server/oauth-public-origin.ts +44 -0
  1371. package/src/server/oauth-return-url.ts +120 -0
  1372. package/src/server/og-fonts-data.ts +15 -0
  1373. package/src/server/og-fonts.ts +75 -0
  1374. package/src/server/onboarding-html.ts +4040 -0
  1375. package/src/server/open-route.ts +311 -0
  1376. package/src/server/org-admin.ts +28 -0
  1377. package/src/server/poll-events.ts +88 -0
  1378. package/src/server/poll.ts +1224 -0
  1379. package/src/server/prompts/framework-core-compact.ts +107 -0
  1380. package/src/server/prompts/framework-core.ts +143 -0
  1381. package/src/server/prompts/index.ts +16 -0
  1382. package/src/server/prompts/model-overlays.ts +54 -0
  1383. package/src/server/prompts/shared-rules.ts +104 -0
  1384. package/src/server/realtime-voice.ts +967 -0
  1385. package/src/server/recap-image-route.ts +242 -0
  1386. package/src/server/recap-image-store.ts +185 -0
  1387. package/src/server/request-context.ts +416 -0
  1388. package/src/server/request-origin.ts +67 -0
  1389. package/src/server/resources-plugin.ts +119 -0
  1390. package/src/server/schema-prompt.ts +429 -0
  1391. package/src/server/scoped-key-storage.ts +223 -0
  1392. package/src/server/security-headers.ts +170 -0
  1393. package/src/server/self-dispatch.ts +224 -0
  1394. package/src/server/sentry-config.ts +73 -0
  1395. package/src/server/sentry-plugin.ts +138 -0
  1396. package/src/server/sentry.ts +444 -0
  1397. package/src/server/short-lived-token.ts +170 -0
  1398. package/src/server/social-og-image.ts +454 -0
  1399. package/src/server/sse.ts +102 -0
  1400. package/src/server/ssr-handler.ts +466 -0
  1401. package/src/server/transcribe-voice.ts +1076 -0
  1402. package/src/server/voice-providers-status.ts +118 -0
  1403. package/src/server/workspace-oauth.ts +31 -0
  1404. package/src/server/workspace-provider-oauth.ts +970 -0
  1405. package/src/session-replay-iframe-protocol.ts +58 -0
  1406. package/src/settings/handlers.ts +44 -0
  1407. package/src/settings/index.ts +34 -0
  1408. package/src/settings/org-settings.ts +83 -0
  1409. package/src/settings/script-helpers.ts +24 -0
  1410. package/src/settings/store.ts +247 -0
  1411. package/src/settings/user-settings.ts +47 -0
  1412. package/src/setup-connections/index.ts +90 -0
  1413. package/src/setup-connections/onboarding.ts +47 -0
  1414. package/src/shared/agent-access.ts +112 -0
  1415. package/src/shared/agent-chat.ts +124 -0
  1416. package/src/shared/agent-env.ts +46 -0
  1417. package/src/shared/agent-readable-resource.ts +111 -0
  1418. package/src/shared/agent-sidebar-url.ts +39 -0
  1419. package/src/shared/cache-control.ts +25 -0
  1420. package/src/shared/cloudflare-globals.d.ts +34 -0
  1421. package/src/shared/context-xray.ts +172 -0
  1422. package/src/shared/embed-auth.ts +6 -0
  1423. package/src/shared/index.ts +83 -0
  1424. package/src/shared/llm-connection.ts +42 -0
  1425. package/src/shared/markdown-block-split.ts +129 -0
  1426. package/src/shared/mcp-connect-content.ts +130 -0
  1427. package/src/shared/mcp-embed-headers.ts +175 -0
  1428. package/src/shared/mcp-integration-config.ts +101 -0
  1429. package/src/shared/merge-by-id.ts +14 -0
  1430. package/src/shared/oauth-state.ts +39 -0
  1431. package/src/shared/reasoning-effort.ts +228 -0
  1432. package/src/shared/route-warmup-config.ts +128 -0
  1433. package/src/shared/runtime.ts +31 -0
  1434. package/src/shared/social-meta.ts +82 -0
  1435. package/src/shared/streaming-text-smoothing.ts +184 -0
  1436. package/src/shared/truncate.ts +13 -0
  1437. package/src/shared/workspace-app-audience.ts +177 -0
  1438. package/src/shared/workspace-app-id.ts +54 -0
  1439. package/src/sharing/access.ts +585 -0
  1440. package/src/sharing/actions/create-agent-resource-link.ts +91 -0
  1441. package/src/sharing/actions/extension-change.ts +22 -0
  1442. package/src/sharing/actions/list-resource-shares.ts +93 -0
  1443. package/src/sharing/actions/set-resource-visibility.ts +91 -0
  1444. package/src/sharing/actions/share-resource.ts +322 -0
  1445. package/src/sharing/actions/unshare-resource.ts +72 -0
  1446. package/src/sharing/index.ts +35 -0
  1447. package/src/sharing/registry.ts +201 -0
  1448. package/src/sharing/schema.ts +99 -0
  1449. package/src/styles/agent-conversation.css +766 -0
  1450. package/src/styles/agent-native.css +938 -0
  1451. package/src/styles/blocks.css +1717 -0
  1452. package/src/styles/chat-history-list.css +1 -0
  1453. package/src/styles/rich-markdown-editor.css +1 -0
  1454. package/src/tailwind.preset.ts +140 -0
  1455. package/src/templates/chat/.agents/skills/agent-native-docs/SKILL.md +15 -13
  1456. package/src/templates/chat/.agents/skills/customizing-agent-native/SKILL.md +63 -20
  1457. package/src/templates/chat/.agents/skills/self-modifying-code/SKILL.md +9 -6
  1458. package/src/templates/chat/AGENTS.md +3 -2
  1459. package/src/templates/default/.agents/skills/agent-native-docs/SKILL.md +15 -13
  1460. package/src/templates/default/.agents/skills/customizing-agent-native/SKILL.md +63 -20
  1461. package/src/templates/default/.agents/skills/self-modifying-code/SKILL.md +9 -6
  1462. package/src/templates/default/AGENTS.md +6 -5
  1463. package/src/templates/headless/.agents/skills/agent-native-docs/SKILL.md +15 -13
  1464. package/src/templates/headless/.agents/skills/customizing-agent-native/SKILL.md +63 -20
  1465. package/src/templates/headless/AGENTS.md +5 -4
  1466. package/src/templates/workspace-core/.agents/skills/agent-native-docs/SKILL.md +15 -13
  1467. package/src/templates/workspace-core/.agents/skills/agent-native-toolkit/SKILL.md +3 -2
  1468. package/src/templates/workspace-core/.agents/skills/customizing-agent-native/SKILL.md +63 -20
  1469. package/src/templates/workspace-core/.agents/skills/self-modifying-code/SKILL.md +9 -6
  1470. package/src/templates/workspace-core/AGENTS.md +4 -4
  1471. package/src/templates/workspace-root/AGENTS.md +4 -4
  1472. package/src/terminal/cli-registry.ts +57 -0
  1473. package/src/terminal/index.ts +22 -0
  1474. package/src/terminal/pty-server.ts +389 -0
  1475. package/src/terminal/terminal-plugin.ts +265 -0
  1476. package/src/testing.ts +23 -0
  1477. package/src/tracking/index.ts +10 -0
  1478. package/src/tracking/providers.ts +422 -0
  1479. package/src/tracking/registry.ts +102 -0
  1480. package/src/tracking/route.ts +108 -0
  1481. package/src/tracking/types.ts +16 -0
  1482. package/src/transcription/builder-transcription.ts +118 -0
  1483. package/src/triggers/actions/list-automations.ts +99 -0
  1484. package/src/triggers/actions/manage-automation.ts +78 -0
  1485. package/src/triggers/actions.ts +333 -0
  1486. package/src/triggers/condition-evaluator.ts +163 -0
  1487. package/src/triggers/dispatcher.ts +536 -0
  1488. package/src/triggers/index.ts +13 -0
  1489. package/src/triggers/routes.ts +322 -0
  1490. package/src/triggers/types.ts +42 -0
  1491. package/src/types/pglite.d.ts +26 -0
  1492. package/src/usage/store.ts +698 -0
  1493. package/src/vite/action-types-plugin.ts +481 -0
  1494. package/src/vite/agent-web-plugin.ts +78 -0
  1495. package/src/vite/agents-bundle-plugin.ts +185 -0
  1496. package/src/vite/client.ts +3039 -0
  1497. package/src/vite/index.ts +21 -0
  1498. package/src/voice/index.ts +18 -0
  1499. package/src/voice/voice-cleanup-prompt.ts +38 -0
  1500. package/src/voice/voice-context.ts +217 -0
  1501. package/src/voice/voice-replacements.ts +75 -0
  1502. package/src/workspace-connections/credentials.ts +603 -0
  1503. package/src/workspace-connections/index.ts +72 -0
  1504. package/src/workspace-connections/lifecycle.ts +43 -0
  1505. package/src/workspace-connections/store.ts +1943 -0
  1506. package/src/workspace-files/index.ts +18 -0
  1507. package/src/workspace-files/store.ts +339 -0
  1508. package/src/workspace-files/tool.ts +266 -0
@@ -0,0 +1,1914 @@
1
+ import type { H3Event } from "h3";
2
+ import { createError, getHeader, readRawBody } from "h3";
3
+
4
+ import type { EnvKeyConfig } from "../../server/create-server.js";
5
+ import { resolveSecret } from "../../server/credential-provider.js";
6
+ import { getRequestContext } from "../../server/request-context.js";
7
+ import { getIntegrationRequestContext } from "../../server/request-context.js";
8
+ import { consumeIntegrationAwaitingInput } from "../awaiting-input-store.js";
9
+ import { createIntegrationControl } from "../controls-store.js";
10
+ import {
11
+ getActiveIntegrationInstallationByKey,
12
+ getActiveIntegrationInstallationForTenant,
13
+ listIntegrationInstallations,
14
+ resolveIntegrationTokenBundle,
15
+ } from "../installations-store.js";
16
+ import { hasActivePendingTask } from "../pending-tasks-store.js";
17
+ import { slackInstallationKey } from "../slack-oauth.js";
18
+ import type {
19
+ PlatformAdapter,
20
+ IncomingMessage,
21
+ OutgoingMessage,
22
+ IntegrationStatus,
23
+ OutboundTarget,
24
+ PlatformRunProgress,
25
+ PlatformRunProgressRef,
26
+ PlatformDeliveryReceipt,
27
+ IntegrationContextMessage,
28
+ IntegrationFileReference,
29
+ } from "../types.js";
30
+
31
+ /** Slack's max message length */
32
+ const SLACK_MAX_LENGTH = 4000;
33
+ const SLACK_SECTION_TEXT_MAX_LENGTH = 3000;
34
+ const SLACK_API_TIMEOUT_MS = 10_000;
35
+ // Permalink lookup happens on Slack's acknowledgement path, so keep it well
36
+ // inside Slack's three-second Events API deadline. Failure is non-fatal: the
37
+ // normalized message still carries channel/thread ids for replies.
38
+ const SLACK_PERMALINK_TIMEOUT_MS = 1_000;
39
+ const SLACK_CONTEXT_MESSAGE_LIMIT = 15;
40
+ const SLACK_CONTEXT_TEXT_LIMIT = 2_000;
41
+ const SLACK_CALM_PROGRESS_THRESHOLD_SECONDS = 30;
42
+ const SLACK_IDENTITY_TIMEOUT_MS = 1_000;
43
+ const SLACK_IDENTITY_CACHE_TTL_MS = 10 * 60 * 1_000;
44
+ // Failed users.info lookups only get a short negative TTL: a transient Slack
45
+ // API blip must not fail-close a sender's identity (and DMs) for 10 minutes.
46
+ const SLACK_IDENTITY_NEGATIVE_CACHE_TTL_MS = 30 * 1_000;
47
+ const SLACK_IDENTITY_CACHE_MAX_ENTRIES = 1_000;
48
+
49
+ interface SlackUserIdentity {
50
+ email: string | null;
51
+ name: string | null;
52
+ memberType: "owner" | "admin" | "member" | "guest" | "external" | "unknown";
53
+ }
54
+
55
+ const slackIdentityCache = new Map<
56
+ string,
57
+ { identity: SlackUserIdentity | null; expiresAt: number }
58
+ >();
59
+
60
+ // Deduped system notices send at most once per key per TTL so senders are
61
+ // informed without being spammed per message. Callers pick the window: the
62
+ // anonymous-tier heads-up uses the default day-long TTL; decline replies pass
63
+ // a short TTL so a persistent condition still reminds the sender occasionally.
64
+ const SLACK_SYSTEM_NOTICE_DEDUPE_TTL_MS = 24 * 60 * 60 * 1_000;
65
+ const SLACK_SYSTEM_NOTICE_CACHE_MAX_ENTRIES = 1_000;
66
+ const slackSystemNoticeCache = new Map<string, number>();
67
+
68
+ /** Returns true when a deduped notice should send now, claiming the slot. */
69
+ function claimSlackSystemNoticeSlot(
70
+ key: string,
71
+ ttlMs = SLACK_SYSTEM_NOTICE_DEDUPE_TTL_MS,
72
+ ): boolean {
73
+ const now = Date.now();
74
+ const expiresAt = slackSystemNoticeCache.get(key);
75
+ if (expiresAt && expiresAt > now) return false;
76
+ if (expiresAt) slackSystemNoticeCache.delete(key);
77
+ if (slackSystemNoticeCache.size >= SLACK_SYSTEM_NOTICE_CACHE_MAX_ENTRIES) {
78
+ const oldestKey = slackSystemNoticeCache.keys().next().value;
79
+ if (oldestKey) slackSystemNoticeCache.delete(oldestKey);
80
+ }
81
+ slackSystemNoticeCache.set(key, now + ttlMs);
82
+ return true;
83
+ }
84
+
85
+ export interface SlackAdapterOptions {
86
+ /** Resolve the bot token for the exact Slack installation. */
87
+ resolveBotToken?: (incoming: IncomingMessage) => Promise<string | undefined>;
88
+ /** Override active-thread detection for hosted adapters/tests. */
89
+ isThreadActive?: (incoming: IncomingMessage) => Promise<boolean>;
90
+ /** Override one-shot clarification-window consumption for tests. */
91
+ consumeAwaitingInput?: (incoming: IncomingMessage) => Promise<boolean>;
92
+ }
93
+
94
+ /**
95
+ * Create a Slack platform adapter.
96
+ *
97
+ * Required env vars:
98
+ * - SLACK_BOT_TOKEN — Bot user OAuth token (xoxb-...)
99
+ * - SLACK_SIGNING_SECRET — Used to verify webhook signatures
100
+ *
101
+ * Optional env vars:
102
+ * - SLACK_ALLOWED_TEAM_IDS — Comma-separated list of Slack workspace
103
+ * `team_id` values (e.g. "T012ABCDEF,T034GHIJKL") that this deployment
104
+ * accepts events from. Required in production and strongly recommended
105
+ * to prevent cross-workspace event injection (H1 in the webhook audit):
106
+ * the global `SLACK_SIGNING_SECRET` is the same key for every workspace
107
+ * the app is installed to, so without an allowlist any installed
108
+ * workspace can drive the agent. When unset the adapter accepts events
109
+ * from any workspace in development, but rejects events in production.
110
+ * - SLACK_ALLOWED_API_APP_IDS — Comma-separated list of Slack app IDs
111
+ * (`api_app_id`) to additionally pin events to. Useful when the same
112
+ * signing secret rotation surfaces multiple app installs.
113
+ */
114
+ export function slackAdapter(
115
+ options: SlackAdapterOptions = {},
116
+ ): PlatformAdapter {
117
+ const resolveBotToken = async (incoming: IncomingMessage) =>
118
+ (await options.resolveBotToken?.(incoming)) ??
119
+ (await resolveManagedSlackBotToken(incoming)) ??
120
+ (await resolveSecret("SLACK_BOT_TOKEN")) ??
121
+ undefined;
122
+
123
+ return {
124
+ platform: "slack",
125
+ label: "Slack",
126
+ capabilities: {
127
+ replyText: true,
128
+ proactiveMessages: true,
129
+ nativeThreads: true,
130
+ contextualReplies: true,
131
+ deferredWebhookResponse: false,
132
+ interactionOnly: false,
133
+ nativeContextHydration: true,
134
+ liveRunProgress: true,
135
+ },
136
+
137
+ getRequiredEnvKeys(): EnvKeyConfig[] {
138
+ return [
139
+ {
140
+ key: "SLACK_BOT_TOKEN",
141
+ label: "Slack Bot Token",
142
+ required: false,
143
+ helpText:
144
+ "In your Slack app's left nav: OAuth & Permissions → Bot User OAuth Token (starts with `xoxb-`).",
145
+ },
146
+ {
147
+ key: "SLACK_CLIENT_ID",
148
+ label: "Slack OAuth Client ID",
149
+ required: false,
150
+ helpText:
151
+ "Slack app Basic Information → App Credentials → Client ID.",
152
+ },
153
+ {
154
+ key: "SLACK_CLIENT_SECRET",
155
+ label: "Slack OAuth Client Secret",
156
+ required: false,
157
+ helpText:
158
+ "Slack app Basic Information → App Credentials → Client Secret.",
159
+ },
160
+ {
161
+ key: "SLACK_SIGNING_SECRET",
162
+ label: "Slack Signing Secret",
163
+ required: true,
164
+ helpText:
165
+ "In your Slack app's left nav: Basic Information → App Credentials → Signing Secret.",
166
+ },
167
+ ];
168
+ },
169
+
170
+ async handleVerification(
171
+ event: H3Event,
172
+ ): Promise<{ handled: boolean; response?: unknown }> {
173
+ // Slack sends url_verification when first setting up the webhook.
174
+ // readRawBodyCached caches the raw bytes on event.context.__rawBody so
175
+ // subsequent verifyWebhook + parseIncomingMessage calls re-use them
176
+ // without re-stringifying a parsed body (M2 in the audit).
177
+ const body = await readRawBodyCached(event);
178
+ try {
179
+ const parsed = JSON.parse(body);
180
+ if (parsed.type === "url_verification") {
181
+ // Slack's URL verifier expects the raw challenge value in the
182
+ // response body. Returning JSON works for some clients but the app
183
+ // settings verifier rejects it as not matching the challenge.
184
+ return { handled: true, response: parsed.challenge };
185
+ }
186
+ } catch {}
187
+ return { handled: false };
188
+ },
189
+
190
+ async verifyWebhook(event: H3Event): Promise<boolean> {
191
+ const signingSecret = await resolveSecret("SLACK_SIGNING_SECRET");
192
+ if (!signingSecret) return false;
193
+
194
+ const signature = getHeader(event, "x-slack-signature");
195
+ const timestamp = getHeader(event, "x-slack-request-timestamp");
196
+ if (!signature || !timestamp) return false;
197
+
198
+ // Reject requests older than 5 minutes (replay protection)
199
+ const ts = parseInt(timestamp, 10);
200
+ if (Math.abs(Date.now() / 1000 - ts) > 300) return false;
201
+
202
+ const body = await readRawBodyCached(event);
203
+ const crypto = await import("node:crypto");
204
+ const basestring = `v0:${timestamp}:${body}`;
205
+ const expectedSignature =
206
+ "v0=" +
207
+ crypto
208
+ .createHmac("sha256", signingSecret)
209
+ .update(basestring)
210
+ .digest("hex");
211
+
212
+ // Timing-safe comparison
213
+ try {
214
+ return crypto.timingSafeEqual(
215
+ Buffer.from(signature),
216
+ Buffer.from(expectedSignature),
217
+ );
218
+ } catch {
219
+ return false;
220
+ }
221
+ },
222
+
223
+ async parseIncomingMessage(
224
+ event: H3Event,
225
+ ): Promise<IncomingMessage | null> {
226
+ const raw = await readRawBodyCached(event);
227
+ let payload: any;
228
+ try {
229
+ payload = JSON.parse(raw);
230
+ } catch {
231
+ return null;
232
+ }
233
+
234
+ // H1 (webhook audit): cross-workspace event injection. The global
235
+ // SLACK_SIGNING_SECRET is the same key for every workspace this Slack
236
+ // app is installed to — without a per-tenant allowlist any installed
237
+ // workspace can drive the agent. We enforce SLACK_ALLOWED_TEAM_IDS
238
+ // here AFTER the signature has already been verified by the webhook
239
+ // handler, so this is purely a tenant-isolation gate (not a forgery
240
+ // defense). When unset in production we surface a one-time warning
241
+ // recommending it be configured.
242
+ await enforceWorkspaceAllowlist(payload);
243
+
244
+ // Handle Events API wrapper
245
+ if (payload.type === "event_callback") {
246
+ const e = payload.event;
247
+ if (!e) return null;
248
+
249
+ // Ignore bot messages
250
+ if (e.bot_id || e.subtype === "bot_message") return null;
251
+ // Ignore message edits and deletes
252
+ if (e.subtype === "message_changed" || e.subtype === "message_deleted")
253
+ return null;
254
+
255
+ // Handle DMs and explicit mentions. Ordinary channel replies are only
256
+ // accepted while this exact workspace-qualified thread has queued or
257
+ // executing work; broad message subscriptions must never invoke the
258
+ // agent for general channel chatter.
259
+ const text = e.text?.trim();
260
+ if (!text) return null;
261
+
262
+ const teamId =
263
+ typeof payload.team_id === "string" ? payload.team_id : "unknown";
264
+ const apiAppId =
265
+ typeof payload.api_app_id === "string"
266
+ ? payload.api_app_id
267
+ : "unknown";
268
+ const agentContext = normalizeSlackAgentContext(e.app_context, teamId);
269
+ const isDm =
270
+ typeof e.channel_type === "string"
271
+ ? e.channel_type === "im"
272
+ : typeof e.channel === "string" && e.channel.startsWith("D");
273
+ const isMention = e.type === "app_mention";
274
+ const isThreadReply = !isDm && !isMention && !!e.thread_ts;
275
+ if (!isDm && !isMention && !isThreadReply) return null;
276
+
277
+ // Remove bot mention from text (e.g., "<@U123> do something" → "do something")
278
+ const cleanText = text.replace(/<@[A-Z0-9]+>/g, "").trim();
279
+ if (!cleanText) return null;
280
+
281
+ // Thread ID: use thread_ts if in a thread, otherwise message ts
282
+ const threadTs = e.thread_ts || e.ts;
283
+ const externalThreadId = `${apiAppId}:${teamId}:${e.channel}:${threadTs}`;
284
+ const partialIncoming: IncomingMessage = {
285
+ platform: "slack",
286
+ externalThreadId,
287
+ text: cleanText,
288
+ senderName: e.user,
289
+ senderId: e.user,
290
+ triggerKind: isDm ? "dm" : isMention ? "mention" : "thread_reply",
291
+ conversationType: isDm ? "dm" : "unknown",
292
+ tenantId: teamId,
293
+ // The signed Slack envelope authenticates the workspace, not the
294
+ // sender's membership tier. `users.info` hydration below is the
295
+ // authority that may promote this to a verified member.
296
+ actorTrust: { memberType: "unknown", verified: false },
297
+ platformContext: {
298
+ channelId: e.channel,
299
+ channelType: e.channel_type,
300
+ threadTs,
301
+ messageTs: e.ts,
302
+ teamId,
303
+ apiAppId,
304
+ enterpriseId:
305
+ typeof payload.enterprise_id === "string"
306
+ ? payload.enterprise_id
307
+ : undefined,
308
+ eventId: payload.event_id,
309
+ ...(agentContext
310
+ ? {
311
+ agentContext: agentContext.entities,
312
+ activeContextChannelId: agentContext.channelId,
313
+ }
314
+ : {}),
315
+ },
316
+ threadRef: threadTs,
317
+ replyRef: e.ts,
318
+ timestamp: Math.floor(parseFloat(e.ts) * 1000),
319
+ };
320
+
321
+ if (isThreadReply) {
322
+ // An ordinary thread reply is narrowly admitted when either work is
323
+ // still queued or the same Slack user is answering a fresh
324
+ // integration-originated clarification. Consuming the latter is a
325
+ // conditional SQL delete, so concurrent replies cannot both reopen
326
+ // the agent and unrelated channel messages remain ignored.
327
+ const answeredClarification = options.consumeAwaitingInput
328
+ ? await options.consumeAwaitingInput(partialIncoming)
329
+ : options.isThreadActive
330
+ ? false
331
+ : await consumeIntegrationAwaitingInput({
332
+ platform: "slack",
333
+ externalThreadId,
334
+ requesterId: e.user,
335
+ });
336
+ const active = options.isThreadActive
337
+ ? await options.isThreadActive(partialIncoming)
338
+ : await hasActivePendingTask("slack", externalThreadId);
339
+ if (!active && !answeredClarification) return null;
340
+ }
341
+
342
+ const token = await resolveBotToken(partialIncoming);
343
+ const threadPermalink = await resolveSlackThreadPermalink(
344
+ e.channel,
345
+ threadTs,
346
+ token,
347
+ );
348
+
349
+ return {
350
+ ...partialIncoming,
351
+ platformContext: {
352
+ ...partialIncoming.platformContext,
353
+ ...(threadPermalink ? { threadPermalink } : {}),
354
+ },
355
+ ...(threadPermalink ? { sourceUrl: threadPermalink } : {}),
356
+ };
357
+ }
358
+
359
+ return null;
360
+ },
361
+
362
+ getLegacyExternalThreadIds(incoming: IncomingMessage): string[] {
363
+ const channelId = incoming.platformContext.channelId;
364
+ const threadTs = incoming.platformContext.threadTs;
365
+ return typeof channelId === "string" && typeof threadTs === "string"
366
+ ? [`${channelId}:${threadTs}`]
367
+ : [];
368
+ },
369
+
370
+ async postProcessingPlaceholder(
371
+ incoming: IncomingMessage,
372
+ ): Promise<{ placeholderRef: string } | null> {
373
+ // No placeholder reply in the thread — Slack's native assistant status
374
+ // bar and the task stream are the loading affordance. Keep the status
375
+ // specific about intent instead of presenting the generic thinking
376
+ // state while the native plan is opening.
377
+ const token = await resolveBotToken(incoming);
378
+ if (!token) return null;
379
+
380
+ const channelId = incoming.platformContext.channelId as string;
381
+ const threadTs = incoming.platformContext.threadTs as string;
382
+ if (!channelId || !threadTs) return null;
383
+
384
+ // Best-effort: flip the native Agent status bar in the
385
+ // channel input area. Slack accepts chat:write for this method. The
386
+ // canonical manifest separately requests assistant:write for Agent View
387
+ // and app_context_changed events.
388
+ setSlackAssistantStatus(
389
+ token,
390
+ channelId,
391
+ threadTs,
392
+ "I’m looking into this now…",
393
+ );
394
+ return null;
395
+ },
396
+
397
+ async hydrateIncomingMessage(
398
+ incoming: IncomingMessage,
399
+ ): Promise<IncomingMessage> {
400
+ const token = await resolveBotToken(incoming);
401
+ if (!token) return incoming;
402
+ return hydrateSlackContext(token, incoming);
403
+ },
404
+
405
+ async hydrateIncomingIdentity(
406
+ incoming: IncomingMessage,
407
+ ): Promise<IncomingMessage> {
408
+ const token = await resolveBotToken(incoming);
409
+ if (!token) return incoming;
410
+ return hydrateSlackIdentity(token, incoming);
411
+ },
412
+
413
+ async startRunProgress(
414
+ incoming: IncomingMessage,
415
+ ): Promise<PlatformRunProgress | null> {
416
+ const token = await resolveBotToken(incoming);
417
+ if (!token) return null;
418
+ return startSlackRunProgress(token, incoming);
419
+ },
420
+
421
+ async resumeRunProgress(
422
+ incoming: IncomingMessage,
423
+ ref: PlatformRunProgressRef,
424
+ ): Promise<PlatformRunProgress | null> {
425
+ if (!isSlackStreamProgressRef(ref)) return null;
426
+ const token = await resolveBotToken(incoming);
427
+ if (!token) return null;
428
+ return resumeSlackRunProgress(token, incoming, ref.streamTs);
429
+ },
430
+
431
+ async sendResponse(
432
+ message: OutgoingMessage,
433
+ context: IncomingMessage,
434
+ opts?: { placeholderRef?: string },
435
+ ): Promise<void | PlatformDeliveryReceipt> {
436
+ const token = await resolveBotToken(context);
437
+ if (!token) {
438
+ throw new Error(
439
+ "[slack] Cannot deliver response: no Slack bot token is configured",
440
+ );
441
+ }
442
+
443
+ const channelId = context.platformContext.channelId as string;
444
+ const threadTs = context.platformContext.threadTs as string;
445
+ const blocks = (message.platformContext as any)?.blocks as
446
+ | unknown[]
447
+ | undefined;
448
+ const placeholderRef = opts?.placeholderRef;
449
+
450
+ // Block-rich path: split text into chunks but render the FIRST chunk as
451
+ // blocks (so we keep the in-place edit + button) and any overflow as
452
+ // plain follow-up posts. The vast majority of replies fit in one block.
453
+ const chunks = splitNonEmptyMessage(message.text, SLACK_MAX_LENGTH);
454
+ const hasProvidedBlocks = Array.isArray(blocks) && blocks.length > 0;
455
+ const firstChunk = chunks[0] ?? (hasProvidedBlocks ? "Response" : "");
456
+ if (!firstChunk) {
457
+ if (threadTs) {
458
+ setSlackAssistantStatus(token, channelId, threadTs, "");
459
+ }
460
+ return;
461
+ }
462
+ const restChunks = chunks.slice(1);
463
+ const messageRefs: string[] = [];
464
+
465
+ const finalBlocks =
466
+ blocks ??
467
+ buildResponseBlocks(firstChunk, {
468
+ threadDeepLinkUrl: (message.platformContext as any)
469
+ ?.threadDeepLinkUrl,
470
+ });
471
+
472
+ const baseBody: Record<string, unknown> = {
473
+ channel: channelId,
474
+ text: firstChunk,
475
+ blocks: finalBlocks,
476
+ unfurl_links: false,
477
+ unfurl_media: false,
478
+ mrkdwn: true,
479
+ };
480
+
481
+ try {
482
+ if (placeholderRef) {
483
+ // Replace the "thinking…" placeholder in place.
484
+ const res = await slackApiFetch("https://slack.com/api/chat.update", {
485
+ method: "POST",
486
+ headers: {
487
+ Authorization: `Bearer ${token}`,
488
+ "Content-Type": "application/json",
489
+ },
490
+ body: JSON.stringify({ ...baseBody, ts: placeholderRef }),
491
+ });
492
+ const data = (await res.json()) as {
493
+ ok: boolean;
494
+ error?: string;
495
+ ts?: string;
496
+ };
497
+ if (!data.ok) {
498
+ console.error("[slack] chat.update error:", data.error);
499
+ // Fall back to a fresh post so the user still sees a reply
500
+ const postedTs = await postFresh(
501
+ token,
502
+ channelId,
503
+ threadTs,
504
+ baseBody,
505
+ );
506
+ if (postedTs) messageRefs.push(postedTs);
507
+ } else {
508
+ messageRefs.push(data.ts || placeholderRef);
509
+ }
510
+ } else {
511
+ const postedTs = await postFresh(
512
+ token,
513
+ channelId,
514
+ threadTs,
515
+ baseBody,
516
+ );
517
+ if (postedTs) messageRefs.push(postedTs);
518
+ }
519
+
520
+ // Clear the AI-assistant "is thinking…" status now that we've
521
+ // delivered the final answer. Empty status clears it.
522
+ if (threadTs) {
523
+ setSlackAssistantStatus(token, channelId, threadTs, "");
524
+ }
525
+
526
+ // Overflow chunks (rare) — post as plain follow-ups in the same thread
527
+ for (const chunk of restChunks) {
528
+ const postedTs = await postFresh(token, channelId, threadTs, {
529
+ channel: channelId,
530
+ text: chunk,
531
+ unfurl_links: false,
532
+ unfurl_media: false,
533
+ mrkdwn: true,
534
+ });
535
+ if (postedTs) messageRefs.push(postedTs);
536
+ }
537
+ return {
538
+ status: "delivered",
539
+ ...(messageRefs.length > 0 ? { messageRefs } : {}),
540
+ };
541
+ } catch (err) {
542
+ console.error("[slack] Failed to send message:", err);
543
+ throw err;
544
+ }
545
+ },
546
+
547
+ async sendSystemNotice(
548
+ incoming: IncomingMessage,
549
+ text: string,
550
+ opts?: { dedupeKey?: string; dedupeTtlMs?: number },
551
+ ): Promise<void> {
552
+ if (!text.trim()) return;
553
+ const dedupeKey = opts?.dedupeKey;
554
+ if (
555
+ dedupeKey &&
556
+ !claimSlackSystemNoticeSlot(dedupeKey, opts?.dedupeTtlMs)
557
+ ) {
558
+ return;
559
+ }
560
+ try {
561
+ const token = await resolveBotToken(incoming);
562
+ if (!token) {
563
+ if (dedupeKey) slackSystemNoticeCache.delete(dedupeKey);
564
+ throw new Error("Slack bot token not configured for system notice");
565
+ }
566
+ const channelId = incoming.platformContext.channelId;
567
+ if (typeof channelId !== "string" || !channelId) {
568
+ if (dedupeKey) slackSystemNoticeCache.delete(dedupeKey);
569
+ throw new Error("Slack channel id missing for system notice");
570
+ }
571
+ const threadTs =
572
+ typeof incoming.platformContext.threadTs === "string"
573
+ ? incoming.platformContext.threadTs
574
+ : undefined;
575
+ await postFresh(token, channelId, threadTs, {
576
+ text,
577
+ unfurl_links: false,
578
+ unfurl_media: false,
579
+ mrkdwn: true,
580
+ });
581
+ } catch (error) {
582
+ // A failed delivery did not inform the sender, so release the slot and
583
+ // allow the next message to retry instead of suppressing notices for a day.
584
+ if (dedupeKey) slackSystemNoticeCache.delete(dedupeKey);
585
+ throw error;
586
+ }
587
+ },
588
+
589
+ async sendMessageToTarget(
590
+ message: OutgoingMessage,
591
+ target: OutboundTarget,
592
+ ): Promise<void> {
593
+ const targetContext: IncomingMessage = {
594
+ platform: "slack",
595
+ externalThreadId: `${target.tenantId ?? "unknown"}:${target.destination}:${target.threadRef ?? "root"}`,
596
+ text: "",
597
+ platformContext: {
598
+ channelId: target.destination,
599
+ threadTs: target.threadRef,
600
+ teamId: target.tenantId,
601
+ },
602
+ tenantId: target.tenantId,
603
+ timestamp: Date.now(),
604
+ };
605
+ const token = await resolveBotToken(targetContext);
606
+ if (!token) {
607
+ console.error("[slack] SLACK_BOT_TOKEN not configured");
608
+ return;
609
+ }
610
+
611
+ const chunks = splitNonEmptyMessage(message.text, SLACK_MAX_LENGTH);
612
+ if (chunks.length === 0) return;
613
+ for (const chunk of chunks) {
614
+ const body: Record<string, unknown> = {
615
+ channel: target.destination,
616
+ text: chunk,
617
+ };
618
+ if (target.threadRef) body.thread_ts = target.threadRef;
619
+
620
+ try {
621
+ const res = await slackApiFetch(
622
+ "https://slack.com/api/chat.postMessage",
623
+ {
624
+ method: "POST",
625
+ headers: {
626
+ Authorization: `Bearer ${token}`,
627
+ "Content-Type": "application/json",
628
+ },
629
+ body: JSON.stringify(body),
630
+ },
631
+ );
632
+ const data = (await res.json()) as { ok: boolean; error?: string };
633
+ if (!data.ok) {
634
+ throw new Error(data.error || "chat.postMessage failed");
635
+ }
636
+ } catch (err) {
637
+ console.error("[slack] Failed to send proactive message:", err);
638
+ throw err;
639
+ }
640
+ }
641
+ },
642
+
643
+ formatAgentResponse(
644
+ text: string,
645
+ opts?: { threadDeepLinkUrl?: string },
646
+ ): OutgoingMessage {
647
+ return {
648
+ text: markdownToSlackMrkdwn(text),
649
+ platformContext: opts?.threadDeepLinkUrl
650
+ ? { threadDeepLinkUrl: opts.threadDeepLinkUrl }
651
+ : {},
652
+ };
653
+ },
654
+
655
+ async getStatus(_baseUrl?: string): Promise<IntegrationStatus> {
656
+ const hasToken = !!(await resolveSecret("SLACK_BOT_TOKEN"));
657
+ const hasSecret = !!(await resolveSecret("SLACK_SIGNING_SECRET"));
658
+ const ctx = getRequestContext();
659
+ const managedInstallations = ctx?.userEmail
660
+ ? await listIntegrationInstallations(
661
+ {
662
+ userEmail: ctx.userEmail,
663
+ orgId: ctx.orgId ?? null,
664
+ },
665
+ "slack",
666
+ ).catch(() => [])
667
+ : [];
668
+ const connectedInstallations = managedInstallations.filter(
669
+ (installation) => installation.status === "connected",
670
+ );
671
+ const configured =
672
+ hasSecret && (hasToken || connectedInstallations.length > 0);
673
+
674
+ return {
675
+ platform: "slack",
676
+ label: "Slack",
677
+ enabled: false, // overridden by plugin
678
+ configured,
679
+ details: {
680
+ hasToken,
681
+ hasSecret,
682
+ managedInstallationCount: connectedInstallations.length,
683
+ managedInstallations: connectedInstallations.map((installation) => ({
684
+ id: installation.id,
685
+ teamId: installation.teamId,
686
+ teamName: installation.teamName,
687
+ enterpriseId: installation.enterpriseId,
688
+ health: installation.health,
689
+ scopes: installation.scopes,
690
+ })),
691
+ },
692
+ error: !configured
693
+ ? "Connect a Slack workspace with OAuth or save a bot token and signing secret"
694
+ : undefined,
695
+ };
696
+ },
697
+ };
698
+ }
699
+
700
+ /**
701
+ * Parse a comma-separated env var into a Set of trimmed, non-empty values.
702
+ * Returns null when the env var is unset or empty (so callers can
703
+ * distinguish "no allowlist configured" from "empty allowlist").
704
+ */
705
+ function parseAllowlistEnv(name: string): Set<string> | null {
706
+ const raw = process.env[name];
707
+ if (!raw) return null;
708
+ const values = raw
709
+ .split(",")
710
+ .map((v) => v.trim())
711
+ .filter((v) => v.length > 0);
712
+ if (values.length === 0) return null;
713
+ return new Set(values);
714
+ }
715
+
716
+ async function resolveManagedSlackBotToken(
717
+ incoming: IncomingMessage,
718
+ ): Promise<string | undefined> {
719
+ const teamId =
720
+ typeof incoming.platformContext.teamId === "string"
721
+ ? incoming.platformContext.teamId
722
+ : incoming.tenantId;
723
+ const apiAppId =
724
+ typeof incoming.platformContext.apiAppId === "string"
725
+ ? incoming.platformContext.apiAppId
726
+ : undefined;
727
+ const enterpriseId =
728
+ typeof incoming.platformContext.enterpriseId === "string"
729
+ ? incoming.platformContext.enterpriseId
730
+ : undefined;
731
+ if (!teamId && !enterpriseId) return undefined;
732
+ try {
733
+ let installation = apiAppId
734
+ ? await getActiveIntegrationInstallationByKey(
735
+ "slack",
736
+ slackInstallationKey({ teamId, enterpriseId, apiAppId }),
737
+ )
738
+ : null;
739
+ if (!installation && teamId) {
740
+ installation = await getActiveIntegrationInstallationForTenant(
741
+ "slack",
742
+ teamId,
743
+ );
744
+ }
745
+ if (!installation && enterpriseId) {
746
+ installation = await getActiveIntegrationInstallationForTenant(
747
+ "slack",
748
+ enterpriseId,
749
+ );
750
+ }
751
+ const key =
752
+ installation?.installationKey ??
753
+ slackInstallationKey({ teamId, enterpriseId, apiAppId });
754
+ return (await resolveIntegrationTokenBundle("slack", key))?.accessToken;
755
+ } catch {
756
+ return undefined;
757
+ }
758
+ }
759
+
760
+ let _missingAllowlistWarned = false;
761
+
762
+ /**
763
+ * Enforce that an incoming Slack event comes from an allowlisted workspace.
764
+ *
765
+ * H1 in the webhook audit: the framework uses a SINGLE global
766
+ * SLACK_SIGNING_SECRET for every workspace the Slack app is installed to,
767
+ * so a valid signature alone doesn't prove the request belongs to the
768
+ * tenant the deployment intends to serve. This helper layers a per-tenant
769
+ * allowlist on top of signature verification.
770
+ *
771
+ * Behavior:
772
+ * - If `SLACK_ALLOWED_TEAM_IDS` is set: reject any payload whose
773
+ * `team_id` isn't in the list.
774
+ * - If `SLACK_ALLOWED_API_APP_IDS` is set: also reject payloads whose
775
+ * `api_app_id` isn't in the list (bot apps can be installed under the
776
+ * same Slack app id across multiple workspaces — pinning both keeps
777
+ * the surface tight when team_id allows multiple workspaces).
778
+ * - If `SLACK_ALLOWED_TEAM_IDS` is unset/empty in production: reject the
779
+ * event. Production must fail closed so any workspace with the shared
780
+ * signing secret cannot drive the agent.
781
+ * - If `SLACK_ALLOWED_TEAM_IDS` is unset/empty in dev / single-tenant: log a
782
+ * one-time warning and accept (current local setup behavior).
783
+ *
784
+ * Throws an h3 401 error when an allowlisted-but-mismatched payload is
785
+ * received, which the integrations plugin surfaces to the caller as
786
+ * "Unrecognized Slack workspace" without enqueuing the event.
787
+ */
788
+ async function enforceWorkspaceAllowlist(payload: any): Promise<void> {
789
+ const teamId =
790
+ typeof payload?.team_id === "string" ? payload.team_id : undefined;
791
+ const apiAppId =
792
+ typeof payload?.api_app_id === "string" ? payload.api_app_id : undefined;
793
+
794
+ const allowedTeamIds = parseAllowlistEnv("SLACK_ALLOWED_TEAM_IDS");
795
+ const allowedAppIds = parseAllowlistEnv("SLACK_ALLOWED_API_APP_IDS");
796
+
797
+ if (!allowedTeamIds) {
798
+ if (process.env.NODE_ENV === "production") {
799
+ let managed = false;
800
+ try {
801
+ const key = slackInstallationKey({ teamId, apiAppId });
802
+ managed = !!(await getActiveIntegrationInstallationByKey("slack", key));
803
+ } catch {}
804
+ if (!managed) {
805
+ throw createError({
806
+ statusCode: 401,
807
+ statusMessage: "Slack workspace is not connected",
808
+ });
809
+ }
810
+ }
811
+ if (!_missingAllowlistWarned) {
812
+ _missingAllowlistWarned = true;
813
+ console.warn(
814
+ "[slack] SLACK_ALLOWED_TEAM_IDS not set — accepting events from any workspace whose signature matches SLACK_SIGNING_SECRET. " +
815
+ "Set SLACK_ALLOWED_TEAM_IDS to a comma-separated list of allowed team_id values before deploying to production.",
816
+ );
817
+ }
818
+ }
819
+
820
+ if (allowedTeamIds) {
821
+ if (!teamId || !allowedTeamIds.has(teamId)) {
822
+ throw createError({
823
+ statusCode: 401,
824
+ statusMessage: "Unrecognized Slack workspace",
825
+ });
826
+ }
827
+ }
828
+
829
+ if (allowedAppIds) {
830
+ if (!apiAppId || !allowedAppIds.has(apiAppId)) {
831
+ throw createError({
832
+ statusCode: 401,
833
+ statusMessage: "Unrecognized Slack workspace",
834
+ });
835
+ }
836
+ }
837
+ }
838
+
839
+ /**
840
+ * Read the raw request body as a string and cache on the event context.
841
+ *
842
+ * This MUST read raw bytes from the request stream — never `JSON.stringify`
843
+ * a parsed body, because Slack's HMAC is computed over the exact bytes Slack
844
+ * sent. Re-stringifying a parsed object loses key ordering, whitespace, and
845
+ * Unicode-escape choices, so the signature check would silently fail for
846
+ * legitimate requests (M2 in the webhook security audit).
847
+ *
848
+ * h3 v2's body stream is consume-once, so we cache the raw string on the
849
+ * event context after the first read. All call sites (handleVerification,
850
+ * verifyWebhook, parseIncomingMessage) MUST go through this helper.
851
+ */
852
+ async function readRawBodyCached(event: H3Event): Promise<string> {
853
+ const cached = event.context.__rawBody;
854
+ if (typeof cached === "string") return cached;
855
+ // h3's readRawBody returns the bytes Slack actually sent, defaulting to
856
+ // utf8-decoded. Returns undefined for empty bodies — we coerce to "" so
857
+ // the HMAC check can proceed deterministically.
858
+ const raw = (await readRawBody(event)) ?? "";
859
+ event.context.__rawBody = raw;
860
+ return raw;
861
+ }
862
+
863
+ function utf8ByteLength(text: string): number {
864
+ return new TextEncoder().encode(text).length;
865
+ }
866
+
867
+ function prefixWithinUtf8ByteLimit(text: string, maxLength: number): string {
868
+ let bytes = 0;
869
+ let end = 0;
870
+ for (const char of text) {
871
+ const nextBytes = utf8ByteLength(char);
872
+ if (bytes + nextBytes > maxLength) break;
873
+ bytes += nextBytes;
874
+ end += char.length;
875
+ }
876
+ return text.slice(0, end || 1);
877
+ }
878
+
879
+ /** Split a message into chunks that fit within the platform's byte limit. */
880
+ function splitMessage(text: string, maxLength: number): string[] {
881
+ if (utf8ByteLength(text) <= maxLength) return [text];
882
+ const chunks: string[] = [];
883
+ let remaining = text;
884
+ while (remaining.length > 0) {
885
+ if (utf8ByteLength(remaining) <= maxLength) {
886
+ chunks.push(remaining);
887
+ break;
888
+ }
889
+
890
+ const prefix = prefixWithinUtf8ByteLimit(remaining, maxLength);
891
+
892
+ // Try to split at a newline
893
+ let splitIdx = prefix.lastIndexOf("\n");
894
+ if (splitIdx <= 0) {
895
+ // Try to split at a space
896
+ splitIdx = prefix.lastIndexOf(" ");
897
+ }
898
+ if (splitIdx <= 0) {
899
+ splitIdx = prefix.length;
900
+ }
901
+ chunks.push(remaining.slice(0, splitIdx));
902
+ remaining = remaining.slice(splitIdx).trimStart();
903
+ }
904
+ return chunks;
905
+ }
906
+
907
+ /** Split a message and drop chunks Slack would render as blank messages. */
908
+ function splitNonEmptyMessage(text: string, maxLength: number): string[] {
909
+ return splitMessage(text, maxLength).filter(
910
+ (chunk) => chunk.trim().length > 0,
911
+ );
912
+ }
913
+
914
+ /** Hard cap on input length we feed to the regex-based mrkdwn converter.
915
+ * L2 in the webhook audit: `\*\*(.+?)\*\*` with the `s` flag on a long
916
+ * string of asterisks can exhibit super-linear backtracking. Slack
917
+ * itself caps message bodies at 4000 chars (SLACK_MAX_LENGTH); we cap
918
+ * the input here at 10x that as a defensive bound for any caller that
919
+ * passes a longer rendering source through this helper before chunking. */
920
+ const MRKDWN_MAX_LENGTH = 40_000;
921
+
922
+ /**
923
+ * Convert standard markdown to Slack's mrkdwn dialect.
924
+ * - `[text](url)` → `<url|text>`
925
+ * - `**bold**` → `*bold*` (Slack uses single asterisks for bold)
926
+ *
927
+ * Inputs longer than MRKDWN_MAX_LENGTH are truncated before the regex
928
+ * pass to bound worst-case backtracking on pathological input (L2 in the
929
+ * webhook audit).
930
+ */
931
+ function markdownToSlackMrkdwn(text: string): string {
932
+ const bounded =
933
+ text.length > MRKDWN_MAX_LENGTH ? text.slice(0, MRKDWN_MAX_LENGTH) : text;
934
+ return (
935
+ bounded
936
+ .replace(/\[([^\]]+)\]\(([^)]+)\)/g, "<$2|$1>")
937
+ // Do not wrap bare URLs in Slack bold markers. Slack's autolinker can
938
+ // treat the trailing `*` as part of the URL, producing a broken link.
939
+ .replace(/\*\*<?(https?:\/\/[^\s>*]+)>?\*\*/g, "<$1>")
940
+ // Bounded character class instead of `.+?` with the `s` flag — caps
941
+ // each bold span at 5000 chars so an attacker can't construct a
942
+ // pathological "**" sequence that exhibits super-linear backtracking.
943
+ // Newlines are allowed because `[^*]` excludes only the asterisk
944
+ // itself, so multi-line bold spans still match.
945
+ .replace(/\*\*([^*]{1,5000})\*\*/g, "*$1*")
946
+ );
947
+ }
948
+
949
+ /**
950
+ * Optionally set Slack's native Agent status indicator (the small "is
951
+ * thinking…" line under the message composer). The method uses chat:write;
952
+ * Agent View itself is configured separately by the Slack app manifest.
953
+ * Pure best-effort — failures never block the response.
954
+ */
955
+ function setSlackAssistantStatus(
956
+ token: string,
957
+ channelId: string,
958
+ threadTs: string,
959
+ status: string,
960
+ ): void {
961
+ slackApiFetch("https://slack.com/api/assistant.threads.setStatus", {
962
+ method: "POST",
963
+ headers: {
964
+ Authorization: `Bearer ${token}`,
965
+ "Content-Type": "application/json",
966
+ },
967
+ body: JSON.stringify({
968
+ channel_id: channelId,
969
+ thread_ts: threadTs,
970
+ status,
971
+ }),
972
+ }).catch(() => {});
973
+ }
974
+
975
+ /**
976
+ * Block Kit payload for the final answer. We avoid auto-unfurl previews by
977
+ * separating the deep-link out into a button instead of inlining it as a
978
+ * `<url|text>` markdown link in the section body — that's what was producing
979
+ * the giant "Agent-Native Dispatch" card in every thread reply.
980
+ */
981
+ function buildResponseBlocks(
982
+ text: string,
983
+ opts: { threadDeepLinkUrl?: string },
984
+ ): unknown[] {
985
+ const sectionChunks = splitMessage(
986
+ text || "_(no response)_",
987
+ SLACK_SECTION_TEXT_MAX_LENGTH,
988
+ );
989
+ const blocks: any[] = sectionChunks.map((chunk) => ({
990
+ type: "section",
991
+ text: { type: "mrkdwn", text: chunk },
992
+ }));
993
+ if (opts.threadDeepLinkUrl) {
994
+ blocks.push({
995
+ type: "actions",
996
+ elements: [
997
+ {
998
+ type: "button",
999
+ text: { type: "plain_text", text: "Open thread", emoji: true },
1000
+ url: opts.threadDeepLinkUrl,
1001
+ action_id: "open_dispatch_thread",
1002
+ },
1003
+ ],
1004
+ });
1005
+ }
1006
+ return blocks;
1007
+ }
1008
+
1009
+ /**
1010
+ * Post a fresh message to a thread. Used as the placeholder-fallback path
1011
+ * (e.g. when chat.update fails) and for follow-up overflow chunks.
1012
+ */
1013
+ async function postFresh(
1014
+ token: string,
1015
+ channelId: string,
1016
+ threadTs: string | undefined,
1017
+ body: Record<string, unknown>,
1018
+ ): Promise<string | undefined> {
1019
+ const hasBlocks =
1020
+ Array.isArray(body.blocks) && (body.blocks as unknown[]).length > 0;
1021
+ if (
1022
+ typeof body.text === "string" &&
1023
+ body.text.trim().length === 0 &&
1024
+ !hasBlocks
1025
+ ) {
1026
+ return undefined;
1027
+ }
1028
+
1029
+ const payload: Record<string, unknown> = {
1030
+ ...body,
1031
+ channel: channelId,
1032
+ };
1033
+ if (threadTs && !payload.thread_ts) payload.thread_ts = threadTs;
1034
+ const res = await slackApiFetch("https://slack.com/api/chat.postMessage", {
1035
+ method: "POST",
1036
+ headers: {
1037
+ Authorization: `Bearer ${token}`,
1038
+ "Content-Type": "application/json",
1039
+ },
1040
+ body: JSON.stringify(payload),
1041
+ });
1042
+ const data = (await res.json()) as {
1043
+ ok: boolean;
1044
+ error?: string;
1045
+ ts?: string;
1046
+ };
1047
+ if (!data.ok) {
1048
+ console.error("[slack] chat.postMessage error:", data.error);
1049
+ throw new Error(data.error || "chat.postMessage failed");
1050
+ }
1051
+ return data.ts;
1052
+ }
1053
+
1054
+ async function slackApiFetch(
1055
+ url: string,
1056
+ init: RequestInit,
1057
+ timeoutMs = SLACK_API_TIMEOUT_MS,
1058
+ ): Promise<Response> {
1059
+ const controller =
1060
+ typeof AbortController !== "undefined" ? new AbortController() : undefined;
1061
+ const timer = controller
1062
+ ? setTimeout(() => controller.abort(), timeoutMs)
1063
+ : undefined;
1064
+ try {
1065
+ return await fetch(url, {
1066
+ ...init,
1067
+ signal: controller?.signal ?? init.signal,
1068
+ });
1069
+ } finally {
1070
+ if (timer) clearTimeout(timer);
1071
+ }
1072
+ }
1073
+
1074
+ async function resolveSlackThreadPermalink(
1075
+ channelId: unknown,
1076
+ threadTs: unknown,
1077
+ resolvedToken?: string,
1078
+ ): Promise<string | undefined> {
1079
+ if (typeof channelId !== "string" || typeof threadTs !== "string") {
1080
+ return undefined;
1081
+ }
1082
+ const token = resolvedToken ?? (await resolveSecret("SLACK_BOT_TOKEN"));
1083
+ if (!token) return undefined;
1084
+
1085
+ try {
1086
+ const url = new URL("https://slack.com/api/chat.getPermalink");
1087
+ url.searchParams.set("channel", channelId);
1088
+ url.searchParams.set("message_ts", threadTs);
1089
+ const res = await slackApiFetch(
1090
+ url.toString(),
1091
+ { headers: { Authorization: `Bearer ${token}` } },
1092
+ SLACK_PERMALINK_TIMEOUT_MS,
1093
+ );
1094
+ const data = (await res.json()) as {
1095
+ ok?: boolean;
1096
+ permalink?: unknown;
1097
+ };
1098
+ if (!data.ok || typeof data.permalink !== "string") return undefined;
1099
+
1100
+ const permalink = new URL(data.permalink);
1101
+ const isSlackHost =
1102
+ permalink.hostname === "slack.com" ||
1103
+ permalink.hostname.endsWith(".slack.com");
1104
+ if (permalink.protocol !== "https:" || !isSlackHost) return undefined;
1105
+ return permalink.toString();
1106
+ } catch {
1107
+ return undefined;
1108
+ }
1109
+ }
1110
+
1111
+ function boundedSlackText(value: unknown): string {
1112
+ return typeof value === "string"
1113
+ ? value.slice(0, SLACK_CONTEXT_TEXT_LIMIT)
1114
+ : "";
1115
+ }
1116
+
1117
+ function normalizeSlackAgentContext(
1118
+ value: unknown,
1119
+ eventTeamId: string,
1120
+ ): {
1121
+ entities: Array<{ type: string; value: string; teamId?: string }>;
1122
+ channelId?: string;
1123
+ } | null {
1124
+ if (!value || typeof value !== "object") return null;
1125
+ const rawEntities = (value as { entities?: unknown }).entities;
1126
+ if (!Array.isArray(rawEntities)) return null;
1127
+ const entities = rawEntities.slice(0, 10).flatMap((entity) => {
1128
+ if (!entity || typeof entity !== "object") return [];
1129
+ const record = entity as Record<string, unknown>;
1130
+ if (typeof record.type !== "string" || typeof record.value !== "string") {
1131
+ return [];
1132
+ }
1133
+ const teamId =
1134
+ typeof record.team_id === "string" ? record.team_id : undefined;
1135
+ if (teamId && eventTeamId !== "unknown" && teamId !== eventTeamId) {
1136
+ return [];
1137
+ }
1138
+ return [
1139
+ {
1140
+ type: record.type.slice(0, 100),
1141
+ value: record.value.slice(0, 200),
1142
+ ...(teamId ? { teamId } : {}),
1143
+ },
1144
+ ];
1145
+ });
1146
+ if (!entities.length) return null;
1147
+ const channelId = entities.find(
1148
+ (entity) =>
1149
+ entity.type === "slack#/types/channel_id" &&
1150
+ /^[CDG][A-Z0-9]+$/.test(entity.value),
1151
+ )?.value;
1152
+ return { entities, ...(channelId ? { channelId } : {}) };
1153
+ }
1154
+
1155
+ function slackFileReference(value: unknown): IntegrationFileReference | null {
1156
+ if (!value || typeof value !== "object") return null;
1157
+ const file = value as Record<string, unknown>;
1158
+ if (typeof file.id !== "string") return null;
1159
+ return {
1160
+ id: file.id,
1161
+ ...(typeof file.name === "string" ? { name: file.name } : {}),
1162
+ ...(typeof file.mimetype === "string" ? { mimetype: file.mimetype } : {}),
1163
+ ...(typeof file.size === "number" ? { size: file.size } : {}),
1164
+ ...(typeof file.permalink === "string"
1165
+ ? { permalink: file.permalink }
1166
+ : {}),
1167
+ ...(typeof file.url_private_download === "string"
1168
+ ? { downloadUrl: file.url_private_download }
1169
+ : {}),
1170
+ };
1171
+ }
1172
+
1173
+ async function slackJson(
1174
+ token: string,
1175
+ method: string,
1176
+ params: Record<string, string>,
1177
+ timeoutMs = 2_000,
1178
+ ): Promise<Record<string, any> | null> {
1179
+ try {
1180
+ const url = new URL(`https://slack.com/api/${method}`);
1181
+ for (const [key, value] of Object.entries(params)) {
1182
+ url.searchParams.set(key, value);
1183
+ }
1184
+ const response = await slackApiFetch(
1185
+ url.toString(),
1186
+ { headers: { Authorization: `Bearer ${token}` } },
1187
+ timeoutMs,
1188
+ );
1189
+ const body = (await response.json()) as Record<string, any>;
1190
+ return body.ok ? body : null;
1191
+ } catch {
1192
+ return null;
1193
+ }
1194
+ }
1195
+
1196
+ function slackIdentityCacheKey(incoming: IncomingMessage): string | null {
1197
+ const teamId = incoming.platformContext.teamId;
1198
+ const senderId = incoming.senderId;
1199
+ if (typeof senderId !== "string" || !senderId.trim()) return null;
1200
+ return `${typeof teamId === "string" && teamId ? teamId : "unknown"}:${senderId}`;
1201
+ }
1202
+
1203
+ async function resolveSlackUserIdentity(
1204
+ token: string,
1205
+ incoming: IncomingMessage,
1206
+ ): Promise<SlackUserIdentity | null> {
1207
+ const cacheKey = slackIdentityCacheKey(incoming);
1208
+ if (!cacheKey) return null;
1209
+ const cached = slackIdentityCache.get(cacheKey);
1210
+ if (cached && cached.expiresAt > Date.now()) return cached.identity;
1211
+ if (cached) slackIdentityCache.delete(cacheKey);
1212
+
1213
+ const user = await slackJson(
1214
+ token,
1215
+ "users.info",
1216
+ { user: incoming.senderId! },
1217
+ SLACK_IDENTITY_TIMEOUT_MS,
1218
+ );
1219
+ const profile = user?.user?.profile;
1220
+ const identity: SlackUserIdentity | null = user?.user
1221
+ ? {
1222
+ email:
1223
+ typeof profile?.email === "string" && profile.email.trim()
1224
+ ? profile.email.trim().toLowerCase()
1225
+ : null,
1226
+ name:
1227
+ typeof profile?.real_name === "string" && profile.real_name.trim()
1228
+ ? profile.real_name.trim()
1229
+ : typeof profile?.display_name === "string" &&
1230
+ profile.display_name.trim()
1231
+ ? profile.display_name.trim()
1232
+ : typeof user.user.real_name === "string" &&
1233
+ user.user.real_name.trim()
1234
+ ? user.user.real_name.trim()
1235
+ : typeof user.user.name === "string" && user.user.name.trim()
1236
+ ? user.user.name.trim()
1237
+ : null,
1238
+ // is_stranger marks Slack Connect DM participants from another
1239
+ // workspace; they must map to "external", never "member".
1240
+ memberType:
1241
+ user.user.is_stranger || user.user.is_ultra_restricted
1242
+ ? "external"
1243
+ : user.user.is_restricted
1244
+ ? "guest"
1245
+ : user.user.is_owner
1246
+ ? "owner"
1247
+ : user.user.is_admin
1248
+ ? "admin"
1249
+ : "member",
1250
+ }
1251
+ : null;
1252
+ if (slackIdentityCache.size >= SLACK_IDENTITY_CACHE_MAX_ENTRIES) {
1253
+ const oldestKey = slackIdentityCache.keys().next().value;
1254
+ if (oldestKey) slackIdentityCache.delete(oldestKey);
1255
+ }
1256
+ slackIdentityCache.set(cacheKey, {
1257
+ identity,
1258
+ expiresAt:
1259
+ Date.now() +
1260
+ (identity
1261
+ ? SLACK_IDENTITY_CACHE_TTL_MS
1262
+ : SLACK_IDENTITY_NEGATIVE_CACHE_TTL_MS),
1263
+ });
1264
+ return identity;
1265
+ }
1266
+
1267
+ async function hydrateSlackIdentity(
1268
+ token: string,
1269
+ incoming: IncomingMessage,
1270
+ ): Promise<IncomingMessage> {
1271
+ const identity = await resolveSlackUserIdentity(token, incoming);
1272
+ if (!identity) {
1273
+ // Context hydration can call users.info again after the webhook identity
1274
+ // pass. A transient failure on that second lookup is not evidence that a
1275
+ // previously verified sender became unverified; preserve the stronger
1276
+ // identity instead of replacing it with a negative-cache result.
1277
+ if (
1278
+ incoming.senderVerified === true &&
1279
+ incoming.senderEmail?.trim() &&
1280
+ incoming.actorTrust?.verified === true
1281
+ ) {
1282
+ return incoming;
1283
+ }
1284
+ return {
1285
+ ...incoming,
1286
+ senderVerified: false,
1287
+ actorTrust: { memberType: "unknown", verified: false },
1288
+ };
1289
+ }
1290
+ return {
1291
+ ...incoming,
1292
+ ...(identity.name ? { senderName: identity.name } : {}),
1293
+ ...(identity.email
1294
+ ? { senderEmail: identity.email, senderVerified: true }
1295
+ : { senderVerified: false }),
1296
+ actorTrust: {
1297
+ memberType: identity.memberType,
1298
+ verified: true,
1299
+ },
1300
+ };
1301
+ }
1302
+
1303
+ async function hydrateSlackContext(
1304
+ token: string,
1305
+ incoming: IncomingMessage,
1306
+ ): Promise<IncomingMessage> {
1307
+ const channelId = incoming.platformContext.channelId;
1308
+ const threadTs = incoming.platformContext.threadTs;
1309
+ const senderId = incoming.senderId;
1310
+ if (typeof channelId !== "string" || typeof threadTs !== "string") {
1311
+ return incoming;
1312
+ }
1313
+
1314
+ const [thread, history, pins, conversation, identity] = await Promise.all([
1315
+ slackJson(token, "conversations.replies", {
1316
+ channel: channelId,
1317
+ ts: threadTs,
1318
+ limit: String(SLACK_CONTEXT_MESSAGE_LIMIT),
1319
+ }),
1320
+ slackJson(token, "conversations.history", {
1321
+ channel: channelId,
1322
+ latest: String(incoming.platformContext.messageTs ?? threadTs),
1323
+ inclusive: "true",
1324
+ limit: String(SLACK_CONTEXT_MESSAGE_LIMIT),
1325
+ }),
1326
+ slackJson(token, "pins.list", { channel: channelId }),
1327
+ slackJson(token, "conversations.info", { channel: channelId }),
1328
+ senderId ? resolveSlackUserIdentity(token, incoming) : null,
1329
+ ]);
1330
+
1331
+ // Agent View can attach the Slack surface the user is currently viewing to
1332
+ // a DM. Treat it only as a context hint: Slack requires us to prove the bot
1333
+ // can access the referenced channel with conversations.info before reading
1334
+ // any history from it.
1335
+ const activeContextChannelId =
1336
+ typeof incoming.platformContext.activeContextChannelId === "string"
1337
+ ? incoming.platformContext.activeContextChannelId
1338
+ : null;
1339
+ const activeContextConversation =
1340
+ activeContextChannelId && activeContextChannelId !== channelId
1341
+ ? await slackJson(token, "conversations.info", {
1342
+ channel: activeContextChannelId,
1343
+ })
1344
+ : null;
1345
+ const activeContextHistory = activeContextConversation
1346
+ ? await slackJson(token, "conversations.history", {
1347
+ channel: activeContextChannelId!,
1348
+ limit: "5",
1349
+ })
1350
+ : null;
1351
+ const activeContextName =
1352
+ typeof activeContextConversation?.channel?.name === "string"
1353
+ ? activeContextConversation.channel.name
1354
+ : null;
1355
+ const activeContextMessages = Array.isArray(activeContextHistory?.messages)
1356
+ ? activeContextHistory.messages.map((message: Record<string, any>) => ({
1357
+ ...message,
1358
+ text: `[Active Slack context${activeContextName ? ` #${activeContextName}` : ""}] ${boundedSlackText(message.text)}`,
1359
+ }))
1360
+ : [];
1361
+
1362
+ const rawMessages = [
1363
+ ...(Array.isArray(history?.messages) ? history.messages : []),
1364
+ ...(Array.isArray(pins?.items)
1365
+ ? pins.items
1366
+ .map((item: Record<string, any>) => item.message)
1367
+ .filter(Boolean)
1368
+ : []),
1369
+ ...(Array.isArray(thread?.messages) ? thread.messages : []),
1370
+ ...activeContextMessages,
1371
+ ];
1372
+ const uniqueMessages = [
1373
+ ...new Map(
1374
+ rawMessages.map((message: Record<string, any>, index) => [
1375
+ typeof message.ts === "string" ? message.ts : `unknown:${index}`,
1376
+ message,
1377
+ ]),
1378
+ ).values(),
1379
+ ].slice(-SLACK_CONTEXT_MESSAGE_LIMIT);
1380
+
1381
+ const messages: IntegrationContextMessage[] = uniqueMessages.length
1382
+ ? uniqueMessages.map((message: Record<string, any>) => {
1383
+ const files = Array.isArray(message.files)
1384
+ ? message.files
1385
+ .map(slackFileReference)
1386
+ .filter(
1387
+ (
1388
+ file: IntegrationFileReference | null,
1389
+ ): file is IntegrationFileReference => file !== null,
1390
+ )
1391
+ : undefined;
1392
+ const reactions = Array.isArray(message.reactions)
1393
+ ? message.reactions
1394
+ .filter(
1395
+ (reaction: any) =>
1396
+ typeof reaction?.name === "string" &&
1397
+ typeof reaction?.count === "number",
1398
+ )
1399
+ .map((reaction: any) => ({
1400
+ name: reaction.name,
1401
+ count: reaction.count,
1402
+ }))
1403
+ : undefined;
1404
+ return {
1405
+ ...(typeof message.user === "string"
1406
+ ? { senderId: message.user }
1407
+ : {}),
1408
+ text: boundedSlackText(message.text),
1409
+ timestamp:
1410
+ typeof message.ts === "string"
1411
+ ? Math.floor(parseFloat(message.ts) * 1000)
1412
+ : incoming.timestamp,
1413
+ ...(reactions?.length ? { reactions } : {}),
1414
+ ...(files?.length ? { files } : {}),
1415
+ };
1416
+ })
1417
+ : [];
1418
+
1419
+ const profile = identity;
1420
+ const isPrivate = conversation?.channel?.is_private === true;
1421
+ const isExternalShared = conversation?.channel?.is_ext_shared === true;
1422
+ const isMpim = conversation?.channel?.is_mpim === true;
1423
+ const isIm = conversation?.channel?.is_im === true;
1424
+ const conversationType = isIm
1425
+ ? "dm"
1426
+ : isMpim
1427
+ ? "group_dm"
1428
+ : isPrivate
1429
+ ? "private_channel"
1430
+ : "channel";
1431
+
1432
+ const attachedFiles = messages.flatMap((message) => message.files ?? []);
1433
+ const detailedFiles = await Promise.all(
1434
+ [...new Set(attachedFiles.map((file) => file.id))]
1435
+ .slice(0, 5)
1436
+ .map(async (fileId) => {
1437
+ const result = await slackJson(token, "files.info", { file: fileId });
1438
+ return slackFileReference(result?.file);
1439
+ }),
1440
+ );
1441
+ const fileById = new Map(
1442
+ detailedFiles
1443
+ .filter((file): file is IntegrationFileReference => file !== null)
1444
+ .map((file) => [file.id, file]),
1445
+ );
1446
+ const hydratedMessages = messages.map((message) => ({
1447
+ ...message,
1448
+ ...(message.files?.length
1449
+ ? {
1450
+ files: message.files.map((file) => ({
1451
+ ...file,
1452
+ ...(fileById.get(file.id) ?? {}),
1453
+ })),
1454
+ }
1455
+ : {}),
1456
+ }));
1457
+ const hydratedFiles = hydratedMessages.flatMap(
1458
+ (message) => message.files ?? [],
1459
+ );
1460
+ return {
1461
+ ...incoming,
1462
+ ...(profile?.name ? { senderName: profile.name } : {}),
1463
+ ...(profile?.email
1464
+ ? { senderEmail: profile.email, senderVerified: true }
1465
+ : { senderVerified: false }),
1466
+ conversationType,
1467
+ // Conversation hydration must not promote a caller when users.info was
1468
+ // unavailable. Preserve the result of the earlier identity-only hydration
1469
+ // unless this request independently resolved the Slack user.
1470
+ actorTrust: identity
1471
+ ? { memberType: identity.memberType, verified: true }
1472
+ : (incoming.actorTrust ?? {
1473
+ memberType: "unknown",
1474
+ verified: false,
1475
+ }),
1476
+ contextMessages: hydratedMessages,
1477
+ ...(hydratedFiles.length ? { files: hydratedFiles.slice(0, 20) } : {}),
1478
+ platformContext: {
1479
+ ...incoming.platformContext,
1480
+ channelName:
1481
+ typeof conversation?.channel?.name === "string"
1482
+ ? conversation.channel.name
1483
+ : undefined,
1484
+ isExternalShared,
1485
+ ...(activeContextChannelId
1486
+ ? {
1487
+ activeContextChannelId,
1488
+ ...(activeContextName
1489
+ ? { activeContextChannelName: activeContextName }
1490
+ : {}),
1491
+ }
1492
+ : {}),
1493
+ },
1494
+ };
1495
+ }
1496
+
1497
+ function shortTaskTitle(value: unknown): string {
1498
+ const text = typeof value === "string" ? value : "Working";
1499
+ return text.replace(/[-_]/g, " ").slice(0, 200);
1500
+ }
1501
+
1502
+ function delegatedTaskTitle(agent: unknown): string {
1503
+ return `Contact ${shortTaskTitle(agent)}`;
1504
+ }
1505
+
1506
+ function formatElapsedSeconds(elapsedSeconds: number): string {
1507
+ const totalSeconds = Math.max(0, Math.round(elapsedSeconds));
1508
+ const minutes = Math.floor(totalSeconds / 60);
1509
+ const seconds = totalSeconds % 60;
1510
+ return minutes > 0 ? `${minutes}m ${seconds}s` : `${seconds}s`;
1511
+ }
1512
+
1513
+ function formatProgressState(state: string): string {
1514
+ if (state === "submitted") return "Queued";
1515
+ if (state === "working") return "Working";
1516
+ return shortTaskTitle(state);
1517
+ }
1518
+
1519
+ function delegatedProgressDetails(
1520
+ agent: unknown,
1521
+ state: string,
1522
+ elapsedSeconds: number,
1523
+ detail?: string,
1524
+ ): string {
1525
+ const elapsed = formatElapsedSeconds(elapsedSeconds);
1526
+ const progress = `${formatProgressState(state)} · ${elapsed}`;
1527
+ const update = detail ? shortTaskTitle(detail) : "";
1528
+
1529
+ if (elapsedSeconds >= SLACK_CALM_PROGRESS_THRESHOLD_SECONDS) {
1530
+ const agentName = shortTaskTitle(agent);
1531
+ const context = update ? ` — ${update}.` : ".";
1532
+ return `${progress}${context} This is taking longer than usual, but ${agentName} is still working. I’ll post the result here.`;
1533
+ }
1534
+
1535
+ return update ? `${progress} — ${update}` : progress;
1536
+ }
1537
+
1538
+ async function postSlackJson(
1539
+ token: string,
1540
+ method: string,
1541
+ body: Record<string, unknown>,
1542
+ ): Promise<Record<string, any>> {
1543
+ const response = await slackApiFetch(`https://slack.com/api/${method}`, {
1544
+ method: "POST",
1545
+ headers: {
1546
+ Authorization: `Bearer ${token}`,
1547
+ "Content-Type": "application/json",
1548
+ },
1549
+ body: JSON.stringify(body),
1550
+ });
1551
+ const data = (await response.json()) as Record<string, any>;
1552
+ if (!data.ok) throw new Error(data.error || `${method} failed`);
1553
+ return data;
1554
+ }
1555
+
1556
+ function streamFailureCode(error: unknown): string {
1557
+ const message = error instanceof Error ? error.message.trim() : "";
1558
+ return /^[a-z0-9_:-]{1,80}$/i.test(message) ? message : "unknown";
1559
+ }
1560
+
1561
+ function streamChunkType(chunk: Record<string, unknown>): string {
1562
+ const type = chunk.type;
1563
+ return type === "task_update" ||
1564
+ type === "plan_update" ||
1565
+ type === "markdown_text" ||
1566
+ type === "blocks"
1567
+ ? type
1568
+ : "unknown";
1569
+ }
1570
+
1571
+ async function startSlackRunProgress(
1572
+ token: string,
1573
+ incoming: IncomingMessage,
1574
+ ): Promise<PlatformRunProgress | null> {
1575
+ const channel = incoming.platformContext.channelId;
1576
+ const threadTs = incoming.platformContext.threadTs;
1577
+ if (typeof channel !== "string" || typeof threadTs !== "string") return null;
1578
+
1579
+ let started: Record<string, any>;
1580
+ try {
1581
+ started = await postSlackJson(token, "chat.startStream", {
1582
+ channel,
1583
+ thread_ts: threadTs,
1584
+ ...(incoming.tenantId ? { recipient_team_id: incoming.tenantId } : {}),
1585
+ ...(incoming.senderId ? { recipient_user_id: incoming.senderId } : {}),
1586
+ task_display_mode: "plan",
1587
+ markdown_text: "I’m looking into this for you.",
1588
+ chunks: [
1589
+ {
1590
+ type: "plan_update",
1591
+ title: "I’m looking into this for you",
1592
+ },
1593
+ {
1594
+ type: "task_update",
1595
+ id: "agent-native:context",
1596
+ title: "Review the request",
1597
+ status: "in_progress",
1598
+ details: "Finding the information needed for an answer",
1599
+ },
1600
+ ],
1601
+ });
1602
+ } catch (error) {
1603
+ console.warn("[slack] chat.startStream failed; using standard reply", {
1604
+ errorCode: streamFailureCode(error),
1605
+ isDirectMessage: incoming.conversationType === "dm",
1606
+ hasRecipientTeam: Boolean(incoming.tenantId),
1607
+ hasRecipientUser: Boolean(incoming.senderId),
1608
+ });
1609
+ return null;
1610
+ }
1611
+
1612
+ const streamTs = started.ts;
1613
+ if (typeof streamTs !== "string") return null;
1614
+ return createSlackRunProgress(token, incoming, channel, threadTs, streamTs);
1615
+ }
1616
+
1617
+ function isSlackStreamProgressRef(ref: PlatformRunProgressRef): boolean {
1618
+ return (
1619
+ ref.kind === "slack-stream" && /^\d{1,20}\.\d{1,9}$/.test(ref.streamTs)
1620
+ );
1621
+ }
1622
+
1623
+ async function resumeSlackRunProgress(
1624
+ token: string,
1625
+ incoming: IncomingMessage,
1626
+ streamTs: string,
1627
+ ): Promise<PlatformRunProgress | null> {
1628
+ const channel = incoming.platformContext.channelId;
1629
+ const threadTs = incoming.platformContext.threadTs;
1630
+ if (typeof channel !== "string" || typeof threadTs !== "string") return null;
1631
+ return createSlackRunProgress(token, incoming, channel, threadTs, streamTs);
1632
+ }
1633
+
1634
+ function createSlackRunProgress(
1635
+ token: string,
1636
+ incoming: IncomingMessage,
1637
+ channel: string,
1638
+ threadTs: string,
1639
+ streamTs: string,
1640
+ ): PlatformRunProgress {
1641
+ const tasks = new Map<string, { title: string; status: string }>();
1642
+ const toolTaskIds = new Map<string, string>();
1643
+ const agentTaskIds = new Map<string, string>();
1644
+ tasks.set("agent-native:context", {
1645
+ title: "Review the request",
1646
+ status: "in_progress",
1647
+ });
1648
+ let sequence = 0;
1649
+ let lastWriteAt = 0;
1650
+ let pending: Record<string, unknown> | null = null;
1651
+ let pendingTimer: ReturnType<typeof setTimeout> | null = null;
1652
+ let approvalControls: { approve: string; deny: string } | null = null;
1653
+ let cancelControl: string | null = null;
1654
+
1655
+ const append = async (chunk: Record<string, unknown>) => {
1656
+ const now = Date.now();
1657
+ const write = async (value: Record<string, unknown>) => {
1658
+ lastWriteAt = Date.now();
1659
+ try {
1660
+ await postSlackJson(token, "chat.appendStream", {
1661
+ channel,
1662
+ ts: streamTs,
1663
+ markdown_text: "Progress updated.",
1664
+ chunks: [value],
1665
+ });
1666
+ } catch (error) {
1667
+ console.warn(
1668
+ "[slack] chat.appendStream failed; progress may be stale",
1669
+ {
1670
+ chunkType: streamChunkType(value),
1671
+ errorCode: streamFailureCode(error),
1672
+ },
1673
+ );
1674
+ }
1675
+ };
1676
+ if (now - lastWriteAt >= 900) {
1677
+ await write(chunk);
1678
+ return;
1679
+ }
1680
+ pending = chunk;
1681
+ if (!pendingTimer) {
1682
+ pendingTimer = setTimeout(
1683
+ () => {
1684
+ const value = pending;
1685
+ pending = null;
1686
+ pendingTimer = null;
1687
+ if (value) void write(value);
1688
+ },
1689
+ 900 - (now - lastWriteAt),
1690
+ );
1691
+ }
1692
+ };
1693
+
1694
+ const taskId = (prefix: string, explicit?: string) =>
1695
+ `${prefix}:${explicit || ++sequence}`.slice(0, 240);
1696
+
1697
+ return {
1698
+ ref: { kind: "slack-stream", streamTs },
1699
+ async onEvent(event) {
1700
+ if (!cancelControl) {
1701
+ const context = getIntegrationRequestContext();
1702
+ const ownerEmail = getRequestContext()?.userEmail;
1703
+ if (
1704
+ context?.lineage?.runId &&
1705
+ ownerEmail &&
1706
+ incoming.senderId &&
1707
+ incoming.tenantId
1708
+ ) {
1709
+ cancelControl = await createIntegrationControl({
1710
+ action: "cancel",
1711
+ ownerEmail,
1712
+ orgId: getRequestContext()?.orgId ?? null,
1713
+ requesterId: incoming.senderId,
1714
+ teamId: incoming.tenantId,
1715
+ apiAppId:
1716
+ typeof incoming.platformContext.apiAppId === "string"
1717
+ ? incoming.platformContext.apiAppId
1718
+ : null,
1719
+ channelId: channel,
1720
+ messageTs: streamTs,
1721
+ runId: context.lineage.runId,
1722
+ incoming,
1723
+ });
1724
+ await append({
1725
+ type: "blocks",
1726
+ blocks: [
1727
+ {
1728
+ type: "actions",
1729
+ block_id: `agent-native-running-${Date.now()}`,
1730
+ elements: [
1731
+ {
1732
+ type: "button",
1733
+ text: { type: "plain_text", text: "Cancel" },
1734
+ style: "danger",
1735
+ action_id: "agent_native_cancel",
1736
+ value: cancelControl,
1737
+ },
1738
+ ],
1739
+ },
1740
+ ],
1741
+ });
1742
+ }
1743
+ }
1744
+ if (event.type === "approval_required") {
1745
+ const context = getIntegrationRequestContext();
1746
+ const ownerEmail = getRequestContext()?.userEmail;
1747
+ if (context && ownerEmail && incoming.senderId && incoming.tenantId) {
1748
+ const common = {
1749
+ ownerEmail,
1750
+ orgId: getRequestContext()?.orgId ?? null,
1751
+ requesterId: incoming.senderId,
1752
+ teamId: incoming.tenantId,
1753
+ apiAppId:
1754
+ typeof incoming.platformContext.apiAppId === "string"
1755
+ ? incoming.platformContext.apiAppId
1756
+ : null,
1757
+ channelId: channel,
1758
+ messageTs: streamTs,
1759
+ runId: context.lineage?.runId ?? null,
1760
+ approvalKey: event.approvalKey,
1761
+ incoming,
1762
+ };
1763
+ const [approve, deny] = await Promise.all([
1764
+ createIntegrationControl({ ...common, action: "approve" }),
1765
+ createIntegrationControl({ ...common, action: "deny" }),
1766
+ ]);
1767
+ approvalControls = { approve, deny };
1768
+ }
1769
+ await append({
1770
+ type: "task_update",
1771
+ id: "agent-native:approval",
1772
+ title: `Approve ${shortTaskTitle(event.tool)}`,
1773
+ status: "pending",
1774
+ details: "Waiting for the requester",
1775
+ });
1776
+ } else if (event.type === "tool_start") {
1777
+ const key = event.id || event.tool;
1778
+ const id = taskId("tool", event.id);
1779
+ toolTaskIds.set(key, id);
1780
+ const title = shortTaskTitle(event.tool);
1781
+ tasks.set(id, { title, status: "in_progress" });
1782
+ await append({
1783
+ type: "task_update",
1784
+ id,
1785
+ title,
1786
+ status: "in_progress",
1787
+ });
1788
+ } else if (event.type === "tool_done") {
1789
+ const key = event.id || event.tool;
1790
+ const id = toolTaskIds.get(key) ?? taskId("tool", event.id);
1791
+ const title = tasks.get(id)?.title ?? shortTaskTitle(event.tool);
1792
+ tasks.set(id, {
1793
+ title,
1794
+ status: event.isError ? "error" : "complete",
1795
+ });
1796
+ await append({
1797
+ type: "task_update",
1798
+ id,
1799
+ title,
1800
+ status: event.isError ? "error" : "complete",
1801
+ });
1802
+ } else if (event.type === "agent_call") {
1803
+ const id =
1804
+ agentTaskIds.get(event.agent) ?? taskId("agent", event.agent);
1805
+ agentTaskIds.set(event.agent, id);
1806
+ const status =
1807
+ event.status === "start"
1808
+ ? "in_progress"
1809
+ : event.status === "done"
1810
+ ? "complete"
1811
+ : "error";
1812
+ const title = delegatedTaskTitle(event.agent);
1813
+ tasks.set(id, { title, status });
1814
+ await append({
1815
+ type: "task_update",
1816
+ id,
1817
+ title,
1818
+ status,
1819
+ ...(event.status === "start"
1820
+ ? {
1821
+ details: `I’m contacting ${shortTaskTitle(event.agent)} for an answer.`,
1822
+ }
1823
+ : {}),
1824
+ });
1825
+ } else if (event.type === "agent_call_progress") {
1826
+ // A2A calls can stay healthy for minutes. Keep the same native Slack
1827
+ // task card alive with each real downstream poll rather than creating
1828
+ // a new card per tick or leaving the user with a stale spinner.
1829
+ const id =
1830
+ agentTaskIds.get(event.agent) ?? taskId("agent", event.agent);
1831
+ agentTaskIds.set(event.agent, id);
1832
+ const title = delegatedTaskTitle(event.agent);
1833
+ const details = delegatedProgressDetails(
1834
+ event.agent,
1835
+ event.state,
1836
+ event.elapsedSeconds,
1837
+ event.detail,
1838
+ );
1839
+ tasks.set(id, { title, status: "in_progress" });
1840
+ await append({
1841
+ type: "task_update",
1842
+ id,
1843
+ title,
1844
+ status: "in_progress",
1845
+ details,
1846
+ });
1847
+ } else if (event.type === "activity") {
1848
+ await append({
1849
+ type: "task_update",
1850
+ id: "agent-native:context",
1851
+ title: "Review the request",
1852
+ status: "in_progress",
1853
+ details: `Working · ${shortTaskTitle(event.label)}`,
1854
+ });
1855
+ }
1856
+ },
1857
+ async complete(message) {
1858
+ if (pendingTimer) clearTimeout(pendingTimer);
1859
+ const finalChunks = [...tasks.entries()].map(([id, task]) => ({
1860
+ type: "task_update",
1861
+ id,
1862
+ title: task.title,
1863
+ status: task.status === "in_progress" ? "complete" : task.status,
1864
+ }));
1865
+ const messageBlocks = Array.isArray(message.platformContext.blocks)
1866
+ ? message.platformContext.blocks
1867
+ : [];
1868
+ const controlBlocks = approvalControls
1869
+ ? [
1870
+ {
1871
+ type: "actions",
1872
+ block_id: `agent-native-approval-${Date.now()}`,
1873
+ elements: [
1874
+ {
1875
+ type: "button",
1876
+ text: { type: "plain_text", text: "Approve" },
1877
+ style: "primary",
1878
+ action_id: "agent_native_approve",
1879
+ value: approvalControls.approve,
1880
+ },
1881
+ {
1882
+ type: "button",
1883
+ text: { type: "plain_text", text: "Deny" },
1884
+ style: "danger",
1885
+ action_id: "agent_native_deny",
1886
+ value: approvalControls.deny,
1887
+ },
1888
+ ],
1889
+ },
1890
+ ]
1891
+ : [];
1892
+ await postSlackJson(token, "chat.stopStream", {
1893
+ channel,
1894
+ ts: streamTs,
1895
+ markdown_text: message.text || "Done.",
1896
+ ...(finalChunks.length ? { chunks: finalChunks } : {}),
1897
+ ...(messageBlocks.length || controlBlocks.length
1898
+ ? { blocks: [...messageBlocks, ...controlBlocks].slice(0, 50) }
1899
+ : {}),
1900
+ });
1901
+ setSlackAssistantStatus(token, channel, threadTs, "");
1902
+ return { status: "delivered", messageRefs: [streamTs] };
1903
+ },
1904
+ async fail(message) {
1905
+ if (pendingTimer) clearTimeout(pendingTimer);
1906
+ await postSlackJson(token, "chat.stopStream", {
1907
+ channel,
1908
+ ts: streamTs,
1909
+ markdown_text: message.slice(0, SLACK_MAX_LENGTH),
1910
+ }).catch(() => {});
1911
+ setSlackAssistantStatus(token, channel, threadTs, "");
1912
+ },
1913
+ };
1914
+ }