@agent-native/core 0.92.0 → 0.92.1

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 (363) hide show
  1. package/corpus/README.md +1 -1
  2. package/corpus/core/CHANGELOG.md +14 -0
  3. package/corpus/core/package.json +1 -1
  4. package/corpus/core/src/application-state/store.ts +12 -1
  5. package/corpus/core/src/client/AssistantChat.tsx +27 -14
  6. package/corpus/core/src/client/PoweredByBadge.tsx +1 -8
  7. package/corpus/core/src/client/agent-chat-adapter.ts +37 -10
  8. package/corpus/core/src/client/chat/widgets/DataTableWidget.tsx +52 -1
  9. package/corpus/core/src/client/db-admin/TableEditor.tsx +49 -0
  10. package/corpus/core/src/client/db-admin/export-utils.ts +13 -4
  11. package/corpus/core/src/client/db-admin/useAgentSync.ts +72 -0
  12. package/corpus/core/src/client/error-capture.ts +69 -7
  13. package/corpus/core/src/client/extensions/EmbeddedExtension.tsx +5 -1
  14. package/corpus/core/src/client/extensions/ExtensionViewer.tsx +53 -8
  15. package/corpus/core/src/client/extensions/InlineExtensionFrame.tsx +5 -1
  16. package/corpus/core/src/client/extensions/portable-extension.ts +1 -0
  17. package/corpus/core/src/client/org/OrgSwitcher.tsx +12 -9
  18. package/corpus/core/src/client/org/TeamPage.tsx +77 -71
  19. package/corpus/core/src/client/settings/SettingsPanel.tsx +205 -52
  20. package/corpus/core/src/client/settings/SettingsSection.tsx +8 -1
  21. package/corpus/core/src/client/settings/SettingsTabsPage.tsx +25 -9
  22. package/corpus/core/src/db-admin/agent-tools.ts +8 -2
  23. package/corpus/core/src/db-admin/operations.ts +116 -4
  24. package/corpus/core/src/db-admin/routes.ts +1 -0
  25. package/corpus/core/src/db-admin/types.ts +4 -0
  26. package/corpus/core/src/extensions/html-shell.ts +5 -4
  27. package/corpus/core/src/extensions/routes.ts +10 -0
  28. package/corpus/core/src/navigation/index.ts +1 -1
  29. package/corpus/core/src/resources/handlers.ts +10 -8
  30. package/corpus/core/src/server/poll.ts +293 -8
  31. package/corpus/core/src/styles/agent-native.css +27 -0
  32. package/corpus/core/src/templates/default/.agents/skills/actions/SKILL.md +5 -0
  33. package/corpus/core/src/templates/default/.agents/skills/adding-a-feature/SKILL.md +5 -0
  34. package/corpus/core/src/templates/default/.agents/skills/real-time-sync/SKILL.md +1 -1
  35. package/corpus/core/src/templates/default/.agents/skills/security/SKILL.md +7 -0
  36. package/corpus/core/src/templates/default/.agents/skills/storing-data/SKILL.md +5 -1
  37. package/corpus/core/src/templates/default/AGENTS.md +4 -2
  38. package/corpus/core/src/templates/headless/AGENTS.md +4 -0
  39. package/corpus/core/src/templates/workspace-core/.agents/skills/actions/SKILL.md +5 -0
  40. package/corpus/core/src/templates/workspace-core/.agents/skills/adding-a-feature/SKILL.md +5 -0
  41. package/corpus/core/src/templates/workspace-core/.agents/skills/context-awareness/SKILL.md +4 -0
  42. package/corpus/core/src/templates/workspace-core/.agents/skills/extensions/SKILL.md +6 -0
  43. package/corpus/core/src/templates/workspace-core/.agents/skills/performance/SKILL.md +4 -0
  44. package/corpus/core/src/templates/workspace-core/.agents/skills/real-time-sync/SKILL.md +1 -1
  45. package/corpus/core/src/templates/workspace-core/.agents/skills/security/SKILL.md +7 -0
  46. package/corpus/core/src/templates/workspace-core/.agents/skills/storing-data/SKILL.md +5 -1
  47. package/corpus/core/src/templates/workspace-core/AGENTS.md +7 -1
  48. package/corpus/core/src/templates/workspace-root/AGENTS.md +7 -1
  49. package/corpus/templates/analytics/.agents/skills/actions/SKILL.md +5 -0
  50. package/corpus/templates/analytics/.agents/skills/dashboard-management/SKILL.md +10 -0
  51. package/corpus/templates/analytics/.agents/skills/real-time-sync/SKILL.md +1 -1
  52. package/corpus/templates/analytics/.agents/skills/security/SKILL.md +7 -0
  53. package/corpus/templates/analytics/.agents/skills/storing-data/SKILL.md +5 -1
  54. package/corpus/templates/analytics/AGENTS.md +33 -14
  55. package/corpus/templates/analytics/actions/capture-test-error.ts +4 -0
  56. package/corpus/templates/analytics/actions/get-analytics-alert-rule-defaults.ts +23 -0
  57. package/corpus/templates/analytics/actions/get-error-issue.ts +1 -1
  58. package/corpus/templates/analytics/actions/list-analysis-revisions.ts +40 -0
  59. package/corpus/templates/analytics/actions/list-dashboard-revisions.ts +40 -0
  60. package/corpus/templates/analytics/actions/list-dashboard-usage-stats.ts +299 -0
  61. package/corpus/templates/analytics/actions/navigate.ts +4 -2
  62. package/corpus/templates/analytics/actions/restore-analysis-revision.ts +43 -0
  63. package/corpus/templates/analytics/actions/restore-dashboard-revision.ts +68 -0
  64. package/corpus/templates/analytics/actions/save-analytics-alert-rule.ts +14 -0
  65. package/corpus/templates/analytics/actions/save-monitor.ts +1 -1
  66. package/corpus/templates/analytics/actions/view-screen.ts +24 -0
  67. package/corpus/templates/analytics/app/components/analysis/AnalysisHistoryPanel.tsx +181 -0
  68. package/corpus/templates/analytics/app/components/dashboard/DashboardHistoryPanel.tsx +184 -0
  69. package/corpus/templates/analytics/app/components/layout/CommandPalette.tsx +22 -16
  70. package/corpus/templates/analytics/app/components/layout/Header.tsx +1 -1
  71. package/corpus/templates/analytics/app/components/layout/Sidebar.tsx +27 -21
  72. package/corpus/templates/analytics/app/hooks/use-analysis-revisions.ts +43 -0
  73. package/corpus/templates/analytics/app/hooks/use-dashboard-chat-context.ts +110 -0
  74. package/corpus/templates/analytics/app/hooks/use-dashboard-revisions.ts +43 -0
  75. package/corpus/templates/analytics/app/hooks/use-navigation-state.ts +8 -3
  76. package/corpus/templates/analytics/app/i18n/zh-TW.ts +64 -2
  77. package/corpus/templates/analytics/app/i18n-data.ts +783 -3
  78. package/corpus/templates/analytics/app/pages/Agents.tsx +359 -19
  79. package/corpus/templates/analytics/app/pages/Settings.tsx +3 -2
  80. package/corpus/templates/analytics/app/pages/adhoc/explorer-dashboard/index.tsx +34 -1
  81. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/index.tsx +28 -0
  82. package/corpus/templates/analytics/app/pages/analyses/AnalysisDetail.tsx +18 -1
  83. package/corpus/templates/analytics/app/pages/monitoring/ErrorsPanel.tsx +7 -10
  84. package/corpus/templates/analytics/app/pages/monitoring/errors/IssueDetail.tsx +479 -23
  85. package/corpus/templates/analytics/app/pages/monitoring/errors/IssueList.tsx +0 -9
  86. package/corpus/templates/analytics/app/pages/monitoring/errors/i18n.ts +11 -0
  87. package/corpus/templates/analytics/app/pages/monitoring/errors/types.ts +9 -1
  88. package/corpus/templates/analytics/app/pages/monitoring/uptime/MonitorFormPage.tsx +6 -3
  89. package/corpus/templates/analytics/app/pages/sessions/SessionDetailPage.tsx +26 -30
  90. package/corpus/templates/analytics/app/pages/sessions/SessionsPage.tsx +9 -99
  91. package/corpus/templates/analytics/app/pages/settings/AlertRulesSettingsCard.tsx +262 -104
  92. package/corpus/templates/analytics/app/routes/team.tsx +1 -1
  93. package/corpus/templates/analytics/changelog/2026-07-08-admins-can-audit-dashboard-usage-ownership-and-cleanup-signa.md +6 -0
  94. package/corpus/templates/analytics/changelog/2026-07-08-agent-monitoring-stays-available-to-non-admins.md +6 -0
  95. package/corpus/templates/analytics/changelog/2026-07-08-alert-rules-are-easier-to-scan-expand-and-edit-from-settings.md +6 -0
  96. package/corpus/templates/analytics/changelog/2026-07-08-analytics-alert-forms-remember-last-email-recipients.md +6 -0
  97. package/corpus/templates/analytics/changelog/2026-07-08-analytics-alert-rules-can-now-use-per-rule-slack-and-webhook.md +6 -0
  98. package/corpus/templates/analytics/changelog/2026-07-08-dashboard-history-and-chat-context.md +5 -0
  99. package/corpus/templates/analytics/changelog/2026-07-08-dashboard-usage-now-counts-explorer-dashboard-traffic.md +6 -0
  100. package/corpus/templates/analytics/changelog/2026-07-08-demo-mode-session-emails-are-filtered-and-anonymized.md +6 -0
  101. package/corpus/templates/analytics/changelog/2026-07-08-error-issue-detail-adds-stack-traces-and-frequency-bars.md +6 -0
  102. package/corpus/templates/analytics/changelog/2026-07-08-error-issue-detail-now-shows-the-latest-occurrence-message-a.md +6 -0
  103. package/corpus/templates/analytics/changelog/2026-07-08-monitoring-errors-only-show-test-action-when-empty.md +6 -0
  104. package/corpus/templates/analytics/changelog/2026-07-08-production-session-replay-now-requires-private-blob-storage-.md +6 -0
  105. package/corpus/templates/analytics/changelog/2026-07-08-shared-extension-links-now-show-a-clear-message-when-you-do-.md +6 -0
  106. package/corpus/templates/analytics/changelog/2026-07-08-team-settings-show-access-controls-next-to-member-lists.md +6 -0
  107. package/corpus/templates/analytics/changelog/2026-07-08-uptime-monitors-now-use-a-10-second-request-timeout-by-defau.md +6 -0
  108. package/corpus/templates/analytics/server/db/schema-monitoring.ts +1 -1
  109. package/corpus/templates/analytics/server/db/schema.ts +56 -0
  110. package/corpus/templates/analytics/server/lib/analytics-alerts.ts +92 -0
  111. package/corpus/templates/analytics/server/lib/dashboards-store.ts +334 -5
  112. package/corpus/templates/analytics/server/lib/error-capture.ts +231 -36
  113. package/corpus/templates/analytics/server/lib/session-replay.ts +114 -8
  114. package/corpus/templates/analytics/server/lib/uptime-monitors.ts +5 -4
  115. package/corpus/templates/analytics/server/plugins/db.ts +112 -2
  116. package/corpus/templates/analytics/server/routes/api/dashboard-agent-context.json.get.ts +1 -0
  117. package/corpus/templates/assets/.agents/skills/actions/SKILL.md +5 -0
  118. package/corpus/templates/assets/.agents/skills/real-time-sync/SKILL.md +1 -1
  119. package/corpus/templates/assets/.agents/skills/security/SKILL.md +7 -0
  120. package/corpus/templates/assets/.agents/skills/storing-data/SKILL.md +5 -1
  121. package/corpus/templates/assets/AGENTS.md +4 -0
  122. package/corpus/templates/assets/app/routes/settings.tsx +1 -1
  123. package/corpus/templates/assets/app/routes/team.tsx +1 -1
  124. package/corpus/templates/brain/.agents/skills/actions/SKILL.md +5 -0
  125. package/corpus/templates/brain/.agents/skills/adding-a-feature/SKILL.md +5 -0
  126. package/corpus/templates/brain/.agents/skills/real-time-sync/SKILL.md +1 -1
  127. package/corpus/templates/brain/.agents/skills/security/SKILL.md +7 -0
  128. package/corpus/templates/brain/AGENTS.md +4 -0
  129. package/corpus/templates/brain/app/routes/team.tsx +1 -1
  130. package/corpus/templates/calendar/.agents/skills/actions/SKILL.md +5 -0
  131. package/corpus/templates/calendar/.agents/skills/real-time-sync/SKILL.md +1 -1
  132. package/corpus/templates/calendar/.agents/skills/security/SKILL.md +7 -0
  133. package/corpus/templates/calendar/.agents/skills/storing-data/SKILL.md +5 -1
  134. package/corpus/templates/calendar/AGENTS.md +4 -0
  135. package/corpus/templates/calendar/app/components/calendar/DayView.tsx +11 -2
  136. package/corpus/templates/calendar/app/components/calendar/EventDetailPopover.tsx +21 -8
  137. package/corpus/templates/calendar/app/components/calendar/MonthView.tsx +7 -1
  138. package/corpus/templates/calendar/app/components/calendar/WeekView.tsx +11 -2
  139. package/corpus/templates/calendar/app/lib/popover-click-guard.ts +48 -4
  140. package/corpus/templates/calendar/app/pages/Settings.tsx +1 -1
  141. package/corpus/templates/calendar/app/routes/_app.team.tsx +1 -1
  142. package/corpus/templates/calendar/changelog/2026-07-08-clicking-empty-calendar-space-closes-an-open-event-popover-b.md +6 -0
  143. package/corpus/templates/chat/.agents/skills/actions/SKILL.md +5 -0
  144. package/corpus/templates/chat/.agents/skills/adding-a-feature/SKILL.md +5 -0
  145. package/corpus/templates/chat/.agents/skills/real-time-sync/SKILL.md +1 -1
  146. package/corpus/templates/chat/.agents/skills/security/SKILL.md +7 -0
  147. package/corpus/templates/chat/AGENTS.md +4 -0
  148. package/corpus/templates/chat/app/hooks/use-navigation-state.ts +1 -1
  149. package/corpus/templates/chat/app/routes/settings.tsx +2 -2
  150. package/corpus/templates/chat/app/routes/team.tsx +1 -1
  151. package/corpus/templates/clips/.agents/skills/actions/SKILL.md +5 -0
  152. package/corpus/templates/clips/.agents/skills/security/SKILL.md +7 -0
  153. package/corpus/templates/clips/AGENTS.md +4 -0
  154. package/corpus/templates/clips/actions/finalize-recording.ts +9 -3
  155. package/corpus/templates/clips/actions/set-thumbnail.ts +11 -2
  156. package/corpus/templates/clips/app/components/meetings/canvas-editor.tsx +1 -7
  157. package/corpus/templates/clips/app/components/player/player-controls.tsx +21 -13
  158. package/corpus/templates/clips/app/components/player/video-player.tsx +30 -75
  159. package/corpus/templates/clips/app/i18n/ar-SA.ts +6 -5
  160. package/corpus/templates/clips/app/i18n/de-DE.ts +6 -6
  161. package/corpus/templates/clips/app/i18n/en-US.ts +6 -5
  162. package/corpus/templates/clips/app/i18n/es-ES.ts +6 -5
  163. package/corpus/templates/clips/app/i18n/fr-FR.ts +6 -6
  164. package/corpus/templates/clips/app/i18n/hi-IN.ts +6 -5
  165. package/corpus/templates/clips/app/i18n/ja-JP.ts +6 -5
  166. package/corpus/templates/clips/app/i18n/ko-KR.ts +6 -5
  167. package/corpus/templates/clips/app/i18n/pt-BR.ts +6 -5
  168. package/corpus/templates/clips/app/i18n/zh-CN.ts +6 -5
  169. package/corpus/templates/clips/app/i18n/zh-TW.ts +6 -5
  170. package/corpus/templates/clips/app/routes/_app.meetings.$meetingId.tsx +51 -118
  171. package/corpus/templates/clips/changelog/2026-07-08-hosted-clip-uploads-now-clear-failed-buffered-chunks.md +6 -0
  172. package/corpus/templates/clips/changelog/2026-07-08-hosted-recording-uploads-now-avoid-sql-chunk-storage.md +6 -0
  173. package/corpus/templates/clips/changelog/2026-07-08-meeting-recaps-now-keep-summaries-action-items-and-transcrip.md +6 -0
  174. package/corpus/templates/clips/changelog/2026-07-08-video-playback-controls-now-match-loom-style-5-second-skips-.md +6 -0
  175. package/corpus/templates/clips/server/lib/recording-upload-state.ts +63 -0
  176. package/corpus/templates/clips/server/lib/video-storage.ts +4 -0
  177. package/corpus/templates/clips/server/routes/api/recordings/[recordingId]/thumbnail.post.ts +19 -13
  178. package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/chunk.post.ts +40 -1
  179. package/corpus/templates/content/.agents/skills/actions/SKILL.md +5 -0
  180. package/corpus/templates/content/.agents/skills/real-time-sync/SKILL.md +1 -1
  181. package/corpus/templates/content/.agents/skills/security/SKILL.md +7 -0
  182. package/corpus/templates/content/.agents/skills/storing-data/SKILL.md +5 -1
  183. package/corpus/templates/content/AGENTS.md +4 -0
  184. package/corpus/templates/content/app/routes/_app.settings.tsx +2 -2
  185. package/corpus/templates/content/app/routes/_app.team.tsx +1 -1
  186. package/corpus/templates/design/.agents/skills/actions/SKILL.md +5 -0
  187. package/corpus/templates/design/.agents/skills/security/SKILL.md +7 -0
  188. package/corpus/templates/design/AGENTS.md +4 -0
  189. package/corpus/templates/design/actions/take-design-screenshot.ts +12 -9
  190. package/corpus/templates/design/app/components/design/inspector/ImageFillControls.tsx +57 -13
  191. package/corpus/templates/design/app/routes/team.tsx +1 -1
  192. package/corpus/templates/design/changelog/2026-07-08-local-images-added-to-designs-now-upload-to-file-storage-ins.md +6 -0
  193. package/corpus/templates/dispatch/.agents/skills/actions/SKILL.md +5 -0
  194. package/corpus/templates/dispatch/.agents/skills/security/SKILL.md +7 -0
  195. package/corpus/templates/dispatch/AGENTS.md +4 -0
  196. package/corpus/templates/dispatch/app/hooks/use-navigation-state.ts +1 -1
  197. package/corpus/templates/dispatch/app/routes/settings.tsx +2 -2
  198. package/corpus/templates/dispatch/app/routes/team.tsx +1 -1
  199. package/corpus/templates/forms/.agents/skills/actions/SKILL.md +5 -0
  200. package/corpus/templates/forms/.agents/skills/real-time-sync/SKILL.md +1 -1
  201. package/corpus/templates/forms/.agents/skills/security/SKILL.md +7 -0
  202. package/corpus/templates/forms/.agents/skills/storing-data/SKILL.md +5 -1
  203. package/corpus/templates/forms/AGENTS.md +4 -0
  204. package/corpus/templates/forms/app/routes/_app.settings.tsx +2 -2
  205. package/corpus/templates/forms/app/routes/_app.team.tsx +1 -1
  206. package/corpus/templates/forms/shared/navigation.ts +1 -1
  207. package/corpus/templates/macros/.agents/skills/security/SKILL.md +7 -0
  208. package/corpus/templates/macros/AGENTS.md +4 -0
  209. package/corpus/templates/macros/app/routes/settings.tsx +2 -2
  210. package/corpus/templates/macros/app/routes/team.tsx +1 -1
  211. package/corpus/templates/mail/.agents/skills/actions/SKILL.md +5 -0
  212. package/corpus/templates/mail/.agents/skills/email-drafts/SKILL.md +1 -1
  213. package/corpus/templates/mail/.agents/skills/real-time-sync/SKILL.md +1 -1
  214. package/corpus/templates/mail/.agents/skills/security/SKILL.md +7 -0
  215. package/corpus/templates/mail/.agents/skills/storing-data/SKILL.md +5 -1
  216. package/corpus/templates/mail/AGENTS.md +4 -0
  217. package/corpus/templates/mail/changelog/2026-07-08-mail-attachments-in-hosted-environments-now-require-file-sto.md +6 -0
  218. package/corpus/templates/mail/server/handlers/media.ts +26 -1
  219. package/corpus/templates/mail/server/lib/outgoing-email.ts +24 -1
  220. package/corpus/templates/mail/server/lib/upload-store.ts +2 -1
  221. package/corpus/templates/plan/.agents/skills/actions/SKILL.md +5 -0
  222. package/corpus/templates/plan/.agents/skills/adding-a-feature/SKILL.md +5 -0
  223. package/corpus/templates/plan/.agents/skills/real-time-sync/SKILL.md +1 -1
  224. package/corpus/templates/plan/.agents/skills/security/SKILL.md +7 -0
  225. package/corpus/templates/plan/AGENTS.md +4 -0
  226. package/corpus/templates/plan/app/hooks/use-navigation-state.ts +1 -1
  227. package/corpus/templates/plan/app/routes/settings.tsx +2 -2
  228. package/corpus/templates/plan/app/routes/team.tsx +1 -1
  229. package/corpus/templates/plan/changelog/2026-07-08-hosted-plan-images-now-require-connected-storage.md +6 -0
  230. package/corpus/templates/plan/server/lib/plan-assets.ts +33 -4
  231. package/corpus/templates/slides/.agents/skills/actions/SKILL.md +5 -0
  232. package/corpus/templates/slides/.agents/skills/security/SKILL.md +7 -0
  233. package/corpus/templates/slides/AGENTS.md +4 -0
  234. package/corpus/templates/slides/actions/generate-image-api.ts +15 -3
  235. package/corpus/templates/slides/app/routes/settings.tsx +2 -2
  236. package/corpus/templates/slides/app/routes/team.tsx +1 -1
  237. package/corpus/templates/slides/changelog/2026-07-08-generated-slide-images-now-return-hosted-file-storage-urls-i.md +6 -0
  238. package/corpus/templates/slides/shared/api.ts +1 -1
  239. package/dist/application-state/store.d.ts.map +1 -1
  240. package/dist/application-state/store.js +8 -2
  241. package/dist/application-state/store.js.map +1 -1
  242. package/dist/client/AssistantChat.d.ts.map +1 -1
  243. package/dist/client/AssistantChat.js +24 -13
  244. package/dist/client/AssistantChat.js.map +1 -1
  245. package/dist/client/PoweredByBadge.d.ts +1 -1
  246. package/dist/client/PoweredByBadge.d.ts.map +1 -1
  247. package/dist/client/PoweredByBadge.js +3 -9
  248. package/dist/client/PoweredByBadge.js.map +1 -1
  249. package/dist/client/agent-chat-adapter.d.ts.map +1 -1
  250. package/dist/client/agent-chat-adapter.js +28 -9
  251. package/dist/client/agent-chat-adapter.js.map +1 -1
  252. package/dist/client/chat/widgets/DataTableWidget.d.ts.map +1 -1
  253. package/dist/client/chat/widgets/DataTableWidget.js +19 -2
  254. package/dist/client/chat/widgets/DataTableWidget.js.map +1 -1
  255. package/dist/client/db-admin/TableEditor.d.ts.map +1 -1
  256. package/dist/client/db-admin/TableEditor.js +19 -2
  257. package/dist/client/db-admin/TableEditor.js.map +1 -1
  258. package/dist/client/db-admin/export-utils.d.ts +2 -0
  259. package/dist/client/db-admin/export-utils.d.ts.map +1 -1
  260. package/dist/client/db-admin/export-utils.js +11 -3
  261. package/dist/client/db-admin/export-utils.js.map +1 -1
  262. package/dist/client/db-admin/useAgentSync.d.ts.map +1 -1
  263. package/dist/client/db-admin/useAgentSync.js +63 -0
  264. package/dist/client/db-admin/useAgentSync.js.map +1 -1
  265. package/dist/client/error-capture.d.ts.map +1 -1
  266. package/dist/client/error-capture.js +41 -7
  267. package/dist/client/error-capture.js.map +1 -1
  268. package/dist/client/extensions/EmbeddedExtension.d.ts.map +1 -1
  269. package/dist/client/extensions/EmbeddedExtension.js +3 -1
  270. package/dist/client/extensions/EmbeddedExtension.js.map +1 -1
  271. package/dist/client/extensions/ExtensionViewer.d.ts.map +1 -1
  272. package/dist/client/extensions/ExtensionViewer.js +32 -5
  273. package/dist/client/extensions/ExtensionViewer.js.map +1 -1
  274. package/dist/client/extensions/InlineExtensionFrame.d.ts.map +1 -1
  275. package/dist/client/extensions/InlineExtensionFrame.js +3 -1
  276. package/dist/client/extensions/InlineExtensionFrame.js.map +1 -1
  277. package/dist/client/extensions/portable-extension.d.ts.map +1 -1
  278. package/dist/client/extensions/portable-extension.js +1 -0
  279. package/dist/client/extensions/portable-extension.js.map +1 -1
  280. package/dist/client/org/OrgSwitcher.d.ts +1 -1
  281. package/dist/client/org/OrgSwitcher.d.ts.map +1 -1
  282. package/dist/client/org/OrgSwitcher.js +11 -6
  283. package/dist/client/org/OrgSwitcher.js.map +1 -1
  284. package/dist/client/org/TeamPage.d.ts.map +1 -1
  285. package/dist/client/org/TeamPage.js +5 -5
  286. package/dist/client/org/TeamPage.js.map +1 -1
  287. package/dist/client/settings/SettingsPanel.d.ts.map +1 -1
  288. package/dist/client/settings/SettingsPanel.js +37 -14
  289. package/dist/client/settings/SettingsPanel.js.map +1 -1
  290. package/dist/client/settings/SettingsSection.js +1 -1
  291. package/dist/client/settings/SettingsSection.js.map +1 -1
  292. package/dist/client/settings/SettingsTabsPage.d.ts.map +1 -1
  293. package/dist/client/settings/SettingsTabsPage.js +21 -10
  294. package/dist/client/settings/SettingsTabsPage.js.map +1 -1
  295. package/dist/collab/routes.d.ts +1 -1
  296. package/dist/db-admin/agent-tools.d.ts.map +1 -1
  297. package/dist/db-admin/agent-tools.js +7 -2
  298. package/dist/db-admin/agent-tools.js.map +1 -1
  299. package/dist/db-admin/operations.d.ts.map +1 -1
  300. package/dist/db-admin/operations.js +90 -4
  301. package/dist/db-admin/operations.js.map +1 -1
  302. package/dist/db-admin/routes.d.ts.map +1 -1
  303. package/dist/db-admin/routes.js +1 -0
  304. package/dist/db-admin/routes.js.map +1 -1
  305. package/dist/db-admin/types.d.ts +4 -0
  306. package/dist/db-admin/types.d.ts.map +1 -1
  307. package/dist/db-admin/types.js.map +1 -1
  308. package/dist/extensions/html-shell.d.ts +5 -4
  309. package/dist/extensions/html-shell.d.ts.map +1 -1
  310. package/dist/extensions/html-shell.js.map +1 -1
  311. package/dist/extensions/routes.d.ts.map +1 -1
  312. package/dist/extensions/routes.js +8 -0
  313. package/dist/extensions/routes.js.map +1 -1
  314. package/dist/navigation/index.d.ts +1 -1
  315. package/dist/navigation/index.d.ts.map +1 -1
  316. package/dist/navigation/index.js +1 -1
  317. package/dist/navigation/index.js.map +1 -1
  318. package/dist/notifications/routes.d.ts +1 -1
  319. package/dist/observability/routes.d.ts +1 -1
  320. package/dist/resources/handlers.d.ts +6 -1
  321. package/dist/resources/handlers.d.ts.map +1 -1
  322. package/dist/resources/handlers.js +9 -8
  323. package/dist/resources/handlers.js.map +1 -1
  324. package/dist/server/poll.d.ts +12 -4
  325. package/dist/server/poll.d.ts.map +1 -1
  326. package/dist/server/poll.js +236 -9
  327. package/dist/server/poll.js.map +1 -1
  328. package/dist/styles/agent-native.css +27 -0
  329. package/dist/templates/default/.agents/skills/actions/SKILL.md +5 -0
  330. package/dist/templates/default/.agents/skills/adding-a-feature/SKILL.md +5 -0
  331. package/dist/templates/default/.agents/skills/real-time-sync/SKILL.md +1 -1
  332. package/dist/templates/default/.agents/skills/security/SKILL.md +7 -0
  333. package/dist/templates/default/.agents/skills/storing-data/SKILL.md +5 -1
  334. package/dist/templates/default/AGENTS.md +4 -2
  335. package/dist/templates/headless/AGENTS.md +4 -0
  336. package/dist/templates/workspace-core/.agents/skills/actions/SKILL.md +5 -0
  337. package/dist/templates/workspace-core/.agents/skills/adding-a-feature/SKILL.md +5 -0
  338. package/dist/templates/workspace-core/.agents/skills/context-awareness/SKILL.md +4 -0
  339. package/dist/templates/workspace-core/.agents/skills/extensions/SKILL.md +6 -0
  340. package/dist/templates/workspace-core/.agents/skills/performance/SKILL.md +4 -0
  341. package/dist/templates/workspace-core/.agents/skills/real-time-sync/SKILL.md +1 -1
  342. package/dist/templates/workspace-core/.agents/skills/security/SKILL.md +7 -0
  343. package/dist/templates/workspace-core/.agents/skills/storing-data/SKILL.md +5 -1
  344. package/dist/templates/workspace-core/AGENTS.md +7 -1
  345. package/dist/templates/workspace-root/AGENTS.md +7 -1
  346. package/package.json +1 -1
  347. package/src/templates/default/.agents/skills/actions/SKILL.md +5 -0
  348. package/src/templates/default/.agents/skills/adding-a-feature/SKILL.md +5 -0
  349. package/src/templates/default/.agents/skills/real-time-sync/SKILL.md +1 -1
  350. package/src/templates/default/.agents/skills/security/SKILL.md +7 -0
  351. package/src/templates/default/.agents/skills/storing-data/SKILL.md +5 -1
  352. package/src/templates/default/AGENTS.md +4 -2
  353. package/src/templates/headless/AGENTS.md +4 -0
  354. package/src/templates/workspace-core/.agents/skills/actions/SKILL.md +5 -0
  355. package/src/templates/workspace-core/.agents/skills/adding-a-feature/SKILL.md +5 -0
  356. package/src/templates/workspace-core/.agents/skills/context-awareness/SKILL.md +4 -0
  357. package/src/templates/workspace-core/.agents/skills/extensions/SKILL.md +6 -0
  358. package/src/templates/workspace-core/.agents/skills/performance/SKILL.md +4 -0
  359. package/src/templates/workspace-core/.agents/skills/real-time-sync/SKILL.md +1 -1
  360. package/src/templates/workspace-core/.agents/skills/security/SKILL.md +7 -0
  361. package/src/templates/workspace-core/.agents/skills/storing-data/SKILL.md +5 -1
  362. package/src/templates/workspace-core/AGENTS.md +7 -1
  363. package/src/templates/workspace-root/AGENTS.md +7 -1
