@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
@@ -8,9 +8,146 @@ import { z } from "zod";
8
8
 
9
9
  import "../server/db/index.js"; // ensure registerShareableResource runs
10
10
 
11
+ const MAX_AGENT_CONTEXT_CHARS = 14_000;
12
+ const MAX_JSON_CONTEXT_CHARS = 2_500;
13
+ const MAX_BUILDER_DOCS = 8;
14
+ const MAX_BUILDER_DOC_CHARS = 1_200;
15
+ const MAX_TOKEN_VALUES = 48;
16
+
17
+ interface BuilderGenerationContext {
18
+ builderDesignSystemId: string;
19
+ builderJobId: string;
20
+ builderProjectId?: string;
21
+ builderUrl?: string;
22
+ builderStatus?: string;
23
+ docs: Array<{
24
+ name?: string;
25
+ type?: string;
26
+ description?: string;
27
+ content?: string;
28
+ tokenValues?: Record<string, string>;
29
+ }>;
30
+ tokenValues: Record<string, string>;
31
+ docCount: number;
32
+ warning?: string;
33
+ }
34
+
35
+ function truncate(value: string, maxChars: number): string {
36
+ if (value.length <= maxChars) return value;
37
+ return `${value.slice(0, maxChars).trimEnd()}\n[truncated]`;
38
+ }
39
+
40
+ function parseJson(value: string | null | undefined): unknown {
41
+ if (!value) return null;
42
+ try {
43
+ return JSON.parse(value);
44
+ } catch {
45
+ return null;
46
+ }
47
+ }
48
+
49
+ function formatJson(value: unknown, maxChars = MAX_JSON_CONTEXT_CHARS): string {
50
+ return truncate(JSON.stringify(value, null, 2), maxChars);
51
+ }
52
+
53
+ function formatTokenValues(tokenValues: Record<string, string>): string[] {
54
+ const entries = Object.entries(tokenValues)
55
+ .filter(([, value]) => typeof value === "string" && value.trim())
56
+ .slice(0, MAX_TOKEN_VALUES);
57
+ if (entries.length === 0) return [];
58
+ return [
59
+ "Builder DSI token values to apply first:",
60
+ ...entries.map(([name, value]) => `- ${name}: ${value}`),
61
+ ];
62
+ }
63
+
64
+ function buildDesignSystemAgentContext({
65
+ id,
66
+ title,
67
+ description,
68
+ data,
69
+ assets,
70
+ customInstructions,
71
+ builder,
72
+ }: {
73
+ id: string;
74
+ title: string;
75
+ description?: string | null;
76
+ data?: string | null;
77
+ assets?: string | null;
78
+ customInstructions?: string | null;
79
+ builder: BuilderGenerationContext | null;
80
+ }): string {
81
+ const lines: string[] = [
82
+ "## Selected Design System Context",
83
+ `Use "${title}" (id: ${id}) as the visual source of truth for this deck.`,
84
+ "Apply these tokens, assets, and usage notes before choosing colors, type, spacing, radius, imagery, slide defaults, or component language.",
85
+ ];
86
+
87
+ if (description?.trim()) {
88
+ lines.push("", "Description:", description.trim());
89
+ }
90
+
91
+ if (customInstructions?.trim()) {
92
+ lines.push("", "Custom instructions:", customInstructions.trim());
93
+ }
94
+
95
+ const parsedAssets = parseJson(assets);
96
+ if (Array.isArray(parsedAssets) && parsedAssets.length > 0) {
97
+ lines.push("", "Design system assets:", formatJson(parsedAssets));
98
+ }
99
+
100
+ if (builder) {
101
+ lines.push(
102
+ "",
103
+ "Builder DSI:",
104
+ `- Design system id: ${builder.builderDesignSystemId}`,
105
+ `- Job id: ${builder.builderJobId}`,
106
+ builder.builderProjectId
107
+ ? `- Project id: ${builder.builderProjectId}`
108
+ : "",
109
+ builder.builderUrl ? `- URL: ${builder.builderUrl}` : "",
110
+ builder.builderStatus ? `- Status: ${builder.builderStatus}` : "",
111
+ "- Builder DSI docs and token values override local proxy placeholders.",
112
+ "- Do not substitute a generic style if DSI docs or tokens are unavailable; call get-design-system again or tell the user Builder indexing is not ready.",
113
+ );
114
+
115
+ if (builder.warning) {
116
+ lines.push(`- Warning: ${builder.warning}`);
117
+ }
118
+
119
+ lines.push("", ...formatTokenValues(builder.tokenValues));
120
+
121
+ const docs = builder.docs.slice(0, MAX_BUILDER_DOCS);
122
+ if (docs.length > 0) {
123
+ lines.push("", "Builder DSI docs to follow:");
124
+ for (const doc of docs) {
125
+ const label = [doc.name, doc.type ? `(${doc.type})` : ""]
126
+ .filter(Boolean)
127
+ .join(" ");
128
+ lines.push(
129
+ "",
130
+ `### ${label || "Design system doc"}`,
131
+ doc.description?.trim() ? doc.description.trim() : "",
132
+ doc.content?.trim()
133
+ ? truncate(doc.content.trim(), MAX_BUILDER_DOC_CHARS)
134
+ : "",
135
+ );
136
+ }
137
+ }
138
+ } else {
139
+ const parsedData = parseJson(data);
140
+ if (parsedData) {
141
+ lines.push("", "Local design-system tokens:", formatJson(parsedData));
142
+ }
143
+ }
144
+
145
+ return truncate(lines.filter(Boolean).join("\n"), MAX_AGENT_CONTEXT_CHARS);
146
+ }
147
+
11
148
  export default defineAction({
12
149
  description:
13
- "Get a design system by ID. Returns full design system data including colors, typography, spacing, and assets.",
150
+ "Get a design system by ID. Returns full design system data including colors, typography, spacing, assets, and a compact agentContext for generation.",
14
151
  schema: z.object({
15
152
  id: z.string().describe("Design system ID"),
16
153
  }),
@@ -51,6 +188,15 @@ export default defineAction({
51
188
  createdAt: row.createdAt,
52
189
  updatedAt: row.updatedAt,
53
190
  builder,
191
+ agentContext: buildDesignSystemAgentContext({
192
+ id: row.id,
193
+ title: row.title,
194
+ description: row.description,
195
+ data: row.data,
196
+ assets: row.assets,
197
+ customInstructions: row.customInstructions,
198
+ builder,
199
+ }),
54
200
  };
55
201
  },
56
202
  });
@@ -101,6 +101,47 @@ function truncateSourceForContext(prompt: string): {
101
101
  };
102
102
  }
103
103
 
