@ainyc/canonry 4.190.1 → 4.191.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/agent-workspace/skills/canonry/SKILL.md +124 -216
- package/assets/assets/{AuditHistoryPanel-Dob_85ay.js → AuditHistoryPanel-C2dvjYNh.js} +1 -1
- package/assets/assets/{BacklinksPage-BDm4gQsa.js → BacklinksPage-D1yPQtfF.js} +1 -1
- package/assets/assets/{HistoryPage-BUGJKNWJ.js → HistoryPage-DOEa7naA.js} +1 -1
- package/assets/assets/{MeasurementPropertyPage-H2g4VdcA.js → MeasurementPropertyPage-D-O8vnMS.js} +1 -1
- package/assets/assets/ProjectPage-DqTCcimz.js +8 -0
- package/assets/assets/{RunRow-Cja3vahD.js → RunRow-BO7lyC1C.js} +1 -1
- package/assets/assets/{RunsPage-BdVfLW9Z.js → RunsPage-DHSWfTav.js} +1 -1
- package/assets/assets/{SettingsPage-Xw9rdDPd.js → SettingsPage-oiJdhiq0.js} +1 -1
- package/assets/assets/SiteHealthSection-gVdylFY-.js +4 -0
- package/assets/assets/{TrafficPage-D5ZqJrJm.js → TrafficPage-YIdwRpQh.js} +1 -1
- package/assets/assets/{TrafficSourceDetailPage-DB5V8cdH.js → TrafficSourceDetailPage-B4Cop6ox.js} +1 -1
- package/assets/assets/{extract-error-message-lzuarNEg.js → extract-error-message-XavUZNf3.js} +1 -1
- package/assets/assets/{index-BjjM151x.css → index-BtTEcbcB.css} +1 -1
- package/assets/assets/{index-YVHujfy1.js → index-njfYnO22.js} +25 -25
- package/assets/assets/{react-sigma_core.esm.min-Ddu-c40B.js → react-sigma_core.esm.min-V7giUpEn.js} +1 -1
- package/assets/index.html +2 -2
- package/dist/{chunk-32QBVRMN.js → chunk-2A7E5TDU.js} +209 -29
- package/dist/{chunk-ROPJUNQN.js → chunk-KBUV3HGS.js} +55 -9
- package/dist/{chunk-2II4ZMMH.js → chunk-WSD5J6O4.js} +2 -2
- package/dist/{chunk-BE366UCM.js → chunk-XI6FN52S.js} +33 -13
- package/dist/{chunk-ECPN4OUR.js → chunk-ZK4FJDCH.js} +217 -48
- package/dist/cli.js +56 -5
- package/dist/index.js +4 -4
- package/dist/{intelligence-service-QCKX2W4G.js → intelligence-service-EVRWZHDG.js} +2 -2
- package/dist/mcp.js +13 -8
- package/package.json +9 -9
- package/assets/assets/ProjectPage-d7iOSkrd.js +0 -8
- package/assets/assets/SiteHealthSection-CjioXMWy.js +0 -4
package/assets/assets/{react-sigma_core.esm.min-Ddu-c40B.js → react-sigma_core.esm.min-V7giUpEn.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-gVdylFY-.js";import"./index-njfYnO22.js";import"./vendor-radix-BpmvLvpp.js";import"./vendor-recharts-FA0uySU7.js";import"./vendor-lucide-dNHw1I5G.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,14 +12,14 @@
|
|
|
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-njfYnO22.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">
|
|
19
19
|
<link rel="modulepreload" crossorigin href="./assets/vendor-lucide-dNHw1I5G.js">
|
|
20
20
|
<link rel="modulepreload" crossorigin href="./assets/vendor-markdown-9tTeP8v7.js">
|
|
21
21
|
<link rel="modulepreload" crossorigin href="./assets/vendor-yaml-GWJz5H2G.js">
|
|
22
|
-
<link rel="stylesheet" crossorigin href="./assets/index-
|
|
22
|
+
<link rel="stylesheet" crossorigin href="./assets/index-BtTEcbcB.css">
|
|
23
23
|
</head>
|
|
24
24
|
<body>
|
|
25
25
|
<div id="root"></div>
|
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
DISCOVERY_MAX_PROBES_CAP,
|
|
7
7
|
DISCOVERY_PROBE_CONCURRENCY_CAP,
|
|
8
8
|
GOOGLE_MARKETING_STORED_SNAPSHOT_PAGE_MAX,
|
|
9
|
+
RESEARCH_RUN_SCOPE,
|
|
9
10
|
SKILL_MANIFEST_FILENAME,
|
|
10
11
|
SkillsClients,
|
|
11
12
|
adsActivateTreeRequestSchema,
|
|
@@ -36,6 +37,7 @@ import {
|
|
|
36
37
|
gaMeasurementHostScopeSchema,
|
|
37
38
|
googleAdsMetricsWindowSchema,
|
|
38
39
|
gscPerformanceOrderBySchema,
|
|
40
|
+
isReadOnlyKey,
|
|
39
41
|
keywordBatchRequestSchema,
|
|
40
42
|
keywordGenerateRequestSchema,
|
|
41
43
|
measurementChangesQuerySchema,
|
|
@@ -88,7 +90,9 @@ import {
|
|
|
88
90
|
queryTrackingCommitRequestSchema,
|
|
89
91
|
queryTrackingPreviewRequestSchema,
|
|
90
92
|
reportPeriodSchema,
|
|
93
|
+
researchBatchCreateSchema,
|
|
91
94
|
researchRunCreateSchema,
|
|
95
|
+
restrictedWriteScopes,
|
|
92
96
|
resultsClearRequestSchema,
|
|
93
97
|
runTriggerRequestSchema,
|
|
94
98
|
schedulableRunKindSchema,
|
|
@@ -100,7 +104,7 @@ import {
|
|
|
100
104
|
trafficEventKindSchema,
|
|
101
105
|
trafficSeriesGranularitySchema,
|
|
102
106
|
visibilityReportRequestSchema
|
|
103
|
-
} from "./chunk-
|
|
107
|
+
} from "./chunk-KBUV3HGS.js";
|
|
104
108
|
|
|
105
109
|
// src/cli-error.ts
|
|
106
110
|
function isMachineFormat(format) {
|
|
@@ -2316,6 +2320,22 @@ var postApiV1ProjectsByNameResearchRuns = (options) => {
|
|
|
2316
2320
|
}
|
|
2317
2321
|
});
|
|
2318
2322
|
};
|
|
2323
|
+
var postApiV1ProjectsByNameResearchBatches = (options) => {
|
|
2324
|
+
return (options.client ?? client).post({
|
|
2325
|
+
security: [
|
|
2326
|
+
{
|
|
2327
|
+
scheme: "bearer",
|
|
2328
|
+
type: "http"
|
|
2329
|
+
}
|
|
2330
|
+
],
|
|
2331
|
+
url: "/api/v1/projects/{name}/research/batches",
|
|
2332
|
+
...options,
|
|
2333
|
+
headers: {
|
|
2334
|
+
"Content-Type": "application/json",
|
|
2335
|
+
...options.headers
|
|
2336
|
+
}
|
|
2337
|
+
});
|
|
2338
|
+
};
|
|
2319
2339
|
var getApiV1ProjectsByNameQueryTracking = (options) => {
|
|
2320
2340
|
return (options.client ?? client).get({
|
|
2321
2341
|
security: [
|
|
@@ -8093,6 +8113,14 @@ var ApiClient = class {
|
|
|
8093
8113
|
})
|
|
8094
8114
|
);
|
|
8095
8115
|
}
|
|
8116
|
+
/** Atomically accept reviewed destinations with a shared retry identity. */
|
|
8117
|
+
async startResearchBatch(project, request) {
|
|
8118
|
+
return this.invoke(() => postApiV1ProjectsByNameResearchBatches({
|
|
8119
|
+
client: this.heyClient,
|
|
8120
|
+
path: { name: project },
|
|
8121
|
+
body: request
|
|
8122
|
+
}));
|
|
8123
|
+
}
|
|
8096
8124
|
async listResearchRuns(project, opts) {
|
|
8097
8125
|
return this.invoke(
|
|
8098
8126
|
() => getApiV1ProjectsByNameResearchRuns({
|
|
@@ -9559,6 +9587,10 @@ var researchRunsListInputSchema = z4.object({
|
|
|
9559
9587
|
project: projectNameSchema,
|
|
9560
9588
|
limit: z4.number().int().positive().max(100).optional().describe("Max saved research runs returned. Default 20.")
|
|
9561
9589
|
});
|
|
9590
|
+
var researchBatchStartInputSchema = z4.object({
|
|
9591
|
+
project: projectNameSchema,
|
|
9592
|
+
request: researchBatchCreateSchema.describe("Reviewed concrete runs, at most 20 destinations and 50 total queries. Specify provider, model and location (null means none) for every run. Pin the plan revision for each market or Property. Reuse the same idempotencyKey and unchanged request after an uncertain response.")
|
|
9593
|
+
});
|
|
9562
9594
|
var researchRunIdInputSchema = z4.object({
|
|
9563
9595
|
project: projectNameSchema,
|
|
9564
9596
|
runId: z4.string().min(1).describe("Research run ID returned by canonry_research_run_start.")
|
|
@@ -11501,6 +11533,7 @@ var canonryMcpTools = [
|
|
|
11501
11533
|
}),
|
|
11502
11534
|
defineTool({
|
|
11503
11535
|
name: "canonry_research_run_start",
|
|
11536
|
+
requiredScope: RESEARCH_RUN_SCOPE,
|
|
11504
11537
|
title: "Start research query run",
|
|
11505
11538
|
description: "Run final free-form queries once each against one API provider, with an optional exact model, location, or one configured market or Property destination. Scope never changes query text or fans out a group. Optional template provenance records the source template ID and version; callers must submit the fully expanded, editable final query text. Results retain that destination and provenance for later inspection. This does not add any query to the tracked basket or affect overview tracking.",
|
|
11506
11539
|
access: "write",
|
|
@@ -11510,6 +11543,18 @@ var canonryMcpTools = [
|
|
|
11510
11543
|
openApiOperations: ["POST /api/v1/projects/{name}/research/runs"],
|
|
11511
11544
|
handler: (client2, input) => client2.startResearchRun(input.project, input.request)
|
|
11512
11545
|
}),
|
|
11546
|
+
defineTool({
|
|
11547
|
+
name: "canonry_research_batch_start",
|
|
11548
|
+
requiredScope: RESEARCH_RUN_SCOPE,
|
|
11549
|
+
title: "Start reviewed research across destinations",
|
|
11550
|
+
description: "Accept a reviewed research batch across explicit markets, Properties, or configured locations. Submit fully expanded, editable final queries with explicit provider/model/location for each destination; the API does not expand patterns or groups. All runs are saved together or none are saved, then processed independently. The required idempotencyKey prevents duplicate work on retries; changed input with the same key conflicts. Each run retains its scope, location and optional pattern provenance. Uses paid answer engines, never adds tracked queries or affects visibility measurements.",
|
|
11551
|
+
access: "write",
|
|
11552
|
+
tier: "discovery",
|
|
11553
|
+
inputSchema: researchBatchStartInputSchema,
|
|
11554
|
+
annotations: writeAnnotations({ idempotentHint: true, openWorldHint: true }),
|
|
11555
|
+
openApiOperations: ["POST /api/v1/projects/{name}/research/batches"],
|
|
11556
|
+
handler: (client2, input) => client2.startResearchBatch(input.project, input.request)
|
|
11557
|
+
}),
|
|
11513
11558
|
defineTool({
|
|
11514
11559
|
name: "canonry_research_runs_list",
|
|
11515
11560
|
title: "List research query runs",
|
|
@@ -12600,7 +12645,7 @@ var DynamicToolCatalog = class {
|
|
|
12600
12645
|
loadedToolkits: [...this.loaded].sort(),
|
|
12601
12646
|
coreTools: this.entries.filter((entry) => entry.tool.tier === "core").map((entry) => entry.tool.name),
|
|
12602
12647
|
toolkits: CANONRY_MCP_TOOLKITS.map((toolkit) => this.toolkitEntry(toolkit)).filter((entry) => entry.toolCount > 0),
|
|
12603
|
-
usage: "Call canonry_load_toolkit with one of the toolkit names listed in `toolkits[].name` to register its tools for the rest of this session. Wait for its response before calling any newly enabled tool."
|
|
12648
|
+
usage: this.eager ? "All tools available on this connection are already loaded. Use their listed schemas; tool visibility does not grant server permissions." : "Call canonry_load_toolkit with one of the toolkit names listed in `toolkits[].name` to register its tools for the rest of this session. Wait for its response before calling any newly enabled tool."
|
|
12604
12649
|
};
|
|
12605
12650
|
}
|
|
12606
12651
|
toolkitEntry(toolkit) {
|
|
@@ -12639,28 +12684,139 @@ var DynamicToolCatalog = class {
|
|
|
12639
12684
|
}
|
|
12640
12685
|
};
|
|
12641
12686
|
|
|
12687
|
+
// src/mcp/operations-guide.generated.ts
|
|
12688
|
+
var OPERATIONS_GUIDE = {
|
|
12689
|
+
"guideVersion": "v1",
|
|
12690
|
+
"operationsGuideUrl": "https://github.com/Canonry/canonry/blob/main/docs/agent-operations/v1.md",
|
|
12691
|
+
"resourceUri": "canonry://agent-operations/v1",
|
|
12692
|
+
"initialize": 'Canonry tracks how AI answer engines mention brands and cite domains.\nStart with canonry_help({intent:"status"}), or name your intended workflow. It returns a small route of currently available tools and approval boundaries. Follow its stored-evidence reads before proposing action. No skill, resource reader, plugin installation, or local CLI is required for connected MCP clients. A host-native Canonry skill, if installed, is optional additional guidance.\nmentioned = brand in answer TEXT; cited = domain in SOURCE links. Never compute one from the other. A null answerMentioned means not checked, not false. No recorded sweep means no measured figure.\nGet explicit approval for live provider reads, sweeps, probes, research, syncs, and writes, bounded to the target and requested work. A readOnlyHint or GET is not proof of a free operation. Live ads reads include canonry_ads_account, canonry_ads_geo_search, canonry_ads_live_delivery, canonry_ads_conversion_pixels, canonry_ads_conversion_event_settings. Google live reads/syncs include canonry_google_ads_customers, canonry_gtm_accounts, canonry_gtm_containers, canonry_gtm_workspaces, canonry_google_ads_sync, canonry_gtm_sync.\nHelp and skills grant no permissions. The server enforces authority. On missing tools or 403, report the boundary; do not switch credentials or endpoints to bypass it. Hosted catalogs are fixed; only use canonry_load_toolkit when help explicitly offers it.\n',
|
|
12693
|
+
"approvalBoundary": [
|
|
12694
|
+
"provider reads",
|
|
12695
|
+
"sweeps",
|
|
12696
|
+
"writes"
|
|
12697
|
+
],
|
|
12698
|
+
"approvalRule": "Get explicit approval for the exact target, action, and bounded provider work before crossing a boundary. Existing approval covers only its stated scope; stop on refusal or ambiguous results.",
|
|
12699
|
+
"authority": "Guidance and tool visibility are not permission grants. Server-side roles, scopes, project boundaries, quotas, and approval receipts remain authoritative. Never bypass a refusal with different credentials or endpoints.",
|
|
12700
|
+
"workflows": {
|
|
12701
|
+
"status": {
|
|
12702
|
+
"keywords": [
|
|
12703
|
+
"status",
|
|
12704
|
+
"overview",
|
|
12705
|
+
"health"
|
|
12706
|
+
],
|
|
12707
|
+
"next": [
|
|
12708
|
+
"canonry_projects_list",
|
|
12709
|
+
"canonry_project_overview"
|
|
12710
|
+
],
|
|
12711
|
+
"guidance": "Select an accessible project, then read its stored overview. Report freshness and missing evidence; do not start a sweep to fill a gap."
|
|
12712
|
+
},
|
|
12713
|
+
"diagnose": {
|
|
12714
|
+
"keywords": [
|
|
12715
|
+
"diagnose",
|
|
12716
|
+
"diagnosis",
|
|
12717
|
+
"regression",
|
|
12718
|
+
"changed",
|
|
12719
|
+
"change",
|
|
12720
|
+
"troubleshoot"
|
|
12721
|
+
],
|
|
12722
|
+
"next": [
|
|
12723
|
+
"canonry_projects_list",
|
|
12724
|
+
"canonry_project_overview",
|
|
12725
|
+
"canonry_project_history"
|
|
12726
|
+
],
|
|
12727
|
+
"guidance": "Compare stored history in the same project, period, provider/model, location, and query-class scope. Separate observed changes from possible causes; propose any live verification for approval."
|
|
12728
|
+
},
|
|
12729
|
+
"measurement": {
|
|
12730
|
+
"keywords": [
|
|
12731
|
+
"measurement",
|
|
12732
|
+
"measure",
|
|
12733
|
+
"portfolio",
|
|
12734
|
+
"property",
|
|
12735
|
+
"target",
|
|
12736
|
+
"query",
|
|
12737
|
+
"queries",
|
|
12738
|
+
"research"
|
|
12739
|
+
],
|
|
12740
|
+
"next": [
|
|
12741
|
+
"canonry_projects_list",
|
|
12742
|
+
"canonry_measurement_overview",
|
|
12743
|
+
"canonry_measurement_setup",
|
|
12744
|
+
"canonry_research_runs_list"
|
|
12745
|
+
],
|
|
12746
|
+
"guidance": "Inspect existing measurement before editing it. Preserve Simple versus Advanced scope, Property/Target identity, market, provider/model, and query class. Direct research submits final queries in one context; reviewed batches submit explicit destinations under one retry key. Expand patterns client-side: scope records a destination and never rewrites queries or fans out a group. Research is separate from tracking; publication does not authorize a sweep."
|
|
12747
|
+
},
|
|
12748
|
+
"integrations": {
|
|
12749
|
+
"keywords": [
|
|
12750
|
+
"integrations",
|
|
12751
|
+
"integration",
|
|
12752
|
+
"connect",
|
|
12753
|
+
"connection",
|
|
12754
|
+
"traffic",
|
|
12755
|
+
"gsc",
|
|
12756
|
+
"ga4",
|
|
12757
|
+
"ads",
|
|
12758
|
+
"gtm"
|
|
12759
|
+
],
|
|
12760
|
+
"next": [
|
|
12761
|
+
"canonry_projects_list",
|
|
12762
|
+
"canonry_project_get",
|
|
12763
|
+
"canonry_ga_status",
|
|
12764
|
+
"canonry_google_ads_status"
|
|
12765
|
+
],
|
|
12766
|
+
"guidance": "Inspect stored connection status and snapshot freshness. Use the currently listed specialist tools for stored evidence. Connecting, selecting resources, syncing, and live provider reads require scoped approval; never request credentials in chat."
|
|
12767
|
+
},
|
|
12768
|
+
"reports": {
|
|
12769
|
+
"keywords": [
|
|
12770
|
+
"reports",
|
|
12771
|
+
"report",
|
|
12772
|
+
"reporting",
|
|
12773
|
+
"summary"
|
|
12774
|
+
],
|
|
12775
|
+
"next": [
|
|
12776
|
+
"canonry_projects_list",
|
|
12777
|
+
"canonry_report"
|
|
12778
|
+
],
|
|
12779
|
+
"guidance": "Read the stored report for the selected project and period. Retain evidence dates, scope, sample sizes, missing data, and separate mention/citation signals; do not generate fresh runs implicitly."
|
|
12780
|
+
}
|
|
12781
|
+
},
|
|
12782
|
+
"markdown": "# Canonry Operations Guide v1\n\nCanonry is an agent-first AI visibility platform. MCP is the universal entry\npoint for connected agents. Host-native skills are optional upgrades, not a\nprerequisite or a permission mechanism.\n\n## Connect and choose a route\n\nRead the initialization guidance, then call `canonry_help` with an `intent`:\n`status`, `diagnose`, `measurement`, `integrations`, `reports`, or a short task\ndescription. Select an accessible project with `canonry_projects_list` before\nusing its exact name in project tools. Inspect each listed tool's input schema;\nhelp suggests tool names, not invented arguments or authorization.\n\nHelp returns a versioned, compact route: connection `mode`, available `next`\ntools, workflow guidance, approval boundaries, and this guide's URL. It performs\nno provider calls, reads no project data, and changes no permissions.\n`includeCatalog: true` additionally returns toolkit details when needed.\n\nHosted connections use a fixed catalog. Help only suggests tools offered by that\nconnection; it never tells a hosted agent to dynamically load a toolkit. A\nprogressive local stdio connection may return `loadToolkits`: call\n`canonry_load_toolkit` with one returned name, await it, then call help again.\nLoading only changes local tool discovery, never server authority.\n\nThe optional `canonry://agent-operations/v1` MCP resource contains this same\nguide. If the host cannot read resources or open links, continue through help.\nDo not install a plugin, local runtime, or skill merely to use connected MCP.\nAn installed Codex or Claude Canonry skill contains a generated copy of this\nguide plus links to host-native references. It does not replace runtime help.\n\n## Vocabulary and evidence\n\n- **Mentioned** means the brand appears in answer text. **Cited** means its\n domain appears in source links. Either, both, or neither can occur; never\n compute one signal from the other.\n- `answerMentioned: null` means not checked, not false. Missing runs and empty\n populations mean no measurement, not zero visibility.\n- Preserve project, time window, provider, requested/served model, location,\n sample size, and query class when comparing evidence. Use server-returned\n metrics; do not invent a score from incompatible populations.\n- Simple projects and Advanced portfolios share the workflow. For Advanced\n results, preserve Property, Target, market, plan revision, and class scope.\n Groups organize navigation; do not infer an unrequested fan-out.\n- Research is isolated evidence, not tracked measurement. A probe still spends\n quota and persists evidence but is excluded from normal tracking metrics.\n\n## Workflows\n\n**Status:** read the stored overview and freshness first. Say when evidence is\nmissing instead of silently creating it.\n\n**Diagnose:** inspect stored history and comparable evidence. Explain what\nchanged separately from why it might have changed. A hypothesis is not a\nmeasured cause. Propose bounded verification if stored evidence is insufficient.\n\n**Measurement:** inspect the existing setup and results before proposing edits.\nKeep research, query tracking, plan publication, and sweep execution separate.\nFor direct research, submit the final editable query text in one context. For a\nreviewed batch, submit each explicit destination with its final text and one\nidempotency key. Pattern substitution happens in the client before either\nrequest; choosing a market or Property records a destination only and never\nrewrites a query or creates an automatic fan-out. `research.run` does not\nauthorize saving patterns, changing tracking, publishing plans, or settings.\nUse a supported preview where available, inspect its exact destination and\nrevision, then seek approval for the actual change. A preview may itself require\nwrite permission; never treat a dry-run flag as a universal safety guarantee.\n\n**Integrations:** inspect stored connection state and snapshot freshness first.\nProvider configuration evidence does not prove a browser event fired or a\nconversion was recorded. Connection, resource selection, refresh/sync, and live\nreads are separate actions. Credentials belong in the operator's secure setup\nflow, never in chat, tool arguments, reports, or public guidance.\n\n**Reports:** use saved evidence for the requested period and scope. Keep mention\nand citation signals separate, include dates and sample sizes, and state missing\nor stale inputs. Preparing a report does not authorize new measurement.\n\n## Authority and approval\n\nStart with stored evidence. Before a live provider read, sweep, probe, research\nrun, sync, write, or externally visible action, obtain approval covering its\nexact target, action, and bounded work. Approval already given for that exact\noperation need not be asked for again, but does not extend to more projects,\nlarger batches, retries with new identities, or recurring work.\n\nHTTP GET and MCP `readOnlyHint` describe aspects of an operation, not its cost\nor permission. Provider discovery, account reads, and live diagnostics may\nconsume quota even when labeled read-only. If the tool's effect is unclear,\ninspect its description and request direction before calling it.\n\nAuthentication, role/scope checks, project restrictions, quotas, and guarded\napproval receipts are enforced by the server. Help, skills, resources, and tool\nvisibility cannot grant authority. Never change credentials, endpoints, or\nproject identifiers to work around a missing tool or a `403` response.\n\nFor guarded ads writes, inspect unresolved operation receipts before retrying.\nUse the receipt's supported recovery action; do not replay a mutation under a\nnew identity. An executor cannot create or widen its own human approval grant.\nOn ambiguous results, exhausted bounds, or refusal, stop and report what is\nknown and what permission or operator action is needed.\n\n## Version and source\n\nThis public, versioned document is the source for initialization guidance,\nintent routes, the optional resource, and generated Canonry `SKILL.md` files.\nGuide v1 may receive compatible clarifications; incompatible routing contracts\nrequire a new guide version. The running server's help describes its actual\ncatalog and remains usable without fetching this document.\n"
|
|
12783
|
+
};
|
|
12784
|
+
|
|
12785
|
+
// src/mcp/operations-guide.ts
|
|
12786
|
+
function operationsHelp(catalog, mode, intent = "", includeCatalog = false) {
|
|
12787
|
+
const workflows = Object.keys(OPERATIONS_GUIDE.workflows);
|
|
12788
|
+
const words = new Set(intent.toLowerCase().split(/[^a-z0-9-]+/));
|
|
12789
|
+
const workflow = workflows.find((name) => OPERATIONS_GUIDE.workflows[name].keywords.some((word) => words.has(word))) ?? "status";
|
|
12790
|
+
const route = OPERATIONS_GUIDE.workflows[workflow];
|
|
12791
|
+
const available = /* @__PURE__ */ new Set([...catalog.coreTools, ...catalog.toolkits.filter((t) => t.loaded).flatMap((t) => t.tools)]);
|
|
12792
|
+
const next = route.next.filter((name) => available.has(name)).slice(0, 4);
|
|
12793
|
+
if (next.length < 2 && available.has("canonry_project_overview") && !next.includes("canonry_project_overview")) {
|
|
12794
|
+
next.push("canonry_project_overview");
|
|
12795
|
+
}
|
|
12796
|
+
const wanted = route.next;
|
|
12797
|
+
const loadToolkits = mode === "stdio-progressive" ? catalog.toolkits.filter((t) => !t.loaded && t.tools.some((name) => wanted.includes(name))).map((t) => t.name) : [];
|
|
12798
|
+
return {
|
|
12799
|
+
guideVersion: OPERATIONS_GUIDE.guideVersion,
|
|
12800
|
+
mode,
|
|
12801
|
+
scope: catalog.scope,
|
|
12802
|
+
workflow,
|
|
12803
|
+
next,
|
|
12804
|
+
workflows,
|
|
12805
|
+
guidance: route.guidance,
|
|
12806
|
+
approvalBoundary: OPERATIONS_GUIDE.approvalBoundary,
|
|
12807
|
+
approvalRule: OPERATIONS_GUIDE.approvalRule,
|
|
12808
|
+
authority: OPERATIONS_GUIDE.authority,
|
|
12809
|
+
operationsGuideUrl: OPERATIONS_GUIDE.operationsGuideUrl,
|
|
12810
|
+
...loadToolkits.length ? { loadToolkits } : {},
|
|
12811
|
+
...includeCatalog ? catalog : {}
|
|
12812
|
+
};
|
|
12813
|
+
}
|
|
12814
|
+
|
|
12642
12815
|
// src/mcp/server.ts
|
|
12643
12816
|
function createCanonryMcpServer(options = {}) {
|
|
12644
12817
|
return createCanonryMcpServerWithCatalog(options).server;
|
|
12645
12818
|
}
|
|
12646
|
-
var SERVER_INSTRUCTIONS =
|
|
12647
|
-
|
|
12648
|
-
Load the "canonry" skill before operator work (project setup, integrations, traffic sources, sweeps, diagnosis). It carries the procedures and the failure modes; this text is only a pointer. Use "aero" for analyst work: regression diagnosis, reporting.
|
|
12649
|
-
|
|
12650
|
-
Two signals, never interchangeable:
|
|
12651
|
-
- mentioned = the brand appears in the answer TEXT the model wrote.
|
|
12652
|
-
- cited = the domain appears in the SOURCE links behind the answer.
|
|
12653
|
-
A model can do either, both or neither. Never compute one from the other, and never report a number for one under the other's name.
|
|
12654
|
-
|
|
12655
|
-
Sweeps, probes, and research runs spend provider quota and write rows. Get explicit approval before any run, apply, or other mutation.
|
|
12656
|
-
|
|
12657
|
-
Most reads are free. Five ads reads are NOT: canonry_ads_account, canonry_ads_geo_search, canonry_ads_live_delivery, canonry_ads_conversion_pixels and canonry_ads_conversion_event_settings call the provider live and spend against the advertiser account. They are marked read, so nothing in the tool list warns you. Get approval for those exactly as for a mutation.
|
|
12658
|
-
|
|
12659
|
-
Google Marketing also calls providers live. Get approval before canonry_google_ads_customers, canonry_gtm_accounts, canonry_gtm_containers, canonry_gtm_workspaces, canonry_google_ads_sync or canonry_gtm_sync.
|
|
12660
|
-
|
|
12661
|
-
A null answerMentioned means NOT CHECKED, not "not mentioned". Never coerce it to false.
|
|
12662
|
-
|
|
12663
|
-
If no sweep has run, say so. Never state a mention or citation figure that no run produced.`;
|
|
12819
|
+
var SERVER_INSTRUCTIONS = OPERATIONS_GUIDE.initialize;
|
|
12664
12820
|
function createCanonryMcpServerWithCatalog(options = {}) {
|
|
12665
12821
|
const clientFactory = options.clientFactory ?? createApiClient;
|
|
12666
12822
|
const client2 = clientFactory();
|
|
@@ -12673,7 +12829,7 @@ function createCanonryMcpServerWithCatalog(options = {}) {
|
|
|
12673
12829
|
});
|
|
12674
12830
|
server.validateToolInput = async (_tool, args) => args;
|
|
12675
12831
|
const entries = [];
|
|
12676
|
-
for (const registryTool of getCanonryMcpTools(scope, options.tiers)) {
|
|
12832
|
+
for (const registryTool of getCanonryMcpTools(scope, options.tiers, options.credentialScopes)) {
|
|
12677
12833
|
const tool = registryTool;
|
|
12678
12834
|
const handler = tool.handler;
|
|
12679
12835
|
const registered = server.registerTool(
|
|
@@ -12694,22 +12850,40 @@ function createCanonryMcpServerWithCatalog(options = {}) {
|
|
|
12694
12850
|
const eager = options.eager === true || options.tiers !== void 0;
|
|
12695
12851
|
const catalog = new DynamicToolCatalog(server, entries, scope, { eager });
|
|
12696
12852
|
catalog.applyInitialEnablement();
|
|
12697
|
-
|
|
12853
|
+
const mode = options.tiers !== void 0 ? "hosted-fixed-catalog" : eager ? "stdio-fixed-catalog" : "stdio-progressive";
|
|
12854
|
+
registerMetaTools(server, catalog, { includeToolkitLoader: options.tiers === void 0, mode });
|
|
12855
|
+
server.registerResource("canonry-agent-operations-v1", OPERATIONS_GUIDE.resourceUri, {
|
|
12856
|
+
title: "Canonry Operations Guide v1",
|
|
12857
|
+
description: "Optional public operations guidance. Use canonry_help when resources are unavailable.",
|
|
12858
|
+
mimeType: "text/markdown"
|
|
12859
|
+
}, async (uri) => ({ contents: [{ uri: uri.href, mimeType: "text/markdown", text: OPERATIONS_GUIDE.markdown }] }));
|
|
12698
12860
|
return { server, catalog };
|
|
12699
12861
|
}
|
|
12700
12862
|
var loadToolkitInputSchema = z5.object({
|
|
12701
12863
|
name: z5.enum(CANONRY_MCP_TOOLKIT_NAMES).describe("Toolkit name. List options with canonry_help.")
|
|
12702
12864
|
});
|
|
12865
|
+
var helpInputSchema = z5.object({
|
|
12866
|
+
intent: z5.string().max(200).optional().describe("Workflow (status, diagnose, measurement, integrations, reports) or a short task description."),
|
|
12867
|
+
includeCatalog: z5.boolean().optional().describe("Include full toolkit details. Omit for a compact, actionable route.")
|
|
12868
|
+
});
|
|
12703
12869
|
function registerMetaTools(server, catalog, opts) {
|
|
12704
12870
|
server.registerTool(
|
|
12705
12871
|
"canonry_help",
|
|
12706
12872
|
{
|
|
12707
|
-
title: "
|
|
12708
|
-
description: "
|
|
12709
|
-
inputSchema:
|
|
12710
|
-
annotations: { readOnlyHint: true }
|
|
12873
|
+
title: "Guide a Canonry workflow",
|
|
12874
|
+
description: "Start here: route an intent to available stored-evidence tools, workflow guidance, and approval boundaries. No provider calls or installation required. Optionally include full toolkit details.",
|
|
12875
|
+
inputSchema: helpInputSchema.shape,
|
|
12876
|
+
annotations: { readOnlyHint: true, idempotentHint: true, openWorldHint: false }
|
|
12711
12877
|
},
|
|
12712
|
-
async () =>
|
|
12878
|
+
async (input) => {
|
|
12879
|
+
try {
|
|
12880
|
+
const parsed = helpInputSchema.parse(input ?? {});
|
|
12881
|
+
const result = operationsHelp(catalog.helpResult(), opts.mode, parsed.intent, parsed.includeCatalog);
|
|
12882
|
+
return { ...jsonToolResult(result), structuredContent: result };
|
|
12883
|
+
} catch (error) {
|
|
12884
|
+
return errorToolResult(error);
|
|
12885
|
+
}
|
|
12886
|
+
}
|
|
12713
12887
|
);
|
|
12714
12888
|
if (!opts.includeToolkitLoader) return;
|
|
12715
12889
|
server.registerTool(
|
|
@@ -12726,8 +12900,14 @@ function registerMetaTools(server, catalog, opts) {
|
|
|
12726
12900
|
})
|
|
12727
12901
|
);
|
|
12728
12902
|
}
|
|
12729
|
-
function getCanonryMcpTools(scope = "all", tiers) {
|
|
12730
|
-
const
|
|
12903
|
+
function getCanonryMcpTools(scope = "all", tiers, credentialScopes) {
|
|
12904
|
+
const readOnly = scope === "read-only" || credentialScopes !== void 0 && isReadOnlyKey(credentialScopes);
|
|
12905
|
+
const restricted = credentialScopes && restrictedWriteScopes(credentialScopes);
|
|
12906
|
+
const byScope = readOnly ? canonryMcpTools.filter((tool) => tool.access === "read") : canonryMcpTools.filter((tool) => {
|
|
12907
|
+
if (!restricted || tool.access === "read") return true;
|
|
12908
|
+
if (tool.requiredScope && restricted.includes(tool.requiredScope)) return true;
|
|
12909
|
+
return restricted.some((grant) => grant !== RESEARCH_RUN_SCOPE) && tool.tier === "ads";
|
|
12910
|
+
});
|
|
12731
12911
|
if (!tiers) return byScope;
|
|
12732
12912
|
const wanted = new Set(tiers);
|
|
12733
12913
|
return byScope.filter((tool) => wanted.has(tool.tier));
|
|
@@ -53,7 +53,7 @@ function quotaExceeded(metric, details) {
|
|
|
53
53
|
function researchDailyLimitExceeded(projectName, limit, date) {
|
|
54
54
|
return new AppError(
|
|
55
55
|
"RESEARCH_DAILY_LIMIT_EXCEEDED",
|
|
56
|
-
`The
|
|
56
|
+
`The shared research run limit for this project has been reached today (${limit}). Try again tomorrow or ask an administrator.`,
|
|
57
57
|
429,
|
|
58
58
|
{ projectName, limit, date }
|
|
59
59
|
);
|
|
@@ -5645,6 +5645,7 @@ var auditLogEntrySchema = z9.object({
|
|
|
5645
5645
|
// ../contracts/src/scopes.ts
|
|
5646
5646
|
var READ_ONLY_SCOPE = "read";
|
|
5647
5647
|
var WILDCARD_SCOPE = "*";
|
|
5648
|
+
var RESEARCH_RUN_SCOPE = "research.run";
|
|
5648
5649
|
var PROJECTS_WRITE_SCOPE = "projects.write";
|
|
5649
5650
|
var ADS_WRITE_SCOPE = "ads.write";
|
|
5650
5651
|
var ADS_APPROVE_SCOPE = "ads.approve";
|
|
@@ -5652,7 +5653,16 @@ var ADS_ACTIVATE_SCOPE = "ads.activate";
|
|
|
5652
5653
|
var GOOGLE_MARKETING_LIVE_READ_SCOPE = "google-marketing.read-live";
|
|
5653
5654
|
var GOOGLE_MARKETING_WRITE_SCOPE = "google-marketing.write";
|
|
5654
5655
|
function grantsWrite(scope) {
|
|
5655
|
-
return scope === WILDCARD_SCOPE || scope === "write" || scope.endsWith(".write") || scope === ADS_APPROVE_SCOPE || scope === ADS_ACTIVATE_SCOPE;
|
|
5656
|
+
return scope === WILDCARD_SCOPE || scope === "write" || scope.endsWith(".write") || scope === ADS_APPROVE_SCOPE || scope === ADS_ACTIVATE_SCOPE || scope === RESEARCH_RUN_SCOPE;
|
|
5657
|
+
}
|
|
5658
|
+
function restrictedWriteScopes(scopes) {
|
|
5659
|
+
const writes = scopes.filter(grantsWrite);
|
|
5660
|
+
const restricted = /* @__PURE__ */ new Set([ADS_WRITE_SCOPE, ADS_APPROVE_SCOPE, ADS_ACTIVATE_SCOPE, RESEARCH_RUN_SCOPE]);
|
|
5661
|
+
return writes.length > 0 && writes.every((scope) => restricted.has(scope)) ? writes : null;
|
|
5662
|
+
}
|
|
5663
|
+
function intersectScopes(authority, requested) {
|
|
5664
|
+
const effective = authority.includes(WILDCARD_SCOPE) ? [...requested] : authority.filter((scope) => requested.includes(scope) || requested.includes(WILDCARD_SCOPE));
|
|
5665
|
+
return effective.length > 0 ? effective : [READ_ONLY_SCOPE];
|
|
5656
5666
|
}
|
|
5657
5667
|
function isReadOnlyKey(scopes) {
|
|
5658
5668
|
return scopes.includes(READ_ONLY_SCOPE) && !scopes.some(grantsWrite);
|
|
@@ -16225,6 +16235,8 @@ var ResearchRunStatuses = researchRunStatusSchema.enum;
|
|
|
16225
16235
|
var researchQueryStatusSchema = z56.enum(["queued", "running", "completed", "failed"]);
|
|
16226
16236
|
var ResearchQueryStatuses = researchQueryStatusSchema.enum;
|
|
16227
16237
|
var DEFAULT_VIEWER_RESEARCH_DAILY_RUN_LIMIT = 20;
|
|
16238
|
+
var MAX_RESEARCH_BATCH_RUNS = 20;
|
|
16239
|
+
var MAX_RESEARCH_BATCH_QUERIES = 50;
|
|
16228
16240
|
var researchScopeSelectionSchema = z56.object({
|
|
16229
16241
|
kind: z56.enum(["market", "property"]),
|
|
16230
16242
|
key: measurementV2StableKeySchema,
|
|
@@ -16247,12 +16259,16 @@ function deduplicateResearchQueries(queries) {
|
|
|
16247
16259
|
return true;
|
|
16248
16260
|
});
|
|
16249
16261
|
}
|
|
16250
|
-
function researchTemplateBindings(scope) {
|
|
16251
|
-
|
|
16252
|
-
return
|
|
16262
|
+
function researchTemplateBindings(scope, location) {
|
|
16263
|
+
const scopeBindings = !scope ? {} : scope.kind === "market" ? { market: scope.label, submarket: scope.label } : { property: scope.label, propertyBrand: scope.label };
|
|
16264
|
+
return location ? { ...scopeBindings, location: location.label } : scopeBindings;
|
|
16253
16265
|
}
|
|
16254
|
-
function expandResearchTemplate(template, scope) {
|
|
16255
|
-
const
|
|
16266
|
+
function expandResearchTemplate(template, scope, location) {
|
|
16267
|
+
const declared = new Set(template.variables);
|
|
16268
|
+
const placeholders = [...template.pattern.matchAll(/\{([^{}]+)\}/g)].map((match) => match[1]);
|
|
16269
|
+
const undeclared = [...new Set(placeholders.filter((variable) => !declared.has(variable)))];
|
|
16270
|
+
if (undeclared.length) throw validationError("The selected research template contains undeclared placeholders: " + undeclared.join(", "));
|
|
16271
|
+
const available = researchTemplateBindings(scope, location);
|
|
16256
16272
|
const unavailable = template.variables.filter((variable) => available[variable] === void 0);
|
|
16257
16273
|
if (unavailable.length) throw validationError("The selected research template requires unavailable bindings: " + unavailable.join(", "));
|
|
16258
16274
|
const bindings = Object.fromEntries(template.variables.map((variable) => [variable, available[variable]]));
|
|
@@ -16273,11 +16289,33 @@ var researchRunCreateSchema = z56.object({
|
|
|
16273
16289
|
}).superRefine((value, ctx) => {
|
|
16274
16290
|
if (value.model && !value.provider) ctx.addIssue({ code: z56.ZodIssueCode.custom, path: ["provider"], message: "provider is required when model is supplied" });
|
|
16275
16291
|
});
|
|
16292
|
+
var researchBatchScopeSelectionSchema = researchScopeSelectionSchema.extend({
|
|
16293
|
+
expectedPlanRevision: z56.number().int().positive()
|
|
16294
|
+
}).strict();
|
|
16295
|
+
var researchBatchRunCreateSchema = z56.object({
|
|
16296
|
+
queries: z56.array(researchQueryTextSchema).min(1).max(MAX_RESEARCH_BATCH_QUERIES),
|
|
16297
|
+
provider: z56.string().trim().min(1),
|
|
16298
|
+
model: z56.string().trim().min(1).max(200),
|
|
16299
|
+
location: locationContextSchema.nullable(),
|
|
16300
|
+
scope: researchBatchScopeSelectionSchema.optional(),
|
|
16301
|
+
template: researchTemplateSelectionSchema.optional()
|
|
16302
|
+
}).strict();
|
|
16303
|
+
var researchBatchCreateSchema = z56.object({
|
|
16304
|
+
idempotencyKey: z56.string().trim().min(1).max(128),
|
|
16305
|
+
runs: z56.array(researchBatchRunCreateSchema).min(1).max(MAX_RESEARCH_BATCH_RUNS)
|
|
16306
|
+
}).strict().superRefine((value, ctx) => {
|
|
16307
|
+
const totalQueries = value.runs.reduce((total, run) => total + run.queries.length, 0);
|
|
16308
|
+
if (totalQueries > MAX_RESEARCH_BATCH_QUERIES) {
|
|
16309
|
+
ctx.addIssue({ code: z56.ZodIssueCode.custom, path: ["runs"], message: `A research batch may contain at most ${MAX_RESEARCH_BATCH_QUERIES} concrete queries across all destinations` });
|
|
16310
|
+
}
|
|
16311
|
+
});
|
|
16276
16312
|
var researchRunPrincipalSchema = z56.object({
|
|
16277
16313
|
kind: z56.enum(["api-key", "user"]),
|
|
16278
16314
|
id: z56.string(),
|
|
16279
16315
|
name: z56.string(),
|
|
16280
|
-
role: userRoleSchema.nullable()
|
|
16316
|
+
role: userRoleSchema.nullable(),
|
|
16317
|
+
/** Consumes the shared limited-research budget. Legacy viewers count by role. */
|
|
16318
|
+
limited: z56.boolean().optional()
|
|
16281
16319
|
});
|
|
16282
16320
|
var researchRunSummarySchema = z56.object({
|
|
16283
16321
|
id: z56.string(),
|
|
@@ -16321,6 +16359,7 @@ var researchRunQuerySchema = z56.object({
|
|
|
16321
16359
|
createdAt: z56.string()
|
|
16322
16360
|
});
|
|
16323
16361
|
var researchRunDetailSchema = researchRunSummarySchema.extend({ queries: z56.array(researchRunQuerySchema) });
|
|
16362
|
+
var researchBatchSchema = z56.object({ runs: z56.array(researchRunDetailSchema) });
|
|
16324
16363
|
var researchProviderOptionSchema = z56.object({
|
|
16325
16364
|
name: z56.string(),
|
|
16326
16365
|
displayName: z56.string(),
|
|
@@ -16330,7 +16369,9 @@ var researchProviderOptionSchema = z56.object({
|
|
|
16330
16369
|
});
|
|
16331
16370
|
var researchRunListSchema = z56.object({
|
|
16332
16371
|
runs: z56.array(researchRunSummarySchema),
|
|
16333
|
-
providers: z56.array(researchProviderOptionSchema).optional()
|
|
16372
|
+
providers: z56.array(researchProviderOptionSchema).optional(),
|
|
16373
|
+
/** Credential-specific admission policy, shared by UI, CLI and MCP consumers. */
|
|
16374
|
+
access: z56.object({ canRun: z56.boolean(), dailyRunLimit: z56.number().int().positive().nullable() }).optional()
|
|
16334
16375
|
});
|
|
16335
16376
|
|
|
16336
16377
|
// ../contracts/src/ads.ts
|
|
@@ -18224,7 +18265,9 @@ export {
|
|
|
18224
18265
|
deduplicateResearchQueries,
|
|
18225
18266
|
expandResearchTemplate,
|
|
18226
18267
|
researchRunCreateSchema,
|
|
18268
|
+
researchBatchCreateSchema,
|
|
18227
18269
|
researchRunDetailSchema,
|
|
18270
|
+
researchBatchSchema,
|
|
18228
18271
|
researchRunListSchema,
|
|
18229
18272
|
AdsReviewStatuses,
|
|
18230
18273
|
AdsIntegrityDecisions,
|
|
@@ -18302,12 +18345,15 @@ export {
|
|
|
18302
18345
|
escapeLikePattern,
|
|
18303
18346
|
READ_ONLY_SCOPE,
|
|
18304
18347
|
WILDCARD_SCOPE,
|
|
18348
|
+
RESEARCH_RUN_SCOPE,
|
|
18305
18349
|
PROJECTS_WRITE_SCOPE,
|
|
18306
18350
|
ADS_WRITE_SCOPE,
|
|
18307
18351
|
ADS_APPROVE_SCOPE,
|
|
18308
18352
|
ADS_ACTIVATE_SCOPE,
|
|
18309
18353
|
GOOGLE_MARKETING_LIVE_READ_SCOPE,
|
|
18310
18354
|
GOOGLE_MARKETING_WRITE_SCOPE,
|
|
18355
|
+
restrictedWriteScopes,
|
|
18356
|
+
intersectScopes,
|
|
18311
18357
|
isReadOnlyKey,
|
|
18312
18358
|
splitList,
|
|
18313
18359
|
parseOriginList,
|
|
@@ -5,11 +5,11 @@ import {
|
|
|
5
5
|
installSkills,
|
|
6
6
|
loadConfigRaw,
|
|
7
7
|
saveConfigPatch
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-2A7E5TDU.js";
|
|
9
9
|
import {
|
|
10
10
|
SKILL_MANIFEST_FILENAME,
|
|
11
11
|
SkillsClients
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-KBUV3HGS.js";
|
|
13
13
|
|
|
14
14
|
// src/skills-autosync.ts
|
|
15
15
|
import fs from "fs";
|