@canonry/canonry 4.165.2 → 4.167.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 (26) hide show
  1. package/assets/assets/{AuditHistoryPanel-DYBAiNCu.js → AuditHistoryPanel-Dvz6QFtW.js} +1 -1
  2. package/assets/assets/{BacklinksPage-p19FCIyh.js → BacklinksPage-BHOtOIr5.js} +1 -1
  3. package/assets/assets/{HistoryPage-CRSuA-J0.js → HistoryPage-Bc5Nx6dX.js} +1 -1
  4. package/assets/assets/{MeasurementPropertyPage-Bgr9VeUk.js → MeasurementPropertyPage-D4FIFiWv.js} +1 -1
  5. package/assets/assets/ProjectPage-CT5ZD7_A.js +9 -0
  6. package/assets/assets/{RunRow-_RMMaLPt.js → RunRow-CB2oG45_.js} +1 -1
  7. package/assets/assets/{RunsPage-CaDPSEfE.js → RunsPage-OLbocIOY.js} +1 -1
  8. package/assets/assets/SettingsPage-DVdPBrap.js +1 -0
  9. package/assets/assets/{SiteHealthSection-Byp_Fu5K.js → SiteHealthSection-B1bjMCqY.js} +3 -3
  10. package/assets/assets/{TrafficPage-BXkXNKYB.js → TrafficPage-BUWXjHhw.js} +1 -1
  11. package/assets/assets/{TrafficSourceDetailPage-CReS8q0H.js → TrafficSourceDetailPage-DwoFzTu7.js} +1 -1
  12. package/assets/assets/{extract-error-message-CHW-A3AQ.js → extract-error-message-CNH2-nPH.js} +1 -1
  13. package/assets/assets/{index-CcS2bDjR.js → index-DdXb59Rg.js} +20 -20
  14. package/assets/assets/{react-sigma_core.esm.min-Cm0RA3Iv.js → react-sigma_core.esm.min-DLRh4X_G.js} +1 -1
  15. package/assets/index.html +1 -1
  16. package/dist/{chunk-BJLIMWL2.js → chunk-7M3QVRJD.js} +134 -57
  17. package/dist/{chunk-J56XZGG6.js → chunk-P5LR3NDQ.js} +6 -5
  18. package/dist/{chunk-UVDX2Y4N.js → chunk-SXENNCJF.js} +104 -96
  19. package/dist/{chunk-P2CQ57UV.js → chunk-TP4KXU3E.js} +20 -2
  20. package/dist/cli.js +36 -29
  21. package/dist/index.js +4 -4
  22. package/dist/{intelligence-service-QGBYYNWV.js → intelligence-service-ULDOVV5Y.js} +2 -2
  23. package/dist/mcp.js +2 -2
  24. package/package.json +11 -11
  25. package/assets/assets/ProjectPage-D6-9qYKU.js +0 -9
  26. package/assets/assets/SettingsPage-Dcp71zcu.js +0 -1
@@ -10,7 +10,7 @@ import {
10
10
  loadConfig,
11
11
  loadConfigRaw,
12
12
  saveConfigPatch
13
- } from "./chunk-J56XZGG6.js";
13
+ } from "./chunk-P5LR3NDQ.js";
14
14
  import {
15
15
  CC_CACHE_DIR,
16
16
  DUCKDB_SPEC,
@@ -139,7 +139,7 @@ import {
139
139
  siteCrawlSnapshots,
140
140
  toAlertView,
141
141
  usageCounters
142
- } from "./chunk-BJLIMWL2.js";
142
+ } from "./chunk-7M3QVRJD.js";
143
143
  import {
144
144
  AGENT_MEMORY_VALUE_MAX_BYTES,
145
145
  AGENT_PROVIDER_IDS,
@@ -204,6 +204,7 @@ import {
204
204
  deriveCitedUrlCandidates,
205
205
  deriveIndexCoverage,
206
206
  deriveSiteHealthState,
207
+ describeError,
207
208
  determineAnswerMentioned,
208
209
  dollarsToMicros,
209
210
  effectiveBrandNames,
@@ -253,7 +254,7 @@ import {
253
254
  validationError,
254
255
  winnabilityClassLabel,
255
256
  withRetry
256
- } from "./chunk-P2CQ57UV.js";
257
+ } from "./chunk-TP4KXU3E.js";
257
258
 
258
259
  // src/telemetry.ts
259
260
  import crypto from "crypto";
@@ -608,7 +609,7 @@ async function withRetry2(fn, options = {}) {
608
609
  onRetry: ({ attempt, err, delayMs }) => {
609
610
  console.warn(
610
611
  `[provider] Attempt ${attempt + 1} failed, retrying in ${delayMs}ms...`,
611
- err instanceof Error ? err.message : String(err)
612
+ describeError(err)
612
613
  );
613
614
  }
614
615
  });
@@ -683,7 +684,7 @@ async function healthcheck(config) {
683
684
  return {
684
685
  ok: false,
685
686
  provider: "gemini",
686
- message: err instanceof Error ? err.message : String(err),
687
+ message: describeError(err),
687
688
  model: config.model ?? DEFAULT_MODEL
688
689
  };
689
690
  }
@@ -713,7 +714,7 @@ async function executeTrackedQuery(input) {
713
714
  searchQueries: parsed.searchQueries
714
715
  };
715
716
  } catch (err) {
716
- const msg = err instanceof Error ? err.message : String(err);
717
+ const msg = describeError(err);
717
718
  throw new Error(`[provider-gemini] ${msg}`);
718
719
  }
719
720
  }
@@ -1056,7 +1057,7 @@ async function withRetry3(fn, options = {}) {
1056
1057
  onRetry: ({ attempt, err, delayMs }) => {
1057
1058
  console.warn(
1058
1059
  `[provider] Attempt ${attempt + 1} failed, retrying in ${delayMs}ms...`,
1059
- err instanceof Error ? err.message : String(err)
1060
+ describeError(err)
1060
1061
  );
1061
1062
  }
1062
1063
  });