104
+ interface DesignSystemGenerationContextResult {
105
+ title?: string;
106
+ agentContext?: string;
107
+ }
108
+
109
+ async function loadDesignSystemGenerationContext(
110
+ designSystemId?: string | null,
111
+ ): Promise<string> {
112
+ if (!designSystemId) return "";
113
+ try {
114
+ const result = (await callAction(
115
+ "get-design-system",
116
+ { id: designSystemId },
117
+ { method: "GET" },
118
+ )) as DesignSystemGenerationContextResult | undefined;
119
+ if (result?.agentContext?.trim()) {
120
+ return [
121
+ "",
122
+ result.agentContext.trim(),
123
+ "",
124
+ "The selected design system context above was hydrated before this agent run. Follow it directly; do not replace it with generic colors, fonts, spacing, imagery, or slide components.",
125
+ ].join("\n");
126
+ }
127
+ } catch (error) {
128
+ const message =
129
+ error instanceof Error ? error.message : "unknown loading error";
130
+ return [
131
+ "",
132
+ "## Selected Design System Context",
133
+ `The selected design system id "${designSystemId}" could not be loaded before generation: ${message}`,
134
+ "Before adding slides, call `get-design-system` for this id. If it still fails, stop and tell the user the selected design system is unavailable instead of improvising a generic style.",
135
+ ].join("\n");
136
+ }
137
+ return [
138
+ "",
139
+ "## Selected Design System Context",
140
+ `The selected design system id "${designSystemId}" returned no generation context.`,
141
+ "Call `get-design-system` for this id before adding slides. If it still has no usable tokens/docs, stop and ask the user to finish design-system indexing instead of improvising a generic style.",
142
+ ].join("\n");
143
+ }
144
+
104
145
  function describeUploadedFilesForAgent(
105
146
  files: UploadedFile[],
106
147
  deckId: string,
@@ -359,13 +400,17 @@ export default function Index() {
359
400
  "If the action cannot read a private document, tell the user the exact sharing step from the action error instead of generating from the URL alone.",
360
401
  ].join("\n")
361
402
  : "";
403
+ const hydratedDesignSystemContext = await loadDesignSystemGenerationContext(
404
+ selectedDesignSystem?.id,
405
+ );
362
406
  const designSystemContext = selectedDesignSystem
363
407
  ? [
364
408
  "",
365
409
  "Design system selection:",
366
410
  `- Use "${selectedDesignSystem.title}" (id: ${selectedDesignSystem.id}).`,
367
411
  "- The deck has already been linked to this design system.",
368
- `- Before adding slides, call \`get-design-system --id ${selectedDesignSystem.id}\` and use its tokens for colors, typography, spacing, imagery, and slide defaults.`,
412
+ "- Use the hydrated design system context below for colors, typography, spacing, imagery, and slide defaults.",
413
+ hydratedDesignSystemContext,
369
414
  "- Do not choose or apply a different design system.",
370
415
  ].join("\n")
371
416
  : [
@@ -4,9 +4,11 @@ import {
4
4
  SettingsTabsPage,
5
5
  useAgentSettingsTabs,
6
6
  useT,
7
+ type SettingsSearchEntry,
7
8
  } from "@agent-native/core/client";
8
9
  import { TeamPage } from "@agent-native/core/client/org";
9
10
  import { useSetPageTitle } from "@agent-native/toolkit/app-shell";
11
+ import { useMemo } from "react";
10
12
 
11
13
  import {
12
14
  Card,
@@ -29,17 +31,30 @@ export default function SettingsRoute() {
29
31
  const agentSettingsTabs = useAgentSettingsTabs();
30
32
  useSetPageTitle(t("settings.title"));
31
33
 
34
+ const generalSearchEntries = useMemo<SettingsSearchEntry[]>(
35
+ () => [
36
+ {
37
+ id: "slides-language",
38
+ label: t("settings.languageTitle"),
39
+ keywords: "language locale translation i18n",
40
+ hash: "language",
41
+ },
42
+ ],
43
+ [t],
44
+ );
45
+
32
46
  return (
33
47
  <SettingsTabsPage
34
48
  teamLabel={t("navigation.team")}
35
49
  extraTabs={agentSettingsTabs}
50
+ generalSearchEntries={generalSearchEntries}
36
51
  general={
37
52
  <div className="mx-auto w-full max-w-3xl space-y-6">
38
53
  <p className="text-sm leading-6 text-muted-foreground">
39
54
  {t("settings.description")}
40
55
  </p>
41
56
 
42
- <Card>
57
+ <Card id="language" className="scroll-mt-16">
43
58
  <CardHeader>
44
59
  <CardTitle className="text-base">
45
60
  {t("settings.languageTitle")}
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: fixed
3
+ date: 2026-07-08
4
+ ---
5
+
6
+ Deck generation now follows hydrated Builder design-system guidance before adding slides.
@@ -0,0 +1,5 @@
1
+ ---
2
+ type: improved
3
+ ---
4
+
5
+ Settings are cleaner and searchable, with a consistent navigation that jumps straight to any setting.
@@ -1,3 +1,5 @@
1
+ import type { AccessContext } from "../sharing/access.js";
2
+ import type { ShareRole } from "../sharing/schema.js";
1
3
  /**
2
4
  * Resolve a run's owning thread id. Checks in-memory run state first (populated
3
5
  * synchronously by startRun, so there is no race against the async SQL insert),
@@ -7,6 +9,10 @@
7
9
  export declare function resolveRunThreadId(runId: string): Promise<string | null>;
8
10
  /** True when `owner` owns the chat thread `threadId`. */
9
11
  export declare function callerOwnsThread(owner: string, threadId: string | null | undefined): Promise<boolean>;
12
+ /** True when `owner` has at least `role` access to the chat thread. */
13
+ export declare function callerHasThreadAccess(owner: string, threadId: string | null | undefined, role?: ShareRole | "owner", ctx?: Omit<AccessContext, "userEmail">): Promise<boolean>;
10
14
  /** True when `owner` owns the thread that run `runId` belongs to. */
11
15
  export declare function callerOwnsRun(owner: string, runId: string): Promise<boolean>;
16
+ /** True when `owner` has at least `role` access to the thread behind `runId`. */
17
+ export declare function callerHasRunAccess(owner: string, runId: string, role?: ShareRole | "owner", ctx?: Omit<AccessContext, "userEmail">): Promise<boolean>;
12
18
  //# sourceMappingURL=run-ownership.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"run-ownership.d.ts","sourceRoot":"","sources":["../../src/agent/run-ownership.ts"],"names":[],"mappings":"AAeA;;;;;GAKG;AACH,wBAAsB,kBAAkB,CACtC,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAKxB;AAED,yDAAyD;AACzD,wBAAsB,gBAAgB,CACpC,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAClC,OAAO,CAAC,OAAO,CAAC,CAIlB;AAED,qEAAqE;AACrE,wBAAsB,aAAa,CACjC,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,OAAO,CAAC,CAElB"}
1
+ {"version":3,"file":"run-ownership.d.ts","sourceRoot":"","sources":["../../src/agent/run-ownership.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAetD;;;;;GAKG;AACH,wBAAsB,kBAAkB,CACtC,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAKxB;AAED,yDAAyD;AACzD,wBAAsB,gBAAgB,CACpC,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAClC,OAAO,CAAC,OAAO,CAAC,CAIlB;AAED,uEAAuE;AACvE,wBAAsB,qBAAqB,CACzC,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EACnC,IAAI,GAAE,SAAS,GAAG,OAAkB,EACpC,GAAG,GAAE,IAAI,CAAC,aAAa,EAAE,WAAW,CAAM,GACzC,OAAO,CAAC,OAAO,CAAC,CAGlB;AAED,qEAAqE;AACrE,wBAAsB,aAAa,CACjC,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,OAAO,CAAC,CAElB;AAED,iFAAiF;AACjF,wBAAsB,kBAAkB,CACtC,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,EACb,IAAI,GAAE,SAAS,GAAG,OAAkB,EACpC,GAAG,GAAE,IAAI,CAAC,aAAa,EAAE,WAAW,CAAM,GACzC,OAAO,CAAC,OAAO,CAAC,CAOlB"}
@@ -1,4 +1,4 @@
1
- import { getThread } from "../chat-threads/store.js";
1
+ import { getThread, resolveThreadAccess } from "../chat-threads/store.js";
2
2
  /**
3
3
  * Ownership checks for the agent run HTTP routes (`/runs/:id/events`,
4
4
  * `/runs/:id/abort`, `/runs/active`).
@@ -32,8 +32,18 @@ export async function callerOwnsThread(owner, threadId) {
32
32
  const thread = await getThread(threadId);
33
33
  return !!thread && thread.ownerEmail === owner;
34
34
  }
35
+ /** True when `owner` has at least `role` access to the chat thread. */
36
+ export async function callerHasThreadAccess(owner, threadId, role = "viewer", ctx = {}) {
37
+ if (!threadId)
38
+ return false;
39
+ return !!(await resolveThreadAccess(owner, threadId, role, ctx));
40
+ }
35
41
  /** True when `owner` owns the thread that run `runId` belongs to. */
36
42
  export async function callerOwnsRun(owner, runId) {
37
43
  return callerOwnsThread(owner, await resolveRunThreadId(runId));
38
44
  }
45
+ /** True when `owner` has at least `role` access to the thread behind `runId`. */
46
+ export async function callerHasRunAccess(owner, runId, role = "viewer", ctx = {}) {
47
+ return callerHasThreadAccess(owner, await resolveRunThreadId(runId), role, ctx);
48
+ }
39
49
  //# sourceMappingURL=run-ownership.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"run-ownership.js","sourceRoot":"","sources":["../../src/agent/run-ownership.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AACrD;;;;;;;;;;GAUG;AACH,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAE5C;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,KAAa;IAEb,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IAC7B,IAAI,MAAM;QAAE,OAAO,MAAM,CAAC,QAAQ,CAAC;IACnC,MAAM,GAAG,GAAG,MAAM,UAAU,CAAC,KAAK,CAAC,CAAC;IACpC,OAAO,GAAG,EAAE,QAAQ,IAAI,IAAI,CAAC;AAC/B,CAAC;AAED,yDAAyD;AACzD,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,KAAa,EACb,QAAmC;IAEnC,IAAI,CAAC,QAAQ;QAAE,OAAO,KAAK,CAAC;IAC5B,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,QAAQ,CAAC,CAAC;IACzC,OAAO,CAAC,CAAC,MAAM,IAAI,MAAM,CAAC,UAAU,KAAK,KAAK,CAAC;AACjD,CAAC;AAED,qEAAqE;AACrE,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,KAAa,EACb,KAAa;IAEb,OAAO,gBAAgB,CAAC,KAAK,EAAE,MAAM,kBAAkB,CAAC,KAAK,CAAC,CAAC,CAAC;AAClE,CAAC","sourcesContent":["import { getThread } from \"../chat-threads/store.js\";\n/**\n * Ownership checks for the agent run HTTP routes (`/runs/:id/events`,\n * `/runs/:id/abort`, `/runs/active`).\n *\n * `agent_runs` has no owner column — a run's ownership lives on its\n * `chat_threads` row via `thread_id`. These helpers resolve that link and\n * compare the thread's owner to the requesting user, so the run routes can\n * reject cross-tenant access (any authenticated user who learns another\n * tenant's runId/threadId must not be able to stream their live agent turn or\n * abort their run).\n */\nimport { getRun } from \"./run-manager.js\";\nimport { getRunById } from \"./run-store.js\";\n\n/**\n * Resolve a run's owning thread id. Checks in-memory run state first (populated\n * synchronously by startRun, so there is no race against the async SQL insert),\n * then falls back to SQL for cross-isolate / post-reload lookups. Returns null\n * when the run is unknown.\n */\nexport async function resolveRunThreadId(\n runId: string,\n): Promise<string | null> {\n const memRun = getRun(runId);\n if (memRun) return memRun.threadId;\n const row = await getRunById(runId);\n return row?.threadId ?? null;\n}\n\n/** True when `owner` owns the chat thread `threadId`. */\nexport async function callerOwnsThread(\n owner: string,\n threadId: string | null | undefined,\n): Promise<boolean> {\n if (!threadId) return false;\n const thread = await getThread(threadId);\n return !!thread && thread.ownerEmail === owner;\n}\n\n/** True when `owner` owns the thread that run `runId` belongs to. */\nexport async function callerOwnsRun(\n owner: string,\n runId: string,\n): Promise<boolean> {\n return callerOwnsThread(owner, await resolveRunThreadId(runId));\n}\n"]}
1
+ {"version":3,"file":"run-ownership.js","sourceRoot":"","sources":["../../src/agent/run-ownership.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAG1E;;;;;;;;;;GAUG;AACH,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAE5C;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,KAAa;IAEb,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IAC7B,IAAI,MAAM;QAAE,OAAO,MAAM,CAAC,QAAQ,CAAC;IACnC,MAAM,GAAG,GAAG,MAAM,UAAU,CAAC,KAAK,CAAC,CAAC;IACpC,OAAO,GAAG,EAAE,QAAQ,IAAI,IAAI,CAAC;AAC/B,CAAC;AAED,yDAAyD;AACzD,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,KAAa,EACb,QAAmC;IAEnC,IAAI,CAAC,QAAQ;QAAE,OAAO,KAAK,CAAC;IAC5B,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,QAAQ,CAAC,CAAC;IACzC,OAAO,CAAC,CAAC,MAAM,IAAI,MAAM,CAAC,UAAU,KAAK,KAAK,CAAC;AACjD,CAAC;AAED,uEAAuE;AACvE,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,KAAa,EACb,QAAmC,EACnC,IAAI,GAAwB,QAAQ,EACpC,GAAG,GAAqC,EAAE;IAE1C,IAAI,CAAC,QAAQ;QAAE,OAAO,KAAK,CAAC;IAC5B,OAAO,CAAC,CAAC,CAAC,MAAM,mBAAmB,CAAC,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC;AACnE,CAAC;AAED,qEAAqE;AACrE,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,KAAa,EACb,KAAa;IAEb,OAAO,gBAAgB,CAAC,KAAK,EAAE,MAAM,kBAAkB,CAAC,KAAK,CAAC,CAAC,CAAC;AAClE,CAAC;AAED,iFAAiF;AACjF,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,KAAa,EACb,KAAa,EACb,IAAI,GAAwB,QAAQ,EACpC,GAAG,GAAqC,EAAE;IAE1C,OAAO,qBAAqB,CAC1B,KAAK,EACL,MAAM,kBAAkB,CAAC,KAAK,CAAC,EAC/B,IAAI,EACJ,GAAG,CACJ,CAAC;AACJ,CAAC","sourcesContent":["import { getThread, resolveThreadAccess } from \"../chat-threads/store.js\";\nimport type { AccessContext } from \"../sharing/access.js\";\nimport type { ShareRole } from \"../sharing/schema.js\";\n/**\n * Ownership checks for the agent run HTTP routes (`/runs/:id/events`,\n * `/runs/:id/abort`, `/runs/active`).\n *\n * `agent_runs` has no owner column — a run's ownership lives on its\n * `chat_threads` row via `thread_id`. These helpers resolve that link and\n * compare the thread's owner to the requesting user, so the run routes can\n * reject cross-tenant access (any authenticated user who learns another\n * tenant's runId/threadId must not be able to stream their live agent turn or\n * abort their run).\n */\nimport { getRun } from \"./run-manager.js\";\nimport { getRunById } from \"./run-store.js\";\n\n/**\n * Resolve a run's owning thread id. Checks in-memory run state first (populated\n * synchronously by startRun, so there is no race against the async SQL insert),\n * then falls back to SQL for cross-isolate / post-reload lookups. Returns null\n * when the run is unknown.\n */\nexport async function resolveRunThreadId(\n runId: string,\n): Promise<string | null> {\n const memRun = getRun(runId);\n if (memRun) return memRun.threadId;\n const row = await getRunById(runId);\n return row?.threadId ?? null;\n}\n\n/** True when `owner` owns the chat thread `threadId`. */\nexport async function callerOwnsThread(\n owner: string,\n threadId: string | null | undefined,\n): Promise<boolean> {\n if (!threadId) return false;\n const thread = await getThread(threadId);\n return !!thread && thread.ownerEmail === owner;\n}\n\n/** True when `owner` has at least `role` access to the chat thread. */\nexport async function callerHasThreadAccess(\n owner: string,\n threadId: string | null | undefined,\n role: ShareRole | \"owner\" = \"viewer\",\n ctx: Omit<AccessContext, \"userEmail\"> = {},\n): Promise<boolean> {\n if (!threadId) return false;\n return !!(await resolveThreadAccess(owner, threadId, role, ctx));\n}\n\n/** True when `owner` owns the thread that run `runId` belongs to. */\nexport async function callerOwnsRun(\n owner: string,\n runId: string,\n): Promise<boolean> {\n return callerOwnsThread(owner, await resolveRunThreadId(runId));\n}\n\n/** True when `owner` has at least `role` access to the thread behind `runId`. */\nexport async function callerHasRunAccess(\n owner: string,\n runId: string,\n role: ShareRole | \"owner\" = \"viewer\",\n ctx: Omit<AccessContext, \"userEmail\"> = {},\n): Promise<boolean> {\n return callerHasThreadAccess(\n owner,\n await resolveRunThreadId(runId),\n role,\n ctx,\n );\n}\n"]}
@@ -66,5 +66,12 @@ declare const CHANGELOG_HEADER: string;
66
66
  * the full updated document. Pure — the CLI handles file IO and deletion.
67
67
  */
68
68
  export declare function rollupChangelog(existing: string, pending: PendingChangelogEntry[], releaseDate: string): string;
69
+ /**
70
+ * Render an app-facing changelog that includes both released CHANGELOG.md
71
+ * sections and adjacent pending `changelog/*.md` entries. Unlike `release`,
72
+ * this is pure and non-destructive, so build/dev bundles can show current
73
+ * product notes without deleting the conflict-free pending files.
74
+ */
75
+ export declare function mergePendingChangelog(existing: string, pending: PendingChangelogEntry[]): string;
69
76
  export { CHANGELOG_HEADER, GROUP_LABELS };
70
77
  //# sourceMappingURL=parse.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"parse.d.ts","sourceRoot":"","sources":["../../src/changelog/parse.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,wDAAwD;AACxD,MAAM,WAAW,cAAc;IAC7B,uEAAuE;IACvE,EAAE,EAAE,MAAM,CAAC;IACX,oEAAoE;IACpE,KAAK,EAAE,MAAM,CAAC;IACd,oEAAoE;IACpE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,4DAA4D;IAC5D,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,wEAAwE;IACxE,IAAI,EAAE,MAAM,CAAC;CACd;AAED,yEAAyE;AACzE,MAAM,WAAW,qBAAqB;IACpC,+DAA+D;IAC/D,IAAI,EAAE,mBAAmB,CAAC;IAC1B,oDAAoD;IACpD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,yDAAyD;IACzD,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,MAAM,mBAAmB,GAC3B,OAAO,GACP,UAAU,GACV,OAAO,GACP,SAAS,GACT,SAAS,GACT,UAAU,CAAC;AAEf;;;GAGG;AACH,eAAO,MAAM,qBAAqB,EAAE,mBAAmB,EAOtD,CAAC;AAEF,QAAA,MAAM,YAAY,EAAE,MAAM,CAAC,mBAAmB,EAAE,MAAM,CAOrD,CAAC;AAIF,6DAA6D;AAC7D,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAMnD;AAiBD;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,cAAc,EAAE,CA+CjE;AAOD;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,qBAAqB,CAuBxE;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,qBAAqB,EAAE,GAAG,MAAM,CAwB1E;AAED,QAAA,MAAM,gBAAgB,QAEgD,CAAC;AAEvE;;;;GAIG;AACH,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,qBAAqB,EAAE,EAChC,WAAW,EAAE,MAAM,GAClB,MAAM,CAgBR;AAED,OAAO,EAAE,gBAAgB,EAAE,YAAY,EAAE,CAAC"}
1
+ {"version":3,"file":"parse.d.ts","sourceRoot":"","sources":["../../src/changelog/parse.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,wDAAwD;AACxD,MAAM,WAAW,cAAc;IAC7B,uEAAuE;IACvE,EAAE,EAAE,MAAM,CAAC;IACX,oEAAoE;IACpE,KAAK,EAAE,MAAM,CAAC;IACd,oEAAoE;IACpE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,4DAA4D;IAC5D,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,wEAAwE;IACxE,IAAI,EAAE,MAAM,CAAC;CACd;AAED,yEAAyE;AACzE,MAAM,WAAW,qBAAqB;IACpC,+DAA+D;IAC/D,IAAI,EAAE,mBAAmB,CAAC;IAC1B,oDAAoD;IACpD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,yDAAyD;IACzD,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,MAAM,mBAAmB,GAC3B,OAAO,GACP,UAAU,GACV,OAAO,GACP,SAAS,GACT,SAAS,GACT,UAAU,CAAC;AAEf;;;GAGG;AACH,eAAO,MAAM,qBAAqB,EAAE,mBAAmB,EAOtD,CAAC;AAEF,QAAA,MAAM,YAAY,EAAE,MAAM,CAAC,mBAAmB,EAAE,MAAM,CAOrD,CAAC;AAIF,6DAA6D;AAC7D,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAMnD;AAiBD;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,cAAc,EAAE,CA+CjE;AAOD;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,qBAAqB,CAuBxE;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,qBAAqB,EAAE,GAAG,MAAM,CAwB1E;AAED,QAAA,MAAM,gBAAgB,QAEgD,CAAC;AAEvE;;;;GAIG;AACH,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,qBAAqB,EAAE,EAChC,WAAW,EAAE,MAAM,GAClB,MAAM,CAgBR;AA0BD;;;;;GAKG;AACH,wBAAgB,qBAAqB,CACnC,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,qBAAqB,EAAE,GAC/B,MAAM,CA2CR;AAED,OAAO,EAAE,gBAAgB,EAAE,YAAY,EAAE,CAAC"}
@@ -196,5 +196,69 @@ export function rollupChangelog(existing, pending, releaseDate) {
196
196
  const rest = doc.slice(firstRelease);
197
197
  return `${head}\n\n${section}\n${rest}\n`;
198
198
  }
199
+ function changelogHeader(markdown) {
200
+ const doc = (markdown || CHANGELOG_HEADER).replace(/\s+$/, "");
201
+ const firstRelease = doc.search(/^##\s+(?!#)/m);
202
+ const header = (firstRelease === -1 ? doc : doc.slice(0, firstRelease)).replace(/\s+$/, "") || CHANGELOG_HEADER.trim();
203
+ return header;
204
+ }
205
+ function pendingSectionTitle(entry) {
206
+ return entry.date?.match(ISO_DATE)?.[1] ?? "Unreleased";
207
+ }
208
+ function pendingSectionSort(a, b) {
209
+ const aDate = a.match(ISO_DATE)?.[1];
210
+ const bDate = b.match(ISO_DATE)?.[1];
211
+ if (aDate && bDate)
212
+ return bDate.localeCompare(aDate);
213
+ if (!aDate && bDate)
214
+ return -1;
215
+ if (aDate && !bDate)
216
+ return 1;
217
+ return a.localeCompare(b);
218
+ }
219
+ /**
220
+ * Render an app-facing changelog that includes both released CHANGELOG.md
221
+ * sections and adjacent pending `changelog/*.md` entries. Unlike `release`,
222
+ * this is pure and non-destructive, so build/dev bundles can show current
223
+ * product notes without deleting the conflict-free pending files.
224
+ */
225
+ export function mergePendingChangelog(existing, pending) {
226
+ const pendingWithText = pending.filter((entry) => entry.text.trim());
227
+ if (pendingWithText.length === 0)
228
+ return existing || CHANGELOG_HEADER;
229
+ const existingEntries = parseChangelog(existing);
230
+ const usedExistingIndexes = new Set();
231
+ const pendingByTitle = new Map();
232
+ for (const entry of pendingWithText) {
233
+ const title = pendingSectionTitle(entry);
234
+ pendingByTitle.set(title, [...(pendingByTitle.get(title) ?? []), entry]);
235
+ }
236
+ const sections = [];
237
+ for (const title of [...pendingByTitle.keys()].sort(pendingSectionSort)) {
238
+ const body = renderReleaseBody(pendingByTitle.get(title) ?? []);
239
+ if (!body)
240
+ continue;
241
+ const existingIndex = existingEntries.findIndex((entry, index) => {
242
+ if (usedExistingIndexes.has(index))
243
+ return false;
244
+ return entry.date === title || entry.title === title;
245
+ });
246
+ if (existingIndex === -1) {
247
+ sections.push(`## ${title}\n\n${body}`);
248
+ continue;
249
+ }
250
+ usedExistingIndexes.add(existingIndex);
251
+ const existingEntry = existingEntries[existingIndex];
252
+ sections.push(`## ${existingEntry.title}\n\n${[body, existingEntry.body]
253
+ .filter(Boolean)
254
+ .join("\n\n")}`);
255
+ }
256
+ existingEntries.forEach((entry, index) => {
257
+ if (usedExistingIndexes.has(index))
258
+ return;
259
+ sections.push(`## ${entry.title}\n\n${entry.body}`);
260
+ });
261
+ return `${changelogHeader(existing)}\n\n${sections.join("\n\n")}\n`;
262
+ }
199
263
  export { CHANGELOG_HEADER, GROUP_LABELS };
200
264
  //# sourceMappingURL=parse.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"parse.js","sourceRoot":"","sources":["../../src/changelog/parse.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Shared, dependency-free changelog parsing + serialization.\n *\n * Used by BOTH:\n * - the browser bundle (rendering an app's CHANGELOG.md in the command\n * menu / settings \"What's new\" surface), and\n * - the `agent-native changelog` CLI (rolling pending entry files up into\n * CHANGELOG.md).\n *\n * Keep this file isomorphic: no Node, no browser, no third-party deps. The\n * markdown shape is the conventional \"Keep a Changelog\" layout — a top-level\n * `# Changelog` heading followed by one `## <release>` section per release.\n */\n\n/** A single released section of a CHANGELOG.md file. */\nexport interface ChangelogEntry {\n /** Stable id derived from the heading — used for \"unseen\" tracking. */\n id: string;\n /** Raw heading text, e.g. `2026-06-23` or `v1.2.0 — 2026-06-23`. */\n title: string;\n /** ISO date (YYYY-MM-DD) extracted from the heading, if present. */\n date?: string;\n /** Version label extracted from the heading, if present. */\n version?: string;\n /** Markdown body beneath the heading (until the next `## ` section). */\n body: string;\n}\n\n/** A not-yet-released entry authored as a `changelog/<file>.md` file. */\nexport interface PendingChangelogEntry {\n /** Category — `added`, `improved`, `fixed`, `changed`, etc. */\n type: ChangelogChangeType;\n /** ISO date the entry was authored (YYYY-MM-DD). */\n date?: string;\n /** User-facing description (markdown, single bullet). */\n text: string;\n}\n\nexport type ChangelogChangeType =\n | \"added\"\n | \"improved\"\n | \"fixed\"\n | \"changed\"\n | \"removed\"\n | \"security\";\n\n/**\n * Order changes are grouped under a release heading. Anything not listed here\n * falls back to the \"changed\" group, then renders in insertion order.\n */\nexport const CHANGELOG_GROUP_ORDER: ChangelogChangeType[] = [\n \"added\",\n \"improved\",\n \"fixed\",\n \"changed\",\n \"removed\",\n \"security\",\n];\n\nconst GROUP_LABELS: Record<ChangelogChangeType, string> = {\n added: \"Added\",\n improved: \"Improved\",\n fixed: \"Fixed\",\n changed: \"Changed\",\n removed: \"Removed\",\n security: \"Security\",\n};\n\nconst ISO_DATE = /(\\d{4}-\\d{2}-\\d{2})/;\n\n/** Lowercase, hyphenate, and strip to a URL/id-safe slug. */\nexport function changelogSlug(value: string): string {\n return value\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-+|-+$/g, \"\")\n .slice(0, 60);\n}\n\nfunction normalizeType(raw: string | undefined): ChangelogChangeType {\n const value = (raw ?? \"\").trim().toLowerCase();\n if ((CHANGELOG_GROUP_ORDER as string[]).includes(value)) {\n return value as ChangelogChangeType;\n }\n // Friendly aliases.\n if (value === \"feature\" || value === \"new\" || value === \"add\") return \"added\";\n if (value === \"improvement\" || value === \"enhancement\" || value === \"perf\") {\n return \"improved\";\n }\n if (value === \"fix\" || value === \"bugfix\" || value === \"bug\") return \"fixed\";\n if (value === \"remove\" || value === \"deprecated\") return \"removed\";\n return \"changed\";\n}\n\n/**\n * Parse a CHANGELOG.md document into structured release entries.\n *\n * Tolerant by design: an empty or malformed file yields an empty list rather\n * than throwing, so a missing/partial changelog never breaks the UI.\n */\nexport function parseChangelog(markdown: string): ChangelogEntry[] {\n if (!markdown || typeof markdown !== \"string\") return [];\n\n const lines = markdown.split(/\\r?\\n/);\n const entries: ChangelogEntry[] = [];\n const seenIds = new Set<string>();\n\n let currentTitle: string | null = null;\n let bodyLines: string[] = [];\n\n const flush = () => {\n if (currentTitle === null) return;\n const title = currentTitle.trim();\n const date = title.match(ISO_DATE)?.[1];\n const version = title.match(/v?\\d+\\.\\d+(?:\\.\\d+)?/)?.[0];\n // Build a stable, unique id from the heading.\n let base = changelogSlug(title) || \"entry\";\n let id = base;\n let n = 2;\n while (seenIds.has(id)) id = `${base}-${n++}`;\n seenIds.add(id);\n entries.push({\n id,\n title,\n date,\n version: version && version !== date ? version : undefined,\n body: bodyLines.join(\"\\n\").trim(),\n });\n currentTitle = null;\n bodyLines = [];\n };\n\n for (const line of lines) {\n // `## ` (but not `### `) starts a new release section.\n const match = /^##\\s+(?!#)(.+?)\\s*$/.exec(line);\n if (match) {\n flush();\n currentTitle = stripBrackets(match[1]);\n continue;\n }\n // Skip the top-level `# Changelog` title and anything before the first `##`.\n if (currentTitle === null) continue;\n bodyLines.push(line);\n }\n flush();\n\n return entries;\n}\n\n/** `## [1.2.0]` → `1.2.0`; leaves un-bracketed headings untouched. */\nfunction stripBrackets(title: string): string {\n return title.replace(/^\\[(.+?)\\]\\s*/, \"$1 \").trim();\n}\n\n/**\n * Parse a pending `changelog/<file>.md` entry: optional `---` frontmatter\n * (`type:` / `date:`) followed by the markdown description body.\n */\nexport function parsePendingEntry(content: string): PendingChangelogEntry {\n let type: string | undefined;\n let date: string | undefined;\n let body = content;\n\n const fm = /^---\\r?\\n([\\s\\S]*?)\\r?\\n---\\r?\\n?/.exec(content);\n if (fm) {\n for (const raw of fm[1].split(/\\r?\\n/)) {\n const kv = /^([a-zA-Z]+)\\s*:\\s*(.+?)\\s*$/.exec(raw);\n if (!kv) continue;\n const key = kv[1].toLowerCase();\n const value = kv[2].replace(/^[\"']|[\"']$/g, \"\").trim();\n if (key === \"type\") type = value;\n else if (key === \"date\") date = value.match(ISO_DATE)?.[1] ?? value;\n }\n body = content.slice(fm[0].length);\n }\n\n return {\n type: normalizeType(type),\n date,\n text: body.trim(),\n };\n}\n\n/**\n * Render a set of pending entries as a single dated release section (the body\n * that goes beneath a `## <date>` heading). Groups bullets by type.\n */\nexport function renderReleaseBody(entries: PendingChangelogEntry[]): string {\n const groups = new Map<ChangelogChangeType, string[]>();\n for (const entry of entries) {\n const text = entry.text.trim();\n if (!text) continue;\n const bullet = text.includes(\"\\n\")\n ? // Preserve multi-line bodies, indenting continuation lines.\n text\n .split(/\\r?\\n/)\n .map((l, i) => (i === 0 ? `- ${l}` : ` ${l}`))\n .join(\"\\n\")\n : `- ${text}`;\n const list = groups.get(entry.type) ?? [];\n list.push(bullet);\n groups.set(entry.type, list);\n }\n\n const sections: string[] = [];\n for (const type of CHANGELOG_GROUP_ORDER) {\n const list = groups.get(type);\n if (!list?.length) continue;\n sections.push(`### ${GROUP_LABELS[type]}\\n\\n${list.join(\"\\n\")}`);\n }\n return sections.join(\"\\n\\n\");\n}\n\nconst CHANGELOG_HEADER =\n \"# Changelog\\n\\n\" +\n \"All notable user-facing changes to this app are documented here.\\n\";\n\n/**\n * Roll a batch of pending entries into an existing CHANGELOG.md document,\n * prepending a new `## <date>` section above the most recent release. Returns\n * the full updated document. Pure — the CLI handles file IO and deletion.\n */\nexport function rollupChangelog(\n existing: string,\n pending: PendingChangelogEntry[],\n releaseDate: string,\n): string {\n const body = renderReleaseBody(pending);\n if (!body) return existing || `${CHANGELOG_HEADER}`;\n\n const section = `## ${releaseDate}\\n\\n${body}\\n`;\n\n const doc = (existing || CHANGELOG_HEADER).replace(/\\s+$/, \"\");\n // Insert the new section immediately before the first existing `## ` release\n // so the header/intro stays on top and releases stay newest-first.\n const firstRelease = doc.search(/^##\\s+(?!#)/m);\n if (firstRelease === -1) {\n return `${doc}\\n\\n${section}\\n`;\n }\n const head = doc.slice(0, firstRelease).replace(/\\s+$/, \"\");\n const rest = doc.slice(firstRelease);\n return `${head}\\n\\n${section}\\n${rest}\\n`;\n}\n\nexport { CHANGELOG_HEADER, GROUP_LABELS };\n"]}
1
+ {"version":3,"file":"parse.js","sourceRoot":"","sources":["../../src/changelog/parse.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Shared, dependency-free changelog parsing + serialization.\n *\n * Used by BOTH:\n * - the browser bundle (rendering an app's CHANGELOG.md in the command\n * menu / settings \"What's new\" surface), and\n * - the `agent-native changelog` CLI (rolling pending entry files up into\n * CHANGELOG.md).\n *\n * Keep this file isomorphic: no Node, no browser, no third-party deps. The\n * markdown shape is the conventional \"Keep a Changelog\" layout — a top-level\n * `# Changelog` heading followed by one `## <release>` section per release.\n */\n\n/** A single released section of a CHANGELOG.md file. */\nexport interface ChangelogEntry {\n /** Stable id derived from the heading — used for \"unseen\" tracking. */\n id: string;\n /** Raw heading text, e.g. `2026-06-23` or `v1.2.0 — 2026-06-23`. */\n title: string;\n /** ISO date (YYYY-MM-DD) extracted from the heading, if present. */\n date?: string;\n /** Version label extracted from the heading, if present. */\n version?: string;\n /** Markdown body beneath the heading (until the next `## ` section). */\n body: string;\n}\n\n/** A not-yet-released entry authored as a `changelog/<file>.md` file. */\nexport interface PendingChangelogEntry {\n /** Category — `added`, `improved`, `fixed`, `changed`, etc. */\n type: ChangelogChangeType;\n /** ISO date the entry was authored (YYYY-MM-DD). */\n date?: string;\n /** User-facing description (markdown, single bullet). */\n text: string;\n}\n\nexport type ChangelogChangeType =\n | \"added\"\n | \"improved\"\n | \"fixed\"\n | \"changed\"\n | \"removed\"\n | \"security\";\n\n/**\n * Order changes are grouped under a release heading. Anything not listed here\n * falls back to the \"changed\" group, then renders in insertion order.\n */\nexport const CHANGELOG_GROUP_ORDER: ChangelogChangeType[] = [\n \"added\",\n \"improved\",\n \"fixed\",\n \"changed\",\n \"removed\",\n \"security\",\n];\n\nconst GROUP_LABELS: Record<ChangelogChangeType, string> = {\n added: \"Added\",\n improved: \"Improved\",\n fixed: \"Fixed\",\n changed: \"Changed\",\n removed: \"Removed\",\n security: \"Security\",\n};\n\nconst ISO_DATE = /(\\d{4}-\\d{2}-\\d{2})/;\n\n/** Lowercase, hyphenate, and strip to a URL/id-safe slug. */\nexport function changelogSlug(value: string): string {\n return value\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-+|-+$/g, \"\")\n .slice(0, 60);\n}\n\nfunction normalizeType(raw: string | undefined): ChangelogChangeType {\n const value = (raw ?? \"\").trim().toLowerCase();\n if ((CHANGELOG_GROUP_ORDER as string[]).includes(value)) {\n return value as ChangelogChangeType;\n }\n // Friendly aliases.\n if (value === \"feature\" || value === \"new\" || value === \"add\") return \"added\";\n if (value === \"improvement\" || value === \"enhancement\" || value === \"perf\") {\n return \"improved\";\n }\n if (value === \"fix\" || value === \"bugfix\" || value === \"bug\") return \"fixed\";\n if (value === \"remove\" || value === \"deprecated\") return \"removed\";\n return \"changed\";\n}\n\n/**\n * Parse a CHANGELOG.md document into structured release entries.\n *\n * Tolerant by design: an empty or malformed file yields an empty list rather\n * than throwing, so a missing/partial changelog never breaks the UI.\n */\nexport function parseChangelog(markdown: string): ChangelogEntry[] {\n if (!markdown || typeof markdown !== \"string\") return [];\n\n const lines = markdown.split(/\\r?\\n/);\n const entries: ChangelogEntry[] = [];\n const seenIds = new Set<string>();\n\n let currentTitle: string | null = null;\n let bodyLines: string[] = [];\n\n const flush = () => {\n if (currentTitle === null) return;\n const title = currentTitle.trim();\n const date = title.match(ISO_DATE)?.[1];\n const version = title.match(/v?\\d+\\.\\d+(?:\\.\\d+)?/)?.[0];\n // Build a stable, unique id from the heading.\n let base = changelogSlug(title) || \"entry\";\n let id = base;\n let n = 2;\n while (seenIds.has(id)) id = `${base}-${n++}`;\n seenIds.add(id);\n entries.push({\n id,\n title,\n date,\n version: version && version !== date ? version : undefined,\n body: bodyLines.join(\"\\n\").trim(),\n });\n currentTitle = null;\n bodyLines = [];\n };\n\n for (const line of lines) {\n // `## ` (but not `### `) starts a new release section.\n const match = /^##\\s+(?!#)(.+?)\\s*$/.exec(line);\n if (match) {\n flush();\n currentTitle = stripBrackets(match[1]);\n continue;\n }\n // Skip the top-level `# Changelog` title and anything before the first `##`.\n if (currentTitle === null) continue;\n bodyLines.push(line);\n }\n flush();\n\n return entries;\n}\n\n/** `## [1.2.0]` → `1.2.0`; leaves un-bracketed headings untouched. */\nfunction stripBrackets(title: string): string {\n return title.replace(/^\\[(.+?)\\]\\s*/, \"$1 \").trim();\n}\n\n/**\n * Parse a pending `changelog/<file>.md` entry: optional `---` frontmatter\n * (`type:` / `date:`) followed by the markdown description body.\n */\nexport function parsePendingEntry(content: string): PendingChangelogEntry {\n let type: string | undefined;\n let date: string | undefined;\n let body = content;\n\n const fm = /^---\\r?\\n([\\s\\S]*?)\\r?\\n---\\r?\\n?/.exec(content);\n if (fm) {\n for (const raw of fm[1].split(/\\r?\\n/)) {\n const kv = /^([a-zA-Z]+)\\s*:\\s*(.+?)\\s*$/.exec(raw);\n if (!kv) continue;\n const key = kv[1].toLowerCase();\n const value = kv[2].replace(/^[\"']|[\"']$/g, \"\").trim();\n if (key === \"type\") type = value;\n else if (key === \"date\") date = value.match(ISO_DATE)?.[1] ?? value;\n }\n body = content.slice(fm[0].length);\n }\n\n return {\n type: normalizeType(type),\n date,\n text: body.trim(),\n };\n}\n\n/**\n * Render a set of pending entries as a single dated release section (the body\n * that goes beneath a `## <date>` heading). Groups bullets by type.\n */\nexport function renderReleaseBody(entries: PendingChangelogEntry[]): string {\n const groups = new Map<ChangelogChangeType, string[]>();\n for (const entry of entries) {\n const text = entry.text.trim();\n if (!text) continue;\n const bullet = text.includes(\"\\n\")\n ? // Preserve multi-line bodies, indenting continuation lines.\n text\n .split(/\\r?\\n/)\n .map((l, i) => (i === 0 ? `- ${l}` : ` ${l}`))\n .join(\"\\n\")\n : `- ${text}`;\n const list = groups.get(entry.type) ?? [];\n list.push(bullet);\n groups.set(entry.type, list);\n }\n\n const sections: string[] = [];\n for (const type of CHANGELOG_GROUP_ORDER) {\n const list = groups.get(type);\n if (!list?.length) continue;\n sections.push(`### ${GROUP_LABELS[type]}\\n\\n${list.join(\"\\n\")}`);\n }\n return sections.join(\"\\n\\n\");\n}\n\nconst CHANGELOG_HEADER =\n \"# Changelog\\n\\n\" +\n \"All notable user-facing changes to this app are documented here.\\n\";\n\n/**\n * Roll a batch of pending entries into an existing CHANGELOG.md document,\n * prepending a new `## <date>` section above the most recent release. Returns\n * the full updated document. Pure — the CLI handles file IO and deletion.\n */\nexport function rollupChangelog(\n existing: string,\n pending: PendingChangelogEntry[],\n releaseDate: string,\n): string {\n const body = renderReleaseBody(pending);\n if (!body) return existing || `${CHANGELOG_HEADER}`;\n\n const section = `## ${releaseDate}\\n\\n${body}\\n`;\n\n const doc = (existing || CHANGELOG_HEADER).replace(/\\s+$/, \"\");\n // Insert the new section immediately before the first existing `## ` release\n // so the header/intro stays on top and releases stay newest-first.\n const firstRelease = doc.search(/^##\\s+(?!#)/m);\n if (firstRelease === -1) {\n return `${doc}\\n\\n${section}\\n`;\n }\n const head = doc.slice(0, firstRelease).replace(/\\s+$/, \"\");\n const rest = doc.slice(firstRelease);\n return `${head}\\n\\n${section}\\n${rest}\\n`;\n}\n\nfunction changelogHeader(markdown: string): string {\n const doc = (markdown || CHANGELOG_HEADER).replace(/\\s+$/, \"\");\n const firstRelease = doc.search(/^##\\s+(?!#)/m);\n const header =\n (firstRelease === -1 ? doc : doc.slice(0, firstRelease)).replace(\n /\\s+$/,\n \"\",\n ) || CHANGELOG_HEADER.trim();\n return header;\n}\n\nfunction pendingSectionTitle(entry: PendingChangelogEntry): string {\n return entry.date?.match(ISO_DATE)?.[1] ?? \"Unreleased\";\n}\n\nfunction pendingSectionSort(a: string, b: string): number {\n const aDate = a.match(ISO_DATE)?.[1];\n const bDate = b.match(ISO_DATE)?.[1];\n if (aDate && bDate) return bDate.localeCompare(aDate);\n if (!aDate && bDate) return -1;\n if (aDate && !bDate) return 1;\n return a.localeCompare(b);\n}\n\n/**\n * Render an app-facing changelog that includes both released CHANGELOG.md\n * sections and adjacent pending `changelog/*.md` entries. Unlike `release`,\n * this is pure and non-destructive, so build/dev bundles can show current\n * product notes without deleting the conflict-free pending files.\n */\nexport function mergePendingChangelog(\n existing: string,\n pending: PendingChangelogEntry[],\n): string {\n const pendingWithText = pending.filter((entry) => entry.text.trim());\n if (pendingWithText.length === 0) return existing || CHANGELOG_HEADER;\n\n const existingEntries = parseChangelog(existing);\n const usedExistingIndexes = new Set<number>();\n const pendingByTitle = new Map<string, PendingChangelogEntry[]>();\n\n for (const entry of pendingWithText) {\n const title = pendingSectionTitle(entry);\n pendingByTitle.set(title, [...(pendingByTitle.get(title) ?? []), entry]);\n }\n\n const sections: string[] = [];\n for (const title of [...pendingByTitle.keys()].sort(pendingSectionSort)) {\n const body = renderReleaseBody(pendingByTitle.get(title) ?? []);\n if (!body) continue;\n\n const existingIndex = existingEntries.findIndex((entry, index) => {\n if (usedExistingIndexes.has(index)) return false;\n return entry.date === title || entry.title === title;\n });\n\n if (existingIndex === -1) {\n sections.push(`## ${title}\\n\\n${body}`);\n continue;\n }\n\n usedExistingIndexes.add(existingIndex);\n const existingEntry = existingEntries[existingIndex];\n sections.push(\n `## ${existingEntry.title}\\n\\n${[body, existingEntry.body]\n .filter(Boolean)\n .join(\"\\n\\n\")}`,\n );\n }\n\n existingEntries.forEach((entry, index) => {\n if (usedExistingIndexes.has(index)) return;\n sections.push(`## ${entry.title}\\n\\n${entry.body}`);\n });\n\n return `${changelogHeader(existing)}\\n\\n${sections.join(\"\\n\\n\")}\\n`;\n}\n\nexport { CHANGELOG_HEADER, GROUP_LABELS };\n"]}