@canonry/canonry 4.147.1 → 4.148.3

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 +2 -2
  2. package/assets/assets/{AuditHistoryPanel-BbEZ_0W9.js → AuditHistoryPanel-D5fRv5sF.js} +1 -1
  3. package/assets/assets/{BacklinksPage-B72RKxC-.js → BacklinksPage-CFdO1s1V.js} +1 -1
  4. package/assets/assets/{ChartPrimitives-Cf-jQ3c8.js → ChartPrimitives-BoB1RfNf.js} +1 -1
  5. package/assets/assets/{HistoryPage-C2U1kxKw.js → HistoryPage-YT2JCo2G.js} +1 -1
  6. package/assets/assets/{MeasurementPropertyPage-ltcSZ0tw.js → MeasurementPropertyPage-JDEzHX1H.js} +1 -1
  7. package/assets/assets/{ProjectPage-ZcGjsDlb.js → ProjectPage-B6t_j9tN.js} +1 -1
  8. package/assets/assets/{RunRow-DxO-zxCm.js → RunRow-yKrIU8zY.js} +1 -1
  9. package/assets/assets/{RunsPage-B1ON2nQC.js → RunsPage-DAeC6Ebm.js} +1 -1
  10. package/assets/assets/{SettingsPage-Cp0bHFHk.js → SettingsPage-8Z251PH0.js} +1 -1
  11. package/assets/assets/{TrafficPage-QzitDjhV.js → TrafficPage-DNJGp16_.js} +1 -1
  12. package/assets/assets/{TrafficSourceDetailPage-BjfFyG2y.js → TrafficSourceDetailPage-BuzdNFB8.js} +1 -1
  13. package/assets/assets/{arrow-left-DJ8ZwUlj.js → arrow-left-BrVL2J2e.js} +1 -1
  14. package/assets/assets/{extract-error-message-CX8ZNJ8S.js → extract-error-message-jd9FdYvE.js} +1 -1
  15. package/assets/assets/{index-DF8X6nM0.js → index-Bo0hzrG2.js} +38 -38
  16. package/assets/assets/{trash-2-UHAxuTT7.js → trash-2-lAIhBm6w.js} +1 -1
  17. package/assets/index.html +1 -1
  18. package/dist/{chunk-BVOU4UJM.js → chunk-3VMKOSTQ.js} +33 -0
  19. package/dist/{chunk-GNKVF6TZ.js → chunk-GUKRQT22.js} +4 -4
  20. package/dist/{chunk-ZRUNFIGA.js → chunk-ILUVQDXM.js} +16 -7
  21. package/dist/{chunk-2NTWZHNF.js → chunk-NIKDPQOF.js} +1 -1
  22. package/dist/cli.js +13 -7
  23. package/dist/index.js +4 -4
  24. package/dist/{intelligence-service-2E5YAXI3.js → intelligence-service-CEYWNR6W.js} +2 -2
  25. package/dist/mcp.js +2 -2
  26. package/package.json +8 -8
@@ -1 +1 @@
1
- import{c as a}from"./index-DF8X6nM0.js";const t=[["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"}]],h=a("circle-question-mark",t);const e=[["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"}]],d=a("download",e);const o=[["path",{d:"M15 3h6v6",key:"1q9fwt"}],["path",{d:"M10 14 21 3",key:"gplh6r"}],["path",{d:"M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6",key:"a6xqqp"}]],p=a("external-link",o);const c=[["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"}]],s=a("trash-2",c);export{h as C,d as D,p as E,s as T};
1
+ import{c as a}from"./index-Bo0hzrG2.js";const t=[["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"}]],h=a("circle-question-mark",t);const e=[["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"}]],d=a("download",e);const o=[["path",{d:"M15 3h6v6",key:"1q9fwt"}],["path",{d:"M10 14 21 3",key:"gplh6r"}],["path",{d:"M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6",key:"a6xqqp"}]],p=a("external-link",o);const c=[["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"}]],s=a("trash-2",c);export{h as C,d as D,p as E,s as T};
package/assets/index.html CHANGED
@@ -12,7 +12,7 @@
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-DF8X6nM0.js"></script>
15
+ <script type="module" crossorigin src="./assets/index-Bo0hzrG2.js"></script>
16
16
  <link rel="modulepreload" crossorigin href="./assets/vendor-tanstack-BjS7iY3g.js">
17
17
  <link rel="modulepreload" crossorigin href="./assets/vendor-radix-DnzzbllM.js">
