@ainyc/canonry 4.47.0 → 4.50.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.
@@ -57,7 +57,7 @@ var PROVIDER_LOCATION_HANDLING = {
57
57
  },
58
58
  openai: {
59
59
  treatment: "request-param",
60
- description: "Location sent as a structured `user_location` field on OpenAI\u2019s web_search_preview tool."
60
+ description: "Location sent as a structured `user_location` field on OpenAI\u2019s web_search tool."
61
61
  },
62
62
  claude: {
63
63
  treatment: "request-param",
@@ -93,7 +93,7 @@ var runKindSchema = z2.enum([
93
93
  "aeo-discover-probe"
94
94
  ]);
95
95
  var RunKinds = runKindSchema.enum;
96
- var runTriggerSchema = z2.enum(["manual", "scheduled", "config-apply", "backfill"]);
96
+ var runTriggerSchema = z2.enum(["manual", "scheduled", "config-apply", "backfill", "probe"]);
97
97
  var RunTriggers = runTriggerSchema.enum;
98
98
  var citationStateSchema = z2.enum(["cited", "not-cited"]);
99
99
  var CitationStates = citationStateSchema.enum;
@@ -105,9 +105,10 @@ var computedTransitionSchema = z2.enum(["new", "cited", "lost", "emerging", "not
105
105
  var ComputedTransitions = computedTransitionSchema.enum;
106
106
  var mentionTransitionSchema = z2.enum(["new", "mentioned", "lost", "emerging", "not-mentioned"]);
107
107
  var MentionTransitions = mentionTransitionSchema.enum;
108
+ var operatorTriggerSchema = z2.enum([RunTriggers.manual, RunTriggers.probe]);
108
109
  var runTriggerRequestSchema = z2.object({
109
110
  kind: z2.literal(RunKinds["answer-visibility"]).optional(),
110
- trigger: z2.literal(RunTriggers.manual).optional(),
111
+ trigger: operatorTriggerSchema.optional(),
111
112
  providers: z2.array(providerNameSchema).optional(),
112
113
  queries: z2.array(z2.string().min(1)).min(1).optional(),
113
114
  location: z2.string().min(1).optional(),
@@ -444,6 +445,13 @@ var projectDtoSchema = z4.object({
444
445
  language: z4.string().min(2),
445
446
  tags: z4.array(z4.string()).default([]),
446
447
  labels: z4.record(z4.string(), z4.string()).default({}),
448
+ // Provider names this project sweeps against (subset of available providers).
449
+ // The server emits this on every project response (see GET /projects/:name in
450
+ // packages/api-routes/src/projects.ts) — the schema was historically missing
451
+ // the field even though the wire shape always included it. Add it here so
452
+ // ProjectDto consumers (web + CLI ApiClient) typecheck against the real
453
+ // response surface.
454
+ providers: z4.array(z4.string()).default([]),
447
455
  locations: z4.array(locationContextSchema).default([]),
448
456
  defaultLocation: z4.string().nullable().optional(),
449
457
  autoExtractBacklinks: z4.boolean().default(false),
@@ -722,6 +730,12 @@ var gscUrlInspectionDtoSchema = z6.object({
722
730
  lastCrawlResult: z6.string().nullable().optional(),
723
731
  isMobileFriendly: z6.boolean().nullable().optional(),
724
732
  richResults: z6.array(z6.string()).default([]),
733
+ // Spec gap: server has returned `referringUrls` since the GSC inspect
734
+ // route shipped (see google.ts handler at /gsc/inspect + /gsc/inspections),
735
+ // but the schema dropped the field so the generated TS client (and
736
+ // anything else reading from this DTO) lost the data silently. Adding
737
+ // here restores end-to-end visibility.
738
+ referringUrls: z6.array(z6.string()).default([]),
725
739
  inspectedAt: z6.string()
726
740
  });
727
741
  var indexTransitionSchema = z6.enum(["stable", "reindexed", "deindexed", "still-missing", "new"]);
@@ -763,12 +777,46 @@ var indexingRequestResultDtoSchema = z6.object({
763
777
  status: z6.enum(["success", "error"]),
764
778
  error: z6.string().optional()
765
779
  });
780
+ var indexingRequestResponseDtoSchema = z6.object({
781
+ summary: z6.object({
782
+ total: z6.number().int().nonnegative(),
783
+ succeeded: z6.number().int().nonnegative(),
784
+ failed: z6.number().int().nonnegative()
785
+ }),
786
+ results: z6.array(indexingRequestResultDtoSchema).default([])
787
+ });
766
788
  var gscCoverageSnapshotDtoSchema = z6.object({
767
789
  date: z6.string(),
768
790
  indexed: z6.number(),
769
791
  notIndexed: z6.number(),
770
792
  reasonBreakdown: z6.record(z6.string(), z6.number()).default({})
771
793
  });
794
+ var gscSiteDtoSchema = z6.object({
795
+ siteUrl: z6.string(),
796
+ permissionLevel: z6.string()
797
+ });
798
+ var gscSiteListResponseDtoSchema = z6.object({
799
+ sites: z6.array(gscSiteDtoSchema).default([])
800
+ });
801
+ var gscSitemapContentDtoSchema = z6.object({
802
+ type: z6.string(),
803
+ submitted: z6.string(),
804
+ indexed: z6.string()
805
+ });
806
+ var gscSitemapDtoSchema = z6.object({
807
+ path: z6.string(),
808
+ lastSubmitted: z6.string().optional(),
809
+ isPending: z6.boolean().optional(),
810
+ isSitemapsIndex: z6.boolean().optional(),
811
+ type: z6.string().optional(),
812
+ lastDownloaded: z6.string().optional(),
813
+ warnings: z6.string().optional(),
814
+ errors: z6.string().optional(),
815
+ contents: z6.array(gscSitemapContentDtoSchema).optional()
816
+ });
817
+ var gscSitemapListResponseDtoSchema = z6.object({
818
+ sitemaps: z6.array(gscSitemapDtoSchema).default([])
819
+ });
772
820
 
773
821
  // ../contracts/src/bing.ts
774
822
  import { z as z7 } from "zod";
@@ -824,152 +872,198 @@ var bingSubmitResultDtoSchema = z7.object({
824
872
  submittedAt: z7.string(),
825
873
  error: z7.string().optional()
826
874
  });
875
+ var bingIndexingRequestResponseDtoSchema = z7.object({
876
+ summary: z7.object({
877
+ total: z7.number().int().nonnegative(),
878
+ succeeded: z7.number().int().nonnegative(),
879
+ failed: z7.number().int().nonnegative()
880
+ }),
881
+ results: z7.array(bingSubmitResultDtoSchema).default([])
882
+ });
883
+ var bingSiteDtoSchema = z7.object({
884
+ url: z7.string(),
885
+ verified: z7.boolean()
886
+ });
887
+ var bingSitesResponseDtoSchema = z7.object({
888
+ sites: z7.array(bingSiteDtoSchema).default([])
889
+ });
890
+ var bingStatusDtoSchema = z7.object({
891
+ connected: z7.boolean(),
892
+ domain: z7.string(),
893
+ siteUrl: z7.string().nullable(),
894
+ createdAt: z7.string().nullable(),
895
+ updatedAt: z7.string().nullable()
896
+ });
897
+ var bingConnectResponseDtoSchema = z7.object({
898
+ connected: z7.boolean(),
899
+ domain: z7.string(),
900
+ siteUrl: z7.string().nullable(),
901
+ availableSites: z7.array(bingSiteDtoSchema).default([])
902
+ });
903
+ var bingSetSiteResponseDtoSchema = z7.object({
904
+ siteUrl: z7.string()
905
+ });
827
906
 
828
- // ../contracts/src/wordpress.ts
907
+ // ../contracts/src/cdp.ts
829
908
  import { z as z8 } from "zod";
830
- var wordpressEnvSchema = z8.enum(["live", "staging"]);
831
- var wordpressConnectionDtoSchema = z8.object({
832
- projectName: z8.string(),
833
- url: z8.string(),
834
- stagingUrl: z8.string().optional(),
835
- username: z8.string(),
909
+ var cdpTargetStatusDtoSchema = z8.object({
910
+ name: z8.string(),
911
+ alive: z8.boolean(),
912
+ lastUsed: z8.string().nullable()
913
+ });
914
+ var cdpStatusDtoSchema = z8.object({
915
+ connected: z8.boolean(),
916
+ endpoint: z8.string(),
917
+ version: z8.string().optional(),
918
+ browserVersion: z8.string().optional(),
919
+ targets: z8.array(cdpTargetStatusDtoSchema).default([])
920
+ });
921
+
922
+ // ../contracts/src/wordpress.ts
923
+ import { z as z9 } from "zod";
924
+ var wordpressEnvSchema = z9.enum(["live", "staging"]);
925
+ var wordpressConnectionDtoSchema = z9.object({
926
+ projectName: z9.string(),
927
+ url: z9.string(),
928
+ stagingUrl: z9.string().optional(),
929
+ username: z9.string(),
836
930
  defaultEnv: wordpressEnvSchema,
837
- createdAt: z8.string(),
838
- updatedAt: z8.string()
839
- });
840
- var wordpressSiteStatusDtoSchema = z8.object({
841
- url: z8.string(),
842
- reachable: z8.boolean(),
843
- pageCount: z8.number().nullable().optional(),
844
- version: z8.string().nullable().optional(),
845
- error: z8.string().nullable().optional(),
846
- plugins: z8.array(z8.string()).optional(),
847
- authenticatedUser: z8.object({
848
- id: z8.number(),
849
- slug: z8.string()
931
+ createdAt: z9.string(),
932
+ updatedAt: z9.string()
933
+ });
934
+ var wordpressSiteStatusDtoSchema = z9.object({
935
+ url: z9.string(),
936
+ reachable: z9.boolean(),
937
+ pageCount: z9.number().nullable().optional(),
938
+ version: z9.string().nullable().optional(),
939
+ error: z9.string().nullable().optional(),
940
+ plugins: z9.array(z9.string()).optional(),
941
+ authenticatedUser: z9.object({
942
+ id: z9.number(),
943
+ slug: z9.string()
850
944
  }).nullable().optional()
851
945
  });
852
- var wordpressStatusDtoSchema = z8.object({
853
- connected: z8.boolean(),
854
- projectName: z8.string(),
946
+ var wordpressStatusDtoSchema = z9.object({
947
+ connected: z9.boolean(),
948
+ projectName: z9.string(),
855
949
  defaultEnv: wordpressEnvSchema,
856
950
  live: wordpressSiteStatusDtoSchema.nullable(),
857
951
  staging: wordpressSiteStatusDtoSchema.nullable(),
858
- adminUrl: z8.string().nullable().optional()
859
- });
860
- var wordpressPageSummaryDtoSchema = z8.object({
861
- id: z8.number(),
862
- slug: z8.string(),
863
- title: z8.string(),
864
- status: z8.string(),
865
- modifiedAt: z8.string().nullable().optional(),
866
- link: z8.string().nullable().optional()
867
- });
868
- var wordpressSeoStateDtoSchema = z8.object({
869
- title: z8.string().nullable(),
870
- description: z8.string().nullable(),
871
- noindex: z8.boolean().nullable(),
872
- writable: z8.boolean().default(false),
873
- writeTargets: z8.array(z8.string()).default([])
874
- });
875
- var wordpressSchemaBlockDtoSchema = z8.object({
876
- type: z8.string(),
877
- json: z8.record(z8.string(), z8.unknown())
952
+ adminUrl: z9.string().nullable().optional()
953
+ });
954
+ var wordpressPageSummaryDtoSchema = z9.object({
955
+ id: z9.number(),
956
+ slug: z9.string(),
957
+ title: z9.string(),
958
+ status: z9.string(),
959
+ modifiedAt: z9.string().nullable().optional(),
960
+ link: z9.string().nullable().optional()
961
+ });
962
+ var wordpressSeoStateDtoSchema = z9.object({
963
+ title: z9.string().nullable(),
964
+ description: z9.string().nullable(),
965
+ noindex: z9.boolean().nullable(),
966
+ writable: z9.boolean().default(false),
967
+ writeTargets: z9.array(z9.string()).default([])
968
+ });
969
+ var wordpressSchemaBlockDtoSchema = z9.object({
970
+ type: z9.string(),
971
+ json: z9.record(z9.string(), z9.unknown())
878
972
  });
879
973
  var wordpressPageDetailDtoSchema = wordpressPageSummaryDtoSchema.extend({
880
974
  env: wordpressEnvSchema,
881
- content: z8.string(),
975
+ content: z9.string(),
882
976
  seo: wordpressSeoStateDtoSchema,
883
- schemaBlocks: z8.array(wordpressSchemaBlockDtoSchema).default([])
977
+ schemaBlocks: z9.array(wordpressSchemaBlockDtoSchema).default([])
884
978
  });
885
979
  var wordpressDiffPageDtoSchema = wordpressPageDetailDtoSchema.extend({
886
- contentHash: z8.string(),
887
- contentSnippet: z8.string()
888
- });
889
- var wordpressManualAssistDtoSchema = z8.object({
890
- manualRequired: z8.literal(true),
891
- targetUrl: z8.string(),
892
- adminUrl: z8.string().nullable().optional(),
893
- content: z8.string(),
894
- nextSteps: z8.array(z8.string()).default([])
895
- });
896
- var wordpressAuditIssueDtoSchema = z8.object({
897
- slug: z8.string(),
898
- severity: z8.enum(["high", "medium", "low"]),
899
- code: z8.enum([
980
+ contentHash: z9.string(),
981
+ contentSnippet: z9.string()
982
+ });
983
+ var wordpressManualAssistDtoSchema = z9.object({
984
+ manualRequired: z9.literal(true),
985
+ targetUrl: z9.string(),
986
+ adminUrl: z9.string().nullable().optional(),
987
+ content: z9.string(),
988
+ nextSteps: z9.array(z9.string()).default([])
989
+ });
990
+ var wordpressAuditIssueDtoSchema = z9.object({
991
+ slug: z9.string(),
992
+ severity: z9.enum(["high", "medium", "low"]),
993
+ code: z9.enum([
900
994
  "noindex",
901
995
  "missing-seo-title",
902
996
  "missing-meta-description",
903
997
  "missing-schema",
904
998
  "thin-content"
905
999
  ]),
906
- message: z8.string()
1000
+ message: z9.string()
907
1001
  });
908
- var wordpressAuditPageDtoSchema = z8.object({
909
- slug: z8.string(),
910
- title: z8.string(),
911
- status: z8.string(),
912
- wordCount: z8.number(),
1002
+ var wordpressAuditPageDtoSchema = z9.object({
1003
+ slug: z9.string(),
1004
+ title: z9.string(),
1005
+ status: z9.string(),
1006
+ wordCount: z9.number(),
913
1007
  seo: wordpressSeoStateDtoSchema,
914
- schemaPresent: z8.boolean(),
915
- issues: z8.array(wordpressAuditIssueDtoSchema).default([])
1008
+ schemaPresent: z9.boolean(),
1009
+ issues: z9.array(wordpressAuditIssueDtoSchema).default([])
916
1010
  });
917
- var wordpressBulkMetaEntryResultDtoSchema = z8.object({
918
- slug: z8.string(),
919
- status: z8.enum(["applied", "skipped", "manual"]),
920
- error: z8.string().optional(),
1011
+ var wordpressBulkMetaEntryResultDtoSchema = z9.object({
1012
+ slug: z9.string(),
1013
+ status: z9.enum(["applied", "skipped", "manual"]),
1014
+ error: z9.string().optional(),
921
1015
  manualAssist: wordpressManualAssistDtoSchema.optional()
922
1016
  });
923
- var wordpressBulkMetaResultDtoSchema = z8.object({
1017
+ var wordpressBulkMetaResultDtoSchema = z9.object({
924
1018
  env: wordpressEnvSchema,
925
- strategy: z8.enum(["plugin", "manual"]),
926
- results: z8.array(wordpressBulkMetaEntryResultDtoSchema)
1019
+ strategy: z9.enum(["plugin", "manual"]),
1020
+ results: z9.array(wordpressBulkMetaEntryResultDtoSchema)
927
1021
  });
928
- var wordpressSchemaDeployEntryResultDtoSchema = z8.object({
929
- slug: z8.string(),
930
- status: z8.enum(["deployed", "stripped", "skipped", "failed"]),
931
- schemasInjected: z8.array(z8.string()).optional(),
1022
+ var wordpressSchemaDeployEntryResultDtoSchema = z9.object({
1023
+ slug: z9.string(),
1024
+ status: z9.enum(["deployed", "stripped", "skipped", "failed"]),
1025
+ schemasInjected: z9.array(z9.string()).optional(),
932
1026
  manualAssist: wordpressManualAssistDtoSchema.optional(),
933
- error: z8.string().optional()
1027
+ error: z9.string().optional()
934
1028
  });
935
- var wordpressSchemaDeployResultDtoSchema = z8.object({
1029
+ var wordpressSchemaDeployResultDtoSchema = z9.object({
936
1030
  env: wordpressEnvSchema,
937
- results: z8.array(wordpressSchemaDeployEntryResultDtoSchema)
1031
+ results: z9.array(wordpressSchemaDeployEntryResultDtoSchema)
938
1032
  });
939
- var wordpressSchemaStatusPageDtoSchema = z8.object({
940
- slug: z8.string(),
941
- title: z8.string(),
942
- canonrySchemas: z8.array(z8.string()),
943
- thirdPartySchemas: z8.array(z8.string()),
944
- hasCanonrySchema: z8.boolean()
1033
+ var wordpressSchemaStatusPageDtoSchema = z9.object({
1034
+ slug: z9.string(),
1035
+ title: z9.string(),
1036
+ canonrySchemas: z9.array(z9.string()),
1037
+ thirdPartySchemas: z9.array(z9.string()),
1038
+ hasCanonrySchema: z9.boolean()
945
1039
  });
946
- var wordpressSchemaStatusResultDtoSchema = z8.object({
1040
+ var wordpressSchemaStatusResultDtoSchema = z9.object({
947
1041
  env: wordpressEnvSchema,
948
- pages: z8.array(wordpressSchemaStatusPageDtoSchema)
1042
+ pages: z9.array(wordpressSchemaStatusPageDtoSchema)
949
1043
  });
950
- var wordpressOnboardStepDtoSchema = z8.object({
951
- name: z8.string(),
952
- status: z8.enum(["completed", "skipped", "failed"]),
953
- summary: z8.string().optional(),
954
- error: z8.string().optional()
1044
+ var wordpressOnboardStepDtoSchema = z9.object({
1045
+ name: z9.string(),
1046
+ status: z9.enum(["completed", "skipped", "failed"]),
1047
+ summary: z9.string().optional(),
1048
+ error: z9.string().optional()
955
1049
  });
956
- var wordpressOnboardResultDtoSchema = z8.object({
957
- projectName: z8.string(),
958
- steps: z8.array(wordpressOnboardStepDtoSchema)
1050
+ var wordpressOnboardResultDtoSchema = z9.object({
1051
+ projectName: z9.string(),
1052
+ steps: z9.array(wordpressOnboardStepDtoSchema)
959
1053
  });
960
- var wordpressDiffDtoSchema = z8.object({
961
- slug: z8.string(),
1054
+ var wordpressDiffDtoSchema = z9.object({
1055
+ slug: z9.string(),
962
1056
  live: wordpressDiffPageDtoSchema,
963
1057
  staging: wordpressDiffPageDtoSchema,
964
- hasDifferences: z8.boolean(),
965
- differences: z8.object({
966
- title: z8.boolean(),
967
- slug: z8.boolean(),
968
- content: z8.boolean(),
969
- seoTitle: z8.boolean(),
970
- seoDescription: z8.boolean(),
971
- noindex: z8.boolean(),
972
- schema: z8.boolean()
1058
+ hasDifferences: z9.boolean(),
1059
+ differences: z9.object({
1060
+ title: z9.boolean(),
1061
+ slug: z9.boolean(),
1062
+ content: z9.boolean(),
1063
+ seoTitle: z9.boolean(),
1064
+ seoDescription: z9.boolean(),
1065
+ noindex: z9.boolean(),
1066
+ schema: z9.boolean()
973
1067
  })
974
1068
  });
975
1069
 
@@ -1004,16 +1098,38 @@ function isAgentProviderId(value) {
1004
1098
  return AGENT_PROVIDER_IDS.includes(value);
1005
1099
  }
1006
1100
 
1101
+ // ../contracts/src/settings.ts
1102
+ import { z as z10 } from "zod";
1103
+ var providerSummaryEntryDtoSchema = z10.object({
1104
+ name: z10.string(),
1105
+ displayName: z10.string().optional(),
1106
+ keyUrl: z10.string().optional(),
1107
+ modelHint: z10.string().optional(),
1108
+ model: z10.string().optional(),
1109
+ configured: z10.boolean(),
1110
+ quota: providerQuotaPolicySchema.optional(),
1111
+ /** Whether Vertex AI is configured for this provider (Gemini only). */
1112
+ vertexConfigured: z10.boolean().optional()
1113
+ });
1114
+ var integrationSettingsSummaryDtoSchema = z10.object({
1115
+ configured: z10.boolean()
1116
+ });
1117
+ var settingsDtoSchema = z10.object({
1118
+ providers: z10.array(providerSummaryEntryDtoSchema).default([]),
1119
+ google: integrationSettingsSummaryDtoSchema,
1120
+ bing: integrationSettingsSummaryDtoSchema
1121
+ });
1122
+
1007
1123
  // ../contracts/src/snapshot.ts
1008
- import { z as z9 } from "zod";
1009
- var snapshotAccuracySchema = z9.enum(["yes", "no", "unknown", "not-mentioned"]);
1010
- var snapshotQueryListSchema = z9.array(z9.string().min(1));
1011
- var snapshotRequestSchema = z9.object({
1012
- companyName: z9.string().min(1),
1013
- domain: z9.string().min(1),
1124
+ import { z as z11 } from "zod";
1125
+ var snapshotAccuracySchema = z11.enum(["yes", "no", "unknown", "not-mentioned"]);
1126
+ var snapshotQueryListSchema = z11.array(z11.string().min(1));
1127
+ var snapshotRequestSchema = z11.object({
1128
+ companyName: z11.string().min(1),
1129
+ domain: z11.string().min(1),
1014
1130
  queries: snapshotQueryListSchema.optional(),
1015
1131
  phrases: snapshotQueryListSchema.optional(),
1016
- competitors: z9.array(z9.string().min(1)).optional().default([])
1132
+ competitors: z11.array(z11.string().min(1)).optional().default([])
1017
1133
  }).superRefine((input, ctx) => {
1018
1134
  if (input.queries !== void 0 && input.phrases !== void 0) {
1019
1135
  ctx.addIssue({
@@ -1026,121 +1142,121 @@ var snapshotRequestSchema = z9.object({
1026
1142
  function resolveSnapshotRequestQueries(input) {
1027
1143
  return input.queries ?? input.phrases ?? [];
1028
1144
  }
1029
- var snapshotCompetitorEntrySchema = z9.object({
1030
- name: z9.string(),
1031
- count: z9.number().int().nonnegative()
1032
- });
1033
- var snapshotAuditFactorSchema = z9.object({
1034
- id: z9.string(),
1035
- name: z9.string(),
1036
- weight: z9.number(),
1037
- score: z9.number(),
1038
- grade: z9.string(),
1039
- status: z9.enum(["pass", "partial", "fail"]),
1040
- findings: z9.array(z9.object({
1041
- type: z9.string(),
1042
- message: z9.string()
1145
+ var snapshotCompetitorEntrySchema = z11.object({
1146
+ name: z11.string(),
1147
+ count: z11.number().int().nonnegative()
1148
+ });
1149
+ var snapshotAuditFactorSchema = z11.object({
1150
+ id: z11.string(),
1151
+ name: z11.string(),
1152
+ weight: z11.number(),
1153
+ score: z11.number(),
1154
+ grade: z11.string(),
1155
+ status: z11.enum(["pass", "partial", "fail"]),
1156
+ findings: z11.array(z11.object({
1157
+ type: z11.string(),
1158
+ message: z11.string()
1043
1159
  })).default([]),
1044
- recommendations: z9.array(z9.string()).default([])
1045
- });
1046
- var snapshotAuditSchema = z9.object({
1047
- url: z9.string(),
1048
- finalUrl: z9.string(),
1049
- auditedAt: z9.string(),
1050
- overallScore: z9.number(),
1051
- overallGrade: z9.string(),
1052
- summary: z9.string(),
1053
- factors: z9.array(snapshotAuditFactorSchema).default([])
1054
- });
1055
- var snapshotProfileSchema = z9.object({
1056
- industry: z9.string(),
1057
- summary: z9.string(),
1058
- services: z9.array(z9.string()).default([]),
1059
- categoryTerms: z9.array(z9.string()).default([])
1060
- });
1061
- var snapshotProviderResultSchema = z9.object({
1062
- provider: z9.string(),
1063
- displayName: z9.string(),
1064
- model: z9.string().nullable().optional(),
1065
- mentioned: z9.boolean(),
1066
- cited: z9.boolean(),
1160
+ recommendations: z11.array(z11.string()).default([])
1161
+ });
1162
+ var snapshotAuditSchema = z11.object({
1163
+ url: z11.string(),
1164
+ finalUrl: z11.string(),
1165
+ auditedAt: z11.string(),
1166
+ overallScore: z11.number(),
1167
+ overallGrade: z11.string(),
1168
+ summary: z11.string(),
1169
+ factors: z11.array(snapshotAuditFactorSchema).default([])
1170
+ });
1171
+ var snapshotProfileSchema = z11.object({
1172
+ industry: z11.string(),
1173
+ summary: z11.string(),
1174
+ services: z11.array(z11.string()).default([]),
1175
+ categoryTerms: z11.array(z11.string()).default([])
1176
+ });
1177
+ var snapshotProviderResultSchema = z11.object({
1178
+ provider: z11.string(),
1179
+ displayName: z11.string(),
1180
+ model: z11.string().nullable().optional(),
1181
+ mentioned: z11.boolean(),
1182
+ cited: z11.boolean(),
1067
1183
  describedAccurately: snapshotAccuracySchema,
1068
- accuracyNotes: z9.string().nullable().optional(),
1069
- incorrectClaims: z9.array(z9.string()).default([]),
1070
- recommendedCompetitors: z9.array(z9.string()).default([]),
1071
- citedDomains: z9.array(z9.string()).default([]),
1072
- groundingSources: z9.array(groundingSourceSchema).default([]),
1073
- searchQueries: z9.array(z9.string()).default([]),
1074
- answerText: z9.string(),
1075
- error: z9.string().nullable().optional()
1076
- });
1077
- var snapshotQueryResultSchema = z9.object({
1078
- query: z9.string(),
1079
- providerResults: z9.array(snapshotProviderResultSchema).default([])
1080
- });
1081
- var snapshotSummarySchema = z9.object({
1082
- totalQueries: z9.number().int().nonnegative(),
1083
- totalProviders: z9.number().int().nonnegative(),
1084
- totalComparisons: z9.number().int().nonnegative(),
1085
- mentionCount: z9.number().int().nonnegative(),
1086
- citationCount: z9.number().int().nonnegative(),
1087
- topCompetitors: z9.array(snapshotCompetitorEntrySchema).default([]),
1088
- visibilityGap: z9.string(),
1089
- whatThisMeans: z9.array(z9.string()).default([]),
1090
- recommendedActions: z9.array(z9.string()).default([])
1091
- });
1092
- var snapshotReportSchema = z9.object({
1093
- companyName: z9.string(),
1094
- domain: z9.string(),
1095
- homepageUrl: z9.string(),
1096
- generatedAt: z9.string(),
1097
- queries: z9.array(z9.string()).default([]),
1098
- competitors: z9.array(z9.string()).default([]),
1184
+ accuracyNotes: z11.string().nullable().optional(),
1185
+ incorrectClaims: z11.array(z11.string()).default([]),
1186
+ recommendedCompetitors: z11.array(z11.string()).default([]),
1187
+ citedDomains: z11.array(z11.string()).default([]),
1188
+ groundingSources: z11.array(groundingSourceSchema).default([]),
1189
+ searchQueries: z11.array(z11.string()).default([]),
1190
+ answerText: z11.string(),
1191
+ error: z11.string().nullable().optional()
1192
+ });
1193
+ var snapshotQueryResultSchema = z11.object({
1194
+ query: z11.string(),
1195
+ providerResults: z11.array(snapshotProviderResultSchema).default([])
1196
+ });
1197
+ var snapshotSummarySchema = z11.object({
1198
+ totalQueries: z11.number().int().nonnegative(),
1199
+ totalProviders: z11.number().int().nonnegative(),
1200
+ totalComparisons: z11.number().int().nonnegative(),
1201
+ mentionCount: z11.number().int().nonnegative(),
1202
+ citationCount: z11.number().int().nonnegative(),
1203
+ topCompetitors: z11.array(snapshotCompetitorEntrySchema).default([]),
1204
+ visibilityGap: z11.string(),
1205
+ whatThisMeans: z11.array(z11.string()).default([]),
1206
+ recommendedActions: z11.array(z11.string()).default([])
1207
+ });
1208
+ var snapshotReportSchema = z11.object({
1209
+ companyName: z11.string(),
1210
+ domain: z11.string(),
1211
+ homepageUrl: z11.string(),
1212
+ generatedAt: z11.string(),
1213
+ queries: z11.array(z11.string()).default([]),
1214
+ competitors: z11.array(z11.string()).default([]),
1099
1215
  profile: snapshotProfileSchema,
1100
1216
  audit: snapshotAuditSchema,
1101
- queryResults: z9.array(snapshotQueryResultSchema).default([]),
1217
+ queryResults: z11.array(snapshotQueryResultSchema).default([]),
1102
1218
  summary: snapshotSummarySchema
1103
1219
  });
1104
1220
 
1105
1221
  // ../contracts/src/schedule.ts
1106
- import { z as z10 } from "zod";
1107
- var schedulableRunKindSchema = z10.enum(["answer-visibility", "traffic-sync"]);
1222
+ import { z as z12 } from "zod";
1223
+ var schedulableRunKindSchema = z12.enum(["answer-visibility", "traffic-sync"]);
1108
1224
  var SchedulableRunKinds = schedulableRunKindSchema.enum;
1109
- var scheduleDtoSchema = z10.object({
1110
- id: z10.string(),
1111
- projectId: z10.string(),
1225
+ var scheduleDtoSchema = z12.object({
1226
+ id: z12.string(),
1227
+ projectId: z12.string(),
1112
1228
  /** Run kind dispatched when this schedule fires. Defaults to 'answer-visibility' for legacy rows. */
1113
1229
  kind: schedulableRunKindSchema,
1114
- cronExpr: z10.string(),
1115
- preset: z10.string().nullable().optional(),
1116
- timezone: z10.string().default("UTC"),
1117
- enabled: z10.boolean().default(true),
1118
- providers: z10.array(providerNameSchema).default([]),
1230
+ cronExpr: z12.string(),
1231
+ preset: z12.string().nullable().optional(),
1232
+ timezone: z12.string().default("UTC"),
1233
+ enabled: z12.boolean().default(true),
1234
+ providers: z12.array(providerNameSchema).default([]),
1119
1235
  /** Traffic-source UUID for `kind === 'traffic-sync'` schedules. Null otherwise. */
1120
- sourceId: z10.string().nullable().optional(),
1121
- lastRunAt: z10.string().nullable().optional(),
1122
- nextRunAt: z10.string().nullable().optional(),
1123
- createdAt: z10.string(),
1124
- updatedAt: z10.string()
1236
+ sourceId: z12.string().nullable().optional(),
1237
+ lastRunAt: z12.string().nullable().optional(),
1238
+ nextRunAt: z12.string().nullable().optional(),
1239
+ createdAt: z12.string(),
1240
+ updatedAt: z12.string()
1125
1241
  });
1126
- var scheduleUpsertRequestSchema = z10.object({
1242
+ var scheduleUpsertRequestSchema = z12.object({
1127
1243
  /** Run kind. Defaults to 'answer-visibility' so existing callers don't have to change. */
1128
1244
  kind: schedulableRunKindSchema.optional(),
1129
- preset: z10.string().optional(),
1130
- cron: z10.string().optional(),
1131
- timezone: z10.string().optional().default("UTC"),
1132
- enabled: z10.boolean().optional().default(true),
1133
- providers: z10.array(providerNameSchema).optional().default([]),
1245
+ preset: z12.string().optional(),
1246
+ cron: z12.string().optional(),
1247
+ timezone: z12.string().optional().default("UTC"),
1248
+ enabled: z12.boolean().optional().default(true),
1249
+ providers: z12.array(providerNameSchema).optional().default([]),
1134
1250
  /** Required when kind === 'traffic-sync'. Forbidden for other kinds. Validated server-side. */
1135
- sourceId: z10.string().optional()
1251
+ sourceId: z12.string().optional()
1136
1252
  }).refine(
1137
1253
  (data) => data.preset && !data.cron || !data.preset && data.cron,
1138
1254
  { message: 'Exactly one of "preset" or "cron" must be provided' }
1139
1255
  );
1140
1256
 
1141
1257
  // ../contracts/src/analytics.ts
1142
- import { z as z11 } from "zod";
1143
- var visibilityMetricModeSchema = z11.enum(["mentioned", "cited"]);
1258
+ import { z as z13 } from "zod";
1259
+ var visibilityMetricModeSchema = z13.enum(["mentioned", "cited"]);
1144
1260
  var VisibilityMetricModes = visibilityMetricModeSchema.enum;
1145
1261
  function parseWindow(value) {
1146
1262
  if (value === "7d" || value === "30d" || value === "90d" || value === "all") return value;
@@ -1279,29 +1395,29 @@ function categoryLabel(category) {
1279
1395
  }
1280
1396
 
1281
1397
  // ../contracts/src/ga.ts
1282
- import { z as z12 } from "zod";
1283
- var ga4ConnectionDtoSchema = z12.object({
1284
- id: z12.string(),
1285
- projectId: z12.string(),
1286
- propertyId: z12.string(),
1287
- clientEmail: z12.string(),
1288
- connected: z12.boolean(),
1289
- createdAt: z12.string(),
1290
- updatedAt: z12.string()
1398
+ import { z as z14 } from "zod";
1399
+ var ga4ConnectionDtoSchema = z14.object({
1400
+ id: z14.string(),
1401
+ projectId: z14.string(),
1402
+ propertyId: z14.string(),
1403
+ clientEmail: z14.string(),
1404
+ connected: z14.boolean(),
1405
+ createdAt: z14.string(),
1406
+ updatedAt: z14.string()
1291
1407
  });
1292
- var ga4TrafficSnapshotDtoSchema = z12.object({
1293
- date: z12.string(),
1294
- landingPage: z12.string(),
1295
- sessions: z12.number(),
1296
- organicSessions: z12.number(),
1297
- users: z12.number()
1298
- });
1299
- var ga4SourceDimensionSchema = z12.enum(["session", "first_user", "manual_utm"]);
1300
- var ga4AiReferralDtoSchema = z12.object({
1301
- source: z12.string(),
1302
- medium: z12.string(),
1303
- sessions: z12.number(),
1304
- users: z12.number(),
1408
+ var ga4TrafficSnapshotDtoSchema = z14.object({
1409
+ date: z14.string(),
1410
+ landingPage: z14.string(),
1411
+ sessions: z14.number(),
1412
+ organicSessions: z14.number(),
1413
+ users: z14.number()
1414
+ });
1415
+ var ga4SourceDimensionSchema = z14.enum(["session", "first_user", "manual_utm"]);
1416
+ var ga4AiReferralDtoSchema = z14.object({
1417
+ source: z14.string(),
1418
+ medium: z14.string(),
1419
+ sessions: z14.number(),
1420
+ users: z14.number(),
1305
1421
  /**
1306
1422
  * The winning attribution dimension for this (source, medium) tuple — the
1307
1423
  * one with the highest session count. GA4 emits one row per dimension
@@ -1311,121 +1427,144 @@ var ga4AiReferralDtoSchema = z12.object({
1311
1427
  */
1312
1428
  sourceDimension: ga4SourceDimensionSchema
1313
1429
  });
1314
- var ga4AiReferralLandingPageDtoSchema = z12.object({
1315
- source: z12.string(),
1316
- medium: z12.string(),
1430
+ var ga4AiReferralLandingPageDtoSchema = z14.object({
1431
+ source: z14.string(),
1432
+ medium: z14.string(),
1317
1433
  /**
1318
1434
  * The winning attribution dimension for this (source, medium, landingPage)
1319
1435
  * tuple — the one with the highest session count.
1320
1436
  */
1321
1437
  sourceDimension: ga4SourceDimensionSchema,
1322
- landingPage: z12.string(),
1323
- sessions: z12.number(),
1324
- users: z12.number()
1325
- });
1326
- var ga4SocialReferralDtoSchema = z12.object({
1327
- source: z12.string(),
1328
- medium: z12.string(),
1329
- sessions: z12.number(),
1330
- users: z12.number(),
1438
+ landingPage: z14.string(),
1439
+ sessions: z14.number(),
1440
+ users: z14.number()
1441
+ });
1442
+ var ga4SocialReferralDtoSchema = z14.object({
1443
+ source: z14.string(),
1444
+ medium: z14.string(),
1445
+ sessions: z14.number(),
1446
+ users: z14.number(),
1331
1447
  /** GA4 default channel group (e.g. 'Organic Social', 'Paid Social') */
1332
- channelGroup: z12.string()
1448
+ channelGroup: z14.string()
1333
1449
  });
1334
- var ga4ChannelBucketDtoSchema = z12.object({
1335
- sessions: z12.number(),
1336
- sharePct: z12.number(),
1337
- sharePctDisplay: z12.string()
1450
+ var ga4ChannelBucketDtoSchema = z14.object({
1451
+ sessions: z14.number(),
1452
+ sharePct: z14.number(),
1453
+ sharePctDisplay: z14.string()
1338
1454
  });
1339
- var ga4ChannelBreakdownDtoSchema = z12.object({
1455
+ var ga4ChannelBreakdownDtoSchema = z14.object({
1340
1456
  organic: ga4ChannelBucketDtoSchema,
1341
1457
  social: ga4ChannelBucketDtoSchema,
1342
1458
  direct: ga4ChannelBucketDtoSchema,
1343
1459
  ai: ga4ChannelBucketDtoSchema,
1344
1460
  other: ga4ChannelBucketDtoSchema
1345
1461
  });
1346
- var ga4TrafficSummaryDtoSchema = z12.object({
1347
- totalSessions: z12.number(),
1348
- totalOrganicSessions: z12.number(),
1462
+ var ga4TrafficSummaryDtoSchema = z14.object({
1463
+ totalSessions: z14.number(),
1464
+ totalOrganicSessions: z14.number(),
1349
1465
  /** 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. */
1350
- totalDirectSessions: z12.number(),
1351
- totalUsers: z12.number(),
1352
- topPages: z12.array(z12.object({
1353
- landingPage: z12.string(),
1354
- sessions: z12.number(),
1355
- organicSessions: z12.number(),
1466
+ totalDirectSessions: z14.number(),
1467
+ totalUsers: z14.number(),
1468
+ topPages: z14.array(z14.object({
1469
+ landingPage: z14.string(),
1470
+ sessions: z14.number(),
1471
+ organicSessions: z14.number(),
1356
1472
  /** Per-page Direct-channel sessions. 0 for legacy rows. */
1357
- directSessions: z12.number(),
1358
- users: z12.number()
1473
+ directSessions: z14.number(),
1474
+ users: z14.number()
1359
1475
  })),
1360
- aiReferrals: z12.array(ga4AiReferralDtoSchema),
1361
- aiReferralLandingPages: z12.array(ga4AiReferralLandingPageDtoSchema),
1476
+ aiReferrals: z14.array(ga4AiReferralDtoSchema),
1477
+ aiReferralLandingPages: z14.array(ga4AiReferralLandingPageDtoSchema),
1362
1478
  /** 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. */
1363
- aiSessionsDeduped: z12.number(),
1479
+ aiSessionsDeduped: z14.number(),
1364
1480
  /** Deduped AI user total: MAX(users) per date+source+medium across attribution dimensions, then summed. */
1365
- aiUsersDeduped: z12.number(),
1481
+ aiUsersDeduped: z14.number(),
1366
1482
  /** AI sessions whose CURRENT sessionSource matched an AI engine. Can overlap with raw Organic/Social/Direct totals; `channelBreakdown` removes those overlaps for display. */
1367
- aiSessionsBySession: z12.number(),
1483
+ aiSessionsBySession: z14.number(),
1368
1484
  /** AI users whose CURRENT sessionSource matched an AI engine. Can overlap with raw Organic/Social/Direct totals. */
1369
- aiUsersBySession: z12.number(),
1370
- socialReferrals: z12.array(ga4SocialReferralDtoSchema),
1485
+ aiUsersBySession: z14.number(),
1486
+ socialReferrals: z14.array(ga4SocialReferralDtoSchema),
1371
1487
  /** Total social sessions (session-scoped, no cross-dimension dedup needed). */
1372
- socialSessions: z12.number(),
1488
+ socialSessions: z14.number(),
1373
1489
  /** Total social users (session-scoped, no cross-dimension dedup needed). */
1374
- socialUsers: z12.number(),
1490
+ socialUsers: z14.number(),
1375
1491
  /** Five disjoint buckets used for the channel breakdown. Known AI session-source matches are removed from their native GA4 bucket before shares are computed. */
1376
1492
  channelBreakdown: ga4ChannelBreakdownDtoSchema,
1377
1493
  /** Organic sessions as a percentage of total sessions (0–100, rounded). */
1378
- organicSharePct: z12.number(),
1494
+ organicSharePct: z14.number(),
1379
1495
  /** Deduped AI sessions as a percentage of total sessions (0–100, rounded). Cross-cutting: can overlap with Direct/Organic/Social. */
1380
- aiSharePct: z12.number(),
1496
+ aiSharePct: z14.number(),
1381
1497
  /** Session-source-only AI sessions as a percentage of total sessions (0–100, rounded). Can overlap with raw Organic/Social/Direct totals. */
1382
- aiSharePctBySession: z12.number(),
1498
+ aiSharePctBySession: z14.number(),
1383
1499
  /** Direct-channel sessions as a percentage of total sessions (0–100, rounded). */
1384
- directSharePct: z12.number(),
1500
+ directSharePct: z14.number(),
1385
1501
  /** Social sessions as a percentage of total sessions (0–100, rounded). */
1386
- socialSharePct: z12.number(),
1502
+ socialSharePct: z14.number(),
1387
1503
  /** Display string for organicSharePct: 'X%', '<1%' for non-zero shares that round below 1, or '—' when sessions exist but total is unknown (partial sync). */
1388
- organicSharePctDisplay: z12.string(),
1504
+ organicSharePctDisplay: z14.string(),
1389
1505
  /** Display string for aiSharePct: 'X%', '<1%' for non-zero shares that round below 1, or '—' when sessions exist but total is unknown (partial sync). */
1390
- aiSharePctDisplay: z12.string(),
1506
+ aiSharePctDisplay: z14.string(),
1391
1507
  /** Display string for aiSharePctBySession: 'X%', '<1%' for non-zero shares that round below 1, or '—' when sessions exist but total is unknown (partial sync). */
1392
- aiSharePctBySessionDisplay: z12.string(),
1508
+ aiSharePctBySessionDisplay: z14.string(),
1393
1509
  /** Display string for directSharePct: 'X%', '<1%' for non-zero shares that round below 1, or '—' when sessions exist but total is unknown (partial sync). */
1394
- directSharePctDisplay: z12.string(),
1510
+ directSharePctDisplay: z14.string(),
1395
1511
  /** Display string for socialSharePct: 'X%', '<1%' for non-zero shares that round below 1, or '—' when sessions exist but total is unknown (partial sync). */
1396
- socialSharePctDisplay: z12.string(),
1512
+ socialSharePctDisplay: z14.string(),
1397
1513
  /** 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). */
1398
- otherSessions: z12.number(),
1514
+ otherSessions: z14.number(),
1399
1515
  /** Other sessions as a percentage of total sessions (0–100, rounded). */
1400
- otherSharePct: z12.number(),
1516
+ otherSharePct: z14.number(),
1401
1517
  /** Display string for otherSharePct: 'X%', '<1%' for non-zero shares that round below 1, or '—' when sessions exist but total is unknown (partial sync). */
1402
- otherSharePctDisplay: z12.string(),
1403
- lastSyncedAt: z12.string().nullable()
1404
- });
1405
- var ga4AiReferralHistoryEntrySchema = z12.object({
1406
- date: z12.string(),
1407
- source: z12.string(),
1408
- medium: z12.string(),
1409
- landingPage: z12.string(),
1410
- sessions: z12.number(),
1411
- users: z12.number(),
1518
+ otherSharePctDisplay: z14.string(),
1519
+ lastSyncedAt: z14.string().nullable()
1520
+ });
1521
+ var ga4StatusDtoSchema = z14.object({
1522
+ connected: z14.boolean(),
1523
+ propertyId: z14.string().nullable(),
1524
+ clientEmail: z14.string().nullable(),
1525
+ authMethod: z14.enum(["service-account", "oauth"]).nullable(),
1526
+ lastSyncedAt: z14.string().nullable(),
1527
+ createdAt: z14.string().nullable().optional(),
1528
+ updatedAt: z14.string().nullable().optional()
1529
+ });
1530
+ var ga4SyncResponseDtoSchema = z14.object({
1531
+ synced: z14.boolean(),
1532
+ rowCount: z14.number().int().nonnegative(),
1533
+ aiReferralCount: z14.number().int().nonnegative(),
1534
+ socialReferralCount: z14.number().int().nonnegative(),
1535
+ days: z14.number().int().nonnegative(),
1536
+ syncedAt: z14.string(),
1537
+ /**
1538
+ * Components that were written this run. Present when `only` is set.
1539
+ * Always includes `traffic` and `summary` (the share denominator) plus
1540
+ * the requested channel breakdown — `ai` and/or `social`.
1541
+ */
1542
+ syncedComponents: z14.array(z14.string()).optional()
1543
+ });
1544
+ var ga4AiReferralHistoryEntrySchema = z14.object({
1545
+ date: z14.string(),
1546
+ source: z14.string(),
1547
+ medium: z14.string(),
1548
+ landingPage: z14.string(),
1549
+ sessions: z14.number(),
1550
+ users: z14.number(),
1412
1551
  /** Which GA4 dimension this row came from: session (sessionSource), first_user (firstUserSource), or manual_utm (utm_source parameter) */
1413
1552
  sourceDimension: ga4SourceDimensionSchema
1414
1553
  });
1415
- var ga4SocialReferralHistoryEntrySchema = z12.object({
1416
- date: z12.string(),
1417
- source: z12.string(),
1418
- medium: z12.string(),
1419
- sessions: z12.number(),
1420
- users: z12.number(),
1554
+ var ga4SocialReferralHistoryEntrySchema = z14.object({
1555
+ date: z14.string(),
1556
+ source: z14.string(),
1557
+ medium: z14.string(),
1558
+ sessions: z14.number(),
1559
+ users: z14.number(),
1421
1560
  /** GA4 default channel group (e.g. 'Organic Social', 'Paid Social') */
1422
- channelGroup: z12.string()
1561
+ channelGroup: z14.string()
1423
1562
  });
1424
- var ga4SessionHistoryEntrySchema = z12.object({
1425
- date: z12.string(),
1426
- sessions: z12.number(),
1427
- organicSessions: z12.number(),
1428
- users: z12.number()
1563
+ var ga4SessionHistoryEntrySchema = z14.object({
1564
+ date: z14.string(),
1565
+ sessions: z14.number(),
1566
+ organicSessions: z14.number(),
1567
+ users: z14.number()
1429
1568
  });
1430
1569
 
1431
1570
  // ../contracts/src/answer-visibility.ts
@@ -1593,121 +1732,149 @@ function escapeRegExp(value) {
1593
1732
  }
1594
1733
 
1595
1734
  // ../contracts/src/agent.ts
1596
- import { z as z13 } from "zod";
1597
- var memorySourceSchema = z13.enum(["aero", "user", "compaction"]);
1735
+ import { z as z15 } from "zod";
1736
+ var agentProviderIdSchema = z15.enum(["claude", "openai", "gemini", "zai"]);
1737
+ var agentProviderOptionDtoSchema = z15.object({
1738
+ /** Stable identifier — what clients pass back as `provider` on the prompt endpoint. */
1739
+ id: agentProviderIdSchema,
1740
+ /** Human-readable label for UI pickers, e.g. "Anthropic (Claude)". */
1741
+ label: z15.string(),
1742
+ /** Default model if the caller doesn't pick one. */
1743
+ defaultModel: z15.string(),
1744
+ /** Whether a usable API key was found (config.yaml or provider env var). */
1745
+ configured: z15.boolean(),
1746
+ /**
1747
+ * Where the key resolved from, if any. `null` when `configured === false`.
1748
+ * Surfaced so the UI can nudge users toward their preferred source of truth.
1749
+ */
1750
+ keySource: z15.enum(["config", "env"]).nullable()
1751
+ });
1752
+ var agentProvidersResponseDtoSchema = z15.object({
1753
+ /**
1754
+ * Every provider Aero knows about. `configured === false` entries are
1755
+ * included so the UI can render them disabled with an onboarding hint.
1756
+ */
1757
+ providers: z15.array(agentProviderOptionDtoSchema).default([]),
1758
+ /**
1759
+ * Provider Aero auto-picks when no explicit override is passed. Null if
1760
+ * nothing is configured (install never exchanged a key).
1761
+ */
1762
+ defaultProvider: agentProviderIdSchema.nullable()
1763
+ });
1764
+ var memorySourceSchema = z15.enum(["aero", "user", "compaction"]);
1598
1765
  var MemorySources = memorySourceSchema.enum;
1599
1766
  var AGENT_MEMORY_VALUE_MAX_BYTES = 2 * 1024;
1600
1767
  var AGENT_MEMORY_KEY_MAX_LENGTH = 128;
1601
- var agentMemoryUpsertRequestSchema = z13.object({
1602
- key: z13.string().min(1).max(AGENT_MEMORY_KEY_MAX_LENGTH),
1603
- value: z13.string().min(1)
1768
+ var agentMemoryUpsertRequestSchema = z15.object({
1769
+ key: z15.string().min(1).max(AGENT_MEMORY_KEY_MAX_LENGTH),
1770
+ value: z15.string().min(1)
1604
1771
  });
1605
- var agentMemoryDeleteRequestSchema = z13.object({
1606
- key: z13.string().min(1).max(AGENT_MEMORY_KEY_MAX_LENGTH)
1772
+ var agentMemoryDeleteRequestSchema = z15.object({
1773
+ key: z15.string().min(1).max(AGENT_MEMORY_KEY_MAX_LENGTH)
1607
1774
  });
1608
1775
 
1609
1776
  // ../contracts/src/backlinks.ts
1610
- import { z as z14 } from "zod";
1611
- var ccReleaseSyncStatusSchema = z14.enum(["queued", "downloading", "querying", "ready", "failed"]);
1777
+ import { z as z16 } from "zod";
1778
+ var ccReleaseSyncStatusSchema = z16.enum(["queued", "downloading", "querying", "ready", "failed"]);
1612
1779
  var CcReleaseSyncStatuses = ccReleaseSyncStatusSchema.enum;
1613
- var ccReleaseSyncDtoSchema = z14.object({
1614
- id: z14.string(),
1615
- release: z14.string(),
1780
+ var ccReleaseSyncDtoSchema = z16.object({
1781
+ id: z16.string(),
1782
+ release: z16.string(),
1616
1783
  status: ccReleaseSyncStatusSchema,
1617
- phaseDetail: z14.string().nullable().optional(),
1618
- vertexPath: z14.string().nullable().optional(),
1619
- edgesPath: z14.string().nullable().optional(),
1620
- vertexSha256: z14.string().nullable().optional(),
1621
- edgesSha256: z14.string().nullable().optional(),
1622
- vertexBytes: z14.number().int().nullable().optional(),
1623
- edgesBytes: z14.number().int().nullable().optional(),
1624
- projectsProcessed: z14.number().int().nullable().optional(),
1625
- domainsDiscovered: z14.number().int().nullable().optional(),
1626
- downloadStartedAt: z14.string().nullable().optional(),
1627
- downloadFinishedAt: z14.string().nullable().optional(),
1628
- queryStartedAt: z14.string().nullable().optional(),
1629
- queryFinishedAt: z14.string().nullable().optional(),
1630
- error: z14.string().nullable().optional(),
1631
- createdAt: z14.string(),
1632
- updatedAt: z14.string()
1633
- });
1634
- var backlinkDomainDtoSchema = z14.object({
1635
- linkingDomain: z14.string(),
1636
- numHosts: z14.number().int()
1637
- });
1638
- var backlinkSummaryDtoSchema = z14.object({
1639
- projectId: z14.string(),
1640
- release: z14.string(),
1641
- targetDomain: z14.string(),
1642
- totalLinkingDomains: z14.number().int(),
1643
- totalHosts: z14.number().int(),
1644
- top10HostsShare: z14.string(),
1645
- queriedAt: z14.string(),
1784
+ phaseDetail: z16.string().nullable().optional(),
1785
+ vertexPath: z16.string().nullable().optional(),
1786
+ edgesPath: z16.string().nullable().optional(),
1787
+ vertexSha256: z16.string().nullable().optional(),
1788
+ edgesSha256: z16.string().nullable().optional(),
1789
+ vertexBytes: z16.number().int().nullable().optional(),
1790
+ edgesBytes: z16.number().int().nullable().optional(),
1791
+ projectsProcessed: z16.number().int().nullable().optional(),
1792
+ domainsDiscovered: z16.number().int().nullable().optional(),
1793
+ downloadStartedAt: z16.string().nullable().optional(),
1794
+ downloadFinishedAt: z16.string().nullable().optional(),
1795
+ queryStartedAt: z16.string().nullable().optional(),
1796
+ queryFinishedAt: z16.string().nullable().optional(),
1797
+ error: z16.string().nullable().optional(),
1798
+ createdAt: z16.string(),
1799
+ updatedAt: z16.string()
1800
+ });
1801
+ var backlinkDomainDtoSchema = z16.object({
1802
+ linkingDomain: z16.string(),
1803
+ numHosts: z16.number().int()
1804
+ });
1805
+ var backlinkSummaryDtoSchema = z16.object({
1806
+ projectId: z16.string(),
1807
+ release: z16.string(),
1808
+ targetDomain: z16.string(),
1809
+ totalLinkingDomains: z16.number().int(),
1810
+ totalHosts: z16.number().int(),
1811
+ top10HostsShare: z16.string(),
1812
+ queriedAt: z16.string(),
1646
1813
  // Populated when the response is filtered (e.g. ?excludeCrawlers=1).
1647
1814
  // Counts the rows omitted from totalLinkingDomains/totalHosts so callers
1648
1815
  // can show "N hidden" hints without re-deriving them.
1649
- excludedLinkingDomains: z14.number().int().optional(),
1650
- excludedHosts: z14.number().int().optional()
1816
+ excludedLinkingDomains: z16.number().int().optional(),
1817
+ excludedHosts: z16.number().int().optional()
1651
1818
  });
1652
- var backlinkListResponseSchema = z14.object({
1819
+ var backlinkListResponseSchema = z16.object({
1653
1820
  summary: backlinkSummaryDtoSchema.nullable(),
1654
- total: z14.number().int(),
1655
- rows: z14.array(backlinkDomainDtoSchema)
1656
- });
1657
- var backlinkHistoryEntrySchema = z14.object({
1658
- release: z14.string(),
1659
- totalLinkingDomains: z14.number().int(),
1660
- totalHosts: z14.number().int(),
1661
- top10HostsShare: z14.string(),
1662
- queriedAt: z14.string()
1663
- });
1664
- var backlinksInstallStatusDtoSchema = z14.object({
1665
- duckdbInstalled: z14.boolean(),
1666
- duckdbVersion: z14.string().nullable().optional(),
1667
- duckdbSpec: z14.string(),
1668
- pluginDir: z14.string()
1669
- });
1670
- var backlinksInstallResultDtoSchema = z14.object({
1671
- installed: z14.boolean(),
1672
- version: z14.string(),
1673
- path: z14.string(),
1674
- alreadyPresent: z14.boolean()
1675
- });
1676
- var ccAvailableReleaseSchema = z14.object({
1677
- release: z14.string(),
1678
- vertexUrl: z14.string(),
1679
- edgesUrl: z14.string(),
1680
- vertexBytes: z14.number().int().nullable(),
1681
- edgesBytes: z14.number().int().nullable(),
1682
- lastModified: z14.string().nullable()
1683
- });
1684
- var ccCachedReleaseSchema = z14.object({
1685
- release: z14.string(),
1821
+ total: z16.number().int(),
1822
+ rows: z16.array(backlinkDomainDtoSchema)
1823
+ });
1824
+ var backlinkHistoryEntrySchema = z16.object({
1825
+ release: z16.string(),
1826
+ totalLinkingDomains: z16.number().int(),
1827
+ totalHosts: z16.number().int(),
1828
+ top10HostsShare: z16.string(),
1829
+ queriedAt: z16.string()
1830
+ });
1831
+ var backlinksInstallStatusDtoSchema = z16.object({
1832
+ duckdbInstalled: z16.boolean(),
1833
+ duckdbVersion: z16.string().nullable().optional(),
1834
+ duckdbSpec: z16.string(),
1835
+ pluginDir: z16.string()
1836
+ });
1837
+ var backlinksInstallResultDtoSchema = z16.object({
1838
+ installed: z16.boolean(),
1839
+ version: z16.string(),
1840
+ path: z16.string(),
1841
+ alreadyPresent: z16.boolean()
1842
+ });
1843
+ var ccAvailableReleaseSchema = z16.object({
1844
+ release: z16.string(),
1845
+ vertexUrl: z16.string(),
1846
+ edgesUrl: z16.string(),
1847
+ vertexBytes: z16.number().int().nullable(),
1848
+ edgesBytes: z16.number().int().nullable(),
1849
+ lastModified: z16.string().nullable()
1850
+ });
1851
+ var ccCachedReleaseSchema = z16.object({
1852
+ release: z16.string(),
1686
1853
  syncStatus: ccReleaseSyncStatusSchema.nullable(),
1687
- bytes: z14.number().int(),
1688
- lastUsedAt: z14.string().nullable()
1854
+ bytes: z16.number().int(),
1855
+ lastUsedAt: z16.string().nullable()
1689
1856
  });
1690
1857
 
1691
1858
  // ../contracts/src/composites.ts
1692
- import { z as z15 } from "zod";
1693
- var searchHitKindSchema = z15.enum(["snapshot", "insight"]);
1694
- var projectSearchSnapshotHitSchema = z15.object({
1695
- kind: z15.literal("snapshot"),
1696
- id: z15.string(),
1697
- runId: z15.string(),
1698
- query: z15.string(),
1699
- provider: z15.string(),
1700
- model: z15.string().nullable(),
1859
+ import { z as z17 } from "zod";
1860
+ var searchHitKindSchema = z17.enum(["snapshot", "insight"]);
1861
+ var projectSearchSnapshotHitSchema = z17.object({
1862
+ kind: z17.literal("snapshot"),
1863
+ id: z17.string(),
1864
+ runId: z17.string(),
1865
+ query: z17.string(),
1866
+ provider: z17.string(),
1867
+ model: z17.string().nullable(),
1701
1868
  citationState: citationStateSchema,
1702
- matchedField: z15.enum(["answerText", "citedDomains", "searchQueries", "query"]),
1703
- snippet: z15.string(),
1704
- createdAt: z15.string()
1705
- });
1706
- var projectSearchInsightHitSchema = z15.object({
1707
- kind: z15.literal("insight"),
1708
- id: z15.string(),
1709
- runId: z15.string().nullable(),
1710
- type: z15.enum([
1869
+ matchedField: z17.enum(["answerText", "citedDomains", "searchQueries", "query"]),
1870
+ snippet: z17.string(),
1871
+ createdAt: z17.string()
1872
+ });
1873
+ var projectSearchInsightHitSchema = z17.object({
1874
+ kind: z17.literal("insight"),
1875
+ id: z17.string(),
1876
+ runId: z17.string().nullable(),
1877
+ type: z17.enum([
1711
1878
  "regression",
1712
1879
  "gain",
1713
1880
  "opportunity",
@@ -1717,29 +1884,29 @@ var projectSearchInsightHitSchema = z15.object({
1717
1884
  "competitor-gained",
1718
1885
  "competitor-lost"
1719
1886
  ]),
1720
- severity: z15.enum(["critical", "high", "medium", "low"]),
1721
- title: z15.string(),
1722
- query: z15.string(),
1723
- provider: z15.string(),
1724
- matchedField: z15.enum(["title", "query", "recommendation", "cause"]),
1725
- snippet: z15.string(),
1726
- dismissed: z15.boolean(),
1727
- createdAt: z15.string()
1728
- });
1729
- var projectSearchHitSchema = z15.discriminatedUnion("kind", [
1887
+ severity: z17.enum(["critical", "high", "medium", "low"]),
1888
+ title: z17.string(),
1889
+ query: z17.string(),
1890
+ provider: z17.string(),
1891
+ matchedField: z17.enum(["title", "query", "recommendation", "cause"]),
1892
+ snippet: z17.string(),
1893
+ dismissed: z17.boolean(),
1894
+ createdAt: z17.string()
1895
+ });
1896
+ var projectSearchHitSchema = z17.discriminatedUnion("kind", [
1730
1897
  projectSearchSnapshotHitSchema,
1731
1898
  projectSearchInsightHitSchema
1732
1899
  ]);
1733
- var projectSearchResponseSchema = z15.object({
1734
- query: z15.string(),
1735
- totalHits: z15.number().int().nonnegative(),
1736
- truncated: z15.boolean(),
1737
- hits: z15.array(projectSearchHitSchema)
1900
+ var projectSearchResponseSchema = z17.object({
1901
+ query: z17.string(),
1902
+ totalHits: z17.number().int().nonnegative(),
1903
+ truncated: z17.boolean(),
1904
+ hits: z17.array(projectSearchHitSchema)
1738
1905
  });
1739
1906
 
1740
1907
  // ../contracts/src/content.ts
1741
- import { z as z16 } from "zod";
1742
- var contentActionSchema = z16.enum(["create", "expand", "refresh", "add-schema"]);
1908
+ import { z as z18 } from "zod";
1909
+ var contentActionSchema = z18.enum(["create", "expand", "refresh", "add-schema"]);
1743
1910
  var ContentActions = contentActionSchema.enum;
1744
1911
  function contentActionLabel(action) {
1745
1912
  switch (action) {
@@ -1753,9 +1920,9 @@ function contentActionLabel(action) {
1753
1920
  return "Add schema";
1754
1921
  }
1755
1922
  }
1756
- var demandSourceSchema = z16.enum(["gsc", "competitor-evidence", "both"]);
1923
+ var demandSourceSchema = z18.enum(["gsc", "competitor-evidence", "both"]);
1757
1924
  var DemandSources = demandSourceSchema.enum;
1758
- var actionConfidenceSchema = z16.enum(["high", "medium", "low"]);
1925
+ var actionConfidenceSchema = z18.enum(["high", "medium", "low"]);
1759
1926
  var ActionConfidences = actionConfidenceSchema.enum;
1760
1927
  function actionConfidenceLabel(confidence) {
1761
1928
  switch (confidence) {
@@ -1767,7 +1934,7 @@ function actionConfidenceLabel(confidence) {
1767
1934
  return "Low";
1768
1935
  }
1769
1936
  }
1770
- var pageTypeSchema = z16.enum([
1937
+ var pageTypeSchema = z18.enum([
1771
1938
  "blog-post",
1772
1939
  "comparison",
1773
1940
  "listicle",
@@ -1776,7 +1943,7 @@ var pageTypeSchema = z16.enum([
1776
1943
  "glossary"
1777
1944
  ]);
1778
1945
  var PageTypes = pageTypeSchema.enum;
1779
- var contentActionStateSchema = z16.enum([
1946
+ var contentActionStateSchema = z18.enum([
1780
1947
  "proposed",
1781
1948
  "briefed",
1782
1949
  "payload-generated",
@@ -1786,88 +1953,88 @@ var contentActionStateSchema = z16.enum([
1786
1953
  "dismissed"
1787
1954
  ]);
1788
1955
  var ContentActionStates = contentActionStateSchema.enum;
1789
- var ourBestPageSchema = z16.object({
1790
- url: z16.string(),
1791
- gscImpressions: z16.number().nonnegative(),
1792
- gscClicks: z16.number().nonnegative(),
1956
+ var ourBestPageSchema = z18.object({
1957
+ url: z18.string(),
1958
+ gscImpressions: z18.number().nonnegative(),
1959
+ gscClicks: z18.number().nonnegative(),
1793
1960
  // Null when the page came from the inventory fallback (no GSC ranking data).
1794
- gscAvgPosition: z16.number().nonnegative().nullable(),
1795
- organicSessions: z16.number().nonnegative()
1796
- });
1797
- var winningCompetitorSchema = z16.object({
1798
- domain: z16.string(),
1799
- url: z16.string(),
1800
- title: z16.string(),
1801
- citationCount: z16.number().int().nonnegative()
1802
- });
1803
- var scoreBreakdownSchema = z16.object({
1804
- demand: z16.number(),
1805
- competitor: z16.number(),
1806
- absence: z16.number(),
1807
- gapSeverity: z16.number()
1808
- });
1809
- var existingActionRefSchema = z16.object({
1810
- actionId: z16.string(),
1961
+ gscAvgPosition: z18.number().nonnegative().nullable(),
1962
+ organicSessions: z18.number().nonnegative()
1963
+ });
1964
+ var winningCompetitorSchema = z18.object({
1965
+ domain: z18.string(),
1966
+ url: z18.string(),
1967
+ title: z18.string(),
1968
+ citationCount: z18.number().int().nonnegative()
1969
+ });
1970
+ var scoreBreakdownSchema = z18.object({
1971
+ demand: z18.number(),
1972
+ competitor: z18.number(),
1973
+ absence: z18.number(),
1974
+ gapSeverity: z18.number()
1975
+ });
1976
+ var existingActionRefSchema = z18.object({
1977
+ actionId: z18.string(),
1811
1978
  state: contentActionStateSchema,
1812
- lastUpdated: z16.string()
1979
+ lastUpdated: z18.string()
1813
1980
  });
1814
- var contentTargetRowDtoSchema = z16.object({
1815
- targetRef: z16.string(),
1816
- query: z16.string(),
1981
+ var contentTargetRowDtoSchema = z18.object({
1982
+ targetRef: z18.string(),
1983
+ query: z18.string(),
1817
1984
  action: contentActionSchema,
1818
1985
  ourBestPage: ourBestPageSchema.nullable(),
1819
1986
  winningCompetitor: winningCompetitorSchema.nullable(),
1820
- score: z16.number(),
1987
+ score: z18.number(),
1821
1988
  scoreBreakdown: scoreBreakdownSchema,
1822
- drivers: z16.array(z16.string()),
1989
+ drivers: z18.array(z18.string()),
1823
1990
  demandSource: demandSourceSchema,
1824
1991
  actionConfidence: actionConfidenceSchema,
1825
1992
  existingAction: existingActionRefSchema.nullable()
1826
1993
  });
1827
- var contentTargetsResponseDtoSchema = z16.object({
1828
- targets: z16.array(contentTargetRowDtoSchema),
1829
- contextMetrics: z16.object({
1830
- totalAiReferralSessions: z16.number().int().nonnegative(),
1831
- latestRunId: z16.string(),
1832
- runTimestamp: z16.string()
1994
+ var contentTargetsResponseDtoSchema = z18.object({
1995
+ targets: z18.array(contentTargetRowDtoSchema),
1996
+ contextMetrics: z18.object({
1997
+ totalAiReferralSessions: z18.number().int().nonnegative(),
1998
+ latestRunId: z18.string(),
1999
+ runTimestamp: z18.string()
1833
2000
  })
1834
2001
  });
1835
- var contentGroundingSourceSchema = z16.object({
1836
- uri: z16.string(),
1837
- title: z16.string(),
1838
- domain: z16.string(),
1839
- isOurDomain: z16.boolean(),
1840
- isCompetitor: z16.boolean(),
1841
- citationCount: z16.number().int().nonnegative(),
1842
- providers: z16.array(providerNameSchema)
1843
- });
1844
- var contentSourceRowDtoSchema = z16.object({
1845
- query: z16.string(),
1846
- groundingSources: z16.array(contentGroundingSourceSchema)
1847
- });
1848
- var contentSourcesResponseDtoSchema = z16.object({
1849
- sources: z16.array(contentSourceRowDtoSchema),
1850
- latestRunId: z16.string()
1851
- });
1852
- var contentGapRowDtoSchema = z16.object({
1853
- query: z16.string(),
1854
- competitorDomains: z16.array(z16.string()),
1855
- competitorCount: z16.number().int().nonnegative(),
1856
- missRate: z16.number().min(0).max(1),
1857
- lastSeenInRunId: z16.string()
1858
- });
1859
- var contentGapsResponseDtoSchema = z16.object({
1860
- gaps: z16.array(contentGapRowDtoSchema),
1861
- latestRunId: z16.string()
2002
+ var contentGroundingSourceSchema = z18.object({
2003
+ uri: z18.string(),
2004
+ title: z18.string(),
2005
+ domain: z18.string(),
2006
+ isOurDomain: z18.boolean(),
2007
+ isCompetitor: z18.boolean(),
2008
+ citationCount: z18.number().int().nonnegative(),
2009
+ providers: z18.array(providerNameSchema)
2010
+ });
2011
+ var contentSourceRowDtoSchema = z18.object({
2012
+ query: z18.string(),
2013
+ groundingSources: z18.array(contentGroundingSourceSchema)
2014
+ });
2015
+ var contentSourcesResponseDtoSchema = z18.object({
2016
+ sources: z18.array(contentSourceRowDtoSchema),
2017
+ latestRunId: z18.string()
2018
+ });
2019
+ var contentGapRowDtoSchema = z18.object({
2020
+ query: z18.string(),
2021
+ competitorDomains: z18.array(z18.string()),
2022
+ competitorCount: z18.number().int().nonnegative(),
2023
+ missRate: z18.number().min(0).max(1),
2024
+ lastSeenInRunId: z18.string()
2025
+ });
2026
+ var contentGapsResponseDtoSchema = z18.object({
2027
+ gaps: z18.array(contentGapRowDtoSchema),
2028
+ latestRunId: z18.string()
1862
2029
  });
1863
2030
 
1864
2031
  // ../contracts/src/doctor.ts
1865
- import { z as z17 } from "zod";
1866
- var checkStatusSchema = z17.enum(["ok", "warn", "fail", "skipped"]);
2032
+ import { z as z19 } from "zod";
2033
+ var checkStatusSchema = z19.enum(["ok", "warn", "fail", "skipped"]);
1867
2034
  var CheckStatuses = checkStatusSchema.enum;
1868
- var checkScopeSchema = z17.enum(["global", "project"]);
2035
+ var checkScopeSchema = z19.enum(["global", "project"]);
1869
2036
  var CheckScopes = checkScopeSchema.enum;
1870
- var checkCategorySchema = z17.enum([
2037
+ var checkCategorySchema = z19.enum([
1871
2038
  "auth",
1872
2039
  "config",
1873
2040
  "providers",
@@ -1878,31 +2045,31 @@ var checkCategorySchema = z17.enum([
1878
2045
  "agent"
1879
2046
  ]);
1880
2047
  var CheckCategories = checkCategorySchema.enum;
1881
- var checkResultSchema = z17.object({
1882
- id: z17.string(),
2048
+ var checkResultSchema = z19.object({
2049
+ id: z19.string(),
1883
2050
  category: checkCategorySchema,
1884
2051
  scope: checkScopeSchema,
1885
- title: z17.string(),
2052
+ title: z19.string(),
1886
2053
  status: checkStatusSchema,
1887
- code: z17.string().describe('Stable machine-readable code (e.g. "google.token.refresh-failed"). Use this for filtering and remediation logic.'),
1888
- summary: z17.string(),
1889
- remediation: z17.string().nullable().optional().describe('Operator-facing next step. Null when status is "ok" or no specific remediation applies.'),
1890
- details: z17.record(z17.string(), z17.unknown()).optional().describe("Structured context \u2014 principal email, redirect URI, missing scopes, etc. Stable per check id."),
1891
- durationMs: z17.number().int().nonnegative().describe("How long the check took to execute.")
2054
+ code: z19.string().describe('Stable machine-readable code (e.g. "google.token.refresh-failed"). Use this for filtering and remediation logic.'),
2055
+ summary: z19.string(),
2056
+ remediation: z19.string().nullable().optional().describe('Operator-facing next step. Null when status is "ok" or no specific remediation applies.'),
2057
+ details: z19.record(z19.string(), z19.unknown()).optional().describe("Structured context \u2014 principal email, redirect URI, missing scopes, etc. Stable per check id."),
2058
+ durationMs: z19.number().int().nonnegative().describe("How long the check took to execute.")
1892
2059
  });
1893
- var doctorReportSchema = z17.object({
2060
+ var doctorReportSchema = z19.object({
1894
2061
  scope: checkScopeSchema,
1895
- project: z17.string().nullable().describe('Project name when scope is "project", null otherwise.'),
1896
- generatedAt: z17.string().describe("ISO-8601 timestamp when this doctor run started."),
1897
- durationMs: z17.number().int().nonnegative(),
1898
- summary: z17.object({
1899
- total: z17.number().int().nonnegative(),
1900
- ok: z17.number().int().nonnegative(),
1901
- warn: z17.number().int().nonnegative(),
1902
- fail: z17.number().int().nonnegative(),
1903
- skipped: z17.number().int().nonnegative()
2062
+ project: z19.string().nullable().describe('Project name when scope is "project", null otherwise.'),
2063
+ generatedAt: z19.string().describe("ISO-8601 timestamp when this doctor run started."),
2064
+ durationMs: z19.number().int().nonnegative(),
2065
+ summary: z19.object({
2066
+ total: z19.number().int().nonnegative(),
2067
+ ok: z19.number().int().nonnegative(),
2068
+ warn: z19.number().int().nonnegative(),
2069
+ fail: z19.number().int().nonnegative(),
2070
+ skipped: z19.number().int().nonnegative()
1904
2071
  }),
1905
- checks: z17.array(checkResultSchema)
2072
+ checks: z19.array(checkResultSchema)
1906
2073
  });
1907
2074
  function summarizeCheckResults(results) {
1908
2075
  const summary = { total: results.length, ok: 0, warn: 0, fail: 0, skipped: 0 };
@@ -2048,52 +2215,52 @@ function normalizeUrlPath(input) {
2048
2215
  }
2049
2216
 
2050
2217
  // ../contracts/src/citations.ts
2051
- import { z as z18 } from "zod";
2052
- var citationCoverageProviderSchema = z18.object({
2053
- provider: z18.string(),
2218
+ import { z as z20 } from "zod";
2219
+ var citationCoverageProviderSchema = z20.object({
2220
+ provider: z20.string(),
2054
2221
  citationState: citationStateSchema,
2055
- cited: z18.boolean(),
2056
- mentioned: z18.boolean(),
2057
- runId: z18.string(),
2058
- runCreatedAt: z18.string()
2059
- });
2060
- var citationCoverageRowSchema = z18.object({
2061
- queryId: z18.string(),
2062
- query: z18.string(),
2063
- providers: z18.array(citationCoverageProviderSchema),
2064
- citedCount: z18.number().int().nonnegative(),
2065
- mentionedCount: z18.number().int().nonnegative(),
2066
- totalProviders: z18.number().int().nonnegative()
2222
+ cited: z20.boolean(),
2223
+ mentioned: z20.boolean(),
2224
+ runId: z20.string(),
2225
+ runCreatedAt: z20.string()
2226
+ });
2227
+ var citationCoverageRowSchema = z20.object({
2228
+ queryId: z20.string(),
2229
+ query: z20.string(),
2230
+ providers: z20.array(citationCoverageProviderSchema),
2231
+ citedCount: z20.number().int().nonnegative(),
2232
+ mentionedCount: z20.number().int().nonnegative(),
2233
+ totalProviders: z20.number().int().nonnegative()
2234
+ });
2235
+ var competitorGapRowSchema = z20.object({
2236
+ queryId: z20.string(),
2237
+ query: z20.string(),
2238
+ provider: z20.string(),
2239
+ citingCompetitors: z20.array(z20.string()),
2240
+ runId: z20.string(),
2241
+ runCreatedAt: z20.string()
2067
2242
  });
2068
- var competitorGapRowSchema = z18.object({
2069
- queryId: z18.string(),
2070
- query: z18.string(),
2071
- provider: z18.string(),
2072
- citingCompetitors: z18.array(z18.string()),
2073
- runId: z18.string(),
2074
- runCreatedAt: z18.string()
2075
- });
2076
- var citationVisibilitySummarySchema = z18.object({
2077
- providersConfigured: z18.number().int().nonnegative(),
2078
- providersCiting: z18.number().int().nonnegative(),
2079
- providersMentioning: z18.number().int().nonnegative(),
2080
- totalQueries: z18.number().int().nonnegative(),
2243
+ var citationVisibilitySummarySchema = z20.object({
2244
+ providersConfigured: z20.number().int().nonnegative(),
2245
+ providersCiting: z20.number().int().nonnegative(),
2246
+ providersMentioning: z20.number().int().nonnegative(),
2247
+ totalQueries: z20.number().int().nonnegative(),
2081
2248
  // Cross-tab buckets — each tracked query with at least one snapshot lands
2082
2249
  // in exactly one of these. Queries with zero snapshots are not counted in
2083
2250
  // any bucket; (sum of buckets) ≤ totalQueries.
2084
- queriesCitedAndMentioned: z18.number().int().nonnegative(),
2085
- queriesCitedOnly: z18.number().int().nonnegative(),
2086
- queriesMentionedOnly: z18.number().int().nonnegative(),
2087
- queriesInvisible: z18.number().int().nonnegative(),
2088
- latestRunId: z18.string().nullable(),
2089
- latestRunAt: z18.string().nullable()
2090
- });
2091
- var citationVisibilityResponseSchema = z18.object({
2251
+ queriesCitedAndMentioned: z20.number().int().nonnegative(),
2252
+ queriesCitedOnly: z20.number().int().nonnegative(),
2253
+ queriesMentionedOnly: z20.number().int().nonnegative(),
2254
+ queriesInvisible: z20.number().int().nonnegative(),
2255
+ latestRunId: z20.string().nullable(),
2256
+ latestRunAt: z20.string().nullable()
2257
+ });
2258
+ var citationVisibilityResponseSchema = z20.object({
2092
2259
  summary: citationVisibilitySummarySchema,
2093
- byQuery: z18.array(citationCoverageRowSchema),
2094
- competitorGaps: z18.array(competitorGapRowSchema),
2095
- status: z18.enum(["ready", "no-data"]),
2096
- reason: z18.enum(["no-runs-yet", "no-queries"]).optional()
2260
+ byQuery: z20.array(citationCoverageRowSchema),
2261
+ competitorGaps: z20.array(competitorGapRowSchema),
2262
+ status: z20.enum(["ready", "no-data"]),
2263
+ reason: z20.enum(["no-runs-yet", "no-queries"]).optional()
2097
2264
  });
2098
2265
  function emptyCitationVisibility(reason) {
2099
2266
  return {
@@ -2120,6 +2287,546 @@ function citationStateToCited(state) {
2120
2287
  }
2121
2288
 
2122
2289
  // ../contracts/src/report.ts
2290
+ import { z as z21 } from "zod";
2291
+ var providerLocationTreatmentSchema = z21.enum([
2292
+ "prompt",
2293
+ "request-param",
2294
+ "browser-geo",
2295
+ "ignored"
2296
+ ]);
2297
+ var reportMetaLocationSchema = z21.object({
2298
+ /** Human-readable label as configured on the project (e.g. "michigan"). */
2299
+ label: z21.string(),
2300
+ /** Resolved city/region/country from the project's `LocationContext`. */
2301
+ city: z21.string(),
2302
+ region: z21.string(),
2303
+ country: z21.string(),
2304
+ /**
2305
+ * Other locations configured on the project that did NOT power this report.
2306
+ * When non-empty, callers should make clear that the report is location-scoped:
2307
+ * a separate sweep is needed to see how AI engines respond from each one.
2308
+ */
2309
+ otherConfiguredLabels: z21.array(z21.string())
2310
+ });
2311
+ var reportProviderLocationHandlingSchema = z21.object({
2312
+ /** Provider name (matches `query_snapshots.provider`). */
2313
+ provider: z21.string(),
2314
+ /** How this provider applied the configured location during this run. */
2315
+ treatment: providerLocationTreatmentSchema,
2316
+ /** One-sentence explanation suitable for the report. */
2317
+ description: z21.string()
2318
+ });
2319
+ var reportMetaSchema = z21.object({
2320
+ /** ISO timestamp the report was generated (server clock). */
2321
+ generatedAt: z21.string(),
2322
+ /** Project the report covers. */
2323
+ project: z21.object({
2324
+ id: z21.string(),
2325
+ name: z21.string(),
2326
+ displayName: z21.string(),
2327
+ canonicalDomain: z21.string(),
2328
+ country: z21.string(),
2329
+ language: z21.string()
2330
+ }),
2331
+ /**
2332
+ * The location that powered the latest visibility run, when one was set.
2333
+ * `null` means the run had no location attached — providers received the
2334
+ * query verbatim with no geographic hint.
2335
+ */
2336
+ location: reportMetaLocationSchema.nullable(),
2337
+ /**
2338
+ * Per-provider location handling for the providers that ran in the latest
2339
+ * visibility sweep. Empty when there were no providers (or no run). Use
2340
+ * this to tell the reader whether the configured location actually shaped
2341
+ * each provider's answer — some providers append it to the prompt, some
2342
+ * pass it as a structured request field, and some (CDP) ignore it.
2343
+ */
2344
+ providerLocationHandling: z21.array(reportProviderLocationHandlingSchema),
2345
+ /** Earliest data point referenced by the report (ISO date). */
2346
+ periodStart: z21.string().nullable(),
2347
+ /** Latest data point referenced by the report (ISO date). */
2348
+ periodEnd: z21.string().nullable()
2349
+ });
2350
+ var reportExecutiveSummarySchema = z21.object({
2351
+ /**
2352
+ * 0..100 — share of tracked queries that were cited by at least one
2353
+ * provider in the latest run. "Cited" means the project's domain appeared
2354
+ * in the source list / grounding the AI used to answer. Computed per-query
2355
+ * (not per-(query × provider)) so the rate is invariant to provider count.
2356
+ */
2357
+ citationRate: z21.number(),
2358
+ /** Numerator of `citationRate` — distinct tracked queries cited by ≥1 provider in the latest run. */
2359
+ citedQueryCount: z21.number(),
2360
+ /** Denominator of `citationRate` — total tracked queries. */
2361
+ totalQueryCount: z21.number(),
2362
+ /**
2363
+ * 0..100 — share of tracked queries where the project's brand or domain
2364
+ * appeared in at least one provider's answer text in the latest run.
2365
+ * "Mentioned" is independent from "cited": a model can mention you in
2366
+ * the prose without citing your domain in its sources, and vice versa.
2367
+ * Same per-query denominator as `citationRate` for consistency.
2368
+ */
2369
+ mentionRate: z21.number(),
2370
+ /** Numerator of `mentionRate` — distinct tracked queries mentioned in ≥1 provider's answer text. */
2371
+ mentionedQueryCount: z21.number(),
2372
+ /** Compared to the previous run: 'up' | 'down' | 'flat' | 'unknown' (no prior run). */
2373
+ trend: z21.enum(["up", "down", "flat", "unknown"]),
2374
+ /** Total tracked queries. */
2375
+ queryCount: z21.number(),
2376
+ /** Total tracked competitors. */
2377
+ competitorCount: z21.number(),
2378
+ /** Number of providers in the latest run. */
2379
+ providerCount: z21.number(),
2380
+ /** GSC totals across the most-recent sync window. Null when GSC is not connected. */
2381
+ gsc: z21.object({
2382
+ clicks: z21.number(),
2383
+ impressions: z21.number(),
2384
+ ctr: z21.number(),
2385
+ avgPosition: z21.number(),
2386
+ periodStart: z21.string(),
2387
+ periodEnd: z21.string()
2388
+ }).nullable(),
2389
+ /** GA4 totals across the most-recent sync period. Null when GA4 is not connected. */
2390
+ ga: z21.object({
2391
+ sessions: z21.number(),
2392
+ users: z21.number(),
2393
+ periodStart: z21.string(),
2394
+ periodEnd: z21.string()
2395
+ }).nullable(),
2396
+ /** Top 3-5 findings, each rendered as a single-sentence narrative. */
2397
+ findings: z21.array(z21.object({
2398
+ title: z21.string(),
2399
+ detail: z21.string(),
2400
+ tone: z21.enum(["positive", "caution", "negative", "neutral"])
2401
+ }))
2402
+ });
2403
+ var citationCellSchema = z21.object({
2404
+ citationState: z21.enum(["cited", "not-cited", "pending"]),
2405
+ answerMentioned: z21.boolean().nullable(),
2406
+ model: z21.string().nullable()
2407
+ });
2408
+ var citationScorecardSchema = z21.object({
2409
+ queries: z21.array(z21.string()),
2410
+ providers: z21.array(z21.string()),
2411
+ /** matrix[queryIndex][providerIndex] — null when no snapshot exists for the pair. */
2412
+ matrix: z21.array(z21.array(citationCellSchema.nullable())),
2413
+ /** Per-provider citation rate (0..100). */
2414
+ providerRates: z21.array(z21.object({
2415
+ provider: z21.string(),
2416
+ citedCount: z21.number(),
2417
+ totalCount: z21.number(),
2418
+ citationRate: z21.number()
2419
+ }))
2420
+ });
2421
+ var competitorRowSchema = z21.object({
2422
+ domain: z21.string(),
2423
+ /** Number of (query × provider) pairs that cited this competitor. */
2424
+ citationCount: z21.number(),
2425
+ /** Out-of count for the same denominator. */
2426
+ totalCount: z21.number(),
2427
+ /** 'High' | 'Moderate' | 'Low' | 'None' — from buildPortfolioProject pressure logic. */
2428
+ pressureLabel: z21.enum(["High", "Moderate", "Low", "None"]),
2429
+ /** Distinct queries on which this competitor was cited. */
2430
+ citedQueries: z21.array(z21.string()),
2431
+ /**
2432
+ * Citation share 0..100. Numerator = this competitor's `citationCount`.
2433
+ * Denominator = sum of `citationCount` across all competitors plus the
2434
+ * project's own `projectCitationCount`. Equals 0 when there are no cited
2435
+ * slots in the snapshot. Distinct from the project-level Mention Share
2436
+ * gauge — that one is brand-in-answer-text, this one is domain-in-source-list.
2437
+ */
2438
+ sharePct: z21.number(),
2439
+ /**
2440
+ * URLs from the latest run's grounding sources whose host matches this
2441
+ * competitor's domain, with the queries each URL was cited for. Empty
2442
+ * when no grounding-source data is available (e.g. no `rawResponse` JSON
2443
+ * stored for the snapshots).
2444
+ */
2445
+ theirCitedPages: z21.array(z21.object({ url: z21.string(), citedFor: z21.array(z21.string()) }))
2446
+ });
2447
+ var competitorLandscapeSchema = z21.object({
2448
+ /** Project's own citation count (for the bar chart comparing project vs competitors). */
2449
+ projectCitationCount: z21.number(),
2450
+ competitors: z21.array(competitorRowSchema)
2451
+ });
2452
+ var mentionRowSchema = z21.object({
2453
+ domain: z21.string(),
2454
+ /** Number of (query × provider) pairs whose answer text mentioned this competitor's brand or domain. */
2455
+ mentionCount: z21.number(),
2456
+ /** Out-of count for the same denominator (snapshots that had answer text). */
2457
+ totalCount: z21.number(),
2458
+ /** 'High' | 'Moderate' | 'Low' | 'None' — mention frequency tier (mirrors CompetitorRow.pressureLabel). */
2459
+ pressureLabel: z21.enum(["High", "Moderate", "Low", "None"]),
2460
+ /** Distinct queries on which this competitor was mentioned. */
2461
+ mentionedQueries: z21.array(z21.string()),
2462
+ /**
2463
+ * Mention share 0..100. Numerator = this competitor's `mentionCount`.
2464
+ * Denominator = sum of `mentionCount` across all competitors plus the
2465
+ * project's own `projectMentionCount`. Equals 0 when no snapshot had any
2466
+ * mention. Per-competitor split of the same head-to-head measure the
2467
+ * project's hero `MentionShareDto` gauge headlines.
2468
+ */
2469
+ sharePct: z21.number()
2470
+ });
2471
+ var mentionLandscapeSchema = z21.object({
2472
+ /** Project's own mention count (for the bar chart comparing project vs competitors). */
2473
+ projectMentionCount: z21.number(),
2474
+ /** Snapshots considered — those with non-empty answerText. Drives the totalCount denominator. */
2475
+ totalAnswerSnapshots: z21.number(),
2476
+ competitors: z21.array(mentionRowSchema)
2477
+ });
2478
+ var aiSourceCategoryBucketSchema = z21.object({
2479
+ /** Category slug from packages/contracts/src/source-categories. */
2480
+ category: z21.string(),
2481
+ /** Display label. */
2482
+ label: z21.string(),
2483
+ /** Number of citations falling in this category. */
2484
+ count: z21.number(),
2485
+ /** 0..100 share of total citations. */
2486
+ sharePct: z21.number()
2487
+ });
2488
+ var aiSourceOriginSchema = z21.object({
2489
+ categories: z21.array(aiSourceCategoryBucketSchema),
2490
+ /** Top 20 source domains by citation count (excluding the project's own domain). */
2491
+ topDomains: z21.array(z21.object({
2492
+ domain: z21.string(),
2493
+ count: z21.number(),
2494
+ /** True when the domain is one of the project's tracked competitors. */
2495
+ isCompetitor: z21.boolean()
2496
+ }))
2497
+ });
2498
+ var gscQueryRowSchema = z21.object({
2499
+ query: z21.string(),
2500
+ clicks: z21.number(),
2501
+ impressions: z21.number(),
2502
+ ctr: z21.number(),
2503
+ avgPosition: z21.number(),
2504
+ /** Heuristic categorization: 'brand' | 'lead-gen' | 'industry' | 'other'. */
2505
+ category: z21.enum(["brand", "lead-gen", "industry", "other"])
2506
+ });
2507
+ var gscSectionSchema = z21.object({
2508
+ periodStart: z21.string(),
2509
+ periodEnd: z21.string(),
2510
+ totalClicks: z21.number(),
2511
+ totalImpressions: z21.number(),
2512
+ ctr: z21.number(),
2513
+ avgPosition: z21.number(),
2514
+ topQueries: z21.array(gscQueryRowSchema),
2515
+ categoryBreakdown: z21.array(z21.object({
2516
+ category: z21.enum(["brand", "lead-gen", "industry", "other"]),
2517
+ clicks: z21.number(),
2518
+ impressions: z21.number(),
2519
+ sharePct: z21.number()
2520
+ })),
2521
+ trend: z21.array(z21.object({ date: z21.string(), clicks: z21.number(), impressions: z21.number() })),
2522
+ /**
2523
+ * Tracked AEO queries that have no GSC impressions in the report window.
2524
+ * Surfaces queries that may not represent real search demand.
2525
+ */
2526
+ trackedButNoGsc: z21.array(z21.string()),
2527
+ /**
2528
+ * GSC top queries (sorted by impressions desc) that are not tracked as
2529
+ * AEO queries — the candidate set for adding to the AEO project.
2530
+ */
2531
+ gscButNotTracked: z21.array(z21.string())
2532
+ });
2533
+ var gaTrafficSectionSchema = z21.object({
2534
+ totalSessions: z21.number(),
2535
+ totalUsers: z21.number(),
2536
+ totalOrganicSessions: z21.number(),
2537
+ periodStart: z21.string(),
2538
+ periodEnd: z21.string(),
2539
+ topLandingPages: z21.array(z21.object({
2540
+ page: z21.string(),
2541
+ sessions: z21.number(),
2542
+ users: z21.number(),
2543
+ organicSessions: z21.number()
2544
+ })),
2545
+ channelBreakdown: z21.array(z21.object({
2546
+ channel: z21.string(),
2547
+ sessions: z21.number(),
2548
+ sharePct: z21.number()
2549
+ }))
2550
+ });
2551
+ var socialReferralSectionSchema = z21.object({
2552
+ totalSessions: z21.number(),
2553
+ organicSessions: z21.number(),
2554
+ paidSessions: z21.number(),
2555
+ channels: z21.array(z21.object({
2556
+ channelGroup: z21.string(),
2557
+ sessions: z21.number(),
2558
+ sharePct: z21.number()
2559
+ })),
2560
+ topCampaigns: z21.array(z21.object({
2561
+ source: z21.string(),
2562
+ medium: z21.string(),
2563
+ sessions: z21.number()
2564
+ }))
2565
+ });
2566
+ var aiReferralSectionSchema = z21.object({
2567
+ totalSessions: z21.number(),
2568
+ totalUsers: z21.number(),
2569
+ bySource: z21.array(z21.object({
2570
+ source: z21.string(),
2571
+ sessions: z21.number(),
2572
+ users: z21.number(),
2573
+ sharePct: z21.number()
2574
+ })),
2575
+ trend: z21.array(z21.object({ date: z21.string(), sessions: z21.number() })),
2576
+ topLandingPages: z21.array(z21.object({
2577
+ page: z21.string(),
2578
+ sessions: z21.number(),
2579
+ users: z21.number()
2580
+ }))
2581
+ });
2582
+ var serverActivitySectionSchema = z21.object({
2583
+ /** ISO8601 inclusive lower bound of the report window (default: 7 days). */
2584
+ windowStart: z21.string(),
2585
+ /** ISO8601 inclusive upper bound. */
2586
+ windowEnd: z21.string(),
2587
+ hasData: z21.boolean(),
2588
+ /** Last-7d total verified crawler hits, with prior 7d for delta. */
2589
+ verifiedCrawlerHits: z21.object({ current: z21.number(), prior: z21.number(), deltaPct: z21.number().nullable() }),
2590
+ /** Last-7d total unverified crawler hits, separated from verified trust metrics. */
2591
+ unverifiedCrawlerHits: z21.object({ current: z21.number(), prior: z21.number(), deltaPct: z21.number().nullable() }),
2592
+ /** Last-7d AI-referral sessions (sessionized from server-side request evidence). */
2593
+ referralArrivals: z21.object({ current: z21.number(), prior: z21.number(), deltaPct: z21.number().nullable() }),
2594
+ /** Per-AI-operator breakdown (OpenAI, Anthropic, Google AI, Perplexity, …). */
2595
+ byOperator: z21.array(z21.object({
2596
+ operator: z21.string(),
2597
+ verifiedHits: z21.number(),
2598
+ /** Shown to agency audience only — claimed-bot UA, rDNS not confirmed. */
2599
+ unverifiedHits: z21.number(),
2600
+ referralArrivals: z21.number(),
2601
+ deltaPct: z21.number().nullable()
2602
+ })),
2603
+ /**
2604
+ * Top crawled paths (verified only, last-7d). Path-level citation cross-reference
2605
+ * is intentionally NOT included today — the citation store is domain-grain
2606
+ * (`query_snapshots.cited_domains` is a JSON array of hostnames), so a path-level
2607
+ * "cited?" flag would be misleading. A future iteration that lands URL-grain
2608
+ * citation evidence can extend this entry with a `citationState` field without
2609
+ * breaking the contract.
2610
+ */
2611
+ topCrawledPaths: z21.array(z21.object({
2612
+ path: z21.string(),
2613
+ verifiedHits: z21.number(),
2614
+ /** How many distinct AI operators crawled this path in the window. */
2615
+ distinctOperators: z21.number()
2616
+ })),
2617
+ /** AI products that sent ≥1 session in the window (referral by destination). */
2618
+ referralProducts: z21.array(z21.object({
2619
+ product: z21.string(),
2620
+ arrivals: z21.number(),
2621
+ distinctLandingPaths: z21.number()
2622
+ })),
2623
+ /** Daily trend, last 14d for sparkline / chart rendering. */
2624
+ dailyTrend: z21.array(z21.object({
2625
+ date: z21.string(),
2626
+ verifiedCrawlerHits: z21.number(),
2627
+ referralArrivals: z21.number()
2628
+ })),
2629
+ /**
2630
+ * Top landing paths for AI-referral sessions (last-7d).
2631
+ * Complements `topCrawledPaths` (what bots fetch) with what humans actually land on.
2632
+ */
2633
+ topReferralLandingPaths: z21.array(z21.object({
2634
+ path: z21.string(),
2635
+ arrivals: z21.number(),
2636
+ distinctProducts: z21.number()
2637
+ }))
2638
+ });
2639
+ var indexingHealthSectionSchema = z21.object({
2640
+ /** Source: 'google' | 'bing' | null when neither is connected. */
2641
+ provider: z21.enum(["google", "bing"]).nullable(),
2642
+ total: z21.number(),
2643
+ indexed: z21.number(),
2644
+ notIndexed: z21.number(),
2645
+ /** Google-only — pages explicitly marked as deindexed. Bing reports 'unknown' instead. */
2646
+ deindexed: z21.number(),
2647
+ /** Bing-only — pages with no inspection data yet. */
2648
+ unknown: z21.number(),
2649
+ /** 0..100. */
2650
+ indexedPct: z21.number()
2651
+ });
2652
+ var citationsTrendPointSchema = z21.object({
2653
+ /** Run ID — anchor for cross-section linking. */
2654
+ runId: z21.string(),
2655
+ /** ISO timestamp when the run finished (or createdAt fallback). */
2656
+ date: z21.string(),
2657
+ /**
2658
+ * 0..100 — same per-query unique-cited definition as
2659
+ * `ReportExecutiveSummary.citationRate`. Stable across runs with different
2660
+ * provider counts so the trend line measures real movement rather than
2661
+ * provider-count variance.
2662
+ */
2663
+ citationRate: z21.number(),
2664
+ /** Numerator of `citationRate` for this run. */
2665
+ citedQueryCount: z21.number(),
2666
+ /** Denominator of `citationRate` for this run. */
2667
+ totalQueryCount: z21.number(),
2668
+ /** 0..100 — same per-query unique-mentioned definition as `ReportExecutiveSummary.mentionRate`. */
2669
+ mentionRate: z21.number(),
2670
+ /** Numerator of `mentionRate` for this run. */
2671
+ mentionedQueryCount: z21.number(),
2672
+ /**
2673
+ * Per-provider rates for the same run. Each provider's rate is per-pair
2674
+ * within that provider (`cited / scanned`), so it remains comparable
2675
+ * between providers in the same run.
2676
+ */
2677
+ providerRates: z21.array(z21.object({ provider: z21.string(), citationRate: z21.number() }))
2678
+ });
2679
+ var reportInsightSchema = z21.object({
2680
+ id: z21.string(),
2681
+ type: z21.enum(["regression", "gain", "opportunity"]),
2682
+ severity: z21.enum(["critical", "high", "medium", "low"]),
2683
+ title: z21.string(),
2684
+ query: z21.string(),
2685
+ provider: z21.string(),
2686
+ recommendation: z21.string().nullable(),
2687
+ createdAt: z21.string(),
2688
+ /**
2689
+ * How many times this insight fired across recent runs for the same
2690
+ * `(query, provider, type)` tuple. Always ≥ 1. Insights returned by the
2691
+ * report API are already deduped to one row per tuple, with this counter
2692
+ * surfacing the multiplicity. Use it directly instead of grouping again
2693
+ * client-side — counts derived from raw insight rows will overcount.
2694
+ */
2695
+ instanceCount: z21.number()
2696
+ });
2697
+ var recommendedNextStepSchema = z21.object({
2698
+ /** 'immediate' | 'short-term' | 'medium-term' — bucketed by severity heuristic. */
2699
+ horizon: z21.enum(["immediate", "short-term", "medium-term"]),
2700
+ title: z21.string(),
2701
+ rationale: z21.string()
2702
+ });
2703
+ var reportRateDeltaSchema = z21.object({
2704
+ /** Current value (0..100 for rates, raw count otherwise). When `window`
2705
+ * is present this is the average over the last `window` checks. */
2706
+ current: z21.number(),
2707
+ /** Prior value compared against. When `window` is present this is the
2708
+ * average over the prior `window` checks before that. */
2709
+ prior: z21.number(),
2710
+ /** Absolute delta (current − prior). Negative = decrease. */
2711
+ deltaAbs: z21.number(),
2712
+ /**
2713
+ * Direction tag for tone mapping. Threshold is metric-specific (3pp for
2714
+ * rates, 0.5 for counts) so small noise lands as 'flat' rather than
2715
+ * flipping up/down each run.
2716
+ */
2717
+ direction: z21.enum(["up", "down", "flat"]),
2718
+ /**
2719
+ * How many points went into each side of the average. Omitted (or 1)
2720
+ * means point-to-point (legacy "since last check"). Higher values mean
2721
+ * a rolling-average comparison — renderers should label it as
2722
+ * "vs prior N checks" when this is ≥ 2.
2723
+ */
2724
+ window: z21.number().optional()
2725
+ });
2726
+ var reportProviderMovementSchema = z21.object({
2727
+ provider: z21.string(),
2728
+ current: z21.number(),
2729
+ prior: z21.number(),
2730
+ deltaAbs: z21.number(),
2731
+ direction: z21.enum(["up", "down", "flat"])
2732
+ });
2733
+ var whatsChangedSectionSchema = z21.object({
2734
+ /**
2735
+ * False when there's no prior run (or fewer than the trend baseline),
2736
+ * meaning all per-metric deltas will be null. Renderers use this to swap
2737
+ * in a "establishing baseline" fallback rather than rendering empty
2738
+ * delta tiles.
2739
+ */
2740
+ enoughHistory: z21.boolean(),
2741
+ /**
2742
+ * One-sentence narrative summary suitable as a section subtitle.
2743
+ * Always present — even on baseline, narrates whatever signal exists.
2744
+ */
2745
+ headline: z21.string(),
2746
+ /** Citation rate delta vs the prior completed run. Null when no prior run. */
2747
+ citationRate: reportRateDeltaSchema.nullable(),
2748
+ /** Mention rate delta vs the prior completed run. Null when no prior run. */
2749
+ mentionRate: reportRateDeltaSchema.nullable(),
2750
+ /** Cited query count delta vs the prior completed run. Null when no prior run. */
2751
+ citedQueryCount: reportRateDeltaSchema.nullable(),
2752
+ /**
2753
+ * GSC clicks delta — last 14 days of `gsc.trend` vs the 14 days before
2754
+ * that. Null when GSC isn't connected or fewer than 28 trend points exist.
2755
+ */
2756
+ gscClicksDelta: reportRateDeltaSchema.nullable(),
2757
+ /**
2758
+ * AI referral sessions delta — last 14 days of `aiReferrals.trend` vs the
2759
+ * 14 days before that. Null when AI referrals aren't tracked or fewer
2760
+ * than 28 trend points exist.
2761
+ */
2762
+ aiReferralsDelta: reportRateDeltaSchema.nullable(),
2763
+ /**
2764
+ * Per-provider citation rate movements (latest run vs prior run). Empty
2765
+ * when no prior run. Sorted by |deltaAbs| desc — providers with the
2766
+ * biggest swing first.
2767
+ */
2768
+ providerMovements: z21.array(reportProviderMovementSchema),
2769
+ /**
2770
+ * Top wins this period — gains surfaced by the intelligence engine.
2771
+ * Capped at 5; sourced from `insights` filtered to `type: 'gain'`.
2772
+ */
2773
+ wins: z21.array(reportInsightSchema),
2774
+ /**
2775
+ * Top regressions this period — citations or mentions lost. Capped at 5;
2776
+ * sourced from `insights` filtered to `type: 'regression'`.
2777
+ */
2778
+ regressions: z21.array(reportInsightSchema)
2779
+ });
2780
+ var reportAudienceSchema = z21.enum(["agency", "client"]);
2781
+ var reportActionAudienceSchema = z21.enum(["agency", "client", "both"]);
2782
+ var reportActionHorizonSchema = z21.enum(["immediate", "short-term", "medium-term"]);
2783
+ var reportActionConfidenceSchema = z21.enum(["high", "medium", "low"]);
2784
+ var reportToneSchema = z21.enum(["positive", "caution", "negative", "neutral"]);
2785
+ var reportActionCategorySchema = z21.enum([
2786
+ "content",
2787
+ "competitors",
2788
+ "provider",
2789
+ "search-demand",
2790
+ "indexing",
2791
+ "location",
2792
+ "monitoring"
2793
+ ]);
2794
+ var reportActionPlanItemSchema = z21.object({
2795
+ /** Which report audience should see this action. `both` renders in both modes. */
2796
+ audience: reportActionAudienceSchema,
2797
+ /** Stable sort priority. Lower numbers render earlier. */
2798
+ priority: z21.number(),
2799
+ /** When this should be tackled. */
2800
+ horizon: reportActionHorizonSchema,
2801
+ category: reportActionCategorySchema,
2802
+ title: z21.string(),
2803
+ /** Direct next step written as an operator/client-friendly imperative. */
2804
+ action: z21.string(),
2805
+ /** Why this matters. Keep each entry concise and evidence-backed. */
2806
+ why: z21.array(z21.string()),
2807
+ /** Specific observations that justify the action. */
2808
+ evidence: z21.array(z21.string()),
2809
+ /** What should move if the action worked. */
2810
+ successMetric: z21.string(),
2811
+ /** Confidence in the recommendation based on the available evidence. */
2812
+ confidence: reportActionConfidenceSchema
2813
+ });
2814
+ var reportClientSummarySchema = z21.object({
2815
+ headline: z21.string(),
2816
+ overview: z21.string(),
2817
+ actionItems: z21.array(reportActionPlanItemSchema),
2818
+ confidenceNotes: z21.array(z21.string())
2819
+ });
2820
+ var reportAgencyDiagnosticSchema = z21.object({
2821
+ title: z21.string(),
2822
+ detail: z21.string(),
2823
+ severity: z21.enum(["positive", "caution", "negative", "neutral"]),
2824
+ evidence: z21.array(z21.string())
2825
+ });
2826
+ var reportAgencyDiagnosticsSchema = z21.object({
2827
+ priorities: z21.array(reportActionPlanItemSchema),
2828
+ diagnostics: z21.array(reportAgencyDiagnosticSchema)
2829
+ });
2123
2830
  function reportActionTone(action) {
2124
2831
  if (action.horizon === "immediate") return "negative";
2125
2832
  if (action.confidence === "high") return "caution";
@@ -2176,6 +2883,51 @@ function reportConfidenceLabel(confidence) {
2176
2883
  return "Low";
2177
2884
  }
2178
2885
  }
2886
+ var projectReportDtoSchema = z21.object({
2887
+ meta: reportMetaSchema,
2888
+ executiveSummary: reportExecutiveSummarySchema,
2889
+ citationScorecard: citationScorecardSchema,
2890
+ competitorLandscape: competitorLandscapeSchema,
2891
+ mentionLandscape: mentionLandscapeSchema,
2892
+ aiSourceOrigin: aiSourceOriginSchema,
2893
+ gsc: gscSectionSchema.nullable(),
2894
+ ga: gaTrafficSectionSchema.nullable(),
2895
+ socialReferrals: socialReferralSectionSchema.nullable(),
2896
+ aiReferrals: aiReferralSectionSchema.nullable(),
2897
+ /** Server-side log-evidence visibility (crawls + click-through sessions). Null when no traffic source connected. */
2898
+ serverActivity: serverActivitySectionSchema.nullable(),
2899
+ indexingHealth: indexingHealthSectionSchema.nullable(),
2900
+ citationsTrend: z21.array(citationsTrendPointSchema),
2901
+ /**
2902
+ * Trend-focused "what's changed" summary for the report's act 2. Always
2903
+ * present; renderers gate empty/baseline states via `enoughHistory`.
2904
+ */
2905
+ whatsChanged: whatsChangedSectionSchema,
2906
+ insights: z21.array(reportInsightSchema),
2907
+ recommendedNextSteps: z21.array(recommendedNextStepSchema),
2908
+ /** Canonical structured actions shared by the client and agency render modes. */
2909
+ actionPlan: z21.array(reportActionPlanItemSchema),
2910
+ /** Polished client-facing summary and action shortlist. */
2911
+ clientSummary: reportClientSummarySchema,
2912
+ /** Technical, evidence-oriented operator diagnostics for agency mode. */
2913
+ agencyDiagnostics: reportAgencyDiagnosticsSchema,
2914
+ /**
2915
+ * Ranked, action-typed content opportunities sourced from the existing
2916
+ * intelligence layer (`buildContentTargetRows`). Empty when no run has
2917
+ * produced candidate queries with demand or competitor signal.
2918
+ */
2919
+ contentOpportunities: z21.array(contentTargetRowDtoSchema),
2920
+ /**
2921
+ * Queries where competitors were cited but the project was not. Sourced
2922
+ * from `buildContentGapRows`. Empty until the first answer-visibility run.
2923
+ */
2924
+ contentGaps: z21.array(contentGapRowDtoSchema),
2925
+ /**
2926
+ * Per-query grounding source map (own + competitor cited URLs). Sourced
2927
+ * from `buildContentSourceRows`. Empty until the first answer-visibility run.
2928
+ */
2929
+ groundingSources: z21.array(contentSourceRowDtoSchema)
2930
+ });
2179
2931
 
2180
2932
  // ../contracts/src/report-dedup.ts
2181
2933
  var REPORT_INTENT_STOPWORDS = /* @__PURE__ */ new Set([
@@ -2245,15 +2997,15 @@ function dedupeReportOpportunities(report) {
2245
2997
  }
2246
2998
 
2247
2999
  // ../contracts/src/skills.ts
2248
- import { z as z19 } from "zod";
2249
- var codingAgentSchema = z19.enum(["claude", "codex"]);
3000
+ import { z as z22 } from "zod";
3001
+ var codingAgentSchema = z22.enum(["claude", "codex"]);
2250
3002
  var CodingAgents = codingAgentSchema.enum;
2251
- var skillsClientSchema = z19.enum(["claude", "codex", "all"]);
3003
+ var skillsClientSchema = z22.enum(["claude", "codex", "all"]);
2252
3004
  var SkillsClients = skillsClientSchema.enum;
2253
3005
 
2254
3006
  // ../contracts/src/traffic.ts
2255
- import { z as z20 } from "zod";
2256
- var trafficSourceTypeSchema = z20.enum([
3007
+ import { z as z23 } from "zod";
3008
+ var trafficSourceTypeSchema = z23.enum([
2257
3009
  "cloud-run",
2258
3010
  "wordpress",
2259
3011
  "cloudflare",
@@ -2261,7 +3013,7 @@ var trafficSourceTypeSchema = z20.enum([
2261
3013
  "generic-log"
2262
3014
  ]);
2263
3015
  var TrafficSourceTypes = trafficSourceTypeSchema.enum;
2264
- var trafficAdapterCapabilitySchema = z20.enum([
3016
+ var trafficAdapterCapabilitySchema = z23.enum([
2265
3017
  "raw-request-events",
2266
3018
  "aggregate-request-metrics",
2267
3019
  "request-url",
@@ -2272,198 +3024,198 @@ var trafficAdapterCapabilitySchema = z20.enum([
2272
3024
  "cursor-pull"
2273
3025
  ]);
2274
3026
  var TrafficAdapterCapabilities = trafficAdapterCapabilitySchema.enum;
2275
- var trafficEvidenceKindSchema = z20.enum(["raw-request", "aggregate-bucket"]);
3027
+ var trafficEvidenceKindSchema = z23.enum(["raw-request", "aggregate-bucket"]);
2276
3028
  var TrafficEvidenceKinds = trafficEvidenceKindSchema.enum;
2277
- var trafficEventConfidenceSchema = z20.enum(["observed", "provider-aggregated", "inferred"]);
3029
+ var trafficEventConfidenceSchema = z23.enum(["observed", "provider-aggregated", "inferred"]);
2278
3030
  var TrafficEventConfidences = trafficEventConfidenceSchema.enum;
2279
- var trafficProviderResourceSchema = z20.object({
2280
- type: z20.string().nullable(),
2281
- labels: z20.record(z20.string(), z20.string())
3031
+ var trafficProviderResourceSchema = z23.object({
3032
+ type: z23.string().nullable(),
3033
+ labels: z23.record(z23.string(), z23.string())
2282
3034
  });
2283
- var normalizedTrafficRequestSchema = z20.object({
3035
+ var normalizedTrafficRequestSchema = z23.object({
2284
3036
  sourceType: trafficSourceTypeSchema,
2285
- evidenceKind: z20.literal(TrafficEvidenceKinds["raw-request"]),
2286
- confidence: z20.literal(TrafficEventConfidences.observed),
2287
- eventId: z20.string().min(1),
2288
- observedAt: z20.string().min(1),
2289
- method: z20.string().nullable(),
2290
- requestUrl: z20.string().nullable(),
2291
- host: z20.string().nullable(),
2292
- path: z20.string().min(1),
2293
- queryString: z20.string().nullable(),
2294
- status: z20.number().int().nullable(),
2295
- userAgent: z20.string().nullable(),
2296
- remoteIp: z20.string().nullable(),
2297
- referer: z20.string().nullable(),
2298
- latencyMs: z20.number().nullable(),
2299
- requestSizeBytes: z20.number().int().nullable(),
2300
- responseSizeBytes: z20.number().int().nullable(),
3037
+ evidenceKind: z23.literal(TrafficEvidenceKinds["raw-request"]),
3038
+ confidence: z23.literal(TrafficEventConfidences.observed),
3039
+ eventId: z23.string().min(1),
3040
+ observedAt: z23.string().min(1),
3041
+ method: z23.string().nullable(),
3042
+ requestUrl: z23.string().nullable(),
3043
+ host: z23.string().nullable(),
3044
+ path: z23.string().min(1),
3045
+ queryString: z23.string().nullable(),
3046
+ status: z23.number().int().nullable(),
3047
+ userAgent: z23.string().nullable(),
3048
+ remoteIp: z23.string().nullable(),
3049
+ referer: z23.string().nullable(),
3050
+ latencyMs: z23.number().nullable(),
3051
+ requestSizeBytes: z23.number().int().nullable(),
3052
+ responseSizeBytes: z23.number().int().nullable(),
2301
3053
  providerResource: trafficProviderResourceSchema,
2302
- providerLabels: z20.record(z20.string(), z20.string())
3054
+ providerLabels: z23.record(z23.string(), z23.string())
2303
3055
  });
2304
- var normalizedTrafficPullPageSchema = z20.object({
2305
- events: z20.array(normalizedTrafficRequestSchema),
2306
- rawEntryCount: z20.number().int().nonnegative(),
2307
- skippedEntryCount: z20.number().int().nonnegative(),
2308
- nextPageToken: z20.string().optional(),
2309
- filter: z20.string()
3056
+ var normalizedTrafficPullPageSchema = z23.object({
3057
+ events: z23.array(normalizedTrafficRequestSchema),
3058
+ rawEntryCount: z23.number().int().nonnegative(),
3059
+ skippedEntryCount: z23.number().int().nonnegative(),
3060
+ nextPageToken: z23.string().optional(),
3061
+ filter: z23.string()
2310
3062
  });
2311
- var trafficSourceStatusSchema = z20.enum(["connected", "paused", "error", "archived"]);
3063
+ var trafficSourceStatusSchema = z23.enum(["connected", "paused", "error", "archived"]);
2312
3064
  var TrafficSourceStatuses = trafficSourceStatusSchema.enum;
2313
- var trafficSourceAuthModeSchema = z20.enum(["oauth", "service-account"]);
3065
+ var trafficSourceAuthModeSchema = z23.enum(["oauth", "service-account"]);
2314
3066
  var TrafficSourceAuthModes = trafficSourceAuthModeSchema.enum;
2315
- var verificationStatusSchema = z20.enum(["verified", "claimed_unverified", "unknown_ai_like"]);
3067
+ var verificationStatusSchema = z23.enum(["verified", "claimed_unverified", "unknown_ai_like"]);
2316
3068
  var VerificationStatuses = verificationStatusSchema.enum;
2317
- var cloudRunSourceConfigSchema = z20.object({
2318
- gcpProjectId: z20.string().min(1),
2319
- serviceName: z20.string().nullable().optional(),
2320
- location: z20.string().nullable().optional(),
3069
+ var cloudRunSourceConfigSchema = z23.object({
3070
+ gcpProjectId: z23.string().min(1),
3071
+ serviceName: z23.string().nullable().optional(),
3072
+ location: z23.string().nullable().optional(),
2321
3073
  authMode: trafficSourceAuthModeSchema
2322
3074
  });
2323
- var wordpressTrafficSourceConfigSchema = z20.object({
2324
- baseUrl: z20.string().url(),
2325
- username: z20.string().min(1)
3075
+ var wordpressTrafficSourceConfigSchema = z23.object({
3076
+ baseUrl: z23.string().url(),
3077
+ username: z23.string().min(1)
2326
3078
  });
2327
- var vercelTrafficEnvironmentSchema = z20.enum(["production", "preview"]);
3079
+ var vercelTrafficEnvironmentSchema = z23.enum(["production", "preview"]);
2328
3080
  var VercelTrafficEnvironments = vercelTrafficEnvironmentSchema.enum;
2329
- var vercelTrafficSourceConfigSchema = z20.object({
3081
+ var vercelTrafficSourceConfigSchema = z23.object({
2330
3082
  /** Vercel project id (e.g. `prj_...`). */
2331
- projectId: z20.string().min(1),
3083
+ projectId: z23.string().min(1),
2332
3084
  /** Vercel team / owner id (e.g. `team_...`). */
2333
- teamId: z20.string().min(1),
3085
+ teamId: z23.string().min(1),
2334
3086
  environment: vercelTrafficEnvironmentSchema
2335
3087
  });
2336
- var trafficSourceDtoSchema = z20.object({
2337
- id: z20.string(),
2338
- projectId: z20.string(),
3088
+ var trafficSourceDtoSchema = z23.object({
3089
+ id: z23.string(),
3090
+ projectId: z23.string(),
2339
3091
  sourceType: trafficSourceTypeSchema,
2340
- displayName: z20.string(),
3092
+ displayName: z23.string(),
2341
3093
  status: trafficSourceStatusSchema,
2342
- lastSyncedAt: z20.string().nullable(),
2343
- lastCursor: z20.string().nullable(),
2344
- lastError: z20.string().nullable(),
2345
- archivedAt: z20.string().nullable(),
2346
- config: z20.record(z20.string(), z20.unknown()),
2347
- createdAt: z20.string(),
2348
- updatedAt: z20.string()
2349
- });
2350
- var trafficConnectCloudRunRequestSchema = z20.object({
2351
- gcpProjectId: z20.string().min(1),
2352
- serviceName: z20.string().min(1).optional(),
2353
- location: z20.string().min(1).optional(),
2354
- displayName: z20.string().min(1).optional(),
3094
+ lastSyncedAt: z23.string().nullable(),
3095
+ lastCursor: z23.string().nullable(),
3096
+ lastError: z23.string().nullable(),
3097
+ archivedAt: z23.string().nullable(),
3098
+ config: z23.record(z23.string(), z23.unknown()),
3099
+ createdAt: z23.string(),
3100
+ updatedAt: z23.string()
3101
+ });
3102
+ var trafficConnectCloudRunRequestSchema = z23.object({
3103
+ gcpProjectId: z23.string().min(1),
3104
+ serviceName: z23.string().min(1).optional(),
3105
+ location: z23.string().min(1).optional(),
3106
+ displayName: z23.string().min(1).optional(),
2355
3107
  /** Service-account JSON content (string). When omitted, defaults to OAuth via `canonry google connect <project> --type ga4` flow. */
2356
- keyJson: z20.string().optional()
3108
+ keyJson: z23.string().optional()
2357
3109
  });
2358
- var trafficConnectWordpressRequestSchema = z20.object({
2359
- baseUrl: z20.string().url(),
2360
- username: z20.string().min(1),
3110
+ var trafficConnectWordpressRequestSchema = z23.object({
3111
+ baseUrl: z23.string().url(),
3112
+ username: z23.string().min(1),
2361
3113
  /** WordPress Application Password (the same auth used by the content client). */
2362
- applicationPassword: z20.string().min(1),
2363
- displayName: z20.string().min(1).optional()
3114
+ applicationPassword: z23.string().min(1),
3115
+ displayName: z23.string().min(1).optional()
2364
3116
  });
2365
- var trafficConnectVercelRequestSchema = z20.object({
3117
+ var trafficConnectVercelRequestSchema = z23.object({
2366
3118
  /** Vercel project id (e.g. `prj_...`) — from the Vercel dashboard or `.vercel/project.json`. */
2367
- projectId: z20.string().min(1),
3119
+ projectId: z23.string().min(1),
2368
3120
  /** Vercel team / owner id (e.g. `team_...`). */
2369
- teamId: z20.string().min(1),
3121
+ teamId: z23.string().min(1),
2370
3122
  /** Vercel API token (personal access token). Stored in `~/.canonry/config.yaml`, never the DB. */
2371
- token: z20.string().min(1),
3123
+ token: z23.string().min(1),
2372
3124
  /** Which deployment environment's request logs to pull. Default: `production`. */
2373
3125
  environment: vercelTrafficEnvironmentSchema.optional(),
2374
- displayName: z20.string().min(1).optional()
2375
- });
2376
- var trafficSyncResponseSchema = z20.object({
2377
- sourceId: z20.string(),
2378
- runId: z20.string(),
2379
- syncedAt: z20.string(),
2380
- pulledEvents: z20.number().int().nonnegative(),
2381
- crawlerHits: z20.number().int().nonnegative(),
2382
- aiReferralHits: z20.number().int().nonnegative(),
2383
- unknownHits: z20.number().int().nonnegative(),
2384
- crawlerBucketRows: z20.number().int().nonnegative(),
2385
- aiReferralBucketRows: z20.number().int().nonnegative(),
2386
- sampleRows: z20.number().int().nonnegative(),
2387
- windowStart: z20.string(),
2388
- windowEnd: z20.string()
2389
- });
2390
- var trafficBackfillRequestSchema = z20.object({
3126
+ displayName: z23.string().min(1).optional()
3127
+ });
3128
+ var trafficSyncResponseSchema = z23.object({
3129
+ sourceId: z23.string(),
3130
+ runId: z23.string(),
3131
+ syncedAt: z23.string(),
3132
+ pulledEvents: z23.number().int().nonnegative(),
3133
+ crawlerHits: z23.number().int().nonnegative(),
3134
+ aiReferralHits: z23.number().int().nonnegative(),
3135
+ unknownHits: z23.number().int().nonnegative(),
3136
+ crawlerBucketRows: z23.number().int().nonnegative(),
3137
+ aiReferralBucketRows: z23.number().int().nonnegative(),
3138
+ sampleRows: z23.number().int().nonnegative(),
3139
+ windowStart: z23.string(),
3140
+ windowEnd: z23.string()
3141
+ });
3142
+ var trafficBackfillRequestSchema = z23.object({
2391
3143
  /** Lookback window in days. Capped server-side at the upstream log retention ceiling (Cloud Logging _Default = 30d). Default: 30. */
2392
- days: z20.number().int().positive().optional()
3144
+ days: z23.number().int().positive().optional()
2393
3145
  });
2394
- var trafficBackfillResponseSchema = z20.object({
2395
- sourceId: z20.string(),
2396
- runId: z20.string(),
3146
+ var trafficBackfillResponseSchema = z23.object({
3147
+ sourceId: z23.string(),
3148
+ runId: z23.string(),
2397
3149
  status: runStatusSchema,
2398
- windowStart: z20.string(),
2399
- windowEnd: z20.string(),
3150
+ windowStart: z23.string(),
3151
+ windowEnd: z23.string(),
2400
3152
  /** Days actually used after server-side clamping (≤ requested). */
2401
- daysRequested: z20.number().int().positive(),
2402
- daysApplied: z20.number().int().positive()
3153
+ daysRequested: z23.number().int().positive(),
3154
+ daysApplied: z23.number().int().positive()
2403
3155
  });
2404
- var trafficSourceTotalsSchema = z20.object({
2405
- crawlerHits: z20.number().int().nonnegative(),
2406
- aiReferralHits: z20.number().int().nonnegative(),
2407
- sampleCount: z20.number().int().nonnegative()
3156
+ var trafficSourceTotalsSchema = z23.object({
3157
+ crawlerHits: z23.number().int().nonnegative(),
3158
+ aiReferralHits: z23.number().int().nonnegative(),
3159
+ sampleCount: z23.number().int().nonnegative()
2408
3160
  });
2409
- var trafficSourceListResponseSchema = z20.object({
2410
- sources: z20.array(trafficSourceDtoSchema)
3161
+ var trafficSourceListResponseSchema = z23.object({
3162
+ sources: z23.array(trafficSourceDtoSchema)
2411
3163
  });
2412
3164
  var trafficSourceDetailDtoSchema = trafficSourceDtoSchema.extend({
2413
3165
  totals24h: trafficSourceTotalsSchema,
2414
- latestRun: z20.object({
2415
- runId: z20.string(),
3166
+ latestRun: z23.object({
3167
+ runId: z23.string(),
2416
3168
  status: runStatusSchema,
2417
- startedAt: z20.string().nullable(),
2418
- finishedAt: z20.string().nullable(),
2419
- error: z20.string().nullable()
3169
+ startedAt: z23.string().nullable(),
3170
+ finishedAt: z23.string().nullable(),
3171
+ error: z23.string().nullable()
2420
3172
  }).nullable()
2421
3173
  });
2422
- var trafficStatusResponseSchema = z20.object({
2423
- sources: z20.array(trafficSourceDetailDtoSchema)
3174
+ var trafficStatusResponseSchema = z23.object({
3175
+ sources: z23.array(trafficSourceDetailDtoSchema)
2424
3176
  });
2425
- var trafficEventKindSchema = z20.enum(["crawler", "ai-referral"]);
3177
+ var trafficEventKindSchema = z23.enum(["crawler", "ai-referral"]);
2426
3178
  var TrafficEventKinds = trafficEventKindSchema.enum;
2427
- var trafficCrawlerEventEntrySchema = z20.object({
2428
- kind: z20.literal(TrafficEventKinds.crawler),
2429
- sourceId: z20.string(),
2430
- tsHour: z20.string(),
2431
- botId: z20.string(),
2432
- operator: z20.string(),
2433
- verificationStatus: z20.string(),
2434
- pathNormalized: z20.string(),
2435
- status: z20.number().int(),
2436
- hits: z20.number().int().nonnegative()
2437
- });
2438
- var trafficAiReferralEventEntrySchema = z20.object({
2439
- kind: z20.literal(TrafficEventKinds["ai-referral"]),
2440
- sourceId: z20.string(),
2441
- tsHour: z20.string(),
2442
- product: z20.string(),
2443
- operator: z20.string(),
2444
- sourceDomain: z20.string(),
2445
- evidenceType: z20.string(),
2446
- landingPathNormalized: z20.string(),
2447
- status: z20.number().int(),
2448
- hits: z20.number().int().nonnegative()
2449
- });
2450
- var trafficEventEntrySchema = z20.discriminatedUnion("kind", [
3179
+ var trafficCrawlerEventEntrySchema = z23.object({
3180
+ kind: z23.literal(TrafficEventKinds.crawler),
3181
+ sourceId: z23.string(),
3182
+ tsHour: z23.string(),
3183
+ botId: z23.string(),
3184
+ operator: z23.string(),
3185
+ verificationStatus: z23.string(),
3186
+ pathNormalized: z23.string(),
3187
+ status: z23.number().int(),
3188
+ hits: z23.number().int().nonnegative()
3189
+ });
3190
+ var trafficAiReferralEventEntrySchema = z23.object({
3191
+ kind: z23.literal(TrafficEventKinds["ai-referral"]),
3192
+ sourceId: z23.string(),
3193
+ tsHour: z23.string(),
3194
+ product: z23.string(),
3195
+ operator: z23.string(),
3196
+ sourceDomain: z23.string(),
3197
+ evidenceType: z23.string(),
3198
+ landingPathNormalized: z23.string(),
3199
+ status: z23.number().int(),
3200
+ hits: z23.number().int().nonnegative()
3201
+ });
3202
+ var trafficEventEntrySchema = z23.discriminatedUnion("kind", [
2451
3203
  trafficCrawlerEventEntrySchema,
2452
3204
  trafficAiReferralEventEntrySchema
2453
3205
  ]);
2454
- var trafficEventsResponseSchema = z20.object({
2455
- windowStart: z20.string(),
2456
- windowEnd: z20.string(),
2457
- totals: z20.object({
2458
- crawlerHits: z20.number().int().nonnegative(),
2459
- aiReferralHits: z20.number().int().nonnegative()
3206
+ var trafficEventsResponseSchema = z23.object({
3207
+ windowStart: z23.string(),
3208
+ windowEnd: z23.string(),
3209
+ totals: z23.object({
3210
+ crawlerHits: z23.number().int().nonnegative(),
3211
+ aiReferralHits: z23.number().int().nonnegative()
2460
3212
  }),
2461
- events: z20.array(trafficEventEntrySchema)
3213
+ events: z23.array(trafficEventEntrySchema)
2462
3214
  });
2463
3215
 
2464
3216
  // ../contracts/src/discovery.ts
2465
- import { z as z21 } from "zod";
2466
- var discoveryBucketSchema = z21.enum(["cited", "aspirational", "wasted-surface"]);
3217
+ import { z as z24 } from "zod";
3218
+ var discoveryBucketSchema = z24.enum(["cited", "aspirational", "wasted-surface"]);
2467
3219
  var DiscoveryBuckets = discoveryBucketSchema.enum;
2468
3220
  var DEFAULT_DISCOVERY_PROMOTE_BUCKETS = [
2469
3221
  DiscoveryBuckets.cited,
@@ -2471,7 +3223,7 @@ var DEFAULT_DISCOVERY_PROMOTE_BUCKETS = [
2471
3223
  ];
2472
3224
  var DISCOVERY_PROMOTE_COMPETITOR_CAP = 20;
2473
3225
  var DISCOVERY_PROMOTE_COMPETITOR_MIN_HITS = 2;
2474
- var discoveryCompetitorTypeSchema = z21.enum([
3226
+ var discoveryCompetitorTypeSchema = z24.enum([
2475
3227
  "direct-competitor",
2476
3228
  "ota-aggregator",
2477
3229
  "editorial-media",
@@ -2482,11 +3234,11 @@ var DiscoveryCompetitorTypes = discoveryCompetitorTypeSchema.enum;
2482
3234
  var DEFAULT_DISCOVERY_PROMOTE_COMPETITOR_TYPES = [
2483
3235
  DiscoveryCompetitorTypes["direct-competitor"]
2484
3236
  ];
2485
- var discoverySessionStatusSchema = z21.enum(["queued", "seeding", "probing", "completed", "failed"]);
3237
+ var discoverySessionStatusSchema = z24.enum(["queued", "seeding", "probing", "completed", "failed"]);
2486
3238
  var DiscoverySessionStatuses = discoverySessionStatusSchema.enum;
2487
- var discoveryCompetitorMapEntrySchema = z21.object({
2488
- domain: z21.string().min(1),
2489
- hits: z21.number().int().positive(),
3239
+ var discoveryCompetitorMapEntrySchema = z24.object({
3240
+ domain: z24.string().min(1),
3241
+ hits: z24.number().int().positive(),
2490
3242
  /**
2491
3243
  * Domain classification from the session's post-probe AI classification
2492
3244
  * pass. Defaults to `unknown` so competitor maps persisted before
@@ -2495,43 +3247,43 @@ var discoveryCompetitorMapEntrySchema = z21.object({
2495
3247
  */
2496
3248
  competitorType: discoveryCompetitorTypeSchema.default("unknown")
2497
3249
  });
2498
- var discoveryProbeDtoSchema = z21.object({
2499
- id: z21.string(),
2500
- sessionId: z21.string(),
2501
- projectId: z21.string(),
2502
- query: z21.string(),
3250
+ var discoveryProbeDtoSchema = z24.object({
3251
+ id: z24.string(),
3252
+ sessionId: z24.string(),
3253
+ projectId: z24.string(),
3254
+ query: z24.string(),
2503
3255
  bucket: discoveryBucketSchema.nullable().default(null),
2504
3256
  citationState: citationStateSchema,
2505
- citedDomains: z21.array(z21.string()).default([]),
2506
- createdAt: z21.string()
3257
+ citedDomains: z24.array(z24.string()).default([]),
3258
+ createdAt: z24.string()
2507
3259
  });
2508
- var discoverySessionDtoSchema = z21.object({
2509
- id: z21.string(),
2510
- projectId: z21.string(),
3260
+ var discoverySessionDtoSchema = z24.object({
3261
+ id: z24.string(),
3262
+ projectId: z24.string(),
2511
3263
  status: discoverySessionStatusSchema,
2512
- icpDescription: z21.string().nullable().optional(),
2513
- seedProvider: z21.string().nullable().optional(),
2514
- seedCountRaw: z21.number().int().nullable().optional(),
2515
- seedCount: z21.number().int().nullable().optional(),
2516
- dedupThreshold: z21.number().nullable().optional(),
2517
- probeCount: z21.number().int().nullable().optional(),
2518
- citedCount: z21.number().int().nullable().default(null),
2519
- aspirationalCount: z21.number().int().nullable().default(null),
2520
- wastedCount: z21.number().int().nullable().default(null),
2521
- competitorMap: z21.array(discoveryCompetitorMapEntrySchema).default([]),
2522
- error: z21.string().nullable().optional(),
2523
- startedAt: z21.string().nullable().optional(),
2524
- finishedAt: z21.string().nullable().optional(),
2525
- createdAt: z21.string()
3264
+ icpDescription: z24.string().nullable().optional(),
3265
+ seedProvider: z24.string().nullable().optional(),
3266
+ seedCountRaw: z24.number().int().nullable().optional(),
3267
+ seedCount: z24.number().int().nullable().optional(),
3268
+ dedupThreshold: z24.number().nullable().optional(),
3269
+ probeCount: z24.number().int().nullable().optional(),
3270
+ citedCount: z24.number().int().nullable().default(null),
3271
+ aspirationalCount: z24.number().int().nullable().default(null),
3272
+ wastedCount: z24.number().int().nullable().default(null),
3273
+ competitorMap: z24.array(discoveryCompetitorMapEntrySchema).default([]),
3274
+ error: z24.string().nullable().optional(),
3275
+ startedAt: z24.string().nullable().optional(),
3276
+ finishedAt: z24.string().nullable().optional(),
3277
+ createdAt: z24.string()
2526
3278
  });
2527
3279
  var discoverySessionDetailDtoSchema = discoverySessionDtoSchema.extend({
2528
- probes: z21.array(discoveryProbeDtoSchema).default([])
3280
+ probes: z24.array(discoveryProbeDtoSchema).default([])
2529
3281
  });
2530
3282
  var DISCOVERY_MAX_PROBES_CAP = 500;
2531
- var discoveryRunRequestSchema = z21.object({
2532
- icpDescription: z21.string().min(1).optional(),
2533
- dedupThreshold: z21.number().min(0).max(1).optional(),
2534
- maxProbes: z21.number().int().positive().max(DISCOVERY_MAX_PROBES_CAP).optional(),
3283
+ var discoveryRunRequestSchema = z24.object({
3284
+ icpDescription: z24.string().min(1).optional(),
3285
+ dedupThreshold: z24.number().min(0).max(1).optional(),
3286
+ maxProbes: z24.number().int().positive().max(DISCOVERY_MAX_PROBES_CAP).optional(),
2535
3287
  /**
2536
3288
  * Optional override of the project's location labels, constraining seed
2537
3289
  * generation to a subset of the configured service areas. Each label must
@@ -2539,39 +3291,39 @@ var discoveryRunRequestSchema = z21.object({
2539
3291
  * `resolveLocations`). Omitted means "use every project location" — a
2540
3292
  * project with no locations is unaffected.
2541
3293
  */
2542
- locations: z21.array(z21.string().min(1)).optional()
3294
+ locations: z24.array(z24.string().min(1)).optional()
2543
3295
  });
2544
- var discoveryPromoteRequestSchema = z21.object({
2545
- buckets: z21.array(discoveryBucketSchema).min(1).optional(),
2546
- includeCompetitors: z21.boolean().optional(),
2547
- competitorTypes: z21.array(discoveryCompetitorTypeSchema).min(1).optional()
3296
+ var discoveryPromoteRequestSchema = z24.object({
3297
+ buckets: z24.array(discoveryBucketSchema).min(1).optional(),
3298
+ includeCompetitors: z24.boolean().optional(),
3299
+ competitorTypes: z24.array(discoveryCompetitorTypeSchema).min(1).optional()
2548
3300
  });
2549
- var discoveryPromotePreviewSchema = z21.object({
2550
- sessionId: z21.string(),
2551
- projectId: z21.string(),
3301
+ var discoveryPromotePreviewSchema = z24.object({
3302
+ sessionId: z24.string(),
3303
+ projectId: z24.string(),
2552
3304
  status: discoverySessionStatusSchema,
2553
- queriesByBucket: z21.object({
2554
- cited: z21.array(z21.string()),
2555
- aspirational: z21.array(z21.string()),
2556
- "wasted-surface": z21.array(z21.string())
3305
+ queriesByBucket: z24.object({
3306
+ cited: z24.array(z24.string()),
3307
+ aspirational: z24.array(z24.string()),
3308
+ "wasted-surface": z24.array(z24.string())
2557
3309
  }),
2558
- suggestedCompetitors: z21.array(discoveryCompetitorMapEntrySchema)
2559
- });
2560
- var discoveryPromoteResultSchema = z21.object({
2561
- sessionId: z21.string(),
2562
- projectId: z21.string(),
2563
- promoted: z21.object({
2564
- queries: z21.array(z21.string()),
2565
- competitors: z21.array(z21.string())
3310
+ suggestedCompetitors: z24.array(discoveryCompetitorMapEntrySchema)
3311
+ });
3312
+ var discoveryPromoteResultSchema = z24.object({
3313
+ sessionId: z24.string(),
3314
+ projectId: z24.string(),
3315
+ promoted: z24.object({
3316
+ queries: z24.array(z24.string()),
3317
+ competitors: z24.array(z24.string())
2566
3318
  }),
2567
- skipped: z21.object({
2568
- queries: z21.array(z21.string()),
2569
- competitors: z21.array(z21.string())
3319
+ skipped: z24.object({
3320
+ queries: z24.array(z24.string()),
3321
+ competitors: z24.array(z24.string())
2570
3322
  })
2571
3323
  });
2572
- var queryProvenanceSchema = z21.union([
2573
- z21.literal("cli"),
2574
- z21.string().regex(/^discovery:.+$/)
3324
+ var queryProvenanceSchema = z24.union([
3325
+ z24.literal("cli"),
3326
+ z24.string().regex(/^discovery:.+$/)
2575
3327
  ]);
2576
3328
 
2577
3329
  // ../contracts/src/embeddings.ts
@@ -2752,6 +3504,7 @@ export {
2752
3504
  locationContextSchema,
2753
3505
  getProviderLocationHandling,
2754
3506
  notificationEventSchema,
3507
+ notificationDtoSchema,
2755
3508
  notificationCreateRequestSchema,
2756
3509
  AppError,
2757
3510
  notFound,
@@ -2771,10 +3524,14 @@ export {
2771
3524
  hasLocationLabel,
2772
3525
  resolveLocations,
2773
3526
  projectUpsertRequestSchema,
3527
+ projectDtoSchema,
3528
+ queryDtoSchema,
3529
+ keywordDtoSchema,
2774
3530
  queryBatchRequestSchema,
2775
3531
  keywordBatchRequestSchema,
2776
3532
  queryGenerateRequestSchema,
2777
3533
  keywordGenerateRequestSchema,
3534
+ competitorDtoSchema,
2778
3535
  competitorBatchRequestSchema,
2779
3536
  normalizeProjectDomain,
2780
3537
  registrableDomain,
@@ -2784,50 +3541,109 @@ export {
2784
3541
  effectiveBrandNames,
2785
3542
  projectConfigSchema,
2786
3543
  resolveConfigSpecQueries,
3544
+ googleConnectionDtoSchema,
3545
+ gscSearchDataDtoSchema,
3546
+ gscPerformanceDailyDtoSchema,
3547
+ gscUrlInspectionDtoSchema,
3548
+ gscDeindexedRowSchema,
3549
+ gscCoverageSummaryDtoSchema,
3550
+ indexingRequestResponseDtoSchema,
3551
+ gscCoverageSnapshotDtoSchema,
3552
+ gscSiteListResponseDtoSchema,
3553
+ gscSitemapListResponseDtoSchema,
3554
+ bingUrlInspectionDtoSchema,
3555
+ bingCoverageSummaryDtoSchema,
3556
+ bingKeywordStatsDtoSchema,
3557
+ bingCoverageSnapshotDtoSchema,
3558
+ bingIndexingRequestResponseDtoSchema,
3559
+ bingSitesResponseDtoSchema,
3560
+ bingStatusDtoSchema,
3561
+ bingConnectResponseDtoSchema,
3562
+ bingSetSiteResponseDtoSchema,
3563
+ cdpStatusDtoSchema,
2787
3564
  wordpressEnvSchema,
3565
+ wordpressStatusDtoSchema,
3566
+ wordpressPageSummaryDtoSchema,
3567
+ wordpressSchemaBlockDtoSchema,
3568
+ wordpressPageDetailDtoSchema,
3569
+ wordpressManualAssistDtoSchema,
3570
+ wordpressAuditPageDtoSchema,
3571
+ wordpressBulkMetaResultDtoSchema,
3572
+ wordpressSchemaDeployResultDtoSchema,
3573
+ wordpressSchemaStatusResultDtoSchema,
3574
+ wordpressOnboardResultDtoSchema,
3575
+ wordpressDiffDtoSchema,
2788
3576
  AgentProviderIds,
2789
3577
  AGENT_PROVIDER_IDS,
2790
3578
  isAgentProviderId,
3579
+ settingsDtoSchema,
2791
3580
  RunStatuses,
2792
3581
  RunKinds,
2793
3582
  RunTriggers,
2794
3583
  citationStateSchema,
2795
3584
  CitationStates,
2796
3585
  runTriggerRequestSchema,
3586
+ runDtoSchema,
2797
3587
  parseRunError,
2798
3588
  buildRunErrorFromMessages,
2799
3589
  serializeRunError,
2800
3590
  formatRunErrorOneLine,
3591
+ snapshotListResponseSchema,
3592
+ snapshotDiffResponseSchema,
3593
+ runDetailDtoSchema,
3594
+ latestProjectRunDtoSchema,
3595
+ auditLogEntrySchema,
2801
3596
  snapshotRequestSchema,
2802
3597
  resolveSnapshotRequestQueries,
3598
+ snapshotReportSchema,
2803
3599
  schedulableRunKindSchema,
2804
3600
  SchedulableRunKinds,
3601
+ scheduleDtoSchema,
2805
3602
  scheduleUpsertRequestSchema,
2806
3603
  parseWindow,
2807
3604
  windowCutoff,
2808
3605
  categorizeSource,
2809
3606
  categorizeSourceWithCompetitors,
2810
3607
  categoryLabel,
3608
+ ga4StatusDtoSchema,
3609
+ ga4SyncResponseDtoSchema,
3610
+ ga4AiReferralHistoryEntrySchema,
3611
+ ga4SocialReferralHistoryEntrySchema,
3612
+ ga4SessionHistoryEntrySchema,
2811
3613
  extractAnswerMentions,
2812
3614
  determineAnswerMentioned,
2813
3615
  visibilityStateFromAnswerMentioned,
2814
3616
  mentionStateFromAnswerMentioned,
2815
3617
  brandKeyFromText,
3618
+ agentProvidersResponseDtoSchema,
2816
3619
  MemorySources,
2817
3620
  AGENT_MEMORY_VALUE_MAX_BYTES,
2818
3621
  AGENT_MEMORY_KEY_MAX_LENGTH,
2819
3622
  agentMemoryUpsertRequestSchema,
2820
3623
  agentMemoryDeleteRequestSchema,
2821
3624
  CcReleaseSyncStatuses,
3625
+ ccReleaseSyncDtoSchema,
3626
+ backlinkSummaryDtoSchema,
3627
+ backlinkListResponseSchema,
3628
+ backlinkHistoryEntrySchema,
3629
+ backlinksInstallStatusDtoSchema,
3630
+ backlinksInstallResultDtoSchema,
3631
+ ccAvailableReleaseSchema,
3632
+ ccCachedReleaseSchema,
2822
3633
  ContentActions,
2823
3634
  contentActionLabel,
2824
3635
  actionConfidenceLabel,
3636
+ contentTargetsResponseDtoSchema,
3637
+ contentSourcesResponseDtoSchema,
3638
+ contentGapsResponseDtoSchema,
2825
3639
  CheckStatuses,
2826
3640
  CheckScopes,
2827
3641
  CheckCategories,
3642
+ doctorReportSchema,
2828
3643
  summarizeCheckResults,
2829
3644
  absolutizeProjectUrl,
2830
3645
  normalizeUrlPath,
3646
+ citationVisibilityResponseSchema,
2831
3647
  emptyCitationVisibility,
2832
3648
  citationStateToCited,
2833
3649
  reportActionTone,
@@ -2835,6 +3651,7 @@ export {
2835
3651
  reportHorizonLabel,
2836
3652
  reportActionCategoryLabel,
2837
3653
  reportConfidenceLabel,
3654
+ projectReportDtoSchema,
2838
3655
  dedupeReportActions,
2839
3656
  dedupeReportOpportunities,
2840
3657
  CodingAgents,
@@ -2846,11 +3663,18 @@ export {
2846
3663
  TrafficSourceStatuses,
2847
3664
  TrafficSourceAuthModes,
2848
3665
  VerificationStatuses,
3666
+ trafficSourceDtoSchema,
2849
3667
  trafficConnectCloudRunRequestSchema,
2850
3668
  trafficConnectWordpressRequestSchema,
2851
3669
  trafficConnectVercelRequestSchema,
3670
+ trafficSyncResponseSchema,
3671
+ trafficBackfillResponseSchema,
3672
+ trafficSourceListResponseSchema,
3673
+ trafficSourceDetailDtoSchema,
3674
+ trafficStatusResponseSchema,
2852
3675
  trafficEventKindSchema,
2853
3676
  TrafficEventKinds,
3677
+ trafficEventsResponseSchema,
2854
3678
  discoveryBucketSchema,
2855
3679
  DiscoveryBuckets,
2856
3680
  DEFAULT_DISCOVERY_PROMOTE_BUCKETS,
@@ -2860,9 +3684,13 @@ export {
2860
3684
  DiscoveryCompetitorTypes,
2861
3685
  DEFAULT_DISCOVERY_PROMOTE_COMPETITOR_TYPES,
2862
3686
  DiscoverySessionStatuses,
3687
+ discoverySessionDtoSchema,
3688
+ discoverySessionDetailDtoSchema,
2863
3689
  DISCOVERY_MAX_PROBES_CAP,
2864
3690
  discoveryRunRequestSchema,
2865
3691
  discoveryPromoteRequestSchema,
3692
+ discoveryPromotePreviewSchema,
3693
+ discoveryPromoteResultSchema,
2866
3694
  clusterByCosine,
2867
3695
  pickClusterRepresentative,
2868
3696
  formatRatio,