@agent-native/core 0.112.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 (1902) hide show
  1. package/agent-native.eject.json +164 -0
  2. package/corpus/README.md +4 -2
  3. package/corpus/core/CHANGELOG.md +33 -0
  4. package/corpus/core/README.md +61 -174
  5. package/corpus/core/agent-native.eject.json +164 -0
  6. package/corpus/core/docs/AGENTS.md +7 -0
  7. package/corpus/core/docs/content/agent-native-toolkit.mdx +38 -0
  8. package/corpus/core/docs/content/integrations.mdx +63 -2
  9. package/corpus/core/docs/content/package-lifecycle.mdx +54 -4
  10. package/corpus/core/docs/design/provider-integration-authority.md +117 -0
  11. package/corpus/core/package.json +20 -2
  12. package/corpus/core/scripts/materialize-source-corpus.mjs +9 -2
  13. package/corpus/core/src/cli/atomic-json-file.ts +324 -0
  14. package/corpus/core/src/cli/claude-code-participant.ts +515 -0
  15. package/corpus/core/src/cli/code-agent-executor.ts +18 -10
  16. package/corpus/core/src/cli/code-agent-runs.concurrent-worker.ts +33 -0
  17. package/corpus/core/src/cli/code-agent-runs.ts +55 -62
  18. package/corpus/core/src/cli/codex-cli-participant.ts +496 -0
  19. package/corpus/core/src/cli/eject.ts +1594 -0
  20. package/corpus/core/src/cli/index.ts +16 -0
  21. package/corpus/core/src/cli/multi-frontier-runs.ts +1246 -135
  22. package/corpus/core/src/client/chat/ChatHistoryList.tsx +7 -404
  23. package/corpus/core/src/client/index.ts +4 -0
  24. package/corpus/core/src/client/resources/McpConnectionSuggestion.tsx +8 -2
  25. package/corpus/core/src/client/resources/McpIntegrationDialog.tsx +7 -2
  26. package/corpus/core/src/client/resources/ResourcesPanel.tsx +17 -3
  27. package/corpus/core/src/client/resources/index.ts +19 -0
  28. package/corpus/core/src/client/resources/mcp-integration-catalog.ts +9 -1
  29. package/corpus/core/src/client/resources/runtime.ts +1 -0
  30. package/corpus/core/src/client/setup-connections/catalog.ts +6 -0
  31. package/corpus/core/src/client/setup-connections/index.ts +1 -0
  32. package/corpus/core/src/client/setup-connections/runtime.ts +1 -0
  33. package/corpus/core/src/connections/catalog.ts +41 -24
  34. package/corpus/core/src/connections/index.ts +1 -0
  35. package/corpus/core/src/connections/runtime.ts +1 -0
  36. package/corpus/core/src/eject/provider-api-definitions.ts +193 -0
  37. package/corpus/core/src/eject/remote-mcp-presets.ts +137 -0
  38. package/corpus/core/src/eject/setup-readiness-ui.tsx +29 -0
  39. package/corpus/core/src/eject/workspace-connections.ts +92 -0
  40. package/corpus/core/src/index.ts +1 -0
  41. package/corpus/core/src/integrations/adapter-overrides.ts +12 -0
  42. package/corpus/core/src/integrations/eject/messaging-adapters.ts +85 -0
  43. package/corpus/core/src/integrations/index.ts +15 -1
  44. package/corpus/core/src/integrations/plugin.ts +34 -12
  45. package/corpus/core/src/integrations/runtime.ts +1 -0
  46. package/corpus/core/src/integrations/slack-oauth.ts +1 -0
  47. package/corpus/core/src/integrations/types.ts +3 -1
  48. package/corpus/core/src/integrations/webhook-delivery.ts +55 -0
  49. package/corpus/core/src/notifications/channels.ts +4 -10
  50. package/corpus/core/src/package-lifecycle/eject-manifest.ts +345 -0
  51. package/corpus/core/src/package-lifecycle/index.ts +1 -0
  52. package/corpus/core/src/provider-api/actions/custom-provider-registration.ts +197 -0
  53. package/corpus/core/src/provider-api/actions/delete-staged-dataset.ts +3 -42
  54. package/corpus/core/src/provider-api/actions/list-staged-datasets.ts +3 -45
  55. package/corpus/core/src/provider-api/actions/provider-api-audit.ts +88 -0
  56. package/corpus/core/src/provider-api/actions/provider-api.ts +460 -0
  57. package/corpus/core/src/provider-api/actions/query-staged-dataset.ts +3 -140
  58. package/corpus/core/src/provider-api/actions/staged-datasets.ts +359 -0
  59. package/corpus/core/src/provider-api/gong.ts +108 -0
  60. package/corpus/core/src/provider-api/index.ts +46 -12
  61. package/corpus/core/src/provider-api/runtime.ts +1 -0
  62. package/corpus/core/src/scripts/docs/source-search.ts +2 -1
  63. package/corpus/core/src/server/google-oauth-credentials.ts +80 -3
  64. package/corpus/core/src/server/index.ts +6 -0
  65. package/corpus/core/src/setup-connections/index.ts +1 -0
  66. package/corpus/core/src/shared/merge-by-id.ts +14 -0
  67. package/corpus/core/src/styles/chat-history-list.css +1 -313
  68. package/corpus/core/src/templates/default/.agents/skills/actions/SKILL.md +32 -12
  69. package/corpus/core/src/templates/default/.agents/skills/agent-native-docs/SKILL.md +21 -9
  70. package/corpus/core/src/templates/default/.agents/skills/customizing-agent-native/SKILL.md +145 -0
  71. package/corpus/core/src/templates/default/.agents/skills/integration-webhooks/SKILL.md +323 -0
  72. package/corpus/core/src/templates/default/.agents/skills/onboarding/SKILL.md +56 -0
  73. package/corpus/core/src/templates/default/.agents/skills/secrets/SKILL.md +273 -0
  74. package/corpus/core/src/templates/default/.agents/skills/self-modifying-code/SKILL.md +14 -2
  75. package/corpus/core/src/templates/default/.agents/skills/upgrade-agent-native/SKILL.md +6 -0
  76. package/corpus/core/src/templates/default/AGENTS.md +26 -18
  77. package/corpus/core/src/templates/headless/.agents/skills/actions/SKILL.md +512 -0
  78. package/corpus/core/src/templates/headless/.agents/skills/agent-native-docs/SKILL.md +21 -9
  79. package/corpus/core/src/templates/headless/.agents/skills/customizing-agent-native/SKILL.md +145 -0
  80. package/corpus/core/src/templates/headless/.agents/skills/integration-webhooks/SKILL.md +323 -0
  81. package/corpus/core/src/templates/headless/.agents/skills/secrets/SKILL.md +273 -0
  82. package/corpus/core/src/templates/headless/.agents/skills/upgrade-agent-native/SKILL.md +6 -0
  83. package/corpus/core/src/templates/headless/AGENTS.md +8 -0
  84. package/corpus/core/src/templates/workspace-core/.agents/skills/actions/SKILL.md +32 -12
  85. package/corpus/core/src/templates/workspace-core/.agents/skills/agent-native-docs/SKILL.md +21 -9
  86. package/corpus/core/src/templates/workspace-core/.agents/skills/agent-native-toolkit/SKILL.md +7 -0
  87. package/corpus/core/src/templates/workspace-core/.agents/skills/customizing-agent-native/SKILL.md +145 -0
  88. package/corpus/core/src/templates/workspace-core/.agents/skills/self-modifying-code/SKILL.md +14 -2
  89. package/corpus/core/src/templates/workspace-core/.agents/skills/upgrade-agent-native/SKILL.md +6 -0
  90. package/corpus/core/src/templates/workspace-core/AGENTS.md +4 -0
  91. package/corpus/core/src/templates/workspace-root/AGENTS.md +4 -0
  92. package/corpus/core/src/vite/client.ts +25 -2
  93. package/corpus/templates/analytics/.agents/skills/actions/SKILL.md +32 -12
  94. package/corpus/templates/analytics/.agents/skills/customizing-agent-native/SKILL.md +145 -0
  95. package/corpus/templates/analytics/.agents/skills/self-modifying-code/SKILL.md +14 -2
  96. package/corpus/templates/analytics/.agents/skills/upgrade-agent-native/SKILL.md +6 -0
  97. package/corpus/templates/analytics/actions/delete-staged-dataset.ts +3 -23
  98. package/corpus/templates/analytics/actions/list-staged-datasets.ts +3 -27
  99. package/corpus/templates/analytics/actions/provider-api-catalog.ts +16 -19
  100. package/corpus/templates/analytics/actions/provider-api-docs.ts +3 -5
  101. package/corpus/templates/analytics/actions/provider-api-request.ts +162 -185
  102. package/corpus/templates/analytics/actions/query-staged-dataset.ts +3 -47
  103. package/corpus/templates/analytics/app/components/layout/Sidebar.tsx +52 -161
  104. package/corpus/templates/assets/.agents/skills/actions/SKILL.md +32 -12
  105. package/corpus/templates/assets/.agents/skills/customizing-agent-native/SKILL.md +145 -0
  106. package/corpus/templates/assets/.agents/skills/self-modifying-code/SKILL.md +14 -2
  107. package/corpus/templates/assets/.agents/skills/upgrade-agent-native/SKILL.md +6 -0
  108. package/corpus/templates/assets/app/components/layout/Sidebar.tsx +63 -160
  109. package/corpus/templates/brain/.agents/skills/actions/SKILL.md +32 -12
  110. package/corpus/templates/brain/.agents/skills/customizing-agent-native/SKILL.md +145 -0
  111. package/corpus/templates/brain/.agents/skills/self-modifying-code/SKILL.md +14 -2
  112. package/corpus/templates/brain/.agents/skills/upgrade-agent-native/SKILL.md +6 -0
  113. package/corpus/templates/brain/actions/_schemas.ts +13 -7
  114. package/corpus/templates/brain/actions/delete-staged-dataset.ts +3 -24
  115. package/corpus/templates/brain/actions/list-staged-datasets.ts +3 -28
  116. package/corpus/templates/brain/actions/provider-api-catalog.ts +5 -11
  117. package/corpus/templates/brain/actions/provider-api-docs.ts +3 -5
  118. package/corpus/templates/brain/actions/provider-api-request.ts +3 -37
  119. package/corpus/templates/brain/actions/query-staged-dataset.ts +3 -48
  120. package/corpus/templates/brain/actions/remediate-legacy-capture-audiences.ts +167 -0
  121. package/corpus/templates/brain/actions/update-source.ts +5 -1
  122. package/corpus/templates/brain/app/components/layout/Sidebar.tsx +48 -154
  123. package/corpus/templates/brain/app/lib/brain-chat-readiness.ts +6 -0
  124. package/corpus/templates/brain/app/lib/brain.ts +55 -0
  125. package/corpus/templates/brain/app/lib/ingest-handoff.ts +35 -0
  126. package/corpus/templates/brain/app/routes/_index.tsx +8 -0
  127. package/corpus/templates/brain/app/routes.ts +1 -0
  128. package/corpus/templates/brain/changelog/2026-07-19-ask-starts-immediately-when-builder-s-managed-ai-connection-.md +6 -0
  129. package/corpus/templates/brain/changelog/2026-07-19-slack-and-granola-backfills-now-process-captures-concurrentl.md +6 -0
  130. package/corpus/templates/brain/changelog/2026-07-19-slack-backfills-can-now-join-configured-public-channels-befo.md +6 -0
  131. package/corpus/templates/brain/changelog/2026-07-19-slack-backfills-now-continue-across-the-configured-number-of.md +6 -0
  132. package/corpus/templates/brain/changelog/2026-07-19-slack-backfills-now-start-with-a-safe-four-week-window-and-r.md +6 -0
  133. package/corpus/templates/brain/changelog/2026-07-19-source-review-settings-now-control-knowledge-approval.md +6 -0
  134. package/corpus/templates/brain/changelog/2026-07-19-the-manage-agent-page-now-opens-correctly-from-brain-navigat.md +6 -0
  135. package/corpus/templates/brain/server/db/schema.ts +3 -0
  136. package/corpus/templates/brain/server/lib/brain.ts +41 -2
  137. package/corpus/templates/brain/server/lib/connectors.ts +432 -115
  138. package/corpus/templates/brain/server/lib/meeting-audience.ts +38 -0
  139. package/corpus/templates/brain/server/lib/slack-channel-membership.ts +44 -0
  140. package/corpus/templates/brain/server/plugins/db.ts +10 -0
  141. package/corpus/templates/brain/server/routes/api/_agent-native/brain/ingest.post.ts +6 -4
  142. package/corpus/templates/brain/shared/slack-source-config.ts +60 -0
  143. package/corpus/templates/calendar/.agents/skills/actions/SKILL.md +32 -12
  144. package/corpus/templates/calendar/.agents/skills/customizing-agent-native/SKILL.md +145 -0
  145. package/corpus/templates/calendar/.agents/skills/self-modifying-code/SKILL.md +14 -2
  146. package/corpus/templates/calendar/.agents/skills/upgrade-agent-native/SKILL.md +6 -0
  147. package/corpus/templates/calendar/actions/delete-staged-dataset.ts +3 -24
  148. package/corpus/templates/calendar/actions/list-staged-datasets.ts +3 -28
  149. package/corpus/templates/calendar/actions/provider-api-catalog.ts +5 -11
  150. package/corpus/templates/calendar/actions/provider-api-docs.ts +3 -5
  151. package/corpus/templates/calendar/actions/provider-api-request.ts +3 -37
  152. package/corpus/templates/calendar/actions/query-staged-dataset.ts +3 -48
  153. package/corpus/templates/calendar/server/handlers/gong.ts +6 -61
  154. package/corpus/templates/calendar/server/handlers/google-auth.ts +10 -8
  155. package/corpus/templates/calendar/server/lib/google-calendar.ts +7 -45
  156. package/corpus/templates/chat/.agents/skills/actions/SKILL.md +32 -12
  157. package/corpus/templates/chat/.agents/skills/agent-native-docs/SKILL.md +21 -9
  158. package/corpus/templates/chat/.agents/skills/customizing-agent-native/SKILL.md +145 -0
  159. package/corpus/templates/chat/.agents/skills/self-modifying-code/SKILL.md +14 -2
  160. package/corpus/templates/chat/.agents/skills/upgrade-agent-native/SKILL.md +6 -0
  161. package/corpus/templates/chat/AGENTS.md +6 -2
  162. package/corpus/templates/chat/app/components/layout/Sidebar.tsx +51 -157
  163. package/corpus/templates/clips/.agents/skills/actions/SKILL.md +32 -12
  164. package/corpus/templates/clips/.agents/skills/customizing-agent-native/SKILL.md +145 -0
  165. package/corpus/templates/clips/.agents/skills/self-modifying-code/SKILL.md +14 -2
  166. package/corpus/templates/clips/.agents/skills/upgrade-agent-native/SKILL.md +6 -0
  167. package/corpus/templates/clips/AGENTS.md +11 -0
  168. package/corpus/templates/clips/actions/export-to-brain.ts +505 -171
  169. package/corpus/templates/clips/changelog/2026-07-19-ready-clips-transcripts-can-be-backfilled-to-brain-for-a-bou.md +6 -0
  170. package/corpus/templates/clips/server/lib/calendar-event-meetings.ts +1 -1
  171. package/corpus/templates/clips/server/lib/google-calendar-client.ts +12 -22
  172. package/corpus/templates/clips/server/lib/google-calendar-oauth.ts +9 -6
  173. package/corpus/templates/clips/server/lib/slack-oauth.ts +12 -47
  174. package/corpus/templates/clips/server/routes/_agent-native/google/auth-url.get.ts +2 -6
  175. package/corpus/templates/clips/server/routes/api/auth/google-calendar.get.ts +4 -4
  176. package/corpus/templates/content/.agents/skills/actions/SKILL.md +32 -12
  177. package/corpus/templates/content/.agents/skills/customizing-agent-native/SKILL.md +145 -0
  178. package/corpus/templates/content/.agents/skills/self-modifying-code/SKILL.md +14 -2
  179. package/corpus/templates/content/.agents/skills/upgrade-agent-native/SKILL.md +6 -0
  180. package/corpus/templates/content/actions/delete-staged-dataset.ts +3 -24
  181. package/corpus/templates/content/actions/list-staged-datasets.ts +3 -28
  182. package/corpus/templates/content/actions/provider-api-catalog.ts +5 -11
  183. package/corpus/templates/content/actions/provider-api-docs.ts +3 -5
  184. package/corpus/templates/content/actions/provider-api-request.ts +3 -37
  185. package/corpus/templates/content/actions/query-staged-dataset.ts +3 -48
  186. package/corpus/templates/design/.agents/skills/actions/SKILL.md +32 -12
  187. package/corpus/templates/design/.agents/skills/customizing-agent-native/SKILL.md +145 -0
  188. package/corpus/templates/design/.agents/skills/self-modifying-code/SKILL.md +14 -2
  189. package/corpus/templates/design/.agents/skills/upgrade-agent-native/SKILL.md +6 -0
  190. package/corpus/templates/design/actions/delete-staged-dataset.ts +4 -23
  191. package/corpus/templates/design/actions/list-staged-datasets.ts +4 -27
  192. package/corpus/templates/design/actions/provider-api-catalog.ts +15 -18
  193. package/corpus/templates/design/actions/provider-api-docs.ts +57 -48
  194. package/corpus/templates/design/actions/provider-api-request.ts +140 -164
  195. package/corpus/templates/design/actions/query-staged-dataset.ts +4 -47
  196. package/corpus/templates/dispatch/.agents/skills/actions/SKILL.md +32 -12
  197. package/corpus/templates/dispatch/.agents/skills/customizing-agent-native/SKILL.md +145 -0
  198. package/corpus/templates/dispatch/.agents/skills/self-modifying-code/SKILL.md +14 -2
  199. package/corpus/templates/dispatch/.agents/skills/upgrade-agent-native/SKILL.md +6 -0
  200. package/corpus/templates/dispatch/actions/delete-staged-dataset.ts +4 -23
  201. package/corpus/templates/dispatch/actions/list-staged-datasets.ts +4 -30
  202. package/corpus/templates/dispatch/actions/provider-api-catalog.ts +15 -18
  203. package/corpus/templates/dispatch/actions/provider-api-docs.ts +57 -48
  204. package/corpus/templates/dispatch/actions/provider-api-request.ts +138 -163
  205. package/corpus/templates/dispatch/actions/query-staged-dataset.ts +4 -47
  206. package/corpus/templates/forms/.agents/skills/actions/SKILL.md +32 -12
  207. package/corpus/templates/forms/.agents/skills/customizing-agent-native/SKILL.md +145 -0
  208. package/corpus/templates/forms/.agents/skills/self-modifying-code/SKILL.md +14 -2
  209. package/corpus/templates/forms/.agents/skills/upgrade-agent-native/SKILL.md +6 -0
  210. package/corpus/templates/forms/server/lib/integrations.ts +23 -22
  211. package/corpus/templates/macros/.agents/skills/customizing-agent-native/SKILL.md +145 -0
  212. package/corpus/templates/macros/.agents/skills/upgrade-agent-native/SKILL.md +6 -0
  213. package/corpus/templates/mail/.agents/skills/actions/SKILL.md +32 -12
  214. package/corpus/templates/mail/.agents/skills/customizing-agent-native/SKILL.md +145 -0
  215. package/corpus/templates/mail/.agents/skills/self-modifying-code/SKILL.md +14 -2
  216. package/corpus/templates/mail/.agents/skills/upgrade-agent-native/SKILL.md +6 -0
  217. package/corpus/templates/mail/actions/delete-staged-dataset.ts +4 -23
  218. package/corpus/templates/mail/actions/list-staged-datasets.ts +4 -27
  219. package/corpus/templates/mail/actions/provider-api-catalog.ts +15 -18
  220. package/corpus/templates/mail/actions/provider-api-docs.ts +57 -48
  221. package/corpus/templates/mail/actions/provider-api-request.ts +146 -173
  222. package/corpus/templates/mail/actions/query-staged-dataset.ts +4 -47
  223. package/corpus/templates/mail/server/handlers/gong.ts +6 -61
  224. package/corpus/templates/mail/server/lib/google-auth.ts +10 -13
  225. package/corpus/templates/plan/.agents/skills/actions/SKILL.md +32 -12
  226. package/corpus/templates/plan/.agents/skills/customizing-agent-native/SKILL.md +145 -0
  227. package/corpus/templates/plan/.agents/skills/self-modifying-code/SKILL.md +14 -2
  228. package/corpus/templates/plan/.agents/skills/upgrade-agent-native/SKILL.md +6 -0
  229. package/corpus/templates/plan/app/components/layout/Sidebar.tsx +47 -156
  230. package/corpus/templates/slides/.agents/skills/actions/SKILL.md +32 -12
  231. package/corpus/templates/slides/.agents/skills/customizing-agent-native/SKILL.md +145 -0
  232. package/corpus/templates/slides/.agents/skills/self-modifying-code/SKILL.md +14 -2
  233. package/corpus/templates/slides/.agents/skills/upgrade-agent-native/SKILL.md +6 -0
  234. package/corpus/templates/slides/actions/delete-staged-dataset.ts +4 -23
  235. package/corpus/templates/slides/actions/list-staged-datasets.ts +4 -27
  236. package/corpus/templates/slides/actions/provider-api-catalog.ts +15 -18
  237. package/corpus/templates/slides/actions/provider-api-docs.ts +57 -48
  238. package/corpus/templates/slides/actions/provider-api-request.ts +145 -172
  239. package/corpus/templates/slides/actions/query-staged-dataset.ts +4 -47
  240. package/corpus/templates/slides/server/lib/google-docs-oauth.ts +11 -36
  241. package/corpus/templates/tasks/.agents/skills/actions/SKILL.md +32 -12
  242. package/corpus/templates/tasks/.agents/skills/agent-native-docs/SKILL.md +21 -9
  243. package/corpus/templates/tasks/.agents/skills/customizing-agent-native/SKILL.md +145 -0
  244. package/corpus/templates/tasks/.agents/skills/self-modifying-code/SKILL.md +14 -2
  245. package/corpus/templates/tasks/.agents/skills/upgrade-agent-native/SKILL.md +6 -0
  246. package/corpus/toolkit/CHANGELOG.md +131 -0
  247. package/corpus/toolkit/README.md +60 -0
  248. package/corpus/toolkit/agent-native.eject.json +411 -0
  249. package/corpus/toolkit/export-snapshot.json +35 -0
  250. package/corpus/toolkit/migration-manifest.json +4 -0
  251. package/corpus/toolkit/package.json +284 -0
  252. package/corpus/toolkit/scripts/finalize-build.mjs +55 -0
  253. package/corpus/toolkit/src/app-shell/header-actions.tsx +84 -0
  254. package/corpus/toolkit/src/app-shell/index.ts +1 -0
  255. package/corpus/toolkit/src/chat-history/ChatHistoryList.tsx +469 -0
  256. package/corpus/toolkit/src/chat-history/index.ts +7 -0
  257. package/corpus/toolkit/src/chat-history.css +314 -0
  258. package/corpus/toolkit/src/collab-ui/AgentPresenceChip.tsx +69 -0
  259. package/corpus/toolkit/src/collab-ui/LiveCursorOverlay.tsx +241 -0
  260. package/corpus/toolkit/src/collab-ui/PresenceBar.tsx +346 -0
  261. package/corpus/toolkit/src/collab-ui/RecentEditHighlights.tsx +225 -0
  262. package/corpus/toolkit/src/collab-ui/RemoteSelectionRings.tsx +227 -0
  263. package/corpus/toolkit/src/collab-ui/agent-identity.ts +16 -0
  264. package/corpus/toolkit/src/collab-ui/index.ts +39 -0
  265. package/corpus/toolkit/src/collab-ui/lead-client.ts +32 -0
  266. package/corpus/toolkit/src/collab-ui/types.ts +96 -0
  267. package/corpus/toolkit/src/composer/AgentComposerFrame.tsx +59 -0
  268. package/corpus/toolkit/src/composer/ComposerPlusMenu.tsx +983 -0
  269. package/corpus/toolkit/src/composer/MentionPopover.tsx +412 -0
  270. package/corpus/toolkit/src/composer/PastedTextChip.tsx +150 -0
  271. package/corpus/toolkit/src/composer/PromptComposer.tsx +718 -0
  272. package/corpus/toolkit/src/composer/RealtimeVoiceMode.tsx +856 -0
  273. package/corpus/toolkit/src/composer/TiptapComposer.tsx +2936 -0
  274. package/corpus/toolkit/src/composer/VoiceButton.tsx +255 -0
  275. package/corpus/toolkit/src/composer/asset-picker-url.ts +80 -0
  276. package/corpus/toolkit/src/composer/attachment-accept.ts +71 -0
  277. package/corpus/toolkit/src/composer/draft-key.ts +7 -0
  278. package/corpus/toolkit/src/composer/extensions/FileReference.tsx +55 -0
  279. package/corpus/toolkit/src/composer/extensions/MentionReference.tsx +93 -0
  280. package/corpus/toolkit/src/composer/extensions/SkillReference.tsx +56 -0
  281. package/corpus/toolkit/src/composer/index.ts +79 -0
  282. package/corpus/toolkit/src/composer/pasted-text.ts +160 -0
  283. package/corpus/toolkit/src/composer/prompt-attachments.ts +93 -0
  284. package/corpus/toolkit/src/composer/realtime-voice-audio-level.ts +64 -0
  285. package/corpus/toolkit/src/composer/realtime-voice-transcript.ts +134 -0
  286. package/corpus/toolkit/src/composer/runtime-adapters.tsx +343 -0
  287. package/corpus/toolkit/src/composer/types.ts +66 -0
  288. package/corpus/toolkit/src/composer/use-file-search.ts +64 -0
  289. package/corpus/toolkit/src/composer/use-mention-search.ts +90 -0
  290. package/corpus/toolkit/src/composer/use-skills.ts +45 -0
  291. package/corpus/toolkit/src/composer/useRealtimeVoiceMode.tsx +2117 -0
  292. package/corpus/toolkit/src/composer/useVoiceDictation.ts +1191 -0
  293. package/corpus/toolkit/src/context-ui/ContextMeter.tsx +101 -0
  294. package/corpus/toolkit/src/context-ui/ContextSegmentRow.tsx +184 -0
  295. package/corpus/toolkit/src/context-ui/ContextTreemap.tsx +125 -0
  296. package/corpus/toolkit/src/context-ui/ContextXRayPanel.tsx +377 -0
  297. package/corpus/toolkit/src/context-ui/format.ts +42 -0
  298. package/corpus/toolkit/src/context-ui/index.ts +15 -0
  299. package/corpus/toolkit/src/context-ui/types.ts +43 -0
  300. package/corpus/toolkit/src/design-tweaks/index.ts +1 -0
  301. package/corpus/toolkit/src/design-tweaks/visual-style-controls.tsx +1084 -0
  302. package/corpus/toolkit/src/editor/BubbleToolbar.tsx +253 -0
  303. package/corpus/toolkit/src/editor/CodeBlockNode.tsx +254 -0
  304. package/corpus/toolkit/src/editor/DragHandle.ts +1437 -0
  305. package/corpus/toolkit/src/editor/ImageExtension.ts +306 -0
  306. package/corpus/toolkit/src/editor/RegistryBlockContext.tsx +107 -0
  307. package/corpus/toolkit/src/editor/RegistryBlockNode.tsx +652 -0
  308. package/corpus/toolkit/src/editor/RichMarkdownEditor.tsx +81 -0
  309. package/corpus/toolkit/src/editor/RunId.ts +61 -0
  310. package/corpus/toolkit/src/editor/SharedRichEditor.tsx +321 -0
  311. package/corpus/toolkit/src/editor/SlashCommandMenu.tsx +310 -0
  312. package/corpus/toolkit/src/editor/extensions.ts +402 -0
  313. package/corpus/toolkit/src/editor/gfmDoc.ts +92 -0
  314. package/corpus/toolkit/src/editor/index.ts +93 -0
  315. package/corpus/toolkit/src/editor/registrySlashCommands.ts +131 -0
  316. package/corpus/toolkit/src/editor/surgical-apply.ts +192 -0
  317. package/corpus/toolkit/src/editor/useCollabReconcile.ts +589 -0
  318. package/corpus/toolkit/src/editor.css +510 -0
  319. package/corpus/toolkit/src/hooks/index.ts +2 -0
  320. package/corpus/toolkit/src/hooks/use-mobile.tsx +21 -0
  321. package/corpus/toolkit/src/hooks/use-toast.ts +188 -0
  322. package/corpus/toolkit/src/index.ts +8 -0
  323. package/corpus/toolkit/src/onboarding/index.ts +1 -0
  324. package/corpus/toolkit/src/provider.tsx +47 -0
  325. package/corpus/toolkit/src/sharing/VisibilityBadge.tsx +37 -0
  326. package/corpus/toolkit/src/sharing/index.ts +4 -0
  327. package/corpus/toolkit/src/styles.css +21 -0
  328. package/corpus/toolkit/src/ui/accordion.tsx +56 -0
  329. package/corpus/toolkit/src/ui/alert-dialog.tsx +141 -0
  330. package/corpus/toolkit/src/ui/alert.tsx +59 -0
  331. package/corpus/toolkit/src/ui/aspect-ratio.tsx +5 -0
  332. package/corpus/toolkit/src/ui/avatar.tsx +48 -0
  333. package/corpus/toolkit/src/ui/badge.tsx +37 -0
  334. package/corpus/toolkit/src/ui/breadcrumb.tsx +115 -0
  335. package/corpus/toolkit/src/ui/button.tsx +78 -0
  336. package/corpus/toolkit/src/ui/calendar.tsx +214 -0
  337. package/corpus/toolkit/src/ui/card.tsx +86 -0
  338. package/corpus/toolkit/src/ui/carousel.tsx +260 -0
  339. package/corpus/toolkit/src/ui/chart.tsx +375 -0
  340. package/corpus/toolkit/src/ui/checkbox.tsx +28 -0
  341. package/corpus/toolkit/src/ui/collapsible.tsx +9 -0
  342. package/corpus/toolkit/src/ui/command.tsx +174 -0
  343. package/corpus/toolkit/src/ui/context-menu.tsx +202 -0
  344. package/corpus/toolkit/src/ui/date-picker.tsx +64 -0
  345. package/corpus/toolkit/src/ui/dialog.tsx +146 -0
  346. package/corpus/toolkit/src/ui/drawer.tsx +126 -0
  347. package/corpus/toolkit/src/ui/dropdown-menu.tsx +218 -0
  348. package/corpus/toolkit/src/ui/form.tsx +177 -0
  349. package/corpus/toolkit/src/ui/hover-card.tsx +27 -0
  350. package/corpus/toolkit/src/ui/index.ts +52 -0
  351. package/corpus/toolkit/src/ui/input-otp.tsx +69 -0
  352. package/corpus/toolkit/src/ui/input.tsx +22 -0
  353. package/corpus/toolkit/src/ui/label.tsx +24 -0
  354. package/corpus/toolkit/src/ui/logo.tsx +36 -0
  355. package/corpus/toolkit/src/ui/menubar.tsx +235 -0
  356. package/corpus/toolkit/src/ui/navigation-menu.tsx +128 -0
  357. package/corpus/toolkit/src/ui/pagination.tsx +121 -0
  358. package/corpus/toolkit/src/ui/popover.tsx +44 -0
  359. package/corpus/toolkit/src/ui/progress.tsx +26 -0
  360. package/corpus/toolkit/src/ui/radio-group.tsx +42 -0
  361. package/corpus/toolkit/src/ui/resizable.tsx +43 -0
  362. package/corpus/toolkit/src/ui/scroll-area.tsx +46 -0
  363. package/corpus/toolkit/src/ui/select.tsx +158 -0
  364. package/corpus/toolkit/src/ui/separator.tsx +29 -0
  365. package/corpus/toolkit/src/ui/sheet.tsx +160 -0
  366. package/corpus/toolkit/src/ui/sidebar.tsx +777 -0
  367. package/corpus/toolkit/src/ui/skeleton.tsx +18 -0
  368. package/corpus/toolkit/src/ui/slider.tsx +26 -0
  369. package/corpus/toolkit/src/ui/sonner.tsx +58 -0
  370. package/corpus/toolkit/src/ui/spinner.tsx +17 -0
  371. package/corpus/toolkit/src/ui/switch.tsx +27 -0
  372. package/corpus/toolkit/src/ui/table.tsx +117 -0
  373. package/corpus/toolkit/src/ui/tabs.tsx +53 -0
  374. package/corpus/toolkit/src/ui/textarea.tsx +23 -0
  375. package/corpus/toolkit/src/ui/toast.tsx +127 -0
  376. package/corpus/toolkit/src/ui/toaster.tsx +33 -0
  377. package/corpus/toolkit/src/ui/toggle-group.tsx +59 -0
  378. package/corpus/toolkit/src/ui/toggle.tsx +43 -0
  379. package/corpus/toolkit/src/ui/tooltip.tsx +53 -0
  380. package/corpus/toolkit/src/ui/use-toast.ts +3 -0
  381. package/corpus/toolkit/src/utils.ts +8 -0
  382. package/corpus/toolkit/tsconfig.json +23 -0
  383. package/dist/cli/atomic-json-file.d.ts +30 -0
  384. package/dist/cli/atomic-json-file.d.ts.map +1 -0
  385. package/dist/cli/atomic-json-file.js +240 -0
  386. package/dist/cli/atomic-json-file.js.map +1 -0
  387. package/dist/cli/claude-code-participant.d.ts +77 -0
  388. package/dist/cli/claude-code-participant.d.ts.map +1 -0
  389. package/dist/cli/claude-code-participant.js +355 -0
  390. package/dist/cli/claude-code-participant.js.map +1 -0
  391. package/dist/cli/code-agent-executor.d.ts.map +1 -1
  392. package/dist/cli/code-agent-executor.js +18 -10
  393. package/dist/cli/code-agent-executor.js.map +1 -1
  394. package/dist/cli/code-agent-runs.concurrent-worker.d.ts +2 -0
  395. package/dist/cli/code-agent-runs.concurrent-worker.d.ts.map +1 -0
  396. package/dist/cli/code-agent-runs.concurrent-worker.js +32 -0
  397. package/dist/cli/code-agent-runs.concurrent-worker.js.map +1 -0
  398. package/dist/cli/code-agent-runs.d.ts.map +1 -1
  399. package/dist/cli/code-agent-runs.js +43 -56
  400. package/dist/cli/code-agent-runs.js.map +1 -1
  401. package/dist/cli/codex-cli-participant.d.ts +77 -0
  402. package/dist/cli/codex-cli-participant.d.ts.map +1 -0
  403. package/dist/cli/codex-cli-participant.js +354 -0
  404. package/dist/cli/codex-cli-participant.js.map +1 -0
  405. package/dist/cli/eject.d.ts +21 -0
  406. package/dist/cli/eject.d.ts.map +1 -0
  407. package/dist/cli/eject.js +1145 -0
  408. package/dist/cli/eject.js.map +1 -0
  409. package/dist/cli/index.js +15 -0
  410. package/dist/cli/index.js.map +1 -1
  411. package/dist/cli/multi-frontier-runs.d.ts +115 -0
  412. package/dist/cli/multi-frontier-runs.d.ts.map +1 -1
  413. package/dist/cli/multi-frontier-runs.js +831 -113
  414. package/dist/cli/multi-frontier-runs.js.map +1 -1
  415. package/dist/client/chat/ChatHistoryList.d.ts +1 -87
  416. package/dist/client/chat/ChatHistoryList.d.ts.map +1 -1
  417. package/dist/client/chat/ChatHistoryList.js +1 -82
  418. package/dist/client/chat/ChatHistoryList.js.map +1 -1
  419. package/dist/client/index.d.ts +1 -1
  420. package/dist/client/index.d.ts.map +1 -1
  421. package/dist/client/index.js +1 -1
  422. package/dist/client/index.js.map +1 -1
  423. package/dist/client/resources/McpConnectionSuggestion.d.ts +4 -3
  424. package/dist/client/resources/McpConnectionSuggestion.d.ts.map +1 -1
  425. package/dist/client/resources/McpConnectionSuggestion.js +3 -3
  426. package/dist/client/resources/McpConnectionSuggestion.js.map +1 -1
  427. package/dist/client/resources/McpIntegrationDialog.d.ts +4 -3
  428. package/dist/client/resources/McpIntegrationDialog.d.ts.map +1 -1
  429. package/dist/client/resources/McpIntegrationDialog.js +2 -2
  430. package/dist/client/resources/McpIntegrationDialog.js.map +1 -1
  431. package/dist/client/resources/ResourcesPanel.d.ts +4 -1
  432. package/dist/client/resources/ResourcesPanel.d.ts.map +1 -1
  433. package/dist/client/resources/ResourcesPanel.js +9 -7
  434. package/dist/client/resources/ResourcesPanel.js.map +1 -1
  435. package/dist/client/resources/index.d.ts +3 -0
  436. package/dist/client/resources/index.d.ts.map +1 -1
  437. package/dist/client/resources/index.js +3 -0
  438. package/dist/client/resources/index.js.map +1 -1
  439. package/dist/client/resources/mcp-integration-catalog.d.ts +2 -1
  440. package/dist/client/resources/mcp-integration-catalog.d.ts.map +1 -1
  441. package/dist/client/resources/mcp-integration-catalog.js +6 -2
  442. package/dist/client/resources/mcp-integration-catalog.js.map +1 -1
  443. package/dist/client/resources/runtime.d.ts +2 -0
  444. package/dist/client/resources/runtime.d.ts.map +1 -0
  445. package/dist/client/resources/runtime.js +2 -0
  446. package/dist/client/resources/runtime.js.map +1 -0
  447. package/dist/client/setup-connections/catalog.d.ts +2 -0
  448. package/dist/client/setup-connections/catalog.d.ts.map +1 -0
  449. package/dist/client/setup-connections/catalog.js +7 -0
  450. package/dist/client/setup-connections/catalog.js.map +1 -0
  451. package/dist/client/setup-connections/index.d.ts +1 -0
  452. package/dist/client/setup-connections/index.d.ts.map +1 -1
  453. package/dist/client/setup-connections/index.js +1 -0
  454. package/dist/client/setup-connections/index.js.map +1 -1
  455. package/dist/client/setup-connections/runtime.d.ts +2 -0
  456. package/dist/client/setup-connections/runtime.d.ts.map +1 -0
  457. package/dist/client/setup-connections/runtime.js +2 -0
  458. package/dist/client/setup-connections/runtime.js.map +1 -0
  459. package/dist/collab/awareness.d.ts +2 -2
  460. package/dist/collab/awareness.d.ts.map +1 -1
  461. package/dist/collab/routes.d.ts +1 -1
  462. package/dist/connections/catalog.d.ts +5 -3
  463. package/dist/connections/catalog.d.ts.map +1 -1
  464. package/dist/connections/catalog.js +16 -8
  465. package/dist/connections/catalog.js.map +1 -1
  466. package/dist/connections/index.d.ts +1 -1
  467. package/dist/connections/index.d.ts.map +1 -1
  468. package/dist/connections/index.js +1 -1
  469. package/dist/connections/index.js.map +1 -1
  470. package/dist/connections/runtime.d.ts +2 -0
  471. package/dist/connections/runtime.d.ts.map +1 -0
  472. package/dist/connections/runtime.js +2 -0
  473. package/dist/connections/runtime.js.map +1 -0
  474. package/dist/eject/provider-api-definitions.d.ts +34 -0
  475. package/dist/eject/provider-api-definitions.d.ts.map +1 -0
  476. package/dist/eject/provider-api-definitions.js +88 -0
  477. package/dist/eject/provider-api-definitions.js.map +1 -0
  478. package/dist/eject/remote-mcp-presets.d.ts +17 -0
  479. package/dist/eject/remote-mcp-presets.d.ts.map +1 -0
  480. package/dist/eject/remote-mcp-presets.js +81 -0
  481. package/dist/eject/remote-mcp-presets.js.map +1 -0
  482. package/dist/eject/setup-readiness-ui.d.ts +7 -0
  483. package/dist/eject/setup-readiness-ui.d.ts.map +1 -0
  484. package/dist/eject/setup-readiness-ui.js +13 -0
  485. package/dist/eject/setup-readiness-ui.js.map +1 -0
  486. package/dist/eject/workspace-connections.d.ts +11 -0
  487. package/dist/eject/workspace-connections.d.ts.map +1 -0
  488. package/dist/eject/workspace-connections.js +47 -0
  489. package/dist/eject/workspace-connections.js.map +1 -0
  490. package/dist/index.d.ts +1 -1
  491. package/dist/index.d.ts.map +1 -1
  492. package/dist/index.js +1 -1
  493. package/dist/index.js.map +1 -1
  494. package/dist/integrations/adapter-overrides.d.ts +3 -0
  495. package/dist/integrations/adapter-overrides.d.ts.map +1 -0
  496. package/dist/integrations/adapter-overrides.js +7 -0
  497. package/dist/integrations/adapter-overrides.js.map +1 -0
  498. package/dist/integrations/eject/messaging-adapters.d.ts +12 -0
  499. package/dist/integrations/eject/messaging-adapters.d.ts.map +1 -0
  500. package/dist/integrations/eject/messaging-adapters.js +49 -0
  501. package/dist/integrations/eject/messaging-adapters.js.map +1 -0
  502. package/dist/integrations/index.d.ts +5 -3
  503. package/dist/integrations/index.d.ts.map +1 -1
  504. package/dist/integrations/index.js +4 -2
  505. package/dist/integrations/index.js.map +1 -1
  506. package/dist/integrations/plugin.d.ts +32 -1
  507. package/dist/integrations/plugin.d.ts.map +1 -1
  508. package/dist/integrations/plugin.js +19 -12
  509. package/dist/integrations/plugin.js.map +1 -1
  510. package/dist/integrations/runtime.d.ts +2 -0
  511. package/dist/integrations/runtime.d.ts.map +1 -0
  512. package/dist/integrations/runtime.js +2 -0
  513. package/dist/integrations/runtime.js.map +1 -0
  514. package/dist/integrations/slack-manifest.d.ts +1 -1
  515. package/dist/integrations/slack-oauth.d.ts +1 -1
  516. package/dist/integrations/slack-oauth.d.ts.map +1 -1
  517. package/dist/integrations/slack-oauth.js +1 -0
  518. package/dist/integrations/slack-oauth.js.map +1 -1
  519. package/dist/integrations/types.d.ts +3 -1
  520. package/dist/integrations/types.d.ts.map +1 -1
  521. package/dist/integrations/types.js.map +1 -1
  522. package/dist/integrations/webhook-delivery.d.ts +23 -0
  523. package/dist/integrations/webhook-delivery.d.ts.map +1 -0
  524. package/dist/integrations/webhook-delivery.js +32 -0
  525. package/dist/integrations/webhook-delivery.js.map +1 -0
  526. package/dist/notifications/channels.d.ts.map +1 -1
  527. package/dist/notifications/channels.js +4 -9
  528. package/dist/notifications/channels.js.map +1 -1
  529. package/dist/notifications/routes.d.ts +3 -3
  530. package/dist/package-lifecycle/eject-manifest.d.ts +43 -0
  531. package/dist/package-lifecycle/eject-manifest.d.ts.map +1 -0
  532. package/dist/package-lifecycle/eject-manifest.js +219 -0
  533. package/dist/package-lifecycle/eject-manifest.js.map +1 -0
  534. package/dist/package-lifecycle/index.d.ts +1 -0
  535. package/dist/package-lifecycle/index.d.ts.map +1 -1
  536. package/dist/package-lifecycle/index.js +1 -0
  537. package/dist/package-lifecycle/index.js.map +1 -1
  538. package/dist/progress/routes.d.ts +1 -1
  539. package/dist/provider-api/actions/custom-provider-registration.d.ts +136 -0
  540. package/dist/provider-api/actions/custom-provider-registration.d.ts.map +1 -0
  541. package/dist/provider-api/actions/custom-provider-registration.js +154 -0
  542. package/dist/provider-api/actions/custom-provider-registration.js.map +1 -0
  543. package/dist/provider-api/actions/delete-staged-dataset.d.ts +1 -1
  544. package/dist/provider-api/actions/delete-staged-dataset.d.ts.map +1 -1
  545. package/dist/provider-api/actions/delete-staged-dataset.js +3 -34
  546. package/dist/provider-api/actions/delete-staged-dataset.js.map +1 -1
  547. package/dist/provider-api/actions/list-staged-datasets.d.ts +2 -3
  548. package/dist/provider-api/actions/list-staged-datasets.d.ts.map +1 -1
  549. package/dist/provider-api/actions/list-staged-datasets.js +3 -40
  550. package/dist/provider-api/actions/list-staged-datasets.js.map +1 -1
  551. package/dist/provider-api/actions/provider-api-audit.d.ts +7 -0
  552. package/dist/provider-api/actions/provider-api-audit.d.ts.map +1 -0
  553. package/dist/provider-api/actions/provider-api-audit.js +74 -0
  554. package/dist/provider-api/actions/provider-api-audit.js.map +1 -0
  555. package/dist/provider-api/actions/provider-api.d.ts +370 -0
  556. package/dist/provider-api/actions/provider-api.d.ts.map +1 -0
  557. package/dist/provider-api/actions/provider-api.js +280 -0
  558. package/dist/provider-api/actions/provider-api.js.map +1 -0
  559. package/dist/provider-api/actions/query-staged-dataset.d.ts +1 -1
  560. package/dist/provider-api/actions/query-staged-dataset.d.ts.map +1 -1
  561. package/dist/provider-api/actions/query-staged-dataset.js +3 -116
  562. package/dist/provider-api/actions/query-staged-dataset.js.map +1 -1
  563. package/dist/provider-api/actions/staged-datasets.d.ts +190 -0
  564. package/dist/provider-api/actions/staged-datasets.d.ts.map +1 -0
  565. package/dist/provider-api/actions/staged-datasets.js +210 -0
  566. package/dist/provider-api/actions/staged-datasets.js.map +1 -0
  567. package/dist/provider-api/corpus-jobs.d.ts +2 -2
  568. package/dist/provider-api/gong.d.ts +44 -0
  569. package/dist/provider-api/gong.d.ts.map +1 -0
  570. package/dist/provider-api/gong.js +56 -0
  571. package/dist/provider-api/gong.js.map +1 -0
  572. package/dist/provider-api/index.d.ts +6 -2
  573. package/dist/provider-api/index.d.ts.map +1 -1
  574. package/dist/provider-api/index.js +25 -12
  575. package/dist/provider-api/index.js.map +1 -1
  576. package/dist/provider-api/runtime.d.ts +2 -0
  577. package/dist/provider-api/runtime.d.ts.map +1 -0
  578. package/dist/provider-api/runtime.js +2 -0
  579. package/dist/provider-api/runtime.js.map +1 -0
  580. package/dist/scripts/docs/source-search.d.ts +2 -1
  581. package/dist/scripts/docs/source-search.d.ts.map +1 -1
  582. package/dist/scripts/docs/source-search.js +2 -1
  583. package/dist/scripts/docs/source-search.js.map +1 -1
  584. package/dist/secrets/routes.d.ts +9 -9
  585. package/dist/server/google-oauth-credentials.d.ts +35 -0
  586. package/dist/server/google-oauth-credentials.d.ts.map +1 -1
  587. package/dist/server/google-oauth-credentials.js +48 -2
  588. package/dist/server/google-oauth-credentials.js.map +1 -1
  589. package/dist/server/index.d.ts +1 -1
  590. package/dist/server/index.d.ts.map +1 -1
  591. package/dist/server/index.js +1 -1
  592. package/dist/server/index.js.map +1 -1
  593. package/dist/server/transcribe-voice.d.ts +1 -1
  594. package/dist/setup-connections/index.d.ts +1 -1
  595. package/dist/setup-connections/index.d.ts.map +1 -1
  596. package/dist/setup-connections/index.js +1 -1
  597. package/dist/setup-connections/index.js.map +1 -1
  598. package/dist/shared/merge-by-id.d.ts +5 -0
  599. package/dist/shared/merge-by-id.d.ts.map +1 -0
  600. package/dist/shared/merge-by-id.js +7 -0
  601. package/dist/shared/merge-by-id.js.map +1 -0
  602. package/dist/styles/chat-history-list.css +1 -313
  603. package/dist/templates/chat/.agents/skills/actions/SKILL.md +32 -12
  604. package/dist/templates/chat/.agents/skills/agent-native-docs/SKILL.md +21 -9
  605. package/dist/templates/chat/.agents/skills/customizing-agent-native/SKILL.md +145 -0
  606. package/dist/templates/chat/.agents/skills/self-modifying-code/SKILL.md +14 -2
  607. package/dist/templates/chat/.agents/skills/upgrade-agent-native/SKILL.md +6 -0
  608. package/dist/templates/chat/AGENTS.md +6 -2
  609. package/dist/templates/chat/app/components/layout/Sidebar.tsx +51 -157
  610. package/dist/templates/default/.agents/skills/actions/SKILL.md +32 -12
  611. package/dist/templates/default/.agents/skills/agent-native-docs/SKILL.md +21 -9
  612. package/dist/templates/default/.agents/skills/customizing-agent-native/SKILL.md +145 -0
  613. package/dist/templates/default/.agents/skills/integration-webhooks/SKILL.md +323 -0
  614. package/dist/templates/default/.agents/skills/onboarding/SKILL.md +56 -0
  615. package/dist/templates/default/.agents/skills/secrets/SKILL.md +273 -0
  616. package/dist/templates/default/.agents/skills/self-modifying-code/SKILL.md +14 -2
  617. package/dist/templates/default/.agents/skills/upgrade-agent-native/SKILL.md +6 -0
  618. package/dist/templates/default/AGENTS.md +26 -18
  619. package/dist/templates/headless/.agents/skills/actions/SKILL.md +512 -0
  620. package/dist/templates/headless/.agents/skills/agent-native-docs/SKILL.md +21 -9
  621. package/dist/templates/headless/.agents/skills/customizing-agent-native/SKILL.md +145 -0
  622. package/dist/templates/headless/.agents/skills/integration-webhooks/SKILL.md +323 -0
  623. package/dist/templates/headless/.agents/skills/secrets/SKILL.md +273 -0
  624. package/dist/templates/headless/.agents/skills/upgrade-agent-native/SKILL.md +6 -0
  625. package/dist/templates/headless/AGENTS.md +8 -0
  626. package/dist/templates/workspace-core/.agents/skills/actions/SKILL.md +32 -12
  627. package/dist/templates/workspace-core/.agents/skills/agent-native-docs/SKILL.md +21 -9
  628. package/dist/templates/workspace-core/.agents/skills/agent-native-toolkit/SKILL.md +7 -0
  629. package/dist/templates/workspace-core/.agents/skills/customizing-agent-native/SKILL.md +145 -0
  630. package/dist/templates/workspace-core/.agents/skills/self-modifying-code/SKILL.md +14 -2
  631. package/dist/templates/workspace-core/.agents/skills/upgrade-agent-native/SKILL.md +6 -0
  632. package/dist/templates/workspace-core/AGENTS.md +4 -0
  633. package/dist/templates/workspace-root/AGENTS.md +4 -0
  634. package/dist/vite/client.d.ts.map +1 -1
  635. package/dist/vite/client.js +22 -2
  636. package/dist/vite/client.js.map +1 -1
  637. package/docs/AGENTS.md +7 -0
  638. package/docs/content/agent-native-toolkit.mdx +38 -0
  639. package/docs/content/integrations.mdx +63 -2
  640. package/docs/content/package-lifecycle.mdx +54 -4
  641. package/docs/design/provider-integration-authority.md +117 -0
  642. package/package.json +20 -2
  643. package/src/a2a/agent-card.ts +83 -0
  644. package/src/a2a/artifact-response.ts +1648 -0
  645. package/src/a2a/auth-policy.ts +66 -0
  646. package/src/a2a/caller-auth.ts +102 -0
  647. package/src/a2a/client.ts +876 -0
  648. package/src/a2a/correlation.ts +50 -0
  649. package/src/a2a/handlers.ts +1285 -0
  650. package/src/a2a/index.ts +50 -0
  651. package/src/a2a/invoke.ts +348 -0
  652. package/src/a2a/response-text.ts +53 -0
  653. package/src/a2a/server.ts +586 -0
  654. package/src/a2a/task-store.ts +917 -0
  655. package/src/a2a/types.ts +221 -0
  656. package/src/a2a-claims.ts +52 -0
  657. package/src/action-change-marker.ts +74 -0
  658. package/src/action-ui.ts +38 -0
  659. package/src/action.ts +1406 -0
  660. package/src/adapters/cli/index.ts +6 -0
  661. package/src/adapters/cli/registry.ts +73 -0
  662. package/src/adapters/cli/shell-adapter.ts +92 -0
  663. package/src/adapters/cli/types.ts +27 -0
  664. package/src/agent/action-continuation-guidance.ts +38 -0
  665. package/src/agent/app-model-defaults.ts +201 -0
  666. package/src/agent/context-xray/actions/context-evict.ts +56 -0
  667. package/src/agent/context-xray/actions/context-manifest-get.ts +75 -0
  668. package/src/agent/context-xray/actions/context-pin.ts +56 -0
  669. package/src/agent/context-xray/actions/context-preview-get.ts +134 -0
  670. package/src/agent/context-xray/actions/context-report.ts +75 -0
  671. package/src/agent/context-xray/actions/context-restore.ts +51 -0
  672. package/src/agent/context-xray/actions/errors.ts +40 -0
  673. package/src/agent/context-xray/apply-directives.ts +137 -0
  674. package/src/agent/context-xray/directives-store.ts +178 -0
  675. package/src/agent/context-xray/identity.ts +37 -0
  676. package/src/agent/context-xray/manifest.ts +284 -0
  677. package/src/agent/context-xray/migrations.ts +32 -0
  678. package/src/agent/context-xray/plugin.ts +23 -0
  679. package/src/agent/context-xray/schema.ts +17 -0
  680. package/src/agent/context-xray/segments.ts +194 -0
  681. package/src/agent/context-xray/tokenize.ts +93 -0
  682. package/src/agent/default-model.ts +5 -0
  683. package/src/agent/durable-background.ts +547 -0
  684. package/src/agent/engine/ai-sdk-engine.ts +565 -0
  685. package/src/agent/engine/anthropic-engine.ts +320 -0
  686. package/src/agent/engine/builder-engine.ts +1110 -0
  687. package/src/agent/engine/builder-gateway-headers.ts +44 -0
  688. package/src/agent/engine/builtin.ts +122 -0
  689. package/src/agent/engine/context-directives-transform.ts +73 -0
  690. package/src/agent/engine/continuation-dispatch-retry.ts +168 -0
  691. package/src/agent/engine/credential-errors.ts +69 -0
  692. package/src/agent/engine/index.ts +54 -0
  693. package/src/agent/engine/openai-compatible-endpoint.ts +25 -0
  694. package/src/agent/engine/output-tokens.ts +181 -0
  695. package/src/agent/engine/provider-env-vars.ts +69 -0
  696. package/src/agent/engine/registry.ts +853 -0
  697. package/src/agent/engine/tool-call-journal-seed.ts +85 -0
  698. package/src/agent/engine/translate-ai-sdk.ts +407 -0
  699. package/src/agent/engine/translate-anthropic.ts +611 -0
  700. package/src/agent/engine/types.ts +310 -0
  701. package/src/agent/harness/acp-adapter.ts +893 -0
  702. package/src/agent/harness/acp-builtin.ts +70 -0
  703. package/src/agent/harness/ai-sdk-adapter.ts +509 -0
  704. package/src/agent/harness/background.ts +365 -0
  705. package/src/agent/harness/builtin.ts +50 -0
  706. package/src/agent/harness/index.ts +86 -0
  707. package/src/agent/harness/lifecycle.ts +498 -0
  708. package/src/agent/harness/registry.ts +97 -0
  709. package/src/agent/harness/runner.ts +182 -0
  710. package/src/agent/harness/store.ts +466 -0
  711. package/src/agent/harness/translate.ts +130 -0
  712. package/src/agent/harness/types.ts +129 -0
  713. package/src/agent/index.ts +32 -0
  714. package/src/agent/loop-settings.ts +186 -0
  715. package/src/agent/model-config.ts +363 -0
  716. package/src/agent/observational-memory/compactor.ts +78 -0
  717. package/src/agent/observational-memory/config.ts +78 -0
  718. package/src/agent/observational-memory/index.ts +79 -0
  719. package/src/agent/observational-memory/internal-run.ts +89 -0
  720. package/src/agent/observational-memory/message-text.ts +49 -0
  721. package/src/agent/observational-memory/migrations.ts +44 -0
  722. package/src/agent/observational-memory/observer.ts +128 -0
  723. package/src/agent/observational-memory/plugin.ts +35 -0
  724. package/src/agent/observational-memory/prompts.ts +53 -0
  725. package/src/agent/observational-memory/read.ts +131 -0
  726. package/src/agent/observational-memory/reflector.ts +119 -0
  727. package/src/agent/observational-memory/schema.ts +48 -0
  728. package/src/agent/observational-memory/store.ts +275 -0
  729. package/src/agent/observational-memory/types.ts +65 -0
  730. package/src/agent/processors.ts +209 -0
  731. package/src/agent/production-agent.ts +8254 -0
  732. package/src/agent/run-loop-with-resume.ts +394 -0
  733. package/src/agent/run-manager.ts +1825 -0
  734. package/src/agent/run-ownership.ts +75 -0
  735. package/src/agent/run-store.ts +2601 -0
  736. package/src/agent/runtime-context.ts +169 -0
  737. package/src/agent/thread-data-builder.ts +1584 -0
  738. package/src/agent/tool-call-journal.ts +368 -0
  739. package/src/agent/tool-error-redaction.ts +52 -0
  740. package/src/agent/tool-result-images.ts +178 -0
  741. package/src/agent/tool-search.ts +376 -0
  742. package/src/agent/types.ts +372 -0
  743. package/src/agent-native/index.ts +198 -0
  744. package/src/agent-web/config.ts +253 -0
  745. package/src/agent-web/generator.ts +382 -0
  746. package/src/agent-web/index.ts +36 -0
  747. package/src/appearance/actions/change-appearance.ts +35 -0
  748. package/src/application-state/emitter.ts +81 -0
  749. package/src/application-state/handlers.ts +121 -0
  750. package/src/application-state/index.ts +44 -0
  751. package/src/application-state/script-helpers.ts +155 -0
  752. package/src/application-state/store.ts +274 -0
  753. package/src/assets/branding/agent-native.icon/Assets/background.svg +3 -0
  754. package/src/assets/branding/agent-native.icon/Assets/foreground.svg +12 -0
  755. package/src/assets/branding/agent-native.icon/icon.json +49 -0
  756. package/src/assets/branding/favicon.png +0 -0
  757. package/src/assets/branding/favicon.svg +1 -0
  758. package/src/assets/branding/icon-on-dark.svg +10 -0
  759. package/src/assets/branding/icon-on-light.svg +10 -0
  760. package/src/assets/branding/mac-app-icon.svg +1 -0
  761. package/src/assets/branding/slack-bot/agent-native-1024.png +0 -0
  762. package/src/assets/branding/slack-bot/agent-native-512.png +0 -0
  763. package/src/assets/branding/tray-icon.svg +6 -0
  764. package/src/assets/branding/wordmark-on-dark.svg +21 -0
  765. package/src/assets/branding/wordmark-on-light.svg +21 -0
  766. package/src/assets/fonts/LICENSE_LIBERATION +96 -0
  767. package/src/assets/fonts/LICENSE_NOTO_NASKH_ARABIC +93 -0
  768. package/src/assets/fonts/LiberationSans-Bold.ttf +0 -0
  769. package/src/assets/fonts/LiberationSans-Regular.ttf +0 -0
  770. package/src/assets/fonts/NotoNaskhArabic-Variable.ttf +0 -0
  771. package/src/audit/actions/export-audit-events.ts +162 -0
  772. package/src/audit/actions/get-audit-event.ts +24 -0
  773. package/src/audit/actions/list-audit-events.ts +66 -0
  774. package/src/audit/cleanup-job.ts +100 -0
  775. package/src/audit/config.ts +90 -0
  776. package/src/audit/index.ts +43 -0
  777. package/src/audit/record.ts +180 -0
  778. package/src/audit/redact.ts +109 -0
  779. package/src/audit/store.ts +346 -0
  780. package/src/audit/types.ts +141 -0
  781. package/src/automation/index.ts +802 -0
  782. package/src/brand-kit/brand-signals.ts +124 -0
  783. package/src/brand-kit/fig/index.ts +64 -0
  784. package/src/brand-kit/index.ts +72 -0
  785. package/src/brand-kit/types.ts +113 -0
  786. package/src/browser-sessions/actions.ts +302 -0
  787. package/src/browser-sessions/routes.ts +234 -0
  788. package/src/browser-sessions/store.ts +679 -0
  789. package/src/browser-sessions/types.ts +84 -0
  790. package/src/changelog/parse.ts +328 -0
  791. package/src/chat-threads/emitter.ts +22 -0
  792. package/src/chat-threads/schema.ts +43 -0
  793. package/src/chat-threads/store.ts +1311 -0
  794. package/src/checkpoints/index.ts +15 -0
  795. package/src/checkpoints/service.ts +142 -0
  796. package/src/checkpoints/store.ts +153 -0
  797. package/src/cli/add.ts +425 -0
  798. package/src/cli/agent.ts +424 -0
  799. package/src/cli/agents.ts +122 -0
  800. package/src/cli/app-skill.ts +1455 -0
  801. package/src/cli/atomic-json-file.ts +324 -0
  802. package/src/cli/audit-agent-web.ts +324 -0
  803. package/src/cli/changelog.ts +199 -0
  804. package/src/cli/claude-code-participant.ts +515 -0
  805. package/src/cli/code-agent-commands.ts +270 -0
  806. package/src/cli/code-agent-connector.ts +1109 -0
  807. package/src/cli/code-agent-executor.ts +1970 -0
  808. package/src/cli/code-agent-output-smoother.ts +140 -0
  809. package/src/cli/code-agent-runs.concurrent-worker.ts +33 -0
  810. package/src/cli/code-agent-runs.ts +548 -0
  811. package/src/cli/code.ts +1805 -0
  812. package/src/cli/codex-cli-participant.ts +496 -0
  813. package/src/cli/connect.ts +2714 -0
  814. package/src/cli/content-local.ts +442 -0
  815. package/src/cli/context-xray-local.ts +2193 -0
  816. package/src/cli/create-workspace.ts +30 -0
  817. package/src/cli/create.ts +2247 -0
  818. package/src/cli/deploy-build.ts +50 -0
  819. package/src/cli/design-connect.ts +3187 -0
  820. package/src/cli/doctor.ts +472 -0
  821. package/src/cli/eject.ts +1594 -0
  822. package/src/cli/eval.ts +134 -0
  823. package/src/cli/gateway-helpers.ts +70 -0
  824. package/src/cli/index.ts +1217 -0
  825. package/src/cli/info.ts +105 -0
  826. package/src/cli/invoke.ts +288 -0
  827. package/src/cli/mcp-config-writers.ts +857 -0
  828. package/src/cli/mcp.ts +594 -0
  829. package/src/cli/migrate.ts +1813 -0
  830. package/src/cli/migration-codemod.ts +646 -0
  831. package/src/cli/multi-frontier-runs.ts +1952 -0
  832. package/src/cli/package-lifecycle.ts +823 -0
  833. package/src/cli/plan-blocks.ts +143 -0
  834. package/src/cli/plan-local.ts +3189 -0
  835. package/src/cli/plan-publish-store.ts +138 -0
  836. package/src/cli/pr-visual-recap-workflow.ts +2 -0
  837. package/src/cli/recap.ts +5 -0
  838. package/src/cli/setup-agents.ts +120 -0
  839. package/src/cli/skills-content/assets-skill.ts +83 -0
  840. package/src/cli/skills-content/canvas.ts +153 -0
  841. package/src/cli/skills-content/connection.ts +52 -0
  842. package/src/cli/skills-content/content-skill.ts +120 -0
  843. package/src/cli/skills-content/design-exploration-skill.ts +118 -0
  844. package/src/cli/skills-content/design-visual-edit-skill.ts +228 -0
  845. package/src/cli/skills-content/document-quality.ts +196 -0
  846. package/src/cli/skills-content/exemplar.ts +69 -0
  847. package/src/cli/skills-content/help.ts +77 -0
  848. package/src/cli/skills-content/index.ts +22 -0
  849. package/src/cli/skills-content/local-files.ts +100 -0
  850. package/src/cli/skills-content/plan-setup-auth.ts +80 -0
  851. package/src/cli/skills-content/visual-plan-skill.ts +493 -0
  852. package/src/cli/skills-content/visual-recap-skill.ts +553 -0
  853. package/src/cli/skills-content/visualize-repo-skill.ts +93 -0
  854. package/src/cli/skills-content/wireframe.ts +349 -0
  855. package/src/cli/skills.ts +4340 -0
  856. package/src/cli/sync-builder-starter-manifest.ts +631 -0
  857. package/src/cli/telemetry.ts +136 -0
  858. package/src/cli/templates-meta.ts +269 -0
  859. package/src/cli/upgrade.ts +956 -0
  860. package/src/cli/visualize-repo.ts +715 -0
  861. package/src/cli/workspace-dev.ts +1486 -0
  862. package/src/cli/workspacify.ts +258 -0
  863. package/src/client/AgentAskPopover.tsx +89 -0
  864. package/src/client/AgentChatHome.tsx +66 -0
  865. package/src/client/AgentNative.tsx +161 -0
  866. package/src/client/AgentNativeEmbedded.tsx +288 -0
  867. package/src/client/AgentNativeFrame.tsx +151 -0
  868. package/src/client/AgentPanel.tsx +3437 -0
  869. package/src/client/AgentTaskCard.tsx +273 -0
  870. package/src/client/AppearancePicker.tsx +79 -0
  871. package/src/client/AssistantChat.tsx +5793 -0
  872. package/src/client/ClientOnly.tsx +22 -0
  873. package/src/client/CommandMenu.tsx +726 -0
  874. package/src/client/ConnectBuilderCard.tsx +390 -0
  875. package/src/client/DefaultSpinner.tsx +47 -0
  876. package/src/client/ErrorBoundary.tsx +359 -0
  877. package/src/client/ErrorReportActions.tsx +69 -0
  878. package/src/client/FeedbackButton.tsx +553 -0
  879. package/src/client/HighlightedCodeBlock.tsx +173 -0
  880. package/src/client/IframeEmbed.tsx +151 -0
  881. package/src/client/KeepTabOpenNotice.tsx +181 -0
  882. package/src/client/MultiTabAssistantChat.tsx +2576 -0
  883. package/src/client/NewWorkspaceAppFlow.tsx +525 -0
  884. package/src/client/PoweredByBadge.tsx +284 -0
  885. package/src/client/RunStuckBanner.tsx +431 -0
  886. package/src/client/StarfieldBackground.tsx +466 -0
  887. package/src/client/Turnstile.tsx +125 -0
  888. package/src/client/active-run-state.ts +139 -0
  889. package/src/client/agent-chat/index.ts +279 -0
  890. package/src/client/agent-chat-adapter.ts +3692 -0
  891. package/src/client/agent-chat.ts +1233 -0
  892. package/src/client/agent-engine-key.ts +122 -0
  893. package/src/client/agent-page/AgentContextTab.tsx +487 -0
  894. package/src/client/agent-page/AgentEmptyState.tsx +44 -0
  895. package/src/client/agent-page/AgentJobsTab.tsx +441 -0
  896. package/src/client/agent-page/AgentTabFrame.tsx +39 -0
  897. package/src/client/agent-page/AgentTabsPage.tsx +1096 -0
  898. package/src/client/agent-page/types.ts +18 -0
  899. package/src/client/agent-page/use-jobs.ts +150 -0
  900. package/src/client/agent-sidebar-state.ts +166 -0
  901. package/src/client/analytics/index.ts +40 -0
  902. package/src/client/analytics-session.ts +70 -0
  903. package/src/client/analytics.ts +1757 -0
  904. package/src/client/api-path.ts +124 -0
  905. package/src/client/app-providers.tsx +230 -0
  906. package/src/client/appearance.ts +130 -0
  907. package/src/client/application-state.ts +154 -0
  908. package/src/client/assistant-ui-recovery.tsx +205 -0
  909. package/src/client/automation/index.ts +4 -0
  910. package/src/client/automation.ts +22 -0
  911. package/src/client/blocks/AiEditableField.tsx +30 -0
  912. package/src/client/blocks/BlockView.tsx +145 -0
  913. package/src/client/blocks/RegistryBlockDataProvider.tsx +121 -0
  914. package/src/client/blocks/SchemaBlockEditor.tsx +457 -0
  915. package/src/client/blocks/agent.ts +95 -0
  916. package/src/client/blocks/code-block-direction.ts +21 -0
  917. package/src/client/blocks/index.ts +308 -0
  918. package/src/client/blocks/library/AnnotatedCodeBlock.tsx +710 -0
  919. package/src/client/blocks/library/ApiEndpointBlock.tsx +1120 -0
  920. package/src/client/blocks/library/DataModelBlock.tsx +775 -0
  921. package/src/client/blocks/library/DiffBlock.tsx +1854 -0
  922. package/src/client/blocks/library/FileTreeBlock.tsx +868 -0
  923. package/src/client/blocks/library/HighlightedCode.tsx +260 -0
  924. package/src/client/blocks/library/JsonExplorerBlock.tsx +608 -0
  925. package/src/client/blocks/library/MermaidBlock.tsx +362 -0
  926. package/src/client/blocks/library/OpenApiSpecBlock.tsx +998 -0
  927. package/src/client/blocks/library/annotated-code.config.ts +101 -0
  928. package/src/client/blocks/library/annotation-rail.tsx +1020 -0
  929. package/src/client/blocks/library/api-endpoint.config.ts +207 -0
  930. package/src/client/blocks/library/block-copy.ts +399 -0
  931. package/src/client/blocks/library/callout.config.ts +57 -0
  932. package/src/client/blocks/library/callout.tsx +149 -0
  933. package/src/client/blocks/library/checklist.config.ts +56 -0
  934. package/src/client/blocks/library/checklist.tsx +208 -0
  935. package/src/client/blocks/library/code-filename-label.tsx +59 -0
  936. package/src/client/blocks/library/code-highlight.tsx +178 -0
  937. package/src/client/blocks/library/code-tabs.config.ts +70 -0
  938. package/src/client/blocks/library/code-tabs.tsx +606 -0
  939. package/src/client/blocks/library/code.config.ts +69 -0
  940. package/src/client/blocks/library/code.tsx +440 -0
  941. package/src/client/blocks/library/columns.config.ts +85 -0
  942. package/src/client/blocks/library/columns.tsx +334 -0
  943. package/src/client/blocks/library/data-model.config.ts +152 -0
  944. package/src/client/blocks/library/dev-doc-ui.tsx +191 -0
  945. package/src/client/blocks/library/diagram.config.ts +222 -0
  946. package/src/client/blocks/library/diagram.tsx +958 -0
  947. package/src/client/blocks/library/diff.config.ts +115 -0
  948. package/src/client/blocks/library/file-tree.config.ts +92 -0
  949. package/src/client/blocks/library/html.config.ts +79 -0
  950. package/src/client/blocks/library/html.tsx +258 -0
  951. package/src/client/blocks/library/json-explorer.config.ts +74 -0
  952. package/src/client/blocks/library/mermaid.config.ts +49 -0
  953. package/src/client/blocks/library/narrow-container.tsx +37 -0
  954. package/src/client/blocks/library/openapi-spec.config.ts +66 -0
  955. package/src/client/blocks/library/question-form.config.ts +127 -0
  956. package/src/client/blocks/library/question-form.tsx +944 -0
  957. package/src/client/blocks/library/sanitize-html.ts +343 -0
  958. package/src/client/blocks/library/server-specs.ts +338 -0
  959. package/src/client/blocks/library/specs.tsx +308 -0
  960. package/src/client/blocks/library/table.config.ts +61 -0
  961. package/src/client/blocks/library/table.tsx +449 -0
  962. package/src/client/blocks/library/tabs.config.ts +96 -0
  963. package/src/client/blocks/library/tabs.tsx +665 -0
  964. package/src/client/blocks/library/wireframe-icons.ts +210 -0
  965. package/src/client/blocks/library/wireframe-kit.tsx +1850 -0
  966. package/src/client/blocks/library/wireframe.config.ts +539 -0
  967. package/src/client/blocks/library/wireframe.tsx +535 -0
  968. package/src/client/blocks/mdx.ts +364 -0
  969. package/src/client/blocks/provider.tsx +51 -0
  970. package/src/client/blocks/registry.ts +83 -0
  971. package/src/client/blocks/schema-form/introspect.ts +201 -0
  972. package/src/client/blocks/server.ts +170 -0
  973. package/src/client/blocks/types.ts +415 -0
  974. package/src/client/browser-session-bridge.ts +548 -0
  975. package/src/client/browser-tab-id.ts +36 -0
  976. package/src/client/builder-frame.ts +194 -0
  977. package/src/client/builder-mark.tsx +21 -0
  978. package/src/client/changelog/Changelog.tsx +333 -0
  979. package/src/client/changelog/index.ts +1 -0
  980. package/src/client/chat/ChatHistoryList.tsx +7 -0
  981. package/src/client/chat/attachment-adapters.ts +426 -0
  982. package/src/client/chat/connectors.ts +1579 -0
  983. package/src/client/chat/index.ts +160 -0
  984. package/src/client/chat/markdown-renderer.tsx +693 -0
  985. package/src/client/chat/message-components.tsx +1326 -0
  986. package/src/client/chat/repo-helpers.ts +281 -0
  987. package/src/client/chat/run-recovery.tsx +994 -0
  988. package/src/client/chat/runtime.ts +1810 -0
  989. package/src/client/chat/tool-call-display.tsx +1270 -0
  990. package/src/client/chat/tool-render-registry.tsx +144 -0
  991. package/src/client/chat/use-agent-chat-lifecycle-tracking.ts +74 -0
  992. package/src/client/chat/use-reconnect-reader-owner.ts +28 -0
  993. package/src/client/chat/widgets/DataChartRenderer.tsx +242 -0
  994. package/src/client/chat/widgets/DataChartWidget.tsx +51 -0
  995. package/src/client/chat/widgets/DataInsightsWidget.tsx +59 -0
  996. package/src/client/chat/widgets/DataTableWidget.tsx +240 -0
  997. package/src/client/chat/widgets/InlineExtensionWidget.tsx +60 -0
  998. package/src/client/chat/widgets/builtin-tool-renderers.tsx +213 -0
  999. package/src/client/chat/widgets/data-widget-types.ts +1 -0
  1000. package/src/client/chat/widgets/inline-extension-result.ts +86 -0
  1001. package/src/client/chat-model-groups.ts +171 -0
  1002. package/src/client/chat-thread-url.ts +11 -0
  1003. package/src/client/chat-view-transition.ts +213 -0
  1004. package/src/client/client-action.ts +21 -0
  1005. package/src/client/client-bootstrap.ts +7 -0
  1006. package/src/client/client-surface.ts +41 -0
  1007. package/src/client/clipboard.ts +89 -0
  1008. package/src/client/code-agent-chat-adapter.ts +537 -0
  1009. package/src/client/collab/index.ts +60 -0
  1010. package/src/client/command-navigation/index.ts +15 -0
  1011. package/src/client/comments-review/index.ts +1 -0
  1012. package/src/client/components/AgentPresenceChip.tsx +4 -0
  1013. package/src/client/components/ApiKeySettings.tsx +309 -0
  1014. package/src/client/components/CodeAgentIndicator.tsx +59 -0
  1015. package/src/client/components/CodeRequiredDialog.tsx +470 -0
  1016. package/src/client/components/LiveCursorOverlay.tsx +5 -0
  1017. package/src/client/components/MissingKeyCard.tsx +61 -0
  1018. package/src/client/components/PresenceBar.tsx +4 -0
  1019. package/src/client/components/RecentEditHighlights.tsx +4 -0
  1020. package/src/client/components/RemoteSelectionRings.tsx +5 -0
  1021. package/src/client/components/icons/AgentNativeIcon.tsx +46 -0
  1022. package/src/client/components/ui/dialog.tsx +1 -0
  1023. package/src/client/components/ui/dropdown-menu.tsx +1 -0
  1024. package/src/client/components/ui/hover-card.tsx +1 -0
  1025. package/src/client/components/ui/message-scroller.tsx +131 -0
  1026. package/src/client/components/ui/popover.tsx +1 -0
  1027. package/src/client/components/ui/sheet.tsx +1 -0
  1028. package/src/client/components/ui/tooltip.tsx +1 -0
  1029. package/src/client/composer/index.ts +11 -0
  1030. package/src/client/composer/runtime-adapters.tsx +123 -0
  1031. package/src/client/composer/use-mention-search.ts +7 -0
  1032. package/src/client/composer/wired-components.tsx +53 -0
  1033. package/src/client/context-xray/ContextMeter.tsx +124 -0
  1034. package/src/client/context-xray/ContextSegmentRow.tsx +27 -0
  1035. package/src/client/context-xray/ContextTreemap.tsx +24 -0
  1036. package/src/client/context-xray/ContextXRayPanel.tsx +59 -0
  1037. package/src/client/context-xray/SegmentProvenancePopover.tsx +18 -0
  1038. package/src/client/context-xray/format.ts +27 -0
  1039. package/src/client/conversation/AgentConversation.tsx +555 -0
  1040. package/src/client/conversation/code-agent-transcript.ts +283 -0
  1041. package/src/client/conversation/index.ts +22 -0
  1042. package/src/client/conversation/types.ts +85 -0
  1043. package/src/client/conversation/use-near-bottom-autoscroll.ts +278 -0
  1044. package/src/client/create-query-client.ts +86 -0
  1045. package/src/client/db-admin/DataGrid.tsx +551 -0
  1046. package/src/client/db-admin/DbAdminPage.tsx +218 -0
  1047. package/src/client/db-admin/DevDatabaseLink.tsx +16 -0
  1048. package/src/client/db-admin/EditableCell.tsx +451 -0
  1049. package/src/client/db-admin/FilterBar.tsx +203 -0
  1050. package/src/client/db-admin/ResultsGrid.tsx +114 -0
  1051. package/src/client/db-admin/RowSidePanel.tsx +337 -0
  1052. package/src/client/db-admin/SqlEditor.tsx +840 -0
  1053. package/src/client/db-admin/TableBrowser.tsx +212 -0
  1054. package/src/client/db-admin/TableEditor.tsx +760 -0
  1055. package/src/client/db-admin/cell-format.ts +246 -0
  1056. package/src/client/db-admin/changeset.ts +296 -0
  1057. package/src/client/db-admin/export-utils.ts +78 -0
  1058. package/src/client/db-admin/index.ts +33 -0
  1059. package/src/client/db-admin/sql-storage.ts +134 -0
  1060. package/src/client/db-admin/storage.ts +68 -0
  1061. package/src/client/db-admin/useAgentSync.ts +226 -0
  1062. package/src/client/db-admin/useDbAdmin.ts +294 -0
  1063. package/src/client/dev-overlay/DevOverlay.tsx +576 -0
  1064. package/src/client/dev-overlay/builtins.ts +40 -0
  1065. package/src/client/dev-overlay/index.ts +23 -0
  1066. package/src/client/dev-overlay/registry.ts +67 -0
  1067. package/src/client/dev-overlay/types.ts +64 -0
  1068. package/src/client/dev-overlay/use-dev-option.ts +78 -0
  1069. package/src/client/dev-overlay/use-dev-overlay-shortcut.ts +31 -0
  1070. package/src/client/dynamic-suggestions.ts +455 -0
  1071. package/src/client/embed-auth.ts +544 -0
  1072. package/src/client/embed.ts +54 -0
  1073. package/src/client/error-capture.ts +690 -0
  1074. package/src/client/error-format.ts +211 -0
  1075. package/src/client/error-reporting.ts +100 -0
  1076. package/src/client/extensions/AgentNativeExtensionFrame.e2e-host.tsx +136 -0
  1077. package/src/client/extensions/AgentNativeExtensionFrame.tsx +708 -0
  1078. package/src/client/extensions/EmbeddedExtension.tsx +604 -0
  1079. package/src/client/extensions/ExtensionEditor.tsx +450 -0
  1080. package/src/client/extensions/ExtensionQueryErrorState.tsx +47 -0
  1081. package/src/client/extensions/ExtensionSlot.tsx +345 -0
  1082. package/src/client/extensions/ExtensionViewer.tsx +1502 -0
  1083. package/src/client/extensions/ExtensionViewerPage.tsx +32 -0
  1084. package/src/client/extensions/ExtensionsListPage.tsx +432 -0
  1085. package/src/client/extensions/ExtensionsSidebarSection.tsx +1259 -0
  1086. package/src/client/extensions/InlineExtensionFrame.tsx +660 -0
  1087. package/src/client/extensions/agent-native-extension-runtime.ts +495 -0
  1088. package/src/client/extensions/delete-extension.ts +76 -0
  1089. package/src/client/extensions/extension-load-error.ts +26 -0
  1090. package/src/client/extensions/extension-order.ts +49 -0
  1091. package/src/client/extensions/extension-popularity.ts +61 -0
  1092. package/src/client/extensions/iframe-bridge.ts +377 -0
  1093. package/src/client/extensions/index.ts +84 -0
  1094. package/src/client/extensions/portable-extension.ts +712 -0
  1095. package/src/client/feature-flags/FeatureFlagsPanel.tsx +519 -0
  1096. package/src/client/feature-flags/helpers.ts +77 -0
  1097. package/src/client/feature-flags/index.ts +13 -0
  1098. package/src/client/feature-flags/types.ts +29 -0
  1099. package/src/client/feature-flags/use-feature-flag.ts +26 -0
  1100. package/src/client/feedback-context.ts +90 -0
  1101. package/src/client/frame-protocol.ts +168 -0
  1102. package/src/client/frame.ts +329 -0
  1103. package/src/client/guided-questions.tsx +1152 -0
  1104. package/src/client/history/VersionHistoryPanel.tsx +175 -0
  1105. package/src/client/history/index.ts +21 -0
  1106. package/src/client/history/use-history.ts +114 -0
  1107. package/src/client/hooks/index.ts +46 -0
  1108. package/src/client/host/index.ts +170 -0
  1109. package/src/client/host-bridge.ts +1272 -0
  1110. package/src/client/host-tools.ts +190 -0
  1111. package/src/client/i18n.tsx +798 -0
  1112. package/src/client/index.ts +370 -0
  1113. package/src/client/integrations/IntegrationCard.tsx +186 -0
  1114. package/src/client/integrations/IntegrationsPanel.tsx +633 -0
  1115. package/src/client/integrations/api.ts +295 -0
  1116. package/src/client/integrations/index.ts +29 -0
  1117. package/src/client/integrations/useIntegrationStatus.ts +52 -0
  1118. package/src/client/mcp-app-host.ts +720 -0
  1119. package/src/client/mcp-apps/McpAppRenderer.tsx +760 -0
  1120. package/src/client/navigation/index.ts +54 -0
  1121. package/src/client/notifications/NotificationsBell.tsx +383 -0
  1122. package/src/client/notifications/index.ts +1 -0
  1123. package/src/client/observability/ObservabilityDashboard.tsx +890 -0
  1124. package/src/client/observability/ThumbsFeedback.tsx +160 -0
  1125. package/src/client/observability/index.ts +20 -0
  1126. package/src/client/observability/useObservability.ts +266 -0
  1127. package/src/client/onboarding/OnboardingBanner.tsx +73 -0
  1128. package/src/client/onboarding/OnboardingPanel.tsx +1036 -0
  1129. package/src/client/onboarding/SetupButton.tsx +64 -0
  1130. package/src/client/onboarding/index.ts +25 -0
  1131. package/src/client/onboarding/use-onboarding.ts +164 -0
  1132. package/src/client/onboarding/use-preview-mode.ts +40 -0
  1133. package/src/client/org/InvitationBanner.tsx +148 -0
  1134. package/src/client/org/OrgSwitcher.tsx +754 -0
  1135. package/src/client/org/RequireActiveOrg.tsx +337 -0
  1136. package/src/client/org/TeamPage.tsx +1432 -0
  1137. package/src/client/org/hooks.ts +359 -0
  1138. package/src/client/org/index.ts +70 -0
  1139. package/src/client/org/workspace-app-links.ts +367 -0
  1140. package/src/client/org-team/index.ts +1 -0
  1141. package/src/client/progress/RunsTray.tsx +680 -0
  1142. package/src/client/progress/index.ts +1 -0
  1143. package/src/client/require-session.tsx +142 -0
  1144. package/src/client/resources/BuiltinCapabilityDetail.tsx +258 -0
  1145. package/src/client/resources/McpConnectionSuggestion.tsx +276 -0
  1146. package/src/client/resources/McpIntegrationDialog.tsx +808 -0
  1147. package/src/client/resources/McpServerDetail.tsx +230 -0
  1148. package/src/client/resources/ResourceEditor.tsx +872 -0
  1149. package/src/client/resources/ResourceTree.tsx +860 -0
  1150. package/src/client/resources/ResourcesPanel.tsx +1960 -0
  1151. package/src/client/resources/index.ts +25 -0
  1152. package/src/client/resources/mcp-integration-catalog.ts +771 -0
  1153. package/src/client/resources/mcp-integration-logos.ts +108 -0
  1154. package/src/client/resources/runtime.ts +1 -0
  1155. package/src/client/resources/use-builtin-capabilities.ts +113 -0
  1156. package/src/client/resources/use-mcp-servers.ts +217 -0
  1157. package/src/client/resources/use-resources.ts +402 -0
  1158. package/src/client/review/ReviewCommentComposer.tsx +123 -0
  1159. package/src/client/review/ReviewStatusBadge.tsx +39 -0
  1160. package/src/client/review/ReviewThreadPanel.tsx +625 -0
  1161. package/src/client/review/index.ts +38 -0
  1162. package/src/client/review/use-review.ts +186 -0
  1163. package/src/client/route-chunk-recovery/index.ts +1 -0
  1164. package/src/client/route-chunk-recovery.ts +331 -0
  1165. package/src/client/route-state.ts +455 -0
  1166. package/src/client/route-warmup.tsx +543 -0
  1167. package/src/client/session-replay-iframe.e2e-host.tsx +100 -0
  1168. package/src/client/session-replay.ts +3417 -0
  1169. package/src/client/settings/AgentsSection.tsx +441 -0
  1170. package/src/client/settings/AutomationsSection.tsx +516 -0
  1171. package/src/client/settings/BackgroundAgentSection.tsx +189 -0
  1172. package/src/client/settings/BrowserSection.tsx +110 -0
  1173. package/src/client/settings/DemoModeSection.tsx +48 -0
  1174. package/src/client/settings/SecretsSection.tsx +875 -0
  1175. package/src/client/settings/SettingsPanel.tsx +3162 -0
  1176. package/src/client/settings/SettingsSection.tsx +283 -0
  1177. package/src/client/settings/SettingsTabsPage.tsx +592 -0
  1178. package/src/client/settings/UsageSection.tsx +401 -0
  1179. package/src/client/settings/VoiceTranscriptionSection.tsx +960 -0
  1180. package/src/client/settings/agent-settings-search.ts +220 -0
  1181. package/src/client/settings/index.ts +27 -0
  1182. package/src/client/settings/useBuilderStatus.ts +1055 -0
  1183. package/src/client/setup-connections/BuilderConnectCard.tsx +89 -0
  1184. package/src/client/setup-connections/ProviderReadinessBadge.tsx +73 -0
  1185. package/src/client/setup-connections/SetupConnectionsPage.tsx +94 -0
  1186. package/src/client/setup-connections/catalog.ts +6 -0
  1187. package/src/client/setup-connections/index.ts +47 -0
  1188. package/src/client/setup-connections/runtime.ts +1 -0
  1189. package/src/client/sharing/ShareButton.tsx +1748 -0
  1190. package/src/client/sharing/ShareDialog.tsx +846 -0
  1191. package/src/client/sharing/VisibilityBadge.tsx +4 -0
  1192. package/src/client/sharing/index.ts +2 -0
  1193. package/src/client/sse-event-processor.ts +2002 -0
  1194. package/src/client/terminal/AgentTerminal.tsx +488 -0
  1195. package/src/client/terminal/index.ts +7 -0
  1196. package/src/client/theme.ts +27 -0
  1197. package/src/client/tombstone/agent-presence-chip.ts +17 -0
  1198. package/src/client/tombstone/editor.ts +265 -0
  1199. package/src/client/tombstone/live-cursor-overlay.ts +21 -0
  1200. package/src/client/tombstone/presence-bar.ts +17 -0
  1201. package/src/client/tombstone/recent-edit-highlights.ts +17 -0
  1202. package/src/client/tombstone/remote-selection-rings.ts +21 -0
  1203. package/src/client/tombstone/rich-markdown-editor.ts +265 -0
  1204. package/src/client/tombstone/ui-dialog.ts +49 -0
  1205. package/src/client/tombstone/ui-dropdown-menu.ts +69 -0
  1206. package/src/client/tombstone/ui-hover-card.ts +21 -0
  1207. package/src/client/tombstone/ui-popover.ts +25 -0
  1208. package/src/client/tombstone/ui-sheet.ts +49 -0
  1209. package/src/client/tombstone/ui-tooltip.ts +29 -0
  1210. package/src/client/tombstone/visual-style-controls.ts +61 -0
  1211. package/src/client/tool-cells/BashCell.tsx +164 -0
  1212. package/src/client/tool-cells/EditCell.tsx +303 -0
  1213. package/src/client/tool-cells/FilesChangedSummary.tsx +208 -0
  1214. package/src/client/tool-cells/WriteCell.tsx +145 -0
  1215. package/src/client/tool-cells/index.ts +7 -0
  1216. package/src/client/tool-display.ts +41 -0
  1217. package/src/client/track.ts +57 -0
  1218. package/src/client/transcription/BuilderTranscriptionCta.tsx +120 -0
  1219. package/src/client/transcription/use-live-transcription.ts +292 -0
  1220. package/src/client/ui/index.ts +55 -0
  1221. package/src/client/uploads/index.ts +6 -0
  1222. package/src/client/uploads/upload-editor-image.ts +79 -0
  1223. package/src/client/uploads/use-upload-resource.ts +24 -0
  1224. package/src/client/url-scrub.ts +51 -0
  1225. package/src/client/use-action.ts +766 -0
  1226. package/src/client/use-agent-chat-context.ts +63 -0
  1227. package/src/client/use-agent-chat-home-handoff.ts +207 -0
  1228. package/src/client/use-agent-chat.ts +53 -0
  1229. package/src/client/use-agent-engine-configured.ts +211 -0
  1230. package/src/client/use-avatar.ts +127 -0
  1231. package/src/client/use-change-version.ts +150 -0
  1232. package/src/client/use-chat-models.ts +252 -0
  1233. package/src/client/use-chat-threads.ts +1262 -0
  1234. package/src/client/use-db-sync.ts +1112 -0
  1235. package/src/client/use-demo-mode-status.ts +30 -0
  1236. package/src/client/use-dev-mode.ts +177 -0
  1237. package/src/client/use-external-value.ts +40 -0
  1238. package/src/client/use-pausing-interval.ts +65 -0
  1239. package/src/client/use-pinch-zoom.ts +202 -0
  1240. package/src/client/use-run-stuck-detection.ts +427 -0
  1241. package/src/client/use-send-to-agent-chat.ts +85 -0
  1242. package/src/client/use-session.ts +114 -0
  1243. package/src/client/utils.ts +7 -0
  1244. package/src/client/visual-style-controls.tsx +1 -0
  1245. package/src/client/vite-dev-recovery-script.ts +226 -0
  1246. package/src/client/voice-provider-status.ts +44 -0
  1247. package/src/client/widgets/index.ts +41 -0
  1248. package/src/code-agents/background-controller.ts +398 -0
  1249. package/src/code-agents/background-run.ts +156 -0
  1250. package/src/code-agents/index.ts +95 -0
  1251. package/src/code-agents/prompt-attachments.ts +39 -0
  1252. package/src/code-agents/transcript-normalizer.ts +750 -0
  1253. package/src/code-agents/transcript-order.ts +73 -0
  1254. package/src/coding-tools/index.ts +742 -0
  1255. package/src/coding-tools/run-code.ts +1662 -0
  1256. package/src/coding-tools/sandbox/adapter.ts +82 -0
  1257. package/src/coding-tools/sandbox/background.ts +406 -0
  1258. package/src/coding-tools/sandbox/executions-store.ts +517 -0
  1259. package/src/coding-tools/sandbox/index.ts +132 -0
  1260. package/src/coding-tools/sandbox/local-child-process-adapter.ts +217 -0
  1261. package/src/collab/agent-identity.ts +5 -0
  1262. package/src/collab/agent-presence.ts +341 -0
  1263. package/src/collab/awareness-store.ts +196 -0
  1264. package/src/collab/awareness.ts +317 -0
  1265. package/src/collab/client-struct.ts +366 -0
  1266. package/src/collab/client.ts +1205 -0
  1267. package/src/collab/emitter.ts +31 -0
  1268. package/src/collab/follow-mode.ts +107 -0
  1269. package/src/collab/index.ts +151 -0
  1270. package/src/collab/json-to-yjs.ts +504 -0
  1271. package/src/collab/presence.ts +207 -0
  1272. package/src/collab/recent-edits.ts +215 -0
  1273. package/src/collab/routes.ts +191 -0
  1274. package/src/collab/storage.ts +228 -0
  1275. package/src/collab/struct-routes.ts +133 -0
  1276. package/src/collab/text-to-yjs.ts +79 -0
  1277. package/src/collab/undo.ts +432 -0
  1278. package/src/collab/xml-ops.ts +68 -0
  1279. package/src/collab/ydoc-manager.ts +544 -0
  1280. package/src/command-navigation/actions.ts +100 -0
  1281. package/src/command-navigation/index.ts +12 -0
  1282. package/src/comments-review/index.ts +1 -0
  1283. package/src/connections/catalog.ts +451 -0
  1284. package/src/connections/index.ts +48 -0
  1285. package/src/connections/reader.ts +911 -0
  1286. package/src/connections/runtime.ts +1 -0
  1287. package/src/credentials/index.ts +187 -0
  1288. package/src/data-programs/actions.ts +335 -0
  1289. package/src/data-programs/contract.ts +284 -0
  1290. package/src/data-programs/execute.ts +693 -0
  1291. package/src/data-programs/index.ts +72 -0
  1292. package/src/data-programs/schema.ts +148 -0
  1293. package/src/data-programs/store.ts +755 -0
  1294. package/src/data-widgets/index.ts +376 -0
  1295. package/src/db/client.ts +1627 -0
  1296. package/src/db/create-get-db.ts +579 -0
  1297. package/src/db/ddl-guard.ts +302 -0
  1298. package/src/db/drizzle-config.ts +190 -0
  1299. package/src/db/ensure-additive-columns.ts +430 -0
  1300. package/src/db/index.ts +57 -0
  1301. package/src/db/migrations.ts +691 -0
  1302. package/src/db/request-telemetry.ts +154 -0
  1303. package/src/db/runtime-diagnostics.ts +331 -0
  1304. package/src/db/schema.ts +121 -0
  1305. package/src/db/widen-columns.ts +75 -0
  1306. package/src/db-admin/agent-tools.ts +202 -0
  1307. package/src/db-admin/index.ts +26 -0
  1308. package/src/db-admin/operations.ts +803 -0
  1309. package/src/db-admin/routes.ts +174 -0
  1310. package/src/db-admin/types.ts +110 -0
  1311. package/src/demo/browser-state.ts +47 -0
  1312. package/src/demo/fetch-interceptor.ts +175 -0
  1313. package/src/demo/redact.ts +575 -0
  1314. package/src/deploy/build.ts +3935 -0
  1315. package/src/deploy/immutable-assets.ts +65 -0
  1316. package/src/deploy/route-discovery.ts +458 -0
  1317. package/src/deploy/workspace-core.ts +282 -0
  1318. package/src/deploy/workspace-deploy.ts +1488 -0
  1319. package/src/eject/provider-api-definitions.ts +193 -0
  1320. package/src/eject/remote-mcp-presets.ts +137 -0
  1321. package/src/eject/setup-readiness-ui.tsx +29 -0
  1322. package/src/eject/workspace-connections.ts +92 -0
  1323. package/src/embedding/agent.ts +159 -0
  1324. package/src/embedding/bridge.ts +297 -0
  1325. package/src/embedding/index.ts +43 -0
  1326. package/src/embedding/protocol.ts +185 -0
  1327. package/src/embedding/react.tsx +319 -0
  1328. package/src/embeddings/index.ts +233 -0
  1329. package/src/eval/agent-runner.ts +210 -0
  1330. package/src/eval/define-eval.ts +55 -0
  1331. package/src/eval/index.ts +49 -0
  1332. package/src/eval/report.ts +75 -0
  1333. package/src/eval/runner.ts +369 -0
  1334. package/src/eval/scorer.ts +244 -0
  1335. package/src/eval/types.ts +188 -0
  1336. package/src/event-bus/bus.ts +140 -0
  1337. package/src/event-bus/index.ts +3 -0
  1338. package/src/event-bus/registry.ts +79 -0
  1339. package/src/event-bus/types.ts +29 -0
  1340. package/src/extensions/actions.ts +1636 -0
  1341. package/src/extensions/change-marker.ts +54 -0
  1342. package/src/extensions/content-patch.ts +468 -0
  1343. package/src/extensions/fetch-tool.ts +461 -0
  1344. package/src/extensions/html-shell.ts +803 -0
  1345. package/src/extensions/local.ts +462 -0
  1346. package/src/extensions/path.ts +40 -0
  1347. package/src/extensions/proxy-security.ts +171 -0
  1348. package/src/extensions/routes.ts +1080 -0
  1349. package/src/extensions/schema.ts +269 -0
  1350. package/src/extensions/session-replay-iframe.ts +131 -0
  1351. package/src/extensions/slots/routes.ts +126 -0
  1352. package/src/extensions/slots/schema.ts +87 -0
  1353. package/src/extensions/slots/store.ts +450 -0
  1354. package/src/extensions/store.ts +1347 -0
  1355. package/src/extensions/theme.ts +114 -0
  1356. package/src/extensions/url-safety.ts +316 -0
  1357. package/src/extensions/web-content.ts +663 -0
  1358. package/src/extensions/web-search-tool.ts +437 -0
  1359. package/src/feature-flags/a2a-action-route.ts +56 -0
  1360. package/src/feature-flags/actions/get-feature-flags.ts +24 -0
  1361. package/src/feature-flags/actions/list-feature-flags.ts +69 -0
  1362. package/src/feature-flags/actions/set-feature-flag.ts +89 -0
  1363. package/src/feature-flags/index.ts +21 -0
  1364. package/src/feature-flags/permissions.ts +53 -0
  1365. package/src/feature-flags/plugin.ts +44 -0
  1366. package/src/feature-flags/registry.ts +96 -0
  1367. package/src/feature-flags/store.ts +176 -0
  1368. package/src/file-upload/actions/upload-image.ts +213 -0
  1369. package/src/file-upload/builder.ts +431 -0
  1370. package/src/file-upload/index.ts +24 -0
  1371. package/src/file-upload/pre-upload-attachments.ts +305 -0
  1372. package/src/file-upload/registry.ts +125 -0
  1373. package/src/file-upload/types.ts +89 -0
  1374. package/src/guards/db-tool-scoping.ts +129 -0
  1375. package/src/guards/index.ts +23 -0
  1376. package/src/guards/no-drizzle-push.ts +116 -0
  1377. package/src/guards/no-env-credentials.ts +229 -0
  1378. package/src/guards/no-env-mutation.ts +114 -0
  1379. package/src/guards/no-localhost-fallback.ts +124 -0
  1380. package/src/guards/no-unscoped-credentials.ts +227 -0
  1381. package/src/guards/no-unscoped-queries.ts +834 -0
  1382. package/src/guards/scan-utils.ts +105 -0
  1383. package/src/guards/types.ts +30 -0
  1384. package/src/history/actions/create-resource-version.ts +92 -0
  1385. package/src/history/actions/get-resource-version.ts +60 -0
  1386. package/src/history/actions/list-resource-history.ts +53 -0
  1387. package/src/history/actions/list-resource-versions.ts +43 -0
  1388. package/src/history/actions/restore-resource-version.ts +96 -0
  1389. package/src/history/index.ts +26 -0
  1390. package/src/history/registry.ts +111 -0
  1391. package/src/history/store.ts +379 -0
  1392. package/src/history/types.ts +69 -0
  1393. package/src/index.browser.ts +155 -0
  1394. package/src/index.ts +408 -0
  1395. package/src/ingestion/docx.ts +158 -0
  1396. package/src/ingestion/figma-node-to-html.ts +1860 -0
  1397. package/src/ingestion/figma.ts +548 -0
  1398. package/src/ingestion/index.ts +107 -0
  1399. package/src/ingestion/media.ts +264 -0
  1400. package/src/ingestion/notion.ts +121 -0
  1401. package/src/ingestion/office.ts +213 -0
  1402. package/src/ingestion/orchestration.ts +160 -0
  1403. package/src/ingestion/pptx.ts +331 -0
  1404. package/src/ingestion/selection.ts +81 -0
  1405. package/src/ingestion/website.ts +151 -0
  1406. package/src/integrations/a2a-continuation-marker.ts +2 -0
  1407. package/src/integrations/a2a-continuation-processor.ts +888 -0
  1408. package/src/integrations/a2a-continuations-store.ts +643 -0
  1409. package/src/integrations/adapter-overrides.ts +12 -0
  1410. package/src/integrations/adapters/discord.ts +364 -0
  1411. package/src/integrations/adapters/email.ts +1164 -0
  1412. package/src/integrations/adapters/google-docs.ts +371 -0
  1413. package/src/integrations/adapters/index.ts +29 -0
  1414. package/src/integrations/adapters/microsoft-teams.ts +413 -0
  1415. package/src/integrations/adapters/slack.ts +1914 -0
  1416. package/src/integrations/adapters/telegram.ts +386 -0
  1417. package/src/integrations/adapters/whatsapp.ts +358 -0
  1418. package/src/integrations/awaiting-input-store.ts +130 -0
  1419. package/src/integrations/catalog.ts +571 -0
  1420. package/src/integrations/computer-supervision-store.ts +423 -0
  1421. package/src/integrations/computer-supervision.ts +213 -0
  1422. package/src/integrations/config-store.ts +131 -0
  1423. package/src/integrations/controls-store.ts +187 -0
  1424. package/src/integrations/eject/messaging-adapters.ts +85 -0
  1425. package/src/integrations/google-docs-poller.ts +671 -0
  1426. package/src/integrations/identity-links-store.ts +210 -0
  1427. package/src/integrations/identity.ts +196 -0
  1428. package/src/integrations/index.ts +220 -0
  1429. package/src/integrations/installations-store.ts +677 -0
  1430. package/src/integrations/integration-memory.ts +187 -0
  1431. package/src/integrations/internal-token.ts +106 -0
  1432. package/src/integrations/pending-tasks-retry-job.ts +286 -0
  1433. package/src/integrations/pending-tasks-store.ts +468 -0
  1434. package/src/integrations/plugin.ts +3048 -0
  1435. package/src/integrations/remote-commands-store.ts +690 -0
  1436. package/src/integrations/remote-devices-store.ts +492 -0
  1437. package/src/integrations/remote-json-safety.ts +127 -0
  1438. package/src/integrations/remote-push-delivery-job.ts +48 -0
  1439. package/src/integrations/remote-push-delivery.ts +370 -0
  1440. package/src/integrations/remote-push-store.ts +664 -0
  1441. package/src/integrations/remote-retry-job.ts +55 -0
  1442. package/src/integrations/remote-run-events-store.ts +222 -0
  1443. package/src/integrations/remote-types.ts +186 -0
  1444. package/src/integrations/runtime.ts +1 -0
  1445. package/src/integrations/scope-store.ts +498 -0
  1446. package/src/integrations/slack-manifest.ts +78 -0
  1447. package/src/integrations/slack-oauth.ts +344 -0
  1448. package/src/integrations/task-queue-stats.ts +144 -0
  1449. package/src/integrations/thread-mapping-store.ts +134 -0
  1450. package/src/integrations/types.ts +485 -0
  1451. package/src/integrations/usage-budget-store.ts +906 -0
  1452. package/src/integrations/webhook-delivery.ts +55 -0
  1453. package/src/integrations/webhook-handler.ts +1939 -0
  1454. package/src/jobs/actions/list-recurring-jobs.ts +105 -0
  1455. package/src/jobs/actions/manage-recurring-job.ts +85 -0
  1456. package/src/jobs/cron.ts +126 -0
  1457. package/src/jobs/index.ts +9 -0
  1458. package/src/jobs/scheduler.ts +703 -0
  1459. package/src/jobs/tools.ts +367 -0
  1460. package/src/local-artifacts/index.ts +1372 -0
  1461. package/src/localization/actions/get-localization-preference.ts +24 -0
  1462. package/src/localization/actions/set-localization-preference.ts +32 -0
  1463. package/src/localization/default-messages.ts +1009 -0
  1464. package/src/localization/index.ts +2 -0
  1465. package/src/localization/server.ts +131 -0
  1466. package/src/localization/shared.ts +208 -0
  1467. package/src/mcp/actions/call-mcp-tool.ts +19 -0
  1468. package/src/mcp/actions/create-org-service-token.ts +87 -0
  1469. package/src/mcp/actions/list-mcp-tools.ts +18 -0
  1470. package/src/mcp/actions/list-org-service-tokens.ts +44 -0
  1471. package/src/mcp/actions/revoke-org-service-token.ts +30 -0
  1472. package/src/mcp/actions/service-token-access.ts +121 -0
  1473. package/src/mcp/ask-app-inline-tasks.ts +125 -0
  1474. package/src/mcp/build-server.ts +2356 -0
  1475. package/src/mcp/builtin-tools.ts +1506 -0
  1476. package/src/mcp/connect-route.ts +1460 -0
  1477. package/src/mcp/connect-store.ts +680 -0
  1478. package/src/mcp/embed-app.ts +2051 -0
  1479. package/src/mcp/embed-route.ts +84 -0
  1480. package/src/mcp/external-agent-policy.ts +18 -0
  1481. package/src/mcp/index.ts +47 -0
  1482. package/src/mcp/oauth-route.ts +1016 -0
  1483. package/src/mcp/oauth-store.ts +581 -0
  1484. package/src/mcp/oauth-token.ts +227 -0
  1485. package/src/mcp/org-directory.ts +343 -0
  1486. package/src/mcp/route-paths.ts +34 -0
  1487. package/src/mcp/screen-memory-stdio.ts +290 -0
  1488. package/src/mcp/server.ts +507 -0
  1489. package/src/mcp/stdio.ts +328 -0
  1490. package/src/mcp/workspace-resolve.ts +261 -0
  1491. package/src/mcp-client/app-api.ts +136 -0
  1492. package/src/mcp-client/app-result.ts +64 -0
  1493. package/src/mcp-client/builtin-capabilities.ts +146 -0
  1494. package/src/mcp-client/builtin-store.ts +93 -0
  1495. package/src/mcp-client/config.ts +281 -0
  1496. package/src/mcp-client/errors.ts +54 -0
  1497. package/src/mcp-client/hub-client.ts +172 -0
  1498. package/src/mcp-client/hub-routes.ts +198 -0
  1499. package/src/mcp-client/index.ts +504 -0
  1500. package/src/mcp-client/manager.ts +968 -0
  1501. package/src/mcp-client/oauth-client.ts +462 -0
  1502. package/src/mcp-client/oauth-routes.ts +307 -0
  1503. package/src/mcp-client/remote-store.ts +674 -0
  1504. package/src/mcp-client/remote-url.ts +97 -0
  1505. package/src/mcp-client/routes.ts +1093 -0
  1506. package/src/mcp-client/screen-memory-local.ts +461 -0
  1507. package/src/mcp-client/tool-policy.ts +182 -0
  1508. package/src/mcp-client/visibility.ts +56 -0
  1509. package/src/mcp-client/workspace-servers.ts +379 -0
  1510. package/src/navigation/index.ts +170 -0
  1511. package/src/notifications/actions.ts +151 -0
  1512. package/src/notifications/channels.ts +410 -0
  1513. package/src/notifications/index.ts +22 -0
  1514. package/src/notifications/registry.ts +216 -0
  1515. package/src/notifications/routes.ts +106 -0
  1516. package/src/notifications/store.ts +236 -0
  1517. package/src/notifications/types.ts +52 -0
  1518. package/src/oauth-tokens/google-refresh.ts +175 -0
  1519. package/src/oauth-tokens/index.ts +15 -0
  1520. package/src/oauth-tokens/store.ts +384 -0
  1521. package/src/observability/cleanup-job.ts +124 -0
  1522. package/src/observability/evals.ts +507 -0
  1523. package/src/observability/experiments.ts +359 -0
  1524. package/src/observability/feedback.ts +332 -0
  1525. package/src/observability/hosted-model-experiment.ts +118 -0
  1526. package/src/observability/index.ts +62 -0
  1527. package/src/observability/plugin.ts +31 -0
  1528. package/src/observability/routes.ts +431 -0
  1529. package/src/observability/sentiment.ts +261 -0
  1530. package/src/observability/store.ts +1347 -0
  1531. package/src/observability/traces.ts +789 -0
  1532. package/src/observability/tracing.ts +157 -0
  1533. package/src/observability/tracking-identity.ts +55 -0
  1534. package/src/observability/types.ts +211 -0
  1535. package/src/onboarding/default-steps.ts +428 -0
  1536. package/src/onboarding/index.ts +22 -0
  1537. package/src/onboarding/plugin.ts +262 -0
  1538. package/src/onboarding/registry.ts +47 -0
  1539. package/src/onboarding/types.ts +96 -0
  1540. package/src/org/accept-pending.ts +98 -0
  1541. package/src/org/auto-join-domain.ts +113 -0
  1542. package/src/org/context.ts +614 -0
  1543. package/src/org/free-email-providers.ts +124 -0
  1544. package/src/org/handlers.ts +1153 -0
  1545. package/src/org/index.ts +63 -0
  1546. package/src/org/migrations.ts +105 -0
  1547. package/src/org/permissions.ts +30 -0
  1548. package/src/org/plugin.ts +255 -0
  1549. package/src/org/schema.ts +28 -0
  1550. package/src/org/types.ts +57 -0
  1551. package/src/org-team/index.ts +1 -0
  1552. package/src/package-lifecycle/deprecated-imports.ts +179 -0
  1553. package/src/package-lifecycle/eject-manifest.ts +345 -0
  1554. package/src/package-lifecycle/index.ts +7 -0
  1555. package/src/package-lifecycle/manifest.ts +120 -0
  1556. package/src/package-lifecycle/migration-manifest.ts +159 -0
  1557. package/src/package-lifecycle/migration-message.ts +6 -0
  1558. package/src/package-lifecycle/tombstone.ts +58 -0
  1559. package/src/package-lifecycle/upgrade-error.ts +37 -0
  1560. package/src/private-blob/index.ts +18 -0
  1561. package/src/private-blob/registry.ts +242 -0
  1562. package/src/private-blob/types.ts +55 -0
  1563. package/src/progress/actions.ts +179 -0
  1564. package/src/progress/index.ts +16 -0
  1565. package/src/progress/registry.ts +127 -0
  1566. package/src/progress/routes.ts +89 -0
  1567. package/src/progress/store.ts +353 -0
  1568. package/src/progress/types.ts +59 -0
  1569. package/src/provider-api/actions/custom-provider-registration.ts +197 -0
  1570. package/src/provider-api/actions/delete-staged-dataset.ts +5 -0
  1571. package/src/provider-api/actions/github-repo-files.ts +266 -0
  1572. package/src/provider-api/actions/list-staged-datasets.ts +5 -0
  1573. package/src/provider-api/actions/provider-api-audit.ts +88 -0
  1574. package/src/provider-api/actions/provider-api.ts +460 -0
  1575. package/src/provider-api/actions/query-staged-dataset.ts +5 -0
  1576. package/src/provider-api/actions/staged-datasets.ts +359 -0
  1577. package/src/provider-api/corpus-jobs-store.ts +522 -0
  1578. package/src/provider-api/corpus-jobs.ts +1817 -0
  1579. package/src/provider-api/custom-registry.ts +456 -0
  1580. package/src/provider-api/github-repo.ts +675 -0
  1581. package/src/provider-api/gong.ts +108 -0
  1582. package/src/provider-api/index.ts +5444 -0
  1583. package/src/provider-api/quota-governor.ts +562 -0
  1584. package/src/provider-api/runtime.ts +1 -0
  1585. package/src/provider-api/staged-datasets-aggregate.ts +304 -0
  1586. package/src/provider-api/staged-datasets-store.ts +441 -0
  1587. package/src/provider-api/staging.ts +483 -0
  1588. package/src/resources/agents.ts +65 -0
  1589. package/src/resources/emitter.ts +54 -0
  1590. package/src/resources/handlers.ts +728 -0
  1591. package/src/resources/index.ts +4 -0
  1592. package/src/resources/metadata.ts +252 -0
  1593. package/src/resources/script-helpers.ts +160 -0
  1594. package/src/resources/store.ts +1618 -0
  1595. package/src/review/actions/consume-review-feedback.ts +48 -0
  1596. package/src/review/actions/create-review-comment.ts +108 -0
  1597. package/src/review/actions/delete-review-comment.ts +67 -0
  1598. package/src/review/actions/get-review-feedback.ts +49 -0
  1599. package/src/review/actions/list-review-comments.ts +87 -0
  1600. package/src/review/actions/reply-review-comment.ts +118 -0
  1601. package/src/review/actions/resolve-review-thread.ts +94 -0
  1602. package/src/review/actions/send-review-thread-to-agent.ts +62 -0
  1603. package/src/review/actions/set-review-status.ts +58 -0
  1604. package/src/review/identity.ts +101 -0
  1605. package/src/review/index.ts +45 -0
  1606. package/src/review/mentions.ts +44 -0
  1607. package/src/review/registry.ts +111 -0
  1608. package/src/review/store.ts +997 -0
  1609. package/src/review/types.ts +101 -0
  1610. package/src/router/index.ts +24 -0
  1611. package/src/scripts/agent-engines/list-agent-engines.ts +130 -0
  1612. package/src/scripts/agent-engines/manage-agent-engine.ts +197 -0
  1613. package/src/scripts/agent-engines/set-agent-engine.ts +84 -0
  1614. package/src/scripts/agent-engines/test-agent-engine.ts +174 -0
  1615. package/src/scripts/call-agent.ts +792 -0
  1616. package/src/scripts/chat/index.ts +8 -0
  1617. package/src/scripts/chat/open-chat.ts +56 -0
  1618. package/src/scripts/chat/search-chats.ts +121 -0
  1619. package/src/scripts/core-scripts.ts +22 -0
  1620. package/src/scripts/db/check-scoping.ts +212 -0
  1621. package/src/scripts/db/exec.ts +791 -0
  1622. package/src/scripts/db/index.ts +19 -0
  1623. package/src/scripts/db/migrate-encrypt-credentials.ts +223 -0
  1624. package/src/scripts/db/migrate-encrypt-oauth-tokens.ts +213 -0
  1625. package/src/scripts/db/migrate-user-api-keys.ts +257 -0
  1626. package/src/scripts/db/patch.ts +820 -0
  1627. package/src/scripts/db/query.ts +299 -0
  1628. package/src/scripts/db/reset-dev-owner.ts +285 -0
  1629. package/src/scripts/db/safety.ts +286 -0
  1630. package/src/scripts/db/schema.ts +364 -0
  1631. package/src/scripts/db/scoping.ts +341 -0
  1632. package/src/scripts/db/sqlite-client.ts +78 -0
  1633. package/src/scripts/db/tool-mode.ts +23 -0
  1634. package/src/scripts/db/tool-schemas.ts +31 -0
  1635. package/src/scripts/db/wipe-leaked-builder-keys.ts +201 -0
  1636. package/src/scripts/dev/index.ts +296 -0
  1637. package/src/scripts/dev/list-files.ts +119 -0
  1638. package/src/scripts/dev/read-file.ts +77 -0
  1639. package/src/scripts/dev/search-files.ts +151 -0
  1640. package/src/scripts/dev/shell.ts +111 -0
  1641. package/src/scripts/dev/write-file.ts +56 -0
  1642. package/src/scripts/dev-session.ts +96 -0
  1643. package/src/scripts/docs/index.ts +8 -0
  1644. package/src/scripts/docs/search.ts +274 -0
  1645. package/src/scripts/docs/source-search.ts +363 -0
  1646. package/src/scripts/index.ts +15 -0
  1647. package/src/scripts/manage-agent-loop-settings.ts +84 -0
  1648. package/src/scripts/parse-args.ts +46 -0
  1649. package/src/scripts/resources/delete-memory.ts +67 -0
  1650. package/src/scripts/resources/delete.ts +69 -0
  1651. package/src/scripts/resources/effective.ts +71 -0
  1652. package/src/scripts/resources/index.ts +18 -0
  1653. package/src/scripts/resources/list.ts +103 -0
  1654. package/src/scripts/resources/migrate-learnings.ts +40 -0
  1655. package/src/scripts/resources/read.ts +107 -0
  1656. package/src/scripts/resources/save-memory.ts +99 -0
  1657. package/src/scripts/resources/write.ts +158 -0
  1658. package/src/scripts/runner.ts +339 -0
  1659. package/src/scripts/utils.ts +130 -0
  1660. package/src/search/index.ts +413 -0
  1661. package/src/search-utils/index.ts +112 -0
  1662. package/src/secrets/crypto.ts +228 -0
  1663. package/src/secrets/index.ts +65 -0
  1664. package/src/secrets/onboarding.ts +101 -0
  1665. package/src/secrets/register-framework-secrets.ts +228 -0
  1666. package/src/secrets/register.ts +129 -0
  1667. package/src/secrets/routes.ts +697 -0
  1668. package/src/secrets/schema.ts +52 -0
  1669. package/src/secrets/storage.ts +561 -0
  1670. package/src/secrets/substitution.ts +305 -0
  1671. package/src/server/__snapshots__/agent-chat-plugin.surface.spec.ts.snap +150 -0
  1672. package/src/server/action-change.ts +66 -0
  1673. package/src/server/action-discovery.ts +774 -0
  1674. package/src/server/action-routes.ts +608 -0
  1675. package/src/server/agent-access.ts +72 -0
  1676. package/src/server/agent-chat/action-filters-a2a.ts +339 -0
  1677. package/src/server/agent-chat/browser-team-tools.ts +510 -0
  1678. package/src/server/agent-chat/context-tools.ts +599 -0
  1679. package/src/server/agent-chat/framework-prompts.ts +467 -0
  1680. package/src/server/agent-chat/lazy-fs.ts +11 -0
  1681. package/src/server/agent-chat/mcp-glue.ts +91 -0
  1682. package/src/server/agent-chat/plugin-options.ts +379 -0
  1683. package/src/server/agent-chat/process-run-failure.ts +62 -0
  1684. package/src/server/agent-chat/prompt-resources.ts +1004 -0
  1685. package/src/server/agent-chat/recurring-jobs-runtime.ts +80 -0
  1686. package/src/server/agent-chat/request-surface.ts +71 -0
  1687. package/src/server/agent-chat/run-code-tools.ts +67 -0
  1688. package/src/server/agent-chat/script-entries.ts +796 -0
  1689. package/src/server/agent-chat/shared-thread.ts +301 -0
  1690. package/src/server/agent-chat/skill-frontmatter.ts +41 -0
  1691. package/src/server/agent-chat-plugin.ts +5930 -0
  1692. package/src/server/agent-discovery.ts +706 -0
  1693. package/src/server/agent-engine-api-key-route.ts +236 -0
  1694. package/src/server/agent-run-context.ts +204 -0
  1695. package/src/server/agent-teams-run-queue.ts +344 -0
  1696. package/src/server/agent-teams.ts +2257 -0
  1697. package/src/server/agents-bundle.ts +464 -0
  1698. package/src/server/analytics.ts +105 -0
  1699. package/src/server/app-base-path.ts +79 -0
  1700. package/src/server/app-name.ts +53 -0
  1701. package/src/server/app-url.ts +184 -0
  1702. package/src/server/attachment-actions.ts +276 -0
  1703. package/src/server/attribution.ts +214 -0
  1704. package/src/server/auth-marketing.ts +260 -0
  1705. package/src/server/auth-plugin.ts +27 -0
  1706. package/src/server/auth.ts +3803 -0
  1707. package/src/server/better-auth-instance.ts +1197 -0
  1708. package/src/server/builder-browser.ts +1701 -0
  1709. package/src/server/builder-design-systems.ts +668 -0
  1710. package/src/server/builder-space.ts +176 -0
  1711. package/src/server/captcha.ts +63 -0
  1712. package/src/server/capture-error.ts +64 -0
  1713. package/src/server/cli-capture.ts +141 -0
  1714. package/src/server/collab-plugin.ts +391 -0
  1715. package/src/server/complete-text.ts +231 -0
  1716. package/src/server/cookie-namespace.ts +159 -0
  1717. package/src/server/core-routes-plugin.ts +4122 -0
  1718. package/src/server/cors-origins.ts +60 -0
  1719. package/src/server/create-server.ts +268 -0
  1720. package/src/server/credential-provider.ts +1202 -0
  1721. package/src/server/csrf.ts +229 -0
  1722. package/src/server/date-utils.ts +42 -0
  1723. package/src/server/deep-link.ts +119 -0
  1724. package/src/server/derived-secret.ts +32 -0
  1725. package/src/server/design-token-utils.ts +1032 -0
  1726. package/src/server/desktop-sso.ts +83 -0
  1727. package/src/server/edge.ts +69 -0
  1728. package/src/server/email-actions.ts +218 -0
  1729. package/src/server/email-template.ts +192 -0
  1730. package/src/server/email-templates.ts +148 -0
  1731. package/src/server/email.ts +219 -0
  1732. package/src/server/embed-route.ts +283 -0
  1733. package/src/server/embed-session.ts +805 -0
  1734. package/src/server/embedded.ts +252 -0
  1735. package/src/server/entry-server.tsx +154 -0
  1736. package/src/server/framework-request-handler.ts +848 -0
  1737. package/src/server/fusion-app.ts +447 -0
  1738. package/src/server/google-auth-mode.ts +34 -0
  1739. package/src/server/google-auth-plugin.ts +496 -0
  1740. package/src/server/google-oauth-credentials.ts +128 -0
  1741. package/src/server/google-oauth.ts +972 -0
  1742. package/src/server/google-realtime-session.ts +182 -0
  1743. package/src/server/h3-helpers.ts +174 -0
  1744. package/src/server/http-response-telemetry.ts +396 -0
  1745. package/src/server/identity-sso-store.ts +304 -0
  1746. package/src/server/identity-sso.ts +514 -0
  1747. package/src/server/index.ts +593 -0
  1748. package/src/server/missing-key.ts +36 -0
  1749. package/src/server/oauth-helpers.ts +44 -0
  1750. package/src/server/oauth-public-origin.ts +44 -0
  1751. package/src/server/oauth-return-url.ts +120 -0
  1752. package/src/server/og-fonts-data.ts +15 -0
  1753. package/src/server/og-fonts.ts +75 -0
  1754. package/src/server/onboarding-html.ts +4040 -0
  1755. package/src/server/open-route.ts +311 -0
  1756. package/src/server/org-admin.ts +28 -0
  1757. package/src/server/poll-events.ts +88 -0
  1758. package/src/server/poll.ts +1224 -0
  1759. package/src/server/prompts/framework-core-compact.ts +107 -0
  1760. package/src/server/prompts/framework-core.ts +143 -0
  1761. package/src/server/prompts/index.ts +16 -0
  1762. package/src/server/prompts/model-overlays.ts +54 -0
  1763. package/src/server/prompts/shared-rules.ts +104 -0
  1764. package/src/server/realtime-voice.ts +967 -0
  1765. package/src/server/recap-image-route.ts +242 -0
  1766. package/src/server/recap-image-store.ts +185 -0
  1767. package/src/server/request-context.ts +416 -0
  1768. package/src/server/request-origin.ts +67 -0
  1769. package/src/server/resources-plugin.ts +119 -0
  1770. package/src/server/schema-prompt.ts +429 -0
  1771. package/src/server/scoped-key-storage.ts +223 -0
  1772. package/src/server/security-headers.ts +170 -0
  1773. package/src/server/self-dispatch.ts +224 -0
  1774. package/src/server/sentry-config.ts +73 -0
  1775. package/src/server/sentry-plugin.ts +138 -0
  1776. package/src/server/sentry.ts +444 -0
  1777. package/src/server/short-lived-token.ts +170 -0
  1778. package/src/server/social-og-image.ts +454 -0
  1779. package/src/server/sse.ts +102 -0
  1780. package/src/server/ssr-handler.ts +466 -0
  1781. package/src/server/transcribe-voice.ts +1076 -0
  1782. package/src/server/voice-providers-status.ts +118 -0
  1783. package/src/server/workspace-oauth.ts +31 -0
  1784. package/src/server/workspace-provider-oauth.ts +970 -0
  1785. package/src/session-replay-iframe-protocol.ts +58 -0
  1786. package/src/settings/handlers.ts +44 -0
  1787. package/src/settings/index.ts +34 -0
  1788. package/src/settings/org-settings.ts +83 -0
  1789. package/src/settings/script-helpers.ts +24 -0
  1790. package/src/settings/store.ts +247 -0
  1791. package/src/settings/user-settings.ts +47 -0
  1792. package/src/setup-connections/index.ts +90 -0
  1793. package/src/setup-connections/onboarding.ts +47 -0
  1794. package/src/shared/agent-access.ts +112 -0
  1795. package/src/shared/agent-chat.ts +124 -0
  1796. package/src/shared/agent-env.ts +46 -0
  1797. package/src/shared/agent-readable-resource.ts +111 -0
  1798. package/src/shared/agent-sidebar-url.ts +39 -0
  1799. package/src/shared/cache-control.ts +25 -0
  1800. package/src/shared/cloudflare-globals.d.ts +34 -0
  1801. package/src/shared/context-xray.ts +172 -0
  1802. package/src/shared/embed-auth.ts +6 -0
  1803. package/src/shared/index.ts +83 -0
  1804. package/src/shared/llm-connection.ts +42 -0
  1805. package/src/shared/markdown-block-split.ts +129 -0
  1806. package/src/shared/mcp-connect-content.ts +130 -0
  1807. package/src/shared/mcp-embed-headers.ts +175 -0
  1808. package/src/shared/mcp-integration-config.ts +101 -0
  1809. package/src/shared/merge-by-id.ts +14 -0
  1810. package/src/shared/oauth-state.ts +39 -0
  1811. package/src/shared/reasoning-effort.ts +228 -0
  1812. package/src/shared/route-warmup-config.ts +128 -0
  1813. package/src/shared/runtime.ts +31 -0
  1814. package/src/shared/social-meta.ts +82 -0
  1815. package/src/shared/streaming-text-smoothing.ts +184 -0
  1816. package/src/shared/truncate.ts +13 -0
  1817. package/src/shared/workspace-app-audience.ts +177 -0
  1818. package/src/shared/workspace-app-id.ts +54 -0
  1819. package/src/sharing/access.ts +585 -0
  1820. package/src/sharing/actions/create-agent-resource-link.ts +91 -0
  1821. package/src/sharing/actions/extension-change.ts +22 -0
  1822. package/src/sharing/actions/list-resource-shares.ts +93 -0
  1823. package/src/sharing/actions/set-resource-visibility.ts +91 -0
  1824. package/src/sharing/actions/share-resource.ts +322 -0
  1825. package/src/sharing/actions/unshare-resource.ts +72 -0
  1826. package/src/sharing/index.ts +35 -0
  1827. package/src/sharing/registry.ts +201 -0
  1828. package/src/sharing/schema.ts +99 -0
  1829. package/src/styles/agent-conversation.css +766 -0
  1830. package/src/styles/agent-native.css +938 -0
  1831. package/src/styles/blocks.css +1717 -0
  1832. package/src/styles/chat-history-list.css +1 -0
  1833. package/src/styles/rich-markdown-editor.css +1 -0
  1834. package/src/tailwind.preset.ts +140 -0
  1835. package/src/templates/chat/.agents/skills/actions/SKILL.md +32 -12
  1836. package/src/templates/chat/.agents/skills/agent-native-docs/SKILL.md +21 -9
  1837. package/src/templates/chat/.agents/skills/customizing-agent-native/SKILL.md +145 -0
  1838. package/src/templates/chat/.agents/skills/self-modifying-code/SKILL.md +14 -2
  1839. package/src/templates/chat/.agents/skills/upgrade-agent-native/SKILL.md +6 -0
  1840. package/src/templates/chat/AGENTS.md +6 -2
  1841. package/src/templates/chat/app/components/layout/Sidebar.tsx +51 -157
  1842. package/src/templates/default/.agents/skills/actions/SKILL.md +32 -12
  1843. package/src/templates/default/.agents/skills/agent-native-docs/SKILL.md +21 -9
  1844. package/src/templates/default/.agents/skills/customizing-agent-native/SKILL.md +145 -0
  1845. package/src/templates/default/.agents/skills/integration-webhooks/SKILL.md +323 -0
  1846. package/src/templates/default/.agents/skills/onboarding/SKILL.md +56 -0
  1847. package/src/templates/default/.agents/skills/secrets/SKILL.md +273 -0
  1848. package/src/templates/default/.agents/skills/self-modifying-code/SKILL.md +14 -2
  1849. package/src/templates/default/.agents/skills/upgrade-agent-native/SKILL.md +6 -0
  1850. package/src/templates/default/AGENTS.md +26 -18
  1851. package/src/templates/headless/.agents/skills/actions/SKILL.md +512 -0
  1852. package/src/templates/headless/.agents/skills/agent-native-docs/SKILL.md +21 -9
  1853. package/src/templates/headless/.agents/skills/customizing-agent-native/SKILL.md +145 -0
  1854. package/src/templates/headless/.agents/skills/integration-webhooks/SKILL.md +323 -0
  1855. package/src/templates/headless/.agents/skills/secrets/SKILL.md +273 -0
  1856. package/src/templates/headless/.agents/skills/upgrade-agent-native/SKILL.md +6 -0
  1857. package/src/templates/headless/AGENTS.md +8 -0
  1858. package/src/templates/workspace-core/.agents/skills/actions/SKILL.md +32 -12
  1859. package/src/templates/workspace-core/.agents/skills/agent-native-docs/SKILL.md +21 -9
  1860. package/src/templates/workspace-core/.agents/skills/agent-native-toolkit/SKILL.md +7 -0
  1861. package/src/templates/workspace-core/.agents/skills/customizing-agent-native/SKILL.md +145 -0
  1862. package/src/templates/workspace-core/.agents/skills/self-modifying-code/SKILL.md +14 -2
  1863. package/src/templates/workspace-core/.agents/skills/upgrade-agent-native/SKILL.md +6 -0
  1864. package/src/templates/workspace-core/AGENTS.md +4 -0
  1865. package/src/templates/workspace-root/AGENTS.md +4 -0
  1866. package/src/terminal/cli-registry.ts +57 -0
  1867. package/src/terminal/index.ts +22 -0
  1868. package/src/terminal/pty-server.ts +389 -0
  1869. package/src/terminal/terminal-plugin.ts +265 -0
  1870. package/src/testing.ts +23 -0
  1871. package/src/tracking/index.ts +10 -0
  1872. package/src/tracking/providers.ts +422 -0
  1873. package/src/tracking/registry.ts +102 -0
  1874. package/src/tracking/route.ts +108 -0
  1875. package/src/tracking/types.ts +16 -0
  1876. package/src/transcription/builder-transcription.ts +118 -0
  1877. package/src/triggers/actions/list-automations.ts +99 -0
  1878. package/src/triggers/actions/manage-automation.ts +78 -0
  1879. package/src/triggers/actions.ts +333 -0
  1880. package/src/triggers/condition-evaluator.ts +163 -0
  1881. package/src/triggers/dispatcher.ts +536 -0
  1882. package/src/triggers/index.ts +13 -0
  1883. package/src/triggers/routes.ts +322 -0
  1884. package/src/triggers/types.ts +42 -0
  1885. package/src/types/pglite.d.ts +26 -0
  1886. package/src/usage/store.ts +698 -0
  1887. package/src/vite/action-types-plugin.ts +481 -0
  1888. package/src/vite/agent-web-plugin.ts +78 -0
  1889. package/src/vite/agents-bundle-plugin.ts +185 -0
  1890. package/src/vite/client.ts +3039 -0
  1891. package/src/vite/index.ts +21 -0
  1892. package/src/voice/index.ts +18 -0
  1893. package/src/voice/voice-cleanup-prompt.ts +38 -0
  1894. package/src/voice/voice-context.ts +217 -0
  1895. package/src/voice/voice-replacements.ts +75 -0
  1896. package/src/workspace-connections/credentials.ts +603 -0
  1897. package/src/workspace-connections/index.ts +72 -0
  1898. package/src/workspace-connections/lifecycle.ts +43 -0
  1899. package/src/workspace-connections/store.ts +1943 -0
  1900. package/src/workspace-files/index.ts +18 -0
  1901. package/src/workspace-files/store.ts +339 -0
  1902. package/src/workspace-files/tool.ts +266 -0