18
18
  <link rel="modulepreload" crossorigin href="./assets/vendor-recharts-33ACLxsD.js">
@@ -5436,6 +5436,14 @@ var apiKeyDtoSchema = z9.object({
5436
5436
  * scoped key may only read/write its own project (enforced server-side).
5437
5437
  */
5438
5438
  projectId: z9.string().nullable(),
5439
+ /**
5440
+ * The scoped project's name, or `null` for a full-instance key. Resolved
5441
+ * server-side so a surface listing keys does not have to fetch every project
5442
+ * to turn an id into something a person can read — the id alone cannot answer
5443
+ * "is this key safe to hand to someone", which is the question the list is
5444
+ * usually open to answer. Additive field.
5445
+ */
5446
+ projectName: z9.string().nullable(),
5439
5447
  /**
5440
5448
  * Server-derived convenience flag: `true` when this key is read-only (carries
5441
5449
  * the `read` scope and no write-granting scope), in which case the API rejects
@@ -7885,7 +7893,32 @@ async function withRetry(fn, opts = {}) {
7885
7893
  }
7886
7894
  throw lastErr;
7887
7895
  }
7896
+ var RATE_LIMIT_MARKERS = [
7897
+ "throttle",
7898
+ // Bing Webmaster Tools: ThrottleHost / ThrottleUser
7899
+ "rate limit",
7900
+ "ratelimit",
7901
+ "too many requests",
7902
+ "quota exceeded",
7903
+ "quotaexceeded",
7904
+ "over quota",
7905
+ "slow down"
7906
+ ];
7907
+ function isRateLimitError(err) {
7908
+ if (err != null && typeof err === "object") {
7909
+ const record = err;
7910
+ const retryAfter = record.retryAfter ?? record["retry-after"];
7911
+ if (typeof retryAfter === "number" || typeof retryAfter === "string") return true;
7912
+ if (typeof record.status === "number" && record.status === 429) return true;
7913
+ }
7914
+ if (err instanceof Error) {
7915
+ const msg = err.message.toLowerCase();
7916
+ return RATE_LIMIT_MARKERS.some((marker) => msg.includes(marker));
7917
+ }
7918
+ return false;
7919
+ }
7888
7920
  function isRetryableHttpError(err) {
7921
+ if (isRateLimitError(err)) return true;
7889
7922
  if (err != null && typeof err === "object" && "status" in err) {
7890
7923
  const status = err.status;
7891
7924
  if (typeof status === "number") {
@@ -10,7 +10,7 @@ import {
10
10
  loadConfig,
11
11
  loadConfigRaw,
12
12
  saveConfigPatch
13
- } from "./chunk-2NTWZHNF.js";
13
+ } from "./chunk-NIKDPQOF.js";
14
14
  import {
15
15
  CC_CACHE_DIR,
16
16
  DUCKDB_SPEC,
@@ -126,7 +126,7 @@ import {
126
126
  siteAuditSnapshots,
127
127
  toAlertView,
128
128
  usageCounters
129
- } from "./chunk-ZRUNFIGA.js";
129
+ } from "./chunk-ILUVQDXM.js";
130
130
  import {
131
131
  AGENT_MEMORY_VALUE_MAX_BYTES,
132
132
  AGENT_PROVIDER_IDS,
@@ -217,7 +217,7 @@ import {
217
217
  validationError,
218
218
  winnabilityClassLabel,
219
219
  withRetry
220
- } from "./chunk-BVOU4UJM.js";
220
+ } from "./chunk-3VMKOSTQ.js";
221
221
 
222
222
  // src/telemetry.ts
223
223
  import crypto from "crypto";
@@ -7420,7 +7420,7 @@ function readStoredGroundingSources(rawResponse) {
7420
7420
  return result;
7421
7421
  }
7422
7422
  async function backfillInsightsCommand(project, opts) {
7423
- const { IntelligenceService: IntelligenceService2 } = await import("./intelligence-service-2E5YAXI3.js");
7423
+ const { IntelligenceService: IntelligenceService2 } = await import("./intelligence-service-CEYWNR6W.js");
7424
7424
  const config = loadConfig();
7425
7425
  const db = createClient(config.database);
7426
7426
  migrate(db);
@@ -517,7 +517,7 @@ import {
517
517
  wordpressSchemaDeployResultDtoSchema,
518
518
  wordpressSchemaStatusResultDtoSchema,
519
519
  wordpressStatusDtoSchema
520
- } from "./chunk-BVOU4UJM.js";
520
+ } from "./chunk-3VMKOSTQ.js";
521
521
 
522
522
  // src/intelligence-service.ts
523
523
  import { eq as eq57, desc as desc26, asc as asc11, and as and45, ne as ne7, or as or11, inArray as inArray19, gte as gte13, lte as lte10 } from "drizzle-orm";
@@ -32727,26 +32727,32 @@ function buildOperationId(method, path8) {
32727
32727
  import crypto22 from "crypto";
32728
32728
  import { desc as desc16, eq as eq35 } from "drizzle-orm";
32729
32729
  var KEYS_WRITE_SCOPE = "keys.write";
32730
- function toApiKeyDto(row) {
32730
+ function toApiKeyDto(row, projectNames) {
32731
32731
  const scopes = Array.isArray(row.scopes) ? row.scopes : [];
32732
+ const projectId = row.projectId ?? null;
32732
32733
  return {
32733
32734
  id: row.id,
32734
32735
  name: row.name,
32735
32736
  keyPrefix: row.keyPrefix,
32736
32737
  scopes,
32737
- projectId: row.projectId ?? null,
32738
+ projectId,
32739
+ projectName: projectId ? projectNames.get(projectId) ?? null : null,
32738
32740
  readOnly: isReadOnlyKey(scopes),
32739
32741
  createdAt: row.createdAt,
32740
32742
  lastUsedAt: row.lastUsedAt ?? null,
32741
32743
  revokedAt: row.revokedAt ?? null
32742
32744
  };
32743
32745
  }
32746
+ function projectNameById(db) {
32747
+ return new Map(db.select().from(projects).all().map((p) => [p.id, p.name]));
32748
+ }
32744
32749
  async function keysRoutes(app) {
32745
32750
  app.get("/keys", async (request) => {
32746
32751
  requireAdminSession(request);
32747
32752
  const scopedProjectId = request.apiKey?.projectId;
32748
32753
  const rows = scopedProjectId ? app.db.select().from(apiKeys).where(eq35(apiKeys.projectId, scopedProjectId)).orderBy(desc16(apiKeys.createdAt)).all() : app.db.select().from(apiKeys).orderBy(desc16(apiKeys.createdAt)).all();
32749
- return { keys: rows.map(toApiKeyDto) };
32754
+ const names = projectNameById(app.db);
32755
+ return { keys: rows.map((row) => toApiKeyDto(row, names)) };
32750
32756
  });
32751
32757
  app.get("/keys/self", async (request) => {
32752
32758
  const id = request.apiKey?.id;
@@ -32757,7 +32763,7 @@ async function keysRoutes(app) {
32757
32763
  if (!row) {
32758
32764
  throw notFound("API key", id);
32759
32765
  }
32760
- return toApiKeyDto(row);
32766
+ return toApiKeyDto(row, projectNameById(app.db));
32761
32767
  });
32762
32768
  app.post("/keys", async (request) => {
32763
32769
  requireAdminSession(request);
@@ -32807,6 +32813,9 @@ async function keysRoutes(app) {
32807
32813
  keyPrefix,
32808
32814
  scopes: effectiveScopes,
32809
32815
  projectId: projectId ?? null,
32816
+ // Resolved from the project the caller just named, so the response says
32817
+ // what the key reaches without a second round trip.
32818
+ projectName: projectId ? projectNameById(app.db).get(projectId) ?? null : null,
32810
32819
  readOnly: isReadOnlyKey(effectiveScopes),
32811
32820
  createdAt: now,
32812
32821
  lastUsedAt: null,
@@ -32831,7 +32840,7 @@ async function keysRoutes(app) {
32831
32840
  throw forbidden("A project-scoped key can only revoke keys scoped to its own project.");
32832
32841
  }
32833
32842
  if (row.revokedAt) {
32834
- return toApiKeyDto(row);
32843
+ return toApiKeyDto(row, projectNameById(app.db));
32835
32844
  }
32836
32845
  const now = (/* @__PURE__ */ new Date()).toISOString();
32837
32846
  app.db.transaction((tx) => {
@@ -32844,7 +32853,7 @@ async function keysRoutes(app) {
32844
32853
  diff: { name: row.name, keyPrefix: row.keyPrefix }
32845
32854
  }));
32846
32855
  });
