@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
@@ -0,0 +1,425 @@
1
+ import { defineAction } from "@agent-native/core";
2
+ import {
3
+ applyText,
4
+ hasCollabState,
5
+ seedFromText,
6
+ } from "@agent-native/core/collab";
7
+ import { isPostgres } from "@agent-native/core/db";
8
+ import { accessFilter, assertAccess } from "@agent-native/core/sharing";
9
+ import { and, eq, isNull, sql } from "drizzle-orm";
10
+ import { z } from "zod";
11
+
12
+ import { getDb, schema } from "../server/db/index.js";
13
+ import { isProbablyHtmlDocumentContent } from "../shared/html-content.js";
14
+ import {
15
+ renameFilenamePreservingExtension,
16
+ replaceDataScreenReferences,
17
+ } from "../shared/screen-rename.js";
18
+ import { sourceContentHash } from "../shared/source-workspace.js";
19
+
20
+ const MAX_RENAME_ATTEMPTS = 5;
21
+ const MAX_CONTENT_OVERRIDE_BYTES = 2_000_000;
22
+ const MAX_TOTAL_CONTENT_OVERRIDE_BYTES = 4_000_000;
23
+ const renameLocks = new Map<string, Promise<unknown>>();
24
+
25
+ class ScreenRenameConflictError extends Error {
26
+ constructor(message = "Screen content changed during rename. Please retry.") {
27
+ super(message);
28
+ this.name = "ScreenRenameConflictError";
29
+ }
30
+ }
31
+
32
+ function withScreenRenameLock<T>(
33
+ designId: string,
34
+ callback: () => Promise<T>,
35
+ ): Promise<T> {
36
+ const previous = renameLocks.get(designId) ?? Promise.resolve();
37
+ const next = previous.then(callback, callback);
38
+ renameLocks.set(designId, next);
39
+ const cleanup = () => {
40
+ if (renameLocks.get(designId) === next) renameLocks.delete(designId);
41
+ };
42
+ next.then(cleanup, cleanup);
43
+ return next;
44
+ }
45
+
46
+ function nextUpdatedAt(current: string | null, now: Date): string {
47
+ const currentMs = current ? Date.parse(current) : Number.NaN;
48
+ const nextMs = Number.isFinite(currentMs)
49
+ ? Math.max(now.getTime(), currentMs + 1)
50
+ : now.getTime();
51
+ return new Date(nextMs).toISOString();
52
+ }
53
+
54
+ function isRetryableTransactionConflict(error: unknown): boolean {
55
+ if (error instanceof ScreenRenameConflictError) return true;
56
+ const rawCode =
57
+ error && typeof error === "object" && "code" in error
58
+ ? (error as { code?: unknown }).code
59
+ : undefined;
60
+ const code =
61
+ typeof rawCode === "string" || typeof rawCode === "number"
62
+ ? String(rawCode)
63
+ : "";
64
+ return (
65
+ code === "SQLITE_BUSY" ||
66
+ code === "SQLITE_LOCKED" ||
67
+ code === "40001" ||
68
+ code === "40P01"
69
+ );
70
+ }
71
+
72
+ function assertValidFilename(filename: string): void {
73
+ let containsControlCharacter = false;
74
+ for (let index = 0; index < filename.length; index += 1) {
75
+ const codeUnit = filename.charCodeAt(index);
76
+ if (codeUnit <= 0x1f || codeUnit === 0x7f) {
77
+ containsControlCharacter = true;
78
+ break;
79
+ }
80
+ }
81
+ if (
82
+ !filename ||
83
+ filename.length > 255 ||
84
+ filename === "." ||
85
+ filename === ".." ||
86
+ filename.includes("..") ||
87
+ filename.includes("/") ||
88
+ filename.includes("\\") ||
89
+ containsControlCharacter
90
+ ) {
91
+ throw new Error("Invalid filename: use a plain name without path segments");
92
+ }
93
+ }
94
+
95
+ const contentOverrideSchema = z.object({
96
+ fileId: z.string().min(1).max(256),
97
+ content: z.string().max(MAX_CONTENT_OVERRIDE_BYTES),
98
+ expectedVersionHash: z.string().min(1).max(256),
99
+ });
100
+
101
+ type RenamedFileResult = {
102
+ id: string;
103
+ filename: string;
104
+ content: string;
105
+ updatedAt: string;
106
+ contentChanged: boolean;
107
+ referenceRewritten: boolean;
108
+ };
109
+
110
+ export default defineAction({
111
+ description:
112
+ "Atomically rename one Design screen and rewrite exact data-screen links in every HTML screen.",
113
+ agentTool: false,
114
+ schema: z
115
+ .object({
116
+ id: z.string().min(1).max(256).describe("design_files.id to rename"),
117
+ name: z
118
+ .string()
119
+ .max(255)
120
+ .describe(
121
+ "New screen display name; the existing extension is preserved",
122
+ ),
123
+ requestSource: z
124
+ .string()
125
+ .min(1)
126
+ .max(256)
127
+ .optional()
128
+ .describe(
129
+ "Stable browser tab id used for collaboration echo suppression",
130
+ ),
131
+ contentOverrides: z
132
+ .array(contentOverrideSchema)
133
+ .max(100)
134
+ .optional()
135
+ .default([])
136
+ .describe(
137
+ "Fresh unsaved HTML snapshots from this client, guarded by their persisted base hashes.",
138
+ ),
139
+ })
140
+ .superRefine((value, ctx) => {
141
+ const encoder = new TextEncoder();
142
+ const totalBytes = value.contentOverrides.reduce(
143
+ (sum, override) => sum + encoder.encode(override.content).byteLength,
144
+ 0,
145
+ );
146
+ if (totalBytes > MAX_TOTAL_CONTENT_OVERRIDE_BYTES) {
147
+ ctx.addIssue({
148
+ code: "custom",
149
+ message: "Screen rename content overrides exceed the 4 MB limit.",
150
+ path: ["contentOverrides"],
151
+ });
152
+ }
153
+ }),
154
+ run: async ({ id, name, requestSource, contentOverrides }) => {
155
+ const db = getDb();
156
+
157
+ const [scopedFile] = await db
158
+ .select({
159
+ id: schema.designFiles.id,
160
+ designId: schema.designFiles.designId,
161
+ })
162
+ .from(schema.designFiles)
163
+ .innerJoin(
164
+ schema.designs,
165
+ eq(schema.designFiles.designId, schema.designs.id),
166
+ )
167
+ .where(
168
+ and(
169
+ eq(schema.designFiles.id, id),
170
+ accessFilter(schema.designs, schema.designShares),
171
+ ),
172
+ )
173
+ .limit(1);
174
+ if (!scopedFile) throw new Error(`Screen not found: ${id}`);
175
+
176
+ await assertAccess("design", scopedFile.designId, "editor");
177
+
178
+ const overrideIds = new Set<string>();
179
+ for (const override of contentOverrides) {
180
+ if (overrideIds.has(override.fileId)) {
181
+ throw new Error(`Duplicate content override: ${override.fileId}`);
182
+ }
183
+ overrideIds.add(override.fileId);
184
+ }
185
+
186
+ const result = await withScreenRenameLock(scopedFile.designId, async () => {
187
+ for (let attempt = 0; attempt < MAX_RENAME_ATTEMPTS; attempt += 1) {
188
+ try {
189
+ return await db.transaction(async (tx) => {
190
+ if (isPostgres()) {
191
+ await (
192
+ tx as unknown as {
193
+ execute: (query: unknown) => Promise<unknown>;
194
+ }
195
+ ).execute(
196
+ sql`LOCK TABLE design_files IN SHARE ROW EXCLUSIVE MODE`,
197
+ );
198
+ }
199
+
200
+ const [design] = await tx
201
+ .select({ updatedAt: schema.designs.updatedAt })
202
+ .from(schema.designs)
203
+ .where(eq(schema.designs.id, scopedFile.designId))
204
+ .limit(1);
205
+ if (!design) {
206
+ throw new Error(`Design not found: ${scopedFile.designId}`);
207
+ }
208
+
209
+ const currentFiles = await tx
210
+ .select({
211
+ id: schema.designFiles.id,
212
+ designId: schema.designFiles.designId,
213
+ filename: schema.designFiles.filename,
214
+ content: schema.designFiles.content,
215
+ fileType: schema.designFiles.fileType,
216
+ updatedAt: schema.designFiles.updatedAt,
217
+ })
218
+ .from(schema.designFiles)
219
+ .where(eq(schema.designFiles.designId, scopedFile.designId));
220
+ const target = currentFiles.find((file) => file.id === id);
221
+ if (!target) throw new Error(`Screen not found: ${id}`);
222
+ if (target.fileType !== "html") {
223
+ throw new Error(`File is not a renameable HTML screen: ${id}`);
224
+ }
225
+
226
+ const nextFilename = renameFilenamePreservingExtension(
227
+ target.filename,
228
+ name,
229
+ );
230
+ assertValidFilename(nextFilename);
231
+ const collision = currentFiles.find(
232
+ (file) => file.id !== id && file.filename === nextFilename,
233
+ );
234
+ if (collision) {
235
+ throw new Error(
236
+ `File "${nextFilename}" already exists in design ${scopedFile.designId}`,
237
+ );
238
+ }
239
+
240
+ const fileById = new Map(
241
+ currentFiles.map((file) => [file.id, file]),
242
+ );
243
+ const overrides = new Map(
244
+ contentOverrides.map((override) => [override.fileId, override]),
245
+ );
246
+ for (const override of contentOverrides) {
247
+ const file = fileById.get(override.fileId);
248
+ if (!file) {
249
+ throw new Error(
250
+ `Content override does not belong to this design: ${override.fileId}`,
251
+ );
252
+ }
253
+ if (file.fileType !== "html") {
254
+ throw new Error(
255
+ `Content overrides are only supported for HTML screens: ${override.fileId}`,
256
+ );
257
+ }
258
+ if (
259
+ file.content !== override.content &&
260
+ !isProbablyHtmlDocumentContent(file.content)
261
+ ) {
262
+ throw new Error(
263
+ `URL-backed screen "${file.filename}" cannot be replaced with inline HTML during rename.`,
264
+ );
265
+ }
266
+ const persistedHash = sourceContentHash(file.content);
267
+ if (
268
+ file.content !== override.content &&
269
+ persistedHash !== override.expectedVersionHash
270
+ ) {
271
+ throw new Error(
272
+ `Screen "${file.filename}" changed before the rename. Refresh and retry.`,
273
+ );
274
+ }
275
+ }
276
+
277
+ const now = new Date();
278
+ const updatedFiles: RenamedFileResult[] = [];
279
+ const orderedFiles = [
280
+ target,
281
+ ...currentFiles.filter((file) => file.id !== target.id),
282
+ ];
283
+ for (const file of orderedFiles) {
284
+ const override = overrides.get(file.id);
285
+ const baseContent = override?.content ?? file.content;
286
+ const nextContent =
287
+ file.fileType === "html"
288
+ ? replaceDataScreenReferences(
289
+ baseContent,
290
+ target.filename,
291
+ nextFilename,
292
+ )
293
+ : baseContent;
294
+ const contentChanged = nextContent !== file.content;
295
+ const referenceRewritten = nextContent !== baseContent;
296
+ const filenameChanged =
297
+ file.id === id && nextFilename !== file.filename;
298
+ if (!contentChanged && !filenameChanged) continue;
299
+
300
+ const updatedAt = nextUpdatedAt(file.updatedAt, now);
301
+ const updates: Record<string, unknown> = { updatedAt };
302
+ if (filenameChanged) updates.filename = nextFilename;
303
+ if (contentChanged) {
304
+ updates.content = nextContent;
305
+ // This atomic server write starts a new content lineage. A
306
+ // late browser save may not use pre-rename revision metadata
307
+ // as proof that no intervening writer changed the document.
308
+ updates.contentOperationSource = null;
309
+ updates.contentOperationRevision = null;
310
+ updates.contentOperationResultHash = null;
311
+ }
312
+
313
+ await tx
314
+ .update(schema.designFiles)
315
+ .set(updates)
316
+ .where(
317
+ and(
318
+ eq(schema.designFiles.id, file.id),
319
+ eq(schema.designFiles.designId, scopedFile.designId),
320
+ eq(schema.designFiles.filename, file.filename),
321
+ eq(schema.designFiles.content, file.content),
322
+ file.updatedAt === null
323
+ ? isNull(schema.designFiles.updatedAt)
324
+ : eq(schema.designFiles.updatedAt, file.updatedAt),
325
+ ),
326
+ );
327
+
328
+ const [confirmed] = await tx
329
+ .select({
330
+ filename: schema.designFiles.filename,
331
+ content: schema.designFiles.content,
332
+ updatedAt: schema.designFiles.updatedAt,
333
+ })
334
+ .from(schema.designFiles)
335
+ .where(eq(schema.designFiles.id, file.id))
336
+ .limit(1);
337
+ if (
338
+ !confirmed ||
339
+ confirmed.filename !==
340
+ (filenameChanged ? nextFilename : file.filename) ||
341
+ confirmed.content !== nextContent ||
342
+ confirmed.updatedAt !== updatedAt
343
+ ) {
344
+ throw new ScreenRenameConflictError();
345
+ }
346
+
347
+ updatedFiles.push({
348
+ id: file.id,
349
+ filename: filenameChanged ? nextFilename : file.filename,
350
+ content: nextContent,
351
+ updatedAt,
352
+ contentChanged,
353
+ referenceRewritten,
354
+ });
355
+ }
356
+
357
+ const designUpdatedAt = nextUpdatedAt(design.updatedAt, now);
358
+ await tx
359
+ .update(schema.designs)
360
+ .set({ updatedAt: designUpdatedAt })
361
+ .where(eq(schema.designs.id, scopedFile.designId));
362
+
363
+ return {
364
+ id,
365
+ designId: scopedFile.designId,
366
+ previousFilename: target.filename,
367
+ filename: nextFilename,
368
+ renamed: nextFilename !== target.filename,
369
+ updatedAt: designUpdatedAt,
370
+ files: updatedFiles,
371
+ rewrittenFileIds: updatedFiles
372
+ .filter((file) => file.referenceRewritten)
373
+ .map((file) => file.id),
374
+ };
375
+ });
376
+ } catch (error) {
377
+ if (
378
+ !isRetryableTransactionConflict(error) ||
379
+ attempt === MAX_RENAME_ATTEMPTS - 1
380
+ ) {
381
+ throw error;
382
+ }
383
+ }
384
+ }
385
+ throw new ScreenRenameConflictError(
386
+ "Screen content kept changing during rename. Please retry.",
387
+ );
388
+ });
389
+
390
+ // SQL is the atomic durable source of truth. Reconcile the same committed
391
+ // snapshots through the existing diff-based Yjs primitive after commit so
392
+ // open peers update without replacing their document or undoing unrelated
393
+ // CRDT operations. If that transport is unavailable, the file/design
394
+ // updatedAt bump and normal get-design invalidation remain the durable
395
+ // reconciliation fallback; never report the committed transaction as a
396
+ // rollback after it has succeeded.
397
+ const collabReconcilePending: string[] = [];
398
+ await Promise.all(
399
+ result.files
400
+ .filter((file) => file.contentChanged)
401
+ .map(async (file) => {
402
+ try {
403
+ if (await hasCollabState(file.id)) {
404
+ await applyText(
405
+ file.id,
406
+ file.content,
407
+ "content",
408
+ requestSource ?? "server",
409
+ );
410
+ } else {
411
+ await seedFromText(file.id, file.content);
412
+ }
413
+ } catch (error) {
414
+ collabReconcilePending.push(file.id);
415
+ console.warn(
416
+ `[design] screen rename committed but collab reconcile is pending for ${file.id}:`,
417
+ error,
418
+ );
419
+ }
420
+ }),
421
+ );
422
+
423
+ return { ...result, collabReconcilePending };
424
+ },
425
+ });
@@ -3,9 +3,12 @@ import {
3
3
  readAppStateForCurrentTab,
4
4
  writeAppState,
5
5
  } from "@agent-native/core/application-state";
