@ainyc/canonry 4.94.0 → 4.95.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 (27) hide show
  1. package/assets/agent-workspace/skills/canonry/SKILL.md +1 -1
  2. package/assets/agent-workspace/skills/canonry/references/canonry-cli.md +2 -2
  3. package/assets/agent-workspace/skills/canonry/references/google-business-profile.md +8 -8
  4. package/assets/assets/{BacklinksPage-FeUApIRv.js → BacklinksPage-CT3DfxMw.js} +1 -1
  5. package/assets/assets/{ChartPrimitives-DFCM9oRt.js → ChartPrimitives-B6Dleq3z.js} +1 -1
  6. package/assets/assets/ProjectPage-DeEE66hg.js +6 -0
  7. package/assets/assets/{RunRow-CF4jm8w8.js → RunRow-C7rEdPSI.js} +1 -1
  8. package/assets/assets/{RunsPage-Dlyl-dmG.js → RunsPage-ByohAHOY.js} +1 -1
  9. package/assets/assets/{SettingsPage-DaQ0YNHz.js → SettingsPage-D4dwPwZy.js} +1 -1
  10. package/assets/assets/{TrafficPage-38zf4QS8.js → TrafficPage-Kh1CSxMr.js} +1 -1
  11. package/assets/assets/{TrafficSourceDetailPage-DJY18oUo.js → TrafficSourceDetailPage-CIlOFRYB.js} +1 -1
  12. package/assets/assets/{arrow-left-CRHf1qtt.js → arrow-left-BoX1Vp7B.js} +1 -1
  13. package/assets/assets/{extract-error-message-uWeOU6mU.js → extract-error-message-ZqsMkFg8.js} +1 -1
  14. package/assets/assets/{index-B7ZT1i67.js → index-k1XIw8WK.js} +2 -2
  15. package/assets/assets/{trash-2-B1qn8ZLk.js → trash-2-A1PQNK3E.js} +1 -1
  16. package/assets/index.html +1 -1
  17. package/dist/{chunk-3TTBKG73.js → chunk-4E4JPS37.js} +18 -6
  18. package/dist/{chunk-ZJADMHJ5.js → chunk-7YU6ILWL.js} +5 -5
  19. package/dist/{chunk-PV3RAHMK.js → chunk-BUGJOQNW.js} +5 -1
  20. package/dist/{chunk-K4QOSPBX.js → chunk-FFSJRZJR.js} +3 -3
  21. package/dist/cli.js +5 -5
  22. package/dist/index.d.ts +9 -1
  23. package/dist/index.js +4 -4
  24. package/dist/{intelligence-service-M33PXIWS.js → intelligence-service-PGEGDNY6.js} +2 -2
  25. package/dist/mcp.js +2 -2
  26. package/package.json +11 -11
  27. package/assets/assets/ProjectPage-Dyx8eZf_.js +0 -6
@@ -9,7 +9,7 @@ import {
9
9
  loadConfig,
10
10
  loadConfigRaw,
11
11
  saveConfigPatch
12
- } from "./chunk-K4QOSPBX.js";
12
+ } from "./chunk-FFSJRZJR.js";
13
13
  import {
14
14
  CC_CACHE_DIR,
15
15
  DUCKDB_SPEC,
@@ -111,7 +111,7 @@ import {
111
111
  siteAuditPages,
112
112
  siteAuditSnapshots,
113
113
  usageCounters
114
- } from "./chunk-ZJADMHJ5.js";
114
+ } from "./chunk-7YU6ILWL.js";
115
115
  import {
116
116
  AGENT_MEMORY_VALUE_MAX_BYTES,
117
117
  AGENT_PROVIDER_IDS,
@@ -171,7 +171,7 @@ import {
171
171
  validationError,
172
172
  winnabilityClassLabel,
173
173
  withRetry
174
- } from "./chunk-PV3RAHMK.js";
174
+ } from "./chunk-BUGJOQNW.js";
175
175
 
176
176
  // src/telemetry.ts
177
177
  import crypto from "crypto";
@@ -2767,6 +2767,15 @@ function normalizeViews(raw) {
2767
2767
  return out.length > 0 ? out : void 0;
2768
2768
  }
2769
2769
 
2770
+ // src/agent-config.ts
2771
+ function resolveAgentEnabled(env, config) {
2772
+ const raw = env.CANONRY_AGENT_DISABLED?.trim();
2773
+ if (raw) {
2774
+ return !(raw === "1" || raw.toLowerCase() === "true");
2775
+ }
2776
+ return config.agent?.mode !== "disabled";
2777
+ }
2778
+
2770
2779
  // src/places-config.ts
