@canonry/canonry 5.13.0 → 5.14.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.
- package/dist/{chunk-IPGBK7XR.js → chunk-2W6GCJ3O.js} +1 -1
- package/dist/{chunk-UWJAATGC.js → chunk-45EGDRVF.js} +28 -0
- package/dist/{chunk-IDZQ5H3J.js → chunk-4LPV6ZZY.js} +2 -2
- package/dist/{chunk-Q35D2R2P.js → chunk-RGMUT5KY.js} +97 -43
- package/dist/{chunk-TDHRUXN3.js → chunk-S6LJSUZO.js} +35 -19
- package/dist/{chunk-6YLNO2T5.js → chunk-SOLFOKZF.js} +2 -2
- package/dist/cli.js +7 -7
- package/dist/{demo-server-IZFTJI7E.js → demo-server-H4ZFIIIB.js} +3 -3
- package/dist/index.js +5 -5
- package/dist/{intelligence-service-PM7MC5VC.js → intelligence-service-CJKOXPOP.js} +2 -2
- package/dist/mcp.js +3 -3
- package/package.json +10 -10
|
@@ -12143,6 +12143,33 @@ function categorizeSourceWithCompetitors(uri, competitorDomains, isCompetitorMat
|
|
|
12143
12143
|
}
|
|
12144
12144
|
return base;
|
|
12145
12145
|
}
|
|
12146
|
+
var LISTING_MARKETPLACE_DOMAINS = [
|
|
12147
|
+
"apartmentfinder.com",
|
|
12148
|
+
"apartmentguide.com",
|
|
12149
|
+
"apartmenthomeliving.com",
|
|
12150
|
+
"apartmentlist.com",
|
|
12151
|
+
"apartmentratings.com",
|
|
12152
|
+
"apartments.com",
|
|
12153
|
+
"craigslist.org",
|
|
12154
|
+
"forrent.com",
|
|
12155
|
+
"homes.com",
|
|
12156
|
+
"hotpads.com",
|
|
12157
|
+
"padmapper.com",
|
|
12158
|
+
"realtor.com",
|
|
12159
|
+
"redfin.com",
|
|
12160
|
+
"rent.com",
|
|
12161
|
+
"rentable.co",
|
|
12162
|
+
"rentals.com",
|
|
12163
|
+
"rentcafe.com",
|
|
12164
|
+
"student.com",
|
|
12165
|
+
"trulia.com",
|
|
12166
|
+
"zillow.com",
|
|
12167
|
+
"zumper.com"
|
|
12168
|
+
];
|
|
12169
|
+
function isListingMarketplace(domainOrUri) {
|
|
12170
|
+
const domain = hostOf(domainOrUri) ?? domainOrUri.trim().toLowerCase();
|
|
12171
|
+
return LISTING_MARKETPLACE_DOMAINS.some((marketplace) => hostMatchesDomain(domain, marketplace));
|
|
12172
|
+
}
|
|
12146
12173
|
function categoryLabel(category) {
|
|
12147
12174
|
return CATEGORY_LABELS[category];
|
|
12148
12175
|
}
|
|
@@ -19739,6 +19766,7 @@ export {
|
|
|
19739
19766
|
shareOfVoiceSummary,
|
|
19740
19767
|
categorizeSource,
|
|
19741
19768
|
categorizeSourceWithCompetitors,
|
|
19769
|
+
isListingMarketplace,
|
|
19742
19770
|
categoryLabel,
|
|
19743
19771
|
cosineSimilarity,
|
|
19744
19772
|
clusterByCosine,
|
|
@@ -5,12 +5,12 @@ import {
|
|
|
5
5
|
siteCrawlGraphNodes,
|
|
6
6
|
siteCrawlPages,
|
|
7
7
|
siteCrawlSnapshots
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-RGMUT5KY.js";
|
|
9
9
|
import {
|
|
10
10
|
SITE_CRAWL_GRAPH_MAX_EDGES,
|
|
11
11
|
SITE_CRAWL_GRAPH_MAX_NODES,
|
|
12
12
|
TEMPLATE_LINK_RATIO_THRESHOLD
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-45EGDRVF.js";
|
|
14
14
|
|
|
15
15
|
// src/site-crawl-graph-layout.ts
|
|
16
16
|
import crypto from "crypto";
|
|
@@ -404,6 +404,7 @@ import {
|
|
|
404
404
|
internalError,
|
|
405
405
|
intersectScopes,
|
|
406
406
|
isBrowserProvider,
|
|
407
|
+
isListingMarketplace,
|
|
407
408
|
isLocationRedirectStatus,
|
|
408
409
|
isReadOnlyKey,
|
|
409
410
|
isRetryableHttpError,
|
|
@@ -783,10 +784,10 @@ import {
|
|
|
783
784
|
wordpressSchemaDeployResultDtoSchema,
|
|
784
785
|
wordpressSchemaStatusResultDtoSchema,
|
|
785
786
|
wordpressStatusDtoSchema
|
|
786
|
-
} from "./chunk-
|
|
787
|
+
} from "./chunk-45EGDRVF.js";
|
|
787
788
|
|
|
788
789
|
// src/intelligence-service.ts
|
|
789
|
-
import { eq as
|
|
790
|
+
import { eq as eq71, desc as desc32, asc as asc12, and as and60, ne as ne11, or as or18, inArray as inArray27, gte as gte18, lte as lte15, isNull as isNull13, sql as sql28, exists } from "drizzle-orm";
|
|
790
791
|
|
|
791
792
|
// ../db/src/client.ts
|
|
792
793
|
import { mkdirSync } from "fs";
|
|
@@ -19691,12 +19692,12 @@ function upsertCompetitor(authoring, body) {
|
|
|
19691
19692
|
};
|
|
19692
19693
|
}
|
|
19693
19694
|
function removeCompetitor(authoring, body) {
|
|
19694
|
-
const { groupKey, competitorKey } = parseBody(measurementDraftRemoveCompetitorRequestSchema, body, "remove-competitor");
|
|
19695
|
+
const { groupKey, competitorKey: competitorKey2 } = parseBody(measurementDraftRemoveCompetitorRequestSchema, body, "remove-competitor");
|
|
19695
19696
|
requireGroup(authoring, groupKey);
|
|
19696
19697
|
return {
|
|
19697
19698
|
authoring: {
|
|
19698
19699
|
...authoring,
|
|
19699
|
-
groups: authoring.groups.map((group) => group.stableKey === groupKey ? { ...group, competitors: group.competitors.filter((competitor) => competitor.stableKey !==
|
|
19700
|
+
groups: authoring.groups.map((group) => group.stableKey === groupKey ? { ...group, competitors: group.competitors.filter((competitor) => competitor.stableKey !== competitorKey2) } : group)
|
|
19700
19701
|
},
|
|
19701
19702
|
warnings: []
|
|
19702
19703
|
};
|
|
@@ -85596,9 +85597,57 @@ function utcDayBounds(now) {
|
|
|
85596
85597
|
return { start, end, date };
|
|
85597
85598
|
}
|
|
85598
85599
|
|
|
85600
|
+
// ../api-routes/src/plan-competitors.ts
|
|
85601
|
+
import { eq as eq69 } from "drizzle-orm";
|
|
85602
|
+
function competitorKey(value) {
|
|
85603
|
+
const host = hostOf(value) ?? value.trim().toLowerCase();
|
|
85604
|
+
return registrableDomain(host) ?? host;
|
|
85605
|
+
}
|
|
85606
|
+
function measurementPlanCompetitors(db, versionId) {
|
|
85607
|
+
if (!versionId) return [];
|
|
85608
|
+
const row = db.select({ canonicalJson: measurementPlanVersions.canonicalJson }).from(measurementPlanVersions).where(eq69(measurementPlanVersions.id, versionId)).get();
|
|
85609
|
+
if (!row) return [];
|
|
85610
|
+
let raw;
|
|
85611
|
+
try {
|
|
85612
|
+
const plan = parseStoredMeasurementPlanAnyVersion(row.canonicalJson);
|
|
85613
|
+
raw = plan.schemaVersion === MEASUREMENT_PLAN_V2_SCHEMA_VERSION ? plan.groups.flatMap((group) => group.competitors.map((competitor) => ({ domain: competitor.domain, names: [competitor.label, ...competitor.aliases] }))) : plan.groups.flatMap((group) => (group.competitors ?? []).map((domain) => ({ domain, names: [] })));
|
|
85614
|
+
} catch {
|
|
85615
|
+
return [];
|
|
85616
|
+
}
|
|
85617
|
+
const merged = /* @__PURE__ */ new Map();
|
|
85618
|
+
for (const { domain, names } of raw) {
|
|
85619
|
+
const key = competitorKey(domain);
|
|
85620
|
+
if (!key) continue;
|
|
85621
|
+
const set = merged.get(key) ?? /* @__PURE__ */ new Set();
|
|
85622
|
+
for (const name of names) if (name.trim()) set.add(name.trim());
|
|
85623
|
+
merged.set(key, set);
|
|
85624
|
+
}
|
|
85625
|
+
return [...merged].sort(([left], [right]) => left.localeCompare(right)).map(([domain, names]) => ({ domain, aliases: [...names] }));
|
|
85626
|
+
}
|
|
85627
|
+
function createRunCompetitorResolver(db, projectCompetitorDomains) {
|
|
85628
|
+
const byVersion = /* @__PURE__ */ new Map();
|
|
85629
|
+
const listOnly = () => ({ domains: [...new Set(projectCompetitorDomains)], aliases: /* @__PURE__ */ new Map() });
|
|
85630
|
+
return (versionId) => {
|
|
85631
|
+
if (!versionId) return listOnly();
|
|
85632
|
+
const cached = byVersion.get(versionId);
|
|
85633
|
+
if (cached) return cached;
|
|
85634
|
+
const domains = /* @__PURE__ */ new Map();
|
|
85635
|
+
for (const domain of projectCompetitorDomains) domains.set(competitorKey(domain), domain);
|
|
85636
|
+
const aliases = /* @__PURE__ */ new Map();
|
|
85637
|
+
for (const competitor of measurementPlanCompetitors(db, versionId)) {
|
|
85638
|
+
const domain = domains.get(competitor.domain) ?? competitor.domain;
|
|
85639
|
+
domains.set(competitor.domain, domain);
|
|
85640
|
+
if (competitor.aliases.length) aliases.set(domain, competitor.aliases);
|
|
85641
|
+
}
|
|
85642
|
+
const resolved = { domains: [...new Set(domains.values())], aliases };
|
|
85643
|
+
byVersion.set(versionId, resolved);
|
|
85644
|
+
return resolved;
|
|
85645
|
+
};
|
|
85646
|
+
}
|
|
85647
|
+
|
|
85599
85648
|
// ../api-routes/src/simple-measurement-definitions.ts
|
|
85600
85649
|
import crypto51 from "crypto";
|
|
85601
|
-
import { and as and59, eq as
|
|
85650
|
+
import { and as and59, eq as eq70 } from "drizzle-orm";
|
|
85602
85651
|
function captureSimpleMeasurementDefinition(db, input) {
|
|
85603
85652
|
return db.transaction((tx) => {
|
|
85604
85653
|
const run = tx.select({
|
|
@@ -85606,7 +85655,7 @@ function captureSimpleMeasurementDefinition(db, input) {
|
|
|
85606
85655
|
trigger: runs.trigger,
|
|
85607
85656
|
status: runs.status,
|
|
85608
85657
|
measurementPlanVersionId: runs.measurementPlanVersionId
|
|
85609
|
-
}).from(runs).where(and59(
|
|
85658
|
+
}).from(runs).where(and59(eq70(runs.projectId, input.projectId), eq70(runs.id, input.runId))).get();
|
|
85610
85659
|
if (!run) throw notFound("Run", input.runId);
|
|
85611
85660
|
if (run.kind !== RunKinds["answer-visibility"] || run.trigger === RunTriggers.probe || run.measurementPlanVersionId !== null) {
|
|
85612
85661
|
return null;
|
|
@@ -85616,7 +85665,7 @@ function captureSimpleMeasurementDefinition(db, input) {
|
|
|
85616
85665
|
if (definition.queries.some((query) => query.queryClass !== (classifier?.classify(query.queryText) ?? null))) {
|
|
85617
85666
|
throw validationError("Query classes must match the captured identity and text.");
|
|
85618
85667
|
}
|
|
85619
|
-
const existing = tx.select().from(simpleMeasurementDefinitions).where(and59(
|
|
85668
|
+
const existing = tx.select().from(simpleMeasurementDefinitions).where(and59(eq70(simpleMeasurementDefinitions.projectId, input.projectId), eq70(simpleMeasurementDefinitions.runId, input.runId))).get();
|
|
85620
85669
|
if (existing) {
|
|
85621
85670
|
const frozen = simpleMeasurementDefinitionSchema.parse(existing.definition);
|
|
85622
85671
|
const replayDefinition = {
|
|
@@ -85637,15 +85686,15 @@ function captureSimpleMeasurementDefinition(db, input) {
|
|
|
85637
85686
|
if (run.status !== RunStatuses.running) {
|
|
85638
85687
|
throw validationError("Only a running run can capture a new measurement definition.");
|
|
85639
85688
|
}
|
|
85640
|
-
if (tx.select({ id: querySnapshots.id }).from(querySnapshots).where(
|
|
85689
|
+
if (tx.select({ id: querySnapshots.id }).from(querySnapshots).where(eq70(querySnapshots.runId, input.runId)).limit(1).get()) {
|
|
85641
85690
|
throw validationError("This run already has stored answers. Its measurement definition cannot be inferred afterward.");
|
|
85642
85691
|
}
|
|
85643
|
-
const projectQueryIds = new Set(tx.select({ id: queries.id }).from(queries).where(
|
|
85692
|
+
const projectQueryIds = new Set(tx.select({ id: queries.id }).from(queries).where(eq70(queries.projectId, input.projectId)).all().map((query) => query.id));
|
|
85644
85693
|
if (definition.queries.some((query) => !projectQueryIds.has(query.queryId))) {
|
|
85645
85694
|
throw validationError("Every captured query must belong to the run project.");
|
|
85646
85695
|
}
|
|
85647
85696
|
if (definition.competitors !== void 0) {
|
|
85648
|
-
const liveCompetitorDomains = new Set(tx.select({ domain: competitors.domain }).from(competitors).where(
|
|
85697
|
+
const liveCompetitorDomains = new Set(tx.select({ domain: competitors.domain }).from(competitors).where(eq70(competitors.projectId, input.projectId)).all().map((competitor) => competitor.domain));
|
|
85649
85698
|
const capturedDomains = new Set(definition.competitors.map((competitor) => competitor.domain));
|
|
85650
85699
|
if (liveCompetitorDomains.size !== capturedDomains.size || [...liveCompetitorDomains].some((domain) => !capturedDomains.has(domain))) {
|
|
85651
85700
|
throw validationError("Captured competitors must exactly match the project competitors dispatched for this run.");
|
|
@@ -86462,7 +86511,7 @@ function determineCitationState(normalized, domains) {
|
|
|
86462
86511
|
}
|
|
86463
86512
|
return "not-cited";
|
|
86464
86513
|
}
|
|
86465
|
-
function computeCompetitorOverlap(normalized, competitorDomains) {
|
|
86514
|
+
function computeCompetitorOverlap(normalized, competitorDomains, competitorAliases = /* @__PURE__ */ new Map()) {
|
|
86466
86515
|
const overlapSet = /* @__PURE__ */ new Set();
|
|
86467
86516
|
for (const d of normalized.citedDomains) {
|
|
86468
86517
|
for (const cd of competitorDomains) {
|
|
@@ -86487,6 +86536,10 @@ function computeCompetitorOverlap(normalized, competitorDomains) {
|
|
|
86487
86536
|
if (brandKeyFromText(brand).length >= 4 && textContainsBrandAlias(normalized.answerText, brand)) {
|
|
86488
86537
|
overlapSet.add(cd);
|
|
86489
86538
|
}
|
|
86539
|
+
const named = competitorAliases.get(cd);
|
|
86540
|
+
if (named?.length && textContainsAnyBrandAlias(normalized.answerText, named)) {
|
|
86541
|
+
overlapSet.add(cd);
|
|
86542
|
+
}
|
|
86490
86543
|
}
|
|
86491
86544
|
}
|
|
86492
86545
|
return [...overlapSet];
|
|
@@ -86500,7 +86553,7 @@ function computeCitedCompetitorDomains(citedDomains, competitorDomains) {
|
|
|
86500
86553
|
}
|
|
86501
86554
|
return [...citedCompetitors];
|
|
86502
86555
|
}
|
|
86503
|
-
function extractRecommendedCompetitors(answerText, ownDomains, citedDomains, competitorDomains, ownBrandNames = []) {
|
|
86556
|
+
function extractRecommendedCompetitors(answerText, ownDomains, citedDomains, competitorDomains, ownBrandNames = [], competitorAliases = /* @__PURE__ */ new Map()) {
|
|
86504
86557
|
if (!answerText || answerText.length < 20) return [];
|
|
86505
86558
|
const ownBrandAliases = new Set(
|
|
86506
86559
|
ownDomains.flatMap((domain) => collectBrandAliasesFromDomain(domain))
|
|
@@ -86510,7 +86563,7 @@ function extractRecommendedCompetitors(answerText, ownDomains, citedDomains, com
|
|
|
86510
86563
|
}
|
|
86511
86564
|
const ownKeys = new Set([...ownBrandAliases].map(brandKeyFromText));
|
|
86512
86565
|
const knownCompetitorAliases = new Set(
|
|
86513
|
-
[...citedDomains, ...competitorDomains].flatMap((domain) => collectBrandAliasesFromDomain(domain)).filter((alias2) => !ownKeys.has(brandKeyFromText(alias2)))
|
|
86566
|
+
[...citedDomains.filter((domain) => !isListingMarketplace(domain)), ...competitorDomains].flatMap((domain) => collectBrandAliasesFromDomain(domain)).concat([...competitorAliases.values()].flat()).filter((alias2) => !ownKeys.has(brandKeyFromText(alias2)))
|
|
86514
86567
|
);
|
|
86515
86568
|
if (knownCompetitorAliases.size === 0) return [];
|
|
86516
86569
|
const candidatePatterns = [
|
|
@@ -86592,10 +86645,10 @@ var log = createLogger("IntelligenceService");
|
|
|
86592
86645
|
var runChronologyKey = sql28`coalesce(${runs.finishedAt}, ${runs.createdAt})`;
|
|
86593
86646
|
function analyzableRunPredicates(projectId) {
|
|
86594
86647
|
return [
|
|
86595
|
-
|
|
86648
|
+
eq71(runs.projectId, projectId),
|
|
86596
86649
|
// Only this kind writes query_snapshots.
|
|
86597
|
-
|
|
86598
|
-
or18(
|
|
86650
|
+
eq71(runs.kind, RunKinds["answer-visibility"]),
|
|
86651
|
+
or18(eq71(runs.status, RunStatuses.completed), eq71(runs.status, RunStatuses.partial)),
|
|
86599
86652
|
// Defensive: RunCoordinator already skips probes before analyzeAndPersist
|
|
86600
86653
|
// is called, but a future call site invoking it directly for a probe must
|
|
86601
86654
|
// still not pollute the intelligence window.
|
|
@@ -86640,7 +86693,7 @@ var IntelligenceService = class {
|
|
|
86640
86693
|
* Returns the analysis result for the coordinator to inspect (e.g. for webhook dispatch).
|
|
86641
86694
|
*/
|
|
86642
86695
|
analyzeAndPersist(runId, projectId) {
|
|
86643
|
-
const currentRunRecord = this.db.select().from(runs).where(and60(
|
|
86696
|
+
const currentRunRecord = this.db.select().from(runs).where(and60(eq71(runs.id, runId), ...analyzableRunPredicates(projectId))).get();
|
|
86644
86697
|
if (!currentRunRecord) {
|
|
86645
86698
|
log.info("intelligence.skip", { runId, reason: "run not eligible for analysis" });
|
|
86646
86699
|
return null;
|
|
@@ -86649,7 +86702,7 @@ var IntelligenceService = class {
|
|
|
86649
86702
|
const recentRuns = this.db.select().from(runs).where(
|
|
86650
86703
|
and60(
|
|
86651
86704
|
...analyzableRunPredicates(projectId),
|
|
86652
|
-
currentLocation === null ? isNull13(runs.location) :
|
|
86705
|
+
currentLocation === null ? isNull13(runs.location) : eq71(runs.location, currentLocation),
|
|
86653
86706
|
// Never look forward. The window is this run's own past, so
|
|
86654
86707
|
// re-analyzing a historical run compares it against its true
|
|
86655
86708
|
// predecessor rather than against sweeps that came after it.
|
|
@@ -86657,7 +86710,7 @@ var IntelligenceService = class {
|
|
|
86657
86710
|
// MEASUREMENT: only runs that actually wrote snapshots — see above.
|
|
86658
86711
|
// Index seek on idx_snapshots_run, short-circuited on the first row.
|
|
86659
86712
|
exists(
|
|
86660
|
-
this.db.select({ one: sql28`1` }).from(querySnapshots).where(
|
|
86713
|
+
this.db.select({ one: sql28`1` }).from(querySnapshots).where(eq71(querySnapshots.runId, runs.id))
|
|
86661
86714
|
)
|
|
86662
86715
|
)
|
|
86663
86716
|
).orderBy(desc32(runs.finishedAt), desc32(runs.createdAt)).limit(HISTORY_WINDOW_RUNS).all();
|
|
@@ -86732,7 +86785,7 @@ var IntelligenceService = class {
|
|
|
86732
86785
|
* Returns the persisted insights so the coordinator can count critical/high.
|
|
86733
86786
|
*/
|
|
86734
86787
|
analyzeAndPersistGbp(runId, projectId) {
|
|
86735
|
-
const runRow = this.db.select({ createdAt: runs.createdAt, startedAt: runs.startedAt, finishedAt: runs.finishedAt }).from(runs).where(
|
|
86788
|
+
const runRow = this.db.select({ createdAt: runs.createdAt, startedAt: runs.startedAt, finishedAt: runs.finishedAt }).from(runs).where(eq71(runs.id, runId)).get();
|
|
86736
86789
|
if (!runRow) {
|
|
86737
86790
|
log.info("gbp-intelligence.skip", { runId, reason: "run not found" });
|
|
86738
86791
|
this.persistGbpInsights(runId, projectId, [], []);
|
|
@@ -86741,8 +86794,8 @@ var IntelligenceService = class {
|
|
|
86741
86794
|
const windowStart = runRow.startedAt ?? runRow.createdAt;
|
|
86742
86795
|
const windowEnd = runRow.finishedAt ?? (/* @__PURE__ */ new Date()).toISOString();
|
|
86743
86796
|
const selected = this.db.select().from(gbpLocations).where(and60(
|
|
86744
|
-
|
|
86745
|
-
|
|
86797
|
+
eq71(gbpLocations.projectId, projectId),
|
|
86798
|
+
eq71(gbpLocations.selected, true),
|
|
86746
86799
|
gte18(gbpLocations.syncedAt, windowStart),
|
|
86747
86800
|
lte15(gbpLocations.syncedAt, windowEnd)
|
|
86748
86801
|
)).all();
|
|
@@ -86777,12 +86830,12 @@ var IntelligenceService = class {
|
|
|
86777
86830
|
}
|
|
86778
86831
|
/** Build the per-location signal bundle the GBP analyzer consumes. */
|
|
86779
86832
|
buildGbpLocationSignals(projectId, locationName, displayName, fallbackDate) {
|
|
86780
|
-
const metricRows = this.db.select({ metric: gbpDailyMetrics.metric, date: gbpDailyMetrics.date, value: gbpDailyMetrics.value }).from(gbpDailyMetrics).where(and60(
|
|
86781
|
-
const placeActionRows = this.db.select({ placeActionType: gbpPlaceActions.placeActionType, providerType: gbpPlaceActions.providerType }).from(gbpPlaceActions).where(and60(
|
|
86782
|
-
const lodgingRow = this.db.select({ populatedGroupCount: gbpLodgingSnapshots.populatedGroupCount }).from(gbpLodgingSnapshots).where(and60(
|
|
86783
|
-
const ownerRow = this.db.select({ description: gbpLocations.description }).from(gbpLocations).where(and60(
|
|
86833
|
+
const metricRows = this.db.select({ metric: gbpDailyMetrics.metric, date: gbpDailyMetrics.date, value: gbpDailyMetrics.value }).from(gbpDailyMetrics).where(and60(eq71(gbpDailyMetrics.projectId, projectId), eq71(gbpDailyMetrics.locationName, locationName))).all();
|
|
86834
|
+
const placeActionRows = this.db.select({ placeActionType: gbpPlaceActions.placeActionType, providerType: gbpPlaceActions.providerType }).from(gbpPlaceActions).where(and60(eq71(gbpPlaceActions.projectId, projectId), eq71(gbpPlaceActions.locationName, locationName))).all();
|
|
86835
|
+
const lodgingRow = this.db.select({ populatedGroupCount: gbpLodgingSnapshots.populatedGroupCount }).from(gbpLodgingSnapshots).where(and60(eq71(gbpLodgingSnapshots.projectId, projectId), eq71(gbpLodgingSnapshots.locationName, locationName))).orderBy(desc32(gbpLodgingSnapshots.syncedAt)).limit(1).get();
|
|
86836
|
+
const ownerRow = this.db.select({ description: gbpLocations.description }).from(gbpLocations).where(and60(eq71(gbpLocations.projectId, projectId), eq71(gbpLocations.locationName, locationName))).get();
|
|
86784
86837
|
const descriptionMissing = !(ownerRow?.description ?? "").trim();
|
|
86785
|
-
const placeRow = this.db.select({ attributes: gbpPlaceDetails.attributes }).from(gbpPlaceDetails).where(and60(
|
|
86838
|
+
const placeRow = this.db.select({ attributes: gbpPlaceDetails.attributes }).from(gbpPlaceDetails).where(and60(eq71(gbpPlaceDetails.projectId, projectId), eq71(gbpPlaceDetails.locationName, locationName))).orderBy(desc32(gbpPlaceDetails.syncedAt)).limit(1).get();
|
|
86786
86839
|
const placesAmenities = placeRow ? extractPlaceAmenities(placeRow.attributes) : [];
|
|
86787
86840
|
const summary3 = buildGbpSummary({
|
|
86788
86841
|
locationName,
|
|
@@ -86818,7 +86871,7 @@ var IntelligenceService = class {
|
|
|
86818
86871
|
/** Build the month-over-month keyword series for a location from the
|
|
86819
86872
|
* accumulating gbp_keyword_monthly table (latest complete month vs prior). */
|
|
86820
86873
|
buildGbpKeywordTrend(projectId, locationName) {
|
|
86821
|
-
const rows = this.db.select({ month: gbpKeywordMonthly.month, keyword: gbpKeywordMonthly.keyword, valueCount: gbpKeywordMonthly.valueCount }).from(gbpKeywordMonthly).where(and60(
|
|
86874
|
+
const rows = this.db.select({ month: gbpKeywordMonthly.month, keyword: gbpKeywordMonthly.keyword, valueCount: gbpKeywordMonthly.valueCount }).from(gbpKeywordMonthly).where(and60(eq71(gbpKeywordMonthly.projectId, projectId), eq71(gbpKeywordMonthly.locationName, locationName))).all();
|
|
86822
86875
|
if (rows.length === 0) return { recentMonth: null, priorMonth: null, points: [] };
|
|
86823
86876
|
const months = [...new Set(rows.map((r) => r.month))].sort().reverse();
|
|
86824
86877
|
const recentMonth = months[0] ?? null;
|
|
@@ -86849,7 +86902,7 @@ var IntelligenceService = class {
|
|
|
86849
86902
|
*/
|
|
86850
86903
|
persistGbpInsights(runId, projectId, gbpInsights, coveredLocationNames) {
|
|
86851
86904
|
const covered = new Set(coveredLocationNames);
|
|
86852
|
-
const existing = this.db.select({ id: insights.id, dismissed: insights.dismissed }).from(insights).where(and60(
|
|
86905
|
+
const existing = this.db.select({ id: insights.id, dismissed: insights.dismissed }).from(insights).where(and60(eq71(insights.projectId, projectId), eq71(insights.provider, GBP_INSIGHT_PROVIDER))).all();
|
|
86853
86906
|
const staleIds = [];
|
|
86854
86907
|
const dismissedSlots = /* @__PURE__ */ new Set();
|
|
86855
86908
|
for (const row of existing) {
|
|
@@ -86860,7 +86913,7 @@ var IntelligenceService = class {
|
|
|
86860
86913
|
}
|
|
86861
86914
|
this.db.transaction((tx) => {
|
|
86862
86915
|
for (const id of staleIds) {
|
|
86863
|
-
tx.delete(insights).where(
|
|
86916
|
+
tx.delete(insights).where(eq71(insights.id, id)).run();
|
|
86864
86917
|
}
|
|
86865
86918
|
for (const insight of gbpInsights) {
|
|
86866
86919
|
const parsed = parseGbpInsightId(insight.id);
|
|
@@ -86946,7 +86999,7 @@ var IntelligenceService = class {
|
|
|
86946
86999
|
* create per run + aggregate). DB is left untouched.
|
|
86947
87000
|
*/
|
|
86948
87001
|
backfill(projectName, opts, onProgress) {
|
|
86949
|
-
const project = this.db.select().from(projects).where(
|
|
87002
|
+
const project = this.db.select().from(projects).where(eq71(projects.name, projectName)).get();
|
|
86950
87003
|
if (!project) {
|
|
86951
87004
|
throw new Error(`Project "${projectName}" not found`);
|
|
86952
87005
|
}
|
|
@@ -87035,7 +87088,7 @@ var IntelligenceService = class {
|
|
|
87035
87088
|
return { processed, skipped: skipped3, totalInsights };
|
|
87036
87089
|
}
|
|
87037
87090
|
loadTrackedCompetitors(projectId) {
|
|
87038
|
-
return this.db.select({ domain: competitors.domain }).from(competitors).where(
|
|
87091
|
+
return this.db.select({ domain: competitors.domain }).from(competitors).where(eq71(competitors.projectId, projectId)).all().map((r) => r.domain);
|
|
87039
87092
|
}
|
|
87040
87093
|
/**
|
|
87041
87094
|
* Which of `runIds` actually wrote query snapshots. One grouped read, so
|
|
@@ -87066,15 +87119,15 @@ var IntelligenceService = class {
|
|
|
87066
87119
|
}
|
|
87067
87120
|
persistResult(result, runId, projectId) {
|
|
87068
87121
|
const previouslyDismissed = /* @__PURE__ */ new Set();
|
|
87069
|
-
const existingInsights = this.db.select({ query: insights.query, provider: insights.provider, type: insights.type, dismissed: insights.dismissed }).from(insights).where(
|
|
87122
|
+
const existingInsights = this.db.select({ query: insights.query, provider: insights.provider, type: insights.type, dismissed: insights.dismissed }).from(insights).where(eq71(insights.runId, runId)).all();
|
|
87070
87123
|
for (const row of existingInsights) {
|
|
87071
87124
|
if (row.dismissed) {
|
|
87072
87125
|
previouslyDismissed.add(`${row.query}:${row.provider}:${row.type}`);
|
|
87073
87126
|
}
|
|
87074
87127
|
}
|
|
87075
87128
|
this.db.transaction((tx) => {
|
|
87076
|
-
tx.delete(insights).where(
|
|
87077
|
-
tx.delete(healthSnapshots).where(
|
|
87129
|
+
tx.delete(insights).where(eq71(insights.runId, runId)).run();
|
|
87130
|
+
tx.delete(healthSnapshots).where(eq71(healthSnapshots.runId, runId)).run();
|
|
87078
87131
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
87079
87132
|
for (const insight of result.insights) {
|
|
87080
87133
|
const wasDismissed = previouslyDismissed.has(`${insight.query}:${insight.provider}:${insight.type}`);
|
|
@@ -87122,7 +87175,7 @@ var IntelligenceService = class {
|
|
|
87122
87175
|
impressions: gscSearchData.impressions,
|
|
87123
87176
|
position: gscSearchData.position
|
|
87124
87177
|
}).from(gscSearchData).where(and60(
|
|
87125
|
-
|
|
87178
|
+
eq71(gscSearchData.projectId, projectId),
|
|
87126
87179
|
gte18(gscSearchData.date, window.startDate),
|
|
87127
87180
|
lte15(gscSearchData.date, window.endDate)
|
|
87128
87181
|
)).all();
|
|
@@ -87175,7 +87228,7 @@ var IntelligenceService = class {
|
|
|
87175
87228
|
const key = row.query.toLowerCase();
|
|
87176
87229
|
gscImpressionsByQuery.set(key, (gscImpressionsByQuery.get(key) ?? 0) + row.impressions);
|
|
87177
87230
|
}
|
|
87178
|
-
const projectRow = this.db.select({ locations: projects.locations }).from(projects).where(
|
|
87231
|
+
const projectRow = this.db.select({ locations: projects.locations }).from(projects).where(eq71(projects.id, projectId)).get();
|
|
87179
87232
|
const locationCount = Math.max(
|
|
87180
87233
|
1,
|
|
87181
87234
|
(projectRow?.locations ?? []).length
|
|
@@ -87183,9 +87236,9 @@ var IntelligenceService = class {
|
|
|
87183
87236
|
const ROWS_PER_GROUP_BUDGET = Math.max(2, locationCount);
|
|
87184
87237
|
const recentRunRows = this.db.select({ id: runs.id, createdAt: runs.createdAt }).from(runs).where(
|
|
87185
87238
|
and60(
|
|
87186
|
-
|
|
87187
|
-
|
|
87188
|
-
or18(
|
|
87239
|
+
eq71(runs.projectId, projectId),
|
|
87240
|
+
eq71(runs.kind, RunKinds["answer-visibility"]),
|
|
87241
|
+
or18(eq71(runs.status, "completed"), eq71(runs.status, "partial")),
|
|
87189
87242
|
// Defensive — see top of file.
|
|
87190
87243
|
ne11(runs.trigger, RunTriggers.probe)
|
|
87191
87244
|
)
|
|
@@ -87205,7 +87258,7 @@ var IntelligenceService = class {
|
|
|
87205
87258
|
const haveHistory = recentRunIds.length > 0;
|
|
87206
87259
|
const priorRegressionsByPair = /* @__PURE__ */ new Map();
|
|
87207
87260
|
if (haveHistory) {
|
|
87208
|
-
const priorRows = this.db.select({ query: insights.query, provider: insights.provider, runId: insights.runId }).from(insights).where(and60(
|
|
87261
|
+
const priorRows = this.db.select({ query: insights.query, provider: insights.provider, runId: insights.runId }).from(insights).where(and60(eq71(insights.type, "regression"), inArray27(insights.runId, recentRunIds))).all();
|
|
87209
87262
|
const regressionGroups = /* @__PURE__ */ new Map();
|
|
87210
87263
|
for (const row of priorRows) {
|
|
87211
87264
|
if (!row.runId) continue;
|
|
@@ -87234,7 +87287,7 @@ var IntelligenceService = class {
|
|
|
87234
87287
|
});
|
|
87235
87288
|
}
|
|
87236
87289
|
buildRunData(runId, projectId, completedAt, location = null, trackedCompetitors = []) {
|
|
87237
|
-
const projectDomainRow = this.db.select({ canonicalDomain: projects.canonicalDomain, ownedDomains: projects.ownedDomains }).from(projects).where(
|
|
87290
|
+
const projectDomainRow = this.db.select({ canonicalDomain: projects.canonicalDomain, ownedDomains: projects.ownedDomains }).from(projects).where(eq71(projects.id, projectId)).get();
|
|
87238
87291
|
const projectDomains = projectDomainRow ? effectiveDomains({
|
|
87239
87292
|
canonicalDomain: projectDomainRow.canonicalDomain,
|
|
87240
87293
|
ownedDomains: projectDomainRow.ownedDomains
|
|
@@ -87252,7 +87305,7 @@ var IntelligenceService = class {
|
|
|
87252
87305
|
citedDomains: querySnapshots.citedDomains,
|
|
87253
87306
|
rawResponse: querySnapshots.rawResponse,
|
|
87254
87307
|
snapshotLocation: querySnapshots.location
|
|
87255
|
-
}).from(querySnapshots).leftJoin(queries,
|
|
87308
|
+
}).from(querySnapshots).leftJoin(queries, eq71(querySnapshots.queryId, queries.id)).where(eq71(querySnapshots.runId, runId)).all();
|
|
87256
87309
|
const snapshots = [];
|
|
87257
87310
|
let orphanCount = 0;
|
|
87258
87311
|
for (const r of rows) {
|
|
@@ -87473,6 +87526,7 @@ export {
|
|
|
87473
87526
|
runChecks,
|
|
87474
87527
|
executeDiscovery,
|
|
87475
87528
|
markSessionFailed,
|
|
87529
|
+
createRunCompetitorResolver,
|
|
87476
87530
|
captureSimpleMeasurementDefinition,
|
|
87477
87531
|
apiRoutes,
|
|
87478
87532
|
addLogListener,
|
|
@@ -17,12 +17,12 @@ import {
|
|
|
17
17
|
resolveOperatorApiKeyIds,
|
|
18
18
|
runWithUsageTags,
|
|
19
19
|
saveConfigPatch
|
|
20
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-2W6GCJ3O.js";
|
|
21
21
|
import {
|
|
22
22
|
deleteSiteCrawlGraphLayout,
|
|
23
23
|
persistSiteCrawlGraphLayout,
|
|
24
24
|
prepareSiteCrawlGraphLayout
|
|
25
|
-
} from "./chunk-
|
|
25
|
+
} from "./chunk-4LPV6ZZY.js";
|
|
26
26
|
import {
|
|
27
27
|
PACKAGE_VERSION
|
|
28
28
|
} from "./chunk-AOJU5LKX.js";
|
|
@@ -73,6 +73,7 @@ import {
|
|
|
73
73
|
createCredentialChecker,
|
|
74
74
|
createFastifyLogger,
|
|
75
75
|
createLogger,
|
|
76
|
+
createRunCompetitorResolver,
|
|
76
77
|
createUserSession,
|
|
77
78
|
deliverWebhook,
|
|
78
79
|
determineCitationState,
|
|
@@ -183,7 +184,7 @@ import {
|
|
|
183
184
|
siteLivenessState,
|
|
184
185
|
toAlertView,
|
|
185
186
|
usageCounters
|
|
186
|
-
} from "./chunk-
|
|
187
|
+
} from "./chunk-RGMUT5KY.js";
|
|
187
188
|
import {
|
|
188
189
|
AGENT_MEMORY_VALUE_MAX_BYTES,
|
|
189
190
|
AGENT_NONE,
|
|
@@ -344,7 +345,7 @@ import {
|
|
|
344
345
|
visibilityReportRequestSchema,
|
|
345
346
|
winnabilityClassLabel,
|
|
346
347
|
withRetry
|
|
347
|
-
} from "./chunk-
|
|
348
|
+
} from "./chunk-45EGDRVF.js";
|
|
348
349
|
|
|
349
350
|
// src/runtime-context.ts
|
|
350
351
|
function cliRuntimeContext(env = process.env, stdio = process) {
|
|
@@ -6490,7 +6491,7 @@ function nonBlank(value) {
|
|
|
6490
6491
|
return trimmed ? trimmed : void 0;
|
|
6491
6492
|
}
|
|
6492
6493
|
function resolveBuildCommit(env = process.env) {
|
|
6493
|
-
const embedded = true ? "
|
|
6494
|
+
const embedded = true ? "f4648ef75d44ebb5a3396cf05739a56a4aa2b7ee" : void 0;
|
|
6494
6495
|
return nonBlank(embedded) ?? nonBlank(env.CANONRY_COMMIT);
|
|
6495
6496
|
}
|
|
6496
6497
|
function resolveInstanceIdentity(env = process.env) {
|
|
@@ -6965,7 +6966,8 @@ var JobRunner = class {
|
|
|
6965
6966
|
}
|
|
6966
6967
|
log2.info("run.dispatch", { runId, providerCount: activeProviders.length, providers: activeProviders.map((p) => p.adapter.name) });
|
|
6967
6968
|
const projectCompetitors = this.db.select().from(competitors).where(eq2(competitors.projectId, projectId)).all();
|
|
6968
|
-
const
|
|
6969
|
+
const runCompetitors = createRunCompetitorResolver(this.db, projectCompetitors.map((c) => c.domain))(existingRun.measurementPlanVersionId);
|
|
6970
|
+
const competitorDomains = runCompetitors.domains;
|
|
6969
6971
|
const allDomains = effectiveDomains({
|
|
6970
6972
|
canonicalDomain: project.canonicalDomain,
|
|
6971
6973
|
ownedDomains: project.ownedDomains
|
|
@@ -7169,6 +7171,7 @@ var JobRunner = class {
|
|
|
7169
7171
|
runId,
|
|
7170
7172
|
allDomains,
|
|
7171
7173
|
competitorDomains,
|
|
7174
|
+
competitorAliases: runCompetitors.aliases,
|
|
7172
7175
|
allBrandNames,
|
|
7173
7176
|
executionGates,
|
|
7174
7177
|
providerDispatchCounts,
|
|
@@ -7426,7 +7429,8 @@ var JobRunner = class {
|
|
|
7426
7429
|
else providerErrors.set(provider, `No ${provider} provider is configured on this instance, so its missing answers did not run.`);
|
|
7427
7430
|
}
|
|
7428
7431
|
const projectCompetitors = this.db.select().from(competitors).where(eq2(competitors.projectId, projectId)).all();
|
|
7429
|
-
const
|
|
7432
|
+
const runCompetitors = createRunCompetitorResolver(this.db, projectCompetitors.map((c) => c.domain))(run.measurementPlanVersionId);
|
|
7433
|
+
const competitorDomains = runCompetitors.domains;
|
|
7430
7434
|
const allDomains = effectiveDomains({ canonicalDomain: project.canonicalDomain, ownedDomains: project.ownedDomains });
|
|
7431
7435
|
const allBrandNames = effectiveBrandNames({ displayName: project.displayName, aliases: project.aliases });
|
|
7432
7436
|
const todayPeriod = getCurrentUsageDay();
|
|
@@ -7481,6 +7485,7 @@ var JobRunner = class {
|
|
|
7481
7485
|
runId,
|
|
7482
7486
|
allDomains,
|
|
7483
7487
|
competitorDomains,
|
|
7488
|
+
competitorAliases: runCompetitors.aliases,
|
|
7484
7489
|
allBrandNames,
|
|
7485
7490
|
executionGates,
|
|
7486
7491
|
providerDispatchCounts,
|
|
@@ -7634,13 +7639,14 @@ var JobRunner = class {
|
|
|
7634
7639
|
ctx.allBrandNames,
|
|
7635
7640
|
ctx.allDomains
|
|
7636
7641
|
);
|
|
7637
|
-
const overlap = computeCompetitorOverlap(normalized, ctx.competitorDomains);
|
|
7642
|
+
const overlap = computeCompetitorOverlap(normalized, ctx.competitorDomains, ctx.competitorAliases);
|
|
7638
7643
|
const extractedCompetitors = extractRecommendedCompetitors(
|
|
7639
7644
|
normalized.answerText,
|
|
7640
7645
|
ctx.allDomains,
|
|
7641
7646
|
normalized.citedDomains,
|
|
7642
7647
|
ctx.competitorDomains,
|
|
7643
|
-
ctx.allBrandNames
|
|
7648
|
+
ctx.allBrandNames,
|
|
7649
|
+
ctx.competitorAliases
|
|
7644
7650
|
);
|
|
7645
7651
|
const snapshotId = crypto6.randomUUID();
|
|
7646
7652
|
let screenshotRelPath = null;
|
|
@@ -11568,10 +11574,11 @@ async function backfillAnswerVisibilityCommand(opts) {
|
|
|
11568
11574
|
let reparsed = 0;
|
|
11569
11575
|
let providerErrors = 0;
|
|
11570
11576
|
if (scopedProjects.length > 0) {
|
|
11571
|
-
const runRows = projectFilter ? db.select({ id: runs.id, projectId: runs.projectId }).from(runs).where(and13(
|
|
11577
|
+
const runRows = projectFilter ? db.select({ id: runs.id, projectId: runs.projectId, planVersionId: runs.measurementPlanVersionId }).from(runs).where(and13(
|
|
11572
11578
|
eq15(runs.kind, RunKinds["answer-visibility"]),
|
|
11573
11579
|
inArray6(runs.projectId, scopedProjects.map((project) => project.id))
|
|
11574
|
-
)).all() : db.select({ id: runs.id, projectId: runs.projectId }).from(runs).where(eq15(runs.kind, RunKinds["answer-visibility"])).all();
|
|
11580
|
+
)).all() : db.select({ id: runs.id, projectId: runs.projectId, planVersionId: runs.measurementPlanVersionId }).from(runs).where(eq15(runs.kind, RunKinds["answer-visibility"])).all();
|
|
11581
|
+
const planVersionByRun = new Map(runRows.map((run) => [run.id, run.planVersionId]));
|
|
11575
11582
|
const runIdsByProject = /* @__PURE__ */ new Map();
|
|
11576
11583
|
for (const run of runRows) {
|
|
11577
11584
|
const existing = runIdsByProject.get(run.projectId);
|
|
@@ -11580,6 +11587,7 @@ async function backfillAnswerVisibilityCommand(opts) {
|
|
|
11580
11587
|
}
|
|
11581
11588
|
for (const project of scopedProjects) {
|
|
11582
11589
|
const competitorDomains = db.select({ domain: competitors.domain }).from(competitors).where(eq15(competitors.projectId, project.id)).all().map((row) => row.domain);
|
|
11590
|
+
const competitorsForRun = createRunCompetitorResolver(db, competitorDomains);
|
|
11583
11591
|
const runIds = runIdsByProject.get(project.id) ?? [];
|
|
11584
11592
|
if (runIds.length === 0) continue;
|
|
11585
11593
|
const projectDomains = effectiveDomains({
|
|
@@ -11594,6 +11602,7 @@ async function backfillAnswerVisibilityCommand(opts) {
|
|
|
11594
11602
|
const batchRunIds = runIds.slice(offset, offset + SNAPSHOT_BATCH_SIZE);
|
|
11595
11603
|
const snapshotRows = db.select({
|
|
11596
11604
|
id: querySnapshots.id,
|
|
11605
|
+
runId: querySnapshots.runId,
|
|
11597
11606
|
provider: querySnapshots.provider,
|
|
11598
11607
|
citationState: querySnapshots.citationState,
|
|
11599
11608
|
answerMentioned: querySnapshots.answerMentioned,
|
|
@@ -11634,13 +11643,15 @@ async function backfillAnswerVisibilityCommand(opts) {
|
|
|
11634
11643
|
};
|
|
11635
11644
|
const nextCitationState = determineCitationState(normalized, projectDomains);
|
|
11636
11645
|
const nextCitedDomains = reparsedResult.citedDomains;
|
|
11637
|
-
const
|
|
11646
|
+
const runCompetitors = competitorsForRun(planVersionByRun.get(snapshot.runId));
|
|
11647
|
+
const nextCompetitorOverlap = computeCompetitorOverlap(normalized, runCompetitors.domains, runCompetitors.aliases);
|
|
11638
11648
|
const nextRecommendedCompetitors = extractRecommendedCompetitors(
|
|
11639
11649
|
normalized.answerText,
|
|
11640
11650
|
projectDomains,
|
|
11641
11651
|
normalized.citedDomains,
|
|
11642
|
-
|
|
11643
|
-
projectBrandNames
|
|
11652
|
+
runCompetitors.domains,
|
|
11653
|
+
projectBrandNames,
|
|
11654
|
+
runCompetitors.aliases
|
|
11644
11655
|
);
|
|
11645
11656
|
const nextRawResponse = stringifyStoredSnapshotEnvelope(
|
|
11646
11657
|
snapshot.rawResponse,
|
|
@@ -11867,8 +11878,10 @@ function backfillProjectAnswerMentions(db, projectId, opts) {
|
|
|
11867
11878
|
const project = db.select().from(projects).where(eq15(projects.id, projectId)).get();
|
|
11868
11879
|
if (!project) return { examined: 0, updated: 0, mentioned: 0 };
|
|
11869
11880
|
const competitorDomains = db.select({ domain: competitors.domain }).from(competitors).where(eq15(competitors.projectId, projectId)).all().map((row) => row.domain);
|
|
11870
|
-
const runRows = db.select({ id: runs.id }).from(runs).where(and13(eq15(runs.kind, RunKinds["answer-visibility"]), eq15(runs.projectId, projectId))).all();
|
|
11881
|
+
const runRows = db.select({ id: runs.id, planVersionId: runs.measurementPlanVersionId }).from(runs).where(and13(eq15(runs.kind, RunKinds["answer-visibility"]), eq15(runs.projectId, projectId))).all();
|
|
11871
11882
|
const runIds = runRows.map((r) => r.id);
|
|
11883
|
+
const planVersionByRun = new Map(runRows.map((run) => [run.id, run.planVersionId]));
|
|
11884
|
+
const competitorsForRun = createRunCompetitorResolver(db, competitorDomains);
|
|
11872
11885
|
let examined = 0;
|
|
11873
11886
|
let updated = 0;
|
|
11874
11887
|
let wouldUpdate = 0;
|
|
@@ -11888,6 +11901,7 @@ function backfillProjectAnswerMentions(db, projectId, opts) {
|
|
|
11888
11901
|
const batchRunIds = runIds.slice(offset, offset + SNAPSHOT_BATCH_SIZE);
|
|
11889
11902
|
const snapshotRows = db.select({
|
|
11890
11903
|
id: querySnapshots.id,
|
|
11904
|
+
runId: querySnapshots.runId,
|
|
11891
11905
|
provider: querySnapshots.provider,
|
|
11892
11906
|
answerMentioned: querySnapshots.answerMentioned,
|
|
11893
11907
|
answerText: querySnapshots.answerText,
|
|
@@ -11913,13 +11927,15 @@ function backfillProjectAnswerMentions(db, projectId, opts) {
|
|
|
11913
11927
|
retrievalStatus: "unknown",
|
|
11914
11928
|
searchQueries: []
|
|
11915
11929
|
};
|
|
11916
|
-
const
|
|
11930
|
+
const runCompetitors = competitorsForRun(planVersionByRun.get(snapshot.runId));
|
|
11931
|
+
const nextCompetitorOverlap = computeCompetitorOverlap(normalized, runCompetitors.domains, runCompetitors.aliases);
|
|
11917
11932
|
const nextRecommendedCompetitors = extractRecommendedCompetitors(
|
|
11918
11933
|
answerText,
|
|
11919
11934
|
projectDomains,
|
|
11920
11935
|
citedDomains,
|
|
11921
|
-
|
|
11922
|
-
projectBrandNames
|
|
11936
|
+
runCompetitors.domains,
|
|
11937
|
+
projectBrandNames,
|
|
11938
|
+
runCompetitors.aliases
|
|
11923
11939
|
);
|
|
11924
11940
|
const nextPatch = {};
|
|
11925
11941
|
if (snapshot.answerMentioned !== nextAnswerMentioned) {
|
|
@@ -12016,7 +12032,7 @@ function readStoredGroundingSources(rawResponse) {
|
|
|
12016
12032
|
return result2;
|
|
12017
12033
|
}
|
|
12018
12034
|
async function backfillInsightsCommand(project, opts) {
|
|
12019
|
-
const { IntelligenceService: IntelligenceService2 } = await import("./intelligence-service-
|
|
12035
|
+
const { IntelligenceService: IntelligenceService2 } = await import("./intelligence-service-CJKOXPOP.js");
|
|
12020
12036
|
const config = loadConfig();
|
|
12021
12037
|
const db = createClient(config.database);
|
|
12022
12038
|
migrate(db);
|
|
@@ -4,14 +4,14 @@ import {
|
|
|
4
4
|
installSkills,
|
|
5
5
|
loadConfigRaw,
|
|
6
6
|
saveConfigPatch
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-2W6GCJ3O.js";
|
|
8
8
|
import {
|
|
9
9
|
PACKAGE_VERSION
|
|
10
10
|
} from "./chunk-AOJU5LKX.js";
|
|
11
11
|
import {
|
|
12
12
|
SKILL_MANIFEST_FILENAME,
|
|
13
13
|
SkillsClients
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-45EGDRVF.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-
|
|
38
|
+
} from "./chunk-S6LJSUZO.js";
|
|
39
39
|
import {
|
|
40
40
|
autoSyncSkills,
|
|
41
41
|
formatAutoSyncNotice
|
|
42
|
-
} from "./chunk-
|
|
42
|
+
} from "./chunk-SOLFOKZF.js";
|
|
43
43
|
import {
|
|
44
44
|
CliError,
|
|
45
45
|
EXIT_SYSTEM_ERROR,
|
|
@@ -66,13 +66,13 @@ import {
|
|
|
66
66
|
shouldPrintServeSkillsNudge,
|
|
67
67
|
systemError,
|
|
68
68
|
usageError
|
|
69
|
-
} from "./chunk-
|
|
69
|
+
} from "./chunk-2W6GCJ3O.js";
|
|
70
70
|
import {
|
|
71
71
|
DEFAULT_DEMO_TRUSTED_PROXIES,
|
|
72
72
|
trustedProxiesProblem,
|
|
73
73
|
trustedProxyProblem
|
|
74
74
|
} from "./chunk-RB2F4D3Z.js";
|
|
75
|
-
import "./chunk-
|
|
75
|
+
import "./chunk-4LPV6ZZY.js";
|
|
76
76
|
import "./chunk-AOJU5LKX.js";
|
|
77
77
|
import {
|
|
78
78
|
CLOUDFLARE_WORKER_BINDINGS,
|
|
@@ -88,7 +88,7 @@ import {
|
|
|
88
88
|
queries,
|
|
89
89
|
renderReportHtml,
|
|
90
90
|
runs
|
|
91
|
-
} from "./chunk-
|
|
91
|
+
} from "./chunk-RGMUT5KY.js";
|
|
92
92
|
import {
|
|
93
93
|
AdsDeliverySnapshotStatuses,
|
|
94
94
|
AdsHistoricalCampaignRollupStatuses,
|
|
@@ -173,7 +173,7 @@ import {
|
|
|
173
173
|
snapshotProviderModeSchema,
|
|
174
174
|
visibilityReportRequestSchema,
|
|
175
175
|
winnabilityClassSchema
|
|
176
|
-
} from "./chunk-
|
|
176
|
+
} from "./chunk-45EGDRVF.js";
|
|
177
177
|
|
|
178
178
|
// src/cli.ts
|
|
179
179
|
import { pathToFileURL } from "url";
|
|
@@ -438,7 +438,7 @@ function parseDemoTrustedProxies(values) {
|
|
|
438
438
|
async function demoCommand(options) {
|
|
439
439
|
const { host, port } = parseDemoListenOptions(options);
|
|
440
440
|
const trustProxy = parseDemoTrustedProxies(options.trustProxy);
|
|
441
|
-
const { createDemoServer } = await import("./demo-server-
|
|
441
|
+
const { createDemoServer } = await import("./demo-server-H4ZFIIIB.js");
|
|
442
442
|
const app = await createDemoServer({ trustProxy });
|
|
443
443
|
let stopping = false;
|
|
444
444
|
const stop = () => {
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
import {
|
|
5
5
|
layoutSiteCrawlGraphInput,
|
|
6
6
|
persistSiteCrawlGraphLayout
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-4LPV6ZZY.js";
|
|
8
8
|
import {
|
|
9
9
|
PACKAGE_VERSION
|
|
10
10
|
} from "./chunk-AOJU5LKX.js";
|
|
@@ -83,7 +83,7 @@ import {
|
|
|
83
83
|
siteCrawlPages,
|
|
84
84
|
siteCrawlSnapshots,
|
|
85
85
|
trafficSources
|
|
86
|
-
} from "./chunk-
|
|
86
|
+
} from "./chunk-RGMUT5KY.js";
|
|
87
87
|
import {
|
|
88
88
|
RunKinds,
|
|
89
89
|
SiteCrawlFetchStates,
|
|
@@ -104,7 +104,7 @@ import {
|
|
|
104
104
|
measurementPlanV2Schema,
|
|
105
105
|
placementLinkDecision,
|
|
106
106
|
siteAuditPageFactorSchema
|
|
107
|
-
} from "./chunk-
|
|
107
|
+
} from "./chunk-45EGDRVF.js";
|
|
108
108
|
|
|
109
109
|
// src/demo-server.ts
|
|
110
110
|
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-
|
|
6
|
+
} from "./chunk-S6LJSUZO.js";
|
|
7
7
|
import {
|
|
8
8
|
loadConfig
|
|
9
|
-
} from "./chunk-
|
|
10
|
-
import "./chunk-
|
|
9
|
+
} from "./chunk-2W6GCJ3O.js";
|
|
10
|
+
import "./chunk-4LPV6ZZY.js";
|
|
11
11
|
import "./chunk-AOJU5LKX.js";
|
|
12
|
-
import "./chunk-
|
|
13
|
-
import "./chunk-
|
|
12
|
+
import "./chunk-RGMUT5KY.js";
|
|
13
|
+
import "./chunk-45EGDRVF.js";
|
|
14
14
|
export {
|
|
15
15
|
GoogleMarketingRuntimeError,
|
|
16
16
|
createGoogleMarketingCredentialStore,
|
package/dist/mcp.js
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import {
|
|
2
2
|
autoSyncSkills
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-SOLFOKZF.js";
|
|
4
4
|
import {
|
|
5
5
|
createApiClient,
|
|
6
6
|
createCanonryMcpServer
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-2W6GCJ3O.js";
|
|
8
8
|
import "./chunk-AOJU5LKX.js";
|
|
9
9
|
import {
|
|
10
10
|
isReadOnlyKey,
|
|
11
11
|
updateCheckEnvOptOut
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-45EGDRVF.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": "5.
|
|
3
|
+
"version": "5.14.0",
|
|
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": [
|
|
@@ -95,23 +95,23 @@
|
|
|
95
95
|
"@ainyc/canonry-integration-bing": "0.0.0",
|
|
96
96
|
"@ainyc/canonry-integration-cloud-run": "0.0.0",
|
|
97
97
|
"@ainyc/canonry-integration-cloudflare-queue": "0.0.0",
|
|
98
|
-
"@ainyc/canonry-integration-cloudflare-worker": "0.0.0",
|
|
99
98
|
"@ainyc/canonry-integration-commoncrawl": "0.0.0",
|
|
100
|
-
"@ainyc/canonry-integration-
|
|
99
|
+
"@ainyc/canonry-integration-cloudflare-worker": "0.0.0",
|
|
101
100
|
"@ainyc/canonry-integration-google-ads": "0.0.0",
|
|
101
|
+
"@ainyc/canonry-integration-google-business-profile": "0.0.0",
|
|
102
|
+
"@ainyc/canonry-integration-google": "0.0.0",
|
|
102
103
|
"@ainyc/canonry-integration-google-places": "0.0.0",
|
|
103
|
-
"@ainyc/canonry-integration-google-tag-manager": "0.0.0",
|
|
104
|
-
"@ainyc/canonry-integration-openai-ads": "0.0.0",
|
|
105
|
-
"@ainyc/canonry-integration-wordpress": "0.0.0",
|
|
106
104
|
"@ainyc/canonry-integration-traffic": "0.0.0",
|
|
105
|
+
"@ainyc/canonry-integration-google-tag-manager": "0.0.0",
|
|
107
106
|
"@ainyc/canonry-intelligence": "0.0.0",
|
|
108
107
|
"@ainyc/canonry-provider-cdp": "0.0.0",
|
|
109
|
-
"@ainyc/canonry-integration-
|
|
108
|
+
"@ainyc/canonry-integration-wordpress": "0.0.0",
|
|
109
|
+
"@ainyc/canonry-provider-claude": "0.0.0",
|
|
110
110
|
"@ainyc/canonry-provider-gemini": "0.0.0",
|
|
111
111
|
"@ainyc/canonry-provider-local": "0.0.0",
|
|
112
|
-
"@ainyc/canonry-provider-
|
|
113
|
-
"@ainyc/canonry-
|
|
114
|
-
"@ainyc/canonry-provider-
|
|
112
|
+
"@ainyc/canonry-provider-perplexity": "0.0.0",
|
|
113
|
+
"@ainyc/canonry-integration-openai-ads": "0.0.0",
|
|
114
|
+
"@ainyc/canonry-provider-openai": "0.0.0"
|
|
115
115
|
},
|
|
116
116
|
"scripts": {
|
|
117
117
|
"build": "pnpm run build:cli && pnpm run build:web",
|