@canonry/canonry 4.165.1 → 4.166.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 (28) hide show
  1. package/README.md +11 -1
  2. package/assets/agent-workspace/skills/canonry/references/server-side-traffic.md +75 -3
  3. package/assets/assets/{AuditHistoryPanel-IYMElyK5.js → AuditHistoryPanel-CZByTZjH.js} +1 -1
  4. package/assets/assets/{BacklinksPage-BMqIPRvZ.js → BacklinksPage-DPsSKu1M.js} +1 -1
  5. package/assets/assets/{HistoryPage-iuETLmwO.js → HistoryPage-9acsanzg.js} +1 -1
  6. package/assets/assets/{MeasurementPropertyPage-BzNAaB8X.js → MeasurementPropertyPage-gIOHHJ4x.js} +1 -1
  7. package/assets/assets/ProjectPage-CTic0OFR.js +9 -0
  8. package/assets/assets/{RunRow-BkkYxEjl.js → RunRow-cuE1cBCg.js} +1 -1
  9. package/assets/assets/{RunsPage-DGTrqrTA.js → RunsPage-Bt6T2Kz2.js} +1 -1
  10. package/assets/assets/SettingsPage-ChyewFuC.js +1 -0
  11. package/assets/assets/{SiteHealthSection-k4I71wfJ.js → SiteHealthSection-BYM32RDv.js} +3 -3
  12. package/assets/assets/{TrafficPage-C8nyb8l1.js → TrafficPage-DMpuFJua.js} +1 -1
  13. package/assets/assets/{TrafficSourceDetailPage-ry7Da0pV.js → TrafficSourceDetailPage-D4G26uyv.js} +1 -1
  14. package/assets/assets/{extract-error-message-BYyBW07F.js → extract-error-message-D7fD7zwP.js} +1 -1
  15. package/assets/assets/{index-rqOXhYwp.js → index-BliSumN-.js} +20 -20
  16. package/assets/assets/{react-sigma_core.esm.min-BtG8TWTe.js → react-sigma_core.esm.min-CmW2JaYh.js} +1 -1
  17. package/assets/index.html +1 -1
  18. package/dist/{chunk-BU6C2DKF.js → chunk-GU7T2JUB.js} +24 -2
  19. package/dist/{chunk-L5SMSDZB.js → chunk-IUWFALUQ.js} +85 -94
  20. package/dist/{chunk-QKLNTSQ2.js → chunk-KU45I42F.js} +66 -64
  21. package/dist/{chunk-QDOZEMDK.js → chunk-QFMHIUV7.js} +6 -5
  22. package/dist/cli.js +29 -28
  23. package/dist/index.js +4 -4
  24. package/dist/{intelligence-service-RDGUEEZQ.js → intelligence-service-KRQNQNEB.js} +2 -2
  25. package/dist/mcp.js +2 -2
  26. package/package.json +11 -11
  27. package/assets/assets/ProjectPage-DIzi4Ggo.js +0 -9
  28. package/assets/assets/SettingsPage-Cwb_Ft9u.js +0 -1
