@agent-native/core 0.92.12 → 0.93.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (772) hide show
  1. package/corpus/README.md +2 -2
  2. package/corpus/core/CHANGELOG.md +39 -0
  3. package/corpus/core/docs/content/automation-connectors.mdx +80 -0
  4. package/corpus/core/docs/content/extensions.mdx +8 -0
  5. package/corpus/core/docs/content/locales/ar-SA/extensions.mdx +8 -0
  6. package/corpus/core/docs/content/locales/ar-SA/messaging.mdx +84 -15
  7. package/corpus/core/docs/content/locales/ar-SA/template-clips.mdx +1 -0
  8. package/corpus/core/docs/content/locales/ar-SA/template-design.mdx +1 -0
  9. package/corpus/core/docs/content/locales/de-DE/extensions.mdx +10 -0
  10. package/corpus/core/docs/content/locales/de-DE/messaging.mdx +92 -15
  11. package/corpus/core/docs/content/locales/de-DE/template-clips.mdx +1 -0
  12. package/corpus/core/docs/content/locales/de-DE/template-design.mdx +1 -0
  13. package/corpus/core/docs/content/locales/es-ES/extensions.mdx +10 -0
  14. package/corpus/core/docs/content/locales/es-ES/messaging.mdx +91 -15
  15. package/corpus/core/docs/content/locales/es-ES/template-clips.mdx +1 -0
  16. package/corpus/core/docs/content/locales/es-ES/template-design.mdx +1 -0
  17. package/corpus/core/docs/content/locales/fr-FR/extensions.mdx +10 -0
  18. package/corpus/core/docs/content/locales/fr-FR/messaging.mdx +91 -15
  19. package/corpus/core/docs/content/locales/fr-FR/template-clips.mdx +1 -0
  20. package/corpus/core/docs/content/locales/fr-FR/template-design.mdx +1 -0
  21. package/corpus/core/docs/content/locales/hi-IN/extensions.mdx +8 -0
  22. package/corpus/core/docs/content/locales/hi-IN/messaging.mdx +81 -15
  23. package/corpus/core/docs/content/locales/hi-IN/template-clips.mdx +1 -0
  24. package/corpus/core/docs/content/locales/hi-IN/template-design.mdx +1 -0
  25. package/corpus/core/docs/content/locales/ja-JP/extensions.mdx +9 -0
  26. package/corpus/core/docs/content/locales/ja-JP/messaging.mdx +81 -15
  27. package/corpus/core/docs/content/locales/ja-JP/template-clips.mdx +1 -0
  28. package/corpus/core/docs/content/locales/ja-JP/template-design.mdx +1 -0
  29. package/corpus/core/docs/content/locales/ko-KR/extensions.mdx +8 -0
  30. package/corpus/core/docs/content/locales/ko-KR/messaging.mdx +80 -15
  31. package/corpus/core/docs/content/locales/ko-KR/template-clips.mdx +1 -0
  32. package/corpus/core/docs/content/locales/ko-KR/template-design.mdx +1 -0
  33. package/corpus/core/docs/content/locales/pt-BR/extensions.mdx +9 -0
  34. package/corpus/core/docs/content/locales/pt-BR/messaging.mdx +88 -15
  35. package/corpus/core/docs/content/locales/pt-BR/template-clips.mdx +1 -0
  36. package/corpus/core/docs/content/locales/pt-BR/template-design.mdx +1 -0
  37. package/corpus/core/docs/content/locales/zh-CN/extensions.mdx +6 -0
  38. package/corpus/core/docs/content/locales/zh-CN/messaging.mdx +78 -15
  39. package/corpus/core/docs/content/locales/zh-CN/template-clips.mdx +1 -0
  40. package/corpus/core/docs/content/locales/zh-CN/template-design.mdx +1 -0
  41. package/corpus/core/docs/content/locales/zh-TW/extensions.mdx +6 -0
  42. package/corpus/core/docs/content/locales/zh-TW/messaging.mdx +78 -15
  43. package/corpus/core/docs/content/locales/zh-TW/template-clips.mdx +1 -0
  44. package/corpus/core/docs/content/locales/zh-TW/template-design.mdx +1 -0
  45. package/corpus/core/docs/content/messaging.mdx +227 -45
  46. package/corpus/core/docs/content/template-clips.mdx +3 -0
  47. package/corpus/core/docs/content/template-design.mdx +4 -0
  48. package/corpus/core/package.json +5 -1
  49. package/corpus/core/src/a2a/artifact-response.ts +131 -2
  50. package/corpus/core/src/a2a/client.ts +10 -0
  51. package/corpus/core/src/a2a/handlers.ts +40 -76
  52. package/corpus/core/src/a2a/types.ts +2 -0
  53. package/corpus/core/src/agent/durable-background.ts +24 -0
  54. package/corpus/core/src/agent/production-agent.ts +15 -3
  55. package/corpus/core/src/agent/run-manager.ts +130 -10
  56. package/corpus/core/src/agent/run-store.ts +225 -15
  57. package/corpus/core/src/agent/types.ts +23 -0
  58. package/corpus/core/src/audit/record.ts +31 -0
  59. package/corpus/core/src/audit/store.ts +69 -3
  60. package/corpus/core/src/audit/types.ts +13 -0
  61. package/corpus/core/src/automation/index.ts +802 -0
  62. package/corpus/core/src/cli/create.ts +12 -5
  63. package/corpus/core/src/cli/design-connect.ts +596 -36
  64. package/corpus/core/src/client/AgentPanel.tsx +51 -6
  65. package/corpus/core/src/client/AssistantChat.tsx +274 -147
  66. package/corpus/core/src/client/MultiTabAssistantChat.tsx +3 -0
  67. package/corpus/core/src/client/RunStuckBanner.tsx +69 -20
  68. package/corpus/core/src/client/agent-chat-adapter.ts +54 -5
  69. package/corpus/core/src/client/automation.ts +22 -0
  70. package/corpus/core/src/client/chat/run-recovery.tsx +67 -50
  71. package/corpus/core/src/client/composer/TiptapComposer.tsx +8 -0
  72. package/corpus/core/src/client/index.ts +30 -0
  73. package/corpus/core/src/client/integrations/api.ts +295 -0
  74. package/corpus/core/src/client/integrations/index.ts +26 -0
  75. package/corpus/core/src/client/transcription/use-live-transcription.ts +68 -5
  76. package/corpus/core/src/client/use-run-stuck-detection.ts +41 -3
  77. package/corpus/core/src/deploy/build.ts +59 -3
  78. package/corpus/core/src/deploy/workspace-deploy.ts +37 -2
  79. package/corpus/core/src/file-upload/types.ts +2 -0
  80. package/corpus/core/src/index.ts +37 -0
  81. package/corpus/core/src/integrations/a2a-continuations-store.ts +6 -4
  82. package/corpus/core/src/integrations/adapters/discord.ts +362 -0
  83. package/corpus/core/src/integrations/adapters/index.ts +29 -0
  84. package/corpus/core/src/integrations/adapters/microsoft-teams.ts +411 -0
  85. package/corpus/core/src/integrations/adapters/slack.ts +861 -27
  86. package/corpus/core/src/integrations/adapters/telegram.ts +54 -15
  87. package/corpus/core/src/integrations/adapters/whatsapp.ts +41 -17
  88. package/corpus/core/src/integrations/catalog.ts +571 -0
  89. package/corpus/core/src/integrations/controls-store.ts +187 -0
  90. package/corpus/core/src/integrations/index.ts +100 -0
  91. package/corpus/core/src/integrations/installations-store.ts +677 -0
  92. package/corpus/core/src/integrations/integration-memory.ts +187 -0
  93. package/corpus/core/src/integrations/pending-tasks-retry-job.ts +6 -6
  94. package/corpus/core/src/integrations/pending-tasks-store.ts +83 -5
  95. package/corpus/core/src/integrations/plugin.ts +685 -47
  96. package/corpus/core/src/integrations/scope-store.ts +498 -0
  97. package/corpus/core/src/integrations/slack-manifest.ts +78 -0
  98. package/corpus/core/src/integrations/slack-oauth.ts +343 -0
  99. package/corpus/core/src/integrations/types.ts +179 -0
  100. package/corpus/core/src/integrations/usage-budget-store.ts +906 -0
  101. package/corpus/core/src/integrations/webhook-handler.ts +562 -51
  102. package/corpus/core/src/jobs/scheduler.ts +100 -2
  103. package/corpus/core/src/jobs/tools.ts +45 -9
  104. package/corpus/core/src/provider-api/index.ts +72 -1
  105. package/corpus/core/src/resources/handlers.ts +88 -14
  106. package/corpus/core/src/resources/script-helpers.ts +36 -7
  107. package/corpus/core/src/resources/store.ts +59 -52
  108. package/corpus/core/src/scripts/call-agent.ts +107 -1
  109. package/corpus/core/src/server/agent-chat-plugin.ts +294 -119
  110. package/corpus/core/src/server/auth.ts +10 -14
  111. package/corpus/core/src/server/builder-design-systems.ts +16 -1
  112. package/corpus/core/src/server/edge.ts +18 -0
  113. package/corpus/core/src/server/index.ts +26 -0
  114. package/corpus/core/src/server/request-context.ts +18 -0
  115. package/corpus/core/src/server/social-og-image.ts +3 -2
  116. package/corpus/core/src/styles/agent-native.css +62 -44
  117. package/corpus/core/src/templates/default/.agents/skills/capture-learnings/SKILL.md +22 -9
  118. package/corpus/core/src/templates/default/AGENTS.md +7 -3
  119. package/corpus/core/src/templates/workspace-core/.agents/skills/authentication/SKILL.md +1 -1
  120. package/corpus/core/src/templates/workspace-core/.agents/skills/capture-learnings/SKILL.md +22 -9
  121. package/corpus/core/src/templates/workspace-core/.agents/skills/extension-points/SKILL.md +6 -3
  122. package/corpus/core/src/templates/workspace-core/.agents/skills/extensions/SKILL.md +25 -0
  123. package/corpus/core/src/templates/workspace-core/.agents/skills/integration-webhooks/SKILL.md +15 -0
  124. package/corpus/core/src/templates/workspace-core/AGENTS.md +3 -2
  125. package/corpus/core/src/usage/store.ts +37 -2
  126. package/corpus/templates/analytics/.agents/skills/capture-learnings/SKILL.md +22 -9
  127. package/corpus/templates/analytics/.agents/skills/provider-api/SKILL.md +23 -0
  128. package/corpus/templates/analytics/.builder/skills/provider-api/SKILL.md +15 -0
  129. package/corpus/templates/analytics/actions/save-monitor.ts +25 -2
  130. package/corpus/templates/analytics/app/lib/data-sources.ts +28 -0
  131. package/corpus/templates/analytics/changelog/2026-07-10-agent-created-uptime-monitors-now-return-a-direct-link-to-th.md +6 -0
  132. package/corpus/templates/analytics/changelog/2026-07-10-dashboard-email-reports-still-arrive-when-screenshot-capture-temporarily-fails.md +6 -0
  133. package/corpus/templates/analytics/server/jobs/dashboard-report.ts +3 -7
  134. package/corpus/templates/analytics/server/lib/credential-keys.ts +12 -0
  135. package/corpus/templates/analytics/server/lib/dashboard-report.ts +5 -1
  136. package/corpus/templates/analytics/server/lib/provider-credentials.ts +2 -0
  137. package/corpus/templates/analytics/server/routes/api/test-connection.post.ts +16 -0
  138. package/corpus/templates/assets/.agents/skills/capture-learnings/SKILL.md +22 -9
  139. package/corpus/templates/brain/.agents/skills/capture-learnings/SKILL.md +22 -9
  140. package/corpus/templates/calendar/.agents/skills/capture-learnings/SKILL.md +22 -9
  141. package/corpus/templates/calendar/app/components/calendar/CommandPalette.tsx +98 -108
  142. package/corpus/templates/calendar/app/components/calendar/EventAttendeesSection.tsx +97 -90
  143. package/corpus/templates/calendar/changelog/2026-07-10-event-guest-details-and-option-menus-now-use-valid-accessibl.md +6 -0
  144. package/corpus/templates/calendar/changelog/2026-07-10-natural-language-event-phrases-stay-available-as-quick-creat.md +6 -0
  145. package/corpus/templates/chat/.agents/skills/capture-learnings/SKILL.md +22 -9
  146. package/corpus/templates/chat/changelog/2026-07-10-chat-now-makes-ai-connection-setup-clear-without-shifting-th.md +6 -0
  147. package/corpus/templates/clips/.agents/skills/capture-learnings/SKILL.md +22 -9
  148. package/corpus/templates/clips/.agents/skills/recording/SKILL.md +17 -1
  149. package/corpus/templates/clips/.agents/skills/video-sharing/SKILL.md +8 -0
  150. package/corpus/templates/clips/AGENTS.md +8 -3
  151. package/corpus/templates/clips/actions/finalize-recording.ts +63 -23
  152. package/corpus/templates/clips/actions/get-recording-player-data.ts +6 -2
  153. package/corpus/templates/clips/actions/lib/ensure-seekable-video.ts +72 -9
  154. package/corpus/templates/clips/actions/list-recordings.ts +19 -3
  155. package/corpus/templates/clips/actions/navigate.ts +2 -0
  156. package/corpus/templates/clips/actions/reprocess-recording.ts +20 -6
  157. package/corpus/templates/clips/actions/request-transcript.ts +16 -31
  158. package/corpus/templates/clips/actions/view-screen.ts +57 -5
  159. package/corpus/templates/clips/app/components/layout/Header.tsx +1 -0
  160. package/corpus/templates/clips/app/components/library/empty-state.tsx +2 -0
  161. package/corpus/templates/clips/app/components/library/library-grid.tsx +69 -42
  162. package/corpus/templates/clips/app/components/library/library-layout.tsx +15 -1
  163. package/corpus/templates/clips/app/components/library/recording-card.tsx +81 -68
  164. package/corpus/templates/clips/app/components/library/search-bar.tsx +4 -3
  165. package/corpus/templates/clips/app/components/player/delete-recording-menu.tsx +9 -3
  166. package/corpus/templates/clips/app/components/player/share-dialog.tsx +1 -1
  167. package/corpus/templates/clips/app/hooks/use-library.ts +1 -1
  168. package/corpus/templates/clips/app/hooks/use-navigation-state.ts +10 -2
  169. package/corpus/templates/clips/app/i18n/ar-SA.ts +7 -1
  170. package/corpus/templates/clips/app/i18n/de-DE.ts +7 -1
  171. package/corpus/templates/clips/app/i18n/en-US.ts +7 -1
  172. package/corpus/templates/clips/app/i18n/es-ES.ts +7 -1
  173. package/corpus/templates/clips/app/i18n/fr-FR.ts +7 -1
  174. package/corpus/templates/clips/app/i18n/hi-IN.ts +7 -1
  175. package/corpus/templates/clips/app/i18n/ja-JP.ts +7 -1
  176. package/corpus/templates/clips/app/i18n/ko-KR.ts +7 -1
  177. package/corpus/templates/clips/app/i18n/pt-BR.ts +7 -1
  178. package/corpus/templates/clips/app/i18n/zh-CN.ts +8 -1
  179. package/corpus/templates/clips/app/i18n/zh-TW.ts +8 -1
  180. package/corpus/templates/clips/app/lib/recording-visibility.ts +70 -0
  181. package/corpus/templates/clips/app/routes/_app.shared.tsx +20 -0
  182. package/corpus/templates/clips/app/routes/download.tsx +24 -8
  183. package/corpus/templates/clips/app/routes/r.$recordingId.tsx +115 -2
  184. package/corpus/templates/clips/app/routes/record.tsx +62 -0
  185. package/corpus/templates/clips/app/routes/share.$shareId.tsx +25 -16
  186. package/corpus/templates/clips/changelog/2026-07-10-clips-desktop-is-now-available-for-linux-with-appimage-debia.md +6 -0
  187. package/corpus/templates/clips/changelog/2026-07-10-clips-downloads-updates-sooner-in-the-background-and-offers-.md +6 -0
  188. package/corpus/templates/clips/changelog/2026-07-10-clips-shared-with-you-now-appear-in-a-searchable-shared-with.md +6 -0
  189. package/corpus/templates/clips/changelog/2026-07-10-clips-with-missing-mobile-video-frames-can-be-repaired-witho.md +6 -0
  190. package/corpus/templates/clips/changelog/2026-07-10-mobile-camera-recordings-pause-while-backgrounded.md +6 -0
  191. package/corpus/templates/clips/changelog/2026-07-10-mp4-downloads-now-show-progress-immediately-after-the-option.md +6 -0
  192. package/corpus/templates/clips/changelog/2026-07-10-recording-pages-now-open-as-soon-as-you-stop-with-a-share-li.md +6 -0
  193. package/corpus/templates/clips/changelog/2026-07-10-recordings-now-seek-smoothly-downloads-use-the-correct-file-.md +6 -0
  194. package/corpus/templates/clips/changelog/2026-07-10-s3-compatible-storage-now-saves-hosted-recordings-without-re.md +6 -0
  195. package/corpus/templates/clips/desktop/README.md +22 -6
  196. package/corpus/templates/clips/desktop/package.json +1 -1
  197. package/corpus/templates/clips/desktop/src/app.tsx +32 -19
  198. package/corpus/templates/clips/desktop/src/components/ReadinessPanel.tsx +15 -9
  199. package/corpus/templates/clips/desktop/src/lib/finalization-guard.ts +22 -0
  200. package/corpus/templates/clips/desktop/src/lib/permissions.ts +3 -1
  201. package/corpus/templates/clips/desktop/src/lib/recorder.ts +97 -120
  202. package/corpus/templates/clips/desktop/src/lib/updater.ts +26 -4
  203. package/corpus/templates/clips/desktop/src/overlays/finalizing.tsx +4 -8
  204. package/corpus/templates/clips/desktop/src-tauri/Cargo.toml +1 -1
  205. package/corpus/templates/clips/desktop/src-tauri/src/clips/mod.rs +2 -2
  206. package/corpus/templates/clips/desktop/src-tauri/src/permission_status.rs +11 -7
  207. package/corpus/templates/clips/desktop/src-tauri/tauri.linux.conf.json +11 -0
  208. package/corpus/templates/clips/netlify.toml +3 -0
  209. package/corpus/templates/clips/server/lib/post-finalize-dispatch.ts +106 -0
  210. package/corpus/templates/clips/server/lib/public-agent-context.ts +9 -1
  211. package/corpus/templates/clips/server/lib/resumable-upload-provider.ts +52 -0
  212. package/corpus/templates/clips/server/lib/s3-upload-provider.ts +433 -85
  213. package/corpus/templates/clips/server/lib/video-remux.ts +114 -0
  214. package/corpus/templates/clips/server/routes/api/_agent-native-background/post-finalize-worker.post.ts +109 -0
  215. package/corpus/templates/clips/server/routes/api/clips-updater.json.get.ts +22 -11
  216. package/corpus/templates/clips/server/routes/api/public-recording.get.ts +4 -2
  217. package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/abort.post.ts +47 -5
  218. package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/chunk.post.ts +10 -2
  219. package/corpus/templates/clips/shared/share-loader-response.ts +12 -0
  220. package/corpus/templates/clips/shared/transcript-status.ts +40 -0
  221. package/corpus/templates/content/.agents/skills/capture-learnings/SKILL.md +22 -9
  222. package/corpus/templates/content/.agents/skills/content/SKILL.md +57 -5
  223. package/corpus/templates/content/AGENTS.md +65 -55
  224. package/corpus/templates/content/actions/_builder-cms-read-client.ts +10 -16
  225. package/corpus/templates/content/actions/_database-source-utils.ts +58 -11
  226. package/corpus/templates/content/actions/_property-utils.ts +30 -2
  227. package/corpus/templates/content/actions/add-content-database-source-field-property.ts +312 -114
  228. package/corpus/templates/content/actions/submit-content-database-form.ts +497 -0
  229. package/corpus/templates/content/actions/update-content-database-view.ts +8 -1
  230. package/corpus/templates/content/actions/view-screen.ts +4 -1
  231. package/corpus/templates/content/agent-native.app-skill.json +1 -1
  232. package/corpus/templates/content/app/components/editor/database/DatabaseView.tsx +250 -64
  233. package/corpus/templates/content/app/components/editor/database/FormView.tsx +460 -0
  234. package/corpus/templates/content/app/components/editor/database/navigation-state.ts +3 -0
  235. package/corpus/templates/content/app/components/editor/database/settings.tsx +30 -37
  236. package/corpus/templates/content/app/components/editor/database/shared.tsx +2 -0
  237. package/corpus/templates/content/app/components/editor/database/view-config.ts +29 -1
  238. package/corpus/templates/content/app/components/ui/textarea.tsx +1 -0
  239. package/corpus/templates/content/app/hooks/use-content-database.ts +22 -0
  240. package/corpus/templates/content/app/i18n/zh-TW.ts +21 -0
  241. package/corpus/templates/content/app/i18n-data.ts +225 -0
  242. package/corpus/templates/content/changelog/2026-07-10-builder-backed-properties-now-load-current-source-values-as-.md +6 -0
  243. package/corpus/templates/content/changelog/2026-07-10-builder-database-refreshes-now-stay-explicit-and-accurate.md +6 -0
  244. package/corpus/templates/content/changelog/2026-07-10-database-form-views-now-collect-ordered-required-answers-and.md +6 -0
  245. package/corpus/templates/content/changelog/2026-07-10-database-tables-now-use-a-quieter-more-compact-layout-with-c.md +6 -0
  246. package/corpus/templates/content/changelog/2026-07-10-slack-intake-routes-to-content-database-forms.md +6 -0
  247. package/corpus/templates/content/parity/matrix.md +1 -0
  248. package/corpus/templates/content/parity/matrix.ts +18 -0
  249. package/corpus/templates/content/shared/api.ts +27 -1
  250. package/corpus/templates/content/shared/database-form.ts +53 -0
  251. package/corpus/templates/design/.agents/skills/capture-learnings/SKILL.md +22 -9
  252. package/corpus/templates/design/.agents/skills/design-generation/SKILL.md +26 -0
  253. package/corpus/templates/design/.agents/skills/design-systems/SKILL.md +85 -12
  254. package/corpus/templates/design/AGENTS.md +72 -18
  255. package/corpus/templates/design/DESIGN.md +1 -1
  256. package/corpus/templates/design/DEVELOPING.md +1 -1
  257. package/corpus/templates/design/FIGMA_INTEROPERABILITY.md +116 -0
  258. package/corpus/templates/design/actions/create-design-from-template.ts +220 -0
  259. package/corpus/templates/design/actions/create-design-system.ts +92 -16
  260. package/corpus/templates/design/actions/delete-design-template.ts +28 -0
  261. package/corpus/templates/design/actions/delete-file.ts +7 -0
  262. package/corpus/templates/design/actions/edit-design.ts +3 -0
  263. package/corpus/templates/design/actions/export-design-as-figma-svg.ts +137 -5
  264. package/corpus/templates/design/actions/export-pdf.ts +1 -1
  265. package/corpus/templates/design/actions/generate-design.ts +3 -0
  266. package/corpus/templates/design/actions/get-design-snapshot.ts +9 -0
  267. package/corpus/templates/design/actions/get-figma-connection-status.ts +26 -0
  268. package/corpus/templates/design/actions/get-figma-design-context.ts +138 -0
  269. package/corpus/templates/design/actions/get-figma-styles.ts +2 -2
  270. package/corpus/templates/design/actions/import-figma-clipboard.ts +112 -16
  271. package/corpus/templates/design/actions/import-figma-frame.ts +15 -4
  272. package/corpus/templates/design/actions/index-design-system-with-builder.ts +4 -0
  273. package/corpus/templates/design/actions/list-design-templates.ts +118 -0
  274. package/corpus/templates/design/actions/navigate.ts +16 -2
  275. package/corpus/templates/design/actions/provider-api-request.ts +11 -1
  276. package/corpus/templates/design/actions/save-design-as-template.ts +156 -0
  277. package/corpus/templates/design/actions/set-active-breakpoint.ts +13 -4
  278. package/corpus/templates/design/actions/take-design-screenshot.ts +73 -3
  279. package/corpus/templates/design/actions/update-file.ts +39 -22
  280. package/corpus/templates/design/actions/view-screen.ts +36 -1
  281. package/corpus/templates/design/actions/write-local-file.ts +50 -38
  282. package/corpus/templates/design/app/components/design/AutoLayoutSuggestionDialog.tsx +151 -0
  283. package/corpus/templates/design/app/components/design/CanvasContextMenu.tsx +20 -0
  284. package/corpus/templates/design/app/components/design/DesignCanvas.tsx +251 -22
  285. package/corpus/templates/design/app/components/design/DesignEditorSkeleton.tsx +3 -3
  286. package/corpus/templates/design/app/components/design/DesignImportPanel.tsx +384 -9
  287. package/corpus/templates/design/app/components/design/EditPanel.tsx +105 -32
  288. package/corpus/templates/design/app/components/design/MultiScreenCanvas.tsx +58 -28
  289. package/corpus/templates/design/app/components/design/TweaksPanel.tsx +6 -0
  290. package/corpus/templates/design/app/components/design/bridge/editor-chrome.bridge.ts +539 -53
  291. package/corpus/templates/design/app/components/design/bridge/embedded-wheel.bridge.ts +40 -0
  292. package/corpus/templates/design/app/components/design/code-workbench/CodeWorkbench.tsx +1 -0
  293. package/corpus/templates/design/app/components/design/code-workbench/explorer/ExplorerView.tsx +1 -0
  294. package/corpus/templates/design/app/components/design/code-workbench/explorer/FileTree.tsx +5 -1
  295. package/corpus/templates/design/app/components/design/code-workbench/workspace/create-providers.ts +2 -0
  296. package/corpus/templates/design/app/components/design/code-workbench/workspace/localhost-provider.ts +3 -1
  297. package/corpus/templates/design/app/components/design/code-workbench/workspace/types.ts +2 -0
  298. package/corpus/templates/design/app/components/design/edit-panel/element-identity.ts +19 -0
  299. package/corpus/templates/design/app/components/design/edit-panel/frame-presets-panel.tsx +1 -0
  300. package/corpus/templates/design/app/components/design/edit-panel/interaction-state-helpers.ts +27 -0
  301. package/corpus/templates/design/app/components/design/inspector/InteractionStatePanel.tsx +137 -81
  302. package/corpus/templates/design/app/components/design/inspector/frame-size-presets.ts +25 -5
  303. package/corpus/templates/design/app/components/design/multi-screen/chrome-transitions.ts +1 -1
  304. package/corpus/templates/design/app/components/design/multi-screen/frame-geometry.ts +220 -3
  305. package/corpus/templates/design/app/components/design/multi-screen/overview-layout.ts +13 -0
  306. package/corpus/templates/design/app/components/design/multi-screen/types.ts +22 -1
  307. package/corpus/templates/design/app/components/design/types.ts +4 -0
  308. package/corpus/templates/design/app/components/design-system/ProductionDesignSystemShowcase.tsx +208 -0
  309. package/corpus/templates/design/app/components/editor/FigmaLinkComposerBubble.tsx +321 -0
  310. package/corpus/templates/design/app/components/editor/PromptDialog.tsx +24 -4
  311. package/corpus/templates/design/app/components/layout/Layout.tsx +16 -2
  312. package/corpus/templates/design/app/components/layout/Sidebar.tsx +2 -0
  313. package/corpus/templates/design/app/components/templates/TemplatePreview.tsx +72 -0
  314. package/corpus/templates/design/app/global.css +2 -35
  315. package/corpus/templates/design/app/hooks/use-navigation-state.ts +10 -0
  316. package/corpus/templates/design/app/i18n/zh-TW.ts +127 -5
  317. package/corpus/templates/design/app/i18n-breakpoints.ts +209 -0
  318. package/corpus/templates/design/app/i18n-data.ts +1317 -59
  319. package/corpus/templates/design/app/i18n-template-feature.ts +458 -0
  320. package/corpus/templates/design/app/lib/design-clipboard.ts +202 -0
  321. package/corpus/templates/design/app/lib/design-file-upload.ts +87 -0
  322. package/corpus/templates/design/app/lib/design-import.ts +168 -11
  323. package/corpus/templates/design/app/lib/desktop-design-preview.ts +423 -0
  324. package/corpus/templates/design/app/lib/figma-clipboard.ts +74 -8
  325. package/corpus/templates/design/app/lib/figma-connection.ts +161 -0
  326. package/corpus/templates/design/app/lib/figma-svg-copy.ts +814 -22
  327. package/corpus/templates/design/app/lib/figma-url.ts +77 -0
  328. package/corpus/templates/design/app/lib/pending-generation.ts +35 -0
  329. package/corpus/templates/design/app/pages/DesignSystems.tsx +236 -177
  330. package/corpus/templates/design/app/pages/Index.tsx +38 -0
  331. package/corpus/templates/design/app/pages/Templates.tsx +498 -0
  332. package/corpus/templates/design/app/pages/design-editor/auto-layout-suggestion.ts +328 -0
  333. package/corpus/templates/design/app/pages/design-editor/clone-idrefs.ts +113 -0
  334. package/corpus/templates/design/app/pages/design-editor/created-screen-navigation.ts +55 -0
  335. package/corpus/templates/design/app/pages/design-editor/editor-session.ts +32 -0
  336. package/corpus/templates/design/app/pages/design-editor/editor-state.ts +49 -2
  337. package/corpus/templates/design/app/pages/design-editor/export-capture.ts +296 -0
  338. package/corpus/templates/design/app/pages/design-editor/history.ts +101 -2
  339. package/corpus/templates/design/app/pages/design-editor/layout-operations.ts +28 -1
  340. package/corpus/templates/design/app/pages/design-editor/overview-camera.ts +34 -0
  341. package/corpus/templates/design/app/pages/design-editor/pending-edits.ts +202 -6
  342. package/corpus/templates/design/app/pages/design-editor/pending-structure-verification.ts +92 -0
  343. package/corpus/templates/design/app/pages/design-editor/save-failure.ts +58 -0
  344. package/corpus/templates/design/app/routes/templates.tsx +4 -6
  345. package/corpus/templates/design/changelog/2026-07-10-app-workspaces-now-use-clean-borderless-main-surfaces-throug.md +6 -0
  346. package/corpus/templates/design/changelog/2026-07-10-ask-chat-what-s-in-a-figma-file-or-frame-structure-screensho.md +6 -0
  347. package/corpus/templates/design/changelog/2026-07-10-canvas-edits-now-reject-malformed-html-before-it-can-corrupt.md +6 -0
  348. package/corpus/templates/design/changelog/2026-07-10-complex-designs-now-export-as-valid-secure-svgs-and-crisp-ra.md +6 -0
  349. package/corpus/templates/design/changelog/2026-07-10-complex-figma-masks-arcs-rich-text-transformed-images-and-ad.md +6 -0
  350. package/corpus/templates/design/changelog/2026-07-10-copied-layers-paste-across-designs-and-browser-tabs.md +6 -0
  351. package/corpus/templates/design/changelog/2026-07-10-copy-and-download-editable-figma-svg.md +6 -0
  352. package/corpus/templates/design/changelog/2026-07-10-copying-design-text-now-pastes-readable-text-into-other-apps.md +6 -0
  353. package/corpus/templates/design/changelog/2026-07-10-deleted-screens-can-be-restored-with-undo-and-removed-again-.md +6 -0
  354. package/corpus/templates/design/changelog/2026-07-10-design-changes-now-save-before-switching-apps-and-retry-when.md +6 -0
  355. package/corpus/templates/design/changelog/2026-07-10-design-stays-usable-on-phones-by-keeping-editor-panels-and-f.md +6 -0
  356. package/corpus/templates/design/changelog/2026-07-10-download-all-screens-as-one-multi-page-pdf-from-the-overview.md +6 -0
  357. package/corpus/templates/design/changelog/2026-07-10-duplicated-layers-now-keep-labels-aria-relationships-fragmen.md +6 -0
  358. package/corpus/templates/design/changelog/2026-07-10-fig-import-results-stay-compact.md +6 -0
  359. package/corpus/templates/design/changelog/2026-07-10-figma-imports-now-load-real-fonts-fix-rotated-gradient-dashe.md +6 -0
  360. package/corpus/templates/design/changelog/2026-07-10-figma-links-in-chat-and-the-import-tab-now-offer-secure-one-.md +6 -0
  361. package/corpus/templates/design/changelog/2026-07-10-fixed-cmd-z-not-restoring-content-after-an-agent-driven-desi.md +6 -0
  362. package/corpus/templates/design/changelog/2026-07-10-fixed-download-pdf-being-unreachable-from-the-export-panel-e.md +6 -0
  363. package/corpus/templates/design/changelog/2026-07-10-fixed-dragging-a-layer-out-of-an-auto-layout-row-column-no-l.md +6 -0
  364. package/corpus/templates/design/changelog/2026-07-10-fixed-figma-svg-export-text-wrapping-sizing-and-inner-layer.md +6 -0
  365. package/corpus/templates/design/changelog/2026-07-10-fixed-hiding-or-locking-one-layer-no-longer-hides-or-blocks-.md +6 -0
  366. package/corpus/templates/design/changelog/2026-07-10-fixed-png-screenshots-of-tall-screens-being-cropped-to-one-v.md +6 -0
  367. package/corpus/templates/design/changelog/2026-07-10-fixed-png-svg-exports-capturing-broken-layout-when-webfonts-.md +6 -0
  368. package/corpus/templates/design/changelog/2026-07-10-frame-tool-now-offers-standard-ad-unit-size-presets-medium-r.md +6 -0
  369. package/corpus/templates/design/changelog/2026-07-10-full-view-controls-stay-within-their-frame-instead-of-coveri.md +6 -0
  370. package/corpus/templates/design/changelog/2026-07-10-hover-focus-focus-visible-pressed-and-disabled-states-now-pr.md +6 -0
  371. package/corpus/templates/design/changelog/2026-07-10-layer-drops-now-land-in-the-intended-grid-row-stay-visually-.md +6 -0
  372. package/corpus/templates/design/changelog/2026-07-10-local-code-workspaces-now-keep-unsaved-edits-across-panel-sw.md +6 -0
  373. package/corpus/templates/design/changelog/2026-07-10-local-visual-editing-now-keeps-authenticated-sessions-shared.md +6 -0
  374. package/corpus/templates/design/changelog/2026-07-10-long-running-agent-work-no-longer-shows-a-premature-stuck-wa.md +6 -0
  375. package/corpus/templates/design/changelog/2026-07-10-managed-figma-connections-are-recognized-automatically.md +6 -0
  376. package/corpus/templates/design/changelog/2026-07-10-new-designs-can-open-directly-in-the-editor-without-a-pr.md +6 -0
  377. package/corpus/templates/design/changelog/2026-07-10-new-screens-are-selected-and-revealed-immediately.md +6 -0
  378. package/corpus/templates/design/changelog/2026-07-10-new-text-layers-undo-as-one-safe-creation.md +6 -0
  379. package/corpus/templates/design/changelog/2026-07-10-preview-and-apply-inferred-auto-layout-without-changing-yo.md +5 -0
  380. package/corpus/templates/design/changelog/2026-07-10-print-pdf-exports-and-paper-size-presets-letter-a4-now-match.md +6 -0
  381. package/corpus/templates/design/changelog/2026-07-10-responsive-frame-editing.md +6 -0
  382. package/corpus/templates/design/changelog/2026-07-10-reusable-design-templates.md +6 -0
  383. package/corpus/templates/design/changelog/2026-07-10-screen-overview-frames-now-use-a-clearer-interact-action-wit.md +6 -0
  384. package/corpus/templates/design/changelog/2026-07-10-start-designs-from-source-linked-material-3-carbon-or-primer.md +6 -0
  385. package/corpus/templates/design/changelog/2026-07-10-tweaks-guidance.md +6 -0
  386. package/corpus/templates/design/changelog/2026-07-10-uploaded-fig-files-can-now-become-editable-design-screens-wi.md +6 -0
  387. package/corpus/templates/design/e2e/helpers.ts +3 -3
  388. package/corpus/templates/design/package.json +2 -0
  389. package/corpus/templates/design/scripts/qa-figma-stress-import.ts +96 -0
  390. package/corpus/templates/design/server/db/index.ts +10 -0
  391. package/corpus/templates/design/server/db/schema.ts +44 -0
  392. package/corpus/templates/design/server/handlers/import-design-file.ts +114 -80
  393. package/corpus/templates/design/server/handlers/index-design-system-with-builder.ts +19 -6
  394. package/corpus/templates/design/server/lib/design-export.ts +240 -3
  395. package/corpus/templates/design/server/lib/design-template-data.ts +89 -0
  396. package/corpus/templates/design/server/lib/design-to-figma-svg.ts +250 -26
  397. package/corpus/templates/design/server/lib/fig-file-decoder.ts +839 -0
  398. package/corpus/templates/design/server/lib/fig-file-import.ts +287 -0
  399. package/corpus/templates/design/server/lib/fig-file-limits.ts +3 -0
  400. package/corpus/templates/design/server/lib/fig-file-to-html.ts +2568 -0
  401. package/corpus/templates/design/server/lib/figma-design-context.ts +359 -0
  402. package/corpus/templates/design/server/lib/figma-node-import.ts +478 -22
  403. package/corpus/templates/design/server/lib/figma-node-to-html.ts +554 -29
  404. package/corpus/templates/design/server/lib/local-figma-qa-upload.ts +112 -0
  405. package/corpus/templates/design/server/lib/verify-write-grant.ts +16 -2
  406. package/corpus/templates/design/server/lib/visible-clipboard-html.ts +13 -3
  407. package/corpus/templates/design/server/plugins/agent-chat.ts +7 -0
  408. package/corpus/templates/design/server/plugins/db.ts +42 -0
  409. package/corpus/templates/design/server/plugins/local-figma-qa-upload.ts +7 -0
  410. package/corpus/templates/design/server/register-secrets.ts +8 -8
  411. package/corpus/templates/design/server/routes/api/qa-figma-import-assets/[assetId].get.ts +46 -0
  412. package/corpus/templates/design/server/source-workspace.ts +104 -12
  413. package/corpus/templates/design/shared/code-layer.ts +105 -28
  414. package/corpus/templates/design/shared/design-system-templates.ts +301 -0
  415. package/corpus/templates/design/shared/design-template-presets.ts +195 -0
  416. package/corpus/templates/design/shared/figma-url.ts +8 -0
  417. package/corpus/templates/design/shared/html-integrity.ts +306 -0
  418. package/corpus/templates/design/shared/interaction-states.ts +318 -23
  419. package/corpus/templates/design/shared/locked-layers.ts +151 -0
  420. package/corpus/templates/dispatch/.agents/skills/capture-learnings/SKILL.md +22 -9
  421. package/corpus/templates/dispatch/app/i18n/zh-TW.ts +48 -0
  422. package/corpus/templates/dispatch/app/i18n-data.ts +536 -1
  423. package/corpus/templates/dispatch/changelog/2026-07-10-connect-slack-workspaces-with-oauth-and-manage-channel-ident.md +6 -0
  424. package/corpus/templates/dispatch/changelog/2026-07-10-microsoft-teams-bots-and-discord-slash-commands-can-now-conn.md +6 -0
  425. package/corpus/templates/dispatch/changelog/2026-07-10-slack-and-telegram-now-route-uptime-monitor-requests-to-anal.md +6 -0
  426. package/corpus/templates/forms/.agents/skills/capture-learnings/SKILL.md +22 -9
  427. package/corpus/templates/forms/.agents/skills/form-publishing/SKILL.md +7 -0
  428. package/corpus/templates/forms/AGENTS.md +4 -0
  429. package/corpus/templates/forms/actions/create-form.ts +44 -7
  430. package/corpus/templates/forms/actions/lib/assert-publishable-form.ts +38 -0
  431. package/corpus/templates/forms/actions/patch-form-fields.ts +4 -0
  432. package/corpus/templates/forms/actions/update-form.ts +2 -36
  433. package/corpus/templates/forms/app/i18n/ar-SA.ts +3 -0
  434. package/corpus/templates/forms/app/i18n/de-DE.ts +3 -0
  435. package/corpus/templates/forms/app/i18n/en-US.ts +3 -0
  436. package/corpus/templates/forms/app/i18n/es-ES.ts +3 -0
  437. package/corpus/templates/forms/app/i18n/fr-FR.ts +3 -0
  438. package/corpus/templates/forms/app/i18n/hi-IN.ts +3 -0
  439. package/corpus/templates/forms/app/i18n/ja-JP.ts +3 -0
  440. package/corpus/templates/forms/app/i18n/ko-KR.ts +3 -0
  441. package/corpus/templates/forms/app/i18n/pt-BR.ts +3 -0
  442. package/corpus/templates/forms/app/i18n/zh-CN.ts +2 -0
  443. package/corpus/templates/forms/app/i18n/zh-TW.ts +3 -0
  444. package/corpus/templates/forms/app/pages/FormBuilderPage.tsx +17 -0
  445. package/corpus/templates/forms/changelog/2026-07-10-agent-created-published-forms-now-return-the-anonymous-publi.md +6 -0
  446. package/corpus/templates/forms/changelog/2026-07-10-published-forms-can-no-longer-be-edited-into-an-unusable-emp.md +6 -0
  447. package/corpus/templates/forms/server/handlers/submissions.ts +4 -3
  448. package/corpus/templates/forms/server/plugins/agent-chat.ts +1 -0
  449. package/corpus/templates/forms/shared/types.ts +5 -0
  450. package/corpus/templates/mail/.agents/skills/capture-learnings/SKILL.md +22 -9
  451. package/corpus/templates/mail/app/components/layout/AppLayout.tsx +2 -2
  452. package/corpus/templates/mail/changelog/2026-07-10-mail-navigation-now-uses-a-clean-borderless-drawer.md +6 -0
  453. package/corpus/templates/plan/.agents/skills/capture-learnings/SKILL.md +22 -9
  454. package/corpus/templates/plan/app/lib/plan-local-bridge.ts +4 -1
  455. package/corpus/templates/plan/changelog/2026-07-10-local-plans-now-keep-valid-content-visible-when-one-generate.md +6 -0
  456. package/corpus/templates/plan/server/lib/local-plan-files.ts +4 -1
  457. package/corpus/templates/slides/.agents/skills/capture-learnings/SKILL.md +22 -9
  458. package/dist/a2a/artifact-response.d.ts.map +1 -1
  459. package/dist/a2a/artifact-response.js +88 -2
  460. package/dist/a2a/artifact-response.js.map +1 -1
  461. package/dist/a2a/client.d.ts +9 -0
  462. package/dist/a2a/client.d.ts.map +1 -1
  463. package/dist/a2a/client.js +1 -0
  464. package/dist/a2a/client.js.map +1 -1
  465. package/dist/a2a/handlers.d.ts.map +1 -1
  466. package/dist/a2a/handlers.js +24 -69
  467. package/dist/a2a/handlers.js.map +1 -1
  468. package/dist/a2a/types.d.ts +2 -0
  469. package/dist/a2a/types.d.ts.map +1 -1
  470. package/dist/a2a/types.js.map +1 -1
  471. package/dist/agent/durable-background.d.ts +11 -0
  472. package/dist/agent/durable-background.d.ts.map +1 -1
  473. package/dist/agent/durable-background.js +17 -0
  474. package/dist/agent/durable-background.js.map +1 -1
  475. package/dist/agent/production-agent.d.ts +2 -2
  476. package/dist/agent/production-agent.d.ts.map +1 -1
  477. package/dist/agent/production-agent.js +15 -5
  478. package/dist/agent/production-agent.js.map +1 -1
  479. package/dist/agent/run-manager.d.ts +44 -2
  480. package/dist/agent/run-manager.d.ts.map +1 -1
  481. package/dist/agent/run-manager.js +90 -9
  482. package/dist/agent/run-manager.js.map +1 -1
  483. package/dist/agent/run-store.d.ts +109 -0
  484. package/dist/agent/run-store.d.ts.map +1 -1
  485. package/dist/agent/run-store.js +206 -15
  486. package/dist/agent/run-store.js.map +1 -1
  487. package/dist/agent/types.d.ts +22 -0
  488. package/dist/agent/types.d.ts.map +1 -1
  489. package/dist/agent/types.js.map +1 -1
  490. package/dist/audit/record.d.ts.map +1 -1
  491. package/dist/audit/record.js +29 -0
  492. package/dist/audit/record.js.map +1 -1
  493. package/dist/audit/store.d.ts.map +1 -1
  494. package/dist/audit/store.js +62 -3
  495. package/dist/audit/store.js.map +1 -1
  496. package/dist/audit/types.d.ts +13 -0
  497. package/dist/audit/types.d.ts.map +1 -1
  498. package/dist/audit/types.js.map +1 -1
  499. package/dist/automation/index.d.ts +193 -0
  500. package/dist/automation/index.d.ts.map +1 -0
  501. package/dist/automation/index.js +464 -0
  502. package/dist/automation/index.js.map +1 -0
  503. package/dist/cli/create.d.ts.map +1 -1
  504. package/dist/cli/create.js +10 -3
  505. package/dist/cli/create.js.map +1 -1
  506. package/dist/cli/design-connect.d.ts.map +1 -1
  507. package/dist/cli/design-connect.js +492 -35
  508. package/dist/cli/design-connect.js.map +1 -1
  509. package/dist/client/AgentPanel.d.ts +7 -1
  510. package/dist/client/AgentPanel.d.ts.map +1 -1
  511. package/dist/client/AgentPanel.js +32 -8
  512. package/dist/client/AgentPanel.js.map +1 -1
  513. package/dist/client/AssistantChat.d.ts +15 -0
  514. package/dist/client/AssistantChat.d.ts.map +1 -1
  515. package/dist/client/AssistantChat.js +115 -47
  516. package/dist/client/AssistantChat.js.map +1 -1
  517. package/dist/client/MultiTabAssistantChat.d.ts.map +1 -1
  518. package/dist/client/MultiTabAssistantChat.js +1 -1
  519. package/dist/client/MultiTabAssistantChat.js.map +1 -1
  520. package/dist/client/RunStuckBanner.d.ts +14 -1
  521. package/dist/client/RunStuckBanner.d.ts.map +1 -1
  522. package/dist/client/RunStuckBanner.js +35 -7
  523. package/dist/client/RunStuckBanner.js.map +1 -1
  524. package/dist/client/agent-chat-adapter.d.ts +4 -1
  525. package/dist/client/agent-chat-adapter.d.ts.map +1 -1
  526. package/dist/client/agent-chat-adapter.js +49 -4
  527. package/dist/client/agent-chat-adapter.js.map +1 -1
  528. package/dist/client/automation.d.ts +14 -0
  529. package/dist/client/automation.d.ts.map +1 -0
  530. package/dist/client/automation.js +9 -0
  531. package/dist/client/automation.js.map +1 -0
  532. package/dist/client/chat/run-recovery.d.ts +4 -0
  533. package/dist/client/chat/run-recovery.d.ts.map +1 -1
  534. package/dist/client/chat/run-recovery.js +12 -10
  535. package/dist/client/chat/run-recovery.js.map +1 -1
  536. package/dist/client/composer/TiptapComposer.d.ts.map +1 -1
  537. package/dist/client/composer/TiptapComposer.js +8 -0
  538. package/dist/client/composer/TiptapComposer.js.map +1 -1
  539. package/dist/client/index.d.ts +2 -0
  540. package/dist/client/index.d.ts.map +1 -1
  541. package/dist/client/index.js +2 -0
  542. package/dist/client/index.js.map +1 -1
  543. package/dist/client/integrations/api.d.ts +115 -0
  544. package/dist/client/integrations/api.d.ts.map +1 -0
  545. package/dist/client/integrations/api.js +123 -0
  546. package/dist/client/integrations/api.js.map +1 -0
  547. package/dist/client/integrations/index.d.ts +1 -0
  548. package/dist/client/integrations/index.d.ts.map +1 -1
  549. package/dist/client/integrations/index.js +1 -0
  550. package/dist/client/integrations/index.js.map +1 -1
  551. package/dist/client/transcription/use-live-transcription.d.ts.map +1 -1
  552. package/dist/client/transcription/use-live-transcription.js +59 -5
  553. package/dist/client/transcription/use-live-transcription.js.map +1 -1
  554. package/dist/client/use-run-stuck-detection.d.ts +16 -1
  555. package/dist/client/use-run-stuck-detection.d.ts.map +1 -1
  556. package/dist/client/use-run-stuck-detection.js +23 -4
  557. package/dist/client/use-run-stuck-detection.js.map +1 -1
  558. package/dist/collab/struct-routes.d.ts +1 -1
  559. package/dist/deploy/build.d.ts.map +1 -1
  560. package/dist/deploy/build.js +49 -4
  561. package/dist/deploy/build.js.map +1 -1
  562. package/dist/deploy/workspace-deploy.d.ts.map +1 -1
  563. package/dist/deploy/workspace-deploy.js +31 -2
  564. package/dist/deploy/workspace-deploy.js.map +1 -1
  565. package/dist/file-upload/types.d.ts +2 -0
  566. package/dist/file-upload/types.d.ts.map +1 -1
  567. package/dist/file-upload/types.js.map +1 -1
  568. package/dist/index.d.ts +2 -0
  569. package/dist/index.d.ts.map +1 -1
  570. package/dist/index.js +2 -0
  571. package/dist/index.js.map +1 -1
  572. package/dist/integrations/a2a-continuations-store.d.ts.map +1 -1
  573. package/dist/integrations/a2a-continuations-store.js +6 -4
  574. package/dist/integrations/a2a-continuations-store.js.map +1 -1
  575. package/dist/integrations/adapters/discord.d.ts +3 -0
  576. package/dist/integrations/adapters/discord.d.ts.map +1 -0
  577. package/dist/integrations/adapters/discord.js +261 -0
  578. package/dist/integrations/adapters/discord.js.map +1 -0
  579. package/dist/integrations/adapters/index.d.ts +4 -0
  580. package/dist/integrations/adapters/index.d.ts.map +1 -0
  581. package/dist/integrations/adapters/index.js +26 -0
  582. package/dist/integrations/adapters/index.js.map +1 -0
  583. package/dist/integrations/adapters/microsoft-teams.d.ts +5 -0
  584. package/dist/integrations/adapters/microsoft-teams.d.ts.map +1 -0
  585. package/dist/integrations/adapters/microsoft-teams.js +295 -0
  586. package/dist/integrations/adapters/microsoft-teams.js.map +1 -0
  587. package/dist/integrations/adapters/slack.d.ts +8 -2
  588. package/dist/integrations/adapters/slack.d.ts.map +1 -1
  589. package/dist/integrations/adapters/slack.js +736 -27
  590. package/dist/integrations/adapters/slack.js.map +1 -1
  591. package/dist/integrations/adapters/telegram.d.ts +0 -2
  592. package/dist/integrations/adapters/telegram.d.ts.map +1 -1
  593. package/dist/integrations/adapters/telegram.js +49 -15
  594. package/dist/integrations/adapters/telegram.js.map +1 -1
  595. package/dist/integrations/adapters/whatsapp.d.ts +0 -2
  596. package/dist/integrations/adapters/whatsapp.d.ts.map +1 -1
  597. package/dist/integrations/adapters/whatsapp.js +40 -17
  598. package/dist/integrations/adapters/whatsapp.js.map +1 -1
  599. package/dist/integrations/catalog.d.ts +75 -0
  600. package/dist/integrations/catalog.d.ts.map +1 -0
  601. package/dist/integrations/catalog.js +451 -0
  602. package/dist/integrations/catalog.js.map +1 -0
  603. package/dist/integrations/controls-store.d.ts +44 -0
  604. package/dist/integrations/controls-store.d.ts.map +1 -0
  605. package/dist/integrations/controls-store.js +129 -0
  606. package/dist/integrations/controls-store.js.map +1 -0
  607. package/dist/integrations/index.d.ts +13 -1
  608. package/dist/integrations/index.d.ts.map +1 -1
  609. package/dist/integrations/index.js +9 -0
  610. package/dist/integrations/index.js.map +1 -1
  611. package/dist/integrations/installations-store.d.ts +112 -0
  612. package/dist/integrations/installations-store.d.ts.map +1 -0
  613. package/dist/integrations/installations-store.js +493 -0
  614. package/dist/integrations/installations-store.js.map +1 -0
  615. package/dist/integrations/integration-memory.d.ts +24 -0
  616. package/dist/integrations/integration-memory.d.ts.map +1 -0
  617. package/dist/integrations/integration-memory.js +136 -0
  618. package/dist/integrations/integration-memory.js.map +1 -0
  619. package/dist/integrations/pending-tasks-retry-job.d.ts.map +1 -1
  620. package/dist/integrations/pending-tasks-retry-job.js +6 -5
  621. package/dist/integrations/pending-tasks-retry-job.js.map +1 -1
  622. package/dist/integrations/pending-tasks-store.d.ts +17 -0
  623. package/dist/integrations/pending-tasks-store.d.ts.map +1 -1
  624. package/dist/integrations/pending-tasks-store.js +71 -5
  625. package/dist/integrations/pending-tasks-store.js.map +1 -1
  626. package/dist/integrations/plugin.d.ts.map +1 -1
  627. package/dist/integrations/plugin.js +520 -35
  628. package/dist/integrations/plugin.js.map +1 -1
  629. package/dist/integrations/scope-store.d.ts +65 -0
  630. package/dist/integrations/scope-store.d.ts.map +1 -0
  631. package/dist/integrations/scope-store.js +361 -0
  632. package/dist/integrations/scope-store.js.map +1 -0
  633. package/dist/integrations/slack-manifest.d.ts +66 -0
  634. package/dist/integrations/slack-manifest.d.ts.map +1 -0
  635. package/dist/integrations/slack-manifest.js +70 -0
  636. package/dist/integrations/slack-manifest.js.map +1 -0
  637. package/dist/integrations/slack-oauth.d.ts +99 -0
  638. package/dist/integrations/slack-oauth.d.ts.map +1 -0
  639. package/dist/integrations/slack-oauth.js +226 -0
  640. package/dist/integrations/slack-oauth.js.map +1 -0
  641. package/dist/integrations/types.d.ts +144 -0
  642. package/dist/integrations/types.d.ts.map +1 -1
  643. package/dist/integrations/types.js +16 -1
  644. package/dist/integrations/types.js.map +1 -1
  645. package/dist/integrations/usage-budget-store.d.ts +84 -0
  646. package/dist/integrations/usage-budget-store.d.ts.map +1 -0
  647. package/dist/integrations/usage-budget-store.js +650 -0
  648. package/dist/integrations/usage-budget-store.js.map +1 -0
  649. package/dist/integrations/webhook-handler.d.ts +4 -0
  650. package/dist/integrations/webhook-handler.d.ts.map +1 -1
  651. package/dist/integrations/webhook-handler.js +415 -47
  652. package/dist/integrations/webhook-handler.js.map +1 -1
  653. package/dist/jobs/scheduler.d.ts +6 -0
  654. package/dist/jobs/scheduler.d.ts.map +1 -1
  655. package/dist/jobs/scheduler.js +83 -4
  656. package/dist/jobs/scheduler.js.map +1 -1
  657. package/dist/jobs/tools.d.ts.map +1 -1
  658. package/dist/jobs/tools.js +43 -11
  659. package/dist/jobs/tools.js.map +1 -1
  660. package/dist/observability/routes.d.ts +5 -5
  661. package/dist/progress/routes.d.ts +1 -1
  662. package/dist/provider-api/index.d.ts +4 -4
  663. package/dist/provider-api/index.d.ts.map +1 -1
  664. package/dist/provider-api/index.js +72 -1
  665. package/dist/provider-api/index.js.map +1 -1
  666. package/dist/resources/handlers.d.ts +3 -3
  667. package/dist/resources/handlers.d.ts.map +1 -1
  668. package/dist/resources/handlers.js +57 -15
  669. package/dist/resources/handlers.js.map +1 -1
  670. package/dist/resources/script-helpers.d.ts.map +1 -1
  671. package/dist/resources/script-helpers.js +34 -8
  672. package/dist/resources/script-helpers.js.map +1 -1
  673. package/dist/resources/store.d.ts +10 -0
  674. package/dist/resources/store.d.ts.map +1 -1
  675. package/dist/resources/store.js +54 -47
  676. package/dist/resources/store.js.map +1 -1
  677. package/dist/scripts/call-agent.d.ts.map +1 -1
  678. package/dist/scripts/call-agent.js +106 -1
  679. package/dist/scripts/call-agent.js.map +1 -1
  680. package/dist/server/agent-chat-plugin.d.ts +15 -4
  681. package/dist/server/agent-chat-plugin.d.ts.map +1 -1
  682. package/dist/server/agent-chat-plugin.js +248 -113
  683. package/dist/server/agent-chat-plugin.js.map +1 -1
  684. package/dist/server/auth.d.ts.map +1 -1
  685. package/dist/server/auth.js +10 -14
  686. package/dist/server/auth.js.map +1 -1
  687. package/dist/server/builder-design-systems.d.ts +3 -1
  688. package/dist/server/builder-design-systems.d.ts.map +1 -1
  689. package/dist/server/builder-design-systems.js +9 -2
  690. package/dist/server/builder-design-systems.js.map +1 -1
  691. package/dist/server/edge.d.ts +1 -1
  692. package/dist/server/edge.d.ts.map +1 -1
  693. package/dist/server/edge.js +1 -1
  694. package/dist/server/edge.js.map +1 -1
  695. package/dist/server/index.d.ts +2 -1
  696. package/dist/server/index.d.ts.map +1 -1
  697. package/dist/server/index.js +2 -1
  698. package/dist/server/index.js.map +1 -1
  699. package/dist/server/request-context.d.ts +18 -0
  700. package/dist/server/request-context.d.ts.map +1 -1
  701. package/dist/server/request-context.js.map +1 -1
  702. package/dist/server/social-og-image.d.ts.map +1 -1
  703. package/dist/server/social-og-image.js +3 -2
  704. package/dist/server/social-og-image.js.map +1 -1
  705. package/dist/server/transcribe-voice.d.ts +1 -1
  706. package/dist/styles/agent-native.css +62 -44
  707. package/dist/templates/default/.agents/skills/capture-learnings/SKILL.md +22 -9
  708. package/dist/templates/default/AGENTS.md +7 -3
  709. package/dist/templates/workspace-core/.agents/skills/authentication/SKILL.md +1 -1
  710. package/dist/templates/workspace-core/.agents/skills/capture-learnings/SKILL.md +22 -9
  711. package/dist/templates/workspace-core/.agents/skills/extension-points/SKILL.md +6 -3
  712. package/dist/templates/workspace-core/.agents/skills/extensions/SKILL.md +25 -0
  713. package/dist/templates/workspace-core/.agents/skills/integration-webhooks/SKILL.md +15 -0
  714. package/dist/templates/workspace-core/AGENTS.md +3 -2
  715. package/dist/usage/store.d.ts +7 -0
  716. package/dist/usage/store.d.ts.map +1 -1
  717. package/dist/usage/store.js +24 -3
  718. package/dist/usage/store.js.map +1 -1
  719. package/docs/content/automation-connectors.mdx +80 -0
  720. package/docs/content/extensions.mdx +8 -0
  721. package/docs/content/locales/ar-SA/extensions.mdx +8 -0
  722. package/docs/content/locales/ar-SA/messaging.mdx +84 -15
  723. package/docs/content/locales/ar-SA/template-clips.mdx +1 -0
  724. package/docs/content/locales/ar-SA/template-design.mdx +1 -0
  725. package/docs/content/locales/de-DE/extensions.mdx +10 -0
  726. package/docs/content/locales/de-DE/messaging.mdx +92 -15
  727. package/docs/content/locales/de-DE/template-clips.mdx +1 -0
  728. package/docs/content/locales/de-DE/template-design.mdx +1 -0
  729. package/docs/content/locales/es-ES/extensions.mdx +10 -0
  730. package/docs/content/locales/es-ES/messaging.mdx +91 -15
  731. package/docs/content/locales/es-ES/template-clips.mdx +1 -0
  732. package/docs/content/locales/es-ES/template-design.mdx +1 -0
  733. package/docs/content/locales/fr-FR/extensions.mdx +10 -0
  734. package/docs/content/locales/fr-FR/messaging.mdx +91 -15
  735. package/docs/content/locales/fr-FR/template-clips.mdx +1 -0
  736. package/docs/content/locales/fr-FR/template-design.mdx +1 -0
  737. package/docs/content/locales/hi-IN/extensions.mdx +8 -0
  738. package/docs/content/locales/hi-IN/messaging.mdx +81 -15
  739. package/docs/content/locales/hi-IN/template-clips.mdx +1 -0
  740. package/docs/content/locales/hi-IN/template-design.mdx +1 -0
  741. package/docs/content/locales/ja-JP/extensions.mdx +9 -0
  742. package/docs/content/locales/ja-JP/messaging.mdx +81 -15
  743. package/docs/content/locales/ja-JP/template-clips.mdx +1 -0
  744. package/docs/content/locales/ja-JP/template-design.mdx +1 -0
  745. package/docs/content/locales/ko-KR/extensions.mdx +8 -0
  746. package/docs/content/locales/ko-KR/messaging.mdx +80 -15
  747. package/docs/content/locales/ko-KR/template-clips.mdx +1 -0
  748. package/docs/content/locales/ko-KR/template-design.mdx +1 -0
  749. package/docs/content/locales/pt-BR/extensions.mdx +9 -0
  750. package/docs/content/locales/pt-BR/messaging.mdx +88 -15
  751. package/docs/content/locales/pt-BR/template-clips.mdx +1 -0
  752. package/docs/content/locales/pt-BR/template-design.mdx +1 -0
  753. package/docs/content/locales/zh-CN/extensions.mdx +6 -0
  754. package/docs/content/locales/zh-CN/messaging.mdx +78 -15
  755. package/docs/content/locales/zh-CN/template-clips.mdx +1 -0
  756. package/docs/content/locales/zh-CN/template-design.mdx +1 -0
  757. package/docs/content/locales/zh-TW/extensions.mdx +6 -0
  758. package/docs/content/locales/zh-TW/messaging.mdx +78 -15
  759. package/docs/content/locales/zh-TW/template-clips.mdx +1 -0
  760. package/docs/content/locales/zh-TW/template-design.mdx +1 -0
  761. package/docs/content/messaging.mdx +227 -45
  762. package/docs/content/template-clips.mdx +3 -0
  763. package/docs/content/template-design.mdx +4 -0
  764. package/package.json +5 -1
  765. package/src/templates/default/.agents/skills/capture-learnings/SKILL.md +22 -9
  766. package/src/templates/default/AGENTS.md +7 -3
  767. package/src/templates/workspace-core/.agents/skills/authentication/SKILL.md +1 -1
  768. package/src/templates/workspace-core/.agents/skills/capture-learnings/SKILL.md +22 -9
  769. package/src/templates/workspace-core/.agents/skills/extension-points/SKILL.md +6 -3
  770. package/src/templates/workspace-core/.agents/skills/extensions/SKILL.md +25 -0
  771. package/src/templates/workspace-core/.agents/skills/integration-webhooks/SKILL.md +15 -0
  772. package/src/templates/workspace-core/AGENTS.md +3 -2
