@agent-native/core 0.68.3 → 0.70.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (212) hide show
  1. package/corpus/README.md +2 -2
  2. package/corpus/core/CHANGELOG.md +54 -0
  3. package/corpus/core/package.json +1 -1
  4. package/corpus/core/src/changelog/parse.ts +245 -0
  5. package/corpus/core/src/cli/changelog.ts +199 -0
  6. package/corpus/core/src/cli/index.ts +19 -0
  7. package/corpus/core/src/cli/recap.ts +24 -1
  8. package/corpus/core/src/cli/skills.ts +72 -45
  9. package/corpus/core/src/client/CommandMenu.tsx +183 -75
  10. package/corpus/core/src/client/agent-chat-adapter.ts +44 -7
  11. package/corpus/core/src/client/analytics.ts +181 -0
  12. package/corpus/core/src/client/changelog/Changelog.tsx +321 -0
  13. package/corpus/core/src/client/index.ts +11 -0
  14. package/corpus/core/src/client/mcp-apps/McpAppRenderer.tsx +54 -0
  15. package/corpus/core/src/client/settings/useBuilderStatus.ts +82 -20
  16. package/corpus/core/src/extensions/web-search-tool.ts +45 -4
  17. package/corpus/core/src/mcp/build-server.ts +1 -1
  18. package/corpus/core/src/mcp/embed-app.ts +112 -6
  19. package/corpus/core/src/secrets/register-framework-secrets.ts +7 -0
  20. package/corpus/core/src/server/attribution.ts +211 -0
  21. package/corpus/core/src/server/auth.ts +6 -0
  22. package/corpus/core/src/server/better-auth-instance.ts +49 -5
  23. package/corpus/core/src/server/builder-browser.ts +27 -1
  24. package/corpus/core/src/server/core-routes-plugin.ts +58 -0
  25. package/corpus/core/src/server/google-oauth.ts +19 -6
  26. package/corpus/core/src/shared/mcp-embed-headers.ts +1 -1
  27. package/corpus/core/src/styles/agent-conversation.css +21 -0
  28. package/corpus/core/src/templates/workspace-core/.agents/skills/changelog/SKILL.md +111 -0
  29. package/corpus/core/src/templates/workspace-core/.agents/skills/tracking/SKILL.md +46 -14
  30. package/corpus/templates/analytics/CHANGELOG.md +10 -0
  31. package/corpus/templates/analytics/actions/install-dashboard-template.ts +2 -2
  32. package/corpus/templates/analytics/actions/open-traffic-dashboard.ts +1 -1
  33. package/corpus/templates/analytics/actions/update-dashboard.ts +5 -3
  34. package/corpus/templates/analytics/app/components/layout/CommandPalette.tsx +180 -144
  35. package/corpus/templates/analytics/app/components/layout/Header.tsx +2 -2
  36. package/corpus/templates/analytics/app/components/layout/Layout.tsx +7 -5
  37. package/corpus/templates/analytics/app/components/layout/Sidebar.tsx +221 -213
  38. package/corpus/templates/analytics/app/hooks/use-navigation-state.ts +6 -3
  39. package/corpus/templates/analytics/app/lib/demo-dashboard-path.ts +1 -1
  40. package/corpus/templates/analytics/app/lib/last-opened.ts +2 -1
  41. package/corpus/templates/analytics/app/pages/Settings.tsx +4 -0
  42. package/corpus/templates/analytics/app/pages/adhoc/explorer-dashboard/index.tsx +3 -3
  43. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/DashboardFilterBar.tsx +2 -2
  44. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/index.tsx +101 -99
  45. package/corpus/templates/analytics/app/pages/overview/OverviewPage.tsx +1 -1
  46. package/corpus/templates/analytics/app/routes/adhoc.$id.tsx +18 -5
  47. package/corpus/templates/analytics/app/routes/catalog.tsx +1 -1
  48. package/corpus/templates/analytics/app/routes/dashboards.$id.tsx +9 -0
  49. package/corpus/templates/analytics/app/routes/traffic.tsx +1 -1
  50. package/corpus/templates/analytics/changelog/2026-06-23-the-dashboards-and-analyses-sidebar-settings-buttons-now-sta.md +6 -0
  51. package/corpus/templates/analytics/seeds/dashboards/agent-native-templates-first-party.json +145 -0
  52. package/corpus/templates/analytics/server/db/index.ts +1 -1
  53. package/corpus/templates/analytics/server/lib/dashboard-catalog.ts +9 -2
  54. package/corpus/templates/analytics/server/lib/demo-dashboards.ts +1 -1
  55. package/corpus/templates/analytics/server/plugins/agent-chat.ts +2 -2
  56. package/corpus/templates/analytics/server/plugins/core-routes.ts +6 -6
  57. package/corpus/templates/assets/CHANGELOG.md +10 -0
  58. package/corpus/templates/assets/app/root.tsx +7 -1
  59. package/corpus/templates/assets/app/routes/settings.tsx +6 -0
  60. package/corpus/templates/brain/CHANGELOG.md +10 -0
  61. package/corpus/templates/brain/app/root.tsx +7 -1
  62. package/corpus/templates/brain/app/routes/settings.tsx +8 -1
  63. package/corpus/templates/calendar/CHANGELOG.md +10 -0
  64. package/corpus/templates/calendar/app/pages/Settings.tsx +4 -0
  65. package/corpus/templates/calendar/app/root.tsx +7 -1
  66. package/corpus/templates/chat/CHANGELOG.md +10 -0
  67. package/corpus/templates/chat/app/root.tsx +7 -1
  68. package/corpus/templates/clips/CHANGELOG.md +10 -0
  69. package/corpus/templates/clips/app/components/player/share-dialog.tsx +33 -7
  70. package/corpus/templates/clips/app/components/player/sign-in-prompt-dialog.tsx +8 -0
  71. package/corpus/templates/clips/app/components/player/video-player.tsx +150 -20
  72. package/corpus/templates/clips/app/components/recorder/pre-record-panel.tsx +72 -20
  73. package/corpus/templates/clips/app/components/recorder/recorder-engine.ts +69 -2
  74. package/corpus/templates/clips/app/components/sharing/slack-share-hint.tsx +71 -0
  75. package/corpus/templates/clips/app/lib/recorder-preferences.ts +67 -0
  76. package/corpus/templates/clips/app/root.tsx +7 -1
  77. package/corpus/templates/clips/app/routes/_app.settings._index.tsx +15 -1
  78. package/corpus/templates/clips/app/routes/_app.trash.tsx +21 -0
  79. package/corpus/templates/clips/app/routes/record.tsx +92 -8
  80. package/corpus/templates/clips/app/routes/share.$shareId.tsx +86 -5
  81. package/corpus/templates/clips/changelog/2026-06-23-clips-shared-in-slack-no-longer-show-a-could-not-start-playb.md +6 -0
  82. package/corpus/templates/clips/changelog/2026-06-23-made-the-play-button-on-shared-and-embedded-clips-scale-with.md +6 -0
  83. package/corpus/templates/clips/changelog/2026-06-23-public-clip-share-links-now-show-whether-they-ll-play-inline.md +6 -0
  84. package/corpus/templates/clips/changelog/2026-06-23-screen-camera-recordings-now-keep-the-presenter-s-face-in-th.md +6 -0
  85. package/corpus/templates/clips/desktop/src/lib/recorder.ts +20 -0
  86. package/corpus/templates/clips/desktop/src/main.tsx +3 -0
  87. package/corpus/templates/clips/desktop/src/overlays/region-record-border.tsx +76 -0
  88. package/corpus/templates/clips/desktop/src/styles.css +49 -0
  89. package/corpus/templates/clips/desktop/src-tauri/capabilities/default.json +2 -1
  90. package/corpus/templates/clips/desktop/src-tauri/src/clips/mod.rs +67 -1
  91. package/corpus/templates/clips/desktop/src-tauri/src/lib.rs +2 -0
  92. package/corpus/templates/clips/desktop/src-tauri/src/util.rs +4 -1
  93. package/corpus/templates/clips/server/routes/api/video/[recordingId].get.ts +51 -1
  94. package/corpus/templates/clips/shared/share-attribution.ts +79 -0
  95. package/corpus/templates/content/CHANGELOG.md +10 -0
  96. package/corpus/templates/content/app/root.tsx +7 -1
  97. package/corpus/templates/content/vitest.config.ts +3 -0
  98. package/corpus/templates/design/CHANGELOG.md +10 -0
  99. package/corpus/templates/design/actions/generate-design.ts +4 -0
  100. package/corpus/templates/design/app/root.tsx +7 -1
  101. package/corpus/templates/design/app/routes/settings.tsx +10 -2
  102. package/corpus/templates/dispatch/CHANGELOG.md +10 -0
  103. package/corpus/templates/dispatch/app/root.tsx +7 -1
  104. package/corpus/templates/forms/CHANGELOG.md +10 -0
  105. package/corpus/templates/forms/app/root.tsx +7 -1
  106. package/corpus/templates/macros/CHANGELOG.md +10 -0
  107. package/corpus/templates/macros/app/root.tsx +7 -1
  108. package/corpus/templates/mail/CHANGELOG.md +10 -0
  109. package/corpus/templates/mail/app/components/layout/CommandPalette.tsx +3 -0
  110. package/corpus/templates/mail/app/pages/SettingsPage.tsx +27 -0
  111. package/corpus/templates/plan/.agents/skills/visual-plan/SKILL.md +31 -17
  112. package/corpus/templates/plan/.agents/skills/visual-plan/references/wireframe.md +7 -4
  113. package/corpus/templates/plan/.agents/skills/visual-recap/SKILL.md +34 -24
  114. package/corpus/templates/plan/.agents/skills/visual-recap/references/wireframe.md +7 -4
  115. package/corpus/templates/plan/AGENTS.md +4 -0
  116. package/corpus/templates/plan/CHANGELOG.md +10 -0
  117. package/corpus/templates/plan/actions/view-screen.ts +5 -0
  118. package/corpus/templates/plan/app/components/layout/Sidebar.tsx +98 -1
  119. package/corpus/templates/plan/app/pages/PlansPage.tsx +107 -7
  120. package/corpus/templates/plan/app/root.tsx +7 -1
  121. package/corpus/templates/plan/shared/share-attribution.ts +72 -0
  122. package/corpus/templates/slides/CHANGELOG.md +10 -0
  123. package/corpus/templates/slides/app/root.tsx +7 -1
  124. package/corpus/templates/videos/CHANGELOG.md +4 -151
  125. package/corpus/templates/videos/app/root.tsx +7 -1
  126. package/dist/changelog/parse.d.ts +70 -0
  127. package/dist/changelog/parse.d.ts.map +1 -0
  128. package/dist/changelog/parse.js +200 -0
  129. package/dist/changelog/parse.js.map +1 -0
  130. package/dist/cli/changelog.d.ts +4 -0
  131. package/dist/cli/changelog.d.ts.map +1 -0
  132. package/dist/cli/changelog.js +166 -0
  133. package/dist/cli/changelog.js.map +1 -0
  134. package/dist/cli/index.js +18 -0
  135. package/dist/cli/index.js.map +1 -1
  136. package/dist/cli/recap.d.ts.map +1 -1
  137. package/dist/cli/recap.js +22 -1
  138. package/dist/cli/recap.js.map +1 -1
  139. package/dist/cli/skills.d.ts +3 -3
  140. package/dist/cli/skills.d.ts.map +1 -1
  141. package/dist/cli/skills.js +72 -45
  142. package/dist/cli/skills.js.map +1 -1
  143. package/dist/client/CommandMenu.d.ts +17 -1
  144. package/dist/client/CommandMenu.d.ts.map +1 -1
  145. package/dist/client/CommandMenu.js +49 -13
  146. package/dist/client/CommandMenu.js.map +1 -1
  147. package/dist/client/agent-chat-adapter.d.ts.map +1 -1
  148. package/dist/client/agent-chat-adapter.js +43 -6
  149. package/dist/client/agent-chat-adapter.js.map +1 -1
  150. package/dist/client/analytics.d.ts +18 -0
  151. package/dist/client/analytics.d.ts.map +1 -1
  152. package/dist/client/analytics.js +177 -0
  153. package/dist/client/analytics.js.map +1 -1
  154. package/dist/client/changelog/Changelog.d.ts +47 -0
  155. package/dist/client/changelog/Changelog.d.ts.map +1 -0
  156. package/dist/client/changelog/Changelog.js +138 -0
  157. package/dist/client/changelog/Changelog.js.map +1 -0
  158. package/dist/client/index.d.ts +2 -1
  159. package/dist/client/index.d.ts.map +1 -1
  160. package/dist/client/index.js +2 -1
  161. package/dist/client/index.js.map +1 -1
  162. package/dist/client/mcp-apps/McpAppRenderer.d.ts +1 -0
  163. package/dist/client/mcp-apps/McpAppRenderer.d.ts.map +1 -1
  164. package/dist/client/mcp-apps/McpAppRenderer.js +42 -1
  165. package/dist/client/mcp-apps/McpAppRenderer.js.map +1 -1
  166. package/dist/client/settings/useBuilderStatus.d.ts +2 -0
  167. package/dist/client/settings/useBuilderStatus.d.ts.map +1 -1
  168. package/dist/client/settings/useBuilderStatus.js +58 -10
  169. package/dist/client/settings/useBuilderStatus.js.map +1 -1
  170. package/dist/extensions/web-search-tool.d.ts +5 -3
  171. package/dist/extensions/web-search-tool.d.ts.map +1 -1
  172. package/dist/extensions/web-search-tool.js +36 -4
  173. package/dist/extensions/web-search-tool.js.map +1 -1
  174. package/dist/mcp/build-server.js +1 -1
  175. package/dist/mcp/build-server.js.map +1 -1
  176. package/dist/mcp/embed-app.d.ts.map +1 -1
  177. package/dist/mcp/embed-app.js +112 -6
  178. package/dist/mcp/embed-app.js.map +1 -1
  179. package/dist/secrets/register-framework-secrets.d.ts.map +1 -1
  180. package/dist/secrets/register-framework-secrets.js +6 -0
  181. package/dist/secrets/register-framework-secrets.js.map +1 -1
  182. package/dist/server/attribution.d.ts +83 -0
  183. package/dist/server/attribution.d.ts.map +1 -0
  184. package/dist/server/attribution.js +178 -0
  185. package/dist/server/attribution.js.map +1 -0
  186. package/dist/server/auth.d.ts.map +1 -1
  187. package/dist/server/auth.js +7 -0
  188. package/dist/server/auth.js.map +1 -1
  189. package/dist/server/better-auth-instance.d.ts +9 -1
  190. package/dist/server/better-auth-instance.d.ts.map +1 -1
  191. package/dist/server/better-auth-instance.js +32 -2
  192. package/dist/server/better-auth-instance.js.map +1 -1
  193. package/dist/server/builder-browser.d.ts +4 -0
  194. package/dist/server/builder-browser.d.ts.map +1 -1
  195. package/dist/server/builder-browser.js +20 -1
  196. package/dist/server/builder-browser.js.map +1 -1
  197. package/dist/server/core-routes-plugin.d.ts +25 -0
  198. package/dist/server/core-routes-plugin.d.ts.map +1 -1
  199. package/dist/server/core-routes-plugin.js +38 -0
  200. package/dist/server/core-routes-plugin.js.map +1 -1
  201. package/dist/server/google-oauth.d.ts.map +1 -1
  202. package/dist/server/google-oauth.js +16 -2
  203. package/dist/server/google-oauth.js.map +1 -1
  204. package/dist/shared/mcp-embed-headers.js +1 -1
  205. package/dist/shared/mcp-embed-headers.js.map +1 -1
  206. package/dist/styles/agent-conversation.css +21 -0
  207. package/dist/templates/workspace-core/.agents/skills/changelog/SKILL.md +111 -0
  208. package/dist/templates/workspace-core/.agents/skills/tracking/SKILL.md +46 -14
  209. package/package.json +1 -1
  210. package/src/templates/workspace-core/.agents/skills/changelog/SKILL.md +111 -0
  211. package/src/templates/workspace-core/.agents/skills/tracking/SKILL.md +46 -14
  212. /package/corpus/templates/analytics/app/routes/{dashboards.tsx → dashboards._index.tsx} +0 -0