@@ -236,6 +236,7 @@ import {
236
236
  deriveCitedUrlCandidates,
237
237
  deriveSiteHealthState,
238
238
  deriveWinnabilityClass,
239
+ describeError,
239
240
  determineAnswerMentioned,
240
241
  discoveryBucketSchema,
241
242
  discoveryHarvestDtoSchema,
@@ -470,6 +471,7 @@ import {
470
471
  recommendationExplainRequestSchema,
471
472
  recommendationExplanationDtoSchema,
472
473
  registrableDomain,
474
+ relativeChangeRatio,
473
475
  reportActionCategoryLabel,
474
476
  reportActionTone,
475
477
  reportComparisonWindowDays,
@@ -582,7 +584,7 @@ import {
582
584
  wordpressSchemaDeployResultDtoSchema,
583
585
  wordpressSchemaStatusResultDtoSchema,
584
586
  wordpressStatusDtoSchema
585
- } from "./chunk-BU6C2DKF.js";
587
+ } from "./chunk-GU7T2JUB.js";
586
588
 
587
589
  // src/intelligence-service.ts
588
590
  import { eq as eq59, desc as desc26, asc as asc11, and as and47, ne as ne7, or as or13, inArray as inArray21, gte as gte14, lte as lte12 } from "drizzle-orm";
@@ -8635,7 +8637,9 @@ function pickWorstKeywordDrop(loc) {
8635
8637
  let worst = null;
8636
8638
  for (const point of loc.keywordPoints) {
8637
8639
  if (point.recent == null || point.prior == null || point.prior < GBP_KEYWORD_MIN_BASELINE) continue;
8638
- const dropPct = Math.round((point.prior - point.recent) / point.prior * 100);
8640
+ const changeRatio = relativeChangeRatio(point.recent, point.prior);
8641
+ if (changeRatio === null) continue;
8642
+ const dropPct = Math.round(-changeRatio * 100);
8639
8643
  if (dropPct < GBP_KEYWORD_DROP_PCT) continue;
8640
8644
  if (!worst || dropPct > worst.dropPct) {
8641
8645
  worst = { keyword: point.keyword, dropPct, recent: point.recent, prior: point.prior };
@@ -13630,7 +13634,7 @@ function assertLimits(limits) {
13630
13634
  // ../api-routes/src/measurement-service.ts
13631
13635
  var DEFAULT_DISCOVERY_URL_LIMIT = 1e4;
13632
13636
  function messageOf(error) {
13633
- return error instanceof Error ? error.message : String(error);
13637
+ return describeError(error);
13634
13638
  }
13635
13639
  async function measurementServiceRoutes(app, opts) {
13636
13640
  app.post("/projects/:name/measurement-discovery", {
@@ -16719,7 +16723,7 @@ function availableStableKey(preferred, taken) {
16719
16723
  throw validationError(`Discovery could not find a free stable key for '${preferred}'.`);
16720
16724
  }
16721
16725
  function messageOf2(error) {
16722
- return error instanceof Error ? error.message : String(error);
16726
+ return describeError(error);
16723
16727
  }
16724
16728
  async function measurementDiscoveryV2Routes(app) {
16725
16729
  app.post("/projects/:name/measurement-plan/draft/actions/import-sitemap", async (request, reply) => {
@@ -19088,7 +19092,7 @@ async function applyRoutes(app, opts) {
19088
19092
  try {
19089
19093
  cronExpr = resolvePreset(schedSpec.preset);
19090
19094
  } catch (err) {
19091
- const msg = err instanceof Error ? err.message : String(err);
19095
+ const msg = describeError(err);
19092
19096
  throw validationError(msg);
19093
19097
  }
19094
19098
  } else if (schedSpec.cron) {
@@ -25913,7 +25917,7 @@ function summarizeServer(crawlers, fetches, referrals) {
25913
25917
  }
25914
25918
  function comparisonDetail(latest, prior) {
25915
25919
  if (prior === 0) return `${latest} in the latest cohort versus 0 in the prior cohort`;
25916
- const change = Math.round((latest - prior) / prior * 100);
25920
+ const change = deltaPercent(latest, prior) ?? 0;
25917
25921
  return `${latest} in the latest cohort versus ${prior} prior (${change >= 0 ? "+" : ""}${change}%)`;
25918
25922
  }
25919
25923
  function aggregateCoverage(row) {
@@ -35135,7 +35139,7 @@ async function scheduleRoutes(app, opts) {
35135
35139
  try {
35136
35140
  cronExpr = resolvePreset(preset);
35137
35141
  } catch (err) {
35138
- const msg = err instanceof Error ? err.message : String(err);
35142
+ const msg = describeError(err);
35139
35143
  throw validationError(msg);
35140
35144
  }
35141
35145
  } else {
@@ -35612,7 +35616,7 @@ function computeWindowDelta(rows, referenceDate) {
35612
35616
  const prior = prior7d[metric2] ?? 0;
35613
35617
  recent7d[metric2] = recent;
35614
35618
  prior7d[metric2] = prior;
35615
- deltaPct[metric2] = prior === 0 ? null : Math.round((recent - prior) / prior * 100);
35619
+ deltaPct[metric2] = deltaPercent(recent, prior);
35616
35620
  }
35617
35621
  return { recent7d, prior7d, deltaPct };
35618
35622
  }
@@ -37622,7 +37626,7 @@ function gscErrorToAppError(err, context) {
37622
37626
  status != null ? { upstreamStatus: status } : void 0
37623
37627
  );
37624
37628
  }
37625
- return providerError(`${context}: ${err instanceof Error ? err.message : String(err)}`);
37629
+ return providerError(`${context}: ${describeError(err)}`);
37626
37630
  }
37627
37631
  async function googleRoutes(app, opts) {
37628
37632
  if (opts.googleStateSecret === void 0) {
@@ -37756,7 +37760,7 @@ async function googleRoutes(app, opts) {
37756
37760
  try {
37757
37761
  tokens = await exchangeCode(googleClientId, googleClientSecret, code, redirectUri);
37758
37762
  } catch (err) {
37759
- const msg = err instanceof Error ? err.message : String(err);
37763
+ const msg = describeError(err);
37760
37764
  return reply.type("text/html").send(
37761
37765
  `<html><body style="font-family:system-ui;padding:40px;max-width:600px;margin:0 auto">
37762
37766
  <h2 style="color:#ef4444">Token exchange failed</h2>
@@ -38377,7 +38381,7 @@ async function googleRoutes(app, opts) {
38377
38381
  });
38378
38382
  results.push({ sitemapUrl, status: "accepted", submittedAt });
38379
38383
  } catch (err) {
38380
- results.push({ sitemapUrl, status: "error", error: err instanceof Error ? err.message : String(err) });
38384
+ results.push({ sitemapUrl, status: "error", error: describeError(err) });
38381
38385
  }
38382
38386
  }
38383
38387
  const accepted = results.filter((result) => result.status === "accepted").length;
@@ -38552,7 +38556,7 @@ async function googleRoutes(app, opts) {
38552
38556
  status: "success"
38553
38557
  });
38554
38558
  } catch (err) {
38555
- const msg = err instanceof Error ? err.message : String(err);
38559
+ const msg = describeError(err);
38556
38560
  results.push({
38557
38561
  url,
38558
38562
  type: "URL_UPDATED",
@@ -42864,7 +42868,7 @@ async function adsRoutes(app, opts) {
42864
42868
  try {
42865
42869
  account = await opts.verifyAdsAccount(parsed.data.apiKey);
42866
42870
  } catch (err) {
42867
- const message = err instanceof Error ? err.message : String(err);
42871
+ const message = describeError(err);
42868
42872
  throw validationError(`OpenAI Ads API rejected the key: ${message}`);
42869
42873
  }
42870
42874
  const now = (/* @__PURE__ */ new Date()).toISOString();
@@ -44201,7 +44205,7 @@ async function bingRoutes(app, opts) {
44201
44205
  sites = await getSites(apiKey);
44202
44206
  bingLog("info", "connect.verify-key", { domain: project.canonicalDomain, siteCount: sites.length });
44203
44207
  } catch (e) {
44204
- const msg = e instanceof Error ? e.message : String(e);
44208
+ const msg = describeError(e);
44205
44209
  bingLog("error", "connect.verify-key-failed", { domain: project.canonicalDomain, error: msg });
44206
44210
  throw validationError(`Failed to verify Bing API key: ${msg}`);
44207
44211
  }
@@ -44469,7 +44473,7 @@ async function bingRoutes(app, opts) {
44469
44473
  } catch (e) {
44470
44474
  bingLog("warn", "inspect-url.crawl-issues-lookup-failed", {
44471
44475
  domain: project.canonicalDomain,
44472
- error: e instanceof Error ? e.message : String(e)
44476
+ error: describeError(e)
44473
44477
  });
44474
44478
  }
44475
44479
  }
@@ -44502,7 +44506,7 @@ async function bingRoutes(app, opts) {
44502
44506
  discoveryDate
44503
44507
  };
44504
44508
  } catch (e) {
44505
- const msg = e instanceof Error ? e.message : String(e);
44509
+ const msg = describeError(e);
44506
44510
  bingLog("error", "inspect-url.failed", { domain: project.canonicalDomain, url, error: msg });
44507
44511
  app.db.update(runs).set({ status: RunStatuses.failed, error: msg, finishedAt: (/* @__PURE__ */ new Date()).toISOString() }).where(eq42(runs.id, runId)).run();
44508
44512
  throw e;
@@ -44580,7 +44584,7 @@ async function bingRoutes(app, opts) {
44580
44584
  }
44581
44585
  bingLog("info", "index-submit.batch-ok", { domain: project.canonicalDomain, batchSize: batch.length, urls: batch });
44582
44586
  } catch (e) {
44583
- const msg = e instanceof Error ? e.message : String(e);
44587
+ const msg = describeError(e);
44584
44588
  const now = (/* @__PURE__ */ new Date()).toISOString();
44585
44589
  for (const url of batch) {
44586
44590
  results.push({ url, status: "error", submittedAt: now, error: msg });
@@ -44595,7 +44599,7 @@ async function bingRoutes(app, opts) {
44595
44599
  results.push({ url, status: "success", submittedAt: (/* @__PURE__ */ new Date()).toISOString() });
44596
44600
  bingLog("info", "index-submit.ok", { domain: project.canonicalDomain, url });
44597
44601
  } catch (e) {
44598
- const msg = e instanceof Error ? e.message : String(e);
44602
+ const msg = describeError(e);
44599
44603
  results.push({ url, status: "error", submittedAt: (/* @__PURE__ */ new Date()).toISOString(), error: msg });
44600
44604
  bingLog("error", "index-submit.failed", { domain: project.canonicalDomain, url, error: msg });
44601
44605
  }
@@ -45153,7 +45157,7 @@ function ga4ErrorToAppError(err, context) {
45153
45157
  }
45154
45158
  return providerError(`${context}: ${err.message}`);
45155
45159
  }
45156
- return providerError(`${context}: ${err instanceof Error ? err.message : String(err)}`);
45160
+ return providerError(`${context}: ${describeError(err)}`);
45157
45161
  }
45158
45162
  async function resolveGa4AccessToken(opts, projectName, canonicalDomain) {
45159
45163
  const saConn = opts.ga4CredentialStore?.getConnection(projectName);
@@ -45219,7 +45223,7 @@ async function ga4Routes(app, opts) {
45219
45223
  await verifyConnection(clientEmail, privateKey, propertyId);
45220
45224
  gaLog("info", "connect.verified.service-account", { projectId: project.id, propertyId });
45221
45225
  } catch (e) {
45222
- const msg = e instanceof Error ? e.message : String(e);
45226
+ const msg = describeError(e);
45223
45227
  gaLog("error", "connect.verify-failed", { projectId: project.id, propertyId, error: msg });
45224
45228
  throw validationError(`Failed to verify GA4 credentials: ${msg}`);
45225
45229
  }
@@ -45264,7 +45268,7 @@ async function ga4Routes(app, opts) {
45264
45268
  await verifyConnectionWithToken(accessToken, propertyId);
45265
45269
  gaLog("info", "connect.verified.oauth", { projectId: project.id, propertyId });
45266
45270
  } catch (e) {
45267
- const msg = e instanceof Error ? e.message : String(e);
45271
+ const msg = describeError(e);
45268
45272
  gaLog("error", "connect.verify-failed.oauth", { projectId: project.id, propertyId, error: msg });
45269
45273
  throw validationError(`Failed to verify GA4 access: ${msg}`);
45270
45274
  }
@@ -45550,7 +45554,7 @@ async function ga4Routes(app, opts) {
45550
45554
  const [acquisitionSettled, leadsSettled] = await measurementFetch;
45551
45555
  const measurementNow = (/* @__PURE__ */ new Date()).toISOString();
45552
45556
  const recordMeasurementFailure = (component, reason) => {
45553
- const message = reason instanceof Error ? reason.message : String(reason);
45557
+ const message = describeError(reason);
45554
45558
  gaLog("warn", "measurement.component-failed", {
45555
45559
  projectId: project.id,
45556
45560
  runId,
@@ -45564,7 +45568,7 @@ async function ga4Routes(app, opts) {
45564
45568
  projectId: project.id,
45565
45569
  runId,
45566
45570
  component,
45567
- error: stateError instanceof Error ? stateError.message : String(stateError)
45571
+ error: describeError(stateError)
45568
45572
  });
45569
45573
  }
45570
45574
  return { status: "error", days: component === "acquisition" ? acquisitionDays : leadDays, rowCount: 0, error: message };
@@ -45648,7 +45652,7 @@ async function ga4Routes(app, opts) {
45648
45652
  ...syncedComponents ? { syncedComponents } : {}
45649
45653
  };
45650
45654
  } catch (e) {
45651
- const msg = e instanceof Error ? e.message : String(e);
45655
+ const msg = describeError(e);
45652
45656
  gaLog("error", "sync.fetch-failed", { projectId: project.id, runId, error: msg });
45653
45657
  app.db.update(runs).set({ status: RunStatuses.failed, error: msg, finishedAt: (/* @__PURE__ */ new Date()).toISOString() }).where(eq44(runs.id, runId)).run();
45654
45658
  throw e;
@@ -45941,7 +45945,6 @@ async function ga4Routes(app, opts) {
45941
45945
  const prev7d = sumSocial(daysAgo(14), daysAgo(7));
45942
45946
  const current30d = sumSocial(daysAgo(30), fmt(today));
45943
45947
  const prev30d = sumSocial(daysAgo(60), daysAgo(30));
45944
- const pct = (cur, prev) => prev === 0 ? null : Math.round((cur - prev) / prev * 100);
45945
45948
  const sourceCurrent = app.db.select({
45946
45949
  source: gaSocialReferrals.source,
45947
45950
  sessions: sql16`SUM(${gaSocialReferrals.sessions})`
@@ -45970,17 +45973,17 @@ async function ga4Routes(app, opts) {
45970
45973
  source: row.source,
45971
45974
  sessions7d: row.sessions,
45972
45975
  sessionsPrev7d: prev,
45973
- changePct: pct(row.sessions, prev) ?? (row.sessions > 0 ? 100 : 0)
45976
+ changePct: deltaPercent(row.sessions, prev) ?? (row.sessions > 0 ? 100 : 0)
45974
45977
  };
45975
45978
  }
45976
45979
  }
45977
45980
  return {
45978
45981
  socialSessions7d: current7d?.sessions ?? 0,
45979
45982
  socialSessionsPrev7d: prev7d?.sessions ?? 0,
45980
- trend7dPct: pct(current7d?.sessions ?? 0, prev7d?.sessions ?? 0),
45983
+ trend7dPct: deltaPercent(current7d?.sessions ?? 0, prev7d?.sessions ?? 0),
45981
45984
  socialSessions30d: current30d?.sessions ?? 0,
45982
45985
  socialSessionsPrev30d: prev30d?.sessions ?? 0,
45983
- trend30dPct: pct(current30d?.sessions ?? 0, prev30d?.sessions ?? 0),
45986
+ trend30dPct: deltaPercent(current30d?.sessions ?? 0, prev30d?.sessions ?? 0),
45984
45987
  biggestMover
45985
45988
  };
45986
45989
  });
@@ -45994,7 +45997,6 @@ async function ga4Routes(app, opts) {
45994
45997
  d.setDate(d.getDate() - n);
45995
45998
  return fmt(d);
45996
45999
  };
45997
- const pct = (cur, prev) => prev === 0 ? null : Math.round((cur - prev) / prev * 100);
45998
46000
  const sumTotal = (from, to) => app.db.select({ sessions: sql16`COALESCE(SUM(${gaTrafficSnapshots.sessions}), 0)` }).from(gaTrafficSnapshots).where(and35(eq44(gaTrafficSnapshots.projectId, project.id), sql16`${gaTrafficSnapshots.date} >= ${from}`, sql16`${gaTrafficSnapshots.date} < ${to}`)).get();
45999
46001
  const sumOrganic = (from, to) => app.db.select({ sessions: sql16`COALESCE(SUM(${gaTrafficSnapshots.organicSessions}), 0)` }).from(gaTrafficSnapshots).where(and35(eq44(gaTrafficSnapshots.projectId, project.id), sql16`${gaTrafficSnapshots.date} >= ${from}`, sql16`${gaTrafficSnapshots.date} < ${to}`)).get();
46000
46002
  const sumDirect = (from, to) => app.db.select({ sessions: sql16`COALESCE(SUM(${gaTrafficSnapshots.directSessions}), 0)` }).from(gaTrafficSnapshots).where(and35(eq44(gaTrafficSnapshots.projectId, project.id), sql16`${gaTrafficSnapshots.date} >= ${from}`, sql16`${gaTrafficSnapshots.date} < ${to}`)).get();
@@ -46011,7 +46013,7 @@ async function ga4Routes(app, opts) {
46011
46013
  const p7 = sum(daysAgo(14), daysAgo(7))?.sessions ?? 0;
46012
46014
  const c30 = sum(daysAgo(30), todayStr)?.sessions ?? 0;
46013
46015
  const p30 = sum(daysAgo(60), daysAgo(30))?.sessions ?? 0;
46014
- return { sessions7d: c7, sessionsPrev7d: p7, trend7dPct: pct(c7, p7), sessions30d: c30, sessionsPrev30d: p30, trend30dPct: pct(c30, p30) };
46016
+ return { sessions7d: c7, sessionsPrev7d: p7, trend7dPct: deltaPercent(c7, p7), sessions30d: c30, sessionsPrev30d: p30, trend30dPct: deltaPercent(c30, p30) };
46015
46017
  };
46016
46018
  const aiSourceCurrent = app.db.select({ source: gaAiReferrals.source, sessions: sql16`COALESCE(SUM(${gaAiReferrals.sessions}), 0)` }).from(gaAiReferrals).where(and35(
46017
46019
  eq44(gaAiReferrals.projectId, project.id),
@@ -46034,7 +46036,7 @@ async function ga4Routes(app, opts) {
46034
46036
  const delta = Math.abs(row.sessions - p);
46035
46037
  if (delta > maxDelta) {
46036
46038
  maxDelta = delta;
46037
- mover = { source: row.source, sessions7d: row.sessions, sessionsPrev7d: p, changePct: pct(row.sessions, p) ?? (row.sessions > 0 ? 100 : 0) };
46039
+ mover = { source: row.source, sessions7d: row.sessions, sessionsPrev7d: p, changePct: deltaPercent(row.sessions, p) ?? (row.sessions > 0 ? 100 : 0) };
46038
46040
  }
46039
46041
  }
46040
46042
  return mover;
@@ -46531,7 +46533,7 @@ async function getSiteStatus(connection, env) {
46531
46533
  authenticatedUser: userInfo
46532
46534
  };
46533
46535
  } catch (error) {
46534
- const message = error instanceof Error ? error.message : String(error);
46536
+ const message = describeError(error);
46535
46537
  return {
46536
46538
  url: site.siteUrl,
46537
46539
  reachable: false,
@@ -46812,7 +46814,7 @@ async function bulkSetSeoMeta(connection, entries, env) {
46812
46814
  return {
46813
46815
  slug: entry.slug,
46814
46816
  status: "skipped",
46815
- error: error instanceof Error ? error.message : String(error)
46817
+ error: describeError(error)
46816
46818
  };
46817
46819
  }
46818
46820
  }
@@ -46893,7 +46895,7 @@ async function deploySchema(connection, slug, schemas, env) {
46893
46895
  return {
46894
46896
  slug,
46895
46897
  status: "failed",
46896
- error: error instanceof Error ? error.message : String(error)
46898
+ error: describeError(error)
46897
46899
  };
46898
46900
  }
46899
46901
  }
@@ -47580,7 +47582,7 @@ async function wordpressRoutes(app, opts) {
47580
47582
  });
47581
47583
  steps.push({ name: "connect", status: "completed", summary: `Connected to ${url}` });
47582
47584
  } catch (err) {
47583
- const msg = err instanceof Error ? err.message : String(err);
47585
+ const msg = describeError(err);
47584
47586
  steps.push({ name: "connect", status: "failed", error: msg });
47585
47587
  return { projectName: project.name, steps };
47586
47588
  }
@@ -47596,7 +47598,7 @@ async function wordpressRoutes(app, opts) {
47596
47598
  pageUrls = pageSummaries.map((p) => p.link).filter((link) => typeof link === "string" && link.length > 0);
47597
47599
  steps.push({ name: "audit", status: "completed", summary: `${pageCount} pages audited, ${issueCount} issues` });
47598
47600
  } catch (err) {
47599
- const msg = err instanceof Error ? err.message : String(err);
47601
+ const msg = describeError(err);
47600
47602
  steps.push({ name: "audit", status: "failed", error: msg });
47601
47603
  return { projectName: project.name, steps };
47602
47604
  }
@@ -47636,7 +47638,7 @@ async function wordpressRoutes(app, opts) {
47636
47638
  });
47637
47639
  }
47638
47640
  } catch (err) {
47639
- const msg = err instanceof Error ? err.message : String(err);
47641
+ const msg = describeError(err);
47640
47642
  steps.push({ name: "set-meta", status: "failed", error: msg });
47641
47643
  return { projectName: project.name, steps };
47642
47644
  }
@@ -47662,7 +47664,7 @@ async function wordpressRoutes(app, opts) {
47662
47664
  });
47663
47665
  }
47664
47666
  } catch (err) {
47665
- const msg = err instanceof Error ? err.message : String(err);
47667
+ const msg = describeError(err);
47666
47668
  steps.push({ name: "schema-deploy", status: "failed", error: msg });
47667
47669
  return { projectName: project.name, steps };
47668
47670
  }
@@ -47694,7 +47696,7 @@ async function wordpressRoutes(app, opts) {
47694
47696
  }
47695
47697
  }
47696
47698
  } catch (err) {
47697
- const msg = err instanceof Error ? err.message : String(err);
47699
+ const msg = describeError(err);
47698
47700
  steps.push({ name: "google-submit", status: "skipped", summary: `Google not available: ${msg}` });
47699
47701
  }
47700
47702
  try {
@@ -47719,7 +47721,7 @@ async function wordpressRoutes(app, opts) {
47719
47721
  }
47720
47722
  }
47721
47723
  } catch (err) {
47722
- const msg = err instanceof Error ? err.message : String(err);
47724
+ const msg = describeError(err);
47723
47725
  steps.push({ name: "bing-submit", status: "skipped", summary: `Bing not available: ${msg}` });
47724
47726
  }
47725
47727
  }
@@ -54152,7 +54154,7 @@ async function runBackfillTask(options) {
54152
54154
  try {
54153
54155
  allEvents = await pullForBackfill();
54154
54156
  } catch (e) {
54155
- markFailed(`${pullErrorPrefix}: ${e instanceof Error ? e.message : String(e)}`);
54157
+ markFailed(`${pullErrorPrefix}: ${describeError(e)}`);
54156
54158
  return;
54157
54159
  }
54158
54160
  if (allEvents.length === 0) {
@@ -54415,7 +54417,7 @@ async function runBackfillTask(options) {
54415
54417
  });
54416
54418
  if (commitOutcome === "source-inactive") return;
54417
54419
  } catch (e) {
54418
- markFailed(`Backfill rollup write failed: ${e instanceof Error ? e.message : String(e)}`);
54420
+ markFailed(`Backfill rollup write failed: ${describeError(e)}`);
54419
54421
  }
54420
54422
  }
54421
54423
  async function trafficRoutes(app, opts) {
@@ -54624,7 +54626,7 @@ async function trafficRoutes(app, opts) {
54624
54626
  `WordPress traffic probe failed (HTTP ${e.status}): ${e.message}${e.body ? ` \u2014 ${e.body}` : ""}`
54625
54627
  );
54626
54628
  }
54627
- const msg = e instanceof Error ? e.message : String(e);
54629
+ const msg = describeError(e);
54628
54630
  throw providerError(`WordPress traffic probe failed: ${msg}`);
54629
54631
  }
54630
54632
  });
@@ -54715,7 +54717,7 @@ async function trafficRoutes(app, opts) {
54715
54717
  `Vercel traffic probe failed (HTTP ${e.status}): ${e.message}${e.body ? ` \u2014 ${e.body}` : ""}`
54716
54718
  );
54717
54719
  }
54718
- const msg = e instanceof Error ? e.message : String(e);
54720
+ const msg = describeError(e);
54719
54721
  throw providerError(`Vercel traffic probe failed: ${msg}`);
54720
54722
  }
54721
54723
  const now = (/* @__PURE__ */ new Date()).toISOString();
@@ -55582,7 +55584,7 @@ async function trafficRoutes(app, opts) {
55582
55584
  try {
55583
55585
  accessToken = await resolveAccessToken2(credential);
55584
55586
  } catch (e) {
55585
- const msg = e instanceof Error ? e.message : String(e);
55587
+ const msg = describeError(e);
55586
55588
  markFailed(msg, "PROVIDER_AUTH");
55587
55589
  throw providerError(`Failed to resolve Cloud Run access token: ${msg}`);
55588
55590
  }
@@ -55601,7 +55603,7 @@ async function trafficRoutes(app, opts) {
55601
55603
  });
55602
55604
  allEvents = page.events;
55603
55605
  } catch (e) {
55604
- const msg = e instanceof Error ? e.message : String(e);
55606
+ const msg = describeError(e);
55605
55607
  markFailed(msg, "PROVIDER_PULL");
55606
55608
  throw providerError(`Cloud Run pull failed: ${msg}`);
55607
55609
  }
@@ -55625,7 +55627,7 @@ async function trafficRoutes(app, opts) {
55625
55627
  try {
55626
55628
  pinnedDispatcher = await assertWordpressTargetAllowed(credential.baseUrl);
55627
55629
  } catch (e) {
55628
- const msg = e instanceof Error ? e.message : String(e);
55630
+ const msg = describeError(e);
55629
55631
  markFailed(msg, "PROVIDER_PULL");
55630
55632
  throw e;
55631
55633
  }
@@ -55651,7 +55653,7 @@ async function trafficRoutes(app, opts) {
55651
55653
  allEvents = collected;
55652
55654
  nextCursor = cursor;
55653
55655
  } catch (e) {
55654
- const msg = e instanceof Error ? e.message : String(e);
55656
+ const msg = describeError(e);
55655
55657
  markFailed(msg, "PROVIDER_PULL");
55656
55658
  throw providerError(`WordPress pull failed: ${msg}`);
55657
55659
  } finally {
@@ -55753,7 +55755,7 @@ async function trafficRoutes(app, opts) {
55753
55755
  }
55754
55756
  allEvents = drained.events;
55755
55757
  } catch (e) {
55756
- const msg = e instanceof Error ? e.message : String(e);
55758
+ const msg = describeError(e);
55757
55759
  markFailed(msg, "PROVIDER_PULL");
55758
55760
  throw providerError(`Vercel pull failed: ${msg}`);
55759
55761
  }
@@ -56995,7 +56997,7 @@ var BING_AUTH_CHECKS = [
56995
56997
  remediation: null
56996
56998
  };
56997
56999
  } catch (err) {
56998
- const message = err instanceof Error ? err.message : String(err);
57000
+ const message = describeError(err);
56999
57001
  return {
57000
57002
  status: CheckStatuses.fail,
57001
57003
  code: "bing.auth.verification-failed",
@@ -57077,7 +57079,7 @@ var BING_AUTH_CHECKS = [
57077
57079
  remediation: null
57078
57080
  };
57079
57081
  } catch (err) {
57080
- const message = err instanceof Error ? err.message : String(err);
57082
+ const message = describeError(err);
57081
57083
  return {
57082
57084
  status: CheckStatuses.fail,
57083
57085
  code: "bing.auth.site-check-failed",
@@ -57337,7 +57339,7 @@ async function checkServiceAccount(conn) {
57337
57339
  try {
57338
57340
  await verifyConnection(conn.clientEmail, conn.privateKey, conn.propertyId);
57339
57341
  } catch (err) {
57340
- const message = err instanceof Error ? err.message : String(err);
57342
+ const message = describeError(err);
57341
57343
  return {
57342
57344
  status: CheckStatuses.fail,
57343
57345
  code: "ga.auth.verify-failed",
@@ -57386,7 +57388,7 @@ async function checkOAuthConnection(ctx, projectName, conn) {
57386
57388
  const tokens = await refreshAccessToken(auth.clientId, auth.clientSecret, conn.refreshToken);
57387
57389
  accessToken = tokens.access_token;
57388
57390
  } catch (err) {
57389
- const message = err instanceof Error ? err.message : String(err);
57391
+ const message = describeError(err);
57390
57392
  return {
57391
57393
  status: CheckStatuses.fail,
57392
57394
  code: "ga.auth.refresh-failed",
@@ -57398,7 +57400,7 @@ async function checkOAuthConnection(ctx, projectName, conn) {
57398
57400
  try {
57399
57401
  await verifyConnectionWithToken(accessToken, conn.propertyId);
57400
57402
  } catch (err) {
57401
- const message = err instanceof Error ? err.message : String(err);
57403
+ const message = describeError(err);
57402
57404
  return {
57403
57405
  status: CheckStatuses.fail,
57404
57406
  code: "ga.auth.verify-failed",
@@ -57517,7 +57519,7 @@ async function resolveGbpToken(ctx) {
57517
57519
  const tokens = await refreshAccessToken(auth.clientId, auth.clientSecret, conn.refreshToken);
57518
57520
  return { ok: true, token: { accessToken: tokens.access_token, conn } };
57519
57521
  } catch (err) {
57520
- const message = err instanceof Error ? err.message : String(err);
57522
+ const message = describeError(err);
57521
57523
  return {
57522
57524
  ok: false,
57523
57525
  output: {
@@ -57649,7 +57651,7 @@ var accountAccessCheck = {
57649
57651
  details: { reason: err.reason ?? void 0, status: err.status }
57650
57652
  };
57651
57653
  }
57652
- const message = err instanceof Error ? err.message : String(err);
57654
+ const message = describeError(err);
57653
57655
  return {
57654
57656
  status: CheckStatuses.fail,
57655
57657
  code: "gbp.account.list-failed",
@@ -57881,7 +57883,7 @@ async function resolveAccessToken(ctx) {
57881
57883
  const tokens = await refreshAccessToken(auth.clientId, auth.clientSecret, conn.refreshToken);
57882
57884
  return { ok: true, token: { accessToken: tokens.access_token } };
57883
57885
  } catch (err) {
57884
- const message = err instanceof Error ? err.message : String(err);
57886
+ const message = describeError(err);
57885
57887
  return {
57886
57888
  ok: false,
57887
57889
  output: {
@@ -57973,7 +57975,7 @@ var propertyAccessCheck = {
57973
57975
  details: { error: err.message }
57974
57976
  };
57975
57977
  }
57976
- const message = err instanceof Error ? err.message : String(err);
57978
+ const message = describeError(err);
57977
57979
  return {
57978
57980
  status: CheckStatuses.fail,
57979
57981
  code: "google.auth.list-sites-failed",
@@ -58560,7 +58562,7 @@ async function runValidator(source, validator, fallbackId, fallbackLabel) {
58560
58562
  }
58561
58563
  return { source, output: result };
58562
58564
  } catch (e) {
58563
- const msg = e instanceof Error ? e.message : String(e);
58565
+ const msg = describeError(e);
58564
58566
  return {
58565
58567
  source,
58566
58568
  output: {
@@ -59015,7 +59017,7 @@ var WORDPRESS_PUBLISH_CHECKS = [
59015
59017
  details: { error: err.message }
59016
59018
  };
59017
59019
  }
59018
- const message = err instanceof Error ? err.message : String(err);
59020
+ const message = describeError(err);
59019
59021
  return {
59020
59022
  status: CheckStatuses.fail,
59021
59023
  code: "wordpress.publish.verification-failed",
@@ -59075,7 +59077,7 @@ async function runChecks(ctx, checks, options = {}) {
59075
59077
  try {
59076
59078
  output = await definition.run(ctx);
59077
59079
  } catch (err) {
59078
- const message = err instanceof Error ? err.message : String(err);
59080
+ const message = describeError(err);
59079
59081
  output = {
59080
59082
  status: CheckStatuses.fail,
59081
59083
  code: `${definition.id}.runtime-error`,
@@ -62099,7 +62101,7 @@ function buildTrafficSourceValidators(opts) {
62099
62101
  summary: `Cloud Run access token resolves for "${source.displayName}" (project ${record.gcpProjectId}).`
62100
62102
  };
62101
62103
  } catch (e) {
62102
- const msg = e instanceof Error ? e.message : String(e);
62104
+ const msg = describeError(e);
62103
62105
  return {
62104
62106
  status: CheckStatuses.fail,
62105
62107
  code: "traffic.credentials.resolve-failed",
@@ -62145,7 +62147,7 @@ function buildTrafficSourceValidators(opts) {
62145
62147
  };
62146
62148
  } catch (e) {
62147
62149
  const httpStatus = e instanceof WordpressTrafficApiError ? e.status : null;
62148
- const msg = e instanceof Error ? e.message : String(e);
62150
+ const msg = describeError(e);
62149
62151
  return {
62150
62152
  status: CheckStatuses.fail,
62151
62153
  code: httpStatus === 401 || httpStatus === 403 ? "traffic.credentials.unauthorized" : "traffic.credentials.resolve-failed",
@@ -62192,7 +62194,7 @@ function buildTrafficSourceValidators(opts) {
62192
62194
  };
62193
62195
  } catch (e) {
62194
62196
  const httpStatus = e instanceof VercelLogsApiError ? e.status : null;
62195
- const msg = e instanceof Error ? e.message : String(e);
62197
+ const msg = describeError(e);
62196
62198
  return {
62197
62199
  status: CheckStatuses.fail,
62198
62200
  code: httpStatus === 401 || httpStatus === 403 ? "traffic.credentials.unauthorized" : "traffic.credentials.resolve-failed",
@@ -17,6 +17,7 @@ import {
17
17
  adsUnresolvedOperationListQuerySchema,
18
18
  backlinkSourceSchema,
19
19
  competitorBatchRequestSchema,
20
+ describeError,
20
21
  discoveryBucketSchema,
21
22
  discoveryCompetitorTypeSchema,
22
23
  discoveryPromoteRequestSchema,
@@ -81,7 +82,7 @@ import {
81
82
  trafficConnectWordpressRequestSchema,
82
83
  trafficEventKindSchema,
83
84
  trafficSeriesGranularitySchema
84
- } from "./chunk-BU6C2DKF.js";
85
+ } from "./chunk-GU7T2JUB.js";
85
86
 
86
87
  // src/config.ts
87
88
  import fs from "fs";
@@ -5271,7 +5272,7 @@ var ApiClient = class {
5271
5272
  result = await call();
5272
5273
  } catch (err) {
5273
5274
  if (err instanceof CliError) throw err;
5274
- const msg = err instanceof Error ? err.message : String(err);
5275
+ const msg = describeError(err);
5275
5276
  if (traceEnabled) {
5276
5277
  process.stderr.write(`[trace] (sdk-call) \u2192 ERROR (${Date.now() - traceStart}ms): ${msg}
5277
5278
  `);
@@ -5388,7 +5389,7 @@ var ApiClient = class {
5388
5389
  res = await fetch(url, { method: "POST", headers, body: JSON.stringify(body ?? {}), signal });
5389
5390
  } catch (err) {
5390
5391
  if (err instanceof CliError) throw err;
5391
- const msg = err instanceof Error ? err.message : String(err);
5392
+ const msg = describeError(err);
5392
5393
  if (msg.includes("fetch failed") || msg.includes("ECONNREFUSED") || msg.includes("connect ECONNREFUSED")) {
5393
5394
  throw new CliError({
5394
5395
  code: "CONNECTION_ERROR",
@@ -5496,7 +5497,7 @@ var ApiClient = class {
5496
5497
  headers: { Authorization: `Bearer ${this.apiKey}` }
5497
5498
  });
5498
5499
  } catch (err) {
5499
- const message = err instanceof Error ? err.message : String(err);
5500
+ const message = describeError(err);
5500
5501
  if (message.includes("fetch failed") || message.includes("ECONNREFUSED") || message.includes("connect ECONNREFUSED")) {
5501
5502
  throw new CliError({
5502
5503
  code: "CONNECTION_ERROR",
@@ -8260,7 +8261,7 @@ async function submitGscSitemapsFromMcp(client2, input) {
8260
8261
  remaining,
8261
8262
  unconfirmedBatch: { index: Math.floor(offset / 50) + 1, sitemapUrls: batchSitemapUrls },
8262
8263
  partialResult: aggregate,
8263
- cause: cause instanceof CliError ? { code: cause.code, message: cause.message, details: cause.details } : { message: cause instanceof Error ? cause.message : String(cause) }
8264
+ cause: cause instanceof CliError ? { code: cause.code, message: cause.message, details: cause.details } : { message: describeError(cause) }
8264
8265
  }
8265
8266
  });
8266
8267
  }