@canonry/canonry 6.1.5 → 6.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/agent-workspace/skills/canonry/references/canonry-cli.md +13 -1
- package/assets/assets/{AuditHistoryPanel-D-W_kwEY.js → AuditHistoryPanel-BUYWIjlG.js} +1 -1
- package/assets/assets/{BacklinksPage-BeqCFRO3.js → BacklinksPage-aBcxpN_9.js} +1 -1
- package/assets/assets/{HistoryPage-wAPbY0z4.js → HistoryPage-PoBuxiY_.js} +1 -1
- package/assets/assets/{MeasurementPropertyPage-BSOrkHCB.js → MeasurementPropertyPage-DyjyqHac.js} +1 -1
- package/assets/assets/{ProjectPage-v0C7CwyA.js → ProjectPage-Mmv5YW-K.js} +1 -1
- package/assets/assets/{RunsPage-CxolaIps.js → RunsPage-CHHxOpzo.js} +1 -1
- package/assets/assets/{SettingsPage-BQqJz0Ms.js → SettingsPage-CNKnrLXC.js} +1 -1
- package/assets/assets/{SiteHealthSection-C56kNcQQ.js → SiteHealthSection-C9RivT7G.js} +3 -3
- package/assets/assets/{TrafficPage-BDmWdYWf.js → TrafficPage-CY-ibXnb.js} +1 -1
- package/assets/assets/{TrafficSourceDetailPage-DZl3YNBs.js → TrafficSourceDetailPage-BgiPXubs.js} +1 -1
- package/assets/assets/{extract-error-message-D0mBVEGn.js → extract-error-message-H1dzzfBP.js} +1 -1
- package/assets/assets/{index-DZ__RzGa.js → index-DSCun3I9.js} +22 -22
- package/assets/assets/{react-sigma_core.esm.min-BQNp33-g.js → react-sigma_core.esm.min-uiYtR_DU.js} +1 -1
- package/assets/assets/{v2-overview-adapter-XZbD7swG.js → v2-overview-adapter-BQokN2eb.js} +1 -1
- package/assets/index.html +1 -1
- package/dist/{chunk-PAYC6TQ2.js → chunk-5GY5WBAF.js} +3 -3
- package/dist/{chunk-5QH72CTN.js → chunk-DERWXLHX.js} +15 -1
- package/dist/{chunk-J7LV4CS2.js → chunk-EV5G5QRR.js} +335 -280
- package/dist/{chunk-MSFBNFTI.js → chunk-FSRVG2H7.js} +2 -2
- package/dist/{chunk-4UEX44C3.js → chunk-OTROA7CN.js} +395 -173
- package/dist/{chunk-MTEVU6KG.js → chunk-QVGG76UW.js} +79 -24
- package/dist/{chunk-FRBKYQN7.js → chunk-ZZEPF3A5.js} +24 -4
- package/dist/cli.js +55 -10
- package/dist/{demo-server-UGILQVEC.js → demo-server-5MNLI6GC.js} +4 -4
- package/dist/index.js +6 -6
- package/dist/{intelligence-service-JYGP6LME.js → intelligence-service-5J36RBEM.js} +2 -2
- package/dist/mcp.js +4 -4
- package/package.json +11 -11
|
@@ -354,6 +354,8 @@ import {
|
|
|
354
354
|
extractAnswerMentions,
|
|
355
355
|
extractDomainsFromText,
|
|
356
356
|
factorStatusFromScore,
|
|
357
|
+
feedbackAcceptedDtoSchema,
|
|
358
|
+
feedbackSubmissionSchema,
|
|
357
359
|
filterBrandedSeedCandidates,
|
|
358
360
|
filterCapturedCitedUrls,
|
|
359
361
|
findDuplicateLocationLabels,
|
|
@@ -869,7 +871,7 @@ import {
|
|
|
869
871
|
wordpressSchemaDeployResultDtoSchema,
|
|
870
872
|
wordpressSchemaStatusResultDtoSchema,
|
|
871
873
|
wordpressStatusDtoSchema
|
|
872
|
-
} from "./chunk-
|
|
874
|
+
} from "./chunk-EV5G5QRR.js";
|
|
873
875
|
|
|
874
876
|
// src/intelligence-service.ts
|
|
875
877
|
import { eq as eq82, desc as desc36, asc as asc15, and as and69, ne as ne14, or as or20, inArray as inArray32, gte as gte22, lte as lte20, isNull as isNull16, sql as sql31, exists } from "drizzle-orm";
|
|
@@ -12466,7 +12468,7 @@ function resolveTrustProxy(raw) {
|
|
|
12466
12468
|
}
|
|
12467
12469
|
var FORWARDED_HEADERS = ["x-forwarded-for", "forwarded", "x-real-ip"];
|
|
12468
12470
|
function hasForwardedHeaders(request) {
|
|
12469
|
-
return FORWARDED_HEADERS.some((
|
|
12471
|
+
return FORWARDED_HEADERS.some((header2) => request.headers[header2] !== void 0);
|
|
12470
12472
|
}
|
|
12471
12473
|
function resolveCallerKey(request, trustProxyConfigured) {
|
|
12472
12474
|
const socketAddress = request.socket.remoteAddress ?? request.ip;
|
|
@@ -12496,9 +12498,9 @@ function cookieIsSecure(request, configured) {
|
|
|
12496
12498
|
function anyUsersExist(db) {
|
|
12497
12499
|
return db.select({ id: users.id }).from(users).limit(1).get() !== void 0;
|
|
12498
12500
|
}
|
|
12499
|
-
function parseCookieHeader(
|
|
12500
|
-
if (!
|
|
12501
|
-
return
|
|
12501
|
+
function parseCookieHeader(header2) {
|
|
12502
|
+
if (!header2) return {};
|
|
12503
|
+
return header2.split(";").map((part) => part.trim()).filter(Boolean).reduce((cookies, part) => {
|
|
12502
12504
|
const eqIdx = part.indexOf("=");
|
|
12503
12505
|
if (eqIdx <= 0) return cookies;
|
|
12504
12506
|
const name = part.slice(0, eqIdx).trim();
|
|
@@ -13018,11 +13020,11 @@ async function authPlugin(app, opts = {}) {
|
|
|
13018
13020
|
app.addHook("onRequest", async (request, reply) => {
|
|
13019
13021
|
const url = request.url.split("?")[0];
|
|
13020
13022
|
if (shouldSkipAuth(url)) return;
|
|
13021
|
-
const
|
|
13023
|
+
const header2 = request.headers.authorization;
|
|
13022
13024
|
let key;
|
|
13023
13025
|
let keyArrivedInCookie = false;
|
|
13024
|
-
if (
|
|
13025
|
-
const parts =
|
|
13026
|
+
if (header2) {
|
|
13027
|
+
const parts = header2.split(" ");
|
|
13026
13028
|
if (parts.length !== 2 || parts[0] !== "Bearer") {
|
|
13027
13029
|
throw authRequired();
|
|
13028
13030
|
}
|
|
@@ -17678,6 +17680,7 @@ function generationFailure(err, fallbackMessage) {
|
|
|
17678
17680
|
return providerAuthError(message);
|
|
17679
17681
|
case "RATE_LIMITED":
|
|
17680
17682
|
return quotaExceeded("provider requests", { message });
|
|
17683
|
+
case "PROVIDER_UNAVAILABLE":
|
|
17681
17684
|
case "NETWORK":
|
|
17682
17685
|
case "TIMEOUT":
|
|
17683
17686
|
return providerError(message);
|
|
@@ -22568,11 +22571,11 @@ function parseCsvRecords(value) {
|
|
|
22568
22571
|
return records.filter((record) => !record.physicalBlank);
|
|
22569
22572
|
}
|
|
22570
22573
|
function parseHeader(records) {
|
|
22571
|
-
const
|
|
22572
|
-
if (!
|
|
22574
|
+
const header2 = records.at(0);
|
|
22575
|
+
if (!header2) csvError("csv-header-missing", "CSV must include a property and group header row.");
|
|
22573
22576
|
const allowed = /* @__PURE__ */ new Set(["property", "group", "url"]);
|
|
22574
22577
|
const indices = /* @__PURE__ */ new Map();
|
|
22575
|
-
for (const [index2, raw] of
|
|
22578
|
+
for (const [index2, raw] of header2.fields.entries()) {
|
|
22576
22579
|
const name = normalizeGroupMembershipLabel(raw);
|
|
22577
22580
|
if (!allowed.has(name)) {
|
|
22578
22581
|
csvError("csv-header-invalid", `CSV header "${raw}" is not supported. Use property, group, and optional url.`, 400, { header: raw });
|
|
@@ -22587,7 +22590,7 @@ function parseHeader(records) {
|
|
|
22587
22590
|
csvError("csv-header-missing", `CSV is missing the required "${required2}" header.`, 400, { header: required2 });
|
|
22588
22591
|
}
|
|
22589
22592
|
}
|
|
22590
|
-
return { indices, length:
|
|
22593
|
+
return { indices, length: header2.fields.length };
|
|
22591
22594
|
}
|
|
22592
22595
|
function parseGroupMembershipCsv(csv) {
|
|
22593
22596
|
const byteLength = Buffer.byteLength(csv, "utf8");
|
|
@@ -22600,7 +22603,7 @@ function parseGroupMembershipCsv(csv) {
|
|
|
22600
22603
|
);
|
|
22601
22604
|
}
|
|
22602
22605
|
const records = parseCsvRecords(csv);
|
|
22603
|
-
const
|
|
22606
|
+
const header2 = parseHeader(records);
|
|
22604
22607
|
const dataRecords = records.slice(1);
|
|
22605
22608
|
if (dataRecords.length > MEASUREMENT_GROUP_MEMBERSHIP_CSV_MAX_DATA_ROWS) {
|
|
22606
22609
|
csvError(
|
|
@@ -22610,9 +22613,9 @@ function parseGroupMembershipCsv(csv) {
|
|
|
22610
22613
|
{ rowCount: dataRecords.length, maxRows: MEASUREMENT_GROUP_MEMBERSHIP_CSV_MAX_DATA_ROWS }
|
|
22611
22614
|
);
|
|
22612
22615
|
}
|
|
22613
|
-
const propertyIndex =
|
|
22614
|
-
const groupIndex =
|
|
22615
|
-
const urlIndex =
|
|
22616
|
+
const propertyIndex = header2.indices.get("property");
|
|
22617
|
+
const groupIndex = header2.indices.get("group");
|
|
22618
|
+
const urlIndex = header2.indices.get("url");
|
|
22616
22619
|
const rows = dataRecords.map((record, index2) => {
|
|
22617
22620
|
const property = record.fields[propertyIndex] ?? "";
|
|
22618
22621
|
const group = record.fields[groupIndex] ?? "";
|
|
@@ -22625,7 +22628,7 @@ function parseGroupMembershipCsv(csv) {
|
|
|
22625
22628
|
url,
|
|
22626
22629
|
normalizedProperty: normalizeGroupMembershipLabel(property),
|
|
22627
22630
|
normalizedGroupLabel: normalizeGroupMembershipLabel(group),
|
|
22628
|
-
columnCountValid: record.fields.length ===
|
|
22631
|
+
columnCountValid: record.fields.length === header2.length
|
|
22629
22632
|
};
|
|
22630
22633
|
});
|
|
22631
22634
|
return { sourceChecksum: sourceChecksum(csv), rows };
|
|
@@ -33765,7 +33768,7 @@ function renderWinsLosses(insights2, heading, emptyMessage, audience) {
|
|
|
33765
33768
|
</tr>`;
|
|
33766
33769
|
}).join("");
|
|
33767
33770
|
const headerCells = (isClient ? REPORT_SECTION_COPY["whats-changed"].client : REPORT_SECTION_COPY["whats-changed"].agency).insightHeaders;
|
|
33768
|
-
const headers = `<tr>${headerCells.map((
|
|
33771
|
+
const headers = `<tr>${headerCells.map((header2) => `<th>${header2}</th>`).join("")}</tr>`;
|
|
33769
33772
|
return `<div class="chart-card"><h3>${escapeHtml2(heading)}</h3>
|
|
33770
33773
|
<div class="table-scroll"><table class="report-table">
|
|
33771
33774
|
<thead>${headers}</thead>
|
|
@@ -39923,6 +39926,8 @@ var SCHEMA_TABLE = {
|
|
|
39923
39926
|
SnapshotRequest: z.object(snapshotRequestInputSchema.shape).omit({ phrases: true }),
|
|
39924
39927
|
SourceBreakdownDto: sourceBreakdownDtoSchema,
|
|
39925
39928
|
TelemetryEventAcceptedDto: telemetryEventAcceptedDtoSchema,
|
|
39929
|
+
FeedbackSubmission: feedbackSubmissionSchema,
|
|
39930
|
+
FeedbackAcceptedDto: feedbackAcceptedDtoSchema,
|
|
39926
39931
|
TelemetryStatusDto: telemetryStatusDtoSchema,
|
|
39927
39932
|
OperationalLogListDto: operationalLogListDtoSchema,
|
|
39928
39933
|
CloudflareWorkerIngestRequest: cloudflareWorkerIngestRequestSchema,
|
|
@@ -43052,6 +43057,28 @@ var routeCatalog = [
|
|
|
43052
43057
|
400: errorResponse("Invalid onboarding telemetry event.")
|
|
43053
43058
|
}
|
|
43054
43059
|
},
|
|
43060
|
+
{
|
|
43061
|
+
method: "post",
|
|
43062
|
+
path: "/api/v1/feedback",
|
|
43063
|
+
summary: "Send product feedback about Canonry",
|
|
43064
|
+
description: "Forwards a struggle, bug, improvement, or other note about Canonry itself to the Canonry team (canonry.ai). Free text is redacted for credentials before it leaves the machine; never include customer data. The server adds version, OS, and the calling surface and agent; the anonymous install id is attached only while telemetry is enabled.",
|
|
43065
|
+
tags: ["feedback"],
|
|
43066
|
+
requestBody: {
|
|
43067
|
+
required: true,
|
|
43068
|
+
content: {
|
|
43069
|
+
"application/json": {
|
|
43070
|
+
schema: { $ref: "#/components/schemas/FeedbackSubmission" }
|
|
43071
|
+
}
|
|
43072
|
+
}
|
|
43073
|
+
},
|
|
43074
|
+
responses: {
|
|
43075
|
+
202: jsonResponse("Feedback accepted by the collector.", "FeedbackAcceptedDto"),
|
|
43076
|
+
400: errorResponse("Invalid feedback."),
|
|
43077
|
+
429: errorResponse("Feedback rate limit reached; try again later."),
|
|
43078
|
+
501: errorResponse("Feedback is not available in this deployment."),
|
|
43079
|
+
502: errorResponse("The feedback collector could not be reached or rejected the submission.")
|
|
43080
|
+
}
|
|
43081
|
+
},
|
|
43055
43082
|
{
|
|
43056
43083
|
method: "get",
|
|
43057
43084
|
path: "/api/v1/screenshots/{snapshotId}",
|
|
@@ -47790,6 +47817,31 @@ async function telemetryRoutes(app, opts) {
|
|
|
47790
47817
|
});
|
|
47791
47818
|
}
|
|
47792
47819
|
|
|
47820
|
+
// ../api-routes/src/feedback.ts
|
|
47821
|
+
function header(value) {
|
|
47822
|
+
return Array.isArray(value) ? value[0] : value;
|
|
47823
|
+
}
|
|
47824
|
+
async function feedbackRoutes(app, opts) {
|
|
47825
|
+
app.post("/feedback", async (request, reply) => {
|
|
47826
|
+
const parsed = feedbackSubmissionSchema.safeParse(request.body);
|
|
47827
|
+
if (!parsed.success) {
|
|
47828
|
+
throw validationError("Invalid feedback", {
|
|
47829
|
+
issues: parsed.error.issues.map((issue) => ({ code: issue.code, path: issue.path.join(".") }))
|
|
47830
|
+
});
|
|
47831
|
+
}
|
|
47832
|
+
if (!opts.submitFeedback) {
|
|
47833
|
+
throw notImplemented("Feedback is not available in this deployment");
|
|
47834
|
+
}
|
|
47835
|
+
const accepted = await opts.submitFeedback(parsed.data, {
|
|
47836
|
+
userAgent: header(request.headers["user-agent"]),
|
|
47837
|
+
surface: header(request.headers[USAGE_TELEMETRY_HEADERS.surface]),
|
|
47838
|
+
agent: header(request.headers[USAGE_TELEMETRY_HEADERS.agent]),
|
|
47839
|
+
mcpClient: header(request.headers[USAGE_TELEMETRY_HEADERS.mcpClient])
|
|
47840
|
+
});
|
|
47841
|
+
return reply.status(202).send(accepted);
|
|
47842
|
+
});
|
|
47843
|
+
}
|
|
47844
|
+
|
|
47793
47845
|
// ../api-routes/src/operational-logs.ts
|
|
47794
47846
|
async function operationalLogsRoutes(app, opts = {}) {
|
|
47795
47847
|
app.get("/operations/logs", async (request, reply) => {
|
|
@@ -47810,8 +47862,8 @@ async function operationalLogsRoutes(app, opts = {}) {
|
|
|
47810
47862
|
return withoutUnrequestedFields(page3, requestedFields(request.headers[OPERATIONAL_LOG_FIELDS_HEADER]));
|
|
47811
47863
|
});
|
|
47812
47864
|
}
|
|
47813
|
-
function requestedFields(
|
|
47814
|
-
const names = (Array.isArray(
|
|
47865
|
+
function requestedFields(header2) {
|
|
47866
|
+
const names = (Array.isArray(header2) ? header2 : [header2 ?? ""]).flatMap((value) => value.split(",")).map((name) => name.trim());
|
|
47815
47867
|
return new Set(OPERATIONAL_LOG_OPT_IN_CONTEXT_FIELDS.filter((field) => names.includes(field)));
|
|
47816
47868
|
}
|
|
47817
47869
|
function withoutUnrequestedFields(page3, requested) {
|
|
@@ -49249,7 +49301,7 @@ function createServiceAccountJwt(clientEmail, privateKey, scope) {
|
|
|
49249
49301
|
validatePrivateKey(privateKey);
|
|
49250
49302
|
validateScope(scope);
|
|
49251
49303
|
const now = Math.floor(Date.now() / 1e3);
|
|
49252
|
-
const
|
|
49304
|
+
const header2 = { alg: "RS256", typ: "JWT" };
|
|
49253
49305
|
const payload = {
|
|
49254
49306
|
iss: clientEmail,
|
|
49255
49307
|
scope,
|
|
@@ -49259,7 +49311,7 @@ function createServiceAccountJwt(clientEmail, privateKey, scope) {
|
|
|
49259
49311
|
// 1 hour
|
|
49260
49312
|
};
|
|
49261
49313
|
const encode = (obj) => Buffer.from(JSON.stringify(obj)).toString("base64url");
|
|
49262
|
-
const headerB64 = encode(
|
|
49314
|
+
const headerB64 = encode(header2);
|
|
49263
49315
|
const payloadB64 = encode(payload);
|
|
49264
49316
|
const signingInput = `${headerB64}.${payloadB64}`;
|
|
49265
49317
|
const sign = crypto30.createSign("RSA-SHA256");
|
|
@@ -63465,7 +63517,7 @@ function createServiceAccountJwt2(clientEmail, privateKey, scope) {
|
|
|
63465
63517
|
if (!privateKey) throw new CloudRunAuthError("privateKey is required");
|
|
63466
63518
|
if (!scope) throw new CloudRunAuthError("scope is required");
|
|
63467
63519
|
const now = Math.floor(Date.now() / 1e3);
|
|
63468
|
-
const
|
|
63520
|
+
const header2 = { alg: "RS256", typ: "JWT" };
|
|
63469
63521
|
const payload = {
|
|
63470
63522
|
iss: clientEmail,
|
|
63471
63523
|
scope,
|
|
@@ -63474,7 +63526,7 @@ function createServiceAccountJwt2(clientEmail, privateKey, scope) {
|
|
|
63474
63526
|
exp: now + 3600
|
|
63475
63527
|
};
|
|
63476
63528
|
const encode = (obj) => Buffer.from(JSON.stringify(obj)).toString("base64url");
|
|
63477
|
-
const headerB64 = encode(
|
|
63529
|
+
const headerB64 = encode(header2);
|
|
63478
63530
|
const payloadB64 = encode(payload);
|
|
63479
63531
|
const signingInput = `${headerB64}.${payloadB64}`;
|
|
63480
63532
|
const sign = crypto43.createSign("RSA-SHA256");
|
|
@@ -90766,6 +90818,9 @@ async function apiRoutes(app, opts) {
|
|
|
90766
90818
|
setTelemetryEnabled: opts.setTelemetryEnabled,
|
|
90767
90819
|
recordOnboardingEvent: opts.recordOnboardingEvent
|
|
90768
90820
|
});
|
|
90821
|
+
await api.register(feedbackRoutes, {
|
|
90822
|
+
submitFeedback: opts.submitFeedback
|
|
90823
|
+
});
|
|
90769
90824
|
await api.register(adsRoutes, {
|
|
90770
90825
|
adsCredentialStore: opts.adsCredentialStore,
|
|
90771
90826
|
verifyAdsAccount: opts.verifyAdsAccount,
|
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
PACKAGE_VERSION,
|
|
6
6
|
canonryMcpTools,
|
|
7
7
|
isMachineFormat
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-DERWXLHX.js";
|
|
9
9
|
import {
|
|
10
10
|
AGENT_PROVIDER_IDS,
|
|
11
11
|
CANONRY_NPM_PACKAGE_URL,
|
|
@@ -50,7 +50,7 @@ import {
|
|
|
50
50
|
skillsClientSchema,
|
|
51
51
|
upgradeCaveatFor,
|
|
52
52
|
upgradeCommandFor
|
|
53
|
-
} from "./chunk-
|
|
53
|
+
} from "./chunk-EV5G5QRR.js";
|
|
54
54
|
|
|
55
55
|
// src/config.ts
|
|
56
56
|
import fs from "fs";
|
|
@@ -186,7 +186,7 @@ function getBootstrapEnv(source, overrides) {
|
|
|
186
186
|
if (parsed.GEMINI_API_KEY || parsed.GEMINI_VERTEX_PROJECT) {
|
|
187
187
|
providers.gemini = {
|
|
188
188
|
apiKey: parsed.GEMINI_API_KEY ?? "",
|
|
189
|
-
model: parsed.GEMINI_MODEL || "gemini-
|
|
189
|
+
model: parsed.GEMINI_MODEL || "gemini-flash-latest",
|
|
190
190
|
baseUrl: parsed.GEMINI_BASE_URL,
|
|
191
191
|
quota: providerQuotaPolicySchema.parse({
|
|
192
192
|
maxConcurrency: 2,
|
|
@@ -3384,6 +3384,22 @@ var putApiV1Telemetry = (options) => {
|
|
|
3384
3384
|
}
|
|
3385
3385
|
});
|
|
3386
3386
|
};
|
|
3387
|
+
var postApiV1Feedback = (options) => {
|
|
3388
|
+
return (options.client ?? client).post({
|
|
3389
|
+
security: [
|
|
3390
|
+
{
|
|
3391
|
+
scheme: "bearer",
|
|
3392
|
+
type: "http"
|
|
3393
|
+
}
|
|
3394
|
+
],
|
|
3395
|
+
url: "/api/v1/feedback",
|
|
3396
|
+
...options,
|
|
3397
|
+
headers: {
|
|
3398
|
+
"Content-Type": "application/json",
|
|
3399
|
+
...options.headers
|
|
3400
|
+
}
|
|
3401
|
+
});
|
|
3402
|
+
};
|
|
3387
3403
|
var getApiV1CdpStatus = (options) => {
|
|
3388
3404
|
return (options?.client ?? client).get({
|
|
3389
3405
|
security: [
|
|
@@ -7482,6 +7498,10 @@ var ApiClient = class {
|
|
|
7482
7498
|
async updateTelemetry(enabled) {
|
|
7483
7499
|
return normalizeTelemetryStatus(await this.invoke(() => putApiV1Telemetry({ client: this.heyClient, body: { enabled } })));
|
|
7484
7500
|
}
|
|
7501
|
+
/** Forward product feedback about Canonry to canonry.ai through the server. */
|
|
7502
|
+
async sendFeedback(body) {
|
|
7503
|
+
return this.invoke(() => postApiV1Feedback({ client: this.heyClient, body }));
|
|
7504
|
+
}
|
|
7485
7505
|
// ── Schedules / notifications / locations ───────────────────────────────
|
|
7486
7506
|
async listSchedules(project) {
|
|
7487
7507
|
return this.invoke(
|
|
@@ -9651,7 +9671,7 @@ var OPERATIONS_GUIDE = {
|
|
|
9651
9671
|
"guideVersion": "v1",
|
|
9652
9672
|
"operationsGuideUrl": "https://github.com/Canonry/canonry/blob/main/docs/agent-operations/v1.md",
|
|
9653
9673
|
"resourceUri": "canonry://agent-operations/v1",
|
|
9654
|
-
"initialize": 'Canonry tracks how AI answer engines mention brands and cite domains.\nStart with canonry_help({intent:"status"}), or name your intended workflow. It returns a small route of currently available tools and approval boundaries. Follow its stored-evidence reads before proposing action. No skill, resource reader, plugin installation, or local CLI is required for connected MCP clients. A host-native Canonry skill, if installed, is 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 explicit approval for live provider reads, sweeps, probes, research, syncs, and writes, bounded to the target and requested work. A readOnlyHint or GET is not proof of a free operation. Live ads reads include canonry_ads_account, canonry_ads_geo_search, canonry_ads_live_delivery, canonry_ads_conversion_pixels, canonry_ads_conversion_event_settings. Google live reads/syncs include canonry_google_ads_customers, canonry_gtm_accounts, canonry_gtm_containers, canonry_gtm_workspaces, canonry_google_ads_sync, canonry_gtm_sync.\nHelp and skills grant no permissions. The server enforces authority. On missing tools or 403, report the boundary; do not switch credentials or endpoints to bypass it. Hosted catalogs are fixed; only use canonry_load_toolkit when help explicitly offers it.\n',
|
|
9674
|
+
"initialize": 'Canonry tracks how AI answer engines mention brands and cite domains.\nStart with canonry_help({intent:"status"}), or name your intended workflow. It returns a small route of currently available tools and approval boundaries. Follow its stored-evidence reads before proposing action. No skill, resource reader, plugin installation, or local CLI is required for connected MCP clients. A host-native Canonry skill, if installed, is 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 explicit approval for live provider reads, sweeps, probes, research, syncs, and writes, bounded to the target and requested work. A readOnlyHint or GET is not proof of a free operation. Live ads reads include canonry_ads_account, canonry_ads_geo_search, canonry_ads_live_delivery, canonry_ads_conversion_pixels, canonry_ads_conversion_event_settings. Google live reads/syncs include canonry_google_ads_customers, canonry_gtm_accounts, canonry_gtm_containers, canonry_gtm_workspaces, canonry_google_ads_sync, canonry_gtm_sync.\nHelp and skills grant no permissions. The server enforces authority. On missing tools or 403, report the boundary; do not switch credentials or endpoints to bypass it. Hosted catalogs are fixed; only use canonry_load_toolkit when help explicitly offers it.\nIf you uncover a Canonry struggle (failure, confusing output, workaround) or a concrete improvement, tell the user and send it once with canonry_feedback. No secrets or customer data.\n',
|
|
9655
9675
|
"approvalBoundary": [
|
|
9656
9676
|
"provider reads",
|
|
9657
9677
|
"sweeps",
|
package/dist/cli.js
CHANGED
|
@@ -35,11 +35,11 @@ import {
|
|
|
35
35
|
trackCliCommandFinished,
|
|
36
36
|
trackEvent,
|
|
37
37
|
waitForServerRuntimeStartup
|
|
38
|
-
} from "./chunk-
|
|
38
|
+
} from "./chunk-OTROA7CN.js";
|
|
39
39
|
import {
|
|
40
40
|
autoSyncSkills,
|
|
41
41
|
formatAutoSyncNotice
|
|
42
|
-
} from "./chunk-
|
|
42
|
+
} from "./chunk-5GY5WBAF.js";
|
|
43
43
|
import {
|
|
44
44
|
configExists,
|
|
45
45
|
createApiClient,
|
|
@@ -56,13 +56,13 @@ import {
|
|
|
56
56
|
saveConfig,
|
|
57
57
|
saveConfigPatch,
|
|
58
58
|
shouldPrintServeSkillsNudge
|
|
59
|
-
} from "./chunk-
|
|
59
|
+
} from "./chunk-ZZEPF3A5.js";
|
|
60
60
|
import {
|
|
61
61
|
DEFAULT_DEMO_TRUSTED_PROXIES,
|
|
62
62
|
trustedProxiesProblem,
|
|
63
63
|
trustedProxyProblem
|
|
64
64
|
} from "./chunk-RB2F4D3Z.js";
|
|
65
|
-
import "./chunk-
|
|
65
|
+
import "./chunk-FSRVG2H7.js";
|
|
66
66
|
import {
|
|
67
67
|
CliError,
|
|
68
68
|
EXIT_SYSTEM_ERROR,
|
|
@@ -74,7 +74,7 @@ import {
|
|
|
74
74
|
runMeasurementDraftAction,
|
|
75
75
|
systemError,
|
|
76
76
|
usageError
|
|
77
|
-
} from "./chunk-
|
|
77
|
+
} from "./chunk-DERWXLHX.js";
|
|
78
78
|
import {
|
|
79
79
|
CLOUDFLARE_WORKER_BINDINGS,
|
|
80
80
|
CLOUDFLARE_WORKER_GENERATED_MARKER,
|
|
@@ -90,7 +90,7 @@ import {
|
|
|
90
90
|
queries,
|
|
91
91
|
renderReportHtml,
|
|
92
92
|
runs
|
|
93
|
-
} from "./chunk-
|
|
93
|
+
} from "./chunk-QVGG76UW.js";
|
|
94
94
|
import {
|
|
95
95
|
AdsDeliverySnapshotStatuses,
|
|
96
96
|
AdsHistoricalCampaignRollupStatuses,
|
|
@@ -103,6 +103,7 @@ import {
|
|
|
103
103
|
CheckScopes,
|
|
104
104
|
CheckStatuses,
|
|
105
105
|
CitationStates,
|
|
106
|
+
FEEDBACK_KINDS,
|
|
106
107
|
GaMoverChangeBases,
|
|
107
108
|
MeasurementEvidenceShapes,
|
|
108
109
|
OUTSTANDING_PROVIDER_BATCH_STATUSES,
|
|
@@ -145,6 +146,7 @@ import {
|
|
|
145
146
|
discoveryCompetitorTypeSchema,
|
|
146
147
|
effectiveDomains,
|
|
147
148
|
factorStatusFromScore,
|
|
149
|
+
feedbackSubmissionSchema,
|
|
148
150
|
formatGbpMetricLabel,
|
|
149
151
|
formatIsoDate,
|
|
150
152
|
formatMicros,
|
|
@@ -198,7 +200,7 @@ import {
|
|
|
198
200
|
visibilityCompareSelectionSchema,
|
|
199
201
|
visibilityReportRequestSchema,
|
|
200
202
|
winnabilityClassSchema
|
|
201
|
-
} from "./chunk-
|
|
203
|
+
} from "./chunk-EV5G5QRR.js";
|
|
202
204
|
|
|
203
205
|
// src/cli.ts
|
|
204
206
|
import { pathToFileURL } from "url";
|
|
@@ -732,7 +734,7 @@ function parseDemoTrustedProxies(values) {
|
|
|
732
734
|
async function demoCommand(options) {
|
|
733
735
|
const { host, port } = parseDemoListenOptions(options);
|
|
734
736
|
const trustProxy = parseDemoTrustedProxies(options.trustProxy);
|
|
735
|
-
const { createDemoServer } = await import("./demo-server-
|
|
737
|
+
const { createDemoServer } = await import("./demo-server-5MNLI6GC.js");
|
|
736
738
|
const app = await createDemoServer({ trustProxy });
|
|
737
739
|
let stopping = false;
|
|
738
740
|
const stop = () => {
|
|
@@ -16126,7 +16128,7 @@ var DEFAULT_AGENT_MODELS = {
|
|
|
16126
16128
|
openai: "openai/gpt-4o",
|
|
16127
16129
|
openrouter: "openrouter/anthropic/claude-sonnet-4-6",
|
|
16128
16130
|
groq: "groq/llama-4-scout-17b",
|
|
16129
|
-
google: "google/gemini-
|
|
16131
|
+
google: "google/gemini-3.8-flash",
|
|
16130
16132
|
mistral: "mistral/mistral-large-latest",
|
|
16131
16133
|
xai: "xai/grok-2"
|
|
16132
16134
|
};
|
|
@@ -16208,7 +16210,7 @@ async function initCommand(opts) {
|
|
|
16208
16210
|
console.log('Or use "canonry bootstrap".\n');
|
|
16209
16211
|
const geminiApiKey = await promptProviderApiKey("Gemini", "GEMINI_API_KEY");
|
|
16210
16212
|
if (geminiApiKey) {
|
|
16211
|
-
const geminiModel = await prompt(" Gemini model [gemini-
|
|
16213
|
+
const geminiModel = await prompt(" Gemini model [gemini-flash-latest]: ") || "gemini-flash-latest";
|
|
16212
16214
|
providers.gemini = { apiKey: geminiApiKey, model: geminiModel, quota: DEFAULT_QUOTA };
|
|
16213
16215
|
}
|
|
16214
16216
|
const openaiApiKey = await promptProviderApiKey("OpenAI", "OPENAI_API_KEY");
|
|
@@ -16950,6 +16952,33 @@ Usage: canonry telemetry <status|enable|disable> [--target local|server] [--form
|
|
|
16950
16952
|
}
|
|
16951
16953
|
}
|
|
16952
16954
|
|
|
16955
|
+
// src/commands/feedback.ts
|
|
16956
|
+
async function feedbackCommand(input, format) {
|
|
16957
|
+
const parsed = feedbackSubmissionSchema.safeParse({
|
|
16958
|
+
kind: input.kind ?? "other",
|
|
16959
|
+
summary: input.summary ?? "",
|
|
16960
|
+
...input.details ? { details: input.details } : {},
|
|
16961
|
+
...input.area ? { area: input.area } : {},
|
|
16962
|
+
...input.command ? { command: input.command } : {},
|
|
16963
|
+
...input.errorCode ? { errorCode: input.errorCode } : {}
|
|
16964
|
+
});
|
|
16965
|
+
if (!parsed.success) {
|
|
16966
|
+
const fields = [...new Set(parsed.error.issues.map((issue) => issue.path.join(".") || "input"))].join(", ");
|
|
16967
|
+
throw usageError(`Error: invalid feedback (${fields}). Kind is one of ${FEEDBACK_KINDS.join(", ")}; the summary is required, up to 500 characters.
|
|
16968
|
+
Usage: ${FEEDBACK_USAGE}`, {
|
|
16969
|
+
message: "Invalid feedback",
|
|
16970
|
+
details: { fields }
|
|
16971
|
+
});
|
|
16972
|
+
}
|
|
16973
|
+
const result = await createApiClient().sendFeedback(parsed.data);
|
|
16974
|
+
if (isMachineFormat(format)) {
|
|
16975
|
+
console.log(JSON.stringify(result, null, 2));
|
|
16976
|
+
return;
|
|
16977
|
+
}
|
|
16978
|
+
console.log(`Thanks, feedback sent to the Canonry team (id ${result.id}).`);
|
|
16979
|
+
}
|
|
16980
|
+
var FEEDBACK_USAGE = 'canonry feedback "<summary>" [--kind struggle|bug|improvement|other] [--details <text>] [--area <area>] [--command <canonry command>] [--error-code <code>] [--format json]';
|
|
16981
|
+
|
|
16953
16982
|
// src/commands/logs.ts
|
|
16954
16983
|
async function showOperationalLogs(query, format) {
|
|
16955
16984
|
const parsed = logQuerySchema.safeParse(query);
|
|
@@ -17110,6 +17139,22 @@ var SYSTEM_CLI_COMMANDS = [
|
|
|
17110
17139
|
stopDaemon(input.format);
|
|
17111
17140
|
}
|
|
17112
17141
|
},
|
|
17142
|
+
{
|
|
17143
|
+
path: ["feedback"],
|
|
17144
|
+
usage: FEEDBACK_USAGE,
|
|
17145
|
+
help: "Send a struggle, bug, improvement or note about Canonry itself to the Canonry team. Credentials are redacted before sending; never include customer data. The anonymous install id is attached only while telemetry is enabled.",
|
|
17146
|
+
options: { kind: stringOption(), details: stringOption(), area: stringOption(), command: stringOption(), "error-code": stringOption() },
|
|
17147
|
+
run: async (input) => {
|
|
17148
|
+
await feedbackCommand({
|
|
17149
|
+
summary: input.positionals.join(" ").trim() || void 0,
|
|
17150
|
+
kind: getString(input.values, "kind"),
|
|
17151
|
+
details: getString(input.values, "details"),
|
|
17152
|
+
area: getString(input.values, "area"),
|
|
17153
|
+
command: getString(input.values, "command"),
|
|
17154
|
+
errorCode: getString(input.values, "error-code")
|
|
17155
|
+
}, input.format);
|
|
17156
|
+
}
|
|
17157
|
+
},
|
|
17113
17158
|
{
|
|
17114
17159
|
path: ["telemetry", "status"],
|
|
17115
17160
|
usage: "canonry telemetry status [--target local|server] [--format json]",
|
|
@@ -5,11 +5,11 @@ import {
|
|
|
5
5
|
computeFactorAverages,
|
|
6
6
|
layoutSiteCrawlGraphInput,
|
|
7
7
|
persistSiteCrawlGraphLayout
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-FSRVG2H7.js";
|
|
9
9
|
import {
|
|
10
10
|
PACKAGE_VERSION,
|
|
11
11
|
canonryMcpTools
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-DERWXLHX.js";
|
|
13
13
|
import {
|
|
14
14
|
HISTORY_WINDOW_RUNS,
|
|
15
15
|
IntelligenceService,
|
|
@@ -85,7 +85,7 @@ import {
|
|
|
85
85
|
siteCrawlPages,
|
|
86
86
|
siteCrawlSnapshots,
|
|
87
87
|
trafficSources
|
|
88
|
-
} from "./chunk-
|
|
88
|
+
} from "./chunk-QVGG76UW.js";
|
|
89
89
|
import {
|
|
90
90
|
RunKinds,
|
|
91
91
|
SiteCrawlFetchStates,
|
|
@@ -112,7 +112,7 @@ import {
|
|
|
112
112
|
roundPreservingTotal,
|
|
113
113
|
siteAuditPageFactorSchema,
|
|
114
114
|
wilsonInterval
|
|
115
|
-
} from "./chunk-
|
|
115
|
+
} from "./chunk-EV5G5QRR.js";
|
|
116
116
|
|
|
117
117
|
// src/demo-server.ts
|
|
118
118
|
import { dirname, join as join2 } from "path";
|
package/dist/index.js
CHANGED
|
@@ -3,14 +3,14 @@ import {
|
|
|
3
3
|
createGoogleMarketingCredentialStore,
|
|
4
4
|
createGoogleMarketingRuntime,
|
|
5
5
|
createServer
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-OTROA7CN.js";
|
|
7
7
|
import {
|
|
8
8
|
loadConfig
|
|
9
|
-
} from "./chunk-
|
|
10
|
-
import "./chunk-
|
|
11
|
-
import "./chunk-
|
|
12
|
-
import "./chunk-
|
|
13
|
-
import "./chunk-
|
|
9
|
+
} from "./chunk-ZZEPF3A5.js";
|
|
10
|
+
import "./chunk-FSRVG2H7.js";
|
|
11
|
+
import "./chunk-DERWXLHX.js";
|
|
12
|
+
import "./chunk-QVGG76UW.js";
|
|
13
|
+
import "./chunk-EV5G5QRR.js";
|
|
14
14
|
export {
|
|
15
15
|
GoogleMarketingRuntimeError,
|
|
16
16
|
createGoogleMarketingCredentialStore,
|
package/dist/mcp.js
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import {
|
|
2
2
|
autoSyncSkills
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-5GY5WBAF.js";
|
|
4
4
|
import {
|
|
5
5
|
createApiClient,
|
|
6
6
|
createCanonryMcpServer
|
|
7
|
-
} from "./chunk-
|
|
8
|
-
import "./chunk-
|
|
7
|
+
} from "./chunk-ZZEPF3A5.js";
|
|
8
|
+
import "./chunk-DERWXLHX.js";
|
|
9
9
|
import {
|
|
10
10
|
isReadOnlyKey,
|
|
11
11
|
updateCheckEnvOptOut
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-EV5G5QRR.js";
|
|
13
13
|
|
|
14
14
|
// src/mcp/cli.ts
|
|
15
15
|
import { randomUUID } from "crypto";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@canonry/canonry",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.3.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Self-hosted AI visibility (AEO) platform: track how ChatGPT, Claude, Gemini, and Perplexity cite your domain, join it with Search Console, GA4, server-side traffic, and paid media, and fix what you find through agent tools (CLI, REST, MCP). Local SQLite.",
|
|
6
6
|
"keywords": [
|
|
@@ -86,33 +86,33 @@
|
|
|
86
86
|
"tsup": "^8.5.1",
|
|
87
87
|
"tsx": "^4.19.0",
|
|
88
88
|
"@ainyc/canonry-web": "0.0.0",
|
|
89
|
-
"@ainyc/canonry-api-client": "0.0.0",
|
|
90
89
|
"@ainyc/canonry-api-routes": "0.0.0",
|
|
90
|
+
"@ainyc/canonry-contracts": "0.0.0",
|
|
91
91
|
"@ainyc/canonry-config": "0.0.0",
|
|
92
|
+
"@ainyc/canonry-api-client": "0.0.0",
|
|
92
93
|
"@ainyc/canonry-db": "0.0.0",
|
|
93
|
-
"@ainyc/canonry-contracts": "0.0.0",
|
|
94
94
|
"@ainyc/canonry-integration-bing": "0.0.0",
|
|
95
|
-
"@ainyc/canonry-integration-cloud-run": "0.0.0",
|
|
96
95
|
"@ainyc/canonry-integration-cloudflare-queue": "0.0.0",
|
|
97
|
-
"@ainyc/canonry-integration-
|
|
96
|
+
"@ainyc/canonry-integration-cloud-run": "0.0.0",
|
|
98
97
|
"@ainyc/canonry-integration-cloudflare-worker": "0.0.0",
|
|
98
|
+
"@ainyc/canonry-integration-commoncrawl": "0.0.0",
|
|
99
99
|
"@ainyc/canonry-integration-google": "0.0.0",
|
|
100
|
-
"@ainyc/canonry-integration-google-business-profile": "0.0.0",
|
|
101
100
|
"@ainyc/canonry-integration-google-ads": "0.0.0",
|
|
101
|
+
"@ainyc/canonry-integration-google-business-profile": "0.0.0",
|
|
102
|
+
"@ainyc/canonry-integration-google-places": "0.0.0",
|
|
102
103
|
"@ainyc/canonry-integration-google-tag-manager": "0.0.0",
|
|
103
|
-
"@ainyc/canonry-integration-openai-ads": "0.0.0",
|
|
104
104
|
"@ainyc/canonry-integration-traffic": "0.0.0",
|
|
105
105
|
"@ainyc/canonry-intelligence": "0.0.0",
|
|
106
|
+
"@ainyc/canonry-integration-openai-ads": "0.0.0",
|
|
106
107
|
"@ainyc/canonry-integration-wordpress": "0.0.0",
|
|
107
|
-
"@ainyc/canonry-integration-google-places": "0.0.0",
|
|
108
108
|
"@ainyc/canonry-provider-claude": "0.0.0",
|
|
109
|
-
"@ainyc/canonry-provider-cdp": "0.0.0",
|
|
110
109
|
"@ainyc/canonry-provider-gemini": "0.0.0",
|
|
111
|
-
"@ainyc/canonry-provider-muse": "0.0.0",
|
|
112
110
|
"@ainyc/canonry-provider-local": "0.0.0",
|
|
111
|
+
"@ainyc/canonry-provider-muse": "0.0.0",
|
|
112
|
+
"@ainyc/canonry-provider-openai": "0.0.0",
|
|
113
113
|
"@ainyc/canonry-provider-perplexity": "0.0.0",
|
|
114
114
|
"@ainyc/canonry-integration-typesafe": "0.0.0",
|
|
115
|
-
"@ainyc/canonry-provider-
|
|
115
|
+
"@ainyc/canonry-provider-cdp": "0.0.0"
|
|
116
116
|
},
|
|
117
117
|
"scripts": {
|
|
118
118
|
"build": "pnpm run build:cli && pnpm run build:web",
|