@canonry/canonry 5.9.0 → 5.11.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 (36) hide show
  1. package/assets/agent-workspace/skills/aero/SKILL.md +13 -6
  2. package/assets/agent-workspace/skills/canonry/references/canonry-cli.md +36 -9
  3. package/assets/assets/{AuditHistoryPanel-DumM4n44.js → AuditHistoryPanel-Cq8CoZV5.js} +1 -1
  4. package/assets/assets/{BacklinksPage-DHW-aDYf.js → BacklinksPage-B5_QeuXd.js} +1 -1
  5. package/assets/assets/{HistoryPage-DJgCpcmY.js → HistoryPage-Foj5--rM.js} +1 -1
  6. package/assets/assets/MeasurementPropertyPage-2t8jVNFL.js +1 -0
  7. package/assets/assets/{ProjectPage-BKZyG1S3.js → ProjectPage-By0UYm8r.js} +5 -5
  8. package/assets/assets/{RunRow-plH2LI7o.js → RunRow-CbTtzDK5.js} +1 -1
  9. package/assets/assets/{RunsPage-JCSy7P9I.js → RunsPage-Cjv7YiXR.js} +1 -1
  10. package/assets/assets/{SettingsPage-B8KXT4YK.js → SettingsPage-DIQgJQ8Y.js} +1 -1
  11. package/assets/assets/SiteHealthSection-CUNhD0To.js +4 -0
  12. package/assets/assets/{TrafficPage-BYLDNQ1A.js → TrafficPage-abuZqCEU.js} +3 -3
  13. package/assets/assets/{TrafficSourceDetailPage-CxseBpYr.js → TrafficSourceDetailPage-B-zVt0Sa.js} +1 -1
  14. package/assets/assets/{extract-error-message-Dv5fwiqy.js → extract-error-message-C5-X8IcG.js} +1 -1
  15. package/assets/assets/index-Dzg_siX8.js +86 -0
  16. package/assets/assets/{index-neNKCg78.css → index-EJC8PSbh.css} +1 -1
  17. package/assets/assets/{react-sigma_core.esm.min-C8381RhL.js → react-sigma_core.esm.min-Ybxr8Ybd.js} +1 -1
  18. package/assets/assets/v2-overview-adapter-BMOnF8IE.js +1 -0
  19. package/assets/assets/{vendor-lucide-CneDbhOr.js → vendor-lucide-N6vOpZmh.js} +1 -1
  20. package/assets/index.html +3 -3
  21. package/dist/{chunk-R4COV5KR.js → chunk-JNU6GLAV.js} +2 -2
  22. package/dist/{chunk-S4DBS5DP.js → chunk-JW5DCORY.js} +188 -52
  23. package/dist/{chunk-D3DKDTXP.js → chunk-MQMJJZ6W.js} +114 -0
  24. package/dist/{chunk-LR7BVM53.js → chunk-NV3X6O5P.js} +2 -2
  25. package/dist/{chunk-5E4ASNU4.js → chunk-SMYBGUVV.js} +2089 -1903
  26. package/dist/{chunk-WTYVSCMP.js → chunk-UYSTNPTX.js} +589 -351
  27. package/dist/cli.js +136 -15
  28. package/dist/{demo-server-WRVVNKLS.js → demo-server-76IZBMJ3.js} +3 -3
  29. package/dist/index.js +5 -5
  30. package/dist/{intelligence-service-4XMMO3JK.js → intelligence-service-KF5WWPGR.js} +2 -2
  31. package/dist/mcp.js +3 -3
  32. package/package.json +11 -11
  33. package/assets/assets/MeasurementPropertyPage-CblC7DUV.js +0 -1
  34. package/assets/assets/SiteHealthSection-06pNjngi.js +0 -4
  35. package/assets/assets/index-2Ldc0Hq4.js +0 -86
  36. package/assets/assets/v2-overview-adapter-BQD1Ap8K.js +0 -1