@@ -1103,7 +1104,7 @@ async function healthcheck2(config) {
1103
1104
  return {
1104
1105
  ok: false,
1105
1106
  provider: "openai",
1106
- message: err instanceof Error ? err.message : String(err),
1107
+ message: describeError(err),
1107
1108
  model: config.model ?? DEFAULT_MODEL2
1108
1109
  };
1109
1110
  }
@@ -1141,7 +1142,7 @@ async function executeTrackedQuery2(input) {
1141
1142
  searchQueries: parsed.searchQueries
1142
1143
  };
1143
1144
  } catch (err) {
1144
- const msg = err instanceof Error ? err.message : String(err);
1145
+ const msg = describeError(err);
1145
1146
  throw new Error(`[provider-openai] ${msg}`);
1146
1147
  }
1147
1148
  }
@@ -1408,7 +1409,7 @@ async function withRetry4(fn, options = {}) {
1408
1409
  onRetry: ({ attempt, err, delayMs }) => {
1409
1410
  console.warn(
1410
1411
  `[provider] Attempt ${attempt + 1} failed, retrying in ${delayMs}ms...`,
1411
- err instanceof Error ? err.message : String(err)
1412
+ describeError(err)
1412
1413
  );
1413
1414
  }
1414
1415
  });
@@ -1464,7 +1465,7 @@ async function healthcheck3(config) {
1464
1465
  return {
1465
1466
  ok: false,
1466
1467
  provider: "claude",
1467
- message: err instanceof Error ? err.message : String(err),
1468
+ message: describeError(err),
1468
1469
  model: resolveModel2(config)
1469
1470
  };
1470
1471
  }
@@ -1514,7 +1515,7 @@ async function executeTrackedQuery3(input) {
1514
1515
  retrievalContract: CLAUDE_RETRIEVAL_CONTRACT
1515
1516
  };
1516
1517
  } catch (err) {
1517
- const msg = err instanceof Error ? err.message : String(err);
1518
+ const msg = describeError(err);
1518
1519
  throw new Error(`[provider-claude] ${msg}`);
1519
1520
  }
1520
1521
  }
@@ -1798,7 +1799,7 @@ async function withRetry5(fn, options = {}) {
1798
1799
  onRetry: ({ attempt, err, delayMs }) => {
1799
1800
  console.warn(
1800
1801
  `[provider] Attempt ${attempt + 1} failed, retrying in ${delayMs}ms...`,
1801
- err instanceof Error ? err.message : String(err)
1802
+ describeError(err)
1802
1803
  );
1803
1804
  }
1804
1805
  });
@@ -1844,7 +1845,7 @@ async function healthcheck4(config) {
1844
1845
  return {
1845
1846
  ok: false,
1846
1847
  provider: "local",
1847
- message: err instanceof Error ? err.message : String(err),
1848
+ message: describeError(err),
1848
1849
  model: config.model ?? DEFAULT_MODEL4
1849
1850
  };
1850
1851
  }
@@ -1881,7 +1882,7 @@ async function executeTrackedQuery4(input) {
1881
1882
  searchQueries: []
1882
1883
  };
1883
1884
  } catch (err) {
1884
- const msg = err instanceof Error ? err.message : String(err);
1885
+ const msg = describeError(err);
1885
1886
  throw new Error(`[provider-local] ${msg}`);
1886
1887
  }
1887
1888
  }
@@ -2110,7 +2111,7 @@ var CDPConnectionManager = class {
2110
2111
  } catch (err) {
2111
2112
  throw new CDPProviderError(
2112
2113
  "CDP_CONNECTION_REFUSED",
2113
- `Failed to connect to Chrome at ${this.host}:${this.port}: ${err instanceof Error ? err.message : String(err)}`
2114
+ `Failed to connect to Chrome at ${this.host}:${this.port}: ${describeError(err)}`
2114
2115
  );
2115
2116
  }
2116
2117
  }
@@ -2128,7 +2129,7 @@ var CDPConnectionManager = class {
2128
2129
  } catch (err) {
2129
2130
  throw new CDPProviderError(
2130
2131
  "CDP_TARGET_SELECTOR_FAILED",
2131
- `Failed to navigate to ${target.newConversationUrl}: ${err instanceof Error ? err.message : String(err)}`
2132
+ `Failed to navigate to ${target.newConversationUrl}: ${describeError(err)}`
2132
2133
  );
2133
2134
  }
2134
2135
  const entry = this.tabs.get(target.name);
@@ -2542,7 +2543,7 @@ var cdpChatgptAdapter = {
2542
2543
  return {
2543
2544
  ok: false,
2544
2545
  provider: "cdp:chatgpt",
2545
- message: err instanceof Error ? err.message : String(err)
2546
+ message: describeError(err)
2546
2547
  };
2547
2548
  }
2548
2549
  },
@@ -2586,7 +2587,7 @@ var cdpChatgptAdapter = {
2586
2587
  screenshotPath: capturedScreenshotPath
2587
2588
  };
2588
2589
  } catch (err) {
2589
- const msg = err instanceof Error ? err.message : String(err);
2590
+ const msg = describeError(err);
2590
2591
  throw new Error(`[provider-cdp] ${msg}`);
2591
2592
  }
2592
2593
  },
@@ -2614,7 +2615,7 @@ async function withRetry6(fn, options = {}) {
2614
2615
  onRetry: ({ attempt, err, delayMs }) => {
2615
2616
  console.warn(
2616
2617
  `[provider] Attempt ${attempt + 1} failed, retrying in ${delayMs}ms...`,
2617
- err instanceof Error ? err.message : String(err)
2618
+ describeError(err)
2618
2619
  );
2619
2620
  }
2620
2621
  });
@@ -2656,7 +2657,7 @@ async function healthcheck5(config) {
2656
2657
  return {
2657
2658
  ok: false,
2658
2659
  provider: "perplexity",
2659
- message: err instanceof Error ? err.message : String(err),
2660
+ message: describeError(err),
2660
2661
  model: config.model ?? DEFAULT_MODEL5
2661
2662
  };
2662
2663
  }
