@agent-native/core 0.90.11 → 0.91.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 (322) hide show
  1. package/corpus/README.md +2 -2
  2. package/corpus/core/CHANGELOG.md +34 -0
  3. package/corpus/core/docs/content/toolkit-settings.mdx +56 -3
  4. package/corpus/core/package.json +2 -1
  5. package/corpus/core/src/agent/run-ownership.ts +29 -1
  6. package/corpus/core/src/changelog/parse.ts +78 -0
  7. package/corpus/core/src/chat-threads/schema.ts +43 -0
  8. package/corpus/core/src/chat-threads/store.ts +144 -12
  9. package/corpus/core/src/cli/design-connect.ts +53 -9
  10. package/corpus/core/src/cli/workspace-dev.ts +25 -5
  11. package/corpus/core/src/client/AgentPanel.tsx +79 -14
  12. package/corpus/core/src/client/AssistantChat.tsx +359 -425
  13. package/corpus/core/src/client/analytics-session.ts +70 -0
  14. package/corpus/core/src/client/analytics.ts +175 -49
  15. package/corpus/core/src/client/chat/message-components.tsx +22 -2
  16. package/corpus/core/src/client/components/ui/message-scroller.tsx +131 -0
  17. package/corpus/core/src/client/conversation/AgentConversation.tsx +63 -41
  18. package/corpus/core/src/client/error-capture.ts +616 -0
  19. package/corpus/core/src/client/index.ts +12 -0
  20. package/corpus/core/src/client/session-replay.ts +57 -7
  21. package/corpus/core/src/client/settings/SettingsPanel.tsx +123 -1
  22. package/corpus/core/src/client/settings/SettingsTabsPage.tsx +292 -45
  23. package/corpus/core/src/client/settings/index.ts +1 -0
  24. package/corpus/core/src/client/sharing/ShareButton.tsx +14 -11
  25. package/corpus/core/src/client/sharing/ShareDialog.tsx +13 -10
  26. package/corpus/core/src/mcp/builtin-tools.ts +29 -2
  27. package/corpus/core/src/server/agent-chat-plugin.ts +174 -79
  28. package/corpus/core/src/server/onboarding-html.ts +28 -16
  29. package/corpus/core/src/sharing/actions/list-resource-shares.ts +45 -1
  30. package/corpus/core/src/sharing/actions/share-resource.ts +9 -0
  31. package/corpus/core/src/templates/workspace-core/.agents/skills/agent-native-toolkit/SKILL.md +4 -2
  32. package/corpus/core/src/templates/workspace-core/.agents/skills/changelog/SKILL.md +9 -6
  33. package/corpus/core/src/vite/client.ts +217 -35
  34. package/corpus/templates/analytics/.agents/skills/adhoc-analysis/SKILL.md +8 -7
  35. package/corpus/templates/analytics/.agents/skills/analysis-workspace/SKILL.md +14 -10
  36. package/corpus/templates/analytics/.agents/skills/bigquery/SKILL.md +15 -15
  37. package/corpus/templates/analytics/.agents/skills/cross-source-analysis/SKILL.md +1 -0
  38. package/corpus/templates/analytics/.agents/skills/dashboard-management/SKILL.md +38 -22
  39. package/corpus/templates/analytics/.agents/skills/data-programs/SKILL.md +114 -61
  40. package/corpus/templates/analytics/.agents/skills/data-querying/SKILL.md +1 -0
  41. package/corpus/templates/analytics/.agents/skills/gong/SKILL.md +7 -7
  42. package/corpus/templates/analytics/.agents/skills/hubspot/SKILL.md +1 -0
  43. package/corpus/templates/analytics/.agents/skills/prometheus/SKILL.md +1 -1
  44. package/corpus/templates/analytics/.builder/skills/bigquery/SKILL.md +17 -17
  45. package/corpus/templates/analytics/.builder/skills/gcloud/SKILL.md +5 -5
  46. package/corpus/templates/analytics/.builder/skills/github/SKILL.md +7 -7
  47. package/corpus/templates/analytics/.builder/skills/gong/SKILL.md +12 -12
  48. package/corpus/templates/analytics/.builder/skills/grafana/SKILL.md +7 -7
  49. package/corpus/templates/analytics/.builder/skills/sentry/SKILL.md +7 -7
  50. package/corpus/templates/analytics/.builder/skills/slack/SKILL.md +6 -6
  51. package/corpus/templates/analytics/.builder/skills/stripe/SKILL.md +7 -7
  52. package/corpus/templates/analytics/AGENTS.md +47 -2
  53. package/corpus/templates/analytics/actions/add-status-page-monitor.ts +36 -0
  54. package/corpus/templates/analytics/actions/capture-test-error.ts +33 -0
  55. package/corpus/templates/analytics/actions/delete-monitor.ts +24 -0
  56. package/corpus/templates/analytics/actions/delete-status-page.ts +23 -0
  57. package/corpus/templates/analytics/actions/get-error-issue.ts +36 -0
  58. package/corpus/templates/analytics/actions/get-monitor-stats.ts +55 -0
  59. package/corpus/templates/analytics/actions/get-monitor.ts +27 -0
  60. package/corpus/templates/analytics/actions/get-public-status-page.ts +41 -0
  61. package/corpus/templates/analytics/actions/get-status-page.ts +29 -0
  62. package/corpus/templates/analytics/actions/list-error-issues.ts +40 -0
  63. package/corpus/templates/analytics/actions/list-monitors.ts +21 -0
  64. package/corpus/templates/analytics/actions/list-status-pages.ts +21 -0
  65. package/corpus/templates/analytics/actions/match-error-issues.ts +51 -0
  66. package/corpus/templates/analytics/actions/navigate.ts +58 -4
  67. package/corpus/templates/analytics/actions/remove-status-page-monitor.ts +22 -0
  68. package/corpus/templates/analytics/actions/reorder-status-page-monitors.ts +25 -0
  69. package/corpus/templates/analytics/actions/resolve-error-issue.ts +38 -0
  70. package/corpus/templates/analytics/actions/run-monitor-check.ts +23 -0
  71. package/corpus/templates/analytics/actions/save-analysis.ts +1 -0
  72. package/corpus/templates/analytics/actions/save-monitor.ts +145 -0
  73. package/corpus/templates/analytics/actions/save-status-page.ts +47 -0
  74. package/corpus/templates/analytics/actions/view-screen.ts +212 -0
  75. package/corpus/templates/analytics/app/components/layout/Header.tsx +1 -0
  76. package/corpus/templates/analytics/app/components/layout/Layout.tsx +10 -1
  77. package/corpus/templates/analytics/app/components/layout/Sidebar.tsx +134 -39
  78. package/corpus/templates/analytics/app/components/monitoring/PublicStatusView.tsx +351 -0
  79. package/corpus/templates/analytics/app/components/monitoring/ResponseTimeChart.tsx +174 -0
  80. package/corpus/templates/analytics/app/components/monitoring/UptimeStatCards.tsx +85 -0
  81. package/corpus/templates/analytics/app/components/monitoring/UptimeTimelineBars.tsx +106 -0
  82. package/corpus/templates/analytics/app/components/monitoring/chart-utils.ts +101 -0
  83. package/corpus/templates/analytics/app/components/monitoring/index.ts +28 -0
  84. package/corpus/templates/analytics/app/components/monitoring/types.ts +42 -0
  85. package/corpus/templates/analytics/app/hooks/use-navigation-state.ts +34 -0
  86. package/corpus/templates/analytics/app/i18n/zh-TW.ts +6 -0
  87. package/corpus/templates/analytics/app/i18n-data.ts +33 -0
  88. package/corpus/templates/analytics/app/pages/DataSources.tsx +28 -0
  89. package/corpus/templates/analytics/app/pages/Settings.tsx +77 -9
  90. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/SqlChartCard.tsx +3 -3
  91. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/dashboard-layout.ts +7 -0
  92. package/corpus/templates/analytics/app/pages/monitoring/ErrorsPanel.tsx +205 -0
  93. package/corpus/templates/analytics/app/pages/monitoring/MonitoringPage.tsx +100 -0
  94. package/corpus/templates/analytics/app/pages/monitoring/UptimePanel.tsx +475 -0
  95. package/corpus/templates/analytics/app/pages/monitoring/errors/IssueDetail.tsx +372 -0
  96. package/corpus/templates/analytics/app/pages/monitoring/errors/IssueList.tsx +360 -0
  97. package/corpus/templates/analytics/app/pages/monitoring/errors/Sparkline.tsx +55 -0
  98. package/corpus/templates/analytics/app/pages/monitoring/errors/i18n.ts +106 -0
  99. package/corpus/templates/analytics/app/pages/monitoring/errors/types.ts +75 -0
  100. package/corpus/templates/analytics/app/pages/monitoring/errors/utils.ts +132 -0
  101. package/corpus/templates/analytics/app/pages/monitoring/uptime/MonitorDetail.tsx +535 -0
  102. package/corpus/templates/analytics/app/pages/monitoring/uptime/MonitorFormPage.tsx +1026 -0
  103. package/corpus/templates/analytics/app/pages/monitoring/uptime/MonitorList.tsx +311 -0
  104. package/corpus/templates/analytics/app/pages/monitoring/uptime/i18n.ts +235 -0
  105. package/corpus/templates/analytics/app/pages/monitoring/uptime/status-pages/StatusPageEditor.tsx +661 -0
  106. package/corpus/templates/analytics/app/pages/monitoring/uptime/status-pages/StatusPagesView.tsx +355 -0
  107. package/corpus/templates/analytics/app/pages/monitoring/uptime/status-pages/i18n.ts +106 -0
  108. package/corpus/templates/analytics/app/pages/monitoring/uptime/status-pages/slug.ts +24 -0
  109. package/corpus/templates/analytics/app/pages/monitoring/uptime/status-pages/types.ts +20 -0
  110. package/corpus/templates/analytics/app/pages/monitoring/uptime/status-summary.ts +87 -0
  111. package/corpus/templates/analytics/app/pages/monitoring/uptime/types.ts +161 -0
  112. package/corpus/templates/analytics/app/pages/monitoring/uptime/utils.ts +210 -0
  113. package/corpus/templates/analytics/app/pages/sessions/SessionDetailPage.tsx +76 -1
  114. package/corpus/templates/analytics/app/pages/sessions/SessionDevToolsPanel.tsx +74 -9
  115. package/corpus/templates/analytics/app/pages/sessions/SessionsPage.tsx +197 -20
  116. package/corpus/templates/analytics/app/root.tsx +33 -1
  117. package/corpus/templates/analytics/app/routes/monitoring._index.tsx +10 -0
  118. package/corpus/templates/analytics/app/routes/status.$slug.tsx +118 -0
  119. package/corpus/templates/analytics/changelog/2026-07-08-add-uptime-monitors-that-ping-your-urls-and-alert-you-when-t.md +6 -0
  120. package/corpus/templates/analytics/changelog/2026-07-08-analytics-chats-keep-large-data-dictionaries-compact-so-prov.md +6 -0
  121. package/corpus/templates/analytics/changelog/2026-07-08-create-public-status-pages-that-share-the-live-health-of-cho.md +6 -0
  122. package/corpus/templates/analytics/changelog/2026-07-08-dashboard-extension-panels-use-clearer-open-copy.md +6 -0
  123. package/corpus/templates/analytics/changelog/2026-07-08-error-capture.md +6 -0
  124. package/corpus/templates/analytics/changelog/2026-07-08-fixed-single-panel-dashboard-drags-so-they-no-longer-rewrite.md +6 -0
  125. package/corpus/templates/analytics/changelog/2026-07-08-jump-straight-from-an-error-in-a-session-recording-to-its-fu.md +6 -0
  126. package/corpus/templates/analytics/changelog/2026-07-08-monitor-detail-and-list-now-show-colorful-uptime-timelines-r.md +6 -0
  127. package/corpus/templates/analytics/changelog/2026-07-08-pinned-ask-chats-now-show-a-pin-icon-in-the-sidebar.md +6 -0
  128. package/corpus/templates/analytics/changelog/2026-07-08-publish-a-public-uptime-status-page-with-colorful-uptime-tim.md +6 -0
  129. package/corpus/templates/analytics/changelog/2026-07-08-sessions-now-hide-visitor-emails-in-demo-mode-and-show-clean.md +6 -0
  130. package/corpus/templates/analytics/changelog/2026-07-08-settings-are-cleaner-searchable-and-alerts-have-their-own-tab.md +5 -0
  131. package/corpus/templates/analytics/changelog/2026-07-08-sidebar-sections-stay-collapsed-until-opened.md +5 -0
  132. package/corpus/templates/analytics/changelog/2026-07-08-the-uptime-monitor-list-now-has-a-current-status-overview-wi.md +6 -0
  133. package/corpus/templates/analytics/docs/error-capture.md +172 -0
  134. package/corpus/templates/analytics/docs/uptime-monitoring.md +150 -0
  135. package/corpus/templates/analytics/server/db/schema-errors.ts +150 -0
  136. package/corpus/templates/analytics/server/db/schema-monitoring.ts +177 -0
  137. package/corpus/templates/analytics/server/db/schema.ts +6 -0
  138. package/corpus/templates/analytics/server/jobs/uptime-monitors.ts +123 -0
  139. package/corpus/templates/analytics/server/lib/agent-chat-plan-mode.ts +41 -0
  140. package/corpus/templates/analytics/server/lib/data-dictionary-context.ts +55 -12
  141. package/corpus/templates/analytics/server/lib/error-capture.ts +1331 -0
  142. package/corpus/templates/analytics/server/lib/first-party-analytics.ts +47 -1
  143. package/corpus/templates/analytics/server/lib/monitor-stats.ts +494 -0
  144. package/corpus/templates/analytics/server/lib/status-pages.ts +798 -0
  145. package/corpus/templates/analytics/server/lib/uptime-monitors.ts +1665 -0
  146. package/corpus/templates/analytics/server/plugins/agent-chat.ts +7 -37
  147. package/corpus/templates/analytics/server/plugins/auth.ts +11 -1
  148. package/corpus/templates/analytics/server/plugins/db.ts +408 -0
  149. package/corpus/templates/analytics/server/plugins/uptime-monitor-jobs.ts +63 -0
  150. package/corpus/templates/assets/app/routes/_index.tsx +1 -1
  151. package/corpus/templates/assets/app/routes/settings.tsx +22 -1
  152. package/corpus/templates/assets/changelog/2026-07-08-recent-drafts-keep-comfortable-side-padding.md +6 -0
  153. package/corpus/templates/assets/changelog/2026-07-08-settings-are-cleaner-and-searchable.md +5 -0
  154. package/corpus/templates/brain/app/routes/settings.tsx +43 -5
  155. package/corpus/templates/brain/changelog/2026-07-08-settings-are-cleaner-and-searchable.md +5 -0
  156. package/corpus/templates/calendar/app/pages/Settings.tsx +44 -6
  157. package/corpus/templates/calendar/changelog/2026-07-08-settings-are-cleaner-and-searchable.md +5 -0
  158. package/corpus/templates/chat/app/routes/settings.tsx +16 -1
  159. package/corpus/templates/chat/changelog/2026-07-08-settings-are-cleaner-and-searchable.md +5 -0
  160. package/corpus/templates/clips/actions/lib/audio-only-transcription.ts +79 -37
  161. package/corpus/templates/clips/app/components/player/player-controls.tsx +35 -0
  162. package/corpus/templates/clips/app/components/player/video-player.tsx +162 -18
  163. package/corpus/templates/clips/app/routes/_app.settings._index.tsx +63 -6
  164. package/corpus/templates/clips/app/routes/record.tsx +18 -1
  165. package/corpus/templates/clips/changelog/2026-07-07-shared-clips-start-playback-reliably-from-the-first-play-click.md +6 -0
  166. package/corpus/templates/clips/changelog/2026-07-08-chrome-extension-camera-and-microphone-menus-now-show-which-.md +6 -0
  167. package/corpus/templates/clips/changelog/2026-07-08-chrome-extension-copies-new-clip-links-after-saving.md +6 -0
  168. package/corpus/templates/clips/changelog/2026-07-08-chrome-extension-recordings-now-continue-after-granting-came.md +6 -0
  169. package/corpus/templates/clips/changelog/2026-07-08-mobile-shared-clips-now-have-loom-style-tap-and-skip-controls.md +6 -0
  170. package/corpus/templates/clips/changelog/2026-07-08-recordings-and-uploads-copy-links-after-saving.md +6 -0
  171. package/corpus/templates/clips/changelog/2026-07-08-settings-are-cleaner-searchable-and-collapse-s3-with-builder.md +5 -0
  172. package/corpus/templates/clips/changelog/2026-07-08-transcripts-are-more-reliable-for-longer-desktop-recordings-.md +6 -0
  173. package/corpus/templates/clips/chrome-extension/public/manifest.json +1 -0
  174. package/corpus/templates/clips/chrome-extension/src/background.ts +162 -13
  175. package/corpus/templates/clips/chrome-extension/src/content-script.ts +14 -0
  176. package/corpus/templates/clips/chrome-extension/src/offscreen.ts +36 -0
  177. package/corpus/templates/clips/chrome-extension/src/overlay.ts +99 -25
  178. package/corpus/templates/clips/chrome-extension/src/permission.ts +63 -14
  179. package/corpus/templates/clips/chrome-extension/src/popup.ts +123 -23
  180. package/corpus/templates/content/actions/_builder-cms-read-client.ts +47 -0
  181. package/corpus/templates/content/actions/_database-source-utils.ts +33 -4
  182. package/corpus/templates/content/actions/add-content-database-source-field-property.ts +214 -29
  183. package/corpus/templates/content/actions/attach-content-database-source.ts +3 -0
  184. package/corpus/templates/content/actions/change-content-database-source-role.ts +1 -0
  185. package/corpus/templates/content/app/components/editor/DocumentProperties.tsx +42 -32
  186. package/corpus/templates/content/app/components/editor/database/DatabaseView.tsx +352 -81
  187. package/corpus/templates/content/app/components/editor/database/settings.tsx +49 -24
  188. package/corpus/templates/content/app/routes/_app.settings.tsx +19 -1
  189. package/corpus/templates/content/changelog/2026-07-07-builder-source-tag-fields-now-import-as-multi-select.md +6 -0
  190. package/corpus/templates/content/changelog/2026-07-08-settings-are-cleaner-and-searchable.md +5 -0
  191. package/corpus/templates/content/shared/api.ts +3 -0
  192. package/corpus/templates/content/shared/properties.ts +42 -0
  193. package/corpus/templates/design/AGENTS.md +9 -0
  194. package/corpus/templates/design/actions/generate-design.ts +3 -0
  195. package/corpus/templates/design/actions/get-design-system.ts +147 -1
  196. package/corpus/templates/design/actions/request-localhost-write-consent.ts +141 -0
  197. package/corpus/templates/design/app/components/design/DesignCanvas.tsx +13 -19
  198. package/corpus/templates/design/app/routes/settings.tsx +16 -1
  199. package/corpus/templates/design/changelog/2026-07-08-design-generation-now-follows-hydrated-builder-design-system.md +6 -0
  200. package/corpus/templates/design/changelog/2026-07-08-settings-are-cleaner-and-searchable.md +5 -0
  201. package/corpus/templates/design/server/lib/verify-write-grant.ts +4 -2
  202. package/corpus/templates/dispatch/app/routes/settings.tsx +23 -2
  203. package/corpus/templates/dispatch/changelog/2026-07-08-settings-are-cleaner-and-searchable.md +5 -0
  204. package/corpus/templates/forms/app/routes/_app.settings.tsx +16 -1
  205. package/corpus/templates/forms/changelog/2026-07-08-settings-are-cleaner-and-searchable.md +5 -0
  206. package/corpus/templates/macros/app/routes/settings.tsx +16 -1
  207. package/corpus/templates/macros/changelog/2026-07-08-settings-are-cleaner-and-searchable.md +5 -0
  208. package/corpus/templates/mail/app/components/settings/GmailFiltersSection.tsx +1 -1
  209. package/corpus/templates/mail/app/components/settings/SnippetsSection.tsx +1 -1
  210. package/corpus/templates/mail/app/pages/SettingsPage.tsx +123 -105
  211. package/corpus/templates/mail/changelog/2026-07-08-settings-redesigned-with-a-consistent-searchable-layout.md +5 -0
  212. package/corpus/templates/plan/app/routes/settings.tsx +23 -2
  213. package/corpus/templates/plan/changelog/2026-07-08-settings-are-cleaner-and-searchable.md +5 -0
  214. package/corpus/templates/slides/actions/add-slide.ts +1 -0
  215. package/corpus/templates/slides/actions/get-design-system.ts +147 -1
  216. package/corpus/templates/slides/app/pages/Index.tsx +46 -1
  217. package/corpus/templates/slides/app/routes/settings.tsx +16 -1
  218. package/corpus/templates/slides/changelog/2026-07-08-deck-generation-now-follows-hydrated-builder-design-system-g.md +6 -0
  219. package/corpus/templates/slides/changelog/2026-07-08-settings-are-cleaner-and-searchable.md +5 -0
  220. package/dist/agent/run-ownership.d.ts +6 -0
  221. package/dist/agent/run-ownership.d.ts.map +1 -1
  222. package/dist/agent/run-ownership.js +11 -1
  223. package/dist/agent/run-ownership.js.map +1 -1
  224. package/dist/changelog/parse.d.ts +7 -0
  225. package/dist/changelog/parse.d.ts.map +1 -1
  226. package/dist/changelog/parse.js +64 -0
  227. package/dist/changelog/parse.js.map +1 -1
  228. package/dist/chat-threads/schema.d.ts +445 -0
  229. package/dist/chat-threads/schema.d.ts.map +1 -0
  230. package/dist/chat-threads/schema.js +39 -0
  231. package/dist/chat-threads/schema.js.map +1 -0
  232. package/dist/chat-threads/store.d.ts +12 -0
  233. package/dist/chat-threads/store.d.ts.map +1 -1
  234. package/dist/chat-threads/store.js +99 -10
  235. package/dist/chat-threads/store.js.map +1 -1
  236. package/dist/cli/design-connect.d.ts.map +1 -1
  237. package/dist/cli/design-connect.js +40 -10
  238. package/dist/cli/design-connect.js.map +1 -1
  239. package/dist/cli/workspace-dev.d.ts.map +1 -1
  240. package/dist/cli/workspace-dev.js +20 -5
  241. package/dist/cli/workspace-dev.js.map +1 -1
  242. package/dist/client/AgentPanel.d.ts.map +1 -1
  243. package/dist/client/AgentPanel.js +35 -7
  244. package/dist/client/AgentPanel.js.map +1 -1
  245. package/dist/client/AssistantChat.d.ts.map +1 -1
  246. package/dist/client/AssistantChat.js +105 -183
  247. package/dist/client/AssistantChat.js.map +1 -1
  248. package/dist/client/analytics-session.d.ts +3 -0
  249. package/dist/client/analytics-session.d.ts.map +1 -0
  250. package/dist/client/analytics-session.js +66 -0
  251. package/dist/client/analytics-session.js.map +1 -0
  252. package/dist/client/analytics.d.ts +32 -0
  253. package/dist/client/analytics.d.ts.map +1 -1
  254. package/dist/client/analytics.js +116 -46
  255. package/dist/client/analytics.js.map +1 -1
  256. package/dist/client/chat/message-components.d.ts +2 -1
  257. package/dist/client/chat/message-components.d.ts.map +1 -1
  258. package/dist/client/chat/message-components.js +16 -6
  259. package/dist/client/chat/message-components.js.map +1 -1
  260. package/dist/client/components/ui/message-scroller.d.ts +16 -0
  261. package/dist/client/components/ui/message-scroller.d.ts.map +1 -0
  262. package/dist/client/components/ui/message-scroller.js +25 -0
  263. package/dist/client/components/ui/message-scroller.js.map +1 -0
  264. package/dist/client/conversation/AgentConversation.d.ts +1 -1
  265. package/dist/client/conversation/AgentConversation.d.ts.map +1 -1
  266. package/dist/client/conversation/AgentConversation.js +3 -8
  267. package/dist/client/conversation/AgentConversation.js.map +1 -1
  268. package/dist/client/error-capture.d.ts +99 -0
  269. package/dist/client/error-capture.d.ts.map +1 -0
  270. package/dist/client/error-capture.js +437 -0
  271. package/dist/client/error-capture.js.map +1 -0
  272. package/dist/client/index.d.ts +2 -2
  273. package/dist/client/index.d.ts.map +1 -1
  274. package/dist/client/index.js +3 -1
  275. package/dist/client/index.js.map +1 -1
  276. package/dist/client/session-replay.d.ts +22 -0
  277. package/dist/client/session-replay.d.ts.map +1 -1
  278. package/dist/client/session-replay.js +45 -4
  279. package/dist/client/session-replay.js.map +1 -1
  280. package/dist/client/settings/SettingsPanel.d.ts.map +1 -1
  281. package/dist/client/settings/SettingsPanel.js +100 -5
  282. package/dist/client/settings/SettingsPanel.js.map +1 -1
  283. package/dist/client/settings/SettingsTabsPage.d.ts +49 -1
  284. package/dist/client/settings/SettingsTabsPage.d.ts.map +1 -1
  285. package/dist/client/settings/SettingsTabsPage.js +131 -19
  286. package/dist/client/settings/SettingsTabsPage.js.map +1 -1
  287. package/dist/client/settings/index.d.ts +1 -1
  288. package/dist/client/settings/index.d.ts.map +1 -1
  289. package/dist/client/settings/index.js.map +1 -1
  290. package/dist/client/sharing/ShareButton.d.ts.map +1 -1
  291. package/dist/client/sharing/ShareButton.js +13 -8
  292. package/dist/client/sharing/ShareButton.js.map +1 -1
  293. package/dist/client/sharing/ShareDialog.d.ts.map +1 -1
  294. package/dist/client/sharing/ShareDialog.js +12 -7
  295. package/dist/client/sharing/ShareDialog.js.map +1 -1
  296. package/dist/collab/routes.d.ts +1 -1
  297. package/dist/file-upload/actions/upload-image.d.ts +1 -1
  298. package/dist/mcp/builtin-tools.d.ts.map +1 -1
  299. package/dist/mcp/builtin-tools.js +21 -2
  300. package/dist/mcp/builtin-tools.js.map +1 -1
  301. package/dist/observability/routes.d.ts +1 -1
  302. package/dist/org/schema.d.ts +15 -15
  303. package/dist/provider-api/corpus-jobs.d.ts +2 -2
  304. package/dist/server/agent-chat-plugin.d.ts.map +1 -1
  305. package/dist/server/agent-chat-plugin.js +109 -73
  306. package/dist/server/agent-chat-plugin.js.map +1 -1
  307. package/dist/server/onboarding-html.d.ts.map +1 -1
  308. package/dist/server/onboarding-html.js +28 -16
  309. package/dist/server/onboarding-html.js.map +1 -1
  310. package/dist/sharing/actions/list-resource-shares.js +30 -1
  311. package/dist/sharing/actions/list-resource-shares.js.map +1 -1
  312. package/dist/sharing/actions/share-resource.js +6 -0
  313. package/dist/sharing/actions/share-resource.js.map +1 -1
  314. package/dist/templates/workspace-core/.agents/skills/agent-native-toolkit/SKILL.md +4 -2
  315. package/dist/templates/workspace-core/.agents/skills/changelog/SKILL.md +9 -6
  316. package/dist/vite/client.d.ts.map +1 -1
  317. package/dist/vite/client.js +192 -30
  318. package/dist/vite/client.js.map +1 -1
  319. package/docs/content/toolkit-settings.mdx +56 -3
  320. package/package.json +2 -1
  321. package/src/templates/workspace-core/.agents/skills/agent-native-toolkit/SKILL.md +4 -2
  322. package/src/templates/workspace-core/.agents/skills/changelog/SKILL.md +9 -6
