@canonry/canonry 4.133.3 → 4.134.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 (28) hide show
  1. package/README.md +0 -13
  2. package/assets/agent-workspace/skills/canonry/references/aeo-analysis.md +3 -2
  3. package/assets/agent-workspace/skills/canonry/references/canonry-cli.md +32 -3
  4. package/assets/assets/{AuditHistoryPanel-DTHQGvkW.js → AuditHistoryPanel-BW7LVMSZ.js} +1 -1
  5. package/assets/assets/{BacklinksPage-DuPI3wt9.js → BacklinksPage-DU65axM1.js} +1 -1
  6. package/assets/assets/{ChartPrimitives-T8mxOObc.js → ChartPrimitives-CUZJ7nUb.js} +1 -1
  7. package/assets/assets/{HistoryPage-T1W40xKG.js → HistoryPage-BswdEXC5.js} +1 -1
  8. package/assets/assets/ProjectPage-CttTuKKo.js +8 -0
  9. package/assets/assets/{RunRow-nHr4wW9B.js → RunRow-CBxbfubI.js} +1 -1
  10. package/assets/assets/{RunsPage-Cbusy_84.js → RunsPage-BQxA05ua.js} +1 -1
  11. package/assets/assets/{SettingsPage-BVcbl4gn.js → SettingsPage-krEusjc9.js} +1 -1
  12. package/assets/assets/{TrafficPage-CZ4NTWI6.js → TrafficPage-DMhcA9lg.js} +1 -1
  13. package/assets/assets/{TrafficSourceDetailPage-xW-KvZY1.js → TrafficSourceDetailPage-Dm0Gj0HS.js} +1 -1
  14. package/assets/assets/{arrow-left-flskyFPK.js → arrow-left-_1YaUPbl.js} +1 -1
  15. package/assets/assets/{extract-error-message-BHfCTm0H.js → extract-error-message-D4XKG37U.js} +1 -1
  16. package/assets/assets/{index-CQzGDGMB.js → index-V1C3c7nO.js} +100 -100
  17. package/assets/assets/{trash-2-LGfqtSzZ.js → trash-2-D3LWIGDJ.js} +1 -1
  18. package/assets/index.html +1 -1
  19. package/dist/{chunk-A6BYMSZL.js → chunk-BSU2MI3Y.js} +79 -4
  20. package/dist/{chunk-YRRQFOAH.js → chunk-CF5WTWXI.js} +257 -2
  21. package/dist/{chunk-HENMGNLT.js → chunk-DVJGFY3J.js} +684 -74
  22. package/dist/{chunk-6ON6GUAL.js → chunk-NWVPRV7A.js} +68 -6
  23. package/dist/cli.js +113 -5
  24. package/dist/index.js +4 -4
  25. package/dist/{intelligence-service-OSLFG5S2.js → intelligence-service-NO4FJUYD.js} +2 -2
  26. package/dist/mcp.js +2 -2
  27. package/package.json +9 -9
  28. package/assets/assets/ProjectPage-DYwM8-Rp.js +0 -8
