@agent-native/core 0.117.2 → 0.118.1

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 (776) hide show
  1. package/corpus/README.md +3 -3
  2. package/corpus/core/CHANGELOG.md +51 -0
  3. package/corpus/core/docs/content/custom-design-system.mdx +445 -0
  4. package/corpus/core/docs/content/toolkit-ui.mdx +16 -0
  5. package/corpus/core/package.json +1 -1
  6. package/corpus/core/src/a2a/client.ts +32 -10
  7. package/corpus/core/src/a2a/types.ts +1 -0
  8. package/corpus/core/src/agent/types.ts +1 -1
  9. package/corpus/core/src/cli/index.ts +18 -10
  10. package/corpus/core/src/cli/multi-frontier-runs.ts +5 -3
  11. package/corpus/core/src/cli/templates-meta.ts +0 -12
  12. package/corpus/core/src/cli/workspace-dev.ts +1 -1
  13. package/corpus/core/src/client/AgentPanel.tsx +99 -108
  14. package/corpus/core/src/client/AssistantChat.tsx +30 -13
  15. package/corpus/core/src/client/CommandMenu.tsx +68 -178
  16. package/corpus/core/src/client/RunStuckBanner.tsx +39 -47
  17. package/corpus/core/src/client/agent-chat-adapter.ts +3 -1
  18. package/corpus/core/src/client/app-providers.tsx +1 -1
  19. package/corpus/core/src/client/chat/action-chat-ui-surface.tsx +32 -0
  20. package/corpus/core/src/client/chat/message-components.tsx +169 -18
  21. package/corpus/core/src/client/chat/tool-call-display.tsx +50 -14
  22. package/corpus/core/src/client/chat/widgets/InlineExtensionWidget.tsx +13 -40
  23. package/corpus/core/src/client/chat/widgets/builtin-tool-renderers.tsx +7 -3
  24. package/corpus/core/src/client/components/ui/message-scroller.tsx +15 -1
  25. package/corpus/core/src/client/conversation/AgentConversation.tsx +12 -1
  26. package/corpus/core/src/client/error-capture.ts +2 -6
  27. package/corpus/core/src/client/i18n.tsx +22 -0
  28. package/corpus/core/src/client/index.ts +17 -0
  29. package/corpus/core/src/client/org/TeamPage.tsx +257 -153
  30. package/corpus/core/src/client/progress/RunsTray.tsx +89 -88
  31. package/corpus/core/src/client/resources/McpConnectionSuggestion.tsx +25 -16
  32. package/corpus/core/src/client/resources/McpIntegrationDialog.tsx +34 -13
  33. package/corpus/core/src/client/resources/ResourcesPanel.tsx +5 -1
  34. package/corpus/core/src/client/resources/mcp-integration-catalog.ts +20 -17
  35. package/corpus/core/src/client/resources/mcp-integration-logos.ts +2 -2
  36. package/corpus/core/src/client/route-chunk-recovery.ts +5 -3
  37. package/corpus/core/src/client/session-replay.ts +3 -3
  38. package/corpus/core/src/client/settings/DemoModeSection.tsx +6 -18
  39. package/corpus/core/src/client/settings/SecretsSection.tsx +97 -52
  40. package/corpus/core/src/client/settings/SettingsPanel.tsx +217 -252
  41. package/corpus/core/src/client/settings/SettingsTabsPage.tsx +23 -2
  42. package/corpus/core/src/client/settings/VoiceTranscriptionSection.tsx +7 -18
  43. package/corpus/core/src/client/settings/index.ts +7 -0
  44. package/corpus/core/src/client/settings/useSettingsPanelController.ts +155 -0
  45. package/corpus/core/src/client/setup-connections/BuilderConnectCard.tsx +116 -51
  46. package/corpus/core/src/client/setup-connections/index.ts +10 -0
  47. package/corpus/core/src/client/setup-connections/useBuilderConnectCardController.ts +82 -0
  48. package/corpus/core/src/client/sharing/ShareButton.tsx +64 -586
  49. package/corpus/core/src/client/sharing/ShareDialog.tsx +299 -633
  50. package/corpus/core/src/client/sharing/index.ts +42 -0
  51. package/corpus/core/src/client/sharing/share-controller-helpers.ts +318 -0
  52. package/corpus/core/src/client/sharing/useShareButtonController.ts +600 -0
  53. package/corpus/core/src/client/sharing/useShareDialogController.ts +559 -0
  54. package/corpus/core/src/client/sse-event-processor.ts +23 -0
  55. package/corpus/core/src/client/tool-display.ts +71 -0
  56. package/corpus/core/src/client/transcription/use-live-transcription.ts +64 -45
  57. package/corpus/core/src/client/use-agent-engine-configured.ts +12 -19
  58. package/corpus/core/src/client/use-chat-threads.ts +33 -12
  59. package/corpus/core/src/deploy/build.ts +2 -1
  60. package/corpus/core/src/guards/db-tool-scoping.ts +1 -1
  61. package/corpus/core/src/integrations/adapters/slack.ts +84 -5
  62. package/corpus/core/src/integrations/index.ts +5 -1
  63. package/corpus/core/src/localization/default-messages.ts +6 -1
  64. package/corpus/core/src/mcp-client/oauth-routes.ts +61 -14
  65. package/corpus/core/src/scripts/call-agent.ts +5 -1
  66. package/corpus/core/src/server/realtime-voice.ts +5 -2
  67. package/corpus/core/src/styles/agent-native.css +0 -24
  68. package/corpus/core/src/templates/default/.agents/skills/agent-native-toolkit/SKILL.md +37 -2
  69. package/corpus/core/src/templates/default/.agents/skills/customizing-agent-native/SKILL.md +86 -11
  70. package/corpus/core/src/templates/default/.agents/skills/frontend-design/SKILL.md +22 -2
  71. package/corpus/core/src/templates/default/.agents/skills/shadcn-ui/SKILL.md +28 -4
  72. package/corpus/core/src/templates/default/app/components/ui/toolkit-provider.tsx +10 -0
  73. package/corpus/core/src/templates/default/app/design-system.ts +3 -0
  74. package/corpus/core/src/templates/default/app/root.tsx +5 -2
  75. package/corpus/core/src/templates/default/package.json +1 -0
  76. package/corpus/core/src/templates/headless/.agents/skills/agent-native-toolkit/SKILL.md +37 -2
  77. package/corpus/core/src/templates/headless/.agents/skills/customizing-agent-native/SKILL.md +86 -11
  78. package/corpus/core/src/templates/workspace-core/.agents/skills/agent-native-toolkit/SKILL.md +37 -2
  79. package/corpus/core/src/templates/workspace-core/.agents/skills/customizing-agent-native/SKILL.md +86 -11
  80. package/corpus/core/src/templates/workspace-core/.agents/skills/frontend-design/SKILL.md +22 -2
  81. package/corpus/core/src/templates/workspace-core/.agents/skills/shadcn-ui/SKILL.md +28 -4
  82. package/corpus/core/src/templates/workspace-core/.agents/skills/voice-transcription/SKILL.md +7 -5
  83. package/corpus/core/src/terminal/cli-registry.ts +1 -1
  84. package/corpus/core/src/vite/client.ts +205 -1
  85. package/corpus/templates/analytics/.agents/skills/agent-native-toolkit/SKILL.md +37 -2
  86. package/corpus/templates/analytics/.agents/skills/customizing-agent-native/SKILL.md +86 -11
  87. package/corpus/templates/analytics/.agents/skills/frontend-design/SKILL.md +22 -2
  88. package/corpus/templates/analytics/.agents/skills/shadcn-ui/SKILL.md +28 -4
  89. package/corpus/templates/analytics/app/components/ui/toolkit-provider.tsx +6 -1
  90. package/corpus/templates/analytics/app/design-system.ts +3 -0
  91. package/corpus/templates/analytics/app/hooks/use-dashboard-views.ts +13 -1
  92. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/ViewsMenu.tsx +10 -0
  93. package/corpus/templates/analytics/changelog/2026-07-22-show-a-useful-error-when-saving-a-dashboard-view-fails.md +6 -0
  94. package/corpus/templates/assets/.agents/skills/agent-native-toolkit/SKILL.md +37 -2
  95. package/corpus/templates/assets/.agents/skills/customizing-agent-native/SKILL.md +86 -11
  96. package/corpus/templates/assets/.agents/skills/frontend-design/SKILL.md +22 -2
  97. package/corpus/templates/assets/.agents/skills/shadcn-ui/SKILL.md +28 -4
  98. package/corpus/templates/assets/app/components/ui/alert.tsx +1 -0
  99. package/corpus/templates/assets/app/components/ui/toolkit-provider.tsx +6 -1
  100. package/corpus/templates/assets/app/design-system.ts +3 -0
  101. package/corpus/templates/assets/app/routes/brand-kits.$id_.presets.$presetId.tsx +26 -30
  102. package/corpus/templates/brain/.agents/skills/agent-native-toolkit/SKILL.md +37 -2
  103. package/corpus/templates/brain/.agents/skills/customizing-agent-native/SKILL.md +86 -11
  104. package/corpus/templates/brain/.agents/skills/frontend-design/SKILL.md +22 -2
  105. package/corpus/templates/brain/.agents/skills/shadcn-ui/SKILL.md +28 -4
  106. package/corpus/templates/brain/app/components/ui/dialog.tsx +1 -0
  107. package/corpus/templates/brain/app/components/ui/toolkit-provider.tsx +6 -1
  108. package/corpus/templates/brain/app/design-system.ts +3 -0
  109. package/corpus/templates/brain/app/routes/sources.tsx +189 -122
  110. package/corpus/templates/calendar/.agents/skills/agent-native-toolkit/SKILL.md +37 -2
  111. package/corpus/templates/calendar/.agents/skills/customizing-agent-native/SKILL.md +86 -11
  112. package/corpus/templates/calendar/.agents/skills/frontend-design/SKILL.md +22 -2
  113. package/corpus/templates/calendar/.agents/skills/shadcn-ui/SKILL.md +28 -4
  114. package/corpus/templates/calendar/app/components/ui/toolkit-provider.tsx +6 -1
  115. package/corpus/templates/calendar/app/design-system.ts +3 -0
  116. package/corpus/templates/chat/.agents/skills/agent-native-toolkit/SKILL.md +37 -2
  117. package/corpus/templates/chat/.agents/skills/customizing-agent-native/SKILL.md +86 -11
  118. package/corpus/templates/chat/.agents/skills/frontend-design/SKILL.md +22 -2
  119. package/corpus/templates/chat/.agents/skills/shadcn-ui/SKILL.md +28 -4
  120. package/corpus/templates/chat/app/components/ui/toolkit-provider.tsx +6 -1
  121. package/corpus/templates/chat/app/design-system.ts +3 -0
  122. package/corpus/templates/clips/.agents/skills/agent-native-toolkit/SKILL.md +37 -2
  123. package/corpus/templates/clips/.agents/skills/customizing-agent-native/SKILL.md +86 -11
  124. package/corpus/templates/clips/.agents/skills/frontend-design/SKILL.md +22 -2
  125. package/corpus/templates/clips/.agents/skills/shadcn-ui/SKILL.md +28 -4
  126. package/corpus/templates/clips/AGENTS.md +8 -6
  127. package/corpus/templates/clips/actions/request-transcript.ts +90 -420
  128. package/corpus/templates/clips/actions/save-browser-transcript.ts +11 -28
  129. package/corpus/templates/clips/app/components/capture-install-options.tsx +5 -3
  130. package/corpus/templates/clips/app/components/player/transcript-panel.tsx +3 -136
  131. package/corpus/templates/clips/app/components/ui/toolkit-provider.tsx +6 -1
  132. package/corpus/templates/clips/app/design-system.ts +3 -0
  133. package/corpus/templates/clips/app/lib/capture-install-options.ts +15 -4
  134. package/corpus/templates/clips/app/routes/_app.library._index.tsx +1 -1
  135. package/corpus/templates/clips/app/routes/download.tsx +3 -2
  136. package/corpus/templates/clips/changelog/2026-07-22-fixed-an-intermittent-hydration-error-on-the-download-page.md +6 -0
  137. package/corpus/templates/clips/changelog/2026-07-22-fixed-transcript-generation-when-native-speech-capture-retur.md +6 -0
  138. package/corpus/templates/clips/changelog/2026-07-22-fixed-windows-recordings-aborting-during-the-countdown.md +6 -0
  139. package/corpus/templates/clips/changelog/2026-07-22-permissions-and-rewind-controls-are-now-grouped-with-clearer.md +6 -0
  140. package/corpus/templates/clips/changelog/2026-07-22-the-desktop-popover-opens-centered-under-the-menu-bar-icon-o.md +6 -0
  141. package/corpus/templates/clips/changelog/2026-07-22-transcript-generation-now-retries-with-backup-speech-recogni.md +6 -0
  142. package/corpus/templates/clips/desktop/src/app.tsx +86 -82
  143. package/corpus/templates/clips/desktop/src/styles.css +13 -0
  144. package/corpus/templates/clips/desktop/src-tauri/src/lib.rs +10 -1
  145. package/corpus/templates/clips/desktop/src-tauri/src/shortcuts.rs +37 -2
  146. package/corpus/templates/clips/desktop/src-tauri/src/tray.rs +18 -0
  147. package/corpus/templates/clips/server/lib/public-agent-context.ts +2 -2
  148. package/corpus/templates/clips/server/register-secrets.ts +7 -6
  149. package/corpus/templates/content/.agents/skills/agent-native-toolkit/SKILL.md +37 -2
  150. package/corpus/templates/content/.agents/skills/customizing-agent-native/SKILL.md +86 -11
  151. package/corpus/templates/content/.agents/skills/frontend-design/SKILL.md +22 -2
  152. package/corpus/templates/content/.agents/skills/shadcn-ui/SKILL.md +28 -4
  153. package/corpus/templates/content/app/components/editor/DocumentToolbar.tsx +41 -59
  154. package/corpus/templates/content/app/components/editor/SlashCommandMenu.tsx +16 -84
  155. package/corpus/templates/content/app/components/editor/VisualEditor.tsx +13 -7
  156. package/corpus/templates/content/app/components/editor/database/DatabaseView.tsx +41 -41
  157. package/corpus/templates/content/app/components/editor/database/GalleryView.tsx +2 -1
  158. package/corpus/templates/content/app/components/editor/database/ListView.tsx +2 -1
  159. package/corpus/templates/content/app/components/editor/database/TimelineView.tsx +9 -9
  160. package/corpus/templates/content/app/components/editor/database/sidebar.tsx +7 -7
  161. package/corpus/templates/content/app/components/editor/database-sources/BuilderSourceReviewDialog.tsx +11 -11
  162. package/corpus/templates/content/app/components/editor/extensions/ImageBlock.tsx +2 -2
  163. package/corpus/templates/content/app/components/ui/checkbox.tsx +1 -0
  164. package/corpus/templates/content/app/components/ui/collapsible.tsx +1 -0
  165. package/corpus/templates/content/app/components/ui/toolkit-provider.tsx +6 -1
  166. package/corpus/templates/content/app/design-system.ts +3 -0
  167. package/corpus/templates/content/app/global.css +29 -3
  168. package/corpus/templates/content/app/i18n-data.ts +10 -0
  169. package/corpus/templates/content/changelog/2026-07-22-page-actions-are-grouped-into-the-three-dots-menu-for-a-clea.md +6 -0
  170. package/corpus/templates/design/.agents/skills/agent-native-toolkit/SKILL.md +37 -2
  171. package/corpus/templates/design/.agents/skills/customizing-agent-native/SKILL.md +86 -11
  172. package/corpus/templates/design/.agents/skills/frontend-design/SKILL.md +22 -2
  173. package/corpus/templates/design/.agents/skills/shadcn-ui/SKILL.md +28 -4
  174. package/corpus/templates/design/app/components/editor/PromptDialog.tsx +8 -8
  175. package/corpus/templates/design/app/components/ui/command.tsx +1 -0
  176. package/corpus/templates/design/app/components/ui/toolkit-provider.tsx +6 -1
  177. package/corpus/templates/design/app/design-system.ts +3 -0
  178. package/corpus/templates/design/server/lib/fig-file-decoder.ts +1 -0
  179. package/corpus/templates/dispatch/.agents/skills/agent-native-toolkit/SKILL.md +37 -2
  180. package/corpus/templates/dispatch/.agents/skills/customizing-agent-native/SKILL.md +86 -11
  181. package/corpus/templates/dispatch/.agents/skills/frontend-design/SKILL.md +22 -2
  182. package/corpus/templates/dispatch/.agents/skills/shadcn-ui/SKILL.md +28 -4
  183. package/corpus/templates/dispatch/app/components/ui/button.tsx +1 -0
  184. package/corpus/templates/dispatch/app/components/ui/toolkit-provider.tsx +17 -0
  185. package/corpus/templates/dispatch/app/design-system.ts +3 -0
  186. package/corpus/templates/dispatch/app/root.tsx +10 -7
  187. package/corpus/templates/dispatch/package.json +1 -0
  188. package/corpus/templates/forms/.agents/skills/agent-native-toolkit/SKILL.md +37 -2
  189. package/corpus/templates/forms/.agents/skills/customizing-agent-native/SKILL.md +86 -11
  190. package/corpus/templates/forms/.agents/skills/frontend-design/SKILL.md +22 -2
  191. package/corpus/templates/forms/.agents/skills/shadcn-ui/SKILL.md +28 -4
  192. package/corpus/templates/forms/app/components/ui/toolkit-provider.tsx +6 -1
  193. package/corpus/templates/forms/app/design-system.ts +3 -0
  194. package/corpus/templates/macros/.agents/skills/agent-native-toolkit/SKILL.md +37 -2
  195. package/corpus/templates/macros/.agents/skills/customizing-agent-native/SKILL.md +86 -11
  196. package/corpus/templates/macros/.agents/skills/frontend-design/SKILL.md +22 -2
  197. package/corpus/templates/macros/.agents/skills/shadcn-ui/SKILL.md +28 -4
  198. package/corpus/templates/macros/app/components/ui/toolkit-provider.tsx +6 -1
  199. package/corpus/templates/macros/app/design-system.ts +3 -0
  200. package/corpus/templates/mail/.agents/skills/agent-native-toolkit/SKILL.md +37 -2
  201. package/corpus/templates/mail/.agents/skills/customizing-agent-native/SKILL.md +86 -11
  202. package/corpus/templates/mail/.agents/skills/frontend-design/SKILL.md +22 -2
  203. package/corpus/templates/mail/.agents/skills/shadcn-ui/SKILL.md +28 -4
  204. package/corpus/templates/mail/app/components/email/EmailThread.tsx +134 -93
  205. package/corpus/templates/mail/app/components/email/email-iframe-document.ts +8 -2
  206. package/corpus/templates/mail/app/components/ui/textarea.tsx +1 -21
  207. package/corpus/templates/mail/app/components/ui/toolkit-provider.tsx +6 -1
  208. package/corpus/templates/mail/app/design-system.ts +3 -0
  209. package/corpus/templates/mail/changelog/2026-07-22-email-messages-no-longer-flash-with-an-unstyled-page-while-l.md +6 -0
  210. package/corpus/templates/plan/.agents/skills/agent-native-toolkit/SKILL.md +37 -2
  211. package/corpus/templates/plan/.agents/skills/customizing-agent-native/SKILL.md +86 -11
  212. package/corpus/templates/plan/.agents/skills/frontend-design/SKILL.md +22 -2
  213. package/corpus/templates/plan/.agents/skills/shadcn-ui/SKILL.md +28 -4
  214. package/corpus/templates/plan/app/components/plan/PlanContentRenderer.tsx +1 -1
  215. package/corpus/templates/plan/app/components/ui/toolkit-provider.tsx +6 -1
  216. package/corpus/templates/plan/app/design-system.ts +3 -0
  217. package/corpus/templates/plan/app/entry.client.tsx +3 -0
  218. package/corpus/templates/plan/changelog/2026-07-22-recover-stale-pages-after-a-deployment-refresh-automatically.md +6 -0
  219. package/corpus/templates/slides/.agents/skills/agent-native-toolkit/SKILL.md +37 -2
  220. package/corpus/templates/slides/.agents/skills/customizing-agent-native/SKILL.md +86 -11
  221. package/corpus/templates/slides/.agents/skills/frontend-design/SKILL.md +22 -2
  222. package/corpus/templates/slides/.agents/skills/shadcn-ui/SKILL.md +28 -4
  223. package/corpus/templates/slides/app/components/ui/toolkit-provider.tsx +6 -1
  224. package/corpus/templates/slides/app/design-system.ts +3 -0
  225. package/corpus/templates/slides/app/hooks/use-agent-generating.ts +10 -3
  226. package/corpus/templates/slides/app/pages/Index.tsx +1 -0
  227. package/corpus/templates/slides/changelog/2026-07-22-new-deck-prompts-now-open-in-their-own-visible-chat-thread.md +6 -0
  228. package/corpus/templates/tasks/.agents/skills/agent-native-toolkit/SKILL.md +37 -2
  229. package/corpus/templates/tasks/.agents/skills/customizing-agent-native/SKILL.md +86 -11
  230. package/corpus/templates/tasks/.agents/skills/frontend-design/SKILL.md +22 -2
  231. package/corpus/templates/tasks/.agents/skills/shadcn-ui/SKILL.md +28 -4
  232. package/corpus/templates/tasks/app/components/ui/toolkit-provider.tsx +17 -0
  233. package/corpus/templates/tasks/app/design-system.ts +3 -0
  234. package/corpus/templates/tasks/app/root.tsx +5 -2
  235. package/corpus/toolkit/CHANGELOG.md +23 -0
  236. package/corpus/toolkit/agent-native.eject.json +71 -0
  237. package/corpus/toolkit/package.json +31 -1
  238. package/corpus/toolkit/src/chat-history/ChatHistoryRail.tsx +100 -39
  239. package/corpus/toolkit/src/chat-history/index.ts +9 -0
  240. package/corpus/toolkit/src/chat-history/useChatHistoryRailController.ts +76 -0
  241. package/corpus/toolkit/src/chat-history.css +2 -0
  242. package/corpus/toolkit/src/composer/ComposerPlusMenu.tsx +11 -8
  243. package/corpus/toolkit/src/composer/PromptComposer.tsx +32 -7
  244. package/corpus/toolkit/src/composer/RealtimeVoiceMode.tsx +119 -31
  245. package/corpus/toolkit/src/composer/useRealtimeVoiceMode.tsx +124 -9
  246. package/corpus/toolkit/src/conformance/__fixtures__/css-in-js-adapter.tsx +401 -0
  247. package/corpus/toolkit/src/conformance/index.ts +3 -0
  248. package/corpus/toolkit/src/conformance/runner.tsx +862 -0
  249. package/corpus/toolkit/src/conformance/types.ts +45 -0
  250. package/corpus/toolkit/src/conformance/version.ts +22 -0
  251. package/corpus/toolkit/src/design-system/components.tsx +146 -0
  252. package/corpus/toolkit/src/design-system/context.tsx +31 -0
  253. package/corpus/toolkit/src/design-system/default-adapter.tsx +915 -0
  254. package/corpus/toolkit/src/design-system/definition.ts +14 -0
  255. package/corpus/toolkit/src/design-system/error-boundary.tsx +37 -0
  256. package/corpus/toolkit/src/design-system/index.ts +7 -0
  257. package/corpus/toolkit/src/design-system/theme.ts +145 -0
  258. package/corpus/toolkit/src/design-system/types.ts +363 -0
  259. package/corpus/toolkit/src/editor/SharedRichEditor.tsx +13 -2
  260. package/corpus/toolkit/src/editor/SlashCommandMenu.tsx +20 -0
  261. package/corpus/toolkit/src/editor/index.ts +2 -0
  262. package/corpus/toolkit/src/provider.tsx +98 -5
  263. package/corpus/toolkit/src/styles.css +52 -23
  264. package/corpus/toolkit/src/ui/button.tsx +95 -6
  265. package/corpus/toolkit/src/ui/dialog.tsx +48 -23
  266. package/corpus/toolkit/src/ui/popover.tsx +16 -2
  267. package/corpus/toolkit/src/ui/select.tsx +7 -3
  268. package/corpus/toolkit/src/ui/sidebar.tsx +47 -48
  269. package/corpus/toolkit/src/ui/tooltip.tsx +7 -3
  270. package/dist/a2a/client.d.ts +3 -1
  271. package/dist/a2a/client.d.ts.map +1 -1
  272. package/dist/a2a/client.js +17 -12
  273. package/dist/a2a/client.js.map +1 -1
  274. package/dist/a2a/types.d.ts +1 -1
  275. package/dist/a2a/types.d.ts.map +1 -1
  276. package/dist/a2a/types.js.map +1 -1
  277. package/dist/agent/types.d.ts +1 -1
  278. package/dist/agent/types.d.ts.map +1 -1
  279. package/dist/agent/types.js.map +1 -1
  280. package/dist/cli/index.js +18 -8
  281. package/dist/cli/index.js.map +1 -1
  282. package/dist/cli/multi-frontier-runs.js +3 -3
  283. package/dist/cli/multi-frontier-runs.js.map +1 -1
  284. package/dist/cli/templates-meta.d.ts.map +1 -1
  285. package/dist/cli/templates-meta.js +0 -12
  286. package/dist/cli/templates-meta.js.map +1 -1
  287. package/dist/cli/workspace-dev.js +1 -1
  288. package/dist/cli/workspace-dev.js.map +1 -1
  289. package/dist/client/AgentPanel.d.ts.map +1 -1
  290. package/dist/client/AgentPanel.js +18 -15
  291. package/dist/client/AgentPanel.js.map +1 -1
  292. package/dist/client/AssistantChat.d.ts.map +1 -1
  293. package/dist/client/AssistantChat.js +26 -15
  294. package/dist/client/AssistantChat.js.map +1 -1
  295. package/dist/client/CommandMenu.d.ts.map +1 -1
  296. package/dist/client/CommandMenu.js +18 -106
  297. package/dist/client/CommandMenu.js.map +1 -1
  298. package/dist/client/RunStuckBanner.d.ts +3 -5
  299. package/dist/client/RunStuckBanner.d.ts.map +1 -1
  300. package/dist/client/RunStuckBanner.js +17 -18
  301. package/dist/client/RunStuckBanner.js.map +1 -1
  302. package/dist/client/agent-chat-adapter.d.ts.map +1 -1
  303. package/dist/client/agent-chat-adapter.js +2 -1
  304. package/dist/client/agent-chat-adapter.js.map +1 -1
  305. package/dist/client/app-providers.d.ts.map +1 -1
  306. package/dist/client/app-providers.js +1 -1
  307. package/dist/client/app-providers.js.map +1 -1
  308. package/dist/client/chat/action-chat-ui-surface.d.ts +8 -0
  309. package/dist/client/chat/action-chat-ui-surface.d.ts.map +1 -0
  310. package/dist/client/chat/action-chat-ui-surface.js +10 -0
  311. package/dist/client/chat/action-chat-ui-surface.js.map +1 -0
  312. package/dist/client/chat/message-components.d.ts +12 -1
  313. package/dist/client/chat/message-components.d.ts.map +1 -1
  314. package/dist/client/chat/message-components.js +102 -14
  315. package/dist/client/chat/message-components.js.map +1 -1
  316. package/dist/client/chat/tool-call-display.d.ts +3 -1
  317. package/dist/client/chat/tool-call-display.d.ts.map +1 -1
  318. package/dist/client/chat/tool-call-display.js +33 -14
  319. package/dist/client/chat/tool-call-display.js.map +1 -1
  320. package/dist/client/chat/widgets/InlineExtensionWidget.d.ts.map +1 -1
  321. package/dist/client/chat/widgets/InlineExtensionWidget.js +9 -12
  322. package/dist/client/chat/widgets/InlineExtensionWidget.js.map +1 -1
  323. package/dist/client/chat/widgets/builtin-tool-renderers.d.ts.map +1 -1
  324. package/dist/client/chat/widgets/builtin-tool-renderers.js +5 -3
  325. package/dist/client/chat/widgets/builtin-tool-renderers.js.map +1 -1
  326. package/dist/client/components/ui/message-scroller.d.ts +1 -1
  327. package/dist/client/components/ui/message-scroller.d.ts.map +1 -1
  328. package/dist/client/components/ui/message-scroller.js +4 -3
  329. package/dist/client/components/ui/message-scroller.js.map +1 -1
  330. package/dist/client/conversation/AgentConversation.d.ts.map +1 -1
  331. package/dist/client/conversation/AgentConversation.js +3 -2
  332. package/dist/client/conversation/AgentConversation.js.map +1 -1
  333. package/dist/client/error-capture.d.ts.map +1 -1
  334. package/dist/client/error-capture.js +2 -2
  335. package/dist/client/error-capture.js.map +1 -1
  336. package/dist/client/i18n.d.ts.map +1 -1
  337. package/dist/client/i18n.js +9 -0
  338. package/dist/client/i18n.js.map +1 -1
  339. package/dist/client/index.d.ts +2 -2
  340. package/dist/client/index.d.ts.map +1 -1
  341. package/dist/client/index.js +2 -2
  342. package/dist/client/index.js.map +1 -1
  343. package/dist/client/org/TeamPage.d.ts.map +1 -1
  344. package/dist/client/org/TeamPage.js +41 -33
  345. package/dist/client/org/TeamPage.js.map +1 -1
  346. package/dist/client/progress/RunsTray.d.ts.map +1 -1
  347. package/dist/client/progress/RunsTray.js +9 -10
  348. package/dist/client/progress/RunsTray.js.map +1 -1
  349. package/dist/client/resources/McpConnectionSuggestion.d.ts +1 -0
  350. package/dist/client/resources/McpConnectionSuggestion.d.ts.map +1 -1
  351. package/dist/client/resources/McpConnectionSuggestion.js +14 -12
  352. package/dist/client/resources/McpConnectionSuggestion.js.map +1 -1
  353. package/dist/client/resources/McpIntegrationDialog.d.ts.map +1 -1
  354. package/dist/client/resources/McpIntegrationDialog.js +10 -8
  355. package/dist/client/resources/McpIntegrationDialog.js.map +1 -1
  356. package/dist/client/resources/ResourcesPanel.d.ts.map +1 -1
  357. package/dist/client/resources/ResourcesPanel.js +3 -1
  358. package/dist/client/resources/ResourcesPanel.js.map +1 -1
  359. package/dist/client/resources/mcp-integration-catalog.d.ts +2 -0
  360. package/dist/client/resources/mcp-integration-catalog.d.ts.map +1 -1
  361. package/dist/client/resources/mcp-integration-catalog.js +17 -17
  362. package/dist/client/resources/mcp-integration-catalog.js.map +1 -1
  363. package/dist/client/resources/mcp-integration-logos.js +2 -2
  364. package/dist/client/resources/mcp-integration-logos.js.map +1 -1
  365. package/dist/client/route-chunk-recovery.d.ts.map +1 -1
  366. package/dist/client/route-chunk-recovery.js +5 -3
  367. package/dist/client/route-chunk-recovery.js.map +1 -1
  368. package/dist/client/session-replay.js +3 -3
  369. package/dist/client/session-replay.js.map +1 -1
  370. package/dist/client/settings/DemoModeSection.d.ts.map +1 -1
  371. package/dist/client/settings/DemoModeSection.js +2 -5
  372. package/dist/client/settings/DemoModeSection.js.map +1 -1
  373. package/dist/client/settings/SecretsSection.d.ts.map +1 -1
  374. package/dist/client/settings/SecretsSection.js +18 -6
  375. package/dist/client/settings/SecretsSection.js.map +1 -1
  376. package/dist/client/settings/SettingsPanel.d.ts.map +1 -1
  377. package/dist/client/settings/SettingsPanel.js +53 -118
  378. package/dist/client/settings/SettingsPanel.js.map +1 -1
  379. package/dist/client/settings/SettingsTabsPage.d.ts.map +1 -1
  380. package/dist/client/settings/SettingsTabsPage.js +16 -1
  381. package/dist/client/settings/SettingsTabsPage.js.map +1 -1
  382. package/dist/client/settings/VoiceTranscriptionSection.d.ts.map +1 -1
  383. package/dist/client/settings/VoiceTranscriptionSection.js +2 -5
  384. package/dist/client/settings/VoiceTranscriptionSection.js.map +1 -1
  385. package/dist/client/settings/index.d.ts +1 -0
  386. package/dist/client/settings/index.d.ts.map +1 -1
  387. package/dist/client/settings/index.js +1 -0
  388. package/dist/client/settings/index.js.map +1 -1
  389. package/dist/client/settings/useSettingsPanelController.d.ts +22 -0
  390. package/dist/client/settings/useSettingsPanelController.d.ts.map +1 -0
  391. package/dist/client/settings/useSettingsPanelController.js +103 -0
  392. package/dist/client/settings/useSettingsPanelController.js.map +1 -0
  393. package/dist/client/setup-connections/BuilderConnectCard.d.ts +14 -6
  394. package/dist/client/setup-connections/BuilderConnectCard.d.ts.map +1 -1
  395. package/dist/client/setup-connections/BuilderConnectCard.js +24 -16
  396. package/dist/client/setup-connections/BuilderConnectCard.js.map +1 -1
  397. package/dist/client/setup-connections/index.d.ts +2 -1
  398. package/dist/client/setup-connections/index.d.ts.map +1 -1
  399. package/dist/client/setup-connections/index.js +2 -1
  400. package/dist/client/setup-connections/index.js.map +1 -1
  401. package/dist/client/setup-connections/useBuilderConnectCardController.d.ts +34 -0
  402. package/dist/client/setup-connections/useBuilderConnectCardController.d.ts.map +1 -0
  403. package/dist/client/setup-connections/useBuilderConnectCardController.js +39 -0
  404. package/dist/client/setup-connections/useBuilderConnectCardController.js.map +1 -0
  405. package/dist/client/sharing/ShareButton.d.ts +2 -1
  406. package/dist/client/sharing/ShareButton.d.ts.map +1 -1
  407. package/dist/client/sharing/ShareButton.js +17 -463
  408. package/dist/client/sharing/ShareButton.js.map +1 -1
  409. package/dist/client/sharing/ShareDialog.d.ts +6 -6
  410. package/dist/client/sharing/ShareDialog.d.ts.map +1 -1
  411. package/dist/client/sharing/ShareDialog.js +69 -283
  412. package/dist/client/sharing/ShareDialog.js.map +1 -1
  413. package/dist/client/sharing/index.d.ts +3 -0
  414. package/dist/client/sharing/index.d.ts.map +1 -1
  415. package/dist/client/sharing/index.js +3 -0
  416. package/dist/client/sharing/index.js.map +1 -1
  417. package/dist/client/sharing/share-controller-helpers.d.ts +70 -0
  418. package/dist/client/sharing/share-controller-helpers.d.ts.map +1 -0
  419. package/dist/client/sharing/share-controller-helpers.js +224 -0
  420. package/dist/client/sharing/share-controller-helpers.js.map +1 -0
  421. package/dist/client/sharing/useShareButtonController.d.ts +91 -0
  422. package/dist/client/sharing/useShareButtonController.d.ts.map +1 -0
  423. package/dist/client/sharing/useShareButtonController.js +397 -0
  424. package/dist/client/sharing/useShareButtonController.js.map +1 -0
  425. package/dist/client/sharing/useShareDialogController.d.ts +109 -0
  426. package/dist/client/sharing/useShareDialogController.d.ts.map +1 -0
  427. package/dist/client/sharing/useShareDialogController.js +348 -0
  428. package/dist/client/sharing/useShareDialogController.js.map +1 -0
  429. package/dist/client/sse-event-processor.d.ts.map +1 -1
  430. package/dist/client/sse-event-processor.js +21 -0
  431. package/dist/client/sse-event-processor.js.map +1 -1
  432. package/dist/client/tool-display.d.ts +16 -0
  433. package/dist/client/tool-display.d.ts.map +1 -1
  434. package/dist/client/tool-display.js +52 -0
  435. package/dist/client/tool-display.js.map +1 -1
  436. package/dist/client/transcription/use-live-transcription.d.ts +3 -3
  437. package/dist/client/transcription/use-live-transcription.d.ts.map +1 -1
  438. package/dist/client/transcription/use-live-transcription.js +22 -11
  439. package/dist/client/transcription/use-live-transcription.js.map +1 -1
  440. package/dist/client/use-agent-engine-configured.d.ts +3 -2
  441. package/dist/client/use-agent-engine-configured.d.ts.map +1 -1
  442. package/dist/client/use-agent-engine-configured.js +7 -19
  443. package/dist/client/use-agent-engine-configured.js.map +1 -1
  444. package/dist/client/use-chat-threads.d.ts.map +1 -1
  445. package/dist/client/use-chat-threads.js +21 -8
  446. package/dist/client/use-chat-threads.js.map +1 -1
  447. package/dist/collab/routes.d.ts +1 -1
  448. package/dist/collab/struct-routes.d.ts +1 -1
  449. package/dist/deploy/build.d.ts.map +1 -1
  450. package/dist/deploy/build.js +1 -1
  451. package/dist/deploy/build.js.map +1 -1
  452. package/dist/guards/db-tool-scoping.js +1 -1
  453. package/dist/guards/db-tool-scoping.js.map +1 -1
  454. package/dist/integrations/adapters/slack.d.ts +1 -0
  455. package/dist/integrations/adapters/slack.d.ts.map +1 -1
  456. package/dist/integrations/adapters/slack.js +61 -5
  457. package/dist/integrations/adapters/slack.js.map +1 -1
  458. package/dist/integrations/index.d.ts +1 -1
  459. package/dist/integrations/index.d.ts.map +1 -1
  460. package/dist/integrations/index.js +1 -1
  461. package/dist/integrations/index.js.map +1 -1
  462. package/dist/localization/default-messages.d.ts +4 -0
  463. package/dist/localization/default-messages.d.ts.map +1 -1
  464. package/dist/localization/default-messages.js +5 -1
  465. package/dist/localization/default-messages.js.map +1 -1
  466. package/dist/mcp-client/oauth-routes.d.ts +5 -0
  467. package/dist/mcp-client/oauth-routes.d.ts.map +1 -1
  468. package/dist/mcp-client/oauth-routes.js +53 -14
  469. package/dist/mcp-client/oauth-routes.js.map +1 -1
  470. package/dist/notifications/routes.d.ts +2 -2
  471. package/dist/observability/routes.d.ts +1 -1
  472. package/dist/provider-api/actions/custom-provider-registration.d.ts +12 -12
  473. package/dist/provider-api/actions/provider-api.d.ts +11 -11
  474. package/dist/scripts/call-agent.d.ts.map +1 -1
  475. package/dist/scripts/call-agent.js +5 -1
  476. package/dist/scripts/call-agent.js.map +1 -1
  477. package/dist/secrets/routes.d.ts +6 -6
  478. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  479. package/dist/server/realtime-voice.d.ts.map +1 -1
  480. package/dist/server/realtime-voice.js +2 -2
  481. package/dist/server/realtime-voice.js.map +1 -1
  482. package/dist/styles/agent-native.css +0 -24
  483. package/dist/templates/chat/.agents/skills/agent-native-toolkit/SKILL.md +37 -2
  484. package/dist/templates/chat/.agents/skills/customizing-agent-native/SKILL.md +86 -11
  485. package/dist/templates/chat/.agents/skills/frontend-design/SKILL.md +22 -2
  486. package/dist/templates/chat/.agents/skills/shadcn-ui/SKILL.md +28 -4
  487. package/dist/templates/chat/app/components/ui/toolkit-provider.tsx +6 -1
  488. package/dist/templates/chat/app/design-system.ts +3 -0
  489. package/dist/templates/default/.agents/skills/agent-native-toolkit/SKILL.md +37 -2
  490. package/dist/templates/default/.agents/skills/customizing-agent-native/SKILL.md +86 -11
  491. package/dist/templates/default/.agents/skills/frontend-design/SKILL.md +22 -2
  492. package/dist/templates/default/.agents/skills/shadcn-ui/SKILL.md +28 -4
  493. package/dist/templates/default/app/components/ui/toolkit-provider.tsx +10 -0
  494. package/dist/templates/default/app/design-system.ts +3 -0
  495. package/dist/templates/default/app/root.tsx +5 -2
  496. package/dist/templates/default/package.json +1 -0
  497. package/dist/templates/headless/.agents/skills/agent-native-toolkit/SKILL.md +37 -2
  498. package/dist/templates/headless/.agents/skills/customizing-agent-native/SKILL.md +86 -11
  499. package/dist/templates/workspace-core/.agents/skills/agent-native-toolkit/SKILL.md +37 -2
  500. package/dist/templates/workspace-core/.agents/skills/customizing-agent-native/SKILL.md +86 -11
  501. package/dist/templates/workspace-core/.agents/skills/frontend-design/SKILL.md +22 -2
  502. package/dist/templates/workspace-core/.agents/skills/shadcn-ui/SKILL.md +28 -4
  503. package/dist/templates/workspace-core/.agents/skills/voice-transcription/SKILL.md +7 -5
  504. package/dist/terminal/cli-registry.js +1 -1
  505. package/dist/terminal/cli-registry.js.map +1 -1
  506. package/dist/vite/client.d.ts +11 -1
  507. package/dist/vite/client.d.ts.map +1 -1
  508. package/dist/vite/client.js +144 -2
  509. package/dist/vite/client.js.map +1 -1
  510. package/docs/content/custom-design-system.mdx +445 -0
  511. package/docs/content/toolkit-ui.mdx +16 -0
  512. package/package.json +2 -2
  513. package/src/a2a/client.ts +32 -10
  514. package/src/a2a/types.ts +1 -0
  515. package/src/agent/types.ts +1 -1
  516. package/src/cli/index.ts +18 -10
  517. package/src/cli/multi-frontier-runs.ts +5 -3
  518. package/src/cli/templates-meta.ts +0 -12
  519. package/src/cli/workspace-dev.ts +1 -1
  520. package/src/client/AgentPanel.tsx +99 -108
  521. package/src/client/AssistantChat.tsx +30 -13
  522. package/src/client/CommandMenu.tsx +68 -178
  523. package/src/client/RunStuckBanner.tsx +39 -47
  524. package/src/client/agent-chat-adapter.ts +3 -1
  525. package/src/client/app-providers.tsx +1 -1
  526. package/src/client/chat/action-chat-ui-surface.tsx +32 -0
  527. package/src/client/chat/message-components.tsx +169 -18
  528. package/src/client/chat/tool-call-display.tsx +50 -14
  529. package/src/client/chat/widgets/InlineExtensionWidget.tsx +13 -40
  530. package/src/client/chat/widgets/builtin-tool-renderers.tsx +7 -3
  531. package/src/client/components/ui/message-scroller.tsx +15 -1
  532. package/src/client/conversation/AgentConversation.tsx +12 -1
  533. package/src/client/error-capture.ts +2 -6
  534. package/src/client/i18n.tsx +22 -0
  535. package/src/client/index.ts +17 -0
  536. package/src/client/org/TeamPage.tsx +257 -153
  537. package/src/client/progress/RunsTray.tsx +89 -88
  538. package/src/client/resources/McpConnectionSuggestion.tsx +25 -16
  539. package/src/client/resources/McpIntegrationDialog.tsx +34 -13
  540. package/src/client/resources/ResourcesPanel.tsx +5 -1
  541. package/src/client/resources/mcp-integration-catalog.ts +20 -17
  542. package/src/client/resources/mcp-integration-logos.ts +2 -2
  543. package/src/client/route-chunk-recovery.ts +5 -3
  544. package/src/client/session-replay.ts +3 -3
  545. package/src/client/settings/DemoModeSection.tsx +6 -18
  546. package/src/client/settings/SecretsSection.tsx +97 -52
  547. package/src/client/settings/SettingsPanel.tsx +217 -252
  548. package/src/client/settings/SettingsTabsPage.tsx +23 -2
  549. package/src/client/settings/VoiceTranscriptionSection.tsx +7 -18
  550. package/src/client/settings/index.ts +7 -0
  551. package/src/client/settings/useSettingsPanelController.ts +155 -0
  552. package/src/client/setup-connections/BuilderConnectCard.tsx +116 -51
  553. package/src/client/setup-connections/index.ts +10 -0
  554. package/src/client/setup-connections/useBuilderConnectCardController.ts +82 -0
  555. package/src/client/sharing/ShareButton.tsx +64 -586
  556. package/src/client/sharing/ShareDialog.tsx +299 -633
  557. package/src/client/sharing/index.ts +42 -0
  558. package/src/client/sharing/share-controller-helpers.ts +318 -0
  559. package/src/client/sharing/useShareButtonController.ts +600 -0
  560. package/src/client/sharing/useShareDialogController.ts +559 -0
  561. package/src/client/sse-event-processor.ts +23 -0
  562. package/src/client/tool-display.ts +71 -0
  563. package/src/client/transcription/use-live-transcription.ts +64 -45
  564. package/src/client/use-agent-engine-configured.ts +12 -19
  565. package/src/client/use-chat-threads.ts +33 -12
  566. package/src/deploy/build.ts +2 -1
  567. package/src/guards/db-tool-scoping.ts +1 -1
  568. package/src/integrations/adapters/slack.ts +84 -5
  569. package/src/integrations/index.ts +5 -1
  570. package/src/localization/default-messages.ts +6 -1
  571. package/src/mcp-client/oauth-routes.ts +61 -14
  572. package/src/scripts/call-agent.ts +5 -1
  573. package/src/server/realtime-voice.ts +5 -2
  574. package/src/styles/agent-native.css +0 -24
  575. package/src/templates/chat/.agents/skills/agent-native-toolkit/SKILL.md +37 -2
  576. package/src/templates/chat/.agents/skills/customizing-agent-native/SKILL.md +86 -11
  577. package/src/templates/chat/.agents/skills/frontend-design/SKILL.md +22 -2
  578. package/src/templates/chat/.agents/skills/shadcn-ui/SKILL.md +28 -4
  579. package/src/templates/chat/app/components/ui/toolkit-provider.tsx +6 -1
  580. package/src/templates/chat/app/design-system.ts +3 -0
  581. package/src/templates/default/.agents/skills/agent-native-toolkit/SKILL.md +37 -2
  582. package/src/templates/default/.agents/skills/customizing-agent-native/SKILL.md +86 -11
  583. package/src/templates/default/.agents/skills/frontend-design/SKILL.md +22 -2
  584. package/src/templates/default/.agents/skills/shadcn-ui/SKILL.md +28 -4
  585. package/src/templates/default/app/components/ui/toolkit-provider.tsx +10 -0
  586. package/src/templates/default/app/design-system.ts +3 -0
  587. package/src/templates/default/app/root.tsx +5 -2
  588. package/src/templates/default/package.json +1 -0
  589. package/src/templates/headless/.agents/skills/agent-native-toolkit/SKILL.md +37 -2
  590. package/src/templates/headless/.agents/skills/customizing-agent-native/SKILL.md +86 -11
  591. package/src/templates/workspace-core/.agents/skills/agent-native-toolkit/SKILL.md +37 -2
  592. package/src/templates/workspace-core/.agents/skills/customizing-agent-native/SKILL.md +86 -11
  593. package/src/templates/workspace-core/.agents/skills/frontend-design/SKILL.md +22 -2
  594. package/src/templates/workspace-core/.agents/skills/shadcn-ui/SKILL.md +28 -4
  595. package/src/templates/workspace-core/.agents/skills/voice-transcription/SKILL.md +7 -5
  596. package/src/terminal/cli-registry.ts +1 -1
  597. package/src/vite/client.ts +205 -1
  598. package/corpus/templates/analytics/app/components/ui/calendar.tsx +0 -70
  599. package/corpus/templates/analytics/app/components/ui/chart.tsx +0 -386
  600. package/corpus/templates/calendar/app/components/ui/sonner.tsx +0 -58
  601. package/corpus/templates/crm/.agents/skills/agent-native-docs/SKILL.md +0 -115
  602. package/corpus/templates/crm/.agents/skills/agent-native-toolkit/SKILL.md +0 -142
  603. package/corpus/templates/crm/.agents/skills/crm/SKILL.md +0 -128
  604. package/corpus/templates/crm/.agents/skills/customizing-agent-native/SKILL.md +0 -145
  605. package/corpus/templates/crm/.agents/skills/feature-flags/SKILL.md +0 -169
  606. package/corpus/templates/crm/.agents/skills/upgrade-agent-native/SKILL.md +0 -100
  607. package/corpus/templates/crm/.env.example +0 -5
  608. package/corpus/templates/crm/AGENTS.md +0 -120
  609. package/corpus/templates/crm/CHANGELOG.md +0 -1
  610. package/corpus/templates/crm/DEVELOPING.md +0 -66
  611. package/corpus/templates/crm/README.md +0 -106
  612. package/corpus/templates/crm/_gitignore +0 -12
  613. package/corpus/templates/crm/actions/_crm-action-utils.ts +0 -87
  614. package/corpus/templates/crm/actions/_crm-dashboard.ts +0 -69
  615. package/corpus/templates/crm/actions/_crm-data-program-actions.ts +0 -15
  616. package/corpus/templates/crm/actions/_crm-signal-utils.ts +0 -79
  617. package/corpus/templates/crm/actions/apply-crm-proposals.ts +0 -203
  618. package/corpus/templates/crm/actions/attach-call-evidence.ts +0 -170
  619. package/corpus/templates/crm/actions/configure-crm-connection.ts +0 -126
  620. package/corpus/templates/crm/actions/configure-native-crm.ts +0 -44
  621. package/corpus/templates/crm/actions/create-crm-record.ts +0 -148
  622. package/corpus/templates/crm/actions/create-crm-signal-tracker.ts +0 -58
  623. package/corpus/templates/crm/actions/delete-staged-dataset.ts +0 -14
  624. package/corpus/templates/crm/actions/get-crm-automation-recipe.ts +0 -36
  625. package/corpus/templates/crm/actions/get-crm-dashboard-panel.ts +0 -35
  626. package/corpus/templates/crm/actions/get-crm-dashboard.ts +0 -14
  627. package/corpus/templates/crm/actions/get-crm-overview.ts +0 -13
  628. package/corpus/templates/crm/actions/get-crm-pipeline-data.ts +0 -61
  629. package/corpus/templates/crm/actions/get-crm-record.ts +0 -75
  630. package/corpus/templates/crm/actions/install-crm-pipeline-dashboard.ts +0 -81
  631. package/corpus/templates/crm/actions/list-crm-dashboard-revisions.ts +0 -15
  632. package/corpus/templates/crm/actions/list-crm-dashboards.ts +0 -15
  633. package/corpus/templates/crm/actions/list-crm-proposals.ts +0 -31
  634. package/corpus/templates/crm/actions/list-crm-records.ts +0 -79
  635. package/corpus/templates/crm/actions/list-crm-saved-views.ts +0 -15
  636. package/corpus/templates/crm/actions/list-crm-signal-hits.ts +0 -43
  637. package/corpus/templates/crm/actions/list-crm-signal-trackers.ts +0 -32
  638. package/corpus/templates/crm/actions/list-crm-tasks.ts +0 -22
  639. package/corpus/templates/crm/actions/list-staged-datasets.ts +0 -14
  640. package/corpus/templates/crm/actions/list-workspace-connections.ts +0 -47
  641. package/corpus/templates/crm/actions/manage-crm-signal-tracker.ts +0 -87
  642. package/corpus/templates/crm/actions/manage-crm-task.ts +0 -132
  643. package/corpus/templates/crm/actions/navigate.ts +0 -63
  644. package/corpus/templates/crm/actions/provider-api-catalog.ts +0 -22
  645. package/corpus/templates/crm/actions/provider-api-docs.ts +0 -54
  646. package/corpus/templates/crm/actions/provider-api-request.ts +0 -92
  647. package/corpus/templates/crm/actions/query-staged-dataset.ts +0 -44
  648. package/corpus/templates/crm/actions/record-crm-call-insight.ts +0 -160
  649. package/corpus/templates/crm/actions/record-crm-smart-signal.ts +0 -150
  650. package/corpus/templates/crm/actions/restore-crm-dashboard-revision.ts +0 -23
  651. package/corpus/templates/crm/actions/review-crm-signal.ts +0 -31
  652. package/corpus/templates/crm/actions/run-crm-saved-view-program.ts +0 -103
  653. package/corpus/templates/crm/actions/run-crm-signal-trackers.ts +0 -275
  654. package/corpus/templates/crm/actions/run.ts +0 -7
  655. package/corpus/templates/crm/actions/save-crm-dashboard.ts +0 -51
  656. package/corpus/templates/crm/actions/save-crm-saved-view.ts +0 -119
  657. package/corpus/templates/crm/actions/sync-crm.ts +0 -146
  658. package/corpus/templates/crm/actions/update-crm-record.ts +0 -510
  659. package/corpus/templates/crm/actions/view-screen.ts +0 -218
  660. package/corpus/templates/crm/agent-native.app-skill.json +0 -58
  661. package/corpus/templates/crm/app/components/crm/CreateCrmRecordDialog.tsx +0 -158
  662. package/corpus/templates/crm/app/components/crm/CrmDashboardPanel.tsx +0 -83
  663. package/corpus/templates/crm/app/components/crm/CrmSignalsPanel.tsx +0 -225
  664. package/corpus/templates/crm/app/components/crm/IntelligenceSettings.tsx +0 -413
  665. package/corpus/templates/crm/app/components/crm/RecordActions.tsx +0 -510
  666. package/corpus/templates/crm/app/components/crm/RecordGrid.tsx +0 -134
  667. package/corpus/templates/crm/app/components/crm/RecordWorkspace.tsx +0 -367
  668. package/corpus/templates/crm/app/components/crm/SavedViewDataProgram.tsx +0 -92
  669. package/corpus/templates/crm/app/components/crm/Surface.tsx +0 -96
  670. package/corpus/templates/crm/app/components/crm/WorkOverview.tsx +0 -180
  671. package/corpus/templates/crm/app/components/layout/CrmLayout.tsx +0 -112
  672. package/corpus/templates/crm/app/components/layout/CrmSidebar.tsx +0 -84
  673. package/corpus/templates/crm/app/entry.client.tsx +0 -16
  674. package/corpus/templates/crm/app/entry.server.tsx +0 -10
  675. package/corpus/templates/crm/app/global.css +0 -167
  676. package/corpus/templates/crm/app/hooks/use-navigation-state.ts +0 -60
  677. package/corpus/templates/crm/app/i18n/en-US.ts +0 -89
  678. package/corpus/templates/crm/app/i18n/index.ts +0 -34
  679. package/corpus/templates/crm/app/lib/dashboard.ts +0 -13
  680. package/corpus/templates/crm/app/lib/navigation.ts +0 -54
  681. package/corpus/templates/crm/app/lib/tab-id.ts +0 -1
  682. package/corpus/templates/crm/app/lib/types.ts +0 -172
  683. package/corpus/templates/crm/app/lib/utils.ts +0 -1
  684. package/corpus/templates/crm/app/root.tsx +0 -88
  685. package/corpus/templates/crm/app/routes/_index.tsx +0 -26
  686. package/corpus/templates/crm/app/routes/accounts.tsx +0 -41
  687. package/corpus/templates/crm/app/routes/agent.tsx +0 -5
  688. package/corpus/templates/crm/app/routes/ask.tsx +0 -53
  689. package/corpus/templates/crm/app/routes/dashboard.tsx +0 -118
  690. package/corpus/templates/crm/app/routes/opportunities.tsx +0 -41
  691. package/corpus/templates/crm/app/routes/people.tsx +0 -41
  692. package/corpus/templates/crm/app/routes/proposals.tsx +0 -266
  693. package/corpus/templates/crm/app/routes/records.$recordId.tsx +0 -35
  694. package/corpus/templates/crm/app/routes/settings.tsx +0 -63
  695. package/corpus/templates/crm/app/routes/setup.tsx +0 -308
  696. package/corpus/templates/crm/app/routes/tasks.tsx +0 -252
  697. package/corpus/templates/crm/app/routes/views.tsx +0 -333
  698. package/corpus/templates/crm/app/routes.ts +0 -17
  699. package/corpus/templates/crm/app/vite-env.d.ts +0 -6
  700. package/corpus/templates/crm/changelog/2026-07-21-agent-native-crm.md +0 -6
  701. package/corpus/templates/crm/changelog/2026-07-21-clips-call-evidence-review-recipe.md +0 -6
  702. package/corpus/templates/crm/changelog/2026-07-21-crm-can-now-find-and-review-evidence-grounded-call-signals-w.md +0 -6
  703. package/corpus/templates/crm/changelog/2026-07-21-crm-can-now-manage-keyword-and-smart-call-signal-trackers-fr.md +0 -6
  704. package/corpus/templates/crm/changelog/2026-07-21-delegated-local-crm-automation.md +0 -6
  705. package/corpus/templates/crm/changelog/2026-07-21-native-sql.md +0 -6
  706. package/corpus/templates/crm/changelog/2026-07-21-pipeline-dashboard.md +0 -6
  707. package/corpus/templates/crm/changelog/2026-07-21-pipeline-dashboards-now-install-correctly-from-the-crm-actio.md +0 -6
  708. package/corpus/templates/crm/changelog/2026-07-21-salesforce-connection.md +0 -6
  709. package/corpus/templates/crm/changelog/2026-07-22-crm-field-validation-now-explains-which-fields-cannot-be-edi.md +0 -6
  710. package/corpus/templates/crm/changelog/2026-07-22-fixed-hubspot-contact-syncs-missing-records-updated-after-th.md +0 -6
  711. package/corpus/templates/crm/changelog/2026-07-22-fixed-pipeline-dashboard-panels-so-their-opportunity-data-lo.md +0 -6
  712. package/corpus/templates/crm/changelog/2026-07-22-full-page-chat-keeps-the-active-conversation-when-moving-to-.md +0 -6
  713. package/corpus/templates/crm/components.json +0 -20
  714. package/corpus/templates/crm/docs/architecture/crm-contract.md +0 -180
  715. package/corpus/templates/crm/learnings.defaults.md +0 -5
  716. package/corpus/templates/crm/package.json +0 -59
  717. package/corpus/templates/crm/public/favicon.svg +0 -1
  718. package/corpus/templates/crm/public/icon-180.svg +0 -1
  719. package/corpus/templates/crm/public/manifest.json +0 -11
  720. package/corpus/templates/crm/react-router.config.ts +0 -7
  721. package/corpus/templates/crm/server/crm/adapter.ts +0 -32
  722. package/corpus/templates/crm/server/crm/crm-field-firewall.ts +0 -64
  723. package/corpus/templates/crm/server/crm/crm-mirror.ts +0 -711
  724. package/corpus/templates/crm/server/crm/hubspot-adapter.ts +0 -1146
  725. package/corpus/templates/crm/server/crm/native-adapter.ts +0 -1715
  726. package/corpus/templates/crm/server/crm/read-through.ts +0 -207
  727. package/corpus/templates/crm/server/crm/salesforce-adapter.ts +0 -1255
  728. package/corpus/templates/crm/server/db/crm-store.ts +0 -1170
  729. package/corpus/templates/crm/server/db/index.ts +0 -169
  730. package/corpus/templates/crm/server/db/schema.ts +0 -441
  731. package/corpus/templates/crm/server/lib/intelligence/default-detectors.ts +0 -65
  732. package/corpus/templates/crm/server/lib/intelligence/evidence.ts +0 -105
  733. package/corpus/templates/crm/server/lib/intelligence/keyword-detector.ts +0 -100
  734. package/corpus/templates/crm/server/lib/intelligence/smart-detector.ts +0 -144
  735. package/corpus/templates/crm/server/lib/intelligence/summary.ts +0 -141
  736. package/corpus/templates/crm/server/lib/provider-api.ts +0 -64
  737. package/corpus/templates/crm/server/middleware/auth.ts +0 -4
  738. package/corpus/templates/crm/server/plugins/agent-chat.ts +0 -68
  739. package/corpus/templates/crm/server/plugins/auth.ts +0 -14
  740. package/corpus/templates/crm/server/plugins/core-routes.ts +0 -17
  741. package/corpus/templates/crm/server/plugins/db.ts +0 -454
  742. package/corpus/templates/crm/server/routes/[...page].get.ts +0 -5
  743. package/corpus/templates/crm/shared/crm-automation-recipes.ts +0 -132
  744. package/corpus/templates/crm/shared/crm-contract.ts +0 -254
  745. package/corpus/templates/crm/shared/crm-sales-config.ts +0 -63
  746. package/corpus/templates/crm/ssr-entry.ts +0 -11
  747. package/corpus/templates/crm/tsconfig.json +0 -24
  748. package/corpus/templates/crm/vite.config.ts +0 -15
  749. package/corpus/templates/crm/vitest.config.ts +0 -5
  750. package/corpus/templates/forms/app/components/ui/calendar.tsx +0 -214
  751. package/corpus/templates/forms/app/components/ui/chart.tsx +0 -379
  752. package/corpus/templates/forms/app/components/ui/command.tsx +0 -153
  753. package/corpus/templates/forms/app/components/ui/context-menu.tsx +0 -198
  754. package/corpus/templates/forms/app/components/ui/menubar.tsx +0 -254
  755. package/corpus/templates/macros/app/components/ui/menubar.tsx +0 -238
  756. package/corpus/templates/macros/app/components/ui/progress.tsx +0 -26
  757. package/corpus/templates/mail/app/components/ui/calendar.tsx +0 -211
  758. package/corpus/templates/mail/app/components/ui/chart.tsx +0 -379
  759. package/corpus/templates/mail/app/components/ui/command.tsx +0 -153
  760. package/corpus/templates/mail/app/components/ui/context-menu.tsx +0 -198
  761. package/corpus/templates/mail/app/components/ui/menubar.tsx +0 -254
  762. package/corpus/templates/tasks/app/components/ui/accordion.tsx +0 -56
  763. package/corpus/templates/tasks/app/components/ui/aspect-ratio.tsx +0 -5
  764. package/corpus/templates/tasks/app/components/ui/breadcrumb.tsx +0 -115
  765. package/corpus/templates/tasks/app/components/ui/calendar.tsx +0 -70
  766. package/corpus/templates/tasks/app/components/ui/carousel.tsx +0 -260
  767. package/corpus/templates/tasks/app/components/ui/chart.tsx +0 -379
  768. package/corpus/templates/tasks/app/components/ui/form.tsx +0 -177
  769. package/corpus/templates/tasks/app/components/ui/hover-card.tsx +0 -27
  770. package/corpus/templates/tasks/app/components/ui/input-otp.tsx +0 -69
  771. package/corpus/templates/tasks/app/components/ui/menubar.tsx +0 -254
  772. package/corpus/templates/tasks/app/components/ui/navigation-menu.tsx +0 -128
  773. package/corpus/templates/tasks/app/components/ui/pagination.tsx +0 -121
  774. package/corpus/templates/tasks/app/components/ui/resizable.tsx +0 -43
  775. package/corpus/templates/tasks/app/components/ui/sidebar.tsx +0 -782
  776. package/corpus/templates/tasks/app/components/ui/toggle.tsx +0 -43
