@agent-native/core 0.145.8 → 0.146.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 (155) hide show
  1. package/corpus/README.md +1 -1
  2. package/corpus/templates/analytics/.agents/skills/turn-into-app/SKILL.md +41 -11
  3. package/corpus/templates/analytics/.agents/skills/turn-into-app/references/fresh-project.md +21 -2
  4. package/corpus/templates/analytics/actions/compose-dashboard.ts +2 -27
  5. package/corpus/templates/analytics/actions/get-sql-dashboard.ts +18 -3
  6. package/corpus/templates/analytics/actions/migrate-first-party-analytics-to-bigquery.ts +75 -24
  7. package/corpus/templates/analytics/actions/mutate-dashboard.ts +16 -24
  8. package/corpus/templates/analytics/actions/rename-dashboard.ts +2 -24
  9. package/corpus/templates/analytics/actions/reorder-dashboard-panels.ts +2 -24
  10. package/corpus/templates/analytics/actions/restore-dashboard-revision.ts +2 -25
  11. package/corpus/templates/analytics/actions/update-dashboard.ts +4 -32
  12. package/corpus/templates/analytics/app/components/layout/CommandPalette.tsx +1 -40
  13. package/corpus/templates/analytics/changelog/2026-08-07-analytics-migrations-now-use-bounded-pressure-aware-backgrou.md +6 -0
  14. package/corpus/templates/analytics/changelog/2026-08-07-language-selection-now-lives-in-settings-instead-of-the-comm.md +6 -0
  15. package/corpus/templates/analytics/changelog/2026-08-07-template-activity-charts-now-show-only-core-agent-native-app.md +6 -0
  16. package/corpus/templates/analytics/netlify.toml +7 -0
  17. package/corpus/templates/analytics/scripts/emit-netlify-dashboard-report-cron.ts +110 -0
  18. package/corpus/templates/analytics/server/jobs/analytics-bigquery-backfill.ts +450 -0
  19. package/corpus/templates/analytics/server/jobs/analytics-rollup-backfill.ts +2 -2
  20. package/corpus/templates/analytics/server/lib/analytics-rollup-lock.ts +4 -5
  21. package/corpus/templates/analytics/server/lib/dashboard-collab-sync.ts +77 -0
  22. package/corpus/templates/analytics/server/lib/demo-dashboards.ts +2 -23
  23. package/corpus/templates/analytics/server/lib/first-party-analytics-backend.ts +10 -4
  24. package/corpus/templates/analytics/server/lib/first-party-analytics-rollups.ts +4 -11
  25. package/corpus/templates/analytics/server/plugins/analytics-rollup-backfill-jobs.ts +2 -5
  26. package/corpus/templates/analytics/server/plugins/db.ts +42 -0
  27. package/corpus/templates/analytics/server/routes/api/analytics-bigquery/backfill.post.ts +55 -0
  28. package/corpus/templates/analytics/server/routes/api/dashboard-agent-context.json.get.ts +18 -4
  29. package/corpus/templates/assets/.agents/skills/turn-into-app/SKILL.md +41 -11
  30. package/corpus/templates/assets/.agents/skills/turn-into-app/references/fresh-project.md +21 -2
  31. package/corpus/templates/brain/.agents/skills/turn-into-app/SKILL.md +41 -11
  32. package/corpus/templates/brain/.agents/skills/turn-into-app/references/fresh-project.md +21 -2
  33. package/corpus/templates/brain/server/lib/connectors.ts +38 -14
  34. package/corpus/templates/calendar/.agents/skills/turn-into-app/SKILL.md +41 -11
  35. package/corpus/templates/calendar/.agents/skills/turn-into-app/references/fresh-project.md +21 -2
  36. package/corpus/templates/chat/.agents/skills/turn-into-app/SKILL.md +41 -11
  37. package/corpus/templates/chat/.agents/skills/turn-into-app/references/fresh-project.md +21 -2
  38. package/corpus/templates/clips/.agents/skills/turn-into-app/SKILL.md +41 -11
  39. package/corpus/templates/clips/.agents/skills/turn-into-app/references/fresh-project.md +21 -2
  40. package/corpus/templates/clips/app/components/player/video-player.tsx +1 -1
  41. package/corpus/templates/clips/changelog/2026-08-07-fixed-trimmed-clips-durations-so-the-main-player-display-mat.md +6 -0
  42. package/corpus/templates/clips/chrome-extension/STORE_DRAFT.md +1 -1
  43. package/corpus/templates/clips/chrome-extension/public/manifest.json +1 -1
  44. package/corpus/templates/content/.agents/skills/turn-into-app/SKILL.md +41 -11
  45. package/corpus/templates/content/.agents/skills/turn-into-app/references/fresh-project.md +21 -2
  46. package/corpus/templates/crm/.agents/skills/turn-into-app/SKILL.md +41 -11
  47. package/corpus/templates/crm/.agents/skills/turn-into-app/references/fresh-project.md +21 -2
  48. package/corpus/templates/design/.agents/skills/turn-into-app/SKILL.md +41 -11
  49. package/corpus/templates/design/.agents/skills/turn-into-app/references/fresh-project.md +21 -2
  50. package/corpus/templates/dispatch/.agents/skills/turn-into-app/SKILL.md +41 -11
  51. package/corpus/templates/dispatch/.agents/skills/turn-into-app/references/fresh-project.md +21 -2
  52. package/corpus/templates/dispatch/changelog/2026-08-07-language-selection-now-lives-in-settings-instead-of-the-disp.md +6 -0
  53. package/corpus/templates/factory/.agents/skills/turn-into-app/SKILL.md +41 -11
  54. package/corpus/templates/factory/.agents/skills/turn-into-app/references/fresh-project.md +21 -2
  55. package/corpus/templates/factory/server/plugins/factory-scheduler-job.ts +59 -22
  56. package/corpus/templates/forms/.agents/skills/turn-into-app/SKILL.md +41 -11
  57. package/corpus/templates/forms/.agents/skills/turn-into-app/references/fresh-project.md +21 -2
  58. package/corpus/templates/macros/.agents/skills/turn-into-app/SKILL.md +41 -11
  59. package/corpus/templates/macros/.agents/skills/turn-into-app/references/fresh-project.md +21 -2
  60. package/corpus/templates/mail/.agents/skills/turn-into-app/SKILL.md +41 -11
  61. package/corpus/templates/mail/.agents/skills/turn-into-app/references/fresh-project.md +21 -2
  62. package/corpus/templates/plan/.agents/skills/turn-into-app/SKILL.md +41 -11
  63. package/corpus/templates/plan/.agents/skills/turn-into-app/references/fresh-project.md +21 -2
  64. package/corpus/templates/slides/.agents/skills/image-generation-via-a2a/SKILL.md +10 -1
  65. package/corpus/templates/slides/.agents/skills/slide-images/SKILL.md +10 -3
  66. package/corpus/templates/slides/.agents/skills/turn-into-app/SKILL.md +41 -11
  67. package/corpus/templates/slides/.agents/skills/turn-into-app/references/fresh-project.md +21 -2
  68. package/corpus/templates/slides/actions/generate-image-api.ts +123 -0
  69. package/corpus/templates/slides/app/components/deck/DeckCard.tsx +10 -2
  70. package/corpus/templates/slides/app/components/editor/EditorSidebar.tsx +13 -0
  71. package/corpus/templates/slides/app/components/editor/GeneratingSlidePreview.tsx +5 -0
  72. package/corpus/templates/slides/app/components/editor/ImageGenPanel.tsx +1 -1
  73. package/corpus/templates/slides/app/components/presentation/PresentationView.tsx +5 -0
  74. package/corpus/templates/slides/app/components/presentation/PresenterView.tsx +5 -0
  75. package/corpus/templates/slides/app/pages/DeckEditor.tsx +3 -0
  76. package/corpus/templates/slides/app/pages/Presentation.tsx +3 -0
  77. package/corpus/templates/slides/app/pages/SharedPresentation.tsx +5 -0
  78. package/corpus/templates/slides/app/routes/slide.tsx +10 -5
  79. package/corpus/templates/slides/changelog/2026-08-07-deleting-a-deck-no-longer-freezes-the-slides-browser.md +6 -0
  80. package/corpus/templates/slides/changelog/2026-08-07-slide-previews-and-present-now-keep-deck-colors-consistent.md +6 -0
  81. package/corpus/templates/slides/changelog/2026-08-07-slides-verify-generated-images-are-persisted-on-the-target-s.md +6 -0
  82. package/corpus/templates/slides/server/db/schema.ts +1 -0
  83. package/corpus/templates/slides/server/handlers/share.ts +51 -3
  84. package/corpus/templates/slides/server/lib/slide-image-insertion.ts +141 -0
  85. package/corpus/templates/slides/server/plugins/agent-chat.ts +2 -0
  86. package/corpus/templates/slides/server/plugins/db.ts +5 -0
  87. package/corpus/templates/slides/shared/api.ts +2 -0
  88. package/corpus/templates/tasks/.agents/skills/turn-into-app/SKILL.md +41 -11
  89. package/corpus/templates/tasks/.agents/skills/turn-into-app/references/fresh-project.md +21 -2
  90. package/dist/cli/code-agent-executor.js +8 -3
  91. package/dist/client/AgentPanel.d.ts +10 -4
  92. package/dist/client/AgentPanel.js +29 -82
  93. package/dist/client/ConnectBuilderCard.d.ts +7 -7
  94. package/dist/client/ConnectBuilderCard.js +45 -20
  95. package/dist/collab/awareness.d.ts +2 -2
  96. package/dist/config.d.ts +9 -2
  97. package/dist/config.js +38 -2
  98. package/dist/db/client.d.ts +13 -1
  99. package/dist/db/client.js +76 -2
  100. package/dist/db/create-get-db.js +2 -2
  101. package/dist/db/migrations.js +22 -4
  102. package/dist/deploy/build.d.ts +1 -0
  103. package/dist/deploy/build.js +32 -23
  104. package/dist/notifications/routes.d.ts +3 -3
  105. package/dist/progress/routes.d.ts +1 -1
  106. package/dist/provider-api/actions/custom-provider-registration.d.ts +9 -9
  107. package/dist/provider-api/actions/provider-api.d.ts +8 -8
  108. package/dist/provider-api/corpus-jobs.d.ts +2 -2
  109. package/dist/scripts/docs/search.js +3 -2
  110. package/dist/server/agent-chat/prompt-resources.js +4 -3
  111. package/dist/server/agents-bundle.d.ts +20 -3
  112. package/dist/server/agents-bundle.js +57 -30
  113. package/dist/server/better-auth-instance.js +2 -2
  114. package/dist/server/builder-browser.d.ts +34 -0
  115. package/dist/server/builder-browser.js +179 -0
  116. package/dist/server/core-routes-plugin.d.ts +5 -0
  117. package/dist/server/core-routes-plugin.js +24 -8
  118. package/dist/server/index.d.ts +1 -1
  119. package/dist/server/index.js +1 -1
  120. package/dist/shared/cache-control.d.ts +2 -2
  121. package/dist/shared/cache-control.js +2 -2
  122. package/dist/shared/runtime-config.js +1 -1
  123. package/dist/templates/chat/.agents/skills/turn-into-app/SKILL.md +41 -11
  124. package/dist/templates/chat/.agents/skills/turn-into-app/references/fresh-project.md +21 -2
  125. package/dist/templates/default/.agents/skills/turn-into-app/SKILL.md +41 -11
  126. package/dist/templates/default/.agents/skills/turn-into-app/references/fresh-project.md +21 -2
  127. package/dist/templates/headless/.agents/skills/turn-into-app/SKILL.md +41 -11
  128. package/dist/templates/headless/.agents/skills/turn-into-app/references/fresh-project.md +21 -2
  129. package/dist/templates/workspace-core/.agents/skills/turn-into-app/SKILL.md +41 -11
  130. package/dist/templates/workspace-core/.agents/skills/turn-into-app/references/fresh-project.md +21 -2
  131. package/dist/vite/agent-native-config-loader.d.ts +10 -0
  132. package/dist/vite/agent-native-config-loader.js +56 -0
  133. package/dist/vite/agents-bundle-plugin.d.ts +5 -1
  134. package/dist/vite/agents-bundle-plugin.js +29 -6
  135. package/dist/vite/client.d.ts +4 -2
  136. package/dist/vite/client.js +17 -50
  137. package/dist/vite/index.d.ts +2 -2
  138. package/dist/vite/index.js +1 -1
  139. package/docs/content/agent-native-config.mdx +43 -17
  140. package/docs/content/drop-in-agent.mdx +3 -3
  141. package/docs/content/environment-variables.mdx +1 -1
  142. package/docs/content/getting-started-actions.mdx +1 -2
  143. package/docs/content/getting-started-pages.mdx +1 -2
  144. package/docs/content/getting-started.mdx +0 -4
  145. package/docs/content/what-is-agent-native.mdx +4 -4
  146. package/package.json +1 -1
  147. package/src/templates/chat/.agents/skills/turn-into-app/SKILL.md +41 -11
  148. package/src/templates/chat/.agents/skills/turn-into-app/references/fresh-project.md +21 -2
  149. package/src/templates/default/.agents/skills/turn-into-app/SKILL.md +41 -11
  150. package/src/templates/default/.agents/skills/turn-into-app/references/fresh-project.md +21 -2
  151. package/src/templates/headless/.agents/skills/turn-into-app/SKILL.md +41 -11
  152. package/src/templates/headless/.agents/skills/turn-into-app/references/fresh-project.md +21 -2
  153. package/src/templates/workspace-core/.agents/skills/turn-into-app/SKILL.md +41 -11
  154. package/src/templates/workspace-core/.agents/skills/turn-into-app/references/fresh-project.md +21 -2
  155. package/docs/content/getting-started-database.mdx +0 -173
