@canonry/canonry 7.95.0 → 7.96.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/assets/agent-workspace/skills/aero/references/ai-traffic-tracking.md +4 -1
- package/assets/agent-workspace/skills/canonry/references/ai-traffic-tracking.md +4 -1
- package/assets/agent-workspace/skills/canonry/references/canonry-cli.md +6 -0
- package/assets/assets/{AgentSetupPage-BV0TvyWO.js → AgentSetupPage-DBiPrrdJ.js} +1 -1
- package/assets/assets/{AuditHistoryPanel-CTVhEVjr.js → AuditHistoryPanel-DSnIs064.js} +1 -1
- package/assets/assets/{BacklinksPage-CE1Bfpf6.js → BacklinksPage-tPiG0nEP.js} +1 -1
- package/assets/assets/{HistoryPage-BhqA-Udl.js → HistoryPage-sxYHrfNk.js} +1 -1
- package/assets/assets/{MeasurementPropertyPage-BiJ06H7w.js → MeasurementPropertyPage-B8EbifR2.js} +1 -1
- package/assets/assets/ProjectPage-C1_A7iGy.js +11 -0
- package/assets/assets/{RunsPage-BII3_JsE.js → RunsPage-RE6nLBTv.js} +1 -1
- package/assets/assets/{SettingsPage-DS4ivpsX.js → SettingsPage-Dn93SUD1.js} +1 -1
- package/assets/assets/{SiteHealthSection-IywsGGIA.js → SiteHealthSection-BEBYoCNu.js} +2 -2
- package/assets/assets/ToneBadge-DFlmWh2A.js +60 -0
- package/assets/assets/{TrafficPage-Bg9JrnxC.js → TrafficPage-cNokjIJa.js} +1 -1
- package/assets/assets/{TrafficSourceDetailPage-BuD8BlaT.js → TrafficSourceDetailPage-DFGbx0zs.js} +1 -1
- package/assets/assets/{account-context-ylqeghOr.js → account-context-RM43ek4w.js} +1 -1
- package/assets/assets/{agent-trust-copy-DxpavxIA.js → agent-trust-copy-CRZ_oe24.js} +1 -1
- package/assets/assets/{card-rZ7BA4sl.js → card-GFeSoV1m.js} +1 -1
- package/assets/assets/{format-helpers-PdOXn5Yf.js → format-helpers-4dA9HFgE.js} +1 -1
- package/assets/assets/{index-CU7tAhKY.js → index-CohgAQ9L.js} +4 -4
- package/assets/assets/{query-client-Cq4kP41m.js → query-client-B3Z7Vqgv.js} +1 -1
- package/assets/assets/{react-query-DVctucqC.js → react-query-HC0PcMhZ.js} +1 -1
- package/assets/assets/{react-sigma_core.esm.min-DYhAEr2t.js → react-sigma_core.esm.min-IsYtRW95.js} +1 -1
- package/assets/assets/{server-traffic-Owp6jMwT.js → server-traffic-BtWOYZXf.js} +1 -1
- package/assets/assets/{service-y3nQY3Ue.js → service-Bu4M0T0x.js} +1 -1
- package/assets/index.html +7 -7
- package/dist/{ads-GN7QSEUV.js → ads-NS4KNR2U.js} +3 -3
- package/dist/{agent-J46OIQHH.js → agent-773TJYGJ.js} +7 -7
- package/dist/{agent-ask-755DZ4YB.js → agent-ask-MQXNRMAN.js} +3 -3
- package/dist/{agent-conversations-QO7C6F6L.js → agent-conversations-5EEEEWEQ.js} +3 -3
- package/dist/{agent-journeys-SVI6LWKM.js → agent-journeys-U5ITMUIM.js} +3 -3
- package/dist/{agent-memory-V3ZJZT5W.js → agent-memory-6PEE54ST.js} +3 -3
- package/dist/{agent-providers-QIHZ222U.js → agent-providers-6D76GSYA.js} +3 -3
- package/dist/{agent-transcript-6TS3ZOCA.js → agent-transcript-6M5RYZIR.js} +3 -3
- package/dist/{analytics-LFT5OAOR.js → analytics-WBFQJTHV.js} +3 -3
- package/dist/{apply-3XXMVLBK.js → apply-AGNDBHNV.js} +3 -3
- package/dist/{backfill-F62Y47XV.js → backfill-ZDPS7VON.js} +10 -10
- package/dist/{backlinks-AOA5KHHB.js → backlinks-TNPNJXPS.js} +3 -3
- package/dist/{bing-75F4W4E2.js → bing-5WB7JCBP.js} +3 -3
- package/dist/{bootstrap-CDGVAICZ.js → bootstrap-XF77XL7U.js} +10 -10
- package/dist/{cdp-YBCWRWY4.js → cdp-NBTJLUPM.js} +7 -7
- package/dist/{chunk-TXW2FPNJ.js → chunk-24CUAPPY.js} +4 -4
- package/dist/{chunk-Q6WHXY7D.js → chunk-35AEUG77.js} +1 -1
- package/dist/{chunk-GUVN5OSX.js → chunk-377PJ4AT.js} +3 -3
- package/dist/{chunk-YTRXALSU.js → chunk-3FHPUOMW.js} +1 -1
- package/dist/{chunk-IATTIKXF.js → chunk-4GECW7XZ.js} +3 -3
- package/dist/{chunk-FESPLVBO.js → chunk-5VLCPNTR.js} +6 -6
- package/dist/{chunk-6RDBULDN.js → chunk-6X24IDPZ.js} +1 -1
- package/dist/{chunk-NMUL63XG.js → chunk-CPJX2RWA.js} +2 -2
- package/dist/{chunk-C6UU2PDJ.js → chunk-F2O42DSO.js} +21 -21
- package/dist/{chunk-BUZBBVDZ.js → chunk-FUMYCZ62.js} +1 -1
- package/dist/{chunk-TG5D4E2Y.js → chunk-G6JSK2RY.js} +1 -1
- package/dist/{chunk-46YXUJSW.js → chunk-HKUH75YH.js} +2 -2
- package/dist/{chunk-73AUPWSG.js → chunk-HN2YNYPO.js} +4 -4
- package/dist/{chunk-JVOOKVCW.js → chunk-I663X7WB.js} +2 -2
- package/dist/{chunk-T3FYWUQL.js → chunk-IO4BZLM7.js} +2 -2
- package/dist/{chunk-J3NS6NGM.js → chunk-JGLX5WU6.js} +1 -1
- package/dist/{chunk-WK6IPTTM.js → chunk-JLC3CCFM.js} +4 -4
- package/dist/{chunk-RPPB4H4D.js → chunk-KCKUCJOG.js} +1 -1
- package/dist/{chunk-LHU3KIKG.js → chunk-LXKWFM74.js} +2 -2
- package/dist/{chunk-6S6XEEGX.js → chunk-MAOKDX3W.js} +5 -5
- package/dist/{chunk-NVWTGVZ4.js → chunk-MJIL4BWR.js} +3 -3
- package/dist/{chunk-KMT7I5KZ.js → chunk-N4SEITGT.js} +5 -5
- package/dist/{chunk-MKLAX5KY.js → chunk-OCXDY2DG.js} +1 -1
- package/dist/{chunk-FWY5HUSB.js → chunk-PC7ZUW2H.js} +2 -2
- package/dist/{chunk-7PUUMJXY.js → chunk-PSCXQGJE.js} +109 -50
- package/dist/{chunk-NJG6WFRK.js → chunk-QBIIQF3J.js} +1 -1
- package/dist/{chunk-TS5Q63NE.js → chunk-S3HNS2YJ.js} +3 -3
- package/dist/{chunk-EWSVH5TU.js → chunk-SDCH5EBA.js} +1 -1
- package/dist/{chunk-L7W72K4X.js → chunk-SPWGDODX.js} +358 -358
- package/dist/{chunk-PHOMW3R4.js → chunk-SXHD2NFT.js} +4 -4
- package/dist/{chunk-VOP74COR.js → chunk-UPALIEP2.js} +2 -2
- package/dist/{chunk-CVCUADCM.js → chunk-W4ZRFNOX.js} +43 -15
- package/dist/{chunk-A6O6X6FU.js → chunk-XOCSSHYD.js} +1 -1
- package/dist/{chunk-KK7NWOGH.js → chunk-YL77WFHQ.js} +7 -7
- package/dist/{chunk-5TPLZD4I.js → chunk-ZZVRDHSK.js} +1 -1
- package/dist/{citations-SQYZTJQ6.js → citations-MZ6XQDI3.js} +3 -3
- package/dist/{cli-catalog-N3JLEU77.js → cli-catalog-QPB2ADGD.js} +3 -3
- package/dist/{cli-commands-QOJJMX2X.js → cli-commands-RRHOMF6X.js} +7 -7
- package/dist/cli.js +13 -13
- package/dist/{competitor-C5JAHHR7.js → competitor-VF77UMUR.js} +3 -3
- package/dist/{content-RVPODQI6.js → content-BINAMQFF.js} +3 -3
- package/dist/{dashboard-3NAY2SX6.js → dashboard-OE4BGMKP.js} +6 -6
- package/dist/{demo-OSYK452E.js → demo-3HVJUP3G.js} +1 -1
- package/dist/{demo-server-GO4V5UXK.js → demo-server-BEFPBA7P.js} +12 -12
- package/dist/{discover-U2DNK2TO.js → discover-3XUPBCXL.js} +3 -3
- package/dist/{discover-eval-ESLS56AH.js → discover-eval-3DWJPIU2.js} +3 -3
- package/dist/{doctor-SBF54WXE.js → doctor-KYWVYS74.js} +3 -3
- package/dist/{evidence-WHDCM7Z5.js → evidence-DCTXENHR.js} +3 -3
- package/dist/{export-cmd-7CHS6K3S.js → export-cmd-E5OUTSMR.js} +3 -3
- package/dist/{ga-XRASDAVX.js → ga-KY7MHW2G.js} +3 -3
- package/dist/{gbp-FEOFMTBH.js → gbp-2TJ6JACW.js} +3 -3
- package/dist/{google-MWJ4HAUB.js → google-BZKYIIA6.js} +4 -4
- package/dist/{google-marketing-GELTQ32D.js → google-marketing-6ACZP4JB.js} +1 -1
- package/dist/{health-cmd-IO7YMTRQ.js → health-cmd-LCVJY5MG.js} +3 -3
- package/dist/{history-I74D3NTT.js → history-MAZOPZZ5.js} +3 -3
- package/dist/index.d.ts +41 -41
- package/dist/index.js +25 -25
- package/dist/{init-ZLJMCJ3Q.js → init-Z35R7A6X.js} +12 -12
- package/dist/{insights-EAMVEB5Y.js → insights-PAZHZP74.js} +3 -3
- package/dist/intelligence-service-YA7PBFQV.js +16 -0
- package/dist/{journeys-E373TZZS.js → journeys-H6OPK5XY.js} +3 -3
- package/dist/{keys-27JRRWKZ.js → keys-DF6LV4T5.js} +3 -3
- package/dist/{keyword-45H2TBRG.js → keyword-ILICCRQK.js} +3 -3
- package/dist/{logs-K4K4OJDY.js → logs-PKKCPDIN.js} +3 -3
- package/dist/{mcp-734WXNIA.js → mcp-7GVOYYX4.js} +4 -4
- package/dist/mcp.js +9 -9
- package/dist/{measurement-plan-XZXK3YLO.js → measurement-plan-V7E7UHE2.js} +5 -5
- package/dist/{notify-ZGLVTSVC.js → notify-ISU7XBAW.js} +3 -3
- package/dist/{organic-evidence-CRTYFYAN.js → organic-evidence-FIL7YJ4Z.js} +3 -3
- package/dist/{overview-5URBJKI4.js → overview-NVBLGY53.js} +4 -4
- package/dist/{project-R5W4Y4L4.js → project-NSNMLL3Z.js} +3 -3
- package/dist/{query-LPGNI3ZR.js → query-TPZUUJ4X.js} +3 -3
- package/dist/{research-GTVKPIO2.js → research-WILAIDCK.js} +3 -3
- package/dist/{results-export-UNQQHELR.js → results-export-XP7XUKI2.js} +3 -3
- package/dist/{run-DLAFXVF4.js → run-L646IKUB.js} +4 -4
- package/dist/{schedule-7I5VIJFS.js → schedule-I2LW344O.js} +3 -3
- package/dist/{search-MUS7FSOJ.js → search-7EBWXQ6X.js} +3 -3
- package/dist/{serve-5TV26VAH.js → serve-LNBKTV5N.js} +26 -26
- package/dist/{session-FWALDL3F.js → session-U2OPQSJE.js} +13 -13
- package/dist/{settings-EB433IDI.js → settings-IGJ6ZA7C.js} +3 -3
- package/dist/{sitemaps-5EVGGGQ5.js → sitemaps-B4G4PXIE.js} +3 -3
- package/dist/{skills-2HS4MYNT.js → skills-WQXXY2HN.js} +2 -2
- package/dist/{snapshot-4DMW7AK2.js → snapshot-2TD4WIEO.js} +3 -3
- package/dist/{src-OYMKXD6L.js → src-DI4RNYAG.js} +2 -2
- package/dist/{status-2CRLY5B6.js → status-SKGGPZFE.js} +4 -4
- package/dist/{technical-aeo-HIQJCEML.js → technical-aeo-AFAXF5M5.js} +3 -3
- package/dist/{telemetry-H3SGPKZC.js → telemetry-ZRRX7I75.js} +4 -4
- package/dist/{tools-PHYD6WYF.js → tools-RY7ZXQJ5.js} +11 -11
- package/dist/{traffic-47L2EV6Q.js → traffic-LA3FZKID.js} +9 -9
- package/dist/{trends-CCWE7MF6.js → trends-GUUBTBCO.js} +3 -3
- package/dist/{users-BGIGSKB2.js → users-W44TRUSL.js} +3 -3
- package/dist/{visibility-stats-XVF64BMX.js → visibility-stats-KMKV4TF5.js} +3 -3
- package/dist/{wordpress-DQ6DAQPS.js → wordpress-FNLXVJDO.js} +3 -3
- package/package.json +1 -1
- package/assets/assets/ProjectPage-BqS0rfDT.js +0 -11
- package/assets/assets/ToneBadge-CTZ_JZLD.js +0 -60
- package/dist/intelligence-service-GSQ7YAYU.js +0 -16
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
pickProjectCitedDomain
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-3FHPUOMW.js";
|
|
4
4
|
import {
|
|
5
5
|
createLogger
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-IO4BZLM7.js";
|
|
7
7
|
import {
|
|
8
8
|
GBP_INSIGHT_PROVIDER,
|
|
9
9
|
PERSISTENT_GAP_THRESHOLD,
|
|
@@ -17,7 +17,7 @@ import {
|
|
|
17
17
|
mergeGscQueryTotalsWithFallback,
|
|
18
18
|
readGscQueryDailyRows,
|
|
19
19
|
readLatestGscDataDate
|
|
20
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-PSCXQGJE.js";
|
|
21
21
|
import {
|
|
22
22
|
competitors,
|
|
23
23
|
gbpDailyMetrics,
|
|
@@ -35,14 +35,14 @@ import {
|
|
|
35
35
|
queries,
|
|
36
36
|
querySnapshots,
|
|
37
37
|
runs
|
|
38
|
-
} from "./chunk-
|
|
38
|
+
} from "./chunk-JGLX5WU6.js";
|
|
39
39
|
import {
|
|
40
40
|
CitationStates,
|
|
41
41
|
RunKinds,
|
|
42
42
|
RunStatuses,
|
|
43
43
|
RunTriggers,
|
|
44
44
|
effectiveDomains
|
|
45
|
-
} from "./chunk-
|
|
45
|
+
} from "./chunk-W4ZRFNOX.js";
|
|
46
46
|
|
|
47
47
|
// src/intelligence-service.ts
|
|
48
48
|
import { eq, desc, asc, and, ne, or, inArray, gte, lte, isNull, sql, exists } from "drizzle-orm";
|
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
siteCrawlGraphNodes,
|
|
6
6
|
siteCrawlPages,
|
|
7
7
|
siteCrawlSnapshots
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-JGLX5WU6.js";
|
|
9
9
|
import {
|
|
10
10
|
SITE_CRAWL_GRAPH_MAX_EDGES,
|
|
11
11
|
SITE_CRAWL_GRAPH_MAX_NODES,
|
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
factorStatusFromDistribution,
|
|
16
16
|
factorStatusFromScore,
|
|
17
17
|
roundPreservingTotal
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-W4ZRFNOX.js";
|
|
19
19
|
|
|
20
20
|
// src/site-audit-factors.ts
|
|
21
21
|
function recordedSharePct(factor) {
|
|
@@ -17,14 +17,14 @@ import {
|
|
|
17
17
|
normalizeTrafficPathPattern,
|
|
18
18
|
sessionizeJourneyRequests,
|
|
19
19
|
verifyRequestSignature
|
|
20
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-OCXDY2DG.js";
|
|
21
21
|
import {
|
|
22
22
|
currentOutcomeAttribution,
|
|
23
23
|
getRequestContext,
|
|
24
24
|
registerRequestContext,
|
|
25
25
|
requestAuditIdentity,
|
|
26
26
|
sanitizeRequestContext
|
|
27
|
-
} from "./chunk-
|
|
27
|
+
} from "./chunk-SDCH5EBA.js";
|
|
28
28
|
import {
|
|
29
29
|
RawEventSampleEventTypes,
|
|
30
30
|
SentimentIdempotencyConflict,
|
|
@@ -184,7 +184,7 @@ import {
|
|
|
184
184
|
userSessions,
|
|
185
185
|
users,
|
|
186
186
|
writeNegativeReviewMaxStars
|
|
187
|
-
} from "./chunk-
|
|
187
|
+
} from "./chunk-JGLX5WU6.js";
|
|
188
188
|
import {
|
|
189
189
|
ADS_ACTIVATE_SCOPE,
|
|
190
190
|
ADS_ACTIVATION_ABSOLUTE_MAX_ENTITIES,
|
|
@@ -1240,6 +1240,7 @@ import {
|
|
|
1240
1240
|
trafficSampleClassifierSchema,
|
|
1241
1241
|
trafficSamplesQuerySchema,
|
|
1242
1242
|
trafficSamplesResponseSchema,
|
|
1243
|
+
trafficSeriesGranularitySchema,
|
|
1243
1244
|
trafficSourceDetailDtoSchema,
|
|
1244
1245
|
trafficSourceDtoSchema,
|
|
1245
1246
|
trafficSourceListResponseSchema,
|
|
@@ -1283,7 +1284,7 @@ import {
|
|
|
1283
1284
|
wordpressSchemaDeployResultDtoSchema,
|
|
1284
1285
|
wordpressSchemaStatusResultDtoSchema,
|
|
1285
1286
|
wordpressStatusDtoSchema
|
|
1286
|
-
} from "./chunk-
|
|
1287
|
+
} from "./chunk-W4ZRFNOX.js";
|
|
1287
1288
|
|
|
1288
1289
|
// ../api-routes/src/user-session.ts
|
|
1289
1290
|
import crypto2 from "crypto";
|
|
@@ -31585,17 +31586,7 @@ function emptyAiCounts() {
|
|
|
31585
31586
|
}
|
|
31586
31587
|
var AI_ATTRIBUTION_PREFERRED_DIMENSION = "session";
|
|
31587
31588
|
function pickWinningAttributionDimension(sessionsByDimension) {
|
|
31588
|
-
|
|
31589
|
-
let winnerSessions = -1;
|
|
31590
|
-
for (const [dimension, sessions] of sessionsByDimension) {
|
|
31591
|
-
const beatsOnCount = sessions > winnerSessions;
|
|
31592
|
-
const winsTie = sessions === winnerSessions && dimension === AI_ATTRIBUTION_PREFERRED_DIMENSION;
|
|
31593
|
-
if (beatsOnCount || winsTie) {
|
|
31594
|
-
winnerSessions = sessions;
|
|
31595
|
-
winner = dimension;
|
|
31596
|
-
}
|
|
31597
|
-
}
|
|
31598
|
-
return winner;
|
|
31589
|
+
return sessionsByDimension.has(AI_ATTRIBUTION_PREFERRED_DIMENSION) ? AI_ATTRIBUTION_PREFERRED_DIMENSION : void 0;
|
|
31599
31590
|
}
|
|
31600
31591
|
function resolveWinningDimensions(rows) {
|
|
31601
31592
|
const groups = /* @__PURE__ */ new Map();
|
|
@@ -44010,7 +44001,7 @@ var routeCatalog = [
|
|
|
44010
44001
|
{ name: "kind", in: "query", description: 'Filter to "crawler", "ai-user-fetch", "ai-referral", a comma-separated list of them (e.g. "ai-user-fetch,ai-referral"), or "all" (default). Rows, totals and series cover only the kinds asked for.', schema: stringSchema },
|
|
44011
44002
|
{ name: "limit", in: "query", description: "Max newest combined detail rows in the events array (default 500, max 5000).", schema: stringSchema },
|
|
44012
44003
|
{ name: "sourceId", in: "query", description: "Restrict to a single traffic source.", schema: stringSchema },
|
|
44013
|
-
{ name: "granularity", in: "query", description: 'Full-window series bucket size: "hour" (default) or "
|
|
44004
|
+
{ name: "granularity", in: "query", description: 'Full-window series bucket size: "hour" (default), "day" or "month" (UTC calendar months).', schema: { type: "string", enum: ["hour", "day", "month"] } }
|
|
44014
44005
|
],
|
|
44015
44006
|
responses: {
|
|
44016
44007
|
200: jsonResponse("Events returned with windowed totals.", "TrafficEventsResponse"),
|
|
@@ -60049,9 +60040,10 @@ function withSessionShares(rows) {
|
|
|
60049
60040
|
}
|
|
60050
60041
|
var DAY_MS4 = 864e5;
|
|
60051
60042
|
var GA_TREND_FILLING_DAYS = 2;
|
|
60043
|
+
var gaFillingFrom = (now) => new Date(Date.parse(now.toISOString().slice(0, 10)) - (GA_TREND_FILLING_DAYS - 1) * DAY_MS4).toISOString().slice(0, 10);
|
|
60052
60044
|
function aiReferralDailyTrend(days, measuredDates, firstAiDate, now) {
|
|
60053
60045
|
if (!firstAiDate) return null;
|
|
60054
|
-
const fillingFrom =
|
|
60046
|
+
const fillingFrom = gaFillingFrom(now);
|
|
60055
60047
|
const usable = [...new Set(measuredDates)].filter((date) => date >= firstAiDate && date < fillingFrom).sort();
|
|
60056
60048
|
if (usable.length < 2) return null;
|
|
60057
60049
|
const sessionsByDate = new Map(days.map((day) => [day.date, day.sessions]));
|
|
@@ -60062,6 +60054,49 @@ function aiReferralDailyTrend(days, measuredDates, firstAiDate, now) {
|
|
|
60062
60054
|
const fit = linearTrend(axis.map((date) => measured.has(date) ? sessionsByDate.get(date) ?? 0 : null));
|
|
60063
60055
|
return fit ? { ...fit, startDate: axis[fit.startIndex], endDate: axis[fit.endIndex] } : null;
|
|
60064
60056
|
}
|
|
60057
|
+
var addMonths = (month, n) => {
|
|
60058
|
+
const [y, m] = month.split("-").map(Number);
|
|
60059
|
+
return new Date(Date.UTC(y, m - 1 + n, 1)).toISOString().slice(0, 7);
|
|
60060
|
+
};
|
|
60061
|
+
var lastDayOf = (month) => new Date(Date.parse(`${addMonths(month, 1)}-01T00:00:00.000Z`) - DAY_MS4).toISOString().slice(0, 10);
|
|
60062
|
+
function aiReferralMonthlySeries(input) {
|
|
60063
|
+
const today = input.now.toISOString().slice(0, 10);
|
|
60064
|
+
const fillingFrom = gaFillingFrom(input.now);
|
|
60065
|
+
const firstDay = input.range.startDate ?? [...input.days.map((day) => day.date), ...input.measuredDates].sort()[0];
|
|
60066
|
+
if (!firstDay) return { months: [], monthlyTrend: null };
|
|
60067
|
+
const lastDay = input.range.endDate && input.range.endDate < today ? input.range.endDate : today;
|
|
60068
|
+
const labels = new Map(input.byEngine.series.map((s) => [s.key, s.label]));
|
|
60069
|
+
const measured = new Set(input.measuredDates);
|
|
60070
|
+
const months = [];
|
|
60071
|
+
for (let month = firstDay.slice(0, 7); month <= lastDay.slice(0, 7); month = addMonths(month, 1)) {
|
|
60072
|
+
const inMonth = (date) => date.startsWith(month);
|
|
60073
|
+
const monthStart = `${month}-01`;
|
|
60074
|
+
const monthEnd = lastDayOf(month);
|
|
60075
|
+
const monthDates = calendarDateRange(monthStart, monthEnd);
|
|
60076
|
+
const days = input.days.filter((day) => inMonth(day.date));
|
|
60077
|
+
const reported = days.length > 0 || monthDates.some((date) => measured.has(date));
|
|
60078
|
+
const engines = /* @__PURE__ */ new Map();
|
|
60079
|
+
for (const day of input.byEngine.days) {
|
|
60080
|
+
if (!inMonth(day.date)) continue;
|
|
60081
|
+
for (const [key, value] of Object.entries(day.values)) engines.set(key, (engines.get(key) ?? 0) + value);
|
|
60082
|
+
}
|
|
60083
|
+
months.push({
|
|
60084
|
+
month,
|
|
60085
|
+
sessions: reported ? days.reduce((sum, day) => sum + day.sessions, 0) : null,
|
|
60086
|
+
complete: reported && monthStart >= firstDay && monthEnd <= lastDay && monthEnd < fillingFrom && monthDates.every((date) => measured.has(date)),
|
|
60087
|
+
engines: [...engines].filter(([, v]) => v > 0).sort((a, b) => b[1] - a[1]).map(([key, sessions]) => ({ key, label: labels.get(key) ?? key, sessions }))
|
|
60088
|
+
});
|
|
60089
|
+
}
|
|
60090
|
+
const fromMonth = input.firstAiDate?.slice(0, 7);
|
|
60091
|
+
const fit = fromMonth ? linearTrend(months.map((m) => m.complete && m.month >= fromMonth ? m.sessions : null)) : null;
|
|
60092
|
+
const monthlyTrend = fit ? {
|
|
60093
|
+
...fit,
|
|
60094
|
+
startMonth: months[fit.startIndex].month,
|
|
60095
|
+
endMonth: months[fit.endIndex].month,
|
|
60096
|
+
changePct: fit.start > 0 ? deltaPercent(fit.end, fit.start) : null
|
|
60097
|
+
} : null;
|
|
60098
|
+
return { months, monthlyTrend };
|
|
60099
|
+
}
|
|
60065
60100
|
function dateRangeConditions(column, range) {
|
|
60066
60101
|
const conditions = [];
|
|
60067
60102
|
if (range.startDate) conditions.push(sql37`${column} >= ${range.startDate}`);
|
|
@@ -61207,9 +61242,8 @@ async function ga4Routes(app, opts) {
|
|
|
61207
61242
|
// every date in the window) counted one visitor once per row. Withdrawn
|
|
61208
61243
|
// in 4.135.0; see `ga-ai-referral-aggregation.ts` for why no correct
|
|
61209
61244
|
// figure can be computed or fetched.
|
|
61210
|
-
// Shares of the rows' own sum,
|
|
61211
|
-
//
|
|
61212
|
-
// window, so it can exceed what the rows add up to.
|
|
61245
|
+
// Shares of the rows' own sum, which agrees with `aiSessionsDeduped`:
|
|
61246
|
+
// both count only the session lens across the same window.
|
|
61213
61247
|
aiReferrals: aiReferralDtos,
|
|
61214
61248
|
aiEngines: groupAiEngines(aiReferralDtos),
|
|
61215
61249
|
aiReferralLandingPages: aiReferralLandingPages.map((r) => ({
|
|
@@ -61319,7 +61353,12 @@ async function ga4Routes(app, opts) {
|
|
|
61319
61353
|
const series = buildAiReferralDailySeries(rows);
|
|
61320
61354
|
const measuredDates = app.db.selectDistinct({ date: gaDailyTotals.date }).from(gaDailyTotals).where(and74(eq86(gaDailyTotals.projectId, project.id), ...dateRangeConditions(gaDailyTotals.date, range))).all().map((row) => row.date);
|
|
61321
61355
|
const firstAiDate = app.db.select({ date: sql37`MIN(${gaAiReferrals.date})` }).from(gaAiReferrals).where(eq86(gaAiReferrals.projectId, project.id)).get()?.date ?? null;
|
|
61322
|
-
|
|
61356
|
+
const now = /* @__PURE__ */ new Date();
|
|
61357
|
+
return {
|
|
61358
|
+
...series,
|
|
61359
|
+
trend: aiReferralDailyTrend(series.days, measuredDates, firstAiDate, now),
|
|
61360
|
+
...aiReferralMonthlySeries({ days: series.days, byEngine: series.byEngine, measuredDates, range, firstAiDate, now })
|
|
61361
|
+
};
|
|
61323
61362
|
});
|
|
61324
61363
|
app.get("/projects/:name/ga/social-referral-history", async (request, _reply) => {
|
|
61325
61364
|
const project = resolveProject(app.db, request.params.name);
|
|
@@ -65733,22 +65772,39 @@ function assertCloudflareIngestUrlOutsideWorkerRoute(ingestUrl, workerRouteHost)
|
|
|
65733
65772
|
function emptyTrafficSeriesPoint(bucket) {
|
|
65734
65773
|
return { bucket, crawlerHits: 0, aiUserFetchHits: 0, aiReferralHits: 0, aiReferralLandedHits: 0, crawlerContentHits: 0, measured: true };
|
|
65735
65774
|
}
|
|
65736
|
-
|
|
65737
|
-
|
|
65738
|
-
|
|
65739
|
-
|
|
65740
|
-
|
|
65741
|
-
|
|
65742
|
-
|
|
65743
|
-
|
|
65744
|
-
|
|
65775
|
+
var SERIES_BUCKET_LENGTH = {
|
|
65776
|
+
[TrafficSeriesGranularities.hour]: null,
|
|
65777
|
+
[TrafficSeriesGranularities.day]: 10,
|
|
65778
|
+
[TrafficSeriesGranularities.month]: 7
|
|
65779
|
+
};
|
|
65780
|
+
function seriesBucketSql(tsHour, granularity) {
|
|
65781
|
+
const length = SERIES_BUCKET_LENGTH[granularity];
|
|
65782
|
+
return length === null ? tsHour : sql40`substr(${tsHour}, 1, ${sql40.raw(String(length))})`;
|
|
65783
|
+
}
|
|
65784
|
+
function seriesBucketOf(iso2, granularity) {
|
|
65785
|
+
const length = SERIES_BUCKET_LENGTH[granularity];
|
|
65786
|
+
return length === null ? iso2.slice(0, 13) : iso2.slice(0, length);
|
|
65787
|
+
}
|
|
65788
|
+
function seriesBucketStartMs(bucket, granularity) {
|
|
65789
|
+
if (granularity === TrafficSeriesGranularities.month) return Date.parse(`${bucket}-01T00:00:00.000Z`);
|
|
65790
|
+
if (granularity === TrafficSeriesGranularities.day) return Date.parse(`${bucket}T00:00:00.000Z`);
|
|
65791
|
+
return Date.parse(bucket.length === 13 ? `${bucket}:00:00.000Z` : bucket);
|
|
65792
|
+
}
|
|
65793
|
+
function nextSeriesBucketStartMs(startMs, granularity) {
|
|
65794
|
+
if (granularity === TrafficSeriesGranularities.month) {
|
|
65795
|
+
const start = new Date(startMs);
|
|
65796
|
+
return Date.UTC(start.getUTCFullYear(), start.getUTCMonth() + 1, 1);
|
|
65745
65797
|
}
|
|
65798
|
+
return startMs + (granularity === TrafficSeriesGranularities.day ? 864e5 : 36e5);
|
|
65799
|
+
}
|
|
65800
|
+
function completeTrafficSeries(windowStart, windowEnd, granularity, pointsByBucket) {
|
|
65801
|
+
const firstBucket = seriesBucketOf(windowStart.toISOString(), granularity);
|
|
65802
|
+
const lastBucketStartMs = seriesBucketStartMs(seriesBucketOf(windowEnd.toISOString(), granularity), granularity);
|
|
65746
65803
|
const points = [];
|
|
65747
|
-
|
|
65748
|
-
const
|
|
65804
|
+
for (let ms = seriesBucketStartMs(firstBucket, granularity); ms <= lastBucketStartMs; ms = nextSeriesBucketStartMs(ms, granularity)) {
|
|
65805
|
+
const iso2 = new Date(ms).toISOString();
|
|
65806
|
+
const bucket = granularity === TrafficSeriesGranularities.hour ? iso2 : seriesBucketOf(iso2, granularity);
|
|
65749
65807
|
points.push(pointsByBucket.get(bucket) ?? emptyTrafficSeriesPoint(bucket));
|
|
65750
|
-
if (granularity === TrafficSeriesGranularities.day) cursor.setUTCDate(cursor.getUTCDate() + 1);
|
|
65751
|
-
else cursor.setUTCHours(cursor.getUTCHours() + 1);
|
|
65752
65808
|
}
|
|
65753
65809
|
return points;
|
|
65754
65810
|
}
|
|
@@ -68794,11 +68850,12 @@ async function trafficRoutes(app, opts) {
|
|
|
68794
68850
|
const granularityParam = request.query?.granularity;
|
|
68795
68851
|
let granularity = TrafficSeriesGranularities.hour;
|
|
68796
68852
|
if (granularityParam !== void 0) {
|
|
68797
|
-
|
|
68798
|
-
|
|
68853
|
+
const parsed = trafficSeriesGranularitySchema.safeParse(granularityParam);
|
|
68854
|
+
if (parsed.success) {
|
|
68855
|
+
granularity = parsed.data;
|
|
68799
68856
|
} else {
|
|
68800
68857
|
throw validationError(
|
|
68801
|
-
`"granularity" must be one of: ${
|
|
68858
|
+
`"granularity" must be one of: ${trafficSeriesGranularitySchema.options.join(", ")}`
|
|
68802
68859
|
);
|
|
68803
68860
|
}
|
|
68804
68861
|
}
|
|
@@ -68833,7 +68890,7 @@ async function trafficRoutes(app, opts) {
|
|
|
68833
68890
|
);
|
|
68834
68891
|
crawlerTotal = crawlerSegments.content + crawlerSegments.sitemap + crawlerSegments.robots + crawlerSegments.asset + crawlerSegments.other;
|
|
68835
68892
|
totalEventRows += pathTotals.reduce((sum, row) => sum + Number(row.rows), 0);
|
|
68836
|
-
const crawlerSeriesBucket =
|
|
68893
|
+
const crawlerSeriesBucket = seriesBucketSql(crawlerEventsHourly.tsHour, granularity);
|
|
68837
68894
|
const distinctPaths = pathTotals.map((r) => ({ pathNormalized: r.pathNormalized }));
|
|
68838
68895
|
const contentPaths = [];
|
|
68839
68896
|
const infraPaths = [];
|
|
@@ -68904,7 +68961,7 @@ async function trafficRoutes(app, opts) {
|
|
|
68904
68961
|
}).from(aiUserFetchEventsHourly).where(userFetchWhere).get();
|
|
68905
68962
|
aiUserFetchTotal = Number(total?.total ?? 0);
|
|
68906
68963
|
totalEventRows += Number(total?.rows ?? 0);
|
|
68907
|
-
const userFetchSeriesBucket =
|
|
68964
|
+
const userFetchSeriesBucket = seriesBucketSql(aiUserFetchEventsHourly.tsHour, granularity);
|
|
68908
68965
|
const userFetchSeries = app.db.select({
|
|
68909
68966
|
bucket: userFetchSeriesBucket,
|
|
68910
68967
|
hits: sql40`COALESCE(SUM(${aiUserFetchEventsHourly.hits}), 0)`
|
|
@@ -68954,7 +69011,7 @@ async function trafficRoutes(app, opts) {
|
|
|
68954
69011
|
Number(total?.organic ?? 0)
|
|
68955
69012
|
);
|
|
68956
69013
|
totalEventRows += Number(total?.rows ?? 0);
|
|
68957
|
-
const referralSeriesBucket =
|
|
69014
|
+
const referralSeriesBucket = seriesBucketSql(aiReferralEventsHourly.tsHour, granularity);
|
|
68958
69015
|
const referralSeries = app.db.select({
|
|
68959
69016
|
bucket: referralSeriesBucket,
|
|
68960
69017
|
hits: sql40`COALESCE(SUM(${aiReferralEventsHourly.sessionsOrHits}), 0)`,
|
|
@@ -69020,32 +69077,34 @@ async function trafficRoutes(app, opts) {
|
|
|
69020
69077
|
const referralCountingChangedAt = aiReferralOlderCountUntil(app.db, { projectId: project.id, sourceId: sourceIdParam });
|
|
69021
69078
|
const referralCountingChangedMs = referralCountingChangedAt === null ? null : Date.parse(referralCountingChangedAt);
|
|
69022
69079
|
const coverageStart = firsts.length ? firsts.slice().sort()[0] : null;
|
|
69023
|
-
const bucketStartMs = (bucket) =>
|
|
69024
|
-
granularity === TrafficSeriesGranularities.day ? `${bucket}T00:00:00.000Z` : bucket
|
|
69025
|
-
);
|
|
69026
|
-
const bucketMs = granularity === TrafficSeriesGranularities.day ? 864e5 : 36e5;
|
|
69080
|
+
const bucketStartMs = (bucket) => seriesBucketStartMs(bucket, granularity);
|
|
69027
69081
|
const lastBucket = points.length ? points[points.length - 1].bucket : null;
|
|
69028
69082
|
const lastBucketStartMs = lastBucket === null ? null : bucketStartMs(lastBucket);
|
|
69029
|
-
const trailingBucketIsPartial = lastBucketStartMs !== null && Number.isFinite(lastBucketStartMs) && until.getTime() < lastBucketStartMs
|
|
69030
|
-
const coverageKey = coverageStart === null ? null :
|
|
69083
|
+
const trailingBucketIsPartial = lastBucketStartMs !== null && Number.isFinite(lastBucketStartMs) && until.getTime() < nextSeriesBucketStartMs(lastBucketStartMs, granularity);
|
|
69084
|
+
const coverageKey = coverageStart === null ? null : seriesBucketOf(coverageStart, granularity);
|
|
69031
69085
|
for (const pt of points) {
|
|
69032
|
-
pt.measured = coverageKey === null ? false : (
|
|
69086
|
+
pt.measured = coverageKey === null ? false : seriesBucketOf(pt.bucket, granularity) >= coverageKey;
|
|
69033
69087
|
}
|
|
69034
69088
|
const firstMeasuredIdx = points.findIndex((pt) => pt.measured);
|
|
69035
69089
|
const coverageStartMs = coverageStart === null ? null : Date.parse(coverageStart);
|
|
69036
|
-
const leadingBucketIsPartial = firstMeasuredIdx >= 0 && coverageStartMs !== null && Number.isFinite(coverageStartMs) && coverageStartMs > bucketStartMs(points[firstMeasuredIdx].bucket);
|
|
69090
|
+
const leadingBucketIsPartial = firstMeasuredIdx >= 0 && coverageStartMs !== null && Number.isFinite(coverageStartMs) && Math.max(coverageStartMs, since.getTime()) > bucketStartMs(points[firstMeasuredIdx].bucket);
|
|
69037
69091
|
return {
|
|
69038
69092
|
granularity,
|
|
69039
69093
|
points,
|
|
69040
69094
|
coverageStart,
|
|
69041
69095
|
aiReferralCountingChangedAt: referralCountingChangedAt,
|
|
69096
|
+
// The same two edges the fits leave out, named for a chart to draw as partial.
|
|
69097
|
+
partialBuckets: [
|
|
69098
|
+
...firstMeasuredIdx >= 0 && leadingBucketIsPartial ? [points[firstMeasuredIdx].bucket] : [],
|
|
69099
|
+
...trailingBucketIsPartial && lastBucket !== null && !(points.length - 1 === firstMeasuredIdx && leadingBucketIsPartial) ? [lastBucket] : []
|
|
69100
|
+
],
|
|
69042
69101
|
// Two edges are excluded from the fit, both for the same reason: a
|
|
69043
69102
|
// bucket that is not a full reading must not be treated as one.
|
|
69044
69103
|
//
|
|
69045
69104
|
// Leading: unmeasured buckets predate recording, so they are the
|
|
69046
69105
|
// ABSENCE of a reading, not a reading of zero. The first MEASURED
|
|
69047
|
-
// bucket goes too when recording began inside it, since
|
|
69048
|
-
// a bucket read as a whole
|
|
69106
|
+
// bucket goes too when recording or the range began inside it, since
|
|
69107
|
+
// a fraction of a bucket read as a whole slopes the fit up out of nothing.
|
|
69049
69108
|
//
|
|
69050
69109
|
// Trailing: `until` defaults to now, so the newest bucket holds only
|
|
69051
69110
|
// the elapsed fraction of the current period. A site flat at 500/day
|
|
@@ -2,18 +2,18 @@ import {
|
|
|
2
2
|
configExists,
|
|
3
3
|
loadConfigRaw,
|
|
4
4
|
saveConfigPatch
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-ZZVRDHSK.js";
|
|
6
6
|
import {
|
|
7
7
|
BUNDLED_SKILL_NAMES,
|
|
8
8
|
installSkills
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-QBIIQF3J.js";
|
|
10
10
|
import {
|
|
11
11
|
PACKAGE_VERSION
|
|
12
12
|
} from "./chunk-AOJU5LKX.js";
|
|
13
13
|
import {
|
|
14
14
|
SKILL_MANIFEST_FILENAME,
|
|
15
15
|
SkillsClients
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-W4ZRFNOX.js";
|
|
17
17
|
|
|
18
18
|
// src/skills-autosync.ts
|
|
19
19
|
import fs from "fs";
|