@agent-native/core 0.117.0 → 0.117.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 (357) hide show
  1. package/corpus/README.md +2 -2
  2. package/corpus/core/CHANGELOG.md +16 -0
  3. package/corpus/core/package.json +2 -1
  4. package/corpus/core/src/cli/context-xray-local.ts +1 -1
  5. package/corpus/core/src/client/extensions/ExtensionViewer.tsx +4 -4
  6. package/corpus/core/src/client/extensions/ExtensionsSidebarSection.tsx +11 -11
  7. package/corpus/core/src/client/extensions/agent-native-extension-runtime.ts +1 -1
  8. package/corpus/core/src/client/extensions/delete-extension.ts +2 -2
  9. package/corpus/core/src/client/org/OrgSwitcher.tsx +25 -1
  10. package/corpus/core/src/client/settings/SettingsPanel.tsx +102 -10
  11. package/corpus/core/src/client/sharing/ShareButton.tsx +7 -6
  12. package/corpus/core/src/db/client.ts +13 -10
  13. package/corpus/core/src/deploy/workspace-deploy.ts +14 -4
  14. package/corpus/core/src/extensions/actions.ts +13 -5
  15. package/corpus/core/src/extensions/local.ts +1 -0
  16. package/corpus/core/src/extensions/routes.ts +10 -5
  17. package/corpus/core/src/extensions/schema.ts +5 -0
  18. package/corpus/core/src/extensions/slots/store.ts +14 -4
  19. package/corpus/core/src/extensions/store.ts +55 -19
  20. package/corpus/core/src/extensions/theme.ts +1 -1
  21. package/corpus/core/src/file-upload/registry.ts +9 -0
  22. package/corpus/core/src/index.browser.ts +5 -0
  23. package/corpus/core/src/index.ts +1 -0
  24. package/corpus/core/src/localization/default-messages.ts +23 -6
  25. package/corpus/core/src/server/action-discovery.ts +8 -0
  26. package/corpus/core/src/server/better-auth-instance.ts +7 -2
  27. package/corpus/core/src/server/email-template.ts +18 -0
  28. package/corpus/core/src/server/email-templates.ts +3 -0
  29. package/corpus/core/src/server/email.ts +40 -4
  30. package/corpus/core/src/sharing/actions/share-resource.ts +1 -0
  31. package/corpus/core/src/templates/default/.agents/skills/agent-native-toolkit/SKILL.md +6 -0
  32. package/corpus/core/src/templates/default/app/global.css +1 -1
  33. package/corpus/core/src/templates/default/app/i18n/ar-SA.ts +6 -6
  34. package/corpus/core/src/templates/default/app/i18n/de-DE.ts +6 -6
  35. package/corpus/core/src/templates/default/app/i18n/en-US.ts +6 -6
  36. package/corpus/core/src/templates/default/app/i18n/es-ES.ts +6 -6
  37. package/corpus/core/src/templates/default/app/i18n/fr-FR.ts +6 -6
  38. package/corpus/core/src/templates/default/app/i18n/hi-IN.ts +6 -6
  39. package/corpus/core/src/templates/default/app/i18n/ja-JP.ts +6 -6
  40. package/corpus/core/src/templates/default/app/i18n/ko-KR.ts +6 -6
  41. package/corpus/core/src/templates/default/app/i18n/pt-BR.ts +6 -6
  42. package/corpus/core/src/templates/default/app/i18n/zh-CN.ts +7 -7
  43. package/corpus/core/src/templates/default/app/i18n/zh-TW.ts +7 -7
  44. package/corpus/core/src/templates/headless/.agents/skills/agent-native-toolkit/SKILL.md +6 -0
  45. package/corpus/core/src/templates/workspace-core/.agents/skills/agent-native-toolkit/SKILL.md +6 -0
  46. package/corpus/core/src/user-profile/actions/get-user-profile.ts +16 -0
  47. package/corpus/core/src/user-profile/actions/update-user-profile.ts +24 -0
  48. package/corpus/core/src/user-profile/index.ts +5 -0
  49. package/corpus/core/src/user-profile/shared.ts +14 -0
  50. package/corpus/core/src/user-profile/store.ts +50 -0
  51. package/corpus/templates/analytics/.agents/skills/agent-native-toolkit/SKILL.md +6 -0
  52. package/corpus/templates/assets/.agents/skills/agent-native-toolkit/SKILL.md +6 -0
  53. package/corpus/templates/assets/app/components/layout/Sidebar.tsx +2 -2
  54. package/corpus/templates/assets/app/global.css +1 -1
  55. package/corpus/templates/assets/changelog/2026-07-22-manage-agent-navigation-now-uses-the-connected-nodes-icon.md +6 -0
  56. package/corpus/templates/brain/.agents/skills/agent-native-toolkit/SKILL.md +6 -0
  57. package/corpus/templates/brain/app/global.css +2 -2
  58. package/corpus/templates/brain/app/lib/brain.ts +2 -2
  59. package/corpus/templates/brain/app/root.tsx +2 -2
  60. package/corpus/templates/brain/changelog/2026-07-22-manage-agent-navigation-now-uses-the-connected-nodes-icon.md +6 -0
  61. package/corpus/templates/calendar/.agents/skills/agent-native-toolkit/SKILL.md +6 -0
  62. package/corpus/templates/calendar/app/components/layout/Sidebar.tsx +6 -2
  63. package/corpus/templates/calendar/app/global.css +1 -1
  64. package/corpus/templates/calendar/app/root.tsx +2 -2
  65. package/corpus/templates/calendar/changelog/2026-07-22-manage-agent-navigation-now-uses-the-connected-nodes-icon.md +6 -0
  66. package/corpus/templates/chat/.agents/skills/agent-native-toolkit/SKILL.md +6 -0
  67. package/corpus/templates/chat/app/components/layout/Sidebar.tsx +2 -2
  68. package/corpus/templates/chat/app/global.css +1 -1
  69. package/corpus/templates/chat/app/root.tsx +2 -2
  70. package/corpus/templates/chat/changelog/2026-07-22-manage-agent-navigation-now-uses-the-connected-nodes-icon.md +6 -0
  71. package/corpus/templates/clips/.agents/skills/agent-native-toolkit/SKILL.md +6 -0
  72. package/corpus/templates/clips/actions/export-to-brain.ts +1 -1
  73. package/corpus/templates/clips/actions/invite-member.ts +1 -0
  74. package/corpus/templates/clips/app/components/library/library-layout.tsx +2 -2
  75. package/corpus/templates/clips/app/components/recorder/recorder-engine.ts +20 -11
  76. package/corpus/templates/clips/app/global.css +1 -1
  77. package/corpus/templates/clips/app/root.tsx +7 -2
  78. package/corpus/templates/clips/app/routes/record.tsx +2 -88
  79. package/corpus/templates/clips/changelog/2026-07-22-builder-connected-recordings-start-resumable-upload-sessions.md +6 -0
  80. package/corpus/templates/clips/changelog/2026-07-22-clip-thumbnails-now-come-from-the-recording-instead-of-the-p.md +6 -0
  81. package/corpus/templates/clips/changelog/2026-07-22-clips-emails-now-render-the-agent-native-logo-in-gmail-and-o.md +6 -0
  82. package/corpus/templates/clips/changelog/2026-07-22-dismissed-zoom-and-teams-meeting-note-prompts-now-stay-dismi.md +6 -0
  83. package/corpus/templates/clips/changelog/2026-07-22-manage-agent-navigation-now-uses-the-connected-nodes-icon.md +6 -0
  84. package/corpus/templates/clips/changelog/2026-07-22-quieter-permissions-and-rewind-controls.md +6 -0
  85. package/corpus/templates/clips/desktop/src/app.tsx +86 -52
  86. package/corpus/templates/clips/desktop/src/lib/meeting-notification-dismissal.ts +31 -0
  87. package/corpus/templates/clips/desktop/src/lib/recorder.ts +4 -167
  88. package/corpus/templates/clips/desktop/src/overlays/meeting-notification.tsx +10 -1
  89. package/corpus/templates/clips/desktop/src/styles.css +98 -36
  90. package/corpus/templates/clips/desktop/src-tauri/src/adhoc_meetings_watcher.rs +67 -4
  91. package/corpus/templates/clips/desktop/src-tauri/src/lib.rs +1 -1
  92. package/corpus/templates/clips/desktop/src-tauri/src/meetings_watcher.rs +51 -0
  93. package/corpus/templates/clips/desktop/src-tauri/src/native_screen/custom_capture.rs +5 -1
  94. package/corpus/templates/clips/desktop/src-tauri/src/native_screen.rs +0 -189
  95. package/corpus/templates/clips/desktop/src-tauri/src/notifications.rs +62 -0
  96. package/corpus/templates/clips/server/plugins/db.ts +6 -2
  97. package/corpus/templates/content/.agents/skills/agent-native-toolkit/SKILL.md +6 -0
  98. package/corpus/templates/content/app/components/sidebar/DocumentSidebar.tsx +3 -3
  99. package/corpus/templates/content/app/global.css +1 -1
  100. package/corpus/templates/content/app/root.tsx +2 -2
  101. package/corpus/templates/content/changelog/2026-07-22-manage-agent-navigation-now-uses-the-connected-nodes-icon.md +6 -0
  102. package/corpus/templates/crm/.agents/skills/agent-native-toolkit/SKILL.md +6 -0
  103. package/corpus/templates/crm/app/global.css +1 -1
  104. package/corpus/templates/design/.agents/skills/agent-native-toolkit/SKILL.md +6 -0
  105. package/corpus/templates/design/app/components/design/CanvasContextMenu.tsx +19 -1
  106. package/corpus/templates/design/app/components/design/DesignCanvas.tsx +12 -1
  107. package/corpus/templates/design/app/components/design/EditPanel.tsx +177 -52
  108. package/corpus/templates/design/app/components/design/MultiScreenCanvas.tsx +179 -59
  109. package/corpus/templates/design/app/components/design/bridge/editor-chrome.bridge.ts +74 -27
  110. package/corpus/templates/design/app/components/design/multi-screen/types.ts +2 -0
  111. package/corpus/templates/design/app/components/layout/Sidebar.tsx +2 -2
  112. package/corpus/templates/design/app/global.css +1 -1
  113. package/corpus/templates/design/app/hooks/use-navigation-state.ts +6 -5
  114. package/corpus/templates/design/app/root.tsx +2 -2
  115. package/corpus/templates/design/changelog/2026-07-22-design-owners-can-keep-editing-their-designs-after-switching.md +6 -0
  116. package/corpus/templates/design/changelog/2026-07-22-inspector-tabs-keep-their-text-labels-at-narrow-widths.md +6 -0
  117. package/corpus/templates/design/changelog/2026-07-22-manage-agent-navigation-now-uses-the-connected-nodes-icon.md +6 -0
  118. package/corpus/templates/design/changelog/2026-07-22-narrow-breakpoint-previews-keep-their-device-labels-readable.md +6 -0
  119. package/corpus/templates/design/changelog/2026-07-22-removed-the-draft-status-chip-from-the-design-editor.md +6 -0
  120. package/corpus/templates/design/changelog/2026-07-22-responsive-breakpoint-controls-stay-within-narrow-sidebars.md +6 -0
  121. package/corpus/templates/design/changelog/2026-07-22-responsive-peers-now-use-a-softer-selection-highlight-withou.md +6 -0
  122. package/corpus/templates/design/changelog/2026-07-22-rotate-from-context-menu.md +6 -0
  123. package/corpus/templates/design/changelog/2026-07-22-the-selection-outline-now-stays-attached-while-moving-screen.md +6 -0
  124. package/corpus/templates/design/changelog/2026-07-22-view-only-designs-now-support-figma-style-layer-inspection-w.md +6 -0
  125. package/corpus/templates/design/server/db/index.ts +4 -0
  126. package/corpus/templates/dispatch/.agents/skills/agent-native-toolkit/SKILL.md +6 -0
  127. package/corpus/templates/dispatch/app/dispatch-extensions.tsx +2 -2
  128. package/corpus/templates/dispatch/app/global.css +1 -1
  129. package/corpus/templates/dispatch/app/root.tsx +2 -2
  130. package/corpus/templates/dispatch/changelog/2026-07-22-manage-agent-navigation-now-uses-the-connected-nodes-icon.md +6 -0
  131. package/corpus/templates/forms/.agents/skills/agent-native-toolkit/SKILL.md +6 -0
  132. package/corpus/templates/forms/app/components/layout/Layout.tsx +1 -1
  133. package/corpus/templates/forms/app/components/layout/Sidebar.tsx +3 -3
  134. package/corpus/templates/forms/app/global.css +1 -1
  135. package/corpus/templates/forms/app/hooks/use-forms.ts +55 -2
  136. package/corpus/templates/forms/app/i18n/en-US.ts +2 -0
  137. package/corpus/templates/forms/app/pages/FormBuilderPage.tsx +3 -3
  138. package/corpus/templates/forms/app/pages/FormsListPage.tsx +23 -6
  139. package/corpus/templates/forms/app/root.tsx +2 -2
  140. package/corpus/templates/forms/changelog/2026-07-22-forms-now-archive-with-optimistic-feedback.md +6 -0
  141. package/corpus/templates/forms/changelog/2026-07-22-manage-agent-navigation-now-uses-the-connected-nodes-icon.md +6 -0
  142. package/corpus/templates/forms/server/plugins/agent-chat.ts +1 -1
  143. package/corpus/templates/macros/.agents/skills/agent-native-toolkit/SKILL.md +6 -0
  144. package/corpus/templates/macros/app/components/layout/AppLayout.tsx +2 -2
  145. package/corpus/templates/macros/app/root.tsx +2 -2
  146. package/corpus/templates/macros/changelog/2026-07-22-manage-agent-navigation-now-uses-the-connected-nodes-icon.md +6 -0
  147. package/corpus/templates/mail/.agents/skills/agent-native-toolkit/SKILL.md +6 -0
  148. package/corpus/templates/mail/app/components/layout/AppLayout.tsx +3 -3
  149. package/corpus/templates/mail/app/components/layout/CommandPalette.tsx +2 -2
  150. package/corpus/templates/mail/app/global.css +1 -1
  151. package/corpus/templates/mail/changelog/2026-07-22-manage-agent-navigation-now-uses-the-connected-nodes-icon.md +6 -0
  152. package/corpus/templates/plan/.agents/skills/agent-native-toolkit/SKILL.md +6 -0
  153. package/corpus/templates/plan/app/components/layout/Sidebar.tsx +2 -2
  154. package/corpus/templates/plan/app/global.css +1 -1
  155. package/corpus/templates/plan/app/root.tsx +2 -2
  156. package/corpus/templates/plan/changelog/2026-07-22-manage-agent-navigation-now-uses-the-connected-nodes-icon.md +6 -0
  157. package/corpus/templates/slides/.agents/skills/agent-native-toolkit/SKILL.md +6 -0
  158. package/corpus/templates/slides/app/components/layout/Sidebar.tsx +2 -2
  159. package/corpus/templates/slides/app/root.tsx +2 -2
  160. package/corpus/templates/slides/changelog/2026-07-22-manage-agent-navigation-now-uses-the-connected-nodes-icon.md +6 -0
  161. package/corpus/templates/slides/changelog/2026-07-22-slides-no-longer-fail-intermittently-on-fresh-server-instances.md +6 -0
  162. package/corpus/templates/slides/changelog/2026-07-22-uploaded-screenshots-can-now-be-analyzed-and-recreated-as-ed.md +6 -0
  163. package/corpus/templates/slides/server/lib/chat-attachments.ts +7 -3
  164. package/corpus/templates/slides/server/plugins/db.ts +44 -17
  165. package/corpus/templates/tasks/.agents/skills/agent-native-toolkit/SKILL.md +6 -0
  166. package/corpus/templates/tasks/app/global.css +1 -1
  167. package/dist/cli/context-xray-local.js +1 -1
  168. package/dist/cli/context-xray-local.js.map +1 -1
  169. package/dist/client/extensions/ExtensionViewer.js +2 -2
  170. package/dist/client/extensions/ExtensionViewer.js.map +1 -1
  171. package/dist/client/extensions/ExtensionsSidebarSection.js +11 -11
  172. package/dist/client/extensions/ExtensionsSidebarSection.js.map +1 -1
  173. package/dist/client/extensions/agent-native-extension-runtime.js +1 -1
  174. package/dist/client/extensions/agent-native-extension-runtime.js.map +1 -1
  175. package/dist/client/extensions/delete-extension.d.ts +1 -1
  176. package/dist/client/extensions/delete-extension.d.ts.map +1 -1
  177. package/dist/client/extensions/delete-extension.js +1 -1
  178. package/dist/client/extensions/delete-extension.js.map +1 -1
  179. package/dist/client/org/OrgSwitcher.d.ts +3 -1
  180. package/dist/client/org/OrgSwitcher.d.ts.map +1 -1
  181. package/dist/client/org/OrgSwitcher.js +12 -4
  182. package/dist/client/org/OrgSwitcher.js.map +1 -1
  183. package/dist/client/settings/SettingsPanel.d.ts.map +1 -1
  184. package/dist/client/settings/SettingsPanel.js +37 -4
  185. package/dist/client/settings/SettingsPanel.js.map +1 -1
  186. package/dist/client/sharing/ShareButton.d.ts +3 -4
  187. package/dist/client/sharing/ShareButton.d.ts.map +1 -1
  188. package/dist/client/sharing/ShareButton.js +3 -2
  189. package/dist/client/sharing/ShareButton.js.map +1 -1
  190. package/dist/collab/awareness.d.ts +2 -2
  191. package/dist/collab/awareness.d.ts.map +1 -1
  192. package/dist/collab/routes.d.ts +1 -1
  193. package/dist/collab/struct-routes.d.ts +1 -1
  194. package/dist/db/client.d.ts +7 -7
  195. package/dist/db/client.d.ts.map +1 -1
  196. package/dist/db/client.js +13 -10
  197. package/dist/db/client.js.map +1 -1
  198. package/dist/deploy/workspace-deploy.js +14 -4
  199. package/dist/deploy/workspace-deploy.js.map +1 -1
  200. package/dist/extensions/actions.d.ts.map +1 -1
  201. package/dist/extensions/actions.js +8 -5
  202. package/dist/extensions/actions.js.map +1 -1
  203. package/dist/extensions/local.d.ts.map +1 -1
  204. package/dist/extensions/local.js +1 -0
  205. package/dist/extensions/local.js.map +1 -1
  206. package/dist/extensions/routes.d.ts.map +1 -1
  207. package/dist/extensions/routes.js +9 -4
  208. package/dist/extensions/routes.js.map +1 -1
  209. package/dist/extensions/schema.d.ts +23 -2
  210. package/dist/extensions/schema.d.ts.map +1 -1
  211. package/dist/extensions/schema.js +5 -0
  212. package/dist/extensions/schema.js.map +1 -1
  213. package/dist/extensions/slots/store.d.ts +1 -1
  214. package/dist/extensions/slots/store.d.ts.map +1 -1
  215. package/dist/extensions/slots/store.js +4 -4
  216. package/dist/extensions/slots/store.js.map +1 -1
  217. package/dist/extensions/store.d.ts +1 -0
  218. package/dist/extensions/store.d.ts.map +1 -1
  219. package/dist/extensions/store.js +38 -21
  220. package/dist/extensions/store.js.map +1 -1
  221. package/dist/extensions/theme.js +1 -1
  222. package/dist/extensions/theme.js.map +1 -1
  223. package/dist/file-upload/registry.d.ts.map +1 -1
  224. package/dist/file-upload/registry.js +9 -0
  225. package/dist/file-upload/registry.js.map +1 -1
  226. package/dist/index.browser.d.ts +1 -0
  227. package/dist/index.browser.d.ts.map +1 -1
  228. package/dist/index.browser.js +1 -0
  229. package/dist/index.browser.js.map +1 -1
  230. package/dist/index.d.ts +1 -0
  231. package/dist/index.d.ts.map +1 -1
  232. package/dist/index.js +1 -0
  233. package/dist/index.js.map +1 -1
  234. package/dist/localization/default-messages.d.ts +16 -0
  235. package/dist/localization/default-messages.d.ts.map +1 -1
  236. package/dist/localization/default-messages.js +22 -6
  237. package/dist/localization/default-messages.js.map +1 -1
  238. package/dist/notifications/routes.d.ts +2 -2
  239. package/dist/observability/routes.d.ts +5 -5
  240. package/dist/progress/routes.d.ts +1 -1
  241. package/dist/provider-api/actions/custom-provider-registration.d.ts +7 -7
  242. package/dist/provider-api/actions/provider-api.d.ts +11 -11
  243. package/dist/provider-api/corpus-jobs.d.ts +2 -2
  244. package/dist/secrets/routes.d.ts +6 -6
  245. package/dist/server/action-discovery.d.ts.map +1 -1
  246. package/dist/server/action-discovery.js +8 -0
  247. package/dist/server/action-discovery.js.map +1 -1
  248. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  249. package/dist/server/better-auth-instance.d.ts +7 -2
  250. package/dist/server/better-auth-instance.d.ts.map +1 -1
  251. package/dist/server/better-auth-instance.js.map +1 -1
  252. package/dist/server/email-template.d.ts +3 -0
  253. package/dist/server/email-template.d.ts.map +1 -1
  254. package/dist/server/email-template.js +13 -0
  255. package/dist/server/email-template.js.map +1 -1
  256. package/dist/server/email-templates.d.ts.map +1 -1
  257. package/dist/server/email-templates.js +3 -0
  258. package/dist/server/email-templates.js.map +1 -1
  259. package/dist/server/email.d.ts.map +1 -1
  260. package/dist/server/email.js +27 -4
  261. package/dist/server/email.js.map +1 -1
  262. package/dist/server/transcribe-voice.d.ts +1 -1
  263. package/dist/sharing/actions/share-resource.js +1 -0
  264. package/dist/sharing/actions/share-resource.js.map +1 -1
  265. package/dist/templates/chat/.agents/skills/agent-native-toolkit/SKILL.md +6 -0
  266. package/dist/templates/chat/app/components/layout/Sidebar.tsx +2 -2
  267. package/dist/templates/chat/app/global.css +1 -1
  268. package/dist/templates/chat/app/root.tsx +2 -2
  269. package/dist/templates/chat/changelog/2026-07-22-manage-agent-navigation-now-uses-the-connected-nodes-icon.md +6 -0
  270. package/dist/templates/default/.agents/skills/agent-native-toolkit/SKILL.md +6 -0
  271. package/dist/templates/default/app/global.css +1 -1
  272. package/dist/templates/default/app/i18n/ar-SA.ts +6 -6
  273. package/dist/templates/default/app/i18n/de-DE.ts +6 -6
  274. package/dist/templates/default/app/i18n/en-US.ts +6 -6
  275. package/dist/templates/default/app/i18n/es-ES.ts +6 -6
  276. package/dist/templates/default/app/i18n/fr-FR.ts +6 -6
  277. package/dist/templates/default/app/i18n/hi-IN.ts +6 -6
  278. package/dist/templates/default/app/i18n/ja-JP.ts +6 -6
  279. package/dist/templates/default/app/i18n/ko-KR.ts +6 -6
  280. package/dist/templates/default/app/i18n/pt-BR.ts +6 -6
  281. package/dist/templates/default/app/i18n/zh-CN.ts +7 -7
  282. package/dist/templates/default/app/i18n/zh-TW.ts +7 -7
  283. package/dist/templates/headless/.agents/skills/agent-native-toolkit/SKILL.md +6 -0
  284. package/dist/templates/workspace-core/.agents/skills/agent-native-toolkit/SKILL.md +6 -0
  285. package/dist/user-profile/actions/get-user-profile.d.ts +4 -0
  286. package/dist/user-profile/actions/get-user-profile.d.ts.map +1 -0
  287. package/dist/user-profile/actions/get-user-profile.js +14 -0
  288. package/dist/user-profile/actions/get-user-profile.js.map +1 -0
  289. package/dist/user-profile/actions/update-user-profile.d.ts +6 -0
  290. package/dist/user-profile/actions/update-user-profile.d.ts.map +1 -0
  291. package/dist/user-profile/actions/update-user-profile.js +20 -0
  292. package/dist/user-profile/actions/update-user-profile.js.map +1 -0
  293. package/dist/user-profile/index.d.ts +2 -0
  294. package/dist/user-profile/index.d.ts.map +1 -0
  295. package/dist/user-profile/index.js +2 -0
  296. package/dist/user-profile/index.js.map +1 -0
  297. package/dist/user-profile/shared.d.ts +7 -0
  298. package/dist/user-profile/shared.d.ts.map +1 -0
  299. package/dist/user-profile/shared.js +6 -0
  300. package/dist/user-profile/shared.js.map +1 -0
  301. package/dist/user-profile/store.d.ts +4 -0
  302. package/dist/user-profile/store.d.ts.map +1 -0
  303. package/dist/user-profile/store.js +38 -0
  304. package/dist/user-profile/store.js.map +1 -0
  305. package/package.json +2 -1
  306. package/src/cli/context-xray-local.ts +1 -1
  307. package/src/client/extensions/ExtensionViewer.tsx +4 -4
  308. package/src/client/extensions/ExtensionsSidebarSection.tsx +11 -11
  309. package/src/client/extensions/agent-native-extension-runtime.ts +1 -1
  310. package/src/client/extensions/delete-extension.ts +2 -2
  311. package/src/client/org/OrgSwitcher.tsx +25 -1
  312. package/src/client/settings/SettingsPanel.tsx +102 -10
  313. package/src/client/sharing/ShareButton.tsx +7 -6
  314. package/src/db/client.ts +13 -10
  315. package/src/deploy/workspace-deploy.ts +14 -4
  316. package/src/extensions/actions.ts +13 -5
  317. package/src/extensions/local.ts +1 -0
  318. package/src/extensions/routes.ts +10 -5
  319. package/src/extensions/schema.ts +5 -0
  320. package/src/extensions/slots/store.ts +14 -4
  321. package/src/extensions/store.ts +55 -19
  322. package/src/extensions/theme.ts +1 -1
  323. package/src/file-upload/registry.ts +9 -0
  324. package/src/index.browser.ts +5 -0
  325. package/src/index.ts +1 -0
  326. package/src/localization/default-messages.ts +23 -6
  327. package/src/server/action-discovery.ts +8 -0
  328. package/src/server/better-auth-instance.ts +7 -2
  329. package/src/server/email-template.ts +18 -0
  330. package/src/server/email-templates.ts +3 -0
  331. package/src/server/email.ts +40 -4
  332. package/src/sharing/actions/share-resource.ts +1 -0
  333. package/src/templates/chat/.agents/skills/agent-native-toolkit/SKILL.md +6 -0
  334. package/src/templates/chat/app/components/layout/Sidebar.tsx +2 -2
  335. package/src/templates/chat/app/global.css +1 -1
  336. package/src/templates/chat/app/root.tsx +2 -2
  337. package/src/templates/chat/changelog/2026-07-22-manage-agent-navigation-now-uses-the-connected-nodes-icon.md +6 -0
  338. package/src/templates/default/.agents/skills/agent-native-toolkit/SKILL.md +6 -0
  339. package/src/templates/default/app/global.css +1 -1
  340. package/src/templates/default/app/i18n/ar-SA.ts +6 -6
  341. package/src/templates/default/app/i18n/de-DE.ts +6 -6
  342. package/src/templates/default/app/i18n/en-US.ts +6 -6
  343. package/src/templates/default/app/i18n/es-ES.ts +6 -6
  344. package/src/templates/default/app/i18n/fr-FR.ts +6 -6
  345. package/src/templates/default/app/i18n/hi-IN.ts +6 -6
  346. package/src/templates/default/app/i18n/ja-JP.ts +6 -6
  347. package/src/templates/default/app/i18n/ko-KR.ts +6 -6
  348. package/src/templates/default/app/i18n/pt-BR.ts +6 -6
  349. package/src/templates/default/app/i18n/zh-CN.ts +7 -7
  350. package/src/templates/default/app/i18n/zh-TW.ts +7 -7
  351. package/src/templates/headless/.agents/skills/agent-native-toolkit/SKILL.md +6 -0
  352. package/src/templates/workspace-core/.agents/skills/agent-native-toolkit/SKILL.md +6 -0
  353. package/src/user-profile/actions/get-user-profile.ts +16 -0
  354. package/src/user-profile/actions/update-user-profile.ts +24 -0
  355. package/src/user-profile/index.ts +5 -0
  356. package/src/user-profile/shared.ts +14 -0
  357. package/src/user-profile/store.ts +50 -0