package/corpus/README.md CHANGED
@@ -28,4 +28,4 @@ rg -n "defineAction|useActionQuery" node_modules/@agent-native/core/corpus
28
28
  ## Generated Counts
29
29
 
30
30
  - core files: 2153
31
- - template files: 5000
31
+ - template files: 5035
@@ -1,5 +1,19 @@
1
1
  # @agent-native/core
2
2
 
3
+ ## 0.92.1
4
+
5
+ ### Patch Changes
6
+
7
+ - 1d13434: Allow extension iframes to trigger user-initiated downloads and add CSV export to standard data table widgets.
8
+ - 1d13434: Remove the GitHub icon from the free and open source badge on public booking pages.
9
+ - 1d13434: Make framework polling cheaper with durable sync events, remove Dispatch's short app-list polling intervals, preview large DB admin cells by default to avoid accidental blob transfers, and require configured file storage for binary resource uploads instead of storing base64 blobs in SQL.
10
+ - 1d13434: Stage database-admin table selections as agent chat context chips and selected-object application state so users can ask the agent about the active table.
11
+ - 1d13434: Show a clear unavailable state for shared extension links that the viewer cannot access, instead of leaving the standalone extension page looking blank.
12
+ - 1d13434: Filter known browser and extension noise from first-party error auto-capture while preserving real app fetch failures.
13
+ - 1d13434: Recover stale background chat runs instead of surfacing them as terminal failures, and keep chat handoffs from restoring stale server snapshots over fresher completed replies.
14
+ - 1d13434: Fix durable polling cursors, DB admin large-cell safeguards, extension unavailable states, and stale chat snapshot handling.
15
+ - 1d13434: Show organization access controls alongside long team member lists when the Team settings surface has enough width.
16
+
3
17
  ## 0.92.0
