@agent-native/core 0.109.0 → 0.109.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 (125) hide show
  1. package/corpus/README.md +2 -2
  2. package/corpus/core/CHANGELOG.md +7 -0
  3. package/corpus/core/package.json +1 -1
  4. package/corpus/core/src/a2a/client.ts +24 -2
  5. package/corpus/core/src/a2a/correlation.ts +50 -0
  6. package/corpus/core/src/a2a/handlers.ts +140 -14
  7. package/corpus/core/src/a2a/index.ts +1 -0
  8. package/corpus/core/src/a2a/invoke.ts +10 -1
  9. package/corpus/core/src/a2a/task-store.ts +146 -6
  10. package/corpus/core/src/a2a/types.ts +16 -0
  11. package/corpus/core/src/action.ts +2 -0
  12. package/corpus/core/src/agent/production-agent.ts +23 -0
  13. package/corpus/core/src/client/use-run-stuck-detection.ts +27 -1
  14. package/corpus/core/src/db/client.ts +55 -0
  15. package/corpus/core/src/observability/traces.ts +172 -19
  16. package/corpus/core/src/scripts/call-agent.ts +53 -2
  17. package/corpus/core/src/server/agent-chat/action-filters-a2a.ts +72 -25
  18. package/corpus/core/src/server/agent-chat-plugin.ts +107 -6
  19. package/corpus/core/src/templates/workspace-core/.agents/skills/a2a-protocol/SKILL.md +21 -0
  20. package/corpus/core/src/templates/workspace-core/.agents/skills/observability/SKILL.md +7 -1
  21. package/corpus/core/src/templates/workspace-core/.agents/skills/tracking/SKILL.md +1 -1
  22. package/corpus/templates/analytics/actions/query-agent-native-analytics.ts +1 -1
  23. package/corpus/templates/analytics/changelog/2026-07-17-analytics-now-includes-a-default-alert-for-spikes-in-stuck-agent-chats.md +6 -0
  24. package/corpus/templates/analytics/docs/schemas/first-party-analytics.md +23 -14
  25. package/corpus/templates/analytics/docs/schemas/tracked-events.md +5 -1
  26. package/corpus/templates/analytics/server/jobs/analytics-alerts.ts +3 -3
  27. package/corpus/templates/analytics/server/lib/analytics-alerts.ts +209 -87
  28. package/corpus/templates/clips/actions/finalize-recording.ts +541 -62
  29. package/corpus/templates/clips/app/components/player/playback-comment-overlay.tsx +17 -2
  30. package/corpus/templates/clips/app/components/player/video-player.tsx +14 -2
  31. package/corpus/templates/clips/app/components/recorder/recorder-engine.ts +2 -2
  32. package/corpus/templates/clips/app/routes/r.$recordingId.tsx +1 -1
  33. package/corpus/templates/clips/app/routes/record.tsx +3 -3
  34. package/corpus/templates/clips/app/routes/share.$shareId.tsx +6 -3
  35. package/corpus/templates/clips/changelog/2026-07-17-clips-now-retries-storage-verification-in-the-background-ins.md +6 -0
  36. package/corpus/templates/clips/changelog/2026-07-17-fixed-broken-thumbnail-icons-appearing-over-playable-clip-em.md +6 -0
  37. package/corpus/templates/clips/changelog/2026-07-17-playback-comments-stay-readable-at-faster-playback-speeds.md +6 -0
  38. package/corpus/templates/clips/chrome-extension/src/finalize-recovery.ts +3 -0
  39. package/corpus/templates/clips/chrome-extension/src/offscreen.ts +3 -3
  40. package/corpus/templates/clips/desktop/src/app.tsx +18 -6
  41. package/corpus/templates/clips/desktop/src/lib/recorder.ts +111 -13
  42. package/corpus/templates/clips/desktop/src/lib/upload-verification.ts +16 -7
  43. package/corpus/templates/clips/desktop/src-tauri/src/lib.rs +2 -4
  44. package/corpus/templates/clips/desktop/src-tauri/src/native_screen/live_upload.rs +32 -15
  45. package/corpus/templates/clips/desktop/src-tauri/src/native_screen.rs +45 -18
  46. package/corpus/templates/clips/server/jobs/media-verification.ts +130 -0
  47. package/corpus/templates/clips/server/lib/builder-media-compression.ts +15 -0
  48. package/corpus/templates/clips/server/lib/media-verification-state.ts +38 -0
  49. package/corpus/templates/clips/server/lib/player-thumbnail-url.ts +31 -0
  50. package/corpus/templates/clips/server/lib/post-finalize-dispatch.ts +10 -3
  51. package/corpus/templates/clips/server/plugins/auth.ts +5 -5
  52. package/corpus/templates/clips/server/plugins/calendar-jobs.ts +2 -0
  53. package/corpus/templates/clips/server/routes/api/_agent-native-background/post-finalize-worker.post.ts +12 -2
  54. package/corpus/templates/clips/server/routes/api/public-recording.get.ts +6 -1
  55. package/corpus/templates/clips/server/routes/api/thumbnail/[recordingId].get.ts +340 -0
  56. package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/abort.post.ts +24 -7
  57. package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/chunk.post.ts +91 -7
  58. package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/status.get.ts +14 -0
  59. package/corpus/templates/clips/shared/finalize-recovery.ts +61 -2
  60. package/corpus/templates/clips/shared/share-meta.ts +1 -1
  61. package/dist/a2a/client.d.ts +11 -2
  62. package/dist/a2a/client.d.ts.map +1 -1
  63. package/dist/a2a/client.js +16 -3
  64. package/dist/a2a/client.js.map +1 -1
  65. package/dist/a2a/correlation.d.ts +10 -0
  66. package/dist/a2a/correlation.d.ts.map +1 -0
  67. package/dist/a2a/correlation.js +40 -0
  68. package/dist/a2a/correlation.js.map +1 -0
  69. package/dist/a2a/handlers.d.ts.map +1 -1
  70. package/dist/a2a/handlers.js +100 -15
  71. package/dist/a2a/handlers.js.map +1 -1
  72. package/dist/a2a/index.d.ts +1 -1
  73. package/dist/a2a/index.d.ts.map +1 -1
  74. package/dist/a2a/index.js.map +1 -1
  75. package/dist/a2a/invoke.d.ts +4 -1
  76. package/dist/a2a/invoke.d.ts.map +1 -1
  77. package/dist/a2a/invoke.js +3 -0
  78. package/dist/a2a/invoke.js.map +1 -1
  79. package/dist/a2a/task-store.d.ts +12 -1
  80. package/dist/a2a/task-store.d.ts.map +1 -1
  81. package/dist/a2a/task-store.js +96 -6
  82. package/dist/a2a/task-store.js.map +1 -1
  83. package/dist/a2a/types.d.ts +15 -0
  84. package/dist/a2a/types.d.ts.map +1 -1
  85. package/dist/a2a/types.js.map +1 -1
  86. package/dist/action.d.ts +2 -0
  87. package/dist/action.d.ts.map +1 -1
  88. package/dist/action.js.map +1 -1
  89. package/dist/agent/production-agent.d.ts +9 -0
  90. package/dist/agent/production-agent.d.ts.map +1 -1
  91. package/dist/agent/production-agent.js +14 -0
  92. package/dist/agent/production-agent.js.map +1 -1
  93. package/dist/client/use-run-stuck-detection.d.ts.map +1 -1
  94. package/dist/client/use-run-stuck-detection.js +25 -1
  95. package/dist/client/use-run-stuck-detection.js.map +1 -1
  96. package/dist/collab/routes.d.ts +1 -1
  97. package/dist/collab/struct-routes.d.ts +1 -1
  98. package/dist/db/client.d.ts +7 -0
  99. package/dist/db/client.d.ts.map +1 -1
  100. package/dist/db/client.js +33 -0
  101. package/dist/db/client.js.map +1 -1
  102. package/dist/observability/routes.d.ts +5 -5
  103. package/dist/observability/traces.d.ts +9 -0
  104. package/dist/observability/traces.d.ts.map +1 -1
  105. package/dist/observability/traces.js +137 -19
  106. package/dist/observability/traces.js.map +1 -1
  107. package/dist/resources/handlers.d.ts +2 -2
  108. package/dist/scripts/call-agent.d.ts.map +1 -1
  109. package/dist/scripts/call-agent.js +35 -3
  110. package/dist/scripts/call-agent.js.map +1 -1
  111. package/dist/secrets/routes.d.ts +9 -9
  112. package/dist/server/agent-chat/action-filters-a2a.d.ts +18 -2
  113. package/dist/server/agent-chat/action-filters-a2a.d.ts.map +1 -1
  114. package/dist/server/agent-chat/action-filters-a2a.js +35 -7
  115. package/dist/server/agent-chat/action-filters-a2a.js.map +1 -1
  116. package/dist/server/agent-chat-plugin.d.ts.map +1 -1
  117. package/dist/server/agent-chat-plugin.js +93 -6
  118. package/dist/server/agent-chat-plugin.js.map +1 -1
  119. package/dist/templates/workspace-core/.agents/skills/a2a-protocol/SKILL.md +21 -0
  120. package/dist/templates/workspace-core/.agents/skills/observability/SKILL.md +7 -1
  121. package/dist/templates/workspace-core/.agents/skills/tracking/SKILL.md +1 -1
  122. package/package.json +1 -1
  123. package/src/templates/workspace-core/.agents/skills/a2a-protocol/SKILL.md +21 -0
  124. package/src/templates/workspace-core/.agents/skills/observability/SKILL.md +7 -1
  125. package/src/templates/workspace-core/.agents/skills/tracking/SKILL.md +1 -1
