@agent-native/core 0.92.6 → 0.92.8

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 (297) hide show
  1. package/corpus/README.md +1 -1
  2. package/corpus/core/CHANGELOG.md +18 -0
  3. package/corpus/core/docs/content/a2a-protocol.mdx +12 -0
  4. package/corpus/core/docs/content/locales/ar-SA/a2a-protocol.mdx +12 -0
  5. package/corpus/core/docs/content/locales/ar-SA/pr-visual-recap.mdx +3 -3
  6. package/corpus/core/docs/content/locales/ar-SA/pure-agent-apps.mdx +4 -0
  7. package/corpus/core/docs/content/locales/de-DE/a2a-protocol.mdx +12 -0
  8. package/corpus/core/docs/content/locales/de-DE/pr-visual-recap.mdx +3 -3
  9. package/corpus/core/docs/content/locales/de-DE/pure-agent-apps.mdx +4 -0
  10. package/corpus/core/docs/content/locales/es-ES/a2a-protocol.mdx +12 -0
  11. package/corpus/core/docs/content/locales/es-ES/pr-visual-recap.mdx +3 -3
  12. package/corpus/core/docs/content/locales/es-ES/pure-agent-apps.mdx +4 -0
  13. package/corpus/core/docs/content/locales/fr-FR/a2a-protocol.mdx +12 -0
  14. package/corpus/core/docs/content/locales/fr-FR/pr-visual-recap.mdx +3 -3
  15. package/corpus/core/docs/content/locales/fr-FR/pure-agent-apps.mdx +4 -0
  16. package/corpus/core/docs/content/locales/hi-IN/a2a-protocol.mdx +12 -0
  17. package/corpus/core/docs/content/locales/hi-IN/pr-visual-recap.mdx +3 -3
  18. package/corpus/core/docs/content/locales/hi-IN/pure-agent-apps.mdx +4 -0
  19. package/corpus/core/docs/content/locales/ja-JP/a2a-protocol.mdx +12 -0
  20. package/corpus/core/docs/content/locales/ja-JP/pr-visual-recap.mdx +3 -3
  21. package/corpus/core/docs/content/locales/ja-JP/pure-agent-apps.mdx +4 -0
  22. package/corpus/core/docs/content/locales/ko-KR/a2a-protocol.mdx +12 -0
  23. package/corpus/core/docs/content/locales/ko-KR/pr-visual-recap.mdx +3 -3
  24. package/corpus/core/docs/content/locales/ko-KR/pure-agent-apps.mdx +4 -0
  25. package/corpus/core/docs/content/locales/pt-BR/a2a-protocol.mdx +12 -0
  26. package/corpus/core/docs/content/locales/pt-BR/pr-visual-recap.mdx +3 -3
  27. package/corpus/core/docs/content/locales/pt-BR/pure-agent-apps.mdx +4 -0
  28. package/corpus/core/docs/content/locales/zh-CN/a2a-protocol.mdx +12 -0
  29. package/corpus/core/docs/content/locales/zh-CN/pr-visual-recap.mdx +3 -3
  30. package/corpus/core/docs/content/locales/zh-CN/pure-agent-apps.mdx +4 -0
  31. package/corpus/core/docs/content/locales/zh-TW/a2a-protocol.mdx +12 -0
  32. package/corpus/core/docs/content/locales/zh-TW/pr-visual-recap.mdx +3 -3
  33. package/corpus/core/docs/content/locales/zh-TW/pure-agent-apps.mdx +4 -0
  34. package/corpus/core/docs/content/pr-visual-recap.mdx +3 -3
  35. package/corpus/core/docs/content/pure-agent-apps.mdx +22 -0
  36. package/corpus/core/package.json +1 -1
  37. package/corpus/core/src/agent/engine/builtin.ts +1 -1
  38. package/corpus/core/src/agent/model-config.ts +30 -30
  39. package/corpus/core/src/agent/production-agent.ts +129 -7
  40. package/corpus/core/src/cli/design-connect.ts +438 -83
  41. package/corpus/core/src/cli/recap.ts +2 -2
  42. package/corpus/core/src/cli/sync-builder-starter-manifest.ts +1 -1
  43. package/corpus/core/src/client/AgentPanel.tsx +8 -1
  44. package/corpus/core/src/client/agent-chat-adapter.ts +12 -7
  45. package/corpus/core/src/client/composer/TiptapComposer.tsx +1 -1
  46. package/corpus/core/src/client/index.ts +4 -0
  47. package/corpus/core/src/client/org/TeamPage.tsx +41 -26
  48. package/corpus/core/src/client/use-action.ts +113 -1
  49. package/corpus/core/src/db/client.ts +12 -2
  50. package/corpus/core/src/db/create-get-db.ts +4 -1
  51. package/corpus/core/src/scripts/agent-engines/manage-agent-engine.ts +1 -1
  52. package/corpus/core/src/scripts/agent-engines/set-agent-engine.ts +1 -1
  53. package/corpus/core/src/server/transcribe-voice.ts +1 -1
  54. package/corpus/core/src/usage/store.ts +13 -4
  55. package/corpus/core/src/vite/client.ts +38 -1
  56. package/corpus/templates/analytics/AGENTS.md +3 -0
  57. package/corpus/templates/analytics/actions/get-data-program.ts +78 -0
  58. package/corpus/templates/analytics/actions/list-data-programs.ts +49 -0
  59. package/corpus/templates/analytics/app/global.css +11 -0
  60. package/corpus/templates/analytics/app/hooks/use-dashboard-chat-context.ts +163 -17
  61. package/corpus/templates/analytics/app/i18n/zh-TW.ts +2 -0
  62. package/corpus/templates/analytics/app/i18n-data.ts +20 -0
  63. package/corpus/templates/analytics/app/pages/adhoc/explorer-dashboard/ChartCard.tsx +96 -3
  64. package/corpus/templates/analytics/app/pages/adhoc/explorer-dashboard/index.tsx +3 -1
  65. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/SqlChartCard.tsx +61 -4
  66. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/index.tsx +40 -2
  67. package/corpus/templates/analytics/changelog/2026-07-09-analytics-no-longer-forgets-successful-data-queries-when-a-l.md +6 -0
  68. package/corpus/templates/analytics/changelog/2026-07-09-dashboard-charts-keep-consistent-spacing-when-they-stack-ver.md +6 -0
  69. package/corpus/templates/analytics/changelog/2026-07-09-dashboard-charts-tables-and-extensions-can-be-selected-and-d.md +6 -0
  70. package/corpus/templates/analytics/changelog/2026-07-09-long-running-analytics-requests-now-recover-automatically-wh.md +6 -0
  71. package/corpus/templates/analytics/server/db/index.ts +6 -0
  72. package/corpus/templates/clips/desktop/src/hooks/useMeetingTranscription.ts +1 -7
  73. package/corpus/templates/content/app/components/editor/DocumentProperties.tsx +102 -15
  74. package/corpus/templates/content/app/hooks/use-content-database.ts +52 -0
  75. package/corpus/templates/content/app/hooks/use-document-properties.ts +50 -6
  76. package/corpus/templates/content/app/i18n/zh-TW.ts +2 -0
  77. package/corpus/templates/content/app/i18n-data.ts +28 -0
  78. package/corpus/templates/content/changelog/2026-07-09-notion-conflict-warnings-no-longer-flash-during-normal-synce.md +6 -0
  79. package/corpus/templates/content/changelog/2026-07-09-property-menus-and-delete-confirmations-now-open-visibly-and.md +6 -0
  80. package/corpus/templates/content/server/lib/notion-sync.ts +130 -28
  81. package/corpus/templates/design/actions/add-breakpoint.ts +48 -68
  82. package/corpus/templates/design/actions/add-localhost-screens.ts +496 -61
  83. package/corpus/templates/design/actions/apply-component-prop-edit.ts +2 -18
  84. package/corpus/templates/design/actions/apply-design-token-edit.ts +51 -82
  85. package/corpus/templates/design/actions/apply-tweaks.ts +63 -41
  86. package/corpus/templates/design/actions/capture-design-state.ts +2 -2
  87. package/corpus/templates/design/actions/connect-localhost.ts +58 -12
  88. package/corpus/templates/design/actions/create-component.ts +2 -18
  89. package/corpus/templates/design/actions/create-design-branch.ts +38 -18
  90. package/corpus/templates/design/actions/create-fusion-app.ts +15 -11
  91. package/corpus/templates/design/actions/delete-file.ts +19 -34
  92. package/corpus/templates/design/actions/deploy-design-preview.ts +59 -27
  93. package/corpus/templates/design/actions/deploy-fusion-app.ts +22 -15
  94. package/corpus/templates/design/actions/export-pdf.ts +2 -1
  95. package/corpus/templates/design/actions/export-zip.ts +9 -3
  96. package/corpus/templates/design/actions/generate-design.ts +107 -70
  97. package/corpus/templates/design/actions/get-component-details.ts +2 -18
  98. package/corpus/templates/design/actions/get-design-branch-diff.ts +2 -3
  99. package/corpus/templates/design/actions/get-design-surface-index.ts +2 -18
  100. package/corpus/templates/design/actions/get-design.ts +2 -1
  101. package/corpus/templates/design/actions/grant-localhost-write-consent.ts +7 -1
  102. package/corpus/templates/design/actions/import-design-tokens.ts +114 -76
  103. package/corpus/templates/design/actions/index-components.ts +2 -18
  104. package/corpus/templates/design/actions/list-design-source-capabilities.ts +23 -28
  105. package/corpus/templates/design/actions/list-local-files.ts +9 -2
  106. package/corpus/templates/design/actions/migrate-board-objects-to-file.ts +82 -98
  107. package/corpus/templates/design/actions/open-component-source.ts +2 -18
  108. package/corpus/templates/design/actions/open-visual-edit.ts +19 -1
  109. package/corpus/templates/design/actions/present-design-variants.ts +70 -70
  110. package/corpus/templates/design/actions/preview-component-prop-edit.ts +4 -14
  111. package/corpus/templates/design/actions/read-local-file.ts +9 -2
  112. package/corpus/templates/design/actions/remove-breakpoint.ts +40 -61
  113. package/corpus/templates/design/actions/rename-screen.ts +425 -0
  114. package/corpus/templates/design/actions/request-localhost-write-consent.ts +12 -2
  115. package/corpus/templates/design/actions/revoke-localhost-write-consent.ts +9 -2
  116. package/corpus/templates/design/actions/sync-fusion-app.ts +56 -39
  117. package/corpus/templates/design/actions/update-design.ts +376 -61
  118. package/corpus/templates/design/actions/update-file.ts +455 -188
  119. package/corpus/templates/design/actions/write-local-file.ts +10 -2
  120. package/corpus/templates/design/app/components/design/DesignCanvas.tsx +685 -608
  121. package/corpus/templates/design/app/components/design/LayersPanel.tsx +43 -15
  122. package/corpus/templates/design/app/components/design/MultiScreenCanvas.tsx +576 -2015
  123. package/corpus/templates/design/app/components/design/bridge/editor-chrome.bridge.ts +62 -14
  124. package/corpus/templates/design/app/components/design/bridge/embedded-wheel.bridge.ts +263 -25
  125. package/corpus/templates/design/app/components/design/design-canvas/annotation-submit.ts +34 -0
  126. package/corpus/templates/design/app/components/design/design-canvas/coordinate-transforms.ts +40 -0
  127. package/corpus/templates/design/app/components/design/design-canvas/creation.ts +47 -0
  128. package/corpus/templates/design/app/components/design/design-canvas/element-payload.ts +27 -0
  129. package/corpus/templates/design/app/components/design/design-canvas/embedded-frame.ts +62 -0
  130. package/corpus/templates/design/app/components/design/design-canvas/external-preview.ts +137 -0
  131. package/corpus/templates/design/app/components/design/design-canvas/file-drop.ts +10 -0
  132. package/corpus/templates/design/app/components/design/design-canvas/hit-test.ts +23 -0
  133. package/corpus/templates/design/app/components/design/design-canvas/iframe-events.ts +23 -0
  134. package/corpus/templates/design/app/components/design/design-canvas/iframe-pan.ts +177 -0
  135. package/corpus/templates/design/app/components/design/design-canvas/motion-types.ts +7 -0
  136. package/corpus/templates/design/app/components/design/design-canvas/pending-text-edit.ts +62 -0
  137. package/corpus/templates/design/app/components/design/index.ts +2 -2
  138. package/corpus/templates/design/app/components/design/multi-screen/canvas-tools.ts +100 -0
  139. package/corpus/templates/design/app/components/design/multi-screen/coordinate-transforms.ts +81 -0
  140. package/corpus/templates/design/app/components/design/multi-screen/cross-screen-drop.ts +23 -13
  141. package/corpus/templates/design/app/components/design/multi-screen/culling.ts +238 -19
  142. package/corpus/templates/design/app/components/design/multi-screen/draft-primitives.ts +424 -0
  143. package/corpus/templates/design/app/components/design/multi-screen/frame-geometry.ts +341 -0
  144. package/corpus/templates/design/app/components/design/multi-screen/iframe-targeting.ts +52 -0
  145. package/corpus/templates/design/app/components/design/multi-screen/overview-layout.ts +62 -0
  146. package/corpus/templates/design/app/components/design/multi-screen/primitive-drop-target.ts +283 -0
  147. package/corpus/templates/design/app/components/design/multi-screen/screen-content-cache.ts +272 -0
  148. package/corpus/templates/design/app/components/design/multi-screen/types.ts +5 -1
  149. package/corpus/templates/design/app/components/design/multi-screen/wheel-gesture-state.ts +12 -0
  150. package/corpus/templates/design/app/components/visual-editor/DrawOverlay.tsx +325 -84
  151. package/corpus/templates/design/app/hooks/use-navigation-state.ts +15 -1
  152. package/corpus/templates/design/app/hooks/useDesignHotkeys.ts +119 -47
  153. package/corpus/templates/design/app/i18n/zh-TW.ts +9 -0
  154. package/corpus/templates/design/app/i18n-data.ts +223 -0
  155. package/corpus/templates/design/app/lib/design-save-outbox.ts +379 -0
  156. package/corpus/templates/design/app/lib/png-clipboard.ts +113 -0
  157. package/corpus/templates/design/app/pages/design-editor/canvas-primitives.ts +229 -0
  158. package/corpus/templates/design/app/pages/design-editor/code-layer-state.ts +918 -0
  159. package/corpus/templates/design/app/pages/design-editor/collab-sync.ts +43 -0
  160. package/corpus/templates/design/app/pages/design-editor/cross-screen-text-color.ts +336 -0
  161. package/corpus/templates/design/app/pages/design-editor/data-operations.ts +270 -0
  162. package/corpus/templates/design/app/pages/design-editor/dom-guards.ts +24 -0
  163. package/corpus/templates/design/app/pages/design-editor/dom-utils.ts +11 -0
  164. package/corpus/templates/design/app/pages/design-editor/editor-session.ts +20 -0
  165. package/corpus/templates/design/app/pages/design-editor/editor-state.ts +408 -0
  166. package/corpus/templates/design/app/pages/design-editor/export-capture.ts +115 -0
  167. package/corpus/templates/design/app/pages/design-editor/geometry-persistence.ts +93 -0
  168. package/corpus/templates/design/app/pages/design-editor/history.ts +169 -0
  169. package/corpus/templates/design/app/pages/design-editor/layout-operations.ts +185 -0
  170. package/corpus/templates/design/app/pages/design-editor/motion-state.ts +309 -0
  171. package/corpus/templates/design/app/pages/design-editor/overview-camera.ts +438 -0
  172. package/corpus/templates/design/app/pages/design-editor/pending-edits.ts +510 -0
  173. package/corpus/templates/design/app/pages/design-editor/portable-style.ts +115 -0
  174. package/corpus/templates/design/app/pages/design-editor/selection-state.ts +337 -0
  175. package/corpus/templates/design/app/pages/design-editor/style-utils.ts +5 -0
  176. package/corpus/templates/design/app/pages/design-editor/tool-state.ts +92 -0
  177. package/corpus/templates/design/app/pages/design-editor/tweak-save.ts +87 -0
  178. package/corpus/templates/design/app/pages/design-editor/types.ts +36 -0
  179. package/corpus/templates/design/app/routes/design.$id.tsx +11 -1
  180. package/corpus/templates/design/changelog/2026-07-09-design-edits-canvas-positions-tools-and-tab-context-now-pers.md +6 -0
  181. package/corpus/templates/design/changelog/2026-07-09-figma-style-shortcuts-drawing-annotations-and-cross-screen-d.md +6 -0
  182. package/corpus/templates/design/changelog/2026-07-09-hand-and-scale-tools-now-keep-their-active-toolbar-identity-.md +6 -0
  183. package/corpus/templates/design/changelog/2026-07-09-large-multi-screen-designs-now-stay-responsive-during-long-c.md +6 -0
  184. package/corpus/templates/design/changelog/2026-07-09-layer-drags-now-land-exactly-where-the-insertion-indicator-s.md +6 -0
  185. package/corpus/templates/design/server/db/index.ts +2 -52
  186. package/corpus/templates/design/server/db/schema.ts +16 -0
  187. package/corpus/templates/design/server/lib/design-data-access.ts +70 -0
  188. package/corpus/templates/design/server/lib/design-data-mutation.ts +249 -0
  189. package/corpus/templates/design/server/lib/fusion-screens.ts +89 -76
  190. package/corpus/templates/design/server/lib/import-design-files.ts +76 -35
  191. package/corpus/templates/design/server/lib/verify-write-grant.ts +7 -2
  192. package/corpus/templates/design/server/plugins/db.ts +19 -0
  193. package/corpus/templates/design/server/source-workspace.ts +12 -13
  194. package/corpus/templates/design/shared/resolve-tweaks.ts +15 -0
  195. package/corpus/templates/design/shared/screen-rename.ts +42 -0
  196. package/corpus/templates/design/shared/source-mode.ts +84 -4
  197. package/dist/agent/engine/builder-engine.d.ts +1 -1
  198. package/dist/agent/engine/builder-engine.d.ts.map +1 -1
  199. package/dist/agent/engine/builtin.js +1 -1
  200. package/dist/agent/engine/builtin.js.map +1 -1
  201. package/dist/agent/model-config.d.ts +9 -9
  202. package/dist/agent/model-config.d.ts.map +1 -1
  203. package/dist/agent/model-config.js +30 -30
  204. package/dist/agent/model-config.js.map +1 -1
  205. package/dist/agent/production-agent.d.ts +60 -1
  206. package/dist/agent/production-agent.d.ts.map +1 -1
  207. package/dist/agent/production-agent.js +106 -7
  208. package/dist/agent/production-agent.js.map +1 -1
  209. package/dist/cli/design-connect.d.ts +30 -1
  210. package/dist/cli/design-connect.d.ts.map +1 -1
  211. package/dist/cli/design-connect.js +359 -75
  212. package/dist/cli/design-connect.js.map +1 -1
  213. package/dist/cli/recap.js +2 -2
  214. package/dist/cli/recap.js.map +1 -1
  215. package/dist/cli/sync-builder-starter-manifest.js +1 -1
  216. package/dist/cli/sync-builder-starter-manifest.js.map +1 -1
  217. package/dist/client/AgentPanel.d.ts.map +1 -1
  218. package/dist/client/AgentPanel.js +6 -1
  219. package/dist/client/AgentPanel.js.map +1 -1
  220. package/dist/client/agent-chat-adapter.d.ts.map +1 -1
  221. package/dist/client/agent-chat-adapter.js +10 -5
  222. package/dist/client/agent-chat-adapter.js.map +1 -1
  223. package/dist/client/composer/TiptapComposer.js +1 -1
  224. package/dist/client/composer/TiptapComposer.js.map +1 -1
  225. package/dist/client/index.d.ts +1 -1
  226. package/dist/client/index.d.ts.map +1 -1
  227. package/dist/client/index.js +1 -1
  228. package/dist/client/index.js.map +1 -1
  229. package/dist/client/org/TeamPage.d.ts.map +1 -1
  230. package/dist/client/org/TeamPage.js +6 -5
  231. package/dist/client/org/TeamPage.js.map +1 -1
  232. package/dist/client/use-action.d.ts +32 -0
  233. package/dist/client/use-action.d.ts.map +1 -1
  234. package/dist/client/use-action.js +68 -1
  235. package/dist/client/use-action.js.map +1 -1
  236. package/dist/collab/awareness.d.ts +2 -2
  237. package/dist/collab/awareness.d.ts.map +1 -1
  238. package/dist/collab/routes.d.ts +1 -1
  239. package/dist/db/client.d.ts +3 -0
  240. package/dist/db/client.d.ts.map +1 -1
  241. package/dist/db/client.js +7 -2
  242. package/dist/db/client.js.map +1 -1
  243. package/dist/db/create-get-db.d.ts.map +1 -1
  244. package/dist/db/create-get-db.js +2 -2
  245. package/dist/db/create-get-db.js.map +1 -1
  246. package/dist/file-upload/actions/upload-image.d.ts +1 -1
  247. package/dist/notifications/routes.d.ts +1 -1
  248. package/dist/observability/routes.d.ts +5 -5
  249. package/dist/progress/routes.d.ts +1 -1
  250. package/dist/resources/handlers.d.ts +1 -1
  251. package/dist/scripts/agent-engines/manage-agent-engine.js +1 -1
  252. package/dist/scripts/agent-engines/manage-agent-engine.js.map +1 -1
  253. package/dist/scripts/agent-engines/set-agent-engine.js +1 -1
  254. package/dist/scripts/agent-engines/set-agent-engine.js.map +1 -1
  255. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  256. package/dist/server/transcribe-voice.js +1 -1
  257. package/dist/server/transcribe-voice.js.map +1 -1
  258. package/dist/usage/store.d.ts.map +1 -1
  259. package/dist/usage/store.js +13 -4
  260. package/dist/usage/store.js.map +1 -1
  261. package/dist/vite/client.d.ts.map +1 -1
  262. package/dist/vite/client.js +36 -1
  263. package/dist/vite/client.js.map +1 -1
  264. package/docs/content/a2a-protocol.mdx +12 -0
  265. package/docs/content/locales/ar-SA/a2a-protocol.mdx +12 -0
  266. package/docs/content/locales/ar-SA/pr-visual-recap.mdx +3 -3
  267. package/docs/content/locales/ar-SA/pure-agent-apps.mdx +4 -0
  268. package/docs/content/locales/de-DE/a2a-protocol.mdx +12 -0
  269. package/docs/content/locales/de-DE/pr-visual-recap.mdx +3 -3
  270. package/docs/content/locales/de-DE/pure-agent-apps.mdx +4 -0
  271. package/docs/content/locales/es-ES/a2a-protocol.mdx +12 -0
  272. package/docs/content/locales/es-ES/pr-visual-recap.mdx +3 -3
  273. package/docs/content/locales/es-ES/pure-agent-apps.mdx +4 -0
  274. package/docs/content/locales/fr-FR/a2a-protocol.mdx +12 -0
  275. package/docs/content/locales/fr-FR/pr-visual-recap.mdx +3 -3
  276. package/docs/content/locales/fr-FR/pure-agent-apps.mdx +4 -0
  277. package/docs/content/locales/hi-IN/a2a-protocol.mdx +12 -0
  278. package/docs/content/locales/hi-IN/pr-visual-recap.mdx +3 -3
  279. package/docs/content/locales/hi-IN/pure-agent-apps.mdx +4 -0
  280. package/docs/content/locales/ja-JP/a2a-protocol.mdx +12 -0
  281. package/docs/content/locales/ja-JP/pr-visual-recap.mdx +3 -3
  282. package/docs/content/locales/ja-JP/pure-agent-apps.mdx +4 -0
  283. package/docs/content/locales/ko-KR/a2a-protocol.mdx +12 -0
  284. package/docs/content/locales/ko-KR/pr-visual-recap.mdx +3 -3
  285. package/docs/content/locales/ko-KR/pure-agent-apps.mdx +4 -0
  286. package/docs/content/locales/pt-BR/a2a-protocol.mdx +12 -0
  287. package/docs/content/locales/pt-BR/pr-visual-recap.mdx +3 -3
  288. package/docs/content/locales/pt-BR/pure-agent-apps.mdx +4 -0
  289. package/docs/content/locales/zh-CN/a2a-protocol.mdx +12 -0
  290. package/docs/content/locales/zh-CN/pr-visual-recap.mdx +3 -3
  291. package/docs/content/locales/zh-CN/pure-agent-apps.mdx +4 -0
  292. package/docs/content/locales/zh-TW/a2a-protocol.mdx +12 -0
  293. package/docs/content/locales/zh-TW/pr-visual-recap.mdx +3 -3
  294. package/docs/content/locales/zh-TW/pure-agent-apps.mdx +4 -0
  295. package/docs/content/pr-visual-recap.mdx +3 -3
  296. package/docs/content/pure-agent-apps.mdx +22 -0
  297. package/package.json +2 -2