@@ -1,9 +1,4 @@
1
1
  import { defineAction, embedApp } from "@agent-native/core";
2
- import {
3
- hasCollabState,
4
- applyText,
5
- seedFromText,
6
- } from "@agent-native/core/collab";
7
2
  import {
8
3
  getRequestUserEmail,
9
4
  getRequestOrgId,
@@ -13,6 +8,7 @@ import { z } from "zod";
13
8
 
14
9
  import { interpolate } from "../app/pages/adhoc/sql-dashboard/interpolate";
15
10
  import { dryRunQuery } from "../server/lib/bigquery";
11
+ import { queueDashboardCollabSync } from "../server/lib/dashboard-collab-sync";
16
12
  import { validateFirstPartyDashboardTimeScope } from "../server/lib/dashboard-time-scope";
17
13
  import {
18
14
  upsertDashboard,
@@ -536,30 +532,6 @@ function opCanChangePanelSql(op: JsonOp): boolean {
536
532
  );
537
533
  }
538
534
 
539
- /**
540
- * Push a config update through the collab layer so open dashboard editors
541
- * receive the change in real time. Seeds the collab state if it doesn't
542
- * exist yet (e.g. dashboard was created before the collab plugin was added).
543
- */
544
- async function syncToCollab(
545
- dashboardId: string,
546
- config: Record<string, unknown>,
547
- requestSource?: string,
548
- ): Promise<void> {
549
- const docId = `dash-${dashboardId}`;
550
- const configStr = JSON.stringify(config);
551
- try {
552
- const exists = await hasCollabState(docId);
553
- if (exists) {
554
- await applyText(docId, configStr, "content", requestSource);
555
- } else {
556
- await seedFromText(docId, configStr);
557
- }
558
- } catch {
559
- // Collab sync is best-effort — the SQL write is the source of truth
560
- }
561
- }
562
-
563
535
  function isAgentCaller(caller: string | undefined): boolean {
564
536
  return caller === "tool" || caller === "mcp" || caller === "a2a";
565
537
  }
@@ -642,7 +614,7 @@ export default defineAction({
642
614
  const sqlError = await validatePanelSql(args.config);
643
615
  if (sqlError) throw new Error(sqlError);
644
616
  await upsertDashboard(dashboardId, "sql", args.config, ctx);
645
- await syncToCollab(
617
+ queueDashboardCollabSync(
646
618
  dashboardId,
647
619
  args.config,
648
620
  isAgentCaller(actionContext?.caller) ? "agent" : undefined,
@@ -675,7 +647,7 @@ export default defineAction({
675
647
  },
676
648
  );
677
649
  const root = saved.config as Record<string, unknown>;
678
- await syncToCollab(
650
+ queueDashboardCollabSync(
679
651
  dashboardId,
680
652
  root,
681
653
  isAgentCaller(actionContext?.caller) ? "agent" : undefined,
@@ -721,7 +693,7 @@ export default defineAction({
721
693
  },
722
694
  );
723
695
  const root = saved.config as Record<string, unknown>;
724
- await syncToCollab(
696
+ queueDashboardCollabSync(
725
697
  dashboardId,
726
698
  root,
727
699
  isAgentCaller(actionContext?.caller) ? "agent" : undefined,
@@ -1,6 +1,6 @@
1
1
  import { ChangelogDialog } from "@agent-native/core/client/changelog";
2
2
  import { callAction, useChangeVersions } from "@agent-native/core/client/hooks";
3
- import { LanguagePicker, useT } from "@agent-native/core/client/i18n";
3
+ import { useT } from "@agent-native/core/client/i18n";
4
4
  import { useOrgRole } from "@agent-native/core/client/org";
5
5
  import {
6
6
  IconFlask,
@@ -11,7 +11,6 @@ import {
11
11
  IconMoon,
12
12
  IconHistory,
13
13
  IconHierarchy2,
14
- IconLanguage,
15
14
  IconRefresh,
16
15
  IconSettings,
17
16
  } from "@tabler/icons-react";
@@ -41,13 +40,6 @@ import {
41
40
  CommandGroup,
42
41
  CommandItem,
43
42
  } from "@/components/ui/command";
44
- import {
45
- Dialog,
46
- DialogContent,
47
- DialogHeader,
48
- DialogTitle,
49
- } from "@/components/ui/dialog";
50
- import { Label } from "@/components/ui/label";
51
43
  import { Skeleton } from "@/components/ui/skeleton";
52
44
  import { useReplayStorageStatus } from "@/hooks/use-replay-storage-status";
53
45
  import { dashboardCacheScope } from "@/lib/prefetch-keys";
@@ -263,7 +255,6 @@ export function CommandPalette() {
263
255
  const dashboardScope = dashboardCacheScope(auth);
264
256
  const [open, setOpen] = useState(false);
265
257
  const [changelogOpen, setChangelogOpen] = useState(false);
266
- const [languageOpen, setLanguageOpen] = useState(false);
267
258
  const [searchQuery, setSearchQuery] = useState("");
268
259
  const [selectedCommand, setSelectedCommand] = useState("");
269
260
  const commandListRef = useRef<HTMLDivElement>(null);
@@ -553,25 +544,6 @@ export function CommandPalette() {
553
544
  key="appearance"
554
545
  heading={t("commandPalette.groupAppearance")}
555
546
  >
556
- <CommandItem
557
- value={`appearance:language:${t("settings.languageTitle")}`}
558
- onSelect={() => {
559
- setOpen(false);
560
- setLanguageOpen(true);
561
- }}
562
- keywords={commandPaletteKeywords(
563
- t("settings.languageTitle"),
564
- t("settings.languageLabel"),
565
- "language",
566
- "locale",
567
- "translation",
568
- "internationalization",
569
- "i18n",
570
- )}
571
- >
572
- <IconLanguage className="me-2 h-4 w-4 text-muted-foreground" />
573
- {t("settings.languageTitle")}
574
- </CommandItem>
575
547
  <CommandItem
576
548
  value={`appearance:theme:${
577
549
  isDark
@@ -678,17 +650,6 @@ export function CommandPalette() {
678
650
  onOpenChange={setChangelogOpen}
679
651
  markdown={changelog}
680
652
  />
681
- <Dialog open={languageOpen} onOpenChange={setLanguageOpen}>
682
- <DialogContent className="max-w-sm">
683
- <DialogHeader>
684
- <DialogTitle>{t("settings.languageTitle")}</DialogTitle>
685
- </DialogHeader>
686
- <div className="space-y-1.5">
687
- <Label>{t("settings.languageLabel")}</Label>
688
- <LanguagePicker label={t("settings.languageLabel")} />
689
- </div>
690
- </DialogContent>
691
- </Dialog>
692
653
  </>
693
654
  );
694
655
  }
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: fixed
3
+ date: 2026-08-07
4
+ ---
5
+
6
+ Analytics migrations now use bounded, pressure-aware background jobs
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: changed
3
+ date: 2026-08-07
4
+ ---
5
+
6
+ Language selection now lives in Settings instead of the command menu.
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: fixed
3
+ date: 2026-08-07
4
+ ---
5
+
6
+ Template activity charts now show only core Agent Native apps
@@ -18,6 +18,13 @@ AGENT_PROD_CODE_EXECUTION = "sandboxed"
18
18
  # turns on the durable background worker instead of the short foreground wall.
19
19
  AGENT_CHAT_DURABLE_BACKGROUND = "true"
20
20
 
21
+ [context.production.environment]
22
+ # Analytics owns its schema at release time (`migrate:production` above), so
23
+ # production request functions skip migrations. Preview functions still run
24
+ # request-path migrations because previews do not run the production release
25
+ # migration step.
26
+ AGENT_NATIVE_RELEASE_MIGRATIONS = "1"
27
+
21
28
  # A2A delegation calls run a full agent loop (LLM + tool calls + DB queries).
22
29
  # Hosted agent chat uses a soft timeout before this function timeout so the
23
30
  # hidden auto-continuation path can hand off before Netlify kills the function.
@@ -26,6 +26,10 @@ const ROLLUP_SCHEDULED_NAME = "analytics-rollup-backfill-cron";
26
26
  const ROLLUP_WORKER_NAME = "analytics-rollup-backfill-background";
27
27
  const ROLLUP_ROUTE_PATH = "/api/analytics-rollups/backfill";
28
28
  const ROLLUP_SCHEDULE = "*/15 * * * *";
29
+ const BIGQUERY_SCHEDULED_NAME = "analytics-bigquery-backfill-cron";
30
+ const BIGQUERY_WORKER_NAME = "analytics-bigquery-backfill-background";
31
+ const BIGQUERY_ROUTE_PATH = "/api/analytics-bigquery/backfill";
32
+ const BIGQUERY_SCHEDULE = "* * * * *";
29
33
  const RETENTION_SCHEDULED_NAME = "session-replay-retention-cron";
30
34
  const RETENTION_WORKER_NAME = "session-replay-retention-sweep-background";
31
35
  const RETENTION_ROUTE_PATH = "/api/session-replay/retention";
@@ -499,6 +503,106 @@ export const config = {
499
503
  writeFileSync(path.join(dest, `${ROLLUP_WORKER_NAME}.mjs`), source);
500
504
  }
501
505
 
506
+ function emitBigQueryScheduledTrigger(token: string) {
507
+ const dest = path.join(FUNCTIONS_DIR, BIGQUERY_SCHEDULED_NAME);
508
+ rmSync(dest, { recursive: true, force: true });
509
+ ensureDir(dest);
510
+
511
+ const source = `const WORKER_PATH = "/.netlify/functions/${BIGQUERY_WORKER_NAME}";
512
+ const CRON_TOKEN = ${JSON.stringify(token)};
513
+
514
+ function siteOrigin(request) {
515
+ const configured = process.env.URL || process.env.DEPLOY_URL;
516
+ if (configured) return configured;
517
+ const url = new URL(request.url);
518
+ return url.origin;
519
+ }
520
+
521
+ export default async function handler(request) {
522
+ const url = new URL(WORKER_PATH, siteOrigin(request));
523
+ const response = await fetch(url.toString(), {
524
+ method: "POST",
525
+ headers: {
526
+ "content-type": "application/json",
527
+ "x-agent-native-analytics-bigquery-cron": CRON_TOKEN,
528
+ },
529
+ body: JSON.stringify({ scheduled: true }),
530
+ });
531
+
532
+ if (!response.ok && response.status !== 202) {
533
+ console.error(
534
+ "[analytics-bigquery-backfill-cron] Background backfill trigger failed:",
535
+ response.status,
536
+ );
537
+ }
538
+ }
539
+
540
+ export const config = {
541
+ name: "analytics BigQuery backfill cron trigger",
542
+ generator: "agent-native analytics build",
543
+ schedule: ${JSON.stringify(BIGQUERY_SCHEDULE)},
544
+ };
545
+ `;
546
+
547
+ writeFileSync(path.join(dest, `${BIGQUERY_SCHEDULED_NAME}.mjs`), source);
548
+ }
549
+
550
+ function emitBigQueryBackgroundWorker(token: string) {
551
+ const dest = path.join(FUNCTIONS_DIR, BIGQUERY_WORKER_NAME);
552
+ rmSync(dest, { recursive: true, force: true });
553
+ cloneServerBundleForFunction(SERVER_DIR, dest);
554
+ rmSync(path.join(dest, "server.mjs"), { force: true });
555
+
556
+ const source = `globalThis.__AGENT_NATIVE_BACKGROUND_RUNTIME__ = true;
557
+ globalThis.__AGENT_NATIVE_LOW_CONNECTION_BACKGROUND_RUNTIME__ = true;
558
+ globalThis.__AGENT_NATIVE_ANALYTICS_BIGQUERY_BACKFILL_SCHEDULED_RUNTIME__ = true;
559
+
560
+ const CRON_TOKEN = ${JSON.stringify(token)};
561
+ const ROUTE_PATH = ${JSON.stringify(BIGQUERY_ROUTE_PATH)};
562
+ let cachedHandler;
563
+
564
+ function timingSafeEquals(a, b) {
565
+ if (a.length !== b.length) return false;
566
+ let diff = 0;
567
+ for (let i = 0; i < a.length; i += 1) {
568
+ diff |= a.charCodeAt(i) ^ b.charCodeAt(i);
569
+ }
570
+ return diff === 0;
571
+ }
572
+
573
+ export default async function handler(request, context) {
574
+ const token = request.headers.get("x-agent-native-analytics-bigquery-cron") || "";
575
+ if (!timingSafeEquals(token, CRON_TOKEN)) {
576
+ return new Response("Unauthorized", { status: 401 });
577
+ }
578
+
579
+ cachedHandler ??= (await import("./main.mjs")).default;
580
+ const url = new URL(request.url);
581
+ url.pathname = ROUTE_PATH;
582
+ url.search = "";
583
+
584
+ const rewritten = new Request(url.toString(), {
585
+ method: "POST",
586
+ headers: new Headers({ "content-type": "application/json" }),
587
+ body: JSON.stringify({ scheduled: true }),
588
+ });
589
+
590
+ return await cachedHandler(rewritten, context);
591
+ }
592
+
593
+ export const config = {
594
+ name: "analytics BigQuery backfill background sweep",
595
+ generator: "agent-native analytics build",
596
+ background: true,
597
+ nodeBundler: "none",
598
+ includedFiles: ["**"],
599
+ preferStatic: false,
600
+ };
601
+ `;
602
+
603
+ writeFileSync(path.join(dest, `${BIGQUERY_WORKER_NAME}.mjs`), source);
604
+ }
605
+
502
606
  function emitRetentionScheduledTrigger(token: string) {
503
607
  const dest = path.join(FUNCTIONS_DIR, RETENTION_SCHEDULED_NAME);
504
608
  rmSync(dest, { recursive: true, force: true });
@@ -621,6 +725,7 @@ function main(): void {
621
725
  const alertToken = randomBytes(32).toString("hex");
622
726
  const uptimeToken = randomBytes(32).toString("hex");
623
727
  const rollupToken = randomBytes(32).toString("hex");
728
+ const bigQueryToken = randomBytes(32).toString("hex");
624
729
  const retentionToken = randomBytes(32).toString("hex");
625
730
  emitScheduledTrigger(token);
626
731
  emitBackgroundWorker(token);
@@ -630,6 +735,8 @@ function main(): void {
630
735
  emitUptimeBackgroundWorker(uptimeToken);
631
736
  emitRollupScheduledTrigger(rollupToken);
632
737
  emitRollupBackgroundWorker(rollupToken);
738
+ emitBigQueryScheduledTrigger(bigQueryToken);
739
+ emitBigQueryBackgroundWorker(bigQueryToken);
633
740
  emitRetentionScheduledTrigger(retentionToken);
634
741
  emitRetentionBackgroundWorker(retentionToken);
635
742
  console.log(
@@ -644,6 +751,9 @@ function main(): void {
644
751
  console.log(
645
752
  `[analytics-rollup-backfill-cron] Emitted Netlify scheduled trigger "${ROLLUP_SCHEDULED_NAME}" (${ROLLUP_SCHEDULE}) and background worker "${ROLLUP_WORKER_NAME}".`,
646
753
  );
754
+ console.log(
755
+ `[analytics-bigquery-backfill-cron] Emitted Netlify scheduled trigger "${BIGQUERY_SCHEDULED_NAME}" (${BIGQUERY_SCHEDULE}) and background worker "${BIGQUERY_WORKER_NAME}".`,
756
+ );
647
757
  console.log(
648
758
  `[session-replay-retention-cron] Emitted Netlify scheduled trigger "${RETENTION_SCHEDULED_NAME}" (${RETENTION_SCHEDULE}) and background worker "${RETENTION_WORKER_NAME}".`,
649
759
  );