@ainyc/canonry 4.180.8 → 4.183.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/README.md +166 -100
- package/assets/agent-workspace/skills/aero/references/orchestration.md +1 -1
- package/assets/agent-workspace/skills/canonry/references/canonry-cli.md +1 -1
- package/assets/assets/{AuditHistoryPanel-qiuqNGvG.js → AuditHistoryPanel-ClwYugEs.js} +1 -1
- package/assets/assets/{BacklinksPage-D-g5f0Xv.js → BacklinksPage-DaEn1w9_.js} +1 -1
- package/assets/assets/{ChartPrimitives-DG35TyhH.js → ChartPrimitives-DLEICrrL.js} +1 -1
- package/assets/assets/{HistoryPage-q8_pCuOs.js → HistoryPage-B4WWIXmx.js} +1 -1
- package/assets/assets/{MeasurementPropertyPage-C_wMjUZe.js → MeasurementPropertyPage-DFvelKfS.js} +1 -1
- package/assets/assets/ProjectPage-D3AuGcau.js +9 -0
- package/assets/assets/{RunRow-D5hatdlY.js → RunRow-0HuBq5KN.js} +1 -1
- package/assets/assets/{RunsPage-Bj2snMM3.js → RunsPage-DhdjoIdK.js} +1 -1
- package/assets/assets/{SettingsPage-Cf5YgyJv.js → SettingsPage-XzHCmYz4.js} +1 -1
- package/assets/assets/{SiteHealthSection-D8RLvMAE.js → SiteHealthSection-BODUx0bX.js} +3 -3
- package/assets/assets/{TrafficPage-CotJ14le.js → TrafficPage-2AKICLH_.js} +1 -1
- package/assets/assets/{TrafficSourceDetailPage-BcxYX-uq.js → TrafficSourceDetailPage-CYVG7qZ0.js} +1 -1
- package/assets/assets/extract-error-message-CtGLEBMO.js +1 -0
- package/assets/assets/index-B64WXjg8.js +86 -0
- package/assets/assets/{index-DXCQf5s1.css → index-DwdK2e4e.css} +1 -1
- package/assets/assets/{react-sigma_core.esm.min-DxZINEmi.js → react-sigma_core.esm.min-D5Honb13.js} +1 -1
- package/assets/assets/{vendor-lucide-nYKv-BB7.js → vendor-lucide-XjCNFK0x.js} +1 -1
- package/assets/assets/{vendor-markdown-Bn7fRwrx.js → vendor-markdown-9tTeP8v7.js} +1 -1
- package/assets/assets/{vendor-radix-4UOaVWza.js → vendor-radix-BpmvLvpp.js} +1 -1
- package/assets/assets/{vendor-recharts-D8rt5lKn.js → vendor-recharts-FA0uySU7.js} +1 -1
- package/assets/assets/{vendor-tanstack-Dock0eH1.js → vendor-tanstack-CYBjbqVr.js} +1 -1
- package/assets/index.html +7 -7
- package/dist/{chunk-ZJ2VGTYU.js → chunk-ISONU3FA.js} +4276 -3389
- package/dist/{chunk-GFVZOVG3.js → chunk-OF3PKBW4.js} +72 -6
- package/dist/{chunk-G7M2KM7Q.js → chunk-RQSSKN5F.js} +2 -2
- package/dist/{chunk-IM4HFNGF.js → chunk-VFQPW2VX.js} +43 -3
- package/dist/{chunk-GN2G7VFK.js → chunk-Z2HTLTQV.js} +162 -4
- package/dist/cli.js +141 -8
- package/dist/index.js +4 -4
- package/dist/{intelligence-service-IURLYRB3.js → intelligence-service-4XQBUFBU.js} +2 -2
- package/dist/mcp.js +3 -3
- package/package.json +8 -8
- package/assets/assets/ProjectPage-33THfDtC.js +0 -9
- package/assets/assets/extract-error-message-Bxt42scd.js +0 -1
- package/assets/assets/index-BlILyZJ5.js +0 -86
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
loadConfig,
|
|
12
12
|
loadConfigRaw,
|
|
13
13
|
saveConfigPatch
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-VFQPW2VX.js";
|
|
15
15
|
import {
|
|
16
16
|
CC_CACHE_DIR,
|
|
17
17
|
DUCKDB_SPEC,
|
|
@@ -157,7 +157,7 @@ import {
|
|
|
157
157
|
siteCrawlSnapshots,
|
|
158
158
|
toAlertView,
|
|
159
159
|
usageCounters
|
|
160
|
-
} from "./chunk-
|
|
160
|
+
} from "./chunk-ISONU3FA.js";
|
|
161
161
|
import {
|
|
162
162
|
AGENT_MEMORY_VALUE_MAX_BYTES,
|
|
163
163
|
AGENT_PROVIDER_IDS,
|
|
@@ -296,7 +296,7 @@ import {
|
|
|
296
296
|
validationError,
|
|
297
297
|
winnabilityClassLabel,
|
|
298
298
|
withRetry
|
|
299
|
-
} from "./chunk-
|
|
299
|
+
} from "./chunk-Z2HTLTQV.js";
|
|
300
300
|
|
|
301
301
|
// src/telemetry.ts
|
|
302
302
|
import crypto from "crypto";
|
|
@@ -11304,15 +11304,17 @@ async function executeSiteAudit(db, runId, projectId, opts = {}) {
|
|
|
11304
11304
|
indexabilityVersion: crawlSummary.indexabilityRulesetVersion,
|
|
11305
11305
|
linkScoreVersion: crawlSummary.linkScoreAlgorithmVersion,
|
|
11306
11306
|
effectiveOptions: {
|
|
11307
|
+
// Null, never absent: a reader must be able to tell "the operator set
|
|
11308
|
+
// no edge budget and the engine derived one" from a missing field.
|
|
11307
11309
|
mode: "summary",
|
|
11308
11310
|
sitemapUrl: opts.sitemapUrl ?? null,
|
|
11309
11311
|
maxPages,
|
|
11310
|
-
maxEdges,
|
|
11312
|
+
maxEdges: maxEdges ?? null,
|
|
11311
11313
|
maxDepth: opts.maxDepth ?? null,
|
|
11312
11314
|
checkDeadLinks: opts.checkDeadLinks ?? false
|
|
11313
11315
|
},
|
|
11314
11316
|
pageBudget: maxPages,
|
|
11315
|
-
edgeBudget: maxEdges,
|
|
11317
|
+
edgeBudget: maxEdges ?? null,
|
|
11316
11318
|
maxDepth: opts.maxDepth ?? null,
|
|
11317
11319
|
checkDeadLinks: opts.checkDeadLinks ?? false,
|
|
11318
11320
|
complete: crawlSummary.complete,
|
|
@@ -11867,7 +11869,7 @@ function readStoredGroundingSources(rawResponse) {
|
|
|
11867
11869
|
return result;
|
|
11868
11870
|
}
|
|
11869
11871
|
async function backfillInsightsCommand(project, opts) {
|
|
11870
|
-
const { IntelligenceService: IntelligenceService2 } = await import("./intelligence-service-
|
|
11872
|
+
const { IntelligenceService: IntelligenceService2 } = await import("./intelligence-service-4XQBUFBU.js");
|
|
11871
11873
|
const config = loadConfig();
|
|
11872
11874
|
const db = createClient(config.database);
|
|
11873
11875
|
migrate(db);
|
|
@@ -13803,6 +13805,68 @@ function trimRowsToFit(rows, render) {
|
|
|
13803
13805
|
}
|
|
13804
13806
|
return kept;
|
|
13805
13807
|
}
|
|
13808
|
+
function nestedArrayCandidates(root) {
|
|
13809
|
+
const candidates = [];
|
|
13810
|
+
const visit = (object) => {
|
|
13811
|
+
let containsRecordCollection = false;
|
|
13812
|
+
for (const [key, value] of Object.entries(object)) {
|
|
13813
|
+
if (Array.isArray(value)) {
|
|
13814
|
+
let hasNestedRecords = false;
|
|
13815
|
+
let hasRecordRows = false;
|
|
13816
|
+
for (const row of value) {
|
|
13817
|
+
if (row && typeof row === "object" && !Array.isArray(row)) {
|
|
13818
|
+
hasRecordRows = true;
|
|
13819
|
+
hasNestedRecords = visit(row) || hasNestedRecords;
|
|
13820
|
+
}
|
|
13821
|
+
}
|
|
13822
|
+
if (value.length > 0 && !hasNestedRecords) {
|
|
13823
|
+
candidates.push({ owner: object, key, rows: value, size: serializeResult(value).length, hasRecordRows });
|
|
13824
|
+
}
|
|
13825
|
+
containsRecordCollection = hasRecordRows || hasNestedRecords || containsRecordCollection;
|
|
13826
|
+
} else if (value && typeof value === "object") {
|
|
13827
|
+
containsRecordCollection = visit(value) || containsRecordCollection;
|
|
13828
|
+
}
|
|
13829
|
+
}
|
|
13830
|
+
return containsRecordCollection;
|
|
13831
|
+
};
|
|
13832
|
+
visit(root);
|
|
13833
|
+
return candidates.sort(
|
|
13834
|
+
(left, right) => Number(right.hasRecordRows) - Number(left.hasRecordRows) || right.size - left.size
|
|
13835
|
+
);
|
|
13836
|
+
}
|
|
13837
|
+
function trimNestedArrays(full) {
|
|
13838
|
+
const parsed = JSON.parse(full);
|
|
13839
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return void 0;
|
|
13840
|
+
const copy = parsed;
|
|
13841
|
+
copy.__truncated = true;
|
|
13842
|
+
let out = serializeResult(copy);
|
|
13843
|
+
while (out.length > MAX_TOOL_RESULT_CHARS) {
|
|
13844
|
+
const candidate = nestedArrayCandidates(copy).at(0);
|
|
13845
|
+
if (!candidate) return void 0;
|
|
13846
|
+
const { owner, key, rows } = candidate;
|
|
13847
|
+
const previous = owner.__omittedRowsByField;
|
|
13848
|
+
const omitted = previous && typeof previous === "object" && !Array.isArray(previous) ? { ...previous } : {};
|
|
13849
|
+
const priorCount = typeof omitted[key] === "number" ? omitted[key] : 0;
|
|
13850
|
+
owner.__truncated = true;
|
|
13851
|
+
owner.__omittedRowsByField = omitted;
|
|
13852
|
+
const keep = (count2) => {
|
|
13853
|
+
owner[key] = rows.slice(0, count2);
|
|
13854
|
+
omitted[key] = priorCount + rows.length - count2;
|
|
13855
|
+
return serializeResult(copy);
|
|
13856
|
+
};
|
|
13857
|
+
out = keep(0);
|
|
13858
|
+
if (out.length > MAX_TOOL_RESULT_CHARS) continue;
|
|
13859
|
+
let low = 0;
|
|
13860
|
+
let high = rows.length - 1;
|
|
13861
|
+
while (low < high) {
|
|
13862
|
+
const middle = Math.ceil((low + high) / 2);
|
|
13863
|
+
if (keep(middle).length <= MAX_TOOL_RESULT_CHARS) low = middle;
|
|
13864
|
+
else high = middle - 1;
|
|
13865
|
+
}
|
|
13866
|
+
out = keep(low);
|
|
13867
|
+
}
|
|
13868
|
+
return out;
|
|
13869
|
+
}
|
|
13806
13870
|
function truncateToolResult(details) {
|
|
13807
13871
|
const full = serializeResult(details);
|
|
13808
13872
|
if (full.length <= MAX_TOOL_RESULT_CHARS) return full;
|
|
@@ -13830,6 +13894,8 @@ function truncateToolResult(details) {
|
|
|
13830
13894
|
});
|
|
13831
13895
|
if (out.length <= MAX_TOOL_RESULT_CHARS) return out;
|
|
13832
13896
|
}
|
|
13897
|
+
const nested = trimNestedArrays(full);
|
|
13898
|
+
if (nested !== void 0) return nested;
|
|
13833
13899
|
}
|
|
13834
13900
|
return full.slice(0, MAX_TOOL_RESULT_CHARS) + "\n" + TRUNCATION_NOTE;
|
|
13835
13901
|
}
|
|
@@ -5,11 +5,11 @@ import {
|
|
|
5
5
|
installSkills,
|
|
6
6
|
loadConfigRaw,
|
|
7
7
|
saveConfigPatch
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-VFQPW2VX.js";
|
|
9
9
|
import {
|
|
10
10
|
SKILL_MANIFEST_FILENAME,
|
|
11
11
|
SkillsClients
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-Z2HTLTQV.js";
|
|
13
13
|
|
|
14
14
|
// src/skills-autosync.ts
|
|
15
15
|
import fs from "fs";
|
|
@@ -25,6 +25,7 @@ import {
|
|
|
25
25
|
classifySkillFile,
|
|
26
26
|
coerceSkillManifest,
|
|
27
27
|
competitorBatchRequestSchema,
|
|
28
|
+
competitorLandscapeQuerySchema,
|
|
28
29
|
describeError,
|
|
29
30
|
discoveryBucketSchema,
|
|
30
31
|
discoveryCompetitorTypeSchema,
|
|
@@ -92,7 +93,7 @@ import {
|
|
|
92
93
|
trafficConnectWordpressRequestSchema,
|
|
93
94
|
trafficEventKindSchema,
|
|
94
95
|
trafficSeriesGranularitySchema
|
|
95
|
-
} from "./chunk-
|
|
96
|
+
} from "./chunk-Z2HTLTQV.js";
|
|
96
97
|
|
|
97
98
|
// src/config.ts
|
|
98
99
|
import fs from "fs";
|
|
@@ -2398,6 +2399,18 @@ var postApiV1ProjectsByNameCompetitors = (options) => {
|
|
|
2398
2399
|
}
|
|
2399
2400
|
});
|
|
2400
2401
|
};
|
|
2402
|
+
var getApiV1ProjectsByNameAnalyticsCompetitors = (options) => {
|
|
2403
|
+
return (options.client ?? client).get({
|
|
2404
|
+
security: [
|
|
2405
|
+
{
|
|
2406
|
+
scheme: "bearer",
|
|
2407
|
+
type: "http"
|
|
2408
|
+
}
|
|
2409
|
+
],
|
|
2410
|
+
url: "/api/v1/projects/{name}/analytics/competitors",
|
|
2411
|
+
...options
|
|
2412
|
+
});
|
|
2413
|
+
};
|
|
2401
2414
|
var getApiV1ProjectsByNameRuns = (options) => {
|
|
2402
2415
|
return (options.client ?? client).get({
|
|
2403
2416
|
security: [
|
|
@@ -6583,6 +6596,16 @@ var ApiClient = class {
|
|
|
6583
6596
|
})
|
|
6584
6597
|
);
|
|
6585
6598
|
}
|
|
6599
|
+
/** Stored competitor SOV, optionally grouped or filtered by requested model; never starts provider work. */
|
|
6600
|
+
async getCompetitorLandscape(project, opts = {}) {
|
|
6601
|
+
return this.invoke(
|
|
6602
|
+
() => getApiV1ProjectsByNameAnalyticsCompetitors({
|
|
6603
|
+
client: this.heyClient,
|
|
6604
|
+
path: { name: project },
|
|
6605
|
+
query: opts
|
|
6606
|
+
})
|
|
6607
|
+
);
|
|
6608
|
+
}
|
|
6586
6609
|
async getAnalyticsGaps(project, window) {
|
|
6587
6610
|
return this.invoke(
|
|
6588
6611
|
() => getApiV1ProjectsByNameAnalyticsGaps({
|
|
@@ -9088,6 +9111,9 @@ var competitorsInputSchema = z3.object({
|
|
|
9088
9111
|
project: projectNameSchema,
|
|
9089
9112
|
request: competitorBatchRequestSchema
|
|
9090
9113
|
});
|
|
9114
|
+
var competitorLandscapeInputSchema = competitorLandscapeQuerySchema.safeExtend({
|
|
9115
|
+
project: projectNameSchema
|
|
9116
|
+
}).strict();
|
|
9091
9117
|
var projectUpsertInputSchema = z3.object({
|
|
9092
9118
|
project: projectNameSchema,
|
|
9093
9119
|
request: projectUpsertRequestSchema
|
|
@@ -9361,7 +9387,7 @@ var technicalAeoRunInputSchema = z3.object({
|
|
|
9361
9387
|
sitemapUrl: z3.string().url().optional().describe("Override the sitemap URL. Defaults to https://<canonicalDomain>/sitemap.xml."),
|
|
9362
9388
|
limit: z3.number().int().positive().max(2e3).optional().describe("Deprecated compatibility alias for maxPages."),
|
|
9363
9389
|
maxPages: z3.number().int().positive().max(5e4).optional().describe("Maximum pages crawled and audited. Defaults to 1,000; hard maximum 50,000."),
|
|
9364
|
-
maxEdges: z3.number().int().positive().max(1e6).optional().describe("Maximum link observations retained for this crawl.
|
|
9390
|
+
maxEdges: z3.number().int().positive().max(1e6).optional().describe("Maximum link observations retained for this crawl. When omitted the crawl engine derives the budget from the page count; hard maximum 1,000,000."),
|
|
9365
9391
|
maxDepth: z3.number().int().min(0).max(100).optional().describe("Maximum internal-link depth from the root page."),
|
|
9366
9392
|
checkDeadLinks: z3.boolean().optional().describe("Opt in to internal dead-link checks. Omitted and false both disable checks.")
|
|
9367
9393
|
});
|
|
@@ -9480,6 +9506,20 @@ var canonryMcpTools = [
|
|
|
9480
9506
|
openApiOperations: ["GET /api/v1/projects/{name}/analytics/sources"],
|
|
9481
9507
|
handler: (client2, input) => client2.getAnalyticsSources(input.project, { window: input.window, limit: input.limit })
|
|
9482
9508
|
}),
|
|
9509
|
+
defineTool({
|
|
9510
|
+
name: "canonry_competitor_landscape",
|
|
9511
|
+
title: "Get historical competitor landscape",
|
|
9512
|
+
description: "Returns pinned competitors first, then observed direct competitors and other cited sources from stored answer/source evidence only. Mention share is percentage points (0..100) from answer text; citations are independent. Share of voice needs ONE query class: `queryClass=all`, and omitting it, pool branded and non-brand, so every `shareOfVoice` comes back null and only the counts are published. Pass `queryClass=non-brand` (or `branded`) for a ratio, exactly as visibility-stats does. A project with no brand name or alias cannot be split by class, so a class-scoped read on one is refused rather than answered empty. Optional groupBy: model adds provider/requested-model groups with separate served-model evidence and sample counts. Optional model filters one exact requested model ID and requires provider. Unknown historical models remain explicit. Groups are not a matched-query or equal-weight comparison. Advanced reads support one market group or explicit scope: all-markets. No provider, discovery, or classifier work runs. Ranked lists are capped at 100 observed/other-source rows per group; pins remain complete. Model groups are capped at 50 and disclose truncation.",
|
|
9513
|
+
access: "read",
|
|
9514
|
+
tier: "monitoring",
|
|
9515
|
+
inputSchema: competitorLandscapeInputSchema,
|
|
9516
|
+
annotations: readAnnotations(),
|
|
9517
|
+
openApiOperations: ["GET /api/v1/projects/{name}/analytics/competitors"],
|
|
9518
|
+
handler: (client2, input) => {
|
|
9519
|
+
const { project, ...query } = input;
|
|
9520
|
+
return client2.getCompetitorLandscape(project, query);
|
|
9521
|
+
}
|
|
9522
|
+
}),
|
|
9483
9523
|
defineTool({
|
|
9484
9524
|
name: "canonry_search",
|
|
9485
9525
|
title: "Search project (composite)",
|
|
@@ -11405,7 +11445,7 @@ var canonryMcpTools = [
|
|
|
11405
11445
|
defineTool({
|
|
11406
11446
|
name: "canonry_technical_aeo_run",
|
|
11407
11447
|
title: "Run Technical AEO site audit",
|
|
11408
|
-
description: "Start a site-audit run. The run discovers root, sitemap, and linked pages.
|
|
11448
|
+
description: "Start a site-audit run. The run discovers root, sitemap, and linked pages. It defaults to 1,000 pages, and the engine derives the link-observation budget from that page count with a 100,000 floor, so raising maxPages raises it too. An explicit maxEdges is a ceiling that replaces the derivation and can sit below it. It returns {runId, status} and continues in the background. If an active run has identical effective options, this tool returns it; different options are refused. Poll canonry_run_get, then read the crawl and score tools.",
|
|
11409
11449
|
access: "write",
|
|
11410
11450
|
tier: "monitoring",
|
|
11411
11451
|
inputSchema: technicalAeoRunInputSchema,
|
|
@@ -6723,6 +6723,22 @@ var measurementDraftUpsertCompetitorRequestSchema = z15.object({
|
|
|
6723
6723
|
groupKey: measurementV2StableKeySchema,
|
|
6724
6724
|
competitor: measurementDraftCompetitorSchema
|
|
6725
6725
|
}).strict();
|
|
6726
|
+
var measurementDraftPinCompetitorRequestSchema = z15.object({
|
|
6727
|
+
expectedActiveRevision: measurementDraftRevisionSchema,
|
|
6728
|
+
groupKey: measurementV2StableKeySchema,
|
|
6729
|
+
domain: z15.string().trim().min(1).refine((value) => hostOf(value) !== null, "A competitor domain must be a valid hostname"),
|
|
6730
|
+
label: z15.string().trim().min(1).optional(),
|
|
6731
|
+
aliases: z15.array(z15.string().trim().min(1)).optional()
|
|
6732
|
+
}).strict();
|
|
6733
|
+
var measurementDraftPinCompetitorResponseSchema = measurementDraftMutationResponseSchema.extend({
|
|
6734
|
+
groupKey: measurementV2StableKeySchema,
|
|
6735
|
+
competitor: measurementDraftCompetitorSchema,
|
|
6736
|
+
draftCreated: z15.boolean(),
|
|
6737
|
+
published: z15.object({
|
|
6738
|
+
revision: measurementDraftRevisionSchema,
|
|
6739
|
+
competitorsChanged: z15.literal(false)
|
|
6740
|
+
}).strict()
|
|
6741
|
+
}).strict();
|
|
6726
6742
|
var measurementDraftRemoveCompetitorRequestSchema = z15.object({
|
|
6727
6743
|
groupKey: measurementV2StableKeySchema,
|
|
6728
6744
|
competitorKey: measurementV2StableKeySchema
|
|
@@ -10627,7 +10643,6 @@ var siteCrawlDeadLinksResponseSchema = z30.discriminatedUnion("state", [
|
|
|
10627
10643
|
]);
|
|
10628
10644
|
var SITE_AUDIT_DEFAULT_PAGE_LIMIT = 1e3;
|
|
10629
10645
|
var SITE_AUDIT_MAX_PAGE_LIMIT = 5e4;
|
|
10630
|
-
var SITE_AUDIT_DEFAULT_EDGE_LIMIT = 1e5;
|
|
10631
10646
|
var SITE_AUDIT_MAX_EDGE_LIMIT = 1e6;
|
|
10632
10647
|
var siteAuditRunRequestSchema = z30.object({
|
|
10633
10648
|
/** @deprecated Prefer the configured project sitemap; retained for compatibility. */
|
|
@@ -10636,7 +10651,7 @@ var siteAuditRunRequestSchema = z30.object({
|
|
|
10636
10651
|
limit: z30.number().int().positive().max(2e3).optional(),
|
|
10637
10652
|
/** Crawl page budget. When omitted, Canonry crawls up to 1,000 pages. */
|
|
10638
10653
|
maxPages: z30.number().int().positive().max(5e4).optional(),
|
|
10639
|
-
/** Internal-link observation budget. When omitted,
|
|
10654
|
+
/** Internal-link observation budget. When omitted, the crawl engine derives it from the page count. */
|
|
10640
10655
|
maxEdges: z30.number().int().positive().max(1e6).optional(),
|
|
10641
10656
|
/** Maximum crawl depth from the root. */
|
|
10642
10657
|
maxDepth: z30.number().int().min(0).max(100).optional(),
|
|
@@ -10645,10 +10660,10 @@ var siteAuditRunRequestSchema = z30.object({
|
|
|
10645
10660
|
});
|
|
10646
10661
|
function normalizeSiteAuditRunRequest(request) {
|
|
10647
10662
|
return {
|
|
10648
|
-
schemaVersion:
|
|
10663
|
+
schemaVersion: 2,
|
|
10649
10664
|
sitemapUrl: request.sitemapUrl ? new URL(request.sitemapUrl).toString() : null,
|
|
10650
10665
|
maxPages: request.maxPages ?? request.limit ?? SITE_AUDIT_DEFAULT_PAGE_LIMIT,
|
|
10651
|
-
maxEdges: request.maxEdges ??
|
|
10666
|
+
maxEdges: request.maxEdges ?? null,
|
|
10652
10667
|
maxDepth: request.maxDepth ?? null,
|
|
10653
10668
|
checkDeadLinks: request.checkDeadLinks === true
|
|
10654
10669
|
};
|
|
@@ -11835,6 +11850,143 @@ var sourceBreakdownDtoSchema = z35.object({
|
|
|
11835
11850
|
/** Applied ranked-list limit; null when the full list is returned. */
|
|
11836
11851
|
limit: z35.number().int().nullable()
|
|
11837
11852
|
});
|
|
11853
|
+
var competitorLandscapeSurfaceClassSchema = z35.enum([
|
|
11854
|
+
"own",
|
|
11855
|
+
"direct-competitor",
|
|
11856
|
+
"ota-aggregator",
|
|
11857
|
+
"editorial-media",
|
|
11858
|
+
"other",
|
|
11859
|
+
"unknown"
|
|
11860
|
+
]);
|
|
11861
|
+
var competitorLandscapeScopeSchema = z35.discriminatedUnion("kind", [
|
|
11862
|
+
z35.object({ kind: z35.literal("project") }).strict(),
|
|
11863
|
+
z35.object({ kind: z35.literal("group"), groupKey: z35.string().trim().min(1) }).strict(),
|
|
11864
|
+
z35.object({ kind: z35.literal("all-markets") }).strict()
|
|
11865
|
+
]);
|
|
11866
|
+
var competitorLandscapeQueryClassSchema = z35.enum(["all", "branded", "non-brand"]);
|
|
11867
|
+
var competitorLandscapeModeSchema = z35.enum(["project", "all-markets"]);
|
|
11868
|
+
var competitorLandscapeQuerySchema = z35.object({
|
|
11869
|
+
window: metricsWindowSchema.optional(),
|
|
11870
|
+
groupKey: z35.string().trim().min(1).optional(),
|
|
11871
|
+
scope: competitorLandscapeModeSchema.optional(),
|
|
11872
|
+
provider: z35.string().trim().min(1).optional(),
|
|
11873
|
+
/** Exact requested model ID; provider is required to disambiguate model names. */
|
|
11874
|
+
model: modelIdSchema.optional(),
|
|
11875
|
+
/** Opt-in agent comparison; the default landscape remains pooled. */
|
|
11876
|
+
groupBy: z35.literal("model").optional(),
|
|
11877
|
+
queryClass: competitorLandscapeQueryClassSchema.optional(),
|
|
11878
|
+
location: z35.string().trim().min(1).optional(),
|
|
11879
|
+
runId: z35.string().trim().min(1).optional()
|
|
11880
|
+
}).strict().superRefine((value, context) => {
|
|
11881
|
+
if (value.scope === "all-markets" && value.groupKey !== void 0) {
|
|
11882
|
+
context.addIssue({
|
|
11883
|
+
code: "custom",
|
|
11884
|
+
path: ["groupKey"],
|
|
11885
|
+
message: "groupKey cannot be combined with scope=all-markets"
|
|
11886
|
+
});
|
|
11887
|
+
}
|
|
11888
|
+
if (value.model !== void 0 && value.provider === void 0) {
|
|
11889
|
+
context.addIssue({
|
|
11890
|
+
code: "custom",
|
|
11891
|
+
path: ["provider"],
|
|
11892
|
+
message: "provider is required when filtering by model"
|
|
11893
|
+
});
|
|
11894
|
+
}
|
|
11895
|
+
});
|
|
11896
|
+
var competitorLandscapeRowSchema = z35.object({
|
|
11897
|
+
domain: z35.string().trim().min(1),
|
|
11898
|
+
label: z35.string().trim().min(1),
|
|
11899
|
+
surfaceClass: competitorLandscapeSurfaceClassSchema,
|
|
11900
|
+
pinned: z35.boolean(),
|
|
11901
|
+
/** One answer-text match at most per result. */
|
|
11902
|
+
mentionCount: z35.number().int().nonnegative(),
|
|
11903
|
+
/**
|
|
11904
|
+
* Percentage points (0..100). Null outside the competitive denominator, and
|
|
11905
|
+
* null for any selection that pools query classes: a brand wins its own
|
|
11906
|
+
* branded queries by definition, so a pooled ratio flatters the project and
|
|
11907
|
+
* buries every competitor. Counts stay populated either way.
|
|
11908
|
+
*/
|
|
11909
|
+
shareOfVoice: z35.number().min(0).max(100).nullable(),
|
|
11910
|
+
/** One source-list credit at most per result. Independent of mentions. */
|
|
11911
|
+
citationCount: z35.number().int().nonnegative(),
|
|
11912
|
+
/** Answer-text result count behind the mention field. */
|
|
11913
|
+
answeredResults: z35.number().int().nonnegative(),
|
|
11914
|
+
firstSeenAt: z35.string().datetime().nullable(),
|
|
11915
|
+
lastSeenAt: z35.string().datetime().nullable(),
|
|
11916
|
+
sampleUrls: z35.array(z35.string().url()).max(3)
|
|
11917
|
+
}).strict();
|
|
11918
|
+
var competitorLandscapeEvidenceSchema = z35.object({
|
|
11919
|
+
answeredResults: z35.number().int().nonnegative(),
|
|
11920
|
+
sourceResults: z35.number().int().nonnegative(),
|
|
11921
|
+
missingAnswerTextResults: z35.number().int().nonnegative(),
|
|
11922
|
+
/** Project plus direct-competitor named credits behind SOV. */
|
|
11923
|
+
mentionCredits: z35.number().int().nonnegative(),
|
|
11924
|
+
/** Citation captures that cannot prove a complete source list; never inferred as misses. */
|
|
11925
|
+
incompleteSourceResults: z35.number().int().nonnegative(),
|
|
11926
|
+
/** Stored probe snapshots intentionally omitted from every landscape metric. */
|
|
11927
|
+
excludedProbeResults: z35.number().int().nonnegative(),
|
|
11928
|
+
/** Stored snapshots from queued/running/failed/cancelled runs omitted from every metric. */
|
|
11929
|
+
excludedNonCompletedResults: z35.number().int().nonnegative()
|
|
11930
|
+
}).strict();
|
|
11931
|
+
var COMPETITOR_LANDSCAPE_MODEL_GROUP_LIMIT = 50;
|
|
11932
|
+
var competitorLandscapeModelGroupSchema = z35.object({
|
|
11933
|
+
provider: z35.string().trim().min(1),
|
|
11934
|
+
/** Null preserves historical observations with unknown requested model identity. */
|
|
11935
|
+
model: modelIdSchema.nullable(),
|
|
11936
|
+
/** Raw upstream-reported identity; never filled from the requested model or current settings. */
|
|
11937
|
+
servedModels: modelEvidenceStateSchema,
|
|
11938
|
+
snapshotCount: z35.number().int().positive(),
|
|
11939
|
+
project: competitorLandscapeRowSchema,
|
|
11940
|
+
pinned: z35.array(competitorLandscapeRowSchema),
|
|
11941
|
+
observed: z35.array(competitorLandscapeRowSchema),
|
|
11942
|
+
otherSources: z35.array(competitorLandscapeRowSchema),
|
|
11943
|
+
evidence: competitorLandscapeEvidenceSchema,
|
|
11944
|
+
/** Per-group ranked-row truncation; all pins and full-population denominators remain included. */
|
|
11945
|
+
truncated: z35.boolean()
|
|
11946
|
+
}).strict();
|
|
11947
|
+
var competitorLandscapeModelComparisonSchema = z35.object({
|
|
11948
|
+
basis: z35.literal("requested-model"),
|
|
11949
|
+
groups: z35.array(competitorLandscapeModelGroupSchema).max(COMPETITOR_LANDSCAPE_MODEL_GROUP_LIMIT),
|
|
11950
|
+
totalGroups: z35.number().int().nonnegative(),
|
|
11951
|
+
/** Groups sort by provider and requested model. Use provider/model filters to narrow a truncated result. */
|
|
11952
|
+
truncated: z35.boolean()
|
|
11953
|
+
}).strict();
|
|
11954
|
+
var competitorLandscapeResponseSchema = z35.object({
|
|
11955
|
+
window: metricsWindowSchema,
|
|
11956
|
+
scope: competitorLandscapeScopeSchema,
|
|
11957
|
+
project: competitorLandscapeRowSchema,
|
|
11958
|
+
/** Explicit/custom competitors, preserved even with zero observations. */
|
|
11959
|
+
pinned: z35.array(competitorLandscapeRowSchema),
|
|
11960
|
+
/** Stored-discovery direct competitors, ordered by historical mention share. */
|
|
11961
|
+
observed: z35.array(competitorLandscapeRowSchema),
|
|
11962
|
+
/** Aggregators, editorial, unknown, and other cited sources; never share-of-voice competitors. */
|
|
11963
|
+
otherSources: z35.array(competitorLandscapeRowSchema),
|
|
11964
|
+
evidence: competitorLandscapeEvidenceSchema,
|
|
11965
|
+
/** Present only when groupBy=model; pooled fields remain available and unchanged. */
|
|
11966
|
+
modelComparison: competitorLandscapeModelComparisonSchema.optional(),
|
|
11967
|
+
/** Present only for Advanced market reads; active metrics stay frozen while draft pins remain pending publish. */
|
|
11968
|
+
marketState: z35.object({
|
|
11969
|
+
activeRevision: z35.number().int().positive(),
|
|
11970
|
+
draft: z35.object({
|
|
11971
|
+
etag: z35.string().trim().min(1),
|
|
11972
|
+
/** Draft-only market identities included in `pinned` for this response. */
|
|
11973
|
+
pendingCompetitorDomains: z35.array(z35.string().trim().min(1))
|
|
11974
|
+
}).strict().nullable()
|
|
11975
|
+
}).strict().nullable(),
|
|
11976
|
+
/** Echoes all applied filters so a client never mistakes a scoped reading for a project-wide one. */
|
|
11977
|
+
filters: z35.object({
|
|
11978
|
+
scope: competitorLandscapeModeSchema,
|
|
11979
|
+
groupKey: z35.string().nullable(),
|
|
11980
|
+
provider: z35.string().nullable(),
|
|
11981
|
+
model: modelIdSchema.optional(),
|
|
11982
|
+
groupBy: z35.literal("model").optional(),
|
|
11983
|
+
queryClass: competitorLandscapeQueryClassSchema,
|
|
11984
|
+
location: z35.string().nullable(),
|
|
11985
|
+
runId: z35.string().nullable()
|
|
11986
|
+
}).strict(),
|
|
11987
|
+
/** True when ranked observed/source lists exceed the server cap; pinned rows are never dropped. */
|
|
11988
|
+
truncated: z35.boolean()
|
|
11989
|
+
}).strict();
|
|
11838
11990
|
function parseWindow(value) {
|
|
11839
11991
|
if (value === void 0 || value === "") return "all";
|
|
11840
11992
|
const parsed = metricsWindowSchema.safeParse(value);
|
|
@@ -16589,6 +16741,7 @@ export {
|
|
|
16589
16741
|
measurementChangesResponseSchema,
|
|
16590
16742
|
measurementDataQualityQuerySchema,
|
|
16591
16743
|
measurementDataQualityResponseSchema,
|
|
16744
|
+
measurementDraftCompetitorSchema,
|
|
16592
16745
|
measurementDraftAuthoringSchema,
|
|
16593
16746
|
MEASUREMENT_DRAFT_MAX_ASSIGNMENTS_PER_ACTION,
|
|
16594
16747
|
MEASUREMENT_DRAFT_MAX_GROUPS,
|
|
@@ -16621,6 +16774,8 @@ export {
|
|
|
16621
16774
|
measurementDraftUpsertGroupRequestSchema,
|
|
16622
16775
|
measurementDraftRemoveGroupRequestSchema,
|
|
16623
16776
|
measurementDraftUpsertCompetitorRequestSchema,
|
|
16777
|
+
measurementDraftPinCompetitorRequestSchema,
|
|
16778
|
+
measurementDraftPinCompetitorResponseSchema,
|
|
16624
16779
|
measurementDraftRemoveCompetitorRequestSchema,
|
|
16625
16780
|
measurementDraftCompilePreviewResponseSchema,
|
|
16626
16781
|
measurementDraftDiffPreviewResponseSchema,
|
|
@@ -16920,6 +17075,9 @@ export {
|
|
|
16920
17075
|
modelIdsEquivalent,
|
|
16921
17076
|
brandMetricsDtoSchema,
|
|
16922
17077
|
sourceBreakdownDtoSchema,
|
|
17078
|
+
competitorLandscapeQuerySchema,
|
|
17079
|
+
COMPETITOR_LANDSCAPE_MODEL_GROUP_LIMIT,
|
|
17080
|
+
competitorLandscapeResponseSchema,
|
|
16923
17081
|
parseWindow,
|
|
16924
17082
|
windowCutoff,
|
|
16925
17083
|
resolveDateRange,
|
package/dist/cli.js
CHANGED
|
@@ -28,11 +28,11 @@ import {
|
|
|
28
28
|
trackCliCommandFinished,
|
|
29
29
|
trackEvent,
|
|
30
30
|
waitForServerRuntimeStartup
|
|
31
|
-
} from "./chunk-
|
|
31
|
+
} from "./chunk-OF3PKBW4.js";
|
|
32
32
|
import {
|
|
33
33
|
autoSyncSkills,
|
|
34
34
|
formatAutoSyncNotice
|
|
35
|
-
} from "./chunk-
|
|
35
|
+
} from "./chunk-RQSSKN5F.js";
|
|
36
36
|
import {
|
|
37
37
|
CliError,
|
|
38
38
|
EXIT_SYSTEM_ERROR,
|
|
@@ -57,7 +57,7 @@ import {
|
|
|
57
57
|
saveConfigPatch,
|
|
58
58
|
systemError,
|
|
59
59
|
usageError
|
|
60
|
-
} from "./chunk-
|
|
60
|
+
} from "./chunk-VFQPW2VX.js";
|
|
61
61
|
import {
|
|
62
62
|
CLOUDFLARE_WORKER_BINDINGS,
|
|
63
63
|
CLOUDFLARE_WORKER_GENERATED_MARKER,
|
|
@@ -71,7 +71,7 @@ import {
|
|
|
71
71
|
projects,
|
|
72
72
|
queries,
|
|
73
73
|
renderReportHtml
|
|
74
|
-
} from "./chunk-
|
|
74
|
+
} from "./chunk-ISONU3FA.js";
|
|
75
75
|
import {
|
|
76
76
|
AdsDeliverySnapshotStatuses,
|
|
77
77
|
AdsHistoricalCampaignRollupStatuses,
|
|
@@ -140,7 +140,7 @@ import {
|
|
|
140
140
|
providerQuotaPolicySchema,
|
|
141
141
|
resolveProviderInput,
|
|
142
142
|
winnabilityClassSchema
|
|
143
|
-
} from "./chunk-
|
|
143
|
+
} from "./chunk-Z2HTLTQV.js";
|
|
144
144
|
|
|
145
145
|
// src/cli.ts
|
|
146
146
|
import { pathToFileURL } from "url";
|
|
@@ -7569,8 +7569,95 @@ async function listCompetitors(project, format) {
|
|
|
7569
7569
|
console.log(` ${c.domain}`);
|
|
7570
7570
|
}
|
|
7571
7571
|
}
|
|
7572
|
+
async function showCompetitorLandscape(project, options) {
|
|
7573
|
+
const client = getClient10();
|
|
7574
|
+
const data = await client.getCompetitorLandscape(project, {
|
|
7575
|
+
window: options.window,
|
|
7576
|
+
scope: options.scope,
|
|
7577
|
+
groupKey: options.groupKey,
|
|
7578
|
+
provider: options.provider,
|
|
7579
|
+
...options.groupBy ? { groupBy: options.groupBy } : {},
|
|
7580
|
+
...options.model !== void 0 ? { model: options.model } : {},
|
|
7581
|
+
queryClass: options.queryClass,
|
|
7582
|
+
location: options.location,
|
|
7583
|
+
runId: options.runId
|
|
7584
|
+
});
|
|
7585
|
+
if (options.format === "json") {
|
|
7586
|
+
console.log(JSON.stringify(data, null, 2));
|
|
7587
|
+
return;
|
|
7588
|
+
}
|
|
7589
|
+
if (options.format === "jsonl") {
|
|
7590
|
+
console.log(JSON.stringify(data));
|
|
7591
|
+
return;
|
|
7592
|
+
}
|
|
7593
|
+
printCompetitorLandscape(data);
|
|
7594
|
+
}
|
|
7595
|
+
function printCompetitorLandscape(data) {
|
|
7596
|
+
const scope = data.scope.kind === "group" ? `market ${data.scope.groupKey}` : data.scope.kind === "all-markets" ? "all markets" : "project";
|
|
7597
|
+
console.log(`Competitor landscape \xB7 ${scope} \xB7 ${data.window}`);
|
|
7598
|
+
if (data.filters.model !== void 0) {
|
|
7599
|
+
console.log(`Requested model filter: ${data.filters.provider} \xB7 ${data.filters.model}`);
|
|
7600
|
+
}
|
|
7601
|
+
console.log("Mention share is answer-text evidence; citations are independent source-list evidence.");
|
|
7602
|
+
console.log(
|
|
7603
|
+
data.filters.queryClass === "all" ? "Share of voice is blank: branded and non-brand queries are pooled here. Add --query-class non-brand for a ratio." : `Counting ${data.filters.queryClass} queries only.`
|
|
7604
|
+
);
|
|
7605
|
+
if (data.truncated) console.log("Top 100 observed competitors and top 100 other cited sources shown; pinned competitors are complete.");
|
|
7606
|
+
console.log("");
|
|
7607
|
+
printLandscapeRows("Your brand", [data.project]);
|
|
7608
|
+
printLandscapeRows("Pinned competitors", data.pinned);
|
|
7609
|
+
printLandscapeRows("Observed competitors", data.observed);
|
|
7610
|
+
printLandscapeRows("Other cited sources", data.otherSources);
|
|
7611
|
+
console.log("");
|
|
7612
|
+
console.log(
|
|
7613
|
+
`Evidence: ${data.evidence.answeredResults} answer-text result(s), ${data.evidence.sourceResults} source result(s); excluded: ${data.evidence.excludedProbeResults} probe, ${data.evidence.excludedNonCompletedResults} non-completed.`
|
|
7614
|
+
);
|
|
7615
|
+
if (data.modelComparison) printModelComparison(data.modelComparison);
|
|
7616
|
+
}
|
|
7617
|
+
function describeServedModels(evidence) {
|
|
7618
|
+
if (evidence.status === "unknown") return "Unknown (not disclosed)";
|
|
7619
|
+
if (evidence.status === "known") return evidence.model;
|
|
7620
|
+
return [...evidence.models, ...evidence.includesUnknown ? ["Unknown (not disclosed)"] : []].join(", ");
|
|
7621
|
+
}
|
|
7622
|
+
function printModelComparison(comparison) {
|
|
7623
|
+
console.log("");
|
|
7624
|
+
console.log(`Model comparison \xB7 requested-model basis \xB7 ${comparison.groups.length} of ${comparison.totalGroups} groups`);
|
|
7625
|
+
console.log("Groups use stored observations. They do not form a matched-query or equal-weight comparison.");
|
|
7626
|
+
if (comparison.truncated) console.log("The first 50 provider/model groups are shown. Additional groups are omitted.");
|
|
7627
|
+
for (const group of comparison.groups) {
|
|
7628
|
+
console.log("");
|
|
7629
|
+
console.log(`${group.provider} \xB7 requested model: ${group.model ?? "Unknown (not recorded)"}`);
|
|
7630
|
+
console.log(`Served model evidence: ${describeServedModels(group.servedModels)}`);
|
|
7631
|
+
console.log(`Samples: ${group.snapshotCount} snapshot(s), ${group.evidence.answeredResults} answer-text result(s), ${group.evidence.sourceResults} source result(s).`);
|
|
7632
|
+
printLandscapeRows("Your brand", [group.project], true);
|
|
7633
|
+
printLandscapeRows("Pinned competitors", group.pinned, true);
|
|
7634
|
+
printLandscapeRows("Observed competitors", group.observed, true);
|
|
7635
|
+
printLandscapeRows("Other cited sources", group.otherSources, true);
|
|
7636
|
+
if (group.truncated) console.log("Top 100 observed competitors and top 100 other sources shown. Pinned competitors are complete.");
|
|
7637
|
+
}
|
|
7638
|
+
}
|
|
7639
|
+
function printLandscapeRows(heading, rows, showSampleCount = false) {
|
|
7640
|
+
console.log(`${heading}:`);
|
|
7641
|
+
if (rows.length === 0) {
|
|
7642
|
+
console.log(" \u2014");
|
|
7643
|
+
return;
|
|
7644
|
+
}
|
|
7645
|
+
for (const row of rows) {
|
|
7646
|
+
const sov = row.shareOfVoice === null ? "\u2014" : `${row.shareOfVoice.toFixed(1)}%`;
|
|
7647
|
+
console.log(` ${row.domain} mention ${row.mentionCount} \xB7 citation ${row.citationCount} \xB7 SOV ${sov}${showSampleCount ? ` \xB7 answers ${row.answeredResults}` : ""}`);
|
|
7648
|
+
}
|
|
7649
|
+
}
|
|
7572
7650
|
|
|
7573
7651
|
// src/cli-commands/competitor.ts
|
|
7652
|
+
var LANDSCAPE_USAGE = "canonry competitor landscape <project> [--window 7d|30d|90d|all] [--group-key <key>|--scope all-markets] [--by-model] [--provider <provider> [--model <id>]] [--query-class all|branded|non-brand] [--location <label>] [--run-id <id>] [--format json|jsonl]";
|
|
7653
|
+
function parseLandscapeScope(value) {
|
|
7654
|
+
if (value === void 0 || value === "") return void 0;
|
|
7655
|
+
if (value !== "all-markets") throw usageError(`--scope must be "all-markets" (got "${value}")`, {
|
|
7656
|
+
message: '--scope must be "all-markets"',
|
|
7657
|
+
details: { command: "competitor.landscape", usage: LANDSCAPE_USAGE }
|
|
7658
|
+
});
|
|
7659
|
+
return value;
|
|
7660
|
+
}
|
|
7574
7661
|
var COMPETITOR_CLI_COMMANDS = [
|
|
7575
7662
|
{
|
|
7576
7663
|
path: ["competitor", "add"],
|
|
@@ -7634,14 +7721,60 @@ var COMPETITOR_CLI_COMMANDS = [
|
|
|
7634
7721
|
await listCompetitors(project, input.format);
|
|
7635
7722
|
}
|
|
7636
7723
|
},
|
|
7724
|
+
{
|
|
7725
|
+
path: ["competitor", "landscape"],
|
|
7726
|
+
usage: LANDSCAPE_USAGE,
|
|
7727
|
+
options: {
|
|
7728
|
+
window: stringOption(),
|
|
7729
|
+
"group-key": stringOption(),
|
|
7730
|
+
scope: stringOption(),
|
|
7731
|
+
provider: stringOption(),
|
|
7732
|
+
"by-model": { type: "boolean" },
|
|
7733
|
+
model: stringOption(),
|
|
7734
|
+
"query-class": stringOption(),
|
|
7735
|
+
location: stringOption(),
|
|
7736
|
+
"run-id": stringOption()
|
|
7737
|
+
},
|
|
7738
|
+
run: async (input) => {
|
|
7739
|
+
const project = requireProject(input, "competitor.landscape", LANDSCAPE_USAGE);
|
|
7740
|
+
const scope = parseLandscapeScope(getString(input.values, "scope"));
|
|
7741
|
+
const groupKey = getString(input.values, "group-key");
|
|
7742
|
+
const provider = getString(input.values, "provider");
|
|
7743
|
+
const model = getString(input.values, "model");
|
|
7744
|
+
if (model !== void 0 && !provider?.trim()) {
|
|
7745
|
+
throw usageError("--model requires --provider", {
|
|
7746
|
+
message: "--model requires --provider",
|
|
7747
|
+
details: { command: "competitor.landscape", usage: LANDSCAPE_USAGE }
|
|
7748
|
+
});
|
|
7749
|
+
}
|
|
7750
|
+
if (scope === "all-markets" && groupKey) {
|
|
7751
|
+
throw usageError("--group-key cannot be combined with --scope all-markets", {
|
|
7752
|
+
message: "--group-key cannot be combined with --scope all-markets",
|
|
7753
|
+
details: { command: "competitor.landscape", usage: LANDSCAPE_USAGE }
|
|
7754
|
+
});
|
|
7755
|
+
}
|
|
7756
|
+
await showCompetitorLandscape(project, {
|
|
7757
|
+
window: getString(input.values, "window"),
|
|
7758
|
+
groupKey,
|
|
7759
|
+
scope,
|
|
7760
|
+
provider,
|
|
7761
|
+
...getBoolean(input.values, "by-model") ? { groupBy: "model" } : {},
|
|
7762
|
+
...model !== void 0 ? { model } : {},
|
|
7763
|
+
queryClass: getString(input.values, "query-class"),
|
|
7764
|
+
location: getString(input.values, "location"),
|
|
7765
|
+
runId: getString(input.values, "run-id"),
|
|
7766
|
+
format: input.format
|
|
7767
|
+
});
|
|
7768
|
+
}
|
|
7769
|
+
},
|
|
7637
7770
|
{
|
|
7638
7771
|
path: ["competitor"],
|
|
7639
|
-
usage: "canonry competitor <add|remove|delete|list> <project> [args]",
|
|
7772
|
+
usage: "canonry competitor <add|remove|delete|list|landscape> <project> [args]",
|
|
7640
7773
|
run: async (input) => {
|
|
7641
7774
|
unknownSubcommand(input.positionals[0], {
|
|
7642
7775
|
command: "competitor",
|
|
7643
|
-
usage: "canonry competitor <add|remove|delete|list> <project> [args]",
|
|
7644
|
-
available: ["add", "remove", "delete", "list"]
|
|
7776
|
+
usage: "canonry competitor <add|remove|delete|list|landscape> <project> [args]",
|
|
7777
|
+
available: ["add", "remove", "delete", "list", "landscape"]
|
|
7645
7778
|
});
|
|
7646
7779
|
}
|
|
7647
7780
|
}
|