32847
- return toApiKeyDto({ ...row, revokedAt: now });
32856
+ return toApiKeyDto({ ...row, revokedAt: now }, projectNameById(app.db));
32848
32857
  });
32849
32858
  }
32850
32859
 
@@ -81,7 +81,7 @@ import {
81
81
  trafficConnectWordpressRequestSchema,
82
82
  trafficEventKindSchema,
83
83
  trafficSeriesGranularitySchema
84
- } from "./chunk-BVOU4UJM.js";
84
+ } from "./chunk-3VMKOSTQ.js";
85
85
 
86
86
  // src/config.ts
87
87
  import fs from "fs";
package/dist/cli.js CHANGED
@@ -30,7 +30,7 @@ import {
30
30
  showFirstRunNotice,
31
31
  trackCliCommandFinished,
32
32
  trackEvent
33
- } from "./chunk-GNKVF6TZ.js";
33
+ } from "./chunk-GUKRQT22.js";
34
34
  import {
35
35
  CliError,
36
36
  EXIT_SYSTEM_ERROR,
@@ -50,7 +50,7 @@ import {
50
50
  saveConfigPatch,
51
51
  systemError,
52
52
  usageError
53
- } from "./chunk-2NTWZHNF.js";
53
+ } from "./chunk-NIKDPQOF.js";
54
54
  import {
55
55
  apiKeys,
56
56
  createClient,
@@ -58,7 +58,7 @@ import {
58
58
  projects,
59
59
  queries,
60
60
  renderReportHtml
61
- } from "./chunk-ZRUNFIGA.js";
61
+ } from "./chunk-ILUVQDXM.js";
62
62
  import {
63
63
  AdsDeliverySnapshotStatuses,
64
64
  AdsHistoricalCampaignRollupStatuses,
@@ -122,7 +122,7 @@ import {
122
122
  providerQuotaPolicySchema,
123
123
  resolveProviderInput,
124
124
  winnabilityClassSchema
125
- } from "./chunk-BVOU4UJM.js";
125
+ } from "./chunk-3VMKOSTQ.js";
126
126
 
