@ainyc/canonry 4.88.0 → 4.89.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 (26) hide show
  1. package/assets/agent-workspace/skills/canonry/references/canonry-cli.md +16 -0
  2. package/assets/assets/{BacklinksPage-Dpx6ylmU.js → BacklinksPage-Cl3V55iK.js} +1 -1
  3. package/assets/assets/{ChartPrimitives-CG5EGu62.js → ChartPrimitives-D4D_lSIp.js} +1 -1
  4. package/assets/assets/{ProjectPage-B_xnYE7W.js → ProjectPage-Dwwcddk2.js} +1 -1
  5. package/assets/assets/{RunRow-C0V4vf-u.js → RunRow-CNjwUkqj.js} +1 -1
  6. package/assets/assets/{RunsPage-9gWTjteG.js → RunsPage-owFYxiRU.js} +1 -1
  7. package/assets/assets/{SettingsPage-kBwz4Glg.js → SettingsPage-D3rc2Hze.js} +1 -1
  8. package/assets/assets/{TrafficPage-D4adjs8S.js → TrafficPage-BDkhe0Iz.js} +1 -1
  9. package/assets/assets/{TrafficSourceDetailPage-CmURRHaU.js → TrafficSourceDetailPage-CUw6Odt1.js} +1 -1
  10. package/assets/assets/{arrow-left-DJ0-oFbd.js → arrow-left-BAOMqvGW.js} +1 -1
  11. package/assets/assets/{extract-error-message-DfBzETgi.js → extract-error-message-BO0DeR7V.js} +1 -1
  12. package/assets/assets/{index-BeuGfMy8.js → index-BbnglhBg.js} +78 -78
  13. package/assets/assets/index-fLUYE9Z5.css +1 -0
  14. package/assets/assets/{trash-2-Bjf6mCqw.js → trash-2-RQK6oqQJ.js} +1 -1
  15. package/assets/index.html +2 -2
  16. package/dist/{chunk-JZ67YCHT.js → chunk-LRO4CLPL.js} +62 -1
  17. package/dist/{chunk-2VEFNAQ3.js → chunk-MUPIPQBB.js} +50 -7
  18. package/dist/{chunk-RH3QYFX3.js → chunk-PRKBJNAG.js} +1 -1
  19. package/dist/{chunk-WMZJO56S.js → chunk-WEV4RH25.js} +1 -1
  20. package/dist/cli.js +35 -11
  21. package/dist/index.d.ts +9 -1
  22. package/dist/index.js +4 -4
  23. package/dist/{intelligence-service-WTEEV46F.js → intelligence-service-SO46DMGR.js} +2 -2
  24. package/dist/mcp.js +2 -2
  25. package/package.json +7 -7
  26. package/assets/assets/index-ClkRAeHL.css +0 -1
@@ -9,7 +9,7 @@ import {
9
9
  loadConfig,
10
10
  loadConfigRaw,
11
11
  saveConfigPatch
12
- } from "./chunk-RH3QYFX3.js";
12
+ } from "./chunk-PRKBJNAG.js";
13
13
  import {
14
14
  CC_CACHE_DIR,
15
15
  DUCKDB_SPEC,
@@ -104,7 +104,7 @@ import {
104
104
  siteAuditPages,
105
105
  siteAuditSnapshots,
106
106
  usageCounters
107
- } from "./chunk-WMZJO56S.js";
107
+ } from "./chunk-WEV4RH25.js";
108
108
  import {
109
109
  AGENT_MEMORY_VALUE_MAX_BYTES,
110
110
  AGENT_PROVIDER_IDS,
@@ -136,6 +136,7 @@ import {
136
136
  agentMemoryUpsertRequestSchema,
137
137
  authInvalid,
138
138
  authRequired,
139
+ buildEmbedClientConfig,
139
140
  buildRunErrorFromMessages,
140
141
  classifySkillFile,
141
142
  coerceSkillManifest,
@@ -147,20 +148,23 @@ import {
147
148
  effectiveBrandNames,
148
149
  effectiveDomains,
149
150
  factorStatusFromScore,
151
+ frameAncestorsHeaderValue,
150
152
  hostOf,
151
153
  isAgentProviderId,
152
154
  isBrowserProvider,
153
155
  isRetryableHttpError,
154
156
  normalizeUrlPath,
155
157
  notFound,
158
+ parseOriginList,
156
159
  providerError,
157
160
  resolveSnapshotRequestQueries,
158
161
  serializeRunError,
159
162
  skillsClientSchema,
163
+ splitList,
160
164
  validationError,
161
165
  winnabilityClassLabel,
162
166
  withRetry
163
- } from "./chunk-JZ67YCHT.js";
167
+ } from "./chunk-LRO4CLPL.js";
164
168
 
165
169
  // src/telemetry.ts
166
170
  import crypto from "crypto";
@@ -2728,6 +2732,34 @@ var perplexityAdapter = {
2728
2732
  }
2729
2733
  };
