@agent-native/core 0.103.1 → 0.104.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (565) hide show
  1. package/corpus/README.md +2 -2
  2. package/corpus/core/CHANGELOG.md +30 -0
  3. package/corpus/core/package.json +9 -2
  4. package/corpus/core/src/agent/engine/credential-errors.ts +2 -2
  5. package/corpus/core/src/agent/production-agent.ts +30 -0
  6. package/corpus/core/src/agent/run-store.ts +12 -2
  7. package/corpus/core/src/cli/create.ts +1 -0
  8. package/corpus/core/src/cli/skills-content/visual-plan-skill.ts +30 -11
  9. package/corpus/core/src/cli/templates-meta.ts +4 -3
  10. package/corpus/core/src/client/AgentAskPopover.tsx +89 -0
  11. package/corpus/core/src/client/AgentChatHome.tsx +4 -0
  12. package/corpus/core/src/client/AgentPanel.tsx +321 -223
  13. package/corpus/core/src/client/AssistantChat.tsx +6 -10
  14. package/corpus/core/src/client/MultiTabAssistantChat.tsx +53 -372
  15. package/corpus/core/src/client/agent-chat-adapter.ts +13 -1
  16. package/corpus/core/src/client/agent-page/AgentContextTab.tsx +133 -149
  17. package/corpus/core/src/client/agent-page/AgentEmptyState.tsx +44 -0
  18. package/corpus/core/src/client/agent-page/AgentJobsTab.tsx +153 -82
  19. package/corpus/core/src/client/agent-page/AgentTabFrame.tsx +39 -0
  20. package/corpus/core/src/client/agent-page/AgentTabsPage.tsx +368 -356
  21. package/corpus/core/src/client/agent-page/types.ts +1 -1
  22. package/corpus/core/src/client/analytics.ts +51 -5
  23. package/corpus/core/src/client/chat/run-recovery.tsx +12 -4
  24. package/corpus/core/src/client/composer/PromptComposer.tsx +5 -15
  25. package/corpus/core/src/client/composer/TiptapComposer.tsx +32 -3
  26. package/corpus/core/src/client/dynamic-suggestions.ts +3 -3
  27. package/corpus/core/src/client/index.ts +16 -1
  28. package/corpus/core/src/client/resources/ResourceTree.tsx +249 -38
  29. package/corpus/core/src/client/resources/ResourcesPanel.tsx +307 -140
  30. package/corpus/core/src/client/session-replay.ts +158 -5
  31. package/corpus/core/src/client/settings/AutomationsSection.tsx +30 -10
  32. package/corpus/core/src/client/settings/SettingsPanel.tsx +3 -2
  33. package/corpus/core/src/client/settings/SettingsTabsPage.tsx +2 -0
  34. package/corpus/core/src/client/settings/agent-settings-search.ts +2 -2
  35. package/corpus/core/src/client/use-chat-threads.ts +2 -0
  36. package/corpus/core/src/connections/catalog.ts +49 -7
  37. package/corpus/core/src/db/index.ts +6 -1
  38. package/corpus/core/src/extensions/actions.ts +106 -16
  39. package/corpus/core/src/extensions/content-patch.ts +22 -0
  40. package/corpus/core/src/extensions/routes.ts +18 -0
  41. package/corpus/core/src/extensions/store.ts +8 -0
  42. package/corpus/core/src/index.ts +3 -0
  43. package/corpus/core/src/ingestion/docx.ts +158 -0
  44. package/corpus/core/src/ingestion/figma-node-to-html.ts +1860 -0
  45. package/corpus/core/src/ingestion/figma.ts +548 -0
  46. package/corpus/core/src/ingestion/index.ts +107 -0
  47. package/corpus/core/src/ingestion/media.ts +264 -0
  48. package/corpus/core/src/ingestion/notion.ts +121 -0
  49. package/corpus/core/src/ingestion/office.ts +214 -0
  50. package/corpus/core/src/ingestion/orchestration.ts +160 -0
  51. package/corpus/core/src/ingestion/pptx.ts +333 -0
  52. package/corpus/core/src/ingestion/selection.ts +81 -0
  53. package/corpus/core/src/ingestion/website.ts +151 -0
  54. package/corpus/core/src/integrations/plugin.ts +45 -37
  55. package/corpus/core/src/localization/default-messages.ts +35 -12
  56. package/corpus/core/src/observability/hosted-model-experiment.ts +118 -0
  57. package/corpus/core/src/observability/traces.ts +5 -3
  58. package/corpus/core/src/provider-api/index.ts +452 -8
  59. package/corpus/core/src/scripts/agent-engines/list-agent-engines.ts +18 -1
  60. package/corpus/core/src/search-utils/index.ts +112 -0
  61. package/corpus/core/src/secrets/register-framework-secrets.ts +61 -0
  62. package/corpus/core/src/server/action-discovery.ts +33 -8
  63. package/corpus/core/src/server/agent-chat/framework-prompts.ts +2 -2
  64. package/corpus/core/src/server/agent-chat/prompt-resources.ts +144 -0
  65. package/corpus/core/src/server/agent-chat-plugin.ts +6 -0
  66. package/corpus/core/src/server/core-routes-plugin.ts +12 -0
  67. package/corpus/core/src/server/index.ts +30 -0
  68. package/corpus/core/src/server/workspace-provider-oauth.ts +583 -0
  69. package/corpus/core/src/styles/agent-native.css +9 -0
  70. package/corpus/core/src/templates/default/app/i18n/en-US.ts +3 -3
  71. package/corpus/core/src/templates/workspace-core/.agents/skills/extensions/SKILL.md +14 -5
  72. package/corpus/core/src/templates/workspace-root/.env.example +12 -0
  73. package/corpus/core/src/workspace-connections/index.ts +6 -0
  74. package/corpus/core/src/workspace-connections/lifecycle.ts +43 -0
  75. package/corpus/core/src/workspace-connections/store.ts +16 -0
  76. package/corpus/templates/analytics/.agents/skills/dashboard-management/SKILL.md +46 -3
  77. package/corpus/templates/analytics/AGENTS.md +9 -0
  78. package/corpus/templates/analytics/actions/dashboard-mutation-api.ts +120 -6
  79. package/corpus/templates/analytics/actions/mutate-dashboard.ts +92 -30
  80. package/corpus/templates/analytics/actions/update-dashboard.ts +5 -5
  81. package/corpus/templates/analytics/app/components/dashboard/SqlChart.tsx +313 -220
  82. package/corpus/templates/analytics/app/components/layout/CommandPalette.tsx +2 -2
  83. package/corpus/templates/analytics/app/components/layout/Layout.tsx +9 -6
  84. package/corpus/templates/analytics/app/components/layout/Sidebar.tsx +90 -64
  85. package/corpus/templates/analytics/app/i18n-data.ts +3 -3
  86. package/corpus/templates/analytics/app/lib/dashboard-list-loading.ts +25 -0
  87. package/corpus/templates/analytics/app/lib/item-popularity.ts +13 -4
  88. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/DashboardFilterBar.tsx +1 -1
  89. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/pivot.ts +8 -3
  90. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/types.ts +1 -0
  91. package/corpus/templates/analytics/app/pages/sessions/SessionDetailPage.tsx +15 -3
  92. package/corpus/templates/analytics/changelog/2026-07-16-dashboard-filter-defaults-can-now-be-changed-reliably-withou.md +6 -0
  93. package/corpus/templates/analytics/changelog/2026-07-16-dashboard-lists-load-in-one-stable-order-without-popping-bet.md +6 -0
  94. package/corpus/templates/analytics/changelog/2026-07-16-fixed-dashboard-filter-dropdown-text-alignment.md +6 -0
  95. package/corpus/templates/analytics/changelog/2026-07-16-recurring-signed-in-users-can-now-be-viewed-as-weekly-bars-b.md +6 -0
  96. package/corpus/templates/analytics/changelog/2026-07-16-the-analytics-agent-can-now-duplicate-a-chart-and-place-the-.md +6 -0
  97. package/corpus/templates/analytics/seeds/dashboards/agent-native-templates-first-party.json +41 -1
  98. package/corpus/templates/analytics/server/lib/dashboard-catalog.ts +1 -1
  99. package/corpus/templates/analytics/server/lib/first-party-metric-catalog.ts +47 -1
  100. package/corpus/templates/analytics/server/lib/session-replay.ts +68 -0
  101. package/corpus/templates/analytics/server/plugins/agent-chat.ts +1 -0
  102. package/corpus/templates/analytics/server/routes/sessions/lookup.get.ts +47 -0
  103. package/corpus/templates/assets/.agents/skills/asset-generation/SKILL.md +16 -9
  104. package/corpus/templates/assets/.agents/skills/creative-context/SKILL.md +86 -0
  105. package/corpus/templates/assets/AGENTS.md +10 -0
  106. package/corpus/templates/assets/actions/create-generation-session.ts +59 -1
  107. package/corpus/templates/assets/actions/edit-image.ts +2 -0
  108. package/corpus/templates/assets/actions/generate-asset.ts +52 -0
  109. package/corpus/templates/assets/actions/generate-image-batch.ts +55 -0
  110. package/corpus/templates/assets/actions/generate-image.ts +219 -1
  111. package/corpus/templates/assets/actions/open-asset-picker.ts +14 -0
  112. package/corpus/templates/assets/actions/refine-image.ts +3 -0
  113. package/corpus/templates/assets/actions/restyle-image.ts +2 -0
  114. package/corpus/templates/assets/agent-native.app-skill.json +4 -0
  115. package/corpus/templates/assets/app/components/layout/Layout.tsx +2 -0
  116. package/corpus/templates/assets/app/i18n/zh-TW.ts +3 -0
  117. package/corpus/templates/assets/app/i18n-data.ts +29 -13
  118. package/corpus/templates/assets/app/routes/agent.tsx +7 -1
  119. package/corpus/templates/assets/app/routes/library.tsx +9 -0
  120. package/corpus/templates/assets/app/routes/settings.tsx +3 -0
  121. package/corpus/templates/assets/changelog/2026-07-16-creative-context-library.md +6 -0
  122. package/corpus/templates/assets/package.json +1 -0
  123. package/corpus/templates/assets/server/lib/image-processing.ts +1 -22
  124. package/corpus/templates/assets/server/plugins/creative-context.ts +205 -0
  125. package/corpus/templates/brain/app/i18n-data.ts +3 -3
  126. package/corpus/templates/brain/app/lib/brain.ts +1 -1
  127. package/corpus/templates/brain/server/lib/search.ts +17 -67
  128. package/corpus/templates/calendar/app/i18n-data.ts +3 -3
  129. package/corpus/templates/calendar/app/pages/BookingLinksPage.tsx +19 -18
  130. package/corpus/templates/chat/app/i18n/en-US.ts +3 -3
  131. package/corpus/templates/chat/app/lib/agent-page.tsx +10 -1
  132. package/corpus/templates/clips/.agents/skills/meetings/SKILL.md +1 -1
  133. package/corpus/templates/clips/AGENTS.md +4 -0
  134. package/corpus/templates/clips/actions/cleanup-transcript.ts +35 -4
  135. package/corpus/templates/clips/actions/create-meeting.ts +6 -2
  136. package/corpus/templates/clips/actions/create-organization.ts +3 -2
  137. package/corpus/templates/clips/actions/create-recording.ts +4 -1
  138. package/corpus/templates/clips/actions/finalize-recording.ts +44 -7
  139. package/corpus/templates/clips/actions/import-loom-recording.ts +4 -1
  140. package/corpus/templates/clips/actions/lib/create-recording-schema.ts +2 -2
  141. package/corpus/templates/clips/actions/list-meetings.ts +23 -5
  142. package/corpus/templates/clips/actions/list-organization-state.ts +1 -1
  143. package/corpus/templates/clips/actions/remove-silences.ts +10 -1
  144. package/corpus/templates/clips/actions/request-transcript.ts +53 -11
  145. package/corpus/templates/clips/actions/search-recordings-utils.ts +7 -0
  146. package/corpus/templates/clips/actions/search-recordings.ts +5 -8
  147. package/corpus/templates/clips/actions/set-organization-branding.ts +2 -2
  148. package/corpus/templates/clips/actions/stitch-recordings.ts +10 -5
  149. package/corpus/templates/clips/actions/update-ai-request-status.ts +38 -0
  150. package/corpus/templates/clips/app/components/editor/editor-layout.tsx +3 -4
  151. package/corpus/templates/clips/app/components/editor/editor-selection.ts +19 -0
  152. package/corpus/templates/clips/app/components/editor/stitch-manager.tsx +10 -10
  153. package/corpus/templates/clips/app/components/library/bulk-action-toolbar.tsx +1 -2
  154. package/corpus/templates/clips/app/components/library/library-grid.tsx +101 -93
  155. package/corpus/templates/clips/app/components/player/video-player.tsx +11 -0
  156. package/corpus/templates/clips/app/components/workspace/branding-editor.tsx +53 -1
  157. package/corpus/templates/clips/app/i18n/ar-SA.ts +7 -1
  158. package/corpus/templates/clips/app/i18n/de-DE.ts +7 -1
  159. package/corpus/templates/clips/app/i18n/en-US.ts +10 -4
  160. package/corpus/templates/clips/app/i18n/es-ES.ts +7 -1
  161. package/corpus/templates/clips/app/i18n/fr-FR.ts +7 -1
  162. package/corpus/templates/clips/app/i18n/hi-IN.ts +7 -1
  163. package/corpus/templates/clips/app/i18n/ja-JP.ts +7 -1
  164. package/corpus/templates/clips/app/i18n/ko-KR.ts +7 -1
  165. package/corpus/templates/clips/app/i18n/pt-BR.ts +7 -1
  166. package/corpus/templates/clips/app/i18n/zh-CN.ts +6 -1
  167. package/corpus/templates/clips/app/i18n/zh-TW.ts +6 -1
  168. package/corpus/templates/clips/app/routes/_app.settings._index.tsx +5 -9
  169. package/corpus/templates/clips/app/routes/_app.settings.organization.tsx +6 -2
  170. package/corpus/templates/clips/app/routes/r.$recordingId.tsx +129 -27
  171. package/corpus/templates/clips/app/routes/record.tsx +23 -2
  172. package/corpus/templates/clips/app/routes/share.$shareId.tsx +6 -2
  173. package/corpus/templates/clips/changelog/2026-07-16-authorized-viewers-can-open-shared-private-clips-without-a-m.md +6 -0
  174. package/corpus/templates/clips/changelog/2026-07-16-camera-bubble-hover-controls-appear-above-the-face.md +6 -0
  175. package/corpus/templates/clips/changelog/2026-07-16-chrome-extension-recovers-stale-recorder-state.md +6 -0
  176. package/corpus/templates/clips/changelog/2026-07-16-clips-agent-chat-no-longer-shows-a-separate-workspace-header.md +6 -0
  177. package/corpus/templates/clips/changelog/2026-07-16-clips-search-now-matches-recording-content-without-requiring.md +6 -0
  178. package/corpus/templates/clips/changelog/2026-07-16-declined-meetings-no-longer-show-desktop-reminders.md +6 -0
  179. package/corpus/templates/clips/changelog/2026-07-16-failed-desktop-saves-now-show-their-local-recovery-copy.md +6 -0
  180. package/corpus/templates/clips/changelog/2026-07-16-long-desktop-clips-now-preserve-complete-playback-synced-aud.md +6 -0
  181. package/corpus/templates/clips/changelog/2026-07-16-long-recording-lists-keep-stitch-and-library-actions-visible.md +6 -0
  182. package/corpus/templates/clips/changelog/2026-07-16-organization-admins-can-choose-new-recording-visibility.md +6 -0
  183. package/corpus/templates/clips/changelog/2026-07-16-remove-silences-now-shows-queued-active-completed-and-failed.md +6 -0
  184. package/corpus/templates/clips/changelog/2026-07-16-settings-no-longer-repeats-the-builder-connection-status-in-.md +6 -0
  185. package/corpus/templates/clips/changelog/2026-07-16-transcripts-now-appear-from-native-browser-speech-sooner-wit.md +6 -0
  186. package/corpus/templates/clips/chrome-extension/public/manifest.json +1 -1
  187. package/corpus/templates/clips/chrome-extension/src/background.ts +73 -1
  188. package/corpus/templates/clips/chrome-extension/src/native-recording-state.ts +32 -0
  189. package/corpus/templates/clips/chrome-extension/src/native-transcription.ts +248 -0
  190. package/corpus/templates/clips/chrome-extension/src/offscreen.ts +106 -0
  191. package/corpus/templates/clips/desktop/src/app.tsx +66 -28
  192. package/corpus/templates/clips/desktop/src/lib/recorder.ts +335 -285
  193. package/corpus/templates/clips/desktop/src/lib/single-flight.ts +7 -0
  194. package/corpus/templates/clips/desktop/src/lib/upload-verification.ts +51 -0
  195. package/corpus/templates/clips/desktop/src/overlays/bubble.tsx +2 -2
  196. package/corpus/templates/clips/desktop/src/overlays/finalizing.tsx +10 -2
  197. package/corpus/templates/clips/desktop/src/styles.css +13 -11
  198. package/corpus/templates/clips/desktop/src-tauri/src/clips/mod.rs +8 -9
  199. package/corpus/templates/clips/desktop/src-tauri/src/meetings_watcher.rs +1 -0
  200. package/corpus/templates/clips/desktop/src-tauri/src/native_screen/custom_capture.rs +88 -13
  201. package/corpus/templates/clips/desktop/src-tauri/src/native_screen/live_upload.rs +13 -2
  202. package/corpus/templates/clips/desktop/src-tauri/src/native_screen.rs +241 -6
  203. package/corpus/templates/clips/server/db/schema.ts +2 -2
  204. package/corpus/templates/clips/server/lib/builder-media-compression.ts +64 -67
  205. package/corpus/templates/clips/server/lib/calendar-event-classification.ts +19 -0
  206. package/corpus/templates/clips/server/lib/google-calendar-client.ts +1 -0
  207. package/corpus/templates/clips/server/lib/recordings.ts +40 -1
  208. package/corpus/templates/clips/server/plugins/agent-chat.ts +1 -0
  209. package/corpus/templates/clips/server/plugins/db.ts +2 -2
  210. package/corpus/templates/clips/server/routes/api/auth/google-calendar.get.ts +1 -1
  211. package/corpus/templates/clips/server/routes/api/public-recording.get.ts +14 -5
  212. package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/chunk.post.ts +51 -1
  213. package/corpus/templates/clips/server/routes/api/video/[recordingId].get.ts +1 -64
  214. package/corpus/templates/clips/shared/media-worker-contract.ts +32 -15
  215. package/corpus/templates/content/.agents/skills/content/SKILL.md +16 -0
  216. package/corpus/templates/content/.agents/skills/creative-context/SKILL.md +85 -0
  217. package/corpus/templates/content/.agents/skills/notion-integration/SKILL.md +8 -0
  218. package/corpus/templates/content/AGENTS.md +9 -0
  219. package/corpus/templates/content/actions/create-document.ts +94 -0
  220. package/corpus/templates/content/actions/edit-document.ts +144 -4
  221. package/corpus/templates/content/actions/update-document.ts +138 -0
  222. package/corpus/templates/content/agent-native.app-skill.json +4 -0
  223. package/corpus/templates/content/app/components/layout/Layout.tsx +2 -0
  224. package/corpus/templates/content/app/i18n/zh-TW.ts +3 -0
  225. package/corpus/templates/content/app/i18n-data.ts +13 -4
  226. package/corpus/templates/content/app/routes/_app.agent.tsx +2 -1
  227. package/corpus/templates/content/app/routes/_app.settings.tsx +3 -0
  228. package/corpus/templates/content/changelog/2026-07-16-creative-context-library.md +6 -0
  229. package/corpus/templates/content/package.json +1 -0
  230. package/corpus/templates/content/server/plugins/creative-context.ts +31 -0
  231. package/corpus/templates/design/.agents/skills/creative-context/SKILL.md +116 -0
  232. package/corpus/templates/design/.agents/skills/design-generation/SKILL.md +16 -0
  233. package/corpus/templates/design/.agents/skills/design-systems/SKILL.md +8 -0
  234. package/corpus/templates/design/AGENTS.md +6 -0
  235. package/corpus/templates/design/actions/clone-creative-context-design.ts +176 -0
  236. package/corpus/templates/design/actions/edit-design.ts +128 -0
  237. package/corpus/templates/design/actions/generate-design.ts +278 -14
  238. package/corpus/templates/design/actions/generate-screens.ts +42 -1
  239. package/corpus/templates/design/agent-native.app-skill.json +4 -0
  240. package/corpus/templates/design/app/components/layout/Layout.tsx +7 -3
  241. package/corpus/templates/design/app/i18n/zh-TW.ts +3 -0
  242. package/corpus/templates/design/app/i18n-data.ts +10 -4
  243. package/corpus/templates/design/app/routes/agent.tsx +2 -1
  244. package/corpus/templates/design/app/routes/settings.tsx +3 -0
  245. package/corpus/templates/design/changelog/2026-07-16-creative-context-library.md +6 -0
  246. package/corpus/templates/design/changelog/2026-07-16-design-agent-chat-no-longer-shows-a-separate-workspace-header.md +6 -0
  247. package/corpus/templates/design/package.json +1 -0
  248. package/corpus/templates/design/server/lib/figma-design-context.ts +5 -335
  249. package/corpus/templates/design/server/lib/figma-node-to-html.ts +1 -1859
  250. package/corpus/templates/design/server/lib/import-design-files.ts +6 -8
  251. package/corpus/templates/design/server/plugins/creative-context.ts +31 -0
  252. package/corpus/templates/design/shared/generation-session.ts +7 -0
  253. package/corpus/templates/dispatch/app/i18n-data.ts +3 -3
  254. package/corpus/templates/forms/app/i18n/en-US.ts +3 -3
  255. package/corpus/templates/macros/app/i18n/en-US.ts +3 -3
  256. package/corpus/templates/mail/app/components/email/EmailThread.tsx +35 -5
  257. package/corpus/templates/mail/app/i18n/en-US.ts +3 -3
  258. package/corpus/templates/mail/changelog/2026-07-16-mail-previews-now-expand-to-show-the-full-message-without-an.md +6 -0
  259. package/corpus/templates/plan/.agents/skills/visual-plan/SKILL.md +30 -11
  260. package/corpus/templates/plan/AGENTS.md +21 -1
  261. package/corpus/templates/plan/actions/get-visual-plan.ts +1 -1
  262. package/corpus/templates/plan/actions/patch-visual-plan-source.ts +161 -0
  263. package/corpus/templates/plan/actions/read-visual-plan-source.ts +1 -1
  264. package/corpus/templates/plan/actions/update-visual-plan.ts +126 -10
  265. package/corpus/templates/plan/app/hooks/use-plans.ts +2 -0
  266. package/corpus/templates/plan/app/i18n/en-US.ts +3 -3
  267. package/corpus/templates/plan/app/pages/PlansPage.tsx +65 -62
  268. package/corpus/templates/plan/changelog/2026-07-16-local-plan-previews-now-load-annotations-containing-html-lik.md +6 -0
  269. package/corpus/templates/plan/changelog/2026-07-16-plan-agents-now-prevent-stale-edits-from-overwriting-newer-p.md +6 -0
  270. package/corpus/templates/plan/server/plan-mdx.ts +75 -2
  271. package/corpus/templates/slides/.agents/skills/create-deck/SKILL.md +21 -4
  272. package/corpus/templates/slides/.agents/skills/creative-context/SKILL.md +122 -0
  273. package/corpus/templates/slides/.agents/skills/design-systems/SKILL.md +11 -0
  274. package/corpus/templates/slides/.agents/skills/slide-editing/SKILL.md +12 -3
  275. package/corpus/templates/slides/AGENTS.md +6 -0
  276. package/corpus/templates/slides/actions/add-slide.ts +230 -14
  277. package/corpus/templates/slides/actions/clone-context-slide.ts +302 -0
  278. package/corpus/templates/slides/actions/create-deck.ts +130 -0
  279. package/corpus/templates/slides/actions/extract-pdf.ts +6 -2
  280. package/corpus/templates/slides/actions/import-file.ts +5 -4
  281. package/corpus/templates/slides/actions/patch-deck.ts +200 -10
  282. package/corpus/templates/slides/actions/update-slide.ts +208 -15
  283. package/corpus/templates/slides/app/components/layout/Layout.tsx +2 -0
  284. package/corpus/templates/slides/app/components/visual-editor/CanvasCommentPins.tsx +16 -1
  285. package/corpus/templates/slides/app/i18n/ar-SA.ts +3 -0
  286. package/corpus/templates/slides/app/i18n/de-DE.ts +3 -0
  287. package/corpus/templates/slides/app/i18n/en-US.ts +6 -3
  288. package/corpus/templates/slides/app/i18n/es-ES.ts +3 -0
  289. package/corpus/templates/slides/app/i18n/fr-FR.ts +3 -0
  290. package/corpus/templates/slides/app/i18n/hi-IN.ts +3 -0
  291. package/corpus/templates/slides/app/i18n/ja-JP.ts +3 -0
  292. package/corpus/templates/slides/app/i18n/ko-KR.ts +3 -0
  293. package/corpus/templates/slides/app/i18n/pt-BR.ts +3 -0
  294. package/corpus/templates/slides/app/i18n/zh-CN.ts +3 -0
  295. package/corpus/templates/slides/app/i18n/zh-TW.ts +3 -0
  296. package/corpus/templates/slides/app/lib/validate-native-slide-html.ts +176 -0
  297. package/corpus/templates/slides/app/routes/agent.tsx +7 -1
  298. package/corpus/templates/slides/app/routes/settings.tsx +3 -0
  299. package/corpus/templates/slides/changelog/2026-07-16-creative-context-library.md +6 -0
  300. package/corpus/templates/slides/changelog/2026-07-16-google-slides-native-cloning.md +6 -0
  301. package/corpus/templates/slides/package.json +1 -0
  302. package/corpus/templates/slides/server/handlers/import/docx-parser.ts +4 -85
  303. package/corpus/templates/slides/server/handlers/import/pptx-parser.ts +7 -421
  304. package/corpus/templates/slides/server/plugins/creative-context.ts +166 -0
  305. package/dist/agent/engine/credential-errors.d.ts +1 -1
  306. package/dist/agent/engine/credential-errors.d.ts.map +1 -1
  307. package/dist/agent/engine/credential-errors.js +2 -2
  308. package/dist/agent/engine/credential-errors.js.map +1 -1
  309. package/dist/agent/production-agent.d.ts.map +1 -1
  310. package/dist/agent/production-agent.js +25 -0
  311. package/dist/agent/production-agent.js.map +1 -1
  312. package/dist/agent/run-store.d.ts.map +1 -1
  313. package/dist/agent/run-store.js +12 -2
  314. package/dist/agent/run-store.js.map +1 -1
  315. package/dist/cli/create.d.ts.map +1 -1
  316. package/dist/cli/create.js +1 -0
  317. package/dist/cli/create.js.map +1 -1
  318. package/dist/cli/skills-content/visual-plan-skill.d.ts +1 -1
  319. package/dist/cli/skills-content/visual-plan-skill.d.ts.map +1 -1
  320. package/dist/cli/skills-content/visual-plan-skill.js +30 -11
  321. package/dist/cli/skills-content/visual-plan-skill.js.map +1 -1
  322. package/dist/cli/templates-meta.d.ts.map +1 -1
  323. package/dist/cli/templates-meta.js +4 -3
  324. package/dist/cli/templates-meta.js.map +1 -1
  325. package/dist/client/AgentAskPopover.d.ts +11 -0
  326. package/dist/client/AgentAskPopover.d.ts.map +1 -0
  327. package/dist/client/AgentAskPopover.js +30 -0
  328. package/dist/client/AgentAskPopover.js.map +1 -0
  329. package/dist/client/AgentChatHome.d.ts +1 -1
  330. package/dist/client/AgentChatHome.d.ts.map +1 -1
  331. package/dist/client/AgentChatHome.js +2 -2
  332. package/dist/client/AgentChatHome.js.map +1 -1
  333. package/dist/client/AgentPanel.d.ts +9 -19
  334. package/dist/client/AgentPanel.d.ts.map +1 -1
  335. package/dist/client/AgentPanel.js +119 -80
  336. package/dist/client/AgentPanel.js.map +1 -1
  337. package/dist/client/AssistantChat.d.ts.map +1 -1
  338. package/dist/client/AssistantChat.js +4 -4
  339. package/dist/client/AssistantChat.js.map +1 -1
  340. package/dist/client/MultiTabAssistantChat.d.ts +3 -9
  341. package/dist/client/MultiTabAssistantChat.d.ts.map +1 -1
  342. package/dist/client/MultiTabAssistantChat.js +49 -189
  343. package/dist/client/MultiTabAssistantChat.js.map +1 -1
  344. package/dist/client/agent-chat-adapter.d.ts.map +1 -1
  345. package/dist/client/agent-chat-adapter.js +12 -1
  346. package/dist/client/agent-chat-adapter.js.map +1 -1
  347. package/dist/client/agent-page/AgentContextTab.d.ts.map +1 -1
  348. package/dist/client/agent-page/AgentContextTab.js +26 -28
  349. package/dist/client/agent-page/AgentContextTab.js.map +1 -1
  350. package/dist/client/agent-page/AgentEmptyState.d.ts +13 -0
  351. package/dist/client/agent-page/AgentEmptyState.d.ts.map +1 -0
  352. package/dist/client/agent-page/AgentEmptyState.js +6 -0
  353. package/dist/client/agent-page/AgentEmptyState.js.map +1 -0
  354. package/dist/client/agent-page/AgentJobsTab.d.ts +1 -1
  355. package/dist/client/agent-page/AgentJobsTab.d.ts.map +1 -1
  356. package/dist/client/agent-page/AgentJobsTab.js +90 -58
  357. package/dist/client/agent-page/AgentJobsTab.js.map +1 -1
  358. package/dist/client/agent-page/AgentTabFrame.d.ts +12 -0
  359. package/dist/client/agent-page/AgentTabFrame.d.ts.map +1 -0
  360. package/dist/client/agent-page/AgentTabFrame.js +7 -0
  361. package/dist/client/agent-page/AgentTabFrame.js.map +1 -0
  362. package/dist/client/agent-page/AgentTabsPage.d.ts +9 -1
  363. package/dist/client/agent-page/AgentTabsPage.d.ts.map +1 -1
  364. package/dist/client/agent-page/AgentTabsPage.js +135 -99
  365. package/dist/client/agent-page/AgentTabsPage.js.map +1 -1
  366. package/dist/client/agent-page/types.d.ts +1 -1
  367. package/dist/client/agent-page/types.d.ts.map +1 -1
  368. package/dist/client/agent-page/types.js.map +1 -1
  369. package/dist/client/analytics.d.ts +10 -3
  370. package/dist/client/analytics.d.ts.map +1 -1
  371. package/dist/client/analytics.js +37 -2
  372. package/dist/client/analytics.js.map +1 -1
  373. package/dist/client/chat/run-recovery.d.ts.map +1 -1
  374. package/dist/client/chat/run-recovery.js +10 -3
  375. package/dist/client/chat/run-recovery.js.map +1 -1
  376. package/dist/client/composer/PromptComposer.d.ts.map +1 -1
  377. package/dist/client/composer/PromptComposer.js +2 -2
  378. package/dist/client/composer/PromptComposer.js.map +1 -1
  379. package/dist/client/composer/TiptapComposer.d.ts.map +1 -1
  380. package/dist/client/composer/TiptapComposer.js +15 -3
  381. package/dist/client/composer/TiptapComposer.js.map +1 -1
  382. package/dist/client/dynamic-suggestions.js +3 -3
  383. package/dist/client/dynamic-suggestions.js.map +1 -1
  384. package/dist/client/index.d.ts +4 -3
  385. package/dist/client/index.d.ts.map +1 -1
  386. package/dist/client/index.js +3 -2
  387. package/dist/client/index.js.map +1 -1
  388. package/dist/client/resources/ResourceTree.d.ts +5 -1
  389. package/dist/client/resources/ResourceTree.d.ts.map +1 -1
  390. package/dist/client/resources/ResourceTree.js +74 -5
  391. package/dist/client/resources/ResourceTree.js.map +1 -1
  392. package/dist/client/resources/ResourcesPanel.d.ts +11 -2
  393. package/dist/client/resources/ResourcesPanel.d.ts.map +1 -1
  394. package/dist/client/resources/ResourcesPanel.js +105 -31
  395. package/dist/client/resources/ResourcesPanel.js.map +1 -1
  396. package/dist/client/session-replay.d.ts +28 -0
  397. package/dist/client/session-replay.d.ts.map +1 -1
  398. package/dist/client/session-replay.js +122 -8
  399. package/dist/client/session-replay.js.map +1 -1
  400. package/dist/client/settings/AutomationsSection.d.ts +3 -1
  401. package/dist/client/settings/AutomationsSection.d.ts.map +1 -1
  402. package/dist/client/settings/AutomationsSection.js +16 -6
  403. package/dist/client/settings/AutomationsSection.js.map +1 -1
  404. package/dist/client/settings/SettingsPanel.d.ts.map +1 -1
  405. package/dist/client/settings/SettingsPanel.js +3 -3
  406. package/dist/client/settings/SettingsPanel.js.map +1 -1
  407. package/dist/client/settings/SettingsTabsPage.d.ts +2 -0
  408. package/dist/client/settings/SettingsTabsPage.d.ts.map +1 -1
  409. package/dist/client/settings/SettingsTabsPage.js.map +1 -1
  410. package/dist/client/settings/agent-settings-search.js +2 -2
  411. package/dist/client/settings/agent-settings-search.js.map +1 -1
  412. package/dist/client/use-chat-threads.d.ts +2 -0
  413. package/dist/client/use-chat-threads.d.ts.map +1 -1
  414. package/dist/client/use-chat-threads.js.map +1 -1
  415. package/dist/collab/routes.d.ts +1 -1
  416. package/dist/connections/catalog.d.ts +41 -7
  417. package/dist/connections/catalog.d.ts.map +1 -1
  418. package/dist/connections/catalog.js +40 -7
  419. package/dist/connections/catalog.js.map +1 -1
  420. package/dist/db/index.d.ts +2 -2
  421. package/dist/db/index.d.ts.map +1 -1
  422. package/dist/db/index.js +2 -2
  423. package/dist/db/index.js.map +1 -1
  424. package/dist/extensions/actions.d.ts.map +1 -1
  425. package/dist/extensions/actions.js +85 -15
  426. package/dist/extensions/actions.js.map +1 -1
  427. package/dist/extensions/content-patch.d.ts +4 -0
  428. package/dist/extensions/content-patch.d.ts.map +1 -1
  429. package/dist/extensions/content-patch.js +18 -0
  430. package/dist/extensions/content-patch.js.map +1 -1
  431. package/dist/extensions/routes.d.ts.map +1 -1
  432. package/dist/extensions/routes.js +14 -0
  433. package/dist/extensions/routes.js.map +1 -1
  434. package/dist/extensions/store.d.ts +1 -0
  435. package/dist/extensions/store.d.ts.map +1 -1
  436. package/dist/extensions/store.js +4 -1
  437. package/dist/extensions/store.js.map +1 -1
  438. package/dist/file-upload/actions/upload-image.d.ts +1 -1
  439. package/dist/index.d.ts +1 -1
  440. package/dist/index.d.ts.map +1 -1
  441. package/dist/index.js +1 -1
  442. package/dist/index.js.map +1 -1
  443. package/dist/ingestion/docx.d.ts +16 -0
  444. package/dist/ingestion/docx.d.ts.map +1 -0
  445. package/dist/ingestion/docx.js +129 -0
  446. package/dist/ingestion/docx.js.map +1 -0
  447. package/dist/ingestion/figma-node-to-html.d.ts +304 -0
  448. package/dist/ingestion/figma-node-to-html.d.ts.map +1 -0
  449. package/dist/ingestion/figma-node-to-html.js +1292 -0
  450. package/dist/ingestion/figma-node-to-html.js.map +1 -0
  451. package/dist/ingestion/figma.d.ts +115 -0
  452. package/dist/ingestion/figma.d.ts.map +1 -0
  453. package/dist/ingestion/figma.js +399 -0
  454. package/dist/ingestion/figma.js.map +1 -0
  455. package/dist/ingestion/index.d.ts +11 -0
  456. package/dist/ingestion/index.d.ts.map +1 -0
  457. package/dist/ingestion/index.js +11 -0
  458. package/dist/ingestion/index.js.map +1 -0
  459. package/dist/ingestion/media.d.ts +36 -0
  460. package/dist/ingestion/media.d.ts.map +1 -0
  461. package/dist/ingestion/media.js +178 -0
  462. package/dist/ingestion/media.js.map +1 -0
  463. package/dist/ingestion/notion.d.ts +12 -0
  464. package/dist/ingestion/notion.d.ts.map +1 -0
  465. package/dist/ingestion/notion.js +104 -0
  466. package/dist/ingestion/notion.js.map +1 -0
  467. package/dist/ingestion/office.d.ts +45 -0
  468. package/dist/ingestion/office.d.ts.map +1 -0
  469. package/dist/ingestion/office.js +141 -0
  470. package/dist/ingestion/office.js.map +1 -0
  471. package/dist/ingestion/orchestration.d.ts +52 -0
  472. package/dist/ingestion/orchestration.d.ts.map +1 -0
  473. package/dist/ingestion/orchestration.js +89 -0
  474. package/dist/ingestion/orchestration.js.map +1 -0
  475. package/dist/ingestion/pptx.d.ts +28 -0
  476. package/dist/ingestion/pptx.d.ts.map +1 -0
  477. package/dist/ingestion/pptx.js +255 -0
  478. package/dist/ingestion/pptx.js.map +1 -0
  479. package/dist/ingestion/selection.d.ts +20 -0
  480. package/dist/ingestion/selection.d.ts.map +1 -0
  481. package/dist/ingestion/selection.js +52 -0
  482. package/dist/ingestion/selection.js.map +1 -0
  483. package/dist/ingestion/website.d.ts +27 -0
  484. package/dist/ingestion/website.d.ts.map +1 -0
  485. package/dist/ingestion/website.js +100 -0
  486. package/dist/ingestion/website.js.map +1 -0
  487. package/dist/integrations/plugin.d.ts.map +1 -1
  488. package/dist/integrations/plugin.js +32 -27
  489. package/dist/integrations/plugin.js.map +1 -1
  490. package/dist/localization/default-messages.d.ts +22 -0
  491. package/dist/localization/default-messages.d.ts.map +1 -1
  492. package/dist/localization/default-messages.js +31 -9
  493. package/dist/localization/default-messages.js.map +1 -1
  494. package/dist/notifications/routes.d.ts +1 -1
  495. package/dist/observability/hosted-model-experiment.d.ts +39 -0
  496. package/dist/observability/hosted-model-experiment.d.ts.map +1 -0
  497. package/dist/observability/hosted-model-experiment.js +90 -0
  498. package/dist/observability/hosted-model-experiment.js.map +1 -0
  499. package/dist/observability/traces.d.ts.map +1 -1
  500. package/dist/observability/traces.js +5 -3
  501. package/dist/observability/traces.js.map +1 -1
  502. package/dist/progress/routes.d.ts +1 -1
  503. package/dist/provider-api/index.d.ts +35 -4
  504. package/dist/provider-api/index.d.ts.map +1 -1
  505. package/dist/provider-api/index.js +339 -8
  506. package/dist/provider-api/index.js.map +1 -1
  507. package/dist/scripts/agent-engines/list-agent-engines.d.ts.map +1 -1
  508. package/dist/scripts/agent-engines/list-agent-engines.js +18 -1
  509. package/dist/scripts/agent-engines/list-agent-engines.js.map +1 -1
  510. package/dist/search-utils/index.d.ts +12 -0
  511. package/dist/search-utils/index.d.ts.map +1 -0
  512. package/dist/search-utils/index.js +95 -0
  513. package/dist/search-utils/index.js.map +1 -0
  514. package/dist/secrets/register-framework-secrets.d.ts.map +1 -1
  515. package/dist/secrets/register-framework-secrets.js +57 -0
  516. package/dist/secrets/register-framework-secrets.js.map +1 -1
  517. package/dist/server/action-discovery.d.ts +8 -0
  518. package/dist/server/action-discovery.d.ts.map +1 -1
  519. package/dist/server/action-discovery.js +26 -9
  520. package/dist/server/action-discovery.js.map +1 -1
  521. package/dist/server/agent-chat/framework-prompts.js +2 -2
  522. package/dist/server/agent-chat/framework-prompts.js.map +1 -1
  523. package/dist/server/agent-chat/prompt-resources.d.ts +19 -0
  524. package/dist/server/agent-chat/prompt-resources.d.ts.map +1 -1
  525. package/dist/server/agent-chat/prompt-resources.js +95 -0
  526. package/dist/server/agent-chat/prompt-resources.js.map +1 -1
  527. package/dist/server/agent-chat-plugin.d.ts.map +1 -1
  528. package/dist/server/agent-chat-plugin.js +7 -0
  529. package/dist/server/agent-chat-plugin.js.map +1 -1
  530. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  531. package/dist/server/core-routes-plugin.d.ts.map +1 -1
  532. package/dist/server/core-routes-plugin.js +5 -0
  533. package/dist/server/core-routes-plugin.js.map +1 -1
  534. package/dist/server/index.d.ts +5 -1
  535. package/dist/server/index.d.ts.map +1 -1
  536. package/dist/server/index.js +5 -1
  537. package/dist/server/index.js.map +1 -1
  538. package/dist/server/workspace-provider-oauth.d.ts +48 -0
  539. package/dist/server/workspace-provider-oauth.d.ts.map +1 -0
  540. package/dist/server/workspace-provider-oauth.js +415 -0
  541. package/dist/server/workspace-provider-oauth.js.map +1 -0
  542. package/dist/styles/agent-native.css +9 -0
  543. package/dist/templates/chat/app/i18n/en-US.ts +3 -3
  544. package/dist/templates/chat/app/lib/agent-page.tsx +10 -1
  545. package/dist/templates/default/app/i18n/en-US.ts +3 -3
  546. package/dist/templates/workspace-core/.agents/skills/extensions/SKILL.md +14 -5
  547. package/dist/templates/workspace-root/.env.example +12 -0
  548. package/dist/workspace-connections/index.d.ts +1 -0
  549. package/dist/workspace-connections/index.d.ts.map +1 -1
  550. package/dist/workspace-connections/index.js +1 -0
  551. package/dist/workspace-connections/index.js.map +1 -1
  552. package/dist/workspace-connections/lifecycle.d.ts +16 -0
  553. package/dist/workspace-connections/lifecycle.d.ts.map +1 -0
  554. package/dist/workspace-connections/lifecycle.js +14 -0
  555. package/dist/workspace-connections/lifecycle.js.map +1 -0
  556. package/dist/workspace-connections/store.d.ts.map +1 -1
  557. package/dist/workspace-connections/store.js +16 -0
  558. package/dist/workspace-connections/store.js.map +1 -1
  559. package/package.json +10 -3
  560. package/src/templates/chat/app/i18n/en-US.ts +3 -3
  561. package/src/templates/chat/app/lib/agent-page.spec.tsx +10 -1
  562. package/src/templates/chat/app/lib/agent-page.tsx +10 -1
  563. package/src/templates/default/app/i18n/en-US.ts +3 -3
  564. package/src/templates/workspace-core/.agents/skills/extensions/SKILL.md +14 -5
  565. package/src/templates/workspace-root/.env.example +12 -0