@@ -135,6 +135,12 @@ function nowIso(): string {
135
135
 
136
136
  const ALERT_RULE_RUNNING_STALE_MS = 15 * 60 * 1000;
137
137
  const DEFAULT_HTTP_5XX_ALERT_ID_PREFIX = "default-http-5xx-spike";
138
+ const DEFAULT_AGENT_CHAT_STUCK_ALERT_ID_PREFIX =
139
+ "default-agent-chat-stuck-spike";
140
+ const DEFAULT_AGENT_CHAT_STUCK_ALERT_THRESHOLD = 3;
141
+ const DEFAULT_AGENT_CHAT_STUCK_ALERT_WINDOW_MINUTES = 10;
142
+ const DEFAULT_AGENT_CHAT_STUCK_ALERT_COOLDOWN_MINUTES = 60;
143
+ const DEFAULT_ALERT_SCOPE_PAGE_SIZE = 500;
138
144
  const ALERT_RULE_DEFAULTS_KEY = "analytics-alert-rule-defaults";
139
145
 
140
146
  function safeJsonParse<T>(raw: unknown, fallback: T): T {
@@ -296,6 +302,14 @@ function defaultHttp5xxAlertEnabled(): boolean {
296
302
  return currentDeployHostname() === "analytics.agent-native.com";
297
303
  }
298
304
 
305
+ function defaultAgentChatStuckAlertEnabled(): boolean {
306
+ const configured = boolEnv(
307
+ "ANALYTICS_DEFAULT_AGENT_CHAT_STUCK_ALERT_ENABLED",
308
+ );
309
+ if (configured !== null) return configured;
310
+ return currentDeployHostname() === "analytics.agent-native.com";
311
+ }
312
+
299
313
  function envInt(name: string, fallback: number, min: number, max: number) {
300
314
  const raw = process.env[name]?.trim();
301
315
  if (!raw) return fallback;
@@ -305,18 +319,30 @@ function envInt(name: string, fallback: number, min: number, max: number) {
305
319
  : fallback;
306
320
  }
307
321
 
308
- function defaultHttp5xxAlertId(ownerEmail: string, orgId: string | null) {
322
+ function defaultAlertId(
323
+ prefix: string,
324
+ ownerEmail: string,
325
+ orgId: string | null,
326
+ ) {
309
327
  const hash = createHash("sha256")
310
328
  .update(`${ownerEmail.toLowerCase()}|${orgId ?? ""}`)
311
329
  .digest("hex")
312
330
  .slice(0, 10);
313
- return `${DEFAULT_HTTP_5XX_ALERT_ID_PREFIX}-${hash}`;
331
+ return `${prefix}-${hash}`;
314
332
  }
315
333
 
316
- async function defaultHttp5xxAlertScopes(): Promise<AccessCtx[]> {
334
+ async function defaultAnalyticsAlertScopePage(offset: number): Promise<{
335
+ scopes: AccessCtx[];
336
+ hasMore: boolean;
337
+ }> {
317
338
  const ownerEmail = process.env.ANALYTICS_DEFAULT_ALERT_OWNER_EMAIL?.trim();
318
339
  const orgId = process.env.ANALYTICS_DEFAULT_ALERT_ORG_ID?.trim() || null;
319
- if (ownerEmail) return [{ email: ownerEmail, orgId }];
340
+ if (ownerEmail) {
341
+ return {
342
+ scopes: offset === 0 ? [{ email: ownerEmail, orgId }] : [],
343
+ hasMore: false,
344
+ };
345
+ }
320
346
 
321
347
  const db = getDb() as any;
322
348
  const rows = await db
@@ -326,7 +352,16 @@ async function defaultHttp5xxAlertScopes(): Promise<AccessCtx[]> {
326
352
  })
327
353
  .from(schema.analyticsPublicKeys)
328
354
  .where(isNull(schema.analyticsPublicKeys.revokedAt))
329
- .limit(1000);
355
+ .groupBy(
356
+ schema.analyticsPublicKeys.ownerEmail,
357
+ schema.analyticsPublicKeys.orgId,
358
+ )
359
+ .orderBy(
360
+ asc(schema.analyticsPublicKeys.ownerEmail),
361
+ asc(schema.analyticsPublicKeys.orgId),
362
+ )
363
+ .limit(DEFAULT_ALERT_SCOPE_PAGE_SIZE)
364
+ .offset(offset);
330
365
 
331
366
  const seen = new Set<string>();
332
367
  const scopes: AccessCtx[] = [];
@@ -342,7 +377,10 @@ async function defaultHttp5xxAlertScopes(): Promise<AccessCtx[]> {
342
377
  seen.add(key);
343
378
  scopes.push({ email, orgId: scopeOrgId });
344
379
  }
345
- return scopes;
380
+ return {
381
+ scopes,
382
+ hasMore: rows.length === DEFAULT_ALERT_SCOPE_PAGE_SIZE,
383
+ };
346
384
  }
347
385
 
348
386
  function rowToRule(row: any): AnalyticsAlertRule {
@@ -517,10 +555,20 @@ export async function deleteAnalyticsAlertRule(
517
555
  });
518
556
  }
519
557
  const db = getDb() as any;
520
- await db.delete(schema.analyticsAlertRules).where(ownerWhere(ctx, id));
558
+ const seededDefault =
559
+ id.startsWith(`${DEFAULT_HTTP_5XX_ALERT_ID_PREFIX}-`) ||
560
+ id.startsWith(`${DEFAULT_AGENT_CHAT_STUCK_ALERT_ID_PREFIX}-`);
561
+ if (seededDefault) {
562
+ await db
563
+ .update(schema.analyticsAlertRules)
564
+ .set({ enabled: false, updatedAt: nowIso() })
565
+ .where(ownerWhere(ctx, id));
566
+ } else {
567
+ await db.delete(schema.analyticsAlertRules).where(ownerWhere(ctx, id));
568
+ }
521
569
  recordChange({
522
570
  source: "analytics-alert-rules",
523
- type: "delete",
571
+ type: seededDefault ? "change" : "delete",
524
572
  key: existing.id,
525
573
  owner: existing.ownerEmail,
526
574
  orgId: existing.orgId ?? undefined,
@@ -529,6 +577,20 @@ export async function deleteAnalyticsAlertRule(
529
577
 
530
578
  const DEFAULT_ALERT_SEED_CHUNK_SIZE = 500;
531
579
 
580
+ interface DefaultAnalyticsAlertDefinition {
581
+ idPrefix: string;
582
+ name: string;
583
+ description: string;
584
+ eventName: string;
585
+ filters: AnalyticsAlertFilter[];
586
+ threshold: number;
587
+ thresholdMode?: AnalyticsAlertThresholdMode;
588
+ distinctBy?: string | null;
589
+ windowMinutes: number;
590
+ cooldownMinutes: number;
591
+ severity: AnalyticsAlertSeverity;
592
+ }
593
+
532
594
  function chunkArray<T>(items: T[], size: number): T[][] {
533
595
  const chunks: T[][] = [];
534
596
  for (let i = 0; i < items.length; i += size) {
@@ -537,95 +599,155 @@ function chunkArray<T>(items: T[], size: number): T[][] {
537
599
  return chunks;
538
600
  }
539
601
 
540
- export async function ensureDefaultHttp5xxSpikeAlertRules(): Promise<{
602
+ function defaultAnalyticsAlertDefinitions(): DefaultAnalyticsAlertDefinition[] {
603
+ const definitions: DefaultAnalyticsAlertDefinition[] = [];
604
+
605
+ if (defaultHttp5xxAlertEnabled()) {
606
+ definitions.push({
607
+ idPrefix: DEFAULT_HTTP_5XX_ALERT_ID_PREFIX,
608
+ name: "Hosted app HTTP 5xx spike",
609
+ description:
610
+ "Default Agent Native alert for a spike in server responses with 5xx status codes.",
611
+ eventName: "http.response",
612
+ filters: [{ field: "properties.status_class", value: "5xx" }],
613
+ threshold: envInt(
614
+ "ANALYTICS_DEFAULT_HTTP_5XX_ALERT_THRESHOLD",
615
+ 5,
616
+ 1,
617
+ 1000,
618
+ ),
619
+ windowMinutes: envInt(
620
+ "ANALYTICS_DEFAULT_HTTP_5XX_ALERT_WINDOW_MINUTES",
621
+ 5,
622
+ 1,
623
+ 60,
624
+ ),
625
+ cooldownMinutes: envInt(
626
+ "ANALYTICS_DEFAULT_HTTP_5XX_ALERT_COOLDOWN_MINUTES",
627
+ 30,
628
+ 0,
629
+ 24 * 60,
630
+ ),
631
+ severity: "critical",
632
+ });
633
+ }
634
+
635
+ if (defaultAgentChatStuckAlertEnabled()) {
636
+ definitions.push({
637
+ idPrefix: DEFAULT_AGENT_CHAT_STUCK_ALERT_ID_PREFIX,
638
+ name: "Hosted agent chat stuck spike",
639
+ description:
640
+ "Default Agent Native alert for a spike in agent chats detected as stuck.",
641
+ eventName: "agent_chat_stuck_detected",
642
+ filters: [],
643
+ threshold: envInt(
644
+ "ANALYTICS_DEFAULT_AGENT_CHAT_STUCK_ALERT_THRESHOLD",
645
+ DEFAULT_AGENT_CHAT_STUCK_ALERT_THRESHOLD,
646
+ 1,
647
+ 1000,
648
+ ),
649
+ thresholdMode: "distinct_count",
650
+ distinctBy: "properties.runId",
651
+ windowMinutes: envInt(
652
+ "ANALYTICS_DEFAULT_AGENT_CHAT_STUCK_ALERT_WINDOW_MINUTES",
653
+ DEFAULT_AGENT_CHAT_STUCK_ALERT_WINDOW_MINUTES,
654
+ 1,
655
+ 60,
656
+ ),
657
+ cooldownMinutes: envInt(
658
+ "ANALYTICS_DEFAULT_AGENT_CHAT_STUCK_ALERT_COOLDOWN_MINUTES",
659
+ DEFAULT_AGENT_CHAT_STUCK_ALERT_COOLDOWN_MINUTES,
660
+ 0,
661
+ 24 * 60,
662
+ ),
663
+ severity: "critical",
664
+ });
665
+ }
666
+
667
+ return definitions;
668
+ }
669
+
670
+ export async function ensureDefaultAnalyticsAlertRules(): Promise<{
541
671
  checked: number;
542
672
  created: number;
543
673
  }> {
544
- if (!defaultHttp5xxAlertEnabled()) return { checked: 0, created: 0 };
545
-
546
- const scopes = await defaultHttp5xxAlertScopes();
547
- if (!scopes.length) return { checked: 0, created: 0 };
674
+ const definitions = defaultAnalyticsAlertDefinitions();
675
+ if (!definitions.length) return { checked: 0, created: 0 };
548
676
 
549
677
  const db = getDb() as any;
550
- const threshold = envInt(
551
- "ANALYTICS_DEFAULT_HTTP_5XX_ALERT_THRESHOLD",
552
- 5,
553
- 1,
554
- 1000,
555
- );
556
- const windowMinutes = envInt(
557
- "ANALYTICS_DEFAULT_HTTP_5XX_ALERT_WINDOW_MINUTES",
558
- 5,
559
- 1,
560
- 60,
561
- );
562
- const cooldownMinutes = envInt(
563
- "ANALYTICS_DEFAULT_HTTP_5XX_ALERT_COOLDOWN_MINUTES",
564
- 30,
565
- 0,
566
- 24 * 60,
567
- );
568
-
569
- const scopesById = new Map<string, AccessCtx>();
570
- for (const scope of scopes) {
571
- scopesById.set(defaultHttp5xxAlertId(scope.email, scope.orgId), scope);
572
- }
573
- const allIds = Array.from(scopesById.keys());
574
-
575
- const existingIds = new Set<string>();
576
- for (const idChunk of chunkArray(allIds, DEFAULT_ALERT_SEED_CHUNK_SIZE)) {
577
- const rows = await db
578
- .select({ id: schema.analyticsAlertRules.id })
579
- .from(schema.analyticsAlertRules)
580
- .where(inArray(schema.analyticsAlertRules.id, idChunk));
581
- for (const row of rows) existingIds.add(row.id);
582
- }
678
+ let checked = 0;
679
+ let created = 0;
680
+ let offset = 0;
681
+ while (true) {
682
+ const page = await defaultAnalyticsAlertScopePage(offset);
683
+ const candidatesById = new Map<
684
+ string,
685
+ { definition: DefaultAnalyticsAlertDefinition; scope: AccessCtx }
686
+ >();
687
+ for (const scope of page.scopes) {
688
+ for (const definition of definitions) {
689
+ candidatesById.set(
690
+ defaultAlertId(definition.idPrefix, scope.email, scope.orgId),
691
+ { definition, scope },
692
+ );
693
+ }
694
+ }
695
+ const allIds = Array.from(candidatesById.keys());
696
+ checked += allIds.length;
697
+
698
+ const existingIds = new Set<string>();
699
+ for (const idChunk of chunkArray(allIds, DEFAULT_ALERT_SEED_CHUNK_SIZE)) {
700
+ const rows = await db
701
+ .select({ id: schema.analyticsAlertRules.id })
702
+ .from(schema.analyticsAlertRules)
703
+ .where(inArray(schema.analyticsAlertRules.id, idChunk));
704
+ for (const row of rows) existingIds.add(row.id);
705
+ }
583
706
 
584
- const missingIds = allIds.filter((id) => !existingIds.has(id));
585
- if (!missingIds.length) return { checked: scopes.length, created: 0 };
707
+ const now = nowIso();
708
+ const rowsToInsert = allIds
709
+ .filter((id) => !existingIds.has(id))
710
+ .map((id) => {
711
+ const { definition, scope } = candidatesById.get(id)!;
712
+ return {
713
+ id,
714
+ name: definition.name,
715
+ description: definition.description,
716
+ eventName: definition.eventName,
717
+ filters: JSON.stringify(definition.filters),
718
+ thresholdMode: definition.thresholdMode ?? ("event_count" as const),
719
+ distinctBy: definition.distinctBy ?? null,
720
+ threshold: definition.threshold,
721
+ windowMinutes: definition.windowMinutes,
722
+ cooldownMinutes: definition.cooldownMinutes,
723
+ severity: definition.severity,
724
+ channels: JSON.stringify(["inbox"]),
725
+ emailRecipients: JSON.stringify([]),
726
+ enabled: true,
727
+ createdAt: now,
728
+ updatedAt: now,
729
+ ownerEmail: scope.email,
730
+ orgId: scope.orgId,
731
+ };
732
+ });
586
733
 
587
- const now = nowIso();
588
- const rowsToInsert = missingIds.map((id) => {
589
- const scope = scopesById.get(id)!;
590
- return {
591
- id,
592
- name: "Hosted app HTTP 5xx spike",
593
- description:
594
- "Default Agent Native alert for a spike in server responses with 5xx status codes.",
595
- eventName: "http.response",
596
- filters: JSON.stringify([
597
- { field: "properties.status_class", value: "5xx" },
598
- ]),
599
- thresholdMode: "event_count" as const,
600
- distinctBy: null,
601
- threshold,
602
- windowMinutes,
603
- cooldownMinutes,
604
- severity: "critical" as const,
605
- channels: JSON.stringify(["inbox"]),
606
- emailRecipients: JSON.stringify([]),
607
- enabled: true,
608
- createdAt: now,
609
- updatedAt: now,
610
- ownerEmail: scope.email,
611
- orgId: scope.orgId,
612
- };
613
- });
734
+ for (const rowChunk of chunkArray(
735
+ rowsToInsert,
736
+ DEFAULT_ALERT_SEED_CHUNK_SIZE,
737
+ )) {
738
+ const inserted = await db
739
+ .insert(schema.analyticsAlertRules)
740
+ .values(rowChunk)
741
+ .onConflictDoNothing()
742
+ .returning({ id: schema.analyticsAlertRules.id });
743
+ created += inserted.length;
744
+ }
614
745
 
615
- let created = 0;
616
- for (const rowChunk of chunkArray(
617
- rowsToInsert,
618
- DEFAULT_ALERT_SEED_CHUNK_SIZE,
619
- )) {
620
- const inserted = await db
621
- .insert(schema.analyticsAlertRules)
622
- .values(rowChunk)
623
- .onConflictDoNothing()
624
- .returning({ id: schema.analyticsAlertRules.id });
625
- created += inserted.length;
746
+ if (!page.hasMore) break;
747
+ offset += DEFAULT_ALERT_SCOPE_PAGE_SIZE;
626
748
  }
627
749
 
628
- return { checked: scopes.length, created };
750
+ return { checked, created };
629
751
  }
630
752
 
631
753
  export async function listEnabledAnalyticsAlertRules(options: {