@ainyc/canonry 2.4.5 → 2.5.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.
package/dist/cli.js CHANGED
@@ -38,7 +38,7 @@ import {
38
38
  showFirstRunNotice,
39
39
  trackEvent,
40
40
  usageError
41
- } from "./chunk-6UY2PETG.js";
41
+ } from "./chunk-TIHU2YXW.js";
42
42
  import {
43
43
  apiKeys,
44
44
  competitors,
@@ -813,6 +813,35 @@ var BACKLINKS_CLI_COMMANDS = [
813
813
  function getClient2() {
814
814
  return createApiClient();
815
815
  }
816
+ async function waitForRunStatus(client, runId, config) {
817
+ const start = Date.now();
818
+ process.stderr.write(config.progressLabel);
819
+ while (Date.now() - start < config.timeoutMs) {
820
+ await new Promise((resolve) => setTimeout(resolve, config.intervalMs));
821
+ const current = await client.getRun(runId);
822
+ process.stderr.write(".");
823
+ if (config.successStatuses.includes(current.status)) {
824
+ process.stderr.write("\n");
825
+ return current;
826
+ }
827
+ if (config.failureStatuses.includes(current.status)) {
828
+ process.stderr.write("\n");
829
+ throw new CliError({
830
+ code: config.failureCode,
831
+ message: config.failureMessage,
832
+ displayMessage: config.failureMessage,
833
+ details: { runId, status: current.status, ...config.details ?? {} }
834
+ });
835
+ }
836
+ }
837
+ process.stderr.write("\n");
838
+ throw new CliError({
839
+ code: config.timeoutCode,
840
+ message: config.timeoutMessage,
841
+ displayMessage: config.timeoutMessage,
842
+ details: { runId, ...config.details ?? {} }
843
+ });
844
+ }
816
845
  async function bingConnect(project, opts) {
817
846
  const apiKey = opts?.apiKey;
818
847
  if (!apiKey) {
@@ -1091,6 +1120,42 @@ async function bingRequestIndexing(project, opts) {
1091
1120
  console.log(`Summary: ${result.summary.succeeded} succeeded, ${result.summary.failed} failed (${result.summary.total} total)`);
1092
1121
  }
1093
1122
  }
1123
+ async function bingInspectSitemap(project, opts) {
1124
+ const client = getClient2();
1125
+ const run = await client.bingInspectSitemap(project, {
1126
+ sitemapUrl: opts.sitemapUrl
1127
+ });
1128
+ if (!opts.wait && opts.format === "json") {
1129
+ console.log(JSON.stringify(run, null, 2));
1130
+ return;
1131
+ }
1132
+ if (opts.format !== "json") {
1133
+ console.log(`Bing sitemap inspection started (run ${run.id})`);
1134
+ }
1135
+ if (opts.wait) {
1136
+ const current = await waitForRunStatus(client, run.id, {
1137
+ timeoutMs: 30 * 60 * 1e3,
1138
+ intervalMs: 3e3,
1139
+ progressLabel: "Waiting for Bing sitemap inspection to complete",
1140
+ successStatuses: ["completed", "partial"],
1141
+ failureStatuses: ["failed"],
1142
+ timeoutCode: "BING_INSPECT_SITEMAP_TIMEOUT",
1143
+ failureCode: "BING_INSPECT_SITEMAP_FAILED",
1144
+ timeoutMessage: "Timed out waiting for Bing sitemap inspection to complete.",
1145
+ failureMessage: "Bing sitemap inspection failed.",
1146
+ details: { project }
1147
+ });
1148
+ if (opts.format === "json") {
1149
+ console.log(JSON.stringify(current, null, 2));
1150
+ return;
1151
+ }
1152
+ if (current.status === "partial") {
1153
+ console.log("Bing sitemap inspection completed with some errors.");
1154
+ return;
1155
+ }
1156
+ console.log("Bing sitemap inspection completed successfully.");
1157
+ }
1158
+ }
1094
1159
  async function bingPerformance(project, format) {
1095
1160
  const client = getClient2();
1096
1161
  const rows = await client.bingPerformance(project);
@@ -1222,6 +1287,22 @@ var BING_CLI_COMMANDS = [
1222
1287
  });
1223
1288
  }
1224
1289
  },
1290
+ {
1291
+ path: ["bing", "inspect-sitemap"],
1292
+ usage: "canonry bing inspect-sitemap <project> [--sitemap-url <url>] [--wait] [--format json]",
1293
+ options: {
1294
+ "sitemap-url": stringOption(),
1295
+ wait: { type: "boolean", default: false }
1296
+ },
1297
+ run: async (input) => {
1298
+ const project = requireProject(input, "bing.inspect-sitemap", "canonry bing inspect-sitemap <project> [--sitemap-url <url>] [--wait] [--format json]");
1299
+ await bingInspectSitemap(project, {
1300
+ sitemapUrl: getString(input.values, "sitemap-url"),
1301
+ wait: getBoolean(input.values, "wait"),
1302
+ format: input.format
1303
+ });
1304
+ }
1305
+ },
1225
1306
  {
1226
1307
  path: ["bing", "request-indexing"],
1227
1308
  usage: "canonry bing request-indexing <project> [url] [--all-unindexed] [--format json]",
@@ -1266,12 +1347,12 @@ var BING_CLI_COMMANDS = [
1266
1347
  },
1267
1348
  {
1268
1349
  path: ["bing"],
1269
- usage: "canonry bing <connect|disconnect|status|sites|set-site|coverage|coverage-history|inspect|inspections|request-indexing|performance|refresh> <project> [args]",
1350
+ usage: "canonry bing <connect|disconnect|status|sites|set-site|coverage|coverage-history|inspect|inspect-sitemap|inspections|request-indexing|performance|refresh> <project> [args]",
1270
1351
  run: async (input) => {
1271
1352
  unknownSubcommand(input.positionals[0], {
1272
1353
  command: "bing",
1273
- usage: "canonry bing <connect|disconnect|status|sites|set-site|coverage|coverage-history|inspect|inspections|request-indexing|performance|refresh> <project> [args]",
1274
- available: ["connect", "disconnect", "status", "sites", "set-site", "coverage", "coverage-history", "inspect", "inspections", "request-indexing", "performance", "refresh"]
1354
+ usage: "canonry bing <connect|disconnect|status|sites|set-site|coverage|coverage-history|inspect|inspect-sitemap|inspections|request-indexing|performance|refresh> <project> [args]",
1355
+ available: ["connect", "disconnect", "status", "sites", "set-site", "coverage", "coverage-history", "inspect", "inspect-sitemap", "inspections", "request-indexing", "performance", "refresh"]
1275
1356
  });
1276
1357
  }
1277
1358
  }
@@ -2181,10 +2262,11 @@ var COMPETITOR_CLI_COMMANDS = [
2181
2262
  ];
2182
2263
 
2183
2264
  // src/commands/google.ts
2265
+ var INDEXING_API_SCOPE_NOTICE = "Note: Google's Indexing API officially supports only pages with JobPosting or BroadcastEvent (livestream VideoObject) structured data. For other URL types, submissions are accepted (HTTP 200) but not guaranteed to be prioritized for crawling. For general pages, submit a sitemap and use URL Inspection to monitor status.";
2184
2266
  function getClient6() {
2185
2267
  return createApiClient();
2186
2268
  }
2187
- async function waitForRunStatus(client, runId, config) {
2269
+ async function waitForRunStatus2(client, runId, config) {
2188
2270
  const start = Date.now();
2189
2271
  process.stderr.write(config.progressLabel);
2190
2272
  while (Date.now() - start < config.timeoutMs) {
@@ -2328,7 +2410,7 @@ async function googleSync(project, opts) {
2328
2410
  console.log(`GSC sync started (run ${run.id})`);
2329
2411
  }
2330
2412
  if (opts.wait) {
2331
- const current = await waitForRunStatus(client, run.id, {
2413
+ const current = await waitForRunStatus2(client, run.id, {
2332
2414
  timeoutMs: 10 * 60 * 1e3,
2333
2415
  intervalMs: 2e3,
2334
2416
  progressLabel: "Waiting for sync to complete",
@@ -2518,7 +2600,7 @@ async function googleInspectSitemap(project, opts) {
2518
2600
  console.log(`Sitemap inspection started (run ${run.id})`);
2519
2601
  }
2520
2602
  if (opts.wait) {
2521
- const current = await waitForRunStatus(client, run.id, {
2603
+ const current = await waitForRunStatus2(client, run.id, {
2522
2604
  timeoutMs: 30 * 60 * 1e3,
2523
2605
  intervalMs: 3e3,
2524
2606
  progressLabel: "Waiting for sitemap inspection to complete",
@@ -2586,7 +2668,7 @@ Primary sitemap: ${result.primarySitemapUrl}`);
2586
2668
  console.log(`Sitemap URL saved. Inspection run queued (run ${result.run.id}).`);
2587
2669
  }
2588
2670
  if (opts.wait) {
2589
- const current = await waitForRunStatus(client, result.run.id, {
2671
+ const current = await waitForRunStatus2(client, result.run.id, {
2590
2672
  timeoutMs: 30 * 60 * 1e3,
2591
2673
  intervalMs: 3e3,
2592
2674
  progressLabel: "Waiting for sitemap inspection to complete",
@@ -2630,27 +2712,32 @@ async function googleRequestIndexing(project, opts) {
2630
2712
  details: { command: "google.request-indexing" }
2631
2713
  });
2632
2714
  }
2715
+ if (opts.format !== "json") {
2716
+ console.error(INDEXING_API_SCOPE_NOTICE);
2717
+ console.error();
2718
+ }
2633
2719
  const result = await client.googleRequestIndexing(project, body);
2634
2720
  let indexingConfirmed = false;
2721
+ const lastInspection = /* @__PURE__ */ new Map();
2635
2722
  if (opts.wait && result.results.some((r) => r.status === "success")) {
2636
2723
  const successUrls = result.results.filter((r) => r.status === "success").map((r) => r.url);
2637
- const timeout = 10 * 60 * 1e3;
2724
+ const timeout = opts.waitTimeoutMs ?? 10 * 60 * 1e3;
2725
+ const pollInterval = opts.waitPollIntervalMs ?? 1e4;
2638
2726
  const start = Date.now();
2639
- process.stderr.write("Waiting for indexing confirmation");
2727
+ process.stderr.write("Polling URL Inspection for indexed verdict");
2640
2728
  while (Date.now() - start < timeout) {
2641
- await new Promise((r) => setTimeout(r, 1e4));
2729
+ await new Promise((r) => setTimeout(r, pollInterval));
2642
2730
  process.stderr.write(".");
2643
2731
  let allIndexed = true;
2644
2732
  for (const url of successUrls) {
2645
2733
  try {
2646
2734
  const inspection = await client.gscInspect(project, url);
2647
- if (inspection.indexingState !== "INDEXING_ALLOWED") {
2735
+ lastInspection.set(url, inspection);
2736
+ if (inspection.verdict !== "PASS") {
2648
2737
  allIndexed = false;
2649
- break;
2650
2738
  }
2651
2739
  } catch {
2652
2740
  allIndexed = false;
2653
- break;
2654
2741
  }
2655
2742
  }
2656
2743
  if (allIndexed) {
@@ -2661,13 +2748,23 @@ async function googleRequestIndexing(project, opts) {
2661
2748
  }
2662
2749
  if (!indexingConfirmed) {
2663
2750
  process.stderr.write("\n");
2751
+ const observed = successUrls.map((url) => {
2752
+ const i = lastInspection.get(url);
2753
+ return {
2754
+ url,
2755
+ verdict: i?.verdict ?? null,
2756
+ coverageState: i?.coverageState ?? null,
2757
+ indexingState: i?.indexingState ?? null
2758
+ };
2759
+ });
2664
2760
  throw new CliError({
2665
2761
  code: "GOOGLE_INDEXING_CONFIRMATION_TIMEOUT",
2666
- message: "Timed out waiting for indexing confirmation. URLs may still be processing.",
2667
- displayMessage: "Timed out waiting for indexing confirmation. URLs may still be processing.",
2762
+ message: "Timed out waiting for Google to report verdict=PASS. Google typically takes hours to days to index new URLs, so this is expected and does not mean the submission failed. Re-check later with `canonry google gsc inspect <url>`.",
2763
+ displayMessage: "Timed out waiting for Google to report verdict=PASS. Google typically takes hours to days to index new URLs \u2014 this is not a failure. Re-check later with `canonry google gsc inspect <url>`.",
2668
2764
  details: {
2669
2765
  project,
2670
- urls: successUrls
2766
+ urls: successUrls,
2767
+ lastObserved: observed
2671
2768
  }
2672
2769
  });
2673
2770
  }
@@ -2692,7 +2789,7 @@ async function googleRequestIndexing(project, opts) {
2692
2789
  console.log(`Summary: ${result.summary.succeeded} succeeded, ${result.summary.failed} failed (${result.summary.total} total)`);
2693
2790
  }
2694
2791
  if (indexingConfirmed) {
2695
- console.log("All requested URLs are now indexed.");
2792
+ console.log("URL Inspection now reports verdict=PASS for the requested URLs (indexed in Google Search).");
2696
2793
  }
2697
2794
  }
2698
2795
  async function googleRefresh(project, format) {
@@ -2701,7 +2798,7 @@ async function googleRefresh(project, format) {
2701
2798
  if (format !== "json") {
2702
2799
  process.stderr.write("Refreshing GSC coverage data");
2703
2800
  }
2704
- const current = await waitForRunStatus(client, run.id, {
2801
+ const current = await waitForRunStatus2(client, run.id, {
2705
2802
  timeoutMs: 10 * 60 * 1e3,
2706
2803
  intervalMs: 2e3,
2707
2804
  progressLabel: "",
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  createServer,
3
3
  loadConfig
4
- } from "./chunk-6UY2PETG.js";
4
+ } from "./chunk-TIHU2YXW.js";
5
5
  import "./chunk-32YTAZBL.js";
6
6
  export {
7
7
  createServer,
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "@ainyc/canonry",
3
- "version": "2.4.5",
3
+ "version": "2.5.0",
4
4
  "type": "module",
5
- "description": "The ultimate open-source AEO monitoring tool - track how answer engines cite your domain",
5
+ "description": "Agent-first open-source AEO operating platform - track how answer engines cite your domain",
6
6
  "license": "FSL-1.1-ALv2",
7
7
  "homepage": "https://ainyc.ai",
8
8
  "repository": {
@@ -57,21 +57,21 @@
57
57
  "@types/node-cron": "^3.0.11",
58
58
  "tsup": "^8.5.1",
59
59
  "tsx": "^4.19.0",
60
- "@ainyc/canonry-db": "0.0.0",
61
60
  "@ainyc/canonry-api-routes": "0.0.0",
62
- "@ainyc/canonry-intelligence": "0.0.0",
61
+ "@ainyc/canonry-config": "0.0.0",
62
+ "@ainyc/canonry-db": "0.0.0",
63
63
  "@ainyc/canonry-contracts": "0.0.0",
64
+ "@ainyc/canonry-intelligence": "0.0.0",
64
65
  "@ainyc/canonry-integration-bing": "0.0.0",
65
- "@ainyc/canonry-config": "0.0.0",
66
66
  "@ainyc/canonry-integration-commoncrawl": "0.0.0",
67
67
  "@ainyc/canonry-integration-google": "0.0.0",
68
68
  "@ainyc/canonry-integration-wordpress": "0.0.0",
69
- "@ainyc/canonry-provider-gemini": "0.0.0",
70
- "@ainyc/canonry-provider-local": "0.0.0",
69
+ "@ainyc/canonry-provider-claude": "0.0.0",
71
70
  "@ainyc/canonry-provider-cdp": "0.0.0",
71
+ "@ainyc/canonry-provider-local": "0.0.0",
72
72
  "@ainyc/canonry-provider-openai": "0.0.0",
73
- "@ainyc/canonry-provider-perplexity": "0.0.0",
74
- "@ainyc/canonry-provider-claude": "0.0.0"
73
+ "@ainyc/canonry-provider-gemini": "0.0.0",
74
+ "@ainyc/canonry-provider-perplexity": "0.0.0"
75
75
  },
76
76
  "scripts": {
77
77
  "build": "tsx scripts/copy-agent-assets.ts && tsup && tsx build-web.ts",