2730
2734
 
2735
+ // src/embed.ts
2736
+ function resolveEmbedConfig(env, config) {
2737
+ const embed = config.embed;
2738
+ const rawEnabled = env.CANONRY_EMBED?.trim();
2739
+ const enabled = rawEnabled ? rawEnabled === "1" || rawEnabled.toLowerCase() === "true" : embed?.enabled === true;
2740
+ const allowedOrigins = env.CANONRY_EMBED_ORIGINS !== void 0 ? parseOriginList(env.CANONRY_EMBED_ORIGINS) : parseOriginList(embed?.allowOrigins);
2741
+ const rawViews = env.CANONRY_EMBED_VIEWS !== void 0 ? splitList(env.CANONRY_EMBED_VIEWS) : splitList(embed?.views);
2742
+ const views = normalizeViews(rawViews);
2743
+ return {
2744
+ enabled,
2745
+ allowedOrigins,
2746
+ ...views ? { views } : {},
2747
+ ...embed?.theme ? { theme: embed.theme } : {}
2748
+ };
2749
+ }
2750
+ function normalizeViews(raw) {
2751
+ if (raw.length === 0) return void 0;
2752
+ const seen = /* @__PURE__ */ new Set();
2753
+ const out = [];
2754
+ for (const view of raw) {
2755
+ const id = view.toLowerCase();
2756
+ if (seen.has(id)) continue;
2757
+ seen.add(id);
2758
+ out.push(id);
2759
+ }
2760
+ return out.length > 0 ? out : void 0;
2761
+ }
2762
+
2731
2763
  // src/places-config.ts
2732
2764
  var DEFAULT_TIER = "atmosphere";
2733
2765
  var DEFAULT_REFRESH_INTERVAL_DAYS = 7;
@@ -6289,7 +6321,7 @@ function readStoredGroundingSources(rawResponse) {
6289
6321
  return result;
6290
6322
  }