package/dist/cli.js CHANGED
@@ -35,11 +35,11 @@ import {
35
35
  trackCliCommandFinished,
36
36
  trackEvent,
37
37
  waitForServerRuntimeStartup
38
- } from "./chunk-WTYVSCMP.js";
38
+ } from "./chunk-UYSTNPTX.js";
39
39
  import {
40
40
  autoSyncSkills,
41
41
  formatAutoSyncNotice
42
- } from "./chunk-LR7BVM53.js";
42
+ } from "./chunk-NV3X6O5P.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-S4DBS5DP.js";
69
+ } from "./chunk-JW5DCORY.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-R4COV5KR.js";
75
+ import "./chunk-JNU6GLAV.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-5E4ASNU4.js";
91
+ } from "./chunk-SMYBGUVV.js";
92
92
  import {
93
93
  AdsDeliverySnapshotStatuses,
94
94
  AdsHistoricalCampaignRollupStatuses,
@@ -123,6 +123,9 @@ import {
123
123
  adsGeoSearchQuerySchema,
124
124
  adsImageUploadRequestSchema,
125
125
  adsPauseRequestSchema,
126
+ agentConversationListQuerySchema,
127
+ agentTurnLimitsSchema,
128
+ agentViewContextSchema,
126
129
  backlinkSourceSchema,
127
130
  buildModelChangeNotice,
128
131
  canonicalizeGtmAccountId,
@@ -170,7 +173,7 @@ import {
170
173
  snapshotProviderModeSchema,
171
174
  visibilityReportRequestSchema,
172
175
  winnabilityClassSchema
173
- } from "./chunk-D3DKDTXP.js";
176
+ } from "./chunk-MQMJJZ6W.js";
174
177
 
175
178
  // src/cli.ts
176
179
  import { pathToFileURL } from "url";
@@ -435,7 +438,7 @@ function parseDemoTrustedProxies(values) {
435
438
  async function demoCommand(options) {
436
439
  const { host, port } = parseDemoListenOptions(options);
437
440
  const trustProxy = parseDemoTrustedProxies(options.trustProxy);
438
- const { createDemoServer } = await import("./demo-server-WRVVNKLS.js");
441
+ const { createDemoServer } = await import("./demo-server-76IZBMJ3.js");
439
442
  const app = await createDemoServer({ trustProxy });
440
443
  let stopping = false;
441
444
  const stop = () => {
@@ -12941,18 +12944,33 @@ async function listSchedules(project, format) {
12941
12944
  function getClient24() {
12942
12945
  return createApiClient();
12943
12946
  }
12947
+ async function readCurrentSchedule(client, project, kind) {
12948
+ try {
12949
+ return await client.getSchedule(project, kind);
12950
+ } catch {
12951
+ return void 0;
12952
+ }
12953
+ }
12944
12954
  async function setSchedule(project, opts) {
12945
12955
  const client = getClient24();
12956
+ const current = await readCurrentSchedule(client, project, opts.kind);
12946
12957
  const body = {};
12947
12958
  if (opts.kind) body.kind = opts.kind;
12948
- if (opts.sourceId) body.sourceId = opts.sourceId;
12949
- if (opts.preset) body.preset = opts.preset;
12950
- if (opts.cron) body.cron = opts.cron;
12959
+ else if (current) body.kind = current.kind;
12951
12960
  if (opts.everyDays || opts.startDate || opts.at) {
12952
12961
  body.recurrence = { everyDays: Number(opts.everyDays), startDate: opts.startDate, time: opts.at };
12953
- }
12962
+ } else if (opts.preset) body.preset = opts.preset;
12963
+ else if (opts.cron) body.cron = opts.cron;
12964
+ else if (current?.recurrence) body.recurrence = current.recurrence;
12965
+ else if (current?.preset) body.preset = current.preset;
12966
+ else if (current?.cronExpr) body.cron = current.cronExpr;
12954
12967
  if (opts.timezone) body.timezone = opts.timezone;
12968
+ else if (current) body.timezone = current.timezone;
12955
12969
  if (opts.providers?.length) body.providers = opts.providers;
12970
+ else if (current?.providers.length) body.providers = current.providers;
12971
+ if (opts.sourceId) body.sourceId = opts.sourceId;
12972
+ else if (current?.sourceId) body.sourceId = current.sourceId;
12973
+ if (current) body.expectedUpdatedAt = current.updatedAt;
12956
12974
  const result = await client.putSchedule(project, body);
12957
12975
  if (isMachineFormat(opts.format)) {
12958
12976
  console.log(JSON.stringify(result, null, 2));
@@ -13012,6 +13030,29 @@ async function removeSchedule(project, format, kind) {
13012
13030
  }
13013
13031
  console.log(`Schedule removed for "${project}" (kind: ${resolvedKind})`);
13014
13032
  }
13033
+ function formatNextRun(nextRunAt, timezone) {
13034
+ const at = new Date(nextRunAt);
13035
+ if (Number.isNaN(at.getTime())) return nextRunAt;
13036
+ try {
13037
+ const parts = new Intl.DateTimeFormat("en-CA", {
13038
+ timeZone: timezone,
13039
+ year: "numeric",
13040
+ month: "2-digit",
13041
+ day: "2-digit",
13042
+ hour: "2-digit",
13043
+ minute: "2-digit",
13044
+ hour12: false,
13045
+ timeZoneName: "longOffset"
13046
+ }).formatToParts(at);
13047
+ const get = (type) => parts.find((part) => part.type === type)?.value ?? "";
13048
+ const offset = get("timeZoneName").replace("GMT", "") || "+00:00";
13049
+ const local = `${get("year")}-${get("month")}-${get("day")} ${get("hour")}:${get("minute")}`;
13050
+ const utc = `${String(at.getUTCHours()).padStart(2, "0")}:${String(at.getUTCMinutes()).padStart(2, "0")}Z`;
13051
+ return `${local} (${offset}) / ${utc}`;
13052
+ } catch {
13053
+ return nextRunAt;
13054
+ }
13055
+ }
13015
13056
  function printSchedule(s) {
13016
13057
  console.log(` Kind: ${s.kind}`);
13017
13058
  if (s.preset) {
@@ -13036,7 +13077,7 @@ function printSchedule(s) {
13036
13077
  console.log(` Last run: ${s.lastRunAt}`);
13037
13078
  }
13038
13079
  if (s.nextRunAt) {
13039
- console.log(` Next run: ${s.nextRunAt}`);
13080
+ console.log(` Next run: ${formatNextRun(s.nextRunAt, s.timezone)}`);
13040
13081
  }
13041
13082
  }
13042
13083
 
@@ -18459,6 +18500,43 @@ var WORDPRESS_CLI_COMMANDS = [
18459
18500
  }
18460
18501
  ];
18461
18502
 
18503
+ // src/commands/agent-conversations.ts
18504
+ import { randomUUID as randomUUID2 } from "crypto";
18505
+ async function agentConversations(opts) {
18506
+ try {
18507
+ const client = createApiClient();
18508
+ const result = await (() => {
18509
+ switch (opts.action) {
18510
+ case "list":
18511
+ return client.listAgentConversations(opts.project, { offset: opts.offset, limit: opts.limit });
18512
+ case "new":
18513
+ return client.createAgentConversation(opts.project, opts.id ?? randomUUID2());
18514
+ case "show":
18515
+ return client.getAgentConversation(opts.project, opts.id);
18516
+ case "resume":
18517
+ return client.resumeAgentConversation(opts.project, opts.id);
18518
+ case "delete":
18519
+ return client.deleteAgentConversation(opts.project, opts.id);
18520
+ }
18521
+ })();
18522
+ if (isMachineFormat(opts.format)) {
18523
+ console.log(JSON.stringify(result, null, 2));
18524
+ return;
18525
+ }
18526
+ if ("conversations" in result) {
18527
+ if (!result.conversations.length) console.log("No Aero conversations yet.");
18528
+ for (const conversation of result.conversations) console.log(`${conversation.active ? "* " : " "}${conversation.id} ${conversation.title} ${conversation.updatedAt}`);
18529
+ if (result.nextOffset !== null) console.log(`More conversations: --offset ${result.nextOffset}`);
18530
+ } else if ("messages" in result) {
18531
+ console.log(`${result.title} \u2014 ${result.id}${result.active ? " (current)" : ""}`);
18532
+ for (const message of result.messages) console.log(`[${message.role}] ${typeof message.content === "string" ? message.content : JSON.stringify(message.content)}`);
18533
+ } else console.log(`Conversation deleted: ${result.id}. Shared project notes kept.`);
18534
+ } catch (error) {
18535
+ printCliError(error, opts.format);
18536
+ process.exitCode = error instanceof CliError ? error.exitCode : 2;
18537
+ }
18538
+ }
18539
+
18462
18540
  // src/agent-webhook.ts
18463
18541
  var AGENT_WEBHOOK_EVENTS = ["run.completed", "insight.critical", "insight.high", "citation.gained"];
18464
18542
 
@@ -18520,15 +18598,19 @@ async function agentAsk(opts) {
18520
18598
  const onSigint = () => controller.abort();
18521
18599
  process.on("SIGINT", onSigint);
18522
18600
  let sawStreamError = false;
18601
+ let streamClosed = false;
18523
18602
  try {
18524
18603
  const client = createApiClient();
18525
18604
  const res = await client.streamPost(
18526
18605
  `/projects/${encodeURIComponent(opts.project)}/agent/prompt`,
18527
18606
  {
18528
18607
  prompt: opts.prompt,
18608
+ ...opts.conversationId ? { conversationId: opts.conversationId } : {},
18529
18609
  provider: opts.provider,
18530
18610
  modelId: opts.modelId,
18531
18611
  scope: opts.scope ?? "all",
18612
+ ...opts.context ? { context: opts.context } : {},
18613
+ ...opts.limits ? { limits: opts.limits } : {},
18532
18614
  ...opts.profile ? { profile: opts.profile } : {}
18533
18615
  },
18534
18616
  controller.signal
@@ -18541,14 +18623,18 @@ async function agentAsk(opts) {
18541
18623
  });
18542
18624
  }
18543
18625
  for await (const event of parseSse(res.body)) {
18626
+ if (event.type === "stream_close") streamClosed = true;
18544
18627
  renderEvent(event, isJson);
18545
18628
  if (event.type === "message_end" && event.message.role === "assistant") {
18546
18629
  const msg = event.message;
18547
18630
  if (msg.stopReason === "error" || msg.errorMessage) sawStreamError = true;
18631
+ } else if (event.type === "aero_turn_status" && event.status?.reason !== "completed") {
18632
+ sawStreamError = true;
18548
18633
  } else if (event.type === "error") {
18549
18634
  sawStreamError = true;
18550
18635
  }
18551
18636
  }
18637
+ if (!streamClosed) throw new CliError({ code: "API_ERROR", message: "Connection ended before Aero finished. Inspect the transcript before retrying.", exitCode: EXIT_SYSTEM_ERROR });
18552
18638
  if (sawStreamError) process.exitCode = EXIT_SYSTEM_ERROR;
18553
18639
  } catch (err) {
18554
18640
  printCliError(err, format);
@@ -18613,6 +18699,9 @@ function renderEvent(event, isJson) {
18613
18699
  }
18614
18700
  break;
18615
18701
  }
18702
+ case "aero_turn_status":
18703
+ if (event.status && event.status.reason !== "completed") console.error(`Aero stopped: ${event.status.reason} (${event.status.toolCalls} tool calls).`);
18704
+ break;
18616
18705
  case "error":
18617
18706
  console.error(`Agent stream error: ${event.message}`);
18618
18707
  break;
@@ -18793,17 +18882,34 @@ async function agentMemoryForget(opts) {
18793
18882
  // src/cli-commands/agent.ts
18794
18883
  var AGENT_ASK_SCOPES = ["all", "read-only"];
18795
18884
  var AGENT_CLI_COMMANDS = [
18885
+ ...["list", "new", "show", "resume", "delete"].map((action) => ({
18886
+ path: ["agent", "conversations", action],
18887
+ usage: `canonry agent conversations ${action} <project> [--id <conversation-id>] [--offset <n>] [--limit <n>] [--format json]`,
18888
+ options: { id: stringOption(), offset: stringOption(), limit: stringOption() },
18889
+ run: async (input) => {
18890
+ const usage = `canonry agent conversations ${action} <project>`;
18891
+ const project = requireProject(input, `agent.conversations.${action}`, usage);
18892
+ const id = action === "new" || action === "list" ? getString(input.values, "id") : requireStringOption(input, "id", { command: `agent.conversations.${action}`, usage, message: "--id is required" });
18893
+ const query = agentConversationListQuerySchema.safeParse({ offset: getString(input.values, "offset"), limit: getString(input.values, "limit") });
18894
+ if (!query.success) throw usageError("Invalid history pagination", { message: query.error.message });
18895
+ await agentConversations({ project, action, id, ...query.data, format: input.format });
18896
+ }
18897
+ })),
18796
18898
  {
18797
18899
  path: ["agent", "ask"],
18798
- usage: `canonry agent ask <project> "<prompt>" [--provider ${listAgentProviders().join("|")}] [--model <id>] [--scope all|read-only] [--profile default|ads-operator] [--format json]`,
18900
+ usage: `canonry agent ask <project> "<prompt>" [--provider ${listAgentProviders().join("|")}] [--model <id>] [--scope all|read-only] [--profile default|ads-operator] [--context <json>] [--conversation <id>] [--max-tool-calls <n>] [--timeout-ms <ms>] [--format json]`,
18799
18901
  options: {
18800
18902
  provider: stringOption(),
18801
18903
  model: stringOption(),
18802
18904
  scope: stringOption(),
18803
- profile: stringOption()
18905
+ profile: stringOption(),
18906
+ context: stringOption(),
18907
+ conversation: stringOption(),
18908
+ "max-tool-calls": stringOption(),
18909
+ "timeout-ms": stringOption()
18804
18910
  },
18805
18911
  run: async (input) => {
18806
- const usage = `canonry agent ask <project> "<prompt>" [--provider ${listAgentProviders().join("|")}] [--model <id>] [--scope all|read-only] [--profile default|ads-operator] [--format json]`;
18912
+ const usage = `canonry agent ask <project> "<prompt>" [--provider ${listAgentProviders().join("|")}] [--model <id>] [--scope all|read-only] [--profile default|ads-operator] [--context <json>] [--conversation <id>] [--max-tool-calls <n>] [--timeout-ms <ms>] [--format json]`;
18807
18913
  const project = requireProject(input, "agent.ask", usage);
18808
18914
  const prompt2 = input.positionals.slice(1).join(" ").trim();
18809
18915
  if (!prompt2) {
@@ -18855,7 +18961,22 @@ Usage: ${usage}`, {
18855
18961
  }
18856
18962
  });
18857
18963
  }
18964
+ let context;
18965
+ try {
18966
+ const rawContext = getString(input.values, "context");
18967
+ if (rawContext) context = agentViewContextSchema.parse(JSON.parse(rawContext));
18968
+ } catch (error) {
18969
+ throw usageError(`Invalid --context: ${describeError(error)}`, { message: "Invalid Aero view context" });
18970
+ }
18971
+ const parsedLimits = agentTurnLimitsSchema.safeParse({
18972
+ ...getString(input.values, "max-tool-calls") ? { maxToolCalls: Number(getString(input.values, "max-tool-calls")) } : {},
18973
+ ...getString(input.values, "timeout-ms") ? { timeoutMs: Number(getString(input.values, "timeout-ms")) } : {}
18974
+ });
18975
+ if (!parsedLimits.success) throw usageError("Invalid Aero turn limits", { message: parsedLimits.error.message });
18858
18976
  await agentAsk({
18977
+ context,
18978
+ conversationId: getString(input.values, "conversation"),
18979
+ limits: parsedLimits.data,
18859
18980
  project,
18860
18981
  prompt: prompt2,
18861
18982
  provider: coerceAgentProvider(providerInput),
@@ -4,7 +4,7 @@ import {
4
4
  import {
5
5
  layoutSiteCrawlGraphInput,
6
6
  persistSiteCrawlGraphLayout
7
- } from "./chunk-R4COV5KR.js";
7
+ } from "./chunk-JNU6GLAV.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-5E4ASNU4.js";
86
+ } from "./chunk-SMYBGUVV.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-D3DKDTXP.js";
107
+ } from "./chunk-MQMJJZ6W.js";
108
108
 
109
109
  // src/demo-server.ts
110
110
  import { dirname, join as join2 } from "path";
package/dist/index.js CHANGED
@@ -3,14 +3,14 @@ import {
3
3
  createGoogleMarketingCredentialStore,
4
4
  createGoogleMarketingRuntime,
5
5
  createServer
6
- } from "./chunk-WTYVSCMP.js";
6
+ } from "./chunk-UYSTNPTX.js";
7
7
  import {
8
8
  loadConfig
9
- } from "./chunk-S4DBS5DP.js";
10
- import "./chunk-R4COV5KR.js";
9
+ } from "./chunk-JW5DCORY.js";
10
+ import "./chunk-JNU6GLAV.js";
11
11
  import "./chunk-AOJU5LKX.js";
12
- import "./chunk-5E4ASNU4.js";
13
- import "./chunk-D3DKDTXP.js";
12
+ import "./chunk-SMYBGUVV.js";
13
+ import "./chunk-MQMJJZ6W.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-5E4ASNU4.js";
5
- import "./chunk-D3DKDTXP.js";
4
+ } from "./chunk-SMYBGUVV.js";
5
+ import "./chunk-MQMJJZ6W.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-LR7BVM53.js";
3
+ } from "./chunk-NV3X6O5P.js";
4
4
  import {
5
5
  createApiClient,
6
6
  createCanonryMcpServer
7
- } from "./chunk-S4DBS5DP.js";
7
+ } from "./chunk-JW5DCORY.js";
8
8
  import "./chunk-AOJU5LKX.js";
9
9
  import {
10
10
  isReadOnlyKey,
11
11
  updateCheckEnvOptOut
12
- } from "./chunk-D3DKDTXP.js";
12
+ } from "./chunk-MQMJJZ6W.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.9.0",
3
+ "version": "5.11.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": [
@@ -88,30 +88,30 @@
88
88
  "tsx": "^4.19.0",
89
89
  "@ainyc/canonry-web": "0.0.0",
90
90
  "@ainyc/canonry-api-routes": "0.0.0",
91
+ "@ainyc/canonry-api-client": "0.0.0",
91
92
  "@ainyc/canonry-config": "0.0.0",
92
93
  "@ainyc/canonry-contracts": "0.0.0",
93
- "@ainyc/canonry-api-client": "0.0.0",
94
94
  "@ainyc/canonry-db": "0.0.0",
95
+ "@ainyc/canonry-integration-bing": "0.0.0",
95
96
  "@ainyc/canonry-integration-cloud-run": "0.0.0",
96
97
  "@ainyc/canonry-integration-cloudflare-queue": "0.0.0",
97
98
  "@ainyc/canonry-integration-cloudflare-worker": "0.0.0",
98
99
  "@ainyc/canonry-integration-commoncrawl": "0.0.0",
100
+ "@ainyc/canonry-integration-google-ads": "0.0.0",
99
101
  "@ainyc/canonry-integration-google": "0.0.0",
100
- "@ainyc/canonry-integration-google-places": "0.0.0",
101
102
  "@ainyc/canonry-integration-google-business-profile": "0.0.0",
102
- "@ainyc/canonry-integration-bing": "0.0.0",
103
- "@ainyc/canonry-integration-openai-ads": "0.0.0",
104
- "@ainyc/canonry-integration-google-ads": "0.0.0",
103
+ "@ainyc/canonry-integration-google-places": "0.0.0",
105
104
  "@ainyc/canonry-integration-google-tag-manager": "0.0.0",
105
+ "@ainyc/canonry-integration-openai-ads": "0.0.0",
106
+ "@ainyc/canonry-integration-wordpress": "0.0.0",
106
107
  "@ainyc/canonry-integration-traffic": "0.0.0",
108
+ "@ainyc/canonry-provider-claude": "0.0.0",
107
109
  "@ainyc/canonry-intelligence": "0.0.0",
108
- "@ainyc/canonry-integration-wordpress": "0.0.0",
109
110
  "@ainyc/canonry-provider-cdp": "0.0.0",
110
- "@ainyc/canonry-provider-claude": "0.0.0",
111
- "@ainyc/canonry-provider-gemini": "0.0.0",
112
- "@ainyc/canonry-provider-perplexity": "0.0.0",
111
+ "@ainyc/canonry-provider-openai": "0.0.0",
113
112
  "@ainyc/canonry-provider-local": "0.0.0",
114
- "@ainyc/canonry-provider-openai": "0.0.0"
113
+ "@ainyc/canonry-provider-perplexity": "0.0.0",
114
+ "@ainyc/canonry-provider-gemini": "0.0.0"
115
115
  },
116
116
  "scripts": {
117
117
  "build": "pnpm run build:cli && pnpm run build:web",
@@ -1 +0,0 @@
1
- import{D as fe,k as Ne,l as we,r as b,u as L,C as Pe,j as e,L as T}from"./vendor-tanstack-ZXXkndVj.js";import{e5 as Ce,dI as Ee,dG as Le,x as Me,dX as Se,f7 as Ae,j as M,f8 as Re,B as g,I as P,T as w,az as ae,aA as ne,f9 as ke,fa as qe,fb as Te,A as Ie}from"./index-2Ldc0Hq4.js";import{j as Ue,o as Be}from"./ChartPrimitives-BQC2VH0O.js";import{p as $e,b as K,g as _e,f as z,a as ce,M as Oe,A as Ve}from"./v2-overview-adapter-BQD1Ap8K.js";import{Y as Qe}from"./vendor-lucide-CneDbhOr.js";import"./vendor-radix-twS1M3FF.js";import"./vendor-recharts-llkUFBGR.js";import"./vendor-markdown-B4giJcws.js";import"./vendor-yaml-GWJz5H2G.js";const re=50,p={branded:{headline:"When they know your name",technical:"Branded queries"},"non-brand":{headline:"When they don't",technical:"Non-brand queries"}},Fe={plan_v1:"Setup update required",no_completed_run:"No completed measurement yet",no_population:"No queries of this type are assigned",evidence_incomplete:"Source evidence is incomplete",not_applicable:"Not applicable for this Property"},ie={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"}},oe={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 Ke(s){return[...s].sort((t,a)=>+(a.classification==="assigned")-+(t.classification==="assigned"))}function ze(s){return`${s.expectedSlotId}:${s.usageEdgeId}`}function He({row:s}){return s.mentioned===null?e.jsxs("span",{className:"inline-flex flex-col items-start gap-0.5",children:[e.jsx(w,{tone:"neutral",children:"Not measured"}),e.jsx("span",{className:"text-xs text-muted",children:"No mention signal for this Property"})]}):e.jsx(w,{tone:s.mentioned?"positive":"neutral",children:s.mentioned?"Mentioned":"Not mentioned"})}const De="—";function We({row:s}){return s.cited===null?e.jsxs("span",{className:"inline-flex flex-col items-start gap-0.5",children:[e.jsx(w,{tone:"neutral",children:"Not measured"}),e.jsx("span",{className:"text-xs text-muted",children:"Sources were not fully captured"})]}):e.jsx(w,{tone:s.cited?"positive":"neutral",children:s.cited?"Cited":"Not cited"})}function Ge({row:s}){return s.cited===null&&s.sources.length===0?e.jsx("p",{className:"py-2 text-sm text-secondary",children:"The sources for this answer were not fully captured, so none can be shown."}):s.sources.length===0?e.jsx("p",{className:"py-2 text-sm text-secondary",children:"This answer returned no source URLs at all."}):e.jsxs("details",{className:"mt-2","data-answer-sources":!0,children:[e.jsxs("summary",{className:"min-h-11 cursor-pointer py-3 text-sm text-secondary focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-mono-400",children:[ce," (",s.sources.length,")"]}),e.jsx("div",{className:"overflow-x-auto",children:e.jsxs("table",{className:"evidence-table min-w-[420px]",children:[e.jsxs("caption",{className:"sr-only",children:["Source URLs for ",s.queryText]}),e.jsx("thead",{children:e.jsxs("tr",{children:[e.jsx("th",{children:"Match"}),e.jsx("th",{children:"URL"})]})}),e.jsx("tbody",{children:Ke(s.sources).map(t=>{const a=Ie(t.sourceUrl);return e.jsxs("tr",{children:[e.jsx("td",{children:e.jsx(w,{tone:oe[t.classification].tone,children:oe[t.classification].label})}),e.jsx("td",{className:"break-all text-secondary",children:a?e.jsx("a",{href:a,target:"_blank",rel:"noopener noreferrer",className:"text-link underline",children:t.sourceUrl}):t.sourceUrl})]},t.sourceUrl)})})]})})]})}function Ye({project:s,targetKey:t,row:a}){const r=L({...Te({client:M,path:{name:s},query:{targetKey:t,resultId:a.observationId}})});if(r.isPending)return e.jsx("p",{className:"py-2 text-sm text-secondary",role:"status","aria-live":"polite",children:"Loading the answer…"});if(r.isError)return e.jsx("p",{className:"py-2 text-sm text-secondary",role:"alert",children:"Could not load this answer."});const o=r.data?.answer;return o==null||o.trim()===""?e.jsx("p",{className:"py-2 text-sm text-secondary",children:"This answer was measured, but its text was not stored."}):e.jsx("div",{className:"py-2",children:e.jsx(Ve,{headingLevel:4,copyable:!0,children:o})})}function U(s){return Fe[s.reason]??"Not measured"}function I({metric:s,emphasis:t=!1}){if(s.state==="unavailable")return e.jsxs("span",{className:"inline-flex flex-col gap-0.5",children:[e.jsx("span",{className:t?"text-lg font-semibold text-secondary":"text-sm font-medium text-secondary",children:"Not measured"}),e.jsx("span",{className:"text-sm text-secondary",children:U(s)})]});const a=`${Math.round(s.value*100)}%`,r=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:t?"text-lg font-semibold text-heading":"text-sm font-medium text-primary",children:a}),r?e.jsx("span",{className:"text-xs text-muted",children:r}):null]})}function le(s,t,a){return ke({client:M,path:{name:s},query:{scope:"property",targetKey:t,queryClass:a}})}function de(s){return s?.properties.items.at(0)}function Xe({measuredAt:s,unmeasuredReason:t,queryClass:a}){const r=s===void 0?null:s===null?"No completed sweep yet":`Measured ${Ue(Be(s))}`;return r===null&&t===void 0?null:e.jsxs("p",{className:"supporting-copy",children:[[r,t].filter(Boolean).join(" · "),r!==null&&t===void 0?` · ${p[a].technical.toLocaleLowerCase()} only`:""]})}function Ze({project:s,groups:t}){return t.length===0?null:e.jsxs("section",{"aria-labelledby":"property-market",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:"Competitive comparison"}),e.jsxs("h2",{id:"property-market",className:"text-base font-semibold text-heading",children:["Measured at the market level",e.jsx(P,{text:"Competitors are attached to a market rather than to a single Property, because one building has nobody to be compared against. Share of voice and competitor pressure are reported for the market this Property sits in."})]})]}),e.jsx(g,{asChild:!0,type:"button",size:"sm",variant:"outline",children:e.jsx(T,{to:"/projects/$projectName",params:{projectName:s},search:a=>K(z(a),{measurementScope:"project"}),children:"Open measurement overview"})})]}),e.jsx("ul",{className:"flex flex-wrap gap-2",children:t.map(a=>e.jsxs("li",{className:"rounded-md border border-default px-3 py-1.5 text-sm text-strong",children:[a.label,e.jsxs("span",{className:"ml-2 text-xs text-muted",children:[a.competitors.length," ",a.competitors.length===1?"competitor":"competitors"]})]},a.stableKey))})]})}function q({label:s,metric:t,failed:a=!1}){if(t===void 0)return e.jsxs("div",{className:"aeo-hero-row",children:[e.jsx("p",{className:"aeo-hero-row-label",children:s}),e.jsx("p",{className:"aeo-hero-row-value text-base font-semibold text-secondary",children:a?"Unavailable":"…"}),a?e.jsx("div",{}):e.jsx("div",{className:"aeo-hero-row-bar","aria-hidden":"true"}),e.jsx("p",{className:"aeo-hero-row-detail",children:a?"Could not be loaded":"Loading"})]});if(t.state==="unavailable"){const j=U(t);return e.jsxs("div",{className:"aeo-hero-row",children:[e.jsx("p",{className:"aeo-hero-row-label",children:s}),e.jsx("p",{className:"aeo-hero-row-value text-base font-semibold text-secondary",children:"Not measured"}),e.jsx("div",{}),e.jsx("p",{className:"aeo-hero-row-detail",children:j==="Not measured"?"":j})]})}const r=Math.round(t.value*100),o=t.numerator===void 0||t.denominator===void 0?null:`${t.numerator} of ${t.denominator}`;return e.jsxs("div",{className:"aeo-hero-row",children:[e.jsx("p",{className:"aeo-hero-row-label",children:s}),e.jsxs("p",{className:"aeo-hero-row-value text-heading",children:[r,e.jsx("span",{className:"text-faint",children:"%"})]}),e.jsx("div",{className:"aeo-hero-row-bar","aria-hidden":"true",children:e.jsx("div",{className:"metric-card-bar-fill progress-fill-neutral",style:{width:`${r}%`}})}),e.jsx("p",{className:"aeo-hero-row-detail tabular-nums",children:o??""})]})}function Je({branded:s,nonBrand:t,brandedFailed:a=!1,nonBrandFailed:r=!1}){return e.jsxs("section",{"aria-labelledby":"property-coverage-hero",children:[e.jsx("h2",{id:"property-coverage-hero",className:"sr-only",children:"Coverage for this Property"}),e.jsxs("div",{className:"space-y-5",children:[e.jsxs("div",{className:"space-y-2",children:[e.jsx("p",{className:"eyebrow eyebrow-soft",children:"Non-brand · the demand to earn"}),e.jsx(q,{label:"Mentioned",metric:t?.mentionCoverage,failed:r}),e.jsx(q,{label:"Cited",metric:t?.citationCoverage,failed:r})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx("p",{className:"eyebrow eyebrow-soft",children:"Branded · already named"}),e.jsx(q,{label:"Mentioned",metric:s?.mentionCoverage,failed:a}),e.jsx(q,{label:"Cited",metric:s?.citationCoverage,failed:a})]})]})]})}function es({branded:s,nonBrand:t,brandedError:a,nonBrandError:r,onRetry:o}){const j=[{queryClass:"branded",row:s,isError:a},{queryClass:"non-brand",row:t,isError:r}];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(P,{text:"Branded queries already contain your name, so an answer engine has an easy path back to you. Non-brand queries describe the need instead, and that is the demand you have to earn. Each row is measured only over the queries assigned to this Property in that class; a class with no assigned query 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 query class"}),e.jsx("thead",{children:e.jsxs("tr",{children:[e.jsx("th",{children:"Query type"}),e.jsx("th",{children:"Mentioned in the answer"}),e.jsx("th",{children:"Cited as a source"})]})}),e.jsx("tbody",{children:j.map(({queryClass:l,row:d,isError:c})=>e.jsxs("tr",{children:[e.jsxs("td",{children:[e.jsx("span",{className:"block font-medium text-heading",children:p[l].headline}),e.jsx("span",{className:"mt-0.5 block text-xs text-muted",children:p[l].technical}),d&&c?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(g,{type:"button",size:"sm",variant:"ghost",className:"h-11 px-3 text-sm md:h-11",onClick:()=>o(l),children:["Retry ",p[l].technical.toLocaleLowerCase()]})]}):null]}),d?e.jsxs(e.Fragment,{children:[e.jsx("td",{children:e.jsx(I,{metric:d.mentionCoverage,emphasis:!0})}),e.jsx("td",{children:e.jsx(I,{metric:d.citationCoverage,emphasis:!0})})]}):c?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 ",p[l].technical.toLocaleLowerCase(),"."]}),e.jsxs(g,{type:"button",size:"sm",variant:"outline",className:"h-11 px-4 text-sm md:h-11",onClick:()=>o(l),children:["Retry ",p[l].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…"})})]})]},l))})]})})]})}function ss({row:s,queryClass:t,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.jsx("div",{children:e.jsxs("h2",{id:"property-providers",className:"text-base font-semibold text-heading",children:["Which engines answer for this Property",e.jsx(P,{text:"Each row is measured over the queries 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 ",p[t].technical.toLocaleLowerCase()," are unavailable. Retry that query 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 ",p[t].technical.toLocaleLowerCase()," for this Property.",s.mentionCoverage.state==="unavailable"?` ${U(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(r=>e.jsxs("tr",{children:[e.jsx("td",{className:"font-medium text-heading",children:r.provider}),e.jsx("td",{children:e.jsx(I,{metric:r.mentionCoverage})}),e.jsx("td",{children:e.jsx(I,{metric:r.citationCoverage})})]},r.provider))})]})})]})}function ts(s){const t=s.questions.join(" · ");return s.questionsTruncated?`${t} +${s.questionTotal-s.questions.length} more`:t}function as({project:s,targetKey:t,queryClass:a}){const r=L({...qe({client:M,path:{name:s},query:{targetKey:t,queryClass:a}})});if(r.isPending||r.isError)return null;const o=r.data?.competitors??[],j=r.data?.basis;return e.jsxs("section",{"aria-labelledby":"property-named-instead",className:"page-section-divider",children:[e.jsxs("div",{className:"section-head section-head-inline",children:[e.jsx("div",{children:e.jsxs("h2",{id:"property-named-instead",className:"text-base font-semibold text-heading",children:["Named instead of this Property",e.jsx(P,{text:"Counted from the answers that did not name this Property, so a name here is one an engine recommended in its place. Occurrences count answers, not positions: an engine naming the same rival in two answers counts twice, and one naming it twice in a single answer counts once."})]})}),o.length>0?e.jsxs("p",{className:"supporting-copy",children:[r.data?.total??o.length," named"]}):null]}),o.length===0?e.jsx("p",{className:"text-sm text-secondary",children:"No rival was named in the answers this Property missed. Nothing to compete with here yet."}):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-[420px]",children:[e.jsx("caption",{className:"sr-only",children:"Names the engines gave instead of this Property"}),e.jsx("thead",{children:e.jsxs("tr",{children:[e.jsx("th",{children:"Named"}),e.jsx("th",{children:"Answers"}),e.jsx("th",{children:"Engines"}),e.jsx("th",{children:"Queries"})]})}),e.jsx("tbody",{children:o.map(l=>e.jsxs("tr",{children:[e.jsx("td",{className:"text-strong",children:l.name}),e.jsx("td",{className:"tabular-nums text-secondary",children:l.occurrences}),e.jsxs("td",{className:"text-secondary",children:[l.providers.join(", "),l.providersTruncated?` +${l.providerTotal-l.providers.length}`:""]}),e.jsx("td",{className:"text-right",children:e.jsxs("span",{className:"inline-flex items-center justify-end gap-1",children:[e.jsx("span",{className:"tabular-nums text-secondary",children:l.questionTotal}),e.jsx(P,{text:ts(l)})]})})]},l.name))})]})}),j?.state==="available"?e.jsxs("p",{className:"supporting-copy mt-2",children:[j.targetMissResults," of ",j.answeredResults," answers to ",p[a].technical.toLocaleLowerCase()," did not name this Property."]}):null]})]})}function ns({questions:s,queryClass:t}){return e.jsxs("section",{"aria-labelledby":"property-questions",className:"page-section-divider",children:[e.jsxs("div",{className:"section-head section-head-inline",children:[e.jsx("div",{children:e.jsxs("h2",{id:"property-questions",className:"text-base font-semibold text-heading",children:[p[t].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 ",p[t].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:"Queries assigned to this Property"}),e.jsx("thead",{children:e.jsx("tr",{children:e.jsx("th",{children:"Query"})})}),e.jsx("tbody",{children:s.map(a=>e.jsx("tr",{children:e.jsx("td",{className:"text-secondary",children:a})},a))})]})})]})}function rs({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.jsx("div",{children:e.jsxs("h2",{id:"property-urls",className:"text-base font-semibold text-heading",children:["URLs that count as this Property",e.jsx(P,{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(t=>e.jsx("tr",{children:e.jsx("td",{className:"break-all text-secondary",children:t})},t))})]})})]})}function is(s,t){const a=[s.marketKey?t??"the selected market":null,s.provider?`the ${s.provider} answer engine`:null,s.model?`the ${s.model} model`:null,s.location?`location ${s.location}`:null,s.from||s.to?"a date range":null,s.measurementRunId?"a saved sweep":null].filter(r=>r!==null);return a.length===0?null:`AI Visibility is filtered to ${a.join(", ")}. This page shows the latest measurement for ${Oe.allMarkets.toLocaleLowerCase()} and answer engines.`}function ys(){const{projectName:s,targetKey:t}=fe({strict:!1}),a=Ne(),r=we({strict:!1}),o=b.useMemo(()=>$e(r),[r]),[j,l]=b.useState(new Set),d=s??"",c=t??"",H=!!d&&!!c,D=b.useMemo(()=>Ce("portfolio",Ee(Le())),[]),S=H&&D,{canWrite:B}=Me(),C=L({...Se({client:M,path:{name:d}}),enabled:S}),W=C.data?.active?.plan,$=W?.schemaVersion===2?W:null,_=o.queryClass==="branded"||o.queryClass==="non-brand"?o.queryClass:null,G=n=>$?.assignments.some(i=>i.targetKey===c&&i.queryClass===n)??!1,m=_??(!G("non-brand")&&G("branded")?"branded":"non-brand");b.useEffect(()=>{!$||_||a({to:".",replace:!0,search:n=>K(n,{queryClass:m})})},[$,_,m,a]);const v=L({...le(d,c,"branded"),enabled:S}),f=L({...le(d,c,"non-brand"),enabled:S}),O=de(v.data),V=de(f.data),y=m==="branded"?v.data:f.data,E=m==="branded"?O:V,Y=(m==="branded"?v.isError:f.isError)&&E===void 0,X=y?.measurement.displayedRunId,he=E?.mentionCoverage.state==="unavailable"?U(E.mentionCoverage):void 0,me=y===void 0?void 0:y.measurement.completedAt??null,A={client:M,path:{name:d},query:{targetKey:c,queryClass:m,shape:Ae.answers,limit:re,...X?{runId:X}:{}}},h=Pe({...Re(A),enabled:S&&y!==void 0,initialPageParam:A,getNextPageParam:n=>n.answers?.nextCursor?{path:A.path,query:{...A.query,cursor:n.answers.nextCursor}}:void 0}),Q=C.data?.active??null,u=Q?.plan.schemaVersion===2?Q.plan:null,xe=Q!==null&&u===null,R=u?.targets.find(n=>n.stableKey===c)??null,Z=is(o,u?.reportingScopes?.find(n=>n.stableKey===o.marketKey)?.label),pe=b.useMemo(()=>{if(!u)return[];const n=new Map(u.querySnapshots.map(i=>[i.queryId,i.queryText]));return[...new Set(u.assignments.filter(i=>i.targetKey===c&&i.queryClass===m).flatMap(i=>{const x=n.get(i.queryId);return x===void 0?[]:[x]}))].sort((i,x)=>i.localeCompare(x))},[u,c,m]),ue=b.useMemo(()=>R?.urlMatchers.map(_e)??[],[R]),je=b.useMemo(()=>u?.groups.filter(n=>n.targetKeys.includes(c))??[],[u,c]),N=b.useMemo(()=>(h.data?.pages??[]).flatMap(x=>x.answers?.items??[]),[h.data]),J=h.data?.pages[0]?.answers?.totalEstimate??N.length,ye=(h.data?.pages??[]).length>0&&(h.data?.pages??[]).every(n=>n.answers===void 0),be=h.data?.pages[0]?.measurement.state,k=e.jsxs(T,{to:"/projects/$projectName",params:{projectName:d},search:z,className:"inline-flex items-center gap-1 text-xs text-muted hover:text-strong",children:[e.jsx(Qe,{className:"size-3.5","aria-hidden":"true"}),"Back to AI Visibility"]});if(!H)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(!D)return e.jsxs("div",{className:"page-container space-y-3",children:[k,e.jsx("p",{className:"text-sm text-muted",children:"This view is not available here."})]});if(C.isPending&&!C.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 ge=C.isError&&C.data===void 0,ee=v.isError&&v.data===void 0,se=f.isError&&f.data===void 0;return ge||ee&&se?e.jsxs("div",{className:"page-container space-y-3",children:[k,e.jsx("p",{role:"alert",className:"text-sm text-negative",children:"Could not load this Property."}),e.jsx(g,{type:"button",size:"sm",variant:"outline",className:"h-11 px-4 text-sm md:h-11",onClick:()=>{C.refetch(),v.refetch(),f.refetch()},children:"Try again"})]}):!u||!R?e.jsxs("div",{className:"page-container space-y-3",children:[k,e.jsx("p",{role:"status",className:"text-sm text-secondary",children:u?"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(g,{asChild:!0,type:"button",variant:"outline",className:"h-11 px-4 text-sm md:h-11",children:e.jsx(T,{to:"/projects/$projectName/portfolio",params:{projectName:d},children:B?xe?"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:[k,e.jsx("h1",{className:"page-title mt-2",children:R.label}),e.jsxs("p",{className:"page-subtitle",children:["Property in ",d,Z?e.jsxs(e.Fragment,{children:[" · Filters not applied ",e.jsx(P,{text:Z})]}):null]})]}),e.jsxs("div",{className:"page-header-right",children:[y?e.jsx(w,{tone:ie[y.measurement.state].tone,children:ie[y.measurement.state].label}):null,E&&E.flags>0?e.jsxs(w,{tone:"caution",children:[E.flags," flagged"]}):null]})]}),e.jsx(Je,{branded:O,nonBrand:V,brandedFailed:ee,nonBrandFailed:se}),e.jsx(es,{branded:O,nonBrand:V,brandedError:v.isError,nonBrandError:f.isError,onRetry:n=>{n==="branded"?v.refetch():f.refetch()}}),y&&(y.measurement.state==="not_measured"||y.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:ne()?ae:B?"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(g,{asChild:!0,type:"button",className:"h-11 px-4 text-sm md:h-11",children:e.jsx(T,{to:"/projects/$projectName",params:{projectName:d},search:z,children:B?"Go to AI Visibility":"View AI Visibility"})})]}):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:"Query type"}),e.jsxs("select",{id:"property-query-class",value:m,onChange:n=>{const i=n.target.value==="branded"?"branded":"non-brand";a({to:".",search:x=>K(x,{queryClass:i})})},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:p["non-brand"].technical}),e.jsx("option",{value:"branded",children:p.branded.technical})]})]}),e.jsx(Xe,{measuredAt:me,unmeasuredReason:he,queryClass:m})]}),e.jsx(ss,{row:E,queryClass:m,isError:Y}),e.jsx(as,{project:d,targetKey:c,queryClass:m}),e.jsx(ns,{questions:pe,queryClass:m}),e.jsx(rs,{urls:ue}),e.jsx(Ze,{project:d,groups:je}),e.jsxs("section",{"aria-labelledby":"property-evidence",className:"page-section-divider",children:[e.jsxs("div",{className:"section-head section-head-inline",children:[e.jsx("div",{children:e.jsxs("h2",{id:"property-evidence",className:"text-base font-semibold text-heading",children:["Answers the engines gave",e.jsx(P,{text:"One row per answer an engine gave for the queries assigned to this Property in the displayed measurement. Mentioned and cited are independent: an answer can name this Property without linking it, or link it without naming it. Answers that did neither are listed first, because those are what a gap is made of. Where the answer text was not stored the mention reads Not measured, never a zero. Open a row to read what the engine actually said, followed by the source URLs it returned, this Property's own first. The answer is where a miss becomes actionable: a query this Property was not named in may still have named a sibling building."})]})}),N.length>0?e.jsxs("p",{className:"supporting-copy",children:[N.length," of ",J]}):null]}),Y?e.jsxs("p",{className:"text-sm text-secondary",children:["Evidence for ",p[m].technical.toLocaleLowerCase()," is unavailable. Retry that query type above."]}):h.isPending&&N.length===0?e.jsx("p",{className:"text-sm text-secondary",children:"Loading evidence…"}):h.isError&&N.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(g,{type:"button",size:"sm",variant:"outline",className:"h-11 px-4 text-sm md:h-11",onClick:()=>{h.refetch()},children:"Retry evidence"})]}):be==="not_measured"?e.jsx("p",{className:"text-sm text-secondary",children:ne()?ae:"Not measured yet. Run a measurement to collect the answers for this Property."}):ye?e.jsx("p",{role:"alert",className:"text-sm text-caution",children:"This measurement was returned in an older format, so the answers cannot be shown here. The numbers above are unaffected."}):N.length===0?e.jsx("p",{className:"text-sm text-secondary",children:"No answers matched this Property in the displayed measurement."}):e.jsxs(e.Fragment,{children:[e.jsx("div",{className:"property-answer-table-container overflow-x-auto rounded-md border border-default",children:e.jsxs("table",{className:"evidence-table property-evidence-table",children:[e.jsx("caption",{className:"sr-only",children:"Answers measured for this Property"}),e.jsx("thead",{children:e.jsxs("tr",{children:[e.jsx("th",{children:"Query"}),e.jsx("th",{children:"Mentioned in the answer"}),e.jsx("th",{children:"Cited as a source"}),e.jsx("th",{children:"Sources"}),e.jsx("th",{children:e.jsx("span",{className:"sr-only",children:"Sources detail"})})]})}),e.jsx("tbody",{children:N.map(n=>{const i=ze(n),x=j.has(i),te=`property-answer-${encodeURIComponent(i)}`;return e.jsxs(b.Fragment,{children:[e.jsxs("tr",{className:"property-answer-summary",children:[e.jsxs("td",{className:"text-secondary",children:[e.jsx("h3",{className:"text-sm font-medium text-heading",children:n.queryText}),e.jsx("span",{className:"mt-1 block text-xs text-muted",children:[n.provider,n.location].filter(Boolean).join(" · ")}),n.historical||n.bridged?e.jsx("span",{className:"mt-1 flex",children:e.jsx(w,{tone:"caution",children:"Historical"})}):null]}),e.jsxs("td",{children:[e.jsx("span",{className:"property-evidence-mobile-label","aria-hidden":"true",children:"Mentioned"}),e.jsx(He,{row:n})]}),e.jsxs("td",{children:[e.jsx("span",{className:"property-evidence-mobile-label","aria-hidden":"true",children:"Cited"}),e.jsx(We,{row:n})]}),e.jsxs("td",{className:"tabular-nums text-secondary",children:[e.jsx("span",{className:"property-evidence-mobile-label","aria-hidden":"true",children:ce}),n.cited===null?De:n.sources.length]}),e.jsx("td",{className:"text-right",children:e.jsx(g,{type:"button",size:"sm",variant:"ghost",className:"h-auto min-h-11 max-w-full whitespace-normal py-2 text-left md:h-auto","aria-expanded":x,"aria-label":x?`Hide the answer for ${n.queryText}`:`Read the answer for ${n.queryText}`,"aria-controls":x?te:void 0,onClick:()=>l(ve=>{const F=new Set(ve);return F.delete(i)||F.add(i),F}),children:x?"Hide answer":"Read answer"})})]}),x?e.jsx("tr",{className:"property-answer-detail",children:e.jsxs("td",{id:te,colSpan:5,className:"bg-surface-subtle px-4",children:[e.jsx(Ye,{project:d,targetKey:c,row:n}),e.jsx(Ge,{row:n})]})}):null]},i)})})]})}),h.hasNextPage?e.jsxs("div",{className:"mt-2 flex flex-wrap items-center gap-3 text-sm text-secondary",children:[e.jsxs("span",{children:["Showing ",N.length," of ",J]}),h.isFetchNextPageError?e.jsx("span",{role:"alert",children:"Could not load more evidence."}):null,e.jsx(g,{size:"sm",variant:"outline",className:"h-11 px-4 text-sm md:h-11",disabled:h.isFetchingNextPage,onClick:()=>{h.fetchNextPage()},children:h.isFetchingNextPage?"Loading…":h.isFetchNextPageError?"Retry more evidence":`Show ${re} more`})]}):null]})]})]})}export{oe as EVIDENCE_LABELS,ys as MeasurementPropertyPage};