@canonry/canonry 6.1.4 → 6.1.5

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.
@@ -19,21 +19,21 @@ import {
19
19
  runWithUsageTags,
20
20
  saveConfigPatch,
21
21
  sentimentInstallReadiness
22
- } from "./chunk-YOMLHHJS.js";
22
+ } from "./chunk-FRBKYQN7.js";
23
23
  import {
24
24
  computeFactorAverages,
25
25
  deleteSiteCrawlGraphLayout,
26
26
  persistSiteCrawlGraphLayout,
27
27
  prepareSiteCrawlGraphLayout,
28
28
  recordedSharePct
29
- } from "./chunk-HB6XZOZ6.js";
29
+ } from "./chunk-MSFBNFTI.js";
30
30
  import {
31
31
  CanonryMcpToolNames,
32
32
  CliError,
33
33
  PACKAGE_VERSION,
34
34
  canonryMcpTools,
35
35
  isMachineFormat
36
- } from "./chunk-6CR7DWLU.js";
36
+ } from "./chunk-5QH72CTN.js";
37
37
  import {
38
38
  CC_CACHE_DIR,
39
39
  DUCKDB_SPEC,
@@ -214,7 +214,7 @@ import {
214
214
  siteLivenessState,
215
215
  toAlertView,
216
216
  usageCounters
217
- } from "./chunk-N7MRAN3G.js";
217
+ } from "./chunk-MTEVU6KG.js";
218
218
  import {
219
219
  AGENT_MEMORY_VALUE_MAX_BYTES,
220
220
  AGENT_NONE,
@@ -414,7 +414,7 @@ import {
414
414
  visibilityReportRequestSchema,
415
415
  winnabilityClassLabel,
416
416
  withRetry
417
- } from "./chunk-4MWLHTRS.js";
417
+ } from "./chunk-J7LV4CS2.js";
418
418
 
419
419
  // src/runtime-context.ts
