@ainyc/canonry 4.190.0 → 4.191.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 (30) hide show
  1. package/README.md +1 -1
  2. package/assets/agent-workspace/skills/canonry/SKILL.md +124 -216
  3. package/assets/assets/{AuditHistoryPanel-wWLs088f.js → AuditHistoryPanel-C2dvjYNh.js} +1 -1
  4. package/assets/assets/{BacklinksPage-DJEO5o9c.js → BacklinksPage-D1yPQtfF.js} +1 -1
  5. package/assets/assets/{HistoryPage-CV5bTBU6.js → HistoryPage-DOEa7naA.js} +1 -1
  6. package/assets/assets/{MeasurementPropertyPage-C7KLIAad.js → MeasurementPropertyPage-D-O8vnMS.js} +1 -1
  7. package/assets/assets/ProjectPage-DqTCcimz.js +8 -0
  8. package/assets/assets/{RunRow-C3Ryj_9u.js → RunRow-BO7lyC1C.js} +1 -1
  9. package/assets/assets/{RunsPage-BxoEkZu3.js → RunsPage-DHSWfTav.js} +1 -1
  10. package/assets/assets/{SettingsPage-D_mB1JUZ.js → SettingsPage-oiJdhiq0.js} +1 -1
  11. package/assets/assets/SiteHealthSection-gVdylFY-.js +4 -0
  12. package/assets/assets/{TrafficPage-DgsWuDtv.js → TrafficPage-YIdwRpQh.js} +1 -1
  13. package/assets/assets/{TrafficSourceDetailPage-BLWlQ8aT.js → TrafficSourceDetailPage-B4Cop6ox.js} +1 -1
  14. package/assets/assets/{extract-error-message-DHIHApUf.js → extract-error-message-XavUZNf3.js} +1 -1
  15. package/assets/assets/{index-BjjM151x.css → index-BtTEcbcB.css} +1 -1
  16. package/assets/assets/{index-nb8QHq99.js → index-njfYnO22.js} +25 -25
  17. package/assets/assets/{react-sigma_core.esm.min-DzTADS1A.js → react-sigma_core.esm.min-V7giUpEn.js} +1 -1
  18. package/assets/index.html +2 -2
  19. package/dist/{chunk-32QBVRMN.js → chunk-2A7E5TDU.js} +209 -29
  20. package/dist/{chunk-ROPJUNQN.js → chunk-KBUV3HGS.js} +55 -9
  21. package/dist/{chunk-2II4ZMMH.js → chunk-WSD5J6O4.js} +2 -2
  22. package/dist/{chunk-4NIQ3GMO.js → chunk-XI6FN52S.js} +33 -13
  23. package/dist/{chunk-6POEZ7GT.js → chunk-ZK4FJDCH.js} +291 -114
  24. package/dist/cli.js +56 -5
  25. package/dist/index.js +4 -4
  26. package/dist/{intelligence-service-WNASQFN4.js → intelligence-service-EVRWZHDG.js} +2 -2
  27. package/dist/mcp.js +13 -8
  28. package/package.json +11 -11
  29. package/assets/assets/ProjectPage-DIW1h05b.js +0 -8
  30. package/assets/assets/SiteHealthSection-Dgqtz9J2.js +0 -4
package/dist/cli.js CHANGED
@@ -28,11 +28,11 @@ import {
28
28
  trackCliCommandFinished,
29
29
  trackEvent,
30
30
  waitForServerRuntimeStartup
31
- } from "./chunk-4NIQ3GMO.js";
31
+ } from "./chunk-XI6FN52S.js";
32
32
  import {
33
33
  autoSyncSkills,
34
34
  formatAutoSyncNotice
35
- } from "./chunk-2II4ZMMH.js";
35
+ } from "./chunk-WSD5J6O4.js";
36
36
  import {
37
37
  CliError,
38
38
  EXIT_SYSTEM_ERROR,
@@ -58,7 +58,7 @@ import {
58
58
  saveConfigPatch,
59
59
  systemError,
60
60
  usageError
61
- } from "./chunk-32QBVRMN.js";
61
+ } from "./chunk-2A7E5TDU.js";
62
62
  import {
63
63
  CLOUDFLARE_WORKER_BINDINGS,
64
64
  CLOUDFLARE_WORKER_GENERATED_MARKER,
@@ -72,7 +72,7 @@ import {
72
72
  projects,
73
73
  queries,
74
74
  renderReportHtml
75
- } from "./chunk-6POEZ7GT.js";
75
+ } from "./chunk-ZK4FJDCH.js";
76
76
  import {
77
77
  AdsDeliverySnapshotStatuses,
78
78
  AdsHistoricalCampaignRollupStatuses,
@@ -141,13 +141,14 @@ import {
141
141
  notificationEventSchema,
142
142
  queryTrackingCommitRequestSchema,
143
143
  queryTrackingPreviewRequestSchema,
144
+ researchBatchCreateSchema,
144
145
  resolveProviderInput,
145
146
  resultsClearRequestSchema,
146
147
  shareOfVoiceLabel,
147
148
  shareOfVoiceReason,
148
149
  visibilityReportRequestSchema,
149
150
  winnabilityClassSchema
150
- } from "./chunk-ROPJUNQN.js";
151
+ } from "./chunk-KBUV3HGS.js";
151
152
 