@@ -1,8 +1,33 @@
1
- import { eq } from "drizzle-orm";
1
+ import { eq, inArray } from "drizzle-orm";
2
2
  import { z } from "zod";
3
3
  import { defineAction } from "../../action.js";
4
+ import { organizations } from "../../org/schema.js";
4
5
  import { resolveAccess } from "../access.js";
5
6
  import { requireShareableResource } from "../registry.js";
7
+ async function loadOrgDisplayNames(db, shares) {
8
+ const orgIds = Array.from(new Set(shares
9
+ .filter((s) => s.principalType === "org" && s.principalId)
10
+ .map((s) => s.principalId)));
11
+ if (!orgIds.length)
12
+ return new Map();
13
+ try {
14
+ const rows = await db
15
+ .select({ id: organizations.id, name: organizations.name })
16
+ .from(organizations)
17
+ .where(inArray(organizations.id, orgIds));
18
+ return new Map(rows.flatMap((row) => {
19
+ if (typeof row.id !== "string" || typeof row.name !== "string") {
20
+ return [];
21
+ }
22
+ const name = row.name.trim();
23
+ return name ? [[row.id, name]] : [];
24
+ }));
25
+ }
26
+ catch {
27
+ // Some templates or older local databases may not have org tables yet.
28
+ return new Map();
29
+ }
30
+ }
6
31
  export default defineAction({
7
32
  description: "List the current visibility and share grants on a shareable resource. Any read access is sufficient.",
8
33
  schema: z.object({
@@ -26,6 +51,7 @@ export default defineAction({
26
51
  .select()
27
52
  .from(reg.sharesTable)
28
53
  .where(eq(reg.sharesTable.resourceId, args.resourceId));
54
+ const orgDisplayNames = await loadOrgDisplayNames(db, shares);
29
55
  return {
30
56
  ownerEmail: access.resource.ownerEmail ?? null,
31
57
  orgId: access.resource.orgId ?? null,
@@ -35,6 +61,9 @@ export default defineAction({
35
61
  id: s.id,
36
62
  principalType: s.principalType,
37
63
  principalId: s.principalId,
64
+ displayName: s.principalType === "org"
65
+ ? orgDisplayNames.get(s.principalId)
66
+ : undefined,
38
67
  role: s.role,
39
68
  createdAt: s.createdAt,
40
69
  })),
@@ -1 +1 @@
1
- {"version":3,"file":"list-resource-shares.js","sourceRoot":"","sources":["../../../src/sharing/actions/list-resource-shares.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,MAAM,aAAa,CAAC;AACjC,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EAAE,wBAAwB,EAAE,MAAM,gBAAgB,CAAC;AAE1D,eAAe,YAAY,CAAC;IAC1B,WAAW,EACT,sGAAsG;IACxG,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC;QACf,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE;QACxB,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE;KACvB,CAAC;IACF,IAAI,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE;IACvB,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;QAClB,MAAM,GAAG,GAAG,wBAAwB,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QACxD,MAAM,MAAM,GAAG;YACb,sEAAsE;YACtE,kDAAkD;YAClD,WAAW,EAAE,GAAG,CAAC,WAAW,KAAK,KAAK;YACtC,6BAA6B,EAAE,GAAG,CAAC,6BAA6B,KAAK,IAAI;SAC1E,CAAC;QACF,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC,IAAI,CAAC,YAAY,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC;QACvE,IAAI,CAAC,MAAM;YACT,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC;QAEpE,MAAM,EAAE,GAAG,GAAG,CAAC,KAAK,EAAS,CAAC;QAC9B,MAAM,MAAM,GAAG,MAAM,EAAE;aACpB,MAAM,EAAE;aACR,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC;aACrB,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,WAAW,CAAC,UAAU,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC;QAE1D,OAAO;YACL,UAAU,EAAE,MAAM,CAAC,QAAQ,CAAC,UAAU,IAAI,IAAI;YAC9C,KAAK,EAAE,MAAM,CAAC,QAAQ,CAAC,KAAK,IAAI,IAAI;YACpC,UAAU,EAAE,MAAM,CAAC,QAAQ,CAAC,UAAU,IAAI,SAAS;YACnD,IAAI,EAAE,MAAM,CAAC,IAAI;YACjB,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC;gBAC9B,EAAE,EAAE,CAAC,CAAC,EAAE;gBACR,aAAa,EAAE,CAAC,CAAC,aAAa;gBAC9B,WAAW,EAAE,CAAC,CAAC,WAAW;gBAC1B,IAAI,EAAE,CAAC,CAAC,IAAI;gBACZ,SAAS,EAAE,CAAC,CAAC,SAAS;aACvB,CAAC,CAAC;YACH,MAAM;SACP,CAAC;IACJ,CAAC;CACF,CAAC,CAAC","sourcesContent":["import { eq } from \"drizzle-orm\";\nimport { z } from \"zod\";\n\nimport { defineAction } from \"../../action.js\";\nimport { resolveAccess } from \"../access.js\";\nimport { requireShareableResource } from \"../registry.js\";\n\nexport default defineAction({\n description:\n \"List the current visibility and share grants on a shareable resource. Any read access is sufficient.\",\n schema: z.object({\n resourceType: z.string(),\n resourceId: z.string(),\n }),\n http: { method: \"GET\" },\n run: async (args) => {\n const reg = requireShareableResource(args.resourceType);\n const policy = {\n // Defaults match registration defaults so the UI behaves the same for\n // resources that haven't opted into restrictions.\n allowPublic: reg.allowPublic !== false,\n requireOrgMemberForUserShares: reg.requireOrgMemberForUserShares === true,\n };\n const access = await resolveAccess(args.resourceType, args.resourceId);\n if (!access)\n return { ownerEmail: null, visibility: null, shares: [], policy };\n\n const db = reg.getDb() as any;\n const shares = await db\n .select()\n .from(reg.sharesTable)\n .where(eq(reg.sharesTable.resourceId, args.resourceId));\n\n return {\n ownerEmail: access.resource.ownerEmail ?? null,\n orgId: access.resource.orgId ?? null,\n visibility: access.resource.visibility ?? \"private\",\n role: access.role,\n shares: shares.map((s: any) => ({\n id: s.id,\n principalType: s.principalType,\n principalId: s.principalId,\n role: s.role,\n createdAt: s.createdAt,\n })),\n policy,\n };\n },\n});\n"]}
1
+ {"version":3,"file":"list-resource-shares.js","sourceRoot":"","sources":["../../../src/sharing/actions/list-resource-shares.ts"],"names":[],"mappings":"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","sourcesContent":["import { eq, inArray } from \"drizzle-orm\";\nimport { z } from \"zod\";\n\nimport { defineAction } from \"../../action.js\";\nimport { organizations } from \"../../org/schema.js\";\nimport { resolveAccess } from \"../access.js\";\nimport { requireShareableResource } from \"../registry.js\";\n\nasync function loadOrgDisplayNames(\n db: any,\n shares: Array<{ principalType: string; principalId: string }>,\n): Promise<Map<string, string>> {\n const orgIds = Array.from(\n new Set(\n shares\n .filter((s) => s.principalType === \"org\" && s.principalId)\n .map((s) => s.principalId),\n ),\n );\n if (!orgIds.length) return new Map();\n\n try {\n const rows = await db\n .select({ id: organizations.id, name: organizations.name })\n .from(organizations)\n .where(inArray(organizations.id, orgIds));\n return new Map(\n rows.flatMap(\n (row: {\n id?: string | null;\n name?: string | null;\n }): Array<[string, string]> => {\n if (typeof row.id !== \"string\" || typeof row.name !== \"string\") {\n return [];\n }\n const name = row.name.trim();\n return name ? [[row.id, name]] : [];\n },\n ),\n );\n } catch {\n // Some templates or older local databases may not have org tables yet.\n return new Map();\n }\n}\n\nexport default defineAction({\n description:\n \"List the current visibility and share grants on a shareable resource. Any read access is sufficient.\",\n schema: z.object({\n resourceType: z.string(),\n resourceId: z.string(),\n }),\n http: { method: \"GET\" },\n run: async (args) => {\n const reg = requireShareableResource(args.resourceType);\n const policy = {\n // Defaults match registration defaults so the UI behaves the same for\n // resources that haven't opted into restrictions.\n allowPublic: reg.allowPublic !== false,\n requireOrgMemberForUserShares: reg.requireOrgMemberForUserShares === true,\n };\n const access = await resolveAccess(args.resourceType, args.resourceId);\n if (!access)\n return { ownerEmail: null, visibility: null, shares: [], policy };\n\n const db = reg.getDb() as any;\n const shares = await db\n .select()\n .from(reg.sharesTable)\n .where(eq(reg.sharesTable.resourceId, args.resourceId));\n const orgDisplayNames = await loadOrgDisplayNames(db, shares);\n\n return {\n ownerEmail: access.resource.ownerEmail ?? null,\n orgId: access.resource.orgId ?? null,\n visibility: access.resource.visibility ?? \"private\",\n role: access.role,\n shares: shares.map((s: any) => ({\n id: s.id,\n principalType: s.principalType,\n principalId: s.principalId,\n displayName:\n s.principalType === \"org\"\n ? orgDisplayNames.get(s.principalId)\n : undefined,\n role: s.role,\n createdAt: s.createdAt,\n })),\n policy,\n };\n },\n});\n"]}
@@ -85,6 +85,9 @@ function normalizePrincipalId(principalType, principalId) {
85
85
  ? principalId.trim().toLowerCase()
86
86
  : principalId;
87
87
  }
88
+ function isEmailPrincipalId(value) {
89
+ return /^[^\s@]+@[^\s@]+$/.test(value.trim());
90
+ }
88
91
  function principalIdMatches(sharesTable, principalType, principalId) {
89
92
  return principalType === "user"
90
93
  ? sql `lower(${sharesTable.principalId}) = ${principalId}`
@@ -155,6 +158,9 @@ export default defineAction({
155
158
  if (!actor)
156
159
  throw new ForbiddenError("Not signed in");
157
160
  const principalId = normalizePrincipalId(args.principalType, args.principalId);
161
+ if (args.principalType === "user" && !isEmailPrincipalId(principalId)) {
162
+ throw new Error("User shares must use an email address, not an internal user id.");
163
+ }
158
164
  const beforeExtensionTargets = await getExtensionShareChangeTargets(args.resourceType, args.resourceId);
159
165
  if (reg.requireOrgMemberForUserShares) {
160
166
  const resourceOrgId = access.resource?.orgId;
@@ -1 +1 @@
1
- {"version":3,"file":"share-resource.js","sourceRoot":"","sources":["../../../src/sharing/actions/share-resource.ts"],"names":[],"mappings":"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","sourcesContent":["import { and, eq, sql, type SQL } from \"drizzle-orm\";\nimport { z } from \"zod\";\n\nimport { defineAction } from \"../../action.js\";\nimport { getDbExec } from \"../../db/client.js\";\nimport { getAppProductionUrl } from \"../../server/app-url.js\";\nimport { renderEmail, emailStrong } from \"../../server/email-template.js\";\nimport { sendEmail, isEmailConfigured } from \"../../server/email.js\";\nimport { invalidateCollabAccessCache } from \"../../server/poll.js\";\nimport { getRequestUserEmail } from \"../../server/request-context.js\";\nimport { assertAccess, ForbiddenError } from \"../access.js\";\nimport { requireShareableResource } from \"../registry.js\";\nimport {\n getExtensionShareChangeTargets,\n notifyExtensionShareChanged,\n} from \"./extension-change.js\";\n\nexport function isSyntheticQaEmail(email: string): boolean {\n const trimmed = email.trim().toLowerCase();\n const at = trimmed.lastIndexOf(\"@\");\n if (at <= 0) return false;\n const local = trimmed.slice(0, at);\n const domain = trimmed.slice(at + 1);\n return (\n local.includes(\"+qa\") &&\n (domain === \"example.test\" ||\n domain.endsWith(\".test\") ||\n domain === \"example.invalid\" ||\n domain.endsWith(\".invalid\"))\n );\n}\n\nfunction appPath(path: string): string {\n if (!path.startsWith(\"/\")) return path;\n const raw = process.env.VITE_APP_BASE_PATH || process.env.APP_BASE_PATH || \"\";\n const base = raw.trim().replace(/^\\/+/, \"\").replace(/\\/+$/, \"\");\n if (!base) return path;\n const normalizedBase = `/${base}`;\n if (path === normalizedBase || path.startsWith(`${normalizedBase}/`)) {\n return path;\n }\n return `${normalizedBase}${path}`;\n}\n\nfunction safeNotificationUrl(value: string, appUrl: string): string | null {\n const trimmed = value.trim();\n if (!trimmed) return null;\n\n try {\n const base = new URL(appUrl);\n if (trimmed.startsWith(\"/\")) {\n const path = appPath(trimmed);\n const basePath = base.pathname.replace(/\\/+$/, \"\");\n const alreadyIncludesBase =\n basePath && basePath !== \"/\" && path.startsWith(`${basePath}/`);\n const joined = alreadyIncludesBase\n ? `${base.origin}${path}`\n : `${appUrl.replace(/\\/+$/, \"\")}${path}`;\n return new URL(joined).toString();\n }\n\n const url = new URL(trimmed);\n if (![\"http:\", \"https:\"].includes(url.protocol)) return null;\n if (url.origin !== base.origin) return null;\n return url.toString();\n } catch {\n return null;\n }\n}\n\nexport function resolveShareNotificationUrl(\n explicitUrl: string | undefined,\n fallbackPath: string | undefined,\n appUrl = getAppProductionUrl(),\n): string {\n for (const candidate of [explicitUrl, fallbackPath]) {\n if (!candidate) continue;\n const url = safeNotificationUrl(candidate, appUrl);\n if (url) return url;\n }\n return appUrl;\n}\n\nfunction nanoid(size = 12): string {\n const chars =\n \"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\";\n let id = \"\";\n const bytes = crypto.getRandomValues(new Uint8Array(size));\n for (const byte of bytes) id += chars[byte % chars.length];\n return id;\n}\n\nfunction normalizePrincipalId(\n principalType: \"user\" | \"org\",\n principalId: string,\n): string {\n return principalType === \"user\"\n ? principalId.trim().toLowerCase()\n : principalId;\n}\n\nfunction principalIdMatches(\n sharesTable: any,\n principalType: \"user\" | \"org\",\n principalId: string,\n): SQL {\n return principalType === \"user\"\n ? sql`lower(${sharesTable.principalId}) = ${principalId}`\n : eq(sharesTable.principalId, principalId);\n}\n\n/**\n * Returns true if the given email is either an active member of `orgId` or\n * has a pending invitation to `orgId`. Used by resources whose registration\n * sets `requireOrgMemberForUserShares` (currently extensions) to refuse\n * cross-org user shares.\n *\n * Both `org_members` and `org_invitations` store email case-insensitively\n * via `LOWER()` in the rest of the framework, so we follow the same\n * convention here.\n */\nasync function isOrgMemberOrInvited(\n orgId: string,\n email: string,\n): Promise<boolean> {\n const lower = email.trim().toLowerCase();\n if (!lower || !orgId) return false;\n const client = getDbExec();\n const member = await client.execute({\n sql: `SELECT 1 FROM org_members WHERE org_id = ? AND LOWER(email) = ? LIMIT 1`,\n args: [orgId, lower],\n });\n if (member.rows.length > 0) return true;\n const invited = await client.execute({\n sql: `SELECT 1 FROM org_invitations WHERE org_id = ? AND LOWER(email) = ? AND status = 'pending' LIMIT 1`,\n args: [orgId, lower],\n });\n return invited.rows.length > 0;\n}\n\nexport default defineAction({\n description:\n \"Grant a user or org access to a shareable resource. Owner or admin role required.\",\n // (audit H5) Sharing-grant operations are admin-tier and let a caller\n // expand who can read/write a resource. Refuse from the tools iframe\n // bridge so a malicious shared tool can't silently re-share its\n // viewer's resources to an attacker-controlled email.\n toolCallable: false,\n schema: z.object({\n resourceType: z\n .string()\n .describe(\"Registered resource type, e.g. 'document', 'form'.\"),\n resourceId: z.string().describe(\"Id of the resource to share.\"),\n principalType: z\n .enum([\"user\", \"org\"])\n .describe(\"'user' for an individual, 'org' for a whole organization.\"),\n principalId: z\n .string()\n .describe(\"Email (user) or org id (org) of the principal.\"),\n role: z\n .enum([\"viewer\", \"editor\", \"admin\"])\n .default(\"viewer\")\n .describe(\"Role to grant.\"),\n notify: z\n .boolean()\n .default(true)\n .describe(\n \"Whether to email the user about a new individual share. Defaults to true.\",\n ),\n resourceUrl: z\n .string()\n .optional()\n .describe(\n \"Optional app-relative or same-origin URL recipients should open. External origins are ignored.\",\n ),\n }),\n run: async (args) => {\n const reg = requireShareableResource(args.resourceType);\n const access = await assertAccess(\n args.resourceType,\n args.resourceId,\n \"admin\",\n );\n const actor = getRequestUserEmail();\n if (!actor) throw new ForbiddenError(\"Not signed in\");\n const principalId = normalizePrincipalId(\n args.principalType,\n args.principalId,\n );\n const beforeExtensionTargets = await getExtensionShareChangeTargets(\n args.resourceType,\n args.resourceId,\n );\n\n if (reg.requireOrgMemberForUserShares) {\n const resourceOrgId = access.resource?.orgId as string | undefined | null;\n if (!resourceOrgId) {\n throw new ForbiddenError(\n `${reg.displayName} can only be shared from within an organization. Create or join an organization first.`,\n );\n }\n if (args.principalType === \"user\") {\n const ok = await isOrgMemberOrInvited(resourceOrgId, principalId);\n if (!ok) {\n throw new ForbiddenError(\n `${principalId} is not in your organization. Invite them to the organization first, then share.`,\n );\n }\n } else if (args.principalType === \"org\") {\n // Cross-org org shares would let an outside org's members run\n // extension code in the viewer's auth context — the same threat\n // model that blocks public + cross-org user shares. Pin org-\n // principal shares to the resource's own org.\n if (principalId !== resourceOrgId) {\n throw new ForbiddenError(\n `${reg.displayName} can only be shared with its own organization, not a different one.`,\n );\n }\n }\n }\n\n const db = reg.getDb() as any;\n const [existing] = await db\n .select()\n .from(reg.sharesTable)\n .where(\n and(\n eq(reg.sharesTable.resourceId, args.resourceId),\n eq(reg.sharesTable.principalType, args.principalType),\n principalIdMatches(reg.sharesTable, args.principalType, principalId),\n ),\n );\n\n if (existing) {\n await db\n .update(reg.sharesTable)\n .set({ role: args.role })\n .where(eq(reg.sharesTable.id, existing.id));\n invalidateCollabAccessCache(args.resourceType, args.resourceId);\n await notifyExtensionShareChanged(\n args.resourceType,\n args.resourceId,\n beforeExtensionTargets,\n );\n return { id: existing.id, updated: true };\n }\n\n const id = nanoid();\n await db.insert(reg.sharesTable).values({\n id,\n resourceId: args.resourceId,\n principalType: args.principalType,\n principalId,\n role: args.role,\n createdBy: actor,\n createdAt: new Date().toISOString(),\n });\n invalidateCollabAccessCache(args.resourceType, args.resourceId);\n await notifyExtensionShareChanged(\n args.resourceType,\n args.resourceId,\n beforeExtensionTargets,\n );\n\n if (\n args.notify !== false &&\n args.principalType === \"user\" &&\n (await isEmailConfigured()) &&\n !isSyntheticQaEmail(principalId)\n ) {\n try {\n const titleCol = reg.titleColumn ?? \"title\";\n const [resource] = await db\n .select()\n .from(reg.resourceTable)\n .where(eq(reg.resourceTable.id, args.resourceId));\n const resourceTitle: string =\n (resource?.[titleCol] as string | undefined) ?? args.resourceType;\n const appUrl = getAppProductionUrl();\n const resourcePath =\n resource && reg.getResourcePath\n ? reg.getResourcePath(resource)\n : undefined;\n const notificationUrl = resolveShareNotificationUrl(\n args.resourceUrl,\n resourcePath,\n appUrl,\n );\n const appName =\n process.env.APP_NAME || process.env.VITE_APP_NAME || \"Agent Native\";\n const subject = `${actor} shared \"${resourceTitle}\" with you on ${appName}`;\n const { html, text } = renderEmail({\n preheader: subject,\n heading: \"You've been given access\",\n paragraphs: [\n `${emailStrong(actor)} has shared the ${reg.displayName} ${emailStrong(resourceTitle)} with you as a ${emailStrong(args.role)}.`,\n `Use the button below to open it. If prompted, sign in with ${emailStrong(principalId)}.`,\n ],\n cta: { label: `Open ${reg.displayName}`, url: notificationUrl },\n footer: `You received this because ${actor} granted you ${args.role} access.`,\n });\n await sendEmail({ to: principalId, subject, html, text });\n } catch (err) {\n console.error(\n \"[share-resource] failed to send share notification:\",\n err,\n );\n }\n }\n\n return { id, updated: false };\n },\n});\n"]}
1
+ {"version":3,"file":"share-resource.js","sourceRoot":"","sources":["../../../src/sharing/actions/share-resource.ts"],"names":[],"mappings":"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","sourcesContent":["import { and, eq, sql, type SQL } from \"drizzle-orm\";\nimport { z } from \"zod\";\n\nimport { defineAction } from \"../../action.js\";\nimport { getDbExec } from \"../../db/client.js\";\nimport { getAppProductionUrl } from \"../../server/app-url.js\";\nimport { renderEmail, emailStrong } from \"../../server/email-template.js\";\nimport { sendEmail, isEmailConfigured } from \"../../server/email.js\";\nimport { invalidateCollabAccessCache } from \"../../server/poll.js\";\nimport { getRequestUserEmail } from \"../../server/request-context.js\";\nimport { assertAccess, ForbiddenError } from \"../access.js\";\nimport { requireShareableResource } from \"../registry.js\";\nimport {\n getExtensionShareChangeTargets,\n notifyExtensionShareChanged,\n} from \"./extension-change.js\";\n\nexport function isSyntheticQaEmail(email: string): boolean {\n const trimmed = email.trim().toLowerCase();\n const at = trimmed.lastIndexOf(\"@\");\n if (at <= 0) return false;\n const local = trimmed.slice(0, at);\n const domain = trimmed.slice(at + 1);\n return (\n local.includes(\"+qa\") &&\n (domain === \"example.test\" ||\n domain.endsWith(\".test\") ||\n domain === \"example.invalid\" ||\n domain.endsWith(\".invalid\"))\n );\n}\n\nfunction appPath(path: string): string {\n if (!path.startsWith(\"/\")) return path;\n const raw = process.env.VITE_APP_BASE_PATH || process.env.APP_BASE_PATH || \"\";\n const base = raw.trim().replace(/^\\/+/, \"\").replace(/\\/+$/, \"\");\n if (!base) return path;\n const normalizedBase = `/${base}`;\n if (path === normalizedBase || path.startsWith(`${normalizedBase}/`)) {\n return path;\n }\n return `${normalizedBase}${path}`;\n}\n\nfunction safeNotificationUrl(value: string, appUrl: string): string | null {\n const trimmed = value.trim();\n if (!trimmed) return null;\n\n try {\n const base = new URL(appUrl);\n if (trimmed.startsWith(\"/\")) {\n const path = appPath(trimmed);\n const basePath = base.pathname.replace(/\\/+$/, \"\");\n const alreadyIncludesBase =\n basePath && basePath !== \"/\" && path.startsWith(`${basePath}/`);\n const joined = alreadyIncludesBase\n ? `${base.origin}${path}`\n : `${appUrl.replace(/\\/+$/, \"\")}${path}`;\n return new URL(joined).toString();\n }\n\n const url = new URL(trimmed);\n if (![\"http:\", \"https:\"].includes(url.protocol)) return null;\n if (url.origin !== base.origin) return null;\n return url.toString();\n } catch {\n return null;\n }\n}\n\nexport function resolveShareNotificationUrl(\n explicitUrl: string | undefined,\n fallbackPath: string | undefined,\n appUrl = getAppProductionUrl(),\n): string {\n for (const candidate of [explicitUrl, fallbackPath]) {\n if (!candidate) continue;\n const url = safeNotificationUrl(candidate, appUrl);\n if (url) return url;\n }\n return appUrl;\n}\n\nfunction nanoid(size = 12): string {\n const chars =\n \"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\";\n let id = \"\";\n const bytes = crypto.getRandomValues(new Uint8Array(size));\n for (const byte of bytes) id += chars[byte % chars.length];\n return id;\n}\n\nfunction normalizePrincipalId(\n principalType: \"user\" | \"org\",\n principalId: string,\n): string {\n return principalType === \"user\"\n ? principalId.trim().toLowerCase()\n : principalId;\n}\n\nfunction isEmailPrincipalId(value: string): boolean {\n return /^[^\\s@]+@[^\\s@]+$/.test(value.trim());\n}\n\nfunction principalIdMatches(\n sharesTable: any,\n principalType: \"user\" | \"org\",\n principalId: string,\n): SQL {\n return principalType === \"user\"\n ? sql`lower(${sharesTable.principalId}) = ${principalId}`\n : eq(sharesTable.principalId, principalId);\n}\n\n/**\n * Returns true if the given email is either an active member of `orgId` or\n * has a pending invitation to `orgId`. Used by resources whose registration\n * sets `requireOrgMemberForUserShares` (currently extensions) to refuse\n * cross-org user shares.\n *\n * Both `org_members` and `org_invitations` store email case-insensitively\n * via `LOWER()` in the rest of the framework, so we follow the same\n * convention here.\n */\nasync function isOrgMemberOrInvited(\n orgId: string,\n email: string,\n): Promise<boolean> {\n const lower = email.trim().toLowerCase();\n if (!lower || !orgId) return false;\n const client = getDbExec();\n const member = await client.execute({\n sql: `SELECT 1 FROM org_members WHERE org_id = ? AND LOWER(email) = ? LIMIT 1`,\n args: [orgId, lower],\n });\n if (member.rows.length > 0) return true;\n const invited = await client.execute({\n sql: `SELECT 1 FROM org_invitations WHERE org_id = ? AND LOWER(email) = ? AND status = 'pending' LIMIT 1`,\n args: [orgId, lower],\n });\n return invited.rows.length > 0;\n}\n\nexport default defineAction({\n description:\n \"Grant a user or org access to a shareable resource. Owner or admin role required.\",\n // (audit H5) Sharing-grant operations are admin-tier and let a caller\n // expand who can read/write a resource. Refuse from the tools iframe\n // bridge so a malicious shared tool can't silently re-share its\n // viewer's resources to an attacker-controlled email.\n toolCallable: false,\n schema: z.object({\n resourceType: z\n .string()\n .describe(\"Registered resource type, e.g. 'document', 'form'.\"),\n resourceId: z.string().describe(\"Id of the resource to share.\"),\n principalType: z\n .enum([\"user\", \"org\"])\n .describe(\"'user' for an individual, 'org' for a whole organization.\"),\n principalId: z\n .string()\n .describe(\"Email (user) or org id (org) of the principal.\"),\n role: z\n .enum([\"viewer\", \"editor\", \"admin\"])\n .default(\"viewer\")\n .describe(\"Role to grant.\"),\n notify: z\n .boolean()\n .default(true)\n .describe(\n \"Whether to email the user about a new individual share. Defaults to true.\",\n ),\n resourceUrl: z\n .string()\n .optional()\n .describe(\n \"Optional app-relative or same-origin URL recipients should open. External origins are ignored.\",\n ),\n }),\n run: async (args) => {\n const reg = requireShareableResource(args.resourceType);\n const access = await assertAccess(\n args.resourceType,\n args.resourceId,\n \"admin\",\n );\n const actor = getRequestUserEmail();\n if (!actor) throw new ForbiddenError(\"Not signed in\");\n const principalId = normalizePrincipalId(\n args.principalType,\n args.principalId,\n );\n if (args.principalType === \"user\" && !isEmailPrincipalId(principalId)) {\n throw new Error(\n \"User shares must use an email address, not an internal user id.\",\n );\n }\n const beforeExtensionTargets = await getExtensionShareChangeTargets(\n args.resourceType,\n args.resourceId,\n );\n\n if (reg.requireOrgMemberForUserShares) {\n const resourceOrgId = access.resource?.orgId as string | undefined | null;\n if (!resourceOrgId) {\n throw new ForbiddenError(\n `${reg.displayName} can only be shared from within an organization. Create or join an organization first.`,\n );\n }\n if (args.principalType === \"user\") {\n const ok = await isOrgMemberOrInvited(resourceOrgId, principalId);\n if (!ok) {\n throw new ForbiddenError(\n `${principalId} is not in your organization. Invite them to the organization first, then share.`,\n );\n }\n } else if (args.principalType === \"org\") {\n // Cross-org org shares would let an outside org's members run\n // extension code in the viewer's auth context — the same threat\n // model that blocks public + cross-org user shares. Pin org-\n // principal shares to the resource's own org.\n if (principalId !== resourceOrgId) {\n throw new ForbiddenError(\n `${reg.displayName} can only be shared with its own organization, not a different one.`,\n );\n }\n }\n }\n\n const db = reg.getDb() as any;\n const [existing] = await db\n .select()\n .from(reg.sharesTable)\n .where(\n and(\n eq(reg.sharesTable.resourceId, args.resourceId),\n eq(reg.sharesTable.principalType, args.principalType),\n principalIdMatches(reg.sharesTable, args.principalType, principalId),\n ),\n );\n\n if (existing) {\n await db\n .update(reg.sharesTable)\n .set({ role: args.role })\n .where(eq(reg.sharesTable.id, existing.id));\n invalidateCollabAccessCache(args.resourceType, args.resourceId);\n await notifyExtensionShareChanged(\n args.resourceType,\n args.resourceId,\n beforeExtensionTargets,\n );\n return { id: existing.id, updated: true };\n }\n\n const id = nanoid();\n await db.insert(reg.sharesTable).values({\n id,\n resourceId: args.resourceId,\n principalType: args.principalType,\n principalId,\n role: args.role,\n createdBy: actor,\n createdAt: new Date().toISOString(),\n });\n invalidateCollabAccessCache(args.resourceType, args.resourceId);\n await notifyExtensionShareChanged(\n args.resourceType,\n args.resourceId,\n beforeExtensionTargets,\n );\n\n if (\n args.notify !== false &&\n args.principalType === \"user\" &&\n (await isEmailConfigured()) &&\n !isSyntheticQaEmail(principalId)\n ) {\n try {\n const titleCol = reg.titleColumn ?? \"title\";\n const [resource] = await db\n .select()\n .from(reg.resourceTable)\n .where(eq(reg.resourceTable.id, args.resourceId));\n const resourceTitle: string =\n (resource?.[titleCol] as string | undefined) ?? args.resourceType;\n const appUrl = getAppProductionUrl();\n const resourcePath =\n resource && reg.getResourcePath\n ? reg.getResourcePath(resource)\n : undefined;\n const notificationUrl = resolveShareNotificationUrl(\n args.resourceUrl,\n resourcePath,\n appUrl,\n );\n const appName =\n process.env.APP_NAME || process.env.VITE_APP_NAME || \"Agent Native\";\n const subject = `${actor} shared \"${resourceTitle}\" with you on ${appName}`;\n const { html, text } = renderEmail({\n preheader: subject,\n heading: \"You've been given access\",\n paragraphs: [\n `${emailStrong(actor)} has shared the ${reg.displayName} ${emailStrong(resourceTitle)} with you as a ${emailStrong(args.role)}.`,\n `Use the button below to open it. If prompted, sign in with ${emailStrong(principalId)}.`,\n ],\n cta: { label: `Open ${reg.displayName}`, url: notificationUrl },\n footer: `You received this because ${actor} granted you ${args.role} access.`,\n });\n await sendEmail({ to: principalId, subject, html, text });\n } catch (err) {\n console.error(\n \"[share-resource] failed to send share notification:\",\n err,\n );\n }\n }\n\n return { id, updated: false };\n },\n});\n"]}
@@ -40,8 +40,10 @@ in the moment of agent use.
40
40
 
41
41
  ## Reusable Kits
42
42
 
43
- - **Settings kit**: account, workspace, AI models, LLM keys, connections,
44
- secrets, usage, notifications, changelog, and app-specific panels.
43
+ - **Settings kit**: a searchable settings page with account, workspace, AI
44
+ models, LLM keys, connections, secrets, usage, notifications, changelog, and
45
+ app-specific panels. Search is on by default; register a `SettingsSearchEntry`
46
+ per control so users find settings by name across tabs.
45
47
  - **Collaboration kit**: Yjs docs, presence, agent presence, live cursors,
46
48
  remote selections, recent edit highlights, real-time sync indicators, and
47
49
  undo/redo grouping.
@@ -15,8 +15,9 @@ metadata:
15
15
  Every template app keeps a `CHANGELOG.md` of **user-facing** changes that
16
16
  renders in-app via the command menu (Cmd+K → "What's new") and on the settings
17
17
  page. The flow mirrors changesets so it survives many agents working in
18
- parallel: each change drops a small **pending entry file**, and a later
19
- **release** rolls all pending files into a dated `CHANGELOG.md` section.
18
+ parallel: each change drops a small **pending entry file**, the in-app surface
19
+ reads pending files plus `CHANGELOG.md`, and a later **release** can roll those
20
+ pending files into dated `CHANGELOG.md` sections.
20
21
 
21
22
  ## When to add an entry
22
23
 
@@ -69,9 +70,10 @@ agent-native changelog release # uses today's date
69
70
  agent-native changelog list # preview pending + released
70
71
  ```
71
72
 
72
- Releasing is usually done at deploy/merge time. The in-app surface reads
73
- `CHANGELOG.md`, so only released entries are visible to users — pending entries
74
- stay invisible until rolled up.
73
+ Releasing is usually done at deploy/merge time to keep the source tree tidy.
74
+ The in-app surface imports `CHANGELOG.md?raw`, and the core Vite plugin merges
75
+ adjacent `changelog/*.md` pending entries into that raw markdown at dev/build
76
+ time, so product notes become visible without waiting for a manual rollup.
75
77
 
76
78
  ## Wiring the in-app surface (once per template)
77
79
 
@@ -108,4 +110,5 @@ host with no server route or runtime file access.
108
110
  - [ ] Shipped a user-visible change? Run `agent-native changelog add "…"`.
109
111
  - [ ] New template UI? Pass `changelog` to its `CommandMenu` and seed a
110
112
  `CHANGELOG.md`.
111
- - [ ] Releasing/deploying? `agent-native changelog release` rolls pending → dated.
113
+ - [ ] Releasing/deploying? Optional: `agent-native changelog release` rolls
114
+ pending → dated sections and deletes the pending files.
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/vite/client.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/vite/client.ts"],"names":[],"mappings":"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"}
@@ -3,6 +3,7 @@ import fs from "fs";
3
3
  import { createRequire, syncBuiltinESMExports } from "module";
4
4
  import path from "path";
5
5
  import { fileURLToPath } from "url";
6
+ import { mergePendingChangelog, parsePendingEntry, } from "../changelog/parse.js";
6
7
  import { getViteDevRecoveryScript } from "../client/vite-dev-recovery-script.js";
7
8
  import { findWorkspaceRoot } from "../scripts/utils.js";
8
9
  import { verifyEmbedSessionToken } from "../server/embed-session.js";
@@ -255,9 +256,7 @@ function findWorkspaceCoreSync(startDir) {
255
256
  }
256
257
  return null;
257
258
  }
258
- function findLocalWorkspacePackageDeps(startDir, workspaceRoot) {
259
- if (!workspaceRoot)
260
- return [];
259
+ function findLocalWorkspacePackageDeps(startDir, _workspaceRoot) {
261
260
  const pkgPath = path.join(startDir, "package.json");
262
261
  if (!fs.existsSync(pkgPath))
263
262
  return [];
@@ -268,22 +267,25 @@ function findLocalWorkspacePackageDeps(startDir, workspaceRoot) {
268
267
  ...(pkg.devDependencies ?? {}),
269
268
  ...(pkg.peerDependencies ?? {}),
270
269
  };
271
- const req = createRequire(pkgPath);
272
270
  const seen = new Set();
273
271
  const packages = [];
274
272
  for (const [packageName, range] of Object.entries(deps)) {
275
- if (!range.startsWith("workspace:"))
276
- continue;
277
273
  if (seen.has(packageName))
278
274
  continue;
279
275
  seen.add(packageName);
280
276
  try {
281
- const packageJsonPath = findInstalledPackageJsonPath(pkgPath, packageName) ??
282
- findPackageJsonFromEntry(req.resolve(packageName));
277
+ let packageJsonPath = null;
278
+ if (range.startsWith("file:")) {
279
+ packageJsonPath = findFilePackageJsonPath(pkgPath, range);
280
+ }
281
+ else {
282
+ continue;
283
+ }
283
284
  if (!packageJsonPath)
284
285
  continue;
285
286
  const packageDir = fs.realpathSync(path.dirname(packageJsonPath));
286
- if (!packageDir.startsWith(path.join(workspaceRoot, "packages")))
287
+ const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, "utf-8"));
288
+ if (packageJson?.name !== packageName)
287
289
  continue;
288
290
  packages.push({ packageName, packageDir });
289
291
  }
@@ -297,24 +299,13 @@ function findLocalWorkspacePackageDeps(startDir, workspaceRoot) {
297
299
  return [];
298
300
  }
299
301
  }
300
- function findInstalledPackageJsonPath(pkgPath, packageName) {
301
- const candidate = path.join(path.dirname(pkgPath), "node_modules", ...packageName.split("/"), "package.json");
302
- return fs.existsSync(candidate) ? candidate : null;
303
- }
304
- function findPackageJsonFromEntry(entryPath) {
305
- let dir = fs.statSync(entryPath).isDirectory()
306
- ? entryPath
307
- : path.dirname(entryPath);
308
- for (let i = 0; i < 20; i++) {
309
- const candidate = path.join(dir, "package.json");
310
- if (fs.existsSync(candidate))
311
- return candidate;
312
- const parent = path.dirname(dir);
313
- if (parent === dir)
314
- break;
315
- dir = parent;
316
- }
317
- return null;
302
+ function findFilePackageJsonPath(pkgPath, range) {
303
+ const spec = range.slice("file:".length);
304
+ const packageDir = spec.startsWith("//")
305
+ ? fileURLToPath(range)
306
+ : path.resolve(path.dirname(pkgPath), spec);
307
+ const packageJsonPath = path.join(packageDir, "package.json");
308
+ return fs.existsSync(packageJsonPath) ? packageJsonPath : null;
318
309
  }
319
310
  function findPnpmWorkspaceRoot(startDir) {
320
311
  let dir = path.resolve(startDir);
@@ -524,6 +515,17 @@ const CORE_CLIENT_SUBPATHS = [
524
515
  "@agent-native/core/client/transcription/use-live-transcription",
525
516
  "@agent-native/core/voice",
526
517
  ];
518
+ const TOOLKIT_CLIENT_SUBPATHS = [
519
+ "@agent-native/toolkit",
520
+ "@agent-native/toolkit/app-shell",
521
+ "@agent-native/toolkit/collab-ui",
522
+ "@agent-native/toolkit/hooks",
523
+ "@agent-native/toolkit/onboarding",
524
+ "@agent-native/toolkit/provider",
525
+ "@agent-native/toolkit/sharing",
526
+ "@agent-native/toolkit/ui",
527
+ "@agent-native/toolkit/utils",
528
+ ];
527
529
  const NODE_SSR_NATIVE_EXTERNALS = ["better-sqlite3", "bindings"];
528
530
  function getDefaultOptimizeDeps(cwd) {
529
531
  const inMonorepo = findCoreSrcDir(cwd) !== null;
@@ -581,6 +583,10 @@ function getDefaultOptimizeDeps(cwd) {
581
583
  specifier: "@agent-native/core/client/tools",
582
584
  packageName: "@agent-native/core",
583
585
  },
586
+ ...TOOLKIT_CLIENT_SUBPATHS.map((specifier) => ({
587
+ specifier,
588
+ packageName: "@agent-native/toolkit",
589
+ })),
584
590
  ]),
585
591
  { specifier: "@libsql/client" },
586
592
  { specifier: "@amplitude/analytics-browser" },
@@ -1471,6 +1477,119 @@ function ssrStubPlugin(packages) {
1471
1477
  },
1472
1478
  };
1473
1479
  }
1480
+ function splitViteRequest(id) {
1481
+ const queryIndex = id.indexOf("?");
1482
+ if (queryIndex === -1)
1483
+ return null;
1484
+ return {
1485
+ file: id.slice(0, queryIndex),
1486
+ query: id.slice(queryIndex + 1),
1487
+ };
1488
+ }
1489
+ function hasRawQuery(query) {
1490
+ return new URLSearchParams(query).has("raw");
1491
+ }
1492
+ function normalizeViteFilePath(file) {
1493
+ if (!file || file.startsWith("\0"))
1494
+ return null;
1495
+ const fsPath = file.startsWith("/@fs/") ? file.slice("/@fs".length) : file;
1496
+ try {
1497
+ return decodeURI(fsPath);
1498
+ }
1499
+ catch {
1500
+ return fsPath;
1501
+ }
1502
+ }
1503
+ function changelogRawPathFromId(id) {
1504
+ const request = splitViteRequest(id);
1505
+ if (!request || !hasRawQuery(request.query))
1506
+ return null;
1507
+ const file = normalizeViteFilePath(request.file);
1508
+ if (!file || path.basename(file) !== "CHANGELOG.md")
1509
+ return null;
1510
+ return path.resolve(file);
1511
+ }
1512
+ function resolveChangelogRawImport(source, importer) {
1513
+ const request = splitViteRequest(source);
1514
+ if (!request || !hasRawQuery(request.query))
1515
+ return null;
1516
+ const rawFile = normalizeViteFilePath(request.file);
1517
+ if (!rawFile || path.basename(rawFile) !== "CHANGELOG.md")
1518
+ return null;
1519
+ const rawImporter = importer?.split("?")[0];
1520
+ const importerFile = (rawImporter && normalizeViteFilePath(rawImporter)) ||
1521
+ rawImporter ||
1522
+ path.join(process.cwd(), "index.ts");
1523
+ const resolved = path.isAbsolute(rawFile)
1524
+ ? rawFile
1525
+ : path.resolve(path.dirname(importerFile), rawFile);
1526
+ return `${resolved}?${request.query}`;
1527
+ }
1528
+ function readAppChangelogMarkdown(changelogPath, watchFile) {
1529
+ // Only ever register real files with Vite's `addWatchFile`. Passing a
1530
+ // directory makes import-analysis try to resolve it as a module and fail
1531
+ // with "Failed to resolve import .../changelog", which breaks hydration for
1532
+ // every template in dev. New/removed pending files are still picked up via
1533
+ // `handleHotUpdate` (Vite watches the project root recursively).
1534
+ watchFile(changelogPath);
1535
+ const existing = fs.existsSync(changelogPath)
1536
+ ? fs.readFileSync(changelogPath, "utf-8")
1537
+ : "";
1538
+ const pendingDir = path.join(path.dirname(changelogPath), "changelog");
1539
+ if (!fs.existsSync(pendingDir)) {
1540
+ return existing;
1541
+ }
1542
+ const pending = fs
1543
+ .readdirSync(pendingDir)
1544
+ .filter((file) => file.endsWith(".md") && file.toLowerCase() !== "readme.md")
1545
+ .sort()
1546
+ .map((file) => {
1547
+ const filePath = path.join(pendingDir, file);
1548
+ watchFile(filePath);
1549
+ return parsePendingEntry(fs.readFileSync(filePath, "utf-8"));
1550
+ });
1551
+ return mergePendingChangelog(existing, pending);
1552
+ }
1553
+ function isChangelogSourceFile(file) {
1554
+ if (path.basename(file) === "CHANGELOG.md")
1555
+ return true;
1556
+ return (path.basename(path.dirname(file)) === "changelog" &&
1557
+ file.endsWith(".md") &&
1558
+ path.basename(file).toLowerCase() !== "readme.md");
1559
+ }
1560
+ function invalidateChangelogRawModules(server) {
1561
+ const moduleGraph = server.moduleGraph;
1562
+ if (!moduleGraph?.idToModuleMap || !moduleGraph.invalidateModule)
1563
+ return;
1564
+ for (const mod of moduleGraph.idToModuleMap.values()) {
1565
+ if (!mod?.id || !changelogRawPathFromId(mod.id))
1566
+ continue;
1567
+ moduleGraph.invalidateModule(mod);
1568
+ }
1569
+ }
1570
+ function appChangelogRawPlugin() {
1571
+ return {
1572
+ name: "agent-native-app-changelog-raw",
1573
+ enforce: "pre",
1574
+ resolveId(source, importer) {
1575
+ return resolveChangelogRawImport(source, importer);
1576
+ },
1577
+ load(id) {
1578
+ const changelogPath = changelogRawPathFromId(id);
1579
+ if (!changelogPath)
1580
+ return null;
1581
+ const markdown = readAppChangelogMarkdown(changelogPath, (file) => this.addWatchFile(file));
1582
+ return `export default ${JSON.stringify(markdown)};`;
1583
+ },
1584
+ handleHotUpdate(ctx) {
1585
+ if (!isChangelogSourceFile(ctx.file))
1586
+ return;
1587
+ invalidateChangelogRawModules(ctx.server);
1588
+ ctx.server.ws.send({ type: "full-reload" });
1589
+ return [];
1590
+ },
1591
+ };
1592
+ }
1474
1593
  /**
1475
1594
  * Expose the resolved Vite dev server port as process.env.PORT so that
1476
1595
  * in-process scripts (which use localFetch → http://localhost:${PORT}/api/...)
@@ -1659,12 +1778,13 @@ function localWorkspacePackageAliases(packages) {
1659
1778
  if (!exportsMap || typeof exportsMap !== "object")
1660
1779
  continue;
1661
1780
  for (const [exportPath, target] of Object.entries(exportsMap)) {
1662
- if (typeof target !== "string")
1781
+ const exportTarget = localWorkspaceExportTarget(packageDir, target);
1782
+ if (!exportTarget)
1663
1783
  continue;
1664
1784
  const importPath = exportPath === "."
1665
1785
  ? packageName
1666
1786
  : `${packageName}${exportPath.slice(1)}`;
1667
- const replacement = path.resolve(packageDir, target);
1787
+ const replacement = path.resolve(packageDir, exportTarget);
1668
1788
  if (importPath.includes("*") || replacement.includes("*")) {
1669
1789
  aliases.push({
1670
1790
  find: new RegExp(`^${escapeRegex(importPath).replace("\\*", "(.+)")}$`),
@@ -1684,6 +1804,48 @@ function localWorkspacePackageAliases(packages) {
1684
1804
  }
1685
1805
  return aliases;
1686
1806
  }
1807
+ function localWorkspaceExportTarget(packageDir, target) {
1808
+ const rawTarget = pickLocalWorkspaceExportTarget(target);
1809
+ if (!rawTarget)
1810
+ return null;
1811
+ return distExportToSourceTarget(packageDir, rawTarget);
1812
+ }
1813
+ function pickLocalWorkspaceExportTarget(target) {
1814
+ if (typeof target === "string")
1815
+ return target;
1816
+ if (!target || typeof target !== "object" || Array.isArray(target)) {
1817
+ return null;
1818
+ }
1819
+ const record = target;
1820
+ for (const condition of ["development", "browser", "import", "default"]) {
1821
+ const resolved = pickLocalWorkspaceExportTarget(record[condition]);
1822
+ if (resolved)
1823
+ return resolved;
1824
+ }
1825
+ return null;
1826
+ }
1827
+ function distExportToSourceTarget(packageDir, target) {
1828
+ if (!target.startsWith("./dist/"))
1829
+ return target;
1830
+ if (target.includes("*")) {
1831
+ return target
1832
+ .replace("./dist/", "./src/")
1833
+ .replace(/\.d\.ts$/, "")
1834
+ .replace(/\.js$/, "");
1835
+ }
1836
+ const sourceBase = target
1837
+ .replace("./dist/", "./src/")
1838
+ .replace(/\.d\.ts$/, "")
1839
+ .replace(/\.js$/, "");
1840
+ const candidates = target.endsWith(".css")
1841
+ ? [sourceBase]
1842
+ : [`${sourceBase}.tsx`, `${sourceBase}.ts`, sourceBase];
1843
+ for (const candidate of candidates) {
1844
+ if (fs.existsSync(path.resolve(packageDir, candidate)))
1845
+ return candidate;
1846
+ }
1847
+ return target;
1848
+ }
1687
1849
  function aliasArrayFrom(alias) {
1688
1850
  if (!alias)
1689
1851
  return [];
@@ -1701,7 +1863,6 @@ const DEFAULT_VITE_WATCH_IGNORES = [
1701
1863
  "**/.generated/**",
1702
1864
  "**/.agents/**",
1703
1865
  "**/.claude/**",
1704
- "**/changelog/**",
1705
1866
  "**/data/**",
1706
1867
  "**/dist/**",
1707
1868
  "**/build/**",
@@ -1722,6 +1883,7 @@ function createAgentNativePlugins(options, { command, includeReactTransform, use
1722
1883
  // the server, so we can't blanket-stub it here).
1723
1884
  ssrStubPlugin(options.ssrStubs ?? []),
1724
1885
  ...userPlugins,
1886
+ appChangelogRawPlugin(),
1725
1887
  actionTypesPlugin(),
1726
1888
  agentsBundlePlugin(),
1727
1889
  autoReloadOnOptimizeDep(),