@agent-native/core 0.102.1 → 0.103.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (295) hide show
  1. package/corpus/README.md +2 -2
  2. package/corpus/core/CHANGELOG.md +15 -0
  3. package/corpus/core/docs/content/local-file-mode.mdx +99 -489
  4. package/corpus/core/docs/content/locales/ar-SA/local-file-mode.mdx +35 -490
  5. package/corpus/core/docs/content/locales/ar-SA/template-content.mdx +10 -24
  6. package/corpus/core/docs/content/locales/de-DE/local-file-mode.mdx +37 -491
  7. package/corpus/core/docs/content/locales/de-DE/template-content.mdx +10 -24
  8. package/corpus/core/docs/content/locales/es-ES/local-file-mode.mdx +35 -493
  9. package/corpus/core/docs/content/locales/es-ES/template-content.mdx +10 -24
  10. package/corpus/core/docs/content/locales/fr-FR/local-file-mode.mdx +38 -491
  11. package/corpus/core/docs/content/locales/fr-FR/template-content.mdx +10 -24
  12. package/corpus/core/docs/content/locales/hi-IN/local-file-mode.mdx +33 -492
  13. package/corpus/core/docs/content/locales/hi-IN/template-content.mdx +10 -24
  14. package/corpus/core/docs/content/locales/ja-JP/local-file-mode.mdx +36 -492
  15. package/corpus/core/docs/content/locales/ja-JP/template-content.mdx +10 -24
  16. package/corpus/core/docs/content/locales/ko-KR/local-file-mode.mdx +35 -490
  17. package/corpus/core/docs/content/locales/ko-KR/template-content.mdx +10 -24
  18. package/corpus/core/docs/content/locales/pt-BR/local-file-mode.mdx +35 -493
  19. package/corpus/core/docs/content/locales/pt-BR/template-content.mdx +10 -24
  20. package/corpus/core/docs/content/locales/zh-CN/local-file-mode.mdx +31 -489
  21. package/corpus/core/docs/content/locales/zh-CN/template-content.mdx +9 -24
  22. package/corpus/core/docs/content/locales/zh-TW/local-file-mode.mdx +31 -489
  23. package/corpus/core/docs/content/locales/zh-TW/template-content.mdx +9 -24
  24. package/corpus/core/docs/content/template-content.mdx +26 -42
  25. package/corpus/core/package.json +1 -1
  26. package/corpus/core/src/cli/content-local.ts +86 -18
  27. package/corpus/core/src/cli/index.ts +2 -2
  28. package/corpus/core/src/cli/skills-content/content-skill.ts +36 -25
  29. package/corpus/core/src/cli/skills.ts +47 -13
  30. package/corpus/core/src/client/AgentPanel.tsx +7 -0
  31. package/corpus/core/src/client/AssistantChat.tsx +7 -0
  32. package/corpus/core/src/client/agent-chat-adapter.ts +7 -1
  33. package/corpus/core/src/client/chat/message-components.tsx +17 -3
  34. package/corpus/core/src/client/composer/ComposerPlusMenu.tsx +96 -6
  35. package/corpus/core/src/client/composer/asset-picker-url.ts +80 -0
  36. package/corpus/core/src/client/error-format.ts +24 -0
  37. package/corpus/core/src/client/resources/McpIntegrationDialog.tsx +8 -1
  38. package/corpus/core/src/local-artifacts/index.ts +65 -0
  39. package/corpus/templates/assets/app/components/library/GenerationPresetsPanel.tsx +325 -0
  40. package/corpus/templates/assets/app/hooks/use-navigation-state.ts +12 -0
  41. package/corpus/templates/assets/app/i18n/zh-TW.ts +21 -0
  42. package/corpus/templates/assets/app/i18n-data.ts +215 -0
  43. package/corpus/templates/assets/app/routes/brand-kits.$id.tsx +19 -479
  44. package/corpus/templates/assets/app/routes/brand-kits.$id_.presets.$presetId.tsx +1 -1
  45. package/corpus/templates/assets/app/routes/brand-kits.$id_.settings.tsx +446 -0
  46. package/corpus/templates/assets/app/routes/library.tsx +69 -0
  47. package/corpus/templates/assets/changelog/2026-07-15-fixed-top-level-image-picker-selections-returning-to-the-com.md +6 -0
  48. package/corpus/templates/clips/actions/disconnect-calendar.ts +57 -9
  49. package/corpus/templates/clips/actions/generate-workflow.ts +102 -59
  50. package/corpus/templates/clips/actions/get-recording-player-data.ts +64 -1
  51. package/corpus/templates/clips/actions/regenerate-summary.ts +7 -0
  52. package/corpus/templates/clips/actions/regenerate-title.ts +29 -11
  53. package/corpus/templates/clips/app/components/editor/editor-layout.tsx +34 -13
  54. package/corpus/templates/clips/app/components/editor/thumbnail-picker.tsx +87 -9
  55. package/corpus/templates/clips/app/components/editor/trim-handles.tsx +15 -0
  56. package/corpus/templates/clips/app/components/editor/waveform.tsx +21 -8
  57. package/corpus/templates/clips/app/components/library/folder-tree.tsx +52 -0
  58. package/corpus/templates/clips/app/components/player/settings-panel.tsx +116 -58
  59. package/corpus/templates/clips/app/components/player/share-dialog.tsx +43 -37
  60. package/corpus/templates/clips/app/components/player/video-player.tsx +50 -2
  61. package/corpus/templates/clips/app/components/recorder/microphone-visualizer.tsx +22 -3
  62. package/corpus/templates/clips/app/i18n/ar-SA.ts +5 -2
  63. package/corpus/templates/clips/app/i18n/de-DE.ts +6 -2
  64. package/corpus/templates/clips/app/i18n/en-US.ts +5 -2
  65. package/corpus/templates/clips/app/i18n/es-ES.ts +6 -2
  66. package/corpus/templates/clips/app/i18n/fr-FR.ts +5 -2
  67. package/corpus/templates/clips/app/i18n/hi-IN.ts +5 -2
  68. package/corpus/templates/clips/app/i18n/ja-JP.ts +6 -1
  69. package/corpus/templates/clips/app/i18n/ko-KR.ts +5 -2
  70. package/corpus/templates/clips/app/i18n/pt-BR.ts +6 -2
  71. package/corpus/templates/clips/app/i18n/zh-CN.ts +5 -2
  72. package/corpus/templates/clips/app/i18n/zh-TW.ts +5 -2
  73. package/corpus/templates/clips/app/lib/timestamp-mapping.ts +14 -0
  74. package/corpus/templates/clips/app/routes/_app.library._index.tsx +1 -2
  75. package/corpus/templates/clips/app/routes/_index.tsx +1 -2
  76. package/corpus/templates/clips/app/routes/r.$recordingId.tsx +98 -32
  77. package/corpus/templates/clips/app/routes/share.$shareId.tsx +4 -1
  78. package/corpus/templates/clips/changelog/2026-07-15-ai-workflow-generation-now-stays-visible-avoids-duplicate-re.md +6 -0
  79. package/corpus/templates/clips/changelog/2026-07-15-clip-playback-and-cta-controls-remain-interactive-through-ed.md +6 -0
  80. package/corpus/templates/clips/changelog/2026-07-15-clip-titles-no-longer-describe-the-product-as-a-loom-alterna.md +6 -0
  81. package/corpus/templates/clips/changelog/2026-07-15-description-regeneration-now-opens-the-agent-chat-so-progres.md +6 -0
  82. package/corpus/templates/clips/changelog/2026-07-15-direct-recording-urls-now-respect-share-link-and-password-ac.md +6 -0
  83. package/corpus/templates/clips/changelog/2026-07-15-disconnecting-a-calendar-now-clears-unrecorded-synced-meetin.md +6 -0
  84. package/corpus/templates/clips/changelog/2026-07-15-folders-now-expose-rename-and-delete-actions-directly-in-the.md +6 -0
  85. package/corpus/templates/clips/changelog/2026-07-15-recording-pages-now-explain-sign-in-access-and-avoid-showing.md +6 -0
  86. package/corpus/templates/clips/changelog/2026-07-15-the-clips-extension-quick-actions-toolbar-can-be-moved-out-o.md +6 -0
  87. package/corpus/templates/clips/changelog/2026-07-15-the-editor-now-skips-cut-sections-during-preview-and-keeps-t.md +6 -0
  88. package/corpus/templates/clips/changelog/2026-07-15-thumbnail-capture-now-updates-previews-while-scrubbing-and-l.md +6 -0
  89. package/corpus/templates/clips/changelog/2026-07-15-windows-permission-links-open-the-matching-settings-page.md +6 -0
  90. package/corpus/templates/clips/chrome-extension/src/content-script.ts +117 -2
  91. package/corpus/templates/clips/chrome-extension/src/overlay.ts +27 -0
  92. package/corpus/templates/clips/desktop/src-tauri/tauri.conf.json +1 -1
  93. package/corpus/templates/clips/server/lib/calendar-event-meetings.ts +139 -101
  94. package/corpus/templates/clips/server/lib/recording-page-access.ts +35 -0
  95. package/corpus/templates/clips/server/lib/share-password.ts +6 -3
  96. package/corpus/templates/content/.agents/skills/content/SKILL.md +26 -39
  97. package/corpus/templates/content/AGENTS.md +25 -30
  98. package/corpus/templates/content/actions/_builder-docs-client.ts +23 -0
  99. package/corpus/templates/content/actions/_content-database-source-adapters.ts +21 -3
  100. package/corpus/templates/content/actions/_content-files.ts +338 -0
  101. package/corpus/templates/content/actions/_content-space-access.ts +135 -0
  102. package/corpus/templates/content/actions/_content-spaces.ts +640 -0
  103. package/corpus/templates/content/actions/_database-source-utils.ts +90 -7
  104. package/corpus/templates/content/actions/_database-utils.ts +7 -1
  105. package/corpus/templates/content/actions/_local-file-documents.ts +0 -9
  106. package/corpus/templates/content/actions/_local-folder-source.ts +53 -0
  107. package/corpus/templates/content/actions/_property-utils.ts +9 -4
  108. package/corpus/templates/content/actions/add-database-item.ts +108 -65
  109. package/corpus/templates/content/actions/backfill-content-files.ts +22 -0
  110. package/corpus/templates/content/actions/connect-local-folder-source.ts +221 -0
  111. package/corpus/templates/content/actions/create-content-database.ts +129 -3
  112. package/corpus/templates/content/actions/create-document.ts +65 -55
  113. package/corpus/templates/content/actions/create-inline-content-database.ts +6 -1
  114. package/corpus/templates/content/actions/delete-content-database.ts +3 -0
  115. package/corpus/templates/content/actions/delete-document.ts +7 -11
  116. package/corpus/templates/content/actions/disconnect-local-folder-source.ts +175 -0
  117. package/corpus/templates/content/actions/duplicate-database-item.ts +10 -0
  118. package/corpus/templates/content/actions/duplicate-database-items.ts +13 -0
  119. package/corpus/templates/content/actions/edit-document.ts +2 -28
  120. package/corpus/templates/content/actions/ensure-content-spaces.ts +26 -0
  121. package/corpus/templates/content/actions/export-content-source.ts +47 -9
  122. package/corpus/templates/content/actions/get-document.ts +0 -14
  123. package/corpus/templates/content/actions/import-content-source.ts +43 -3
  124. package/corpus/templates/content/actions/list-content-spaces.ts +103 -0
  125. package/corpus/templates/content/actions/list-documents.ts +12 -9
  126. package/corpus/templates/content/actions/move-document.ts +3 -14
  127. package/corpus/templates/content/actions/pull-document.ts +0 -23
  128. package/corpus/templates/content/actions/remove-local-file-source.ts +50 -29
  129. package/corpus/templates/content/actions/resolve-local-folder-conflict.ts +442 -0
  130. package/corpus/templates/content/actions/reveal-local-source-file.ts +6 -17
  131. package/corpus/templates/content/actions/search-documents.ts +0 -34
  132. package/corpus/templates/content/actions/share-local-file-document.ts +25 -1
  133. package/corpus/templates/content/actions/submit-content-database-form.ts +12 -0
  134. package/corpus/templates/content/actions/sync-local-folder-source.ts +731 -0
  135. package/corpus/templates/content/actions/sync-manifest-local-folder-source.ts +123 -0
  136. package/corpus/templates/content/actions/update-content-database-view.ts +10 -1
  137. package/corpus/templates/content/actions/update-document.ts +0 -15
  138. package/corpus/templates/content/actions/view-screen.ts +2 -50
  139. package/corpus/templates/content/app/components/editor/SlashCommandMenu.tsx +76 -62
  140. package/corpus/templates/content/app/components/editor/database/DatabaseView.tsx +70 -22
  141. package/corpus/templates/content/app/components/editor/database/grouping.ts +2 -1
  142. package/corpus/templates/content/app/components/editor/database/settings.tsx +23 -20
  143. package/corpus/templates/content/app/components/editor/database/shared.tsx +2 -0
  144. package/corpus/templates/content/app/components/editor/database/sidebar.tsx +330 -0
  145. package/corpus/templates/content/app/components/editor/database/types.ts +1 -0
  146. package/corpus/templates/content/app/components/editor/database/view-config.ts +3 -1
  147. package/corpus/templates/content/app/components/layout/Layout.tsx +25 -1
  148. package/corpus/templates/content/app/components/sidebar/DocumentSidebar.tsx +209 -113
  149. package/corpus/templates/content/app/components/sidebar/select-content-space.ts +31 -0
  150. package/corpus/templates/content/app/hooks/use-content-database.ts +16 -0
  151. package/corpus/templates/content/app/hooks/use-content-spaces.ts +39 -0
  152. package/corpus/templates/content/app/i18n/zh-TW.ts +11 -0
  153. package/corpus/templates/content/app/i18n-data.ts +75 -0
  154. package/corpus/templates/content/app/routes/_app.local-files.tsx +174 -65
  155. package/corpus/templates/content/changelog/2026-07-16-content-callouts-can-now-be-reviewed-and-published-to-builder.md +6 -0
  156. package/corpus/templates/content/changelog/2026-07-16-heading-5-and-heading-6-are-available-from-the-editor-slash-.md +6 -0
  157. package/corpus/templates/content/changelog/2026-07-16-organize-every-workspace-through-a-customizable-files-databa.md +6 -0
  158. package/corpus/templates/content/parity/matrix.md +2 -1
  159. package/corpus/templates/content/parity/matrix.ts +37 -1
  160. package/corpus/templates/content/scripts/dev-database.mjs +7 -5
  161. package/corpus/templates/content/server/db/schema.ts +113 -40
  162. package/corpus/templates/content/server/lib/document-context.ts +15 -1
  163. package/corpus/templates/content/server/lib/notion-sync.ts +6 -0
  164. package/corpus/templates/content/server/plugins/db.ts +153 -0
  165. package/corpus/templates/content/shared/api.ts +17 -3
  166. package/corpus/templates/content/shared/builder-mdx.ts +163 -16
  167. package/corpus/templates/design/.agents/skills/design-templates/SKILL.md +59 -0
  168. package/corpus/templates/design/AGENTS.md +6 -1
  169. package/corpus/templates/design/actions/create-design-from-template.ts +19 -7
  170. package/corpus/templates/design/actions/list-design-templates.ts +69 -21
  171. package/corpus/templates/design/actions/navigate.ts +2 -2
  172. package/corpus/templates/design/actions/view-screen.ts +15 -2
  173. package/corpus/templates/design/agent-native.app-skill.json +5 -0
  174. package/corpus/templates/design/app/components/design/design-canvas/external-preview.ts +7 -3
  175. package/corpus/templates/design/app/components/editor/PromptDialog.tsx +281 -56
  176. package/corpus/templates/design/app/components/templates/TemplatePreview.tsx +14 -2
  177. package/corpus/templates/design/app/hooks/use-navigation-state.ts +3 -2
  178. package/corpus/templates/design/app/i18n/zh-TW.ts +3 -3
  179. package/corpus/templates/design/app/i18n-data.ts +21 -2
  180. package/corpus/templates/design/app/i18n-template-feature.ts +218 -10
  181. package/corpus/templates/design/app/pages/Index.tsx +195 -24
  182. package/corpus/templates/design/app/pages/Templates.tsx +144 -55
  183. package/corpus/templates/design/app/pages/design-editor/generation-prompt-directives.ts +12 -1
  184. package/corpus/templates/design/changelog/2026-07-14-templates-now-appear-in-the-new-design-picker-with-previews-.md +6 -0
  185. package/corpus/templates/design/changelog/2026-07-15-prototype-print-and-download-buttons-now-work-in-preview.md +6 -0
  186. package/corpus/templates/design/changelog/2026-07-15-templates-now-open-immediately-after-copying-even-while-the-.md +6 -0
  187. package/corpus/templates/design/server/plugins/agent-chat.ts +1 -1
  188. package/corpus/templates/mail/AGENTS.md +23 -18
  189. package/corpus/templates/mail/actions/bulk-archive.ts +32 -28
  190. package/corpus/templates/mail/actions/mark-read.ts +131 -20
  191. package/corpus/templates/mail/actions/mark-thread-read.ts +1 -1
  192. package/corpus/templates/mail/actions/move-email.ts +30 -24
  193. package/corpus/templates/mail/actions/send-email.ts +73 -68
  194. package/corpus/templates/mail/changelog/2026-07-15-unread-inbox-cleanup-now-completes-reliably.md +6 -0
  195. package/corpus/templates/mail/server/handlers/emails.ts +218 -209
  196. package/corpus/templates/mail/server/lib/bulk-mark-read.ts +30 -0
  197. package/corpus/templates/mail/server/lib/email-state.ts +198 -113
  198. package/corpus/templates/mail/server/lib/google-auth.ts +218 -25
  199. package/corpus/templates/mail/server/lib/jobs.ts +69 -74
  200. package/corpus/templates/mail/server/lib/local-email-store.ts +265 -0
  201. package/corpus/templates/mail/server/plugins/agent-chat.ts +6 -0
  202. package/corpus/templates/slides/actions/extract-pdf.ts +1 -1
  203. package/corpus/templates/slides/actions/import-file.ts +4 -1
  204. package/corpus/templates/slides/app/components/editor/ImageGenPanel.tsx +1 -1
  205. package/corpus/templates/slides/app/components/editor/ImageSearchPanel.tsx +9 -12
  206. package/corpus/templates/slides/app/components/editor/SlideEditor.tsx +29 -21
  207. package/corpus/templates/slides/app/i18n/ar-SA.ts +1 -0
  208. package/corpus/templates/slides/app/i18n/de-DE.ts +1 -0
  209. package/corpus/templates/slides/app/i18n/en-US.ts +1 -0
  210. package/corpus/templates/slides/app/i18n/es-ES.ts +1 -0
  211. package/corpus/templates/slides/app/i18n/fr-FR.ts +1 -0
  212. package/corpus/templates/slides/app/i18n/hi-IN.ts +1 -0
  213. package/corpus/templates/slides/app/i18n/ja-JP.ts +1 -0
  214. package/corpus/templates/slides/app/i18n/ko-KR.ts +1 -0
  215. package/corpus/templates/slides/app/i18n/pt-BR.ts +1 -0
  216. package/corpus/templates/slides/app/i18n/zh-CN.ts +1 -0
  217. package/corpus/templates/slides/app/i18n/zh-TW.ts +1 -0
  218. package/corpus/templates/slides/changelog/2026-07-15-image-search-and-generation-controls-now-use-the-registered-.md +6 -0
  219. package/corpus/templates/slides/changelog/2026-07-15-pdf-deck-references-can-be-imported-for-slide-inspiration-ag.md +6 -0
  220. package/corpus/templates/slides/changelog/2026-07-15-stable-style-inspector-dock.md +6 -0
  221. package/dist/cli/content-local.d.ts +1 -0
  222. package/dist/cli/content-local.d.ts.map +1 -1
  223. package/dist/cli/content-local.js +75 -17
  224. package/dist/cli/content-local.js.map +1 -1
  225. package/dist/cli/index.js +2 -2
  226. package/dist/cli/index.js.map +1 -1
  227. package/dist/cli/skills-content/content-skill.d.ts +1 -1
  228. package/dist/cli/skills-content/content-skill.d.ts.map +1 -1
  229. package/dist/cli/skills-content/content-skill.js +36 -25
  230. package/dist/cli/skills-content/content-skill.js.map +1 -1
  231. package/dist/cli/skills.d.ts.map +1 -1
  232. package/dist/cli/skills.js +47 -14
  233. package/dist/cli/skills.js.map +1 -1
  234. package/dist/client/AgentPanel.d.ts.map +1 -1
  235. package/dist/client/AgentPanel.js +5 -0
  236. package/dist/client/AgentPanel.js.map +1 -1
  237. package/dist/client/AssistantChat.d.ts.map +1 -1
  238. package/dist/client/AssistantChat.js +7 -0
  239. package/dist/client/AssistantChat.js.map +1 -1
  240. package/dist/client/agent-chat-adapter.d.ts.map +1 -1
  241. package/dist/client/agent-chat-adapter.js +8 -1
  242. package/dist/client/agent-chat-adapter.js.map +1 -1
  243. package/dist/client/chat/message-components.d.ts +4 -0
  244. package/dist/client/chat/message-components.d.ts.map +1 -1
  245. package/dist/client/chat/message-components.js +10 -3
  246. package/dist/client/chat/message-components.js.map +1 -1
  247. package/dist/client/composer/ComposerPlusMenu.d.ts.map +1 -1
  248. package/dist/client/composer/ComposerPlusMenu.js +58 -6
  249. package/dist/client/composer/ComposerPlusMenu.js.map +1 -1
  250. package/dist/client/composer/asset-picker-url.d.ts +16 -0
  251. package/dist/client/composer/asset-picker-url.d.ts.map +1 -0
  252. package/dist/client/composer/asset-picker-url.js +64 -0
  253. package/dist/client/composer/asset-picker-url.js.map +1 -0
  254. package/dist/client/error-format.d.ts.map +1 -1
  255. package/dist/client/error-format.js +17 -0
  256. package/dist/client/error-format.js.map +1 -1
  257. package/dist/client/resources/McpIntegrationDialog.d.ts.map +1 -1
  258. package/dist/client/resources/McpIntegrationDialog.js +6 -1
  259. package/dist/client/resources/McpIntegrationDialog.js.map +1 -1
  260. package/dist/collab/awareness.d.ts +2 -2
  261. package/dist/collab/awareness.d.ts.map +1 -1
  262. package/dist/collab/struct-routes.d.ts +1 -1
  263. package/dist/local-artifacts/index.d.ts +10 -0
  264. package/dist/local-artifacts/index.d.ts.map +1 -1
  265. package/dist/local-artifacts/index.js +39 -0
  266. package/dist/local-artifacts/index.js.map +1 -1
  267. package/dist/notifications/routes.d.ts +1 -1
  268. package/dist/provider-api/corpus-jobs.d.ts +2 -2
  269. package/dist/resources/handlers.d.ts +3 -3
  270. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  271. package/dist/server/transcribe-voice.d.ts +1 -1
  272. package/docs/content/local-file-mode.mdx +99 -489
  273. package/docs/content/locales/ar-SA/local-file-mode.mdx +35 -490
  274. package/docs/content/locales/ar-SA/template-content.mdx +10 -24
  275. package/docs/content/locales/de-DE/local-file-mode.mdx +37 -491
  276. package/docs/content/locales/de-DE/template-content.mdx +10 -24
  277. package/docs/content/locales/es-ES/local-file-mode.mdx +35 -493
  278. package/docs/content/locales/es-ES/template-content.mdx +10 -24
  279. package/docs/content/locales/fr-FR/local-file-mode.mdx +38 -491
  280. package/docs/content/locales/fr-FR/template-content.mdx +10 -24
  281. package/docs/content/locales/hi-IN/local-file-mode.mdx +33 -492
  282. package/docs/content/locales/hi-IN/template-content.mdx +10 -24
  283. package/docs/content/locales/ja-JP/local-file-mode.mdx +36 -492
  284. package/docs/content/locales/ja-JP/template-content.mdx +10 -24
  285. package/docs/content/locales/ko-KR/local-file-mode.mdx +35 -490
  286. package/docs/content/locales/ko-KR/template-content.mdx +10 -24
  287. package/docs/content/locales/pt-BR/local-file-mode.mdx +35 -493
  288. package/docs/content/locales/pt-BR/template-content.mdx +10 -24
  289. package/docs/content/locales/zh-CN/local-file-mode.mdx +31 -489
  290. package/docs/content/locales/zh-CN/template-content.mdx +9 -24
  291. package/docs/content/locales/zh-TW/local-file-mode.mdx +31 -489
  292. package/docs/content/locales/zh-TW/template-content.mdx +9 -24
  293. package/docs/content/template-content.mdx +26 -42
  294. package/package.json +1 -1
  295. package/corpus/templates/assets/app/components/library/EditLibraryDialog.tsx +0 -126
