@ainyc/canonry 4.61.0 → 4.62.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.
Files changed (25) hide show
  1. package/README.md +3 -2
  2. package/assets/agent-workspace/skills/aero/references/regression-playbook.md +2 -0
  3. package/assets/agent-workspace/skills/canonry/references/google-business-profile.md +1 -0
  4. package/assets/assets/{BacklinksPage-CsGOAPNN.js → BacklinksPage-BemXB6GS.js} +1 -1
  5. package/assets/assets/{ChartPrimitives-Bjow7aaC.js → ChartPrimitives-dmrE9jZb.js} +1 -1
  6. package/assets/assets/ProjectPage-DqCnHEV2.js +6 -0
  7. package/assets/assets/{RunRow-ve7H_XIu.js → RunRow-DoylbyR5.js} +1 -1
  8. package/assets/assets/{RunsPage-mYmYevh0.js → RunsPage-Dqk6N23k.js} +1 -1
  9. package/assets/assets/{SettingsPage-DoRiIJK5.js → SettingsPage-BiHfUMwX.js} +1 -1
  10. package/assets/assets/{TrafficPage-1LFyX4OT.js → TrafficPage-D1kFNV8R.js} +1 -1
  11. package/assets/assets/{TrafficSourceDetailPage-BYDJtQdO.js → TrafficSourceDetailPage-DOK7re41.js} +1 -1
  12. package/assets/assets/{extract-error-message-Bt6jcL_M.js → extract-error-message-CD8TzPFm.js} +1 -1
  13. package/assets/assets/{index-BQxaYi-t.js → index-D4km1FDL.js} +52 -52
  14. package/assets/assets/{index-Cp0p2Bib.css → index-DbIJBXnx.css} +1 -1
  15. package/assets/assets/server-traffic-K8586rYW.js +1 -0
  16. package/assets/assets/{trash-2-BFSmyr_7.js → trash-2-D2qhBJ9M.js} +1 -1
  17. package/assets/index.html +2 -2
  18. package/dist/{chunk-ZTVBTGDW.js → chunk-4FLI5VSQ.js} +2 -2
  19. package/dist/{chunk-QZN3J35I.js → chunk-QU62IX7K.js} +44 -18
  20. package/dist/cli.js +2 -2
  21. package/dist/index.js +2 -2
  22. package/dist/{intelligence-service-RWVBWSB5.js → intelligence-service-AZDX2EBS.js} +1 -1
  23. package/package.json +9 -9
  24. package/assets/assets/ProjectPage-BZoMD93_.js +0 -6
  25. package/assets/assets/server-traffic-C5f87b84.js +0 -1
@@ -0,0 +1 @@
1
+ import{c as d,j as a,bP as S,bJ as l,bQ as v,aq as m,l as t,bR as y,bK as i,bS as T,bT as h,bU as p,bV as b}from"./index-D4km1FDL.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 q(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(()=>q(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 Q(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 R(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 I(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,Q as a,R as b,E as c,V as d,F as e,A as f,I as g,M as t,k as u};
@@ -1 +1 @@
1
- import{c}from"./index-BQxaYi-t.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};
1
+ import{c}from"./index-D4km1FDL.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-BQxaYi-t.js"></script>
15
+ <script type="module" crossorigin src="./assets/index-D4km1FDL.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-DWvKDyBF.js">
19
19
  <link rel="modulepreload" crossorigin href="./assets/vendor-markdown-DK7fbRNb.js">
20
- <link rel="stylesheet" crossorigin href="./assets/index-Cp0p2Bib.css">
20
+ <link rel="stylesheet" crossorigin href="./assets/index-DbIJBXnx.css">
21
21
  </head>
22
22
  <body>
23
23
  <div id="root"></div>
