@agent-native/core 0.120.0 → 0.120.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (207) hide show
  1. package/corpus/README.md +2 -2
  2. package/corpus/core/CHANGELOG.md +16 -0
  3. package/corpus/core/docs/content/extensions.mdx +23 -4
  4. package/corpus/core/package.json +1 -1
  5. package/corpus/core/src/agent/production-agent.ts +4 -0
  6. package/corpus/core/src/agent/run-manager.ts +36 -10
  7. package/corpus/core/src/agent/types.ts +2 -0
  8. package/corpus/core/src/client/MultiTabAssistantChat.tsx +45 -0
  9. package/corpus/core/src/client/extensions/ExtensionsListPage.tsx +16 -3
  10. package/corpus/core/src/client/settings/ExtensionsSettingsContent.tsx +24 -0
  11. package/corpus/core/src/client/settings/SettingsPanel.tsx +10 -0
  12. package/corpus/core/src/client/use-chat-models.ts +45 -0
  13. package/corpus/core/src/deploy/build.ts +3 -0
  14. package/corpus/core/src/server/analytics.ts +164 -20
  15. package/corpus/core/src/server/auth.ts +17 -13
  16. package/corpus/core/src/server/better-auth-instance.ts +13 -1
  17. package/corpus/core/src/templates/chat/app/components/layout/Sidebar.tsx +35 -6
  18. package/corpus/core/src/templates/chat/app/routes/extensions._index.tsx +2 -2
  19. package/corpus/core/src/templates/chat/netlify.toml +1 -0
  20. package/corpus/core/src/templates/workspace-core/.agents/skills/extensions/SKILL.md +16 -0
  21. package/corpus/core/src/vite/client.ts +6 -0
  22. package/corpus/templates/analytics/.agents/skills/adhoc-analysis/SKILL.md +27 -43
  23. package/corpus/templates/analytics/.agents/skills/dashboard-management/SKILL.md +19 -8
  24. package/corpus/templates/analytics/.agents/skills/data-querying/SKILL.md +2 -2
  25. package/corpus/templates/analytics/AGENTS.md +20 -8
  26. package/corpus/templates/analytics/actions/get-explorer-dashboard.ts +3 -0
  27. package/corpus/templates/analytics/actions/list-dashboard-usage-stats.ts +140 -46
  28. package/corpus/templates/analytics/actions/migrate-analytics-artifacts.ts +48 -0
  29. package/corpus/templates/analytics/actions/save-analysis.ts +2 -3
  30. package/corpus/templates/analytics/actions/view-screen.ts +1 -1
  31. package/corpus/templates/analytics/app/components/dashboard/DashboardMetadata.tsx +77 -0
  32. package/corpus/templates/analytics/app/components/dashboard/DashboardPanelSkeleton.tsx +7 -1
  33. package/corpus/templates/analytics/app/components/layout/NewDashboardDialog.tsx +1 -0
  34. package/corpus/templates/analytics/app/components/layout/Sidebar.tsx +103 -502
  35. package/corpus/templates/analytics/app/global.css +30 -0
  36. package/corpus/templates/analytics/app/hooks/use-navigation-state.ts +2 -2
  37. package/corpus/templates/analytics/app/i18n-data.ts +80 -0
  38. package/corpus/templates/analytics/app/pages/Agents.tsx +49 -2
  39. package/corpus/templates/analytics/app/pages/adhoc/explorer-dashboard/index.tsx +54 -11
  40. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/SqlChartCard.tsx +3 -53
  41. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/index.tsx +23 -25
  42. package/corpus/templates/analytics/app/pages/analyses/AnalysisDetail.tsx +2 -2
  43. package/corpus/templates/analytics/app/routes/analyses._index.tsx +3 -2
  44. package/corpus/templates/analytics/app/routes/extensions._index.tsx +2 -2
  45. package/corpus/templates/analytics/changelog/2026-07-23-analytics-now-groups-saved-analyses-and-embedded-extensions-.md +6 -0
  46. package/corpus/templates/analytics/changelog/2026-07-23-dashboard-menus-show-who-created-and-last-updated-each-dashb.md +6 -0
  47. package/corpus/templates/analytics/changelog/2026-07-23-dashboard-usage-now-loads-reliably-for-organizations-with-ma.md +6 -0
  48. package/corpus/templates/analytics/changelog/2026-07-23-long-dashboard-building-requests-now-continue-without-stoppi.md +6 -0
  49. package/corpus/templates/analytics/netlify.toml +4 -0
  50. package/corpus/templates/analytics/server/db/schema.ts +4 -0
  51. package/corpus/templates/analytics/server/lib/agent-chat-plan-mode.ts +0 -1
  52. package/corpus/templates/analytics/server/lib/agent-readable-resource-context.ts +1 -0
  53. package/corpus/templates/analytics/server/lib/migrate-analytics-artifacts.ts +1062 -0
  54. package/corpus/templates/analytics/server/plugins/agent-chat.ts +6 -52
  55. package/corpus/templates/analytics/server/plugins/core-routes.ts +1 -1
  56. package/corpus/templates/analytics/server/plugins/db.ts +10 -0
  57. package/corpus/templates/assets/actions/generate-image-batch.ts +36 -1
  58. package/corpus/templates/assets/actions/generate-image.ts +28 -1
  59. package/corpus/templates/assets/app/components/layout/Sidebar.tsx +47 -9
  60. package/corpus/templates/assets/app/routes/extensions._index.tsx +2 -2
  61. package/corpus/templates/assets/changelog/2026-07-23-assets-image-generation-now-recovers-after-a-completed-tool-.md +6 -0
  62. package/corpus/templates/assets/changelog/2026-07-23-new-chat-aligns-with-sidebar-controls.md +6 -0
  63. package/corpus/templates/assets/netlify.toml +1 -0
  64. package/corpus/templates/brain/app/components/layout/Sidebar.tsx +38 -8
  65. package/corpus/templates/brain/app/routes/extensions._index.tsx +2 -2
  66. package/corpus/templates/brain/netlify.toml +1 -0
  67. package/corpus/templates/calendar/app/components/layout/Sidebar.tsx +43 -5
  68. package/corpus/templates/calendar/app/routes/_app.extensions._index.tsx +2 -16
  69. package/corpus/templates/calendar/netlify.toml +1 -0
  70. package/corpus/templates/chat/app/components/layout/Sidebar.tsx +35 -6
  71. package/corpus/templates/chat/app/routes/extensions._index.tsx +2 -2
  72. package/corpus/templates/chat/netlify.toml +1 -0
  73. package/corpus/templates/clips/app/components/library/library-layout.tsx +52 -6
  74. package/corpus/templates/clips/app/routes/_app.extensions._index.tsx +2 -16
  75. package/corpus/templates/clips/changelog/2026-07-23-agent-settings-are-clearly-labeled-manage-agent-in-the-sideb.md +6 -0
  76. package/corpus/templates/clips/changelog/2026-07-23-meeting-recording-meters-and-dismissed-prompts.md +6 -0
  77. package/corpus/templates/clips/desktop/src/hooks/useMicMeter.ts +1 -1
  78. package/corpus/templates/clips/desktop/src/lib/meeting-notification-dismissal.ts +2 -0
  79. package/corpus/templates/clips/desktop/src/lib/voice-dictation.ts +1 -3
  80. package/corpus/templates/clips/desktop/src/overlays/live-audio-bars.tsx +86 -0
  81. package/corpus/templates/clips/desktop/src/overlays/meeting-notification.tsx +24 -0
  82. package/corpus/templates/clips/desktop/src/overlays/recording-pill.tsx +5 -69
  83. package/corpus/templates/clips/desktop/src/styles.css +35 -3
  84. package/corpus/templates/clips/desktop/src-tauri/src/adhoc_meetings_watcher.rs +13 -44
  85. package/corpus/templates/clips/desktop/src-tauri/src/notifications.rs +119 -17
  86. package/corpus/templates/clips/netlify.toml +1 -0
  87. package/corpus/templates/content/app/components/sidebar/DocumentSidebar.tsx +3 -7
  88. package/corpus/templates/content/app/routes/_app.extensions._index.tsx +2 -2
  89. package/corpus/templates/content/changelog/2026-07-23-agent-settings-are-clearly-labeled-manage-agent-in-the-sideb.md +6 -0
  90. package/corpus/templates/content/netlify.toml +1 -0
  91. package/corpus/templates/design/app/components/layout/Sidebar.tsx +55 -17
  92. package/corpus/templates/design/app/routes/extensions._index.tsx +2 -2
  93. package/corpus/templates/design/changelog/2026-07-23-agent-settings-are-clearly-labeled-manage-agent-in-the-sideb.md +6 -0
  94. package/corpus/templates/design/netlify.toml +1 -0
  95. package/corpus/templates/dispatch/app/dispatch-extensions.tsx +1 -1
  96. package/corpus/templates/dispatch/changelog/2026-07-23-agent-settings-are-clearly-labeled-manage-agent-in-the-sideb.md +6 -0
  97. package/corpus/templates/dispatch/netlify.toml +1 -0
  98. package/corpus/templates/forms/.agents/skills/form-publishing/SKILL.md +9 -3
  99. package/corpus/templates/forms/AGENTS.md +11 -1
  100. package/corpus/templates/forms/README.md +24 -1
  101. package/corpus/templates/forms/actions/update-form.ts +12 -5
  102. package/corpus/templates/forms/app/components/builder/FieldPropertiesPanel.tsx +199 -1
  103. package/corpus/templates/forms/app/components/layout/Sidebar.tsx +41 -45
  104. package/corpus/templates/forms/app/i18n/en-US.ts +13 -1
  105. package/corpus/templates/forms/app/pages/FormBuilderPage.tsx +35 -4
  106. package/corpus/templates/forms/app/pages/FormFillPage.tsx +7 -16
  107. package/corpus/templates/forms/app/routes/_app.extensions._index.tsx +2 -2
  108. package/corpus/templates/forms/changelog/2026-07-23-agent-settings-are-clearly-labeled-manage-agent-in-the-sideb.md +6 -0
  109. package/corpus/templates/forms/changelog/2026-07-23-forms-can-branch-into-follow-up-questions-and-route-response.md +6 -0
  110. package/corpus/templates/forms/netlify.toml +1 -0
  111. package/corpus/templates/forms/server/handlers/submissions.ts +22 -31
  112. package/corpus/templates/forms/server/lib/integrations.ts +11 -2
  113. package/corpus/templates/forms/server/lib/public-form-ssr.ts +26 -5
  114. package/corpus/templates/forms/server/lib/validate-fields.ts +48 -11
  115. package/corpus/templates/forms/server/plugins/agent-chat.ts +1 -0
  116. package/corpus/templates/forms/shared/conditional.ts +67 -0
  117. package/corpus/templates/macros/app/components/layout/AppLayout.tsx +36 -5
  118. package/corpus/templates/macros/app/routes/extensions._index.tsx +2 -2
  119. package/corpus/templates/macros/netlify.toml +1 -0
  120. package/corpus/templates/mail/app/components/layout/AppLayout.tsx +0 -9
  121. package/corpus/templates/mail/app/routes/extensions._index.tsx +2 -2
  122. package/corpus/templates/mail/netlify.toml +1 -0
  123. package/corpus/templates/plan/app/components/layout/Sidebar.tsx +38 -5
  124. package/corpus/templates/plan/app/routes/extensions._index.tsx +2 -2
  125. package/corpus/templates/plan/netlify.toml +1 -0
  126. package/corpus/templates/slides/app/components/layout/Sidebar.tsx +47 -4
  127. package/corpus/templates/slides/app/routes/extensions._index.tsx +2 -2
  128. package/corpus/templates/slides/netlify.toml +1 -0
  129. package/corpus/templates/tasks/app/components/layout/Sidebar.tsx +37 -6
  130. package/corpus/templates/tasks/app/routes/extensions._index.tsx +2 -2
  131. package/corpus/templates/tasks/app/routes/settings.tsx +31 -0
  132. package/corpus/templates/tasks/netlify.toml +1 -0
  133. package/dist/agent/production-agent.d.ts.map +1 -1
  134. package/dist/agent/production-agent.js +4 -0
  135. package/dist/agent/production-agent.js.map +1 -1
  136. package/dist/agent/run-manager.d.ts +9 -0
  137. package/dist/agent/run-manager.d.ts.map +1 -1
  138. package/dist/agent/run-manager.js +25 -10
  139. package/dist/agent/run-manager.js.map +1 -1
  140. package/dist/agent/types.d.ts +2 -2
  141. package/dist/agent/types.d.ts.map +1 -1
  142. package/dist/agent/types.js.map +1 -1
  143. package/dist/client/MultiTabAssistantChat.d.ts.map +1 -1
  144. package/dist/client/MultiTabAssistantChat.js +35 -0
  145. package/dist/client/MultiTabAssistantChat.js.map +1 -1
  146. package/dist/client/extensions/ExtensionsListPage.d.ts +5 -1
  147. package/dist/client/extensions/ExtensionsListPage.d.ts.map +1 -1
  148. package/dist/client/extensions/ExtensionsListPage.js +5 -3
  149. package/dist/client/extensions/ExtensionsListPage.js.map +1 -1
  150. package/dist/client/settings/ExtensionsSettingsContent.d.ts +2 -0
  151. package/dist/client/settings/ExtensionsSettingsContent.d.ts.map +1 -0
  152. package/dist/client/settings/ExtensionsSettingsContent.js +10 -0
  153. package/dist/client/settings/ExtensionsSettingsContent.js.map +1 -0
  154. package/dist/client/settings/SettingsPanel.d.ts.map +1 -1
  155. package/dist/client/settings/SettingsPanel.js +10 -1
  156. package/dist/client/settings/SettingsPanel.js.map +1 -1
  157. package/dist/client/use-chat-models.d.ts +1 -0
  158. package/dist/client/use-chat-models.d.ts.map +1 -1
  159. package/dist/client/use-chat-models.js +33 -0
  160. package/dist/client/use-chat-models.js.map +1 -1
  161. package/dist/collab/awareness.d.ts +2 -2
  162. package/dist/collab/awareness.d.ts.map +1 -1
  163. package/dist/deploy/build.js +1 -0
  164. package/dist/deploy/build.js.map +1 -1
  165. package/dist/file-upload/actions/upload-image.d.ts +1 -1
  166. package/dist/observability/routes.d.ts +3 -3
  167. package/dist/provider-api/actions/custom-provider-registration.d.ts +4 -4
  168. package/dist/provider-api/actions/provider-api.d.ts +2 -2
  169. package/dist/server/analytics.d.ts +17 -4
  170. package/dist/server/analytics.d.ts.map +1 -1
  171. package/dist/server/analytics.js +122 -17
  172. package/dist/server/analytics.js.map +1 -1
  173. package/dist/server/auth.d.ts.map +1 -1
  174. package/dist/server/auth.js +5 -4
  175. package/dist/server/auth.js.map +1 -1
  176. package/dist/server/better-auth-instance.d.ts +8 -0
  177. package/dist/server/better-auth-instance.d.ts.map +1 -1
  178. package/dist/server/better-auth-instance.js +10 -1
  179. package/dist/server/better-auth-instance.js.map +1 -1
  180. package/dist/templates/chat/app/components/layout/Sidebar.tsx +35 -6
  181. package/dist/templates/chat/app/routes/extensions._index.tsx +2 -2
  182. package/dist/templates/chat/netlify.toml +1 -0
  183. package/dist/templates/workspace-core/.agents/skills/extensions/SKILL.md +16 -0
  184. package/dist/vite/client.d.ts.map +1 -1
  185. package/dist/vite/client.js +2 -0
  186. package/dist/vite/client.js.map +1 -1
  187. package/docs/content/extensions.mdx +23 -4
  188. package/package.json +1 -1
  189. package/src/agent/production-agent.ts +4 -0
  190. package/src/agent/run-manager.ts +36 -10
  191. package/src/agent/types.ts +2 -0
  192. package/src/client/MultiTabAssistantChat.tsx +45 -0
  193. package/src/client/extensions/ExtensionsListPage.tsx +16 -3
  194. package/src/client/settings/ExtensionsSettingsContent.tsx +24 -0
  195. package/src/client/settings/SettingsPanel.tsx +10 -0
  196. package/src/client/use-chat-models.ts +45 -0
  197. package/src/deploy/build.ts +3 -0
  198. package/src/server/analytics.ts +164 -20
  199. package/src/server/auth.ts +17 -13
  200. package/src/server/better-auth-instance.ts +13 -1
  201. package/src/templates/chat/app/components/layout/Sidebar.tsx +35 -6
  202. package/src/templates/chat/app/routes/extensions._index.tsx +2 -2
  203. package/src/templates/chat/netlify.toml +1 -0
  204. package/src/templates/workspace-core/.agents/skills/extensions/SKILL.md +16 -0
  205. package/src/vite/client.ts +6 -0
  206. package/corpus/templates/analytics/app/components/layout/NewAnalysisDialog.tsx +0 -165
  207. package/corpus/templates/analytics/app/pages/analyses/AnalysesList.tsx +0 -175