6
- import { getRequestUserEmail } from "@agent-native/core/server/request-context";
6
+ import {
7
+ getRequestOrgId,
8
+ getRequestUserEmail,
9
+ } from "@agent-native/core/server/request-context";
7
10
  import { assertAccess } from "@agent-native/core/sharing";
8
- import { and, eq } from "drizzle-orm";
11
+ import { and, eq, isNull } from "drizzle-orm";
9
12
  import { z } from "zod";
10
13
 
11
14
  import { getDb, schema } from "../server/db/index.js";
@@ -40,6 +43,7 @@ export default defineAction({
40
43
 
41
44
  const ownerEmail = getRequestUserEmail();
42
45
  if (!ownerEmail) throw new Error("no authenticated user");
46
+ const orgId = getRequestOrgId() ?? null;
43
47
 
44
48
  const db = getDb();
45
49
  const [connection] = await db
@@ -52,6 +56,9 @@ export default defineAction({
52
56
  and(
53
57
  eq(schema.designLocalhostConnections.id, connectionId),
54
58
  eq(schema.designLocalhostConnections.ownerEmail, ownerEmail),
59
+ orgId
60
+ ? eq(schema.designLocalhostConnections.orgId, orgId)
61
+ : isNull(schema.designLocalhostConnections.orgId),
55
62
  ),
56
63
  )
57
64
  .limit(1);
@@ -85,6 +92,9 @@ export default defineAction({
85
92
  eq(schema.designLocalhostWriteGrants.designId, designId),
86
93
  eq(schema.designLocalhostWriteGrants.connectionId, connectionId),
87
94
  eq(schema.designLocalhostWriteGrants.ownerEmail, ownerEmail),
95
+ orgId
96
+ ? eq(schema.designLocalhostWriteGrants.orgId, orgId)
97
+ : isNull(schema.designLocalhostWriteGrants.orgId),
88
98
  ),
89
99
  )
90
100
  .limit(1);
@@ -1,7 +1,10 @@
1
1
  import { defineAction } from "@agent-native/core";
2
- import { getRequestUserEmail } from "@agent-native/core/server/request-context";
2
+ import {
3
+ getRequestOrgId,
4
+ getRequestUserEmail,
5
+ } from "@agent-native/core/server/request-context";
3
6
  import { assertAccess } from "@agent-native/core/sharing";
4
- import { and, eq } from "drizzle-orm";
7
+ import { and, eq, isNull } from "drizzle-orm";
5
8
  import { z } from "zod";
6
9
 
7
10
  import { getDb, schema } from "../server/db/index.js";
@@ -22,6 +25,7 @@ export default defineAction({
22
25
 
23
26
  const ownerEmail = getRequestUserEmail();
24
27
  if (!ownerEmail) throw new Error("no authenticated user");
28
+ const orgId = getRequestOrgId() ?? null;
25
29
 
26
30
  const db = getDb();
27
31
 
@@ -33,6 +37,9 @@ export default defineAction({
33
37
  eq(schema.designLocalhostWriteGrants.designId, designId),
34
38
  eq(schema.designLocalhostWriteGrants.connectionId, connectionId),
35
39
  eq(schema.designLocalhostWriteGrants.ownerEmail, ownerEmail),
40
+ orgId
41
+ ? eq(schema.designLocalhostWriteGrants.orgId, orgId)
42
+ : isNull(schema.designLocalhostWriteGrants.orgId),
36
43
  );
37
44
 
38
45
  const [grant] = await db
@@ -17,6 +17,7 @@ import { z } from "zod";
17
17
 
18
18
  import { getDb, schema } from "../server/db/index.js";
19
19
  import "../server/db/index.js"; // ensure registerShareableResource runs
20
+ import { mutateDesignData } from "../server/lib/design-data-mutation.js";
20
21
  import {
21
22
  DEFAULT_FUSION_SCREEN_HEIGHT,
22
23
  DEFAULT_FUSION_SCREEN_WIDTH,
@@ -90,40 +91,55 @@ export default defineAction({
90
91
  timeoutMs: 20_000,
91
92
  });
92
93
 
93
- const db = getDb();
94
94
  const now = new Date().toISOString();
95
95
 
96
96
  if (result.status === "error") {
97
- const nextData = writeFusionApp(data, {
98
- ...fusionApp,
99
- status: "error",
100
- statusMessage: result.message ?? "Container provisioning failed",
101
- updatedAt: now,
97
+ const statusMessage = result.message ?? "Container provisioning failed";
98
+ await mutateDesignData({
99
+ designId,
100
+ mutate: (current) =>
101
+ writeFusionApp(current, {
102
+ ...(readFusionApp(current) ?? fusionApp),
103
+ status: "error",
104
+ statusMessage,
105
+ updatedAt: now,
106
+ }),
107
+ isApplied: (current) => {
108
+ const persisted = readFusionApp(current);
109
+ return (
110
+ persisted?.status === "error" &&
111
+ persisted.statusMessage === statusMessage
112
+ );
113
+ },
102
114
  });
103
- await db
104
- .update(schema.designs)
105
- .set({ data: JSON.stringify(nextData), updatedAt: now })
106
- .where(eq(schema.designs.id, designId));
107
115
  return {
108
116
  status: "error" as const,
109
- message: result.message ?? "Container provisioning failed",
117
+ message: statusMessage,
110
118
  };
111
119
  }
112
120
 
113
121
  if (result.status === "provisioning") {
114
- const nextData = writeFusionApp(data, {
115
- ...fusionApp,
116
- status: "building",
117
- statusMessage: result.message ?? "Container is still starting",
118
- updatedAt: now,
122
+ const statusMessage = result.message ?? "Container is still starting";
123
+ await mutateDesignData({
124
+ designId,
125
+ mutate: (current) =>
126
+ writeFusionApp(current, {
127
+ ...(readFusionApp(current) ?? fusionApp),
128
+ status: "building",
129
+ statusMessage,
130
+ updatedAt: now,
131
+ }),
132
+ isApplied: (current) => {
133
+ const persisted = readFusionApp(current);
134
+ return (
135
+ persisted?.status === "building" &&
136
+ persisted.statusMessage === statusMessage
137
+ );
138
+ },
119
139
  });
120
- await db
121
- .update(schema.designs)
122
- .set({ data: JSON.stringify(nextData), updatedAt: now })
123
- .where(eq(schema.designs.id, designId));
124
140
  return {
125
141
  status: "building" as const,
126
- message: result.message ?? "Container is still starting",
142
+ message: statusMessage,
127
143
  };
128
144
  }
129
145
 
@@ -159,25 +175,26 @@ export default defineAction({
159
175
  height: DEFAULT_FUSION_SCREEN_HEIGHT,
160
176
  });
161
177
 
162
- // Re-read the design's data since upsertFusionScreens just wrote it, then
163
- // layer the fusionApp update on top so we don't clobber the screen writes.
164
- const [refreshed] = await db
165
- .select({ data: schema.designs.data })
166
- .from(schema.designs)
167
- .where(eq(schema.designs.id, designId))
168
- .limit(1);
169
- const refreshedData = parseDesignDataBlob(refreshed?.data);
170
- const nextData = writeFusionApp(refreshedData, {
171
- ...fusionApp,
172
- previewUrl,
173
- status: "ready",
174
- statusMessage: result.message ?? "Container is ready",
175
- updatedAt: now,
178
+ const statusMessage = result.message ?? "Container is ready";
179
+ await mutateDesignData({
180
+ designId,
181
+ mutate: (current) =>
182
+ writeFusionApp(current, {
183
+ ...(readFusionApp(current) ?? fusionApp),
184
+ previewUrl,
185
+ status: "ready",
186
+ statusMessage,
187
+ updatedAt: now,
188
+ }),
189
+ isApplied: (current) => {
190
+ const persisted = readFusionApp(current);
191
+ return (
192
+ persisted?.previewUrl === previewUrl &&
193
+ persisted.status === "ready" &&
194
+ persisted.statusMessage === statusMessage
195
+ );
196
+ },
176
197
  });
177
- await db
178
- .update(schema.designs)
179
- .set({ data: JSON.stringify(nextData), updatedAt: now })
180
- .where(eq(schema.designs.id, designId));
181
198
 
182
199
  const pendingEditCount = await countPendingEdits(design);
183
200