@@ -3,6 +3,7 @@ import crypto from "node:crypto";
3
3
  import fsSync from "node:fs";
4
4
  import fs from "node:fs/promises";
5
5
  import http from "node:http";
6
+ import https from "node:https";
6
7
  import path from "node:path";
7
8
  const DEFAULT_BRIDGE_PORT = 7331;
8
9
  const ROUTE_MANIFEST_FILE = path.join(".agent-native", "design-routes.json");
@@ -40,6 +41,7 @@ const MANIFEST_CAPABILITIES = {
40
41
  writeTextFiles: true,
41
42
  };
42
43
  const PREVIEW_TOKEN_DOMAIN = "agent-native-design-preview-v1\0";
44
+ const PREVIEW_SESSION_COOKIE_NAME = "agent-native-preview-token";
43
45
  /**
44
46
  * Derive a read-only preview credential from the stronger filesystem token.
45
47
  * The one-way hash keeps old `--bridge-token` launch commands compatible while
@@ -601,8 +603,8 @@ function configureBridgeCors(req, res, configuredOrigins) {
601
603
  res[BRIDGE_CORS_HEADERS] = approved
602
604
  ? {
603
605
  "access-control-allow-origin": origin,
604
- "access-control-allow-methods": "GET, HEAD, POST, OPTIONS",
605
- "access-control-allow-headers": "content-type, x-bridge-token, x-design-preview-token",
606
+ "access-control-allow-methods": "GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS",
607
+ "access-control-allow-headers": "authorization, content-type, x-bridge-token, x-design-preview-token, x-csrf-token, x-xsrf-token, x-requested-with",
606
608
  "access-control-allow-private-network": "true",
607
609
  vary: "Origin",
608
610
  }
@@ -619,17 +621,19 @@ function sendJson(res, statusCode, body) {
619
621
  });
620
622
  res.end(`${JSON.stringify(body, null, 2)}\n`);
621
623
  }
622
- function sendText(res, statusCode, body, contentType) {
624
+ function sendText(res, statusCode, body, contentType, setCookieHeaders = []) {
623
625
  res.writeHead(statusCode, {
624
626
  "content-type": contentType,
627
+ ...(setCookieHeaders.length > 0 ? { "set-cookie": setCookieHeaders } : {}),
625
628
  ...bridgeCorsHeaders(res),
626
629
  });
627
630
  res.end(body);
628
631
  }
629
- function sendBytes(res, statusCode, body, headers, contentLength = body.length) {
632
+ function sendBytes(res, statusCode, body, headers, contentLength = body.length, setCookieHeaders = []) {
630
633
  const responseHeaders = {
631
634
  ...bridgeCorsHeaders(res),
632
635
  "content-length": String(contentLength),
636
+ ...(setCookieHeaders.length > 0 ? { "set-cookie": setCookieHeaders } : {}),
633
637
  };
634
638
  for (const name of [
635
639
  "content-type",
@@ -665,23 +669,232 @@ function readHeader(req, name) {
665
669
  const value = req.headers[name];
666
670
  return typeof value === "string" ? value : "";
667
671
  }
672
+ function readRequestCookie(req, name) {
673
+ for (const rawPair of readHeader(req, "cookie").split(";")) {
674
+ const pair = rawPair.trim();
675
+ const separator = pair.indexOf("=");
676
+ if (separator <= 0 || pair.slice(0, separator).trim() !== name)
677
+ continue;
678
+ return pair.slice(separator + 1).trim();
679
+ }
680
+ return "";
681
+ }
682
+ function previewSessionSetCookie(previewToken) {
683
+ // Partitioned SameSite=None keeps the read-only bridge credential available
684
+ // to nested Design frames without granting an unpartitioned third-party
685
+ // cookie. Loopback origins are potentially trustworthy in Chromium, which
686
+ // permits Secure cookies for local development.
687
+ return `${PREVIEW_SESSION_COOKIE_NAME}=${previewToken}; HttpOnly; Path=/; SameSite=None; Secure; Partitioned`;
688
+ }
668
689
  /**
669
- * Preserve only the browser request metadata a local dev server needs to
670
- * classify Vite source-module and stylesheet requests. Agent Native's dev
671
- * gateway intentionally varies source-file handling by `Sec-Fetch-Dest`; if
672
- * the bridge drops it, React Router module URLs such as `/app/root.tsx` fall
673
- * through to Nitro and 404. Keep this allowlist narrow: cookies, authorization,
674
- * bridge tokens, origins, and referrers must never be forwarded upstream.
690
+ * Preserve only browser metadata a local dev server needs to classify module
691
+ * requests and parse ordinary same-origin app mutations. Browser cookies and
692
+ * Authorization are forwarded only when Sec-Fetch-Site says the request came
693
+ * from the proxied app itself; cross-site callers cannot relay them. Bridge
694
+ * control tokens and referrers are never forwarded, and mutation origins are
695
+ * replaced with the connected dev-server origin. Cookie-backed login also
696
+ * uses the isolated in-memory upstream jar below so iframe cookie restrictions
697
+ * cannot split the session across URL-backed screens.
675
698
  */
