@canonry/canonry 5.11.0 → 5.13.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/assets/agent-workspace/skills/canonry/references/canonry-cli.md +5 -0
  2. package/assets/assets/{AuditHistoryPanel-Cq8CoZV5.js → AuditHistoryPanel-DWDOPf8c.js} +1 -1
  3. package/assets/assets/{BacklinksPage-B5_QeuXd.js → BacklinksPage-DGxq-iU6.js} +1 -1
  4. package/assets/assets/{HistoryPage-Foj5--rM.js → HistoryPage-DR91m-gT.js} +1 -1
  5. package/assets/assets/{MeasurementPropertyPage-2t8jVNFL.js → MeasurementPropertyPage-a8poltfM.js} +1 -1
  6. package/assets/assets/{ProjectPage-By0UYm8r.js → ProjectPage-CCCJE7rA.js} +1 -1
  7. package/assets/assets/{RunRow-CbTtzDK5.js → RunRow-Xe63DyPK.js} +1 -1
  8. package/assets/assets/{RunsPage-Cjv7YiXR.js → RunsPage-DK119ZZw.js} +1 -1
  9. package/assets/assets/{SettingsPage-DIQgJQ8Y.js → SettingsPage-G461foD-.js} +1 -1
  10. package/assets/assets/{SiteHealthSection-CUNhD0To.js → SiteHealthSection-CJnHkGM2.js} +3 -3
  11. package/assets/assets/{TrafficPage-abuZqCEU.js → TrafficPage-AsWgc7Ot.js} +1 -1
  12. package/assets/assets/{TrafficSourceDetailPage-B-zVt0Sa.js → TrafficSourceDetailPage-D10yBQoD.js} +1 -1
  13. package/assets/assets/{extract-error-message-C5-X8IcG.js → extract-error-message-PP4HD_Dp.js} +1 -1
  14. package/assets/assets/{index-Dzg_siX8.js → index-CCIeAE4J.js} +27 -27
  15. package/assets/assets/{react-sigma_core.esm.min-Ybxr8Ybd.js → react-sigma_core.esm.min-CkyyYkKU.js} +1 -1
  16. package/assets/assets/{v2-overview-adapter-BMOnF8IE.js → v2-overview-adapter-DW-In1hp.js} +1 -1
  17. package/assets/index.html +1 -1
  18. package/dist/{chunk-NV3X6O5P.js → chunk-6YLNO2T5.js} +2 -2
  19. package/dist/{chunk-JNU6GLAV.js → chunk-IDZQ5H3J.js} +2 -2
  20. package/dist/{chunk-JW5DCORY.js → chunk-IPGBK7XR.js} +87 -1
  21. package/dist/{chunk-SMYBGUVV.js → chunk-Q35D2R2P.js} +2515 -2097
  22. package/dist/{chunk-UYSTNPTX.js → chunk-TDHRUXN3.js} +487 -172
  23. package/dist/{chunk-MQMJJZ6W.js → chunk-UWJAATGC.js} +3021 -2925
  24. package/dist/cli.js +133 -7
  25. package/dist/{demo-server-76IZBMJ3.js → demo-server-IZFTJI7E.js} +3 -3
  26. package/dist/index.d.ts +28 -1
  27. package/dist/index.js +5 -5
  28. package/dist/{intelligence-service-KF5WWPGR.js → intelligence-service-PM7MC5VC.js} +2 -2
  29. package/dist/mcp.js +3 -3
  30. package/package.json +8 -8
package/dist/cli.js CHANGED
@@ -35,11 +35,11 @@ import {
35
35
  trackCliCommandFinished,
36
36
  trackEvent,
37
37
  waitForServerRuntimeStartup
38
- } from "./chunk-UYSTNPTX.js";
38
+ } from "./chunk-TDHRUXN3.js";
39
39
  import {
40
40
  autoSyncSkills,
41
41
  formatAutoSyncNotice
42
- } from "./chunk-NV3X6O5P.js";
42
+ } from "./chunk-6YLNO2T5.js";
43
43
  import {
44
44
  CliError,
45
45
  EXIT_SYSTEM_ERROR,
@@ -66,13 +66,13 @@ import {
66
66
  shouldPrintServeSkillsNudge,
67
67
  systemError,
68
68
  usageError
69
- } from "./chunk-JW5DCORY.js";
69
+ } from "./chunk-IPGBK7XR.js";
70
70
  import {
71
71
  DEFAULT_DEMO_TRUSTED_PROXIES,
72
72
  trustedProxiesProblem,
73
73
  trustedProxyProblem
74
74
  } from "./chunk-RB2F4D3Z.js";