@@ -93,7 +93,7 @@ import {
93
93
  runs,
94
94
  schedules,
95
95
  usageCounters
96
- } from "./chunk-QZN3J35I.js";
96
+ } from "./chunk-QU62IX7K.js";
97
97
  import {
98
98
  AGENT_MEMORY_VALUE_MAX_BYTES,
99
99
  AGENT_PROVIDER_IDS,
@@ -5616,7 +5616,7 @@ function readStoredGroundingSources(rawResponse) {
5616
5616
  return result;
5617
5617
  }
5618
5618
  async function backfillInsightsCommand(project, opts) {
5619
- const { IntelligenceService: IntelligenceService2 } = await import("./intelligence-service-RWVBWSB5.js");
5619
+ const { IntelligenceService: IntelligenceService2 } = await import("./intelligence-service-AZDX2EBS.js");
5620
5620
  const config = loadConfig();
5621
5621
  const db = createClient(config.database);
5622
5622
  migrate(db);
@@ -31222,6 +31222,17 @@ function matchesBrandKey(candidateKey, brandKeys) {
31222
31222
  var RECURRENCE_LOOKBACK_RUNS = 5;
31223
31223
  var HISTORY_WINDOW_RUNS = Math.max(PERSISTENT_GAP_THRESHOLD, 5);
31224
31224
  var log = createLogger("IntelligenceService");
31225
+ function gbpInsightSlot(typeOrSlot) {
31226
+ return typeOrSlot === "gbp-lodging-gap" || typeOrSlot === "gbp-listing-discrepancy" ? "lodging" : typeOrSlot;
31227
+ }
31228
+ function gbpInsightId(projectId, locationName, type) {
31229
+ return `${projectId}::gbp::${locationName}::${gbpInsightSlot(type)}`;
31230
+ }
31231
+ function parseGbpInsightId(id) {
31232
+ const parts = id.split("::");
31233
+ if (parts.length !== 4 || parts[1] !== "gbp") return null;
31234
+ return { location: parts[2], slot: gbpInsightSlot(parts[3]) };
31235
+ }
31225
31236
  var IntelligenceService = class {
31226
31237
  constructor(db) {
31227
31238
  this.db = db;
@@ -31320,7 +31331,7 @@ var IntelligenceService = class {
31320
31331
  const runRow = this.db.select({ createdAt: runs.createdAt, startedAt: runs.startedAt, finishedAt: runs.finishedAt }).from(runs).where(eq30(runs.id, runId)).get();
31321
31332
  if (!runRow) {
31322
31333
  log.info("gbp-intelligence.skip", { runId, reason: "run not found" });
31323
- this.persistGbpInsights(runId, projectId, []);
31334
+ this.persistGbpInsights(runId, projectId, [], []);
31324
31335
  return [];
31325
31336
  }
31326
31337
  const windowStart = runRow.startedAt ?? runRow.createdAt;
@@ -31333,7 +31344,7 @@ var IntelligenceService = class {
31333
31344
  )).all();
31334
31345
  if (selected.length === 0) {
31335
31346
  log.info("gbp-intelligence.skip", { runId, reason: "no locations synced during run" });
31336
- this.persistGbpInsights(runId, projectId, []);
31347
+ this.persistGbpInsights(runId, projectId, [], []);
31337
31348
  return [];
31338
31349
  }
31339
31350
  const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
@@ -31343,10 +31354,11 @@ var IntelligenceService = class {
31343
31354
  const drafts = analyzeGbp(signals);
31344
31355
  const now = (/* @__PURE__ */ new Date()).toISOString();
31345
31356
  const builtInsights = drafts.map((d) => ({
31346
- // Stable id: unique per (run, location, type). Embedding runId keeps the
31347
- // PK unique across runs; embedding locationName keeps two chain locations
31348
- // that share a displayName from colliding.
31349
- id: `${runId}::gbp::${d.locationName}::${d.type}`,
31357
+ // Stable, run-independent id per (project, location, slot) so each sync
31358
+ // REPLACES the prior insight for that slot instead of appending a per-run
31359
+ // copy. The lodging slot is shared by gbp-lodging-gap and its
31360
+ // gbp-listing-discrepancy upgrade, so the latter supersedes the former.
31361
+ id: gbpInsightId(projectId, d.locationName, d.type),
31350
31362
  type: d.type,
31351
31363
  severity: d.severity,
31352
31364
  title: d.title,
@@ -31355,7 +31367,7 @@ var IntelligenceService = class {
31355
31367
  recommendation: d.recommendation,
31356
31368
  createdAt: now
31357
31369
  }));
31358
- this.persistGbpInsights(runId, projectId, builtInsights);
31370
+ this.persistGbpInsights(runId, projectId, builtInsights, signals.map((s) => s.locationName));
31359
31371
  log.info("gbp-intelligence.analyzed", { runId, locations: selected.length, insights: builtInsights.length });
31360
31372
  return builtInsights;
31361
31373
  }
@@ -31416,20 +31428,34 @@ var IntelligenceService = class {
31416
31428
  return { recentMonth, priorMonth, points };
31417
31429
  }
31418
31430
  /**
31419
- * Persist GBP insights for a run. Mirrors `persistResult`'s idempotency
31420
- * (delete-then-insert for the run) and dismissal preservation, but keyed by
31421
- * the stable insight id (GBP insights aren't query/provider-scoped) and
31422
- * WITHOUT a health snapshot.
31431
+ * Persist GBP insights as CURRENT STATE for the locations a sync evaluated.
31432
+ * GBP insights are point-in-time profile facts, not run-to-run transitions, so
31433
+ * each sync REPLACES the prior insights for the locations it covered — keyed by
31434
+ * the run-independent `${projectId}::gbp::${location}::${slot}` id — instead of
31435
+ * appending a fresh per-run copy. This collapses run-over-run duplicates,
31436
+ * supersedes `gbp-lodging-gap` with `gbp-listing-discrepancy` (shared `lodging`
31437
+ * slot), and clears a location's stale insight once its gap is resolved.
31438
+ * Dismissals are preserved by (location, slot). Locations NOT covered by this
31439
+ * run (e.g. a `--location`-scoped sync) are left untouched.
31423
31440
  */
31424
- persistGbpInsights(runId, projectId, gbpInsights) {
31425
- const previouslyDismissed = /* @__PURE__ */ new Set();
31426
- const existing = this.db.select({ id: insights.id, dismissed: insights.dismissed }).from(insights).where(eq30(insights.runId, runId)).all();
31441
+ persistGbpInsights(runId, projectId, gbpInsights, coveredLocationNames) {
31442
+ const covered = new Set(coveredLocationNames);
31443
+ const existing = this.db.select({ id: insights.id, dismissed: insights.dismissed }).from(insights).where(and23(eq30(insights.projectId, projectId), eq30(insights.provider, GBP_INSIGHT_PROVIDER))).all();
31444
+ const staleIds = [];
31445
+ const dismissedSlots = /* @__PURE__ */ new Set();
31427
31446
  for (const row of existing) {
31428
- if (row.dismissed) previouslyDismissed.add(row.id);
31447
+ const parsed = parseGbpInsightId(row.id);
31448
+ if (!parsed) continue;
31449
+ if (covered.has(parsed.location)) staleIds.push(row.id);
31450
+ if (row.dismissed) dismissedSlots.add(`${parsed.location}::${parsed.slot}`);
31429
31451
  }
31430
31452
  this.db.transaction((tx) => {
31431
- tx.delete(insights).where(eq30(insights.runId, runId)).run();
31453
+ for (const id of staleIds) {
31454
+ tx.delete(insights).where(eq30(insights.id, id)).run();
31455
+ }
31432
31456
  for (const insight of gbpInsights) {
31457
+ const parsed = parseGbpInsightId(insight.id);
31458
+ const dismissed = parsed ? dismissedSlots.has(`${parsed.location}::${parsed.slot}`) : false;
31433
31459
  tx.insert(insights).values({
31434
31460
  id: insight.id,
31435
31461
  projectId,
@@ -31441,12 +31467,12 @@ var IntelligenceService = class {
31441
31467
  provider: insight.provider,
31442
31468
  recommendation: insight.recommendation ?? null,
31443
31469
  cause: insight.cause ?? null,
31444
- dismissed: previouslyDismissed.has(insight.id),
31470
+ dismissed,
31445
31471
  createdAt: insight.createdAt
31446
31472
  }).run();
31447
31473
  }
31448
31474
  });
31449
- log.info("gbp-intelligence.persisted", { runId, insights: gbpInsights.length });
31475
+ log.info("gbp-intelligence.persisted", { runId, insights: gbpInsights.length, replaced: staleIds.length });
31450
31476
  }
31451
31477
  /**
31452
31478
  * Analyze a single run given an explicit previous run (or null for first run).
package/dist/cli.js CHANGED
@@ -27,7 +27,7 @@ import {
27
27
  setTelemetrySource,
28
28
  showFirstRunNotice,
29
29
  trackEvent
30
- } from "./chunk-ZTVBTGDW.js";
30
+ } from "./chunk-4FLI5VSQ.js";
31
31
  import {
32
32
  CliError,
33
33
  EXIT_SYSTEM_ERROR,
@@ -51,7 +51,7 @@ import {
51
51
  projects,
52
52
  queries,
53
53
  renderReportHtml
54
- } from "./chunk-QZN3J35I.js";
54
+ } from "./chunk-QU62IX7K.js";
55
55
  import {
56
56
  CcReleaseSyncStatuses,
57
57
  CheckScopes,
package/dist/index.js CHANGED
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  createServer
3
- } from "./chunk-ZTVBTGDW.js";
3
+ } from "./chunk-4FLI5VSQ.js";
4
4
  import {
5
5
  loadConfig
6
6
  } from "./chunk-PITZUUFV.js";
7
- import "./chunk-QZN3J35I.js";
7
+ import "./chunk-QU62IX7K.js";
8
8
  import "./chunk-URPUUKLC.js";
9
9
  export {
10
10
  createServer,
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  IntelligenceService
3
- } from "./chunk-QZN3J35I.js";
3
+ } from "./chunk-QU62IX7K.js";
4
4
  import "./chunk-URPUUKLC.js";
5
5
  export {
6
6
  IntelligenceService
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ainyc/canonry",
3
- "version": "4.61.0",
3
+ "version": "4.62.0",
4
4
  "type": "module",
5
5
  "description": "Agent-first open-source AEO operating platform - track how answer engines cite your domain",
6
6
  "license": "FSL-1.1-ALv2",
@@ -61,26 +61,26 @@
61
61
  "@types/node-cron": "^3.0.11",
62
62
  "tsup": "^8.5.1",
63
63
  "tsx": "^4.19.0",
64
- "@ainyc/canonry-config": "0.0.0",
65
64
  "@ainyc/canonry-api-client": "0.0.0",
66
65
  "@ainyc/canonry-api-routes": "0.0.0",
66
+ "@ainyc/canonry-config": "0.0.0",
67
67
  "@ainyc/canonry-db": "0.0.0",
68
68
  "@ainyc/canonry-integration-bing": "0.0.0",
69
69
  "@ainyc/canonry-contracts": "0.0.0",
70
70
  "@ainyc/canonry-integration-cloud-run": "0.0.0",
71
+ "@ainyc/canonry-integration-commoncrawl": "0.0.0",
71
72
  "@ainyc/canonry-integration-google-business-profile": "0.0.0",
72
- "@ainyc/canonry-integration-google": "0.0.0",
73
73
  "@ainyc/canonry-integration-google-places": "0.0.0",
74
- "@ainyc/canonry-integration-commoncrawl": "0.0.0",
75
74
  "@ainyc/canonry-integration-traffic": "0.0.0",
76
- "@ainyc/canonry-intelligence": "0.0.0",
77
- "@ainyc/canonry-provider-cdp": "0.0.0",
78
- "@ainyc/canonry-provider-claude": "0.0.0",
79
75
  "@ainyc/canonry-integration-wordpress": "0.0.0",
76
+ "@ainyc/canonry-integration-google": "0.0.0",
80
77
  "@ainyc/canonry-provider-gemini": "0.0.0",
81
- "@ainyc/canonry-provider-openai": "0.0.0",
78
+ "@ainyc/canonry-intelligence": "0.0.0",
79
+ "@ainyc/canonry-provider-claude": "0.0.0",
80
+ "@ainyc/canonry-provider-local": "0.0.0",
82
81
  "@ainyc/canonry-provider-perplexity": "0.0.0",
83
- "@ainyc/canonry-provider-local": "0.0.0"
82
+ "@ainyc/canonry-provider-cdp": "0.0.0",
83
+ "@ainyc/canonry-provider-openai": "0.0.0"
84
84
  },
85
85
  "scripts": {
86
86
  "build": "tsx scripts/copy-agent-assets.ts && tsup && tsx build-web.ts",