152
153
  // src/cli.ts
153
154
  import { pathToFileURL } from "url";
@@ -2599,6 +2600,7 @@ var DISCOVER_CLI_COMMANDS = [
2599
2600
  ];
2600
2601
 
2601
2602
  // src/commands/research.ts
2603
+ import { readFileSync } from "fs";
2602
2604
  var TERMINAL_RESEARCH_STATUSES = /* @__PURE__ */ new Set([
2603
2605
  ResearchRunStatuses.completed,
2604
2606
  ResearchRunStatuses.partial,
@@ -2636,6 +2638,39 @@ async function researchRun(project, opts) {
2636
2638
  const detail = await pollResearchRun(client, project, started.id, isMachineFormat(opts.format));
2637
2639
  printDetail(project, detail, opts.format);
2638
2640
  }
2641
+ async function researchBatch(project, source, opts) {
2642
+ let raw;
2643
+ try {
2644
+ raw = JSON.parse(readFileSync(source === "-" ? 0 : source, "utf8"));
2645
+ } catch {
2646
+ throw usageError("Research batch input must be a readable JSON file (or - for stdin).", {
2647
+ message: "Research batch input must be a readable JSON file (or - for stdin).",
2648
+ details: { command: "research.batch" }
2649
+ });
2650
+ }
2651
+ const parsed = researchBatchCreateSchema.safeParse(raw);
2652
+ if (!parsed.success) {
2653
+ const message = parsed.error.issues.map((issue) => `${issue.path.join(".")}: ${issue.message}`).join("; ");
2654
+ throw usageError(`Invalid research batch: ${message}`, {
2655
+ message: `Invalid research batch: ${message}`,
2656
+ details: { command: "research.batch" }
2657
+ });
2658
+ }
2659
+ const client = getClient5();
2660
+ const started = await client.startResearchBatch(project, parsed.data);
2661
+ const runs = opts.wait ? await Promise.all(started.runs.map((run) => TERMINAL_RESEARCH_STATUSES.has(run.status) ? Promise.resolve(run) : pollResearchRun(client, project, run.id, true))) : started.runs;
2662
+ if (opts.format === "jsonl") {
2663
+ emitJsonl(runs.map((run) => ({ project, ...run })));
2664
+ } else if (opts.format === "json") {
2665
+ console.log(JSON.stringify({ runs }, null, 2));
2666
+ } else {
2667
+ console.log(`Research saved for ${runs.length} destinations (${runs.reduce((count, run) => count + run.totalQueries, 0)} queries).`);
2668
+ for (const run of runs) {
2669
+ if (opts.wait) printDetail(project, run);
2670
+ else printStarted(project, run);
2671
+ }
2672
+ }
2673
+ }
2639
2674
  async function researchList(project, opts) {
2640
2675
  const client = getClient5();
2641
2676
  const { runs } = await client.listResearchRuns(project, opts.limit === void 0 ? void 0 : { limit: opts.limit });
@@ -2688,6 +2723,7 @@ function printStarted(project, run) {
2688
2723
  console.log(` Status: ${run.status}`);
2689
2724
  console.log(` Queries: ${run.totalQueries}`);
2690
2725
  console.log(` Scope: ${formatScope(run.scope)}`);
2726
+ console.log(` Location: ${run.location?.label ?? "No location context"}`);
2691
2727
  console.log(` Provider: ${run.provider}${run.resolvedModel ? ` / ${run.resolvedModel}` : ""}`);
2692
2728
  console.log(` Inspect: canonry research show ${project} ${run.id}`);
2693
2729
  console.log(" Nothing was added to tracked queries.");
@@ -2737,6 +2773,7 @@ function formatScope(scope) {
2737
2773
 
2738
2774
  // src/cli-commands/research.ts
2739
2775
  var RUN_USAGE = "canonry research run <project> <query...> [--query <text>] [--provider <name>] [--model <id>] [--market <key>|--property <key>] [--template-id <id> --template-version <version>] [--location <label>|--no-location] [--idempotency-key <key>] [--wait] [--format json|jsonl]";
2776
+ var BATCH_USAGE = "canonry research batch <project> <json-file|-> [--wait] [--format json|jsonl]";
2740
2777
  function normalizeQueries(input, usage) {
2741
2778
  const positional = input.positionals.slice(1);
2742
2779
  const flagged = getStringArray(input.values, "query") ?? [];
@@ -2814,6 +2851,20 @@ Usage: ${usage}`, {
2814
2851
  return templateId && templateVersion ? { templateId, templateVersion } : void 0;
2815
2852
  }
2816
2853
  var RESEARCH_CLI_COMMANDS = [
2854
+ {
2855
+ path: ["research", "batch"],
2856
+ usage: BATCH_USAGE,
2857
+ options: { wait: { type: "boolean", default: false } },
2858
+ run: async (input) => {
2859
+ const project = requireProject(input, "research.batch", BATCH_USAGE);
2860
+ const source = requirePositional(input, 1, {
2861
+ command: "research.batch",
2862
+ usage: BATCH_USAGE,
2863
+ message: "reviewed research batch JSON file is required"
2864
+ });
2865
+ await researchBatch(project, source, { wait: getBoolean(input.values, "wait"), format: input.format });
2866
+ }
2867
+ },
2817
2868
  {
2818
2869
  path: ["research", "run"],
2819
2870
  usage: RUN_USAGE,
package/dist/index.js CHANGED
@@ -3,12 +3,12 @@ import {
3
3
  createGoogleMarketingCredentialStore,
4
4
  createGoogleMarketingRuntime,
5
5
  createServer
6
- } from "./chunk-4NIQ3GMO.js";
6
+ } from "./chunk-XI6FN52S.js";
7
7
  import {
8
8
  loadConfig
9
- } from "./chunk-32QBVRMN.js";
10
- import "./chunk-6POEZ7GT.js";
11
- import "./chunk-ROPJUNQN.js";
9
+ } from "./chunk-2A7E5TDU.js";
10
+ import "./chunk-ZK4FJDCH.js";
11
+ import "./chunk-KBUV3HGS.js";
12
12
  export {
13
13
  GoogleMarketingRuntimeError,
14
14
  createGoogleMarketingCredentialStore,
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  IntelligenceService
3
- } from "./chunk-6POEZ7GT.js";
4
- import "./chunk-ROPJUNQN.js";
3
+ } from "./chunk-ZK4FJDCH.js";
4
+ import "./chunk-KBUV3HGS.js";
5
5
  export {
6
6
  IntelligenceService
7
7
  };
package/dist/mcp.js CHANGED
@@ -1,13 +1,13 @@
1
1
  import {
2
2
  autoSyncSkills
3
- } from "./chunk-2II4ZMMH.js";
3
+ } from "./chunk-WSD5J6O4.js";
4
4
  import {
5
5
  createApiClient,
6
6
  createCanonryMcpServer
7
- } from "./chunk-32QBVRMN.js";
7
+ } from "./chunk-2A7E5TDU.js";
8
8
  import {
9
9
  isReadOnlyKey
10
- } from "./chunk-ROPJUNQN.js";
10
+ } from "./chunk-KBUV3HGS.js";
11
11
 
12
12
  // src/mcp/cli.ts
13
13
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
@@ -46,23 +46,27 @@ async function main(argv = process.argv.slice(2)) {
46
46
  }
47
47
  void autoSyncSkills();
48
48
  const client = createApiClient();
49
- const scope = await resolveEffectiveScope(client, options.scope);
50
- const server = createCanonryMcpServer({ scope, eager: options.eager, clientFactory: () => client });
49
+ const authorization = await resolveEffectiveAuthorization(client, options.scope);
50
+ const server = createCanonryMcpServer({ ...authorization, eager: options.eager, clientFactory: () => client });
51
51
  await server.connect(new StdioServerTransport());
52
52
  }
53
53
  async function resolveEffectiveScope(client, flagScope) {
54
- if (flagScope === "read-only") return "read-only";
54
+ return (await resolveEffectiveAuthorization(client, flagScope)).scope;
55
+ }
56
+ async function resolveEffectiveAuthorization(client, flagScope) {
57
+ if (flagScope === "read-only") return { scope: "read-only" };
55
58
  try {
56
59
  const self = await client.getApiKeySelf();
57
60
  if (isReadOnlyKey(self.scopes)) {
58
61
  process.stderr.write(
59
62
  "canonry-mcp: configured API key is read-only \u2014 restricting to read tools.\n"
60
63
  );
61
- return "read-only";
64
+ return { scope: "read-only", credentialScopes: self.scopes };
62
65
  }
66
+ return { scope: flagScope, credentialScopes: self.scopes };
63
67
  } catch {
64
68
  }
65
- return flagScope;
69
+ return { scope: flagScope };
66
70
  }
67
71
  function parseCliOptions(argv, env = process.env) {
68
72
  if (argv.includes("--help") || argv.includes("-h")) {
@@ -118,5 +122,6 @@ export {
118
122
  HelpRequested,
119
123
  main,
120
124
  parseCliOptions,
125
+ resolveEffectiveAuthorization,
121
126
  resolveEffectiveScope
122
127
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ainyc/canonry",
3
- "version": "4.190.0",
3
+ "version": "4.191.0",
4
4
  "type": "module",
5
5
  "description": "Self-hosted AI visibility (AEO) platform: track how ChatGPT, Claude, Gemini, and Perplexity cite your domain, join it with Search Console, GA4, server-side traffic, and paid media, and fix what you find through agent tools (CLI, REST, MCP). Local SQLite.",
6
6
  "license": "FSL-1.1-ALv2",
@@ -70,31 +70,31 @@
70
70
  "@types/node-cron": "^3.0.11",
71
71
  "tsup": "^8.5.1",
72
72
  "tsx": "^4.19.0",
73
+ "@ainyc/canonry-api-client": "0.0.0",
73
74
  "@ainyc/canonry-web": "0.0.0",
74
75
  "@ainyc/canonry-api-routes": "0.0.0",
75
- "@ainyc/canonry-contracts": "0.0.0",
76
76
  "@ainyc/canonry-config": "0.0.0",
77
- "@ainyc/canonry-api-client": "0.0.0",
78
- "@ainyc/canonry-integration-bing": "0.0.0",
77
+ "@ainyc/canonry-contracts": "0.0.0",
78
+ "@ainyc/canonry-db": "0.0.0",
79
79
  "@ainyc/canonry-integration-cloud-run": "0.0.0",
80
+ "@ainyc/canonry-integration-bing": "0.0.0",
81
+ "@ainyc/canonry-integration-cloudflare-worker": "0.0.0",
80
82
  "@ainyc/canonry-integration-cloudflare-queue": "0.0.0",
81
- "@ainyc/canonry-db": "0.0.0",
83
+ "@ainyc/canonry-integration-google": "0.0.0",
82
84
  "@ainyc/canonry-integration-commoncrawl": "0.0.0",
83
- "@ainyc/canonry-integration-cloudflare-worker": "0.0.0",
84
85
  "@ainyc/canonry-integration-google-ads": "0.0.0",
85
- "@ainyc/canonry-integration-google": "0.0.0",
86
86
  "@ainyc/canonry-integration-google-places": "0.0.0",
87
87
  "@ainyc/canonry-integration-google-tag-manager": "0.0.0",
88
- "@ainyc/canonry-integration-google-business-profile": "0.0.0",
89
88
  "@ainyc/canonry-integration-openai-ads": "0.0.0",
90
- "@ainyc/canonry-integration-wordpress": "0.0.0",
91
- "@ainyc/canonry-intelligence": "0.0.0",
92
89
  "@ainyc/canonry-integration-traffic": "0.0.0",
90
+ "@ainyc/canonry-integration-wordpress": "0.0.0",
91
+ "@ainyc/canonry-integration-google-business-profile": "0.0.0",
93
92
  "@ainyc/canonry-provider-cdp": "0.0.0",
93
+ "@ainyc/canonry-intelligence": "0.0.0",
94
94
  "@ainyc/canonry-provider-claude": "0.0.0",
95
95
  "@ainyc/canonry-provider-gemini": "0.0.0",
96
- "@ainyc/canonry-provider-openai": "0.0.0",
97
96
  "@ainyc/canonry-provider-local": "0.0.0",
97
+ "@ainyc/canonry-provider-openai": "0.0.0",
98
98
  "@ainyc/canonry-provider-perplexity": "0.0.0"
99
99
  },
100
100
  "scripts": {