420
420
  function cliRuntimeContext(env = process.env, stdio = process) {
@@ -7830,7 +7830,7 @@ function nonBlank(value) {
7830
7830
  return trimmed ? trimmed : void 0;
7831
7831
  }
7832
7832
  function resolveBuildCommit(env = process.env) {
7833
- const embedded = true ? "5bfed51c11b95f292c522e93568efee2f164c4ed" : void 0;
7833
+ const embedded = true ? "07710f04d6bdd8ec8b4374a93f0f3c3d1b56f498" : void 0;
7834
7834
  return nonBlank(embedded) ?? nonBlank(env.CANONRY_COMMIT);
7835
7835
  }
7836
7836
  function resolveInstanceIdentity(env = process.env) {
@@ -7845,6 +7845,7 @@ import crypto6 from "crypto";
7845
7845
  import fs4 from "fs";
7846
7846
  import path3 from "path";
7847
7847
  import os3 from "os";
7848
+ import { setImmediate as yieldToEventLoop } from "timers/promises";
7848
7849
  import { and as and3, asc as asc2, count, eq as eq3, inArray, isNotNull, isNull, ne, sql as sql2 } from "drizzle-orm";
7849
7850
 
7850
7851
  // src/run-telemetry.ts
@@ -8115,6 +8116,8 @@ async function runWithConcurrency(items, limit, worker) {
8115
8116
  await Promise.all(Array.from({ length: cap }, next));
8116
8117
  }
8117
8118
  var PROVIDER_FANOUT_DEFAULT = 8;
8119
+ var BATCH_INGEST_CHUNK_SIZE = 32;
8120
+ var BATCH_INGEST_PAYLOAD_BYTES = 1024 * 1024;
8118
8121
  var SYNC_SLOT_DISPATCH = {
8119
8122
  idempotent: false,
8120
8123
  mode: ProviderDispatchModes.sync,
@@ -9350,10 +9353,10 @@ var JobRunner = class {
9350
9353
  /**
9351
9354
  * Read an ended batch's results into its run: every line mapped by
9352
9355
  * `custom_id` to its slot, parsed by the adapter's own parser and recorded
9353
- * through `recordSlot`, exactly like a sync answer but at the batch tier.
9356
+ * through the shared slot preparation, like a sync answer at the batch tier.
9354
9357
  *
9355
- * Idempotent across crashes. Each line's outcome is written as soon as it is
9356
- * handled and a handled line is skipped on the next pass; the insert does
9358
+ * Idempotent across crashes. Bounded chunks commit each snapshot together
9359
+ * with its outcome; handled lines are skipped on the next pass. The insert does
9357
9360
  * nothing on a slot that is already answered; the reservation of unbilled
9358
9361
  * lines is released under `quota_released`, in the same transaction that
9359
9362
  * marks the batch `ingested`. Answers are scored against the project's
@@ -9375,30 +9378,74 @@ var JobRunner = class {
9375
9378
  const requests = new Map(this.db.select().from(providerBatchRequests).where(eq3(providerBatchRequests.batchId, batch.id)).all().map((row) => [row.id, row]));
9376
9379
  const ctx = { ...this.buildRunRecordingContext(batch.runId, batch.projectId), onInserted: () => {
9377
9380
  } };
9381
+ const pending = [];
9382
+ let pendingBytes = 0;
9383
+ const queued = /* @__PURE__ */ new Set();
9384
+ const flush = () => {
9385
+ if (pending.length === 0) return true;
9386
+ const chunk = pending.splice(0);
9387
+ pendingBytes = 0;
9388
+ const settled = this.persistBatchLines(batch, chunk);
9389
+ if (!settled) return false;
9390
+ for (const result2 of settled) {
9391
+ const request = requests.get(result2.line.requestId);
9392
+ requests.set(request.id, { ...request, outcome: result2.outcome, error: result2.line.error });
9393
+ result2.line.slot?.report(result2.inserted);
9394
+ result2.line.report?.();
9395
+ }
9396
+ queued.clear();
9397
+ return true;
9398
+ };
9378
9399
  try {
9400
+ let linesSinceYield = 0;
9379
9401
  for await (const line of capability.results(batch.providerBatchId, registered.config)) {
9402
+ if (linesSinceYield === BATCH_INGEST_CHUNK_SIZE) {
9403
+ await yieldToEventLoop();
9404
+ linesSinceYield = 0;
9405
+ }
9406
+ linesSinceYield++;
9380
9407
  const request = requests.get(line.customId);
9381
9408
  if (!request) {
9382
9409
  log2.warn("batch.unknown-line", { batchId: batch.id, provider: batch.provider, customId: line.customId });
9383
9410
  continue;
9384
9411
  }
9385
- if (request.outcome !== null) continue;
9386
- if (this.db.select({ status: providerBatches.status }).from(providerBatches).where(eq3(providerBatches.id, batch.id)).get()?.status !== ProviderBatchStatuses.ended) {
9387
- return { kind: "cancelled" };
9412
+ if (request.outcome !== null || queued.has(request.id)) continue;
9413
+ if (this.db.select({ status: providerBatches.status }).from(providerBatches).where(eq3(providerBatches.id, batch.id)).get()?.status !== ProviderBatchStatuses.ended) return { kind: "cancelled" };
9414
+ const prepared = await this.prepareBatchLine(ctx, registered, batch, request, line);
9415
+ const payloadBytes = Buffer.byteLength(prepared.slot?.snapshot.rawResponse ?? "") + Buffer.byteLength(prepared.slot?.snapshot.answerText ?? "") + Buffer.byteLength(prepared.error ?? "");
9416
+ if (pending.length > 0 && pendingBytes + payloadBytes > BATCH_INGEST_PAYLOAD_BYTES) {
9417
+ if (!flush()) return { kind: "cancelled" };
9418
+ await yieldToEventLoop();
9419
+ linesSinceYield = 0;
9420
+ }
9421
+ pending.push(prepared);
9422
+ pendingBytes += payloadBytes;
9423
+ queued.add(request.id);
9424
+ if (pending.length === BATCH_INGEST_CHUNK_SIZE || pendingBytes >= BATCH_INGEST_PAYLOAD_BYTES) {
9425
+ if (!flush()) return { kind: "cancelled" };
9426
+ await yieldToEventLoop();
9427
+ linesSinceYield = 0;
9388
9428
  }
9389
- const settled = await this.ingestBatchLine(ctx, registered, batch, request, line);
9390
- this.db.update(providerBatchRequests).set({ outcome: settled.outcome, error: settled.error }).where(and3(eq3(providerBatchRequests.id, request.id), isNull(providerBatchRequests.outcome))).run();
9391
- requests.set(request.id, { ...request, outcome: settled.outcome });
9392
9429
  }
9430
+ if (!flush()) return { kind: "cancelled" };
9393
9431
  } catch (err) {
9394
- if (!(err instanceof RunCancelledError)) throw err;
9432
+ let failure2 = err;
9433
+ if (!(failure2 instanceof RunCancelledError)) {
9434
+ try {
9435
+ if (!flush()) return { kind: "cancelled" };
9436
+ } catch (flushError) {
9437
+ failure2 = flushError;
9438
+ }
9439
+ }
9440
+ if (!(failure2 instanceof RunCancelledError)) throw failure2;
9395
9441
  this.markBatchesCancelled([batch.id], "Cancelled because its run is no longer running.");
9396
9442
  return { kind: "cancelled" };
9397
9443
  }
9398
9444
  return this.completeBatchIngest(batch);
9399
9445
  }
9400
- async ingestBatchLine(ctx, registered, batch, request, line) {
9401
- if (line.type !== "succeeded") return { outcome: unansweredOutcome(line.type), error: line.error };
9446
+ async prepareBatchLine(ctx, registered, batch, request, line) {
9447
+ const base = { requestId: request.id, slot: null };
9448
+ if (line.type !== "succeeded") return { ...base, outcome: unansweredOutcome(line.type), error: line.error };
9402
9449
  const { adapter } = registered;
9403
9450
  if (!adapter.parseTrackedQueryResponse) throw new Error(`Provider ${adapter.name} cannot read a batch answer`);
9404
9451
  let raw;
@@ -9406,34 +9453,67 @@ var JobRunner = class {
9406
9453
  raw = adapter.parseTrackedQueryResponse(line.body, resolveProviderModel(adapter.name, request.requestedModel));
9407
9454
  } catch (err) {
9408
9455
  const error = describeError(err);
9409
- log2.warn("batch.parse-failed", { runId: batch.runId, batchId: batch.id, provider: batch.provider, executionId: request.executionId, error });
9410
- return { outcome: ProviderBatchRequestOutcomes.parse_failed, error };
9456
+ return {
9457
+ ...base,
9458
+ outcome: ProviderBatchRequestOutcomes.parse_failed,
9459
+ error,
9460
+ report: () => log2.warn("batch.parse-failed", { runId: batch.runId, batchId: batch.id, provider: batch.provider, executionId: request.executionId, error })
9461
+ };
9411
9462
  }
9412
- const unit = {
9463
+ const slot = await this.prepareSlot(ctx, registered, {
9413
9464
  executionId: request.executionId,
9414
9465
  queryText: request.queryText,
9415
9466
  context: request.requestedContext,
9416
9467
  queryId: request.queryId,
9417
9468
  requestedModel: request.requestedModel
9418
- };
9419
- const written = await this.recordSlot(ctx, registered, unit, raw, {
9469
+ }, raw, {
9420
9470
  idempotent: true,
9421
9471
  mode: ProviderDispatchModes.batch,
9422
9472
  providerBatchId: batch.id,
9423
9473
  pricingTier: PricingTiers.batch
9424
9474
  });
9425
- if (written) return { outcome: ProviderBatchRequestOutcomes.recorded, error: null };
9426
- const existing = this.db.select({ providerBatchId: querySnapshots.providerBatchId }).from(querySnapshots).where(and3(
9427
- eq3(querySnapshots.runId, batch.runId),
9428
- eq3(querySnapshots.measurementExecutionId, request.executionId),
9429
- eq3(querySnapshots.provider, registered.adapter.name)
9430
- )).get();
9431
- return existing?.providerBatchId === batch.id ? { outcome: ProviderBatchRequestOutcomes.recorded, error: null } : { outcome: ProviderBatchRequestOutcomes.duplicate, error: null };
9475
+ return { requestId: request.id, slot, outcome: ProviderBatchRequestOutcomes.recorded, error: null };
9476
+ }
9477
+ /** Snapshots and their replay ledger commit together, with no callbacks or awaits. */
9478
+ persistBatchLines(batch, lines) {
9479
+ return this.db.transaction((tx) => {
9480
+ if (tx.select({ status: providerBatches.status }).from(providerBatches).where(eq3(providerBatches.id, batch.id)).get()?.status !== ProviderBatchStatuses.ended) return null;
9481
+ if (tx.select({ status: runs.status }).from(runs).where(eq3(runs.id, batch.runId)).get()?.status !== RunStatuses.running) throw new RunCancelledError(batch.runId);
9482
+ const current = new Map(tx.select({
9483
+ id: providerBatchRequests.id,
9484
+ outcome: providerBatchRequests.outcome,
9485
+ queryId: providerBatchRequests.queryId,
9486
+ executionId: providerBatchRequests.executionId
9487
+ }).from(providerBatchRequests).where(inArray(providerBatchRequests.id, lines.map((line) => line.requestId))).all().map((row) => [row.id, row]));
9488
+ const settled = [];
9489
+ for (const line of lines) {
9490
+ const request = current.get(line.requestId);
9491
+ if (!request || request.outcome !== null) continue;
9492
+ current.delete(line.requestId);
9493
+ let outcome = line.outcome;
9494
+ let inserted = false;
9495
+ if (line.slot) {
9496
+ const snapshot = { ...line.slot.snapshot, queryId: request.queryId };
9497
+ inserted = tx.insert(querySnapshots).values(snapshot).onConflictDoNothing().run().changes > 0;
9498
+ if (!inserted) {
9499
+ const existing = tx.select({ providerBatchId: querySnapshots.providerBatchId }).from(querySnapshots).where(and3(
9500
+ eq3(querySnapshots.runId, batch.runId),
9501
+ eq3(querySnapshots.measurementExecutionId, request.executionId),
9502
+ eq3(querySnapshots.provider, batch.provider)
9503
+ )).get();
9504
+ outcome = existing?.providerBatchId === batch.id ? ProviderBatchRequestOutcomes.recorded : ProviderBatchRequestOutcomes.duplicate;
9505
+ }
9506
+ }
9507
+ tx.update(providerBatchRequests).set({ outcome, error: line.error }).where(and3(eq3(providerBatchRequests.id, request.id), isNull(providerBatchRequests.outcome))).run();
9508
+ settled.push({ line, outcome, inserted });
9509
+ }
9510
+ return settled;
9511
+ }, { behavior: "immediate" });
9432
9512
  }
9433
9513
  /** Close an ingest: counts, the unbilled lines' quota, and `ingested`, in one transaction. */
9434
9514
  completeBatchIngest(batch) {
9435
9515
  const at = (/* @__PURE__ */ new Date()).toISOString();
9436
- return this.db.transaction((tx) => {
9516
+ const result2 = this.db.transaction((tx) => {
9437
9517
  const txDb = tx;
9438
9518
  const current = txDb.select().from(providerBatches).where(eq3(providerBatches.id, batch.id)).get();
9439
9519
  if (current?.status !== ProviderBatchStatuses.ended) return { kind: "skipped" };
@@ -9449,9 +9529,19 @@ var JobRunner = class {
9449
9529
  updatedAt: at
9450
9530
  }).where(and3(eq3(providerBatches.id, batch.id), eq3(providerBatches.status, ProviderBatchStatuses.ended))).run();
9451
9531
  const { recordedCount: recorded, notRecorded } = tally;
9452
- log2.info("batch.ingested", { runId: batch.runId, batchId: batch.id, provider: batch.provider, recorded, notRecorded, released });
9453
9532
  return { kind: "ingested", recorded, notRecorded, released };
9454
9533
  });
9534
+ if (result2.kind === "ingested") {
9535
+ log2.info("batch.ingested", {
9536
+ runId: batch.runId,
9537
+ batchId: batch.id,
9538
+ provider: batch.provider,
9539
+ recorded: result2.recorded,
9540
+ notRecorded: result2.notRecorded,
9541
+ released: result2.released
9542
+ });
9543
+ }
9544
+ return result2;
9455
9545
  }
9456
9546
  /**
9457
9547
  * Give up on an ended batch whose results cannot be read in time. It
@@ -9742,6 +9832,15 @@ var JobRunner = class {
9742
9832
  * writes nothing and resolves false.
9743
9833
  */
9744
9834
  async recordSlot(ctx, registeredProvider, unit, raw, dispatch) {
9835
+ const prepared = await this.prepareSlot(ctx, registeredProvider, unit, raw, dispatch);
9836
+ this.throwIfRunCancelled(ctx.runId);
9837
+ const insert = this.db.insert(querySnapshots).values(prepared.snapshot);
9838
+ const written = ctx.fill || dispatch.idempotent ? insert.onConflictDoNothing().run() : insert.run();
9839
+ prepared.report(written.changes > 0);
9840
+ return written.changes > 0;
9841
+ }
9842
+ /** Resolve network/file evidence and derived fields before opening a write transaction. */
9843
+ async prepareSlot(ctx, registeredProvider, unit, raw, dispatch) {
9745
9844
  const { adapter } = registeredProvider;
9746
9845
  const providerName = adapter.name;
9747
9846
  const { domains: competitorDomains, aliases: competitorAliases } = ctx.competitorsFor(unit.executionId);
@@ -9798,7 +9897,7 @@ var JobRunner = class {
9798
9897
  fs4.renameSync(raw.screenshotPath, destPath);
9799
9898
  screenshotRelPath = `${ctx.runId}/${snapshotId}.png`;
9800
9899
  }
9801
- const insert = this.db.insert(querySnapshots).values({
9900
+ const snapshot = {
9802
9901
  id: snapshotId,
9803
9902
  runId: ctx.runId,
9804
9903
  queryId: unit.queryId,
@@ -9850,20 +9949,23 @@ var JobRunner = class {
9850
9949
  overrides: registeredProvider.config.pricing
9851
9950
  }),
9852
9951
  createdAt: (/* @__PURE__ */ new Date()).toISOString()
9853
- });
9854
- const written = ctx.fill || dispatch.idempotent ? insert.onConflictDoNothing().run() : insert.run();
9855
- if (written.changes > 0) ctx.onInserted();
9856
- ctx.fill?.onOutcome(providerName, true);
9857
- log2.info("query.citation", {
9858
- runId: ctx.runId,
9859
- provider: providerName,
9860
- query: unit.queryText,
9861
- executionId: unit.executionId,
9862
- location: requestedContext?.label ?? null,
9863
- citationState,
9864
- answerMentioned
9865
- });
9866
- return written.changes > 0;
9952
+ };
9953
+ return {
9954
+ snapshot,
9955
+ report: (inserted) => {
9956
+ if (inserted) ctx.onInserted();
9957
+ ctx.fill?.onOutcome(providerName, true);
9958
+ log2.info("query.citation", {
9959
+ runId: ctx.runId,
9960
+ provider: providerName,
9961
+ query: unit.queryText,
9962
+ executionId: unit.executionId,
9963
+ location: requestedContext?.label ?? null,
9964
+ citationState,
9965
+ answerMentioned
9966
+ });
9967
+ }
9968
+ };
9867
9969
  }
9868
9970
  /**
9869
9971
  * Rebuild a run's recording identity from the database, for a path that
@@ -13968,8 +14070,10 @@ async function executeSiteAudit(db, runId, projectId, opts = {}) {
13968
14070
  }
13969
14071
 
13970
14072
  // src/commands/backfill.ts
13971
- import { and as and15, eq as eq17, inArray as inArray7, isNull as isNull2, sql as sql7 } from "drizzle-orm";
14073
+ import { setImmediate as yieldToEventLoop2 } from "timers/promises";
14074
+ import { and as and15, asc as asc4, desc as desc7, eq as eq17, gt as gt3, inArray as inArray7, isNull as isNull2, lte as lte2, sql as sql7 } from "drizzle-orm";
13972
14075
  var SNAPSHOT_BATCH_SIZE = 500;
14076
+ var PATH_REPAIR_PAGE_SIZE = 128;
13973
14077
  async function backfillAnswerVisibilityCommand(opts) {
13974
14078
  const config = loadConfig();
13975
14079
  const db = createClient(config.database);
@@ -14150,35 +14254,54 @@ No DB writes performed. Re-run without --dry-run to apply.`);
14150
14254
  }
14151
14255
  }
14152
14256
  function backfillNormalizedPaths(db, opts) {
14153
- const baseConditions = [];
14154
- if (opts?.projectId) {
14155
- baseConditions.push(eq17(gaTrafficSnapshots.projectId, opts.projectId));
14156
- }
14157
- const rows = db.select({
14158
- id: gaTrafficSnapshots.id,
14159
- landingPage: gaTrafficSnapshots.landingPage,
14160
- landingPageNormalized: gaTrafficSnapshots.landingPageNormalized
14161
- }).from(gaTrafficSnapshots).where(baseConditions.length > 0 ? and15(...baseConditions) : void 0).all();
14257
+ return repairStoredPaths(db, gaTrafficSnapshots, opts);
14258
+ }
14259
+ async function repairStoredPaths(db, table, opts) {
14260
+ const pageSize = opts?.pageSize ?? PATH_REPAIR_PAGE_SIZE;
14261
+ const projectScope = opts?.projectId ? sql7`+${table.projectId} = ${opts.projectId}` : void 0;
14262
+ const lastId = db.select({ id: table.id }).from(table).where(projectScope).orderBy(desc7(table.id)).limit(1).get()?.id;
14263
+ if (lastId === void 0) return { examined: 0, updated: 0, unchanged: 0 };
14264
+ let cursor;
14265
+ let examined = 0;
14162
14266
  let updated = 0;
14163
- let unchanged = 0;
14164
- if (rows.length > 0) {
14165
- db.transaction((tx) => {
14166
- for (const row of rows) {
14167
- const next = normalizeUrlPath(row.landingPage);
14168
- if (next === null) {
14169
- unchanged++;
14170
- continue;
14171
- }
14172
- if (row.landingPageNormalized === next) {
14173
- unchanged++;
14174
- continue;
14175
- }
14176
- tx.update(gaTrafficSnapshots).set({ landingPageNormalized: next }).where(eq17(gaTrafficSnapshots.id, row.id)).run();
14177
- updated++;
14178
- }
14267
+ for (; ; ) {
14268
+ const rows = db.select({
14269
+ id: table.id,
14270
+ projectId: table.projectId,
14271
+ landingPage: table.landingPage,
14272
+ landingPageNormalized: table.landingPageNormalized
14273
+ }).from(table).where(and15(
14274
+ projectScope,
14275
+ lte2(table.id, lastId),
14276
+ cursor === void 0 ? void 0 : gt3(table.id, cursor)
14277
+ )).orderBy(asc4(table.id)).limit(pageSize).all();
14278
+ examined += rows.length;
14279
+ const changes = rows.flatMap((row) => {
14280
+ const next = normalizeUrlPath(row.landingPage);
14281
+ return next === null || row.landingPageNormalized === next ? [] : [{ row, next }];
14179
14282
  });
14283
+ if (changes.length > 0) {
14284
+ const written = db.transaction((tx) => {
14285
+ let written2 = 0;
14286
+ for (const { row, next } of changes) {
14287
+ written2 += tx.update(table).set({ landingPageNormalized: next }).where(and15(
14288
+ eq17(table.id, row.id),
14289
+ eq17(table.projectId, row.projectId),
14290
+ eq17(table.landingPage, row.landingPage),
14291
+ row.landingPageNormalized === null ? isNull2(table.landingPageNormalized) : eq17(table.landingPageNormalized, row.landingPageNormalized)
14292
+ )).run().changes;
14293
+ }
14294
+ return written2;
14295
+ });
14296
+ updated += written;
14297
+ if (written < changes.length) opts?.onConflict?.();
14298
+ }
14299
+ if (rows.length < pageSize) break;
14300
+ cursor = rows.at(-1).id;
14301
+ if (cursor === lastId) break;
14302
+ await yieldToEventLoop2();
14180
14303
  }
14181
- return { examined: rows.length, updated, unchanged };
14304
+ return { examined, updated, unchanged: examined - updated };
14182
14305
  }
14183
14306
  async function backfillNormalizedPathsCommand(opts) {
14184
14307
  const config = loadConfig();
@@ -14204,7 +14327,7 @@ async function backfillNormalizedPathsCommand(opts) {
14204
14327
  }
14205
14328
  projectId = project.id;
14206
14329
  }
14207
- const { examined, updated, unchanged } = backfillNormalizedPaths(db, { projectId });
14330
+ const { examined, updated, unchanged } = await backfillNormalizedPaths(db, { projectId });
14208
14331
  const result2 = {
14209
14332
  project: projectFilter ?? null,
14210
14333
  examined,
@@ -14222,35 +14345,7 @@ async function backfillNormalizedPathsCommand(opts) {
14222
14345
  console.log(` Unchanged: ${unchanged}`);
14223
14346
  }
14224
14347
  function backfillAiReferralPaths(db, opts) {
14225
- const baseConditions = [];
14226
- if (opts?.projectId) {
14227
- baseConditions.push(eq17(gaAiReferrals.projectId, opts.projectId));
14228
- }
14229
- const rows = db.select({
14230
- id: gaAiReferrals.id,
14231
- landingPage: gaAiReferrals.landingPage,
14232
- landingPageNormalized: gaAiReferrals.landingPageNormalized
14233
- }).from(gaAiReferrals).where(baseConditions.length > 0 ? and15(...baseConditions) : void 0).all();
14234
- let updated = 0;
14235
- let unchanged = 0;
14236
- if (rows.length > 0) {
14237
- db.transaction((tx) => {
14238
- for (const row of rows) {
14239
- const next = normalizeUrlPath(row.landingPage);
14240
- if (next === null) {
14241
- unchanged++;
14242
- continue;
14243
- }
14244
- if (row.landingPageNormalized === next) {
14245
- unchanged++;
14246
- continue;
14247
- }
14248
- tx.update(gaAiReferrals).set({ landingPageNormalized: next }).where(eq17(gaAiReferrals.id, row.id)).run();
14249
- updated++;
14250
- }
14251
- });
14252
- }
14253
- return { examined: rows.length, updated, unchanged };
14348
+ return repairStoredPaths(db, gaAiReferrals, opts);
14254
14349
  }
14255
14350
  async function backfillAiReferralPathsCommand(opts) {
14256
14351
  const config = loadConfig();
@@ -14276,7 +14371,7 @@ async function backfillAiReferralPathsCommand(opts) {
14276
14371
  }
14277
14372
  projectId = project.id;
14278
14373
  }
14279
- const { examined, updated, unchanged } = backfillAiReferralPaths(db, { projectId });
14374
+ const { examined, updated, unchanged } = await backfillAiReferralPaths(db, { projectId });
14280
14375
  const result2 = {
14281
14376
  project: projectFilter ?? null,
14282
14377
  examined,
@@ -14454,7 +14549,7 @@ function readStoredGroundingSources(rawResponse) {
14454
14549
  return result2;
14455
14550
  }
14456
14551
  async function backfillInsightsCommand(project, opts) {
14457
- const { IntelligenceService: IntelligenceService2 } = await import("./intelligence-service-QUAOWEIA.js");
14552
+ const { IntelligenceService: IntelligenceService2 } = await import("./intelligence-service-JYGP6LME.js");
14458
14553
  const config = loadConfig();
14459
14554
  const db = createClient(config.database);
14460
14555
  migrate(db);
@@ -15871,7 +15966,7 @@ async function refreshAllIntegrations(client, projectName, now = /* @__PURE__ */
15871
15966
  }
15872
15967
 
15873
15968
  // src/notifier.ts
15874
- import { eq as eq20, desc as desc7, and as and18, inArray as inArray10, or } from "drizzle-orm";
15969
+ import { eq as eq20, desc as desc8, and as and18, inArray as inArray10, or } from "drizzle-orm";
15875
15970
  import crypto21 from "crypto";
15876
15971
  var log19 = createLogger("Notifier");
15877
15972
  var MATERIAL_MAGNITUDE_DELTA = 20;
@@ -16412,7 +16507,7 @@ var Notifier = class {
16412
16507
  eq20(runs.kind, thisRun.kind),
16413
16508
  or(eq20(runs.status, "completed"), eq20(runs.status, "partial"))
16414
16509
  )
16415
- ).orderBy(desc7(runs.createdAt), desc7(runs.id)).limit(RECENT_FETCH_LIMIT).all();
16510
+ ).orderBy(desc8(runs.createdAt), desc8(runs.id)).limit(RECENT_FETCH_LIMIT).all();
16416
16511
  const groups = groupRunsByCreatedAt(recentRuns);
16417
16512
  const currentGroupIdx = groups.findIndex((g) => g[0]?.createdAt === thisRun.createdAt);
16418
16513
  if (currentGroupIdx < 0) return [];
@@ -18631,7 +18726,7 @@ async function loadExternalMcpTools(servers, opts = {}) {
18631
18726
 
18632
18727
  // src/agent/memory-store.ts
18633
18728
  import crypto24 from "crypto";
18634
- import { and as and19, desc as desc8, eq as eq22, like, sql as sql10, or as or2 } from "drizzle-orm";
18729
+ import { and as and19, desc as desc9, eq as eq22, like, sql as sql10, or as or2 } from "drizzle-orm";
18635
18730
  var COMPACTION_KEY_PREFIX = "compaction:";
18636
18731
  var COMPACTION_NOTES_PER_SESSION = 3;
18637
18732
  function rowToDto(row) {
@@ -18645,7 +18740,7 @@ function rowToDto(row) {
18645
18740
  };
18646
18741
  }
18647
18742
  function listMemoryEntries(db, projectId, opts = {}) {
18648
- const query = db.select().from(agentMemory).where(eq22(agentMemory.projectId, projectId)).orderBy(desc8(agentMemory.updatedAt));
18743
+ const query = db.select().from(agentMemory).where(eq22(agentMemory.projectId, projectId)).orderBy(desc9(agentMemory.updatedAt));
18649
18744
  const rows = opts.limit === void 0 ? query.all() : query.limit(opts.limit).all();
18650
18745
  return rows.map(rowToDto);
18651
18746
  }
@@ -18691,7 +18786,7 @@ function loadRecentForHydrate(db, projectId, limit, sessionId) {
18691
18786
  return db.select().from(agentMemory).where(and19(
18692
18787
  eq22(agentMemory.projectId, projectId),
18693
18788
  or2(sql10`substr(${agentMemory.key}, 1, ${COMPACTION_KEY_PREFIX.length}) <> ${COMPACTION_KEY_PREFIX}`, sessionId ? sql10`substr(${agentMemory.key}, 1, ${sessionPrefix.length}) = ${sessionPrefix}` : void 0)
18694
- )).orderBy(desc8(agentMemory.updatedAt)).limit(limit).all().map(rowToDto);
18789
+ )).orderBy(desc9(agentMemory.updatedAt)).limit(limit).all().map(rowToDto);
18695
18790
  }
18696
18791
  function writeCompactionNote(db, args) {
18697
18792
  if (Buffer.byteLength(args.summary, "utf8") > AGENT_MEMORY_VALUE_MAX_BYTES) {
@@ -18719,7 +18814,7 @@ function writeCompactionNote(db, args) {
18719
18814
  eq22(agentMemory.projectId, args.projectId),
18720
18815
  like(agentMemory.key, `${sessionPrefix}%`)
18721
18816
  )
18722
- ).orderBy(desc8(agentMemory.updatedAt)).all();
18817
+ ).orderBy(desc9(agentMemory.updatedAt)).all();
18723
18818
  const stale = existing.slice(COMPACTION_NOTES_PER_SESSION).map((r) => r.id);
18724
18819
  if (stale.length > 0) {
18725
18820
  tx.delete(agentMemory).where(sql10`${agentMemory.id} IN (${sql10.join(stale.map((s) => sql10`${s}`), sql10`, `)})`).run();
@@ -128,7 +128,7 @@ import {
128
128
  trafficSeriesGranularitySchema,
129
129
  visibilityCompareSelectionSchema,
130
130
  visibilityReportRequestSchema
131
- } from "./chunk-4MWLHTRS.js";
131
+ } from "./chunk-J7LV4CS2.js";
132
132
 
133
133
  // src/cli-error.ts
134
134
  function isMachineFormat(format) {
@@ -5,7 +5,7 @@ import {
5
5
  PACKAGE_VERSION,
6
6
  canonryMcpTools,
7
7
  isMachineFormat
8
- } from "./chunk-6CR7DWLU.js";
8
+ } from "./chunk-5QH72CTN.js";
9
9
  import {
10
10
  AGENT_PROVIDER_IDS,
11
11
  CANONRY_NPM_PACKAGE_URL,
@@ -50,7 +50,7 @@ import {
50
50
  skillsClientSchema,
51
51
  upgradeCaveatFor,
52
52
  upgradeCommandFor
53
- } from "./chunk-4MWLHTRS.js";
53
+ } from "./chunk-J7LV4CS2.js";
54
54
 
55
55
  // src/config.ts
56
56
  import fs from "fs";
@@ -3481,6 +3481,7 @@ function extractDomainsFromText(text) {
3481
3481
  function textContainsDomain(text, domain) {
3482
3482
  return extractDomainsFromText(text).some((candidate) => hostMatchesDomain(candidate, domain));
3483
3483
  }
3484
+ var URL_PATH_NORMALIZATION_VERSION = 1;
3484
3485
  function normalizeUrlPath(input) {
3485
3486
  if (input == null) return null;
3486
3487
  let trimmed = input.trim();
@@ -21378,6 +21379,7 @@ export {
21378
21379
  hostMatchesAnyDomain,
21379
21380
  extractDomainsFromText,
21380
21381
  textContainsDomain,
21382
+ URL_PATH_NORMALIZATION_VERSION,
21381
21383
  normalizeUrlPath,
21382
21384
  brandKeyFromText,
21383
21385
  prepareBrandMatchText,
@@ -5,7 +5,7 @@ import {
5
5
  siteCrawlGraphNodes,
6
6
  siteCrawlPages,
7
7
  siteCrawlSnapshots
8
- } from "./chunk-N7MRAN3G.js";
8
+ } from "./chunk-MTEVU6KG.js";
9
9
  import {
10
10
  SITE_CRAWL_GRAPH_MAX_EDGES,
11
11
  SITE_CRAWL_GRAPH_MAX_NODES,
@@ -13,7 +13,7 @@ import {
13
13
  TEMPLATE_LINK_RATIO_THRESHOLD,
14
14
  factorStatusFromScore,
15
15
  roundPreservingTotal
16
- } from "./chunk-4MWLHTRS.js";
16
+ } from "./chunk-J7LV4CS2.js";
17
17
 
18
18
  // src/site-audit-factors.ts
19
19
  function recordedSharePct(factor) {
@@ -869,7 +869,7 @@ import {
869
869
  wordpressSchemaDeployResultDtoSchema,
870
870
  wordpressSchemaStatusResultDtoSchema,
871
871
  wordpressStatusDtoSchema
872
- } from "./chunk-4MWLHTRS.js";
872
+ } from "./chunk-J7LV4CS2.js";
873
873
 
874
874
  // src/intelligence-service.ts
875
875
  import { eq as eq82, desc as desc36, asc as asc15, and as and69, ne as ne14, or as or20, inArray as inArray32, gte as gte22, lte as lte20, isNull as isNull16, sql as sql31, exists } from "drizzle-orm";
@@ -912,6 +912,7 @@ __export(schema_exports, {
912
912
  conversionTrackingContracts: () => conversionTrackingContracts,
913
913
  crawlerEventsHourly: () => crawlerEventsHourly,
914
914
  crawlerVerificationManifestsHourly: () => crawlerVerificationManifestsHourly,
915
+ dataRepairCompletions: () => dataRepairCompletions,
915
916
  discoveryProbes: () => discoveryProbes,
916
917
  discoverySessions: () => discoverySessions,
917
918
  doctorHealthState: () => doctorHealthState,
@@ -1527,6 +1528,11 @@ var runtimeLogMetadata = sqliteTable("runtime_log_metadata", {
1527
1528
  dropped: integer("dropped").notNull().default(0),
1528
1529
  captureErrors: integer("capture_errors").notNull().default(0)
1529
1530
  });
1531
+ var dataRepairCompletions = sqliteTable("data_repair_completions", {
1532
+ name: text("name").primaryKey().notNull(),
1533
+ version: integer("version").notNull(),
1534
+ completedAt: text("completed_at").notNull()
1535
+ });
1530
1536
  var apiKeys = sqliteTable("api_keys", {
1531
1537
  id: text("id").primaryKey(),
1532
1538
  name: text("name").notNull(),
@@ -8191,6 +8197,17 @@ var MIGRATION_VERSIONS = [
8191
8197
  statements: [
8192
8198
  `ALTER TABLE projects ADD COLUMN qualified_aliases TEXT NOT NULL DEFAULT '[]'`
8193
8199
  ]
8200
+ },
8201
+ {
8202
+ version: 167,
8203
+ name: "data-repair-completions",
8204
+ statements: [
8205
+ `CREATE TABLE IF NOT EXISTS data_repair_completions (
8206
+ name TEXT PRIMARY KEY NOT NULL,
8207
+ version INTEGER NOT NULL,
8208
+ completed_at TEXT NOT NULL
8209
+ )`
8210
+ ]
8194
8211
  }
8195
8212
  ];
8196
8213
  var AERO_LEDGER_REBUILDS = [
@@ -8578,11 +8595,11 @@ var OperationalLogStore = class {
8578
8595
  append(event) {
8579
8596
  try {
8580
8597
  const entry = projectEvent(event);
8581
- if (Buffer.byteLength(JSON.stringify(entry), "utf8") > MAX_ENTRY_BYTES) {
8598
+ const entryBytes = Buffer.byteLength(JSON.stringify(entry), "utf8");
8599
+ if (entryBytes > MAX_ENTRY_BYTES) {
8582
8600
  throw new RangeError(`Operational log entry exceeds ${MAX_ENTRY_BYTES} bytes.`);
8583
8601
  }
8584
8602
  this.withoutLockWait(() => this.db.transaction((tx) => {
8585
- this.prune(tx);
8586
8603
  const metadata2 = readMetadata(tx);
8587
8604
  tx.run(sql3`
8588
8605
  INSERT INTO runtime_logs (
@@ -8590,12 +8607,12 @@ var OperationalLogStore = class {
8590
8607
  ) VALUES (
8591
8608
  ${metadata2.nextSequence}, ${entry.ts}, ${entry.level}, ${entry.module}, ${entry.action}, ${entry.message ?? null},
8592
8609
  ${entry.projectId ?? null}, ${entry.runId ?? null}, ${entry.context.actor ?? null}, ${entry.context.requestId ?? null},
8593
- ${JSON.stringify(entry.context)}, ${Buffer.byteLength(JSON.stringify(entry), "utf8")}
8610
+ ${JSON.stringify(entry.context)}, ${entryBytes}
8594
8611
  )
8595
8612
  `);
8596
8613
  tx.run(sql3`UPDATE runtime_log_metadata SET next_sequence = ${metadata2.nextSequence + 1} WHERE id = ${METADATA_ID}`);
8597
8614
  this.prune(tx);
8598
- }));
8615
+ }, { behavior: "immediate" }));
8599
8616
  } catch {
8600
8617
  this.recordCaptureError();
8601
8618
  }
@@ -92232,6 +92249,7 @@ export {
92232
92249
  providerBatches,
92233
92250
  providerBatchRequests,
92234
92251
  auditLog,
92252
+ dataRepairCompletions,
92235
92253
  apiKeys,
92236
92254
  schedules,
92237
92255
  insightNotifyState,
@@ -4,14 +4,14 @@ import {
4
4
  installSkills,
5
5
  loadConfigRaw,
6
6
  saveConfigPatch
7
- } from "./chunk-YOMLHHJS.js";
7
+ } from "./chunk-FRBKYQN7.js";
8
8
  import {
9
9
  PACKAGE_VERSION
10
- } from "./chunk-6CR7DWLU.js";
10
+ } from "./chunk-5QH72CTN.js";
11
11
  import {
12
12
  SKILL_MANIFEST_FILENAME,
13
13
  SkillsClients
14
- } from "./chunk-4MWLHTRS.js";
14
+ } from "./chunk-J7LV4CS2.js";
15
15
 
16
16
  // src/skills-autosync.ts
17
17
  import fs from "fs";
package/dist/cli.js CHANGED
@@ -35,11 +35,11 @@ import {
35
35
  trackCliCommandFinished,
36
36
  trackEvent,
37
37
  waitForServerRuntimeStartup
38
- } from "./chunk-5LZLDXEN.js";
38
+ } from "./chunk-4UEX44C3.js";
39
39
  import {
40
40
  autoSyncSkills,
41
41
  formatAutoSyncNotice
42
- } from "./chunk-TBAVVIVI.js";
42
+ } from "./chunk-PAYC6TQ2.js";
43
43
  import {
44
44
  configExists,
45
45
  createApiClient,
@@ -56,13 +56,13 @@ import {
56
56
  saveConfig,
57
57
  saveConfigPatch,
58
58
  shouldPrintServeSkillsNudge
59
- } from "./chunk-YOMLHHJS.js";
59
+ } from "./chunk-FRBKYQN7.js";
60
60
  import {
61
61
  DEFAULT_DEMO_TRUSTED_PROXIES,
62
62
  trustedProxiesProblem,
63
63
  trustedProxyProblem
64
64
  } from "./chunk-RB2F4D3Z.js";
65
- import "./chunk-HB6XZOZ6.js";
65
+ import "./chunk-MSFBNFTI.js";
66
66
  import {
67
67
  CliError,
68
68
  EXIT_SYSTEM_ERROR,
@@ -74,7 +74,7 @@ import {
74
74
  runMeasurementDraftAction,
75
75
  systemError,
76
76
  usageError
77
- } from "./chunk-6CR7DWLU.js";
77
+ } from "./chunk-5QH72CTN.js";
78
78
  import {
79
79
  CLOUDFLARE_WORKER_BINDINGS,
80
80
  CLOUDFLARE_WORKER_GENERATED_MARKER,
@@ -82,6 +82,7 @@ import {
82
82
  DEFAULT_BOT_LIST,
83
83
  apiKeys,
84
84
  createClient,
85
+ dataRepairCompletions,
85
86
  generateWorkerScript,
86
87
  generateWranglerToml,
87
88
  migrate,
@@ -89,7 +90,7 @@ import {
89
90
  queries,
90
91
  renderReportHtml,
91
92
  runs
92
- } from "./chunk-N7MRAN3G.js";
93
+ } from "./chunk-MTEVU6KG.js";
93
94
  import {
94
95
  AdsDeliverySnapshotStatuses,
95
96
  AdsHistoricalCampaignRollupStatuses,
@@ -116,6 +117,7 @@ import {
116
117
  TrafficEventKinds,
117
118
  TrafficSeriesGranularities,
118
119
  UNATTRIBUTED_MENTION_REASON,
120
+ URL_PATH_NORMALIZATION_VERSION,
119
121
  USER_PASSWORD_MIN_LENGTH,
120
122
  UserRoles,
121
123
  adsActivateTreeRequestSchema,
@@ -196,7 +198,7 @@ import {
196
198
  visibilityCompareSelectionSchema,
197
199
  visibilityReportRequestSchema,
198
200
  winnabilityClassSchema
199
- } from "./chunk-4MWLHTRS.js";
201
+ } from "./chunk-J7LV4CS2.js";
200
202
 
201
203
  // src/cli.ts
202
204
  import { pathToFileURL } from "url";
@@ -730,7 +732,7 @@ function parseDemoTrustedProxies(values) {
730
732
  async function demoCommand(options) {
731
733
  const { host, port } = parseDemoListenOptions(options);
732
734
  const trustProxy = parseDemoTrustedProxies(options.trustProxy);
733
- const { createDemoServer } = await import("./demo-server-2622GU2H.js");
735
+ const { createDemoServer } = await import("./demo-server-UGILQVEC.js");
734
736
  const app = await createDemoServer({ trustProxy });
735
737
  let stopping = false;
736
738
  const stop = () => {
@@ -16458,7 +16460,7 @@ function encodeLegacySetupState(state) {
16458
16460
  }
16459
16461
 
16460
16462
  // src/commands/serve.ts
16461
- import { and, asc, eq as eq2, ne } from "drizzle-orm";
16463
+ import { and, asc, eq as eq3, ne } from "drizzle-orm";
16462
16464
 
16463
16465
  // src/server-shutdown.ts
16464
16466
  async function closeWithIdleSweep(app, intervalMs = 250) {
@@ -16471,6 +16473,33 @@ async function closeWithIdleSweep(app, intervalMs = 250) {
16471
16473
  }
16472
16474
  }
16473
16475
 
16476
+ // src/startup-path-repairs.ts
16477
+ import { eq as eq2, lt } from "drizzle-orm";
16478
+ var STARTUP_REPAIR_PAGE_SIZE = 4096;
16479
+ function repairNormalizedPathsOnStartup(db) {
16480
+ return repairPathsOnce(db, "ga-traffic-paths", backfillNormalizedPaths);
16481
+ }
16482
+ function repairAiReferralPathsOnStartup(db) {
16483
+ return repairPathsOnce(db, "ga-ai-referral-paths", backfillAiReferralPaths);
16484
+ }
16485
+ async function repairPathsOnce(db, name, repair) {
16486
+ const completed = db.select({ version: dataRepairCompletions.version }).from(dataRepairCompletions).where(eq2(dataRepairCompletions.name, name)).get();
16487
+ if (completed && completed.version >= URL_PATH_NORMALIZATION_VERSION) return null;
16488
+ let conflicted = false;
16489
+ const result = await repair(db, { pageSize: STARTUP_REPAIR_PAGE_SIZE, onConflict: () => {
16490
+ conflicted = true;
16491
+ } });
16492
+ if (!conflicted) {
16493
+ const completion = { version: URL_PATH_NORMALIZATION_VERSION, completedAt: (/* @__PURE__ */ new Date()).toISOString() };
16494
+ db.insert(dataRepairCompletions).values({ name, ...completion }).onConflictDoUpdate({
16495
+ target: dataRepairCompletions.name,
16496
+ set: completion,
16497
+ setWhere: lt(dataRepairCompletions.version, URL_PATH_NORMALIZATION_VERSION)
16498
+ }).run();
16499
+ }
16500
+ return result;
16501
+ }
16502
+
16474
16503
  // src/agent-plugin.ts
16475
16504
  import fs18 from "fs";
16476
16505
  import path12 from "path";
@@ -16683,7 +16712,7 @@ function readServeOpenState(db) {
16683
16712
  projectId: runs.projectId,
16684
16713
  status: runs.status
16685
16714
  }).from(runs).where(and(
16686
- eq2(runs.kind, RunKinds["site-audit"]),
16715
+ eq3(runs.kind, RunKinds["site-audit"]),
16687
16716
  ne(runs.trigger, RunTriggers.probe)
16688
16717
  )).all();
16689
16718
  scanned = new Set(
@@ -16718,8 +16747,8 @@ async function serveCommand(format = "text") {
16718
16747
  const db = createClient(config.database);
16719
16748
  migrate(db);
16720
16749
  try {
16721
- const result = backfillNormalizedPaths(db);
16722
- if (result.updated > 0 && format === "text") {
16750
+ const result = await repairNormalizedPathsOnStartup(db);
16751
+ if (result && result.updated > 0 && format === "text") {
16723
16752
  console.log(
16724
16753
  `Migrated ${result.updated} GA landing-page row${result.updated === 1 ? "" : "s"} to canonical form.`
16725
16754
  );
@@ -16730,8 +16759,8 @@ async function serveCommand(format = "text") {
16730
16759
  `);
16731
16760
  }
16732
16761
  try {
16733
- const result = backfillAiReferralPaths(db);
16734
- if (result.updated > 0 && format === "text") {
16762
+ const result = await repairAiReferralPathsOnStartup(db);
16763
+ if (result && result.updated > 0 && format === "text") {
16735
16764
  console.log(
16736
16765
  `Migrated ${result.updated} GA AI referral row${result.updated === 1 ? "" : "s"} to canonical form.`
16737
16766
  );
@@ -5,11 +5,11 @@ import {
5
5
  computeFactorAverages,
6
6
  layoutSiteCrawlGraphInput,
7
7
  persistSiteCrawlGraphLayout
8
- } from "./chunk-HB6XZOZ6.js";
8
+ } from "./chunk-MSFBNFTI.js";
9
9
  import {
10
10
  PACKAGE_VERSION,
11
11
  canonryMcpTools
12
- } from "./chunk-6CR7DWLU.js";
12
+ } from "./chunk-5QH72CTN.js";
13
13
  import {
14
14
  HISTORY_WINDOW_RUNS,
15
15
  IntelligenceService,
@@ -85,7 +85,7 @@ import {
85
85
  siteCrawlPages,
86
86
  siteCrawlSnapshots,
87
87
  trafficSources
88
- } from "./chunk-N7MRAN3G.js";
88
+ } from "./chunk-MTEVU6KG.js";
89
89
  import {
90
90
  RunKinds,
91
91
  SiteCrawlFetchStates,
@@ -112,7 +112,7 @@ import {
112
112
  roundPreservingTotal,
113
113
  siteAuditPageFactorSchema,
114
114
  wilsonInterval
115
- } from "./chunk-4MWLHTRS.js";
115
+ } from "./chunk-J7LV4CS2.js";
116
116
 
117
117
  // src/demo-server.ts
118
118
  import { dirname, join as join2 } from "path";
package/dist/index.js CHANGED
@@ -3,14 +3,14 @@ import {
3
3
  createGoogleMarketingCredentialStore,
4
4
  createGoogleMarketingRuntime,
5
5
  createServer
6
- } from "./chunk-5LZLDXEN.js";
6
+ } from "./chunk-4UEX44C3.js";
7
7
  import {
8
8
  loadConfig
9
- } from "./chunk-YOMLHHJS.js";
10
- import "./chunk-HB6XZOZ6.js";
11
- import "./chunk-6CR7DWLU.js";
12
- import "./chunk-N7MRAN3G.js";
13
- import "./chunk-4MWLHTRS.js";
9
+ } from "./chunk-FRBKYQN7.js";
10
+ import "./chunk-MSFBNFTI.js";
11
+ import "./chunk-5QH72CTN.js";
12
+ import "./chunk-MTEVU6KG.js";
13
+ import "./chunk-J7LV4CS2.js";
14
14
  export {
15
15
  GoogleMarketingRuntimeError,
16
16
  createGoogleMarketingCredentialStore,
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  HISTORY_WINDOW_RUNS,
3
3
  IntelligenceService
4
- } from "./chunk-N7MRAN3G.js";
5
- import "./chunk-4MWLHTRS.js";
4
+ } from "./chunk-MTEVU6KG.js";
5
+ import "./chunk-J7LV4CS2.js";
6
6
  export {
7
7
  HISTORY_WINDOW_RUNS,
8
8
  IntelligenceService
package/dist/mcp.js CHANGED
@@ -1,15 +1,15 @@
1
1
  import {
2
2
  autoSyncSkills
3
- } from "./chunk-TBAVVIVI.js";
3
+ } from "./chunk-PAYC6TQ2.js";
4
4
  import {
5
5
  createApiClient,
6
6
  createCanonryMcpServer
7
- } from "./chunk-YOMLHHJS.js";
8
- import "./chunk-6CR7DWLU.js";
7
+ } from "./chunk-FRBKYQN7.js";
8
+ import "./chunk-5QH72CTN.js";
9
9
  import {
10
10
  isReadOnlyKey,
11
11
  updateCheckEnvOptOut
12
- } from "./chunk-4MWLHTRS.js";
12
+ } from "./chunk-J7LV4CS2.js";
13
13
 
14
14
  // src/mcp/cli.ts
15
15
  import { randomUUID } from "crypto";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@canonry/canonry",
3
- "version": "6.1.4",
3
+ "version": "6.1.5",
4
4
  "type": "module",
5
5
  "description": "Self-hosted AI visibility (AEO) platform: track how ChatGPT, Claude, Gemini, and Perplexity cite your domain, join it with Search Console, GA4, server-side traffic, and paid media, and fix what you find through agent tools (CLI, REST, MCP). Local SQLite.",
6
6
  "keywords": [
@@ -89,27 +89,27 @@
89
89
  "@ainyc/canonry-api-client": "0.0.0",
90
90
  "@ainyc/canonry-api-routes": "0.0.0",
91
91
  "@ainyc/canonry-config": "0.0.0",
92
- "@ainyc/canonry-contracts": "0.0.0",
93
92
  "@ainyc/canonry-db": "0.0.0",
93
+ "@ainyc/canonry-contracts": "0.0.0",
94
94
  "@ainyc/canonry-integration-bing": "0.0.0",
95
95
  "@ainyc/canonry-integration-cloud-run": "0.0.0",
96
96
  "@ainyc/canonry-integration-cloudflare-queue": "0.0.0",
97
- "@ainyc/canonry-integration-cloudflare-worker": "0.0.0",
98
97
  "@ainyc/canonry-integration-commoncrawl": "0.0.0",
98
+ "@ainyc/canonry-integration-cloudflare-worker": "0.0.0",
99
99
  "@ainyc/canonry-integration-google": "0.0.0",
100
- "@ainyc/canonry-integration-google-ads": "0.0.0",
101
- "@ainyc/canonry-integration-google-places": "0.0.0",
102
100
  "@ainyc/canonry-integration-google-business-profile": "0.0.0",
103
- "@ainyc/canonry-integration-openai-ads": "0.0.0",
101
+ "@ainyc/canonry-integration-google-ads": "0.0.0",
104
102
  "@ainyc/canonry-integration-google-tag-manager": "0.0.0",
103
+ "@ainyc/canonry-integration-openai-ads": "0.0.0",
105
104
  "@ainyc/canonry-integration-traffic": "0.0.0",
105
+ "@ainyc/canonry-intelligence": "0.0.0",
106
106
  "@ainyc/canonry-integration-wordpress": "0.0.0",
107
- "@ainyc/canonry-provider-cdp": "0.0.0",
107
+ "@ainyc/canonry-integration-google-places": "0.0.0",
108
108
  "@ainyc/canonry-provider-claude": "0.0.0",
109
- "@ainyc/canonry-intelligence": "0.0.0",
109
+ "@ainyc/canonry-provider-cdp": "0.0.0",
110
110
  "@ainyc/canonry-provider-gemini": "0.0.0",
111
- "@ainyc/canonry-provider-local": "0.0.0",
112
111
  "@ainyc/canonry-provider-muse": "0.0.0",
112
+ "@ainyc/canonry-provider-local": "0.0.0",
113
113
  "@ainyc/canonry-provider-perplexity": "0.0.0",
114
114
  "@ainyc/canonry-integration-typesafe": "0.0.0",
115
115
  "@ainyc/canonry-provider-openai": "0.0.0"