@canonry/canonry 4.117.1 → 4.118.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/canonry/references/canonry-cli.md +74 -1
- package/assets/assets/AuditHistoryPanel-Yh7VEe4P.js +1 -0
- package/assets/assets/{BacklinksPage-Bkafm10m.js → BacklinksPage-BmO77kMs.js} +1 -1
- package/assets/assets/{ChartPrimitives-NV_GgqFn.js → ChartPrimitives-H0ICVpw_.js} +1 -1
- package/assets/assets/HistoryPage-DkLV_iRc.js +1 -0
- package/assets/assets/ProjectPage-R3odr_eA.js +7 -0
- package/assets/assets/{RunRow-df0d24S6.js → RunRow-BDH9agxQ.js} +1 -1
- package/assets/assets/RunsPage-D9YsEeT3.js +1 -0
- package/assets/assets/{SettingsPage-BKw6B6cd.js → SettingsPage-o5as3Ixw.js} +1 -1
- package/assets/assets/{TrafficPage-CzpiYHKj.js → TrafficPage-BCK203aQ.js} +1 -1
- package/assets/assets/{TrafficSourceDetailPage-CC5nuqM1.js → TrafficSourceDetailPage-DsVMAZvS.js} +1 -1
- package/assets/assets/{arrow-left-CbQcW2pL.js → arrow-left-B7ZR6VC9.js} +1 -1
- package/assets/assets/{extract-error-message-CvqIZ-le.js → extract-error-message-DeYDUpew.js} +1 -1
- package/assets/assets/index-Bot6YiD6.css +1 -0
- package/assets/assets/index-QCFQv0xh.js +210 -0
- package/assets/assets/{trash-2-3J2u0woR.js → trash-2-xxHTqWbF.js} +1 -1
- package/assets/index.html +2 -2
- package/dist/{chunk-BMBHUFMI.js → chunk-75UBTCKS.js} +540 -16
- package/dist/{chunk-V4SW7SVX.js → chunk-CMZIPFNQ.js} +1598 -486
- package/dist/{chunk-NY7SC4ES.js → chunk-HGNY5GL4.js} +384 -15
- package/dist/{chunk-IAJ5TQ4S.js → chunk-KEZWLP4O.js} +1385 -1145
- package/dist/cli.js +390 -113
- package/dist/index.js +4 -4
- package/dist/{intelligence-service-C5YLASIP.js → intelligence-service-FWPXMAVK.js} +2 -2
- package/dist/mcp.js +2 -2
- package/package.json +7 -7
- package/assets/assets/ProjectPage-0-NnRxys.js +0 -7
- package/assets/assets/RunsPage-CU6-4YTM.js +0 -1
- package/assets/assets/index-B4R1-8hR.css +0 -1
- package/assets/assets/index-LjcWHaNZ.js +0 -210
|
@@ -32,6 +32,9 @@ var AppError = class extends Error {
|
|
|
32
32
|
function notFound(entity, id) {
|
|
33
33
|
return new AppError("NOT_FOUND", `${entity} '${id}' not found`, 404);
|
|
34
34
|
}
|
|
35
|
+
function alreadyExists(entity, id) {
|
|
36
|
+
return new AppError("ALREADY_EXISTS", `${entity} '${id}' already exists`, 409);
|
|
37
|
+
}
|
|
35
38
|
function validationError(message, details) {
|
|
36
39
|
return new AppError("VALIDATION_ERROR", message, 400, details);
|
|
37
40
|
}
|
|
@@ -574,12 +577,17 @@ var auditLogEntrySchema = z3.object({
|
|
|
574
577
|
entityType: z3.string(),
|
|
575
578
|
entityId: z3.string().nullable().optional(),
|
|
576
579
|
diff: z3.unknown().optional(),
|
|
580
|
+
/** Originating HTTP client, when available (dashboard browser, CLI, MCP, or external script). */
|
|
581
|
+
userAgent: z3.string().nullable().optional(),
|
|
582
|
+
/** Optional caller-supplied correlation key for grouping related mutations. */
|
|
583
|
+
actorSession: z3.string().nullable().optional(),
|
|
577
584
|
createdAt: z3.string()
|
|
578
585
|
});
|
|
579
586
|
|
|
580
587
|
// ../contracts/src/scopes.ts
|
|
581
588
|
var READ_ONLY_SCOPE = "read";
|
|
582
589
|
var WILDCARD_SCOPE = "*";
|
|
590
|
+
var ADS_WRITE_SCOPE = "ads.write";
|
|
583
591
|
function grantsWrite(scope) {
|
|
584
592
|
return scope === WILDCARD_SCOPE || scope === "write" || scope.endsWith(".write");
|
|
585
593
|
}
|
|
@@ -3037,11 +3045,64 @@ function calendarMonthBounds(month) {
|
|
|
3037
3045
|
};
|
|
3038
3046
|
}
|
|
3039
3047
|
|
|
3048
|
+
// ../contracts/src/results-export.ts
|
|
3049
|
+
import { z as z21 } from "zod";
|
|
3050
|
+
var resultsExportFormatSchema = z21.enum(["json", "csv"]);
|
|
3051
|
+
var resultsExportRecordSchema = z21.object({
|
|
3052
|
+
runId: z21.string(),
|
|
3053
|
+
runKind: z21.literal("answer-visibility"),
|
|
3054
|
+
runStatus: runStatusSchema,
|
|
3055
|
+
runTrigger: runTriggerSchema,
|
|
3056
|
+
runCreatedAt: z21.string(),
|
|
3057
|
+
runStartedAt: z21.string().nullable(),
|
|
3058
|
+
runFinishedAt: z21.string().nullable(),
|
|
3059
|
+
snapshotId: z21.string(),
|
|
3060
|
+
snapshotCreatedAt: z21.string(),
|
|
3061
|
+
/** Nullable when a tracked query was removed after this observation. */
|
|
3062
|
+
queryId: z21.string().nullable(),
|
|
3063
|
+
/** Snapshot-time query text, preserving removed queries where available. */
|
|
3064
|
+
query: z21.string().nullable(),
|
|
3065
|
+
provider: z21.string(),
|
|
3066
|
+
model: z21.string().nullable(),
|
|
3067
|
+
location: z21.string().nullable(),
|
|
3068
|
+
citationState: citationStateSchema,
|
|
3069
|
+
cited: z21.boolean(),
|
|
3070
|
+
answerMentioned: z21.boolean().nullable(),
|
|
3071
|
+
// A union keeps OpenAPI generators from dropping `null` on this enum.
|
|
3072
|
+
mentionState: z21.union([mentionStateSchema, z21.null()]),
|
|
3073
|
+
citedDomains: z21.array(z21.string()),
|
|
3074
|
+
competitorOverlap: z21.array(z21.string()),
|
|
3075
|
+
recommendedCompetitors: z21.array(z21.string()),
|
|
3076
|
+
answerText: z21.string().nullable(),
|
|
3077
|
+
groundingSources: z21.array(groundingSourceSchema),
|
|
3078
|
+
searchQueries: z21.array(z21.string())
|
|
3079
|
+
});
|
|
3080
|
+
var resultsExportFiltersSchema = z21.object({
|
|
3081
|
+
since: z21.string().nullable(),
|
|
3082
|
+
until: z21.string().nullable(),
|
|
3083
|
+
includeProbes: z21.boolean()
|
|
3084
|
+
});
|
|
3085
|
+
var resultsExportDtoSchema = z21.object({
|
|
3086
|
+
schemaVersion: z21.literal("canonry.results-export/v1"),
|
|
3087
|
+
generatedAt: z21.string(),
|
|
3088
|
+
project: z21.object({
|
|
3089
|
+
id: z21.string(),
|
|
3090
|
+
name: z21.string(),
|
|
3091
|
+
displayName: z21.string(),
|
|
3092
|
+
canonicalDomain: z21.string(),
|
|
3093
|
+
country: z21.string(),
|
|
3094
|
+
language: z21.string()
|
|
3095
|
+
}),
|
|
3096
|
+
filters: resultsExportFiltersSchema,
|
|
3097
|
+
recordCount: z21.number().int().nonnegative(),
|
|
3098
|
+
records: z21.array(resultsExportRecordSchema)
|
|
3099
|
+
});
|
|
3100
|
+
|
|
3040
3101
|
// ../contracts/src/ga.ts
|
|
3041
|
-
import { z as
|
|
3102
|
+
import { z as z23 } from "zod";
|
|
3042
3103
|
|
|
3043
3104
|
// ../contracts/src/traffic-class.ts
|
|
3044
|
-
import { z as
|
|
3105
|
+
import { z as z22 } from "zod";
|
|
3045
3106
|
|
|
3046
3107
|
// ../contracts/src/formatting.ts
|
|
3047
3108
|
function formatRatio(value) {
|
|
@@ -3128,7 +3189,7 @@ function formatWindowCountDelta(d, countLabel, windowLabel) {
|
|
|
3128
3189
|
}
|
|
3129
3190
|
|
|
3130
3191
|
// ../contracts/src/traffic-class.ts
|
|
3131
|
-
var aiReferralTrafficClassSchema =
|
|
3192
|
+
var aiReferralTrafficClassSchema = z22.enum(["organic", "paid"]);
|
|
3132
3193
|
var AiReferralTrafficClasses = aiReferralTrafficClassSchema.enum;
|
|
3133
3194
|
var PAID_CHANNEL_GROUPS = /* @__PURE__ */ new Set([
|
|
3134
3195
|
"paid search",
|
|
@@ -3198,29 +3259,29 @@ function formatAiReferralClassSummary(counts) {
|
|
|
3198
3259
|
}
|
|
3199
3260
|
|
|
3200
3261
|
// ../contracts/src/ga.ts
|
|
3201
|
-
var ga4ConnectionDtoSchema =
|
|
3202
|
-
id:
|
|
3203
|
-
projectId:
|
|
3204
|
-
propertyId:
|
|
3205
|
-
clientEmail:
|
|
3206
|
-
connected:
|
|
3207
|
-
createdAt:
|
|
3208
|
-
updatedAt:
|
|
3209
|
-
});
|
|
3210
|
-
var ga4TrafficSnapshotDtoSchema =
|
|
3211
|
-
date:
|
|
3212
|
-
landingPage:
|
|
3213
|
-
sessions:
|
|
3214
|
-
organicSessions:
|
|
3215
|
-
users:
|
|
3216
|
-
});
|
|
3217
|
-
var ga4SourceDimensionSchema =
|
|
3218
|
-
var ga4AiReferralDtoSchema =
|
|
3219
|
-
source:
|
|
3220
|
-
medium:
|
|
3262
|
+
var ga4ConnectionDtoSchema = z23.object({
|
|
3263
|
+
id: z23.string(),
|
|
3264
|
+
projectId: z23.string(),
|
|
3265
|
+
propertyId: z23.string(),
|
|
3266
|
+
clientEmail: z23.string(),
|
|
3267
|
+
connected: z23.boolean(),
|
|
3268
|
+
createdAt: z23.string(),
|
|
3269
|
+
updatedAt: z23.string()
|
|
3270
|
+
});
|
|
3271
|
+
var ga4TrafficSnapshotDtoSchema = z23.object({
|
|
3272
|
+
date: z23.string(),
|
|
3273
|
+
landingPage: z23.string(),
|
|
3274
|
+
sessions: z23.number(),
|
|
3275
|
+
organicSessions: z23.number(),
|
|
3276
|
+
users: z23.number()
|
|
3277
|
+
});
|
|
3278
|
+
var ga4SourceDimensionSchema = z23.enum(["session", "first_user", "manual_utm"]);
|
|
3279
|
+
var ga4AiReferralDtoSchema = z23.object({
|
|
3280
|
+
source: z23.string(),
|
|
3281
|
+
medium: z23.string(),
|
|
3221
3282
|
trafficClass: aiReferralTrafficClassSchema,
|
|
3222
|
-
sessions:
|
|
3223
|
-
users:
|
|
3283
|
+
sessions: z23.number(),
|
|
3284
|
+
users: z23.number(),
|
|
3224
3285
|
/**
|
|
3225
3286
|
* The winning attribution dimension for this (source, medium) tuple — the
|
|
3226
3287
|
* one with the highest session count. GA4 emits one row per dimension
|
|
@@ -3230,178 +3291,178 @@ var ga4AiReferralDtoSchema = z22.object({
|
|
|
3230
3291
|
*/
|
|
3231
3292
|
sourceDimension: ga4SourceDimensionSchema
|
|
3232
3293
|
});
|
|
3233
|
-
var ga4AiReferralLandingPageDtoSchema =
|
|
3234
|
-
source:
|
|
3235
|
-
medium:
|
|
3294
|
+
var ga4AiReferralLandingPageDtoSchema = z23.object({
|
|
3295
|
+
source: z23.string(),
|
|
3296
|
+
medium: z23.string(),
|
|
3236
3297
|
trafficClass: aiReferralTrafficClassSchema,
|
|
3237
3298
|
/**
|
|
3238
3299
|
* The winning attribution dimension for this (source, medium, landingPage)
|
|
3239
3300
|
* tuple — the one with the highest session count.
|
|
3240
3301
|
*/
|
|
3241
3302
|
sourceDimension: ga4SourceDimensionSchema,
|
|
3242
|
-
landingPage:
|
|
3243
|
-
sessions:
|
|
3244
|
-
users:
|
|
3245
|
-
});
|
|
3246
|
-
var ga4SocialReferralDtoSchema =
|
|
3247
|
-
source:
|
|
3248
|
-
medium:
|
|
3249
|
-
sessions:
|
|
3250
|
-
users:
|
|
3303
|
+
landingPage: z23.string(),
|
|
3304
|
+
sessions: z23.number(),
|
|
3305
|
+
users: z23.number()
|
|
3306
|
+
});
|
|
3307
|
+
var ga4SocialReferralDtoSchema = z23.object({
|
|
3308
|
+
source: z23.string(),
|
|
3309
|
+
medium: z23.string(),
|
|
3310
|
+
sessions: z23.number(),
|
|
3311
|
+
users: z23.number(),
|
|
3251
3312
|
/** GA4 default channel group (e.g. 'Organic Social', 'Paid Social') */
|
|
3252
|
-
channelGroup:
|
|
3313
|
+
channelGroup: z23.string()
|
|
3253
3314
|
});
|
|
3254
|
-
var ga4ChannelBucketDtoSchema =
|
|
3255
|
-
sessions:
|
|
3256
|
-
sharePct:
|
|
3257
|
-
sharePctDisplay:
|
|
3315
|
+
var ga4ChannelBucketDtoSchema = z23.object({
|
|
3316
|
+
sessions: z23.number(),
|
|
3317
|
+
sharePct: z23.number(),
|
|
3318
|
+
sharePctDisplay: z23.string()
|
|
3258
3319
|
});
|
|
3259
|
-
var ga4ChannelBreakdownDtoSchema =
|
|
3320
|
+
var ga4ChannelBreakdownDtoSchema = z23.object({
|
|
3260
3321
|
organic: ga4ChannelBucketDtoSchema,
|
|
3261
3322
|
social: ga4ChannelBucketDtoSchema,
|
|
3262
3323
|
direct: ga4ChannelBucketDtoSchema,
|
|
3263
3324
|
ai: ga4ChannelBucketDtoSchema,
|
|
3264
3325
|
other: ga4ChannelBucketDtoSchema
|
|
3265
3326
|
});
|
|
3266
|
-
var ga4TrafficSummaryDtoSchema =
|
|
3267
|
-
totalSessions:
|
|
3268
|
-
totalOrganicSessions:
|
|
3327
|
+
var ga4TrafficSummaryDtoSchema = z23.object({
|
|
3328
|
+
totalSessions: z23.number(),
|
|
3329
|
+
totalOrganicSessions: z23.number(),
|
|
3269
3330
|
/** Direct-channel sessions (sessions with no source — bookmarks, typed URLs, AI-driven traffic with stripped referrer). 0 for legacy rows from before the column was added. */
|
|
3270
|
-
totalDirectSessions:
|
|
3271
|
-
totalUsers:
|
|
3272
|
-
topPages:
|
|
3273
|
-
landingPage:
|
|
3274
|
-
sessions:
|
|
3275
|
-
organicSessions:
|
|
3331
|
+
totalDirectSessions: z23.number(),
|
|
3332
|
+
totalUsers: z23.number(),
|
|
3333
|
+
topPages: z23.array(z23.object({
|
|
3334
|
+
landingPage: z23.string(),
|
|
3335
|
+
sessions: z23.number(),
|
|
3336
|
+
organicSessions: z23.number(),
|
|
3276
3337
|
/** Per-page Direct-channel sessions. 0 for legacy rows. */
|
|
3277
|
-
directSessions:
|
|
3278
|
-
users:
|
|
3338
|
+
directSessions: z23.number(),
|
|
3339
|
+
users: z23.number()
|
|
3279
3340
|
})),
|
|
3280
|
-
aiReferrals:
|
|
3281
|
-
aiReferralLandingPages:
|
|
3341
|
+
aiReferrals: z23.array(ga4AiReferralDtoSchema),
|
|
3342
|
+
aiReferralLandingPages: z23.array(ga4AiReferralLandingPageDtoSchema),
|
|
3282
3343
|
/** Deduped AI session total: MAX(sessions) per date+source+medium across attribution dimensions, then summed. Cross-cutting: can overlap with Direct/Organic/Social via firstUserSource. */
|
|
3283
|
-
aiSessionsDeduped:
|
|
3344
|
+
aiSessionsDeduped: z23.number(),
|
|
3284
3345
|
/** Deduped AI user total: MAX(users) per date+source+medium across attribution dimensions, then summed. */
|
|
3285
|
-
aiUsersDeduped:
|
|
3346
|
+
aiUsersDeduped: z23.number(),
|
|
3286
3347
|
/** Deduped AI sessions whose attribution carries paid intent. */
|
|
3287
|
-
paidAiSessionsDeduped:
|
|
3348
|
+
paidAiSessionsDeduped: z23.number(),
|
|
3288
3349
|
/** Deduped users for paid AI sessions. */
|
|
3289
|
-
paidAiUsersDeduped:
|
|
3350
|
+
paidAiUsersDeduped: z23.number(),
|
|
3290
3351
|
/** Deduped AI sessions without paid intent evidence. */
|
|
3291
|
-
organicAiSessionsDeduped:
|
|
3352
|
+
organicAiSessionsDeduped: z23.number(),
|
|
3292
3353
|
/** Deduped users for organic/non-paid AI sessions. */
|
|
3293
|
-
organicAiUsersDeduped:
|
|
3354
|
+
organicAiUsersDeduped: z23.number(),
|
|
3294
3355
|
/** AI sessions whose CURRENT sessionSource matched an AI engine. Can overlap with raw Organic/Social/Direct totals; `channelBreakdown` removes those overlaps for display. */
|
|
3295
|
-
aiSessionsBySession:
|
|
3356
|
+
aiSessionsBySession: z23.number(),
|
|
3296
3357
|
/** AI users whose CURRENT sessionSource matched an AI engine. Can overlap with raw Organic/Social/Direct totals. */
|
|
3297
|
-
aiUsersBySession:
|
|
3358
|
+
aiUsersBySession: z23.number(),
|
|
3298
3359
|
/** Session-source-only paid AI sessions. */
|
|
3299
|
-
paidAiSessionsBySession:
|
|
3360
|
+
paidAiSessionsBySession: z23.number(),
|
|
3300
3361
|
/** Session-source-only paid AI users. */
|
|
3301
|
-
paidAiUsersBySession:
|
|
3362
|
+
paidAiUsersBySession: z23.number(),
|
|
3302
3363
|
/** Session-source-only organic/non-paid AI sessions. */
|
|
3303
|
-
organicAiSessionsBySession:
|
|
3364
|
+
organicAiSessionsBySession: z23.number(),
|
|
3304
3365
|
/** Session-source-only organic/non-paid AI users. */
|
|
3305
|
-
organicAiUsersBySession:
|
|
3306
|
-
socialReferrals:
|
|
3366
|
+
organicAiUsersBySession: z23.number(),
|
|
3367
|
+
socialReferrals: z23.array(ga4SocialReferralDtoSchema),
|
|
3307
3368
|
/** Total social sessions (session-scoped, no cross-dimension dedup needed). */
|
|
3308
|
-
socialSessions:
|
|
3369
|
+
socialSessions: z23.number(),
|
|
3309
3370
|
/** Total social users (session-scoped, no cross-dimension dedup needed). */
|
|
3310
|
-
socialUsers:
|
|
3371
|
+
socialUsers: z23.number(),
|
|
3311
3372
|
/** Five disjoint buckets used for the channel breakdown. Known AI session-source matches are removed from their native GA4 bucket before shares are computed. */
|
|
3312
3373
|
channelBreakdown: ga4ChannelBreakdownDtoSchema,
|
|
3313
3374
|
/** Organic sessions as a percentage of total sessions (0–100, rounded). */
|
|
3314
|
-
organicSharePct:
|
|
3375
|
+
organicSharePct: z23.number(),
|
|
3315
3376
|
/** Deduped AI sessions as a percentage of total sessions (0–100, rounded). Cross-cutting: can overlap with Direct/Organic/Social. */
|
|
3316
|
-
aiSharePct:
|
|
3377
|
+
aiSharePct: z23.number(),
|
|
3317
3378
|
/** Session-source-only AI sessions as a percentage of total sessions (0–100, rounded). Can overlap with raw Organic/Social/Direct totals. */
|
|
3318
|
-
aiSharePctBySession:
|
|
3379
|
+
aiSharePctBySession: z23.number(),
|
|
3319
3380
|
/** Paid AI sessions as a percentage of total sessions (0–100, rounded). */
|
|
3320
|
-
paidAiSharePct:
|
|
3381
|
+
paidAiSharePct: z23.number(),
|
|
3321
3382
|
/** Session-source paid AI sessions as a percentage of total sessions (0–100, rounded). */
|
|
3322
|
-
paidAiSharePctBySession:
|
|
3383
|
+
paidAiSharePctBySession: z23.number(),
|
|
3323
3384
|
/** Organic/non-paid AI sessions as a percentage of total sessions (0–100, rounded). */
|
|
3324
|
-
organicAiSharePct:
|
|
3385
|
+
organicAiSharePct: z23.number(),
|
|
3325
3386
|
/** Session-source organic/non-paid AI sessions as a percentage of total sessions (0–100, rounded). */
|
|
3326
|
-
organicAiSharePctBySession:
|
|
3387
|
+
organicAiSharePctBySession: z23.number(),
|
|
3327
3388
|
/** Direct-channel sessions as a percentage of total sessions (0–100, rounded). */
|
|
3328
|
-
directSharePct:
|
|
3389
|
+
directSharePct: z23.number(),
|
|
3329
3390
|
/** Social sessions as a percentage of total sessions (0–100, rounded). */
|
|
3330
|
-
socialSharePct:
|
|
3391
|
+
socialSharePct: z23.number(),
|
|
3331
3392
|
/** Display string for organicSharePct: 'X%', '<1%' for non-zero shares that round below 1, or '—' when sessions exist but total is unknown (partial sync). */
|
|
3332
|
-
organicSharePctDisplay:
|
|
3393
|
+
organicSharePctDisplay: z23.string(),
|
|
3333
3394
|
/** Display string for aiSharePct: 'X%', '<1%' for non-zero shares that round below 1, or '—' when sessions exist but total is unknown (partial sync). */
|
|
3334
|
-
aiSharePctDisplay:
|
|
3395
|
+
aiSharePctDisplay: z23.string(),
|
|
3335
3396
|
/** Display string for aiSharePctBySession: 'X%', '<1%' for non-zero shares that round below 1, or '—' when sessions exist but total is unknown (partial sync). */
|
|
3336
|
-
aiSharePctBySessionDisplay:
|
|
3397
|
+
aiSharePctBySessionDisplay: z23.string(),
|
|
3337
3398
|
/** Display string for paidAiSharePct. */
|
|
3338
|
-
paidAiSharePctDisplay:
|
|
3399
|
+
paidAiSharePctDisplay: z23.string(),
|
|
3339
3400
|
/** Display string for paidAiSharePctBySession. */
|
|
3340
|
-
paidAiSharePctBySessionDisplay:
|
|
3401
|
+
paidAiSharePctBySessionDisplay: z23.string(),
|
|
3341
3402
|
/** Display string for organicAiSharePct. */
|
|
3342
|
-
organicAiSharePctDisplay:
|
|
3403
|
+
organicAiSharePctDisplay: z23.string(),
|
|
3343
3404
|
/** Display string for organicAiSharePctBySession. */
|
|
3344
|
-
organicAiSharePctBySessionDisplay:
|
|
3405
|
+
organicAiSharePctBySessionDisplay: z23.string(),
|
|
3345
3406
|
/** Display string for directSharePct: 'X%', '<1%' for non-zero shares that round below 1, or '—' when sessions exist but total is unknown (partial sync). */
|
|
3346
|
-
directSharePctDisplay:
|
|
3407
|
+
directSharePctDisplay: z23.string(),
|
|
3347
3408
|
/** Display string for socialSharePct: 'X%', '<1%' for non-zero shares that round below 1, or '—' when sessions exist but total is unknown (partial sync). */
|
|
3348
|
-
socialSharePctDisplay:
|
|
3409
|
+
socialSharePctDisplay: z23.string(),
|
|
3349
3410
|
/** Sessions not covered by Organic, Social, Direct, or AI (session) channels — e.g. Referral, Email, Paid Search, Display. Always non-negative; clamped to 0 when the four disjoint channels sum above total (rounding edge). */
|
|
3350
|
-
otherSessions:
|
|
3411
|
+
otherSessions: z23.number(),
|
|
3351
3412
|
/** Other sessions as a percentage of total sessions (0–100, rounded). */
|
|
3352
|
-
otherSharePct:
|
|
3413
|
+
otherSharePct: z23.number(),
|
|
3353
3414
|
/** Display string for otherSharePct: 'X%', '<1%' for non-zero shares that round below 1, or '—' when sessions exist but total is unknown (partial sync). */
|
|
3354
|
-
otherSharePctDisplay:
|
|
3355
|
-
lastSyncedAt:
|
|
3356
|
-
});
|
|
3357
|
-
var ga4StatusDtoSchema =
|
|
3358
|
-
connected:
|
|
3359
|
-
propertyId:
|
|
3360
|
-
clientEmail:
|
|
3361
|
-
authMethod:
|
|
3362
|
-
lastSyncedAt:
|
|
3363
|
-
createdAt:
|
|
3364
|
-
updatedAt:
|
|
3365
|
-
});
|
|
3366
|
-
var ga4SyncResponseDtoSchema =
|
|
3367
|
-
synced:
|
|
3368
|
-
rowCount:
|
|
3369
|
-
aiReferralCount:
|
|
3370
|
-
socialReferralCount:
|
|
3371
|
-
days:
|
|
3372
|
-
syncedAt:
|
|
3415
|
+
otherSharePctDisplay: z23.string(),
|
|
3416
|
+
lastSyncedAt: z23.string().nullable()
|
|
3417
|
+
});
|
|
3418
|
+
var ga4StatusDtoSchema = z23.object({
|
|
3419
|
+
connected: z23.boolean(),
|
|
3420
|
+
propertyId: z23.string().nullable(),
|
|
3421
|
+
clientEmail: z23.string().nullable(),
|
|
3422
|
+
authMethod: z23.enum(["service-account", "oauth"]).nullable(),
|
|
3423
|
+
lastSyncedAt: z23.string().nullable(),
|
|
3424
|
+
createdAt: z23.string().nullable().optional(),
|
|
3425
|
+
updatedAt: z23.string().nullable().optional()
|
|
3426
|
+
});
|
|
3427
|
+
var ga4SyncResponseDtoSchema = z23.object({
|
|
3428
|
+
synced: z23.boolean(),
|
|
3429
|
+
rowCount: z23.number().int().nonnegative(),
|
|
3430
|
+
aiReferralCount: z23.number().int().nonnegative(),
|
|
3431
|
+
socialReferralCount: z23.number().int().nonnegative(),
|
|
3432
|
+
days: z23.number().int().nonnegative(),
|
|
3433
|
+
syncedAt: z23.string(),
|
|
3373
3434
|
/**
|
|
3374
3435
|
* Components that were written this run. Present when `only` is set.
|
|
3375
3436
|
* Always includes `traffic` and `summary` (the share denominator) plus
|
|
3376
3437
|
* the requested channel breakdown — `ai` and/or `social`.
|
|
3377
3438
|
*/
|
|
3378
|
-
syncedComponents:
|
|
3439
|
+
syncedComponents: z23.array(z23.string()).optional()
|
|
3379
3440
|
});
|
|
3380
|
-
var ga4AiReferralHistoryEntrySchema =
|
|
3381
|
-
date:
|
|
3382
|
-
source:
|
|
3383
|
-
medium:
|
|
3441
|
+
var ga4AiReferralHistoryEntrySchema = z23.object({
|
|
3442
|
+
date: z23.string(),
|
|
3443
|
+
source: z23.string(),
|
|
3444
|
+
medium: z23.string(),
|
|
3384
3445
|
trafficClass: aiReferralTrafficClassSchema,
|
|
3385
|
-
landingPage:
|
|
3386
|
-
sessions:
|
|
3387
|
-
users:
|
|
3446
|
+
landingPage: z23.string(),
|
|
3447
|
+
sessions: z23.number(),
|
|
3448
|
+
users: z23.number(),
|
|
3388
3449
|
/** Which GA4 dimension this row came from: session (sessionSource), first_user (firstUserSource), or manual_utm (utm_source parameter) */
|
|
3389
3450
|
sourceDimension: ga4SourceDimensionSchema
|
|
3390
3451
|
});
|
|
3391
|
-
var ga4SocialReferralHistoryEntrySchema =
|
|
3392
|
-
date:
|
|
3393
|
-
source:
|
|
3394
|
-
medium:
|
|
3395
|
-
sessions:
|
|
3396
|
-
users:
|
|
3452
|
+
var ga4SocialReferralHistoryEntrySchema = z23.object({
|
|
3453
|
+
date: z23.string(),
|
|
3454
|
+
source: z23.string(),
|
|
3455
|
+
medium: z23.string(),
|
|
3456
|
+
sessions: z23.number(),
|
|
3457
|
+
users: z23.number(),
|
|
3397
3458
|
/** GA4 default channel group (e.g. 'Organic Social', 'Paid Social') */
|
|
3398
|
-
channelGroup:
|
|
3459
|
+
channelGroup: z23.string()
|
|
3399
3460
|
});
|
|
3400
|
-
var ga4SessionHistoryEntrySchema =
|
|
3401
|
-
date:
|
|
3402
|
-
sessions:
|
|
3403
|
-
organicSessions:
|
|
3404
|
-
users:
|
|
3461
|
+
var ga4SessionHistoryEntrySchema = z23.object({
|
|
3462
|
+
date: z23.string(),
|
|
3463
|
+
sessions: z23.number(),
|
|
3464
|
+
organicSessions: z23.number(),
|
|
3465
|
+
users: z23.number()
|
|
3405
3466
|
});
|
|
3406
3467
|
|
|
3407
3468
|
// ../contracts/src/answer-visibility.ts
|
|
@@ -3568,51 +3629,88 @@ function escapeRegExp(value) {
|
|
|
3568
3629
|
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
3569
3630
|
}
|
|
3570
3631
|
|
|
3632
|
+
// ../contracts/src/intelligence.ts
|
|
3633
|
+
import { z as z24 } from "zod";
|
|
3634
|
+
var healthSnapshotDtoSchema = z24.object({
|
|
3635
|
+
id: z24.string(),
|
|
3636
|
+
projectId: z24.string(),
|
|
3637
|
+
runId: z24.string().nullable(),
|
|
3638
|
+
overallCitedRate: z24.number(),
|
|
3639
|
+
/**
|
|
3640
|
+
* Share of (query × provider) pairs where the project was MENTIONED in the
|
|
3641
|
+
* answer text. Independent of `overallCitedRate` — never derived from it.
|
|
3642
|
+
* Legacy snapshots persisted before the mention columns existed read back
|
|
3643
|
+
* as 0 (the API coalesces NULL→0).
|
|
3644
|
+
*/
|
|
3645
|
+
overallMentionRate: z24.number(),
|
|
3646
|
+
totalPairs: z24.number().int().nonnegative(),
|
|
3647
|
+
citedPairs: z24.number().int().nonnegative(),
|
|
3648
|
+
/** Count of pairs mentioned in the answer text. Legacy rows read back as 0. */
|
|
3649
|
+
mentionedPairs: z24.number().int().nonnegative(),
|
|
3650
|
+
providerBreakdown: z24.record(z24.string(), z24.object({
|
|
3651
|
+
citedRate: z24.number(),
|
|
3652
|
+
mentionRate: z24.number(),
|
|
3653
|
+
cited: z24.number().int().nonnegative(),
|
|
3654
|
+
mentioned: z24.number().int().nonnegative(),
|
|
3655
|
+
total: z24.number().int().nonnegative()
|
|
3656
|
+
})),
|
|
3657
|
+
createdAt: z24.string(),
|
|
3658
|
+
/**
|
|
3659
|
+
* `'ready'` when the snapshot reflects real data; `'no-data'` for the
|
|
3660
|
+
* sentinel returned by `/health/latest` when a project has no health
|
|
3661
|
+
* snapshots yet (newly created, or only failed runs). Numeric fields are
|
|
3662
|
+
* zero and `providerBreakdown` is `{}` in the no-data case.
|
|
3663
|
+
*/
|
|
3664
|
+
status: z24.enum(["ready", "no-data"]),
|
|
3665
|
+
/** Reason for `status === 'no-data'`. Absent when `status === 'ready'`. */
|
|
3666
|
+
reason: z24.literal("no-runs-yet").optional()
|
|
3667
|
+
});
|
|
3668
|
+
|
|
3571
3669
|
// ../contracts/src/agent.ts
|
|
3572
|
-
import { z as
|
|
3573
|
-
var agentProviderIdSchema =
|
|
3574
|
-
var agentProviderOptionDtoSchema =
|
|
3670
|
+
import { z as z25 } from "zod";
|
|
3671
|
+
var agentProviderIdSchema = z25.enum(["claude", "openai", "gemini", "zai", "deepinfra"]);
|
|
3672
|
+
var agentProviderOptionDtoSchema = z25.object({
|
|
3575
3673
|
/** Stable identifier — what clients pass back as `provider` on the prompt endpoint. */
|
|
3576
3674
|
id: agentProviderIdSchema,
|
|
3577
3675
|
/** Human-readable label for UI pickers, e.g. "Anthropic (Claude)". */
|
|
3578
|
-
label:
|
|
3676
|
+
label: z25.string(),
|
|
3579
3677
|
/** Default model if the caller doesn't pick one. */
|
|
3580
|
-
defaultModel:
|
|
3678
|
+
defaultModel: z25.string(),
|
|
3581
3679
|
/** Whether a usable API key was found (config.yaml or provider env var). */
|
|
3582
|
-
configured:
|
|
3680
|
+
configured: z25.boolean(),
|
|
3583
3681
|
/**
|
|
3584
3682
|
* Where the key resolved from, if any. `null` when `configured === false`.
|
|
3585
3683
|
* Surfaced so the UI can nudge users toward their preferred source of truth.
|
|
3586
3684
|
*/
|
|
3587
|
-
keySource:
|
|
3685
|
+
keySource: z25.enum(["config", "env"]).nullable()
|
|
3588
3686
|
});
|
|
3589
|
-
var agentProvidersResponseDtoSchema =
|
|
3687
|
+
var agentProvidersResponseDtoSchema = z25.object({
|
|
3590
3688
|
/**
|
|
3591
3689
|
* Every provider Aero knows about. `configured === false` entries are
|
|
3592
3690
|
* included so the UI can render them disabled with an onboarding hint.
|
|
3593
3691
|
*/
|
|
3594
|
-
providers:
|
|
3692
|
+
providers: z25.array(agentProviderOptionDtoSchema).default([]),
|
|
3595
3693
|
/**
|
|
3596
3694
|
* Provider Aero auto-picks when no explicit override is passed. Null if
|
|
3597
3695
|
* nothing is configured (install never exchanged a key).
|
|
3598
3696
|
*/
|
|
3599
3697
|
defaultProvider: agentProviderIdSchema.nullable()
|
|
3600
3698
|
});
|
|
3601
|
-
var memorySourceSchema =
|
|
3699
|
+
var memorySourceSchema = z25.enum(["aero", "user", "compaction"]);
|
|
3602
3700
|
var MemorySources = memorySourceSchema.enum;
|
|
3603
3701
|
var AGENT_MEMORY_VALUE_MAX_BYTES = 2 * 1024;
|
|
3604
3702
|
var AGENT_MEMORY_KEY_MAX_LENGTH = 128;
|
|
3605
|
-
var agentMemoryUpsertRequestSchema =
|
|
3606
|
-
key:
|
|
3607
|
-
value:
|
|
3703
|
+
var agentMemoryUpsertRequestSchema = z25.object({
|
|
3704
|
+
key: z25.string().min(1).max(AGENT_MEMORY_KEY_MAX_LENGTH),
|
|
3705
|
+
value: z25.string().min(1)
|
|
3608
3706
|
});
|
|
3609
|
-
var agentMemoryDeleteRequestSchema =
|
|
3610
|
-
key:
|
|
3707
|
+
var agentMemoryDeleteRequestSchema = z25.object({
|
|
3708
|
+
key: z25.string().min(1).max(AGENT_MEMORY_KEY_MAX_LENGTH)
|
|
3611
3709
|
});
|
|
3612
3710
|
|
|
3613
3711
|
// ../contracts/src/backlinks.ts
|
|
3614
|
-
import { z as
|
|
3615
|
-
var backlinkSourceSchema =
|
|
3712
|
+
import { z as z26 } from "zod";
|
|
3713
|
+
var backlinkSourceSchema = z26.enum(["commoncrawl", "bing-webmaster"]);
|
|
3616
3714
|
var BacklinkSources = backlinkSourceSchema.enum;
|
|
3617
3715
|
function computeBacklinkSummaryMetrics(rows) {
|
|
3618
3716
|
if (rows.length === 0) {
|
|
@@ -3628,181 +3726,181 @@ function computeBacklinkSummaryMetrics(rows) {
|
|
|
3628
3726
|
top10HostsShare: share.toFixed(6)
|
|
3629
3727
|
};
|
|
3630
3728
|
}
|
|
3631
|
-
var ccReleaseSyncStatusSchema =
|
|
3729
|
+
var ccReleaseSyncStatusSchema = z26.enum(["queued", "downloading", "querying", "ready", "failed"]);
|
|
3632
3730
|
var CcReleaseSyncStatuses = ccReleaseSyncStatusSchema.enum;
|
|
3633
|
-
var ccReleaseSyncDtoSchema =
|
|
3634
|
-
id:
|
|
3635
|
-
release:
|
|
3731
|
+
var ccReleaseSyncDtoSchema = z26.object({
|
|
3732
|
+
id: z26.string(),
|
|
3733
|
+
release: z26.string(),
|
|
3636
3734
|
status: ccReleaseSyncStatusSchema,
|
|
3637
|
-
phaseDetail:
|
|
3638
|
-
vertexPath:
|
|
3639
|
-
edgesPath:
|
|
3640
|
-
vertexSha256:
|
|
3641
|
-
edgesSha256:
|
|
3642
|
-
vertexBytes:
|
|
3643
|
-
edgesBytes:
|
|
3644
|
-
projectsProcessed:
|
|
3645
|
-
domainsDiscovered:
|
|
3646
|
-
downloadStartedAt:
|
|
3647
|
-
downloadFinishedAt:
|
|
3648
|
-
queryStartedAt:
|
|
3649
|
-
queryFinishedAt:
|
|
3650
|
-
error:
|
|
3651
|
-
createdAt:
|
|
3652
|
-
updatedAt:
|
|
3735
|
+
phaseDetail: z26.string().nullable().optional(),
|
|
3736
|
+
vertexPath: z26.string().nullable().optional(),
|
|
3737
|
+
edgesPath: z26.string().nullable().optional(),
|
|
3738
|
+
vertexSha256: z26.string().nullable().optional(),
|
|
3739
|
+
edgesSha256: z26.string().nullable().optional(),
|
|
3740
|
+
vertexBytes: z26.number().int().nullable().optional(),
|
|
3741
|
+
edgesBytes: z26.number().int().nullable().optional(),
|
|
3742
|
+
projectsProcessed: z26.number().int().nullable().optional(),
|
|
3743
|
+
domainsDiscovered: z26.number().int().nullable().optional(),
|
|
3744
|
+
downloadStartedAt: z26.string().nullable().optional(),
|
|
3745
|
+
downloadFinishedAt: z26.string().nullable().optional(),
|
|
3746
|
+
queryStartedAt: z26.string().nullable().optional(),
|
|
3747
|
+
queryFinishedAt: z26.string().nullable().optional(),
|
|
3748
|
+
error: z26.string().nullable().optional(),
|
|
3749
|
+
createdAt: z26.string(),
|
|
3750
|
+
updatedAt: z26.string()
|
|
3653
3751
|
});
|
|
3654
|
-
var backlinkDomainDtoSchema =
|
|
3655
|
-
linkingDomain:
|
|
3752
|
+
var backlinkDomainDtoSchema = z26.object({
|
|
3753
|
+
linkingDomain: z26.string(),
|
|
3656
3754
|
// For Common Crawl this is the count of distinct hosts within the linking
|
|
3657
3755
|
// domain; for Bing Webmaster it is the count of distinct linking pages (URLs)
|
|
3658
3756
|
// from that linking host. Read alongside `source` — the unit differs per source.
|
|
3659
|
-
numHosts:
|
|
3757
|
+
numHosts: z26.number().int(),
|
|
3660
3758
|
source: backlinkSourceSchema
|
|
3661
3759
|
});
|
|
3662
|
-
var backlinkSummaryDtoSchema =
|
|
3663
|
-
projectId:
|
|
3760
|
+
var backlinkSummaryDtoSchema = z26.object({
|
|
3761
|
+
projectId: z26.string(),
|
|
3664
3762
|
// Window identifier. Common Crawl uses the release slug
|
|
3665
3763
|
// (`cc-main-YYYY-<mon>-<mon>-<mon>`); Bing Webmaster uses a synthetic
|
|
3666
3764
|
// per-sync-day window (`bing-YYYY-MM-DD`).
|
|
3667
|
-
release:
|
|
3668
|
-
targetDomain:
|
|
3669
|
-
totalLinkingDomains:
|
|
3670
|
-
totalHosts:
|
|
3671
|
-
top10HostsShare:
|
|
3672
|
-
queriedAt:
|
|
3765
|
+
release: z26.string(),
|
|
3766
|
+
targetDomain: z26.string(),
|
|
3767
|
+
totalLinkingDomains: z26.number().int(),
|
|
3768
|
+
totalHosts: z26.number().int(),
|
|
3769
|
+
top10HostsShare: z26.string(),
|
|
3770
|
+
queriedAt: z26.string(),
|
|
3673
3771
|
source: backlinkSourceSchema,
|
|
3674
3772
|
// Populated when the response is filtered (e.g. ?excludeCrawlers=1).
|
|
3675
3773
|
// Counts the rows omitted from totalLinkingDomains/totalHosts so callers
|
|
3676
3774
|
// can show "N hidden" hints without re-deriving them.
|
|
3677
|
-
excludedLinkingDomains:
|
|
3678
|
-
excludedHosts:
|
|
3775
|
+
excludedLinkingDomains: z26.number().int().optional(),
|
|
3776
|
+
excludedHosts: z26.number().int().optional()
|
|
3679
3777
|
});
|
|
3680
|
-
var backlinkListResponseSchema =
|
|
3778
|
+
var backlinkListResponseSchema = z26.object({
|
|
3681
3779
|
// The source this response was filtered to (defaults to commoncrawl when the
|
|
3682
3780
|
// caller omits `?source`).
|
|
3683
3781
|
source: backlinkSourceSchema,
|
|
3684
3782
|
summary: backlinkSummaryDtoSchema.nullable(),
|
|
3685
|
-
total:
|
|
3686
|
-
rows:
|
|
3687
|
-
});
|
|
3688
|
-
var backlinkHistoryEntrySchema =
|
|
3689
|
-
release:
|
|
3690
|
-
totalLinkingDomains:
|
|
3691
|
-
totalHosts:
|
|
3692
|
-
top10HostsShare:
|
|
3693
|
-
queriedAt:
|
|
3783
|
+
total: z26.number().int(),
|
|
3784
|
+
rows: z26.array(backlinkDomainDtoSchema)
|
|
3785
|
+
});
|
|
3786
|
+
var backlinkHistoryEntrySchema = z26.object({
|
|
3787
|
+
release: z26.string(),
|
|
3788
|
+
totalLinkingDomains: z26.number().int(),
|
|
3789
|
+
totalHosts: z26.number().int(),
|
|
3790
|
+
top10HostsShare: z26.string(),
|
|
3791
|
+
queriedAt: z26.string(),
|
|
3694
3792
|
source: backlinkSourceSchema
|
|
3695
3793
|
});
|
|
3696
|
-
var backlinkSourceAvailabilityDtoSchema =
|
|
3794
|
+
var backlinkSourceAvailabilityDtoSchema = z26.object({
|
|
3697
3795
|
source: backlinkSourceSchema,
|
|
3698
3796
|
/**
|
|
3699
3797
|
* The source is set up for this project:
|
|
3700
3798
|
* - commoncrawl: `autoExtractBacklinks` enabled AND a `ready` release sync exists.
|
|
3701
3799
|
* - bing-webmaster: a Bing Webmaster connection exists for the project domain.
|
|
3702
3800
|
*/
|
|
3703
|
-
connected:
|
|
3801
|
+
connected: z26.boolean(),
|
|
3704
3802
|
/** Backlink rows exist for this project + source. */
|
|
3705
|
-
hasData:
|
|
3803
|
+
hasData: z26.boolean(),
|
|
3706
3804
|
/** Latest window id with data for this source, null when none. */
|
|
3707
|
-
latestRelease:
|
|
3805
|
+
latestRelease: z26.string().nullable(),
|
|
3708
3806
|
/**
|
|
3709
3807
|
* Linking-domain count in the latest window. Excludes crawler/proxy hosts only
|
|
3710
3808
|
* when the request sets `?excludeCrawlers=1` (default off, matching the summary
|
|
3711
3809
|
* and domains endpoints); the dashboard passes it so the switcher pill matches
|
|
3712
3810
|
* the metric card.
|
|
3713
3811
|
*/
|
|
3714
|
-
totalLinkingDomains:
|
|
3812
|
+
totalLinkingDomains: z26.number().int(),
|
|
3715
3813
|
/** Freshness: `queriedAt` of the latest summary for this source, null when none. */
|
|
3716
|
-
lastSyncedAt:
|
|
3814
|
+
lastSyncedAt: z26.string().nullable()
|
|
3717
3815
|
});
|
|
3718
|
-
var backlinkSourcesResponseSchema =
|
|
3719
|
-
projectId:
|
|
3720
|
-
targetDomain:
|
|
3816
|
+
var backlinkSourcesResponseSchema = z26.object({
|
|
3817
|
+
projectId: z26.string(),
|
|
3818
|
+
targetDomain: z26.string(),
|
|
3721
3819
|
/** Availability for every known source, in a stable order. */
|
|
3722
|
-
sources:
|
|
3723
|
-
anyConnected:
|
|
3724
|
-
anyData:
|
|
3725
|
-
});
|
|
3726
|
-
var backlinksInstallStatusDtoSchema =
|
|
3727
|
-
duckdbInstalled:
|
|
3728
|
-
duckdbVersion:
|
|
3729
|
-
duckdbSpec:
|
|
3730
|
-
pluginDir:
|
|
3731
|
-
});
|
|
3732
|
-
var backlinksInstallResultDtoSchema =
|
|
3733
|
-
installed:
|
|
3734
|
-
version:
|
|
3735
|
-
path:
|
|
3736
|
-
alreadyPresent:
|
|
3737
|
-
});
|
|
3738
|
-
var ccAvailableReleaseSchema =
|
|
3739
|
-
release:
|
|
3740
|
-
vertexUrl:
|
|
3741
|
-
edgesUrl:
|
|
3742
|
-
vertexBytes:
|
|
3743
|
-
edgesBytes:
|
|
3744
|
-
lastModified:
|
|
3745
|
-
});
|
|
3746
|
-
var ccCachedReleaseSchema =
|
|
3747
|
-
release:
|
|
3820
|
+
sources: z26.array(backlinkSourceAvailabilityDtoSchema),
|
|
3821
|
+
anyConnected: z26.boolean(),
|
|
3822
|
+
anyData: z26.boolean()
|
|
3823
|
+
});
|
|
3824
|
+
var backlinksInstallStatusDtoSchema = z26.object({
|
|
3825
|
+
duckdbInstalled: z26.boolean(),
|
|
3826
|
+
duckdbVersion: z26.string().nullable().optional(),
|
|
3827
|
+
duckdbSpec: z26.string(),
|
|
3828
|
+
pluginDir: z26.string()
|
|
3829
|
+
});
|
|
3830
|
+
var backlinksInstallResultDtoSchema = z26.object({
|
|
3831
|
+
installed: z26.boolean(),
|
|
3832
|
+
version: z26.string(),
|
|
3833
|
+
path: z26.string(),
|
|
3834
|
+
alreadyPresent: z26.boolean()
|
|
3835
|
+
});
|
|
3836
|
+
var ccAvailableReleaseSchema = z26.object({
|
|
3837
|
+
release: z26.string(),
|
|
3838
|
+
vertexUrl: z26.string(),
|
|
3839
|
+
edgesUrl: z26.string(),
|
|
3840
|
+
vertexBytes: z26.number().int().nullable(),
|
|
3841
|
+
edgesBytes: z26.number().int().nullable(),
|
|
3842
|
+
lastModified: z26.string().nullable()
|
|
3843
|
+
});
|
|
3844
|
+
var ccCachedReleaseSchema = z26.object({
|
|
3845
|
+
release: z26.string(),
|
|
3748
3846
|
syncStatus: ccReleaseSyncStatusSchema.nullable(),
|
|
3749
|
-
bytes:
|
|
3750
|
-
lastUsedAt:
|
|
3847
|
+
bytes: z26.number().int(),
|
|
3848
|
+
lastUsedAt: z26.string().nullable()
|
|
3751
3849
|
});
|
|
3752
3850
|
|
|
3753
3851
|
// ../contracts/src/composites.ts
|
|
3754
|
-
import { z as
|
|
3755
|
-
var metricToneSchema =
|
|
3756
|
-
var scoreSummarySchema =
|
|
3757
|
-
label:
|
|
3758
|
-
value:
|
|
3759
|
-
delta:
|
|
3852
|
+
import { z as z27 } from "zod";
|
|
3853
|
+
var metricToneSchema = z27.enum(["positive", "caution", "negative", "neutral"]);
|
|
3854
|
+
var scoreSummarySchema = z27.object({
|
|
3855
|
+
label: z27.string(),
|
|
3856
|
+
value: z27.string(),
|
|
3857
|
+
delta: z27.string(),
|
|
3760
3858
|
tone: metricToneSchema,
|
|
3761
|
-
description:
|
|
3762
|
-
tooltip:
|
|
3763
|
-
trend:
|
|
3764
|
-
progress:
|
|
3765
|
-
providerCoverage:
|
|
3859
|
+
description: z27.string(),
|
|
3860
|
+
tooltip: z27.string().optional(),
|
|
3861
|
+
trend: z27.array(z27.number()),
|
|
3862
|
+
progress: z27.number().optional(),
|
|
3863
|
+
providerCoverage: z27.string().optional()
|
|
3766
3864
|
});
|
|
3767
3865
|
var mentionShareSchema = scoreSummarySchema.extend({
|
|
3768
|
-
breakdown:
|
|
3769
|
-
projectMentionSnapshots:
|
|
3770
|
-
competitorMentionSnapshots:
|
|
3771
|
-
perCompetitor:
|
|
3772
|
-
domain:
|
|
3773
|
-
mentionSnapshots:
|
|
3774
|
-
shareOfCompetitiveTotal:
|
|
3866
|
+
breakdown: z27.object({
|
|
3867
|
+
projectMentionSnapshots: z27.number().int().nonnegative(),
|
|
3868
|
+
competitorMentionSnapshots: z27.number().int().nonnegative(),
|
|
3869
|
+
perCompetitor: z27.array(z27.object({
|
|
3870
|
+
domain: z27.string(),
|
|
3871
|
+
mentionSnapshots: z27.number().int().nonnegative(),
|
|
3872
|
+
shareOfCompetitiveTotal: z27.number()
|
|
3775
3873
|
})),
|
|
3776
|
-
snapshotsWithAnswerText:
|
|
3777
|
-
snapshotsTotal:
|
|
3874
|
+
snapshotsWithAnswerText: z27.number().int().nonnegative(),
|
|
3875
|
+
snapshotsTotal: z27.number().int().nonnegative()
|
|
3778
3876
|
})
|
|
3779
3877
|
});
|
|
3780
|
-
var movementSummarySchema =
|
|
3781
|
-
gained:
|
|
3782
|
-
lost:
|
|
3878
|
+
var movementSummarySchema = z27.object({
|
|
3879
|
+
gained: z27.number().int().nonnegative(),
|
|
3880
|
+
lost: z27.number().int().nonnegative(),
|
|
3783
3881
|
tone: metricToneSchema,
|
|
3784
|
-
hasPreviousRun:
|
|
3785
|
-
gainedQueries:
|
|
3786
|
-
lostQueries:
|
|
3787
|
-
});
|
|
3788
|
-
var movementComparisonSchema =
|
|
3789
|
-
hasPreviousRun:
|
|
3790
|
-
comparable:
|
|
3791
|
-
querySetChanged:
|
|
3792
|
-
previousRunAt:
|
|
3793
|
-
currentQueryCount:
|
|
3794
|
-
previousQueryCount:
|
|
3795
|
-
comparableQueryCount:
|
|
3796
|
-
addedQueryCount:
|
|
3797
|
-
removedQueryCount:
|
|
3798
|
-
addedQueries:
|
|
3799
|
-
removedQueries:
|
|
3800
|
-
});
|
|
3801
|
-
var projectOverviewInsightSchema =
|
|
3802
|
-
id:
|
|
3803
|
-
projectId:
|
|
3804
|
-
runId:
|
|
3805
|
-
type:
|
|
3882
|
+
hasPreviousRun: z27.boolean(),
|
|
3883
|
+
gainedQueries: z27.array(z27.string()).optional(),
|
|
3884
|
+
lostQueries: z27.array(z27.string()).optional()
|
|
3885
|
+
});
|
|
3886
|
+
var movementComparisonSchema = z27.object({
|
|
3887
|
+
hasPreviousRun: z27.boolean(),
|
|
3888
|
+
comparable: z27.boolean(),
|
|
3889
|
+
querySetChanged: z27.boolean(),
|
|
3890
|
+
previousRunAt: z27.string().nullable(),
|
|
3891
|
+
currentQueryCount: z27.number().int().nonnegative(),
|
|
3892
|
+
previousQueryCount: z27.number().int().nonnegative(),
|
|
3893
|
+
comparableQueryCount: z27.number().int().nonnegative(),
|
|
3894
|
+
addedQueryCount: z27.number().int().nonnegative(),
|
|
3895
|
+
removedQueryCount: z27.number().int().nonnegative(),
|
|
3896
|
+
addedQueries: z27.array(z27.string()),
|
|
3897
|
+
removedQueries: z27.array(z27.string())
|
|
3898
|
+
});
|
|
3899
|
+
var projectOverviewInsightSchema = z27.object({
|
|
3900
|
+
id: z27.string(),
|
|
3901
|
+
projectId: z27.string(),
|
|
3902
|
+
runId: z27.string().nullable(),
|
|
3903
|
+
type: z27.enum([
|
|
3806
3904
|
"regression",
|
|
3807
3905
|
"gain",
|
|
3808
3906
|
"opportunity",
|
|
@@ -3818,70 +3916,70 @@ var projectOverviewInsightSchema = z25.object({
|
|
|
3818
3916
|
"gbp-metric-drop",
|
|
3819
3917
|
"gbp-keyword-drop"
|
|
3820
3918
|
]),
|
|
3821
|
-
severity:
|
|
3822
|
-
title:
|
|
3823
|
-
query:
|
|
3824
|
-
provider:
|
|
3825
|
-
recommendation:
|
|
3826
|
-
action:
|
|
3827
|
-
target:
|
|
3828
|
-
reason:
|
|
3919
|
+
severity: z27.enum(["critical", "high", "medium", "low"]),
|
|
3920
|
+
title: z27.string(),
|
|
3921
|
+
query: z27.string(),
|
|
3922
|
+
provider: z27.string(),
|
|
3923
|
+
recommendation: z27.object({
|
|
3924
|
+
action: z27.string(),
|
|
3925
|
+
target: z27.string().optional(),
|
|
3926
|
+
reason: z27.string()
|
|
3829
3927
|
}).optional(),
|
|
3830
|
-
cause:
|
|
3831
|
-
cause:
|
|
3832
|
-
competitorDomain:
|
|
3833
|
-
details:
|
|
3928
|
+
cause: z27.object({
|
|
3929
|
+
cause: z27.string(),
|
|
3930
|
+
competitorDomain: z27.string().optional(),
|
|
3931
|
+
details: z27.string().optional()
|
|
3834
3932
|
}).optional(),
|
|
3835
|
-
dismissed:
|
|
3836
|
-
createdAt:
|
|
3837
|
-
});
|
|
3838
|
-
var projectOverviewHealthSchema =
|
|
3839
|
-
id:
|
|
3840
|
-
projectId:
|
|
3841
|
-
runId:
|
|
3842
|
-
overallCitedRate:
|
|
3843
|
-
overallMentionRate:
|
|
3844
|
-
totalPairs:
|
|
3845
|
-
citedPairs:
|
|
3846
|
-
mentionedPairs:
|
|
3847
|
-
providerBreakdown:
|
|
3848
|
-
citedRate:
|
|
3849
|
-
mentionRate:
|
|
3850
|
-
cited:
|
|
3851
|
-
mentioned:
|
|
3852
|
-
total:
|
|
3933
|
+
dismissed: z27.boolean(),
|
|
3934
|
+
createdAt: z27.string()
|
|
3935
|
+
});
|
|
3936
|
+
var projectOverviewHealthSchema = z27.object({
|
|
3937
|
+
id: z27.string(),
|
|
3938
|
+
projectId: z27.string(),
|
|
3939
|
+
runId: z27.string().nullable(),
|
|
3940
|
+
overallCitedRate: z27.number(),
|
|
3941
|
+
overallMentionRate: z27.number(),
|
|
3942
|
+
totalPairs: z27.number().int().nonnegative(),
|
|
3943
|
+
citedPairs: z27.number().int().nonnegative(),
|
|
3944
|
+
mentionedPairs: z27.number().int().nonnegative(),
|
|
3945
|
+
providerBreakdown: z27.record(z27.string(), z27.object({
|
|
3946
|
+
citedRate: z27.number(),
|
|
3947
|
+
mentionRate: z27.number(),
|
|
3948
|
+
cited: z27.number().int().nonnegative(),
|
|
3949
|
+
mentioned: z27.number().int().nonnegative(),
|
|
3950
|
+
total: z27.number().int().nonnegative()
|
|
3853
3951
|
})),
|
|
3854
|
-
createdAt:
|
|
3855
|
-
status:
|
|
3856
|
-
reason:
|
|
3952
|
+
createdAt: z27.string(),
|
|
3953
|
+
status: z27.enum(["ready", "no-data"]),
|
|
3954
|
+
reason: z27.literal("no-runs-yet").optional()
|
|
3857
3955
|
});
|
|
3858
|
-
var projectOverviewDtoSchema =
|
|
3956
|
+
var projectOverviewDtoSchema = z27.object({
|
|
3859
3957
|
project: projectDtoSchema,
|
|
3860
3958
|
latestRun: latestProjectRunDtoSchema,
|
|
3861
3959
|
health: projectOverviewHealthSchema.nullable(),
|
|
3862
|
-
topInsights:
|
|
3863
|
-
queryCounts:
|
|
3864
|
-
totalQueries:
|
|
3865
|
-
citedQueries:
|
|
3866
|
-
notCitedQueries:
|
|
3867
|
-
citedRate:
|
|
3868
|
-
mentionedQueries:
|
|
3869
|
-
notMentionedQueries:
|
|
3870
|
-
mentionRate:
|
|
3960
|
+
topInsights: z27.array(projectOverviewInsightSchema),
|
|
3961
|
+
queryCounts: z27.object({
|
|
3962
|
+
totalQueries: z27.number().int().nonnegative(),
|
|
3963
|
+
citedQueries: z27.number().int().nonnegative(),
|
|
3964
|
+
notCitedQueries: z27.number().int().nonnegative(),
|
|
3965
|
+
citedRate: z27.number(),
|
|
3966
|
+
mentionedQueries: z27.number().int().nonnegative(),
|
|
3967
|
+
notMentionedQueries: z27.number().int().nonnegative(),
|
|
3968
|
+
mentionRate: z27.number()
|
|
3871
3969
|
}),
|
|
3872
|
-
providers:
|
|
3873
|
-
provider:
|
|
3874
|
-
citedRate:
|
|
3875
|
-
cited:
|
|
3876
|
-
total:
|
|
3970
|
+
providers: z27.array(z27.object({
|
|
3971
|
+
provider: z27.string(),
|
|
3972
|
+
citedRate: z27.number(),
|
|
3973
|
+
cited: z27.number().int().nonnegative(),
|
|
3974
|
+
total: z27.number().int().nonnegative()
|
|
3877
3975
|
})),
|
|
3878
|
-
transitions:
|
|
3879
|
-
since:
|
|
3880
|
-
gained:
|
|
3881
|
-
lost:
|
|
3882
|
-
emerging:
|
|
3976
|
+
transitions: z27.object({
|
|
3977
|
+
since: z27.string().nullable(),
|
|
3978
|
+
gained: z27.number().int().nonnegative(),
|
|
3979
|
+
lost: z27.number().int().nonnegative(),
|
|
3980
|
+
emerging: z27.number().int().nonnegative()
|
|
3883
3981
|
}),
|
|
3884
|
-
scores:
|
|
3982
|
+
scores: z27.object({
|
|
3885
3983
|
mention: scoreSummarySchema,
|
|
3886
3984
|
visibility: scoreSummarySchema,
|
|
3887
3985
|
mentionShare: mentionShareSchema,
|
|
@@ -3895,72 +3993,72 @@ var projectOverviewDtoSchema = z25.object({
|
|
|
3895
3993
|
citationMovement: movementSummarySchema,
|
|
3896
3994
|
mentionMovement: movementSummarySchema,
|
|
3897
3995
|
movementComparison: movementComparisonSchema,
|
|
3898
|
-
competitors:
|
|
3899
|
-
id:
|
|
3900
|
-
domain:
|
|
3901
|
-
citationCount:
|
|
3902
|
-
totalQueries:
|
|
3903
|
-
pressureLabel:
|
|
3904
|
-
citedQueries:
|
|
3996
|
+
competitors: z27.array(z27.object({
|
|
3997
|
+
id: z27.string(),
|
|
3998
|
+
domain: z27.string(),
|
|
3999
|
+
citationCount: z27.number().int().nonnegative(),
|
|
4000
|
+
totalQueries: z27.number().int().nonnegative(),
|
|
4001
|
+
pressureLabel: z27.enum(["None", "Low", "Moderate", "High"]),
|
|
4002
|
+
citedQueries: z27.array(z27.string())
|
|
3905
4003
|
})),
|
|
3906
|
-
providerScores:
|
|
3907
|
-
provider:
|
|
3908
|
-
model:
|
|
3909
|
-
score:
|
|
3910
|
-
cited:
|
|
3911
|
-
total:
|
|
3912
|
-
trend:
|
|
4004
|
+
providerScores: z27.array(z27.object({
|
|
4005
|
+
provider: z27.string(),
|
|
4006
|
+
model: z27.string().nullable(),
|
|
4007
|
+
score: z27.number(),
|
|
4008
|
+
cited: z27.number().int().nonnegative(),
|
|
4009
|
+
total: z27.number().int().nonnegative(),
|
|
4010
|
+
trend: z27.array(z27.number()).optional()
|
|
3913
4011
|
})),
|
|
3914
|
-
attentionItems:
|
|
3915
|
-
id:
|
|
4012
|
+
attentionItems: z27.array(z27.object({
|
|
4013
|
+
id: z27.string(),
|
|
3916
4014
|
tone: metricToneSchema,
|
|
3917
|
-
title:
|
|
3918
|
-
detail:
|
|
3919
|
-
actionLabel:
|
|
3920
|
-
href:
|
|
4015
|
+
title: z27.string(),
|
|
4016
|
+
detail: z27.string(),
|
|
4017
|
+
actionLabel: z27.string(),
|
|
4018
|
+
href: z27.string()
|
|
3921
4019
|
})),
|
|
3922
|
-
runHistory:
|
|
3923
|
-
runId:
|
|
3924
|
-
createdAt:
|
|
3925
|
-
citedCount:
|
|
3926
|
-
totalCount:
|
|
3927
|
-
citationRate:
|
|
3928
|
-
mentionedCount:
|
|
3929
|
-
mentionRate:
|
|
3930
|
-
status:
|
|
4020
|
+
runHistory: z27.array(z27.object({
|
|
4021
|
+
runId: z27.string(),
|
|
4022
|
+
createdAt: z27.string(),
|
|
4023
|
+
citedCount: z27.number().int().nonnegative(),
|
|
4024
|
+
totalCount: z27.number().int().nonnegative(),
|
|
4025
|
+
citationRate: z27.number(),
|
|
4026
|
+
mentionedCount: z27.number().int().nonnegative(),
|
|
4027
|
+
mentionRate: z27.number(),
|
|
4028
|
+
status: z27.string()
|
|
3931
4029
|
})),
|
|
3932
|
-
suggestedQueries:
|
|
3933
|
-
rows:
|
|
3934
|
-
query:
|
|
3935
|
-
impressions:
|
|
3936
|
-
clicks:
|
|
3937
|
-
avgPosition:
|
|
3938
|
-
reason:
|
|
4030
|
+
suggestedQueries: z27.object({
|
|
4031
|
+
rows: z27.array(z27.object({
|
|
4032
|
+
query: z27.string(),
|
|
4033
|
+
impressions: z27.number(),
|
|
4034
|
+
clicks: z27.number(),
|
|
4035
|
+
avgPosition: z27.number(),
|
|
4036
|
+
reason: z27.string()
|
|
3939
4037
|
})),
|
|
3940
|
-
totalCandidates:
|
|
3941
|
-
skippedAlreadyTracked:
|
|
4038
|
+
totalCandidates: z27.number().int().nonnegative(),
|
|
4039
|
+
skippedAlreadyTracked: z27.number().int().nonnegative()
|
|
3942
4040
|
}),
|
|
3943
|
-
dateRangeLabel:
|
|
3944
|
-
contextLabel:
|
|
3945
|
-
});
|
|
3946
|
-
var searchHitKindSchema =
|
|
3947
|
-
var projectSearchSnapshotHitSchema =
|
|
3948
|
-
kind:
|
|
3949
|
-
id:
|
|
3950
|
-
runId:
|
|
3951
|
-
query:
|
|
3952
|
-
provider:
|
|
3953
|
-
model:
|
|
4041
|
+
dateRangeLabel: z27.string(),
|
|
4042
|
+
contextLabel: z27.string()
|
|
4043
|
+
});
|
|
4044
|
+
var searchHitKindSchema = z27.enum(["snapshot", "insight"]);
|
|
4045
|
+
var projectSearchSnapshotHitSchema = z27.object({
|
|
4046
|
+
kind: z27.literal("snapshot"),
|
|
4047
|
+
id: z27.string(),
|
|
4048
|
+
runId: z27.string(),
|
|
4049
|
+
query: z27.string(),
|
|
4050
|
+
provider: z27.string(),
|
|
4051
|
+
model: z27.string().nullable(),
|
|
3954
4052
|
citationState: citationStateSchema,
|
|
3955
|
-
matchedField:
|
|
3956
|
-
snippet:
|
|
3957
|
-
createdAt:
|
|
3958
|
-
});
|
|
3959
|
-
var projectSearchInsightHitSchema =
|
|
3960
|
-
kind:
|
|
3961
|
-
id:
|
|
3962
|
-
runId:
|
|
3963
|
-
type:
|
|
4053
|
+
matchedField: z27.enum(["answerText", "citedDomains", "searchQueries", "query"]),
|
|
4054
|
+
snippet: z27.string(),
|
|
4055
|
+
createdAt: z27.string()
|
|
4056
|
+
});
|
|
4057
|
+
var projectSearchInsightHitSchema = z27.object({
|
|
4058
|
+
kind: z27.literal("insight"),
|
|
4059
|
+
id: z27.string(),
|
|
4060
|
+
runId: z27.string().nullable(),
|
|
4061
|
+
type: z27.enum([
|
|
3964
4062
|
"regression",
|
|
3965
4063
|
"gain",
|
|
3966
4064
|
"opportunity",
|
|
@@ -3977,29 +4075,29 @@ var projectSearchInsightHitSchema = z25.object({
|
|
|
3977
4075
|
"gbp-metric-drop",
|
|
3978
4076
|
"gbp-keyword-drop"
|
|
3979
4077
|
]),
|
|
3980
|
-
severity:
|
|
3981
|
-
title:
|
|
3982
|
-
query:
|
|
3983
|
-
provider:
|
|
3984
|
-
matchedField:
|
|
3985
|
-
snippet:
|
|
3986
|
-
dismissed:
|
|
3987
|
-
createdAt:
|
|
3988
|
-
});
|
|
3989
|
-
var projectSearchHitSchema =
|
|
4078
|
+
severity: z27.enum(["critical", "high", "medium", "low"]),
|
|
4079
|
+
title: z27.string(),
|
|
4080
|
+
query: z27.string(),
|
|
4081
|
+
provider: z27.string(),
|
|
4082
|
+
matchedField: z27.enum(["title", "query", "recommendation", "cause"]),
|
|
4083
|
+
snippet: z27.string(),
|
|
4084
|
+
dismissed: z27.boolean(),
|
|
4085
|
+
createdAt: z27.string()
|
|
4086
|
+
});
|
|
4087
|
+
var projectSearchHitSchema = z27.discriminatedUnion("kind", [
|
|
3990
4088
|
projectSearchSnapshotHitSchema,
|
|
3991
4089
|
projectSearchInsightHitSchema
|
|
3992
4090
|
]);
|
|
3993
|
-
var projectSearchResponseSchema =
|
|
3994
|
-
query:
|
|
3995
|
-
totalHits:
|
|
3996
|
-
truncated:
|
|
3997
|
-
hits:
|
|
4091
|
+
var projectSearchResponseSchema = z27.object({
|
|
4092
|
+
query: z27.string(),
|
|
4093
|
+
totalHits: z27.number().int().nonnegative(),
|
|
4094
|
+
truncated: z27.boolean(),
|
|
4095
|
+
hits: z27.array(projectSearchHitSchema)
|
|
3998
4096
|
});
|
|
3999
4097
|
|
|
4000
4098
|
// ../contracts/src/content.ts
|
|
4001
|
-
import { z as
|
|
4002
|
-
var contentActionSchema =
|
|
4099
|
+
import { z as z28 } from "zod";
|
|
4100
|
+
var contentActionSchema = z28.enum(["create", "expand", "refresh", "add-schema"]);
|
|
4003
4101
|
var ContentActions = contentActionSchema.enum;
|
|
4004
4102
|
function contentActionLabel(action) {
|
|
4005
4103
|
switch (action) {
|
|
@@ -4013,9 +4111,9 @@ function contentActionLabel(action) {
|
|
|
4013
4111
|
return "Add schema";
|
|
4014
4112
|
}
|
|
4015
4113
|
}
|
|
4016
|
-
var demandSourceSchema =
|
|
4114
|
+
var demandSourceSchema = z28.enum(["gsc", "competitor-evidence", "both"]);
|
|
4017
4115
|
var DemandSources = demandSourceSchema.enum;
|
|
4018
|
-
var actionConfidenceSchema =
|
|
4116
|
+
var actionConfidenceSchema = z28.enum(["high", "medium", "low"]);
|
|
4019
4117
|
var ActionConfidences = actionConfidenceSchema.enum;
|
|
4020
4118
|
function actionConfidenceLabel(confidence) {
|
|
4021
4119
|
switch (confidence) {
|
|
@@ -4027,7 +4125,7 @@ function actionConfidenceLabel(confidence) {
|
|
|
4027
4125
|
return "Low";
|
|
4028
4126
|
}
|
|
4029
4127
|
}
|
|
4030
|
-
var pageTypeSchema =
|
|
4128
|
+
var pageTypeSchema = z28.enum([
|
|
4031
4129
|
"blog-post",
|
|
4032
4130
|
"comparison",
|
|
4033
4131
|
"listicle",
|
|
@@ -4036,7 +4134,7 @@ var pageTypeSchema = z26.enum([
|
|
|
4036
4134
|
"glossary"
|
|
4037
4135
|
]);
|
|
4038
4136
|
var PageTypes = pageTypeSchema.enum;
|
|
4039
|
-
var contentActionStateSchema =
|
|
4137
|
+
var contentActionStateSchema = z28.enum([
|
|
4040
4138
|
"proposed",
|
|
4041
4139
|
"briefed",
|
|
4042
4140
|
"payload-generated",
|
|
@@ -4046,7 +4144,7 @@ var contentActionStateSchema = z26.enum([
|
|
|
4046
4144
|
"dismissed"
|
|
4047
4145
|
]);
|
|
4048
4146
|
var ContentActionStates = contentActionStateSchema.enum;
|
|
4049
|
-
var winnabilityClassSchema =
|
|
4147
|
+
var winnabilityClassSchema = z28.enum(["ownable", "ceded"]);
|
|
4050
4148
|
var WinnabilityClasses = winnabilityClassSchema.enum;
|
|
4051
4149
|
function winnabilityClassLabel(winnabilityClass) {
|
|
4052
4150
|
switch (winnabilityClass) {
|
|
@@ -4081,40 +4179,40 @@ function deriveWinnabilityClass(citedSurfaceDomains, surfaceClasses, threshold =
|
|
|
4081
4179
|
winnability
|
|
4082
4180
|
};
|
|
4083
4181
|
}
|
|
4084
|
-
var ourBestPageSchema =
|
|
4085
|
-
url:
|
|
4086
|
-
gscImpressions:
|
|
4087
|
-
gscClicks:
|
|
4182
|
+
var ourBestPageSchema = z28.object({
|
|
4183
|
+
url: z28.string(),
|
|
4184
|
+
gscImpressions: z28.number().nonnegative(),
|
|
4185
|
+
gscClicks: z28.number().nonnegative(),
|
|
4088
4186
|
// Null when the page came from the inventory fallback (no GSC ranking data).
|
|
4089
|
-
gscAvgPosition:
|
|
4090
|
-
organicSessions:
|
|
4091
|
-
});
|
|
4092
|
-
var winningCompetitorSchema =
|
|
4093
|
-
domain:
|
|
4094
|
-
url:
|
|
4095
|
-
title:
|
|
4096
|
-
citationCount:
|
|
4097
|
-
});
|
|
4098
|
-
var scoreBreakdownSchema =
|
|
4099
|
-
demand:
|
|
4100
|
-
competitor:
|
|
4101
|
-
absence:
|
|
4102
|
-
gapSeverity:
|
|
4103
|
-
});
|
|
4104
|
-
var existingActionRefSchema =
|
|
4105
|
-
actionId:
|
|
4187
|
+
gscAvgPosition: z28.number().nonnegative().nullable(),
|
|
4188
|
+
organicSessions: z28.number().nonnegative()
|
|
4189
|
+
});
|
|
4190
|
+
var winningCompetitorSchema = z28.object({
|
|
4191
|
+
domain: z28.string(),
|
|
4192
|
+
url: z28.string(),
|
|
4193
|
+
title: z28.string(),
|
|
4194
|
+
citationCount: z28.number().int().nonnegative()
|
|
4195
|
+
});
|
|
4196
|
+
var scoreBreakdownSchema = z28.object({
|
|
4197
|
+
demand: z28.number(),
|
|
4198
|
+
competitor: z28.number(),
|
|
4199
|
+
absence: z28.number(),
|
|
4200
|
+
gapSeverity: z28.number()
|
|
4201
|
+
});
|
|
4202
|
+
var existingActionRefSchema = z28.object({
|
|
4203
|
+
actionId: z28.string(),
|
|
4106
4204
|
state: contentActionStateSchema,
|
|
4107
|
-
lastUpdated:
|
|
4205
|
+
lastUpdated: z28.string()
|
|
4108
4206
|
});
|
|
4109
|
-
var contentTargetRowDtoSchema =
|
|
4110
|
-
targetRef:
|
|
4111
|
-
query:
|
|
4207
|
+
var contentTargetRowDtoSchema = z28.object({
|
|
4208
|
+
targetRef: z28.string(),
|
|
4209
|
+
query: z28.string(),
|
|
4112
4210
|
action: contentActionSchema,
|
|
4113
4211
|
ourBestPage: ourBestPageSchema.nullable(),
|
|
4114
4212
|
winningCompetitor: winningCompetitorSchema.nullable(),
|
|
4115
|
-
score:
|
|
4213
|
+
score: z28.number(),
|
|
4116
4214
|
scoreBreakdown: scoreBreakdownSchema,
|
|
4117
|
-
drivers:
|
|
4215
|
+
drivers: z28.array(z28.string()),
|
|
4118
4216
|
demandSource: demandSourceSchema,
|
|
4119
4217
|
actionConfidence: actionConfidenceSchema,
|
|
4120
4218
|
existingAction: existingActionRefSchema.nullable(),
|
|
@@ -4129,134 +4227,134 @@ var contentTargetRowDtoSchema = z26.object({
|
|
|
4129
4227
|
* `[0, 1]`. `null` when the gate failed open (no classification coverage for
|
|
4130
4228
|
* the cited surface) — distinct from a computed `1.0`.
|
|
4131
4229
|
*/
|
|
4132
|
-
winnability:
|
|
4133
|
-
});
|
|
4134
|
-
var contentTargetsResponseDtoSchema =
|
|
4135
|
-
targets:
|
|
4136
|
-
contextMetrics:
|
|
4137
|
-
totalAiReferralSessions:
|
|
4138
|
-
latestRunId:
|
|
4139
|
-
runTimestamp:
|
|
4230
|
+
winnability: z28.number().min(0).max(1).nullable()
|
|
4231
|
+
});
|
|
4232
|
+
var contentTargetsResponseDtoSchema = z28.object({
|
|
4233
|
+
targets: z28.array(contentTargetRowDtoSchema),
|
|
4234
|
+
contextMetrics: z28.object({
|
|
4235
|
+
totalAiReferralSessions: z28.number().int().nonnegative(),
|
|
4236
|
+
latestRunId: z28.string(),
|
|
4237
|
+
runTimestamp: z28.string()
|
|
4140
4238
|
})
|
|
4141
4239
|
});
|
|
4142
|
-
var contentTargetDismissalDtoSchema =
|
|
4143
|
-
targetRef:
|
|
4144
|
-
addressedUrl:
|
|
4145
|
-
note:
|
|
4146
|
-
dismissedAt:
|
|
4240
|
+
var contentTargetDismissalDtoSchema = z28.object({
|
|
4241
|
+
targetRef: z28.string(),
|
|
4242
|
+
addressedUrl: z28.string().nullable(),
|
|
4243
|
+
note: z28.string().nullable(),
|
|
4244
|
+
dismissedAt: z28.string()
|
|
4147
4245
|
});
|
|
4148
|
-
var contentTargetDismissalsResponseDtoSchema =
|
|
4149
|
-
dismissals:
|
|
4246
|
+
var contentTargetDismissalsResponseDtoSchema = z28.object({
|
|
4247
|
+
dismissals: z28.array(contentTargetDismissalDtoSchema)
|
|
4150
4248
|
});
|
|
4151
|
-
var contentTargetDismissRequestSchema =
|
|
4152
|
-
targetRef:
|
|
4249
|
+
var contentTargetDismissRequestSchema = z28.object({
|
|
4250
|
+
targetRef: z28.string().min(1),
|
|
4153
4251
|
/** URL of the page the user wrote that addresses this recommendation. Stored verbatim for the audit trail; not currently used to suppress the slug-token matcher. */
|
|
4154
|
-
addressedUrl:
|
|
4252
|
+
addressedUrl: z28.string().url().optional(),
|
|
4155
4253
|
/** Free-form note (e.g. "covered in our Q1 content sprint"). 500 char cap is the API surface limit; the DB column is unbounded. */
|
|
4156
|
-
note:
|
|
4254
|
+
note: z28.string().max(500).optional()
|
|
4157
4255
|
});
|
|
4158
|
-
var recommendationExplanationDtoSchema =
|
|
4159
|
-
targetRef:
|
|
4256
|
+
var recommendationExplanationDtoSchema = z28.object({
|
|
4257
|
+
targetRef: z28.string(),
|
|
4160
4258
|
/** Version of the prompt template used. Bumping the version invalidates the cache forward without touching the table. */
|
|
4161
|
-
promptVersion:
|
|
4259
|
+
promptVersion: z28.string(),
|
|
4162
4260
|
/** Provider that produced the explanation (e.g. "claude", "gemini"). */
|
|
4163
|
-
provider:
|
|
4261
|
+
provider: z28.string(),
|
|
4164
4262
|
/** Model id within that provider (e.g. "claude-sonnet-4-6"). */
|
|
4165
|
-
model:
|
|
4263
|
+
model: z28.string(),
|
|
4166
4264
|
/** Markdown-formatted rationale + recommended next steps. */
|
|
4167
|
-
responseText:
|
|
4265
|
+
responseText: z28.string(),
|
|
4168
4266
|
/** Estimated cost in millicents (1/100 of a cent). 0 when unknown. */
|
|
4169
|
-
costMillicents:
|
|
4170
|
-
generatedAt:
|
|
4267
|
+
costMillicents: z28.number().int().nonnegative(),
|
|
4268
|
+
generatedAt: z28.string()
|
|
4171
4269
|
});
|
|
4172
|
-
var recommendationExplainRequestSchema =
|
|
4270
|
+
var recommendationExplainRequestSchema = z28.object({
|
|
4173
4271
|
/**
|
|
4174
4272
|
* Optional provider override (e.g. "claude" to force Claude even if
|
|
4175
4273
|
* the project's default is Gemini). Falls through to project default
|
|
4176
4274
|
* → auto-detect when omitted.
|
|
4177
4275
|
*/
|
|
4178
|
-
provider:
|
|
4276
|
+
provider: z28.string().optional(),
|
|
4179
4277
|
/**
|
|
4180
4278
|
* Optional model override within the chosen provider. Falls through to
|
|
4181
4279
|
* the `analyze`-tier default model when omitted.
|
|
4182
4280
|
*/
|
|
4183
|
-
model:
|
|
4281
|
+
model: z28.string().optional(),
|
|
4184
4282
|
/**
|
|
4185
4283
|
* Force a fresh LLM call even if a cached explanation exists for the
|
|
4186
4284
|
* current prompt version. Use sparingly — defeats the cache.
|
|
4187
4285
|
*/
|
|
4188
|
-
forceRefresh:
|
|
4286
|
+
forceRefresh: z28.boolean().optional()
|
|
4189
4287
|
});
|
|
4190
|
-
var contentBriefDtoSchema =
|
|
4288
|
+
var contentBriefDtoSchema = z28.object({
|
|
4191
4289
|
/** The query the brief is for (echoed from the recommendation). */
|
|
4192
|
-
targetQuery:
|
|
4290
|
+
targetQuery: z28.string().trim().min(1),
|
|
4193
4291
|
/** Always `ownable` in practice — the gate rejects `ceded` before synthesis. */
|
|
4194
4292
|
winnabilityClass: winnabilityClassSchema,
|
|
4195
4293
|
/** The differentiated content angle to take. */
|
|
4196
|
-
angle:
|
|
4294
|
+
angle: z28.string().trim().min(1),
|
|
4197
4295
|
/** Why this query is winnable, citing the cited-surface signal. */
|
|
4198
|
-
whyWinnable:
|
|
4296
|
+
whyWinnable: z28.string().trim().min(1),
|
|
4199
4297
|
/** The schema.org type or markup to add or extend. */
|
|
4200
|
-
schemaHookup:
|
|
4298
|
+
schemaHookup: z28.string().trim().min(1),
|
|
4201
4299
|
/** Why the cited surface is controllable (the ownable-vs-ceded reasoning). */
|
|
4202
|
-
controllableSurfaceRationale:
|
|
4300
|
+
controllableSurfaceRationale: z28.string().trim().min(1)
|
|
4203
4301
|
});
|
|
4204
|
-
var recommendationBriefDtoSchema =
|
|
4205
|
-
targetRef:
|
|
4302
|
+
var recommendationBriefDtoSchema = z28.object({
|
|
4303
|
+
targetRef: z28.string(),
|
|
4206
4304
|
/** Version of the brief prompt template; bumping invalidates the cache forward. */
|
|
4207
|
-
promptVersion:
|
|
4208
|
-
provider:
|
|
4209
|
-
model:
|
|
4305
|
+
promptVersion: z28.string(),
|
|
4306
|
+
provider: z28.string(),
|
|
4307
|
+
model: z28.string(),
|
|
4210
4308
|
brief: contentBriefDtoSchema,
|
|
4211
4309
|
/** Estimated cost in millicents (1/100 of a cent). 0 when unknown. */
|
|
4212
|
-
costMillicents:
|
|
4213
|
-
generatedAt:
|
|
4310
|
+
costMillicents: z28.number().int().nonnegative(),
|
|
4311
|
+
generatedAt: z28.string()
|
|
4214
4312
|
});
|
|
4215
|
-
var domainClassificationDtoSchema =
|
|
4216
|
-
domain:
|
|
4313
|
+
var domainClassificationDtoSchema = z28.object({
|
|
4314
|
+
domain: z28.string(),
|
|
4217
4315
|
competitorType: discoveryCompetitorTypeSchema,
|
|
4218
|
-
hits:
|
|
4219
|
-
updatedAt:
|
|
4316
|
+
hits: z28.number().int().nonnegative(),
|
|
4317
|
+
updatedAt: z28.string()
|
|
4318
|
+
});
|
|
4319
|
+
var domainClassificationsResponseDtoSchema = z28.object({
|
|
4320
|
+
classifications: z28.array(domainClassificationDtoSchema)
|
|
4321
|
+
});
|
|
4322
|
+
var contentGroundingSourceSchema = z28.object({
|
|
4323
|
+
uri: z28.string(),
|
|
4324
|
+
title: z28.string(),
|
|
4325
|
+
domain: z28.string(),
|
|
4326
|
+
isOurDomain: z28.boolean(),
|
|
4327
|
+
isCompetitor: z28.boolean(),
|
|
4328
|
+
citationCount: z28.number().int().nonnegative(),
|
|
4329
|
+
providers: z28.array(providerNameSchema)
|
|
4330
|
+
});
|
|
4331
|
+
var contentSourceRowDtoSchema = z28.object({
|
|
4332
|
+
query: z28.string(),
|
|
4333
|
+
groundingSources: z28.array(contentGroundingSourceSchema)
|
|
4334
|
+
});
|
|
4335
|
+
var contentSourcesResponseDtoSchema = z28.object({
|
|
4336
|
+
sources: z28.array(contentSourceRowDtoSchema),
|
|
4337
|
+
latestRunId: z28.string()
|
|
4338
|
+
});
|
|
4339
|
+
var contentGapRowDtoSchema = z28.object({
|
|
4340
|
+
query: z28.string(),
|
|
4341
|
+
competitorDomains: z28.array(z28.string()),
|
|
4342
|
+
competitorCount: z28.number().int().nonnegative(),
|
|
4343
|
+
missRate: z28.number().min(0).max(1),
|
|
4344
|
+
lastSeenInRunId: z28.string()
|
|
4220
4345
|
});
|
|
4221
|
-
var
|
|
4222
|
-
|
|
4223
|
-
|
|
4224
|
-
var contentGroundingSourceSchema = z26.object({
|
|
4225
|
-
uri: z26.string(),
|
|
4226
|
-
title: z26.string(),
|
|
4227
|
-
domain: z26.string(),
|
|
4228
|
-
isOurDomain: z26.boolean(),
|
|
4229
|
-
isCompetitor: z26.boolean(),
|
|
4230
|
-
citationCount: z26.number().int().nonnegative(),
|
|
4231
|
-
providers: z26.array(providerNameSchema)
|
|
4232
|
-
});
|
|
4233
|
-
var contentSourceRowDtoSchema = z26.object({
|
|
4234
|
-
query: z26.string(),
|
|
4235
|
-
groundingSources: z26.array(contentGroundingSourceSchema)
|
|
4236
|
-
});
|
|
4237
|
-
var contentSourcesResponseDtoSchema = z26.object({
|
|
4238
|
-
sources: z26.array(contentSourceRowDtoSchema),
|
|
4239
|
-
latestRunId: z26.string()
|
|
4240
|
-
});
|
|
4241
|
-
var contentGapRowDtoSchema = z26.object({
|
|
4242
|
-
query: z26.string(),
|
|
4243
|
-
competitorDomains: z26.array(z26.string()),
|
|
4244
|
-
competitorCount: z26.number().int().nonnegative(),
|
|
4245
|
-
missRate: z26.number().min(0).max(1),
|
|
4246
|
-
lastSeenInRunId: z26.string()
|
|
4247
|
-
});
|
|
4248
|
-
var contentGapsResponseDtoSchema = z26.object({
|
|
4249
|
-
gaps: z26.array(contentGapRowDtoSchema),
|
|
4250
|
-
latestRunId: z26.string()
|
|
4346
|
+
var contentGapsResponseDtoSchema = z28.object({
|
|
4347
|
+
gaps: z28.array(contentGapRowDtoSchema),
|
|
4348
|
+
latestRunId: z28.string()
|
|
4251
4349
|
});
|
|
4252
4350
|
|
|
4253
4351
|
// ../contracts/src/doctor.ts
|
|
4254
|
-
import { z as
|
|
4255
|
-
var checkStatusSchema =
|
|
4352
|
+
import { z as z29 } from "zod";
|
|
4353
|
+
var checkStatusSchema = z29.enum(["ok", "warn", "fail", "skipped"]);
|
|
4256
4354
|
var CheckStatuses = checkStatusSchema.enum;
|
|
4257
|
-
var checkScopeSchema =
|
|
4355
|
+
var checkScopeSchema = z29.enum(["global", "project"]);
|
|
4258
4356
|
var CheckScopes = checkScopeSchema.enum;
|
|
4259
|
-
var checkCategorySchema =
|
|
4357
|
+
var checkCategorySchema = z29.enum([
|
|
4260
4358
|
"auth",
|
|
4261
4359
|
"config",
|
|
4262
4360
|
"providers",
|
|
@@ -4267,31 +4365,31 @@ var checkCategorySchema = z27.enum([
|
|
|
4267
4365
|
"agent"
|
|
4268
4366
|
]);
|
|
4269
4367
|
var CheckCategories = checkCategorySchema.enum;
|
|
4270
|
-
var checkResultSchema =
|
|
4271
|
-
id:
|
|
4368
|
+
var checkResultSchema = z29.object({
|
|
4369
|
+
id: z29.string(),
|
|
4272
4370
|
category: checkCategorySchema,
|
|
4273
4371
|
scope: checkScopeSchema,
|
|
4274
|
-
title:
|
|
4372
|
+
title: z29.string(),
|
|
4275
4373
|
status: checkStatusSchema,
|
|
4276
|
-
code:
|
|
4277
|
-
summary:
|
|
4278
|
-
remediation:
|
|
4279
|
-
details:
|
|
4280
|
-
durationMs:
|
|
4374
|
+
code: z29.string().describe('Stable machine-readable code (e.g. "google.token.refresh-failed"). Use this for filtering and remediation logic.'),
|
|
4375
|
+
summary: z29.string(),
|
|
4376
|
+
remediation: z29.string().nullable().optional().describe('Operator-facing next step. Null when status is "ok" or no specific remediation applies.'),
|
|
4377
|
+
details: z29.record(z29.string(), z29.unknown()).optional().describe("Structured context \u2014 principal email, redirect URI, missing scopes, etc. Stable per check id."),
|
|
4378
|
+
durationMs: z29.number().int().nonnegative().describe("How long the check took to execute.")
|
|
4281
4379
|
});
|
|
4282
|
-
var doctorReportSchema =
|
|
4380
|
+
var doctorReportSchema = z29.object({
|
|
4283
4381
|
scope: checkScopeSchema,
|
|
4284
|
-
project:
|
|
4285
|
-
generatedAt:
|
|
4286
|
-
durationMs:
|
|
4287
|
-
summary:
|
|
4288
|
-
total:
|
|
4289
|
-
ok:
|
|
4290
|
-
warn:
|
|
4291
|
-
fail:
|
|
4292
|
-
skipped:
|
|
4382
|
+
project: z29.string().nullable().describe('Project name when scope is "project", null otherwise.'),
|
|
4383
|
+
generatedAt: z29.string().describe("ISO-8601 timestamp when this doctor run started."),
|
|
4384
|
+
durationMs: z29.number().int().nonnegative(),
|
|
4385
|
+
summary: z29.object({
|
|
4386
|
+
total: z29.number().int().nonnegative(),
|
|
4387
|
+
ok: z29.number().int().nonnegative(),
|
|
4388
|
+
warn: z29.number().int().nonnegative(),
|
|
4389
|
+
fail: z29.number().int().nonnegative(),
|
|
4390
|
+
skipped: z29.number().int().nonnegative()
|
|
4293
4391
|
}),
|
|
4294
|
-
checks:
|
|
4392
|
+
checks: z29.array(checkResultSchema)
|
|
4295
4393
|
});
|
|
4296
4394
|
function summarizeCheckResults(results) {
|
|
4297
4395
|
const summary = { total: results.length, ok: 0, warn: 0, fail: 0, skipped: 0 };
|
|
@@ -4320,52 +4418,52 @@ function normalizeQueryText(value) {
|
|
|
4320
4418
|
}
|
|
4321
4419
|
|
|
4322
4420
|
// ../contracts/src/citations.ts
|
|
4323
|
-
import { z as
|
|
4324
|
-
var citationCoverageProviderSchema =
|
|
4325
|
-
provider:
|
|
4421
|
+
import { z as z30 } from "zod";
|
|
4422
|
+
var citationCoverageProviderSchema = z30.object({
|
|
4423
|
+
provider: z30.string(),
|
|
4326
4424
|
citationState: citationStateSchema,
|
|
4327
|
-
cited:
|
|
4328
|
-
mentioned:
|
|
4329
|
-
runId:
|
|
4330
|
-
runCreatedAt:
|
|
4331
|
-
});
|
|
4332
|
-
var citationCoverageRowSchema =
|
|
4333
|
-
queryId:
|
|
4334
|
-
query:
|
|
4335
|
-
providers:
|
|
4336
|
-
citedCount:
|
|
4337
|
-
mentionedCount:
|
|
4338
|
-
totalProviders:
|
|
4339
|
-
});
|
|
4340
|
-
var competitorGapRowSchema =
|
|
4341
|
-
queryId:
|
|
4342
|
-
query:
|
|
4343
|
-
provider:
|
|
4344
|
-
citingCompetitors:
|
|
4345
|
-
runId:
|
|
4346
|
-
runCreatedAt:
|
|
4347
|
-
});
|
|
4348
|
-
var citationVisibilitySummarySchema =
|
|
4349
|
-
providersConfigured:
|
|
4350
|
-
providersCiting:
|
|
4351
|
-
providersMentioning:
|
|
4352
|
-
totalQueries:
|
|
4425
|
+
cited: z30.boolean(),
|
|
4426
|
+
mentioned: z30.boolean(),
|
|
4427
|
+
runId: z30.string(),
|
|
4428
|
+
runCreatedAt: z30.string()
|
|
4429
|
+
});
|
|
4430
|
+
var citationCoverageRowSchema = z30.object({
|
|
4431
|
+
queryId: z30.string(),
|
|
4432
|
+
query: z30.string(),
|
|
4433
|
+
providers: z30.array(citationCoverageProviderSchema),
|
|
4434
|
+
citedCount: z30.number().int().nonnegative(),
|
|
4435
|
+
mentionedCount: z30.number().int().nonnegative(),
|
|
4436
|
+
totalProviders: z30.number().int().nonnegative()
|
|
4437
|
+
});
|
|
4438
|
+
var competitorGapRowSchema = z30.object({
|
|
4439
|
+
queryId: z30.string(),
|
|
4440
|
+
query: z30.string(),
|
|
4441
|
+
provider: z30.string(),
|
|
4442
|
+
citingCompetitors: z30.array(z30.string()),
|
|
4443
|
+
runId: z30.string(),
|
|
4444
|
+
runCreatedAt: z30.string()
|
|
4445
|
+
});
|
|
4446
|
+
var citationVisibilitySummarySchema = z30.object({
|
|
4447
|
+
providersConfigured: z30.number().int().nonnegative(),
|
|
4448
|
+
providersCiting: z30.number().int().nonnegative(),
|
|
4449
|
+
providersMentioning: z30.number().int().nonnegative(),
|
|
4450
|
+
totalQueries: z30.number().int().nonnegative(),
|
|
4353
4451
|
// Cross-tab buckets — each tracked query with at least one snapshot lands
|
|
4354
4452
|
// in exactly one of these. Queries with zero snapshots are not counted in
|
|
4355
4453
|
// any bucket; (sum of buckets) ≤ totalQueries.
|
|
4356
|
-
queriesCitedAndMentioned:
|
|
4357
|
-
queriesCitedOnly:
|
|
4358
|
-
queriesMentionedOnly:
|
|
4359
|
-
queriesInvisible:
|
|
4360
|
-
latestRunId:
|
|
4361
|
-
latestRunAt:
|
|
4362
|
-
});
|
|
4363
|
-
var citationVisibilityResponseSchema =
|
|
4454
|
+
queriesCitedAndMentioned: z30.number().int().nonnegative(),
|
|
4455
|
+
queriesCitedOnly: z30.number().int().nonnegative(),
|
|
4456
|
+
queriesMentionedOnly: z30.number().int().nonnegative(),
|
|
4457
|
+
queriesInvisible: z30.number().int().nonnegative(),
|
|
4458
|
+
latestRunId: z30.string().nullable(),
|
|
4459
|
+
latestRunAt: z30.string().nullable()
|
|
4460
|
+
});
|
|
4461
|
+
var citationVisibilityResponseSchema = z30.object({
|
|
4364
4462
|
summary: citationVisibilitySummarySchema,
|
|
4365
|
-
byQuery:
|
|
4366
|
-
competitorGaps:
|
|
4367
|
-
status:
|
|
4368
|
-
reason:
|
|
4463
|
+
byQuery: z30.array(citationCoverageRowSchema),
|
|
4464
|
+
competitorGaps: z30.array(competitorGapRowSchema),
|
|
4465
|
+
status: z30.enum(["ready", "no-data"]),
|
|
4466
|
+
reason: z30.enum(["no-runs-yet", "no-queries"]).optional()
|
|
4369
4467
|
});
|
|
4370
4468
|
function emptyCitationVisibility(reason) {
|
|
4371
4469
|
return {
|
|
@@ -4392,10 +4490,10 @@ function citationStateToCited(state) {
|
|
|
4392
4490
|
}
|
|
4393
4491
|
|
|
4394
4492
|
// ../contracts/src/report.ts
|
|
4395
|
-
import { z as
|
|
4493
|
+
import { z as z31 } from "zod";
|
|
4396
4494
|
var REPORT_PERIOD_OPTIONS = [7, 14, 30, 90];
|
|
4397
4495
|
var REPORT_DEFAULT_PERIOD_DAYS = 30;
|
|
4398
|
-
var reportPeriodSchema =
|
|
4496
|
+
var reportPeriodSchema = z31.union([z31.literal(7), z31.literal(14), z31.literal(30), z31.literal(90)]).describe("Report window in days (7, 14, 30, or 90). Defaults to 30 when omitted.");
|
|
4399
4497
|
function isReportPeriodDays(n) {
|
|
4400
4498
|
return REPORT_PERIOD_OPTIONS.includes(n);
|
|
4401
4499
|
}
|
|
@@ -4410,45 +4508,45 @@ function parseReportPeriodDays(value) {
|
|
|
4410
4508
|
function reportComparisonWindowDays(periodDays) {
|
|
4411
4509
|
return Math.max(1, Math.floor(periodDays / 2));
|
|
4412
4510
|
}
|
|
4413
|
-
var providerLocationTreatmentSchema =
|
|
4511
|
+
var providerLocationTreatmentSchema = z31.enum([
|
|
4414
4512
|
"prompt",
|
|
4415
4513
|
"request-param",
|
|
4416
4514
|
"browser-geo",
|
|
4417
4515
|
"ignored"
|
|
4418
4516
|
]);
|
|
4419
|
-
var reportMetaLocationSchema =
|
|
4517
|
+
var reportMetaLocationSchema = z31.object({
|
|
4420
4518
|
/** Human-readable label as configured on the project (e.g. "michigan"). */
|
|
4421
|
-
label:
|
|
4519
|
+
label: z31.string(),
|
|
4422
4520
|
/** Resolved city/region/country from the project's `LocationContext`. */
|
|
4423
|
-
city:
|
|
4424
|
-
region:
|
|
4425
|
-
country:
|
|
4521
|
+
city: z31.string(),
|
|
4522
|
+
region: z31.string(),
|
|
4523
|
+
country: z31.string(),
|
|
4426
4524
|
/**
|
|
4427
4525
|
* Other locations configured on the project that did NOT power this report.
|
|
4428
4526
|
* When non-empty, callers should make clear that the report is location-scoped:
|
|
4429
4527
|
* a separate sweep is needed to see how AI engines respond from each one.
|
|
4430
4528
|
*/
|
|
4431
|
-
otherConfiguredLabels:
|
|
4529
|
+
otherConfiguredLabels: z31.array(z31.string())
|
|
4432
4530
|
});
|
|
4433
|
-
var reportProviderLocationHandlingSchema =
|
|
4531
|
+
var reportProviderLocationHandlingSchema = z31.object({
|
|
4434
4532
|
/** Provider name (matches `query_snapshots.provider`). */
|
|
4435
|
-
provider:
|
|
4533
|
+
provider: z31.string(),
|
|
4436
4534
|
/** How this provider applied the configured location during this run. */
|
|
4437
4535
|
treatment: providerLocationTreatmentSchema,
|
|
4438
4536
|
/** One-sentence explanation suitable for the report. */
|
|
4439
|
-
description:
|
|
4537
|
+
description: z31.string()
|
|
4440
4538
|
});
|
|
4441
|
-
var reportMetaSchema =
|
|
4539
|
+
var reportMetaSchema = z31.object({
|
|
4442
4540
|
/** ISO timestamp the report was generated (server clock). */
|
|
4443
|
-
generatedAt:
|
|
4541
|
+
generatedAt: z31.string(),
|
|
4444
4542
|
/** Project the report covers. */
|
|
4445
|
-
project:
|
|
4446
|
-
id:
|
|
4447
|
-
name:
|
|
4448
|
-
displayName:
|
|
4449
|
-
canonicalDomain:
|
|
4450
|
-
country:
|
|
4451
|
-
language:
|
|
4543
|
+
project: z31.object({
|
|
4544
|
+
id: z31.string(),
|
|
4545
|
+
name: z31.string(),
|
|
4546
|
+
displayName: z31.string(),
|
|
4547
|
+
canonicalDomain: z31.string(),
|
|
4548
|
+
country: z31.string(),
|
|
4549
|
+
language: z31.string()
|
|
4452
4550
|
}),
|
|
4453
4551
|
/**
|
|
4454
4552
|
* The location that powered the latest visibility run, when one was set.
|
|
@@ -4463,31 +4561,31 @@ var reportMetaSchema = z29.object({
|
|
|
4463
4561
|
* each provider's answer — some providers append it to the prompt, some
|
|
4464
4562
|
* pass it as a structured request field, and some (CDP) ignore it.
|
|
4465
4563
|
*/
|
|
4466
|
-
providerLocationHandling:
|
|
4564
|
+
providerLocationHandling: z31.array(reportProviderLocationHandlingSchema),
|
|
4467
4565
|
/** Earliest data point referenced by the report (ISO date). */
|
|
4468
|
-
periodStart:
|
|
4566
|
+
periodStart: z31.string().nullable(),
|
|
4469
4567
|
/** Latest data point referenced by the report (ISO date). */
|
|
4470
|
-
periodEnd:
|
|
4568
|
+
periodEnd: z31.string().nullable(),
|
|
4471
4569
|
/**
|
|
4472
4570
|
* The selected report window, in days (one of `REPORT_PERIOD_OPTIONS`).
|
|
4473
4571
|
* Every time-windowed section scopes to this many days; renderers read it to
|
|
4474
4572
|
* label the window ("Last 30 days", "(30d)"). Defaults to
|
|
4475
4573
|
* `REPORT_DEFAULT_PERIOD_DAYS` when no `period` is requested.
|
|
4476
4574
|
*/
|
|
4477
|
-
periodDays:
|
|
4575
|
+
periodDays: z31.number().int().positive()
|
|
4478
4576
|
});
|
|
4479
|
-
var reportExecutiveSummarySchema =
|
|
4577
|
+
var reportExecutiveSummarySchema = z31.object({
|
|
4480
4578
|
/**
|
|
4481
4579
|
* 0..100 — share of tracked queries that were cited by at least one
|
|
4482
4580
|
* provider in the latest run. "Cited" means the project's domain appeared
|
|
4483
4581
|
* in the source list / grounding the AI used to answer. Computed per-query
|
|
4484
4582
|
* (not per-(query × provider)) so the rate is invariant to provider count.
|
|
4485
4583
|
*/
|
|
4486
|
-
citationRate:
|
|
4584
|
+
citationRate: z31.number(),
|
|
4487
4585
|
/** Numerator of `citationRate` — distinct tracked queries cited by ≥1 provider in the latest run. */
|
|
4488
|
-
citedQueryCount:
|
|
4586
|
+
citedQueryCount: z31.number(),
|
|
4489
4587
|
/** Denominator of `citationRate` — total tracked queries. */
|
|
4490
|
-
totalQueryCount:
|
|
4588
|
+
totalQueryCount: z31.number(),
|
|
4491
4589
|
/**
|
|
4492
4590
|
* 0..100 — share of tracked queries where the project's brand or domain
|
|
4493
4591
|
* appeared in at least one provider's answer text in the latest run.
|
|
@@ -4495,71 +4593,71 @@ var reportExecutiveSummarySchema = z29.object({
|
|
|
4495
4593
|
* the prose without citing your domain in its sources, and vice versa.
|
|
4496
4594
|
* Same per-query denominator as `citationRate` for consistency.
|
|
4497
4595
|
*/
|
|
4498
|
-
mentionRate:
|
|
4596
|
+
mentionRate: z31.number(),
|
|
4499
4597
|
/** Numerator of `mentionRate` — distinct tracked queries mentioned in ≥1 provider's answer text. */
|
|
4500
|
-
mentionedQueryCount:
|
|
4598
|
+
mentionedQueryCount: z31.number(),
|
|
4501
4599
|
/** Compared to the previous run: 'up' | 'down' | 'flat' | 'unknown' (no prior run). */
|
|
4502
|
-
trend:
|
|
4600
|
+
trend: z31.enum(["up", "down", "flat", "unknown"]),
|
|
4503
4601
|
/** Total tracked queries. */
|
|
4504
|
-
queryCount:
|
|
4602
|
+
queryCount: z31.number(),
|
|
4505
4603
|
/** Total tracked competitors. */
|
|
4506
|
-
competitorCount:
|
|
4604
|
+
competitorCount: z31.number(),
|
|
4507
4605
|
/** Number of providers in the latest run. */
|
|
4508
|
-
providerCount:
|
|
4606
|
+
providerCount: z31.number(),
|
|
4509
4607
|
/** GSC totals across the most-recent sync window. Null when GSC is not connected. */
|
|
4510
|
-
gsc:
|
|
4511
|
-
clicks:
|
|
4512
|
-
impressions:
|
|
4513
|
-
ctr:
|
|
4514
|
-
avgPosition:
|
|
4515
|
-
periodStart:
|
|
4516
|
-
periodEnd:
|
|
4608
|
+
gsc: z31.object({
|
|
4609
|
+
clicks: z31.number(),
|
|
4610
|
+
impressions: z31.number(),
|
|
4611
|
+
ctr: z31.number(),
|
|
4612
|
+
avgPosition: z31.number(),
|
|
4613
|
+
periodStart: z31.string(),
|
|
4614
|
+
periodEnd: z31.string()
|
|
4517
4615
|
}).nullable(),
|
|
4518
4616
|
/** GA4 totals across the most-recent sync period. Null when GA4 is not connected. */
|
|
4519
|
-
ga:
|
|
4520
|
-
sessions:
|
|
4521
|
-
users:
|
|
4522
|
-
periodStart:
|
|
4523
|
-
periodEnd:
|
|
4617
|
+
ga: z31.object({
|
|
4618
|
+
sessions: z31.number(),
|
|
4619
|
+
users: z31.number(),
|
|
4620
|
+
periodStart: z31.string(),
|
|
4621
|
+
periodEnd: z31.string()
|
|
4524
4622
|
}).nullable(),
|
|
4525
4623
|
/** Top 3-5 findings, each rendered as a single-sentence narrative. */
|
|
4526
|
-
findings:
|
|
4527
|
-
title:
|
|
4528
|
-
detail:
|
|
4529
|
-
tone:
|
|
4624
|
+
findings: z31.array(z31.object({
|
|
4625
|
+
title: z31.string(),
|
|
4626
|
+
detail: z31.string(),
|
|
4627
|
+
tone: z31.enum(["positive", "caution", "negative", "neutral"])
|
|
4530
4628
|
}))
|
|
4531
4629
|
});
|
|
4532
|
-
var citationCellSchema =
|
|
4533
|
-
citationState:
|
|
4534
|
-
answerMentioned:
|
|
4535
|
-
model:
|
|
4630
|
+
var citationCellSchema = z31.object({
|
|
4631
|
+
citationState: z31.enum(["cited", "not-cited", "pending"]),
|
|
4632
|
+
answerMentioned: z31.boolean().nullable(),
|
|
4633
|
+
model: z31.string().nullable()
|
|
4536
4634
|
});
|
|
4537
|
-
var citationScorecardSchema =
|
|
4538
|
-
queries:
|
|
4539
|
-
providers:
|
|
4635
|
+
var citationScorecardSchema = z31.object({
|
|
4636
|
+
queries: z31.array(z31.string()),
|
|
4637
|
+
providers: z31.array(z31.string()),
|
|
4540
4638
|
/** matrix[queryIndex][providerIndex] — null when no snapshot exists for the pair. */
|
|
4541
|
-
matrix:
|
|
4639
|
+
matrix: z31.array(z31.array(citationCellSchema.nullable())),
|
|
4542
4640
|
/** Per-provider citation + mention rates (0..100). */
|
|
4543
|
-
providerRates:
|
|
4544
|
-
provider:
|
|
4545
|
-
citedCount:
|
|
4641
|
+
providerRates: z31.array(z31.object({
|
|
4642
|
+
provider: z31.string(),
|
|
4643
|
+
citedCount: z31.number(),
|
|
4546
4644
|
/** Number of snapshots for this provider where the answer text mentioned the project. */
|
|
4547
|
-
mentionedCount:
|
|
4548
|
-
totalCount:
|
|
4549
|
-
citationRate:
|
|
4550
|
-
mentionRate:
|
|
4645
|
+
mentionedCount: z31.number(),
|
|
4646
|
+
totalCount: z31.number(),
|
|
4647
|
+
citationRate: z31.number(),
|
|
4648
|
+
mentionRate: z31.number()
|
|
4551
4649
|
}))
|
|
4552
4650
|
});
|
|
4553
|
-
var competitorRowSchema =
|
|
4554
|
-
domain:
|
|
4651
|
+
var competitorRowSchema = z31.object({
|
|
4652
|
+
domain: z31.string(),
|
|
4555
4653
|
/** Number of (query × provider) pairs that cited this competitor. */
|
|
4556
|
-
citationCount:
|
|
4654
|
+
citationCount: z31.number(),
|
|
4557
4655
|
/** Out-of count for the same denominator. */
|
|
4558
|
-
totalCount:
|
|
4656
|
+
totalCount: z31.number(),
|
|
4559
4657
|
/** 'High' | 'Moderate' | 'Low' | 'None' — from buildPortfolioProject pressure logic. */
|
|
4560
|
-
pressureLabel:
|
|
4658
|
+
pressureLabel: z31.enum(["High", "Moderate", "Low", "None"]),
|
|
4561
4659
|
/** Distinct queries on which this competitor was cited. */
|
|
4562
|
-
citedQueries:
|
|
4660
|
+
citedQueries: z31.array(z31.string()),
|
|
4563
4661
|
/**
|
|
4564
4662
|
* Citation share 0..100. Numerator = this competitor's `citationCount`.
|
|
4565
4663
|
* Denominator = sum of `citationCount` across all competitors plus the
|
|
@@ -4567,30 +4665,30 @@ var competitorRowSchema = z29.object({
|
|
|
4567
4665
|
* slots in the snapshot. Distinct from the project-level Mention Share
|
|
4568
4666
|
* gauge — that one is brand-in-answer-text, this one is domain-in-source-list.
|
|
4569
4667
|
*/
|
|
4570
|
-
sharePct:
|
|
4668
|
+
sharePct: z31.number(),
|
|
4571
4669
|
/**
|
|
4572
4670
|
* URLs from the latest run's grounding sources whose host matches this
|
|
4573
4671
|
* competitor's domain, with the queries each URL was cited for. Empty
|
|
4574
4672
|
* when no grounding-source data is available (e.g. no `rawResponse` JSON
|
|
4575
4673
|
* stored for the snapshots).
|
|
4576
4674
|
*/
|
|
4577
|
-
theirCitedPages:
|
|
4675
|
+
theirCitedPages: z31.array(z31.object({ url: z31.string(), citedFor: z31.array(z31.string()) }))
|
|
4578
4676
|
});
|
|
4579
|
-
var competitorLandscapeSchema =
|
|
4677
|
+
var competitorLandscapeSchema = z31.object({
|
|
4580
4678
|
/** Project's own citation count (for the bar chart comparing project vs competitors). */
|
|
4581
|
-
projectCitationCount:
|
|
4582
|
-
competitors:
|
|
4679
|
+
projectCitationCount: z31.number(),
|
|
4680
|
+
competitors: z31.array(competitorRowSchema)
|
|
4583
4681
|
});
|
|
4584
|
-
var mentionRowSchema =
|
|
4585
|
-
domain:
|
|
4682
|
+
var mentionRowSchema = z31.object({
|
|
4683
|
+
domain: z31.string(),
|
|
4586
4684
|
/** Number of (query × provider) pairs whose answer text mentioned this competitor's brand or domain. */
|
|
4587
|
-
mentionCount:
|
|
4685
|
+
mentionCount: z31.number(),
|
|
4588
4686
|
/** Out-of count for the same denominator (snapshots that had answer text). */
|
|
4589
|
-
totalCount:
|
|
4687
|
+
totalCount: z31.number(),
|
|
4590
4688
|
/** 'High' | 'Moderate' | 'Low' | 'None' — mention frequency tier (mirrors CompetitorRow.pressureLabel). */
|
|
4591
|
-
pressureLabel:
|
|
4689
|
+
pressureLabel: z31.enum(["High", "Moderate", "Low", "None"]),
|
|
4592
4690
|
/** Distinct queries on which this competitor was mentioned. */
|
|
4593
|
-
mentionedQueries:
|
|
4691
|
+
mentionedQueries: z31.array(z31.string()),
|
|
4594
4692
|
/**
|
|
4595
4693
|
* Mention share 0..100. Numerator = this competitor's `mentionCount`.
|
|
4596
4694
|
* Denominator = sum of `mentionCount` across all competitors plus the
|
|
@@ -4598,135 +4696,135 @@ var mentionRowSchema = z29.object({
|
|
|
4598
4696
|
* mention. Per-competitor split of the same head-to-head measure the
|
|
4599
4697
|
* project's hero `MentionShareDto` gauge headlines.
|
|
4600
4698
|
*/
|
|
4601
|
-
sharePct:
|
|
4699
|
+
sharePct: z31.number()
|
|
4602
4700
|
});
|
|
4603
|
-
var mentionLandscapeSchema =
|
|
4701
|
+
var mentionLandscapeSchema = z31.object({
|
|
4604
4702
|
/** Project's own mention count (for the bar chart comparing project vs competitors). */
|
|
4605
|
-
projectMentionCount:
|
|
4703
|
+
projectMentionCount: z31.number(),
|
|
4606
4704
|
/** Snapshots considered — those with non-empty answerText. Drives the totalCount denominator. */
|
|
4607
|
-
totalAnswerSnapshots:
|
|
4608
|
-
competitors:
|
|
4705
|
+
totalAnswerSnapshots: z31.number(),
|
|
4706
|
+
competitors: z31.array(mentionRowSchema)
|
|
4609
4707
|
});
|
|
4610
|
-
var aiSourceCategoryBucketSchema =
|
|
4708
|
+
var aiSourceCategoryBucketSchema = z31.object({
|
|
4611
4709
|
/** Category slug from packages/contracts/src/source-categories. */
|
|
4612
|
-
category:
|
|
4710
|
+
category: z31.string(),
|
|
4613
4711
|
/** Display label. */
|
|
4614
|
-
label:
|
|
4712
|
+
label: z31.string(),
|
|
4615
4713
|
/** Number of citations falling in this category. */
|
|
4616
|
-
count:
|
|
4714
|
+
count: z31.number(),
|
|
4617
4715
|
/** 0..100 share of total citations. */
|
|
4618
|
-
sharePct:
|
|
4716
|
+
sharePct: z31.number()
|
|
4619
4717
|
});
|
|
4620
|
-
var aiSourceOriginSchema =
|
|
4621
|
-
categories:
|
|
4718
|
+
var aiSourceOriginSchema = z31.object({
|
|
4719
|
+
categories: z31.array(aiSourceCategoryBucketSchema),
|
|
4622
4720
|
/** Top 20 source domains by citation count (excluding the project's own domain). */
|
|
4623
|
-
topDomains:
|
|
4624
|
-
domain:
|
|
4625
|
-
count:
|
|
4721
|
+
topDomains: z31.array(z31.object({
|
|
4722
|
+
domain: z31.string(),
|
|
4723
|
+
count: z31.number(),
|
|
4626
4724
|
/** True when the domain is one of the project's tracked competitors. */
|
|
4627
|
-
isCompetitor:
|
|
4725
|
+
isCompetitor: z31.boolean()
|
|
4628
4726
|
}))
|
|
4629
4727
|
});
|
|
4630
|
-
var gscQueryRowSchema =
|
|
4631
|
-
query:
|
|
4632
|
-
clicks:
|
|
4633
|
-
impressions:
|
|
4634
|
-
ctr:
|
|
4635
|
-
avgPosition:
|
|
4728
|
+
var gscQueryRowSchema = z31.object({
|
|
4729
|
+
query: z31.string(),
|
|
4730
|
+
clicks: z31.number(),
|
|
4731
|
+
impressions: z31.number(),
|
|
4732
|
+
ctr: z31.number(),
|
|
4733
|
+
avgPosition: z31.number(),
|
|
4636
4734
|
/** Heuristic categorization: 'brand' | 'lead-gen' | 'industry' | 'other'. */
|
|
4637
|
-
category:
|
|
4638
|
-
});
|
|
4639
|
-
var gscSectionSchema =
|
|
4640
|
-
periodStart:
|
|
4641
|
-
periodEnd:
|
|
4642
|
-
totalClicks:
|
|
4643
|
-
totalImpressions:
|
|
4644
|
-
ctr:
|
|
4645
|
-
avgPosition:
|
|
4646
|
-
topQueries:
|
|
4647
|
-
categoryBreakdown:
|
|
4648
|
-
category:
|
|
4649
|
-
clicks:
|
|
4650
|
-
impressions:
|
|
4651
|
-
sharePct:
|
|
4735
|
+
category: z31.enum(["brand", "lead-gen", "industry", "other"])
|
|
4736
|
+
});
|
|
4737
|
+
var gscSectionSchema = z31.object({
|
|
4738
|
+
periodStart: z31.string(),
|
|
4739
|
+
periodEnd: z31.string(),
|
|
4740
|
+
totalClicks: z31.number(),
|
|
4741
|
+
totalImpressions: z31.number(),
|
|
4742
|
+
ctr: z31.number(),
|
|
4743
|
+
avgPosition: z31.number(),
|
|
4744
|
+
topQueries: z31.array(gscQueryRowSchema),
|
|
4745
|
+
categoryBreakdown: z31.array(z31.object({
|
|
4746
|
+
category: z31.enum(["brand", "lead-gen", "industry", "other"]),
|
|
4747
|
+
clicks: z31.number(),
|
|
4748
|
+
impressions: z31.number(),
|
|
4749
|
+
sharePct: z31.number()
|
|
4652
4750
|
})),
|
|
4653
|
-
trend:
|
|
4751
|
+
trend: z31.array(z31.object({ date: z31.string(), clicks: z31.number(), impressions: z31.number() })),
|
|
4654
4752
|
/**
|
|
4655
4753
|
* Tracked AEO queries that have no GSC impressions in the report window.
|
|
4656
4754
|
* Surfaces queries that may not represent real search demand.
|
|
4657
4755
|
*/
|
|
4658
|
-
trackedButNoGsc:
|
|
4756
|
+
trackedButNoGsc: z31.array(z31.string()),
|
|
4659
4757
|
/**
|
|
4660
4758
|
* GSC top queries (sorted by impressions desc) that are not tracked as
|
|
4661
4759
|
* AEO queries — the candidate set for adding to the AEO project.
|
|
4662
4760
|
*/
|
|
4663
|
-
gscButNotTracked:
|
|
4664
|
-
});
|
|
4665
|
-
var gaTrafficSectionSchema =
|
|
4666
|
-
totalSessions:
|
|
4667
|
-
totalUsers:
|
|
4668
|
-
totalOrganicSessions:
|
|
4669
|
-
periodStart:
|
|
4670
|
-
periodEnd:
|
|
4671
|
-
topLandingPages:
|
|
4672
|
-
page:
|
|
4673
|
-
sessions:
|
|
4674
|
-
users:
|
|
4675
|
-
organicSessions:
|
|
4761
|
+
gscButNotTracked: z31.array(z31.string())
|
|
4762
|
+
});
|
|
4763
|
+
var gaTrafficSectionSchema = z31.object({
|
|
4764
|
+
totalSessions: z31.number(),
|
|
4765
|
+
totalUsers: z31.number(),
|
|
4766
|
+
totalOrganicSessions: z31.number(),
|
|
4767
|
+
periodStart: z31.string(),
|
|
4768
|
+
periodEnd: z31.string(),
|
|
4769
|
+
topLandingPages: z31.array(z31.object({
|
|
4770
|
+
page: z31.string(),
|
|
4771
|
+
sessions: z31.number(),
|
|
4772
|
+
users: z31.number(),
|
|
4773
|
+
organicSessions: z31.number()
|
|
4676
4774
|
})),
|
|
4677
|
-
channelBreakdown:
|
|
4678
|
-
channel:
|
|
4679
|
-
sessions:
|
|
4680
|
-
sharePct:
|
|
4775
|
+
channelBreakdown: z31.array(z31.object({
|
|
4776
|
+
channel: z31.string(),
|
|
4777
|
+
sessions: z31.number(),
|
|
4778
|
+
sharePct: z31.number()
|
|
4681
4779
|
}))
|
|
4682
4780
|
});
|
|
4683
|
-
var socialReferralSectionSchema =
|
|
4684
|
-
totalSessions:
|
|
4685
|
-
organicSessions:
|
|
4686
|
-
paidSessions:
|
|
4687
|
-
channels:
|
|
4688
|
-
channelGroup:
|
|
4689
|
-
sessions:
|
|
4690
|
-
sharePct:
|
|
4781
|
+
var socialReferralSectionSchema = z31.object({
|
|
4782
|
+
totalSessions: z31.number(),
|
|
4783
|
+
organicSessions: z31.number(),
|
|
4784
|
+
paidSessions: z31.number(),
|
|
4785
|
+
channels: z31.array(z31.object({
|
|
4786
|
+
channelGroup: z31.string(),
|
|
4787
|
+
sessions: z31.number(),
|
|
4788
|
+
sharePct: z31.number()
|
|
4691
4789
|
})),
|
|
4692
|
-
topCampaigns:
|
|
4693
|
-
source:
|
|
4694
|
-
medium:
|
|
4695
|
-
sessions:
|
|
4790
|
+
topCampaigns: z31.array(z31.object({
|
|
4791
|
+
source: z31.string(),
|
|
4792
|
+
medium: z31.string(),
|
|
4793
|
+
sessions: z31.number()
|
|
4696
4794
|
}))
|
|
4697
4795
|
});
|
|
4698
|
-
var aiReferralSectionSchema =
|
|
4699
|
-
totalSessions:
|
|
4700
|
-
totalUsers:
|
|
4701
|
-
paidSessions:
|
|
4702
|
-
paidUsers:
|
|
4703
|
-
organicSessions:
|
|
4704
|
-
organicUsers:
|
|
4705
|
-
bySource:
|
|
4706
|
-
source:
|
|
4707
|
-
sessions:
|
|
4708
|
-
users:
|
|
4709
|
-
paidSessions:
|
|
4710
|
-
organicSessions:
|
|
4711
|
-
sharePct:
|
|
4796
|
+
var aiReferralSectionSchema = z31.object({
|
|
4797
|
+
totalSessions: z31.number(),
|
|
4798
|
+
totalUsers: z31.number(),
|
|
4799
|
+
paidSessions: z31.number(),
|
|
4800
|
+
paidUsers: z31.number(),
|
|
4801
|
+
organicSessions: z31.number(),
|
|
4802
|
+
organicUsers: z31.number(),
|
|
4803
|
+
bySource: z31.array(z31.object({
|
|
4804
|
+
source: z31.string(),
|
|
4805
|
+
sessions: z31.number(),
|
|
4806
|
+
users: z31.number(),
|
|
4807
|
+
paidSessions: z31.number(),
|
|
4808
|
+
organicSessions: z31.number(),
|
|
4809
|
+
sharePct: z31.number()
|
|
4712
4810
|
})),
|
|
4713
|
-
trend:
|
|
4714
|
-
topLandingPages:
|
|
4715
|
-
page:
|
|
4716
|
-
sessions:
|
|
4717
|
-
users:
|
|
4811
|
+
trend: z31.array(z31.object({ date: z31.string(), sessions: z31.number() })),
|
|
4812
|
+
topLandingPages: z31.array(z31.object({
|
|
4813
|
+
page: z31.string(),
|
|
4814
|
+
sessions: z31.number(),
|
|
4815
|
+
users: z31.number()
|
|
4718
4816
|
}))
|
|
4719
4817
|
});
|
|
4720
|
-
var serverActivitySectionSchema =
|
|
4818
|
+
var serverActivitySectionSchema = z31.object({
|
|
4721
4819
|
/** ISO8601 inclusive lower bound of the report window (default: 7 days). */
|
|
4722
|
-
windowStart:
|
|
4820
|
+
windowStart: z31.string(),
|
|
4723
4821
|
/** ISO8601 inclusive upper bound. */
|
|
4724
|
-
windowEnd:
|
|
4725
|
-
hasData:
|
|
4822
|
+
windowEnd: z31.string(),
|
|
4823
|
+
hasData: z31.boolean(),
|
|
4726
4824
|
/** Last-7d total verified crawler hits, with prior 7d for delta. */
|
|
4727
|
-
verifiedCrawlerHits:
|
|
4825
|
+
verifiedCrawlerHits: z31.object({ current: z31.number(), prior: z31.number(), deltaPct: z31.number().nullable() }),
|
|
4728
4826
|
/** Last-7d total unverified crawler hits, separated from verified trust metrics. */
|
|
4729
|
-
unverifiedCrawlerHits:
|
|
4827
|
+
unverifiedCrawlerHits: z31.object({ current: z31.number(), prior: z31.number(), deltaPct: z31.number().nullable() }),
|
|
4730
4828
|
/**
|
|
4731
4829
|
* Last-7d on-demand per-user fetches from AI surfaces (ChatGPT-User,
|
|
4732
4830
|
* Perplexity-User, MistralAI-User). Disjoint from `verifiedCrawlerHits` /
|
|
@@ -4735,9 +4833,9 @@ var serverActivitySectionSchema = z29.object({
|
|
|
4735
4833
|
* because the operational question for user-fetch is "is this happening?"
|
|
4736
4834
|
* not "is this a confirmed bot identity?"
|
|
4737
4835
|
*/
|
|
4738
|
-
aiUserFetchHits:
|
|
4836
|
+
aiUserFetchHits: z31.object({ current: z31.number(), prior: z31.number(), deltaPct: z31.number().nullable() }),
|
|
4739
4837
|
/** Last-7d AI-referral sessions (sessionized from server-side request evidence). Paid + organic + unclassified. */
|
|
4740
|
-
referralArrivals:
|
|
4838
|
+
referralArrivals: z31.object({ current: z31.number(), prior: z31.number(), deltaPct: z31.number().nullable() }),
|
|
4741
4839
|
/**
|
|
4742
4840
|
* `referralArrivals` split by traffic class. The three buckets sum to it.
|
|
4743
4841
|
*
|
|
@@ -4746,23 +4844,23 @@ var serverActivitySectionSchema = z29.object({
|
|
|
4746
4844
|
* never be resolved. Reporting them as organic would overstate earned AI
|
|
4747
4845
|
* traffic by exactly a client's ad volume.
|
|
4748
4846
|
*/
|
|
4749
|
-
referralArrivalsByClass:
|
|
4750
|
-
paid:
|
|
4751
|
-
organic:
|
|
4752
|
-
unclassified:
|
|
4847
|
+
referralArrivalsByClass: z31.object({
|
|
4848
|
+
paid: z31.object({ current: z31.number(), prior: z31.number(), deltaPct: z31.number().nullable() }),
|
|
4849
|
+
organic: z31.object({ current: z31.number(), prior: z31.number(), deltaPct: z31.number().nullable() }),
|
|
4850
|
+
unclassified: z31.object({ current: z31.number(), prior: z31.number(), deltaPct: z31.number().nullable() })
|
|
4753
4851
|
}),
|
|
4754
4852
|
/** Pre-rendered one-line breakdown, e.g. "Paid 1,200 · Organic 24". Empty when there is nothing to split. */
|
|
4755
|
-
referralArrivalsClassSummary:
|
|
4853
|
+
referralArrivalsClassSummary: z31.string(),
|
|
4756
4854
|
/** Per-AI-operator breakdown (OpenAI, Anthropic, Google AI, Perplexity, …). */
|
|
4757
|
-
byOperator:
|
|
4758
|
-
operator:
|
|
4759
|
-
verifiedHits:
|
|
4855
|
+
byOperator: z31.array(z31.object({
|
|
4856
|
+
operator: z31.string(),
|
|
4857
|
+
verifiedHits: z31.number(),
|
|
4760
4858
|
/** Shown to agency audience only: claimed-bot UA, source IP not in a published range. */
|
|
4761
|
-
unverifiedHits:
|
|
4859
|
+
unverifiedHits: z31.number(),
|
|
4762
4860
|
/** Per-user fetches from this operator's AI surface (ChatGPT-User, …). */
|
|
4763
|
-
userFetchHits:
|
|
4764
|
-
referralArrivals:
|
|
4765
|
-
deltaPct:
|
|
4861
|
+
userFetchHits: z31.number(),
|
|
4862
|
+
referralArrivals: z31.number(),
|
|
4863
|
+
deltaPct: z31.number().nullable()
|
|
4766
4864
|
})),
|
|
4767
4865
|
/**
|
|
4768
4866
|
* Top crawled paths (verified only, last-7d). Path-level citation cross-reference
|
|
@@ -4772,88 +4870,88 @@ var serverActivitySectionSchema = z29.object({
|
|
|
4772
4870
|
* citation evidence can extend this entry with a `citationState` field without
|
|
4773
4871
|
* breaking the contract.
|
|
4774
4872
|
*/
|
|
4775
|
-
topCrawledPaths:
|
|
4776
|
-
path:
|
|
4777
|
-
verifiedHits:
|
|
4873
|
+
topCrawledPaths: z31.array(z31.object({
|
|
4874
|
+
path: z31.string(),
|
|
4875
|
+
verifiedHits: z31.number(),
|
|
4778
4876
|
/** How many distinct AI operators crawled this path in the window. */
|
|
4779
|
-
distinctOperators:
|
|
4877
|
+
distinctOperators: z31.number()
|
|
4780
4878
|
})),
|
|
4781
4879
|
/** AI products that sent ≥1 session in the window (referral by destination). */
|
|
4782
|
-
referralProducts:
|
|
4783
|
-
product:
|
|
4784
|
-
arrivals:
|
|
4785
|
-
distinctLandingPaths:
|
|
4880
|
+
referralProducts: z31.array(z31.object({
|
|
4881
|
+
product: z31.string(),
|
|
4882
|
+
arrivals: z31.number(),
|
|
4883
|
+
distinctLandingPaths: z31.number()
|
|
4786
4884
|
})),
|
|
4787
4885
|
/** Daily trend, last 14d for sparkline / chart rendering. */
|
|
4788
|
-
dailyTrend:
|
|
4789
|
-
date:
|
|
4790
|
-
verifiedCrawlerHits:
|
|
4791
|
-
userFetchHits:
|
|
4792
|
-
referralArrivals:
|
|
4886
|
+
dailyTrend: z31.array(z31.object({
|
|
4887
|
+
date: z31.string(),
|
|
4888
|
+
verifiedCrawlerHits: z31.number(),
|
|
4889
|
+
userFetchHits: z31.number(),
|
|
4890
|
+
referralArrivals: z31.number()
|
|
4793
4891
|
})),
|
|
4794
4892
|
/**
|
|
4795
4893
|
* Top landing paths for AI-referral sessions (last-7d).
|
|
4796
4894
|
* Complements `topCrawledPaths` (what bots fetch) with what humans actually land on.
|
|
4797
4895
|
*/
|
|
4798
|
-
topReferralLandingPaths:
|
|
4799
|
-
path:
|
|
4800
|
-
arrivals:
|
|
4801
|
-
distinctProducts:
|
|
4896
|
+
topReferralLandingPaths: z31.array(z31.object({
|
|
4897
|
+
path: z31.string(),
|
|
4898
|
+
arrivals: z31.number(),
|
|
4899
|
+
distinctProducts: z31.number()
|
|
4802
4900
|
}))
|
|
4803
4901
|
});
|
|
4804
|
-
var indexingHealthSectionSchema =
|
|
4902
|
+
var indexingHealthSectionSchema = z31.object({
|
|
4805
4903
|
/** Source: 'google' | 'bing' | null when neither is connected. */
|
|
4806
|
-
provider:
|
|
4807
|
-
total:
|
|
4808
|
-
indexed:
|
|
4809
|
-
notIndexed:
|
|
4904
|
+
provider: z31.enum(["google", "bing"]).nullable(),
|
|
4905
|
+
total: z31.number(),
|
|
4906
|
+
indexed: z31.number(),
|
|
4907
|
+
notIndexed: z31.number(),
|
|
4810
4908
|
/** Google-only — pages explicitly marked as deindexed. Bing reports 'unknown' instead. */
|
|
4811
|
-
deindexed:
|
|
4909
|
+
deindexed: z31.number(),
|
|
4812
4910
|
/** Bing-only — pages with no inspection data yet. */
|
|
4813
|
-
unknown:
|
|
4911
|
+
unknown: z31.number(),
|
|
4814
4912
|
/** 0..100. */
|
|
4815
|
-
indexedPct:
|
|
4913
|
+
indexedPct: z31.number()
|
|
4816
4914
|
});
|
|
4817
|
-
var citationsTrendPointSchema =
|
|
4915
|
+
var citationsTrendPointSchema = z31.object({
|
|
4818
4916
|
/** Run ID — anchor for cross-section linking. */
|
|
4819
|
-
runId:
|
|
4917
|
+
runId: z31.string(),
|
|
4820
4918
|
/** ISO timestamp when the run finished (or createdAt fallback). */
|
|
4821
|
-
date:
|
|
4919
|
+
date: z31.string(),
|
|
4822
4920
|
/**
|
|
4823
4921
|
* 0..100 — same per-query unique-cited definition as
|
|
4824
4922
|
* `ReportExecutiveSummary.citationRate`. Stable across runs with different
|
|
4825
4923
|
* provider counts so the trend line measures real movement rather than
|
|
4826
4924
|
* provider-count variance.
|
|
4827
4925
|
*/
|
|
4828
|
-
citationRate:
|
|
4926
|
+
citationRate: z31.number(),
|
|
4829
4927
|
/** Numerator of `citationRate` for this run. */
|
|
4830
|
-
citedQueryCount:
|
|
4928
|
+
citedQueryCount: z31.number(),
|
|
4831
4929
|
/** Denominator of `citationRate` for this run. */
|
|
4832
|
-
totalQueryCount:
|
|
4930
|
+
totalQueryCount: z31.number(),
|
|
4833
4931
|
/** 0..100 — same per-query unique-mentioned definition as `ReportExecutiveSummary.mentionRate`. */
|
|
4834
|
-
mentionRate:
|
|
4932
|
+
mentionRate: z31.number(),
|
|
4835
4933
|
/** Numerator of `mentionRate` for this run. */
|
|
4836
|
-
mentionedQueryCount:
|
|
4934
|
+
mentionedQueryCount: z31.number(),
|
|
4837
4935
|
/**
|
|
4838
4936
|
* Per-provider rates for the same run. Each provider's rate is per-pair
|
|
4839
4937
|
* within that provider (`cited / scanned`), so it remains comparable
|
|
4840
4938
|
* between providers in the same run.
|
|
4841
4939
|
*/
|
|
4842
|
-
providerRates:
|
|
4843
|
-
provider:
|
|
4844
|
-
citationRate:
|
|
4845
|
-
mentionRate:
|
|
4940
|
+
providerRates: z31.array(z31.object({
|
|
4941
|
+
provider: z31.string(),
|
|
4942
|
+
citationRate: z31.number(),
|
|
4943
|
+
mentionRate: z31.number()
|
|
4846
4944
|
}))
|
|
4847
4945
|
});
|
|
4848
|
-
var reportInsightSchema =
|
|
4849
|
-
id:
|
|
4850
|
-
type:
|
|
4851
|
-
severity:
|
|
4852
|
-
title:
|
|
4853
|
-
query:
|
|
4854
|
-
provider:
|
|
4855
|
-
recommendation:
|
|
4856
|
-
createdAt:
|
|
4946
|
+
var reportInsightSchema = z31.object({
|
|
4947
|
+
id: z31.string(),
|
|
4948
|
+
type: z31.enum(["regression", "gain", "opportunity"]),
|
|
4949
|
+
severity: z31.enum(["critical", "high", "medium", "low"]),
|
|
4950
|
+
title: z31.string(),
|
|
4951
|
+
query: z31.string(),
|
|
4952
|
+
provider: z31.string(),
|
|
4953
|
+
recommendation: z31.string().nullable(),
|
|
4954
|
+
createdAt: z31.string(),
|
|
4857
4955
|
/**
|
|
4858
4956
|
* How many times this insight fired across recent runs for the same
|
|
4859
4957
|
* `(query, provider, type)` tuple. Always ≥ 1. Insights returned by the
|
|
@@ -4861,64 +4959,64 @@ var reportInsightSchema = z29.object({
|
|
|
4861
4959
|
* surfacing the multiplicity. Use it directly instead of grouping again
|
|
4862
4960
|
* client-side — counts derived from raw insight rows will overcount.
|
|
4863
4961
|
*/
|
|
4864
|
-
instanceCount:
|
|
4962
|
+
instanceCount: z31.number()
|
|
4865
4963
|
});
|
|
4866
|
-
var recommendedNextStepSchema =
|
|
4964
|
+
var recommendedNextStepSchema = z31.object({
|
|
4867
4965
|
/** 'immediate' | 'short-term' | 'medium-term' — bucketed by severity heuristic. */
|
|
4868
|
-
horizon:
|
|
4869
|
-
title:
|
|
4870
|
-
rationale:
|
|
4966
|
+
horizon: z31.enum(["immediate", "short-term", "medium-term"]),
|
|
4967
|
+
title: z31.string(),
|
|
4968
|
+
rationale: z31.string()
|
|
4871
4969
|
});
|
|
4872
|
-
var reportRateDeltaSchema =
|
|
4970
|
+
var reportRateDeltaSchema = z31.object({
|
|
4873
4971
|
/** Current value (0..100 for rates, raw count otherwise). When `window`
|
|
4874
4972
|
* is present this is the average over the last `window` checks. */
|
|
4875
|
-
current:
|
|
4973
|
+
current: z31.number(),
|
|
4876
4974
|
/** Prior value compared against. When `window` is present this is the
|
|
4877
4975
|
* average over the prior `window` checks before that. */
|
|
4878
|
-
prior:
|
|
4976
|
+
prior: z31.number(),
|
|
4879
4977
|
/** Absolute delta (current − prior). Negative = decrease. */
|
|
4880
|
-
deltaAbs:
|
|
4978
|
+
deltaAbs: z31.number(),
|
|
4881
4979
|
/**
|
|
4882
4980
|
* Signed percent change vs `prior`, rounded to a whole number. Null when
|
|
4883
4981
|
* `prior <= 0` (percentage undefined). Renderers route count/traffic tiles
|
|
4884
4982
|
* through the "smart %" rule — percentage when the prior base is large
|
|
4885
4983
|
* enough (`MIN_PCT_BASE`), otherwise a rounded raw delta.
|
|
4886
4984
|
*/
|
|
4887
|
-
deltaPct:
|
|
4985
|
+
deltaPct: z31.number().nullable(),
|
|
4888
4986
|
/**
|
|
4889
4987
|
* Direction tag for tone mapping. Threshold is metric-specific (3pp for
|
|
4890
4988
|
* rates, 0.5 for counts) so small noise lands as 'flat' rather than
|
|
4891
4989
|
* flipping up/down each run.
|
|
4892
4990
|
*/
|
|
4893
|
-
direction:
|
|
4991
|
+
direction: z31.enum(["up", "down", "flat"]),
|
|
4894
4992
|
/**
|
|
4895
4993
|
* How many points went into each side of the average. Omitted (or 1)
|
|
4896
4994
|
* means point-to-point (legacy "since last check"). Higher values mean
|
|
4897
4995
|
* a rolling-average comparison — renderers should label it as
|
|
4898
4996
|
* "vs prior N checks" when this is ≥ 2.
|
|
4899
4997
|
*/
|
|
4900
|
-
window:
|
|
4998
|
+
window: z31.number().optional()
|
|
4901
4999
|
});
|
|
4902
|
-
var reportProviderMovementSchema =
|
|
4903
|
-
provider:
|
|
4904
|
-
current:
|
|
4905
|
-
prior:
|
|
4906
|
-
deltaAbs:
|
|
4907
|
-
direction:
|
|
5000
|
+
var reportProviderMovementSchema = z31.object({
|
|
5001
|
+
provider: z31.string(),
|
|
5002
|
+
current: z31.number(),
|
|
5003
|
+
prior: z31.number(),
|
|
5004
|
+
deltaAbs: z31.number(),
|
|
5005
|
+
direction: z31.enum(["up", "down", "flat"])
|
|
4908
5006
|
});
|
|
4909
|
-
var whatsChangedSectionSchema =
|
|
5007
|
+
var whatsChangedSectionSchema = z31.object({
|
|
4910
5008
|
/**
|
|
4911
5009
|
* False when there's no prior run (or fewer than the trend baseline),
|
|
4912
5010
|
* meaning all per-metric deltas will be null. Renderers use this to swap
|
|
4913
5011
|
* in a "establishing baseline" fallback rather than rendering empty
|
|
4914
5012
|
* delta tiles.
|
|
4915
5013
|
*/
|
|
4916
|
-
enoughHistory:
|
|
5014
|
+
enoughHistory: z31.boolean(),
|
|
4917
5015
|
/**
|
|
4918
5016
|
* One-sentence narrative summary suitable as a section subtitle.
|
|
4919
5017
|
* Always present — even on baseline, narrates whatever signal exists.
|
|
4920
5018
|
*/
|
|
4921
|
-
headline:
|
|
5019
|
+
headline: z31.string(),
|
|
4922
5020
|
/** Citation rate delta vs the prior completed run. Null when no prior run. */
|
|
4923
5021
|
citationRate: reportRateDeltaSchema.nullable(),
|
|
4924
5022
|
/** Mention rate delta vs the prior completed run. Null when no prior run. */
|
|
@@ -4946,30 +5044,30 @@ var whatsChangedSectionSchema = z29.object({
|
|
|
4946
5044
|
* deltas "vs prior {comparisonWindowDays} days" off this single value so the
|
|
4947
5045
|
* SPA and HTML stay verbatim-identical.
|
|
4948
5046
|
*/
|
|
4949
|
-
comparisonWindowDays:
|
|
5047
|
+
comparisonWindowDays: z31.number().int().positive(),
|
|
4950
5048
|
/**
|
|
4951
5049
|
* Per-provider citation rate movements (latest run vs prior run). Empty
|
|
4952
5050
|
* when no prior run. Sorted by |deltaAbs| desc — providers with the
|
|
4953
5051
|
* biggest swing first.
|
|
4954
5052
|
*/
|
|
4955
|
-
providerMovements:
|
|
5053
|
+
providerMovements: z31.array(reportProviderMovementSchema),
|
|
4956
5054
|
/**
|
|
4957
5055
|
* Top wins this period — gains surfaced by the intelligence engine.
|
|
4958
5056
|
* Capped at 5; sourced from `insights` filtered to `type: 'gain'`.
|
|
4959
5057
|
*/
|
|
4960
|
-
wins:
|
|
5058
|
+
wins: z31.array(reportInsightSchema),
|
|
4961
5059
|
/**
|
|
4962
5060
|
* Top regressions this period — citations or mentions lost. Capped at 5;
|
|
4963
5061
|
* sourced from `insights` filtered to `type: 'regression'`.
|
|
4964
5062
|
*/
|
|
4965
|
-
regressions:
|
|
4966
|
-
});
|
|
4967
|
-
var reportAudienceSchema =
|
|
4968
|
-
var reportActionAudienceSchema =
|
|
4969
|
-
var reportActionHorizonSchema =
|
|
4970
|
-
var reportActionConfidenceSchema =
|
|
4971
|
-
var reportToneSchema =
|
|
4972
|
-
var reportActionCategorySchema =
|
|
5063
|
+
regressions: z31.array(reportInsightSchema)
|
|
5064
|
+
});
|
|
5065
|
+
var reportAudienceSchema = z31.enum(["agency", "client"]);
|
|
5066
|
+
var reportActionAudienceSchema = z31.enum(["agency", "client", "both"]);
|
|
5067
|
+
var reportActionHorizonSchema = z31.enum(["immediate", "short-term", "medium-term"]);
|
|
5068
|
+
var reportActionConfidenceSchema = z31.enum(["high", "medium", "low"]);
|
|
5069
|
+
var reportToneSchema = z31.enum(["positive", "caution", "negative", "neutral"]);
|
|
5070
|
+
var reportActionCategorySchema = z31.enum([
|
|
4973
5071
|
"content",
|
|
4974
5072
|
"competitors",
|
|
4975
5073
|
"provider",
|
|
@@ -4978,23 +5076,23 @@ var reportActionCategorySchema = z29.enum([
|
|
|
4978
5076
|
"location",
|
|
4979
5077
|
"monitoring"
|
|
4980
5078
|
]);
|
|
4981
|
-
var reportActionPlanItemSchema =
|
|
5079
|
+
var reportActionPlanItemSchema = z31.object({
|
|
4982
5080
|
/** Which report audience should see this action. `both` renders in both modes. */
|
|
4983
5081
|
audience: reportActionAudienceSchema,
|
|
4984
5082
|
/** Stable sort priority. Lower numbers render earlier. */
|
|
4985
|
-
priority:
|
|
5083
|
+
priority: z31.number(),
|
|
4986
5084
|
/** When this should be tackled. */
|
|
4987
5085
|
horizon: reportActionHorizonSchema,
|
|
4988
5086
|
category: reportActionCategorySchema,
|
|
4989
|
-
title:
|
|
5087
|
+
title: z31.string(),
|
|
4990
5088
|
/** Direct next step written as an operator/client-friendly imperative. */
|
|
4991
|
-
action:
|
|
5089
|
+
action: z31.string(),
|
|
4992
5090
|
/** Why this matters. Keep each entry concise and evidence-backed. */
|
|
4993
|
-
why:
|
|
5091
|
+
why: z31.array(z31.string()),
|
|
4994
5092
|
/** Specific observations that justify the action. */
|
|
4995
|
-
evidence:
|
|
5093
|
+
evidence: z31.array(z31.string()),
|
|
4996
5094
|
/** What should move if the action worked. */
|
|
4997
|
-
successMetric:
|
|
5095
|
+
successMetric: z31.string(),
|
|
4998
5096
|
/** Confidence in the recommendation based on the available evidence. */
|
|
4999
5097
|
confidence: reportActionConfidenceSchema,
|
|
5000
5098
|
/**
|
|
@@ -5006,23 +5104,23 @@ var reportActionPlanItemSchema = z29.object({
|
|
|
5006
5104
|
* load. Actions sourced from other signals (competitor gaps, indexing
|
|
5007
5105
|
* issues, etc.) omit this and use their own dismiss flows.
|
|
5008
5106
|
*/
|
|
5009
|
-
targetRef:
|
|
5107
|
+
targetRef: z31.string().optional()
|
|
5010
5108
|
});
|
|
5011
|
-
var reportClientSummarySchema =
|
|
5012
|
-
headline:
|
|
5013
|
-
overview:
|
|
5014
|
-
actionItems:
|
|
5015
|
-
confidenceNotes:
|
|
5109
|
+
var reportClientSummarySchema = z31.object({
|
|
5110
|
+
headline: z31.string(),
|
|
5111
|
+
overview: z31.string(),
|
|
5112
|
+
actionItems: z31.array(reportActionPlanItemSchema),
|
|
5113
|
+
confidenceNotes: z31.array(z31.string())
|
|
5016
5114
|
});
|
|
5017
|
-
var reportAgencyDiagnosticSchema =
|
|
5018
|
-
title:
|
|
5019
|
-
detail:
|
|
5020
|
-
severity:
|
|
5021
|
-
evidence:
|
|
5115
|
+
var reportAgencyDiagnosticSchema = z31.object({
|
|
5116
|
+
title: z31.string(),
|
|
5117
|
+
detail: z31.string(),
|
|
5118
|
+
severity: z31.enum(["positive", "caution", "negative", "neutral"]),
|
|
5119
|
+
evidence: z31.array(z31.string())
|
|
5022
5120
|
});
|
|
5023
|
-
var reportAgencyDiagnosticsSchema =
|
|
5024
|
-
priorities:
|
|
5025
|
-
diagnostics:
|
|
5121
|
+
var reportAgencyDiagnosticsSchema = z31.object({
|
|
5122
|
+
priorities: z31.array(reportActionPlanItemSchema),
|
|
5123
|
+
diagnostics: z31.array(reportAgencyDiagnosticSchema)
|
|
5026
5124
|
});
|
|
5027
5125
|
function reportActionTone(action) {
|
|
5028
5126
|
if (action.horizon === "immediate") return "negative";
|
|
@@ -5080,7 +5178,7 @@ function reportConfidenceLabel(confidence) {
|
|
|
5080
5178
|
return "Low";
|
|
5081
5179
|
}
|
|
5082
5180
|
}
|
|
5083
|
-
var projectReportDtoSchema =
|
|
5181
|
+
var projectReportDtoSchema = z31.object({
|
|
5084
5182
|
meta: reportMetaSchema,
|
|
5085
5183
|
executiveSummary: reportExecutiveSummarySchema,
|
|
5086
5184
|
citationScorecard: citationScorecardSchema,
|
|
@@ -5094,16 +5192,16 @@ var projectReportDtoSchema = z29.object({
|
|
|
5094
5192
|
/** Server-side log-evidence visibility (crawls + click-through sessions). Null when no traffic source connected. */
|
|
5095
5193
|
serverActivity: serverActivitySectionSchema.nullable(),
|
|
5096
5194
|
indexingHealth: indexingHealthSectionSchema.nullable(),
|
|
5097
|
-
citationsTrend:
|
|
5195
|
+
citationsTrend: z31.array(citationsTrendPointSchema),
|
|
5098
5196
|
/**
|
|
5099
5197
|
* Trend-focused "what's changed" summary for the report's act 2. Always
|
|
5100
5198
|
* present; renderers gate empty/baseline states via `enoughHistory`.
|
|
5101
5199
|
*/
|
|
5102
5200
|
whatsChanged: whatsChangedSectionSchema,
|
|
5103
|
-
insights:
|
|
5104
|
-
recommendedNextSteps:
|
|
5201
|
+
insights: z31.array(reportInsightSchema),
|
|
5202
|
+
recommendedNextSteps: z31.array(recommendedNextStepSchema),
|
|
5105
5203
|
/** Canonical structured actions shared by the client and agency render modes. */
|
|
5106
|
-
actionPlan:
|
|
5204
|
+
actionPlan: z31.array(reportActionPlanItemSchema),
|
|
5107
5205
|
/** Polished client-facing summary and action shortlist. */
|
|
5108
5206
|
clientSummary: reportClientSummarySchema,
|
|
5109
5207
|
/** Technical, evidence-oriented operator diagnostics for agency mode. */
|
|
@@ -5113,17 +5211,17 @@ var projectReportDtoSchema = z29.object({
|
|
|
5113
5211
|
* intelligence layer (`buildContentTargetRows`). Empty when no run has
|
|
5114
5212
|
* produced candidate queries with demand or competitor signal.
|
|
5115
5213
|
*/
|
|
5116
|
-
contentOpportunities:
|
|
5214
|
+
contentOpportunities: z31.array(contentTargetRowDtoSchema),
|
|
5117
5215
|
/**
|
|
5118
5216
|
* Queries where competitors were cited but the project was not. Sourced
|
|
5119
5217
|
* from `buildContentGapRows`. Empty until the first answer-visibility run.
|
|
5120
5218
|
*/
|
|
5121
|
-
contentGaps:
|
|
5219
|
+
contentGaps: z31.array(contentGapRowDtoSchema),
|
|
5122
5220
|
/**
|
|
5123
5221
|
* Per-query grounding source map (own + competitor cited URLs). Sourced
|
|
5124
5222
|
* from `buildContentSourceRows`. Empty until the first answer-visibility run.
|
|
5125
5223
|
*/
|
|
5126
|
-
groundingSources:
|
|
5224
|
+
groundingSources: z31.array(contentSourceRowDtoSchema)
|
|
5127
5225
|
});
|
|
5128
5226
|
|
|
5129
5227
|
// ../contracts/src/report-dedup.ts
|
|
@@ -5194,10 +5292,10 @@ function dedupeReportOpportunities(report) {
|
|
|
5194
5292
|
}
|
|
5195
5293
|
|
|
5196
5294
|
// ../contracts/src/skills.ts
|
|
5197
|
-
import { z as
|
|
5198
|
-
var codingAgentSchema =
|
|
5295
|
+
import { z as z32 } from "zod";
|
|
5296
|
+
var codingAgentSchema = z32.enum(["claude", "codex"]);
|
|
5199
5297
|
var CodingAgents = codingAgentSchema.enum;
|
|
5200
|
-
var skillsClientSchema =
|
|
5298
|
+
var skillsClientSchema = z32.enum(["claude", "codex", "all"]);
|
|
5201
5299
|
var SkillsClients = skillsClientSchema.enum;
|
|
5202
5300
|
var SKILL_MANIFEST_FILENAME = ".canonry-skill-manifest.json";
|
|
5203
5301
|
function classifySkillFile(params) {
|
|
@@ -5215,22 +5313,22 @@ function coerceSkillManifest(parsed) {
|
|
|
5215
5313
|
}
|
|
5216
5314
|
|
|
5217
5315
|
// ../contracts/src/traffic.ts
|
|
5218
|
-
import { z as
|
|
5219
|
-
var trafficCrawlerSegmentsSchema =
|
|
5220
|
-
content:
|
|
5221
|
-
sitemap:
|
|
5222
|
-
robots:
|
|
5223
|
-
asset:
|
|
5224
|
-
other:
|
|
5225
|
-
});
|
|
5226
|
-
var trafficPathClassSchema =
|
|
5316
|
+
import { z as z33 } from "zod";
|
|
5317
|
+
var trafficCrawlerSegmentsSchema = z33.object({
|
|
5318
|
+
content: z33.number().int().nonnegative(),
|
|
5319
|
+
sitemap: z33.number().int().nonnegative(),
|
|
5320
|
+
robots: z33.number().int().nonnegative(),
|
|
5321
|
+
asset: z33.number().int().nonnegative(),
|
|
5322
|
+
other: z33.number().int().nonnegative()
|
|
5323
|
+
});
|
|
5324
|
+
var trafficPathClassSchema = z33.enum([
|
|
5227
5325
|
"content",
|
|
5228
5326
|
"sitemap",
|
|
5229
5327
|
"robots",
|
|
5230
5328
|
"asset",
|
|
5231
5329
|
"other"
|
|
5232
5330
|
]);
|
|
5233
|
-
var trafficSourceTypeSchema =
|
|
5331
|
+
var trafficSourceTypeSchema = z33.enum([
|
|
5234
5332
|
"cloud-run",
|
|
5235
5333
|
"wordpress",
|
|
5236
5334
|
"cloudflare",
|
|
@@ -5238,7 +5336,7 @@ var trafficSourceTypeSchema = z31.enum([
|
|
|
5238
5336
|
"generic-log"
|
|
5239
5337
|
]);
|
|
5240
5338
|
var TrafficSourceTypes = trafficSourceTypeSchema.enum;
|
|
5241
|
-
var trafficAdapterCapabilitySchema =
|
|
5339
|
+
var trafficAdapterCapabilitySchema = z33.enum([
|
|
5242
5340
|
"raw-request-events",
|
|
5243
5341
|
"aggregate-request-metrics",
|
|
5244
5342
|
"request-url",
|
|
@@ -5249,252 +5347,252 @@ var trafficAdapterCapabilitySchema = z31.enum([
|
|
|
5249
5347
|
"cursor-pull"
|
|
5250
5348
|
]);
|
|
5251
5349
|
var TrafficAdapterCapabilities = trafficAdapterCapabilitySchema.enum;
|
|
5252
|
-
var trafficEvidenceKindSchema =
|
|
5350
|
+
var trafficEvidenceKindSchema = z33.enum(["raw-request", "aggregate-bucket"]);
|
|
5253
5351
|
var TrafficEvidenceKinds = trafficEvidenceKindSchema.enum;
|
|
5254
|
-
var trafficEventConfidenceSchema =
|
|
5352
|
+
var trafficEventConfidenceSchema = z33.enum(["observed", "provider-aggregated", "inferred"]);
|
|
5255
5353
|
var TrafficEventConfidences = trafficEventConfidenceSchema.enum;
|
|
5256
|
-
var trafficProviderResourceSchema =
|
|
5257
|
-
type:
|
|
5258
|
-
labels:
|
|
5354
|
+
var trafficProviderResourceSchema = z33.object({
|
|
5355
|
+
type: z33.string().nullable(),
|
|
5356
|
+
labels: z33.record(z33.string(), z33.string())
|
|
5259
5357
|
});
|
|
5260
|
-
var normalizedTrafficRequestSchema =
|
|
5358
|
+
var normalizedTrafficRequestSchema = z33.object({
|
|
5261
5359
|
sourceType: trafficSourceTypeSchema,
|
|
5262
|
-
evidenceKind:
|
|
5263
|
-
confidence:
|
|
5264
|
-
eventId:
|
|
5265
|
-
observedAt:
|
|
5266
|
-
method:
|
|
5267
|
-
requestUrl:
|
|
5268
|
-
host:
|
|
5269
|
-
path:
|
|
5270
|
-
queryString:
|
|
5271
|
-
status:
|
|
5272
|
-
userAgent:
|
|
5273
|
-
remoteIp:
|
|
5274
|
-
referer:
|
|
5275
|
-
latencyMs:
|
|
5276
|
-
requestSizeBytes:
|
|
5277
|
-
responseSizeBytes:
|
|
5360
|
+
evidenceKind: z33.literal(TrafficEvidenceKinds["raw-request"]),
|
|
5361
|
+
confidence: z33.literal(TrafficEventConfidences.observed),
|
|
5362
|
+
eventId: z33.string().min(1),
|
|
5363
|
+
observedAt: z33.string().min(1),
|
|
5364
|
+
method: z33.string().nullable(),
|
|
5365
|
+
requestUrl: z33.string().nullable(),
|
|
5366
|
+
host: z33.string().nullable(),
|
|
5367
|
+
path: z33.string().min(1),
|
|
5368
|
+
queryString: z33.string().nullable(),
|
|
5369
|
+
status: z33.number().int().nullable(),
|
|
5370
|
+
userAgent: z33.string().nullable(),
|
|
5371
|
+
remoteIp: z33.string().nullable(),
|
|
5372
|
+
referer: z33.string().nullable(),
|
|
5373
|
+
latencyMs: z33.number().nullable(),
|
|
5374
|
+
requestSizeBytes: z33.number().int().nullable(),
|
|
5375
|
+
responseSizeBytes: z33.number().int().nullable(),
|
|
5278
5376
|
providerResource: trafficProviderResourceSchema,
|
|
5279
|
-
providerLabels:
|
|
5377
|
+
providerLabels: z33.record(z33.string(), z33.string())
|
|
5280
5378
|
});
|
|
5281
|
-
var normalizedTrafficPullPageSchema =
|
|
5282
|
-
events:
|
|
5283
|
-
rawEntryCount:
|
|
5284
|
-
skippedEntryCount:
|
|
5285
|
-
nextPageToken:
|
|
5286
|
-
filter:
|
|
5379
|
+
var normalizedTrafficPullPageSchema = z33.object({
|
|
5380
|
+
events: z33.array(normalizedTrafficRequestSchema),
|
|
5381
|
+
rawEntryCount: z33.number().int().nonnegative(),
|
|
5382
|
+
skippedEntryCount: z33.number().int().nonnegative(),
|
|
5383
|
+
nextPageToken: z33.string().optional(),
|
|
5384
|
+
filter: z33.string()
|
|
5287
5385
|
});
|
|
5288
|
-
var trafficSourceStatusSchema =
|
|
5386
|
+
var trafficSourceStatusSchema = z33.enum(["connected", "paused", "error", "archived"]);
|
|
5289
5387
|
var TrafficSourceStatuses = trafficSourceStatusSchema.enum;
|
|
5290
|
-
var trafficSourceAuthModeSchema =
|
|
5388
|
+
var trafficSourceAuthModeSchema = z33.enum(["oauth", "service-account"]);
|
|
5291
5389
|
var TrafficSourceAuthModes = trafficSourceAuthModeSchema.enum;
|
|
5292
|
-
var verificationStatusSchema =
|
|
5390
|
+
var verificationStatusSchema = z33.enum(["verified", "claimed_unverified", "unknown_ai_like"]);
|
|
5293
5391
|
var VerificationStatuses = verificationStatusSchema.enum;
|
|
5294
|
-
var cloudRunSourceConfigSchema =
|
|
5295
|
-
gcpProjectId:
|
|
5296
|
-
serviceName:
|
|
5297
|
-
location:
|
|
5392
|
+
var cloudRunSourceConfigSchema = z33.object({
|
|
5393
|
+
gcpProjectId: z33.string().min(1),
|
|
5394
|
+
serviceName: z33.string().nullable().optional(),
|
|
5395
|
+
location: z33.string().nullable().optional(),
|
|
5298
5396
|
authMode: trafficSourceAuthModeSchema
|
|
5299
5397
|
});
|
|
5300
|
-
var wordpressTrafficSourceConfigSchema =
|
|
5301
|
-
baseUrl:
|
|
5302
|
-
username:
|
|
5398
|
+
var wordpressTrafficSourceConfigSchema = z33.object({
|
|
5399
|
+
baseUrl: z33.string().url(),
|
|
5400
|
+
username: z33.string().min(1)
|
|
5303
5401
|
});
|
|
5304
|
-
var vercelTrafficEnvironmentSchema =
|
|
5402
|
+
var vercelTrafficEnvironmentSchema = z33.enum(["production", "preview"]);
|
|
5305
5403
|
var VercelTrafficEnvironments = vercelTrafficEnvironmentSchema.enum;
|
|
5306
|
-
var vercelTrafficSourceConfigSchema =
|
|
5404
|
+
var vercelTrafficSourceConfigSchema = z33.object({
|
|
5307
5405
|
/** Vercel project id (e.g. `prj_...`). */
|
|
5308
|
-
projectId:
|
|
5406
|
+
projectId: z33.string().min(1),
|
|
5309
5407
|
/** Vercel team or account id: the org that owns the project. */
|
|
5310
|
-
teamId:
|
|
5408
|
+
teamId: z33.string().min(1),
|
|
5311
5409
|
environment: vercelTrafficEnvironmentSchema
|
|
5312
5410
|
});
|
|
5313
|
-
var trafficSourceDtoSchema =
|
|
5314
|
-
id:
|
|
5315
|
-
projectId:
|
|
5411
|
+
var trafficSourceDtoSchema = z33.object({
|
|
5412
|
+
id: z33.string(),
|
|
5413
|
+
projectId: z33.string(),
|
|
5316
5414
|
sourceType: trafficSourceTypeSchema,
|
|
5317
|
-
displayName:
|
|
5415
|
+
displayName: z33.string(),
|
|
5318
5416
|
status: trafficSourceStatusSchema,
|
|
5319
|
-
lastSyncedAt:
|
|
5320
|
-
lastCursor:
|
|
5321
|
-
lastError:
|
|
5322
|
-
archivedAt:
|
|
5323
|
-
config:
|
|
5324
|
-
createdAt:
|
|
5325
|
-
updatedAt:
|
|
5326
|
-
});
|
|
5327
|
-
var trafficConnectCloudRunRequestSchema =
|
|
5328
|
-
gcpProjectId:
|
|
5329
|
-
serviceName:
|
|
5330
|
-
location:
|
|
5331
|
-
displayName:
|
|
5417
|
+
lastSyncedAt: z33.string().nullable(),
|
|
5418
|
+
lastCursor: z33.string().nullable(),
|
|
5419
|
+
lastError: z33.string().nullable(),
|
|
5420
|
+
archivedAt: z33.string().nullable(),
|
|
5421
|
+
config: z33.record(z33.string(), z33.unknown()),
|
|
5422
|
+
createdAt: z33.string(),
|
|
5423
|
+
updatedAt: z33.string()
|
|
5424
|
+
});
|
|
5425
|
+
var trafficConnectCloudRunRequestSchema = z33.object({
|
|
5426
|
+
gcpProjectId: z33.string().min(1),
|
|
5427
|
+
serviceName: z33.string().min(1).optional(),
|
|
5428
|
+
location: z33.string().min(1).optional(),
|
|
5429
|
+
displayName: z33.string().min(1).optional(),
|
|
5332
5430
|
/** Service-account JSON content (string). When omitted, defaults to OAuth via `canonry google connect <project> --type ga4` flow. */
|
|
5333
|
-
keyJson:
|
|
5431
|
+
keyJson: z33.string().optional()
|
|
5334
5432
|
});
|
|
5335
|
-
var trafficConnectWordpressRequestSchema =
|
|
5336
|
-
baseUrl:
|
|
5337
|
-
username:
|
|
5433
|
+
var trafficConnectWordpressRequestSchema = z33.object({
|
|
5434
|
+
baseUrl: z33.string().url(),
|
|
5435
|
+
username: z33.string().min(1),
|
|
5338
5436
|
/** WordPress Application Password (the same auth used by the content client). */
|
|
5339
|
-
applicationPassword:
|
|
5340
|
-
displayName:
|
|
5437
|
+
applicationPassword: z33.string().min(1),
|
|
5438
|
+
displayName: z33.string().min(1).optional()
|
|
5341
5439
|
});
|
|
5342
|
-
var trafficConnectVercelRequestSchema =
|
|
5440
|
+
var trafficConnectVercelRequestSchema = z33.object({
|
|
5343
5441
|
/** Vercel project id (e.g. `prj_...`) — from the Vercel dashboard or `.vercel/project.json`. */
|
|
5344
|
-
projectId:
|
|
5442
|
+
projectId: z33.string().min(1),
|
|
5345
5443
|
/** Vercel team or account id: the org that owns the project ("orgId" in .vercel/project.json). */
|
|
5346
|
-
teamId:
|
|
5444
|
+
teamId: z33.string().min(1),
|
|
5347
5445
|
/** Vercel personal access token. Stored in `~/.canonry/config.yaml`, never the DB. */
|
|
5348
|
-
token:
|
|
5446
|
+
token: z33.string().min(1),
|
|
5349
5447
|
/** Which deployment environment's request logs to pull. Default: `production`. */
|
|
5350
5448
|
environment: vercelTrafficEnvironmentSchema.optional(),
|
|
5351
|
-
displayName:
|
|
5449
|
+
displayName: z33.string().min(1).optional()
|
|
5352
5450
|
});
|
|
5353
|
-
var trafficSyncResponseSchema =
|
|
5354
|
-
sourceId:
|
|
5355
|
-
runId:
|
|
5356
|
-
syncedAt:
|
|
5357
|
-
pulledEvents:
|
|
5451
|
+
var trafficSyncResponseSchema = z33.object({
|
|
5452
|
+
sourceId: z33.string(),
|
|
5453
|
+
runId: z33.string(),
|
|
5454
|
+
syncedAt: z33.string(),
|
|
5455
|
+
pulledEvents: z33.number().int().nonnegative(),
|
|
5358
5456
|
/** Self-traffic events (Canonry's own tooling) dropped before rollup. */
|
|
5359
|
-
selfTrafficExcluded:
|
|
5360
|
-
crawlerHits:
|
|
5361
|
-
aiUserFetchHits:
|
|
5362
|
-
aiReferralHits:
|
|
5363
|
-
unknownHits:
|
|
5364
|
-
crawlerBucketRows:
|
|
5365
|
-
aiUserFetchBucketRows:
|
|
5366
|
-
aiReferralBucketRows:
|
|
5367
|
-
sampleRows:
|
|
5368
|
-
windowStart:
|
|
5369
|
-
windowEnd:
|
|
5370
|
-
});
|
|
5371
|
-
var trafficBackfillRequestSchema =
|
|
5457
|
+
selfTrafficExcluded: z33.number().int().nonnegative(),
|
|
5458
|
+
crawlerHits: z33.number().int().nonnegative(),
|
|
5459
|
+
aiUserFetchHits: z33.number().int().nonnegative(),
|
|
5460
|
+
aiReferralHits: z33.number().int().nonnegative(),
|
|
5461
|
+
unknownHits: z33.number().int().nonnegative(),
|
|
5462
|
+
crawlerBucketRows: z33.number().int().nonnegative(),
|
|
5463
|
+
aiUserFetchBucketRows: z33.number().int().nonnegative(),
|
|
5464
|
+
aiReferralBucketRows: z33.number().int().nonnegative(),
|
|
5465
|
+
sampleRows: z33.number().int().nonnegative(),
|
|
5466
|
+
windowStart: z33.string(),
|
|
5467
|
+
windowEnd: z33.string()
|
|
5468
|
+
});
|
|
5469
|
+
var trafficBackfillRequestSchema = z33.object({
|
|
5372
5470
|
/** Lookback window in days. Capped server-side at the upstream log retention ceiling (Cloud Logging _Default = 30d). Default: 30. */
|
|
5373
|
-
days:
|
|
5471
|
+
days: z33.number().int().positive().optional()
|
|
5374
5472
|
});
|
|
5375
|
-
var trafficResetRequestSchema =
|
|
5376
|
-
advanceToNow:
|
|
5473
|
+
var trafficResetRequestSchema = z33.object({
|
|
5474
|
+
advanceToNow: z33.literal(true)
|
|
5377
5475
|
});
|
|
5378
|
-
var trafficBackfillResponseSchema =
|
|
5379
|
-
sourceId:
|
|
5380
|
-
runId:
|
|
5476
|
+
var trafficBackfillResponseSchema = z33.object({
|
|
5477
|
+
sourceId: z33.string(),
|
|
5478
|
+
runId: z33.string(),
|
|
5381
5479
|
status: runStatusSchema,
|
|
5382
|
-
windowStart:
|
|
5383
|
-
windowEnd:
|
|
5480
|
+
windowStart: z33.string(),
|
|
5481
|
+
windowEnd: z33.string(),
|
|
5384
5482
|
/** Days actually used after server-side clamping (≤ requested). */
|
|
5385
|
-
daysRequested:
|
|
5386
|
-
daysApplied:
|
|
5483
|
+
daysRequested: z33.number().int().positive(),
|
|
5484
|
+
daysApplied: z33.number().int().positive()
|
|
5387
5485
|
});
|
|
5388
|
-
var trafficSourceTotalsSchema =
|
|
5486
|
+
var trafficSourceTotalsSchema = z33.object({
|
|
5389
5487
|
/**
|
|
5390
5488
|
* Total classified-crawler hits in the window. UNCHANGED contract — still the
|
|
5391
5489
|
* full count across every path class. Use `crawlerContentHits` for the
|
|
5392
5490
|
* "content was actually crawled" signal.
|
|
5393
5491
|
*/
|
|
5394
|
-
crawlerHits:
|
|
5492
|
+
crawlerHits: z33.number().int().nonnegative(),
|
|
5395
5493
|
/** Crawler hits against content/document paths only (= `crawlerSegments.content`). */
|
|
5396
|
-
crawlerContentHits:
|
|
5494
|
+
crawlerContentHits: z33.number().int().nonnegative(),
|
|
5397
5495
|
/** Infrastructure crawler hits — sitemap + robots + asset fetches (`crawlerSegments.{sitemap,robots,asset}`). */
|
|
5398
|
-
crawlerInfraHits:
|
|
5496
|
+
crawlerInfraHits: z33.number().int().nonnegative(),
|
|
5399
5497
|
/** Full per-class crawler-hit breakdown; the five buckets sum to `crawlerHits`. */
|
|
5400
5498
|
crawlerSegments: trafficCrawlerSegmentsSchema,
|
|
5401
|
-
aiUserFetchHits:
|
|
5402
|
-
aiReferralHits:
|
|
5403
|
-
sampleCount:
|
|
5499
|
+
aiUserFetchHits: z33.number().int().nonnegative(),
|
|
5500
|
+
aiReferralHits: z33.number().int().nonnegative(),
|
|
5501
|
+
sampleCount: z33.number().int().nonnegative()
|
|
5404
5502
|
});
|
|
5405
|
-
var trafficSourceListResponseSchema =
|
|
5406
|
-
sources:
|
|
5503
|
+
var trafficSourceListResponseSchema = z33.object({
|
|
5504
|
+
sources: z33.array(trafficSourceDtoSchema)
|
|
5407
5505
|
});
|
|
5408
5506
|
var trafficSourceDetailDtoSchema = trafficSourceDtoSchema.extend({
|
|
5409
5507
|
totals24h: trafficSourceTotalsSchema,
|
|
5410
|
-
latestRun:
|
|
5411
|
-
runId:
|
|
5508
|
+
latestRun: z33.object({
|
|
5509
|
+
runId: z33.string(),
|
|
5412
5510
|
status: runStatusSchema,
|
|
5413
|
-
startedAt:
|
|
5414
|
-
finishedAt:
|
|
5415
|
-
error:
|
|
5511
|
+
startedAt: z33.string().nullable(),
|
|
5512
|
+
finishedAt: z33.string().nullable(),
|
|
5513
|
+
error: z33.string().nullable()
|
|
5416
5514
|
}).nullable()
|
|
5417
5515
|
});
|
|
5418
|
-
var trafficStatusResponseSchema =
|
|
5419
|
-
sources:
|
|
5516
|
+
var trafficStatusResponseSchema = z33.object({
|
|
5517
|
+
sources: z33.array(trafficSourceDetailDtoSchema)
|
|
5420
5518
|
});
|
|
5421
|
-
var trafficEventKindSchema =
|
|
5519
|
+
var trafficEventKindSchema = z33.enum(["crawler", "ai-user-fetch", "ai-referral"]);
|
|
5422
5520
|
var TrafficEventKinds = trafficEventKindSchema.enum;
|
|
5423
|
-
var trafficCrawlerEventEntrySchema =
|
|
5424
|
-
kind:
|
|
5425
|
-
sourceId:
|
|
5426
|
-
tsHour:
|
|
5427
|
-
botId:
|
|
5428
|
-
operator:
|
|
5429
|
-
verificationStatus:
|
|
5430
|
-
pathNormalized:
|
|
5521
|
+
var trafficCrawlerEventEntrySchema = z33.object({
|
|
5522
|
+
kind: z33.literal(TrafficEventKinds.crawler),
|
|
5523
|
+
sourceId: z33.string(),
|
|
5524
|
+
tsHour: z33.string(),
|
|
5525
|
+
botId: z33.string(),
|
|
5526
|
+
operator: z33.string(),
|
|
5527
|
+
verificationStatus: z33.string(),
|
|
5528
|
+
pathNormalized: z33.string(),
|
|
5431
5529
|
/** Coarse class of the fetched path — lets the UI split content crawls from sitemap/robots/asset polling. */
|
|
5432
5530
|
pathClass: trafficPathClassSchema,
|
|
5433
|
-
status:
|
|
5434
|
-
hits:
|
|
5435
|
-
});
|
|
5436
|
-
var trafficAiUserFetchEventEntrySchema =
|
|
5437
|
-
kind:
|
|
5438
|
-
sourceId:
|
|
5439
|
-
tsHour:
|
|
5440
|
-
botId:
|
|
5441
|
-
operator:
|
|
5442
|
-
verificationStatus:
|
|
5443
|
-
pathNormalized:
|
|
5444
|
-
status:
|
|
5445
|
-
hits:
|
|
5446
|
-
});
|
|
5447
|
-
var trafficAiReferralEventEntrySchema =
|
|
5448
|
-
kind:
|
|
5449
|
-
sourceId:
|
|
5450
|
-
tsHour:
|
|
5451
|
-
product:
|
|
5452
|
-
operator:
|
|
5453
|
-
sourceDomain:
|
|
5454
|
-
evidenceType:
|
|
5455
|
-
landingPathNormalized:
|
|
5456
|
-
status:
|
|
5531
|
+
status: z33.number().int(),
|
|
5532
|
+
hits: z33.number().int().nonnegative()
|
|
5533
|
+
});
|
|
5534
|
+
var trafficAiUserFetchEventEntrySchema = z33.object({
|
|
5535
|
+
kind: z33.literal(TrafficEventKinds["ai-user-fetch"]),
|
|
5536
|
+
sourceId: z33.string(),
|
|
5537
|
+
tsHour: z33.string(),
|
|
5538
|
+
botId: z33.string(),
|
|
5539
|
+
operator: z33.string(),
|
|
5540
|
+
verificationStatus: z33.string(),
|
|
5541
|
+
pathNormalized: z33.string(),
|
|
5542
|
+
status: z33.number().int(),
|
|
5543
|
+
hits: z33.number().int().nonnegative()
|
|
5544
|
+
});
|
|
5545
|
+
var trafficAiReferralEventEntrySchema = z33.object({
|
|
5546
|
+
kind: z33.literal(TrafficEventKinds["ai-referral"]),
|
|
5547
|
+
sourceId: z33.string(),
|
|
5548
|
+
tsHour: z33.string(),
|
|
5549
|
+
product: z33.string(),
|
|
5550
|
+
operator: z33.string(),
|
|
5551
|
+
sourceDomain: z33.string(),
|
|
5552
|
+
evidenceType: z33.string(),
|
|
5553
|
+
landingPathNormalized: z33.string(),
|
|
5554
|
+
status: z33.number().int(),
|
|
5457
5555
|
/** Total AI-referral sessions in the bucket. `paidHits + organicHits + unknownHits === hits`. */
|
|
5458
|
-
hits:
|
|
5556
|
+
hits: z33.number().int().nonnegative(),
|
|
5459
5557
|
/** Sessions carrying paid-attribution UTM evidence (`utm_medium=cpc`, …). */
|
|
5460
|
-
paidHits:
|
|
5558
|
+
paidHits: z33.number().int().nonnegative(),
|
|
5461
5559
|
/** Sessions with no paid-attribution evidence. Not proof the click was unpaid — an untagged ad click is indistinguishable. */
|
|
5462
|
-
organicHits:
|
|
5560
|
+
organicHits: z33.number().int().nonnegative(),
|
|
5463
5561
|
/**
|
|
5464
5562
|
* Sessions ingested before the classifier shipped. Their UTM tags were never
|
|
5465
5563
|
* persisted, so they can never be resolved to paid or organic. Never fold
|
|
5466
5564
|
* these into `organicHits`.
|
|
5467
5565
|
*/
|
|
5468
|
-
unknownHits:
|
|
5566
|
+
unknownHits: z33.number().int().nonnegative()
|
|
5469
5567
|
});
|
|
5470
|
-
var trafficEventEntrySchema =
|
|
5568
|
+
var trafficEventEntrySchema = z33.discriminatedUnion("kind", [
|
|
5471
5569
|
trafficCrawlerEventEntrySchema,
|
|
5472
5570
|
trafficAiUserFetchEventEntrySchema,
|
|
5473
5571
|
trafficAiReferralEventEntrySchema
|
|
5474
5572
|
]);
|
|
5475
|
-
var trafficEventsResponseSchema =
|
|
5476
|
-
windowStart:
|
|
5477
|
-
windowEnd:
|
|
5478
|
-
totals:
|
|
5573
|
+
var trafficEventsResponseSchema = z33.object({
|
|
5574
|
+
windowStart: z33.string(),
|
|
5575
|
+
windowEnd: z33.string(),
|
|
5576
|
+
totals: z33.object({
|
|
5479
5577
|
/** Total classified-crawler hits across the window. UNCHANGED contract. */
|
|
5480
|
-
crawlerHits:
|
|
5578
|
+
crawlerHits: z33.number().int().nonnegative(),
|
|
5481
5579
|
/** Crawler hits against content/document paths only (= `crawlerSegments.content`). */
|
|
5482
|
-
crawlerContentHits:
|
|
5580
|
+
crawlerContentHits: z33.number().int().nonnegative(),
|
|
5483
5581
|
/** Infrastructure crawler hits — sitemap + robots + asset fetches. */
|
|
5484
|
-
crawlerInfraHits:
|
|
5582
|
+
crawlerInfraHits: z33.number().int().nonnegative(),
|
|
5485
5583
|
/** Full per-class crawler-hit breakdown; the five buckets sum to `crawlerHits`. */
|
|
5486
5584
|
crawlerSegments: trafficCrawlerSegmentsSchema,
|
|
5487
|
-
aiUserFetchHits:
|
|
5585
|
+
aiUserFetchHits: z33.number().int().nonnegative(),
|
|
5488
5586
|
/** Total AI-referral sessions. The three class buckets below sum to it. */
|
|
5489
|
-
aiReferralHits:
|
|
5587
|
+
aiReferralHits: z33.number().int().nonnegative(),
|
|
5490
5588
|
/** AI-referral sessions carrying paid-attribution UTM evidence. */
|
|
5491
|
-
aiReferralPaidHits:
|
|
5589
|
+
aiReferralPaidHits: z33.number().int().nonnegative(),
|
|
5492
5590
|
/** AI-referral sessions with no paid-attribution evidence. */
|
|
5493
|
-
aiReferralOrganicHits:
|
|
5591
|
+
aiReferralOrganicHits: z33.number().int().nonnegative(),
|
|
5494
5592
|
/** AI-referral sessions ingested before the classifier shipped; unresolvable, never organic. */
|
|
5495
|
-
aiReferralUnknownHits:
|
|
5593
|
+
aiReferralUnknownHits: z33.number().int().nonnegative()
|
|
5496
5594
|
}),
|
|
5497
|
-
events:
|
|
5595
|
+
events: z33.array(trafficEventEntrySchema)
|
|
5498
5596
|
});
|
|
5499
5597
|
|
|
5500
5598
|
// ../contracts/src/traffic-path.ts
|
|
@@ -5637,14 +5735,14 @@ function round(value, dp = 4) {
|
|
|
5637
5735
|
const f = 10 ** dp;
|
|
5638
5736
|
return (Math.round(value * f) + 0) / f;
|
|
5639
5737
|
}
|
|
5640
|
-
function wilsonInterval(successes, n,
|
|
5738
|
+
function wilsonInterval(successes, n, z35 = 1.96) {
|
|
5641
5739
|
if (!Number.isFinite(n) || n <= 0) return null;
|
|
5642
5740
|
const s = Math.max(0, Math.min(successes, n));
|
|
5643
5741
|
const p = s / n;
|
|
5644
|
-
const z210 =
|
|
5742
|
+
const z210 = z35 * z35;
|
|
5645
5743
|
const denom = 1 + z210 / n;
|
|
5646
5744
|
const center = (p + z210 / (2 * n)) / denom;
|
|
5647
|
-
const margin =
|
|
5745
|
+
const margin = z35 / denom * Math.sqrt(p * (1 - p) / n + z210 / (4 * n * n));
|
|
5648
5746
|
return {
|
|
5649
5747
|
low: round(Math.max(0, center - margin)),
|
|
5650
5748
|
high: round(Math.min(1, center + margin))
|
|
@@ -5652,118 +5750,241 @@ function wilsonInterval(successes, n, z33 = 1.96) {
|
|
|
5652
5750
|
}
|
|
5653
5751
|
|
|
5654
5752
|
// ../contracts/src/ads.ts
|
|
5655
|
-
import { z as
|
|
5656
|
-
var adsConnectRequestSchema =
|
|
5753
|
+
import { z as z34 } from "zod";
|
|
5754
|
+
var adsConnectRequestSchema = z34.object({
|
|
5657
5755
|
/** Ads Manager "SDK key" scoped to one ad account. Stored in config.yaml, never the DB. */
|
|
5658
|
-
apiKey:
|
|
5659
|
-
});
|
|
5660
|
-
var adsConnectionStatusDtoSchema =
|
|
5661
|
-
connected:
|
|
5662
|
-
adAccountId:
|
|
5663
|
-
displayName:
|
|
5664
|
-
currencyCode:
|
|
5665
|
-
timezone:
|
|
5666
|
-
status:
|
|
5667
|
-
lastSyncedAt:
|
|
5756
|
+
apiKey: z34.string().min(1)
|
|
5757
|
+
});
|
|
5758
|
+
var adsConnectionStatusDtoSchema = z34.object({
|
|
5759
|
+
connected: z34.boolean(),
|
|
5760
|
+
adAccountId: z34.string().nullable().optional(),
|
|
5761
|
+
displayName: z34.string().nullable().optional(),
|
|
5762
|
+
currencyCode: z34.string().nullable().optional(),
|
|
5763
|
+
timezone: z34.string().nullable().optional(),
|
|
5764
|
+
status: z34.string().nullable().optional(),
|
|
5765
|
+
lastSyncedAt: z34.string().nullable().optional(),
|
|
5668
5766
|
/** Whether the ad account has OpenAI conversion tracking (pixel or CAPI) configured,
|
|
5669
5767
|
* detected from synced campaigns carrying conversion_event_setting_ids. Optional:
|
|
5670
5768
|
* only present when connected. */
|
|
5671
|
-
conversionTrackingConfigured:
|
|
5672
|
-
});
|
|
5673
|
-
var adsDisconnectResponseSchema =
|
|
5674
|
-
disconnected:
|
|
5675
|
-
});
|
|
5676
|
-
var adsSyncResponseSchema =
|
|
5677
|
-
runId:
|
|
5678
|
-
status:
|
|
5679
|
-
});
|
|
5680
|
-
var adsCreativeDtoSchema =
|
|
5681
|
-
type:
|
|
5682
|
-
title:
|
|
5683
|
-
body:
|
|
5684
|
-
targetUrl:
|
|
5685
|
-
|
|
5686
|
-
|
|
5687
|
-
|
|
5688
|
-
|
|
5689
|
-
|
|
5690
|
-
|
|
5691
|
-
|
|
5692
|
-
|
|
5693
|
-
|
|
5694
|
-
|
|
5695
|
-
|
|
5696
|
-
|
|
5697
|
-
|
|
5698
|
-
|
|
5699
|
-
|
|
5700
|
-
|
|
5769
|
+
conversionTrackingConfigured: z34.boolean().optional()
|
|
5770
|
+
});
|
|
5771
|
+
var adsDisconnectResponseSchema = z34.object({
|
|
5772
|
+
disconnected: z34.boolean()
|
|
5773
|
+
});
|
|
5774
|
+
var adsSyncResponseSchema = z34.object({
|
|
5775
|
+
runId: z34.string(),
|
|
5776
|
+
status: z34.string()
|
|
5777
|
+
});
|
|
5778
|
+
var adsCreativeDtoSchema = z34.object({
|
|
5779
|
+
type: z34.string().nullable().optional(),
|
|
5780
|
+
title: z34.string().nullable().optional(),
|
|
5781
|
+
body: z34.string().nullable().optional(),
|
|
5782
|
+
targetUrl: z34.string().nullable().optional(),
|
|
5783
|
+
fileId: z34.string().nullable().optional()
|
|
5784
|
+
});
|
|
5785
|
+
var adsAdDtoSchema = z34.object({
|
|
5786
|
+
id: z34.string(),
|
|
5787
|
+
adGroupId: z34.string(),
|
|
5788
|
+
name: z34.string(),
|
|
5789
|
+
status: z34.string(),
|
|
5790
|
+
reviewStatus: z34.string().nullable().optional(),
|
|
5791
|
+
creative: adsCreativeDtoSchema.nullable().optional(),
|
|
5792
|
+
upstreamUpdatedAt: z34.number().int().nullable().optional(),
|
|
5793
|
+
syncedAt: z34.string().optional()
|
|
5794
|
+
});
|
|
5795
|
+
var adsAdGroupDtoSchema = z34.object({
|
|
5796
|
+
id: z34.string(),
|
|
5797
|
+
campaignId: z34.string(),
|
|
5798
|
+
name: z34.string(),
|
|
5799
|
+
description: z34.string().nullable().optional(),
|
|
5800
|
+
status: z34.string(),
|
|
5801
|
+
billingEventType: z34.string().nullable().optional(),
|
|
5802
|
+
maxBidMicros: z34.number().int().nullable().optional(),
|
|
5701
5803
|
/**
|
|
5702
5804
|
* The targeting primitive: entries are multi-line strings of
|
|
5703
5805
|
* newline-separated example queries (the live Ads Manager format).
|
|
5704
5806
|
*/
|
|
5705
|
-
contextHints:
|
|
5706
|
-
ads:
|
|
5707
|
-
|
|
5708
|
-
|
|
5709
|
-
|
|
5710
|
-
|
|
5711
|
-
|
|
5712
|
-
|
|
5713
|
-
|
|
5714
|
-
|
|
5715
|
-
|
|
5716
|
-
|
|
5717
|
-
|
|
5718
|
-
|
|
5719
|
-
|
|
5720
|
-
|
|
5807
|
+
contextHints: z34.array(z34.string()).default([]),
|
|
5808
|
+
ads: z34.array(adsAdDtoSchema).default([]),
|
|
5809
|
+
upstreamUpdatedAt: z34.number().int().nullable().optional(),
|
|
5810
|
+
syncedAt: z34.string().optional()
|
|
5811
|
+
});
|
|
5812
|
+
var adsCampaignDtoSchema = z34.object({
|
|
5813
|
+
id: z34.string(),
|
|
5814
|
+
name: z34.string(),
|
|
5815
|
+
description: z34.string().nullable().optional(),
|
|
5816
|
+
status: z34.string(),
|
|
5817
|
+
startTime: z34.number().int().nullable().optional(),
|
|
5818
|
+
endTime: z34.number().int().nullable().optional(),
|
|
5819
|
+
biddingType: z34.string().nullable().optional(),
|
|
5820
|
+
dailySpendLimitMicros: z34.number().int().nullable().optional(),
|
|
5821
|
+
lifetimeSpendLimitMicros: z34.number().int().nullable().optional(),
|
|
5822
|
+
locationIds: z34.array(z34.string()).optional(),
|
|
5823
|
+
adGroups: z34.array(adsAdGroupDtoSchema).default([]),
|
|
5824
|
+
upstreamUpdatedAt: z34.number().int().nullable().optional(),
|
|
5825
|
+
syncedAt: z34.string().optional()
|
|
5826
|
+
});
|
|
5827
|
+
var adsCampaignListResponseSchema = z34.object({
|
|
5828
|
+
campaigns: z34.array(adsCampaignDtoSchema)
|
|
5829
|
+
});
|
|
5830
|
+
var adsInsightLevelSchema = z34.enum(["campaign", "ad_group"]);
|
|
5721
5831
|
var AdsInsightLevels = adsInsightLevelSchema.enum;
|
|
5722
|
-
var adsInsightRowDtoSchema =
|
|
5832
|
+
var adsInsightRowDtoSchema = z34.object({
|
|
5723
5833
|
level: adsInsightLevelSchema,
|
|
5724
|
-
entityId:
|
|
5725
|
-
date:
|
|
5726
|
-
impressions:
|
|
5727
|
-
clicks:
|
|
5728
|
-
spendMicros:
|
|
5834
|
+
entityId: z34.string(),
|
|
5835
|
+
date: z34.string(),
|
|
5836
|
+
impressions: z34.number().int(),
|
|
5837
|
+
clicks: z34.number().int(),
|
|
5838
|
+
spendMicros: z34.number().int(),
|
|
5729
5839
|
/** Conversion count for the row. 0 when conversion tracking is not configured.
|
|
5730
5840
|
* Conversion VALUE (for ROAS) is a deliberate follow-up: the upstream value
|
|
5731
5841
|
* field is not yet captured against a live conversion-tracking account. */
|
|
5732
|
-
conversions:
|
|
5842
|
+
conversions: z34.number().int(),
|
|
5733
5843
|
/** clicks / impressions; null when impressions is 0. */
|
|
5734
|
-
ctr:
|
|
5844
|
+
ctr: z34.number().nullable(),
|
|
5735
5845
|
/** spendMicros / clicks, rounded to integer micros; null when clicks is 0. */
|
|
5736
|
-
cpcMicros:
|
|
5846
|
+
cpcMicros: z34.number().int().nullable()
|
|
5737
5847
|
});
|
|
5738
|
-
var adsInsightsResponseSchema =
|
|
5739
|
-
rows:
|
|
5848
|
+
var adsInsightsResponseSchema = z34.object({
|
|
5849
|
+
rows: z34.array(adsInsightRowDtoSchema),
|
|
5740
5850
|
/** Account currency for rendering spend/cpc; null before the first sync. */
|
|
5741
|
-
currencyCode:
|
|
5742
|
-
});
|
|
5743
|
-
var adsTotalsDtoSchema =
|
|
5744
|
-
impressions:
|
|
5745
|
-
clicks:
|
|
5746
|
-
spendMicros:
|
|
5747
|
-
conversions:
|
|
5748
|
-
ctr:
|
|
5749
|
-
cpcMicros:
|
|
5750
|
-
});
|
|
5751
|
-
var adsSummaryDtoSchema =
|
|
5752
|
-
connected:
|
|
5753
|
-
displayName:
|
|
5754
|
-
currencyCode:
|
|
5755
|
-
lastSyncedAt:
|
|
5756
|
-
campaignCount:
|
|
5757
|
-
adGroupCount:
|
|
5758
|
-
adCount:
|
|
5851
|
+
currencyCode: z34.string().nullable().optional()
|
|
5852
|
+
});
|
|
5853
|
+
var adsTotalsDtoSchema = z34.object({
|
|
5854
|
+
impressions: z34.number().int(),
|
|
5855
|
+
clicks: z34.number().int(),
|
|
5856
|
+
spendMicros: z34.number().int(),
|
|
5857
|
+
conversions: z34.number().int(),
|
|
5858
|
+
ctr: z34.number().nullable(),
|
|
5859
|
+
cpcMicros: z34.number().int().nullable()
|
|
5860
|
+
});
|
|
5861
|
+
var adsSummaryDtoSchema = z34.object({
|
|
5862
|
+
connected: z34.boolean(),
|
|
5863
|
+
displayName: z34.string().nullable().optional(),
|
|
5864
|
+
currencyCode: z34.string().nullable().optional(),
|
|
5865
|
+
lastSyncedAt: z34.string().nullable().optional(),
|
|
5866
|
+
campaignCount: z34.number().int(),
|
|
5867
|
+
adGroupCount: z34.number().int(),
|
|
5868
|
+
adCount: z34.number().int(),
|
|
5759
5869
|
/** Date range the totals cover (oldest/newest rollup date), null when empty. */
|
|
5760
|
-
window:
|
|
5761
|
-
from:
|
|
5762
|
-
to:
|
|
5870
|
+
window: z34.object({
|
|
5871
|
+
from: z34.string().nullable(),
|
|
5872
|
+
to: z34.string().nullable()
|
|
5763
5873
|
}),
|
|
5764
5874
|
/** Campaign-level rollup totals over the window (levels are not summed across). */
|
|
5765
5875
|
totals: adsTotalsDtoSchema
|
|
5766
5876
|
});
|
|
5877
|
+
var adsOperationKeySchema = z34.string().min(8).max(128).regex(/^[\w.:-]+$/, "operationKey may contain letters, numbers, dot, underscore, colon, and hyphen");
|
|
5878
|
+
var adsEntityIdSchema = z34.string().min(1).max(200);
|
|
5879
|
+
var adsNameSchema = z34.string().min(3).max(1e3).refine((value) => value.trim().length > 0);
|
|
5880
|
+
var adsTimestampSchema = z34.number().int().min(946684800).max(4102444800);
|
|
5881
|
+
var adsMicrosSchema = z34.number().int().positive().max(Number.MAX_SAFE_INTEGER);
|
|
5882
|
+
var adsHttpsUrlSchema = z34.string().url().refine((value) => new URL(value).protocol === "https:", {
|
|
5883
|
+
message: "URL must use https"
|
|
5884
|
+
});
|
|
5885
|
+
var adsOperationKindSchema = z34.enum([
|
|
5886
|
+
"image_upload",
|
|
5887
|
+
"campaign_create",
|
|
5888
|
+
"campaign_update",
|
|
5889
|
+
"campaign_pause",
|
|
5890
|
+
"ad_group_create",
|
|
5891
|
+
"ad_group_update",
|
|
5892
|
+
"ad_group_pause",
|
|
5893
|
+
"ad_create",
|
|
5894
|
+
"ad_update",
|
|
5895
|
+
"ad_pause"
|
|
5896
|
+
]);
|
|
5897
|
+
var AdsOperationKinds = adsOperationKindSchema.enum;
|
|
5898
|
+
var adsOperationStateSchema = z34.enum(["pending", "succeeded", "failed", "unknown"]);
|
|
5899
|
+
var AdsOperationStates = adsOperationStateSchema.enum;
|
|
5900
|
+
var adsEntityStatusSchema = z34.enum(["active", "paused", "archived"]);
|
|
5901
|
+
var AdsEntityStatuses = adsEntityStatusSchema.enum;
|
|
5902
|
+
var adsEntityTypeSchema = z34.enum(["file", "campaign", "ad_group", "ad"]);
|
|
5903
|
+
var AdsEntityTypes = adsEntityTypeSchema.enum;
|
|
5904
|
+
var adsImageUploadRequestSchema = z34.object({
|
|
5905
|
+
operationKey: adsOperationKeySchema,
|
|
5906
|
+
imageUrl: adsHttpsUrlSchema
|
|
5907
|
+
});
|
|
5908
|
+
var adsCampaignCreateRequestSchema = z34.object({
|
|
5909
|
+
operationKey: adsOperationKeySchema,
|
|
5910
|
+
name: adsNameSchema,
|
|
5911
|
+
description: z34.string().max(4e3).optional(),
|
|
5912
|
+
startTime: adsTimestampSchema.optional(),
|
|
5913
|
+
endTime: adsTimestampSchema.optional(),
|
|
5914
|
+
lifetimeSpendLimitMicros: adsMicrosSchema.min(1e6),
|
|
5915
|
+
locationIds: z34.array(adsEntityIdSchema).min(1).max(100)
|
|
5916
|
+
}).superRefine((value, ctx) => {
|
|
5917
|
+
if (value.startTime !== void 0 && value.endTime !== void 0 && value.endTime <= value.startTime) {
|
|
5918
|
+
ctx.addIssue({ code: "custom", path: ["endTime"], message: "endTime must be after startTime" });
|
|
5919
|
+
}
|
|
5920
|
+
});
|
|
5921
|
+
var adsAdGroupCreateRequestSchema = z34.object({
|
|
5922
|
+
operationKey: adsOperationKeySchema,
|
|
5923
|
+
campaignId: adsEntityIdSchema,
|
|
5924
|
+
name: adsNameSchema,
|
|
5925
|
+
description: z34.string().max(4e3).optional(),
|
|
5926
|
+
contextHints: z34.array(z34.string().min(1).max(1e3)).min(1).max(100),
|
|
5927
|
+
maxBidMicros: adsMicrosSchema.max(1e8)
|
|
5928
|
+
});
|
|
5929
|
+
var adsChatCardCreativeRequestSchema = z34.object({
|
|
5930
|
+
title: z34.string().min(3).max(50),
|
|
5931
|
+
body: z34.string().min(1).max(100),
|
|
5932
|
+
targetUrl: adsHttpsUrlSchema,
|
|
5933
|
+
fileId: adsEntityIdSchema
|
|
5934
|
+
});
|
|
5935
|
+
var adsAdCreateRequestSchema = z34.object({
|
|
5936
|
+
operationKey: adsOperationKeySchema,
|
|
5937
|
+
adGroupId: adsEntityIdSchema,
|
|
5938
|
+
name: adsNameSchema,
|
|
5939
|
+
creative: adsChatCardCreativeRequestSchema
|
|
5940
|
+
});
|
|
5941
|
+
function hasMutationField(value) {
|
|
5942
|
+
return Object.keys(value).some((key) => key !== "operationKey" && key !== "expectedUpdatedAt");
|
|
5943
|
+
}
|
|
5944
|
+
var adsCampaignUpdateRequestSchema = z34.object({
|
|
5945
|
+
operationKey: adsOperationKeySchema,
|
|
5946
|
+
expectedUpdatedAt: z34.number().int().nonnegative(),
|
|
5947
|
+
name: adsNameSchema.optional(),
|
|
5948
|
+
description: z34.string().max(4e3).nullable().optional(),
|
|
5949
|
+
startTime: adsTimestampSchema.nullable().optional(),
|
|
5950
|
+
endTime: adsTimestampSchema.nullable().optional(),
|
|
5951
|
+
lifetimeSpendLimitMicros: adsMicrosSchema.min(1e6).optional(),
|
|
5952
|
+
locationIds: z34.array(adsEntityIdSchema).min(1).max(100).optional()
|
|
5953
|
+
}).refine(hasMutationField, { message: "At least one campaign field must be updated" });
|
|
5954
|
+
var adsAdGroupUpdateRequestSchema = z34.object({
|
|
5955
|
+
operationKey: adsOperationKeySchema,
|
|
5956
|
+
expectedUpdatedAt: z34.number().int().nonnegative(),
|
|
5957
|
+
name: adsNameSchema.optional(),
|
|
5958
|
+
description: z34.string().max(4e3).nullable().optional(),
|
|
5959
|
+
contextHints: z34.array(z34.string().min(1).max(1e3)).min(1).max(100).optional(),
|
|
5960
|
+
maxBidMicros: adsMicrosSchema.max(1e8).optional()
|
|
5961
|
+
}).refine(hasMutationField, { message: "At least one ad group field must be updated" });
|
|
5962
|
+
var adsAdUpdateRequestSchema = z34.object({
|
|
5963
|
+
operationKey: adsOperationKeySchema,
|
|
5964
|
+
expectedUpdatedAt: z34.number().int().nonnegative(),
|
|
5965
|
+
name: adsNameSchema.optional(),
|
|
5966
|
+
creative: adsChatCardCreativeRequestSchema.optional()
|
|
5967
|
+
}).refine(hasMutationField, { message: "At least one ad field must be updated" });
|
|
5968
|
+
var adsPauseRequestSchema = z34.object({
|
|
5969
|
+
operationKey: adsOperationKeySchema
|
|
5970
|
+
});
|
|
5971
|
+
var adsOperationDtoSchema = z34.object({
|
|
5972
|
+
id: z34.string(),
|
|
5973
|
+
operationKey: z34.string(),
|
|
5974
|
+
kind: adsOperationKindSchema,
|
|
5975
|
+
state: adsOperationStateSchema,
|
|
5976
|
+
entityType: adsEntityTypeSchema.nullable(),
|
|
5977
|
+
entityId: z34.string().nullable(),
|
|
5978
|
+
upstreamUpdatedAt: z34.number().int().nullable(),
|
|
5979
|
+
errorCode: z34.string().nullable(),
|
|
5980
|
+
errorMessage: z34.string().nullable(),
|
|
5981
|
+
createdAt: z34.string(),
|
|
5982
|
+
updatedAt: z34.string()
|
|
5983
|
+
});
|
|
5984
|
+
var adsOperationResponseSchema = z34.object({
|
|
5985
|
+
operation: adsOperationDtoSchema,
|
|
5986
|
+
replayed: z34.boolean()
|
|
5987
|
+
});
|
|
5767
5988
|
function adsCtr(clicks, impressions) {
|
|
5768
5989
|
return impressions > 0 ? clicks / impressions : null;
|
|
5769
5990
|
}
|
|
@@ -5966,6 +6187,7 @@ export {
|
|
|
5966
6187
|
notificationCreateRequestSchema,
|
|
5967
6188
|
AppError,
|
|
5968
6189
|
notFound,
|
|
6190
|
+
alreadyExists,
|
|
5969
6191
|
validationError,
|
|
5970
6192
|
authRequired,
|
|
5971
6193
|
authInvalid,
|
|
@@ -6059,8 +6281,10 @@ export {
|
|
|
6059
6281
|
LlmCapabilities,
|
|
6060
6282
|
LLM_CAPABILITIES,
|
|
6061
6283
|
settingsDtoSchema,
|
|
6284
|
+
runStatusSchema,
|
|
6062
6285
|
RunStatuses,
|
|
6063
6286
|
RunKinds,
|
|
6287
|
+
runTriggerSchema,
|
|
6064
6288
|
RunTriggers,
|
|
6065
6289
|
citationStateSchema,
|
|
6066
6290
|
CitationStates,
|
|
@@ -6136,6 +6360,7 @@ export {
|
|
|
6136
6360
|
visibilityStatsDtoSchema,
|
|
6137
6361
|
visibilityCompareDtoSchema,
|
|
6138
6362
|
calendarMonthBounds,
|
|
6363
|
+
resultsExportDtoSchema,
|
|
6139
6364
|
formatRatio,
|
|
6140
6365
|
formatNumber,
|
|
6141
6366
|
formatDate,
|
|
@@ -6161,6 +6386,7 @@ export {
|
|
|
6161
6386
|
visibilityStateFromAnswerMentioned,
|
|
6162
6387
|
mentionStateFromAnswerMentioned,
|
|
6163
6388
|
brandKeyFromText,
|
|
6389
|
+
healthSnapshotDtoSchema,
|
|
6164
6390
|
agentProvidersResponseDtoSchema,
|
|
6165
6391
|
MemorySources,
|
|
6166
6392
|
AGENT_MEMORY_VALUE_MAX_BYTES,
|
|
@@ -6257,6 +6483,19 @@ export {
|
|
|
6257
6483
|
adsInsightLevelSchema,
|
|
6258
6484
|
adsInsightsResponseSchema,
|
|
6259
6485
|
adsSummaryDtoSchema,
|
|
6486
|
+
AdsOperationKinds,
|
|
6487
|
+
AdsOperationStates,
|
|
6488
|
+
AdsEntityStatuses,
|
|
6489
|
+
AdsEntityTypes,
|
|
6490
|
+
adsImageUploadRequestSchema,
|
|
6491
|
+
adsCampaignCreateRequestSchema,
|
|
6492
|
+
adsAdGroupCreateRequestSchema,
|
|
6493
|
+
adsAdCreateRequestSchema,
|
|
6494
|
+
adsCampaignUpdateRequestSchema,
|
|
6495
|
+
adsAdGroupUpdateRequestSchema,
|
|
6496
|
+
adsAdUpdateRequestSchema,
|
|
6497
|
+
adsPauseRequestSchema,
|
|
6498
|
+
adsOperationResponseSchema,
|
|
6260
6499
|
adsCtr,
|
|
6261
6500
|
adsCpcMicros,
|
|
6262
6501
|
dollarsToMicros,
|
|
@@ -6267,6 +6506,7 @@ export {
|
|
|
6267
6506
|
AI_PROVIDER_INFRA_DOMAINS,
|
|
6268
6507
|
escapeLikePattern,
|
|
6269
6508
|
READ_ONLY_SCOPE,
|
|
6509
|
+
ADS_WRITE_SCOPE,
|
|
6270
6510
|
isReadOnlyKey,
|
|
6271
6511
|
splitList,
|
|
6272
6512
|
parseOriginList,
|