@@ -2683,7 +2684,7 @@ async function executeTrackedQuery5(input) {
2683
2684
  searchQueries: parsed.searchQueries
2684
2685
  };
2685
2686
  } catch (err) {
2686
- const msg = err instanceof Error ? err.message : String(err);
2687
+ const msg = describeError(err);
2687
2688
  throw new Error(`[provider-perplexity] ${msg}`);
2688
2689
  }
2689
2690
  }
@@ -3831,7 +3832,7 @@ var JobRunner = class {
3831
3832
  runId,
3832
3833
  provider: providerName,
3833
3834
  query: q.query,
3834
- error: err instanceof Error ? err.message : String(err)
3835
+ error: describeError(err)
3835
3836
  });
3836
3837
  }
3837
3838
  this.throwIfRunCancelled(runId);
@@ -3936,7 +3937,7 @@ var JobRunner = class {
3936
3937
  if (err instanceof RunCancelledError) {
3937
3938
  throw err;
3938
3939
  }
3939
- const msg = err instanceof Error ? err.message : String(err);
3940
+ const msg = describeError(err);
3940
3941
  const stack = err instanceof Error ? err.stack : void 0;
3941
3942
  log.error("query.failed", { runId, provider: providerName, query: q.query, error: msg, stack });
3942
3943
  if (!providerErrors.has(providerName)) {
@@ -3989,7 +3990,7 @@ var JobRunner = class {
3989
3990
  runId,
3990
3991
  provider: providerName,
3991
3992
  query: unit.queryText,
3992
- error: err instanceof Error ? err.message : String(err)
3993
+ error: describeError(err)
3993
3994
  });
3994
3995
  }
3995
3996
  this.throwIfRunCancelled(runId);
@@ -4076,7 +4077,7 @@ var JobRunner = class {
4076
4077
  if (err instanceof RunCancelledError) {
4077
4078
  throw err;
4078
4079
  }
4079
- const msg = err instanceof Error ? err.message : String(err);
4080
+ const msg = describeError(err);
4080
4081
  const stack = err instanceof Error ? err.stack : void 0;
4081
4082
  log.error("query.failed", { runId, provider: providerName, query: unit.queryText, executionId: unit.executionId, error: msg, stack });
4082
4083
  if (!providerErrors.has(providerName)) {
@@ -4176,7 +4177,7 @@ var JobRunner = class {
4176
4177
  this.incrementUsage(projectId, "runs", 1);
4177
4178
  if (this.onRunCompleted) {
4178
4179
  this.onRunCompleted(runId, projectId).catch((err) => {
4179
- log.error("notification.callback-failed", { runId, error: err instanceof Error ? err.message : String(err) });
4180
+ log.error("notification.callback-failed", { runId, error: describeError(err) });
4180
4181
  });
4181
4182
  }
4182
4183
  } catch (err) {
@@ -4193,7 +4194,7 @@ var JobRunner = class {
4193
4194
  this.handleCancelledRun(runId, projectId, startTime, executionContext);
4194
4195
  return;
4195
4196
  }
4196
- const errorMessage = err instanceof Error ? err.message : String(err);
4197
+ const errorMessage = describeError(err);
4197
4198
  this.db.update(runs).set({
4198
4199
  status: "failed",
4199
4200
  finishedAt: (/* @__PURE__ */ new Date()).toISOString(),
@@ -4234,7 +4235,7 @@ var JobRunner = class {
4234
4235
  }
4235
4236
  if (this.onRunCompleted) {
4236
4237
  this.onRunCompleted(runId, projectId).catch((notifErr) => {
4237
- log.error("notification.callback-failed", { runId, error: notifErr instanceof Error ? notifErr.message : String(notifErr) });
4238
+ log.error("notification.callback-failed", { runId, error: describeError(notifErr) });
4238
4239
  });
4239
4240
  }
4240
4241
  }
@@ -4314,7 +4315,7 @@ var JobRunner = class {
4314
4315
  );
4315
4316
  if (this.onRunCompleted) {
4316
4317
  this.onRunCompleted(runId, projectId).catch((err) => {
4317
- log.error("notification.callback-failed", { runId, error: err instanceof Error ? err.message : String(err) });
4318
+ log.error("notification.callback-failed", { runId, error: describeError(err) });
4318
4319
  });
4319
4320
  }
4320
4321
  }
@@ -4588,7 +4589,7 @@ async function executeGscSync(db, runId, projectId, opts) {
4588
4589
  db.update(runs).set({ status: "completed", finishedAt: (/* @__PURE__ */ new Date()).toISOString() }).where(eq4(runs.id, runId)).run();
4589
4590
  log2.info("sync.completed", { runId, projectId, searchDataRows: rows.length, indexed: coverage.indexed, notIndexed: coverage.notIndexed, unknown: coverage.unknown, verifiedByInspection: coverage.verifiedByInspection });
4590
4591
  } catch (err) {
4591
- const errorMsg = err instanceof Error ? err.message : String(err);
4592
+ const errorMsg = describeError(err);
4592
4593
  db.update(runs).set({ status: "failed", error: errorMsg, finishedAt: (/* @__PURE__ */ new Date()).toISOString() }).where(eq4(runs.id, runId)).run();
4593
4594
  log2.error("sync.failed", { runId, projectId, error: errorMsg });
4594
4595
  throw err;
@@ -4712,7 +4713,7 @@ async function executeGbpSync(db, runId, projectId, opts) {
4712
4713
  placeToTouch = latestPlace.id;
4713
4714
  }
4714
4715
  } catch (placesErr) {
4715
- log3.warn("places.failed", { runId, location: loc.locationName, error: placesErr instanceof Error ? placesErr.message : String(placesErr) });
4716
+ log3.warn("places.failed", { runId, location: loc.locationName, error: describeError(placesErr) });
4716
4717
  }
4717
4718
  }
4718
4719
  }
@@ -4833,8 +4834,8 @@ async function executeGbpSync(db, runId, projectId, opts) {
4833
4834
  });
