@agent-native/core 0.92.11 → 0.93.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (777) hide show
  1. package/corpus/README.md +2 -2
  2. package/corpus/core/CHANGELOG.md +45 -0
  3. package/corpus/core/docs/content/automation-connectors.mdx +80 -0
  4. package/corpus/core/docs/content/extensions.mdx +8 -0
  5. package/corpus/core/docs/content/locales/ar-SA/extensions.mdx +8 -0
  6. package/corpus/core/docs/content/locales/ar-SA/messaging.mdx +84 -15
  7. package/corpus/core/docs/content/locales/ar-SA/template-clips.mdx +1 -0
  8. package/corpus/core/docs/content/locales/ar-SA/template-design.mdx +1 -0
  9. package/corpus/core/docs/content/locales/de-DE/extensions.mdx +10 -0
  10. package/corpus/core/docs/content/locales/de-DE/messaging.mdx +92 -15
  11. package/corpus/core/docs/content/locales/de-DE/template-clips.mdx +1 -0
  12. package/corpus/core/docs/content/locales/de-DE/template-design.mdx +1 -0
  13. package/corpus/core/docs/content/locales/es-ES/extensions.mdx +10 -0
  14. package/corpus/core/docs/content/locales/es-ES/messaging.mdx +91 -15
  15. package/corpus/core/docs/content/locales/es-ES/template-clips.mdx +1 -0
  16. package/corpus/core/docs/content/locales/es-ES/template-design.mdx +1 -0
  17. package/corpus/core/docs/content/locales/fr-FR/extensions.mdx +10 -0
  18. package/corpus/core/docs/content/locales/fr-FR/messaging.mdx +91 -15
  19. package/corpus/core/docs/content/locales/fr-FR/template-clips.mdx +1 -0
  20. package/corpus/core/docs/content/locales/fr-FR/template-design.mdx +1 -0
  21. package/corpus/core/docs/content/locales/hi-IN/extensions.mdx +8 -0
  22. package/corpus/core/docs/content/locales/hi-IN/messaging.mdx +81 -15
  23. package/corpus/core/docs/content/locales/hi-IN/template-clips.mdx +1 -0
  24. package/corpus/core/docs/content/locales/hi-IN/template-design.mdx +1 -0
  25. package/corpus/core/docs/content/locales/ja-JP/extensions.mdx +9 -0
  26. package/corpus/core/docs/content/locales/ja-JP/messaging.mdx +81 -15
  27. package/corpus/core/docs/content/locales/ja-JP/template-clips.mdx +1 -0
  28. package/corpus/core/docs/content/locales/ja-JP/template-design.mdx +1 -0
  29. package/corpus/core/docs/content/locales/ko-KR/extensions.mdx +8 -0
  30. package/corpus/core/docs/content/locales/ko-KR/messaging.mdx +80 -15
  31. package/corpus/core/docs/content/locales/ko-KR/template-clips.mdx +1 -0
  32. package/corpus/core/docs/content/locales/ko-KR/template-design.mdx +1 -0
  33. package/corpus/core/docs/content/locales/pt-BR/extensions.mdx +9 -0
  34. package/corpus/core/docs/content/locales/pt-BR/messaging.mdx +88 -15
  35. package/corpus/core/docs/content/locales/pt-BR/template-clips.mdx +1 -0
  36. package/corpus/core/docs/content/locales/pt-BR/template-design.mdx +1 -0
  37. package/corpus/core/docs/content/locales/zh-CN/extensions.mdx +6 -0
  38. package/corpus/core/docs/content/locales/zh-CN/messaging.mdx +78 -15
  39. package/corpus/core/docs/content/locales/zh-CN/template-clips.mdx +1 -0
  40. package/corpus/core/docs/content/locales/zh-CN/template-design.mdx +1 -0
  41. package/corpus/core/docs/content/locales/zh-TW/extensions.mdx +6 -0
  42. package/corpus/core/docs/content/locales/zh-TW/messaging.mdx +78 -15
  43. package/corpus/core/docs/content/locales/zh-TW/template-clips.mdx +1 -0
  44. package/corpus/core/docs/content/locales/zh-TW/template-design.mdx +1 -0
  45. package/corpus/core/docs/content/messaging.mdx +227 -45
  46. package/corpus/core/docs/content/template-clips.mdx +3 -0
  47. package/corpus/core/docs/content/template-design.mdx +4 -0
  48. package/corpus/core/package.json +5 -1
  49. package/corpus/core/src/a2a/artifact-response.ts +131 -2
  50. package/corpus/core/src/a2a/client.ts +10 -0
  51. package/corpus/core/src/a2a/handlers.ts +40 -76
  52. package/corpus/core/src/a2a/types.ts +2 -0
  53. package/corpus/core/src/agent/durable-background.ts +24 -0
  54. package/corpus/core/src/agent/production-agent.ts +48 -5
  55. package/corpus/core/src/agent/run-manager.ts +171 -20
  56. package/corpus/core/src/agent/run-store.ts +297 -42
  57. package/corpus/core/src/agent/types.ts +23 -0
  58. package/corpus/core/src/audit/record.ts +31 -0
  59. package/corpus/core/src/audit/store.ts +69 -3
  60. package/corpus/core/src/audit/types.ts +13 -0
  61. package/corpus/core/src/automation/index.ts +802 -0
  62. package/corpus/core/src/cli/create.ts +12 -5
  63. package/corpus/core/src/cli/design-connect.ts +596 -36
  64. package/corpus/core/src/client/AgentPanel.tsx +51 -6
  65. package/corpus/core/src/client/AssistantChat.tsx +274 -147
  66. package/corpus/core/src/client/MultiTabAssistantChat.tsx +3 -0
  67. package/corpus/core/src/client/RunStuckBanner.tsx +69 -20
  68. package/corpus/core/src/client/agent-chat-adapter.ts +110 -17
  69. package/corpus/core/src/client/automation.ts +22 -0
  70. package/corpus/core/src/client/chat/run-recovery.tsx +67 -50
  71. package/corpus/core/src/client/composer/TiptapComposer.tsx +8 -0
  72. package/corpus/core/src/client/index.ts +30 -0
  73. package/corpus/core/src/client/integrations/api.ts +295 -0
  74. package/corpus/core/src/client/integrations/index.ts +26 -0
  75. package/corpus/core/src/client/transcription/use-live-transcription.ts +68 -5
  76. package/corpus/core/src/client/use-run-stuck-detection.ts +41 -3
  77. package/corpus/core/src/deploy/build.ts +59 -3
  78. package/corpus/core/src/deploy/workspace-deploy.ts +37 -2
  79. package/corpus/core/src/file-upload/types.ts +2 -0
  80. package/corpus/core/src/index.ts +37 -0
  81. package/corpus/core/src/integrations/a2a-continuations-store.ts +6 -4
  82. package/corpus/core/src/integrations/adapters/discord.ts +362 -0
  83. package/corpus/core/src/integrations/adapters/index.ts +29 -0
  84. package/corpus/core/src/integrations/adapters/microsoft-teams.ts +411 -0
  85. package/corpus/core/src/integrations/adapters/slack.ts +861 -27
  86. package/corpus/core/src/integrations/adapters/telegram.ts +54 -15
  87. package/corpus/core/src/integrations/adapters/whatsapp.ts +41 -17
  88. package/corpus/core/src/integrations/catalog.ts +571 -0
  89. package/corpus/core/src/integrations/controls-store.ts +187 -0
  90. package/corpus/core/src/integrations/index.ts +100 -0
  91. package/corpus/core/src/integrations/installations-store.ts +677 -0
  92. package/corpus/core/src/integrations/integration-memory.ts +187 -0
  93. package/corpus/core/src/integrations/pending-tasks-retry-job.ts +6 -6
  94. package/corpus/core/src/integrations/pending-tasks-store.ts +83 -5
  95. package/corpus/core/src/integrations/plugin.ts +685 -47
  96. package/corpus/core/src/integrations/scope-store.ts +498 -0
  97. package/corpus/core/src/integrations/slack-manifest.ts +78 -0
  98. package/corpus/core/src/integrations/slack-oauth.ts +343 -0
  99. package/corpus/core/src/integrations/types.ts +179 -0
  100. package/corpus/core/src/integrations/usage-budget-store.ts +906 -0
  101. package/corpus/core/src/integrations/webhook-handler.ts +562 -51
  102. package/corpus/core/src/jobs/scheduler.ts +100 -2
  103. package/corpus/core/src/jobs/tools.ts +45 -9
  104. package/corpus/core/src/provider-api/index.ts +72 -1
  105. package/corpus/core/src/resources/handlers.ts +88 -14
  106. package/corpus/core/src/resources/script-helpers.ts +36 -7
  107. package/corpus/core/src/resources/store.ts +59 -52
  108. package/corpus/core/src/scripts/call-agent.ts +107 -1
  109. package/corpus/core/src/server/agent-chat-plugin.ts +294 -119
  110. package/corpus/core/src/server/auth.ts +10 -14
  111. package/corpus/core/src/server/builder-design-systems.ts +16 -1
  112. package/corpus/core/src/server/edge.ts +18 -0
  113. package/corpus/core/src/server/index.ts +26 -0
  114. package/corpus/core/src/server/request-context.ts +18 -0
  115. package/corpus/core/src/server/social-og-image.ts +3 -2
  116. package/corpus/core/src/styles/agent-native.css +62 -44
  117. package/corpus/core/src/templates/default/.agents/skills/capture-learnings/SKILL.md +22 -9
  118. package/corpus/core/src/templates/default/AGENTS.md +7 -3
  119. package/corpus/core/src/templates/workspace-core/.agents/skills/authentication/SKILL.md +1 -1
  120. package/corpus/core/src/templates/workspace-core/.agents/skills/capture-learnings/SKILL.md +22 -9
  121. package/corpus/core/src/templates/workspace-core/.agents/skills/extension-points/SKILL.md +6 -3
  122. package/corpus/core/src/templates/workspace-core/.agents/skills/extensions/SKILL.md +25 -0
  123. package/corpus/core/src/templates/workspace-core/.agents/skills/integration-webhooks/SKILL.md +15 -0
  124. package/corpus/core/src/templates/workspace-core/AGENTS.md +3 -2
  125. package/corpus/core/src/usage/store.ts +37 -2
  126. package/corpus/templates/analytics/.agents/skills/capture-learnings/SKILL.md +22 -9
  127. package/corpus/templates/analytics/.agents/skills/provider-api/SKILL.md +23 -0
  128. package/corpus/templates/analytics/.builder/skills/provider-api/SKILL.md +15 -0
  129. package/corpus/templates/analytics/actions/save-monitor.ts +25 -2
  130. package/corpus/templates/analytics/app/lib/data-sources.ts +28 -0
  131. package/corpus/templates/analytics/changelog/2026-07-10-agent-created-uptime-monitors-now-return-a-direct-link-to-th.md +6 -0
  132. package/corpus/templates/analytics/changelog/2026-07-10-dashboard-email-reports-still-arrive-when-screenshot-capture-temporarily-fails.md +6 -0
  133. package/corpus/templates/analytics/server/jobs/dashboard-report.ts +3 -7
  134. package/corpus/templates/analytics/server/lib/credential-keys.ts +12 -0
  135. package/corpus/templates/analytics/server/lib/dashboard-report.ts +5 -1
  136. package/corpus/templates/analytics/server/lib/provider-credentials.ts +2 -0
  137. package/corpus/templates/analytics/server/routes/api/test-connection.post.ts +16 -0
  138. package/corpus/templates/assets/.agents/skills/capture-learnings/SKILL.md +22 -9
  139. package/corpus/templates/brain/.agents/skills/capture-learnings/SKILL.md +22 -9
  140. package/corpus/templates/calendar/.agents/skills/capture-learnings/SKILL.md +22 -9
  141. package/corpus/templates/calendar/app/components/calendar/CommandPalette.tsx +98 -108
  142. package/corpus/templates/calendar/app/components/calendar/EventAttendeesSection.tsx +97 -90
  143. package/corpus/templates/calendar/changelog/2026-07-10-event-guest-details-and-option-menus-now-use-valid-accessibl.md +6 -0
  144. package/corpus/templates/calendar/changelog/2026-07-10-natural-language-event-phrases-stay-available-as-quick-creat.md +6 -0
  145. package/corpus/templates/chat/.agents/skills/capture-learnings/SKILL.md +22 -9
  146. package/corpus/templates/chat/changelog/2026-07-10-chat-now-makes-ai-connection-setup-clear-without-shifting-th.md +6 -0
  147. package/corpus/templates/clips/.agents/skills/capture-learnings/SKILL.md +22 -9
  148. package/corpus/templates/clips/.agents/skills/recording/SKILL.md +17 -1
  149. package/corpus/templates/clips/.agents/skills/video-sharing/SKILL.md +8 -0
  150. package/corpus/templates/clips/AGENTS.md +8 -3
  151. package/corpus/templates/clips/actions/finalize-recording.ts +63 -23
  152. package/corpus/templates/clips/actions/get-recording-player-data.ts +6 -2
  153. package/corpus/templates/clips/actions/lib/ensure-seekable-video.ts +72 -9
  154. package/corpus/templates/clips/actions/list-recordings.ts +19 -3
  155. package/corpus/templates/clips/actions/navigate.ts +2 -0
  156. package/corpus/templates/clips/actions/reprocess-recording.ts +20 -6
  157. package/corpus/templates/clips/actions/request-transcript.ts +16 -31
  158. package/corpus/templates/clips/actions/view-screen.ts +57 -5
  159. package/corpus/templates/clips/app/components/layout/Header.tsx +1 -0
  160. package/corpus/templates/clips/app/components/library/empty-state.tsx +2 -0
  161. package/corpus/templates/clips/app/components/library/library-grid.tsx +69 -42
  162. package/corpus/templates/clips/app/components/library/library-layout.tsx +15 -1
  163. package/corpus/templates/clips/app/components/library/recording-card.tsx +81 -68
  164. package/corpus/templates/clips/app/components/library/search-bar.tsx +4 -3
  165. package/corpus/templates/clips/app/components/player/delete-recording-menu.tsx +9 -3
  166. package/corpus/templates/clips/app/components/player/share-dialog.tsx +1 -1
  167. package/corpus/templates/clips/app/components/player/transcript-panel.tsx +27 -5
  168. package/corpus/templates/clips/app/hooks/use-library.ts +1 -1
  169. package/corpus/templates/clips/app/hooks/use-navigation-state.ts +10 -2
  170. package/corpus/templates/clips/app/hooks/use-player-shortcuts.ts +1 -0
  171. package/corpus/templates/clips/app/i18n/ar-SA.ts +7 -1
  172. package/corpus/templates/clips/app/i18n/de-DE.ts +7 -1
  173. package/corpus/templates/clips/app/i18n/en-US.ts +7 -1
  174. package/corpus/templates/clips/app/i18n/es-ES.ts +7 -1
  175. package/corpus/templates/clips/app/i18n/fr-FR.ts +7 -1
  176. package/corpus/templates/clips/app/i18n/hi-IN.ts +7 -1
  177. package/corpus/templates/clips/app/i18n/ja-JP.ts +7 -1
  178. package/corpus/templates/clips/app/i18n/ko-KR.ts +7 -1
  179. package/corpus/templates/clips/app/i18n/pt-BR.ts +7 -1
  180. package/corpus/templates/clips/app/i18n/zh-CN.ts +8 -1
  181. package/corpus/templates/clips/app/i18n/zh-TW.ts +8 -1
  182. package/corpus/templates/clips/app/lib/recording-visibility.ts +70 -0
  183. package/corpus/templates/clips/app/routes/_app.shared.tsx +20 -0
  184. package/corpus/templates/clips/app/routes/download.tsx +24 -8
  185. package/corpus/templates/clips/app/routes/r.$recordingId.tsx +115 -2
  186. package/corpus/templates/clips/app/routes/record.tsx +62 -0
  187. package/corpus/templates/clips/app/routes/share.$shareId.tsx +25 -16
  188. package/corpus/templates/clips/changelog/2026-07-10-clips-desktop-is-now-available-for-linux-with-appimage-debia.md +6 -0
  189. package/corpus/templates/clips/changelog/2026-07-10-clips-downloads-updates-sooner-in-the-background-and-offers-.md +6 -0
  190. package/corpus/templates/clips/changelog/2026-07-10-clips-shared-with-you-now-appear-in-a-searchable-shared-with.md +6 -0
  191. package/corpus/templates/clips/changelog/2026-07-10-clips-with-missing-mobile-video-frames-can-be-repaired-witho.md +6 -0
  192. package/corpus/templates/clips/changelog/2026-07-10-fixed-copying-agent-responses-and-transcript-text-from-recor.md +6 -0
  193. package/corpus/templates/clips/changelog/2026-07-10-mobile-camera-recordings-pause-while-backgrounded.md +6 -0
  194. package/corpus/templates/clips/changelog/2026-07-10-mp4-downloads-now-show-progress-immediately-after-the-option.md +6 -0
  195. package/corpus/templates/clips/changelog/2026-07-10-recording-pages-now-open-as-soon-as-you-stop-with-a-share-li.md +6 -0
  196. package/corpus/templates/clips/changelog/2026-07-10-recordings-now-seek-smoothly-downloads-use-the-correct-file-.md +6 -0
  197. package/corpus/templates/clips/changelog/2026-07-10-s3-compatible-storage-now-saves-hosted-recordings-without-re.md +6 -0
  198. package/corpus/templates/clips/desktop/README.md +22 -6
  199. package/corpus/templates/clips/desktop/package.json +1 -1
  200. package/corpus/templates/clips/desktop/src/app.tsx +32 -19
  201. package/corpus/templates/clips/desktop/src/components/ReadinessPanel.tsx +15 -9
  202. package/corpus/templates/clips/desktop/src/lib/finalization-guard.ts +22 -0
  203. package/corpus/templates/clips/desktop/src/lib/permissions.ts +3 -1
  204. package/corpus/templates/clips/desktop/src/lib/recorder.ts +97 -120
  205. package/corpus/templates/clips/desktop/src/lib/updater.ts +26 -4
  206. package/corpus/templates/clips/desktop/src/overlays/finalizing.tsx +4 -8
  207. package/corpus/templates/clips/desktop/src-tauri/Cargo.toml +1 -1
  208. package/corpus/templates/clips/desktop/src-tauri/src/clips/mod.rs +2 -2
  209. package/corpus/templates/clips/desktop/src-tauri/src/permission_status.rs +11 -7
  210. package/corpus/templates/clips/desktop/src-tauri/tauri.linux.conf.json +11 -0
  211. package/corpus/templates/clips/netlify.toml +3 -0
  212. package/corpus/templates/clips/server/lib/post-finalize-dispatch.ts +106 -0
  213. package/corpus/templates/clips/server/lib/public-agent-context.ts +9 -1
  214. package/corpus/templates/clips/server/lib/resumable-upload-provider.ts +52 -0
  215. package/corpus/templates/clips/server/lib/s3-upload-provider.ts +433 -85
  216. package/corpus/templates/clips/server/lib/video-remux.ts +114 -0
  217. package/corpus/templates/clips/server/routes/api/_agent-native-background/post-finalize-worker.post.ts +109 -0
  218. package/corpus/templates/clips/server/routes/api/clips-updater.json.get.ts +22 -11
  219. package/corpus/templates/clips/server/routes/api/public-recording.get.ts +4 -2
  220. package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/abort.post.ts +47 -5
  221. package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/chunk.post.ts +10 -2
  222. package/corpus/templates/clips/shared/share-loader-response.ts +12 -0
  223. package/corpus/templates/clips/shared/transcript-status.ts +40 -0
  224. package/corpus/templates/content/.agents/skills/capture-learnings/SKILL.md +22 -9
  225. package/corpus/templates/content/.agents/skills/content/SKILL.md +57 -5
  226. package/corpus/templates/content/AGENTS.md +65 -55
  227. package/corpus/templates/content/actions/_builder-cms-read-client.ts +92 -23
  228. package/corpus/templates/content/actions/_database-source-utils.ts +207 -41
  229. package/corpus/templates/content/actions/_property-utils.ts +30 -2
  230. package/corpus/templates/content/actions/add-content-database-source-field-property.ts +316 -121
  231. package/corpus/templates/content/actions/attach-content-database-source.ts +41 -17
  232. package/corpus/templates/content/actions/change-content-database-source-role.ts +46 -8
  233. package/corpus/templates/content/actions/submit-content-database-form.ts +497 -0
  234. package/corpus/templates/content/actions/suggest-source-join-key.ts +8 -1
  235. package/corpus/templates/content/actions/update-content-database-view.ts +8 -1
  236. package/corpus/templates/content/actions/view-screen.ts +4 -1
  237. package/corpus/templates/content/agent-native.app-skill.json +1 -1
  238. package/corpus/templates/content/app/components/editor/database/DatabaseView.tsx +250 -64
  239. package/corpus/templates/content/app/components/editor/database/FormView.tsx +460 -0
  240. package/corpus/templates/content/app/components/editor/database/navigation-state.ts +3 -0
  241. package/corpus/templates/content/app/components/editor/database/settings.tsx +30 -37
  242. package/corpus/templates/content/app/components/editor/database/shared.tsx +2 -0
  243. package/corpus/templates/content/app/components/editor/database/view-config.ts +29 -1
  244. package/corpus/templates/content/app/components/ui/textarea.tsx +1 -0
  245. package/corpus/templates/content/app/hooks/use-content-database.ts +22 -0
  246. package/corpus/templates/content/app/i18n/zh-TW.ts +21 -0
  247. package/corpus/templates/content/app/i18n-data.ts +225 -0
  248. package/corpus/templates/content/changelog/2026-07-09-builder-source-refreshes-now-keep-mapped-fields-such-as-topi.md +6 -0
  249. package/corpus/templates/content/changelog/2026-07-10-builder-backed-properties-now-load-current-source-values-as-.md +6 -0
  250. package/corpus/templates/content/changelog/2026-07-10-builder-database-refreshes-now-stay-explicit-and-accurate.md +6 -0
  251. package/corpus/templates/content/changelog/2026-07-10-database-form-views-now-collect-ordered-required-answers-and.md +6 -0
  252. package/corpus/templates/content/changelog/2026-07-10-database-tables-now-use-a-quieter-more-compact-layout-with-c.md +6 -0
  253. package/corpus/templates/content/changelog/2026-07-10-slack-intake-routes-to-content-database-forms.md +6 -0
  254. package/corpus/templates/content/parity/matrix.md +1 -0
  255. package/corpus/templates/content/parity/matrix.ts +18 -0
  256. package/corpus/templates/content/shared/api.ts +28 -1
  257. package/corpus/templates/content/shared/database-form.ts +53 -0
  258. package/corpus/templates/design/.agents/skills/capture-learnings/SKILL.md +22 -9
  259. package/corpus/templates/design/.agents/skills/design-generation/SKILL.md +26 -0
  260. package/corpus/templates/design/.agents/skills/design-systems/SKILL.md +85 -12
  261. package/corpus/templates/design/AGENTS.md +72 -18
  262. package/corpus/templates/design/DESIGN.md +1 -1
  263. package/corpus/templates/design/DEVELOPING.md +1 -1
  264. package/corpus/templates/design/FIGMA_INTEROPERABILITY.md +116 -0
  265. package/corpus/templates/design/actions/create-design-from-template.ts +220 -0
  266. package/corpus/templates/design/actions/create-design-system.ts +92 -16
  267. package/corpus/templates/design/actions/delete-design-template.ts +28 -0
  268. package/corpus/templates/design/actions/delete-file.ts +7 -0
  269. package/corpus/templates/design/actions/edit-design.ts +3 -0
  270. package/corpus/templates/design/actions/export-design-as-figma-svg.ts +137 -5
  271. package/corpus/templates/design/actions/export-pdf.ts +1 -1
  272. package/corpus/templates/design/actions/generate-design.ts +3 -0
  273. package/corpus/templates/design/actions/get-design-snapshot.ts +9 -0
  274. package/corpus/templates/design/actions/get-figma-connection-status.ts +26 -0
  275. package/corpus/templates/design/actions/get-figma-design-context.ts +138 -0
  276. package/corpus/templates/design/actions/get-figma-styles.ts +2 -2
  277. package/corpus/templates/design/actions/import-figma-clipboard.ts +112 -16
  278. package/corpus/templates/design/actions/import-figma-frame.ts +15 -4
  279. package/corpus/templates/design/actions/index-design-system-with-builder.ts +4 -0
  280. package/corpus/templates/design/actions/list-design-templates.ts +118 -0
  281. package/corpus/templates/design/actions/navigate.ts +16 -2
  282. package/corpus/templates/design/actions/provider-api-request.ts +11 -1
  283. package/corpus/templates/design/actions/save-design-as-template.ts +156 -0
  284. package/corpus/templates/design/actions/set-active-breakpoint.ts +13 -4
  285. package/corpus/templates/design/actions/take-design-screenshot.ts +73 -3
  286. package/corpus/templates/design/actions/update-file.ts +39 -22
  287. package/corpus/templates/design/actions/view-screen.ts +36 -1
  288. package/corpus/templates/design/actions/write-local-file.ts +50 -38
  289. package/corpus/templates/design/app/components/design/AutoLayoutSuggestionDialog.tsx +151 -0
  290. package/corpus/templates/design/app/components/design/CanvasContextMenu.tsx +20 -0
  291. package/corpus/templates/design/app/components/design/DesignCanvas.tsx +251 -22
  292. package/corpus/templates/design/app/components/design/DesignEditorSkeleton.tsx +3 -3
  293. package/corpus/templates/design/app/components/design/DesignImportPanel.tsx +384 -9
  294. package/corpus/templates/design/app/components/design/EditPanel.tsx +105 -32
  295. package/corpus/templates/design/app/components/design/MultiScreenCanvas.tsx +58 -28
  296. package/corpus/templates/design/app/components/design/TweaksPanel.tsx +6 -0
  297. package/corpus/templates/design/app/components/design/bridge/editor-chrome.bridge.ts +539 -53
  298. package/corpus/templates/design/app/components/design/bridge/embedded-wheel.bridge.ts +40 -0
  299. package/corpus/templates/design/app/components/design/code-workbench/CodeWorkbench.tsx +1 -0
  300. package/corpus/templates/design/app/components/design/code-workbench/explorer/ExplorerView.tsx +1 -0
  301. package/corpus/templates/design/app/components/design/code-workbench/explorer/FileTree.tsx +5 -1
  302. package/corpus/templates/design/app/components/design/code-workbench/workspace/create-providers.ts +2 -0
  303. package/corpus/templates/design/app/components/design/code-workbench/workspace/localhost-provider.ts +3 -1
  304. package/corpus/templates/design/app/components/design/code-workbench/workspace/types.ts +2 -0
  305. package/corpus/templates/design/app/components/design/edit-panel/element-identity.ts +19 -0
  306. package/corpus/templates/design/app/components/design/edit-panel/frame-presets-panel.tsx +1 -0
  307. package/corpus/templates/design/app/components/design/edit-panel/interaction-state-helpers.ts +27 -0
  308. package/corpus/templates/design/app/components/design/inspector/InteractionStatePanel.tsx +137 -81
  309. package/corpus/templates/design/app/components/design/inspector/frame-size-presets.ts +25 -5
  310. package/corpus/templates/design/app/components/design/multi-screen/chrome-transitions.ts +1 -1
  311. package/corpus/templates/design/app/components/design/multi-screen/frame-geometry.ts +220 -3
  312. package/corpus/templates/design/app/components/design/multi-screen/overview-layout.ts +13 -0
  313. package/corpus/templates/design/app/components/design/multi-screen/types.ts +22 -1
  314. package/corpus/templates/design/app/components/design/types.ts +4 -0
  315. package/corpus/templates/design/app/components/design-system/ProductionDesignSystemShowcase.tsx +208 -0
  316. package/corpus/templates/design/app/components/editor/FigmaLinkComposerBubble.tsx +321 -0
  317. package/corpus/templates/design/app/components/editor/PromptDialog.tsx +24 -4
  318. package/corpus/templates/design/app/components/layout/Layout.tsx +16 -2
  319. package/corpus/templates/design/app/components/layout/Sidebar.tsx +2 -0
  320. package/corpus/templates/design/app/components/templates/TemplatePreview.tsx +72 -0
  321. package/corpus/templates/design/app/global.css +2 -35
  322. package/corpus/templates/design/app/hooks/use-navigation-state.ts +10 -0
  323. package/corpus/templates/design/app/i18n/zh-TW.ts +127 -5
  324. package/corpus/templates/design/app/i18n-breakpoints.ts +209 -0
  325. package/corpus/templates/design/app/i18n-data.ts +1317 -59
  326. package/corpus/templates/design/app/i18n-template-feature.ts +458 -0
  327. package/corpus/templates/design/app/lib/design-clipboard.ts +202 -0
  328. package/corpus/templates/design/app/lib/design-file-upload.ts +87 -0
  329. package/corpus/templates/design/app/lib/design-import.ts +168 -11
  330. package/corpus/templates/design/app/lib/desktop-design-preview.ts +423 -0
  331. package/corpus/templates/design/app/lib/figma-clipboard.ts +74 -8
  332. package/corpus/templates/design/app/lib/figma-connection.ts +161 -0
  333. package/corpus/templates/design/app/lib/figma-svg-copy.ts +814 -22
  334. package/corpus/templates/design/app/lib/figma-url.ts +77 -0
  335. package/corpus/templates/design/app/lib/pending-generation.ts +35 -0
  336. package/corpus/templates/design/app/pages/DesignSystems.tsx +236 -177
  337. package/corpus/templates/design/app/pages/Index.tsx +38 -0
  338. package/corpus/templates/design/app/pages/Templates.tsx +498 -0
  339. package/corpus/templates/design/app/pages/design-editor/auto-layout-suggestion.ts +328 -0
  340. package/corpus/templates/design/app/pages/design-editor/clone-idrefs.ts +113 -0
  341. package/corpus/templates/design/app/pages/design-editor/created-screen-navigation.ts +55 -0
  342. package/corpus/templates/design/app/pages/design-editor/editor-session.ts +32 -0
  343. package/corpus/templates/design/app/pages/design-editor/editor-state.ts +49 -2
  344. package/corpus/templates/design/app/pages/design-editor/export-capture.ts +296 -0
  345. package/corpus/templates/design/app/pages/design-editor/history.ts +101 -2
  346. package/corpus/templates/design/app/pages/design-editor/layout-operations.ts +28 -1
  347. package/corpus/templates/design/app/pages/design-editor/overview-camera.ts +34 -0
  348. package/corpus/templates/design/app/pages/design-editor/pending-edits.ts +202 -6
  349. package/corpus/templates/design/app/pages/design-editor/pending-structure-verification.ts +92 -0
  350. package/corpus/templates/design/app/pages/design-editor/save-failure.ts +58 -0
  351. package/corpus/templates/design/app/routes/templates.tsx +4 -6
  352. package/corpus/templates/design/changelog/2026-07-10-app-workspaces-now-use-clean-borderless-main-surfaces-throug.md +6 -0
  353. package/corpus/templates/design/changelog/2026-07-10-ask-chat-what-s-in-a-figma-file-or-frame-structure-screensho.md +6 -0
  354. package/corpus/templates/design/changelog/2026-07-10-canvas-edits-now-reject-malformed-html-before-it-can-corrupt.md +6 -0
  355. package/corpus/templates/design/changelog/2026-07-10-complex-designs-now-export-as-valid-secure-svgs-and-crisp-ra.md +6 -0
  356. package/corpus/templates/design/changelog/2026-07-10-complex-figma-masks-arcs-rich-text-transformed-images-and-ad.md +6 -0
  357. package/corpus/templates/design/changelog/2026-07-10-copied-layers-paste-across-designs-and-browser-tabs.md +6 -0
  358. package/corpus/templates/design/changelog/2026-07-10-copy-and-download-editable-figma-svg.md +6 -0
  359. package/corpus/templates/design/changelog/2026-07-10-copying-design-text-now-pastes-readable-text-into-other-apps.md +6 -0
  360. package/corpus/templates/design/changelog/2026-07-10-deleted-screens-can-be-restored-with-undo-and-removed-again-.md +6 -0
  361. package/corpus/templates/design/changelog/2026-07-10-design-changes-now-save-before-switching-apps-and-retry-when.md +6 -0
  362. package/corpus/templates/design/changelog/2026-07-10-design-stays-usable-on-phones-by-keeping-editor-panels-and-f.md +6 -0
  363. package/corpus/templates/design/changelog/2026-07-10-download-all-screens-as-one-multi-page-pdf-from-the-overview.md +6 -0
  364. package/corpus/templates/design/changelog/2026-07-10-duplicated-layers-now-keep-labels-aria-relationships-fragmen.md +6 -0
  365. package/corpus/templates/design/changelog/2026-07-10-fig-import-results-stay-compact.md +6 -0
  366. package/corpus/templates/design/changelog/2026-07-10-figma-imports-now-load-real-fonts-fix-rotated-gradient-dashe.md +6 -0
  367. package/corpus/templates/design/changelog/2026-07-10-figma-links-in-chat-and-the-import-tab-now-offer-secure-one-.md +6 -0
  368. package/corpus/templates/design/changelog/2026-07-10-fixed-cmd-z-not-restoring-content-after-an-agent-driven-desi.md +6 -0
  369. package/corpus/templates/design/changelog/2026-07-10-fixed-download-pdf-being-unreachable-from-the-export-panel-e.md +6 -0
  370. package/corpus/templates/design/changelog/2026-07-10-fixed-dragging-a-layer-out-of-an-auto-layout-row-column-no-l.md +6 -0
  371. package/corpus/templates/design/changelog/2026-07-10-fixed-figma-svg-export-text-wrapping-sizing-and-inner-layer.md +6 -0
  372. package/corpus/templates/design/changelog/2026-07-10-fixed-hiding-or-locking-one-layer-no-longer-hides-or-blocks-.md +6 -0
  373. package/corpus/templates/design/changelog/2026-07-10-fixed-png-screenshots-of-tall-screens-being-cropped-to-one-v.md +6 -0
  374. package/corpus/templates/design/changelog/2026-07-10-fixed-png-svg-exports-capturing-broken-layout-when-webfonts-.md +6 -0
  375. package/corpus/templates/design/changelog/2026-07-10-frame-tool-now-offers-standard-ad-unit-size-presets-medium-r.md +6 -0
  376. package/corpus/templates/design/changelog/2026-07-10-full-view-controls-stay-within-their-frame-instead-of-coveri.md +6 -0
  377. package/corpus/templates/design/changelog/2026-07-10-hover-focus-focus-visible-pressed-and-disabled-states-now-pr.md +6 -0
  378. package/corpus/templates/design/changelog/2026-07-10-layer-drops-now-land-in-the-intended-grid-row-stay-visually-.md +6 -0
  379. package/corpus/templates/design/changelog/2026-07-10-local-code-workspaces-now-keep-unsaved-edits-across-panel-sw.md +6 -0
  380. package/corpus/templates/design/changelog/2026-07-10-local-visual-editing-now-keeps-authenticated-sessions-shared.md +6 -0
  381. package/corpus/templates/design/changelog/2026-07-10-long-running-agent-work-no-longer-shows-a-premature-stuck-wa.md +6 -0
  382. package/corpus/templates/design/changelog/2026-07-10-managed-figma-connections-are-recognized-automatically.md +6 -0
  383. package/corpus/templates/design/changelog/2026-07-10-new-designs-can-open-directly-in-the-editor-without-a-pr.md +6 -0
  384. package/corpus/templates/design/changelog/2026-07-10-new-screens-are-selected-and-revealed-immediately.md +6 -0
  385. package/corpus/templates/design/changelog/2026-07-10-new-text-layers-undo-as-one-safe-creation.md +6 -0
  386. package/corpus/templates/design/changelog/2026-07-10-preview-and-apply-inferred-auto-layout-without-changing-yo.md +5 -0
  387. package/corpus/templates/design/changelog/2026-07-10-print-pdf-exports-and-paper-size-presets-letter-a4-now-match.md +6 -0
  388. package/corpus/templates/design/changelog/2026-07-10-responsive-frame-editing.md +6 -0
  389. package/corpus/templates/design/changelog/2026-07-10-reusable-design-templates.md +6 -0
  390. package/corpus/templates/design/changelog/2026-07-10-screen-overview-frames-now-use-a-clearer-interact-action-wit.md +6 -0
  391. package/corpus/templates/design/changelog/2026-07-10-start-designs-from-source-linked-material-3-carbon-or-primer.md +6 -0
  392. package/corpus/templates/design/changelog/2026-07-10-tweaks-guidance.md +6 -0
  393. package/corpus/templates/design/changelog/2026-07-10-uploaded-fig-files-can-now-become-editable-design-screens-wi.md +6 -0
  394. package/corpus/templates/design/e2e/helpers.ts +3 -3
  395. package/corpus/templates/design/package.json +2 -0
  396. package/corpus/templates/design/scripts/qa-figma-stress-import.ts +96 -0
  397. package/corpus/templates/design/server/db/index.ts +10 -0
  398. package/corpus/templates/design/server/db/schema.ts +44 -0
  399. package/corpus/templates/design/server/handlers/import-design-file.ts +114 -80
  400. package/corpus/templates/design/server/handlers/index-design-system-with-builder.ts +19 -6
  401. package/corpus/templates/design/server/lib/design-export.ts +240 -3
  402. package/corpus/templates/design/server/lib/design-template-data.ts +89 -0
  403. package/corpus/templates/design/server/lib/design-to-figma-svg.ts +250 -26
  404. package/corpus/templates/design/server/lib/fig-file-decoder.ts +839 -0
  405. package/corpus/templates/design/server/lib/fig-file-import.ts +287 -0
  406. package/corpus/templates/design/server/lib/fig-file-limits.ts +3 -0
  407. package/corpus/templates/design/server/lib/fig-file-to-html.ts +2568 -0
  408. package/corpus/templates/design/server/lib/figma-design-context.ts +359 -0
  409. package/corpus/templates/design/server/lib/figma-node-import.ts +478 -22
  410. package/corpus/templates/design/server/lib/figma-node-to-html.ts +554 -29
  411. package/corpus/templates/design/server/lib/local-figma-qa-upload.ts +112 -0
  412. package/corpus/templates/design/server/lib/verify-write-grant.ts +16 -2
  413. package/corpus/templates/design/server/lib/visible-clipboard-html.ts +13 -3
  414. package/corpus/templates/design/server/plugins/agent-chat.ts +7 -0
  415. package/corpus/templates/design/server/plugins/db.ts +42 -0
  416. package/corpus/templates/design/server/plugins/local-figma-qa-upload.ts +7 -0
  417. package/corpus/templates/design/server/register-secrets.ts +8 -8
  418. package/corpus/templates/design/server/routes/api/qa-figma-import-assets/[assetId].get.ts +46 -0
  419. package/corpus/templates/design/server/source-workspace.ts +104 -12
  420. package/corpus/templates/design/shared/code-layer.ts +105 -28
  421. package/corpus/templates/design/shared/design-system-templates.ts +301 -0
  422. package/corpus/templates/design/shared/design-template-presets.ts +195 -0
  423. package/corpus/templates/design/shared/figma-url.ts +8 -0
  424. package/corpus/templates/design/shared/html-integrity.ts +306 -0
  425. package/corpus/templates/design/shared/interaction-states.ts +318 -23
  426. package/corpus/templates/design/shared/locked-layers.ts +151 -0
  427. package/corpus/templates/dispatch/.agents/skills/capture-learnings/SKILL.md +22 -9
  428. package/corpus/templates/dispatch/app/i18n/zh-TW.ts +48 -0
  429. package/corpus/templates/dispatch/app/i18n-data.ts +536 -1
  430. package/corpus/templates/dispatch/changelog/2026-07-10-connect-slack-workspaces-with-oauth-and-manage-channel-ident.md +6 -0
  431. package/corpus/templates/dispatch/changelog/2026-07-10-microsoft-teams-bots-and-discord-slash-commands-can-now-conn.md +6 -0
  432. package/corpus/templates/dispatch/changelog/2026-07-10-slack-and-telegram-now-route-uptime-monitor-requests-to-anal.md +6 -0
  433. package/corpus/templates/forms/.agents/skills/capture-learnings/SKILL.md +22 -9
  434. package/corpus/templates/forms/.agents/skills/form-publishing/SKILL.md +7 -0
  435. package/corpus/templates/forms/AGENTS.md +4 -0
  436. package/corpus/templates/forms/actions/create-form.ts +44 -7
  437. package/corpus/templates/forms/actions/lib/assert-publishable-form.ts +38 -0
  438. package/corpus/templates/forms/actions/patch-form-fields.ts +4 -0
  439. package/corpus/templates/forms/actions/update-form.ts +2 -36
  440. package/corpus/templates/forms/app/i18n/ar-SA.ts +3 -0
  441. package/corpus/templates/forms/app/i18n/de-DE.ts +3 -0
  442. package/corpus/templates/forms/app/i18n/en-US.ts +3 -0
  443. package/corpus/templates/forms/app/i18n/es-ES.ts +3 -0
  444. package/corpus/templates/forms/app/i18n/fr-FR.ts +3 -0
  445. package/corpus/templates/forms/app/i18n/hi-IN.ts +3 -0
  446. package/corpus/templates/forms/app/i18n/ja-JP.ts +3 -0
  447. package/corpus/templates/forms/app/i18n/ko-KR.ts +3 -0
  448. package/corpus/templates/forms/app/i18n/pt-BR.ts +3 -0
  449. package/corpus/templates/forms/app/i18n/zh-CN.ts +2 -0
  450. package/corpus/templates/forms/app/i18n/zh-TW.ts +3 -0
  451. package/corpus/templates/forms/app/pages/FormBuilderPage.tsx +17 -0
  452. package/corpus/templates/forms/changelog/2026-07-10-agent-created-published-forms-now-return-the-anonymous-publi.md +6 -0
  453. package/corpus/templates/forms/changelog/2026-07-10-published-forms-can-no-longer-be-edited-into-an-unusable-emp.md +6 -0
  454. package/corpus/templates/forms/server/handlers/submissions.ts +4 -3
  455. package/corpus/templates/forms/server/plugins/agent-chat.ts +1 -0
  456. package/corpus/templates/forms/shared/types.ts +5 -0
  457. package/corpus/templates/mail/.agents/skills/capture-learnings/SKILL.md +22 -9
  458. package/corpus/templates/mail/app/components/layout/AppLayout.tsx +2 -2
  459. package/corpus/templates/mail/changelog/2026-07-10-mail-navigation-now-uses-a-clean-borderless-drawer.md +6 -0
  460. package/corpus/templates/plan/.agents/skills/capture-learnings/SKILL.md +22 -9
  461. package/corpus/templates/plan/app/lib/plan-local-bridge.ts +4 -1
  462. package/corpus/templates/plan/changelog/2026-07-10-local-plans-now-keep-valid-content-visible-when-one-generate.md +6 -0
  463. package/corpus/templates/plan/server/lib/local-plan-files.ts +4 -1
  464. package/corpus/templates/slides/.agents/skills/capture-learnings/SKILL.md +22 -9
  465. package/dist/a2a/artifact-response.d.ts.map +1 -1
  466. package/dist/a2a/artifact-response.js +88 -2
  467. package/dist/a2a/artifact-response.js.map +1 -1
  468. package/dist/a2a/client.d.ts +9 -0
  469. package/dist/a2a/client.d.ts.map +1 -1
  470. package/dist/a2a/client.js +1 -0
  471. package/dist/a2a/client.js.map +1 -1
  472. package/dist/a2a/handlers.d.ts.map +1 -1
  473. package/dist/a2a/handlers.js +24 -69
  474. package/dist/a2a/handlers.js.map +1 -1
  475. package/dist/a2a/types.d.ts +2 -0
  476. package/dist/a2a/types.d.ts.map +1 -1
  477. package/dist/a2a/types.js.map +1 -1
  478. package/dist/agent/durable-background.d.ts +11 -0
  479. package/dist/agent/durable-background.d.ts.map +1 -1
  480. package/dist/agent/durable-background.js +17 -0
  481. package/dist/agent/durable-background.js.map +1 -1
  482. package/dist/agent/production-agent.d.ts +5 -3
  483. package/dist/agent/production-agent.d.ts.map +1 -1
  484. package/dist/agent/production-agent.js +34 -8
  485. package/dist/agent/production-agent.js.map +1 -1
  486. package/dist/agent/run-manager.d.ts +44 -2
  487. package/dist/agent/run-manager.d.ts.map +1 -1
  488. package/dist/agent/run-manager.js +124 -18
  489. package/dist/agent/run-manager.js.map +1 -1
  490. package/dist/agent/run-store.d.ts +109 -0
  491. package/dist/agent/run-store.d.ts.map +1 -1
  492. package/dist/agent/run-store.js +274 -37
  493. package/dist/agent/run-store.js.map +1 -1
  494. package/dist/agent/types.d.ts +22 -0
  495. package/dist/agent/types.d.ts.map +1 -1
  496. package/dist/agent/types.js.map +1 -1
  497. package/dist/audit/record.d.ts.map +1 -1
  498. package/dist/audit/record.js +29 -0
  499. package/dist/audit/record.js.map +1 -1
  500. package/dist/audit/store.d.ts.map +1 -1
  501. package/dist/audit/store.js +62 -3
  502. package/dist/audit/store.js.map +1 -1
  503. package/dist/audit/types.d.ts +13 -0
  504. package/dist/audit/types.d.ts.map +1 -1
  505. package/dist/audit/types.js.map +1 -1
  506. package/dist/automation/index.d.ts +193 -0
  507. package/dist/automation/index.d.ts.map +1 -0
  508. package/dist/automation/index.js +464 -0
  509. package/dist/automation/index.js.map +1 -0
  510. package/dist/cli/create.d.ts.map +1 -1
  511. package/dist/cli/create.js +10 -3
  512. package/dist/cli/create.js.map +1 -1
  513. package/dist/cli/design-connect.d.ts.map +1 -1
  514. package/dist/cli/design-connect.js +492 -35
  515. package/dist/cli/design-connect.js.map +1 -1
  516. package/dist/client/AgentPanel.d.ts +7 -1
  517. package/dist/client/AgentPanel.d.ts.map +1 -1
  518. package/dist/client/AgentPanel.js +32 -8
  519. package/dist/client/AgentPanel.js.map +1 -1
  520. package/dist/client/AssistantChat.d.ts +15 -0
  521. package/dist/client/AssistantChat.d.ts.map +1 -1
  522. package/dist/client/AssistantChat.js +115 -47
  523. package/dist/client/AssistantChat.js.map +1 -1
  524. package/dist/client/MultiTabAssistantChat.d.ts.map +1 -1
  525. package/dist/client/MultiTabAssistantChat.js +1 -1
  526. package/dist/client/MultiTabAssistantChat.js.map +1 -1
  527. package/dist/client/RunStuckBanner.d.ts +14 -1
  528. package/dist/client/RunStuckBanner.d.ts.map +1 -1
  529. package/dist/client/RunStuckBanner.js +35 -7
  530. package/dist/client/RunStuckBanner.js.map +1 -1
  531. package/dist/client/agent-chat-adapter.d.ts +4 -1
  532. package/dist/client/agent-chat-adapter.d.ts.map +1 -1
  533. package/dist/client/agent-chat-adapter.js +97 -16
  534. package/dist/client/agent-chat-adapter.js.map +1 -1
  535. package/dist/client/automation.d.ts +14 -0
  536. package/dist/client/automation.d.ts.map +1 -0
  537. package/dist/client/automation.js +9 -0
  538. package/dist/client/automation.js.map +1 -0
  539. package/dist/client/chat/run-recovery.d.ts +4 -0
  540. package/dist/client/chat/run-recovery.d.ts.map +1 -1
  541. package/dist/client/chat/run-recovery.js +12 -10
  542. package/dist/client/chat/run-recovery.js.map +1 -1
  543. package/dist/client/composer/TiptapComposer.d.ts.map +1 -1
  544. package/dist/client/composer/TiptapComposer.js +8 -0
  545. package/dist/client/composer/TiptapComposer.js.map +1 -1
  546. package/dist/client/index.d.ts +2 -0
  547. package/dist/client/index.d.ts.map +1 -1
  548. package/dist/client/index.js +2 -0
  549. package/dist/client/index.js.map +1 -1
  550. package/dist/client/integrations/api.d.ts +115 -0
  551. package/dist/client/integrations/api.d.ts.map +1 -0
  552. package/dist/client/integrations/api.js +123 -0
  553. package/dist/client/integrations/api.js.map +1 -0
  554. package/dist/client/integrations/index.d.ts +1 -0
  555. package/dist/client/integrations/index.d.ts.map +1 -1
  556. package/dist/client/integrations/index.js +1 -0
  557. package/dist/client/integrations/index.js.map +1 -1
  558. package/dist/client/transcription/use-live-transcription.d.ts.map +1 -1
  559. package/dist/client/transcription/use-live-transcription.js +59 -5
  560. package/dist/client/transcription/use-live-transcription.js.map +1 -1
  561. package/dist/client/use-run-stuck-detection.d.ts +16 -1
  562. package/dist/client/use-run-stuck-detection.d.ts.map +1 -1
  563. package/dist/client/use-run-stuck-detection.js +23 -4
  564. package/dist/client/use-run-stuck-detection.js.map +1 -1
  565. package/dist/collab/awareness.d.ts +2 -2
  566. package/dist/collab/awareness.d.ts.map +1 -1
  567. package/dist/deploy/build.d.ts.map +1 -1
  568. package/dist/deploy/build.js +49 -4
  569. package/dist/deploy/build.js.map +1 -1
  570. package/dist/deploy/workspace-deploy.d.ts.map +1 -1
  571. package/dist/deploy/workspace-deploy.js +31 -2
  572. package/dist/deploy/workspace-deploy.js.map +1 -1
  573. package/dist/file-upload/types.d.ts +2 -0
  574. package/dist/file-upload/types.d.ts.map +1 -1
  575. package/dist/file-upload/types.js.map +1 -1
  576. package/dist/index.d.ts +2 -0
  577. package/dist/index.d.ts.map +1 -1
  578. package/dist/index.js +2 -0
  579. package/dist/index.js.map +1 -1
  580. package/dist/integrations/a2a-continuations-store.d.ts.map +1 -1
  581. package/dist/integrations/a2a-continuations-store.js +6 -4
  582. package/dist/integrations/a2a-continuations-store.js.map +1 -1
  583. package/dist/integrations/adapters/discord.d.ts +3 -0
  584. package/dist/integrations/adapters/discord.d.ts.map +1 -0
  585. package/dist/integrations/adapters/discord.js +261 -0
  586. package/dist/integrations/adapters/discord.js.map +1 -0
  587. package/dist/integrations/adapters/index.d.ts +4 -0
  588. package/dist/integrations/adapters/index.d.ts.map +1 -0
  589. package/dist/integrations/adapters/index.js +26 -0
  590. package/dist/integrations/adapters/index.js.map +1 -0
  591. package/dist/integrations/adapters/microsoft-teams.d.ts +5 -0
  592. package/dist/integrations/adapters/microsoft-teams.d.ts.map +1 -0
  593. package/dist/integrations/adapters/microsoft-teams.js +295 -0
  594. package/dist/integrations/adapters/microsoft-teams.js.map +1 -0
  595. package/dist/integrations/adapters/slack.d.ts +8 -2
  596. package/dist/integrations/adapters/slack.d.ts.map +1 -1
  597. package/dist/integrations/adapters/slack.js +736 -27
  598. package/dist/integrations/adapters/slack.js.map +1 -1
  599. package/dist/integrations/adapters/telegram.d.ts +0 -2
  600. package/dist/integrations/adapters/telegram.d.ts.map +1 -1
  601. package/dist/integrations/adapters/telegram.js +49 -15
  602. package/dist/integrations/adapters/telegram.js.map +1 -1
  603. package/dist/integrations/adapters/whatsapp.d.ts +0 -2
  604. package/dist/integrations/adapters/whatsapp.d.ts.map +1 -1
  605. package/dist/integrations/adapters/whatsapp.js +40 -17
  606. package/dist/integrations/adapters/whatsapp.js.map +1 -1
  607. package/dist/integrations/catalog.d.ts +75 -0
  608. package/dist/integrations/catalog.d.ts.map +1 -0
  609. package/dist/integrations/catalog.js +451 -0
  610. package/dist/integrations/catalog.js.map +1 -0
  611. package/dist/integrations/controls-store.d.ts +44 -0
  612. package/dist/integrations/controls-store.d.ts.map +1 -0
  613. package/dist/integrations/controls-store.js +129 -0
  614. package/dist/integrations/controls-store.js.map +1 -0
  615. package/dist/integrations/index.d.ts +13 -1
  616. package/dist/integrations/index.d.ts.map +1 -1
  617. package/dist/integrations/index.js +9 -0
  618. package/dist/integrations/index.js.map +1 -1
  619. package/dist/integrations/installations-store.d.ts +112 -0
  620. package/dist/integrations/installations-store.d.ts.map +1 -0
  621. package/dist/integrations/installations-store.js +493 -0
  622. package/dist/integrations/installations-store.js.map +1 -0
  623. package/dist/integrations/integration-memory.d.ts +24 -0
  624. package/dist/integrations/integration-memory.d.ts.map +1 -0
  625. package/dist/integrations/integration-memory.js +136 -0
  626. package/dist/integrations/integration-memory.js.map +1 -0
  627. package/dist/integrations/pending-tasks-retry-job.d.ts.map +1 -1
  628. package/dist/integrations/pending-tasks-retry-job.js +6 -5
  629. package/dist/integrations/pending-tasks-retry-job.js.map +1 -1
  630. package/dist/integrations/pending-tasks-store.d.ts +17 -0
  631. package/dist/integrations/pending-tasks-store.d.ts.map +1 -1
  632. package/dist/integrations/pending-tasks-store.js +71 -5
  633. package/dist/integrations/pending-tasks-store.js.map +1 -1
  634. package/dist/integrations/plugin.d.ts.map +1 -1
  635. package/dist/integrations/plugin.js +520 -35
  636. package/dist/integrations/plugin.js.map +1 -1
  637. package/dist/integrations/scope-store.d.ts +65 -0
  638. package/dist/integrations/scope-store.d.ts.map +1 -0
  639. package/dist/integrations/scope-store.js +361 -0
  640. package/dist/integrations/scope-store.js.map +1 -0
  641. package/dist/integrations/slack-manifest.d.ts +66 -0
  642. package/dist/integrations/slack-manifest.d.ts.map +1 -0
  643. package/dist/integrations/slack-manifest.js +70 -0
  644. package/dist/integrations/slack-manifest.js.map +1 -0
  645. package/dist/integrations/slack-oauth.d.ts +99 -0
  646. package/dist/integrations/slack-oauth.d.ts.map +1 -0
  647. package/dist/integrations/slack-oauth.js +226 -0
  648. package/dist/integrations/slack-oauth.js.map +1 -0
  649. package/dist/integrations/types.d.ts +144 -0
  650. package/dist/integrations/types.d.ts.map +1 -1
  651. package/dist/integrations/types.js +16 -1
  652. package/dist/integrations/types.js.map +1 -1
  653. package/dist/integrations/usage-budget-store.d.ts +84 -0
  654. package/dist/integrations/usage-budget-store.d.ts.map +1 -0
  655. package/dist/integrations/usage-budget-store.js +650 -0
  656. package/dist/integrations/usage-budget-store.js.map +1 -0
  657. package/dist/integrations/webhook-handler.d.ts +4 -0
  658. package/dist/integrations/webhook-handler.d.ts.map +1 -1
  659. package/dist/integrations/webhook-handler.js +415 -47
  660. package/dist/integrations/webhook-handler.js.map +1 -1
  661. package/dist/jobs/scheduler.d.ts +6 -0
  662. package/dist/jobs/scheduler.d.ts.map +1 -1
  663. package/dist/jobs/scheduler.js +83 -4
  664. package/dist/jobs/scheduler.js.map +1 -1
  665. package/dist/jobs/tools.d.ts.map +1 -1
  666. package/dist/jobs/tools.js +43 -11
  667. package/dist/jobs/tools.js.map +1 -1
  668. package/dist/provider-api/index.d.ts +4 -4
  669. package/dist/provider-api/index.d.ts.map +1 -1
  670. package/dist/provider-api/index.js +72 -1
  671. package/dist/provider-api/index.js.map +1 -1
  672. package/dist/resources/handlers.d.ts.map +1 -1
  673. package/dist/resources/handlers.js +57 -15
  674. package/dist/resources/handlers.js.map +1 -1
  675. package/dist/resources/script-helpers.d.ts.map +1 -1
  676. package/dist/resources/script-helpers.js +34 -8
  677. package/dist/resources/script-helpers.js.map +1 -1
  678. package/dist/resources/store.d.ts +10 -0
  679. package/dist/resources/store.d.ts.map +1 -1
  680. package/dist/resources/store.js +54 -47
  681. package/dist/resources/store.js.map +1 -1
  682. package/dist/scripts/call-agent.d.ts.map +1 -1
  683. package/dist/scripts/call-agent.js +106 -1
  684. package/dist/scripts/call-agent.js.map +1 -1
  685. package/dist/server/agent-chat-plugin.d.ts +15 -4
  686. package/dist/server/agent-chat-plugin.d.ts.map +1 -1
  687. package/dist/server/agent-chat-plugin.js +248 -113
  688. package/dist/server/agent-chat-plugin.js.map +1 -1
  689. package/dist/server/auth.d.ts.map +1 -1
  690. package/dist/server/auth.js +10 -14
  691. package/dist/server/auth.js.map +1 -1
  692. package/dist/server/builder-design-systems.d.ts +3 -1
  693. package/dist/server/builder-design-systems.d.ts.map +1 -1
  694. package/dist/server/builder-design-systems.js +9 -2
  695. package/dist/server/builder-design-systems.js.map +1 -1
  696. package/dist/server/edge.d.ts +1 -1
  697. package/dist/server/edge.d.ts.map +1 -1
  698. package/dist/server/edge.js +1 -1
  699. package/dist/server/edge.js.map +1 -1
  700. package/dist/server/index.d.ts +2 -1
  701. package/dist/server/index.d.ts.map +1 -1
  702. package/dist/server/index.js +2 -1
  703. package/dist/server/index.js.map +1 -1
  704. package/dist/server/request-context.d.ts +18 -0
  705. package/dist/server/request-context.d.ts.map +1 -1
  706. package/dist/server/request-context.js.map +1 -1
  707. package/dist/server/social-og-image.d.ts.map +1 -1
  708. package/dist/server/social-og-image.js +3 -2
  709. package/dist/server/social-og-image.js.map +1 -1
  710. package/dist/server/transcribe-voice.d.ts +1 -1
  711. package/dist/styles/agent-native.css +62 -44
  712. package/dist/templates/default/.agents/skills/capture-learnings/SKILL.md +22 -9
  713. package/dist/templates/default/AGENTS.md +7 -3
  714. package/dist/templates/workspace-core/.agents/skills/authentication/SKILL.md +1 -1
  715. package/dist/templates/workspace-core/.agents/skills/capture-learnings/SKILL.md +22 -9
  716. package/dist/templates/workspace-core/.agents/skills/extension-points/SKILL.md +6 -3
  717. package/dist/templates/workspace-core/.agents/skills/extensions/SKILL.md +25 -0
  718. package/dist/templates/workspace-core/.agents/skills/integration-webhooks/SKILL.md +15 -0
  719. package/dist/templates/workspace-core/AGENTS.md +3 -2
  720. package/dist/usage/store.d.ts +7 -0
  721. package/dist/usage/store.d.ts.map +1 -1
  722. package/dist/usage/store.js +24 -3
  723. package/dist/usage/store.js.map +1 -1
  724. package/docs/content/automation-connectors.mdx +80 -0
  725. package/docs/content/extensions.mdx +8 -0
  726. package/docs/content/locales/ar-SA/extensions.mdx +8 -0
  727. package/docs/content/locales/ar-SA/messaging.mdx +84 -15
  728. package/docs/content/locales/ar-SA/template-clips.mdx +1 -0
  729. package/docs/content/locales/ar-SA/template-design.mdx +1 -0
  730. package/docs/content/locales/de-DE/extensions.mdx +10 -0
  731. package/docs/content/locales/de-DE/messaging.mdx +92 -15
  732. package/docs/content/locales/de-DE/template-clips.mdx +1 -0
  733. package/docs/content/locales/de-DE/template-design.mdx +1 -0
  734. package/docs/content/locales/es-ES/extensions.mdx +10 -0
  735. package/docs/content/locales/es-ES/messaging.mdx +91 -15
  736. package/docs/content/locales/es-ES/template-clips.mdx +1 -0
  737. package/docs/content/locales/es-ES/template-design.mdx +1 -0
  738. package/docs/content/locales/fr-FR/extensions.mdx +10 -0
  739. package/docs/content/locales/fr-FR/messaging.mdx +91 -15
  740. package/docs/content/locales/fr-FR/template-clips.mdx +1 -0
  741. package/docs/content/locales/fr-FR/template-design.mdx +1 -0
  742. package/docs/content/locales/hi-IN/extensions.mdx +8 -0
  743. package/docs/content/locales/hi-IN/messaging.mdx +81 -15
  744. package/docs/content/locales/hi-IN/template-clips.mdx +1 -0
  745. package/docs/content/locales/hi-IN/template-design.mdx +1 -0
  746. package/docs/content/locales/ja-JP/extensions.mdx +9 -0
  747. package/docs/content/locales/ja-JP/messaging.mdx +81 -15
  748. package/docs/content/locales/ja-JP/template-clips.mdx +1 -0
  749. package/docs/content/locales/ja-JP/template-design.mdx +1 -0
  750. package/docs/content/locales/ko-KR/extensions.mdx +8 -0
  751. package/docs/content/locales/ko-KR/messaging.mdx +80 -15
  752. package/docs/content/locales/ko-KR/template-clips.mdx +1 -0
  753. package/docs/content/locales/ko-KR/template-design.mdx +1 -0
  754. package/docs/content/locales/pt-BR/extensions.mdx +9 -0
  755. package/docs/content/locales/pt-BR/messaging.mdx +88 -15
  756. package/docs/content/locales/pt-BR/template-clips.mdx +1 -0
  757. package/docs/content/locales/pt-BR/template-design.mdx +1 -0
  758. package/docs/content/locales/zh-CN/extensions.mdx +6 -0
  759. package/docs/content/locales/zh-CN/messaging.mdx +78 -15
  760. package/docs/content/locales/zh-CN/template-clips.mdx +1 -0
  761. package/docs/content/locales/zh-CN/template-design.mdx +1 -0
  762. package/docs/content/locales/zh-TW/extensions.mdx +6 -0
  763. package/docs/content/locales/zh-TW/messaging.mdx +78 -15
  764. package/docs/content/locales/zh-TW/template-clips.mdx +1 -0
  765. package/docs/content/locales/zh-TW/template-design.mdx +1 -0
  766. package/docs/content/messaging.mdx +227 -45
  767. package/docs/content/template-clips.mdx +3 -0
  768. package/docs/content/template-design.mdx +4 -0
  769. package/package.json +5 -1
  770. package/src/templates/default/.agents/skills/capture-learnings/SKILL.md +22 -9
  771. package/src/templates/default/AGENTS.md +7 -3
  772. package/src/templates/workspace-core/.agents/skills/authentication/SKILL.md +1 -1
  773. package/src/templates/workspace-core/.agents/skills/capture-learnings/SKILL.md +22 -9
  774. package/src/templates/workspace-core/.agents/skills/extension-points/SKILL.md +6 -3
  775. package/src/templates/workspace-core/.agents/skills/extensions/SKILL.md +25 -0
  776. package/src/templates/workspace-core/.agents/skills/integration-webhooks/SKILL.md +15 -0
  777. package/src/templates/workspace-core/AGENTS.md +3 -2
