@canonry/canonry 7.25.0 → 7.43.2
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 +3 -2
- package/assets/agent-workspace/skills/canonry/references/aeo-analysis.md +24 -0
- package/assets/agent-workspace/skills/canonry/references/canonry-cli.md +219 -6
- package/assets/agent-workspace/skills/canonry/references/server-side-traffic.md +14 -2
- package/assets/assets/{AuditHistoryPanel-B-9DLSmD.js → AuditHistoryPanel-C5oZsvsR.js} +1 -1
- package/assets/assets/{BacklinksPage-DPssWU5-.js → BacklinksPage-CF5sGSTQ.js} +1 -1
- package/assets/assets/{HistoryPage-BAPUoHjI.js → HistoryPage-DumL6cl5.js} +1 -1
- package/assets/assets/{MeasurementPropertyPage-aTs5l1OV.js → MeasurementPropertyPage-DCegOp_w.js} +3 -3
- package/assets/assets/ProjectPage-CWDk48Y6.js +8 -0
- package/assets/assets/RunsPage-Bb1VMWYu.js +1 -0
- package/assets/assets/{SettingsPage-Oo861eRm.js → SettingsPage-CHGh169l.js} +1 -1
- package/assets/assets/{SiteHealthSection-BMdk3Och.js → SiteHealthSection-bGzH9m9-.js} +3 -3
- package/assets/assets/{TrafficPage-Ciot_0lN.js → TrafficPage-cfnEZ2Mu.js} +1 -1
- package/assets/assets/{TrafficSourceDetailPage-D7tWadfJ.js → TrafficSourceDetailPage-BQS0MAXE.js} +1 -1
- package/assets/assets/{extract-error-message-Bb4azvlK.js → extract-error-message-IWhACkO_.js} +1 -1
- package/assets/assets/index-BDY3-V1S.js +86 -0
- package/assets/assets/{react-sigma_core.esm.min-C-Y9Z74U.js → react-sigma_core.esm.min-BQt189AI.js} +1 -1
- package/assets/assets/{v2-overview-adapter-D2S25ivE.js → v2-overview-adapter-ZC3VuoTT.js} +1 -1
- package/assets/index.html +1 -1
- package/dist/{chunk-PKQF7BV2.js → chunk-65BHDVYO.js} +5650 -4002
- package/dist/{chunk-NOA7KJDB.js → chunk-BPFRGC7K.js} +3 -3
- package/dist/{chunk-I3546GTK.js → chunk-BWR5MNL5.js} +2 -2
- package/dist/chunk-C2I7M3B2.js +22948 -0
- package/dist/{chunk-PFEQWGJN.js → chunk-E43JM3QV.js} +11444 -10397
- package/dist/chunk-HGMYEDAQ.js +79 -0
- package/dist/{chunk-BMBHREYM.js → chunk-KOIOZ7QW.js} +195 -20
- package/dist/{chunk-6AOIFHC6.js → chunk-LYKDNJXR.js} +163 -107
- package/dist/chunk-WRUKKEGR.js +562 -0
- package/dist/chunk-WU2BRWXY.js +546 -0
- package/dist/{chunk-NX257AKC.js → chunk-WXX3NL4C.js} +108 -41
- package/dist/cli-catalog-J3O6W726.js +15 -0
- package/dist/cli-commands-QST2CPDG.js +15 -0
- package/dist/cli.js +136 -22502
- package/dist/{demo-server-RUZWYXSW.js → demo-server-KA7DWTY6.js} +5 -4
- package/dist/index.js +7 -6
- package/dist/{intelligence-service-TYSVXO3S.js → intelligence-service-LHZZTJPH.js} +2 -2
- package/dist/mcp.js +30 -15
- package/package.json +6 -6
- package/assets/assets/ProjectPage-sVY1ETmt.js +0 -8
- package/assets/assets/RunsPage-D0q7ifK3.js +0 -1
- package/assets/assets/index-ClA5Nf2V.js +0 -86
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
// src/support-links.ts
|
|
2
|
+
var CANONRY_DISCORD_URL = "https://discord.gg/jnJ2H2z5Xh";
|
|
3
|
+
var CANONRY_ISSUES_URL = "https://github.com/Canonry/canonry/issues";
|
|
4
|
+
|
|
5
|
+
// src/cli-error.ts
|
|
6
|
+
function isMachineFormat(format) {
|
|
7
|
+
return format === "json" || format === "jsonl";
|
|
8
|
+
}
|
|
9
|
+
var EXIT_USER_ERROR = 1;
|
|
10
|
+
var EXIT_SYSTEM_ERROR = 2;
|
|
11
|
+
var CliError = class extends Error {
|
|
12
|
+
code;
|
|
13
|
+
displayMessage;
|
|
14
|
+
details;
|
|
15
|
+
exitCode;
|
|
16
|
+
constructor(options) {
|
|
17
|
+
super(options.message);
|
|
18
|
+
this.name = "CliError";
|
|
19
|
+
this.code = options.code;
|
|
20
|
+
this.displayMessage = options.displayMessage;
|
|
21
|
+
this.details = options.details;
|
|
22
|
+
this.exitCode = options.exitCode ?? EXIT_USER_ERROR;
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
function usageError(displayMessage, options) {
|
|
26
|
+
const firstLine = displayMessage.split("\n", 1)[0] ?? "Error: invalid command usage";
|
|
27
|
+
return new CliError({
|
|
28
|
+
code: "CLI_USAGE_ERROR",
|
|
29
|
+
message: options?.message ?? firstLine.replace(/^Error:\s*/, ""),
|
|
30
|
+
displayMessage,
|
|
31
|
+
details: options?.details
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
function isEndpointMissing(err) {
|
|
35
|
+
if (!(err instanceof CliError)) return false;
|
|
36
|
+
const status = err.details?.httpStatus;
|
|
37
|
+
return status === 404 || status === 405;
|
|
38
|
+
}
|
|
39
|
+
function systemError(message, options) {
|
|
40
|
+
return new CliError({
|
|
41
|
+
code: "CLI_SYSTEM_ERROR",
|
|
42
|
+
message,
|
|
43
|
+
displayMessage: options?.displayMessage,
|
|
44
|
+
details: options?.details,
|
|
45
|
+
exitCode: EXIT_SYSTEM_ERROR
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
function printCliError(err, format) {
|
|
49
|
+
if (isMachineFormat(format)) {
|
|
50
|
+
const envelope = err instanceof CliError ? { error: { code: err.code, message: err.message, ...err.details ? { details: err.details } : {} } } : { error: { code: "CLI_ERROR", message: err instanceof Error ? err.message : "An unexpected error occurred" } };
|
|
51
|
+
console.error(JSON.stringify(envelope, null, format === "jsonl" ? 0 : 2));
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
if (err instanceof CliError && err.displayMessage) {
|
|
55
|
+
console.error(err.displayMessage);
|
|
56
|
+
} else if (err instanceof Error) {
|
|
57
|
+
console.error(`Error: ${err.message}`);
|
|
58
|
+
} else {
|
|
59
|
+
console.error("An unexpected error occurred");
|
|
60
|
+
}
|
|
61
|
+
const unexpected = !(err instanceof CliError) || err.exitCode === EXIT_SYSTEM_ERROR;
|
|
62
|
+
if (unexpected && process.stderr.isTTY) {
|
|
63
|
+
console.error(`
|
|
64
|
+
Need help? Run 'canonry support' or ask in the Canonry Discord: ${CANONRY_DISCORD_URL}`);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export {
|
|
69
|
+
CANONRY_DISCORD_URL,
|
|
70
|
+
CANONRY_ISSUES_URL,
|
|
71
|
+
isMachineFormat,
|
|
72
|
+
EXIT_USER_ERROR,
|
|
73
|
+
EXIT_SYSTEM_ERROR,
|
|
74
|
+
CliError,
|
|
75
|
+
usageError,
|
|
76
|
+
isEndpointMissing,
|
|
77
|
+
systemError,
|
|
78
|
+
printCliError
|
|
79
|
+
};
|
|
@@ -1,11 +1,14 @@
|
|
|
1
|
+
import {
|
|
2
|
+
PACKAGE_VERSION,
|
|
3
|
+
canonryMcpTools,
|
|
4
|
+
toolOperationAccess
|
|
5
|
+
} from "./chunk-LYKDNJXR.js";
|
|
1
6
|
import {
|
|
2
7
|
CliError,
|
|
3
8
|
EXIT_SYSTEM_ERROR,
|
|
4
9
|
EXIT_USER_ERROR,
|
|
5
|
-
PACKAGE_VERSION,
|
|
6
|
-
canonryMcpTools,
|
|
7
10
|
isMachineFormat
|
|
8
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-HGMYEDAQ.js";
|
|
9
12
|
import {
|
|
10
13
|
AGENT_PROVIDER_IDS,
|
|
11
14
|
CANONRY_NPM_PACKAGE_URL,
|
|
@@ -13,8 +16,11 @@ import {
|
|
|
13
16
|
DEFAULT_VIEWER_RESEARCH_DAILY_RUN_LIMIT,
|
|
14
17
|
OPERATIONAL_LOG_FIELDS_HEADER,
|
|
15
18
|
OPERATIONAL_LOG_OPT_IN_CONTEXT_FIELDS,
|
|
19
|
+
OPERATION_ACCESS_HEADER,
|
|
20
|
+
OperationAccesses,
|
|
16
21
|
RESEARCH_RUN_SCOPE,
|
|
17
22
|
SKILL_MANIFEST_FILENAME,
|
|
23
|
+
STORED_ONLY_HEADER,
|
|
18
24
|
SkillsClients,
|
|
19
25
|
USAGE_TELEMETRY_HEADERS,
|
|
20
26
|
agentPluginClientLabel,
|
|
@@ -31,8 +37,10 @@ import {
|
|
|
31
37
|
isRetiredAgentProviderId,
|
|
32
38
|
isSensitiveDiagnosticQueryKey,
|
|
33
39
|
isStrictSemver,
|
|
40
|
+
matchOperationTemplate,
|
|
34
41
|
normalizeAgentSlug,
|
|
35
42
|
normalizeTelemetryStatus,
|
|
43
|
+
operationAccess,
|
|
36
44
|
operationalLogListReadSchema,
|
|
37
45
|
providerBatchConfigSchema,
|
|
38
46
|
providerPricingSchema,
|
|
@@ -49,7 +57,7 @@ import {
|
|
|
49
57
|
skillsClientSchema,
|
|
50
58
|
upgradeCaveatFor,
|
|
51
59
|
upgradeCommandFor
|
|
52
|
-
} from "./chunk-
|
|
60
|
+
} from "./chunk-E43JM3QV.js";
|
|
53
61
|
|
|
54
62
|
// src/config.ts
|
|
55
63
|
import fs from "fs";
|
|
@@ -1505,6 +1513,22 @@ var getApiV1ProjectsByName = (options) => {
|
|
|
1505
1513
|
...options
|
|
1506
1514
|
});
|
|
1507
1515
|
};
|
|
1516
|
+
var patchApiV1ProjectsByName = (options) => {
|
|
1517
|
+
return (options.client ?? client).patch({
|
|
1518
|
+
security: [
|
|
1519
|
+
{
|
|
1520
|
+
scheme: "bearer",
|
|
1521
|
+
type: "http"
|
|
1522
|
+
}
|
|
1523
|
+
],
|
|
1524
|
+
url: "/api/v1/projects/{name}",
|
|
1525
|
+
...options,
|
|
1526
|
+
headers: {
|
|
1527
|
+
"Content-Type": "application/json",
|
|
1528
|
+
...options.headers
|
|
1529
|
+
}
|
|
1530
|
+
});
|
|
1531
|
+
};
|
|
1508
1532
|
var putApiV1ProjectsByName = (options) => {
|
|
1509
1533
|
return (options.client ?? client).put({
|
|
1510
1534
|
security: [
|
|
@@ -2949,6 +2973,34 @@ var getApiV1ProjectsByNameAnalyticsCompetitors = (options) => {
|
|
|
2949
2973
|
...options
|
|
2950
2974
|
});
|
|
2951
2975
|
};
|
|
2976
|
+
var getApiV1ProjectsByNameCompetitorSuggestions = (options) => {
|
|
2977
|
+
return (options.client ?? client).get({
|
|
2978
|
+
security: [
|
|
2979
|
+
{
|
|
2980
|
+
scheme: "bearer",
|
|
2981
|
+
type: "http"
|
|
2982
|
+
}
|
|
2983
|
+
],
|
|
2984
|
+
url: "/api/v1/projects/{name}/competitor-suggestions",
|
|
2985
|
+
...options
|
|
2986
|
+
});
|
|
2987
|
+
};
|
|
2988
|
+
var postApiV1ProjectsByNameCompetitorChangesPreview = (options) => {
|
|
2989
|
+
return (options.client ?? client).post({
|
|
2990
|
+
security: [
|
|
2991
|
+
{
|
|
2992
|
+
scheme: "bearer",
|
|
2993
|
+
type: "http"
|
|
2994
|
+
}
|
|
2995
|
+
],
|
|
2996
|
+
url: "/api/v1/projects/{name}/competitor-changes/preview",
|
|
2997
|
+
...options,
|
|
2998
|
+
headers: {
|
|
2999
|
+
"Content-Type": "application/json",
|
|
3000
|
+
...options.headers
|
|
3001
|
+
}
|
|
3002
|
+
});
|
|
3003
|
+
};
|
|
2952
3004
|
var getApiV1ProjectsByNameRuns = (options) => {
|
|
2953
3005
|
return (options.client ?? client).get({
|
|
2954
3006
|
security: [
|
|
@@ -3057,6 +3109,22 @@ var postApiV1Apply = (options) => {
|
|
|
3057
3109
|
}
|
|
3058
3110
|
});
|
|
3059
3111
|
};
|
|
3112
|
+
var postApiV1ApplyPreview = (options) => {
|
|
3113
|
+
return (options.client ?? client).post({
|
|
3114
|
+
security: [
|
|
3115
|
+
{
|
|
3116
|
+
scheme: "bearer",
|
|
3117
|
+
type: "http"
|
|
3118
|
+
}
|
|
3119
|
+
],
|
|
3120
|
+
url: "/api/v1/apply/preview",
|
|
3121
|
+
...options,
|
|
3122
|
+
headers: {
|
|
3123
|
+
"Content-Type": "application/json",
|
|
3124
|
+
...options.headers
|
|
3125
|
+
}
|
|
3126
|
+
});
|
|
3127
|
+
};
|
|
3060
3128
|
var getApiV1ProjectsByNameHistory = (options) => {
|
|
3061
3129
|
return (options.client ?? client).get({
|
|
3062
3130
|
security: [
|
|
@@ -5245,6 +5313,18 @@ var getApiV1ProjectsByNameGaProperties = (options) => {
|
|
|
5245
5313
|
...options
|
|
5246
5314
|
});
|
|
5247
5315
|
};
|
|
5316
|
+
var getApiV1ProjectsByNameGaAcquisition = (options) => {
|
|
5317
|
+
return (options.client ?? client).get({
|
|
5318
|
+
security: [
|
|
5319
|
+
{
|
|
5320
|
+
scheme: "bearer",
|
|
5321
|
+
type: "http"
|
|
5322
|
+
}
|
|
5323
|
+
],
|
|
5324
|
+
url: "/api/v1/projects/{name}/ga/acquisition",
|
|
5325
|
+
...options
|
|
5326
|
+
});
|
|
5327
|
+
};
|
|
5248
5328
|
var getApiV1ProjectsByNameGaMeasurementAnalysis = (options) => {
|
|
5249
5329
|
return (options.client ?? client).get({
|
|
5250
5330
|
security: [
|
|
@@ -5629,6 +5709,18 @@ var getApiV1Doctor = (options) => {
|
|
|
5629
5709
|
...options
|
|
5630
5710
|
});
|
|
5631
5711
|
};
|
|
5712
|
+
var getApiV1Status = (options) => {
|
|
5713
|
+
return (options?.client ?? client).get({
|
|
5714
|
+
security: [
|
|
5715
|
+
{
|
|
5716
|
+
scheme: "bearer",
|
|
5717
|
+
type: "http"
|
|
5718
|
+
}
|
|
5719
|
+
],
|
|
5720
|
+
url: "/api/v1/status",
|
|
5721
|
+
...options
|
|
5722
|
+
});
|
|
5723
|
+
};
|
|
5632
5724
|
var getApiV1ProjectsByNameDoctor = (options) => {
|
|
5633
5725
|
return (options.client ?? client).get({
|
|
5634
5726
|
security: [
|
|
@@ -5977,6 +6069,18 @@ var getApiV1ProjectsByNameTrafficReferralAssessment = (options) => {
|
|
|
5977
6069
|
...options
|
|
5978
6070
|
});
|
|
5979
6071
|
};
|
|
6072
|
+
var getApiV1ProjectsByNameTrafficSamples = (options) => {
|
|
6073
|
+
return (options.client ?? client).get({
|
|
6074
|
+
security: [
|
|
6075
|
+
{
|
|
6076
|
+
scheme: "bearer",
|
|
6077
|
+
type: "http"
|
|
6078
|
+
}
|
|
6079
|
+
],
|
|
6080
|
+
url: "/api/v1/projects/{name}/traffic/samples",
|
|
6081
|
+
...options
|
|
6082
|
+
});
|
|
6083
|
+
};
|
|
5980
6084
|
var getApiV1ProjectsByNameTrafficEvents = (options) => {
|
|
5981
6085
|
return (options.client ?? client).get({
|
|
5982
6086
|
security: [
|
|
@@ -6477,6 +6581,30 @@ function runWithUsageTags(client2, tags, fn) {
|
|
|
6477
6581
|
if (!(client2 instanceof ApiClient)) return fn();
|
|
6478
6582
|
return usageTagStore.run(tags, fn);
|
|
6479
6583
|
}
|
|
6584
|
+
function classifyStoredOnlyRequest(method, url) {
|
|
6585
|
+
const operation = matchOperationTemplate(method, url);
|
|
6586
|
+
const separator = operation.indexOf(" ");
|
|
6587
|
+
return {
|
|
6588
|
+
operation,
|
|
6589
|
+
access: operationAccess(operation.slice(0, separator), operation.slice(separator + 1), OperationAccesses.live)
|
|
6590
|
+
};
|
|
6591
|
+
}
|
|
6592
|
+
function storedOnlyRequestHeaders(method, url) {
|
|
6593
|
+
if (!["1", "true"].includes((process.env.CANONRY_STORED_ONLY ?? "").toLowerCase())) return {};
|
|
6594
|
+
const { operation, access } = classifyStoredOnlyRequest(method, url);
|
|
6595
|
+
if (access !== OperationAccesses.stored) {
|
|
6596
|
+
throw new CliError({
|
|
6597
|
+
code: "STORED_ONLY_REFUSED",
|
|
6598
|
+
message: `Stored-only mode refuses ${access} operation ${operation}`,
|
|
6599
|
+
details: { operation, access },
|
|
6600
|
+
exitCode: EXIT_USER_ERROR
|
|
6601
|
+
});
|
|
6602
|
+
}
|
|
6603
|
+
return { [STORED_ONLY_HEADER]: "1" };
|
|
6604
|
+
}
|
|
6605
|
+
function storedOnlyProbeHeaders() {
|
|
6606
|
+
return ["1", "true"].includes((process.env.CANONRY_STORED_ONLY ?? "").toLowerCase()) ? { [STORED_ONLY_HEADER]: "1" } : {};
|
|
6607
|
+
}
|
|
6480
6608
|
var SAFE_CLIENT_NAME = /^\w[\w./-]{0,127}$/;
|
|
6481
6609
|
var SAFE_ACTOR_SESSION = /^\w[\w.:-]{0,127}$/;
|
|
6482
6610
|
function safeClientName(value) {
|
|
@@ -6548,6 +6676,7 @@ var ApiClient = class {
|
|
|
6548
6676
|
};
|
|
6549
6677
|
this.heyClient = createClient2({ baseUrl: this.originUrl, apiKey: this.apiKey, headers: this.requestHeaders });
|
|
6550
6678
|
this.heyClient.interceptors.request.use((request) => {
|
|
6679
|
+
for (const [key, value] of Object.entries(storedOnlyRequestHeaders(request.method, request.url.toString()))) request.headers.set(key, value);
|
|
6551
6680
|
const tags = usageTagStore.getStore();
|
|
6552
6681
|
if (tags?.mcpTool) request.headers.set(USAGE_TELEMETRY_HEADERS.mcpTool, tags.mcpTool);
|
|
6553
6682
|
if (tags?.mcpCall) request.headers.set(USAGE_TELEMETRY_HEADERS.mcpCall, tags.mcpCall);
|
|
@@ -6569,6 +6698,7 @@ var ApiClient = class {
|
|
|
6569
6698
|
try {
|
|
6570
6699
|
const origin = new URL(this.originUrl).origin;
|
|
6571
6700
|
const res = await fetch(`${origin}/health`, {
|
|
6701
|
+
headers: storedOnlyProbeHeaders(),
|
|
6572
6702
|
signal: AbortSignal.timeout(2e3)
|
|
6573
6703
|
});
|
|
6574
6704
|
if (res.ok) {
|
|
@@ -6626,7 +6756,7 @@ var ApiClient = class {
|
|
|
6626
6756
|
if (traceEnabled) {
|
|
6627
6757
|
const durMs = Date.now() - traceStart;
|
|
6628
6758
|
process.stderr.write(
|
|
6629
|
-
`[trace] ${result.request.method} ${redactRequestTarget(result.request.url)} \u2192 ${result.response.status} (${durMs}ms)
|
|
6759
|
+
`[trace] ${result.request.method} ${redactRequestTarget(result.request.url)} \u2192 ${result.response.status} (${durMs}ms) access=${result.response.headers.get(OPERATION_ACCESS_HEADER) ?? "unknown"}
|
|
6630
6760
|
`
|
|
6631
6761
|
);
|
|
6632
6762
|
}
|
|
@@ -6729,10 +6859,13 @@ var ApiClient = class {
|
|
|
6729
6859
|
* and releases the response when done.
|
|
6730
6860
|
*/
|
|
6731
6861
|
async streamPost(path3, body, signal) {
|
|
6862
|
+
const candidateUrl = `${this.originUrl}/api/v1${path3}`;
|
|
6863
|
+
const storedOnlyHeaders = storedOnlyRequestHeaders("POST", candidateUrl);
|
|
6732
6864
|
await this.probeBasePath();
|
|
6733
6865
|
const url = `${this.originUrl}/api/v1${path3}`;
|
|
6734
6866
|
const headers = {
|
|
6735
6867
|
...this.requestHeaders,
|
|
6868
|
+
...storedOnlyHeaders,
|
|
6736
6869
|
"Content-Type": "application/json",
|
|
6737
6870
|
Accept: "text/event-stream"
|
|
6738
6871
|
};
|
|
@@ -6772,6 +6905,11 @@ var ApiClient = class {
|
|
|
6772
6905
|
() => putApiV1ProjectsByName({ client: this.heyClient, path: { name }, body })
|
|
6773
6906
|
);
|
|
6774
6907
|
}
|
|
6908
|
+
async patchProject(name, body) {
|
|
6909
|
+
return this.invoke(
|
|
6910
|
+
() => patchApiV1ProjectsByName({ client: this.heyClient, path: { name }, body })
|
|
6911
|
+
);
|
|
6912
|
+
}
|
|
6775
6913
|
async listProjects() {
|
|
6776
6914
|
return this.invoke(() => getApiV1Projects({ client: this.heyClient }));
|
|
6777
6915
|
}
|
|
@@ -6786,19 +6924,26 @@ var ApiClient = class {
|
|
|
6786
6924
|
() => getApiV1ProjectsByNameDeletePreview({ client: this.heyClient, path: { name } })
|
|
6787
6925
|
);
|
|
6788
6926
|
}
|
|
6789
|
-
async getStatus(
|
|
6927
|
+
async getStatus(opts) {
|
|
6790
6928
|
return this.invoke(
|
|
6791
|
-
() =>
|
|
6929
|
+
() => getApiV1Status({ client: this.heyClient, query: { project: opts?.project, problems: opts?.problems } })
|
|
6792
6930
|
);
|
|
6793
6931
|
}
|
|
6794
|
-
async getExport(project) {
|
|
6932
|
+
async getExport(project, opts) {
|
|
6795
6933
|
return this.invoke(
|
|
6796
|
-
() => getApiV1ProjectsByNameExport({
|
|
6934
|
+
() => getApiV1ProjectsByNameExport({
|
|
6935
|
+
client: this.heyClient,
|
|
6936
|
+
path: { name: project },
|
|
6937
|
+
query: { includeSecrets: opts?.includeSecrets }
|
|
6938
|
+
})
|
|
6797
6939
|
);
|
|
6798
6940
|
}
|
|
6799
6941
|
async apply(config) {
|
|
6800
6942
|
return this.invoke(() => postApiV1Apply({ client: this.heyClient, body: config }));
|
|
6801
6943
|
}
|
|
6944
|
+
async previewApply(config) {
|
|
6945
|
+
return this.invoke(() => postApiV1ApplyPreview({ client: this.heyClient, body: config }));
|
|
6946
|
+
}
|
|
6802
6947
|
async getProjectOverview(project, opts) {
|
|
6803
6948
|
return this.invoke(
|
|
6804
6949
|
() => getApiV1ProjectsByNameOverview({
|
|
@@ -6834,10 +6979,11 @@ var ApiClient = class {
|
|
|
6834
6979
|
if (opts.until) params.set("until", opts.until);
|
|
6835
6980
|
if (opts.includeProbes) params.set("includeProbes", "true");
|
|
6836
6981
|
const url = `${this.originUrl}/api/v1/projects/${encodeURIComponent(project)}/results/export?${params.toString()}`;
|
|
6982
|
+
const storedOnlyHeaders = storedOnlyRequestHeaders("GET", url);
|
|
6837
6983
|
let res;
|
|
6838
6984
|
try {
|
|
6839
6985
|
res = await fetch(url, {
|
|
6840
|
-
headers: { ...this.requestHeaders }
|
|
6986
|
+
headers: { ...this.requestHeaders, ...storedOnlyHeaders }
|
|
6841
6987
|
});
|
|
6842
6988
|
} catch (err) {
|
|
6843
6989
|
const message = describeError(err);
|
|
@@ -6892,8 +7038,9 @@ var ApiClient = class {
|
|
|
6892
7038
|
() => deleteApiV1ProjectsByNameQueries({ client: this.heyClient, path: { name: project }, body: { queries } })
|
|
6893
7039
|
);
|
|
6894
7040
|
}
|
|
7041
|
+
/** Appends (existing texts are skipped) and returns the project's full query list, each row with its `queryClass`. */
|
|
6895
7042
|
async appendQueries(project, queries) {
|
|
6896
|
-
|
|
7043
|
+
return this.invoke(
|
|
6897
7044
|
() => postApiV1ProjectsByNameQueries({ client: this.heyClient, path: { name: project }, body: { queries } })
|
|
6898
7045
|
);
|
|
6899
7046
|
}
|
|
@@ -6940,13 +7087,27 @@ var ApiClient = class {
|
|
|
6940
7087
|
() => getApiV1ProjectsByNameCompetitors({ client: this.heyClient, path: { name: project } })
|
|
6941
7088
|
);
|
|
6942
7089
|
}
|
|
7090
|
+
async suggestCompetitors(project, query = {}) {
|
|
7091
|
+
return this.invoke(
|
|
7092
|
+
() => getApiV1ProjectsByNameCompetitorSuggestions({
|
|
7093
|
+
client: this.heyClient,
|
|
7094
|
+
path: { name: project },
|
|
7095
|
+
query
|
|
7096
|
+
})
|
|
7097
|
+
);
|
|
7098
|
+
}
|
|
7099
|
+
async previewCompetitorChange(project, request) {
|
|
7100
|
+
return this.invoke(
|
|
7101
|
+
() => postApiV1ProjectsByNameCompetitorChangesPreview({ client: this.heyClient, path: { name: project }, body: request })
|
|
7102
|
+
);
|
|
7103
|
+
}
|
|
6943
7104
|
/** Each entry is a domain or `{ domain, aliases }`; stated aliases are added to that competitor's list. */
|
|
6944
|
-
async appendCompetitors(project, competitors) {
|
|
7105
|
+
async appendCompetitors(project, competitors, options) {
|
|
6945
7106
|
return this.invoke(
|
|
6946
7107
|
() => postApiV1ProjectsByNameCompetitors({
|
|
6947
7108
|
client: this.heyClient,
|
|
6948
7109
|
path: { name: project },
|
|
6949
|
-
body: { competitors }
|
|
7110
|
+
body: { competitors, ...options?.acknowledgeBulkAdd !== void 0 ? { acknowledgeBulkAdd: options.acknowledgeBulkAdd } : {} }
|
|
6950
7111
|
})
|
|
6951
7112
|
);
|
|
6952
7113
|
}
|
|
@@ -7518,13 +7679,13 @@ var ApiClient = class {
|
|
|
7518
7679
|
})
|
|
7519
7680
|
);
|
|
7520
7681
|
}
|
|
7521
|
-
async listRuns(project, limit, kind, status, excludeKind, excludeKinds) {
|
|
7682
|
+
async listRuns(project, limit, kind, status, excludeKind, excludeKinds, since) {
|
|
7522
7683
|
return this.invoke(
|
|
7523
7684
|
() => getApiV1ProjectsByNameRuns({
|
|
7524
7685
|
client: this.heyClient,
|
|
7525
7686
|
path: { name: project },
|
|
7526
7687
|
// Filters arrive as free CLI strings; the server validates them against the enums.
|
|
7527
|
-
query: { limit, kind, status, excludeKind, excludeKinds }
|
|
7688
|
+
query: { limit, kind, status, excludeKind, excludeKinds, since }
|
|
7528
7689
|
})
|
|
7529
7690
|
);
|
|
7530
7691
|
}
|
|
@@ -7640,6 +7801,7 @@ var ApiClient = class {
|
|
|
7640
7801
|
* never run the CLI about a newer release.
|
|
7641
7802
|
*/
|
|
7642
7803
|
async getServerUpdateAvailable() {
|
|
7804
|
+
if (storedOnlyProbeHeaders()[STORED_ONLY_HEADER]) return null;
|
|
7643
7805
|
try {
|
|
7644
7806
|
await this.probeBasePath();
|
|
7645
7807
|
const res = await fetch(`${this.originUrl}/health`, { signal: AbortSignal.timeout(2e3) });
|
|
@@ -8652,6 +8814,9 @@ var ApiClient = class {
|
|
|
8652
8814
|
() => getApiV1ProjectsByNameGaProperties({ client: this.heyClient, path: { name: project } })
|
|
8653
8815
|
);
|
|
8654
8816
|
}
|
|
8817
|
+
async gaAcquisition(project, query) {
|
|
8818
|
+
return this.invoke(() => getApiV1ProjectsByNameGaAcquisition({ client: this.heyClient, path: { name: project }, query }));
|
|
8819
|
+
}
|
|
8655
8820
|
async gaMeasurementAnalysis(project, params) {
|
|
8656
8821
|
return this.invoke(
|
|
8657
8822
|
() => getApiV1ProjectsByNameGaMeasurementAnalysis({
|
|
@@ -8851,6 +9016,9 @@ var ApiClient = class {
|
|
|
8851
9016
|
query
|
|
8852
9017
|
}));
|
|
8853
9018
|
}
|
|
9019
|
+
async trafficListSamples(project, query) {
|
|
9020
|
+
return this.invoke(() => getApiV1ProjectsByNameTrafficSamples({ client: this.heyClient, path: { name: project }, query }));
|
|
9021
|
+
}
|
|
8854
9022
|
async trafficListEvents(project, params) {
|
|
8855
9023
|
return this.invoke(
|
|
8856
9024
|
() => getApiV1ProjectsByNameTrafficEvents({
|
|
@@ -9883,6 +10051,7 @@ var DynamicToolCatalog = class {
|
|
|
9883
10051
|
eager: this.eager,
|
|
9884
10052
|
loadedToolkits: [...this.loaded].sort(),
|
|
9885
10053
|
coreTools: this.entries.filter((entry) => entry.tool.tier === "core").map((entry) => entry.tool.name),
|
|
10054
|
+
liveTools: this.entries.filter((entry) => entry.tool.tier === "core" && toolOperationAccess(entry.tool) === OperationAccesses.live).map((entry) => entry.tool.name),
|
|
9886
10055
|
toolkits: CANONRY_MCP_TOOLKITS.map((toolkit) => this.toolkitEntry(toolkit)).filter((entry) => entry.toolCount > 0),
|
|
9887
10056
|
usage: this.eager ? "All tools available on this connection are already loaded. Use their listed schemas; tool visibility does not grant server permissions." : "Call canonry_load_toolkit with one of the toolkit names listed in `toolkits[].name` to register its tools for the rest of this session. Wait for its response before calling any newly enabled tool."
|
|
9888
10057
|
};
|
|
@@ -9896,6 +10065,7 @@ var DynamicToolCatalog = class {
|
|
|
9896
10065
|
whenToLoad: toolkit.whenToLoad,
|
|
9897
10066
|
toolCount: tools.length,
|
|
9898
10067
|
tools,
|
|
10068
|
+
liveTools: this.entries.filter((entry) => entry.tool.tier === toolkit.name && toolOperationAccess(entry.tool) === OperationAccesses.live).map((entry) => entry.tool.name),
|
|
9899
10069
|
loaded: this.loaded.has(toolkit.name)
|
|
9900
10070
|
};
|
|
9901
10071
|
}
|
|
@@ -9928,7 +10098,7 @@ var OPERATIONS_GUIDE = {
|
|
|
9928
10098
|
"guideVersion": "v1",
|
|
9929
10099
|
"operationsGuideUrl": "https://github.com/Canonry/canonry/blob/main/docs/agent-operations/v1.md",
|
|
9930
10100
|
"resourceUri": "canonry://agent-operations/v1",
|
|
9931
|
-
"initialize": 'Canonry tracks how AI answer engines mention brands and cite domains
|
|
10101
|
+
"initialize": 'Canonry tracks how AI answer engines mention brands and cite domains. Start with canonry_help({intent:"status"}) or a workflow; follow its stored reads and approval boundaries. Connected MCP clients need no skill, resource, plugin, or local CLI. The Canonry skill offers optional additional guidance.\nmentioned = brand in answer TEXT; cited = domain in SOURCE links. Never compute one from the other. A null answerMentioned means not checked, not false. No recorded sweep means no measured figure.\nGet approval for live provider reads, sweeps, probes, research, syncs and writes, scoped to the exact target, action and work. A GET or readOnlyHint does not mean free. canonry_help returns all liveTools for this connection; each needs approval, including read-only tools.\nREST exposes x-canonry-access; CLI help/catalog expose access; MCP help lists liveTools.\nStored-only: CLI --stored-only or CANONRY_STORED_ONLY=1; MCP --stored-only, --scope=stored-only or CANONRY_MCP_SCOPE=stored-only. It refuses live/write work (including doctor) before execution and suppresses housekeeping. CLI refusal is STORED_ONLY_REFUSED. Explicit exports may write files; server accounting remains separate from business mutations.\nHelp and skills grant no permissions; the server enforces authority. Report missing tools or 403; never bypass them with other credentials or endpoints. Hosted catalogs are fixed; use canonry_load_toolkit only when help offers it.\nReport concrete Canonry failures, confusing output, workarounds or improvements to the user and once via canonry_feedback. Exclude secrets and customer data.\n',
|
|
9932
10102
|
"approvalBoundary": [
|
|
9933
10103
|
"provider reads",
|
|
9934
10104
|
"sweeps",
|
|
@@ -9961,10 +10131,11 @@ var OPERATIONS_GUIDE = {
|
|
|
9961
10131
|
"health"
|
|
9962
10132
|
],
|
|
9963
10133
|
"next": [
|
|
10134
|
+
"canonry_status",
|
|
9964
10135
|
"canonry_projects_list",
|
|
9965
10136
|
"canonry_project_overview"
|
|
9966
10137
|
],
|
|
9967
|
-
"guidance": "
|
|
10138
|
+
"guidance": "Read canonry_status first for stored integration health, freshness, and repeated failures across accessible projects, then inspect a project overview for detail. Report missing evidence; do not start a sweep or sync to fill a gap."
|
|
9968
10139
|
},
|
|
9969
10140
|
"diagnose": {
|
|
9970
10141
|
"keywords": [
|
|
@@ -10029,12 +10200,13 @@ var OPERATIONS_GUIDE = {
|
|
|
10029
10200
|
"gtm"
|
|
10030
10201
|
],
|
|
10031
10202
|
"next": [
|
|
10203
|
+
"canonry_status",
|
|
10032
10204
|
"canonry_projects_list",
|
|
10033
10205
|
"canonry_project_get",
|
|
10034
10206
|
"canonry_ga_status",
|
|
10035
10207
|
"canonry_google_ads_status"
|
|
10036
10208
|
],
|
|
10037
|
-
"guidance": "
|
|
10209
|
+
"guidance": "Read canonry_status first for the stored instance or project health view, then use specialist tools for detail. Connecting, selecting resources, syncing, and live provider reads require scoped approval; never request credentials in chat."
|
|
10038
10210
|
},
|
|
10039
10211
|
"reports": {
|
|
10040
10212
|
"keywords": [
|
|
@@ -10070,6 +10242,8 @@ function operationsHelp(catalog, mode, intent = "", includeCatalog = false) {
|
|
|
10070
10242
|
}
|
|
10071
10243
|
const wanted = [...reads, ...requestedActions];
|
|
10072
10244
|
const loadToolkits = mode === "stdio-progressive" ? catalog.toolkits.filter((t) => !t.loaded && t.tools.some((name) => wanted.includes(name))).map((t) => t.name) : [];
|
|
10245
|
+
const liveTools = [...catalog.liveTools];
|
|
10246
|
+
for (const toolkit of catalog.toolkits) liveTools.push(...toolkit.liveTools);
|
|
10073
10247
|
return {
|
|
10074
10248
|
guideVersion: OPERATIONS_GUIDE.guideVersion,
|
|
10075
10249
|
mode,
|
|
@@ -10084,7 +10258,8 @@ function operationsHelp(catalog, mode, intent = "", includeCatalog = false) {
|
|
|
10084
10258
|
authority: OPERATIONS_GUIDE.authority,
|
|
10085
10259
|
operationsGuideUrl: OPERATIONS_GUIDE.operationsGuideUrl,
|
|
10086
10260
|
...loadToolkits.length ? { loadToolkits } : {},
|
|
10087
|
-
...includeCatalog ? catalog : {}
|
|
10261
|
+
...includeCatalog ? catalog : {},
|
|
10262
|
+
liveTools: [...new Set(liveTools)].sort()
|
|
10088
10263
|
};
|
|
10089
10264
|
}
|
|
10090
10265
|
|
|
@@ -10208,7 +10383,7 @@ function getCanonryMcpTools(scope = "all", tiers, credentialScopes, operator = f
|
|
|
10208
10383
|
const readOnly = scope === "read-only" || credentialScopes !== void 0 && isReadOnlyKey(credentialScopes);
|
|
10209
10384
|
const restricted = credentialScopes && restrictedWriteScopes(credentialScopes);
|
|
10210
10385
|
const authorized = canonryMcpTools.filter((tool) => !tool.requiresOperator || operator);
|
|
10211
|
-
const byScope = readOnly ? authorized.filter((tool) => tool.access === "read") : authorized.filter((tool) => {
|
|
10386
|
+
const byScope = scope === "stored-only" ? authorized.filter((tool) => toolOperationAccess(tool) === OperationAccesses.stored) : readOnly ? authorized.filter((tool) => tool.access === "read") : authorized.filter((tool) => {
|
|
10212
10387
|
if (!restricted || tool.access === "read") return true;
|
|
10213
10388
|
if (tool.requiredScope && restricted.includes(tool.requiredScope)) return true;
|
|
10214
10389
|
return restricted.some((grant) => grant !== RESEARCH_RUN_SCOPE) && tool.tier === "ads";
|