4834
4835
  okCount++;
4835
4836
  } catch (err) {
4836
- errors.set(loc.locationName, err instanceof Error ? err.message : String(err));
4837
- log3.error("location.failed", { runId, location: loc.locationName, error: err instanceof Error ? err.message : String(err) });
4837
+ errors.set(loc.locationName, describeError(err));
4838
+ log3.error("location.failed", { runId, location: loc.locationName, error: describeError(err) });
4838
4839
  }
4839
4840
  }));
4840
4841
  }
@@ -4856,7 +4857,7 @@ async function executeGbpSync(db, runId, projectId, opts) {
4856
4857
  }
4857
4858
  log3.info("sync.done", { runId, projectId, ok: okCount, failed: errors.size });
4858
4859
  } catch (err) {
4859
- const errorMsg = err instanceof Error ? err.message : String(err);
4860
+ const errorMsg = describeError(err);
4860
4861
  db.update(runs).set({ status: "failed", error: serializeRunError({ message: errorMsg }), finishedAt: (/* @__PURE__ */ new Date()).toISOString() }).where(eq5(runs.id, runId)).run();
4861
4862
  log3.error("sync.failed", { runId, projectId, error: errorMsg });
4862
4863
  throw err;
@@ -5567,8 +5568,8 @@ async function executeAdsSync(db, runId, projectId, opts) {
5567
5568
  insightUpserts.push(...toDailyUpserts("ad_group", group.id, insights2));
5568
5569
  }
5569
5570
  } catch (err) {
5570
- errors.set(campaign.name, err instanceof Error ? err.message : String(err));
5571
- log4.error("campaign.failed", { runId, campaignId: campaign.id, error: err instanceof Error ? err.message : String(err) });
5571
+ errors.set(campaign.name, describeError(err));
5572
+ log4.error("campaign.failed", { runId, campaignId: campaign.id, error: describeError(err) });
5572
5573
  }
5573
5574
  }
5574
5575
  const conversionTrackingConfigured = campaigns.some(
@@ -5690,7 +5691,7 @@ async function executeAdsSync(db, runId, projectId, opts) {
5690
5691
  }
5691
5692
  log4.info("sync.done", { runId, projectId, campaigns: syncedCampaigns.length, insightRows: insightUpserts.length, failed: errors.size });
5692
5693
  } catch (err) {
5693
- const errorMsg = err instanceof Error ? err.message : String(err);
5694
+ const errorMsg = describeError(err);
5694
5695
  db.update(runs).set({ status: "failed", error: serializeRunError({ message: errorMsg }), finishedAt: (/* @__PURE__ */ new Date()).toISOString() }).where(eq6(runs.id, runId)).run();
5695
5696
  log4.error("sync.failed", { runId, projectId, error: errorMsg });
5696
5697
  throw err;
@@ -5746,7 +5747,7 @@ async function parseSitemapRecursive(url, urls, visited, depth, isChild) {
5746
5747
  if (!isChild) throw err;
5747
5748
  log5.warn("child-sitemap.fetch-failed", {
5748
5749
  url,
5749
- error: err instanceof Error ? err.message : String(err)
5750
+ error: describeError(err)
5750
5751
  });
5751
5752
  return;
5752
5753
  }
@@ -5764,7 +5765,7 @@ async function parseSitemapRecursive(url, urls, visited, depth, isChild) {
5764
5765
  if (!isChild) throw err;
5765
5766
  log5.warn("child-sitemap.parse-failed", {
5766
5767
  url,
5767
- error: err instanceof Error ? err.message : String(err)
5768
+ error: describeError(err)
5768
5769
  });
5769
5770
  return;
5770
5771
  }
@@ -5877,7 +5878,7 @@ async function inspectUrlsPaced(urls, cb, deps) {
5877
5878
  url,
5878
5879
  attempt: attempt2,
5879
5880
  delayMs: Math.round(delayMs),
5880
- error: err instanceof Error ? err.message : String(err)
5881
+ error: describeError(err)
5881
5882
  })
5882
5883
  });
5883
5884
  cb.onResult(url, result, index);
@@ -5992,7 +5993,7 @@ async function executeInspectSitemap(db, runId, projectId, opts) {
5992
5993
  log6.info("inspect.url-done", { runId, projectId, url: pageUrl, progress: `${index + 1}/${urls.length}` });
5993
5994
  },
5994
5995
  onError: (pageUrl, err) => {
5995
- log6.error("inspect.url-failed", { runId, projectId, url: pageUrl, error: err instanceof Error ? err.message : String(err) });
5996
+ log6.error("inspect.url-failed", { runId, projectId, url: pageUrl, error: describeError(err) });
5996
5997
  }
5997
5998
  },
5998
5999
  {
@@ -6009,7 +6010,7 @@ async function executeInspectSitemap(db, runId, projectId, opts) {
6009
6010
  }
6010
6011
  );
