@canonry/canonry 7.82.0 → 7.83.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (152) hide show
  1. package/assets/agent-workspace/skills/aero/references/ai-traffic-tracking.md +20 -3
  2. package/assets/agent-workspace/skills/canonry/references/ai-traffic-tracking.md +20 -3
  3. package/assets/agent-workspace/skills/canonry/references/canonry-cli.md +35 -2
  4. package/assets/agent-workspace/skills/canonry/references/server-side-traffic.md +57 -1
  5. package/assets/assets/{AgentSetupPage-CcjQeUvK.js → AgentSetupPage-B9NOQP8a.js} +6 -6
  6. package/assets/assets/{AuditHistoryPanel-DgTvt2hQ.js → AuditHistoryPanel-Fvh4WFjq.js} +1 -1
  7. package/assets/assets/{BacklinksPage-DFQhtk4d.js → BacklinksPage-D1UHFLoV.js} +1 -1
  8. package/assets/assets/{ChartPrimitives-CfjGDL5d.js → ChartPrimitives-B5L9FUj3.js} +1 -1
  9. package/assets/assets/{Hint-Ro2RKH6t.js → Hint-CfeZmZig.js} +1 -1
  10. package/assets/assets/{HistoryPage-CkkWqQol.js → HistoryPage-CBcacDgP.js} +1 -1
  11. package/assets/assets/{InfoTooltip-CJ3IWqBk.js → InfoTooltip-DrBIPuSU.js} +1 -1
  12. package/assets/assets/MeasurementPropertyPage-ZuZpurwr.js +4 -0
  13. package/assets/assets/ProjectPage-BoqDyoGi.js +11 -0
  14. package/assets/assets/{RunsPage-B4tMl-_9.js → RunsPage-tlCk_gOw.js} +1 -1
  15. package/assets/assets/{SettingsPage-DmDdf02o.js → SettingsPage-7mRTFLFQ.js} +1 -1
  16. package/assets/assets/SiteHealthSection-l_A_AmY_.js +2 -0
  17. package/assets/assets/ToneBadge-CXyUIWzB.js +60 -0
  18. package/assets/assets/{TrafficPage-C9y8xEr6.js → TrafficPage-DQbBT3TP.js} +2 -2
  19. package/assets/assets/TrafficSourceDetailPage-D3DwE6Qd.js +1 -0
  20. package/assets/assets/{account-context-BjM5ZlYl.js → account-context-Bhgg1lEH.js} +1 -1
  21. package/assets/assets/agent-trust-copy-CKZsKhc0.js +1 -0
  22. package/assets/assets/{card-CDFncx20.js → card-B16Dvxau.js} +1 -1
  23. package/assets/assets/{extract-error-message-s3FKmMjt.js → extract-error-message-B5_v_-U8.js} +1 -1
  24. package/assets/assets/{format-helpers-CYQ-LjnQ.js → format-helpers-Bs9rrO74.js} +1 -1
  25. package/assets/assets/index-3aBRkQpI.js +60 -0
  26. package/assets/assets/{index-TBDfE2OO.css → index-BnmWwrZA.css} +1 -1
  27. package/assets/assets/{query-client-C_dAEVvf.js → query-client-D-tt1sn3.js} +1 -1
  28. package/assets/assets/react-query-DQr9PoNm.js +1 -0
  29. package/assets/assets/{react-sigma_core.esm.min-J2l6CcJl.js → react-sigma_core.esm.min-BfZVKh7v.js} +1 -1
  30. package/assets/assets/{service-BhAtQFOI.js → service-Cmt36bhL.js} +1 -1
  31. package/assets/assets/{vendor-lucide-BILL9eZH.js → vendor-lucide-CoTHJwai.js} +1 -1
  32. package/assets/assets/{vendor-markdown-DNTP_967.js → vendor-markdown-cQgSk2i0.js} +1 -1
  33. package/assets/assets/{vendor-radix-C6jOoh_7.js → vendor-radix-wS8sWIWE.js} +1 -1
  34. package/assets/assets/{vendor-recharts-PsGDYxIT.js → vendor-recharts-AnNqECZW.js} +1 -1
  35. package/assets/assets/{vendor-tanstack-BoP7BGaH.js → vendor-tanstack-q5SvZtcv.js} +1 -1
  36. package/assets/index.html +15 -15
  37. package/dist/{ads-UDOONRKQ.js → ads-BSVYKQ2L.js} +3 -3
  38. package/dist/{agent-JTEGEX6X.js → agent-L7VUHOHS.js} +7 -7
  39. package/dist/{agent-ask-PUV4EVGS.js → agent-ask-A4HQCNLV.js} +3 -3
  40. package/dist/{agent-conversations-TWTSQHBR.js → agent-conversations-L3TJJKPJ.js} +3 -3
  41. package/dist/agent-journeys-FEXRAZYN.js +86 -0
  42. package/dist/{agent-memory-ZJEXAUJB.js → agent-memory-LBTLOHUA.js} +3 -3
  43. package/dist/{agent-providers-2RQZSGMP.js → agent-providers-X7V2IHRK.js} +3 -3
  44. package/dist/{agent-transcript-YYS3XBES.js → agent-transcript-YSP2HKUZ.js} +3 -3
  45. package/dist/{analytics-RLC6PRUZ.js → analytics-FBPHES6M.js} +3 -3
  46. package/dist/{apply-Z5SSCEJ2.js → apply-PBCXZC5F.js} +3 -3
  47. package/dist/{backfill-6K2UMALK.js → backfill-NMHO3AIW.js} +9 -9
  48. package/dist/{backlinks-LDI2VTPT.js → backlinks-QMLTF2VF.js} +3 -3
  49. package/dist/{bing-SSNMNZEF.js → bing-H65WGTXU.js} +3 -3
  50. package/dist/{bootstrap-ISRV5I52.js → bootstrap-JAZNMAKP.js} +10 -10
  51. package/dist/{cdp-WU7QCPQ3.js → cdp-4DAMAHTB.js} +7 -7
  52. package/dist/{chunk-T76RQIGK.js → chunk-32U5LFIT.js} +4 -4
  53. package/dist/{chunk-SIRWPXGJ.js → chunk-33EHXZDH.js} +18 -9
  54. package/dist/{chunk-2GJLKCXL.js → chunk-3UFQI4KL.js} +114 -1
  55. package/dist/{chunk-5NDUJLUL.js → chunk-4PPF3SIU.js} +7 -7
  56. package/dist/{chunk-J7EYQFMJ.js → chunk-4XM3T65L.js} +4 -4
  57. package/dist/{chunk-QHEKMJL4.js → chunk-7Q5BSCKN.js} +2 -2
  58. package/dist/{chunk-JMUSNZJR.js → chunk-AA6P5NK3.js} +1 -1
  59. package/dist/{chunk-462CIYLY.js → chunk-CBAYQHNX.js} +1 -1
  60. package/dist/{chunk-J2DA4LUR.js → chunk-DRZDOL3P.js} +22 -22
  61. package/dist/{chunk-M7WS2BL3.js → chunk-FICCBAAY.js} +152 -5
  62. package/dist/{chunk-HDVJNYYE.js → chunk-HIC62JTS.js} +34 -5
  63. package/dist/{chunk-ZX7XDVPC.js → chunk-IPPNN5KE.js} +18 -2
  64. package/dist/{chunk-LRFCNERP.js → chunk-JCWXEVYW.js} +3 -3
  65. package/dist/{chunk-ZR3RYJF3.js → chunk-JECDHS6M.js} +5 -5
  66. package/dist/{chunk-EIDOBJF2.js → chunk-KCFIQJOL.js} +2 -2
  67. package/dist/{chunk-2FIDPBWE.js → chunk-KFMU6CLU.js} +1 -1
  68. package/dist/{chunk-OH42CAWP.js → chunk-LZGVQSZL.js} +1 -1
  69. package/dist/{chunk-JI7FDO7I.js → chunk-MTW37GXF.js} +1 -1
  70. package/dist/{chunk-RMZCQUKN.js → chunk-N3PYCQYT.js} +392 -343
  71. package/dist/{chunk-JDEHNF7K.js → chunk-NCM6PX64.js} +1 -1
  72. package/dist/{chunk-NPMJFPBM.js → chunk-OIHR2BDK.js} +3042 -2633
  73. package/dist/{chunk-GKHM5OT6.js → chunk-OMNS42ZQ.js} +2 -2
  74. package/dist/{chunk-NNUZ37NJ.js → chunk-P76XOEWL.js} +4 -4
  75. package/dist/{chunk-S6IC7ZK2.js → chunk-PHVIMUAQ.js} +2683 -2474
  76. package/dist/{chunk-SVF4P6DB.js → chunk-QAJDHHC5.js} +1 -1
  77. package/dist/{chunk-2PDDTRTG.js → chunk-S5Y633HH.js} +4 -4
  78. package/dist/{chunk-5K3S74ZX.js → chunk-SEAXXCU6.js} +3 -1
  79. package/dist/{chunk-4IYFVC22.js → chunk-SKH3N6WI.js} +3 -3
  80. package/dist/{chunk-VVOCZTNC.js → chunk-SVMTN7MI.js} +2 -2
  81. package/dist/{chunk-WB6VIQ7L.js → chunk-W5ZBMBBZ.js} +1 -1
  82. package/dist/{chunk-7ZJHKLTK.js → chunk-WA4FD5Y6.js} +1 -1
  83. package/dist/{chunk-AAMOBJXJ.js → chunk-WDEDEEWA.js} +1 -1
  84. package/dist/{chunk-F4FDJI5O.js → chunk-X7U7XYJQ.js} +3 -3
  85. package/dist/{chunk-DWFVH3E2.js → chunk-Y7WHB65J.js} +2 -2
  86. package/dist/{chunk-JP4RTZGE.js → chunk-YCRPOY2Y.js} +2 -2
  87. package/dist/{chunk-VWYB4RA4.js → chunk-YJOGWS7F.js} +2 -2
  88. package/dist/{citations-X5LS7SZX.js → citations-MNLMO33V.js} +3 -3
  89. package/dist/{cli-catalog-S4RLOOCK.js → cli-catalog-IKF4A7ZS.js} +3 -3
  90. package/dist/{cli-commands-BGNM6H6P.js → cli-commands-7UXIHESS.js} +7 -7
  91. package/dist/cli.js +14 -14
  92. package/dist/{competitor-O5YXN5SD.js → competitor-5DY5PKNU.js} +3 -3
  93. package/dist/{content-C6SO5LNZ.js → content-XNK2YY4S.js} +3 -3
  94. package/dist/{dashboard-3P6FFYCW.js → dashboard-72QZZ5Q6.js} +6 -6
  95. package/dist/{demo-OJ6C4DU3.js → demo-KD2SLCIP.js} +1 -1
  96. package/dist/{demo-server-GJXDVREB.js → demo-server-7EYKEN23.js} +12 -12
  97. package/dist/{discover-Z355GK36.js → discover-D4H4ALIE.js} +3 -3
  98. package/dist/{discover-eval-6OVS55LV.js → discover-eval-2CID2IBT.js} +3 -3
  99. package/dist/{doctor-E52VMIEP.js → doctor-OWRQNDWF.js} +3 -3
  100. package/dist/{evidence-ITVU3HYF.js → evidence-SQX4IMQM.js} +3 -3
  101. package/dist/{export-cmd-S2UD3ALT.js → export-cmd-73PYMZZ5.js} +3 -3
  102. package/dist/{ga-T3UEGAZC.js → ga-S6AKEVAL.js} +3 -3
  103. package/dist/{gbp-3G45OTYX.js → gbp-57J3AXEY.js} +3 -3
  104. package/dist/{google-YZS4HLN3.js → google-PPU5MJSV.js} +4 -4
  105. package/dist/{google-marketing-LIV6O63R.js → google-marketing-W4KZ74HX.js} +1 -1
  106. package/dist/{health-cmd-2FC73XH6.js → health-cmd-QYP4MS3E.js} +3 -3
  107. package/dist/{history-KLRMAVLG.js → history-MFHBHYH7.js} +3 -3
  108. package/dist/index.d.ts +683 -11
  109. package/dist/index.js +26 -26
  110. package/dist/{init-CTP7OZTR.js → init-R2OT2EC7.js} +12 -12
  111. package/dist/{insights-KTGRGFAN.js → insights-IIMMXGRO.js} +3 -3
  112. package/dist/intelligence-service-4D34S2P6.js +16 -0
  113. package/dist/{journeys-PF2OO5W2.js → journeys-DXXRNANM.js} +6 -5
  114. package/dist/{keys-7NTJ7TFJ.js → keys-O3T52MLX.js} +3 -3
  115. package/dist/{keyword-C37ZTBOS.js → keyword-MS23BR7O.js} +3 -3
  116. package/dist/{logs-GU223TLX.js → logs-SKR5OLTY.js} +3 -3
  117. package/dist/{mcp-2DZFAHOW.js → mcp-NFC2PBGD.js} +4 -4
  118. package/dist/mcp.js +10 -10
  119. package/dist/{measurement-plan-ZSZUAW4Y.js → measurement-plan-Z73LMQYB.js} +5 -5
  120. package/dist/{notify-GYSA5V67.js → notify-2RUWK2AR.js} +3 -3
  121. package/dist/{organic-evidence-2NLMSKHX.js → organic-evidence-BGAOEVMZ.js} +3 -3
  122. package/dist/{overview-NL3B5XME.js → overview-DONWVYZT.js} +4 -4
  123. package/dist/{project-3THJAPRN.js → project-FFSPWR6R.js} +3 -3
  124. package/dist/{query-JU5UHTGT.js → query-AXEUWIW3.js} +3 -3
  125. package/dist/{research-WLS77NOR.js → research-YURAJRCV.js} +3 -3
  126. package/dist/{results-export-RQKUM5OA.js → results-export-ECSJKZHZ.js} +3 -3
  127. package/dist/{run-H6BA7COC.js → run-27EXPBE4.js} +4 -4
  128. package/dist/{schedule-ISTF4OHX.js → schedule-NY55SZZF.js} +3 -3
  129. package/dist/{search-HIYAHDZR.js → search-RXCBX3ST.js} +3 -3
  130. package/dist/{serve-5WPYWTOF.js → serve-HWLAUXAU.js} +27 -27
  131. package/dist/{session-4B5VWFCF.js → session-LBMTUPPY.js} +14 -14
  132. package/dist/{settings-ZI4UQXJO.js → settings-IPC5SSDU.js} +3 -3
  133. package/dist/{skills-LN34DUVA.js → skills-Y3VNCWQM.js} +2 -2
  134. package/dist/{snapshot-BDPWMMDS.js → snapshot-TPDSMADU.js} +3 -3
  135. package/dist/{src-UENQLEK4.js → src-IDX2F2SR.js} +8 -2
  136. package/dist/{status-6CIRB7TO.js → status-YSQJBNM7.js} +4 -4
  137. package/dist/{technical-aeo-L435UGJL.js → technical-aeo-NMUQVIFG.js} +3 -3
  138. package/dist/{telemetry-VIY5GILS.js → telemetry-OA6W7Q54.js} +4 -4
  139. package/dist/{tools-LILY27JS.js → tools-LROEIKWI.js} +11 -11
  140. package/dist/{traffic-KHGUZSP6.js → traffic-ZJHB2TWF.js} +10 -6
  141. package/dist/{users-KLOJMJSB.js → users-NMWBTCDI.js} +3 -3
  142. package/dist/{visibility-stats-OG2HEGFX.js → visibility-stats-DE64FVOJ.js} +3 -3
  143. package/dist/{wordpress-NPVZAUSN.js → wordpress-AJWIJSM7.js} +3 -3
  144. package/package.json +1 -1
  145. package/assets/assets/MeasurementPropertyPage-Cwnda2BA.js +0 -4
  146. package/assets/assets/ProjectPage-C39ua8CG.js +0 -11
  147. package/assets/assets/SiteHealthSection-CfQePJ7s.js +0 -2
  148. package/assets/assets/ToneBadge-bXf5LaSI.js +0 -60
  149. package/assets/assets/TrafficSourceDetailPage-Dklvlek4.js +0 -1
  150. package/assets/assets/index-qWvnlyfA.js +0 -60
  151. package/assets/assets/react-query-BKozxbv1.js +0 -1
  152. package/dist/intelligence-service-YX72V6NG.js +0 -16