@@ -0,0 +1,583 @@
1
+ import crypto from "node:crypto";
2
+
3
+ import {
4
+ deleteCookie,
5
+ defineEventHandler,
6
+ getCookie,
7
+ getMethod,
8
+ getQuery,
9
+ setCookie,
10
+ setResponseStatus,
11
+ type H3Event,
12
+ } from "h3";
13
+
14
+ import {
15
+ getWorkspaceConnectionProvider,
16
+ type WorkspaceConnectionProvider,
17
+ } from "../connections/catalog.js";
18
+ import { saveOAuthTokens, setOAuthDisplayName } from "../oauth-tokens/store.js";
19
+ import { decryptSecretValue, encryptSecretValue } from "../secrets/crypto.js";
20
+ import {
21
+ listWorkspaceConnections,
22
+ upsertWorkspaceConnection,
23
+ upsertWorkspaceConnectionGrant,
24
+ } from "../workspace-connections/store.js";
25
+ import { getSession, safeReturnPath } from "./auth.js";
26
+ import { resolveSecret } from "./credential-provider.js";
27
+ import {
28
+ decodeOAuthState,
29
+ encodeOAuthState,
30
+ getAppUrl,
31
+ resolveOAuthRedirectUri,
32
+ type OAuthStatePayload,
33
+ } from "./google-oauth.js";
34
+ import { runWithRequestContext } from "./request-context.js";
35
+
36
+ export type GenericWorkspaceOAuthProvider = "figma" | "google_drive" | "notion";
37
+
38
+ const SUPPORTED_PROVIDERS = new Set<GenericWorkspaceOAuthProvider>([
39
+ "figma",
40
+ "google_drive",
41
+ "notion",
42
+ ]);
43
+ const FLOW_TTL_SECONDS = 10 * 60;
44
+ const PROVIDER_REQUEST_TIMEOUT_MS = 10_000;
45
+ const PROVIDER_RESPONSE_MAX_BYTES = 256 * 1024;
46
+
47
+ export interface WorkspaceProviderOAuthFlow {
48
+ provider: GenericWorkspaceOAuthProvider;
49
+ flowId: string;
50
+ verifier: string;
51
+ redirectUri: string;
52
+ owner: string;
53
+ orgId?: string;
54
+ appId: string;
55
+ expiresAt: number;
56
+ }
57
+
58
+ export function workspaceProviderOAuthPath(
59
+ provider: GenericWorkspaceOAuthProvider,
60
+ phase: "start" | "callback",
61
+ ): string {
62
+ return `/_agent-native/connections/oauth/${provider}/${phase}`;
63
+ }
64
+
65
+ export function createWorkspaceProviderOAuthHandler(
66
+ provider: GenericWorkspaceOAuthProvider,
67
+ phase: "start" | "callback",
68
+ ) {
69
+ if (!SUPPORTED_PROVIDERS.has(provider)) {
70
+ throw new Error(`Unsupported workspace OAuth provider: ${provider}`);
71
+ }
72
+ return defineEventHandler((event) =>
73
+ phase === "start"
74
+ ? handleWorkspaceProviderOAuthStart(event, provider)
75
+ : handleWorkspaceProviderOAuthCallback(event, provider),
76
+ );
77
+ }
78
+
79
+ export async function handleWorkspaceProviderOAuthStart(
80
+ event: H3Event,
81
+ providerId: GenericWorkspaceOAuthProvider,
82
+ ): Promise<Response | Record<string, unknown>> {
83
+ if (getMethod(event) !== "GET") return methodNotAllowed(event);
84
+ const session = await getSession(event).catch(() => null);
85
+ if (!session?.email) return unauthorized(event);
86
+ const provider = requiredProvider(providerId);
87
+ const query = getQuery(event);
88
+ const appId = normalizeAppId(
89
+ text(query.appId) ??
90
+ process.env.AGENT_NATIVE_WORKSPACE_APP_ID ??
91
+ process.env.VITE_AGENT_NATIVE_WORKSPACE_APP_ID ??
92
+ "creative-context",
93
+ );
94
+ const redirectUri = resolveOAuthRedirectUri(
95
+ event,
96
+ workspaceProviderOAuthPath(providerId, "callback"),
97
+ );
98
+ if (!redirectUri) {
99
+ setResponseStatus(event, 400);
100
+ return { error: "Invalid OAuth redirect URI." };
101
+ }
102
+ return runWithRequestContext(
103
+ { userEmail: session.email, orgId: session.orgId },
104
+ async () => {
105
+ const [clientId, clientSecret] = await Promise.all([
106
+ resolveSecret(clientCredentialKey(providerId, "id")),
107
+ resolveSecret(clientCredentialKey(providerId, "secret")),
108
+ ]);
109
+ if (!clientId || !clientSecret) {
110
+ setResponseStatus(event, 503);
111
+ return {
112
+ error: `${provider.label} OAuth client credentials are not configured.`,
113
+ };
114
+ }
115
+ const verifier = crypto.randomBytes(48).toString("base64url");
116
+ const challenge = crypto
117
+ .createHash("sha256")
118
+ .update(verifier)
119
+ .digest("base64url");
120
+ const flowId = crypto.randomUUID();
121
+ const requestedReturnUrl = text(query.return);
122
+ const returnUrl = requestedReturnUrl
123
+ ? safeReturnPath(requestedReturnUrl)
124
+ : undefined;
125
+ const state = encodeOAuthState({
126
+ redirectUri,
127
+ owner: session.email,
128
+ orgId: session.orgId,
129
+ app: appId,
130
+ returnUrl,
131
+ flowId,
132
+ });
133
+ const flow: WorkspaceProviderOAuthFlow = {
134
+ provider: providerId,
135
+ flowId,
136
+ verifier,
137
+ redirectUri,
138
+ owner: session.email,
139
+ ...(session.orgId ? { orgId: session.orgId } : {}),
140
+ appId,
141
+ expiresAt: Date.now() + FLOW_TTL_SECONDS * 1_000,
142
+ };
143
+ setCookie(
144
+ event,
145
+ flowCookieName(providerId),
146
+ encryptSecretValue(JSON.stringify(flow)),
147
+ {
148
+ httpOnly: true,
149
+ secure: redirectUri.startsWith("https://"),
150
+ sameSite: "lax",
151
+ path: "/",
152
+ maxAge: FLOW_TTL_SECONDS,
153
+ },
154
+ );
155
+ const authorizationUrl = buildWorkspaceProviderAuthorizationUrl({
156
+ provider,
157
+ clientId,
158
+ redirectUri,
159
+ state,
160
+ challenge,
161
+ });
162
+ return Response.redirect(authorizationUrl, 302);
163
+ },
164
+ );
165
+ }
166
+
167
+ export async function handleWorkspaceProviderOAuthCallback(
168
+ event: H3Event,
169
+ providerId: GenericWorkspaceOAuthProvider,
170
+ ): Promise<Response | Record<string, unknown>> {
171
+ if (getMethod(event) !== "GET") return methodNotAllowed(event);
172
+ const session = await getSession(event).catch(() => null);
173
+ if (!session?.email) return unauthorized(event);
174
+ const query = getQuery(event);
175
+ const code = text(query.code);
176
+ const stateParam = text(query.state);
177
+ const providerError = text(query.error);
178
+ if (providerError) {
179
+ setResponseStatus(event, 400);
180
+ return { error: "OAuth authorization was not completed." };
181
+ }
182
+ if (!code || !stateParam) {
183
+ setResponseStatus(event, 400);
184
+ return { error: "OAuth callback is missing code or state." };
185
+ }
186
+ const flow = readStoredFlow(event, providerId);
187
+ deleteCookie(event, flowCookieName(providerId), { path: "/" });
188
+ const state = decodeOAuthState(stateParam, "");
189
+ if (
190
+ !flow ||
191
+ !isWorkspaceProviderOAuthFlowValid({
192
+ flow,
193
+ state,
194
+ provider: providerId,
195
+ sessionEmail: session.email,
196
+ sessionOrgId: session.orgId,
197
+ })
198
+ ) {
199
+ setResponseStatus(event, 400);
200
+ return { error: "OAuth state is invalid or expired." };
201
+ }
202
+ const provider = requiredProvider(providerId);
203
+ return runWithRequestContext(
204
+ { userEmail: session.email, orgId: session.orgId },
205
+ async () => {
206
+ const [clientId, clientSecret] = await Promise.all([
207
+ resolveSecret(clientCredentialKey(providerId, "id")),
208
+ resolveSecret(clientCredentialKey(providerId, "secret")),
209
+ ]);
210
+ if (!clientId || !clientSecret) {
211
+ setResponseStatus(event, 503);
212
+ return {
213
+ error: `${provider.label} OAuth client credentials are not configured.`,
214
+ };
215
+ }
216
+ const tokens = await exchangeWorkspaceProviderOAuthCode({
217
+ providerId,
218
+ provider,
219
+ clientId,
220
+ clientSecret,
221
+ code,
222
+ verifier: flow.verifier,
223
+ redirectUri: flow.redirectUri,
224
+ });
225
+ const identity = await resolveWorkspaceProviderIdentity(
226
+ providerId,
227
+ tokens,
228
+ );
229
+ await saveOAuthTokens(
230
+ provider.oauth!.provider,
231
+ identity.accountId,
232
+ tokens,
233
+ session.email,
234
+ );
235
+ await setOAuthDisplayName(
236
+ provider.oauth!.provider,
237
+ identity.accountId,
238
+ identity.label,
239
+ );
240
+ const existing = (
241
+ await listWorkspaceConnections({
242
+ provider: providerId,
243
+ includeDisabled: true,
244
+ })
245
+ ).find((connection) => connection.accountId === identity.accountId);
246
+ const scopes = mergeWorkspaceOAuthValues(
247
+ existing?.scopes ?? [],
248
+ tokenScopes(tokens, provider.oauth!.scopes),
249
+ );
250
+ const connection = await upsertWorkspaceConnection({
251
+ ...(existing ? { id: existing.id } : {}),
252
+ provider: providerId,
253
+ label: `${provider.label}: ${identity.label}`,
254
+ accountId: identity.accountId,
255
+ accountLabel: identity.label,
256
+ status: "connected",
257
+ scopes,
258
+ allowedApps: existing?.allowedApps ?? [],
259
+ config: { credentialMode: "oauth" },
260
+ lastCheckedAt: new Date(),
261
+ lastError: null,
262
+ });
263
+ await upsertWorkspaceConnectionGrant({
264
+ connectionId: connection.id,
265
+ appId: flow.appId,
266
+ provider: providerId,
267
+ scopes,
268
+ config: { credentialMode: "oauth" },
269
+ });
270
+ const returnPath =
271
+ state.returnUrl ??
272
+ `/settings/connections?connected=${encodeURIComponent(providerId)}`;
273
+ return Response.redirect(getAppUrl(event, returnPath), 302);
274
+ },
275
+ );
276
+ }
277
+
278
+ export function buildWorkspaceProviderAuthorizationUrl(input: {
279
+ provider: WorkspaceConnectionProvider;
280
+ clientId: string;
281
+ redirectUri: string;
282
+ state: string;
283
+ challenge: string;
284
+ }): string {
285
+ if (!input.provider.oauth)
286
+ throw new Error("Provider does not support OAuth.");
287
+ const url = new URL(input.provider.oauth.authorizationUrl);
288
+ url.searchParams.set("client_id", input.clientId);
289
+ url.searchParams.set("redirect_uri", input.redirectUri);
290
+ url.searchParams.set("response_type", "code");
291
+ url.searchParams.set("state", input.state);
292
+ if (input.provider.id === "figma") {
293
+ url.searchParams.set("code_challenge", input.challenge);
294
+ url.searchParams.set("code_challenge_method", "S256");
295
+ }
296
+ if (input.provider.id === "google_drive") {
297
+ url.searchParams.set("access_type", "offline");
298
+ url.searchParams.set("include_granted_scopes", "true");
299
+ url.searchParams.set("prompt", "consent");
300
+ }
301
+ if (input.provider.oauth.scopes.length) {
302
+ url.searchParams.set("scope", input.provider.oauth.scopes.join(" "));
303
+ }
304
+ if (input.provider.id === "notion") url.searchParams.set("owner", "user");
305
+ return url.href;
306
+ }
307
+
308
+ export async function exchangeWorkspaceProviderOAuthCode(input: {
309
+ providerId: GenericWorkspaceOAuthProvider;
310
+ provider: WorkspaceConnectionProvider;
311
+ clientId: string;
312
+ clientSecret: string;
313
+ code: string;
314
+ verifier: string;
315
+ redirectUri: string;
316
+ }): Promise<Record<string, unknown>> {
317
+ const tokenUrl = input.provider.oauth?.tokenUrl;
318
+ if (!tokenUrl) throw new Error("Provider does not support OAuth.");
319
+ const authorization = `Basic ${Buffer.from(`${input.clientId}:${input.clientSecret}`).toString("base64")}`;
320
+ const fields = {
321
+ grant_type: "authorization_code",
322
+ code: input.code,
323
+ redirect_uri: input.redirectUri,
324
+ ...(input.providerId === "figma" ? { code_verifier: input.verifier } : {}),
325
+ ...(input.providerId === "google_drive"
326
+ ? { client_id: input.clientId, client_secret: input.clientSecret }
327
+ : {}),
328
+ };
329
+ const { response, body } = await fetchBoundedProviderJson(
330
+ tokenUrl,
331
+ {
332
+ method: "POST",
333
+ headers:
334
+ input.providerId === "notion"
335
+ ? {
336
+ Authorization: authorization,
337
+ Accept: "application/json",
338
+ "Content-Type": "application/json",
339
+ }
340
+ : input.providerId === "figma"
341
+ ? {
342
+ Authorization: authorization,
343
+ "Content-Type": "application/x-www-form-urlencoded",
344
+ }
345
+ : { "Content-Type": "application/x-www-form-urlencoded" },
346
+ body:
347
+ input.providerId === "notion"
348
+ ? JSON.stringify(fields)
349
+ : new URLSearchParams(fields),
350
+ },
351
+ input.provider.label,
352
+ );
353
+ const accessToken = text(body.access_token);
354
+ if (!response.ok || !accessToken) {
355
+ throw new Error(
356
+ `${input.provider.label} OAuth token exchange failed (${response.status}).`,
357
+ );
358
+ }
359
+ const expiresIn = Number(body.expires_in);
360
+ return {
361
+ ...body,
362
+ ...(Number.isFinite(expiresIn) && expiresIn > 0
363
+ ? { expiry_date: Date.now() + expiresIn * 1_000 }
364
+ : {}),
365
+ };
366
+ }
367
+
368
+ export async function resolveWorkspaceProviderIdentity(
369
+ providerId: GenericWorkspaceOAuthProvider,
370
+ tokens: Record<string, unknown>,
371
+ ): Promise<{ accountId: string; label: string }> {
372
+ if (providerId === "notion") {
373
+ const owner = record(tokens.owner);
374
+ const user = record(owner?.user);
375
+ const person = record(user?.person);
376
+ const accountId =
377
+ text(user?.id) ??
378
+ text(person?.email) ??
379
+ text(tokens.workspace_id) ??
380
+ text(tokens.bot_id);
381
+ if (!accountId)
382
+ throw new Error(
383
+ "Notion OAuth response did not identify the connected user.",
384
+ );
385
+ return {
386
+ accountId,
387
+ label:
388
+ text(person?.email) ??
389
+ text(tokens.workspace_name) ??
390
+ "Notion workspace",
391
+ };
392
+ }
393
+ if (providerId === "google_drive") {
394
+ const accessToken = text(tokens.access_token)!;
395
+ const { response, body } = await fetchBoundedProviderJson(
396
+ "https://www.googleapis.com/drive/v3/about?fields=user(displayName,emailAddress,permissionId)",
397
+ { headers: { Authorization: `Bearer ${accessToken}` } },
398
+ "Google Drive",
399
+ );
400
+ const user = record(body.user);
401
+ const accountId = text(user?.permissionId) ?? text(user?.emailAddress);
402
+ if (!response.ok || !accountId) {
403
+ throw new Error(
404
+ "Google Drive OAuth response did not identify the connected account.",
405
+ );
406
+ }
407
+ return {
408
+ accountId,
409
+ label:
410
+ text(user?.emailAddress) ??
411
+ text(user?.displayName) ??
412
+ "Google Drive account",
413
+ };
414
+ }
415
+ const accessToken = text(tokens.access_token)!;
416
+ const { response, body: me } = await fetchBoundedProviderJson(
417
+ "https://api.figma.com/v1/me",
418
+ { headers: { Authorization: `Bearer ${accessToken}` } },
419
+ "Figma",
420
+ );
421
+ const accountId = text(me.id) ?? text(me.email) ?? text(tokens.user_id);
422
+ if (!response.ok || !accountId) {
423
+ throw new Error(
424
+ "Figma OAuth response did not identify the connected user.",
425
+ );
426
+ }
427
+ return {
428
+ accountId,
429
+ label: text(me.email) ?? text(me.handle) ?? "Figma account",
430
+ };
431
+ }
432
+
433
+ function requiredProvider(
434
+ providerId: GenericWorkspaceOAuthProvider,
435
+ ): WorkspaceConnectionProvider {
436
+ const provider = getWorkspaceConnectionProvider(providerId);
437
+ if (!provider?.oauth)
438
+ throw new Error(`${providerId} OAuth is not configured.`);
439
+ return provider;
440
+ }
441
+
442
+ function readStoredFlow(
443
+ event: H3Event,
444
+ provider: GenericWorkspaceOAuthProvider,
445
+ ): WorkspaceProviderOAuthFlow | null {
446
+ const encrypted = getCookie(event, flowCookieName(provider));
447
+ if (!encrypted) return null;
448
+ try {
449
+ return JSON.parse(
450
+ decryptSecretValue(encrypted),
451
+ ) as WorkspaceProviderOAuthFlow;
452
+ } catch {
453
+ return null;
454
+ }
455
+ }
456
+
457
+ export function isWorkspaceProviderOAuthFlowValid(input: {
458
+ flow: WorkspaceProviderOAuthFlow;
459
+ state: OAuthStatePayload;
460
+ provider: GenericWorkspaceOAuthProvider;
461
+ sessionEmail: string;
462
+ sessionOrgId?: string;
463
+ now?: number;
464
+ }): boolean {
465
+ return (
466
+ input.flow.expiresAt >= (input.now ?? Date.now()) &&
467
+ input.flow.provider === input.provider &&
468
+ input.state.flowId === input.flow.flowId &&
469
+ input.state.redirectUri === input.flow.redirectUri &&
470
+ input.state.owner === input.flow.owner &&
471
+ input.sessionEmail === input.flow.owner &&
472
+ input.state.orgId === input.flow.orgId &&
473
+ input.sessionOrgId === input.flow.orgId &&
474
+ input.state.app === input.flow.appId
475
+ );
476
+ }
477
+
478
+ async function fetchBoundedProviderJson(
479
+ url: string,
480
+ init: RequestInit,
481
+ providerLabel: string,
482
+ ): Promise<{ response: Response; body: Record<string, unknown> }> {
483
+ let response: Response;
484
+ try {
485
+ response = await fetch(url, {
486
+ ...init,
487
+ signal: AbortSignal.timeout(PROVIDER_REQUEST_TIMEOUT_MS),
488
+ });
489
+ } catch {
490
+ throw new Error(`${providerLabel} OAuth request failed.`);
491
+ }
492
+ const declaredLength = Number(response.headers.get("content-length"));
493
+ if (
494
+ Number.isFinite(declaredLength) &&
495
+ declaredLength > PROVIDER_RESPONSE_MAX_BYTES
496
+ ) {
497
+ throw new Error(`${providerLabel} OAuth response exceeded the size limit.`);
498
+ }
499
+ if (!response.body) return { response, body: {} };
500
+ const reader = response.body.getReader();
501
+ const chunks: Uint8Array[] = [];
502
+ let length = 0;
503
+ try {
504
+ while (true) {
505
+ const chunk = await reader.read();
506
+ if (chunk.done) break;
507
+ length += chunk.value.byteLength;
508
+ if (length > PROVIDER_RESPONSE_MAX_BYTES) {
509
+ await reader.cancel();
510
+ break;
511
+ }
512
+ chunks.push(chunk.value);
513
+ }
514
+ } catch {
515
+ throw new Error(`${providerLabel} OAuth request failed.`);
516
+ }
517
+ if (length > PROVIDER_RESPONSE_MAX_BYTES) {
518
+ throw new Error(`${providerLabel} OAuth response exceeded the size limit.`);
519
+ }
520
+ try {
521
+ const json = Buffer.concat(chunks).toString("utf8");
522
+ const body = JSON.parse(json) as unknown;
523
+ return { response, body: record(body) ?? {} };
524
+ } catch {
525
+ return { response, body: {} };
526
+ }
527
+ }
528
+
529
+ function tokenScopes(
530
+ tokens: Record<string, unknown>,
531
+ fallback: readonly string[],
532
+ ): string[] {
533
+ const scope = text(tokens.scope);
534
+ return scope ? scope.split(/[ ,]+/).filter(Boolean) : [...fallback];
535
+ }
536
+
537
+ export function mergeWorkspaceOAuthValues(
538
+ existing: readonly string[],
539
+ incoming: readonly string[],
540
+ ): string[] {
541
+ return [...new Set([...existing, ...incoming])];
542
+ }
543
+
544
+ function clientCredentialKey(
545
+ provider: GenericWorkspaceOAuthProvider,
546
+ field: "id" | "secret",
547
+ ): string {
548
+ const prefix =
549
+ provider === "google_drive" ? "GOOGLE" : provider.toUpperCase();
550
+ return `${prefix}_CLIENT_${field === "id" ? "ID" : "SECRET"}`;
551
+ }
552
+
553
+ function flowCookieName(provider: GenericWorkspaceOAuthProvider): string {
554
+ return `an_workspace_oauth_${provider}`;
555
+ }
556
+
557
+ function normalizeAppId(value: string): string {
558
+ const normalized = value.trim().toLowerCase();
559
+ if (!/^[a-z0-9][a-z0-9_-]{0,99}$/.test(normalized)) {
560
+ throw new Error("OAuth appId is invalid.");
561
+ }
562
+ return normalized;
563
+ }
564
+
565
+ function text(value: unknown): string | undefined {
566
+ return typeof value === "string" && value.trim() ? value.trim() : undefined;
567
+ }
568
+
569
+ function record(value: unknown): Record<string, unknown> | null {
570
+ return value && typeof value === "object" && !Array.isArray(value)
571
+ ? (value as Record<string, unknown>)
572
+ : null;
573
+ }
574
+
575
+ function methodNotAllowed(event: H3Event) {
576
+ setResponseStatus(event, 405);
577
+ return { error: "Method not allowed" };
578
+ }
579
+
580
+ function unauthorized(event: H3Event) {
581
+ setResponseStatus(event, 401);
582
+ return { error: "Authentication required" };
583
+ }
@@ -155,6 +155,11 @@
155
155
  box-shadow 260ms var(--ease-drawer);