676
- function previewProxyRequestHeaders(req) {
699
+ function previewProxyRequestHeaders(req, devServerUrl, cookieHeader = "") {
677
700
  const headers = {};
678
- for (const name of ["accept", "sec-fetch-dest"]) {
701
+ for (const name of [
702
+ "accept",
703
+ "accept-language",
704
+ "content-type",
705
+ "sec-fetch-dest",
706
+ "sec-fetch-mode",
707
+ "sec-fetch-site",
708
+ "x-csrf-token",
709
+ "x-xsrf-token",
710
+ "x-requested-with",
711
+ ]) {
679
712
  const value = readHeader(req, name);
680
713
  if (value)
681
714
  headers[name] = value;
682
715
  }
716
+ const browserSameOrigin = readHeader(req, "sec-fetch-site") === "same-origin";
717
+ const browserCookie = browserSameOrigin ? readHeader(req, "cookie") : "";
718
+ const mergedCookie = mergePreviewCookieHeaders(cookieHeader, browserCookie);
719
+ if (mergedCookie)
720
+ headers["cookie"] = mergedCookie;
721
+ // Same-origin app code may use localStorage-backed bearer auth. Forward it
722
+ // only from a browser request already classified as same-origin; cross-site
723
+ // callers still authenticate to the bridge with the separate preview token,
724
+ // which is never copied upstream.
725
+ if (browserSameOrigin) {
726
+ const authorization = readHeader(req, "authorization");
727
+ if (authorization && authorization.length <= 16 * 1024) {
728
+ headers["authorization"] = authorization;
729
+ }
730
+ }
731
+ if (req.method && !["GET", "HEAD"].includes(req.method)) {
732
+ headers["origin"] = new URL(devServerUrl).origin;
733
+ }
683
734
  return headers;
684
735
  }
736
+ function mergePreviewCookieHeaders(jarCookieHeader, browserCookieHeader) {
737
+ const values = new Map();
738
+ const absorb = (header) => {
739
+ if (!header || Buffer.byteLength(header) > MAX_PREVIEW_COOKIE_BYTES)
740
+ return;
741
+ for (const rawPair of header.split(";")) {
742
+ const pair = rawPair.trim();
743
+ const separator = pair.indexOf("=");
744
+ if (separator <= 0)
745
+ continue;
746
+ const name = pair.slice(0, separator).trim();
747
+ const value = pair.slice(separator + 1).trim();
748
+ if (!/^[!#$%&'*+.^_`|~0-9A-Za-z-]+$/.test(name))
749
+ continue;
750
+ if (/^(?:x-)?agent-native-(?:bridge|preview)(?:-|$)/i.test(name)) {
751
+ continue;
752
+ }
753
+ values.set(name, value);
754
+ }
755
+ };
756
+ absorb(jarCookieHeader);
757
+ // A client-readable same-origin cookie is allowed to update the jar's stale
758
+ // value for this request. HttpOnly cookies arrive with the same value and
759
+ // remain effectively jar-owned.
760
+ absorb(browserCookieHeader);
761
+ return [...values].map(([name, value]) => `${name}=${value}`).join("; ");
762
+ }
763
+ const MAX_PREVIEW_SESSION_COOKIES = 128;
764
+ const MAX_PREVIEW_COOKIE_BYTES = 8 * 1024;
765
+ function responseSetCookieHeaders(headers) {
766
+ const withGetSetCookie = headers;
767
+ if (typeof withGetSetCookie.getSetCookie === "function") {
768
+ return withGetSetCookie.getSetCookie();
769
+ }
770
+ const single = headers.get("set-cookie");
771
+ return single ? [single] : [];
772
+ }
773
+ function defaultCookiePath(url) {
774
+ const pathname = url.pathname || "/";
775
+ const lastSlash = pathname.lastIndexOf("/");
776
+ return lastSlash <= 0 ? "/" : pathname.slice(0, lastSlash);
777
+ }
778
+ function sanitizedBridgeSetCookie(raw) {
779
+ return raw
780
+ .split(";")
781
+ .filter((part) => !/^\s*domain\s*=/i.test(part))
782
+ .join(";");
783
+ }
784
+ /**
785
+ * Ephemeral cookie session for one connected dev-server origin. Cookies never
786
+ * enter SQL, disk, logs, or another target origin, and disappear when the
787
+ * local bridge exits. This keeps authenticated URL screens in one bridge
788
+ * process on the same upstream session even when browser third-party-cookie
789
+ * rules would otherwise isolate or reject the nested iframe cookies.
790
+ */
791
+ class PreviewSessionCookieJar {
792
+ origin;
793
+ cookies = new Map();
794
+ constructor(devServerUrl) {
795
+ this.origin = new URL(devServerUrl).origin;
796
+ }
797
+ store(headers, responseUrl) {
798
+ const parsedUrl = new URL(responseUrl);
799
+ if (parsedUrl.origin !== this.origin)
800
+ return [];
801
+ const browserCookies = [];
802
+ for (const raw of responseSetCookieHeaders(headers)) {
803
+ if (!raw || Buffer.byteLength(raw) > MAX_PREVIEW_COOKIE_BYTES)
804
+ continue;
805
+ const parts = raw.split(";");
806
+ const first = parts.shift()?.trim() ?? "";
807
+ const separator = first.indexOf("=");
808
+ if (separator <= 0)
809
+ continue;
810
+ const name = first.slice(0, separator).trim();
811
+ const value = first.slice(separator + 1).trim();
812
+ if (!/^[!#$%&'*+.^_`|~0-9A-Za-z-]+$/.test(name))
813
+ continue;
814
+ let cookiePath = defaultCookiePath(parsedUrl);
815
+ let secure = false;
816
+ let expiresAt;
817
+ let deleteCookie = false;
818
+ for (const attribute of parts) {
819
+ const trimmed = attribute.trim();
820
+ const equals = trimmed.indexOf("=");
821
+ const key = (equals < 0 ? trimmed : trimmed.slice(0, equals))
822
+ .trim()
823
+ .toLowerCase();
824
+ const attributeValue = equals < 0 ? "" : trimmed.slice(equals + 1).trim();
825
+ if (key === "path" && attributeValue.startsWith("/")) {
826
+ cookiePath = attributeValue;
827
+ }
828
+ else if (key === "secure") {
829
+ secure = true;
830
+ }
831
+ else if (key === "max-age") {
832
+ const seconds = Number(attributeValue);
833
+ if (Number.isFinite(seconds)) {
834
+ deleteCookie = seconds <= 0;
835
+ expiresAt = Date.now() + seconds * 1000;
836
+ }
837
+ }
838
+ else if (key === "expires" && expiresAt === undefined) {
839
+ const parsed = Date.parse(attributeValue);
840
+ if (Number.isFinite(parsed))
841
+ expiresAt = parsed;
842
+ }
843
+ }
844
+ const mapKey = `${cookiePath}\u0000${name}`;
845
+ if (deleteCookie ||
846
+ (expiresAt !== undefined && expiresAt <= Date.now())) {
847
+ this.cookies.delete(mapKey);
848
+ }
849
+ else {
850
+ this.cookies.delete(mapKey);
851
+ this.cookies.set(mapKey, {
852
+ name,
853
+ value,
854
+ path: cookiePath,
855
+ secure,
856
+ ...(expiresAt !== undefined ? { expiresAt } : {}),
857
+ });
858
+ while (this.cookies.size > MAX_PREVIEW_SESSION_COOKIES) {
859
+ const oldest = this.cookies.keys().next().value;
860
+ if (typeof oldest !== "string")
861
+ break;
862
+ this.cookies.delete(oldest);
863
+ }
864
+ }
865
+ browserCookies.push(sanitizedBridgeSetCookie(raw));
866
+ }
867
+ return browserCookies;
868
+ }
869
+ headerFor(targetUrl) {
870
+ const parsed = new URL(targetUrl);
871
+ if (parsed.origin !== this.origin)
872
+ return "";
873
+ const now = Date.now();
874
+ const matches = [];
875
+ for (const [key, cookie] of this.cookies) {
876
+ if (cookie.expiresAt !== undefined && cookie.expiresAt <= now) {
877
+ this.cookies.delete(key);
878
+ continue;
879
+ }
880
+ if (cookie.secure &&
881
+ parsed.protocol !== "https:" &&
882
+ !isLoopbackOrigin(parsed)) {
883
+ continue;
884
+ }
885
+ const pathMatches = cookie.path === "/" ||
886
+ parsed.pathname === cookie.path ||
887
+ (cookie.path.endsWith("/")
888
+ ? parsed.pathname.startsWith(cookie.path)
889
+ : parsed.pathname.startsWith(`${cookie.path}/`));
890
+ if (!pathMatches)
891
+ continue;
892
+ matches.push(cookie);
893
+ }
894
+ matches.sort((a, b) => b.path.length - a.path.length);
895
+ return matches.map((cookie) => `${cookie.name}=${cookie.value}`).join("; ");
896
+ }
897
+ }
685
898
  function resolvePreviewSnapshotUrl(devServerUrl, rawUrl) {
686
899
  const base = normalizeHttpUrl(devServerUrl);
687
900
  const parsed = new URL(rawUrl?.trim() || "/", `${base}/`);
@@ -704,7 +917,7 @@ function resolvePreviewProxyUrl(devServerUrl, requestUrl) {
704
917
  }
705
918
  return parsed.toString();
706
919
  }
707
- async function fetchPreviewSnapshot(devServerUrl, targetUrl, redirects = 0) {
920
+ async function fetchPreviewSnapshot(devServerUrl, targetUrl, cookieJar, redirects = 0) {
708
921
  if (redirects > 5) {
709
922
  throw new Error("Too many redirects while fetching preview snapshot.");
710
923
  }
@@ -717,8 +930,12 @@ async function fetchPreviewSnapshot(devServerUrl, targetUrl, redirects = 0) {
717
930
  signal: controller.signal,
718
931
  headers: {
719
932
  accept: "text/html,application/xhtml+xml;q=0.9,*/*;q=0.8",
933
+ ...(cookieJar?.headerFor(targetUrl)
934
+ ? { cookie: cookieJar.headerFor(targetUrl) }
935
+ : {}),
720
936
  },
721
937
  });
938
+ const setCookieHeaders = cookieJar?.store(response.headers, targetUrl) ?? [];
722
939
  const location = response.headers.get("location");
723
940
  if (location && response.status >= 300 && response.status < 400) {
724
941
  const redirected = new URL(location, targetUrl);
@@ -726,20 +943,21 @@ async function fetchPreviewSnapshot(devServerUrl, targetUrl, redirects = 0) {
726
943
  if (!sameOrigin(redirected.toString(), devServerUrl)) {
727
944
  throw new Error("Snapshot redirect left the connected dev server.");
728
945
  }
729
- return fetchPreviewSnapshot(devServerUrl, redirected.toString(), redirects + 1);
946
+ return fetchPreviewSnapshot(devServerUrl, redirected.toString(), cookieJar, redirects + 1);
730
947
  }
731
948
  return {
732
949
  url: response.url || targetUrl,
733
950
  status: response.status,
734
951
  contentType: response.headers.get("content-type") ?? "",
735
952
  html: await response.text(),
953
+ setCookieHeaders,
736
954
  };
737
955
  }
738
956
  finally {
739
957
  clearTimeout(timeout);
740
958
  }
741
959
  }
742
- async function fetchPreviewProxyResource(devServerUrl, targetUrl, requestHeaders = {}, redirects = 0) {
960
+ async function fetchPreviewProxyResource(devServerUrl, targetUrl, request, cookieJar, redirects = 0) {
743
961
  if (redirects > 5) {
744
962
  throw new Error("Too many redirects while proxying preview resource.");
745
963
  }
@@ -747,11 +965,15 @@ async function fetchPreviewProxyResource(devServerUrl, targetUrl, requestHeaders
747
965
  const timeout = setTimeout(() => controller.abort(), 10_000);
748
966
  try {
749
967
  const response = await fetch(targetUrl, {
750
- method: "GET",
968
+ method: request.method,
751
969
  redirect: "manual",
752
970
  signal: controller.signal,
753
- headers: requestHeaders,
971
+ headers: request.headers,
972
+ body: request.method === "GET" || request.method === "HEAD"
973
+ ? undefined
974
+ : request.body,
754
975
  });
976
+ const setCookieHeaders = cookieJar?.store(response.headers, targetUrl) ?? [];
755
977
  const location = response.headers.get("location");
756
978
  if (location && response.status >= 300 && response.status < 400) {
757
979
  const redirected = new URL(location, targetUrl);
@@ -759,13 +981,33 @@ async function fetchPreviewProxyResource(devServerUrl, targetUrl, requestHeaders
759
981
  if (!sameOrigin(redirected.toString(), devServerUrl)) {
760
982
  throw new Error("Proxy redirect left the connected dev server.");
761
983
  }
762
- return fetchPreviewProxyResource(devServerUrl, redirected.toString(), requestHeaders, redirects + 1);
984
+ const switchToGet = response.status === 303 ||
985
+ ((response.status === 301 || response.status === 302) &&
986
+ request.method === "POST");
987
+ const redirectedResponse = await fetchPreviewProxyResource(devServerUrl, redirected.toString(), {
988
+ method: switchToGet ? "GET" : request.method,
989
+ headers: {
990
+ ...(request.headers ?? {}),
991
+ ...(cookieJar?.headerFor(redirected.toString())
992
+ ? { cookie: cookieJar.headerFor(redirected.toString()) }
993
+ : {}),
994
+ },
995
+ body: switchToGet ? undefined : request.body,
996
+ }, cookieJar, redirects + 1);
997
+ return {
998
+ ...redirectedResponse,
999
+ setCookieHeaders: [
1000
+ ...setCookieHeaders,
1001
+ ...redirectedResponse.setCookieHeaders,
1002
+ ],
1003
+ };
763
1004
  }
764
1005
  return {
765
1006
  url: response.url || targetUrl,
766
1007
  status: response.status,
767
1008
  headers: response.headers,
768
1009
  body: Buffer.from(await response.arrayBuffer()),
1010
+ setCookieHeaders,
769
1011
  };
770
1012
  }
771
1013
  finally {
@@ -829,6 +1071,39 @@ async function readRequestBody(req) {
829
1071
  req.on("error", reject);
830
1072
  });
831
1073
  }
1074
+ const MAX_PREVIEW_PROXY_REQUEST_BYTES = 8 * 1024 * 1024;
1075
+ class PreviewProxyRequestTooLargeError extends Error {
1076
+ }
1077
+ async function readPreviewProxyRequestBody(req) {
1078
+ const declaredLength = Number(readHeader(req, "content-length"));
1079
+ if (Number.isFinite(declaredLength) &&
1080
+ declaredLength > MAX_PREVIEW_PROXY_REQUEST_BYTES) {
1081
+ throw new PreviewProxyRequestTooLargeError("Preview request body exceeds the 8 MB limit.");
1082
+ }
1083
+ return new Promise((resolve, reject) => {
1084
+ const chunks = [];
1085
+ let size = 0;
1086
+ let tooLarge = false;
1087
+ req.on("data", (chunk) => {
1088
+ size += chunk.length;
1089
+ if (size > MAX_PREVIEW_PROXY_REQUEST_BYTES) {
1090
+ tooLarge = true;
1091
+ chunks.length = 0;
1092
+ return;
1093
+ }
1094
+ if (!tooLarge)
1095
+ chunks.push(chunk);
1096
+ });
1097
+ req.on("end", () => {
1098
+ if (tooLarge) {
1099
+ reject(new PreviewProxyRequestTooLargeError("Preview request body exceeds the 8 MB limit."));
1100
+ return;
1101
+ }
1102
+ resolve(Buffer.concat(chunks));
1103
+ });
1104
+ req.on("error", reject);
1105
+ });
1106
+ }
832
1107
  /**
833
1108
  * Resolve `targetDir` under `rootPath` with realpath so that symlinks and
834
1109
  * traversal sequences (../../etc) cannot escape the root. Throws if the
@@ -1055,8 +1330,13 @@ async function atomicWriteBridgeFile(args) {
1055
1330
  await fs.rm(tempPath, { force: true }).catch(() => undefined);
1056
1331
  }
1057
1332
  }
1058
- /** Allowed file extensions for write/apply-edit operations. */
1059
- const ALLOWED_WRITE_EXTENSIONS = new Set([
1333
+ /**
1334
+ * Extensions that are safe for creating a brand-new text/code file through
1335
+ * the bridge. Existing files are classified by their bytes instead, so the
1336
+ * Code workbench can edit languages and extensionless config files without a
1337
+ * permanently incomplete allowlist.
1338
+ */
1339
+ const ALLOWED_NEW_TEXT_FILE_EXTENSIONS = new Set([
1060
1340
  ".html",
1061
1341
  ".htm",
1062
1342
  ".css",
@@ -1078,11 +1358,90 @@ const ALLOWED_WRITE_EXTENSIONS = new Set([
1078
1358
  ".yml",
1079
1359
  ".yaml",
1080
1360
  ".svg",
1361
+ ".py",
1362
+ ".rb",
1363
+ ".php",
1364
+ ".java",
1365
+ ".kt",
1366
+ ".kts",
1367
+ ".go",
1368
+ ".rs",
1369
+ ".c",
1370
+ ".h",
1371
+ ".cc",
1372
+ ".cpp",
1373
+ ".hpp",
1374
+ ".cs",
1375
+ ".swift",
1376
+ ".sh",
1377
+ ".bash",
1378
+ ".zsh",
1379
+ ".fish",
1380
+ ".sql",
1381
+ ".toml",
1382
+ ".xml",
1383
+ ".graphql",
1384
+ ".gql",
1385
+ ".prisma",
1386
+ ".properties",
1387
+ ".ini",
1388
+ ".conf",
1389
+ ".env.example",
1390
+ ]);
1391
+ const ALLOWED_NEW_EXTENSIONLESS_TEXT_FILES = new Set([
1392
+ "dockerfile",
1393
+ "makefile",
1394
+ "procfile",
1395
+ "gemfile",
1396
+ "rakefile",
1397
+ "license",
1398
+ "readme",
1081
1399
  ]);
1082
- function assertAllowedExtension(relPath) {
1400
+ const BLOCKED_BINARY_WRITE_EXTENSIONS = new Set([
1401
+ ".png",
1402
+ ".jpg",
1403
+ ".jpeg",
1404
+ ".gif",
1405
+ ".webp",
1406
+ ".ico",
1407
+ ".woff",
1408
+ ".woff2",
1409
+ ".ttf",
1410
+ ".otf",
1411
+ ".eot",
1412
+ ".mp3",
1413
+ ".mp4",
1414
+ ".mov",
1415
+ ".webm",
1416
+ ".zip",
1417
+ ".gz",
1418
+ ".tar",
1419
+ ".pdf",
1420
+ ".wasm",
1421
+ ".fig",
1422
+ ".sketch",
1423
+ ".exe",
1424
+ ".dll",
1425
+ ".dylib",
1426
+ ".so",
1427
+ ".class",
1428
+ ".jar",
1429
+ ]);
1430
+ function assertEditableTextFile(relPath, existing) {
1083
1431
  const ext = path.extname(relPath).toLowerCase();
1084
- if (!ALLOWED_WRITE_EXTENSIONS.has(ext)) {
1085
- throw new Error(`Write rejected: extension "${ext || "(no extension)"}" is not in the allowed text-file list for bridge writes.`);
1432
+ if (BLOCKED_BINARY_WRITE_EXTENSIONS.has(ext)) {
1433
+ throw new Error(`Write rejected: extension "${ext}" is a binary file type.`);
1434
+ }
1435
+ if (existing) {
1436
+ if (existing.content.includes("\0")) {
1437
+ throw new Error("Write rejected: the existing file contains binary data.");
1438
+ }
1439
+ return;
1440
+ }
1441
+ const basename = path.basename(relPath).toLowerCase();
1442
+ if (!ALLOWED_NEW_TEXT_FILE_EXTENSIONS.has(ext) &&
1443
+ !ALLOWED_NEW_EXTENSIONLESS_TEXT_FILES.has(basename)) {
1444
+ throw new Error(`Write rejected: extension "${ext || "(no extension)"}" is not recognized for a new text/code file.`);
1086
1445
  }
1087
1446
  }
1088
1447
  /**
@@ -1423,6 +1782,7 @@ export async function startDesignConnectBridge(manifest, seedOrOptions) {
1423
1782
  // registered" (id changed, safe to transparently re-POST `/live-edit-bridge`
1424
1783
  // and retry) — instead of guessing from the error text or retrying forever.
1425
1784
  const bridgeInstanceId = crypto.randomBytes(16).toString("hex");
1785
+ const previewSessionCookies = new PreviewSessionCookieJar(manifest.devServerUrl);
1426
1786
  const server = http.createServer((req, res) => {
1427
1787
  const corsApproved = configureBridgeCors(req, res, configuredOrigins);
1428
1788
  if (req.method === "OPTIONS") {
@@ -1435,6 +1795,7 @@ export async function startDesignConnectBridge(manifest, seedOrOptions) {
1435
1795
  const pathname = requestUrl.pathname;
1436
1796
  const providedPreviewToken = readHeader(req, "x-design-preview-token") ||
1437
1797
  requestUrl.searchParams.get("previewToken") ||
1798
+ readRequestCookie(req, PREVIEW_SESSION_COOKIE_NAME) ||
1438
1799
  "";
1439
1800
  const previewTokenValid = constantTimeTokenMatches(providedPreviewToken, previewToken);
1440
1801
  const rejectInvalidPreviewToken = () => {
@@ -1546,7 +1907,7 @@ export async function startDesignConnectBridge(manifest, seedOrOptions) {
1546
1907
  try {
1547
1908
  const targetUrl = resolvePreviewSnapshotUrl(manifest.devServerUrl, requestUrl.searchParams.get("url") ??
1548
1909
  requestUrl.searchParams.get("path"));
1549
- const snapshot = await fetchPreviewSnapshot(manifest.devServerUrl, targetUrl);
1910
+ const snapshot = await fetchPreviewSnapshot(manifest.devServerUrl, targetUrl, previewSessionCookies);
1550
1911
  const includeEditorBridge = requestUrl.searchParams.get("bridge") !== "0";
1551
1912
  const requestedBridgeKey = requestUrl.searchParams.get("bridgeKey")?.trim() ?? "";
1552
1913
  const editorBridgeScript = requestedBridgeKey
@@ -1578,7 +1939,10 @@ export async function startDesignConnectBridge(manifest, seedOrOptions) {
1578
1939
  const html = injectLiveEditBridge(snapshot.html, new URL("/", manifest.bridgeUrl).toString(), includeEditorBridge ? editorBridgeScript : "", targetPath);
1579
1940
  sendText(res, snapshot.status >= 400 ? snapshot.status : 200, html, snapshot.contentType.includes("html")
1580
1941
  ? snapshot.contentType
1581
- : "text/html; charset=utf-8");
1942
+ : "text/html; charset=utf-8", [
1943
+ ...snapshot.setCookieHeaders,
1944
+ previewSessionSetCookie(previewToken),
1945
+ ]);
1582
1946
  }
1583
1947
  catch (err) {
1584
1948
  sendJson(res, 400, {
@@ -1600,7 +1964,7 @@ export async function startDesignConnectBridge(manifest, seedOrOptions) {
1600
1964
  try {
1601
1965
  const targetUrl = resolvePreviewSnapshotUrl(manifest.devServerUrl, requestUrl.searchParams.get("url") ??
1602
1966
  requestUrl.searchParams.get("path"));
1603
- const snapshot = await fetchPreviewSnapshot(manifest.devServerUrl, targetUrl);
1967
+ const snapshot = await fetchPreviewSnapshot(manifest.devServerUrl, targetUrl, previewSessionCookies);
1604
1968
  sendJson(res, snapshot.status >= 400 ? snapshot.status : 200, {
1605
1969
  ok: snapshot.status < 400,
1606
1970
  source: manifest.source,
@@ -1683,8 +2047,6 @@ export async function startDesignConnectBridge(manifest, seedOrOptions) {
1683
2047
  });
1684
2048
  return;
1685
2049
  }
1686
- // write-file and apply-edit only allow known text/code extensions.
1687
- assertAllowedExtension(relPath);
1688
2050
  const expectedVersionHash = typeof body["expectedVersionHash"] === "string"
1689
2051
  ? body["expectedVersionHash"]
1690
2052
  : undefined;
@@ -1695,6 +2057,7 @@ export async function startDesignConnectBridge(manifest, seedOrOptions) {
1695
2057
  throw new Error("Bridge target changed while waiting for the write lock");
1696
2058
  }
1697
2059
  const existing = await readBridgeFileSnapshot(lockedTarget.absolutePath);
2060
+ assertEditableTextFile(relPath, existing);
1698
2061
  assertExpectedBridgeVersion(expectedVersionHash, existing?.versionHash, requireExpectedVersionHash);
1699
2062
  if (pathname === "/write-file") {
1700
2063
  const content = typeof body["content"] === "string"
@@ -1821,9 +2184,9 @@ export async function startDesignConnectBridge(manifest, seedOrOptions) {
1821
2184
  })();
1822
2185
  return;
1823
2186
  }
1824
- if (req.method === "GET" || req.method === "HEAD") {
1825
- const sameOriginPreviewSubresource = readHeader(req, "sec-fetch-site") === "same-origin";
1826
- if (!previewTokenValid && !sameOriginPreviewSubresource) {
2187
+ if (req.method &&
2188
+ ["GET", "HEAD", "POST", "PUT", "PATCH", "DELETE"].includes(req.method)) {
2189
+ if (!previewTokenValid) {
1827
2190
  sendJson(res, 401, {
1828
2191
  ok: false,
1829
2192
  error: "invalid or missing preview token",
@@ -1832,12 +2195,31 @@ export async function startDesignConnectBridge(manifest, seedOrOptions) {
1832
2195
  }
1833
2196
  void (async () => {
1834
2197
  try {
1835
- const targetUrl = resolvePreviewProxyUrl(manifest.devServerUrl, req.url);
1836
- const proxied = await fetchPreviewProxyResource(manifest.devServerUrl, targetUrl, previewProxyRequestHeaders(req));
1837
- sendBytes(res, proxied.status >= 400 ? proxied.status : 200, req.method === "HEAD" ? Buffer.alloc(0) : proxied.body, proxied.headers, proxied.body.length);
2198
+ const proxyRequestUrl = new URL(req.url ?? "/", manifest.bridgeUrl);
2199
+ proxyRequestUrl.searchParams.delete("previewToken");
2200
+ const targetUrl = resolvePreviewProxyUrl(manifest.devServerUrl, `${proxyRequestUrl.pathname}${proxyRequestUrl.search}`);
2201
+ const method = req.method ?? "GET";
2202
+ const requestBody = method === "GET" || method === "HEAD"
2203
+ ? undefined
2204
+ : await readPreviewProxyRequestBody(req);
2205
+ const cookieHeader = previewSessionCookies.headerFor(targetUrl);
2206
+ const proxied = await fetchPreviewProxyResource(manifest.devServerUrl, targetUrl, {
2207
+ method,
2208
+ headers: previewProxyRequestHeaders(req, manifest.devServerUrl, cookieHeader),
2209
+ body: requestBody,
2210
+ }, previewSessionCookies);
2211
+ const contentType = proxied.headers.get("content-type") ?? "";
2212
+ const documentNavigation = readHeader(req, "sec-fetch-dest") === "document";
2213
+ const responseBody = documentNavigation && contentType.includes("html")
2214
+ ? Buffer.from(injectLiveEditBridge(proxied.body.toString("utf8"), new URL("/", manifest.bridgeUrl).toString(), liveEditBridgeScript, (() => {
2215
+ const parsed = new URL(proxied.url);
2216
+ return `${parsed.pathname}${parsed.search}` || "/";
2217
+ })()))
2218
+ : proxied.body;
2219
+ sendBytes(res, proxied.status, method === "HEAD" ? Buffer.alloc(0) : responseBody, proxied.headers, responseBody.length, proxied.setCookieHeaders);
1838
2220
  }
1839
2221
  catch (err) {
1840
- sendJson(res, 400, {
2222
+ sendJson(res, err instanceof PreviewProxyRequestTooLargeError ? 413 : 400, {
1841
2223
  ok: false,
1842
2224
  error: err instanceof Error ? err.message : String(err),
1843
2225
  });
@@ -1847,6 +2229,81 @@ export async function startDesignConnectBridge(manifest, seedOrOptions) {
1847
2229
  }
1848
2230
  sendJson(res, 404, { ok: false, error: "not found" });
1849
2231
  });
2232
+ // Vite's proxied /@vite/client derives its HMR socket from the document's
2233
+ // bridge origin. Tunnel WebSocket upgrades to the one connected dev-server
2234
+ // origin so Fast Refresh remains live inside URL-backed screens. The target
2235
+ // is never caller-controlled, bridge credentials are stripped, and only a
2236
+ // same-origin iframe (or an explicit preview-token caller) can open it.
2237
+ server.on("upgrade", (req, clientSocket, clientHead) => {
2238
+ const requestUrl = new URL(req.url ?? "/", manifest.bridgeUrl);
2239
+ const providedPreviewToken = readHeader(req, "x-design-preview-token") ||
2240
+ requestUrl.searchParams.get("previewToken") ||
2241
+ readRequestCookie(req, PREVIEW_SESSION_COOKIE_NAME) ||
2242
+ "";
2243
+ const browserOrigin = readHeader(req, "origin");
2244
+ const sameBridgeOrigin = browserOrigin === new URL(manifest.bridgeUrl).origin;
2245
+ if (!constantTimeTokenMatches(providedPreviewToken, previewToken)) {
2246
+ clientSocket.end("HTTP/1.1 401 Unauthorized\r\nConnection: close\r\nContent-Length: 0\r\n\r\n");
2247
+ return;
2248
+ }
2249
+ requestUrl.searchParams.delete("previewToken");
2250
+ let targetUrl;
2251
+ try {
2252
+ targetUrl = new URL(resolvePreviewProxyUrl(manifest.devServerUrl, `${requestUrl.pathname}${requestUrl.search}`));
2253
+ }
2254
+ catch {
2255
+ clientSocket.end("HTTP/1.1 400 Bad Request\r\nConnection: close\r\nContent-Length: 0\r\n\r\n");
2256
+ return;
2257
+ }
2258
+ const upstreamHeaders = { ...req.headers };
2259
+ delete upstreamHeaders["x-bridge-token"];
2260
+ delete upstreamHeaders["x-design-preview-token"];
2261
+ delete upstreamHeaders["authorization"];
2262
+ delete upstreamHeaders["cookie"];
2263
+ upstreamHeaders.host = targetUrl.host;
2264
+ upstreamHeaders.origin = new URL(manifest.devServerUrl).origin;
2265
+ const cookie = mergePreviewCookieHeaders(previewSessionCookies.headerFor(targetUrl.toString()), sameBridgeOrigin ? readHeader(req, "cookie") : "");
2266
+ if (cookie)
2267
+ upstreamHeaders.cookie = cookie;
2268
+ const requestImpl = targetUrl.protocol === "https:" ? https : http;
2269
+ const upstreamRequest = requestImpl.request({
2270
+ protocol: targetUrl.protocol,
2271
+ hostname: targetUrl.hostname,
2272
+ port: targetUrl.port,
2273
+ path: `${targetUrl.pathname}${targetUrl.search}`,
2274
+ method: "GET",
2275
+ headers: upstreamHeaders,
2276
+ });
2277
+ upstreamRequest.on("upgrade", (upstreamResponse, upstreamSocket, upstreamHead) => {
2278
+ const statusLine = `HTTP/1.1 ${upstreamResponse.statusCode ?? 101} ${upstreamResponse.statusMessage || "Switching Protocols"}\r\n`;
2279
+ const headerLines = [];
2280
+ for (let index = 0; index < upstreamResponse.rawHeaders.length; index += 2) {
2281
+ const name = upstreamResponse.rawHeaders[index];
2282
+ const value = upstreamResponse.rawHeaders[index + 1];
2283
+ if (name && value !== undefined)
2284
+ headerLines.push(`${name}: ${value}`);
2285
+ }
2286
+ clientSocket.write(`${statusLine}${headerLines.join("\r\n")}\r\n\r\n`);
2287
+ if (clientHead.length > 0)
2288
+ upstreamSocket.write(clientHead);
2289
+ if (upstreamHead.length > 0)
2290
+ clientSocket.write(upstreamHead);
2291
+ clientSocket.once("close", () => upstreamSocket.destroy());
2292
+ upstreamSocket.once("close", () => clientSocket.destroy());
2293
+ upstreamSocket.pipe(clientSocket);
2294
+ clientSocket.pipe(upstreamSocket);
2295
+ });
2296
+ upstreamRequest.on("response", (upstreamResponse) => {
2297
+ clientSocket.end(`HTTP/1.1 ${upstreamResponse.statusCode ?? 502} ${upstreamResponse.statusMessage || "WebSocket upgrade failed"}\r\nConnection: close\r\nContent-Length: 0\r\n\r\n`);
2298
+ upstreamResponse.resume();
2299
+ });
2300
+ upstreamRequest.on("error", () => {
2301
+ if (!clientSocket.destroyed) {
2302
+ clientSocket.end("HTTP/1.1 502 Bad Gateway\r\nConnection: close\r\nContent-Length: 0\r\n\r\n");
2303
+ }
2304
+ });
2305
+ upstreamRequest.end();
2306
+ });
1850
2307
  await new Promise((resolve, reject) => {
1851
2308
  server.once("error", reject);
1852
2309
  server.listen(new URL(manifest.bridgeUrl).port, "127.0.0.1", () => {