127
127
  // src/cli.ts
128
128
  import { pathToFileURL } from "url";
@@ -7437,16 +7437,21 @@ async function listApiKeys(format) {
7437
7437
  return;
7438
7438
  }
7439
7439
  console.log(
7440
- `${"NAME".padEnd(20)} ${"PREFIX".padEnd(11)} ${"SCOPES".padEnd(20)} ${"CREATED".padEnd(12)} ${"LAST USED".padEnd(12)} STATUS`
7440
+ `${"NAME".padEnd(20)} ${"PREFIX".padEnd(11)} ${"SCOPES".padEnd(20)} ${"REACH".padEnd(18)} ${"CREATED".padEnd(12)} ${"LAST USED".padEnd(12)} STATUS`
7441
7441
  );
7442
7442
  for (const key of keys) {
7443
7443
  const scopes = key.scopes.join(",");
7444
7444
  const lastUsed = key.lastUsedAt ? formatIsoDate(key.lastUsedAt) : "\u2014";
7445
7445
  console.log(
7446
- `${key.name.padEnd(20)} ${key.keyPrefix.padEnd(11)} ${scopes.padEnd(20)} ${formatIsoDate(key.createdAt).padEnd(12)} ${lastUsed.padEnd(12)} ${keyStatus(key)}`
7446
+ `${key.name.padEnd(20)} ${key.keyPrefix.padEnd(11)} ${scopes.padEnd(20)} ${keyReach(key).padEnd(18)} ${formatIsoDate(key.createdAt).padEnd(12)} ${lastUsed.padEnd(12)} ${keyStatus(key)}`
7447
7447
  );
7448
7448
  }
7449
7449
  }