@@ -1 +1 @@
1
- import{c as a}from"./index-CQzGDGMB.js";const c=[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["path",{d:"m9 12 2 2 4-4",key:"dzmm74"}]],d=a("circle-check",c);const e=[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["path",{d:"M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3",key:"1u773s"}],["path",{d:"M12 17h.01",key:"p32p05"}]],k=a("circle-question-mark",e);const t=[["path",{d:"M12 15V3",key:"m9g1x1"}],["path",{d:"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4",key:"ih7n3h"}],["path",{d:"m7 10 5 5 5-5",key:"brsn70"}]],s=a("download",t);const o=[["path",{d:"M15 3h6v6",key:"1q9fwt"}],["path",{d:"M10 14 21 3",key:"gplh6r"}],["path",{d:"M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6",key:"a6xqqp"}]],r=a("external-link",o);const n=[["path",{d:"M10 11v6",key:"nco0om"}],["path",{d:"M14 11v6",key:"outv1u"}],["path",{d:"M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6",key:"miytrc"}],["path",{d:"M3 6h18",key:"d0wm0j"}],["path",{d:"M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2",key:"e791ji"}]],y=a("trash-2",n);export{d as C,s as D,r as E,y as T,k as a};
1
+ import{c as a}from"./index-V1C3c7nO.js";const c=[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["path",{d:"m9 12 2 2 4-4",key:"dzmm74"}]],d=a("circle-check",c);const e=[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["path",{d:"M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3",key:"1u773s"}],["path",{d:"M12 17h.01",key:"p32p05"}]],k=a("circle-question-mark",e);const t=[["path",{d:"M12 15V3",key:"m9g1x1"}],["path",{d:"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4",key:"ih7n3h"}],["path",{d:"m7 10 5 5 5-5",key:"brsn70"}]],s=a("download",t);const o=[["path",{d:"M15 3h6v6",key:"1q9fwt"}],["path",{d:"M10 14 21 3",key:"gplh6r"}],["path",{d:"M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6",key:"a6xqqp"}]],r=a("external-link",o);const n=[["path",{d:"M10 11v6",key:"nco0om"}],["path",{d:"M14 11v6",key:"outv1u"}],["path",{d:"M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6",key:"miytrc"}],["path",{d:"M3 6h18",key:"d0wm0j"}],["path",{d:"M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2",key:"e791ji"}]],y=a("trash-2",n);export{d as C,s as D,r as E,y as T,k as a};
package/assets/index.html CHANGED
@@ -12,7 +12,7 @@
12
12
  <link rel="icon" type="image/png" sizes="32x32" href="./favicon-32.png" />
13
13
  <link rel="apple-touch-icon" href="./apple-touch-icon.png" />
14
14
  <title>Canonry</title>
15
- <script type="module" crossorigin src="./assets/index-CQzGDGMB.js"></script>
15
+ <script type="module" crossorigin src="./assets/index-V1C3c7nO.js"></script>
16
16
  <link rel="modulepreload" crossorigin href="./assets/vendor-tanstack-Be8JdV5M.js">
17
17
  <link rel="modulepreload" crossorigin href="./assets/vendor-radix-CQ77EO2y.js">
18
18
  <link rel="modulepreload" crossorigin href="./assets/vendor-recharts-DSxTZhaH.js">
@@ -42,7 +42,7 @@ import {
42
42
  trafficConnectWordpressRequestSchema,
43
43
  trafficEventKindSchema,
44
44
  trafficSeriesGranularitySchema
45
- } from "./chunk-YRRQFOAH.js";
45
+ } from "./chunk-CF5WTWXI.js";
46
46
 
47
47
  // src/config.ts
48
48
  import fs from "fs";
@@ -2739,6 +2739,18 @@ var getApiV1ProjectsByNameAdsDeliveryDiagnostics = (options) => {
2739
2739
  ...options
2740
2740
  });
2741
2741
  };