@@ -8,6 +8,7 @@ import http, {
8
8
  type Server,
9
9
  type ServerResponse,
10
10
  } from "node:http";
11
+ import https from "node:https";
11
12
  import path from "node:path";
12
13
 
13
14
  const DEFAULT_BRIDGE_PORT = 7331;
@@ -142,6 +143,7 @@ export interface DesignConnectBridgeOptions {
142
143
  }
143
144
 
144
145
  const PREVIEW_TOKEN_DOMAIN = "agent-native-design-preview-v1\0";
146
+ const PREVIEW_SESSION_COOKIE_NAME = "agent-native-preview-token";
145
147
 
146
148
  /**
147
149
  * Derive a read-only preview credential from the stronger filesystem token.
@@ -749,9 +751,10 @@ function configureBridgeCors(
749
751
  (res as CorsAwareResponse)[BRIDGE_CORS_HEADERS] = approved
750
752
  ? {
751
753
  "access-control-allow-origin": origin,
752
- "access-control-allow-methods": "GET, HEAD, POST, OPTIONS",
754
+ "access-control-allow-methods":
755
+ "GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS",
753
756
  "access-control-allow-headers":
754
- "content-type, x-bridge-token, x-design-preview-token",
757
+ "authorization, content-type, x-bridge-token, x-design-preview-token, x-csrf-token, x-xsrf-token, x-requested-with",
755
758
  "access-control-allow-private-network": "true",
756
759
  vary: "Origin",
757
760
  }
@@ -780,9 +783,11 @@ function sendText(
780
783
  statusCode: number,
781
784
  body: string,
782
785
  contentType: string,
786
+ setCookieHeaders: string[] = [],
783
787
  ) {
784
788
  res.writeHead(statusCode, {
785
789
  "content-type": contentType,
790
+ ...(setCookieHeaders.length > 0 ? { "set-cookie": setCookieHeaders } : {}),
786
791
  ...bridgeCorsHeaders(res),
787
792
  });
788
793
  res.end(body);
@@ -794,10 +799,12 @@ function sendBytes(
794
799
  body: Buffer,
795
800
  headers: Headers,
796
801
  contentLength = body.length,
802
+ setCookieHeaders: string[] = [],
797
803
  ) {
798
- const responseHeaders: Record<string, string> = {
804
+ const responseHeaders: Record<string, string | string[]> = {
799
805
  ...bridgeCorsHeaders(res),
800
806
  "content-length": String(contentLength),
807
+ ...(setCookieHeaders.length > 0 ? { "set-cookie": setCookieHeaders } : {}),
801
808
  };
802
809
  for (const name of [
803
810
  "content-type",
@@ -842,25 +849,249 @@ function readHeader(req: IncomingMessage, name: string): string {
842
849
  return typeof value === "string" ? value : "";
843
850
  }
844
851
 
852
+ function readRequestCookie(req: IncomingMessage, name: string): string {
853
+ for (const rawPair of readHeader(req, "cookie").split(";")) {
854
+ const pair = rawPair.trim();
855
+ const separator = pair.indexOf("=");
856
+ if (separator <= 0 || pair.slice(0, separator).trim() !== name) continue;
857
+ return pair.slice(separator + 1).trim();
858
+ }
859
+ return "";
860
+ }
861
+
862
+ function previewSessionSetCookie(previewToken: string): string {
863
+ // Partitioned SameSite=None keeps the read-only bridge credential available
864
+ // to nested Design frames without granting an unpartitioned third-party
865
+ // cookie. Loopback origins are potentially trustworthy in Chromium, which
866
+ // permits Secure cookies for local development.
867
+ return `${PREVIEW_SESSION_COOKIE_NAME}=${previewToken}; HttpOnly; Path=/; SameSite=None; Secure; Partitioned`;
868
+ }
869
+
845
870
  /**
846
- * Preserve only the browser request metadata a local dev server needs to
847
- * classify Vite source-module and stylesheet requests. Agent Native's dev
848
- * gateway intentionally varies source-file handling by `Sec-Fetch-Dest`; if
849
- * the bridge drops it, React Router module URLs such as `/app/root.tsx` fall
850
- * through to Nitro and 404. Keep this allowlist narrow: cookies, authorization,
851
- * bridge tokens, origins, and referrers must never be forwarded upstream.
871
+ * Preserve only browser metadata a local dev server needs to classify module
872
+ * requests and parse ordinary same-origin app mutations. Browser cookies and
873
+ * Authorization are forwarded only when Sec-Fetch-Site says the request came
874
+ * from the proxied app itself; cross-site callers cannot relay them. Bridge
875
+ * control tokens and referrers are never forwarded, and mutation origins are
876
+ * replaced with the connected dev-server origin. Cookie-backed login also
877
+ * uses the isolated in-memory upstream jar below so iframe cookie restrictions
878
+ * cannot split the session across URL-backed screens.
852
879
  */
