@agent-native/core 0.92.12 → 0.93.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 (772) hide show
  1. package/corpus/README.md +2 -2
  2. package/corpus/core/CHANGELOG.md +39 -0
  3. package/corpus/core/docs/content/automation-connectors.mdx +80 -0
  4. package/corpus/core/docs/content/extensions.mdx +8 -0
  5. package/corpus/core/docs/content/locales/ar-SA/extensions.mdx +8 -0
  6. package/corpus/core/docs/content/locales/ar-SA/messaging.mdx +84 -15
  7. package/corpus/core/docs/content/locales/ar-SA/template-clips.mdx +1 -0
  8. package/corpus/core/docs/content/locales/ar-SA/template-design.mdx +1 -0
  9. package/corpus/core/docs/content/locales/de-DE/extensions.mdx +10 -0
  10. package/corpus/core/docs/content/locales/de-DE/messaging.mdx +92 -15
  11. package/corpus/core/docs/content/locales/de-DE/template-clips.mdx +1 -0
  12. package/corpus/core/docs/content/locales/de-DE/template-design.mdx +1 -0
  13. package/corpus/core/docs/content/locales/es-ES/extensions.mdx +10 -0
  14. package/corpus/core/docs/content/locales/es-ES/messaging.mdx +91 -15
  15. package/corpus/core/docs/content/locales/es-ES/template-clips.mdx +1 -0
  16. package/corpus/core/docs/content/locales/es-ES/template-design.mdx +1 -0
  17. package/corpus/core/docs/content/locales/fr-FR/extensions.mdx +10 -0
  18. package/corpus/core/docs/content/locales/fr-FR/messaging.mdx +91 -15
  19. package/corpus/core/docs/content/locales/fr-FR/template-clips.mdx +1 -0
  20. package/corpus/core/docs/content/locales/fr-FR/template-design.mdx +1 -0
  21. package/corpus/core/docs/content/locales/hi-IN/extensions.mdx +8 -0
  22. package/corpus/core/docs/content/locales/hi-IN/messaging.mdx +81 -15
  23. package/corpus/core/docs/content/locales/hi-IN/template-clips.mdx +1 -0
  24. package/corpus/core/docs/content/locales/hi-IN/template-design.mdx +1 -0
  25. package/corpus/core/docs/content/locales/ja-JP/extensions.mdx +9 -0
  26. package/corpus/core/docs/content/locales/ja-JP/messaging.mdx +81 -15
  27. package/corpus/core/docs/content/locales/ja-JP/template-clips.mdx +1 -0
  28. package/corpus/core/docs/content/locales/ja-JP/template-design.mdx +1 -0
  29. package/corpus/core/docs/content/locales/ko-KR/extensions.mdx +8 -0
  30. package/corpus/core/docs/content/locales/ko-KR/messaging.mdx +80 -15
  31. package/corpus/core/docs/content/locales/ko-KR/template-clips.mdx +1 -0
  32. package/corpus/core/docs/content/locales/ko-KR/template-design.mdx +1 -0
  33. package/corpus/core/docs/content/locales/pt-BR/extensions.mdx +9 -0
  34. package/corpus/core/docs/content/locales/pt-BR/messaging.mdx +88 -15
  35. package/corpus/core/docs/content/locales/pt-BR/template-clips.mdx +1 -0
  36. package/corpus/core/docs/content/locales/pt-BR/template-design.mdx +1 -0
  37. package/corpus/core/docs/content/locales/zh-CN/extensions.mdx +6 -0
  38. package/corpus/core/docs/content/locales/zh-CN/messaging.mdx +78 -15
  39. package/corpus/core/docs/content/locales/zh-CN/template-clips.mdx +1 -0
  40. package/corpus/core/docs/content/locales/zh-CN/template-design.mdx +1 -0
  41. package/corpus/core/docs/content/locales/zh-TW/extensions.mdx +6 -0
  42. package/corpus/core/docs/content/locales/zh-TW/messaging.mdx +78 -15
  43. package/corpus/core/docs/content/locales/zh-TW/template-clips.mdx +1 -0
  44. package/corpus/core/docs/content/locales/zh-TW/template-design.mdx +1 -0
  45. package/corpus/core/docs/content/messaging.mdx +227 -45
  46. package/corpus/core/docs/content/template-clips.mdx +3 -0
  47. package/corpus/core/docs/content/template-design.mdx +4 -0
  48. package/corpus/core/package.json +5 -1
  49. package/corpus/core/src/a2a/artifact-response.ts +131 -2
  50. package/corpus/core/src/a2a/client.ts +10 -0
  51. package/corpus/core/src/a2a/handlers.ts +40 -76
  52. package/corpus/core/src/a2a/types.ts +2 -0
  53. package/corpus/core/src/agent/durable-background.ts +24 -0
  54. package/corpus/core/src/agent/production-agent.ts +15 -3
  55. package/corpus/core/src/agent/run-manager.ts +130 -10
  56. package/corpus/core/src/agent/run-store.ts +225 -15
  57. package/corpus/core/src/agent/types.ts +23 -0
  58. package/corpus/core/src/audit/record.ts +31 -0
  59. package/corpus/core/src/audit/store.ts +69 -3
  60. package/corpus/core/src/audit/types.ts +13 -0
  61. package/corpus/core/src/automation/index.ts +802 -0
  62. package/corpus/core/src/cli/create.ts +12 -5
  63. package/corpus/core/src/cli/design-connect.ts +596 -36
  64. package/corpus/core/src/client/AgentPanel.tsx +51 -6
  65. package/corpus/core/src/client/AssistantChat.tsx +274 -147
  66. package/corpus/core/src/client/MultiTabAssistantChat.tsx +3 -0
  67. package/corpus/core/src/client/RunStuckBanner.tsx +69 -20
  68. package/corpus/core/src/client/agent-chat-adapter.ts +54 -5
  69. package/corpus/core/src/client/automation.ts +22 -0
  70. package/corpus/core/src/client/chat/run-recovery.tsx +67 -50
  71. package/corpus/core/src/client/composer/TiptapComposer.tsx +8 -0
  72. package/corpus/core/src/client/index.ts +30 -0
  73. package/corpus/core/src/client/integrations/api.ts +295 -0
  74. package/corpus/core/src/client/integrations/index.ts +26 -0
  75. package/corpus/core/src/client/transcription/use-live-transcription.ts +68 -5
  76. package/corpus/core/src/client/use-run-stuck-detection.ts +41 -3
  77. package/corpus/core/src/deploy/build.ts +59 -3
  78. package/corpus/core/src/deploy/workspace-deploy.ts +37 -2
  79. package/corpus/core/src/file-upload/types.ts +2 -0
  80. package/corpus/core/src/index.ts +37 -0
  81. package/corpus/core/src/integrations/a2a-continuations-store.ts +6 -4
  82. package/corpus/core/src/integrations/adapters/discord.ts +362 -0
  83. package/corpus/core/src/integrations/adapters/index.ts +29 -0
  84. package/corpus/core/src/integrations/adapters/microsoft-teams.ts +411 -0
  85. package/corpus/core/src/integrations/adapters/slack.ts +861 -27
  86. package/corpus/core/src/integrations/adapters/telegram.ts +54 -15
  87. package/corpus/core/src/integrations/adapters/whatsapp.ts +41 -17
  88. package/corpus/core/src/integrations/catalog.ts +571 -0
  89. package/corpus/core/src/integrations/controls-store.ts +187 -0
  90. package/corpus/core/src/integrations/index.ts +100 -0
  91. package/corpus/core/src/integrations/installations-store.ts +677 -0
  92. package/corpus/core/src/integrations/integration-memory.ts +187 -0
  93. package/corpus/core/src/integrations/pending-tasks-retry-job.ts +6 -6
  94. package/corpus/core/src/integrations/pending-tasks-store.ts +83 -5
  95. package/corpus/core/src/integrations/plugin.ts +685 -47
  96. package/corpus/core/src/integrations/scope-store.ts +498 -0
  97. package/corpus/core/src/integrations/slack-manifest.ts +78 -0
  98. package/corpus/core/src/integrations/slack-oauth.ts +343 -0
  99. package/corpus/core/src/integrations/types.ts +179 -0
  100. package/corpus/core/src/integrations/usage-budget-store.ts +906 -0
  101. package/corpus/core/src/integrations/webhook-handler.ts +562 -51
  102. package/corpus/core/src/jobs/scheduler.ts +100 -2
  103. package/corpus/core/src/jobs/tools.ts +45 -9
  104. package/corpus/core/src/provider-api/index.ts +72 -1
  105. package/corpus/core/src/resources/handlers.ts +88 -14
  106. package/corpus/core/src/resources/script-helpers.ts +36 -7
  107. package/corpus/core/src/resources/store.ts +59 -52
  108. package/corpus/core/src/scripts/call-agent.ts +107 -1
  109. package/corpus/core/src/server/agent-chat-plugin.ts +294 -119
  110. package/corpus/core/src/server/auth.ts +10 -14
  111. package/corpus/core/src/server/builder-design-systems.ts +16 -1
  112. package/corpus/core/src/server/edge.ts +18 -0
  113. package/corpus/core/src/server/index.ts +26 -0
  114. package/corpus/core/src/server/request-context.ts +18 -0
  115. package/corpus/core/src/server/social-og-image.ts +3 -2
  116. package/corpus/core/src/styles/agent-native.css +62 -44
  117. package/corpus/core/src/templates/default/.agents/skills/capture-learnings/SKILL.md +22 -9
  118. package/corpus/core/src/templates/default/AGENTS.md +7 -3
  119. package/corpus/core/src/templates/workspace-core/.agents/skills/authentication/SKILL.md +1 -1
  120. package/corpus/core/src/templates/workspace-core/.agents/skills/capture-learnings/SKILL.md +22 -9
  121. package/corpus/core/src/templates/workspace-core/.agents/skills/extension-points/SKILL.md +6 -3
  122. package/corpus/core/src/templates/workspace-core/.agents/skills/extensions/SKILL.md +25 -0
  123. package/corpus/core/src/templates/workspace-core/.agents/skills/integration-webhooks/SKILL.md +15 -0
  124. package/corpus/core/src/templates/workspace-core/AGENTS.md +3 -2
  125. package/corpus/core/src/usage/store.ts +37 -2
  126. package/corpus/templates/analytics/.agents/skills/capture-learnings/SKILL.md +22 -9
  127. package/corpus/templates/analytics/.agents/skills/provider-api/SKILL.md +23 -0
  128. package/corpus/templates/analytics/.builder/skills/provider-api/SKILL.md +15 -0
  129. package/corpus/templates/analytics/actions/save-monitor.ts +25 -2
  130. package/corpus/templates/analytics/app/lib/data-sources.ts +28 -0
  131. package/corpus/templates/analytics/changelog/2026-07-10-agent-created-uptime-monitors-now-return-a-direct-link-to-th.md +6 -0
  132. package/corpus/templates/analytics/changelog/2026-07-10-dashboard-email-reports-still-arrive-when-screenshot-capture-temporarily-fails.md +6 -0
  133. package/corpus/templates/analytics/server/jobs/dashboard-report.ts +3 -7
  134. package/corpus/templates/analytics/server/lib/credential-keys.ts +12 -0
  135. package/corpus/templates/analytics/server/lib/dashboard-report.ts +5 -1
  136. package/corpus/templates/analytics/server/lib/provider-credentials.ts +2 -0
  137. package/corpus/templates/analytics/server/routes/api/test-connection.post.ts +16 -0
  138. package/corpus/templates/assets/.agents/skills/capture-learnings/SKILL.md +22 -9
  139. package/corpus/templates/brain/.agents/skills/capture-learnings/SKILL.md +22 -9
  140. package/corpus/templates/calendar/.agents/skills/capture-learnings/SKILL.md +22 -9
  141. package/corpus/templates/calendar/app/components/calendar/CommandPalette.tsx +98 -108
  142. package/corpus/templates/calendar/app/components/calendar/EventAttendeesSection.tsx +97 -90
  143. package/corpus/templates/calendar/changelog/2026-07-10-event-guest-details-and-option-menus-now-use-valid-accessibl.md +6 -0
  144. package/corpus/templates/calendar/changelog/2026-07-10-natural-language-event-phrases-stay-available-as-quick-creat.md +6 -0
  145. package/corpus/templates/chat/.agents/skills/capture-learnings/SKILL.md +22 -9
  146. package/corpus/templates/chat/changelog/2026-07-10-chat-now-makes-ai-connection-setup-clear-without-shifting-th.md +6 -0
  147. package/corpus/templates/clips/.agents/skills/capture-learnings/SKILL.md +22 -9
  148. package/corpus/templates/clips/.agents/skills/recording/SKILL.md +17 -1
  149. package/corpus/templates/clips/.agents/skills/video-sharing/SKILL.md +8 -0
  150. package/corpus/templates/clips/AGENTS.md +8 -3
  151. package/corpus/templates/clips/actions/finalize-recording.ts +63 -23
  152. package/corpus/templates/clips/actions/get-recording-player-data.ts +6 -2
  153. package/corpus/templates/clips/actions/lib/ensure-seekable-video.ts +72 -9
  154. package/corpus/templates/clips/actions/list-recordings.ts +19 -3
  155. package/corpus/templates/clips/actions/navigate.ts +2 -0
  156. package/corpus/templates/clips/actions/reprocess-recording.ts +20 -6
  157. package/corpus/templates/clips/actions/request-transcript.ts +16 -31
  158. package/corpus/templates/clips/actions/view-screen.ts +57 -5
  159. package/corpus/templates/clips/app/components/layout/Header.tsx +1 -0
  160. package/corpus/templates/clips/app/components/library/empty-state.tsx +2 -0
  161. package/corpus/templates/clips/app/components/library/library-grid.tsx +69 -42
  162. package/corpus/templates/clips/app/components/library/library-layout.tsx +15 -1
  163. package/corpus/templates/clips/app/components/library/recording-card.tsx +81 -68
  164. package/corpus/templates/clips/app/components/library/search-bar.tsx +4 -3
  165. package/corpus/templates/clips/app/components/player/delete-recording-menu.tsx +9 -3
  166. package/corpus/templates/clips/app/components/player/share-dialog.tsx +1 -1
  167. package/corpus/templates/clips/app/hooks/use-library.ts +1 -1
  168. package/corpus/templates/clips/app/hooks/use-navigation-state.ts +10 -2
  169. package/corpus/templates/clips/app/i18n/ar-SA.ts +7 -1
  170. package/corpus/templates/clips/app/i18n/de-DE.ts +7 -1
  171. package/corpus/templates/clips/app/i18n/en-US.ts +7 -1
  172. package/corpus/templates/clips/app/i18n/es-ES.ts +7 -1
  173. package/corpus/templates/clips/app/i18n/fr-FR.ts +7 -1
  174. package/corpus/templates/clips/app/i18n/hi-IN.ts +7 -1
  175. package/corpus/templates/clips/app/i18n/ja-JP.ts +7 -1
  176. package/corpus/templates/clips/app/i18n/ko-KR.ts +7 -1
  177. package/corpus/templates/clips/app/i18n/pt-BR.ts +7 -1
  178. package/corpus/templates/clips/app/i18n/zh-CN.ts +8 -1
  179. package/corpus/templates/clips/app/i18n/zh-TW.ts +8 -1
  180. package/corpus/templates/clips/app/lib/recording-visibility.ts +70 -0
  181. package/corpus/templates/clips/app/routes/_app.shared.tsx +20 -0
  182. package/corpus/templates/clips/app/routes/download.tsx +24 -8
  183. package/corpus/templates/clips/app/routes/r.$recordingId.tsx +115 -2
  184. package/corpus/templates/clips/app/routes/record.tsx +62 -0
  185. package/corpus/templates/clips/app/routes/share.$shareId.tsx +25 -16
  186. package/corpus/templates/clips/changelog/2026-07-10-clips-desktop-is-now-available-for-linux-with-appimage-debia.md +6 -0
  187. package/corpus/templates/clips/changelog/2026-07-10-clips-downloads-updates-sooner-in-the-background-and-offers-.md +6 -0
  188. package/corpus/templates/clips/changelog/2026-07-10-clips-shared-with-you-now-appear-in-a-searchable-shared-with.md +6 -0
  189. package/corpus/templates/clips/changelog/2026-07-10-clips-with-missing-mobile-video-frames-can-be-repaired-witho.md +6 -0
  190. package/corpus/templates/clips/changelog/2026-07-10-mobile-camera-recordings-pause-while-backgrounded.md +6 -0
  191. package/corpus/templates/clips/changelog/2026-07-10-mp4-downloads-now-show-progress-immediately-after-the-option.md +6 -0
  192. package/corpus/templates/clips/changelog/2026-07-10-recording-pages-now-open-as-soon-as-you-stop-with-a-share-li.md +6 -0
  193. package/corpus/templates/clips/changelog/2026-07-10-recordings-now-seek-smoothly-downloads-use-the-correct-file-.md +6 -0
  194. package/corpus/templates/clips/changelog/2026-07-10-s3-compatible-storage-now-saves-hosted-recordings-without-re.md +6 -0
  195. package/corpus/templates/clips/desktop/README.md +22 -6
  196. package/corpus/templates/clips/desktop/package.json +1 -1
  197. package/corpus/templates/clips/desktop/src/app.tsx +32 -19
  198. package/corpus/templates/clips/desktop/src/components/ReadinessPanel.tsx +15 -9
  199. package/corpus/templates/clips/desktop/src/lib/finalization-guard.ts +22 -0
  200. package/corpus/templates/clips/desktop/src/lib/permissions.ts +3 -1
  201. package/corpus/templates/clips/desktop/src/lib/recorder.ts +97 -120
  202. package/corpus/templates/clips/desktop/src/lib/updater.ts +26 -4
  203. package/corpus/templates/clips/desktop/src/overlays/finalizing.tsx +4 -8
  204. package/corpus/templates/clips/desktop/src-tauri/Cargo.toml +1 -1
  205. package/corpus/templates/clips/desktop/src-tauri/src/clips/mod.rs +2 -2
  206. package/corpus/templates/clips/desktop/src-tauri/src/permission_status.rs +11 -7
  207. package/corpus/templates/clips/desktop/src-tauri/tauri.linux.conf.json +11 -0
  208. package/corpus/templates/clips/netlify.toml +3 -0
  209. package/corpus/templates/clips/server/lib/post-finalize-dispatch.ts +106 -0
  210. package/corpus/templates/clips/server/lib/public-agent-context.ts +9 -1
  211. package/corpus/templates/clips/server/lib/resumable-upload-provider.ts +52 -0
  212. package/corpus/templates/clips/server/lib/s3-upload-provider.ts +433 -85
  213. package/corpus/templates/clips/server/lib/video-remux.ts +114 -0
  214. package/corpus/templates/clips/server/routes/api/_agent-native-background/post-finalize-worker.post.ts +109 -0
  215. package/corpus/templates/clips/server/routes/api/clips-updater.json.get.ts +22 -11
  216. package/corpus/templates/clips/server/routes/api/public-recording.get.ts +4 -2
  217. package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/abort.post.ts +47 -5
  218. package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/chunk.post.ts +10 -2
  219. package/corpus/templates/clips/shared/share-loader-response.ts +12 -0
  220. package/corpus/templates/clips/shared/transcript-status.ts +40 -0
  221. package/corpus/templates/content/.agents/skills/capture-learnings/SKILL.md +22 -9
  222. package/corpus/templates/content/.agents/skills/content/SKILL.md +57 -5
  223. package/corpus/templates/content/AGENTS.md +65 -55
  224. package/corpus/templates/content/actions/_builder-cms-read-client.ts +10 -16
  225. package/corpus/templates/content/actions/_database-source-utils.ts +58 -11
  226. package/corpus/templates/content/actions/_property-utils.ts +30 -2
  227. package/corpus/templates/content/actions/add-content-database-source-field-property.ts +312 -114
  228. package/corpus/templates/content/actions/submit-content-database-form.ts +497 -0
  229. package/corpus/templates/content/actions/update-content-database-view.ts +8 -1
  230. package/corpus/templates/content/actions/view-screen.ts +4 -1
  231. package/corpus/templates/content/agent-native.app-skill.json +1 -1
  232. package/corpus/templates/content/app/components/editor/database/DatabaseView.tsx +250 -64
  233. package/corpus/templates/content/app/components/editor/database/FormView.tsx +460 -0
  234. package/corpus/templates/content/app/components/editor/database/navigation-state.ts +3 -0
  235. package/corpus/templates/content/app/components/editor/database/settings.tsx +30 -37
  236. package/corpus/templates/content/app/components/editor/database/shared.tsx +2 -0
  237. package/corpus/templates/content/app/components/editor/database/view-config.ts +29 -1
  238. package/corpus/templates/content/app/components/ui/textarea.tsx +1 -0
  239. package/corpus/templates/content/app/hooks/use-content-database.ts +22 -0
  240. package/corpus/templates/content/app/i18n/zh-TW.ts +21 -0
  241. package/corpus/templates/content/app/i18n-data.ts +225 -0
  242. package/corpus/templates/content/changelog/2026-07-10-builder-backed-properties-now-load-current-source-values-as-.md +6 -0
  243. package/corpus/templates/content/changelog/2026-07-10-builder-database-refreshes-now-stay-explicit-and-accurate.md +6 -0
  244. package/corpus/templates/content/changelog/2026-07-10-database-form-views-now-collect-ordered-required-answers-and.md +6 -0
  245. package/corpus/templates/content/changelog/2026-07-10-database-tables-now-use-a-quieter-more-compact-layout-with-c.md +6 -0
  246. package/corpus/templates/content/changelog/2026-07-10-slack-intake-routes-to-content-database-forms.md +6 -0
  247. package/corpus/templates/content/parity/matrix.md +1 -0
  248. package/corpus/templates/content/parity/matrix.ts +18 -0
  249. package/corpus/templates/content/shared/api.ts +27 -1
  250. package/corpus/templates/content/shared/database-form.ts +53 -0
  251. package/corpus/templates/design/.agents/skills/capture-learnings/SKILL.md +22 -9
  252. package/corpus/templates/design/.agents/skills/design-generation/SKILL.md +26 -0
  253. package/corpus/templates/design/.agents/skills/design-systems/SKILL.md +85 -12
  254. package/corpus/templates/design/AGENTS.md +72 -18
  255. package/corpus/templates/design/DESIGN.md +1 -1
  256. package/corpus/templates/design/DEVELOPING.md +1 -1
  257. package/corpus/templates/design/FIGMA_INTEROPERABILITY.md +116 -0
  258. package/corpus/templates/design/actions/create-design-from-template.ts +220 -0
  259. package/corpus/templates/design/actions/create-design-system.ts +92 -16
  260. package/corpus/templates/design/actions/delete-design-template.ts +28 -0
  261. package/corpus/templates/design/actions/delete-file.ts +7 -0
  262. package/corpus/templates/design/actions/edit-design.ts +3 -0
  263. package/corpus/templates/design/actions/export-design-as-figma-svg.ts +137 -5
  264. package/corpus/templates/design/actions/export-pdf.ts +1 -1
  265. package/corpus/templates/design/actions/generate-design.ts +3 -0
  266. package/corpus/templates/design/actions/get-design-snapshot.ts +9 -0
  267. package/corpus/templates/design/actions/get-figma-connection-status.ts +26 -0
  268. package/corpus/templates/design/actions/get-figma-design-context.ts +138 -0
  269. package/corpus/templates/design/actions/get-figma-styles.ts +2 -2
  270. package/corpus/templates/design/actions/import-figma-clipboard.ts +112 -16
  271. package/corpus/templates/design/actions/import-figma-frame.ts +15 -4
  272. package/corpus/templates/design/actions/index-design-system-with-builder.ts +4 -0
  273. package/corpus/templates/design/actions/list-design-templates.ts +118 -0
  274. package/corpus/templates/design/actions/navigate.ts +16 -2
  275. package/corpus/templates/design/actions/provider-api-request.ts +11 -1
  276. package/corpus/templates/design/actions/save-design-as-template.ts +156 -0
  277. package/corpus/templates/design/actions/set-active-breakpoint.ts +13 -4
  278. package/corpus/templates/design/actions/take-design-screenshot.ts +73 -3
  279. package/corpus/templates/design/actions/update-file.ts +39 -22
  280. package/corpus/templates/design/actions/view-screen.ts +36 -1
  281. package/corpus/templates/design/actions/write-local-file.ts +50 -38
  282. package/corpus/templates/design/app/components/design/AutoLayoutSuggestionDialog.tsx +151 -0
  283. package/corpus/templates/design/app/components/design/CanvasContextMenu.tsx +20 -0
  284. package/corpus/templates/design/app/components/design/DesignCanvas.tsx +251 -22
  285. package/corpus/templates/design/app/components/design/DesignEditorSkeleton.tsx +3 -3
  286. package/corpus/templates/design/app/components/design/DesignImportPanel.tsx +384 -9
  287. package/corpus/templates/design/app/components/design/EditPanel.tsx +105 -32
  288. package/corpus/templates/design/app/components/design/MultiScreenCanvas.tsx +58 -28
  289. package/corpus/templates/design/app/components/design/TweaksPanel.tsx +6 -0
  290. package/corpus/templates/design/app/components/design/bridge/editor-chrome.bridge.ts +539 -53
  291. package/corpus/templates/design/app/components/design/bridge/embedded-wheel.bridge.ts +40 -0
  292. package/corpus/templates/design/app/components/design/code-workbench/CodeWorkbench.tsx +1 -0
  293. package/corpus/templates/design/app/components/design/code-workbench/explorer/ExplorerView.tsx +1 -0
  294. package/corpus/templates/design/app/components/design/code-workbench/explorer/FileTree.tsx +5 -1
  295. package/corpus/templates/design/app/components/design/code-workbench/workspace/create-providers.ts +2 -0
  296. package/corpus/templates/design/app/components/design/code-workbench/workspace/localhost-provider.ts +3 -1
  297. package/corpus/templates/design/app/components/design/code-workbench/workspace/types.ts +2 -0
  298. package/corpus/templates/design/app/components/design/edit-panel/element-identity.ts +19 -0
  299. package/corpus/templates/design/app/components/design/edit-panel/frame-presets-panel.tsx +1 -0
  300. package/corpus/templates/design/app/components/design/edit-panel/interaction-state-helpers.ts +27 -0
  301. package/corpus/templates/design/app/components/design/inspector/InteractionStatePanel.tsx +137 -81
  302. package/corpus/templates/design/app/components/design/inspector/frame-size-presets.ts +25 -5
  303. package/corpus/templates/design/app/components/design/multi-screen/chrome-transitions.ts +1 -1
  304. package/corpus/templates/design/app/components/design/multi-screen/frame-geometry.ts +220 -3
  305. package/corpus/templates/design/app/components/design/multi-screen/overview-layout.ts +13 -0
  306. package/corpus/templates/design/app/components/design/multi-screen/types.ts +22 -1
  307. package/corpus/templates/design/app/components/design/types.ts +4 -0
  308. package/corpus/templates/design/app/components/design-system/ProductionDesignSystemShowcase.tsx +208 -0
  309. package/corpus/templates/design/app/components/editor/FigmaLinkComposerBubble.tsx +321 -0
  310. package/corpus/templates/design/app/components/editor/PromptDialog.tsx +24 -4
  311. package/corpus/templates/design/app/components/layout/Layout.tsx +16 -2
  312. package/corpus/templates/design/app/components/layout/Sidebar.tsx +2 -0
  313. package/corpus/templates/design/app/components/templates/TemplatePreview.tsx +72 -0
  314. package/corpus/templates/design/app/global.css +2 -35
  315. package/corpus/templates/design/app/hooks/use-navigation-state.ts +10 -0
  316. package/corpus/templates/design/app/i18n/zh-TW.ts +127 -5
  317. package/corpus/templates/design/app/i18n-breakpoints.ts +209 -0
  318. package/corpus/templates/design/app/i18n-data.ts +1317 -59
  319. package/corpus/templates/design/app/i18n-template-feature.ts +458 -0
  320. package/corpus/templates/design/app/lib/design-clipboard.ts +202 -0
  321. package/corpus/templates/design/app/lib/design-file-upload.ts +87 -0
  322. package/corpus/templates/design/app/lib/design-import.ts +168 -11
  323. package/corpus/templates/design/app/lib/desktop-design-preview.ts +423 -0
  324. package/corpus/templates/design/app/lib/figma-clipboard.ts +74 -8
  325. package/corpus/templates/design/app/lib/figma-connection.ts +161 -0
  326. package/corpus/templates/design/app/lib/figma-svg-copy.ts +814 -22
  327. package/corpus/templates/design/app/lib/figma-url.ts +77 -0
  328. package/corpus/templates/design/app/lib/pending-generation.ts +35 -0
  329. package/corpus/templates/design/app/pages/DesignSystems.tsx +236 -177
  330. package/corpus/templates/design/app/pages/Index.tsx +38 -0
  331. package/corpus/templates/design/app/pages/Templates.tsx +498 -0
  332. package/corpus/templates/design/app/pages/design-editor/auto-layout-suggestion.ts +328 -0
  333. package/corpus/templates/design/app/pages/design-editor/clone-idrefs.ts +113 -0
  334. package/corpus/templates/design/app/pages/design-editor/created-screen-navigation.ts +55 -0
  335. package/corpus/templates/design/app/pages/design-editor/editor-session.ts +32 -0
  336. package/corpus/templates/design/app/pages/design-editor/editor-state.ts +49 -2
  337. package/corpus/templates/design/app/pages/design-editor/export-capture.ts +296 -0
  338. package/corpus/templates/design/app/pages/design-editor/history.ts +101 -2
  339. package/corpus/templates/design/app/pages/design-editor/layout-operations.ts +28 -1
  340. package/corpus/templates/design/app/pages/design-editor/overview-camera.ts +34 -0
  341. package/corpus/templates/design/app/pages/design-editor/pending-edits.ts +202 -6
  342. package/corpus/templates/design/app/pages/design-editor/pending-structure-verification.ts +92 -0
  343. package/corpus/templates/design/app/pages/design-editor/save-failure.ts +58 -0
  344. package/corpus/templates/design/app/routes/templates.tsx +4 -6
  345. package/corpus/templates/design/changelog/2026-07-10-app-workspaces-now-use-clean-borderless-main-surfaces-throug.md +6 -0
  346. package/corpus/templates/design/changelog/2026-07-10-ask-chat-what-s-in-a-figma-file-or-frame-structure-screensho.md +6 -0
  347. package/corpus/templates/design/changelog/2026-07-10-canvas-edits-now-reject-malformed-html-before-it-can-corrupt.md +6 -0
  348. package/corpus/templates/design/changelog/2026-07-10-complex-designs-now-export-as-valid-secure-svgs-and-crisp-ra.md +6 -0
  349. package/corpus/templates/design/changelog/2026-07-10-complex-figma-masks-arcs-rich-text-transformed-images-and-ad.md +6 -0
  350. package/corpus/templates/design/changelog/2026-07-10-copied-layers-paste-across-designs-and-browser-tabs.md +6 -0
  351. package/corpus/templates/design/changelog/2026-07-10-copy-and-download-editable-figma-svg.md +6 -0
  352. package/corpus/templates/design/changelog/2026-07-10-copying-design-text-now-pastes-readable-text-into-other-apps.md +6 -0
  353. package/corpus/templates/design/changelog/2026-07-10-deleted-screens-can-be-restored-with-undo-and-removed-again-.md +6 -0
  354. package/corpus/templates/design/changelog/2026-07-10-design-changes-now-save-before-switching-apps-and-retry-when.md +6 -0
  355. package/corpus/templates/design/changelog/2026-07-10-design-stays-usable-on-phones-by-keeping-editor-panels-and-f.md +6 -0
  356. package/corpus/templates/design/changelog/2026-07-10-download-all-screens-as-one-multi-page-pdf-from-the-overview.md +6 -0
  357. package/corpus/templates/design/changelog/2026-07-10-duplicated-layers-now-keep-labels-aria-relationships-fragmen.md +6 -0
  358. package/corpus/templates/design/changelog/2026-07-10-fig-import-results-stay-compact.md +6 -0
  359. package/corpus/templates/design/changelog/2026-07-10-figma-imports-now-load-real-fonts-fix-rotated-gradient-dashe.md +6 -0
  360. package/corpus/templates/design/changelog/2026-07-10-figma-links-in-chat-and-the-import-tab-now-offer-secure-one-.md +6 -0
  361. package/corpus/templates/design/changelog/2026-07-10-fixed-cmd-z-not-restoring-content-after-an-agent-driven-desi.md +6 -0
  362. package/corpus/templates/design/changelog/2026-07-10-fixed-download-pdf-being-unreachable-from-the-export-panel-e.md +6 -0
  363. package/corpus/templates/design/changelog/2026-07-10-fixed-dragging-a-layer-out-of-an-auto-layout-row-column-no-l.md +6 -0
  364. package/corpus/templates/design/changelog/2026-07-10-fixed-figma-svg-export-text-wrapping-sizing-and-inner-layer.md +6 -0
  365. package/corpus/templates/design/changelog/2026-07-10-fixed-hiding-or-locking-one-layer-no-longer-hides-or-blocks-.md +6 -0
  366. package/corpus/templates/design/changelog/2026-07-10-fixed-png-screenshots-of-tall-screens-being-cropped-to-one-v.md +6 -0
  367. package/corpus/templates/design/changelog/2026-07-10-fixed-png-svg-exports-capturing-broken-layout-when-webfonts-.md +6 -0
  368. package/corpus/templates/design/changelog/2026-07-10-frame-tool-now-offers-standard-ad-unit-size-presets-medium-r.md +6 -0
  369. package/corpus/templates/design/changelog/2026-07-10-full-view-controls-stay-within-their-frame-instead-of-coveri.md +6 -0
  370. package/corpus/templates/design/changelog/2026-07-10-hover-focus-focus-visible-pressed-and-disabled-states-now-pr.md +6 -0
  371. package/corpus/templates/design/changelog/2026-07-10-layer-drops-now-land-in-the-intended-grid-row-stay-visually-.md +6 -0
  372. package/corpus/templates/design/changelog/2026-07-10-local-code-workspaces-now-keep-unsaved-edits-across-panel-sw.md +6 -0
  373. package/corpus/templates/design/changelog/2026-07-10-local-visual-editing-now-keeps-authenticated-sessions-shared.md +6 -0
  374. package/corpus/templates/design/changelog/2026-07-10-long-running-agent-work-no-longer-shows-a-premature-stuck-wa.md +6 -0
  375. package/corpus/templates/design/changelog/2026-07-10-managed-figma-connections-are-recognized-automatically.md +6 -0
  376. package/corpus/templates/design/changelog/2026-07-10-new-designs-can-open-directly-in-the-editor-without-a-pr.md +6 -0
  377. package/corpus/templates/design/changelog/2026-07-10-new-screens-are-selected-and-revealed-immediately.md +6 -0
  378. package/corpus/templates/design/changelog/2026-07-10-new-text-layers-undo-as-one-safe-creation.md +6 -0
  379. package/corpus/templates/design/changelog/2026-07-10-preview-and-apply-inferred-auto-layout-without-changing-yo.md +5 -0
  380. package/corpus/templates/design/changelog/2026-07-10-print-pdf-exports-and-paper-size-presets-letter-a4-now-match.md +6 -0
  381. package/corpus/templates/design/changelog/2026-07-10-responsive-frame-editing.md +6 -0
  382. package/corpus/templates/design/changelog/2026-07-10-reusable-design-templates.md +6 -0
  383. package/corpus/templates/design/changelog/2026-07-10-screen-overview-frames-now-use-a-clearer-interact-action-wit.md +6 -0
  384. package/corpus/templates/design/changelog/2026-07-10-start-designs-from-source-linked-material-3-carbon-or-primer.md +6 -0
  385. package/corpus/templates/design/changelog/2026-07-10-tweaks-guidance.md +6 -0
  386. package/corpus/templates/design/changelog/2026-07-10-uploaded-fig-files-can-now-become-editable-design-screens-wi.md +6 -0
  387. package/corpus/templates/design/e2e/helpers.ts +3 -3
  388. package/corpus/templates/design/package.json +2 -0
  389. package/corpus/templates/design/scripts/qa-figma-stress-import.ts +96 -0
  390. package/corpus/templates/design/server/db/index.ts +10 -0
  391. package/corpus/templates/design/server/db/schema.ts +44 -0
  392. package/corpus/templates/design/server/handlers/import-design-file.ts +114 -80
  393. package/corpus/templates/design/server/handlers/index-design-system-with-builder.ts +19 -6
  394. package/corpus/templates/design/server/lib/design-export.ts +240 -3
  395. package/corpus/templates/design/server/lib/design-template-data.ts +89 -0
  396. package/corpus/templates/design/server/lib/design-to-figma-svg.ts +250 -26
  397. package/corpus/templates/design/server/lib/fig-file-decoder.ts +839 -0
  398. package/corpus/templates/design/server/lib/fig-file-import.ts +287 -0
  399. package/corpus/templates/design/server/lib/fig-file-limits.ts +3 -0
  400. package/corpus/templates/design/server/lib/fig-file-to-html.ts +2568 -0
  401. package/corpus/templates/design/server/lib/figma-design-context.ts +359 -0
  402. package/corpus/templates/design/server/lib/figma-node-import.ts +478 -22
  403. package/corpus/templates/design/server/lib/figma-node-to-html.ts +554 -29
  404. package/corpus/templates/design/server/lib/local-figma-qa-upload.ts +112 -0
  405. package/corpus/templates/design/server/lib/verify-write-grant.ts +16 -2
  406. package/corpus/templates/design/server/lib/visible-clipboard-html.ts +13 -3
  407. package/corpus/templates/design/server/plugins/agent-chat.ts +7 -0
  408. package/corpus/templates/design/server/plugins/db.ts +42 -0
  409. package/corpus/templates/design/server/plugins/local-figma-qa-upload.ts +7 -0
  410. package/corpus/templates/design/server/register-secrets.ts +8 -8
  411. package/corpus/templates/design/server/routes/api/qa-figma-import-assets/[assetId].get.ts +46 -0
  412. package/corpus/templates/design/server/source-workspace.ts +104 -12
  413. package/corpus/templates/design/shared/code-layer.ts +105 -28
  414. package/corpus/templates/design/shared/design-system-templates.ts +301 -0
  415. package/corpus/templates/design/shared/design-template-presets.ts +195 -0
  416. package/corpus/templates/design/shared/figma-url.ts +8 -0
  417. package/corpus/templates/design/shared/html-integrity.ts +306 -0
  418. package/corpus/templates/design/shared/interaction-states.ts +318 -23
  419. package/corpus/templates/design/shared/locked-layers.ts +151 -0
  420. package/corpus/templates/dispatch/.agents/skills/capture-learnings/SKILL.md +22 -9
  421. package/corpus/templates/dispatch/app/i18n/zh-TW.ts +48 -0
  422. package/corpus/templates/dispatch/app/i18n-data.ts +536 -1
  423. package/corpus/templates/dispatch/changelog/2026-07-10-connect-slack-workspaces-with-oauth-and-manage-channel-ident.md +6 -0
  424. package/corpus/templates/dispatch/changelog/2026-07-10-microsoft-teams-bots-and-discord-slash-commands-can-now-conn.md +6 -0
  425. package/corpus/templates/dispatch/changelog/2026-07-10-slack-and-telegram-now-route-uptime-monitor-requests-to-anal.md +6 -0
  426. package/corpus/templates/forms/.agents/skills/capture-learnings/SKILL.md +22 -9
  427. package/corpus/templates/forms/.agents/skills/form-publishing/SKILL.md +7 -0
  428. package/corpus/templates/forms/AGENTS.md +4 -0
  429. package/corpus/templates/forms/actions/create-form.ts +44 -7
  430. package/corpus/templates/forms/actions/lib/assert-publishable-form.ts +38 -0
  431. package/corpus/templates/forms/actions/patch-form-fields.ts +4 -0
  432. package/corpus/templates/forms/actions/update-form.ts +2 -36
  433. package/corpus/templates/forms/app/i18n/ar-SA.ts +3 -0
  434. package/corpus/templates/forms/app/i18n/de-DE.ts +3 -0
  435. package/corpus/templates/forms/app/i18n/en-US.ts +3 -0
  436. package/corpus/templates/forms/app/i18n/es-ES.ts +3 -0
  437. package/corpus/templates/forms/app/i18n/fr-FR.ts +3 -0
  438. package/corpus/templates/forms/app/i18n/hi-IN.ts +3 -0
  439. package/corpus/templates/forms/app/i18n/ja-JP.ts +3 -0
  440. package/corpus/templates/forms/app/i18n/ko-KR.ts +3 -0
  441. package/corpus/templates/forms/app/i18n/pt-BR.ts +3 -0
  442. package/corpus/templates/forms/app/i18n/zh-CN.ts +2 -0
  443. package/corpus/templates/forms/app/i18n/zh-TW.ts +3 -0
  444. package/corpus/templates/forms/app/pages/FormBuilderPage.tsx +17 -0
  445. package/corpus/templates/forms/changelog/2026-07-10-agent-created-published-forms-now-return-the-anonymous-publi.md +6 -0
  446. package/corpus/templates/forms/changelog/2026-07-10-published-forms-can-no-longer-be-edited-into-an-unusable-emp.md +6 -0
  447. package/corpus/templates/forms/server/handlers/submissions.ts +4 -3
  448. package/corpus/templates/forms/server/plugins/agent-chat.ts +1 -0
  449. package/corpus/templates/forms/shared/types.ts +5 -0
  450. package/corpus/templates/mail/.agents/skills/capture-learnings/SKILL.md +22 -9
  451. package/corpus/templates/mail/app/components/layout/AppLayout.tsx +2 -2
  452. package/corpus/templates/mail/changelog/2026-07-10-mail-navigation-now-uses-a-clean-borderless-drawer.md +6 -0
  453. package/corpus/templates/plan/.agents/skills/capture-learnings/SKILL.md +22 -9
  454. package/corpus/templates/plan/app/lib/plan-local-bridge.ts +4 -1
  455. package/corpus/templates/plan/changelog/2026-07-10-local-plans-now-keep-valid-content-visible-when-one-generate.md +6 -0
  456. package/corpus/templates/plan/server/lib/local-plan-files.ts +4 -1
  457. package/corpus/templates/slides/.agents/skills/capture-learnings/SKILL.md +22 -9
  458. package/dist/a2a/artifact-response.d.ts.map +1 -1
  459. package/dist/a2a/artifact-response.js +88 -2
  460. package/dist/a2a/artifact-response.js.map +1 -1
  461. package/dist/a2a/client.d.ts +9 -0
  462. package/dist/a2a/client.d.ts.map +1 -1
  463. package/dist/a2a/client.js +1 -0
  464. package/dist/a2a/client.js.map +1 -1
  465. package/dist/a2a/handlers.d.ts.map +1 -1
  466. package/dist/a2a/handlers.js +24 -69
  467. package/dist/a2a/handlers.js.map +1 -1
  468. package/dist/a2a/types.d.ts +2 -0
  469. package/dist/a2a/types.d.ts.map +1 -1
  470. package/dist/a2a/types.js.map +1 -1
  471. package/dist/agent/durable-background.d.ts +11 -0
  472. package/dist/agent/durable-background.d.ts.map +1 -1
  473. package/dist/agent/durable-background.js +17 -0
  474. package/dist/agent/durable-background.js.map +1 -1
  475. package/dist/agent/production-agent.d.ts +2 -2
  476. package/dist/agent/production-agent.d.ts.map +1 -1
  477. package/dist/agent/production-agent.js +15 -5
  478. package/dist/agent/production-agent.js.map +1 -1
  479. package/dist/agent/run-manager.d.ts +44 -2
  480. package/dist/agent/run-manager.d.ts.map +1 -1
  481. package/dist/agent/run-manager.js +90 -9
  482. package/dist/agent/run-manager.js.map +1 -1
  483. package/dist/agent/run-store.d.ts +109 -0
  484. package/dist/agent/run-store.d.ts.map +1 -1
  485. package/dist/agent/run-store.js +206 -15
  486. package/dist/agent/run-store.js.map +1 -1
  487. package/dist/agent/types.d.ts +22 -0
  488. package/dist/agent/types.d.ts.map +1 -1
  489. package/dist/agent/types.js.map +1 -1
  490. package/dist/audit/record.d.ts.map +1 -1
  491. package/dist/audit/record.js +29 -0
  492. package/dist/audit/record.js.map +1 -1
  493. package/dist/audit/store.d.ts.map +1 -1
  494. package/dist/audit/store.js +62 -3
  495. package/dist/audit/store.js.map +1 -1
  496. package/dist/audit/types.d.ts +13 -0
  497. package/dist/audit/types.d.ts.map +1 -1
  498. package/dist/audit/types.js.map +1 -1
  499. package/dist/automation/index.d.ts +193 -0
  500. package/dist/automation/index.d.ts.map +1 -0
  501. package/dist/automation/index.js +464 -0
  502. package/dist/automation/index.js.map +1 -0
  503. package/dist/cli/create.d.ts.map +1 -1
  504. package/dist/cli/create.js +10 -3
  505. package/dist/cli/create.js.map +1 -1
  506. package/dist/cli/design-connect.d.ts.map +1 -1
  507. package/dist/cli/design-connect.js +492 -35
  508. package/dist/cli/design-connect.js.map +1 -1
  509. package/dist/client/AgentPanel.d.ts +7 -1
  510. package/dist/client/AgentPanel.d.ts.map +1 -1
  511. package/dist/client/AgentPanel.js +32 -8
  512. package/dist/client/AgentPanel.js.map +1 -1
  513. package/dist/client/AssistantChat.d.ts +15 -0
  514. package/dist/client/AssistantChat.d.ts.map +1 -1
  515. package/dist/client/AssistantChat.js +115 -47
  516. package/dist/client/AssistantChat.js.map +1 -1
  517. package/dist/client/MultiTabAssistantChat.d.ts.map +1 -1
  518. package/dist/client/MultiTabAssistantChat.js +1 -1
  519. package/dist/client/MultiTabAssistantChat.js.map +1 -1
  520. package/dist/client/RunStuckBanner.d.ts +14 -1
  521. package/dist/client/RunStuckBanner.d.ts.map +1 -1
  522. package/dist/client/RunStuckBanner.js +35 -7
  523. package/dist/client/RunStuckBanner.js.map +1 -1
  524. package/dist/client/agent-chat-adapter.d.ts +4 -1
  525. package/dist/client/agent-chat-adapter.d.ts.map +1 -1
  526. package/dist/client/agent-chat-adapter.js +49 -4
  527. package/dist/client/agent-chat-adapter.js.map +1 -1
  528. package/dist/client/automation.d.ts +14 -0
  529. package/dist/client/automation.d.ts.map +1 -0
  530. package/dist/client/automation.js +9 -0
  531. package/dist/client/automation.js.map +1 -0
  532. package/dist/client/chat/run-recovery.d.ts +4 -0
  533. package/dist/client/chat/run-recovery.d.ts.map +1 -1
  534. package/dist/client/chat/run-recovery.js +12 -10
  535. package/dist/client/chat/run-recovery.js.map +1 -1
  536. package/dist/client/composer/TiptapComposer.d.ts.map +1 -1
  537. package/dist/client/composer/TiptapComposer.js +8 -0
  538. package/dist/client/composer/TiptapComposer.js.map +1 -1
  539. package/dist/client/index.d.ts +2 -0
  540. package/dist/client/index.d.ts.map +1 -1
  541. package/dist/client/index.js +2 -0
  542. package/dist/client/index.js.map +1 -1
  543. package/dist/client/integrations/api.d.ts +115 -0
  544. package/dist/client/integrations/api.d.ts.map +1 -0
  545. package/dist/client/integrations/api.js +123 -0
  546. package/dist/client/integrations/api.js.map +1 -0
  547. package/dist/client/integrations/index.d.ts +1 -0
  548. package/dist/client/integrations/index.d.ts.map +1 -1
  549. package/dist/client/integrations/index.js +1 -0
  550. package/dist/client/integrations/index.js.map +1 -1
  551. package/dist/client/transcription/use-live-transcription.d.ts.map +1 -1
  552. package/dist/client/transcription/use-live-transcription.js +59 -5
  553. package/dist/client/transcription/use-live-transcription.js.map +1 -1
  554. package/dist/client/use-run-stuck-detection.d.ts +16 -1
  555. package/dist/client/use-run-stuck-detection.d.ts.map +1 -1
  556. package/dist/client/use-run-stuck-detection.js +23 -4
  557. package/dist/client/use-run-stuck-detection.js.map +1 -1
  558. package/dist/collab/struct-routes.d.ts +1 -1
  559. package/dist/deploy/build.d.ts.map +1 -1
  560. package/dist/deploy/build.js +49 -4
  561. package/dist/deploy/build.js.map +1 -1
  562. package/dist/deploy/workspace-deploy.d.ts.map +1 -1
  563. package/dist/deploy/workspace-deploy.js +31 -2
  564. package/dist/deploy/workspace-deploy.js.map +1 -1
  565. package/dist/file-upload/types.d.ts +2 -0
  566. package/dist/file-upload/types.d.ts.map +1 -1
  567. package/dist/file-upload/types.js.map +1 -1
  568. package/dist/index.d.ts +2 -0
  569. package/dist/index.d.ts.map +1 -1
  570. package/dist/index.js +2 -0
  571. package/dist/index.js.map +1 -1
  572. package/dist/integrations/a2a-continuations-store.d.ts.map +1 -1
  573. package/dist/integrations/a2a-continuations-store.js +6 -4
  574. package/dist/integrations/a2a-continuations-store.js.map +1 -1
  575. package/dist/integrations/adapters/discord.d.ts +3 -0
  576. package/dist/integrations/adapters/discord.d.ts.map +1 -0
  577. package/dist/integrations/adapters/discord.js +261 -0
  578. package/dist/integrations/adapters/discord.js.map +1 -0
  579. package/dist/integrations/adapters/index.d.ts +4 -0
  580. package/dist/integrations/adapters/index.d.ts.map +1 -0
  581. package/dist/integrations/adapters/index.js +26 -0
  582. package/dist/integrations/adapters/index.js.map +1 -0
  583. package/dist/integrations/adapters/microsoft-teams.d.ts +5 -0
  584. package/dist/integrations/adapters/microsoft-teams.d.ts.map +1 -0
  585. package/dist/integrations/adapters/microsoft-teams.js +295 -0
  586. package/dist/integrations/adapters/microsoft-teams.js.map +1 -0
  587. package/dist/integrations/adapters/slack.d.ts +8 -2
  588. package/dist/integrations/adapters/slack.d.ts.map +1 -1
  589. package/dist/integrations/adapters/slack.js +736 -27
  590. package/dist/integrations/adapters/slack.js.map +1 -1
  591. package/dist/integrations/adapters/telegram.d.ts +0 -2
  592. package/dist/integrations/adapters/telegram.d.ts.map +1 -1
  593. package/dist/integrations/adapters/telegram.js +49 -15
  594. package/dist/integrations/adapters/telegram.js.map +1 -1
  595. package/dist/integrations/adapters/whatsapp.d.ts +0 -2
  596. package/dist/integrations/adapters/whatsapp.d.ts.map +1 -1
  597. package/dist/integrations/adapters/whatsapp.js +40 -17
  598. package/dist/integrations/adapters/whatsapp.js.map +1 -1
  599. package/dist/integrations/catalog.d.ts +75 -0
  600. package/dist/integrations/catalog.d.ts.map +1 -0
  601. package/dist/integrations/catalog.js +451 -0
  602. package/dist/integrations/catalog.js.map +1 -0
  603. package/dist/integrations/controls-store.d.ts +44 -0
  604. package/dist/integrations/controls-store.d.ts.map +1 -0
  605. package/dist/integrations/controls-store.js +129 -0
  606. package/dist/integrations/controls-store.js.map +1 -0
  607. package/dist/integrations/index.d.ts +13 -1
  608. package/dist/integrations/index.d.ts.map +1 -1
  609. package/dist/integrations/index.js +9 -0
  610. package/dist/integrations/index.js.map +1 -1
  611. package/dist/integrations/installations-store.d.ts +112 -0
  612. package/dist/integrations/installations-store.d.ts.map +1 -0
  613. package/dist/integrations/installations-store.js +493 -0
  614. package/dist/integrations/installations-store.js.map +1 -0
  615. package/dist/integrations/integration-memory.d.ts +24 -0
  616. package/dist/integrations/integration-memory.d.ts.map +1 -0
  617. package/dist/integrations/integration-memory.js +136 -0
  618. package/dist/integrations/integration-memory.js.map +1 -0
  619. package/dist/integrations/pending-tasks-retry-job.d.ts.map +1 -1
  620. package/dist/integrations/pending-tasks-retry-job.js +6 -5
  621. package/dist/integrations/pending-tasks-retry-job.js.map +1 -1
  622. package/dist/integrations/pending-tasks-store.d.ts +17 -0
  623. package/dist/integrations/pending-tasks-store.d.ts.map +1 -1
  624. package/dist/integrations/pending-tasks-store.js +71 -5
  625. package/dist/integrations/pending-tasks-store.js.map +1 -1
  626. package/dist/integrations/plugin.d.ts.map +1 -1
  627. package/dist/integrations/plugin.js +520 -35
  628. package/dist/integrations/plugin.js.map +1 -1
  629. package/dist/integrations/scope-store.d.ts +65 -0
  630. package/dist/integrations/scope-store.d.ts.map +1 -0
  631. package/dist/integrations/scope-store.js +361 -0
  632. package/dist/integrations/scope-store.js.map +1 -0
  633. package/dist/integrations/slack-manifest.d.ts +66 -0
  634. package/dist/integrations/slack-manifest.d.ts.map +1 -0
  635. package/dist/integrations/slack-manifest.js +70 -0
  636. package/dist/integrations/slack-manifest.js.map +1 -0
  637. package/dist/integrations/slack-oauth.d.ts +99 -0
  638. package/dist/integrations/slack-oauth.d.ts.map +1 -0
  639. package/dist/integrations/slack-oauth.js +226 -0
  640. package/dist/integrations/slack-oauth.js.map +1 -0
  641. package/dist/integrations/types.d.ts +144 -0
  642. package/dist/integrations/types.d.ts.map +1 -1
  643. package/dist/integrations/types.js +16 -1
  644. package/dist/integrations/types.js.map +1 -1
  645. package/dist/integrations/usage-budget-store.d.ts +84 -0
  646. package/dist/integrations/usage-budget-store.d.ts.map +1 -0
  647. package/dist/integrations/usage-budget-store.js +650 -0
  648. package/dist/integrations/usage-budget-store.js.map +1 -0
  649. package/dist/integrations/webhook-handler.d.ts +4 -0
  650. package/dist/integrations/webhook-handler.d.ts.map +1 -1
  651. package/dist/integrations/webhook-handler.js +415 -47
  652. package/dist/integrations/webhook-handler.js.map +1 -1
  653. package/dist/jobs/scheduler.d.ts +6 -0
  654. package/dist/jobs/scheduler.d.ts.map +1 -1
  655. package/dist/jobs/scheduler.js +83 -4
  656. package/dist/jobs/scheduler.js.map +1 -1
  657. package/dist/jobs/tools.d.ts.map +1 -1
  658. package/dist/jobs/tools.js +43 -11
  659. package/dist/jobs/tools.js.map +1 -1
  660. package/dist/observability/routes.d.ts +5 -5
  661. package/dist/progress/routes.d.ts +1 -1
  662. package/dist/provider-api/index.d.ts +4 -4
  663. package/dist/provider-api/index.d.ts.map +1 -1
  664. package/dist/provider-api/index.js +72 -1
  665. package/dist/provider-api/index.js.map +1 -1
  666. package/dist/resources/handlers.d.ts +3 -3
  667. package/dist/resources/handlers.d.ts.map +1 -1
  668. package/dist/resources/handlers.js +57 -15
  669. package/dist/resources/handlers.js.map +1 -1
  670. package/dist/resources/script-helpers.d.ts.map +1 -1
  671. package/dist/resources/script-helpers.js +34 -8
  672. package/dist/resources/script-helpers.js.map +1 -1
  673. package/dist/resources/store.d.ts +10 -0
  674. package/dist/resources/store.d.ts.map +1 -1
  675. package/dist/resources/store.js +54 -47
  676. package/dist/resources/store.js.map +1 -1
  677. package/dist/scripts/call-agent.d.ts.map +1 -1
  678. package/dist/scripts/call-agent.js +106 -1
  679. package/dist/scripts/call-agent.js.map +1 -1
  680. package/dist/server/agent-chat-plugin.d.ts +15 -4
  681. package/dist/server/agent-chat-plugin.d.ts.map +1 -1
  682. package/dist/server/agent-chat-plugin.js +248 -113
  683. package/dist/server/agent-chat-plugin.js.map +1 -1
  684. package/dist/server/auth.d.ts.map +1 -1
  685. package/dist/server/auth.js +10 -14
  686. package/dist/server/auth.js.map +1 -1
  687. package/dist/server/builder-design-systems.d.ts +3 -1
  688. package/dist/server/builder-design-systems.d.ts.map +1 -1
  689. package/dist/server/builder-design-systems.js +9 -2
  690. package/dist/server/builder-design-systems.js.map +1 -1
  691. package/dist/server/edge.d.ts +1 -1
  692. package/dist/server/edge.d.ts.map +1 -1
  693. package/dist/server/edge.js +1 -1
  694. package/dist/server/edge.js.map +1 -1
  695. package/dist/server/index.d.ts +2 -1
  696. package/dist/server/index.d.ts.map +1 -1
  697. package/dist/server/index.js +2 -1
  698. package/dist/server/index.js.map +1 -1
  699. package/dist/server/request-context.d.ts +18 -0
  700. package/dist/server/request-context.d.ts.map +1 -1
  701. package/dist/server/request-context.js.map +1 -1
  702. package/dist/server/social-og-image.d.ts.map +1 -1
  703. package/dist/server/social-og-image.js +3 -2
  704. package/dist/server/social-og-image.js.map +1 -1
  705. package/dist/server/transcribe-voice.d.ts +1 -1
  706. package/dist/styles/agent-native.css +62 -44
  707. package/dist/templates/default/.agents/skills/capture-learnings/SKILL.md +22 -9
  708. package/dist/templates/default/AGENTS.md +7 -3
  709. package/dist/templates/workspace-core/.agents/skills/authentication/SKILL.md +1 -1
  710. package/dist/templates/workspace-core/.agents/skills/capture-learnings/SKILL.md +22 -9
  711. package/dist/templates/workspace-core/.agents/skills/extension-points/SKILL.md +6 -3
  712. package/dist/templates/workspace-core/.agents/skills/extensions/SKILL.md +25 -0
  713. package/dist/templates/workspace-core/.agents/skills/integration-webhooks/SKILL.md +15 -0
  714. package/dist/templates/workspace-core/AGENTS.md +3 -2
  715. package/dist/usage/store.d.ts +7 -0
  716. package/dist/usage/store.d.ts.map +1 -1
  717. package/dist/usage/store.js +24 -3
  718. package/dist/usage/store.js.map +1 -1
  719. package/docs/content/automation-connectors.mdx +80 -0
  720. package/docs/content/extensions.mdx +8 -0
  721. package/docs/content/locales/ar-SA/extensions.mdx +8 -0
  722. package/docs/content/locales/ar-SA/messaging.mdx +84 -15
  723. package/docs/content/locales/ar-SA/template-clips.mdx +1 -0
  724. package/docs/content/locales/ar-SA/template-design.mdx +1 -0
  725. package/docs/content/locales/de-DE/extensions.mdx +10 -0
  726. package/docs/content/locales/de-DE/messaging.mdx +92 -15
  727. package/docs/content/locales/de-DE/template-clips.mdx +1 -0
  728. package/docs/content/locales/de-DE/template-design.mdx +1 -0
  729. package/docs/content/locales/es-ES/extensions.mdx +10 -0
  730. package/docs/content/locales/es-ES/messaging.mdx +91 -15
  731. package/docs/content/locales/es-ES/template-clips.mdx +1 -0
  732. package/docs/content/locales/es-ES/template-design.mdx +1 -0
  733. package/docs/content/locales/fr-FR/extensions.mdx +10 -0
  734. package/docs/content/locales/fr-FR/messaging.mdx +91 -15
  735. package/docs/content/locales/fr-FR/template-clips.mdx +1 -0
  736. package/docs/content/locales/fr-FR/template-design.mdx +1 -0
  737. package/docs/content/locales/hi-IN/extensions.mdx +8 -0
  738. package/docs/content/locales/hi-IN/messaging.mdx +81 -15
  739. package/docs/content/locales/hi-IN/template-clips.mdx +1 -0
  740. package/docs/content/locales/hi-IN/template-design.mdx +1 -0
  741. package/docs/content/locales/ja-JP/extensions.mdx +9 -0
  742. package/docs/content/locales/ja-JP/messaging.mdx +81 -15
  743. package/docs/content/locales/ja-JP/template-clips.mdx +1 -0
  744. package/docs/content/locales/ja-JP/template-design.mdx +1 -0
  745. package/docs/content/locales/ko-KR/extensions.mdx +8 -0
  746. package/docs/content/locales/ko-KR/messaging.mdx +80 -15
  747. package/docs/content/locales/ko-KR/template-clips.mdx +1 -0
  748. package/docs/content/locales/ko-KR/template-design.mdx +1 -0
  749. package/docs/content/locales/pt-BR/extensions.mdx +9 -0
  750. package/docs/content/locales/pt-BR/messaging.mdx +88 -15
  751. package/docs/content/locales/pt-BR/template-clips.mdx +1 -0
  752. package/docs/content/locales/pt-BR/template-design.mdx +1 -0
  753. package/docs/content/locales/zh-CN/extensions.mdx +6 -0
  754. package/docs/content/locales/zh-CN/messaging.mdx +78 -15
  755. package/docs/content/locales/zh-CN/template-clips.mdx +1 -0
  756. package/docs/content/locales/zh-CN/template-design.mdx +1 -0
  757. package/docs/content/locales/zh-TW/extensions.mdx +6 -0
  758. package/docs/content/locales/zh-TW/messaging.mdx +78 -15
  759. package/docs/content/locales/zh-TW/template-clips.mdx +1 -0
  760. package/docs/content/locales/zh-TW/template-design.mdx +1 -0
  761. package/docs/content/messaging.mdx +227 -45
  762. package/docs/content/template-clips.mdx +3 -0
  763. package/docs/content/template-design.mdx +4 -0
  764. package/package.json +5 -1
  765. package/src/templates/default/.agents/skills/capture-learnings/SKILL.md +22 -9
  766. package/src/templates/default/AGENTS.md +7 -3
  767. package/src/templates/workspace-core/.agents/skills/authentication/SKILL.md +1 -1
  768. package/src/templates/workspace-core/.agents/skills/capture-learnings/SKILL.md +22 -9
  769. package/src/templates/workspace-core/.agents/skills/extension-points/SKILL.md +6 -3
  770. package/src/templates/workspace-core/.agents/skills/extensions/SKILL.md +25 -0
  771. package/src/templates/workspace-core/.agents/skills/integration-webhooks/SKILL.md +15 -0
  772. package/src/templates/workspace-core/AGENTS.md +3 -2