4
18
 
5
19
  ### Minor Changes
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-native/core",
3
- "version": "0.92.0",
3
+ "version": "0.92.1",
4
4
  "description": "Framework for agent-native application development — where AI agents and UI share SQL state, actions, and context",
5
5
  "homepage": "https://github.com/BuilderIO/agent-native#readme",
6
6
  "bugs": {
@@ -1,5 +1,6 @@
1
1
  import {
2
2
  getDbExec,
3
+ isLocalDatabase,
3
4
  isConnectionError,
4
5
  isPostgres,
5
6
  intType,
@@ -10,6 +11,7 @@ import type { StoreWriteOptions } from "../settings/store.js";
10
11
  import { emitAppStateChange, emitAppStateDelete } from "./emitter.js";
11
12
 
12
13
  let _initPromise: Promise<void> | undefined;
14
+ const MAX_HOSTED_APP_STATE_VALUE_BYTES = 1024 * 1024;
13
15
 
14
16
  // Escapes LIKE wildcards (`%`, `_`) and the escape char itself so a caller's
15
17
  // literal prefix is matched verbatim. Used with `ESCAPE '!'` in prefix queries
@@ -123,11 +125,20 @@ export async function appStatePut(
123
125
  ): Promise<void> {
124
126
  await ensureTable();
125
127
  const client = getDbExec();
128
+ const serialized = JSON.stringify(value);
129
+ if (
130
+ !isLocalDatabase() &&
131
+ Buffer.byteLength(serialized, "utf8") > MAX_HOSTED_APP_STATE_VALUE_BYTES
132
+ ) {
133
+ throw new Error(
134
+ `application_state value "${key}" is too large for hosted SQL storage. Store large files, base64, or blobs in file storage and write only a URL or handle.`,
135
+ );
136
+ }
126
137
  await client.execute({
127
138
  sql: isPostgres()
128
139
  ? `INSERT INTO application_state (session_id, key, value, updated_at) VALUES (?, ?, ?, ?) ON CONFLICT (session_id, key) DO UPDATE SET value=EXCLUDED.value, updated_at=EXCLUDED.updated_at`
129
140
  : `INSERT OR REPLACE INTO application_state (session_id, key, value, updated_at) VALUES (?, ?, ?, ?)`,
130
- args: [sessionId, key, JSON.stringify(value), Date.now()],
141
+ args: [sessionId, key, serialized, Date.now()],
131
142
  });
132
143
  emitAppStateChange(key, options?.requestSource, sessionId);
133
144
  }
@@ -1894,7 +1894,9 @@ const AssistantChatInner = forwardRef<
1894
1894
  repo,
1895
1895
  );
1896
1896
  } catch {
1897
- shouldImport = true;
1897
+ // If the runtime/export comparison itself fails, do not fail open by
1898
+ // importing a server snapshot that may be stale relative to local UI.
1899
+ shouldImport = false;
1898
1900
  }