@@ -56,6 +56,38 @@ struct AdhocMeetingsWatcherInner {
56
56
  session_notified: HashMap<String, bool>,
57
57
  }
58
58
 
59
+ impl AdhocMeetingsWatcherInner {
60
+ fn refresh_suppression(&mut self, platform: &str, now_ts: i64) {
61
+ self.session_notified.insert(platform.to_string(), true);
62
+ self.cooldown_until
63
+ .insert(platform.to_string(), now_ts + COOLDOWN_SECS);
64
+ self.dwell_platform = None;
65
+ self.dwell_since = None;
66
+ }
67
+
68
+ fn is_suppressed(&self, platform: &str, now_ts: i64) -> bool {
69
+ self.cooldown_until.get(platform).copied().unwrap_or(0) > now_ts
70
+ || self
71
+ .session_notified
72
+ .get(platform)
73
+ .copied()
74
+ .unwrap_or(false)
75
+ }
76
+ }
77
+
78
+ pub fn refresh_dismissal_suppression(app: &AppHandle, platform: &str) -> Result<(), String> {
79
+ let platform = platform.trim().to_lowercase();
80
+ if platform.is_empty() {
81
+ return Ok(());
82
+ }
83
+ let state = app
84
+ .try_state::<AdhocMeetingsWatcherState>()
85
+ .ok_or_else(|| "no AdhocMeetingsWatcherState".to_string())?;
86
+ let mut g = state.inner.lock().map_err(|e| e.to_string())?;
87
+ g.refresh_suppression(&platform, chrono::Utc::now().timestamp());
88
+ Ok(())
89
+ }
90
+
59
91
  /// Spawn the long-running adhoc watcher. Idempotent — gated by OnceLock.