6011
6012
  if (aborted) {
6012
- const detail = abortError instanceof Error ? abortError.message : String(abortError);
6013
+ const detail = describeError(abortError);
6013
6014
  throw new Error(
6014
6015
  `URL inspection aborted after ${INSPECT_FAILFAST_THRESHOLD} consecutive rate/access failures (likely GSC URL Inspection quota exhaustion or property access loss). Last error: ${detail}`
6015
6016
  );
@@ -6022,7 +6023,7 @@ async function executeInspectSitemap(db, runId, projectId, opts) {
6022
6023
  db.update(runs).set({ status, finishedAt: (/* @__PURE__ */ new Date()).toISOString() }).where(eq7(runs.id, runId)).run();
6023
6024
  log6.info("inspect.completed", { runId, projectId, inspected, errors, total: urls.length, indexed: snapIndexed, notIndexed: snapNotIndexed });
6024
6025
  } catch (err) {
6025
- const errorMsg = err instanceof Error ? err.message : String(err);
6026
+ const errorMsg = describeError(err);
6026
6027
  db.update(runs).set({ status: "failed", error: errorMsg, finishedAt: (/* @__PURE__ */ new Date()).toISOString() }).where(eq7(runs.id, runId)).run();
6027
6028
  log6.error("inspect.failed", { runId, projectId, error: errorMsg });
6028
6029
  throw err;
@@ -6034,16 +6035,6 @@ import crypto11 from "crypto";
6034
6035
  import { eq as eq8, desc as desc3 } from "drizzle-orm";
6035
6036
  var log7 = createLogger("BingInspectSitemap");
6036
6037
  var BING_INSPECT_SPACING_MS = 2e3;
6037
- function describeError(err) {
6038
- if (err instanceof Error) return err.message;
6039
- if (typeof err === "string") return err;
6040
- if (err == null) return "unknown error";
6041
- try {
6042
- return JSON.stringify(err);
6043
- } catch {
6044
- return "unserializable error";
6045
- }
6046
- }
6047
6038
  function parseBingDate(value) {
6048
6039
  if (!value) return null;
6049
6040
  const match = /\/Date\((-?\d+)(?:[-+]\d+)?\)\//.exec(value);
@@ -6103,7 +6094,7 @@ async function executeBingInspectSitemap(db, runId, projectId, opts) {
6103
6094
  log7.warn("crawl-issues.lookup-failed", {
6104
6095
  runId,
6105
6096
  projectId,
6106
- error: err instanceof Error ? err.message : String(err)
6097
+ error: describeError(err)
6107
6098
  });
6108
6099
  blockedUrls = /* @__PURE__ */ new Set();
6109
6100
  }
@@ -6168,7 +6159,7 @@ async function executeBingInspectSitemap(db, runId, projectId, opts) {
6168
6159
  runId,
6169
6160
  projectId,
6170
6161
  url: pageUrl,
6171
- error: err instanceof Error ? err.message : String(err)
6162
+ error: describeError(err)
6172
6163
  });
6173
6164
  }
6174
6165
  },
@@ -6262,7 +6253,7 @@ async function executeBingInspectSitemap(db, runId, projectId, opts) {
6262
6253
  unknown: snapUnknown
6263
6254
  });
6264
6255
  } catch (err) {
6265
- const errorMsg = err instanceof Error ? err.message : String(err);
6256
+ const errorMsg = describeError(err);
6266
6257
  db.update(runs).set({ status: RunStatuses.failed, error: errorMsg, finishedAt: (/* @__PURE__ */ new Date()).toISOString() }).where(eq8(runs.id, runId)).run();
6267
6258
  log7.error("inspect.failed", { runId, projectId, error: errorMsg });
6268
6259
  throw err;
@@ -6336,7 +6327,7 @@ async function maybeRefreshGscCoverage(db, config, projectId, deps = defaultDeps
6336
6327
  log8.error("refresh.failed", {
6337
6328
  projectId,
6338
6329
  runId,
6339
- error: err instanceof Error ? err.message : String(err)
6330
+ error: describeError(err)
6340
6331
  });
6341
6332
  }
6342
6333
  return runId;
@@ -6488,13 +6479,13 @@ async function executeReleaseSync(db, syncId, opts) {
6488
6479
  syncId,
6489
6480
  release,
6490
6481
  projectId: p.id,
6491
- error: err instanceof Error ? err.message : String(err)
6482
+ error: describeError(err)
6492
6483
  });
6493
6484
  }
6494
6485
  }
6495
6486
  }
