@ainyc/canonry 4.51.1 → 4.51.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/assets/{BacklinksPage-DIZCcqsP.js → BacklinksPage-9TlM08Wf.js} +1 -1
- package/assets/assets/ProjectPage-CD591qDz.js +6 -0
- package/assets/assets/{RunRow-DqezNIUy.js → RunRow-D7qdWWRl.js} +1 -1
- package/assets/assets/{RunsPage-CfvTJ9Ny.js → RunsPage-CvewepfU.js} +1 -1
- package/assets/assets/{SettingsPage-HfMGIa5v.js → SettingsPage-C7BvAhiB.js} +1 -1
- package/assets/assets/{TrafficPage-DV_Dvpl3.js → TrafficPage-DC3NhFOh.js} +1 -1
- package/assets/assets/TrafficSourceDetailPage-BvtTA6rs.js +1 -0
- package/assets/assets/{arrow-left-DpxpMUNt.js → arrow-left-Agb02DMK.js} +1 -1
- package/assets/assets/index-DTCZ93Ne.js +210 -0
- package/assets/assets/server-traffic-C-0Ndjpw.js +1 -0
- package/assets/assets/{trash-2-CnBiLbiZ.js → trash-2-lkrXVRRm.js} +1 -1
- package/assets/index.html +1 -1
- package/dist/{chunk-2ARCCG5E.js → chunk-FYGBW3SM.js} +4 -0
- package/dist/{chunk-GGXU5VKI.js → chunk-HMZKIOLG.js} +1 -1
- package/dist/{chunk-DLDLDWH4.js → chunk-QZ5XSM6C.js} +34 -1
- package/dist/{chunk-JOKPYAEL.js → chunk-WBO5S3IX.js} +3131 -277
- package/dist/cli.js +40 -8
- package/dist/index.js +4 -4
- package/dist/{intelligence-service-XMZEWLCW.js → intelligence-service-2XL2M7QP.js} +2 -2
- package/dist/mcp.js +2 -2
- package/package.json +11 -11
- package/assets/assets/ProjectPage-R2cxJb5Y.js +0 -6
- package/assets/assets/TrafficSourceDetailPage-lefreKBO.js +0 -1
- package/assets/assets/index-DKBPD33e.js +0 -210
- package/assets/assets/server-traffic-Bm8iKtXK.js +0 -1
|
@@ -2,10 +2,11 @@ import {
|
|
|
2
2
|
ApiClient,
|
|
3
3
|
canonryMcpTools,
|
|
4
4
|
configExists,
|
|
5
|
+
getConfigPath,
|
|
5
6
|
loadConfig,
|
|
6
7
|
loadConfigRaw,
|
|
7
8
|
saveConfigPatch
|
|
8
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-HMZKIOLG.js";
|
|
9
10
|
import {
|
|
10
11
|
DEFAULT_RUN_HISTORY_LIMIT,
|
|
11
12
|
IntelligenceService,
|
|
@@ -82,7 +83,7 @@ import {
|
|
|
82
83
|
smoothedRunDelta,
|
|
83
84
|
trafficSources,
|
|
84
85
|
usageCounters
|
|
85
|
-
} from "./chunk-
|
|
86
|
+
} from "./chunk-QZ5XSM6C.js";
|
|
86
87
|
import {
|
|
87
88
|
AGENT_MEMORY_VALUE_MAX_BYTES,
|
|
88
89
|
AGENT_PROVIDER_IDS,
|
|
@@ -247,6 +248,7 @@ import {
|
|
|
247
248
|
runInProgress,
|
|
248
249
|
runNotCancellable,
|
|
249
250
|
runTriggerRequestSchema,
|
|
251
|
+
runtimeStateMissing,
|
|
250
252
|
schedulableRunKindSchema,
|
|
251
253
|
scheduleDtoSchema,
|
|
252
254
|
scheduleUpsertRequestSchema,
|
|
@@ -282,7 +284,7 @@ import {
|
|
|
282
284
|
wordpressSchemaDeployResultDtoSchema,
|
|
283
285
|
wordpressSchemaStatusResultDtoSchema,
|
|
284
286
|
wordpressStatusDtoSchema
|
|
285
|
-
} from "./chunk-
|
|
287
|
+
} from "./chunk-FYGBW3SM.js";
|
|
286
288
|
|
|
287
289
|
// src/telemetry.ts
|
|
288
290
|
import crypto from "crypto";
|
|
@@ -571,12 +573,15 @@ function checkLatestVersionForServer(opts) {
|
|
|
571
573
|
// src/server.ts
|
|
572
574
|
import { createRequire as createRequire4 } from "module";
|
|
573
575
|
import crypto35 from "crypto";
|
|
574
|
-
import
|
|
576
|
+
import fs15 from "fs";
|
|
575
577
|
import path15 from "path";
|
|
576
578
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
577
579
|
import { eq as eq42 } from "drizzle-orm";
|
|
578
580
|
import Fastify from "fastify";
|
|
579
581
|
|
|
582
|
+
// ../api-routes/src/index.ts
|
|
583
|
+
import fs8 from "fs";
|
|
584
|
+
|
|
580
585
|
// ../api-routes/src/auth.ts
|
|
581
586
|
import crypto2 from "crypto";
|
|
582
587
|
import { eq } from "drizzle-orm";
|
|
@@ -669,9 +674,22 @@ function writeAuditLog(db, entry) {
|
|
|
669
674
|
entityType: entry.entityType,
|
|
670
675
|
entityId: entry.entityId ?? null,
|
|
671
676
|
diff: entry.diff != null ? JSON.stringify(entry.diff) : null,
|
|
677
|
+
userAgent: entry.userAgent ?? null,
|
|
678
|
+
actorSession: entry.actorSession ?? null,
|
|
672
679
|
createdAt: now
|
|
673
680
|
}).run();
|
|
674
681
|
}
|
|
682
|
+
function auditFromRequest(request, entry) {
|
|
683
|
+
const ua = request.headers["user-agent"];
|
|
684
|
+
const userAgent = Array.isArray(ua) ? ua.join(", ") : ua ?? null;
|
|
685
|
+
const sess = request.headers["x-canonry-actor-session"];
|
|
686
|
+
const actorSession = Array.isArray(sess) ? sess.join(", ") : sess ?? null;
|
|
687
|
+
return {
|
|
688
|
+
...entry,
|
|
689
|
+
userAgent: entry.userAgent ?? userAgent,
|
|
690
|
+
actorSession: entry.actorSession ?? actorSession
|
|
691
|
+
};
|
|
692
|
+
}
|
|
675
693
|
function resolveSnapshotMentionResult(snapshot, project) {
|
|
676
694
|
if (snapshot.answerText) {
|
|
677
695
|
const domains = effectiveDomains({
|
|
@@ -1023,6 +1041,12 @@ function aliasArraysEqual(a, b) {
|
|
|
1023
1041
|
// ../api-routes/src/queries.ts
|
|
1024
1042
|
import crypto5 from "crypto";
|
|
1025
1043
|
import { eq as eq4, inArray, sql as sql3 } from "drizzle-orm";
|
|
1044
|
+
function preserveSnapshotQueryText(tx, projectId, queryIds) {
|
|
1045
|
+
const candidates = queryIds && queryIds.length > 0 ? tx.select({ id: queries.id, text: queries.query }).from(queries).where(inArray(queries.id, queryIds)).all() : tx.select({ id: queries.id, text: queries.query }).from(queries).where(eq4(queries.projectId, projectId)).all();
|
|
1046
|
+
for (const q of candidates) {
|
|
1047
|
+
tx.update(querySnapshots).set({ queryText: q.text }).where(eq4(querySnapshots.queryId, q.id)).run();
|
|
1048
|
+
}
|
|
1049
|
+
}
|
|
1026
1050
|
async function queryRoutes(app, opts) {
|
|
1027
1051
|
app.get("/projects/:name/queries", async (request, reply) => {
|
|
1028
1052
|
const project = resolveProject(app.db, request.params.name);
|
|
@@ -1037,6 +1061,7 @@ async function queryRoutes(app, opts) {
|
|
|
1037
1061
|
}
|
|
1038
1062
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
1039
1063
|
app.db.transaction((tx) => {
|
|
1064
|
+
preserveSnapshotQueryText(tx, project.id);
|
|
1040
1065
|
tx.delete(queries).where(eq4(queries.projectId, project.id)).run();
|
|
1041
1066
|
for (const q of body.queries) {
|
|
1042
1067
|
tx.insert(queries).values({
|
|
@@ -1047,13 +1072,13 @@ async function queryRoutes(app, opts) {
|
|
|
1047
1072
|
createdAt: now
|
|
1048
1073
|
}).run();
|
|
1049
1074
|
}
|
|
1050
|
-
writeAuditLog(tx, {
|
|
1075
|
+
writeAuditLog(tx, auditFromRequest(request, {
|
|
1051
1076
|
projectId: project.id,
|
|
1052
1077
|
actor: "api",
|
|
1053
1078
|
action: "queries.replaced",
|
|
1054
1079
|
entityType: "query",
|
|
1055
1080
|
diff: { queries: body.queries }
|
|
1056
|
-
});
|
|
1081
|
+
}));
|
|
1057
1082
|
});
|
|
1058
1083
|
const rows = app.db.select().from(queries).where(eq4(queries.projectId, project.id)).all();
|
|
1059
1084
|
return reply.send(rows.map((r) => ({ id: r.id, query: r.query, createdAt: r.createdAt })));
|
|
@@ -1099,16 +1124,17 @@ async function queryRoutes(app, opts) {
|
|
|
1099
1124
|
const idsToDelete = existing.filter((q) => toDelete.has(q.query)).map((q) => q.id);
|
|
1100
1125
|
if (idsToDelete.length > 0) {
|
|
1101
1126
|
app.db.transaction((tx) => {
|
|
1127
|
+
preserveSnapshotQueryText(tx, project.id, idsToDelete);
|
|
1102
1128
|
for (const id of idsToDelete) {
|
|
1103
1129
|
tx.delete(queries).where(eq4(queries.id, id)).run();
|
|
1104
1130
|
}
|
|
1105
|
-
writeAuditLog(tx, {
|
|
1131
|
+
writeAuditLog(tx, auditFromRequest(request, {
|
|
1106
1132
|
projectId: project.id,
|
|
1107
1133
|
actor: "api",
|
|
1108
1134
|
action: "queries.deleted",
|
|
1109
1135
|
entityType: "query",
|
|
1110
1136
|
diff: { deleted: body.queries.filter((q) => existing.some((e) => e.query === q)) }
|
|
1111
|
-
});
|
|
1137
|
+
}));
|
|
1112
1138
|
});
|
|
1113
1139
|
}
|
|
1114
1140
|
const rows = app.db.select().from(queries).where(eq4(queries.projectId, project.id)).all();
|
|
@@ -1138,13 +1164,13 @@ async function queryRoutes(app, opts) {
|
|
|
1138
1164
|
}
|
|
1139
1165
|
}
|
|
1140
1166
|
if (added.length > 0) {
|
|
1141
|
-
writeAuditLog(app.db, {
|
|
1167
|
+
writeAuditLog(app.db, auditFromRequest(request, {
|
|
1142
1168
|
projectId: project.id,
|
|
1143
1169
|
actor: "api",
|
|
1144
1170
|
action: "queries.appended",
|
|
1145
1171
|
entityType: "query",
|
|
1146
1172
|
diff: { added }
|
|
1147
|
-
});
|
|
1173
|
+
}));
|
|
1148
1174
|
}
|
|
1149
1175
|
const rows = app.db.select().from(queries).where(eq4(queries.projectId, project.id)).all();
|
|
1150
1176
|
return reply.send(rows.map((r) => ({ id: r.id, query: r.query, createdAt: r.createdAt })));
|
|
@@ -1202,6 +1228,7 @@ async function queryRoutes(app, opts) {
|
|
|
1202
1228
|
}
|
|
1203
1229
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
1204
1230
|
app.db.transaction((tx) => {
|
|
1231
|
+
preserveSnapshotQueryText(tx, project.id);
|
|
1205
1232
|
tx.delete(queries).where(eq4(queries.projectId, project.id)).run();
|
|
1206
1233
|
for (const keyword of body.keywords) {
|
|
1207
1234
|
tx.insert(queries).values({
|
|
@@ -1212,13 +1239,13 @@ async function queryRoutes(app, opts) {
|
|
|
1212
1239
|
createdAt: now
|
|
1213
1240
|
}).run();
|
|
1214
1241
|
}
|
|
1215
|
-
writeAuditLog(tx, {
|
|
1242
|
+
writeAuditLog(tx, auditFromRequest(request, {
|
|
1216
1243
|
projectId: project.id,
|
|
1217
1244
|
actor: "api",
|
|
1218
1245
|
action: "queries.replaced",
|
|
1219
1246
|
entityType: "query",
|
|
1220
1247
|
diff: { queries: body.keywords }
|
|
1221
|
-
});
|
|
1248
|
+
}));
|
|
1222
1249
|
});
|
|
1223
1250
|
const rows = app.db.select().from(queries).where(eq4(queries.projectId, project.id)).all();
|
|
1224
1251
|
return reply.send(rows.map((r) => ({ id: r.id, keyword: r.query, createdAt: r.createdAt })));
|
|
@@ -1234,16 +1261,17 @@ async function queryRoutes(app, opts) {
|
|
|
1234
1261
|
const idsToDelete = existing.filter((q) => toDelete.has(q.query)).map((q) => q.id);
|
|
1235
1262
|
if (idsToDelete.length > 0) {
|
|
1236
1263
|
app.db.transaction((tx) => {
|
|
1264
|
+
preserveSnapshotQueryText(tx, project.id, idsToDelete);
|
|
1237
1265
|
for (const id of idsToDelete) {
|
|
1238
1266
|
tx.delete(queries).where(eq4(queries.id, id)).run();
|
|
1239
1267
|
}
|
|
1240
|
-
writeAuditLog(tx, {
|
|
1268
|
+
writeAuditLog(tx, auditFromRequest(request, {
|
|
1241
1269
|
projectId: project.id,
|
|
1242
1270
|
actor: "api",
|
|
1243
1271
|
action: "queries.deleted",
|
|
1244
1272
|
entityType: "query",
|
|
1245
1273
|
diff: { deleted: body.keywords.filter((keyword) => existing.some((e) => e.query === keyword)) }
|
|
1246
|
-
});
|
|
1274
|
+
}));
|
|
1247
1275
|
});
|
|
1248
1276
|
}
|
|
1249
1277
|
const rows = app.db.select().from(queries).where(eq4(queries.projectId, project.id)).all();
|
|
@@ -1273,13 +1301,13 @@ async function queryRoutes(app, opts) {
|
|
|
1273
1301
|
}
|
|
1274
1302
|
}
|
|
1275
1303
|
if (added.length > 0) {
|
|
1276
|
-
writeAuditLog(app.db, {
|
|
1304
|
+
writeAuditLog(app.db, auditFromRequest(request, {
|
|
1277
1305
|
projectId: project.id,
|
|
1278
1306
|
actor: "api",
|
|
1279
1307
|
action: "queries.appended",
|
|
1280
1308
|
entityType: "query",
|
|
1281
1309
|
diff: { added }
|
|
1282
|
-
});
|
|
1310
|
+
}));
|
|
1283
1311
|
}
|
|
1284
1312
|
const rows = app.db.select().from(queries).where(eq4(queries.projectId, project.id)).all();
|
|
1285
1313
|
return reply.send(rows.map((r) => ({ id: r.id, keyword: r.query, createdAt: r.createdAt })));
|
|
@@ -1639,8 +1667,10 @@ async function runRoutes(app, opts) {
|
|
|
1639
1667
|
const limit = parseListLimit(request.query.limit, 500, 5e3);
|
|
1640
1668
|
const since = parseListSince(request.query.since);
|
|
1641
1669
|
const includeProbe = request.query.includeProbe === "1" || request.query.includeProbe === "true";
|
|
1670
|
+
const kind = parseListKind(request.query.kind);
|
|
1642
1671
|
const filters = [gte(runs.createdAt, since)];
|
|
1643
1672
|
if (!includeProbe) filters.push(notProbeRun());
|
|
1673
|
+
if (kind) filters.push(eq7(runs.kind, kind));
|
|
1644
1674
|
const rows = app.db.select().from(runs).where(and2(...filters)).orderBy(desc(runs.createdAt), desc(runs.id)).limit(limit).all();
|
|
1645
1675
|
return reply.send(rows.map(formatRun));
|
|
1646
1676
|
});
|
|
@@ -1749,6 +1779,14 @@ function parseListLimit(raw, defaultValue, max) {
|
|
|
1749
1779
|
}
|
|
1750
1780
|
return Math.min(parsed, max);
|
|
1751
1781
|
}
|
|
1782
|
+
function parseListKind(raw) {
|
|
1783
|
+
if (raw === void 0 || raw === "") return null;
|
|
1784
|
+
const validKinds = Object.values(RunKinds);
|
|
1785
|
+
if (!validKinds.includes(raw)) {
|
|
1786
|
+
throw validationError(`"kind" must be one of: ${validKinds.join(", ")}`);
|
|
1787
|
+
}
|
|
1788
|
+
return raw;
|
|
1789
|
+
}
|
|
1752
1790
|
function parseListSince(raw) {
|
|
1753
1791
|
if (raw === void 0) {
|
|
1754
1792
|
const thirtyDaysAgo = new Date(Date.now() - 30 * 24 * 60 * 60 * 1e3);
|
|
@@ -2495,9 +2533,24 @@ async function historyRoutes(app) {
|
|
|
2495
2533
|
...snapshot,
|
|
2496
2534
|
answerMentioned: resolveSnapshotAnswerMentioned(snapshot, project)
|
|
2497
2535
|
}));
|
|
2536
|
+
const queryByText = /* @__PURE__ */ new Map();
|
|
2537
|
+
for (const q of projectQueries) queryByText.set(q.query, q);
|
|
2538
|
+
function resolveSnapQueryId(snap) {
|
|
2539
|
+
if (snap.queryId) return snap.queryId;
|
|
2540
|
+
if (snap.queryText) {
|
|
2541
|
+
const match = queryByText.get(snap.queryText);
|
|
2542
|
+
if (match) return match.id;
|
|
2543
|
+
}
|
|
2544
|
+
return null;
|
|
2545
|
+
}
|
|
2546
|
+
const allSnapshotsResolved = allSnapshots.map((s) => ({
|
|
2547
|
+
...s,
|
|
2548
|
+
resolvedQueryId: resolveSnapQueryId(s)
|
|
2549
|
+
}));
|
|
2498
2550
|
const deduped = /* @__PURE__ */ new Map();
|
|
2499
|
-
for (const snap of
|
|
2500
|
-
|
|
2551
|
+
for (const snap of allSnapshotsResolved) {
|
|
2552
|
+
if (!snap.resolvedQueryId) continue;
|
|
2553
|
+
const key = `${snap.runId}:${snap.resolvedQueryId}`;
|
|
2501
2554
|
const existing = deduped.get(key);
|
|
2502
2555
|
if (!existing || !existing.answerMentioned && snap.answerMentioned || existing.answerMentioned === snap.answerMentioned && snap.citationState === CitationStates.cited) {
|
|
2503
2556
|
deduped.set(key, snap);
|
|
@@ -2505,15 +2558,17 @@ async function historyRoutes(app) {
|
|
|
2505
2558
|
}
|
|
2506
2559
|
const dedupedSnapshots = [...deduped.values()];
|
|
2507
2560
|
const rawByQueryProvider = /* @__PURE__ */ new Map();
|
|
2508
|
-
for (const snap of
|
|
2509
|
-
|
|
2561
|
+
for (const snap of allSnapshotsResolved) {
|
|
2562
|
+
if (!snap.resolvedQueryId) continue;
|
|
2563
|
+
const key = `${snap.resolvedQueryId}::${snap.provider}`;
|
|
2510
2564
|
const arr = rawByQueryProvider.get(key);
|
|
2511
2565
|
if (arr) arr.push(snap);
|
|
2512
2566
|
else rawByQueryProvider.set(key, [snap]);
|
|
2513
2567
|
}
|
|
2514
2568
|
const rawByQueryModel = /* @__PURE__ */ new Map();
|
|
2515
|
-
for (const snap of
|
|
2516
|
-
|
|
2569
|
+
for (const snap of allSnapshotsResolved) {
|
|
2570
|
+
if (!snap.resolvedQueryId) continue;
|
|
2571
|
+
const key = `${snap.resolvedQueryId}::${snap.provider}:${snap.model ?? "unknown"}`;
|
|
2517
2572
|
const arr = rawByQueryModel.get(key);
|
|
2518
2573
|
if (arr) arr.push(snap);
|
|
2519
2574
|
else rawByQueryModel.set(key, [snap]);
|
|
@@ -2560,7 +2615,7 @@ async function historyRoutes(app) {
|
|
|
2560
2615
|
});
|
|
2561
2616
|
}
|
|
2562
2617
|
const timeline = projectQueries.map((q) => {
|
|
2563
|
-
const qSnapshots = dedupedSnapshots.filter((s) => s.
|
|
2618
|
+
const qSnapshots = dedupedSnapshots.filter((s) => s.resolvedQueryId === q.id).sort((a, b) => a.createdAt.localeCompare(b.createdAt));
|
|
2564
2619
|
const runEntries = computeTransitions(qSnapshots);
|
|
2565
2620
|
const providerRuns = {};
|
|
2566
2621
|
const providerKeys = [...rawByQueryProvider.keys()].filter((k) => k.startsWith(`${q.id}::`));
|
|
@@ -8387,6 +8442,39 @@ var scheduleKindQueryParameter = {
|
|
|
8387
8442
|
description: 'Schedulable run kind. Defaults to "answer-visibility" for backward compatibility.',
|
|
8388
8443
|
schema: { type: "string", enum: ["answer-visibility", "traffic-sync"] }
|
|
8389
8444
|
};
|
|
8445
|
+
var runsListKindQueryParameter = {
|
|
8446
|
+
name: "kind",
|
|
8447
|
+
in: "query",
|
|
8448
|
+
description: "Restrict results to a single run kind. Without this filter, integration syncs (bing-inspect, gsc-sync, ga-sync) can fill the default 500-row cap within minutes on busy projects and push answer-visibility runs out of the response.",
|
|
8449
|
+
schema: {
|
|
8450
|
+
type: "string",
|
|
8451
|
+
enum: [
|
|
8452
|
+
"answer-visibility",
|
|
8453
|
+
"site-audit",
|
|
8454
|
+
"gsc-sync",
|
|
8455
|
+
"inspect-sitemap",
|
|
8456
|
+
"ga-sync",
|
|
8457
|
+
"bing-inspect",
|
|
8458
|
+
"bing-inspect-sitemap",
|
|
8459
|
+
"backlink-extract",
|
|
8460
|
+
"traffic-sync",
|
|
8461
|
+
"aeo-discover-seed",
|
|
8462
|
+
"aeo-discover-probe"
|
|
8463
|
+
]
|
|
8464
|
+
}
|
|
8465
|
+
};
|
|
8466
|
+
var runsListSinceQueryParameter = {
|
|
8467
|
+
name: "since",
|
|
8468
|
+
in: "query",
|
|
8469
|
+
description: "Only return runs with created_at >= this ISO 8601 timestamp. Defaults to 30 days ago.",
|
|
8470
|
+
schema: stringSchema
|
|
8471
|
+
};
|
|
8472
|
+
var runsListIncludeProbeQueryParameter = {
|
|
8473
|
+
name: "includeProbe",
|
|
8474
|
+
in: "query",
|
|
8475
|
+
description: 'Set to "1" or "true" to include probe runs. Probes are excluded by default because they are operator/agent test runs and must not pollute dashboard aggregates.',
|
|
8476
|
+
schema: stringSchema
|
|
8477
|
+
};
|
|
8390
8478
|
var reportAudienceQueryParameter = {
|
|
8391
8479
|
name: "audience",
|
|
8392
8480
|
in: "query",
|
|
@@ -8970,6 +9058,12 @@ var routeCatalog = [
|
|
|
8970
9058
|
path: "/api/v1/runs",
|
|
8971
9059
|
summary: "List all runs",
|
|
8972
9060
|
tags: ["runs"],
|
|
9061
|
+
parameters: [
|
|
9062
|
+
limitQueryParameter,
|
|
9063
|
+
runsListSinceQueryParameter,
|
|
9064
|
+
runsListIncludeProbeQueryParameter,
|
|
9065
|
+
runsListKindQueryParameter
|
|
9066
|
+
],
|
|
8973
9067
|
responses: {
|
|
8974
9068
|
200: jsonArrayResponse("Runs returned.", "RunDto")
|
|
8975
9069
|
}
|
|
@@ -17504,7 +17598,7 @@ async function queryBacklinks(opts) {
|
|
|
17504
17598
|
const reversed = opts.targets.map(reverseDomain);
|
|
17505
17599
|
const targetList = reversed.map(quote).join(", ");
|
|
17506
17600
|
const limitClause = opts.limitPerTarget ? `QUALIFY row_number() OVER (PARTITION BY t.target_rev_domain ORDER BY v.num_hosts DESC) <= ${Math.floor(opts.limitPerTarget)}` : "";
|
|
17507
|
-
const
|
|
17601
|
+
const sql17 = `
|
|
17508
17602
|
WITH vertices AS (
|
|
17509
17603
|
SELECT * FROM read_csv(
|
|
17510
17604
|
${quote(opts.vertexPath)},
|
|
@@ -17540,7 +17634,7 @@ async function queryBacklinks(opts) {
|
|
|
17540
17634
|
const conn = await instance.connect();
|
|
17541
17635
|
let rows;
|
|
17542
17636
|
try {
|
|
17543
|
-
const reader = await conn.runAndReadAll(
|
|
17637
|
+
const reader = await conn.runAndReadAll(sql17);
|
|
17544
17638
|
rows = reader.getRowObjects();
|
|
17545
17639
|
} finally {
|
|
17546
17640
|
conn.disconnectSync?.();
|
|
@@ -18212,217 +18306,2472 @@ async function listCloudRunTrafficEvents(accessToken, options) {
|
|
|
18212
18306
|
};
|
|
18213
18307
|
}
|
|
18214
18308
|
|
|
18215
|
-
// ../integration-traffic/src/
|
|
18216
|
-
var
|
|
18217
|
-
|
|
18218
|
-
|
|
18219
|
-
|
|
18220
|
-
|
|
18221
|
-
|
|
18222
|
-
|
|
18223
|
-
|
|
18224
|
-
|
|
18225
|
-
|
|
18226
|
-
id: "openai-searchbot",
|
|
18227
|
-
operator: "OpenAI",
|
|
18228
|
-
product: "OAI-SearchBot",
|
|
18229
|
-
purpose: "search",
|
|
18230
|
-
userAgentPatterns: [/OAI-SearchBot\//i]
|
|
18231
|
-
},
|
|
18232
|
-
{
|
|
18233
|
-
id: "openai-chatgpt-user",
|
|
18234
|
-
operator: "OpenAI",
|
|
18235
|
-
product: "ChatGPT-User",
|
|
18236
|
-
purpose: "user-agent",
|
|
18237
|
-
userAgentPatterns: [/ChatGPT-User\//i]
|
|
18238
|
-
},
|
|
18239
|
-
{
|
|
18240
|
-
id: "anthropic-claudebot",
|
|
18241
|
-
operator: "Anthropic",
|
|
18242
|
-
product: "ClaudeBot",
|
|
18243
|
-
purpose: "training",
|
|
18244
|
-
userAgentPatterns: [/ClaudeBot\//i, /Claude-Web\//i, /anthropic-ai/i]
|
|
18245
|
-
},
|
|
18246
|
-
{
|
|
18247
|
-
id: "perplexity-bot",
|
|
18248
|
-
operator: "Perplexity",
|
|
18249
|
-
product: "PerplexityBot",
|
|
18250
|
-
purpose: "search",
|
|
18251
|
-
userAgentPatterns: [/PerplexityBot\//i]
|
|
18252
|
-
},
|
|
18253
|
-
{
|
|
18254
|
-
id: "google-extended",
|
|
18255
|
-
operator: "Google",
|
|
18256
|
-
product: "Google-Extended",
|
|
18257
|
-
purpose: "training-control",
|
|
18258
|
-
userAgentPatterns: [/Google-Extended/i]
|
|
18259
|
-
},
|
|
18260
|
-
{
|
|
18261
|
-
id: "bytespider",
|
|
18262
|
-
operator: "ByteDance",
|
|
18263
|
-
product: "Bytespider",
|
|
18264
|
-
purpose: "training",
|
|
18265
|
-
userAgentPatterns: [/Bytespider/i]
|
|
18266
|
-
},
|
|
18267
|
-
{
|
|
18268
|
-
id: "applebot-extended",
|
|
18269
|
-
operator: "Apple",
|
|
18270
|
-
product: "Applebot-Extended",
|
|
18271
|
-
purpose: "training",
|
|
18272
|
-
userAgentPatterns: [/Applebot-Extended/i]
|
|
18273
|
-
},
|
|
18274
|
-
{
|
|
18275
|
-
id: "meta-externalagent",
|
|
18276
|
-
operator: "Meta",
|
|
18277
|
-
product: "meta-externalagent",
|
|
18278
|
-
purpose: "training",
|
|
18279
|
-
userAgentPatterns: [/meta-externalagent/i]
|
|
18280
|
-
},
|
|
18281
|
-
{
|
|
18282
|
-
id: "ccbot",
|
|
18283
|
-
operator: "Common Crawl",
|
|
18284
|
-
product: "CCBot",
|
|
18285
|
-
purpose: "crawl",
|
|
18286
|
-
userAgentPatterns: [/CCBot\//i]
|
|
18287
|
-
},
|
|
18288
|
-
{
|
|
18289
|
-
id: "cohere-ai",
|
|
18290
|
-
operator: "Cohere",
|
|
18291
|
-
product: "cohere-ai",
|
|
18292
|
-
purpose: "training",
|
|
18293
|
-
userAgentPatterns: [/cohere-ai/i]
|
|
18294
|
-
},
|
|
18295
|
-
{
|
|
18296
|
-
id: "diffbot",
|
|
18297
|
-
operator: "Diffbot",
|
|
18298
|
-
product: "Diffbot",
|
|
18299
|
-
purpose: "crawl",
|
|
18300
|
-
userAgentPatterns: [/Diffbot/i]
|
|
18301
|
-
},
|
|
18302
|
-
{
|
|
18303
|
-
id: "mistral-ai",
|
|
18304
|
-
operator: "Mistral AI",
|
|
18305
|
-
product: "MistralAI-User",
|
|
18306
|
-
purpose: "crawl",
|
|
18307
|
-
userAgentPatterns: [/MistralAI/i]
|
|
18308
|
-
}
|
|
18309
|
-
];
|
|
18310
|
-
var DEFAULT_AI_REFERRER_RULES = [
|
|
18311
|
-
{ domain: AI_ENGINE_DOMAINS.chatgpt, operator: "OpenAI", product: "ChatGPT" },
|
|
18312
|
-
{ domain: LEGACY_CHATGPT_DOMAIN, operator: "OpenAI", product: "ChatGPT" },
|
|
18313
|
-
{ domain: AI_ENGINE_DOMAINS.perplexity, operator: "Perplexity", product: "Perplexity" },
|
|
18314
|
-
{ domain: AI_ENGINE_DOMAINS.claude, operator: "Anthropic", product: "Claude" },
|
|
18315
|
-
{ domain: AI_ENGINE_DOMAINS.gemini, operator: "Google", product: "Gemini" },
|
|
18316
|
-
{ domain: AI_ENGINE_DOMAINS.copilotMicrosoft, operator: "Microsoft", product: "Copilot" },
|
|
18317
|
-
{ domain: AI_ENGINE_DOMAINS.phind, operator: "Phind", product: "Phind" },
|
|
18318
|
-
{ domain: AI_ENGINE_DOMAINS.you, operator: "You.com", product: "You.com" },
|
|
18319
|
-
{ domain: AI_ENGINE_DOMAINS.metaAi, operator: "Meta", product: "Meta AI" }
|
|
18320
|
-
];
|
|
18321
|
-
|
|
18322
|
-
// ../integration-traffic/src/classifier.ts
|
|
18323
|
-
function normalizeHost(host) {
|
|
18324
|
-
return host.trim().toLowerCase().replace(/^www\./, "");
|
|
18325
|
-
}
|
|
18326
|
-
function hostMatches(host, domain) {
|
|
18327
|
-
const normalizedHost = normalizeHost(host);
|
|
18328
|
-
const normalizedDomain = normalizeHost(domain);
|
|
18329
|
-
return normalizedHost === normalizedDomain || normalizedHost.endsWith(`.${normalizedDomain}`);
|
|
18330
|
-
}
|
|
18331
|
-
function utmTokenMatchesDomain(utmSource, domain) {
|
|
18332
|
-
if (hostMatches(utmSource, domain)) return true;
|
|
18333
|
-
const normalizedUtm = normalizeHost(utmSource);
|
|
18334
|
-
const firstLabel = normalizeHost(domain).split(".")[0];
|
|
18335
|
-
return Boolean(firstLabel) && normalizedUtm === firstLabel;
|
|
18336
|
-
}
|
|
18337
|
-
function hostFromUrl(value) {
|
|
18338
|
-
if (!value) return null;
|
|
18339
|
-
try {
|
|
18340
|
-
return normalizeHost(new URL(value).hostname);
|
|
18341
|
-
} catch {
|
|
18342
|
-
return null;
|
|
18343
|
-
}
|
|
18344
|
-
}
|
|
18345
|
-
function utmSourceFromQuery(queryString) {
|
|
18346
|
-
if (!queryString) return null;
|
|
18347
|
-
const params = new URLSearchParams(queryString);
|
|
18348
|
-
const source = params.get("utm_source");
|
|
18349
|
-
return source ? normalizeHost(source) : null;
|
|
18350
|
-
}
|
|
18351
|
-
function utmSourceFromUrl(value) {
|
|
18352
|
-
if (!value) return null;
|
|
18353
|
-
try {
|
|
18354
|
-
return utmSourceFromQuery(new URL(value).search.replace(/^\?/, ""));
|
|
18355
|
-
} catch {
|
|
18356
|
-
return null;
|
|
18357
|
-
}
|
|
18358
|
-
}
|
|
18359
|
-
function classifyCrawler(event) {
|
|
18360
|
-
const userAgent = event.userAgent?.trim();
|
|
18361
|
-
if (!userAgent) return null;
|
|
18362
|
-
for (const rule of DEFAULT_AI_CRAWLER_RULES) {
|
|
18363
|
-
if (rule.userAgentPatterns.some((pattern) => pattern.test(userAgent))) {
|
|
18364
|
-
return {
|
|
18365
|
-
botId: rule.id,
|
|
18366
|
-
operator: rule.operator,
|
|
18367
|
-
product: rule.product,
|
|
18368
|
-
purpose: rule.purpose,
|
|
18369
|
-
verificationStatus: "claimed_unverified",
|
|
18370
|
-
matchedUserAgent: userAgent
|
|
18371
|
-
};
|
|
18372
|
-
}
|
|
18373
|
-
}
|
|
18374
|
-
return null;
|
|
18375
|
-
}
|
|
18376
|
-
function classifyAiReferral(event) {
|
|
18377
|
-
const refererHost = hostFromUrl(event.referer);
|
|
18378
|
-
if (refererHost) {
|
|
18379
|
-
const rule = DEFAULT_AI_REFERRER_RULES.find((candidate) => hostMatches(refererHost, candidate.domain));
|
|
18380
|
-
if (rule) {
|
|
18381
|
-
return {
|
|
18382
|
-
operator: rule.operator,
|
|
18383
|
-
product: rule.product,
|
|
18384
|
-
sourceDomain: refererHost,
|
|
18385
|
-
evidenceType: "referer"
|
|
18386
|
-
};
|
|
18387
|
-
}
|
|
18388
|
-
}
|
|
18389
|
-
const utmSource = utmSourceFromQuery(event.queryString);
|
|
18390
|
-
if (utmSource) {
|
|
18391
|
-
const rule = DEFAULT_AI_REFERRER_RULES.find((candidate) => utmTokenMatchesDomain(utmSource, candidate.domain));
|
|
18392
|
-
if (rule) {
|
|
18393
|
-
return {
|
|
18394
|
-
operator: rule.operator,
|
|
18395
|
-
product: rule.product,
|
|
18396
|
-
sourceDomain: utmSource,
|
|
18397
|
-
evidenceType: "utm"
|
|
18398
|
-
};
|
|
18399
|
-
}
|
|
18400
|
-
}
|
|
18401
|
-
const refererUtmSource = utmSourceFromUrl(event.referer);
|
|
18402
|
-
if (refererUtmSource) {
|
|
18403
|
-
const rule = DEFAULT_AI_REFERRER_RULES.find((candidate) => utmTokenMatchesDomain(refererUtmSource, candidate.domain));
|
|
18404
|
-
if (rule) {
|
|
18405
|
-
return {
|
|
18406
|
-
operator: rule.operator,
|
|
18407
|
-
product: rule.product,
|
|
18408
|
-
sourceDomain: refererUtmSource,
|
|
18409
|
-
evidenceType: "referer-utm"
|
|
18410
|
-
};
|
|
18411
|
-
}
|
|
18412
|
-
}
|
|
18413
|
-
return null;
|
|
18414
|
-
}
|
|
18309
|
+
// ../integration-traffic/src/ip-ranges/anthropic.json
|
|
18310
|
+
var anthropic_default = {
|
|
18311
|
+
_source: "ARIN RDAP \u2014 every network registered to Anthropic, PBC (handle AP-2440)",
|
|
18312
|
+
_query: "https://rdap.arin.net/registry/entity/AP-2440",
|
|
18313
|
+
_notes: "Anthropic does not publish a clean machine-readable IP-range JSON like Google or OpenAI do. These prefixes are taken straight from ARIN's authoritative allocation records (NOT bgp.tools' AS-based view, which can include misleading announcements \u2014 e.g. AS60808 is registered to Anthropic but announces 209.249.57.0/24 which actually belongs to Mitel Networks). 216.73.216.0/22 (AWS-ANTHROPIC) is the load-bearing prefix \u2014 empirical Cloud Run logs show 100% of real ClaudeBot traffic comes from there; the other two are Anthropic's own allocations for non-crawler infra (kept since the verification gate still requires a Claude-* UA match). Refresh by re-running the ARIN RDAP query above and replacing the prefix list.",
|
|
18314
|
+
prefixes: [
|
|
18315
|
+
{ ipv4Prefix: "216.73.216.0/22" },
|
|
18316
|
+
{ ipv4Prefix: "160.79.104.0/21" },
|
|
18317
|
+
{ ipv6Prefix: "2607:6bc0::/32" }
|
|
18318
|
+
]
|
|
18319
|
+
};
|
|
18415
18320
|
|
|
18416
|
-
// ../integration-traffic/src/
|
|
18417
|
-
var
|
|
18418
|
-
|
|
18419
|
-
|
|
18420
|
-
|
|
18421
|
-
|
|
18422
|
-
|
|
18423
|
-
|
|
18424
|
-
|
|
18425
|
-
|
|
18321
|
+
// ../integration-traffic/src/ip-ranges/bingbot.json
|
|
18322
|
+
var bingbot_default = {
|
|
18323
|
+
_source: "https://www.bing.com/toolbox/bingbot.json",
|
|
18324
|
+
creationTime: "2024-01-03T10:00:00.121331",
|
|
18325
|
+
prefixes: [
|
|
18326
|
+
{
|
|
18327
|
+
ipv4Prefix: "157.55.39.0/24"
|
|
18328
|
+
},
|
|
18329
|
+
{
|
|
18330
|
+
ipv4Prefix: "207.46.13.0/24"
|
|
18331
|
+
},
|
|
18332
|
+
{
|
|
18333
|
+
ipv4Prefix: "40.77.167.0/24"
|
|
18334
|
+
},
|
|
18335
|
+
{
|
|
18336
|
+
ipv4Prefix: "13.66.139.0/24"
|
|
18337
|
+
},
|
|
18338
|
+
{
|
|
18339
|
+
ipv4Prefix: "13.66.144.0/24"
|
|
18340
|
+
},
|
|
18341
|
+
{
|
|
18342
|
+
ipv4Prefix: "52.167.144.0/24"
|
|
18343
|
+
},
|
|
18344
|
+
{
|
|
18345
|
+
ipv4Prefix: "13.67.10.16/28"
|
|
18346
|
+
},
|
|
18347
|
+
{
|
|
18348
|
+
ipv4Prefix: "13.69.66.240/28"
|
|
18349
|
+
},
|
|
18350
|
+
{
|
|
18351
|
+
ipv4Prefix: "13.71.172.224/28"
|
|
18352
|
+
},
|
|
18353
|
+
{
|
|
18354
|
+
ipv4Prefix: "139.217.52.0/28"
|
|
18355
|
+
},
|
|
18356
|
+
{
|
|
18357
|
+
ipv4Prefix: "191.233.204.224/28"
|
|
18358
|
+
},
|
|
18359
|
+
{
|
|
18360
|
+
ipv4Prefix: "20.36.108.32/28"
|
|
18361
|
+
},
|
|
18362
|
+
{
|
|
18363
|
+
ipv4Prefix: "20.43.120.16/28"
|
|
18364
|
+
},
|
|
18365
|
+
{
|
|
18366
|
+
ipv4Prefix: "40.79.131.208/28"
|
|
18367
|
+
},
|
|
18368
|
+
{
|
|
18369
|
+
ipv4Prefix: "40.79.186.176/28"
|
|
18370
|
+
},
|
|
18371
|
+
{
|
|
18372
|
+
ipv4Prefix: "52.231.148.0/28"
|
|
18373
|
+
},
|
|
18374
|
+
{
|
|
18375
|
+
ipv4Prefix: "20.79.107.240/28"
|
|
18376
|
+
},
|
|
18377
|
+
{
|
|
18378
|
+
ipv4Prefix: "51.105.67.0/28"
|
|
18379
|
+
},
|
|
18380
|
+
{
|
|
18381
|
+
ipv4Prefix: "20.125.163.80/28"
|
|
18382
|
+
},
|
|
18383
|
+
{
|
|
18384
|
+
ipv4Prefix: "40.77.188.0/22"
|
|
18385
|
+
},
|
|
18386
|
+
{
|
|
18387
|
+
ipv4Prefix: "65.55.210.0/24"
|
|
18388
|
+
},
|
|
18389
|
+
{
|
|
18390
|
+
ipv4Prefix: "199.30.24.0/23"
|
|
18391
|
+
},
|
|
18392
|
+
{
|
|
18393
|
+
ipv4Prefix: "40.77.202.0/24"
|
|
18394
|
+
},
|
|
18395
|
+
{
|
|
18396
|
+
ipv4Prefix: "40.77.139.0/25"
|
|
18397
|
+
},
|
|
18398
|
+
{
|
|
18399
|
+
ipv4Prefix: "20.74.197.0/28"
|
|
18400
|
+
},
|
|
18401
|
+
{
|
|
18402
|
+
ipv4Prefix: "20.15.133.160/27"
|
|
18403
|
+
},
|
|
18404
|
+
{
|
|
18405
|
+
ipv4Prefix: "40.77.177.0/24"
|
|
18406
|
+
},
|
|
18407
|
+
{
|
|
18408
|
+
ipv4Prefix: "40.77.178.0/23"
|
|
18409
|
+
}
|
|
18410
|
+
]
|
|
18411
|
+
};
|
|
18412
|
+
|
|
18413
|
+
// ../integration-traffic/src/ip-ranges/chatgpt-user.json
|
|
18414
|
+
var chatgpt_user_default = {
|
|
18415
|
+
_source: "https://openai.com/chatgpt-user.json",
|
|
18416
|
+
creationTime: "2026-05-17T23:03:25.747192",
|
|
18417
|
+
prefixes: [
|
|
18418
|
+
{
|
|
18419
|
+
ipv4Prefix: "104.210.139.192/28"
|
|
18420
|
+
},
|
|
18421
|
+
{
|
|
18422
|
+
ipv4Prefix: "104.210.139.224/28"
|
|
18423
|
+
},
|
|
18424
|
+
{
|
|
18425
|
+
ipv4Prefix: "13.65.138.112/28"
|
|
18426
|
+
},
|
|
18427
|
+
{
|
|
18428
|
+
ipv4Prefix: "13.65.138.96/28"
|
|
18429
|
+
},
|
|
18430
|
+
{
|
|
18431
|
+
ipv4Prefix: "13.67.72.16/28"
|
|
18432
|
+
},
|
|
18433
|
+
{
|
|
18434
|
+
ipv4Prefix: "13.70.107.160/28"
|
|
18435
|
+
},
|
|
18436
|
+
{
|
|
18437
|
+
ipv4Prefix: "13.71.2.208/28"
|
|
18438
|
+
},
|
|
18439
|
+
{
|
|
18440
|
+
ipv4Prefix: "13.76.115.224/28"
|
|
18441
|
+
},
|
|
18442
|
+
{
|
|
18443
|
+
ipv4Prefix: "13.76.115.240/28"
|
|
18444
|
+
},
|
|
18445
|
+
{
|
|
18446
|
+
ipv4Prefix: "13.76.116.80/28"
|
|
18447
|
+
},
|
|
18448
|
+
{
|
|
18449
|
+
ipv4Prefix: "13.76.32.208/28"
|
|
18450
|
+
},
|
|
18451
|
+
{
|
|
18452
|
+
ipv4Prefix: "13.83.167.128/28"
|
|
18453
|
+
},
|
|
18454
|
+
{
|
|
18455
|
+
ipv4Prefix: "13.83.237.176/28"
|
|
18456
|
+
},
|
|
18457
|
+
{
|
|
18458
|
+
ipv4Prefix: "132.196.82.48/28"
|
|
18459
|
+
},
|
|
18460
|
+
{
|
|
18461
|
+
ipv4Prefix: "135.119.134.128/28"
|
|
18462
|
+
},
|
|
18463
|
+
{
|
|
18464
|
+
ipv4Prefix: "135.119.134.192/28"
|
|
18465
|
+
},
|
|
18466
|
+
{
|
|
18467
|
+
ipv4Prefix: "135.220.73.208/28"
|
|
18468
|
+
},
|
|
18469
|
+
{
|
|
18470
|
+
ipv4Prefix: "135.220.73.240/28"
|
|
18471
|
+
},
|
|
18472
|
+
{
|
|
18473
|
+
ipv4Prefix: "135.237.131.208/28"
|
|
18474
|
+
},
|
|
18475
|
+
{
|
|
18476
|
+
ipv4Prefix: "135.237.133.48/28"
|
|
18477
|
+
},
|
|
18478
|
+
{
|
|
18479
|
+
ipv4Prefix: "137.135.191.176/28"
|
|
18480
|
+
},
|
|
18481
|
+
{
|
|
18482
|
+
ipv4Prefix: "138.91.30.48/28"
|
|
18483
|
+
},
|
|
18484
|
+
{
|
|
18485
|
+
ipv4Prefix: "138.91.46.96/28"
|
|
18486
|
+
},
|
|
18487
|
+
{
|
|
18488
|
+
ipv4Prefix: "168.63.252.240/28"
|
|
18489
|
+
},
|
|
18490
|
+
{
|
|
18491
|
+
ipv4Prefix: "172.170.8.208/28"
|
|
18492
|
+
},
|
|
18493
|
+
{
|
|
18494
|
+
ipv4Prefix: "172.171.4.176/28"
|
|
18495
|
+
},
|
|
18496
|
+
{
|
|
18497
|
+
ipv4Prefix: "172.178.140.144/28"
|
|
18498
|
+
},
|
|
18499
|
+
{
|
|
18500
|
+
ipv4Prefix: "172.178.141.112/28"
|
|
18501
|
+
},
|
|
18502
|
+
{
|
|
18503
|
+
ipv4Prefix: "172.178.141.128/28"
|
|
18504
|
+
},
|
|
18505
|
+
{
|
|
18506
|
+
ipv4Prefix: "172.183.143.224/28"
|
|
18507
|
+
},
|
|
18508
|
+
{
|
|
18509
|
+
ipv4Prefix: "172.183.222.128/28"
|
|
18510
|
+
},
|
|
18511
|
+
{
|
|
18512
|
+
ipv4Prefix: "172.196.40.208/28"
|
|
18513
|
+
},
|
|
18514
|
+
{
|
|
18515
|
+
ipv4Prefix: "172.202.102.112/28"
|
|
18516
|
+
},
|
|
18517
|
+
{
|
|
18518
|
+
ipv4Prefix: "172.204.16.64/28"
|
|
18519
|
+
},
|
|
18520
|
+
{
|
|
18521
|
+
ipv4Prefix: "172.204.27.16/28"
|
|
18522
|
+
},
|
|
18523
|
+
{
|
|
18524
|
+
ipv4Prefix: "172.212.159.64/28"
|
|
18525
|
+
},
|
|
18526
|
+
{
|
|
18527
|
+
ipv4Prefix: "172.212.172.160/28"
|
|
18528
|
+
},
|
|
18529
|
+
{
|
|
18530
|
+
ipv4Prefix: "172.213.11.144/28"
|
|
18531
|
+
},
|
|
18532
|
+
{
|
|
18533
|
+
ipv4Prefix: "172.213.12.112/28"
|
|
18534
|
+
},
|
|
18535
|
+
{
|
|
18536
|
+
ipv4Prefix: "172.213.21.112/28"
|
|
18537
|
+
},
|
|
18538
|
+
{
|
|
18539
|
+
ipv4Prefix: "172.213.21.144/28"
|
|
18540
|
+
},
|
|
18541
|
+
{
|
|
18542
|
+
ipv4Prefix: "172.213.21.16/28"
|
|
18543
|
+
},
|
|
18544
|
+
{
|
|
18545
|
+
ipv4Prefix: "172.215.218.96/28"
|
|
18546
|
+
},
|
|
18547
|
+
{
|
|
18548
|
+
ipv4Prefix: "191.233.1.112/28"
|
|
18549
|
+
},
|
|
18550
|
+
{
|
|
18551
|
+
ipv4Prefix: "191.233.1.128/28"
|
|
18552
|
+
},
|
|
18553
|
+
{
|
|
18554
|
+
ipv4Prefix: "191.233.1.224/28"
|
|
18555
|
+
},
|
|
18556
|
+
{
|
|
18557
|
+
ipv4Prefix: "191.233.194.32/28"
|
|
18558
|
+
},
|
|
18559
|
+
{
|
|
18560
|
+
ipv4Prefix: "191.233.196.112/28"
|
|
18561
|
+
},
|
|
18562
|
+
{
|
|
18563
|
+
ipv4Prefix: "191.233.199.160/28"
|
|
18564
|
+
},
|
|
18565
|
+
{
|
|
18566
|
+
ipv4Prefix: "191.233.2.0/28"
|
|
18567
|
+
},
|
|
18568
|
+
{
|
|
18569
|
+
ipv4Prefix: "191.234.167.128/28"
|
|
18570
|
+
},
|
|
18571
|
+
{
|
|
18572
|
+
ipv4Prefix: "191.235.66.16/28"
|
|
18573
|
+
},
|
|
18574
|
+
{
|
|
18575
|
+
ipv4Prefix: "191.235.98.144/28"
|
|
18576
|
+
},
|
|
18577
|
+
{
|
|
18578
|
+
ipv4Prefix: "191.235.99.80/28"
|
|
18579
|
+
},
|
|
18580
|
+
{
|
|
18581
|
+
ipv4Prefix: "191.237.249.64/28"
|
|
18582
|
+
},
|
|
18583
|
+
{
|
|
18584
|
+
ipv4Prefix: "191.239.245.16/28"
|
|
18585
|
+
},
|
|
18586
|
+
{
|
|
18587
|
+
ipv4Prefix: "20.0.53.96/28"
|
|
18588
|
+
},
|
|
18589
|
+
{
|
|
18590
|
+
ipv4Prefix: "20.102.212.144/28"
|
|
18591
|
+
},
|
|
18592
|
+
{
|
|
18593
|
+
ipv4Prefix: "20.113.218.16/28"
|
|
18594
|
+
},
|
|
18595
|
+
{
|
|
18596
|
+
ipv4Prefix: "20.113.225.112/28"
|
|
18597
|
+
},
|
|
18598
|
+
{
|
|
18599
|
+
ipv4Prefix: "20.125.112.224/28"
|
|
18600
|
+
},
|
|
18601
|
+
{
|
|
18602
|
+
ipv4Prefix: "20.125.144.144/28"
|
|
18603
|
+
},
|
|
18604
|
+
{
|
|
18605
|
+
ipv4Prefix: "20.161.75.208/28"
|
|
18606
|
+
},
|
|
18607
|
+
{
|
|
18608
|
+
ipv4Prefix: "20.168.7.192/28"
|
|
18609
|
+
},
|
|
18610
|
+
{
|
|
18611
|
+
ipv4Prefix: "20.168.7.240/28"
|
|
18612
|
+
},
|
|
18613
|
+
{
|
|
18614
|
+
ipv4Prefix: "20.169.72.112/28"
|
|
18615
|
+
},
|
|
18616
|
+
{
|
|
18617
|
+
ipv4Prefix: "20.169.72.96/28"
|
|
18618
|
+
},
|
|
18619
|
+
{
|
|
18620
|
+
ipv4Prefix: "20.169.73.176/28"
|
|
18621
|
+
},
|
|
18622
|
+
{
|
|
18623
|
+
ipv4Prefix: "20.169.73.32/28"
|
|
18624
|
+
},
|
|
18625
|
+
{
|
|
18626
|
+
ipv4Prefix: "20.169.73.64/28"
|
|
18627
|
+
},
|
|
18628
|
+
{
|
|
18629
|
+
ipv4Prefix: "20.169.78.112/28"
|
|
18630
|
+
},
|
|
18631
|
+
{
|
|
18632
|
+
ipv4Prefix: "20.169.78.128/28"
|
|
18633
|
+
},
|
|
18634
|
+
{
|
|
18635
|
+
ipv4Prefix: "20.169.78.144/28"
|
|
18636
|
+
},
|
|
18637
|
+
{
|
|
18638
|
+
ipv4Prefix: "20.169.78.160/28"
|
|
18639
|
+
},
|
|
18640
|
+
{
|
|
18641
|
+
ipv4Prefix: "20.169.78.176/28"
|
|
18642
|
+
},
|
|
18643
|
+
{
|
|
18644
|
+
ipv4Prefix: "20.169.78.192/28"
|
|
18645
|
+
},
|
|
18646
|
+
{
|
|
18647
|
+
ipv4Prefix: "20.169.78.208/28"
|
|
18648
|
+
},
|
|
18649
|
+
{
|
|
18650
|
+
ipv4Prefix: "20.169.78.48/28"
|
|
18651
|
+
},
|
|
18652
|
+
{
|
|
18653
|
+
ipv4Prefix: "20.169.78.64/28"
|
|
18654
|
+
},
|
|
18655
|
+
{
|
|
18656
|
+
ipv4Prefix: "20.169.78.80/28"
|
|
18657
|
+
},
|
|
18658
|
+
{
|
|
18659
|
+
ipv4Prefix: "20.169.78.96/28"
|
|
18660
|
+
},
|
|
18661
|
+
{
|
|
18662
|
+
ipv4Prefix: "20.169.86.224/28"
|
|
18663
|
+
},
|
|
18664
|
+
{
|
|
18665
|
+
ipv4Prefix: "20.169.86.240/28"
|
|
18666
|
+
},
|
|
18667
|
+
{
|
|
18668
|
+
ipv4Prefix: "20.169.87.112/28"
|
|
18669
|
+
},
|
|
18670
|
+
{
|
|
18671
|
+
ipv4Prefix: "20.17.108.96/28"
|
|
18672
|
+
},
|
|
18673
|
+
{
|
|
18674
|
+
ipv4Prefix: "20.172.29.32/28"
|
|
18675
|
+
},
|
|
18676
|
+
{
|
|
18677
|
+
ipv4Prefix: "20.193.233.240/28"
|
|
18678
|
+
},
|
|
18679
|
+
{
|
|
18680
|
+
ipv4Prefix: "20.193.50.32/28"
|
|
18681
|
+
},
|
|
18682
|
+
{
|
|
18683
|
+
ipv4Prefix: "20.194.0.208/28"
|
|
18684
|
+
},
|
|
18685
|
+
{
|
|
18686
|
+
ipv4Prefix: "20.194.1.0/28"
|
|
18687
|
+
},
|
|
18688
|
+
{
|
|
18689
|
+
ipv4Prefix: "20.194.157.176/28"
|
|
18690
|
+
},
|
|
18691
|
+
{
|
|
18692
|
+
ipv4Prefix: "20.198.67.96/28"
|
|
18693
|
+
},
|
|
18694
|
+
{
|
|
18695
|
+
ipv4Prefix: "20.199.211.160/28"
|
|
18696
|
+
},
|
|
18697
|
+
{
|
|
18698
|
+
ipv4Prefix: "20.203.245.32/28"
|
|
18699
|
+
},
|
|
18700
|
+
{
|
|
18701
|
+
ipv4Prefix: "20.204.24.240/28"
|
|
18702
|
+
},
|
|
18703
|
+
{
|
|
18704
|
+
ipv4Prefix: "20.206.107.192/28"
|
|
18705
|
+
},
|
|
18706
|
+
{
|
|
18707
|
+
ipv4Prefix: "20.210.154.128/28"
|
|
18708
|
+
},
|
|
18709
|
+
{
|
|
18710
|
+
ipv4Prefix: "20.210.174.208/28"
|
|
18711
|
+
},
|
|
18712
|
+
{
|
|
18713
|
+
ipv4Prefix: "20.210.211.192/28"
|
|
18714
|
+
},
|
|
18715
|
+
{
|
|
18716
|
+
ipv4Prefix: "20.215.187.208/28"
|
|
18717
|
+
},
|
|
18718
|
+
{
|
|
18719
|
+
ipv4Prefix: "20.215.188.192/28"
|
|
18720
|
+
},
|
|
18721
|
+
{
|
|
18722
|
+
ipv4Prefix: "20.215.214.16/28"
|
|
18723
|
+
},
|
|
18724
|
+
{
|
|
18725
|
+
ipv4Prefix: "20.215.219.128/28"
|
|
18726
|
+
},
|
|
18727
|
+
{
|
|
18728
|
+
ipv4Prefix: "20.215.219.160/28"
|
|
18729
|
+
},
|
|
18730
|
+
{
|
|
18731
|
+
ipv4Prefix: "20.215.219.208/28"
|
|
18732
|
+
},
|
|
18733
|
+
{
|
|
18734
|
+
ipv4Prefix: "20.215.220.112/28"
|
|
18735
|
+
},
|
|
18736
|
+
{
|
|
18737
|
+
ipv4Prefix: "20.215.220.128/28"
|
|
18738
|
+
},
|
|
18739
|
+
{
|
|
18740
|
+
ipv4Prefix: "20.215.220.144/28"
|
|
18741
|
+
},
|
|
18742
|
+
{
|
|
18743
|
+
ipv4Prefix: "20.215.220.160/28"
|
|
18744
|
+
},
|
|
18745
|
+
{
|
|
18746
|
+
ipv4Prefix: "20.215.220.176/28"
|
|
18747
|
+
},
|
|
18748
|
+
{
|
|
18749
|
+
ipv4Prefix: "20.215.220.192/28"
|
|
18750
|
+
},
|
|
18751
|
+
{
|
|
18752
|
+
ipv4Prefix: "20.215.220.208/28"
|
|
18753
|
+
},
|
|
18754
|
+
{
|
|
18755
|
+
ipv4Prefix: "20.215.220.64/28"
|
|
18756
|
+
},
|
|
18757
|
+
{
|
|
18758
|
+
ipv4Prefix: "20.215.220.80/28"
|
|
18759
|
+
},
|
|
18760
|
+
{
|
|
18761
|
+
ipv4Prefix: "20.215.220.96/28"
|
|
18762
|
+
},
|
|
18763
|
+
{
|
|
18764
|
+
ipv4Prefix: "20.226.32.80/28"
|
|
18765
|
+
},
|
|
18766
|
+
{
|
|
18767
|
+
ipv4Prefix: "20.227.140.32/28"
|
|
18768
|
+
},
|
|
18769
|
+
{
|
|
18770
|
+
ipv4Prefix: "20.228.106.176/28"
|
|
18771
|
+
},
|
|
18772
|
+
{
|
|
18773
|
+
ipv4Prefix: "20.235.75.208/28"
|
|
18774
|
+
},
|
|
18775
|
+
{
|
|
18776
|
+
ipv4Prefix: "20.235.87.224/28"
|
|
18777
|
+
},
|
|
18778
|
+
{
|
|
18779
|
+
ipv4Prefix: "20.249.63.208/28"
|
|
18780
|
+
},
|
|
18781
|
+
{
|
|
18782
|
+
ipv4Prefix: "20.27.94.128/28"
|
|
18783
|
+
},
|
|
18784
|
+
{
|
|
18785
|
+
ipv4Prefix: "20.42.250.32/28"
|
|
18786
|
+
},
|
|
18787
|
+
{
|
|
18788
|
+
ipv4Prefix: "20.45.178.144/28"
|
|
18789
|
+
},
|
|
18790
|
+
{
|
|
18791
|
+
ipv4Prefix: "20.55.229.144/28"
|
|
18792
|
+
},
|
|
18793
|
+
{
|
|
18794
|
+
ipv4Prefix: "20.57.199.192/28"
|
|
18795
|
+
},
|
|
18796
|
+
{
|
|
18797
|
+
ipv4Prefix: "20.63.221.64/28"
|
|
18798
|
+
},
|
|
18799
|
+
{
|
|
18800
|
+
ipv4Prefix: "20.97.189.96/28"
|
|
18801
|
+
},
|
|
18802
|
+
{
|
|
18803
|
+
ipv4Prefix: "23.102.140.144/28"
|
|
18804
|
+
},
|
|
18805
|
+
{
|
|
18806
|
+
ipv4Prefix: "23.102.141.32/28"
|
|
18807
|
+
},
|
|
18808
|
+
{
|
|
18809
|
+
ipv4Prefix: "23.97.109.224/28"
|
|
18810
|
+
},
|
|
18811
|
+
{
|
|
18812
|
+
ipv4Prefix: "23.98.142.176/28"
|
|
18813
|
+
},
|
|
18814
|
+
{
|
|
18815
|
+
ipv4Prefix: "23.98.179.16/28"
|
|
18816
|
+
},
|
|
18817
|
+
{
|
|
18818
|
+
ipv4Prefix: "23.98.186.176/28"
|
|
18819
|
+
},
|
|
18820
|
+
{
|
|
18821
|
+
ipv4Prefix: "23.98.186.192/28"
|
|
18822
|
+
},
|
|
18823
|
+
{
|
|
18824
|
+
ipv4Prefix: "23.98.186.64/28"
|
|
18825
|
+
},
|
|
18826
|
+
{
|
|
18827
|
+
ipv4Prefix: "23.98.186.96/28"
|
|
18828
|
+
},
|
|
18829
|
+
{
|
|
18830
|
+
ipv4Prefix: "4.151.119.48/28"
|
|
18831
|
+
},
|
|
18832
|
+
{
|
|
18833
|
+
ipv4Prefix: "4.151.241.240/28"
|
|
18834
|
+
},
|
|
18835
|
+
{
|
|
18836
|
+
ipv4Prefix: "4.151.71.176/28"
|
|
18837
|
+
},
|
|
18838
|
+
{
|
|
18839
|
+
ipv4Prefix: "4.189.118.208/28"
|
|
18840
|
+
},
|
|
18841
|
+
{
|
|
18842
|
+
ipv4Prefix: "4.189.119.48/28"
|
|
18843
|
+
},
|
|
18844
|
+
{
|
|
18845
|
+
ipv4Prefix: "4.196.118.112/28"
|
|
18846
|
+
},
|
|
18847
|
+
{
|
|
18848
|
+
ipv4Prefix: "4.196.198.80/28"
|
|
18849
|
+
},
|
|
18850
|
+
{
|
|
18851
|
+
ipv4Prefix: "4.197.115.112/28"
|
|
18852
|
+
},
|
|
18853
|
+
{
|
|
18854
|
+
ipv4Prefix: "4.197.19.176/28"
|
|
18855
|
+
},
|
|
18856
|
+
{
|
|
18857
|
+
ipv4Prefix: "4.197.22.112/28"
|
|
18858
|
+
},
|
|
18859
|
+
{
|
|
18860
|
+
ipv4Prefix: "4.197.64.0/28"
|
|
18861
|
+
},
|
|
18862
|
+
{
|
|
18863
|
+
ipv4Prefix: "4.197.64.16/28"
|
|
18864
|
+
},
|
|
18865
|
+
{
|
|
18866
|
+
ipv4Prefix: "4.197.64.48/28"
|
|
18867
|
+
},
|
|
18868
|
+
{
|
|
18869
|
+
ipv4Prefix: "4.197.64.64/28"
|
|
18870
|
+
},
|
|
18871
|
+
{
|
|
18872
|
+
ipv4Prefix: "4.198.72.16/28"
|
|
18873
|
+
},
|
|
18874
|
+
{
|
|
18875
|
+
ipv4Prefix: "4.205.128.176/28"
|
|
18876
|
+
},
|
|
18877
|
+
{
|
|
18878
|
+
ipv4Prefix: "4.226.226.32/28"
|
|
18879
|
+
},
|
|
18880
|
+
{
|
|
18881
|
+
ipv4Prefix: "40.116.73.208/28"
|
|
18882
|
+
},
|
|
18883
|
+
{
|
|
18884
|
+
ipv4Prefix: "40.122.235.112/28"
|
|
18885
|
+
},
|
|
18886
|
+
{
|
|
18887
|
+
ipv4Prefix: "40.67.183.160/28"
|
|
18888
|
+
},
|
|
18889
|
+
{
|
|
18890
|
+
ipv4Prefix: "40.67.183.176/28"
|
|
18891
|
+
},
|
|
18892
|
+
{
|
|
18893
|
+
ipv4Prefix: "40.75.14.224/28"
|
|
18894
|
+
},
|
|
18895
|
+
{
|
|
18896
|
+
ipv4Prefix: "40.81.134.128/28"
|
|
18897
|
+
},
|
|
18898
|
+
{
|
|
18899
|
+
ipv4Prefix: "40.81.134.144/28"
|
|
18900
|
+
},
|
|
18901
|
+
{
|
|
18902
|
+
ipv4Prefix: "40.81.234.144/28"
|
|
18903
|
+
},
|
|
18904
|
+
{
|
|
18905
|
+
ipv4Prefix: "40.84.181.32/28"
|
|
18906
|
+
},
|
|
18907
|
+
{
|
|
18908
|
+
ipv4Prefix: "40.84.221.208/28"
|
|
18909
|
+
},
|
|
18910
|
+
{
|
|
18911
|
+
ipv4Prefix: "40.84.221.224/28"
|
|
18912
|
+
},
|
|
18913
|
+
{
|
|
18914
|
+
ipv4Prefix: "48.193.44.32/28"
|
|
18915
|
+
},
|
|
18916
|
+
{
|
|
18917
|
+
ipv4Prefix: "51.107.70.192/28"
|
|
18918
|
+
},
|
|
18919
|
+
{
|
|
18920
|
+
ipv4Prefix: "51.116.2.64/28"
|
|
18921
|
+
},
|
|
18922
|
+
{
|
|
18923
|
+
ipv4Prefix: "51.116.2.80/28"
|
|
18924
|
+
},
|
|
18925
|
+
{
|
|
18926
|
+
ipv4Prefix: "51.8.155.48/28"
|
|
18927
|
+
},
|
|
18928
|
+
{
|
|
18929
|
+
ipv4Prefix: "51.8.155.64/28"
|
|
18930
|
+
},
|
|
18931
|
+
{
|
|
18932
|
+
ipv4Prefix: "51.8.155.80/28"
|
|
18933
|
+
},
|
|
18934
|
+
{
|
|
18935
|
+
ipv4Prefix: "52.148.129.32/28"
|
|
18936
|
+
},
|
|
18937
|
+
{
|
|
18938
|
+
ipv4Prefix: "52.153.130.48/28"
|
|
18939
|
+
},
|
|
18940
|
+
{
|
|
18941
|
+
ipv4Prefix: "52.153.130.64/28"
|
|
18942
|
+
},
|
|
18943
|
+
{
|
|
18944
|
+
ipv4Prefix: "52.154.22.48/28"
|
|
18945
|
+
},
|
|
18946
|
+
{
|
|
18947
|
+
ipv4Prefix: "52.156.77.144/28"
|
|
18948
|
+
},
|
|
18949
|
+
{
|
|
18950
|
+
ipv4Prefix: "52.159.227.32/28"
|
|
18951
|
+
},
|
|
18952
|
+
{
|
|
18953
|
+
ipv4Prefix: "52.159.249.96/28"
|
|
18954
|
+
},
|
|
18955
|
+
{
|
|
18956
|
+
ipv4Prefix: "52.165.212.16/28"
|
|
18957
|
+
},
|
|
18958
|
+
{
|
|
18959
|
+
ipv4Prefix: "52.165.212.32/28"
|
|
18960
|
+
},
|
|
18961
|
+
{
|
|
18962
|
+
ipv4Prefix: "52.165.212.48/28"
|
|
18963
|
+
},
|
|
18964
|
+
{
|
|
18965
|
+
ipv4Prefix: "52.172.129.160/28"
|
|
18966
|
+
},
|
|
18967
|
+
{
|
|
18968
|
+
ipv4Prefix: "52.172.251.112/28"
|
|
18969
|
+
},
|
|
18970
|
+
{
|
|
18971
|
+
ipv4Prefix: "52.173.123.0/28"
|
|
18972
|
+
},
|
|
18973
|
+
{
|
|
18974
|
+
ipv4Prefix: "52.173.219.112/28"
|
|
18975
|
+
},
|
|
18976
|
+
{
|
|
18977
|
+
ipv4Prefix: "52.173.219.96/28"
|
|
18978
|
+
},
|
|
18979
|
+
{
|
|
18980
|
+
ipv4Prefix: "52.173.221.16/28"
|
|
18981
|
+
},
|
|
18982
|
+
{
|
|
18983
|
+
ipv4Prefix: "52.173.221.176/28"
|
|
18984
|
+
},
|
|
18985
|
+
{
|
|
18986
|
+
ipv4Prefix: "52.173.221.208/28"
|
|
18987
|
+
},
|
|
18988
|
+
{
|
|
18989
|
+
ipv4Prefix: "52.173.234.16/28"
|
|
18990
|
+
},
|
|
18991
|
+
{
|
|
18992
|
+
ipv4Prefix: "52.173.234.80/28"
|
|
18993
|
+
},
|
|
18994
|
+
{
|
|
18995
|
+
ipv4Prefix: "52.173.235.80/28"
|
|
18996
|
+
},
|
|
18997
|
+
{
|
|
18998
|
+
ipv4Prefix: "52.176.139.176/28"
|
|
18999
|
+
},
|
|
19000
|
+
{
|
|
19001
|
+
ipv4Prefix: "52.187.246.128/28"
|
|
19002
|
+
},
|
|
19003
|
+
{
|
|
19004
|
+
ipv4Prefix: "52.190.137.144/28"
|
|
19005
|
+
},
|
|
19006
|
+
{
|
|
19007
|
+
ipv4Prefix: "52.190.137.16/28"
|
|
19008
|
+
},
|
|
19009
|
+
{
|
|
19010
|
+
ipv4Prefix: "52.190.139.48/28"
|
|
19011
|
+
},
|
|
19012
|
+
{
|
|
19013
|
+
ipv4Prefix: "52.190.142.64/28"
|
|
19014
|
+
},
|
|
19015
|
+
{
|
|
19016
|
+
ipv4Prefix: "52.190.190.16/28"
|
|
19017
|
+
},
|
|
19018
|
+
{
|
|
19019
|
+
ipv4Prefix: "52.225.75.208/28"
|
|
19020
|
+
},
|
|
19021
|
+
{
|
|
19022
|
+
ipv4Prefix: "52.230.163.32/28"
|
|
19023
|
+
},
|
|
19024
|
+
{
|
|
19025
|
+
ipv4Prefix: "52.230.164.176/28"
|
|
19026
|
+
},
|
|
19027
|
+
{
|
|
19028
|
+
ipv4Prefix: "52.231.30.48/28"
|
|
19029
|
+
},
|
|
19030
|
+
{
|
|
19031
|
+
ipv4Prefix: "52.231.34.176/28"
|
|
19032
|
+
},
|
|
19033
|
+
{
|
|
19034
|
+
ipv4Prefix: "52.231.39.144/28"
|
|
19035
|
+
},
|
|
19036
|
+
{
|
|
19037
|
+
ipv4Prefix: "52.231.39.192/28"
|
|
19038
|
+
},
|
|
19039
|
+
{
|
|
19040
|
+
ipv4Prefix: "52.231.49.48/28"
|
|
19041
|
+
},
|
|
19042
|
+
{
|
|
19043
|
+
ipv4Prefix: "52.231.50.64/28"
|
|
19044
|
+
},
|
|
19045
|
+
{
|
|
19046
|
+
ipv4Prefix: "52.236.94.144/28"
|
|
19047
|
+
},
|
|
19048
|
+
{
|
|
19049
|
+
ipv4Prefix: "52.241.146.208/28"
|
|
19050
|
+
},
|
|
19051
|
+
{
|
|
19052
|
+
ipv4Prefix: "52.242.132.224/28"
|
|
19053
|
+
},
|
|
19054
|
+
{
|
|
19055
|
+
ipv4Prefix: "52.242.132.240/28"
|
|
19056
|
+
},
|
|
19057
|
+
{
|
|
19058
|
+
ipv4Prefix: "52.242.245.208/28"
|
|
19059
|
+
},
|
|
19060
|
+
{
|
|
19061
|
+
ipv4Prefix: "52.252.113.240/28"
|
|
19062
|
+
},
|
|
19063
|
+
{
|
|
19064
|
+
ipv4Prefix: "52.255.109.112/28"
|
|
19065
|
+
},
|
|
19066
|
+
{
|
|
19067
|
+
ipv4Prefix: "52.255.109.128/28"
|
|
19068
|
+
},
|
|
19069
|
+
{
|
|
19070
|
+
ipv4Prefix: "52.255.109.144/28"
|
|
19071
|
+
},
|
|
19072
|
+
{
|
|
19073
|
+
ipv4Prefix: "52.255.109.80/28"
|
|
19074
|
+
},
|
|
19075
|
+
{
|
|
19076
|
+
ipv4Prefix: "52.255.109.96/28"
|
|
19077
|
+
},
|
|
19078
|
+
{
|
|
19079
|
+
ipv4Prefix: "52.255.111.0/28"
|
|
19080
|
+
},
|
|
19081
|
+
{
|
|
19082
|
+
ipv4Prefix: "52.255.111.112/28"
|
|
19083
|
+
},
|
|
19084
|
+
{
|
|
19085
|
+
ipv4Prefix: "52.255.111.16/28"
|
|
19086
|
+
},
|
|
19087
|
+
{
|
|
19088
|
+
ipv4Prefix: "52.255.111.32/28"
|
|
19089
|
+
},
|
|
19090
|
+
{
|
|
19091
|
+
ipv4Prefix: "52.255.111.48/28"
|
|
19092
|
+
},
|
|
19093
|
+
{
|
|
19094
|
+
ipv4Prefix: "52.255.111.80/28"
|
|
19095
|
+
},
|
|
19096
|
+
{
|
|
19097
|
+
ipv4Prefix: "57.151.131.224/28"
|
|
19098
|
+
},
|
|
19099
|
+
{
|
|
19100
|
+
ipv4Prefix: "57.154.174.112/28"
|
|
19101
|
+
},
|
|
19102
|
+
{
|
|
19103
|
+
ipv4Prefix: "57.154.175.0/28"
|
|
19104
|
+
},
|
|
19105
|
+
{
|
|
19106
|
+
ipv4Prefix: "57.154.187.32/28"
|
|
19107
|
+
},
|
|
19108
|
+
{
|
|
19109
|
+
ipv4Prefix: "68.154.28.96/28"
|
|
19110
|
+
},
|
|
19111
|
+
{
|
|
19112
|
+
ipv4Prefix: "68.218.30.112/28"
|
|
19113
|
+
},
|
|
19114
|
+
{
|
|
19115
|
+
ipv4Prefix: "68.220.57.64/28"
|
|
19116
|
+
},
|
|
19117
|
+
{
|
|
19118
|
+
ipv4Prefix: "68.221.67.160/28"
|
|
19119
|
+
},
|
|
19120
|
+
{
|
|
19121
|
+
ipv4Prefix: "68.221.67.192/28"
|
|
19122
|
+
},
|
|
19123
|
+
{
|
|
19124
|
+
ipv4Prefix: "68.221.67.224/28"
|
|
19125
|
+
},
|
|
19126
|
+
{
|
|
19127
|
+
ipv4Prefix: "68.221.67.240/28"
|
|
19128
|
+
},
|
|
19129
|
+
{
|
|
19130
|
+
ipv4Prefix: "68.221.75.16/28"
|
|
19131
|
+
},
|
|
19132
|
+
{
|
|
19133
|
+
ipv4Prefix: "70.153.76.16/28"
|
|
19134
|
+
},
|
|
19135
|
+
{
|
|
19136
|
+
ipv4Prefix: "74.226.253.160/28"
|
|
19137
|
+
},
|
|
19138
|
+
{
|
|
19139
|
+
ipv4Prefix: "74.249.86.176/28"
|
|
19140
|
+
},
|
|
19141
|
+
{
|
|
19142
|
+
ipv4Prefix: "74.7.35.112/28"
|
|
19143
|
+
},
|
|
19144
|
+
{
|
|
19145
|
+
ipv4Prefix: "74.7.35.48/28"
|
|
19146
|
+
},
|
|
19147
|
+
{
|
|
19148
|
+
ipv4Prefix: "74.7.36.64/28"
|
|
19149
|
+
},
|
|
19150
|
+
{
|
|
19151
|
+
ipv4Prefix: "74.7.36.80/28"
|
|
19152
|
+
},
|
|
19153
|
+
{
|
|
19154
|
+
ipv4Prefix: "74.7.36.96/28"
|
|
19155
|
+
},
|
|
19156
|
+
{
|
|
19157
|
+
ipv4Prefix: "85.211.241.128/28"
|
|
19158
|
+
},
|
|
19159
|
+
{
|
|
19160
|
+
ipv4Prefix: "9.160.163.224/28"
|
|
19161
|
+
},
|
|
19162
|
+
{
|
|
19163
|
+
ipv4Prefix: "9.160.164.128/28"
|
|
19164
|
+
},
|
|
19165
|
+
{
|
|
19166
|
+
ipv4Prefix: "9.234.96.192/28"
|
|
19167
|
+
}
|
|
19168
|
+
]
|
|
19169
|
+
};
|
|
19170
|
+
|
|
19171
|
+
// ../integration-traffic/src/ip-ranges/googlebot.json
|
|
19172
|
+
var googlebot_default = {
|
|
19173
|
+
_source: "https://developers.google.com/static/search/apis/ipranges/googlebot.json",
|
|
19174
|
+
creationTime: "2026-05-18T14:46:14.000000",
|
|
19175
|
+
prefixes: [
|
|
19176
|
+
{
|
|
19177
|
+
ipv6Prefix: "2001:4860:4801:10::/64"
|
|
19178
|
+
},
|
|
19179
|
+
{
|
|
19180
|
+
ipv6Prefix: "2001:4860:4801:11::/64"
|
|
19181
|
+
},
|
|
19182
|
+
{
|
|
19183
|
+
ipv6Prefix: "2001:4860:4801:12::/64"
|
|
19184
|
+
},
|
|
19185
|
+
{
|
|
19186
|
+
ipv6Prefix: "2001:4860:4801:13::/64"
|
|
19187
|
+
},
|
|
19188
|
+
{
|
|
19189
|
+
ipv6Prefix: "2001:4860:4801:14::/64"
|
|
19190
|
+
},
|
|
19191
|
+
{
|
|
19192
|
+
ipv6Prefix: "2001:4860:4801:15::/64"
|
|
19193
|
+
},
|
|
19194
|
+
{
|
|
19195
|
+
ipv6Prefix: "2001:4860:4801:16::/64"
|
|
19196
|
+
},
|
|
19197
|
+
{
|
|
19198
|
+
ipv6Prefix: "2001:4860:4801:17::/64"
|
|
19199
|
+
},
|
|
19200
|
+
{
|
|
19201
|
+
ipv6Prefix: "2001:4860:4801:18::/64"
|
|
19202
|
+
},
|
|
19203
|
+
{
|
|
19204
|
+
ipv6Prefix: "2001:4860:4801:19::/64"
|
|
19205
|
+
},
|
|
19206
|
+
{
|
|
19207
|
+
ipv6Prefix: "2001:4860:4801:1a::/64"
|
|
19208
|
+
},
|
|
19209
|
+
{
|
|
19210
|
+
ipv6Prefix: "2001:4860:4801:1b::/64"
|
|
19211
|
+
},
|
|
19212
|
+
{
|
|
19213
|
+
ipv6Prefix: "2001:4860:4801:1c::/64"
|
|
19214
|
+
},
|
|
19215
|
+
{
|
|
19216
|
+
ipv6Prefix: "2001:4860:4801:1d::/64"
|
|
19217
|
+
},
|
|
19218
|
+
{
|
|
19219
|
+
ipv6Prefix: "2001:4860:4801:1e::/64"
|
|
19220
|
+
},
|
|
19221
|
+
{
|
|
19222
|
+
ipv6Prefix: "2001:4860:4801:1f::/64"
|
|
19223
|
+
},
|
|
19224
|
+
{
|
|
19225
|
+
ipv6Prefix: "2001:4860:4801:20::/64"
|
|
19226
|
+
},
|
|
19227
|
+
{
|
|
19228
|
+
ipv6Prefix: "2001:4860:4801:21::/64"
|
|
19229
|
+
},
|
|
19230
|
+
{
|
|
19231
|
+
ipv6Prefix: "2001:4860:4801:22::/64"
|
|
19232
|
+
},
|
|
19233
|
+
{
|
|
19234
|
+
ipv6Prefix: "2001:4860:4801:23::/64"
|
|
19235
|
+
},
|
|
19236
|
+
{
|
|
19237
|
+
ipv6Prefix: "2001:4860:4801:24::/64"
|
|
19238
|
+
},
|
|
19239
|
+
{
|
|
19240
|
+
ipv6Prefix: "2001:4860:4801:25::/64"
|
|
19241
|
+
},
|
|
19242
|
+
{
|
|
19243
|
+
ipv6Prefix: "2001:4860:4801:26::/64"
|
|
19244
|
+
},
|
|
19245
|
+
{
|
|
19246
|
+
ipv6Prefix: "2001:4860:4801:27::/64"
|
|
19247
|
+
},
|
|
19248
|
+
{
|
|
19249
|
+
ipv6Prefix: "2001:4860:4801:28::/64"
|
|
19250
|
+
},
|
|
19251
|
+
{
|
|
19252
|
+
ipv6Prefix: "2001:4860:4801:29::/64"
|
|
19253
|
+
},
|
|
19254
|
+
{
|
|
19255
|
+
ipv6Prefix: "2001:4860:4801:2::/64"
|
|
19256
|
+
},
|
|
19257
|
+
{
|
|
19258
|
+
ipv6Prefix: "2001:4860:4801:2a::/64"
|
|
19259
|
+
},
|
|
19260
|
+
{
|
|
19261
|
+
ipv6Prefix: "2001:4860:4801:2b::/64"
|
|
19262
|
+
},
|
|
19263
|
+
{
|
|
19264
|
+
ipv6Prefix: "2001:4860:4801:2c::/64"
|
|
19265
|
+
},
|
|
19266
|
+
{
|
|
19267
|
+
ipv6Prefix: "2001:4860:4801:2d::/64"
|
|
19268
|
+
},
|
|
19269
|
+
{
|
|
19270
|
+
ipv6Prefix: "2001:4860:4801:2e::/64"
|
|
19271
|
+
},
|
|
19272
|
+
{
|
|
19273
|
+
ipv6Prefix: "2001:4860:4801:2f::/64"
|
|
19274
|
+
},
|
|
19275
|
+
{
|
|
19276
|
+
ipv6Prefix: "2001:4860:4801:30::/64"
|
|
19277
|
+
},
|
|
19278
|
+
{
|
|
19279
|
+
ipv6Prefix: "2001:4860:4801:31::/64"
|
|
19280
|
+
},
|
|
19281
|
+
{
|
|
19282
|
+
ipv6Prefix: "2001:4860:4801:32::/64"
|
|
19283
|
+
},
|
|
19284
|
+
{
|
|
19285
|
+
ipv6Prefix: "2001:4860:4801:33::/64"
|
|
19286
|
+
},
|
|
19287
|
+
{
|
|
19288
|
+
ipv6Prefix: "2001:4860:4801:34::/64"
|
|
19289
|
+
},
|
|
19290
|
+
{
|
|
19291
|
+
ipv6Prefix: "2001:4860:4801:35::/64"
|
|
19292
|
+
},
|
|
19293
|
+
{
|
|
19294
|
+
ipv6Prefix: "2001:4860:4801:36::/64"
|
|
19295
|
+
},
|
|
19296
|
+
{
|
|
19297
|
+
ipv6Prefix: "2001:4860:4801:37::/64"
|
|
19298
|
+
},
|
|
19299
|
+
{
|
|
19300
|
+
ipv6Prefix: "2001:4860:4801:38::/64"
|
|
19301
|
+
},
|
|
19302
|
+
{
|
|
19303
|
+
ipv6Prefix: "2001:4860:4801:39::/64"
|
|
19304
|
+
},
|
|
19305
|
+
{
|
|
19306
|
+
ipv6Prefix: "2001:4860:4801:3a::/64"
|
|
19307
|
+
},
|
|
19308
|
+
{
|
|
19309
|
+
ipv6Prefix: "2001:4860:4801:3b::/64"
|
|
19310
|
+
},
|
|
19311
|
+
{
|
|
19312
|
+
ipv6Prefix: "2001:4860:4801:3c::/64"
|
|
19313
|
+
},
|
|
19314
|
+
{
|
|
19315
|
+
ipv6Prefix: "2001:4860:4801:3d::/64"
|
|
19316
|
+
},
|
|
19317
|
+
{
|
|
19318
|
+
ipv6Prefix: "2001:4860:4801:3e::/64"
|
|
19319
|
+
},
|
|
19320
|
+
{
|
|
19321
|
+
ipv6Prefix: "2001:4860:4801:3f::/64"
|
|
19322
|
+
},
|
|
19323
|
+
{
|
|
19324
|
+
ipv6Prefix: "2001:4860:4801:40::/64"
|
|
19325
|
+
},
|
|
19326
|
+
{
|
|
19327
|
+
ipv6Prefix: "2001:4860:4801:41::/64"
|
|
19328
|
+
},
|
|
19329
|
+
{
|
|
19330
|
+
ipv6Prefix: "2001:4860:4801:42::/64"
|
|
19331
|
+
},
|
|
19332
|
+
{
|
|
19333
|
+
ipv6Prefix: "2001:4860:4801:44::/64"
|
|
19334
|
+
},
|
|
19335
|
+
{
|
|
19336
|
+
ipv6Prefix: "2001:4860:4801:45::/64"
|
|
19337
|
+
},
|
|
19338
|
+
{
|
|
19339
|
+
ipv6Prefix: "2001:4860:4801:46::/64"
|
|
19340
|
+
},
|
|
19341
|
+
{
|
|
19342
|
+
ipv6Prefix: "2001:4860:4801:47::/64"
|
|
19343
|
+
},
|
|
19344
|
+
{
|
|
19345
|
+
ipv6Prefix: "2001:4860:4801:48::/64"
|
|
19346
|
+
},
|
|
19347
|
+
{
|
|
19348
|
+
ipv6Prefix: "2001:4860:4801:49::/64"
|
|
19349
|
+
},
|
|
19350
|
+
{
|
|
19351
|
+
ipv6Prefix: "2001:4860:4801:4a::/64"
|
|
19352
|
+
},
|
|
19353
|
+
{
|
|
19354
|
+
ipv6Prefix: "2001:4860:4801:4b::/64"
|
|
19355
|
+
},
|
|
19356
|
+
{
|
|
19357
|
+
ipv6Prefix: "2001:4860:4801:4c::/64"
|
|
19358
|
+
},
|
|
19359
|
+
{
|
|
19360
|
+
ipv6Prefix: "2001:4860:4801:4d::/64"
|
|
19361
|
+
},
|
|
19362
|
+
{
|
|
19363
|
+
ipv6Prefix: "2001:4860:4801:4e::/64"
|
|
19364
|
+
},
|
|
19365
|
+
{
|
|
19366
|
+
ipv6Prefix: "2001:4860:4801:50::/64"
|
|
19367
|
+
},
|
|
19368
|
+
{
|
|
19369
|
+
ipv6Prefix: "2001:4860:4801:51::/64"
|
|
19370
|
+
},
|
|
19371
|
+
{
|
|
19372
|
+
ipv6Prefix: "2001:4860:4801:52::/64"
|
|
19373
|
+
},
|
|
19374
|
+
{
|
|
19375
|
+
ipv6Prefix: "2001:4860:4801:53::/64"
|
|
19376
|
+
},
|
|
19377
|
+
{
|
|
19378
|
+
ipv6Prefix: "2001:4860:4801:54::/64"
|
|
19379
|
+
},
|
|
19380
|
+
{
|
|
19381
|
+
ipv6Prefix: "2001:4860:4801:55::/64"
|
|
19382
|
+
},
|
|
19383
|
+
{
|
|
19384
|
+
ipv6Prefix: "2001:4860:4801:56::/64"
|
|
19385
|
+
},
|
|
19386
|
+
{
|
|
19387
|
+
ipv6Prefix: "2001:4860:4801:57::/64"
|
|
19388
|
+
},
|
|
19389
|
+
{
|
|
19390
|
+
ipv6Prefix: "2001:4860:4801:58::/64"
|
|
19391
|
+
},
|
|
19392
|
+
{
|
|
19393
|
+
ipv6Prefix: "2001:4860:4801:59::/64"
|
|
19394
|
+
},
|
|
19395
|
+
{
|
|
19396
|
+
ipv6Prefix: "2001:4860:4801:60::/64"
|
|
19397
|
+
},
|
|
19398
|
+
{
|
|
19399
|
+
ipv6Prefix: "2001:4860:4801:61::/64"
|
|
19400
|
+
},
|
|
19401
|
+
{
|
|
19402
|
+
ipv6Prefix: "2001:4860:4801:62::/64"
|
|
19403
|
+
},
|
|
19404
|
+
{
|
|
19405
|
+
ipv6Prefix: "2001:4860:4801:63::/64"
|
|
19406
|
+
},
|
|
19407
|
+
{
|
|
19408
|
+
ipv6Prefix: "2001:4860:4801:64::/64"
|
|
19409
|
+
},
|
|
19410
|
+
{
|
|
19411
|
+
ipv6Prefix: "2001:4860:4801:65::/64"
|
|
19412
|
+
},
|
|
19413
|
+
{
|
|
19414
|
+
ipv6Prefix: "2001:4860:4801:66::/64"
|
|
19415
|
+
},
|
|
19416
|
+
{
|
|
19417
|
+
ipv6Prefix: "2001:4860:4801:67::/64"
|
|
19418
|
+
},
|
|
19419
|
+
{
|
|
19420
|
+
ipv6Prefix: "2001:4860:4801:68::/64"
|
|
19421
|
+
},
|
|
19422
|
+
{
|
|
19423
|
+
ipv6Prefix: "2001:4860:4801:69::/64"
|
|
19424
|
+
},
|
|
19425
|
+
{
|
|
19426
|
+
ipv6Prefix: "2001:4860:4801:6a::/64"
|
|
19427
|
+
},
|
|
19428
|
+
{
|
|
19429
|
+
ipv6Prefix: "2001:4860:4801:6b::/64"
|
|
19430
|
+
},
|
|
19431
|
+
{
|
|
19432
|
+
ipv6Prefix: "2001:4860:4801:6c::/64"
|
|
19433
|
+
},
|
|
19434
|
+
{
|
|
19435
|
+
ipv6Prefix: "2001:4860:4801:6d::/64"
|
|
19436
|
+
},
|
|
19437
|
+
{
|
|
19438
|
+
ipv6Prefix: "2001:4860:4801:6e::/64"
|
|
19439
|
+
},
|
|
19440
|
+
{
|
|
19441
|
+
ipv6Prefix: "2001:4860:4801:6f::/64"
|
|
19442
|
+
},
|
|
19443
|
+
{
|
|
19444
|
+
ipv6Prefix: "2001:4860:4801:70::/64"
|
|
19445
|
+
},
|
|
19446
|
+
{
|
|
19447
|
+
ipv6Prefix: "2001:4860:4801:71::/64"
|
|
19448
|
+
},
|
|
19449
|
+
{
|
|
19450
|
+
ipv6Prefix: "2001:4860:4801:72::/64"
|
|
19451
|
+
},
|
|
19452
|
+
{
|
|
19453
|
+
ipv6Prefix: "2001:4860:4801:73::/64"
|
|
19454
|
+
},
|
|
19455
|
+
{
|
|
19456
|
+
ipv6Prefix: "2001:4860:4801:74::/64"
|
|
19457
|
+
},
|
|
19458
|
+
{
|
|
19459
|
+
ipv6Prefix: "2001:4860:4801:75::/64"
|
|
19460
|
+
},
|
|
19461
|
+
{
|
|
19462
|
+
ipv6Prefix: "2001:4860:4801:76::/64"
|
|
19463
|
+
},
|
|
19464
|
+
{
|
|
19465
|
+
ipv6Prefix: "2001:4860:4801:77::/64"
|
|
19466
|
+
},
|
|
19467
|
+
{
|
|
19468
|
+
ipv6Prefix: "2001:4860:4801:78::/64"
|
|
19469
|
+
},
|
|
19470
|
+
{
|
|
19471
|
+
ipv6Prefix: "2001:4860:4801:79::/64"
|
|
19472
|
+
},
|
|
19473
|
+
{
|
|
19474
|
+
ipv6Prefix: "2001:4860:4801:7a::/64"
|
|
19475
|
+
},
|
|
19476
|
+
{
|
|
19477
|
+
ipv6Prefix: "2001:4860:4801:7b::/64"
|
|
19478
|
+
},
|
|
19479
|
+
{
|
|
19480
|
+
ipv6Prefix: "2001:4860:4801:7c::/64"
|
|
19481
|
+
},
|
|
19482
|
+
{
|
|
19483
|
+
ipv6Prefix: "2001:4860:4801:7d::/64"
|
|
19484
|
+
},
|
|
19485
|
+
{
|
|
19486
|
+
ipv6Prefix: "2001:4860:4801:80::/64"
|
|
19487
|
+
},
|
|
19488
|
+
{
|
|
19489
|
+
ipv6Prefix: "2001:4860:4801:81::/64"
|
|
19490
|
+
},
|
|
19491
|
+
{
|
|
19492
|
+
ipv6Prefix: "2001:4860:4801:82::/64"
|
|
19493
|
+
},
|
|
19494
|
+
{
|
|
19495
|
+
ipv6Prefix: "2001:4860:4801:83::/64"
|
|
19496
|
+
},
|
|
19497
|
+
{
|
|
19498
|
+
ipv6Prefix: "2001:4860:4801:84::/64"
|
|
19499
|
+
},
|
|
19500
|
+
{
|
|
19501
|
+
ipv6Prefix: "2001:4860:4801:85::/64"
|
|
19502
|
+
},
|
|
19503
|
+
{
|
|
19504
|
+
ipv6Prefix: "2001:4860:4801:86::/64"
|
|
19505
|
+
},
|
|
19506
|
+
{
|
|
19507
|
+
ipv6Prefix: "2001:4860:4801:87::/64"
|
|
19508
|
+
},
|
|
19509
|
+
{
|
|
19510
|
+
ipv6Prefix: "2001:4860:4801:88::/64"
|
|
19511
|
+
},
|
|
19512
|
+
{
|
|
19513
|
+
ipv6Prefix: "2001:4860:4801:90::/64"
|
|
19514
|
+
},
|
|
19515
|
+
{
|
|
19516
|
+
ipv6Prefix: "2001:4860:4801:91::/64"
|
|
19517
|
+
},
|
|
19518
|
+
{
|
|
19519
|
+
ipv6Prefix: "2001:4860:4801:92::/64"
|
|
19520
|
+
},
|
|
19521
|
+
{
|
|
19522
|
+
ipv6Prefix: "2001:4860:4801:93::/64"
|
|
19523
|
+
},
|
|
19524
|
+
{
|
|
19525
|
+
ipv6Prefix: "2001:4860:4801:94::/64"
|
|
19526
|
+
},
|
|
19527
|
+
{
|
|
19528
|
+
ipv6Prefix: "2001:4860:4801:95::/64"
|
|
19529
|
+
},
|
|
19530
|
+
{
|
|
19531
|
+
ipv6Prefix: "2001:4860:4801:96::/64"
|
|
19532
|
+
},
|
|
19533
|
+
{
|
|
19534
|
+
ipv6Prefix: "2001:4860:4801:97::/64"
|
|
19535
|
+
},
|
|
19536
|
+
{
|
|
19537
|
+
ipv6Prefix: "2001:4860:4801:a0::/64"
|
|
19538
|
+
},
|
|
19539
|
+
{
|
|
19540
|
+
ipv6Prefix: "2001:4860:4801:a1::/64"
|
|
19541
|
+
},
|
|
19542
|
+
{
|
|
19543
|
+
ipv6Prefix: "2001:4860:4801:a2::/64"
|
|
19544
|
+
},
|
|
19545
|
+
{
|
|
19546
|
+
ipv6Prefix: "2001:4860:4801:a3::/64"
|
|
19547
|
+
},
|
|
19548
|
+
{
|
|
19549
|
+
ipv6Prefix: "2001:4860:4801:a4::/64"
|
|
19550
|
+
},
|
|
19551
|
+
{
|
|
19552
|
+
ipv6Prefix: "2001:4860:4801:a5::/64"
|
|
19553
|
+
},
|
|
19554
|
+
{
|
|
19555
|
+
ipv6Prefix: "2001:4860:4801:a6::/64"
|
|
19556
|
+
},
|
|
19557
|
+
{
|
|
19558
|
+
ipv6Prefix: "2001:4860:4801:a7::/64"
|
|
19559
|
+
},
|
|
19560
|
+
{
|
|
19561
|
+
ipv6Prefix: "2001:4860:4801:a8::/64"
|
|
19562
|
+
},
|
|
19563
|
+
{
|
|
19564
|
+
ipv6Prefix: "2001:4860:4801:a9::/64"
|
|
19565
|
+
},
|
|
19566
|
+
{
|
|
19567
|
+
ipv6Prefix: "2001:4860:4801:aa::/64"
|
|
19568
|
+
},
|
|
19569
|
+
{
|
|
19570
|
+
ipv6Prefix: "2001:4860:4801:ab::/64"
|
|
19571
|
+
},
|
|
19572
|
+
{
|
|
19573
|
+
ipv6Prefix: "2001:4860:4801:ac::/64"
|
|
19574
|
+
},
|
|
19575
|
+
{
|
|
19576
|
+
ipv6Prefix: "2001:4860:4801:ad::/64"
|
|
19577
|
+
},
|
|
19578
|
+
{
|
|
19579
|
+
ipv6Prefix: "2001:4860:4801:ae::/64"
|
|
19580
|
+
},
|
|
19581
|
+
{
|
|
19582
|
+
ipv6Prefix: "2001:4860:4801:b0::/64"
|
|
19583
|
+
},
|
|
19584
|
+
{
|
|
19585
|
+
ipv6Prefix: "2001:4860:4801:b1::/64"
|
|
19586
|
+
},
|
|
19587
|
+
{
|
|
19588
|
+
ipv6Prefix: "2001:4860:4801:b2::/64"
|
|
19589
|
+
},
|
|
19590
|
+
{
|
|
19591
|
+
ipv6Prefix: "2001:4860:4801:b3::/64"
|
|
19592
|
+
},
|
|
19593
|
+
{
|
|
19594
|
+
ipv6Prefix: "2001:4860:4801:b4::/64"
|
|
19595
|
+
},
|
|
19596
|
+
{
|
|
19597
|
+
ipv6Prefix: "2001:4860:4801:b5::/64"
|
|
19598
|
+
},
|
|
19599
|
+
{
|
|
19600
|
+
ipv6Prefix: "2001:4860:4801:b6::/64"
|
|
19601
|
+
},
|
|
19602
|
+
{
|
|
19603
|
+
ipv6Prefix: "2001:4860:4801:c::/64"
|
|
19604
|
+
},
|
|
19605
|
+
{
|
|
19606
|
+
ipv6Prefix: "2001:4860:4801:f::/64"
|
|
19607
|
+
},
|
|
19608
|
+
{
|
|
19609
|
+
ipv4Prefix: "192.178.4.0/27"
|
|
19610
|
+
},
|
|
19611
|
+
{
|
|
19612
|
+
ipv4Prefix: "192.178.4.128/27"
|
|
19613
|
+
},
|
|
19614
|
+
{
|
|
19615
|
+
ipv4Prefix: "192.178.4.160/27"
|
|
19616
|
+
},
|
|
19617
|
+
{
|
|
19618
|
+
ipv4Prefix: "192.178.4.192/27"
|
|
19619
|
+
},
|
|
19620
|
+
{
|
|
19621
|
+
ipv4Prefix: "192.178.4.224/27"
|
|
19622
|
+
},
|
|
19623
|
+
{
|
|
19624
|
+
ipv4Prefix: "192.178.4.32/27"
|
|
19625
|
+
},
|
|
19626
|
+
{
|
|
19627
|
+
ipv4Prefix: "192.178.4.64/27"
|
|
19628
|
+
},
|
|
19629
|
+
{
|
|
19630
|
+
ipv4Prefix: "192.178.4.96/27"
|
|
19631
|
+
},
|
|
19632
|
+
{
|
|
19633
|
+
ipv4Prefix: "192.178.5.0/27"
|
|
19634
|
+
},
|
|
19635
|
+
{
|
|
19636
|
+
ipv4Prefix: "192.178.6.0/27"
|
|
19637
|
+
},
|
|
19638
|
+
{
|
|
19639
|
+
ipv4Prefix: "192.178.6.128/27"
|
|
19640
|
+
},
|
|
19641
|
+
{
|
|
19642
|
+
ipv4Prefix: "192.178.6.160/27"
|
|
19643
|
+
},
|
|
19644
|
+
{
|
|
19645
|
+
ipv4Prefix: "192.178.6.192/27"
|
|
19646
|
+
},
|
|
19647
|
+
{
|
|
19648
|
+
ipv4Prefix: "192.178.6.224/27"
|
|
19649
|
+
},
|
|
19650
|
+
{
|
|
19651
|
+
ipv4Prefix: "192.178.6.32/27"
|
|
19652
|
+
},
|
|
19653
|
+
{
|
|
19654
|
+
ipv4Prefix: "192.178.6.64/27"
|
|
19655
|
+
},
|
|
19656
|
+
{
|
|
19657
|
+
ipv4Prefix: "192.178.6.96/27"
|
|
19658
|
+
},
|
|
19659
|
+
{
|
|
19660
|
+
ipv4Prefix: "192.178.7.0/27"
|
|
19661
|
+
},
|
|
19662
|
+
{
|
|
19663
|
+
ipv4Prefix: "192.178.7.128/27"
|
|
19664
|
+
},
|
|
19665
|
+
{
|
|
19666
|
+
ipv4Prefix: "192.178.7.160/27"
|
|
19667
|
+
},
|
|
19668
|
+
{
|
|
19669
|
+
ipv4Prefix: "192.178.7.192/27"
|
|
19670
|
+
},
|
|
19671
|
+
{
|
|
19672
|
+
ipv4Prefix: "192.178.7.224/27"
|
|
19673
|
+
},
|
|
19674
|
+
{
|
|
19675
|
+
ipv4Prefix: "192.178.7.32/27"
|
|
19676
|
+
},
|
|
19677
|
+
{
|
|
19678
|
+
ipv4Prefix: "192.178.7.64/27"
|
|
19679
|
+
},
|
|
19680
|
+
{
|
|
19681
|
+
ipv4Prefix: "192.178.7.96/27"
|
|
19682
|
+
},
|
|
19683
|
+
{
|
|
19684
|
+
ipv4Prefix: "34.100.182.96/28"
|
|
19685
|
+
},
|
|
19686
|
+
{
|
|
19687
|
+
ipv4Prefix: "34.101.50.144/28"
|
|
19688
|
+
},
|
|
19689
|
+
{
|
|
19690
|
+
ipv4Prefix: "34.118.254.0/28"
|
|
19691
|
+
},
|
|
19692
|
+
{
|
|
19693
|
+
ipv4Prefix: "34.118.66.0/28"
|
|
19694
|
+
},
|
|
19695
|
+
{
|
|
19696
|
+
ipv4Prefix: "34.126.178.96/28"
|
|
19697
|
+
},
|
|
19698
|
+
{
|
|
19699
|
+
ipv4Prefix: "34.146.150.144/28"
|
|
19700
|
+
},
|
|
19701
|
+
{
|
|
19702
|
+
ipv4Prefix: "34.147.110.144/28"
|
|
19703
|
+
},
|
|
19704
|
+
{
|
|
19705
|
+
ipv4Prefix: "34.151.74.144/28"
|
|
19706
|
+
},
|
|
19707
|
+
{
|
|
19708
|
+
ipv4Prefix: "34.152.50.64/28"
|
|
19709
|
+
},
|
|
19710
|
+
{
|
|
19711
|
+
ipv4Prefix: "34.154.114.144/28"
|
|
19712
|
+
},
|
|
19713
|
+
{
|
|
19714
|
+
ipv4Prefix: "34.155.98.32/28"
|
|
19715
|
+
},
|
|
19716
|
+
{
|
|
19717
|
+
ipv4Prefix: "34.165.18.176/28"
|
|
19718
|
+
},
|
|
19719
|
+
{
|
|
19720
|
+
ipv4Prefix: "34.175.160.64/28"
|
|
19721
|
+
},
|
|
19722
|
+
{
|
|
19723
|
+
ipv4Prefix: "34.176.130.16/28"
|
|
19724
|
+
},
|
|
19725
|
+
{
|
|
19726
|
+
ipv4Prefix: "34.22.85.0/27"
|
|
19727
|
+
},
|
|
19728
|
+
{
|
|
19729
|
+
ipv4Prefix: "34.64.82.64/28"
|
|
19730
|
+
},
|
|
19731
|
+
{
|
|
19732
|
+
ipv4Prefix: "34.65.242.112/28"
|
|
19733
|
+
},
|
|
19734
|
+
{
|
|
19735
|
+
ipv4Prefix: "34.80.50.80/28"
|
|
19736
|
+
},
|
|
19737
|
+
{
|
|
19738
|
+
ipv4Prefix: "34.88.194.0/28"
|
|
19739
|
+
},
|
|
19740
|
+
{
|
|
19741
|
+
ipv4Prefix: "34.89.10.80/28"
|
|
19742
|
+
},
|
|
19743
|
+
{
|
|
19744
|
+
ipv4Prefix: "34.89.198.80/28"
|
|
19745
|
+
},
|
|
19746
|
+
{
|
|
19747
|
+
ipv4Prefix: "34.96.162.48/28"
|
|
19748
|
+
},
|
|
19749
|
+
{
|
|
19750
|
+
ipv4Prefix: "35.247.243.240/28"
|
|
19751
|
+
},
|
|
19752
|
+
{
|
|
19753
|
+
ipv4Prefix: "66.249.64.0/27"
|
|
19754
|
+
},
|
|
19755
|
+
{
|
|
19756
|
+
ipv4Prefix: "66.249.64.128/27"
|
|
19757
|
+
},
|
|
19758
|
+
{
|
|
19759
|
+
ipv4Prefix: "66.249.64.160/27"
|
|
19760
|
+
},
|
|
19761
|
+
{
|
|
19762
|
+
ipv4Prefix: "66.249.64.192/27"
|
|
19763
|
+
},
|
|
19764
|
+
{
|
|
19765
|
+
ipv4Prefix: "66.249.64.224/27"
|
|
19766
|
+
},
|
|
19767
|
+
{
|
|
19768
|
+
ipv4Prefix: "66.249.64.32/27"
|
|
19769
|
+
},
|
|
19770
|
+
{
|
|
19771
|
+
ipv4Prefix: "66.249.64.64/27"
|
|
19772
|
+
},
|
|
19773
|
+
{
|
|
19774
|
+
ipv4Prefix: "66.249.64.96/27"
|
|
19775
|
+
},
|
|
19776
|
+
{
|
|
19777
|
+
ipv4Prefix: "66.249.65.0/27"
|
|
19778
|
+
},
|
|
19779
|
+
{
|
|
19780
|
+
ipv4Prefix: "66.249.65.128/27"
|
|
19781
|
+
},
|
|
19782
|
+
{
|
|
19783
|
+
ipv4Prefix: "66.249.65.160/27"
|
|
19784
|
+
},
|
|
19785
|
+
{
|
|
19786
|
+
ipv4Prefix: "66.249.65.192/27"
|
|
19787
|
+
},
|
|
19788
|
+
{
|
|
19789
|
+
ipv4Prefix: "66.249.65.224/27"
|
|
19790
|
+
},
|
|
19791
|
+
{
|
|
19792
|
+
ipv4Prefix: "66.249.65.32/27"
|
|
19793
|
+
},
|
|
19794
|
+
{
|
|
19795
|
+
ipv4Prefix: "66.249.65.64/27"
|
|
19796
|
+
},
|
|
19797
|
+
{
|
|
19798
|
+
ipv4Prefix: "66.249.65.96/27"
|
|
19799
|
+
},
|
|
19800
|
+
{
|
|
19801
|
+
ipv4Prefix: "66.249.66.0/27"
|
|
19802
|
+
},
|
|
19803
|
+
{
|
|
19804
|
+
ipv4Prefix: "66.249.66.128/27"
|
|
19805
|
+
},
|
|
19806
|
+
{
|
|
19807
|
+
ipv4Prefix: "66.249.66.160/27"
|
|
19808
|
+
},
|
|
19809
|
+
{
|
|
19810
|
+
ipv4Prefix: "66.249.66.192/27"
|
|
19811
|
+
},
|
|
19812
|
+
{
|
|
19813
|
+
ipv4Prefix: "66.249.66.224/27"
|
|
19814
|
+
},
|
|
19815
|
+
{
|
|
19816
|
+
ipv4Prefix: "66.249.66.32/27"
|
|
19817
|
+
},
|
|
19818
|
+
{
|
|
19819
|
+
ipv4Prefix: "66.249.66.64/27"
|
|
19820
|
+
},
|
|
19821
|
+
{
|
|
19822
|
+
ipv4Prefix: "66.249.66.96/27"
|
|
19823
|
+
},
|
|
19824
|
+
{
|
|
19825
|
+
ipv4Prefix: "66.249.67.0/27"
|
|
19826
|
+
},
|
|
19827
|
+
{
|
|
19828
|
+
ipv4Prefix: "66.249.67.32/27"
|
|
19829
|
+
},
|
|
19830
|
+
{
|
|
19831
|
+
ipv4Prefix: "66.249.67.64/27"
|
|
19832
|
+
},
|
|
19833
|
+
{
|
|
19834
|
+
ipv4Prefix: "66.249.68.0/27"
|
|
19835
|
+
},
|
|
19836
|
+
{
|
|
19837
|
+
ipv4Prefix: "66.249.68.128/27"
|
|
19838
|
+
},
|
|
19839
|
+
{
|
|
19840
|
+
ipv4Prefix: "66.249.68.160/27"
|
|
19841
|
+
},
|
|
19842
|
+
{
|
|
19843
|
+
ipv4Prefix: "66.249.68.192/27"
|
|
19844
|
+
},
|
|
19845
|
+
{
|
|
19846
|
+
ipv4Prefix: "66.249.68.32/27"
|
|
19847
|
+
},
|
|
19848
|
+
{
|
|
19849
|
+
ipv4Prefix: "66.249.68.64/27"
|
|
19850
|
+
},
|
|
19851
|
+
{
|
|
19852
|
+
ipv4Prefix: "66.249.68.96/27"
|
|
19853
|
+
},
|
|
19854
|
+
{
|
|
19855
|
+
ipv4Prefix: "66.249.69.0/27"
|
|
19856
|
+
},
|
|
19857
|
+
{
|
|
19858
|
+
ipv4Prefix: "66.249.69.128/27"
|
|
19859
|
+
},
|
|
19860
|
+
{
|
|
19861
|
+
ipv4Prefix: "66.249.69.160/27"
|
|
19862
|
+
},
|
|
19863
|
+
{
|
|
19864
|
+
ipv4Prefix: "66.249.69.192/27"
|
|
19865
|
+
},
|
|
19866
|
+
{
|
|
19867
|
+
ipv4Prefix: "66.249.69.224/27"
|
|
19868
|
+
},
|
|
19869
|
+
{
|
|
19870
|
+
ipv4Prefix: "66.249.69.32/27"
|
|
19871
|
+
},
|
|
19872
|
+
{
|
|
19873
|
+
ipv4Prefix: "66.249.69.64/27"
|
|
19874
|
+
},
|
|
19875
|
+
{
|
|
19876
|
+
ipv4Prefix: "66.249.69.96/27"
|
|
19877
|
+
},
|
|
19878
|
+
{
|
|
19879
|
+
ipv4Prefix: "66.249.70.0/27"
|
|
19880
|
+
},
|
|
19881
|
+
{
|
|
19882
|
+
ipv4Prefix: "66.249.70.128/27"
|
|
19883
|
+
},
|
|
19884
|
+
{
|
|
19885
|
+
ipv4Prefix: "66.249.70.160/27"
|
|
19886
|
+
},
|
|
19887
|
+
{
|
|
19888
|
+
ipv4Prefix: "66.249.70.192/27"
|
|
19889
|
+
},
|
|
19890
|
+
{
|
|
19891
|
+
ipv4Prefix: "66.249.70.224/27"
|
|
19892
|
+
},
|
|
19893
|
+
{
|
|
19894
|
+
ipv4Prefix: "66.249.70.32/27"
|
|
19895
|
+
},
|
|
19896
|
+
{
|
|
19897
|
+
ipv4Prefix: "66.249.70.64/27"
|
|
19898
|
+
},
|
|
19899
|
+
{
|
|
19900
|
+
ipv4Prefix: "66.249.70.96/27"
|
|
19901
|
+
},
|
|
19902
|
+
{
|
|
19903
|
+
ipv4Prefix: "66.249.71.0/27"
|
|
19904
|
+
},
|
|
19905
|
+
{
|
|
19906
|
+
ipv4Prefix: "66.249.71.128/27"
|
|
19907
|
+
},
|
|
19908
|
+
{
|
|
19909
|
+
ipv4Prefix: "66.249.71.160/27"
|
|
19910
|
+
},
|
|
19911
|
+
{
|
|
19912
|
+
ipv4Prefix: "66.249.71.192/27"
|
|
19913
|
+
},
|
|
19914
|
+
{
|
|
19915
|
+
ipv4Prefix: "66.249.71.224/27"
|
|
19916
|
+
},
|
|
19917
|
+
{
|
|
19918
|
+
ipv4Prefix: "66.249.71.32/27"
|
|
19919
|
+
},
|
|
19920
|
+
{
|
|
19921
|
+
ipv4Prefix: "66.249.71.64/27"
|
|
19922
|
+
},
|
|
19923
|
+
{
|
|
19924
|
+
ipv4Prefix: "66.249.71.96/27"
|
|
19925
|
+
},
|
|
19926
|
+
{
|
|
19927
|
+
ipv4Prefix: "66.249.72.0/27"
|
|
19928
|
+
},
|
|
19929
|
+
{
|
|
19930
|
+
ipv4Prefix: "66.249.72.128/27"
|
|
19931
|
+
},
|
|
19932
|
+
{
|
|
19933
|
+
ipv4Prefix: "66.249.72.160/27"
|
|
19934
|
+
},
|
|
19935
|
+
{
|
|
19936
|
+
ipv4Prefix: "66.249.72.192/27"
|
|
19937
|
+
},
|
|
19938
|
+
{
|
|
19939
|
+
ipv4Prefix: "66.249.72.224/27"
|
|
19940
|
+
},
|
|
19941
|
+
{
|
|
19942
|
+
ipv4Prefix: "66.249.72.32/27"
|
|
19943
|
+
},
|
|
19944
|
+
{
|
|
19945
|
+
ipv4Prefix: "66.249.72.64/27"
|
|
19946
|
+
},
|
|
19947
|
+
{
|
|
19948
|
+
ipv4Prefix: "66.249.72.96/27"
|
|
19949
|
+
},
|
|
19950
|
+
{
|
|
19951
|
+
ipv4Prefix: "66.249.73.0/27"
|
|
19952
|
+
},
|
|
19953
|
+
{
|
|
19954
|
+
ipv4Prefix: "66.249.73.128/27"
|
|
19955
|
+
},
|
|
19956
|
+
{
|
|
19957
|
+
ipv4Prefix: "66.249.73.160/27"
|
|
19958
|
+
},
|
|
19959
|
+
{
|
|
19960
|
+
ipv4Prefix: "66.249.73.192/27"
|
|
19961
|
+
},
|
|
19962
|
+
{
|
|
19963
|
+
ipv4Prefix: "66.249.73.224/27"
|
|
19964
|
+
},
|
|
19965
|
+
{
|
|
19966
|
+
ipv4Prefix: "66.249.73.32/27"
|
|
19967
|
+
},
|
|
19968
|
+
{
|
|
19969
|
+
ipv4Prefix: "66.249.73.64/27"
|
|
19970
|
+
},
|
|
19971
|
+
{
|
|
19972
|
+
ipv4Prefix: "66.249.73.96/27"
|
|
19973
|
+
},
|
|
19974
|
+
{
|
|
19975
|
+
ipv4Prefix: "66.249.74.0/27"
|
|
19976
|
+
},
|
|
19977
|
+
{
|
|
19978
|
+
ipv4Prefix: "66.249.74.128/27"
|
|
19979
|
+
},
|
|
19980
|
+
{
|
|
19981
|
+
ipv4Prefix: "66.249.74.160/27"
|
|
19982
|
+
},
|
|
19983
|
+
{
|
|
19984
|
+
ipv4Prefix: "66.249.74.192/27"
|
|
19985
|
+
},
|
|
19986
|
+
{
|
|
19987
|
+
ipv4Prefix: "66.249.74.224/27"
|
|
19988
|
+
},
|
|
19989
|
+
{
|
|
19990
|
+
ipv4Prefix: "66.249.74.32/27"
|
|
19991
|
+
},
|
|
19992
|
+
{
|
|
19993
|
+
ipv4Prefix: "66.249.74.64/27"
|
|
19994
|
+
},
|
|
19995
|
+
{
|
|
19996
|
+
ipv4Prefix: "66.249.74.96/27"
|
|
19997
|
+
},
|
|
19998
|
+
{
|
|
19999
|
+
ipv4Prefix: "66.249.75.0/27"
|
|
20000
|
+
},
|
|
20001
|
+
{
|
|
20002
|
+
ipv4Prefix: "66.249.75.128/27"
|
|
20003
|
+
},
|
|
20004
|
+
{
|
|
20005
|
+
ipv4Prefix: "66.249.75.160/27"
|
|
20006
|
+
},
|
|
20007
|
+
{
|
|
20008
|
+
ipv4Prefix: "66.249.75.192/27"
|
|
20009
|
+
},
|
|
20010
|
+
{
|
|
20011
|
+
ipv4Prefix: "66.249.75.224/27"
|
|
20012
|
+
},
|
|
20013
|
+
{
|
|
20014
|
+
ipv4Prefix: "66.249.75.32/27"
|
|
20015
|
+
},
|
|
20016
|
+
{
|
|
20017
|
+
ipv4Prefix: "66.249.75.64/27"
|
|
20018
|
+
},
|
|
20019
|
+
{
|
|
20020
|
+
ipv4Prefix: "66.249.75.96/27"
|
|
20021
|
+
},
|
|
20022
|
+
{
|
|
20023
|
+
ipv4Prefix: "66.249.76.0/27"
|
|
20024
|
+
},
|
|
20025
|
+
{
|
|
20026
|
+
ipv4Prefix: "66.249.76.128/27"
|
|
20027
|
+
},
|
|
20028
|
+
{
|
|
20029
|
+
ipv4Prefix: "66.249.76.160/27"
|
|
20030
|
+
},
|
|
20031
|
+
{
|
|
20032
|
+
ipv4Prefix: "66.249.76.192/27"
|
|
20033
|
+
},
|
|
20034
|
+
{
|
|
20035
|
+
ipv4Prefix: "66.249.76.224/27"
|
|
20036
|
+
},
|
|
20037
|
+
{
|
|
20038
|
+
ipv4Prefix: "66.249.76.32/27"
|
|
20039
|
+
},
|
|
20040
|
+
{
|
|
20041
|
+
ipv4Prefix: "66.249.76.64/27"
|
|
20042
|
+
},
|
|
20043
|
+
{
|
|
20044
|
+
ipv4Prefix: "66.249.76.96/27"
|
|
20045
|
+
},
|
|
20046
|
+
{
|
|
20047
|
+
ipv4Prefix: "66.249.77.0/27"
|
|
20048
|
+
},
|
|
20049
|
+
{
|
|
20050
|
+
ipv4Prefix: "66.249.77.128/27"
|
|
20051
|
+
},
|
|
20052
|
+
{
|
|
20053
|
+
ipv4Prefix: "66.249.77.160/27"
|
|
20054
|
+
},
|
|
20055
|
+
{
|
|
20056
|
+
ipv4Prefix: "66.249.77.192/27"
|
|
20057
|
+
},
|
|
20058
|
+
{
|
|
20059
|
+
ipv4Prefix: "66.249.77.224/27"
|
|
20060
|
+
},
|
|
20061
|
+
{
|
|
20062
|
+
ipv4Prefix: "66.249.77.32/27"
|
|
20063
|
+
},
|
|
20064
|
+
{
|
|
20065
|
+
ipv4Prefix: "66.249.77.64/27"
|
|
20066
|
+
},
|
|
20067
|
+
{
|
|
20068
|
+
ipv4Prefix: "66.249.77.96/27"
|
|
20069
|
+
},
|
|
20070
|
+
{
|
|
20071
|
+
ipv4Prefix: "66.249.78.0/27"
|
|
20072
|
+
},
|
|
20073
|
+
{
|
|
20074
|
+
ipv4Prefix: "66.249.78.128/27"
|
|
20075
|
+
},
|
|
20076
|
+
{
|
|
20077
|
+
ipv4Prefix: "66.249.78.160/27"
|
|
20078
|
+
},
|
|
20079
|
+
{
|
|
20080
|
+
ipv4Prefix: "66.249.78.32/27"
|
|
20081
|
+
},
|
|
20082
|
+
{
|
|
20083
|
+
ipv4Prefix: "66.249.78.64/27"
|
|
20084
|
+
},
|
|
20085
|
+
{
|
|
20086
|
+
ipv4Prefix: "66.249.78.96/27"
|
|
20087
|
+
},
|
|
20088
|
+
{
|
|
20089
|
+
ipv4Prefix: "66.249.79.0/27"
|
|
20090
|
+
},
|
|
20091
|
+
{
|
|
20092
|
+
ipv4Prefix: "66.249.79.128/27"
|
|
20093
|
+
},
|
|
20094
|
+
{
|
|
20095
|
+
ipv4Prefix: "66.249.79.160/27"
|
|
20096
|
+
},
|
|
20097
|
+
{
|
|
20098
|
+
ipv4Prefix: "66.249.79.192/27"
|
|
20099
|
+
},
|
|
20100
|
+
{
|
|
20101
|
+
ipv4Prefix: "66.249.79.224/27"
|
|
20102
|
+
},
|
|
20103
|
+
{
|
|
20104
|
+
ipv4Prefix: "66.249.79.32/27"
|
|
20105
|
+
},
|
|
20106
|
+
{
|
|
20107
|
+
ipv4Prefix: "66.249.79.64/27"
|
|
20108
|
+
}
|
|
20109
|
+
]
|
|
20110
|
+
};
|
|
20111
|
+
|
|
20112
|
+
// ../integration-traffic/src/ip-ranges/gptbot.json
|
|
20113
|
+
var gptbot_default = {
|
|
20114
|
+
_source: "https://openai.com/gptbot.json",
|
|
20115
|
+
creationTime: "2025-10-30T11:00:00.000000",
|
|
20116
|
+
prefixes: [
|
|
20117
|
+
{
|
|
20118
|
+
ipv4Prefix: "132.196.86.0/24"
|
|
20119
|
+
},
|
|
20120
|
+
{
|
|
20121
|
+
ipv4Prefix: "172.182.202.0/25"
|
|
20122
|
+
},
|
|
20123
|
+
{
|
|
20124
|
+
ipv4Prefix: "172.182.204.0/24"
|
|
20125
|
+
},
|
|
20126
|
+
{
|
|
20127
|
+
ipv4Prefix: "172.182.207.0/25"
|
|
20128
|
+
},
|
|
20129
|
+
{
|
|
20130
|
+
ipv4Prefix: "172.182.214.0/24"
|
|
20131
|
+
},
|
|
20132
|
+
{
|
|
20133
|
+
ipv4Prefix: "172.182.215.0/24"
|
|
20134
|
+
},
|
|
20135
|
+
{
|
|
20136
|
+
ipv4Prefix: "20.125.66.80/28"
|
|
20137
|
+
},
|
|
20138
|
+
{
|
|
20139
|
+
ipv4Prefix: "20.171.206.0/24"
|
|
20140
|
+
},
|
|
20141
|
+
{
|
|
20142
|
+
ipv4Prefix: "20.171.207.0/24"
|
|
20143
|
+
},
|
|
20144
|
+
{
|
|
20145
|
+
ipv4Prefix: "4.227.36.0/25"
|
|
20146
|
+
},
|
|
20147
|
+
{
|
|
20148
|
+
ipv4Prefix: "52.230.152.0/24"
|
|
20149
|
+
},
|
|
20150
|
+
{
|
|
20151
|
+
ipv4Prefix: "74.7.175.128/25"
|
|
20152
|
+
},
|
|
20153
|
+
{
|
|
20154
|
+
ipv4Prefix: "74.7.227.0/25"
|
|
20155
|
+
},
|
|
20156
|
+
{
|
|
20157
|
+
ipv4Prefix: "74.7.227.128/25"
|
|
20158
|
+
},
|
|
20159
|
+
{
|
|
20160
|
+
ipv4Prefix: "74.7.228.0/25"
|
|
20161
|
+
},
|
|
20162
|
+
{
|
|
20163
|
+
ipv4Prefix: "74.7.230.0/25"
|
|
20164
|
+
},
|
|
20165
|
+
{
|
|
20166
|
+
ipv4Prefix: "74.7.241.0/25"
|
|
20167
|
+
},
|
|
20168
|
+
{
|
|
20169
|
+
ipv4Prefix: "74.7.241.128/25"
|
|
20170
|
+
},
|
|
20171
|
+
{
|
|
20172
|
+
ipv4Prefix: "74.7.242.0/25"
|
|
20173
|
+
},
|
|
20174
|
+
{
|
|
20175
|
+
ipv4Prefix: "74.7.243.128/25"
|
|
20176
|
+
},
|
|
20177
|
+
{
|
|
20178
|
+
ipv4Prefix: "74.7.244.0/25"
|
|
20179
|
+
}
|
|
20180
|
+
]
|
|
20181
|
+
};
|
|
20182
|
+
|
|
20183
|
+
// ../integration-traffic/src/ip-ranges/oai-searchbot.json
|
|
20184
|
+
var oai_searchbot_default = {
|
|
20185
|
+
_source: "https://openai.com/searchbot.json",
|
|
20186
|
+
creationTime: "2026-01-02T11:00:00.000000",
|
|
20187
|
+
prefixes: [
|
|
20188
|
+
{
|
|
20189
|
+
ipv4Prefix: "104.210.140.128/28"
|
|
20190
|
+
},
|
|
20191
|
+
{
|
|
20192
|
+
ipv4Prefix: "135.234.64.0/24"
|
|
20193
|
+
},
|
|
20194
|
+
{
|
|
20195
|
+
ipv4Prefix: "172.182.193.224/28"
|
|
20196
|
+
},
|
|
20197
|
+
{
|
|
20198
|
+
ipv4Prefix: "172.182.193.80/28"
|
|
20199
|
+
},
|
|
20200
|
+
{
|
|
20201
|
+
ipv4Prefix: "172.182.194.144/28"
|
|
20202
|
+
},
|
|
20203
|
+
{
|
|
20204
|
+
ipv4Prefix: "172.182.194.32/28"
|
|
20205
|
+
},
|
|
20206
|
+
{
|
|
20207
|
+
ipv4Prefix: "172.182.195.48/28"
|
|
20208
|
+
},
|
|
20209
|
+
{
|
|
20210
|
+
ipv4Prefix: "172.182.209.208/28"
|
|
20211
|
+
},
|
|
20212
|
+
{
|
|
20213
|
+
ipv4Prefix: "172.182.211.192/28"
|
|
20214
|
+
},
|
|
20215
|
+
{
|
|
20216
|
+
ipv4Prefix: "172.182.213.192/28"
|
|
20217
|
+
},
|
|
20218
|
+
{
|
|
20219
|
+
ipv4Prefix: "172.182.224.0/28"
|
|
20220
|
+
},
|
|
20221
|
+
{
|
|
20222
|
+
ipv4Prefix: "172.203.190.128/28"
|
|
20223
|
+
},
|
|
20224
|
+
{
|
|
20225
|
+
ipv4Prefix: "20.14.99.96/28"
|
|
20226
|
+
},
|
|
20227
|
+
{
|
|
20228
|
+
ipv4Prefix: "20.168.18.32/28"
|
|
20229
|
+
},
|
|
20230
|
+
{
|
|
20231
|
+
ipv4Prefix: "20.169.6.224/28"
|
|
20232
|
+
},
|
|
20233
|
+
{
|
|
20234
|
+
ipv4Prefix: "20.169.7.48/28"
|
|
20235
|
+
},
|
|
20236
|
+
{
|
|
20237
|
+
ipv4Prefix: "20.169.77.0/25"
|
|
20238
|
+
},
|
|
20239
|
+
{
|
|
20240
|
+
ipv4Prefix: "20.171.123.64/28"
|
|
20241
|
+
},
|
|
20242
|
+
{
|
|
20243
|
+
ipv4Prefix: "20.171.53.224/28"
|
|
20244
|
+
},
|
|
20245
|
+
{
|
|
20246
|
+
ipv4Prefix: "20.25.151.224/28"
|
|
20247
|
+
},
|
|
20248
|
+
{
|
|
20249
|
+
ipv4Prefix: "20.42.10.176/28"
|
|
20250
|
+
},
|
|
20251
|
+
{
|
|
20252
|
+
ipv4Prefix: "4.227.36.0/25"
|
|
20253
|
+
},
|
|
20254
|
+
{
|
|
20255
|
+
ipv4Prefix: "40.67.175.0/25"
|
|
20256
|
+
},
|
|
20257
|
+
{
|
|
20258
|
+
ipv4Prefix: "40.90.214.16/28"
|
|
20259
|
+
},
|
|
20260
|
+
{
|
|
20261
|
+
ipv4Prefix: "51.8.102.0/24"
|
|
20262
|
+
},
|
|
20263
|
+
{
|
|
20264
|
+
ipv4Prefix: "74.7.175.128/25"
|
|
20265
|
+
},
|
|
20266
|
+
{
|
|
20267
|
+
ipv4Prefix: "74.7.228.0/25"
|
|
20268
|
+
},
|
|
20269
|
+
{
|
|
20270
|
+
ipv4Prefix: "74.7.228.128/25"
|
|
20271
|
+
},
|
|
20272
|
+
{
|
|
20273
|
+
ipv4Prefix: "74.7.229.0/25"
|
|
20274
|
+
},
|
|
20275
|
+
{
|
|
20276
|
+
ipv4Prefix: "74.7.229.128/25"
|
|
20277
|
+
},
|
|
20278
|
+
{
|
|
20279
|
+
ipv4Prefix: "74.7.230.0/25"
|
|
20280
|
+
},
|
|
20281
|
+
{
|
|
20282
|
+
ipv4Prefix: "74.7.241.128/25"
|
|
20283
|
+
},
|
|
20284
|
+
{
|
|
20285
|
+
ipv4Prefix: "74.7.242.128/25"
|
|
20286
|
+
},
|
|
20287
|
+
{
|
|
20288
|
+
ipv4Prefix: "74.7.243.0/25"
|
|
20289
|
+
},
|
|
20290
|
+
{
|
|
20291
|
+
ipv4Prefix: "74.7.244.0/25"
|
|
20292
|
+
}
|
|
20293
|
+
]
|
|
20294
|
+
};
|
|
20295
|
+
|
|
20296
|
+
// ../integration-traffic/src/ip-ranges/perplexity-user.json
|
|
20297
|
+
var perplexity_user_default = {
|
|
20298
|
+
_source: "https://www.perplexity.ai/perplexity-user.json",
|
|
20299
|
+
creationTime: "2025-10-17T10:17:00.000000",
|
|
20300
|
+
prefixes: [
|
|
20301
|
+
{
|
|
20302
|
+
ipv4Prefix: "44.208.221.197/32"
|
|
20303
|
+
},
|
|
20304
|
+
{
|
|
20305
|
+
ipv4Prefix: "34.193.163.52/32"
|
|
20306
|
+
},
|
|
20307
|
+
{
|
|
20308
|
+
ipv4Prefix: "18.97.21.0/30"
|
|
20309
|
+
},
|
|
20310
|
+
{
|
|
20311
|
+
ipv4Prefix: "18.97.43.80/29"
|
|
20312
|
+
}
|
|
20313
|
+
]
|
|
20314
|
+
};
|
|
20315
|
+
|
|
20316
|
+
// ../integration-traffic/src/ip-ranges/perplexitybot.json
|
|
20317
|
+
var perplexitybot_default = {
|
|
20318
|
+
_source: "https://www.perplexity.ai/perplexitybot.json",
|
|
20319
|
+
creationTime: "2025-02-07T16:56:00.000000",
|
|
20320
|
+
prefixes: [
|
|
20321
|
+
{
|
|
20322
|
+
ipv4Prefix: "107.20.236.150/32"
|
|
20323
|
+
},
|
|
20324
|
+
{
|
|
20325
|
+
ipv4Prefix: "3.224.62.45/32"
|
|
20326
|
+
},
|
|
20327
|
+
{
|
|
20328
|
+
ipv4Prefix: "18.210.92.235/32"
|
|
20329
|
+
},
|
|
20330
|
+
{
|
|
20331
|
+
ipv4Prefix: "3.222.232.239/32"
|
|
20332
|
+
},
|
|
20333
|
+
{
|
|
20334
|
+
ipv4Prefix: "3.211.124.183/32"
|
|
20335
|
+
},
|
|
20336
|
+
{
|
|
20337
|
+
ipv4Prefix: "3.231.139.107/32"
|
|
20338
|
+
},
|
|
20339
|
+
{
|
|
20340
|
+
ipv4Prefix: "18.97.1.228/30"
|
|
20341
|
+
},
|
|
20342
|
+
{
|
|
20343
|
+
ipv4Prefix: "18.97.9.96/29"
|
|
20344
|
+
}
|
|
20345
|
+
]
|
|
20346
|
+
};
|
|
20347
|
+
|
|
20348
|
+
// ../integration-traffic/src/ip-verify.ts
|
|
20349
|
+
var RULE_ID_TO_RANGES = {
|
|
20350
|
+
// OpenAI — three separate published lists (training crawler vs
|
|
20351
|
+
// user-on-behalf fetcher vs search engine; OpenAI maintains the
|
|
20352
|
+
// split because the IPs really do differ between products).
|
|
20353
|
+
// src: https://openai.com/gptbot.json
|
|
20354
|
+
"openai-gptbot": gptbot_default,
|
|
20355
|
+
// src: https://openai.com/chatgpt-user.json
|
|
20356
|
+
"openai-chatgpt-user": chatgpt_user_default,
|
|
20357
|
+
// src: https://openai.com/searchbot.json
|
|
20358
|
+
"openai-searchbot": oai_searchbot_default,
|
|
20359
|
+
// Search engines.
|
|
20360
|
+
// src: https://developers.google.com/static/search/apis/ipranges/googlebot.json
|
|
20361
|
+
// (also covers Gemini grounding — Google doesn't publish a
|
|
20362
|
+
// separate Gemini list; Google-Extended traffic comes from the
|
|
20363
|
+
// same Googlebot ranges)
|
|
20364
|
+
"googlebot": googlebot_default,
|
|
20365
|
+
// src: https://www.bing.com/toolbox/bingbot.json
|
|
20366
|
+
// (also covers Copilot grounding — Microsoft routes Copilot's
|
|
20367
|
+
// web fetches through bingbot infrastructure)
|
|
20368
|
+
"bingbot": bingbot_default,
|
|
20369
|
+
// Perplexity — split between crawler and user-on-behalf fetcher,
|
|
20370
|
+
// same shape as OpenAI's split.
|
|
20371
|
+
// src: https://www.perplexity.ai/perplexitybot.json
|
|
20372
|
+
"perplexity-bot": perplexitybot_default,
|
|
20373
|
+
// src: https://www.perplexity.ai/perplexity-user.json
|
|
20374
|
+
"perplexity-user": perplexity_user_default,
|
|
20375
|
+
// Anthropic — no machine-readable JSON published. The bundled
|
|
20376
|
+
// anthropic.json is the set of networks registered to Anthropic,
|
|
20377
|
+
// PBC at ARIN (the authoritative allocation record). Maintained by
|
|
20378
|
+
// hand; refresh by re-querying the ARIN entity below. The crawler
|
|
20379
|
+
// block is AWS-ANTHROPIC 216.73.216.0/22 — empirical Cloud Run
|
|
20380
|
+
// logs show all real ClaudeBot traffic comes from there. Same raw
|
|
20381
|
+
// set is shared across every Claude-* UA the classifier emits.
|
|
20382
|
+
// src: https://rdap.arin.net/registry/entity/AP-2440
|
|
20383
|
+
"anthropic-claudebot": anthropic_default
|
|
20384
|
+
};
|
|
20385
|
+
var CACHE = (() => {
|
|
20386
|
+
const cache = /* @__PURE__ */ new Map();
|
|
20387
|
+
for (const [ruleId, raw] of Object.entries(RULE_ID_TO_RANGES)) {
|
|
20388
|
+
const parsed = [];
|
|
20389
|
+
for (const entry of raw.prefixes) {
|
|
20390
|
+
const cidr = entry.ipv4Prefix ?? entry.ipv6Prefix;
|
|
20391
|
+
if (!cidr) continue;
|
|
20392
|
+
const p = parseCidr(cidr);
|
|
20393
|
+
if (p) parsed.push(p);
|
|
20394
|
+
}
|
|
20395
|
+
cache.set(ruleId, parsed);
|
|
20396
|
+
}
|
|
20397
|
+
return cache;
|
|
20398
|
+
})();
|
|
20399
|
+
function parseIp(ip) {
|
|
20400
|
+
if (!ip) return null;
|
|
20401
|
+
const mappedMatch = /^::ffff:(\d+\.\d+\.\d+\.\d+)$/i.exec(ip);
|
|
20402
|
+
if (mappedMatch) return parseIp(mappedMatch[1]);
|
|
20403
|
+
if (ip.includes(":")) {
|
|
20404
|
+
const sides = ip.split("::");
|
|
20405
|
+
if (sides.length > 2) return null;
|
|
20406
|
+
const left = sides[0].length > 0 ? sides[0].split(":") : [];
|
|
20407
|
+
const right = sides.length === 2 && sides[1].length > 0 ? sides[1].split(":") : [];
|
|
20408
|
+
const groupCount = left.length + right.length;
|
|
20409
|
+
if (groupCount > 8) return null;
|
|
20410
|
+
if (sides.length === 1 && groupCount !== 8) return null;
|
|
20411
|
+
const fill = 8 - groupCount;
|
|
20412
|
+
const groups = [...left, ...new Array(fill).fill("0"), ...right];
|
|
20413
|
+
let addr2 = 0n;
|
|
20414
|
+
for (const g of groups) {
|
|
20415
|
+
if (g.length === 0 || g.length > 4) return null;
|
|
20416
|
+
const n = Number.parseInt(g, 16);
|
|
20417
|
+
if (!Number.isFinite(n) || n < 0 || n > 65535) return null;
|
|
20418
|
+
addr2 = addr2 << 16n | BigInt(n);
|
|
20419
|
+
}
|
|
20420
|
+
return { version: 6, addr: addr2 };
|
|
20421
|
+
}
|
|
20422
|
+
const octets = ip.split(".");
|
|
20423
|
+
if (octets.length !== 4) return null;
|
|
20424
|
+
let addr = 0n;
|
|
20425
|
+
for (const o of octets) {
|
|
20426
|
+
if (o.length === 0 || o.length > 3) return null;
|
|
20427
|
+
const n = Number.parseInt(o, 10);
|
|
20428
|
+
if (!Number.isInteger(n) || n < 0 || n > 255) return null;
|
|
20429
|
+
addr = addr << 8n | BigInt(n);
|
|
20430
|
+
}
|
|
20431
|
+
return { version: 4, addr };
|
|
20432
|
+
}
|
|
20433
|
+
function parseCidr(cidr) {
|
|
20434
|
+
const [ipPart, prefixStr] = cidr.split("/");
|
|
20435
|
+
if (!ipPart || !prefixStr) return null;
|
|
20436
|
+
const prefix = Number.parseInt(prefixStr, 10);
|
|
20437
|
+
if (!Number.isInteger(prefix)) return null;
|
|
20438
|
+
const parsed = parseIp(ipPart);
|
|
20439
|
+
if (!parsed) return null;
|
|
20440
|
+
const totalBits = parsed.version === 4 ? 32 : 128;
|
|
20441
|
+
if (prefix < 0 || prefix > totalBits) return null;
|
|
20442
|
+
const allOnes = (1n << BigInt(totalBits)) - 1n;
|
|
20443
|
+
const mask = allOnes >> BigInt(totalBits - prefix) << BigInt(totalBits - prefix);
|
|
20444
|
+
return {
|
|
20445
|
+
version: parsed.version,
|
|
20446
|
+
network: parsed.addr & mask,
|
|
20447
|
+
mask
|
|
20448
|
+
};
|
|
20449
|
+
}
|
|
20450
|
+
function verifyIpForRule(ip, ruleId) {
|
|
20451
|
+
if (!ip) return false;
|
|
20452
|
+
const ranges = CACHE.get(ruleId);
|
|
20453
|
+
if (!ranges || ranges.length === 0) return false;
|
|
20454
|
+
const parsed = parseIp(ip);
|
|
20455
|
+
if (!parsed) return false;
|
|
20456
|
+
for (const cidr of ranges) {
|
|
20457
|
+
if (parsed.version !== cidr.version) continue;
|
|
20458
|
+
if ((parsed.addr & cidr.mask) === cidr.network) return true;
|
|
20459
|
+
}
|
|
20460
|
+
return false;
|
|
20461
|
+
}
|
|
20462
|
+
|
|
20463
|
+
// ../integration-traffic/src/rules.ts
|
|
20464
|
+
var LEGACY_CHATGPT_DOMAIN = "chat.openai.com";
|
|
20465
|
+
var DEFAULT_AI_CRAWLER_RULES = [
|
|
20466
|
+
{
|
|
20467
|
+
id: "openai-gptbot",
|
|
20468
|
+
operator: "OpenAI",
|
|
20469
|
+
product: "GPTBot",
|
|
20470
|
+
purpose: "training",
|
|
20471
|
+
userAgentPatterns: [/GPTBot\//i]
|
|
20472
|
+
},
|
|
20473
|
+
{
|
|
20474
|
+
id: "openai-searchbot",
|
|
20475
|
+
operator: "OpenAI",
|
|
20476
|
+
product: "OAI-SearchBot",
|
|
20477
|
+
purpose: "search",
|
|
20478
|
+
userAgentPatterns: [/OAI-SearchBot\//i]
|
|
20479
|
+
},
|
|
20480
|
+
{
|
|
20481
|
+
id: "openai-chatgpt-user",
|
|
20482
|
+
operator: "OpenAI",
|
|
20483
|
+
product: "ChatGPT-User",
|
|
20484
|
+
purpose: "user-agent",
|
|
20485
|
+
userAgentPatterns: [/ChatGPT-User\//i]
|
|
20486
|
+
},
|
|
20487
|
+
{
|
|
20488
|
+
id: "anthropic-claudebot",
|
|
20489
|
+
operator: "Anthropic",
|
|
20490
|
+
product: "ClaudeBot",
|
|
20491
|
+
purpose: "training",
|
|
20492
|
+
// Anthropic ships several Claude-* crawlers (ClaudeBot for training,
|
|
20493
|
+
// Claude-Web for chat fetches, Claude-SearchBot for search). The
|
|
20494
|
+
// `Claude-` prefix + `Bot/` suffix is the stable shape — pattern is
|
|
20495
|
+
// permissive enough to catch new Claude-* variants as Anthropic
|
|
20496
|
+
// adds them, without matching unrelated UAs that happen to mention
|
|
20497
|
+
// "claude".
|
|
20498
|
+
userAgentPatterns: [
|
|
20499
|
+
/ClaudeBot\//i,
|
|
20500
|
+
/Claude-Web\//i,
|
|
20501
|
+
/Claude-SearchBot\//i,
|
|
20502
|
+
/Claude-[A-Z]+Bot\//i,
|
|
20503
|
+
/anthropic-ai/i
|
|
20504
|
+
]
|
|
20505
|
+
},
|
|
20506
|
+
{
|
|
20507
|
+
id: "perplexity-bot",
|
|
20508
|
+
operator: "Perplexity",
|
|
20509
|
+
product: "PerplexityBot",
|
|
20510
|
+
purpose: "search",
|
|
20511
|
+
userAgentPatterns: [/PerplexityBot\//i]
|
|
20512
|
+
},
|
|
20513
|
+
{
|
|
20514
|
+
// User-initiated fetches when a Perplexity user opens a citation
|
|
20515
|
+
// link. Separate from PerplexityBot (crawl) — different ranges and
|
|
20516
|
+
// different operational signal. Perplexity publishes both UA
|
|
20517
|
+
// patterns at perplexity.ai/perplexity-user.json.
|
|
20518
|
+
id: "perplexity-user",
|
|
20519
|
+
operator: "Perplexity",
|
|
20520
|
+
product: "Perplexity-User",
|
|
20521
|
+
purpose: "user-agent",
|
|
20522
|
+
userAgentPatterns: [/Perplexity-User\//i]
|
|
20523
|
+
},
|
|
20524
|
+
{
|
|
20525
|
+
id: "google-extended",
|
|
20526
|
+
operator: "Google",
|
|
20527
|
+
product: "Google-Extended",
|
|
20528
|
+
purpose: "training-control",
|
|
20529
|
+
userAgentPatterns: [/Google-Extended/i]
|
|
20530
|
+
},
|
|
20531
|
+
{
|
|
20532
|
+
id: "bytespider",
|
|
20533
|
+
operator: "ByteDance",
|
|
20534
|
+
product: "Bytespider",
|
|
20535
|
+
purpose: "training",
|
|
20536
|
+
userAgentPatterns: [/Bytespider/i]
|
|
20537
|
+
},
|
|
20538
|
+
{
|
|
20539
|
+
id: "applebot-extended",
|
|
20540
|
+
operator: "Apple",
|
|
20541
|
+
product: "Applebot-Extended",
|
|
20542
|
+
purpose: "training",
|
|
20543
|
+
userAgentPatterns: [/Applebot-Extended/i]
|
|
20544
|
+
},
|
|
20545
|
+
{
|
|
20546
|
+
// Apple's general crawler (separate from Applebot-Extended, which is
|
|
20547
|
+
// the training-opt-out signaling UA). Both indexes pages for Apple
|
|
20548
|
+
// services (Siri/Spotlight); only Applebot-Extended is gated by
|
|
20549
|
+
// training-data opt-out.
|
|
20550
|
+
id: "applebot",
|
|
20551
|
+
operator: "Apple",
|
|
20552
|
+
product: "Applebot",
|
|
20553
|
+
purpose: "crawl",
|
|
20554
|
+
userAgentPatterns: [/Applebot\//i]
|
|
20555
|
+
},
|
|
20556
|
+
{
|
|
20557
|
+
id: "meta-externalagent",
|
|
20558
|
+
operator: "Meta",
|
|
20559
|
+
product: "meta-externalagent",
|
|
20560
|
+
purpose: "training",
|
|
20561
|
+
userAgentPatterns: [/meta-externalagent/i]
|
|
20562
|
+
},
|
|
20563
|
+
{
|
|
20564
|
+
id: "ccbot",
|
|
20565
|
+
operator: "Common Crawl",
|
|
20566
|
+
product: "CCBot",
|
|
20567
|
+
purpose: "crawl",
|
|
20568
|
+
userAgentPatterns: [/CCBot\//i]
|
|
20569
|
+
},
|
|
20570
|
+
{
|
|
20571
|
+
id: "cohere-ai",
|
|
20572
|
+
operator: "Cohere",
|
|
20573
|
+
product: "cohere-ai",
|
|
20574
|
+
purpose: "training",
|
|
20575
|
+
userAgentPatterns: [/cohere-ai/i]
|
|
20576
|
+
},
|
|
20577
|
+
{
|
|
20578
|
+
id: "diffbot",
|
|
20579
|
+
operator: "Diffbot",
|
|
20580
|
+
product: "Diffbot",
|
|
20581
|
+
purpose: "crawl",
|
|
20582
|
+
userAgentPatterns: [/Diffbot/i]
|
|
20583
|
+
},
|
|
20584
|
+
{
|
|
20585
|
+
id: "mistral-ai",
|
|
20586
|
+
operator: "Mistral AI",
|
|
20587
|
+
product: "MistralAI-User",
|
|
20588
|
+
purpose: "crawl",
|
|
20589
|
+
// Mistral ships both `MistralAI-User/*` (chat-on-behalf-of-user
|
|
20590
|
+
// fetches) and `MistralBot/*` (general crawler). Earlier rule only
|
|
20591
|
+
// matched `MistralAI` and missed the bot — caught on 2026-05-18
|
|
20592
|
+
// when canonry.ai/canonry-landing's classification chart went flat
|
|
20593
|
+
// and the bot UA was sitting in the `unknown` bucket.
|
|
20594
|
+
userAgentPatterns: [/MistralAI/i, /MistralBot/i]
|
|
20595
|
+
},
|
|
20596
|
+
{
|
|
20597
|
+
id: "deepseek",
|
|
20598
|
+
operator: "DeepSeek",
|
|
20599
|
+
product: "DeepSeekBot",
|
|
20600
|
+
purpose: "training",
|
|
20601
|
+
userAgentPatterns: [/DeepSeekBot/i]
|
|
20602
|
+
},
|
|
20603
|
+
// Classic search-engine crawlers. Not strictly "AI" by training origin,
|
|
20604
|
+
// but the same audience: machine traffic indexing the site for query
|
|
20605
|
+
// surfaces. Operators tracking AI visibility want this signal too —
|
|
20606
|
+
// SERP indexing is the upstream that feeds AI answer engines (Bing
|
|
20607
|
+
// powers ChatGPT search; Google powers Gemini grounding). Classified
|
|
20608
|
+
// alongside LLM crawlers; the dashboard's "AI crawler hits" label is
|
|
20609
|
+
// imprecise here but functionally correct (these are still bots, not
|
|
20610
|
+
// humans).
|
|
20611
|
+
{
|
|
20612
|
+
id: "googlebot",
|
|
20613
|
+
operator: "Google",
|
|
20614
|
+
product: "Googlebot",
|
|
20615
|
+
purpose: "search",
|
|
20616
|
+
// Googlebot has Smartphone / Desktop / Image / News / Video variants.
|
|
20617
|
+
// All match the `Googlebot/` prefix on first appearance in the UA.
|
|
20618
|
+
// Excludes `Googlebot-Image` etc. that ride a `Googlebot-` prefix —
|
|
20619
|
+
// they also match `Googlebot/` in their UA strings.
|
|
20620
|
+
userAgentPatterns: [/Googlebot[/-]/i]
|
|
20621
|
+
},
|
|
20622
|
+
{
|
|
20623
|
+
id: "bingbot",
|
|
20624
|
+
operator: "Microsoft",
|
|
20625
|
+
product: "bingbot",
|
|
20626
|
+
purpose: "search",
|
|
20627
|
+
userAgentPatterns: [/bingbot\//i]
|
|
20628
|
+
},
|
|
20629
|
+
{
|
|
20630
|
+
id: "duckduckbot",
|
|
20631
|
+
operator: "DuckDuckGo",
|
|
20632
|
+
product: "DuckDuckBot",
|
|
20633
|
+
purpose: "search",
|
|
20634
|
+
userAgentPatterns: [/DuckDuckBot/i]
|
|
20635
|
+
},
|
|
20636
|
+
{
|
|
20637
|
+
id: "yandexbot",
|
|
20638
|
+
operator: "Yandex",
|
|
20639
|
+
product: "YandexBot",
|
|
20640
|
+
purpose: "search",
|
|
20641
|
+
userAgentPatterns: [/YandexBot\//i]
|
|
20642
|
+
},
|
|
20643
|
+
{
|
|
20644
|
+
id: "baiduspider",
|
|
20645
|
+
operator: "Baidu",
|
|
20646
|
+
product: "Baiduspider",
|
|
20647
|
+
purpose: "search",
|
|
20648
|
+
userAgentPatterns: [/Baiduspider/i]
|
|
20649
|
+
},
|
|
20650
|
+
{
|
|
20651
|
+
id: "amazonbot",
|
|
20652
|
+
operator: "Amazon",
|
|
20653
|
+
product: "Amazonbot",
|
|
20654
|
+
purpose: "crawl",
|
|
20655
|
+
userAgentPatterns: [/Amazonbot\//i]
|
|
20656
|
+
}
|
|
20657
|
+
];
|
|
20658
|
+
var DEFAULT_AI_REFERRER_RULES = [
|
|
20659
|
+
{ domain: AI_ENGINE_DOMAINS.chatgpt, operator: "OpenAI", product: "ChatGPT" },
|
|
20660
|
+
{ domain: LEGACY_CHATGPT_DOMAIN, operator: "OpenAI", product: "ChatGPT" },
|
|
20661
|
+
{ domain: AI_ENGINE_DOMAINS.perplexity, operator: "Perplexity", product: "Perplexity" },
|
|
20662
|
+
{ domain: AI_ENGINE_DOMAINS.claude, operator: "Anthropic", product: "Claude" },
|
|
20663
|
+
{ domain: AI_ENGINE_DOMAINS.gemini, operator: "Google", product: "Gemini" },
|
|
20664
|
+
{ domain: AI_ENGINE_DOMAINS.copilotMicrosoft, operator: "Microsoft", product: "Copilot" },
|
|
20665
|
+
{ domain: AI_ENGINE_DOMAINS.phind, operator: "Phind", product: "Phind" },
|
|
20666
|
+
{ domain: AI_ENGINE_DOMAINS.you, operator: "You.com", product: "You.com" },
|
|
20667
|
+
{ domain: AI_ENGINE_DOMAINS.metaAi, operator: "Meta", product: "Meta AI" }
|
|
20668
|
+
];
|
|
20669
|
+
|
|
20670
|
+
// ../integration-traffic/src/classifier.ts
|
|
20671
|
+
function normalizeHost(host) {
|
|
20672
|
+
return host.trim().toLowerCase().replace(/^www\./, "");
|
|
20673
|
+
}
|
|
20674
|
+
function hostMatches(host, domain) {
|
|
20675
|
+
const normalizedHost = normalizeHost(host);
|
|
20676
|
+
const normalizedDomain = normalizeHost(domain);
|
|
20677
|
+
return normalizedHost === normalizedDomain || normalizedHost.endsWith(`.${normalizedDomain}`);
|
|
20678
|
+
}
|
|
20679
|
+
function utmTokenMatchesDomain(utmSource, domain) {
|
|
20680
|
+
if (hostMatches(utmSource, domain)) return true;
|
|
20681
|
+
const normalizedUtm = normalizeHost(utmSource);
|
|
20682
|
+
const firstLabel = normalizeHost(domain).split(".")[0];
|
|
20683
|
+
return Boolean(firstLabel) && normalizedUtm === firstLabel;
|
|
20684
|
+
}
|
|
20685
|
+
function hostFromUrl(value) {
|
|
20686
|
+
if (!value) return null;
|
|
20687
|
+
try {
|
|
20688
|
+
return normalizeHost(new URL(value).hostname);
|
|
20689
|
+
} catch {
|
|
20690
|
+
return null;
|
|
20691
|
+
}
|
|
20692
|
+
}
|
|
20693
|
+
function utmSourceFromQuery(queryString) {
|
|
20694
|
+
if (!queryString) return null;
|
|
20695
|
+
const params = new URLSearchParams(queryString);
|
|
20696
|
+
const source = params.get("utm_source");
|
|
20697
|
+
return source ? normalizeHost(source) : null;
|
|
20698
|
+
}
|
|
20699
|
+
function utmSourceFromUrl(value) {
|
|
20700
|
+
if (!value) return null;
|
|
20701
|
+
try {
|
|
20702
|
+
return utmSourceFromQuery(new URL(value).search.replace(/^\?/, ""));
|
|
20703
|
+
} catch {
|
|
20704
|
+
return null;
|
|
20705
|
+
}
|
|
20706
|
+
}
|
|
20707
|
+
function classifyCrawler(event) {
|
|
20708
|
+
const userAgent = event.userAgent?.trim();
|
|
20709
|
+
if (!userAgent) return null;
|
|
20710
|
+
for (const rule of DEFAULT_AI_CRAWLER_RULES) {
|
|
20711
|
+
if (rule.userAgentPatterns.some((pattern) => pattern.test(userAgent))) {
|
|
20712
|
+
const verified = verifyIpForRule(event.remoteIp, rule.id);
|
|
20713
|
+
return {
|
|
20714
|
+
botId: rule.id,
|
|
20715
|
+
operator: rule.operator,
|
|
20716
|
+
product: rule.product,
|
|
20717
|
+
purpose: rule.purpose,
|
|
20718
|
+
verificationStatus: verified ? "verified" : "claimed_unverified",
|
|
20719
|
+
matchedUserAgent: userAgent
|
|
20720
|
+
};
|
|
20721
|
+
}
|
|
20722
|
+
}
|
|
20723
|
+
return null;
|
|
20724
|
+
}
|
|
20725
|
+
function classifyAiReferral(event) {
|
|
20726
|
+
const refererHost = hostFromUrl(event.referer);
|
|
20727
|
+
if (refererHost) {
|
|
20728
|
+
const rule = DEFAULT_AI_REFERRER_RULES.find((candidate) => hostMatches(refererHost, candidate.domain));
|
|
20729
|
+
if (rule) {
|
|
20730
|
+
return {
|
|
20731
|
+
operator: rule.operator,
|
|
20732
|
+
product: rule.product,
|
|
20733
|
+
sourceDomain: refererHost,
|
|
20734
|
+
evidenceType: "referer"
|
|
20735
|
+
};
|
|
20736
|
+
}
|
|
20737
|
+
}
|
|
20738
|
+
const utmSource = utmSourceFromQuery(event.queryString);
|
|
20739
|
+
if (utmSource) {
|
|
20740
|
+
const rule = DEFAULT_AI_REFERRER_RULES.find((candidate) => utmTokenMatchesDomain(utmSource, candidate.domain));
|
|
20741
|
+
if (rule) {
|
|
20742
|
+
return {
|
|
20743
|
+
operator: rule.operator,
|
|
20744
|
+
product: rule.product,
|
|
20745
|
+
sourceDomain: utmSource,
|
|
20746
|
+
evidenceType: "utm"
|
|
20747
|
+
};
|
|
20748
|
+
}
|
|
20749
|
+
}
|
|
20750
|
+
const refererUtmSource = utmSourceFromUrl(event.referer);
|
|
20751
|
+
if (refererUtmSource) {
|
|
20752
|
+
const rule = DEFAULT_AI_REFERRER_RULES.find((candidate) => utmTokenMatchesDomain(refererUtmSource, candidate.domain));
|
|
20753
|
+
if (rule) {
|
|
20754
|
+
return {
|
|
20755
|
+
operator: rule.operator,
|
|
20756
|
+
product: rule.product,
|
|
20757
|
+
sourceDomain: refererUtmSource,
|
|
20758
|
+
evidenceType: "referer-utm"
|
|
20759
|
+
};
|
|
20760
|
+
}
|
|
20761
|
+
}
|
|
20762
|
+
return null;
|
|
20763
|
+
}
|
|
20764
|
+
|
|
20765
|
+
// ../integration-traffic/src/rollup.ts
|
|
20766
|
+
var DEFAULT_SAMPLE_LIMIT = 25;
|
|
20767
|
+
var DEFAULT_AI_REFERRAL_SESSION_WINDOW_MS = 6e4;
|
|
20768
|
+
var UUID_SEGMENT = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
20769
|
+
var LONG_HEX_SEGMENT = /^[0-9a-f]{16,}$/i;
|
|
20770
|
+
var NUMERIC_SEGMENT = /^\d+$/;
|
|
20771
|
+
var ASSET_EXTENSION_PATTERN = /\.(?:avif|bmp|css|gif|ico|jpe?g|js|json|map|mjs|mp4|otf|png|svg|webm|webmanifest|woff2?|xml)$/i;
|
|
20772
|
+
var ASSET_PATH_PREFIXES = [
|
|
20773
|
+
"/_next/static/",
|
|
20774
|
+
"/assets/",
|
|
18426
20775
|
"/build/",
|
|
18427
20776
|
"/dist/",
|
|
18428
20777
|
"/fonts/",
|
|
@@ -20817,6 +23166,79 @@ var providersConfiguredCheck = {
|
|
|
20817
23166
|
};
|
|
20818
23167
|
var PROVIDERS_CHECKS = [providersConfiguredCheck];
|
|
20819
23168
|
|
|
23169
|
+
// ../api-routes/src/doctor/checks/runtime-state.ts
|
|
23170
|
+
import fs7 from "fs";
|
|
23171
|
+
var dbFilePresentCheck = {
|
|
23172
|
+
id: "db.file.present",
|
|
23173
|
+
category: CheckCategories.database,
|
|
23174
|
+
scope: CheckScopes.global,
|
|
23175
|
+
title: "Database file present",
|
|
23176
|
+
run: (ctx) => {
|
|
23177
|
+
const path16 = ctx.runtimeStatePaths?.databasePath;
|
|
23178
|
+
if (!path16) {
|
|
23179
|
+
return {
|
|
23180
|
+
status: CheckStatuses.skipped,
|
|
23181
|
+
code: "db.file.path-not-wired",
|
|
23182
|
+
summary: "No database file path configured for this deployment (cloud DB).",
|
|
23183
|
+
remediation: null
|
|
23184
|
+
};
|
|
23185
|
+
}
|
|
23186
|
+
if (!fs7.existsSync(path16)) {
|
|
23187
|
+
return {
|
|
23188
|
+
status: CheckStatuses.fail,
|
|
23189
|
+
code: "db.file.missing",
|
|
23190
|
+
summary: `Database file at \`${path16}\` has been deleted while the daemon is running.`,
|
|
23191
|
+
remediation: "Restart `canonry serve` so a fresh database is created and migrations re-run. Until you do, the daemon will keep serving stale data from a deleted-but-open file handle and writes will be lost.",
|
|
23192
|
+
details: { path: path16 }
|
|
23193
|
+
};
|
|
23194
|
+
}
|
|
23195
|
+
return {
|
|
23196
|
+
status: CheckStatuses.ok,
|
|
23197
|
+
code: "db.file.present",
|
|
23198
|
+
summary: `Database file present at \`${path16}\`.`,
|
|
23199
|
+
remediation: null,
|
|
23200
|
+
details: { path: path16 }
|
|
23201
|
+
};
|
|
23202
|
+
}
|
|
23203
|
+
};
|
|
23204
|
+
var configFilePresentCheck = {
|
|
23205
|
+
id: "config.file.present",
|
|
23206
|
+
category: CheckCategories.config,
|
|
23207
|
+
scope: CheckScopes.global,
|
|
23208
|
+
title: "Config file present",
|
|
23209
|
+
run: (ctx) => {
|
|
23210
|
+
const path16 = ctx.runtimeStatePaths?.configPath;
|
|
23211
|
+
if (!path16) {
|
|
23212
|
+
return {
|
|
23213
|
+
status: CheckStatuses.skipped,
|
|
23214
|
+
code: "config.file.path-not-wired",
|
|
23215
|
+
summary: "No config file path configured for this deployment.",
|
|
23216
|
+
remediation: null
|
|
23217
|
+
};
|
|
23218
|
+
}
|
|
23219
|
+
if (!fs7.existsSync(path16)) {
|
|
23220
|
+
return {
|
|
23221
|
+
status: CheckStatuses.fail,
|
|
23222
|
+
code: "config.file.missing",
|
|
23223
|
+
summary: `Config file at \`${path16}\` has been deleted while the daemon is running.`,
|
|
23224
|
+
remediation: "Restart `canonry serve` after the file is restored (provider keys, OAuth tokens, and integration credentials live in this file; the in-memory copy is read-only until restart).",
|
|
23225
|
+
details: { path: path16 }
|
|
23226
|
+
};
|
|
23227
|
+
}
|
|
23228
|
+
return {
|
|
23229
|
+
status: CheckStatuses.ok,
|
|
23230
|
+
code: "config.file.present",
|
|
23231
|
+
summary: `Config file present at \`${path16}\`.`,
|
|
23232
|
+
remediation: null,
|
|
23233
|
+
details: { path: path16 }
|
|
23234
|
+
};
|
|
23235
|
+
}
|
|
23236
|
+
};
|
|
23237
|
+
var RUNTIME_STATE_CHECKS = [
|
|
23238
|
+
dbFilePresentCheck,
|
|
23239
|
+
configFilePresentCheck
|
|
23240
|
+
];
|
|
23241
|
+
|
|
20820
23242
|
// ../api-routes/src/doctor/checks/traffic-source.ts
|
|
20821
23243
|
import { and as and20, eq as eq25, gte as gte4, ne as ne4, sql as sql11 } from "drizzle-orm";
|
|
20822
23244
|
var RECENT_DATA_WARN_DAYS = 7;
|
|
@@ -21122,6 +23544,9 @@ var TRAFFIC_SOURCE_CHECKS = [
|
|
|
21122
23544
|
|
|
21123
23545
|
// ../api-routes/src/doctor/registry.ts
|
|
21124
23546
|
var ALL_CHECKS = [
|
|
23547
|
+
// Runtime-state checks run first so file-system gone errors surface
|
|
23548
|
+
// before any auth/integration checks try to touch the (orphaned) DB.
|
|
23549
|
+
...RUNTIME_STATE_CHECKS,
|
|
21125
23550
|
...GOOGLE_AUTH_CHECKS,
|
|
21126
23551
|
...BING_AUTH_CHECKS,
|
|
21127
23552
|
...GA_AUTH_CHECKS,
|
|
@@ -21212,7 +23637,8 @@ async function doctorRoutes(app, opts) {
|
|
|
21212
23637
|
getGoogleAuthConfig: opts.getGoogleAuthConfig,
|
|
21213
23638
|
redirectUri,
|
|
21214
23639
|
providerSummary: opts.providerSummary,
|
|
21215
|
-
trafficSourceValidators: opts.trafficSourceValidators
|
|
23640
|
+
trafficSourceValidators: opts.trafficSourceValidators,
|
|
23641
|
+
runtimeStatePaths: opts.runtimeStatePaths
|
|
21216
23642
|
};
|
|
21217
23643
|
return runChecks(ctx, ALL_CHECKS, { checkIds });
|
|
21218
23644
|
});
|
|
@@ -21233,7 +23659,8 @@ async function doctorRoutes(app, opts) {
|
|
|
21233
23659
|
getGoogleAuthConfig: opts.getGoogleAuthConfig,
|
|
21234
23660
|
redirectUri,
|
|
21235
23661
|
providerSummary: opts.providerSummary,
|
|
21236
|
-
trafficSourceValidators: opts.trafficSourceValidators
|
|
23662
|
+
trafficSourceValidators: opts.trafficSourceValidators,
|
|
23663
|
+
runtimeStatePaths: opts.runtimeStatePaths
|
|
21237
23664
|
};
|
|
21238
23665
|
return runChecks(ctx, ALL_CHECKS, { checkIds });
|
|
21239
23666
|
});
|
|
@@ -21722,6 +24149,21 @@ async function apiRoutes(app, opts) {
|
|
|
21722
24149
|
}
|
|
21723
24150
|
});
|
|
21724
24151
|
});
|
|
24152
|
+
if (opts.runtimeStatePaths) {
|
|
24153
|
+
const { databasePath, configPath } = opts.runtimeStatePaths;
|
|
24154
|
+
const isDiagnosticUrl = (url) => url === "/health" || /\/doctor(?:\?|$)/.test(url);
|
|
24155
|
+
app.addHook("onRequest", async (request) => {
|
|
24156
|
+
if (isDiagnosticUrl(request.url)) return;
|
|
24157
|
+
const missing = [];
|
|
24158
|
+
if (!fs8.existsSync(databasePath)) missing.push(`database file \`${databasePath}\``);
|
|
24159
|
+
if (configPath && !fs8.existsSync(configPath)) missing.push(`config file \`${configPath}\``);
|
|
24160
|
+
if (missing.length === 0) return;
|
|
24161
|
+
throw runtimeStateMissing(
|
|
24162
|
+
`Runtime state missing: ${missing.join(" and ")}. Restart \`canonry serve\` so a fresh state is created (the daemon's open file handles still point at the deleted inode, so writes are being lost).`,
|
|
24163
|
+
{ missing }
|
|
24164
|
+
);
|
|
24165
|
+
});
|
|
24166
|
+
}
|
|
21725
24167
|
await app.register(async (api) => {
|
|
21726
24168
|
if (!opts.skipAuth) {
|
|
21727
24169
|
await authPlugin(api, {
|
|
@@ -21845,7 +24287,8 @@ async function apiRoutes(app, opts) {
|
|
|
21845
24287
|
getGoogleAuthConfig: opts.getGoogleAuthConfig,
|
|
21846
24288
|
publicUrl: opts.publicUrl,
|
|
21847
24289
|
providerSummary: opts.providerSummary,
|
|
21848
|
-
trafficSourceValidators: buildTrafficSourceValidators(opts)
|
|
24290
|
+
trafficSourceValidators: buildTrafficSourceValidators(opts),
|
|
24291
|
+
runtimeStatePaths: opts.runtimeStatePaths
|
|
21849
24292
|
});
|
|
21850
24293
|
if (opts.registerAuthenticatedRoutes) {
|
|
21851
24294
|
await opts.registerAuthenticatedRoutes(api);
|
|
@@ -22031,7 +24474,7 @@ async function withRetry(fn, options = {}) {
|
|
|
22031
24474
|
}
|
|
22032
24475
|
|
|
22033
24476
|
// ../provider-gemini/src/normalize.ts
|
|
22034
|
-
var DEFAULT_MODEL = "gemini-
|
|
24477
|
+
var DEFAULT_MODEL = "gemini-2.5-flash";
|
|
22035
24478
|
function isVertexConfig(config) {
|
|
22036
24479
|
return !!config.vertexProject;
|
|
22037
24480
|
}
|
|
@@ -22368,15 +24811,14 @@ var geminiAdapter = {
|
|
|
22368
24811
|
keyUrl: "https://aistudio.google.com/apikey",
|
|
22369
24812
|
// Upstream model list: https://ai.google.dev/gemini-api/docs/models
|
|
22370
24813
|
modelRegistry: {
|
|
22371
|
-
defaultModel: "gemini-
|
|
24814
|
+
defaultModel: "gemini-2.5-flash",
|
|
22372
24815
|
validationPattern: /./,
|
|
22373
|
-
validationHint: "any valid Google model name (e.g. gemini-
|
|
24816
|
+
validationHint: "any valid Google model name (e.g. gemini-2.5-flash, learnlm-1.5-pro-experimental)",
|
|
22374
24817
|
knownModels: [
|
|
22375
|
-
{ id: "gemini-
|
|
22376
|
-
{ id: "gemini-
|
|
22377
|
-
{ id: "gemini-
|
|
22378
|
-
{ id: "gemini-
|
|
22379
|
-
{ id: "gemini-2.5-flash", displayName: "Gemini 2.5 Flash", tier: "standard" }
|
|
24818
|
+
{ id: "gemini-2.5-pro", displayName: "Gemini 2.5 Pro", tier: "flagship" },
|
|
24819
|
+
{ id: "gemini-2.5-flash", displayName: "Gemini 2.5 Flash", tier: "standard" },
|
|
24820
|
+
{ id: "gemini-2.5-flash-lite", displayName: "Gemini 2.5 Flash-Lite", tier: "economy" },
|
|
24821
|
+
{ id: "gemini-2.0-flash", displayName: "Gemini 2.0 Flash", tier: "standard" }
|
|
22380
24822
|
]
|
|
22381
24823
|
},
|
|
22382
24824
|
validateConfig(config) {
|
|
@@ -23792,12 +26234,12 @@ function sleep2(ms) {
|
|
|
23792
26234
|
}
|
|
23793
26235
|
|
|
23794
26236
|
// ../provider-cdp/src/screenshot.ts
|
|
23795
|
-
import
|
|
26237
|
+
import fs9 from "fs";
|
|
23796
26238
|
import path8 from "path";
|
|
23797
26239
|
async function captureElementScreenshot(client, selector, outputPath) {
|
|
23798
26240
|
const dir = path8.dirname(outputPath);
|
|
23799
|
-
if (!
|
|
23800
|
-
|
|
26241
|
+
if (!fs9.existsSync(dir)) {
|
|
26242
|
+
fs9.mkdirSync(dir, { recursive: true });
|
|
23801
26243
|
}
|
|
23802
26244
|
let clip;
|
|
23803
26245
|
try {
|
|
@@ -23831,7 +26273,7 @@ async function captureElementScreenshot(client, selector, outputPath) {
|
|
|
23831
26273
|
}
|
|
23832
26274
|
const { data } = await client.Page.captureScreenshot(screenshotParams);
|
|
23833
26275
|
const buffer = Buffer.from(data, "base64");
|
|
23834
|
-
|
|
26276
|
+
fs9.writeFileSync(outputPath, buffer);
|
|
23835
26277
|
return outputPath;
|
|
23836
26278
|
}
|
|
23837
26279
|
|
|
@@ -24589,7 +27031,7 @@ function removeWordpressConnection(config, projectName) {
|
|
|
24589
27031
|
|
|
24590
27032
|
// src/job-runner.ts
|
|
24591
27033
|
import crypto25 from "crypto";
|
|
24592
|
-
import
|
|
27034
|
+
import fs10 from "fs";
|
|
24593
27035
|
import path10 from "path";
|
|
24594
27036
|
import os5 from "os";
|
|
24595
27037
|
import { and as and22, eq as eq28, inArray as inArray10, sql as sql12 } from "drizzle-orm";
|
|
@@ -25083,12 +27525,12 @@ var JobRunner = class {
|
|
|
25083
27525
|
allBrandNames
|
|
25084
27526
|
);
|
|
25085
27527
|
let screenshotRelPath = null;
|
|
25086
|
-
if (raw.screenshotPath &&
|
|
27528
|
+
if (raw.screenshotPath && fs10.existsSync(raw.screenshotPath)) {
|
|
25087
27529
|
const snapshotId = crypto25.randomUUID();
|
|
25088
27530
|
const screenshotDir = path10.join(os5.homedir(), ".canonry", "screenshots", runId);
|
|
25089
|
-
if (!
|
|
27531
|
+
if (!fs10.existsSync(screenshotDir)) fs10.mkdirSync(screenshotDir, { recursive: true });
|
|
25090
27532
|
const destPath = path10.join(screenshotDir, `${snapshotId}.png`);
|
|
25091
|
-
|
|
27533
|
+
fs10.renameSync(raw.screenshotPath, destPath);
|
|
25092
27534
|
screenshotRelPath = `${runId}/${snapshotId}.png`;
|
|
25093
27535
|
this.db.insert(querySnapshots).values({
|
|
25094
27536
|
id: snapshotId,
|
|
@@ -26126,7 +28568,7 @@ function computeSummary(rows) {
|
|
|
26126
28568
|
|
|
26127
28569
|
// src/backlink-extract.ts
|
|
26128
28570
|
import crypto30 from "crypto";
|
|
26129
|
-
import
|
|
28571
|
+
import fs11 from "fs";
|
|
26130
28572
|
import { and as and26, desc as desc16, eq as eq33 } from "drizzle-orm";
|
|
26131
28573
|
var log7 = createLogger("BacklinkExtract");
|
|
26132
28574
|
function defaultDeps2() {
|
|
@@ -26155,7 +28597,7 @@ async function executeBacklinkExtract(db, runId, projectId, opts = {}) {
|
|
|
26155
28597
|
if (!sync.vertexPath || !sync.edgesPath) {
|
|
26156
28598
|
throw new Error(`Release ${sync.release} is missing cached file paths`);
|
|
26157
28599
|
}
|
|
26158
|
-
if (!
|
|
28600
|
+
if (!fs11.existsSync(sync.vertexPath) || !fs11.existsSync(sync.edgesPath)) {
|
|
26159
28601
|
throw new Error(
|
|
26160
28602
|
`Cache for release ${sync.release} is missing from disk (expected at ${sync.vertexPath}). The sync record exists in the database, but the ~16 GB dump was deleted or never present on this machine. Re-sync this release from the Backlinks admin page to restore the cache.`
|
|
26161
28603
|
);
|
|
@@ -26546,7 +28988,7 @@ function buildDiscoveryInsightTitle(input) {
|
|
|
26546
28988
|
}
|
|
26547
28989
|
|
|
26548
28990
|
// src/commands/backfill.ts
|
|
26549
|
-
import { and as and28, eq as eq35, inArray as inArray11 } from "drizzle-orm";
|
|
28991
|
+
import { and as and28, eq as eq35, inArray as inArray11, isNull, sql as sql15 } from "drizzle-orm";
|
|
26550
28992
|
var SNAPSHOT_BATCH_SIZE = 500;
|
|
26551
28993
|
async function backfillAnswerVisibilityCommand(opts) {
|
|
26552
28994
|
const config = loadConfig();
|
|
@@ -27003,7 +29445,7 @@ function readStoredGroundingSources(rawResponse) {
|
|
|
27003
29445
|
return result;
|
|
27004
29446
|
}
|
|
27005
29447
|
async function backfillInsightsCommand(project, opts) {
|
|
27006
|
-
const { IntelligenceService: IntelligenceService2 } = await import("./intelligence-service-
|
|
29448
|
+
const { IntelligenceService: IntelligenceService2 } = await import("./intelligence-service-2XL2M7QP.js");
|
|
27007
29449
|
const config = loadConfig();
|
|
27008
29450
|
const db = createClient(config.database);
|
|
27009
29451
|
migrate(db);
|
|
@@ -27051,6 +29493,247 @@ Backfill ${isDryRun ? "preview" : "complete"}.`);
|
|
|
27051
29493
|
console.log(` No DB writes performed. Re-run without --dry-run to apply.`);
|
|
27052
29494
|
}
|
|
27053
29495
|
}
|
|
29496
|
+
function replayQueryAuditLog(events) {
|
|
29497
|
+
const active = [];
|
|
29498
|
+
for (const ev of events) {
|
|
29499
|
+
let diff;
|
|
29500
|
+
try {
|
|
29501
|
+
diff = ev.diff ? JSON.parse(ev.diff) : {};
|
|
29502
|
+
} catch {
|
|
29503
|
+
continue;
|
|
29504
|
+
}
|
|
29505
|
+
if (ev.action === "keywords.appended" || ev.action === "queries.appended") {
|
|
29506
|
+
const added = Array.isArray(diff.added) ? diff.added : [];
|
|
29507
|
+
for (const q of added) {
|
|
29508
|
+
active.push({ text: q, addedAt: ev.createdAt, deletedAt: null });
|
|
29509
|
+
}
|
|
29510
|
+
} else if (ev.action === "keywords.deleted" || ev.action === "queries.deleted") {
|
|
29511
|
+
const deleted = Array.isArray(diff.deleted) ? diff.deleted : [];
|
|
29512
|
+
for (const q of deleted) {
|
|
29513
|
+
for (let i = active.length - 1; i >= 0; i--) {
|
|
29514
|
+
if (active[i].text === q && active[i].deletedAt === null) {
|
|
29515
|
+
active[i].deletedAt = ev.createdAt;
|
|
29516
|
+
break;
|
|
29517
|
+
}
|
|
29518
|
+
}
|
|
29519
|
+
}
|
|
29520
|
+
} else if (ev.action === "queries.replaced") {
|
|
29521
|
+
const newSet = Array.isArray(diff.queries) ? diff.queries : [];
|
|
29522
|
+
for (const e of active) {
|
|
29523
|
+
if (e.deletedAt === null) e.deletedAt = ev.createdAt;
|
|
29524
|
+
}
|
|
29525
|
+
for (const q of newSet) {
|
|
29526
|
+
active.push({ text: q, addedAt: ev.createdAt, deletedAt: null });
|
|
29527
|
+
}
|
|
29528
|
+
}
|
|
29529
|
+
}
|
|
29530
|
+
return active;
|
|
29531
|
+
}
|
|
29532
|
+
function activeQueriesAt(history, t) {
|
|
29533
|
+
return history.filter((e) => e.addedAt <= t && (e.deletedAt === null || e.deletedAt > t)).map((e) => e.text);
|
|
29534
|
+
}
|
|
29535
|
+
var CONTENT_MATCH_STOPWORDS = /* @__PURE__ */ new Set([
|
|
29536
|
+
"the",
|
|
29537
|
+
"a",
|
|
29538
|
+
"an",
|
|
29539
|
+
"and",
|
|
29540
|
+
"or",
|
|
29541
|
+
"but",
|
|
29542
|
+
"is",
|
|
29543
|
+
"are",
|
|
29544
|
+
"was",
|
|
29545
|
+
"were",
|
|
29546
|
+
"be",
|
|
29547
|
+
"been",
|
|
29548
|
+
"being",
|
|
29549
|
+
"have",
|
|
29550
|
+
"has",
|
|
29551
|
+
"had",
|
|
29552
|
+
"do",
|
|
29553
|
+
"does",
|
|
29554
|
+
"did",
|
|
29555
|
+
"will",
|
|
29556
|
+
"would",
|
|
29557
|
+
"could",
|
|
29558
|
+
"should",
|
|
29559
|
+
"may",
|
|
29560
|
+
"might",
|
|
29561
|
+
"can",
|
|
29562
|
+
"this",
|
|
29563
|
+
"that",
|
|
29564
|
+
"these",
|
|
29565
|
+
"those",
|
|
29566
|
+
"i",
|
|
29567
|
+
"you",
|
|
29568
|
+
"he",
|
|
29569
|
+
"she",
|
|
29570
|
+
"it",
|
|
29571
|
+
"we",
|
|
29572
|
+
"they",
|
|
29573
|
+
"what",
|
|
29574
|
+
"which",
|
|
29575
|
+
"who",
|
|
29576
|
+
"how",
|
|
29577
|
+
"why",
|
|
29578
|
+
"when",
|
|
29579
|
+
"where",
|
|
29580
|
+
"with",
|
|
29581
|
+
"for",
|
|
29582
|
+
"from",
|
|
29583
|
+
"of",
|
|
29584
|
+
"in",
|
|
29585
|
+
"on",
|
|
29586
|
+
"at",
|
|
29587
|
+
"to",
|
|
29588
|
+
"by",
|
|
29589
|
+
"as",
|
|
29590
|
+
"best",
|
|
29591
|
+
"most"
|
|
29592
|
+
]);
|
|
29593
|
+
function tokenizeForMatch(s) {
|
|
29594
|
+
return s.toLowerCase().replace(/[^a-z0-9\s]/g, " ").split(/\s+/).filter((t) => t.length >= 3 && !CONTENT_MATCH_STOPWORDS.has(t));
|
|
29595
|
+
}
|
|
29596
|
+
function contentMatchScore(queryText, answerText) {
|
|
29597
|
+
const queryTokens = [...new Set(tokenizeForMatch(queryText))];
|
|
29598
|
+
if (queryTokens.length === 0) return 0;
|
|
29599
|
+
const answerHead = answerText.slice(0, 300).toLowerCase();
|
|
29600
|
+
const hit = queryTokens.filter((t) => answerHead.includes(t)).length;
|
|
29601
|
+
return hit / queryTokens.length;
|
|
29602
|
+
}
|
|
29603
|
+
async function backfillSnapshotAttributionCommand(opts) {
|
|
29604
|
+
const config = loadConfig();
|
|
29605
|
+
const db = createClient(config.database);
|
|
29606
|
+
migrate(db);
|
|
29607
|
+
const project = db.select().from(projects).where(eq35(projects.name, opts.project)).get();
|
|
29608
|
+
if (!project) {
|
|
29609
|
+
throw new Error(`Project "${opts.project}" not found`);
|
|
29610
|
+
}
|
|
29611
|
+
const isJson = opts.format === "json";
|
|
29612
|
+
const isDryRun = opts.dryRun === true;
|
|
29613
|
+
if (!isJson) {
|
|
29614
|
+
const mode = isDryRun ? " [DRY RUN \u2014 no writes]" : "";
|
|
29615
|
+
process.stderr.write(`Recovering orphan snapshot attribution for "${project.name}"${mode}...
|
|
29616
|
+
`);
|
|
29617
|
+
}
|
|
29618
|
+
const events = db.select({ createdAt: auditLog.createdAt, action: auditLog.action, diff: auditLog.diff }).from(auditLog).where(and28(
|
|
29619
|
+
eq35(auditLog.projectId, project.id),
|
|
29620
|
+
inArray11(auditLog.action, ["keywords.appended", "keywords.deleted", "queries.appended", "queries.deleted", "queries.replaced"])
|
|
29621
|
+
)).orderBy(auditLog.createdAt).all();
|
|
29622
|
+
const history = replayQueryAuditLog(events);
|
|
29623
|
+
const orphanRuns = db.select({
|
|
29624
|
+
runId: runs.id,
|
|
29625
|
+
createdAt: runs.createdAt,
|
|
29626
|
+
location: runs.location
|
|
29627
|
+
}).from(runs).innerJoin(querySnapshots, eq35(querySnapshots.runId, runs.id)).where(and28(
|
|
29628
|
+
eq35(runs.projectId, project.id),
|
|
29629
|
+
isNull(querySnapshots.queryId),
|
|
29630
|
+
isNull(querySnapshots.queryText)
|
|
29631
|
+
)).groupBy(runs.id).orderBy(runs.createdAt).all();
|
|
29632
|
+
const result = {
|
|
29633
|
+
project: project.name,
|
|
29634
|
+
examinedRuns: orphanRuns.length,
|
|
29635
|
+
orphanSnapshots: 0,
|
|
29636
|
+
recoveredByPosition: 0,
|
|
29637
|
+
recoveredByContent: 0,
|
|
29638
|
+
unrecovered: 0,
|
|
29639
|
+
dryRun: isDryRun,
|
|
29640
|
+
perRun: []
|
|
29641
|
+
};
|
|
29642
|
+
const updates = [];
|
|
29643
|
+
for (const run of orphanRuns) {
|
|
29644
|
+
const activeAt = activeQueriesAt(history, run.createdAt);
|
|
29645
|
+
const orphanSnaps = db.select({
|
|
29646
|
+
id: querySnapshots.id,
|
|
29647
|
+
provider: querySnapshots.provider,
|
|
29648
|
+
createdAt: querySnapshots.createdAt,
|
|
29649
|
+
answerText: querySnapshots.answerText
|
|
29650
|
+
}).from(querySnapshots).where(and28(
|
|
29651
|
+
eq35(querySnapshots.runId, run.runId),
|
|
29652
|
+
isNull(querySnapshots.queryId),
|
|
29653
|
+
isNull(querySnapshots.queryText)
|
|
29654
|
+
)).orderBy(querySnapshots.provider, querySnapshots.createdAt).all();
|
|
29655
|
+
const byProvider = /* @__PURE__ */ new Map();
|
|
29656
|
+
for (const s of orphanSnaps) {
|
|
29657
|
+
const arr = byProvider.get(s.provider);
|
|
29658
|
+
if (arr) arr.push(s);
|
|
29659
|
+
else byProvider.set(s.provider, [s]);
|
|
29660
|
+
}
|
|
29661
|
+
let runPosition = 0;
|
|
29662
|
+
let runContent = 0;
|
|
29663
|
+
let runUnrecovered = 0;
|
|
29664
|
+
for (const [, snaps] of byProvider) {
|
|
29665
|
+
if (snaps.length === activeAt.length) {
|
|
29666
|
+
for (let i = 0; i < snaps.length; i++) {
|
|
29667
|
+
updates.push({ id: snaps[i].id, queryText: activeAt[i] });
|
|
29668
|
+
runPosition++;
|
|
29669
|
+
}
|
|
29670
|
+
} else if (snaps.length < activeAt.length) {
|
|
29671
|
+
const LOOKAHEAD_LIMIT = 5;
|
|
29672
|
+
let cidx = 0;
|
|
29673
|
+
for (const snap of snaps) {
|
|
29674
|
+
const answerText = snap.answerText ?? "";
|
|
29675
|
+
let matchedIdx = -1;
|
|
29676
|
+
for (let i = cidx; i < Math.min(activeAt.length, cidx + LOOKAHEAD_LIMIT); i++) {
|
|
29677
|
+
if (contentMatchScore(activeAt[i], answerText) >= 1) {
|
|
29678
|
+
matchedIdx = i;
|
|
29679
|
+
break;
|
|
29680
|
+
}
|
|
29681
|
+
}
|
|
29682
|
+
if (matchedIdx >= 0) {
|
|
29683
|
+
updates.push({ id: snap.id, queryText: activeAt[matchedIdx] });
|
|
29684
|
+
runContent++;
|
|
29685
|
+
cidx = matchedIdx + 1;
|
|
29686
|
+
} else {
|
|
29687
|
+
runUnrecovered++;
|
|
29688
|
+
}
|
|
29689
|
+
}
|
|
29690
|
+
} else {
|
|
29691
|
+
runUnrecovered += snaps.length;
|
|
29692
|
+
}
|
|
29693
|
+
}
|
|
29694
|
+
result.orphanSnapshots += orphanSnaps.length;
|
|
29695
|
+
result.recoveredByPosition += runPosition;
|
|
29696
|
+
result.recoveredByContent += runContent;
|
|
29697
|
+
result.unrecovered += runUnrecovered;
|
|
29698
|
+
result.perRun.push({
|
|
29699
|
+
runId: run.runId,
|
|
29700
|
+
runCreatedAt: run.createdAt,
|
|
29701
|
+
activeQueryCount: activeAt.length,
|
|
29702
|
+
orphanSnaps: orphanSnaps.length,
|
|
29703
|
+
recoveredPosition: runPosition,
|
|
29704
|
+
recoveredContent: runContent,
|
|
29705
|
+
unrecovered: runUnrecovered
|
|
29706
|
+
});
|
|
29707
|
+
if (!isJson) {
|
|
29708
|
+
process.stderr.write(
|
|
29709
|
+
` ${run.createdAt} loc=${run.location ?? "-"} \u2192 ${orphanSnaps.length} orphan; ${runPosition} position-matched, ${runContent} content-matched, ${runUnrecovered} unrecovered
|
|
29710
|
+
`
|
|
29711
|
+
);
|
|
29712
|
+
}
|
|
29713
|
+
}
|
|
29714
|
+
if (!isDryRun && updates.length > 0) {
|
|
29715
|
+
db.transaction((tx) => {
|
|
29716
|
+
for (const u of updates) {
|
|
29717
|
+
tx.update(querySnapshots).set({ queryText: u.queryText }).where(eq35(querySnapshots.id, u.id)).run();
|
|
29718
|
+
}
|
|
29719
|
+
});
|
|
29720
|
+
}
|
|
29721
|
+
if (isJson) {
|
|
29722
|
+
console.log(JSON.stringify(result, null, 2));
|
|
29723
|
+
return;
|
|
29724
|
+
}
|
|
29725
|
+
console.log(`
|
|
29726
|
+
Snapshot attribution ${isDryRun ? "preview" : "recovery"} complete.`);
|
|
29727
|
+
console.log(` Examined runs: ${result.examinedRuns}`);
|
|
29728
|
+
console.log(` Orphan snapshots: ${result.orphanSnapshots}`);
|
|
29729
|
+
console.log(` Position-matched: ${result.recoveredByPosition}`);
|
|
29730
|
+
console.log(` Content-matched: ${result.recoveredByContent}`);
|
|
29731
|
+
console.log(` Unrecovered: ${result.unrecovered}`);
|
|
29732
|
+
if (isDryRun) {
|
|
29733
|
+
console.log(`
|
|
29734
|
+
No DB writes performed. Re-run without --dry-run to apply.`);
|
|
29735
|
+
}
|
|
29736
|
+
}
|
|
27054
29737
|
function reparseProviderSnapshot(provider, rawResponse) {
|
|
27055
29738
|
const envelope = parseJsonColumn(rawResponse, {});
|
|
27056
29739
|
const apiResponse = resolveStoredApiResponse(envelope);
|
|
@@ -27098,6 +29781,157 @@ function stringifyStoredSnapshotEnvelope(rawResponse, reparsed) {
|
|
|
27098
29781
|
...apiResponse ? { apiResponse } : {}
|
|
27099
29782
|
});
|
|
27100
29783
|
}
|
|
29784
|
+
async function backfillTrafficClassificationCommand(opts) {
|
|
29785
|
+
const config = loadConfig();
|
|
29786
|
+
const db = createClient(config.database);
|
|
29787
|
+
migrate(db);
|
|
29788
|
+
const projectFilter = opts?.project?.trim();
|
|
29789
|
+
const isDryRun = opts?.dryRun === true;
|
|
29790
|
+
const isJson = opts?.format === "json";
|
|
29791
|
+
const scopedProjects = projectFilter ? db.select().from(projects).where(eq35(projects.name, projectFilter)).all() : db.select().from(projects).all();
|
|
29792
|
+
if (scopedProjects.length === 0) {
|
|
29793
|
+
if (projectFilter && !isJson) {
|
|
29794
|
+
process.stderr.write(`No project named "${projectFilter}".
|
|
29795
|
+
`);
|
|
29796
|
+
}
|
|
29797
|
+
if (isJson) console.log(JSON.stringify({ project: projectFilter ?? null, examined: 0, reclassified: 0 }));
|
|
29798
|
+
return;
|
|
29799
|
+
}
|
|
29800
|
+
if (!isJson) {
|
|
29801
|
+
const mode = isDryRun ? " [DRY RUN \u2014 no writes]" : "";
|
|
29802
|
+
const scope = projectFilter ? `"${projectFilter}"` : "all projects";
|
|
29803
|
+
process.stderr.write(`Re-classifying unknown traffic samples for ${scope}${mode}...
|
|
29804
|
+
`);
|
|
29805
|
+
}
|
|
29806
|
+
const projectIds = scopedProjects.map((p) => p.id);
|
|
29807
|
+
const result = {
|
|
29808
|
+
project: projectFilter ?? null,
|
|
29809
|
+
examined: 0,
|
|
29810
|
+
reclassified: 0,
|
|
29811
|
+
unknownBefore: 0,
|
|
29812
|
+
unknownAfter: 0,
|
|
29813
|
+
dryRun: isDryRun,
|
|
29814
|
+
byBot: {}
|
|
29815
|
+
};
|
|
29816
|
+
const unknownCountRow = db.select({ n: sql15`count(*)` }).from(rawEventSamples).where(and28(
|
|
29817
|
+
eq35(rawEventSamples.eventType, "unknown"),
|
|
29818
|
+
inArray11(rawEventSamples.projectId, projectIds)
|
|
29819
|
+
)).get();
|
|
29820
|
+
result.unknownBefore = Number(unknownCountRow?.n ?? 0);
|
|
29821
|
+
const unknownSamples = db.select({
|
|
29822
|
+
id: rawEventSamples.id,
|
|
29823
|
+
projectId: rawEventSamples.projectId,
|
|
29824
|
+
sourceId: rawEventSamples.sourceId,
|
|
29825
|
+
ts: rawEventSamples.ts,
|
|
29826
|
+
userAgent: rawEventSamples.userAgent,
|
|
29827
|
+
pathNormalized: rawEventSamples.pathNormalized,
|
|
29828
|
+
status: rawEventSamples.status
|
|
29829
|
+
}).from(rawEventSamples).where(and28(
|
|
29830
|
+
eq35(rawEventSamples.eventType, "unknown"),
|
|
29831
|
+
inArray11(rawEventSamples.projectId, projectIds)
|
|
29832
|
+
)).all();
|
|
29833
|
+
result.examined = unknownSamples.length;
|
|
29834
|
+
if (unknownSamples.length === 0) {
|
|
29835
|
+
result.unknownAfter = result.unknownBefore;
|
|
29836
|
+
emitTrafficClassificationReport(result, isJson);
|
|
29837
|
+
return;
|
|
29838
|
+
}
|
|
29839
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
29840
|
+
for (const snap of unknownSamples) {
|
|
29841
|
+
if (!snap.userAgent) continue;
|
|
29842
|
+
const probe = {
|
|
29843
|
+
sourceType: TrafficSourceTypes["cloud-run"],
|
|
29844
|
+
evidenceKind: TrafficEvidenceKinds["raw-request"],
|
|
29845
|
+
confidence: TrafficEventConfidences.observed,
|
|
29846
|
+
eventId: snap.id,
|
|
29847
|
+
observedAt: snap.ts,
|
|
29848
|
+
method: "GET",
|
|
29849
|
+
requestUrl: `https://placeholder${snap.pathNormalized}`,
|
|
29850
|
+
host: "placeholder",
|
|
29851
|
+
path: snap.pathNormalized,
|
|
29852
|
+
queryString: null,
|
|
29853
|
+
status: snap.status ?? 200,
|
|
29854
|
+
userAgent: snap.userAgent,
|
|
29855
|
+
remoteIp: null,
|
|
29856
|
+
referer: null,
|
|
29857
|
+
latencyMs: null,
|
|
29858
|
+
requestSizeBytes: null,
|
|
29859
|
+
responseSizeBytes: null,
|
|
29860
|
+
providerResource: { type: "cloud_run_revision", labels: {} },
|
|
29861
|
+
providerLabels: {}
|
|
29862
|
+
};
|
|
29863
|
+
const classified = classifyCrawler(probe);
|
|
29864
|
+
if (!classified) continue;
|
|
29865
|
+
result.reclassified++;
|
|
29866
|
+
result.byBot[classified.botId] = (result.byBot[classified.botId] ?? 0) + 1;
|
|
29867
|
+
if (isDryRun) continue;
|
|
29868
|
+
db.update(rawEventSamples).set({ eventType: TrafficEventKinds.crawler }).where(eq35(rawEventSamples.id, snap.id)).run();
|
|
29869
|
+
const tsHour = new Date(snap.ts);
|
|
29870
|
+
tsHour.setUTCMinutes(0, 0, 0);
|
|
29871
|
+
db.insert(crawlerEventsHourly).values({
|
|
29872
|
+
projectId: snap.projectId,
|
|
29873
|
+
sourceId: snap.sourceId,
|
|
29874
|
+
tsHour: tsHour.toISOString(),
|
|
29875
|
+
botId: classified.botId,
|
|
29876
|
+
operator: classified.operator,
|
|
29877
|
+
verificationStatus: classified.verificationStatus,
|
|
29878
|
+
pathNormalized: snap.pathNormalized,
|
|
29879
|
+
status: snap.status ?? 200,
|
|
29880
|
+
hits: 1,
|
|
29881
|
+
sampledUserAgent: snap.userAgent,
|
|
29882
|
+
createdAt: now,
|
|
29883
|
+
updatedAt: now
|
|
29884
|
+
}).onConflictDoUpdate({
|
|
29885
|
+
target: [
|
|
29886
|
+
crawlerEventsHourly.projectId,
|
|
29887
|
+
crawlerEventsHourly.sourceId,
|
|
29888
|
+
crawlerEventsHourly.tsHour,
|
|
29889
|
+
crawlerEventsHourly.botId,
|
|
29890
|
+
crawlerEventsHourly.verificationStatus,
|
|
29891
|
+
crawlerEventsHourly.pathNormalized,
|
|
29892
|
+
crawlerEventsHourly.status
|
|
29893
|
+
],
|
|
29894
|
+
set: {
|
|
29895
|
+
hits: sql15`${crawlerEventsHourly.hits} + 1`,
|
|
29896
|
+
updatedAt: now
|
|
29897
|
+
}
|
|
29898
|
+
}).run();
|
|
29899
|
+
}
|
|
29900
|
+
if (!isDryRun) {
|
|
29901
|
+
const afterRow = db.select({ n: sql15`count(*)` }).from(rawEventSamples).where(and28(
|
|
29902
|
+
eq35(rawEventSamples.eventType, "unknown"),
|
|
29903
|
+
inArray11(rawEventSamples.projectId, projectIds)
|
|
29904
|
+
)).get();
|
|
29905
|
+
result.unknownAfter = Number(afterRow?.n ?? 0);
|
|
29906
|
+
} else {
|
|
29907
|
+
result.unknownAfter = result.unknownBefore - result.reclassified;
|
|
29908
|
+
}
|
|
29909
|
+
emitTrafficClassificationReport(result, isJson);
|
|
29910
|
+
}
|
|
29911
|
+
function emitTrafficClassificationReport(result, isJson) {
|
|
29912
|
+
if (isJson) {
|
|
29913
|
+
console.log(JSON.stringify(result, null, 2));
|
|
29914
|
+
return;
|
|
29915
|
+
}
|
|
29916
|
+
const verb = result.dryRun ? "Would re-classify" : "Re-classified";
|
|
29917
|
+
console.log(`
|
|
29918
|
+
Traffic classification ${result.dryRun ? "preview" : "recovery"} complete.`);
|
|
29919
|
+
console.log(` Examined unknowns: ${result.examined}`);
|
|
29920
|
+
console.log(` ${verb}: ${result.reclassified}`);
|
|
29921
|
+
console.log(` Unknown before: ${result.unknownBefore}`);
|
|
29922
|
+
console.log(` Unknown after: ${result.unknownAfter}`);
|
|
29923
|
+
if (result.reclassified > 0) {
|
|
29924
|
+
console.log(` By bot:`);
|
|
29925
|
+
const sorted = Object.entries(result.byBot).sort(([, a], [, b]) => b - a);
|
|
29926
|
+
for (const [bot, count] of sorted) {
|
|
29927
|
+
console.log(` ${count.toString().padStart(5)} ${bot}`);
|
|
29928
|
+
}
|
|
29929
|
+
}
|
|
29930
|
+
if (result.dryRun) {
|
|
29931
|
+
console.log(`
|
|
29932
|
+
No DB writes performed. Re-run without --dry-run to apply.`);
|
|
29933
|
+
}
|
|
29934
|
+
}
|
|
27101
29935
|
|
|
27102
29936
|
// src/provider-registry.ts
|
|
27103
29937
|
var ProviderRegistry = class {
|
|
@@ -27650,7 +30484,7 @@ import crypto34 from "crypto";
|
|
|
27650
30484
|
import { eq as eq40 } from "drizzle-orm";
|
|
27651
30485
|
|
|
27652
30486
|
// src/agent/session.ts
|
|
27653
|
-
import
|
|
30487
|
+
import fs14 from "fs";
|
|
27654
30488
|
import path14 from "path";
|
|
27655
30489
|
import { Agent } from "@mariozechner/pi-agent-core";
|
|
27656
30490
|
import { registerBuiltInApiProviders } from "@mariozechner/pi-ai";
|
|
@@ -27791,7 +30625,7 @@ function buildAgentProvidersResponse(config) {
|
|
|
27791
30625
|
}
|
|
27792
30626
|
|
|
27793
30627
|
// src/agent/skill-paths.ts
|
|
27794
|
-
import
|
|
30628
|
+
import fs12 from "fs";
|
|
27795
30629
|
import path12 from "path";
|
|
27796
30630
|
import { fileURLToPath } from "url";
|
|
27797
30631
|
function resolveAeroSkillDir(pkgDir) {
|
|
@@ -27802,14 +30636,14 @@ function resolveAeroSkillDir(pkgDir) {
|
|
|
27802
30636
|
path12.join(here, "../../../../skills/aero")
|
|
27803
30637
|
];
|
|
27804
30638
|
for (const candidate of candidates) {
|
|
27805
|
-
if (
|
|
30639
|
+
if (fs12.existsSync(path12.join(candidate, "SKILL.md"))) return candidate;
|
|
27806
30640
|
}
|
|
27807
30641
|
throw new Error(`Aero skill not found. Searched:
|
|
27808
30642
|
${candidates.join("\n ")}`);
|
|
27809
30643
|
}
|
|
27810
30644
|
|
|
27811
30645
|
// src/agent/skill-tools.ts
|
|
27812
|
-
import
|
|
30646
|
+
import fs13 from "fs";
|
|
27813
30647
|
import path13 from "path";
|
|
27814
30648
|
import { Type } from "@sinclair/typebox";
|
|
27815
30649
|
var MAX_DOC_CHARS = 2e4;
|
|
@@ -27832,12 +30666,12 @@ function parseDescription(body) {
|
|
|
27832
30666
|
}
|
|
27833
30667
|
function scanSkillDocs(skillDir) {
|
|
27834
30668
|
const refsDir = path13.join(skillDir ?? resolveAeroSkillDir(), "references");
|
|
27835
|
-
if (!
|
|
30669
|
+
if (!fs13.existsSync(refsDir)) return [];
|
|
27836
30670
|
const entries = [];
|
|
27837
|
-
for (const file of
|
|
30671
|
+
for (const file of fs13.readdirSync(refsDir)) {
|
|
27838
30672
|
if (!file.endsWith(".md")) continue;
|
|
27839
30673
|
const filePath = path13.join(refsDir, file);
|
|
27840
|
-
const body =
|
|
30674
|
+
const body = fs13.readFileSync(filePath, "utf-8");
|
|
27841
30675
|
entries.push({
|
|
27842
30676
|
slug: file.replace(/\.md$/, ""),
|
|
27843
30677
|
description: parseDescription(body),
|
|
@@ -27881,7 +30715,7 @@ function buildReadSkillDocTool() {
|
|
|
27881
30715
|
});
|
|
27882
30716
|
}
|
|
27883
30717
|
const filePath = path13.join(skillDir, "references", `${match.slug}.md`);
|
|
27884
|
-
const content =
|
|
30718
|
+
const content = fs13.readFileSync(filePath, "utf-8");
|
|
27885
30719
|
if (content.length > MAX_DOC_CHARS) {
|
|
27886
30720
|
return textResult({
|
|
27887
30721
|
slug: match.slug,
|
|
@@ -27975,10 +30809,10 @@ function ensureBuiltinsRegistered() {
|
|
|
27975
30809
|
}
|
|
27976
30810
|
function loadAeroSystemPrompt(pkgDir) {
|
|
27977
30811
|
const skillDir = resolveAeroSkillDir(pkgDir);
|
|
27978
|
-
const skillBody =
|
|
30812
|
+
const skillBody = fs14.readFileSync(path14.join(skillDir, "SKILL.md"), "utf-8");
|
|
27979
30813
|
const soulPath = path14.join(skillDir, "soul.md");
|
|
27980
|
-
if (!
|
|
27981
|
-
const soulBody =
|
|
30814
|
+
if (!fs14.existsSync(soulPath)) return skillBody;
|
|
30815
|
+
const soulBody = fs14.readFileSync(soulPath, "utf-8");
|
|
27982
30816
|
return `${soulBody.trimEnd()}
|
|
27983
30817
|
|
|
27984
30818
|
---
|
|
@@ -28036,7 +30870,7 @@ function resolveSessionProviderAndModel(config, opts) {
|
|
|
28036
30870
|
|
|
28037
30871
|
// src/agent/memory-store.ts
|
|
28038
30872
|
import crypto33 from "crypto";
|
|
28039
|
-
import { and as and31, desc as desc18, eq as eq39, like as like2, sql as
|
|
30873
|
+
import { and as and31, desc as desc18, eq as eq39, like as like2, sql as sql16 } from "drizzle-orm";
|
|
28040
30874
|
var COMPACTION_KEY_PREFIX = "compaction:";
|
|
28041
30875
|
var COMPACTION_NOTES_PER_SESSION = 3;
|
|
28042
30876
|
function rowToDto2(row) {
|
|
@@ -28122,7 +30956,7 @@ function writeCompactionNote(db, args) {
|
|
|
28122
30956
|
).orderBy(desc18(agentMemory.updatedAt)).all();
|
|
28123
30957
|
const stale = existing.slice(COMPACTION_NOTES_PER_SESSION).map((r) => r.id);
|
|
28124
30958
|
if (stale.length > 0) {
|
|
28125
|
-
tx.delete(agentMemory).where(
|
|
30959
|
+
tx.delete(agentMemory).where(sql16`${agentMemory.id} IN (${sql16.join(stale.map((s) => sql16`${s}`), sql16`, `)})`).run();
|
|
28126
30960
|
}
|
|
28127
30961
|
const row = tx.select().from(agentMemory).where(and31(eq39(agentMemory.projectId, args.projectId), eq39(agentMemory.key, key))).get();
|
|
28128
30962
|
if (row) inserted = rowToDto2(row);
|
|
@@ -29915,7 +32749,7 @@ async function createServer(opts) {
|
|
|
29915
32749
|
jobRunner.onRunCompleted = (runId, projectId) => runCoordinator.onRunCompleted(runId, projectId);
|
|
29916
32750
|
const snapshotService = new SnapshotService(registry);
|
|
29917
32751
|
const orphanedOpenClawDir = path15.join(os6.homedir(), ".openclaw-aero");
|
|
29918
|
-
if (
|
|
32752
|
+
if (fs15.existsSync(orphanedOpenClawDir)) {
|
|
29919
32753
|
app.log.warn(
|
|
29920
32754
|
{ path: orphanedOpenClawDir },
|
|
29921
32755
|
"OpenClaw gateway is no longer used. Remove ~/.openclaw-aero/ manually to reclaim the directory."
|
|
@@ -30262,6 +33096,24 @@ async function createServer(opts) {
|
|
|
30262
33096
|
sessionCookieName: SESSION_COOKIE_NAME,
|
|
30263
33097
|
resolveSessionApiKeyId,
|
|
30264
33098
|
explainContentRecommendation,
|
|
33099
|
+
// On-disk paths the daemon depends on. The api-routes plugin uses these
|
|
33100
|
+
// to fail loud (HTTP 503) when the operator wipes the DB or config out
|
|
33101
|
+
// from under a running serve — SQLite holds the inode open across
|
|
33102
|
+
// `unlink`, so without this the daemon keeps serving stale data from
|
|
33103
|
+
// an orphaned file and `rm ~/.canonry/data.db` silently does nothing.
|
|
33104
|
+
//
|
|
33105
|
+
// Only attach `configPath` if it actually exists at construction time:
|
|
33106
|
+
// production always boots via `serveCommand`, which calls `loadConfig()`
|
|
33107
|
+
// and would have thrown if the file were missing; tests that construct
|
|
33108
|
+
// `createServer` directly (bypassing `loadConfig`) won't have written
|
|
33109
|
+
// a config and shouldn't get 503s from a stub-missing file.
|
|
33110
|
+
runtimeStatePaths: (() => {
|
|
33111
|
+
const configPath = getConfigPath();
|
|
33112
|
+
return {
|
|
33113
|
+
databasePath: opts.config.database,
|
|
33114
|
+
configPath: fs15.existsSync(configPath) ? configPath : null
|
|
33115
|
+
};
|
|
33116
|
+
})(),
|
|
30265
33117
|
// Local canonry serve runs on the operator's machine, where pointing a
|
|
30266
33118
|
// webhook at localhost (Discord test container, Pipedream-mock dev server,
|
|
30267
33119
|
// etc.) is a legitimate workflow. Default to allowing it for the local
|
|
@@ -30634,7 +33486,7 @@ async function createServer(opts) {
|
|
|
30634
33486
|
});
|
|
30635
33487
|
const dirname = path15.dirname(fileURLToPath2(import.meta.url));
|
|
30636
33488
|
const assetsDir = path15.join(dirname, "..", "assets");
|
|
30637
|
-
if (
|
|
33489
|
+
if (fs15.existsSync(assetsDir)) {
|
|
30638
33490
|
const indexPath = path15.join(assetsDir, "index.html");
|
|
30639
33491
|
const injectConfig = (html) => {
|
|
30640
33492
|
const clientConfig = {};
|
|
@@ -30667,8 +33519,8 @@ async function createServer(opts) {
|
|
|
30667
33519
|
}
|
|
30668
33520
|
});
|
|
30669
33521
|
const serveIndex = (_request, reply) => {
|
|
30670
|
-
if (
|
|
30671
|
-
const html =
|
|
33522
|
+
if (fs15.existsSync(indexPath)) {
|
|
33523
|
+
const html = fs15.readFileSync(indexPath, "utf-8");
|
|
30672
33524
|
return reply.header("Cache-Control", "no-cache, must-revalidate").type("text/html").send(injectConfig(html));
|
|
30673
33525
|
}
|
|
30674
33526
|
return reply.status(404).send({ error: "Dashboard not built" });
|
|
@@ -30688,8 +33540,8 @@ async function createServer(opts) {
|
|
|
30688
33540
|
if (basePath && !url.startsWith(basePath)) {
|
|
30689
33541
|
return reply.status(404).send({ error: "Not found", path: request.url });
|
|
30690
33542
|
}
|
|
30691
|
-
if (
|
|
30692
|
-
const html =
|
|
33543
|
+
if (fs15.existsSync(indexPath)) {
|
|
33544
|
+
const html = fs15.readFileSync(indexPath, "utf-8");
|
|
30693
33545
|
return reply.header("Cache-Control", "no-cache, must-revalidate").type("text/html").send(injectConfig(html));
|
|
30694
33546
|
}
|
|
30695
33547
|
return reply.status(404).send({ error: "Not found" });
|
|
@@ -30777,6 +33629,8 @@ export {
|
|
|
30777
33629
|
backfillAiReferralPathsCommand,
|
|
30778
33630
|
backfillAnswerMentionsCommand,
|
|
30779
33631
|
backfillInsightsCommand,
|
|
33632
|
+
backfillSnapshotAttributionCommand,
|
|
33633
|
+
backfillTrafficClassificationCommand,
|
|
30780
33634
|
renderReportHtml,
|
|
30781
33635
|
setGoogleAuthConfig,
|
|
30782
33636
|
formatAuditFactorScore,
|