1899
1901
  if (shouldImport) {
1900
1902
  if (options?.markTitleGenerated) {
@@ -1907,7 +1909,7 @@ const AssistantChatInner = forwardRef<
1907
1909
  settled = false;
1908
1910
  }
1909
1911
  }
1910
- if (Array.isArray(repo?.queuedMessages)) {
1912
+ if (settled && Array.isArray(repo?.queuedMessages)) {
1911
1913
  const incomingQueue = repo.queuedMessages as QueuedMessage[];
1912
1914
  const incomingSerialized = JSON.stringify(incomingQueue);
1913
1915
  const currentSerialized = JSON.stringify(queuedMessagesRef.current);
@@ -2521,18 +2523,29 @@ const AssistantChatInner = forwardRef<
2521
2523
  markTitleGenerated: true,
2522
2524
  });
2523
2525
  if (repo) {
2524
- const { title, preview } = extractThreadMeta(repo);
2525
- writeCachedThreadSnapshot(apiUrl, threadId, {
2526
- threadData:
2527
- typeof data.threadData === "string"
2528
- ? data.threadData
2529
- : JSON.stringify(data.threadData),
2530
- title: data.title || title,
2531
- preview,
2532
- messageCount: Array.isArray(repo.messages)
2533
- ? repo.messages.length
2534
- : 0,
2535
- });
2526
+ let shouldCacheServerSnapshot = true;
2527
+ try {
2528
+ shouldCacheServerSnapshot = shouldImportServerThreadData(
2529
+ normalizeThreadRepository(threadRuntime.export()),
2530
+ repo,
2531
+ );
2532
+ } catch {
2533
+ shouldCacheServerSnapshot = false;
2534
+ }
2535
+ if (shouldCacheServerSnapshot) {
2536
+ const { title, preview } = extractThreadMeta(repo);
2537
+ writeCachedThreadSnapshot(apiUrl, threadId, {
2538
+ threadData:
2539
+ typeof data.threadData === "string"
2540
+ ? data.threadData
2541
+ : JSON.stringify(data.threadData),
2542
+ title: data.title || title,
2543
+ preview,
2544
+ messageCount: Array.isArray(repo.messages)
2545
+ ? repo.messages.length
2546
+ : 0,
2547
+ });
2548
+ }
2536
2549
  }