156
156
  }
157
157
 
158
+ .agent-sidebar-shell[data-agent-sidebar-resizing="true"],
159
+ .agent-sidebar-shell[data-agent-sidebar-resizing="true"] * {
160
+ transition: none !important;
161
+ }
162
+
158
163
  .agent-native-app-main {
159
164
  container: agent-native-main / inline-size;
160
165
  }
@@ -237,6 +242,10 @@
237
242
  transition: width 260ms var(--ease-drawer);
238
243
  }
239
244
 
245
+ .agent-sidebar-panel[data-agent-sidebar-animation="desktop"][data-agent-sidebar-resizing="true"] {
246
+ transition: none;
247
+ }
248
+
240
249
  .agent-sidebar-panel[data-agent-sidebar-animation="desktop"][data-agent-sidebar-state="open"] {
241
250
  width: var(--agent-sidebar-width);
242
251
  }
@@ -18,10 +18,10 @@ const messages = {
18
18
  languageDescription:
19
19
  "Choose the interface language. This preference is saved for your account.",
20
20
  languageLabel: "Interface language",
21
- agentTitle: "Agent settings",
21
+ agentTitle: "Agent workspace",
22
22
  agentDescription:
23
- "Open the agent sidebar settings for model, API keys, automations, voice, and other agent controls.",
24
- openAgentSettings: "Open agent settings",
23
+ "Open the agent workspace for model, API keys, automations, voice, and other agent controls.",
24
+ openAgentSettings: "Open agent workspace",
25
25
  workspaceTitle: "Workspace",
26
26
  workspaceDescription: "Manage team access and shared workspace resources.",
27
27
  openTeamSettings: "Open team settings",
@@ -200,9 +200,10 @@ extension content:
200
200
  ```
201
201
 
202
202
  `update-extension` accepts the same `contentFromAttachment` for full-body
203
- replacement. Inline `content` still works for everything you author yourself —
204
- use `contentFromAttachment` only to avoid regurgitating something the user
205
- already pasted.
203
+ replacement, but full-body replacement requires `allowFullReplacement: true`.
204
+ Inline `content` still works for everything you author yourself — use
205
+ `contentFromAttachment` only to avoid regurgitating something the user already
206
+ pasted.
206
207
 
207
208
  ## Editing an extension
208
209
 
@@ -211,6 +212,13 @@ changes instead of regenerating the full HTML. For medium/large extensions,
211
212
  add stable section comments around major blocks so future agents can target
212
213
  them without touching unrelated indentation:
213
214
 
215
+ For data-only repairs, preserve the existing layout, CSS, copy, and
216
+ interactions. Do not reconstruct and submit the entire body. The action and
217
+ store reject full-body replacement unless `allowFullReplacement: true` is
218
+ explicitly supplied for a user-requested visual rewrite or complete replacement
219
+ body. If a focused edit fails, inspect the current body and adjust its target;
220
+ do not retry unchanged arguments.
221
+
214
222
  ```html
215
223
  <!-- agent-native:section npm-daily-chart -->
216
224
  <section>...</section>
@@ -243,7 +251,8 @@ Supported `edits` operations:
243
251
  Use `expectedMatches` when ambiguity would be dangerous. Missing required
244
252
  targets fail instead of silently doing nothing. Pass `format: true` to run
245
253
  Prettier on the final HTML after the patch. Full `content` replacement is
246
- still available for broad rewrites.
254
+ still available for broad rewrites when `allowFullReplacement: true` is
255
+ supplied.
247
256
 
248
257
  Legacy `patches` still work for simple literal replacements:
249
258
 
@@ -264,7 +273,7 @@ To replace the full content instead:
264
273
 
265
274
  ```
266
275
  PUT /_agent-native/extensions/:id
267
- { "content": "full new HTML" }
276
+ { "content": "full new HTML", "allowFullReplacement": true }
268
277
  ```
269
278
 
270
279
  ## History and rollback
@@ -70,6 +70,18 @@ DISPATCH_DEFAULT_OWNER_EMAIL=
70
70
  GOOGLE_CLIENT_ID=
71
71
  GOOGLE_CLIENT_SECRET=
72
72
 
73
+ # Optional workspace connectors. Register the matching callback URLs in each
74
+ # provider using APP_URL as the origin:
75
+ # /_agent-native/connections/oauth/google_drive/callback
76
+ # /_agent-native/connections/oauth/figma/callback
77
+ # /_agent-native/connections/oauth/notion/callback
78
+ # Google reuses the client above. User access and refresh tokens are encrypted
79
+ # in the workspace token store.
80
+ FIGMA_CLIENT_ID=
81
+ FIGMA_CLIENT_SECRET=
82
+ NOTION_CLIENT_ID=
83
+ NOTION_CLIENT_SECRET=
84
+
73
85
  # Optional: GitHub sign-in.
74
86
  GITHUB_CLIENT_ID=
75
87
  GITHUB_CLIENT_SECRET=
@@ -64,3 +64,9 @@ export {
64
64
  type WorkspaceConnectionCredentialResolutionStatus,
65
65
  type WorkspaceConnectionCredentialsResolution,
66
66
  } from "./credentials.js";
67
+
68
+ export {
69
+ registerWorkspaceConnectionLifecycleListener,
70
+ type WorkspaceConnectionLifecycleEvent,
71
+ type WorkspaceConnectionLifecycleListener,
72
+ } from "./lifecycle.js";