2742
+ var getApiV1ProjectsByNameAdsLiveDelivery = (options) => {
2743
+ return (options.client ?? client).get({
2744
+ security: [
2745
+ {
2746
+ scheme: "bearer",
2747
+ type: "http"
2748
+ }
2749
+ ],
2750
+ url: "/api/v1/projects/{name}/ads/live-delivery",
2751
+ ...options
2752
+ });
2753
+ };
2742
2754
  var postApiV1ProjectsByNameBingConnect = (options) => {
2743
2755
  return (options.client ?? client).post({
2744
2756
  security: [
@@ -3271,6 +3283,18 @@ var getApiV1ProjectsByNameGaAiReferralHistory = (options) => {
3271
3283
  ...options
3272
3284
  });
3273
3285
  };
3286
+ var getApiV1ProjectsByNameGaAiReferralDaily = (options) => {
3287
+ return (options.client ?? client).get({
3288
+ security: [
3289
+ {
3290
+ scheme: "bearer",
3291
+ type: "http"
3292
+ }
3293
+ ],
3294
+ url: "/api/v1/projects/{name}/ga/ai-referral-daily",
3295
+ ...options
3296
+ });
3297
+ };
3274
3298
  var getApiV1ProjectsByNameGaSocialReferralHistory = (options) => {
3275
3299
  return (options.client ?? client).get({
3276
3300
  security: [
@@ -4871,6 +4895,18 @@ var ApiClient = class {
4871
4895
  () => getApiV1ProjectsByNameAdsDeliveryDiagnostics({ client: this.heyClient, path: { name: project } })
4872
4896
  );
4873
4897
  }
4898
+ async getAdsLiveDelivery(project, opts) {
4899
+ return this.invoke(
4900
+ () => getApiV1ProjectsByNameAdsLiveDelivery({
4901
+ client: this.heyClient,
4902
+ path: { name: project },
4903
+ query: {
4904
+ ...opts?.campaignId === void 0 ? {} : { campaignId: opts.campaignId },
4905
+ ...opts?.lookbackDays === void 0 ? {} : { lookbackDays: opts.lookbackDays }
4906
+ }
4907
+ })
4908
+ );
4909
+ }
4874
4910
  async getAdsOperation(project, operationKey) {
4875
4911
  return this.invoke(
4876
4912
  () => getApiV1ProjectsByNameAdsOperationsByOperationKey({
@@ -5328,6 +5364,15 @@ var ApiClient = class {
5328
5364
  })
5329
5365
  );
5330
5366
  }
5367
+ async gaAiReferralDaily(project, params) {
5368
+ return this.invoke(
5369
+ () => getApiV1ProjectsByNameGaAiReferralDaily({
5370
+ client: this.heyClient,
5371
+ path: { name: project },
5372
+ query: params
5373
+ })
5374
+ );
5375
+ }
5331
5376
  async gaSocialReferralHistory(project, params) {
5332
5377
  return this.invoke(
5333
5378
  () => getApiV1ProjectsByNameGaSocialReferralHistory({
@@ -6169,6 +6214,11 @@ var adsInsightsInputSchema = z2.object({
6169
6214
  var adsGeoSearchInputSchema = adsGeoSearchQuerySchema.extend({
6170
6215
  project: projectNameSchema
6171
6216
  });
6217
+ var adsLiveDeliveryInputSchema = z2.object({
6218
+ project: projectNameSchema,
6219
+ campaignId: z2.string().min(1).max(200).optional(),
6220
+ lookbackDays: z2.number().int().min(1).max(30).optional()
6221
+ });
6172
6222
  var adsOperationInputSchema = z2.object({
6173
6223
  project: projectNameSchema,
6174
6224
  operationKey: z2.string().min(8).max(128)
@@ -7052,8 +7102,8 @@ var canonryMcpTools = [
7052
7102
  }),
7053
7103
  defineTool({
7054
7104
  name: "canonry_ga_ai_referral_history",
7055
- title: "Get GA AI referral history",
7056
- description: "Get AI referral sessions per day grouped by source.",
7105
+ title: "Get GA AI referral detail rows",
7106
+ description: "Get raw AI referral rows per day, landing page, and attribution dimension. Detail, not totals: use canonry_ga_ai_referral_daily for session counts.",
7057
7107
  access: "read",
7058
7108
  tier: "ga",
7059
7109
  inputSchema: gaWindowInputSchema,
@@ -7061,6 +7111,17 @@ var canonryMcpTools = [
7061
7111
  openApiOperations: ["GET /api/v1/projects/{name}/ga/ai-referral-history"],
7062
7112
  handler: (client2, input) => client2.gaAiReferralHistory(input.project, compactStringParams(input, ["window"]))
7063
7113
  }),
7114
+ defineTool({
7115
+ name: "canonry_ga_ai_referral_daily",
7116
+ title: "Get GA AI referral sessions per day",
7117
+ description: "Get AI referral sessions per day and per source, deduplicated across attribution dimensions. Totals match the AI sessions reported by canonry_ga_traffic.",
7118
+ access: "read",
7119
+ tier: "ga",
7120
+ inputSchema: gaWindowInputSchema,
7121
+ annotations: readAnnotations(),
7122
+ openApiOperations: ["GET /api/v1/projects/{name}/ga/ai-referral-daily"],
7123
+ handler: (client2, input) => client2.gaAiReferralDaily(input.project, compactStringParams(input, ["window"]))
7124
+ }),
7064
7125
  defineTool({
7065
7126
  name: "canonry_ga_social_referral_history",
7066
7127
  title: "Get GA social referral history",
@@ -7710,7 +7771,7 @@ var canonryMcpTools = [
7710
7771
  defineTool({
7711
7772
  name: "canonry_research_run_get",
7712
7773
  title: "Get research query run",
7713
- description: "Get the saved per-query answers, sources, cited domains, and independent mention/citation results for one research run. It is read-only and does not promote or track any query.",
7774
+ description: "Get saved per-query answers, source links, cited domains, answer-text named competitors, cited competitor domains, and independent mention/citation results for one research run. It is read-only and does not promote or track any query.",
7714
7775
  access: "read",
7715
7776
  tier: "discovery",
7716
7777
  inputSchema: researchRunIdInputSchema,
@@ -7940,6 +8001,20 @@ var canonryMcpTools = [
7940
8001
  openApiOperations: ["GET /api/v1/projects/{name}/ads/delivery-diagnostics"],
7941
8002
  handler: (client2, input) => client2.getAdsDeliveryDiagnostics(input.project)
7942
8003
  }),
8004
+ defineTool({
8005
+ name: "canonry_ads_live_delivery",
8006
+ title: "Live ads read with stored-snapshot delta",
8007
+ description: "Call the OpenAI Ads API right now and return the provider's current status and metrics per campaign / ad group / ad, unaggregated, alongside the stored snapshot values and an explicit per-entity delta. Use this when stored data is suspected of being stale or contradicted by the advertiser UI. Read-only: it mutates nothing and does not wait for a sync. The walk is bounded and one project may issue at most one live read per minute, so prefer canonry_ads_delivery_diagnostics for routine checks.",
8008
+ access: "read",
8009
+ tier: "ads",
8010
+ inputSchema: adsLiveDeliveryInputSchema,
8011
+ annotations: readAnnotations(),
8012
+ openApiOperations: ["GET /api/v1/projects/{name}/ads/live-delivery"],
8013
+ handler: (client2, input) => client2.getAdsLiveDelivery(input.project, {
8014
+ campaignId: input.campaignId,
8015
+ lookbackDays: input.lookbackDays
8016
+ })
8017
+ }),
7943
8018
  defineTool({
7944
8019
  name: "canonry_ads_operations_unresolved",
7945
8020
  title: "List unresolved ads mutation receipts",
@@ -47,8 +47,8 @@ function authInvalid() {
47
47
  function forbidden(message = "Forbidden", details) {
48
48
  return new AppError("FORBIDDEN", message, 403, details);
49
49
  }
50
- function quotaExceeded(metric) {
51
- return new AppError("QUOTA_EXCEEDED", `Quota exceeded for ${metric}`, 429);
50
+ function quotaExceeded(metric, details) {
51
+ return new AppError("QUOTA_EXCEEDED", `Quota exceeded for ${metric}`, 429, details);
52
52
  }
53
53
  function providerError(message, details) {
54
54
  return new AppError("PROVIDER_ERROR", message, 502, details);
@@ -960,6 +960,111 @@ function formatIsoDate(iso) {
960
960
  return iso;
961
961
  }
962
962
  }
963
+ function zonedClockFormat(timeZone) {
964
+ return new Intl.DateTimeFormat("en-US", {
965
+ timeZone,
966
+ year: "numeric",
967
+ month: "2-digit",
968
+ day: "2-digit",
969
+ hour: "2-digit",
970
+ minute: "2-digit",
971
+ second: "2-digit",
972
+ hourCycle: "h23"
973
+ });
974
+ }
975
+ function readZonedParts(format, date) {
976
+ const values = {};
977
+ for (const part of format.formatToParts(date)) values[part.type] = part.value;
978
+ return values;
979
+ }
980
+ function readZonedClock(format, date) {
981
+ const parts = readZonedParts(format, date);
982
+ const value = (raw) => {
983
+ if (raw === void 0) return null;
984
+ const parsed = Number(raw);
985
+ return Number.isFinite(parsed) ? parsed : null;
986
+ };
987
+ const year = value(parts.year);
988
+ const month = value(parts.month);
989
+ const day = value(parts.day);
990
+ const hour = value(parts.hour);
991
+ const minute = value(parts.minute);
992
+ const second = value(parts.second);
993
+ if (year === null || month === null || day === null) return null;
994
+ if (hour === null || minute === null || second === null) return null;
995
+ return { year, month, day, hour, minute, second };
996
+ }
997
+ function formatIsoDateInTimeZone(iso, timeZone) {
998
+ if (!iso) return formatIsoDate(iso);
999
+ const d = new Date(iso);
1000
+ if (Number.isNaN(d.getTime())) return iso;
1001
+ try {
1002
+ const parts = readZonedParts(zonedClockFormat(timeZone), d);
1003
+ const yyyy = parts.year;
1004
+ const mm = parts.month;
1005
+ const dd = parts.day;
1006
+ if (!yyyy || !mm || !dd) return formatIsoDate(iso);
1007
+ return `${yyyy}-${mm}-${dd}`;
1008
+ } catch {
1009
+ return formatIsoDate(iso);
1010
+ }
1011
+ }
1012
+ function shiftIsoCalendarDate(isoDate, days) {
1013
+ if (!Number.isFinite(days)) return isoDate;
1014
+ const match = /^(\d{4})-(\d{2})-(\d{2})$/.exec(isoDate);
1015
+ if (!match?.[1] || !match[2] || !match[3]) return isoDate;
1016
+ const shifted = new Date(Date.UTC(
1017
+ Number(match[1]),
1018
+ Number(match[2]) - 1,
1019
+ Number(match[3]) + Math.trunc(days)
1020
+ ));
1021
+ if (Number.isNaN(shifted.getTime())) return isoDate;
1022
+ const yyyy = shifted.getUTCFullYear();
1023
+ const mm = String(shifted.getUTCMonth() + 1).padStart(2, "0");
1024
+ const dd = String(shifted.getUTCDate()).padStart(2, "0");
1025
+ return `${yyyy}-${mm}-${dd}`;
1026
+ }
1027
+ function isoDateDaysBeforeInTimeZone(iso, days, timeZone) {
1028
+ return shiftIsoCalendarDate(formatIsoDateInTimeZone(iso, timeZone), -days);
1029
+ }
1030
+ var HOURS_PER_DAY = 24;
1031
+ var ONE_DAY_MS = 24 * 60 * 60 * 1e3;
1032
+ function localHourExists(format, year, month, day, hour) {
1033
+ const asIfUtcMs = Date.UTC(year, month - 1, day, hour);
1034
+ for (const probeMs of [asIfUtcMs - ONE_DAY_MS, asIfUtcMs + ONE_DAY_MS]) {
1035
+ const probeClock = readZonedClock(format, new Date(probeMs));
1036
+ if (!probeClock) continue;
1037
+ const offsetMs = Date.UTC(
1038
+ probeClock.year,
1039
+ probeClock.month - 1,
1040
+ probeClock.day,
1041
+ probeClock.hour,
1042
+ probeClock.minute,
1043
+ probeClock.second
1044
+ ) - probeMs;
1045
+ const candidate = readZonedClock(format, new Date(asIfUtcMs - offsetMs));
1046
+ if (!candidate) continue;
1047
+ if (candidate.year === year && candidate.month === month && candidate.day === day && candidate.hour === hour && candidate.minute === 0 && candidate.second === 0) return true;
1048
+ }
1049
+ return false;
1050
+ }
1051
+ function startOfDayHourInTimeZone(isoDate, timeZone) {
1052
+ const hourBoundary = (hour) => `${isoDate}T${String(hour).padStart(2, "0")}`;
1053
+ const match = /^(\d{4})-(\d{2})-(\d{2})$/.exec(isoDate);
1054
+ if (!match?.[1] || !match[2] || !match[3]) return hourBoundary(0);
1055
+ const year = Number(match[1]);
1056
+ const month = Number(match[2]);
1057
+ const day = Number(match[3]);
1058
+ try {
1059
+ const format = zonedClockFormat(timeZone);
1060
+ for (let hour = 0; hour < HOURS_PER_DAY; hour += 1) {
1061
+ if (localHourExists(format, year, month, day, hour)) return hourBoundary(hour);
1062
+ }
1063
+ return hourBoundary(0);
1064
+ } catch {
1065
+ return hourBoundary(0);
1066
+ }
1067
+ }
963
1068
  function formatDateRange(start, end) {
964
1069
  if (!start && !end) return "";
965
1070
  if (start && end) return `${formatDate(start)} \u2192 ${formatDate(end)}`;
@@ -4043,6 +4148,29 @@ var ga4AiReferralHistoryEntrySchema = z25.object({
4043
4148
  /** Which GA4 dimension this row came from: session (sessionSource), first_user (firstUserSource), or manual_utm (utm_source parameter) */
4044
4149
  sourceDimension: ga4SourceDimensionSchema
4045
4150
  });
4151
+ var ga4AiReferralDailySourceSchema = z25.object({
4152
+ source: z25.string(),
4153
+ sessions: z25.number(),
4154
+ paidSessions: z25.number(),
4155
+ organicSessions: z25.number()
4156
+ });
4157
+ var ga4AiReferralDailyEntrySchema = z25.object({
4158
+ date: z25.string(),
4159
+ sessions: z25.number(),
4160
+ paidSessions: z25.number(),
4161
+ organicSessions: z25.number(),
4162
+ /** Per-source split of the day. `sessions` is the sum of these. */
4163
+ bySource: z25.array(ga4AiReferralDailySourceSchema)
4164
+ });
4165
+ var ga4AiReferralDailyDtoSchema = z25.object({
4166
+ /** Ascending by date. Dates with no AI referrals are absent, not zero-filled. */
4167
+ days: z25.array(ga4AiReferralDailyEntrySchema),
4168
+ /** Sources present in the window, ordered by total sessions descending. */
4169
+ sources: z25.array(z25.string()),
4170
+ totalSessions: z25.number(),
4171
+ totalPaidSessions: z25.number(),
4172
+ totalOrganicSessions: z25.number()
4173
+ });
4046
4174
  var ga4SocialReferralHistoryEntrySchema = z25.object({
4047
4175
  date: z25.string(),
4048
4176
  source: z25.string(),
@@ -6518,6 +6646,8 @@ var researchRunQuerySchema = z37.object({
6518
6646
  groundingSources: z37.array(groundingSourceSchema),
6519
6647
  citedDomains: z37.array(z37.string()),
6520
6648
  searchQueries: z37.array(z37.string()),
6649
+ namedCompetitors: z37.array(z37.string()).default([]),
6650
+ citedCompetitorDomains: z37.array(z37.string()).default([]),
6521
6651
  answerMentioned: z37.boolean().nullable(),
6522
6652
  citationState: citationStateSchema.nullable(),
6523
6653
  error: z37.string().nullable(),
@@ -7333,6 +7463,122 @@ var adsOperationReconcileResponseSchema = z38.object({
7333
7463
  operation: adsOperationDtoSchema,
7334
7464
  resolved: z38.boolean()
7335
7465
  });
7466
+ var adsLiveDeliveryQuerySchema = z38.object({
7467
+ campaignId: z38.string().min(1).max(200).optional(),
7468
+ lookbackDays: z38.coerce.number().int().min(1).max(30).default(7)
7469
+ });
7470
+ var adsLiveEntityTypeSchema = z38.enum(["campaign", "ad_group", "ad"]);
7471
+ var AdsLiveEntityTypes = adsLiveEntityTypeSchema.enum;
7472
+ var adsLivePresenceSchema = z38.enum(["both", "live-only", "stored-only"]);
7473
+ var AdsLivePresences = adsLivePresenceSchema.enum;
7474
+ var adsLiveDeliveryBasisSchema = z38.literal("live-provider-read");
7475
+ var AdsLiveDeliveryBases = { liveProviderRead: "live-provider-read" };
7476
+ var adsLiveMetricRowSchema = z38.object({
7477
+ date: z38.string().nullable(),
7478
+ startTime: z38.number().nullable(),
7479
+ endTime: z38.number().nullable(),
7480
+ impressions: z38.number().nullable(),
7481
+ clicks: z38.number().nullable(),
7482
+ spend: z38.number().nullable(),
7483
+ conversions: z38.number().nullable(),
7484
+ ctr: z38.number().nullable(),
7485
+ cpc: z38.number().nullable(),
7486
+ cpm: z38.number().nullable()
7487
+ });
7488
+ var adsLiveMetricValuesSchema = z38.object({
7489
+ impressions: z38.number().int(),
7490
+ clicks: z38.number().int(),
7491
+ spendMicros: z38.number().int(),
7492
+ conversions: z38.number().int()
7493
+ });
7494
+ var adsLiveMetricDeltaSchema = z38.object({
7495
+ date: z38.string(),
7496
+ live: adsLiveMetricValuesSchema.nullable(),
7497
+ stored: adsLiveMetricValuesSchema.nullable(),
7498
+ drifted: z38.boolean()
7499
+ });
7500
+ var adsLiveFieldDeltaSchema = z38.object({
7501
+ field: z38.string(),
7502
+ live: z38.string().nullable(),
7503
+ stored: z38.string().nullable()
7504
+ });
7505
+ var adsLiveEntityStateSchema = z38.object({
7506
+ name: z38.string().nullable(),
7507
+ status: z38.string(),
7508
+ reviewStatus: z38.string().nullable(),
7509
+ mode: z38.string().nullable(),
7510
+ updatedAt: z38.number().nullable()
7511
+ });
7512
+ var adsStoredEntityStateSchema = z38.object({
7513
+ name: z38.string(),
7514
+ status: z38.string(),
7515
+ reviewStatus: z38.string().nullable(),
7516
+ upstreamUpdatedAt: z38.number().nullable(),
7517
+ syncedAt: z38.string()
7518
+ });
7519
+ var adsLiveEntityComparisonSchema = z38.object({
7520
+ entityType: adsLiveEntityTypeSchema,
7521
+ id: z38.string(),
7522
+ parentId: z38.string().nullable(),
7523
+ presence: adsLivePresenceSchema,
7524
+ live: adsLiveEntityStateSchema.nullable(),
7525
+ stored: adsStoredEntityStateSchema.nullable(),
7526
+ fieldDeltas: z38.array(adsLiveFieldDeltaSchema),
7527
+ /** Provider rows, unaggregated. Null for ads (no per-ad insights surface). */
7528
+ liveMetrics: z38.array(adsLiveMetricRowSchema).nullable(),
7529
+ metricDeltas: z38.array(adsLiveMetricDeltaSchema).nullable(),
7530
+ drifted: z38.boolean()
7531
+ });
7532
+ var adsLiveReadFailureSchema = z38.object({
7533
+ surface: z38.string(),
7534
+ entityId: z38.string().nullable(),
7535
+ upstreamStatus: z38.number().int().nullable()
7536
+ });
7537
+ var adsLiveDeliveryDtoSchema = z38.object({
7538
+ basis: adsLiveDeliveryBasisSchema,
7539
+ /** Instant the live read was issued; the metrics window is measured back from it. */
7540
+ fetchedAt: z38.string(),
7541
+ adAccountId: z38.string(),
7542
+ storedSnapshotSyncedAt: z38.string().nullable(),
7543
+ metricsWindow: z38.object({ lookbackDays: z38.number().int().positive() }),
7544
+ /**
7545
+ * Two different units live here, and confusing them understates the cost of
7546
+ * this endpoint by two orders of magnitude.
7547
+ *
7548
+ * A READER CALL is one logical list or insight read. Every list/insight
7549
+ * reader call is an auto-paginating walk, so one reader call can issue up to
7550
+ * `maxPagesPerReaderCall` upstream HTTP requests before the client gives up.
7551
+ * `maxUpstreamHttpRequests` is the honest worst-case ceiling in HTTP
7552
+ * requests (`maxReaderCalls * maxPagesPerReaderCall`, about 4000 at the
7553
+ * shipped defaults, not 40).
7554
+ *
7555
+ * `readerCalls` is an observed count of reader calls. There is deliberately
7556
+ * no observed HTTP-request count: the pagination happens inside the provider
7557
+ * client, below the injected reader seam, so the route cannot see it.
7558
+ */
7559
+ bounds: z38.object({
7560
+ maxCampaigns: z38.number().int().positive(),
7561
+ maxAdGroupsPerCampaign: z38.number().int().positive(),
7562
+ maxAdsPerAdGroup: z38.number().int().positive(),
7563
+ /** Budget in logical reader calls, NOT in upstream HTTP requests. */
7564
+ maxReaderCalls: z38.number().int().positive(),
7565
+ /** Reader calls this read actually issued. Observed, not a bound. */
7566
+ readerCalls: z38.number().int().nonnegative(),
7567
+ /** Pages one paginated reader call may fetch before the client gives up. */
7568
+ maxPagesPerReaderCall: z38.number().int().positive(),
7569
+ /** Worst-case upstream HTTP requests. A documented bound, not an observation. */
7570
+ maxUpstreamHttpRequests: z38.number().int().positive(),
7571
+ truncated: z38.boolean()
7572
+ }),
7573
+ entities: z38.array(adsLiveEntityComparisonSchema),
7574
+ drift: z38.object({
7575
+ entitiesCompared: z38.number().int().nonnegative(),
7576
+ driftedEntities: z38.number().int().nonnegative(),
7577
+ statusDrifted: z38.number().int().nonnegative(),
7578
+ metricsDrifted: z38.number().int().nonnegative()
7579
+ }),
7580
+ errors: z38.array(adsLiveReadFailureSchema)
7581
+ });
7336
7582
  function adsCtr(clicks, impressions) {
7337
7583
  return impressions > 0 ? clicks / impressions : null;
7338
7584
  }
@@ -7583,6 +7829,9 @@ export {
7583
7829
  formatNumber,
7584
7830
  formatDate,
7585
7831
  formatIsoDate,
7832
+ formatIsoDateInTimeZone,
7833
+ isoDateDaysBeforeInTimeZone,
7834
+ startOfDayHourInTimeZone,
7586
7835
  formatDateRange,
7587
7836
  parseInclusiveEndMs,
7588
7837
  deltaPercent,
@@ -7739,6 +7988,7 @@ export {
7739
7988
  ga4StatusDtoSchema,
7740
7989
  ga4SyncResponseDtoSchema,
7741
7990
  ga4AiReferralHistoryEntrySchema,
7991
+ ga4AiReferralDailyDtoSchema,
7742
7992
  ga4SocialReferralHistoryEntrySchema,
7743
7993
  ga4SessionHistoryEntrySchema,
7744
7994
  extractAnswerMentions,
@@ -7902,6 +8152,11 @@ export {
7902
8152
  adsUnresolvedOperationListResponseSchema,
7903
8153
  adsOperationReconcileRequestSchema,
7904
8154
  adsOperationReconcileResponseSchema,
8155
+ adsLiveDeliveryQuerySchema,
8156
+ AdsLiveEntityTypes,
8157
+ AdsLivePresences,
8158
+ AdsLiveDeliveryBases,
8159
+ adsLiveDeliveryDtoSchema,
7905
8160
  adsCtr,
7906
8161
  adsCpcMicros,
7907
8162
  dollarsToMicros,