6291
6323
  async function backfillInsightsCommand(project, opts) {
6292
- const { IntelligenceService: IntelligenceService2 } = await import("./intelligence-service-WTEEV46F.js");
6324
+ const { IntelligenceService: IntelligenceService2 } = await import("./intelligence-service-SO46DMGR.js");
6293
6325
  const config = loadConfig();
6294
6326
  const db = createClient(config.database);
6295
6327
  migrate(db);
@@ -10538,6 +10570,8 @@ async function createServer(opts) {
10538
10570
  const rawBasePath = process.env.CANONRY_BASE_PATH ?? opts.config.basePath;
10539
10571
  const normalizedBasePath = rawBasePath ? "/" + rawBasePath.replace(/^\//, "").replace(/\/?$/, "/") : void 0;
10540
10572
  const basePath = normalizedBasePath === "/" ? void 0 : normalizedBasePath;
10573
+ const embed = resolveEmbedConfig(process.env, opts.config);
10574
+ const embedCsp = embed.enabled ? frameAncestorsHeaderValue(embed.allowedOrigins) : void 0;
10541
10575
  const apiPrefix = basePath ? `${basePath}api/v1` : "/api/v1";
10542
10576
  if (opts.config.apiKey) {
10543
10577
  const keyHash = hashApiKey(opts.config.apiKey);
@@ -11173,16 +11207,25 @@ async function createServer(opts) {
11173
11207
  }
11174
11208
  });
11175
11209
  const dirname = path9.dirname(fileURLToPath3(import.meta.url));
11176
- const assetsDir = path9.join(dirname, "..", "assets");
11210
+ const assetsDir = opts.assetsDir ?? path9.join(dirname, "..", "assets");
11177
11211
  if (fs8.existsSync(assetsDir)) {
11178
11212
  const indexPath = path9.join(assetsDir, "index.html");
11179
11213
  const injectConfig = (html) => {
11180
11214
  const clientConfig = {};
11181
11215
  if (basePath) clientConfig.basePath = basePath;
11216
+ if (embed.enabled) {
11217
+ const embedClient = buildEmbedClientConfig(embed);
11218
+ if (embedClient) clientConfig.embed = embedClient;
11219
+ }
11182
11220
  const configScript = `<script>window.__CANONRY_CONFIG__=${JSON.stringify(clientConfig)}</script>`;
11183
11221
  const baseTag = `<base href="${basePath ?? "/"}">`;
11184
11222
  return html.replace("<head>", `<head>${baseTag}`).replace("</head>", `${configScript}</head>`);
11185
11223
  };
11224
+ const sendSpaDocument = (reply, html) => {
11225
+ reply.header("Cache-Control", "no-cache, must-revalidate");
11226
+ if (embedCsp) reply.header("Content-Security-Policy", embedCsp);
11227
+ return reply.type("text/html").send(injectConfig(html));
11228
+ };
11186
11229
  const fastifyStatic = await import("@fastify/static");
11187
11230
  await app.register(fastifyStatic.default, {
11188
11231
  root: assetsDir,
@@ -11209,7 +11252,7 @@ async function createServer(opts) {
11209
11252
  const serveIndex = (_request, reply) => {
11210
11253
  if (fs8.existsSync(indexPath)) {
11211
11254
  const html = fs8.readFileSync(indexPath, "utf-8");
11212
- return reply.header("Cache-Control", "no-cache, must-revalidate").type("text/html").send(injectConfig(html));
11255
+ return sendSpaDocument(reply, html);
11213
11256
  }
11214
11257
  return reply.status(404).send({ error: "Dashboard not built" });
11215
11258
  };
@@ -11230,7 +11273,7 @@ async function createServer(opts) {
11230
11273
  }
11231
11274
  if (fs8.existsSync(indexPath)) {
11232
11275
  const html = fs8.readFileSync(indexPath, "utf-8");
11233
- return reply.header("Cache-Control", "no-cache, must-revalidate").type("text/html").send(injectConfig(html));
11276
+ return sendSpaDocument(reply, html);
11234
11277
  }
11235
11278
  return reply.status(404).send({ error: "Not found" });
11236
11279
  });
@@ -23,7 +23,7 @@ import {
23
23
  trafficConnectVercelRequestSchema,
24
24
  trafficConnectWordpressRequestSchema,
25
25
  trafficEventKindSchema
26
- } from "./chunk-JZ67YCHT.js";
26
+ } from "./chunk-LRO4CLPL.js";
27
27
 
28
28
  // src/config.ts
29
29
  import fs from "fs";
@@ -258,7 +258,7 @@ import {
258
258
  wordpressSchemaDeployResultDtoSchema,
259
259
  wordpressSchemaStatusResultDtoSchema,
260
260
  wordpressStatusDtoSchema
261
- } from "./chunk-JZ67YCHT.js";
261
+ } from "./chunk-LRO4CLPL.js";
262
262
 
263
263
  // src/intelligence-service.ts
264
264
  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";
package/dist/cli.js CHANGED
@@ -27,7 +27,7 @@ import {
27
27
  setTelemetrySource,
28
28
  showFirstRunNotice,
29
29
  trackEvent
30
- } from "./chunk-2VEFNAQ3.js";
30
+ } from "./chunk-MUPIPQBB.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-RH3QYFX3.js";
47
+ } from "./chunk-PRKBJNAG.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-WMZJO56S.js";
55
+ } from "./chunk-WEV4RH25.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-JZ67YCHT.js";
80
+ } from "./chunk-LRO4CLPL.js";
81
81
 
82
82
  // src/cli.ts
83
83
  import { pathToFileURL } from "url";
@@ -10299,6 +10299,18 @@ async function waitForReady(host, port, maxMs = 1e4) {
10299
10299
  }
10300
10300
  return false;
10301
10301
  }