@@ -68,6 +68,7 @@ import {
68
68
  useAgentEngineConfigured,
69
69
  useActionQuery,
70
70
  useSession,
71
+ track,
71
72
  emailToColor,
72
73
  emailToName,
73
74
  type AgentSidebarStateChangeDetail,
@@ -219,6 +220,11 @@ import {
219
220
  type PlanVersionDetail,
220
221
  type PlanVersionSummary,
221
222
  } from "@shared/types";
223
+ import {
224
+ PLAN_SHARE_SURFACE,
225
+ readPlanShareAttribution,
226
+ withPlanShareAttribution,
227
+ } from "@shared/share-attribution";
222
228
  import {
223
229
  diffPlanVersions,
224
230
  formatVersionDiffSummary,
@@ -3783,13 +3789,92 @@ export function PlansPage({ localPlanSlug }: { localPlanSlug?: string } = {}) {
3783
3789
  }
3784
3790
  if (!selectedId) return undefined;
3785
3791
  const base = bundle?.plan.kind === "recap" ? "recaps" : "plans";
3786
- return `${window.location.origin}${appPath(`/${base}/${selectedId}`)}`;
3792
+ const url = `${window.location.origin}${appPath(`/${base}/${selectedId}`)}`;
3793
+ // Viral attribution: tag the shared/public plan link so signups arriving
3794
+ // from it can be attributed even when `document.referrer` is empty. `via`
3795
+ // is a non-PII owner id and is only set when the current viewer is the
3796
+ // owner (the only person whose session userId is the plan owner's id).
3797
+ const ownerViaId =
3798
+ effectivePlanAccessRole === "owner" ? (session?.userId ?? null) : null;
3799
+ return withPlanShareAttribution(url, ownerViaId);
3787
3800
  }, [
3788
3801
  bundle?.plan.kind,
3802
+ effectivePlanAccessRole,
3789
3803
  localPlanMode,
3790
3804
  localPlanRepoPath,
3791
3805
  localPlanSlug,
3792
3806
  selectedId,
3807
+ session?.userId,
3808
+ ]);
3809
+
3810
+ // Viral attribution: read the `ref`/`via` the visitor arrived on (from a
3811
+ // tagged share link) so funnel events carry the same attribution the
3812
+ // framework first-touch cookie captured. Read once from the URL on mount.
3813
+ const shareAttribution = useMemo(
3814
+ () =>
3815
+ readPlanShareAttribution(
3816
+ typeof window === "undefined" ? "" : window.location.search,
3817
+ ),
3818
+ [],
3819
+ );
3820
+
3821
+ // A logged-out visitor looking at a public plan/recap is the share funnel
3822
+ // audience. Their CTAs (comment, sign in) route through `openSignIn`.
3823
+ const isLoggedOutPublicPlanView =
3824
+ !sessionLoading &&
3825
+ !session &&
3826
+ !localPlanMode &&
3827
+ Boolean(selectedId) &&
3828
+ effectivePlanVisibility === "public";
3829
+
3830
+ // share_cta_click — fire alongside (never instead of) the real navigation.
3831
+ // `track` is non-throwing, but guard anyway so analytics can never break a
3832
+ // CTA. Only fires for the logged-out public-plan funnel audience.
3833
+ const fireShareCtaClick = useCallback(
3834
+ (cta: string) => {
3835
+ if (!isLoggedOutPublicPlanView) return;
3836
+ try {
3837
+ void track("share_cta_click", {
3838
+ surface: PLAN_SHARE_SURFACE,
3839
+ plan_id: selectedId ?? "",
3840
+ cta,
3841
+ ref: shareAttribution.ref,
3842
+ via: shareAttribution.via,
3843
+ });
3844
+ } catch {
3845
+ // Never let analytics break a CTA.
3846
+ }
3847
+ },
3848
+ [
3849
+ isLoggedOutPublicPlanView,
3850
+ selectedId,
3851
+ shareAttribution.ref,
3852
+ shareAttribution.via,
3853
+ ],
3854
+ );
3855
+
3856
+ // share_view — fire once when a logged-out visitor views a public plan. The
3857
+ // ref guard prevents double-fire across re-renders / StrictMode double-invoke.
3858
+ const shareViewFiredRef = useRef(false);
3859
+ useEffect(() => {
3860
+ if (!isLoggedOutPublicPlanView) return;
3861
+ if (shareViewFiredRef.current) return;
3862
+ shareViewFiredRef.current = true;
3863
+ try {
3864
+ void track("share_view", {
3865
+ surface: PLAN_SHARE_SURFACE,
3866
+ plan_id: selectedId ?? "",
3867
+ ref: shareAttribution.ref,
3868
+ via: shareAttribution.via,
3869
+ });
3870
+ } catch {
3871
+ // Never let analytics break the page render.
3872
+ }
3873
+ }, [
3874
+ isLoggedOutPublicPlanView,
3875
+ selectedId,
3876
+ shareAttribution.ref,
3877
+ shareAttribution.via,
3793
3878
  ]);
