@agent-native/core 0.100.1 → 0.101.2

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 (387) hide show
  1. package/corpus/README.md +2 -2
  2. package/corpus/core/CHANGELOG.md +73 -0
  3. package/corpus/core/docs/content/locales/ar-SA/pr-visual-recap.mdx +48 -30
  4. package/corpus/core/docs/content/locales/ar-SA/template-plan.mdx +7 -0
  5. package/corpus/core/docs/content/locales/de-DE/pr-visual-recap.mdx +48 -30
  6. package/corpus/core/docs/content/locales/de-DE/template-plan.mdx +7 -0
  7. package/corpus/core/docs/content/locales/es-ES/pr-visual-recap.mdx +48 -30
  8. package/corpus/core/docs/content/locales/es-ES/template-plan.mdx +14 -0
  9. package/corpus/core/docs/content/locales/fr-FR/pr-visual-recap.mdx +48 -30
  10. package/corpus/core/docs/content/locales/fr-FR/template-plan.mdx +7 -0
  11. package/corpus/core/docs/content/locales/hi-IN/pr-visual-recap.mdx +48 -30
  12. package/corpus/core/docs/content/locales/hi-IN/template-plan.mdx +7 -0
  13. package/corpus/core/docs/content/locales/ja-JP/pr-visual-recap.mdx +48 -30
  14. package/corpus/core/docs/content/locales/ja-JP/template-plan.mdx +7 -0
  15. package/corpus/core/docs/content/locales/ko-KR/pr-visual-recap.mdx +48 -30
  16. package/corpus/core/docs/content/locales/ko-KR/template-plan.mdx +7 -0
  17. package/corpus/core/docs/content/locales/pt-BR/pr-visual-recap.mdx +48 -30
  18. package/corpus/core/docs/content/locales/pt-BR/template-plan.mdx +14 -0
  19. package/corpus/core/docs/content/locales/zh-CN/pr-visual-recap.mdx +48 -30
  20. package/corpus/core/docs/content/locales/zh-CN/template-plan.mdx +7 -0
  21. package/corpus/core/docs/content/locales/zh-TW/pr-visual-recap.mdx +48 -30
  22. package/corpus/core/docs/content/locales/zh-TW/template-plan.mdx +7 -0
  23. package/corpus/core/docs/content/pr-visual-recap.mdx +50 -32
  24. package/corpus/core/docs/content/template-plan.mdx +14 -0
  25. package/corpus/core/docs/content/toolkit-comments-review.mdx +16 -2
  26. package/corpus/core/package.json +4 -1
  27. package/corpus/core/src/a2a/index.ts +2 -1
  28. package/corpus/core/src/a2a/server.ts +34 -9
  29. package/corpus/core/src/agent/production-agent.ts +56 -10
  30. package/corpus/core/src/cli/create.ts +47 -19
  31. package/corpus/core/src/cli/pr-visual-recap-workflow.ts +2 -3
  32. package/corpus/core/src/cli/recap.ts +3 -4932
  33. package/corpus/core/src/cli/skills-content/visual-plan-skill.ts +6 -4
  34. package/corpus/core/src/cli/skills-content/visual-recap-skill.ts +7 -1
  35. package/corpus/core/src/client/AgentPanel.tsx +19 -17
  36. package/corpus/core/src/client/AssistantChat.tsx +4 -0
  37. package/corpus/core/src/client/analytics.ts +8 -1
  38. package/corpus/core/src/client/chat/markdown-renderer.tsx +54 -8
  39. package/corpus/core/src/client/chat/message-components.tsx +8 -2
  40. package/corpus/core/src/client/clipboard.ts +28 -1
  41. package/corpus/core/src/client/composer/PromptComposer.tsx +4 -0
  42. package/corpus/core/src/client/composer/TiptapComposer.tsx +30 -3
  43. package/corpus/core/src/client/guided-questions.tsx +4 -0
  44. package/corpus/core/src/client/i18n.tsx +2 -1
  45. package/corpus/core/src/client/index.ts +4 -0
  46. package/corpus/core/src/client/review/ReviewCommentComposer.tsx +108 -0
  47. package/corpus/core/src/client/review/ReviewThreadPanel.tsx +482 -150
  48. package/corpus/core/src/client/review/index.ts +8 -0
  49. package/corpus/core/src/client/review/use-review.ts +35 -1
  50. package/corpus/core/src/client/use-agent-chat-context.ts +3 -2
  51. package/corpus/core/src/integrations/webhook-handler.ts +4 -2
  52. package/corpus/core/src/review/actions/create-review-comment.ts +2 -1
  53. package/corpus/core/src/review/actions/get-review-feedback.ts +6 -11
  54. package/corpus/core/src/review/actions/list-review-comments.ts +38 -4
  55. package/corpus/core/src/review/actions/reply-review-comment.ts +33 -22
  56. package/corpus/core/src/review/actions/resolve-review-thread.ts +29 -2
  57. package/corpus/core/src/review/actions/send-review-thread-to-agent.ts +62 -0
  58. package/corpus/core/src/review/identity.ts +101 -0
  59. package/corpus/core/src/review/index.ts +14 -0
  60. package/corpus/core/src/review/store.ts +315 -8
  61. package/corpus/core/src/review/types.ts +4 -0
  62. package/corpus/core/src/secrets/crypto.ts +98 -47
  63. package/corpus/core/src/secrets/index.ts +2 -1
  64. package/corpus/core/src/secrets/schema.ts +3 -0
  65. package/corpus/core/src/secrets/storage.ts +164 -31
  66. package/corpus/core/src/server/action-discovery.ts +4 -0
  67. package/corpus/core/src/server/action-routes.ts +125 -4
  68. package/corpus/core/src/server/agent-chat/plugin-options.ts +16 -0
  69. package/corpus/core/src/server/agent-chat-plugin.ts +1 -0
  70. package/corpus/core/src/server/index.ts +8 -0
  71. package/corpus/core/src/vite/action-types-plugin.ts +4 -0
  72. package/corpus/templates/analytics/changelog/2026-07-14-daily-dashboard-email-captures-authenticate-with-a-sessi.md +6 -0
  73. package/corpus/templates/analytics/server/lib/dashboard-report.ts +156 -3
  74. package/corpus/templates/assets/app/components/generation/GenerationResults.tsx +402 -142
  75. package/corpus/templates/assets/app/components/layout/Layout.tsx +4 -0
  76. package/corpus/templates/assets/app/hooks/use-navigation-state.ts +3 -1
  77. package/corpus/templates/assets/app/i18n/zh-TW.ts +1 -0
  78. package/corpus/templates/assets/app/i18n-data.ts +1 -0
  79. package/corpus/templates/assets/app/routes/library.tsx +187 -48
  80. package/corpus/templates/assets/changelog/2026-07-13-assets-keeps-the-right-chat-sidebar-closed-when-the-full-pag.md +6 -0
  81. package/corpus/templates/assets/changelog/2026-07-13-merged-the-candidates-panel-into-the-library-as-a-drafts-tab.md +6 -0
  82. package/corpus/templates/chat/app/lib/agent-page.tsx +40 -0
  83. package/corpus/templates/chat/app/routes/agent.tsx +5 -3
  84. package/corpus/templates/chat/changelog/2026-07-14-fixed-chat-template-startup-with-older-core-versions.md +6 -0
  85. package/corpus/templates/clips/.agents/skills/ai-video-tools/SKILL.md +5 -0
  86. package/corpus/templates/clips/AGENTS.md +4 -0
  87. package/corpus/templates/clips/actions/get-feature-flags.ts +30 -0
  88. package/corpus/templates/clips/actions/lib/transcript-preview.ts +48 -0
  89. package/corpus/templates/clips/actions/request-transcript.ts +41 -1
  90. package/corpus/templates/clips/actions/view-screen.ts +5 -9
  91. package/corpus/templates/clips/app/components/library/library-layout.tsx +1 -1
  92. package/corpus/templates/clips/app/components/player/video-player.tsx +39 -1
  93. package/corpus/templates/clips/app/hooks/use-desktop-promo.ts +6 -12
  94. package/corpus/templates/clips/app/hooks/use-mse-video-source.ts +146 -0
  95. package/corpus/templates/clips/app/lib/capture-install-options.ts +21 -0
  96. package/corpus/templates/clips/app/lib/fmp4.ts +271 -0
  97. package/corpus/templates/clips/app/lib/mse-video-loader.ts +585 -0
  98. package/corpus/templates/clips/app/routes/_app.dictate.tsx +0 -4
  99. package/corpus/templates/clips/app/routes/_app.meetings.$meetingId.tsx +5 -13
  100. package/corpus/templates/clips/app/routes/_app.meetings._index.tsx +2 -37
  101. package/corpus/templates/clips/app/routes/download.tsx +3 -2
  102. package/corpus/templates/clips/changelog/2026-07-10-shared-clips-now-start-playing-instantly-instead-of-showing-.md +6 -0
  103. package/corpus/templates/clips/changelog/2026-07-14-clips-now-distinguishes-transcript-previews-from-incomplete-.md +6 -0
  104. package/corpus/templates/clips/changelog/2026-07-14-desktop-app-prompts-stay-hidden-after-you-download-the-insta.md +6 -0
  105. package/corpus/templates/clips/desktop/src/lib/recorder.ts +5 -0
  106. package/corpus/templates/clips/desktop/src/overlays/recording-pill.tsx +10 -0
  107. package/corpus/templates/clips/desktop/src-tauri/src/lib.rs +4 -0
  108. package/corpus/templates/clips/desktop/src-tauri/src/native_screen/custom_capture.rs +2518 -0
  109. package/corpus/templates/clips/desktop/src-tauri/src/native_screen/live_upload.rs +353 -0
  110. package/corpus/templates/clips/desktop/src-tauri/src/native_screen.rs +558 -67
  111. package/corpus/templates/clips/desktop/src-tauri/src/recording_indicator.rs +11 -1
  112. package/corpus/templates/clips/desktop/src-tauri/src/remote_flags.rs +188 -0
  113. package/corpus/templates/clips/desktop/src-tauri/src/whisper_speech.rs +1 -1
  114. package/corpus/templates/clips/server/lib/post-finalize-dispatch.ts +1 -0
  115. package/corpus/templates/clips/server/plugins/agent-chat.ts +5 -0
  116. package/corpus/templates/clips/server/routes/api/_agent-native-background/post-finalize-worker.post.ts +5 -1
  117. package/corpus/templates/clips/shared/feature-flags.ts +41 -0
  118. package/corpus/templates/design/.agents/skills/design-generation/SKILL.md +3 -0
  119. package/corpus/templates/design/.agents/skills/design-review-feedback/SKILL.md +42 -0
  120. package/corpus/templates/design/AGENTS.md +6 -0
  121. package/corpus/templates/design/README.md +1 -0
  122. package/corpus/templates/design/actions/navigate.ts +4 -4
  123. package/corpus/templates/design/actions/view-screen.ts +116 -2
  124. package/corpus/templates/design/agent-native.app-skill.json +5 -0
  125. package/corpus/templates/design/app/components/design/DesignCanvas.tsx +52 -59
  126. package/corpus/templates/design/app/components/design/DesignExtensionsPanel.tsx +13 -9
  127. package/corpus/templates/design/app/components/design/EditPanel.tsx +79 -11
  128. package/corpus/templates/design/app/components/design/LayersPanel.tsx +78 -65
  129. package/corpus/templates/design/app/components/design/ReviewCommentsPanel.tsx +161 -0
  130. package/corpus/templates/design/app/components/design/ReviewStatusControl.tsx +96 -0
  131. package/corpus/templates/design/app/components/design/bridge/hit-test.bridge.ts +166 -0
  132. package/corpus/templates/design/app/components/layout/Layout.tsx +1 -0
  133. package/corpus/templates/design/app/components/visual-editor/ReviewCanvasPins.tsx +1077 -0
  134. package/corpus/templates/design/app/components/visual-editor/index.ts +1 -0
  135. package/corpus/templates/design/app/components/visual-editor/review-canvas-state.ts +42 -0
  136. package/corpus/templates/design/app/hooks/use-design-systems.ts +2 -2
  137. package/corpus/templates/design/app/hooks/use-navigation-state.ts +9 -6
  138. package/corpus/templates/design/app/hooks/use-question-flow.ts +7 -1
  139. package/corpus/templates/design/app/i18n/ar-SA.ts +56 -1
  140. package/corpus/templates/design/app/i18n/de-DE.ts +57 -1
  141. package/corpus/templates/design/app/i18n/en-US.ts +56 -1
  142. package/corpus/templates/design/app/i18n/es-ES.ts +56 -1
  143. package/corpus/templates/design/app/i18n/fr-FR.ts +57 -1
  144. package/corpus/templates/design/app/i18n/hi-IN.ts +56 -1
  145. package/corpus/templates/design/app/i18n/ja-JP.ts +56 -1
  146. package/corpus/templates/design/app/i18n/ko-KR.ts +56 -1
  147. package/corpus/templates/design/app/i18n/pt-BR.ts +57 -1
  148. package/corpus/templates/design/app/i18n/zh-CN.ts +56 -1
  149. package/corpus/templates/design/app/i18n/zh-TW.ts +51 -0
  150. package/corpus/templates/design/app/pages/Present.tsx +172 -14
  151. package/corpus/templates/design/app/pages/design-editor/overview-camera.ts +23 -0
  152. package/corpus/templates/design/app/pages/design-editor/tool-state.ts +10 -0
  153. package/corpus/templates/design/app/pages/present-review-state.ts +18 -0
  154. package/corpus/templates/design/app/public-routes.ts +8 -0
  155. package/corpus/templates/design/app/root.tsx +7 -6
  156. package/corpus/templates/design/changelog/2026-07-13-dragged-design-assets-now-appear-at-the-visible-drop-locatio.md +6 -0
  157. package/corpus/templates/design/changelog/2026-07-13-reviewers-can-pin-comments-on-shared-designs-and-apply-verif.md +6 -0
  158. package/corpus/templates/design/server/plugins/agent-chat.ts +10 -0
  159. package/corpus/templates/design/server/plugins/auth.ts +7 -5
  160. package/corpus/templates/design/server/plugins/review.ts +9 -0
  161. package/corpus/templates/design/shared/review-anchor.ts +83 -0
  162. package/corpus/templates/design/shared/review-summary.ts +25 -0
  163. package/corpus/templates/forms/.agents/skills/form-publishing/SKILL.md +2 -0
  164. package/corpus/templates/forms/AGENTS.md +4 -0
  165. package/corpus/templates/forms/actions/create-form.ts +2 -1
  166. package/corpus/templates/forms/actions/update-form.ts +5 -2
  167. package/corpus/templates/forms/app/i18n/ar-SA.ts +3 -0
  168. package/corpus/templates/forms/app/i18n/de-DE.ts +3 -0
  169. package/corpus/templates/forms/app/i18n/en-US.ts +3 -0
  170. package/corpus/templates/forms/app/i18n/es-ES.ts +3 -0
  171. package/corpus/templates/forms/app/i18n/fr-FR.ts +3 -0
  172. package/corpus/templates/forms/app/i18n/hi-IN.ts +3 -0
  173. package/corpus/templates/forms/app/i18n/ja-JP.ts +3 -0
  174. package/corpus/templates/forms/app/i18n/ko-KR.ts +3 -0
  175. package/corpus/templates/forms/app/i18n/pt-BR.ts +3 -0
  176. package/corpus/templates/forms/app/i18n/zh-CN.ts +3 -0
  177. package/corpus/templates/forms/app/i18n/zh-TW.ts +3 -0
  178. package/corpus/templates/forms/app/pages/FormBuilderPage.tsx +19 -0
  179. package/corpus/templates/forms/changelog/2026-07-14-fixed-the-ask-forms-loading-input-appearing-above-the-welcom.md +6 -0
  180. package/corpus/templates/forms/changelog/2026-07-14-form-social-previews-now-show-the-form-title-description-and.md +6 -0
  181. package/corpus/templates/forms/changelog/2026-07-14-forms-can-email-the-form-owner-when-new-responses-arrive.md +6 -0
  182. package/corpus/templates/forms/server/handlers/submissions.ts +17 -0
  183. package/corpus/templates/forms/server/lib/form-og-image.ts +64 -6
  184. package/corpus/templates/forms/server/lib/public-form-ssr.ts +6 -2
  185. package/corpus/templates/forms/server/lib/response-email.ts +65 -0
  186. package/corpus/templates/forms/server/plugins/agent-chat.ts +1 -0
  187. package/corpus/templates/forms/server/routes/api/forms/og/[...slug]/og.png.get.ts +184 -0
  188. package/corpus/templates/forms/shared/types.ts +2 -0
  189. package/corpus/templates/plan/.agents/skills/visual-plan/SKILL.md +6 -4
  190. package/corpus/templates/plan/.agents/skills/visual-recap/SKILL.md +7 -1
  191. package/dist/a2a/index.d.ts +2 -1
  192. package/dist/a2a/index.d.ts.map +1 -1
  193. package/dist/a2a/index.js +1 -1
  194. package/dist/a2a/index.js.map +1 -1
  195. package/dist/a2a/server.d.ts +25 -0
  196. package/dist/a2a/server.d.ts.map +1 -1
  197. package/dist/a2a/server.js +30 -6
  198. package/dist/a2a/server.js.map +1 -1
  199. package/dist/agent/production-agent.d.ts +2 -0
  200. package/dist/agent/production-agent.d.ts.map +1 -1
  201. package/dist/agent/production-agent.js +37 -12
  202. package/dist/agent/production-agent.js.map +1 -1
  203. package/dist/cli/create.d.ts +5 -3
  204. package/dist/cli/create.d.ts.map +1 -1
  205. package/dist/cli/create.js +44 -19
  206. package/dist/cli/create.js.map +1 -1
  207. package/dist/cli/pr-visual-recap-workflow.d.ts +2 -2
  208. package/dist/cli/pr-visual-recap-workflow.d.ts.map +1 -1
  209. package/dist/cli/pr-visual-recap-workflow.js +2 -2
  210. package/dist/cli/pr-visual-recap-workflow.js.map +1 -1
  211. package/dist/cli/recap.d.ts +3 -562
  212. package/dist/cli/recap.d.ts.map +1 -1
  213. package/dist/cli/recap.js +3 -3875
  214. package/dist/cli/recap.js.map +1 -1
  215. package/dist/cli/skills-content/visual-plan-skill.d.ts +1 -1
  216. package/dist/cli/skills-content/visual-plan-skill.d.ts.map +1 -1
  217. package/dist/cli/skills-content/visual-plan-skill.js +6 -4
  218. package/dist/cli/skills-content/visual-plan-skill.js.map +1 -1
  219. package/dist/cli/skills-content/visual-recap-skill.d.ts +1 -1
  220. package/dist/cli/skills-content/visual-recap-skill.d.ts.map +1 -1
  221. package/dist/cli/skills-content/visual-recap-skill.js +7 -1
  222. package/dist/cli/skills-content/visual-recap-skill.js.map +1 -1
  223. package/dist/client/AgentPanel.d.ts.map +1 -1
  224. package/dist/client/AgentPanel.js +3 -3
  225. package/dist/client/AgentPanel.js.map +1 -1
  226. package/dist/client/AssistantChat.d.ts +2 -0
  227. package/dist/client/AssistantChat.d.ts.map +1 -1
  228. package/dist/client/AssistantChat.js +2 -2
  229. package/dist/client/AssistantChat.js.map +1 -1
  230. package/dist/client/analytics.d.ts +5 -0
  231. package/dist/client/analytics.d.ts.map +1 -1
  232. package/dist/client/analytics.js +3 -1
  233. package/dist/client/analytics.js.map +1 -1
  234. package/dist/client/chat/markdown-renderer.d.ts +1 -0
  235. package/dist/client/chat/markdown-renderer.d.ts.map +1 -1
  236. package/dist/client/chat/markdown-renderer.js +36 -1
  237. package/dist/client/chat/markdown-renderer.js.map +1 -1
  238. package/dist/client/chat/message-components.d.ts.map +1 -1
  239. package/dist/client/chat/message-components.js +5 -2
  240. package/dist/client/chat/message-components.js.map +1 -1
  241. package/dist/client/clipboard.d.ts +3 -1
  242. package/dist/client/clipboard.d.ts.map +1 -1
  243. package/dist/client/clipboard.js +24 -1
  244. package/dist/client/clipboard.js.map +1 -1
  245. package/dist/client/composer/PromptComposer.d.ts +2 -0
  246. package/dist/client/composer/PromptComposer.d.ts.map +1 -1
  247. package/dist/client/composer/PromptComposer.js +2 -2
  248. package/dist/client/composer/PromptComposer.js.map +1 -1
  249. package/dist/client/composer/TiptapComposer.d.ts +3 -1
  250. package/dist/client/composer/TiptapComposer.d.ts.map +1 -1
  251. package/dist/client/composer/TiptapComposer.js +20 -5
  252. package/dist/client/composer/TiptapComposer.js.map +1 -1
  253. package/dist/client/guided-questions.d.ts +3 -1
  254. package/dist/client/guided-questions.d.ts.map +1 -1
  255. package/dist/client/guided-questions.js +2 -1
  256. package/dist/client/guided-questions.js.map +1 -1
  257. package/dist/client/i18n.d.ts.map +1 -1
  258. package/dist/client/i18n.js +3 -1
  259. package/dist/client/i18n.js.map +1 -1
  260. package/dist/client/index.d.ts +1 -1
  261. package/dist/client/index.d.ts.map +1 -1
  262. package/dist/client/index.js +1 -1
  263. package/dist/client/index.js.map +1 -1
  264. package/dist/client/review/ReviewCommentComposer.d.ts +18 -0
  265. package/dist/client/review/ReviewCommentComposer.d.ts.map +1 -0
  266. package/dist/client/review/ReviewCommentComposer.js +30 -0
  267. package/dist/client/review/ReviewCommentComposer.js.map +1 -0
  268. package/dist/client/review/ReviewThreadPanel.d.ts +28 -1
  269. package/dist/client/review/ReviewThreadPanel.d.ts.map +1 -1
  270. package/dist/client/review/ReviewThreadPanel.js +151 -39
  271. package/dist/client/review/ReviewThreadPanel.js.map +1 -1
  272. package/dist/client/review/index.d.ts +3 -2
  273. package/dist/client/review/index.d.ts.map +1 -1
  274. package/dist/client/review/index.js +2 -1
  275. package/dist/client/review/index.js.map +1 -1
  276. package/dist/client/review/use-review.d.ts +23 -0
  277. package/dist/client/review/use-review.d.ts.map +1 -1
  278. package/dist/client/review/use-review.js +3 -0
  279. package/dist/client/review/use-review.js.map +1 -1
  280. package/dist/client/use-agent-chat-context.d.ts +1 -1
  281. package/dist/client/use-agent-chat-context.d.ts.map +1 -1
  282. package/dist/client/use-agent-chat-context.js +4 -2
  283. package/dist/client/use-agent-chat-context.js.map +1 -1
  284. package/dist/collab/awareness.d.ts +2 -2
  285. package/dist/collab/awareness.d.ts.map +1 -1
  286. package/dist/collab/struct-routes.d.ts +1 -1
  287. package/dist/file-upload/actions/upload-image.d.ts +1 -1
  288. package/dist/integrations/webhook-handler.d.ts.map +1 -1
  289. package/dist/integrations/webhook-handler.js +3 -2
  290. package/dist/integrations/webhook-handler.js.map +1 -1
  291. package/dist/notifications/routes.d.ts +3 -3
  292. package/dist/observability/routes.d.ts +5 -5
  293. package/dist/progress/routes.d.ts +1 -1
  294. package/dist/provider-api/corpus-jobs.d.ts +2 -2
  295. package/dist/resources/handlers.d.ts +2 -2
  296. package/dist/review/actions/create-review-comment.js +2 -1
  297. package/dist/review/actions/create-review-comment.js.map +1 -1
  298. package/dist/review/actions/get-review-feedback.js +6 -11
  299. package/dist/review/actions/get-review-feedback.js.map +1 -1
  300. package/dist/review/actions/list-review-comments.d.ts +1 -0
  301. package/dist/review/actions/list-review-comments.js +25 -4
  302. package/dist/review/actions/list-review-comments.js.map +1 -1
  303. package/dist/review/actions/reply-review-comment.js +12 -5
  304. package/dist/review/actions/reply-review-comment.js.map +1 -1
  305. package/dist/review/actions/resolve-review-thread.d.ts +3 -0
  306. package/dist/review/actions/resolve-review-thread.js +20 -3
  307. package/dist/review/actions/resolve-review-thread.js.map +1 -1
  308. package/dist/review/actions/send-review-thread-to-agent.d.ts +17 -0
  309. package/dist/review/actions/send-review-thread-to-agent.d.ts.map +1 -0
  310. package/dist/review/actions/send-review-thread-to-agent.js +49 -0
  311. package/dist/review/actions/send-review-thread-to-agent.js.map +1 -0
  312. package/dist/review/identity.d.ts +6 -0
  313. package/dist/review/identity.d.ts.map +1 -0
  314. package/dist/review/identity.js +68 -0
  315. package/dist/review/identity.js.map +1 -0
  316. package/dist/review/index.d.ts +3 -1
  317. package/dist/review/index.d.ts.map +1 -1
  318. package/dist/review/index.js +2 -1
  319. package/dist/review/index.js.map +1 -1
  320. package/dist/review/store.d.ts +36 -0
  321. package/dist/review/store.d.ts.map +1 -1
  322. package/dist/review/store.js +223 -8
  323. package/dist/review/store.js.map +1 -1
  324. package/dist/review/types.d.ts +4 -0
  325. package/dist/review/types.d.ts.map +1 -1
  326. package/dist/review/types.js.map +1 -1
  327. package/dist/secrets/crypto.d.ts +35 -13
  328. package/dist/secrets/crypto.d.ts.map +1 -1
  329. package/dist/secrets/crypto.js +78 -41
  330. package/dist/secrets/crypto.js.map +1 -1
  331. package/dist/secrets/index.d.ts.map +1 -1
  332. package/dist/secrets/index.js +2 -1
  333. package/dist/secrets/index.js.map +1 -1
  334. package/dist/secrets/routes.d.ts +9 -9
  335. package/dist/secrets/schema.d.ts +20 -1
  336. package/dist/secrets/schema.d.ts.map +1 -1
  337. package/dist/secrets/schema.js +3 -0
  338. package/dist/secrets/schema.js.map +1 -1
  339. package/dist/secrets/storage.d.ts +7 -7
  340. package/dist/secrets/storage.d.ts.map +1 -1
  341. package/dist/secrets/storage.js +121 -30
  342. package/dist/secrets/storage.js.map +1 -1
  343. package/dist/server/action-discovery.d.ts.map +1 -1
  344. package/dist/server/action-discovery.js +4 -0
  345. package/dist/server/action-discovery.js.map +1 -1
  346. package/dist/server/action-routes.d.ts +45 -0
  347. package/dist/server/action-routes.d.ts.map +1 -1
  348. package/dist/server/action-routes.js +71 -5
  349. package/dist/server/action-routes.js.map +1 -1
  350. package/dist/server/agent-chat/plugin-options.d.ts +16 -0
  351. package/dist/server/agent-chat/plugin-options.d.ts.map +1 -1
  352. package/dist/server/agent-chat/plugin-options.js.map +1 -1
  353. package/dist/server/agent-chat-plugin.d.ts.map +1 -1
  354. package/dist/server/agent-chat-plugin.js +1 -0
  355. package/dist/server/agent-chat-plugin.js.map +1 -1
  356. package/dist/server/index.d.ts +3 -1
  357. package/dist/server/index.d.ts.map +1 -1
  358. package/dist/server/index.js +2 -0
  359. package/dist/server/index.js.map +1 -1
  360. package/dist/vite/action-types-plugin.d.ts.map +1 -1
  361. package/dist/vite/action-types-plugin.js +4 -0
  362. package/dist/vite/action-types-plugin.js.map +1 -1
  363. package/docs/content/locales/ar-SA/pr-visual-recap.mdx +48 -30
  364. package/docs/content/locales/ar-SA/template-plan.mdx +7 -0
  365. package/docs/content/locales/de-DE/pr-visual-recap.mdx +48 -30
  366. package/docs/content/locales/de-DE/template-plan.mdx +7 -0
  367. package/docs/content/locales/es-ES/pr-visual-recap.mdx +48 -30
  368. package/docs/content/locales/es-ES/template-plan.mdx +14 -0
  369. package/docs/content/locales/fr-FR/pr-visual-recap.mdx +48 -30
  370. package/docs/content/locales/fr-FR/template-plan.mdx +7 -0
  371. package/docs/content/locales/hi-IN/pr-visual-recap.mdx +48 -30
  372. package/docs/content/locales/hi-IN/template-plan.mdx +7 -0
  373. package/docs/content/locales/ja-JP/pr-visual-recap.mdx +48 -30
  374. package/docs/content/locales/ja-JP/template-plan.mdx +7 -0
  375. package/docs/content/locales/ko-KR/pr-visual-recap.mdx +48 -30
  376. package/docs/content/locales/ko-KR/template-plan.mdx +7 -0
  377. package/docs/content/locales/pt-BR/pr-visual-recap.mdx +48 -30
  378. package/docs/content/locales/pt-BR/template-plan.mdx +14 -0
  379. package/docs/content/locales/zh-CN/pr-visual-recap.mdx +48 -30
  380. package/docs/content/locales/zh-CN/template-plan.mdx +7 -0
  381. package/docs/content/locales/zh-TW/pr-visual-recap.mdx +48 -30
  382. package/docs/content/locales/zh-TW/template-plan.mdx +7 -0
  383. package/docs/content/pr-visual-recap.mdx +50 -32
  384. package/docs/content/template-plan.mdx +14 -0
  385. package/docs/content/toolkit-comments-review.mdx +16 -2
  386. package/package.json +4 -1
  387. package/corpus/templates/forms/server/routes/api/forms/og/[slug]/og.png.get.ts +0 -45