@@ -0,0 +1,493 @@
1
+ /**
2
+ * Durable metadata and encrypted credentials for managed messaging installs.
3
+ *
4
+ * The installation row deliberately contains only provider metadata and an
5
+ * opaque `app_secrets` key. OAuth access and refresh tokens are serialized as
6
+ * one bundle and encrypted by the framework secrets vault. List/read helpers
7
+ * never expose the secret key or token values.
8
+ */
9
+ import { createHash, randomUUID } from "node:crypto";
10
+ import { getDbExec, intType, isPostgres, isUniqueViolation, retryOnDdlRace, } from "../db/client.js";
11
+ import { ensureIndexExists, ensureTableExists } from "../db/ddl-guard.js";
12
+ import { deleteAppSecret, readAppSecret, writeAppSecret, } from "../secrets/storage.js";
13
+ const TABLE = "integration_installations";
14
+ let _initPromise;
15
+ function createSql() {
16
+ const integer = intType();
17
+ return `CREATE TABLE IF NOT EXISTS ${TABLE} (
18
+ id TEXT PRIMARY KEY,
19
+ platform TEXT NOT NULL,
20
+ installation_key TEXT NOT NULL,
21
+ team_id TEXT,
22
+ team_name TEXT,
23
+ enterprise_id TEXT,
24
+ enterprise_name TEXT,
25
+ is_enterprise_install ${integer} NOT NULL DEFAULT 0,
26
+ api_app_id TEXT,
27
+ bot_user_id TEXT,
28
+ scopes_json TEXT NOT NULL DEFAULT '[]',
29
+ installed_by_external_user_id TEXT,
30
+ owner_email TEXT NOT NULL,
31
+ org_id TEXT,
32
+ token_secret_key TEXT NOT NULL,
33
+ secret_scope TEXT NOT NULL,
34
+ secret_scope_id TEXT NOT NULL,
35
+ status TEXT NOT NULL DEFAULT 'connected',
36
+ health TEXT NOT NULL DEFAULT 'unknown',
37
+ last_error TEXT,
38
+ health_checked_at ${integer},
39
+ last_healthy_at ${integer},
40
+ token_expires_at ${integer},
41
+ created_at ${integer} NOT NULL,
42
+ updated_at ${integer} NOT NULL,
43
+ disconnected_at ${integer}
44
+ )`;
45
+ }
46
+ const INDEXES = [
47
+ [
48
+ "idx_integration_installations_key",
49
+ `CREATE UNIQUE INDEX IF NOT EXISTS idx_integration_installations_key ON ${TABLE}(platform, installation_key)`,
50
+ ],
51
+ [
52
+ "idx_integration_installations_team",
53
+ `CREATE INDEX IF NOT EXISTS idx_integration_installations_team ON ${TABLE}(platform, team_id, status)`,
54
+ ],
55
+ [
56
+ "idx_integration_installations_owner",
57
+ `CREATE INDEX IF NOT EXISTS idx_integration_installations_owner ON ${TABLE}(owner_email, updated_at)`,
58
+ ],
59
+ [
60
+ "idx_integration_installations_org",
61
+ `CREATE INDEX IF NOT EXISTS idx_integration_installations_org ON ${TABLE}(org_id, updated_at)`,
62
+ ],
63
+ ];
64
+ async function ensureTable() {
65
+ if (!_initPromise) {
66
+ _initPromise = (async () => {
67
+ const client = getDbExec();
68
+ const ddl = createSql();
69
+ if (isPostgres()) {
70
+ await ensureTableExists(TABLE, ddl);
71
+ for (const [name, sql] of INDEXES) {
72
+ await ensureIndexExists(name, sql);
73
+ }
74
+ return;
75
+ }
76
+ await retryOnDdlRace(() => client.execute(ddl));
77
+ for (const [, sql] of INDEXES) {
78
+ await retryOnDdlRace(() => client.execute(sql));
79
+ }
80
+ })().catch((error) => {
81
+ _initPromise = undefined;
82
+ throw error;
83
+ });
84
+ }
85
+ return _initPromise;
86
+ }
87
+ function required(value, name) {
88
+ const normalized = value.trim();
89
+ if (!normalized)
90
+ throw new Error(`${name} is required`);
91
+ if (normalized.length > 512)
92
+ throw new Error(`${name} is too long`);
93
+ return normalized;
94
+ }
95
+ function normalizePlatform(value) {
96
+ return required(value, "platform").toLowerCase();
97
+ }
98
+ function normalizeEmail(value) {
99
+ return required(value, "ownerEmail").toLowerCase();
100
+ }
101
+ function normalizeScopes(scopes) {
102
+ return Array.from(new Set((scopes ?? [])
103
+ .map((scope) => scope.trim())
104
+ .filter(Boolean)
105
+ .sort()));
106
+ }
107
+ function parseScopes(value) {
108
+ if (typeof value !== "string")
109
+ return [];
110
+ try {
111
+ const parsed = JSON.parse(value);
112
+ return Array.isArray(parsed) &&
113
+ parsed.every((item) => typeof item === "string")
114
+ ? parsed
115
+ : [];
116
+ }
117
+ catch {
118
+ return [];
119
+ }
120
+ }
121
+ function toBoolean(value) {
122
+ return value === true || value === 1 || value === "1" || value === "true";
123
+ }
124
+ function nullableNumber(value) {
125
+ return value == null ? null : Number(value);
126
+ }
127
+ function rowToRaw(row) {
128
+ return {
129
+ id: String(row.id),
130
+ platform: String(row.platform),
131
+ installationKey: String(row.installation_key),
132
+ teamId: row.team_id ?? null,
133
+ teamName: row.team_name ?? null,
134
+ enterpriseId: row.enterprise_id ?? null,
135
+ enterpriseName: row.enterprise_name ?? null,
136
+ isEnterpriseInstall: toBoolean(row.is_enterprise_install),
137
+ apiAppId: row.api_app_id ?? null,
138
+ botUserId: row.bot_user_id ?? null,
139
+ scopes: parseScopes(row.scopes_json),
140
+ installedByExternalUserId: row.installed_by_external_user_id ?? null,
141
+ ownerEmail: String(row.owner_email),
142
+ orgId: row.org_id ?? null,
143
+ tokenSecretKey: String(row.token_secret_key),
144
+ secretScope: row.secret_scope,
145
+ secretScopeId: String(row.secret_scope_id),
146
+ status: row.status,
147
+ health: row.health,
148
+ lastError: row.last_error ?? null,
149
+ healthCheckedAt: nullableNumber(row.health_checked_at),
150
+ lastHealthyAt: nullableNumber(row.last_healthy_at),
151
+ tokenExpiresAt: nullableNumber(row.token_expires_at),
152
+ createdAt: Number(row.created_at ?? 0),
153
+ updatedAt: Number(row.updated_at ?? 0),
154
+ disconnectedAt: nullableNumber(row.disconnected_at),
155
+ };
156
+ }
157
+ function toSafeInstallation(row) {
158
+ const { tokenSecretKey: _tokenSecretKey, secretScope: _scope, secretScopeId: _scopeId, ...safe } = row;
159
+ return safe;
160
+ }
161
+ function tokenSecretKey(platform, installationKey) {
162
+ const digest = createHash("sha256")
163
+ .update(`${platform}\0${installationKey}`)
164
+ .digest("hex")
165
+ .slice(0, 32);
166
+ return `integration:${platform}:${digest}:oauth-token-bundle`;
167
+ }
168
+ function sameOwner(a, b) {
169
+ return a.trim().toLowerCase() === b.trim().toLowerCase();
170
+ }
171
+ function sameScope(row, ownerEmail, orgId) {
172
+ if (row.orgId || orgId)
173
+ return !!row.orgId && row.orgId === orgId;
174
+ return sameOwner(row.ownerEmail, ownerEmail);
175
+ }
176
+ function canMutate(row, actor) {
177
+ if (row.orgId) {
178
+ return actor.orgId === row.orgId && actor.isOrgAdmin === true;
179
+ }
180
+ return sameOwner(row.ownerEmail, actor.userEmail);
181
+ }
182
+ async function selectRawById(id) {
183
+ await ensureTable();
184
+ const { rows } = await getDbExec().execute({
185
+ sql: `SELECT * FROM ${TABLE} WHERE id = ? LIMIT 1`,
186
+ args: [id],
187
+ });
188
+ return rows[0] ? rowToRaw(rows[0]) : null;
189
+ }
190
+ async function selectRawByKey(platform, installationKey) {
191
+ await ensureTable();
192
+ const { rows } = await getDbExec().execute({
193
+ sql: `SELECT * FROM ${TABLE} WHERE platform = ? AND installation_key = ? LIMIT 1`,
194
+ args: [
195
+ normalizePlatform(platform),
196
+ required(installationKey, "installationKey"),
197
+ ],
198
+ });
199
+ return rows[0] ? rowToRaw(rows[0]) : null;
200
+ }
201
+ /**
202
+ * Create or refresh a managed install. Re-installs may rotate tokens inside
203
+ * the same owner/org scope, but cannot silently move an existing provider
204
+ * installation into another Agent Native tenant.
205
+ */
206
+ export async function upsertIntegrationInstallation(input) {
207
+ await ensureTable();
208
+ const platform = normalizePlatform(input.platform);
209
+ const installationKey = required(input.installationKey, "installationKey");
210
+ const ownerEmail = normalizeEmail(input.ownerEmail);
211
+ const orgId = input.orgId?.trim() || null;
212
+ const secretScopeId = required(input.secretScopeId, "secretScopeId");
213
+ const accessToken = input.tokenBundle.accessToken?.trim();
214
+ if (!accessToken)
215
+ throw new Error("tokenBundle.accessToken is required");
216
+ const existing = await selectRawByKey(platform, installationKey);
217
+ if (existing && !sameScope(existing, ownerEmail, orgId)) {
218
+ throw new Error("This provider installation is already connected to another owner or organization.");
219
+ }
220
+ const secretKey = existing?.tokenSecretKey ?? tokenSecretKey(platform, installationKey);
221
+ const persistTokenBundle = (key) => writeAppSecret({
222
+ key,
223
+ value: JSON.stringify(input.tokenBundle),
224
+ scope: input.secretScope,
225
+ scopeId: secretScopeId,
226
+ description: `${platform} OAuth token bundle for a managed installation`,
227
+ });
228
+ await persistTokenBundle(secretKey);
229
+ const now = Date.now();
230
+ let id = existing?.id ?? randomUUID();
231
+ const scopesJson = JSON.stringify(normalizeScopes(input.scopes));
232
+ const tokenExpiresAt = input.tokenExpiresAt ?? input.tokenBundle.expiresAt ?? null;
233
+ const updateExisting = async (rowId, rowSecretKey) => {
234
+ await getDbExec().execute({
235
+ sql: `UPDATE ${TABLE} SET
236
+ team_id = ?, team_name = ?, enterprise_id = ?, enterprise_name = ?,
237
+ is_enterprise_install = ?, api_app_id = ?, bot_user_id = ?, scopes_json = ?,
238
+ installed_by_external_user_id = ?, owner_email = ?, org_id = ?,
239
+ token_secret_key = ?, secret_scope = ?, secret_scope_id = ?, status = ?,
240
+ health = ?, last_error = ?, health_checked_at = ?, last_healthy_at = ?,
241
+ token_expires_at = ?, updated_at = ?, disconnected_at = ?
242
+ WHERE id = ?`,
243
+ args: [
244
+ input.teamId ?? null,
245
+ input.teamName ?? null,
246
+ input.enterpriseId ?? null,
247
+ input.enterpriseName ?? null,
248
+ input.isEnterpriseInstall ? 1 : 0,
249
+ input.apiAppId ?? null,
250
+ input.botUserId ?? null,
251
+ scopesJson,
252
+ input.installedByExternalUserId ?? null,
253
+ ownerEmail,
254
+ orgId,
255
+ rowSecretKey,
256
+ input.secretScope,
257
+ secretScopeId,
258
+ input.status ?? "connected",
259
+ input.health ?? "unknown",
260
+ input.lastError ?? null,
261
+ input.healthCheckedAt ?? null,
262
+ input.lastHealthyAt ?? null,
263
+ tokenExpiresAt,
264
+ now,
265
+ null,
266
+ rowId,
267
+ ],
268
+ });
269
+ };
270
+ if (existing) {
271
+ await updateExisting(existing.id, existing.tokenSecretKey);
272
+ }
273
+ else {
274
+ try {
275
+ await getDbExec().execute({
276
+ sql: `INSERT INTO ${TABLE} (
277
+ id, platform, installation_key, team_id, team_name, enterprise_id,
278
+ enterprise_name, is_enterprise_install, api_app_id, bot_user_id,
279
+ scopes_json, installed_by_external_user_id, owner_email, org_id,
280
+ token_secret_key, secret_scope, secret_scope_id, status, health,
281
+ last_error, health_checked_at, last_healthy_at, token_expires_at,
282
+ created_at, updated_at, disconnected_at
283
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
284
+ args: [
285
+ id,
286
+ platform,
287
+ installationKey,
288
+ input.teamId ?? null,
289
+ input.teamName ?? null,
290
+ input.enterpriseId ?? null,
291
+ input.enterpriseName ?? null,
292
+ input.isEnterpriseInstall ? 1 : 0,
293
+ input.apiAppId ?? null,
294
+ input.botUserId ?? null,
295
+ scopesJson,
296
+ input.installedByExternalUserId ?? null,
297
+ ownerEmail,
298
+ orgId,
299
+ secretKey,
300
+ input.secretScope,
301
+ secretScopeId,
302
+ input.status ?? "connected",
303
+ input.health ?? "unknown",
304
+ input.lastError ?? null,
305
+ input.healthCheckedAt ?? null,
306
+ input.lastHealthyAt ?? null,
307
+ tokenExpiresAt,
308
+ now,
309
+ now,
310
+ null,
311
+ ],
312
+ });
313
+ }
314
+ catch (error) {
315
+ if (!isUniqueViolation(error))
316
+ throw error;
317
+ const raced = await selectRawByKey(platform, installationKey);
318
+ if (!raced)
319
+ throw error;
320
+ if (!sameScope(raced, ownerEmail, orgId)) {
321
+ throw new Error("This provider installation is already connected to another owner or organization.");
322
+ }
323
+ id = raced.id;
324
+ if (raced.tokenSecretKey !== secretKey) {
325
+ await persistTokenBundle(raced.tokenSecretKey);
326
+ }
327
+ await updateExisting(raced.id, raced.tokenSecretKey);
328
+ }
329
+ }
330
+ const stored = await selectRawById(id);
331
+ if (!stored)
332
+ throw new Error("Managed installation was not persisted");
333
+ return toSafeInstallation(stored);
334
+ }
335
+ /** List installations visible to the owner or active organization member. */
336
+ export async function listIntegrationInstallations(actor, platform) {
337
+ await ensureTable();
338
+ const ownerEmail = normalizeEmail(actor.userEmail);
339
+ const args = [ownerEmail];
340
+ let visibility = "owner_email = ?";
341
+ if (actor.orgId) {
342
+ visibility = `(owner_email = ? OR org_id = ?)`;
343
+ args.push(actor.orgId);
344
+ }
345
+ let platformFilter = "";
346
+ if (platform) {
347
+ platformFilter = " AND platform = ?";
348
+ args.push(normalizePlatform(platform));
349
+ }
350
+ const { rows } = await getDbExec().execute({
351
+ sql: `SELECT * FROM ${TABLE} WHERE ${visibility}${platformFilter} ORDER BY updated_at DESC`,
352
+ args,
353
+ });
354
+ return rows.map((row) => toSafeInstallation(rowToRaw(row)));
355
+ }
356
+ /** Read one installation through owner/org visibility scoping. */
357
+ export async function getIntegrationInstallation(id, actor) {
358
+ const row = await selectRawById(id);
359
+ if (!row)
360
+ return null;
361
+ if (!sameOwner(row.ownerEmail, actor.userEmail) &&
362
+ (!row.orgId || row.orgId !== actor.orgId)) {
363
+ return null;
364
+ }
365
+ return toSafeInstallation(row);
366
+ }
367
+ /** Update non-secret installation metadata after an owner/admin access check. */
368
+ export async function updateIntegrationInstallation(id, actor, patch) {
369
+ const row = await selectRawById(id);
370
+ if (!row)
371
+ return null;
372
+ if (!canMutate(row, actor)) {
373
+ throw new Error("You do not have access to update this installation.");
374
+ }
375
+ const next = {
376
+ teamName: patch.teamName === undefined ? row.teamName : patch.teamName,
377
+ enterpriseName: patch.enterpriseName === undefined
378
+ ? row.enterpriseName
379
+ : patch.enterpriseName,
380
+ botUserId: patch.botUserId === undefined ? row.botUserId : patch.botUserId,
381
+ scopes: patch.scopes === undefined ? row.scopes : normalizeScopes(patch.scopes),
382
+ status: patch.status ?? row.status,
383
+ health: patch.health ?? row.health,
384
+ lastError: patch.lastError === undefined ? row.lastError : patch.lastError,
385
+ healthCheckedAt: patch.healthCheckedAt === undefined
386
+ ? row.healthCheckedAt
387
+ : patch.healthCheckedAt,
388
+ lastHealthyAt: patch.lastHealthyAt === undefined
389
+ ? row.lastHealthyAt
390
+ : patch.lastHealthyAt,
391
+ tokenExpiresAt: patch.tokenExpiresAt === undefined
392
+ ? row.tokenExpiresAt
393
+ : patch.tokenExpiresAt,
394
+ };
395
+ await getDbExec().execute({
396
+ sql: `UPDATE ${TABLE} SET team_name = ?, enterprise_name = ?, bot_user_id = ?,
397
+ scopes_json = ?, status = ?, health = ?, last_error = ?, health_checked_at = ?,
398
+ last_healthy_at = ?, token_expires_at = ?, updated_at = ? WHERE id = ?`,
399
+ args: [
400
+ next.teamName,
401
+ next.enterpriseName,
402
+ next.botUserId,
403
+ JSON.stringify(next.scopes),
404
+ next.status,
405
+ next.health,
406
+ next.lastError,
407
+ next.healthCheckedAt,
408
+ next.lastHealthyAt,
409
+ next.tokenExpiresAt,
410
+ Date.now(),
411
+ id,
412
+ ],
413
+ });
414
+ const updated = await selectRawById(id);
415
+ return updated ? toSafeInstallation(updated) : null;
416
+ }
417
+ /** Delete the encrypted token bundle and retain disconnected audit metadata. */
418
+ export async function disconnectIntegrationInstallation(id, actor) {
419
+ const row = await selectRawById(id);
420
+ if (!row)
421
+ return null;
422
+ if (!canMutate(row, actor)) {
423
+ throw new Error("You do not have access to disconnect this installation.");
424
+ }
425
+ await deleteAppSecret({
426
+ key: row.tokenSecretKey,
427
+ scope: row.secretScope,
428
+ scopeId: row.secretScopeId,
429
+ });
430
+ const now = Date.now();
431
+ await getDbExec().execute({
432
+ sql: `UPDATE ${TABLE} SET status = 'disconnected', health = 'unknown',
433
+ last_error = NULL, token_expires_at = NULL, disconnected_at = ?, updated_at = ?
434
+ WHERE id = ?`,
435
+ args: [now, now, id],
436
+ });
437
+ const updated = await selectRawById(id);
438
+ return updated ? toSafeInstallation(updated) : null;
439
+ }
440
+ /**
441
+ * Resolve credentials for a verified provider webhook/runtime path.
442
+ *
443
+ * This is intentionally separate from every user-facing list/read helper.
444
+ * Callers must first authenticate the provider webhook (or run inside a
445
+ * trusted OAuth callback) and must never log or return the result.
446
+ */
447
+ export async function resolveIntegrationTokenBundle(platform, installationKey) {
448
+ const row = await selectRawByKey(platform, installationKey);
449
+ if (!row || row.status !== "connected" || row.health === "revoked")
450
+ return null;
451
+ const secret = await readAppSecret({
452
+ key: row.tokenSecretKey,
453
+ scope: row.secretScope,
454
+ scopeId: row.secretScopeId,
455
+ });
456
+ if (!secret)
457
+ return null;
458
+ try {
459
+ const parsed = JSON.parse(secret.value);
460
+ if (typeof parsed.accessToken !== "string" || !parsed.accessToken)
461
+ return null;
462
+ return parsed;
463
+ }
464
+ catch {
465
+ return null;
466
+ }
467
+ }
468
+ /** Safe metadata lookup for a verified provider event. */
469
+ export async function getActiveIntegrationInstallationByKey(platform, installationKey) {
470
+ const row = await selectRawByKey(platform, installationKey);
471
+ if (!row || row.status !== "connected")
472
+ return null;
473
+ return toSafeInstallation(row);
474
+ }
475
+ /** Resolve a connected installation by workspace or enterprise tenant id. */
476
+ export async function getActiveIntegrationInstallationForTenant(platform, tenantId) {
477
+ await ensureTable();
478
+ const { rows } = await getDbExec().execute({
479
+ sql: `SELECT * FROM ${TABLE}
480
+ WHERE platform = ? AND (team_id = ? OR enterprise_id = ?)
481
+ AND status = 'connected'
482
+ ORDER BY updated_at DESC LIMIT 1`,
483
+ args: [
484
+ normalizePlatform(platform),
485
+ required(tenantId, "tenantId"),
486
+ required(tenantId, "tenantId"),
487
+ ],
488
+ });
489
+ return rows[0]
490
+ ? toSafeInstallation(rowToRaw(rows[0]))
491
+ : null;
492
+ }
493
+ //# sourceMappingURL=installations-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"installations-store.js","sourceRoot":"","sources":["../../src/integrations/installations-store.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Durable metadata and encrypted credentials for managed messaging installs.\n *\n * The installation row deliberately contains only provider metadata and an\n * opaque `app_secrets` key. OAuth access and refresh tokens are serialized as\n * one bundle and encrypted by the framework secrets vault. List/read helpers\n * never expose the secret key or token values.\n */\n\nimport { createHash, randomUUID } from \"node:crypto\";\n\nimport {\n getDbExec,\n intType,\n isPostgres,\n isUniqueViolation,\n retryOnDdlRace,\n} from \"../db/client.js\";\nimport { ensureIndexExists, ensureTableExists } from \"../db/ddl-guard.js\";\nimport type { SecretScope } from \"../secrets/register.js\";\nimport {\n deleteAppSecret,\n readAppSecret,\n writeAppSecret,\n} from \"../secrets/storage.js\";\n\nconst TABLE = \"integration_installations\";\nlet _initPromise: Promise<void> | undefined;\n\nexport type IntegrationInstallationStatus =\n | \"connected\"\n | \"disconnected\"\n | \"revoked\"\n | \"error\";\n\nexport type IntegrationInstallationHealth =\n | \"unknown\"\n | \"healthy\"\n | \"degraded\"\n | \"revoked\";\n\nexport interface IntegrationTokenBundle {\n accessToken: string;\n refreshToken?: string;\n tokenType?: string;\n expiresAt?: number;\n}\n\n/** Safe-to-return installation metadata. No secret reference or token value. */\nexport interface IntegrationInstallation {\n id: string;\n platform: string;\n installationKey: string;\n teamId: string | null;\n teamName: string | null;\n enterpriseId: string | null;\n enterpriseName: string | null;\n isEnterpriseInstall: boolean;\n apiAppId: string | null;\n botUserId: string | null;\n scopes: string[];\n installedByExternalUserId: string | null;\n ownerEmail: string;\n orgId: string | null;\n status: IntegrationInstallationStatus;\n health: IntegrationInstallationHealth;\n lastError: string | null;\n healthCheckedAt: number | null;\n lastHealthyAt: number | null;\n tokenExpiresAt: number | null;\n createdAt: number;\n updatedAt: number;\n disconnectedAt: number | null;\n}\n\ninterface RawInstallation extends IntegrationInstallation {\n tokenSecretKey: string;\n secretScope: SecretScope;\n secretScopeId: string;\n}\n\nexport interface InstallationActor {\n userEmail: string;\n orgId?: string | null;\n /** Must come from a verified active organization membership. */\n isOrgAdmin?: boolean;\n}\n\nexport interface UpsertIntegrationInstallationInput {\n platform: string;\n installationKey: string;\n teamId?: string | null;\n teamName?: string | null;\n enterpriseId?: string | null;\n enterpriseName?: string | null;\n isEnterpriseInstall?: boolean;\n apiAppId?: string | null;\n botUserId?: string | null;\n scopes?: readonly string[];\n installedByExternalUserId?: string | null;\n ownerEmail: string;\n orgId?: string | null;\n secretScope: SecretScope;\n secretScopeId: string;\n tokenBundle: IntegrationTokenBundle;\n status?: IntegrationInstallationStatus;\n health?: IntegrationInstallationHealth;\n lastError?: string | null;\n healthCheckedAt?: number | null;\n lastHealthyAt?: number | null;\n tokenExpiresAt?: number | null;\n}\n\nexport interface IntegrationInstallationUpdate {\n teamName?: string | null;\n enterpriseName?: string | null;\n botUserId?: string | null;\n scopes?: readonly string[];\n status?: IntegrationInstallationStatus;\n health?: IntegrationInstallationHealth;\n lastError?: string | null;\n healthCheckedAt?: number | null;\n lastHealthyAt?: number | null;\n tokenExpiresAt?: number | null;\n}\n\nfunction createSql(): string {\n const integer = intType();\n return `CREATE TABLE IF NOT EXISTS ${TABLE} (\n id TEXT PRIMARY KEY,\n platform TEXT NOT NULL,\n installation_key TEXT NOT NULL,\n team_id TEXT,\n team_name TEXT,\n enterprise_id TEXT,\n enterprise_name TEXT,\n is_enterprise_install ${integer} NOT NULL DEFAULT 0,\n api_app_id TEXT,\n bot_user_id TEXT,\n scopes_json TEXT NOT NULL DEFAULT '[]',\n installed_by_external_user_id TEXT,\n owner_email TEXT NOT NULL,\n org_id TEXT,\n token_secret_key TEXT NOT NULL,\n secret_scope TEXT NOT NULL,\n secret_scope_id TEXT NOT NULL,\n status TEXT NOT NULL DEFAULT 'connected',\n health TEXT NOT NULL DEFAULT 'unknown',\n last_error TEXT,\n health_checked_at ${integer},\n last_healthy_at ${integer},\n token_expires_at ${integer},\n created_at ${integer} NOT NULL,\n updated_at ${integer} NOT NULL,\n disconnected_at ${integer}\n )`;\n}\n\nconst INDEXES = [\n [\n \"idx_integration_installations_key\",\n `CREATE UNIQUE INDEX IF NOT EXISTS idx_integration_installations_key ON ${TABLE}(platform, installation_key)`,\n ],\n [\n \"idx_integration_installations_team\",\n `CREATE INDEX IF NOT EXISTS idx_integration_installations_team ON ${TABLE}(platform, team_id, status)`,\n ],\n [\n \"idx_integration_installations_owner\",\n `CREATE INDEX IF NOT EXISTS idx_integration_installations_owner ON ${TABLE}(owner_email, updated_at)`,\n ],\n [\n \"idx_integration_installations_org\",\n `CREATE INDEX IF NOT EXISTS idx_integration_installations_org ON ${TABLE}(org_id, updated_at)`,\n ],\n] as const;\n\nasync function ensureTable(): Promise<void> {\n if (!_initPromise) {\n _initPromise = (async () => {\n const client = getDbExec();\n const ddl = createSql();\n if (isPostgres()) {\n await ensureTableExists(TABLE, ddl);\n for (const [name, sql] of INDEXES) {\n await ensureIndexExists(name, sql);\n }\n return;\n }\n await retryOnDdlRace(() => client.execute(ddl));\n for (const [, sql] of INDEXES) {\n await retryOnDdlRace(() => client.execute(sql));\n }\n })().catch((error) => {\n _initPromise = undefined;\n throw error;\n });\n }\n return _initPromise;\n}\n\nfunction required(value: string, name: string): string {\n const normalized = value.trim();\n if (!normalized) throw new Error(`${name} is required`);\n if (normalized.length > 512) throw new Error(`${name} is too long`);\n return normalized;\n}\n\nfunction normalizePlatform(value: string): string {\n return required(value, \"platform\").toLowerCase();\n}\n\nfunction normalizeEmail(value: string): string {\n return required(value, \"ownerEmail\").toLowerCase();\n}\n\nfunction normalizeScopes(scopes: readonly string[] | undefined): string[] {\n return Array.from(\n new Set(\n (scopes ?? [])\n .map((scope) => scope.trim())\n .filter(Boolean)\n .sort(),\n ),\n );\n}\n\nfunction parseScopes(value: unknown): string[] {\n if (typeof value !== \"string\") return [];\n try {\n const parsed: unknown = JSON.parse(value);\n return Array.isArray(parsed) &&\n parsed.every((item) => typeof item === \"string\")\n ? parsed\n : [];\n } catch {\n return [];\n }\n}\n\nfunction toBoolean(value: unknown): boolean {\n return value === true || value === 1 || value === \"1\" || value === \"true\";\n}\n\nfunction nullableNumber(value: unknown): number | null {\n return value == null ? null : Number(value);\n}\n\nfunction rowToRaw(row: Record<string, unknown>): RawInstallation {\n return {\n id: String(row.id),\n platform: String(row.platform),\n installationKey: String(row.installation_key),\n teamId: (row.team_id as string | null) ?? null,\n teamName: (row.team_name as string | null) ?? null,\n enterpriseId: (row.enterprise_id as string | null) ?? null,\n enterpriseName: (row.enterprise_name as string | null) ?? null,\n isEnterpriseInstall: toBoolean(row.is_enterprise_install),\n apiAppId: (row.api_app_id as string | null) ?? null,\n botUserId: (row.bot_user_id as string | null) ?? null,\n scopes: parseScopes(row.scopes_json),\n installedByExternalUserId:\n (row.installed_by_external_user_id as string | null) ?? null,\n ownerEmail: String(row.owner_email),\n orgId: (row.org_id as string | null) ?? null,\n tokenSecretKey: String(row.token_secret_key),\n secretScope: row.secret_scope as SecretScope,\n secretScopeId: String(row.secret_scope_id),\n status: row.status as IntegrationInstallationStatus,\n health: row.health as IntegrationInstallationHealth,\n lastError: (row.last_error as string | null) ?? null,\n healthCheckedAt: nullableNumber(row.health_checked_at),\n lastHealthyAt: nullableNumber(row.last_healthy_at),\n tokenExpiresAt: nullableNumber(row.token_expires_at),\n createdAt: Number(row.created_at ?? 0),\n updatedAt: Number(row.updated_at ?? 0),\n disconnectedAt: nullableNumber(row.disconnected_at),\n };\n}\n\nfunction toSafeInstallation(row: RawInstallation): IntegrationInstallation {\n const {\n tokenSecretKey: _tokenSecretKey,\n secretScope: _scope,\n secretScopeId: _scopeId,\n ...safe\n } = row;\n return safe;\n}\n\nfunction tokenSecretKey(platform: string, installationKey: string): string {\n const digest = createHash(\"sha256\")\n .update(`${platform}\\0${installationKey}`)\n .digest(\"hex\")\n .slice(0, 32);\n return `integration:${platform}:${digest}:oauth-token-bundle`;\n}\n\nfunction sameOwner(a: string, b: string): boolean {\n return a.trim().toLowerCase() === b.trim().toLowerCase();\n}\n\nfunction sameScope(\n row: Pick<RawInstallation, \"ownerEmail\" | \"orgId\">,\n ownerEmail: string,\n orgId: string | null,\n): boolean {\n if (row.orgId || orgId) return !!row.orgId && row.orgId === orgId;\n return sameOwner(row.ownerEmail, ownerEmail);\n}\n\nfunction canMutate(row: RawInstallation, actor: InstallationActor): boolean {\n if (row.orgId) {\n return actor.orgId === row.orgId && actor.isOrgAdmin === true;\n }\n return sameOwner(row.ownerEmail, actor.userEmail);\n}\n\nasync function selectRawById(id: string): Promise<RawInstallation | null> {\n await ensureTable();\n const { rows } = await getDbExec().execute({\n sql: `SELECT * FROM ${TABLE} WHERE id = ? LIMIT 1`,\n args: [id],\n });\n return rows[0] ? rowToRaw(rows[0] as Record<string, unknown>) : null;\n}\n\nasync function selectRawByKey(\n platform: string,\n installationKey: string,\n): Promise<RawInstallation | null> {\n await ensureTable();\n const { rows } = await getDbExec().execute({\n sql: `SELECT * FROM ${TABLE} WHERE platform = ? AND installation_key = ? LIMIT 1`,\n args: [\n normalizePlatform(platform),\n required(installationKey, \"installationKey\"),\n ],\n });\n return rows[0] ? rowToRaw(rows[0] as Record<string, unknown>) : null;\n}\n\n/**\n * Create or refresh a managed install. Re-installs may rotate tokens inside\n * the same owner/org scope, but cannot silently move an existing provider\n * installation into another Agent Native tenant.\n */\nexport async function upsertIntegrationInstallation(\n input: UpsertIntegrationInstallationInput,\n): Promise<IntegrationInstallation> {\n await ensureTable();\n const platform = normalizePlatform(input.platform);\n const installationKey = required(input.installationKey, \"installationKey\");\n const ownerEmail = normalizeEmail(input.ownerEmail);\n const orgId = input.orgId?.trim() || null;\n const secretScopeId = required(input.secretScopeId, \"secretScopeId\");\n const accessToken = input.tokenBundle.accessToken?.trim();\n if (!accessToken) throw new Error(\"tokenBundle.accessToken is required\");\n\n const existing = await selectRawByKey(platform, installationKey);\n if (existing && !sameScope(existing, ownerEmail, orgId)) {\n throw new Error(\n \"This provider installation is already connected to another owner or organization.\",\n );\n }\n\n const secretKey =\n existing?.tokenSecretKey ?? tokenSecretKey(platform, installationKey);\n const persistTokenBundle = (key: string) =>\n writeAppSecret({\n key,\n value: JSON.stringify(input.tokenBundle),\n scope: input.secretScope,\n scopeId: secretScopeId,\n description: `${platform} OAuth token bundle for a managed installation`,\n });\n await persistTokenBundle(secretKey);\n\n const now = Date.now();\n let id = existing?.id ?? randomUUID();\n const scopesJson = JSON.stringify(normalizeScopes(input.scopes));\n const tokenExpiresAt =\n input.tokenExpiresAt ?? input.tokenBundle.expiresAt ?? null;\n\n const updateExisting = async (rowId: string, rowSecretKey: string) => {\n await getDbExec().execute({\n sql: `UPDATE ${TABLE} SET\n team_id = ?, team_name = ?, enterprise_id = ?, enterprise_name = ?,\n is_enterprise_install = ?, api_app_id = ?, bot_user_id = ?, scopes_json = ?,\n installed_by_external_user_id = ?, owner_email = ?, org_id = ?,\n token_secret_key = ?, secret_scope = ?, secret_scope_id = ?, status = ?,\n health = ?, last_error = ?, health_checked_at = ?, last_healthy_at = ?,\n token_expires_at = ?, updated_at = ?, disconnected_at = ?\n WHERE id = ?`,\n args: [\n input.teamId ?? null,\n input.teamName ?? null,\n input.enterpriseId ?? null,\n input.enterpriseName ?? null,\n input.isEnterpriseInstall ? 1 : 0,\n input.apiAppId ?? null,\n input.botUserId ?? null,\n scopesJson,\n input.installedByExternalUserId ?? null,\n ownerEmail,\n orgId,\n rowSecretKey,\n input.secretScope,\n secretScopeId,\n input.status ?? \"connected\",\n input.health ?? \"unknown\",\n input.lastError ?? null,\n input.healthCheckedAt ?? null,\n input.lastHealthyAt ?? null,\n tokenExpiresAt,\n now,\n null,\n rowId,\n ],\n });\n };\n\n if (existing) {\n await updateExisting(existing.id, existing.tokenSecretKey);\n } else {\n try {\n await getDbExec().execute({\n sql: `INSERT INTO ${TABLE} (\n id, platform, installation_key, team_id, team_name, enterprise_id,\n enterprise_name, is_enterprise_install, api_app_id, bot_user_id,\n scopes_json, installed_by_external_user_id, owner_email, org_id,\n token_secret_key, secret_scope, secret_scope_id, status, health,\n last_error, health_checked_at, last_healthy_at, token_expires_at,\n created_at, updated_at, disconnected_at\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n args: [\n id,\n platform,\n installationKey,\n input.teamId ?? null,\n input.teamName ?? null,\n input.enterpriseId ?? null,\n input.enterpriseName ?? null,\n input.isEnterpriseInstall ? 1 : 0,\n input.apiAppId ?? null,\n input.botUserId ?? null,\n scopesJson,\n input.installedByExternalUserId ?? null,\n ownerEmail,\n orgId,\n secretKey,\n input.secretScope,\n secretScopeId,\n input.status ?? \"connected\",\n input.health ?? \"unknown\",\n input.lastError ?? null,\n input.healthCheckedAt ?? null,\n input.lastHealthyAt ?? null,\n tokenExpiresAt,\n now,\n now,\n null,\n ],\n });\n } catch (error) {\n if (!isUniqueViolation(error)) throw error;\n\n const raced = await selectRawByKey(platform, installationKey);\n if (!raced) throw error;\n if (!sameScope(raced, ownerEmail, orgId)) {\n throw new Error(\n \"This provider installation is already connected to another owner or organization.\",\n );\n }\n\n id = raced.id;\n if (raced.tokenSecretKey !== secretKey) {\n await persistTokenBundle(raced.tokenSecretKey);\n }\n await updateExisting(raced.id, raced.tokenSecretKey);\n }\n }\n\n const stored = await selectRawById(id);\n if (!stored) throw new Error(\"Managed installation was not persisted\");\n return toSafeInstallation(stored);\n}\n\n/** List installations visible to the owner or active organization member. */\nexport async function listIntegrationInstallations(\n actor: InstallationActor,\n platform?: string,\n): Promise<IntegrationInstallation[]> {\n await ensureTable();\n const ownerEmail = normalizeEmail(actor.userEmail);\n const args: unknown[] = [ownerEmail];\n let visibility = \"owner_email = ?\";\n if (actor.orgId) {\n visibility = `(owner_email = ? OR org_id = ?)`;\n args.push(actor.orgId);\n }\n let platformFilter = \"\";\n if (platform) {\n platformFilter = \" AND platform = ?\";\n args.push(normalizePlatform(platform));\n }\n const { rows } = await getDbExec().execute({\n sql: `SELECT * FROM ${TABLE} WHERE ${visibility}${platformFilter} ORDER BY updated_at DESC`,\n args,\n });\n return rows.map((row) =>\n toSafeInstallation(rowToRaw(row as Record<string, unknown>)),\n );\n}\n\n/** Read one installation through owner/org visibility scoping. */\nexport async function getIntegrationInstallation(\n id: string,\n actor: InstallationActor,\n): Promise<IntegrationInstallation | null> {\n const row = await selectRawById(id);\n if (!row) return null;\n if (\n !sameOwner(row.ownerEmail, actor.userEmail) &&\n (!row.orgId || row.orgId !== actor.orgId)\n ) {\n return null;\n }\n return toSafeInstallation(row);\n}\n\n/** Update non-secret installation metadata after an owner/admin access check. */\nexport async function updateIntegrationInstallation(\n id: string,\n actor: InstallationActor,\n patch: IntegrationInstallationUpdate,\n): Promise<IntegrationInstallation | null> {\n const row = await selectRawById(id);\n if (!row) return null;\n if (!canMutate(row, actor)) {\n throw new Error(\"You do not have access to update this installation.\");\n }\n const next = {\n teamName: patch.teamName === undefined ? row.teamName : patch.teamName,\n enterpriseName:\n patch.enterpriseName === undefined\n ? row.enterpriseName\n : patch.enterpriseName,\n botUserId: patch.botUserId === undefined ? row.botUserId : patch.botUserId,\n scopes:\n patch.scopes === undefined ? row.scopes : normalizeScopes(patch.scopes),\n status: patch.status ?? row.status,\n health: patch.health ?? row.health,\n lastError: patch.lastError === undefined ? row.lastError : patch.lastError,\n healthCheckedAt:\n patch.healthCheckedAt === undefined\n ? row.healthCheckedAt\n : patch.healthCheckedAt,\n lastHealthyAt:\n patch.lastHealthyAt === undefined\n ? row.lastHealthyAt\n : patch.lastHealthyAt,\n tokenExpiresAt:\n patch.tokenExpiresAt === undefined\n ? row.tokenExpiresAt\n : patch.tokenExpiresAt,\n };\n await getDbExec().execute({\n sql: `UPDATE ${TABLE} SET team_name = ?, enterprise_name = ?, bot_user_id = ?,\n scopes_json = ?, status = ?, health = ?, last_error = ?, health_checked_at = ?,\n last_healthy_at = ?, token_expires_at = ?, updated_at = ? WHERE id = ?`,\n args: [\n next.teamName,\n next.enterpriseName,\n next.botUserId,\n JSON.stringify(next.scopes),\n next.status,\n next.health,\n next.lastError,\n next.healthCheckedAt,\n next.lastHealthyAt,\n next.tokenExpiresAt,\n Date.now(),\n id,\n ],\n });\n const updated = await selectRawById(id);\n return updated ? toSafeInstallation(updated) : null;\n}\n\n/** Delete the encrypted token bundle and retain disconnected audit metadata. */\nexport async function disconnectIntegrationInstallation(\n id: string,\n actor: InstallationActor,\n): Promise<IntegrationInstallation | null> {\n const row = await selectRawById(id);\n if (!row) return null;\n if (!canMutate(row, actor)) {\n throw new Error(\"You do not have access to disconnect this installation.\");\n }\n await deleteAppSecret({\n key: row.tokenSecretKey,\n scope: row.secretScope,\n scopeId: row.secretScopeId,\n });\n const now = Date.now();\n await getDbExec().execute({\n sql: `UPDATE ${TABLE} SET status = 'disconnected', health = 'unknown',\n last_error = NULL, token_expires_at = NULL, disconnected_at = ?, updated_at = ?\n WHERE id = ?`,\n args: [now, now, id],\n });\n const updated = await selectRawById(id);\n return updated ? toSafeInstallation(updated) : null;\n}\n\n/**\n * Resolve credentials for a verified provider webhook/runtime path.\n *\n * This is intentionally separate from every user-facing list/read helper.\n * Callers must first authenticate the provider webhook (or run inside a\n * trusted OAuth callback) and must never log or return the result.\n */\nexport async function resolveIntegrationTokenBundle(\n platform: string,\n installationKey: string,\n): Promise<IntegrationTokenBundle | null> {\n const row = await selectRawByKey(platform, installationKey);\n if (!row || row.status !== \"connected\" || row.health === \"revoked\")\n return null;\n const secret = await readAppSecret({\n key: row.tokenSecretKey,\n scope: row.secretScope,\n scopeId: row.secretScopeId,\n });\n if (!secret) return null;\n try {\n const parsed = JSON.parse(secret.value) as Partial<IntegrationTokenBundle>;\n if (typeof parsed.accessToken !== \"string\" || !parsed.accessToken)\n return null;\n return parsed as IntegrationTokenBundle;\n } catch {\n return null;\n }\n}\n\n/** Safe metadata lookup for a verified provider event. */\nexport async function getActiveIntegrationInstallationByKey(\n platform: string,\n installationKey: string,\n): Promise<IntegrationInstallation | null> {\n const row = await selectRawByKey(platform, installationKey);\n if (!row || row.status !== \"connected\") return null;\n return toSafeInstallation(row);\n}\n\n/** Resolve a connected installation by workspace or enterprise tenant id. */\nexport async function getActiveIntegrationInstallationForTenant(\n platform: string,\n tenantId: string,\n): Promise<IntegrationInstallation | null> {\n await ensureTable();\n const { rows } = await getDbExec().execute({\n sql: `SELECT * FROM ${TABLE}\n WHERE platform = ? AND (team_id = ? OR enterprise_id = ?)\n AND status = 'connected'\n ORDER BY updated_at DESC LIMIT 1`,\n args: [\n normalizePlatform(platform),\n required(tenantId, \"tenantId\"),\n required(tenantId, \"tenantId\"),\n ],\n });\n return rows[0]\n ? toSafeInstallation(rowToRaw(rows[0] as Record<string, unknown>))\n : null;\n}\n"]}
@@ -0,0 +1,24 @@
1
+ import type { ActionEntry } from "../agent/production-agent.js";
2
+ export declare function listIntegrationMemory(scopeId?: string): Promise<{
3
+ name: string;
4
+ path: string;
5
+ updatedAt: number;
6
+ size: number;
7
+ }[]>;
8
+ export declare function rememberForIntegrationScope(input: {
9
+ name: string;
10
+ description: string;
11
+ content: string;
12
+ }, scopeId?: string): Promise<{
13
+ name: string;
14
+ description: string;
15
+ }>;
16
+ export declare function forgetIntegrationMemory(input: {
17
+ name: string;
18
+ }, scopeId?: string): Promise<{
19
+ name: string;
20
+ deleted: boolean;
21
+ }>;
22
+ export declare function loadIntegrationMemoryPrompt(scopeId: string | undefined): Promise<string>;
23
+ export declare function integrationMemoryActions(): Record<string, ActionEntry>;
24
+ //# sourceMappingURL=integration-memory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"integration-memory.d.ts","sourceRoot":"","sources":["../../src/integrations/integration-memory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AA6ChE,wBAAsB,qBAAqB,CAAC,OAAO,SAAmB;;;;;KAWrE;AAED,wBAAsB,2BAA2B,CAC/C,KAAK,EAAE;IACL,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;CACjB,EACD,OAAO,SAAmB,GACzB,OAAO,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,CAAC,CAyBhD;AAED,wBAAsB,uBAAuB,CAC3C,KAAK,EAAE;IACL,IAAI,EAAE,MAAM,CAAC;CACd,EACD,OAAO,SAAmB,GACzB,OAAO,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CAAC,CAc7C;AAED,wBAAsB,2BAA2B,CAC/C,OAAO,EAAE,MAAM,GAAG,SAAS,GAC1B,OAAO,CAAC,MAAM,CAAC,CAkBjB;AAED,wBAAgB,wBAAwB,IAAI,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAmDtE"}