@@ -3,37 +3,148 @@ import { writeAppState } from "@agent-native/core/application-state";
3
3
  import { getRequestUserEmail } from "@agent-native/core/server";
4
4
  import { z } from "zod";
5
5
 
6
- import { markRead } from "../server/lib/email-state.js";
6
+ import { markAllLocalUnreadRead, markRead } from "../server/lib/email-state.js";
7
7
  import {
8
8
  gmailBatchModifyByAccount,
9
9
  isConnected,
10
+ markAllUnreadReadForAccount,
10
11
  } from "../server/lib/google-auth.js";
11
12
 
13
+ export const MARK_READ_DESCRIPTION =
14
+ 'Mark explicit email IDs as read/unread, or use scope "all-unread" once to mark every unread message in one account read while preserving excluded thread IDs. Never loop mark-thread-read for broad cleanup.';
15
+
12
16
  export default defineAction({
13
- description: "Mark one or more emails as read or unread.",
14
- schema: z.object({
15
- id: z.string().optional().describe("Email ID(s), comma-separated"),
16
- unread: z.coerce
17
- .boolean()
18
- .optional()
19
- .describe("Set to true to mark as unread instead of read"),
20
- accountEmail: z
21
- .string()
22
- .optional()
23
- .describe("Specific connected account to use"),
24
- accountEmails: z
25
- .string()
26
- .optional()
27
- .describe(
28
- "Per-id account emails, comma-separated and positionally matched to --id (bulk UI calls only)",
29
- ),
30
- }),
17
+ description: MARK_READ_DESCRIPTION,
18
+ schema: z
19
+ .object({
20
+ id: z.string().optional().describe("Email ID(s), comma-separated"),
21
+ unread: z.coerce
22
+ .boolean()
23
+ .optional()
24
+ .describe("Set to true to mark explicit IDs unread instead of read"),
25
+ accountEmail: z
26
+ .string()
27
+ .optional()
28
+ .describe(
29
+ 'Exact connected account; required when scope is "all-unread"',
30
+ ),
31
+ accountEmails: z
32
+ .string()
33
+ .optional()
34
+ .describe(
35
+ "Per-id account emails, comma-separated and positionally matched to --id (bulk UI calls only)",
36
+ ),
37
+ scope: z
38
+ .enum(["all-unread"])
39
+ .optional()
40
+ .describe(
41
+ 'Mark every unread message in accountEmail read in one verified action; mutually exclusive with "id"',
42
+ ),
43
+ excludeThreadIds: z
44
+ .string()
45
+ .optional()
46
+ .describe(
47
+ 'Thread IDs to leave unread, comma-separated; valid only with scope "all-unread"',
48
+ ),
49
+ })
50
+ .superRefine((args, ctx) => {
51
+ const hasIds = Boolean(args.id?.trim());
52
+ const hasScope = Boolean(args.scope);
53
+ if (hasIds === hasScope) {
54
+ ctx.addIssue({
55
+ code: "custom",
56
+ message: 'Provide exactly one of "id" or "scope"',
57
+ });
58
+ }
59
+ if (hasScope && !args.accountEmail?.trim()) {
60
+ ctx.addIssue({
61
+ code: "custom",
62
+ path: ["accountEmail"],
63
+ message: 'accountEmail is required for scope "all-unread"',
64
+ });
65
+ }
66
+ if (hasScope && args.accountEmails) {
67
+ ctx.addIssue({
68
+ code: "custom",
69
+ path: ["accountEmails"],
70
+ message: 'accountEmails cannot be used with scope "all-unread"',
71
+ });
72
+ }
73
+ if (hasScope && args.unread === true) {
74
+ ctx.addIssue({
75
+ code: "custom",
76
+ path: ["unread"],
77
+ message: 'scope "all-unread" can only mark messages read',
78
+ });
79
+ }
80
+ if (hasIds && args.excludeThreadIds) {
81
+ ctx.addIssue({
82
+ code: "custom",
83
+ path: ["excludeThreadIds"],
84
+ message: "excludeThreadIds can only be used with bulk scope",
85
+ });
86
+ }
87
+ }),
31
88
  run: async (args) => {
32
89
  const ids = args.id
33
90
  ?.split(",")
34
91
  .map((s) => s.trim())
35
92
  .filter(Boolean);
36
- if (!ids || ids.length === 0) throw new Error("--id is required");
93
+ const hasIds = Boolean(ids?.length);
94
+ const hasScope = args.scope === "all-unread";
95
+ if (hasIds === hasScope) {
96
+ throw new Error('Provide exactly one of "id" or "scope"');
97
+ }
98
+
99
+ if (hasScope) {
100
+ if (!args.accountEmail?.trim()) {
101
+ throw new Error('accountEmail is required for scope "all-unread"');
102
+ }
103
+ if (args.accountEmails) {
104
+ throw new Error('accountEmails cannot be used with scope "all-unread"');
105
+ }
106
+ if (args.unread === true) {
107
+ throw new Error('scope "all-unread" can only mark messages read');
108
+ }
109
+
110
+ const ownerEmail = getRequestUserEmail();
111
+ if (!ownerEmail) throw new Error("no authenticated user");
112
+ const excludeThreadIds = (args.excludeThreadIds ?? "")
113
+ .split(",")
114
+ .map((value) => value.trim())
115
+ .filter(Boolean);
116
+ const input = {
117
+ ownerEmail,
118
+ accountEmail: args.accountEmail.trim(),
119
+ excludeThreadIds,
120
+ };
121
+ let result;
122
+ try {
123
+ result = (await isConnected(ownerEmail))
124
+ ? await markAllUnreadReadForAccount(input)
125
+ : await markAllLocalUnreadRead(input);
126
+ } finally {
127
+ // A provider verification read can fail after Gmail accepted the
128
+ // mutation. Always make the UI discard its pre-mutation list cache.
129
+ await writeAppState("refresh-signal", { ts: Date.now() });
130
+ }
131
+
132
+ if (!result.verificationComplete) {
133
+ const verificationDetail = result.verificationError
134
+ ? `verification failed: ${result.verificationError}`
135
+ : `${result.unexpectedUnreadMessages} unexpected unread messages remain`;
136
+ const error = new Error(
137
+ `Bulk mark-read incomplete for ${result.accountEmail}: matched ${result.matchedMessages}, excluded ${result.excludedMessages}, changed ${result.changedMessages}; ${result.failures.length} failed and ${verificationDetail}`,
138
+ ) as Error & { details?: typeof result };
139
+ error.details = result;
140
+ throw error;
141
+ }
142
+ return result;
143
+ }
144
+
145
+ if (!ids || ids.length === 0) {
146
+ throw new Error('Provide exactly one of "id" or "scope"');
147
+ }
37
148
  const isRead = args.unread !== true;
38
149
 
39
150
  const ownerEmail = getRequestUserEmail();
@@ -7,7 +7,7 @@ import { markThreadRead } from "../server/lib/email-state.js";
7
7
 
8
8
  export default defineAction({
9
9
  description:
10
- "Mark all messages in a thread as read or unread. Prefer this over mark-read when acting on a whole conversation.",
10
+ 'Mark one conversation thread as read or unread. For broad unread cleanup across many threads, call mark-read once with scope "all-unread" instead of looping this action.',
11
11
  schema: z.object({
12
12
  threadId: z.string().describe("Thread ID to mark read/unread"),
13
13
  unread: z.coerce
@@ -1,7 +1,6 @@
1
1
  import { defineAction } from "@agent-native/core";
2
2
  import { writeAppState } from "@agent-native/core/application-state";
3
3
  import { getRequestUserEmail } from "@agent-native/core/server";
4
- import { getUserSetting, putUserSetting } from "@agent-native/core/settings";
5
4
  import { z } from "zod";
6
5
 
7
6
  import {
@@ -10,6 +9,11 @@ import {
10
9
  gmailModifyThread,
11
10
  } from "../server/lib/google-api.js";
12
11
  import { isConnected } from "../server/lib/google-auth.js";
12
+ import {
13
+ readLocalEmails,
14
+ withLocalEmailMutationLock,
15
+ writeLocalEmails,
16
+ } from "../server/lib/local-email-store.js";
13
17
  import { getAccessTokens } from "./helpers.js";
14
18
 
15
19
  type GmailLabel = { id?: string; name?: string };
@@ -80,31 +84,33 @@ export default defineAction({
80
84
  if (!ownerEmail) throw new Error("no authenticated user");
81
85
 
82
86
  if (!(await isConnected(ownerEmail))) {
83
- const data = await getUserSetting(ownerEmail, "local-emails");
84
- const emails =
85
- data && Array.isArray((data as any).emails) ? (data as any).emails : [];
86
- const idSet = new Set(ids);
87
- const targetThreads = new Set<string>();
88
- for (const email of emails) {
89
- if (idSet.has(email.id)) targetThreads.add(email.threadId || email.id);
90
- }
87
+ const changed = await withLocalEmailMutationLock(ownerEmail, async () => {
88
+ const emails = await readLocalEmails(ownerEmail);
89
+ const idSet = new Set(ids);
90
+ const targetThreads = new Set<string>();
91
+ for (const email of emails) {
92
+ if (idSet.has(email.id))
93
+ targetThreads.add(email.threadId || email.id);
94
+ }
91
95
 
92
- let changed = 0;
93
- const updated = emails.map((email: any) => {
94
- if (!targetThreads.has(email.threadId || email.id)) return email;
95
- changed++;
96
- const labelIds = new Set<string>(email.labelIds ?? []);
97
- labelIds.delete("inbox");
98
- if (args.removeLabel) labelIds.delete(args.removeLabel);
99
- labelIds.add(targetLabel);
100
- return {
101
- ...email,
102
- isArchived: true,
103
- labelIds: [...labelIds],
104
- };
96
+ let changed = 0;
97
+ const updated = emails.map((email) => {
98
+ if (!targetThreads.has(email.threadId || email.id)) return email;
99
+ changed++;
100
+ const labelIds = new Set<string>(email.labelIds ?? []);
101
+ labelIds.delete("inbox");
102
+ if (args.removeLabel) labelIds.delete(args.removeLabel);
103
+ labelIds.add(targetLabel);
104
+ return {
105
+ ...email,
106
+ isArchived: true,
107
+ labelIds: [...labelIds],
108
+ };
109
+ });
110
+
111
+ await writeLocalEmails(ownerEmail, updated);
112
+ return changed;
105
113
  });
106
-
107
- await putUserSetting(ownerEmail, "local-emails", { emails: updated });
108
114
  await writeAppState("refresh-signal", { ts: Date.now() });
109
115
  return `Moved ${changed} local email(s) to ${targetLabel}`;
110
116
  }
@@ -3,7 +3,7 @@ import { emit } from "@agent-native/core/event-bus";
3
3
  import { setOAuthDisplayName } from "@agent-native/core/oauth-tokens";
4
4
  import { getRequestUserEmail } from "@agent-native/core/server";
5
5
  import { getAppProductionUrl } from "@agent-native/core/server";
6
- import { getUserSetting, putUserSetting } from "@agent-native/core/settings";
6
+ import { getUserSetting } from "@agent-native/core/settings";
7
7
  import { nanoid } from "nanoid";
8
8
  import { z } from "zod";
9
9
 
@@ -20,6 +20,11 @@ import {
20
20
  invalidateListCacheForOwner,
21
21
  setAccountDisplayName,
22
22
  } from "../server/lib/google-auth.js";
23
+ import {
24
+ readLocalEmails,
25
+ withLocalEmailMutationLock,
26
+ writeLocalEmails,
27
+ } from "../server/lib/local-email-store.js";
23
28
  import {
24
29
  bodyToHtml,
25
30
  buildRawEmail,
@@ -154,73 +159,73 @@ export default defineAction({
154
159
 
155
160
  const accounts = await getAccessTokens();
156
161
  if (accounts.length === 0) {
157
- const data = await getUserSetting(ownerEmail, "local-emails");
158
- const emails =
159
- data && Array.isArray((data as any).emails) ? (data as any).emails : [];
160
- const newEmail = {
161
- id: `msg-${nanoid(8)}`,
162
- threadId: args.replyToId
163
- ? (emails.find((e: any) => e.id === args.replyToId)?.threadId ??
164
- `thread-${nanoid(8)}`)
165
- : `thread-${nanoid(8)}`,
166
- from: { name: settings.name, email: settings.email },
167
- to: args.to.split(",").map((value) => {
168
- const trimmed = value.trim();
169
- return { name: trimmed, email: trimmed };
170
- }),
171
- ...(args.cc
172
- ? {
173
- cc: args.cc.split(",").map((value) => {
174
- const trimmed = value.trim();
175
- return { name: trimmed, email: trimmed };
176
- }),
177
- }
178
- : {}),
179
- ...(args.bcc
180
- ? {
181
- bcc: args.bcc.split(",").map((value) => {
182
- const trimmed = value.trim();
183
- return { name: trimmed, email: trimmed };
184
- }),
185
- }
186
- : {}),
187
- subject: args.subject,
188
- snippet: markdownPreviewSnippet(args.body),
189
- body: args.body,
190
- bodyHtml: bodyToHtml(args.body),
191
- date: new Date().toISOString(),
192
- isRead: true,
193
- isStarred: false,
194
- isSent: true,
195
- isArchived: false,
196
- isTrashed: false,
197
- labelIds: ["sent"],
198
- ...(resolvedAttachments.length > 0
199
- ? {
200
- attachments: resolvedAttachments.map((att) => ({
201
- id: att.filename,
202
- filename: att.originalName,
203
- mimeType: att.mimeType,
204
- size: att.size,
205
- url: att.url,
206
- })),
207
- }
208
- : {}),
209
- };
210
- emails.push(newEmail);
211
- await putUserSetting(ownerEmail, "local-emails", { emails });
212
- try {
213
- emit(
214
- "mail.message.sent",
215
- {
216
- messageId: newEmail.id,
217
- to: args.to,
218
- subject: args.subject,
219
- },
220
- { owner: ownerEmail },
221
- );
222
- } catch {}
223
- return JSON.stringify(newEmail, null, 2);
162
+ return withLocalEmailMutationLock(ownerEmail, async () => {
163
+ const emails = await readLocalEmails(ownerEmail);
164
+ const newEmail = {
165
+ id: `msg-${nanoid(8)}`,
166
+ threadId: args.replyToId
167
+ ? (emails.find((e: any) => e.id === args.replyToId)?.threadId ??
168
+ `thread-${nanoid(8)}`)
169
+ : `thread-${nanoid(8)}`,
170
+ from: { name: settings.name, email: settings.email },
171
+ to: args.to.split(",").map((value) => {
172
+ const trimmed = value.trim();
173
+ return { name: trimmed, email: trimmed };
174
+ }),
175
+ ...(args.cc
176
+ ? {
177
+ cc: args.cc.split(",").map((value) => {
178
+ const trimmed = value.trim();
179
+ return { name: trimmed, email: trimmed };
180
+ }),
181
+ }
182
+ : {}),
183
+ ...(args.bcc
184
+ ? {
185
+ bcc: args.bcc.split(",").map((value) => {
186
+ const trimmed = value.trim();
187
+ return { name: trimmed, email: trimmed };
188
+ }),
189
+ }
190
+ : {}),
191
+ subject: args.subject,
192
+ snippet: markdownPreviewSnippet(args.body),
193
+ body: args.body,
194
+ bodyHtml: bodyToHtml(args.body),
195
+ date: new Date().toISOString(),
196
+ isRead: true,
197
+ isStarred: false,
198
+ isSent: true,
199
+ isArchived: false,
200
+ isTrashed: false,
201
+ labelIds: ["sent"],
202
+ ...(resolvedAttachments.length > 0
203
+ ? {
204
+ attachments: resolvedAttachments.map((att) => ({
205
+ id: att.filename,
206
+ filename: att.originalName,
207
+ mimeType: att.mimeType,
208
+ size: att.size,
209
+ url: att.url,
210
+ })),
211
+ }
212
+ : {}),
213
+ };
214
+ emails.push(newEmail);
215
+ await writeLocalEmails(ownerEmail, emails);
216
+ try {
217
+ emit(
218
+ "mail.message.sent",
219
+ {
220
+ messageId: newEmail.id,
221
+ to: args.to,
222
+ subject: args.subject,
223
+ },
224
+ { owner: ownerEmail },
225
+ );
226
+ } catch {}
227
+ return JSON.stringify(newEmail, null, 2);
228
+ });
224
229
  }
225
230
 
226
231
  let selectedToken = accounts[0].accessToken;
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: fixed
3
+ date: 2026-07-15
4
+ ---
5
+
6
+ Unread inbox cleanup now completes reliably in one verified operation while preserving excluded conversations.