@canonry/canonry 4.177.0 → 4.177.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 -1
- package/assets/agent-workspace/skills/canonry/SKILL.md +7 -0
- package/assets/agent-workspace/skills/canonry/references/server-side-traffic.md +40 -9
- package/dist/{chunk-F4ZZKGAC.js → chunk-6XUWDSLN.js} +10 -10
- package/dist/{chunk-X776E66Z.js → chunk-GJE334DA.js} +823 -613
- package/dist/{chunk-UXXXKDW4.js → chunk-PQT3ECM3.js} +5 -4
- package/dist/{chunk-WW7TDVLV.js → chunk-QRE3DAAU.js} +2 -2
- package/dist/{chunk-YWFNRDLK.js → chunk-XFAPF2YX.js} +4 -4
- package/dist/cli.js +9 -6
- package/dist/index.js +4 -4
- package/dist/{intelligence-service-QLLGPZOC.js → intelligence-service-C57RIB37.js} +2 -2
- package/dist/mcp.js +3 -3
- package/package.json +10 -10
package/README.md
CHANGED
|
@@ -18,7 +18,7 @@ Think PostHog, for AI search visibility. Canonry tracks what ChatGPT, Claude, Ge
|
|
|
18
18
|
|---|---|
|
|
19
19
|
| **Measure** | Track mentions and citations across Gemini, ChatGPT, Claude, Perplexity, and local models. Join them with GSC, GA4, Bing, server side traffic, Business Profile, and backlink data. |
|
|
20
20
|
| **Diagnose** | Crawl the site, score Page Health, inspect evidence, compare competitors, and explain regressions. |
|
|
21
|
-
| **Act** | Give your agent the context to make surgical on-site technical SEO changes and coordinate content, indexing, analytics, and paid media. |
|
|
21
|
+
| **Act** | Give your agent the context + skills to make surgical on-site technical SEO changes and coordinate content, indexing, analytics, and paid media. |
|
|
22
22
|
| **Operate** | Create automation workflows, schedule checks, sync data, send webhooks, and generate client-ready reports. |
|
|
23
23
|
|
|
24
24
|
### Built-in integrations and workflows
|
|
@@ -160,6 +160,13 @@ schedule interval. Use `cnry traffic events`, `cnry traffic sources`, and
|
|
|
160
160
|
`cnry traffic status` for every adapter. See
|
|
161
161
|
`references/server-side-traffic.md` for setup and smoke tests.
|
|
162
162
|
|
|
163
|
+
**WordPress safety:** incremental pulls are fixed `[since, until)` windows; a
|
|
164
|
+
new or idle source begins at the plugin's 365-day maximum retention horizon.
|
|
165
|
+
Canonry rejects an endpoint that returns events outside that window. Keep
|
|
166
|
+
existing WordPress rollups intact: generic replace-mode backfill is unavailable
|
|
167
|
+
until a retention-aware repair can prove coverage and declare any unrecoverable
|
|
168
|
+
span.
|
|
169
|
+
|
|
163
170
|
**Vercel gotcha:** a freshly connected Vercel source captures only going-forward traffic — `lastSyncedAt` is seeded to NOW to avoid the 30-day default window exceeding Vercel's ~14-day request-logs retention (which would otherwise throw on every first sync). Use `cnry traffic backfill <project> --source <id> --days N` for historical recovery. If an idle Vercel/Cloud Run source has been failing long enough that `lastSyncedAt` aged past retention, unstick it with `cnry traffic reset <project> --source <id> --advance-to-now`.
|
|
164
171
|
|
|
165
172
|
## Local AEO (Google Business Profile)
|
|
@@ -151,6 +151,38 @@ The plugin auto-prunes events older than the retention window (default
|
|
|
151
151
|
90 days) once per day via WP-Cron. Operators who want a different
|
|
152
152
|
window change it in `Settings → Canonry Traffic Logger`.
|
|
153
153
|
|
|
154
|
+
### WordPress incremental-window safety
|
|
155
|
+
|
|
156
|
+
Each incremental WordPress sync uses one fixed half-open `[since, until)`
|
|
157
|
+
window. A fresh source, or an idle source without an explicit
|
|
158
|
+
`--since-minutes`, starts with a 365-day horizon, matching the plugin's
|
|
159
|
+
maximum configurable retention. A site configured for less retention simply
|
|
160
|
+
returns its available tail. If the window needs more than one capped drain,
|
|
161
|
+
Canonry persists both its lower and upper bounds with the continuation cursor
|
|
162
|
+
and retries that exact interval until the plugin reports it is terminal. It
|
|
163
|
+
then advances the normal watermark. Every returned event is validated against
|
|
164
|
+
the requested interval; an older or custom extension that ignores `since` or
|
|
165
|
+
`until` fails closed before any rollup is written. Update that extension to a
|
|
166
|
+
bounded-window-capable Canonry traffic logger before syncing again.
|
|
167
|
+
|
|
168
|
+
Do not run generic replace-mode backfill for a WordPress source. The plugin
|
|
169
|
+
prunes retained events and cannot prove that it covers every bucket a replace
|
|
170
|
+
transaction would delete, even when no continuation is pending. Canonry
|
|
171
|
+
rejects that generic path universally. Keep existing rollups intact, use a
|
|
172
|
+
retention-aware repair, and explicitly declare any unrecoverable portion before
|
|
173
|
+
reporting a historical trend.
|
|
174
|
+
|
|
175
|
+
After upgrading from the former unbounded WordPress sync, a source with an old
|
|
176
|
+
continuation cursor is intentionally rejected rather than guessed at. Keep its
|
|
177
|
+
schedule paused, record the ambiguous historical span, then use the explicit
|
|
178
|
+
reset below to start fresh. Reset stops future replay; it does not repair past
|
|
179
|
+
rollups. Generic WordPress replace-mode backfill remains unavailable until a
|
|
180
|
+
retention-aware repair can establish coverage.
|
|
181
|
+
|
|
182
|
+
Reconnecting with a different WordPress `baseUrl` archives the old source and
|
|
183
|
+
creates a fresh one. Its existing rollups and any unrecovered marker remain
|
|
184
|
+
with the old lineage rather than mixing with the new endpoint's traffic.
|
|
185
|
+
|
|
154
186
|
## Connecting a Vercel source
|
|
155
187
|
|
|
156
188
|
The Vercel adapter pulls per-request logs from the Vercel API for a
|
|
@@ -869,15 +901,14 @@ cnry traffic reset <project> --source <id> --advance-to-now
|
|
|
869
901
|
|
|
870
902
|
`--advance-to-now` is required — there is no implicit reset.
|
|
871
903
|
|
|
872
|
-
`reset` accepts any **non-archived** source type.
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
`cnry traffic connect ...` instead.
|
|
904
|
+
`reset` accepts any **non-archived** source type. A WordPress reset clears
|
|
905
|
+
its `last_cursor` and pending-window marker as well as advancing
|
|
906
|
+
`lastSyncedAt`, so the next bounded drain begins at the reset watermark
|
|
907
|
+
instead of combining it with an old cursor. The primary use case is the
|
|
908
|
+
retention-trap recovery above; clearing `lastError` for a transient WordPress
|
|
909
|
+
failure also works. Reset deliberately abandons any ambiguous pending history;
|
|
910
|
+
it is not a historical repair. Archived sources are rejected — re-connect them
|
|
911
|
+
with `cnry traffic connect ...` instead.
|
|
881
912
|
|
|
882
913
|
Time-window and cursor adapters use the `last_event_ids` overlap ring. Queue
|
|
883
914
|
pull uses durable event receipts sized to Queue retention. Both paths make a
|
|
@@ -91,7 +91,7 @@ import {
|
|
|
91
91
|
trafficConnectWordpressRequestSchema,
|
|
92
92
|
trafficEventKindSchema,
|
|
93
93
|
trafficSeriesGranularitySchema
|
|
94
|
-
} from "./chunk-
|
|
94
|
+
} from "./chunk-PQT3ECM3.js";
|
|
95
95
|
|
|
96
96
|
// src/config.ts
|
|
97
97
|
import fs from "fs";
|
|
@@ -9487,17 +9487,17 @@ var trafficConnectVercelInputSchema = z3.object({
|
|
|
9487
9487
|
var trafficSyncInputSchema = z3.object({
|
|
9488
9488
|
project: projectNameSchema,
|
|
9489
9489
|
sourceId: z3.string().min(1).describe("Traffic source ID returned by canonry_traffic_connect_cloud_run or canonry_traffic_sources_list."),
|
|
9490
|
-
sinceMinutes: z3.number().int().positive().max(
|
|
9490
|
+
sinceMinutes: z3.number().int().positive().max(365 * 24 * 60).optional().describe("Optional lookback in minutes. Defaults are adapter-specific and clamp forward to lastSyncedAt; a new or idle WordPress source uses 365d to cover the plugin\u2019s maximum configurable retention.")
|
|
9491
9491
|
});
|
|
9492
9492
|
var trafficBackfillInputSchema = z3.object({
|
|
9493
9493
|
project: projectNameSchema,
|
|
9494
9494
|
sourceId: z3.string().min(1).describe("Traffic source ID returned by canonry_traffic_sources_list."),
|
|
9495
|
-
days: z3.number().int().positive().max(
|
|
9495
|
+
days: z3.number().int().positive().max(90).optional().describe("Lookback window in days. Default 30, capped by the adapter at 90d. Generic WordPress replace backfill is unavailable because retained coverage is unproven.")
|
|
9496
9496
|
});
|
|
9497
9497
|
var trafficResetInputSchema = z3.object({
|
|
9498
9498
|
project: projectNameSchema,
|
|
9499
9499
|
sourceId: z3.string().min(1).describe("Traffic source ID returned by canonry_traffic_sources_list."),
|
|
9500
|
-
advanceToNow: z3.literal(true).describe("Must be `true`. Explicit gate against accidental resets. Advances lastSyncedAt to NOW and clears the source's error state.")
|
|
9500
|
+
advanceToNow: z3.literal(true).describe("Must be `true`. Explicit gate against accidental resets. Advances lastSyncedAt to NOW and clears the source's error state; WordPress also clears its continuation state and records an unrecovered span that needs retention-aware repair.")
|
|
9501
9501
|
});
|
|
9502
9502
|
var trafficEventsInputSchema = z3.object({
|
|
9503
9503
|
project: projectNameSchema,
|
|
@@ -10650,7 +10650,7 @@ var canonryMcpTools = [
|
|
|
10650
10650
|
defineTool({
|
|
10651
10651
|
name: "canonry_traffic_connect_wordpress",
|
|
10652
10652
|
title: "Connect WordPress traffic-logger source",
|
|
10653
|
-
description: "Connect a WordPress site (running the canonry traffic-logger plugin) as a server-side traffic source. Probes the plugin endpoint with the supplied Application Password before persisting
|
|
10653
|
+
description: "Connect a WordPress site (running the canonry traffic-logger plugin) as a server-side traffic source. Probes the plugin endpoint with the supplied Application Password before persisting; a bad credential or unreachable host surfaces as a 502 error. Reconnecting the same endpoint updates the active source in place. Changing baseUrl archives the old lineage and creates a fresh source so rollups cannot mix across endpoints. The Application Password is stored in ~/.canonry/config.yaml (not the DB) and never echoed back.",
|
|
10654
10654
|
access: "write",
|
|
10655
10655
|
tier: "traffic",
|
|
10656
10656
|
inputSchema: trafficConnectWordpressInputSchema,
|
|
@@ -10671,8 +10671,8 @@ var canonryMcpTools = [
|
|
|
10671
10671
|
}),
|
|
10672
10672
|
defineTool({
|
|
10673
10673
|
name: "canonry_traffic_sync",
|
|
10674
|
-
title: "Sync
|
|
10675
|
-
description: "Pull
|
|
10674
|
+
title: "Sync traffic source",
|
|
10675
|
+
description: "Pull a Cloud Run, WordPress, Vercel, or Cloudflare Queue traffic source, classify crawler / AI-referral / unknown traffic, and upsert hourly rollups plus raw samples. Time-window pulls clamp forward to lastSyncedAt. WordPress uses a fixed bounded window, defaults a new or idle source to 365d, validates the returned events remain inside that window, and serializes syncs with a source lease.",
|
|
10676
10676
|
access: "write",
|
|
10677
10677
|
tier: "traffic",
|
|
10678
10678
|
inputSchema: trafficSyncInputSchema,
|
|
@@ -10682,8 +10682,8 @@ var canonryMcpTools = [
|
|
|
10682
10682
|
}),
|
|
10683
10683
|
defineTool({
|
|
10684
10684
|
name: "canonry_traffic_backfill",
|
|
10685
|
-
title: "Backfill
|
|
10686
|
-
description: 'Async one-shot reclassification
|
|
10685
|
+
title: "Backfill traffic source",
|
|
10686
|
+
description: 'Async one-shot reclassification for Cloud Run or Vercel traffic. It replaces the selected window\u2019s rollups with a fresh bounded pull and current classifier output. WordPress generic replace backfill is unavailable because the endpoint cannot prove retained coverage; use a retention-aware repair that explicitly declares any unrecoverable span. Returns `{ runId, status: "running" }`; poll canonry_run_get for completion.',
|
|
10687
10687
|
access: "write",
|
|
10688
10688
|
tier: "traffic",
|
|
10689
10689
|
inputSchema: trafficBackfillInputSchema,
|
|
@@ -10694,7 +10694,7 @@ var canonryMcpTools = [
|
|
|
10694
10694
|
defineTool({
|
|
10695
10695
|
name: "canonry_traffic_reset",
|
|
10696
10696
|
title: "Advance traffic source lastSyncedAt to NOW",
|
|
10697
|
-
description: "Operator recovery for a stuck traffic source. Advances `lastSyncedAt` to NOW, sets `status` back to `connected`, and clears `last_error`.
|
|
10697
|
+
description: "Operator recovery for a stuck traffic source. Advances `lastSyncedAt` to NOW, sets `status` back to `connected`, and clears `last_error`. A WordPress reset also clears its continuation state and records an unrecovered span so its next bounded drain cannot combine an old cursor with a new window. That stops replay but is not historical repair. Generic WordPress replace-mode backfill is unavailable because retained coverage is unproven; use a retention-aware repair that explicitly declares any unrecoverable span. Archived sources are rejected; reconnect them with the appropriate canonry_traffic_connect_* tool.",
|
|
10698
10698
|
access: "write",
|
|
10699
10699
|
tier: "traffic",
|
|
10700
10700
|
inputSchema: trafficResetInputSchema,
|