@ainyc/canonry 4.27.0 → 4.27.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -1960,6 +1960,33 @@ function migrate(db) {
|
|
|
1960
1960
|
}
|
|
1961
1961
|
}
|
|
1962
1962
|
|
|
1963
|
+
// ../db/src/run-helpers.ts
|
|
1964
|
+
function groupRunsByCreatedAt(rows) {
|
|
1965
|
+
const groups = [];
|
|
1966
|
+
let current = [];
|
|
1967
|
+
let currentCreatedAt = null;
|
|
1968
|
+
for (const row of rows) {
|
|
1969
|
+
if (row.createdAt === currentCreatedAt) {
|
|
1970
|
+
current.push(row);
|
|
1971
|
+
} else {
|
|
1972
|
+
if (current.length > 0) groups.push(current);
|
|
1973
|
+
current = [row];
|
|
1974
|
+
currentCreatedAt = row.createdAt;
|
|
1975
|
+
}
|
|
1976
|
+
}
|
|
1977
|
+
if (current.length > 0) groups.push(current);
|
|
1978
|
+
return groups;
|
|
1979
|
+
}
|
|
1980
|
+
function pickGroupRepresentative(group) {
|
|
1981
|
+
if (group.length === 0) return null;
|
|
1982
|
+
let best = group[0];
|
|
1983
|
+
for (let i = 1; i < group.length; i++) {
|
|
1984
|
+
const candidate = group[i];
|
|
1985
|
+
if (candidate.id > best.id) best = candidate;
|
|
1986
|
+
}
|
|
1987
|
+
return best;
|
|
1988
|
+
}
|
|
1989
|
+
|
|
1963
1990
|
// ../intelligence/src/regressions.ts
|
|
1964
1991
|
function detectRegressions(currentRun, previousRun) {
|
|
1965
1992
|
const regressions = [];
|
|
@@ -3560,20 +3587,49 @@ var IntelligenceService = class {
|
|
|
3560
3587
|
const key = row.query.toLowerCase();
|
|
3561
3588
|
gscImpressionsByQuery.set(key, (gscImpressionsByQuery.get(key) ?? 0) + row.impressions);
|
|
3562
3589
|
}
|
|
3563
|
-
const
|
|
3590
|
+
const projectRow = this.db.select({ locations: projects.locations }).from(projects).where(eq(projects.id, projectId)).get();
|
|
3591
|
+
const locationCount = Math.max(
|
|
3592
|
+
1,
|
|
3593
|
+
parseJsonColumn(projectRow?.locations ?? null, []).length
|
|
3594
|
+
);
|
|
3595
|
+
const ROWS_PER_GROUP_BUDGET = Math.max(2, locationCount);
|
|
3596
|
+
const recentRunRows = this.db.select({ id: runs.id, createdAt: runs.createdAt }).from(runs).where(
|
|
3564
3597
|
and(
|
|
3565
3598
|
eq(runs.projectId, projectId),
|
|
3566
3599
|
eq(runs.kind, RunKinds["answer-visibility"]),
|
|
3567
3600
|
or(eq(runs.status, "completed"), eq(runs.status, "partial"))
|
|
3568
3601
|
)
|
|
3569
|
-
).orderBy(desc(runs.createdAt)).limit(RECURRENCE_LOOKBACK_RUNS + 1)
|
|
3602
|
+
).orderBy(desc(runs.createdAt), desc(runs.id)).limit((RECURRENCE_LOOKBACK_RUNS + 1) * ROWS_PER_GROUP_BUDGET).all();
|
|
3603
|
+
const recentGroups = groupRunsByCreatedAt(recentRunRows);
|
|
3604
|
+
const recentRunIds = [];
|
|
3605
|
+
const recentRunIdToCreatedAt = /* @__PURE__ */ new Map();
|
|
3606
|
+
let consumedGroups = 0;
|
|
3607
|
+
for (const group of recentGroups) {
|
|
3608
|
+
const groupIds = group.map((r) => r.id);
|
|
3609
|
+
if (groupIds.includes(excludeRunId)) continue;
|
|
3610
|
+
for (const r of group) recentRunIdToCreatedAt.set(r.id, r.createdAt);
|
|
3611
|
+
recentRunIds.push(...groupIds);
|
|
3612
|
+
consumedGroups++;
|
|
3613
|
+
if (consumedGroups >= RECURRENCE_LOOKBACK_RUNS) break;
|
|
3614
|
+
}
|
|
3570
3615
|
const haveHistory = recentRunIds.length > 0;
|
|
3571
3616
|
const priorRegressionsByPair = /* @__PURE__ */ new Map();
|
|
3572
3617
|
if (haveHistory) {
|
|
3573
|
-
const priorRows = this.db.select({ query: insights.query, provider: insights.provider }).from(insights).where(and(eq(insights.type, "regression"), inArray(insights.runId, recentRunIds))).all();
|
|
3618
|
+
const priorRows = this.db.select({ query: insights.query, provider: insights.provider, runId: insights.runId }).from(insights).where(and(eq(insights.type, "regression"), inArray(insights.runId, recentRunIds))).all();
|
|
3619
|
+
const regressionGroups = /* @__PURE__ */ new Map();
|
|
3574
3620
|
for (const row of priorRows) {
|
|
3621
|
+
if (!row.runId) continue;
|
|
3575
3622
|
const key = `${row.query}:${row.provider}`;
|
|
3576
|
-
|
|
3623
|
+
const groupKey = recentRunIdToCreatedAt.get(row.runId) ?? row.runId;
|
|
3624
|
+
let groups = regressionGroups.get(key);
|
|
3625
|
+
if (!groups) {
|
|
3626
|
+
groups = /* @__PURE__ */ new Set();
|
|
3627
|
+
regressionGroups.set(key, groups);
|
|
3628
|
+
}
|
|
3629
|
+
groups.add(groupKey);
|
|
3630
|
+
}
|
|
3631
|
+
for (const [key, groups] of regressionGroups) {
|
|
3632
|
+
priorRegressionsByPair.set(key, groups.size);
|
|
3577
3633
|
}
|
|
3578
3634
|
}
|
|
3579
3635
|
return rawInsights.map((insight) => {
|
|
@@ -3649,6 +3705,8 @@ export {
|
|
|
3649
3705
|
extractLegacyCredentials,
|
|
3650
3706
|
dropLegacyCredentialColumns,
|
|
3651
3707
|
migrate,
|
|
3708
|
+
groupRunsByCreatedAt,
|
|
3709
|
+
pickGroupRepresentative,
|
|
3652
3710
|
isBlogShapedQuery,
|
|
3653
3711
|
buildInventory,
|
|
3654
3712
|
buildContentTargetRows,
|
|
@@ -50,6 +50,7 @@ import {
|
|
|
50
50
|
gaTrafficSummaries,
|
|
51
51
|
gaTrafficWindowSummaries,
|
|
52
52
|
groupInsights,
|
|
53
|
+
groupRunsByCreatedAt,
|
|
53
54
|
gscCoverageSnapshots,
|
|
54
55
|
gscSearchData,
|
|
55
56
|
gscUrlInspections,
|
|
@@ -60,6 +61,7 @@ import {
|
|
|
60
61
|
mapOpportunitiesToNextSteps,
|
|
61
62
|
notifications,
|
|
62
63
|
parseJsonColumn,
|
|
64
|
+
pickGroupRepresentative,
|
|
63
65
|
projects,
|
|
64
66
|
queries,
|
|
65
67
|
querySnapshots,
|
|
@@ -68,7 +70,7 @@ import {
|
|
|
68
70
|
schedules,
|
|
69
71
|
trafficSources,
|
|
70
72
|
usageCounters
|
|
71
|
-
} from "./chunk-
|
|
73
|
+
} from "./chunk-NXXD6TX7.js";
|
|
72
74
|
import {
|
|
73
75
|
AGENT_MEMORY_VALUE_MAX_BYTES,
|
|
74
76
|
AGENT_PROVIDER_IDS,
|
|
@@ -2317,12 +2319,16 @@ async function analyticsRoutes(app) {
|
|
|
2317
2319
|
const project = resolveProject(app.db, request.params.name);
|
|
2318
2320
|
const window = parseWindow(request.query.window);
|
|
2319
2321
|
const cutoff = windowCutoff(window);
|
|
2320
|
-
const
|
|
2322
|
+
const completedRuns = app.db.select().from(runs).where(eq10(runs.projectId, project.id)).orderBy(desc3(runs.createdAt), desc3(runs.id)).all().filter((r) => r.status === "completed" || r.status === "partial");
|
|
2323
|
+
const latestGroup = groupRunsByCreatedAt(completedRuns)[0] ?? [];
|
|
2324
|
+
const latestGroupRunIds = latestGroup.map((r) => r.id);
|
|
2325
|
+
const latestRun = pickGroupRepresentative(latestGroup);
|
|
2321
2326
|
if (!latestRun) {
|
|
2322
2327
|
return reply.send({ cited: [], gap: [], uncited: [], mentionedQueries: [], mentionGap: [], notMentioned: [], runId: "", window });
|
|
2323
2328
|
}
|
|
2324
2329
|
const windowRuns = app.db.select().from(runs).where(eq10(runs.projectId, project.id)).orderBy(runs.createdAt).all().filter((r) => r.status === "completed" || r.status === "partial").filter((r) => !cutoff || r.createdAt >= cutoff);
|
|
2325
2330
|
const windowRunIds = windowRuns.map((r) => r.id);
|
|
2331
|
+
const runIdToCreatedAt = new Map(windowRuns.map((r) => [r.id, r.createdAt]));
|
|
2326
2332
|
const consistencyMap = /* @__PURE__ */ new Map();
|
|
2327
2333
|
if (windowRunIds.length > 0) {
|
|
2328
2334
|
const allWindowSnaps = app.db.select({
|
|
@@ -2333,14 +2339,15 @@ async function analyticsRoutes(app) {
|
|
|
2333
2339
|
answerText: querySnapshots.answerText
|
|
2334
2340
|
}).from(querySnapshots).where(inArray2(querySnapshots.runId, windowRunIds)).all();
|
|
2335
2341
|
for (const s of allWindowSnaps) {
|
|
2342
|
+
const timePoint = runIdToCreatedAt.get(s.runId) ?? s.runId;
|
|
2336
2343
|
let entry = consistencyMap.get(s.queryId);
|
|
2337
2344
|
if (!entry) {
|
|
2338
2345
|
entry = { citedRuns: /* @__PURE__ */ new Set(), totalRuns: /* @__PURE__ */ new Set(), mentionedRuns: /* @__PURE__ */ new Set() };
|
|
2339
2346
|
consistencyMap.set(s.queryId, entry);
|
|
2340
2347
|
}
|
|
2341
|
-
entry.totalRuns.add(
|
|
2342
|
-
if (s.citationState === CitationStates.cited) entry.citedRuns.add(
|
|
2343
|
-
if (resolveSnapshotAnswerMentioned(s, project)) entry.mentionedRuns.add(
|
|
2348
|
+
entry.totalRuns.add(timePoint);
|
|
2349
|
+
if (s.citationState === CitationStates.cited) entry.citedRuns.add(timePoint);
|
|
2350
|
+
if (resolveSnapshotAnswerMentioned(s, project)) entry.mentionedRuns.add(timePoint);
|
|
2344
2351
|
}
|
|
2345
2352
|
}
|
|
2346
2353
|
const rawSnapshots = app.db.select({
|
|
@@ -2351,7 +2358,7 @@ async function analyticsRoutes(app) {
|
|
|
2351
2358
|
answerMentioned: querySnapshots.answerMentioned,
|
|
2352
2359
|
answerText: querySnapshots.answerText,
|
|
2353
2360
|
competitorOverlap: querySnapshots.competitorOverlap
|
|
2354
|
-
}).from(querySnapshots).leftJoin(queries, eq10(querySnapshots.queryId, queries.id)).where(
|
|
2361
|
+
}).from(querySnapshots).leftJoin(queries, eq10(querySnapshots.queryId, queries.id)).where(inArray2(querySnapshots.runId, latestGroupRunIds)).all();
|
|
2355
2362
|
const snapshots = rawSnapshots.map((s) => ({
|
|
2356
2363
|
...s,
|
|
2357
2364
|
resolvedMentioned: resolveSnapshotAnswerMentioned(s, project)
|
|
@@ -2435,11 +2442,12 @@ async function analyticsRoutes(app) {
|
|
|
2435
2442
|
const project = resolveProject(app.db, request.params.name);
|
|
2436
2443
|
const window = parseWindow(request.query.window);
|
|
2437
2444
|
const cutoff = windowCutoff(window);
|
|
2438
|
-
const windowRuns = app.db.select().from(runs).where(eq10(runs.projectId, project.id)).orderBy(desc3(runs.createdAt)).all().filter((r) => r.status === "completed" || r.status === "partial").filter((r) => !cutoff || r.createdAt >= cutoff);
|
|
2445
|
+
const windowRuns = app.db.select().from(runs).where(eq10(runs.projectId, project.id)).orderBy(desc3(runs.createdAt), desc3(runs.id)).all().filter((r) => r.status === "completed" || r.status === "partial").filter((r) => !cutoff || r.createdAt >= cutoff);
|
|
2439
2446
|
if (windowRuns.length === 0) {
|
|
2440
2447
|
return reply.send({ overall: [], byQuery: {}, runId: "", window });
|
|
2441
2448
|
}
|
|
2442
|
-
const
|
|
2449
|
+
const latestGroup = groupRunsByCreatedAt(windowRuns)[0] ?? [];
|
|
2450
|
+
const latestRunId = pickGroupRepresentative(latestGroup)?.id ?? windowRuns[0].id;
|
|
2443
2451
|
const windowRunIds = windowRuns.map((r) => r.id);
|
|
2444
2452
|
const snapshots = app.db.select({
|
|
2445
2453
|
queryId: querySnapshots.queryId,
|
|
@@ -5317,7 +5325,11 @@ function categorizeQuery(query, projectDisplayName, canonicalDomain) {
|
|
|
5317
5325
|
return categorizeQueryByIntent(query, buildBrandTokens(canonicalDomain, projectDisplayName));
|
|
5318
5326
|
}
|
|
5319
5327
|
function loadSnapshotsForRun(db, runId) {
|
|
5320
|
-
|
|
5328
|
+
return loadSnapshotsForRunIds(db, [runId]);
|
|
5329
|
+
}
|
|
5330
|
+
function loadSnapshotsForRunIds(db, runIds) {
|
|
5331
|
+
if (runIds.length === 0) return [];
|
|
5332
|
+
const rows = db.select().from(querySnapshots).where(inArray4(querySnapshots.runId, [...runIds])).all();
|
|
5321
5333
|
return rows.map((r) => ({
|
|
5322
5334
|
id: r.id,
|
|
5323
5335
|
runId: r.runId,
|
|
@@ -6436,13 +6448,15 @@ function buildWhatsChanged(input) {
|
|
|
6436
6448
|
function buildProjectReport(db, projectName) {
|
|
6437
6449
|
const project = resolveProject(db, projectName);
|
|
6438
6450
|
const queryLookup = loadQueryLookup(db, project.id);
|
|
6439
|
-
const allRuns = db.select().from(runs).where(eq13(runs.projectId, project.id)).orderBy(desc6(runs.createdAt)).all();
|
|
6451
|
+
const allRuns = db.select().from(runs).where(eq13(runs.projectId, project.id)).orderBy(desc6(runs.createdAt), desc6(runs.id)).all();
|
|
6440
6452
|
const visibilityRuns = allRuns.filter((r) => r.kind === RunKinds["answer-visibility"]);
|
|
6441
|
-
const
|
|
6442
|
-
(r) => r.status === RunStatuses.completed || r.status === RunStatuses.partial
|
|
6443
|
-
)
|
|
6444
|
-
const
|
|
6445
|
-
const
|
|
6453
|
+
const completedVisRunGroups = groupRunsByCreatedAt(
|
|
6454
|
+
visibilityRuns.filter((r) => r.status === RunStatuses.completed || r.status === RunStatuses.partial)
|
|
6455
|
+
);
|
|
6456
|
+
const latestVisRunGroup = completedVisRunGroups[0] ?? [];
|
|
6457
|
+
const representativeLatestRun = pickGroupRepresentative(latestVisRunGroup) ?? visibilityRuns[0] ?? null;
|
|
6458
|
+
const latestSnapshots = loadSnapshotsForRunIds(db, latestVisRunGroup.map((r) => r.id));
|
|
6459
|
+
const latestRunLocation = representativeLatestRun?.location ?? null;
|
|
6446
6460
|
const competitorRows = db.select().from(competitors).where(eq13(competitors.projectId, project.id)).all();
|
|
6447
6461
|
const competitorDomains = competitorRows.map((c) => c.domain);
|
|
6448
6462
|
const ownedDomains = parseJsonColumn(project.ownedDomains, []);
|
|
@@ -6509,7 +6523,7 @@ function buildProjectReport(db, projectName) {
|
|
|
6509
6523
|
const previousPoint = citationsTrend.length >= 2 ? citationsTrend.at(-2) : null;
|
|
6510
6524
|
let trend = "unknown";
|
|
6511
6525
|
if (!trendBaseline && latestPoint) {
|
|
6512
|
-
const latestRunOnTrend =
|
|
6526
|
+
const latestRunOnTrend = representativeLatestRun?.id === latestPoint.runId;
|
|
6513
6527
|
const currentRate = latestRunOnTrend ? latestPoint.citationRate : citationRate;
|
|
6514
6528
|
const priorRate = latestRunOnTrend ? previousPoint?.citationRate : latestPoint.citationRate;
|
|
6515
6529
|
if (priorRate !== void 0) {
|
|
@@ -6531,7 +6545,7 @@ function buildProjectReport(db, projectName) {
|
|
|
6531
6545
|
const periodStart = citationsTrend[0]?.date ?? null;
|
|
6532
6546
|
const periodEnd = citationsTrend.at(-1)?.date ?? null;
|
|
6533
6547
|
const configuredLocations = parseJsonColumn(project.locations, []);
|
|
6534
|
-
const reportLocation = buildLocationMeta(
|
|
6548
|
+
const reportLocation = buildLocationMeta(representativeLatestRun?.location ?? null, configuredLocations);
|
|
6535
6549
|
const providerLocationHandling = reportLocation ? buildProviderLocationHandling(citationScorecard.providers) : [];
|
|
6536
6550
|
const executiveSummary = {
|
|
6537
6551
|
citationRate,
|
|
@@ -6839,15 +6853,17 @@ async function compositeRoutes(app) {
|
|
|
6839
6853
|
const project = resolveProject(app.db, request.params.name);
|
|
6840
6854
|
const filterLocation = (request.query.location ?? "").trim() || null;
|
|
6841
6855
|
const sinceIso = parseSinceFilter(request.query.since);
|
|
6842
|
-
const allRunsRaw = app.db.select().from(runs).where(eq15(runs.projectId, project.id)).orderBy(desc7(runs.createdAt)).all();
|
|
6856
|
+
const allRunsRaw = app.db.select().from(runs).where(eq15(runs.projectId, project.id)).orderBy(desc7(runs.createdAt), desc7(runs.id)).all();
|
|
6843
6857
|
const allRuns = allRunsRaw.filter((r) => runMatchesFilters(r, filterLocation, sinceIso));
|
|
6844
6858
|
const totalRuns = allRuns.length;
|
|
6845
6859
|
const visibilityRuns = allRuns.filter((r) => r.kind === RunKinds["answer-visibility"]);
|
|
6846
6860
|
const completedVisRuns = visibilityRuns.filter(
|
|
6847
6861
|
(r) => r.status === RunStatuses.completed || r.status === RunStatuses.partial
|
|
6848
6862
|
);
|
|
6849
|
-
const
|
|
6850
|
-
const
|
|
6863
|
+
const visRunGroups = groupRunsByCreatedAt(completedVisRuns);
|
|
6864
|
+
const latestVisRunGroup = visRunGroups[0] ?? [];
|
|
6865
|
+
const previousVisRunGroup = visRunGroups[1] ?? [];
|
|
6866
|
+
const previousVisibilityRun = pickGroupRepresentative(previousVisRunGroup);
|
|
6851
6867
|
const latestRunRow = allRuns[0] ?? null;
|
|
6852
6868
|
const latestRun = latestRunRow ? { totalRuns, run: summarizeRun(latestRunRow) } : { totalRuns: 0, run: null };
|
|
6853
6869
|
const healthRow = app.db.select().from(healthSnapshots).where(eq15(healthSnapshots.projectId, project.id)).orderBy(desc7(healthSnapshots.createdAt)).limit(1).get();
|
|
@@ -6856,11 +6872,11 @@ async function compositeRoutes(app) {
|
|
|
6856
6872
|
const topInsights = insightRows.filter((row) => !row.dismissed).slice(0, TOP_INSIGHT_LIMIT).map(mapInsightRow2);
|
|
6857
6873
|
const sparklineRunIds = visibilityRuns.slice(0, DEFAULT_RUN_HISTORY_LIMIT).map((r) => r.id);
|
|
6858
6874
|
const snapshotRunIds = new Set(sparklineRunIds);
|
|
6859
|
-
|
|
6860
|
-
|
|
6875
|
+
for (const run of latestVisRunGroup) snapshotRunIds.add(run.id);
|
|
6876
|
+
for (const run of previousVisRunGroup) snapshotRunIds.add(run.id);
|
|
6861
6877
|
const snapshotsByRun = loadSnapshotsByRunIds(app, [...snapshotRunIds]);
|
|
6862
|
-
const latestSnapshots =
|
|
6863
|
-
const previousSnapshots =
|
|
6878
|
+
const latestSnapshots = latestVisRunGroup.flatMap((r) => snapshotsByRun.get(r.id) ?? []);
|
|
6879
|
+
const previousSnapshots = previousVisRunGroup.flatMap((r) => snapshotsByRun.get(r.id) ?? []);
|
|
6864
6880
|
const { queryCounts, providers } = summarizeFromSnapshots(latestSnapshots);
|
|
6865
6881
|
const transitions = summarizeTransitionsFromSnapshots(
|
|
6866
6882
|
latestSnapshots,
|
|
@@ -24656,7 +24672,7 @@ var Scheduler = class {
|
|
|
24656
24672
|
};
|
|
24657
24673
|
|
|
24658
24674
|
// src/notifier.ts
|
|
24659
|
-
import { eq as eq35, desc as desc16, and as and22, or as or4 } from "drizzle-orm";
|
|
24675
|
+
import { eq as eq35, desc as desc16, and as and22, inArray as inArray8, or as or4 } from "drizzle-orm";
|
|
24660
24676
|
import crypto31 from "crypto";
|
|
24661
24677
|
var log10 = createLogger("Notifier");
|
|
24662
24678
|
var Notifier = class {
|
|
@@ -24761,41 +24777,76 @@ var Notifier = class {
|
|
|
24761
24777
|
}
|
|
24762
24778
|
}
|
|
24763
24779
|
computeTransitions(runId, projectId) {
|
|
24780
|
+
const thisRun = this.db.select().from(runs).where(eq35(runs.id, runId)).get();
|
|
24781
|
+
if (!thisRun) return [];
|
|
24782
|
+
const groupSiblings = this.db.select().from(runs).where(and22(
|
|
24783
|
+
eq35(runs.projectId, projectId),
|
|
24784
|
+
eq35(runs.kind, thisRun.kind),
|
|
24785
|
+
eq35(runs.createdAt, thisRun.createdAt)
|
|
24786
|
+
)).all();
|
|
24787
|
+
const stillPending = groupSiblings.some((r) => r.status === "queued" || r.status === "running");
|
|
24788
|
+
if (stillPending) return [];
|
|
24789
|
+
const completedPartialSiblings = groupSiblings.filter(
|
|
24790
|
+
(r) => r.status === "completed" || r.status === "partial"
|
|
24791
|
+
);
|
|
24792
|
+
if (completedPartialSiblings.length === 0) return [];
|
|
24793
|
+
const winner = completedPartialSiblings.reduce((best, candidate) => {
|
|
24794
|
+
const candFinish = candidate.finishedAt ?? "";
|
|
24795
|
+
const bestFinish = best.finishedAt ?? "";
|
|
24796
|
+
if (candFinish > bestFinish) return candidate;
|
|
24797
|
+
if (candFinish < bestFinish) return best;
|
|
24798
|
+
return candidate.id > best.id ? candidate : best;
|
|
24799
|
+
});
|
|
24800
|
+
if (winner.id !== runId) return [];
|
|
24801
|
+
const projectLocations = this.db.select({ locations: projects.locations }).from(projects).where(eq35(projects.id, projectId)).get();
|
|
24802
|
+
const locationCount = Math.max(
|
|
24803
|
+
1,
|
|
24804
|
+
parseJsonColumn(projectLocations?.locations ?? null, []).length
|
|
24805
|
+
);
|
|
24806
|
+
const RECENT_FETCH_LIMIT = Math.max(8, locationCount * 4);
|
|
24764
24807
|
const recentRuns = this.db.select().from(runs).where(
|
|
24765
24808
|
and22(
|
|
24766
24809
|
eq35(runs.projectId, projectId),
|
|
24810
|
+
eq35(runs.kind, thisRun.kind),
|
|
24767
24811
|
or4(eq35(runs.status, "completed"), eq35(runs.status, "partial"))
|
|
24768
24812
|
)
|
|
24769
|
-
).orderBy(desc16(runs.createdAt)).limit(
|
|
24770
|
-
|
|
24771
|
-
const
|
|
24772
|
-
|
|
24773
|
-
|
|
24813
|
+
).orderBy(desc16(runs.createdAt), desc16(runs.id)).limit(RECENT_FETCH_LIMIT).all();
|
|
24814
|
+
const groups = groupRunsByCreatedAt(recentRuns);
|
|
24815
|
+
const currentGroupIdx = groups.findIndex((g) => g[0]?.createdAt === thisRun.createdAt);
|
|
24816
|
+
if (currentGroupIdx < 0) return [];
|
|
24817
|
+
const currentGroup = groups[currentGroupIdx] ?? [];
|
|
24818
|
+
const previousGroup = groups[currentGroupIdx + 1] ?? [];
|
|
24819
|
+
if (currentGroup.length === 0 || previousGroup.length === 0) return [];
|
|
24820
|
+
const currentRunIds = currentGroup.map((r) => r.id);
|
|
24821
|
+
const previousRunIds = previousGroup.map((r) => r.id);
|
|
24774
24822
|
const currentSnapshots = this.db.select({
|
|
24775
24823
|
queryId: querySnapshots.queryId,
|
|
24776
24824
|
query: queries.query,
|
|
24777
24825
|
provider: querySnapshots.provider,
|
|
24826
|
+
location: querySnapshots.location,
|
|
24778
24827
|
citationState: querySnapshots.citationState
|
|
24779
|
-
}).from(querySnapshots).leftJoin(queries, eq35(querySnapshots.queryId, queries.id)).where(
|
|
24828
|
+
}).from(querySnapshots).leftJoin(queries, eq35(querySnapshots.queryId, queries.id)).where(inArray8(querySnapshots.runId, currentRunIds)).all();
|
|
24780
24829
|
const previousSnapshots = this.db.select({
|
|
24781
24830
|
queryId: querySnapshots.queryId,
|
|
24782
24831
|
provider: querySnapshots.provider,
|
|
24832
|
+
location: querySnapshots.location,
|
|
24783
24833
|
citationState: querySnapshots.citationState
|
|
24784
|
-
}).from(querySnapshots).where(
|
|
24834
|
+
}).from(querySnapshots).where(inArray8(querySnapshots.runId, previousRunIds)).all();
|
|
24785
24835
|
const prevMap = /* @__PURE__ */ new Map();
|
|
24786
24836
|
for (const s of previousSnapshots) {
|
|
24787
|
-
prevMap.set(`${s.queryId}:${s.provider}`, s.citationState);
|
|
24837
|
+
prevMap.set(`${s.queryId}:${s.provider}:${s.location ?? ""}`, s.citationState);
|
|
24788
24838
|
}
|
|
24789
24839
|
const transitions = [];
|
|
24790
24840
|
for (const s of currentSnapshots) {
|
|
24791
|
-
const key = `${s.queryId}:${s.provider}`;
|
|
24841
|
+
const key = `${s.queryId}:${s.provider}:${s.location ?? ""}`;
|
|
24792
24842
|
const prevState = prevMap.get(key);
|
|
24793
24843
|
if (prevState && prevState !== s.citationState) {
|
|
24794
24844
|
transitions.push({
|
|
24795
24845
|
query: s.query ?? s.queryId,
|
|
24796
24846
|
from: prevState,
|
|
24797
24847
|
to: s.citationState,
|
|
24798
|
-
provider: s.provider
|
|
24848
|
+
provider: s.provider,
|
|
24849
|
+
location: s.location
|
|
24799
24850
|
});
|
|
24800
24851
|
}
|
|
24801
24852
|
}
|
package/dist/cli.js
CHANGED
|
@@ -20,7 +20,7 @@ import {
|
|
|
20
20
|
setTelemetrySource,
|
|
21
21
|
showFirstRunNotice,
|
|
22
22
|
trackEvent
|
|
23
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-QNXGCQEM.js";
|
|
24
24
|
import {
|
|
25
25
|
CliError,
|
|
26
26
|
EXIT_SYSTEM_ERROR,
|
|
@@ -49,7 +49,7 @@ import {
|
|
|
49
49
|
queries,
|
|
50
50
|
querySnapshots,
|
|
51
51
|
runs
|
|
52
|
-
} from "./chunk-
|
|
52
|
+
} from "./chunk-NXXD6TX7.js";
|
|
53
53
|
import {
|
|
54
54
|
CcReleaseSyncStatuses,
|
|
55
55
|
CheckScopes,
|
|
@@ -621,7 +621,7 @@ function readStoredGroundingSources(rawResponse) {
|
|
|
621
621
|
return result;
|
|
622
622
|
}
|
|
623
623
|
async function backfillInsightsCommand(project, opts) {
|
|
624
|
-
const { IntelligenceService } = await import("./intelligence-service-
|
|
624
|
+
const { IntelligenceService } = await import("./intelligence-service-Z6QIELKP.js");
|
|
625
625
|
const config = loadConfig();
|
|
626
626
|
const db = createClient(config.database);
|
|
627
627
|
migrate(db);
|
package/dist/index.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
createServer
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-QNXGCQEM.js";
|
|
4
4
|
import {
|
|
5
5
|
loadConfig
|
|
6
6
|
} from "./chunk-2FAEQ56I.js";
|
|
7
|
-
import "./chunk-
|
|
7
|
+
import "./chunk-NXXD6TX7.js";
|
|
8
8
|
import "./chunk-HVW665A4.js";
|
|
9
9
|
export {
|
|
10
10
|
createServer,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ainyc/canonry",
|
|
3
|
-
"version": "4.27.
|
|
3
|
+
"version": "4.27.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Agent-first open-source AEO operating platform - track how answer engines cite your domain",
|
|
6
6
|
"license": "FSL-1.1-ALv2",
|
|
@@ -63,19 +63,19 @@
|
|
|
63
63
|
"@ainyc/canonry-config": "0.0.0",
|
|
64
64
|
"@ainyc/canonry-contracts": "0.0.0",
|
|
65
65
|
"@ainyc/canonry-db": "0.0.0",
|
|
66
|
-
"@ainyc/canonry-integration-
|
|
66
|
+
"@ainyc/canonry-integration-bing": "0.0.0",
|
|
67
|
+
"@ainyc/canonry-integration-cloud-run": "0.0.0",
|
|
67
68
|
"@ainyc/canonry-integration-google": "0.0.0",
|
|
68
69
|
"@ainyc/canonry-intelligence": "0.0.0",
|
|
69
|
-
"@ainyc/canonry-integration-
|
|
70
|
+
"@ainyc/canonry-integration-commoncrawl": "0.0.0",
|
|
70
71
|
"@ainyc/canonry-integration-traffic": "0.0.0",
|
|
71
|
-
"@ainyc/canonry-integration-wordpress": "0.0.0",
|
|
72
72
|
"@ainyc/canonry-provider-cdp": "0.0.0",
|
|
73
|
+
"@ainyc/canonry-integration-wordpress": "0.0.0",
|
|
73
74
|
"@ainyc/canonry-provider-claude": "0.0.0",
|
|
74
|
-
"@ainyc/canonry-integration-bing": "0.0.0",
|
|
75
|
-
"@ainyc/canonry-provider-gemini": "0.0.0",
|
|
76
75
|
"@ainyc/canonry-provider-local": "0.0.0",
|
|
76
|
+
"@ainyc/canonry-provider-openai": "0.0.0",
|
|
77
77
|
"@ainyc/canonry-provider-perplexity": "0.0.0",
|
|
78
|
-
"@ainyc/canonry-provider-
|
|
78
|
+
"@ainyc/canonry-provider-gemini": "0.0.0"
|
|
79
79
|
},
|
|
80
80
|
"scripts": {
|
|
81
81
|
"build": "tsx scripts/copy-agent-assets.ts && tsup && tsx build-web.ts",
|