@ainyc/canonry 4.87.0 → 4.88.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/agent-workspace/skills/canonry/references/server-side-traffic.md +19 -0
- package/assets/assets/{BacklinksPage-BPvsw_Bi.js → BacklinksPage-Dpx6ylmU.js} +1 -1
- package/assets/assets/{ChartPrimitives-BdlKCq7y.js → ChartPrimitives-CG5EGu62.js} +1 -1
- package/assets/assets/{ProjectPage-1Q8YC9Vd.js → ProjectPage-B_xnYE7W.js} +1 -1
- package/assets/assets/{RunRow-DcSsnE5c.js → RunRow-C0V4vf-u.js} +1 -1
- package/assets/assets/{RunsPage-DKoIMkQL.js → RunsPage-9gWTjteG.js} +1 -1
- package/assets/assets/{SettingsPage-bH3PdNKb.js → SettingsPage-kBwz4Glg.js} +1 -1
- package/assets/assets/{TrafficPage-IW_DX-0V.js → TrafficPage-D4adjs8S.js} +1 -1
- package/assets/assets/TrafficSourceDetailPage-CmURRHaU.js +1 -0
- package/assets/assets/{arrow-left-B5Du72nk.js → arrow-left-DJ0-oFbd.js} +1 -1
- package/assets/assets/{extract-error-message-C7Vhd5zH.js → extract-error-message-DfBzETgi.js} +1 -1
- package/assets/assets/{index-C_ZzKZfM.js → index-BeuGfMy8.js} +53 -53
- package/assets/assets/{trash-2-DWcofmpv.js → trash-2-Bjf6mCqw.js} +1 -1
- package/assets/index.html +1 -1
- package/dist/{chunk-DUDFNP5Y.js → chunk-2VEFNAQ3.js} +4 -4
- package/dist/{chunk-MDRDX5R2.js → chunk-JZ67YCHT.js} +168 -0
- package/dist/{chunk-6XMXBAEW.js → chunk-RH3QYFX3.js} +1 -1
- package/dist/{chunk-5LW7CJAO.js → chunk-WMZJO56S.js} +30 -6
- package/dist/cli.js +13 -7
- package/dist/index.js +4 -4
- package/dist/{intelligence-service-XUKYOHKL.js → intelligence-service-WTEEV46F.js} +2 -2
- package/dist/mcp.js +2 -2
- package/package.json +9 -9
- package/assets/assets/TrafficSourceDetailPage-DRHOGn9B.js +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
import{c}from"./index-
|
|
1
|
+
import{c}from"./index-BeuGfMy8.js";const a=[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["path",{d:"m9 12 2 2 4-4",key:"dzmm74"}]],h=c("circle-check",a);const e=[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["path",{d:"M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3",key:"1u773s"}],["path",{d:"M12 17h.01",key:"p32p05"}]],n=c("circle-question-mark",e);const o=[["path",{d:"M12 15V3",key:"m9g1x1"}],["path",{d:"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4",key:"ih7n3h"}],["path",{d:"m7 10 5 5 5-5",key:"brsn70"}]],s=c("download",o);const t=[["path",{d:"M10 11v6",key:"nco0om"}],["path",{d:"M14 11v6",key:"outv1u"}],["path",{d:"M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6",key:"miytrc"}],["path",{d:"M3 6h18",key:"d0wm0j"}],["path",{d:"M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2",key:"e791ji"}]],r=c("trash-2",t);export{h as C,s as D,r as T,n as a};
|
package/assets/index.html
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
<link rel="icon" type="image/png" sizes="32x32" href="./favicon-32.png" />
|
|
13
13
|
<link rel="apple-touch-icon" href="./apple-touch-icon.png" />
|
|
14
14
|
<title>Canonry</title>
|
|
15
|
-
<script type="module" crossorigin src="./assets/index-
|
|
15
|
+
<script type="module" crossorigin src="./assets/index-BeuGfMy8.js"></script>
|
|
16
16
|
<link rel="modulepreload" crossorigin href="./assets/vendor-tanstack-Dq7p98wZ.js">
|
|
17
17
|
<link rel="modulepreload" crossorigin href="./assets/vendor-radix-B57xfQbP.js">
|
|
18
18
|
<link rel="modulepreload" crossorigin href="./assets/vendor-recharts-ClRVR6aX.js">
|
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
loadConfig,
|
|
10
10
|
loadConfigRaw,
|
|
11
11
|
saveConfigPatch
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-RH3QYFX3.js";
|
|
13
13
|
import {
|
|
14
14
|
CC_CACHE_DIR,
|
|
15
15
|
DUCKDB_SPEC,
|
|
@@ -104,7 +104,7 @@ import {
|
|
|
104
104
|
siteAuditPages,
|
|
105
105
|
siteAuditSnapshots,
|
|
106
106
|
usageCounters
|
|
107
|
-
} from "./chunk-
|
|
107
|
+
} from "./chunk-WMZJO56S.js";
|
|
108
108
|
import {
|
|
109
109
|
AGENT_MEMORY_VALUE_MAX_BYTES,
|
|
110
110
|
AGENT_PROVIDER_IDS,
|
|
@@ -160,7 +160,7 @@ import {
|
|
|
160
160
|
validationError,
|
|
161
161
|
winnabilityClassLabel,
|
|
162
162
|
withRetry
|
|
163
|
-
} from "./chunk-
|
|
163
|
+
} from "./chunk-JZ67YCHT.js";
|
|
164
164
|
|
|
165
165
|
// src/telemetry.ts
|
|
166
166
|
import crypto from "crypto";
|
|
@@ -6289,7 +6289,7 @@ function readStoredGroundingSources(rawResponse) {
|
|
|
6289
6289
|
return result;
|
|
6290
6290
|
}
|
|
6291
6291
|
async function backfillInsightsCommand(project, opts) {
|
|
6292
|
-
const { IntelligenceService: IntelligenceService2 } = await import("./intelligence-service-
|
|
6292
|
+
const { IntelligenceService: IntelligenceService2 } = await import("./intelligence-service-WTEEV46F.js");
|
|
6293
6293
|
const config = loadConfig();
|
|
6294
6294
|
const db = createClient(config.database);
|
|
6295
6295
|
migrate(db);
|
|
@@ -4555,6 +4555,20 @@ function coerceSkillManifest(parsed) {
|
|
|
4555
4555
|
|
|
4556
4556
|
// ../contracts/src/traffic.ts
|
|
4557
4557
|
import { z as z30 } from "zod";
|
|
4558
|
+
var trafficCrawlerSegmentsSchema = z30.object({
|
|
4559
|
+
content: z30.number().int().nonnegative(),
|
|
4560
|
+
sitemap: z30.number().int().nonnegative(),
|
|
4561
|
+
robots: z30.number().int().nonnegative(),
|
|
4562
|
+
asset: z30.number().int().nonnegative(),
|
|
4563
|
+
other: z30.number().int().nonnegative()
|
|
4564
|
+
});
|
|
4565
|
+
var trafficPathClassSchema = z30.enum([
|
|
4566
|
+
"content",
|
|
4567
|
+
"sitemap",
|
|
4568
|
+
"robots",
|
|
4569
|
+
"asset",
|
|
4570
|
+
"other"
|
|
4571
|
+
]);
|
|
4558
4572
|
var trafficSourceTypeSchema = z30.enum([
|
|
4559
4573
|
"cloud-run",
|
|
4560
4574
|
"wordpress",
|
|
@@ -4711,7 +4725,18 @@ var trafficBackfillResponseSchema = z30.object({
|
|
|
4711
4725
|
daysApplied: z30.number().int().positive()
|
|
4712
4726
|
});
|
|
4713
4727
|
var trafficSourceTotalsSchema = z30.object({
|
|
4728
|
+
/**
|
|
4729
|
+
* Total classified-crawler hits in the window. UNCHANGED contract — still the
|
|
4730
|
+
* full count across every path class. Use `crawlerContentHits` for the
|
|
4731
|
+
* "content was actually crawled" signal.
|
|
4732
|
+
*/
|
|
4714
4733
|
crawlerHits: z30.number().int().nonnegative(),
|
|
4734
|
+
/** Crawler hits against content/document paths only (= `crawlerSegments.content`). */
|
|
4735
|
+
crawlerContentHits: z30.number().int().nonnegative(),
|
|
4736
|
+
/** Infrastructure crawler hits — sitemap + robots + asset fetches (`crawlerSegments.{sitemap,robots,asset}`). */
|
|
4737
|
+
crawlerInfraHits: z30.number().int().nonnegative(),
|
|
4738
|
+
/** Full per-class crawler-hit breakdown; the five buckets sum to `crawlerHits`. */
|
|
4739
|
+
crawlerSegments: trafficCrawlerSegmentsSchema,
|
|
4715
4740
|
aiUserFetchHits: z30.number().int().nonnegative(),
|
|
4716
4741
|
aiReferralHits: z30.number().int().nonnegative(),
|
|
4717
4742
|
sampleCount: z30.number().int().nonnegative()
|
|
@@ -4742,6 +4767,8 @@ var trafficCrawlerEventEntrySchema = z30.object({
|
|
|
4742
4767
|
operator: z30.string(),
|
|
4743
4768
|
verificationStatus: z30.string(),
|
|
4744
4769
|
pathNormalized: z30.string(),
|
|
4770
|
+
/** Coarse class of the fetched path — lets the UI split content crawls from sitemap/robots/asset polling. */
|
|
4771
|
+
pathClass: trafficPathClassSchema,
|
|
4745
4772
|
status: z30.number().int(),
|
|
4746
4773
|
hits: z30.number().int().nonnegative()
|
|
4747
4774
|
});
|
|
@@ -4777,13 +4804,151 @@ var trafficEventsResponseSchema = z30.object({
|
|
|
4777
4804
|
windowStart: z30.string(),
|
|
4778
4805
|
windowEnd: z30.string(),
|
|
4779
4806
|
totals: z30.object({
|
|
4807
|
+
/** Total classified-crawler hits across the window. UNCHANGED contract. */
|
|
4780
4808
|
crawlerHits: z30.number().int().nonnegative(),
|
|
4809
|
+
/** Crawler hits against content/document paths only (= `crawlerSegments.content`). */
|
|
4810
|
+
crawlerContentHits: z30.number().int().nonnegative(),
|
|
4811
|
+
/** Infrastructure crawler hits — sitemap + robots + asset fetches. */
|
|
4812
|
+
crawlerInfraHits: z30.number().int().nonnegative(),
|
|
4813
|
+
/** Full per-class crawler-hit breakdown; the five buckets sum to `crawlerHits`. */
|
|
4814
|
+
crawlerSegments: trafficCrawlerSegmentsSchema,
|
|
4781
4815
|
aiUserFetchHits: z30.number().int().nonnegative(),
|
|
4782
4816
|
aiReferralHits: z30.number().int().nonnegative()
|
|
4783
4817
|
}),
|
|
4784
4818
|
events: z30.array(trafficEventEntrySchema)
|
|
4785
4819
|
});
|
|
4786
4820
|
|
|
4821
|
+
// ../contracts/src/traffic-path.ts
|
|
4822
|
+
var TrafficPathClasses = {
|
|
4823
|
+
content: "content",
|
|
4824
|
+
sitemap: "sitemap",
|
|
4825
|
+
robots: "robots",
|
|
4826
|
+
asset: "asset",
|
|
4827
|
+
other: "other"
|
|
4828
|
+
};
|
|
4829
|
+
var ROBOTS_BASENAMES = /* @__PURE__ */ new Set(["robots.txt", "llms.txt", "llms-full.txt"]);
|
|
4830
|
+
var ASSET_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
4831
|
+
"css",
|
|
4832
|
+
"js",
|
|
4833
|
+
"mjs",
|
|
4834
|
+
"cjs",
|
|
4835
|
+
"map",
|
|
4836
|
+
"json",
|
|
4837
|
+
"png",
|
|
4838
|
+
"jpg",
|
|
4839
|
+
"jpeg",
|
|
4840
|
+
"webp",
|
|
4841
|
+
"avif",
|
|
4842
|
+
"gif",
|
|
4843
|
+
"svg",
|
|
4844
|
+
"ico",
|
|
4845
|
+
"bmp",
|
|
4846
|
+
"tif",
|
|
4847
|
+
"tiff",
|
|
4848
|
+
"woff",
|
|
4849
|
+
"woff2",
|
|
4850
|
+
"ttf",
|
|
4851
|
+
"otf",
|
|
4852
|
+
"eot",
|
|
4853
|
+
"mp4",
|
|
4854
|
+
"webm",
|
|
4855
|
+
"mov",
|
|
4856
|
+
"m4v",
|
|
4857
|
+
"mp3",
|
|
4858
|
+
"wav",
|
|
4859
|
+
"ogg",
|
|
4860
|
+
"flac",
|
|
4861
|
+
"m4a",
|
|
4862
|
+
"wasm"
|
|
4863
|
+
]);
|
|
4864
|
+
var DOCUMENT_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
4865
|
+
"html",
|
|
4866
|
+
"htm",
|
|
4867
|
+
"xhtml",
|
|
4868
|
+
"shtml",
|
|
4869
|
+
"php",
|
|
4870
|
+
"php5",
|
|
4871
|
+
"php7",
|
|
4872
|
+
"asp",
|
|
4873
|
+
"aspx",
|
|
4874
|
+
"jsp",
|
|
4875
|
+
"jspx",
|
|
4876
|
+
"cfm",
|
|
4877
|
+
"md"
|
|
4878
|
+
]);
|
|
4879
|
+
var DOWNLOAD_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
4880
|
+
"pdf",
|
|
4881
|
+
"csv",
|
|
4882
|
+
"tsv",
|
|
4883
|
+
"txt",
|
|
4884
|
+
"doc",
|
|
4885
|
+
"docx",
|
|
4886
|
+
"xls",
|
|
4887
|
+
"xlsx",
|
|
4888
|
+
"ppt",
|
|
4889
|
+
"pptx",
|
|
4890
|
+
"odt",
|
|
4891
|
+
"ods",
|
|
4892
|
+
"odp",
|
|
4893
|
+
"rtf",
|
|
4894
|
+
"zip",
|
|
4895
|
+
"gz",
|
|
4896
|
+
"tgz",
|
|
4897
|
+
"tar",
|
|
4898
|
+
"rar",
|
|
4899
|
+
"7z",
|
|
4900
|
+
"bz2",
|
|
4901
|
+
"xz",
|
|
4902
|
+
"rss",
|
|
4903
|
+
"atom",
|
|
4904
|
+
"ics",
|
|
4905
|
+
"vcf",
|
|
4906
|
+
"epub",
|
|
4907
|
+
"mobi",
|
|
4908
|
+
"apk",
|
|
4909
|
+
"dmg",
|
|
4910
|
+
"exe",
|
|
4911
|
+
"bin",
|
|
4912
|
+
"iso",
|
|
4913
|
+
"sql"
|
|
4914
|
+
]);
|
|
4915
|
+
var SITEMAP_BASENAME = /^sitemap(?:[-_]index)?$/;
|
|
4916
|
+
function classifyTrafficPath(pathNormalized) {
|
|
4917
|
+
const raw = (pathNormalized ?? "").trim();
|
|
4918
|
+
if (!raw) return TrafficPathClasses.other;
|
|
4919
|
+
const rawPath = raw.split(/[?#]/)[0] ?? "";
|
|
4920
|
+
const pathOnly = rawPath.length > 1 ? rawPath.replace(/\/+$/, "") || "/" : rawPath;
|
|
4921
|
+
if (!pathOnly) return TrafficPathClasses.other;
|
|
4922
|
+
const lower = pathOnly.toLowerCase();
|
|
4923
|
+
const segments = lower.split("/");
|
|
4924
|
+
const basename = segments[segments.length - 1] ?? "";
|
|
4925
|
+
if (ROBOTS_BASENAMES.has(basename)) return TrafficPathClasses.robots;
|
|
4926
|
+
if (lower.endsWith(".xml") || lower.endsWith(".xml.gz")) return TrafficPathClasses.sitemap;
|
|
4927
|
+
if (SITEMAP_BASENAME.test(basename)) return TrafficPathClasses.sitemap;
|
|
4928
|
+
const dot = basename.lastIndexOf(".");
|
|
4929
|
+
const ext = dot > 0 ? basename.slice(dot + 1) : "";
|
|
4930
|
+
if (ext) {
|
|
4931
|
+
if (ASSET_EXTENSIONS.has(ext)) return TrafficPathClasses.asset;
|
|
4932
|
+
if (DOCUMENT_EXTENSIONS.has(ext)) return TrafficPathClasses.content;
|
|
4933
|
+
if (DOWNLOAD_EXTENSIONS.has(ext)) return TrafficPathClasses.other;
|
|
4934
|
+
return TrafficPathClasses.content;
|
|
4935
|
+
}
|
|
4936
|
+
return TrafficPathClasses.content;
|
|
4937
|
+
}
|
|
4938
|
+
function emptyCrawlerSegments() {
|
|
4939
|
+
return { content: 0, sitemap: 0, robots: 0, asset: 0, other: 0 };
|
|
4940
|
+
}
|
|
4941
|
+
function segmentCrawlerHits(rows) {
|
|
4942
|
+
const segments = emptyCrawlerSegments();
|
|
4943
|
+
for (const row of rows) {
|
|
4944
|
+
segments[classifyTrafficPath(row.pathNormalized)] += row.hits;
|
|
4945
|
+
}
|
|
4946
|
+
return segments;
|
|
4947
|
+
}
|
|
4948
|
+
function sumInfraHits(segments) {
|
|
4949
|
+
return segments.sitemap + segments.robots + segments.asset;
|
|
4950
|
+
}
|
|
4951
|
+
|
|
4787
4952
|
// ../contracts/src/formatting.ts
|
|
4788
4953
|
function formatRatio(value) {
|
|
4789
4954
|
if (!Number.isFinite(value) || value === 0) return "0%";
|
|
@@ -5285,6 +5450,9 @@ export {
|
|
|
5285
5450
|
trafficEventKindSchema,
|
|
5286
5451
|
TrafficEventKinds,
|
|
5287
5452
|
trafficEventsResponseSchema,
|
|
5453
|
+
classifyTrafficPath,
|
|
5454
|
+
segmentCrawlerHits,
|
|
5455
|
+
sumInfraHits,
|
|
5288
5456
|
formatRatio,
|
|
5289
5457
|
formatNumber,
|
|
5290
5458
|
formatDate,
|
|
@@ -86,6 +86,7 @@ import {
|
|
|
86
86
|
classifyCitedSurface,
|
|
87
87
|
classifySkillFile,
|
|
88
88
|
classifySurfaceFromCategory,
|
|
89
|
+
classifyTrafficPath,
|
|
89
90
|
clusterByCosine,
|
|
90
91
|
coerceSkillManifest,
|
|
91
92
|
competitorBatchRequestSchema,
|
|
@@ -210,6 +211,7 @@ import {
|
|
|
210
211
|
scheduleDtoSchema,
|
|
211
212
|
scheduleUpsertRequestSchema,
|
|
212
213
|
seedCollapseWarning,
|
|
214
|
+
segmentCrawlerHits,
|
|
213
215
|
serializeRunError,
|
|
214
216
|
settingsDtoSchema,
|
|
215
217
|
siteAuditPagesResponseSchema,
|
|
@@ -222,6 +224,7 @@ import {
|
|
|
222
224
|
snapshotReportSchema,
|
|
223
225
|
snapshotRequestSchema,
|
|
224
226
|
sourceBreakdownDtoSchema,
|
|
227
|
+
sumInfraHits,
|
|
225
228
|
summarizeCheckResults,
|
|
226
229
|
surfaceClassFromCompetitorType,
|
|
227
230
|
surfaceClassLabel,
|
|
@@ -255,7 +258,7 @@ import {
|
|
|
255
258
|
wordpressSchemaDeployResultDtoSchema,
|
|
256
259
|
wordpressSchemaStatusResultDtoSchema,
|
|
257
260
|
wordpressStatusDtoSchema
|
|
258
|
-
} from "./chunk-
|
|
261
|
+
} from "./chunk-JZ67YCHT.js";
|
|
259
262
|
|
|
260
263
|
// src/intelligence-service.ts
|
|
261
264
|
import { eq as eq37, desc as desc18, asc as asc5, and as and27, ne as ne5, or as or5, inArray as inArray14, gte as gte7, lte as lte4 } from "drizzle-orm";
|
|
@@ -30625,12 +30628,19 @@ async function trafficRoutes(app, opts) {
|
|
|
30625
30628
|
return response;
|
|
30626
30629
|
});
|
|
30627
30630
|
function buildSourceDetail(projectId, row, since) {
|
|
30628
|
-
const
|
|
30631
|
+
const crawlerPathRows = app.db.select({
|
|
30632
|
+
pathNormalized: crawlerEventsHourly.pathNormalized,
|
|
30633
|
+
hits: sql11`COALESCE(SUM(${crawlerEventsHourly.hits}), 0)`
|
|
30634
|
+
}).from(crawlerEventsHourly).where(
|
|
30629
30635
|
and21(
|
|
30630
30636
|
eq27(crawlerEventsHourly.sourceId, row.id),
|
|
30631
30637
|
gte4(crawlerEventsHourly.tsHour, since)
|
|
30632
30638
|
)
|
|
30633
|
-
).
|
|
30639
|
+
).groupBy(crawlerEventsHourly.pathNormalized).all();
|
|
30640
|
+
const crawlerSegments = segmentCrawlerHits(
|
|
30641
|
+
crawlerPathRows.map((r) => ({ pathNormalized: r.pathNormalized, hits: Number(r.hits) }))
|
|
30642
|
+
);
|
|
30643
|
+
const crawlerTotal = crawlerSegments.content + crawlerSegments.sitemap + crawlerSegments.robots + crawlerSegments.asset + crawlerSegments.other;
|
|
30634
30644
|
const aiUserFetchTotals = app.db.select({ total: sql11`COALESCE(SUM(${aiUserFetchEventsHourly.hits}), 0)` }).from(aiUserFetchEventsHourly).where(
|
|
30635
30645
|
and21(
|
|
30636
30646
|
eq27(aiUserFetchEventsHourly.sourceId, row.id),
|
|
@@ -30659,7 +30669,10 @@ async function trafficRoutes(app, opts) {
|
|
|
30659
30669
|
return {
|
|
30660
30670
|
...rowToDto(row),
|
|
30661
30671
|
totals24h: {
|
|
30662
|
-
crawlerHits:
|
|
30672
|
+
crawlerHits: crawlerTotal,
|
|
30673
|
+
crawlerContentHits: crawlerSegments.content,
|
|
30674
|
+
crawlerInfraHits: sumInfraHits(crawlerSegments),
|
|
30675
|
+
crawlerSegments,
|
|
30663
30676
|
aiUserFetchHits: Number(aiUserFetchTotals?.total ?? 0),
|
|
30664
30677
|
aiReferralHits: Number(aiTotals?.total ?? 0),
|
|
30665
30678
|
sampleCount: Number(sampleTotals?.total ?? 0)
|
|
@@ -30776,6 +30789,7 @@ async function trafficRoutes(app, opts) {
|
|
|
30776
30789
|
const untilIso = until.toISOString();
|
|
30777
30790
|
const events = [];
|
|
30778
30791
|
let crawlerTotal = 0;
|
|
30792
|
+
let crawlerSegments = { content: 0, sitemap: 0, robots: 0, asset: 0, other: 0 };
|
|
30779
30793
|
let aiUserFetchTotal = 0;
|
|
30780
30794
|
let aiReferralTotal = 0;
|
|
30781
30795
|
if (kind === "all" || kind === TrafficEventKinds.crawler) {
|
|
@@ -30786,8 +30800,14 @@ async function trafficRoutes(app, opts) {
|
|
|
30786
30800
|
];
|
|
30787
30801
|
if (sourceIdParam) crawlerFilters.push(eq27(crawlerEventsHourly.sourceId, sourceIdParam));
|
|
30788
30802
|
const crawlerWhere = and21(...crawlerFilters);
|
|
30789
|
-
const
|
|
30790
|
-
|
|
30803
|
+
const pathTotals = app.db.select({
|
|
30804
|
+
pathNormalized: crawlerEventsHourly.pathNormalized,
|
|
30805
|
+
hits: sql11`COALESCE(SUM(${crawlerEventsHourly.hits}), 0)`
|
|
30806
|
+
}).from(crawlerEventsHourly).where(crawlerWhere).groupBy(crawlerEventsHourly.pathNormalized).all();
|
|
30807
|
+
crawlerSegments = segmentCrawlerHits(
|
|
30808
|
+
pathTotals.map((r) => ({ pathNormalized: r.pathNormalized, hits: Number(r.hits) }))
|
|
30809
|
+
);
|
|
30810
|
+
crawlerTotal = crawlerSegments.content + crawlerSegments.sitemap + crawlerSegments.robots + crawlerSegments.asset + crawlerSegments.other;
|
|
30791
30811
|
const rows = app.db.select().from(crawlerEventsHourly).where(crawlerWhere).orderBy(desc15(crawlerEventsHourly.tsHour)).limit(limit).all();
|
|
30792
30812
|
for (const r of rows) {
|
|
30793
30813
|
events.push({
|
|
@@ -30798,6 +30818,7 @@ async function trafficRoutes(app, opts) {
|
|
|
30798
30818
|
operator: r.operator,
|
|
30799
30819
|
verificationStatus: r.verificationStatus,
|
|
30800
30820
|
pathNormalized: r.pathNormalized,
|
|
30821
|
+
pathClass: classifyTrafficPath(r.pathNormalized),
|
|
30801
30822
|
status: r.status,
|
|
30802
30823
|
hits: r.hits
|
|
30803
30824
|
});
|
|
@@ -30861,6 +30882,9 @@ async function trafficRoutes(app, opts) {
|
|
|
30861
30882
|
windowEnd: untilIso,
|
|
30862
30883
|
totals: {
|
|
30863
30884
|
crawlerHits: crawlerTotal,
|
|
30885
|
+
crawlerContentHits: crawlerSegments.content,
|
|
30886
|
+
crawlerInfraHits: sumInfraHits(crawlerSegments),
|
|
30887
|
+
crawlerSegments,
|
|
30864
30888
|
aiUserFetchHits: aiUserFetchTotal,
|
|
30865
30889
|
aiReferralHits: aiReferralTotal
|
|
30866
30890
|
},
|
package/dist/cli.js
CHANGED
|
@@ -27,7 +27,7 @@ import {
|
|
|
27
27
|
setTelemetrySource,
|
|
28
28
|
showFirstRunNotice,
|
|
29
29
|
trackEvent
|
|
30
|
-
} from "./chunk-
|
|
30
|
+
} from "./chunk-2VEFNAQ3.js";
|
|
31
31
|
import {
|
|
32
32
|
CliError,
|
|
33
33
|
EXIT_SYSTEM_ERROR,
|
|
@@ -44,7 +44,7 @@ import {
|
|
|
44
44
|
saveConfig,
|
|
45
45
|
saveConfigPatch,
|
|
46
46
|
usageError
|
|
47
|
-
} from "./chunk-
|
|
47
|
+
} from "./chunk-RH3QYFX3.js";
|
|
48
48
|
import {
|
|
49
49
|
apiKeys,
|
|
50
50
|
createClient,
|
|
@@ -52,7 +52,7 @@ import {
|
|
|
52
52
|
projects,
|
|
53
53
|
queries,
|
|
54
54
|
renderReportHtml
|
|
55
|
-
} from "./chunk-
|
|
55
|
+
} from "./chunk-WMZJO56S.js";
|
|
56
56
|
import {
|
|
57
57
|
BacklinkSources,
|
|
58
58
|
CcReleaseSyncStatuses,
|
|
@@ -77,7 +77,7 @@ import {
|
|
|
77
77
|
providerQuotaPolicySchema,
|
|
78
78
|
resolveProviderInput,
|
|
79
79
|
winnabilityClassSchema
|
|
80
|
-
} from "./chunk-
|
|
80
|
+
} from "./chunk-JZ67YCHT.js";
|
|
81
81
|
|
|
82
82
|
// src/cli.ts
|
|
83
83
|
import { pathToFileURL } from "url";
|
|
@@ -4245,7 +4245,10 @@ async function trafficStatus(project, opts) {
|
|
|
4245
4245
|
console.log(` Status: ${d.status}`);
|
|
4246
4246
|
console.log(` Last synced: ${d.lastSyncedAt ?? "never"}`);
|
|
4247
4247
|
if (d.lastError) console.log(` Last error: ${d.lastError}`);
|
|
4248
|
-
console.log(` 24h
|
|
4248
|
+
console.log(` 24h content: ${d.totals24h.crawlerContentHits} crawls`);
|
|
4249
|
+
console.log(` 24h infra: ${d.totals24h.crawlerInfraHits} sitemap/robots/asset fetches`);
|
|
4250
|
+
console.log(` 24h other: ${d.totals24h.crawlerSegments.other} fetches`);
|
|
4251
|
+
console.log(` 24h crawler: ${d.totals24h.crawlerHits} hits total`);
|
|
4249
4252
|
console.log(` 24h AI referral: ${d.totals24h.aiReferralHits} sessions`);
|
|
4250
4253
|
console.log(` 24h samples: ${d.totals24h.sampleCount}`);
|
|
4251
4254
|
if (d.latestRun) {
|
|
@@ -4268,7 +4271,7 @@ function formatEventLine(event) {
|
|
|
4268
4271
|
event.botId,
|
|
4269
4272
|
event.verificationStatus,
|
|
4270
4273
|
String(event.status),
|
|
4271
|
-
event.pathNormalized
|
|
4274
|
+
`${event.pathNormalized} [${event.pathClass}]`,
|
|
4272
4275
|
`${event.hits} hits`
|
|
4273
4276
|
].join(" ");
|
|
4274
4277
|
case TrafficEventKinds["ai-user-fetch"]:
|
|
@@ -4328,7 +4331,10 @@ async function trafficEvents(project, opts) {
|
|
|
4328
4331
|
return;
|
|
4329
4332
|
}
|
|
4330
4333
|
console.log(`Traffic events for "${project}" ${result.windowStart} \u2192 ${result.windowEnd}`);
|
|
4331
|
-
console.log(`
|
|
4334
|
+
console.log(` Content crawls (window): ${result.totals.crawlerContentHits}`);
|
|
4335
|
+
console.log(` Infra fetches (window): ${result.totals.crawlerInfraHits} (sitemap ${result.totals.crawlerSegments.sitemap} \xB7 robots ${result.totals.crawlerSegments.robots} \xB7 asset ${result.totals.crawlerSegments.asset})`);
|
|
4336
|
+
console.log(` Other fetches (window): ${result.totals.crawlerSegments.other}`);
|
|
4337
|
+
console.log(` Crawler hits total (window): ${result.totals.crawlerHits}`);
|
|
4332
4338
|
console.log(` AI user-fetch hits (window): ${result.totals.aiUserFetchHits}`);
|
|
4333
4339
|
console.log(` AI referral sessions (window): ${result.totals.aiReferralHits}`);
|
|
4334
4340
|
console.log("");
|
package/dist/index.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
2
|
createServer
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-2VEFNAQ3.js";
|
|
4
4
|
import {
|
|
5
5
|
loadConfig
|
|
6
|
-
} from "./chunk-
|
|
7
|
-
import "./chunk-
|
|
8
|
-
import "./chunk-
|
|
6
|
+
} from "./chunk-RH3QYFX3.js";
|
|
7
|
+
import "./chunk-WMZJO56S.js";
|
|
8
|
+
import "./chunk-JZ67YCHT.js";
|
|
9
9
|
export {
|
|
10
10
|
createServer,
|
|
11
11
|
loadConfig
|
package/dist/mcp.js
CHANGED
|
@@ -3,10 +3,10 @@ import {
|
|
|
3
3
|
PACKAGE_VERSION,
|
|
4
4
|
canonryMcpTools,
|
|
5
5
|
createApiClient
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-RH3QYFX3.js";
|
|
7
7
|
import {
|
|
8
8
|
isReadOnlyKey
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-JZ67YCHT.js";
|
|
10
10
|
|
|
11
11
|
// src/mcp/cli.ts
|
|
12
12
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ainyc/canonry",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.88.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Agent-first open-source AEO operating platform - track how answer engines cite your domain",
|
|
6
6
|
"license": "FSL-1.1-ALv2",
|
|
@@ -62,25 +62,25 @@
|
|
|
62
62
|
"@types/node-cron": "^3.0.11",
|
|
63
63
|
"tsup": "^8.5.1",
|
|
64
64
|
"tsx": "^4.19.0",
|
|
65
|
-
"@ainyc/canonry-api-routes": "0.0.0",
|
|
66
|
-
"@ainyc/canonry-config": "0.0.0",
|
|
67
65
|
"@ainyc/canonry-api-client": "0.0.0",
|
|
66
|
+
"@ainyc/canonry-config": "0.0.0",
|
|
67
|
+
"@ainyc/canonry-api-routes": "0.0.0",
|
|
68
68
|
"@ainyc/canonry-contracts": "0.0.0",
|
|
69
69
|
"@ainyc/canonry-db": "0.0.0",
|
|
70
|
-
"@ainyc/canonry-integration-
|
|
70
|
+
"@ainyc/canonry-integration-bing": "0.0.0",
|
|
71
71
|
"@ainyc/canonry-integration-cloud-run": "0.0.0",
|
|
72
72
|
"@ainyc/canonry-integration-commoncrawl": "0.0.0",
|
|
73
|
-
"@ainyc/canonry-integration-bing": "0.0.0",
|
|
74
|
-
"@ainyc/canonry-integration-google-business-profile": "0.0.0",
|
|
75
73
|
"@ainyc/canonry-integration-google": "0.0.0",
|
|
74
|
+
"@ainyc/canonry-integration-openai-ads": "0.0.0",
|
|
75
|
+
"@ainyc/canonry-integration-google-business-profile": "0.0.0",
|
|
76
76
|
"@ainyc/canonry-integration-google-places": "0.0.0",
|
|
77
77
|
"@ainyc/canonry-integration-traffic": "0.0.0",
|
|
78
|
-
"@ainyc/canonry-integration-wordpress": "0.0.0",
|
|
79
78
|
"@ainyc/canonry-intelligence": "0.0.0",
|
|
80
|
-
"@ainyc/canonry-
|
|
81
|
-
"@ainyc/canonry-provider-local": "0.0.0",
|
|
79
|
+
"@ainyc/canonry-integration-wordpress": "0.0.0",
|
|
82
80
|
"@ainyc/canonry-provider-cdp": "0.0.0",
|
|
81
|
+
"@ainyc/canonry-provider-gemini": "0.0.0",
|
|
83
82
|
"@ainyc/canonry-provider-claude": "0.0.0",
|
|
83
|
+
"@ainyc/canonry-provider-local": "0.0.0",
|
|
84
84
|
"@ainyc/canonry-provider-openai": "0.0.0",
|
|
85
85
|
"@ainyc/canonry-provider-perplexity": "0.0.0"
|
|
86
86
|
},
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{j as e,A as Re,B as Le,r as h,L as $e}from"./vendor-tanstack-Dq7p98wZ.js";import{I as O,c2 as Y,c3 as u,T as Ee,B as Ue,g as H,b as Fe,c4 as Me,c5 as He}from"./index-C_ZzKZfM.js";import{g as Pe,h as Oe,i as De,t as Be,R as _e,d as Ge}from"./extract-error-message-C7Vhd5zH.js";import{e as ee,i as Ke,C as ie,a as le,c as We,h as Ve}from"./ChartPrimitives-BdlKCq7y.js";import{R as Ye,B as Xe,a as Qe,X as qe,Y as Ze,T as Je,e as X,f as Q}from"./vendor-recharts-ClRVR6aX.js";import{A as ce}from"./arrow-left-B5Du72nk.js";import"./vendor-radix-B57xfQbP.js";import"./vendor-markdown-DK7fbRNb.js";function q({value:s,label:a,delta:n,tone:r,description:x,tooltip:l,isNumeric:c=!0,progress:o,providerCoverage:d}){const v=2*Math.PI*48,m=Number.parseInt(s,10),I=typeof o=="number"&&Number.isFinite(o)?Math.min(Math.max(o,0),100)/100:c&&!Number.isNaN(m)?Math.min(m/100,1):.5,y=v*(1-I);return e.jsxs("div",{className:"score-gauge",children:[e.jsxs("div",{className:"gauge-ring-wrapper",children:[e.jsxs("svg",{className:"gauge-ring",viewBox:"0 0 120 120","aria-hidden":"true",children:[e.jsx("circle",{className:"gauge-bg",cx:"60",cy:"60",r:48,strokeWidth:6}),e.jsx("circle",{className:`gauge-fill gauge-fill-${r}`,cx:"60",cy:"60",r:48,strokeWidth:6,strokeDasharray:v,strokeDashoffset:y,transform:"rotate(-90 60 60)"})]}),e.jsx("div",{className:"gauge-center",children:e.jsx("span",{className:c?"gauge-value":"gauge-value-text",children:s.split(" / ")[0]})})]}),e.jsxs("p",{className:"gauge-label",children:[a,l&&e.jsx(O,{text:l})]}),e.jsx("p",{className:"gauge-delta",children:n}),d&&e.jsx("p",{className:"gauge-provider-coverage",children:d}),e.jsx("p",{className:"gauge-description",children:x})]})}const et=[{value:"all",label:"All status"},{value:"2xx",label:"2xx success"},{value:"3xx",label:"3xx redirect"},{value:"4xx",label:"4xx client error"},{value:"5xx",label:"5xx server error"}],fe=[{value:"all",label:"All claims"},{value:Y.verified,label:"Verified"},{value:Y.claimed_unverified,label:"Claimed unverified"},{value:Y.unknown_ai_like,label:"Unknown AI-like"}];function tt(s){return s==="all"?null:Number.parseInt(s[0],10)}function pe(s){switch(s.kind){case u.crawler:case u["ai-user-fetch"]:return s.botId;case u["ai-referral"]:return s.product}}function ge(s){switch(s.kind){case u.crawler:case u["ai-user-fetch"]:return s.pathNormalized;case u["ai-referral"]:return s.landingPathNormalized}}function st(s){switch(s.kind){case u.crawler:case u["ai-user-fetch"]:return s.verificationStatus;case u["ai-referral"]:return null}}function be(s,a){if(a==="hour")return s;const n=new Date(s),r=n.getFullYear(),x=String(n.getMonth()+1).padStart(2,"0"),l=String(n.getDate()).padStart(2,"0");return`${r}-${x}-${l}`}function at(s,a,n){const r=a.pathQuery.trim().toLowerCase(),x=tt(a.statusClass);return s.filter(l=>!(a.selectedBucket&&be(l.tsHour,n)!==a.selectedBucket||a.identity&&pe(l)!==a.identity||a.operator&&l.operator!==a.operator||r&&!ge(l).toLowerCase().includes(r)||x!==null&&Math.floor(l.status/100)!==x||a.verification!=="all"&&st(l)!==a.verification))}function rt(s,a){if(!s||typeof s!="object")return null;const n=s.activeTooltipIndex;let r;if(typeof n=="number")r=n;else if(typeof n=="string"&&n!=="")r=Number(n);else return null;return!Number.isInteger(r)||r<0||r>=a.length?null:a[r]?.bucket??null}const D=[{value:60,label:"1h",granularity:"hour",fetchLimit:500},{value:360,label:"6h",granularity:"hour",fetchLimit:500},{value:1440,label:"24h",granularity:"hour",fetchLimit:500},{value:10080,label:"7d",granularity:"hour",fetchLimit:1e3},{value:720*60,label:"30d",granularity:"day",fetchLimit:2e3},{value:2160*60,label:"90d",granularity:"day",fetchLimit:5e3}],oe=D.find(s=>s.label==="24h")??D[2],L=50,ue=ee[0],de=ee[2],xe=ee[1],he=Me();function je(s){const a=new Date(s);return`${a.getMonth()+1}/${a.getDate()} ${String(a.getHours()).padStart(2,"0")}:00`}function nt(s){const a=new Date(`${s}T00:00:00`);return`${a.getMonth()+1}/${a.getDate()}`}function $(s){if(!s)return"never";const a=Date.now()-new Date(s).getTime(),n=Math.floor(a/6e4);if(n<1)return"just now";if(n<60)return`${n}m ago`;const r=Math.floor(n/60);return r<24?`${r}h ago`:`${Math.floor(r/24)}d ago`}function me({canGoBack:s,className:a}){const n="inline-flex items-center gap-1";if(s){const r=()=>{window.history.back()};return e.jsxs("button",{type:"button",onClick:r,className:`${n} ${a??""}`,children:[e.jsx(ce,{className:"size-3"})," Back"]})}return e.jsxs($e,{to:"/traffic",className:`${n} ${a??""}`,children:[e.jsx(ce,{className:"size-3"})," All sources"]})}function yt(){const s=Re({strict:!1}),a=s.projectName??"",n=Le(),r=s.sourceId??"",[x,l]=h.useState(oe.value),[c,o]=h.useState(()=>new Set(["crawler","ai-user-fetch","ai-referral"])),[d,z]=h.useState(null),[f,v]=h.useState(""),[m,I]=h.useState(""),[y,B]=h.useState(""),[S,_]=h.useState("all"),[k,G]=h.useState("all"),[ye,K]=h.useState(1),[te,se]=h.useState(null),[ae,re]=h.useState(null),b=h.useMemo(()=>D.find(t=>t.value===x)??oe,[x]),W=Pe(a||null,r||null),j=Oe(a||null,{kind:"all",sourceId:r||void 0,sinceMinutes:x,limit:b.fetchLimit}),E=De(a||null,r||null),i=W.data,N=j.data?.events??[],C=j.data?.totals,U=h.useMemo(()=>N.filter(t=>{switch(t.kind){case u.crawler:return c.has("crawler");case u["ai-user-fetch"]:return c.has("ai-user-fetch");case u["ai-referral"]:return c.has("ai-referral")}}),[N,c]),ve=h.useMemo(()=>{const t=new Set;for(const p of N)t.add(pe(p));return f&&t.add(f),[...t].sort((p,g)=>p.localeCompare(g))},[N,f]),Ne=h.useMemo(()=>{const t=new Set;for(const p of N)t.add(p.operator);return m&&t.add(m),[...t].sort((p,g)=>p.localeCompare(g))},[N,m]),w=h.useMemo(()=>at(U,{selectedBucket:d,identity:f,operator:m,pathQuery:y,statusClass:S,verification:k},b.granularity),[U,d,f,m,y,S,k,b.granularity]);h.useEffect(()=>{K(1)},[U,d,f,m,y,S,k]);const F=Math.max(1,Math.ceil(w.length/L)),M=Math.min(Math.max(1,ye),F),R=(M-1)*L,we=h.useMemo(()=>w.slice(R,R+L),[w,R]),ze=w.length>L,Se=w.length===0?0:R+1,ke=Math.min(R+L,w.length),ne=h.useMemo(()=>d?P(d,b.granularity):null,[d,b.granularity]),T=h.useMemo(()=>it(N,b.granularity,j.data?.windowStart,j.data?.windowEnd),[N,b.granularity,j.data?.windowStart,j.data?.windowEnd]),V=t=>{o(p=>{const g=new Set(p);return g.has(t)?g.size>1&&g.delete(t):g.add(t),g})},Ce=t=>{const p=rt(t,T);p&&z(g=>g===p?null:p)},Te=()=>{z(null),v(""),I(""),B(""),_("all"),G("all")},Ae=!!(d||f||m||y.trim()||S!=="all"||k!=="all"),Ie=async()=>{se(null),re(null);try{const t=await E.mutateAsync({sinceMinutes:60});re(`Pulled ${t.pulledEvents} entries · ${t.crawlerHits} crawler · ${t.aiUserFetchHits} AI user fetch · ${t.aiReferralHits} AI referral · ${t.unknownHits} unknown`)}catch(t){se(Ge(t))}};return!a||!r?e.jsx("div",{className:"page-container",children:e.jsx("p",{className:"text-sm text-zinc-500",children:"Missing project name or source id in URL."})}):W.isLoading?e.jsx("div",{className:"page-container",children:e.jsx("p",{className:"text-sm text-zinc-500",children:"Loading source…"})}):W.isError||!i?e.jsxs("div",{className:"page-container",children:[e.jsx("p",{className:"text-sm text-rose-300",children:"Could not load this source."}),e.jsx(me,{canGoBack:n,className:"mt-2 text-xs text-zinc-400 hover:text-zinc-200"})]}):e.jsxs("div",{className:"page-container space-y-8",children:[e.jsxs("div",{className:"page-header",children:[e.jsxs("div",{className:"page-header-left",children:[e.jsx(me,{canGoBack:n,className:"text-xs text-zinc-500 hover:text-zinc-200"}),e.jsx("h1",{className:"page-title mt-2",children:i.displayName}),e.jsxs("p",{className:"page-subtitle",children:[i.sourceType," · project ",e.jsx("span",{className:"text-zinc-300",children:a})," ·",e.jsx("span",{className:"ml-1 font-mono text-zinc-400",children:i.id})]})]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(Ee,{tone:Be(i.status),children:i.status}),e.jsxs(Ue,{type:"button",variant:"outline",size:"sm",disabled:E.isPending,onClick:()=>{Ie()},children:[e.jsx(_e,{className:`size-3.5 ${E.isPending?"animate-spin":""}`}),E.isPending?"Syncing…":"Sync now"]})]})]}),te?e.jsx("div",{className:"rounded-md border border-rose-800/50 bg-rose-950/30 px-3 py-2 text-xs text-rose-200",children:te}):null,ae?e.jsx("div",{className:"rounded-md border border-emerald-800/50 bg-emerald-950/30 px-3 py-2 text-xs text-emerald-200",children:ae}):null,e.jsxs("section",{className:"grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3",children:[e.jsx(q,{label:"24h crawler hits",value:String(i.totals24h.crawlerHits),delta:i.lastSyncedAt?`last sync ${$(i.lastSyncedAt)}`:"never synced",tone:i.totals24h.crawlerHits>0?"positive":"neutral",description:"Bulk machine crawl — GPTBot, OAI-SearchBot, PerplexityBot, Googlebot, etc.",isNumeric:!0,progress:Math.min(100,Math.round(i.totals24h.crawlerHits/1e3*100))}),e.jsx(q,{label:"24h AI user fetches",value:String(i.totals24h.aiUserFetchHits),delta:i.lastSyncedAt?`last sync ${$(i.lastSyncedAt)}`:"never synced",tone:i.totals24h.aiUserFetchHits>0?"positive":"neutral",description:"ChatGPT-User, Perplexity-User — fetches initiated by a real user inside an AI surface (citation click, URL read).",isNumeric:!0,progress:Math.min(100,Math.round(i.totals24h.aiUserFetchHits/1e3*100))}),e.jsx(q,{label:"24h AI referral sessions",value:String(i.totals24h.aiReferralHits),delta:i.lastSyncedAt?`last sync ${$(i.lastSyncedAt)}`:"never synced",tone:i.totals24h.aiReferralHits>0?"positive":"neutral",description:"Browser click-throughs from chatgpt.com, perplexity.ai, etc. (Referer / UTM evidence).",isNumeric:!0,progress:Math.min(100,Math.round(i.totals24h.aiReferralHits/1e3*100))})]}),e.jsxs("section",{children:[e.jsx("p",{className:"mb-4 text-[10px] font-semibold uppercase tracking-wider text-zinc-500",children:"Latest sync run"}),i.latestRun?e.jsxs(H,{className:"p-4 text-sm",children:[e.jsxs("div",{className:"flex flex-wrap items-center gap-x-6 gap-y-1.5",children:[e.jsxs("span",{className:"text-zinc-100",children:["Status: ",e.jsx("span",{className:"font-medium",children:i.latestRun.status})]}),e.jsxs("span",{className:"text-zinc-500",children:["Started: ",$(i.latestRun.startedAt)]}),i.latestRun.finishedAt?e.jsxs("span",{className:"text-zinc-500",children:["Finished: ",$(i.latestRun.finishedAt)]}):null,e.jsx("span",{className:"font-mono text-[11px] text-zinc-600",children:i.latestRun.runId})]}),i.latestRun.error?e.jsx("p",{className:"mt-2 rounded border border-rose-900/40 bg-rose-950/30 px-3 py-2 text-xs text-rose-300",children:i.latestRun.error}):null]}):e.jsx(H,{className:"px-4 py-3 text-sm text-zinc-500",children:'No traffic-sync runs recorded yet. Hit "Sync now" above to create one.'})]}),e.jsxs("section",{children:[e.jsxs("div",{className:"mb-4 flex flex-wrap items-end justify-between gap-x-4 gap-y-3",children:[e.jsxs("div",{children:[e.jsx("p",{className:"text-[10px] font-semibold uppercase tracking-wider text-zinc-500",children:"Events"}),e.jsx("h2",{className:"mt-1 text-base font-semibold text-zinc-50",children:b.granularity==="day"?"Daily rollups":"Hourly rollups"}),C?e.jsxs("p",{className:"mt-1.5 text-xs text-zinc-500",children:[C.crawlerHits.toLocaleString("en-US")," crawler ·"," ",C.aiUserFetchHits.toLocaleString("en-US")," AI user fetches ·"," ",C.aiReferralHits.toLocaleString("en-US")," AI referral sessions · last ",b.label," · ",he]}):null]}),e.jsx("div",{className:"filter-row mb-0",role:"toolbar","aria-label":"Window",children:D.map(t=>e.jsx("button",{type:"button",className:`filter-chip ${x===t.value?"filter-chip-active":""}`,"aria-pressed":x===t.value,onClick:()=>{l(t.value),z(null)},children:t.label},t.value))})]}),e.jsxs(H,{className:"p-4",children:[e.jsxs("div",{className:"mb-3 flex flex-wrap items-center gap-2",role:"toolbar","aria-label":"Series",children:[e.jsx(J,{label:"Crawler",color:ue,count:C?.crawlerHits??0,active:c.has("crawler"),onToggle:()=>V("crawler")}),e.jsx(J,{label:"AI user fetches",color:de,count:C?.aiUserFetchHits??0,active:c.has("ai-user-fetch"),onToggle:()=>V("ai-user-fetch")}),e.jsx(J,{label:"AI referral sessions",color:xe,count:C?.aiReferralHits??0,active:c.has("ai-referral"),onToggle:()=>V("ai-referral")})]}),j.isError?e.jsxs("p",{className:"py-12 text-center text-xs text-rose-400",children:["Failed to load events: ",j.error instanceof Error?j.error.message:"Unknown error"]}):j.isLoading?e.jsx("p",{className:"py-12 text-center text-xs text-zinc-500",children:"Loading events…"}):T.length===0?e.jsx("p",{className:"py-12 text-center text-xs text-zinc-500",children:"No events in this window."}):e.jsx("div",{className:"h-72",children:e.jsx(Ye,{children:e.jsxs(Xe,{data:T,margin:{top:4,right:4,bottom:0,left:0},onClick:Ce,style:{cursor:"pointer"},children:[e.jsx(Qe,{stroke:Ke,strokeDasharray:"3 3"}),e.jsx(qe,{dataKey:"label",tick:le,stroke:ie,interval:"preserveStartEnd",minTickGap:b.granularity==="day"?24:32}),e.jsx(Ze,{tick:le,stroke:ie,allowDecimals:!1}),e.jsx(Je,{...We}),c.has("crawler")?e.jsx(X,{dataKey:"crawler",name:"Crawler",fill:ue,stackId:"a",children:T.map(t=>e.jsx(Q,{fillOpacity:d&&d!==t.bucket?.25:1},t.bucket))}):null,c.has("ai-user-fetch")?e.jsx(X,{dataKey:"aiUserFetch",name:"AI user fetch",fill:de,stackId:"a",children:T.map(t=>e.jsx(Q,{fillOpacity:d&&d!==t.bucket?.25:1},t.bucket))}):null,c.has("ai-referral")?e.jsx(X,{dataKey:"aiReferral",name:"AI referral",fill:xe,stackId:"a",children:T.map(t=>e.jsx(Q,{fillOpacity:d&&d!==t.bucket?.25:1},t.bucket))}):null]})})})]})]}),e.jsxs("section",{children:[e.jsxs("div",{className:"mb-4 flex flex-wrap items-end justify-between gap-x-4 gap-y-2",children:[e.jsxs("div",{children:[e.jsx("p",{className:"text-[10px] font-semibold uppercase tracking-wider text-zinc-500",children:"Event rows"}),e.jsxs("p",{className:"mt-1 text-xs text-zinc-500",children:["Showing ",e.jsx("span",{className:"tabular-nums text-zinc-300",children:w.length.toLocaleString("en-US")})," of"," ",e.jsx("span",{className:"tabular-nums text-zinc-500",children:U.length.toLocaleString("en-US")})," events · ",he]})]}),e.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[e.jsxs("span",{className:"inline-flex items-center text-zinc-400",children:[e.jsxs("select",{"aria-label":"Filter by identity",value:f,onChange:t=>v(t.target.value),className:"rounded-md border border-zinc-800 bg-zinc-950 px-2.5 py-1.5 text-xs text-zinc-200 focus:outline-none focus-visible:ring-1 focus-visible:ring-zinc-600",children:[e.jsx("option",{value:"",children:"All identities"}),ve.map(t=>e.jsx("option",{value:t,children:t},t))]}),e.jsx(O,{text:"The specific bot or AI product making the request (e.g., GPTBot, ChatGPT-User, Perplexity). One operator usually runs several identities."})]}),e.jsxs("span",{className:"inline-flex items-center text-zinc-400",children:[e.jsxs("select",{"aria-label":"Filter by operator",value:m,onChange:t=>I(t.target.value),className:"rounded-md border border-zinc-800 bg-zinc-950 px-2.5 py-1.5 text-xs text-zinc-200 focus:outline-none focus-visible:ring-1 focus-visible:ring-zinc-600",children:[e.jsx("option",{value:"",children:"All operators"}),Ne.map(t=>e.jsx("option",{value:t,children:t},t))]}),e.jsx(O,{text:"The company that runs the bot or product (e.g., OpenAI, Anthropic, Perplexity). Filtering by operator includes every identity under that company."})]}),e.jsx("select",{"aria-label":"Filter by HTTP status class",value:S,onChange:t=>_(t.target.value),className:"rounded-md border border-zinc-800 bg-zinc-950 px-2.5 py-1.5 text-xs text-zinc-200 focus:outline-none focus-visible:ring-1 focus-visible:ring-zinc-600",children:et.map(t=>e.jsx("option",{value:t.value,children:t.label},t.value))}),e.jsx("select",{"aria-label":"Filter by verification claim",value:k,onChange:t=>G(t.target.value),className:"rounded-md border border-zinc-800 bg-zinc-950 px-2.5 py-1.5 text-xs text-zinc-200 focus:outline-none focus-visible:ring-1 focus-visible:ring-zinc-600",children:fe.map(t=>e.jsx("option",{value:t.value,children:t.label},t.value))}),e.jsx("input",{type:"search","aria-label":"Filter by path",placeholder:"path contains…",value:y,onChange:t=>B(t.target.value),className:"w-44 rounded-md border border-zinc-800 bg-zinc-950 px-2.5 py-1.5 text-xs text-zinc-200 placeholder:text-zinc-600 focus:outline-none focus-visible:ring-1 focus-visible:ring-zinc-600"})]})]}),Ae?e.jsxs("div",{className:"mb-3 flex flex-wrap items-center gap-2",children:[ne?e.jsx(A,{label:`Bucket: ${ne}`,onClear:()=>z(null)}):null,f?e.jsx(A,{label:`Identity: ${f}`,onClear:()=>v("")}):null,m?e.jsx(A,{label:`Operator: ${m}`,onClear:()=>I("")}):null,y.trim()?e.jsx(A,{label:`Path: ${y.trim()}`,onClear:()=>B("")}):null,S!=="all"?e.jsx(A,{label:`Status: ${S}`,onClear:()=>_("all")}):null,k!=="all"?e.jsx(A,{label:`Claim: ${lt(k)}`,onClear:()=>G("all")}):null,e.jsx("button",{type:"button",onClick:Te,className:"text-xs text-zinc-500 underline-offset-4 hover:text-zinc-200 hover:underline",children:"Clear all"})]}):null,e.jsx(dt,{events:we}),ze?e.jsxs("div",{className:"mt-3 flex flex-wrap items-center justify-between gap-x-4 gap-y-2 text-xs text-zinc-400",children:[e.jsxs("p",{className:"tabular-nums",children:["Showing ",e.jsx("span",{className:"text-zinc-300",children:Se.toLocaleString("en-US")}),"–",e.jsx("span",{className:"text-zinc-300",children:ke.toLocaleString("en-US")})," of"," ",e.jsx("span",{className:"text-zinc-300",children:w.length.toLocaleString("en-US")})," events"]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsxs("button",{type:"button",onClick:()=>K(t=>Math.max(1,t-1)),disabled:M<=1,"aria-label":"Previous page",className:"inline-flex items-center gap-1 rounded-md border border-zinc-800 bg-zinc-950 px-2.5 py-1.5 text-zinc-200 transition hover:border-zinc-700 hover:text-zinc-50 disabled:cursor-not-allowed disabled:opacity-40 disabled:hover:border-zinc-800 disabled:hover:text-zinc-200",children:[e.jsx(Ve,{className:"size-3.5"}),"Prev"]}),e.jsxs("span",{className:"tabular-nums",children:["Page ",e.jsx("span",{className:"text-zinc-200",children:M})," of"," ",e.jsx("span",{className:"text-zinc-200",children:F})]}),e.jsxs("button",{type:"button",onClick:()=>K(t=>Math.min(F,t+1)),disabled:M>=F,"aria-label":"Next page",className:"inline-flex items-center gap-1 rounded-md border border-zinc-800 bg-zinc-950 px-2.5 py-1.5 text-zinc-200 transition hover:border-zinc-700 hover:text-zinc-50 disabled:cursor-not-allowed disabled:opacity-40 disabled:hover:border-zinc-800 disabled:hover:text-zinc-200",children:["Next",e.jsx(Fe,{className:"size-3.5"})]})]})]}):null]})]})}function Z(s,a){return{bucket:s,label:a,crawler:0,aiUserFetch:0,aiReferral:0}}function P(s,a){return a==="day"?nt(s):je(s)}function it(s,a,n,r){const x=new Map;for(const l of s){const c=be(l.tsHour,a);let o=x.get(c);switch(o||(o=Z(c,P(c,a)),x.set(c,o)),l.kind){case u.crawler:o.crawler+=l.hits;break;case u["ai-user-fetch"]:o.aiUserFetch+=l.hits;break;case u["ai-referral"]:o.aiReferral+=l.hits;break}}if(n&&r){const l=new Date(n),c=new Date(r);if(a==="day"){const o=new Date(Date.UTC(l.getUTCFullYear(),l.getUTCMonth(),l.getUTCDate())),d=new Date(Date.UTC(c.getUTCFullYear(),c.getUTCMonth(),c.getUTCDate()));for(;o<=d;){const z=o.getUTCFullYear(),f=String(o.getUTCMonth()+1).padStart(2,"0"),v=String(o.getUTCDate()).padStart(2,"0"),m=`${z}-${f}-${v}`;x.has(m)||x.set(m,Z(m,P(m,a))),o.setUTCDate(o.getUTCDate()+1)}}else{const o=new Date(l);for(o.setUTCMinutes(0,0,0);o<=c;){const d=o.toISOString();x.has(d)||x.set(d,Z(d,P(d,a))),o.setUTCHours(o.getUTCHours()+1)}}}return[...x.values()].sort((l,c)=>l.bucket<c.bucket?-1:l.bucket>c.bucket?1:0)}function lt(s){return fe.find(a=>a.value===s)?.label??s}function A({label:s,onClear:a}){return e.jsxs("span",{className:"inline-flex items-center gap-1.5 rounded-full border border-zinc-700 bg-zinc-800/60 px-2.5 py-1 text-[11px] text-zinc-200",children:[s,e.jsx("button",{type:"button",onClick:a,"aria-label":`Clear ${s}`,className:"rounded-full p-0.5 text-zinc-400 hover:bg-zinc-700/60 hover:text-zinc-100",children:e.jsx(He,{className:"size-3"})})]})}function J({label:s,color:a,count:n,active:r,onToggle:x}){return e.jsxs("button",{type:"button",onClick:x,"aria-pressed":r,className:`inline-flex items-center gap-2 rounded-full border px-3 py-1 text-xs font-medium transition ${r?"border-zinc-700 bg-zinc-800/60 text-zinc-100":"border-zinc-800 bg-transparent text-zinc-500 hover:text-zinc-300"}`,children:[e.jsx("span",{"aria-hidden":"true",className:`size-2 rounded-full transition-opacity ${r?"opacity-100":"opacity-30"}`,style:{backgroundColor:a}}),e.jsx("span",{children:s}),e.jsx("span",{className:`tabular-nums ${r?"text-zinc-400":"text-zinc-600"}`,children:n.toLocaleString("en-US")})]})}function ct(s){switch(s){case u.crawler:return"Crawler";case u["ai-user-fetch"]:return"AI hit";case u["ai-referral"]:return"AI referral"}}function ot(s){switch(s.kind){case u.crawler:case u["ai-user-fetch"]:return s.botId;case u["ai-referral"]:return s.product}}function ut(s){switch(s.kind){case u.crawler:case u["ai-user-fetch"]:return`${s.verificationStatus} · HTTP ${s.status}`;case u["ai-referral"]:return`${s.evidenceType} · ${s.sourceDomain}`}}function dt({events:s}){return s.length===0?e.jsx(H,{className:"p-6 text-center text-sm text-zinc-500",children:"No event rows match the current filters."}):e.jsx("div",{className:"rounded-xl border border-zinc-800/60 bg-zinc-900/30 overflow-hidden",children:e.jsxs("table",{className:"w-full text-sm",children:[e.jsx("thead",{className:"bg-zinc-900/50 text-[10px] font-semibold uppercase tracking-wider text-zinc-500",children:e.jsxs("tr",{children:[e.jsx("th",{className:"px-4 py-2 text-left",children:"Hour"}),e.jsx("th",{className:"px-4 py-2 text-left",children:"Kind"}),e.jsx("th",{className:"px-4 py-2 text-left",children:"Identity"}),e.jsx("th",{className:"px-4 py-2 text-left",children:"Evidence / status"}),e.jsx("th",{className:"px-4 py-2 text-left",children:"Path"}),e.jsx("th",{className:"px-4 py-2 text-right",children:e.jsxs("span",{className:"inline-flex items-center",children:["Hits",e.jsx(O,{text:"Each row is one hour-bucket, not one request. Hits is the number of requests in that hour that shared the same identity, path, HTTP status, and verification claim."})]})})]})}),e.jsx("tbody",{className:"divide-y divide-zinc-800/60",children:s.map((a,n)=>e.jsxs("tr",{className:"hover:bg-zinc-900/40 transition-colors",children:[e.jsx("td",{className:"px-4 py-2 font-mono text-xs text-zinc-300",children:je(a.tsHour)}),e.jsx("td",{className:"px-4 py-2 text-zinc-300",children:ct(a.kind)}),e.jsxs("td",{className:"px-4 py-2 text-zinc-100",children:[ot(a),e.jsx("span",{className:"ml-2 text-[11px] text-zinc-500",children:a.operator})]}),e.jsx("td",{className:"px-4 py-2 text-zinc-300",children:ut(a)}),e.jsx("td",{className:"px-4 py-2 truncate font-mono text-xs text-zinc-300",children:ge(a)}),e.jsx("td",{className:"px-4 py-2 text-right tabular-nums text-zinc-100",children:a.hits})]},`${a.kind}:${a.tsHour}:${n}`))})]})})}export{yt as TrafficSourceDetailPage};
|