@ainyc/canonry 4.182.3 → 4.183.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +139 -104
- package/assets/agent-workspace/skills/aero/references/orchestration.md +1 -1
- package/assets/agent-workspace/skills/canonry/references/canonry-cli.md +1 -1
- package/assets/assets/{AuditHistoryPanel-1_FHpzj-.js → AuditHistoryPanel-DM-2GC2i.js} +1 -1
- package/assets/assets/{BacklinksPage-045za10_.js → BacklinksPage-YJU9B2RQ.js} +1 -1
- package/assets/assets/{HistoryPage-36K_6asu.js → HistoryPage-DcFzvVRB.js} +1 -1
- package/assets/assets/{MeasurementPropertyPage-B4DJGoY6.js → MeasurementPropertyPage-OQ3X0KHU.js} +1 -1
- package/assets/assets/{ProjectPage-CshC68Ne.js → ProjectPage-CMZO1xb2.js} +8 -8
- package/assets/assets/{RunRow-U2CN755e.js → RunRow-6SFvSqhK.js} +1 -1
- package/assets/assets/{RunsPage-D0CtU4d-.js → RunsPage-Chk_-IOW.js} +1 -1
- package/assets/assets/{SettingsPage-zMWieTPK.js → SettingsPage-DSS1eunM.js} +1 -1
- package/assets/assets/{SiteHealthSection-TpQPu_Uj.js → SiteHealthSection-CewNWjGo.js} +3 -3
- package/assets/assets/{TrafficPage-DfLUt-64.js → TrafficPage-DRZ1aqnG.js} +1 -1
- package/assets/assets/{TrafficSourceDetailPage-DbjNNWSt.js → TrafficSourceDetailPage-vaBD4zHK.js} +1 -1
- package/assets/assets/{extract-error-message-CWqz1QPC.js → extract-error-message-DD4JJz8j.js} +1 -1
- package/assets/assets/{index-Brb7M_6G.js → index-BdR4Vlu6.js} +23 -23
- package/assets/assets/{react-sigma_core.esm.min-Drqprr9L.js → react-sigma_core.esm.min-B8Wmi5Ko.js} +1 -1
- package/assets/index.html +1 -1
- package/dist/{chunk-FVC7PGYQ.js → chunk-3SFCUICM.js} +3 -3
- package/dist/{chunk-K45YKXE4.js → chunk-7ATZMDG2.js} +158 -41
- package/dist/{chunk-BDJT7XZL.js → chunk-AZJOCWZ4.js} +42 -6
- package/dist/{chunk-DY5ZDKQW.js → chunk-DU5Q5ZOX.js} +4574 -4390
- package/dist/{chunk-I3KSOMJA.js → chunk-VXPM6O4R.js} +2 -2
- package/dist/cli.js +5 -5
- package/dist/index.js +4 -4
- package/dist/{intelligence-service-HGA553GT.js → intelligence-service-BQIIWWQJ.js} +2 -2
- package/dist/mcp.js +3 -3
- package/package.json +9 -9
package/assets/assets/{react-sigma_core.esm.min-Drqprr9L.js → react-sigma_core.esm.min-B8Wmi5Ko.js}
RENAMED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{g as Bt,t as S,r as C}from"./vendor-tanstack-CYBjbqVr.js";import{e as Ht,G as Wt}from"./SiteHealthSection-
|
|
1
|
+
import{g as Bt,t as S,r as C}from"./vendor-tanstack-CYBjbqVr.js";import{e as Ht,G as Wt}from"./SiteHealthSection-CewNWjGo.js";import"./index-BdR4Vlu6.js";import"./vendor-radix-BpmvLvpp.js";import"./vendor-recharts-FA0uySU7.js";import"./vendor-lucide-XjCNFK0x.js";import"./vendor-markdown-9tTeP8v7.js";import"./vendor-yaml-GWJz5H2G.js";import"./ChartPrimitives-DLEICrrL.js";function Vt(r,n){if(typeof r!="object"||!r)return r;var i=r[Symbol.toPrimitive];if(i!==void 0){var e=i.call(r,n);if(typeof e!="object")return e;throw new TypeError("@@toPrimitive must return a primitive value.")}return String(r)}function ae(r){var n=Vt(r,"string");return typeof n=="symbol"?n:n+""}function A(r,n){if(!(r instanceof n))throw new TypeError("Cannot call a class as a function")}function He(r,n){for(var i=0;i<n.length;i++){var e=n[i];e.enumerable=e.enumerable||!1,e.configurable=!0,"value"in e&&(e.writable=!0),Object.defineProperty(r,ae(e.key),e)}}function L(r,n,i){return n&&He(r.prototype,n),i&&He(r,i),Object.defineProperty(r,"prototype",{writable:!1}),r}function Q(r){return Q=Object.setPrototypeOf?Object.getPrototypeOf.bind():function(n){return n.__proto__||Object.getPrototypeOf(n)},Q(r)}function yt(){try{var r=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){}))}catch{}return(yt=function(){return!!r})()}function jt(r){if(r===void 0)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return r}function Zt(r,n){if(n&&(typeof n=="object"||typeof n=="function"))return n;if(n!==void 0)throw new TypeError("Derived constructors may only return object or undefined");return jt(r)}function I(r,n,i){return n=Q(n),Zt(r,yt()?Reflect.construct(n,i||[],Q(r).constructor):n.apply(r,i))}function xe(r,n){return xe=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(i,e){return i.__proto__=e,i},xe(r,n)}function G(r,n){if(typeof n!="function"&&n!==null)throw new TypeError("Super expression must either be null or a function");r.prototype=Object.create(n&&n.prototype,{constructor:{value:r,writable:!0,configurable:!0}}),Object.defineProperty(r,"prototype",{writable:!1}),n&&xe(r,n)}function qt(r){if(Array.isArray(r))return r}function Yt(r,n){var i=r==null?null:typeof Symbol<"u"&&r[Symbol.iterator]||r["@@iterator"];if(i!=null){var e,t,a,o,s=[],l=!0,h=!1;try{if(a=(i=i.call(r)).next,n===0){if(Object(i)!==i)return;l=!1}else for(;!(l=(e=a.call(i)).done)&&(s.push(e.value),s.length!==n);l=!0);}catch(u){h=!0,t=u}finally{try{if(!l&&i.return!=null&&(o=i.return(),Object(o)!==o))return}finally{if(h)throw t}}return s}}function Se(r,n){(n==null||n>r.length)&&(n=r.length);for(var i=0,e=Array(n);i<n;i++)e[i]=r[i];return e}function Tt(r,n){if(r){if(typeof r=="string")return Se(r,n);var i={}.toString.call(r).slice(8,-1);return i==="Object"&&r.constructor&&(i=r.constructor.name),i==="Map"||i==="Set"?Array.from(r):i==="Arguments"||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(i)?Se(r,n):void 0}}function Xt(){throw new TypeError(`Invalid attempt to destructure non-iterable instance.
|
|
2
2
|
In order to be iterable, non-array objects must have a [Symbol.iterator]() method.`)}function ee(r,n){return qt(r)||Yt(r,n)||Tt(r,n)||Xt()}var pe={black:"#000000",silver:"#C0C0C0",gray:"#808080",grey:"#808080",white:"#FFFFFF",maroon:"#800000",red:"#FF0000",purple:"#800080",fuchsia:"#FF00FF",green:"#008000",lime:"#00FF00",olive:"#808000",yellow:"#FFFF00",navy:"#000080",blue:"#0000FF",teal:"#008080",aqua:"#00FFFF",darkblue:"#00008B",mediumblue:"#0000CD",darkgreen:"#006400",darkcyan:"#008B8B",deepskyblue:"#00BFFF",darkturquoise:"#00CED1",mediumspringgreen:"#00FA9A",springgreen:"#00FF7F",cyan:"#00FFFF",midnightblue:"#191970",dodgerblue:"#1E90FF",lightseagreen:"#20B2AA",forestgreen:"#228B22",seagreen:"#2E8B57",darkslategray:"#2F4F4F",darkslategrey:"#2F4F4F",limegreen:"#32CD32",mediumseagreen:"#3CB371",turquoise:"#40E0D0",royalblue:"#4169E1",steelblue:"#4682B4",darkslateblue:"#483D8B",mediumturquoise:"#48D1CC",indigo:"#4B0082",darkolivegreen:"#556B2F",cadetblue:"#5F9EA0",cornflowerblue:"#6495ED",rebeccapurple:"#663399",mediumaquamarine:"#66CDAA",dimgray:"#696969",dimgrey:"#696969",slateblue:"#6A5ACD",olivedrab:"#6B8E23",slategray:"#708090",slategrey:"#708090",lightslategray:"#778899",lightslategrey:"#778899",mediumslateblue:"#7B68EE",lawngreen:"#7CFC00",chartreuse:"#7FFF00",aquamarine:"#7FFFD4",skyblue:"#87CEEB",lightskyblue:"#87CEFA",blueviolet:"#8A2BE2",darkred:"#8B0000",darkmagenta:"#8B008B",saddlebrown:"#8B4513",darkseagreen:"#8FBC8F",lightgreen:"#90EE90",mediumpurple:"#9370DB",darkviolet:"#9400D3",palegreen:"#98FB98",darkorchid:"#9932CC",yellowgreen:"#9ACD32",sienna:"#A0522D",brown:"#A52A2A",darkgray:"#A9A9A9",darkgrey:"#A9A9A9",lightblue:"#ADD8E6",greenyellow:"#ADFF2F",paleturquoise:"#AFEEEE",lightsteelblue:"#B0C4DE",powderblue:"#B0E0E6",firebrick:"#B22222",darkgoldenrod:"#B8860B",mediumorchid:"#BA55D3",rosybrown:"#BC8F8F",darkkhaki:"#BDB76B",mediumvioletred:"#C71585",indianred:"#CD5C5C",peru:"#CD853F",chocolate:"#D2691E",tan:"#D2B48C",lightgray:"#D3D3D3",lightgrey:"#D3D3D3",thistle:"#D8BFD8",orchid:"#DA70D6",goldenrod:"#DAA520",palevioletred:"#DB7093",crimson:"#DC143C",gainsboro:"#DCDCDC",plum:"#DDA0DD",burlywood:"#DEB887",lightcyan:"#E0FFFF",lavender:"#E6E6FA",darksalmon:"#E9967A",violet:"#EE82EE",palegoldenrod:"#EEE8AA",lightcoral:"#F08080",khaki:"#F0E68C",aliceblue:"#F0F8FF",honeydew:"#F0FFF0",azure:"#F0FFFF",sandybrown:"#F4A460",wheat:"#F5DEB3",beige:"#F5F5DC",whitesmoke:"#F5F5F5",mintcream:"#F5FFFA",ghostwhite:"#F8F8FF",salmon:"#FA8072",antiquewhite:"#FAEBD7",linen:"#FAF0E6",lightgoldenrodyellow:"#FAFAD2",oldlace:"#FDF5E6",magenta:"#FF00FF",deeppink:"#FF1493",orangered:"#FF4500",tomato:"#FF6347",hotpink:"#FF69B4",coral:"#FF7F50",darkorange:"#FF8C00",lightsalmon:"#FFA07A",orange:"#FFA500",lightpink:"#FFB6C1",pink:"#FFC0CB",gold:"#FFD700",peachpuff:"#FFDAB9",navajowhite:"#FFDEAD",moccasin:"#FFE4B5",bisque:"#FFE4C4",mistyrose:"#FFE4E1",blanchedalmond:"#FFEBCD",papayawhip:"#FFEFD5",lavenderblush:"#FFF0F5",seashell:"#FFF5EE",cornsilk:"#FFF8DC",lemonchiffon:"#FFFACD",floralwhite:"#FFFAF0",snow:"#FFFAFA",lightyellow:"#FFFFE0",ivory:"#FFFFF0"},Ct=new Int8Array(4),be=new Int32Array(Ct.buffer,0,1),$t=new Float32Array(Ct.buffer,0,1),Kt=/^\s*rgba?\s*\(/,Jt=/^\s*rgba?\s*\(\s*([0-9]*)\s*,\s*([0-9]*)\s*,\s*([0-9]*)(?:\s*,\s*(.*)?)?\)\s*$/;function Qt(r){var n=0,i=0,e=0,t=1;if(r[0]==="#")r.length===4?(n=parseInt(r.charAt(1)+r.charAt(1),16),i=parseInt(r.charAt(2)+r.charAt(2),16),e=parseInt(r.charAt(3)+r.charAt(3),16)):(n=parseInt(r.charAt(1)+r.charAt(2),16),i=parseInt(r.charAt(3)+r.charAt(4),16),e=parseInt(r.charAt(5)+r.charAt(6),16)),r.length===9&&(t=parseInt(r.charAt(7)+r.charAt(8),16)/255);else if(Kt.test(r)){var a=r.match(Jt);a&&(n=+a[1],i=+a[2],e=+a[3],a[4]&&(t=+a[4]))}return{r:n,g:i,b:e,a:t}}var J={};for(var le in pe)J[le]=oe(pe[le]),J[pe[le]]=J[le];function Rt(r,n,i,e,t){return be[0]=e<<24|i<<16|n<<8|r,be[0]=be[0]&4278190079,$t[0]}function oe(r){if(r=r.toLowerCase(),typeof J[r]<"u")return J[r];var n=Qt(r),i=n.r,e=n.g,t=n.b,a=n.a;a=a*255|0;var o=Rt(i,e,t,a);return J[r]=o,o}var Ee={};function _t(r){if(typeof Ee[r]<"u")return Ee[r];var n=(r&16711680)>>>16,i=(r&65280)>>>8,e=r&255,t=255,a=Rt(n,i,e,t);return Ee[r]=a,a}function We(r,n,i,e){return i+(n<<8)+(r<<16)}function Ve(r,n,i,e,t,a){var o=Math.floor(i/a*t),s=Math.floor(r.drawingBufferHeight/a-e/a*t),l=new Uint8Array(4);r.bindFramebuffer(r.FRAMEBUFFER,n),r.readPixels(o,s,1,1,r.RGBA,r.UNSIGNED_BYTE,l);var h=ee(l,4),u=h[0],d=h[1],f=h[2],g=h[3];return[u,d,f,g]}function c(r,n,i){return(n=ae(n))in r?Object.defineProperty(r,n,{value:i,enumerable:!0,configurable:!0,writable:!0}):r[n]=i,r}function je(r,n){var i=Object.keys(r);if(Object.getOwnPropertySymbols){var e=Object.getOwnPropertySymbols(r);n&&(e=e.filter(function(t){return Object.getOwnPropertyDescriptor(r,t).enumerable})),i.push.apply(i,e)}return i}function b(r){for(var n=1;n<arguments.length;n++){var i=arguments[n]!=null?arguments[n]:{};n%2?je(Object(i),!0).forEach(function(e){c(r,e,i[e])}):Object.getOwnPropertyDescriptors?Object.defineProperties(r,Object.getOwnPropertyDescriptors(i)):je(Object(i)).forEach(function(e){Object.defineProperty(r,e,Object.getOwnPropertyDescriptor(i,e))})}return r}function ei(r,n){for(;!{}.hasOwnProperty.call(r,n)&&(r=Q(r))!==null;);return r}function Ae(){return Ae=typeof Reflect<"u"&&Reflect.get?Reflect.get.bind():function(r,n,i){var e=ei(r,n);if(e){var t=Object.getOwnPropertyDescriptor(e,n);return t.get?t.get.call(arguments.length<3?r:i):t.value}},Ae.apply(null,arguments)}function wt(r,n,i,e){var t=Ae(Q(r.prototype),n,i);return typeof t=="function"?function(a){return t.apply(i,a)}:t}function ti(r){return r.normalized?1:r.size}function ye(r){var n=0;return r.forEach(function(i){return n+=ti(i)}),n}function xt(r,n,i){var e=r==="VERTEX"?n.VERTEX_SHADER:n.FRAGMENT_SHADER,t=n.createShader(e);if(t===null)throw new Error("loadShader: error while creating the shader");n.shaderSource(t,i),n.compileShader(t);var a=n.getShaderParameter(t,n.COMPILE_STATUS);if(!a){var o=n.getShaderInfoLog(t);throw n.deleteShader(t),new Error(`loadShader: error while compiling the shader:
|
|
3
3
|
`.concat(o,`
|
|
4
4
|
`).concat(i))}return t}function ii(r,n){return xt("VERTEX",r,n)}function ri(r,n){return xt("FRAGMENT",r,n)}function ni(r,n){var i=r.createProgram();if(i===null)throw new Error("loadProgram: error while creating the program.");var e,t;for(e=0,t=n.length;e<t;e++)r.attachShader(i,n[e]);r.linkProgram(i);var a=r.getProgramParameter(i,r.LINK_STATUS);if(!a){var o=r.getProgramInfoLog(i);throw r.deleteProgram(i),new Error("loadProgram: error while linking the program: ".concat(o))}return i}function Ze(r){var n=r.gl,i=r.buffer,e=r.program,t=r.vertexShader,a=r.fragmentShader;n.deleteShader(t),n.deleteShader(a),n.deleteProgram(e),n.deleteBuffer(i)}var qe=`#define PICKING_MODE
|
package/assets/index.html
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
<link rel="icon" type="image/png" sizes="32x32" href="./favicon-32.png" />
|
|
13
13
|
<link rel="apple-touch-icon" href="./apple-touch-icon.png" />
|
|
14
14
|
<title>Canonry</title>
|
|
15
|
-
<script type="module" crossorigin src="./assets/index-
|
|
15
|
+
<script type="module" crossorigin src="./assets/index-BdR4Vlu6.js"></script>
|
|
16
16
|
<link rel="modulepreload" crossorigin href="./assets/vendor-tanstack-CYBjbqVr.js">
|
|
17
17
|
<link rel="modulepreload" crossorigin href="./assets/vendor-radix-BpmvLvpp.js">
|
|
18
18
|
<link rel="modulepreload" crossorigin href="./assets/vendor-recharts-FA0uySU7.js">
|
|
@@ -93,7 +93,7 @@ import {
|
|
|
93
93
|
trafficConnectWordpressRequestSchema,
|
|
94
94
|
trafficEventKindSchema,
|
|
95
95
|
trafficSeriesGranularitySchema
|
|
96
|
-
} from "./chunk-
|
|
96
|
+
} from "./chunk-DU5Q5ZOX.js";
|
|
97
97
|
|
|
98
98
|
// src/config.ts
|
|
99
99
|
import fs from "fs";
|
|
@@ -9387,7 +9387,7 @@ var technicalAeoRunInputSchema = z3.object({
|
|
|
9387
9387
|
sitemapUrl: z3.string().url().optional().describe("Override the sitemap URL. Defaults to https://<canonicalDomain>/sitemap.xml."),
|
|
9388
9388
|
limit: z3.number().int().positive().max(2e3).optional().describe("Deprecated compatibility alias for maxPages."),
|
|
9389
9389
|
maxPages: z3.number().int().positive().max(5e4).optional().describe("Maximum pages crawled and audited. Defaults to 1,000; hard maximum 50,000."),
|
|
9390
|
-
maxEdges: z3.number().int().positive().max(1e6).optional().describe("Maximum link observations retained for this crawl.
|
|
9390
|
+
maxEdges: z3.number().int().positive().max(1e6).optional().describe("Maximum link observations retained for this crawl. When omitted the crawl engine derives the budget from the page count; hard maximum 1,000,000."),
|
|
9391
9391
|
maxDepth: z3.number().int().min(0).max(100).optional().describe("Maximum internal-link depth from the root page."),
|
|
9392
9392
|
checkDeadLinks: z3.boolean().optional().describe("Opt in to internal dead-link checks. Omitted and false both disable checks.")
|
|
9393
9393
|
});
|
|
@@ -11445,7 +11445,7 @@ var canonryMcpTools = [
|
|
|
11445
11445
|
defineTool({
|
|
11446
11446
|
name: "canonry_technical_aeo_run",
|
|
11447
11447
|
title: "Run Technical AEO site audit",
|
|
11448
|
-
description: "Start a site-audit run. The run discovers root, sitemap, and linked pages.
|
|
11448
|
+
description: "Start a site-audit run. The run discovers root, sitemap, and linked pages. It defaults to 1,000 pages, and the engine derives the link-observation budget from that page count with a 100,000 floor, so raising maxPages raises it too. An explicit maxEdges is a ceiling that replaces the derivation and can sit below it. It returns {runId, status} and continues in the background. If an active run has identical effective options, this tool returns it; different options are refused. Poll canonry_run_get, then read the crawl and score tools.",
|
|
11449
11449
|
access: "write",
|
|
11450
11450
|
tier: "monitoring",
|
|
11451
11451
|
inputSchema: technicalAeoRunInputSchema,
|
|
@@ -209,6 +209,7 @@ import {
|
|
|
209
209
|
canonicalMeasurementPlanJson,
|
|
210
210
|
canonicalMeasurementPlanV2,
|
|
211
211
|
canonicalMeasurementPlanV2Json,
|
|
212
|
+
canonicalSimpleMeasurementDefinitionJson,
|
|
212
213
|
canonicalizeAdsActivationManifest,
|
|
213
214
|
canonicalizeGoogleAdsCustomerSelection,
|
|
214
215
|
canonicalizeGtmAccountId,
|
|
@@ -573,6 +574,7 @@ import {
|
|
|
573
574
|
serializeRunError,
|
|
574
575
|
settingsDtoSchema,
|
|
575
576
|
shiftIsoCalendarDate,
|
|
577
|
+
simpleMeasurementDefinitionSchema,
|
|
576
578
|
siteAuditLivePageHealthSchema,
|
|
577
579
|
siteAuditPageFactorSchema,
|
|
578
580
|
siteAuditPagesResponseSchema,
|
|
@@ -652,10 +654,10 @@ import {
|
|
|
652
654
|
wordpressSchemaDeployResultDtoSchema,
|
|
653
655
|
wordpressSchemaStatusResultDtoSchema,
|
|
654
656
|
wordpressStatusDtoSchema
|
|
655
|
-
} from "./chunk-
|
|
657
|
+
} from "./chunk-DU5Q5ZOX.js";
|
|
656
658
|
|
|
657
659
|
// src/intelligence-service.ts
|
|
658
|
-
import { eq as
|
|
660
|
+
import { eq as eq64, desc as desc27, asc as asc12, and as and53, ne as ne8, or as or14, inArray as inArray23, gte as gte16, lte as lte13, isNull as isNull9, sql as sql25, exists } from "drizzle-orm";
|
|
659
661
|
|
|
660
662
|
// ../db/src/client.ts
|
|
661
663
|
import { mkdirSync } from "fs";
|
|
@@ -756,6 +758,7 @@ __export(schema_exports, {
|
|
|
756
758
|
researchRuns: () => researchRuns,
|
|
757
759
|
runs: () => runs,
|
|
758
760
|
schedules: () => schedules,
|
|
761
|
+
simpleMeasurementDefinitions: () => simpleMeasurementDefinitions,
|
|
759
762
|
siteAuditPages: () => siteAuditPages,
|
|
760
763
|
siteAuditSnapshots: () => siteAuditSnapshots,
|
|
761
764
|
siteCrawlAttempts: () => siteCrawlAttempts,
|
|
@@ -1016,6 +1019,20 @@ var runs = sqliteTable("runs", {
|
|
|
1016
1019
|
foreignColumns: [measurementPlanVersions.projectId, measurementPlanVersions.id]
|
|
1017
1020
|
})
|
|
1018
1021
|
]);
|
|
1022
|
+
var simpleMeasurementDefinitions = sqliteTable("simple_measurement_definitions", {
|
|
1023
|
+
runId: text("run_id").notNull().primaryKey(),
|
|
1024
|
+
projectId: text("project_id").notNull(),
|
|
1025
|
+
definition: text("definition", { mode: "json" }).$type().notNull(),
|
|
1026
|
+
checksum: text("checksum").notNull(),
|
|
1027
|
+
capturedAt: text("captured_at").notNull()
|
|
1028
|
+
}, (table) => [
|
|
1029
|
+
index("idx_simple_measurement_definitions_project").on(table.projectId),
|
|
1030
|
+
foreignKey({
|
|
1031
|
+
name: "simple_measurement_definitions_project_run_fk",
|
|
1032
|
+
columns: [table.projectId, table.runId],
|
|
1033
|
+
foreignColumns: [runs.projectId, runs.id]
|
|
1034
|
+
}).onDelete("cascade")
|
|
1035
|
+
]);
|
|
1019
1036
|
var queryBasketVersions = sqliteTable("query_basket_versions", {
|
|
1020
1037
|
projectId: text("project_id").notNull().references(() => projects.id, { onDelete: "cascade" }),
|
|
1021
1038
|
revision: integer("revision").notNull(),
|
|
@@ -7080,6 +7097,36 @@ var MIGRATION_VERSIONS = [
|
|
|
7080
7097
|
statements: [
|
|
7081
7098
|
`ALTER TABLE measurement_plan_versions ADD COLUMN comparable_to_version_id TEXT`
|
|
7082
7099
|
]
|
|
7100
|
+
},
|
|
7101
|
+
{
|
|
7102
|
+
// A simple (planless) run resolves its live inputs at dispatch, not queue
|
|
7103
|
+
// time. The sidecar freezes only new captures; historic runs intentionally
|
|
7104
|
+
// remain absent because no truthful definition can be reconstructed for
|
|
7105
|
+
// them. It is deliberately separate from the advanced-plan manifest and
|
|
7106
|
+
// checksum/continuity chain.
|
|
7107
|
+
version: 150,
|
|
7108
|
+
name: "simple-measurement-definitions",
|
|
7109
|
+
statements: [
|
|
7110
|
+
`CREATE TABLE IF NOT EXISTS simple_measurement_definitions (
|
|
7111
|
+
run_id TEXT PRIMARY KEY NOT NULL,
|
|
7112
|
+
project_id TEXT NOT NULL,
|
|
7113
|
+
definition TEXT NOT NULL,
|
|
7114
|
+
checksum TEXT NOT NULL,
|
|
7115
|
+
captured_at TEXT NOT NULL,
|
|
7116
|
+
FOREIGN KEY (project_id, run_id)
|
|
7117
|
+
REFERENCES runs(project_id, id) ON DELETE CASCADE
|
|
7118
|
+
)`,
|
|
7119
|
+
`CREATE INDEX IF NOT EXISTS idx_simple_measurement_definitions_project
|
|
7120
|
+
ON simple_measurement_definitions(project_id)`,
|
|
7121
|
+
// Frozen input cannot be corrected in place: a retry must either reuse
|
|
7122
|
+
// this exact definition or start a distinct run, never reinterpret a
|
|
7123
|
+
// stored answer through newly-current project settings.
|
|
7124
|
+
`CREATE TRIGGER IF NOT EXISTS simple_measurement_definitions_no_update
|
|
7125
|
+
BEFORE UPDATE ON simple_measurement_definitions
|
|
7126
|
+
BEGIN
|
|
7127
|
+
SELECT RAISE(ABORT, 'simple measurement definition is immutable');
|
|
7128
|
+
END`
|
|
7129
|
+
]
|
|
7083
7130
|
}
|
|
7084
7131
|
];
|
|
7085
7132
|
function addRunsMeasurementPlanVersionForeignKey(tx) {
|
|
@@ -38203,7 +38250,7 @@ var routeCatalog = [
|
|
|
38203
38250
|
sitemapUrl: { ...stringSchema, description: "Deprecated compatibility alias for the sitemap override." },
|
|
38204
38251
|
limit: { ...integerSchema, minimum: 1, maximum: 2e3, description: "Deprecated compatibility alias for maxPages. Max 2000." },
|
|
38205
38252
|
maxPages: { ...integerSchema, minimum: 1, maximum: 5e4, description: "Crawl page budget. Defaults to 1000; max 50000." },
|
|
38206
|
-
maxEdges: { ...integerSchema, minimum: 1, maximum: 1e6, description: "Internal-link observation budget.
|
|
38253
|
+
maxEdges: { ...integerSchema, minimum: 1, maximum: 1e6, description: "Internal-link observation budget. When omitted the crawl engine derives it from the page count; max 1000000." },
|
|
38207
38254
|
maxDepth: { ...integerSchema, minimum: 0, maximum: 100, description: "Maximum crawl depth from the root. Max 100." },
|
|
38208
38255
|
checkDeadLinks: { ...booleanSchema, default: false, description: "Enable dead-link checking. Defaults to false." }
|
|
38209
38256
|
}
|
|
@@ -79595,7 +79642,9 @@ async function technicalAeoRoutes(app, opts) {
|
|
|
79595
79642
|
sitemapUrl: effectiveRequest.sitemapUrl ?? void 0,
|
|
79596
79643
|
limit: parsed.data.limit,
|
|
79597
79644
|
maxPages: effectiveRequest.maxPages,
|
|
79598
|
-
|
|
79645
|
+
// Stays undefined when unset so the engine derives the edge budget
|
|
79646
|
+
// from the page count instead of inheriting a flat ceiling here.
|
|
79647
|
+
maxEdges: effectiveRequest.maxEdges ?? void 0,
|
|
79599
79648
|
maxDepth: effectiveRequest.maxDepth ?? void 0,
|
|
79600
79649
|
checkDeadLinks: effectiveRequest.checkDeadLinks
|
|
79601
79650
|
});
|
|
@@ -79678,6 +79727,73 @@ function serializeQuery(row) {
|
|
|
79678
79727
|
return { id: row.id, position: row.position, query: row.queryText, status: row.status, requestedModel: row.requestedModel, resolvedModel: row.resolvedModel, servedModel: row.servedModel, answerText: row.answerText, groundingSources: row.groundingSources, citedDomains: row.citedDomains, searchQueries: row.searchQueries, namedCompetitors: row.namedCompetitors, citedCompetitorDomains: row.citedCompetitorDomains, answerMentioned: row.answerMentioned, citationState: row.citationState, error: row.error, startedAt: row.startedAt, finishedAt: row.finishedAt, createdAt: row.createdAt };
|
|
79679
79728
|
}
|
|
79680
79729
|
|
|
79730
|
+
// ../api-routes/src/simple-measurement-definitions.ts
|
|
79731
|
+
import crypto49 from "crypto";
|
|
79732
|
+
import { and as and52, eq as eq63 } from "drizzle-orm";
|
|
79733
|
+
function captureSimpleMeasurementDefinition(db, input) {
|
|
79734
|
+
return db.transaction((tx) => {
|
|
79735
|
+
const run = tx.select({
|
|
79736
|
+
kind: runs.kind,
|
|
79737
|
+
trigger: runs.trigger,
|
|
79738
|
+
status: runs.status,
|
|
79739
|
+
measurementPlanVersionId: runs.measurementPlanVersionId
|
|
79740
|
+
}).from(runs).where(and52(eq63(runs.projectId, input.projectId), eq63(runs.id, input.runId))).get();
|
|
79741
|
+
if (!run) throw notFound("Run", input.runId);
|
|
79742
|
+
if (run.kind !== RunKinds["answer-visibility"] || run.trigger === RunTriggers.probe || run.measurementPlanVersionId !== null) {
|
|
79743
|
+
return null;
|
|
79744
|
+
}
|
|
79745
|
+
const definition = simpleMeasurementDefinitionSchema.parse(input.definition);
|
|
79746
|
+
const classifier = compileQueryClassifier(effectiveBrandNames(definition.identity));
|
|
79747
|
+
if (definition.queries.some((query) => query.queryClass !== (classifier?.classify(query.queryText) ?? null))) {
|
|
79748
|
+
throw validationError("Query classes must match the captured identity and text.");
|
|
79749
|
+
}
|
|
79750
|
+
const existing = tx.select().from(simpleMeasurementDefinitions).where(and52(eq63(simpleMeasurementDefinitions.projectId, input.projectId), eq63(simpleMeasurementDefinitions.runId, input.runId))).get();
|
|
79751
|
+
if (existing) {
|
|
79752
|
+
const frozen = simpleMeasurementDefinitionSchema.parse(existing.definition);
|
|
79753
|
+
const replayDefinition = {
|
|
79754
|
+
...definition,
|
|
79755
|
+
capturedAt: frozen.capturedAt
|
|
79756
|
+
};
|
|
79757
|
+
const replayChecksum = crypto49.createHash("sha256").update(canonicalSimpleMeasurementDefinitionJson(replayDefinition)).digest("hex");
|
|
79758
|
+
if (existing.checksum !== replayChecksum) {
|
|
79759
|
+
if (frozen.competitors === void 0) {
|
|
79760
|
+
const { competitors: _currentCompetitors, ...legacyReplayDefinition } = replayDefinition;
|
|
79761
|
+
const legacyReplayChecksum = crypto49.createHash("sha256").update(canonicalSimpleMeasurementDefinitionJson(legacyReplayDefinition)).digest("hex");
|
|
79762
|
+
if (existing.checksum === legacyReplayChecksum) return frozen;
|
|
79763
|
+
}
|
|
79764
|
+
throw validationError("This run already has a captured measurement definition. Start a new run for changed inputs.");
|
|
79765
|
+
}
|
|
79766
|
+
return frozen;
|
|
79767
|
+
}
|
|
79768
|
+
if (run.status !== RunStatuses.running) {
|
|
79769
|
+
throw validationError("Only a running run can capture a new measurement definition.");
|
|
79770
|
+
}
|
|
79771
|
+
if (tx.select({ id: querySnapshots.id }).from(querySnapshots).where(eq63(querySnapshots.runId, input.runId)).limit(1).get()) {
|
|
79772
|
+
throw validationError("This run already has stored answers. Its measurement definition cannot be inferred afterward.");
|
|
79773
|
+
}
|
|
79774
|
+
const projectQueryIds = new Set(tx.select({ id: queries.id }).from(queries).where(eq63(queries.projectId, input.projectId)).all().map((query) => query.id));
|
|
79775
|
+
if (definition.queries.some((query) => !projectQueryIds.has(query.queryId))) {
|
|
79776
|
+
throw validationError("Every captured query must belong to the run project.");
|
|
79777
|
+
}
|
|
79778
|
+
if (definition.competitors !== void 0) {
|
|
79779
|
+
const liveCompetitorDomains = new Set(tx.select({ domain: competitors.domain }).from(competitors).where(eq63(competitors.projectId, input.projectId)).all().map((competitor) => competitor.domain));
|
|
79780
|
+
const capturedDomains = new Set(definition.competitors.map((competitor) => competitor.domain));
|
|
79781
|
+
if (liveCompetitorDomains.size !== capturedDomains.size || [...liveCompetitorDomains].some((domain) => !capturedDomains.has(domain))) {
|
|
79782
|
+
throw validationError("Captured competitors must exactly match the project competitors dispatched for this run.");
|
|
79783
|
+
}
|
|
79784
|
+
}
|
|
79785
|
+
const checksum = crypto49.createHash("sha256").update(canonicalSimpleMeasurementDefinitionJson(definition)).digest("hex");
|
|
79786
|
+
tx.insert(simpleMeasurementDefinitions).values({
|
|
79787
|
+
projectId: input.projectId,
|
|
79788
|
+
runId: input.runId,
|
|
79789
|
+
definition,
|
|
79790
|
+
checksum,
|
|
79791
|
+
capturedAt: definition.capturedAt
|
|
79792
|
+
}).run();
|
|
79793
|
+
return definition;
|
|
79794
|
+
});
|
|
79795
|
+
}
|
|
79796
|
+
|
|
79681
79797
|
// ../api-routes/src/index.ts
|
|
79682
79798
|
async function apiRoutes(app, opts) {
|
|
79683
79799
|
app.decorate("db", opts.db);
|
|
@@ -80183,7 +80299,7 @@ function buildTrafficSourceValidators(opts) {
|
|
|
80183
80299
|
}
|
|
80184
80300
|
|
|
80185
80301
|
// src/intelligence-service.ts
|
|
80186
|
-
import
|
|
80302
|
+
import crypto50 from "crypto";
|
|
80187
80303
|
|
|
80188
80304
|
// src/logger.ts
|
|
80189
80305
|
var IS_TTY = process.stdout.isTTY === true;
|
|
@@ -80371,10 +80487,10 @@ var log = createLogger("IntelligenceService");
|
|
|
80371
80487
|
var runChronologyKey = sql25`coalesce(${runs.finishedAt}, ${runs.createdAt})`;
|
|
80372
80488
|
function analyzableRunPredicates(projectId) {
|
|
80373
80489
|
return [
|
|
80374
|
-
|
|
80490
|
+
eq64(runs.projectId, projectId),
|
|
80375
80491
|
// Only this kind writes query_snapshots.
|
|
80376
|
-
|
|
80377
|
-
or14(
|
|
80492
|
+
eq64(runs.kind, RunKinds["answer-visibility"]),
|
|
80493
|
+
or14(eq64(runs.status, RunStatuses.completed), eq64(runs.status, RunStatuses.partial)),
|
|
80378
80494
|
// Defensive: RunCoordinator already skips probes before analyzeAndPersist
|
|
80379
80495
|
// is called, but a future call site invoking it directly for a probe must
|
|
80380
80496
|
// still not pollute the intelligence window.
|
|
@@ -80419,16 +80535,16 @@ var IntelligenceService = class {
|
|
|
80419
80535
|
* Returns the analysis result for the coordinator to inspect (e.g. for webhook dispatch).
|
|
80420
80536
|
*/
|
|
80421
80537
|
analyzeAndPersist(runId, projectId) {
|
|
80422
|
-
const currentRunRecord = this.db.select().from(runs).where(
|
|
80538
|
+
const currentRunRecord = this.db.select().from(runs).where(and53(eq64(runs.id, runId), ...analyzableRunPredicates(projectId))).get();
|
|
80423
80539
|
if (!currentRunRecord) {
|
|
80424
80540
|
log.info("intelligence.skip", { runId, reason: "run not eligible for analysis" });
|
|
80425
80541
|
return null;
|
|
80426
80542
|
}
|
|
80427
80543
|
const currentLocation = currentRunRecord.location ?? null;
|
|
80428
80544
|
const recentRuns = this.db.select().from(runs).where(
|
|
80429
|
-
|
|
80545
|
+
and53(
|
|
80430
80546
|
...analyzableRunPredicates(projectId),
|
|
80431
|
-
currentLocation === null ? isNull9(runs.location) :
|
|
80547
|
+
currentLocation === null ? isNull9(runs.location) : eq64(runs.location, currentLocation),
|
|
80432
80548
|
// Never look forward. The window is this run's own past, so
|
|
80433
80549
|
// re-analyzing a historical run compares it against its true
|
|
80434
80550
|
// predecessor rather than against sweeps that came after it.
|
|
@@ -80436,7 +80552,7 @@ var IntelligenceService = class {
|
|
|
80436
80552
|
// MEASUREMENT: only runs that actually wrote snapshots — see above.
|
|
80437
80553
|
// Index seek on idx_snapshots_run, short-circuited on the first row.
|
|
80438
80554
|
exists(
|
|
80439
|
-
this.db.select({ one: sql25`1` }).from(querySnapshots).where(
|
|
80555
|
+
this.db.select({ one: sql25`1` }).from(querySnapshots).where(eq64(querySnapshots.runId, runs.id))
|
|
80440
80556
|
)
|
|
80441
80557
|
)
|
|
80442
80558
|
).orderBy(desc27(runs.finishedAt), desc27(runs.createdAt)).limit(HISTORY_WINDOW_RUNS).all();
|
|
@@ -80511,7 +80627,7 @@ var IntelligenceService = class {
|
|
|
80511
80627
|
* Returns the persisted insights so the coordinator can count critical/high.
|
|
80512
80628
|
*/
|
|
80513
80629
|
analyzeAndPersistGbp(runId, projectId) {
|
|
80514
|
-
const runRow = this.db.select({ createdAt: runs.createdAt, startedAt: runs.startedAt, finishedAt: runs.finishedAt }).from(runs).where(
|
|
80630
|
+
const runRow = this.db.select({ createdAt: runs.createdAt, startedAt: runs.startedAt, finishedAt: runs.finishedAt }).from(runs).where(eq64(runs.id, runId)).get();
|
|
80515
80631
|
if (!runRow) {
|
|
80516
80632
|
log.info("gbp-intelligence.skip", { runId, reason: "run not found" });
|
|
80517
80633
|
this.persistGbpInsights(runId, projectId, [], []);
|
|
@@ -80519,9 +80635,9 @@ var IntelligenceService = class {
|
|
|
80519
80635
|
}
|
|
80520
80636
|
const windowStart = runRow.startedAt ?? runRow.createdAt;
|
|
80521
80637
|
const windowEnd = runRow.finishedAt ?? (/* @__PURE__ */ new Date()).toISOString();
|
|
80522
|
-
const selected = this.db.select().from(gbpLocations).where(
|
|
80523
|
-
|
|
80524
|
-
|
|
80638
|
+
const selected = this.db.select().from(gbpLocations).where(and53(
|
|
80639
|
+
eq64(gbpLocations.projectId, projectId),
|
|
80640
|
+
eq64(gbpLocations.selected, true),
|
|
80525
80641
|
gte16(gbpLocations.syncedAt, windowStart),
|
|
80526
80642
|
lte13(gbpLocations.syncedAt, windowEnd)
|
|
80527
80643
|
)).all();
|
|
@@ -80556,12 +80672,12 @@ var IntelligenceService = class {
|
|
|
80556
80672
|
}
|
|
80557
80673
|
/** Build the per-location signal bundle the GBP analyzer consumes. */
|
|
80558
80674
|
buildGbpLocationSignals(projectId, locationName, displayName, fallbackDate) {
|
|
80559
|
-
const metricRows = this.db.select({ metric: gbpDailyMetrics.metric, date: gbpDailyMetrics.date, value: gbpDailyMetrics.value }).from(gbpDailyMetrics).where(
|
|
80560
|
-
const placeActionRows = this.db.select({ placeActionType: gbpPlaceActions.placeActionType, providerType: gbpPlaceActions.providerType }).from(gbpPlaceActions).where(
|
|
80561
|
-
const lodgingRow = this.db.select({ populatedGroupCount: gbpLodgingSnapshots.populatedGroupCount }).from(gbpLodgingSnapshots).where(
|
|
80562
|
-
const ownerRow = this.db.select({ description: gbpLocations.description }).from(gbpLocations).where(
|
|
80675
|
+
const metricRows = this.db.select({ metric: gbpDailyMetrics.metric, date: gbpDailyMetrics.date, value: gbpDailyMetrics.value }).from(gbpDailyMetrics).where(and53(eq64(gbpDailyMetrics.projectId, projectId), eq64(gbpDailyMetrics.locationName, locationName))).all();
|
|
80676
|
+
const placeActionRows = this.db.select({ placeActionType: gbpPlaceActions.placeActionType, providerType: gbpPlaceActions.providerType }).from(gbpPlaceActions).where(and53(eq64(gbpPlaceActions.projectId, projectId), eq64(gbpPlaceActions.locationName, locationName))).all();
|
|
80677
|
+
const lodgingRow = this.db.select({ populatedGroupCount: gbpLodgingSnapshots.populatedGroupCount }).from(gbpLodgingSnapshots).where(and53(eq64(gbpLodgingSnapshots.projectId, projectId), eq64(gbpLodgingSnapshots.locationName, locationName))).orderBy(desc27(gbpLodgingSnapshots.syncedAt)).limit(1).get();
|
|
80678
|
+
const ownerRow = this.db.select({ description: gbpLocations.description }).from(gbpLocations).where(and53(eq64(gbpLocations.projectId, projectId), eq64(gbpLocations.locationName, locationName))).get();
|
|
80563
80679
|
const descriptionMissing = !(ownerRow?.description ?? "").trim();
|
|
80564
|
-
const placeRow = this.db.select({ attributes: gbpPlaceDetails.attributes }).from(gbpPlaceDetails).where(
|
|
80680
|
+
const placeRow = this.db.select({ attributes: gbpPlaceDetails.attributes }).from(gbpPlaceDetails).where(and53(eq64(gbpPlaceDetails.projectId, projectId), eq64(gbpPlaceDetails.locationName, locationName))).orderBy(desc27(gbpPlaceDetails.syncedAt)).limit(1).get();
|
|
80565
80681
|
const placesAmenities = placeRow ? extractPlaceAmenities(placeRow.attributes) : [];
|
|
80566
80682
|
const summary = buildGbpSummary({
|
|
80567
80683
|
locationName,
|
|
@@ -80597,7 +80713,7 @@ var IntelligenceService = class {
|
|
|
80597
80713
|
/** Build the month-over-month keyword series for a location from the
|
|
80598
80714
|
* accumulating gbp_keyword_monthly table (latest complete month vs prior). */
|
|
80599
80715
|
buildGbpKeywordTrend(projectId, locationName) {
|
|
80600
|
-
const rows = this.db.select({ month: gbpKeywordMonthly.month, keyword: gbpKeywordMonthly.keyword, valueCount: gbpKeywordMonthly.valueCount }).from(gbpKeywordMonthly).where(
|
|
80716
|
+
const rows = this.db.select({ month: gbpKeywordMonthly.month, keyword: gbpKeywordMonthly.keyword, valueCount: gbpKeywordMonthly.valueCount }).from(gbpKeywordMonthly).where(and53(eq64(gbpKeywordMonthly.projectId, projectId), eq64(gbpKeywordMonthly.locationName, locationName))).all();
|
|
80601
80717
|
if (rows.length === 0) return { recentMonth: null, priorMonth: null, points: [] };
|
|
80602
80718
|
const months = [...new Set(rows.map((r) => r.month))].sort().reverse();
|
|
80603
80719
|
const recentMonth = months[0] ?? null;
|
|
@@ -80628,7 +80744,7 @@ var IntelligenceService = class {
|
|
|
80628
80744
|
*/
|
|
80629
80745
|
persistGbpInsights(runId, projectId, gbpInsights, coveredLocationNames) {
|
|
80630
80746
|
const covered = new Set(coveredLocationNames);
|
|
80631
|
-
const existing = this.db.select({ id: insights.id, dismissed: insights.dismissed }).from(insights).where(
|
|
80747
|
+
const existing = this.db.select({ id: insights.id, dismissed: insights.dismissed }).from(insights).where(and53(eq64(insights.projectId, projectId), eq64(insights.provider, GBP_INSIGHT_PROVIDER))).all();
|
|
80632
80748
|
const staleIds = [];
|
|
80633
80749
|
const dismissedSlots = /* @__PURE__ */ new Set();
|
|
80634
80750
|
for (const row of existing) {
|
|
@@ -80639,7 +80755,7 @@ var IntelligenceService = class {
|
|
|
80639
80755
|
}
|
|
80640
80756
|
this.db.transaction((tx) => {
|
|
80641
80757
|
for (const id of staleIds) {
|
|
80642
|
-
tx.delete(insights).where(
|
|
80758
|
+
tx.delete(insights).where(eq64(insights.id, id)).run();
|
|
80643
80759
|
}
|
|
80644
80760
|
for (const insight of gbpInsights) {
|
|
80645
80761
|
const parsed = parseGbpInsightId(insight.id);
|
|
@@ -80725,7 +80841,7 @@ var IntelligenceService = class {
|
|
|
80725
80841
|
* create per run + aggregate). DB is left untouched.
|
|
80726
80842
|
*/
|
|
80727
80843
|
backfill(projectName, opts, onProgress) {
|
|
80728
|
-
const project = this.db.select().from(projects).where(
|
|
80844
|
+
const project = this.db.select().from(projects).where(eq64(projects.name, projectName)).get();
|
|
80729
80845
|
if (!project) {
|
|
80730
80846
|
throw new Error(`Project "${projectName}" not found`);
|
|
80731
80847
|
}
|
|
@@ -80737,7 +80853,7 @@ var IntelligenceService = class {
|
|
|
80737
80853
|
}
|
|
80738
80854
|
sinceTimestamp = parsed;
|
|
80739
80855
|
}
|
|
80740
|
-
const allRuns = this.db.select().from(runs).where(
|
|
80856
|
+
const allRuns = this.db.select().from(runs).where(and53(...analyzableRunPredicates(project.id))).orderBy(asc12(runs.finishedAt)).all();
|
|
80741
80857
|
const measuredRunIds = this.runIdsWithSnapshots(allRuns.map((r) => r.id));
|
|
80742
80858
|
const measuredRuns = allRuns.filter((r) => measuredRunIds.has(r.id));
|
|
80743
80859
|
let startIdx = 0;
|
|
@@ -80814,7 +80930,7 @@ var IntelligenceService = class {
|
|
|
80814
80930
|
return { processed, skipped, totalInsights };
|
|
80815
80931
|
}
|
|
80816
80932
|
loadTrackedCompetitors(projectId) {
|
|
80817
|
-
return this.db.select({ domain: competitors.domain }).from(competitors).where(
|
|
80933
|
+
return this.db.select({ domain: competitors.domain }).from(competitors).where(eq64(competitors.projectId, projectId)).all().map((r) => r.domain);
|
|
80818
80934
|
}
|
|
80819
80935
|
/**
|
|
80820
80936
|
* Which of `runIds` actually wrote query snapshots. One grouped read, so
|
|
@@ -80845,15 +80961,15 @@ var IntelligenceService = class {
|
|
|
80845
80961
|
}
|
|
80846
80962
|
persistResult(result, runId, projectId) {
|
|
80847
80963
|
const previouslyDismissed = /* @__PURE__ */ new Set();
|
|
80848
|
-
const existingInsights = this.db.select({ query: insights.query, provider: insights.provider, type: insights.type, dismissed: insights.dismissed }).from(insights).where(
|
|
80964
|
+
const existingInsights = this.db.select({ query: insights.query, provider: insights.provider, type: insights.type, dismissed: insights.dismissed }).from(insights).where(eq64(insights.runId, runId)).all();
|
|
80849
80965
|
for (const row of existingInsights) {
|
|
80850
80966
|
if (row.dismissed) {
|
|
80851
80967
|
previouslyDismissed.add(`${row.query}:${row.provider}:${row.type}`);
|
|
80852
80968
|
}
|
|
80853
80969
|
}
|
|
80854
80970
|
this.db.transaction((tx) => {
|
|
80855
|
-
tx.delete(insights).where(
|
|
80856
|
-
tx.delete(healthSnapshots).where(
|
|
80971
|
+
tx.delete(insights).where(eq64(insights.runId, runId)).run();
|
|
80972
|
+
tx.delete(healthSnapshots).where(eq64(healthSnapshots.runId, runId)).run();
|
|
80857
80973
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
80858
80974
|
for (const insight of result.insights) {
|
|
80859
80975
|
const wasDismissed = previouslyDismissed.has(`${insight.query}:${insight.provider}:${insight.type}`);
|
|
@@ -80873,7 +80989,7 @@ var IntelligenceService = class {
|
|
|
80873
80989
|
}).run();
|
|
80874
80990
|
}
|
|
80875
80991
|
tx.insert(healthSnapshots).values({
|
|
80876
|
-
id:
|
|
80992
|
+
id: crypto50.randomUUID(),
|
|
80877
80993
|
projectId,
|
|
80878
80994
|
runId,
|
|
80879
80995
|
overallCitedRate: String(result.health.overallCitedRate),
|
|
@@ -80900,8 +81016,8 @@ var IntelligenceService = class {
|
|
|
80900
81016
|
clicks: gscSearchData.clicks,
|
|
80901
81017
|
impressions: gscSearchData.impressions,
|
|
80902
81018
|
position: gscSearchData.position
|
|
80903
|
-
}).from(gscSearchData).where(
|
|
80904
|
-
|
|
81019
|
+
}).from(gscSearchData).where(and53(
|
|
81020
|
+
eq64(gscSearchData.projectId, projectId),
|
|
80905
81021
|
gte16(gscSearchData.date, window.startDate),
|
|
80906
81022
|
lte13(gscSearchData.date, window.endDate)
|
|
80907
81023
|
)).all();
|
|
@@ -80954,17 +81070,17 @@ var IntelligenceService = class {
|
|
|
80954
81070
|
const key = row.query.toLowerCase();
|
|
80955
81071
|
gscImpressionsByQuery.set(key, (gscImpressionsByQuery.get(key) ?? 0) + row.impressions);
|
|
80956
81072
|
}
|
|
80957
|
-
const projectRow = this.db.select({ locations: projects.locations }).from(projects).where(
|
|
81073
|
+
const projectRow = this.db.select({ locations: projects.locations }).from(projects).where(eq64(projects.id, projectId)).get();
|
|
80958
81074
|
const locationCount = Math.max(
|
|
80959
81075
|
1,
|
|
80960
81076
|
(projectRow?.locations ?? []).length
|
|
80961
81077
|
);
|
|
80962
81078
|
const ROWS_PER_GROUP_BUDGET = Math.max(2, locationCount);
|
|
80963
81079
|
const recentRunRows = this.db.select({ id: runs.id, createdAt: runs.createdAt }).from(runs).where(
|
|
80964
|
-
|
|
80965
|
-
|
|
80966
|
-
|
|
80967
|
-
or14(
|
|
81080
|
+
and53(
|
|
81081
|
+
eq64(runs.projectId, projectId),
|
|
81082
|
+
eq64(runs.kind, RunKinds["answer-visibility"]),
|
|
81083
|
+
or14(eq64(runs.status, "completed"), eq64(runs.status, "partial")),
|
|
80968
81084
|
// Defensive — see top of file.
|
|
80969
81085
|
ne8(runs.trigger, RunTriggers.probe)
|
|
80970
81086
|
)
|
|
@@ -80984,7 +81100,7 @@ var IntelligenceService = class {
|
|
|
80984
81100
|
const haveHistory = recentRunIds.length > 0;
|
|
80985
81101
|
const priorRegressionsByPair = /* @__PURE__ */ new Map();
|
|
80986
81102
|
if (haveHistory) {
|
|
80987
|
-
const priorRows = this.db.select({ query: insights.query, provider: insights.provider, runId: insights.runId }).from(insights).where(
|
|
81103
|
+
const priorRows = this.db.select({ query: insights.query, provider: insights.provider, runId: insights.runId }).from(insights).where(and53(eq64(insights.type, "regression"), inArray23(insights.runId, recentRunIds))).all();
|
|
80988
81104
|
const regressionGroups = /* @__PURE__ */ new Map();
|
|
80989
81105
|
for (const row of priorRows) {
|
|
80990
81106
|
if (!row.runId) continue;
|
|
@@ -81013,7 +81129,7 @@ var IntelligenceService = class {
|
|
|
81013
81129
|
});
|
|
81014
81130
|
}
|
|
81015
81131
|
buildRunData(runId, projectId, completedAt, location = null, trackedCompetitors = []) {
|
|
81016
|
-
const projectDomainRow = this.db.select({ canonicalDomain: projects.canonicalDomain, ownedDomains: projects.ownedDomains }).from(projects).where(
|
|
81132
|
+
const projectDomainRow = this.db.select({ canonicalDomain: projects.canonicalDomain, ownedDomains: projects.ownedDomains }).from(projects).where(eq64(projects.id, projectId)).get();
|
|
81017
81133
|
const projectDomains = projectDomainRow ? effectiveDomains({
|
|
81018
81134
|
canonicalDomain: projectDomainRow.canonicalDomain,
|
|
81019
81135
|
ownedDomains: projectDomainRow.ownedDomains
|
|
@@ -81031,7 +81147,7 @@ var IntelligenceService = class {
|
|
|
81031
81147
|
citedDomains: querySnapshots.citedDomains,
|
|
81032
81148
|
rawResponse: querySnapshots.rawResponse,
|
|
81033
81149
|
snapshotLocation: querySnapshots.location
|
|
81034
|
-
}).from(querySnapshots).leftJoin(queries,
|
|
81150
|
+
}).from(querySnapshots).leftJoin(queries, eq64(querySnapshots.queryId, queries.id)).where(eq64(querySnapshots.runId, runId)).all();
|
|
81035
81151
|
const snapshots = [];
|
|
81036
81152
|
let orphanCount = 0;
|
|
81037
81153
|
for (const r of rows) {
|
|
@@ -81225,6 +81341,7 @@ export {
|
|
|
81225
81341
|
generateWranglerToml,
|
|
81226
81342
|
executeDiscovery,
|
|
81227
81343
|
markSessionFailed,
|
|
81344
|
+
captureSimpleMeasurementDefinition,
|
|
81228
81345
|
apiRoutes,
|
|
81229
81346
|
createLogger,
|
|
81230
81347
|
IntelligenceService
|
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
loadConfig,
|
|
12
12
|
loadConfigRaw,
|
|
13
13
|
saveConfigPatch
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-3SFCUICM.js";
|
|
15
15
|
import {
|
|
16
16
|
CC_CACHE_DIR,
|
|
17
17
|
DUCKDB_SPEC,
|
|
@@ -40,6 +40,7 @@ import {
|
|
|
40
40
|
bingCoverageSnapshots,
|
|
41
41
|
bingUrlInspections,
|
|
42
42
|
buildLocationProfileFields,
|
|
43
|
+
captureSimpleMeasurementDefinition,
|
|
43
44
|
ccReleasePaths,
|
|
44
45
|
ccReleaseSyncs,
|
|
45
46
|
classifyAiUserFetch,
|
|
@@ -157,7 +158,7 @@ import {
|
|
|
157
158
|
siteCrawlSnapshots,
|
|
158
159
|
toAlertView,
|
|
159
160
|
usageCounters
|
|
160
|
-
} from "./chunk-
|
|
161
|
+
} from "./chunk-7ATZMDG2.js";
|
|
161
162
|
import {
|
|
162
163
|
AGENT_MEMORY_VALUE_MAX_BYTES,
|
|
163
164
|
AGENT_PROVIDER_IDS,
|
|
@@ -214,8 +215,10 @@ import {
|
|
|
214
215
|
agentMemoryUpsertRequestSchema,
|
|
215
216
|
authInvalid,
|
|
216
217
|
authRequired,
|
|
218
|
+
brandLabelFromDomain,
|
|
217
219
|
bucketOnboardingCount,
|
|
218
220
|
buildRunErrorFromMessages,
|
|
221
|
+
buildSimpleMeasurementDefinition,
|
|
219
222
|
canonicalizeGtmAccountId,
|
|
220
223
|
canonicalizeGtmContainerId,
|
|
221
224
|
canonicalizeGtmResourceSelection,
|
|
@@ -296,7 +299,7 @@ import {
|
|
|
296
299
|
validationError,
|
|
297
300
|
winnabilityClassLabel,
|
|
298
301
|
withRetry
|
|
299
|
-
} from "./chunk-
|
|
302
|
+
} from "./chunk-DU5Q5ZOX.js";
|
|
300
303
|
|
|
301
304
|
// src/telemetry.ts
|
|
302
305
|
import crypto from "crypto";
|
|
@@ -6860,6 +6863,37 @@ var JobRunner = class {
|
|
|
6860
6863
|
}
|
|
6861
6864
|
}
|
|
6862
6865
|
};
|
|
6866
|
+
if (existingRun.kind === RunKinds["answer-visibility"] && existingRun.trigger !== RunTriggers.probe && existingRun.measurementPlanVersionId === null) {
|
|
6867
|
+
const definition = buildSimpleMeasurementDefinition({
|
|
6868
|
+
capturedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
6869
|
+
identity: {
|
|
6870
|
+
displayName: project.displayName,
|
|
6871
|
+
aliases: project.aliases,
|
|
6872
|
+
canonicalDomain: project.canonicalDomain,
|
|
6873
|
+
ownedDomains: project.ownedDomains
|
|
6874
|
+
},
|
|
6875
|
+
country: project.country,
|
|
6876
|
+
language: project.language,
|
|
6877
|
+
location: runLocation ?? null,
|
|
6878
|
+
engines: activeProviders.map(({ adapter, config }) => ({
|
|
6879
|
+
provider: adapter.name,
|
|
6880
|
+
requestedModel: config.model ?? null
|
|
6881
|
+
})),
|
|
6882
|
+
// The legacy competitors table has domains only. Freeze the exact
|
|
6883
|
+
// identity we actually dispatched with so later reporting never
|
|
6884
|
+
// borrows renamed or newly added competitors from live project state.
|
|
6885
|
+
competitors: projectCompetitors.map((competitor) => {
|
|
6886
|
+
const label = brandLabelFromDomain(competitor.domain) || competitor.domain;
|
|
6887
|
+
return { domain: competitor.domain, label, aliases: [label] };
|
|
6888
|
+
}),
|
|
6889
|
+
queries: projectQueries.map((query) => ({
|
|
6890
|
+
queryId: query.id,
|
|
6891
|
+
queryText: query.query,
|
|
6892
|
+
provenance: query.provenance ?? null
|
|
6893
|
+
}))
|
|
6894
|
+
});
|
|
6895
|
+
captureSimpleMeasurementDefinition(this.db, { projectId, runId, definition });
|
|
6896
|
+
}
|
|
6863
6897
|
providerCallStart = Date.now();
|
|
6864
6898
|
if (planExecution) {
|
|
6865
6899
|
const plan = planExecution;
|
|
@@ -11304,15 +11338,17 @@ async function executeSiteAudit(db, runId, projectId, opts = {}) {
|
|
|
11304
11338
|
indexabilityVersion: crawlSummary.indexabilityRulesetVersion,
|
|
11305
11339
|
linkScoreVersion: crawlSummary.linkScoreAlgorithmVersion,
|
|
11306
11340
|
effectiveOptions: {
|
|
11341
|
+
// Null, never absent: a reader must be able to tell "the operator set
|
|
11342
|
+
// no edge budget and the engine derived one" from a missing field.
|
|
11307
11343
|
mode: "summary",
|
|
11308
11344
|
sitemapUrl: opts.sitemapUrl ?? null,
|
|
11309
11345
|
maxPages,
|
|
11310
|
-
maxEdges,
|
|
11346
|
+
maxEdges: maxEdges ?? null,
|
|
11311
11347
|
maxDepth: opts.maxDepth ?? null,
|
|
11312
11348
|
checkDeadLinks: opts.checkDeadLinks ?? false
|
|
11313
11349
|
},
|
|
11314
11350
|
pageBudget: maxPages,
|
|
11315
|
-
edgeBudget: maxEdges,
|
|
11351
|
+
edgeBudget: maxEdges ?? null,
|
|
11316
11352
|
maxDepth: opts.maxDepth ?? null,
|
|
11317
11353
|
checkDeadLinks: opts.checkDeadLinks ?? false,
|
|
11318
11354
|
complete: crawlSummary.complete,
|
|
@@ -11867,7 +11903,7 @@ function readStoredGroundingSources(rawResponse) {
|
|
|
11867
11903
|
return result;
|
|
11868
11904
|
}
|
|
11869
11905
|
async function backfillInsightsCommand(project, opts) {
|
|
11870
|
-
const { IntelligenceService: IntelligenceService2 } = await import("./intelligence-service-
|
|
11906
|
+
const { IntelligenceService: IntelligenceService2 } = await import("./intelligence-service-BQIIWWQJ.js");
|
|
11871
11907
|
const config = loadConfig();
|
|
11872
11908
|
const db = createClient(config.database);
|
|
11873
11909
|
migrate(db);
|