@@ -86,9 +86,14 @@ through these in order and say which one applies.
86
86
  read `cnry traffic status <p>` and the last sync's `syncSummary`
87
87
  (`cnry runs <p> --kind traffic-sync --format json`) before quoting recent
88
88
  days. Recent days look low while a backlog drains.
89
- 8. **Is it noise?** Unverified "AI user" fetches of `/.env`, admin paths or
90
- 404s are scanners using AI bot names. Quote verified fetches
91
- (`verificationStatus: verified`) and pages that returned 200.
89
+ 8. **Is it noise?** Scanners using AI agent names are mostly filtered already:
90
+ requests judged likely fake (credential or admin paths, or a user agent
91
+ unlike OpenAI's or Mistral's published string) are left out of AI user
92
+ fetch hits and counted as
93
+ `totals24h.aiUserFetchLikelyFakeHits`. `cnry traffic samples <p> --kind
94
+ ai-user-fetch` shows each sample's `trust` and `trustReasons`. Quote
95
+ `verified` and `likely_real` requests and pages that returned 200; treat
96
+ `unknown` as unconfirmed.
92
97
 
93
98
  ## What attribution can and cannot say
94
99
 
@@ -141,6 +146,18 @@ through these in order and say which one applies.
141
146
  fetches with status 200, group by path, and leave out `robots.txt`. These are
142
147
  the pages assistants open while answering people, even when nobody clicks.
143
148
 