@@ -1,8 +1,10 @@
1
1
  import { usePinchZoom, useT } from "@agent-native/core/client";
2
+ import type { ReviewThread } from "@agent-native/core/client";
2
3
  import {
3
4
  injectSessionReplayIframeBootstrap,
4
5
  SESSION_REPLAY_IFRAME_ATTRIBUTE,
5
6
  } from "@agent-native/core/client";
7
+ import type { ReviewComment } from "@agent-native/core/review";
6
8
  import {
7
9
  DEFAULT_CANVAS_MAX_ZOOM,
8
10
  DEFAULT_CANVAS_MIN_ZOOM,
@@ -23,7 +25,14 @@ import {
23
25
  type PenPoint,
24
26
  } from "@shared/pen-path";
25
27
  import { IconPlugConnectedX, IconRefresh } from "@tabler/icons-react";
26
- import { useRef, useEffect, useCallback, useMemo, useState } from "react";
28
+ import {
29
+ useCallback,
30
+ useEffect,
31
+ useId,
32
+ useMemo,
33
+ useRef,
34
+ useState,
35
+ } from "react";
27
36
  import { toast } from "sonner";
28
37
 
29
38
  import { Button } from "@/components/ui/button";
@@ -33,8 +42,8 @@ import { Button } from "@/components/ui/button";
33
42
  // exist for now and can be reconciled in a follow-up. Don't import both.
34
43
  import {
35
44
  DrawOverlay as SharedDrawOverlay,
36
- CanvasCommentPins,
37
- type CanvasPin,
45
+ ReviewCanvasPins,
46
+ type ReviewFocusRequest,
38
47
  } from "@/components/visual-editor";
39
48
  import { sendToDesignAgentChatAndConfirm } from "@/lib/agent-chat";
40
49
  import {
@@ -503,9 +512,9 @@ interface DesignCanvasProps {
503
512
  pinMode?: boolean;
504
513
  /**
505
514
  * When true, suppresses rendering of comment pins on this canvas (e.g. the
506
- * Figma-style Shift+C "hide comments" toggle in single-screen mode). Only
507
- * affects pin *visibility* pin drop mode (`pinMode`) still behaves
508
- * normally underneath so toggling this back off doesn't lose anything.
515
+ * Figma-style Shift+C "hide comments" toggle in single-screen mode). Hiding
516
+ * comments while pin mode is active also exits pin mode so an invisible
517
+ * click target cannot keep intercepting canvas interactions.
509
518
  */
510
519
  commentPinsHidden?: boolean;
511
520
  selectedSelector?: string | null;
@@ -521,6 +530,18 @@ interface DesignCanvasProps {
521
530
  onExitPinMode?: () => void;
522
531
  /** Stable id of the open design (used for pin scoping + agent prompt). */
523
532
  designId?: string;
533
+ /** Whether the current signed-in viewer may create review comments. */
534
+ reviewCanPost?: boolean;
535
+ /** Whether the current viewer may resolve review threads. */
536
+ reviewCanResolve?: boolean;
537
+ /** A panel-driven request to focus an anchored review comment. */
538
+ reviewFocusRequest?: ReviewFocusRequest | null;
539
+ /** Dispatch a newly created agent-targeted comment to the local agent chat. */
540
+ onDispatchCommentToAgent?: (comment: ReviewComment) => void;
541
+ /** Dispatch one existing review thread to the local agent chat. */
542
+ onSendThreadToAgent?: (thread: ReviewThread) => void;
543
+ /** Thread currently being routed to the agent. */
544
+ reviewSendingThreadId?: string | null;
524
545
  /** Human-readable label for the design (used in agent prompt). */
525
546
  designTitle?: string;
526
547
  /** Stable id for comment pins, usually scoped to the active screen. */
@@ -1022,11 +1043,16 @@ export function DesignCanvas({
1022
1043
  onExitPinMode,
1023
1044
  registerRuntimeBridge = true,
1024
1045
  designId,
1046
+ reviewCanPost = false,
1047
+ reviewCanResolve = false,
1048
+ reviewFocusRequest,
1049
+ onDispatchCommentToAgent,
1050
+ onSendThreadToAgent,
1051
+ reviewSendingThreadId,
1025
1052
  designTitle,
1026
1053
  commentContextId,
1027
1054
  screenId,
1028
1055
  previewFrameId,
1029
- commentContextLabel,
1030
1056
  onPrototypeNavigate,
1031
1057
  motionTracks,
1032
1058
  motionDefaultEase,
@@ -1050,6 +1076,7 @@ export function DesignCanvas({
1050
1076
  null,
1051
1077
  );
1052
1078
  const scrollContainerRef = useRef<HTMLDivElement>(null);
1079
+ const reviewCanvasId = useId();
1053
1080
  const zoomLayerRef = useRef<HTMLDivElement>(null);
1054
1081
  const zoomRef = useRef(zoom);
1055
1082
  // Zoom-invariant chrome: the non-embedded-frame render path below wraps the
@@ -1119,8 +1146,6 @@ export function DesignCanvas({
1119
1146
  return true;
1120
1147
  }, []);
1121
1148
  const [renderedContent, setRenderedContent] = useState(content);
1122
- const [annotationPins, setAnnotationPins] = useState<CanvasPin[]>([]);
1123
- const [pinSubmitSignal, setPinSubmitSignal] = useState(0);
1124
1149
  // True while a drawing send is capturing/compositing/uploading the
1125
1150
  // annotated screenshot (see design-canvas/annotation-snapshot.ts). Drives
1126
1151
  // SharedDrawOverlay's busy Send state so a slow capture can't be triggered
@@ -1919,14 +1944,6 @@ export function DesignCanvas({
1919
1944
  setExternalSnapshotRetryNonce((nonce) => nonce + 1);
1920
1945
  }, []);
1921
1946
 
1922
- const queuedAnnotationPins = useMemo(
1923
- () =>
1924
- annotationPins.filter(
1925
- (pin) => pin.queued && !pin.submitted && (pin.draft || "").trim(),
1926
- ),
1927
- [annotationPins],
1928
- );
1929
-
1930
1947
  useEffect(() => {
1931
1948
  if (previousContentKeyRef.current !== contentKey) {
1932
1949
  previousContentKeyRef.current = contentKey;
@@ -4009,6 +4026,7 @@ export function DesignCanvas({
4009
4026
  // visible when a design background matches the editor canvas.
4010
4027
  const iframeElement = (
4011
4028
  <div
4029
+ data-review-canvas-id={reviewCanvasId}
4012
4030
  className="design-canvas-iframe-wrapper relative inline-block ring-1 ring-border/60 shadow-[0_0_0_1px_rgba(0,0,0,0.04),0_8px_24px_-12px_rgba(0,0,0,0.45)]"
4013
4031
  onDragEnter={handleWrapperDragEnter}
4014
4032
  onDragOver={handleWrapperDragOver}
@@ -4305,7 +4323,7 @@ export function DesignCanvas({
4305
4323
  scopeKey={screenId}
4306
4324
  retainSurfaceWhenHidden={retainDrawOverlayWhenHidden}
4307
4325
  canvasInteractive={!pinMode}
4308
- queuedAnnotationCount={queuedAnnotationPins.length}
4326
+ queuedAnnotationCount={0}
4309
4327
  zoom={zoom}
4310
4328
  sending={annotationCaptureBusy}
4311
4329
  onClose={() => onExitDrawMode?.()}
@@ -4318,33 +4336,14 @@ export function DesignCanvas({
4318
4336
  : `[label "${a.text}" at ${a.position.x.toFixed(0)},${a.position.y.toFixed(0)}]`,
4319
4337
  )
4320
4338
  .join("\n");
4321
- const pinSummary = queuedAnnotationPins
4322
- .flatMap((pin, index) => {
4323
- const lines = [
4324
- `[${index + 1}] Comment pin on ${commentContextLabel || designTitle || commentContextId || designId || "design"}`,
4325
- `Position: ${pin.xPct.toFixed(1)}% from left, ${pin.yPct.toFixed(1)}% from top`,
4326
- ];
4327
- if (pin.targetAnchorId)
4328
- lines.push(`Anchor id: ${pin.targetAnchorId}`);
4329
- if (pin.targetSelector)
4330
- lines.push(`Element: ${pin.targetSelector}`);
4331
- if (pin.targetText)
4332
- lines.push(`Nearby text: "${pin.targetText}"`);
4333
- lines.push("");
4334
- lines.push((pin.draft || "").trim());
4335
- return [...lines, ""];
4336
- })
4337
- .join("\n");
4338
4339
  const lines = [
4339
4340
  `[Annotations on design ${designId || ""}${designTitle ? ` (${designTitle})` : ""}]`,
4340
4341
  `Canvas size: ${canvasSize.width.toFixed(0)}x${canvasSize.height.toFixed(0)}`,
4341
4342
  ...(summary ? ["", "[Drawing]", summary] : []),
4342
- ...(pinSummary ? ["", "[Comment pins]", pinSummary] : []),
4343
4343
  "",
4344
4344
  instruction || "Apply these annotations to the design.",
4345
4345
  ];
4346
4346
  const message = lines.join("\n");
4347
- const hasQueuedPins = queuedAnnotationPins.length > 0;
4348
4347
 
4349
4348
  // Best-effort: render the annotated screen + composited drawing as
4350
4349
  // ONE image the agent can see (see design-canvas/annotation-snapshot.ts),
@@ -4368,7 +4367,7 @@ export function DesignCanvas({
4368
4367
  .then((imageUrl) =>
4369
4368
  submitDesignAnnotations({
4370
4369
  message,
4371
- hasQueuedPins,
4370
+ hasQueuedPins: false,
4372
4371
  // Ack-confirmed send: only exit draw mode / mark pins
4373
4372
  // submitted once the message is CONFIRMED to have reached
4374
4373
  // the chat (became a visible turn). A fire-and-forget send
@@ -4389,9 +4388,7 @@ export function DesignCanvas({
4389
4388
  );
4390
4389
  }
4391
4390
  },
4392
- markQueuedPinsSubmitted: () => {
4393
- setPinSubmitSignal((signal) => signal + 1);
4394
- },
4391
+ markQueuedPinsSubmitted: () => {},
4395
4392
  exitDrawMode: () => onExitDrawMode?.(),
4396
4393
  onError: (error) => {
4397
4394
  console.error(
@@ -4536,27 +4533,23 @@ export function DesignCanvas({
4536
4533
  </div>
4537
4534
  )}
4538
4535
 
4539
- {/* Canvas comment pins anchored to the iframe wrapper. The pins
4540
- themselves render via fixed positioning, so we mount them outside
4541
- the zoom-transformed container to keep coordinates stable.
4542
- Suppressed entirely when commentPinsHidden (Figma-style Shift+C
4543
- "hide comments" toggle) is set — existing pins disappear and pin
4544
- drop-mode has nothing to render into until it's toggled back on. */}
4545
- {!commentPinsHidden && (
4546
- <CanvasCommentPins
4536
+ {designId && (screenId || commentContextId) ? (
4537
+ <ReviewCanvasPins
4547
4538
  active={!!pinMode}
4548
- submitMode={drawMode ? "queue" : "direct"}
4549
- onPinsChange={setAnnotationPins}
4550
- submitQueuedSignal={pinSubmitSignal}
4551
- clickPlaneUnderToolbar={!!drawMode}
4539
+ hidden={commentPinsHidden}
4552
4540
  onClose={() => onExitPinMode?.()}
4553
- canvasSelector=".design-canvas-iframe-wrapper"
4554
- contextId={commentContextId || designId || "design"}
4555
- contextLabel={
4556
- commentContextLabel || designTitle || commentContextId || designId
4557
- }
4541
+ canvasSelector={`[data-review-canvas-id="${reviewCanvasId}"]`}
4542
+ resourceType="design"
4543
+ resourceId={designId}
4544
+ targetId={screenId ?? commentContextId ?? ""}
4545
+ canPost={reviewCanPost}
4546
+ canResolve={reviewCanResolve}
4547
+ focusRequest={reviewFocusRequest}
4548
+ onDispatchCommentToAgent={onDispatchCommentToAgent}
4549
+ onSendThreadToAgent={onSendThreadToAgent}
4550
+ sendingThreadId={reviewSendingThreadId}
4558
4551
  />
4559
- )}
4552
+ ) : null}
4560
4553
  </div>
4561
4554
  );
4562
4555
  }
@@ -480,9 +480,9 @@ interface AssetLibraryPanelProps {
480
480
  * overview canvas, over the board surface, or the editor is in
481
481
  * single-screen mode and the point is outside that screen's iframe).
482
482
  *
483
- * When omitted (the default no DesignEditor wiring yet), this panel
484
- * falls back to EXACTLY today's behavior: it sends the raw viewport point
485
- * as `x`/`y` with no `screenId`, which the action already handles safely
483
+ * When omitted by another host, this panel falls back to sending the raw
484
+ * viewport point as `x`/`y` with no `screenId`, which the action already
485
+ * handles safely
486
486
  * (a raw client point rarely lands inside a real screen's small content
487
487
  * bounds, and even when it coincidentally does, worst case is an
488
488
  * imprecisely-placed insert — never a crash or data loss; see
@@ -693,9 +693,9 @@ export function AssetLibraryPanel({
693
693
  // isUsableDropPosition for the exact "both x and y, non-negative"
694
694
  // usability contract a caller-supplied position must meet, and this
695
695
  // component's resolveScreenPoint prop doc above for how dropPosition
696
- // gets its coordinate space (converted screen-content px when
697
- // resolveScreenPoint is wired up by the DesignEditor owner, otherwise
698
- // the raw viewport point as an inert-but-harmless fallback).
696
+ // gets its coordinate space (converted screen-content px when the host
697
+ // supplies resolveScreenPoint, otherwise the raw viewport point as an
698
+ // inert-but-harmless fallback).
699
699
  insertNativeAsset.mutate(
700
700
  {
701
701
  kind: asset.kind,
@@ -755,9 +755,9 @@ export function AssetLibraryPanel({
755
755
  if (!draggedNativeAsset) return;
756
756
  // Convert the viewport drop point into a specific screen's own
757
757
  // content-px coordinates via the optional resolveScreenPoint prop (see
758
- // its doc comment above for the exact contract). Without that prop
759
- // (no DesignEditor wiring yet), fall back to sending the raw viewport
760
- // point with no screenId — the exact behavior this drop handler always
758
+ // its doc comment above for the exact contract). Without that prop, fall
759
+ // back to sending the raw viewport point with no screenId — the behavior
760
+ // this drop handler historically
761
761
  // had, and still safe: insert-design-native-asset's isUsableDropPosition
762
762
  // only requires non-negative finite numbers, so an unconverted point is
763
763
  // never rejected, just imprecise (see that action's fallback doc).
@@ -765,6 +765,10 @@ export function AssetLibraryPanel({
765
765
  clientX: event.clientX,
766
766
  clientY: event.clientY,
767
767
  });
768
+ if (resolveScreenPoint && !resolved) {
769
+ clearNativeAssetDrag();
770
+ return;
771
+ }
768
772
  handleInsertNativeAsset(
769
773
  draggedNativeAsset,
770
774
  resolved
@@ -28,6 +28,7 @@ import {
28
28
  type InteractionState,
29
29
  } from "@shared/interaction-states";
30
30
  import {
31
+ IconAdjustmentsHorizontal,
31
32
  IconAlignCenter,
32
33
  IconAlignJustified,
33
34
  IconAlignLeft,
@@ -73,6 +74,7 @@ import {
73
74
  IconLink,
74
75
  IconLinkOff,
75
76
  IconMinus,
77
+ IconMessageCircle,
76
78
  IconPerspective,
77
79
  IconPhoto,
78
80
  IconPlus,
@@ -336,6 +338,10 @@ import {
336
338
  GlslShaderEffectSection,
337
339
  type GlslShaderPanelContext,
338
340
  } from "./inspector/GlslShaderPanel";
341
+ import {
342
+ ReviewCommentsPanel,
343
+ type ReviewCommentsPanelProps,
344
+ } from "./ReviewCommentsPanel";
339
345
  import { ReviewPanel } from "./ReviewPanel";
340
346
  import type { ReviewPanelProps } from "./ReviewPanel";
341
347
  import type { StatesPanelProps } from "./StatesPanel";
@@ -393,7 +399,7 @@ export function mergeOptimisticInteractionStateStyles(
393
399
  return { ...(persisted ?? {}), ...(pending ?? {}) };
394
400
  }
395
401
 
396
- export type InspectorTab = "design" | "tweaks";
402
+ export type InspectorTab = "design" | "tweaks" | "comments";
397
403
 
398
404
  interface EditPanelProps {
399
405
  selectedElement: ElementInfo | null;
@@ -456,6 +462,10 @@ interface EditPanelProps {
456
462
  statesPanelProps?: Omit<StatesPanelProps, "designId">;
457
463
  /** Props forwarded to the ReviewPanel (§6.5). */
458
464
  reviewPanelProps?: Omit<ReviewPanelProps, "className">;
465
+ /** Persisted design review comments and feedback queue. */
466
+ reviewCommentsPanelProps?: ReviewCommentsPanelProps;
467
+ /** Open review-thread count shown on the inspector tab. */
468
+ reviewCommentsCount?: number;
459
469
  // -------------------------------------------------------------------------
460
470
  // Component section (§6.1)
461
471
  // When a component instance is selected, pass its node id here to unlock
@@ -1091,31 +1101,82 @@ function InspectorTabsHeader({
1091
1101
  activeTab,
1092
1102
  onActiveTabChange,
1093
1103
  trailing,
1104
+ commentsCount = 0,
1105
+ compact = false,
1094
1106
  }: {
1095
1107
  activeTab: InspectorTab;
1096
1108
  onActiveTabChange: (tab: InspectorTab) => void;
1097
1109
  trailing?: ReactNode;
1110
+ commentsCount?: number;
1111
+ compact?: boolean;
1098
1112
  }) {
1099
1113
  const t = useT();
1100
1114
 
1101
1115
  return (
1102
- <div className="flex min-h-8 shrink-0 items-center justify-between gap-1 border-b border-border/90 px-2 py-1">
1116
+ <div className="flex min-h-8 min-w-0 shrink-0 items-center justify-between gap-1 border-b border-border/90 px-2 py-1">
1103
1117
  <Tabs
1104
1118
  value={activeTab}
1105
1119
  onValueChange={(value) => onActiveTabChange(value as InspectorTab)}
1120
+ className="min-w-0"
1106
1121
  >
1107
- <TabsList className="h-7 justify-start gap-0.5 rounded-none bg-transparent p-0">
1122
+ <TabsList className="h-7 max-w-full justify-start gap-0.5 overflow-hidden rounded-none bg-transparent p-0">
1108
1123
  <TabsTrigger
1109
1124
  value="design"
1110
- className="h-6 rounded-md px-1.5 !text-[11px] font-semibold text-muted-foreground shadow-none transition-colors hover:text-foreground data-[state=active]:bg-[var(--design-editor-panel-raised-bg)] data-[state=active]:text-foreground data-[state=active]:shadow-none"
1125
+ aria-label={t("navigation.brand")}
1126
+ className={cn(
1127
+ "h-6 rounded-md !text-[11px] font-semibold text-muted-foreground shadow-none transition-colors hover:text-foreground data-[state=active]:bg-[var(--design-editor-panel-raised-bg)] data-[state=active]:text-foreground data-[state=active]:shadow-none",
1128
+ compact ? "w-7 px-0" : "px-1.5",
1129
+ )}
1111
1130
  >
1112
- {"Design" /* i18n-ignore design inspector tab */}
1131
+ {compact ? (
1132
+ <IconBrush className="size-3.5" />
1133
+ ) : (
1134
+ t("navigation.brand")
1135
+ )}
1136
+ </TabsTrigger>
1137
+ <TabsTrigger
1138
+ value="comments"
1139
+ aria-label={
1140
+ commentsCount > 0
1141
+ ? t("review.commentsTab", { count: commentsCount })
1142
+ : t("review.comments")
1143
+ }
1144
+ className={cn(
1145
+ "group h-6 min-w-0 rounded-md !text-[11px] font-semibold text-muted-foreground shadow-none transition-colors hover:text-foreground data-[state=active]:bg-[var(--design-editor-panel-raised-bg)] data-[state=active]:text-foreground data-[state=active]:shadow-none",
1146
+ compact ? "w-auto gap-0.5 px-1" : "gap-1 px-1.5",
1147
+ )}
1148
+ >
1149
+ {compact ? (
1150
+ <IconMessageCircle className="size-3.5" />
1151
+ ) : (
1152
+ <span className="truncate">{t("review.comments")}</span>
1153
+ )}
1154
+ {commentsCount > 0 ? (
1155
+ <span
1156
+ className={cn(
1157
+ "flex shrink-0 items-center justify-center rounded-full bg-muted tabular-nums text-muted-foreground group-data-[state=active]:bg-background",
1158
+ compact
1159
+ ? "h-3.5 min-w-3.5 px-0.5 text-[8px]"
1160
+ : "h-4 min-w-4 px-1 text-[9px]",
1161
+ )}
1162
+ >
1163
+ {commentsCount > 99 ? "99+" : commentsCount}
1164
+ </span>
1165
+ ) : null}
1113
1166
  </TabsTrigger>
1114
1167
  <TabsTrigger
1115
1168
  value="tweaks"
1116
- className="h-6 rounded-md px-1.5 !text-[11px] font-semibold text-muted-foreground shadow-none transition-colors hover:text-foreground data-[state=active]:bg-[var(--design-editor-panel-raised-bg)] data-[state=active]:text-foreground data-[state=active]:shadow-none"
1169
+ aria-label={t("designEditor.tweaks")}
1170
+ className={cn(
1171
+ "h-6 rounded-md !text-[11px] font-semibold text-muted-foreground shadow-none transition-colors hover:text-foreground data-[state=active]:bg-[var(--design-editor-panel-raised-bg)] data-[state=active]:text-foreground data-[state=active]:shadow-none",
1172
+ compact ? "w-7 px-0" : "px-1.5",
1173
+ )}
1117
1174
  >
1118
- {t("designEditor.tweaks")}
1175
+ {compact ? (
1176
+ <IconAdjustmentsHorizontal className="size-3.5" />
1177
+ ) : (
1178
+ t("designEditor.tweaks")
1179
+ )}
1119
1180
  </TabsTrigger>
1120
1181
  </TabsList>
1121
1182
  </Tabs>
@@ -1367,6 +1428,8 @@ export const EditPanel = memo(function EditPanel({
1367
1428
  designId,
1368
1429
  onComponentPropApplied,
1369
1430
  reviewPanelProps,
1431
+ reviewCommentsPanelProps,
1432
+ reviewCommentsCount = 0,
1370
1433
  componentNodeId,
1371
1434
  componentSwapPickerRequest,
1372
1435
  sourceCapabilities = [],
@@ -1707,11 +1770,12 @@ export const EditPanel = memo(function EditPanel({
1707
1770
  const userScrollIntentRef = useRef(false);
1708
1771
  const scrollTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
1709
1772
 
1710
- // Figma replaces the entire right panel with the size-preset list while the
1711
- // Frame tool is armed regardless of which inspector tab (Design/Tweaks)
1712
- // was showing beforehand — so this takes priority over `activeTab` below.
1773
+ // Frame presets belong to the Design inspector. Keep Comments and Tweaks
1774
+ // visible when the Frame tool remains armed while another tab is active.
1713
1775
  const showFramePresets =
1714
- activeTool === "frame" && Boolean(onCreateScreenFromPreset);
1776
+ activeTab === "design" &&
1777
+ activeTool === "frame" &&
1778
+ Boolean(onCreateScreenFromPreset);
1715
1779
 
1716
1780
  return (
1717
1781
  <TooltipProvider delayDuration={300} skipDelayDuration={400}>
@@ -1726,6 +1790,8 @@ export const EditPanel = memo(function EditPanel({
1726
1790
  activeTab={activeTab}
1727
1791
  onActiveTabChange={handleActiveTabChange}
1728
1792
  trailing={headerTrailing}
1793
+ commentsCount={reviewCommentsCount}
1794
+ compact={width < 280}
1729
1795
  />
1730
1796
 
1731
1797
  {showFramePresets ? (
@@ -2061,6 +2127,8 @@ export const EditPanel = memo(function EditPanel({
2061
2127
  />
2062
2128
  </div>
2063
2129
  </div>
2130
+ ) : activeTab === "comments" && reviewCommentsPanelProps ? (
2131
+ <ReviewCommentsPanel {...reviewCommentsPanelProps} />
2064
2132
  ) : null}
2065
2133
  </div>
2066
2134
  </TooltipProvider>
@@ -11,9 +11,9 @@ import {
11
11
  IconFrame,
12
12
  IconLayersSubtract,
13
13
  IconLayersUnion,
14
+ IconLayoutGrid,
14
15
  IconLock,
15
16
  IconLockOpen,
16
- IconLayoutGrid,
17
17
  IconPencil,
18
18
  IconPlus,
19
19
  IconSearch,
@@ -30,8 +30,8 @@ import {
30
30
  useMemo,
31
31
  useRef,
32
32
  useState,
33
- type KeyboardEvent,
34
33
  type DragEvent,
34
+ type KeyboardEvent,
35
35
  type MouseEvent,
36
36
  type ReactNode,
37
37
  type Ref,
@@ -2047,7 +2047,7 @@ const LayerRow = memo(function LayerRow({
2047
2047
  aria-expanded={hasChildren ? isExpanded : undefined}
2048
2048
  aria-level={depth + 1}
2049
2049
  aria-selected={selectable ? isSelected : undefined}
2050
- className="relative min-w-full"
2050
+ className="relative w-max min-w-full"
2051
2051
  draggable={draggable}
2052
2052
  onDragStart={handleDragStart}
2053
2053
  onDragOver={handleDragOver}
@@ -2087,7 +2087,7 @@ const LayerRow = memo(function LayerRow({
2087
2087
  ) : null}
2088
2088
  <div
2089
2089
  className={cn(
2090
- "group flex h-8 min-w-full items-center gap-1 rounded-[5px] pr-1 text-[12px]",
2090
+ "group flex h-7 w-max min-w-full items-center gap-1 rounded-[5px] pr-1 text-[12px] bg-[var(--design-editor-panel-bg)]",
2091
2091
  activeDrop === "inside" &&
2092
2092
  "ring-1 ring-inset ring-[var(--design-editor-accent-color)]",
2093
2093
  isSelected &&
@@ -2233,67 +2233,80 @@ const LayerRow = memo(function LayerRow({
2233
2233
  ) : null}
2234
2234
  </button>
2235
2235
 
2236
- {lockable ? (
2237
- <Tooltip>
2238
- <TooltipTrigger asChild>
2239
- <Button
2240
- type="button"
2241
- variant="ghost"
2242
- size="icon"
2243
- className={cn(
2244
- "size-5 shrink-0 rounded-sm p-0 text-muted-foreground opacity-0 hover:bg-transparent hover:text-foreground group-hover:opacity-100 focus-visible:opacity-100",
2245
- node.locked && "opacity-100",
2246
- isSelected && "text-foreground",
2247
- )}
2248
- aria-label={node.locked ? labels.unlock : labels.lock}
2249
- onClick={(event) => {
2250
- event.stopPropagation();
2251
- onToggleLocked?.(node.id, !node.locked);
2252
- }}
2253
- >
2254
- {node.locked ? (
2255
- <IconLock className="size-3" />
2256
- ) : (
2257
- <IconLockOpen className="size-3" />
2258
- )}
2259
- </Button>
2260
- </TooltipTrigger>
2261
- <TooltipContent>
2262
- {node.locked ? labels.unlock : labels.lock}
2263
- </TooltipContent>
2264
- </Tooltip>
2265
- ) : null}
2266
-
2267
- {hideable ? (
2268
- <Tooltip>
2269
- <TooltipTrigger asChild>
2270
- <Button
2271
- type="button"
2272
- variant="ghost"
2273
- size="icon"
2274
- className={cn(
2275
- "size-5 shrink-0 rounded-sm p-0 text-muted-foreground opacity-0 hover:bg-transparent hover:text-foreground group-hover:opacity-100 focus-visible:opacity-100",
2276
- node.hidden && "opacity-100",
2277
- isSelected && "text-foreground",
2278
- )}
2279
- aria-label={node.hidden ? labels.show : labels.hide}
2280
- onClick={(event) => {
2281
- event.stopPropagation();
2282
- onToggleHidden?.(node.id, !node.hidden);
2283
- }}
2284
- >
2285
- {node.hidden ? (
2286
- <IconEyeOff className="size-3" />
2287
- ) : (
2288
- <IconEye className="size-3" />
2289
- )}
2290
- </Button>
2291
- </TooltipTrigger>
2292
- <TooltipContent>
2293
- {node.hidden ? labels.show : labels.hide}
2294
- </TooltipContent>
2295
- </Tooltip>
2296
- ) : null}
2236
+ {(lockable || hideable) && (
2237
+ <div
2238
+ className={cn(
2239
+ "sticky right-0 z-10 ml-auto flex shrink-0 items-center gap-1 bg-inherit",
2240
+ node.locked || node.hidden
2241
+ ? "w-auto overflow-visible pl-2 pr-1"
2242
+ : "w-0 overflow-hidden pl-0 pr-0 group-hover:w-auto group-hover:overflow-visible group-hover:pl-2 group-hover:pr-1 focus-within:w-auto focus-within:overflow-visible focus-within:pl-2 focus-within:pr-1",
2243
+ )}
2244
+ >
2245
+ <div className="absolute inset-0 -z-20 bg-[var(--design-editor-panel-bg)]" />
2246
+ <div className="absolute inset-0 -z-10 bg-inherit" />
2247
+ {lockable ? (
2248
+ <Tooltip>
2249
+ <TooltipTrigger asChild>
2250
+ <Button
2251
+ type="button"
2252
+ variant="ghost"
2253
+ size="icon"
2254
+ className={cn(
2255
+ "size-5 shrink-0 rounded-sm p-0 text-muted-foreground opacity-0 hover:bg-transparent hover:text-foreground group-hover:opacity-100 focus-visible:opacity-100",
2256
+ node.locked && "opacity-100",
2257
+ isSelected && "text-foreground",
2258
+ )}
2259
+ aria-label={node.locked ? labels.unlock : labels.lock}
2260
+ onClick={(event) => {
2261
+ event.stopPropagation();
2262
+ onToggleLocked?.(node.id, !node.locked);
2263
+ }}
2264
+ >
2265
+ {node.locked ? (
2266
+ <IconLock className="size-3" />
2267
+ ) : (
2268
+ <IconLockOpen className="size-3" />
2269
+ )}
2270
+ </Button>
2271
+ </TooltipTrigger>
2272
+ <TooltipContent>
2273
+ {node.locked ? labels.unlock : labels.lock}
2274
+ </TooltipContent>
2275
+ </Tooltip>
2276
+ ) : null}
2277
+
2278
+ {hideable ? (
2279
+ <Tooltip>
2280
+ <TooltipTrigger asChild>
2281
+ <Button
2282
+ type="button"
2283
+ variant="ghost"
2284
+ size="icon"
2285
+ className={cn(
2286
+ "size-5 shrink-0 rounded-sm p-0 text-muted-foreground opacity-0 hover:bg-transparent hover:text-foreground group-hover:opacity-100 focus-visible:opacity-100",
2287
+ node.hidden && "opacity-100",
2288
+ isSelected && "text-foreground",
2289
+ )}
2290
+ aria-label={node.hidden ? labels.show : labels.hide}
2291
+ onClick={(event) => {
2292
+ event.stopPropagation();
2293
+ onToggleHidden?.(node.id, !node.hidden);
2294
+ }}
2295
+ >
2296
+ {node.hidden ? (
2297
+ <IconEyeOff className="size-3" />
2298
+ ) : (
2299
+ <IconEye className="size-3" />
2300
+ )}
2301
+ </Button>
2302
+ </TooltipTrigger>
2303
+ <TooltipContent>
2304
+ {node.hidden ? labels.show : labels.hide}
2305
+ </TooltipContent>
2306
+ </Tooltip>
2307
+ ) : null}
2308
+ </div>
2309
+ )}
2297
2310
  </div>
2298
2311
  </div>
2299
2312
  </ContextMenuTrigger>