@canonry/canonry 7.58.1 → 7.58.3

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 (55) hide show
  1. package/README.md +5 -0
  2. package/assets/agent-workspace/skills/aero/SKILL.md +9 -2
  3. package/assets/agent-workspace/skills/aero/references/reporting.md +4 -0
  4. package/assets/agent-workspace/skills/aero/references/seo-analysis.md +123 -0
  5. package/assets/assets/{AgentSetupPage-BSkstQJa.js → AgentSetupPage-CRvCLiCD.js} +2 -2
  6. package/assets/assets/{AuditHistoryPanel-DAY6GbzH.js → AuditHistoryPanel-DSUKF9GC.js} +1 -1
  7. package/assets/assets/{BacklinksPage-Ci9s8osY.js → BacklinksPage-DIZy0NkW.js} +1 -1
  8. package/assets/assets/{ChartPrimitives-BgY3tqbD.js → ChartPrimitives-CksxPvHn.js} +1 -1
  9. package/assets/assets/{Hint-BsfMSR5e.js → Hint-C0TmIzHX.js} +1 -1
  10. package/assets/assets/{HistoryPage-BM7PM3Ow.js → HistoryPage-B2Xtxu5L.js} +1 -1
  11. package/assets/assets/{InfoTooltip-COkeQYiP.js → InfoTooltip-DV3_9Qp1.js} +1 -1
  12. package/assets/assets/MeasurementPropertyPage-B3qnQtNg.js +4 -0
  13. package/assets/assets/{ProjectPage-Dnev2R09.js → ProjectPage-j9V9UFfY.js} +5 -5
  14. package/assets/assets/RunsPage-CvqCrsiH.js +1 -0
  15. package/assets/assets/SettingsPage-CX5Rzsm3.js +1 -0
  16. package/assets/assets/SiteHealthSection-CYKyJBaJ.js +2 -0
  17. package/assets/assets/{ToneBadge-Bk7cBexZ.js → ToneBadge-DYEbxp5S.js} +1 -1
  18. package/assets/assets/TrafficPage-DNC0DP-U.js +40 -0
  19. package/assets/assets/{TrafficSourceDetailPage-BVAVo-JO.js → TrafficSourceDetailPage-Dp7AYvRP.js} +1 -1
  20. package/assets/assets/{account-context-ChEngAKj.js → account-context-DHWaWJSr.js} +1 -1
  21. package/assets/assets/{card-qOcJFZhl.js → card-im88-x1b.js} +1 -1
  22. package/assets/assets/{extract-error-message-bWEYiDDO.js → extract-error-message-Bq8oNvfF.js} +1 -1
  23. package/assets/assets/{format-helpers-CvOZG1pt.js → format-helpers-DOEct2q8.js} +1 -1
  24. package/assets/assets/index-B662I7kR.css +1 -0
  25. package/assets/assets/index-CQwjYVPD.js +60 -0
  26. package/assets/assets/{query-client-nsJhXK9R.js → query-client-BN_-qp71.js} +1 -1
  27. package/assets/assets/{react-query-BKjNH2ek.js → react-query-P6OZ-MPl.js} +1 -1
  28. package/assets/assets/{react-sigma_core.esm.min-C8kc2J6I.js → react-sigma_core.esm.min-BNkIcXRz.js} +1 -1
  29. package/assets/assets/{service-DmVT5F26.js → service-CWdIU_mf.js} +1 -1
  30. package/assets/assets/{vendor-lucide-CPeGWK5C.js → vendor-lucide-4KkDquAu.js} +1 -1
  31. package/assets/assets/{vendor-markdown-Bdsu1JLE.js → vendor-markdown-9SSeLNHZ.js} +1 -1
  32. package/assets/assets/vendor-radix-BuErWiA2.js +41 -0
  33. package/assets/assets/{vendor-recharts-CFnqWvWF.js → vendor-recharts-qIim36Mt.js} +1 -1
  34. package/assets/assets/{vendor-tanstack-CXaF1vMI.js → vendor-tanstack-pEsPGDvT.js} +1 -1
  35. package/assets/index.html +15 -15
  36. package/dist/{chunk-SML23FNI.js → chunk-BDUHO7KK.js} +4 -4
  37. package/dist/{chunk-3O2F2LGB.js → chunk-JDRKZOUP.js} +1 -1
  38. package/dist/{chunk-VVJ22ZN5.js → chunk-SXGLLWS4.js} +1 -1
  39. package/dist/{cli-commands-QLHV4NXP.js → cli-commands-3HTHHRXT.js} +1 -1
  40. package/dist/cli.js +2 -2
  41. package/dist/{demo-UBMNDBRF.js → demo-TPOKI7ZM.js} +1 -1
  42. package/dist/{demo-server-F4M74FVL.js → demo-server-ZBNKYYM2.js} +42 -32
  43. package/dist/index.d.ts +63 -63
  44. package/dist/index.js +1 -1
  45. package/dist/{init-MAUH2G2K.js → init-4IKMMWAD.js} +1 -1
  46. package/dist/{serve-3GW2F3WS.js → serve-2AOLGG3F.js} +1 -1
  47. package/package.json +1 -1
  48. package/assets/assets/MeasurementPropertyPage-CHzsfcb5.js +0 -4
  49. package/assets/assets/RunsPage-uPCDTjPM.js +0 -1
  50. package/assets/assets/SettingsPage-rBvx_O4A.js +0 -1
  51. package/assets/assets/SiteHealthSection-oBg5h5Ge.js +0 -2
  52. package/assets/assets/TrafficPage-BJSxxkbT.js +0 -40
  53. package/assets/assets/index-BIfsFQb8.js +0 -56
  54. package/assets/assets/index-D67dZGOY.css +0 -1
  55. package/assets/assets/vendor-radix-3k2C0Ly9.js +0 -41
package/README.md CHANGED
@@ -19,6 +19,11 @@ Canonry is an **agent-first (CLI, MCP, API), open-source AEO operating platform
19
19
 
20
20
  ## Quick start
21
21
 
22
+ Local installation requires Node.js in one of these supported ranges:
23
+ `>=22.23.4 <23`, `>=24.22.1 <25`, or `>=26.12.1 <27`.
24
+ Check `node --version` before installing; upgrade Node first if it is outside
25
+ these ranges. An existing hosted MCP connection needs no local Node install.
26
+
22
27
  <a id="or-use-any-shell-capable-coding-agent"></a>
23
28
 
24
29
  ### Start with your agent
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: aero
3
- description: "Diagnose AEO regressions and interpret Canonry AI visibility, Advanced multi-property portfolios, and Site Health evidence. Use when a mention or citation coverage number moved and needs explaining, when comparing Properties or markets, diagnosing crawl or page findings, preparing a client report or month-over-month comparison, or analyzing a completed `cnry` sweep or site audit. Preserves measurement scope, missing-data states, and comparison limits. Use the canonry skill for setup and operations."
3
+ description: "Diagnose AEO regressions and interpret Canonry AI visibility, SEO data, Advanced multi-property portfolios, and Site Health evidence. Use when prioritizing keyword or organic ranking opportunities, explaining mention or citation changes, comparing Properties or markets, diagnosing page findings, preparing reports, or analyzing a completed `cnry` sweep or site audit. Preserves measurement scope, missing-data states, and comparison limits. Use the canonry skill for setup and operations."
4
4
  metadata:
5
5
  homepage: https://canonry.ai
6
6
  repository: https://github.com/AINYC/aero
@@ -8,7 +8,7 @@ metadata:
8
8
 
9
9
  # Aero Orchestration Skill
10
10
 
11
- Use Canonry's stored evidence to explain AI visibility and site readiness. In
11
+ Use Canonry's stored evidence to explain AI visibility, SEO opportunities, and site readiness. In
12
12
  built-in Aero, use `aero_list_toolkits` and `aero_load_toolkit` to load relevant
13
13
  tools, then call the available `canonry_*` tools directly. Project-scoped
14
14
  tools use the session's project; they do not accept a different project from
@@ -23,6 +23,12 @@ covering that work; an existing explicit authorization remains valid.
23
23
 
24
24
  ## Choose the evidence scope
25
25
 
26
+ - **SEO data:** read `references/seo-analysis.md` before prioritizing keywords,
27
+ organic rankings, or domain comparisons. In built-in Aero, discover it with
28
+ `list_skill_docs`, then call `read_skill_doc` with `slug: "seo-analysis"`.
29
+ Load the `seo` toolkit and use the selected profile's saved evidence.
30
+ Priorities are recommendations, not computed scores or traffic forecasts.
31
+ Aero cannot edit SEO profiles or start paid SEO refreshes.
26
32
  - **Establish the portfolio type before answering; never infer it.**
27
33
  `canonry_project_overview` returns no plan, Target, or Property data, so its
28
34
  silence is not evidence of a Simple project. When the system prompt carries
@@ -244,6 +250,7 @@ Detailed playbooks live alongside this file. Read them on demand when the task m
244
250
 
245
251
  | File | Read when |
246
252
  |---|---|
253
+ | `references/seo-analysis.md` | Prioritizing keyword or organic ranking opportunities from saved SEO data |
247
254
  | `references/portfolio-analysis.md` | Interpreting Simple or Advanced portfolios, ranking Properties or markets, or comparing measurement runs |
248
255
  | `references/site-health.md` | Diagnosing site/page scores, crawl completeness, internal links, or changes between scans |
249
256
  | `references/agent-operations.md` | Checking shared scope, evidence, comparison, or permission rules; generated from the canonical operations guide |
@@ -58,6 +58,10 @@ A sweep crippled by a provider outage captures fewer questions and looks identic
58
58
 
59
59
  ## Build summaries from stored evidence
60
60
 
61
+ For keyword and organic ranking recommendations, read `seo-analysis.md`.
62
+ Keep its qualitative priorities and provider estimates separate from measured traffic and AI coverage.
63
+ State the SEO profile, refresh date, and inspected coverage in the report.
64
+
61
65
  Use the project overview for current state, `canonry_visibility_compare` for
62
66
  calendar-month comparisons, and scoped measurement tools for Advanced
63
67
  Properties and markets. Read `canonry_organic_evidence` for the stored GSC,