2771
2780
  var DEFAULT_TIER = "atmosphere";
2772
2781
  var DEFAULT_REFRESH_INTERVAL_DAYS = 7;
@@ -6387,7 +6396,7 @@ function readStoredGroundingSources(rawResponse) {
6387
6396
  return result;
6388
6397
  }
6389
6398
  async function backfillInsightsCommand(project, opts) {
6390
- const { IntelligenceService: IntelligenceService2 } = await import("./intelligence-service-M33PXIWS.js");
6399
+ const { IntelligenceService: IntelligenceService2 } = await import("./intelligence-service-PGEGDNY6.js");
6391
6400
  const config = loadConfig();
6392
6401
  const db = createClient(config.database);
6393
6402
  migrate(db);
@@ -10333,17 +10342,19 @@ async function createServer(opts) {
10333
10342
  const notifier = new Notifier(opts.db, serverUrl);
10334
10343
  const intelligenceService = new IntelligenceService(opts.db);
10335
10344
  const aeroClient = new ApiClient(opts.config.apiUrl, opts.config.apiKey, { skipProbe: true });
10336
- const sessionRegistry = new SessionRegistry({
10345
+ const agentEnabled = resolveAgentEnabled(process.env, opts.config);
10346
+ const sessionRegistry = agentEnabled ? new SessionRegistry({
10337
10347
  db: opts.db,
10338
10348
  client: aeroClient,
10339
10349
  config: opts.config
10340
- });
10350
+ }) : void 0;
10341
10351
  const runCoordinator = new RunCoordinator(
10342
10352
  opts.db,
10343
10353
  notifier,
10344
10354
  intelligenceService,
10345
10355
  (runId, projectId, result) => notifier.dispatchInsightWebhooks(runId, projectId, result),
10346
10356
  async (ctx) => {
10357
+ if (!sessionRegistry) return;
10347
10358
  const project = opts.db.select({ name: projects.name }).from(projects).where(eq20(projects.id, ctx.projectId)).get();
10348
10359
  if (!project) return;
10349
10360
  let content;
@@ -10870,6 +10881,7 @@ async function createServer(opts) {
10870
10881
  // Local-only Aero agent routes. Registered here so they inherit api-routes'
10871
10882
  // auth plugin — bare `registerAgentRoutes(app, ...)` would skip auth.
10872
10883
  registerAuthenticatedRoutes: async (scope) => {
10884
+ if (!sessionRegistry) return;
10873
10885
  registerAgentRoutes(scope, { db: opts.db, sessionRegistry });
10874
10886
  },
10875
10887
  getGoogleAuthConfig: () => getGoogleAuthConfig(opts.config),
@@ -259,7 +259,7 @@ import {
259
259
  wordpressSchemaDeployResultDtoSchema,
260
260
  wordpressSchemaStatusResultDtoSchema,
261
261
  wordpressStatusDtoSchema
262
- } from "./chunk-PV3RAHMK.js";
262
+ } from "./chunk-BUGJOQNW.js";
263
263
 
264
264
  // src/intelligence-service.ts
265
265
  import { eq as eq37, desc as desc18, asc as asc5, and as and27, ne as ne5, or as or5, inArray as inArray14, gte as gte7, lte as lte4 } from "drizzle-orm";
@@ -5284,7 +5284,7 @@ function analyzeGbp(signals) {
5284
5284
  title: `${loc.displayName}: public listing advertises ${loc.placesAmenities.length} amenit${loc.placesAmenities.length === 1 ? "y" : "ies"} canonry can\u2019t confirm via the GBP API`,
5285
5285
  recommendation: {
5286
5286
  action: 'Verify these amenities are set in the Google Business Profile "Hotel details" panel so the structured profile matches what the public listing advertises.',
5287
- reason: `Google\u2019s rendered listing advertises ${amenityList}, but the GBP Lodging API returns no structured attributes for this location. The Lodging API does not expose the owner-set "Hotel details" amenity panel, so the amenities may already be set there and simply not be readable via the API. Verify in Hotel details: if any are missing, add them, since the structured attributes are the amenity data you directly control and that AI answer engines cite.`
5287
+ reason: `Google\u2019s rendered listing advertises ${amenityList}, but the GBP Lodging API returned no readable structured groups for this location. The amenities may already be set in the owner-facing "Hotel details" panel and simply not be visible in this API response. Verify in Hotel details: if any are missing, add them, since those structured attributes are amenity data you directly control.`
5288
5288
  }
5289
5289
  });
5290
5290
  } else {
@@ -5295,7 +5295,7 @@ function analyzeGbp(signals) {
5295
5295
  title: `${loc.displayName}: structured lodging attributes not readable via the GBP API`,
5296
5296
  recommendation: {
5297
5297
  action: 'Verify the hotel amenities in the Google Business Profile "Hotel details" panel. If they are already set there, no change is needed.',
5298
- reason: 'The GBP Lodging API returns no structured attributes for this location. That resource is commonly empty even for complete hotels, because the owner-set "Hotel details" amenity panel (breakfast, wifi, parking, accessibility, and the like) writes to a separate surface the Lodging API does not expose. Treat this as a verify, not a confirmed gap: confirm the amenities are set in Hotel details, the amenity source you directly control and that AI answer engines cite.'
5298
+ reason: 'The GBP Lodging API returned no readable structured groups for this location. That response can be empty even for complete hotels whose owner-facing "Hotel details" panel has amenities set. Treat this as a verify, not a confirmed gap: confirm the amenities are set in Hotel details.'
5299
5299
  }
5300
5300
  });
5301
5301
  }
@@ -34564,8 +34564,8 @@ var IntelligenceService = class {
34564
34564
  *
34565
34565
  * Point-in-time (no previous-run comparison): for each SELECTED location it
34566
34566
  * derives signals from the shared GBP summary math (metric week-over-week,
34567
- * lodging completeness, place-action CTAs) plus the accumulating keyword
34568
- * monthly series (month-over-month keyword drop), then runs the pure
34567
+ * Lodging API readable-group state, place-action CTAs) plus the accumulating
34568
+ * keyword monthly series (month-over-month keyword drop), then runs the pure
34569
34569
  * `analyzeGbp` analyzer. Persists insights ONLY — no health snapshot, which is
34570
34570
  * an answer-visibility concept. Idempotent per `runId`; dismissals are
34571
34571
  * preserved across re-analysis of the same run by the stable insight id.
@@ -995,7 +995,11 @@ var gbpPlaceActionListResponseSchema = z8.object({
995
995
  });
996
996
  var gbpLodgingDtoSchema = z8.object({
997
997
  locationName: z8.string(),
998
- /** Count of non-empty top-level attribute groups (0 = empty profile / AEO gap). */
998
+ /**
999
+ * Count of non-empty top-level groups in the Lodging API response.
1000
+ * 0 means the API returned no readable structured groups; it is a
1001
+ * verify-the-Hotel-details-panel signal, not proof the hotel has no amenities.
1002
+ */
999
1003
  populatedGroupCount: z8.number().int().nonnegative(),
1000
1004
  syncedAt: z8.string(),
1001
1005
  /** Raw Lodging resource as Google returned it. */
@@ -23,7 +23,7 @@ import {
23
23
  trafficConnectVercelRequestSchema,
24
24
  trafficConnectWordpressRequestSchema,
25
25
  trafficEventKindSchema
26
- } from "./chunk-PV3RAHMK.js";
26
+ } from "./chunk-BUGJOQNW.js";
27
27
 
28
28
  // src/config.ts
29
29
  import fs from "fs";
@@ -6315,7 +6315,7 @@ var canonryMcpTools = [
6315
6315
  defineTool({
6316
6316
  name: "canonry_gbp_lodging",
6317
6317
  title: "Get GBP lodging attributes",
6318
- description: 'List the latest Google Business Profile lodging snapshot per location (hotel structured attributes). populatedGroupCount=0 means the Lodging API returned no structured attributes, which is common even for complete hotels because the owner-set "Hotel details" amenity panel is a separate surface the API does not expose. Treat it as a "verify the Hotel details panel", not a confirmed gap.',
6318
+ description: 'List the latest Google Business Profile lodging snapshot per location (hotel structured attributes). populatedGroupCount=0 means the Lodging API returned no readable structured groups, which can happen even for complete hotels whose owner-facing "Hotel details" panel has amenities set. Treat it as a "verify the Hotel details panel", not a confirmed gap.',
6319
6319
  access: "read",
6320
6320
  tier: "gbp",
6321
6321
  inputSchema: gbpLocationScopedInputSchema,
@@ -6348,7 +6348,7 @@ var canonryMcpTools = [
6348
6348
  defineTool({
6349
6349
  name: "canonry_gbp_summary",
6350
6350
  title: "Get GBP local-AEO summary",
6351
- description: "Composite Google Business Profile summary for a project: performance totals + 7d deltas, keyword thresholded %, place-action CTA presence, lodging coverage, and owner-content profile completeness (how many selected locations populate secondary categories / description / service area / hours / phone, plus closed-status counts). All derived numbers computed server-side.",
6351
+ description: "Composite Google Business Profile summary for a project: performance totals + 7d deltas, keyword thresholded %, place-action CTA presence, Lodging API readable-group counts, and owner-content profile completeness (how many selected locations populate secondary categories / description / service area / hours / phone, plus closed-status counts). All derived numbers computed server-side.",
6352
6352
  access: "read",
6353
6353
  tier: "gbp",
6354
6354
  inputSchema: gbpLocationScopedInputSchema,
package/dist/cli.js CHANGED
@@ -27,7 +27,7 @@ import {
27
27
  setTelemetrySource,
28
28
  showFirstRunNotice,
29
29
  trackEvent
30
- } from "./chunk-3TTBKG73.js";
30
+ } from "./chunk-4E4JPS37.js";
31
31
  import {
32
32
  CliError,
33
33
  EXIT_SYSTEM_ERROR,
@@ -44,7 +44,7 @@ import {
44
44
  saveConfig,
45
45
  saveConfigPatch,
46
46
  usageError
47
- } from "./chunk-K4QOSPBX.js";
47
+ } from "./chunk-FFSJRZJR.js";
48
48
  import {
49
49
  apiKeys,
50
50
  createClient,
@@ -52,7 +52,7 @@ import {
52
52
  projects,
53
53
  queries,
54
54
  renderReportHtml
55
- } from "./chunk-ZJADMHJ5.js";
55
+ } from "./chunk-7YU6ILWL.js";
56
56
  import {
57
57
  BacklinkSources,
58
58
  CcReleaseSyncStatuses,
@@ -77,7 +77,7 @@ import {
77
77
  providerQuotaPolicySchema,
78
78
  resolveProviderInput,
79
79
  winnabilityClassSchema
80
- } from "./chunk-PV3RAHMK.js";
80
+ } from "./chunk-BUGJOQNW.js";
81
81
 
82
82
  // src/cli.ts
83
83
  import { pathToFileURL } from "url";
@@ -3590,7 +3590,7 @@ async function gbpSummary(project, opts) {
3590
3590
  console.log(`
3591
3591
  Keywords: ${s.keywords.total} tracked, ${s.keywords.thresholdedPct}% privacy-thresholded`);
3592
3592
  console.log(`Place actions: ${s.placeActions.total} CTA(s) \u2014 reservation:${s.placeActions.hasReservationCta ? "yes" : "no"} booking:${s.placeActions.hasBookingCta ? "yes" : "no"} direct-merchant:${s.placeActions.hasDirectMerchantCta ? "yes" : "no"}`);
3593
- console.log(`Lodging: ${s.lodging.lodgingLocationCount} profile(s), ${s.lodging.populatedLodgingCount} populated, ${s.lodging.emptyLodgingCount} empty`);
3593
+ console.log(`Lodging API: ${s.lodging.lodgingLocationCount} profile(s), ${s.lodging.populatedLodgingCount} with readable groups, ${s.lodging.emptyLodgingCount} with 0 readable groups`);
3594
3594
  const pc = s.profileCompleteness;
3595
3595
  console.log(`Profile completeness (${pc.locationCount} location(s)): ${pc.withSecondaryCategories} w/ secondary categories (${pc.secondaryCategoryTotal} total), ${pc.withDescription} w/ description, ${pc.withServiceArea} w/ service area, ${pc.withHours} w/ hours, ${pc.withPrimaryPhone} w/ phone` + (pc.permanentlyClosed || pc.temporarilyClosed ? `; closed: ${pc.permanentlyClosed} permanently, ${pc.temporarilyClosed} temporarily` : ""));
3596
3596
  }
package/dist/index.d.ts CHANGED
@@ -157,7 +157,15 @@ interface VercelTrafficConfigEntry {
157
157
  connections?: VercelTrafficConnectionConfigEntry[];
158
158
  }
159
159
  interface AgentConfigEntry {
160
- /** Agent mode. Only 'disabled' is valid until the native loop ships. */
160
+ /**
161
+ * Agent mode. `'disabled'` turns the built-in Aero agent OFF entirely — the
162
+ * proactive auto-wake on run completion does not fire, the `SessionRegistry`
163
+ * is not constructed, and the interactive agent routes (`/projects/:name/
164
+ * agent/*`) plus the `canonry agent ask` CLI (a thin client of those routes)
165
+ * are not served. Absent (the default) leaves Aero enabled. Resolved, with
166
+ * the `CANONRY_AGENT_DISABLED` env override, by `resolveAgentEnabled` in
167
+ * agent-config.ts.
168
+ */
161
169
  mode?: 'disabled';
162
170
  }
163
171
  /**
package/dist/index.js CHANGED
@@ -1,11 +1,11 @@
1
1
  import {
2
2
  createServer
3
- } from "./chunk-3TTBKG73.js";
3
+ } from "./chunk-4E4JPS37.js";
4
4
  import {
5
5
  loadConfig
6
- } from "./chunk-K4QOSPBX.js";
7
- import "./chunk-ZJADMHJ5.js";
8
- import "./chunk-PV3RAHMK.js";
6
+ } from "./chunk-FFSJRZJR.js";
7
+ import "./chunk-7YU6ILWL.js";
8
+ import "./chunk-BUGJOQNW.js";
9
9
  export {
10
10
  createServer,
11
11
  loadConfig
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  IntelligenceService
3
- } from "./chunk-ZJADMHJ5.js";
4
- import "./chunk-PV3RAHMK.js";
3
+ } from "./chunk-7YU6ILWL.js";
4
+ import "./chunk-BUGJOQNW.js";
5
5
  export {
6
6
  IntelligenceService
7
7
  };
package/dist/mcp.js CHANGED
@@ -3,10 +3,10 @@ import {
3
3
  PACKAGE_VERSION,
4
4
  canonryMcpTools,
5
5
  createApiClient
6
- } from "./chunk-K4QOSPBX.js";
6
+ } from "./chunk-FFSJRZJR.js";
7
7
  import {
8
8
  isReadOnlyKey
9
- } from "./chunk-PV3RAHMK.js";
9
+ } from "./chunk-BUGJOQNW.js";
10
10
 
11
11
  // src/mcp/cli.ts
12
12
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ainyc/canonry",
3
- "version": "4.94.0",
3
+ "version": "4.95.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",
@@ -62,27 +62,27 @@
62
62
  "@types/node-cron": "^3.0.11",
63
63
  "tsup": "^8.5.1",
64
64
  "tsx": "^4.19.0",
65
- "@ainyc/canonry-api-client": "0.0.0",
66
- "@ainyc/canonry-contracts": "0.0.0",
67
- "@ainyc/canonry-config": "0.0.0",
68
65
  "@ainyc/canonry-api-routes": "0.0.0",
69
- "@ainyc/canonry-db": "0.0.0",
66
+ "@ainyc/canonry-contracts": "0.0.0",
67
+ "@ainyc/canonry-integration-openai-ads": "0.0.0",
70
68
  "@ainyc/canonry-integration-bing": "0.0.0",
69
+ "@ainyc/canonry-api-client": "0.0.0",
70
+ "@ainyc/canonry-db": "0.0.0",
71
71
  "@ainyc/canonry-integration-cloud-run": "0.0.0",
72
72
  "@ainyc/canonry-integration-commoncrawl": "0.0.0",
73
- "@ainyc/canonry-integration-openai-ads": "0.0.0",
74
- "@ainyc/canonry-integration-google-business-profile": "0.0.0",
73
+ "@ainyc/canonry-config": "0.0.0",
75
74
  "@ainyc/canonry-integration-google": "0.0.0",
75
+ "@ainyc/canonry-integration-google-business-profile": "0.0.0",
76
+ "@ainyc/canonry-integration-google-places": "0.0.0",
77
+ "@ainyc/canonry-integration-wordpress": "0.0.0",
76
78
  "@ainyc/canonry-integration-traffic": "0.0.0",
77
79
  "@ainyc/canonry-intelligence": "0.0.0",
78
- "@ainyc/canonry-integration-google-places": "0.0.0",
79
80
  "@ainyc/canonry-provider-cdp": "0.0.0",
80
- "@ainyc/canonry-integration-wordpress": "0.0.0",
81
81
  "@ainyc/canonry-provider-claude": "0.0.0",
82
82
  "@ainyc/canonry-provider-gemini": "0.0.0",
83
+ "@ainyc/canonry-provider-local": "0.0.0",
83
84
  "@ainyc/canonry-provider-openai": "0.0.0",
84
- "@ainyc/canonry-provider-perplexity": "0.0.0",
85
- "@ainyc/canonry-provider-local": "0.0.0"
85
+ "@ainyc/canonry-provider-perplexity": "0.0.0"
86
86
  },
87
87
  "scripts": {
88
88
  "build": "tsx scripts/copy-agent-assets.ts && tsup && tsx build-web.ts",