149
+ **"What did an agent do on our site?"**
150
+ Read `cnry traffic agent-journeys <p> --since <date> --until <date>`, then
151
+ `cnry traffic agent-journey <p> <id>` with the same selectors. MCP equivalents
152
+ are `canonry_traffic_agent_journeys` and `canonry_traffic_agent_journey`.
153
+ Report the recorded request sequence and HTTP errors. Separate trust (each
154
+ sequence's `trustLevels`; `--trust verified|likely_real|unknown`) from request
155
+ correlation: IP/UA grouping is inferred, and requests without an IP are
156
+ unlinked. Likely fake requests are counted in `coverage.likelyFakeRequests`,
157
+ never listed; the count is null with a Property filter. Preserve source gaps and daily caps. For an Advanced
158
+ Property, use `--target-key` and report current-plan URL attribution and revision.
159
+ Do not infer clicks, a user's prompt, business outcomes or off-site browsing.
160
+
144
161
  **"Do AI visitors come back?"**
145
162
  `cnry journeys summary <p>`: `returnRate`, `returnedVia` and
146
163
  `medianDaysToReturn`. Report `keyBasis` and `partialSources` with the numbers;
@@ -79,9 +79,14 @@ through these in order and say which one applies.
79
79
  read `cnry traffic status <p>` and the last sync's `syncSummary`
80
80
  (`cnry runs <p> --kind traffic-sync --format json`) before quoting recent
81
81
  days. Recent days look low while a backlog drains.
82
- 8. **Is it noise?** Unverified "AI user" fetches of `/.env`, admin paths or
83
- 404s are scanners using AI bot names. Quote verified fetches
84
- (`verificationStatus: verified`) and pages that returned 200.
82
+ 8. **Is it noise?** Scanners using AI agent names are mostly filtered already:
83
+ requests judged likely fake (credential or admin paths, or a user agent
84
+ unlike OpenAI's or Mistral's published string) are left out of AI user
85
+ fetch hits and counted as
86
+ `totals24h.aiUserFetchLikelyFakeHits`. `cnry traffic samples <p> --kind
87
+ ai-user-fetch` shows each sample's `trust` and `trustReasons`. Quote
88
+ `verified` and `likely_real` requests and pages that returned 200; treat
89
+ `unknown` as unconfirmed.
85
90
 
86
91
  ## What attribution can and cannot say
87
92
 
@@ -134,6 +139,18 @@ through these in order and say which one applies.
134
139
  fetches with status 200, group by path, and leave out `robots.txt`. These are
135
140
  the pages assistants open while answering people, even when nobody clicks.
136
141
 
142
+ **"What did an agent do on our site?"**
143
+ Read `cnry traffic agent-journeys <p> --since <date> --until <date>`, then
144
+ `cnry traffic agent-journey <p> <id>` with the same selectors. MCP equivalents
145
+ are `canonry_traffic_agent_journeys` and `canonry_traffic_agent_journey`.
146
+ Report the recorded request sequence and HTTP errors. Separate trust (each
147
+ sequence's `trustLevels`; `--trust verified|likely_real|unknown`) from request
148
+ correlation: IP/UA grouping is inferred, and requests without an IP are
149
+ unlinked. Likely fake requests are counted in `coverage.likelyFakeRequests`,
150
+ never listed; the count is null with a Property filter. Preserve source gaps and daily caps. For an Advanced
151
+ Property, use `--target-key` and report current-plan URL attribution and revision.
152
+ Do not infer clicks, a user's prompt, business outcomes or off-site browsing.
153
+
137
154
  **"Do AI visitors come back?"**
138
155
  `cnry journeys summary <p>`: `returnRate`, `returnedVia` and
139
156
  `medianDaysToReturn`. Report `keyBasis` and `partialSources` with the numbers;
@@ -1918,6 +1918,36 @@ attribution applies equally to Simple and Advanced portfolios; Property, Target,
1918
1918
  and market attribution is unavailable. No provider call or write. Signed-in
1919
1919
  viewers and embeds cannot read samples; API read keys retain project scope.
1920
1920
 
1921
+ ### Agent request journeys
1922
+
1923
+ ```bash
1924
+ cnry traffic agent-journeys <project> --since 2026-10-20 --until 2026-10-27 --source <source-id> --format json
1925
+ cnry traffic agent-journey <project> <journey-id> --since 2026-10-20 --until 2026-10-27 --source <source-id> --limit 50 --offset 0
1926
+ ```
1927
+
1928
+ These commands follow recorded user-triggered agent requests, separately from
1929
+ AI-referred browser visitors. Both accept `--agent <id>`, `--trust
1930
+ verified|likely_real|unknown`, and `--target-key <key>` in addition
1931
+ to the window/source selectors. The default window is 24 hours; the maximum is
1932
+ 31 days. Keep selectors unchanged when opening a detail or requesting another
1933
+ page. Reads over 20,000 selected source/agent events require a narrower window.
1934
+ Limits are 1 to 200. JSON matches the API response;
1935
+ JSONL streams a `journey` or an `event` with its full scope and coverage context.
1936
+
1937
+ IP and user-agent grouping is inferred and can merge tasks. Requests without
1938
+ an IP stay unlinked; trust does not prove a user session. Each request carries
1939
+ `trust` and `trustReasons`: verified by the operator's published IP list, likely
1940
+ real (unchecked, but the operator's published user agent), or unknown. Likely
1941
+ fake requests are counted in `coverage.likelyFakeRequests` and never listed;
1942
+ with `--target-key` that count is null, because hourly totals carry no page
1943
+ path. `cnry traffic sync` reports them as `aiUserFetchLikelyFakeHits`.
1944
+ The API reports retention, inactivity gap, daily caps and source gaps. Advanced
1945
+ Properties match the current plan's URL coverage, not the historical user's
1946
+ intent. Keep its plan revision and unavailable dimensions with the evidence.
1947
+ HTTP status and paths do not prove a completed purchase, booking or other task.
1948
+ Stored reads only. Viewers and embeds are denied; API read keys retain project
1949
+ scope.
1950
+
1921
1951
  ### Unrecognized bots and agents
1922
1952
 
1923
1953
  ```bash
@@ -1932,12 +1962,13 @@ example user agent and path, and its sources. Default window: the last 30 days.
1932
1962
  generic HTTP tools (curl, python-requests and the like), static files and writes
1933
1963
  are left out. Stored rows only, no provider call. Viewers and embeds are denied.
1934
1964
 
1935
- ### AI visitor journeys
1965
+ ### AI-referred visitor journeys
1936
1966
 
1937
1967
  ```bash
1938
1968
  cnry journeys summary <project> --since 2026-10-01 --format json
1939
1969
  cnry journeys list <project> --engine ChatGPT --returned true --limit 50 --format jsonl
1940
1970
  cnry journeys show <project> <visitor-key> --limit 100 --offset 0
1971
+ cnry journeys show <project> <visitor-key> --events pages # pages plus every non-GET/HEAD request
1941
1972
  ```
1942
1973
 
1943
1974
  Follows visitors with at least one AI-referred visit, from that first AI visit
@@ -1947,7 +1978,9 @@ falls in the window (default 30 days), how many came back in a later visit, by
1947
1978
  which entry (`ai`, `search`, `social`, `paid`, `referral`, `direct`), and median
1948
1979
  days to return. `list` returns those visitors newest first with their first 20
1949
1980
  visits (`visitCount` is the total) and marks user-agent-only keys; `show` pages
1950
- through one visitor's visits and requests. A visit ends after 30 idle minutes
1981
+ through one visitor's visits and requests; `--events pages` keeps page
1982
+ requests plus every request that is not GET or HEAD, while each visit keeps its
1983
+ stored `requestCount`. A visit ends after 30 idle minutes
1951
1984
  or when the visitor arrives again from another outside source; a same-site,
1952
1985
  sign-in, payment or booking-engine referer is a step inside the visit.
1953
1986
 
@@ -57,7 +57,8 @@ Four tables store the shared output from every adapter:
57
57
  | Table | What's in it |
58
58
  |---|---|
59
59
  | `crawler_events_hourly` | One row per `(project, source, hour, bot, verification, path, status)` — bot crawls rolled up by hour |
60
- | `ai_user_fetch_events_hourly` | One row per `(project, source, hour, bot, verification, path, status)` — user-initiated AI fetches rolled up by hour |
60
+ | `ai_user_fetch_events_hourly` | One row per `(project, source, hour, bot, verification, path, status)` — user-initiated AI fetches rolled up by hour, excluding likely fake requests |
61
+ | `ai_user_fetch_likely_fake_hourly` | One row per `(project, source, hour, bot, first trust reason)` — requests that claimed a user-triggered agent but were judged likely fake |
61
62
  | `ai_referral_events_hourly` | One row per `(project, source, hour, product, source_domain, evidence_type, landing_path, status)` — click-through arrivals rolled up by hour |
62
63
  | `raw_event_samples` | Bounded forensic samples for spot checks. Source writes plus a startup/daily global sweep enforce 30-day retention; Cloudflare also uses a per-source, per-hour cap |
63
64
 
@@ -1203,8 +1204,63 @@ request coverage. The `traffic.source.cache-blindspot` doctor check is a static
1203
1204
  warning; it does not request or impersonate traffic against the public origin,
1204
1205
  and it never sends a `health.degraded` alert.
1205
1206
 
1207
+ ### Agent request journeys
1208
+
1209
+ In the dashboard, open the project's **Journeys** tab and select **Agent
1210
+ requests**. The sibling **Visitors** view shows browser visitors who arrived
1211
+ through AI, how many came back, and each visitor's visits in time order. The
1212
+ view, period, filters and selected visitor stay in the page URL. Traffic
1213
+ sources remains the connection-management page.
1214
+
1215
+ `cnry traffic agent-journeys <project>` lists recorded user-triggered agent
1216
+ request sequences. Open one with `cnry traffic agent-journey <project> <id>`;
1217
+ keep the list's window, source, agent, trust and Property filters. MCP
1218
+ equivalents are `canonry_traffic_agent_journeys` and
1219
+ `canonry_traffic_agent_journey` in the traffic toolkit.
1220
+
1221
+ Each timeline preserves time, hostname, masked path, method, status, available
1222
+ latency, operator verification, trust level with reasons, and current-plan
1223
+ Property attribution. IP/UA grouping is inferred and can combine different tasks
1224
+ on shared infrastructure; without an IP the requests stay unlinked. Neither
1225
+ grouping nor trust identifies a person or establishes their task.
1226
+
1227
+ Every user-triggered agent request gets a trust level when it is classified,
1228
+ judged on that request alone. `verified` means the source IP is in the
1229
+ operator's published list. Otherwise: `likely_fake` when the path asks for
1230
+ credential, version-control or admin files, when an operator that publishes a
1231
+ full user-agent string (OpenAI, Mistral) sees a different one; an IP missing
1232
+ from the published list alone leaves a request `unknown`, because lists lag
1233
+ real addresses and some rotate; `likely_real`
1234
+ when nothing could be checked (no IP, or no published list) but the user agent
1235
+ matches the published string; `unknown` for the rest. `trustReasons` lists the
1236
+ evidence. Likely fake requests are never added to AI user fetch hits or stored
1237
+ as journey events: hourly totals count them (`totals24h.aiUserFetchLikelyFakeHits`,
1238
+ `aiUserFetchLikelyFakeHits` on sync results, `coverage.likelyFakeRequests`),
1239
+ and raw samples keep their classification for review. With a Property filter,
1240
+ `coverage.likelyFakeRequests` is null: hourly totals carry no page path. Trust
1241
+ applies to traffic recorded from the release that added it, and to any window
1242
+ a backfill rewrites; other older rollups are unchanged.
1243
+
1244
+ Preserve the
1245
+ response's retention, daily-cap and source limitations; missing requests do
1246
+ not prove the agent stopped. HTTP status alone does not prove business success.
1247
+ Simple and Advanced projects use the same stored instrument. A Property filter
1248
+ uses current-plan URL coverage with its revision; no market, query class, model
1249
+ or task intent is inferred. No site snippet or provider call is required to
1250
+ read stored events. New recording cannot recover discarded historical samples.
1251
+
1206
1252
  ### AI visitor journeys
1207
1253
 
1254
+ The project's **Journeys → Visitors** view uses the same summary, list and
1255
+ detail reads as the CLI. Its period selects visitors by first AI arrival;
1256
+ return behavior can include later visits beyond that period. Engine and
1257
+ came-back controls filter the list, not the summary. The selected visitor's
1258
+ visits read left to right in time order, and its requests load with
1259
+ `events=pages` (pages plus every request that is not GET or HEAD), the same
1260
+ filter as `cnry journeys show --events pages`. These are approximate visitor
1261
+ keys, not unique people, and the scope is project-wide in Simple and Advanced
1262
+ portfolios.
1263
+
1208
1264
  Every sync, backfill and push also follows visitors who arrived from an AI
1209
1265
  engine: their later visits, how they came back (search, direct, social, paid,
1210
1266
  referral, another AI visit) and each page or API request. It works the same for
@@ -1,18 +1,18 @@
1
- import{r as e}from"./rolldown-runtime-XKyaHtl9.js";import{V as t,Y as n,ot as r,z as i}from"./vendor-lucide-BILL9eZH.js";import{r as a}from"./vendor-markdown-DNTP_967.js";import{Ar as o,Dn as s,Mr as c,Qt as l,Tt as u,Zt as d,ct as f,jr as p,r as m,t as h,wt as g}from"./ToneBadge-bXf5LaSI.js";import{r as _}from"./account-context-BjM5ZlYl.js";import{t as v}from"./async-handler-Bj3TnIRw.js";import{Q as y,nt as b}from"./index-qWvnlyfA.js";var x=e(r(),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=`codex plugin marketplace add Canonry/canonry
2
- codex plugin add canonry-remote@canonry`,O={[p[`public-url-required`]]:`Configure this instance’s public URL before connecting a hosted client.`,[p[`https-required`]]:`Configure an HTTPS public URL for this instance.`,[p[`public-host-required`]]:`Use a public HTTPS address that your client can reach. Localhost and private-network addresses do not work for hosted connectors.`,[p[`public-path-mismatch`]]:`Make the publicUrl path match basePath, and preserve that prefix when the proxy forwards requests for hosted OAuth.`,[p[`oauth-unavailable`]]:`The sign-in routes are unavailable. Check this instance’s OAuth configuration.`,[p[`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.`,[p[`transport-unavailable`]]:`Restore the instance’s HTTP MCP service before connecting a hosted client.`},k={codex:{label:`Codex`,command:`codex plugin marketplace add Canonry/canonry
1
+ import{r as e}from"./rolldown-runtime-XKyaHtl9.js";import{B as t,H as n,X as r,st as i}from"./vendor-lucide-CoTHJwai.js";import{r as a}from"./vendor-markdown-cQgSk2i0.js";import{Br as o,Dn as s,Qt as c,Rr as l,Tt as u,Zt as d,ct as f,r as p,t as m,wt as h,zr as g}from"./ToneBadge-CXyUIWzB.js";import{r as _}from"./account-context-Bhgg1lEH.js";import{t as v}from"./async-handler-Bj3TnIRw.js";import{Q as y,nt as b}from"./index-3aBRkQpI.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=`codex plugin marketplace add Canonry/canonry
2
+ codex plugin add canonry-remote@canonry`,O={[g[`public-url-required`]]:`Configure this instance’s public URL before connecting a hosted client.`,[g[`https-required`]]:`Configure an HTTPS public URL for this instance.`,[g[`public-host-required`]]:`Use a public HTTPS address that your client can reach. Localhost and private-network addresses do not work for hosted connectors.`,[g[`public-path-mismatch`]]:`Make the publicUrl path match basePath, and preserve that prefix when the proxy forwards requests for hosted OAuth.`,[g[`oauth-unavailable`]]:`The sign-in routes are unavailable. Check this instance’s OAuth configuration.`,[g[`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.`,[g[`transport-unavailable`]]:`Restore the instance’s HTTP MCP service before connecting a hosted client.`},k={codex:{label:`Codex`,command:`codex plugin marketplace add Canonry/canonry
3
3
  codex plugin add canonry@canonry`},claude:{label:`Claude Code`,command:`claude plugin marketplace add Canonry/canonry
4
- claude plugin install canonry@canonry`},other:{label:`Other MCP clients`,command:`canonry-mcp`}};function A({label:e,value:r,showText:i=!1,secondary:a=!1,action:o=`agent_setup.copy`}){let c=(0,x.useId)(),[l,u]=(0,x.useState)(!1),[d,f]=(0,x.useState)(!1);async function p(){try{await navigator.clipboard.writeText(r),s(o),u(!0),f(!1)}catch{u(!1),f(!0)}}return(0,S.jsxs)(`div`,{className:`min-w-0 space-y-3`,children:[i?(0,S.jsx)(`pre`,{className:`overflow-x-auto material-base p-3 text-copy-14 text-heading`,children:(0,S.jsx)(`code`,{children:r})}):null,(0,S.jsxs)(m,{type:`button`,className:`pointer-coarse:min-h-11`,variant:a?`outline`:`default`,onClick:v(p),children:[l?(0,S.jsx)(n,{className:`size-4`,"aria-hidden":`true`}):(0,S.jsx)(t,{className:`size-4`,"aria-hidden":`true`}),e]}),l?(0,S.jsx)(`p`,{role:`status`,className:`text-copy-14 text-secondary`,children:`Copied.`}):null,!i||d?(0,S.jsxs)(`details`,{open:d||void 0,className:`text-label-14 text-secondary`,children:[(0,S.jsx)(`summary`,{className:`min-h-11 w-fit cursor-pointer py-3`,children:d?`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:d&&i?3:8,value:r,className:`mt-2 w-full rounded-md border border-default bg-bg p-3 text-copy-14 text-heading`})]}):null]})}function j(){return g()||u()?(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-copy-14 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-label-14 underline`,href:C,target:`_blank`,rel:`noopener noreferrer`,children:`Read the connection guide`}):null]}):(0,S.jsx)(M,{})}function M(){let e=b(),{isAdmin:t}=_(),n=d(),r=l(),a=y(!e,e?.health),s=a.data?.apiStatus,u=s?.state===`ok`?s.mcp:void 0,p=u?.status===c.available&&u.hosted?.status===o.ready?u.hosted:void 0,m=u?.hosted?.status===o.unavailable?u.hosted.reason:void 0,g=`${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=t&&n?O[m]:`Ask your Canonry administrator to finish hosted connection setup for this instance.`:s?.state===`error`?v=`The instance’s connection settings could not be checked. Try again after the service is available.`:u?.status===c[`not-supported`]&&(v=`This deployment does not provide hosted MCP connections. Ask your administrator for a supported connection.`);let x=p?`Help me connect this existing Canonry instance to ChatGPT or Claude Desktop using its remote MCP URL: ${p.url}
4
+ claude plugin install canonry@canonry`},other:{label:`Other MCP clients`,command:`canonry-mcp`}};function A({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),[d,f]=(0,x.useState)(!1);async function m(){try{await navigator.clipboard.writeText(t),s(o),u(!0),f(!1)}catch{u(!1),f(!0)}}return(0,S.jsxs)(`div`,{className:`min-w-0 space-y-3`,children:[i?(0,S.jsx)(`pre`,{className:`overflow-x-auto material-base p-3 text-copy-14 text-heading`,children:(0,S.jsx)(`code`,{children:t})}):null,(0,S.jsxs)(p,{type:`button`,className:`pointer-coarse: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)(n,{className:`size-4`,"aria-hidden":`true`}),e]}),l?(0,S.jsx)(`p`,{role:`status`,className:`text-copy-14 text-secondary`,children:`Copied.`}):null,!i||d?(0,S.jsxs)(`details`,{open:d||void 0,className:`text-label-14 text-secondary`,children:[(0,S.jsx)(`summary`,{className:`min-h-11 w-fit cursor-pointer py-3`,children:d?`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:d&&i?3:8,value:t,className:`mt-2 w-full rounded-md border border-default bg-bg p-3 text-copy-14 text-heading`})]}):null]})}function j(){return h()||u()?(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-copy-14 text-secondary`,children:`Open Agent setup in your own Canonry instance to connect your agent.`}),c()?(0,S.jsx)(`a`,{className:`mt-4 inline-block text-label-14 underline`,href:C,target:`_blank`,rel:`noopener noreferrer`,children:`Read the connection guide`}):null]}):(0,S.jsx)(M,{})}function M(){let e=b(),{isAdmin:n}=_(),r=d(),i=c(),a=y(!e,e?.health),s=a.data?.apiStatus,u=s?.state===`ok`?s.mcp:void 0,p=u?.status===o.available&&u.hosted?.status===l.ready?u.hosted:void 0,h=u?.hosted?.status===l.unavailable?u.hosted.reason:void 0,g=`${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.`:h?v=n&&r?O[h]:`Ask your Canonry administrator to finish hosted connection setup for this instance.`:s?.state===`error`?v=`The instance’s connection settings could not be checked. Try again after the service is available.`:u?.status===o[`not-supported`]&&(v=`This deployment does not provide hosted MCP connections. Ask your administrator for a supported connection.`);let x=p?`Help me connect this existing Canonry instance to ChatGPT or Claude Desktop using its remote MCP URL: ${p.url}
5
5
 
6
6
  Use the client's remote MCP connection flow with OAuth sign-in. For Claude, set the OAuth client option to Register automatically; Claude's published identity is not supported here, and on Team or Enterprise plans an Owner adds custom connectors. 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.
7
7
 
8
8
  ChatGPT guide: ${T}
9
9
  Claude guide: ${E}
10
10
 
11
- After authorization, enable the connection in this conversation. Call canonry_help with intent "status", follow its available tool guidance, and list accessible projects using stored reads only. Confirm the target instance and report whether the read succeeded; an empty list can still mean success. Do not run scans, sweeps, research, live provider checks, or other writes.`:void 0;return(0,S.jsxs)(`div`,{className:`page-container`,children:[(0,S.jsx)(`div`,{className:`page-header`,children:(0,S.jsxs)(`div`,{className:`page-header-left`,children:[(0,S.jsx)(`h1`,{className:`page-title`,children:`Agent setup`}),(0,S.jsx)(`p`,{className:`page-subtitle`,children:n?`Connect ChatGPT, Claude Desktop, or another agent to this instance.`:`Connect ChatGPT or Claude Desktop to this instance.`})]})}),(0,S.jsxs)(`div`,{className:`max-w-3xl`,children:[(0,S.jsxs)(`div`,{className:`flex flex-wrap items-center justify-between gap-3 border-b border-default pb-5`,children:[(0,S.jsxs)(`div`,{className:`min-w-0`,children:[(0,S.jsx)(`p`,{className:`text-copy-14-strong text-heading`,children:`Your Canonry instance`}),(0,S.jsx)(`p`,{className:`mt-1 break-all text-copy-14 text-secondary`,children:g})]}),(0,S.jsx)(h,{tone:p?`positive`:m||s?.state===`error`?`caution`:`neutral`,children:p?`Hosted setup configured`:a.isPending?`Checking hosted setup`:m?`Hosted setup needs attention`:`Hosted setup not confirmed`})]}),p&&x?p.plugin?(0,S.jsxs)(S.Fragment,{children:[(0,S.jsx)(N,{plugin:p.plugin}),(0,S.jsxs)(`details`,{className:`border-t border-default py-3 text-label-14`,children:[(0,S.jsx)(`summary`,{className:`min-h-11 w-fit cursor-pointer py-3 text-label-14-strong text-heading`,children:`Connect directly (Claude and other MCP clients)`}),(0,S.jsx)(P,{url:p.url,setupPrompt:x})]})]}):(0,S.jsx)(P,{url:p.url,setupPrompt:x}):(0,S.jsxs)(`section`,{className:`py-6`,"aria-labelledby":`agent-requirements-title`,children:[(0,S.jsx)(`h2`,{id:`agent-requirements-title`,className:`text-heading-20 text-heading`,children:`Before you connect a hosted client`}),(0,S.jsx)(`p`,{className:`mt-2 max-w-prose text-copy-14 text-secondary`,children:v}),r?(0,S.jsxs)(`a`,{href:C,target:`_blank`,rel:`noopener noreferrer`,className:`mt-3 inline-flex min-h-11 items-center gap-2 text-label-14 underline`,children:[`Read the connection guide `,(0,S.jsx)(i,{className:`size-3.5`,"aria-hidden":`true`})]}):null]}),n?(0,S.jsx)(I,{instanceUrl:g,showResourceLinks:r}):null]})]})}function N({plugin:e}){return(0,S.jsxs)(`section`,{className:`py-6`,"aria-labelledby":`agent-plugin-title`,children:[(0,S.jsx)(`h2`,{id:`agent-plugin-title`,className:`text-heading-20 text-heading`,children:`Use the Canonry plugin`}),(0,S.jsx)(`p`,{className:`mt-2 max-w-prose text-copy-14 text-secondary`,children:`For the ChatGPT desktop app and Codex. The plugin opens this workspace with your Canonry sign-in and reads stored results only.`}),(0,S.jsxs)(`ol`,{className:`mt-5 space-y-6`,children:[(0,S.jsxs)(`li`,{className:`space-y-3`,children:[(0,S.jsx)(`h3`,{className:`text-label-14-strong text-heading`,children:`1. Install the plugin`}),(0,S.jsx)(`p`,{className:`max-w-prose text-copy-14 text-secondary`,children:`Add the Canonry marketplace, then install Canonry. In Codex, run:`}),(0,S.jsx)(A,{label:`Copy plugin install commands`,value:D,showText:!0,secondary:!0})]}),(0,S.jsxs)(`li`,{className:`space-y-3`,children:[(0,S.jsx)(`h3`,{className:`text-label-14-strong text-heading`,children:`2. Enter this workspace`}),(0,S.jsx)(`p`,{className:`max-w-prose text-copy-14 text-secondary`,children:`When Canonry asks which workspace to open, enter:`}),(0,S.jsx)(A,{label:`Copy workspace`,value:e.workspace,showText:!0,secondary:!0},e.workspace)]}),(0,S.jsxs)(`li`,{className:`space-y-2`,children:[(0,S.jsx)(`h3`,{className:`text-label-14-strong text-heading`,children:`3. Sign in and approve access`}),(0,S.jsx)(`p`,{className:`max-w-prose text-copy-14 text-secondary`,children:`Sign in with your Canonry account for this workspace and approve read access. The plugin cannot start sweeps or change settings.`})]})]})]})}function P({url:e,setupPrompt:t}){return(0,S.jsxs)(S.Fragment,{children:[(0,S.jsxs)(`section`,{className:`py-6`,"aria-labelledby":`agent-connect-title`,children:[(0,S.jsx)(`h2`,{id:`agent-connect-title`,className:`text-heading-20 text-heading`,children:`1. Add Canonry to your client`}),(0,S.jsx)(`p`,{className:`mt-2 mb-4 max-w-prose text-copy-14 text-secondary`,children:`Add this URL to your client’s remote connector settings. No local installation is needed.`}),(0,S.jsx)(A,{label:`Copy MCP URL`,value:e,showText:!0},e),(0,S.jsxs)(`div`,{className:`mt-4 flex flex-wrap gap-x-5 gap-y-2 text-label-14 text-secondary`,children:[(0,S.jsx)(`a`,{href:T,target:`_blank`,rel:`noopener noreferrer`,className:`underline`,children:`ChatGPT setup guide`}),(0,S.jsx)(`a`,{href:E,target:`_blank`,rel:`noopener noreferrer`,className:`underline`,children:`Claude Desktop setup guide`})]}),(0,S.jsx)(`p`,{className:`mt-2 max-w-prose text-copy-14 text-secondary`,children:`Choose OAuth. In Claude, set the OAuth client to “Register automatically”. On Claude Team and Enterprise plans, an Owner adds the connector first.`}),(0,S.jsx)(`div`,{className:`mt-4`,children:(0,S.jsx)(A,{label:`Copy setup prompt`,value:t,secondary:!0},t)})]}),(0,S.jsxs)(`section`,{className:`border-t border-default py-6`,"aria-labelledby":`agent-authorize-title`,children:[(0,S.jsx)(`h2`,{id:`agent-authorize-title`,className:`text-heading-20 text-heading`,children:`2. Sign in and approve access`}),(0,S.jsx)(`p`,{className:`mt-2 max-w-prose text-copy-14 text-secondary`,children:`Sign in with your Canonry account and review the requested access. After approving it, return to your client and enable the connection for your conversation.`})]}),(0,S.jsxs)(`section`,{className:`border-t border-default py-6`,"aria-labelledby":`agent-verify-title`,children:[(0,S.jsx)(`h2`,{id:`agent-verify-title`,className:`text-heading-20 text-heading`,children:`3. Verify the connection`}),(0,S.jsx)(`p`,{className:`mt-2 mb-4 max-w-prose text-copy-14 text-secondary`,children:`Server configuration is ready. Use this prompt to confirm your agent can read your projects without starting work or using provider quota.`}),(0,S.jsx)(F,{target:e})]})]})}function F({target:e,local:t=!1}){let n=`Verify my existing Canonry connection targets ${e}. Call canonry_help with intent "status", follow its available tool guidance, then list accessible projects using stored reads only. Report the instance, connection method, and whether the project read succeeded. An empty project list can still be a successful connection. If the target cannot be confirmed, stop and explain. Do not install anything, change configuration, create projects, run scans, sweeps, research, or live provider checks.`;return(0,S.jsx)(A,{label:t?`Copy local verification prompt`:`Copy verification prompt`,value:n,secondary:!0,action:`agent_setup.verify_copy`},e)}function I({instanceUrl:e,showResourceLinks:t}){let[n,r]=(0,x.useState)(`codex`),a=`Connect my local agent to this existing Canonry instance: ${e}
11
+ After authorization, enable the connection in this conversation. Call canonry_help with intent "status", follow its available tool guidance, and list accessible projects using stored reads only. Confirm the target instance and report whether the read succeeded; an empty list can still mean success. Do not run scans, sweeps, research, live provider checks, or other writes.`:void 0;return(0,S.jsxs)(`div`,{className:`page-container`,children:[(0,S.jsx)(`div`,{className:`page-header`,children:(0,S.jsxs)(`div`,{className:`page-header-left`,children:[(0,S.jsx)(`h1`,{className:`page-title`,children:`Agent setup`}),(0,S.jsx)(`p`,{className:`page-subtitle`,children:r?`Connect ChatGPT, Claude Desktop, or another agent to this instance.`:`Connect ChatGPT or Claude Desktop to this instance.`})]})}),(0,S.jsxs)(`div`,{className:`max-w-3xl`,children:[(0,S.jsxs)(`div`,{className:`flex flex-wrap items-center justify-between gap-3 border-b border-default pb-5`,children:[(0,S.jsxs)(`div`,{className:`min-w-0`,children:[(0,S.jsx)(`p`,{className:`text-copy-14-strong text-heading`,children:`Your Canonry instance`}),(0,S.jsx)(`p`,{className:`mt-1 break-all text-copy-14 text-secondary`,children:g})]}),(0,S.jsx)(m,{tone:p?`positive`:h||s?.state===`error`?`caution`:`neutral`,children:p?`Hosted setup configured`:a.isPending?`Checking hosted setup`:h?`Hosted setup needs attention`:`Hosted setup not confirmed`})]}),p&&x?p.plugin?(0,S.jsxs)(S.Fragment,{children:[(0,S.jsx)(N,{plugin:p.plugin}),(0,S.jsxs)(`details`,{className:`border-t border-default py-3 text-label-14`,children:[(0,S.jsx)(`summary`,{className:`min-h-11 w-fit cursor-pointer py-3 text-label-14-strong text-heading`,children:`Connect directly (Claude and other MCP clients)`}),(0,S.jsx)(P,{url:p.url,setupPrompt:x})]})]}):(0,S.jsx)(P,{url:p.url,setupPrompt:x}):(0,S.jsxs)(`section`,{className:`py-6`,"aria-labelledby":`agent-requirements-title`,children:[(0,S.jsx)(`h2`,{id:`agent-requirements-title`,className:`text-heading-20 text-heading`,children:`Before you connect a hosted client`}),(0,S.jsx)(`p`,{className:`mt-2 max-w-prose text-copy-14 text-secondary`,children:v}),i?(0,S.jsxs)(`a`,{href:C,target:`_blank`,rel:`noopener noreferrer`,className:`mt-3 inline-flex min-h-11 items-center gap-2 text-label-14 underline`,children:[`Read the connection guide `,(0,S.jsx)(t,{className:`size-3.5`,"aria-hidden":`true`})]}):null]}),r?(0,S.jsx)(I,{instanceUrl:g,showResourceLinks:i}):null]})]})}function N({plugin:e}){return(0,S.jsxs)(`section`,{className:`py-6`,"aria-labelledby":`agent-plugin-title`,children:[(0,S.jsx)(`h2`,{id:`agent-plugin-title`,className:`text-heading-20 text-heading`,children:`Use the Canonry plugin`}),(0,S.jsx)(`p`,{className:`mt-2 max-w-prose text-copy-14 text-secondary`,children:`For the ChatGPT desktop app and Codex. The plugin opens this workspace with your Canonry sign-in and reads stored results only.`}),(0,S.jsxs)(`ol`,{className:`mt-5 space-y-6`,children:[(0,S.jsxs)(`li`,{className:`space-y-3`,children:[(0,S.jsx)(`h3`,{className:`text-label-14-strong text-heading`,children:`1. Install the plugin`}),(0,S.jsx)(`p`,{className:`max-w-prose text-copy-14 text-secondary`,children:`Add the Canonry marketplace, then install Canonry. In Codex, run:`}),(0,S.jsx)(A,{label:`Copy plugin install commands`,value:D,showText:!0,secondary:!0})]}),(0,S.jsxs)(`li`,{className:`space-y-3`,children:[(0,S.jsx)(`h3`,{className:`text-label-14-strong text-heading`,children:`2. Enter this workspace`}),(0,S.jsx)(`p`,{className:`max-w-prose text-copy-14 text-secondary`,children:`When Canonry asks which workspace to open, enter:`}),(0,S.jsx)(A,{label:`Copy workspace`,value:e.workspace,showText:!0,secondary:!0},e.workspace)]}),(0,S.jsxs)(`li`,{className:`space-y-2`,children:[(0,S.jsx)(`h3`,{className:`text-label-14-strong text-heading`,children:`3. Sign in and approve access`}),(0,S.jsx)(`p`,{className:`max-w-prose text-copy-14 text-secondary`,children:`Sign in with your Canonry account for this workspace and approve read access. The plugin cannot start sweeps or change settings.`})]})]})]})}function P({url:e,setupPrompt:t}){return(0,S.jsxs)(S.Fragment,{children:[(0,S.jsxs)(`section`,{className:`py-6`,"aria-labelledby":`agent-connect-title`,children:[(0,S.jsx)(`h2`,{id:`agent-connect-title`,className:`text-heading-20 text-heading`,children:`1. Add Canonry to your client`}),(0,S.jsx)(`p`,{className:`mt-2 mb-4 max-w-prose text-copy-14 text-secondary`,children:`Add this URL to your client’s remote connector settings. No local installation is needed.`}),(0,S.jsx)(A,{label:`Copy MCP URL`,value:e,showText:!0},e),(0,S.jsxs)(`div`,{className:`mt-4 flex flex-wrap gap-x-5 gap-y-2 text-label-14 text-secondary`,children:[(0,S.jsx)(`a`,{href:T,target:`_blank`,rel:`noopener noreferrer`,className:`underline`,children:`ChatGPT setup guide`}),(0,S.jsx)(`a`,{href:E,target:`_blank`,rel:`noopener noreferrer`,className:`underline`,children:`Claude Desktop setup guide`})]}),(0,S.jsx)(`p`,{className:`mt-2 max-w-prose text-copy-14 text-secondary`,children:`Choose OAuth. In Claude, set the OAuth client to “Register automatically”. On Claude Team and Enterprise plans, an Owner adds the connector first.`}),(0,S.jsx)(`div`,{className:`mt-4`,children:(0,S.jsx)(A,{label:`Copy setup prompt`,value:t,secondary:!0},t)})]}),(0,S.jsxs)(`section`,{className:`border-t border-default py-6`,"aria-labelledby":`agent-authorize-title`,children:[(0,S.jsx)(`h2`,{id:`agent-authorize-title`,className:`text-heading-20 text-heading`,children:`2. Sign in and approve access`}),(0,S.jsx)(`p`,{className:`mt-2 max-w-prose text-copy-14 text-secondary`,children:`Sign in with your Canonry account and review the requested access. After approving it, return to your client and enable the connection for your conversation.`})]}),(0,S.jsxs)(`section`,{className:`border-t border-default py-6`,"aria-labelledby":`agent-verify-title`,children:[(0,S.jsx)(`h2`,{id:`agent-verify-title`,className:`text-heading-20 text-heading`,children:`3. Verify the connection`}),(0,S.jsx)(`p`,{className:`mt-2 mb-4 max-w-prose text-copy-14 text-secondary`,children:`Server configuration is ready. Use this prompt to confirm your agent can read your projects without starting work or using provider quota.`}),(0,S.jsx)(F,{target:e})]})]})}function F({target:e,local:t=!1}){let n=`Verify my existing Canonry connection targets ${e}. Call canonry_help with intent "status", follow its available tool guidance, then list accessible projects using stored reads only. Report the instance, connection method, and whether the project read succeeded. An empty project list can still be a successful connection. If the target cannot be confirmed, stop and explain. Do not install anything, change configuration, create projects, run scans, sweeps, research, or live provider checks.`;return(0,S.jsx)(A,{label:t?`Copy local verification prompt`:`Copy verification prompt`,value:n,secondary:!0,action:`agent_setup.verify_copy`},e)}function I({instanceUrl:e,showResourceLinks:n}){let[r,i]=(0,x.useState)(`codex`),a=`Connect my local agent to this existing Canonry instance: ${e}
12
12
 
13
13
  Use an installed Canonry runtime whose private configuration already points to this exact instance. A local plugin or canonry-mcp process does not inherit the browser connection, and shell environment changes do not retarget an already-connected tool. Check the saved API URL before using it.
14
14
 
15
- ${t?`Official connection guide: ${C}
15
+ ${n?`Official connection guide: ${C}
16
16
  Optional plugin guide for Codex or Claude Code: ${w}
17
17
 
18
- `:``}Preserve existing client connections, credentials, and access. Do not create another Canonry instance, bootstrap a config, or create projects. Keep secrets and configuration contents out of chat. Ask before changing client configuration or installing software. Reload the client if needed, then verify with stored reads only. Do not run scans, sweeps, research, live provider checks, or other writes.`;return(0,S.jsxs)(`details`,{className:`border-t border-default py-3 text-label-14`,children:[(0,S.jsx)(`summary`,{className:`min-h-11 w-fit cursor-pointer py-3 text-label-14-strong text-heading`,children:`Local plugins and other MCP clients`}),(0,S.jsxs)(`div`,{className:`space-y-4 py-4`,children:[(0,S.jsx)(`p`,{className:`max-w-prose text-copy-14 text-secondary`,children:`For an agent running on your computer, use a Canonry runtime whose private configuration already points to this instance. The plugin does not inherit your browser connection.`}),(0,S.jsx)(A,{label:`Copy local setup prompt`,value:a,secondary:!0}),(0,S.jsx)(`label`,{className:`block text-label-14-strong text-heading`,htmlFor:`agent-client`,children:`Your client`}),(0,S.jsx)(`select`,{id:`agent-client`,className:`h-11 max-w-full rounded-md border border-default bg-bg px-3 text-label-14 text-heading`,value:n,onChange:e=>{let t=e.target.value;(t===`codex`||t===`claude`||t===`other`)&&r(t)},children:Object.entries(k).map(([e,t])=>(0,S.jsx)(`option`,{value:e,children:t.label},e))}),(0,S.jsx)(A,{label:n===`other`?`Copy MCP command`:`Copy install commands`,value:k[n].command,showText:!0,secondary:!0},n),(0,S.jsxs)(`p`,{className:`text-copy-14 text-secondary`,children:[n===`other`?`Add this executable as a stdio MCP server in your client.`:`Reload your client after installing the plugin.`,` Keep one Canonry connection per instance.`]}),t?(0,S.jsxs)(`a`,{href:w,target:`_blank`,rel:`noopener noreferrer`,className:`inline-flex min-h-11 items-center gap-2 underline`,children:[`Runtime and plugin instructions `,(0,S.jsx)(i,{className:`size-3.5`,"aria-hidden":`true`})]}):null,(0,S.jsx)(F,{target:e,local:!0})]})]})}export{j as AgentSetupPage};
18
+ `:``}Preserve existing client connections, credentials, and access. Do not create another Canonry instance, bootstrap a config, or create projects. Keep secrets and configuration contents out of chat. Ask before changing client configuration or installing software. Reload the client if needed, then verify with stored reads only. Do not run scans, sweeps, research, live provider checks, or other writes.`;return(0,S.jsxs)(`details`,{className:`border-t border-default py-3 text-label-14`,children:[(0,S.jsx)(`summary`,{className:`min-h-11 w-fit cursor-pointer py-3 text-label-14-strong text-heading`,children:`Local plugins and other MCP clients`}),(0,S.jsxs)(`div`,{className:`space-y-4 py-4`,children:[(0,S.jsx)(`p`,{className:`max-w-prose text-copy-14 text-secondary`,children:`For an agent running on your computer, use a Canonry runtime whose private configuration already points to this instance. The plugin does not inherit your browser connection.`}),(0,S.jsx)(A,{label:`Copy local setup prompt`,value:a,secondary:!0}),(0,S.jsx)(`label`,{className:`block text-label-14-strong text-heading`,htmlFor:`agent-client`,children:`Your client`}),(0,S.jsx)(`select`,{id:`agent-client`,className:`h-11 max-w-full rounded-md border border-default bg-bg px-3 text-label-14 text-heading`,value:r,onChange:e=>{let t=e.target.value;(t===`codex`||t===`claude`||t===`other`)&&i(t)},children:Object.entries(k).map(([e,t])=>(0,S.jsx)(`option`,{value:e,children:t.label},e))}),(0,S.jsx)(A,{label:r===`other`?`Copy MCP command`:`Copy install commands`,value:k[r].command,showText:!0,secondary:!0},r),(0,S.jsxs)(`p`,{className:`text-copy-14 text-secondary`,children:[r===`other`?`Add this executable as a stdio MCP server in your client.`:`Reload your client after installing the plugin.`,` Keep one Canonry connection per instance.`]}),n?(0,S.jsxs)(`a`,{href:w,target:`_blank`,rel:`noopener noreferrer`,className:`inline-flex min-h-11 items-center gap-2 underline`,children:[`Runtime and plugin instructions `,(0,S.jsx)(t,{className:`size-3.5`,"aria-hidden":`true`})]}):null,(0,S.jsx)(F,{target:e,local:!0})]})]})}export{j as AgentSetupPage};
@@ -1 +1 @@
1
- import{r as e}from"./rolldown-runtime-XKyaHtl9.js";import{ot as t}from"./vendor-lucide-BILL9eZH.js";import{r as n}from"./vendor-markdown-DNTP_967.js";import{b as r}from"./vendor-tanstack-BoP7BGaH.js";import{mt as i,r as a,t as o}from"./ToneBadge-bXf5LaSI.js";import{Qt as s,Y as c,i as l}from"./react-query-BKozxbv1.js";import{t as u}from"./card-CDFncx20.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-label-14 text-strong placeholder-mono-400 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-label-14 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-label-14 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 text-label-12-mono 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 text-label-12-mono 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-label-14 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-copy-13 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-label-12 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{st as t}from"./vendor-lucide-CoTHJwai.js";import{r as n}from"./vendor-markdown-cQgSk2i0.js";import{b as r}from"./vendor-tanstack-q5SvZtcv.js";import{mt as i,r as a,t as o}from"./ToneBadge-CXyUIWzB.js";import{Y as s,i as c,rn as l}from"./react-query-DQr9PoNm.js";import{t as u}from"./card-B16Dvxau.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({...s({client:i,path:{name:e??``},query:T}),enabled:!!e}),D=r({...c({client:i,query:T}),enabled:!e}),O=r({...l({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-label-14 text-strong placeholder-mono-400 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-label-14 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-label-14 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 text-label-12-mono 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 text-label-12-mono 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-label-14 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-copy-13 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-label-12 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{B as t,C as n,o as r,ot as i,s as a,z as o}from"./vendor-lucide-BILL9eZH.js";import{r as s}from"./vendor-markdown-DNTP_967.js";import{J as c,L as l,R as u,U as d,W as f,a as p,jt as m,r as h,t as g,un as _,vt as v,wt as y}from"./ToneBadge-bXf5LaSI.js";import{t as b}from"./async-handler-Bj3TnIRw.js";import{t as x}from"./card-CDFncx20.js";import{t as S}from"./Hint-Ro2RKH6t.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([l(),f().catch(()=>null),c().catch(()=>[]),u().catch(()=>[]),d().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 v();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 _(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 p&&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 m(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 bg-negative-soft`,children:(0,w.jsx)(`p`,{className:`text-copy-14 text-negative`,children:K})}),J&&(0,w.jsx)(x,{className:`surface-card p-4 mb-4 bg-positive-soft`,children:(0,w.jsx)(`p`,{className:`text-copy-14 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)(g,{tone:`positive`,children:`Installed`}):(0,w.jsx)(g,{tone:`caution`,children:`Not installed`})]}),(0,w.jsx)(x,{className:`surface-card p-4`,children:I?(0,w.jsx)(`p`,{className:`text-copy-14 text-muted`,children:`Checking…`}):e?.duckdbInstalled?(0,w.jsx)(`p`,{className:`text-copy-14 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-copy-14 text-secondary`,children:`Install the local query engine to enable release syncs.`}),!y()&&(0,w.jsxs)(h,{type:`button`,size:`sm`,disabled:R,onClick:b(Z),children:[(0,w.jsx)(t,{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)(g,{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-label-14`,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-label-12 text-muted pt-2`,children:[(0,w.jsxs)(`div`,{children:[(0,w.jsx)(`p`,{className:`text-faint normal-case text-label-12`,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 normal-case text-label-12 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 normal-case text-label-12`,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 normal-case text-label-12`,children:`Finished`}),(0,w.jsx)(`p`,{className:`text-neutral mt-0.5`,children:D(s.queryFinishedAt)})]})]}),s.error&&(0,w.jsx)(`p`,{className:`text-copy-14 text-negative-400 pt-2`,children:s.error})]}):(0,w.jsx)(`p`,{className:`text-copy-14 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)(r,{className:`h-4 w-4 text-caution-400 shrink-0 mt-0.5`,"aria-hidden":!0}),(0,w.jsxs)(`div`,{className:`text-label-14 text-neutral`,children:[(0,w.jsx)(`p`,{className:`text-copy-14-strong 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 material-base 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-label-12 normal-case text-muted`,children:`Auto-detected release`}),P?(0,w.jsxs)(`p`,{className:`text-copy-14 text-strong mt-0.5`,children:[(0,w.jsx)(`code`,{className:`text-heading`,children:P.release}),(0,w.jsxs)(`span`,{className:`ml-2 text-label-12 text-muted`,children:[`Vertex `,E(P.vertexBytes),`, edges `,E(P.edgesBytes)]})]}):(0,w.jsx)(`p`,{className:`text-copy-14 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-label-12 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)(o,{className:`h-3 w-3`,"aria-hidden":!0})]})]}),!y()&&(0,w.jsxs)(`div`,{className:`flex items-center gap-2 shrink-0`,children:[(0,w.jsxs)(h,{type:`button`,size:`sm`,disabled:B||!e?.duckdbInstalled||!P&&!H.trim(),onClick:b(Q),children:[(0,w.jsx)(n,{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).`]})]})]})]}),y()?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-label-14 text-strong placeholder-mono-400 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-button-14 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-button-14 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-copy-14 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-label-14-strong 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-copy-14 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-label-14`,children:[(0,w.jsx)(`thead`,{children:(0,w.jsxs)(`tr`,{className:`border-b border-base text-left text-label-12 normal-case text-faint`,children:[(0,w.jsx)(`th`,{className:`px-4 py-2 text-label-12-strong`,children:`Release`}),(0,w.jsx)(`th`,{className:`px-4 py-2 text-label-12-strong`,children:`Sync status`}),(0,w.jsx)(`th`,{className:`px-4 py-2 text-right text-label-12-strong`,children:`Size`}),(0,w.jsx)(`th`,{className:`px-4 py-2 text-label-12-strong`,children:`Last used`}),!y()&&(0,w.jsx)(`th`,{className:`px-4 py-2 text-label-12-strong 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)(g,{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)}),!y()&&(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)(h,{type:`button`,variant:`outline`,size:`sm`,onClick:()=>{$(e.release)},children:[(0,w.jsx)(a,{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-label-14 text-muted`,colSpan:y()?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-copy-13 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-label-14`,children:[(0,w.jsx)(`thead`,{children:(0,w.jsxs)(`tr`,{className:`border-b border-base text-left text-label-12 normal-case text-faint`,children:[(0,w.jsx)(`th`,{className:`px-4 py-2 text-label-12-strong`,children:`Release`}),(0,w.jsx)(`th`,{className:`px-4 py-2 text-label-12-strong`,children:`Status`}),(0,w.jsx)(`th`,{className:`px-4 py-2 text-right text-label-12-strong`,children:`Projects`}),(0,w.jsx)(`th`,{className:`px-4 py-2 text-right text-label-12-strong`,children:`Rows`}),(0,w.jsx)(`th`,{className:`px-4 py-2 text-label-12-strong`,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)(g,{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{B as t,C as n,V as r,o as i,s as a,st as o}from"./vendor-lucide-CoTHJwai.js";import{r as s}from"./vendor-markdown-cQgSk2i0.js";import{J as c,L as l,R as u,U as d,W as f,a as p,jt as m,r as h,t as g,un as _,vt as v,wt as y}from"./ToneBadge-CXyUIWzB.js";import{t as b}from"./async-handler-Bj3TnIRw.js";import{t as x}from"./card-B16Dvxau.js";import{t as S}from"./Hint-CfeZmZig.js";var C=e(o(),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,o]=(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([l(),f().catch(()=>null),c().catch(()=>[]),u().catch(()=>[]),d().catch(()=>null)]);o(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 v();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 _(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 p&&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 m(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 bg-negative-soft`,children:(0,w.jsx)(`p`,{className:`text-copy-14 text-negative`,children:K})}),J&&(0,w.jsx)(x,{className:`surface-card p-4 mb-4 bg-positive-soft`,children:(0,w.jsx)(`p`,{className:`text-copy-14 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)(g,{tone:`positive`,children:`Installed`}):(0,w.jsx)(g,{tone:`caution`,children:`Not installed`})]}),(0,w.jsx)(x,{className:`surface-card p-4`,children:I?(0,w.jsx)(`p`,{className:`text-copy-14 text-muted`,children:`Checking…`}):e?.duckdbInstalled?(0,w.jsx)(`p`,{className:`text-copy-14 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-copy-14 text-secondary`,children:`Install the local query engine to enable release syncs.`}),!y()&&(0,w.jsxs)(h,{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)(g,{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-label-14`,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-label-12 text-muted pt-2`,children:[(0,w.jsxs)(`div`,{children:[(0,w.jsx)(`p`,{className:`text-faint normal-case text-label-12`,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 normal-case text-label-12 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 normal-case text-label-12`,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 normal-case text-label-12`,children:`Finished`}),(0,w.jsx)(`p`,{className:`text-neutral mt-0.5`,children:D(s.queryFinishedAt)})]})]}),s.error&&(0,w.jsx)(`p`,{className:`text-copy-14 text-negative-400 pt-2`,children:s.error})]}):(0,w.jsx)(`p`,{className:`text-copy-14 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-label-14 text-neutral`,children:[(0,w.jsx)(`p`,{className:`text-copy-14-strong 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 material-base 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-label-12 normal-case text-muted`,children:`Auto-detected release`}),P?(0,w.jsxs)(`p`,{className:`text-copy-14 text-strong mt-0.5`,children:[(0,w.jsx)(`code`,{className:`text-heading`,children:P.release}),(0,w.jsxs)(`span`,{className:`ml-2 text-label-12 text-muted`,children:[`Vertex `,E(P.vertexBytes),`, edges `,E(P.edgesBytes)]})]}):(0,w.jsx)(`p`,{className:`text-copy-14 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-label-12 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})]})]}),!y()&&(0,w.jsxs)(`div`,{className:`flex items-center gap-2 shrink-0`,children:[(0,w.jsxs)(h,{type:`button`,size:`sm`,disabled:B||!e?.duckdbInstalled||!P&&!H.trim(),onClick:b(Q),children:[(0,w.jsx)(n,{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).`]})]})]})]}),y()?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-label-14 text-strong placeholder-mono-400 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-button-14 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-button-14 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-copy-14 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-label-14-strong 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-copy-14 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-label-14`,children:[(0,w.jsx)(`thead`,{children:(0,w.jsxs)(`tr`,{className:`border-b border-base text-left text-label-12 normal-case text-faint`,children:[(0,w.jsx)(`th`,{className:`px-4 py-2 text-label-12-strong`,children:`Release`}),(0,w.jsx)(`th`,{className:`px-4 py-2 text-label-12-strong`,children:`Sync status`}),(0,w.jsx)(`th`,{className:`px-4 py-2 text-right text-label-12-strong`,children:`Size`}),(0,w.jsx)(`th`,{className:`px-4 py-2 text-label-12-strong`,children:`Last used`}),!y()&&(0,w.jsx)(`th`,{className:`px-4 py-2 text-label-12-strong 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)(g,{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)}),!y()&&(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)(h,{type:`button`,variant:`outline`,size:`sm`,onClick:()=>{$(e.release)},children:[(0,w.jsx)(a,{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-label-14 text-muted`,colSpan:y()?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-copy-13 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-label-14`,children:[(0,w.jsx)(`thead`,{children:(0,w.jsxs)(`tr`,{className:`border-b border-base text-left text-label-12 normal-case text-faint`,children:[(0,w.jsx)(`th`,{className:`px-4 py-2 text-label-12-strong`,children:`Release`}),(0,w.jsx)(`th`,{className:`px-4 py-2 text-label-12-strong`,children:`Status`}),(0,w.jsx)(`th`,{className:`px-4 py-2 text-right text-label-12-strong`,children:`Projects`}),(0,w.jsx)(`th`,{className:`px-4 py-2 text-right text-label-12-strong`,children:`Rows`}),(0,w.jsx)(`th`,{className:`px-4 py-2 text-label-12-strong`,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)(g,{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-DNTP_967.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-PsGDYxIT.js";var l=e(),u={contentStyle:{backgroundColor:`var(--chart-tooltip-bg, #0a0a0a)`,border:`none`,borderRadius:`var(--radius-material-tooltip)`,boxShadow:`var(--shadow-material-tooltip)`,fontSize:13,lineHeight:`18px`,fontWeight:400},labelStyle:{color:`var(--chart-tooltip-label, #ededed)`},itemStyle:{color:`var(--chart-tooltip-item, #a1a1a1)`}},d={fill:`var(--chart-neutral-text-dim, #a1a1a1)`,fontSize:12},f=`var(--chart-grid, #2e2e2e)`,p=`var(--chart-axis, #2e2e2e)`,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, #a1a1a1)`,textDim:`var(--chart-neutral-text-dim, #a1a1a1)`,textFaint:`var(--chart-neutral-text-faint, #7d7d7d)`,surface:`var(--chart-neutral-surface, #2e2e2e)`,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, #a1a1a1)`};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-cQgSk2i0.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-AnNqECZW.js";var l=e(),u={contentStyle:{backgroundColor:`var(--chart-tooltip-bg, #0a0a0a)`,border:`none`,borderRadius:`var(--radius-material-tooltip)`,boxShadow:`var(--shadow-material-tooltip)`,fontSize:13,lineHeight:`18px`,fontWeight:400},labelStyle:{color:`var(--chart-tooltip-label, #ededed)`},itemStyle:{color:`var(--chart-tooltip-item, #a1a1a1)`}},d={fill:`var(--chart-neutral-text-dim, #a1a1a1)`,fontSize:12},f=`var(--chart-grid, #2e2e2e)`,p=`var(--chart-axis, #2e2e2e)`,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, #a1a1a1)`,textDim:`var(--chart-neutral-text-dim, #a1a1a1)`,textFaint:`var(--chart-neutral-text-faint, #7d7d7d)`,surface:`var(--chart-neutral-surface, #2e2e2e)`,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, #a1a1a1)`};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{W as t,ot as n}from"./vendor-lucide-BILL9eZH.js";import{r}from"./vendor-markdown-DNTP_967.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:`material-tooltip absolute z-50 w-64 px-3 py-2 text-copy-13 text-secondary ${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{G as t,st as n}from"./vendor-lucide-CoTHJwai.js";import{r}from"./vendor-markdown-cQgSk2i0.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:`material-tooltip absolute z-50 w-64 px-3 py-2 text-copy-13 text-secondary ${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-DNTP_967.js";import{t}from"./AuditHistoryPanel-DgTvt2hQ.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-cQgSk2i0.js";import{t}from"./AuditHistoryPanel-Fvh4WFjq.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{o as t,ot as n}from"./vendor-lucide-BILL9eZH.js";import{u as r}from"./vendor-radix-C6jOoh_7.js";import{r as i}from"./vendor-markdown-DNTP_967.js";var a=e(n(),1),o=e(r(),1),s=i();function c({text:e,placement:n=`top`,tone:r=`info`,label:i}){let[c,l]=(0,a.useState)(null),u=(0,a.useRef)(null),d=(0,a.useRef)(null),f=(0,a.useRef)(!1),p=(0,a.useCallback)(()=>{if(!u.current)return;let e=u.current.getBoundingClientRect(),t=e.left+e.width/2,r=Math.min(224,window.innerWidth-16)/2;l({top:n===`bottom`?e.bottom:e.top,left:n===`bottom`?Math.max(r+8,Math.min(t,window.innerWidth-r-8)):t})},[n]);(0,a.useLayoutEffect)(()=>{if(n!==`bottom`||!c||!d.current)return;let e=d.current.getBoundingClientRect().bottom-window.innerHeight+8;if(e<=0)return;let t=Math.max(0,c.top-e);t!==c.top&&l({...c,top:t})},[n,c]);let m=(0,a.useCallback)(()=>l(null),[]),h=(0,a.useCallback)(()=>{c===null?p():m()},[c,p,m]);return(0,s.jsxs)(`span`,{className:`info-tooltip-wrapper`,onMouseEnter:p,onMouseLeave:m,children:[(0,s.jsxs)(`button`,{ref:u,type:`button`,className:`info-tooltip-trigger${i?` info-tooltip-trigger-labeled`:``}${r===`caution`?` info-tooltip-trigger-caution`:``}`,"aria-label":e,"aria-expanded":c!==null,onFocus:p,onBlur:m,onPointerDown:()=>{f.current=c!==null&&u.current?.ownerDocument.activeElement===u.current},onClick:e=>{e.detail===0?h():f.current?m():p()},onKeyDown:e=>{e.key===`Escape`&&m()},children:[r===`caution`?(0,s.jsx)(t,{className:`info-tooltip-icon`,"aria-hidden":`true`}):(0,s.jsxs)(`svg`,{className:`info-tooltip-icon`,viewBox:`0 0 16 16`,fill:`none`,"aria-hidden":`true`,children:[(0,s.jsx)(`circle`,{cx:`8`,cy:`8`,r:`7`,stroke:`currentColor`,strokeWidth:`1.5`}),(0,s.jsx)(`path`,{d:`M8 7v4M8 5.5v0`,stroke:`currentColor`,strokeWidth:`1.5`,strokeLinecap:`round`})]}),i?(0,s.jsx)(`span`,{"aria-hidden":`true`,children:i}):null]}),c!==null&&(0,o.createPortal)((0,s.jsx)(`span`,{ref:d,"aria-hidden":`true`,className:`material-tooltip px-3 py-2 text-copy-13 text-secondary`,style:{position:`fixed`,top:c.top,left:c.left,transform:n===`bottom`?`translateX(-50%) translateY(8px)`:`translateX(-50%) translateY(calc(-100% - 8px))`,zIndex:9999,pointerEvents:`none`,width:n===`bottom`?`min(14rem, calc(100vw - 1rem))`:`14rem`},children:e}),u.current?.closest(`.app-shell-embed`)??document.body)]})}export{c as t};
1
+ import{r as e}from"./rolldown-runtime-XKyaHtl9.js";import{o as t,st as n}from"./vendor-lucide-CoTHJwai.js";import{u as r}from"./vendor-radix-wS8sWIWE.js";import{r as i}from"./vendor-markdown-cQgSk2i0.js";var a=e(n(),1),o=e(r(),1),s=i();function c({text:e,placement:n=`top`,tone:r=`info`,label:i}){let[c,l]=(0,a.useState)(null),u=(0,a.useRef)(null),d=(0,a.useRef)(null),f=(0,a.useRef)(!1),p=(0,a.useCallback)(()=>{if(!u.current)return;let e=u.current.getBoundingClientRect(),t=e.left+e.width/2,r=Math.min(224,window.innerWidth-16)/2;l({top:n===`bottom`?e.bottom:e.top,left:n===`bottom`?Math.max(r+8,Math.min(t,window.innerWidth-r-8)):t})},[n]);(0,a.useLayoutEffect)(()=>{if(n!==`bottom`||!c||!d.current)return;let e=d.current.getBoundingClientRect().bottom-window.innerHeight+8;if(e<=0)return;let t=Math.max(0,c.top-e);t!==c.top&&l({...c,top:t})},[n,c]);let m=(0,a.useCallback)(()=>l(null),[]),h=(0,a.useCallback)(()=>{c===null?p():m()},[c,p,m]);return(0,s.jsxs)(`span`,{className:`info-tooltip-wrapper`,onMouseEnter:p,onMouseLeave:m,children:[(0,s.jsxs)(`button`,{ref:u,type:`button`,className:`info-tooltip-trigger${i?` info-tooltip-trigger-labeled`:``}${r===`caution`?` info-tooltip-trigger-caution`:``}`,"aria-label":e,"aria-expanded":c!==null,onFocus:p,onBlur:m,onPointerDown:()=>{f.current=c!==null&&u.current?.ownerDocument.activeElement===u.current},onClick:e=>{e.detail===0?h():f.current?m():p()},onKeyDown:e=>{e.key===`Escape`&&m()},children:[r===`caution`?(0,s.jsx)(t,{className:`info-tooltip-icon`,"aria-hidden":`true`}):(0,s.jsxs)(`svg`,{className:`info-tooltip-icon`,viewBox:`0 0 16 16`,fill:`none`,"aria-hidden":`true`,children:[(0,s.jsx)(`circle`,{cx:`8`,cy:`8`,r:`7`,stroke:`currentColor`,strokeWidth:`1.5`}),(0,s.jsx)(`path`,{d:`M8 7v4M8 5.5v0`,stroke:`currentColor`,strokeWidth:`1.5`,strokeLinecap:`round`})]}),i?(0,s.jsx)(`span`,{"aria-hidden":`true`,children:i}):null]}),c!==null&&(0,o.createPortal)((0,s.jsx)(`span`,{ref:d,"aria-hidden":`true`,className:`material-tooltip px-3 py-2 text-copy-13 text-secondary`,style:{position:`fixed`,top:c.top,left:c.left,transform:n===`bottom`?`translateX(-50%) translateY(8px)`:`translateX(-50%) translateY(calc(-100% - 8px))`,zIndex:9999,pointerEvents:`none`,width:n===`bottom`?`min(14rem, calc(100vw - 1rem))`:`14rem`},children:e}),u.current?.closest(`.app-shell-embed`)??document.body)]})}export{c as t};
@@ -0,0 +1,4 @@
1
+ import{r as e}from"./rolldown-runtime-XKyaHtl9.js";import{at as t,st as n}from"./vendor-lucide-CoTHJwai.js";import{r}from"./vendor-markdown-cQgSk2i0.js";import{_ as i,b as a,d as o,f as s,g as c,p as l,u}from"./vendor-tanstack-q5SvZtcv.js";import{Ct as d,Gr as f,Kr as p,Qr as ee,ji as m,mt as h,oi as g,ot as te,r as _,t as v}from"./ToneBadge-CXyUIWzB.js";import{_ as y,a as b,b as x}from"./format-helpers-Bs9rrO74.js";import{r as ne}from"./account-context-Bhgg1lEH.js";import{et as S,it as C,nn as re,nt as ie,rt as w,st as T,tt as ae,ut as oe}from"./react-query-DQr9PoNm.js";import{f as E,h as D}from"./ChartPrimitives-B5L9FUj3.js";import{t as O}from"./InfoTooltip-DrBIPuSU.js";import{I as k,J as A,L as j,V as se,W as M,X as N,at as P,cn as ce,fn as le,q as ue,st as F,un as de,z as fe}from"./index-3aBRkQpI.js";import{c as I,r as L,s as pe,t as R}from"./service-Cmt36bhL.js";var z=e(n(),1),B=r(),V={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 H(e){return[...new Set(e.split(`
2
+ `).map(e=>e.trim()).filter(Boolean))]}function U(e,t){return e.length===t.length&&e.every((e,n)=>e===t[n])}function W(e,t){return U(e.aliases,t.aliases)&&U(e.identityAliases??[],t.identityAliases??[])}function me(e,t,n){let{identityAliases:r,...i}=e;return n.length>0?{...i,aliases:t,identityAliases:n}:{...i,aliases:t}}function he({label:e,names:t}){return(0,B.jsxs)(`div`,{className:`space-y-1`,children:[(0,B.jsx)(`h3`,{className:`text-heading-14 text-heading`,children:e}),(0,B.jsx)(`ul`,{className:`space-y-1`,children:t.map(e=>(0,B.jsx)(`li`,{className:`text-label-14 text-secondary`,children:e},e))})]})}function G({id:e,issues:t}){return t.length===0?null:(0,B.jsx)(`ul`,{id:e,className:`mt-2 space-y-1`,"aria-label":`Name warnings`,children:t.map(e=>(0,B.jsx)(`li`,{className:`text-label-14 text-caution`,children:f(e)},`${e.field}:${e.index}`))})}function ge({projectName:e,targetKey:t,published:n,activeRevision:r,publishedBrandNames:o,service:s=R}){let{canWrite:c}=ne(),l=(0,z.useId)(),d=a({...ae({client:h,path:{name:e}}),enabled:c}),f=a({...oe({client:h,path:{name:e}}),enabled:c}),m=d.data?.draft?.authoring.targets.find(e=>e.stableKey===t),g=n.identityAliases??[],te=m!==void 0&&d.data?.draft?.baseActiveRevision===r&&!W(m,n),v=!d.isFetching&&!f.isPending,y=f.data,b=(0,z.useMemo)(()=>y?ee(y):o,[y,o]),[x,S]=(0,z.useState)(!1),[C,re]=(0,z.useState)(``),[ie,w]=(0,z.useState)(``),[T,E]=(0,z.useState)(n),[D,k]=(0,z.useState)(null),A=`${e}\u0000${t}`,[j,se]=(0,z.useState)(A);j!==A&&(se(A),S(!1),re(``),w(``),E(n),k(null));let M=(0,z.useRef)(A);M.current=A;let N=(0,z.useMemo)(()=>H(C),[C]),P=(0,z.useMemo)(()=>H(ie),[ie]),ce=(0,z.useMemo)(()=>p({aliases:N,identityAliases:P,brandNames:b}),[N,P,b]),le=ce.filter(e=>e.field===`aliases`),ue=ce.filter(e=>e.field===`identityAliases`);function F(e){re(e.aliases.join(`
3
+ `)),w((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 I(){F(te?m:n),k(null),S(!0)}function pe(e){e&&F(e),k({tone:`negative`,text:V.conflict,review:!1})}let U=i({mutationFn:async i=>{let a=await s.loadDraft(e);if(!a.draft){if(W(i.names,n))return{outcome:`unchanged`};if(!W(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(V.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`}:W(i.names,c)?{outcome:`unchanged`}:W(i.base,c)?(await s.upsertTarget(e,a.etag,me(c,i.names.aliases,i.names.identityAliases)),{outcome:`saved`}):{outcome:`conflict`,latest:c}},meta:{skipGlobalErrorToast:!0},onSuccess:(e,t)=>{if(t.openFor===M.current)switch(e.outcome){case`saved`:S(!1),k({tone:`positive`,text:V.saved,review:!0});return;case`unchanged`:S(!1),k({tone:`positive`,text:V.noChanges,review:!1});return;case`stale`:k({tone:`negative`,text:V.staleDraft,review:!0});return;case`missing`:k({tone:`negative`,text:V.missingFromDraft,review:!0});return;case`conflict`:pe(e.latest),d.refetch();return}},onError:(e,t)=>{t.openFor===M.current&&(L(e)?(pe(null),d.refetch().then(e=>{e.isSuccess&&pe(de(e.data))})):k({tone:`negative`,text:V.failed,review:!1}))}}),ge=(0,B.jsx)(u,{to:`/projects/$projectName/portfolio`,params:{projectName:e},className:`text-link underline-offset-2 hover:underline`,children:V.review}),K=n.aliases.length+g.length;return(0,B.jsxs)(`section`,{"aria-labelledby":`property-names`,className:`page-section-divider`,children:[(0,B.jsxs)(`div`,{className:`section-head section-head-inline`,children:[(0,B.jsxs)(`div`,{className:`flex items-center gap-1`,children:[(0,B.jsx)(`h2`,{id:`property-names`,className:`text-heading-16 text-heading`,children:V.heading}),(0,B.jsx)(O,{text:V.help})]}),(0,B.jsxs)(`div`,{className:`flex flex-wrap items-center gap-3`,children:[(0,B.jsxs)(`p`,{className:`supporting-copy`,children:[K,` `,K===1?`name`:`names`]}),c&&!x?(0,B.jsx)(_,{type:`button`,size:`sm`,variant:`outline`,className:`h-11 px-4 text-button-14 md:h-11`,disabled:!v,onClick:I,children:V.edit}):null]})]}),D?(0,B.jsxs)(`p`,{role:D.tone===`negative`?`alert`:`status`,className:`mb-3 text-copy-14 ${D.tone===`negative`?`text-negative`:`text-positive`}`,children:[D.text,D.review?(0,B.jsxs)(B.Fragment,{children:[` `,ge]}):null]}):te&&!x?(0,B.jsxs)(`p`,{role:`status`,className:`mb-3 text-copy-14 text-caution`,children:[V.pending,` `,ge]}):null,x?(0,B.jsxs)(`form`,{className:`space-y-4`,"aria-label":`Edit names`,onSubmit:e=>{e.preventDefault(),!U.isPending&&U.mutate({names:{aliases:N,identityAliases:P},base:T,openFor:A})},children:[(0,B.jsxs)(`div`,{children:[(0,B.jsx)(`label`,{htmlFor:`${l}-names`,className:`block text-label-14-strong text-heading`,children:V.names}),(0,B.jsx)(`p`,{id:`${l}-names-hint`,className:`text-copy-14 text-secondary`,children:V.namesHint}),(0,B.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-copy-14 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=>re(e.target.value)}),(0,B.jsx)(G,{id:`${l}-names-issues`,issues:le}),N.length===0?(0,B.jsx)(`p`,{className:`mt-2 text-copy-14 text-caution`,children:V.noNames}):null]}),(0,B.jsxs)(`div`,{children:[(0,B.jsx)(`label`,{htmlFor:`${l}-qualified`,className:`block text-label-14-strong text-heading`,children:V.qualifiedNames}),(0,B.jsx)(`p`,{id:`${l}-qualified-hint`,className:`text-copy-14 text-secondary`,children:V.qualifiedHint}),(0,B.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-copy-14 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:ie,onChange:e=>w(e.target.value)}),(0,B.jsx)(G,{id:`${l}-qualified-issues`,issues:ue}),(0,B.jsx)(`p`,{id:`${l}-qualified-note`,className:`mt-2 max-w-3xl text-copy-14 text-secondary`,children:V.qualifiedNote})]}),(0,B.jsx)(`p`,{className:`text-copy-14 text-secondary`,children:V.draftOnly}),(0,B.jsxs)(`div`,{className:`flex flex-wrap items-center gap-3`,children:[(0,B.jsx)(fe,{type:`submit`,className:`h-11 px-4 text-label-14 md:h-11`,disabled:U.isPending,children:U.isPending?V.saving:V.save}),(0,B.jsx)(_,{type:`button`,variant:`ghost`,className:`h-11 px-4 text-button-14 md:h-11`,disabled:U.isPending,onClick:()=>{S(!1),k(null)},children:V.cancel})]})]}):K===0?(0,B.jsx)(`p`,{className:`text-copy-14 text-secondary`,children:V.noNames}):(0,B.jsxs)(`div`,{className:`grid gap-4 sm:grid-cols-2`,children:[n.aliases.length>0?(0,B.jsx)(he,{label:V.names,names:n.aliases}):null,g.length>0?(0,B.jsx)(he,{label:V.qualifiedNames,names:g}):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:x,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,B.jsxs)(`span`,{className:`inline-flex flex-col items-start gap-0.5`,children:[(0,B.jsx)(v,{tone:`neutral`,children:`Not measured`}),(0,B.jsx)(`span`,{className:`text-label-12 text-muted`,children:`No mention signal for this Property`})]}):!e.mentioned&&e.mentionIdentity===`wrong-subject`?(0,B.jsxs)(`span`,{className:`inline-flex flex-col items-start gap-0.5`,children:[(0,B.jsx)(v,{tone:`neutral`,children:`Not mentioned`}),(0,B.jsxs)(`span`,{className:`inline-flex items-center gap-1 text-label-12 text-muted`,children:[F.label,(0,B.jsx)(O,{text:F.property})]})]}):(0,B.jsx)(v,{tone:e.mentioned?`positive`:`neutral`,children:e.mentioned?`Mentioned`:`Not mentioned`})}var xe=`—`;function Se({row:e}){return e.cited===null?(0,B.jsxs)(`span`,{className:`inline-flex flex-col items-start gap-0.5`,children:[(0,B.jsx)(v,{tone:`neutral`,children:`Not measured`}),(0,B.jsx)(`span`,{className:`text-label-12 text-muted`,children:`Sources were not fully captured`})]}):(0,B.jsx)(v,{tone:e.cited?`positive`:`neutral`,children:e.cited?`Cited`:`Not cited`})}function Ce({row:e}){return e.cited===null&&e.sources.length===0?(0,B.jsx)(`p`,{className:`py-2 text-copy-14 text-secondary`,children:`The sources for this answer were not fully captured, so none can be shown.`}):e.sources.length===0?(0,B.jsx)(`p`,{className:`py-2 text-copy-14 text-secondary`,children:`This answer returned no source URLs at all.`}):(0,B.jsxs)(`details`,{className:`mt-2`,"data-answer-sources":!0,children:[(0,B.jsxs)(`summary`,{className:`min-h-11 cursor-pointer py-3 text-label-14 text-secondary focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-mono-400`,children:[k,` (`,e.sources.length,`)`]}),(0,B.jsx)(`div`,{className:`overflow-x-auto`,children:(0,B.jsxs)(`table`,{className:`evidence-table min-w-[420px]`,children:[(0,B.jsxs)(`caption`,{className:`sr-only`,children:[`Source URLs for `,e.queryText]}),(0,B.jsx)(`thead`,{children:(0,B.jsxs)(`tr`,{children:[(0,B.jsx)(`th`,{children:`Match`}),(0,B.jsx)(`th`,{children:`URL`})]})}),(0,B.jsx)(`tbody`,{children:Y(e.sources).map(e=>(0,B.jsxs)(`tr`,{children:[(0,B.jsx)(`td`,{children:(0,B.jsx)(v,{tone:J[e.classification].tone,children:J[e.classification].label})}),(0,B.jsx)(`td`,{children:(0,B.jsx)(P,{url:e.sourceUrl})})]},e.sourceUrl))})]})})]})}function we({project:e,targetKey:t,resultId:n}){let r=a({...T({client:h,path:{name:e},query:{targetKey:t,resultId:n}})});if(r.isPending)return(0,B.jsx)(`p`,{className:`py-2 text-copy-14 text-secondary`,role:`status`,"aria-live":`polite`,children:`Loading the answer…`});if(r.isError)return(0,B.jsx)(`p`,{className:`py-2 text-copy-14 text-secondary`,role:`alert`,children:`Could not load this answer.`});let i=r.data?.answer;return i==null||i.trim()===``?(0,B.jsx)(`p`,{className:`py-2 text-copy-14 text-secondary`,children:`This answer was measured, but its text was not stored.`}):(0,B.jsx)(`div`,{className:`py-2`,children:(0,B.jsx)(j,{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,B.jsxs)(`span`,{className:`inline-flex flex-col gap-0.5`,children:[(0,B.jsx)(`span`,{className:n?`text-label-18-strong text-secondary`:`text-label-14-strong text-secondary`,children:`Not measured`}),(0,B.jsx)(`span`,{className:`text-label-14 text-secondary`,children:Te(e)})]});let r=g(e.value),i=e.numerator===void 0||e.denominator===void 0?null:`${e.numerator} of ${e.denominator}`,a=b(e,t);return(0,B.jsxs)(`span`,{className:`inline-flex flex-col gap-0.5 tabular-nums`,children:[(0,B.jsx)(`span`,{className:n?`text-label-18-strong text-heading`:`text-label-14-strong text-primary`,children:r}),i?(0,B.jsx)(`span`,{className:`text-label-12 text-muted`,children:i}):null,a?(0,B.jsx)(`span`,{className:`-ml-2 flex`,children:(0,B.jsx)(O,{tone:`caution`,placement:`bottom`,label:a.label,text:a.text})}):null]})}function Ee(e,t,n){return S({client:h,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,B.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,B.jsxs)(`section`,{"aria-labelledby":`property-market`,className:`page-section-divider`,children:[(0,B.jsxs)(`div`,{className:`section-head section-head-inline`,children:[(0,B.jsxs)(`div`,{children:[(0,B.jsx)(`p`,{className:`eyebrow eyebrow-soft`,children:`Competitive comparison`}),(0,B.jsxs)(`h2`,{id:`property-market`,className:`text-heading-16 text-heading`,children:[`Measured at the market level`,(0,B.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,B.jsx)(_,{asChild:!0,type:`button`,size:`sm`,variant:`outline`,children:(0,B.jsx)(u,{to:`/projects/$projectName`,params:{projectName:e},search:e=>A(M(e),{measurementScope:`project`}),children:`Open measurement overview`})})]}),(0,B.jsx)(`ul`,{className:`flex flex-wrap gap-2`,children:t.map(e=>(0,B.jsxs)(`li`,{className:`rounded-md border border-default px-3 py-1.5 text-label-14 text-strong`,children:[e.label,(0,B.jsxs)(`span`,{className:`ml-2 text-label-12 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,B.jsxs)(`div`,{className:`aeo-hero-row`,children:[(0,B.jsx)(`p`,{className:`aeo-hero-row-label`,children:e}),(0,B.jsx)(`p`,{className:`aeo-hero-row-value text-copy-16-strong text-secondary`,children:r?`Unavailable`:`…`}),r?(0,B.jsx)(`div`,{}):(0,B.jsx)(`div`,{className:`aeo-hero-row-bar`,"aria-hidden":`true`}),(0,B.jsx)(`p`,{className:`aeo-hero-row-detail`,children:r?`Could not be loaded`:`Loading`})]});if(t.state===`unavailable`){let n=Te(t);return(0,B.jsxs)(`div`,{className:`aeo-hero-row`,children:[(0,B.jsx)(`p`,{className:`aeo-hero-row-label`,children:e}),(0,B.jsx)(`p`,{className:`aeo-hero-row-value text-copy-16-strong text-secondary`,children:`Not measured`}),(0,B.jsx)(`div`,{}),(0,B.jsx)(`p`,{className:`aeo-hero-row-detail`,children:n===`Not measured`?``:n})]})}let{figure:i,sign:a}=y(g(t.value)),o=t.numerator===void 0||t.denominator===void 0?null:`${t.numerator} of ${t.denominator}`,s=b(t,n);return(0,B.jsxs)(`div`,{className:`aeo-hero-row`,children:[(0,B.jsx)(`p`,{className:`aeo-hero-row-label`,children:e}),(0,B.jsxs)(`p`,{className:`aeo-hero-row-value text-heading`,children:[i,a?(0,B.jsx)(`span`,{className:`text-faint`,children:a}):null]}),(0,B.jsx)(`div`,{className:`aeo-hero-row-bar`,"aria-hidden":`true`,children:(0,B.jsx)(`div`,{className:`metric-card-bar-fill progress-fill-neutral`,style:{width:`${t.value*100}%`}})}),(0,B.jsxs)(`p`,{className:`aeo-hero-row-detail tabular-nums`,children:[o??``,s?(0,B.jsx)(`span`,{className:`block`,children:(0,B.jsx)(O,{tone:`caution`,placement:`bottom`,label:s.label,text:s.text})}):null]})]})}function Ae({branded:e,nonBrand:t,brandedFailed:n=!1,nonBrandFailed:r=!1}){return(0,B.jsxs)(`section`,{"aria-labelledby":`property-coverage-hero`,children:[(0,B.jsx)(`h2`,{id:`property-coverage-hero`,className:`sr-only`,children:`Coverage for this Property`}),(0,B.jsxs)(`div`,{className:`space-y-5`,children:[(0,B.jsxs)(`div`,{className:`space-y-2`,children:[(0,B.jsx)(`p`,{className:`eyebrow eyebrow-soft`,children:`Non-brand · the demand to earn`}),(0,B.jsx)(Z,{label:`Mentioned`,metric:t?.mentionCoverage,signal:`mentioned`,failed:r}),(0,B.jsx)(Z,{label:`Cited`,metric:t?.citationCoverage,signal:`cited`,failed:r})]}),(0,B.jsxs)(`div`,{className:`space-y-2`,children:[(0,B.jsx)(`p`,{className:`eyebrow eyebrow-soft`,children:`Branded · already named`}),(0,B.jsx)(Z,{label:`Mentioned`,metric:e?.mentionCoverage,signal:`mentioned`,failed:n}),(0,B.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,B.jsxs)(`section`,{"aria-labelledby":`property-brand-contrast`,children:[(0,B.jsx)(`div`,{className:`section-head section-head-inline`,children:(0,B.jsxs)(`div`,{children:[(0,B.jsx)(`p`,{className:`eyebrow eyebrow-soft`,children:`The gap`}),(0,B.jsxs)(`h2`,{id:`property-brand-contrast`,className:`text-heading-16 text-heading`,children:[`Named versus not named`,(0,B.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,B.jsx)(`div`,{className:`overflow-x-auto rounded-md border border-default`,children:(0,B.jsxs)(`table`,{className:`evidence-table min-w-[560px]`,children:[(0,B.jsx)(`caption`,{className:`sr-only`,children:`Mention and citation coverage for this Property, split by query class`}),(0,B.jsx)(`thead`,{children:(0,B.jsxs)(`tr`,{children:[(0,B.jsx)(`th`,{children:`Query type`}),(0,B.jsx)(`th`,{children:`Mentioned in the answer`}),(0,B.jsx)(`th`,{children:`Cited as a source`})]})}),(0,B.jsx)(`tbody`,{children:[{queryClass:`branded`,row:e,isError:n},{queryClass:`non-brand`,row:t,isError:r}].map(({queryClass:e,row:t,isError:n})=>(0,B.jsxs)(`tr`,{children:[(0,B.jsxs)(`td`,{children:[(0,B.jsx)(`span`,{className:`block text-label-14-strong text-heading`,children:q[e].headline}),(0,B.jsx)(`span`,{className:`mt-0.5 block text-label-12 text-muted`,children:q[e].technical}),t&&n?(0,B.jsxs)(`span`,{className:`mt-2 flex flex-wrap items-center gap-2 text-label-14 text-caution`,children:[(0,B.jsx)(`span`,{role:`status`,children:`Refresh failed.`}),(0,B.jsxs)(_,{type:`button`,size:`sm`,variant:`ghost`,className:`h-11 px-3 text-button-14 md:h-11`,onClick:()=>i(e),children:[`Retry `,q[e].technical.toLocaleLowerCase()]})]}):null]}),t?(0,B.jsxs)(B.Fragment,{children:[(0,B.jsx)(`td`,{children:(0,B.jsx)(X,{metric:t.mentionCoverage,signal:`mentioned`,emphasis:!0})}),(0,B.jsx)(`td`,{children:(0,B.jsx)(X,{metric:t.citationCoverage,signal:`cited`,emphasis:!0})})]}):n?(0,B.jsx)(`td`,{colSpan:2,children:(0,B.jsxs)(`div`,{className:`flex flex-wrap items-center gap-3 text-label-14 text-secondary`,children:[(0,B.jsxs)(`span`,{role:`alert`,children:[`Could not load `,q[e].technical.toLocaleLowerCase(),`.`]}),(0,B.jsxs)(_,{type:`button`,size:`sm`,variant:`outline`,className:`h-11 px-4 text-button-14 md:h-11`,onClick:()=>i(e),children:[`Retry `,q[e].technical.toLocaleLowerCase()]})]})}):(0,B.jsxs)(B.Fragment,{children:[(0,B.jsx)(`td`,{children:(0,B.jsx)(`span`,{className:`text-label-14 text-secondary`,children:`Loading…`})}),(0,B.jsx)(`td`,{children:(0,B.jsx)(`span`,{className:`text-label-14 text-secondary`,children:`Loading…`})})]})]},e))})]})})]})}function Me({row:e,queryClass:t,isError:n}){return(0,B.jsxs)(`section`,{"aria-labelledby":`property-providers`,className:`page-section-divider`,children:[(0,B.jsx)(`div`,{className:`section-head section-head-inline`,children:(0,B.jsx)(`div`,{children:(0,B.jsxs)(`h2`,{id:`property-providers`,className:`text-heading-16 text-heading`,children:[`Which engines answer for this Property`,(0,B.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,B.jsxs)(`p`,{className:`text-copy-14 text-secondary`,children:[`Details for `,q[t].technical.toLocaleLowerCase(),` are unavailable. Retry that query type above.`]}):e===void 0?(0,B.jsx)(`p`,{className:`text-copy-14 text-secondary`,children:`Loading…`}):e.providers.length===0?(0,B.jsxs)(`p`,{className:`text-copy-14 text-secondary`,children:[`No answer engine has measured `,q[t].technical.toLocaleLowerCase(),` for this Property.`,e.mentionCoverage.state===`unavailable`?` ${Te(e.mentionCoverage)}.`:``]}):(0,B.jsx)(`div`,{className:`overflow-x-auto rounded-md border border-default`,children:(0,B.jsxs)(`table`,{className:`evidence-table min-w-[520px]`,children:[(0,B.jsx)(`caption`,{className:`sr-only`,children:`Per-engine mention and citation coverage`}),(0,B.jsx)(`thead`,{children:(0,B.jsxs)(`tr`,{children:[(0,B.jsx)(`th`,{children:`Engine`}),(0,B.jsx)(`th`,{children:`Mentioned`}),(0,B.jsx)(`th`,{children:`Cited`})]})}),(0,B.jsx)(`tbody`,{children:e.providers.map(e=>(0,B.jsxs)(`tr`,{children:[(0,B.jsx)(`td`,{className:`text-label-14-strong text-heading`,children:e.provider}),(0,B.jsx)(`td`,{children:(0,B.jsx)(X,{metric:e.mentionCoverage,signal:`mentioned`})}),(0,B.jsx)(`td`,{children:(0,B.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:h,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,B.jsxs)(`section`,{"aria-labelledby":`property-named-instead`,className:`page-section-divider`,children:[(0,B.jsxs)(`div`,{className:`section-head section-head-inline`,children:[(0,B.jsx)(`div`,{children:(0,B.jsxs)(`h2`,{id:`property-named-instead`,className:`text-heading-16 text-heading`,children:[`Named instead of this Property`,(0,B.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,B.jsxs)(`p`,{className:`supporting-copy`,children:[r.data?.total??i.length,` named`]}):null]}),i.length===0?(0,B.jsx)(`p`,{className:`text-copy-14 text-secondary`,children:`No rival was named in the answers this Property missed. Nothing to compete with here yet.`}):(0,B.jsxs)(B.Fragment,{children:[(0,B.jsx)(`div`,{className:`overflow-x-auto rounded-md border border-default`,children:(0,B.jsxs)(`table`,{className:`evidence-table min-w-[420px]`,children:[(0,B.jsx)(`caption`,{className:`sr-only`,children:`Names the engines gave instead of this Property`}),(0,B.jsx)(`thead`,{children:(0,B.jsxs)(`tr`,{children:[(0,B.jsx)(`th`,{children:`Named`}),(0,B.jsx)(`th`,{children:`Answers`}),(0,B.jsx)(`th`,{children:`Engines`}),(0,B.jsx)(`th`,{children:`Queries`})]})}),(0,B.jsx)(`tbody`,{children:i.map(e=>(0,B.jsxs)(`tr`,{children:[(0,B.jsx)(`td`,{className:`text-strong`,children:e.name}),(0,B.jsx)(`td`,{className:`tabular-nums text-secondary`,children:e.occurrences}),(0,B.jsxs)(`td`,{className:`text-secondary`,children:[e.providers.join(`, `),e.providersTruncated?` +${e.providerTotal-e.providers.length}`:``]}),(0,B.jsx)(`td`,{className:`text-right`,children:(0,B.jsxs)(`span`,{className:`inline-flex items-center justify-end gap-1`,children:[(0,B.jsx)(`span`,{className:`tabular-nums text-secondary`,children:e.questionTotal}),(0,B.jsx)(O,{text:Ne(e)})]})})]},e.name))})]})}),o?.state===`available`?(0,B.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,B.jsxs)(`section`,{"aria-labelledby":`property-questions`,className:`page-section-divider`,children:[(0,B.jsxs)(`div`,{className:`section-head section-head-inline`,children:[(0,B.jsx)(`div`,{children:(0,B.jsxs)(`h2`,{id:`property-questions`,className:`text-heading-16 text-heading`,children:[q[t].technical,` assigned to this Property`]})}),(0,B.jsxs)(`p`,{className:`supporting-copy`,children:[e.length,` assigned`]})]}),e.length===0?(0,B.jsxs)(`p`,{className:`text-copy-14 text-secondary`,children:[`No `,q[t].technical.toLocaleLowerCase(),` are assigned. Add one in advanced measurement setup to measure this class.`]}):(0,B.jsx)(`div`,{className:`overflow-x-auto rounded-md border border-default`,children:(0,B.jsxs)(`table`,{className:`evidence-table min-w-[420px]`,children:[(0,B.jsx)(`caption`,{className:`sr-only`,children:`Queries assigned to this Property`}),(0,B.jsx)(`thead`,{children:(0,B.jsx)(`tr`,{children:(0,B.jsx)(`th`,{children:`Query`})})}),(0,B.jsx)(`tbody`,{children:e.map(e=>(0,B.jsx)(`tr`,{children:(0,B.jsx)(`td`,{className:`text-secondary`,children:e})},e))})]})})]})}function Ie({urls:e}){return(0,B.jsxs)(`section`,{"aria-labelledby":`property-urls`,className:`page-section-divider`,children:[(0,B.jsxs)(`div`,{className:`section-head section-head-inline`,children:[(0,B.jsx)(`div`,{children:(0,B.jsxs)(`h2`,{id:`property-urls`,className:`text-heading-16 text-heading`,children:[`URLs that count as this Property`,(0,B.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,B.jsxs)(`p`,{className:`supporting-copy`,children:[e.length,` configured`]})]}),e.length===0?(0,B.jsx)(`p`,{className:`text-copy-14 text-secondary`,children:`No URLs are configured for this Property.`}):(0,B.jsx)(`div`,{className:`overflow-x-auto rounded-md border border-default`,children:(0,B.jsxs)(`table`,{className:`evidence-table min-w-[420px]`,children:[(0,B.jsx)(`caption`,{className:`sr-only`,children:`URL matchers configured for this Property`}),(0,B.jsx)(`thead`,{children:(0,B.jsx)(`tr`,{children:(0,B.jsx)(`th`,{children:`URL`})})}),(0,B.jsx)(`tbody`,{children:e.map(e=>(0,B.jsx)(`tr`,{children:(0,B.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,z.useState)(new Set),s={client:h,path:{name:e},query:{targetKey:t,queryClass:n,shape:m[`other-queries`],limit:K,...r?{runId:r}:{}}},l=c({...C(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??[]),p=d[0]?.otherQueries?.totalEstimate??f.length,ee=e=>`${e.expectedSlotId}:${e.queryClass}`,g=q[n].technical.toLocaleLowerCase();return(0,B.jsxs)(`section`,{"aria-labelledby":`property-other-queries`,className:`page-section-divider`,children:[(0,B.jsxs)(`div`,{className:`section-head section-head-inline`,children:[(0,B.jsxs)(`div`,{className:`flex items-center gap-1`,children:[(0,B.jsx)(`h2`,{id:`property-other-queries`,className:`text-heading-16 text-heading`,children:Q.heading}),(0,B.jsx)(O,{text:Q.help})]}),l.data?(0,B.jsxs)(`p`,{className:`supporting-copy`,children:[p,` `,p===1?`answer`:`answers`,` · `,g,` · `,Q.notCounted]}):null]}),l.isPending?(0,B.jsx)(`p`,{className:`text-copy-14 text-secondary`,children:`Loading…`}):l.isError&&f.length===0?(0,B.jsxs)(`div`,{className:`flex flex-wrap items-center gap-3 text-label-14 text-secondary`,children:[(0,B.jsx)(`span`,{role:`alert`,children:Q.loadError}),(0,B.jsx)(_,{type:`button`,size:`sm`,variant:`outline`,className:`h-11 px-4 text-button-14 md:h-11`,onClick:()=>{l.refetch()},children:`Retry`})]}):f.length===0?(0,B.jsx)(`p`,{className:`text-copy-14 text-secondary`,children:Q.empty}):(0,B.jsxs)(B.Fragment,{children:[(0,B.jsx)(`div`,{className:`overflow-x-auto rounded-md border border-default`,children:(0,B.jsxs)(`table`,{className:`evidence-table min-w-[640px]`,children:[(0,B.jsx)(`caption`,{className:`sr-only`,children:`Answers to other properties’ queries that cited this Property’s pages`}),(0,B.jsx)(`thead`,{children:(0,B.jsxs)(`tr`,{children:[(0,B.jsx)(`th`,{children:`Query`}),(0,B.jsx)(`th`,{children:`Assigned to`}),(0,B.jsx)(`th`,{children:`Pages cited`}),(0,B.jsx)(`th`,{children:(0,B.jsx)(`span`,{className:`sr-only`,children:`Answer`})})]})}),(0,B.jsx)(`tbody`,{children:f.map(t=>{let n=ee(t),r=a.has(n),s=`property-other-query-${encodeURIComponent(n)}`;return(0,B.jsxs)(z.Fragment,{children:[(0,B.jsxs)(`tr`,{children:[(0,B.jsxs)(`td`,{className:`text-secondary`,children:[(0,B.jsx)(`span`,{className:`block text-label-14-strong text-heading`,children:t.queryText}),(0,B.jsx)(`span`,{className:`mt-1 block text-label-12 text-muted`,children:[t.provider,t.location].filter(Boolean).join(` · `)})]}),(0,B.jsx)(`td`,{children:(0,B.jsx)(`ul`,{className:`space-y-1`,children:t.assignedTargetKeys.map(t=>(0,B.jsx)(`li`,{children:(0,B.jsx)(u,{to:`/projects/$projectName/properties/$targetKey`,params:{projectName:e,targetKey:t},search:M,className:`text-label-14 text-link hover:underline focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-mono-400`,children:i.get(t)??t})},t))})}),(0,B.jsxs)(`td`,{children:[(0,B.jsx)(`ul`,{className:`space-y-1`,children:t.sources.map(e=>(0,B.jsx)(`li`,{className:`min-w-0`,children:(0,B.jsx)(P,{url:e.sourceUrl})},e.sourceUrl))}),t.sourcesTruncated?(0,B.jsxs)(`span`,{className:`mt-1 block text-label-12 text-muted`,children:[t.sourceCount,` pages in total`]}):null,t.evidenceComplete?null:(0,B.jsx)(`span`,{className:`mt-1 block text-label-12 text-muted`,children:Q.partlySaved})]}),(0,B.jsx)(`td`,{className:`text-right`,children:(0,B.jsx)(_,{type:`button`,size:`sm`,variant:`ghost`,className:`h-auto pointer-coarse: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,B.jsx)(`tr`,{children:(0,B.jsx)(`td`,{id:s,colSpan:4,className:`bg-surface-subtle px-4`,children:(0,B.jsx)(we,{project:e,targetKey:t.assignedTargetKeys[0],resultId:t.observationId})})}):null]},n)})})]})}),l.hasNextPage?(0,B.jsxs)(`div`,{className:`mt-2 flex flex-wrap items-center gap-3 text-label-14 text-secondary`,children:[(0,B.jsxs)(`span`,{children:[`Showing `,f.length,` of `,p]}),(0,B.jsx)(_,{size:`sm`,variant:`outline`,className:`h-11 px-4 text-button-14 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:n}=l({strict:!1}),r=o(),i=s({strict:!1}),f=(0,z.useMemo)(()=>ue(i),[i]),[p,ee]=(0,z.useState)(new Set),g=e??``,y=n??``,b=!!g&&!!y,x=(0,z.useMemo)(()=>de(`portfolio`,ce(te())),[]),S=b&&x,{canWrite:w}=ne(),T=a({...ie({client:h,path:{name:g}}),enabled:S}),ae=T.data?.active?.plan,oe=ae?.schemaVersion===2?ae:null,E=f.queryClass===`branded`||f.queryClass===`non-brand`?f.queryClass:null,D=e=>oe?.assignments.some(t=>t.targetKey===y&&t.queryClass===e)??!1,j=E??(!D(`non-brand`)&&D(`branded`)?`branded`:`non-brand`);(0,z.useEffect)(()=>{oe&&!E&&r({to:`.`,replace:!0,search:e=>A(e,{queryClass:j})})},[oe,E,j,r]);let P=a({...Ee(g,y,`branded`),enabled:S}),F=a({...Ee(g,y,`non-brand`),enabled:S}),fe=De(P.data),I=De(F.data),L=j===`branded`?P.data:F.data,R=j===`branded`?fe:I,V=(j===`branded`?P.isError:F.isError)&&R===void 0,H=L?.measurement.displayedRunId;le(g,{view:`property`,selection:{mode:`advanced`,scope:`property`,scopeKey:y,queryClass:j,limit:10,...H?{runId:H}:{}}});let U=R?.mentionCoverage.state===`unavailable`?Te(R.mentionCoverage):void 0,W=L===void 0?void 0:L.measurement.completedAt??null,me=L!==void 0&&(L.measurement.state===`not_measured`||L.nextAction.kind===`run_measurement`),he=e=>A(M(e),{measurementScope:`property`,measurementScopeKey:y,queryClass:j,measurementRunId:void 0,measurementRevision:void 0,measurementTo:void 0}),G=a({...re({client:h,path:{name:g},query:N(ue(he(i)))}),enabled:S&&me,retry:!1}).data,_e=G!==void 0&&G.selection.measurement.measuredRevision!==null&&(G.populations.find(e=>e.queryClass===j)?.summary.queryCount??0)>0,J={client:h,path:{name:g},query:{targetKey:y,queryClass:j,shape:m.answers,limit:K,...H?{runId:H}:{}}},Y=c({...C(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=T.data?.active??null,Z=X?.plan.schemaVersion===2?X.plan:null,Ne=X!==null&&Z===null,Q=Z?.targets.find(e=>e.stableKey===y)??null,ze=Re(f,Z?.reportingScopes?.find(e=>e.stableKey===f.marketKey)?.label),Be=(0,z.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===y&&e.queryClass===j).flatMap(t=>{let n=e.get(t.queryId);return n===void 0?[]:[n]}))].sort((e,t)=>e.localeCompare(t))},[Z,y,j]),Ve=(0,z.useMemo)(()=>Q?.urlMatchers.map(pe)??[],[Q]),He=(0,z.useMemo)(()=>new Map((Z?.targets??[]).map(e=>[e.stableKey,e.label])),[Z]),Ue=(0,z.useMemo)(()=>Z?.groups.filter(e=>e.targetKeys.includes(y))??[],[Z,y]),$=(0,z.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,B.jsxs)(u,{to:`/projects/$projectName`,params:{projectName:g},search:M,className:`inline-flex items-center gap-1 text-label-12 text-muted hover:text-strong`,children:[(0,B.jsx)(t,{className:`size-3.5`,"aria-hidden":`true`}),`Back to AI Visibility`]});if(!b)return(0,B.jsx)(`div`,{className:`page-container`,children:(0,B.jsx)(`p`,{className:`text-copy-14 text-muted`,children:`Missing project name or Property key in URL.`})});if(!x)return(0,B.jsxs)(`div`,{className:`page-container space-y-3`,children:[qe,(0,B.jsx)(`p`,{className:`text-copy-14 text-muted`,children:`This view is not available here.`})]});if(T.isPending&&!T.isError)return(0,B.jsx)(`div`,{className:`page-container`,children:(0,B.jsxs)(`div`,{role:`status`,"aria-live":`polite`,children:[(0,B.jsx)(`span`,{className:`sr-only`,children:`Loading Property`}),(0,B.jsx)(`div`,{className:`h-32 animate-pulse rounded-md bg-surface-subtle`,"aria-hidden":`true`})]})});let Je=T.isError&&T.data===void 0,Ye=P.isError&&P.data===void 0,Xe=F.isError&&F.data===void 0;return Je||Ye&&Xe?(0,B.jsxs)(`div`,{className:`page-container space-y-3`,children:[qe,(0,B.jsx)(`p`,{role:`alert`,className:`text-copy-14 text-negative`,children:`Could not load this Property.`}),(0,B.jsx)(_,{type:`button`,size:`sm`,variant:`outline`,className:`h-11 px-4 text-button-14 md:h-11`,onClick:()=>{T.refetch(),P.refetch(),F.refetch()},children:`Try again`})]}):!Z||!Q?(0,B.jsxs)(`div`,{className:`page-container space-y-3`,children:[qe,(0,B.jsx)(`p`,{role:`status`,className:`text-copy-14 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,B.jsx)(_,{asChild:!0,type:`button`,variant:`outline`,className:`h-11 px-4 text-button-14 md:h-11`,children:(0,B.jsx)(u,{to:`/projects/$projectName/portfolio`,params:{projectName:g},children:w?Ne?`Republish setup`:`Open measurement setup`:`View measurement setup`})})]}):(0,B.jsxs)(`div`,{className:`page-container space-y-8`,children:[(0,B.jsxs)(`div`,{className:`page-header`,children:[(0,B.jsxs)(`div`,{className:`page-header-left`,children:[qe,(0,B.jsx)(`h1`,{className:`page-title mt-2`,children:Q.label}),(0,B.jsxs)(`p`,{className:`page-subtitle`,children:[`Property in `,g,ze?(0,B.jsxs)(B.Fragment,{children:[` · Filters not applied `,(0,B.jsx)(O,{text:ze})]}):null]})]}),(0,B.jsxs)(`div`,{className:`page-header-right`,children:[L?(0,B.jsx)(v,{tone:ve[L.measurement.state].tone,children:ve[L.measurement.state].label}):null,R&&R.flags>0?(0,B.jsxs)(v,{tone:`caution`,children:[R.flags,` flagged`]}):null]})]}),(0,B.jsx)(Ae,{branded:fe,nonBrand:I,brandedFailed:Ye,nonBrandFailed:Xe}),(0,B.jsx)(je,{branded:fe,nonBrand:I,brandedError:P.isError,nonBrandError:F.isError,onRetry:e=>{e===`branded`?P.refetch():F.refetch()}}),me?(0,B.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,B.jsx)(`p`,{className:`text-copy-14 text-secondary`,children:d()?se:w?`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,B.jsx)(_,{asChild:!0,type:`button`,className:`h-11 px-4 text-button-14 md:h-11`,children:(0,B.jsx)(u,{to:`/projects/$projectName`,params:{projectName:g},search:_e?he:M,children:_e?`See the last results`:w?`Go to AI Visibility`:`View AI Visibility`})})]}):null,(0,B.jsxs)(`div`,{className:`flex flex-wrap items-end gap-4 border-y border-default py-4`,children:[(0,B.jsxs)(`div`,{className:`space-y-1`,children:[(0,B.jsx)(`label`,{htmlFor:`property-query-class`,className:`block text-label-14-strong text-heading`,children:`Query type`}),(0,B.jsxs)(`select`,{id:`property-query-class`,value:j,onChange:e=>{let t=e.target.value===`branded`?`branded`:`non-brand`;r({to:`.`,search:e=>A(e,{queryClass:t})})},className:`h-11 rounded-md border border-default bg-surface px-3 text-label-14 text-primary focus:outline-none focus:ring-2 focus:ring-mono-400`,children:[(0,B.jsx)(`option`,{value:`non-brand`,children:q[`non-brand`].technical}),(0,B.jsx)(`option`,{value:`branded`,children:q.branded.technical})]})]}),(0,B.jsx)(Oe,{measuredAt:W,unmeasuredReason:U,queryClass:j})]}),(0,B.jsx)(Me,{row:R,queryClass:j,isError:V}),(0,B.jsx)(Pe,{project:g,targetKey:y,queryClass:j}),(0,B.jsx)(Fe,{questions:Be,queryClass:j}),(0,B.jsx)(ge,{projectName:g,targetKey:y,published:Q,activeRevision:X.revision,publishedBrandNames:Z.identities.projectBrand.names}),(0,B.jsx)(Ie,{urls:Ve}),(0,B.jsx)(ke,{project:g,groups:Ue}),(0,B.jsxs)(`section`,{"aria-labelledby":`property-evidence`,className:`page-section-divider`,children:[(0,B.jsxs)(`div`,{className:`section-head section-head-inline`,children:[(0,B.jsx)(`div`,{children:(0,B.jsxs)(`h2`,{id:`property-evidence`,className:`text-heading-16 text-heading`,children:[`Answers the engines gave`,(0,B.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,B.jsxs)(`p`,{className:`supporting-copy`,children:[$.length,` of `,We]}):null]}),V?(0,B.jsxs)(`p`,{className:`text-copy-14 text-secondary`,children:[`Evidence for `,q[j].technical.toLocaleLowerCase(),` is unavailable. Retry that query type above.`]}):Y.isPending&&$.length===0?(0,B.jsx)(`p`,{className:`text-copy-14 text-secondary`,children:`Loading evidence…`}):Y.isError&&$.length===0?(0,B.jsxs)(`div`,{className:`flex flex-wrap items-center gap-3 text-label-14 text-secondary`,children:[(0,B.jsx)(`span`,{role:`alert`,children:`Evidence could not be loaded.`}),(0,B.jsx)(_,{type:`button`,size:`sm`,variant:`outline`,className:`h-11 px-4 text-button-14 md:h-11`,onClick:()=>{Y.refetch()},children:`Retry evidence`})]}):Ke===`not_measured`?(0,B.jsx)(`p`,{className:`text-copy-14 text-secondary`,children:d()?se:`Not measured yet. Run a measurement to collect the answers for this Property.`}):Ge?(0,B.jsx)(`p`,{role:`alert`,className:`text-copy-14 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,B.jsx)(`p`,{className:`text-copy-14 text-secondary`,children:`No answers matched this Property in the displayed measurement.`}):(0,B.jsxs)(B.Fragment,{children:[(0,B.jsx)(`div`,{className:`property-answer-table-container overflow-x-auto rounded-md border border-default`,children:(0,B.jsxs)(`table`,{className:`evidence-table property-evidence-table`,children:[(0,B.jsx)(`caption`,{className:`sr-only`,children:`Answers measured for this Property`}),(0,B.jsx)(`thead`,{children:(0,B.jsxs)(`tr`,{children:[(0,B.jsx)(`th`,{children:`Query`}),(0,B.jsx)(`th`,{children:`Mentioned in the answer`}),(0,B.jsx)(`th`,{children:`Cited as a source`}),(0,B.jsx)(`th`,{children:`Sources`}),(0,B.jsx)(`th`,{children:(0,B.jsx)(`span`,{className:`sr-only`,children:`Sources detail`})})]})}),(0,B.jsx)(`tbody`,{children:$.map(e=>{let t=ye(e),n=p.has(t),r=`property-answer-${encodeURIComponent(t)}`;return(0,B.jsxs)(z.Fragment,{children:[(0,B.jsxs)(`tr`,{className:`property-answer-summary`,children:[(0,B.jsxs)(`td`,{className:`text-secondary`,children:[(0,B.jsx)(`h3`,{className:`text-heading-14 text-heading`,children:e.queryText}),(0,B.jsx)(`span`,{className:`mt-1 block text-label-12 text-muted`,children:[e.provider,e.location].filter(Boolean).join(` · `)}),e.historical||e.bridged?(0,B.jsx)(`span`,{className:`mt-1 flex`,children:(0,B.jsx)(v,{tone:`caution`,children:`Historical`})}):null]}),(0,B.jsxs)(`td`,{children:[(0,B.jsx)(`span`,{className:`property-evidence-mobile-label`,"aria-hidden":`true`,children:`Mentioned`}),(0,B.jsx)(be,{row:e})]}),(0,B.jsxs)(`td`,{children:[(0,B.jsx)(`span`,{className:`property-evidence-mobile-label`,"aria-hidden":`true`,children:`Cited`}),(0,B.jsx)(Se,{row:e})]}),(0,B.jsxs)(`td`,{className:`tabular-nums text-secondary`,children:[(0,B.jsx)(`span`,{className:`property-evidence-mobile-label`,"aria-hidden":`true`,children:k}),e.cited===null?xe:e.sources.length]}),(0,B.jsx)(`td`,{className:`text-right`,children:(0,B.jsx)(_,{type:`button`,size:`sm`,variant:`ghost`,className:`h-auto pointer-coarse: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:()=>ee(e=>{let n=new Set(e);return n.delete(t)||n.add(t),n}),children:n?`Hide answer`:`Read answer`})})]}),n?(0,B.jsx)(`tr`,{className:`property-answer-detail`,children:(0,B.jsxs)(`td`,{id:r,colSpan:5,className:`bg-surface-subtle px-4`,children:[(0,B.jsx)(we,{project:g,targetKey:y,resultId:e.observationId}),(0,B.jsx)(Ce,{row:e})]})}):null]},t)})})]})}),Y.hasNextPage?(0,B.jsxs)(`div`,{className:`mt-2 flex flex-wrap items-center gap-3 text-label-14 text-secondary`,children:[(0,B.jsxs)(`span`,{children:[`Showing `,$.length,` of `,We]}),Y.isFetchNextPageError?(0,B.jsx)(`span`,{role:`alert`,children:`Could not load more evidence.`}):null,(0,B.jsx)(_,{size:`sm`,variant:`outline`,className:`h-11 px-4 text-button-14 md:h-11`,disabled:Y.isFetchingNextPage,onClick:()=>{Y.fetchNextPage()},children:Y.isFetchingNextPage?`Loading…`:Y.isFetchNextPageError?`Retry more evidence`:`Show ${K} more`})]}):null]})]}),L?(0,B.jsx)(Le,{project:g,targetKey:y,queryClass:j,runId:H,targetLabels:He}):null]})}export{J as EVIDENCE_LABELS,ze as MeasurementPropertyPage,Q as OTHER_QUERIES_COPY};