@canonry/canonry 4.146.0 → 4.147.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/assets/assets/{AuditHistoryPanel-IDsSUFI3.js → AuditHistoryPanel-DiQ0Ynw5.js} +1 -1
- package/assets/assets/{BacklinksPage-BswN-pyj.js → BacklinksPage-DLUQuPE_.js} +1 -1
- package/assets/assets/{ChartPrimitives-CIe-R58_.js → ChartPrimitives-BoEy1qo7.js} +1 -1
- package/assets/assets/{HistoryPage-B18Jpq8c.js → HistoryPage-mYR2vk8n.js} +1 -1
- package/assets/assets/MeasurementPropertyPage-BocyGHJN.js +1 -0
- package/assets/assets/ProjectPage-Q5wQ7nSW.js +12 -0
- package/assets/assets/{RunRow-3ZwTR4Bv.js → RunRow-Ct-A6H9e.js} +1 -1
- package/assets/assets/{RunsPage-BCAJulR1.js → RunsPage-CsDtq0Qw.js} +1 -1
- package/assets/assets/{SettingsPage-BT2_l0Do.js → SettingsPage-BXwFGc1P.js} +1 -1
- package/assets/assets/{TrafficPage-Cux8rj5G.js → TrafficPage-B2omyoI8.js} +1 -1
- package/assets/assets/{TrafficSourceDetailPage-DI1Ad8KS.js → TrafficSourceDetailPage-CoEqc6OJ.js} +1 -1
- package/assets/assets/{arrow-left-BMSx9HQB.js → arrow-left-Dh0vsQxe.js} +1 -1
- package/assets/assets/extract-error-message-DvWJ0xRn.js +1 -0
- package/assets/assets/{index-C6E5hp28.css → index-CXe6S1ey.css} +1 -1
- package/assets/assets/index-FE8JPHmT.js +213 -0
- package/assets/assets/{trash-2-CyoJtRAr.js → trash-2-D1_8ZseY.js} +1 -1
- package/assets/index.html +2 -2
- package/dist/{chunk-UQOTEIA6.js → chunk-4BL24FQA.js} +378 -3
- package/dist/{chunk-B5H55ZMA.js → chunk-BVOU4UJM.js} +3687 -3025
- package/dist/{chunk-ED7C5TWT.js → chunk-DRDNHYIF.js} +3757 -1424
- package/dist/{chunk-Z7B6BRPP.js → chunk-ZDYS24LW.js} +4 -4
- package/dist/cli.js +223 -15
- package/dist/index.js +4 -4
- package/dist/{intelligence-service-M5UNHF7X.js → intelligence-service-7CGZ537D.js} +2 -2
- package/dist/mcp.js +5 -5
- package/package.json +8 -7
- package/assets/assets/MeasurementPropertyPage-CvmQeoo7.js +0 -1
- package/assets/assets/ProjectPage-BE1MUAB5.js +0 -11
- package/assets/assets/extract-error-message-B-9FdQh8.js +0 -1
- package/assets/assets/index-kOXUzdqD.js +0 -213
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
loadConfig,
|
|
11
11
|
loadConfigRaw,
|
|
12
12
|
saveConfigPatch
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-4BL24FQA.js";
|
|
14
14
|
import {
|
|
15
15
|
CC_CACHE_DIR,
|
|
16
16
|
DUCKDB_SPEC,
|
|
@@ -126,7 +126,7 @@ import {
|
|
|
126
126
|
siteAuditSnapshots,
|
|
127
127
|
toAlertView,
|
|
128
128
|
usageCounters
|
|
129
|
-
} from "./chunk-
|
|
129
|
+
} from "./chunk-DRDNHYIF.js";
|
|
130
130
|
import {
|
|
131
131
|
AGENT_MEMORY_VALUE_MAX_BYTES,
|
|
132
132
|
AGENT_PROVIDER_IDS,
|
|
@@ -217,7 +217,7 @@ import {
|
|
|
217
217
|
validationError,
|
|
218
218
|
winnabilityClassLabel,
|
|
219
219
|
withRetry
|
|
220
|
-
} from "./chunk-
|
|
220
|
+
} from "./chunk-BVOU4UJM.js";
|
|
221
221
|
|
|
222
222
|
// src/telemetry.ts
|
|
223
223
|
import crypto from "crypto";
|
|
@@ -7420,7 +7420,7 @@ function readStoredGroundingSources(rawResponse) {
|
|
|
7420
7420
|
return result;
|
|
7421
7421
|
}
|
|
7422
7422
|
async function backfillInsightsCommand(project, opts) {
|
|
7423
|
-
const { IntelligenceService: IntelligenceService2 } = await import("./intelligence-service-
|
|
7423
|
+
const { IntelligenceService: IntelligenceService2 } = await import("./intelligence-service-7CGZ537D.js");
|
|
7424
7424
|
const config = loadConfig();
|
|
7425
7425
|
const db = createClient(config.database);
|
|
7426
7426
|
migrate(db);
|
package/dist/cli.js
CHANGED
|
@@ -30,7 +30,7 @@ import {
|
|
|
30
30
|
showFirstRunNotice,
|
|
31
31
|
trackCliCommandFinished,
|
|
32
32
|
trackEvent
|
|
33
|
-
} from "./chunk-
|
|
33
|
+
} from "./chunk-ZDYS24LW.js";
|
|
34
34
|
import {
|
|
35
35
|
CliError,
|
|
36
36
|
EXIT_SYSTEM_ERROR,
|
|
@@ -46,8 +46,9 @@ import {
|
|
|
46
46
|
printCliError,
|
|
47
47
|
saveConfig,
|
|
48
48
|
saveConfigPatch,
|
|
49
|
+
systemError,
|
|
49
50
|
usageError
|
|
50
|
-
} from "./chunk-
|
|
51
|
+
} from "./chunk-4BL24FQA.js";
|
|
51
52
|
import {
|
|
52
53
|
apiKeys,
|
|
53
54
|
createClient,
|
|
@@ -55,7 +56,7 @@ import {
|
|
|
55
56
|
projects,
|
|
56
57
|
queries,
|
|
57
58
|
renderReportHtml
|
|
58
|
-
} from "./chunk-
|
|
59
|
+
} from "./chunk-DRDNHYIF.js";
|
|
59
60
|
import {
|
|
60
61
|
AdsDeliverySnapshotStatuses,
|
|
61
62
|
AdsHistoricalCampaignRollupStatuses,
|
|
@@ -68,6 +69,7 @@ import {
|
|
|
68
69
|
CheckScopes,
|
|
69
70
|
CheckStatuses,
|
|
70
71
|
CitationStates,
|
|
72
|
+
MeasurementEvidenceShapes,
|
|
71
73
|
READ_ONLY_SCOPE,
|
|
72
74
|
REPORT_PERIOD_OPTIONS,
|
|
73
75
|
ResearchRunStatuses,
|
|
@@ -106,7 +108,7 @@ import {
|
|
|
106
108
|
providerQuotaPolicySchema,
|
|
107
109
|
resolveProviderInput,
|
|
108
110
|
winnabilityClassSchema
|
|
109
|
-
} from "./chunk-
|
|
111
|
+
} from "./chunk-BVOU4UJM.js";
|
|
110
112
|
|
|
111
113
|
// src/cli.ts
|
|
112
114
|
import { pathToFileURL } from "url";
|
|
@@ -15714,6 +15716,7 @@ Usage: ${usage}`, {
|
|
|
15714
15716
|
];
|
|
15715
15717
|
|
|
15716
15718
|
// src/commands/measurement-plan.ts
|
|
15719
|
+
import crypto3 from "crypto";
|
|
15717
15720
|
import fs16 from "fs";
|
|
15718
15721
|
import { parse } from "yaml";
|
|
15719
15722
|
function readPlan(source) {
|
|
@@ -15745,6 +15748,76 @@ async function publishMeasurementPlan(project, source) {
|
|
|
15745
15748
|
async function retireMeasurementPlanSegment(project, stableKey) {
|
|
15746
15749
|
console.log(JSON.stringify(await createApiClient().retireMeasurementPlanSegment(project, stableKey), null, 2));
|
|
15747
15750
|
}
|
|
15751
|
+
async function measurementAssignmentRequest(project, opts) {
|
|
15752
|
+
const client = createApiClient();
|
|
15753
|
+
const current = await client.getMeasurementPlanDraft(project);
|
|
15754
|
+
if (!current.draft || !current.etag) {
|
|
15755
|
+
throw new Error(`Project "${project}" has no Advanced Measurement draft. Start setup in the dashboard or create a draft first.`);
|
|
15756
|
+
}
|
|
15757
|
+
const targetKeys = opts.allProperties ? current.draft.authoring.targets.filter((target) => target.status === "included").map((target) => target.stableKey) : opts.targetKeys;
|
|
15758
|
+
return {
|
|
15759
|
+
client,
|
|
15760
|
+
request: {
|
|
15761
|
+
...targetKeys?.length ? { targetKeys } : {},
|
|
15762
|
+
...opts.groupKeys?.length ? { groupKeys: opts.groupKeys } : {},
|
|
15763
|
+
queryIds: opts.queryIds
|
|
15764
|
+
}
|
|
15765
|
+
};
|
|
15766
|
+
}
|
|
15767
|
+
async function previewMeasurementPlanAssignments(project, opts) {
|
|
15768
|
+
const { client, request } = await measurementAssignmentRequest(project, opts);
|
|
15769
|
+
console.log(JSON.stringify(await client.previewMeasurementDraftAssignments(project, request), null, 2));
|
|
15770
|
+
}
|
|
15771
|
+
async function applyMeasurementPlanAssignments(project, opts) {
|
|
15772
|
+
const { client, request } = await measurementAssignmentRequest(project, opts);
|
|
15773
|
+
const preview = await client.previewMeasurementDraftAssignments(project, request);
|
|
15774
|
+
const result = await client.applyMeasurementDraftAssignments(
|
|
15775
|
+
project,
|
|
15776
|
+
request,
|
|
15777
|
+
crypto3.randomUUID(),
|
|
15778
|
+
preview.draftEtag
|
|
15779
|
+
);
|
|
15780
|
+
console.log(JSON.stringify({ preview, result }, null, 2));
|
|
15781
|
+
}
|
|
15782
|
+
async function replaceMeasurementPlanAssignments(project, opts) {
|
|
15783
|
+
const { client, request } = await measurementAssignmentRequest(project, opts);
|
|
15784
|
+
const preview = await client.previewMeasurementDraftAssignments(project, request);
|
|
15785
|
+
const result = await client.replaceMeasurementDraftAssignments(
|
|
15786
|
+
project,
|
|
15787
|
+
request,
|
|
15788
|
+
crypto3.randomUUID(),
|
|
15789
|
+
preview.draftEtag
|
|
15790
|
+
);
|
|
15791
|
+
console.log(JSON.stringify({ preview, result }, null, 2));
|
|
15792
|
+
}
|
|
15793
|
+
function readGroupMembershipCsv(source) {
|
|
15794
|
+
return source === "-" ? fs16.readFileSync(0, "utf8") : fs16.readFileSync(source, "utf8");
|
|
15795
|
+
}
|
|
15796
|
+
async function previewMeasurementPlanGroups(project, source) {
|
|
15797
|
+
const preview = await createApiClient().previewMeasurementDraftGroupMembership(project, {
|
|
15798
|
+
csv: readGroupMembershipCsv(source)
|
|
15799
|
+
});
|
|
15800
|
+
console.log(JSON.stringify(preview, null, 2));
|
|
15801
|
+
}
|
|
15802
|
+
async function applyMeasurementPlanGroups(project, source, opts) {
|
|
15803
|
+
const client = createApiClient();
|
|
15804
|
+
const csv = readGroupMembershipCsv(source);
|
|
15805
|
+
const preview = await client.previewMeasurementDraftGroupMembership(project, { csv });
|
|
15806
|
+
if (preview.counts.needsAttention > 0 && !opts.acknowledgeSkipped) {
|
|
15807
|
+
throw new Error(
|
|
15808
|
+
`${preview.counts.needsAttention} CSV rows need attention. Correct them or add --acknowledge-skipped to apply only the selected matched rows.`
|
|
15809
|
+
);
|
|
15810
|
+
}
|
|
15811
|
+
const acceptedRows = opts.acceptAllMatched ? preview.rows.filter((row) => row.status === "matched").map((row) => row.dataRow) : opts.acceptedRows ?? [];
|
|
15812
|
+
if (acceptedRows.length === 0) throw new Error("No matched CSV rows were selected for apply.");
|
|
15813
|
+
const result = await client.applyMeasurementDraftGroupMembership(project, {
|
|
15814
|
+
csv,
|
|
15815
|
+
sourceChecksum: preview.sourceChecksum,
|
|
15816
|
+
previewChecksum: preview.previewChecksum,
|
|
15817
|
+
acceptedRows
|
|
15818
|
+
}, crypto3.randomUUID(), preview.draftEtag);
|
|
15819
|
+
console.log(JSON.stringify({ preview, result }, null, 2));
|
|
15820
|
+
}
|
|
15748
15821
|
async function discoverMeasurementTargets(project, sitemapUrl, ruleSource, maxUrls) {
|
|
15749
15822
|
const request = measurementDiscoveryRequestSchema.parse({
|
|
15750
15823
|
sitemapUrl,
|
|
@@ -15801,6 +15874,11 @@ function printMeasurementProperty(response) {
|
|
|
15801
15874
|
}
|
|
15802
15875
|
console.log(lines.join("\n"));
|
|
15803
15876
|
}
|
|
15877
|
+
function shapedPage(response) {
|
|
15878
|
+
if (response.answers !== void 0) return { shape: MeasurementEvidenceShapes.answers, ...response.answers };
|
|
15879
|
+
if (response.evidence !== void 0) return { shape: MeasurementEvidenceShapes.sources, ...response.evidence };
|
|
15880
|
+
throw systemError("The measurement property evidence response carried neither an evidence nor an answers page.");
|
|
15881
|
+
}
|
|
15804
15882
|
async function showMeasurementPropertyEvidence(project, opts) {
|
|
15805
15883
|
const response = await createApiClient().getMeasurementPropertyEvidence(project, {
|
|
15806
15884
|
targetKey: opts.targetKey,
|
|
@@ -15808,19 +15886,22 @@ async function showMeasurementPropertyEvidence(project, opts) {
|
|
|
15808
15886
|
...opts.provider === void 0 ? {} : { provider: opts.provider },
|
|
15809
15887
|
...opts.location === void 0 ? {} : { location: opts.location },
|
|
15810
15888
|
...opts.runId === void 0 ? {} : { runId: opts.runId },
|
|
15889
|
+
...opts.shape === void 0 ? {} : { shape: opts.shape },
|
|
15811
15890
|
...opts.cursor === void 0 ? {} : { cursor: opts.cursor },
|
|
15812
15891
|
...opts.limit === void 0 ? {} : { limit: opts.limit }
|
|
15813
15892
|
});
|
|
15814
15893
|
if (opts.format === "jsonl") {
|
|
15894
|
+
const page = shapedPage(response);
|
|
15815
15895
|
emitJsonl([{
|
|
15816
15896
|
kind: "measurement-property-evidence-header",
|
|
15897
|
+
shape: page.shape,
|
|
15817
15898
|
property: response.property,
|
|
15818
15899
|
queryClass: response.queryClass,
|
|
15819
15900
|
measurement: response.measurement,
|
|
15820
|
-
totalEstimate:
|
|
15821
|
-
nextCursor:
|
|
15901
|
+
totalEstimate: page.totalEstimate ?? null,
|
|
15902
|
+
nextCursor: page.nextCursor ?? null
|
|
15822
15903
|
}]);
|
|
15823
|
-
emitJsonl(
|
|
15904
|
+
emitJsonl(page.items);
|
|
15824
15905
|
return;
|
|
15825
15906
|
}
|
|
15826
15907
|
if (opts.format === "json") {
|
|
@@ -15829,6 +15910,10 @@ async function showMeasurementPropertyEvidence(project, opts) {
|
|
|
15829
15910
|
}
|
|
15830
15911
|
printMeasurementPropertyEvidence(response);
|
|
15831
15912
|
}
|
|
15913
|
+
function signalText(signal) {
|
|
15914
|
+
if (signal === null) return "not measured";
|
|
15915
|
+
return signal ? "yes" : "no";
|
|
15916
|
+
}
|
|
15832
15917
|
function printMeasurementPropertyEvidence(response) {
|
|
15833
15918
|
const lines = [];
|
|
15834
15919
|
lines.push(`${response.property.label} \u2014 ${response.queryClass} questions`);
|
|
@@ -15837,18 +15922,28 @@ function printMeasurementPropertyEvidence(response) {
|
|
|
15837
15922
|
console.log(lines.join("\n"));
|
|
15838
15923
|
return;
|
|
15839
15924
|
}
|
|
15840
|
-
const page = response
|
|
15925
|
+
const page = shapedPage(response);
|
|
15926
|
+
const answerShape = page.shape === MeasurementEvidenceShapes.answers;
|
|
15841
15927
|
lines.push(`Measurement: ${response.measurement.state}${response.measurement.displayedRunId ? ` \xB7 run ${response.measurement.displayedRunId}` : ""}`);
|
|
15842
15928
|
if (page.items.length === 0) {
|
|
15843
|
-
lines.push("No source evidence matched this Property in the displayed run.");
|
|
15929
|
+
lines.push(answerShape ? "No answers matched this Property in the displayed run." : "No source evidence matched this Property in the displayed run.");
|
|
15844
15930
|
console.log(lines.join("\n"));
|
|
15845
15931
|
return;
|
|
15846
15932
|
}
|
|
15847
|
-
lines.push(`${page.items.length} of ${page.totalEstimate ?? page.items.length} evidence rows`);
|
|
15933
|
+
lines.push(`${page.items.length} of ${page.totalEstimate ?? page.items.length} ${answerShape ? "answers" : "evidence rows"}`);
|
|
15848
15934
|
lines.push("");
|
|
15849
|
-
|
|
15850
|
-
|
|
15851
|
-
|
|
15935
|
+
if (page.shape === MeasurementEvidenceShapes.answers) {
|
|
15936
|
+
lines.push(`${"Engine".padEnd(12)}${"Question".padEnd(40)}${"Mentioned".padEnd(15)}${"Cited".padEnd(8)}Sources`);
|
|
15937
|
+
for (const item of page.items) {
|
|
15938
|
+
lines.push(
|
|
15939
|
+
`${item.provider.padEnd(12)}${item.queryText.slice(0, 39).padEnd(40)}${signalText(item.mentioned).padEnd(15)}${signalText(item.cited).padEnd(8)}${item.sources.length}`
|
|
15940
|
+
);
|
|
15941
|
+
}
|
|
15942
|
+
} else {
|
|
15943
|
+
lines.push(`${"Match".padEnd(14)}${"Engine".padEnd(12)}${"Question".padEnd(40)}URL`);
|
|
15944
|
+
for (const item of page.items) {
|
|
15945
|
+
lines.push(`${item.classification.padEnd(14)}${item.provider.padEnd(12)}${item.queryText.slice(0, 39).padEnd(40)}${item.sourceUrl}`);
|
|
15946
|
+
}
|
|
15852
15947
|
}
|
|
15853
15948
|
if (page.nextCursor) lines.push(`
|
|
15854
15949
|
More rows: --cursor ${page.nextCursor}`);
|
|
@@ -15857,6 +15952,7 @@ More rows: --cursor ${page.nextCursor}`);
|
|
|
15857
15952
|
|
|
15858
15953
|
// src/cli-commands/measurement-plan.ts
|
|
15859
15954
|
var QUERY_CLASSES = ["all", "branded", "non-brand"];
|
|
15955
|
+
var EVIDENCE_SHAPES = ["sources", "answers"];
|
|
15860
15956
|
function queryClassOption(input) {
|
|
15861
15957
|
const value = getString(input.values, "query-class");
|
|
15862
15958
|
if (value === void 0) return void 0;
|
|
@@ -15864,6 +15960,13 @@ function queryClassOption(input) {
|
|
|
15864
15960
|
if (!match) throw usageError(`--query-class must be one of ${QUERY_CLASSES.join(", ")}`);
|
|
15865
15961
|
return match;
|
|
15866
15962
|
}
|
|
15963
|
+
function shapeOption(input) {
|
|
15964
|
+
const value = getString(input.values, "shape");
|
|
15965
|
+
if (value === void 0) return void 0;
|
|
15966
|
+
const match = EVIDENCE_SHAPES.find((candidate) => candidate === value);
|
|
15967
|
+
if (!match) throw usageError(`--shape must be one of ${EVIDENCE_SHAPES.join(", ")}`);
|
|
15968
|
+
return match;
|
|
15969
|
+
}
|
|
15867
15970
|
function propertyScope(input, command, usage) {
|
|
15868
15971
|
return {
|
|
15869
15972
|
targetKey: requireStringOption(input, "target-key", { command, usage, message: "--target-key is required" }),
|
|
@@ -15881,6 +15984,30 @@ var PROPERTY_SCOPE_OPTIONS = {
|
|
|
15881
15984
|
location: stringOption(),
|
|
15882
15985
|
"run-id": stringOption()
|
|
15883
15986
|
};
|
|
15987
|
+
var ASSIGNMENT_AUDIENCE_OPTIONS = {
|
|
15988
|
+
group: multiStringOption(),
|
|
15989
|
+
"target-key": multiStringOption(),
|
|
15990
|
+
"all-properties": { type: "boolean" },
|
|
15991
|
+
"query-id": multiStringOption()
|
|
15992
|
+
};
|
|
15993
|
+
function assignmentAudience(input, command, usage) {
|
|
15994
|
+
const project = requireProject(input, command, usage);
|
|
15995
|
+
const groupKeys = getStringArray(input.values, "group")?.map((value) => value.trim()).filter(Boolean);
|
|
15996
|
+
const targetKeys = getStringArray(input.values, "target-key")?.map((value) => value.trim()).filter(Boolean);
|
|
15997
|
+
const queryIds = getStringArray(input.values, "query-id")?.map((value) => value.trim()).filter(Boolean) ?? [];
|
|
15998
|
+
const allProperties = getBoolean(input.values, "all-properties");
|
|
15999
|
+
if (queryIds.length === 0) throw usageError(`Error: at least one --query-id is required
|
|
16000
|
+
Usage: ${usage}`);
|
|
16001
|
+
if (allProperties && ((groupKeys?.length ?? 0) > 0 || (targetKeys?.length ?? 0) > 0)) {
|
|
16002
|
+
throw usageError(`Error: --all-properties cannot be combined with --group or --target-key
|
|
16003
|
+
Usage: ${usage}`);
|
|
16004
|
+
}
|
|
16005
|
+
if (!allProperties && (groupKeys?.length ?? 0) === 0 && (targetKeys?.length ?? 0) === 0) {
|
|
16006
|
+
throw usageError(`Error: select at least one --group, --target-key, or --all-properties
|
|
16007
|
+
Usage: ${usage}`);
|
|
16008
|
+
}
|
|
16009
|
+
return { project, options: { groupKeys, targetKeys, queryIds, allProperties } };
|
|
16010
|
+
}
|
|
15884
16011
|
var MEASUREMENT_PLAN_CLI_COMMANDS = [
|
|
15885
16012
|
{ path: ["measurement-plan", "show"], usage: "canonry measurement-plan show <project> [--revision N] [--format json]", options: { revision: stringOption() }, run: async (input) => {
|
|
15886
16013
|
const value = getString(input.values, "revision");
|
|
@@ -15901,6 +16028,85 @@ var MEASUREMENT_PLAN_CLI_COMMANDS = [
|
|
|
15901
16028
|
if (!stableKey) throw usageError("stable segment key is required");
|
|
15902
16029
|
return retireMeasurementPlanSegment(project, stableKey);
|
|
15903
16030
|
} },
|
|
16031
|
+
{
|
|
16032
|
+
path: ["measurement-plan", "assignments", "preview"],
|
|
16033
|
+
usage: "canonry measurement-plan assignments preview <project> [--group KEY ...] [--target-key KEY ... | --all-properties] --query-id ID [--query-id ID ...] [--format json]",
|
|
16034
|
+
options: ASSIGNMENT_AUDIENCE_OPTIONS,
|
|
16035
|
+
run: (input) => {
|
|
16036
|
+
const usage = "canonry measurement-plan assignments preview <project> [--group KEY ...] [--target-key KEY ... | --all-properties] --query-id ID [--query-id ID ...]";
|
|
16037
|
+
const { project, options } = assignmentAudience(input, "measurement-plan.assignments.preview", usage);
|
|
16038
|
+
return previewMeasurementPlanAssignments(project, options);
|
|
16039
|
+
}
|
|
16040
|
+
},
|
|
16041
|
+
{
|
|
16042
|
+
path: ["measurement-plan", "assignments", "apply"],
|
|
16043
|
+
usage: "canonry measurement-plan assignments apply <project> [--group KEY ...] [--target-key KEY ... | --all-properties] --query-id ID [--query-id ID ...] [--format json]",
|
|
16044
|
+
options: ASSIGNMENT_AUDIENCE_OPTIONS,
|
|
16045
|
+
run: (input) => {
|
|
16046
|
+
const usage = "canonry measurement-plan assignments apply <project> [--group KEY ...] [--target-key KEY ... | --all-properties] --query-id ID [--query-id ID ...]";
|
|
16047
|
+
const { project, options } = assignmentAudience(input, "measurement-plan.assignments.apply", usage);
|
|
16048
|
+
return applyMeasurementPlanAssignments(project, options);
|
|
16049
|
+
}
|
|
16050
|
+
},
|
|
16051
|
+
{
|
|
16052
|
+
path: ["measurement-plan", "assignments", "replace"],
|
|
16053
|
+
usage: "canonry measurement-plan assignments replace <project> [--group KEY ...] [--target-key KEY ... | --all-properties] --query-id ID [--query-id ID ...] --confirm [--format json]",
|
|
16054
|
+
options: { ...ASSIGNMENT_AUDIENCE_OPTIONS, confirm: { type: "boolean" } },
|
|
16055
|
+
run: (input) => {
|
|
16056
|
+
const usage = "canonry measurement-plan assignments replace <project> [--group KEY ...] [--target-key KEY ... | --all-properties] --query-id ID [--query-id ID ...] --confirm";
|
|
16057
|
+
if (!getBoolean(input.values, "confirm")) throw usageError(`Error: --confirm is required
|
|
16058
|
+
Usage: ${usage}`);
|
|
16059
|
+
const { project, options } = assignmentAudience(input, "measurement-plan.assignments.replace", usage);
|
|
16060
|
+
return replaceMeasurementPlanAssignments(project, options);
|
|
16061
|
+
}
|
|
16062
|
+
},
|
|
16063
|
+
{
|
|
16064
|
+
path: ["measurement-plan", "groups", "preview"],
|
|
16065
|
+
usage: "canonry measurement-plan groups preview <project> <csv|-> [--format json]",
|
|
16066
|
+
run: (input) => {
|
|
16067
|
+
const usage = "canonry measurement-plan groups preview <project> <csv|->";
|
|
16068
|
+
const project = requireProject(input, "measurement-plan.groups.preview", usage);
|
|
16069
|
+
const source = input.positionals[1];
|
|
16070
|
+
if (!source) throw usageError(`Error: CSV file path or - is required
|
|
16071
|
+
Usage: ${usage}`);
|
|
16072
|
+
return previewMeasurementPlanGroups(project, source);
|
|
16073
|
+
}
|
|
16074
|
+
},
|
|
16075
|
+
{
|
|
16076
|
+
path: ["measurement-plan", "groups", "apply"],
|
|
16077
|
+
usage: "canonry measurement-plan groups apply <project> <csv|-> --confirm [--accept-row N ... | --accept-all-matched] [--acknowledge-skipped] [--format json]",
|
|
16078
|
+
options: {
|
|
16079
|
+
confirm: { type: "boolean" },
|
|
16080
|
+
"accept-row": multiStringOption(),
|
|
16081
|
+
"accept-all-matched": { type: "boolean" },
|
|
16082
|
+
"acknowledge-skipped": { type: "boolean" }
|
|
16083
|
+
},
|
|
16084
|
+
run: (input) => {
|
|
16085
|
+
const usage = "canonry measurement-plan groups apply <project> <csv|-> --confirm [--accept-row N ... | --accept-all-matched] [--acknowledge-skipped]";
|
|
16086
|
+
const project = requireProject(input, "measurement-plan.groups.apply", usage);
|
|
16087
|
+
const source = input.positionals[1];
|
|
16088
|
+
if (!source) throw usageError(`Error: CSV file path or - is required
|
|
16089
|
+
Usage: ${usage}`);
|
|
16090
|
+
if (!getBoolean(input.values, "confirm")) throw usageError(`Error: --confirm is required
|
|
16091
|
+
Usage: ${usage}`);
|
|
16092
|
+
const acceptAllMatched = getBoolean(input.values, "accept-all-matched");
|
|
16093
|
+
const rowValues = getStringArray(input.values, "accept-row") ?? [];
|
|
16094
|
+
if (acceptAllMatched === rowValues.length > 0) {
|
|
16095
|
+
throw usageError(`Error: choose exactly one of --accept-row or --accept-all-matched
|
|
16096
|
+
Usage: ${usage}`);
|
|
16097
|
+
}
|
|
16098
|
+
const acceptedRows = rowValues.map((value) => Number(value));
|
|
16099
|
+
if (acceptedRows.some((row) => !Number.isSafeInteger(row) || row < 1)) {
|
|
16100
|
+
throw usageError(`Error: --accept-row must be a positive integer
|
|
16101
|
+
Usage: ${usage}`);
|
|
16102
|
+
}
|
|
16103
|
+
return applyMeasurementPlanGroups(project, source, {
|
|
16104
|
+
acceptedRows,
|
|
16105
|
+
acceptAllMatched,
|
|
16106
|
+
acknowledgeSkipped: getBoolean(input.values, "acknowledge-skipped")
|
|
16107
|
+
});
|
|
16108
|
+
}
|
|
16109
|
+
},
|
|
15904
16110
|
{
|
|
15905
16111
|
path: ["measurement-plan", "discover"],
|
|
15906
16112
|
usage: "canonry measurement-plan discover <project> --sitemap-url <url> --rule <yaml|json|-> [--max-urls N] [--format json]",
|
|
@@ -15952,8 +16158,8 @@ var MEASUREMENT_PLAN_CLI_COMMANDS = [
|
|
|
15952
16158
|
},
|
|
15953
16159
|
{
|
|
15954
16160
|
path: ["measurement-plan", "property-evidence"],
|
|
15955
|
-
usage: "canonry measurement-plan property-evidence <project> --target-key <key> [--query-class all|branded|non-brand] [--provider <p>] [--location <l>] [--run-id <id>] [--cursor <c>] [--limit N] [--format json|jsonl]",
|
|
15956
|
-
options: { ...PROPERTY_SCOPE_OPTIONS, cursor: stringOption(), limit: stringOption() },
|
|
16161
|
+
usage: "canonry measurement-plan property-evidence <project> --target-key <key> [--query-class all|branded|non-brand] [--provider <p>] [--location <l>] [--run-id <id>] [--shape sources|answers] [--cursor <c>] [--limit N] [--format json|jsonl]",
|
|
16162
|
+
options: { ...PROPERTY_SCOPE_OPTIONS, shape: stringOption(), cursor: stringOption(), limit: stringOption() },
|
|
15957
16163
|
run: (input) => {
|
|
15958
16164
|
const usage = "canonry measurement-plan property-evidence <project> --target-key <key>";
|
|
15959
16165
|
const project = requireProject(input, "measurement-plan.property-evidence", usage);
|
|
@@ -15962,8 +16168,10 @@ var MEASUREMENT_PLAN_CLI_COMMANDS = [
|
|
|
15962
16168
|
if (limit !== void 0 && (!Number.isInteger(limit) || limit < 1 || limit > 100)) {
|
|
15963
16169
|
throw usageError("--limit must be an integer from 1 to 100");
|
|
15964
16170
|
}
|
|
16171
|
+
const shape = shapeOption(input);
|
|
15965
16172
|
return showMeasurementPropertyEvidence(project, {
|
|
15966
16173
|
...propertyScope(input, "measurement-plan.property-evidence", usage),
|
|
16174
|
+
...shape === void 0 ? {} : { shape },
|
|
15967
16175
|
cursor: getString(input.values, "cursor"),
|
|
15968
16176
|
...limit === void 0 ? {} : { limit }
|
|
15969
16177
|
});
|
package/dist/index.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
2
|
createServer
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-ZDYS24LW.js";
|
|
4
4
|
import {
|
|
5
5
|
loadConfig
|
|
6
|
-
} from "./chunk-
|
|
7
|
-
import "./chunk-
|
|
8
|
-
import "./chunk-
|
|
6
|
+
} from "./chunk-4BL24FQA.js";
|
|
7
|
+
import "./chunk-DRDNHYIF.js";
|
|
8
|
+
import "./chunk-BVOU4UJM.js";
|
|
9
9
|
export {
|
|
10
10
|
createServer,
|
|
11
11
|
loadConfig
|
package/dist/mcp.js
CHANGED
|
@@ -3,10 +3,10 @@ import {
|
|
|
3
3
|
PACKAGE_VERSION,
|
|
4
4
|
canonryMcpTools,
|
|
5
5
|
createApiClient
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-4BL24FQA.js";
|
|
7
7
|
import {
|
|
8
8
|
isReadOnlyKey
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-BVOU4UJM.js";
|
|
10
10
|
|
|
11
11
|
// src/mcp/cli.ts
|
|
12
12
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
@@ -110,9 +110,9 @@ var CANONRY_MCP_TOOLKIT_NAMES = ["monitoring", "setup", "gsc", "ga", "gbp", "ads
|
|
|
110
110
|
var CANONRY_MCP_TOOLKITS = [
|
|
111
111
|
{
|
|
112
112
|
name: "monitoring",
|
|
113
|
-
title: "
|
|
114
|
-
description: "Inspect
|
|
115
|
-
whenToLoad: "Load when
|
|
113
|
+
title: "Measurement, runs, insights, health",
|
|
114
|
+
description: "Inspect portfolio and Property measurement, question results, run history, intelligence insights, and health timelines.",
|
|
115
|
+
whenToLoad: "Load when finding weak Properties, reviewing answers and competitors, checking data quality, comparing runs, or investigating regressions."
|
|
116
116
|
},
|
|
117
117
|
{
|
|
118
118
|
name: "setup",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@canonry/canonry",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.147.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Agent-first open-source AEO operating platform - track how answer engines cite your domain",
|
|
6
6
|
"license": "FSL-1.1-ALv2",
|
|
@@ -41,6 +41,7 @@
|
|
|
41
41
|
"dependencies": {
|
|
42
42
|
"@ainyc/aeo-audit": "4.0.1",
|
|
43
43
|
"@anthropic-ai/sdk": "^0.91.1",
|
|
44
|
+
"@fastify/rate-limit": "^11.2.0",
|
|
44
45
|
"@fastify/static": "^9.1.1",
|
|
45
46
|
"@google/genai": "^1.46.0",
|
|
46
47
|
"@mariozechner/pi-agent-core": "0.67.6",
|
|
@@ -66,23 +67,23 @@
|
|
|
66
67
|
"tsup": "^8.5.1",
|
|
67
68
|
"tsx": "^4.19.0",
|
|
68
69
|
"@ainyc/canonry-api-client": "0.0.0",
|
|
70
|
+
"@ainyc/canonry-config": "0.0.0",
|
|
69
71
|
"@ainyc/canonry-api-routes": "0.0.0",
|
|
70
|
-
"@ainyc/canonry-contracts": "0.0.0",
|
|
71
72
|
"@ainyc/canonry-db": "0.0.0",
|
|
72
|
-
"@ainyc/canonry-
|
|
73
|
+
"@ainyc/canonry-contracts": "0.0.0",
|
|
73
74
|
"@ainyc/canonry-integration-bing": "0.0.0",
|
|
74
75
|
"@ainyc/canonry-integration-openai-ads": "0.0.0",
|
|
75
76
|
"@ainyc/canonry-integration-cloud-run": "0.0.0",
|
|
77
|
+
"@ainyc/canonry-integration-google": "0.0.0",
|
|
76
78
|
"@ainyc/canonry-integration-commoncrawl": "0.0.0",
|
|
77
79
|
"@ainyc/canonry-integration-google-business-profile": "0.0.0",
|
|
78
|
-
"@ainyc/canonry-integration-google": "0.0.0",
|
|
80
|
+
"@ainyc/canonry-integration-google-places": "0.0.0",
|
|
79
81
|
"@ainyc/canonry-integration-traffic": "0.0.0",
|
|
80
82
|
"@ainyc/canonry-integration-wordpress": "0.0.0",
|
|
81
|
-
"@ainyc/canonry-integration-google-places": "0.0.0",
|
|
82
83
|
"@ainyc/canonry-intelligence": "0.0.0",
|
|
83
|
-
"@ainyc/canonry-provider-gemini": "0.0.0",
|
|
84
|
-
"@ainyc/canonry-provider-claude": "0.0.0",
|
|
85
84
|
"@ainyc/canonry-provider-cdp": "0.0.0",
|
|
85
|
+
"@ainyc/canonry-provider-claude": "0.0.0",
|
|
86
|
+
"@ainyc/canonry-provider-gemini": "0.0.0",
|
|
86
87
|
"@ainyc/canonry-provider-local": "0.0.0",
|
|
87
88
|
"@ainyc/canonry-provider-openai": "0.0.0",
|
|
88
89
|
"@ainyc/canonry-provider-perplexity": "0.0.0"
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{C as J,r as P,u as A,D as X,j as e,L as B}from"./vendor-tanstack-BjS7iY3g.js";import{bH as Y,bO as ee,c_ as se,bU as te,bI as ae,B as v,T as E,I as C,c$ as ne,m as U}from"./index-kOXUzdqD.js";import{m as re}from"./v2-overview-adapter-owDeFdUc.js";import{A as ie}from"./arrow-left-BMSx9HQB.js";import"./vendor-radix-DnzzbllM.js";import"./vendor-recharts-33ACLxsD.js";import"./vendor-markdown-CpDJch4G.js";const _=50,o={branded:{headline:"When they know your name",technical:"Branded questions"},"non-brand":{headline:"When they don't",technical:"Non-brand questions"}},oe={plan_v1:"Setup update required",no_completed_run:"No completed measurement yet",no_population:"No questions of this type are assigned",evidence_incomplete:"Source evidence is incomplete",not_applicable:"Not applicable for this Property"},Q={complete:{label:"Measured",tone:"positive"},partial:{label:"Partly measured",tone:"caution"},running:{label:"Measuring now",tone:"neutral"},queued:{label:"Measurement queued",tone:"neutral"},failed:{label:"Measurement failed",tone:"negative"},not_measured:{label:"Not measured",tone:"neutral"}},$={assigned:{label:"Matches this Property",tone:"positive"},sibling:{label:"Matches another Property",tone:"caution"},ownedUnmapped:{label:"Site URL not in a Property",tone:"caution"},external:{label:"External URL",tone:"neutral"},ambiguous:{label:"Matches multiple Properties",tone:"caution"},invalid:{label:"Invalid URL",tone:"negative"}};function F(s){return oe[s.reason]??"Not measured"}function L({metric:s,emphasis:n=!1}){if(s.state==="unavailable")return e.jsxs("span",{className:"inline-flex flex-col gap-0.5",children:[e.jsx("span",{className:n?"text-lg font-semibold text-secondary":"text-sm font-medium text-secondary",children:"Not measured"}),e.jsx("span",{className:"text-sm text-secondary",children:F(s)})]});const a=`${Math.round(s.value*100)}%`,d=s.numerator===void 0||s.denominator===void 0?null:`${s.numerator} of ${s.denominator}`;return e.jsxs("span",{className:"inline-flex flex-col gap-0.5 tabular-nums",children:[e.jsx("span",{className:n?"text-lg font-semibold text-heading":"text-sm font-medium text-primary",children:a}),d?e.jsx("span",{className:"text-xs text-muted",children:d}):null]})}function V(s,n,a){return ne({client:U,path:{name:s},query:{scope:"property",targetKey:n,queryClass:a}})}function O(s){return s?.properties.items.at(0)}function le({branded:s,nonBrand:n,brandedError:a,nonBrandError:d,onRetry:l}){const c=[{queryClass:"branded",row:s,isError:a},{queryClass:"non-brand",row:n,isError:d}];return e.jsxs("section",{"aria-labelledby":"property-brand-contrast",children:[e.jsx("div",{className:"section-head section-head-inline",children:e.jsxs("div",{children:[e.jsx("p",{className:"eyebrow eyebrow-soft",children:"The gap"}),e.jsxs("h2",{id:"property-brand-contrast",className:"text-base font-semibold text-heading",children:["Named versus not named",e.jsx(C,{text:"Branded questions already contain your name, so an answer engine has an easy path back to you. Non-brand questions describe the need instead, and that is the demand you have to earn. Each row is measured only over the questions assigned to this Property in that class; a class with no assigned question reads Not measured rather than 0%."})]})]})}),e.jsx("div",{className:"overflow-x-auto rounded-md border border-default",children:e.jsxs("table",{className:"evidence-table min-w-[560px]",children:[e.jsx("caption",{className:"sr-only",children:"Mention and citation coverage for this Property, split by question class"}),e.jsx("thead",{children:e.jsxs("tr",{children:[e.jsx("th",{children:"Question type"}),e.jsx("th",{children:"Mentioned in the answer"}),e.jsx("th",{children:"Cited as a source"})]})}),e.jsx("tbody",{children:c.map(({queryClass:r,row:x,isError:h})=>e.jsxs("tr",{children:[e.jsxs("td",{children:[e.jsx("span",{className:"block font-medium text-heading",children:o[r].headline}),e.jsx("span",{className:"mt-0.5 block text-xs text-muted",children:o[r].technical}),x&&h?e.jsxs("span",{className:"mt-2 flex flex-wrap items-center gap-2 text-sm text-caution",children:[e.jsx("span",{role:"status",children:"Refresh failed."}),e.jsxs(v,{type:"button",size:"sm",variant:"ghost",className:"h-11 px-3 text-sm md:h-11",onClick:()=>l(r),children:["Retry ",o[r].technical.toLocaleLowerCase()]})]}):null]}),x?e.jsxs(e.Fragment,{children:[e.jsx("td",{children:e.jsx(L,{metric:x.mentionCoverage,emphasis:!0})}),e.jsx("td",{children:e.jsx(L,{metric:x.citationCoverage,emphasis:!0})})]}):h?e.jsx("td",{colSpan:2,children:e.jsxs("div",{className:"flex flex-wrap items-center gap-3 text-sm text-secondary",children:[e.jsxs("span",{role:"alert",children:["Could not load ",o[r].technical.toLocaleLowerCase(),"."]}),e.jsxs(v,{type:"button",size:"sm",variant:"outline",className:"h-11 px-4 text-sm md:h-11",onClick:()=>l(r),children:["Retry ",o[r].technical.toLocaleLowerCase()]})]})}):e.jsxs(e.Fragment,{children:[e.jsx("td",{children:e.jsx("span",{className:"text-sm text-secondary",children:"Loading…"})}),e.jsx("td",{children:e.jsx("span",{className:"text-sm text-secondary",children:"Loading…"})})]})]},r))})]})})]})}function de({row:s,queryClass:n,isError:a}){return e.jsxs("section",{"aria-labelledby":"property-providers",className:"page-section-divider",children:[e.jsx("div",{className:"section-head section-head-inline",children:e.jsxs("div",{children:[e.jsx("p",{className:"eyebrow eyebrow-soft",children:"By answer engine"}),e.jsxs("h2",{id:"property-providers",className:"text-base font-semibold text-heading",children:["Which engines answer for this Property",e.jsx(C,{text:"Each row is measured over the questions that engine actually answered for this Property, so the rows are a split of the same population rather than parts that add up to the Property total. An engine that answered nothing for this Property is absent instead of shown at 0%."})]})]})}),s===void 0&&a?e.jsxs("p",{className:"text-sm text-secondary",children:["Details for ",o[n].technical.toLocaleLowerCase()," are unavailable. Retry that question type above."]}):s===void 0?e.jsx("p",{className:"text-sm text-secondary",children:"Loading…"}):s.providers.length===0?e.jsxs("p",{className:"text-sm text-secondary",children:["No answer engine has measured ",o[n].technical.toLocaleLowerCase()," for this Property.",s.mentionCoverage.state==="unavailable"?` ${F(s.mentionCoverage)}.`:""]}):e.jsx("div",{className:"overflow-x-auto rounded-md border border-default",children:e.jsxs("table",{className:"evidence-table min-w-[520px]",children:[e.jsx("caption",{className:"sr-only",children:"Per-engine mention and citation coverage"}),e.jsx("thead",{children:e.jsxs("tr",{children:[e.jsx("th",{children:"Engine"}),e.jsx("th",{children:"Mentioned"}),e.jsx("th",{children:"Cited"})]})}),e.jsx("tbody",{children:s.providers.map(d=>e.jsxs("tr",{children:[e.jsx("td",{className:"font-medium text-heading",children:d.provider}),e.jsx("td",{children:e.jsx(L,{metric:d.mentionCoverage})}),e.jsx("td",{children:e.jsx(L,{metric:d.citationCoverage})})]},d.provider))})]})})]})}function ce({questions:s,queryClass:n}){return e.jsxs("section",{"aria-labelledby":"property-questions",className:"page-section-divider",children:[e.jsxs("div",{className:"section-head section-head-inline",children:[e.jsxs("div",{children:[e.jsx("p",{className:"eyebrow eyebrow-soft",children:"Questions"}),e.jsxs("h2",{id:"property-questions",className:"text-base font-semibold text-heading",children:[o[n].technical," assigned to this Property"]})]}),e.jsxs("p",{className:"supporting-copy",children:[s.length," assigned"]})]}),s.length===0?e.jsxs("p",{className:"text-sm text-secondary",children:["No ",o[n].technical.toLocaleLowerCase()," are assigned. Add one in advanced measurement setup to measure this class."]}):e.jsx("div",{className:"overflow-x-auto rounded-md border border-default",children:e.jsxs("table",{className:"evidence-table min-w-[420px]",children:[e.jsx("caption",{className:"sr-only",children:"Questions assigned to this Property"}),e.jsx("thead",{children:e.jsx("tr",{children:e.jsx("th",{children:"Question"})})}),e.jsx("tbody",{children:s.map(a=>e.jsx("tr",{children:e.jsx("td",{className:"text-secondary",children:a})},a))})]})})]})}function he({urls:s}){return e.jsxs("section",{"aria-labelledby":"property-urls",className:"page-section-divider",children:[e.jsxs("div",{className:"section-head section-head-inline",children:[e.jsxs("div",{children:[e.jsx("p",{className:"eyebrow eyebrow-soft",children:"Pages"}),e.jsxs("h2",{id:"property-urls",className:"text-base font-semibold text-heading",children:["URLs that count as this Property",e.jsx(C,{text:"A cited source URL is credited to this Property when it matches one of these. The most specific matcher wins, so a URL covered by two Properties at the same specificity is flagged for review instead of being credited to either."})]})]}),e.jsxs("p",{className:"supporting-copy",children:[s.length," configured"]})]}),s.length===0?e.jsx("p",{className:"text-sm text-secondary",children:"No URLs are configured for this Property."}):e.jsx("div",{className:"overflow-x-auto rounded-md border border-default",children:e.jsxs("table",{className:"evidence-table min-w-[420px]",children:[e.jsx("caption",{className:"sr-only",children:"URL matchers configured for this Property"}),e.jsx("thead",{children:e.jsx("tr",{children:e.jsx("th",{children:"URL"})})}),e.jsx("tbody",{children:s.map(n=>e.jsx("tr",{children:e.jsx("td",{className:"break-all text-secondary",children:n})},n))})]})})]})}function ge(){const{projectName:s,targetKey:n}=J({strict:!1}),[a,d]=P.useState("non-brand"),l=s??"",c=n??"",r=!!l&&!!c,{canWrite:x}=Y(),h=A({...ee({client:U,path:{name:l}}),enabled:r}),p=A({...V(l,c,"branded"),enabled:r}),u=A({...V(l,c,"non-brand"),enabled:r}),S=O(p.data),k=O(u.data),j=a==="branded"?p.data:u.data,g=a==="branded"?S:k,q=(a==="branded"?p.isError:u.isError)&&g===void 0,I=j?.measurement.displayedRunId,f={client:U,path:{name:l},query:{targetKey:c,queryClass:a,limit:_,...I?{runId:I}:{}}},i=X({...se(f),enabled:r&&j!==void 0,initialPageParam:f,getNextPageParam:t=>t.evidence.nextCursor?{path:f.path,query:{...f.query,cursor:t.evidence.nextCursor}}:void 0}),R=h.data?.active??null,y=R?.plan.schemaVersion===2?R.plan:null,z=R!==null&&y===null,N=y?.targets.find(t=>t.stableKey===c)??null,D=P.useMemo(()=>{if(!y)return[];const t=new Map(y.querySnapshots.map(m=>[m.queryId,m.queryText]));return[...new Set(y.assignments.filter(m=>m.targetKey===c&&m.queryClass===a).flatMap(m=>{const w=t.get(m.queryId);return w===void 0?[]:[w]}))].sort((m,w)=>m.localeCompare(w))},[y,c,a]),K=P.useMemo(()=>N?.urlMatchers.map(re)??[],[N]),b=P.useMemo(()=>(i.data?.pages??[]).flatMap(t=>t.evidence.items),[i.data]),T=i.data?.pages[0]?.evidence.totalEstimate??b.length,W=i.data?.pages[0]?.measurement.state,M=e.jsxs(B,{to:"/projects/$projectName",params:{projectName:l},className:"inline-flex items-center gap-1 text-xs text-muted hover:text-strong",children:[e.jsx(ie,{className:"size-3.5","aria-hidden":"true"}),"Back to measurement overview"]});if(!r)return e.jsx("div",{className:"page-container",children:e.jsx("p",{className:"text-sm text-muted",children:"Missing project name or Property key in URL."})});if(!te("portfolio",ae()?.projectTabs))return e.jsx("div",{className:"page-container",children:e.jsx("p",{className:"text-sm text-muted",children:"This view is not available here."})});if(h.isPending&&!h.isError)return e.jsx("div",{className:"page-container",children:e.jsxs("div",{role:"status","aria-live":"polite",children:[e.jsx("span",{className:"sr-only",children:"Loading Property"}),e.jsx("div",{className:"h-32 animate-pulse rounded-md bg-surface-subtle","aria-hidden":"true"})]})});const G=h.isError&&h.data===void 0,H=p.isError&&p.data===void 0,Z=u.isError&&u.data===void 0;return G||H&&Z?e.jsxs("div",{className:"page-container space-y-3",children:[M,e.jsx("p",{role:"alert",className:"text-sm text-negative",children:"Could not load this Property."}),e.jsx(v,{type:"button",size:"sm",variant:"outline",className:"h-11 px-4 text-sm md:h-11",onClick:()=>{h.refetch(),p.refetch(),u.refetch()},children:"Try again"})]}):!y||!N?e.jsxs("div",{className:"page-container space-y-3",children:[M,e.jsx("p",{role:"status",className:"text-sm text-secondary",children:y?"This Property is not in the published setup. It may have been renamed or removed.":"A Property page needs a published advanced measurement setup. Republish setup from the project Portfolio tab."}),e.jsx(v,{asChild:!0,type:"button",variant:"outline",className:"h-11 px-4 text-sm md:h-11",children:e.jsx(B,{to:"/projects/$projectName/portfolio",params:{projectName:l},children:x?z?"Republish setup":"Open measurement setup":"View measurement setup"})})]}):e.jsxs("div",{className:"page-container space-y-8",children:[e.jsxs("div",{className:"page-header",children:[e.jsxs("div",{className:"page-header-left",children:[M,e.jsx("h1",{className:"page-title mt-2",children:N.label}),e.jsxs("p",{className:"page-subtitle",children:["Property in ",l]})]}),e.jsxs("div",{className:"page-header-right",children:[j?e.jsx(E,{tone:Q[j.measurement.state].tone,children:Q[j.measurement.state].label}):null,g&&g.flags>0?e.jsxs(E,{tone:"caution",children:[g.flags," flagged"]}):null]})]}),e.jsx(le,{branded:S,nonBrand:k,brandedError:p.isError,nonBrandError:u.isError,onRetry:t=>{t==="branded"?p.refetch():u.refetch()}}),j&&(j.measurement.state==="not_measured"||j.nextAction.kind==="run_measurement")?e.jsxs("section",{className:"flex flex-wrap items-center justify-between gap-3 border-y border-default py-4","aria-label":"Measurement next step",children:[e.jsx("p",{className:"text-sm text-secondary",children:x?"Run a measurement from the project overview to collect this Property’s coverage and source evidence.":"This Property needs a new measurement before coverage and source evidence are available."}),e.jsx(v,{asChild:!0,type:"button",className:"h-11 px-4 text-sm md:h-11",children:e.jsx(B,{to:"/projects/$projectName",params:{projectName:l},children:x?"Go to measurement overview":"View measurement overview"})})]}):null,e.jsxs("div",{className:"flex flex-wrap items-end gap-4 border-y border-default py-4",children:[e.jsxs("div",{className:"space-y-1",children:[e.jsx("label",{htmlFor:"property-query-class",className:"block text-sm font-medium text-heading",children:"Question type"}),e.jsxs("select",{id:"property-query-class",value:a,onChange:t=>d(t.target.value==="branded"?"branded":"non-brand"),className:"h-11 rounded-md border border-default bg-surface px-3 text-sm text-primary focus:outline-none focus:ring-2 focus:ring-mono-400",children:[e.jsx("option",{value:"non-brand",children:o["non-brand"].technical}),e.jsx("option",{value:"branded",children:o.branded.technical})]})]}),e.jsxs("p",{className:"supporting-copy",children:["Everything below is measured over ",o[a].technical.toLocaleLowerCase()," only."]})]}),e.jsx(de,{row:g,queryClass:a,isError:q}),e.jsx(ce,{questions:D,queryClass:a}),e.jsx(he,{urls:K}),e.jsxs("section",{"aria-labelledby":"property-evidence",className:"page-section-divider",children:[e.jsxs("div",{className:"section-head section-head-inline",children:[e.jsxs("div",{children:[e.jsx("p",{className:"eyebrow eyebrow-soft",children:"Evidence"}),e.jsxs("h2",{id:"property-evidence",className:"text-base font-semibold text-heading",children:["Source URLs the engines used",e.jsx(C,{text:"Every source URL an answer engine returned for the questions assigned to this Property in the displayed measurement. A row matching this Property is what a citation is counted from; the other classifications are shown so a miss can be explained rather than guessed at."})]})]}),b.length>0?e.jsxs("p",{className:"supporting-copy",children:[b.length," of ",T]}):null]}),q?e.jsxs("p",{className:"text-sm text-secondary",children:["Evidence for ",o[a].technical.toLocaleLowerCase()," is unavailable. Retry that question type above."]}):i.isPending&&b.length===0?e.jsx("p",{className:"text-sm text-secondary",children:"Loading evidence…"}):i.isError&&b.length===0?e.jsxs("div",{className:"flex flex-wrap items-center gap-3 text-sm text-secondary",children:[e.jsx("span",{role:"alert",children:"Evidence could not be loaded."}),e.jsx(v,{type:"button",size:"sm",variant:"outline",className:"h-11 px-4 text-sm md:h-11",onClick:()=>{i.refetch()},children:"Retry evidence"})]}):W==="not_measured"?e.jsx("p",{className:"text-sm text-secondary",children:"Not measured yet. Run a measurement to collect source evidence for this Property."}):b.length===0?e.jsx("p",{className:"text-sm text-secondary",children:"No source evidence matched this Property in the displayed measurement."}):e.jsxs(e.Fragment,{children:[e.jsx("div",{className:"overflow-x-auto rounded-md border border-default",children:e.jsxs("table",{className:"evidence-table min-w-[720px]",children:[e.jsx("caption",{className:"sr-only",children:"Source evidence for this Property"}),e.jsx("thead",{children:e.jsxs("tr",{children:[e.jsx("th",{children:"Match"}),e.jsx("th",{children:"Question"}),e.jsx("th",{children:"URL"})]})}),e.jsx("tbody",{children:b.map(t=>e.jsxs("tr",{children:[e.jsx("td",{children:e.jsxs("span",{className:"flex flex-wrap items-center gap-1",children:[e.jsx(E,{tone:$[t.classification].tone,children:$[t.classification].label}),t.historical||t.bridged?e.jsx(E,{tone:"caution",children:"Historical"}):null]})}),e.jsxs("td",{className:"text-secondary",children:[e.jsx("span",{className:"block",children:t.queryText}),e.jsx("span",{className:"mt-1 block text-xs text-muted",children:[t.provider,t.location].filter(Boolean).join(" · ")})]}),e.jsx("td",{className:"break-all text-secondary",children:t.sourceUrl})]},`${t.expectedSlotId}:${t.usageEdgeId}:${t.sourceUrl}`))})]})}),i.hasNextPage?e.jsxs("div",{className:"mt-2 flex flex-wrap items-center gap-3 text-sm text-secondary",children:[e.jsxs("span",{children:["Showing ",b.length," of ",T]}),i.isFetchNextPageError?e.jsx("span",{role:"alert",children:"Could not load more evidence."}):null,e.jsx(v,{size:"sm",variant:"outline",className:"h-11 px-4 text-sm md:h-11",disabled:i.isFetchingNextPage,onClick:()=>{i.fetchNextPage()},children:i.isFetchingNextPage?"Loading…":i.isFetchNextPageError?"Retry more evidence":`Show ${_} more`})]}):null]})]})]})}export{ge as MeasurementPropertyPage};
|