7450
+ function keyReach(key) {
7451
+ if (!key.projectId) return "full instance";
7452
+ if (typeof key.projectName === "string") return key.projectName;
7453
+ return key.projectName === null ? "(deleted project)" : key.projectId.slice(0, 8);
7454
+ }
7450
7455
  async function createApiKey(opts) {
7451
7456
  const explicitScopes = opts.scopes && opts.scopes.length > 0 ? opts.scopes : void 0;
7452
7457
  if (opts.readOnly && explicitScopes) {
@@ -7475,7 +7480,7 @@ async function createApiKey(opts) {
7475
7480
  console.log(` Prefix: ${created.keyPrefix}`);
7476
7481
  console.log(` Scopes: ${created.scopes.join(", ")}`);
7477
7482
  console.log(` Read-only: ${created.readOnly ? "yes" : "no"}`);
7478
- console.log(` Project: ${opts.project ?? "(full instance)"}`);
7483
+ console.log(` Reach: ${keyReach(created)}`);
7479
7484
  console.log("\nSave this now \u2014 it will not be shown again.");
7480
7485
  }
7481
7486
  async function showApiKeySelf(format) {
@@ -7488,6 +7493,7 @@ async function showApiKeySelf(format) {
7488
7493
  console.log(`API key "${key.name}" (${key.keyPrefix})`);
7489
7494
  console.log(` Scopes: ${key.scopes.join(", ")}`);
7490
7495
  console.log(` Read-only: ${key.readOnly ? "yes" : "no"}`);
7496
+ console.log(` Reach: ${keyReach(key)}`);
7491
7497
  console.log(` Status: ${keyStatus(key)}`);
7492
7498
  }
7493
7499
  async function revokeApiKey(id, format) {
package/dist/index.js CHANGED
@@ -1,11 +1,11 @@
1
1
  import {
2
2
  createServer
3
- } from "./chunk-GNKVF6TZ.js";
3
+ } from "./chunk-GUKRQT22.js";
4
4
  import {
5
5
  loadConfig
6
- } from "./chunk-2NTWZHNF.js";
7
- import "./chunk-ZRUNFIGA.js";
8
- import "./chunk-BVOU4UJM.js";
6
+ } from "./chunk-NIKDPQOF.js";
7
+ import "./chunk-ILUVQDXM.js";
8
+ import "./chunk-3VMKOSTQ.js";
9
9
  export {
10
10
  createServer,
11
11
  loadConfig
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  IntelligenceService
3
- } from "./chunk-ZRUNFIGA.js";
4
- import "./chunk-BVOU4UJM.js";
3
+ } from "./chunk-ILUVQDXM.js";
4
+ import "./chunk-3VMKOSTQ.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-2NTWZHNF.js";
6
+ } from "./chunk-NIKDPQOF.js";
7
7
  import {
8
8
  isReadOnlyKey
9
- } from "./chunk-BVOU4UJM.js";
9
+ } from "./chunk-3VMKOSTQ.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": "@canonry/canonry",
3
- "version": "4.147.1",
3
+ "version": "4.148.3",
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",
@@ -67,26 +67,26 @@
67
67
  "tsup": "^8.5.1",
68
68
  "tsx": "^4.19.0",
69
69
  "@ainyc/canonry-api-client": "0.0.0",
70
+ "@ainyc/canonry-api-routes": "0.0.0",
70
71
  "@ainyc/canonry-config": "0.0.0",
71
- "@ainyc/canonry-contracts": "0.0.0",
72
72
  "@ainyc/canonry-db": "0.0.0",
73
- "@ainyc/canonry-api-routes": "0.0.0",
74
- "@ainyc/canonry-integration-bing": "0.0.0",
73
+ "@ainyc/canonry-contracts": "0.0.0",
75
74
  "@ainyc/canonry-integration-openai-ads": "0.0.0",
75
+ "@ainyc/canonry-integration-bing": "0.0.0",
76
76
  "@ainyc/canonry-integration-cloud-run": "0.0.0",
77
+ "@ainyc/canonry-integration-commoncrawl": "0.0.0",
77
78
  "@ainyc/canonry-integration-google": "0.0.0",
78
79
  "@ainyc/canonry-integration-google-business-profile": "0.0.0",
79
80
  "@ainyc/canonry-integration-google-places": "0.0.0",
81
+ "@ainyc/canonry-integration-wordpress": "0.0.0",
80
82
  "@ainyc/canonry-integration-traffic": "0.0.0",
81
83
  "@ainyc/canonry-intelligence": "0.0.0",
82
84
  "@ainyc/canonry-provider-cdp": "0.0.0",
83
- "@ainyc/canonry-integration-commoncrawl": "0.0.0",
84
85
  "@ainyc/canonry-provider-claude": "0.0.0",
85
86
  "@ainyc/canonry-provider-gemini": "0.0.0",
87
+ "@ainyc/canonry-provider-openai": "0.0.0",
86
88
  "@ainyc/canonry-provider-local": "0.0.0",
87
- "@ainyc/canonry-integration-wordpress": "0.0.0",
88
- "@ainyc/canonry-provider-perplexity": "0.0.0",
89
- "@ainyc/canonry-provider-openai": "0.0.0"
89
+ "@ainyc/canonry-provider-perplexity": "0.0.0"
90
90
  },
91
91
  "scripts": {
92
92
  "build": "tsx scripts/copy-agent-assets.ts && tsup && tsx build-web.ts",