@@ -1,7 +1,8 @@
1
1
  import type { CSSProperties } from "react";
2
2
 
3
- import { SURFACE_PADDING } from "../MultiScreenCanvas";
4
3
  import type { PortableStyleSnapshot } from "../types";
4
+ import { screenLocalRectToBoardGeometry } from "./coordinate-transforms";
5
+ import { SURFACE_PADDING } from "./overview-layout";
5
6
  import type {
6
7
  CrossScreenDropAxis,
7
8
  CrossScreenDropGuide,
@@ -67,19 +68,14 @@ export function getCrossScreenDropGuideForHitTest(args: {
67
68
  if (!rect) return null;
68
69
  const placement = args.hit.placement ?? "inside";
69
70
  const axis = args.hit.axis ?? "y";
70
- const scaleX =
71
- args.targetGeometry.width / Math.max(1, args.targetMetadata.width);
72
- const scaleY =
73
- args.targetGeometry.height / Math.max(1, args.targetMetadata.height);
74
71
  return {
75
72
  placement,
76
73
  axis,
77
- boardRect: {
78
- x: args.targetGeometry.x + rect.left * scaleX,
79
- y: args.targetGeometry.y + rect.top * scaleY,
80
- width: Math.max(1, rect.width * scaleX),
81
- height: Math.max(1, rect.height * scaleY),
82
- },
74
+ boardRect: screenLocalRectToBoardGeometry(
75
+ rect,
76
+ args.targetGeometry,
77
+ args.targetMetadata,
78
+ ),
83
79
  };
84
80
  }
85
81
 
@@ -93,6 +89,7 @@ export function getCrossScreenDropGuideStyle(args: {
93
89
  const top = args.pan.y + (SURFACE_PADDING + boardRect.y) * args.scale;
94
90
  const width = Math.max(1, boardRect.width * args.scale);
95
91
  const height = Math.max(1, boardRect.height * args.scale);
92
+ const rotation = boardRect.rotation ?? 0;
96
93
 
97
94
  if (placement === "inside") {
98
95
  return {
@@ -105,30 +102,43 @@ export function getCrossScreenDropGuideStyle(args: {
105
102
  "color-mix(in srgb, var(--design-editor-accent-color) 14%, transparent)",
106
103
  borderRadius: 2,
107
104
  boxShadow: "none",
105
+ transform: rotation ? `rotate(${rotation}deg)` : undefined,
108
106
  };
109
107
  }
110
108
 
111
109
  if (axis === "x") {
112
110
  const x = placement === "before" ? left : left + width;
111
+ const lineLeft = x - 1;
113
112
  return {
114
- left: x - 1,
113
+ left: lineLeft,
115
114
  top,
116
115
  width: 2,
117
116
  height: Math.max(8, height),
118
117
  background: "var(--design-editor-accent-color)",
119
118
  borderRadius: 999,
120
119
  boxShadow: "0 0 0 1px var(--design-editor-accent-color)",
120
+ transform: rotation ? `rotate(${rotation}deg)` : undefined,
121
+ // Rotate the insertion line around the anchor rect's center, not its
122
+ // own center, so before/after edges stay attached to a rotated target.
123
+ transformOrigin: rotation
124
+ ? `${left + width / 2 - lineLeft}px ${height / 2}px`
125
+ : undefined,
121
126
  };
122
127
  }
123
128
 
124
129
  const y = placement === "before" ? top : top + height;
130
+ const lineTop = y - 1;
125
131
  return {
126
132
  left,
127
- top: y - 1,
133
+ top: lineTop,
128
134
  width: Math.max(8, width),
129
135
  height: 2,
130
136
  background: "var(--design-editor-accent-color)",
131
137
  borderRadius: 999,
132
138
  boxShadow: "0 0 0 1px var(--design-editor-accent-color)",
139
+ transform: rotation ? `rotate(${rotation}deg)` : undefined,
140
+ transformOrigin: rotation
141
+ ? `${width / 2}px ${top + height / 2 - lineTop}px`
142
+ : undefined,
133
143
  };
134
144
  }
@@ -1,6 +1,6 @@
1
1
  import { getRotatedFrameAABB } from "@shared/canvas-math";
2
2
 
3
- import { SURFACE_PADDING } from "../MultiScreenCanvas";
3
+ import { SURFACE_PADDING } from "./overview-layout";
4
4
  import type { FrameGeometry, Point } from "./types";
5
5
 
6
6
  // ── Overview viewport culling (PF22) ────────────────────────────────────────
@@ -20,12 +20,11 @@ import type { FrameGeometry, Point } from "./types";
20
20
  // screen (the debounced commit lags real cursor position by up to
21
21
  // ~120ms — see scheduleViewCommit) is already mounted by the time it's
22
22
  // reachable.
23
- // - Two tiers, see computeScreenCullTier: a screen that has never intersected
24
- // the overscanned viewport this session renders a lightweight placeholder;
25
- // once visible it mounts real content and never goes back to a placeholder
26
- // it only ever gets hidden (Tier B), never unmounted, since iframes lose
27
- // all internal state (scroll position, form input, Alpine/JS state) on
28
- // unmount.
23
+ // - A bounded live-context pool keeps nearby screens warm without retaining
24
+ // every browsing context ever visited. Active/selected/in-progress screens
25
+ // are protected; the remaining budget is filled by viewport distance and
26
+ // then by recency. Evicted screens keep their lightweight React content-cache
27
+ // entry so revisiting can remount directly without rebuilding source HTML.
29
28
 
30
29
  /** Escape hatch: flip to `false` to fully disable culling in one line if a
31
30
  * regression appears — every screen goes back to always rendering full
@@ -40,17 +39,236 @@ export const OVERVIEW_CULLING_ENABLED = true;
40
39
  * recomputes. */
41
40
  export const OVERVIEW_CULLING_OVERSCAN_FACTOR = 1.5;
42
41
 
42
+ /** Maximum number of evictable overview browsing contexts kept mounted at
43
+ * once. One screen costs its primary preview plus every breakpoint preview.
44
+ * Interaction-protected screens are the sole safety exception: if the user
45
+ * explicitly selects more than this budget, preserving their live editor
46
+ * state wins until that interaction ends, after which the pool contracts on
47
+ * the next culling pass. */
48
+ export const OVERVIEW_LIVE_IFRAME_BUDGET = 32;
49
+
43
50
  export type ScreenCullTier =
44
51
  /** Full content (iframe/DesignCanvas) is mounted and rendered normally. */
45
52
  | "visible"
46
53
  /** Has been visible before this session; content stays mounted (iframes
47
- * never unmount — see the module doc above) but is skipped from paint via
54
+ * remains inside the bounded warm pool) but is skipped from paint via
48
55
  * visibility/content-visibility, not display:none or will-change. */
49
56
  | "culled"
57
+ /** Has rendered before but was least-recently-used outside the bounded live
58
+ * iframe pool. Its browsing contexts are unmounted; the cached React node
59
+ * is retained so a revisit can remount without regenerating content. */
60
+ | "evicted"
50
61
  /** Has never been visible this session; renders a lightweight placeholder
51
62
  * with no iframe/content node at all. */
52
63
  | "placeholder";
53
64
 
65
+ /** Shared render lifecycle for every iframe belonging to one screen, including
66
+ * breakpoint previews. Warm offscreen screens remain mounted and hidden;
67
+ * never-seen and LRU-evicted screens own no browsing contexts. */
68
+ export function getScreenContentCullState(tier: ScreenCullTier): {
69
+ shouldMount: boolean;
70
+ isHidden: boolean;
71
+ } {
72
+ return {
73
+ shouldMount: tier === "visible" || tier === "culled",
74
+ isHidden: tier === "culled",
75
+ };
76
+ }
77
+
78
+ export interface ScreenCullCandidate {
79
+ id: string;
80
+ geometry: FrameGeometry;
81
+ /** Primary preview plus all breakpoint preview iframes for this screen. */
82
+ iframeCount: number;
83
+ }
84
+
85
+ export interface BoundedScreenCullState {
86
+ tierByScreenId: Map<string, ScreenCullTier>;
87
+ liveScreenIds: Set<string>;
88
+ everVisibleScreenIds: Set<string>;
89
+ lastVisibleEpochByScreenId: Map<string, number>;
90
+ mountedIframeCount: number;
91
+ }
92
+
93
+ function normalizedIframeCount(candidate: ScreenCullCandidate): number {
94
+ return Math.max(1, Math.floor(candidate.iframeCount));
95
+ }
96
+
97
+ function distanceSquaredToViewportCenter(
98
+ geometry: FrameGeometry,
99
+ viewport: OverscannedViewportBounds,
100
+ ): number {
101
+ const bounds = getRotatedFrameAABB(geometry);
102
+ const dx =
103
+ (bounds.left + bounds.right) / 2 - (viewport.left + viewport.right) / 2;
104
+ const dy =
105
+ (bounds.top + bounds.bottom) / 2 - (viewport.top + viewport.bottom) / 2;
106
+ return dx * dx + dy * dy;
107
+ }
108
+
109
+ /**
110
+ * Allocate overview browsing contexts under a bounded LRU/distance budget.
111
+ *
112
+ * Allocation order is intentional:
113
+ * 1. protected interactions (active, selected, dragged, text/layer edited),
114
+ * 2. screens inside the overscanned viewport, nearest the viewport center,
115
+ * 3. previously-mounted offscreen screens, most recently visible first.
116
+ *
117
+ * This keeps imminent pan/zoom destinations live while guaranteeing that a
118
+ * long tour through a 100+ screen board cannot accumulate 100+ hidden iframe
119
+ * documents. The function is pure: callers own the returned Set/Map snapshots
120
+ * and can feed them into the next committed pan/zoom pass.
121
+ */
122
+ export function computeBoundedScreenCullState({
123
+ candidates,
124
+ viewport,
125
+ protectedScreenIds,
126
+ previousLiveScreenIds,
127
+ everVisibleScreenIds,
128
+ lastVisibleEpochByScreenId,
129
+ accessEpoch,
130
+ liveIframeBudget = OVERVIEW_LIVE_IFRAME_BUDGET,
131
+ }: {
132
+ candidates: readonly ScreenCullCandidate[];
133
+ viewport: OverscannedViewportBounds | null;
134
+ protectedScreenIds: ReadonlySet<string>;
135
+ previousLiveScreenIds: ReadonlySet<string>;
136
+ everVisibleScreenIds: ReadonlySet<string>;
137
+ lastVisibleEpochByScreenId: ReadonlyMap<string, number>;
138
+ accessEpoch: number;
139
+ liveIframeBudget?: number;
140
+ }): BoundedScreenCullState {
141
+ if (!OVERVIEW_CULLING_ENABLED) {
142
+ const allIds = new Set(candidates.map((candidate) => candidate.id));
143
+ return {
144
+ tierByScreenId: new Map(
145
+ candidates.map((candidate) => [candidate.id, "visible"] as const),
146
+ ),
147
+ liveScreenIds: allIds,
148
+ everVisibleScreenIds: allIds,
149
+ lastVisibleEpochByScreenId: new Map(
150
+ candidates.map((candidate) => [candidate.id, accessEpoch] as const),
151
+ ),
152
+ mountedIframeCount: candidates.reduce(
153
+ (total, candidate) => total + normalizedIframeCount(candidate),
154
+ 0,
155
+ ),
156
+ };
157
+ }
158
+
159
+ const candidateById = new Map(
160
+ candidates.map((candidate) => [candidate.id, candidate] as const),
161
+ );
162
+ const viewportScreenIds = new Set<string>();
163
+ if (viewport) {
164
+ for (const candidate of candidates) {
165
+ if (isFrameWithinOverscannedViewport(candidate.geometry, viewport)) {
166
+ viewportScreenIds.add(candidate.id);
167
+ }
168
+ }
169
+ }
170
+
171
+ const nextLastVisible = new Map(lastVisibleEpochByScreenId);
172
+ for (const id of protectedScreenIds) {
173
+ if (candidateById.has(id)) nextLastVisible.set(id, accessEpoch);
174
+ }
175
+ for (const id of viewportScreenIds) nextLastVisible.set(id, accessEpoch);
176
+
177
+ const nextLive = new Set<string>();
178
+ let mountedIframeCount = 0;
179
+ const add = (candidate: ScreenCullCandidate) => {
180
+ if (nextLive.has(candidate.id)) return;
181
+ nextLive.add(candidate.id);
182
+ mountedIframeCount += normalizedIframeCount(candidate);
183
+ };
184
+
185
+ // Protected editor interactions must never be destroyed mid-gesture/edit.
186
+ for (const candidate of candidates) {
187
+ if (protectedScreenIds.has(candidate.id)) add(candidate);
188
+ }
189
+ // Protected screens can temporarily exceed the normal pool. In that case
190
+ // no evictable iframe is admitted until the interaction set shrinks again.
191
+ const effectiveBudget = Math.max(
192
+ Math.max(0, Math.floor(liveIframeBudget)),
193
+ mountedIframeCount,
194
+ );
195
+ const tryAddWithinBudget = (candidate: ScreenCullCandidate) => {
196
+ if (nextLive.has(candidate.id)) return;
197
+ if (
198
+ mountedIframeCount + normalizedIframeCount(candidate) <=
199
+ effectiveBudget
200
+ ) {
201
+ add(candidate);
202
+ }
203
+ };
204
+
205
+ const visibleCandidates = candidates
206
+ .filter(
207
+ (candidate) =>
208
+ viewportScreenIds.has(candidate.id) &&
209
+ !protectedScreenIds.has(candidate.id),
210
+ )
211
+ .sort((a, b) => {
212
+ if (!viewport) return a.id.localeCompare(b.id);
213
+ const distanceDelta =
214
+ distanceSquaredToViewportCenter(a.geometry, viewport) -
215
+ distanceSquaredToViewportCenter(b.geometry, viewport);
216
+ if (distanceDelta !== 0) return distanceDelta;
217
+ const recencyDelta =
218
+ (nextLastVisible.get(b.id) ?? -1) - (nextLastVisible.get(a.id) ?? -1);
219
+ return recencyDelta || a.id.localeCompare(b.id);
220
+ });
221
+ visibleCandidates.forEach(tryAddWithinBudget);
222
+
223
+ const warmCandidates = candidates
224
+ .filter(
225
+ (candidate) =>
226
+ previousLiveScreenIds.has(candidate.id) &&
227
+ !viewportScreenIds.has(candidate.id) &&
228
+ !protectedScreenIds.has(candidate.id),
229
+ )
230
+ .sort((a, b) => {
231
+ const recencyDelta =
232
+ (nextLastVisible.get(b.id) ?? -1) - (nextLastVisible.get(a.id) ?? -1);
233
+ return recencyDelta || a.id.localeCompare(b.id);
234
+ });
235
+ warmCandidates.forEach(tryAddWithinBudget);
236
+
237
+ const nextEverVisible = new Set(everVisibleScreenIds);
238
+ const tierByScreenId = new Map<string, ScreenCullTier>();
239
+ for (const candidate of candidates) {
240
+ const isProtected = protectedScreenIds.has(candidate.id);
241
+ const isInViewport = viewportScreenIds.has(candidate.id);
242
+ const isLive = nextLive.has(candidate.id);
243
+ if (isLive && (isProtected || isInViewport)) {
244
+ nextEverVisible.add(candidate.id);
245
+ tierByScreenId.set(candidate.id, "visible");
246
+ } else if (isLive) {
247
+ tierByScreenId.set(candidate.id, "culled");
248
+ } else if (nextEverVisible.has(candidate.id)) {
249
+ tierByScreenId.set(candidate.id, "evicted");
250
+ } else {
251
+ tierByScreenId.set(candidate.id, "placeholder");
252
+ }
253
+ }
254
+
255
+ const liveIds = new Set(candidateById.keys());
256
+ for (const id of nextEverVisible) {
257
+ if (!liveIds.has(id)) nextEverVisible.delete(id);
258
+ }
259
+ for (const id of nextLastVisible.keys()) {
260
+ if (!liveIds.has(id)) nextLastVisible.delete(id);
261
+ }
262
+
263
+ return {
264
+ tierByScreenId,
265
+ liveScreenIds: nextLive,
266
+ everVisibleScreenIds: nextEverVisible,
267
+ lastVisibleEpochByScreenId: nextLastVisible,
268
+ mountedIframeCount,
269
+ };
270
+ }
271
+
54
272
  /** The world-space (canvas-space) rectangle currently visible inside the
55
273
  * pannable surface, expanded by `overscanFactor` viewport-widths/heights in
56
274
  * every direction. Built from the *committed* pan/zoom state, matching the
@@ -72,8 +290,9 @@ export interface OverscannedViewportBounds {
72
290
  * `SURFACE_PADDING`-relative space — compare directly against
73
291
  * `geometry.x`/`geometry.y`-based frame bounds, no further offset needed.
74
292
  * Returns `null` when the surface has no measured size yet (e.g. before the
75
- * first layout pass) callers should treat that as "cannot determine
76
- * visibility yet" and fall back to treating everything as visible. */
293
+ * first layout pass). Callers keep only active/selected or previously-live
294
+ * screens mounted until measurement; otherwise a cold open would eagerly
295
+ * instantiate every iframe and permanently defeat placeholder culling. */
77
296
  export function getOverscannedViewportCanvasBounds(
78
297
  surfaceSize: { width: number; height: number },
79
298
  pan: Point,
@@ -158,12 +377,13 @@ export function clampFrameGeometryToViewport(
158
377
  * itself never culls the object you're actively editing or have selected,
159
378
  * and keeping these paths iframe-backed avoids any risk of interrupting
160
379
  * in-progress edits/bridge state on the screen the user is looking at.
161
- * `viewport` is `null` when surface size isn't known yet (initial layout)
162
- * treated as visible so nothing is incorrectly culled before we can measure.
380
+ * `viewport` is `null` when surface size isn't known yet (initial layout).
381
+ * Active/selected screens stay visible, previously-live screens stay mounted
382
+ * but culled, and never-seen screens remain placeholders until measurement.
163
383
  * `hasBeenVisible` should reflect whether this screen id has *ever* been
164
- * visible this session (see the hasBeenVisibleRef Set in MultiScreenCanvas):
165
- * once true, a screen can only be "visible" or "culled", never regress to
166
- * "placeholder". */
384
+ * visible this session (see the hasBeenVisibleRef Set in MultiScreenCanvas).
385
+ * This low-level geometry helper does not apply the live-iframe budget;
386
+ * computeBoundedScreenCullState layers the separate "evicted" tier on top. */
167
387
  export function computeScreenCullTier({
168
388
  geometry,
169
389
  viewport,
@@ -176,10 +396,9 @@ export function computeScreenCullTier({
176
396
  hasBeenVisible: boolean;
177
397
  }): ScreenCullTier {
178
398
  if (!OVERVIEW_CULLING_ENABLED) return "visible";
179
- const isWithinViewport =
180
- alwaysVisible ||
181
- !viewport ||
182
- isFrameWithinOverscannedViewport(geometry, viewport);
399
+ if (alwaysVisible) return "visible";
400
+ if (!viewport) return hasBeenVisible ? "culled" : "placeholder";
401
+ const isWithinViewport = isFrameWithinOverscannedViewport(geometry, viewport);
183
402
  if (isWithinViewport) return "visible";
184
403
  return hasBeenVisible ? "culled" : "placeholder";
185
404
  }