@ainyc/canonry 4.33.0 → 4.33.1

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.
@@ -10388,7 +10388,7 @@ var routeCatalog = [
10388
10388
  method: "post",
10389
10389
  path: "/api/v1/projects/{name}/discover/run",
10390
10390
  summary: "Start a tracked-basket discovery session",
10391
- description: 'Kicks off a discovery session for the project. The pipeline: ICP description \u2192 Gemini grounded seed prompt \u2192 embed + cluster (cosine \u2265 0.85 by default) \u2192 pick canonical representatives \u2192 probe each canonical via Gemini grounding \u2192 classify into cited / aspirational / wasted-surface \u2192 aggregate competitor map. Returns immediately with `{ runId, sessionId, status: "running" }`; the actual work runs in the background. Poll `GET /projects/{name}/discover/sessions/{id}` until `status` is `completed` or `failed`.',
10391
+ description: 'Kicks off a discovery session for the project. The pipeline: ICP description \u2192 Gemini grounded seed prompt \u2192 embed + cluster (cosine \u2265 0.85 by default) \u2192 pick canonical representatives \u2192 probe each canonical via Gemini grounding \u2192 classify into cited / aspirational / wasted-surface \u2192 aggregate competitor map. Returns immediately with `{ runId, sessionId, status: "running", consolidated }`; the actual work runs in the background. Poll `GET /projects/{name}/discover/sessions/{id}` until `status` is `completed` or `failed`. Concurrent/duplicate requests for the same (project, ICP) are consolidated onto a single in-flight session: the response carries `consolidated: true` and `200 OK` instead of `201`, and the request\'s `dedupThreshold` / `maxProbes` are ignored (the in-flight session keeps its original config).',
10392
10392
  tags: ["discovery"],
10393
10393
  parameters: [nameParameter],
10394
10394
  requestBody: {
@@ -10412,7 +10412,8 @@ var routeCatalog = [
10412
10412
  }
10413
10413
  },
10414
10414
  responses: {
10415
- 201: { description: "Discovery session enqueued; returns { runId, sessionId, status }." },
10415
+ 200: { description: "An in-flight session with the same project + ICP was reused; returns { runId, sessionId, status, consolidated: true }. The request's dedupThreshold / maxProbes are ignored." },
10416
+ 201: { description: "New discovery session enqueued; returns { runId, sessionId, status, consolidated: false }." },
10416
10417
  400: { description: "Missing or invalid ICP / parameters." },
10417
10418
  404: { description: "Project not found." }
10418
10419
  }
@@ -20009,7 +20010,8 @@ async function doctorRoutes(app, opts) {
20009
20010
 
20010
20011
  // ../api-routes/src/discovery/routes.ts
20011
20012
  import crypto21 from "crypto";
20012
- import { eq as eq25, desc as desc13 } from "drizzle-orm";
20013
+ import { and as and16, desc as desc13, eq as eq25, gte as gte4, inArray as inArray8 } from "drizzle-orm";
20014
+ var MAX_INFLIGHT_DISCOVERY_AGE_MS = 2 * 60 * 60 * 1e3;
20013
20015
  async function discoveryRoutes(app, opts) {
20014
20016
  app.post("/projects/:name/discover/run", async (request, reply) => {
20015
20017
  const project = resolveProject(app.db, request.params.name);
@@ -20038,9 +20040,23 @@ async function discoveryRoutes(app, opts) {
20038
20040
  });
20039
20041
  }
20040
20042
  const now = (/* @__PURE__ */ new Date()).toISOString();
20041
- const sessionId = crypto21.randomUUID();
20042
- const runId = crypto21.randomUUID();
20043
- app.db.transaction((tx) => {
20043
+ const ageFloorIso = new Date(Date.now() - MAX_INFLIGHT_DISCOVERY_AGE_MS).toISOString();
20044
+ const decision = app.db.transaction((tx) => {
20045
+ const existing = tx.select({ id: discoverySessions.id, runId: discoverySessions.runId }).from(discoverySessions).where(and16(
20046
+ eq25(discoverySessions.projectId, project.id),
20047
+ eq25(discoverySessions.icpDescription, icpDescription),
20048
+ inArray8(discoverySessions.status, [
20049
+ DiscoverySessionStatuses.queued,
20050
+ DiscoverySessionStatuses.seeding,
20051
+ DiscoverySessionStatuses.probing
20052
+ ]),
20053
+ gte4(discoverySessions.createdAt, ageFloorIso)
20054
+ )).orderBy(desc13(discoverySessions.createdAt)).get();
20055
+ if (existing && existing.runId) {
20056
+ return { reused: true, sessionId: existing.id, runId: existing.runId };
20057
+ }
20058
+ const sessionId = crypto21.randomUUID();
20059
+ const runId = crypto21.randomUUID();
20044
20060
  tx.insert(discoverySessions).values({
20045
20061
  id: sessionId,
20046
20062
  projectId: project.id,
@@ -20066,17 +20082,31 @@ async function discoveryRoutes(app, opts) {
20066
20082
  entityType: "discovery_session",
20067
20083
  entityId: sessionId
20068
20084
  });
20085
+ return { reused: false, sessionId, runId };
20069
20086
  });
20087
+ if (decision.reused) {
20088
+ return reply.status(200).send({
20089
+ runId: decision.runId,
20090
+ sessionId: decision.sessionId,
20091
+ status: "running",
20092
+ consolidated: true
20093
+ });
20094
+ }
20070
20095
  opts.onDiscoveryRunRequested({
20071
- runId,
20072
- sessionId,
20096
+ runId: decision.runId,
20097
+ sessionId: decision.sessionId,
20073
20098
  projectId: project.id,
20074
20099
  icpDescription,
20075
20100
  dedupThreshold: parsed.data.dedupThreshold,
20076
20101
  maxProbes: parsed.data.maxProbes,
20077
20102
  locations
20078
20103
  });
20079
- return reply.status(201).send({ runId, sessionId, status: "running" });
20104
+ return reply.status(201).send({
20105
+ runId: decision.runId,
20106
+ sessionId: decision.sessionId,
20107
+ status: "running",
20108
+ consolidated: false
20109
+ });
20080
20110
  });
20081
20111
  app.get(
20082
20112
  "/projects/:name/discover/sessions",
@@ -23328,7 +23358,7 @@ import crypto24 from "crypto";
23328
23358
  import fs7 from "fs";
23329
23359
  import path9 from "path";
23330
23360
  import os5 from "os";
23331
- import { and as and16, eq as eq27, inArray as inArray8, sql as sql10 } from "drizzle-orm";
23361
+ import { and as and17, eq as eq27, inArray as inArray9, sql as sql10 } from "drizzle-orm";
23332
23362
 
23333
23363
  // src/run-telemetry.ts
23334
23364
  import crypto23 from "crypto";
@@ -23669,7 +23699,7 @@ var JobRunner = class {
23669
23699
  this.registry = registry;
23670
23700
  }
23671
23701
  recoverStaleRuns() {
23672
- const stale = this.db.select({ id: runs.id, status: runs.status }).from(runs).where(inArray8(runs.status, ["running", "queued"])).all();
23702
+ const stale = this.db.select({ id: runs.id, status: runs.status }).from(runs).where(inArray9(runs.status, ["running", "queued"])).all();
23673
23703
  if (stale.length === 0) return;
23674
23704
  const now = (/* @__PURE__ */ new Date()).toISOString();
23675
23705
  for (const run of stale) {
@@ -23707,7 +23737,7 @@ var JobRunner = class {
23707
23737
  throw new Error(`Run ${runId} is not executable from status '${existingRun.status}'`);
23708
23738
  }
23709
23739
  if (existingRun.status === "queued") {
23710
- this.db.update(runs).set({ status: "running", startedAt: now }).where(and16(eq27(runs.id, runId), eq27(runs.status, "queued"))).run();
23740
+ this.db.update(runs).set({ status: "running", startedAt: now }).where(and17(eq27(runs.id, runId), eq27(runs.status, "queued"))).run();
23711
23741
  }
23712
23742
  this.throwIfRunCancelled(runId);
23713
23743
  const project = this.db.select().from(projects).where(eq27(projects.id, projectId)).get();
@@ -23732,7 +23762,7 @@ var JobRunner = class {
23732
23762
  }
23733
23763
  log.info("run.dispatch", { runId, providerCount: activeProviders.length, providers: activeProviders.map((p) => p.adapter.name) });
23734
23764
  const scopedQueryNames = parseJsonColumn(existingRun.queries, null);
23735
- projectQueries = scopedQueryNames ? this.db.select().from(queries).where(and16(eq27(queries.projectId, projectId), inArray8(queries.query, scopedQueryNames))).all() : this.db.select().from(queries).where(eq27(queries.projectId, projectId)).all();
23765
+ projectQueries = scopedQueryNames ? this.db.select().from(queries).where(and17(eq27(queries.projectId, projectId), inArray9(queries.query, scopedQueryNames))).all() : this.db.select().from(queries).where(eq27(queries.projectId, projectId)).all();
23736
23766
  const projectCompetitors = this.db.select().from(competitors).where(eq27(competitors.projectId, projectId)).all();
23737
23767
  const competitorDomains = projectCompetitors.map((c) => c.domain);
23738
23768
  const allDomains = effectiveDomains({
@@ -24068,7 +24098,7 @@ function buildPhases(input) {
24068
24098
 
24069
24099
  // src/gsc-sync.ts
24070
24100
  import crypto25 from "crypto";
24071
- import { eq as eq28, and as and17, sql as sql11 } from "drizzle-orm";
24101
+ import { eq as eq28, and as and18, sql as sql11 } from "drizzle-orm";
24072
24102
  var log2 = createLogger("GscSync");
24073
24103
  function formatDate3(d) {
24074
24104
  return d.toISOString().split("T")[0];
@@ -24120,7 +24150,7 @@ async function executeGscSync(db, runId, projectId, opts) {
24120
24150
  });
24121
24151
  log2.info("fetch.complete", { runId, projectId, rowCount: rows.length });
24122
24152
  db.delete(gscSearchData).where(
24123
- and17(
24153
+ and18(
24124
24154
  eq28(gscSearchData.projectId, projectId),
24125
24155
  sql11`${gscSearchData.date} >= ${startDate}`,
24126
24156
  sql11`${gscSearchData.date} <= ${endDate}`
@@ -24209,7 +24239,7 @@ async function executeGscSync(db, runId, projectId, opts) {
24209
24239
  }
24210
24240
  }
24211
24241
  const snapshotDate = formatDate3(/* @__PURE__ */ new Date());
24212
- db.delete(gscCoverageSnapshots).where(and17(eq28(gscCoverageSnapshots.projectId, projectId), eq28(gscCoverageSnapshots.date, snapshotDate))).run();
24242
+ db.delete(gscCoverageSnapshots).where(and18(eq28(gscCoverageSnapshots.projectId, projectId), eq28(gscCoverageSnapshots.date, snapshotDate))).run();
24213
24243
  db.insert(gscCoverageSnapshots).values({
24214
24244
  id: crypto25.randomUUID(),
24215
24245
  projectId,
@@ -24232,7 +24262,7 @@ async function executeGscSync(db, runId, projectId, opts) {
24232
24262
 
24233
24263
  // src/gsc-inspect-sitemap.ts
24234
24264
  import crypto26 from "crypto";
24235
- import { eq as eq29, and as and18 } from "drizzle-orm";
24265
+ import { eq as eq29, and as and19 } from "drizzle-orm";
24236
24266
 
24237
24267
  // src/sitemap-parser.ts
24238
24268
  var log3 = createLogger("SitemapParser");
@@ -24448,7 +24478,7 @@ async function executeInspectSitemap(db, runId, projectId, opts) {
24448
24478
  }
24449
24479
  }
24450
24480
  const snapshotDate = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
24451
- db.delete(gscCoverageSnapshots).where(and18(eq29(gscCoverageSnapshots.projectId, projectId), eq29(gscCoverageSnapshots.date, snapshotDate))).run();
24481
+ db.delete(gscCoverageSnapshots).where(and19(eq29(gscCoverageSnapshots.projectId, projectId), eq29(gscCoverageSnapshots.date, snapshotDate))).run();
24452
24482
  db.insert(gscCoverageSnapshots).values({
24453
24483
  id: crypto26.randomUUID(),
24454
24484
  projectId,
@@ -24659,7 +24689,7 @@ async function executeBingInspectSitemap(db, runId, projectId, opts) {
24659
24689
  // src/commoncrawl-sync.ts
24660
24690
  import crypto28 from "crypto";
24661
24691
  import path10 from "path";
24662
- import { and as and19, eq as eq31, sql as sql12 } from "drizzle-orm";
24692
+ import { and as and20, eq as eq31, sql as sql12 } from "drizzle-orm";
24663
24693
  var log6 = createLogger("CommonCrawlSync");
24664
24694
  var INSERT_CHUNK_SIZE = 1e4;
24665
24695
  function defaultDeps() {
@@ -24850,7 +24880,7 @@ function computeSummary(rows) {
24850
24880
  // src/backlink-extract.ts
24851
24881
  import crypto29 from "crypto";
24852
24882
  import fs8 from "fs";
24853
- import { and as and20, desc as desc15, eq as eq32 } from "drizzle-orm";
24883
+ import { and as and21, desc as desc15, eq as eq32 } from "drizzle-orm";
24854
24884
  var log7 = createLogger("BacklinkExtract");
24855
24885
  function defaultDeps2() {
24856
24886
  return {
@@ -24896,7 +24926,7 @@ async function executeBacklinkExtract(db, runId, projectId, opts = {}) {
24896
24926
  const targetDomain = project.canonicalDomain;
24897
24927
  db.transaction((tx) => {
24898
24928
  tx.delete(backlinkDomains).where(
24899
- and20(eq32(backlinkDomains.projectId, projectId), eq32(backlinkDomains.release, release))
24929
+ and21(eq32(backlinkDomains.projectId, projectId), eq32(backlinkDomains.release, release))
24900
24930
  ).run();
24901
24931
  if (rows.length > 0) {
24902
24932
  const values = rows.map((r) => ({
@@ -25313,7 +25343,7 @@ var ProviderRegistry = class {
25313
25343
 
25314
25344
  // src/scheduler.ts
25315
25345
  import cron from "node-cron";
25316
- import { and as and21, eq as eq34 } from "drizzle-orm";
25346
+ import { and as and22, eq as eq34 } from "drizzle-orm";
25317
25347
  var log9 = createLogger("Scheduler");
25318
25348
  function taskKey(projectId, kind) {
25319
25349
  return `${projectId}::${kind}`;
@@ -25358,7 +25388,7 @@ var Scheduler = class {
25358
25388
  this.stopTask(key, existing, "Stopped");
25359
25389
  this.tasks.delete(key);
25360
25390
  }
25361
- const schedule = this.db.select().from(schedules).where(and21(eq34(schedules.projectId, projectId), eq34(schedules.kind, kind))).get();
25391
+ const schedule = this.db.select().from(schedules).where(and22(eq34(schedules.projectId, projectId), eq34(schedules.kind, kind))).get();
25362
25392
  if (schedule && schedule.enabled === 1) {
25363
25393
  this.registerCronTask(schedule);
25364
25394
  }
@@ -25482,7 +25512,7 @@ var Scheduler = class {
25482
25512
  };
25483
25513
 
25484
25514
  // src/notifier.ts
25485
- import { eq as eq35, desc as desc16, and as and22, inArray as inArray9, or as or4 } from "drizzle-orm";
25515
+ import { eq as eq35, desc as desc16, and as and23, inArray as inArray10, or as or4 } from "drizzle-orm";
25486
25516
  import crypto31 from "crypto";
25487
25517
  var log10 = createLogger("Notifier");
25488
25518
  var Notifier = class {
@@ -25589,7 +25619,7 @@ var Notifier = class {
25589
25619
  computeTransitions(runId, projectId) {
25590
25620
  const thisRun = this.db.select().from(runs).where(eq35(runs.id, runId)).get();
25591
25621
  if (!thisRun) return [];
25592
- const groupSiblings = this.db.select().from(runs).where(and22(
25622
+ const groupSiblings = this.db.select().from(runs).where(and23(
25593
25623
  eq35(runs.projectId, projectId),
25594
25624
  eq35(runs.kind, thisRun.kind),
25595
25625
  eq35(runs.createdAt, thisRun.createdAt)
@@ -25615,7 +25645,7 @@ var Notifier = class {
25615
25645
  );
25616
25646
  const RECENT_FETCH_LIMIT = Math.max(8, locationCount * 4);
25617
25647
  const recentRuns = this.db.select().from(runs).where(
25618
- and22(
25648
+ and23(
25619
25649
  eq35(runs.projectId, projectId),
25620
25650
  eq35(runs.kind, thisRun.kind),
25621
25651
  or4(eq35(runs.status, "completed"), eq35(runs.status, "partial"))
@@ -25635,13 +25665,13 @@ var Notifier = class {
25635
25665
  provider: querySnapshots.provider,
25636
25666
  location: querySnapshots.location,
25637
25667
  citationState: querySnapshots.citationState
25638
- }).from(querySnapshots).leftJoin(queries, eq35(querySnapshots.queryId, queries.id)).where(inArray9(querySnapshots.runId, currentRunIds)).all();
25668
+ }).from(querySnapshots).leftJoin(queries, eq35(querySnapshots.queryId, queries.id)).where(inArray10(querySnapshots.runId, currentRunIds)).all();
25639
25669
  const previousSnapshots = this.db.select({
25640
25670
  queryId: querySnapshots.queryId,
25641
25671
  provider: querySnapshots.provider,
25642
25672
  location: querySnapshots.location,
25643
25673
  citationState: querySnapshots.citationState
25644
- }).from(querySnapshots).where(inArray9(querySnapshots.runId, previousRunIds)).all();
25674
+ }).from(querySnapshots).where(inArray10(querySnapshots.runId, previousRunIds)).all();
25645
25675
  const prevMap = /* @__PURE__ */ new Map();
25646
25676
  for (const s of previousSnapshots) {
25647
25677
  prevMap.set(`${s.queryId}:${s.provider}:${s.location ?? ""}`, s.citationState);
@@ -26152,7 +26182,7 @@ function resolveSessionProviderAndModel(config, opts) {
26152
26182
 
26153
26183
  // src/agent/memory-store.ts
26154
26184
  import crypto32 from "crypto";
26155
- import { and as and23, desc as desc17, eq as eq37, like as like2, sql as sql13 } from "drizzle-orm";
26185
+ import { and as and24, desc as desc17, eq as eq37, like as like2, sql as sql13 } from "drizzle-orm";
26156
26186
  var COMPACTION_KEY_PREFIX = "compaction:";
26157
26187
  var COMPACTION_NOTES_PER_SESSION = 3;
26158
26188
  function rowToDto2(row) {
@@ -26197,12 +26227,12 @@ function upsertMemoryEntry(db, args) {
26197
26227
  updatedAt: now
26198
26228
  }
26199
26229
  }).run();
26200
- const row = db.select().from(agentMemory).where(and23(eq37(agentMemory.projectId, args.projectId), eq37(agentMemory.key, args.key))).get();
26230
+ const row = db.select().from(agentMemory).where(and24(eq37(agentMemory.projectId, args.projectId), eq37(agentMemory.key, args.key))).get();
26201
26231
  if (!row) throw new Error("memory upsert produced no row");
26202
26232
  return rowToDto2(row);
26203
26233
  }
26204
26234
  function deleteMemoryEntry(db, projectId, key) {
26205
- const result = db.delete(agentMemory).where(and23(eq37(agentMemory.projectId, projectId), eq37(agentMemory.key, key))).run();
26235
+ const result = db.delete(agentMemory).where(and24(eq37(agentMemory.projectId, projectId), eq37(agentMemory.key, key))).run();
26206
26236
  const changes = result.changes ?? 0;
26207
26237
  return changes > 0;
26208
26238
  }
@@ -26231,7 +26261,7 @@ function writeCompactionNote(db, args) {
26231
26261
  }).run();
26232
26262
  const sessionPrefix = `${COMPACTION_KEY_PREFIX}${args.sessionId}:`;
26233
26263
  const existing = tx.select({ id: agentMemory.id, updatedAt: agentMemory.updatedAt }).from(agentMemory).where(
26234
- and23(
26264
+ and24(
26235
26265
  eq37(agentMemory.projectId, args.projectId),
26236
26266
  like2(agentMemory.key, `${sessionPrefix}%`)
26237
26267
  )
@@ -26240,7 +26270,7 @@ function writeCompactionNote(db, args) {
26240
26270
  if (stale.length > 0) {
26241
26271
  tx.delete(agentMemory).where(sql13`${agentMemory.id} IN (${sql13.join(stale.map((s) => sql13`${s}`), sql13`, `)})`).run();
26242
26272
  }
26243
- const row = tx.select().from(agentMemory).where(and23(eq37(agentMemory.projectId, args.projectId), eq37(agentMemory.key, key))).get();
26273
+ const row = tx.select().from(agentMemory).where(and24(eq37(agentMemory.projectId, args.projectId), eq37(agentMemory.key, key))).get();
26244
26274
  if (row) inserted = rowToDto2(row);
26245
26275
  });
26246
26276
  if (!inserted) throw new Error("compaction note write produced no row");
package/dist/cli.js CHANGED
@@ -20,7 +20,7 @@ import {
20
20
  setTelemetrySource,
21
21
  showFirstRunNotice,
22
22
  trackEvent
23
- } from "./chunk-JJHBPITI.js";
23
+ } from "./chunk-DZENHID5.js";
24
24
  import {
25
25
  CliError,
26
26
  EXIT_SYSTEM_ERROR,
@@ -2020,10 +2020,17 @@ Sessions already started (recover with \`canonry discover show ${project} <id>\`
2020
2020
  }
2021
2021
  for (const { angle, start } of runs2) {
2022
2022
  if (angle) console.log(`[${angle}]`);
2023
- console.log(`Discovery run started: ${start.runId}`);
2024
- console.log(` Session: ${start.sessionId}`);
2025
- console.log(` Status: ${start.status}`);
2026
- console.log(` Tail: canonry discover show ${project} ${start.sessionId}`);
2023
+ if (start.consolidated) {
2024
+ console.log(`Reusing in-flight discovery session: ${start.sessionId}`);
2025
+ console.log(` Run: ${start.runId}`);
2026
+ console.log(` Status: ${start.status}`);
2027
+ console.log(` Tail: canonry discover show ${project} ${start.sessionId}`);
2028
+ } else {
2029
+ console.log(`Discovery run started: ${start.runId}`);
2030
+ console.log(` Session: ${start.sessionId}`);
2031
+ console.log(` Status: ${start.status}`);
2032
+ console.log(` Tail: canonry discover show ${project} ${start.sessionId}`);
2033
+ }
2027
2034
  if (runs2.length > 1) console.log();
2028
2035
  }
2029
2036
  return;
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  createServer
3
- } from "./chunk-JJHBPITI.js";
3
+ } from "./chunk-DZENHID5.js";
4
4
  import {
5
5
  loadConfig
6
6
  } from "./chunk-5EBN7736.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ainyc/canonry",
3
- "version": "4.33.0",
3
+ "version": "4.33.1",
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,21 +61,21 @@
61
61
  "tsup": "^8.5.1",
62
62
  "tsx": "^4.19.0",
63
63
  "@ainyc/canonry-api-routes": "0.0.0",
64
+ "@ainyc/canonry-config": "0.0.0",
64
65
  "@ainyc/canonry-contracts": "0.0.0",
65
- "@ainyc/canonry-intelligence": "0.0.0",
66
+ "@ainyc/canonry-integration-bing": "0.0.0",
66
67
  "@ainyc/canonry-db": "0.0.0",
68
+ "@ainyc/canonry-intelligence": "0.0.0",
67
69
  "@ainyc/canonry-integration-cloud-run": "0.0.0",
68
- "@ainyc/canonry-config": "0.0.0",
69
- "@ainyc/canonry-integration-bing": "0.0.0",
70
- "@ainyc/canonry-integration-google": "0.0.0",
70
+ "@ainyc/canonry-integration-traffic": "0.0.0",
71
+ "@ainyc/canonry-provider-cdp": "0.0.0",
71
72
  "@ainyc/canonry-integration-commoncrawl": "0.0.0",
73
+ "@ainyc/canonry-integration-google": "0.0.0",
72
74
  "@ainyc/canonry-integration-wordpress": "0.0.0",
73
- "@ainyc/canonry-provider-cdp": "0.0.0",
74
75
  "@ainyc/canonry-provider-gemini": "0.0.0",
75
- "@ainyc/canonry-integration-traffic": "0.0.0",
76
+ "@ainyc/canonry-provider-openai": "0.0.0",
76
77
  "@ainyc/canonry-provider-claude": "0.0.0",
77
78
  "@ainyc/canonry-provider-perplexity": "0.0.0",
78
- "@ainyc/canonry-provider-openai": "0.0.0",
79
79
  "@ainyc/canonry-provider-local": "0.0.0"
80
80
  },
81
81
  "scripts": {