6496
6487
  } catch (err) {
6497
- const errorMsg = err instanceof Error ? err.message : String(err);
6488
+ const errorMsg = describeError(err);
6498
6489
  const finishedAt = deps.now().toISOString();
6499
6490
  db.update(ccReleaseSyncs).set({
6500
6491
  status: CcReleaseSyncStatuses.failed,
@@ -6632,7 +6623,7 @@ async function executeBacklinkExtract(db, runId, projectId, opts = {}) {
6632
6623
  db.update(runs).set({ status: RunStatuses.completed, finishedAt }).where(eq11(runs.id, runId)).run();
6633
6624
  log10.info("extract.completed", { runId, projectId, release, rows: rows.length });
6634
6625
  } catch (err) {
6635
- const errorMsg = err instanceof Error ? err.message : String(err);
6626
+ const errorMsg = describeError(err);
6636
6627
  const finishedAt = deps.now().toISOString();
6637
6628
  db.update(runs).set({
6638
6629
  status: RunStatuses.failed,
@@ -6741,7 +6732,7 @@ async function executeDiscoveryRun(opts) {
6741
6732
  competitorCount: result.competitorMap.length
6742
6733
  });
6743
6734
  } catch (err) {
6744
- const errorMsg = err instanceof Error ? err.message : String(err);
6735
+ const errorMsg = describeError(err);
6745
6736
  log11.error("discovery.failed", { runId: opts.runId, sessionId: opts.sessionId, error: errorMsg });
6746
6737
  markSessionFailed(opts.db, opts.sessionId, errorMsg);
6747
6738
  opts.db.update(runs).set({
@@ -8094,15 +8085,29 @@ function observedErrorCount(pages) {
8094
8085
  for (const page of pages) if (page.state === "fetch-error") total++;
8095
8086
  return total;
8096
8087
  }
8088
+ function isUnverifiablePage(page) {
8089
+ return page.state === "fetch-error" && page.statusCode === null;
8090
+ }
8097
8091
  function deadLinkCheckedCount(edges, pages) {
8098
8092
  const attemptedUrls = /* @__PURE__ */ new Set();
8099
8093
  for (const page of pages) {
8100
8094
  if (page.state === "discovered" || page.state === "robots-blocked") continue;
8095
+ if (isUnverifiablePage(page)) continue;
8101
8096
  attemptedUrls.add(page.requestedUrl);
8102
8097
  if (page.finalUrl) attemptedUrls.add(page.finalUrl);
8103
8098
  }
8104
8099
  return new Set([...edges].filter((edge) => edge.type === "anchor" && edge.classification === "internal" && attemptedUrls.has(edge.to)).map((edge) => edge.to)).size;
8105
8100
  }
8101
+ function partitionDeadLinks(deadLinks) {
8102
+ const reported = deadLinks.findings;
8103
+ const engineUnverified = deadLinks.unverified ?? [];
8104
+ const dead = reported.filter((finding) => typeof finding.statusCode === "number" && finding.statusCode >= 400);
8105
+ const unverified = [
8106
+ ...reported.filter((finding) => typeof finding.statusCode !== "number"),
8107
+ ...engineUnverified
8108
+ ];
8109
+ return { dead, unverified };
8110
+ }
8106
8111
  async function executeSiteAudit(db, runId, projectId, opts = {}) {
8107
8112
  const startedAt = (/* @__PURE__ */ new Date()).toISOString();
8108
8113
  const claim = db.update(runs).set({ status: "running", startedAt }).where(and12(eq15(runs.id, runId), eq15(runs.projectId, projectId), eq15(runs.status, "queued"))).run();
@@ -8444,7 +8449,9 @@ async function executeSiteAudit(db, runId, projectId, opts = {}) {
8444
8449
  const errorCount = observedErrorCount(observedPages.values());
8445
8450
  const terminalStatus = crawlSummary.complete ? "completed" : "partial";
8446
8451
  const deadLinksChecked = opts.checkDeadLinks ? deadLinkCheckedCount(observedEdges.values(), observedPages.values()) : 0;
8447
- const deadLinksFound = report.deadLinks.findings.length;
8452
+ const { dead: deadLinkFindings, unverified: unverifiedLinks } = partitionDeadLinks(report.deadLinks);
8453
+ const deadLinksFound = deadLinkFindings.length;
8454
+ const deadLinksUnverified = new Set(unverifiedLinks.map((finding) => finding.to)).size;
8448
8455
  const legacyIssues = factors.map((factor) => toLegacyIssue(factor, crawlSummary.auditRollup.auditedPages)).filter((issue) => issue !== null);
8449
8456
  try {
8450
8457
  persistSiteCrawlGraphLayout(db, { projectId, runId, attemptId }, graphLayout, finishedAt);
@@ -8452,7 +8459,7 @@ async function executeSiteAudit(db, runId, projectId, opts = {}) {
8452
8459
  log12.warn("graph-layout.persist-failed", {
8453
8460
  runId,
8454
8461
  projectId,
8455
- error: error instanceof Error ? error.message : String(error)
8462
+ error: describeError(error)
8456
8463
  });
8457
8464
  try {
8458
8465
  persistSiteCrawlGraphLayout(db, { projectId, runId, attemptId }, {
@@ -8470,7 +8477,7 @@ async function executeSiteAudit(db, runId, projectId, opts = {}) {
8470
8477
  log12.warn("graph-layout.marker-persist-failed", {
8471
8478
  runId,
8472
8479
  projectId,
8473
- error: markerError instanceof Error ? markerError.message : String(markerError)
8480
+ error: describeError(markerError)
8474
8481
  });
8475
8482
  }
8476
8483
  }
@@ -8545,13 +8552,14 @@ async function executeSiteAudit(db, runId, projectId, opts = {}) {
8545
8552
  deadLinkState: report.deadLinks.state,
8546
8553
  deadLinksChecked,
8547
8554
  deadLinksFound,
8555
+ deadLinksUnverified,
8548
8556
  templateDetection: templateLinks.detection,
8549
8557
  linkPlacementRulesetVersion: placementRulesetVersion,
8550
8558
  createdAt: finishedAt,
8551
8559
  updatedAt: finishedAt
8552
8560
  }).run();
8553
8561
  if (opts.checkDeadLinks) {
8554
- for (const finding of report.deadLinks.findings) {
8562
+ for (const finding of deadLinkFindings) {
8555
8563
  tx.insert(siteCrawlFindings).values({
8556
8564
  id: crypto17.randomUUID(),
8557
8565
  projectId,
@@ -8589,7 +8597,7 @@ async function executeSiteAudit(db, runId, projectId, opts = {}) {
8589
8597
  log12.warn("graph-layout.cleanup-failed", {
8590
8598
  runId,
8591
8599
  projectId,
8592
- error: cleanupError instanceof Error ? cleanupError.message : String(cleanupError)
8600
+ error: describeError(cleanupError)
8593
8601
  });
8594
8602
  }
8595
8603
  const current = db.select({ status: runs.status }).from(runs).where(eq15(runs.id, runId)).get();
@@ -8600,7 +8608,7 @@ async function executeSiteAudit(db, runId, projectId, opts = {}) {
8600
8608
  } catch (error) {
8601
8609
  const finishedAt = (/* @__PURE__ */ new Date()).toISOString();
8602
8610
  const cancelled = isCancelled(error, opts.signal);
8603
- const message = error instanceof Error ? error.message : String(error);
8611
+ const message = describeError(error);
8604
8612
  db.transaction((tx) => {
8605
8613
  tx.update(siteCrawlAttempts).set({
8606
8614
  state: cancelled ? "cancelled" : "failed",
@@ -9084,7 +9092,7 @@ function readStoredGroundingSources(rawResponse) {
9084
9092
  return result;
9085
9093
  }
9086
9094
  async function backfillInsightsCommand(project, opts) {
9087
- const { IntelligenceService: IntelligenceService2 } = await import("./intelligence-service-QGBYYNWV.js");
9095
+ const { IntelligenceService: IntelligenceService2 } = await import("./intelligence-service-ULDOVV5Y.js");
9088
9096
  const config = loadConfig();
9089
9097
  const db = createClient(config.database);
9090
9098
  migrate(db);
@@ -10384,7 +10392,7 @@ var Scheduler = class {
10384
10392
  log13.info("run.triggered", { runId, projectName: project.name, providers: providers ?? "all" });
10385
10393
  this.callbacks.onRunCreated(runId, projectId, providers, resolvedLocation);
10386
10394
  } catch (err) {
10387
- log13.error("trigger.error", { scheduleId, projectId, kind, error: err instanceof Error ? err.message : String(err) });
10395
+ log13.error("trigger.error", { scheduleId, projectId, kind, error: describeError(err) });
10388
10396
  }
10389
10397
  }
10390
10398
  };
@@ -10406,7 +10414,7 @@ async function refreshAllIntegrations(client, projectName) {
10406
10414
  log14.info("integration.refreshed", { projectName, integration });
10407
10415
  } else {
10408
10416
  const reason = result.reason;
10409
- const message = reason instanceof Error ? reason.message : String(reason);
10417
+ const message = describeError(reason);
10410
10418
  log14.warn("integration.refresh-failed", { projectName, integration, error: message });
10411
10419
  }
10412
10420
  });
@@ -10727,7 +10735,7 @@ var Notifier = class {
10727
10735
  this.logDelivery(projectId, notificationId, payload.event, "failed", errorDetail);
10728
10736
  }
10729
10737
  } catch (err) {
10730
- const errorDetail = err instanceof Error ? err.message : String(err);
10738
+ const errorDetail = describeError(err);
10731
10739
  if (attempt === maxRetries - 1) {
10732
10740
  this.logDelivery(projectId, notificationId, payload.event, "failed", errorDetail);
10733
10741
  log15.error("webhook.exhausted", { event: payload.event, url: targetLabel, maxRetries, error: errorDetail });
@@ -10786,7 +10794,7 @@ var RunCoordinator = class {
10786
10794
  try {
10787
10795
  await this.notifier.onRunCompleted(runId, projectId);
10788
10796
  } catch (err) {
10789
- log16.error("notifier.failed", { runId, error: err instanceof Error ? err.message : String(err) });
10797
+ log16.error("notifier.failed", { runId, error: describeError(err) });
10790
10798
  }
10791
10799
  return;
10792
10800
  }
@@ -10804,12 +10812,12 @@ var RunCoordinator = class {
10804
10812
  try {
10805
10813
  await this.onInsightsGenerated(runId, projectId, result);
10806
10814
  } catch (err) {
10807
- log16.error("insight-webhook.failed", { runId, error: err instanceof Error ? err.message : String(err) });
10815
+ log16.error("insight-webhook.failed", { runId, error: describeError(err) });
10808
10816
  }
10809
10817
  }
10810
10818
  }
10811
10819
  } catch (err) {
10812
- log16.error("intelligence.failed", { runId, error: err instanceof Error ? err.message : String(err) });
10820
+ log16.error("intelligence.failed", { runId, error: describeError(err) });
10813
10821
  }
10814
10822
  } else if (kind === RunKinds["gbp-sync"]) {
10815
10823
  try {
@@ -10822,17 +10830,17 @@ var RunCoordinator = class {
10822
10830
  try {
10823
10831
  await this.onInsightsGenerated(runId, projectId, analysisResultFromInsights(gbpInsights));
10824
10832
  } catch (err) {
10825
- log16.error("gbp-insight-webhook.failed", { runId, error: err instanceof Error ? err.message : String(err) });
10833
+ log16.error("gbp-insight-webhook.failed", { runId, error: describeError(err) });
10826
10834
  }
10827
10835
  }
10828
10836
  } catch (err) {
10829
- log16.error("gbp-intelligence.failed", { runId, error: err instanceof Error ? err.message : String(err) });
10837
+ log16.error("gbp-intelligence.failed", { runId, error: describeError(err) });
10830
10838
  }
10831
10839
  }
10832
10840
  try {
10833
10841
  await this.notifier.onRunCompleted(runId, projectId);
10834
10842
  } catch (err) {
10835
- log16.error("notifier.failed", { runId, error: err instanceof Error ? err.message : String(err) });
10843
+ log16.error("notifier.failed", { runId, error: describeError(err) });
10836
10844
  }
10837
10845
  if (this.onAeroEvent) {
10838
10846
  try {
@@ -10845,7 +10853,7 @@ var RunCoordinator = class {
10845
10853
  };
10846
10854
  await this.onAeroEvent(ctx);
10847
10855
  } catch (err) {
10848
- log16.error("aero.failed", { runId, error: err instanceof Error ? err.message : String(err) });
10856
+ log16.error("aero.failed", { runId, error: describeError(err) });
10849
10857
  }
10850
10858
  }
10851
10859
  }
@@ -11451,7 +11459,7 @@ async function readSection(fn) {
11451
11459
  } catch (err) {
11452
11460
  return {
11453
11461
  status: "error",
11454
- error: err instanceof Error ? err.message : String(err)
11462
+ error: describeError(err)
11455
11463
  };
11456
11464
  }
11457
11465
  }
@@ -12002,7 +12010,7 @@ async function loadExternalMcpTools(servers, opts = {}) {
12002
12010
  } catch (err) {
12003
12011
  log17.error("external-mcp.connect-failed", {
12004
12012
  label,
12005
- error: err instanceof Error ? err.message : String(err)
12013
+ error: describeError(err)
12006
12014
  });
12007
12015
  continue;
12008
12016
  }
@@ -12012,7 +12020,7 @@ async function loadExternalMcpTools(servers, opts = {}) {
12012
12020
  } catch (err) {
12013
12021
  log17.error("external-mcp.list-failed", {
12014
12022
  label,
12015
- error: err instanceof Error ? err.message : String(err)
12023
+ error: describeError(err)
12016
12024
  });
12017
12025
  continue;
12018
12026
  }
@@ -12298,7 +12306,7 @@ var SessionRegistry = class {
12298
12306
  this.externalToolsPromise = loadExternalMcpTools(this.opts.config.externalMcpServers).catch(
12299
12307
  (err) => {
12300
12308
  log18.error("external-mcp.load-failed", {
12301
- error: err instanceof Error ? err.message : String(err)
12309
+ error: describeError(err)
12302
12310
  });
12303
12311
  return [];
12304
12312
  }
@@ -12550,7 +12558,7 @@ ${lines.join("\n")}
12550
12558
  } catch (err) {
12551
12559
  log18.error("compaction.failed", {
12552
12560
  projectName,
12553
- error: err instanceof Error ? err.message : String(err)
12561
+ error: describeError(err)
12554
12562
  });
12555
12563
  }
12556
12564
  }
@@ -12651,7 +12659,7 @@ ${lines.join("\n")}
12651
12659
  } catch (err) {
12652
12660
  log18.error("drain.failed", {
12653
12661
  projectName,
12654
- error: err instanceof Error ? err.message : String(err)
12662
+ error: describeError(err)
12655
12663
  });
12656
12664
  }
12657
12665
  }
@@ -12861,7 +12869,7 @@ function registerAgentRoutes(app, opts) {
12861
12869
  await agent.waitForIdle();
12862
12870
  opts.sessionRegistry.save(project.name);
12863
12871
  } catch (err) {
12864
- write({ type: "error", message: err instanceof Error ? err.message : String(err) });
12872
+ write({ type: "error", message: describeError(err) });
12865
12873
  } finally {
12866
12874
  unsubscribe();
12867
12875
  write({ type: "stream_close" });
@@ -13323,7 +13331,7 @@ var SnapshotService = class {
13323
13331
  const report = await runAeoAudit(homepageUrl);
13324
13332
  return mapAuditReport(report);
13325
13333
  } catch (err) {
13326
- const message = err instanceof Error ? err.message : String(err);
13334
+ const message = describeError(err);
13327
13335
  log19.warn("audit.failed", { homepageUrl, error: message });
13328
13336
  return {
13329
13337
  url: homepageUrl,
@@ -13356,7 +13364,7 @@ var SnapshotService = class {
13356
13364
  log19.warn("profile.generation-failed", {
13357
13365
  domain: ctx.domain,
13358
13366
  provider: ctx.analysisProvider.adapter.name,
13359
- error: err instanceof Error ? err.message : String(err)
13367
+ error: describeError(err)
13360
13368
  });
13361
13369
  }
13362
13370
  }
@@ -13439,7 +13447,7 @@ var SnapshotService = class {
13439
13447
  groundingSources: [],
13440
13448
  searchQueries: [],
13441
13449
  answerText: "",
13442
- error: err instanceof Error ? err.message : String(err)
13450
+ error: describeError(err)
13443
13451
  };
13444
13452
  }
13445
13453
  });
@@ -13498,7 +13506,7 @@ var SnapshotService = class {
13498
13506
  } catch (err) {
13499
13507
  log19.warn("response.analysis-failed", {
13500
13508
  provider: ctx.analysisProvider.adapter.name,
13501
- error: err instanceof Error ? err.message : String(err)
13509
+ error: describeError(err)
13502
13510
  });
13503
13511
  return buildFallbackBatchAssessment(ctx.companyName, ctx.audit);
13504
13512
  }
@@ -13830,7 +13838,7 @@ async function executeResearchRun(db, registry, runId, projectId) {
13830
13838
  try {
13831
13839
  markResearchQueryFailed(db, runId, row.id, error);
13832
13840
  } catch (persistenceError) {
13833
- workerPersistenceErrors.push(persistenceError instanceof Error ? persistenceError.message : String(persistenceError));
13841
+ workerPersistenceErrors.push(describeError(persistenceError));
13834
13842
  }
13835
13843
  }
13836
13844
  });
@@ -13838,7 +13846,7 @@ async function executeResearchRun(db, registry, runId, projectId) {
13838
13846
  fatalError = `Failed to persist one or more research query results: ${workerPersistenceErrors[0]}`;
13839
13847
  }
13840
13848
  } catch (error) {
13841
- fatalError = error instanceof Error ? error.message : String(error);
13849
+ fatalError = describeError(error);
13842
13850
  } finally {
13843
13851
  if (fatalError) markUnfinishedResearchQueriesFailed(db, runId, fatalError);
13844
13852
  finalizeResearchRun(db, runId, fatalError);
@@ -13851,7 +13859,7 @@ function incrementResearchProgress(db, runId, column) {
13851
13859
  db.update(researchRuns).set({ [column]: sql10`${researchRuns[column]} + 1` }).where(eq23(researchRuns.id, runId)).run();
13852
13860
  }
13853
13861
  function markResearchQueryFailed(db, runId, queryId, error) {
13854
- const message = error instanceof Error ? error.message : String(error);
13862
+ const message = describeError(error);
13855
13863
  const failed = db.update(researchRunQueries).set({ status: ResearchQueryStatuses.failed, error: message, finishedAt: (/* @__PURE__ */ new Date()).toISOString() }).where(and17(eq23(researchRunQueries.id, queryId), inArray8(researchRunQueries.status, unfinishedResearchQueryStatuses))).run();
13856
13864
  if (failed.changes === 1) incrementResearchProgress(db, runId, "failedQueries");
13857
13865
  }
@@ -14123,7 +14131,7 @@ async function createServer(opts) {
14123
14131
  dropLegacyCredentialColumns(opts.db);
14124
14132
  } catch (err) {
14125
14133
  log20.warn("credentials.migration.failed", {
14126
- error: err instanceof Error ? err.message : String(err)
14134
+ error: describeError(err)
14127
14135
  });
14128
14136
  }
14129
14137
  log20.info("providers.configured", {
@@ -14524,7 +14532,7 @@ async function createServer(opts) {
14524
14532
  {
14525
14533
  projectName,
14526
14534
  sourceId,
14527
- err: err instanceof Error ? err.message : String(err)
14535
+ err: describeError(err)
14528
14536
  },
14529
14537
  "Scheduled traffic sync failed"
14530
14538
  );
@@ -14585,7 +14593,7 @@ async function createServer(opts) {
14585
14593
  {
14586
14594
  projectName,
14587
14595
  release: probed.release,
14588
- err: err instanceof Error ? err.message : String(err)
14596
+ err: describeError(err)
14589
14597
  },
14590
14598
  "Scheduled backlinks sync failed"
14591
14599
  );