60
92
  pub fn spawn_watcher(app: AppHandle) {
61
93
  use std::sync::OnceLock;
@@ -170,10 +202,7 @@ async fn tick_macos(
170
202
  // Prune expired cooldowns.
171
203
  g.cooldown_until.retain(|_, until| *until > now_ts);
172
204
 
173
- if g.cooldown_until.get(platform).copied().unwrap_or(0) > now_ts {
174
- return Ok(());
175
- }
176
- if g.session_notified.get(platform).copied().unwrap_or(false) {
205
+ if g.is_suppressed(platform, now_ts) {
177
206
  return Ok(());
178
207
  }
179
208
 
@@ -263,6 +292,40 @@ async fn tick_macos(
263
292
  Ok(())
264
293
  }
265
294
 
295
+ #[cfg(test)]
296
+ mod tests {
297
+ use super::*;
298
+
299
+ #[test]
300
+ fn dismissal_refreshes_the_existing_cooldown_and_clears_dwell() {
301
+ let now_ts = 1_000;
302
+ let mut state = AdhocMeetingsWatcherInner {
303
+ dwell_platform: Some("zoom".to_string()),
304
+ dwell_since: Some(Instant::now()),
305
+ ..Default::default()
306
+ };
307
+
308
+ state.refresh_suppression("zoom", now_ts);
309
+ state.session_notified.remove("zoom");
310
+
311
+ assert!(state.is_suppressed("zoom", now_ts + COOLDOWN_SECS - 1));
312
+ assert!(!state.is_suppressed("zoom", now_ts + COOLDOWN_SECS));
313
+ assert_eq!(state.dwell_platform, None);
314
+ assert_eq!(state.dwell_since, None);
315
+ }
316
+
317
+ #[test]
318
+ fn dismissal_suppression_remains_platform_scoped() {
319
+ let now_ts = 1_000;
320
+ let mut state = AdhocMeetingsWatcherInner::default();
321
+
322
+ state.refresh_suppression("zoom", now_ts);
323
+
324
+ assert!(state.is_suppressed("zoom", now_ts));
325
+ assert!(!state.is_suppressed("teams", now_ts));
326
+ }
327
+ }
328
+
266
329
  fn reset_dwell(app: &AppHandle) {
267
330
  if let Some(state) = app.try_state::<AdhocMeetingsWatcherState>() {
268
331
  if let Ok(mut g) = state.inner.lock() {
@@ -147,7 +147,6 @@ pub fn run() {
147
147
  native_screen::native_fullscreen_claim_upload_open,
148
148
  native_screen::native_fullscreen_recording_warm,
149
149
  native_screen::native_fullscreen_recording_begin,
150
- native_screen::native_fullscreen_capture_thumbnail,
151
150
  native_screen::native_fullscreen_recording_stop_and_upload,
152
151
  native_screen::native_fullscreen_recording_stop_and_save,
153
152
  native_screen::native_fullscreen_recording_cancel,
@@ -204,6 +203,7 @@ pub fn run() {
204
203
  // notifications
205
204
  notifications::take_pending_meeting_notification,
206
205
  notifications::notify_meeting_starting,
206
+ notifications::dismiss_meeting_notification,
207
207
  // meetings watcher (background poller)
208
208
  meetings_watcher::meetings_watcher_set_server_url,
209
209
  meetings_watcher::meetings_watcher_set_session,
@@ -145,6 +145,8 @@ struct MeetingItem {
145
145
  join_url: Option<String>,
146
146
  #[serde(default)]
147
147
  platform: Option<String>,
148
+ #[serde(default)]
149
+ source: Option<String>,
148
150
  }
149
151
 
150
152
  #[derive(Debug, Deserialize)]
@@ -345,6 +347,9 @@ async fn tick_once(app: &AppHandle, client: &reqwest::Client) -> Result<(), Stri
345
347
  let now = chrono::Utc::now();
346
348
  let now_ts = now.timestamp();
347
349
  for m in meetings {
350
+ if !is_calendar_reminder_candidate(&m) {
351
+ continue;
352
+ }
348
353
  let Some(start_str) = m.scheduled_start.as_deref() else {
349
354
  continue;
350
355
  };
@@ -445,6 +450,10 @@ async fn tick_once(app: &AppHandle, client: &reqwest::Client) -> Result<(), Stri
445
450
  Ok(())
446
451
  }
447
452
 
453
+ fn is_calendar_reminder_candidate(meeting: &MeetingItem) -> bool {
454
+ meeting.source.as_deref() != Some("adhoc")
455
+ }
456
+
448
457
  fn parse_meetings(body: &serde_json::Value) -> Vec<MeetingItem> {
449
458
  if let Ok(parsed) = serde_json::from_value::<ListMeetingsResponse>(body.clone()) {
450
459
  if let Some(v) = parsed.upcoming {
@@ -462,3 +471,45 @@ fn parse_meetings(body: &serde_json::Value) -> Vec<MeetingItem> {
462
471
  }
463
472
  Vec::new()
464
473
  }
474
+
475
+ #[cfg(test)]
476
+ mod tests {
477
+ use super::{is_calendar_reminder_candidate, parse_meetings};
478
+
479
+ #[test]
480
+ fn excludes_adhoc_meetings_from_calendar_reminders() {
481
+ let meetings = parse_meetings(&serde_json::json!({
482
+ "meetings": [
483
+ {
484
+ "id": "adhoc-meeting",
485
+ "scheduledStart": "2026-07-22T19:10:00Z",
486
+ "source": "adhoc"
487
+ },
488
+ {
489
+ "id": "calendar-meeting",
490
+ "scheduledStart": "2026-07-22T19:10:00Z",
491
+ "source": "calendar"
492
+ }
493
+ ]
494
+ }));
495
+
496
+ assert_eq!(meetings.len(), 2);
497
+ assert!(!is_calendar_reminder_candidate(&meetings[0]));
498
+ assert!(is_calendar_reminder_candidate(&meetings[1]));
499
+ }
500
+
501
+ #[test]
502
+ fn keeps_meetings_without_source_eligible_for_legacy_payloads() {
503
+ let meetings = parse_meetings(&serde_json::json!({
504
+ "meetings": [
505
+ {
506
+ "id": "legacy-meeting",
507
+ "scheduledStart": "2026-07-22T19:10:00Z"
508
+ }
509
+ ]
510
+ }));
511
+
512
+ assert_eq!(meetings.len(), 1);
513
+ assert!(is_calendar_reminder_candidate(&meetings[0]));
514
+ }
515
+ }
@@ -2629,7 +2629,11 @@ fn decode_samples_to_f32(bytes: &[u8], is_float: bool, bits: u32) -> Vec<f32> {
2629
2629
  .map(|c| {
2630
2630
  // Reconstruct a 24-bit little-endian signed integer and sign-extend to i32.
2631
2631
  let raw = (c[0] as i32) | ((c[1] as i32) << 8) | ((c[2] as i32) << 16);
2632
- let signed = if raw & 0x800000 != 0 { raw | !0x00FF_FFFFi32 } else { raw };
2632
+ let signed = if raw & 0x800000 != 0 {
2633
+ raw | !0x00FF_FFFFi32
2634
+ } else {
2635
+ raw
2636
+ };
2633
2637
  signed as f32 / 8_388_608.0
2634
2638
  })
2635
2639
  .collect(),
@@ -155,10 +155,6 @@ const FFMPEG_CANDIDATE_PATHS: &[&str] = &[
155
155
  ];
156
156
  const PENDING_UPLOADS_DIR: &str = "pending-recording-uploads";
157
157
  const CLIP_DRAFTS_DIR: &str = "Drafts";
158
- const THUMBNAIL_MIME_TYPE: &str = "image/jpeg";
159
- const THUMBNAIL_MAX_BYTES: u64 = 2 * 1024 * 1024;
160
- const THUMBNAIL_WIDTH: &str = "1280";
161
- const SIPS_PATH: &str = "/usr/bin/sips";
162
158
  // Minimum free space required to start recording; below this we hard-block.
163
159
  pub(crate) const DISK_SPACE_BLOCK_BYTES: u64 = 500 * 1024 * 1024;
164
160
  // Free space below this at start time is logged as a warning but not blocked.
@@ -2018,31 +2014,6 @@ pub async fn native_fullscreen_recording_stop_and_save(
2018
2014
  save_finalized_native_artifact_to_local_export(&app, &artifact, &folder_name, &file_role)
2019
2015
  }
2020
2016
 
2021
- #[tauri::command]
2022
- pub async fn native_fullscreen_capture_thumbnail(
2023
- app: AppHandle,
2024
- server_url: String,
2025
- recording_id: String,
2026
- auth_token: Option<String>,
2027
- cookie: Option<String>,
2028
- ) -> Result<(), String> {
2029
- let bytes = capture_thumbnail_bytes(&app, &recording_id)?;
2030
- tauri::async_runtime::spawn(async move {
2031
- if let Err(err) = upload_thumbnail_bytes(
2032
- server_url,
2033
- recording_id.clone(),
2034
- auth_token.unwrap_or_default(),
2035
- cookie.unwrap_or_default(),
2036
- bytes,
2037
- )
2038
- .await
2039
- {
2040
- eprintln!("[clips-tray] native thumbnail upload failed for {recording_id}: {err}");
2041
- }
2042
- });
2043
- Ok(())
2044
- }
2045
-
2046
2017
  /// Called from the app's exit path (tray Quit / Cmd+Q) so a live `screencapture`
2047
2018
  /// fallback process doesn't survive the app quitting. `app.exit()` triggers
2048
2019
  /// `std::process::exit` under the hood, which does not run Rust destructors,
@@ -3455,117 +3426,6 @@ fn saved_recording_metadata_path(app: &AppHandle, recording_id: &str) -> Result<
3455
3426
  Ok(pending_uploads_dir(app)?.join(format!("{safe_id}.json")))
3456
3427
  }
3457
3428
 
3458
- fn thumbnail_path(app: &AppHandle, recording_id: &str) -> Result<PathBuf, String> {
3459
- let safe_id = sanitize_recording_id(recording_id);
3460
- pending_recording_path(app, &format!("{safe_id}-thumb"), "jpg")
3461
- }
3462
-
3463
- fn resized_thumbnail_path(path: &Path) -> PathBuf {
3464
- let stem = path
3465
- .file_stem()
3466
- .and_then(|value| value.to_str())
3467
- .unwrap_or("thumbnail");
3468
- path.with_file_name(format!("{stem}-1280.jpg"))
3469
- }
3470
-
3471
- fn thumbnail_file_for_upload(path: &Path) -> Result<PathBuf, String> {
3472
- let original_bytes = std::fs::metadata(path)
3473
- .map_err(|e| format!("thumbnail metadata unavailable: {e}"))?
3474
- .len();
3475
- if original_bytes <= THUMBNAIL_MAX_BYTES || !std::path::Path::new(SIPS_PATH).exists() {
3476
- return Ok(path.to_path_buf());
3477
- }
3478
-
3479
- let resized_path = resized_thumbnail_path(path);
3480
- let _ = std::fs::remove_file(&resized_path);
3481
- let status = Command::new(SIPS_PATH)
3482
- .arg("--resampleWidth")
3483
- .arg(THUMBNAIL_WIDTH)
3484
- .arg("--setProperty")
3485
- .arg("format")
3486
- .arg("jpeg")
3487
- .arg("--setProperty")
3488
- .arg("formatOptions")
3489
- .arg("85")
3490
- .arg(path)
3491
- .arg("--out")
3492
- .arg(&resized_path)
3493
- .stdin(Stdio::null())
3494
- .stdout(Stdio::null())
3495
- .stderr(Stdio::null())
3496
- .status()
3497
- .map_err(|e| format!("thumbnail resize failed: {e}"))?;
3498
-
3499
- if !status.success() {
3500
- let _ = std::fs::remove_file(&resized_path);
3501
- return Ok(path.to_path_buf());
3502
- }
3503
-
3504
- let resized_bytes = std::fs::metadata(&resized_path)
3505
- .map_err(|e| format!("resized thumbnail metadata unavailable: {e}"))?
3506
- .len();
3507
- if resized_bytes == 0 || resized_bytes > original_bytes {
3508
- let _ = std::fs::remove_file(&resized_path);
3509
- return Ok(path.to_path_buf());
3510
- }
3511
-
3512
- Ok(resized_path)
3513
- }
3514
-
3515
- fn capture_thumbnail_bytes(app: &AppHandle, recording_id: &str) -> Result<Vec<u8>, String> {
3516
- #[cfg(not(target_os = "macos"))]
3517
- {
3518
- let _ = (app, recording_id);
3519
- Err("Native full-screen thumbnails are currently macOS-only.".into())
3520
- }
3521
-
3522
- #[cfg(target_os = "macos")]
3523
- {
3524
- if !std::path::Path::new("/usr/sbin/screencapture").exists() {
3525
- return Err("macOS screencapture is unavailable on this machine.".into());
3526
- }
3527
-
3528
- let path = thumbnail_path(app, recording_id)?;
3529
- let _ = std::fs::remove_file(&path);
3530
- let thumb_display_flag = tray_display_id(app)
3531
- .and_then(|id| {
3532
- CGDisplay::active_displays().ok().and_then(|ids| {
3533
- ids.iter()
3534
- .position(|&aid| aid == id)
3535
- .map(|p| format!("-D{}", p + 1))
3536
- })
3537
- })
3538
- .unwrap_or_else(|| "-D1".to_string());
3539
- let status = Command::new("/usr/sbin/screencapture")
3540
- .arg("-x")
3541
- .arg("-t")
3542
- .arg("jpg")
3543
- .arg(thumb_display_flag)
3544
- .arg(&path)
3545
- .stdin(Stdio::null())
3546
- .stdout(Stdio::null())
3547
- .stderr(Stdio::null())
3548
- .status()
3549
- .map_err(|e| format!("thumbnail capture failed: {e}"))?;
3550
- if !status.success() {
3551
- let _ = std::fs::remove_file(&path);
3552
- return Err(format!("thumbnail capture exited with {status}"));
3553
- }
3554
-
3555
- let upload_path = thumbnail_file_for_upload(&path)?;
3556
- let bytes =
3557
- std::fs::read(&upload_path).map_err(|e| format!("thumbnail read failed: {e}"))?;
3558
- if upload_path != path {
3559
- let _ = std::fs::remove_file(&upload_path);
3560
- }
3561
- let _ = std::fs::remove_file(&path);
3562
- if bytes.is_empty() {
3563
- return Err("Thumbnail capture produced an empty file.".into());
3564
- }
3565
- Ok(bytes)
3566
- }
3567
- }
3568
-
3569
3429
  fn saved_recording_from_session(
3570
3430
  session: &NativeFullscreenSession,
3571
3431
  server_url: &str,
@@ -4767,55 +4627,6 @@ async fn reset_upload_chunks(
4767
4627
  Ok(NativeUploadMode::from_reset_response(&body))
4768
4628
  }
4769
4629
 
4770
- async fn upload_thumbnail_bytes(
4771
- server_url: String,
4772
- recording_id: String,
4773
- auth_token: String,
4774
- cookie: String,
4775
- bytes: Vec<u8>,
4776
- ) -> Result<(), String> {
4777
- let url = thumbnail_upload_url(&server_url, &recording_id)?;
4778
- let client = reqwest::Client::builder()
4779
- .timeout(Duration::from_secs(30))
4780
- .build()
4781
- .map_err(|e| format!("thumbnail upload client failed: {e}"))?;
4782
- let mut request = client
4783
- .post(url)
4784
- .header("Content-Type", THUMBNAIL_MIME_TYPE)
4785
- .header("X-Request-Source", "clips-desktop")
4786
- .body(bytes);
4787
- let trimmed_token = auth_token.trim();
4788
- if !trimmed_token.is_empty() {
4789
- request = request.bearer_auth(trimmed_token);
4790
- }
4791
- let trimmed_cookie = cookie.trim();
4792
- if !trimmed_cookie.is_empty() {
4793
- request = request.header("Cookie", trimmed_cookie);
4794
- }
4795
-
4796
- let response = request
4797
- .send()
4798
- .await
4799
- .map_err(|e| format!("native thumbnail upload failed: {e}"))?;
4800
- let status = response.status();
4801
- let body = response.text().await.unwrap_or_default();
4802
- if !status.is_success() {
4803
- return Err(format!(
4804
- "native thumbnail upload returned {status}: {}",
4805
- body.chars().take(400).collect::<String>()
4806
- ));
4807
- }
4808
- Ok(())
4809
- }
4810
-
4811
- fn thumbnail_upload_url(server_url: &str, recording_id: &str) -> Result<url::Url, String> {
4812
- let base = server_url.trim_end_matches('/');
4813
- url::Url::parse(&format!(
4814
- "{base}/api/recordings/{recording_id}/thumbnail?replace=auto"
4815
- ))
4816
- .map_err(|e| format!("invalid thumbnail upload URL: {e}"))
4817
- }
4818
-
4819
4630
  async fn send_upload_post(
4820
4631
  client: &reqwest::Client,
4821
4632
  server_url: &str,
@@ -194,6 +194,50 @@ pub fn take_pending_meeting_notification(app: AppHandle) -> Result<Option<Value>
194
194
  Ok(pending.take())
195
195
  }
196
196
 
197
+ fn clear_pending_notification(pending: &mut Option<Value>, meeting_id: &str) -> bool {
198
+ let matches = pending
199
+ .as_ref()
200
+ .and_then(|payload| payload.get("meetingId"))
201
+ .and_then(Value::as_str)
202
+ == Some(meeting_id);
203
+ if matches {
204
+ *pending = None;
205
+ }
206
+ matches
207
+ }
208
+
209
+ #[tauri::command]
210
+ pub fn dismiss_meeting_notification(
211
+ app: AppHandle,
212
+ meeting_id: String,
213
+ notification_type: String,
214
+ platform: Option<String>,
215
+ scheduled_start: Option<String>,
216
+ scheduled_end: Option<String>,
217
+ ) -> Result<(), String> {
218
+ let state = app.state::<MeetingNotificationState>();
219
+ let mut pending = state
220
+ .0
221
+ .lock()
222
+ .map_err(|_| "meeting notification state lock poisoned".to_string())?;
223
+ clear_pending_notification(&mut pending, &meeting_id);
224
+ drop(pending);
225
+
226
+ if let Some(platform) = platform.as_deref() {
227
+ crate::adhoc_meetings_watcher::refresh_dismissal_suppression(&app, platform)?;
228
+ }
229
+
230
+ dlog!(
231
+ "[clips-tray] meeting notification dismissed type={} id={} platform={:?} start={:?} end={:?}",
232
+ notification_type,
233
+ meeting_id,
234
+ platform,
235
+ scheduled_start,
236
+ scheduled_end
237
+ );
238
+ Ok(())
239
+ }
240
+
197
241
  fn format_time_range_subtitle(
198
242
  scheduled_start: Option<&str>,
199
243
  scheduled_end: Option<&str>,
@@ -285,3 +329,21 @@ pub async fn notify_meeting_starting(
285
329
 
286
330
  Ok(())
287
331
  }
332
+
333
+ #[cfg(test)]
334
+ mod tests {
335
+ use super::*;
336
+
337
+ #[test]
338
+ fn clears_only_the_matching_pending_notification() {
339
+ let mut pending = Some(serde_json::json!({
340
+ "meetingId": "meeting-1",
341
+ "type": "adhoc"
342
+ }));
343
+
344
+ assert!(!clear_pending_notification(&mut pending, "meeting-2"));
345
+ assert!(pending.is_some());
346
+ assert!(clear_pending_notification(&mut pending, "meeting-1"));
347
+ assert!(pending.is_none());
348
+ }
349
+ }
@@ -1280,7 +1280,9 @@ function rowNumber(value: unknown): number {
1280
1280
  * rows forever. We only delete sessions whose recording row is gone, or whose
1281
1281
  * recording reached a terminal status more than an hour ago. Abandoned browser
1282
1282
  * uploads can leave the recording stuck in `uploading`, so those are swept only
1283
- * after a much longer grace window.
1283
+ * after a much longer grace window. Resumable session activity is the heartbeat
1284
+ * for in-progress uploads because streaming chunks do not update the recording
1285
+ * row on every provider relay.
1284
1286
  */
1285
1287
  async function sweepOrphanedResumableSessions(): Promise<void> {
1286
1288
  const exec = getDbExec();
@@ -1331,6 +1333,8 @@ async function sweepOrphanedResumableSessions(): Promise<void> {
1331
1333
  if (!key.startsWith(prefix)) continue;
1332
1334
  const recordingId = key.slice(prefix.length);
1333
1335
  if (!recordingId) continue;
1336
+ const sessionUpdatedAt =
1337
+ typeof row.updated_at === "string" ? row.updated_at : "";
1334
1338
 
1335
1339
  let shouldSweep = false;
1336
1340
  try {
@@ -1353,7 +1357,7 @@ async function sweepOrphanedResumableSessions(): Promise<void> {
1353
1357
  } else if (
1354
1358
  (recording.status === "uploading" ||
1355
1359
  recording.status === "processing") &&
1356
- (recording.updated_at ?? "") < staleInProgressIso
1360
+ (sessionUpdatedAt || recording.updated_at || "") < staleInProgressIso
1357
1361
  ) {
1358
1362
  try {
1359
1363
  await exec.execute({
@@ -59,6 +59,12 @@ quick controls and deep links such as:
59
59
  - `/settings/usage`
60
60
  - `/settings/apps/:appId`
61
61
 
62
+ The shared Account section is the canonical profile surface at
63
+ `/settings#account`. It owns the editable display name and existing avatar
64
+ control through the authenticated `get-user-profile` and `update-user-profile`
65
+ actions. Shared workspace chrome such as `OrgSwitcher` should link to this
66
+ surface rather than creating an app-local profile page.
67
+
62
68
  When adding a new API key, OAuth grant, provider connection, model selector, app
63
69
  preference, notification preference, or usage/billing surface, register it as a
64
70
  settings tab or app settings panel first. Only add sidebar UI when it is needed
@@ -36,7 +36,7 @@ import type {
36
36
  } from "@shared/api";
37
37
  import { CONTENT_DATABASE_PERSONAL_VIEW_OVERRIDES_VERSION } from "@shared/api";
38
38
  import {
39
- IconBrain,
39
+ IconHierarchy2,
40
40
  IconFolder,
41
41
  IconFolderOpen,
42
42
  IconPlus,
@@ -1282,7 +1282,7 @@ export function DocumentSidebar({
1282
1282
  : "text-muted-foreground hover:bg-accent/50 hover:text-foreground",
1283
1283
  )}
1284
1284
  >
1285
- <IconBrain size={15} className="shrink-0" />
1285
+ <IconHierarchy2 size={15} className="shrink-0" />
1286
1286
  <span className="min-w-0 flex-1 truncate text-start">
1287
1287
  {t("navigation.agent")}
1288
1288
  </span>
@@ -1849,7 +1849,7 @@ export function DocumentSidebar({
1849
1849
  : "text-muted-foreground hover:text-foreground",
1850
1850
  )}
1851
1851
  >
1852
- <IconBrain size={16} />
1852
+ <IconHierarchy2 size={16} />
1853
1853
  </Link>
1854
1854
  </TooltipTrigger>
1855
1855
  <TooltipContent>{t("navigation.agent")}</TooltipContent>
@@ -80,7 +80,7 @@
80
80
  --accent: 0 0% 18%;
81
81
  --accent-foreground: 0 0% 90%;
82
82
 
83
- --destructive: 0 62% 50%;
83
+ --destructive: 0 84% 60%;
84
84
  --destructive-foreground: 0 0% 100%;
85
85
 
86
86
  --border: 0 0% 24%;
@@ -26,7 +26,7 @@ import type { ListContentDatabasesResponse } from "@shared/api";
26
26
  import {
27
27
  IconDatabase,
28
28
  IconDeviceDesktop,
29
- IconBrain,
29
+ IconHierarchy2,
30
30
  IconFileText,
31
31
  IconFolderOpen,
32
32
  IconLoader2,
@@ -539,7 +539,7 @@ function ContentCommandMenu({
539
539
  >
540
540
  <CommandMenu.Group heading={t("root.commandContent")}>
541
541
  <CommandMenu.Item onSelect={() => navigate("/agent")}>
542
- <IconBrain size={16} />
542
+ <IconHierarchy2 size={16} />
543
543
  {t("root.openAgent")}
544
544
  </CommandMenu.Item>
545
545
  </CommandMenu.Group>
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: improved
3
+ date: 2026-07-22
4
+ ---
5
+
6
+ Manage agent navigation now uses the connected-nodes icon.
@@ -59,6 +59,12 @@ quick controls and deep links such as:
59
59
  - `/settings/usage`
60
60
  - `/settings/apps/:appId`
61
61
 
62
+ The shared Account section is the canonical profile surface at
63
+ `/settings#account`. It owns the editable display name and existing avatar
64
+ control through the authenticated `get-user-profile` and `update-user-profile`
65
+ actions. Shared workspace chrome such as `OrgSwitcher` should link to this
66
+ surface rather than creating an app-local profile page.
67
+
62
68
  When adding a new API key, OAuth grant, provider connection, model selector, app
63
69
  preference, notification preference, or usage/billing surface, register it as a
64
70
  settings tab or app settings panel first. Only add sidebar UI when it is needed
@@ -57,7 +57,7 @@
57
57
  --muted-foreground: 0 0% 60%;
58
58
  --accent: 0 0% 18%;
59
59
  --accent-foreground: 0 0% 96%;
60
- --destructive: 0 63% 51%;
60
+ --destructive: 0 84% 60%;
61
61
  --destructive-foreground: 0 0% 98%;
62
62
  --border: 0 0% 24%;
63
63
  --input: 0 0% 24%;
@@ -59,6 +59,12 @@ quick controls and deep links such as:
59
59
  - `/settings/usage`
60
60
  - `/settings/apps/:appId`
61
61
 
62
+ The shared Account section is the canonical profile surface at
63
+ `/settings#account`. It owns the editable display name and existing avatar
64
+ control through the authenticated `get-user-profile` and `update-user-profile`
65
+ actions. Shared workspace chrome such as `OrgSwitcher` should link to this
66
+ surface rather than creating an app-local profile page.
67
+
62
68
  When adding a new API key, OAuth grant, provider connection, model selector, app
63
69
  preference, notification preference, or usage/billing surface, register it as a
64
70
  settings tab or app settings panel first. Only add sidebar UI when it is needed