@@ -0,0 +1,3048 @@
1
+ import {
2
+ defineEventHandler,
3
+ setResponseStatus,
4
+ setResponseHeader,
5
+ getMethod,
6
+ getQuery,
7
+ sendRedirect,
8
+ } from "h3";
9
+ import { getRequestHeader } from "h3";
10
+ import { createRemoteJWKSet, jwtVerify } from "jose";
11
+
12
+ import { abortRun } from "../agent/run-manager.js";
13
+ import { getOrgContext, resolveOrgIdForEmail } from "../org/context.js";
14
+ import { loadResourcesForPrompt } from "../server/agent-chat-plugin.js";
15
+ import { withConfiguredAppBasePath } from "../server/app-base-path.js";
16
+ import { getSession } from "../server/auth.js";
17
+ import { FRAMEWORK_ROUTE_PREFIX } from "../server/core-routes-plugin.js";
18
+ import { resolveSecret } from "../server/credential-provider.js";
19
+ import {
20
+ getH3App,
21
+ markDefaultPluginProvided,
22
+ } from "../server/framework-request-handler.js";
23
+ import {
24
+ decodeOAuthState,
25
+ encodeOAuthState,
26
+ oauthCallbackResponse,
27
+ oauthErrorPage,
28
+ resolveOAuthRedirectUri,
29
+ } from "../server/google-oauth.js";
30
+ import { readBody } from "../server/h3-helpers.js";
31
+ import { runWithRequestContext } from "../server/request-context.js";
32
+ import {
33
+ processA2AContinuationById,
34
+ processDueA2AContinuations,
35
+ } from "./a2a-continuation-processor.js";
36
+ import { failA2AContinuation } from "./a2a-continuations-store.js";
37
+ import { mergeIntegrationAdapters } from "./adapter-overrides.js";
38
+ import { discordAdapter } from "./adapters/discord.js";
39
+ import { emailAdapter } from "./adapters/email.js";
40
+ import { googleDocsAdapter } from "./adapters/google-docs.js";
41
+ import { microsoftTeamsAdapter } from "./adapters/microsoft-teams.js";
42
+ import { slackAdapter } from "./adapters/slack.js";
43
+ import { telegramAdapter } from "./adapters/telegram.js";
44
+ import { whatsappAdapter } from "./adapters/whatsapp.js";
45
+ import {
46
+ createComputerApprovalRequest,
47
+ decideComputerApproval,
48
+ listComputerApprovalsForOwner,
49
+ } from "./computer-supervision-store.js";
50
+ import { ComputerSupervisionError } from "./computer-supervision.js";
51
+ import { getIntegrationConfig, saveIntegrationConfig } from "./config-store.js";
52
+ import { claimIntegrationControl } from "./controls-store.js";
53
+ import {
54
+ startGoogleDocsPoller,
55
+ handlePushNotification,
56
+ } from "./google-docs-poller.js";
57
+ import {
58
+ IntegrationIdentityDeclinedError,
59
+ resolveDefaultIntegrationExecutionContext,
60
+ } from "./identity.js";
61
+ import {
62
+ disconnectIntegrationInstallation,
63
+ listIntegrationInstallations,
64
+ resolveIntegrationTokenBundle,
65
+ updateIntegrationInstallation,
66
+ upsertIntegrationInstallation,
67
+ } from "./installations-store.js";
68
+ import {
69
+ forgetIntegrationMemory,
70
+ integrationMemoryActions,
71
+ listIntegrationMemory,
72
+ rememberForIntegrationScope,
73
+ } from "./integration-memory.js";
74
+ import {
75
+ extractBearerToken,
76
+ signInternalToken,
77
+ verifyInternalToken,
78
+ } from "./internal-token.js";
79
+ import { startPendingTasksRetryJob } from "./pending-tasks-retry-job.js";
80
+ import {
81
+ claimPendingTask,
82
+ failTaskDeliveryTransition,
83
+ getNextPendingTaskIdForThread,
84
+ insertPendingTask,
85
+ isDuplicateEventError,
86
+ MAX_PENDING_TASK_ATTEMPTS,
87
+ markTaskCompleted,
88
+ markTaskDeliveryRetryable,
89
+ markTaskFailed,
90
+ markTaskRetryable,
91
+ stageTaskDeliveryPayload,
92
+ } from "./pending-tasks-store.js";
93
+ import {
94
+ claimNextComputerCommand,
95
+ claimNextRemoteCommand,
96
+ enqueueComputerCommand,
97
+ enqueueRemoteCommand as enqueueRemoteCommandRow,
98
+ isRemoteCommandKind,
99
+ listRemoteCommandsForOwner,
100
+ updateRemoteCommandResult,
101
+ } from "./remote-commands-store.js";
102
+ import {
103
+ authenticateRemoteDeviceToken,
104
+ createRemoteDevice,
105
+ getRemoteComputerCapabilities,
106
+ getRemoteDeviceForOwner,
107
+ listRemoteDevicesForOwner,
108
+ revokeRemoteDeviceForOwner,
109
+ toPublicRemoteDevice,
110
+ unregisterRemoteDevice,
111
+ updateRemoteDeviceDetails,
112
+ } from "./remote-devices-store.js";
113
+ import { startRemotePushDeliveryJob } from "./remote-push-delivery-job.js";
114
+ import {
115
+ listRemotePushNotificationsForOwner,
116
+ listRemotePushRegistrationsForOwner,
117
+ queueRemotePushNotifications,
118
+ toPublicRemotePushRegistration,
119
+ unregisterRemotePushRegistrationForOwner,
120
+ upsertRemotePushRegistration,
121
+ } from "./remote-push-store.js";
122
+ import { startRemoteCommandsRetryJob } from "./remote-retry-job.js";
123
+ import {
124
+ insertRemoteRunEvents,
125
+ listRemoteRunEvents,
126
+ } from "./remote-run-events-store.js";
127
+ import type {
128
+ ComputerCommandEnvelope,
129
+ ComputerOperationClass,
130
+ RemoteCommand,
131
+ RemoteCommandKind,
132
+ RemoteDevice,
133
+ } from "./remote-types.js";
134
+ import { listIntegrationScopes, saveIntegrationScope } from "./scope-store.js";
135
+ import { buildSlackAgentManifest } from "./slack-manifest.js";
136
+ import {
137
+ assertSlackInstallAccess,
138
+ buildSlackAuthorizeUrl,
139
+ exchangeSlackOAuthCode,
140
+ slackOAuthResponseToInstallation,
141
+ testSlackAuth,
142
+ } from "./slack-oauth.js";
143
+ import { getTaskQueueStats } from "./task-queue-stats.js";
144
+ import type {
145
+ PlatformAdapter,
146
+ IntegrationsPluginOptions,
147
+ IntegrationStatus,
148
+ IntegrationExecutionContext,
149
+ IncomingMessage,
150
+ PlatformDeliveryReceipt,
151
+ } from "./types.js";
152
+ import {
153
+ listIntegrationUsageBudgets,
154
+ saveIntegrationUsageBudget,
155
+ } from "./usage-budget-store.js";
156
+ import {
157
+ handleWebhook,
158
+ processIntegrationTask,
159
+ recordIntegrationResponseDelivery,
160
+ type IntegrationResponseDeliveryTaskPayload,
161
+ } from "./webhook-handler.js";
162
+
163
+ type NitroPluginDef = (nitroApp: any) => void | Promise<void>;
164
+
165
+ let a2aContinuationRetryInterval: ReturnType<typeof setInterval> | null = null;
166
+
167
+ function startA2AContinuationRetryJob(
168
+ adapters: Map<string, PlatformAdapter>,
169
+ ): void {
170
+ if (a2aContinuationRetryInterval) return;
171
+ const initialTimer = setTimeout(() => {
172
+ processDueA2AContinuations({ adapters }).catch((err) => {
173
+ console.error("[integrations] A2A continuation retry job failed:", err);
174
+ });
175
+ }, 10_000);
176
+ unrefTimer(initialTimer);
177
+ a2aContinuationRetryInterval = setInterval(() => {
178
+ processDueA2AContinuations({ adapters }).catch((err) => {
179
+ console.error("[integrations] A2A continuation retry job failed:", err);
180
+ });
181
+ }, 60_000);
182
+ unrefTimer(a2aContinuationRetryInterval);
183
+ }
184
+
185
+ function unrefTimer(timer: ReturnType<typeof setInterval>): void {
186
+ (timer as unknown as { unref?: () => void }).unref?.();
187
+ }
188
+
189
+ // ─── Google Pub/Sub OIDC verifier (for Drive changes.watch push) ────────────
190
+ // Cache Google's public keys for OIDC verification. jose handles TTL +
191
+ // refresh internally — same pattern as templates/mail/.../gmail/push.post.ts.
192
+ // Used to verify Google Pub/Sub push notifications carry a valid bearer token
193
+ // signed by a configured service account. Without this, the webhook is wide
194
+ // open to anonymous callers who can force a Drive sync (H7 in the audit).
195
+ const GOOGLE_JWKS = createRemoteJWKSet(
196
+ new URL("https://www.googleapis.com/oauth2/v3/certs"),
197
+ );
198
+ const GOOGLE_ISSUERS = ["https://accounts.google.com", "accounts.google.com"];
199
+
200
+ /**
201
+ * Verify a Pub/Sub OIDC bearer token. Throws on any verification failure.
202
+ * Requires GOOGLE_DOCS_PUSH_AUDIENCE and GOOGLE_DOCS_PUSH_SIGNER_EMAIL to be
203
+ * set; if either is missing in production, the webhook handler refuses the
204
+ * request entirely (so a misconfigured deployment fails closed, surfacing in
205
+ * Pub/Sub's delivery metrics).
206
+ */
207
+ async function verifyGoogleDocsPushToken(authHeader: string): Promise<void> {
208
+ if (!authHeader.startsWith("Bearer ")) {
209
+ throw new Error("missing bearer token");
210
+ }
211
+ const token = authHeader.slice(7);
212
+ const audience = process.env.GOOGLE_DOCS_PUSH_AUDIENCE;
213
+ if (!audience) {
214
+ throw new Error("GOOGLE_DOCS_PUSH_AUDIENCE not configured");
215
+ }
216
+ const { payload } = await jwtVerify(token, GOOGLE_JWKS, {
217
+ issuer: GOOGLE_ISSUERS,
218
+ audience,
219
+ });
220
+ if (payload.email_verified !== true) {
221
+ throw new Error("email_verified claim is not true");
222
+ }
223
+ // Pin to a specific service account — without this, any Google-issued
224
+ // token with the right audience could trigger a Drive sync.
225
+ const expectedSigner = process.env.GOOGLE_DOCS_PUSH_SIGNER_EMAIL;
226
+ if (!expectedSigner) {
227
+ throw new Error("GOOGLE_DOCS_PUSH_SIGNER_EMAIL not configured");
228
+ }
229
+ if (payload.email !== expectedSigner) {
230
+ throw new Error(`unexpected signer: ${String(payload.email)}`);
231
+ }
232
+ }
233
+
234
+ export const BUILT_IN_INTEGRATION_ADAPTER_FACTORIES = Object.freeze([
235
+ { platform: "slack", create: slackAdapter },
236
+ { platform: "telegram", create: telegramAdapter },
237
+ { platform: "whatsapp", create: whatsappAdapter },
238
+ { platform: "microsoft-teams", create: microsoftTeamsAdapter },
239
+ { platform: "discord", create: discordAdapter },
240
+ { platform: "google-docs", create: googleDocsAdapter },
241
+ { platform: "email", create: emailAdapter },
242
+ ] as const satisfies ReadonlyArray<{
243
+ platform: string;
244
+ create: () => PlatformAdapter;
245
+ }>);
246
+
247
+ export const BUILT_IN_INTEGRATION_ADAPTER_IDS = Object.freeze(
248
+ BUILT_IN_INTEGRATION_ADAPTER_FACTORIES.map(({ platform }) => platform),
249
+ );
250
+
251
+ export function createBuiltInIntegrationAdapters(): PlatformAdapter[] {
252
+ return BUILT_IN_INTEGRATION_ADAPTER_FACTORIES.map(({ create }) => create());
253
+ }
254
+
255
+ const INTEGRATION_SYSTEM_PROMPT = `You are an AI agent responding via a messaging platform integration (Slack, Microsoft Teams, Discord interactions, Telegram, WhatsApp, etc.).
256
+
257
+ You have the same capabilities as the web chat agent. Use your tools to help the user.
258
+
259
+ Keep responses concise — messaging platforms have character limits and users expect shorter replies than in a web interface. Use markdown sparingly (bold and lists are fine, but avoid complex formatting that may not render well on all platforms).
260
+
261
+ If a task requires many steps, summarize what you did rather than streaming every detail.`;
262
+
263
+ type RemoteCodeCommandEnvelope = {
264
+ kind?: unknown;
265
+ ownerEmail?: unknown;
266
+ orgId?: unknown;
267
+ command?: unknown;
268
+ source?: unknown;
269
+ };
270
+
271
+ type IntegrationCredentialContext = {
272
+ userEmail: string;
273
+ orgId?: string;
274
+ isIntegrationCaller?: boolean;
275
+ };
276
+
277
+ const REMOTE_DEVICE_ONLINE_MS = 90_000;
278
+
279
+ // One decline reply per sender + decline reason per window: during a Slack
280
+ // API outage every message would otherwise get another identical "try again"
281
+ // reply. Short enough that a persistent condition still reminds the sender.
282
+ const DECLINE_NOTICE_DEDUPE_TTL_MS = 5 * 60 * 1_000;
283
+ const SYSTEM_NOTICE_DEDUPE_TTL_MS = 24 * 60 * 60 * 1_000;
284
+
285
+ type IntegrationSystemNoticeTaskPayload = {
286
+ kind: "system-notice";
287
+ incoming: IncomingMessage;
288
+ text: string;
289
+ dedupeKey?: string;
290
+ dedupeTtlMs?: number;
291
+ };
292
+
293
+ function systemNoticeEventKey(
294
+ dedupeKey: string,
295
+ ttlMs: number,
296
+ now = Date.now(),
297
+ ): string {
298
+ return `system-notice:${dedupeKey}:${Math.floor(now / ttlMs)}`;
299
+ }
300
+
301
+ export async function enqueueRemoteCommand(
302
+ envelope: RemoteCodeCommandEnvelope,
303
+ ): Promise<Record<string, unknown>> {
304
+ const ownerEmail = readString(envelope.ownerEmail);
305
+ if (!ownerEmail) throw new Error("ownerEmail is required");
306
+ const hasOrgId = Object.prototype.hasOwnProperty.call(envelope, "orgId");
307
+ const orgId = hasOrgId ? (readString(envelope.orgId) ?? null) : undefined;
308
+ const command = readObject(envelope.command);
309
+ if (!command) throw new Error("command is required");
310
+ const commandType = readString(command.type);
311
+ const commands = await listRemoteCommandsForOwner({
312
+ ownerEmail,
313
+ ...(hasOrgId ? { orgId } : {}),
314
+ limit: 50,
315
+ });
316
+
317
+ if (commandType === "list") {
318
+ return {
319
+ ok: true,
320
+ runs: commands.map(remoteCommandToRunSummary).filter(Boolean),
321
+ hostOnline: await hasOnlineRemoteDevice(ownerEmail, orgId),
322
+ };
323
+ }
324
+
325
+ if (commandType === "status") {
326
+ const runRef = readString(command.runRef);
327
+ const run = runRef
328
+ ? commands.map(remoteCommandToRunSummary).find((item) => {
329
+ const candidate = item as Record<string, unknown>;
330
+ return candidate.id === runRef || candidate.runId === runRef;
331
+ })
332
+ : undefined;
333
+ const hostOnline = await hasOnlineRemoteDevice(ownerEmail, orgId);
334
+ return {
335
+ ok: true,
336
+ hostOnline,
337
+ hostStatus: hostOnline ? "online" : "offline",
338
+ ...(run ? { run } : {}),
339
+ };
340
+ }
341
+
342
+ const devices = await listRemoteDevicesForOwner({
343
+ ownerEmail,
344
+ ...(hasOrgId ? { orgId } : {}),
345
+ status: "active",
346
+ limit: 10,
347
+ });
348
+ const requestedDeviceId =
349
+ readString(command.hostId) ?? readString(command.deviceId);
350
+ const device =
351
+ (requestedDeviceId
352
+ ? devices.find((candidate) => candidate.id === requestedDeviceId)
353
+ : undefined) ?? devices[0];
354
+ if (!device) {
355
+ return {
356
+ ok: false,
357
+ hostOnline: false,
358
+ hostStatus: "offline",
359
+ error: "No paired computer is available for code-agent commands.",
360
+ };
361
+ }
362
+
363
+ const source = readObject(envelope.source);
364
+ const kind = remoteCodeCommandKind(commandType);
365
+ if (!kind) throw new Error(`Unsupported code-agent command: ${commandType}`);
366
+ const row = await enqueueRemoteCommandRow({
367
+ deviceId: device.id,
368
+ ownerEmail,
369
+ orgId: device.orgId ?? orgId ?? null,
370
+ kind,
371
+ params: remoteCodeCommandParams(command),
372
+ platform: readString(source?.platform) ?? null,
373
+ externalThreadId: readString(source?.externalThreadId) ?? null,
374
+ });
375
+ const hostOnline = isRemoteDeviceOnline(device);
376
+ return {
377
+ ok: true,
378
+ commandId: row.id,
379
+ requestId: row.id,
380
+ hostOnline,
381
+ hostStatus: hostOnline ? "online" : "offline",
382
+ message:
383
+ commandType === "create"
384
+ ? hostOnline
385
+ ? `Queued code run (${row.id}).`
386
+ : `Queued code run (${row.id}). Your computer looks offline or asleep, so it will pick this up when it wakes.`
387
+ : undefined,
388
+ };
389
+ }
390
+
391
+ function remoteCodeCommandKind(
392
+ commandType: string | undefined,
393
+ ): RemoteCommandKind | null {
394
+ switch (commandType) {
395
+ case "create":
396
+ return "create-run";
397
+ case "continue":
398
+ return "append-followup";
399
+ case "approve":
400
+ return "approve";
401
+ case "deny":
402
+ return "deny";
403
+ case "stop":
404
+ return "stop";
405
+ default:
406
+ return null;
407
+ }
408
+ }
409
+
410
+ function remoteCodeCommandParams(
411
+ command: Record<string, unknown>,
412
+ ): Record<string, unknown> {
413
+ const type = readString(command.type);
414
+ if (type === "create") {
415
+ return {
416
+ prompt: readString(command.prompt) ?? "",
417
+ title: readString(command.title),
418
+ cwd: readString(command.cwd),
419
+ goalId: readString(command.goalId) ?? "task",
420
+ permissionMode: readString(command.permissionMode),
421
+ };
422
+ }
423
+ if (type === "continue") {
424
+ return {
425
+ runId: readString(command.runRef) ?? readString(command.runId),
426
+ prompt: readString(command.text) ?? readString(command.prompt),
427
+ permissionMode: readString(command.permissionMode),
428
+ };
429
+ }
430
+ if (type === "approve" || type === "deny") {
431
+ const id = readString(command.approvalId) ?? readString(command.runId);
432
+ return { runId: id, approvalId: id };
433
+ }
434
+ if (type === "stop") {
435
+ return { runId: readString(command.runRef) ?? readString(command.runId) };
436
+ }
437
+ return {};
438
+ }
439
+
440
+ function enqueueBodyToRemoteCodeCommand(
441
+ body: Record<string, unknown>,
442
+ ): Record<string, unknown> | null {
443
+ const direct = readObject(body.command);
444
+ if (body.kind === "code-agent" && direct) return direct;
445
+
446
+ const operation = readString(body.operation) ?? readString(body.type);
447
+ const payload = readObject(body.payload) ?? body;
448
+ if (!operation?.startsWith("code-agent.")) return null;
449
+
450
+ if (operation === "code-agent.run.create") {
451
+ return {
452
+ type: "create",
453
+ prompt: payload.prompt,
454
+ title: payload.title,
455
+ hostId: payload.hostId,
456
+ deviceId: payload.deviceId,
457
+ cwd: payload.cwd,
458
+ goalId: payload.goalId,
459
+ permissionMode: payload.permissionMode,
460
+ };
461
+ }
462
+ if (operation === "code-agent.run.follow-up") {
463
+ return {
464
+ type: "continue",
465
+ runRef: payload.runId,
466
+ text: payload.prompt ?? payload.message,
467
+ hostId: payload.hostId,
468
+ deviceId: payload.deviceId,
469
+ permissionMode: payload.permissionMode,
470
+ };
471
+ }
472
+ if (operation === "code-agent.pending-command.decide") {
473
+ return {
474
+ type: payload.decision === "deny" ? "deny" : "approve",
475
+ approvalId: payload.commandId ?? payload.runId,
476
+ runId: payload.runId,
477
+ hostId: payload.hostId,
478
+ deviceId: payload.deviceId,
479
+ };
480
+ }
481
+ if (operation === "code-agent.run.stop") {
482
+ return {
483
+ type: "stop",
484
+ runRef: payload.runId,
485
+ hostId: payload.hostId,
486
+ deviceId: payload.deviceId,
487
+ };
488
+ }
489
+ return null;
490
+ }
491
+
492
+ function remoteCommandToRunSummary(
493
+ command: RemoteCommand,
494
+ ): Record<string, unknown> | null {
495
+ const result = readObject(command.result);
496
+ const nestedResult = readObject(result?.result) ?? result;
497
+ const run = readObject(nestedResult?.run);
498
+ if (run) {
499
+ return {
500
+ ...run,
501
+ commandId: command.id,
502
+ hostId: command.deviceId,
503
+ status: readString(run.status) ?? command.status,
504
+ updatedAt: readString(run.updatedAt) ?? command.updatedAt,
505
+ };
506
+ }
507
+ if (command.kind !== "create-run") return null;
508
+ const params = readObject(command.params) ?? {};
509
+ return {
510
+ id: command.id,
511
+ runId: command.id,
512
+ hostId: command.deviceId,
513
+ title:
514
+ readString(params.title) ?? readString(params.prompt) ?? "Queued run",
515
+ prompt: readString(params.prompt),
516
+ status: command.status === "failed" ? "errored" : "queued",
517
+ createdAt: command.createdAt,
518
+ updatedAt: command.updatedAt,
519
+ metadata: { remoteCommandId: command.id },
520
+ };
521
+ }
522
+
523
+ function readObject(value: unknown): Record<string, unknown> | null {
524
+ return value && typeof value === "object" && !Array.isArray(value)
525
+ ? (value as Record<string, unknown>)
526
+ : null;
527
+ }
528
+
529
+ function readString(value: unknown): string | undefined {
530
+ return typeof value === "string" && value.trim() ? value.trim() : undefined;
531
+ }
532
+
533
+ function isRemoteDeviceOnline(device: { lastSeenAt: number | null }): boolean {
534
+ return typeof device.lastSeenAt === "number"
535
+ ? Date.now() - device.lastSeenAt <= REMOTE_DEVICE_ONLINE_MS
536
+ : false;
537
+ }
538
+
539
+ async function hasOnlineRemoteDevice(
540
+ ownerEmail: string,
541
+ orgId: string | null | undefined,
542
+ ): Promise<boolean> {
543
+ const hasOrgId = orgId !== undefined;
544
+ const devices = await listRemoteDevicesForOwner({
545
+ ownerEmail,
546
+ ...(hasOrgId ? { orgId } : {}),
547
+ status: "active",
548
+ limit: 10,
549
+ });
550
+ return devices.some(isRemoteDeviceOnline);
551
+ }
552
+
553
+ function remoteDeviceToHost(device: RemoteDevice): Record<string, unknown> {
554
+ const online = device.status === "active" && isRemoteDeviceOnline(device);
555
+ return {
556
+ id: device.id,
557
+ name: device.label,
558
+ label: device.label,
559
+ status:
560
+ device.status === "active" ? (online ? "online" : "offline") : "revoked",
561
+ lastSeenAt: device.lastSeenAt
562
+ ? new Date(device.lastSeenAt).toISOString()
563
+ : undefined,
564
+ platform: device.platform ?? "desktop",
565
+ appVersion: device.appVersion ?? undefined,
566
+ hostName: device.hostName ?? undefined,
567
+ metadata: device.metadata ?? undefined,
568
+ device: toPublicRemoteDevice(device),
569
+ };
570
+ }
571
+
572
+ function mountedPathParts(event: any, mountSuffix: string): string[] {
573
+ const rawPath = String(
574
+ event.path ?? event.url?.pathname ?? event.node?.req?.url ?? "/",
575
+ ).split("?")[0];
576
+ const normalized = rawPath.replace(/^\/+/, "");
577
+ const marker = mountSuffix.replace(/^\/+/, "");
578
+ const markerIndex = normalized.indexOf(marker);
579
+ const suffix =
580
+ markerIndex >= 0
581
+ ? normalized.slice(markerIndex + marker.length)
582
+ : normalized;
583
+ return suffix
584
+ .split("/")
585
+ .filter(Boolean)
586
+ .map((part) => decodeURIComponent(part));
587
+ }
588
+
589
+ function remoteCommandPushPayload(
590
+ command: RemoteCommand,
591
+ ): Record<string, unknown> {
592
+ const status = command.status;
593
+ const title =
594
+ status === "completed"
595
+ ? "Remote run completed"
596
+ : status === "failed"
597
+ ? "Remote run failed"
598
+ : "Remote run updated";
599
+ const body =
600
+ status === "completed"
601
+ ? "Open Agent Native to review the result."
602
+ : status === "failed"
603
+ ? "Open Agent Native to review the failure."
604
+ : "Open Agent Native to review the latest status.";
605
+ return {
606
+ title,
607
+ body,
608
+ commandId: command.id,
609
+ hostId: command.deviceId,
610
+ kind: command.kind,
611
+ status,
612
+ updatedAt: command.updatedAt,
613
+ };
614
+ }
615
+
616
+ /**
617
+ * Creates a Nitro plugin that mounts messaging platform integration webhook routes.
618
+ *
619
+ * Routes:
620
+ * POST /_agent-native/integrations/:platform/webhook — receive platform webhooks
621
+ * GET /_agent-native/integrations/status — all integrations status
622
+ * GET /_agent-native/integrations/:platform/status — single platform status
623
+ * POST /_agent-native/integrations/:platform/enable — enable integration
624
+ * POST /_agent-native/integrations/:platform/disable — disable integration
625
+ * POST /_agent-native/integrations/:platform/setup — platform-specific setup
626
+ */
627
+ export function createIntegrationsPlugin(
628
+ options?: IntegrationsPluginOptions,
629
+ ): NitroPluginDef {
630
+ if (
631
+ options?.adapters !== undefined &&
632
+ options.adapterOverrides !== undefined
633
+ ) {
634
+ throw new Error(
635
+ "Choose either adapters for full replacement or adapterOverrides for per-platform customization.",
636
+ );
637
+ }
638
+ return async (nitroApp: any) => {
639
+ markDefaultPluginProvided(nitroApp, "integrations");
640
+ const adapters =
641
+ options?.adapters ??
642
+ mergeIntegrationAdapters(
643
+ createBuiltInIntegrationAdapters(),
644
+ options?.adapterOverrides,
645
+ );
646
+ const adapterMap = new Map<string, PlatformAdapter>();
647
+ for (const adapter of adapters) {
648
+ adapterMap.set(adapter.platform, adapter);
649
+ }
650
+
651
+ const model = options?.model;
652
+ // Read the API key at REQUEST time, not plugin-init time. On Netlify
653
+ // Lambda the plugin module loads in a context where env vars from the
654
+ // site's runtime config may not yet be populated, so capturing at
655
+ // init can leave us with an empty string forever. The getter
656
+ // re-resolves on every webhook so freshly-set secrets work without
657
+ // a redeploy.
658
+ const getApiKey = () => options?.apiKey ?? "";
659
+
660
+ // Build the system prompt
661
+ const baseSystemPrompt = options?.systemPrompt ?? INTEGRATION_SYSTEM_PROMPT;
662
+
663
+ // Resolve actions — auto-include call-agent so the integration agent can
664
+ // delegate to other A2A apps, matching the behavior of the agent-chat plugin.
665
+ const localActions = options?.actions ?? {};
666
+ let callAgentEntry: Record<string, unknown> = {};
667
+ try {
668
+ const mod = await import("../scripts/call-agent.js");
669
+ callAgentEntry = {
670
+ "call-agent": {
671
+ tool: mod.tool,
672
+ run: (args: Record<string, string>, context: unknown) =>
673
+ mod.run(args, context as any, options?.appId),
674
+ },
675
+ };
676
+ } catch {
677
+ // call-agent script not available — skip
678
+ }
679
+ const actions = {
680
+ ...integrationMemoryActions(),
681
+ ...localActions,
682
+ ...callAgentEntry,
683
+ } as typeof localActions;
684
+ // Keep the app's own actions visible on the first request to the model;
685
+ // defer the framework additions merged in above (integration memory,
686
+ // call-agent) behind the tool-search entry `handleWebhook` /
687
+ // `startGoogleDocsPoller` attach to `actions`. The run loop's mid-run
688
+ // tool expansion still lets the model discover and call them after a
689
+ // search — see `filterInitialEngineTools` / `expandActiveTools`.
690
+ const initialToolNames = Object.keys(localActions);
691
+
692
+ const h3 = getH3App(nitroApp);
693
+ const P = `${FRAMEWORK_ROUTE_PREFIX}/integrations`;
694
+
695
+ async function enqueueSystemNotice(
696
+ event: any,
697
+ incoming: IncomingMessage,
698
+ text: string,
699
+ opts?: { dedupeKey?: string; dedupeTtlMs?: number },
700
+ ): Promise<void> {
701
+ if (!text.trim()) return;
702
+ const taskId = `notice-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
703
+ const dedupeTtlMs = Math.max(
704
+ 1,
705
+ opts?.dedupeTtlMs ?? SYSTEM_NOTICE_DEDUPE_TTL_MS,
706
+ );
707
+ const noticeThreadId = `system-notice:${taskId}`;
708
+ const payload: IntegrationSystemNoticeTaskPayload = {
709
+ kind: "system-notice",
710
+ incoming,
711
+ text,
712
+ ...(opts?.dedupeKey ? { dedupeKey: opts.dedupeKey } : {}),
713
+ ...(opts?.dedupeTtlMs ? { dedupeTtlMs: opts.dedupeTtlMs } : {}),
714
+ };
715
+ try {
716
+ await insertPendingTask({
717
+ id: taskId,
718
+ platform: incoming.platform,
719
+ // System notices are auxiliary delivery work, not the user's agent
720
+ // run. Give each notice its own queue lane so a retrying notice cannot
721
+ // block the real message task for this Slack/Telegram thread.
722
+ externalThreadId: noticeThreadId,
723
+ payload: JSON.stringify(payload),
724
+ ownerEmail: `integration@${incoming.platform}`,
725
+ externalEventKey: opts?.dedupeKey
726
+ ? systemNoticeEventKey(opts.dedupeKey, dedupeTtlMs)
727
+ : undefined,
728
+ });
729
+ } catch (err) {
730
+ if (isDuplicateEventError(err)) return;
731
+ throw err;
732
+ }
733
+
734
+ // The SQL row is the durable source of truth. This best-effort self-call
735
+ // only reduces latency; the recurring pending-task sweep retries a row
736
+ // if the serverless host freezes this webhook execution immediately.
737
+ let token: string | undefined;
738
+ try {
739
+ token = signInternalToken(taskId);
740
+ } catch (err) {
741
+ if (process.env.NODE_ENV === "production") throw err;
742
+ }
743
+ void fetch(`${getBaseUrl(event)}${P}/process-task`, {
744
+ method: "POST",
745
+ headers: {
746
+ "Content-Type": "application/json",
747
+ ...(token ? { Authorization: `Bearer ${token}` } : {}),
748
+ },
749
+ body: JSON.stringify({ taskId }),
750
+ }).catch((err) => {
751
+ console.warn("[integrations] System notice dispatch failed:", err);
752
+ });
753
+ }
754
+
755
+ async function requireSession(event: any): Promise<boolean> {
756
+ const session = await getSession(event).catch(() => null);
757
+ if (session?.email) return true;
758
+ setResponseStatus(event, 401);
759
+ return false;
760
+ }
761
+
762
+ async function requireSessionContext(
763
+ event: any,
764
+ ): Promise<{ ownerEmail: string; orgId: string | null } | null> {
765
+ const session = await getSession(event).catch(() => null);
766
+ if (!session?.email) {
767
+ setResponseStatus(event, 401);
768
+ return null;
769
+ }
770
+ const orgCtx = await getOrgContext(event).catch(() => null);
771
+ return {
772
+ ownerEmail: session.email,
773
+ orgId: orgCtx?.orgId ?? session.orgId ?? null,
774
+ };
775
+ }
776
+
777
+ function toCredentialContext(
778
+ ctx: { ownerEmail: string; orgId: string | null },
779
+ opts?: { isIntegrationCaller?: boolean },
780
+ ): IntegrationCredentialContext {
781
+ return {
782
+ userEmail: ctx.ownerEmail,
783
+ ...(ctx.orgId ? { orgId: ctx.orgId } : {}),
784
+ ...(opts?.isIntegrationCaller ? { isIntegrationCaller: true } : {}),
785
+ };
786
+ }
787
+
788
+ async function credentialContextForIntegrationConfig(
789
+ config: Awaited<ReturnType<typeof getIntegrationConfig>>,
790
+ ): Promise<IntegrationCredentialContext | null> {
791
+ const ownerEmail =
792
+ typeof config?.owner === "string" ? config.owner.trim() : "";
793
+ if (!ownerEmail) return null;
794
+ const orgId = await resolveOrgIdForEmail(ownerEmail).catch(() => null);
795
+ return {
796
+ userEmail: ownerEmail,
797
+ ...(orgId ? { orgId } : {}),
798
+ isIntegrationCaller: true,
799
+ };
800
+ }
801
+
802
+ async function withCredentialContext<T>(
803
+ context: IntegrationCredentialContext | null,
804
+ fn: () => Promise<T>,
805
+ ): Promise<T> {
806
+ if (!context) return fn();
807
+ return runWithRequestContext(context, fn);
808
+ }
809
+
810
+ async function requireRemoteDevice(event: any) {
811
+ const token = extractBearerToken(
812
+ getRequestHeader(event, "authorization"),
813
+ );
814
+ const device = await authenticateRemoteDeviceToken(token);
815
+ if (device) return device;
816
+ setResponseStatus(event, 401);
817
+ return null;
818
+ }
819
+
820
+ /**
821
+ * Gate destructive integration writes (enable/disable, setup,
822
+ * setIntegrationConfig…) behind an org-owner/admin check.
823
+ *
824
+ * `integration_configs` is keyed `(platform, config_key)` with no
825
+ * owner column in the PRIMARY KEY — so this row is effectively
826
+ * deployment-wide. Any signed-in user toggling /enable or /disable
827
+ * would otherwise affect every other user (a regular org member could
828
+ * disable Slack/email org-wide, write a malicious allowlist for
829
+ * inbound email, etc.). This check enforces that only owners and
830
+ * admins of the user's active org may mutate integration config.
831
+ *
832
+ * Solo / no-org sessions (i.e. ctx.orgId == null) are allowed — that's
833
+ * the local-dev / single-user case where there's no privilege gradient
834
+ * to enforce. The deployment is single-tenant by definition there.
835
+ *
836
+ * Returns an `{ ok: true }` on pass, or `{ ok: false, error }` with the
837
+ * status already set on the event. The error string lines up with the
838
+ * status code (401 → "unauthorized"; 403 → admin-required message).
839
+ */
840
+ async function checkOrgAdmin(
841
+ event: any,
842
+ ): Promise<{ ok: true } | { ok: false; error: string }> {
843
+ const session = await getSession(event).catch(() => null);
844
+ if (!session?.email) {
845
+ setResponseStatus(event, 401);
846
+ return { ok: false, error: "unauthorized" };
847
+ }
848
+ const ctx = await getOrgContext(event).catch(() => null);
849
+ // Solo (no org membership) — single-tenant flow, allow.
850
+ if (!ctx?.orgId) return { ok: true };
851
+ if (ctx.role === "owner" || ctx.role === "admin") return { ok: true };
852
+ setResponseStatus(event, 403);
853
+ return {
854
+ ok: false,
855
+ error:
856
+ "Only organization owners and admins can mutate integration config",
857
+ };
858
+ }
859
+
860
+ // ─── Status endpoint (all integrations) ───────────────────────
861
+ h3.use(
862
+ `${P}/status`,
863
+ defineEventHandler(async (event) => {
864
+ if (getMethod(event) !== "GET") {
865
+ setResponseStatus(event, 405);
866
+ return { error: "Method not allowed" };
867
+ }
868
+ const baseUrl = getBaseUrl(event);
869
+ const ctx = await requireSessionContext(event);
870
+ if (!ctx) return { error: "unauthorized" };
871
+ const credentialContext = toCredentialContext(ctx);
872
+ const statuses: IntegrationStatus[] = [];
873
+ for (const adapter of adapters) {
874
+ const status = await withCredentialContext(credentialContext, () =>
875
+ adapter.getStatus(baseUrl),
876
+ );
877
+ const config = await getIntegrationConfig(adapter.platform);
878
+ status.enabled = !!config?.configData?.enabled;
879
+ status.webhookUrl = `${baseUrl}${P}/${adapter.platform}/webhook`;
880
+ if (!status.requiredEnvKeys) {
881
+ try {
882
+ status.requiredEnvKeys = adapter.getRequiredEnvKeys();
883
+ } catch {
884
+ status.requiredEnvKeys = [];
885
+ }
886
+ }
887
+ statuses.push(status);
888
+ }
889
+ return statuses;
890
+ }),
891
+ );
892
+
893
+ // ─── Task queue status (observability) ───────────────────────
894
+ // GET /_agent-native/integrations/task-queue/status
895
+ // Returns counts + recent failures for the integration_pending_tasks
896
+ // queue. Requires a normal session — this exposes operational data, not
897
+ // platform secrets. If the queue table doesn't exist yet (no inbound
898
+ // webhook has been processed), returns zeroed stats rather than 500.
899
+ h3.use(
900
+ `${P}/task-queue/status`,
901
+ defineEventHandler(async (event) => {
902
+ if (getMethod(event) !== "GET") {
903
+ setResponseStatus(event, 405);
904
+ return { error: "Method not allowed" };
905
+ }
906
+ if (!(await requireSession(event))) return { error: "unauthorized" };
907
+ try {
908
+ return await getTaskQueueStats();
909
+ } catch (err: any) {
910
+ setResponseStatus(event, 500);
911
+ return { error: err?.message ?? String(err) };
912
+ }
913
+ }),
914
+ );
915
+
916
+ // ─── Remote relay endpoints ──────────────────────────────────
917
+ // These routes allow a signed-in browser session to enqueue work for a
918
+ // registered remote device, and the device to claim/complete that work
919
+ // using its one-time-issued bearer token. State lives entirely in SQL so
920
+ // long polling can safely degrade to short polling on serverless hosts.
921
+ h3.use(
922
+ `${P}/remote/register`,
923
+ defineEventHandler(async (event) => {
924
+ if (getMethod(event) !== "POST") {
925
+ setResponseStatus(event, 405);
926
+ return { error: "Method not allowed" };
927
+ }
928
+ const ctx = await requireSessionContext(event);
929
+ if (!ctx) return { error: "unauthorized" };
930
+ const body = (await readBody(event)) as {
931
+ label?: unknown;
932
+ platform?: unknown;
933
+ appVersion?: unknown;
934
+ version?: unknown;
935
+ hostName?: unknown;
936
+ hostname?: unknown;
937
+ metadata?: unknown;
938
+ };
939
+ const label =
940
+ typeof body.label === "string" && body.label.trim()
941
+ ? body.label.trim().slice(0, 200)
942
+ : "Remote device";
943
+ const { device, token } = await createRemoteDevice({
944
+ ownerEmail: ctx.ownerEmail,
945
+ orgId: ctx.orgId,
946
+ label,
947
+ platform: readString(body.platform),
948
+ appVersion: readString(body.appVersion) ?? readString(body.version),
949
+ hostName: readString(body.hostName) ?? readString(body.hostname),
950
+ metadata: readObject(body.metadata),
951
+ });
952
+ return { device: toPublicRemoteDevice(device), token };
953
+ }),
954
+ );
955
+
956
+ h3.use(
957
+ `${P}/remote/hosts`,
958
+ defineEventHandler(async (event) => {
959
+ if (getMethod(event) !== "GET") {
960
+ setResponseStatus(event, 405);
961
+ return { error: "Method not allowed" };
962
+ }
963
+ const ctx = await requireSessionContext(event);
964
+ if (!ctx) return { error: "unauthorized" };
965
+ const devices = await listRemoteDevicesForOwner({
966
+ ownerEmail: ctx.ownerEmail,
967
+ orgId: ctx.orgId,
968
+ limit: 50,
969
+ });
970
+ const hosts = devices.map(remoteDeviceToHost);
971
+ const parts = mountedPathParts(event, "remote/hosts");
972
+ if (parts[0]) {
973
+ const host = hosts.find((candidate) => candidate.id === parts[0]);
974
+ if (!host) {
975
+ setResponseStatus(event, 404);
976
+ return { error: "host not found" };
977
+ }
978
+ return { host, device: host.device };
979
+ }
980
+ return { hosts, devices: hosts };
981
+ }),
982
+ );
983
+
984
+ h3.use(
985
+ `${P}/remote/devices`,
986
+ defineEventHandler(async (event) => {
987
+ const method = getMethod(event);
988
+ if (method !== "GET" && method !== "DELETE" && method !== "POST") {
989
+ setResponseStatus(event, 405);
990
+ return { error: "Method not allowed" };
991
+ }
992
+ const ctx = await requireSessionContext(event);
993
+ if (!ctx) return { error: "unauthorized" };
994
+ const parts = mountedPathParts(event, "remote/devices");
995
+
996
+ if (method === "GET") {
997
+ if (!parts[0]) {
998
+ const devices = await listRemoteDevicesForOwner({
999
+ ownerEmail: ctx.ownerEmail,
1000
+ orgId: ctx.orgId,
1001
+ limit: 100,
1002
+ });
1003
+ return {
1004
+ devices: devices.map(toPublicRemoteDevice),
1005
+ hosts: devices.map(remoteDeviceToHost),
1006
+ };
1007
+ }
1008
+ const device = await getRemoteDeviceForOwner({
1009
+ id: parts[0],
1010
+ ownerEmail: ctx.ownerEmail,
1011
+ orgId: ctx.orgId,
1012
+ });
1013
+ if (!device) {
1014
+ setResponseStatus(event, 404);
1015
+ return { error: "device not found" };
1016
+ }
1017
+ return {
1018
+ device: toPublicRemoteDevice(device),
1019
+ host: remoteDeviceToHost(device),
1020
+ };
1021
+ }
1022
+
1023
+ const id = parts[0];
1024
+ const action = parts[1];
1025
+ if (!id || (method === "POST" && action !== "revoke")) {
1026
+ setResponseStatus(event, 404);
1027
+ return { error: "not found" };
1028
+ }
1029
+ const device = await revokeRemoteDeviceForOwner({
1030
+ id,
1031
+ ownerEmail: ctx.ownerEmail,
1032
+ orgId: ctx.orgId,
1033
+ });
1034
+ if (!device) {
1035
+ setResponseStatus(event, 404);
1036
+ return { error: "device not found" };
1037
+ }
1038
+ return { ok: true, device: toPublicRemoteDevice(device) };
1039
+ }),
1040
+ );
1041
+
1042
+ h3.use(
1043
+ `${P}/remote/unregister`,
1044
+ defineEventHandler(async (event) => {
1045
+ if (getMethod(event) !== "POST" && getMethod(event) !== "DELETE") {
1046
+ setResponseStatus(event, 405);
1047
+ return { error: "Method not allowed" };
1048
+ }
1049
+ const device = await requireRemoteDevice(event);
1050
+ if (!device) return { error: "unauthorized" };
1051
+ await unregisterRemoteDevice(device.id);
1052
+ return { ok: true, deviceId: device.id };
1053
+ }),
1054
+ );
1055
+
1056
+ h3.use(
1057
+ `${P}/remote/heartbeat`,
1058
+ defineEventHandler(async (event) => {
1059
+ if (getMethod(event) !== "POST") {
1060
+ setResponseStatus(event, 405);
1061
+ return { error: "Method not allowed" };
1062
+ }
1063
+ const device = await requireRemoteDevice(event);
1064
+ if (!device) return { error: "unauthorized" };
1065
+ const body = (await readBody(event)) as Record<string, unknown>;
1066
+ const updated = await updateRemoteDeviceDetails({
1067
+ id: device.id,
1068
+ label: readString(body.label),
1069
+ platform: readString(body.platform),
1070
+ appVersion: readString(body.appVersion) ?? readString(body.version),
1071
+ hostName: readString(body.hostName) ?? readString(body.hostname),
1072
+ metadata: readObject(body.metadata),
1073
+ });
1074
+ return {
1075
+ ok: true,
1076
+ device: updated ? toPublicRemoteDevice(updated) : null,
1077
+ };
1078
+ }),
1079
+ );
1080
+
1081
+ h3.use(
1082
+ `${P}/remote/push/register`,
1083
+ defineEventHandler(async (event) => {
1084
+ if (getMethod(event) !== "POST") {
1085
+ setResponseStatus(event, 405);
1086
+ return { error: "Method not allowed" };
1087
+ }
1088
+ const ctx = await requireSessionContext(event);
1089
+ if (!ctx) return { error: "unauthorized" };
1090
+ const body = (await readBody(event)) as Record<string, unknown>;
1091
+ const token = readString(body.token);
1092
+ if (!token) {
1093
+ setResponseStatus(event, 400);
1094
+ return { error: "token required" };
1095
+ }
1096
+ const registration = await upsertRemotePushRegistration({
1097
+ ownerEmail: ctx.ownerEmail,
1098
+ orgId: ctx.orgId,
1099
+ provider: readString(body.provider) ?? "unknown",
1100
+ token,
1101
+ platform: readString(body.platform),
1102
+ clientDeviceId:
1103
+ readString(body.clientDeviceId) ?? readString(body.deviceId),
1104
+ label: readString(body.label),
1105
+ });
1106
+ return {
1107
+ registration: toPublicRemotePushRegistration(registration),
1108
+ };
1109
+ }),
1110
+ );
1111
+
1112
+ h3.use(
1113
+ `${P}/remote/push/registrations`,
1114
+ defineEventHandler(async (event) => {
1115
+ if (getMethod(event) !== "GET") {
1116
+ setResponseStatus(event, 405);
1117
+ return { error: "Method not allowed" };
1118
+ }
1119
+ const ctx = await requireSessionContext(event);
1120
+ if (!ctx) return { error: "unauthorized" };
1121
+ const registrations = await listRemotePushRegistrationsForOwner({
1122
+ ownerEmail: ctx.ownerEmail,
1123
+ orgId: ctx.orgId,
1124
+ includeInactive: getQuery(event).includeInactive === "true",
1125
+ limit: 100,
1126
+ });
1127
+ return {
1128
+ registrations: registrations.map(toPublicRemotePushRegistration),
1129
+ };
1130
+ }),
1131
+ );
1132
+
1133
+ h3.use(
1134
+ `${P}/remote/push/unregister`,
1135
+ defineEventHandler(async (event) => {
1136
+ const method = getMethod(event);
1137
+ if (method !== "POST" && method !== "DELETE") {
1138
+ setResponseStatus(event, 405);
1139
+ return { error: "Method not allowed" };
1140
+ }
1141
+ const ctx = await requireSessionContext(event);
1142
+ if (!ctx) return { error: "unauthorized" };
1143
+ const body = (await readBody(event)) as Record<string, unknown>;
1144
+ const removed = await unregisterRemotePushRegistrationForOwner({
1145
+ ownerEmail: ctx.ownerEmail,
1146
+ orgId: ctx.orgId,
1147
+ id: readString(body.id) ?? readString(body.registrationId),
1148
+ token: readString(body.token),
1149
+ });
1150
+ if (!removed) {
1151
+ setResponseStatus(event, 404);
1152
+ return { error: "registration not found" };
1153
+ }
1154
+ return { ok: true };
1155
+ }),
1156
+ );
1157
+
1158
+ h3.use(
1159
+ `${P}/remote/push/notifications`,
1160
+ defineEventHandler(async (event) => {
1161
+ if (getMethod(event) !== "GET") {
1162
+ setResponseStatus(event, 405);
1163
+ return { error: "Method not allowed" };
1164
+ }
1165
+ const ctx = await requireSessionContext(event);
1166
+ if (!ctx) return { error: "unauthorized" };
1167
+ const query = getQuery(event);
1168
+ const status =
1169
+ query.status === "delivered" ||
1170
+ query.status === "failed" ||
1171
+ query.status === "pending"
1172
+ ? query.status
1173
+ : undefined;
1174
+ const notifications = await listRemotePushNotificationsForOwner({
1175
+ ownerEmail: ctx.ownerEmail,
1176
+ orgId: ctx.orgId,
1177
+ status,
1178
+ limit: Number(query.limit ?? 50) || 50,
1179
+ });
1180
+ return { notifications };
1181
+ }),
1182
+ );
1183
+
1184
+ h3.use(
1185
+ `${P}/remote/runs`,
1186
+ defineEventHandler(async (event) => {
1187
+ if (getMethod(event) !== "GET") {
1188
+ setResponseStatus(event, 405);
1189
+ return { error: "Method not allowed" };
1190
+ }
1191
+ const ctx = await requireSessionContext(event);
1192
+ if (!ctx) return { error: "unauthorized" };
1193
+ const parts = mountedPathParts(event, "remote/runs");
1194
+ const commands = await listRemoteCommandsForOwner({
1195
+ ownerEmail: ctx.ownerEmail,
1196
+ orgId: ctx.orgId,
1197
+ limit: 100,
1198
+ });
1199
+
1200
+ if (parts.length === 0) {
1201
+ return {
1202
+ runs: commands.map(remoteCommandToRunSummary).filter(Boolean),
1203
+ };
1204
+ }
1205
+
1206
+ const runId = decodeURIComponent(parts[0] ?? "");
1207
+ const match = commands.find((command) => {
1208
+ const run = remoteCommandToRunSummary(command);
1209
+ return (
1210
+ command.id === runId || run?.id === runId || run?.runId === runId
1211
+ );
1212
+ });
1213
+ if (!match) {
1214
+ setResponseStatus(event, 404);
1215
+ return { error: "run not found" };
1216
+ }
1217
+ const run = remoteCommandToRunSummary(match);
1218
+
1219
+ if (parts[1] === "transcript") {
1220
+ const remoteRunId =
1221
+ readString(run?.runId) ??
1222
+ readString(run?.id) ??
1223
+ readString(match.id);
1224
+ const events = remoteRunId
1225
+ ? await listRemoteRunEvents({
1226
+ deviceId: match.deviceId,
1227
+ remoteRunId,
1228
+ limit: 1000,
1229
+ })
1230
+ : [];
1231
+ return {
1232
+ run,
1233
+ events: events.map((event) => event.event),
1234
+ };
1235
+ }
1236
+
1237
+ if (parts.length === 1) return { run };
1238
+ setResponseStatus(event, 404);
1239
+ return { error: "not found" };
1240
+ }),
1241
+ );
1242
+
1243
+ h3.use(
1244
+ `${P}/remote/computer/approvals`,
1245
+ defineEventHandler(async (event) => {
1246
+ const method = getMethod(event);
1247
+ if (method !== "GET" && method !== "POST") {
1248
+ setResponseStatus(event, 405);
1249
+ return { error: "Method not allowed" };
1250
+ }
1251
+ const ctx = await requireSessionContext(event);
1252
+ if (!ctx) return { error: "unauthorized" };
1253
+ const parts = mountedPathParts(event, "remote/computer/approvals");
1254
+ if (method === "GET") {
1255
+ if (parts.length > 0) {
1256
+ setResponseStatus(event, 404);
1257
+ return { error: "not found" };
1258
+ }
1259
+ const query = getQuery(event);
1260
+ const status = readComputerApprovalStatus(query.status);
1261
+ return {
1262
+ approvals: await listComputerApprovalsForOwner({
1263
+ ownerEmail: ctx.ownerEmail,
1264
+ orgId: ctx.orgId,
1265
+ deviceId: readString(query.deviceId),
1266
+ taskId: readString(query.taskId),
1267
+ runId: readString(query.runId),
1268
+ status,
1269
+ limit: Number(query.limit ?? 100) || 100,
1270
+ }),
1271
+ };
1272
+ }
1273
+ const body = (await readBody(event)) as Record<string, unknown>;
1274
+ if (parts[0] && parts[1] === "decision" && parts.length === 2) {
1275
+ const decision =
1276
+ body.decision === "approved" || body.decision === "denied"
1277
+ ? body.decision
1278
+ : null;
1279
+ const actionHash = readString(body.actionHash);
1280
+ if (!decision || !actionHash) {
1281
+ setResponseStatus(event, 400);
1282
+ return { error: "decision and actionHash required" };
1283
+ }
1284
+ const approval = await decideComputerApproval({
1285
+ id: decodeURIComponent(parts[0]),
1286
+ ownerEmail: ctx.ownerEmail,
1287
+ orgId: ctx.orgId,
1288
+ actionHash,
1289
+ decision,
1290
+ decidedBy: ctx.ownerEmail,
1291
+ result: readObject(body.result),
1292
+ });
1293
+ if (!approval) {
1294
+ setResponseStatus(event, 404);
1295
+ return { error: "approval not found or no longer pending" };
1296
+ }
1297
+ return { approval };
1298
+ }
1299
+ if (parts.length > 0) {
1300
+ setResponseStatus(event, 404);
1301
+ return { error: "not found" };
1302
+ }
1303
+ const deviceId = readString(body.deviceId);
1304
+ if (!deviceId || !body.envelope) {
1305
+ setResponseStatus(event, 400);
1306
+ return { error: "deviceId and envelope required" };
1307
+ }
1308
+ try {
1309
+ const approval = await createComputerApprovalRequest({
1310
+ ownerEmail: ctx.ownerEmail,
1311
+ orgId: ctx.orgId,
1312
+ deviceId,
1313
+ envelope: body.envelope as ComputerCommandEnvelope,
1314
+ });
1315
+ return { approval };
1316
+ } catch (error) {
1317
+ return computerSupervisionRouteError(event, error);
1318
+ }
1319
+ }),
1320
+ );
1321
+
1322
+ h3.use(
1323
+ `${P}/remote/computer/commands`,
1324
+ defineEventHandler(async (event) => {
1325
+ if (getMethod(event) !== "POST") {
1326
+ setResponseStatus(event, 405);
1327
+ return { error: "Method not allowed" };
1328
+ }
1329
+ const ctx = await requireSessionContext(event);
1330
+ if (!ctx) return { error: "unauthorized" };
1331
+ const body = (await readBody(event)) as Record<string, unknown>;
1332
+ const deviceId = readString(body.deviceId);
1333
+ if (!deviceId || !body.envelope) {
1334
+ setResponseStatus(event, 400);
1335
+ return { error: "deviceId and envelope required" };
1336
+ }
1337
+ try {
1338
+ const command = await enqueueComputerCommand({
1339
+ deviceId,
1340
+ ownerEmail: ctx.ownerEmail,
1341
+ orgId: ctx.orgId,
1342
+ envelope: body.envelope as ComputerCommandEnvelope,
1343
+ platform: readString(body.platform),
1344
+ });
1345
+ return { command };
1346
+ } catch (error) {
1347
+ return computerSupervisionRouteError(event, error);
1348
+ }
1349
+ }),
1350
+ );
1351
+
1352
+ h3.use(
1353
+ `${P}/remote/enqueue`,
1354
+ defineEventHandler(async (event) => {
1355
+ if (getMethod(event) !== "POST") {
1356
+ setResponseStatus(event, 405);
1357
+ return { error: "Method not allowed" };
1358
+ }
1359
+ const ctx = await requireSessionContext(event);
1360
+ if (!ctx) return { error: "unauthorized" };
1361
+ const body = (await readBody(event)) as {
1362
+ deviceId?: unknown;
1363
+ kind?: unknown;
1364
+ params?: unknown;
1365
+ platform?: unknown;
1366
+ externalThreadId?: unknown;
1367
+ operation?: unknown;
1368
+ payload?: unknown;
1369
+ command?: unknown;
1370
+ source?: unknown;
1371
+ };
1372
+ const highLevel = enqueueBodyToRemoteCodeCommand(body);
1373
+ if (highLevel) {
1374
+ return enqueueRemoteCommand({
1375
+ kind: "code-agent",
1376
+ ownerEmail: ctx.ownerEmail,
1377
+ orgId: ctx.orgId ?? undefined,
1378
+ command: highLevel,
1379
+ source: body.source ?? {
1380
+ platform:
1381
+ typeof body.platform === "string" ? body.platform : "mobile",
1382
+ externalThreadId:
1383
+ typeof body.externalThreadId === "string"
1384
+ ? body.externalThreadId
1385
+ : "mobile",
1386
+ },
1387
+ });
1388
+ }
1389
+ if (typeof body.deviceId !== "string" || !body.deviceId.trim()) {
1390
+ setResponseStatus(event, 400);
1391
+ return { error: "deviceId required" };
1392
+ }
1393
+ if (!isRemoteCommandKind(body.kind)) {
1394
+ setResponseStatus(event, 400);
1395
+ return { error: "invalid command kind" };
1396
+ }
1397
+ const device = await getRemoteDeviceForOwner({
1398
+ id: body.deviceId,
1399
+ ownerEmail: ctx.ownerEmail,
1400
+ orgId: ctx.orgId,
1401
+ });
1402
+ if (!device) {
1403
+ setResponseStatus(event, 404);
1404
+ return { error: "device not found" };
1405
+ }
1406
+ if (device.status !== "active") {
1407
+ setResponseStatus(event, 410);
1408
+ return { error: "device revoked" };
1409
+ }
1410
+ const command = await enqueueRemoteCommandRow({
1411
+ deviceId: device.id,
1412
+ ownerEmail: ctx.ownerEmail,
1413
+ orgId: ctx.orgId,
1414
+ kind: body.kind,
1415
+ params: body.params ?? {},
1416
+ platform: typeof body.platform === "string" ? body.platform : null,
1417
+ externalThreadId:
1418
+ typeof body.externalThreadId === "string"
1419
+ ? body.externalThreadId
1420
+ : null,
1421
+ });
1422
+ return { command };
1423
+ }),
1424
+ );
1425
+
1426
+ h3.use(
1427
+ `${P}/remote/poll`,
1428
+ defineEventHandler(async (event) => {
1429
+ const method = getMethod(event);
1430
+ if (method !== "POST" && method !== "GET") {
1431
+ setResponseStatus(event, 405);
1432
+ return { error: "Method not allowed" };
1433
+ }
1434
+ const device = await requireRemoteDevice(event);
1435
+ if (!device) return { error: "unauthorized" };
1436
+ const query = getQuery(event);
1437
+ const body =
1438
+ method === "POST"
1439
+ ? ((await readBody(event)) as {
1440
+ waitMs?: unknown;
1441
+ computerCapabilities?: unknown;
1442
+ })
1443
+ : {};
1444
+ let pollingDevice = device;
1445
+ if (
1446
+ method === "POST" &&
1447
+ Object.prototype.hasOwnProperty.call(body, "computerCapabilities")
1448
+ ) {
1449
+ const computerCapabilities = readComputerCapabilities(
1450
+ body.computerCapabilities,
1451
+ );
1452
+ const updated = await updateRemoteDeviceDetails({
1453
+ id: device.id,
1454
+ metadata: {
1455
+ ...(device.metadata ?? {}),
1456
+ computerCapabilities,
1457
+ },
1458
+ });
1459
+ if (updated) pollingDevice = updated;
1460
+ }
1461
+ const requestedWait =
1462
+ Number(body.waitMs ?? query.waitMs ?? query.wait_ms ?? 25_000) || 0;
1463
+ const waitMs = Math.max(0, Math.min(25_000, requestedWait));
1464
+ const deadline = Date.now() + waitMs;
1465
+
1466
+ while (true) {
1467
+ const operationClasses =
1468
+ advertisedComputerOperationClasses(pollingDevice);
1469
+ const computerCommand =
1470
+ operationClasses.length > 0
1471
+ ? await claimNextComputerCommand({
1472
+ deviceId: pollingDevice.id,
1473
+ ownerEmail: pollingDevice.ownerEmail,
1474
+ orgId: pollingDevice.orgId,
1475
+ operationClasses,
1476
+ })
1477
+ : null;
1478
+ const command =
1479
+ computerCommand ?? (await claimNextRemoteCommand(pollingDevice.id));
1480
+ if (command) return { command };
1481
+ const remaining = deadline - Date.now();
1482
+ if (remaining <= 0) return { command: null };
1483
+ await sleep(Math.min(1000, remaining));
1484
+ }
1485
+ }),
1486
+ );
1487
+
1488
+ h3.use(
1489
+ `${P}/remote/result`,
1490
+ defineEventHandler(async (event) => {
1491
+ if (getMethod(event) !== "POST") {
1492
+ setResponseStatus(event, 405);
1493
+ return { error: "Method not allowed" };
1494
+ }
1495
+ const device = await requireRemoteDevice(event);
1496
+ if (!device) return { error: "unauthorized" };
1497
+ const body = (await readBody(event)) as {
1498
+ commandId?: unknown;
1499
+ status?: unknown;
1500
+ result?: unknown;
1501
+ errorMessage?: unknown;
1502
+ };
1503
+ if (typeof body.commandId !== "string" || !body.commandId.trim()) {
1504
+ setResponseStatus(event, 400);
1505
+ return { error: "commandId required" };
1506
+ }
1507
+ if (
1508
+ body.status !== "running" &&
1509
+ body.status !== "completed" &&
1510
+ body.status !== "failed"
1511
+ ) {
1512
+ setResponseStatus(event, 400);
1513
+ return { error: "invalid command status" };
1514
+ }
1515
+ const command = await updateRemoteCommandResult({
1516
+ deviceId: device.id,
1517
+ commandId: body.commandId,
1518
+ status: body.status,
1519
+ result: body.result,
1520
+ errorMessage:
1521
+ typeof body.errorMessage === "string" ? body.errorMessage : null,
1522
+ });
1523
+ if (!command) {
1524
+ setResponseStatus(event, 404);
1525
+ return { error: "command not found" };
1526
+ }
1527
+ if (command.status === "completed" || command.status === "failed") {
1528
+ await queueRemotePushNotifications({
1529
+ ownerEmail: device.ownerEmail,
1530
+ orgId: device.orgId,
1531
+ payload: remoteCommandPushPayload(command),
1532
+ }).catch((err) => {
1533
+ console.error("[integrations] remote push queue failed:", err);
1534
+ });
1535
+ }
1536
+ return { command };
1537
+ }),
1538
+ );
1539
+
1540
+ h3.use(
1541
+ `${P}/remote/run-events`,
1542
+ defineEventHandler(async (event) => {
1543
+ if (getMethod(event) !== "POST") {
1544
+ setResponseStatus(event, 405);
1545
+ return { error: "Method not allowed" };
1546
+ }
1547
+ const device = await requireRemoteDevice(event);
1548
+ if (!device) return { error: "unauthorized" };
1549
+ const body = (await readBody(event)) as {
1550
+ remoteRunId?: unknown;
1551
+ runId?: unknown;
1552
+ events?: unknown;
1553
+ };
1554
+ const remoteRunId =
1555
+ typeof body.remoteRunId === "string" && body.remoteRunId.trim()
1556
+ ? body.remoteRunId.trim()
1557
+ : typeof body.runId === "string" && body.runId.trim()
1558
+ ? body.runId.trim()
1559
+ : "";
1560
+ if (!remoteRunId) {
1561
+ setResponseStatus(event, 400);
1562
+ return { error: "remoteRunId required" };
1563
+ }
1564
+ if (!Array.isArray(body.events)) {
1565
+ setResponseStatus(event, 400);
1566
+ return { error: "events required" };
1567
+ }
1568
+ const events = body.events
1569
+ .slice(0, 1000)
1570
+ .map((entry, index) => {
1571
+ const value = entry as { seq?: unknown; event?: unknown };
1572
+ const rawEvent =
1573
+ value && typeof value === "object" && "event" in value
1574
+ ? value.event
1575
+ : entry;
1576
+ return {
1577
+ seq:
1578
+ value && typeof value === "object" && "seq" in value
1579
+ ? Number(value.seq)
1580
+ : index,
1581
+ event: rawEvent ?? null,
1582
+ };
1583
+ })
1584
+ .filter((entry) => Number.isInteger(entry.seq) && entry.seq >= 0);
1585
+ if (events.length !== body.events.length) {
1586
+ setResponseStatus(event, 400);
1587
+ return { error: "invalid event sequence" };
1588
+ }
1589
+ const result = await insertRemoteRunEvents({
1590
+ deviceId: device.id,
1591
+ remoteRunId,
1592
+ events,
1593
+ });
1594
+ return { ok: true, ...result };
1595
+ }),
1596
+ );
1597
+
1598
+ // ─── Process pending task (cross-platform task queue) ────────
1599
+ // POST /_agent-native/integrations/process-task
1600
+ // Internal endpoint invoked via fire-and-forget self-webhook from the
1601
+ // public webhook handler. Auth: HMAC bearer signed with A2A_SECRET.
1602
+ // Each invocation runs the agent loop in a fresh function execution.
1603
+ h3.use(
1604
+ `${P}/process-task`,
1605
+ defineEventHandler(async (event) => {
1606
+ if (getMethod(event) !== "POST") {
1607
+ setResponseStatus(event, 405);
1608
+ return { error: "Method not allowed" };
1609
+ }
1610
+
1611
+ const body = (await readBody(event)) as { taskId?: string };
1612
+ const taskId = body?.taskId;
1613
+ if (!taskId) {
1614
+ setResponseStatus(event, 400);
1615
+ return { error: "taskId required" };
1616
+ }
1617
+
1618
+ // Auth: HMAC token bound to the task id.
1619
+ //
1620
+ // In production we MUST require A2A_SECRET — a publicly-callable
1621
+ // process-task endpoint lets attackers re-trigger any queued task
1622
+ // by guessing or sniffing its id (C3 in the webhook security audit).
1623
+ // The atomic SQL claim only prevents *double*-processing, not the
1624
+ // first attacker-driven processing.
1625
+ //
1626
+ // In dev we keep the loose posture so contributors don't have to
1627
+ // configure A2A_SECRET to play with the integration locally.
1628
+ if (!process.env.A2A_SECRET) {
1629
+ if (process.env.NODE_ENV === "production") {
1630
+ setResponseStatus(event, 503);
1631
+ return {
1632
+ error:
1633
+ "A2A_SECRET not configured — internal token signing is required to process integration tasks in production.",
1634
+ };
1635
+ }
1636
+ // Dev: fall through unsigned (the atomic claim still gates double-processing).
1637
+ } else {
1638
+ const tok = extractBearerToken(
1639
+ getRequestHeader(event, "authorization"),
1640
+ );
1641
+ if (!tok || !verifyInternalToken(taskId, tok)) {
1642
+ setResponseStatus(event, 401);
1643
+ return { error: "Invalid or expired internal token" };
1644
+ }
1645
+ }
1646
+
1647
+ // Atomic claim: only one invocation gets to process this task
1648
+ const task = await claimPendingTask(taskId);
1649
+ if (!task) {
1650
+ setResponseStatus(event, 200);
1651
+ return { ok: true, skipped: "already-claimed-or-missing" };
1652
+ }
1653
+
1654
+ let deliveryRetryTransitionStarted = false;
1655
+ let deliveryRetryRecovery:
1656
+ | { payload: string; errorMessage: string }
1657
+ | undefined;
1658
+ let confirmedDeliveryRetryPayload: string | undefined;
1659
+ try {
1660
+ const adapter = adapterMap.get(task.platform);
1661
+ if (!adapter) {
1662
+ await markTaskFailed(taskId, `Unknown platform: ${task.platform}`);
1663
+ setResponseStatus(event, 404);
1664
+ return { error: "Unknown platform" };
1665
+ }
1666
+ const processingResult = await runWithRequestContext(
1667
+ {
1668
+ userEmail: task.ownerEmail,
1669
+ ...(task.orgId ? { orgId: task.orgId } : {}),
1670
+ isIntegrationCaller: true,
1671
+ },
1672
+ async () => {
1673
+ const taskPayload = JSON.parse(task.payload) as
1674
+ | IntegrationSystemNoticeTaskPayload
1675
+ | IntegrationResponseDeliveryTaskPayload
1676
+ | { kind?: undefined };
1677
+ if (taskPayload.kind === "system-notice") {
1678
+ if (!adapter.sendSystemNotice) {
1679
+ throw new Error(
1680
+ `Platform ${task.platform} cannot deliver system notices`,
1681
+ );
1682
+ }
1683
+ const config = await getIntegrationConfig(task.platform);
1684
+ const credentialContext =
1685
+ await credentialContextForIntegrationConfig(config);
1686
+ await withCredentialContext(credentialContext, () =>
1687
+ adapter.sendSystemNotice!(
1688
+ taskPayload.incoming,
1689
+ taskPayload.text,
1690
+ {
1691
+ ...(taskPayload.dedupeKey
1692
+ ? { dedupeKey: taskPayload.dedupeKey }
1693
+ : {}),
1694
+ ...(taskPayload.dedupeTtlMs
1695
+ ? { dedupeTtlMs: taskPayload.dedupeTtlMs }
1696
+ : {}),
1697
+ },
1698
+ ),
1699
+ );
1700
+ return;
1701
+ }
1702
+ if (taskPayload.kind === "response-delivery") {
1703
+ let receipt: void | PlatformDeliveryReceipt =
1704
+ taskPayload.deliveryReceipt;
1705
+ if (!receipt) {
1706
+ receipt = await adapter.sendResponse(
1707
+ taskPayload.message,
1708
+ taskPayload.incoming,
1709
+ {
1710
+ ...(taskPayload.placeholderRef
1711
+ ? { placeholderRef: taskPayload.placeholderRef }
1712
+ : {}),
1713
+ },
1714
+ );
1715
+ }
1716
+ if (receipt?.status !== "delivered") {
1717
+ throw new Error(
1718
+ `${task.platform} response completed without delivery proof`,
1719
+ );
1720
+ }
1721
+ const deliveredPayload = taskPayload.deliveryReceipt
1722
+ ? taskPayload
1723
+ : {
1724
+ ...taskPayload,
1725
+ deliveryReceipt: receipt,
1726
+ deliveredAt: new Date().toISOString(),
1727
+ };
1728
+ confirmedDeliveryRetryPayload =
1729
+ JSON.stringify(deliveredPayload);
1730
+ if (!taskPayload.deliveryReceipt) {
1731
+ deliveryRetryRecovery = {
1732
+ payload: confirmedDeliveryRetryPayload,
1733
+ errorMessage:
1734
+ "Provider delivery was confirmed but its receipt checkpoint failed",
1735
+ };
1736
+ await stageTaskDeliveryPayload(
1737
+ task.id,
1738
+ deliveryRetryRecovery.payload,
1739
+ );
1740
+ deliveryRetryRecovery = undefined;
1741
+ }
1742
+ await recordIntegrationResponseDelivery(
1743
+ deliveredPayload,
1744
+ receipt,
1745
+ );
1746
+ return;
1747
+ }
1748
+ const resources = await loadResourcesForPrompt(
1749
+ task.ownerEmail,
1750
+ true,
1751
+ options?.appId,
1752
+ task.orgId,
1753
+ );
1754
+ const result = await processIntegrationTask(task, {
1755
+ adapter,
1756
+ systemPrompt: baseSystemPrompt + resources,
1757
+ actions,
1758
+ initialToolNames,
1759
+ model,
1760
+ apiKey: getApiKey(),
1761
+ engine: options?.engine,
1762
+ ownerEmail: task.ownerEmail,
1763
+ appId: options?.appId,
1764
+ });
1765
+ if (result?.status === "delivery-pending") {
1766
+ deliveryRetryTransitionStarted = true;
1767
+ await markTaskDeliveryRetryable(
1768
+ task.id,
1769
+ JSON.stringify(result.payload),
1770
+ result.errorMessage,
1771
+ );
1772
+ return "delivery-retry" as const;
1773
+ }
1774
+ return "completed" as const;
1775
+ },
1776
+ );
1777
+ if (processingResult === "delivery-retry") {
1778
+ setResponseStatus(event, 202);
1779
+ return { ok: true, taskId, retrying: "response-delivery" };
1780
+ }
1781
+ await markTaskCompleted(taskId);
1782
+ const nextTaskId = await getNextPendingTaskIdForThread(
1783
+ task.platform,
1784
+ task.externalThreadId,
1785
+ );
1786
+ if (nextTaskId) {
1787
+ const nextToken = signInternalToken(nextTaskId);
1788
+ void fetch(`${getBaseUrl(event)}${P}/process-task`, {
1789
+ method: "POST",
1790
+ headers: {
1791
+ "Content-Type": "application/json",
1792
+ ...(nextToken ? { Authorization: `Bearer ${nextToken}` } : {}),
1793
+ },
1794
+ body: JSON.stringify({ taskId: nextTaskId }),
1795
+ }).catch((err) => {
1796
+ console.error(
1797
+ "[integrations] Failed to dispatch queued thread turn:",
1798
+ err,
1799
+ );
1800
+ });
1801
+ }
1802
+ await processDueA2AContinuations({
1803
+ adapters: adapterMap,
1804
+ limit: 2,
1805
+ }).catch((err) => {
1806
+ console.error(
1807
+ "[integrations] A2A continuation opportunistic sweep failed:",
1808
+ err,
1809
+ );
1810
+ });
1811
+ return { ok: true, taskId };
1812
+ } catch (err: any) {
1813
+ const errorMessage = err?.message
1814
+ ? String(err.message).slice(0, 1000)
1815
+ : "processor failed";
1816
+ if (deliveryRetryRecovery) {
1817
+ try {
1818
+ await markTaskDeliveryRetryable(
1819
+ taskId,
1820
+ deliveryRetryRecovery.payload,
1821
+ `${deliveryRetryRecovery.errorMessage}: ${errorMessage}`,
1822
+ );
1823
+ setResponseStatus(event, 202);
1824
+ return { ok: true, taskId, retrying: "response-delivery" };
1825
+ } catch (transitionError) {
1826
+ const transitionMessage =
1827
+ transitionError instanceof Error
1828
+ ? transitionError.message
1829
+ : String(transitionError);
1830
+ await failTaskDeliveryTransition(
1831
+ taskId,
1832
+ `Could not safely checkpoint the delivery receipt: ${transitionMessage}`,
1833
+ ).catch((failureTransitionError) => {
1834
+ console.error(
1835
+ "[integrations] Failed to contain delivery receipt transition failure:",
1836
+ failureTransitionError,
1837
+ );
1838
+ });
1839
+ }
1840
+ } else if (confirmedDeliveryRetryPayload) {
1841
+ try {
1842
+ await markTaskDeliveryRetryable(
1843
+ taskId,
1844
+ confirmedDeliveryRetryPayload,
1845
+ `Provider delivery was confirmed but history persistence failed: ${errorMessage}`,
1846
+ );
1847
+ console.error("[integrations] process-task failure:", err);
1848
+ setResponseStatus(event, 202);
1849
+ return { ok: true, taskId, retrying: "response-delivery" };
1850
+ } catch (transitionError) {
1851
+ console.error(
1852
+ "[integrations] Failed to requeue confirmed delivery history:",
1853
+ transitionError,
1854
+ );
1855
+ }
1856
+ } else if (deliveryRetryTransitionStarted) {
1857
+ await failTaskDeliveryTransition(
1858
+ taskId,
1859
+ `Could not safely checkpoint the delivery retry: ${errorMessage}`,
1860
+ ).catch((transitionError) => {
1861
+ console.error(
1862
+ "[integrations] Failed to contain delivery retry transition failure:",
1863
+ transitionError,
1864
+ );
1865
+ });
1866
+ } else if (task.attempts >= MAX_PENDING_TASK_ATTEMPTS) {
1867
+ await markTaskFailed(taskId, errorMessage);
1868
+ } else {
1869
+ await markTaskRetryable(taskId, errorMessage);
1870
+ }
1871
+ // Log the detail server-side; never return the raw error message
1872
+ // to the caller. Raw messages have leaked DB error codes, schema
1873
+ // names, and stack hints in the past (L3 in the webhook security
1874
+ // audit). Sentry / log providers still see the full error.
1875
+ console.error("[integrations] process-task failure:", err);
1876
+ setResponseStatus(event, 500);
1877
+ return { error: "Internal task failed" };
1878
+ }
1879
+ }),
1880
+ );
1881
+
1882
+ // ─── Process deferred A2A continuation ──────────────────────────
1883
+ // POST /_agent-native/integrations/process-a2a-continuation
1884
+ // Internal endpoint invoked when call-agent timed out inside an
1885
+ // integration processor but the remote A2A task kept running.
1886
+ h3.use(
1887
+ `${P}/process-a2a-continuation`,
1888
+ defineEventHandler(async (event) => {
1889
+ if (getMethod(event) !== "POST") {
1890
+ setResponseStatus(event, 405);
1891
+ return { error: "Method not allowed" };
1892
+ }
1893
+
1894
+ const body = (await readBody(event)) as { continuationId?: string };
1895
+ const continuationId = body?.continuationId;
1896
+ if (!continuationId) {
1897
+ setResponseStatus(event, 400);
1898
+ return { error: "continuationId required" };
1899
+ }
1900
+
1901
+ if (!process.env.A2A_SECRET) {
1902
+ if (process.env.NODE_ENV === "production") {
1903
+ setResponseStatus(event, 503);
1904
+ return {
1905
+ error:
1906
+ "A2A_SECRET not configured — internal token signing is required to process A2A continuations in production.",
1907
+ };
1908
+ }
1909
+ } else {
1910
+ const tok = extractBearerToken(
1911
+ getRequestHeader(event, "authorization"),
1912
+ );
1913
+ if (!tok || !verifyInternalToken(continuationId, tok)) {
1914
+ setResponseStatus(event, 401);
1915
+ return { error: "Invalid or expired internal token" };
1916
+ }
1917
+ }
1918
+
1919
+ try {
1920
+ await processA2AContinuationById(continuationId, {
1921
+ adapters: adapterMap,
1922
+ });
1923
+ } catch (err: any) {
1924
+ // Mark the continuation failed so it isn't left dangling, and surface
1925
+ // a 500 to the caller instead of leaking an unhandled rejection.
1926
+ await failA2AContinuation(
1927
+ continuationId,
1928
+ err?.message?.slice(0, 500) || "continuation processing failed",
1929
+ ).catch(() => {});
1930
+ console.error(
1931
+ "[integrations] process-a2a-continuation failure:",
1932
+ err,
1933
+ );
1934
+ setResponseStatus(event, 500);
1935
+ return { error: "Failed to process A2A continuation" };
1936
+ }
1937
+ return { ok: true, continuationId };
1938
+ }),
1939
+ );
1940
+
1941
+ // ─── Slack native action controls ─────────────────────────────
1942
+ h3.use(
1943
+ `${P}/slack/interactions`,
1944
+ defineEventHandler(async (event) => {
1945
+ if (getMethod(event) !== "POST") {
1946
+ setResponseStatus(event, 405);
1947
+ return { error: "Method not allowed" };
1948
+ }
1949
+ const adapter = adapterMap.get("slack");
1950
+ if (!adapter) {
1951
+ setResponseStatus(event, 404);
1952
+ return "ok";
1953
+ }
1954
+ // handleVerification caches the exact raw form bytes even though the
1955
+ // body is not JSON; verifyWebhook then validates Slack's HMAC before
1956
+ // any action value is parsed.
1957
+ await adapter.handleVerification(event);
1958
+ if (!(await adapter.verifyWebhook(event))) {
1959
+ setResponseStatus(event, 401);
1960
+ return { error: "Invalid webhook signature" };
1961
+ }
1962
+ try {
1963
+ const raw = String(event.context?.__rawBody ?? "");
1964
+ const encoded = new URLSearchParams(raw).get("payload");
1965
+ const payload = encoded ? JSON.parse(encoded) : null;
1966
+ const action = payload?.actions?.[0];
1967
+ const actionKind =
1968
+ action?.action_id === "agent_native_approve"
1969
+ ? "approve"
1970
+ : action?.action_id === "agent_native_deny"
1971
+ ? "deny"
1972
+ : action?.action_id === "agent_native_cancel"
1973
+ ? "cancel"
1974
+ : null;
1975
+ if (!actionKind || typeof action?.value !== "string") return "ok";
1976
+ const requesterId = payload?.user?.id;
1977
+ const teamId = payload?.team?.id ?? payload?.user?.team_id;
1978
+ const channelId =
1979
+ payload?.channel?.id ?? payload?.container?.channel_id;
1980
+ const messageTs = payload?.container?.message_ts;
1981
+ if (!requesterId || !teamId || !channelId || !messageTs) {
1982
+ return "ok";
1983
+ }
1984
+ const control = await claimIntegrationControl({
1985
+ id: action.value,
1986
+ action: actionKind,
1987
+ requesterId,
1988
+ teamId,
1989
+ apiAppId:
1990
+ typeof payload?.api_app_id === "string" ? payload.api_app_id : "",
1991
+ channelId,
1992
+ messageTs,
1993
+ });
1994
+ if (!control) return "ok";
1995
+ if (actionKind === "cancel") {
1996
+ if (control.runId) abortRun(control.runId, "slack_cancel");
1997
+ return "ok";
1998
+ }
1999
+ if (actionKind === "deny") return "ok";
2000
+ if (!control.approvalKey) return "ok";
2001
+
2002
+ const taskId = `task-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
2003
+ const incoming = {
2004
+ ...control.incoming,
2005
+ text: "The requester approved the pending action. Continue the task.",
2006
+ approvedToolCalls: [control.approvalKey],
2007
+ timestamp: Date.now(),
2008
+ platformContext: {
2009
+ ...control.incoming.platformContext,
2010
+ eventId: `control:${control.id}`,
2011
+ },
2012
+ };
2013
+ await insertPendingTask({
2014
+ id: taskId,
2015
+ platform: incoming.platform,
2016
+ externalThreadId: incoming.externalThreadId,
2017
+ payload: JSON.stringify({ incoming }),
2018
+ ownerEmail: control.ownerEmail,
2019
+ orgId: control.orgId,
2020
+ externalEventKey: `control:${control.id}`,
2021
+ });
2022
+ const processUrl = `${getBaseUrl(event)}${P}/process-task`;
2023
+ const token = signInternalToken(taskId);
2024
+ void fetch(processUrl, {
2025
+ method: "POST",
2026
+ headers: {
2027
+ "Content-Type": "application/json",
2028
+ ...(token ? { Authorization: `Bearer ${token}` } : {}),
2029
+ },
2030
+ body: JSON.stringify({ taskId }),
2031
+ }).catch((err) => {
2032
+ console.error("[slack] Approval dispatch failed:", err);
2033
+ });
2034
+ } catch (err) {
2035
+ console.error("[slack] Interaction handling failed:", err);
2036
+ }
2037
+ return "ok";
2038
+ }),
2039
+ );
2040
+
2041
+ // ─── Managed integration installations ───────────────────────
2042
+ h3.use(
2043
+ `${P}/installations`,
2044
+ defineEventHandler(async (event) => {
2045
+ const method = getMethod(event);
2046
+ if (method !== "GET" && method !== "POST") {
2047
+ setResponseStatus(event, 405);
2048
+ return { error: "Method not allowed" };
2049
+ }
2050
+ const session = await getSession(event).catch(() => null);
2051
+ if (!session?.email) {
2052
+ setResponseStatus(event, 401);
2053
+ return { error: "unauthorized" };
2054
+ }
2055
+ const org = await getOrgContext(event).catch(() => null);
2056
+ const actor = {
2057
+ userEmail: session.email,
2058
+ orgId: org?.orgId ?? session.orgId ?? null,
2059
+ isOrgAdmin: org?.role === "owner" || org?.role === "admin",
2060
+ };
2061
+ if (method === "GET") {
2062
+ const query = getQuery(event);
2063
+ return {
2064
+ installations: await listIntegrationInstallations(
2065
+ actor,
2066
+ typeof query.platform === "string" ? query.platform : undefined,
2067
+ ),
2068
+ };
2069
+ }
2070
+ const body = (await readBody(event)) as {
2071
+ id?: unknown;
2072
+ action?: unknown;
2073
+ };
2074
+ const id = typeof body.id === "string" ? body.id : "";
2075
+ if (!id) {
2076
+ setResponseStatus(event, 400);
2077
+ return { error: "installation id required" };
2078
+ }
2079
+ if (body.action === "disconnect") {
2080
+ return {
2081
+ installation: await disconnectIntegrationInstallation(id, actor),
2082
+ };
2083
+ }
2084
+ if (body.action === "test") {
2085
+ const installation = (
2086
+ await listIntegrationInstallations(actor, "slack")
2087
+ ).find((item) => item.id === id);
2088
+ if (!installation) {
2089
+ setResponseStatus(event, 404);
2090
+ return { error: "installation not found" };
2091
+ }
2092
+ const bundle = await resolveIntegrationTokenBundle(
2093
+ installation.platform,
2094
+ installation.installationKey,
2095
+ );
2096
+ if (!bundle) {
2097
+ const updated = await updateIntegrationInstallation(id, actor, {
2098
+ health: "revoked",
2099
+ status: "revoked",
2100
+ lastError: "token_unavailable",
2101
+ healthCheckedAt: Date.now(),
2102
+ });
2103
+ return { installation: updated };
2104
+ }
2105
+ const health = await testSlackAuth(bundle.accessToken);
2106
+ const updated = await updateIntegrationInstallation(id, actor, {
2107
+ health: health.health,
2108
+ status: health.health === "revoked" ? "revoked" : "connected",
2109
+ lastError: health.error,
2110
+ healthCheckedAt: health.checkedAt,
2111
+ ...(health.ok ? { lastHealthyAt: health.checkedAt } : {}),
2112
+ });
2113
+ return { installation: updated };
2114
+ }
2115
+ setResponseStatus(event, 400);
2116
+ return { error: "unsupported installation action" };
2117
+ }),
2118
+ );
2119
+
2120
+ h3.use(
2121
+ `${P}/scopes`,
2122
+ defineEventHandler(async (event) => {
2123
+ const method = getMethod(event);
2124
+ if (method !== "GET" && method !== "POST") {
2125
+ setResponseStatus(event, 405);
2126
+ return { error: "Method not allowed" };
2127
+ }
2128
+ const ctx = await requireSessionContext(event);
2129
+ if (!ctx) return { error: "unauthorized" };
2130
+ const access = { ownerEmail: ctx.ownerEmail, orgId: ctx.orgId };
2131
+ if (method === "GET") {
2132
+ const query = getQuery(event);
2133
+ return {
2134
+ scopes: await listIntegrationScopes(access, {
2135
+ platform:
2136
+ typeof query.platform === "string" ? query.platform : undefined,
2137
+ tenantId:
2138
+ typeof query.tenantId === "string" ? query.tenantId : undefined,
2139
+ }),
2140
+ };
2141
+ }
2142
+ const admin = await checkOrgAdmin(event);
2143
+ if (!admin.ok) return { error: admin.error };
2144
+ try {
2145
+ const body = (await readBody(event)) as Parameters<
2146
+ typeof saveIntegrationScope
2147
+ >[0];
2148
+ return { scope: await saveIntegrationScope(body, access) };
2149
+ } catch (err) {
2150
+ setResponseStatus(event, 400);
2151
+ return {
2152
+ error: err instanceof Error ? err.message : "invalid scope",
2153
+ };
2154
+ }
2155
+ }),
2156
+ );
2157
+
2158
+ h3.use(
2159
+ `${P}/budgets`,
2160
+ defineEventHandler(async (event) => {
2161
+ const method = getMethod(event);
2162
+ if (method !== "GET" && method !== "POST") {
2163
+ setResponseStatus(event, 405);
2164
+ return { error: "Method not allowed" };
2165
+ }
2166
+ const ctx = await requireSessionContext(event);
2167
+ if (!ctx) return { error: "unauthorized" };
2168
+ const access = { ownerEmail: ctx.ownerEmail, orgId: ctx.orgId };
2169
+ if (method === "GET") {
2170
+ return { budgets: await listIntegrationUsageBudgets(access) };
2171
+ }
2172
+ const admin = await checkOrgAdmin(event);
2173
+ if (!admin.ok) return { error: admin.error };
2174
+ try {
2175
+ const body = (await readBody(event)) as Parameters<
2176
+ typeof saveIntegrationUsageBudget
2177
+ >[0];
2178
+ return {
2179
+ budget: await saveIntegrationUsageBudget(body, access),
2180
+ };
2181
+ } catch (err) {
2182
+ setResponseStatus(event, 400);
2183
+ return {
2184
+ error: err instanceof Error ? err.message : "invalid budget",
2185
+ };
2186
+ }
2187
+ }),
2188
+ );
2189
+
2190
+ h3.use(
2191
+ `${P}/memory`,
2192
+ defineEventHandler(async (event) => {
2193
+ const method = getMethod(event);
2194
+ if (method !== "GET" && method !== "POST") {
2195
+ setResponseStatus(event, 405);
2196
+ return { error: "Method not allowed" };
2197
+ }
2198
+ const ctx = await requireSessionContext(event);
2199
+ if (!ctx) return { error: "unauthorized" };
2200
+ const access = { ownerEmail: ctx.ownerEmail, orgId: ctx.orgId };
2201
+ const query = getQuery(event);
2202
+ const body =
2203
+ method === "POST"
2204
+ ? ((await readBody(event)) as Record<string, unknown>)
2205
+ : null;
2206
+ const scopeId =
2207
+ typeof query.scopeId === "string"
2208
+ ? query.scopeId
2209
+ : typeof body?.scopeId === "string"
2210
+ ? body.scopeId
2211
+ : "";
2212
+ const scope = (await listIntegrationScopes(access)).find(
2213
+ (item) => item.id === scopeId,
2214
+ );
2215
+ if (!scope) {
2216
+ setResponseStatus(event, 404);
2217
+ return { error: "integration scope not found" };
2218
+ }
2219
+ if (method === "GET") {
2220
+ return { memories: await listIntegrationMemory(scope.id) };
2221
+ }
2222
+ const admin = await checkOrgAdmin(event);
2223
+ if (!admin.ok) return { error: admin.error };
2224
+ if (body?.action === "remember") {
2225
+ return {
2226
+ memory: await rememberForIntegrationScope(
2227
+ {
2228
+ name: String(body.name ?? ""),
2229
+ description: String(body.description ?? ""),
2230
+ content: String(body.content ?? ""),
2231
+ },
2232
+ scope.id,
2233
+ ),
2234
+ };
2235
+ }
2236
+ if (body?.action === "forget") {
2237
+ return {
2238
+ memory: await forgetIntegrationMemory(
2239
+ { name: String(body.name ?? "") },
2240
+ scope.id,
2241
+ ),
2242
+ };
2243
+ }
2244
+ setResponseStatus(event, 400);
2245
+ return { error: "unsupported memory action" };
2246
+ }),
2247
+ );
2248
+
2249
+ // ─── Managed Slack OAuth ──────────────────────────────────────
2250
+ h3.use(
2251
+ `${P}/slack/manifest`,
2252
+ defineEventHandler(async (event) => {
2253
+ if (getMethod(event) !== "GET") {
2254
+ setResponseStatus(event, 405);
2255
+ return { error: "Method not allowed" };
2256
+ }
2257
+ const oauthRedirectUrl = resolveOAuthRedirectUri(
2258
+ event,
2259
+ `${P}/slack/oauth/callback`,
2260
+ );
2261
+ const eventsRequestUrl = resolveOAuthRedirectUri(
2262
+ event,
2263
+ `${P}/slack/webhook`,
2264
+ );
2265
+ const interactivityRequestUrl = resolveOAuthRedirectUri(
2266
+ event,
2267
+ `${P}/slack/interactions`,
2268
+ );
2269
+ if (
2270
+ !oauthRedirectUrl ||
2271
+ !eventsRequestUrl ||
2272
+ !interactivityRequestUrl
2273
+ ) {
2274
+ setResponseStatus(event, 400);
2275
+ return { error: "Slack manifest URLs are not allowed." };
2276
+ }
2277
+ setResponseHeader(
2278
+ event,
2279
+ "content-disposition",
2280
+ 'attachment; filename="agent-native-slack-manifest.json"',
2281
+ );
2282
+ return buildSlackAgentManifest({
2283
+ oauthRedirectUrl,
2284
+ eventsRequestUrl,
2285
+ interactivityRequestUrl,
2286
+ });
2287
+ }),
2288
+ );
2289
+
2290
+ h3.use(
2291
+ `${P}/slack/oauth/install`,
2292
+ defineEventHandler(async (event) => {
2293
+ if (getMethod(event) !== "GET") {
2294
+ setResponseStatus(event, 405);
2295
+ return { error: "Method not allowed" };
2296
+ }
2297
+ const session = await getSession(event).catch(() => null);
2298
+ if (!session?.email) {
2299
+ setResponseStatus(event, 401);
2300
+ return { error: "Sign in before connecting Slack." };
2301
+ }
2302
+ const org = await getOrgContext(event).catch(() => null);
2303
+ try {
2304
+ assertSlackInstallAccess({
2305
+ email: session.email,
2306
+ orgId: org?.orgId ?? session.orgId ?? null,
2307
+ orgRole: org?.role ?? null,
2308
+ });
2309
+ } catch (err) {
2310
+ setResponseStatus(event, 403);
2311
+ return {
2312
+ error: err instanceof Error ? err.message : "Slack access denied",
2313
+ };
2314
+ }
2315
+ return await runWithRequestContext(
2316
+ {
2317
+ userEmail: session.email,
2318
+ orgId: org?.orgId ?? session.orgId ?? undefined,
2319
+ },
2320
+ async () => {
2321
+ const clientId = await resolveSecret("SLACK_CLIENT_ID");
2322
+ const clientSecret = await resolveSecret("SLACK_CLIENT_SECRET");
2323
+ const signingSecret = await resolveSecret("SLACK_SIGNING_SECRET");
2324
+ if (!clientId || !clientSecret || !signingSecret) {
2325
+ setResponseStatus(event, 503);
2326
+ return {
2327
+ error:
2328
+ "Slack OAuth is not configured. Add the Slack client id, client secret, and signing secret first.",
2329
+ };
2330
+ }
2331
+ const redirectUri = resolveOAuthRedirectUri(
2332
+ event,
2333
+ `${P}/slack/oauth/callback`,
2334
+ );
2335
+ if (!redirectUri) {
2336
+ setResponseStatus(event, 400);
2337
+ return { error: "Slack OAuth redirect URL is not allowed." };
2338
+ }
2339
+ const query = getQuery(event);
2340
+ const state = encodeOAuthState({
2341
+ redirectUri,
2342
+ owner: session.email,
2343
+ orgId: org?.orgId ?? session.orgId ?? undefined,
2344
+ app: "agent-native:slack",
2345
+ addAccount: true,
2346
+ returnUrl:
2347
+ typeof query.return === "string" ? query.return : "/messaging",
2348
+ });
2349
+ return sendRedirect(
2350
+ event,
2351
+ buildSlackAuthorizeUrl({ clientId, redirectUri, state }),
2352
+ 302,
2353
+ );
2354
+ },
2355
+ );
2356
+ }),
2357
+ );
2358
+
2359
+ h3.use(
2360
+ `${P}/slack/oauth/callback`,
2361
+ defineEventHandler(async (event) => {
2362
+ if (getMethod(event) !== "GET") {
2363
+ setResponseStatus(event, 405);
2364
+ return { error: "Method not allowed" };
2365
+ }
2366
+ const query = getQuery(event);
2367
+ if (typeof query.error === "string") {
2368
+ return oauthErrorPage("Slack authorization was canceled or denied.");
2369
+ }
2370
+ const fallbackRedirect = resolveOAuthRedirectUri(
2371
+ event,
2372
+ `${P}/slack/oauth/callback`,
2373
+ );
2374
+ if (!fallbackRedirect) {
2375
+ return oauthErrorPage("Slack OAuth redirect URL is not allowed.");
2376
+ }
2377
+ const state = decodeOAuthState(
2378
+ typeof query.state === "string" ? query.state : undefined,
2379
+ fallbackRedirect,
2380
+ );
2381
+ const session = await getSession(event).catch(() => null);
2382
+ const org = await getOrgContext(event).catch(() => null);
2383
+ if (
2384
+ state.app !== "agent-native:slack" ||
2385
+ !session?.email ||
2386
+ !state.owner ||
2387
+ session.email.toLowerCase() !== state.owner.toLowerCase() ||
2388
+ (state.orgId ?? null) !== (org?.orgId ?? session.orgId ?? null)
2389
+ ) {
2390
+ return oauthErrorPage(
2391
+ "Your Slack install session expired or changed. Sign in and start again.",
2392
+ );
2393
+ }
2394
+ const code = typeof query.code === "string" ? query.code : null;
2395
+ if (!code) return oauthErrorPage("Slack did not return an OAuth code.");
2396
+ try {
2397
+ const access = assertSlackInstallAccess({
2398
+ email: session.email,
2399
+ orgId: org?.orgId ?? session.orgId ?? null,
2400
+ orgRole: org?.role ?? null,
2401
+ });
2402
+ return await runWithRequestContext(
2403
+ {
2404
+ userEmail: access.ownerEmail,
2405
+ orgId: access.orgId ?? undefined,
2406
+ },
2407
+ async () => {
2408
+ const clientId = await resolveSecret("SLACK_CLIENT_ID");
2409
+ const clientSecret = await resolveSecret("SLACK_CLIENT_SECRET");
2410
+ if (!clientId || !clientSecret) {
2411
+ return oauthErrorPage("Slack OAuth is not configured.");
2412
+ }
2413
+ const oauth = await exchangeSlackOAuthCode({
2414
+ code,
2415
+ clientId,
2416
+ clientSecret,
2417
+ redirectUri: state.redirectUri,
2418
+ });
2419
+ const health = await testSlackAuth(oauth.access_token || "");
2420
+ if (!health.ok) {
2421
+ return oauthErrorPage(
2422
+ "Slack connected, but the bot token could not be verified. Please retry.",
2423
+ );
2424
+ }
2425
+ if (
2426
+ oauth.team?.id &&
2427
+ health.teamId &&
2428
+ oauth.team.id !== health.teamId
2429
+ ) {
2430
+ return oauthErrorPage(
2431
+ "Slack returned inconsistent workspace details. Please retry.",
2432
+ );
2433
+ }
2434
+ const input = slackOAuthResponseToInstallation(oauth, access);
2435
+ const installation = await upsertIntegrationInstallation({
2436
+ ...input,
2437
+ health: health.health,
2438
+ healthCheckedAt: health.checkedAt,
2439
+ lastHealthyAt: health.checkedAt,
2440
+ });
2441
+ await saveIntegrationConfig(
2442
+ "slack",
2443
+ { enabled: true, managedOAuth: true },
2444
+ "default",
2445
+ access.ownerEmail,
2446
+ );
2447
+ return oauthCallbackResponse(
2448
+ event,
2449
+ installation.teamName || installation.enterpriseName || "Slack",
2450
+ {
2451
+ addAccount: true,
2452
+ appName: "Agent Native",
2453
+ returnUrl: state.returnUrl || "/messaging",
2454
+ },
2455
+ );
2456
+ },
2457
+ );
2458
+ } catch (err) {
2459
+ console.error("[slack] OAuth callback failed:", err);
2460
+ return oauthErrorPage("Slack connection failed. Please try again.");
2461
+ }
2462
+ }),
2463
+ );
2464
+
2465
+ // ─── Per-platform catch-all ───────────────────────────────────
2466
+ // Handles: webhook, status, enable, disable, setup for each platform
2467
+ h3.use(
2468
+ `${P}`,
2469
+ defineEventHandler(async (event) => {
2470
+ const method = getMethod(event);
2471
+ // event.path is stripped to the remainder after the mount prefix
2472
+ const raw = (event.path || "/").split("?")[0].replace(/^\//, "");
2473
+ const parts = raw.split("/").filter(Boolean);
2474
+
2475
+ // Already handled by the dedicated /status route above
2476
+ if (parts[0] === "status" && parts.length === 1) return;
2477
+ // Already handled by the dedicated /task-queue/status route above
2478
+ if (parts[0] === "task-queue") return;
2479
+ // Already handled by the dedicated /remote/* routes above
2480
+ if (parts[0] === "remote") return;
2481
+ // Already handled by the dedicated /process-task route above
2482
+ if (parts[0] === "process-task") return;
2483
+ // Already handled by the dedicated /process-a2a-continuation route above
2484
+ if (parts[0] === "process-a2a-continuation") return;
2485
+ // These are framework-owned control-plane routes, not integration
2486
+ // platforms. The dedicated handlers above normally return a response
2487
+ // before this catch-all runs, but keeping them reserved here prevents
2488
+ // an unexpected mount fall-through from turning a valid control-plane
2489
+ // request into a misleading "Unknown platform" response.
2490
+ if (
2491
+ parts[0] === "installations" ||
2492
+ parts[0] === "scopes" ||
2493
+ parts[0] === "budgets" ||
2494
+ parts[0] === "memory"
2495
+ ) {
2496
+ setResponseStatus(event, 404);
2497
+ return { error: "Not found" };
2498
+ }
2499
+
2500
+ const platform = parts[0];
2501
+ const action = parts[1]; // webhook, status, enable, disable, setup
2502
+
2503
+ if (!platform) {
2504
+ setResponseStatus(event, 404);
2505
+ return { error: "Platform required" };
2506
+ }
2507
+
2508
+ const adapter = adapterMap.get(platform);
2509
+ if (!adapter) {
2510
+ setResponseStatus(event, 404);
2511
+ return { error: `Unknown platform: ${platform}` };
2512
+ }
2513
+
2514
+ // Set params for handlers that read them
2515
+ if (event.context) {
2516
+ event.context.params = {
2517
+ ...event.context.params,
2518
+ platform,
2519
+ };
2520
+ }
2521
+
2522
+ // ─── GET /:platform/status ─────────────────────────────
2523
+ if (action === "status" && method === "GET") {
2524
+ const ctx = await requireSessionContext(event);
2525
+ if (!ctx) return { error: "unauthorized" };
2526
+ const baseUrl = getBaseUrl(event);
2527
+ const status = await withCredentialContext(
2528
+ toCredentialContext(ctx),
2529
+ () => adapter.getStatus(baseUrl),
2530
+ );
2531
+ const config = await getIntegrationConfig(platform);
2532
+ status.enabled = !!config?.configData?.enabled;
2533
+ status.webhookUrl = `${baseUrl}${P}/${platform}/webhook`;
2534
+ if (!status.requiredEnvKeys) {
2535
+ try {
2536
+ status.requiredEnvKeys = adapter.getRequiredEnvKeys();
2537
+ } catch {
2538
+ status.requiredEnvKeys = [];
2539
+ }
2540
+ }
2541
+ return status;
2542
+ }
2543
+
2544
+ // ─── POST /:platform/webhook ───────────────────────────
2545
+ if (action === "webhook" && method === "POST") {
2546
+ // Google Docs push notifications bypass the normal webhook flow —
2547
+ // they're opaque "something changed" pings, not message payloads.
2548
+ // We MUST verify the Pub/Sub OIDC token here. Without it, anyone
2549
+ // could POST any body to this URL and force a Drive changes pull
2550
+ // (H7 in the webhook security audit).
2551
+ if (platform === "google-docs") {
2552
+ const audience = process.env.GOOGLE_DOCS_PUSH_AUDIENCE;
2553
+ if (!audience) {
2554
+ if (process.env.NODE_ENV === "production") {
2555
+ // Fail closed in prod so a misconfigured deployment surfaces
2556
+ // in Pub/Sub's delivery metrics rather than silently
2557
+ // accepting anonymous requests.
2558
+ setResponseStatus(event, 503);
2559
+ return {
2560
+ ok: false,
2561
+ error:
2562
+ "google-docs push endpoint disabled (audience not configured)",
2563
+ };
2564
+ }
2565
+ // Dev: keep the loose posture so contributors can play with the
2566
+ // integration locally without configuring Pub/Sub.
2567
+ handlePushNotification().catch((err) => {
2568
+ console.error("[google-docs] Push handler error:", err);
2569
+ });
2570
+ return "ok";
2571
+ }
2572
+ const authHeader = getRequestHeader(event, "authorization") || "";
2573
+ try {
2574
+ await verifyGoogleDocsPushToken(authHeader);
2575
+ } catch (err: any) {
2576
+ console.warn(
2577
+ `[google-docs] OIDC verify failed: ${err?.message ?? String(err)}`,
2578
+ );
2579
+ setResponseStatus(event, 401);
2580
+ return { ok: false, error: "unauthorized" };
2581
+ }
2582
+ handlePushNotification().catch((err) => {
2583
+ console.error("[google-docs] Push handler error:", err);
2584
+ });
2585
+ return "ok";
2586
+ }
2587
+
2588
+ const config = await getIntegrationConfig(platform);
2589
+ const credentialContext =
2590
+ await credentialContextForIntegrationConfig(config);
2591
+
2592
+ // Let the adapter cache the raw request and identify setup
2593
+ // challenges, but never return a challenge response until the
2594
+ // provider signature has been verified.
2595
+ const verification = await withCredentialContext(
2596
+ credentialContext,
2597
+ () => adapter.handleVerification(event),
2598
+ );
2599
+
2600
+ // Verify the webhook signature BEFORE parsing. We pre-parse the
2601
+ // body here (so handleWebhook can skip its second readBody, which
2602
+ // hangs on streaming providers), and that means handleWebhook's
2603
+ // own verifyWebhook step is bypassed. Without this call anyone
2604
+ // could POST a forged Slack/Telegram/email payload.
2605
+ const isValid = await withCredentialContext(credentialContext, () =>
2606
+ adapter.verifyWebhook(event),
2607
+ );
2608
+ if (!isValid) {
2609
+ setResponseStatus(event, 401);
2610
+ return { error: "Invalid webhook signature" };
2611
+ }
2612
+ if (verification.handled) {
2613
+ setResponseStatus(event, 200);
2614
+ return verification.response ?? "ok";
2615
+ }
2616
+
2617
+ if (!config?.configData?.enabled) {
2618
+ setResponseStatus(event, 404);
2619
+ return { error: `Integration ${platform} is not enabled` };
2620
+ }
2621
+
2622
+ let incoming = await withCredentialContext(credentialContext, () =>
2623
+ adapter.parseIncomingMessage(event),
2624
+ );
2625
+ if (!incoming) {
2626
+ setResponseStatus(event, 200);
2627
+ return "ok";
2628
+ }
2629
+ if (adapter.hydrateIncomingIdentity) {
2630
+ try {
2631
+ incoming = await withCredentialContext(credentialContext, () =>
2632
+ adapter.hydrateIncomingIdentity!(incoming!),
2633
+ );
2634
+ } catch (err) {
2635
+ // Identity hydration is best-effort for platforms that have an
2636
+ // app-specific resolver. Slack's default DM resolver below will
2637
+ // still fail closed when the identity is absent or unverified.
2638
+ console.warn(
2639
+ `[integrations] Could not hydrate ${platform} sender identity:`,
2640
+ err instanceof Error ? err.message : err,
2641
+ );
2642
+ }
2643
+ }
2644
+ let defaultExecutionContext: IntegrationExecutionContext | null =
2645
+ null;
2646
+ if (
2647
+ incoming.platform === "slack" &&
2648
+ incoming.conversationType === "dm" &&
2649
+ !options?.resolveExecutionContext
2650
+ ) {
2651
+ try {
2652
+ defaultExecutionContext = await withCredentialContext(
2653
+ credentialContext,
2654
+ () => resolveDefaultIntegrationExecutionContext(incoming!),
2655
+ );
2656
+ } catch (err) {
2657
+ // The legacy owner-only resolver predates org-bound identities
2658
+ // and must not turn a rejected Slack DM into an authenticated
2659
+ // owner run. Custom resolveExecutionContext is checked above and
2660
+ // skips this default ladder entirely so apps can fully own auth
2661
+ // without framework membership checks or identity side effects.
2662
+ const declined =
2663
+ err instanceof IntegrationIdentityDeclinedError ? err : null;
2664
+ if (declined) {
2665
+ console.warn(
2666
+ `[integrations] default Slack DM identity declined message:`,
2667
+ declined.message,
2668
+ );
2669
+ if (adapter.sendSystemNotice) {
2670
+ try {
2671
+ await enqueueSystemNotice(
2672
+ event,
2673
+ incoming!,
2674
+ declined.userFacingMessage,
2675
+ {
2676
+ dedupeKey: `decline:${incoming!.tenantId ?? "unknown"}:${incoming!.senderId ?? "unknown"}:${declined.reason}`,
2677
+ dedupeTtlMs: DECLINE_NOTICE_DEDUPE_TTL_MS,
2678
+ },
2679
+ );
2680
+ } catch (noticeErr) {
2681
+ console.warn(
2682
+ `[integrations] could not persist decline notice:`,
2683
+ noticeErr instanceof Error
2684
+ ? noticeErr.message
2685
+ : noticeErr,
2686
+ );
2687
+ setResponseStatus(event, 500);
2688
+ return { error: "notice enqueue failed" };
2689
+ }
2690
+ }
2691
+ } else {
2692
+ console.error(
2693
+ `[integrations] default Slack DM identity denied message:`,
2694
+ err,
2695
+ );
2696
+ }
2697
+ setResponseStatus(event, 200);
2698
+ return "ok";
2699
+ }
2700
+ }
2701
+ let executionContext: IntegrationExecutionContext = {
2702
+ ownerEmail: `integration@${platform}`,
2703
+ orgId: null as string | null,
2704
+ principalType: "service" as const,
2705
+ };
2706
+ if (options?.resolveExecutionContext) {
2707
+ try {
2708
+ executionContext = await withCredentialContext(
2709
+ credentialContext,
2710
+ () =>
2711
+ Promise.resolve(options.resolveExecutionContext!(incoming)),
2712
+ );
2713
+ } catch (err) {
2714
+ console.error(
2715
+ `[integrations] resolveExecutionContext denied message:`,
2716
+ err,
2717
+ );
2718
+ setResponseStatus(event, 200);
2719
+ return "ok";
2720
+ }
2721
+ } else if (defaultExecutionContext) {
2722
+ executionContext = defaultExecutionContext;
2723
+ if (defaultExecutionContext.anonymousMember) {
2724
+ if (!options?.allowAnonymousOrgScopedSlackDm) {
2725
+ const senderEmail =
2726
+ typeof incoming.senderEmail === "string" &&
2727
+ incoming.senderEmail.trim()
2728
+ ? incoming.senderEmail.trim()
2729
+ : null;
2730
+ const noticeText = senderEmail
2731
+ ? `I couldn't match your Slack account to an organization member, so I can't run this request. Ask an organization admin to add ${senderEmail}, then try again.`
2732
+ : "I couldn't verify your Slack account email, so I can't run this request. Ask an organization admin to reconnect Slack with the users:read.email scope, then try again.";
2733
+ if (adapter.sendSystemNotice) {
2734
+ try {
2735
+ await enqueueSystemNotice(event, incoming, noticeText, {
2736
+ dedupeKey: `anonymous-tier-disabled:${incoming.tenantId ?? "unknown"}:${incoming.senderId ?? "unknown"}`,
2737
+ });
2738
+ } catch (noticeErr) {
2739
+ console.warn(
2740
+ `[integrations] could not persist unlinked-member notice:`,
2741
+ noticeErr instanceof Error
2742
+ ? noticeErr.message
2743
+ : noticeErr,
2744
+ );
2745
+ setResponseStatus(event, 500);
2746
+ return { error: "notice enqueue failed" };
2747
+ }
2748
+ }
2749
+ setResponseStatus(event, 200);
2750
+ return "ok";
2751
+ }
2752
+ // The anonymous tier must never be silent. (1) The agent run
2753
+ // can tell: the note rides the serialized `incoming` into the
2754
+ // queued task and surfaces via <integration-context>.
2755
+ incoming.identityNote =
2756
+ "Caller is an unlinked Slack workspace member running with organization-wide visibility only; personal or privately-shared data is not accessible. They can get personal access by having an admin add their Slack email to the organization (or by reconnecting Slack with the users:read.email scope).";
2757
+ // (2) The sender gets a one-time heads-up through the same
2758
+ // durable SQL queue as agent work. The self-dispatch is only a
2759
+ // latency optimization; the retry sweep guarantees delivery.
2760
+ if (adapter.sendSystemNotice) {
2761
+ const senderEmail =
2762
+ typeof incoming.senderEmail === "string" &&
2763
+ incoming.senderEmail.trim()
2764
+ ? incoming.senderEmail.trim()
2765
+ : null;
2766
+ const noticeText = senderEmail
2767
+ ? `Heads up: I couldn't match your Slack account to an organization member, so I can only use org-wide data. Ask an admin to add ${senderEmail} to the organization for personal access.`
2768
+ : "Heads up: I couldn't verify your Slack account's email, so I can only use org-wide data. Ask an admin to update the Slack connection with the users:read.email scope for personal access.";
2769
+ try {
2770
+ await enqueueSystemNotice(event, incoming, noticeText, {
2771
+ dedupeKey: `anonymous-tier:${incoming.tenantId ?? "unknown"}:${incoming.senderId ?? "unknown"}`,
2772
+ });
2773
+ } catch (noticeErr) {
2774
+ console.warn(
2775
+ `[integrations] could not persist anonymous-tier notice:`,
2776
+ noticeErr instanceof Error ? noticeErr.message : noticeErr,
2777
+ );
2778
+ setResponseStatus(event, 500);
2779
+ return { error: "notice enqueue failed" };
2780
+ }
2781
+ }
2782
+ }
2783
+ } else if (options?.resolveOwner) {
2784
+ try {
2785
+ executionContext.ownerEmail = await withCredentialContext(
2786
+ credentialContext,
2787
+ () => Promise.resolve(options.resolveOwner!(incoming)),
2788
+ );
2789
+ } catch (err) {
2790
+ console.error(
2791
+ `[integrations] resolveOwner failed, using default:`,
2792
+ err,
2793
+ );
2794
+ }
2795
+ } else {
2796
+ try {
2797
+ executionContext = await withCredentialContext(
2798
+ credentialContext,
2799
+ () => resolveDefaultIntegrationExecutionContext(incoming!),
2800
+ );
2801
+ } catch (err) {
2802
+ console.error(
2803
+ `[integrations] default execution identity denied message:`,
2804
+ err,
2805
+ );
2806
+ setResponseStatus(event, 200);
2807
+ return "ok";
2808
+ }
2809
+ }
2810
+ if (executionContext.scopeId) {
2811
+ incoming.integrationScopeId = executionContext.scopeId;
2812
+ }
2813
+ const result = await handleWebhook(event, {
2814
+ adapter,
2815
+ // The processor reloads scoped resources immediately before the
2816
+ // agent run. Avoid doing that work on the acknowledgement path,
2817
+ // where providers such as Discord enforce a 3-second deadline.
2818
+ systemPrompt: baseSystemPrompt,
2819
+ actions,
2820
+ initialToolNames,
2821
+ model,
2822
+ apiKey: getApiKey(),
2823
+ engine: options?.engine,
2824
+ appId: options?.appId,
2825
+ ownerEmail: executionContext.ownerEmail,
2826
+ orgId: executionContext.orgId,
2827
+ principalType: executionContext.principalType,
2828
+ beforeProcess: options?.beforeProcess,
2829
+ incoming,
2830
+ });
2831
+ setResponseStatus(event, result.status);
2832
+ return result.body;
2833
+ }
2834
+
2835
+ // ─── POST /:platform/enable ────────────────────────────
2836
+ if (action === "enable" && method === "POST") {
2837
+ const adminCheck = await checkOrgAdmin(event);
2838
+ if (adminCheck.ok === false) return { error: adminCheck.error };
2839
+ // Stamp the org-admin who toggled this so downstream code can
2840
+ // tell who is responsible — useful for audit logs even though
2841
+ // the row itself remains deployment-wide.
2842
+ const session = await getSession(event).catch(() => null);
2843
+ await saveIntegrationConfig(
2844
+ platform,
2845
+ { enabled: true },
2846
+ "default",
2847
+ session?.email,
2848
+ );
2849
+ return { ok: true, platform, enabled: true };
2850
+ }
2851
+
2852
+ // ─── POST /:platform/disable ───────────────────────────
2853
+ if (action === "disable" && method === "POST") {
2854
+ const adminCheck = await checkOrgAdmin(event);
2855
+ if (adminCheck.ok === false) return { error: adminCheck.error };
2856
+ const session = await getSession(event).catch(() => null);
2857
+ await saveIntegrationConfig(
2858
+ platform,
2859
+ { enabled: false },
2860
+ "default",
2861
+ session?.email,
2862
+ );
2863
+ return { ok: true, platform, enabled: false };
2864
+ }
2865
+
2866
+ // ─── POST /:platform/setup ─────────────────────────────
2867
+ if (action === "setup" && method === "POST") {
2868
+ const adminCheck = await checkOrgAdmin(event);
2869
+ if (adminCheck.ok === false) return { error: adminCheck.error };
2870
+ if (platform === "telegram") {
2871
+ const baseUrl = getBaseUrl(event);
2872
+ const webhookUrl = `${baseUrl}${P}/telegram/webhook`;
2873
+ const ctx = await requireSessionContext(event);
2874
+ if (!ctx) return { error: "unauthorized" };
2875
+ const token = await withCredentialContext(
2876
+ toCredentialContext(ctx),
2877
+ () => resolveSecret("TELEGRAM_BOT_TOKEN"),
2878
+ );
2879
+ const webhookSecret = await withCredentialContext(
2880
+ toCredentialContext(ctx),
2881
+ () => resolveSecret("TELEGRAM_WEBHOOK_SECRET"),
2882
+ );
2883
+ if (!token || !webhookSecret) {
2884
+ setResponseStatus(event, 400);
2885
+ return {
2886
+ error:
2887
+ "TELEGRAM_BOT_TOKEN and TELEGRAM_WEBHOOK_SECRET must be configured before webhook setup.",
2888
+ };
2889
+ }
2890
+ try {
2891
+ const res = await fetch(
2892
+ `https://api.telegram.org/bot${token}/setWebhook`,
2893
+ {
2894
+ method: "POST",
2895
+ headers: { "Content-Type": "application/json" },
2896
+ body: JSON.stringify({
2897
+ url: webhookUrl,
2898
+ secret_token: webhookSecret,
2899
+ }),
2900
+ },
2901
+ );
2902
+ const data = await res.json();
2903
+ return { ok: true, platform, webhookUrl, result: data };
2904
+ } catch (err: any) {
2905
+ setResponseStatus(event, 500);
2906
+ return { error: err.message };
2907
+ }
2908
+ }
2909
+ return { ok: true, platform, message: "No setup required" };
2910
+ }
2911
+
2912
+ setResponseStatus(event, 404);
2913
+ return { error: "Not found" };
2914
+ }),
2915
+ );
2916
+
2917
+ // ─── Start pending-tasks retry sweeper ────────────────────────
2918
+ // Sweeps the integration_pending_tasks queue every 60s and re-fires the
2919
+ // processor for any tasks that got stuck (initial dispatch lost or
2920
+ // processor killed mid-flight). No-ops gracefully if the queue table
2921
+ // hasn't been created yet on this deployment.
2922
+ startPendingTasksRetryJob({
2923
+ webhookBaseUrl: process.env.WEBHOOK_BASE_URL,
2924
+ });
2925
+ startA2AContinuationRetryJob(adapterMap);
2926
+ startRemoteCommandsRetryJob();
2927
+ startRemotePushDeliveryJob();
2928
+
2929
+ // ─── Start Google Docs poller/push ────────────────────────────
2930
+ if (adapterMap.has("google-docs")) {
2931
+ // Defer startup slightly so the server is fully ready
2932
+ setTimeout(() => {
2933
+ // We don't know the base URL at plugin init time — it depends on
2934
+ // the incoming request. For push mode, the webhook URL needs to be
2935
+ // resolved. We pass it as a special option; the poller will attempt
2936
+ // to register a watch when the first request reveals the base URL,
2937
+ // or use the WEBHOOK_BASE_URL env var if set.
2938
+ const baseUrl = process.env.WEBHOOK_BASE_URL;
2939
+ const webhookUrl = baseUrl
2940
+ ? `${withConfiguredAppBasePath(baseUrl)}${P}/google-docs/webhook`
2941
+ : undefined;
2942
+
2943
+ void startGoogleDocsPoller({
2944
+ systemPrompt: baseSystemPrompt,
2945
+ actions,
2946
+ initialToolNames,
2947
+ model: model ?? "",
2948
+ apiKey: getApiKey(),
2949
+ ownerEmail: "integration@google-docs",
2950
+ webhookUrl,
2951
+ });
2952
+ }, 2000);
2953
+ }
2954
+
2955
+ if (process.env.DEBUG)
2956
+ console.log(
2957
+ `[integrations] Mounted integration routes for: ${adapters.map((a) => a.platform).join(", ")}`,
2958
+ );
2959
+ };
2960
+ }
2961
+
2962
+ /**
2963
+ * Default integrations plugin — auto-mounts all adapters.
2964
+ */
2965
+ export const defaultIntegrationsPlugin = createIntegrationsPlugin();
2966
+
2967
+ /** Extract base URL from the request */
2968
+ function getBaseUrl(event: any): string {
2969
+ try {
2970
+ const headers = event.node?.req?.headers || event.headers || {};
2971
+ const getHeader = (name: string) =>
2972
+ typeof headers.get === "function"
2973
+ ? headers.get(name)
2974
+ : (headers as Record<string, string>)[name];
2975
+ const proto = getHeader("x-forwarded-proto") || "http";
2976
+ const host = getHeader("host") || "localhost:3000";
2977
+ return withConfiguredAppBasePath(`${proto}://${host}`);
2978
+ } catch {
2979
+ return withConfiguredAppBasePath("http://localhost:3000");
2980
+ }
2981
+ }
2982
+
2983
+ function sleep(ms: number): Promise<void> {
2984
+ return new Promise((resolve) => setTimeout(resolve, ms));
2985
+ }
2986
+
2987
+ function readComputerCapabilities(value: unknown) {
2988
+ const input = readObject(value);
2989
+ const readSurface = (surface: unknown, desktop = false) => {
2990
+ const record = readObject(surface);
2991
+ if (!record) return undefined;
2992
+ return {
2993
+ observe: record.observe === true,
2994
+ control: record.control === true,
2995
+ ...(desktop
2996
+ ? {
2997
+ accessibility: record.accessibility === true,
2998
+ screenCapture: record.screenCapture === true,
2999
+ }
3000
+ : {}),
3001
+ provider: readString(record.provider) ?? null,
3002
+ version: readString(record.version) ?? null,
3003
+ };
3004
+ };
3005
+ return {
3006
+ browser: readSurface(input?.browser),
3007
+ desktop: readSurface(input?.desktop, true),
3008
+ };
3009
+ }
3010
+
3011
+ function advertisedComputerOperationClasses(
3012
+ device: Pick<RemoteDevice, "metadata">,
3013
+ ): ComputerOperationClass[] {
3014
+ const capabilities = getRemoteComputerCapabilities(device);
3015
+ const classes: ComputerOperationClass[] = [];
3016
+ if (capabilities?.browser?.observe) classes.push("browser.observe");
3017
+ if (capabilities?.browser?.control) classes.push("browser.control");
3018
+ if (capabilities?.desktop?.observe) classes.push("desktop.observe");
3019
+ if (capabilities?.desktop?.control) classes.push("desktop.control");
3020
+ return classes;
3021
+ }
3022
+
3023
+ function readComputerApprovalStatus(value: unknown) {
3024
+ return value === "pending" ||
3025
+ value === "approved" ||
3026
+ value === "denied" ||
3027
+ value === "consumed" ||
3028
+ value === "expired"
3029
+ ? value
3030
+ : undefined;
3031
+ }
3032
+
3033
+ function computerSupervisionRouteError(event: any, error: unknown) {
3034
+ if (error instanceof ComputerSupervisionError) {
3035
+ const status =
3036
+ error.code === "expired-lease"
3037
+ ? 410
3038
+ : error.code === "replay"
3039
+ ? 409
3040
+ : error.code === "approval-required" ||
3041
+ error.code === "approval-denied"
3042
+ ? 403
3043
+ : 400;
3044
+ setResponseStatus(event, status);
3045
+ return { error: error.message, code: error.code };
3046
+ }
3047
+ throw error;
3048
+ }