@@ -1,1255 +0,0 @@
1
- import { resolveProviderApiOAuthAccessToken } from "@agent-native/core/provider-api";
2
- import {
3
- resolveWorkspaceConnectionCredentialForApp,
4
- resolveWorkspaceConnectionForApp,
5
- type ResolvedWorkspaceConnectionForApp,
6
- type WorkspaceConnectionForApp,
7
- } from "@agent-native/core/workspace-connections";
8
-
9
- import type {
10
- CrmAccessScope,
11
- CrmAdapter,
12
- CrmAdapterCapabilities,
13
- CrmConnectionRef,
14
- CrmFieldDefinition,
15
- CrmObjectDefinition,
16
- CrmObjectKind,
17
- CrmProvenance,
18
- CrmRecord,
19
- CrmRecordRef,
20
- CrmRelationship,
21
- CrmSyncPage,
22
- CrmValue,
23
- } from "../../shared/crm-contract.js";
24
-
25
- const CRM_APP_ID = "crm";
26
- const SALESFORCE_CREDENTIAL_KEYS = [
27
- "SALESFORCE_ACCESS_TOKEN",
28
- "SALESFORCE_OAUTH_TOKEN",
29
- ] as const;
30
- const CORE_OBJECT_TYPES = ["Account", "Contact", "Opportunity"] as const;
31
- const MAX_PAGE_SIZE = 200;
32
- const MAX_DISCOVERED_OBJECTS = 100;
33
- const DISCOVERY_CONCURRENCY = 5;
34
- const MAX_RETRY_ATTEMPTS = 3;
35
- const MAX_RETRY_DELAY_MS = 1_500;
36
- const MAX_SINGLE_RETRY_DELAY_MS = 1_000;
37
- const REQUEST_TIMEOUT_MS = 10_000;
38
- const DEFAULT_API_VERSION = "v60.0";
39
- const SAFE_OBJECT_NAME = /^[A-Za-z][A-Za-z0-9_]*$/;
40
- const SAFE_FIELD_NAME = /^[A-Za-z][A-Za-z0-9_]*$/;
41
-
42
- export interface SalesforceTransportRequest {
43
- path: string;
44
- method?: "GET" | "POST" | "PATCH" | "PUT" | "DELETE";
45
- body?: unknown;
46
- headers?: Record<string, string>;
47
- retrySafe?: boolean;
48
- }
49
-
50
- export interface SalesforceTransportResponse {
51
- status: number;
52
- body?: unknown;
53
- headers?: Record<string, string | undefined>;
54
- }
55
-
56
- export interface SalesforceTransport {
57
- request(
58
- input: SalesforceTransportRequest,
59
- ): Promise<SalesforceTransportResponse>;
60
- }
61
-
62
- export interface SalesforceCrmAdapterOptions {
63
- connection: WorkspaceConnectionForApp;
64
- transport: SalesforceTransport;
65
- }
66
-
67
- export interface CreateSalesforceCrmAdapterOptions {
68
- connectionId?: string;
69
- userEmail?: string;
70
- orgId?: string | null;
71
- transport?: SalesforceTransport;
72
- }
73
-
74
- type SalesforceField = {
75
- name?: string;
76
- label?: string;
77
- type?: string;
78
- accessible?: boolean;
79
- createable?: boolean;
80
- updateable?: boolean;
81
- nillable?: boolean;
82
- defaultedOnCreate?: boolean;
83
- calculated?: boolean;
84
- encrypted?: boolean;
85
- restrictedPicklist?: boolean;
86
- picklistValues?: Array<{
87
- value?: string;
88
- label?: string;
89
- active?: boolean;
90
- }>;
91
- referenceTo?: string[];
92
- relationshipName?: string;
93
- };
94
-
95
- type SalesforceObjectDescription = {
96
- name?: string;
97
- label?: string;
98
- labelPlural?: string;
99
- custom?: boolean;
100
- queryable?: boolean;
101
- searchable?: boolean;
102
- createable?: boolean;
103
- updateable?: boolean;
104
- deletable?: boolean;
105
- fields?: SalesforceField[];
106
- };
107
-
108
- type SalesforceGlobalObject = {
109
- name?: string;
110
- label?: string;
111
- custom?: boolean;
112
- queryable?: boolean;
113
- };
114
-
115
- type SalesforceRecord = Record<string, unknown> & {
116
- Id?: string;
117
- SystemModstamp?: string;
118
- LastModifiedDate?: string;
119
- IsDeleted?: boolean;
120
- };
121
-
122
- type SalesforceQueryResponse = {
123
- records?: SalesforceRecord[];
124
- done?: boolean;
125
- nextRecordsUrl?: string;
126
- };
127
-
128
- function nonEmpty(value: string | undefined | null): string | undefined {
129
- const trimmed = value?.trim();
130
- return trimmed || undefined;
131
- }
132
-
133
- function uniqueStrings(values: readonly string[]): string[] {
134
- return Array.from(
135
- new Set(values.map((value) => value.trim()).filter(Boolean)),
136
- );
137
- }
138
-
139
- function assertSafeObjectType(value: string): string {
140
- const objectType = nonEmpty(value);
141
- if (!objectType || !SAFE_OBJECT_NAME.test(objectType)) {
142
- throw new Error("Salesforce objectType contains unsupported characters.");
143
- }
144
- return objectType;
145
- }
146
-
147
- function safeFields(fields: readonly string[]): string[] {
148
- return uniqueStrings(fields).filter((field) => SAFE_FIELD_NAME.test(field));
149
- }
150
-
151
- function objectKind(objectType: string): CrmObjectKind {
152
- switch (objectType.toLowerCase()) {
153
- case "account":
154
- return "account";
155
- case "contact":
156
- case "lead":
157
- return "person";
158
- case "opportunity":
159
- return "opportunity";
160
- case "task":
161
- return "task";
162
- case "event":
163
- case "case":
164
- return "activity";
165
- default:
166
- return "custom";
167
- }
168
- }
169
-
170
- function displayFields(objectType: string): string[] {
171
- switch (objectType.toLowerCase()) {
172
- case "account":
173
- return ["Name", "Website"];
174
- case "contact":
175
- return ["FirstName", "LastName", "Email"];
176
- case "opportunity":
177
- return ["Name"];
178
- case "lead":
179
- return ["FirstName", "LastName", "Email"];
180
- default:
181
- return ["Name"];
182
- }
183
- }
184
-
185
- function searchField(objectType: string): string {
186
- switch (objectType.toLowerCase()) {
187
- case "task":
188
- case "event":
189
- case "case":
190
- return "Subject";
191
- default:
192
- return "Name";
193
- }
194
- }
195
-
196
- function fieldValueType(
197
- field: SalesforceField,
198
- ): CrmFieldDefinition["valueType"] {
199
- switch (field.type?.toLowerCase()) {
200
- case "boolean":
201
- return "boolean";
202
- case "currency":
203
- return "currency";
204
- case "percent":
205
- return "percent";
206
- case "double":
207
- case "int":
208
- case "long":
209
- return "number";
210
- case "date":
211
- return "date";
212
- case "datetime":
213
- case "time":
214
- return "datetime";
215
- case "picklist":
216
- return "enum";
217
- case "multipicklist":
218
- return "multi-enum";
219
- case "reference":
220
- return "reference";
221
- case "address":
222
- case "location":
223
- case "json":
224
- return "json";
225
- default:
226
- return "string";
227
- }
228
- }
229
-
230
- function isSensitiveField(field: SalesforceField): boolean {
231
- const name = field.name?.toLowerCase() ?? "";
232
- return (
233
- field.encrypted === true || /(password|secret|token|ssn|social)/.test(name)
234
- );
235
- }
236
-
237
- function scalarValue(value: unknown): CrmValue | undefined {
238
- if (
239
- value === null ||
240
- typeof value === "string" ||
241
- typeof value === "number" ||
242
- typeof value === "boolean"
243
- ) {
244
- return value;
245
- }
246
- if (Array.isArray(value)) {
247
- const entries = value.filter(
248
- (item): item is string | number | boolean | null =>
249
- item === null ||
250
- typeof item === "string" ||
251
- typeof item === "number" ||
252
- typeof item === "boolean",
253
- );
254
- return entries.length === value.length ? entries : undefined;
255
- }
256
- return undefined;
257
- }
258
-
259
- function encodedCursor(value: unknown): string {
260
- const bytes = new TextEncoder().encode(JSON.stringify(value));
261
- let binary = "";
262
- for (const byte of bytes) binary += String.fromCharCode(byte);
263
- return btoa(binary)
264
- .replace(/\+/g, "-")
265
- .replace(/\//g, "_")
266
- .replace(/=+$/, "");
267
- }
268
-
269
- function decodeCursor<T>(cursor: string | undefined): T | null {
270
- if (!cursor) return null;
271
- try {
272
- const padded = cursor
273
- .replace(/-/g, "+")
274
- .replace(/_/g, "/")
275
- .padEnd(Math.ceil(cursor.length / 4) * 4, "=");
276
- const binary = atob(padded);
277
- return JSON.parse(
278
- new TextDecoder().decode(
279
- Uint8Array.from(binary, (character) => character.charCodeAt(0)),
280
- ),
281
- ) as T;
282
- } catch {
283
- return null;
284
- }
285
- }
286
-
287
- function scopeAllows(
288
- connection: WorkspaceConnectionForApp,
289
- objectType: string,
290
- operation: "read" | "write",
291
- ): boolean {
292
- const scopes = [
293
- ...connection.scopes,
294
- ...(connection.explicitGrant?.scopes ?? []),
295
- ].map((scope) => scope.toLowerCase());
296
- if (scopes.length === 0) return operation === "read";
297
- const object = objectType.toLowerCase();
298
- return scopes.some(
299
- (scope) =>
300
- scope === "all" ||
301
- scope === "api" ||
302
- scope === "crm" ||
303
- scope === `crm.${operation}` ||
304
- scope === `crm.objects.${operation}` ||
305
- scope === `crm.objects.${object}.${operation}` ||
306
- (operation === "write" && scope.endsWith(".write")),
307
- );
308
- }
309
-
310
- function configurationValue(
311
- connection: WorkspaceConnectionForApp,
312
- keys: string[],
313
- ): string | undefined {
314
- const sources = [connection.explicitGrant?.config, connection.config];
315
- for (const source of sources) {
316
- for (const key of keys) {
317
- const value = source?.[key];
318
- if (typeof value === "string" && value.trim()) return value.trim();
319
- }
320
- }
321
- return undefined;
322
- }
323
-
324
- function resolveInstanceUrl(connection: WorkspaceConnectionForApp): string {
325
- const configured = configurationValue(connection, [
326
- "instanceUrl",
327
- "instance_url",
328
- "salesforceInstanceUrl",
329
- ]);
330
- if (!configured) {
331
- throw new Error(
332
- "Salesforce workspace connection is missing a trusted instance URL in connection metadata.",
333
- );
334
- }
335
- let url: URL;
336
- try {
337
- url = new URL(configured);
338
- } catch {
339
- throw new Error(
340
- "Salesforce workspace connection has an invalid instance URL.",
341
- );
342
- }
343
- const host = url.hostname.toLowerCase();
344
- const trustedHost =
345
- host === "salesforce.com" || host.endsWith(".salesforce.com");
346
- if (
347
- url.protocol !== "https:" ||
348
- !trustedHost ||
349
- url.port ||
350
- url.username ||
351
- url.password ||
352
- url.pathname !== "/" ||
353
- url.search ||
354
- url.hash
355
- ) {
356
- throw new Error(
357
- "Salesforce workspace connection must use an HTTPS Salesforce instance origin.",
358
- );
359
- }
360
- return url.origin;
361
- }
362
-
363
- function actorIdForConnection(connection: WorkspaceConnectionForApp): string {
364
- const identityUrl = configurationValue(connection, ["salesforceIdentityUrl"]);
365
- if (!identityUrl) return connection.ownerEmail;
366
- try {
367
- const url = new URL(identityUrl);
368
- const host = url.hostname.toLowerCase();
369
- const parts = url.pathname.split("/").filter(Boolean);
370
- const trustedHost =
371
- host === "salesforce.com" || host.endsWith(".salesforce.com");
372
- const organizationId = configurationValue(connection, [
373
- "salesforceOrganizationId",
374
- ]);
375
- if (
376
- url.protocol === "https:" &&
377
- trustedHost &&
378
- !url.port &&
379
- !url.username &&
380
- !url.password &&
381
- parts[0] === "id" &&
382
- parts[1] &&
383
- parts[2] &&
384
- (!organizationId || organizationId === parts[1])
385
- ) {
386
- return parts[2];
387
- }
388
- } catch {
389
- return connection.ownerEmail;
390
- }
391
- return connection.ownerEmail;
392
- }
393
-
394
- function resolveApiVersion(connection: WorkspaceConnectionForApp): string {
395
- const value = configurationValue(connection, [
396
- "apiVersion",
397
- "salesforceApiVersion",
398
- ]);
399
- return value && /^v\d{2}\.\d$/.test(value) ? value : DEFAULT_API_VERSION;
400
- }
401
-
402
- function hashPermissions(fields: SalesforceField[]): string | undefined {
403
- const values = fields
404
- .map((field) => {
405
- const name = nonEmpty(field.name);
406
- return name
407
- ? `${name}:${field.accessible === false ? 0 : 1}:${field.createable === true ? 1 : 0}:${field.updateable === true ? 1 : 0}`
408
- : "";
409
- })
410
- .filter(Boolean)
411
- .sort();
412
- if (!values.length) return undefined;
413
- let hash = 2_166_136_261;
414
- for (const character of values.join("|")) {
415
- hash ^= character.charCodeAt(0);
416
- hash = Math.imul(hash, 16_777_619);
417
- }
418
- return `sf-fp-${(hash >>> 0).toString(36)}`;
419
- }
420
-
421
- function stableFingerprint(value: string): string {
422
- let hash = 2_166_136_261;
423
- for (const character of value) {
424
- hash ^= character.charCodeAt(0);
425
- hash = Math.imul(hash, 16_777_619);
426
- }
427
- return (hash >>> 0).toString(36);
428
- }
429
-
430
- function accessScopeFor(
431
- connection: WorkspaceConnectionForApp,
432
- objectType: string,
433
- fields: SalesforceField[] = [],
434
- ): CrmAccessScope {
435
- const grantId = connection.appAccess.grantId ?? undefined;
436
- const oauthConnection =
437
- configurationValue(connection, ["credentialMode"]) === "oauth";
438
- const mode =
439
- oauthConnection ||
440
- [
441
- ...connection.credentialRefs,
442
- ...(connection.explicitGrant?.credentialRefs ?? []),
443
- ].some((ref) => ref.scope === "user")
444
- ? "user"
445
- : "service-account";
446
- const configuredVisibility = configurationValue(connection, [
447
- "recordVisibility",
448
- "record_visibility",
449
- ]);
450
- const recordVisibility =
451
- configuredVisibility === "actor" ||
452
- configuredVisibility === "cohort" ||
453
- configuredVisibility === "workspace"
454
- ? configuredVisibility
455
- : mode === "user"
456
- ? "actor"
457
- : "unknown";
458
- const sharingFingerprint =
459
- configurationValue(connection, [
460
- "sharingFingerprint",
461
- "sharing_fingerprint",
462
- ]) ??
463
- `sf-share-${stableFingerprint(
464
- `${connection.id}:${grantId ?? connection.appAccess.mode}:${objectType}:${recordVisibility}`,
465
- )}`;
466
- return {
467
- key: `${connection.id}:${grantId ?? connection.appAccess.mode}`,
468
- actorId:
469
- mode === "user"
470
- ? actorIdForConnection(connection)
471
- : connection.ownerEmail,
472
- grantId,
473
- mode,
474
- objectReadable: scopeAllows(connection, objectType, "read"),
475
- objectCreateable: scopeAllows(connection, objectType, "write"),
476
- objectUpdateable: scopeAllows(connection, objectType, "write"),
477
- objectDeleteable: false,
478
- recordVisibility,
479
- ...(hashPermissions(fields)
480
- ? { fieldPermissionsHash: hashPermissions(fields) }
481
- : {}),
482
- sharingFingerprint,
483
- };
484
- }
485
-
486
- function definitionFrom(
487
- connection: WorkspaceConnectionForApp,
488
- objectType: string,
489
- description: SalesforceObjectDescription,
490
- ): CrmObjectDefinition {
491
- const fields = description.fields ?? [];
492
- const scope = accessScopeFor(connection, objectType, fields);
493
- return {
494
- connectionId: connection.id,
495
- provider: "salesforce",
496
- ...(connection.accountId ? { accountId: connection.accountId } : {}),
497
- actorId: actorIdForConnection(connection),
498
- objectType,
499
- kind: objectKind(objectType),
500
- label: description.label || objectType,
501
- pluralLabel: description.labelPlural || description.label || objectType,
502
- custom: description.custom === true || objectType.endsWith("__c"),
503
- queryable: description.queryable !== false && scope.objectReadable,
504
- searchable: description.searchable !== false && scope.objectReadable,
505
- createable: description.createable === true && scope.objectCreateable,
506
- updateable: description.updateable === true && scope.objectUpdateable,
507
- deleteable: false,
508
- fields: fields
509
- .map((field): CrmFieldDefinition | null => {
510
- const name = nonEmpty(field.name);
511
- if (!name) return null;
512
- const sensitive = isSensitiveField(field);
513
- return {
514
- name,
515
- label: field.label || name,
516
- valueType: fieldValueType(field),
517
- storagePolicy: sensitive ? "redacted" : "remote-only",
518
- sensitive,
519
- readable:
520
- field.accessible !== false && !sensitive && scope.objectReadable,
521
- createable:
522
- !sensitive &&
523
- field.createable === true &&
524
- field.calculated !== true &&
525
- scope.objectCreateable,
526
- updateable:
527
- !sensitive &&
528
- field.updateable === true &&
529
- field.calculated !== true &&
530
- scope.objectUpdateable,
531
- required:
532
- field.nillable === false &&
533
- field.defaultedOnCreate !== true &&
534
- field.calculated !== true,
535
- ...(field.picklistValues
536
- ? {
537
- options: field.picklistValues
538
- .filter((option) => nonEmpty(option.value))
539
- .map((option) => ({
540
- value: option.value!.trim(),
541
- label: option.label || option.value!.trim(),
542
- ...(option.active === false ? { active: false } : {}),
543
- })),
544
- }
545
- : {}),
546
- ...(field.referenceTo?.[0]
547
- ? { referencedObjectType: field.referenceTo[0] }
548
- : {}),
549
- };
550
- })
551
- .filter((field): field is CrmFieldDefinition => field !== null),
552
- };
553
- }
554
-
555
- function recordRef(
556
- connection: WorkspaceConnectionForApp,
557
- objectType: string,
558
- remoteId: string,
559
- ): CrmRecordRef {
560
- return {
561
- connectionId: connection.id,
562
- provider: "salesforce",
563
- ...(connection.accountId ? { accountId: connection.accountId } : {}),
564
- actorId: actorIdForConnection(connection),
565
- objectType,
566
- kind: objectKind(objectType),
567
- remoteId,
568
- };
569
- }
570
-
571
- function projectRecord(
572
- connection: WorkspaceConnectionForApp,
573
- objectType: string,
574
- source: SalesforceRecord,
575
- fields: string[],
576
- definition?: SalesforceObjectDescription,
577
- ): CrmRecord | null {
578
- const remoteId = nonEmpty(source.Id);
579
- if (!remoteId) return null;
580
- const allowed = safeFields(fields);
581
- const values: Record<string, CrmValue> = {};
582
- for (const field of allowed) {
583
- const value = scalarValue(source[field]);
584
- if (value !== undefined) values[field] = value;
585
- }
586
- const displayName =
587
- displayFields(objectType)
588
- .map((field) => values[field])
589
- .filter(
590
- (value): value is string | number | boolean =>
591
- typeof value === "string" ||
592
- typeof value === "number" ||
593
- typeof value === "boolean",
594
- )
595
- .map(String)
596
- .filter(Boolean)
597
- .join(" ") || remoteId;
598
- const remoteRevision =
599
- nonEmpty(source.SystemModstamp) ?? nonEmpty(source.LastModifiedDate);
600
- const observedAt = new Date().toISOString();
601
- return {
602
- ref: recordRef(connection, objectType, remoteId),
603
- displayName,
604
- fields: values,
605
- ...(remoteRevision
606
- ? { remoteRevision, remoteUpdatedAt: remoteRevision }
607
- : {}),
608
- deleted: source.IsDeleted === true,
609
- accessScope: accessScopeFor(connection, objectType, definition?.fields),
610
- provenance: Object.keys(values).map((fieldName) => ({
611
- provider: "salesforce",
612
- connectionId: connection.id,
613
- objectType,
614
- remoteId,
615
- fieldName,
616
- ...(remoteRevision ? { remoteRevision } : {}),
617
- observedAt,
618
- })),
619
- };
620
- }
621
-
622
- function soqlString(value: string): string {
623
- return `'${value.replace(/\\/g, "\\\\").replace(/'/g, "\\'")}'`;
624
- }
625
-
626
- function soqlDateTime(value: string): string | undefined {
627
- const timestamp = Date.parse(value);
628
- return Number.isNaN(timestamp)
629
- ? undefined
630
- : new Date(timestamp).toISOString();
631
- }
632
-
633
- function queryPath(query: string, includeDeleted = false): string {
634
- return `/query${includeDeleted ? "All" : ""}?q=${encodeURIComponent(query)}`;
635
- }
636
-
637
- function headerValue(
638
- headers: Record<string, string | undefined> | undefined,
639
- name: string,
640
- ): string | undefined {
641
- if (!headers) return undefined;
642
- const expected = name.toLowerCase();
643
- return Object.entries(headers).find(
644
- ([key]) => key.toLowerCase() === expected,
645
- )?.[1];
646
- }
647
-
648
- export function salesforceRetryDelayMs(
649
- response: SalesforceTransportResponse,
650
- attempt: number,
651
- elapsedMs: number,
652
- now = Date.now(),
653
- ): number {
654
- const retryAfter = headerValue(response.headers, "retry-after")?.trim();
655
- const numeric = retryAfter ? Number(retryAfter) : Number.NaN;
656
- const requested = Number.isFinite(numeric)
657
- ? Math.max(0, numeric * 1_000)
658
- : retryAfter
659
- ? Math.max(0, Date.parse(retryAfter) - now)
660
- : 100 * 2 ** attempt;
661
- return Math.max(
662
- 0,
663
- Math.min(
664
- requested,
665
- MAX_SINGLE_RETRY_DELAY_MS,
666
- MAX_RETRY_DELAY_MS - elapsedMs,
667
- ),
668
- );
669
- }
670
-
671
- class SalesforceApiError extends Error {
672
- constructor(
673
- readonly status: number,
674
- message: string,
675
- ) {
676
- super(message);
677
- }
678
- }
679
-
680
- function salesforceErrorMessage(status: number): string {
681
- if (status === 401 || status === 403)
682
- return "Salesforce authentication or authorization failed.";
683
- if (status === 404) return "Salesforce resource was not found.";
684
- if (status === 429) return "Salesforce rate limit exceeded.";
685
- if (status >= 500) return "Salesforce service is temporarily unavailable.";
686
- return "Salesforce request failed.";
687
- }
688
-
689
- function isNotFound(error: unknown): boolean {
690
- return error instanceof SalesforceApiError && error.status === 404;
691
- }
692
-
693
- function isSafeContinuation(path: string): boolean {
694
- return /^\/services\/data\/v\d{2}\.\d\/query(?:All)?\/.+/.test(path);
695
- }
696
-
697
- function assertOwnedRecord(
698
- connection: WorkspaceConnectionForApp,
699
- record: CrmRecordRef,
700
- ): void {
701
- if (
702
- record.provider !== "salesforce" ||
703
- record.connectionId !== connection.id
704
- ) {
705
- throw new Error(
706
- "Salesforce record does not belong to this workspace connection.",
707
- );
708
- }
709
- }
710
-
711
- class FetchSalesforceTransport implements SalesforceTransport {
712
- constructor(
713
- private readonly instanceOrigin: string,
714
- private readonly apiVersion: string,
715
- private readonly accessToken: string,
716
- ) {}
717
-
718
- async request(
719
- input: SalesforceTransportRequest,
720
- ): Promise<SalesforceTransportResponse> {
721
- const path = input.path.startsWith("/services/data/")
722
- ? input.path
723
- : `/services/data/${this.apiVersion}${input.path}`;
724
- const response = await fetch(`${this.instanceOrigin}${path}`, {
725
- method: input.method ?? "GET",
726
- signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS),
727
- headers: {
728
- Authorization: `Bearer ${this.accessToken}`,
729
- ...(input.body === undefined
730
- ? {}
731
- : { "Content-Type": "application/json" }),
732
- ...input.headers,
733
- },
734
- ...(input.body === undefined ? {} : { body: JSON.stringify(input.body) }),
735
- });
736
- const text = await response.text();
737
- let body: unknown;
738
- if (text) {
739
- try {
740
- body = JSON.parse(text);
741
- } catch {
742
- body = text;
743
- }
744
- }
745
- return {
746
- status: response.status,
747
- body,
748
- headers: {
749
- "retry-after": response.headers.get("retry-after") ?? undefined,
750
- },
751
- };
752
- }
753
- }
754
-
755
- export class SalesforceCrmAdapter implements CrmAdapter {
756
- readonly connection: CrmConnectionRef;
757
- readonly capabilities: CrmAdapterCapabilities = {
758
- schemaDiscovery: true,
759
- customObjects: true,
760
- search: true,
761
- incrementalSync: true,
762
- deletedRecordSync: true,
763
- conditionalMutations: false,
764
- labeledRelationships: true,
765
- perFieldPermissions: true,
766
- perRecordPermissions: true,
767
- };
768
-
769
- private readonly descriptions = new Map<
770
- string,
771
- SalesforceObjectDescription
772
- >();
773
-
774
- constructor(private readonly options: SalesforceCrmAdapterOptions) {
775
- this.connection = {
776
- connectionId: options.connection.id,
777
- provider: "salesforce",
778
- ...(options.connection.accountId
779
- ? { accountId: options.connection.accountId }
780
- : {}),
781
- actorId: actorIdForConnection(options.connection),
782
- };
783
- }
784
-
785
- private get workspaceConnection(): WorkspaceConnectionForApp {
786
- return this.options.connection;
787
- }
788
-
789
- private async request<T>(input: SalesforceTransportRequest): Promise<T> {
790
- const readRetrySafe =
791
- input.retrySafe === true ||
792
- input.method === undefined ||
793
- input.method === "GET";
794
- let elapsedDelayMs = 0;
795
- for (let attempt = 0; attempt < MAX_RETRY_ATTEMPTS; attempt++) {
796
- const response = await this.options.transport.request(input);
797
- if (response.status >= 200 && response.status < 300) {
798
- return (response.body ?? {}) as T;
799
- }
800
- const retryable =
801
- attempt + 1 < MAX_RETRY_ATTEMPTS &&
802
- readRetrySafe &&
803
- (response.status === 429 || response.status >= 500) &&
804
- elapsedDelayMs < MAX_RETRY_DELAY_MS;
805
- if (!retryable) {
806
- throw new SalesforceApiError(
807
- response.status,
808
- `Salesforce API error ${response.status}: ${salesforceErrorMessage(response.status)}`,
809
- );
810
- }
811
- const delay = salesforceRetryDelayMs(response, attempt, elapsedDelayMs);
812
- if (delay > 0) {
813
- await new Promise<void>((resolve) => setTimeout(resolve, delay));
814
- elapsedDelayMs += delay;
815
- }
816
- }
817
- throw new Error("Salesforce retry budget was exhausted.");
818
- }
819
-
820
- private async describe(
821
- objectType: string,
822
- ): Promise<SalesforceObjectDescription> {
823
- const normalized = assertSafeObjectType(objectType);
824
- const cached = this.descriptions.get(normalized);
825
- if (cached) return cached;
826
- const description = await this.request<SalesforceObjectDescription>({
827
- path: `/sobjects/${encodeURIComponent(normalized)}/describe`,
828
- });
829
- this.descriptions.set(normalized, description);
830
- return description;
831
- }
832
-
833
- async discoverObjects(): Promise<CrmObjectDefinition[]> {
834
- const global = await this.request<{ sobjects?: SalesforceGlobalObject[] }>({
835
- path: "/sobjects/",
836
- });
837
- const types = uniqueStrings([
838
- ...CORE_OBJECT_TYPES,
839
- ...(global.sobjects ?? [])
840
- .filter((object) => object.queryable !== false)
841
- .map((object) => object.name ?? ""),
842
- ])
843
- .filter((type) => SAFE_OBJECT_NAME.test(type))
844
- .slice(0, MAX_DISCOVERED_OBJECTS);
845
- const definitions: CrmObjectDefinition[] = [];
846
- for (let index = 0; index < types.length; index += DISCOVERY_CONCURRENCY) {
847
- definitions.push(
848
- ...(await Promise.all(
849
- types
850
- .slice(index, index + DISCOVERY_CONCURRENCY)
851
- .map((type) => this.describeObject(type)),
852
- )),
853
- );
854
- }
855
- return definitions;
856
- }
857
-
858
- async describeObject(objectType: string): Promise<CrmObjectDefinition> {
859
- const normalized = assertSafeObjectType(objectType);
860
- const description = await this.describe(normalized);
861
- return definitionFrom(this.workspaceConnection, normalized, description);
862
- }
863
-
864
- async getAccessScope(objectType: string): Promise<CrmAccessScope> {
865
- const normalized = assertSafeObjectType(objectType);
866
- const description = await this.describe(normalized);
867
- return accessScopeFor(
868
- this.workspaceConnection,
869
- normalized,
870
- description?.fields,
871
- );
872
- }
873
-
874
- private async query(path: string): Promise<SalesforceQueryResponse> {
875
- return this.request<SalesforceQueryResponse>({ path });
876
- }
877
-
878
- private selectFields(fields: string[]): string[] {
879
- return uniqueStrings([
880
- "Id",
881
- "SystemModstamp",
882
- "LastModifiedDate",
883
- "IsDeleted",
884
- ...safeFields(fields),
885
- ]);
886
- }
887
-
888
- private scopeWhere(input: {
889
- objectType: string;
890
- pipelineIds?: string[];
891
- ownerIds?: string[];
892
- updatedAfter?: string;
893
- }): string[] {
894
- const filters: string[] = [];
895
- if (input.objectType === "Opportunity" && input.pipelineIds?.length) {
896
- const ids = uniqueStrings(input.pipelineIds).map(soqlString);
897
- if (ids.length) filters.push(`RecordTypeId IN (${ids.join(",")})`);
898
- }
899
- if (input.ownerIds?.length) {
900
- const ids = uniqueStrings(input.ownerIds).map(soqlString);
901
- if (ids.length) filters.push(`OwnerId IN (${ids.join(",")})`);
902
- }
903
- const updatedAfter = input.updatedAfter
904
- ? soqlDateTime(input.updatedAfter)
905
- : undefined;
906
- if (updatedAfter) filters.push(`SystemModstamp >= ${updatedAfter}`);
907
- return filters;
908
- }
909
-
910
- async syncPage(
911
- input: Parameters<CrmAdapter["syncPage"]>[0],
912
- ): Promise<CrmSyncPage> {
913
- const objectType = assertSafeObjectType(input.scope.objectType);
914
- if (input.scope.associatedRecordIds?.length) {
915
- throw new Error(
916
- "Salesforce associated-record cohorts are not enabled; scope the sync with recordIds, ownerIds, or Opportunity record-type IDs.",
917
- );
918
- }
919
- const limit = Math.max(1, Math.min(MAX_PAGE_SIZE, input.limit));
920
- const fields = safeFields(input.fieldAllowList);
921
- const description = await this.describe(objectType);
922
- const recordIds = uniqueStrings(input.scope.recordIds ?? []);
923
- const cursor = decodeCursor<{ index?: number; next?: string }>(
924
- input.cursor,
925
- );
926
- let page: SalesforceQueryResponse;
927
- let nextCursor: string | undefined;
928
- if (cursor?.next && isSafeContinuation(cursor.next)) {
929
- page = await this.query(cursor.next);
930
- nextCursor =
931
- page.nextRecordsUrl && isSafeContinuation(page.nextRecordsUrl)
932
- ? encodedCursor({ next: page.nextRecordsUrl })
933
- : undefined;
934
- } else if (recordIds.length) {
935
- const index = Math.max(0, Math.min(cursor?.index ?? 0, recordIds.length));
936
- const ids = recordIds.slice(index, index + limit).map(soqlString);
937
- if (!ids.length)
938
- return { records: [], relationships: [], complete: true };
939
- page = await this.query(
940
- queryPath(
941
- `SELECT ${this.selectFields(fields).join(",")} FROM ${objectType} WHERE Id IN (${ids.join(",")}) LIMIT ${limit}`,
942
- input.scope.includeDeleted,
943
- ),
944
- );
945
- const offset = index + limit;
946
- nextCursor =
947
- offset < recordIds.length
948
- ? encodedCursor({ index: offset })
949
- : undefined;
950
- } else {
951
- const where = this.scopeWhere({ ...input.scope, objectType });
952
- page = await this.query(
953
- queryPath(
954
- `SELECT ${this.selectFields(fields).join(",")} FROM ${objectType}${where.length ? ` WHERE ${where.join(" AND ")}` : ""} ORDER BY SystemModstamp ASC, Id ASC LIMIT ${limit}`,
955
- input.scope.includeDeleted,
956
- ),
957
- );
958
- nextCursor =
959
- page.nextRecordsUrl && isSafeContinuation(page.nextRecordsUrl)
960
- ? encodedCursor({ next: page.nextRecordsUrl })
961
- : undefined;
962
- }
963
- const records = (page.records ?? [])
964
- .map((record) =>
965
- projectRecord(
966
- this.workspaceConnection,
967
- objectType,
968
- record,
969
- fields,
970
- description,
971
- ),
972
- )
973
- .filter((record): record is CrmRecord => record !== null);
974
- return {
975
- records,
976
- relationships: [],
977
- ...(nextCursor ? { nextCursor } : {}),
978
- complete: !nextCursor,
979
- };
980
- }
981
-
982
- async getRecord(
983
- input: Parameters<CrmAdapter["getRecord"]>[0],
984
- ): Promise<CrmRecord | null> {
985
- assertOwnedRecord(this.workspaceConnection, input.record);
986
- const objectType = assertSafeObjectType(input.record.objectType);
987
- const description = await this.describe(objectType);
988
- const fields = safeFields(input.fields);
989
- try {
990
- const record = await this.request<SalesforceRecord>({
991
- path: `/sobjects/${encodeURIComponent(objectType)}/${encodeURIComponent(input.record.remoteId)}?fields=${encodeURIComponent(this.selectFields(fields).join(","))}`,
992
- });
993
- return projectRecord(
994
- this.workspaceConnection,
995
- objectType,
996
- record,
997
- fields,
998
- description,
999
- );
1000
- } catch (error) {
1001
- if (isNotFound(error)) return null;
1002
- throw error;
1003
- }
1004
- }
1005
-
1006
- async search(
1007
- input: Parameters<CrmAdapter["search"]>[0],
1008
- ): Promise<CrmSyncPage> {
1009
- const objectTypes = uniqueStrings(input.objectTypes).filter((type) =>
1010
- SAFE_OBJECT_NAME.test(type),
1011
- );
1012
- if (!objectTypes.length)
1013
- return { records: [], relationships: [], complete: true };
1014
- const state = decodeCursor<{ index?: number; next?: string }>(input.cursor);
1015
- const index = Math.max(
1016
- 0,
1017
- Math.min(state?.index ?? 0, objectTypes.length - 1),
1018
- );
1019
- const objectType = objectTypes[index]!;
1020
- const fields = safeFields(input.fields);
1021
- const limit = Math.max(1, Math.min(MAX_PAGE_SIZE, input.limit));
1022
- const description = await this.describe(objectType);
1023
- const page =
1024
- state?.next && isSafeContinuation(state.next)
1025
- ? await this.query(state.next)
1026
- : await this.query(
1027
- queryPath(
1028
- `SELECT ${this.selectFields(fields).join(",")} FROM ${objectType} WHERE ${searchField(objectType)} LIKE ${soqlString(`%${input.query.trim()}%`)} ORDER BY SystemModstamp DESC, Id ASC LIMIT ${limit}`,
1029
- ),
1030
- );
1031
- const records = (page.records ?? [])
1032
- .map((record) =>
1033
- projectRecord(
1034
- this.workspaceConnection,
1035
- objectType,
1036
- record,
1037
- fields,
1038
- description,
1039
- ),
1040
- )
1041
- .filter((record): record is CrmRecord => record !== null);
1042
- const nextCursor =
1043
- page.nextRecordsUrl && isSafeContinuation(page.nextRecordsUrl)
1044
- ? encodedCursor({ index, next: page.nextRecordsUrl })
1045
- : index + 1 < objectTypes.length
1046
- ? encodedCursor({ index: index + 1 })
1047
- : undefined;
1048
- return {
1049
- records,
1050
- relationships: [],
1051
- ...(nextCursor ? { nextCursor } : {}),
1052
- complete: !nextCursor,
1053
- };
1054
- }
1055
-
1056
- async listRelationships(
1057
- input: Parameters<CrmAdapter["listRelationships"]>[0],
1058
- ): Promise<{
1059
- relationships: CrmRelationship[];
1060
- nextCursor?: string;
1061
- complete: boolean;
1062
- }> {
1063
- assertOwnedRecord(this.workspaceConnection, input.record);
1064
- const objectType = assertSafeObjectType(input.record.objectType);
1065
- const description = await this.describe(objectType);
1066
- const targets = new Set(uniqueStrings(input.targetObjectTypes ?? []));
1067
- const state = decodeCursor<{ index?: number }>(input.cursor);
1068
- const fields = (description.fields ?? []).filter(
1069
- (field) =>
1070
- field.type === "reference" &&
1071
- field.accessible !== false &&
1072
- field.name &&
1073
- (!targets.size ||
1074
- field.referenceTo?.some((target) => targets.has(target))),
1075
- );
1076
- const start = Math.max(0, Math.min(state?.index ?? 0, fields.length));
1077
- const boundedFields = fields.slice(
1078
- start,
1079
- start + Math.max(1, Math.min(MAX_PAGE_SIZE, input.limit)),
1080
- );
1081
- if (!boundedFields.length) return { relationships: [], complete: true };
1082
- const record = await this.request<SalesforceRecord>({
1083
- path: `/sobjects/${encodeURIComponent(objectType)}/${encodeURIComponent(input.record.remoteId)}?fields=${encodeURIComponent(["Id", ...boundedFields.map((field) => field.name!)].join(","))}`,
1084
- });
1085
- const relationships = boundedFields.flatMap((field): CrmRelationship[] => {
1086
- const remoteId = scalarValue(record[field.name!]);
1087
- const target = field.referenceTo?.[0];
1088
- if (typeof remoteId !== "string" || !target) return [];
1089
- return [
1090
- {
1091
- from: input.record,
1092
- to: recordRef(this.workspaceConnection, target, remoteId),
1093
- relationshipType: field.name!,
1094
- ...(field.label ? { label: field.label } : {}),
1095
- },
1096
- ];
1097
- });
1098
- const nextCursor =
1099
- start + boundedFields.length < fields.length
1100
- ? encodedCursor({ index: start + boundedFields.length })
1101
- : undefined;
1102
- return {
1103
- relationships,
1104
- ...(nextCursor ? { nextCursor } : {}),
1105
- complete: !nextCursor,
1106
- };
1107
- }
1108
-
1109
- async applyMutation(mutation: Parameters<CrmAdapter["applyMutation"]>[0]) {
1110
- assertOwnedRecord(this.workspaceConnection, mutation.record);
1111
- if (!mutation.idempotencyKey.trim()) {
1112
- return {
1113
- status: "rejected" as const,
1114
- message: "An idempotency key is required.",
1115
- };
1116
- }
1117
- if (mutation.operation === "delete") {
1118
- return {
1119
- status: "rejected" as const,
1120
- message:
1121
- "Salesforce deletion is disabled during the initial CRM transport rollout.",
1122
- };
1123
- }
1124
- if (
1125
- mutation.operation === "associate" ||
1126
- mutation.operation === "disassociate"
1127
- ) {
1128
- return {
1129
- status: "rejected" as const,
1130
- message:
1131
- "Salesforce association mutation requires an explicit relationship definition and is not enabled in the initial rollout.",
1132
- };
1133
- }
1134
- if (
1135
- !scopeAllows(
1136
- this.workspaceConnection,
1137
- mutation.record.objectType,
1138
- "write",
1139
- )
1140
- ) {
1141
- return {
1142
- status: "rejected" as const,
1143
- message:
1144
- "The workspace connection does not prove write access for this Salesforce object.",
1145
- };
1146
- }
1147
- if (mutation.operation === "create") {
1148
- return {
1149
- status: "rejected" as const,
1150
- message:
1151
- "Salesforce creation is disabled because this adapter cannot guarantee an atomic idempotent create.",
1152
- };
1153
- }
1154
- if (!mutation.expectedRemoteRevision) {
1155
- return {
1156
- status: "rejected" as const,
1157
- message: "Salesforce mutations require a current remote revision.",
1158
- };
1159
- }
1160
- const current = await this.getRecord({
1161
- record: mutation.record,
1162
- fields: [],
1163
- });
1164
- if (
1165
- !current ||
1166
- current.remoteRevision !== mutation.expectedRemoteRevision
1167
- ) {
1168
- return {
1169
- status: "conflict" as const,
1170
- ...(current?.remoteRevision
1171
- ? { remoteRevision: current.remoteRevision }
1172
- : {}),
1173
- message:
1174
- "The Salesforce record changed before this mutation could be applied.",
1175
- };
1176
- }
1177
- return {
1178
- status: "rejected" as const,
1179
- remoteRevision: current.remoteRevision,
1180
- message:
1181
- "Salesforce does not support an atomic conditional update through this CRM adapter.",
1182
- };
1183
- }
1184
- }
1185
-
1186
- function requireResolvedConnection(
1187
- result: ResolvedWorkspaceConnectionForApp,
1188
- ): WorkspaceConnectionForApp {
1189
- if (!result.available || !result.connection) {
1190
- throw new Error(
1191
- `Salesforce workspace connection is unavailable: ${result.reason}`,
1192
- );
1193
- }
1194
- return result.connection;
1195
- }
1196
-
1197
- export async function createSalesforceCrmAdapter(
1198
- options: CreateSalesforceCrmAdapterOptions = {},
1199
- ): Promise<SalesforceCrmAdapter> {
1200
- const resolved = await resolveWorkspaceConnectionForApp({
1201
- appId: CRM_APP_ID,
1202
- provider: "salesforce",
1203
- ...(options.connectionId ? { connectionId: options.connectionId } : {}),
1204
- requireConnected: true,
1205
- });
1206
- const connection = requireResolvedConnection(resolved);
1207
- if (options.transport) {
1208
- return new SalesforceCrmAdapter({
1209
- connection,
1210
- transport: options.transport,
1211
- });
1212
- }
1213
- const instanceUrl = resolveInstanceUrl(connection);
1214
- try {
1215
- const oauth = await resolveProviderApiOAuthAccessToken(
1216
- { provider: "salesforce", connectionId: connection.id },
1217
- { appId: CRM_APP_ID, providerIds: ["salesforce"] },
1218
- );
1219
- if (oauth.connectionId === connection.id && oauth.accessToken) {
1220
- return new SalesforceCrmAdapter({
1221
- connection,
1222
- transport: new FetchSalesforceTransport(
1223
- instanceUrl,
1224
- resolveApiVersion(connection),
1225
- oauth.accessToken,
1226
- ),
1227
- });
1228
- }
1229
- } catch {
1230
- // Manual bearer credentials remain supported for non-OAuth connections.
1231
- }
1232
- for (const key of SALESFORCE_CREDENTIAL_KEYS) {
1233
- const credential = await resolveWorkspaceConnectionCredentialForApp({
1234
- appId: CRM_APP_ID,
1235
- provider: "salesforce",
1236
- key,
1237
- connectionId: connection.id,
1238
- ...(options.userEmail ? { userEmail: options.userEmail } : {}),
1239
- ...(options.orgId !== undefined ? { orgId: options.orgId } : {}),
1240
- });
1241
- if (!credential.available || !credential.value) continue;
1242
- if (credential.provenance?.connectionId !== connection.id) continue;
1243
- return new SalesforceCrmAdapter({
1244
- connection,
1245
- transport: new FetchSalesforceTransport(
1246
- instanceUrl,
1247
- resolveApiVersion(connection),
1248
- credential.value,
1249
- ),
1250
- });
1251
- }
1252
- throw new Error(
1253
- "Salesforce workspace connection is unavailable: no scoped credential was resolved for the granted connection.",
1254
- );
1255
- }