3794
3879
 
3795
3880
  useEffect(() => {
@@ -6227,11 +6312,14 @@ export function PlansPage({ localPlanSlug }: { localPlanSlug?: string } = {}) {
6227
6312
  {!session ? (
6228
6313
  <GuestCommentCta
6229
6314
  position={inlineCommentPosition}
6230
- onSignIn={() =>
6315
+ onSignIn={() => {
6316
+ // share funnel: logged-out viewer of a public plan
6317
+ // clicking the "create account to comment" CTA.
6318
+ fireShareCtaClick("comment_signin");
6231
6319
  openSignIn(
6232
6320
  window.location.pathname + window.location.search,
6233
- )
6234
- }
6321
+ );
6322
+ }}
6235
6323
  onCancel={closeInlineComment}
6236
6324
  />
6237
6325
  ) : (
@@ -6669,9 +6757,12 @@ function PlanShareControl({
6669
6757
  effectivePublishedUrl && hostedPlanOnCurrentOrigin && effectiveHostedPlanId
6670
6758
  ? effectiveHostedPlanId
6671
6759
  : planId;
6760
+ // Viral attribution: the owner is the one publishing/managing the share here,
6761
+ // so `via` is their non-PII session userId. `localShareUrl` is already tagged
6762
+ // upstream; tag the hosted/public URL too so both paths self-attribute.
6672
6763
  const managedShareUrl =
6673
6764
  effectivePublishedUrl && hostedPlanOnCurrentOrigin
6674
- ? effectivePublishedUrl
6765
+ ? withPlanShareAttribution(effectivePublishedUrl, session?.userId ?? null)
6675
6766
  : localShareUrl;
6676
6767
 
6677
6768
  useEffect(() => {
@@ -6713,11 +6804,20 @@ function PlanShareControl({
6713
6804
  hostedPlanId: result.hostedPlanId,
6714
6805
  });
6715
6806
  setAuthPrompt(null);
6716
- copyPublishedUrl(result.hostedPlanUrl ?? result.url);
6807
+ // Tag the freshly-minted public link so signups from it are
6808
+ // attributed. The publisher is the owner, so `via` is their userId.
6809
+ copyPublishedUrl(
6810
+ withPlanShareAttribution(
6811
+ result.hostedPlanUrl ?? result.url,
6812
+ session?.userId ?? null,
6813
+ ) ??
6814
+ result.hostedPlanUrl ??
6815
+ result.url,
6816
+ );
6717
6817
  },
6718
6818
  },
6719
6819
  );
6720
- }, [copyPublishedUrl, planId, publishPlan]);
6820
+ }, [copyPublishedUrl, planId, publishPlan, session?.userId]);
6721
6821
 
6722
6822
  // Logged-in / local-dev: manage shares for the plan in this app instance.
6723
6823
  if (canManageLocalShares) {
@@ -22,6 +22,7 @@ import {
22
22
  } from "@agent-native/core/client";
23
23
  import { IconSun, IconMoon } from "@tabler/icons-react";
24
24
  import { useTheme } from "next-themes";
25
+ import changelog from "../CHANGELOG.md?raw";
25
26
  import { Toaster } from "@/components/ui/sonner";
26
27
  import { Layout as AppLayout } from "@/components/layout/Layout";
27
28
  import { TAB_ID } from "@/lib/tab-id";
@@ -106,7 +107,12 @@ function AppContent() {
106
107
  );
107
108
  return (
108
109
  <>
109
- <CommandMenu open={cmdkOpen} onOpenChange={setCmdkOpen}>
110
+ <CommandMenu
111
+ open={cmdkOpen}
112
+ onOpenChange={setCmdkOpen}
113
+ changelog={changelog}
114
+ changelogKey="plan"
115
+ >
110
116
  <CommandMenu.Group heading="Actions">
111
117
  <CommandMenu.Item onSelect={() => go("/")}>Ask Plan</CommandMenu.Item>
112
118
  <CommandMenu.Item onSelect={() => go("/plans")}>
@@ -0,0 +1,72 @@
1
+ /**
2
+ * Viral attribution contract for shared/public Plan links.
3
+ *
4
+ * Public plan/recap URLs self-attribute so the signup funnel can be measured
5
+ * even when `document.referrer` is empty (desktop app, Slack, native clients,
6
+ * etc.). The framework captures first-touch from these params into a cookie and
7
+ * enriches the `signup` event; Plan's job is to (a) tag the share/public URLs it
8
+ * mints and (b) emit funnel events when a logged-out visitor views a public plan
9
+ * and clicks a sign-up CTA.
10
+ *
11
+ * Contract strings are centralized here so the minting side (share popover /
12
+ * copy-link) and the measuring side (public plan view) cannot drift apart. The
13
+ * framework also derives `plan_share` from public plan paths (`/p/`, `/plan/`,
14
+ * `/plans/`, `/recaps/`, `/share-plan/`) as a fallback when the param is lost.
15
+ *
16
+ * Privacy: `via` must be a non-PII stable id (the owner's user id), never an
17
+ * email. Omit `via` rather than leak PII into a public URL or event.
18
+ */
19
+
20
+ /** Fixed referral source for plan shares. */
21
+ export const PLAN_SHARE_REF = "plan_share";
22
+
23
+ /** Surface tag included on plan share funnel events. */
24
+ export const PLAN_SHARE_SURFACE = "plan";
25
+
26
+ /** Query param names that carry attribution. */
27
+ export const REF_PARAM = "ref";
28
+ export const VIA_PARAM = "via";
29
+
30
+ /**
31
+ * Append `ref=plan_share` (and `via=<ownerId>` when a non-PII owner id is known)
32
+ * to an absolute share/public plan URL, preserving any existing query params.
33
+ * Returns the input unchanged when it isn't a parseable absolute URL.
34
+ */
35
+ export function withPlanShareAttribution(
36
+ url: string | undefined,
37
+ ownerId?: string | null,
38
+ ): string | undefined {
39
+ if (!url) return url;
40
+ try {
41
+ const parsed = new URL(url);
42
+ parsed.searchParams.set(REF_PARAM, PLAN_SHARE_REF);
43
+ const owner = (ownerId ?? "").trim();
44
+ if (owner) parsed.searchParams.set(VIA_PARAM, owner);
45
+ return parsed.toString();
46
+ } catch {
47
+ return url;
48
+ }
49
+ }
50
+
51
+ export type ShareAttribution = {
52
+ ref: string | undefined;
53
+ via: string | undefined;
54
+ };
55
+
56
+ /**
57
+ * Read `ref`/`via` from a query string (e.g. `window.location.search`). Falls
58
+ * back to `ref=plan_share` so downstream attribution stays meaningful even when
59
+ * the visitor arrived via a link that lost the param. Never throws.
60
+ */
61
+ export function readPlanShareAttribution(search: string): ShareAttribution {
62
+ let ref: string | undefined;
63
+ let via: string | undefined;
64
+ try {
65
+ const params = new URLSearchParams(search ?? "");
66
+ ref = params.get(REF_PARAM) ?? undefined;
67
+ via = params.get(VIA_PARAM) ?? undefined;
68
+ } catch {
69
+ // Ignore malformed query strings — fall through to the default below.
70
+ }
71
+ return { ref: ref || PLAN_SHARE_REF, via: via || undefined };
72
+ }
@@ -0,0 +1,10 @@
1
+ # Changelog
2
+
3
+ All notable user-facing changes to Agent-Native Slides are documented here. Open it any
4
+ time from the command menu (Cmd+K → "What's new").
5
+
6
+ ## 2026-06-23
7
+
8
+ ### Added
9
+
10
+ - See what's new right inside Agent-Native Slides — a changelog now lives in the command menu (Cmd+K).
@@ -28,6 +28,7 @@ import { useQueryClient } from "@tanstack/react-query";
28
28
  import type { LinksFunction } from "react-router";
29
29
  import stylesheet from "./global.css?url";
30
30
  import { configureTracking } from "@agent-native/core/client";
31
+ import changelog from "../CHANGELOG.md?raw";
31
32
  import { getThemeInitScript } from "@agent-native/core/client";
32
33
  import { TAB_ID } from "@/lib/tab-id";
33
34
  configureTracking({
@@ -162,7 +163,12 @@ function AppContent() {
162
163
 
163
164
  return (
164
165
  <>
165
- <CommandMenu open={cmdkOpen} onOpenChange={setCmdkOpen}>
166
+ <CommandMenu
167
+ open={cmdkOpen}
168
+ onOpenChange={setCmdkOpen}
169
+ changelog={changelog}
170
+ changelogKey="slides"
171
+ >
166
172
  <CommandMenu.Group heading="Presentations">
167
173
  <CommandMenu.Item onSelect={() => {}}>Search decks</CommandMenu.Item>
168
174
  </CommandMenu.Group>
@@ -1,157 +1,10 @@
1
1
  # Changelog
2
2
 
3
- ## [Unreleased] - 2026-02-28
3
+ All notable user-facing changes to Agent-Native Videos are documented here. Open it any
4
+ time from the command menu (Cmd+K → "What's new").
4
5
 
5
- ### Architecture Improvements ✨
6
-
7
- - **Extracted Animation Logic to Reusable Pure Function**
8
- - Created `app/remotion/animations/useElementAnimations.ts` (202 lines)
9
- - Exported `calculateElementAnimations()` - pure function (not hook)
10
- - Removed 130 lines of animation logic from InteractiveCardGrid
11
- - Centralized all animation calculations in testable function
12
- - Can be called inside loops (no Rules of Hooks violations)
13
- - Other compositions can now reuse animation system instantly
14
- - Reduced InteractiveCardGrid from 400+ to 320 lines
15
- - Simpler and faster than hook-based approach
16
-
17
- - **Centralized Configuration Constants**
18
- - Created `app/config/constants.ts` (204 lines)
19
- - Eliminated all magic numbers across codebase
20
- - Organized by domain: ANIMATION_CONFIG, CURSOR_CONFIG, CARD_CONFIG, UI_CONFIG, etc.
21
- - Type-safe with `as const`
22
- - Well-documented with inline comments
23
-
24
- - **Code Quality Improvements**
25
- - Max function length: 87 lines → 42 lines
26
- - Animation logic now testable in isolation
27
- - Proper type guards with centralized validation
28
- - Cleaner separation of concerns
29
-
30
- **Impact**: Architecture grade improved from C+ to A-
6
+ ## 2026-06-23
31
7
 
32
8
  ### Added
33
9
 
34
- - **Color Animation Support**: Background and border color properties for cursor interactions
35
- - Added `backgroundColor` and `borderColor` to animation property options
36
- - Implemented color interpolation function for smooth color transitions
37
- - Color picker UI with native browser color input
38
- - Colors animate from each element's base color to target color (preserves multicolor designs)
39
-
40
- - **Click Animation Return-to-Hover**: Click animations now properly animate back
41
- - Implemented "there-and-back" animation (0→1→0 progress mapping)
42
- - Doubles animation duration to accommodate forward and return transitions
43
- - Smooth easing applied to both directions
44
-
45
- - **Timeline Visual Enhancements**
46
- - Changed cursor keyframe click indicator dot from grey/white to yellow (#facc15)
47
- - Improved visual distinction for click events in timeline
48
-
49
- ### Changed
50
-
51
- - **Playback Speed System**: Simplified from adaptive to manual control
52
- - Removed adaptive playback rate compensation based on FPS measurement
53
- - Added manual playback speed dropdown (0.25× to 2×)
54
- - Moved speed selector to VideoPlayer bottom controls (next to Frame counter)
55
- - Removed playback speed from Timeline component
56
-
57
- - **Composition Creation Workflow**: Restored AI-powered generation
58
- - Rewrote `NewCompositionPopover` with full agent chat integration
59
- - Added file attachment support (images, videos, SVGs via data URLs)
60
- - Implemented postMessage API for parent window communication
61
- - Added event listener for `builder.agentChat.chatRunning` completion detection
62
- - Slug-based URL generation with conflict resolution (`/c/comp-title`, `/c/comp-title-2`)
63
- - Navigate to `/c/new` on submission for AI generation
64
-
65
- - **Properties Panel Improvements**
66
- - Removed composition name input from Properties > Properties section (non-editable)
67
- - Hidden "x" unit label to avoid confusion with delete button (kept "px", "deg", etc.)
68
- - Moved "Add Property" section above property list (below Motion Curve)
69
- - Swapped + button to left side of dropdown
70
- - Added Enter key support to add properties from dropdown
71
- - Changed focus ring color to red-400 for consistency
72
- - Removed hex code display next to color picker (visible in native picker)
73
-
74
- - **Animation System Architecture**
75
- - Updated `AnimationKeyframe.value` type to support `number | string` for colors
76
- - Color animations only apply when `hoverProgress > 0` or `clickProgress > 0`
77
- - Each element's base color extracted and used as animation starting point
78
- - Hover and click animations support mixed numeric and color properties
79
-
80
- ### Fixed
81
-
82
- - Browser cache issues causing stale code errors
83
- - Fixed `ReferenceError: adaptivePlaybackRate is not defined`
84
- - Fixed `ReferenceError: onCreateComposition is not defined`
85
- - Solution: Dev server restart to clear Vite cache
86
-
87
- - Color animation not preserving element colors
88
- - Cards were all turning blue when backgroundColor animation added
89
- - Fixed by interpolating from each card's unique base color instead of fixed start color
90
- - Only applies color animations during active hover/click (preserves idle state)
91
-
92
- - Click animations jumping back to hover state
93
- - Animations were not tweening back, causing abrupt transitions
94
- - Implemented smooth 0→1→0 progress curve with doubled duration
95
-
96
- ### Technical Details
97
-
98
- #### Color Interpolation Implementation
99
-
100
- ```typescript
101
- // New function in elementAnimations.ts
102
- export function interpolateColor(
103
- color1: string,
104
- color2: string,
105
- progress: number,
106
- ): string;
107
- ```
108
-
109
- - Parses hex colors to RGB components
110
- - Linear interpolation per channel
111
- - Returns hex color string
112
-
113
- #### Animation Progress Mapping
114
-
115
- ```typescript
116
- // Click animation: 0→1→0 curve
117
- const rawProgress = framesSinceClick / clickDuration; // 0→2
118
- clickProgress = rawProgress <= 1 ? rawProgress : 2 - rawProgress; // 0→1→0
119
- ```
120
-
121
- #### Files Modified
122
-
123
- - `app/components/VideoPlayer.tsx` - Simplified playback rate
124
- - `app/components/Timeline.tsx` - Removed playback UI, changed dot color
125
- - `app/pages/CompositionView.tsx` - Playback rate state management
126
- - `app/components/NewCompositionPopover.tsx` - Complete rewrite for agent chat integration
127
- - `app/components/Sidebar.tsx` - Updated props, removed name input
128
- - `app/components/PropsEditor.tsx` - Removed composition name field
129
- - `app/components/CurrentElementPanel.tsx` - Color properties, UI improvements
130
- - `app/types/elementAnimations.ts` - Color support, interpolation
131
- - `app/remotion/compositions/InteractiveCardGrid.tsx` - Color animation logic
132
-
133
- #### Files Created
134
-
135
- - `app/remotion/animations/useElementAnimations.ts` (209 lines) - **Reusable animation hook**
136
- - `app/config/constants.ts` (204 lines) - **Centralized configuration**
137
- - `app/utils/compositionHelpers.ts` (378 lines) - Helper functions library
138
- - `app/utils/debug.ts` (104 lines) - Production-safe logging utility
139
- - `scripts/create-composition.ts` (127 lines) - Example composition script
140
- - `COMPOSITION_GUIDE.md` (787 lines) - Comprehensive API reference
141
- - `QUICK_START.md` (498 lines) - Beginner-friendly guide
142
- - `README.md` (209 lines) - Project overview
143
- - `CHANGELOG.md`, `CODE_REVIEW.md`, `TODO.md`, `PR_DESCRIPTION.md`, `SESSION_SUMMARY.md`
144
-
145
- ### Developer Experience
146
-
147
- - Native `<select>` supports type-to-search for properties
148
- - Arrow keys navigate property options
149
- - Enter key adds selected property
150
- - Color picker shows hex values natively
151
- - Improved visual hierarchy in properties panel
152
-
153
- ---
154
-
155
- ## Notes
156
-
157
- All changes maintain backward compatibility with existing compositions. Color animation feature is additive and optional.
10
+ - See what's new right inside Agent-Native Videos a changelog now lives in the command menu (Cmd+K).
@@ -20,6 +20,7 @@ import {
20
20
  configureTracking,
21
21
  getThemeInitScript,
22
22
  } from "@agent-native/core/client";
23
+ import changelog from "../CHANGELOG.md?raw";
23
24
  configureTracking({
24
25
  getDefaultProps: (_name, properties) => ({
25
26
  ...properties,
@@ -83,7 +84,12 @@ function AppContent() {
83
84
 
84
85
  return (
85
86
  <>
86
- <CommandMenu open={cmdkOpen} onOpenChange={setCmdkOpen}>
87
+ <CommandMenu
88
+ open={cmdkOpen}
89
+ onOpenChange={setCmdkOpen}
90
+ changelog={changelog}
91
+ changelogKey="videos"
92
+ >
87
93
  <CommandMenu.Group heading="Videos">
88
94
  <CommandMenu.Item onSelect={() => {}}>
89
95
  Search compositions
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Shared, dependency-free changelog parsing + serialization.
3
+ *
4
+ * Used by BOTH:
5
+ * - the browser bundle (rendering an app's CHANGELOG.md in the command
6
+ * menu / settings "What's new" surface), and
7
+ * - the `agent-native changelog` CLI (rolling pending entry files up into
8
+ * CHANGELOG.md).
9
+ *
10
+ * Keep this file isomorphic: no Node, no browser, no third-party deps. The
11
+ * markdown shape is the conventional "Keep a Changelog" layout — a top-level
12
+ * `# Changelog` heading followed by one `## <release>` section per release.
13
+ */
14
+ /** A single released section of a CHANGELOG.md file. */
15
+ export interface ChangelogEntry {
16
+ /** Stable id derived from the heading — used for "unseen" tracking. */
17
+ id: string;
18
+ /** Raw heading text, e.g. `2026-06-23` or `v1.2.0 — 2026-06-23`. */
19
+ title: string;
20
+ /** ISO date (YYYY-MM-DD) extracted from the heading, if present. */
21
+ date?: string;
22
+ /** Version label extracted from the heading, if present. */
23
+ version?: string;
24
+ /** Markdown body beneath the heading (until the next `## ` section). */
25
+ body: string;
26
+ }
27
+ /** A not-yet-released entry authored as a `changelog/<file>.md` file. */
28
+ export interface PendingChangelogEntry {
29
+ /** Category — `added`, `improved`, `fixed`, `changed`, etc. */
30
+ type: ChangelogChangeType;
31
+ /** ISO date the entry was authored (YYYY-MM-DD). */
32
+ date?: string;
33
+ /** User-facing description (markdown, single bullet). */
34
+ text: string;
35
+ }
36
+ export type ChangelogChangeType = "added" | "improved" | "fixed" | "changed" | "removed" | "security";
37
+ /**
38
+ * Order changes are grouped under a release heading. Anything not listed here
39
+ * falls back to the "changed" group, then renders in insertion order.
40
+ */
41
+ export declare const CHANGELOG_GROUP_ORDER: ChangelogChangeType[];
42
+ declare const GROUP_LABELS: Record<ChangelogChangeType, string>;
43
+ /** Lowercase, hyphenate, and strip to a URL/id-safe slug. */
44
+ export declare function changelogSlug(value: string): string;
45
+ /**
46
+ * Parse a CHANGELOG.md document into structured release entries.
47
+ *
48
+ * Tolerant by design: an empty or malformed file yields an empty list rather
49
+ * than throwing, so a missing/partial changelog never breaks the UI.
50
+ */
51
+ export declare function parseChangelog(markdown: string): ChangelogEntry[];
52
+ /**
53
+ * Parse a pending `changelog/<file>.md` entry: optional `---` frontmatter
54
+ * (`type:` / `date:`) followed by the markdown description body.
55
+ */
56
+ export declare function parsePendingEntry(content: string): PendingChangelogEntry;
57
+ /**
58
+ * Render a set of pending entries as a single dated release section (the body
59
+ * that goes beneath a `## <date>` heading). Groups bullets by type.
60
+ */
61
+ export declare function renderReleaseBody(entries: PendingChangelogEntry[]): string;
62
+ declare const CHANGELOG_HEADER: string;
63
+ /**
64
+ * Roll a batch of pending entries into an existing CHANGELOG.md document,
65
+ * prepending a new `## <date>` section above the most recent release. Returns
66
+ * the full updated document. Pure — the CLI handles file IO and deletion.
67
+ */
68
+ export declare function rollupChangelog(existing: string, pending: PendingChangelogEntry[], releaseDate: string): string;
69
+ export { CHANGELOG_HEADER, GROUP_LABELS };
70
+ //# sourceMappingURL=parse.d.ts.map
@@ -0,0 +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"}