75
- import "./chunk-JNU6GLAV.js";
75
+ import "./chunk-IDZQ5H3J.js";
76
76
  import "./chunk-AOJU5LKX.js";
77
77
  import {
78
78
  CLOUDFLARE_WORKER_BINDINGS,
@@ -88,7 +88,7 @@ import {
88
88
  queries,
89
89
  renderReportHtml,
90
90
  runs
91
- } from "./chunk-SMYBGUVV.js";
91
+ } from "./chunk-Q35D2R2P.js";
92
92
  import {
93
93
  AdsDeliverySnapshotStatuses,
94
94
  AdsHistoricalCampaignRollupStatuses,
@@ -173,7 +173,7 @@ import {
173
173
  snapshotProviderModeSchema,
174
174
  visibilityReportRequestSchema,
175
175
  winnabilityClassSchema
176
- } from "./chunk-MQMJJZ6W.js";
176
+ } from "./chunk-UWJAATGC.js";
177
177
 
178
178
  // src/cli.ts
179
179
  import { pathToFileURL } from "url";
@@ -438,7 +438,7 @@ function parseDemoTrustedProxies(values) {
438
438
  async function demoCommand(options) {
439
439
  const { host, port } = parseDemoListenOptions(options);
440
440
  const trustProxy = parseDemoTrustedProxies(options.trustProxy);
441
- const { createDemoServer } = await import("./demo-server-76IZBMJ3.js");
441
+ const { createDemoServer } = await import("./demo-server-IZFTJI7E.js");
442
442
  const app = await createDemoServer({ trustProxy });
443
443
  let stopping = false;
444
444
  const stop = () => {
@@ -12775,10 +12775,96 @@ function printRunDetail(run) {
12775
12775
  }
12776
12776
  }
12777
12777
  }
12778
+ var FILL_POLL_INTERVAL_MS = 3e3;
12779
+ var FILL_POLL_TIMEOUT_MS = 6 * 60 * 60 * 1e3;
12780
+ function missingSummary(completeness) {
12781
+ const parts = Object.entries(completeness.missingByProvider).sort(([left], [right]) => left.localeCompare(right)).map(([provider, count]) => `${provider} ${count}`);
12782
+ return parts.length ? parts.join(", ") : "none";
12783
+ }
12784
+ function printCompleteness(completeness) {
12785
+ console.log(`Run: ${completeness.runId}`);
12786
+ console.log(` Status: ${completeness.status}`);
12787
+ if (!completeness.planned) {
12788
+ console.log(" Not a measurement-plan run: there are no expected answers to count.");
12789
+ return;
12790
+ }
12791
+ if (!completeness.readable) {
12792
+ console.log(" Answers: unknown (the run's manifest cannot be read)");
12793
+ } else {
12794
+ console.log(` Answers: ${completeness.executed}/${completeness.expected}`);
12795
+ console.log(` Missing: ${completeness.missing} (${missingSummary(completeness)})`);
12796
+ }
12797
+ if (completeness.refusal) console.log(` Fillable: no. ${completeness.refusal.message}`);
12798
+ else console.log(` Fillable: ${completeness.fillable ? "yes" : "not right now (a sweep or another fill is running)"}`);
12799
+ const fill = completeness.latestFill;
12800
+ if (fill) {
12801
+ console.log(` Last fill: ${fill.id} ${fill.status}, ${fill.filled}/${fill.expected} recorded${fill.error ? `. ${fill.error}` : ""}`);
12802
+ }
12803
+ }
12804
+ async function showRunCompleteness(runId, format) {
12805
+ const completeness = await getClient23().getRunCompleteness(runId);
12806
+ if (isMachineFormat(format)) {
12807
+ console.log(JSON.stringify(completeness, null, 2));
12808
+ return;
12809
+ }
12810
+ printCompleteness(completeness);
12811
+ }
12812
+ async function fillRun(runId, opts = {}) {
12813
+ const client = getClient23();
12814
+ const response = await client.fillRun(runId, {
12815
+ ...opts.providers?.length ? { providers: opts.providers } : {},
12816
+ ...opts.dryRun ? { dryRun: true } : {}
12817
+ });
12818
+ if (!opts.wait || response.outcome !== "queued" || !response.fill) {
12819
+ if (isMachineFormat(opts.format)) {
12820
+ console.log(JSON.stringify(response, null, 2));
12821
+ return;
12822
+ }
12823
+ if (response.outcome === "already-complete") console.log(`Run ${runId} is already complete: nothing to fill.`);
12824
+ else if (response.outcome === "dry-run") console.log("Dry run: nothing was queued.");
12825
+ else if (response.fill) console.log(`Fill ${response.fill.id} queued: ${response.fill.expected} missing answer(s) (${missingSummary(response.completeness)}).`);
12826
+ printCompleteness(response.completeness);
12827
+ return;
12828
+ }
12829
+ const fillId = response.fill.id;
12830
+ const deadline = Date.now() + FILL_POLL_TIMEOUT_MS;
12831
+ let completeness = response.completeness;
12832
+ if (!isMachineFormat(opts.format)) {
12833
+ process.stderr.write(`Filling ${response.fill.expected} missing answer(s) in run ${runId}`);
12834
+ }
12835
+ for (; ; ) {
12836
+ await new Promise((resolve) => setTimeout(resolve, FILL_POLL_INTERVAL_MS));
12837
+ if (Date.now() > deadline) {
12838
+ throw new CliError({
12839
+ code: "RUN_FILL_INCOMPLETE",
12840
+ message: `Timed out waiting for fill ${fillId}; it may still be running. Check with: canonry run completeness ${runId}`,
12841
+ exitCode: EXIT_SYSTEM_ERROR,
12842
+ details: { runId, fillId }
12843
+ });
12844
+ }
12845
+ completeness = await client.getRunCompleteness(runId);
12846
+ if (!isMachineFormat(opts.format)) process.stderr.write(".");
12847
+ const latest = completeness.latestFill;
12848
+ const working = latest !== null && (latest.status === "queued" || latest.status === "running");
12849
+ if (completeness.status === "completed" || !working) break;
12850
+ }
12851
+ if (!isMachineFormat(opts.format)) process.stderr.write("\n");
12852
+ if (isMachineFormat(opts.format)) console.log(JSON.stringify(completeness, null, 2));
12853
+ else printCompleteness(completeness);
12854
+ if (completeness.status !== "completed") {
12855
+ throw new CliError({
12856
+ code: "RUN_FILL_INCOMPLETE",
12857
+ message: `Run ${runId} is still ${completeness.status}: ${completeness.missing} answer(s) missing (${missingSummary(completeness)}).`,
12858
+ exitCode: EXIT_SYSTEM_ERROR,
12859
+ details: { runId, fillId, missing: completeness.missing, missingByProvider: completeness.missingByProvider }
12860
+ });
12861
+ }
12862
+ }
12778
12863
 
12779
12864
  // src/cli-commands/run.ts
12780
12865
  var RUN_TRIGGER_USAGE = "canonry run trigger <project> [--group <key>]... [--target <key>]... [--provider <name>] [--query <q>...] [--location <label>] [--all-locations] [--no-location] [--probe] [--wait] [--format json]";
12781
12866
  var RUN_USAGE2 = "canonry run <project|--all> [--group <key>]... [--target <key>]... [--provider <name>] [--query <q>...] [--location <label>] [--all-locations] [--no-location] [--probe] [--wait] [--format json]";
12867
+ var RUN_FILL_USAGE = "canonry run fill <run-id> [--provider <name>[,<name>]] [--dry-run] [--wait] [--format json]";
12782
12868
  var RUNS_USAGE = "canonry runs <project> [--limit <n>] [--kind <kind>] [--status <status>] [--format json]";
12783
12869
  var RUN_TRIGGER_OPTIONS = {
12784
12870
  provider: stringOption(),
@@ -12875,6 +12961,43 @@ var RUN_CLI_COMMANDS = [
12875
12961
  await showRun(id, input.format);
12876
12962
  }
12877
12963
  },
12964
+ {
12965
+ path: ["run", "fill"],
12966
+ usage: RUN_FILL_USAGE,
12967
+ options: {
12968
+ provider: stringOption(),
12969
+ wait: { type: "boolean", default: false }
12970
+ },
12971
+ supportsDryRun: true,
12972
+ run: async (input) => {
12973
+ if (input.positionals.length === 0 && !input.dryRun) return triggerRunCommand({ ...input, positionals: ["fill"] }, "run");
12974
+ const runId = requirePositional(input, 0, {
12975
+ command: "run.fill",
12976
+ usage: RUN_FILL_USAGE,
12977
+ message: "run ID is required"
12978
+ });
12979
+ const provider = getString(input.values, "provider");
12980
+ await fillRun(runId, {
12981
+ providers: provider ? provider.split(",").map((value) => value.trim()).filter(Boolean) : void 0,
12982
+ dryRun: input.dryRun,
12983
+ wait: getBoolean(input.values, "wait"),
12984
+ format: input.format
12985
+ });
12986
+ }
12987
+ },
12988
+ {
12989
+ path: ["run", "completeness"],
12990
+ usage: "canonry run completeness <run-id> [--format json]",
12991
+ run: async (input) => {
12992
+ if (input.positionals.length === 0) return triggerRunCommand({ ...input, positionals: ["completeness"] }, "run");
12993
+ const runId = requirePositional(input, 0, {
12994
+ command: "run.completeness",
12995
+ usage: "canonry run completeness <run-id> [--format json]",
12996
+ message: "run ID is required"
12997
+ });
12998
+ await showRunCompleteness(runId, input.format);
12999
+ }
13000
+ },
12878
13001
  {
12879
13002
  path: ["run", "cancel"],
12880
13003
  usage: "canonry run cancel <project> [run-id] [--format json]",
@@ -19536,6 +19659,9 @@ var TELEMETRY_ERROR_CODES = /* @__PURE__ */ new Set([
19536
19659
  "AGENT_BUSY",
19537
19660
  "MISSING_DEPENDENCY",
19538
19661
  "RUNTIME_STATE_MISSING",
19662
+ "RUN_FILL_REFUSED",
19663
+ "RUN_FILL_IN_PROGRESS",
19664
+ "RUN_FILL_INCOMPLETE",
19539
19665
  "API_ERROR",
19540
19666
  "CLI_ERROR",
19541
19667
  "CLI_USAGE_ERROR",
@@ -4,7 +4,7 @@ import {
4
4
  import {
5
5
  layoutSiteCrawlGraphInput,
6
6
  persistSiteCrawlGraphLayout
7
- } from "./chunk-JNU6GLAV.js";
7
+ } from "./chunk-IDZQ5H3J.js";
8
8
  import {
9
9
  PACKAGE_VERSION
10
10
  } from "./chunk-AOJU5LKX.js";
@@ -83,7 +83,7 @@ import {
83
83
  siteCrawlPages,
84
84
  siteCrawlSnapshots,
85
85
  trafficSources
86
- } from "./chunk-SMYBGUVV.js";
86
+ } from "./chunk-Q35D2R2P.js";
87
87
  import {
88
88
  RunKinds,
89
89
  SiteCrawlFetchStates,
@@ -104,7 +104,7 @@ import {
104
104
  measurementPlanV2Schema,
105
105
  placementLinkDecision,
106
106
  siteAuditPageFactorSchema
107
- } from "./chunk-MQMJJZ6W.js";
107
+ } from "./chunk-UWJAATGC.js";
108
108
 
109
109
  // src/demo-server.ts
110
110
  import { dirname, join as join2 } from "path";
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { FastifyInstance } from 'fastify';
2
2
  import { DatabaseClient } from '@ainyc/canonry-db';
3
- import { ProviderQuotaPolicy, SchedulableRunKind, EmbedConfigEntry, AgentPluginState, GoogleAdsCampaignMetricsQuery, GoogleAdsRawSnapshotDto, GoogleAdsEffectiveGoalGraphDto, GoogleMarketingProvider, GoogleAdsAccessibleCustomersResponse, GoogleAdsAccessibleCustomerDto, GtmAccountsResponse, GtmContainerListResponse, GtmWorkspaceListResponse, GtmRawSnapshotDto } from '@ainyc/canonry-contracts';
3
+ import { ProviderQuotaPolicy, SchedulableRunKind, AgentProviderId, EmbedConfigEntry, AgentPluginState, GoogleAdsCampaignMetricsQuery, GoogleAdsRawSnapshotDto, GoogleAdsEffectiveGoalGraphDto, GoogleMarketingProvider, GoogleAdsAccessibleCustomersResponse, GoogleAdsAccessibleCustomerDto, GtmAccountsResponse, GtmContainerListResponse, GtmWorkspaceListResponse, GtmRawSnapshotDto } from '@ainyc/canonry-contracts';
4
4
  import { GoogleTokenResponse } from '@ainyc/canonry-integration-google';
5
5
 
6
6
  type GoogleConnectionType = 'gsc' | 'ga4' | 'gbp';
@@ -289,6 +289,33 @@ interface AgentConfigEntry {
289
289
  * Both resolvers live in agent-config.ts.
290
290
  */
291
291
  mode?: 'disabled' | 'prompt-only';
292
+ /**
293
+ * Pin the LLM provider Aero reasons with.
294
+ *
295
+ * Absent (the default) keeps the historical behaviour: the first provider
296
+ * holding a usable key wins, by `autoDetectPriority`. That default is an
297
+ * accident of which ANSWER-ENGINE keys the install happens to hold -- an
298
+ * install that sweeps with Claude silently gets Claude for Aero too, at that
299
+ * provider's agent-tier pricing -- so any deployment that cares which model
300
+ * answers has to say so here rather than rely on detection order.
301
+ *
302
+ * Ranked by `resolveSessionProviderAndModel`: an explicit per-request
303
+ * provider beats this pin, and this pin beats both the persisted session row
304
+ * and auto-detection. Because it outranks the row, a pin survives the
305
+ * conversation-delete path that drops that row entirely. An explicit request
306
+ * lasts one turn: the next turn that names no provider returns to the pin.
307
+ *
308
+ * Removing the pin does not move an existing session back to detection:
309
+ * without a pin a session keeps its stored provider, as it always has, until
310
+ * its conversation is deleted. Starting a new conversation keeps it too.
311
+ */
312
+ provider?: AgentProviderId;
313
+ /**
314
+ * Model id for `provider`. Ignored unless `provider` is set: a model slug is
315
+ * only meaningful against the provider that serves it. Absent uses that
316
+ * provider's agent-tier default.
317
+ */
318
+ model?: string;
292
319
  }
293
320
  interface DashboardConfigEntry {
294
321
  /**
package/dist/index.js CHANGED
@@ -3,14 +3,14 @@ import {
3
3
  createGoogleMarketingCredentialStore,
4
4
  createGoogleMarketingRuntime,
5
5
  createServer
6
- } from "./chunk-UYSTNPTX.js";
6
+ } from "./chunk-TDHRUXN3.js";
7
7
  import {
8
8
  loadConfig
9
- } from "./chunk-JW5DCORY.js";
10
- import "./chunk-JNU6GLAV.js";
9
+ } from "./chunk-IPGBK7XR.js";
10
+ import "./chunk-IDZQ5H3J.js";
11
11
  import "./chunk-AOJU5LKX.js";
12
- import "./chunk-SMYBGUVV.js";
13
- import "./chunk-MQMJJZ6W.js";
12
+ import "./chunk-Q35D2R2P.js";
13
+ import "./chunk-UWJAATGC.js";
14
14
  export {
15
15
  GoogleMarketingRuntimeError,
16
16
  createGoogleMarketingCredentialStore,
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  HISTORY_WINDOW_RUNS,
3
3
  IntelligenceService
4
- } from "./chunk-SMYBGUVV.js";
5
- import "./chunk-MQMJJZ6W.js";
4
+ } from "./chunk-Q35D2R2P.js";
5
+ import "./chunk-UWJAATGC.js";
6
6
  export {
7
7
  HISTORY_WINDOW_RUNS,
8
8
  IntelligenceService
package/dist/mcp.js CHANGED
@@ -1,15 +1,15 @@
1
1
  import {
2
2
  autoSyncSkills
3
- } from "./chunk-NV3X6O5P.js";
3
+ } from "./chunk-6YLNO2T5.js";
4
4
  import {
5
5
  createApiClient,
6
6
  createCanonryMcpServer
7
- } from "./chunk-JW5DCORY.js";
7
+ } from "./chunk-IPGBK7XR.js";
8
8
  import "./chunk-AOJU5LKX.js";
9
9
  import {
10
10
  isReadOnlyKey,
11
11
  updateCheckEnvOptOut
12
- } from "./chunk-MQMJJZ6W.js";
12
+ } from "./chunk-UWJAATGC.js";
13
13
 
14
14
  // src/mcp/cli.ts
15
15
  import { randomUUID } from "crypto";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@canonry/canonry",
3
- "version": "5.11.0",
3
+ "version": "5.13.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
  "keywords": [
@@ -87,8 +87,8 @@
87
87
  "tsup": "^8.5.1",
88
88
  "tsx": "^4.19.0",
89
89
  "@ainyc/canonry-web": "0.0.0",
90
- "@ainyc/canonry-api-routes": "0.0.0",
91
90
  "@ainyc/canonry-api-client": "0.0.0",
91
+ "@ainyc/canonry-api-routes": "0.0.0",
92
92
  "@ainyc/canonry-config": "0.0.0",
93
93
  "@ainyc/canonry-contracts": "0.0.0",
94
94
  "@ainyc/canonry-db": "0.0.0",
@@ -97,21 +97,21 @@
97
97
  "@ainyc/canonry-integration-cloudflare-queue": "0.0.0",
98
98
  "@ainyc/canonry-integration-cloudflare-worker": "0.0.0",
99
99
  "@ainyc/canonry-integration-commoncrawl": "0.0.0",
100
- "@ainyc/canonry-integration-google-ads": "0.0.0",
101
100
  "@ainyc/canonry-integration-google": "0.0.0",
102
- "@ainyc/canonry-integration-google-business-profile": "0.0.0",
101
+ "@ainyc/canonry-integration-google-ads": "0.0.0",
103
102
  "@ainyc/canonry-integration-google-places": "0.0.0",
104
103
  "@ainyc/canonry-integration-google-tag-manager": "0.0.0",
105
104
  "@ainyc/canonry-integration-openai-ads": "0.0.0",
106
105
  "@ainyc/canonry-integration-wordpress": "0.0.0",
107
106
  "@ainyc/canonry-integration-traffic": "0.0.0",
108
- "@ainyc/canonry-provider-claude": "0.0.0",
109
107
  "@ainyc/canonry-intelligence": "0.0.0",
110
108
  "@ainyc/canonry-provider-cdp": "0.0.0",
111
- "@ainyc/canonry-provider-openai": "0.0.0",
109
+ "@ainyc/canonry-integration-google-business-profile": "0.0.0",
110
+ "@ainyc/canonry-provider-gemini": "0.0.0",
112
111
  "@ainyc/canonry-provider-local": "0.0.0",
113
- "@ainyc/canonry-provider-perplexity": "0.0.0",
114
- "@ainyc/canonry-provider-gemini": "0.0.0"
112
+ "@ainyc/canonry-provider-claude": "0.0.0",
113
+ "@ainyc/canonry-provider-openai": "0.0.0",
114
+ "@ainyc/canonry-provider-perplexity": "0.0.0"
115
115
  },
116
116
  "scripts": {
117
117
  "build": "pnpm run build:cli && pnpm run build:web",