@@ -17,12 +17,12 @@ declare const _default: import("../../action.js").ActionDefinition<{
17
17
  id?: undefined;
18
18
  provider?: undefined;
19
19
  } | {
20
+ error?: undefined;
20
21
  configured?: undefined;
21
22
  connectPath?: undefined;
22
23
  url: string;
23
24
  id: string;
24
25
  provider: string;
25
- error?: undefined;
26
26
  }>;
27
27
  export default _default;
28
28
  //# sourceMappingURL=upload-image.d.ts.map
@@ -41,23 +41,23 @@ export declare function createObservabilityHandler(): import("h3").EventHandlerW
41
41
  thumbsUpRate: number;
42
42
  avgEvalScore: number;
43
43
  } | {
44
- ok?: undefined;
45
44
  error?: undefined;
46
45
  summary: import("./types.js").TraceSummary;
47
46
  spans: import("./types.js").TraceSpan[];
48
47
  id?: undefined;
49
- } | {
50
48
  ok?: undefined;
49
+ } | {
51
50
  error?: undefined;
52
51
  summary?: undefined;
53
52
  spans?: undefined;
54
53
  id: string;
55
- } | {
56
54
  ok?: undefined;
55
+ } | {
57
56
  summary?: undefined;
58
57
  spans?: undefined;
59
58
  id?: undefined;
60
59
  error: any;
60
+ ok?: undefined;
61
61
  } | {
62
62
  error?: undefined;
63
63
  summary?: undefined;
@@ -76,7 +76,6 @@ export declare function createCustomProviderRegistrationAction<TSchema extends Z
76
76
  }>>;
