@canonry/canonry 4.126.0 → 4.127.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (24) hide show
  1. package/assets/assets/{AuditHistoryPanel-C-KSU-dr.js → AuditHistoryPanel-DwJpVWme.js} +1 -1
  2. package/assets/assets/{BacklinksPage-BH4njwCh.js → BacklinksPage-K8FQUBxI.js} +1 -1
  3. package/assets/assets/{ChartPrimitives-BhB9Kxzc.js → ChartPrimitives-6oFKrJFk.js} +1 -1
  4. package/assets/assets/{HistoryPage-BQVNx0eu.js → HistoryPage-DwOAoN1Z.js} +1 -1
  5. package/assets/assets/{ProjectPage-DnkNE1AW.js → ProjectPage-CdgFUk7h.js} +1 -1
  6. package/assets/assets/{RunRow-70N3oGz8.js → RunRow-lt9IS99U.js} +1 -1
  7. package/assets/assets/{RunsPage-CtuKRP0o.js → RunsPage-DitYcIdx.js} +1 -1
  8. package/assets/assets/{SettingsPage-B1ZGnDz8.js → SettingsPage-CAOrh65Q.js} +1 -1
  9. package/assets/assets/{TrafficPage-BOGbXHd9.js → TrafficPage-BqzNvx75.js} +1 -1
  10. package/assets/assets/{TrafficSourceDetailPage-5jj7n7W1.js → TrafficSourceDetailPage-DXbygZUA.js} +1 -1
  11. package/assets/assets/{arrow-left-gOf0lyu3.js → arrow-left-AmG4gtUR.js} +1 -1
  12. package/assets/assets/{extract-error-message-CZKcwJhv.js → extract-error-message-DlVtjoPz.js} +1 -1
  13. package/assets/assets/{index-B_CDPjOg.js → index-BiCDkOH4.js} +3 -3
  14. package/assets/assets/{trash-2-BnFgG3Wq.js → trash-2-gFHWd1A1.js} +1 -1
  15. package/assets/index.html +1 -1
  16. package/dist/{chunk-M6GKSLOJ.js → chunk-A4YBV4Y4.js} +4 -4
  17. package/dist/{chunk-RFLNTI7Y.js → chunk-BLSHHRRU.js} +21 -5
  18. package/dist/{chunk-FCGRCCX6.js → chunk-HQRUFTLN.js} +105 -41
  19. package/dist/{chunk-WA57WG6W.js → chunk-IHRW6WWV.js} +1 -1
  20. package/dist/cli.js +4 -4
  21. package/dist/index.js +4 -4
  22. package/dist/{intelligence-service-K6B3MTDS.js → intelligence-service-2WKS3EWJ.js} +2 -2
  23. package/dist/mcp.js +2 -2
  24. package/package.json +6 -6
@@ -1 +1 @@
1
- import{c}from"./index-B_CDPjOg.js";const a=[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["path",{d:"m9 12 2 2 4-4",key:"dzmm74"}]],h=c("circle-check",a);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"}]],n=c("circle-question-mark",e);const o=[["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=c("download",o);const t=[["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"}]],r=c("trash-2",t);export{h as C,s as D,r as T,n as a};
1
+ import{c}from"./index-BiCDkOH4.js";const a=[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["path",{d:"m9 12 2 2 4-4",key:"dzmm74"}]],h=c("circle-check",a);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"}]],n=c("circle-question-mark",e);const o=[["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=c("download",o);const t=[["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"}]],r=c("trash-2",t);export{h as C,s as D,r as T,n 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-B_CDPjOg.js"></script>
15
+ <script type="module" crossorigin src="./assets/index-BiCDkOH4.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">
@@ -10,7 +10,7 @@ import {
10
10
  loadConfig,
11
11
  loadConfigRaw,
12
12
  saveConfigPatch
13
- } from "./chunk-WA57WG6W.js";
13
+ } from "./chunk-IHRW6WWV.js";
14
14
  import {
15
15
  CC_CACHE_DIR,
16
16
  DUCKDB_SPEC,
@@ -116,7 +116,7 @@ import {
116
116
  siteAuditPages,
117
117
  siteAuditSnapshots,
118
118
  usageCounters
119
- } from "./chunk-FCGRCCX6.js";
119
+ } from "./chunk-HQRUFTLN.js";
120
120
  import {
121
121
  AGENT_MEMORY_VALUE_MAX_BYTES,
122
122
  AGENT_PROVIDER_IDS,
@@ -186,7 +186,7 @@ import {
186
186
  validationError,
187
187
  winnabilityClassLabel,
188
188
  withRetry
189
- } from "./chunk-RFLNTI7Y.js";
189
+ } from "./chunk-BLSHHRRU.js";
190
190
 