@@ -0,0 +1,123 @@
1
+ ---
2
+ name: seo-analysis
3
+ description: Prioritize keyword and organic ranking opportunities from saved SEO evidence. Covers profile selection, bounded samples, Advanced scopes, provider estimates, and actionable shortlists.
4
+ ---
5
+
6
+ # SEO analysis
7
+
8
+ Use this playbook for keyword research, ranking opportunities, and domain comparisons.
9
+ Priorities are editorial recommendations from the inspected evidence, not Canonry scores or predicted gains.
10
+ The workflow uses normalized SEO capabilities. Take the provider and dataset names from returned provenance.
11
+
12
+ ## Read the selected evidence
13
+
14
+ 1. For a question about the current SEO view, start with `aero_inspect_view`.
15
+ 2. Load the `seo` toolkit through `aero_load_toolkit` in built-in Aero.
16
+ External MCP agents use `canonry_help` with intent `seo` and their exposed catalog.
17
+ 3. Read `canonry_seo_context` and `canonry_seo_profiles` to resolve the source, capabilities, profile, and supported scope.
18
+ Preserve an explicitly selected profile or refresh. If several profiles match an ambiguous request, ask which one to use.
19
+ 4. Read `canonry_seo_overview` for that `profileId` and any selected `runId`.
20
+ Use `evidenceRunId` for subsequent evidence reads. Use `evidenceRun` for the date, scope, locale, and profile revision.
21
+ For historical evidence, use the run's capabilities and scope instead of the current profile's settings.
22
+ A newer `latestRun` can be running or failed while older evidence remains available.
23
+ The overview's `status.lastCompletedAt` is project-wide. Its summary describes only the first target, not all profile domains.
24
+ 5. Read the relevant datasets with the same `profileId` and evidence `runId`:
25
+
26
+ | Tool | Evidence |
27
+ |---|---|
28
+ | `canonry_seo_keyword_metrics` | Explicit keywords, demand estimates, difficulty, intent, and monthly estimates |
29
+ | `canonry_seo_ranked_keywords` | Observed positions, ranking URLs, target identity, and traffic estimates |
30
+ | `canonry_seo_domain_intelligence` | Per-target keyword totals, position buckets, and traffic estimates |
31
+
32
+ 6. Page with `limit` and `offset` until the relevant stored rows are covered, or disclose the inspected sample.
33
+ These tools accept no keyword filter, target filter, or sort parameter. Do not invent them.
34
+ `total` counts stored rows, not the complete search market.
35
+ Run detail returns at most 20 rows per dataset. Check `resultsTruncated` and `resultCounts`, then use the dataset tools.
36
+
37
+ Use completed or partial evidence for a stable read. Describe partial results and failed tasks before recommendations.
38
+ For partial or failed refreshes, inspect `canonry_seo_run` task details to identify the affected datasets and targets.
39
+ An unconfigured source does not prevent analysis of saved evidence.
40
+ If the user selects an active refresh, treat its rows as provisional because the stored set can still change.
41
+ If no usable evidence exists, explain the missing dataset and request an operator refresh for the exact profile.
42
+ Aero cannot edit profiles, start or cancel SEO refreshes, or inspect operator receipts.
43
+ Analysis never requires a refresh intent. Keep credentials and hosted financial controls out of the response.
44
+
45
+ ## Preserve the measurement boundary
46
+
47
+ - Simple profiles use project scope. Advanced profiles retain their project scope or group, market, or Property key, plus plan revision.
48
+ Use the capabilities returned for that scope. Never replace a path or entity Property with its whole domain.
49
+ Keyword-only scopes support research recommendations, not claims about that Property's rankings.
50
+ - Keep the target's kind, value, and `includeSubdomains` setting with its evidence.
51
+ Establish which targets belong to the project and which are competitors before recommending changes to a URL.
52
+ A first-target summary does not establish ownership.
53
+ - Preserve provider, dataset, engine, location, language, device, collection date, and available source date.
54
+ Retrieval time is not measurement time. Missing source dates leave upstream freshness unknown.
55
+ - Rank comparisons require the same keyword, target definition, URL identity, scope, locale, and comparable source methods.
56
+ A null rank is unknown. `rankOrganic` and `rankAbsolute` measure different positions.
57
+ Do not manufacture rank deltas, visibility share, keyword gaps, or trends from unmatched snapshots.
58
+ Historical runs do not expose the complete frozen keyword basket or row limit.
59
+ A changed profile revision cannot establish comparable coverage from today's profile alone.
60
+ - Rank lists are bounded provider samples, even after every stored page is read.
61
+ An absent keyword does not prove that a site stopped ranking or that a competitor has an exclusive keyword.
62
+ Run history is bounded too. An absent older run does not prove that no history exists.
63
+ - If rows repeat, preserve separate keyword, URL, target, and provenance identities.
64
+ Group related findings for presentation without adding overlapping volume, traffic, or domain totals.
65
+ Multiple URLs for one keyword are not proof of cannibalization.
66
+ `coreKeyword` can suggest a topic group, but it does not make synonym demand additive.
67
+
68
+ ## Prioritize the work
69
+
70
+ First establish the user's market, audience, products, and conversion goal from available project context.
71
+ If these are unknown, label business relevance as provisional or ask for the missing goal.
72
+ Review evidence coverage before treating a candidate as ready for action.
73
+
74
+ Use this order of judgment:
75
+
76
+ 1. Prefer keywords that match the business and the intended searcher's need.
77
+ 2. Prefer an identified owned URL with observed organic rankings and a specific change worth checking.
78
+ Positions near the desired results can justify inspection. They do not guarantee an easy improvement.
79
+ 3. Use supplied demand estimates to distinguish otherwise relevant candidates within a comparable source and locale.
80
+ 4. Use difficulty, intent, and monthly estimates as supporting evidence, with their missing values stated.
81
+ 5. If page evidence or user context supports effort or business value, include it in the recommendation.
82
+
83
+ | Candidate | Recommendation | Evidence needed before execution |
84
+ |---|---|---|
85
+ | Relevant keyword with an owned ranking URL | Inspect that page for a specific improvement | Stored page/content evidence and the user's goal |
86
+ | Relevant keyword with demand but no known matching page | Investigate a content opportunity | Page inventory and intent fit. Absence from ranks is insufficient. |
87
+ | Valuable page already ranking strongly | Preserve what works and check identified issues | Measured business value or an explicit user priority |
88
+ | Competitor with stronger domain estimates | Investigate the difference within comparable scope | Per-target evidence. Totals do not establish keyword gaps. |
89
+ | Missing, stale, partial, or incompatible evidence | Validate the evidence first | The exact missing dataset, profile, or comparable refresh |
90
+
91
+ Inspect stored page or Site Health evidence before prescribing title, content, indexability, or internal-link changes.
92
+ Read `site-health` through `read_skill_doc` for its interpretation rules.
93
+ A rank alone cannot identify a technical or content cause.
94
+ If supporting evidence is absent, recommend a specific inspection instead of asserting a defect.
95
+
96
+ Keep the metrics honest:
97
+
98
+ - `keywordDifficulty` is the provider's 0–100 score, not a percentage or probability of success.
99
+ Do not transfer thresholds between providers.
100
+ - `adCompetition` measures advertising competition, not organic difficulty.
101
+ - CPC and estimated traffic value are research estimates, not revenue, acquisition cost, or ROI.
102
+ High CPC alone does not establish business value.
103
+ - Monthly search estimates describe demand, not this site's traffic or ranking trend.
104
+ Missing months and different sampling periods limit seasonal claims.
105
+ - `serpFeatures` describes the search results. It does not prove that the target owns a feature.
106
+ - Search Console, analytics, backlinks, and AI citation and mention coverage remain separate instruments.
107
+ Use their stored tools for corroboration with matching scope and dates. Do not combine them into an SEO score.
108
+
109
+ ## Return a concise shortlist
110
+
111
+ Lead with the most useful next action and the evidence limitation that affects it.
112
+ Use one short table for the strongest supported candidates, usually no more than five:
113
+
114
+ | Priority | Keyword / owned URL | Evidence | Recommended action | Confidence / missing evidence |
115
+ |---|---|---|---|---|
116
+ | Now, Next, or Validate | Preserve target identity | Supplied position and demand, source, date | One concrete inspection or proposed change | State why the recommendation is supported or provisional |
117
+
118
+ “Now” means the next recommended investigation or approved action, not permission to publish or spend.
119
+ Label the order as your recommendation. If the read is incomplete, call it a shortlist from the inspected sample.
120
+ Do not call it the project's top opportunities or calculate an opportunity score, forecast, or aggregate growth rate.
121
+ Put common profile, market, language, refresh, and coverage information once above the table.
122
+ Link the returned evidence beside each finding. If rows share evidence, link the selected SEO view once.
123
+ If no evidence URL is returned, cite the profile and refresh IDs instead of inventing a link.
@@ -1,6 +1,6 @@
1
- import{r as e}from"./rolldown-runtime-XKyaHtl9.js";import{L as t,it as n,q as r,z as i}from"./vendor-lucide-CPeGWK5C.js";import{r as a}from"./vendor-markdown-Bdsu1JLE.js";import{Ct as o,En as s,Xt as c,Zt as l,_r as u,r as d,st as f,t as p,vr as m,wt as h,yr as g}from"./ToneBadge-Bk7cBexZ.js";import{r as _}from"./account-context-ChEngAKj.js";import{t as v}from"./async-handler-Bj3TnIRw.js";import{$ as y,Y as b}from"./index-BIfsFQb8.js";var x=e(n(),1),S=a(),C=`https://github.com/Canonry/canonry/blob/main/docs/mcp.md`,w=`https://github.com/Canonry/canonry/blob/main/docs/plugins.md`,T=`https://help.openai.com/en/articles/12584461-connecting-custom-mcp-servers-in-chatgpt`,E=`https://support.claude.com/en/articles/11175166-get-started-with-custom-connectors-using-remote-mcp`,D={[m[`public-url-required`]]:`Configure this instance’s public URL before connecting a hosted client.`,[m[`https-required`]]:`Configure an HTTPS public URL for this instance.`,[m[`public-host-required`]]:`Use a public HTTPS address that your client can reach. Localhost and private-network addresses do not work for hosted connectors.`,[m[`public-path-mismatch`]]:`Make the publicUrl path match basePath, and preserve that prefix when the proxy forwards requests for hosted OAuth.`,[m[`oauth-unavailable`]]:`The sign-in routes are unavailable. Check this instance’s OAuth configuration.`,[m[`account-required`]]:`Create a named Canonry account on this instance’s server with canonry user create. A shared dashboard password does not provide an OAuth account.`,[m[`transport-unavailable`]]:`Restore the instance’s HTTP MCP service before connecting a hosted client.`},O={codex:{label:`Codex`,command:`codex plugin marketplace add Canonry/canonry
1
+ import{r as e}from"./rolldown-runtime-XKyaHtl9.js";import{I as t,K as n,R as r,rt as i}from"./vendor-lucide-4KkDquAu.js";import{r as a}from"./vendor-markdown-9SSeLNHZ.js";import{Ct as o,En as s,Xt as c,Zt as l,_r as u,r as d,st as f,t as p,vr as m,wt as h,yr as g}from"./ToneBadge-DYEbxp5S.js";import{r as _}from"./account-context-DHWaWJSr.js";import{t as v}from"./async-handler-Bj3TnIRw.js";import{X as y,et as b}from"./index-CQwjYVPD.js";var x=e(i(),1),S=a(),C=`https://github.com/Canonry/canonry/blob/main/docs/mcp.md`,w=`https://github.com/Canonry/canonry/blob/main/docs/plugins.md`,T=`https://help.openai.com/en/articles/12584461-connecting-custom-mcp-servers-in-chatgpt`,E=`https://support.claude.com/en/articles/11175166-get-started-with-custom-connectors-using-remote-mcp`,D={[m[`public-url-required`]]:`Configure this instance’s public URL before connecting a hosted client.`,[m[`https-required`]]:`Configure an HTTPS public URL for this instance.`,[m[`public-host-required`]]:`Use a public HTTPS address that your client can reach. Localhost and private-network addresses do not work for hosted connectors.`,[m[`public-path-mismatch`]]:`Make the publicUrl path match basePath, and preserve that prefix when the proxy forwards requests for hosted OAuth.`,[m[`oauth-unavailable`]]:`The sign-in routes are unavailable. Check this instance’s OAuth configuration.`,[m[`account-required`]]:`Create a named Canonry account on this instance’s server with canonry user create. A shared dashboard password does not provide an OAuth account.`,[m[`transport-unavailable`]]:`Restore the instance’s HTTP MCP service before connecting a hosted client.`},O={codex:{label:`Codex`,command:`codex plugin marketplace add Canonry/canonry
2
2
  codex plugin add canonry@canonry`},claude:{label:`Claude Code`,command:`claude plugin marketplace add Canonry/canonry
3
- claude plugin install canonry@canonry`},other:{label:`Other MCP clients`,command:`canonry-mcp`}};function k({label:e,value:t,showText:n=!1,secondary:a=!1,action:o=`agent_setup.copy`}){let c=(0,x.useId)(),[l,u]=(0,x.useState)(!1),[f,p]=(0,x.useState)(!1);async function m(){try{await navigator.clipboard.writeText(t),s(o),u(!0),p(!1)}catch{u(!1),p(!0)}}return(0,S.jsxs)(`div`,{className:`min-w-0 space-y-3`,children:[n?(0,S.jsx)(`pre`,{className:`overflow-x-auto rounded-md border border-default bg-bg p-3 text-sm text-heading`,children:(0,S.jsx)(`code`,{children:t})}):null,(0,S.jsxs)(d,{type:`button`,className:`min-h-11`,variant:a?`outline`:`default`,onClick:v(m),children:[l?(0,S.jsx)(r,{className:`size-4`,"aria-hidden":`true`}):(0,S.jsx)(i,{className:`size-4`,"aria-hidden":`true`}),e]}),l?(0,S.jsx)(`p`,{role:`status`,className:`text-sm text-secondary`,children:`Copied.`}):null,!n||f?(0,S.jsxs)(`details`,{open:f||void 0,className:`text-sm text-secondary`,children:[(0,S.jsx)(`summary`,{className:`min-h-11 w-fit cursor-pointer py-3`,children:f?`Copy unavailable. Select the text below.`:`Preview text`}),(0,S.jsxs)(`label`,{htmlFor:c,className:`sr-only`,children:[e,` text`]}),(0,S.jsx)(`textarea`,{id:c,readOnly:!0,rows:f&&n?3:8,value:t,className:`mt-2 w-full rounded-md border border-default bg-bg p-3 text-sm leading-6 text-heading`})]}):null]})}function A(){return o()||h()?(0,S.jsxs)(`div`,{className:`page-container`,children:[(0,S.jsx)(`h1`,{className:`page-title`,children:`Agent setup`}),(0,S.jsx)(`p`,{className:`mt-3 text-sm text-secondary`,children:`Open Agent setup in your own Canonry instance to connect your agent.`}),l()?(0,S.jsx)(`a`,{className:`mt-4 inline-block text-sm underline`,href:C,target:`_blank`,rel:`noopener noreferrer`,children:`Read the connection guide`}):null]}):(0,S.jsx)(j,{})}function j(){let e=y(),{isAdmin:n}=_(),r=c(),i=l(),a=b(!e,e?.health),o=a.data?.apiStatus,s=o?.state===`ok`?o.mcp:void 0,d=s?.status===g.available&&s.hosted?.status===u.ready?s.hosted:void 0,m=s?.hosted?.status===u.unavailable?s.hosted.reason:void 0,h=`${window.location.origin}${f()}`,v=`This server has not confirmed a public URL and OAuth sign-in. Ask your administrator to check the connection configuration or update Canonry.`;a.isPending?v=`Checking the instance’s hosted connection settings.`:m?v=n&&r?D[m]:`Ask your Canonry administrator to finish hosted connection setup for this instance.`:o?.state===`error`?v=`The instance’s connection settings could not be checked. Try again after the service is available.`:s?.status===g[`not-supported`]&&(v=`This deployment does not provide hosted MCP connections. Ask your administrator for a supported connection.`);let x=d?`Help me connect this existing Canonry instance to ChatGPT or Claude Desktop using its remote MCP URL: ${d.url}
3
+ claude plugin install canonry@canonry`},other:{label:`Other MCP clients`,command:`canonry-mcp`}};function k({label:e,value:t,showText:i=!1,secondary:a=!1,action:o=`agent_setup.copy`}){let c=(0,x.useId)(),[l,u]=(0,x.useState)(!1),[f,p]=(0,x.useState)(!1);async function m(){try{await navigator.clipboard.writeText(t),s(o),u(!0),p(!1)}catch{u(!1),p(!0)}}return(0,S.jsxs)(`div`,{className:`min-w-0 space-y-3`,children:[i?(0,S.jsx)(`pre`,{className:`overflow-x-auto rounded-md border border-default bg-bg p-3 text-sm text-heading`,children:(0,S.jsx)(`code`,{children:t})}):null,(0,S.jsxs)(d,{type:`button`,className:`min-h-11`,variant:a?`outline`:`default`,onClick:v(m),children:[l?(0,S.jsx)(n,{className:`size-4`,"aria-hidden":`true`}):(0,S.jsx)(r,{className:`size-4`,"aria-hidden":`true`}),e]}),l?(0,S.jsx)(`p`,{role:`status`,className:`text-sm text-secondary`,children:`Copied.`}):null,!i||f?(0,S.jsxs)(`details`,{open:f||void 0,className:`text-sm text-secondary`,children:[(0,S.jsx)(`summary`,{className:`min-h-11 w-fit cursor-pointer py-3`,children:f?`Copy unavailable. Select the text below.`:`Preview text`}),(0,S.jsxs)(`label`,{htmlFor:c,className:`sr-only`,children:[e,` text`]}),(0,S.jsx)(`textarea`,{id:c,readOnly:!0,rows:f&&i?3:8,value:t,className:`mt-2 w-full rounded-md border border-default bg-bg p-3 text-sm leading-6 text-heading`})]}):null]})}function A(){return o()||h()?(0,S.jsxs)(`div`,{className:`page-container`,children:[(0,S.jsx)(`h1`,{className:`page-title`,children:`Agent setup`}),(0,S.jsx)(`p`,{className:`mt-3 text-sm text-secondary`,children:`Open Agent setup in your own Canonry instance to connect your agent.`}),l()?(0,S.jsx)(`a`,{className:`mt-4 inline-block text-sm underline`,href:C,target:`_blank`,rel:`noopener noreferrer`,children:`Read the connection guide`}):null]}):(0,S.jsx)(j,{})}function j(){let e=b(),{isAdmin:n}=_(),r=c(),i=l(),a=y(!e,e?.health),o=a.data?.apiStatus,s=o?.state===`ok`?o.mcp:void 0,d=s?.status===g.available&&s.hosted?.status===u.ready?s.hosted:void 0,m=s?.hosted?.status===u.unavailable?s.hosted.reason:void 0,h=`${window.location.origin}${f()}`,v=`This server has not confirmed a public URL and OAuth sign-in. Ask your administrator to check the connection configuration or update Canonry.`;a.isPending?v=`Checking the instance’s hosted connection settings.`:m?v=n&&r?D[m]:`Ask your Canonry administrator to finish hosted connection setup for this instance.`:o?.state===`error`?v=`The instance’s connection settings could not be checked. Try again after the service is available.`:s?.status===g[`not-supported`]&&(v=`This deployment does not provide hosted MCP connections. Ask your administrator for a supported connection.`);let x=d?`Help me connect this existing Canonry instance to ChatGPT or Claude Desktop using its remote MCP URL: ${d.url}
4
4
 
5
5
  Use the client's remote MCP connection flow with OAuth sign-in. For Claude, choose Register automatically if asked how to register the OAuth client. Have me sign in to Canonry in the browser and review the requested access before approving it. Keep passwords, API keys, browser sessions, and other credentials out of chat. Do not install software, run local commands, create another instance, or broaden access.
6
6
 
@@ -1 +1 @@
1
- import{r as e}from"./rolldown-runtime-XKyaHtl9.js";import{it as t}from"./vendor-lucide-CPeGWK5C.js";import{r as n}from"./vendor-markdown-Bdsu1JLE.js";import{b as r}from"./vendor-tanstack-CXaF1vMI.js";import{pt as i,r as a,t as o}from"./ToneBadge-Bk7cBexZ.js";import{Jt as s,Y as c,i as l}from"./react-query-BKjNH2ek.js";import{t as u}from"./card-qOcJFZhl.js";var d=e(t(),1),f=n(),p=100;function m(e){if(e===`all`)return;let t=Number.parseInt(e,10);return new Date(Date.now()-t*24*60*60*1e3).toISOString()}function h(e){let t=e.userAgent?.toLowerCase()??``;return t.includes(`canonry-mcp`)?`MCP`:t.includes(`canonry-cli`)?`CLI`:t.includes(`mozilla/`)?`Dashboard`:e.actor===`scheduler`?`Scheduler`:e.actor===`agent`?`Agent`:e.actor===`mcp`?`MCP`:e.actor===`cli`?`CLI`:e.actor}function g(e){return/delete|remove|revoke|disconnect|failed|refused/.test(e)?`negative`:/create|add|connect|completed/.test(e)?`positive`:/update|replace|sync|apply/.test(e)?`caution`:`neutral`}function _(e){return[e.action,e.actor,e.entityType,e.entityId,e.actorSession,e.userAgent,e.diff==null?``:JSON.stringify(e.diff)].filter(Boolean).join(` `).toLowerCase()}function v({projectName:e}){let[t,n]=(0,d.useState)(0),[v,y]=(0,d.useState)(`90d`),[b,x]=(0,d.useState)(``),[S,C]=(0,d.useState)(``),w=(0,d.useMemo)(()=>m(v),[v]),T={limit:p,offset:t*p,since:w,actor:b||void 0},E=r({...c({client:i,path:{name:e??``},query:T}),enabled:!!e}),D=r({...l({client:i,query:T}),enabled:!e}),O=r({...s({client:i}),enabled:!e}),k=e?E:D,A=k.data??[],j=(0,d.useMemo)(()=>new Map((O.data??[]).map(e=>[e.id,e.displayName||e.name])),[O.data]),M=S.trim().toLowerCase(),N=(0,d.useMemo)(()=>M?A.filter(e=>_(e).includes(M)):A,[A,M]),P=e=>{n(0),e()};return k.isLoading?(0,f.jsx)(`p`,{className:`supporting-copy mt-6`,role:`status`,children:`Loading change history…`}):(0,f.jsxs)(`section`,{className:`mt-6`,"aria-labelledby":`change-history-heading`,children:[(0,f.jsxs)(`div`,{className:`section-head section-head-inline`,children:[(0,f.jsxs)(`div`,{children:[(0,f.jsx)(`p`,{className:`eyebrow eyebrow-soft`,children:`Audit trail`}),(0,f.jsx)(`h2`,{id:`change-history-heading`,children:`Change history`}),(0,f.jsx)(`p`,{className:`supporting-copy mt-1 max-w-2xl`,children:`Configuration and operator actions. Execution outcomes remain in Runs.`})]}),(0,f.jsx)(a,{type:`button`,variant:`outline`,size:`sm`,onClick:()=>void k.refetch(),disabled:k.isFetching,children:k.isFetching?`Refreshing…`:`Refresh`})]}),(0,f.jsxs)(`div`,{className:`mt-4 grid gap-2 sm:grid-cols-3`,children:[(0,f.jsx)(`input`,{type:`search`,"aria-label":`Search change history`,value:S,onChange:e=>C(e.target.value),placeholder:`Search actions, entities, or details`,className:`min-h-11 rounded-md border border-base bg-bg px-3 text-sm text-strong placeholder-mono-600 focus:outline-none focus-visible:ring-1 focus-visible:ring-mono-600`}),(0,f.jsxs)(`select`,{"aria-label":`Filter change history by actor`,value:b,onChange:e=>P(()=>x(e.target.value)),className:`min-h-11 rounded-md border border-base bg-bg px-3 text-sm text-strong focus:outline-none focus-visible:ring-1 focus-visible:ring-mono-600`,children:[(0,f.jsx)(`option`,{value:``,children:`All actors`}),(0,f.jsx)(`option`,{value:`api`,children:`API and dashboard`}),(0,f.jsx)(`option`,{value:`cli`,children:`CLI`}),(0,f.jsx)(`option`,{value:`scheduler`,children:`Scheduler`}),(0,f.jsx)(`option`,{value:`agent`,children:`Agent`}),(0,f.jsx)(`option`,{value:`mcp`,children:`MCP`})]}),(0,f.jsxs)(`select`,{"aria-label":`Filter change history by date range`,value:v,onChange:e=>P(()=>y(e.target.value)),className:`min-h-11 rounded-md border border-base bg-bg px-3 text-sm text-strong focus:outline-none focus-visible:ring-1 focus-visible:ring-mono-600`,children:[(0,f.jsx)(`option`,{value:`30d`,children:`Last 30 days`}),(0,f.jsx)(`option`,{value:`90d`,children:`Last 90 days`}),(0,f.jsx)(`option`,{value:`365d`,children:`Last year`}),(0,f.jsx)(`option`,{value:`all`,children:`All retained history`})]})]}),k.isError?(0,f.jsxs)(u,{className:`surface-card empty-card mt-4`,children:[(0,f.jsx)(`h3`,{children:`Change history unavailable`}),(0,f.jsx)(`p`,{children:k.error instanceof Error?k.error.message:`Could not load the audit trail.`})]}):N.length===0?(0,f.jsxs)(u,{className:`surface-card empty-card mt-4`,children:[(0,f.jsx)(`h3`,{children:`No changes match these filters`}),(0,f.jsx)(`p`,{children:`Widen the date range or clear the actor and search filters.`})]}):(0,f.jsx)(`div`,{className:`evidence-table-wrap mt-4`,children:(0,f.jsxs)(`table`,{className:`evidence-table`,children:[(0,f.jsx)(`thead`,{children:(0,f.jsxs)(`tr`,{children:[(0,f.jsx)(`th`,{children:`When`}),e?null:(0,f.jsx)(`th`,{children:`Scope`}),(0,f.jsx)(`th`,{children:`Action`}),(0,f.jsx)(`th`,{children:`Entity`}),(0,f.jsx)(`th`,{children:`Origin`}),(0,f.jsx)(`th`,{children:`Details`})]})}),(0,f.jsx)(`tbody`,{children:N.map(t=>(0,f.jsxs)(`tr`,{children:[(0,f.jsx)(`td`,{className:`whitespace-nowrap tabular-nums text-muted`,children:new Date(t.createdAt).toLocaleString()}),e?null:(0,f.jsx)(`td`,{className:`text-secondary`,children:t.projectId?j.get(t.projectId)??`Deleted project · ${t.projectId}`:`Instance settings`}),(0,f.jsx)(`td`,{children:(0,f.jsx)(o,{tone:g(t.action),children:t.action})}),(0,f.jsxs)(`td`,{children:[(0,f.jsx)(`span`,{className:`text-strong`,children:t.entityType}),t.entityId?(0,f.jsx)(`span`,{className:`mt-0.5 block max-w-48 truncate font-mono text-[11px] text-faint`,title:t.entityId,children:t.entityId}):null]}),(0,f.jsxs)(`td`,{children:[(0,f.jsx)(`span`,{className:`text-secondary`,children:h(t)}),t.actorSession?(0,f.jsxs)(`span`,{className:`mt-0.5 block max-w-40 truncate font-mono text-[11px] text-faint`,title:t.actorSession,children:[`Session `,t.actorSession]}):null]}),(0,f.jsx)(`td`,{children:t.diff==null?(0,f.jsx)(`span`,{className:`text-faint`,children:`No field diff`}):(0,f.jsxs)(`details`,{children:[(0,f.jsx)(`summary`,{className:`min-h-11 cursor-pointer py-3 text-sm text-secondary hover:text-strong`,children:`View diff`}),(0,f.jsx)(`pre`,{className:`max-h-72 max-w-xl overflow-auto whitespace-pre-wrap break-words rounded-md bg-bg-elevated p-3 text-xs text-secondary`,children:JSON.stringify(t.diff,null,2)})]})})]},t.id))})]})}),!k.isError&&(t>0||A.length===p)?(0,f.jsxs)(`div`,{className:`mt-4 flex items-center justify-between gap-3`,children:[(0,f.jsx)(a,{type:`button`,variant:`outline`,size:`sm`,disabled:t===0,onClick:()=>n(e=>Math.max(0,e-1)),children:`Previous`}),(0,f.jsxs)(`span`,{className:`text-xs tabular-nums text-muted`,children:[`Page `,t+1]}),(0,f.jsx)(a,{type:`button`,variant:`outline`,size:`sm`,disabled:A.length<p,onClick:()=>n(e=>e+1),children:`Next`})]}):null]})}export{v as t};
1
+ import{r as e}from"./rolldown-runtime-XKyaHtl9.js";import{rt as t}from"./vendor-lucide-4KkDquAu.js";import{r as n}from"./vendor-markdown-9SSeLNHZ.js";import{b as r}from"./vendor-tanstack-pEsPGDvT.js";import{pt as i,r as a,t as o}from"./ToneBadge-DYEbxp5S.js";import{Jt as s,Y as c,i as l}from"./react-query-P6OZ-MPl.js";import{t as u}from"./card-im88-x1b.js";var d=e(t(),1),f=n(),p=100;function m(e){if(e===`all`)return;let t=Number.parseInt(e,10);return new Date(Date.now()-t*24*60*60*1e3).toISOString()}function h(e){let t=e.userAgent?.toLowerCase()??``;return t.includes(`canonry-mcp`)?`MCP`:t.includes(`canonry-cli`)?`CLI`:t.includes(`mozilla/`)?`Dashboard`:e.actor===`scheduler`?`Scheduler`:e.actor===`agent`?`Agent`:e.actor===`mcp`?`MCP`:e.actor===`cli`?`CLI`:e.actor}function g(e){return/delete|remove|revoke|disconnect|failed|refused/.test(e)?`negative`:/create|add|connect|completed/.test(e)?`positive`:/update|replace|sync|apply/.test(e)?`caution`:`neutral`}function _(e){return[e.action,e.actor,e.entityType,e.entityId,e.actorSession,e.userAgent,e.diff==null?``:JSON.stringify(e.diff)].filter(Boolean).join(` `).toLowerCase()}function v({projectName:e}){let[t,n]=(0,d.useState)(0),[v,y]=(0,d.useState)(`90d`),[b,x]=(0,d.useState)(``),[S,C]=(0,d.useState)(``),w=(0,d.useMemo)(()=>m(v),[v]),T={limit:p,offset:t*p,since:w,actor:b||void 0},E=r({...c({client:i,path:{name:e??``},query:T}),enabled:!!e}),D=r({...l({client:i,query:T}),enabled:!e}),O=r({...s({client:i}),enabled:!e}),k=e?E:D,A=k.data??[],j=(0,d.useMemo)(()=>new Map((O.data??[]).map(e=>[e.id,e.displayName||e.name])),[O.data]),M=S.trim().toLowerCase(),N=(0,d.useMemo)(()=>M?A.filter(e=>_(e).includes(M)):A,[A,M]),P=e=>{n(0),e()};return k.isLoading?(0,f.jsx)(`p`,{className:`supporting-copy mt-6`,role:`status`,children:`Loading change history…`}):(0,f.jsxs)(`section`,{className:`mt-6`,"aria-labelledby":`change-history-heading`,children:[(0,f.jsxs)(`div`,{className:`section-head section-head-inline`,children:[(0,f.jsxs)(`div`,{children:[(0,f.jsx)(`p`,{className:`eyebrow eyebrow-soft`,children:`Audit trail`}),(0,f.jsx)(`h2`,{id:`change-history-heading`,children:`Change history`}),(0,f.jsx)(`p`,{className:`supporting-copy mt-1 max-w-2xl`,children:`Configuration and operator actions. Execution outcomes remain in Runs.`})]}),(0,f.jsx)(a,{type:`button`,variant:`outline`,size:`sm`,onClick:()=>void k.refetch(),disabled:k.isFetching,children:k.isFetching?`Refreshing…`:`Refresh`})]}),(0,f.jsxs)(`div`,{className:`mt-4 grid gap-2 sm:grid-cols-3`,children:[(0,f.jsx)(`input`,{type:`search`,"aria-label":`Search change history`,value:S,onChange:e=>C(e.target.value),placeholder:`Search actions, entities, or details`,className:`min-h-11 rounded-md border border-base bg-bg px-3 text-sm text-strong placeholder-mono-600 focus:outline-none focus-visible:ring-1 focus-visible:ring-mono-600`}),(0,f.jsxs)(`select`,{"aria-label":`Filter change history by actor`,value:b,onChange:e=>P(()=>x(e.target.value)),className:`min-h-11 rounded-md border border-base bg-bg px-3 text-sm text-strong focus:outline-none focus-visible:ring-1 focus-visible:ring-mono-600`,children:[(0,f.jsx)(`option`,{value:``,children:`All actors`}),(0,f.jsx)(`option`,{value:`api`,children:`API and dashboard`}),(0,f.jsx)(`option`,{value:`cli`,children:`CLI`}),(0,f.jsx)(`option`,{value:`scheduler`,children:`Scheduler`}),(0,f.jsx)(`option`,{value:`agent`,children:`Agent`}),(0,f.jsx)(`option`,{value:`mcp`,children:`MCP`})]}),(0,f.jsxs)(`select`,{"aria-label":`Filter change history by date range`,value:v,onChange:e=>P(()=>y(e.target.value)),className:`min-h-11 rounded-md border border-base bg-bg px-3 text-sm text-strong focus:outline-none focus-visible:ring-1 focus-visible:ring-mono-600`,children:[(0,f.jsx)(`option`,{value:`30d`,children:`Last 30 days`}),(0,f.jsx)(`option`,{value:`90d`,children:`Last 90 days`}),(0,f.jsx)(`option`,{value:`365d`,children:`Last year`}),(0,f.jsx)(`option`,{value:`all`,children:`All retained history`})]})]}),k.isError?(0,f.jsxs)(u,{className:`surface-card empty-card mt-4`,children:[(0,f.jsx)(`h3`,{children:`Change history unavailable`}),(0,f.jsx)(`p`,{children:k.error instanceof Error?k.error.message:`Could not load the audit trail.`})]}):N.length===0?(0,f.jsxs)(u,{className:`surface-card empty-card mt-4`,children:[(0,f.jsx)(`h3`,{children:`No changes match these filters`}),(0,f.jsx)(`p`,{children:`Widen the date range or clear the actor and search filters.`})]}):(0,f.jsx)(`div`,{className:`evidence-table-wrap mt-4`,children:(0,f.jsxs)(`table`,{className:`evidence-table`,children:[(0,f.jsx)(`thead`,{children:(0,f.jsxs)(`tr`,{children:[(0,f.jsx)(`th`,{children:`When`}),e?null:(0,f.jsx)(`th`,{children:`Scope`}),(0,f.jsx)(`th`,{children:`Action`}),(0,f.jsx)(`th`,{children:`Entity`}),(0,f.jsx)(`th`,{children:`Origin`}),(0,f.jsx)(`th`,{children:`Details`})]})}),(0,f.jsx)(`tbody`,{children:N.map(t=>(0,f.jsxs)(`tr`,{children:[(0,f.jsx)(`td`,{className:`whitespace-nowrap tabular-nums text-muted`,children:new Date(t.createdAt).toLocaleString()}),e?null:(0,f.jsx)(`td`,{className:`text-secondary`,children:t.projectId?j.get(t.projectId)??`Deleted project · ${t.projectId}`:`Instance settings`}),(0,f.jsx)(`td`,{children:(0,f.jsx)(o,{tone:g(t.action),children:t.action})}),(0,f.jsxs)(`td`,{children:[(0,f.jsx)(`span`,{className:`text-strong`,children:t.entityType}),t.entityId?(0,f.jsx)(`span`,{className:`mt-0.5 block max-w-48 truncate font-mono text-[11px] text-faint`,title:t.entityId,children:t.entityId}):null]}),(0,f.jsxs)(`td`,{children:[(0,f.jsx)(`span`,{className:`text-secondary`,children:h(t)}),t.actorSession?(0,f.jsxs)(`span`,{className:`mt-0.5 block max-w-40 truncate font-mono text-[11px] text-faint`,title:t.actorSession,children:[`Session `,t.actorSession]}):null]}),(0,f.jsx)(`td`,{children:t.diff==null?(0,f.jsx)(`span`,{className:`text-faint`,children:`No field diff`}):(0,f.jsxs)(`details`,{children:[(0,f.jsx)(`summary`,{className:`min-h-11 cursor-pointer py-3 text-sm text-secondary hover:text-strong`,children:`View diff`}),(0,f.jsx)(`pre`,{className:`max-h-72 max-w-xl overflow-auto whitespace-pre-wrap break-words rounded-md bg-bg-elevated p-3 text-xs text-secondary`,children:JSON.stringify(t.diff,null,2)})]})})]},t.id))})]})}),!k.isError&&(t>0||A.length===p)?(0,f.jsxs)(`div`,{className:`mt-4 flex items-center justify-between gap-3`,children:[(0,f.jsx)(a,{type:`button`,variant:`outline`,size:`sm`,disabled:t===0,onClick:()=>n(e=>Math.max(0,e-1)),children:`Previous`}),(0,f.jsxs)(`span`,{className:`text-xs tabular-nums text-muted`,children:[`Page `,t+1]}),(0,f.jsx)(a,{type:`button`,variant:`outline`,size:`sm`,disabled:A.length<p,onClick:()=>n(e=>e+1),children:`Next`})]}):null]})}export{v as t};
@@ -1 +1 @@
1
- import{r as e}from"./rolldown-runtime-XKyaHtl9.js";import{C as t,L as n,R as r,it as i,o as a,s as o}from"./vendor-lucide-CPeGWK5C.js";import{r as s}from"./vendor-markdown-Bdsu1JLE.js";import{At as c,Ct as l,H as u,I as d,L as f,U as p,_t as m,a as h,ln as g,q as _,r as v,t as y}from"./ToneBadge-Bk7cBexZ.js";import{t as b}from"./async-handler-Bj3TnIRw.js";import{t as x}from"./card-qOcJFZhl.js";import{t as S}from"./Hint-BsfMSR5e.js";var C=e(i(),1),w=s(),T=`https://commoncrawl.org/web-graphs`;function E(e){return e==null?`—`:e>=0xe8d4a51000?`${(e/0xe8d4a51000).toFixed(1)} TB`:e>=1e9?`${(e/1e9).toFixed(1)} GB`:e>=1e6?`${(e/1e6).toFixed(1)} MB`:e>=1e3?`${(e/1e3).toFixed(1)} KB`:`${e} B`}function D(e){if(!e)return`—`;let t=Date.now()-new Date(e).getTime(),n=Math.floor(t/6e4);if(n<1)return`just now`;if(n<60)return`${n}m ago`;let r=Math.floor(n/60);return r<24?`${r}h ago`:`${Math.floor(r/24)}d ago`}function O(e){switch(e){case`ready`:return`positive`;case`failed`:return`negative`;case`downloading`:case`querying`:case`queued`:return`caution`}}function k(){let[e,i]=(0,C.useState)(null),[s,k]=(0,C.useState)(null),[A,j]=(0,C.useState)([]),[M,N]=(0,C.useState)([]),[P,F]=(0,C.useState)(null),[I,L]=(0,C.useState)(!0),[R,z]=(0,C.useState)(!1),[B,V]=(0,C.useState)(!1),[H,U]=(0,C.useState)(``),[W,G]=(0,C.useState)(!1),[K,q]=(0,C.useState)(null),[J,Y]=(0,C.useState)(null),X=(0,C.useCallback)(async()=>{L(!0),q(null);try{let[e,t,n,r,a]=await Promise.all([d(),p().catch(()=>null),_().catch(()=>[]),f().catch(()=>[]),u().catch(()=>null)]);i(e),k(t),j(n),N(r),F(a)}catch(e){q(e instanceof Error?e.message:`Failed to load backlinks status`)}finally{L(!1)}},[]);(0,C.useEffect)(()=>{X()},[X]);async function Z(){z(!0),q(null),Y(null);try{let e=await m();Y(e.alreadyPresent?`DuckDB already installed (${e.version}).`:`Installed DuckDB ${e.version}.`),await X()}catch(e){q(e instanceof Error?e.message:`Failed to install DuckDB`)}finally{z(!1)}}async function Q(){let e=H.trim()||void 0;V(!0),q(null),Y(null);try{let t=await g(e);Y(e?`Queued sync for ${t.release}. Download + query runs in the background.`:`Queued sync for auto-discovered release ${t.release}. Download + query runs in the background.`),U(``),G(!1),await X()}catch(e){e instanceof h&&e.code===`MISSING_DEPENDENCY`?q(`DuckDB is not installed. Install it first.`):q(e instanceof Error?e.message:`Failed to trigger sync`)}finally{V(!1)}}async function $(e){q(null),Y(null);try{await c(e),Y(`Pruned cached release ${e}.`),await X()}catch(e){q(e instanceof Error?e.message:`Failed to prune release`)}}let ee=s?.status===`ready`&&M.every(e=>e.release!==s.release);return(0,w.jsxs)(`div`,{className:`page-container`,children:[(0,w.jsx)(`div`,{className:`page-header`,children:(0,w.jsxs)(`div`,{className:`page-header-left`,children:[(0,w.jsx)(`h1`,{className:`page-title`,children:`Backlink data`}),(0,w.jsx)(`p`,{className:`page-subtitle`,children:`Manage the shared backlink source and review its latest data.`})]})}),K&&(0,w.jsx)(x,{className:`surface-card p-4 mb-4 border-negative-800/60`,children:(0,w.jsx)(`p`,{className:`text-sm text-negative`,children:K})}),J&&(0,w.jsx)(x,{className:`surface-card p-4 mb-4 border-positive-800/60`,children:(0,w.jsx)(`p`,{className:`text-sm text-positive`,children:J})}),(0,w.jsxs)(`section`,{className:`page-section-divider`,children:[(0,w.jsxs)(`div`,{className:`section-head section-head-inline`,children:[(0,w.jsxs)(`div`,{children:[(0,w.jsx)(`p`,{className:`eyebrow eyebrow-soft`,children:`Readiness`}),(0,w.jsx)(`h2`,{children:`Backlink source`})]}),e?.duckdbInstalled?(0,w.jsx)(y,{tone:`positive`,children:`Installed`}):(0,w.jsx)(y,{tone:`caution`,children:`Not installed`})]}),(0,w.jsx)(x,{className:`surface-card p-4`,children:I?(0,w.jsx)(`p`,{className:`text-sm text-muted`,children:`Checking…`}):e?.duckdbInstalled?(0,w.jsx)(`p`,{className:`text-sm text-secondary`,children:`Ready to sync a Common Crawl release.`}):(0,w.jsxs)(`div`,{className:`flex items-center justify-between gap-4`,children:[(0,w.jsx)(`p`,{className:`text-sm text-secondary`,children:`Install the local query engine to enable release syncs.`}),!l()&&(0,w.jsxs)(v,{type:`button`,size:`sm`,disabled:R,onClick:b(Z),children:[(0,w.jsx)(r,{className:`h-4 w-4 mr-1.5`,"aria-hidden":!0}),R?`Installing…`:`Install DuckDB`]})]})})]}),(0,w.jsxs)(`section`,{className:`page-section-divider`,children:[(0,w.jsxs)(`div`,{className:`section-head section-head-inline`,children:[(0,w.jsxs)(`div`,{children:[(0,w.jsx)(`p`,{className:`eyebrow eyebrow-soft`,children:`Latest sync`}),(0,w.jsxs)(`h2`,{className:`flex items-center gap-2`,children:[`Release sync`,(0,w.jsx)(S,{label:`What is a release sync?`,children:`A release sync downloads one Common Crawl dump (~16 GB) and extracts backlinks for every project in this workspace in one pass. This is the heavy job — subsequent per-project re-runs skip the download and just re-query the cached files.`})]})]}),s&&(0,w.jsx)(y,{tone:O(s.status),children:s.status})]}),(0,w.jsxs)(x,{className:`surface-card p-5`,children:[s?(0,w.jsxs)(`div`,{className:`space-y-2 text-sm`,children:[(0,w.jsxs)(`p`,{className:`text-strong`,children:[`Release `,(0,w.jsx)(`code`,{className:`text-neutral`,children:s.release})]}),s.phaseDetail&&(0,w.jsx)(`p`,{className:`text-secondary`,children:s.phaseDetail}),(0,w.jsxs)(`div`,{className:`grid grid-cols-2 md:grid-cols-4 gap-4 text-xs text-muted pt-2`,children:[(0,w.jsxs)(`div`,{children:[(0,w.jsx)(`p`,{className:`text-faint uppercase tracking-wide`,children:`Projects`}),(0,w.jsx)(`p`,{className:`text-neutral mt-0.5`,children:s.projectsProcessed??`—`})]}),(0,w.jsxs)(`div`,{children:[(0,w.jsxs)(`p`,{className:`text-faint uppercase tracking-wide flex items-center gap-1`,children:[`Rows`,(0,w.jsx)(S,{label:`What are rows?`,children:`Total number of (project, referring domain) pairs persisted in SQLite from this sync, across every project in the workspace.`})]}),(0,w.jsx)(`p`,{className:`text-neutral mt-0.5`,children:s.domainsDiscovered??`—`})]}),(0,w.jsxs)(`div`,{children:[(0,w.jsx)(`p`,{className:`text-faint uppercase tracking-wide`,children:`Started`}),(0,w.jsx)(`p`,{className:`text-neutral mt-0.5`,children:D(s.downloadStartedAt??s.createdAt)})]}),(0,w.jsxs)(`div`,{children:[(0,w.jsx)(`p`,{className:`text-faint uppercase tracking-wide`,children:`Finished`}),(0,w.jsx)(`p`,{className:`text-neutral mt-0.5`,children:D(s.queryFinishedAt)})]})]}),s.error&&(0,w.jsx)(`p`,{className:`text-sm text-negative-400 pt-2`,children:s.error})]}):(0,w.jsx)(`p`,{className:`text-sm text-muted`,children:`No release sync has run in this workspace yet.`}),ee&&(0,w.jsx)(`div`,{className:`mt-4 rounded border border-caution-800/60 bg-caution-950/20 p-3`,children:(0,w.jsxs)(`div`,{className:`flex items-start gap-2`,children:[(0,w.jsx)(a,{className:`h-4 w-4 text-caution-400 shrink-0 mt-0.5`,"aria-hidden":!0}),(0,w.jsxs)(`div`,{className:`text-sm text-neutral leading-relaxed`,children:[(0,w.jsx)(`p`,{className:`font-medium text-caution-200`,children:`Cached files for this release are missing.`}),(0,w.jsx)(`p`,{className:`mt-1 text-secondary`,children:`Sync this release again, or sync the newest release, before refreshing individual projects.`})]})]})}),(0,w.jsxs)(`div`,{className:`mt-4 rounded border border-base bg-bg-elevated/40 p-3`,children:[(0,w.jsxs)(`div`,{className:`flex items-start justify-between gap-3 mb-3`,children:[(0,w.jsxs)(`div`,{children:[(0,w.jsx)(`p`,{className:`text-[10px] uppercase tracking-wide text-muted`,children:`Auto-detected release`}),P?(0,w.jsxs)(`p`,{className:`text-sm text-strong mt-0.5`,children:[(0,w.jsx)(`code`,{className:`text-heading`,children:P.release}),(0,w.jsxs)(`span`,{className:`ml-2 text-xs text-muted`,children:[`Vertex `,E(P.vertexBytes),`, edges `,E(P.edgesBytes)]})]}):(0,w.jsx)(`p`,{className:`text-sm text-muted mt-0.5`,children:I?`Checking Common Crawl…`:`Could not find a release. Choose one below.`}),(0,w.jsxs)(`a`,{href:T,target:`_blank`,rel:`noopener noreferrer`,className:`mt-1 inline-flex items-center gap-1 text-xs text-secondary hover:text-strong focus:text-strong focus:outline-none focus-visible:ring-1 focus-visible:ring-mono-500 rounded`,children:[`Browse all Common Crawl web-graph releases`,(0,w.jsx)(n,{className:`h-3 w-3`,"aria-hidden":!0})]})]}),!l()&&(0,w.jsxs)(`div`,{className:`flex items-center gap-2 shrink-0`,children:[(0,w.jsxs)(v,{type:`button`,size:`sm`,disabled:B||!e?.duckdbInstalled||!P&&!H.trim(),onClick:b(Q),children:[(0,w.jsx)(t,{className:`h-4 w-4 mr-1.5`,"aria-hidden":!0}),B?`Queuing…`:`Run sync`]}),(0,w.jsxs)(S,{label:`What does Run sync do?`,children:[(0,w.jsxs)(`span`,{className:`block`,children:[`Downloads the auto-detected (or chosen) Common Crawl release (~16 GB) to`,` `,(0,w.jsx)(`code`,{className:`text-neutral`,children:`~/.canonry/cache/commoncrawl/`}),`, then runs a single DuckDB query that extracts referring domains for every project in this workspace.`]}),(0,w.jsxs)(`span`,{className:`mt-2 block text-secondary`,children:[`First time for a release: `,(0,w.jsx)(`span`,{className:`text-strong`,children:`~10–20 min download + ~5 min query`}),`. Re-running the same release later: `,(0,w.jsx)(`span`,{className:`text-strong`,children:`skips download, just re-queries`}),` (~5 min).`]})]})]})]}),l()?null:W?(0,w.jsxs)(`div`,{className:`flex flex-wrap items-center gap-2`,children:[(0,w.jsx)(`input`,{type:`text`,className:`flex-1 min-w-[240px] rounded border border-strong bg-transparent px-2.5 py-1.5 text-sm text-strong placeholder-mono-600 focus:border-mono-500 focus:outline-none`,placeholder:`cc-main-2026-jan-feb-mar`,value:H,onChange:e=>U(e.target.value),disabled:B,autoFocus:!0}),(0,w.jsx)(`button`,{type:`button`,className:`text-sm text-secondary hover:text-neutral focus:text-neutral focus:outline-none focus-visible:ring-1 focus-visible:ring-mono-500 rounded`,onClick:()=>{U(``),G(!1)},disabled:B,children:`Cancel`})]}):(0,w.jsx)(`button`,{type:`button`,className:`text-sm text-secondary hover:text-neutral focus:text-neutral focus:outline-none focus-visible:ring-1 focus-visible:ring-mono-500 rounded`,onClick:()=>G(!0),disabled:B,children:`Use a different release →`})]}),!e?.duckdbInstalled&&(0,w.jsx)(`p`,{className:`text-sm text-secondary mt-2`,children:`Install DuckDB first to enable sync.`})]})]}),(0,w.jsxs)(`details`,{className:`page-section-divider group`,children:[(0,w.jsx)(`summary`,{className:`cursor-pointer text-sm font-medium text-secondary hover:text-strong focus:outline-none focus-visible:ring-1 focus-visible:ring-mono-500 rounded`,children:`Technical details and cache`}),(0,w.jsxs)(`div`,{className:`mt-4`,children:[(0,w.jsx)(`p`,{className:`text-sm text-secondary mb-3`,children:`Cached releases support project re-extracts. Pruning a release does not remove saved backlink results.`}),(0,w.jsx)(x,{className:`surface-card overflow-hidden`,children:(0,w.jsxs)(`table`,{className:`w-full text-sm`,children:[(0,w.jsx)(`thead`,{children:(0,w.jsxs)(`tr`,{className:`border-b border-base text-left text-xs uppercase tracking-wide text-faint`,children:[(0,w.jsx)(`th`,{className:`px-4 py-2 font-medium`,children:`Release`}),(0,w.jsx)(`th`,{className:`px-4 py-2 font-medium`,children:`Sync status`}),(0,w.jsx)(`th`,{className:`px-4 py-2 text-right font-medium`,children:`Size`}),(0,w.jsx)(`th`,{className:`px-4 py-2 font-medium`,children:`Last used`}),!l()&&(0,w.jsx)(`th`,{className:`px-4 py-2 font-medium sr-only`,children:`Actions`})]})}),(0,w.jsxs)(`tbody`,{children:[M.map(e=>(0,w.jsxs)(`tr`,{className:`border-b border-mono-900 last:border-0`,children:[(0,w.jsx)(`td`,{className:`px-4 py-2 text-strong`,children:(0,w.jsx)(`code`,{children:e.release})}),(0,w.jsx)(`td`,{className:`px-4 py-2`,children:e.syncStatus?(0,w.jsx)(y,{tone:O(e.syncStatus),children:e.syncStatus}):(0,w.jsx)(`span`,{className:`text-faint`,children:`—`})}),(0,w.jsx)(`td`,{className:`px-4 py-2 text-right text-secondary tabular-nums`,children:E(e.bytes)}),(0,w.jsx)(`td`,{className:`px-4 py-2 text-secondary`,children:D(e.lastUsedAt)}),!l()&&(0,w.jsx)(`td`,{className:`px-4 py-2 text-right`,children:(0,w.jsxs)(`div`,{className:`inline-flex items-center gap-1`,children:[(0,w.jsxs)(v,{type:`button`,variant:`outline`,size:`sm`,onClick:()=>{$(e.release)},children:[(0,w.jsx)(o,{className:`h-4 w-4 mr-1.5`,"aria-hidden":!0}),`Prune`]}),(0,w.jsx)(S,{label:`What does Prune do?`,placement:`top`,children:`Deletes the ~16 GB cache for this release from disk. Backlink results already in SQLite remain untouched. To re-run extracts against this release, you’d have to sync it again (another ~16 GB download).`})]})})]},e.release)),M.length===0&&(0,w.jsx)(`tr`,{children:(0,w.jsx)(`td`,{className:`px-4 py-4 text-sm text-muted`,colSpan:l()?4:5,children:`No cached releases on this machine. If you ran a sync from a different machine (or deleted the cache), the backlink data is still in the database — but you’ll need to re-sync a release to run new extracts.`})})]})]})}),(0,w.jsx)(`p`,{className:`mt-3 text-xs text-muted`,children:`Common Crawl files are stored locally. DuckDB reads them; Canonry stores results in its normal database.`})]})]}),A.length>1&&(0,w.jsxs)(`section`,{className:`page-section-divider`,children:[(0,w.jsx)(`div`,{className:`section-head section-head-inline`,children:(0,w.jsxs)(`div`,{children:[(0,w.jsx)(`p`,{className:`eyebrow eyebrow-soft`,children:`History`}),(0,w.jsx)(`h2`,{children:`Past release syncs`})]})}),(0,w.jsx)(x,{className:`surface-card overflow-hidden`,children:(0,w.jsxs)(`table`,{className:`w-full text-sm`,children:[(0,w.jsx)(`thead`,{children:(0,w.jsxs)(`tr`,{className:`border-b border-base text-left text-xs uppercase tracking-wide text-faint`,children:[(0,w.jsx)(`th`,{className:`px-4 py-2 font-medium`,children:`Release`}),(0,w.jsx)(`th`,{className:`px-4 py-2 font-medium`,children:`Status`}),(0,w.jsx)(`th`,{className:`px-4 py-2 text-right font-medium`,children:`Projects`}),(0,w.jsx)(`th`,{className:`px-4 py-2 text-right font-medium`,children:`Rows`}),(0,w.jsx)(`th`,{className:`px-4 py-2 font-medium`,children:`Finished`})]})}),(0,w.jsx)(`tbody`,{children:A.map(e=>(0,w.jsxs)(`tr`,{className:`border-b border-mono-900 last:border-0`,children:[(0,w.jsx)(`td`,{className:`px-4 py-2 text-strong`,children:(0,w.jsx)(`code`,{children:e.release})}),(0,w.jsx)(`td`,{className:`px-4 py-2`,children:(0,w.jsx)(y,{tone:O(e.status),children:e.status})}),(0,w.jsx)(`td`,{className:`px-4 py-2 text-right text-secondary tabular-nums`,children:e.projectsProcessed??`—`}),(0,w.jsx)(`td`,{className:`px-4 py-2 text-right text-secondary tabular-nums`,children:e.domainsDiscovered??`—`}),(0,w.jsx)(`td`,{className:`px-4 py-2 text-secondary`,children:D(e.queryFinishedAt??e.updatedAt)})]},e.id))})]})})]})]})}export{k as BacklinksPage};
1
+ import{r as e}from"./rolldown-runtime-XKyaHtl9.js";import{I as t,L as n,S as r,o as i,rt as a,s as o}from"./vendor-lucide-4KkDquAu.js";import{r as s}from"./vendor-markdown-9SSeLNHZ.js";import{At as c,Ct as l,H as u,I as d,L as f,U as p,_t as m,a as h,ln as g,q as _,r as v,t as y}from"./ToneBadge-DYEbxp5S.js";import{t as b}from"./async-handler-Bj3TnIRw.js";import{t as x}from"./card-im88-x1b.js";import{t as S}from"./Hint-C0TmIzHX.js";var C=e(a(),1),w=s(),T=`https://commoncrawl.org/web-graphs`;function E(e){return e==null?`—`:e>=0xe8d4a51000?`${(e/0xe8d4a51000).toFixed(1)} TB`:e>=1e9?`${(e/1e9).toFixed(1)} GB`:e>=1e6?`${(e/1e6).toFixed(1)} MB`:e>=1e3?`${(e/1e3).toFixed(1)} KB`:`${e} B`}function D(e){if(!e)return`—`;let t=Date.now()-new Date(e).getTime(),n=Math.floor(t/6e4);if(n<1)return`just now`;if(n<60)return`${n}m ago`;let r=Math.floor(n/60);return r<24?`${r}h ago`:`${Math.floor(r/24)}d ago`}function O(e){switch(e){case`ready`:return`positive`;case`failed`:return`negative`;case`downloading`:case`querying`:case`queued`:return`caution`}}function k(){let[e,a]=(0,C.useState)(null),[s,k]=(0,C.useState)(null),[A,j]=(0,C.useState)([]),[M,N]=(0,C.useState)([]),[P,F]=(0,C.useState)(null),[I,L]=(0,C.useState)(!0),[R,z]=(0,C.useState)(!1),[B,V]=(0,C.useState)(!1),[H,U]=(0,C.useState)(``),[W,G]=(0,C.useState)(!1),[K,q]=(0,C.useState)(null),[J,Y]=(0,C.useState)(null),X=(0,C.useCallback)(async()=>{L(!0),q(null);try{let[e,t,n,r,i]=await Promise.all([d(),p().catch(()=>null),_().catch(()=>[]),f().catch(()=>[]),u().catch(()=>null)]);a(e),k(t),j(n),N(r),F(i)}catch(e){q(e instanceof Error?e.message:`Failed to load backlinks status`)}finally{L(!1)}},[]);(0,C.useEffect)(()=>{X()},[X]);async function Z(){z(!0),q(null),Y(null);try{let e=await m();Y(e.alreadyPresent?`DuckDB already installed (${e.version}).`:`Installed DuckDB ${e.version}.`),await X()}catch(e){q(e instanceof Error?e.message:`Failed to install DuckDB`)}finally{z(!1)}}async function Q(){let e=H.trim()||void 0;V(!0),q(null),Y(null);try{let t=await g(e);Y(e?`Queued sync for ${t.release}. Download + query runs in the background.`:`Queued sync for auto-discovered release ${t.release}. Download + query runs in the background.`),U(``),G(!1),await X()}catch(e){e instanceof h&&e.code===`MISSING_DEPENDENCY`?q(`DuckDB is not installed. Install it first.`):q(e instanceof Error?e.message:`Failed to trigger sync`)}finally{V(!1)}}async function $(e){q(null),Y(null);try{await c(e),Y(`Pruned cached release ${e}.`),await X()}catch(e){q(e instanceof Error?e.message:`Failed to prune release`)}}let ee=s?.status===`ready`&&M.every(e=>e.release!==s.release);return(0,w.jsxs)(`div`,{className:`page-container`,children:[(0,w.jsx)(`div`,{className:`page-header`,children:(0,w.jsxs)(`div`,{className:`page-header-left`,children:[(0,w.jsx)(`h1`,{className:`page-title`,children:`Backlink data`}),(0,w.jsx)(`p`,{className:`page-subtitle`,children:`Manage the shared backlink source and review its latest data.`})]})}),K&&(0,w.jsx)(x,{className:`surface-card p-4 mb-4 border-negative-800/60`,children:(0,w.jsx)(`p`,{className:`text-sm text-negative`,children:K})}),J&&(0,w.jsx)(x,{className:`surface-card p-4 mb-4 border-positive-800/60`,children:(0,w.jsx)(`p`,{className:`text-sm text-positive`,children:J})}),(0,w.jsxs)(`section`,{className:`page-section-divider`,children:[(0,w.jsxs)(`div`,{className:`section-head section-head-inline`,children:[(0,w.jsxs)(`div`,{children:[(0,w.jsx)(`p`,{className:`eyebrow eyebrow-soft`,children:`Readiness`}),(0,w.jsx)(`h2`,{children:`Backlink source`})]}),e?.duckdbInstalled?(0,w.jsx)(y,{tone:`positive`,children:`Installed`}):(0,w.jsx)(y,{tone:`caution`,children:`Not installed`})]}),(0,w.jsx)(x,{className:`surface-card p-4`,children:I?(0,w.jsx)(`p`,{className:`text-sm text-muted`,children:`Checking…`}):e?.duckdbInstalled?(0,w.jsx)(`p`,{className:`text-sm text-secondary`,children:`Ready to sync a Common Crawl release.`}):(0,w.jsxs)(`div`,{className:`flex items-center justify-between gap-4`,children:[(0,w.jsx)(`p`,{className:`text-sm text-secondary`,children:`Install the local query engine to enable release syncs.`}),!l()&&(0,w.jsxs)(v,{type:`button`,size:`sm`,disabled:R,onClick:b(Z),children:[(0,w.jsx)(n,{className:`h-4 w-4 mr-1.5`,"aria-hidden":!0}),R?`Installing…`:`Install DuckDB`]})]})})]}),(0,w.jsxs)(`section`,{className:`page-section-divider`,children:[(0,w.jsxs)(`div`,{className:`section-head section-head-inline`,children:[(0,w.jsxs)(`div`,{children:[(0,w.jsx)(`p`,{className:`eyebrow eyebrow-soft`,children:`Latest sync`}),(0,w.jsxs)(`h2`,{className:`flex items-center gap-2`,children:[`Release sync`,(0,w.jsx)(S,{label:`What is a release sync?`,children:`A release sync downloads one Common Crawl dump (~16 GB) and extracts backlinks for every project in this workspace in one pass. This is the heavy job — subsequent per-project re-runs skip the download and just re-query the cached files.`})]})]}),s&&(0,w.jsx)(y,{tone:O(s.status),children:s.status})]}),(0,w.jsxs)(x,{className:`surface-card p-5`,children:[s?(0,w.jsxs)(`div`,{className:`space-y-2 text-sm`,children:[(0,w.jsxs)(`p`,{className:`text-strong`,children:[`Release `,(0,w.jsx)(`code`,{className:`text-neutral`,children:s.release})]}),s.phaseDetail&&(0,w.jsx)(`p`,{className:`text-secondary`,children:s.phaseDetail}),(0,w.jsxs)(`div`,{className:`grid grid-cols-2 md:grid-cols-4 gap-4 text-xs text-muted pt-2`,children:[(0,w.jsxs)(`div`,{children:[(0,w.jsx)(`p`,{className:`text-faint uppercase tracking-wide`,children:`Projects`}),(0,w.jsx)(`p`,{className:`text-neutral mt-0.5`,children:s.projectsProcessed??`—`})]}),(0,w.jsxs)(`div`,{children:[(0,w.jsxs)(`p`,{className:`text-faint uppercase tracking-wide flex items-center gap-1`,children:[`Rows`,(0,w.jsx)(S,{label:`What are rows?`,children:`Total number of (project, referring domain) pairs persisted in SQLite from this sync, across every project in the workspace.`})]}),(0,w.jsx)(`p`,{className:`text-neutral mt-0.5`,children:s.domainsDiscovered??`—`})]}),(0,w.jsxs)(`div`,{children:[(0,w.jsx)(`p`,{className:`text-faint uppercase tracking-wide`,children:`Started`}),(0,w.jsx)(`p`,{className:`text-neutral mt-0.5`,children:D(s.downloadStartedAt??s.createdAt)})]}),(0,w.jsxs)(`div`,{children:[(0,w.jsx)(`p`,{className:`text-faint uppercase tracking-wide`,children:`Finished`}),(0,w.jsx)(`p`,{className:`text-neutral mt-0.5`,children:D(s.queryFinishedAt)})]})]}),s.error&&(0,w.jsx)(`p`,{className:`text-sm text-negative-400 pt-2`,children:s.error})]}):(0,w.jsx)(`p`,{className:`text-sm text-muted`,children:`No release sync has run in this workspace yet.`}),ee&&(0,w.jsx)(`div`,{className:`mt-4 rounded border border-caution-800/60 bg-caution-950/20 p-3`,children:(0,w.jsxs)(`div`,{className:`flex items-start gap-2`,children:[(0,w.jsx)(i,{className:`h-4 w-4 text-caution-400 shrink-0 mt-0.5`,"aria-hidden":!0}),(0,w.jsxs)(`div`,{className:`text-sm text-neutral leading-relaxed`,children:[(0,w.jsx)(`p`,{className:`font-medium text-caution-200`,children:`Cached files for this release are missing.`}),(0,w.jsx)(`p`,{className:`mt-1 text-secondary`,children:`Sync this release again, or sync the newest release, before refreshing individual projects.`})]})]})}),(0,w.jsxs)(`div`,{className:`mt-4 rounded border border-base bg-bg-elevated/40 p-3`,children:[(0,w.jsxs)(`div`,{className:`flex items-start justify-between gap-3 mb-3`,children:[(0,w.jsxs)(`div`,{children:[(0,w.jsx)(`p`,{className:`text-[10px] uppercase tracking-wide text-muted`,children:`Auto-detected release`}),P?(0,w.jsxs)(`p`,{className:`text-sm text-strong mt-0.5`,children:[(0,w.jsx)(`code`,{className:`text-heading`,children:P.release}),(0,w.jsxs)(`span`,{className:`ml-2 text-xs text-muted`,children:[`Vertex `,E(P.vertexBytes),`, edges `,E(P.edgesBytes)]})]}):(0,w.jsx)(`p`,{className:`text-sm text-muted mt-0.5`,children:I?`Checking Common Crawl…`:`Could not find a release. Choose one below.`}),(0,w.jsxs)(`a`,{href:T,target:`_blank`,rel:`noopener noreferrer`,className:`mt-1 inline-flex items-center gap-1 text-xs text-secondary hover:text-strong focus:text-strong focus:outline-none focus-visible:ring-1 focus-visible:ring-mono-500 rounded`,children:[`Browse all Common Crawl web-graph releases`,(0,w.jsx)(t,{className:`h-3 w-3`,"aria-hidden":!0})]})]}),!l()&&(0,w.jsxs)(`div`,{className:`flex items-center gap-2 shrink-0`,children:[(0,w.jsxs)(v,{type:`button`,size:`sm`,disabled:B||!e?.duckdbInstalled||!P&&!H.trim(),onClick:b(Q),children:[(0,w.jsx)(r,{className:`h-4 w-4 mr-1.5`,"aria-hidden":!0}),B?`Queuing…`:`Run sync`]}),(0,w.jsxs)(S,{label:`What does Run sync do?`,children:[(0,w.jsxs)(`span`,{className:`block`,children:[`Downloads the auto-detected (or chosen) Common Crawl release (~16 GB) to`,` `,(0,w.jsx)(`code`,{className:`text-neutral`,children:`~/.canonry/cache/commoncrawl/`}),`, then runs a single DuckDB query that extracts referring domains for every project in this workspace.`]}),(0,w.jsxs)(`span`,{className:`mt-2 block text-secondary`,children:[`First time for a release: `,(0,w.jsx)(`span`,{className:`text-strong`,children:`~10–20 min download + ~5 min query`}),`. Re-running the same release later: `,(0,w.jsx)(`span`,{className:`text-strong`,children:`skips download, just re-queries`}),` (~5 min).`]})]})]})]}),l()?null:W?(0,w.jsxs)(`div`,{className:`flex flex-wrap items-center gap-2`,children:[(0,w.jsx)(`input`,{type:`text`,className:`flex-1 min-w-[240px] rounded border border-strong bg-transparent px-2.5 py-1.5 text-sm text-strong placeholder-mono-600 focus:border-mono-500 focus:outline-none`,placeholder:`cc-main-2026-jan-feb-mar`,value:H,onChange:e=>U(e.target.value),disabled:B,autoFocus:!0}),(0,w.jsx)(`button`,{type:`button`,className:`text-sm text-secondary hover:text-neutral focus:text-neutral focus:outline-none focus-visible:ring-1 focus-visible:ring-mono-500 rounded`,onClick:()=>{U(``),G(!1)},disabled:B,children:`Cancel`})]}):(0,w.jsx)(`button`,{type:`button`,className:`text-sm text-secondary hover:text-neutral focus:text-neutral focus:outline-none focus-visible:ring-1 focus-visible:ring-mono-500 rounded`,onClick:()=>G(!0),disabled:B,children:`Use a different release →`})]}),!e?.duckdbInstalled&&(0,w.jsx)(`p`,{className:`text-sm text-secondary mt-2`,children:`Install DuckDB first to enable sync.`})]})]}),(0,w.jsxs)(`details`,{className:`page-section-divider group`,children:[(0,w.jsx)(`summary`,{className:`cursor-pointer text-sm font-medium text-secondary hover:text-strong focus:outline-none focus-visible:ring-1 focus-visible:ring-mono-500 rounded`,children:`Technical details and cache`}),(0,w.jsxs)(`div`,{className:`mt-4`,children:[(0,w.jsx)(`p`,{className:`text-sm text-secondary mb-3`,children:`Cached releases support project re-extracts. Pruning a release does not remove saved backlink results.`}),(0,w.jsx)(x,{className:`surface-card overflow-hidden`,children:(0,w.jsxs)(`table`,{className:`w-full text-sm`,children:[(0,w.jsx)(`thead`,{children:(0,w.jsxs)(`tr`,{className:`border-b border-base text-left text-xs uppercase tracking-wide text-faint`,children:[(0,w.jsx)(`th`,{className:`px-4 py-2 font-medium`,children:`Release`}),(0,w.jsx)(`th`,{className:`px-4 py-2 font-medium`,children:`Sync status`}),(0,w.jsx)(`th`,{className:`px-4 py-2 text-right font-medium`,children:`Size`}),(0,w.jsx)(`th`,{className:`px-4 py-2 font-medium`,children:`Last used`}),!l()&&(0,w.jsx)(`th`,{className:`px-4 py-2 font-medium sr-only`,children:`Actions`})]})}),(0,w.jsxs)(`tbody`,{children:[M.map(e=>(0,w.jsxs)(`tr`,{className:`border-b border-mono-900 last:border-0`,children:[(0,w.jsx)(`td`,{className:`px-4 py-2 text-strong`,children:(0,w.jsx)(`code`,{children:e.release})}),(0,w.jsx)(`td`,{className:`px-4 py-2`,children:e.syncStatus?(0,w.jsx)(y,{tone:O(e.syncStatus),children:e.syncStatus}):(0,w.jsx)(`span`,{className:`text-faint`,children:`—`})}),(0,w.jsx)(`td`,{className:`px-4 py-2 text-right text-secondary tabular-nums`,children:E(e.bytes)}),(0,w.jsx)(`td`,{className:`px-4 py-2 text-secondary`,children:D(e.lastUsedAt)}),!l()&&(0,w.jsx)(`td`,{className:`px-4 py-2 text-right`,children:(0,w.jsxs)(`div`,{className:`inline-flex items-center gap-1`,children:[(0,w.jsxs)(v,{type:`button`,variant:`outline`,size:`sm`,onClick:()=>{$(e.release)},children:[(0,w.jsx)(o,{className:`h-4 w-4 mr-1.5`,"aria-hidden":!0}),`Prune`]}),(0,w.jsx)(S,{label:`What does Prune do?`,placement:`top`,children:`Deletes the ~16 GB cache for this release from disk. Backlink results already in SQLite remain untouched. To re-run extracts against this release, you’d have to sync it again (another ~16 GB download).`})]})})]},e.release)),M.length===0&&(0,w.jsx)(`tr`,{children:(0,w.jsx)(`td`,{className:`px-4 py-4 text-sm text-muted`,colSpan:l()?4:5,children:`No cached releases on this machine. If you ran a sync from a different machine (or deleted the cache), the backlink data is still in the database — but you’ll need to re-sync a release to run new extracts.`})})]})]})}),(0,w.jsx)(`p`,{className:`mt-3 text-xs text-muted`,children:`Common Crawl files are stored locally. DuckDB reads them; Canonry stores results in its normal database.`})]})]}),A.length>1&&(0,w.jsxs)(`section`,{className:`page-section-divider`,children:[(0,w.jsx)(`div`,{className:`section-head section-head-inline`,children:(0,w.jsxs)(`div`,{children:[(0,w.jsx)(`p`,{className:`eyebrow eyebrow-soft`,children:`History`}),(0,w.jsx)(`h2`,{children:`Past release syncs`})]})}),(0,w.jsx)(x,{className:`surface-card overflow-hidden`,children:(0,w.jsxs)(`table`,{className:`w-full text-sm`,children:[(0,w.jsx)(`thead`,{children:(0,w.jsxs)(`tr`,{className:`border-b border-base text-left text-xs uppercase tracking-wide text-faint`,children:[(0,w.jsx)(`th`,{className:`px-4 py-2 font-medium`,children:`Release`}),(0,w.jsx)(`th`,{className:`px-4 py-2 font-medium`,children:`Status`}),(0,w.jsx)(`th`,{className:`px-4 py-2 text-right font-medium`,children:`Projects`}),(0,w.jsx)(`th`,{className:`px-4 py-2 text-right font-medium`,children:`Rows`}),(0,w.jsx)(`th`,{className:`px-4 py-2 font-medium`,children:`Finished`})]})}),(0,w.jsx)(`tbody`,{children:A.map(e=>(0,w.jsxs)(`tr`,{className:`border-b border-mono-900 last:border-0`,children:[(0,w.jsx)(`td`,{className:`px-4 py-2 text-strong`,children:(0,w.jsx)(`code`,{children:e.release})}),(0,w.jsx)(`td`,{className:`px-4 py-2`,children:(0,w.jsx)(y,{tone:O(e.status),children:e.status})}),(0,w.jsx)(`td`,{className:`px-4 py-2 text-right text-secondary tabular-nums`,children:e.projectsProcessed??`—`}),(0,w.jsx)(`td`,{className:`px-4 py-2 text-right text-secondary tabular-nums`,children:e.domainsDiscovered??`—`}),(0,w.jsx)(`td`,{className:`px-4 py-2 text-secondary`,children:D(e.queryFinishedAt??e.updatedAt)})]},e.id))})]})})]})]})}export{k as BacklinksPage};
@@ -1 +1 @@
1
- import{r as e}from"./vendor-markdown-Bdsu1JLE.js";import{c as t,f as n,i as r,m as i,r as a,s as o,t as s,u as c}from"./vendor-recharts-CFnqWvWF.js";var l=e(),u={contentStyle:{backgroundColor:`var(--chart-tooltip-bg, #18181b)`,border:`1px solid var(--chart-tooltip-border, #3f3f46)`,borderRadius:8,fontSize:12},labelStyle:{color:`var(--chart-tooltip-label, #e4e4e7)`},itemStyle:{color:`var(--chart-tooltip-item, #a1a1aa)`}},d={fill:`var(--chart-neutral-text-dim, #8b8b93)`,fontSize:11},f=`var(--chart-grid, #27272a)`,p=`var(--chart-axis, #27272a)`,m=[`var(--chart-series-1, #34d399)`,`var(--chart-series-2, #60a5fa)`,`var(--chart-series-3, #f472b6)`,`var(--chart-series-4, #facc15)`,`var(--chart-series-5, #a78bfa)`,`var(--chart-series-6, #fb923c)`,`var(--chart-series-7, #22d3ee)`,`var(--chart-series-8, #f87171)`],h={gemini:`#60a5fa`,openai:`#34d399`,claude:`#fb923c`,perplexity:`#22d3ee`,muse:`#818cf8`,local:`#a78bfa`};function g(e,t=0){return h[e]??m[t%m.length]}var _={text:`var(--chart-neutral-text, #a1a1aa)`,textDim:`var(--chart-neutral-text-dim, #8b8b93)`,textFaint:`var(--chart-neutral-text-faint, #52525b)`,surface:`var(--chart-neutral-surface, #27272a)`,trackSubtle:`var(--chart-neutral-track-subtle, rgb(255 255 255 / 0.04))`,gridLine:`var(--chart-neutral-grid-line, rgb(255 255 255 / 0.06))`},v={positive:`var(--chart-tone-positive, #34d399)`,positiveDeep:`var(--chart-tone-positive-deep, #10b981)`,caution:`var(--chart-tone-caution, #fbbf24)`,negative:`var(--chart-tone-negative, #fb7185)`,neutral:`var(--chart-tone-neutral, #a1a1aa)`};function y(e){return e}function b(e){let t=/^(\d{4})-(\d{2})-(\d{2})/.exec(e);return t?{year:Number(t[1]),month:Number(t[2]),day:Number(t[3])}:null}function x(e){let t=String(e),n=b(t);return n?new Date(Date.UTC(n.year,n.month-1,n.day)).toLocaleDateString(void 0,{timeZone:`UTC`,month:`short`,day:`numeric`,year:`numeric`}):t}function S(e){let t=b(String(e));return t?`${t.month}/${t.day}`:String(e)}function C(e){let t=b(String(e));return t?new Date(Date.UTC(t.year,t.month-1,t.day)).toLocaleDateString(void 0,{timeZone:`UTC`,month:`short`,day:`numeric`}):String(e)}function w(e){return new Date(e).toLocaleDateString(void 0,{month:`short`,day:`numeric`,year:`numeric`})}function T(e){return new Date(e).toLocaleDateString(void 0,{month:`short`,day:`numeric`})}function E(e){return new Date(e).getFullYear()}function D(e){let t=new Date(e);return`${t.getMonth()+1}/${t.getDate()}`}function O({data:e,xKey:m,series:h,height:g=260,xTickFormatter:v,labelFormatter:y,onSelectX:b,selectedX:x,accessibilityLayer:S=!0,ariaLabel:C}){let w=[...new Set(h.map(e=>e.axisId))],T=new Map(h.map(e=>[e.label,e.formatValue])),E=e.map((t,n)=>{let r={...t};for(let t of h){if(!t.trend)continue;let i=t.trend.startIndex??0,a=t.trend.endIndex??e.length-1;n<i||n>a?r[`${t.dataKey}__trend`]=null:r[`${t.dataKey}__trend`]=a<=i?t.trend.start:t.trend.start+(t.trend.end-t.trend.start)*(n-i)/(a-i)}return r});return(0,l.jsx)(i,{width:`100%`,height:g,children:(0,l.jsxs)(s,{data:E,accessibilityLayer:S,"aria-label":C,margin:{top:8,right:8,bottom:4,left:0},onClick:b?e=>{e?.activeLabel!==void 0&&b(String(e.activeLabel))}:void 0,style:b?{cursor:`pointer`}:void 0,children:[(0,l.jsx)(t,{stroke:f,strokeDasharray:`3 3`,vertical:!1}),x!=null&&(0,l.jsx)(c,{x,yAxisId:w[0],stroke:_.text,strokeDasharray:`2 3`,strokeWidth:1}),(0,l.jsx)(r,{dataKey:m,tick:d,stroke:p,tickFormatter:v,minTickGap:24}),w.map((e,t)=>{let n=h.find(t=>t.axisId===e);return(0,l.jsx)(a,{yAxisId:e,orientation:t===1?`right`:`left`,hide:t>1,reversed:n.inverted??!1,domain:n.inverted?[1,`auto`]:[0,`auto`],tick:d,stroke:p,width:48,tickFormatter:n.formatValue},e)}),(0,l.jsx)(n,{...u,labelFormatter:e=>{let t=typeof e==`string`||typeof e==`number`?String(e):``;return y?y(t):t},formatter:(e,t)=>{let n=String(t??``);return typeof e==`number`?[T.get(n)?.(e)??e.toLocaleString(),n]:[String(e??``),n]}}),h.filter(e=>e.trend).map(e=>(0,l.jsx)(o,{yAxisId:e.axisId,dataKey:`${e.dataKey}__trend`,name:`${e.label} trend`,stroke:e.color,strokeWidth:1.5,strokeDasharray:`5 4`,strokeOpacity:.55,dot:!1,activeDot:!1,isAnimationActive:!1,legendType:`none`,tooltipType:`none`},`${e.dataKey}-trend`)),h.map(e=>(0,l.jsx)(o,{yAxisId:e.axisId,dataKey:e.dataKey,name:e.label,stroke:e.color,strokeWidth:2,dot:!1,activeDot:{r:3},connectNulls:!1,isAnimationActive:!1},e.dataKey))]})})}export{g as _,m as a,O as c,S as d,w as f,E as g,y as h,_ as i,x as l,D as m,d as n,v as o,T as p,f as r,u as s,p as t,C as u};
1
+ import{r as e}from"./vendor-markdown-9SSeLNHZ.js";import{c as t,f as n,i as r,m as i,r as a,s as o,t as s,u as c}from"./vendor-recharts-qIim36Mt.js";var l=e(),u={contentStyle:{backgroundColor:`var(--chart-tooltip-bg, #18181b)`,border:`1px solid var(--chart-tooltip-border, #3f3f46)`,borderRadius:8,fontSize:12},labelStyle:{color:`var(--chart-tooltip-label, #e4e4e7)`},itemStyle:{color:`var(--chart-tooltip-item, #a1a1aa)`}},d={fill:`var(--chart-neutral-text-dim, #8b8b93)`,fontSize:11},f=`var(--chart-grid, #27272a)`,p=`var(--chart-axis, #27272a)`,m=[`var(--chart-series-1, #34d399)`,`var(--chart-series-2, #60a5fa)`,`var(--chart-series-3, #f472b6)`,`var(--chart-series-4, #facc15)`,`var(--chart-series-5, #a78bfa)`,`var(--chart-series-6, #fb923c)`,`var(--chart-series-7, #22d3ee)`,`var(--chart-series-8, #f87171)`],h={gemini:`#60a5fa`,openai:`#34d399`,claude:`#fb923c`,perplexity:`#22d3ee`,muse:`#818cf8`,local:`#a78bfa`};function g(e,t=0){return h[e]??m[t%m.length]}var _={text:`var(--chart-neutral-text, #a1a1aa)`,textDim:`var(--chart-neutral-text-dim, #8b8b93)`,textFaint:`var(--chart-neutral-text-faint, #52525b)`,surface:`var(--chart-neutral-surface, #27272a)`,trackSubtle:`var(--chart-neutral-track-subtle, rgb(255 255 255 / 0.04))`,gridLine:`var(--chart-neutral-grid-line, rgb(255 255 255 / 0.06))`},v={positive:`var(--chart-tone-positive, #34d399)`,positiveDeep:`var(--chart-tone-positive-deep, #10b981)`,caution:`var(--chart-tone-caution, #fbbf24)`,negative:`var(--chart-tone-negative, #fb7185)`,neutral:`var(--chart-tone-neutral, #a1a1aa)`};function y(e){return e}function b(e){let t=/^(\d{4})-(\d{2})-(\d{2})/.exec(e);return t?{year:Number(t[1]),month:Number(t[2]),day:Number(t[3])}:null}function x(e){let t=String(e),n=b(t);return n?new Date(Date.UTC(n.year,n.month-1,n.day)).toLocaleDateString(void 0,{timeZone:`UTC`,month:`short`,day:`numeric`,year:`numeric`}):t}function S(e){let t=b(String(e));return t?`${t.month}/${t.day}`:String(e)}function C(e){let t=b(String(e));return t?new Date(Date.UTC(t.year,t.month-1,t.day)).toLocaleDateString(void 0,{timeZone:`UTC`,month:`short`,day:`numeric`}):String(e)}function w(e){return new Date(e).toLocaleDateString(void 0,{month:`short`,day:`numeric`,year:`numeric`})}function T(e){return new Date(e).toLocaleDateString(void 0,{month:`short`,day:`numeric`})}function E(e){return new Date(e).getFullYear()}function D(e){let t=new Date(e);return`${t.getMonth()+1}/${t.getDate()}`}function O({data:e,xKey:m,series:h,height:g=260,xTickFormatter:v,labelFormatter:y,onSelectX:b,selectedX:x,accessibilityLayer:S=!0,ariaLabel:C}){let w=[...new Set(h.map(e=>e.axisId))],T=new Map(h.map(e=>[e.label,e.formatValue])),E=e.map((t,n)=>{let r={...t};for(let t of h){if(!t.trend)continue;let i=t.trend.startIndex??0,a=t.trend.endIndex??e.length-1;n<i||n>a?r[`${t.dataKey}__trend`]=null:r[`${t.dataKey}__trend`]=a<=i?t.trend.start:t.trend.start+(t.trend.end-t.trend.start)*(n-i)/(a-i)}return r});return(0,l.jsx)(i,{width:`100%`,height:g,children:(0,l.jsxs)(s,{data:E,accessibilityLayer:S,"aria-label":C,margin:{top:8,right:8,bottom:4,left:0},onClick:b?e=>{e?.activeLabel!==void 0&&b(String(e.activeLabel))}:void 0,style:b?{cursor:`pointer`}:void 0,children:[(0,l.jsx)(t,{stroke:f,strokeDasharray:`3 3`,vertical:!1}),x!=null&&(0,l.jsx)(c,{x,yAxisId:w[0],stroke:_.text,strokeDasharray:`2 3`,strokeWidth:1}),(0,l.jsx)(r,{dataKey:m,tick:d,stroke:p,tickFormatter:v,minTickGap:24}),w.map((e,t)=>{let n=h.find(t=>t.axisId===e);return(0,l.jsx)(a,{yAxisId:e,orientation:t===1?`right`:`left`,hide:t>1,reversed:n.inverted??!1,domain:n.inverted?[1,`auto`]:[0,`auto`],tick:d,stroke:p,width:48,tickFormatter:n.formatValue},e)}),(0,l.jsx)(n,{...u,labelFormatter:e=>{let t=typeof e==`string`||typeof e==`number`?String(e):``;return y?y(t):t},formatter:(e,t)=>{let n=String(t??``);return typeof e==`number`?[T.get(n)?.(e)??e.toLocaleString(),n]:[String(e??``),n]}}),h.filter(e=>e.trend).map(e=>(0,l.jsx)(o,{yAxisId:e.axisId,dataKey:`${e.dataKey}__trend`,name:`${e.label} trend`,stroke:e.color,strokeWidth:1.5,strokeDasharray:`5 4`,strokeOpacity:.55,dot:!1,activeDot:!1,isAnimationActive:!1,legendType:`none`,tooltipType:`none`},`${e.dataKey}-trend`)),h.map(e=>(0,l.jsx)(o,{yAxisId:e.axisId,dataKey:e.dataKey,name:e.label,stroke:e.color,strokeWidth:2,dot:!1,activeDot:{r:3},connectNulls:!1,isAnimationActive:!1},e.dataKey))]})})}export{g as _,m as a,O as c,S as d,w as f,E as g,y as h,_ as i,x as l,D as m,d as n,v as o,T as p,f as r,u as s,p as t,C as u};
@@ -1 +1 @@
1
- import{r as e}from"./rolldown-runtime-XKyaHtl9.js";import{H as t,it as n}from"./vendor-lucide-CPeGWK5C.js";import{r}from"./vendor-markdown-Bdsu1JLE.js";var i=e(n(),1),a=r();function o({children:e,label:n=`More info`,placement:r=`top`,className:o}){let s=(0,i.useId)(),[c,l]=(0,i.useState)(!1);return(0,a.jsxs)(`span`,{className:`relative inline-flex ${o??``}`,children:[(0,a.jsx)(`button`,{type:`button`,"aria-label":n,"aria-describedby":c?s:void 0,className:`inline-flex h-4 w-4 items-center justify-center rounded-full text-muted hover:text-strong focus:text-strong focus:outline-none focus-visible:ring-1 focus-visible:ring-mono-500`,onMouseEnter:()=>l(!0),onMouseLeave:()=>l(!1),onFocus:()=>l(!0),onBlur:()=>l(!1),children:(0,a.jsx)(t,{className:`h-3.5 w-3.5`,"aria-hidden":!0})}),c&&(0,a.jsx)(`span`,{id:s,role:`tooltip`,className:`absolute z-50 w-64 rounded border border-strong bg-bg-elevated px-3 py-2 text-xs font-normal leading-relaxed text-strong shadow-lg ${r===`top`?`bottom-full mb-2`:`top-full mt-2`} left-1/2 -translate-x-1/2 whitespace-normal`,children:e})]})}export{o as t};
1
+ import{r as e}from"./rolldown-runtime-XKyaHtl9.js";import{V as t,rt as n}from"./vendor-lucide-4KkDquAu.js";import{r}from"./vendor-markdown-9SSeLNHZ.js";var i=e(n(),1),a=r();function o({children:e,label:n=`More info`,placement:r=`top`,className:o}){let s=(0,i.useId)(),[c,l]=(0,i.useState)(!1);return(0,a.jsxs)(`span`,{className:`relative inline-flex ${o??``}`,children:[(0,a.jsx)(`button`,{type:`button`,"aria-label":n,"aria-describedby":c?s:void 0,className:`inline-flex h-4 w-4 items-center justify-center rounded-full text-muted hover:text-strong focus:text-strong focus:outline-none focus-visible:ring-1 focus-visible:ring-mono-500`,onMouseEnter:()=>l(!0),onMouseLeave:()=>l(!1),onFocus:()=>l(!0),onBlur:()=>l(!1),children:(0,a.jsx)(t,{className:`h-3.5 w-3.5`,"aria-hidden":!0})}),c&&(0,a.jsx)(`span`,{id:s,role:`tooltip`,className:`absolute z-50 w-64 rounded border border-strong bg-bg-elevated px-3 py-2 text-xs font-normal leading-relaxed text-strong shadow-lg ${r===`top`?`bottom-full mb-2`:`top-full mt-2`} left-1/2 -translate-x-1/2 whitespace-normal`,children:e})]})}export{o as t};
@@ -1 +1 @@
1
- import{r as e}from"./vendor-markdown-Bdsu1JLE.js";import{t}from"./AuditHistoryPanel-DAY6GbzH.js";var n=e();function r(){return(0,n.jsxs)(`div`,{className:`page-container`,children:[(0,n.jsx)(`div`,{className:`page-header`,children:(0,n.jsxs)(`div`,{className:`page-header-left`,children:[(0,n.jsx)(`h1`,{className:`page-title`,children:`History`}),(0,n.jsx)(`p`,{className:`page-subtitle`,children:`Changes to projects and settings.`})]})}),(0,n.jsx)(t,{})]})}export{r as HistoryPage};
1
+ import{r as e}from"./vendor-markdown-9SSeLNHZ.js";import{t}from"./AuditHistoryPanel-DSUKF9GC.js";var n=e();function r(){return(0,n.jsxs)(`div`,{className:`page-container`,children:[(0,n.jsx)(`div`,{className:`page-header`,children:(0,n.jsxs)(`div`,{className:`page-header-left`,children:[(0,n.jsx)(`h1`,{className:`page-title`,children:`History`}),(0,n.jsx)(`p`,{className:`page-subtitle`,children:`Changes to projects and settings.`})]})}),(0,n.jsx)(t,{})]})}export{r as HistoryPage};
@@ -1 +1 @@
1
- import{r as e}from"./rolldown-runtime-XKyaHtl9.js";import{it as t}from"./vendor-lucide-CPeGWK5C.js";import{l as n}from"./vendor-radix-3k2C0Ly9.js";import{r}from"./vendor-markdown-Bdsu1JLE.js";var i=e(t(),1),a=e(n(),1),o=r();function s({text:e,placement:t=`top`}){let[n,r]=(0,i.useState)(null),s=(0,i.useRef)(null),c=(0,i.useRef)(null),l=(0,i.useRef)(!1),u=(0,i.useCallback)(()=>{if(!s.current)return;let e=s.current.getBoundingClientRect(),n=e.left+e.width/2,i=Math.min(224,window.innerWidth-16)/2;r({top:t===`bottom`?e.bottom:e.top,left:t===`bottom`?Math.max(i+8,Math.min(n,window.innerWidth-i-8)):n})},[t]);(0,i.useLayoutEffect)(()=>{if(t!==`bottom`||!n||!c.current)return;let e=c.current.getBoundingClientRect().bottom-window.innerHeight+8;if(e<=0)return;let i=Math.max(0,n.top-e);i!==n.top&&r({...n,top:i})},[t,n]);let d=(0,i.useCallback)(()=>r(null),[]),f=(0,i.useCallback)(()=>{n===null?u():d()},[n,u,d]);return(0,o.jsxs)(`span`,{className:`info-tooltip-wrapper`,onMouseEnter:u,onMouseLeave:d,children:[(0,o.jsx)(`button`,{ref:s,type:`button`,className:`info-tooltip-trigger`,"aria-label":e,"aria-expanded":n!==null,onFocus:u,onBlur:d,onPointerDown:()=>{l.current=n!==null&&s.current?.ownerDocument.activeElement===s.current},onClick:e=>{e.detail===0?f():l.current?d():u()},onKeyDown:e=>{e.key===`Escape`&&d()},children:(0,o.jsxs)(`svg`,{className:`info-tooltip-icon`,viewBox:`0 0 16 16`,fill:`none`,"aria-hidden":`true`,children:[(0,o.jsx)(`circle`,{cx:`8`,cy:`8`,r:`7`,stroke:`currentColor`,strokeWidth:`1.5`}),(0,o.jsx)(`path`,{d:`M8 7v4M8 5.5v0`,stroke:`currentColor`,strokeWidth:`1.5`,strokeLinecap:`round`})]})}),n!==null&&(0,a.createPortal)((0,o.jsx)(`span`,{ref:c,"aria-hidden":`true`,style:{position:`fixed`,top:n.top,left:n.left,transform:t===`bottom`?`translateX(-50%) translateY(8px)`:`translateX(-50%) translateY(calc(-100% - 8px))`,zIndex:9999,pointerEvents:`none`,width:t===`bottom`?`min(14rem, calc(100vw - 1rem))`:`14rem`,padding:`0.5rem 0.75rem`,fontSize:t===`bottom`?`13px`:`11px`,fontWeight:400,textTransform:`none`,letterSpacing:`normal`,lineHeight:t===`bottom`?`18px`:`1rem`,color:`var(--color-neutral-text)`,backgroundColor:`var(--color-bg-elevated)`,border:`1px solid color-mix(in oklab, var(--color-border-strong) 60%, transparent)`,borderRadius:`0.5rem`,boxShadow:`0 10px 15px -3px var(--color-shadow-tooltip), 0 4px 6px -4px var(--color-shadow-tooltip)`},children:e}),document.body)]})}export{s as t};
1
+ import{r as e}from"./rolldown-runtime-XKyaHtl9.js";import{rt as t}from"./vendor-lucide-4KkDquAu.js";import{u as n}from"./vendor-radix-BuErWiA2.js";import{r}from"./vendor-markdown-9SSeLNHZ.js";var i=e(t(),1),a=e(n(),1),o=r();function s({text:e,placement:t=`top`}){let[n,r]=(0,i.useState)(null),s=(0,i.useRef)(null),c=(0,i.useRef)(null),l=(0,i.useRef)(!1),u=(0,i.useCallback)(()=>{if(!s.current)return;let e=s.current.getBoundingClientRect(),n=e.left+e.width/2,i=Math.min(224,window.innerWidth-16)/2;r({top:t===`bottom`?e.bottom:e.top,left:t===`bottom`?Math.max(i+8,Math.min(n,window.innerWidth-i-8)):n})},[t]);(0,i.useLayoutEffect)(()=>{if(t!==`bottom`||!n||!c.current)return;let e=c.current.getBoundingClientRect().bottom-window.innerHeight+8;if(e<=0)return;let i=Math.max(0,n.top-e);i!==n.top&&r({...n,top:i})},[t,n]);let d=(0,i.useCallback)(()=>r(null),[]),f=(0,i.useCallback)(()=>{n===null?u():d()},[n,u,d]);return(0,o.jsxs)(`span`,{className:`info-tooltip-wrapper`,onMouseEnter:u,onMouseLeave:d,children:[(0,o.jsx)(`button`,{ref:s,type:`button`,className:`info-tooltip-trigger`,"aria-label":e,"aria-expanded":n!==null,onFocus:u,onBlur:d,onPointerDown:()=>{l.current=n!==null&&s.current?.ownerDocument.activeElement===s.current},onClick:e=>{e.detail===0?f():l.current?d():u()},onKeyDown:e=>{e.key===`Escape`&&d()},children:(0,o.jsxs)(`svg`,{className:`info-tooltip-icon`,viewBox:`0 0 16 16`,fill:`none`,"aria-hidden":`true`,children:[(0,o.jsx)(`circle`,{cx:`8`,cy:`8`,r:`7`,stroke:`currentColor`,strokeWidth:`1.5`}),(0,o.jsx)(`path`,{d:`M8 7v4M8 5.5v0`,stroke:`currentColor`,strokeWidth:`1.5`,strokeLinecap:`round`})]})}),n!==null&&(0,a.createPortal)((0,o.jsx)(`span`,{ref:c,"aria-hidden":`true`,style:{position:`fixed`,top:n.top,left:n.left,transform:t===`bottom`?`translateX(-50%) translateY(8px)`:`translateX(-50%) translateY(calc(-100% - 8px))`,zIndex:9999,pointerEvents:`none`,width:t===`bottom`?`min(14rem, calc(100vw - 1rem))`:`14rem`,padding:`0.5rem 0.75rem`,fontSize:t===`bottom`?`13px`:`11px`,fontWeight:400,textTransform:`none`,letterSpacing:`normal`,lineHeight:t===`bottom`?`18px`:`1rem`,color:`var(--color-neutral-text)`,backgroundColor:`var(--color-bg-elevated)`,border:`1px solid color-mix(in oklab, var(--color-border-strong) 60%, transparent)`,borderRadius:`0.5rem`,boxShadow:`0 10px 15px -3px var(--color-shadow-tooltip), 0 4px 6px -4px var(--color-shadow-tooltip)`},children:e}),document.body)]})}export{s as t};
@@ -0,0 +1,4 @@
1
+ import{r as e}from"./rolldown-runtime-XKyaHtl9.js";import{rt as t,tt as n}from"./vendor-lucide-4KkDquAu.js";import{r}from"./vendor-markdown-9SSeLNHZ.js";import{_ as i,b as a,d as o,f as s,g as c,p as l,u}from"./vendor-tanstack-pEsPGDvT.js";import{Lr as d,St as f,Tr as ee,at as p,jr as te,pt as m,r as h,si as ne,t as g,wr as _}from"./ToneBadge-DYEbxp5S.js";import{_ as v,a as y,b}from"./format-helpers-DOEct2q8.js";import{r as re}from"./account-context-DHWaWJSr.js";import{$ as x,Q as S,Z as C,et as w,it as T,qt as ie,st as ae,tt as oe}from"./react-query-P6OZ-MPl.js";import{f as E,h as D}from"./ChartPrimitives-CksxPvHn.js";import{t as O}from"./InfoTooltip-DV3_9Qp1.js";import{G as k,H as A,J as se,K as j,L as M,it as N,ln as P,on as ce,ot as F,sn as le,z as ue}from"./index-CQwjYVPD.js";import{c as I,d as de,r as L,s as fe,t as R,u as z}from"./service-CWdIU_mf.js";var B=e(t(),1),V=r(),H={heading:`Names that count as this Property`,help:`An answer mentions this Property when its text contains one of these names as whole words. Source titles and source links never count, but a link in the answer whose text is one of these names does. Qualified names are longer forms, such as the name with its street or city, for a name that other places share.`,names:`Names`,qualifiedNames:`Qualified names`,noNames:`No names are set, so answers can cite this Property but never mention it.`,edit:`Edit names`,save:`Save to draft`,saving:`Saving…`,cancel:`Cancel`,namesHint:`One name per line.`,qualifiedHint:`One per line. Each must include one of the names above plus more words, such as a street or city.`,qualifiedNote:`With qualified names set, an answer that uses only a plain name counts as a mention only when it also cites this Property’s own page. Otherwise it is left out as not tied to one property.`,draftOnly:`Saving changes the draft only. Nothing is measured differently until the setup is published.`,saved:`Saved to the draft. Publish the setup to start using these names.`,pending:`Name changes are saved in the draft and not published yet.`,review:`Review and publish`,noChanges:`No changes to save.`,staleDraft:`The draft is based on an older published setup. Open measurement setup to restart it before editing names.`,missingFromDraft:`This Property is not included in the current draft. Open measurement setup to review it.`,conflict:`The draft changed in another session. The latest names are loaded; review them and save again.`,failed:`Could not save these names. Try again.`};function U(e){return[...new Set(e.split(`
2
+ `).map(e=>e.trim()).filter(Boolean))]}function W(e,t){return e.length===t.length&&e.every((e,n)=>e===t[n])}function G(e,t){return W(e.aliases,t.aliases)&&W(e.identityAliases??[],t.identityAliases??[])}function pe(e,t,n){let{identityAliases:r,...i}=e;return n.length>0?{...i,aliases:t,identityAliases:n}:{...i,aliases:t}}function me({label:e,names:t}){return(0,V.jsxs)(`div`,{className:`space-y-1`,children:[(0,V.jsx)(`h3`,{className:`text-sm font-medium text-heading`,children:e}),(0,V.jsx)(`ul`,{className:`space-y-1`,children:t.map(e=>(0,V.jsx)(`li`,{className:`text-sm text-secondary`,children:e},e))})]})}function he({id:e,issues:t}){return t.length===0?null:(0,V.jsx)(`ul`,{id:e,className:`mt-2 space-y-1`,"aria-label":`Name warnings`,children:t.map(e=>(0,V.jsx)(`li`,{className:`text-sm text-caution`,children:_(e)},`${e.field}:${e.index}`))})}function ge({projectName:e,targetKey:t,published:n,activeRevision:r,publishedBrandNames:o,service:s=R}){let{canWrite:c}=re(),l=(0,B.useId)(),d=a({...S({client:m,path:{name:e}}),enabled:c}),f=a({...ae({client:m,path:{name:e}}),enabled:c}),p=d.data?.draft?.authoring.targets.find(e=>e.stableKey===t),ne=n.identityAliases??[],g=p!==void 0&&d.data?.draft?.baseActiveRevision===r&&!G(p,n),_=!d.isFetching&&!f.isPending,v=f.data,y=(0,B.useMemo)(()=>v?te(v):o,[v,o]),[b,x]=(0,B.useState)(!1),[C,w]=(0,B.useState)(``),[T,ie]=(0,B.useState)(``),[oe,E]=(0,B.useState)(n),[D,k]=(0,B.useState)(null),A=`${e}\u0000${t}`,[se,j]=(0,B.useState)(A);se!==A&&(j(A),x(!1),w(``),ie(``),E(n),k(null));let N=(0,B.useRef)(A);N.current=A;let P=(0,B.useMemo)(()=>U(C),[C]),ce=(0,B.useMemo)(()=>U(T),[T]),F=(0,B.useMemo)(()=>ee({aliases:P,identityAliases:ce,brandNames:y}),[P,ce,y]),le=F.filter(e=>e.field===`aliases`),ue=F.filter(e=>e.field===`identityAliases`);function I(e){w(e.aliases.join(`
3
+ `)),ie((e.identityAliases??[]).join(`
4
+ `)),E({aliases:[...e.aliases],identityAliases:[...e.identityAliases??[]]})}function de(e){return e.draft?e.draft.authoring.targets.find(e=>e.stableKey===t)??null:n}function fe(){I(g?p:n),k(null),x(!0)}function z(e){e&&I(e),k({tone:`negative`,text:H.conflict,review:!1})}let W=i({mutationFn:async i=>{let a=await s.loadDraft(e);if(!a.draft){if(G(i.names,n))return{outcome:`unchanged`};if(!G(i.base,n))return{outcome:`conflict`,latest:n};await s.createDraft(e,r),a=await s.loadDraft(e)}let o=a.draft;if(!o||!a.etag)throw Error(H.failed);if(o.baseActiveRevision!==r)return{outcome:`stale`};let c=o.authoring.targets.find(e=>e.stableKey===t);return!c||c.status!==`included`?{outcome:`missing`}:G(i.names,c)?{outcome:`unchanged`}:G(i.base,c)?(await s.upsertTarget(e,a.etag,pe(c,i.names.aliases,i.names.identityAliases)),{outcome:`saved`}):{outcome:`conflict`,latest:c}},meta:{skipGlobalErrorToast:!0},onSuccess:(e,t)=>{if(t.openFor===N.current)switch(e.outcome){case`saved`:x(!1),k({tone:`positive`,text:H.saved,review:!0});return;case`unchanged`:x(!1),k({tone:`positive`,text:H.noChanges,review:!1});return;case`stale`:k({tone:`negative`,text:H.staleDraft,review:!0});return;case`missing`:k({tone:`negative`,text:H.missingFromDraft,review:!0});return;case`conflict`:z(e.latest),d.refetch();return}},onError:(e,t)=>{t.openFor===N.current&&(L(e)?(z(null),d.refetch().then(e=>{e.isSuccess&&z(de(e.data))})):k({tone:`negative`,text:H.failed,review:!1}))}}),ge=(0,V.jsx)(u,{to:`/projects/$projectName/portfolio`,params:{projectName:e},className:`text-link underline-offset-2 hover:underline`,children:H.review}),K=n.aliases.length+ne.length;return(0,V.jsxs)(`section`,{"aria-labelledby":`property-names`,className:`page-section-divider`,children:[(0,V.jsxs)(`div`,{className:`section-head section-head-inline`,children:[(0,V.jsxs)(`div`,{className:`flex items-center gap-1`,children:[(0,V.jsx)(`h2`,{id:`property-names`,className:`text-base font-semibold text-heading`,children:H.heading}),(0,V.jsx)(O,{text:H.help})]}),(0,V.jsxs)(`div`,{className:`flex flex-wrap items-center gap-3`,children:[(0,V.jsxs)(`p`,{className:`supporting-copy`,children:[K,` `,K===1?`name`:`names`]}),c&&!b?(0,V.jsx)(h,{type:`button`,size:`sm`,variant:`outline`,className:`h-11 px-4 text-sm md:h-11`,disabled:!_,onClick:fe,children:H.edit}):null]})]}),D?(0,V.jsxs)(`p`,{role:D.tone===`negative`?`alert`:`status`,className:`mb-3 text-sm ${D.tone===`negative`?`text-negative`:`text-positive`}`,children:[D.text,D.review?(0,V.jsxs)(V.Fragment,{children:[` `,ge]}):null]}):g&&!b?(0,V.jsxs)(`p`,{role:`status`,className:`mb-3 text-sm text-caution`,children:[H.pending,` `,ge]}):null,b?(0,V.jsxs)(`form`,{className:`space-y-4`,"aria-label":`Edit names`,onSubmit:e=>{e.preventDefault(),!W.isPending&&W.mutate({names:{aliases:P,identityAliases:ce},base:oe,openFor:A})},children:[(0,V.jsxs)(`div`,{children:[(0,V.jsx)(`label`,{htmlFor:`${l}-names`,className:`block text-sm font-medium text-heading`,children:H.names}),(0,V.jsx)(`p`,{id:`${l}-names-hint`,className:`text-sm text-secondary`,children:H.namesHint}),(0,V.jsx)(`textarea`,{id:`${l}-names`,className:`mt-1 min-h-24 w-full rounded-md border border-strong bg-transparent px-3 py-2 text-sm text-strong focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-mono-400`,"aria-describedby":`${l}-names-hint${le.length?` ${l}-names-issues`:``}`,value:C,onChange:e=>w(e.target.value)}),(0,V.jsx)(he,{id:`${l}-names-issues`,issues:le}),P.length===0?(0,V.jsx)(`p`,{className:`mt-2 text-sm text-caution`,children:H.noNames}):null]}),(0,V.jsxs)(`div`,{children:[(0,V.jsx)(`label`,{htmlFor:`${l}-qualified`,className:`block text-sm font-medium text-heading`,children:H.qualifiedNames}),(0,V.jsx)(`p`,{id:`${l}-qualified-hint`,className:`text-sm text-secondary`,children:H.qualifiedHint}),(0,V.jsx)(`textarea`,{id:`${l}-qualified`,className:`mt-1 min-h-20 w-full rounded-md border border-strong bg-transparent px-3 py-2 text-sm text-strong focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-mono-400`,"aria-describedby":`${l}-qualified-hint ${l}-qualified-note${ue.length?` ${l}-qualified-issues`:``}`,value:T,onChange:e=>ie(e.target.value)}),(0,V.jsx)(he,{id:`${l}-qualified-issues`,issues:ue}),(0,V.jsx)(`p`,{id:`${l}-qualified-note`,className:`mt-2 max-w-3xl text-sm text-secondary`,children:H.qualifiedNote})]}),(0,V.jsx)(`p`,{className:`text-sm text-secondary`,children:H.draftOnly}),(0,V.jsxs)(`div`,{className:`flex flex-wrap items-center gap-3`,children:[(0,V.jsx)(M,{type:`submit`,className:`h-11 px-4 text-sm md:h-11`,disabled:W.isPending,children:W.isPending?H.saving:H.save}),(0,V.jsx)(h,{type:`button`,variant:`ghost`,className:`h-11 px-4 text-sm md:h-11`,disabled:W.isPending,onClick:()=>{x(!1),k(null)},children:H.cancel})]})]}):K===0?(0,V.jsx)(`p`,{className:`text-sm text-secondary`,children:H.noNames}):(0,V.jsxs)(`div`,{className:`grid gap-4 sm:grid-cols-2`,children:[n.aliases.length>0?(0,V.jsx)(me,{label:H.names,names:n.aliases}):null,ne.length>0?(0,V.jsx)(me,{label:H.qualifiedNames,names:ne}):null]})]})}var K=50,q={branded:{headline:`When they know your name`,technical:`Branded queries`},"non-brand":{headline:`When they don't`,technical:`Non-brand queries`}},_e={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`,identity_ambiguous:b,not_applicable:`Not applicable for this Property`},ve={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`}},J={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 Y(e){return[...e].sort((e,t)=>Number(t.classification===`assigned`)-Number(e.classification===`assigned`))}function ye(e){return`${e.expectedSlotId}:${e.usageEdgeId}`}function be({row:e}){return e.mentioned===null?(0,V.jsxs)(`span`,{className:`inline-flex flex-col items-start gap-0.5`,children:[(0,V.jsx)(g,{tone:`neutral`,children:`Not measured`}),(0,V.jsx)(`span`,{className:`text-xs text-muted`,children:`No mention signal for this Property`})]}):!e.mentioned&&e.mentionIdentity===`wrong-subject`?(0,V.jsxs)(`span`,{className:`inline-flex flex-col items-start gap-0.5`,children:[(0,V.jsx)(g,{tone:`neutral`,children:`Not mentioned`}),(0,V.jsxs)(`span`,{className:`inline-flex items-center gap-1 text-xs text-muted`,children:[F.label,(0,V.jsx)(O,{text:F.property})]})]}):(0,V.jsx)(g,{tone:e.mentioned?`positive`:`neutral`,children:e.mentioned?`Mentioned`:`Not mentioned`})}var xe=`—`;function Se({row:e}){return e.cited===null?(0,V.jsxs)(`span`,{className:`inline-flex flex-col items-start gap-0.5`,children:[(0,V.jsx)(g,{tone:`neutral`,children:`Not measured`}),(0,V.jsx)(`span`,{className:`text-xs text-muted`,children:`Sources were not fully captured`})]}):(0,V.jsx)(g,{tone:e.cited?`positive`:`neutral`,children:e.cited?`Cited`:`Not cited`})}function Ce({row:e}){return e.cited===null&&e.sources.length===0?(0,V.jsx)(`p`,{className:`py-2 text-sm text-secondary`,children:`The sources for this answer were not fully captured, so none can be shown.`}):e.sources.length===0?(0,V.jsx)(`p`,{className:`py-2 text-sm text-secondary`,children:`This answer returned no source URLs at all.`}):(0,V.jsxs)(`details`,{className:`mt-2`,"data-answer-sources":!0,children:[(0,V.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:[z,` (`,e.sources.length,`)`]}),(0,V.jsx)(`div`,{className:`overflow-x-auto`,children:(0,V.jsxs)(`table`,{className:`evidence-table min-w-[420px]`,children:[(0,V.jsxs)(`caption`,{className:`sr-only`,children:[`Source URLs for `,e.queryText]}),(0,V.jsx)(`thead`,{children:(0,V.jsxs)(`tr`,{children:[(0,V.jsx)(`th`,{children:`Match`}),(0,V.jsx)(`th`,{children:`URL`})]})}),(0,V.jsx)(`tbody`,{children:Y(e.sources).map(e=>(0,V.jsxs)(`tr`,{children:[(0,V.jsx)(`td`,{children:(0,V.jsx)(g,{tone:J[e.classification].tone,children:J[e.classification].label})}),(0,V.jsx)(`td`,{children:(0,V.jsx)(N,{url:e.sourceUrl})})]},e.sourceUrl))})]})})]})}function we({project:e,targetKey:t,resultId:n}){let r=a({...T({client:m,path:{name:e},query:{targetKey:t,resultId:n}})});if(r.isPending)return(0,V.jsx)(`p`,{className:`py-2 text-sm text-secondary`,role:`status`,"aria-live":`polite`,children:`Loading the answer…`});if(r.isError)return(0,V.jsx)(`p`,{className:`py-2 text-sm text-secondary`,role:`alert`,children:`Could not load this answer.`});let i=r.data?.answer;return i==null||i.trim()===``?(0,V.jsx)(`p`,{className:`py-2 text-sm text-secondary`,children:`This answer was measured, but its text was not stored.`}):(0,V.jsx)(`div`,{className:`py-2`,children:(0,V.jsx)(de,{headingLevel:4,copyable:!0,children:i})})}function Te(e){return _e[e.reason]??`Not measured`}function X({metric:e,signal:t,emphasis:n=!1}){if(e.state===`unavailable`)return(0,V.jsxs)(`span`,{className:`inline-flex flex-col gap-0.5`,children:[(0,V.jsx)(`span`,{className:n?`text-lg font-semibold text-secondary`:`text-sm font-medium text-secondary`,children:`Not measured`}),(0,V.jsx)(`span`,{className:`text-sm text-secondary`,children:Te(e)})]});let r=d(e.value),i=e.numerator===void 0||e.denominator===void 0?null:`${e.numerator} of ${e.denominator}`,a=y(e,t);return(0,V.jsxs)(`span`,{className:`inline-flex flex-col gap-0.5 tabular-nums`,children:[(0,V.jsx)(`span`,{className:n?`text-lg font-semibold text-heading`:`text-sm font-medium text-primary`,children:r}),i?(0,V.jsx)(`span`,{className:`text-xs text-muted`,children:i}):null,a?(0,V.jsx)(`span`,{className:`text-xs text-muted`,children:a}):null]})}function Ee(e,t,n){return C({client:m,path:{name:e},query:{scope:`property`,targetKey:t,queryClass:n}})}function De(e){return e?.properties.items.at(0)}function Oe({measuredAt:e,unmeasuredReason:t,queryClass:n}){let r=e===void 0?null:e===null?`No completed check yet`:`Measured ${E(D(e))}`;return r===null&&t===void 0?null:(0,V.jsxs)(`p`,{className:`supporting-copy`,children:[[r,t].filter(Boolean).join(` · `),r!==null&&t===void 0?` · ${q[n].technical.toLocaleLowerCase()} only`:``]})}function ke({project:e,groups:t}){return t.length===0?null:(0,V.jsxs)(`section`,{"aria-labelledby":`property-market`,className:`page-section-divider`,children:[(0,V.jsxs)(`div`,{className:`section-head section-head-inline`,children:[(0,V.jsxs)(`div`,{children:[(0,V.jsx)(`p`,{className:`eyebrow eyebrow-soft`,children:`Competitive comparison`}),(0,V.jsxs)(`h2`,{id:`property-market`,className:`text-base font-semibold text-heading`,children:[`Measured at the market level`,(0,V.jsx)(O,{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.`})]})]}),(0,V.jsx)(h,{asChild:!0,type:`button`,size:`sm`,variant:`outline`,children:(0,V.jsx)(u,{to:`/projects/$projectName`,params:{projectName:e},search:e=>j(A(e),{measurementScope:`project`}),children:`Open measurement overview`})})]}),(0,V.jsx)(`ul`,{className:`flex flex-wrap gap-2`,children:t.map(e=>(0,V.jsxs)(`li`,{className:`rounded-md border border-default px-3 py-1.5 text-sm text-strong`,children:[e.label,(0,V.jsxs)(`span`,{className:`ml-2 text-xs text-muted`,children:[e.competitors.length,` `,e.competitors.length===1?`competitor`:`competitors`]})]},e.stableKey))})]})}function Z({label:e,metric:t,signal:n,failed:r=!1}){if(t===void 0)return(0,V.jsxs)(`div`,{className:`aeo-hero-row`,children:[(0,V.jsx)(`p`,{className:`aeo-hero-row-label`,children:e}),(0,V.jsx)(`p`,{className:`aeo-hero-row-value text-base font-semibold text-secondary`,children:r?`Unavailable`:`…`}),r?(0,V.jsx)(`div`,{}):(0,V.jsx)(`div`,{className:`aeo-hero-row-bar`,"aria-hidden":`true`}),(0,V.jsx)(`p`,{className:`aeo-hero-row-detail`,children:r?`Could not be loaded`:`Loading`})]});if(t.state===`unavailable`){let n=Te(t);return(0,V.jsxs)(`div`,{className:`aeo-hero-row`,children:[(0,V.jsx)(`p`,{className:`aeo-hero-row-label`,children:e}),(0,V.jsx)(`p`,{className:`aeo-hero-row-value text-base font-semibold text-secondary`,children:`Not measured`}),(0,V.jsx)(`div`,{}),(0,V.jsx)(`p`,{className:`aeo-hero-row-detail`,children:n===`Not measured`?``:n})]})}let{figure:i,sign:a}=v(d(t.value)),o=t.numerator===void 0||t.denominator===void 0?null:`${t.numerator} of ${t.denominator}`,s=y(t,n);return(0,V.jsxs)(`div`,{className:`aeo-hero-row`,children:[(0,V.jsx)(`p`,{className:`aeo-hero-row-label`,children:e}),(0,V.jsxs)(`p`,{className:`aeo-hero-row-value text-heading`,children:[i,a?(0,V.jsx)(`span`,{className:`text-faint`,children:a}):null]}),(0,V.jsx)(`div`,{className:`aeo-hero-row-bar`,"aria-hidden":`true`,children:(0,V.jsx)(`div`,{className:`metric-card-bar-fill progress-fill-neutral`,style:{width:`${t.value*100}%`}})}),(0,V.jsxs)(`p`,{className:`aeo-hero-row-detail tabular-nums`,children:[o??``,s?(0,V.jsx)(`span`,{className:`block`,children:s}):null]})]})}function Ae({branded:e,nonBrand:t,brandedFailed:n=!1,nonBrandFailed:r=!1}){return(0,V.jsxs)(`section`,{"aria-labelledby":`property-coverage-hero`,children:[(0,V.jsx)(`h2`,{id:`property-coverage-hero`,className:`sr-only`,children:`Coverage for this Property`}),(0,V.jsxs)(`div`,{className:`space-y-5`,children:[(0,V.jsxs)(`div`,{className:`space-y-2`,children:[(0,V.jsx)(`p`,{className:`eyebrow eyebrow-soft`,children:`Non-brand · the demand to earn`}),(0,V.jsx)(Z,{label:`Mentioned`,metric:t?.mentionCoverage,signal:`mentioned`,failed:r}),(0,V.jsx)(Z,{label:`Cited`,metric:t?.citationCoverage,signal:`cited`,failed:r})]}),(0,V.jsxs)(`div`,{className:`space-y-2`,children:[(0,V.jsx)(`p`,{className:`eyebrow eyebrow-soft`,children:`Branded · already named`}),(0,V.jsx)(Z,{label:`Mentioned`,metric:e?.mentionCoverage,signal:`mentioned`,failed:n}),(0,V.jsx)(Z,{label:`Cited`,metric:e?.citationCoverage,signal:`cited`,failed:n})]})]})]})}function je({branded:e,nonBrand:t,brandedError:n,nonBrandError:r,onRetry:i}){return(0,V.jsxs)(`section`,{"aria-labelledby":`property-brand-contrast`,children:[(0,V.jsx)(`div`,{className:`section-head section-head-inline`,children:(0,V.jsxs)(`div`,{children:[(0,V.jsx)(`p`,{className:`eyebrow eyebrow-soft`,children:`The gap`}),(0,V.jsxs)(`h2`,{id:`property-brand-contrast`,className:`text-base font-semibold text-heading`,children:[`Named versus not named`,(0,V.jsx)(O,{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%.`})]})]})}),(0,V.jsx)(`div`,{className:`overflow-x-auto rounded-md border border-default`,children:(0,V.jsxs)(`table`,{className:`evidence-table min-w-[560px]`,children:[(0,V.jsx)(`caption`,{className:`sr-only`,children:`Mention and citation coverage for this Property, split by query class`}),(0,V.jsx)(`thead`,{children:(0,V.jsxs)(`tr`,{children:[(0,V.jsx)(`th`,{children:`Query type`}),(0,V.jsx)(`th`,{children:`Mentioned in the answer`}),(0,V.jsx)(`th`,{children:`Cited as a source`})]})}),(0,V.jsx)(`tbody`,{children:[{queryClass:`branded`,row:e,isError:n},{queryClass:`non-brand`,row:t,isError:r}].map(({queryClass:e,row:t,isError:n})=>(0,V.jsxs)(`tr`,{children:[(0,V.jsxs)(`td`,{children:[(0,V.jsx)(`span`,{className:`block font-medium text-heading`,children:q[e].headline}),(0,V.jsx)(`span`,{className:`mt-0.5 block text-xs text-muted`,children:q[e].technical}),t&&n?(0,V.jsxs)(`span`,{className:`mt-2 flex flex-wrap items-center gap-2 text-sm text-caution`,children:[(0,V.jsx)(`span`,{role:`status`,children:`Refresh failed.`}),(0,V.jsxs)(h,{type:`button`,size:`sm`,variant:`ghost`,className:`h-11 px-3 text-sm md:h-11`,onClick:()=>i(e),children:[`Retry `,q[e].technical.toLocaleLowerCase()]})]}):null]}),t?(0,V.jsxs)(V.Fragment,{children:[(0,V.jsx)(`td`,{children:(0,V.jsx)(X,{metric:t.mentionCoverage,signal:`mentioned`,emphasis:!0})}),(0,V.jsx)(`td`,{children:(0,V.jsx)(X,{metric:t.citationCoverage,signal:`cited`,emphasis:!0})})]}):n?(0,V.jsx)(`td`,{colSpan:2,children:(0,V.jsxs)(`div`,{className:`flex flex-wrap items-center gap-3 text-sm text-secondary`,children:[(0,V.jsxs)(`span`,{role:`alert`,children:[`Could not load `,q[e].technical.toLocaleLowerCase(),`.`]}),(0,V.jsxs)(h,{type:`button`,size:`sm`,variant:`outline`,className:`h-11 px-4 text-sm md:h-11`,onClick:()=>i(e),children:[`Retry `,q[e].technical.toLocaleLowerCase()]})]})}):(0,V.jsxs)(V.Fragment,{children:[(0,V.jsx)(`td`,{children:(0,V.jsx)(`span`,{className:`text-sm text-secondary`,children:`Loading…`})}),(0,V.jsx)(`td`,{children:(0,V.jsx)(`span`,{className:`text-sm text-secondary`,children:`Loading…`})})]})]},e))})]})})]})}function Me({row:e,queryClass:t,isError:n}){return(0,V.jsxs)(`section`,{"aria-labelledby":`property-providers`,className:`page-section-divider`,children:[(0,V.jsx)(`div`,{className:`section-head section-head-inline`,children:(0,V.jsx)(`div`,{children:(0,V.jsxs)(`h2`,{id:`property-providers`,className:`text-base font-semibold text-heading`,children:[`Which engines answer for this Property`,(0,V.jsx)(O,{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%.`})]})})}),e===void 0&&n?(0,V.jsxs)(`p`,{className:`text-sm text-secondary`,children:[`Details for `,q[t].technical.toLocaleLowerCase(),` are unavailable. Retry that query type above.`]}):e===void 0?(0,V.jsx)(`p`,{className:`text-sm text-secondary`,children:`Loading…`}):e.providers.length===0?(0,V.jsxs)(`p`,{className:`text-sm text-secondary`,children:[`No answer engine has measured `,q[t].technical.toLocaleLowerCase(),` for this Property.`,e.mentionCoverage.state===`unavailable`?` ${Te(e.mentionCoverage)}.`:``]}):(0,V.jsx)(`div`,{className:`overflow-x-auto rounded-md border border-default`,children:(0,V.jsxs)(`table`,{className:`evidence-table min-w-[520px]`,children:[(0,V.jsx)(`caption`,{className:`sr-only`,children:`Per-engine mention and citation coverage`}),(0,V.jsx)(`thead`,{children:(0,V.jsxs)(`tr`,{children:[(0,V.jsx)(`th`,{children:`Engine`}),(0,V.jsx)(`th`,{children:`Mentioned`}),(0,V.jsx)(`th`,{children:`Cited`})]})}),(0,V.jsx)(`tbody`,{children:e.providers.map(e=>(0,V.jsxs)(`tr`,{children:[(0,V.jsx)(`td`,{className:`font-medium text-heading`,children:e.provider}),(0,V.jsx)(`td`,{children:(0,V.jsx)(X,{metric:e.mentionCoverage,signal:`mentioned`})}),(0,V.jsx)(`td`,{children:(0,V.jsx)(X,{metric:e.citationCoverage,signal:`cited`})})]},e.provider))})]})})]})}function Ne(e){let t=e.questions.join(` · `);return e.questionsTruncated?`${t} +${e.questionTotal-e.questions.length} more`:t}function Pe({project:e,targetKey:t,queryClass:n}){let r=a({...w({client:m,path:{name:e},query:{targetKey:t,queryClass:n}})});if(r.isPending||r.isError)return null;let i=r.data?.competitors??[],o=r.data?.basis;return(0,V.jsxs)(`section`,{"aria-labelledby":`property-named-instead`,className:`page-section-divider`,children:[(0,V.jsxs)(`div`,{className:`section-head section-head-inline`,children:[(0,V.jsx)(`div`,{children:(0,V.jsxs)(`h2`,{id:`property-named-instead`,className:`text-base font-semibold text-heading`,children:[`Named instead of this Property`,(0,V.jsx)(O,{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.`})]})}),i.length>0?(0,V.jsxs)(`p`,{className:`supporting-copy`,children:[r.data?.total??i.length,` named`]}):null]}),i.length===0?(0,V.jsx)(`p`,{className:`text-sm text-secondary`,children:`No rival was named in the answers this Property missed. Nothing to compete with here yet.`}):(0,V.jsxs)(V.Fragment,{children:[(0,V.jsx)(`div`,{className:`overflow-x-auto rounded-md border border-default`,children:(0,V.jsxs)(`table`,{className:`evidence-table min-w-[420px]`,children:[(0,V.jsx)(`caption`,{className:`sr-only`,children:`Names the engines gave instead of this Property`}),(0,V.jsx)(`thead`,{children:(0,V.jsxs)(`tr`,{children:[(0,V.jsx)(`th`,{children:`Named`}),(0,V.jsx)(`th`,{children:`Answers`}),(0,V.jsx)(`th`,{children:`Engines`}),(0,V.jsx)(`th`,{children:`Queries`})]})}),(0,V.jsx)(`tbody`,{children:i.map(e=>(0,V.jsxs)(`tr`,{children:[(0,V.jsx)(`td`,{className:`text-strong`,children:e.name}),(0,V.jsx)(`td`,{className:`tabular-nums text-secondary`,children:e.occurrences}),(0,V.jsxs)(`td`,{className:`text-secondary`,children:[e.providers.join(`, `),e.providersTruncated?` +${e.providerTotal-e.providers.length}`:``]}),(0,V.jsx)(`td`,{className:`text-right`,children:(0,V.jsxs)(`span`,{className:`inline-flex items-center justify-end gap-1`,children:[(0,V.jsx)(`span`,{className:`tabular-nums text-secondary`,children:e.questionTotal}),(0,V.jsx)(O,{text:Ne(e)})]})})]},e.name))})]})}),o?.state===`available`?(0,V.jsxs)(`p`,{className:`supporting-copy mt-2`,children:[o.targetMissResults,` of `,o.answeredResults,` answers to `,q[n].technical.toLocaleLowerCase(),` did not name this Property.`]}):null]})]})}function Fe({questions:e,queryClass:t}){return(0,V.jsxs)(`section`,{"aria-labelledby":`property-questions`,className:`page-section-divider`,children:[(0,V.jsxs)(`div`,{className:`section-head section-head-inline`,children:[(0,V.jsx)(`div`,{children:(0,V.jsxs)(`h2`,{id:`property-questions`,className:`text-base font-semibold text-heading`,children:[q[t].technical,` assigned to this Property`]})}),(0,V.jsxs)(`p`,{className:`supporting-copy`,children:[e.length,` assigned`]})]}),e.length===0?(0,V.jsxs)(`p`,{className:`text-sm text-secondary`,children:[`No `,q[t].technical.toLocaleLowerCase(),` are assigned. Add one in advanced measurement setup to measure this class.`]}):(0,V.jsx)(`div`,{className:`overflow-x-auto rounded-md border border-default`,children:(0,V.jsxs)(`table`,{className:`evidence-table min-w-[420px]`,children:[(0,V.jsx)(`caption`,{className:`sr-only`,children:`Queries assigned to this Property`}),(0,V.jsx)(`thead`,{children:(0,V.jsx)(`tr`,{children:(0,V.jsx)(`th`,{children:`Query`})})}),(0,V.jsx)(`tbody`,{children:e.map(e=>(0,V.jsx)(`tr`,{children:(0,V.jsx)(`td`,{className:`text-secondary`,children:e})},e))})]})})]})}function Ie({urls:e}){return(0,V.jsxs)(`section`,{"aria-labelledby":`property-urls`,className:`page-section-divider`,children:[(0,V.jsxs)(`div`,{className:`section-head section-head-inline`,children:[(0,V.jsx)(`div`,{children:(0,V.jsxs)(`h2`,{id:`property-urls`,className:`text-base font-semibold text-heading`,children:[`URLs that count as this Property`,(0,V.jsx)(O,{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.`})]})}),(0,V.jsxs)(`p`,{className:`supporting-copy`,children:[e.length,` configured`]})]}),e.length===0?(0,V.jsx)(`p`,{className:`text-sm text-secondary`,children:`No URLs are configured for this Property.`}):(0,V.jsx)(`div`,{className:`overflow-x-auto rounded-md border border-default`,children:(0,V.jsxs)(`table`,{className:`evidence-table min-w-[420px]`,children:[(0,V.jsx)(`caption`,{className:`sr-only`,children:`URL matchers configured for this Property`}),(0,V.jsx)(`thead`,{children:(0,V.jsx)(`tr`,{children:(0,V.jsx)(`th`,{children:`URL`})})}),(0,V.jsx)(`tbody`,{children:e.map(e=>(0,V.jsx)(`tr`,{children:(0,V.jsx)(`td`,{className:`break-all text-secondary`,children:e})},e))})]})})]})}var Q={heading:`Cited on other queries`,help:`Answers to queries assigned to other properties that still cited one of this Property’s own pages. This Property was not measured on those queries, so these answers are not in its Mentioned or Cited rates.`,notCounted:`not in this Property’s rates`,empty:`No answer to a query assigned elsewhere cited this Property’s pages in the displayed measurement.`,loadError:`Citations from other queries could not be loaded.`,partlySaved:`Sources partly saved`};function Le({project:e,targetKey:t,queryClass:n,runId:r,targetLabels:i}){let[a,o]=(0,B.useState)(new Set),s={client:m,path:{name:e},query:{targetKey:t,queryClass:n,shape:ne[`other-queries`],limit:K,...r?{runId:r}:{}}},l=c({...oe(s),initialPageParam:s,getNextPageParam:e=>e.otherQueries?.nextCursor?{path:s.path,query:{...s.query,cursor:e.otherQueries.nextCursor}}:void 0}),d=l.data?.pages??[];if(d[0]?.measurement.state===`not_measured`)return null;let f=d.flatMap(e=>e.otherQueries?.items??[]),ee=d[0]?.otherQueries?.totalEstimate??f.length,p=e=>`${e.expectedSlotId}:${e.queryClass}`,te=q[n].technical.toLocaleLowerCase();return(0,V.jsxs)(`section`,{"aria-labelledby":`property-other-queries`,className:`page-section-divider`,children:[(0,V.jsxs)(`div`,{className:`section-head section-head-inline`,children:[(0,V.jsxs)(`div`,{className:`flex items-center gap-1`,children:[(0,V.jsx)(`h2`,{id:`property-other-queries`,className:`text-base font-semibold text-heading`,children:Q.heading}),(0,V.jsx)(O,{text:Q.help})]}),l.data?(0,V.jsxs)(`p`,{className:`supporting-copy`,children:[ee,` `,ee===1?`answer`:`answers`,` · `,te,` · `,Q.notCounted]}):null]}),l.isPending?(0,V.jsx)(`p`,{className:`text-sm text-secondary`,children:`Loading…`}):l.isError&&f.length===0?(0,V.jsxs)(`div`,{className:`flex flex-wrap items-center gap-3 text-sm text-secondary`,children:[(0,V.jsx)(`span`,{role:`alert`,children:Q.loadError}),(0,V.jsx)(h,{type:`button`,size:`sm`,variant:`outline`,className:`h-11 px-4 text-sm md:h-11`,onClick:()=>{l.refetch()},children:`Retry`})]}):f.length===0?(0,V.jsx)(`p`,{className:`text-sm text-secondary`,children:Q.empty}):(0,V.jsxs)(V.Fragment,{children:[(0,V.jsx)(`div`,{className:`overflow-x-auto rounded-md border border-default`,children:(0,V.jsxs)(`table`,{className:`evidence-table min-w-[640px]`,children:[(0,V.jsx)(`caption`,{className:`sr-only`,children:`Answers to other properties’ queries that cited this Property’s pages`}),(0,V.jsx)(`thead`,{children:(0,V.jsxs)(`tr`,{children:[(0,V.jsx)(`th`,{children:`Query`}),(0,V.jsx)(`th`,{children:`Assigned to`}),(0,V.jsx)(`th`,{children:`Pages cited`}),(0,V.jsx)(`th`,{children:(0,V.jsx)(`span`,{className:`sr-only`,children:`Answer`})})]})}),(0,V.jsx)(`tbody`,{children:f.map(t=>{let n=p(t),r=a.has(n),s=`property-other-query-${encodeURIComponent(n)}`;return(0,V.jsxs)(B.Fragment,{children:[(0,V.jsxs)(`tr`,{children:[(0,V.jsxs)(`td`,{className:`text-secondary`,children:[(0,V.jsx)(`span`,{className:`block text-sm font-medium text-heading`,children:t.queryText}),(0,V.jsx)(`span`,{className:`mt-1 block text-xs text-muted`,children:[t.provider,t.location].filter(Boolean).join(` · `)})]}),(0,V.jsx)(`td`,{children:(0,V.jsx)(`ul`,{className:`space-y-1`,children:t.assignedTargetKeys.map(t=>(0,V.jsx)(`li`,{children:(0,V.jsx)(u,{to:`/projects/$projectName/properties/$targetKey`,params:{projectName:e,targetKey:t},search:A,className:`text-sm text-link hover:underline focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-mono-400`,children:i.get(t)??t})},t))})}),(0,V.jsxs)(`td`,{children:[(0,V.jsx)(`ul`,{className:`space-y-1`,children:t.sources.map(e=>(0,V.jsx)(`li`,{className:`min-w-0`,children:(0,V.jsx)(N,{url:e.sourceUrl})},e.sourceUrl))}),t.sourcesTruncated?(0,V.jsxs)(`span`,{className:`mt-1 block text-xs text-muted`,children:[t.sourceCount,` pages in total`]}):null,t.evidenceComplete?null:(0,V.jsx)(`span`,{className:`mt-1 block text-xs text-muted`,children:Q.partlySaved})]}),(0,V.jsx)(`td`,{className:`text-right`,children:(0,V.jsx)(h,{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":r,"aria-label":r?`Hide the answer for ${t.queryText}`:`Read the answer for ${t.queryText}`,"aria-controls":r?s:void 0,onClick:()=>o(e=>{let t=new Set(e);return t.delete(n)||t.add(n),t}),children:r?`Hide answer`:`Read answer`})})]}),r?(0,V.jsx)(`tr`,{children:(0,V.jsx)(`td`,{id:s,colSpan:4,className:`bg-surface-subtle px-4`,children:(0,V.jsx)(we,{project:e,targetKey:t.assignedTargetKeys[0],resultId:t.observationId})})}):null]},n)})})]})}),l.hasNextPage?(0,V.jsxs)(`div`,{className:`mt-2 flex flex-wrap items-center gap-3 text-sm text-secondary`,children:[(0,V.jsxs)(`span`,{children:[`Showing `,f.length,` of `,ee]}),(0,V.jsx)(h,{size:`sm`,variant:`outline`,className:`h-11 px-4 text-sm md:h-11`,disabled:l.isFetchingNextPage,onClick:()=>{l.fetchNextPage()},children:l.isFetchingNextPage?`Loading…`:`Show ${K} more`})]}):null]})]})}function Re(e,t){let n=[e.marketKey?t??`the selected market`:null,e.provider?`the ${e.provider} answer engine`:null,e.model?`the ${e.model} model`:null,e.location?`location ${e.location}`:null,e.from||e.to?`a date range`:null,e.measurementRunId?`a saved check`:null].filter(e=>e!==null);return n.length===0?null:`AI Visibility is filtered to ${n.join(`, `)}. This page shows the latest measurement for ${I.allMarkets.toLocaleLowerCase()} and answer engines.`}function ze(){let{projectName:e,targetKey:t}=l({strict:!1}),r=o(),i=s({strict:!1}),d=(0,B.useMemo)(()=>k(i),[i]),[ee,te]=(0,B.useState)(new Set),_=e??``,v=t??``,y=!!_&&!!v,b=(0,B.useMemo)(()=>le(`portfolio`,ce(p())),[]),S=y&&b,{canWrite:C}=re(),w=a({...x({client:m,path:{name:_}}),enabled:S}),T=w.data?.active?.plan,ae=T?.schemaVersion===2?T:null,E=d.queryClass===`branded`||d.queryClass===`non-brand`?d.queryClass:null,D=e=>ae?.assignments.some(t=>t.targetKey===v&&t.queryClass===e)??!1,M=E??(!D(`non-brand`)&&D(`branded`)?`branded`:`non-brand`);(0,B.useEffect)(()=>{ae&&!E&&r({to:`.`,replace:!0,search:e=>j(e,{queryClass:M})})},[ae,E,M,r]);let N=a({...Ee(_,v,`branded`),enabled:S}),F=a({...Ee(_,v,`non-brand`),enabled:S}),I=De(N.data),de=De(F.data),L=M===`branded`?N.data:F.data,R=M===`branded`?I:de,H=(M===`branded`?N.isError:F.isError)&&R===void 0,U=L?.measurement.displayedRunId;P(_,{view:`property`,selection:{mode:`advanced`,scope:`property`,scopeKey:v,queryClass:M,limit:10,...U?{runId:U}:{}}});let W=R?.mentionCoverage.state===`unavailable`?Te(R.mentionCoverage):void 0,G=L===void 0?void 0:L.measurement.completedAt??null,pe=L!==void 0&&(L.measurement.state===`not_measured`||L.nextAction.kind===`run_measurement`),me=e=>j(A(e),{measurementScope:`property`,measurementScopeKey:v,queryClass:M,measurementRunId:void 0,measurementRevision:void 0,measurementTo:void 0}),he=a({...ie({client:m,path:{name:_},query:se(k(me(i)))}),enabled:S&&pe,retry:!1}).data,_e=he!==void 0&&he.selection.measurement.measuredRevision!==null&&(he.populations.find(e=>e.queryClass===M)?.summary.queryCount??0)>0,J={client:m,path:{name:_},query:{targetKey:v,queryClass:M,shape:ne.answers,limit:K,...U?{runId:U}:{}}},Y=c({...oe(J),enabled:S&&L!==void 0,initialPageParam:J,getNextPageParam:e=>e.answers?.nextCursor?{path:J.path,query:{...J.query,cursor:e.answers.nextCursor}}:void 0}),X=w.data?.active??null,Z=X?.plan.schemaVersion===2?X.plan:null,Ne=X!==null&&Z===null,Q=Z?.targets.find(e=>e.stableKey===v)??null,ze=Re(d,Z?.reportingScopes?.find(e=>e.stableKey===d.marketKey)?.label),Be=(0,B.useMemo)(()=>{if(!Z)return[];let e=new Map(Z.querySnapshots.map(e=>[e.queryId,e.queryText]));return[...new Set(Z.assignments.filter(e=>e.targetKey===v&&e.queryClass===M).flatMap(t=>{let n=e.get(t.queryId);return n===void 0?[]:[n]}))].sort((e,t)=>e.localeCompare(t))},[Z,v,M]),Ve=(0,B.useMemo)(()=>Q?.urlMatchers.map(fe)??[],[Q]),He=(0,B.useMemo)(()=>new Map((Z?.targets??[]).map(e=>[e.stableKey,e.label])),[Z]),Ue=(0,B.useMemo)(()=>Z?.groups.filter(e=>e.targetKeys.includes(v))??[],[Z,v]),$=(0,B.useMemo)(()=>(Y.data?.pages??[]).flatMap(e=>e.answers?.items??[]),[Y.data]),We=Y.data?.pages[0]?.answers?.totalEstimate??$.length,Ge=(Y.data?.pages??[]).length>0&&(Y.data?.pages??[]).every(e=>e.answers===void 0),Ke=Y.data?.pages[0]?.measurement.state,qe=(0,V.jsxs)(u,{to:`/projects/$projectName`,params:{projectName:_},search:A,className:`inline-flex items-center gap-1 text-xs text-muted hover:text-strong`,children:[(0,V.jsx)(n,{className:`size-3.5`,"aria-hidden":`true`}),`Back to AI Visibility`]});if(!y)return(0,V.jsx)(`div`,{className:`page-container`,children:(0,V.jsx)(`p`,{className:`text-sm text-muted`,children:`Missing project name or Property key in URL.`})});if(!b)return(0,V.jsxs)(`div`,{className:`page-container space-y-3`,children:[qe,(0,V.jsx)(`p`,{className:`text-sm text-muted`,children:`This view is not available here.`})]});if(w.isPending&&!w.isError)return(0,V.jsx)(`div`,{className:`page-container`,children:(0,V.jsxs)(`div`,{role:`status`,"aria-live":`polite`,children:[(0,V.jsx)(`span`,{className:`sr-only`,children:`Loading Property`}),(0,V.jsx)(`div`,{className:`h-32 animate-pulse rounded-md bg-surface-subtle`,"aria-hidden":`true`})]})});let Je=w.isError&&w.data===void 0,Ye=N.isError&&N.data===void 0,Xe=F.isError&&F.data===void 0;return Je||Ye&&Xe?(0,V.jsxs)(`div`,{className:`page-container space-y-3`,children:[qe,(0,V.jsx)(`p`,{role:`alert`,className:`text-sm text-negative`,children:`Could not load this Property.`}),(0,V.jsx)(h,{type:`button`,size:`sm`,variant:`outline`,className:`h-11 px-4 text-sm md:h-11`,onClick:()=>{w.refetch(),N.refetch(),F.refetch()},children:`Try again`})]}):!Z||!Q?(0,V.jsxs)(`div`,{className:`page-container space-y-3`,children:[qe,(0,V.jsx)(`p`,{role:`status`,className:`text-sm text-secondary`,children:Z?`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.`}),(0,V.jsx)(h,{asChild:!0,type:`button`,variant:`outline`,className:`h-11 px-4 text-sm md:h-11`,children:(0,V.jsx)(u,{to:`/projects/$projectName/portfolio`,params:{projectName:_},children:C?Ne?`Republish setup`:`Open measurement setup`:`View measurement setup`})})]}):(0,V.jsxs)(`div`,{className:`page-container space-y-8`,children:[(0,V.jsxs)(`div`,{className:`page-header`,children:[(0,V.jsxs)(`div`,{className:`page-header-left`,children:[qe,(0,V.jsx)(`h1`,{className:`page-title mt-2`,children:Q.label}),(0,V.jsxs)(`p`,{className:`page-subtitle`,children:[`Property in `,_,ze?(0,V.jsxs)(V.Fragment,{children:[` · Filters not applied `,(0,V.jsx)(O,{text:ze})]}):null]})]}),(0,V.jsxs)(`div`,{className:`page-header-right`,children:[L?(0,V.jsx)(g,{tone:ve[L.measurement.state].tone,children:ve[L.measurement.state].label}):null,R&&R.flags>0?(0,V.jsxs)(g,{tone:`caution`,children:[R.flags,` flagged`]}):null]})]}),(0,V.jsx)(Ae,{branded:I,nonBrand:de,brandedFailed:Ye,nonBrandFailed:Xe}),(0,V.jsx)(je,{branded:I,nonBrand:de,brandedError:N.isError,nonBrandError:F.isError,onRetry:e=>{e===`branded`?N.refetch():F.refetch()}}),pe?(0,V.jsxs)(`section`,{className:`flex flex-wrap items-center justify-between gap-3 border-y border-default py-4`,"aria-label":`Measurement next step`,children:[(0,V.jsx)(`p`,{className:`text-sm text-secondary`,children:f()?ue:C?`Run a measurement from the project overview to collect this Property’s coverage and source evidence.${_e?` AI Visibility still shows the last results.`:``}`:`This Property needs a new measurement before coverage and source evidence are available.`}),(0,V.jsx)(h,{asChild:!0,type:`button`,className:`h-11 px-4 text-sm md:h-11`,children:(0,V.jsx)(u,{to:`/projects/$projectName`,params:{projectName:_},search:_e?me:A,children:_e?`See the last results`:C?`Go to AI Visibility`:`View AI Visibility`})})]}):null,(0,V.jsxs)(`div`,{className:`flex flex-wrap items-end gap-4 border-y border-default py-4`,children:[(0,V.jsxs)(`div`,{className:`space-y-1`,children:[(0,V.jsx)(`label`,{htmlFor:`property-query-class`,className:`block text-sm font-medium text-heading`,children:`Query type`}),(0,V.jsxs)(`select`,{id:`property-query-class`,value:M,onChange:e=>{let t=e.target.value===`branded`?`branded`:`non-brand`;r({to:`.`,search:e=>j(e,{queryClass:t})})},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:[(0,V.jsx)(`option`,{value:`non-brand`,children:q[`non-brand`].technical}),(0,V.jsx)(`option`,{value:`branded`,children:q.branded.technical})]})]}),(0,V.jsx)(Oe,{measuredAt:G,unmeasuredReason:W,queryClass:M})]}),(0,V.jsx)(Me,{row:R,queryClass:M,isError:H}),(0,V.jsx)(Pe,{project:_,targetKey:v,queryClass:M}),(0,V.jsx)(Fe,{questions:Be,queryClass:M}),(0,V.jsx)(ge,{projectName:_,targetKey:v,published:Q,activeRevision:X.revision,publishedBrandNames:Z.identities.projectBrand.names}),(0,V.jsx)(Ie,{urls:Ve}),(0,V.jsx)(ke,{project:_,groups:Ue}),(0,V.jsxs)(`section`,{"aria-labelledby":`property-evidence`,className:`page-section-divider`,children:[(0,V.jsxs)(`div`,{className:`section-head section-head-inline`,children:[(0,V.jsx)(`div`,{children:(0,V.jsxs)(`h2`,{id:`property-evidence`,className:`text-base font-semibold text-heading`,children:[`Answers the engines gave`,(0,V.jsx)(O,{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.`})]})}),$.length>0?(0,V.jsxs)(`p`,{className:`supporting-copy`,children:[$.length,` of `,We]}):null]}),H?(0,V.jsxs)(`p`,{className:`text-sm text-secondary`,children:[`Evidence for `,q[M].technical.toLocaleLowerCase(),` is unavailable. Retry that query type above.`]}):Y.isPending&&$.length===0?(0,V.jsx)(`p`,{className:`text-sm text-secondary`,children:`Loading evidence…`}):Y.isError&&$.length===0?(0,V.jsxs)(`div`,{className:`flex flex-wrap items-center gap-3 text-sm text-secondary`,children:[(0,V.jsx)(`span`,{role:`alert`,children:`Evidence could not be loaded.`}),(0,V.jsx)(h,{type:`button`,size:`sm`,variant:`outline`,className:`h-11 px-4 text-sm md:h-11`,onClick:()=>{Y.refetch()},children:`Retry evidence`})]}):Ke===`not_measured`?(0,V.jsx)(`p`,{className:`text-sm text-secondary`,children:f()?ue:`Not measured yet. Run a measurement to collect the answers for this Property.`}):Ge?(0,V.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.`}):$.length===0?(0,V.jsx)(`p`,{className:`text-sm text-secondary`,children:`No answers matched this Property in the displayed measurement.`}):(0,V.jsxs)(V.Fragment,{children:[(0,V.jsx)(`div`,{className:`property-answer-table-container overflow-x-auto rounded-md border border-default`,children:(0,V.jsxs)(`table`,{className:`evidence-table property-evidence-table`,children:[(0,V.jsx)(`caption`,{className:`sr-only`,children:`Answers measured for this Property`}),(0,V.jsx)(`thead`,{children:(0,V.jsxs)(`tr`,{children:[(0,V.jsx)(`th`,{children:`Query`}),(0,V.jsx)(`th`,{children:`Mentioned in the answer`}),(0,V.jsx)(`th`,{children:`Cited as a source`}),(0,V.jsx)(`th`,{children:`Sources`}),(0,V.jsx)(`th`,{children:(0,V.jsx)(`span`,{className:`sr-only`,children:`Sources detail`})})]})}),(0,V.jsx)(`tbody`,{children:$.map(e=>{let t=ye(e),n=ee.has(t),r=`property-answer-${encodeURIComponent(t)}`;return(0,V.jsxs)(B.Fragment,{children:[(0,V.jsxs)(`tr`,{className:`property-answer-summary`,children:[(0,V.jsxs)(`td`,{className:`text-secondary`,children:[(0,V.jsx)(`h3`,{className:`text-sm font-medium text-heading`,children:e.queryText}),(0,V.jsx)(`span`,{className:`mt-1 block text-xs text-muted`,children:[e.provider,e.location].filter(Boolean).join(` · `)}),e.historical||e.bridged?(0,V.jsx)(`span`,{className:`mt-1 flex`,children:(0,V.jsx)(g,{tone:`caution`,children:`Historical`})}):null]}),(0,V.jsxs)(`td`,{children:[(0,V.jsx)(`span`,{className:`property-evidence-mobile-label`,"aria-hidden":`true`,children:`Mentioned`}),(0,V.jsx)(be,{row:e})]}),(0,V.jsxs)(`td`,{children:[(0,V.jsx)(`span`,{className:`property-evidence-mobile-label`,"aria-hidden":`true`,children:`Cited`}),(0,V.jsx)(Se,{row:e})]}),(0,V.jsxs)(`td`,{className:`tabular-nums text-secondary`,children:[(0,V.jsx)(`span`,{className:`property-evidence-mobile-label`,"aria-hidden":`true`,children:z}),e.cited===null?xe:e.sources.length]}),(0,V.jsx)(`td`,{className:`text-right`,children:(0,V.jsx)(h,{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":n,"aria-label":n?`Hide the answer for ${e.queryText}`:`Read the answer for ${e.queryText}`,"aria-controls":n?r:void 0,onClick:()=>te(e=>{let n=new Set(e);return n.delete(t)||n.add(t),n}),children:n?`Hide answer`:`Read answer`})})]}),n?(0,V.jsx)(`tr`,{className:`property-answer-detail`,children:(0,V.jsxs)(`td`,{id:r,colSpan:5,className:`bg-surface-subtle px-4`,children:[(0,V.jsx)(we,{project:_,targetKey:v,resultId:e.observationId}),(0,V.jsx)(Ce,{row:e})]})}):null]},t)})})]})}),Y.hasNextPage?(0,V.jsxs)(`div`,{className:`mt-2 flex flex-wrap items-center gap-3 text-sm text-secondary`,children:[(0,V.jsxs)(`span`,{children:[`Showing `,$.length,` of `,We]}),Y.isFetchNextPageError?(0,V.jsx)(`span`,{role:`alert`,children:`Could not load more evidence.`}):null,(0,V.jsx)(h,{size:`sm`,variant:`outline`,className:`h-11 px-4 text-sm md:h-11`,disabled:Y.isFetchingNextPage,onClick:()=>{Y.fetchNextPage()},children:Y.isFetchingNextPage?`Loading…`:Y.isFetchNextPageError?`Retry more evidence`:`Show ${K} more`})]}):null]})]}),L?(0,V.jsx)(Le,{project:_,targetKey:v,queryClass:M,runId:U,targetLabels:He}):null]})}export{J as EVIDENCE_LABELS,ze as MeasurementPropertyPage,Q as OTHER_QUERIES_COPY};