77
77
  }, z.core.$strip>>, {
78
78
  deleted?: undefined;
79
- message?: undefined;
80
79
  providers: {
81
80
  id: string;
82
81
  label: string;
@@ -92,9 +91,9 @@ export declare function createCustomProviderRegistrationAction<TSchema extends Z
92
91
  registered?: undefined;
93
92
  id?: undefined;
94
93
  label?: undefined;
94
+ message?: undefined;
95
95
  } | {
96
96
  deleted?: undefined;
97
- message?: undefined;
98
97
  providers?: undefined;
99
98
  count?: undefined;
100
99
  found: boolean;
@@ -102,9 +101,9 @@ export declare function createCustomProviderRegistrationAction<TSchema extends Z
102
101
  registered?: undefined;
103
102
  id?: undefined;
104
103
  label?: undefined;
104
+ message?: undefined;
105
105
  } | {
106
106
  deleted?: undefined;
107
- message?: undefined;
108
107
  providers?: undefined;
109
108
  count?: undefined;
110
109
  provider?: undefined;
@@ -112,8 +111,8 @@ export declare function createCustomProviderRegistrationAction<TSchema extends Z
112
111
  id: string;
113
112
  registered?: undefined;
114
113
  label?: undefined;
115
- } | {
116
114
  message?: undefined;
115
+ } | {
117
116
  providers?: undefined;
118
117
  count?: undefined;
119
118
  provider?: undefined;
@@ -122,6 +121,7 @@ export declare function createCustomProviderRegistrationAction<TSchema extends Z
122
121
  id: string;
123
122
  registered?: undefined;
124
123
  label?: undefined;
124
+ message?: undefined;
125
125
  } | {
126
126
  deleted?: undefined;
127
127
  providers?: undefined;
@@ -309,9 +309,9 @@ export declare function createProviderApiActions(runtime: Pick<ProviderApiRuntim
309
309
  notes?: string | undefined;
310
310
  scope?: "org" | "user" | undefined;
311
311
  }, {
312
- id?: undefined;
313
312
  message?: undefined;
314
313
  deleted?: undefined;
314
+ id?: undefined;
315
315
  providers: {
316
316
  id: string;
317
317
  label: string;
@@ -327,9 +327,9 @@ export declare function createProviderApiActions(runtime: Pick<ProviderApiRuntim
327
327
  registered?: undefined;
328
328
  label?: undefined;
329
329
  } | {
330
- id?: undefined;
331
330
  message?: undefined;
332
331
  deleted?: undefined;
332
+ id?: undefined;
333
333
  count?: undefined;
334
334
  providers?: undefined;
335
335
  found: boolean;
@@ -2,16 +2,21 @@
2
2
  * Opt-in analytics injection for SSR streams.
3
3
  * Supported environment variables:
4
4
  * - `GA_MEASUREMENT_ID` — Google Analytics 4 measurement ID
5
+ * - `GTM_CONTAINER_ID` — Google Tag Manager web container ID
5
6
  *
6
7
  * Netlify configuration-file env vars are build-time only for serverless
7
8
  * functions, so the Vite/Nitro build paths also bake this public value into
8
9
  * SSR bundles.
9
10
  *
10
11
  * Amplitude and Sentry are initialized client-side via their npm packages
11
- * (see `packages/core/src/client/analytics.ts`). Only GA requires script
12
- * tag injection because the gtag.js loader must be a `<script src>`.
12
+ * (see `packages/core/src/client/analytics.ts`). GTM and GA require script
13
+ * tag injection because their loaders must be `<script>` elements.
13
14
  *
14
- * When set, the corresponding script tags are injected before `</head>`.
15
+ * When GTM is set, its head bootstrap is injected before `</head>` and its
16
+ * noscript fallback immediately after `<body>`. GTM takes precedence over GA
17
+ * so pageviews are not double-counted; configure the GA tag inside GTM.
18
+ * When only GA is set, the corresponding script tags are injected before
19
+ * `</head>`.
15
20
  * When not set, the stream passes through untouched (zero overhead).
16
21
  *
17
22
  * Usage in entry.server.tsx:
@@ -26,5 +31,13 @@
26
31
  * Returns `null` when GA is not configured.
27
32
  */
28
33
  export declare function getGaInlineConfigScriptBody(): string | null;
29
- export declare function wrapWithAnalytics(body: ReadableStream): ReadableStream;
34
+ /**
35
+ * Add the configured analytics scripts to a complete HTML document.
36
+ *
37
+ * The normal app document is streamed through `wrapWithAnalytics`, but
38
+ * framework-owned documents such as `/signup` are returned as strings by the
39
+ * auth guard and need the same injection path.
40
+ */
41
+ export declare function injectAnalyticsIntoHtml(html: string): string;
42
+ export declare function wrapWithAnalytics(body: ReadableStream<Uint8Array>): ReadableStream<Uint8Array>;
30
43
  //# sourceMappingURL=analytics.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"analytics.d.ts","sourceRoot":"","sources":["../../src/server/analytics.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAuBH;;;;GAIG;AACH,wBAAgB,2BAA2B,IAAI,MAAM,GAAG,IAAI,CAc3D;AAaD,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,cAAc,GAAG,cAAc,CA4BtE"}
1
+ {"version":3,"file":"analytics.d.ts","sourceRoot":"","sources":["../../src/server/analytics.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AA2CH;;;;GAIG;AACH,wBAAgB,2BAA2B,IAAI,MAAM,GAAG,IAAI,CAc3D;AA4CD;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAsB5D;AAED,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,cAAc,CAAC,UAAU,CAAC,GAC/B,cAAc,CAAC,UAAU,CAAC,CAmF5B"}
@@ -2,16 +2,21 @@
2
2
  * Opt-in analytics injection for SSR streams.
3
3
  * Supported environment variables:
4
4
  * - `GA_MEASUREMENT_ID` — Google Analytics 4 measurement ID
5
+ * - `GTM_CONTAINER_ID` — Google Tag Manager web container ID
5
6
  *
6
7
  * Netlify configuration-file env vars are build-time only for serverless
7
8
  * functions, so the Vite/Nitro build paths also bake this public value into
8
9
  * SSR bundles.
9
10
  *
10
11
  * Amplitude and Sentry are initialized client-side via their npm packages
11
- * (see `packages/core/src/client/analytics.ts`). Only GA requires script
12
- * tag injection because the gtag.js loader must be a `<script src>`.
12
+ * (see `packages/core/src/client/analytics.ts`). GTM and GA require script
13
+ * tag injection because their loaders must be `<script>` elements.
13
14
  *
14
- * When set, the corresponding script tags are injected before `</head>`.
15
+ * When GTM is set, its head bootstrap is injected before `</head>` and its
16
+ * noscript fallback immediately after `<body>`. GTM takes precedence over GA
17
+ * so pageviews are not double-counted; configure the GA tag inside GTM.
18
+ * When only GA is set, the corresponding script tags are injected before
19
+ * `</head>`.
15
20
  * When not set, the stream passes through untouched (zero overhead).
16
21
  *
17
22
  * Usage in entry.server.tsx:
@@ -29,6 +34,20 @@ function getViteBakedGaMeasurementId() {
29
34
  ? __AGENT_NATIVE_BUILD_GA_MEASUREMENT_ID__
30
35
  : undefined;
31
36
  }
37
+ function normalizeContainerId(value) {
38
+ const trimmed = value?.trim().toUpperCase();
39
+ return trimmed && /^GTM-[A-Z0-9]+$/.test(trimmed) ? trimmed : null;
40
+ }
41
+ function getViteBakedGtmContainerId() {
42
+ return typeof __AGENT_NATIVE_BUILD_GTM_CONTAINER_ID__ === "string"
43
+ ? __AGENT_NATIVE_BUILD_GTM_CONTAINER_ID__
44
+ : undefined;
45
+ }
46
+ function getGtmContainerId() {
47
+ return (normalizeContainerId(process.env.GTM_CONTAINER_ID) ||
48
+ normalizeContainerId(process.env.AGENT_NATIVE_BUILD_GTM_CONTAINER_ID) ||
49
+ normalizeContainerId(getViteBakedGtmContainerId()));
50
+ }
32
51
  function getGaMeasurementId() {
33
52
  return (normalizeMeasurementId(process.env.GA_MEASUREMENT_ID) ||
34
53
  normalizeMeasurementId(process.env.AGENT_NATIVE_BUILD_GA_MEASUREMENT_ID) ||
@@ -62,29 +81,115 @@ function getGaScript() {
62
81
  return (`<script async src="https://www.googletagmanager.com/gtag/js?id=${srcId}"></script>` +
63
82
  `<script>${inlineBody}</script>`);
64
83
  }
84
+ function getGtmHeadScript(containerId) {
85
+ const jsId = JSON.stringify(containerId);
86
+ return `<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src='https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);})(window,document,'script','dataLayer',${jsId});</script>`;
87
+ }
88
+ function getGtmBodyFallback(containerId) {
89
+ const src = encodeURIComponent(containerId);
90
+ return `<noscript><iframe src="https://www.googletagmanager.com/ns.html?id=${src}" height="0" width="0" style="display:none;visibility:hidden" title="Google Tag Manager"></iframe></noscript>`;
91
+ }
92
+ function getAnalyticsInjection() {
93
+ const containerId = getGtmContainerId();
94
+ if (containerId) {
95
+ return {
96
+ head: getGtmHeadScript(containerId),
97
+ body: getGtmBodyFallback(containerId),
98
+ };
99
+ }
100
+ const gaScript = getGaScript();
101
+ return gaScript ? { head: gaScript, body: "" } : null;
102
+ }
103
+ const HEAD_CLOSE_PATTERN = /<\/head>/i;
104
+ const BODY_OPEN_PATTERN = /<body\b[^>]*>/i;
105
+ /**
106
+ * Add the configured analytics scripts to a complete HTML document.
107
+ *
108
+ * The normal app document is streamed through `wrapWithAnalytics`, but
109
+ * framework-owned documents such as `/signup` are returned as strings by the
110
+ * auth guard and need the same injection path.
111
+ */
112
+ export function injectAnalyticsIntoHtml(html) {
113
+ const injection = getAnalyticsInjection();
114
+ if (!injection)
115
+ return html;
116
+ const headCloseMatch = HEAD_CLOSE_PATTERN.exec(html);
117
+ if (!headCloseMatch || headCloseMatch.index === undefined)
118
+ return html;
119
+ let output = html.slice(0, headCloseMatch.index) +
120
+ injection.head +
121
+ html.slice(headCloseMatch.index);
122
+ if (injection.body) {
123
+ const bodyOpenMatch = BODY_OPEN_PATTERN.exec(output);
124
+ if (bodyOpenMatch && bodyOpenMatch.index !== undefined) {
125
+ const bodyEnd = bodyOpenMatch.index + bodyOpenMatch[0].length;
126
+ output =
127
+ output.slice(0, bodyEnd) + injection.body + output.slice(bodyEnd);
128
+ }
129
+ }
130
+ return output;
131
+ }
65
132
  export function wrapWithAnalytics(body) {
66
- const scripts = [getGaScript()].filter(Boolean).join("");
67
- if (!scripts)
133
+ const injection = getAnalyticsInjection();
134
+ if (!injection)
68
135
  return body;
69
136
  const decoder = new TextDecoder();
70
137
  const encoder = new TextEncoder();
71
- let injected = false;
138
+ let pending = "";
139
+ let headInjected = false;
140
+ let bodyInjected = !injection.body;
72
141
  return body.pipeThrough(new TransformStream({
73
142
  transform(chunk, controller) {
74
- if (injected) {
75
- controller.enqueue(chunk);
76
- return;
143
+ pending += decoder.decode(chunk, { stream: true });
144
+ if (!headInjected) {
145
+ const headCloseMatch = HEAD_CLOSE_PATTERN.exec(pending);
146
+ if (!headCloseMatch || headCloseMatch.index === undefined)
147
+ return;
148
+ const headEnd = headCloseMatch.index + headCloseMatch[0].length;
149
+ controller.enqueue(encoder.encode(pending.slice(0, headCloseMatch.index) +
150
+ injection.head +
151
+ pending.slice(headCloseMatch.index, headEnd)));
152
+ pending = pending.slice(headEnd);
153
+ headInjected = true;
77
154
  }
78
- const text = decoder.decode(chunk, { stream: true });
79
- const headCloseIdx = text.indexOf("</head>");
80
- if (headCloseIdx !== -1) {
81
- const modified = text.slice(0, headCloseIdx) + scripts + text.slice(headCloseIdx);
82
- controller.enqueue(encoder.encode(modified));
83
- injected = true;
155
+ if (!bodyInjected) {
156
+ const bodyOpenMatch = BODY_OPEN_PATTERN.exec(pending);
157
+ if (!bodyOpenMatch || bodyOpenMatch.index === undefined)
158
+ return;
159
+ const bodyEnd = bodyOpenMatch.index + bodyOpenMatch[0].length;
160
+ controller.enqueue(encoder.encode(pending.slice(0, bodyEnd) + injection.body));
161
+ pending = pending.slice(bodyEnd);
162
+ bodyInjected = true;
163
+ }
164
+ if (pending) {
165
+ controller.enqueue(encoder.encode(pending));
166
+ pending = "";
167
+ }
168
+ },
169
+ flush(controller) {
170
+ pending += decoder.decode();
171
+ if (!headInjected) {
172
+ const headCloseMatch = HEAD_CLOSE_PATTERN.exec(pending);
173
+ if (headCloseMatch && headCloseMatch.index !== undefined) {
174
+ const headEnd = headCloseMatch.index + headCloseMatch[0].length;
175
+ controller.enqueue(encoder.encode(pending.slice(0, headCloseMatch.index) +
176
+ injection.head +
177
+ pending.slice(headCloseMatch.index, headEnd)));
178
+ pending = pending.slice(headEnd);
179
+ headInjected = true;
180
+ }
84
181
  }
85
- else {
86
- controller.enqueue(chunk);
182
+ if (headInjected && !bodyInjected) {
183
+ const bodyOpenMatch = BODY_OPEN_PATTERN.exec(pending);
184
+ if (bodyOpenMatch && bodyOpenMatch.index !== undefined) {
185
+ const bodyEnd = bodyOpenMatch.index + bodyOpenMatch[0].length;
186
+ controller.enqueue(encoder.encode(pending.slice(0, bodyEnd) + injection.body));
187
+ pending = pending.slice(bodyEnd);
188
+ bodyInjected = true;
189
+ }
87
190
  }
191
+ if (pending)
192
+ controller.enqueue(encoder.encode(pending));
88
193
  },
89
194
  }));
90
195
  }
@@ -1 +1 @@
1
- {"version":3,"file":"analytics.js","sourceRoot":"","sources":["../../src/server/analytics.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAIH,SAAS,sBAAsB,CAAC,KAAyB;IACvD,MAAM,OAAO,GAAG,KAAK,EAAE,IAAI,EAAE,CAAC;IAC9B,OAAO,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC;AAClC,CAAC;AAED,SAAS,2BAA2B;IAClC,OAAO,OAAO,wCAAwC,KAAK,QAAQ;QACjE,CAAC,CAAC,wCAAwC;QAC1C,CAAC,CAAC,SAAS,CAAC;AAChB,CAAC;AAED,SAAS,kBAAkB;IACzB,OAAO,CACL,sBAAsB,CAAC,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC;QACrD,sBAAsB,CAAC,OAAO,CAAC,GAAG,CAAC,oCAAoC,CAAC;QACxE,sBAAsB,CAAC,2BAA2B,EAAE,CAAC,CACtD,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,2BAA2B;IACzC,MAAM,EAAE,GAAG,kBAAkB,EAAE,CAAC;IAChC,IAAI,CAAC,EAAE;QAAE,OAAO,IAAI,CAAC;IACrB,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;IAChC,OAAO,CACL,wCAAwC;QACxC,6CAA6C;QAC7C,wBAAwB;QACxB,iBAAiB,IAAI,IAAI;QACzB,iFAAiF;QACjF,2CAA2C;QAC3C,0BAA0B;QAC1B,GAAG,CACJ,CAAC;AACJ,CAAC;AAED,SAAS,WAAW;IAClB,MAAM,EAAE,GAAG,kBAAkB,EAAE,CAAC;IAChC,IAAI,CAAC,EAAE;QAAE,OAAO,IAAI,CAAC;IACrB,MAAM,KAAK,GAAG,kBAAkB,CAAC,EAAE,CAAC,CAAC;IACrC,MAAM,UAAU,GAAG,2BAA2B,EAAE,CAAC;IACjD,OAAO,CACL,kEAAkE,KAAK,aAAa;QACpF,WAAW,UAAU,WAAW,CACjC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,IAAoB;IACpD,MAAM,OAAO,GAAG,CAAC,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACzD,IAAI,CAAC,OAAO;QAAE,OAAO,IAAI,CAAC;IAE1B,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAC;IAClC,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAC;IAClC,IAAI,QAAQ,GAAG,KAAK,CAAC;IAErB,OAAO,IAAI,CAAC,WAAW,CACrB,IAAI,eAAe,CAAC;QAClB,SAAS,CAAC,KAAK,EAAE,UAAU;YACzB,IAAI,QAAQ,EAAE,CAAC;gBACb,UAAU,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;gBAC1B,OAAO;YACT,CAAC;YACD,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;YACrD,MAAM,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;YAC7C,IAAI,YAAY,KAAK,CAAC,CAAC,EAAE,CAAC;gBACxB,MAAM,QAAQ,GACZ,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,YAAY,CAAC,GAAG,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;gBACnE,UAAU,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC;gBAC7C,QAAQ,GAAG,IAAI,CAAC;YAClB,CAAC;iBAAM,CAAC;gBACN,UAAU,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;YAC5B,CAAC;QACH,CAAC;KACF,CAAC,CACH,CAAC;AACJ,CAAC","sourcesContent":["/**\n * Opt-in analytics injection for SSR streams.\n * Supported environment variables:\n * - `GA_MEASUREMENT_ID` — Google Analytics 4 measurement ID\n *\n * Netlify configuration-file env vars are build-time only for serverless\n * functions, so the Vite/Nitro build paths also bake this public value into\n * SSR bundles.\n *\n * Amplitude and Sentry are initialized client-side via their npm packages\n * (see `packages/core/src/client/analytics.ts`). Only GA requires script\n * tag injection because the gtag.js loader must be a `<script src>`.\n *\n * When set, the corresponding script tags are injected before `</head>`.\n * When not set, the stream passes through untouched (zero overhead).\n *\n * Usage in entry.server.tsx:\n * ```ts\n * import { wrapWithAnalytics } from \"@agent-native/core/server\";\n * return new Response(wrapWithAnalytics(body), { ... });\n * ```\n */\n\ndeclare const __AGENT_NATIVE_BUILD_GA_MEASUREMENT_ID__: string | undefined;\n\nfunction normalizeMeasurementId(value: string | undefined): string | null {\n const trimmed = value?.trim();\n return trimmed ? trimmed : null;\n}\n\nfunction getViteBakedGaMeasurementId(): string | undefined {\n return typeof __AGENT_NATIVE_BUILD_GA_MEASUREMENT_ID__ === \"string\"\n ? __AGENT_NATIVE_BUILD_GA_MEASUREMENT_ID__\n : undefined;\n}\n\nfunction getGaMeasurementId(): string | null {\n return (\n normalizeMeasurementId(process.env.GA_MEASUREMENT_ID) ||\n normalizeMeasurementId(process.env.AGENT_NATIVE_BUILD_GA_MEASUREMENT_ID) ||\n normalizeMeasurementId(getViteBakedGaMeasurementId())\n );\n}\n\n/**\n * The exact JS body (no surrounding `<script>` tags) of the inline gtag config\n * block injected next to the gtag.js loader.\n * Returns `null` when GA is not configured.\n */\nexport function getGaInlineConfigScriptBody(): string | null {\n const id = getGaMeasurementId();\n if (!id) return null;\n const jsId = JSON.stringify(id);\n return (\n `window.dataLayer=window.dataLayer||[];` +\n `function gtag(){dataLayer.push(arguments);}` +\n `gtag('js',new Date());` +\n `gtag('config',${jsId});` +\n `if(typeof sessionStorage!=='undefined'&&sessionStorage.getItem('__an_signin')){` +\n `sessionStorage.removeItem('__an_signin');` +\n `gtag('event','sign_in');` +\n `}`\n );\n}\n\nfunction getGaScript(): string | null {\n const id = getGaMeasurementId();\n if (!id) return null;\n const srcId = encodeURIComponent(id);\n const inlineBody = getGaInlineConfigScriptBody();\n return (\n `<script async src=\"https://www.googletagmanager.com/gtag/js?id=${srcId}\"></script>` +\n `<script>${inlineBody}</script>`\n );\n}\n\nexport function wrapWithAnalytics(body: ReadableStream): ReadableStream {\n const scripts = [getGaScript()].filter(Boolean).join(\"\");\n if (!scripts) return body;\n\n const decoder = new TextDecoder();\n const encoder = new TextEncoder();\n let injected = false;\n\n return body.pipeThrough(\n new TransformStream({\n transform(chunk, controller) {\n if (injected) {\n controller.enqueue(chunk);\n return;\n }\n const text = decoder.decode(chunk, { stream: true });\n const headCloseIdx = text.indexOf(\"</head>\");\n if (headCloseIdx !== -1) {\n const modified =\n text.slice(0, headCloseIdx) + scripts + text.slice(headCloseIdx);\n controller.enqueue(encoder.encode(modified));\n injected = true;\n } else {\n controller.enqueue(chunk);\n }\n },\n }),\n );\n}\n"]}
1
+ {"version":3,"file":"analytics.js","sourceRoot":"","sources":["../../src/server/analytics.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Opt-in analytics injection for SSR streams.\n * Supported environment variables:\n * - `GA_MEASUREMENT_ID` — Google Analytics 4 measurement ID\n * - `GTM_CONTAINER_ID` — Google Tag Manager web container ID\n *\n * Netlify configuration-file env vars are build-time only for serverless\n * functions, so the Vite/Nitro build paths also bake this public value into\n * SSR bundles.\n *\n * Amplitude and Sentry are initialized client-side via their npm packages\n * (see `packages/core/src/client/analytics.ts`). GTM and GA require script\n * tag injection because their loaders must be `<script>` elements.\n *\n * When GTM is set, its head bootstrap is injected before `</head>` and its\n * noscript fallback immediately after `<body>`. GTM takes precedence over GA\n * so pageviews are not double-counted; configure the GA tag inside GTM.\n * When only GA is set, the corresponding script tags are injected before\n * `</head>`.\n * When not set, the stream passes through untouched (zero overhead).\n *\n * Usage in entry.server.tsx:\n * ```ts\n * import { wrapWithAnalytics } from \"@agent-native/core/server\";\n * return new Response(wrapWithAnalytics(body), { ... });\n * ```\n */\n\ndeclare const __AGENT_NATIVE_BUILD_GA_MEASUREMENT_ID__: string | undefined;\ndeclare const __AGENT_NATIVE_BUILD_GTM_CONTAINER_ID__: string | undefined;\n\nfunction normalizeMeasurementId(value: string | undefined): string | null {\n const trimmed = value?.trim();\n return trimmed ? trimmed : null;\n}\n\nfunction getViteBakedGaMeasurementId(): string | undefined {\n return typeof __AGENT_NATIVE_BUILD_GA_MEASUREMENT_ID__ === \"string\"\n ? __AGENT_NATIVE_BUILD_GA_MEASUREMENT_ID__\n : undefined;\n}\n\nfunction normalizeContainerId(value: string | undefined): string | null {\n const trimmed = value?.trim().toUpperCase();\n return trimmed && /^GTM-[A-Z0-9]+$/.test(trimmed) ? trimmed : null;\n}\n\nfunction getViteBakedGtmContainerId(): string | undefined {\n return typeof __AGENT_NATIVE_BUILD_GTM_CONTAINER_ID__ === \"string\"\n ? __AGENT_NATIVE_BUILD_GTM_CONTAINER_ID__\n : undefined;\n}\n\nfunction getGtmContainerId(): string | null {\n return (\n normalizeContainerId(process.env.GTM_CONTAINER_ID) ||\n normalizeContainerId(process.env.AGENT_NATIVE_BUILD_GTM_CONTAINER_ID) ||\n normalizeContainerId(getViteBakedGtmContainerId())\n );\n}\n\nfunction getGaMeasurementId(): string | null {\n return (\n normalizeMeasurementId(process.env.GA_MEASUREMENT_ID) ||\n normalizeMeasurementId(process.env.AGENT_NATIVE_BUILD_GA_MEASUREMENT_ID) ||\n normalizeMeasurementId(getViteBakedGaMeasurementId())\n );\n}\n\n/**\n * The exact JS body (no surrounding `<script>` tags) of the inline gtag config\n * block injected next to the gtag.js loader.\n * Returns `null` when GA is not configured.\n */\nexport function getGaInlineConfigScriptBody(): string | null {\n const id = getGaMeasurementId();\n if (!id) return null;\n const jsId = JSON.stringify(id);\n return (\n `window.dataLayer=window.dataLayer||[];` +\n `function gtag(){dataLayer.push(arguments);}` +\n `gtag('js',new Date());` +\n `gtag('config',${jsId});` +\n `if(typeof sessionStorage!=='undefined'&&sessionStorage.getItem('__an_signin')){` +\n `sessionStorage.removeItem('__an_signin');` +\n `gtag('event','sign_in');` +\n `}`\n );\n}\n\nfunction getGaScript(): string | null {\n const id = getGaMeasurementId();\n if (!id) return null;\n const srcId = encodeURIComponent(id);\n const inlineBody = getGaInlineConfigScriptBody();\n return (\n `<script async src=\"https://www.googletagmanager.com/gtag/js?id=${srcId}\"></script>` +\n `<script>${inlineBody}</script>`\n );\n}\n\nfunction getGtmHeadScript(containerId: string): string {\n const jsId = JSON.stringify(containerId);\n return `<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src='https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);})(window,document,'script','dataLayer',${jsId});</script>`;\n}\n\nfunction getGtmBodyFallback(containerId: string): string {\n const src = encodeURIComponent(containerId);\n return `<noscript><iframe src=\"https://www.googletagmanager.com/ns.html?id=${src}\" height=\"0\" width=\"0\" style=\"display:none;visibility:hidden\" title=\"Google Tag Manager\"></iframe></noscript>`;\n}\n\ntype AnalyticsInjection = {\n head: string;\n body: string;\n};\n\nfunction getAnalyticsInjection(): AnalyticsInjection | null {\n const containerId = getGtmContainerId();\n if (containerId) {\n return {\n head: getGtmHeadScript(containerId),\n body: getGtmBodyFallback(containerId),\n };\n }\n\n const gaScript = getGaScript();\n return gaScript ? { head: gaScript, body: \"\" } : null;\n}\n\nconst HEAD_CLOSE_PATTERN = /<\\/head>/i;\nconst BODY_OPEN_PATTERN = /<body\\b[^>]*>/i;\n\n/**\n * Add the configured analytics scripts to a complete HTML document.\n *\n * The normal app document is streamed through `wrapWithAnalytics`, but\n * framework-owned documents such as `/signup` are returned as strings by the\n * auth guard and need the same injection path.\n */\nexport function injectAnalyticsIntoHtml(html: string): string {\n const injection = getAnalyticsInjection();\n if (!injection) return html;\n\n const headCloseMatch = HEAD_CLOSE_PATTERN.exec(html);\n if (!headCloseMatch || headCloseMatch.index === undefined) return html;\n\n let output =\n html.slice(0, headCloseMatch.index) +\n injection.head +\n html.slice(headCloseMatch.index);\n\n if (injection.body) {\n const bodyOpenMatch = BODY_OPEN_PATTERN.exec(output);\n if (bodyOpenMatch && bodyOpenMatch.index !== undefined) {\n const bodyEnd = bodyOpenMatch.index + bodyOpenMatch[0].length;\n output =\n output.slice(0, bodyEnd) + injection.body + output.slice(bodyEnd);\n }\n }\n\n return output;\n}\n\nexport function wrapWithAnalytics(\n body: ReadableStream<Uint8Array>,\n): ReadableStream<Uint8Array> {\n const injection = getAnalyticsInjection();\n if (!injection) return body;\n\n const decoder = new TextDecoder();\n const encoder = new TextEncoder();\n let pending = \"\";\n let headInjected = false;\n let bodyInjected = !injection.body;\n\n return body.pipeThrough(\n new TransformStream<Uint8Array, Uint8Array>({\n transform(chunk, controller) {\n pending += decoder.decode(chunk, { stream: true });\n\n if (!headInjected) {\n const headCloseMatch = HEAD_CLOSE_PATTERN.exec(pending);\n if (!headCloseMatch || headCloseMatch.index === undefined) return;\n\n const headEnd = headCloseMatch.index + headCloseMatch[0].length;\n controller.enqueue(\n encoder.encode(\n pending.slice(0, headCloseMatch.index) +\n injection.head +\n pending.slice(headCloseMatch.index, headEnd),\n ),\n );\n pending = pending.slice(headEnd);\n headInjected = true;\n }\n\n if (!bodyInjected) {\n const bodyOpenMatch = BODY_OPEN_PATTERN.exec(pending);\n if (!bodyOpenMatch || bodyOpenMatch.index === undefined) return;\n\n const bodyEnd = bodyOpenMatch.index + bodyOpenMatch[0].length;\n controller.enqueue(\n encoder.encode(pending.slice(0, bodyEnd) + injection.body),\n );\n pending = pending.slice(bodyEnd);\n bodyInjected = true;\n }\n\n if (pending) {\n controller.enqueue(encoder.encode(pending));\n pending = \"\";\n }\n },\n flush(controller) {\n pending += decoder.decode();\n\n if (!headInjected) {\n const headCloseMatch = HEAD_CLOSE_PATTERN.exec(pending);\n if (headCloseMatch && headCloseMatch.index !== undefined) {\n const headEnd = headCloseMatch.index + headCloseMatch[0].length;\n controller.enqueue(\n encoder.encode(\n pending.slice(0, headCloseMatch.index) +\n injection.head +\n pending.slice(headCloseMatch.index, headEnd),\n ),\n );\n pending = pending.slice(headEnd);\n headInjected = true;\n }\n }\n\n if (headInjected && !bodyInjected) {\n const bodyOpenMatch = BODY_OPEN_PATTERN.exec(pending);\n if (bodyOpenMatch && bodyOpenMatch.index !== undefined) {\n const bodyEnd = bodyOpenMatch.index + bodyOpenMatch[0].length;\n controller.enqueue(\n encoder.encode(pending.slice(0, bodyEnd) + injection.body),\n );\n pending = pending.slice(bodyEnd);\n bodyInjected = true;\n }\n }\n\n if (pending) controller.enqueue(encoder.encode(pending));\n },\n }),\n );\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/server/auth.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/server/auth.ts"],"names":[],"mappings":"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"}
@@ -49,6 +49,7 @@ import { extractOAuthStateAppId } from "../shared/oauth-state.js";
49
49
  import { AGENT_NATIVE_SOCIAL_IMAGE_ALT, AGENT_NATIVE_SOCIAL_IMAGE_HEIGHT, AGENT_NATIVE_SOCIAL_IMAGE_PATH, AGENT_NATIVE_SOCIAL_IMAGE_TYPE, AGENT_NATIVE_SOCIAL_IMAGE_WIDTH, withAgentNativeSocialImageCacheBuster, } from "../shared/social-meta.js";
50
50
  import { normalizeWorkspaceAppAudience, workspaceAppAudienceFromEnv, workspaceAppRouteAccessFromEnv, } from "../shared/workspace-app-audience.js";
51
51
  import { isValidWorkspaceAppIdFormat } from "../shared/workspace-app-id.js";
52
+ import { injectAnalyticsIntoHtml } from "./analytics.js";
52
53
  import { signupAttributionFromCookieHeader } from "./attribution.js";
53
54
  import { getBetterAuth, getBetterAuthSync } from "./better-auth-instance.js";
54
55
  import { BUILDER_CONNECT_OWNER_COOKIE, BUILDER_CONNECT_PARAM, BUILDER_RELAY_PATH, BUILDER_RELAY_STATE_PARAM, BUILDER_STATE_PARAM, verifyBuilderCallbackStateAndGetOwner, verifyBuilderConnectTokenAndGetOwner, verifyBuilderPreviewRelayStateForCallback, } from "./builder-browser.js";
@@ -1166,16 +1167,16 @@ function injectLoginSocialImageMeta(loginHtml, event) {
1166
1167
  loginHtml.slice(headCloseIdx));
1167
1168
  }
1168
1169
  function loginHtmlResponse(loginHtml, event) {
1169
- return new Response(injectLoginSocialImageMeta(loginHtml, event), {
1170
+ return new Response(injectAnalyticsIntoHtml(injectLoginSocialImageMeta(loginHtml, event)), {
1170
1171
  status: 200,
1171
1172
  headers: {
1172
1173
  "Content-Type": "text/html; charset=utf-8",
1173
1174
  // The sign-in document is part of the public server shell. Keep it on the
1174
1175
  // same long-fresh/long-SWR CDN policy as React Router SSR so hosted
1175
1176
  // template roots do not invoke origin just to render anonymous login UI.
1176
- // The login HTML is env-INDEPENDENT (a Google-only app always renders a
1177
- // working button), so a cached copy is never "wrong" — never downgrade
1178
- // this to private/no-store.
1177
+ // The login markup is env-INDEPENDENT (a Google-only app always renders
1178
+ // a working button); the analytics script is public build configuration,
1179
+ // not user/session state. Never downgrade this to private/no-store.
1179
1180
  ...DEFAULT_SSR_CACHE_HEADERS,
1180
1181
  "X-Robots-Tag": "noindex, nofollow",
1181
1182
  },