@canonry/canonry 4.162.0 → 4.163.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/assets/assets/{AuditHistoryPanel-BTtqk1mK.js → AuditHistoryPanel-FDQx9TS5.js} +1 -1
  2. package/assets/assets/{BacklinksPage-wqRYkJFG.js → BacklinksPage-DVvsQsdk.js} +1 -1
  3. package/assets/assets/{HistoryPage-Dj1FU5WV.js → HistoryPage-31HR6TIJ.js} +1 -1
  4. package/assets/assets/{MeasurementPropertyPage-CPCYzznG.js → MeasurementPropertyPage-Dps7MF7r.js} +1 -1
  5. package/assets/assets/{ProjectPage-7vg1El9D.js → ProjectPage-BijTUrpk.js} +6 -6
  6. package/assets/assets/{RunRow-CTgtgq5x.js → RunRow-9DiFrBlc.js} +1 -1
  7. package/assets/assets/{RunsPage-qS7etC5f.js → RunsPage-DQlAc4J9.js} +1 -1
  8. package/assets/assets/{SettingsPage-BlUWPiA7.js → SettingsPage-c1nxJsbL.js} +1 -1
  9. package/assets/assets/SiteHealthSection-0B0oUUQx.js +4 -0
  10. package/assets/assets/{TrafficPage-BSWUsXM1.js → TrafficPage-HzwQyLzl.js} +1 -1
  11. package/assets/assets/{TrafficSourceDetailPage-DOTtU4SK.js → TrafficSourceDetailPage-BTVAQjRd.js} +1 -1
  12. package/assets/assets/{extract-error-message-DOWCsWL0.js → extract-error-message-B5bhJRmf.js} +1 -1
  13. package/assets/assets/{index-BYGqta_M.js → index-CQsvCUM0.js} +19 -19
  14. package/assets/assets/{react-sigma_core.esm.min-C4kgfZfm.js → react-sigma_core.esm.min-6BxcniCA.js} +1 -1
  15. package/assets/index.html +1 -1
  16. package/dist/{chunk-NG7OR6GO.js → chunk-ESH3LPYQ.js} +120 -7
  17. package/dist/{chunk-C6ZZH3XI.js → chunk-G5UZTODF.js} +108 -32
  18. package/dist/{chunk-2TLRE2L3.js → chunk-INXI6PO7.js} +3 -3
  19. package/dist/{chunk-FZAAGXTK.js → chunk-MRHYSEZB.js} +80 -30
  20. package/dist/cli.js +4 -4
  21. package/dist/index.js +4 -4
  22. package/dist/{intelligence-service-ANRFEQWX.js → intelligence-service-AFAFGLCM.js} +2 -2
  23. package/dist/mcp.js +2 -2
  24. package/package.json +12 -12
  25. package/assets/assets/SiteHealthSection-tUFchSy-.js +0 -4