191
191
  // src/telemetry.ts
192
192
  import crypto from "crypto";
@@ -6967,7 +6967,7 @@ function readStoredGroundingSources(rawResponse) {
6967
6967
  return result;
6968
6968
  }
6969
6969
  async function backfillInsightsCommand(project, opts) {
6970
- const { IntelligenceService: IntelligenceService2 } = await import("./intelligence-service-K6B3MTDS.js");
6970
+ const { IntelligenceService: IntelligenceService2 } = await import("./intelligence-service-2WKS3EWJ.js");
6971
6971
  const config = loadConfig();
6972
6972
  const db = createClient(config.database);
6973
6973
  migrate(db);
@@ -5256,15 +5256,30 @@ var socialReferralSectionSchema = z32.object({
5256
5256
  });
5257
5257
  var aiReferralSectionSchema = z32.object({
5258
5258
  totalSessions: z32.number(),
5259
- totalUsers: z32.number(),
5260
5259
  paidSessions: z32.number(),
5261
- paidUsers: z32.number(),
5262
5260
  organicSessions: z32.number(),
5263
- organicUsers: z32.number(),
5261
+ /**
5262
+ * @deprecated Never emitted since 4.127.0 and removed in the next major.
5263
+ *
5264
+ * GA reports `totalUsers` as a COUNT DISTINCT at the grain requested, and
5265
+ * `ga_ai_referrals` is keyed by (date, source, medium, channelGroup,
5266
+ * landingPage, sourceDimension), so summing it re-counted the same visitor on
5267
+ * every extra day, page and channel. Unlike GA daily users, no
5268
+ * un-dimensioned AI-referral fetch exists to ask Google for the true figure,
5269
+ * so the number could not be corrected — only withdrawn. Optional rather than
5270
+ * deleted so existing API / `canonry report --format json` / MCP consumers
5271
+ * keep parsing; they now read `undefined` instead of an inflated number.
5272
+ */
5273
+ totalUsers: z32.number().optional(),
5274
+ /** @deprecated See `totalUsers`. Never emitted since 4.127.0. */
5275
+ paidUsers: z32.number().optional(),
5276
+ /** @deprecated See `totalUsers`. Never emitted since 4.127.0. */
5277
+ organicUsers: z32.number().optional(),
5264
5278
  bySource: z32.array(z32.object({
5265
5279
  source: z32.string(),
5266
5280
  sessions: z32.number(),
5267
- users: z32.number(),
5281
+ /** @deprecated See `totalUsers`. Never emitted since 4.127.0. */
5282
+ users: z32.number().optional(),
5268
5283
  paidSessions: z32.number(),
5269
5284
  organicSessions: z32.number(),
5270
5285
  sharePct: z32.number()
@@ -5273,7 +5288,8 @@ var aiReferralSectionSchema = z32.object({
5273
5288
  topLandingPages: z32.array(z32.object({
5274
5289
  page: z32.string(),
5275
5290
  sessions: z32.number(),
5276
- users: z32.number()
5291
+ /** @deprecated See `totalUsers`. Never emitted since 4.127.0. */
5292
+ users: z32.number().optional()
5277
5293
  }))
5278
5294
  });
5279
5295
  var serverActivitySectionSchema = z32.object({
@@ -336,7 +336,7 @@ import {
336
336
  wordpressSchemaDeployResultDtoSchema,
337
337
  wordpressSchemaStatusResultDtoSchema,
338
338
  wordpressStatusDtoSchema
339
- } from "./chunk-RFLNTI7Y.js";
339
+ } from "./chunk-BLSHHRRU.js";
340
340
 
341
341
  // src/intelligence-service.ts
342
342
  import { eq as eq41, desc as desc18, asc as asc9, and as and32, ne as ne6, or as or8, inArray as inArray15, gte as gte10, lte as lte6 } from "drizzle-orm";
@@ -12358,7 +12358,6 @@ function renderAiReferrals(report) {
12358
12358
  <tr>
12359
12359
  <td class="page-cell">${formatLandingPageHtml(p.page)}</td>
12360
12360
  <td class="numeric">${formatNumber(p.sessions)}</td>
12361
- <td class="numeric">${formatNumber(p.users)}</td>
12362
12361
  </tr>`).join("");
12363
12362
  const trendChart = renderLineChart(
12364
12363
  ai.trend.map((t) => ({ x: t.date, y: t.sessions, label: t.date.slice(5) })),
@@ -12369,13 +12368,12 @@ function renderAiReferrals(report) {
12369
12368
  { id: "ai-referrals", eyebrow: "Section 9", title: "AI Referral Traffic", intro: "Traffic arriving from AI answer engines." },
12370
12369
  `<div class="metric-grid">
12371
12370
  <div class="metric"><div class="label">Total sessions</div><div class="value">${formatNumber(ai.totalSessions)}</div></div>
12372
- <div class="metric"><div class="label">Total users</div><div class="value">${formatNumber(ai.totalUsers)}</div></div>
12373
12371
  </div>
12374
12372
  ${trendChart}
12375
12373
  ${sourceBars}
12376
12374
  <div class="chart-card"><h3>Top AI landing pages</h3>
12377
12375
  <table class="report-table">
12378
- <thead><tr><th>Page</th><th class="numeric">Sessions</th><th class="numeric">Users</th></tr></thead>
12376
+ <thead><tr><th>Page</th><th class="numeric">Sessions</th></tr></thead>
12379
12377
  <tbody>${pageRows}</tbody>
12380
12378
  </table>
12381
12379
  </div>`
@@ -13305,8 +13303,24 @@ function buildSocialReferrals(db, projectId) {
13305
13303
  topCampaigns
13306
13304
  };
13307
13305
  }
13308
- function buildAiReferrals(db, projectId) {
13309
- const rows = db.select().from(gaAiReferrals).where(eq16(gaAiReferrals.projectId, projectId)).all();
13306
+ function resolveAiReferralWindow(db, projectId, windowDays) {
13307
+ const windowKey = GA_WINDOW_SUMMARY_KEYS[windowDays];
13308
+ const windowSummary = windowKey ? db.select({ periodStart: gaTrafficWindowSummaries.periodStart, periodEnd: gaTrafficWindowSummaries.periodEnd }).from(gaTrafficWindowSummaries).where(and12(
13309
+ eq16(gaTrafficWindowSummaries.projectId, projectId),
13310
+ eq16(gaTrafficWindowSummaries.windowKey, windowKey)
13311
+ )).get() : void 0;
13312
+ if (windowSummary) return { start: windowSummary.periodStart, end: windowSummary.periodEnd };
13313
+ const latestSummary = db.select({ periodEnd: gaTrafficSummaries.periodEnd }).from(gaTrafficSummaries).where(eq16(gaTrafficSummaries.projectId, projectId)).orderBy(desc7(gaTrafficSummaries.syncedAt)).get();
13314
+ const end = latestSummary?.periodEnd ?? (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
13315
+ return { start: windowStartDate(end, windowDays), end };
13316
+ }
13317
+ function buildAiReferrals(db, projectId, windowDays) {
13318
+ const window = resolveAiReferralWindow(db, projectId, windowDays);
13319
+ const rows = db.select().from(gaAiReferrals).where(and12(
13320
+ eq16(gaAiReferrals.projectId, projectId),
13321
+ sql7`${gaAiReferrals.date} >= ${window.start}`,
13322
+ sql7`${gaAiReferrals.date} <= ${window.end}`
13323
+ )).all();
13310
13324
  if (rows.length === 0) return null;
13311
13325
  const dimSessionsByTuple = /* @__PURE__ */ new Map();
13312
13326
  for (const r of rows) {
@@ -13334,60 +13348,47 @@ function buildAiReferrals(db, projectId) {
13334
13348
  (r) => winningDimension.get(`${r.date}::${r.source}::${r.medium}`) === r.sourceDimension
13335
13349
  );
13336
13350
  let total = 0;
13337
- let totalUsers = 0;
13338
13351
  let paidSessions = 0;
13339
- let paidUsers = 0;
13340
13352
  let organicSessions = 0;
13341
- let organicUsers = 0;
13342
13353
  const sourceAgg = /* @__PURE__ */ new Map();
13343
13354
  const trendAgg = /* @__PURE__ */ new Map();
13344
13355
  const pageAgg = /* @__PURE__ */ new Map();
13345
13356
  for (const r of dedupedRows) {
13346
13357
  total += r.sessions;
13347
- totalUsers += r.users;
13348
13358
  const paid = isPaidAiTrafficClass(r.trafficClass);
13349
13359
  if (paid) {
13350
13360
  paidSessions += r.sessions;
13351
- paidUsers += r.users;
13352
13361
  } else {
13353
13362
  organicSessions += r.sessions;
13354
- organicUsers += r.users;
13355
13363
  }
13356
13364
  const s = sourceAgg.get(r.source) ?? {
13357
13365
  sessions: 0,
13358
- users: 0,
13359
13366
  paidSessions: 0,
13360
13367
  organicSessions: 0
13361
13368
  };
13362
13369
  s.sessions += r.sessions;
13363
- s.users += r.users;
13364
13370
  if (paid) s.paidSessions += r.sessions;
13365
13371
  else s.organicSessions += r.sessions;
13366
13372
  sourceAgg.set(r.source, s);
13367
13373
  trendAgg.set(r.date, (trendAgg.get(r.date) ?? 0) + r.sessions);
13368
13374
  const page = r.landingPageNormalized ?? r.landingPage;
13369
- const p = pageAgg.get(page) ?? { sessions: 0, users: 0 };
13375
+ const p = pageAgg.get(page) ?? { sessions: 0 };
13370
13376
  p.sessions += r.sessions;
13371
- p.users += r.users;
13372
13377
  pageAgg.set(page, p);
13373
13378
  }
13374
13379
  const bySource = [...sourceAgg.entries()].map(([source, data]) => ({
13375
13380
  source,
13376
13381
  sessions: data.sessions,
13377
- users: data.users,
13378
13382
  paidSessions: data.paidSessions,
13379
13383
  organicSessions: data.organicSessions,
13380
13384
  sharePct: total > 0 ? Math.round(data.sessions / total * 100) : 0
13381
13385
  })).sort((a, b) => b.sessions - a.sessions);
13382
13386
  const trend = [...trendAgg.entries()].map(([date, sessions]) => ({ date, sessions })).sort((a, b) => a.date.localeCompare(b.date));
13383
- const topLandingPages = [...pageAgg.entries()].map(([page, data]) => ({ page, sessions: data.sessions, users: data.users })).sort((a, b) => b.sessions - a.sessions).slice(0, TOP_AI_REFERRAL_PAGES_LIMIT);
13387
+ const topLandingPages = [...pageAgg.entries()].map(([page, data]) => ({ page, sessions: data.sessions })).sort((a, b) => b.sessions - a.sessions).slice(0, TOP_AI_REFERRAL_PAGES_LIMIT);
13384
13388
  return {
13385
13389
  totalSessions: total,
13386
- totalUsers,
13387
13390
  paidSessions,
13388
- paidUsers,
13389
13391
  organicSessions,
13390
- organicUsers,
13391
13392
  bySource,
13392
13393
  trend,
13393
13394
  topLandingPages
@@ -14392,7 +14393,7 @@ function buildProjectReport(db, projectName, periodDays) {
14392
14393
  );
14393
14394
  const gaSection = buildGaSection(db, project.id, periodDays);
14394
14395
  const socialSection = buildSocialReferrals(db, project.id);
14395
- const aiReferralsSection = buildAiReferrals(db, project.id);
14396
+ const aiReferralsSection = buildAiReferrals(db, project.id, periodDays);
14396
14397
  const serverActivitySection = buildServerActivity(db, project.id, periodDays);
14397
14398
  const indexingHealthSection = buildIndexingHealth(db, project.id);
14398
14399
  const citationsTrend = buildCitationsTrend(db, project.id, queryLookup, latestRunLocation);
@@ -24691,6 +24692,7 @@ var AdsActivationError = class extends Error {
24691
24692
  entity;
24692
24693
  };
24693
24694
  var DEFAULT_LEASE_MS = 5 * 6e4;
24695
+ var DEFAULT_ACTIVATION_VERIFICATION_RETRY_DELAYS_MS = [100, 250, 500, 1e3, 2e3, 2e3];
24694
24696
  var PROVIDER_PAUSED = "paused";
24695
24697
  var PROVIDER_ACTIVE = "active";
24696
24698
  function assertNever(value) {
@@ -25625,6 +25627,66 @@ async function validateActiveDescendants(ctx, parent) {
25625
25627
  );
25626
25628
  }
25627
25629
  }
25630
+ async function verifyActiveAfterMutation(ctx, target) {
25631
+ let lastUpdatedAt = null;
25632
+ for (let attempt = 0; ; attempt++) {
25633
+ let entity = null;
25634
+ try {
25635
+ entity = await readTarget(ctx.deps.provider, target);
25636
+ lastUpdatedAt = entity.updatedAt;
25637
+ } catch {
25638
+ }
25639
+ if (entity) {
25640
+ try {
25641
+ validateIdentity(target, entity);
25642
+ validateAdApproval(target, entity);
25643
+ } catch (cause) {
25644
+ return {
25645
+ ok: false,
25646
+ error: cause instanceof AdsActivationError ? cause : targetError(
25647
+ AdsActivationErrorCodes.providerMutationFailed,
25648
+ "Provider activation validation failed",
25649
+ 502,
25650
+ target
25651
+ ),
25652
+ providerUpdatedAt: entity.updatedAt
25653
+ };
25654
+ }
25655
+ if (entity.status === PROVIDER_ACTIVE && entity.updatedAt !== null) {
25656
+ return { ok: true, entity };
25657
+ }
25658
+ const exactPreMutationSnapshot = entity.status === PROVIDER_PAUSED && entity.updatedAt === target.expectedUpdatedAt;
25659
+ if (!exactPreMutationSnapshot) {
25660
+ return {
25661
+ ok: false,
25662
+ error: targetError(
25663
+ AdsActivationErrorCodes.providerMutationFailed,
25664
+ "Provider did not confirm the required active state",
25665
+ 502,
25666
+ target
25667
+ ),
25668
+ providerUpdatedAt: entity.updatedAt
25669
+ };
25670
+ }
25671
+ }
25672
+ if (attempt >= ctx.deps.activationVerificationRetryDelaysMs.length) {
25673
+ return {
25674
+ ok: false,
25675
+ error: targetError(
25676
+ AdsActivationErrorCodes.providerMutationFailed,
25677
+ "Provider activation outcome could not be verified",
25678
+ 502,
25679
+ target
25680
+ ),
25681
+ providerUpdatedAt: lastUpdatedAt
25682
+ };
25683
+ }
25684
+ const delayMs = ctx.deps.activationVerificationRetryDelaysMs[attempt];
25685
+ await renewLease(ctx);
25686
+ await ctx.deps.sleep(delayMs);
25687
+ await renewLease(ctx);
25688
+ }
25689
+ }
25628
25690
  async function activateOne(ctx, original) {
25629
25691
  let step = currentStep(ctx, original.id);
25630
25692
  if (step.state === AdsOperationStepStates.active) {
@@ -25676,25 +25738,16 @@ async function activateOne(ctx, original) {
25676
25738
  } catch {
25677
25739
  }
25678
25740
  await renewLease(ctx);
25679
- let entity;
25680
- try {
25681
- entity = await readTarget(ctx.deps.provider, target);
25682
- } catch {
25683
- const error = targetError(AdsActivationErrorCodes.providerMutationFailed, "Provider activation outcome could not be verified", 502, target);
25684
- await transitionStep(ctx, step, unknownStep(step, error, null, ctx.deps.now().toISOString()));
25685
- throw error;
25686
- }
25687
- try {
25688
- validateIdentity(target, entity);
25689
- validateAdApproval(target, entity);
25690
- if (entity.status !== PROVIDER_ACTIVE || entity.updatedAt === null) {
25691
- throw targetError(AdsActivationErrorCodes.providerMutationFailed, "Provider did not confirm the required active state", 502, target);
25692
- }
25693
- } catch (cause) {
25694
- const error = cause instanceof AdsActivationError ? cause : targetError(AdsActivationErrorCodes.providerMutationFailed, "Provider activation validation failed", 502, target);
25695
- await transitionStep(ctx, step, unknownStep(step, error, entity.updatedAt, ctx.deps.now().toISOString()));
25696
- throw error;
25741
+ const verification = await verifyActiveAfterMutation(ctx, target);
25742
+ if (!verification.ok) {
25743
+ await transitionStep(
25744
+ ctx,
25745
+ step,
25746
+ unknownStep(step, verification.error, verification.providerUpdatedAt, ctx.deps.now().toISOString())
25747
+ );
25748
+ throw verification.error;
25697
25749
  }
25750
+ const { entity } = verification;
25698
25751
  await validateExactDescendants(
25699
25752
  ctx.deps.provider,
25700
25753
  ctx.manifest,
@@ -25878,11 +25931,22 @@ async function executeApprovedAdsActivation(dependencies, request) {
25878
25931
  provider: dependencies.provider,
25879
25932
  now: dependencies.now ?? (() => /* @__PURE__ */ new Date()),
25880
25933
  randomId: dependencies.randomId ?? (() => crypto20.randomUUID()),
25881
- leaseMs: dependencies.leaseMs ?? DEFAULT_LEASE_MS
25934
+ leaseMs: dependencies.leaseMs ?? DEFAULT_LEASE_MS,
25935
+ sleep: dependencies.sleep ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms))),
25936
+ activationVerificationRetryDelaysMs: dependencies.activationVerificationRetryDelaysMs ?? DEFAULT_ACTIVATION_VERIFICATION_RETRY_DELAYS_MS
25882
25937
  };
25883
25938
  if (!Number.isSafeInteger(deps.leaseMs) || deps.leaseMs <= 0) {
25884
25939
  throw new AdsActivationError(AdsActivationErrorCodes.invalidManifest, "Activation lease duration is invalid", 400);
25885
25940
  }
25941
+ if (deps.activationVerificationRetryDelaysMs.some(
25942
+ (delay) => !Number.isSafeInteger(delay) || delay < 0
25943
+ )) {
25944
+ throw new AdsActivationError(
25945
+ AdsActivationErrorCodes.invalidManifest,
25946
+ "Activation verification retry delays are invalid",
25947
+ 400
25948
+ );
25949
+ }
25886
25950
  const now = deps.now();
25887
25951
  const operationId = deps.randomId();
25888
25952
  const leaseOwner = deps.randomId();
@@ -37,7 +37,7 @@ import {
37
37
  trafficConnectVercelRequestSchema,
38
38
  trafficConnectWordpressRequestSchema,
39
39
  trafficEventKindSchema
40
- } from "./chunk-RFLNTI7Y.js";
40
+ } from "./chunk-BLSHHRRU.js";
41
41
 
42
42
  // src/config.ts
43
43
  import fs from "fs";
package/dist/cli.js CHANGED
@@ -29,7 +29,7 @@ import {
29
29
  setTelemetrySource,
30
30
  showFirstRunNotice,
31
31
  trackEvent
32
- } from "./chunk-M6GKSLOJ.js";
32
+ } from "./chunk-A4YBV4Y4.js";
33
33
  import {
34
34
  CliError,
35
35
  EXIT_SYSTEM_ERROR,
@@ -46,7 +46,7 @@ import {
46
46
  saveConfig,
47
47
  saveConfigPatch,
48
48
  usageError
49
- } from "./chunk-WA57WG6W.js";
49
+ } from "./chunk-IHRW6WWV.js";
50
50
  import {
51
51
  apiKeys,
52
52
  createClient,
@@ -54,7 +54,7 @@ import {
54
54
  projects,
55
55
  queries,
56
56
  renderReportHtml
57
- } from "./chunk-FCGRCCX6.js";
57
+ } from "./chunk-HQRUFTLN.js";
58
58
  import {
59
59
  AdsOperationKinds,
60
60
  AdsOperationStates,
@@ -95,7 +95,7 @@ import {
95
95
  providerQuotaPolicySchema,
96
96
  resolveProviderInput,
97
97
  winnabilityClassSchema
98
- } from "./chunk-RFLNTI7Y.js";
98
+ } from "./chunk-BLSHHRRU.js";
99
99
 
100
100
  // src/cli.ts
101
101
  import { pathToFileURL } from "url";
package/dist/index.js CHANGED
@@ -1,11 +1,11 @@
1
1
  import {
2
2
  createServer
3
- } from "./chunk-M6GKSLOJ.js";
3
+ } from "./chunk-A4YBV4Y4.js";
4
4
  import {
5
5
  loadConfig
6
- } from "./chunk-WA57WG6W.js";
7
- import "./chunk-FCGRCCX6.js";
8
- import "./chunk-RFLNTI7Y.js";
6
+ } from "./chunk-IHRW6WWV.js";
7
+ import "./chunk-HQRUFTLN.js";
8
+ import "./chunk-BLSHHRRU.js";
9
9
  export {
10
10
  createServer,
11
11
  loadConfig
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  IntelligenceService
3
- } from "./chunk-FCGRCCX6.js";
4
- import "./chunk-RFLNTI7Y.js";
3
+ } from "./chunk-HQRUFTLN.js";
4
+ import "./chunk-BLSHHRRU.js";
5
5
  export {
6
6
  IntelligenceService
7
7
  };
package/dist/mcp.js CHANGED
@@ -3,10 +3,10 @@ import {
3
3
  PACKAGE_VERSION,
4
4
  canonryMcpTools,
5
5
  createApiClient
6
- } from "./chunk-WA57WG6W.js";
6
+ } from "./chunk-IHRW6WWV.js";
7
7
  import {
8
8
  isReadOnlyKey
9
- } from "./chunk-RFLNTI7Y.js";
9
+ } from "./chunk-BLSHHRRU.js";
10
10
 
11
11
  // src/mcp/cli.ts
12
12
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@canonry/canonry",
3
- "version": "4.126.0",
3
+ "version": "4.127.0",
4
4
  "type": "module",
5
5
  "description": "Agent-first open-source AEO operating platform - track how answer engines cite your domain",
6
6
  "license": "FSL-1.1-ALv2",
@@ -67,25 +67,25 @@
67
67
  "tsx": "^4.19.0",
68
68
  "@ainyc/canonry-api-client": "0.0.0",
69
69
  "@ainyc/canonry-api-routes": "0.0.0",
70
+ "@ainyc/canonry-config": "0.0.0",
70
71
  "@ainyc/canonry-contracts": "0.0.0",
71
72
  "@ainyc/canonry-db": "0.0.0",
72
- "@ainyc/canonry-config": "0.0.0",
73
73
  "@ainyc/canonry-integration-bing": "0.0.0",
74
74
  "@ainyc/canonry-integration-openai-ads": "0.0.0",
75
75
  "@ainyc/canonry-integration-cloud-run": "0.0.0",
76
76
  "@ainyc/canonry-integration-commoncrawl": "0.0.0",
77
77
  "@ainyc/canonry-integration-google": "0.0.0",
78
- "@ainyc/canonry-integration-google-business-profile": "0.0.0",
79
78
  "@ainyc/canonry-integration-google-places": "0.0.0",
79
+ "@ainyc/canonry-intelligence": "0.0.0",
80
80
  "@ainyc/canonry-integration-traffic": "0.0.0",
81
81
  "@ainyc/canonry-integration-wordpress": "0.0.0",
82
- "@ainyc/canonry-intelligence": "0.0.0",
83
82
  "@ainyc/canonry-provider-cdp": "0.0.0",
83
+ "@ainyc/canonry-provider-claude": "0.0.0",
84
+ "@ainyc/canonry-integration-google-business-profile": "0.0.0",
84
85
  "@ainyc/canonry-provider-local": "0.0.0",
85
86
  "@ainyc/canonry-provider-openai": "0.0.0",
86
- "@ainyc/canonry-provider-gemini": "0.0.0",
87
87
  "@ainyc/canonry-provider-perplexity": "0.0.0",
88
- "@ainyc/canonry-provider-claude": "0.0.0"
88
+ "@ainyc/canonry-provider-gemini": "0.0.0"
89
89
  },
90
90
  "scripts": {
91
91
  "build": "tsx scripts/copy-agent-assets.ts && tsup && tsx build-web.ts",