10302
+ function buildServeForwardArgs(opts) {
10303
+ const args = [];
10304
+ if (opts.port) args.push("--port", opts.port);
10305
+ if (opts.host) args.push("--host", opts.host);
10306
+ if (opts.basePath) args.push("--base-path", opts.basePath);
10307
+ if (opts.embed) {
10308
+ args.push("--embed");
10309
+ for (const origin of opts.embedAllowOrigins ?? []) args.push("--embed-allow-origin", origin);
10310
+ for (const view of opts.embedViews ?? []) args.push("--embed-view", view);
10311
+ }
10312
+ return args;
10313
+ }
10302
10314
  async function startDaemon(opts) {
10303
10315
  const pidPath = getPidPath();
10304
10316
  const format = opts.format ?? "text";
@@ -10319,9 +10331,7 @@ async function startDaemon(opts) {
10319
10331
  const cliPath = path7.resolve(new URL(import.meta.url).pathname);
10320
10332
  const inSourceMode = new URL(import.meta.url).pathname.endsWith(".ts");
10321
10333
  const args = inSourceMode ? ["--import", "tsx", cliPath, "serve"] : [cliPath, "serve"];
10322
- if (opts.port) args.push("--port", opts.port);
10323
- if (opts.host) args.push("--host", opts.host);
10324
- if (opts.basePath) args.push("--base-path", opts.basePath);
10334
+ args.push(...buildServeForwardArgs(opts));
10325
10335
  const child = spawn(process.execPath, args, {
10326
10336
  detached: true,
10327
10337
  stdio: "ignore"
@@ -11002,6 +11012,11 @@ function applyServerEnv(values) {
11002
11012
  if (port) process.env.CANONRY_PORT = port;
11003
11013
  if (host) process.env.CANONRY_HOST = host;
11004
11014
  if (basePath) process.env.CANONRY_BASE_PATH = basePath;
11015
+ const embedOrigins = getStringArray(values, "embed-allow-origin");
11016
+ const embedViews = getStringArray(values, "embed-view");
11017
+ if (getBoolean(values, "embed")) process.env.CANONRY_EMBED = "1";
11018
+ if (embedOrigins && embedOrigins.length > 0) process.env.CANONRY_EMBED_ORIGINS = embedOrigins.join(",");
11019
+ if (embedViews && embedViews.length > 0) process.env.CANONRY_EMBED_VIEWS = embedViews.join(",");
11005
11020
  }
11006
11021
  var SYSTEM_CLI_COMMANDS = [
11007
11022
  {
@@ -11058,11 +11073,14 @@ var SYSTEM_CLI_COMMANDS = [
11058
11073
  },
11059
11074
  {
11060
11075
  path: ["serve"],
11061
- usage: "canonry serve [--port <port>] [--host <host>] [--base-path <path>] [--format json]",
11076
+ usage: "canonry serve [--port <port>] [--host <host>] [--base-path <path>] [--embed] [--embed-allow-origin <origin>...] [--embed-view <view>...] [--format json]",
11062
11077
  options: {
11063
11078
  port: stringOption(),
11064
11079
  host: stringOption(),
11065
- "base-path": stringOption()
11080
+ "base-path": stringOption(),
11081
+ embed: { type: "boolean", default: false },
11082
+ "embed-allow-origin": multiStringOption(),
11083
+ "embed-view": multiStringOption()
11066
11084
  },
11067
11085
  allowPositionals: false,
11068
11086
  run: async (input) => {
@@ -11072,11 +11090,14 @@ var SYSTEM_CLI_COMMANDS = [
11072
11090
  },
11073
11091
  {
11074
11092
  path: ["start"],
11075
- usage: "canonry start [--port <port>] [--host <host>] [--base-path <path>] [--format json]",
11093
+ usage: "canonry start [--port <port>] [--host <host>] [--base-path <path>] [--embed] [--embed-allow-origin <origin>...] [--embed-view <view>...] [--format json]",
11076
11094
  options: {
11077
11095
  port: stringOption(),
11078
11096
  host: stringOption(),
11079
- "base-path": stringOption()
11097
+ "base-path": stringOption(),
11098
+ embed: { type: "boolean", default: false },
11099
+ "embed-allow-origin": multiStringOption(),
11100
+ "embed-view": multiStringOption()
11080
11101
  },
11081
11102
  allowPositionals: false,
11082
11103
  run: async (input) => {
@@ -11084,6 +11105,9 @@ var SYSTEM_CLI_COMMANDS = [
11084
11105
  port: getString(input.values, "port"),
11085
11106
  host: getString(input.values, "host"),
11086
11107
  basePath: getString(input.values, "base-path"),
11108
+ embed: getBoolean(input.values, "embed"),
11109
+ embedAllowOrigins: getStringArray(input.values, "embed-allow-origin"),
11110
+ embedViews: getStringArray(input.values, "embed-view"),
11087
11111
  format: input.format
11088
11112
  });
11089
11113
  }
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { FastifyInstance } from 'fastify';
2
2
  import { DatabaseClient } from '@ainyc/canonry-db';
3
- import { ProviderQuotaPolicy } from '@ainyc/canonry-contracts';
3
+ import { ProviderQuotaPolicy, EmbedConfigEntry } from '@ainyc/canonry-contracts';
4
4
 
5
5
  type GoogleConnectionType = 'gsc' | 'ga4' | 'gbp';
6
6
  interface ProviderConfigEntry {
@@ -205,6 +205,7 @@ interface CanonryConfig {
205
205
  lastKnownLatestVersion?: string;
206
206
  agent?: AgentConfigEntry;
207
207
  places?: PlacesConfigEntry;
208
+ embed?: EmbedConfigEntry;
208
209
  }
209
210
  declare function loadConfig(): CanonryConfig;
210
211
 
@@ -223,6 +224,13 @@ declare function createServer(opts: {
223
224
  * Defaults to loopback when unset (programmatic/test callers).
224
225
  */
225
226
  host?: string;
227
+ /**
228
+ * Override for the directory the pre-built SPA is served from. Defaults to
229
+ * the package's bundled `assets/` (resolved from `import.meta.url`). Exposed
230
+ * so tests can point at a temp dir containing a fixture `index.html` and
231
+ * assert the injected config + framing header on the served document.
232
+ */
233
+ assetsDir?: string;
226
234
  }): Promise<FastifyInstance>;
227
235
 
228
236
  export { type CanonryConfig, createServer, loadConfig };
package/dist/index.js CHANGED
@@ -1,11 +1,11 @@
1
1
  import {
2
2
  createServer
3
- } from "./chunk-2VEFNAQ3.js";
3
+ } from "./chunk-MUPIPQBB.js";
4
4
  import {
5
5
  loadConfig
6
- } from "./chunk-RH3QYFX3.js";
7
- import "./chunk-WMZJO56S.js";
8
- import "./chunk-JZ67YCHT.js";
6
+ } from "./chunk-PRKBJNAG.js";
7
+ import "./chunk-WEV4RH25.js";
8
+ import "./chunk-LRO4CLPL.js";
9
9
  export {
10
10
  createServer,
11
11
  loadConfig
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  IntelligenceService
3
- } from "./chunk-WMZJO56S.js";
4
- import "./chunk-JZ67YCHT.js";
3
+ } from "./chunk-WEV4RH25.js";
4
+ import "./chunk-LRO4CLPL.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-RH3QYFX3.js";
6
+ } from "./chunk-PRKBJNAG.js";
7
7
  import {
8
8
  isReadOnlyKey
9
- } from "./chunk-JZ67YCHT.js";
9
+ } from "./chunk-LRO4CLPL.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.88.0",
3
+ "version": "4.89.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,24 +62,24 @@
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-config": "0.0.0",
67
65
  "@ainyc/canonry-api-routes": "0.0.0",
66
+ "@ainyc/canonry-config": "0.0.0",
68
67
  "@ainyc/canonry-contracts": "0.0.0",
69
68
  "@ainyc/canonry-db": "0.0.0",
70
- "@ainyc/canonry-integration-bing": "0.0.0",
71
69
  "@ainyc/canonry-integration-cloud-run": "0.0.0",
70
+ "@ainyc/canonry-integration-bing": "0.0.0",
71
+ "@ainyc/canonry-api-client": "0.0.0",
72
+ "@ainyc/canonry-integration-openai-ads": "0.0.0",
72
73
  "@ainyc/canonry-integration-commoncrawl": "0.0.0",
73
74
  "@ainyc/canonry-integration-google": "0.0.0",
74
- "@ainyc/canonry-integration-openai-ads": "0.0.0",
75
- "@ainyc/canonry-integration-google-business-profile": "0.0.0",
76
75
  "@ainyc/canonry-integration-google-places": "0.0.0",
76
+ "@ainyc/canonry-integration-google-business-profile": "0.0.0",
77
77
  "@ainyc/canonry-integration-traffic": "0.0.0",
78
78
  "@ainyc/canonry-intelligence": "0.0.0",
79
79
  "@ainyc/canonry-integration-wordpress": "0.0.0",
80
80
  "@ainyc/canonry-provider-cdp": "0.0.0",
81
- "@ainyc/canonry-provider-gemini": "0.0.0",
82
81
  "@ainyc/canonry-provider-claude": "0.0.0",
82
+ "@ainyc/canonry-provider-gemini": "0.0.0",
83
83
  "@ainyc/canonry-provider-local": "0.0.0",
84
84
  "@ainyc/canonry-provider-openai": "0.0.0",
85
85
  "@ainyc/canonry-provider-perplexity": "0.0.0"