2537
2550
  }
2538
2551
  // Also skip title generation if thread already has a title
@@ -1,4 +1,3 @@
1
- import { IconBrandGithub } from "@tabler/icons-react";
2
1
  import type { CSSProperties } from "react";
3
2
 
4
3
  import { appPath } from "./api-path.js";
@@ -192,7 +191,7 @@ export function PoweredByBadge({
192
191
  }
193
192
 
194
193
  /**
195
- * Small GitHub badge: "Free and open source"
194
+ * Small badge: "Free and open source"
196
195
  *
197
196
  * Intended to pair with PoweredByBadge on public pages.
198
197
  */
@@ -209,11 +208,6 @@ export function OpenSourceBadge({
209
208
  return (
210
209
  <>
211
210
  <style>{`
212
- .an-open-source-badge svg {
213
- width: 15px;
214
- height: 15px;
215
- flex: none;
216
- }
217
211
  .an-open-source-badge {
218
212
  background: transparent !important;
219
213
  border-color: transparent !important;
@@ -283,7 +277,6 @@ export function OpenSourceBadge({
283
277
  : containerStyle(position)
284
278
  }
285
279
  >
286
- <IconBrandGithub aria-hidden="true" stroke={1.8} />
287
280
  <span>Free and open source</span>
288
281
  </a>
289
282
  </>
@@ -2276,7 +2276,11 @@ export function createAgentChatAdapter(
2276
2276
  // ends the turn from the client side.
2277
2277
  const followBackgroundTurn = async function* (
2278
2278
  initialSignal: AgentAutoContinueSignal,
2279
- ): AsyncGenerator<ChatModelRunResult, void, unknown> {
2279
+ ): AsyncGenerator<
2280
+ ChatModelRunResult,
2281
+ "completed" | "client_continue",
2282
+ unknown
2283
+ > {
2280
2284
  lastAutoContinueReason = initialSignal.reason;
2281
2285
  if (initialSignal.activityTrail.length > 0) {
2282
2286
  lastActivityTrail = [...initialSignal.activityTrail];
@@ -2310,7 +2314,7 @@ export function createAgentChatAdapter(
2310
2314
  while (true) {
2311
2315
  if (abortSignal.aborted) {
2312
2316
  clearActiveRun();
2313
- return;
2317
+ return "completed";
2314
2318
  }
2315
2319
  let active: Record<string, unknown> | null = null;
2316
2320
  try {
@@ -2324,7 +2328,7 @@ export function createAgentChatAdapter(
2324
2328
  } catch (pollErr: unknown) {
2325
2329
  if (pollErr instanceof Error && pollErr.name === "AbortError") {
2326
2330
  clearActiveRun();
2327
- return;
2331
+ return "completed";
2328
2332
  }
2329
2333
  // Transient poll failure — counts as "no active run" this tick.
2330
2334
  }
@@ -2351,8 +2355,25 @@ export function createAgentChatAdapter(
2351
2355
  const isTerminal =
2352
2356
  activeStatus === "completed" || activeStatus === "errored";
2353
2357
  if (isTerminal && replayedTerminalRunIds.has(activeRunId)) {
2358
+ if (
2359
+ lastAutoContinueReason === "stale_run" &&
2360
+ lastRecoverableRunError?.errorCode === "stale_run"
2361
+ ) {
2362
+ const continuation = prepareAutoContinuation(
2363
+ new AgentAutoContinueSignal({
2364
+ reason: "stale_run",
2365
+ errorInfo: lastRecoverableRunError,
2366
+ activityTrail: lastActivityTrail,
2367
+ }),
2368
+ );
2369
+ if (continuation.ok) {
2370
+ dispatchResumingUiEvent();
2371
+ await delay(250, abortSignal);
2372
+ return "client_continue";
2373
+ }
2374
+ }
2354
2375
  yield* emitBackgroundTerminalOutcome(active);
2355
- return;
2376
+ return "completed";
2356
2377
  }
2357
2378
  const previousRunId = runId;
2358
2379
  runId = activeRunId;
@@ -2365,7 +2386,7 @@ export function createAgentChatAdapter(
2365
2386
  }
2366
2387
  const attach = yield* followAttachOnce();
2367
2388
  if (attach === "completed" || attach === "aborted") {
2368
- return;
2389
+ return "completed";
2369
2390
  }
2370
2391
  if (isTerminal) {
2371
2392
  replayedTerminalRunIds.add(activeRunId);
@@ -2387,7 +2408,7 @@ export function createAgentChatAdapter(
2387
2408
  BACKGROUND_FOLLOW_IDLE_TIMEOUT_MS
2388
2409
  ) {
2389
2410
  yield* emitBackgroundTerminalOutcome(lastSeenActive);
2390
- return;
2411
+ return "completed";
2391
2412
  }
2392
2413
  }
2393
2414
  dispatchResumingUiEvent();
@@ -2407,13 +2428,13 @@ export function createAgentChatAdapter(
2407
2428
  },
2408
2429
  );
2409
2430
  yield* emitBackgroundTerminalOutcome(lastSeenActive);
2410
- return;
2431
+ return "completed";
2411
2432
  }
2412
2433
  }
2413
2434
  await delay(BACKGROUND_FOLLOW_POLL_INTERVAL_MS, abortSignal);
2414
2435
  if (abortSignal.aborted) {
2415
2436
  clearActiveRun();
2416
- return;
2437
+ return "completed";
2417
2438
  }
2418
2439
  }
2419
2440
  };
@@ -3003,7 +3024,10 @@ export function createAgentChatAdapter(
3003
3024
  // client/server recovery race: client watchdog signals here are
3004
3025
  // just "reattach", not "recover".
3005
3026
  if (shouldFollowServerContinuation(err) && threadId) {
3006
- yield* followBackgroundTurn(err);
3027
+ const followOutcome = yield* followBackgroundTurn(err);
3028
+ if (followOutcome === "client_continue") {
3029
+ continue;
3030
+ }
3007
3031
  return;
3008
3032
  }
3009
3033
  if (err.reason === "no_progress") {
@@ -3182,9 +3206,12 @@ export function createAgentChatAdapter(
3182
3206
  // before any response headers arrived has no dispatch mode yet
3183
3207
  // and keeps the foreground startup-retry path.)
3184
3208
  if (shouldFollowServerContinuation() && threadId) {
3185
- yield* followBackgroundTurn(
3209
+ const followOutcome = yield* followBackgroundTurn(
3186
3210
  new AgentAutoContinueSignal({ reason: "stream_ended" }),
3187
3211
  );
3212
+ if (followOutcome === "client_continue") {
3213
+ continue;
3214
+ }
3188
3215
  return;
3189
3216
  }
3190
3217
 
@@ -1,8 +1,20 @@
1
- import { IconExternalLink, IconTable } from "@tabler/icons-react";
1
+ import {
2
+ IconDots,
3
+ IconDownload,
4
+ IconExternalLink,
5
+ IconTable,
6
+ } from "@tabler/icons-react";
2
7
 
3
8
  import { requestAgentSidebarOpen } from "../../agent-sidebar-state.js";
4
9
  import { appPath } from "../../api-path.js";
5
10
  import { startAgentChatViewTransition } from "../../chat-view-transition.js";
11
+ import {
12
+ DropdownMenu,
13
+ DropdownMenuContent,
14
+ DropdownMenuItem,
15
+ DropdownMenuTrigger,
16
+ } from "../../components/ui/dropdown-menu.js";
17
+ import { downloadFile, toCSVTable } from "../../db-admin/export-utils.js";
6
18
  import { cn } from "../../utils.js";
7
19
  import type { DataTableWidget as DataTableWidgetData } from "./data-widget-types.js";
8
20
 
@@ -82,6 +94,15 @@ function navigateSameAppHref(href: string): void {
82
94
  });
83
95
  }
84
96
 
97
+ function slugifyFilenamePart(value: string | undefined): string {
98
+ const slug = (value ?? "data-table")
99
+ .trim()
100
+ .toLowerCase()
101
+ .replace(/[^a-z0-9]+/g, "-")
102
+ .replace(/^-+|-+$/g, "");
103
+ return slug || "data-table";
104
+ }
105
+
85
106
  export function DataTableWidget({
86
107
  table,
87
108
  action,
@@ -91,6 +112,19 @@ export function DataTableWidget({
91
112
  }) {
92
113
  const rows = table.rows ?? [];
93
114
  const actionHref = action ? normalizeActionHref(action.href) : null;
115
+ const canExportCsv = table.columns.length > 0;
116
+ const exportCsv = () => {
117
+ if (!canExportCsv) return;
118
+ const stamp = new Date().toISOString().slice(0, 10);
119
+ downloadFile(
120
+ `${slugifyFilenamePart(table.title)}-${stamp}.csv`,
121
+ "text/csv;charset=utf-8",
122
+ toCSVTable(
123
+ table.columns.map((column) => column.label),
124
+ rows.map((row) => table.columns.map((column) => row[column.key])),
125
+ ),
126
+ );
127
+ };
94
128
 
95
129
  return (
96
130
  <div className="my-1.5 overflow-hidden rounded-lg border border-border bg-background text-foreground shadow-sm">
@@ -131,6 +165,23 @@ export function DataTableWidget({
131
165
  <IconExternalLink className="h-3 w-3" />
132
166
  </a>
133
167
  ) : null}
168
+ <DropdownMenu>
169
+ <DropdownMenuTrigger asChild>
170
+ <button
171
+ type="button"
172
+ aria-label="Data table options"
173
+ className="inline-flex size-7 shrink-0 items-center justify-center rounded-md text-muted-foreground transition-colors hover:bg-muted hover:text-foreground"
174
+ >
175
+ <IconDots className="h-3.5 w-3.5" />
176
+ </button>
177
+ </DropdownMenuTrigger>
178
+ <DropdownMenuContent align="end" className="w-44">
179
+ <DropdownMenuItem onSelect={exportCsv} disabled={!canExportCsv}>
180
+ <IconDownload className="mr-2 h-3.5 w-3.5" />
181
+ Download CSV
182
+ </DropdownMenuItem>
183
+ </DropdownMenuContent>
184
+ </DropdownMenu>
134
185
  </div>
135
186
  <div className="max-h-[360px] overflow-auto">
136
187
  <table className="w-full min-w-[420px] border-collapse text-xs">
@@ -7,6 +7,8 @@ import {
7
7
  IconCode,
8
8
  IconArrowBackUp,
9
9
  IconDeviceFloppy,
10
+ IconDots,
11
+ IconDownload,
10
12
  IconChevronLeft,
11
13
  IconChevronRight,
12
14
  IconChevronsLeft,
@@ -25,6 +27,12 @@ import type {
25
27
  DbAdminSort,
26
28
  DbAdminMutationResult,
27
29
  } from "../../db-admin/types.js";
30
+ import {
31
+ DropdownMenu,
32
+ DropdownMenuContent,
33
+ DropdownMenuItem,
34
+ DropdownMenuTrigger,
35
+ } from "../components/ui/dropdown-menu.js";
28
36
  import {
29
37
  Popover,
30
38
  PopoverContent,
@@ -33,6 +41,7 @@ import {
33
41
  import { cn } from "../utils.js";
34
42
  import { useChangeset, pkStringFor } from "./changeset.js";
35
43
  import { DataGrid, type GridRow, type ActiveCell } from "./DataGrid.js";
44
+ import { downloadFile, toCSVTable } from "./export-utils.js";
36
45
  import { FilterBar } from "./FilterBar.js";
37
46
  import { RowSidePanel, type RowSidePanelMode } from "./RowSidePanel.js";
38
47
  import { loadGridState, saveGridState } from "./storage.js";
@@ -54,6 +63,15 @@ export interface TableEditorProps {
54
63
  const DEFAULT_PAGE_SIZE = 100;
55
64
  const PAGE_SIZES = [25, 50, 100, 250, 500];
56
65
 
66
+ function slugifyFilenamePart(value: string): string {
67
+ const slug = value
68
+ .trim()
69
+ .toLowerCase()
70
+ .replace(/[^a-z0-9]+/g, "-")
71
+ .replace(/^-+|-+$/g, "");
72
+ return slug || "table";
73
+ }
74
+
57
75
  export function TableEditor({
58
76
  table,
59
77
  dialect: _dialect,
@@ -300,6 +318,20 @@ export function TableEditor({
300
318
  }
301
319
 
302
320
  const noPk = schema.primaryKey.length === 0;
321
+ const exportCurrentPageCsv = () => {
322
+ const columns = schema.columns.map((column) => column.name);
323
+ const stamp = new Date().toISOString().slice(0, 10);
324
+ downloadFile(
325
+ `${slugifyFilenamePart(table)}-${stamp}.csv`,
326
+ "text/csv;charset=utf-8",
327
+ toCSVTable(
328
+ columns,
329
+ gridRows
330
+ .filter((row) => !row.isDeleted)
331
+ .map((row) => columns.map((column) => row.values[column])),
332
+ ),
333
+ );
334
+ };
303
335
 
304
336
  return (
305
337
  <div className="flex h-full min-h-0 flex-col">
@@ -337,6 +369,23 @@ export function TableEditor({
337
369
  primary
338
370
  />
339
371
  )}
372
+ <DropdownMenu>
373
+ <DropdownMenuTrigger asChild>
374
+ <button
375
+ type="button"
376
+ aria-label="Table options"
377
+ className="inline-flex h-7 w-7 cursor-pointer items-center justify-center rounded-md border border-border text-muted-foreground hover:bg-muted hover:text-foreground"
378
+ >
379
+ <IconDots className="h-3.5 w-3.5" />
380
+ </button>
381
+ </DropdownMenuTrigger>
382
+ <DropdownMenuContent align="end" className="w-44">
383
+ <DropdownMenuItem onSelect={exportCurrentPageCsv}>
384
+ <IconDownload className="mr-2 h-3.5 w-3.5" />
385
+ Download CSV
386
+ </DropdownMenuItem>
387
+ </DropdownMenuContent>
388
+ </DropdownMenu>
340
389
  </div>
341
390
  </div>
342
391
 
@@ -16,6 +16,9 @@ function cellToCSV(value: unknown): string {
16
16
  } else {
17
17
  str = String(value);
18
18
  }
19
+ // Spreadsheet apps treat leading =, +, -, and @ as formulas. Prefix with an
20
+ // apostrophe so exported CSV opens as literal text instead of executing.
21
+ if (/^[=+\-@]/.test(str)) str = `'${str}`;
19
22
  // Quote when the value contains a comma, quote, CR, or LF. Escape embedded
20
23
  // double-quotes by doubling them (RFC 4180).
21
24
  if (/[",\r\n]/.test(str)) {
@@ -24,16 +27,22 @@ function cellToCSV(value: unknown): string {
24
27
  return str;
25
28
  }
26
29
 
30
+ /** Render a matrix as RFC-4180-style CSV with a header row. */
31
+ export function toCSVTable(headers: string[], rows: unknown[][]): string {
32
+ const header = headers.map(cellToCSV).join(",");
33
+ const body = rows.map((row) => row.map(cellToCSV).join(","));
34
+ return [header, ...body].join("\r\n");
35
+ }
36
+
27
37
  /** Render rows as RFC-4180-style CSV with a header row of the given columns. */
28
38
  export function toCSV(
29
39
  columns: string[],
30
40
  rows: Record<string, unknown>[],
31
41
  ): string {
32
- const header = columns.map(cellToCSV).join(",");
33
- const body = rows.map((row) =>
34
- columns.map((col) => cellToCSV(row[col])).join(","),
42
+ return toCSVTable(
43
+ columns,
44
+ rows.map((row) => columns.map((col) => row[col])),
35
45
  );
36
- return [header, ...body].join("\r\n");
37
46
  }
38
47
 
39
48
  /** Render rows as a pretty-printed JSON array. */
@@ -14,7 +14,16 @@
14
14
  */
15
15
  import { useEffect, useRef } from "react";
16
16
 
17
+ import {
18
+ removeAgentChatContextItem,
19
+ setAgentChatContextItem,
20
+ } from "../agent-chat.js";
17
21
  import { agentNativePath } from "../api-path.js";
22
+ import {
23
+ deleteClientAppState,
24
+ readClientAppState,
25
+ setClientAppState,
26
+ } from "../application-state.js";
18
27
 
19
28
  const NAVIGATION_PATH = agentNativePath(
20
29
  "/_agent-native/application-state/navigation",
@@ -24,6 +33,9 @@ const NAVIGATE_PATH = agentNativePath(
24
33
  );
25
34
 
26
35
  const POLL_INTERVAL_MS = 1500;
36
+ const TABLE_CONTEXT_KEY = "database-selected-table";
37
+ const SELECTED_OBJECT_STATE_KEY = "selected-object";
38
+ const SELECTED_OBJECT_SOURCE_FIELD = "__agentNativeSelectedObjectSource";
27
39
 
28
40
  let cachedSource: string | null = null;
29
41
 
@@ -55,6 +67,23 @@ function headers(extra?: Record<string, string>): Record<string, string> {
55
67
  return h;
56
68
  }
57
69
 
70
+ async function deleteSelectedObjectIfOwned(source: string | undefined) {
71
+ if (!source) return;
72
+ try {
73
+ const current = await readClientAppState<Record<string, unknown>>(
74
+ SELECTED_OBJECT_STATE_KEY,
75
+ );
76
+ if (current?.[SELECTED_OBJECT_SOURCE_FIELD] !== source) return;
77
+ await deleteClientAppState(SELECTED_OBJECT_STATE_KEY, {
78
+ keepalive: true,
79
+ requestSource: source,
80
+ });
81
+ } catch {
82
+ // Best effort only; stale selected-object context is less harmful than
83
+ // clearing a selection owned by another tab.
84
+ }
85
+ }
86
+
58
87
  export interface DbAdminNavigationState {
59
88
  view: "database";
60
89
  table: string | null;
@@ -88,6 +117,49 @@ export function useDbAdminAgentSync({
88
117
  body: JSON.stringify(state),
89
118
  }).catch(() => {});
90
119
  }, [enabled, table, mode]);
120
+
121
+ useEffect(() => {
122
+ if (!enabled) return;
123
+ const source = requestSource();
124
+ if (!table) {
125
+ removeAgentChatContextItem({
126
+ key: TABLE_CONTEXT_KEY,
127
+ openSidebar: false,
128
+ });
129
+ deleteSelectedObjectIfOwned(source);
130
+ return;
131
+ }
132
+
133
+ const selection = {
134
+ type: "database-table",
135
+ table,
136
+ mode,
137
+ [SELECTED_OBJECT_SOURCE_FIELD]: source,
138
+ };
139
+ setAgentChatContextItem({
140
+ key: TABLE_CONTEXT_KEY,
141
+ title: `Table: ${table}`,
142
+ context: [
143
+ `The user currently has this database table selected: ${table}.`,
144
+ `Database admin mode: ${mode}`,
145
+ "Use the database admin actions and current-screen context to inspect rows, schema, or run SQL against this table.",
146
+ ].join("\n"),
147
+ openSidebar: false,
148
+ focus: false,
149
+ });
150
+ setClientAppState(SELECTED_OBJECT_STATE_KEY, selection, {
151
+ keepalive: true,
152
+ requestSource: source,
153
+ }).catch(() => {});
154
+
155
+ return () => {
156
+ removeAgentChatContextItem({
157
+ key: TABLE_CONTEXT_KEY,
158
+ openSidebar: false,
159
+ });
160
+ deleteSelectedObjectIfOwned(source);
161
+ };
162
+ }, [enabled, table, mode]);
91
163
  }
92
164
 
93
165
  interface NavigateCommand {