853
880
  function previewProxyRequestHeaders(
854
881
  req: IncomingMessage,
882
+ devServerUrl: string,
883
+ cookieHeader = "",
855
884
  ): Record<string, string> {
856
885
  const headers: Record<string, string> = {};
857
- for (const name of ["accept", "sec-fetch-dest"] as const) {
886
+ for (const name of [
887
+ "accept",
888
+ "accept-language",
889
+ "content-type",
890
+ "sec-fetch-dest",
891
+ "sec-fetch-mode",
892
+ "sec-fetch-site",
893
+ "x-csrf-token",
894
+ "x-xsrf-token",
895
+ "x-requested-with",
896
+ ] as const) {
858
897
  const value = readHeader(req, name);
859
898
  if (value) headers[name] = value;
860
899
  }
900
+ const browserSameOrigin = readHeader(req, "sec-fetch-site") === "same-origin";
901
+ const browserCookie = browserSameOrigin ? readHeader(req, "cookie") : "";
902
+ const mergedCookie = mergePreviewCookieHeaders(cookieHeader, browserCookie);
903
+ if (mergedCookie) headers["cookie"] = mergedCookie;
904
+ // Same-origin app code may use localStorage-backed bearer auth. Forward it
905
+ // only from a browser request already classified as same-origin; cross-site
906
+ // callers still authenticate to the bridge with the separate preview token,
907
+ // which is never copied upstream.
908
+ if (browserSameOrigin) {
909
+ const authorization = readHeader(req, "authorization");
910
+ if (authorization && authorization.length <= 16 * 1024) {
911
+ headers["authorization"] = authorization;
912
+ }
913
+ }
914
+ if (req.method && !["GET", "HEAD"].includes(req.method)) {
915
+ headers["origin"] = new URL(devServerUrl).origin;
916
+ }
861
917
  return headers;
862
918
  }
863
919
 
920
+ function mergePreviewCookieHeaders(
921
+ jarCookieHeader: string,
922
+ browserCookieHeader: string,
923
+ ): string {
924
+ const values = new Map<string, string>();
925
+ const absorb = (header: string) => {
926
+ if (!header || Buffer.byteLength(header) > MAX_PREVIEW_COOKIE_BYTES) return;
927
+ for (const rawPair of header.split(";")) {
928
+ const pair = rawPair.trim();
929
+ const separator = pair.indexOf("=");
930
+ if (separator <= 0) continue;
931
+ const name = pair.slice(0, separator).trim();
932
+ const value = pair.slice(separator + 1).trim();
933
+ if (!/^[!#$%&'*+.^_`|~0-9A-Za-z-]+$/.test(name)) continue;
934
+ if (/^(?:x-)?agent-native-(?:bridge|preview)(?:-|$)/i.test(name)) {
935
+ continue;
936
+ }
937
+ values.set(name, value);
938
+ }
939
+ };
940
+ absorb(jarCookieHeader);
941
+ // A client-readable same-origin cookie is allowed to update the jar's stale
942
+ // value for this request. HttpOnly cookies arrive with the same value and
943
+ // remain effectively jar-owned.
944
+ absorb(browserCookieHeader);
945
+ return [...values].map(([name, value]) => `${name}=${value}`).join("; ");
946
+ }
947
+
948
+ const MAX_PREVIEW_SESSION_COOKIES = 128;
949
+ const MAX_PREVIEW_COOKIE_BYTES = 8 * 1024;
950
+
951
+ type PreviewSessionCookie = {
952
+ name: string;
953
+ value: string;
954
+ path: string;
955
+ secure: boolean;
956
+ expiresAt?: number;
957
+ };
958
+
959
+ function responseSetCookieHeaders(headers: Headers): string[] {
960
+ const withGetSetCookie = headers as Headers & {
961
+ getSetCookie?: () => string[];
962
+ };
963
+ if (typeof withGetSetCookie.getSetCookie === "function") {
964
+ return withGetSetCookie.getSetCookie();
965
+ }
966
+ const single = headers.get("set-cookie");
967
+ return single ? [single] : [];
968
+ }
969
+
970
+ function defaultCookiePath(url: URL): string {
971
+ const pathname = url.pathname || "/";
972
+ const lastSlash = pathname.lastIndexOf("/");
973
+ return lastSlash <= 0 ? "/" : pathname.slice(0, lastSlash);
974
+ }
975
+
976
+ function sanitizedBridgeSetCookie(raw: string): string {
977
+ return raw
978
+ .split(";")
979
+ .filter((part) => !/^\s*domain\s*=/i.test(part))
980
+ .join(";");
981
+ }
982
+
983
+ /**
984
+ * Ephemeral cookie session for one connected dev-server origin. Cookies never
985
+ * enter SQL, disk, logs, or another target origin, and disappear when the
986
+ * local bridge exits. This keeps authenticated URL screens in one bridge
987
+ * process on the same upstream session even when browser third-party-cookie
988
+ * rules would otherwise isolate or reject the nested iframe cookies.
989
+ */
990
+ class PreviewSessionCookieJar {
991
+ private readonly origin: string;
992
+ private readonly cookies = new Map<string, PreviewSessionCookie>();
993
+
994
+ constructor(devServerUrl: string) {
995
+ this.origin = new URL(devServerUrl).origin;
996
+ }
997
+
998
+ store(headers: Headers, responseUrl: string): string[] {
999
+ const parsedUrl = new URL(responseUrl);
1000
+ if (parsedUrl.origin !== this.origin) return [];
1001
+ const browserCookies: string[] = [];
1002
+ for (const raw of responseSetCookieHeaders(headers)) {
1003
+ if (!raw || Buffer.byteLength(raw) > MAX_PREVIEW_COOKIE_BYTES) continue;
1004
+ const parts = raw.split(";");
1005
+ const first = parts.shift()?.trim() ?? "";
1006
+ const separator = first.indexOf("=");
1007
+ if (separator <= 0) continue;
1008
+ const name = first.slice(0, separator).trim();
1009
+ const value = first.slice(separator + 1).trim();
1010
+ if (!/^[!#$%&'*+.^_`|~0-9A-Za-z-]+$/.test(name)) continue;
1011
+ let cookiePath = defaultCookiePath(parsedUrl);
1012
+ let secure = false;
1013
+ let expiresAt: number | undefined;
1014
+ let deleteCookie = false;
1015
+ for (const attribute of parts) {
1016
+ const trimmed = attribute.trim();
1017
+ const equals = trimmed.indexOf("=");
1018
+ const key = (equals < 0 ? trimmed : trimmed.slice(0, equals))
1019
+ .trim()
1020
+ .toLowerCase();
1021
+ const attributeValue =
1022
+ equals < 0 ? "" : trimmed.slice(equals + 1).trim();
1023
+ if (key === "path" && attributeValue.startsWith("/")) {
1024
+ cookiePath = attributeValue;
1025
+ } else if (key === "secure") {
1026
+ secure = true;
1027
+ } else if (key === "max-age") {
1028
+ const seconds = Number(attributeValue);
1029
+ if (Number.isFinite(seconds)) {
1030
+ deleteCookie = seconds <= 0;
1031
+ expiresAt = Date.now() + seconds * 1000;
1032
+ }
1033
+ } else if (key === "expires" && expiresAt === undefined) {
1034
+ const parsed = Date.parse(attributeValue);
1035
+ if (Number.isFinite(parsed)) expiresAt = parsed;
1036
+ }
1037
+ }
1038
+ const mapKey = `${cookiePath}\u0000${name}`;
1039
+ if (
1040
+ deleteCookie ||
1041
+ (expiresAt !== undefined && expiresAt <= Date.now())
1042
+ ) {
1043
+ this.cookies.delete(mapKey);
1044
+ } else {
1045
+ this.cookies.delete(mapKey);
1046
+ this.cookies.set(mapKey, {
1047
+ name,
1048
+ value,
1049
+ path: cookiePath,
1050
+ secure,
1051
+ ...(expiresAt !== undefined ? { expiresAt } : {}),
1052
+ });
1053
+ while (this.cookies.size > MAX_PREVIEW_SESSION_COOKIES) {
1054
+ const oldest = this.cookies.keys().next().value;
1055
+ if (typeof oldest !== "string") break;
1056
+ this.cookies.delete(oldest);
1057
+ }
1058
+ }
1059
+ browserCookies.push(sanitizedBridgeSetCookie(raw));
1060
+ }
1061
+ return browserCookies;
1062
+ }
1063
+
1064
+ headerFor(targetUrl: string): string {
1065
+ const parsed = new URL(targetUrl);
1066
+ if (parsed.origin !== this.origin) return "";
1067
+ const now = Date.now();
1068
+ const matches: PreviewSessionCookie[] = [];
1069
+ for (const [key, cookie] of this.cookies) {
1070
+ if (cookie.expiresAt !== undefined && cookie.expiresAt <= now) {
1071
+ this.cookies.delete(key);
1072
+ continue;
1073
+ }
1074
+ if (
1075
+ cookie.secure &&
1076
+ parsed.protocol !== "https:" &&
1077
+ !isLoopbackOrigin(parsed)
1078
+ ) {
1079
+ continue;
1080
+ }
1081
+ const pathMatches =
1082
+ cookie.path === "/" ||
1083
+ parsed.pathname === cookie.path ||
1084
+ (cookie.path.endsWith("/")
1085
+ ? parsed.pathname.startsWith(cookie.path)
1086
+ : parsed.pathname.startsWith(`${cookie.path}/`));
1087
+ if (!pathMatches) continue;
1088
+ matches.push(cookie);
1089
+ }
1090
+ matches.sort((a, b) => b.path.length - a.path.length);
1091
+ return matches.map((cookie) => `${cookie.name}=${cookie.value}`).join("; ");
1092
+ }
1093
+ }
1094
+
864
1095
  function resolvePreviewSnapshotUrl(
865
1096
  devServerUrl: string,
866
1097
  rawUrl: string | null,
@@ -897,12 +1128,14 @@ function resolvePreviewProxyUrl(
897
1128
  async function fetchPreviewSnapshot(
898
1129
  devServerUrl: string,
899
1130
  targetUrl: string,
1131
+ cookieJar?: PreviewSessionCookieJar,
900
1132
  redirects = 0,
901
1133
  ): Promise<{
902
1134
  url: string;
903
1135
  status: number;
904
1136
  contentType: string;
905
1137
  html: string;
1138
+ setCookieHeaders: string[];
906
1139
  }> {
907
1140
  if (redirects > 5) {
908
1141
  throw new Error("Too many redirects while fetching preview snapshot.");
@@ -916,8 +1149,13 @@ async function fetchPreviewSnapshot(
916
1149
  signal: controller.signal,
917
1150
  headers: {
918
1151
  accept: "text/html,application/xhtml+xml;q=0.9,*/*;q=0.8",
1152
+ ...(cookieJar?.headerFor(targetUrl)
1153
+ ? { cookie: cookieJar.headerFor(targetUrl) }
1154
+ : {}),
919
1155
  },
920
1156
  });
1157
+ const setCookieHeaders =
1158
+ cookieJar?.store(response.headers, targetUrl) ?? [];
921
1159
  const location = response.headers.get("location");
922
1160
  if (location && response.status >= 300 && response.status < 400) {
923
1161
  const redirected = new URL(location, targetUrl);
@@ -928,6 +1166,7 @@ async function fetchPreviewSnapshot(
928
1166
  return fetchPreviewSnapshot(
929
1167
  devServerUrl,
930
1168
  redirected.toString(),
1169
+ cookieJar,
931
1170
  redirects + 1,
932
1171
  );
933
1172
  }
@@ -936,6 +1175,7 @@ async function fetchPreviewSnapshot(
936
1175
  status: response.status,
937
1176
  contentType: response.headers.get("content-type") ?? "",
938
1177
  html: await response.text(),
1178
+ setCookieHeaders,
939
1179
  };
940
1180
  } finally {
941
1181
  clearTimeout(timeout);
@@ -945,13 +1185,19 @@ async function fetchPreviewSnapshot(
945
1185
  async function fetchPreviewProxyResource(
946
1186
  devServerUrl: string,
947
1187
  targetUrl: string,
948
- requestHeaders: Record<string, string> = {},
1188
+ request: {
1189
+ method: string;
1190
+ headers?: Record<string, string>;
1191
+ body?: Buffer;
1192
+ },
1193
+ cookieJar?: PreviewSessionCookieJar,
949
1194
  redirects = 0,
950
1195
  ): Promise<{
951
1196
  url: string;
952
1197
  status: number;
953
1198
  headers: Headers;
954
1199
  body: Buffer;
1200
+ setCookieHeaders: string[];
955
1201
  }> {
956
1202
  if (redirects > 5) {
957
1203
  throw new Error("Too many redirects while proxying preview resource.");
@@ -960,11 +1206,17 @@ async function fetchPreviewProxyResource(
960
1206
  const timeout = setTimeout(() => controller.abort(), 10_000);
961
1207
  try {
962
1208
  const response = await fetch(targetUrl, {
963
- method: "GET",
1209
+ method: request.method,
964
1210
  redirect: "manual",
965
1211
  signal: controller.signal,
966
- headers: requestHeaders,
1212
+ headers: request.headers,
1213
+ body:
1214
+ request.method === "GET" || request.method === "HEAD"
1215
+ ? undefined
1216
+ : request.body,
967
1217
  });
1218
+ const setCookieHeaders =
1219
+ cookieJar?.store(response.headers, targetUrl) ?? [];
968
1220
  const location = response.headers.get("location");
969
1221
  if (location && response.status >= 300 && response.status < 400) {
970
1222
  const redirected = new URL(location, targetUrl);
@@ -972,18 +1224,40 @@ async function fetchPreviewProxyResource(
972
1224
  if (!sameOrigin(redirected.toString(), devServerUrl)) {
973
1225
  throw new Error("Proxy redirect left the connected dev server.");
974
1226
  }
975
- return fetchPreviewProxyResource(
1227
+ const switchToGet =
1228
+ response.status === 303 ||
1229
+ ((response.status === 301 || response.status === 302) &&
1230
+ request.method === "POST");
1231
+ const redirectedResponse = await fetchPreviewProxyResource(
976
1232
  devServerUrl,
977
1233
  redirected.toString(),
978
- requestHeaders,
1234
+ {
1235
+ method: switchToGet ? "GET" : request.method,
1236
+ headers: {
1237
+ ...(request.headers ?? {}),
1238
+ ...(cookieJar?.headerFor(redirected.toString())
1239
+ ? { cookie: cookieJar.headerFor(redirected.toString()) }
1240
+ : {}),
1241
+ },
1242
+ body: switchToGet ? undefined : request.body,
1243
+ },
1244
+ cookieJar,
979
1245
  redirects + 1,
980
1246
  );
1247
+ return {
1248
+ ...redirectedResponse,
1249
+ setCookieHeaders: [
1250
+ ...setCookieHeaders,
1251
+ ...redirectedResponse.setCookieHeaders,
1252
+ ],
1253
+ };
981
1254
  }
982
1255
  return {
983
1256
  url: response.url || targetUrl,
984
1257
  status: response.status,
985
1258
  headers: response.headers,
986
1259
  body: Buffer.from(await response.arrayBuffer()),
1260
+ setCookieHeaders,
987
1261
  };
988
1262
  } finally {
989
1263
  clearTimeout(timeout);
@@ -1062,6 +1336,50 @@ async function readRequestBody(req: IncomingMessage): Promise<string> {
1062
1336
  });
1063
1337
  }
1064
1338
 
1339
+ const MAX_PREVIEW_PROXY_REQUEST_BYTES = 8 * 1024 * 1024;
1340
+
1341
+ class PreviewProxyRequestTooLargeError extends Error {}
1342
+
1343
+ async function readPreviewProxyRequestBody(
1344
+ req: IncomingMessage,
1345
+ ): Promise<Buffer> {
1346
+ const declaredLength = Number(readHeader(req, "content-length"));
1347
+ if (
1348
+ Number.isFinite(declaredLength) &&
1349
+ declaredLength > MAX_PREVIEW_PROXY_REQUEST_BYTES
1350
+ ) {
1351
+ throw new PreviewProxyRequestTooLargeError(
1352
+ "Preview request body exceeds the 8 MB limit.",
1353
+ );
1354
+ }
1355
+ return new Promise<Buffer>((resolve, reject) => {
1356
+ const chunks: Buffer[] = [];
1357
+ let size = 0;
1358
+ let tooLarge = false;
1359
+ req.on("data", (chunk: Buffer) => {
1360
+ size += chunk.length;
1361
+ if (size > MAX_PREVIEW_PROXY_REQUEST_BYTES) {
1362
+ tooLarge = true;
1363
+ chunks.length = 0;
1364
+ return;
1365
+ }
1366
+ if (!tooLarge) chunks.push(chunk);
1367
+ });
1368
+ req.on("end", () => {
1369
+ if (tooLarge) {
1370
+ reject(
1371
+ new PreviewProxyRequestTooLargeError(
1372
+ "Preview request body exceeds the 8 MB limit.",
1373
+ ),
1374
+ );
1375
+ return;
1376
+ }
1377
+ resolve(Buffer.concat(chunks));
1378
+ });
1379
+ req.on("error", reject);
1380
+ });
1381
+ }
1382
+
1065
1383
  /**
1066
1384
  * Resolve `targetDir` under `rootPath` with realpath so that symlinks and
1067
1385
  * traversal sequences (../../etc) cannot escape the root. Throws if the
@@ -1362,8 +1680,13 @@ async function atomicWriteBridgeFile(args: {
1362
1680
  }
1363
1681
  }
1364
1682
 
1365
- /** Allowed file extensions for write/apply-edit operations. */
1366
- const ALLOWED_WRITE_EXTENSIONS = new Set([
1683
+ /**
1684
+ * Extensions that are safe for creating a brand-new text/code file through
1685
+ * the bridge. Existing files are classified by their bytes instead, so the
1686
+ * Code workbench can edit languages and extensionless config files without a
1687
+ * permanently incomplete allowlist.
1688
+ */
1689
+ const ALLOWED_NEW_TEXT_FILE_EXTENSIONS = new Set([
1367
1690
  ".html",
1368
1691
  ".htm",
1369
1692
  ".css",
@@ -1385,13 +1708,103 @@ const ALLOWED_WRITE_EXTENSIONS = new Set([
1385
1708
  ".yml",
1386
1709
  ".yaml",
1387
1710
  ".svg",
1711
+ ".py",
1712
+ ".rb",
1713
+ ".php",
1714
+ ".java",
1715
+ ".kt",
1716
+ ".kts",
1717
+ ".go",
1718
+ ".rs",
1719
+ ".c",
1720
+ ".h",
1721
+ ".cc",
1722
+ ".cpp",
1723
+ ".hpp",
1724
+ ".cs",
1725
+ ".swift",
1726
+ ".sh",
1727
+ ".bash",
1728
+ ".zsh",
1729
+ ".fish",
1730
+ ".sql",
1731
+ ".toml",
1732
+ ".xml",
1733
+ ".graphql",
1734
+ ".gql",
1735
+ ".prisma",
1736
+ ".properties",
1737
+ ".ini",
1738
+ ".conf",
1739
+ ".env.example",
1740
+ ]);
1741
+
1742
+ const ALLOWED_NEW_EXTENSIONLESS_TEXT_FILES = new Set([
1743
+ "dockerfile",
1744
+ "makefile",
1745
+ "procfile",
1746
+ "gemfile",
1747
+ "rakefile",
1748
+ "license",
1749
+ "readme",
1388
1750
  ]);
1389
1751
 
1390
- function assertAllowedExtension(relPath: string): void {
1752
+ const BLOCKED_BINARY_WRITE_EXTENSIONS = new Set([
1753
+ ".png",
1754
+ ".jpg",
1755
+ ".jpeg",
1756
+ ".gif",
1757
+ ".webp",
1758
+ ".ico",
1759
+ ".woff",
1760
+ ".woff2",
1761
+ ".ttf",
1762
+ ".otf",
1763
+ ".eot",
1764
+ ".mp3",
1765
+ ".mp4",
1766
+ ".mov",
1767
+ ".webm",
1768
+ ".zip",
1769
+ ".gz",
1770
+ ".tar",
1771
+ ".pdf",
1772
+ ".wasm",
1773
+ ".fig",
1774
+ ".sketch",
1775
+ ".exe",
1776
+ ".dll",
1777
+ ".dylib",
1778
+ ".so",
1779
+ ".class",
1780
+ ".jar",
1781
+ ]);
1782
+
1783
+ function assertEditableTextFile(
1784
+ relPath: string,
1785
+ existing: BridgeFileSnapshot | null,
1786
+ ): void {
1391
1787
  const ext = path.extname(relPath).toLowerCase();
1392
- if (!ALLOWED_WRITE_EXTENSIONS.has(ext)) {
1788
+ if (BLOCKED_BINARY_WRITE_EXTENSIONS.has(ext)) {
1393
1789
  throw new Error(
1394
- `Write rejected: extension "${ext || "(no extension)"}" is not in the allowed text-file list for bridge writes.`,
1790
+ `Write rejected: extension "${ext}" is a binary file type.`,
1791
+ );
1792
+ }
1793
+ if (existing) {
1794
+ if (existing.content.includes("\0")) {
1795
+ throw new Error(
1796
+ "Write rejected: the existing file contains binary data.",
1797
+ );
1798
+ }
1799
+ return;
1800
+ }
1801
+ const basename = path.basename(relPath).toLowerCase();
1802
+ if (
1803
+ !ALLOWED_NEW_TEXT_FILE_EXTENSIONS.has(ext) &&
1804
+ !ALLOWED_NEW_EXTENSIONLESS_TEXT_FILES.has(basename)
1805
+ ) {
1806
+ throw new Error(
1807
+ `Write rejected: extension "${ext || "(no extension)"}" is not recognized for a new text/code file.`,
1395
1808
  );
1396
1809
  }
1397
1810
  }
@@ -1774,6 +2187,9 @@ export async function startDesignConnectBridge(
1774
2187
  // registered" (id changed, safe to transparently re-POST `/live-edit-bridge`
1775
2188
  // and retry) — instead of guessing from the error text or retrying forever.
1776
2189
  const bridgeInstanceId = crypto.randomBytes(16).toString("hex");
2190
+ const previewSessionCookies = new PreviewSessionCookieJar(
2191
+ manifest.devServerUrl,
2192
+ );
1777
2193
 
1778
2194
  const server = http.createServer(
1779
2195
  (req: IncomingMessage, res: ServerResponse) => {
@@ -1794,6 +2210,7 @@ export async function startDesignConnectBridge(
1794
2210
  const providedPreviewToken =
1795
2211
  readHeader(req, "x-design-preview-token") ||
1796
2212
  requestUrl.searchParams.get("previewToken") ||
2213
+ readRequestCookie(req, PREVIEW_SESSION_COOKIE_NAME) ||
1797
2214
  "";
1798
2215
  const previewTokenValid = constantTimeTokenMatches(
1799
2216
  providedPreviewToken,
@@ -1915,6 +2332,7 @@ export async function startDesignConnectBridge(
1915
2332
  const snapshot = await fetchPreviewSnapshot(
1916
2333
  manifest.devServerUrl,
1917
2334
  targetUrl,
2335
+ previewSessionCookies,
1918
2336
  );
1919
2337
  const includeEditorBridge =
1920
2338
  requestUrl.searchParams.get("bridge") !== "0";
@@ -1963,6 +2381,10 @@ export async function startDesignConnectBridge(
1963
2381
  snapshot.contentType.includes("html")
1964
2382
  ? snapshot.contentType
1965
2383
  : "text/html; charset=utf-8",
2384
+ [
2385
+ ...snapshot.setCookieHeaders,
2386
+ previewSessionSetCookie(previewToken),
2387
+ ],
1966
2388
  );
1967
2389
  } catch (err: unknown) {
1968
2390
  sendJson(res, 400, {
@@ -1989,6 +2411,7 @@ export async function startDesignConnectBridge(
1989
2411
  const snapshot = await fetchPreviewSnapshot(
1990
2412
  manifest.devServerUrl,
1991
2413
  targetUrl,
2414
+ previewSessionCookies,
1992
2415
  );
1993
2416
  sendJson(res, snapshot.status >= 400 ? snapshot.status : 200, {
1994
2417
  ok: snapshot.status < 400,
@@ -2088,9 +2511,6 @@ export async function startDesignConnectBridge(
2088
2511
  return;
2089
2512
  }
2090
2513
 
2091
- // write-file and apply-edit only allow known text/code extensions.
2092
- assertAllowedExtension(relPath);
2093
-
2094
2514
  const expectedVersionHash =
2095
2515
  typeof body["expectedVersionHash"] === "string"
2096
2516
  ? body["expectedVersionHash"]
@@ -2110,6 +2530,7 @@ export async function startDesignConnectBridge(
2110
2530
  const existing = await readBridgeFileSnapshot(
2111
2531
  lockedTarget.absolutePath,
2112
2532
  );
2533
+ assertEditableTextFile(relPath, existing);
2113
2534
  assertExpectedBridgeVersion(
2114
2535
  expectedVersionHash,
2115
2536
  existing?.versionHash,
@@ -2251,10 +2672,11 @@ export async function startDesignConnectBridge(
2251
2672
  return;
2252
2673
  }
2253
2674
 
2254
- if (req.method === "GET" || req.method === "HEAD") {
2255
- const sameOriginPreviewSubresource =
2256
- readHeader(req, "sec-fetch-site") === "same-origin";
2257
- if (!previewTokenValid && !sameOriginPreviewSubresource) {
2675
+ if (
2676
+ req.method &&
2677
+ ["GET", "HEAD", "POST", "PUT", "PATCH", "DELETE"].includes(req.method)
2678
+ ) {
2679
+ if (!previewTokenValid) {
2258
2680
  sendJson(res, 401, {
2259
2681
  ok: false,
2260
2682
  error: "invalid or missing preview token",
@@ -2263,27 +2685,66 @@ export async function startDesignConnectBridge(
2263
2685
  }
2264
2686
  void (async () => {
2265
2687
  try {
2688
+ const proxyRequestUrl = new URL(req.url ?? "/", manifest.bridgeUrl);
2689
+ proxyRequestUrl.searchParams.delete("previewToken");
2266
2690
  const targetUrl = resolvePreviewProxyUrl(
2267
2691
  manifest.devServerUrl,
2268
- req.url,
2692
+ `${proxyRequestUrl.pathname}${proxyRequestUrl.search}`,
2269
2693
  );
2694
+ const method = req.method ?? "GET";
2695
+ const requestBody =
2696
+ method === "GET" || method === "HEAD"
2697
+ ? undefined
2698
+ : await readPreviewProxyRequestBody(req);
2699
+ const cookieHeader = previewSessionCookies.headerFor(targetUrl);
2270
2700
  const proxied = await fetchPreviewProxyResource(
2271
2701
  manifest.devServerUrl,
2272
2702
  targetUrl,
2273
- previewProxyRequestHeaders(req),
2703
+ {
2704
+ method,
2705
+ headers: previewProxyRequestHeaders(
2706
+ req,
2707
+ manifest.devServerUrl,
2708
+ cookieHeader,
2709
+ ),
2710
+ body: requestBody,
2711
+ },
2712
+ previewSessionCookies,
2274
2713
  );
2714
+ const contentType = proxied.headers.get("content-type") ?? "";
2715
+ const documentNavigation =
2716
+ readHeader(req, "sec-fetch-dest") === "document";
2717
+ const responseBody =
2718
+ documentNavigation && contentType.includes("html")
2719
+ ? Buffer.from(
2720
+ injectLiveEditBridge(
2721
+ proxied.body.toString("utf8"),
2722
+ new URL("/", manifest.bridgeUrl).toString(),
2723
+ liveEditBridgeScript,
2724
+ (() => {
2725
+ const parsed = new URL(proxied.url);
2726
+ return `${parsed.pathname}${parsed.search}` || "/";
2727
+ })(),
2728
+ ),
2729
+ )
2730
+ : proxied.body;
2275
2731
  sendBytes(
2276
2732
  res,
2277
- proxied.status >= 400 ? proxied.status : 200,
2278
- req.method === "HEAD" ? Buffer.alloc(0) : proxied.body,
2733
+ proxied.status,
2734
+ method === "HEAD" ? Buffer.alloc(0) : responseBody,
2279
2735
  proxied.headers,
2280
- proxied.body.length,
2736
+ responseBody.length,
2737
+ proxied.setCookieHeaders,
2281
2738
  );
2282
2739
  } catch (err: unknown) {
2283
- sendJson(res, 400, {
2284
- ok: false,
2285
- error: err instanceof Error ? err.message : String(err),
2286
- });
2740
+ sendJson(
2741
+ res,
2742
+ err instanceof PreviewProxyRequestTooLargeError ? 413 : 400,
2743
+ {
2744
+ ok: false,
2745
+ error: err instanceof Error ? err.message : String(err),
2746
+ },
2747
+ );
2287
2748
  }
2288
2749
  })();
2289
2750
  return;
@@ -2293,6 +2754,105 @@ export async function startDesignConnectBridge(
2293
2754
  },
2294
2755
  );
2295
2756
 
2757
+ // Vite's proxied /@vite/client derives its HMR socket from the document's
2758
+ // bridge origin. Tunnel WebSocket upgrades to the one connected dev-server
2759
+ // origin so Fast Refresh remains live inside URL-backed screens. The target
2760
+ // is never caller-controlled, bridge credentials are stripped, and only a
2761
+ // same-origin iframe (or an explicit preview-token caller) can open it.
2762
+ server.on("upgrade", (req, clientSocket, clientHead) => {
2763
+ const requestUrl = new URL(req.url ?? "/", manifest.bridgeUrl);
2764
+ const providedPreviewToken =
2765
+ readHeader(req, "x-design-preview-token") ||
2766
+ requestUrl.searchParams.get("previewToken") ||
2767
+ readRequestCookie(req, PREVIEW_SESSION_COOKIE_NAME) ||
2768
+ "";
2769
+ const browserOrigin = readHeader(req, "origin");
2770
+ const sameBridgeOrigin =
2771
+ browserOrigin === new URL(manifest.bridgeUrl).origin;
2772
+ if (!constantTimeTokenMatches(providedPreviewToken, previewToken)) {
2773
+ clientSocket.end(
2774
+ "HTTP/1.1 401 Unauthorized\r\nConnection: close\r\nContent-Length: 0\r\n\r\n",
2775
+ );
2776
+ return;
2777
+ }
2778
+ requestUrl.searchParams.delete("previewToken");
2779
+ let targetUrl: URL;
2780
+ try {
2781
+ targetUrl = new URL(
2782
+ resolvePreviewProxyUrl(
2783
+ manifest.devServerUrl,
2784
+ `${requestUrl.pathname}${requestUrl.search}`,
2785
+ ),
2786
+ );
2787
+ } catch {
2788
+ clientSocket.end(
2789
+ "HTTP/1.1 400 Bad Request\r\nConnection: close\r\nContent-Length: 0\r\n\r\n",
2790
+ );
2791
+ return;
2792
+ }
2793
+
2794
+ const upstreamHeaders = { ...req.headers };
2795
+ delete upstreamHeaders["x-bridge-token"];
2796
+ delete upstreamHeaders["x-design-preview-token"];
2797
+ delete upstreamHeaders["authorization"];
2798
+ delete upstreamHeaders["cookie"];
2799
+ upstreamHeaders.host = targetUrl.host;
2800
+ upstreamHeaders.origin = new URL(manifest.devServerUrl).origin;
2801
+ const cookie = mergePreviewCookieHeaders(
2802
+ previewSessionCookies.headerFor(targetUrl.toString()),
2803
+ sameBridgeOrigin ? readHeader(req, "cookie") : "",
2804
+ );
2805
+ if (cookie) upstreamHeaders.cookie = cookie;
2806
+
2807
+ const requestImpl = targetUrl.protocol === "https:" ? https : http;
2808
+ const upstreamRequest = requestImpl.request({
2809
+ protocol: targetUrl.protocol,
2810
+ hostname: targetUrl.hostname,
2811
+ port: targetUrl.port,
2812
+ path: `${targetUrl.pathname}${targetUrl.search}`,
2813
+ method: "GET",
2814
+ headers: upstreamHeaders,
2815
+ });
2816
+ upstreamRequest.on(
2817
+ "upgrade",
2818
+ (upstreamResponse, upstreamSocket, upstreamHead) => {
2819
+ const statusLine = `HTTP/1.1 ${upstreamResponse.statusCode ?? 101} ${upstreamResponse.statusMessage || "Switching Protocols"}\r\n`;
2820
+ const headerLines: string[] = [];
2821
+ for (
2822
+ let index = 0;
2823
+ index < upstreamResponse.rawHeaders.length;
2824
+ index += 2
2825
+ ) {
2826
+ const name = upstreamResponse.rawHeaders[index];
2827
+ const value = upstreamResponse.rawHeaders[index + 1];
2828
+ if (name && value !== undefined)
2829
+ headerLines.push(`${name}: ${value}`);
2830
+ }
2831
+ clientSocket.write(`${statusLine}${headerLines.join("\r\n")}\r\n\r\n`);
2832
+ if (clientHead.length > 0) upstreamSocket.write(clientHead);
2833
+ if (upstreamHead.length > 0) clientSocket.write(upstreamHead);
2834
+ clientSocket.once("close", () => upstreamSocket.destroy());
2835
+ upstreamSocket.once("close", () => clientSocket.destroy());
2836
+ upstreamSocket.pipe(clientSocket);
2837
+ clientSocket.pipe(upstreamSocket);
2838
+ },
2839
+ );
2840
+ upstreamRequest.on("response", (upstreamResponse) => {
2841
+ clientSocket.end(
2842
+ `HTTP/1.1 ${upstreamResponse.statusCode ?? 502} ${upstreamResponse.statusMessage || "WebSocket upgrade failed"}\r\nConnection: close\r\nContent-Length: 0\r\n\r\n`,
2843
+ );
2844
+ upstreamResponse.resume();
2845
+ });
2846
+ upstreamRequest.on("error", () => {
2847
+ if (!clientSocket.destroyed) {
2848
+ clientSocket.end(
2849
+ "HTTP/1.1 502 Bad Gateway\r\nConnection: close\r\nContent-Length: 0\r\n\r\n",
2850
+ );
2851
+ }
2852
+ });
2853
+ upstreamRequest.end();
2854
+ });
2855
+
2296
2856
  await new Promise<void>((resolve, reject) => {
2297
2857
  server.once("error", reject);
2298
2858
  server.listen(new URL(manifest.bridgeUrl).port, "127.0.0.1", () => {