@@ -10,7 +10,7 @@ import {
10
10
  loadConfig,
11
11
  loadConfigRaw,
12
12
  saveConfigPatch
13
- } from "./chunk-2TLRE2L3.js";
13
+ } from "./chunk-INXI6PO7.js";
14
14
  import {
15
15
  CC_CACHE_DIR,
16
16
  DUCKDB_SPEC,
@@ -139,7 +139,7 @@ import {
139
139
  siteCrawlSnapshots,
140
140
  toAlertView,
141
141
  usageCounters
142
- } from "./chunk-C6ZZH3XI.js";
142
+ } from "./chunk-G5UZTODF.js";
143
143
  import {
144
144
  AGENT_MEMORY_VALUE_MAX_BYTES,
145
145
  AGENT_PROVIDER_IDS,
@@ -172,7 +172,7 @@ import {
172
172
  SITE_CRAWL_GRAPH_MAX_NODES,
173
173
  SKILL_MANIFEST_FILENAME,
174
174
  SchedulableRunKinds,
175
- SiteHealthTemplateDetections,
175
+ SiteHealthLinkClassificationSources,
176
176
  SkillsClients,
177
177
  TEMPLATE_LINK_RATIO_THRESHOLD,
178
178
  TrafficEventConfidences,
@@ -193,11 +193,13 @@ import {
193
193
  bucketOnboardingCount,
194
194
  buildRunErrorFromMessages,
195
195
  classifySkillFile,
196
+ classifyTemplateLinkEdge,
196
197
  cloudflareQueueNameSchema,
197
198
  coerceSkillManifest,
198
199
  computeBacklinkSummaryMetrics,
199
200
  contentActionLabel,
200
201
  contentBriefDtoSchema,
202
+ createTemplateLinkDetectionTally,
201
203
  createTemplateLinkPairIndex,
202
204
  deriveCitedUrlCandidates,
203
205
  deriveIndexCoverage,
@@ -220,7 +222,6 @@ import {
220
222
  isGhostTelemetryEvent,
221
223
  isRetryableHttpError,
222
224
  isSelfLink,
223
- isTemplateLinkRatio,
224
225
  isVertexGroundingRedirect,
225
226
  mapWithConcurrency,
226
227
  normalizeIdTokens,
@@ -229,6 +230,7 @@ import {
229
230
  normalizeSiteAuditRunRequest,
230
231
  normalizeUrlPath,
231
232
  notFound,
233
+ observeTemplateLinkDetection,
232
234
  observeTemplateLinkEdges,
233
235
  parseMeasurementRunManifestV1,
234
236
  parseOriginList,
@@ -244,13 +246,14 @@ import {
244
246
  splitList,
245
247
  startOfDayHourInTimeZone,
246
248
  templateLinkDetection,
247
- templateLinkRatio,
249
+ templateLinkPlacementAvailable,
250
+ templateLinkUbiquityAvailable,
248
251
  textContainsBrandAlias,
249
252
  textContainsDomain,
250
253
  validationError,
251
254
  winnabilityClassLabel,
252
255
  withRetry
253
- } from "./chunk-NG7OR6GO.js";
256
+ } from "./chunk-ESH3LPYQ.js";
254
257
 
255
258
  // src/telemetry.ts
256
259
  import crypto from "crypto";
@@ -7304,7 +7307,7 @@ var COMPONENT_PACKING_SPACING_FACTOR = 3;
7304
7307
  function siteCrawlGraphLayoutSettingsFingerprint(settings) {
7305
7308
  return crypto16.createHash("sha256").update(JSON.stringify(settings)).digest("hex").slice(0, 8);
7306
7309
  }
7307
- var SITE_CRAWL_GRAPH_LAYOUT_ALGORITHM = "site-health-fa2-v4";
7310
+ var SITE_CRAWL_GRAPH_LAYOUT_ALGORITHM = "site-health-fa2-v5";
7308
7311
  var SITE_CRAWL_GRAPH_LAYOUT_VERSION = `${SITE_CRAWL_GRAPH_LAYOUT_ALGORITHM}-${siteCrawlGraphLayoutSettingsFingerprint({
7309
7312
  forceAtlas: FORCE_ATLAS_SETTINGS,
7310
7313
  noverlap: NOVERLAP_SETTINGS,
@@ -7860,6 +7863,13 @@ function deleteSiteCrawlGraphLayout(db, scope) {
7860
7863
  import { and as and11, asc as asc2, eq as eq14, gt, inArray as inArray4 } from "drizzle-orm";
7861
7864
  var TEMPLATE_LINK_READ_BATCH = 2e3;
7862
7865
  var TEMPLATE_LINK_WRITE_BATCH = 500;
7866
+ function placementOccurrencesOf(row) {
7867
+ const { placementNavigationOccurrences: navigation } = row;
7868
+ const { placementContentOccurrences: content } = row;
7869
+ const { placementUnknownOccurrences: unknown } = row;
7870
+ if (navigation == null || content == null || unknown == null) return null;
7871
+ return { navigation, content, unknown };
7872
+ }
7863
7873
  function* streamAttemptEdges(db, scope) {
7864
7874
  let after = "";
7865
7875
  for (; ; ) {
@@ -7867,7 +7877,11 @@ function* streamAttemptEdges(db, scope) {
7867
7877
  edgeKey: siteCrawlEdges.edgeKey,
7868
7878
  sourceNodeKey: siteCrawlEdges.sourceNodeKey,
7869
7879
  targetNodeKey: siteCrawlEdges.targetNodeKey,
7870
- anchors: siteCrawlEdges.anchors
7880
+ anchors: siteCrawlEdges.anchors,
7881
+ relation: siteCrawlEdges.relation,
7882
+ placementNavigationOccurrences: siteCrawlEdges.placementNavigationOccurrences,
7883
+ placementContentOccurrences: siteCrawlEdges.placementContentOccurrences,
7884
+ placementUnknownOccurrences: siteCrawlEdges.placementUnknownOccurrences
7871
7885
  }).from(siteCrawlEdges).where(and11(
7872
7886
  eq14(siteCrawlEdges.projectId, scope.projectId),
7873
7887
  eq14(siteCrawlEdges.runId, scope.runId),
@@ -7875,7 +7889,14 @@ function* streamAttemptEdges(db, scope) {
7875
7889
  gt(siteCrawlEdges.edgeKey, after)
7876
7890
  )).orderBy(asc2(siteCrawlEdges.edgeKey)).limit(TEMPLATE_LINK_READ_BATCH).all();
7877
7891
  if (rows.length === 0) return;
7878
- yield rows;
7892
+ yield rows.map((row) => ({
7893
+ edgeKey: row.edgeKey,
7894
+ sourceNodeKey: row.sourceNodeKey,
7895
+ targetNodeKey: row.targetNodeKey,
7896
+ anchors: row.anchors,
7897
+ relation: row.relation,
7898
+ placementOccurrences: placementOccurrencesOf(row)
7899
+ }));
7879
7900
  after = rows[rows.length - 1].edgeKey;
7880
7901
  if (rows.length < TEMPLATE_LINK_READ_BATCH) return;
7881
7902
  }
@@ -7885,39 +7906,56 @@ function* chunked(values, size = TEMPLATE_LINK_WRITE_BATCH) {
7885
7906
  yield values.slice(offset, offset + size);
7886
7907
  }
7887
7908
  }
7888
- function classifySiteCrawlTemplateLinks(db, scope, pagesFetched) {
7909
+ function writeGroupKey(isTemplate, templateRatio) {
7910
+ return `${isTemplate ? "1" : "0"}${templateRatio ?? ""}`;
7911
+ }
7912
+ function classifySiteCrawlTemplateLinks(db, scope, pagesFetched, placementRulesetVersion) {
7889
7913
  const scopeFilter = and11(
7890
7914
  eq14(siteCrawlEdges.projectId, scope.projectId),
7891
7915
  eq14(siteCrawlEdges.runId, scope.runId),
7892
7916
  eq14(siteCrawlEdges.attemptId, scope.attemptId)
7893
7917
  );
7894
- const detection = templateLinkDetection(pagesFetched);
7918
+ const placementAvailable = templateLinkPlacementAvailable(placementRulesetVersion);
7919
+ const ubiquityAvailable = templateLinkUbiquityAvailable(pagesFetched);
7895
7920
  db.update(siteCrawlEdges).set({ isTemplate: false, templateRatio: null }).where(scopeFilter).run();
7896
- if (detection !== SiteHealthTemplateDetections.applied) {
7897
- return { detection, templateEdgeCount: 0 };
7898
- }
7899
7921
  const index = createTemplateLinkPairIndex();
7900
- for (const batch of streamAttemptEdges(db, scope)) observeTemplateLinkEdges(index, batch);
7901
- const edgeKeysByRatio = /* @__PURE__ */ new Map();
7922
+ if (ubiquityAvailable) {
7923
+ for (const batch of streamAttemptEdges(db, scope)) observeTemplateLinkEdges(index, batch);
7924
+ }
7925
+ const edgeKeysByValue = /* @__PURE__ */ new Map();
7902
7926
  let templateEdgeCount = 0;
7927
+ let placementEdgeCount = 0;
7928
+ const tally = createTemplateLinkDetectionTally();
7903
7929
  for (const batch of streamAttemptEdges(db, scope)) {
7904
7930
  for (const edge of batch) {
7905
- const ratio = templateLinkRatio(index, pagesFetched, edge);
7906
- if (ratio == null) continue;
7907
- const group = edgeKeysByRatio.get(ratio);
7908
- if (group) group.push(edge.edgeKey);
7909
- else edgeKeysByRatio.set(ratio, [edge.edgeKey]);
7910
- if (isTemplateLinkRatio(ratio)) templateEdgeCount += 1;
7931
+ const decision = classifyTemplateLinkEdge(edge, { index, pagesFetched, placementAvailable, ubiquityAvailable });
7932
+ observeTemplateLinkDetection(tally, edge, decision);
7933
+ if (decision.source === SiteHealthLinkClassificationSources.placement) placementEdgeCount += 1;
7934
+ if (decision.isTemplate) templateEdgeCount += 1;
7935
+ if (!decision.isTemplate && decision.templateRatio == null) continue;
7936
+ const key = writeGroupKey(decision.isTemplate, decision.templateRatio);
7937
+ const group = edgeKeysByValue.get(key);
7938
+ if (group) group.edgeKeys.push(decision.edgeKey);
7939
+ else {
7940
+ edgeKeysByValue.set(key, {
7941
+ isTemplate: decision.isTemplate,
7942
+ templateRatio: decision.templateRatio,
7943
+ edgeKeys: [decision.edgeKey]
7944
+ });
7945
+ }
7911
7946
  }
7912
7947
  }
7913
7948
  const now = (/* @__PURE__ */ new Date()).toISOString();
7914
- for (const [ratio, edgeKeys] of edgeKeysByRatio) {
7915
- const isTemplate = isTemplateLinkRatio(ratio);
7916
- for (const chunk of chunked(edgeKeys)) {
7917
- db.update(siteCrawlEdges).set({ isTemplate, templateRatio: ratio, updatedAt: now }).where(and11(scopeFilter, inArray4(siteCrawlEdges.edgeKey, chunk))).run();
7949
+ for (const group of edgeKeysByValue.values()) {
7950
+ for (const chunk of chunked(group.edgeKeys)) {
7951
+ db.update(siteCrawlEdges).set({ isTemplate: group.isTemplate, templateRatio: group.templateRatio, updatedAt: now }).where(and11(scopeFilter, inArray4(siteCrawlEdges.edgeKey, chunk))).run();
7918
7952
  }
7919
7953
  }
7920
- return { detection, templateEdgeCount };
7954
+ return {
7955
+ detection: templateLinkDetection({ placementAvailable, ubiquityAvailable, tally }),
7956
+ templateEdgeCount,
7957
+ placementEdgeCount
7958
+ };
7921
7959
  }
7922
7960
 
7923
7961
  // src/execute-site-audit.ts
@@ -8230,6 +8268,11 @@ async function executeSiteAudit(db, runId, projectId, opts = {}) {
8230
8268
  for (const page of pages) persistPage(tx, page, now);
8231
8269
  bindReferences(tx, changedUrls, now);
8232
8270
  };
8271
+ const edgePlacementColumns = (edge) => ({
8272
+ placementNavigationOccurrences: edge.placementOccurrences?.navigation ?? null,
8273
+ placementContentOccurrences: edge.placementOccurrences?.content ?? null,
8274
+ placementUnknownOccurrences: edge.placementOccurrences?.unknown ?? null
8275
+ });
8233
8276
  const persistEdge = (tx, edge, now) => {
8234
8277
  if (isSelfLink(edge.from, edge.to)) return;
8235
8278
  observedEdges.set(edge.key, edge);
@@ -8250,6 +8293,7 @@ async function executeSiteAudit(db, runId, projectId, opts = {}) {
8250
8293
  followableOccurrences: edge.followableOccurrences,
8251
8294
  nofollowOccurrences: edge.nofollowOccurrences,
8252
8295
  anchors: edge.anchorSummaries.map((anchor) => anchor.text),
8296
+ ...edgePlacementColumns(edge),
8253
8297
  createdAt: now,
8254
8298
  updatedAt: now
8255
8299
  }).onConflictDoUpdate({
@@ -8266,6 +8310,7 @@ async function executeSiteAudit(db, runId, projectId, opts = {}) {
8266
8310
  followableOccurrences: edge.followableOccurrences,
8267
8311
  nofollowOccurrences: edge.nofollowOccurrences,
8268
8312
  anchors: edge.anchorSummaries.map((anchor) => anchor.text),
8313
+ ...edgePlacementColumns(edge),
8269
8314
  updatedAt: now
8270
8315
  }
8271
8316
  }).run();
@@ -8373,16 +8418,20 @@ async function executeSiteAudit(db, runId, projectId, opts = {}) {
8373
8418
  if (crawlSummary.complete && !hasAuditedPages) {
8374
8419
  throw emptyCompleteCrawlError(crawlSummary.rootUrl, crawlSummary.finalRootUrl, crawlSummary.pagesObserved);
8375
8420
  }
8421
+ const placementRulesetVersion = crawlSummary.linkPlacementRulesetVersion ?? null;
8376
8422
  const templateLinks = classifySiteCrawlTemplateLinks(
8377
8423
  db,
8378
8424
  { projectId, runId, attemptId },
8379
- crawlSummary.pagesFetched
8425
+ crawlSummary.pagesFetched,
8426
+ placementRulesetVersion
8380
8427
  );
8381
8428
  log12.info("template-links", {
8382
8429
  runId,
8383
8430
  projectId,
8384
8431
  detection: templateLinks.detection,
8385
- templateEdges: templateLinks.templateEdgeCount
8432
+ templateEdges: templateLinks.templateEdgeCount,
8433
+ placementEdges: templateLinks.placementEdgeCount,
8434
+ placementRulesetVersion
8386
8435
  });
8387
8436
  const graphLayout = await prepareSiteCrawlGraphLayout(db, {
8388
8437
  projectId,
@@ -8497,6 +8546,7 @@ async function executeSiteAudit(db, runId, projectId, opts = {}) {
8497
8546
  deadLinksChecked,
8498
8547
  deadLinksFound,
8499
8548
  templateDetection: templateLinks.detection,
8549
+ linkPlacementRulesetVersion: placementRulesetVersion,
8500
8550
  createdAt: finishedAt,
8501
8551
  updatedAt: finishedAt
8502
8552
  }).run();
@@ -9034,7 +9084,7 @@ function readStoredGroundingSources(rawResponse) {
9034
9084
  return result;
9035
9085
  }
9036
9086
  async function backfillInsightsCommand(project, opts) {
9037
- const { IntelligenceService: IntelligenceService2 } = await import("./intelligence-service-ANRFEQWX.js");
9087
+ const { IntelligenceService: IntelligenceService2 } = await import("./intelligence-service-AFAFGLCM.js");
9038
9088
  const config = loadConfig();
9039
9089
  const db = createClient(config.database);
9040
9090
  migrate(db);
package/dist/cli.js CHANGED
@@ -31,7 +31,7 @@ import {
31
31
  showFirstRunNotice,
32
32
  trackCliCommandFinished,
33
33
  trackEvent
34
- } from "./chunk-FZAAGXTK.js";
34
+ } from "./chunk-MRHYSEZB.js";
35
35
  import {
36
36
  CliError,
37
37
  EXIT_SYSTEM_ERROR,
@@ -51,7 +51,7 @@ import {
51
51
  saveConfigPatch,
52
52
  systemError,
53
53
  usageError
54
- } from "./chunk-2TLRE2L3.js";
54
+ } from "./chunk-INXI6PO7.js";
55
55
  import {
56
56
  CLOUDFLARE_WORKER_BINDINGS,
57
57
  CLOUDFLARE_WORKER_GENERATED_MARKER,
@@ -65,7 +65,7 @@ import {
65
65
  projects,
66
66
  queries,
67
67
  renderReportHtml
68
- } from "./chunk-C6ZZH3XI.js";
68
+ } from "./chunk-G5UZTODF.js";
69
69
  import {
70
70
  AdsDeliverySnapshotStatuses,
71
71
  AdsHistoricalCampaignRollupStatuses,
@@ -129,7 +129,7 @@ import {
129
129
  providerQuotaPolicySchema,
130
130
  resolveProviderInput,
131
131
  winnabilityClassSchema
132
- } from "./chunk-NG7OR6GO.js";
132
+ } from "./chunk-ESH3LPYQ.js";
133
133
 
134
134
  // src/cli.ts
135
135
  import { pathToFileURL } from "url";
package/dist/index.js CHANGED
@@ -1,11 +1,11 @@
1
1
  import {
2
2
  createServer
3
- } from "./chunk-FZAAGXTK.js";
3
+ } from "./chunk-MRHYSEZB.js";
4
4
  import {
5
5
  loadConfig
6
- } from "./chunk-2TLRE2L3.js";
7
- import "./chunk-C6ZZH3XI.js";
8
- import "./chunk-NG7OR6GO.js";
6
+ } from "./chunk-INXI6PO7.js";
7
+ import "./chunk-G5UZTODF.js";
8
+ import "./chunk-ESH3LPYQ.js";
9
9
  export {
10
10
  createServer,
11
11
  loadConfig
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  IntelligenceService
3
- } from "./chunk-C6ZZH3XI.js";
4
- import "./chunk-NG7OR6GO.js";
3
+ } from "./chunk-G5UZTODF.js";
4
+ import "./chunk-ESH3LPYQ.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-2TLRE2L3.js";
6
+ } from "./chunk-INXI6PO7.js";
7
7
  import {
8
8
  isReadOnlyKey
9
- } from "./chunk-NG7OR6GO.js";
9
+ } from "./chunk-ESH3LPYQ.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.162.0",
3
+ "version": "4.163.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",
@@ -41,7 +41,7 @@
41
41
  },
42
42
  "dependencies": {
43
43
  "@anthropic-ai/sdk": "^0.91.1",
44
- "@canonry/aeo-audit": "4.6.2",
44
+ "@canonry/aeo-audit": "4.7.0",
45
45
  "@fastify/rate-limit": "^11.2.0",
46
46
  "@fastify/static": "^9.1.1",
47
47
  "@google/genai": "^1.46.0",
@@ -71,28 +71,28 @@
71
71
  "tsup": "^8.5.1",
72
72
  "tsx": "^4.19.0",
73
73
  "@ainyc/canonry-api-client": "0.0.0",
74
- "@ainyc/canonry-config": "0.0.0",
75
- "@ainyc/canonry-integration-bing": "0.0.0",
74
+ "@ainyc/canonry-api-routes": "0.0.0",
76
75
  "@ainyc/canonry-contracts": "0.0.0",
77
76
  "@ainyc/canonry-db": "0.0.0",
77
+ "@ainyc/canonry-config": "0.0.0",
78
+ "@ainyc/canonry-integration-bing": "0.0.0",
78
79
  "@ainyc/canonry-integration-cloudflare-queue": "0.0.0",
79
80
  "@ainyc/canonry-integration-cloudflare-worker": "0.0.0",
80
- "@ainyc/canonry-api-routes": "0.0.0",
81
- "@ainyc/canonry-integration-cloud-run": "0.0.0",
82
81
  "@ainyc/canonry-integration-openai-ads": "0.0.0",
83
- "@ainyc/canonry-integration-google": "0.0.0",
84
82
  "@ainyc/canonry-integration-commoncrawl": "0.0.0",
83
+ "@ainyc/canonry-integration-cloud-run": "0.0.0",
84
+ "@ainyc/canonry-integration-google": "0.0.0",
85
+ "@ainyc/canonry-integration-google-business-profile": "0.0.0",
85
86
  "@ainyc/canonry-integration-google-places": "0.0.0",
86
87
  "@ainyc/canonry-integration-traffic": "0.0.0",
87
- "@ainyc/canonry-integration-google-business-profile": "0.0.0",
88
88
  "@ainyc/canonry-integration-wordpress": "0.0.0",
89
- "@ainyc/canonry-provider-claude": "0.0.0",
90
89
  "@ainyc/canonry-provider-cdp": "0.0.0",
91
- "@ainyc/canonry-provider-gemini": "0.0.0",
90
+ "@ainyc/canonry-provider-claude": "0.0.0",
92
91
  "@ainyc/canonry-intelligence": "0.0.0",
93
- "@ainyc/canonry-provider-openai": "0.0.0",
92
+ "@ainyc/canonry-provider-gemini": "0.0.0",
94
93
  "@ainyc/canonry-provider-local": "0.0.0",
95
- "@ainyc/canonry-provider-perplexity": "0.0.0"
94
+ "@ainyc/canonry-provider-perplexity": "0.0.0",
95
+ "@ainyc/canonry-provider-openai": "0.0.0"
96
96
  },
97
97
  "scripts": {
98
98
  "build": "tsx scripts/copy-agent-assets.ts && tsup && tsx build-web.ts",