@ainyc/canonry 4.64.1 → 4.68.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 +1 -0
- package/assets/agent-workspace/skills/canonry/references/canonry-cli.md +38 -2
- package/assets/assets/{BacklinksPage-B9oyoljV.js → BacklinksPage-B9Q2r9zM.js} +1 -1
- package/assets/assets/ChartPrimitives-D-YWOWK-.js +1 -0
- package/assets/assets/ProjectPage-BXgxWKyT.js +6 -0
- package/assets/assets/{RunRow-vHM36Fdi.js → RunRow-CJpjUaht.js} +1 -1
- package/assets/assets/{RunsPage-Cr58nTet.js → RunsPage-DVl_pgqe.js} +1 -1
- package/assets/assets/{SettingsPage-BuiP8ZOv.js → SettingsPage-CAiVL2mo.js} +1 -1
- package/assets/assets/{TrafficPage-bwOxChyo.js → TrafficPage-B8dnHFqk.js} +1 -1
- package/assets/assets/{TrafficSourceDetailPage-B0uY6VIB.js → TrafficSourceDetailPage-37s8p8eZ.js} +1 -1
- package/assets/assets/{extract-error-message-CWdzuNp4.js → extract-error-message-DwqbPRoa.js} +1 -1
- package/assets/assets/index-BquJzH0t.css +1 -0
- package/assets/assets/{index-DiN_mzYU.js → index-DFo2OL9c.js} +79 -79
- package/assets/assets/{server-traffic-D3aICbxr.js → server-traffic-CMFP8-x2.js} +1 -1
- package/assets/assets/{trash-2-CVKno2W2.js → trash-2-C4sYVIa6.js} +1 -1
- package/assets/index.html +2 -2
- package/dist/{chunk-34PATQZM.js → chunk-D75O5A27.js} +36 -1
- package/dist/{chunk-MDNDIBUM.js → chunk-GZYLAE6M.js} +57 -19
- package/dist/{chunk-KHN3XMOR.js → chunk-Y24OE7R3.js} +64 -26
- package/dist/{chunk-64IDABSF.js → chunk-YYFBMDLC.js} +22 -31
- package/dist/cli.js +433 -219
- package/dist/index.js +4 -4
- package/dist/{intelligence-service-SMU5JVVD.js → intelligence-service-5V2JWQ6K.js} +2 -2
- package/dist/mcp.js +2 -2
- package/package.json +8 -7
- package/assets/assets/ChartPrimitives-CvfM24iC.js +0 -1
- package/assets/assets/ProjectPage-DELbOAlm.js +0 -6
- package/assets/assets/index-yMJe1bJR.css +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
import{c as d,j as a,
|
|
1
|
+
import{c as d,j as a,bU as S,bO as l,bV as v,av as m,l as t,bW as y,bP as i,bX as T,bY as h,bZ as p,b_ as b}from"./index-DFo2OL9c.js";import{u as s,r as C,n as c,o as u}from"./vendor-tanstack-Dq7p98wZ.js";const g=[["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"}]],B=d("refresh-cw",g);function M(e){switch(e){case i.connected:return"positive";case i.paused:return"caution";case i.error:return"negative";case i.archived:return"neutral"}}function w(e){const r={};return e.kind&&e.kind!=="all"&&(r.kind=e.kind),e.sourceId&&(r.sourceId=e.sourceId),e.sinceMinutes!==void 0&&(r.since=new Date(Date.now()-e.sinceMinutes*6e4).toISOString()),e.limit!==void 0&&(r.limit=String(e.limit)),r}function o(e){e.invalidateQueries({predicate:r=>{const n=r.queryKey[0];return typeof n?._id=="string"&&n._id.startsWith("getApiV1ProjectsByNameTraffic")}})}function V(e){return s({...S({client:t,path:{name:e??""}}),enabled:!!e,staleTime:a})}function k(e){return s({...b({client:t,path:{name:e??""}}),enabled:!!e,staleTime:a})}function F(e,r){return s({...l({client:t,path:{name:e??"",id:r??""}}),enabled:!!(e&&r),staleTime:a})}function A(e,r){const n=C.useMemo(()=>w(r),[r.kind,r.sourceId,r.sinceMinutes,r.limit]);return s({...v({client:t,path:{name:e??""},query:n}),enabled:!!e,staleTime:a})}function E(e){const r=c();return u({mutationFn:n=>{if(!e)throw new Error("Project is required to connect a Cloud Run source");return p(e,n)},onSuccess:()=>{e&&o(r)}})}function I(e){const r=c();return u({mutationFn:n=>{if(!e)throw new Error("Project is required to connect a WordPress source");return T(e,n)},onSuccess:()=>{e&&o(r)}})}function Q(e){const r=c();return u({mutationFn:n=>{if(!e)throw new Error("Project is required to connect a Vercel source");return h(e,n)},onSuccess:()=>{e&&o(r)}})}function R(e,r){const n=c();return u({mutationFn:f=>{if(!e||!r)throw new Error("Project and sourceId are required to sync");return y(e,r,f??void 0)},onSuccess:()=>{e&&(o(n),n.invalidateQueries({queryKey:m({client:t})}))}})}export{B as R,I as a,Q as b,E as c,V as d,F as e,A as f,R as g,M as t,k as u};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{c}from"./index-
|
|
1
|
+
import{c}from"./index-DFo2OL9c.js";const a=[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["path",{d:"m9 12 2 2 4-4",key:"dzmm74"}]],h=c("circle-check",a);const e=[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["path",{d:"M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3",key:"1u773s"}],["path",{d:"M12 17h.01",key:"p32p05"}]],n=c("circle-question-mark",e);const o=[["path",{d:"M12 15V3",key:"m9g1x1"}],["path",{d:"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4",key:"ih7n3h"}],["path",{d:"m7 10 5 5 5-5",key:"brsn70"}]],s=c("download",o);const t=[["path",{d:"M10 11v6",key:"nco0om"}],["path",{d:"M14 11v6",key:"outv1u"}],["path",{d:"M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6",key:"miytrc"}],["path",{d:"M3 6h18",key:"d0wm0j"}],["path",{d:"M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2",key:"e791ji"}]],r=c("trash-2",t);export{h as C,s as D,r as T,n as a};
|
package/assets/index.html
CHANGED
|
@@ -12,12 +12,12 @@
|
|
|
12
12
|
<link rel="icon" type="image/png" sizes="32x32" href="./favicon-32.png" />
|
|
13
13
|
<link rel="apple-touch-icon" href="./apple-touch-icon.png" />
|
|
14
14
|
<title>Canonry</title>
|
|
15
|
-
<script type="module" crossorigin src="./assets/index-
|
|
15
|
+
<script type="module" crossorigin src="./assets/index-DFo2OL9c.js"></script>
|
|
16
16
|
<link rel="modulepreload" crossorigin href="./assets/vendor-tanstack-Dq7p98wZ.js">
|
|
17
17
|
<link rel="modulepreload" crossorigin href="./assets/vendor-radix-B57xfQbP.js">
|
|
18
18
|
<link rel="modulepreload" crossorigin href="./assets/vendor-recharts-ClRVR6aX.js">
|
|
19
19
|
<link rel="modulepreload" crossorigin href="./assets/vendor-markdown-DK7fbRNb.js">
|
|
20
|
-
<link rel="stylesheet" crossorigin href="./assets/index-
|
|
20
|
+
<link rel="stylesheet" crossorigin href="./assets/index-BquJzH0t.css">
|
|
21
21
|
</head>
|
|
22
22
|
<body>
|
|
23
23
|
<div id="root"></div>
|
|
@@ -1498,7 +1498,7 @@ var snapshotReportSchema = z12.object({
|
|
|
1498
1498
|
|
|
1499
1499
|
// ../contracts/src/schedule.ts
|
|
1500
1500
|
import { z as z13 } from "zod";
|
|
1501
|
-
var schedulableRunKindSchema = z13.enum(["answer-visibility", "traffic-sync", "gbp-sync", "data-refresh"]);
|
|
1501
|
+
var schedulableRunKindSchema = z13.enum(["answer-visibility", "traffic-sync", "gbp-sync", "data-refresh", "backlinks-sync"]);
|
|
1502
1502
|
var SchedulableRunKinds = schedulableRunKindSchema.enum;
|
|
1503
1503
|
var scheduleDtoSchema = z13.object({
|
|
1504
1504
|
id: z13.string(),
|
|
@@ -1534,8 +1534,42 @@ var scheduleUpsertRequestSchema = z13.object({
|
|
|
1534
1534
|
|
|
1535
1535
|
// ../contracts/src/analytics.ts
|
|
1536
1536
|
import { z as z14 } from "zod";
|
|
1537
|
+
var metricsWindowSchema = z14.enum(["7d", "30d", "90d", "all"]);
|
|
1538
|
+
var trendDirectionSchema = z14.enum(["improving", "declining", "stable"]);
|
|
1537
1539
|
var visibilityMetricModeSchema = z14.enum(["mentioned", "cited"]);
|
|
1538
1540
|
var VisibilityMetricModes = visibilityMetricModeSchema.enum;
|
|
1541
|
+
var providerMetricSchema = z14.object({
|
|
1542
|
+
citationRate: z14.number(),
|
|
1543
|
+
cited: z14.number().int(),
|
|
1544
|
+
total: z14.number().int(),
|
|
1545
|
+
mentionRate: z14.number(),
|
|
1546
|
+
mentionedCount: z14.number().int()
|
|
1547
|
+
});
|
|
1548
|
+
var timeBucketSchema = z14.object({
|
|
1549
|
+
startDate: z14.string(),
|
|
1550
|
+
endDate: z14.string(),
|
|
1551
|
+
citationRate: z14.number(),
|
|
1552
|
+
cited: z14.number().int(),
|
|
1553
|
+
total: z14.number().int(),
|
|
1554
|
+
queryCount: z14.number().int(),
|
|
1555
|
+
mentionRate: z14.number(),
|
|
1556
|
+
mentionedCount: z14.number().int(),
|
|
1557
|
+
byProvider: z14.record(z14.string(), providerMetricSchema)
|
|
1558
|
+
});
|
|
1559
|
+
var queryChangeEventSchema = z14.object({
|
|
1560
|
+
date: z14.string(),
|
|
1561
|
+
delta: z14.number().int(),
|
|
1562
|
+
label: z14.string()
|
|
1563
|
+
});
|
|
1564
|
+
var brandMetricsDtoSchema = z14.object({
|
|
1565
|
+
window: metricsWindowSchema,
|
|
1566
|
+
buckets: z14.array(timeBucketSchema),
|
|
1567
|
+
overall: providerMetricSchema,
|
|
1568
|
+
byProvider: z14.record(z14.string(), providerMetricSchema),
|
|
1569
|
+
trend: trendDirectionSchema,
|
|
1570
|
+
mentionTrend: trendDirectionSchema,
|
|
1571
|
+
queryChanges: z14.array(queryChangeEventSchema)
|
|
1572
|
+
});
|
|
1539
1573
|
function parseWindow(value) {
|
|
1540
1574
|
if (value === "7d" || value === "30d" || value === "90d" || value === "all") return value;
|
|
1541
1575
|
return "all";
|
|
@@ -4010,6 +4044,7 @@ export {
|
|
|
4010
4044
|
SchedulableRunKinds,
|
|
4011
4045
|
scheduleDtoSchema,
|
|
4012
4046
|
scheduleUpsertRequestSchema,
|
|
4047
|
+
brandMetricsDtoSchema,
|
|
4013
4048
|
parseWindow,
|
|
4014
4049
|
windowCutoff,
|
|
4015
4050
|
categorizeSource,
|
|
@@ -5,10 +5,11 @@ import {
|
|
|
5
5
|
canonryMcpTools,
|
|
6
6
|
configExists,
|
|
7
7
|
getConfigPath,
|
|
8
|
+
isMachineFormat,
|
|
8
9
|
loadConfig,
|
|
9
10
|
loadConfigRaw,
|
|
10
11
|
saveConfigPatch
|
|
11
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-YYFBMDLC.js";
|
|
12
13
|
import {
|
|
13
14
|
CC_CACHE_DIR,
|
|
14
15
|
DUCKDB_SPEC,
|
|
@@ -76,6 +77,7 @@ import {
|
|
|
76
77
|
loadDuckdb,
|
|
77
78
|
markSessionFailed,
|
|
78
79
|
migrate,
|
|
80
|
+
nextRunFromCron,
|
|
79
81
|
notifications,
|
|
80
82
|
parseJsonColumn,
|
|
81
83
|
probeLatestRelease,
|
|
@@ -93,7 +95,7 @@ import {
|
|
|
93
95
|
runs,
|
|
94
96
|
schedules,
|
|
95
97
|
usageCounters
|
|
96
|
-
} from "./chunk-
|
|
98
|
+
} from "./chunk-Y24OE7R3.js";
|
|
97
99
|
import {
|
|
98
100
|
AGENT_MEMORY_VALUE_MAX_BYTES,
|
|
99
101
|
AGENT_PROVIDER_IDS,
|
|
@@ -141,7 +143,7 @@ import {
|
|
|
141
143
|
skillsClientSchema,
|
|
142
144
|
validationError,
|
|
143
145
|
withRetry
|
|
144
|
-
} from "./chunk-
|
|
146
|
+
} from "./chunk-D75O5A27.js";
|
|
145
147
|
|
|
146
148
|
// src/telemetry.ts
|
|
147
149
|
import crypto from "crypto";
|
|
@@ -433,7 +435,7 @@ import crypto17 from "crypto";
|
|
|
433
435
|
import fs8 from "fs";
|
|
434
436
|
import path9 from "path";
|
|
435
437
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
436
|
-
import { eq as eq17 } from "drizzle-orm";
|
|
438
|
+
import { and as and13, eq as eq17 } from "drizzle-orm";
|
|
437
439
|
import Fastify from "fastify";
|
|
438
440
|
import os5 from "os";
|
|
439
441
|
|
|
@@ -5296,7 +5298,7 @@ async function backfillAnswerVisibilityCommand(opts) {
|
|
|
5296
5298
|
result.dryRun = true;
|
|
5297
5299
|
result.wouldUpdate = wouldUpdate;
|
|
5298
5300
|
}
|
|
5299
|
-
if (opts?.format
|
|
5301
|
+
if (isMachineFormat(opts?.format)) {
|
|
5300
5302
|
console.log(JSON.stringify(result, null, 2));
|
|
5301
5303
|
return;
|
|
5302
5304
|
}
|
|
@@ -5366,7 +5368,7 @@ async function backfillNormalizedPathsCommand(opts) {
|
|
|
5366
5368
|
updated: 0,
|
|
5367
5369
|
unchanged: 0
|
|
5368
5370
|
};
|
|
5369
|
-
if (opts?.format
|
|
5371
|
+
if (isMachineFormat(opts?.format)) {
|
|
5370
5372
|
console.log(JSON.stringify(result2, null, 2));
|
|
5371
5373
|
return;
|
|
5372
5374
|
}
|
|
@@ -5382,7 +5384,7 @@ async function backfillNormalizedPathsCommand(opts) {
|
|
|
5382
5384
|
updated,
|
|
5383
5385
|
unchanged
|
|
5384
5386
|
};
|
|
5385
|
-
if (opts?.format
|
|
5387
|
+
if (isMachineFormat(opts?.format)) {
|
|
5386
5388
|
console.log(JSON.stringify(result, null, 2));
|
|
5387
5389
|
return;
|
|
5388
5390
|
}
|
|
@@ -5438,7 +5440,7 @@ async function backfillAiReferralPathsCommand(opts) {
|
|
|
5438
5440
|
updated: 0,
|
|
5439
5441
|
unchanged: 0
|
|
5440
5442
|
};
|
|
5441
|
-
if (opts?.format
|
|
5443
|
+
if (isMachineFormat(opts?.format)) {
|
|
5442
5444
|
console.log(JSON.stringify(result2, null, 2));
|
|
5443
5445
|
return;
|
|
5444
5446
|
}
|
|
@@ -5454,7 +5456,7 @@ async function backfillAiReferralPathsCommand(opts) {
|
|
|
5454
5456
|
updated,
|
|
5455
5457
|
unchanged
|
|
5456
5458
|
};
|
|
5457
|
-
if (opts?.format
|
|
5459
|
+
if (isMachineFormat(opts?.format)) {
|
|
5458
5460
|
console.log(JSON.stringify(result, null, 2));
|
|
5459
5461
|
return;
|
|
5460
5462
|
}
|
|
@@ -5579,7 +5581,7 @@ async function backfillAnswerMentionsCommand(opts) {
|
|
|
5579
5581
|
result.dryRun = true;
|
|
5580
5582
|
result.wouldUpdate = wouldUpdate;
|
|
5581
5583
|
}
|
|
5582
|
-
if (opts?.format
|
|
5584
|
+
if (isMachineFormat(opts?.format)) {
|
|
5583
5585
|
console.log(JSON.stringify(result, null, 2));
|
|
5584
5586
|
return;
|
|
5585
5587
|
}
|
|
@@ -5616,12 +5618,12 @@ function readStoredGroundingSources(rawResponse) {
|
|
|
5616
5618
|
return result;
|
|
5617
5619
|
}
|
|
5618
5620
|
async function backfillInsightsCommand(project, opts) {
|
|
5619
|
-
const { IntelligenceService: IntelligenceService2 } = await import("./intelligence-service-
|
|
5621
|
+
const { IntelligenceService: IntelligenceService2 } = await import("./intelligence-service-5V2JWQ6K.js");
|
|
5620
5622
|
const config = loadConfig();
|
|
5621
5623
|
const db = createClient(config.database);
|
|
5622
5624
|
migrate(db);
|
|
5623
5625
|
const service = new IntelligenceService2(db);
|
|
5624
|
-
const isJson = opts?.format
|
|
5626
|
+
const isJson = isMachineFormat(opts?.format);
|
|
5625
5627
|
const isDryRun = opts?.dryRun === true;
|
|
5626
5628
|
if (!isJson) {
|
|
5627
5629
|
const scope = opts?.since ? ` (since ${opts.since})` : "";
|
|
@@ -5779,7 +5781,7 @@ async function backfillSnapshotAttributionCommand(opts) {
|
|
|
5779
5781
|
if (!project) {
|
|
5780
5782
|
throw new Error(`Project "${opts.project}" not found`);
|
|
5781
5783
|
}
|
|
5782
|
-
const isJson = opts.format
|
|
5784
|
+
const isJson = isMachineFormat(opts.format);
|
|
5783
5785
|
const isDryRun = opts.dryRun === true;
|
|
5784
5786
|
if (!isJson) {
|
|
5785
5787
|
const mode = isDryRun ? " [DRY RUN \u2014 no writes]" : "";
|
|
@@ -5958,7 +5960,7 @@ async function backfillTrafficClassificationCommand(opts) {
|
|
|
5958
5960
|
migrate(db);
|
|
5959
5961
|
const projectFilter = opts?.project?.trim();
|
|
5960
5962
|
const isDryRun = opts?.dryRun === true;
|
|
5961
|
-
const isJson = opts?.format
|
|
5963
|
+
const isJson = isMachineFormat(opts?.format);
|
|
5962
5964
|
const scopedProjects = projectFilter ? db.select().from(projects).where(eq10(projects.name, projectFilter)).all() : db.select().from(projects).all();
|
|
5963
5965
|
if (scopedProjects.length === 0) {
|
|
5964
5966
|
if (projectFilter && !isJson) {
|
|
@@ -6395,7 +6397,7 @@ async function installSkills(opts = {}) {
|
|
|
6395
6397
|
}
|
|
6396
6398
|
async function listSkills(opts = {}) {
|
|
6397
6399
|
const skills = getBundledSkills();
|
|
6398
|
-
if (opts.format
|
|
6400
|
+
if (isMachineFormat(opts.format)) {
|
|
6399
6401
|
console.log(JSON.stringify({
|
|
6400
6402
|
skills: skills.map((s) => ({
|
|
6401
6403
|
name: s.name,
|
|
@@ -6416,7 +6418,7 @@ async function listSkills(opts = {}) {
|
|
|
6416
6418
|
}
|
|
6417
6419
|
}
|
|
6418
6420
|
function emitInstallSummary(summary, format) {
|
|
6419
|
-
if (format
|
|
6421
|
+
if (isMachineFormat(format)) {
|
|
6420
6422
|
console.log(JSON.stringify(summary, null, 2));
|
|
6421
6423
|
return;
|
|
6422
6424
|
}
|
|
@@ -6601,7 +6603,7 @@ var Scheduler = class {
|
|
|
6601
6603
|
});
|
|
6602
6604
|
this.tasks.set(taskKey(projectId, kind), task);
|
|
6603
6605
|
this.db.update(schedules).set({
|
|
6604
|
-
nextRunAt:
|
|
6606
|
+
nextRunAt: nextRunFromCron(cronExpr, timezone),
|
|
6605
6607
|
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
6606
6608
|
}).where(eq11(schedules.id, scheduleId)).run();
|
|
6607
6609
|
const label = schedule.preset ?? cronExpr;
|
|
@@ -6616,8 +6618,7 @@ var Scheduler = class {
|
|
|
6616
6618
|
this.remove(projectId, kind);
|
|
6617
6619
|
return;
|
|
6618
6620
|
}
|
|
6619
|
-
const
|
|
6620
|
-
const nextRunAt = task?.getNextRun()?.toISOString() ?? null;
|
|
6621
|
+
const nextRunAt = nextRunFromCron(currentSchedule.cronExpr, currentSchedule.timezone);
|
|
6621
6622
|
const project = this.db.select().from(projects).where(eq11(projects.id, projectId)).get();
|
|
6622
6623
|
if (!project) {
|
|
6623
6624
|
log11.error("project.not-found", { projectId, kind, msg: "skipping scheduled run" });
|
|
@@ -6680,6 +6681,20 @@ var Scheduler = class {
|
|
|
6680
6681
|
this.callbacks.onDataRefreshRequested(project.name);
|
|
6681
6682
|
return;
|
|
6682
6683
|
}
|
|
6684
|
+
if (kind === SchedulableRunKinds["backlinks-sync"]) {
|
|
6685
|
+
if (!this.callbacks.onBacklinksSyncRequested) {
|
|
6686
|
+
log11.warn("backlinks-sync.no-callback", { scheduleId, projectId, msg: "host did not register onBacklinksSyncRequested" });
|
|
6687
|
+
return;
|
|
6688
|
+
}
|
|
6689
|
+
this.db.update(schedules).set({
|
|
6690
|
+
lastRunAt: now,
|
|
6691
|
+
nextRunAt,
|
|
6692
|
+
updatedAt: now
|
|
6693
|
+
}).where(eq11(schedules.id, currentSchedule.id)).run();
|
|
6694
|
+
log11.info("backlinks-sync.triggered", { projectName: project.name });
|
|
6695
|
+
this.callbacks.onBacklinksSyncRequested(project.name);
|
|
6696
|
+
return;
|
|
6697
|
+
}
|
|
6683
6698
|
const projectLocations = project.locations;
|
|
6684
6699
|
let resolvedLocation;
|
|
6685
6700
|
if (project.defaultLocation) {
|
|
@@ -9451,6 +9466,29 @@ async function createServer(opts) {
|
|
|
9451
9466
|
},
|
|
9452
9467
|
onDataRefreshRequested: (projectName) => {
|
|
9453
9468
|
void refreshAllIntegrations(aeroClient, projectName);
|
|
9469
|
+
},
|
|
9470
|
+
onBacklinksSyncRequested: (projectName) => {
|
|
9471
|
+
void (async () => {
|
|
9472
|
+
const probed = await probeLatestRelease().catch((err) => {
|
|
9473
|
+
app.log.warn({ projectName, err }, "Scheduled backlinks sync: latest-release probe failed");
|
|
9474
|
+
return null;
|
|
9475
|
+
});
|
|
9476
|
+
if (!probed) return;
|
|
9477
|
+
const alreadySynced = opts.db.select().from(ccReleaseSyncs).where(and13(
|
|
9478
|
+
eq17(ccReleaseSyncs.release, probed.release),
|
|
9479
|
+
eq17(ccReleaseSyncs.status, CcReleaseSyncStatuses.ready)
|
|
9480
|
+
)).limit(1).get();
|
|
9481
|
+
if (alreadySynced) {
|
|
9482
|
+
app.log.info({ projectName, release: probed.release }, "Scheduled backlinks sync: already up to date, skipping");
|
|
9483
|
+
return;
|
|
9484
|
+
}
|
|
9485
|
+
aeroClient.backlinksTriggerSync(probed.release).catch((err) => {
|
|
9486
|
+
app.log.error(
|
|
9487
|
+
{ projectName, release: probed.release, err: err instanceof Error ? err.message : String(err) },
|
|
9488
|
+
"Scheduled backlinks sync failed"
|
|
9489
|
+
);
|
|
9490
|
+
});
|
|
9491
|
+
})();
|
|
9454
9492
|
}
|
|
9455
9493
|
});
|
|
9456
9494
|
const providerSummary = API_ADAPTERS.map((adapter) => ({
|
|
@@ -51,6 +51,7 @@ import {
|
|
|
51
51
|
bingUrlInspectionDtoSchema,
|
|
52
52
|
brandKeyFromText,
|
|
53
53
|
brandLabelFromDomain,
|
|
54
|
+
brandMetricsDtoSchema,
|
|
54
55
|
categorizeSource,
|
|
55
56
|
categorizeSourceWithCompetitors,
|
|
56
57
|
categoryLabel,
|
|
@@ -207,7 +208,7 @@ import {
|
|
|
207
208
|
wordpressSchemaDeployResultDtoSchema,
|
|
208
209
|
wordpressSchemaStatusResultDtoSchema,
|
|
209
210
|
wordpressStatusDtoSchema
|
|
210
|
-
} from "./chunk-
|
|
211
|
+
} from "./chunk-D75O5A27.js";
|
|
211
212
|
|
|
212
213
|
// src/intelligence-service.ts
|
|
213
214
|
import { eq as eq30, desc as desc15, asc as asc3, and as and23, ne as ne5, or as or5, inArray as inArray11, gte as gte6, lte as lte3 } from "drizzle-orm";
|
|
@@ -6131,6 +6132,7 @@ import crypto10 from "crypto";
|
|
|
6131
6132
|
import { and as and3, eq as eq8 } from "drizzle-orm";
|
|
6132
6133
|
|
|
6133
6134
|
// ../api-routes/src/schedule-utils.ts
|
|
6135
|
+
import { CronExpressionParser } from "cron-parser";
|
|
6134
6136
|
var DAY_MAP = {
|
|
6135
6137
|
sun: "0",
|
|
6136
6138
|
mon: "1",
|
|
@@ -6217,6 +6219,17 @@ function isValidTimezone(tz) {
|
|
|
6217
6219
|
return false;
|
|
6218
6220
|
}
|
|
6219
6221
|
}
|
|
6222
|
+
function nextRunFromCron(cronExpr, timezone, from = /* @__PURE__ */ new Date()) {
|
|
6223
|
+
try {
|
|
6224
|
+
const interval = CronExpressionParser.parse(cronExpr, {
|
|
6225
|
+
currentDate: from,
|
|
6226
|
+
tz: timezone
|
|
6227
|
+
});
|
|
6228
|
+
return interval.next().toDate().toISOString();
|
|
6229
|
+
} catch {
|
|
6230
|
+
return null;
|
|
6231
|
+
}
|
|
6232
|
+
}
|
|
6220
6233
|
|
|
6221
6234
|
// ../api-routes/src/webhooks.ts
|
|
6222
6235
|
import crypto9 from "crypto";
|
|
@@ -7243,6 +7256,10 @@ function computeBuckets(snapshots, projectRuns, bucketDays, queryCreatedAt) {
|
|
|
7243
7256
|
}
|
|
7244
7257
|
const metric = computeProviderMetric(usable);
|
|
7245
7258
|
const queryCount = new Set(usable.map((s) => s.queryId)).size;
|
|
7259
|
+
const byProvider = {};
|
|
7260
|
+
for (const provider of new Set(usable.map((s) => s.provider))) {
|
|
7261
|
+
byProvider[provider] = computeProviderMetric(usable.filter((s) => s.provider === provider));
|
|
7262
|
+
}
|
|
7246
7263
|
buckets.push({
|
|
7247
7264
|
startDate: startISO,
|
|
7248
7265
|
endDate: endISO,
|
|
@@ -7251,7 +7268,8 @@ function computeBuckets(snapshots, projectRuns, bucketDays, queryCreatedAt) {
|
|
|
7251
7268
|
total: metric.total,
|
|
7252
7269
|
queryCount,
|
|
7253
7270
|
mentionRate: metric.mentionRate,
|
|
7254
|
-
mentionedCount: metric.mentionedCount
|
|
7271
|
+
mentionedCount: metric.mentionedCount,
|
|
7272
|
+
byProvider
|
|
7255
7273
|
});
|
|
7256
7274
|
}
|
|
7257
7275
|
start = end;
|
|
@@ -12012,6 +12030,7 @@ async function compositeRoutes(app) {
|
|
|
12012
12030
|
const attentionItems = buildAttentionItems(insightRows, allRuns);
|
|
12013
12031
|
const sparklineRuns = visibilityRuns.slice(0, DEFAULT_RUN_HISTORY_LIMIT).map((r) => ({ id: r.id, createdAt: r.createdAt, status: r.status }));
|
|
12014
12032
|
const runHistory = buildRunHistory(sparklineRuns, snapshotsByRun);
|
|
12033
|
+
scores.visibility.trend = runHistory.map((p) => p.citationRate);
|
|
12015
12034
|
const suggestedQueries = buildSuggestedQueriesFromGsc(
|
|
12016
12035
|
app,
|
|
12017
12036
|
project.id,
|
|
@@ -12544,6 +12563,7 @@ var SCHEMA_TABLE = {
|
|
|
12544
12563
|
BingSitesResponseDto: bingSitesResponseDtoSchema,
|
|
12545
12564
|
BingStatusDto: bingStatusDtoSchema,
|
|
12546
12565
|
BingUrlInspectionDto: bingUrlInspectionDtoSchema,
|
|
12566
|
+
BrandMetricsDto: brandMetricsDtoSchema,
|
|
12547
12567
|
CcAvailableRelease: ccAvailableReleaseSchema,
|
|
12548
12568
|
CcCachedRelease: ccCachedReleaseSchema,
|
|
12549
12569
|
CcReleaseSyncDto: ccReleaseSyncDtoSchema,
|
|
@@ -12595,6 +12615,7 @@ var SCHEMA_TABLE = {
|
|
|
12595
12615
|
QueryDto: queryDtoSchema,
|
|
12596
12616
|
RunDetailDto: runDetailDtoSchema,
|
|
12597
12617
|
RunDto: runDtoSchema,
|
|
12618
|
+
SchedulableRunKind: schedulableRunKindSchema,
|
|
12598
12619
|
ScheduleDto: scheduleDtoSchema,
|
|
12599
12620
|
SettingsDto: settingsDtoSchema,
|
|
12600
12621
|
SnapshotDiffResponse: snapshotDiffResponseSchema,
|
|
@@ -12630,11 +12651,20 @@ var SCHEMA_TABLE = {
|
|
|
12630
12651
|
})
|
|
12631
12652
|
})
|
|
12632
12653
|
};
|
|
12654
|
+
var SHARED_ENUM_REFS = [
|
|
12655
|
+
{ schema: "ScheduleDto", property: "kind", component: "SchedulableRunKind" }
|
|
12656
|
+
];
|
|
12633
12657
|
function buildComponentSchemas() {
|
|
12634
12658
|
const out = {};
|
|
12635
12659
|
for (const [name, schema] of Object.entries(SCHEMA_TABLE)) {
|
|
12636
12660
|
out[name] = z.toJSONSchema(schema, { target: "openapi-3.0" });
|
|
12637
12661
|
}
|
|
12662
|
+
for (const { schema, property, component } of SHARED_ENUM_REFS) {
|
|
12663
|
+
const properties = out[schema]?.properties;
|
|
12664
|
+
if (properties && properties[property]) {
|
|
12665
|
+
properties[property] = { $ref: `#/components/schemas/${component}` };
|
|
12666
|
+
}
|
|
12667
|
+
}
|
|
12638
12668
|
return out;
|
|
12639
12669
|
}
|
|
12640
12670
|
function jsonResponse(description, schemaName) {
|
|
@@ -12680,7 +12710,6 @@ var integerSchema = { type: "integer" };
|
|
|
12680
12710
|
var objectSchema = { type: "object", additionalProperties: true };
|
|
12681
12711
|
var stringArraySchema = { type: "array", items: stringSchema };
|
|
12682
12712
|
var googleConnectionTypeSchema = { type: "string", enum: ["gsc", "ga4", "gbp"] };
|
|
12683
|
-
var scheduleKindEnum = Object.values(SchedulableRunKinds);
|
|
12684
12713
|
var locationSchema = {
|
|
12685
12714
|
type: "object",
|
|
12686
12715
|
required: ["label", "city", "region", "country"],
|
|
@@ -12770,7 +12799,7 @@ var scheduleKindQueryParameter = {
|
|
|
12770
12799
|
name: "kind",
|
|
12771
12800
|
in: "query",
|
|
12772
12801
|
description: 'Schedulable run kind. Defaults to "answer-visibility" for backward compatibility.',
|
|
12773
|
-
schema: {
|
|
12802
|
+
schema: { $ref: "#/components/schemas/SchedulableRunKind" }
|
|
12774
12803
|
};
|
|
12775
12804
|
var runsListKindQueryParameter = {
|
|
12776
12805
|
name: "kind",
|
|
@@ -13516,8 +13545,7 @@ var routeCatalog = [
|
|
|
13516
13545
|
tags: ["analytics"],
|
|
13517
13546
|
parameters: [nameParameter, analyticsWindowParameter],
|
|
13518
13547
|
responses: {
|
|
13519
|
-
|
|
13520
|
-
200: rawJsonResponse("Citation metrics returned.", looseObjectSchema),
|
|
13548
|
+
200: jsonResponse("Citation metrics returned.", "BrandMetricsDto"),
|
|
13521
13549
|
404: errorResponse("Project not found.")
|
|
13522
13550
|
}
|
|
13523
13551
|
},
|
|
@@ -13731,7 +13759,7 @@ var routeCatalog = [
|
|
|
13731
13759
|
schema: {
|
|
13732
13760
|
type: "object",
|
|
13733
13761
|
properties: {
|
|
13734
|
-
kind: {
|
|
13762
|
+
kind: { $ref: "#/components/schemas/SchedulableRunKind" },
|
|
13735
13763
|
preset: stringSchema,
|
|
13736
13764
|
cron: stringSchema,
|
|
13737
13765
|
timezone: stringSchema,
|
|
@@ -16583,6 +16611,9 @@ async function scheduleRoutes(app, opts) {
|
|
|
16583
16611
|
} else if (sourceId) {
|
|
16584
16612
|
throw validationError(`"sourceId" is only valid when kind is "traffic-sync"`);
|
|
16585
16613
|
}
|
|
16614
|
+
if (kind === SchedulableRunKinds["backlinks-sync"] && providers && providers.length > 0) {
|
|
16615
|
+
throw validationError('"providers" is not valid for kind "backlinks-sync"');
|
|
16616
|
+
}
|
|
16586
16617
|
const validNames = opts.validProviderNames ?? [];
|
|
16587
16618
|
if (validNames.length && providers?.length) {
|
|
16588
16619
|
const invalid = providers.filter((p) => !validNames.includes(p));
|
|
@@ -22781,7 +22812,8 @@ var PLUGIN_DIR = path2.join(os2.homedir(), ".canonry", "plugins");
|
|
|
22781
22812
|
var PLUGIN_PKG_JSON = path2.join(PLUGIN_DIR, "package.json");
|
|
22782
22813
|
var DUCKDB_SPEC = process.env.CANONRY_DUCKDB_SPEC ?? "@duckdb/node-api@1.4.4-r.3";
|
|
22783
22814
|
var CC_CACHE_DIR = process.env.CANONRY_CC_CACHE_DIR ?? path2.join(os2.homedir(), ".canonry", "cache", "commoncrawl");
|
|
22784
|
-
var
|
|
22815
|
+
var CC_MONTH = "(?:jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)";
|
|
22816
|
+
var RELEASE_ID_REGEX = new RegExp(`^cc-main-(\\d{4})-(${CC_MONTH}-${CC_MONTH}-${CC_MONTH})$`);
|
|
22785
22817
|
function ccReleasePaths(release) {
|
|
22786
22818
|
const base = `${CC_BASE_URL}/${release}/domain`;
|
|
22787
22819
|
const vertexFilename = `${release}-domain-vertices.txt.gz`;
|
|
@@ -22806,23 +22838,28 @@ function forwardDomain(revDomain) {
|
|
|
22806
22838
|
function isValidReleaseId(id) {
|
|
22807
22839
|
return RELEASE_ID_REGEX.test(id);
|
|
22808
22840
|
}
|
|
22809
|
-
function formatReleaseId(year,
|
|
22810
|
-
return `cc-main-${year}-${
|
|
22841
|
+
function formatReleaseId(year, window) {
|
|
22842
|
+
return `cc-main-${year}-${window}`;
|
|
22811
22843
|
}
|
|
22812
22844
|
|
|
22813
22845
|
// ../integration-commoncrawl/src/release-discovery.ts
|
|
22814
|
-
var
|
|
22815
|
-
|
|
22816
|
-
|
|
22817
|
-
|
|
22818
|
-
|
|
22819
|
-
|
|
22820
|
-
|
|
22821
|
-
|
|
22846
|
+
var MONTHS = ["jan", "feb", "mar", "apr", "may", "jun", "jul", "aug", "sep", "oct", "nov", "dec"];
|
|
22847
|
+
function windowSlug(firstMonthIndex) {
|
|
22848
|
+
const a = MONTHS[firstMonthIndex % 12];
|
|
22849
|
+
const b = MONTHS[(firstMonthIndex + 1) % 12];
|
|
22850
|
+
const c = MONTHS[(firstMonthIndex + 2) % 12];
|
|
22851
|
+
return `${a}-${b}-${c}`;
|
|
22852
|
+
}
|
|
22853
|
+
function probeCandidates(now, maxMonthsBack) {
|
|
22854
|
+
let year = now.getUTCFullYear();
|
|
22855
|
+
let month = now.getUTCMonth();
|
|
22822
22856
|
const out = [];
|
|
22823
|
-
for (let
|
|
22824
|
-
|
|
22825
|
-
|
|
22857
|
+
for (let step = 0; step <= maxMonthsBack; step++) {
|
|
22858
|
+
out.push({ year, window: windowSlug(month) });
|
|
22859
|
+
month -= 1;
|
|
22860
|
+
if (month < 0) {
|
|
22861
|
+
month = 11;
|
|
22862
|
+
year -= 1;
|
|
22826
22863
|
}
|
|
22827
22864
|
}
|
|
22828
22865
|
return out;
|
|
@@ -22845,11 +22882,11 @@ async function probeRelease(release, fetchImpl = fetch) {
|
|
|
22845
22882
|
}
|
|
22846
22883
|
async function probeLatestRelease(opts = {}) {
|
|
22847
22884
|
const now = opts.now ?? /* @__PURE__ */ new Date();
|
|
22848
|
-
const maxBack = opts.
|
|
22885
|
+
const maxBack = opts.maxMonthsBack ?? 14;
|
|
22849
22886
|
const fetchImpl = opts.fetchImpl ?? fetch;
|
|
22850
22887
|
const candidates = probeCandidates(now, maxBack);
|
|
22851
|
-
for (const { year,
|
|
22852
|
-
const release = formatReleaseId(year,
|
|
22888
|
+
for (const { year, window } of candidates) {
|
|
22889
|
+
const release = formatReleaseId(year, window);
|
|
22853
22890
|
const result = await probeRelease(release, fetchImpl);
|
|
22854
22891
|
if (result) return result;
|
|
22855
22892
|
}
|
|
@@ -23312,7 +23349,7 @@ async function backlinksRoutes(app, opts) {
|
|
|
23312
23349
|
if (!release) {
|
|
23313
23350
|
if (!opts.discoverLatestRelease) {
|
|
23314
23351
|
throw validationError(
|
|
23315
|
-
"No `release` provided and auto-discovery is unavailable on this deployment. Pass an explicit release id (e.g., cc-main-2026-
|
|
23352
|
+
"No `release` provided and auto-discovery is unavailable on this deployment. Pass an explicit release id (e.g., cc-main-2026-mar-apr-may)."
|
|
23316
23353
|
);
|
|
23317
23354
|
}
|
|
23318
23355
|
const discovered = await opts.discoverLatestRelease();
|
|
@@ -23324,7 +23361,7 @@ async function backlinksRoutes(app, opts) {
|
|
|
23324
23361
|
release = discovered.release;
|
|
23325
23362
|
}
|
|
23326
23363
|
if (!isValidReleaseId(release)) {
|
|
23327
|
-
throw validationError("Invalid release id. Expected form: cc-main-YYYY-
|
|
23364
|
+
throw validationError("Invalid release id. Expected form: cc-main-YYYY-<mon>-<mon>-<mon> (a rolling 3-month window, e.g. cc-main-2026-mar-apr-may).");
|
|
23328
23365
|
}
|
|
23329
23366
|
if (!opts.getBacklinksStatus || !opts.onReleaseSyncRequested) {
|
|
23330
23367
|
throw missingDependency(BACKLINKS_UNSUPPORTED_MESSAGE);
|
|
@@ -31959,6 +31996,7 @@ export {
|
|
|
31959
31996
|
getPlaceDetails,
|
|
31960
31997
|
hashPlaceDetails,
|
|
31961
31998
|
queueRunIfProjectIdle,
|
|
31999
|
+
nextRunFromCron,
|
|
31962
32000
|
resolveWebhookTarget,
|
|
31963
32001
|
deliverWebhook,
|
|
31964
32002
|
redactNotificationUrl,
|
|
@@ -22,7 +22,7 @@ import {
|
|
|
22
22
|
trafficConnectVercelRequestSchema,
|
|
23
23
|
trafficConnectWordpressRequestSchema,
|
|
24
24
|
trafficEventKindSchema
|
|
25
|
-
} from "./chunk-
|
|
25
|
+
} from "./chunk-D75O5A27.js";
|
|
26
26
|
|
|
27
27
|
// src/config.ts
|
|
28
28
|
import fs from "fs";
|
|
@@ -190,6 +190,9 @@ function configExists() {
|
|
|
190
190
|
}
|
|
191
191
|
|
|
192
192
|
// src/cli-error.ts
|
|
193
|
+
function isMachineFormat(format) {
|
|
194
|
+
return format === "json" || format === "jsonl";
|
|
195
|
+
}
|
|
193
196
|
var EXIT_USER_ERROR = 1;
|
|
194
197
|
var EXIT_SYSTEM_ERROR = 2;
|
|
195
198
|
var CliError = class extends Error {
|
|
@@ -221,36 +224,9 @@ function isEndpointMissing(err) {
|
|
|
221
224
|
return status === 404 || status === 405;
|
|
222
225
|
}
|
|
223
226
|
function printCliError(err, format) {
|
|
224
|
-
if (format
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
JSON.stringify(
|
|
228
|
-
{
|
|
229
|
-
error: {
|
|
230
|
-
code: err.code,
|
|
231
|
-
message: err.message,
|
|
232
|
-
...err.details ? { details: err.details } : {}
|
|
233
|
-
}
|
|
234
|
-
},
|
|
235
|
-
null,
|
|
236
|
-
2
|
|
237
|
-
)
|
|
238
|
-
);
|
|
239
|
-
return;
|
|
240
|
-
}
|
|
241
|
-
const message = err instanceof Error ? err.message : "An unexpected error occurred";
|
|
242
|
-
console.error(
|
|
243
|
-
JSON.stringify(
|
|
244
|
-
{
|
|
245
|
-
error: {
|
|
246
|
-
code: "CLI_ERROR",
|
|
247
|
-
message
|
|
248
|
-
}
|
|
249
|
-
},
|
|
250
|
-
null,
|
|
251
|
-
2
|
|
252
|
-
)
|
|
253
|
-
);
|
|
227
|
+
if (isMachineFormat(format)) {
|
|
228
|
+
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" } };
|
|
229
|
+
console.error(JSON.stringify(envelope, null, format === "jsonl" ? 0 : 2));
|
|
254
230
|
return;
|
|
255
231
|
}
|
|
256
232
|
if (err instanceof CliError && err.displayMessage) {
|
|
@@ -5155,6 +5131,20 @@ var canonryMcpTools = [
|
|
|
5155
5131
|
openApiOperations: ["GET /api/v1/projects/{name}/report"],
|
|
5156
5132
|
handler: (client2, input) => client2.getReport(input.project)
|
|
5157
5133
|
}),
|
|
5134
|
+
defineTool({
|
|
5135
|
+
name: "canonry_analytics_metrics",
|
|
5136
|
+
title: "Get citation & mention trend",
|
|
5137
|
+
description: "Citation and mention rates over time for a project, bucketed adaptively (daily \u2192 monthly by span) and probe-excluded. Returns overall + per-provider window aggregates AND a per-bucket `byProvider` breakdown so you can read how each engine's cited/mentioned rate moved run-over-run \u2014 the same data the dashboard's \"Citations & mentions over time\" chart plots. Includes trend direction (improving/declining/stable) for both signals and query-set-change annotations. Filter the range with `window` (7d/30d/90d/all).",
|
|
5138
|
+
access: "read",
|
|
5139
|
+
tier: "monitoring",
|
|
5140
|
+
inputSchema: z2.object({
|
|
5141
|
+
project: projectNameSchema,
|
|
5142
|
+
window: analyticsWindowSchema.optional().describe("Time range: 7d, 30d, 90d, or all (default all).")
|
|
5143
|
+
}),
|
|
5144
|
+
annotations: readAnnotations(),
|
|
5145
|
+
openApiOperations: ["GET /api/v1/projects/{name}/analytics/metrics"],
|
|
5146
|
+
handler: (client2, input) => client2.getAnalyticsMetrics(input.project, input.window)
|
|
5147
|
+
}),
|
|
5158
5148
|
defineTool({
|
|
5159
5149
|
name: "canonry_search",
|
|
5160
5150
|
title: "Search project (composite)",
|
|
@@ -6256,6 +6246,7 @@ export {
|
|
|
6256
6246
|
saveConfig,
|
|
6257
6247
|
saveConfigPatch,
|
|
6258
6248
|
configExists,
|
|
6249
|
+
isMachineFormat,
|
|
6259
6250
|
EXIT_USER_ERROR,
|
|
6260
6251
|
EXIT_SYSTEM_ERROR,
|
|
6261
6252
|
CliError,
|