@canonry/canonry 4.128.0 → 4.129.1
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/README.md +15 -10
- package/assets/agent-workspace/skills/aero/SKILL.md +15 -7
- package/assets/agent-workspace/skills/aero/references/aeo-discovery.md +3 -1
- package/assets/agent-workspace/skills/aero/references/orchestration.md +5 -3
- package/assets/agent-workspace/skills/aero/soul.md +1 -1
- package/assets/agent-workspace/skills/canonry/SKILL.md +50 -13
- package/assets/agent-workspace/skills/canonry/references/canonry-cli.md +9 -1
- package/assets/agent-workspace/skills/canonry/references/indexing.md +4 -2
- package/assets/assets/{AuditHistoryPanel-DwJpVWme.js → AuditHistoryPanel-wJqs99Ak.js} +1 -1
- package/assets/assets/{BacklinksPage-K8FQUBxI.js → BacklinksPage-BBDExYo_.js} +1 -1
- package/assets/assets/{ChartPrimitives-6oFKrJFk.js → ChartPrimitives-DSr5ldMf.js} +1 -1
- package/assets/assets/{HistoryPage-DwOAoN1Z.js → HistoryPage-Ca-GGnTI.js} +1 -1
- package/assets/assets/{ProjectPage-CdgFUk7h.js → ProjectPage-BuaSDSwf.js} +1 -1
- package/assets/assets/{RunRow-lt9IS99U.js → RunRow-O9TbOdQY.js} +1 -1
- package/assets/assets/{RunsPage-DitYcIdx.js → RunsPage-C1Sqd7AN.js} +1 -1
- package/assets/assets/{SettingsPage-CAOrh65Q.js → SettingsPage-DPFh62BV.js} +1 -1
- package/assets/assets/{TrafficPage-BqzNvx75.js → TrafficPage-5vKoQyoP.js} +1 -1
- package/assets/assets/TrafficSourceDetailPage-D17oADs8.js +1 -0
- package/assets/assets/{arrow-left-AmG4gtUR.js → arrow-left-De5P5AIE.js} +1 -1
- package/assets/assets/extract-error-message-BqMd-fQ6.js +1 -0
- package/assets/assets/{index-BiCDkOH4.js → index-C1ABEgkr.js} +53 -53
- package/assets/assets/{trash-2-gFHWd1A1.js → trash-2-6ZpABj9G.js} +1 -1
- package/assets/index.html +1 -1
- package/dist/{chunk-ZKUSY4PI.js → chunk-GYAKRVE2.js} +25 -5
- package/dist/{chunk-BLSHHRRU.js → chunk-K4FDDCYG.js} +29 -0
- package/dist/{chunk-NCFH26X5.js → chunk-LPEE5AYY.js} +198 -25
- package/dist/{chunk-IHRW6WWV.js → chunk-WWZE7VDQ.js} +10 -6
- package/dist/cli.js +226 -38
- package/dist/index.d.ts +3 -1
- package/dist/index.js +4 -4
- package/dist/{intelligence-service-SH5Z6JFT.js → intelligence-service-2QBAGT5X.js} +2 -2
- package/dist/mcp.js +2 -2
- package/package.json +7 -7
- package/assets/assets/TrafficSourceDetailPage-DXbygZUA.js +0 -1
- package/assets/assets/extract-error-message-DlVtjoPz.js +0 -1
package/dist/cli.js
CHANGED
|
@@ -29,7 +29,7 @@ import {
|
|
|
29
29
|
setTelemetrySource,
|
|
30
30
|
showFirstRunNotice,
|
|
31
31
|
trackEvent
|
|
32
|
-
} from "./chunk-
|
|
32
|
+
} from "./chunk-GYAKRVE2.js";
|
|
33
33
|
import {
|
|
34
34
|
CliError,
|
|
35
35
|
EXIT_SYSTEM_ERROR,
|
|
@@ -46,7 +46,7 @@ import {
|
|
|
46
46
|
saveConfig,
|
|
47
47
|
saveConfigPatch,
|
|
48
48
|
usageError
|
|
49
|
-
} from "./chunk-
|
|
49
|
+
} from "./chunk-WWZE7VDQ.js";
|
|
50
50
|
import {
|
|
51
51
|
apiKeys,
|
|
52
52
|
createClient,
|
|
@@ -54,7 +54,7 @@ import {
|
|
|
54
54
|
projects,
|
|
55
55
|
queries,
|
|
56
56
|
renderReportHtml
|
|
57
|
-
} from "./chunk-
|
|
57
|
+
} from "./chunk-LPEE5AYY.js";
|
|
58
58
|
import {
|
|
59
59
|
AdsOperationKinds,
|
|
60
60
|
AdsOperationStates,
|
|
@@ -68,6 +68,7 @@ import {
|
|
|
68
68
|
REPORT_PERIOD_OPTIONS,
|
|
69
69
|
RunStatuses,
|
|
70
70
|
TrafficEventKinds,
|
|
71
|
+
TrafficSeriesGranularities,
|
|
71
72
|
adsActivateTreeRequestSchema,
|
|
72
73
|
adsActivationGrantCreateRequestSchema,
|
|
73
74
|
adsAdCreateRequestSchema,
|
|
@@ -95,7 +96,7 @@ import {
|
|
|
95
96
|
providerQuotaPolicySchema,
|
|
96
97
|
resolveProviderInput,
|
|
97
98
|
winnabilityClassSchema
|
|
98
|
-
} from "./chunk-
|
|
99
|
+
} from "./chunk-K4FDDCYG.js";
|
|
99
100
|
|
|
100
101
|
// src/cli.ts
|
|
101
102
|
import { pathToFileURL } from "url";
|
|
@@ -141,9 +142,9 @@ import { parseArgs } from "util";
|
|
|
141
142
|
function commandId(spec) {
|
|
142
143
|
return spec.path.join(".");
|
|
143
144
|
}
|
|
144
|
-
function matchesPath(args,
|
|
145
|
-
if (args.length <
|
|
146
|
-
return
|
|
145
|
+
function matchesPath(args, path12) {
|
|
146
|
+
if (args.length < path12.length) return false;
|
|
147
|
+
return path12.every((segment, index) => args[index] === segment);
|
|
147
148
|
}
|
|
148
149
|
function withGlobalOptions(options) {
|
|
149
150
|
const base = options ? { ...options } : {};
|
|
@@ -3506,9 +3507,9 @@ async function gaConnect(project, opts) {
|
|
|
3506
3507
|
propertyId: opts.propertyId
|
|
3507
3508
|
};
|
|
3508
3509
|
if (opts.keyFile) {
|
|
3509
|
-
const
|
|
3510
|
+
const fs16 = await import("fs");
|
|
3510
3511
|
try {
|
|
3511
|
-
const content =
|
|
3512
|
+
const content = fs16.readFileSync(opts.keyFile, "utf-8");
|
|
3512
3513
|
JSON.parse(content);
|
|
3513
3514
|
body.keyJson = content;
|
|
3514
3515
|
} catch (e) {
|
|
@@ -4766,9 +4767,9 @@ async function getCommand(opts) {
|
|
|
4766
4767
|
console.log(JSON.stringify(leaf, null, 2));
|
|
4767
4768
|
}
|
|
4768
4769
|
}
|
|
4769
|
-
function walkPath(value,
|
|
4770
|
-
if (!
|
|
4771
|
-
const segments =
|
|
4770
|
+
function walkPath(value, path12) {
|
|
4771
|
+
if (!path12 || path12 === ".") return value;
|
|
4772
|
+
const segments = path12.split(".").flatMap((part) => {
|
|
4772
4773
|
const tokens = [];
|
|
4773
4774
|
let i = 0;
|
|
4774
4775
|
const bracketStart = part.indexOf("[");
|
|
@@ -4816,13 +4817,13 @@ var GET_CLI_COMMANDS = [
|
|
|
4816
4817
|
},
|
|
4817
4818
|
run: async (input) => {
|
|
4818
4819
|
const project = requireProject(input, "get", USAGE2);
|
|
4819
|
-
const
|
|
4820
|
+
const path12 = requirePositional(input, 1, {
|
|
4820
4821
|
command: "get",
|
|
4821
4822
|
usage: USAGE2,
|
|
4822
4823
|
message: 'path is required (e.g. "scores.mentionShare.value")'
|
|
4823
4824
|
});
|
|
4824
4825
|
const from = getString(input.values, "from");
|
|
4825
|
-
await getCommand({ project, path:
|
|
4826
|
+
await getCommand({ project, path: path12, from, format: input.format });
|
|
4826
4827
|
}
|
|
4827
4828
|
}
|
|
4828
4829
|
];
|
|
@@ -4861,9 +4862,9 @@ async function trafficConnectWordpress(project, opts) {
|
|
|
4861
4862
|
}
|
|
4862
4863
|
let applicationPassword = opts.appPassword?.trim() ?? "";
|
|
4863
4864
|
if (!applicationPassword && opts.appPasswordFile) {
|
|
4864
|
-
const
|
|
4865
|
+
const fs16 = await import("fs");
|
|
4865
4866
|
try {
|
|
4866
|
-
applicationPassword =
|
|
4867
|
+
applicationPassword = fs16.readFileSync(opts.appPasswordFile, "utf-8").trim();
|
|
4867
4868
|
} catch (e) {
|
|
4868
4869
|
const msg = e instanceof Error ? e.message : String(e);
|
|
4869
4870
|
throw new CliError({
|
|
@@ -4919,10 +4920,10 @@ async function trafficConnectCloudRun(project, opts) {
|
|
|
4919
4920
|
details: { project }
|
|
4920
4921
|
});
|
|
4921
4922
|
}
|
|
4922
|
-
const
|
|
4923
|
+
const fs16 = await import("fs");
|
|
4923
4924
|
let keyJson;
|
|
4924
4925
|
try {
|
|
4925
|
-
keyJson =
|
|
4926
|
+
keyJson = fs16.readFileSync(opts.serviceAccountKey, "utf-8");
|
|
4926
4927
|
JSON.parse(keyJson);
|
|
4927
4928
|
} catch (e) {
|
|
4928
4929
|
const msg = e instanceof Error ? e.message : String(e);
|
|
@@ -4982,9 +4983,9 @@ async function trafficConnectVercel(project, opts) {
|
|
|
4982
4983
|
}
|
|
4983
4984
|
let token = opts.token?.trim() ?? "";
|
|
4984
4985
|
if (!token && opts.tokenFile) {
|
|
4985
|
-
const
|
|
4986
|
+
const fs16 = await import("fs");
|
|
4986
4987
|
try {
|
|
4987
|
-
token =
|
|
4988
|
+
token = fs16.readFileSync(opts.tokenFile, "utf-8").trim();
|
|
4988
4989
|
} catch (e) {
|
|
4989
4990
|
const msg = e instanceof Error ? e.message : String(e);
|
|
4990
4991
|
throw new CliError({
|
|
@@ -5276,10 +5277,19 @@ async function trafficEvents(project, opts) {
|
|
|
5276
5277
|
details: { project, kind: opts.kind }
|
|
5277
5278
|
});
|
|
5278
5279
|
}
|
|
5280
|
+
if (opts.granularity && opts.granularity !== TrafficSeriesGranularities.hour && opts.granularity !== TrafficSeriesGranularities.day) {
|
|
5281
|
+
throw new CliError({
|
|
5282
|
+
code: "TRAFFIC_INVALID_GRANULARITY",
|
|
5283
|
+
message: `--granularity must be one of: ${TrafficSeriesGranularities.hour}, ${TrafficSeriesGranularities.day}`,
|
|
5284
|
+
displayMessage: `Error: --granularity must be "${TrafficSeriesGranularities.hour}" or "${TrafficSeriesGranularities.day}"`,
|
|
5285
|
+
details: { project, granularity: opts.granularity }
|
|
5286
|
+
});
|
|
5287
|
+
}
|
|
5279
5288
|
const params = {};
|
|
5280
5289
|
if (opts.kind && opts.kind !== "all") params.kind = opts.kind;
|
|
5281
5290
|
if (opts.source) params.sourceId = opts.source;
|
|
5282
5291
|
if (opts.limit !== void 0) params.limit = opts.limit;
|
|
5292
|
+
if (opts.granularity) params.granularity = opts.granularity;
|
|
5283
5293
|
if (opts.sinceMinutes !== void 0) {
|
|
5284
5294
|
const since = new Date(Date.now() - opts.sinceMinutes * 6e4).toISOString();
|
|
5285
5295
|
params.since = since;
|
|
@@ -5531,14 +5541,15 @@ var TRAFFIC_CLI_COMMANDS = [
|
|
|
5531
5541
|
},
|
|
5532
5542
|
{
|
|
5533
5543
|
path: ["traffic", "events"],
|
|
5534
|
-
usage: "canonry traffic events <project> [--kind crawler|ai-referral|all] [--source <id>] [--since-minutes 1440] [--since <iso>] [--until <iso>] [--limit 500] [--format json]",
|
|
5544
|
+
usage: "canonry traffic events <project> [--kind crawler|ai-referral|all] [--source <id>] [--since-minutes 1440] [--since <iso>] [--until <iso>] [--limit 500] [--granularity hour|day] [--format json]",
|
|
5535
5545
|
options: {
|
|
5536
5546
|
kind: stringOption(),
|
|
5537
5547
|
source: stringOption(),
|
|
5538
5548
|
"since-minutes": stringOption(),
|
|
5539
5549
|
since: stringOption(),
|
|
5540
5550
|
until: stringOption(),
|
|
5541
|
-
limit: stringOption()
|
|
5551
|
+
limit: stringOption(),
|
|
5552
|
+
granularity: stringOption()
|
|
5542
5553
|
},
|
|
5543
5554
|
run: async (input) => {
|
|
5544
5555
|
const project = requireProject(
|
|
@@ -5559,6 +5570,7 @@ var TRAFFIC_CLI_COMMANDS = [
|
|
|
5559
5570
|
await trafficEvents(project, {
|
|
5560
5571
|
kind: getString(input.values, "kind"),
|
|
5561
5572
|
source: getString(input.values, "source"),
|
|
5573
|
+
granularity: getString(input.values, "granularity"),
|
|
5562
5574
|
sinceMinutes,
|
|
5563
5575
|
since: getString(input.values, "since"),
|
|
5564
5576
|
until: getString(input.values, "until"),
|
|
@@ -12026,6 +12038,177 @@ function encodeSetupState(state) {
|
|
|
12026
12038
|
return flags.length > 0 ? flags.sort().join("|") : "none";
|
|
12027
12039
|
}
|
|
12028
12040
|
|
|
12041
|
+
// src/agent-plugin.ts
|
|
12042
|
+
import fs14 from "fs";
|
|
12043
|
+
import path11 from "path";
|
|
12044
|
+
var CANONRY_PLUGIN_ID = "canonry@canonry";
|
|
12045
|
+
var REQUIRED_SKILLS = ["canonry", "aero"];
|
|
12046
|
+
function parseSemver(version) {
|
|
12047
|
+
const match = /^(\d+)\.(\d+)\.(\d+)(?:-([0-9a-z.-]+))?(?:\+[0-9a-z.-]+)?$/i.exec(version);
|
|
12048
|
+
if (!match) return null;
|
|
12049
|
+
return {
|
|
12050
|
+
core: [Number(match[1]), Number(match[2]), Number(match[3])],
|
|
12051
|
+
prerelease: match.at(4)?.split(".")
|
|
12052
|
+
};
|
|
12053
|
+
}
|
|
12054
|
+
function compareSemver(left, right) {
|
|
12055
|
+
const leftVersion = parseSemver(left);
|
|
12056
|
+
const rightVersion = parseSemver(right);
|
|
12057
|
+
for (let index = 0; index < leftVersion.core.length; index += 1) {
|
|
12058
|
+
if (leftVersion.core[index] !== rightVersion.core[index]) {
|
|
12059
|
+
return leftVersion.core[index] > rightVersion.core[index] ? 1 : -1;
|
|
12060
|
+
}
|
|
12061
|
+
}
|
|
12062
|
+
if (!leftVersion.prerelease && !rightVersion.prerelease) return 0;
|
|
12063
|
+
if (!leftVersion.prerelease) return 1;
|
|
12064
|
+
if (!rightVersion.prerelease) return -1;
|
|
12065
|
+
const length = Math.max(leftVersion.prerelease.length, rightVersion.prerelease.length);
|
|
12066
|
+
for (let index = 0; index < length; index += 1) {
|
|
12067
|
+
const leftIdentifier = leftVersion.prerelease.at(index);
|
|
12068
|
+
const rightIdentifier = rightVersion.prerelease.at(index);
|
|
12069
|
+
if (leftIdentifier === void 0) return -1;
|
|
12070
|
+
if (rightIdentifier === void 0) return 1;
|
|
12071
|
+
if (leftIdentifier === rightIdentifier) continue;
|
|
12072
|
+
const leftNumeric = /^\d+$/.test(leftIdentifier);
|
|
12073
|
+
const rightNumeric = /^\d+$/.test(rightIdentifier);
|
|
12074
|
+
if (leftNumeric && rightNumeric) return Number(leftIdentifier) > Number(rightIdentifier) ? 1 : -1;
|
|
12075
|
+
if (leftNumeric !== rightNumeric) return leftNumeric ? -1 : 1;
|
|
12076
|
+
return leftIdentifier > rightIdentifier ? 1 : -1;
|
|
12077
|
+
}
|
|
12078
|
+
return 0;
|
|
12079
|
+
}
|
|
12080
|
+
function isCanonryPluginId(value) {
|
|
12081
|
+
return value.trim() === CANONRY_PLUGIN_ID;
|
|
12082
|
+
}
|
|
12083
|
+
function readJson(filePath) {
|
|
12084
|
+
try {
|
|
12085
|
+
return JSON.parse(fs14.readFileSync(filePath, "utf8"));
|
|
12086
|
+
} catch {
|
|
12087
|
+
return null;
|
|
12088
|
+
}
|
|
12089
|
+
}
|
|
12090
|
+
function readClaudePluginConfigured(filePath) {
|
|
12091
|
+
const parsed = readJson(filePath);
|
|
12092
|
+
if (!parsed || typeof parsed !== "object") return false;
|
|
12093
|
+
const enabledPlugins = parsed.enabledPlugins;
|
|
12094
|
+
if (!enabledPlugins || typeof enabledPlugins !== "object") return false;
|
|
12095
|
+
for (const [id, enabled] of Object.entries(enabledPlugins)) {
|
|
12096
|
+
if (isCanonryPluginId(id)) return enabled === true;
|
|
12097
|
+
}
|
|
12098
|
+
return false;
|
|
12099
|
+
}
|
|
12100
|
+
function readCodexPluginConfigured(filePath) {
|
|
12101
|
+
try {
|
|
12102
|
+
let currentPlugin = null;
|
|
12103
|
+
let inPluginsTable = false;
|
|
12104
|
+
for (const line of fs14.readFileSync(filePath, "utf8").split(/\r?\n/)) {
|
|
12105
|
+
const section = /^\s*\[plugins\.(?:"([^"]+)"|'([^']+)'|(\S+))\]\s*(?:#.*)?$/.exec(line);
|
|
12106
|
+
if (section) {
|
|
12107
|
+
const captures = section.slice(1, 4);
|
|
12108
|
+
currentPlugin = captures.find((value) => value != null && value.length > 0) ?? null;
|
|
12109
|
+
inPluginsTable = false;
|
|
12110
|
+
continue;
|
|
12111
|
+
}
|
|
12112
|
+
if (/^\s*\[plugins\]\s*(?:#.*)?$/.test(line)) {
|
|
12113
|
+
currentPlugin = null;
|
|
12114
|
+
inPluginsTable = true;
|
|
12115
|
+
continue;
|
|
12116
|
+
}
|
|
12117
|
+
if (/^\s*\[/.test(line)) {
|
|
12118
|
+
currentPlugin = null;
|
|
12119
|
+
inPluginsTable = false;
|
|
12120
|
+
continue;
|
|
12121
|
+
}
|
|
12122
|
+
if (currentPlugin && isCanonryPluginId(currentPlugin)) {
|
|
12123
|
+
const enabled = /^\s*enabled\s*=\s*(true|false)\s*(?:#.*)?$/.exec(line);
|
|
12124
|
+
if (enabled) return enabled[1] === "true";
|
|
12125
|
+
} else if (inPluginsTable) {
|
|
12126
|
+
const inline = /^\s*(?:"([^"]+)"|'([^']+)'|([^=\s]+))\s*=\s*\{[^}]*\benabled\s*=\s*(true|false)\b[^}]*\}\s*(?:#.*)?$/.exec(line);
|
|
12127
|
+
const id = inline?.[1] ?? inline?.[2] ?? inline?.[3];
|
|
12128
|
+
if (inline && id && isCanonryPluginId(id)) return inline[4] === "true";
|
|
12129
|
+
}
|
|
12130
|
+
}
|
|
12131
|
+
return false;
|
|
12132
|
+
} catch {
|
|
12133
|
+
return false;
|
|
12134
|
+
}
|
|
12135
|
+
}
|
|
12136
|
+
function verifiedPluginVersion(root, client) {
|
|
12137
|
+
const manifestDir = client === "claude-code" ? ".claude-plugin" : ".codex-plugin";
|
|
12138
|
+
const manifest = readJson(path11.join(root, manifestDir, "plugin.json"));
|
|
12139
|
+
if (!manifest || typeof manifest !== "object") return null;
|
|
12140
|
+
const plugin = manifest;
|
|
12141
|
+
if (plugin.name !== "canonry" || typeof plugin.version !== "string" || !parseSemver(plugin.version) || plugin.skills !== "./skills/" || plugin.mcpServers !== "./.mcp.json") {
|
|
12142
|
+
return null;
|
|
12143
|
+
}
|
|
12144
|
+
const mcp = readJson(path11.join(root, ".mcp.json"));
|
|
12145
|
+
if (!mcp || typeof mcp !== "object") return null;
|
|
12146
|
+
const canonryServer = mcp.mcpServers?.canonry;
|
|
12147
|
+
if (canonryServer?.command !== "canonry-mcp") return null;
|
|
12148
|
+
return REQUIRED_SKILLS.every((name) => fs14.existsSync(path11.join(root, "skills", name, "SKILL.md"))) ? plugin.version : null;
|
|
12149
|
+
}
|
|
12150
|
+
function readClaudeUserInstallPaths(claudeConfigDir) {
|
|
12151
|
+
const parsed = readJson(path11.join(claudeConfigDir, "plugins", "installed_plugins.json"));
|
|
12152
|
+
if (!parsed || typeof parsed !== "object") return [];
|
|
12153
|
+
const plugins = parsed.plugins;
|
|
12154
|
+
if (!plugins || typeof plugins !== "object") return [];
|
|
12155
|
+
const installs = plugins[CANONRY_PLUGIN_ID];
|
|
12156
|
+
if (!Array.isArray(installs)) return [];
|
|
12157
|
+
return installs.flatMap((install) => {
|
|
12158
|
+
if (!install || typeof install !== "object") return [];
|
|
12159
|
+
const record = install;
|
|
12160
|
+
return record.scope === "user" && typeof record.installPath === "string" ? [record.installPath] : [];
|
|
12161
|
+
});
|
|
12162
|
+
}
|
|
12163
|
+
function listDirectories(dir) {
|
|
12164
|
+
try {
|
|
12165
|
+
return fs14.readdirSync(dir, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => path11.join(dir, entry.name));
|
|
12166
|
+
} catch {
|
|
12167
|
+
return [];
|
|
12168
|
+
}
|
|
12169
|
+
}
|
|
12170
|
+
function newestVersion(versions) {
|
|
12171
|
+
return versions.sort(compareSemver).at(-1) ?? null;
|
|
12172
|
+
}
|
|
12173
|
+
function verifiedClaudeVersion(claudeConfigDir) {
|
|
12174
|
+
return newestVersion(readClaudeUserInstallPaths(claudeConfigDir).map((installPath) => verifiedPluginVersion(installPath, "claude-code")).filter((version) => version !== null));
|
|
12175
|
+
}
|
|
12176
|
+
function verifiedCodexVersion(codexHome) {
|
|
12177
|
+
const pluginCache = path11.join(codexHome, "plugins", "cache", "canonry", "canonry");
|
|
12178
|
+
const versionedRoots = listDirectories(pluginCache).map((installPath) => ({ installPath, version: path11.basename(installPath) })).filter((candidate) => parseSemver(candidate.version) !== null).sort((left, right) => compareSemver(left.version, right.version));
|
|
12179
|
+
const active = versionedRoots.at(-1);
|
|
12180
|
+
if (!active) return verifiedPluginVersion(pluginCache, "codex");
|
|
12181
|
+
const manifestVersion = verifiedPluginVersion(active.installPath, "codex");
|
|
12182
|
+
return manifestVersion === active.version ? manifestVersion : null;
|
|
12183
|
+
}
|
|
12184
|
+
function detectCanonryAgentPlugin(opts = {}) {
|
|
12185
|
+
const home = opts.home?.trim() || null;
|
|
12186
|
+
const claudeConfigDir = opts.claudeConfigDir?.trim() || (home ? path11.join(home, ".claude") : null);
|
|
12187
|
+
const codexHome = opts.codexHome?.trim() || (home ? path11.join(home, ".codex") : null);
|
|
12188
|
+
const configuredClients = [];
|
|
12189
|
+
const verifiedClients = [];
|
|
12190
|
+
const verifiedClientVersions = {};
|
|
12191
|
+
const claudeConfigured = claudeConfigDir ? readClaudePluginConfigured(path11.join(claudeConfigDir, "settings.json")) : false;
|
|
12192
|
+
if (claudeConfigured) {
|
|
12193
|
+
configuredClients.push("claude-code");
|
|
12194
|
+
const version = claudeConfigDir ? verifiedClaudeVersion(claudeConfigDir) : null;
|
|
12195
|
+
if (version) {
|
|
12196
|
+
verifiedClients.push("claude-code");
|
|
12197
|
+
verifiedClientVersions["claude-code"] = version;
|
|
12198
|
+
}
|
|
12199
|
+
}
|
|
12200
|
+
const codexConfigured = codexHome ? readCodexPluginConfigured(path11.join(codexHome, "config.toml")) : false;
|
|
12201
|
+
if (codexConfigured) {
|
|
12202
|
+
configuredClients.push("codex");
|
|
12203
|
+
const version = codexHome ? verifiedCodexVersion(codexHome) : null;
|
|
12204
|
+
if (version) {
|
|
12205
|
+
verifiedClients.push("codex");
|
|
12206
|
+
verifiedClientVersions.codex = version;
|
|
12207
|
+
}
|
|
12208
|
+
}
|
|
12209
|
+
return { configuredClients, verifiedClients, verifiedClientVersions };
|
|
12210
|
+
}
|
|
12211
|
+
|
|
12029
12212
|
// src/commands/serve.ts
|
|
12030
12213
|
function resolveServePort(envPort, configPort) {
|
|
12031
12214
|
const trimmed = envPort?.trim();
|
|
@@ -12063,7 +12246,12 @@ async function serveCommand(format = "text") {
|
|
|
12063
12246
|
process.stderr.write(`warning: ai-referral-paths backfill skipped: ${msg}
|
|
12064
12247
|
`);
|
|
12065
12248
|
}
|
|
12066
|
-
const
|
|
12249
|
+
const getAgentPluginState = () => detectCanonryAgentPlugin({
|
|
12250
|
+
home: process.env.HOME,
|
|
12251
|
+
claudeConfigDir: process.env.CLAUDE_CONFIG_DIR,
|
|
12252
|
+
codexHome: process.env.CODEX_HOME
|
|
12253
|
+
});
|
|
12254
|
+
const app = await createServer({ config, db, host, getAgentPluginState });
|
|
12067
12255
|
let shuttingDown = false;
|
|
12068
12256
|
const shutdown = (signal) => {
|
|
12069
12257
|
if (shuttingDown) return;
|
|
@@ -12099,7 +12287,7 @@ Canonry server running at ${url}`);
|
|
|
12099
12287
|
console.log("First-run dashboard password setup is unauthenticated only on loopback; complete setup from this machine first or use a bearer cnry_... key.");
|
|
12100
12288
|
}
|
|
12101
12289
|
console.log("Press Ctrl+C to stop.\n");
|
|
12102
|
-
const nudge = getMissingUserSkillsNudge(process.env.HOME);
|
|
12290
|
+
const nudge = getMissingUserSkillsNudge(process.env.HOME, getAgentPluginState());
|
|
12103
12291
|
if (nudge) process.stderr.write(`${nudge.message}
|
|
12104
12292
|
`);
|
|
12105
12293
|
}
|
|
@@ -12855,7 +13043,7 @@ var VISIBILITY_STATS_CLI_COMMANDS = [
|
|
|
12855
13043
|
];
|
|
12856
13044
|
|
|
12857
13045
|
// src/cli-commands/wordpress.ts
|
|
12858
|
-
import
|
|
13046
|
+
import fs15 from "fs";
|
|
12859
13047
|
|
|
12860
13048
|
// src/commands/wordpress.ts
|
|
12861
13049
|
function getClient26() {
|
|
@@ -13094,12 +13282,12 @@ async function wordpressSetMeta(project, body) {
|
|
|
13094
13282
|
printPageDetail(result);
|
|
13095
13283
|
}
|
|
13096
13284
|
async function wordpressBulkSetMeta(project, opts) {
|
|
13097
|
-
const
|
|
13098
|
-
const
|
|
13099
|
-
const filePath =
|
|
13285
|
+
const fs16 = await import("fs/promises");
|
|
13286
|
+
const path12 = await import("path");
|
|
13287
|
+
const filePath = path12.resolve(opts.from);
|
|
13100
13288
|
let raw;
|
|
13101
13289
|
try {
|
|
13102
|
-
raw = await
|
|
13290
|
+
raw = await fs16.readFile(filePath, "utf8");
|
|
13103
13291
|
} catch {
|
|
13104
13292
|
throw new CliError({
|
|
13105
13293
|
code: "FILE_READ_ERROR",
|
|
@@ -13196,13 +13384,13 @@ async function wordpressSetSchema(project, body) {
|
|
|
13196
13384
|
printManualAssist(`Schema update for "${body.slug}"`, result);
|
|
13197
13385
|
}
|
|
13198
13386
|
async function wordpressSchemaDeploy(project, opts) {
|
|
13199
|
-
const
|
|
13200
|
-
const
|
|
13387
|
+
const fs16 = await import("fs/promises");
|
|
13388
|
+
const path12 = await import("path");
|
|
13201
13389
|
const yaml = await loadYamlModule();
|
|
13202
|
-
const filePath =
|
|
13390
|
+
const filePath = path12.resolve(opts.profile);
|
|
13203
13391
|
let raw;
|
|
13204
13392
|
try {
|
|
13205
|
-
raw = await
|
|
13393
|
+
raw = await fs16.readFile(filePath, "utf8");
|
|
13206
13394
|
} catch {
|
|
13207
13395
|
throw new CliError({
|
|
13208
13396
|
code: "FILE_READ_ERROR",
|
|
@@ -13307,13 +13495,13 @@ async function wordpressOnboard(project, opts) {
|
|
|
13307
13495
|
}
|
|
13308
13496
|
let profileData;
|
|
13309
13497
|
if (opts.profile) {
|
|
13310
|
-
const
|
|
13311
|
-
const
|
|
13498
|
+
const fs16 = await import("fs/promises");
|
|
13499
|
+
const path12 = await import("path");
|
|
13312
13500
|
const yaml = await loadYamlModule();
|
|
13313
|
-
const filePath =
|
|
13501
|
+
const filePath = path12.resolve(opts.profile);
|
|
13314
13502
|
let raw;
|
|
13315
13503
|
try {
|
|
13316
|
-
raw = await
|
|
13504
|
+
raw = await fs16.readFile(filePath, "utf8");
|
|
13317
13505
|
} catch {
|
|
13318
13506
|
throw new CliError({
|
|
13319
13507
|
code: "FILE_READ_ERROR",
|
|
@@ -13462,7 +13650,7 @@ function resolveContent(input, command, usage, options) {
|
|
|
13462
13650
|
}
|
|
13463
13651
|
if (contentFile) {
|
|
13464
13652
|
try {
|
|
13465
|
-
return
|
|
13653
|
+
return fs15.readFileSync(contentFile, "utf-8");
|
|
13466
13654
|
} catch (error) {
|
|
13467
13655
|
const message = error instanceof Error ? error.message : String(error);
|
|
13468
13656
|
throw usageError(`Error: could not read --content-file "${contentFile}": ${message}`, {
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { FastifyInstance } from 'fastify';
|
|
2
2
|
import { DatabaseClient } from '@ainyc/canonry-db';
|
|
3
|
-
import { ProviderQuotaPolicy, EmbedConfigEntry } from '@ainyc/canonry-contracts';
|
|
3
|
+
import { ProviderQuotaPolicy, EmbedConfigEntry, AgentPluginState } from '@ainyc/canonry-contracts';
|
|
4
4
|
|
|
5
5
|
type GoogleConnectionType = 'gsc' | 'ga4' | 'gbp';
|
|
6
6
|
interface ProviderConfigEntry {
|
|
@@ -264,6 +264,8 @@ declare function createServer(opts: {
|
|
|
264
264
|
* assert the injected config + framing header on the served document.
|
|
265
265
|
*/
|
|
266
266
|
assetsDir?: string;
|
|
267
|
+
/** Live user-global native Canonry plugin state for agent-skills doctor checks. */
|
|
268
|
+
getAgentPluginState?: () => AgentPluginState;
|
|
267
269
|
}): Promise<FastifyInstance>;
|
|
268
270
|
|
|
269
271
|
export { type CanonryConfig, createServer, loadConfig };
|
package/dist/index.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
2
|
createServer
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-GYAKRVE2.js";
|
|
4
4
|
import {
|
|
5
5
|
loadConfig
|
|
6
|
-
} from "./chunk-
|
|
7
|
-
import "./chunk-
|
|
8
|
-
import "./chunk-
|
|
6
|
+
} from "./chunk-WWZE7VDQ.js";
|
|
7
|
+
import "./chunk-LPEE5AYY.js";
|
|
8
|
+
import "./chunk-K4FDDCYG.js";
|
|
9
9
|
export {
|
|
10
10
|
createServer,
|
|
11
11
|
loadConfig
|
package/dist/mcp.js
CHANGED
|
@@ -3,10 +3,10 @@ import {
|
|
|
3
3
|
PACKAGE_VERSION,
|
|
4
4
|
canonryMcpTools,
|
|
5
5
|
createApiClient
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-WWZE7VDQ.js";
|
|
7
7
|
import {
|
|
8
8
|
isReadOnlyKey
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-K4FDDCYG.js";
|
|
10
10
|
|
|
11
11
|
// src/mcp/cli.ts
|
|
12
12
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@canonry/canonry",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.129.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Agent-first open-source AEO operating platform - track how answer engines cite your domain",
|
|
6
6
|
"license": "FSL-1.1-ALv2",
|
|
@@ -65,26 +65,26 @@
|
|
|
65
65
|
"@types/node-cron": "^3.0.11",
|
|
66
66
|
"tsup": "^8.5.1",
|
|
67
67
|
"tsx": "^4.19.0",
|
|
68
|
-
"@ainyc/canonry-api-routes": "0.0.0",
|
|
69
68
|
"@ainyc/canonry-api-client": "0.0.0",
|
|
69
|
+
"@ainyc/canonry-api-routes": "0.0.0",
|
|
70
70
|
"@ainyc/canonry-config": "0.0.0",
|
|
71
71
|
"@ainyc/canonry-contracts": "0.0.0",
|
|
72
72
|
"@ainyc/canonry-db": "0.0.0",
|
|
73
73
|
"@ainyc/canonry-integration-bing": "0.0.0",
|
|
74
|
-
"@ainyc/canonry-integration-commoncrawl": "0.0.0",
|
|
75
|
-
"@ainyc/canonry-integration-google": "0.0.0",
|
|
76
74
|
"@ainyc/canonry-integration-openai-ads": "0.0.0",
|
|
77
|
-
"@ainyc/canonry-integration-
|
|
75
|
+
"@ainyc/canonry-integration-commoncrawl": "0.0.0",
|
|
78
76
|
"@ainyc/canonry-integration-google-business-profile": "0.0.0",
|
|
79
77
|
"@ainyc/canonry-integration-google-places": "0.0.0",
|
|
80
78
|
"@ainyc/canonry-integration-wordpress": "0.0.0",
|
|
81
|
-
"@ainyc/canonry-integration-
|
|
79
|
+
"@ainyc/canonry-integration-google": "0.0.0",
|
|
80
|
+
"@ainyc/canonry-integration-cloud-run": "0.0.0",
|
|
82
81
|
"@ainyc/canonry-intelligence": "0.0.0",
|
|
82
|
+
"@ainyc/canonry-integration-traffic": "0.0.0",
|
|
83
83
|
"@ainyc/canonry-provider-cdp": "0.0.0",
|
|
84
84
|
"@ainyc/canonry-provider-claude": "0.0.0",
|
|
85
85
|
"@ainyc/canonry-provider-gemini": "0.0.0",
|
|
86
|
-
"@ainyc/canonry-provider-local": "0.0.0",
|
|
87
86
|
"@ainyc/canonry-provider-openai": "0.0.0",
|
|
87
|
+
"@ainyc/canonry-provider-local": "0.0.0",
|
|
88
88
|
"@ainyc/canonry-provider-perplexity": "0.0.0"
|
|
89
89
|
},
|
|
90
90
|
"scripts": {
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{j as e,B as $e,C as Ue,r as h,L as Ee}from"./vendor-tanstack-Be8JdV5M.js";import{I as D,ci as Y,cj as u,T as Fe,i as le,B as Me,g as P,b as He,ck as Pe,cl as Oe}from"./index-BiCDkOH4.js";import{g as De,h as _e,i as Be,t as ze,R as Ge,d as Ke}from"./extract-error-message-DlVtjoPz.js";import{e as ee,i as We,C as ie,a as ce,c as Ve,h as Ye}from"./ChartPrimitives-6oFKrJFk.js";import{R as Xe,B as Qe,a as qe,X as Ze,Y as Je,T as et,f as X,g as Q}from"./vendor-recharts-DSxTZhaH.js";import{A as oe}from"./arrow-left-AmG4gtUR.js";import"./vendor-radix-CQ77EO2y.js";import"./vendor-markdown-6dwjPOKK.js";function q({value:s,label:a,delta:l,tone:n,description:x,tooltip:i,isNumeric:c=!0,progress:o,providerCoverage:d}){const v=2*Math.PI*48,m=Number.parseInt(s,10),L=typeof o=="number"&&Number.isFinite(o)?Math.min(Math.max(o,0),100)/100:c&&!Number.isNaN(m)?Math.min(m/100,1):.5,j=v*(1-L);return e.jsxs("div",{className:"score-gauge",children:[e.jsxs("div",{className:"gauge-ring-wrapper",children:[e.jsxs("svg",{className:"gauge-ring",viewBox:"0 0 120 120","aria-hidden":"true",children:[e.jsx("circle",{className:"gauge-bg",cx:"60",cy:"60",r:48,strokeWidth:6}),e.jsx("circle",{className:`gauge-fill gauge-fill-${n}`,cx:"60",cy:"60",r:48,strokeWidth:6,strokeDasharray:v,strokeDashoffset:j,transform:"rotate(-90 60 60)"})]}),e.jsx("div",{className:"gauge-center",children:e.jsx("span",{className:c?"gauge-value":"gauge-value-text",children:s.split(" / ")[0]})})]}),e.jsxs("p",{className:"gauge-label",children:[a,i&&e.jsx(D,{text:i})]}),e.jsx("p",{className:"gauge-delta",children:l}),d&&e.jsx("p",{className:"gauge-provider-coverage",children:d}),e.jsx("p",{className:"gauge-description",children:x})]})}const tt=[{value:"all",label:"All status"},{value:"2xx",label:"2xx success"},{value:"3xx",label:"3xx redirect"},{value:"4xx",label:"4xx client error"},{value:"5xx",label:"5xx server error"}],pe=[{value:"all",label:"All claims"},{value:Y.verified,label:"Verified"},{value:Y.claimed_unverified,label:"Claimed unverified"},{value:Y.unknown_ai_like,label:"Unknown AI-like"}];function st(s){return s==="all"?null:Number.parseInt(s[0],10)}function ge(s){switch(s.kind){case u.crawler:case u["ai-user-fetch"]:return s.botId;case u["ai-referral"]:return s.product}}function be(s){switch(s.kind){case u.crawler:case u["ai-user-fetch"]:return s.pathNormalized;case u["ai-referral"]:return s.landingPathNormalized}}function at(s){switch(s.kind){case u.crawler:case u["ai-user-fetch"]:return s.verificationStatus;case u["ai-referral"]:return null}}function ye(s,a){if(a==="hour")return s;const l=new Date(s),n=l.getFullYear(),x=String(l.getMonth()+1).padStart(2,"0"),i=String(l.getDate()).padStart(2,"0");return`${n}-${x}-${i}`}function rt(s,a,l){const n=a.pathQuery.trim().toLowerCase(),x=st(a.statusClass);return s.filter(i=>!(a.selectedBucket&&ye(i.tsHour,l)!==a.selectedBucket||a.identity&&ge(i)!==a.identity||a.operator&&i.operator!==a.operator||n&&!be(i).toLowerCase().includes(n)||x!==null&&Math.floor(i.status/100)!==x||a.verification!=="all"&&at(i)!==a.verification))}function nt(s,a){if(!s||typeof s!="object")return null;const l=s.activeTooltipIndex;let n;if(typeof l=="number")n=l;else if(typeof l=="string"&&l!=="")n=Number(l);else return null;return!Number.isInteger(n)||n<0||n>=a.length?null:a[n]?.bucket??null}const _=[{value:60,label:"1h",granularity:"hour",fetchLimit:500},{value:360,label:"6h",granularity:"hour",fetchLimit:500},{value:1440,label:"24h",granularity:"hour",fetchLimit:500},{value:10080,label:"7d",granularity:"hour",fetchLimit:1e3},{value:720*60,label:"30d",granularity:"day",fetchLimit:2e3},{value:2160*60,label:"90d",granularity:"day",fetchLimit:5e3}],ue=_.find(s=>s.label==="24h")??_[2],$=50,de=ee[0],xe=ee[2],he=ee[1],me=Pe();function je(s){const a=new Date(s);return`${a.getMonth()+1}/${a.getDate()} ${String(a.getHours()).padStart(2,"0")}:00`}function lt(s){const a=new Date(`${s}T00:00:00`);return`${a.getMonth()+1}/${a.getDate()}`}function U(s){if(!s)return"never";const a=Date.now()-new Date(s).getTime(),l=Math.floor(a/6e4);if(l<1)return"just now";if(l<60)return`${l}m ago`;const n=Math.floor(l/60);return n<24?`${n}h ago`:`${Math.floor(n/24)}d ago`}function fe({canGoBack:s,className:a}){const l="inline-flex items-center gap-1";if(s){const n=()=>{window.history.back()};return e.jsxs("button",{type:"button",onClick:n,className:`${l} ${a??""}`,children:[e.jsx(oe,{className:"size-3"})," Back"]})}return e.jsxs(Ee,{to:"/traffic",className:`${l} ${a??""}`,children:[e.jsx(oe,{className:"size-3"})," All sources"]})}function vt(){const s=$e({strict:!1}),a=s.projectName??"",l=Ue(),n=s.sourceId??"",[x,i]=h.useState(ue.value),[c,o]=h.useState(()=>new Set(["crawler","ai-user-fetch","ai-referral"])),[d,C]=h.useState(null),[f,v]=h.useState(""),[m,L]=h.useState(""),[j,B]=h.useState(""),[k,z]=h.useState("all"),[T,G]=h.useState("all"),[ve,K]=h.useState(1),[te,se]=h.useState(null),[ae,re]=h.useState(null),b=h.useMemo(()=>_.find(t=>t.value===x)??ue,[x]),W=De(a||null,n||null),y=_e(a||null,{kind:"all",sourceId:n||void 0,sinceMinutes:x,limit:b.fetchLimit}),E=Be(a||null,n||null),r=W.data,N=y.data?.events??[],S=y.data?.totals,F=h.useMemo(()=>N.filter(t=>{switch(t.kind){case u.crawler:return c.has("crawler");case u["ai-user-fetch"]:return c.has("ai-user-fetch");case u["ai-referral"]:return c.has("ai-referral")}}),[N,c]),Ne=h.useMemo(()=>{const t=new Set;for(const p of N)t.add(ge(p));return f&&t.add(f),[...t].sort((p,g)=>p.localeCompare(g))},[N,f]),Se=h.useMemo(()=>{const t=new Set;for(const p of N)t.add(p.operator);return m&&t.add(m),[...t].sort((p,g)=>p.localeCompare(g))},[N,m]),w=h.useMemo(()=>rt(F,{selectedBucket:d,identity:f,operator:m,pathQuery:j,statusClass:k,verification:T},b.granularity),[F,d,f,m,j,k,T,b.granularity]);h.useEffect(()=>{K(1)},[F,d,f,m,j,k,T]);const M=Math.max(1,Math.ceil(w.length/$)),H=Math.min(Math.max(1,ve),M),R=(H-1)*$,we=h.useMemo(()=>w.slice(R,R+$),[w,R]),Ce=w.length>$,ke=w.length===0?0:R+1,Te=Math.min(R+$,w.length),ne=h.useMemo(()=>d?O(d,b.granularity):null,[d,b.granularity]),I=h.useMemo(()=>it(N,b.granularity,y.data?.windowStart,y.data?.windowEnd),[N,b.granularity,y.data?.windowStart,y.data?.windowEnd]),V=t=>{o(p=>{const g=new Set(p);return g.has(t)?g.size>1&&g.delete(t):g.add(t),g})},Ie=t=>{const p=nt(t,I);p&&C(g=>g===p?null:p)},Ae=()=>{C(null),v(""),L(""),B(""),z("all"),G("all")},Le=!!(d||f||m||j.trim()||k!=="all"||T!=="all"),Re=async()=>{se(null),re(null);try{const t=await E.mutateAsync({sinceMinutes:60});re(`Pulled ${t.pulledEvents} entries · ${t.crawlerHits} crawler · ${t.aiUserFetchHits} AI user fetch · ${t.aiReferralHits} AI referral · ${t.unknownHits} unknown`)}catch(t){se(Ke(t))}};return!a||!n?e.jsx("div",{className:"page-container",children:e.jsx("p",{className:"text-sm text-muted",children:"Missing project name or source id in URL."})}):W.isLoading?e.jsx("div",{className:"page-container",children:e.jsx("p",{className:"text-sm text-muted",children:"Loading source…"})}):W.isError||!r?e.jsxs("div",{className:"page-container",children:[e.jsx("p",{className:"text-sm text-negative",children:"Could not load this source."}),e.jsx(fe,{canGoBack:l,className:"mt-2 text-xs text-secondary hover:text-strong"})]}):e.jsxs("div",{className:"page-container space-y-8",children:[e.jsxs("div",{className:"page-header",children:[e.jsxs("div",{className:"page-header-left",children:[e.jsx(fe,{canGoBack:l,className:"text-xs text-muted hover:text-strong"}),e.jsx("h1",{className:"page-title mt-2",children:r.displayName}),e.jsxs("p",{className:"page-subtitle",children:[r.sourceType," · project ",e.jsx("span",{className:"text-neutral",children:a})," ·",e.jsx("span",{className:"ml-1 font-mono text-secondary",children:r.id})]})]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(Fe,{tone:ze(r.status),children:r.status}),!le()&&e.jsxs(Me,{type:"button",variant:"outline",size:"sm",disabled:E.isPending,onClick:()=>{Re()},children:[e.jsx(Ge,{className:`size-3.5 ${E.isPending?"animate-spin":""}`}),E.isPending?"Syncing…":"Sync now"]})]})]}),te?e.jsx("div",{className:"rounded-md border border-negative-800/50 bg-negative-950/30 px-3 py-2 text-xs text-negative-200",children:te}):null,ae?e.jsx("div",{className:"rounded-md border border-positive-800/50 bg-positive-950/30 px-3 py-2 text-xs text-positive-200",children:ae}):null,e.jsxs("section",{className:"grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3",children:[e.jsx(q,{label:"24h content crawls",value:String(r.totals24h.crawlerContentHits),delta:r.lastSyncedAt?`last sync ${U(r.lastSyncedAt)}`:"never synced",tone:r.totals24h.crawlerContentHits>0?"positive":"neutral",description:`Pages crawled — ${r.totals24h.crawlerInfraHits.toLocaleString("en-US")} sitemap/robots/asset fetches excluded.`,tooltip:`Content-page crawls by GPTBot, OAI-SearchBot, PerplexityBot, Googlebot, etc. Infrastructure fetches (sitemap ${r.totals24h.crawlerSegments.sitemap.toLocaleString("en-US")}, robots ${r.totals24h.crawlerSegments.robots.toLocaleString("en-US")}, assets ${r.totals24h.crawlerSegments.asset.toLocaleString("en-US")}) are tracked separately so polling doesn't inflate this number. Total crawler hits: ${r.totals24h.crawlerHits.toLocaleString("en-US")}.`,isNumeric:!0,progress:Math.min(100,Math.round(r.totals24h.crawlerContentHits/1e3*100))}),e.jsx(q,{label:"24h AI user fetches",value:String(r.totals24h.aiUserFetchHits),delta:r.lastSyncedAt?`last sync ${U(r.lastSyncedAt)}`:"never synced",tone:r.totals24h.aiUserFetchHits>0?"positive":"neutral",description:"ChatGPT-User, Perplexity-User — fetches initiated by a real user inside an AI surface (citation click, URL read).",isNumeric:!0,progress:Math.min(100,Math.round(r.totals24h.aiUserFetchHits/1e3*100))}),e.jsx(q,{label:"24h AI referral sessions",value:String(r.totals24h.aiReferralHits),delta:r.lastSyncedAt?`last sync ${U(r.lastSyncedAt)}`:"never synced",tone:r.totals24h.aiReferralHits>0?"positive":"neutral",description:"Browser click-throughs from chatgpt.com, perplexity.ai, etc. (Referer / UTM evidence).",isNumeric:!0,progress:Math.min(100,Math.round(r.totals24h.aiReferralHits/1e3*100))})]}),e.jsxs("section",{children:[e.jsx("p",{className:"mb-4 text-[10px] font-semibold uppercase tracking-wider text-muted",children:"Latest sync run"}),r.latestRun?e.jsxs(P,{className:"p-4 text-sm",children:[e.jsxs("div",{className:"flex flex-wrap items-center gap-x-6 gap-y-1.5",children:[e.jsxs("span",{className:"text-heading",children:["Status: ",e.jsx("span",{className:"font-medium",children:r.latestRun.status})]}),e.jsxs("span",{className:"text-muted",children:["Started: ",U(r.latestRun.startedAt)]}),r.latestRun.finishedAt?e.jsxs("span",{className:"text-muted",children:["Finished: ",U(r.latestRun.finishedAt)]}):null,e.jsx("span",{className:"font-mono text-[11px] text-faint",children:r.latestRun.runId})]}),r.latestRun.error?e.jsx("p",{className:"mt-2 rounded border border-negative-900/40 bg-negative-950/30 px-3 py-2 text-xs text-negative",children:r.latestRun.error}):null]}):e.jsx(P,{className:"px-4 py-3 text-sm text-muted",children:le()?"No traffic-sync runs recorded yet.":'No traffic-sync runs recorded yet. Hit "Sync now" above to create one.'})]}),e.jsxs("section",{children:[e.jsxs("div",{className:"mb-4 flex flex-wrap items-end justify-between gap-x-4 gap-y-3",children:[e.jsxs("div",{children:[e.jsx("p",{className:"text-[10px] font-semibold uppercase tracking-wider text-muted",children:"Events"}),e.jsx("h2",{className:"mt-1 text-base font-semibold text-primary",children:b.granularity==="day"?"Daily rollups":"Hourly rollups"}),S?e.jsxs("p",{className:"mt-1.5 text-xs text-muted",children:[S.crawlerContentHits.toLocaleString("en-US")," content crawls ·"," ",S.crawlerInfraHits.toLocaleString("en-US")," infra (sitemap/robots/assets) ·"," ",S.aiUserFetchHits.toLocaleString("en-US")," AI user fetches ·"," ",S.aiReferralHits.toLocaleString("en-US")," AI referral sessions · last ",b.label," · ",me]}):null]}),e.jsx("div",{className:"filter-row mb-0",role:"toolbar","aria-label":"Window",children:_.map(t=>e.jsx("button",{type:"button",className:`filter-chip ${x===t.value?"filter-chip-active":""}`,"aria-pressed":x===t.value,onClick:()=>{i(t.value),C(null)},children:t.label},t.value))})]}),e.jsxs(P,{className:"p-4",children:[e.jsxs("div",{className:"mb-3 flex flex-wrap items-center gap-2",role:"toolbar","aria-label":"Series",children:[e.jsx(J,{label:"Crawler",color:de,count:S?.crawlerHits??0,active:c.has("crawler"),onToggle:()=>V("crawler")}),e.jsx(J,{label:"AI user fetches",color:xe,count:S?.aiUserFetchHits??0,active:c.has("ai-user-fetch"),onToggle:()=>V("ai-user-fetch")}),e.jsx(J,{label:"AI referral sessions",color:he,count:S?.aiReferralHits??0,active:c.has("ai-referral"),onToggle:()=>V("ai-referral")})]}),y.isError?e.jsxs("p",{className:"py-12 text-center text-xs text-negative-400",children:["Failed to load events: ",y.error instanceof Error?y.error.message:"Unknown error"]}):y.isLoading?e.jsx("p",{className:"py-12 text-center text-xs text-muted",children:"Loading events…"}):I.length===0?e.jsx("p",{className:"py-12 text-center text-xs text-muted",children:"No events in this window."}):e.jsx("div",{className:"h-72",children:e.jsx(Xe,{children:e.jsxs(Qe,{data:I,margin:{top:4,right:4,bottom:0,left:0},onClick:Ie,style:{cursor:"pointer"},children:[e.jsx(qe,{stroke:We,strokeDasharray:"3 3"}),e.jsx(Ze,{dataKey:"label",tick:ce,stroke:ie,interval:"preserveStartEnd",minTickGap:b.granularity==="day"?24:32}),e.jsx(Je,{tick:ce,stroke:ie,allowDecimals:!1}),e.jsx(et,{...Ve}),c.has("crawler")?e.jsx(X,{dataKey:"crawler",name:"Crawler",fill:de,stackId:"a",children:I.map(t=>e.jsx(Q,{fillOpacity:d&&d!==t.bucket?.25:1},t.bucket))}):null,c.has("ai-user-fetch")?e.jsx(X,{dataKey:"aiUserFetch",name:"AI user fetch",fill:xe,stackId:"a",children:I.map(t=>e.jsx(Q,{fillOpacity:d&&d!==t.bucket?.25:1},t.bucket))}):null,c.has("ai-referral")?e.jsx(X,{dataKey:"aiReferral",name:"AI referral",fill:he,stackId:"a",children:I.map(t=>e.jsx(Q,{fillOpacity:d&&d!==t.bucket?.25:1},t.bucket))}):null]})})})]})]}),e.jsxs("section",{children:[e.jsxs("div",{className:"mb-4 flex flex-wrap items-end justify-between gap-x-4 gap-y-2",children:[e.jsxs("div",{children:[e.jsx("p",{className:"text-[10px] font-semibold uppercase tracking-wider text-muted",children:"Event rows"}),e.jsxs("p",{className:"mt-1 text-xs text-muted",children:["Showing ",e.jsx("span",{className:"tabular-nums text-neutral",children:w.length.toLocaleString("en-US")})," of"," ",e.jsx("span",{className:"tabular-nums text-muted",children:F.length.toLocaleString("en-US")})," events · ",me]})]}),e.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[e.jsxs("span",{className:"inline-flex items-center text-secondary",children:[e.jsxs("select",{"aria-label":"Filter by identity",value:f,onChange:t=>v(t.target.value),className:"rounded-md border border-base bg-bg px-2.5 py-1.5 text-xs text-strong focus:outline-none focus-visible:ring-1 focus-visible:ring-mono-600",children:[e.jsx("option",{value:"",children:"All identities"}),Ne.map(t=>e.jsx("option",{value:t,children:t},t))]}),e.jsx(D,{text:"The specific bot or AI product making the request (e.g., GPTBot, ChatGPT-User, Perplexity). One operator usually runs several identities."})]}),e.jsxs("span",{className:"inline-flex items-center text-secondary",children:[e.jsxs("select",{"aria-label":"Filter by operator",value:m,onChange:t=>L(t.target.value),className:"rounded-md border border-base bg-bg px-2.5 py-1.5 text-xs text-strong focus:outline-none focus-visible:ring-1 focus-visible:ring-mono-600",children:[e.jsx("option",{value:"",children:"All operators"}),Se.map(t=>e.jsx("option",{value:t,children:t},t))]}),e.jsx(D,{text:"The company that runs the bot or product (e.g., OpenAI, Anthropic, Perplexity). Filtering by operator includes every identity under that company."})]}),e.jsx("select",{"aria-label":"Filter by HTTP status class",value:k,onChange:t=>z(t.target.value),className:"rounded-md border border-base bg-bg px-2.5 py-1.5 text-xs text-strong focus:outline-none focus-visible:ring-1 focus-visible:ring-mono-600",children:tt.map(t=>e.jsx("option",{value:t.value,children:t.label},t.value))}),e.jsx("select",{"aria-label":"Filter by verification claim",value:T,onChange:t=>G(t.target.value),className:"rounded-md border border-base bg-bg px-2.5 py-1.5 text-xs text-strong focus:outline-none focus-visible:ring-1 focus-visible:ring-mono-600",children:pe.map(t=>e.jsx("option",{value:t.value,children:t.label},t.value))}),e.jsx("input",{type:"search","aria-label":"Filter by path",placeholder:"path contains…",value:j,onChange:t=>B(t.target.value),className:"w-44 rounded-md border border-base bg-bg px-2.5 py-1.5 text-xs text-strong placeholder:text-faint focus:outline-none focus-visible:ring-1 focus-visible:ring-mono-600"})]})]}),Le?e.jsxs("div",{className:"mb-3 flex flex-wrap items-center gap-2",children:[ne?e.jsx(A,{label:`Bucket: ${ne}`,onClear:()=>C(null)}):null,f?e.jsx(A,{label:`Identity: ${f}`,onClear:()=>v("")}):null,m?e.jsx(A,{label:`Operator: ${m}`,onClear:()=>L("")}):null,j.trim()?e.jsx(A,{label:`Path: ${j.trim()}`,onClear:()=>B("")}):null,k!=="all"?e.jsx(A,{label:`Status: ${k}`,onClear:()=>z("all")}):null,T!=="all"?e.jsx(A,{label:`Claim: ${ct(T)}`,onClear:()=>G("all")}):null,e.jsx("button",{type:"button",onClick:Ae,className:"text-xs text-muted underline-offset-4 hover:text-strong hover:underline",children:"Clear all"})]}):null,e.jsx(xt,{events:we}),Ce?e.jsxs("div",{className:"mt-3 flex flex-wrap items-center justify-between gap-x-4 gap-y-2 text-xs text-secondary",children:[e.jsxs("p",{className:"tabular-nums",children:["Showing ",e.jsx("span",{className:"text-neutral",children:ke.toLocaleString("en-US")}),"–",e.jsx("span",{className:"text-neutral",children:Te.toLocaleString("en-US")})," of"," ",e.jsx("span",{className:"text-neutral",children:w.length.toLocaleString("en-US")})," events"]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsxs("button",{type:"button",onClick:()=>K(t=>Math.max(1,t-1)),disabled:H<=1,"aria-label":"Previous page",className:"inline-flex items-center gap-1 rounded-md border border-base bg-bg px-2.5 py-1.5 text-strong transition hover:border-strong hover:text-primary disabled:cursor-not-allowed disabled:opacity-40 disabled:hover:border-base disabled:hover:text-strong",children:[e.jsx(Ye,{className:"size-3.5"}),"Prev"]}),e.jsxs("span",{className:"tabular-nums",children:["Page ",e.jsx("span",{className:"text-strong",children:H})," of"," ",e.jsx("span",{className:"text-strong",children:M})]}),e.jsxs("button",{type:"button",onClick:()=>K(t=>Math.min(M,t+1)),disabled:H>=M,"aria-label":"Next page",className:"inline-flex items-center gap-1 rounded-md border border-base bg-bg px-2.5 py-1.5 text-strong transition hover:border-strong hover:text-primary disabled:cursor-not-allowed disabled:opacity-40 disabled:hover:border-base disabled:hover:text-strong",children:["Next",e.jsx(He,{className:"size-3.5"})]})]})]}):null]})]})}function Z(s,a){return{bucket:s,label:a,crawler:0,aiUserFetch:0,aiReferral:0}}function O(s,a){return a==="day"?lt(s):je(s)}function it(s,a,l,n){const x=new Map;for(const i of s){const c=ye(i.tsHour,a);let o=x.get(c);switch(o||(o=Z(c,O(c,a)),x.set(c,o)),i.kind){case u.crawler:o.crawler+=i.hits;break;case u["ai-user-fetch"]:o.aiUserFetch+=i.hits;break;case u["ai-referral"]:o.aiReferral+=i.hits;break}}if(l&&n){const i=new Date(l),c=new Date(n);if(a==="day"){const o=new Date(Date.UTC(i.getUTCFullYear(),i.getUTCMonth(),i.getUTCDate())),d=new Date(Date.UTC(c.getUTCFullYear(),c.getUTCMonth(),c.getUTCDate()));for(;o<=d;){const C=o.getUTCFullYear(),f=String(o.getUTCMonth()+1).padStart(2,"0"),v=String(o.getUTCDate()).padStart(2,"0"),m=`${C}-${f}-${v}`;x.has(m)||x.set(m,Z(m,O(m,a))),o.setUTCDate(o.getUTCDate()+1)}}else{const o=new Date(i);for(o.setUTCMinutes(0,0,0);o<=c;){const d=o.toISOString();x.has(d)||x.set(d,Z(d,O(d,a))),o.setUTCHours(o.getUTCHours()+1)}}}return[...x.values()].sort((i,c)=>i.bucket<c.bucket?-1:i.bucket>c.bucket?1:0)}function ct(s){return pe.find(a=>a.value===s)?.label??s}function A({label:s,onClear:a}){return e.jsxs("span",{className:"inline-flex items-center gap-1.5 rounded-full border border-strong bg-surface-inset px-2.5 py-1 text-[11px] text-strong",children:[s,e.jsx("button",{type:"button",onClick:a,"aria-label":`Clear ${s}`,className:"rounded-full p-0.5 text-secondary hover:bg-mono-700/60 hover:text-heading",children:e.jsx(Oe,{className:"size-3"})})]})}function J({label:s,color:a,count:l,active:n,onToggle:x}){return e.jsxs("button",{type:"button",onClick:x,"aria-pressed":n,className:`inline-flex items-center gap-2 rounded-full border px-3 py-1 text-xs font-medium transition ${n?"border-strong bg-surface-inset text-heading":"border-base bg-transparent text-muted hover:text-neutral"}`,children:[e.jsx("span",{"aria-hidden":"true",className:`size-2 rounded-full transition-opacity ${n?"opacity-100":"opacity-30"}`,style:{backgroundColor:a}}),e.jsx("span",{children:s}),e.jsx("span",{className:`tabular-nums ${n?"text-secondary":"text-faint"}`,children:l.toLocaleString("en-US")})]})}function ot(s){switch(s){case u.crawler:return"Crawler";case u["ai-user-fetch"]:return"AI hit";case u["ai-referral"]:return"AI referral"}}function ut(s){switch(s.kind){case u.crawler:case u["ai-user-fetch"]:return s.botId;case u["ai-referral"]:return s.product}}function dt(s){switch(s.kind){case u.crawler:case u["ai-user-fetch"]:return`${s.verificationStatus} · HTTP ${s.status}`;case u["ai-referral"]:return`${s.evidenceType} · ${s.sourceDomain}`}}function xt({events:s}){return s.length===0?e.jsx(P,{className:"p-6 text-center text-sm text-muted",children:"No event rows match the current filters."}):e.jsx("div",{className:"rounded-xl border border-default bg-surface overflow-hidden",children:e.jsxs("table",{className:"w-full text-sm",children:[e.jsx("thead",{className:"bg-bg-elevated/50 text-[10px] font-semibold uppercase tracking-wider text-muted",children:e.jsxs("tr",{children:[e.jsx("th",{className:"px-4 py-2 text-left",children:"Hour"}),e.jsx("th",{className:"px-4 py-2 text-left",children:"Kind"}),e.jsx("th",{className:"px-4 py-2 text-left",children:"Identity"}),e.jsx("th",{className:"px-4 py-2 text-left",children:"Evidence / status"}),e.jsx("th",{className:"px-4 py-2 text-left",children:"Path"}),e.jsx("th",{className:"px-4 py-2 text-right",children:e.jsxs("span",{className:"inline-flex items-center",children:["Hits",e.jsx(D,{text:"Each row is one hour-bucket, not one request. Hits is the number of requests in that hour that shared the same identity, path, HTTP status, and verification claim."})]})})]})}),e.jsx("tbody",{className:"divide-y divide-mono-800/60",children:s.map((a,l)=>e.jsxs("tr",{className:"hover:bg-bg-elevated/40 transition-colors",children:[e.jsx("td",{className:"px-4 py-2 font-mono text-xs text-neutral",children:je(a.tsHour)}),e.jsx("td",{className:"px-4 py-2 text-neutral",children:ot(a.kind)}),e.jsxs("td",{className:"px-4 py-2 text-heading",children:[ut(a),e.jsx("span",{className:"ml-2 text-[11px] text-muted",children:a.operator})]}),e.jsx("td",{className:"px-4 py-2 text-neutral",children:dt(a)}),e.jsx("td",{className:"px-4 py-2 truncate font-mono text-xs text-neutral",children:be(a)}),e.jsx("td",{className:"px-4 py-2 text-right tabular-nums text-heading",children:a.hits})]},`${a.kind}:${a.tsHour}:${l}`))})]})})}export{vt as TrafficSourceDetailPage};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{c as m,k as a,cm as l,cg as y,cn as S,aF as g,m as t,co as v,ch as s,cp as p,cq as T,cr as h,cs as q}from"./index-BiCDkOH4.js";import{u as c,r as C,n as o,o as u}from"./vendor-tanstack-Be8JdV5M.js";const w=[["path",{d:"M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8",key:"v9h5vc"}],["path",{d:"M21 3v5h-5",key:"1q7to0"}],["path",{d:"M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16",key:"3uifl3"}],["path",{d:"M8 16H3v5",key:"1cv678"}]],F=m("refresh-cw",w);function P(e){switch(e){case s.connected:return"positive";case s.paused:return"caution";case s.error:return"negative";case s.archived:return"neutral"}}function M(e){const n={};return e.kind&&e.kind!=="all"&&(n.kind=e.kind),e.sourceId&&(n.sourceId=e.sourceId),e.sinceMinutes!==void 0&&(n.since=new Date(Date.now()-e.sinceMinutes*6e4).toISOString()),e.limit!==void 0&&(n.limit=String(e.limit)),n}function f(e){e.invalidateQueries({predicate:n=>{const r=n.queryKey[0];return typeof r?._id=="string"&&r._id.startsWith("getApiV1ProjectsByNameTraffic")}})}function A(e){return c({...l({client:t,path:{name:e??""}}),enabled:!!e,staleTime:a})}function R(e){return c({...q({client:t,path:{name:e??""}}),enabled:!!e,staleTime:a})}function V(e,n){return c({...y({client:t,path:{name:e??"",id:n??""}}),enabled:!!(e&&n),staleTime:a})}function I(e,n){const r=C.useMemo(()=>M(n),[n.kind,n.sourceId,n.sinceMinutes,n.limit]);return c({...S({client:t,path:{name:e??""},query:r}),enabled:!!e,staleTime:a})}function b(e){const n=o();return u({mutationFn:r=>{if(!e)throw new Error("Project is required to connect a Cloud Run source");return h(e,r)},onSuccess:()=>{e&&f(n)}})}function Q(e){const n=o();return u({mutationFn:r=>{if(!e)throw new Error("Project is required to connect a WordPress source");return p(e,r)},onSuccess:()=>{e&&f(n)}})}function N(e){const n=o();return u({mutationFn:r=>{if(!e)throw new Error("Project is required to connect a Vercel source");return T(e,r)},onSuccess:()=>{e&&f(n)}})}function _(e,n){const r=o();return u({mutationFn:d=>{if(!e||!n)throw new Error("Project and sourceId are required to sync");return v(e,n,d??void 0)},onSuccess:()=>{e&&(f(r),r.invalidateQueries({queryKey:g({client:t})}))}})}function i(e){return typeof e=="object"&&e!==null}function E(e){if(e instanceof Error){const n=e;return{message:e.message,code:typeof n.code=="string"?n.code:void 0,details:i(n.details)?n.details:void 0}}if(i(e)){const n=e.error;if(i(n))return{message:typeof n.message=="string"?n.message:"Request failed",code:typeof n.code=="string"?n.code:void 0,details:i(n.details)?n.details:void 0};if(typeof n=="string")return{message:n};const r=e.message;if(typeof r=="string")return{message:r}}return typeof e=="string"?{message:e}:{message:String(e)}}function O(e){return E(e).message}export{F as R,Q as a,N as b,b as c,O as d,E as e,A as f,V as g,I as h,_ as i,P as t,R as u};
|