@wix/mcp 1.0.94 → 1.0.96
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 +2 -2
- package/build/bin-standalone.js +1457 -332
- package/build/cjs/index.cjs +3379 -1333
- package/build/cjs/toolkit.cjs +2158 -373
- package/build/dts/api-call/headless-release.d.ts +56 -0
- package/build/dts/api-call/headless-release.js +135 -0
- package/build/dts/api-call/index.d.ts +9 -1
- package/build/dts/api-call/index.js +36 -8
- package/build/dts/api-call/site-files.d.ts +14 -0
- package/build/dts/api-call/site-files.js +106 -10
- package/build/dts/api-call/upload-headless-website-files.d.ts +117 -5
- package/build/dts/api-call/upload-headless-website-files.js +565 -20
- package/build/dts/api-call/upload-image-tool.d.ts +2 -0
- package/build/dts/api-call/upload-image-tool.js +8 -4
- package/build/dts/bin.d.ts +1 -1
- package/build/dts/bin.js +3 -1
- package/build/dts/code-mode/attachments.d.ts +9 -6
- package/build/dts/code-mode/attachments.js +23 -16
- package/build/dts/code-mode/index.d.ts +6 -1
- package/build/dts/code-mode/index.js +32 -12
- package/build/dts/code-mode/truncate-response.js +5 -1
- package/build/dts/config/default-config.d.ts +35 -5
- package/build/dts/config/default-config.js +339 -182
- package/build/dts/config/file-params.d.ts +22 -0
- package/build/dts/config/file-params.js +24 -0
- package/build/dts/config/param-descriptions.d.ts +14 -2
- package/build/dts/config/param-descriptions.js +33 -14
- package/build/dts/constants.d.ts +1 -0
- package/build/dts/constants.js +1 -0
- package/build/dts/docs/docs.d.ts +12 -1
- package/build/dts/docs/docs.js +274 -43
- package/build/dts/docs/fetch-article.d.ts +21 -0
- package/build/dts/docs/fetch-article.js +66 -4
- package/build/dts/docs/get-to-know.d.ts +7 -2
- package/build/dts/docs/get-to-know.js +36 -14
- package/build/dts/docs/guessed-url.d.ts +41 -0
- package/build/dts/docs/guessed-url.js +185 -0
- package/build/dts/docs/mintlify-docs.d.ts +121 -0
- package/build/dts/docs/mintlify-docs.js +391 -0
- package/build/dts/docs/semanticSearch.d.ts +2 -1
- package/build/dts/docs/semanticSearch.js +14 -7
- package/build/dts/docs/start-deploy-website.d.ts +7 -6
- package/build/dts/docs/start-deploy-website.js +13 -8
- package/build/dts/docs/start-headless-build.d.ts +8 -10
- package/build/dts/docs/start-headless-build.js +14 -28
- package/build/dts/index.d.ts +2 -2
- package/build/dts/index.js +2 -2
- package/build/dts/infra/redact-personal-data.d.ts +4 -0
- package/build/dts/infra/redact-personal-data.js +148 -0
- package/build/dts/site-widget-tools/constants.d.ts +50 -2
- package/build/dts/site-widget-tools/constants.js +65 -8
- package/build/dts/site-widget-tools/index.d.ts +1 -0
- package/build/dts/site-widget-tools/index.js +1 -0
- package/build/dts/site-widget-tools/pick-images-tool/index.d.ts +14 -0
- package/build/dts/site-widget-tools/pick-images-tool/index.js +138 -0
- package/build/dts/site-widget-tools/pull-site-creation-job-tool/index.js +1 -1
- package/build/dts/site-widget-tools/search-site-templates-tool/index.js +25 -2
- package/build/dts/site-widget-tools/site-builder-tool/index.js +35 -3
- package/build/dts/site-widget-tools/site-creation-tool/index.d.ts +7 -1
- package/build/dts/site-widget-tools/site-creation-tool/index.js +22 -51
- package/build/dts/site-widget-tools/suggested-domain-tool/index.js +26 -12
- package/build/dts/support/index.d.ts +4 -0
- package/build/dts/support/index.js +13 -7
- package/build/dts/tool-utils.d.ts +8 -1
- package/build/dts/tool-utils.js +26 -2
- package/build/dts/toolkit-entry.d.cts +15 -10
- package/build/dts/toolkit-entry.d.ts +15 -10
- package/build/dts/toolkit.d.ts +2 -2
- package/build/dts/toolkit.js +21 -8
- package/build/dts/wix-mcp-server.d.ts +10 -1
- package/build/dts/wix-mcp-server.js +25 -7
- package/build/dts/wixel/constants.d.ts +8 -1
- package/build/dts/wixel/constants.js +8 -1
- package/build/dts/wixel/index.d.ts +1 -1
- package/build/dts/wixel/index.js +2 -2
- package/build/dts/wixel/wixel-a2a-client.d.ts +83 -0
- package/build/dts/wixel/wixel-a2a-client.js +166 -0
- package/build/dts/wixel/wixel-bi.d.ts +2 -1
- package/build/dts/wixel/wixel-bi.js +2 -1
- package/build/dts/wixel/{external-agent-api.d.ts → wixel-session-entries.d.ts} +11 -33
- package/build/dts/wixel/{external-agent-api.js → wixel-session-entries.js} +33 -54
- package/build/dts/wixel/wixel-session-tools.d.ts +21 -26
- package/build/dts/wixel/wixel-session-tools.js +494 -599
- package/build/esm/index.js +3422 -1388
- package/build/esm/toolkit.js +2158 -373
- package/package.json +4 -4
package/build/bin-standalone.js
CHANGED
|
@@ -71066,6 +71066,8 @@ var runSemanticSearch = async (toolName, toolParams, maxResults = 20, rerank = f
|
|
|
71066
71066
|
kbNames.push("VELO_DOCS_KB_ID", "VELO_METHODS_KB_ID");
|
|
71067
71067
|
} else if (toolName === "CLI") {
|
|
71068
71068
|
kbNames.push("CLI_KB_ID");
|
|
71069
|
+
} else if (toolName === "HELP_CENTER") {
|
|
71070
|
+
kbNames.push("HELP_CENTER_KB_ID");
|
|
71069
71071
|
}
|
|
71070
71072
|
logger2.log(
|
|
71071
71073
|
`[SemanticSearch] Tool: ${toolName}, KBs: [${kbNames.join(", ")}], Query: "${toolParams.searchTerm}"`
|
|
@@ -71098,9 +71100,9 @@ var runSemanticSearch = async (toolName, toolParams, maxResults = 20, rerank = f
|
|
|
71098
71100
|
);
|
|
71099
71101
|
return data?.results;
|
|
71100
71102
|
};
|
|
71101
|
-
var runPlatformizedSemanticSearch = async (toolName, searchTerm, maxResults = 20, linesInEachResult, extraDocumentTypes) => {
|
|
71103
|
+
var runPlatformizedSemanticSearch = async (toolName, searchTerm, maxResults = 20, linesInEachResult, extraDocumentTypes, documentTypesOverride) => {
|
|
71102
71104
|
const startTime = Date.now();
|
|
71103
|
-
const documentTypes = extraDocumentTypes?.length ? [toolName, ...extraDocumentTypes] : void 0;
|
|
71105
|
+
const documentTypes = documentTypesOverride?.length ? documentTypesOverride : extraDocumentTypes?.length ? [toolName, ...extraDocumentTypes] : void 0;
|
|
71104
71106
|
logger2.log(
|
|
71105
71107
|
`[SemanticSearch/v2] Tool: ${documentTypes ? documentTypes.join("+") : toolName}, Query: "${searchTerm}"`
|
|
71106
71108
|
);
|
|
@@ -71144,15 +71146,17 @@ var runSemanticSearchAndFormat = async ({
|
|
|
71144
71146
|
rerank,
|
|
71145
71147
|
linesInEachResult,
|
|
71146
71148
|
usePlatformizedSearch = true,
|
|
71147
|
-
extraDocumentTypes
|
|
71149
|
+
extraDocumentTypes,
|
|
71150
|
+
documentTypes
|
|
71148
71151
|
}) => {
|
|
71149
|
-
if (usePlatformizedSearch) {
|
|
71152
|
+
if (usePlatformizedSearch || documentTypes?.length) {
|
|
71150
71153
|
return runPlatformizedSemanticSearch(
|
|
71151
71154
|
toolName,
|
|
71152
71155
|
toolParams.searchTerm,
|
|
71153
71156
|
maxResults,
|
|
71154
71157
|
linesInEachResult,
|
|
71155
|
-
extraDocumentTypes
|
|
71158
|
+
extraDocumentTypes,
|
|
71159
|
+
documentTypes
|
|
71156
71160
|
);
|
|
71157
71161
|
} else {
|
|
71158
71162
|
const results = await runSemanticSearch(
|
|
@@ -71168,6 +71172,7 @@ var runSemanticSearchAndFormat = async ({
|
|
|
71168
71172
|
// src/constants.ts
|
|
71169
71173
|
var RAW_DOCS_API_URL = "https://dev.wix.com/rawdocs/api";
|
|
71170
71174
|
var GET_ARTICLE_CONTENT_URL = `${RAW_DOCS_API_URL}/get-article-content`;
|
|
71175
|
+
var GET_SOURCE_CONTENT_URL = `${RAW_DOCS_API_URL}/get-source-content`;
|
|
71171
71176
|
var PORTAL_INDEX_URL = `${RAW_DOCS_API_URL}/portal-index`;
|
|
71172
71177
|
var DOCS_API_BASE_URL = "https://dev.wix.com/docs/api/v1";
|
|
71173
71178
|
var GET_SKILLS_BY_PORTAL_URL = `${DOCS_API_BASE_URL}/docs-web-app/menu-node/get-skills-by-portal`;
|
|
@@ -71180,7 +71185,13 @@ var SKILLS_REGISTRY_URL = new RegExp(
|
|
|
71180
71185
|
"^https://(?:dev\\.wix\\.com(?:/docs)?|www\\.wix\\.com(?:/velo/reference)?)/skills(?:[/.?#]|$)|^https://www\\.wix\\.com/headless/"
|
|
71181
71186
|
);
|
|
71182
71187
|
function isSkillsRegistryUrl(url) {
|
|
71183
|
-
return SKILLS_REGISTRY_URL.test(url
|
|
71188
|
+
return SKILLS_REGISTRY_URL.test(normalizeSkillsUrl(url));
|
|
71189
|
+
}
|
|
71190
|
+
var GITHUB_SKILLS_URL = /^https:\/\/(?:www\.)?github\.com\/wix\/skills\/(?:blob|raw|tree)\/[^/]+\/skills\/([^#?]+)/;
|
|
71191
|
+
function normalizeSkillsUrl(url) {
|
|
71192
|
+
const apex = url.trim().replace(/^https:\/\/wix\.com\//, "https://www.wix.com/");
|
|
71193
|
+
const gh = apex.match(GITHUB_SKILLS_URL);
|
|
71194
|
+
return gh ? `https://www.wix.com/skills/${gh[1]}` : apex;
|
|
71184
71195
|
}
|
|
71185
71196
|
async function fetchSkillsRegistryPage(httpClient, url) {
|
|
71186
71197
|
let data;
|
|
@@ -71278,6 +71289,40 @@ async function fetchArticleContentFromDigor(httpClient, articleUrl, mode, stripH
|
|
|
71278
71289
|
}
|
|
71279
71290
|
return articleContent;
|
|
71280
71291
|
}
|
|
71292
|
+
function parseSourceContentUrl(url) {
|
|
71293
|
+
let parsed;
|
|
71294
|
+
try {
|
|
71295
|
+
parsed = new URL(url);
|
|
71296
|
+
} catch {
|
|
71297
|
+
return void 0;
|
|
71298
|
+
}
|
|
71299
|
+
if (`${parsed.origin}${parsed.pathname}` !== GET_SOURCE_CONTENT_URL) {
|
|
71300
|
+
return void 0;
|
|
71301
|
+
}
|
|
71302
|
+
const repo = parsed.searchParams.get("repo");
|
|
71303
|
+
const path10 = parsed.searchParams.get("path");
|
|
71304
|
+
const commitHash = parsed.searchParams.get("commitHash");
|
|
71305
|
+
if (!repo || !path10) return void 0;
|
|
71306
|
+
return commitHash ? { repo, path: path10, commitHash } : { repo, path: path10 };
|
|
71307
|
+
}
|
|
71308
|
+
async function fetchSourceContent(httpClient, repo, path10, commitHash) {
|
|
71309
|
+
const url = new URL(GET_SOURCE_CONTENT_URL);
|
|
71310
|
+
url.searchParams.set("repo", repo);
|
|
71311
|
+
url.searchParams.set("path", path10);
|
|
71312
|
+
if (commitHash) url.searchParams.set("commitHash", commitHash);
|
|
71313
|
+
let data;
|
|
71314
|
+
try {
|
|
71315
|
+
({ data } = await httpClient.get(url.toString()));
|
|
71316
|
+
} catch (error2) {
|
|
71317
|
+
const { message, status } = getHttpErrorDetails(error2);
|
|
71318
|
+
const statusSuffix = status ? ` (status ${status})` : "";
|
|
71319
|
+
throw new Error(`${message}${statusSuffix}`);
|
|
71320
|
+
}
|
|
71321
|
+
if (!data?.content) {
|
|
71322
|
+
throw new Error("Source content is empty");
|
|
71323
|
+
}
|
|
71324
|
+
return data.content;
|
|
71325
|
+
}
|
|
71281
71326
|
async function fetchArticleContent(httpClient, articleUrl, mode, stripHeader = false, skillsPortalUrl, repo, commitHash, fetchMcpWhiteList) {
|
|
71282
71327
|
const effectiveUrl = applyPortalUrlOverride(articleUrl, skillsPortalUrl);
|
|
71283
71328
|
const isOverridden = effectiveUrl !== articleUrl;
|
|
@@ -71291,7 +71336,10 @@ async function fetchArticleContent(httpClient, articleUrl, mode, stripHeader = f
|
|
|
71291
71336
|
`[fetch] Override failed for ${effectiveUrl}, falling back to ${articleUrl}:`,
|
|
71292
71337
|
error2 instanceof Error ? error2.message : error2
|
|
71293
71338
|
);
|
|
71294
|
-
content = isSkillsRegistryUrl(articleUrl) ? await fetchSkillsRegistryPage(
|
|
71339
|
+
content = isSkillsRegistryUrl(articleUrl) ? await fetchSkillsRegistryPage(
|
|
71340
|
+
httpClient,
|
|
71341
|
+
normalizeSkillsUrl(articleUrl)
|
|
71342
|
+
) : await fetchArticleContentFromDigor(
|
|
71295
71343
|
httpClient,
|
|
71296
71344
|
articleUrl,
|
|
71297
71345
|
mode,
|
|
@@ -71299,7 +71347,10 @@ async function fetchArticleContent(httpClient, articleUrl, mode, stripHeader = f
|
|
|
71299
71347
|
);
|
|
71300
71348
|
}
|
|
71301
71349
|
} else if (isSkillsRegistryUrl(articleUrl)) {
|
|
71302
|
-
content = await fetchSkillsRegistryPage(
|
|
71350
|
+
content = await fetchSkillsRegistryPage(
|
|
71351
|
+
httpClient,
|
|
71352
|
+
normalizeSkillsUrl(articleUrl)
|
|
71353
|
+
);
|
|
71303
71354
|
} else if (mode === "raw") {
|
|
71304
71355
|
let parsedUrl;
|
|
71305
71356
|
try {
|
|
@@ -71442,6 +71493,140 @@ async function fetchPlatformizedMenu(menuUrl) {
|
|
|
71442
71493
|
return data.content;
|
|
71443
71494
|
}
|
|
71444
71495
|
|
|
71496
|
+
// src/docs/guessed-url.ts
|
|
71497
|
+
var SKILLS_BASE = "https://www.wix.com/skills/";
|
|
71498
|
+
var registryUrl = (url) => normalizeSkillsUrl(url).replace(
|
|
71499
|
+
/^https:\/\/(?:dev\.wix\.com(?:\/docs)?|www\.wix\.com\/velo\/reference)\/skills\//,
|
|
71500
|
+
SKILLS_BASE
|
|
71501
|
+
);
|
|
71502
|
+
var DOCS_BASE = "https://dev.wix.com/docs/";
|
|
71503
|
+
var FILLER = /* @__PURE__ */ new Set([
|
|
71504
|
+
"",
|
|
71505
|
+
"md",
|
|
71506
|
+
"a",
|
|
71507
|
+
"an",
|
|
71508
|
+
"the",
|
|
71509
|
+
"and",
|
|
71510
|
+
"or",
|
|
71511
|
+
"of",
|
|
71512
|
+
"to",
|
|
71513
|
+
"wix",
|
|
71514
|
+
"s"
|
|
71515
|
+
]);
|
|
71516
|
+
var slugWords = (slug) => new Set(
|
|
71517
|
+
slug.toLowerCase().replace(/\.md$/, "").split(/[^a-z0-9]+/).filter((w) => !FILLER.has(w)).map((w) => w.length > 3 && w.endsWith("s") ? w.slice(0, -1) : w)
|
|
71518
|
+
);
|
|
71519
|
+
function slugSimilarity(a2, b) {
|
|
71520
|
+
const x = slugWords(a2);
|
|
71521
|
+
const y = slugWords(b);
|
|
71522
|
+
if (x.size === 0 || y.size === 0) return 0;
|
|
71523
|
+
let shared = 0;
|
|
71524
|
+
for (const w of x) if (y.has(w)) shared++;
|
|
71525
|
+
return shared / (x.size + y.size - shared);
|
|
71526
|
+
}
|
|
71527
|
+
var lastSegment = (path10) => path10.slice(path10.lastIndexOf("/") + 1);
|
|
71528
|
+
var folderOf = (path10) => path10.includes("/") ? path10.slice(0, path10.lastIndexOf("/")) : "";
|
|
71529
|
+
var SKILL_FILE_MATCH = 0.5;
|
|
71530
|
+
function closestSkillFile(url, manifest, manifestUrl) {
|
|
71531
|
+
const normalized = registryUrl(url).replace(/[?#].*$/, "");
|
|
71532
|
+
if (!normalized.startsWith(SKILLS_BASE)) return null;
|
|
71533
|
+
const [, ...rest] = normalized.slice(SKILLS_BASE.length).split("/");
|
|
71534
|
+
const asked = rest.join("/");
|
|
71535
|
+
const paths = (manifest.files ?? []).map((f) => f.path);
|
|
71536
|
+
if (!asked || paths.length === 0) return null;
|
|
71537
|
+
const base = manifest.base ?? manifestUrl.replace(/\.manifest\.json$/, "/");
|
|
71538
|
+
const name = lastSegment(asked);
|
|
71539
|
+
const folder = folderOf(asked);
|
|
71540
|
+
const sameName = paths.filter((p) => lastSegment(p) === name);
|
|
71541
|
+
if (sameName.length === 1) {
|
|
71542
|
+
return { kind: "file", path: sameName[0], url: base + sameName[0] };
|
|
71543
|
+
}
|
|
71544
|
+
const ranked = paths.filter((p) => folderOf(p) === folder).map((p) => ({ p, score: slugSimilarity(lastSegment(p), name) })).sort((a2, b) => b.score - a2.score);
|
|
71545
|
+
const [best, next] = ranked;
|
|
71546
|
+
if (best && best.score >= SKILL_FILE_MATCH && best.score > (next?.score ?? 0)) {
|
|
71547
|
+
return { kind: "file", path: best.p, url: base + best.p };
|
|
71548
|
+
}
|
|
71549
|
+
if (ranked.length > 0) {
|
|
71550
|
+
return {
|
|
71551
|
+
kind: "folder",
|
|
71552
|
+
folder,
|
|
71553
|
+
files: ranked.map((r) => base + r.p),
|
|
71554
|
+
manifestUrl
|
|
71555
|
+
};
|
|
71556
|
+
}
|
|
71557
|
+
const top = [...new Set(paths.map((p) => p.split("/")[0]))].sort();
|
|
71558
|
+
return {
|
|
71559
|
+
kind: "folder",
|
|
71560
|
+
folder: "",
|
|
71561
|
+
files: top.map((t) => base + t),
|
|
71562
|
+
manifestUrl
|
|
71563
|
+
};
|
|
71564
|
+
}
|
|
71565
|
+
function skillManifestUrl(url) {
|
|
71566
|
+
const normalized = registryUrl(url);
|
|
71567
|
+
if (!normalized.startsWith(SKILLS_BASE)) return null;
|
|
71568
|
+
const skill = normalized.slice(SKILLS_BASE.length).split(/[/?#]/)[0];
|
|
71569
|
+
return skill ? `${SKILLS_BASE}${skill}.manifest.json` : null;
|
|
71570
|
+
}
|
|
71571
|
+
var MENU_WALK_UP_LEVELS = 3;
|
|
71572
|
+
var MIN_MENU_SEGMENTS = 3;
|
|
71573
|
+
function parentMenuUrls(url) {
|
|
71574
|
+
const clean = url.replace(/[?#].*$/, "").replace(/\/+$/, "");
|
|
71575
|
+
if (!clean.startsWith(DOCS_BASE)) return [];
|
|
71576
|
+
const segments = clean.slice(DOCS_BASE.length).split("/");
|
|
71577
|
+
const out = [];
|
|
71578
|
+
for (let up = 1; up <= MENU_WALK_UP_LEVELS; up++) {
|
|
71579
|
+
const kept = segments.length - up;
|
|
71580
|
+
if (kept < MIN_MENU_SEGMENTS) break;
|
|
71581
|
+
out.push(DOCS_BASE + segments.slice(0, kept).join("/"));
|
|
71582
|
+
}
|
|
71583
|
+
return out;
|
|
71584
|
+
}
|
|
71585
|
+
function closestMenuLinks(menuText, menuUrl, askedUrl, limit = 3) {
|
|
71586
|
+
const asked = lastSegment(
|
|
71587
|
+
askedUrl.replace(/[?#].*$/, "").replace(/\/+$/, "")
|
|
71588
|
+
);
|
|
71589
|
+
const under = `${menuUrl.replace(/\/+$/, "")}/`;
|
|
71590
|
+
const links = [
|
|
71591
|
+
...new Set(
|
|
71592
|
+
menuText.match(/https:\/\/dev\.wix\.com\/docs\/[^\s)\]>"'`]+/g) ?? []
|
|
71593
|
+
)
|
|
71594
|
+
].filter((l) => l.startsWith(under));
|
|
71595
|
+
return links.map((l) => ({
|
|
71596
|
+
l,
|
|
71597
|
+
score: slugSimilarity(lastSegment(l.replace(/\.md$/, "")), asked)
|
|
71598
|
+
})).filter((r) => r.score > 0).sort((a2, b) => b.score - a2.score).slice(0, limit).map((r) => r.l);
|
|
71599
|
+
}
|
|
71600
|
+
var SMALL_MENU = 3;
|
|
71601
|
+
var MENU_ENTRY_MATCH = 0.75;
|
|
71602
|
+
function subMenusToRead(menuText, menuUrl, askedUrl, limit = 2) {
|
|
71603
|
+
const asked = lastSegment(
|
|
71604
|
+
askedUrl.replace(/[?#].*$/, "").replace(/\/+$/, "")
|
|
71605
|
+
);
|
|
71606
|
+
const under = `${menuUrl.replace(/\/+$/, "")}/`;
|
|
71607
|
+
const methods = new Set(
|
|
71608
|
+
[
|
|
71609
|
+
...menuText.matchAll(
|
|
71610
|
+
/\]\((https:\/\/dev\.wix\.com\/docs\/[^)\s]+)\)\s*_\((?:GET|POST|PUT|PATCH|DELETE)\)_/g
|
|
71611
|
+
)
|
|
71612
|
+
].map((m) => m[1])
|
|
71613
|
+
);
|
|
71614
|
+
const entries = [
|
|
71615
|
+
...new Set(
|
|
71616
|
+
menuText.match(/https:\/\/dev\.wix\.com\/docs\/[^\s)\]>"'`]+/g) ?? []
|
|
71617
|
+
)
|
|
71618
|
+
].filter(
|
|
71619
|
+
(l) => l.startsWith(under) && !l.slice(under.length).replace(/\.md$/, "").includes("/") && !methods.has(l)
|
|
71620
|
+
);
|
|
71621
|
+
const scored = entries.map((l) => ({
|
|
71622
|
+
l,
|
|
71623
|
+
score: slugSimilarity(lastSegment(l.replace(/\.md$/, "")), asked)
|
|
71624
|
+
})).sort((a2, b) => b.score - a2.score);
|
|
71625
|
+
if (scored.some((s) => s.score >= MENU_ENTRY_MATCH)) return [];
|
|
71626
|
+
if (entries.length <= SMALL_MENU) return entries;
|
|
71627
|
+
return scored.filter((s) => s.score > 0).slice(0, limit).map((s) => s.l);
|
|
71628
|
+
}
|
|
71629
|
+
|
|
71445
71630
|
// ../../node_modules/dedent/dist/dedent.mjs
|
|
71446
71631
|
function ownKeys2(object3, enumerableOnly) {
|
|
71447
71632
|
var keys = Object.keys(object3);
|
|
@@ -71586,54 +71771,97 @@ function rethrowIfUnauthorized(error2) {
|
|
|
71586
71771
|
var ARRAY_QUERY_PARAMS_RULE = "Repeat array query params once per value: `?fieldsets=URL&fieldsets=RICH_CONTENT`. Do NOT comma-join values (`fieldsets=URL,RICH_CONTENT`), do NOT leave a trailing comma, and do NOT use a value the method schema does not list, even if a sibling method accepts it (draft posts have no `SEO` fieldset).";
|
|
71587
71772
|
var WQL_FILTER_RULE = "Query and search filters are written in WQL: each field takes a single operator, so combine conditions with the logical operators \u2014 `$and` and `$or` take an array of expressions, `$not` takes one, and they can nest.";
|
|
71588
71773
|
|
|
71774
|
+
// src/config/file-params.ts
|
|
71775
|
+
var FILE_PARAM_CLIENTS = "OpenAI clients (ChatGPT, Codex)";
|
|
71776
|
+
function fileParamNote(otherwise) {
|
|
71777
|
+
return `${FILE_PARAM_CLIENTS} only: pass each file as you have it (attached in the chat or created in your sandbox, by its file id or path) and the client swaps it for { download_url, file_id, file_name?, mime_type? } before the call reaches Wix. No other client does this swap, so elsewhere a path or file:// URL here fails at once; leave this out and ${otherwise}.`;
|
|
71778
|
+
}
|
|
71779
|
+
|
|
71780
|
+
// src/site-widget-tools/constants.ts
|
|
71781
|
+
var WIX_BUSINESS_FEATURES = "a store, bookings or appointments, rentals, events and tickets, a restaurant menu with online orders or reservations, a blog, a portfolio, pricing plans and memberships, donations, Wix Forms, members and login, a CMS, payments";
|
|
71782
|
+
var SITE_CREATION_DEFAULT_ACTIONS = "add products, set up bookings, and adjust your content";
|
|
71783
|
+
var SITE_CREATION_CUSTOM_ACTIONS_GUIDANCE = `2\u20133 specific, high-value setup actions for the site's industry, written as a comma-separated phrase (it slots into "\u2026ask me to ___ right here in the chat"). Use the following domain patterns as guidance:
|
|
71784
|
+
* E-commerce / Retail: "add products, set up payment methods, and organize collections"
|
|
71785
|
+
* Restaurants / Food / Bakeries: "add menu items, set up online ordering, and collect table reservations"
|
|
71786
|
+
* Services / Fitness / Salons / Consultants: "set up booking slots, add service pricing, and manage appointments"
|
|
71787
|
+
* Creative / Portfolios / Photographers: "upload project galleries, feature client reviews, and customize contact forms"
|
|
71788
|
+
* Events / Weddings / Real Estate: "add event schedules, display listings, and manage RSVP forms"
|
|
71789
|
+
* General / Unspecified: "${SITE_CREATION_DEFAULT_ACTIONS}"
|
|
71790
|
+
If none of these patterns fit the site, infer 2\u20133 actions that suit what that kind of business would manage on its site.`;
|
|
71791
|
+
var SITE_BUILDER_CHOICE = {
|
|
71792
|
+
here: {
|
|
71793
|
+
label: "Build it here with me",
|
|
71794
|
+
pitch: "I build it in code right here, and you change anything by asking me"
|
|
71795
|
+
},
|
|
71796
|
+
editor: {
|
|
71797
|
+
label: "Design it in Wix's editor",
|
|
71798
|
+
pitch: "Wix designs a first version or you start from a template, then you edit it in Wix"
|
|
71799
|
+
},
|
|
71800
|
+
/** The editor's second step, in the widget and its reply. */
|
|
71801
|
+
editorStart: {
|
|
71802
|
+
wix: {
|
|
71803
|
+
label: "Let Wix design it",
|
|
71804
|
+
pitch: "Wix designs a first version from your description for you to edit"
|
|
71805
|
+
},
|
|
71806
|
+
template: {
|
|
71807
|
+
label: "Browse templates",
|
|
71808
|
+
pitch: "start from a ready-made design and edit it in Wix"
|
|
71809
|
+
}
|
|
71810
|
+
},
|
|
71811
|
+
/** Asked in chat when no widget is shown: who builds it. */
|
|
71812
|
+
whoQuestion: "Do you want me to build it here, so you can change anything just by asking me, or do you want to design it yourself in Wix's editor?",
|
|
71813
|
+
/** Asked next, only when the user chose Wix's editor. */
|
|
71814
|
+
editorQuestion: "Should Wix design a first version for you to edit, or do you want to start from a template?",
|
|
71815
|
+
/** What the widget sends as the user's message when they pick "Build it here with me". */
|
|
71816
|
+
hereFollowUp: "Build it here with me, in code, so I can keep changing it by asking you."
|
|
71817
|
+
};
|
|
71818
|
+
|
|
71589
71819
|
// src/config/default-config.ts
|
|
71590
71820
|
var AGENT_GOAL = dedent_default`
|
|
71591
|
-
You
|
|
71592
|
-
|
|
71821
|
+
You help the user with their Wix sites and account.
|
|
71822
|
+
Work out what the task needs and do it: read the Wix skills, docs and API schemas that cover it, and write and run the code that calls Wix APIs, until the task is done.
|
|
71593
71823
|
`;
|
|
71824
|
+
var CALL_WIX_SITE_API_RECONNECT_LINE = "If the Wix MCP offers no ExecuteWixAPI at all, your Wix connection is likely an old or cached version: tell the user once to reconnect the Wix connector or restart the client, and use this tool until then.";
|
|
71825
|
+
var CALL_WIX_SITE_API_NO_EXECUTE_LINE = "If ExecuteWixAPI isn't in your tool list, use this tool.";
|
|
71594
71826
|
var DISCOVERY_FLOWS = [
|
|
71595
|
-
"- CONVERSATION CONTEXT BASED: find relevant docs article or API example for the user's prompt/task in the conversation context -> call API
|
|
71596
|
-
"- METHOD CODE EXAMPLE BASED: BrowseWixRESTDocsMenu() or SearchWixRESTDocumentation() -> find relevant method -> read method article using ReadFullDocsArticle() to get method code examples -> call API
|
|
71597
|
-
"- FULL SCHEMA BASED: BrowseWixRESTDocsMenu() or SearchWixRESTDocumentation() -> find relevant method -> read method article using ReadFullDocsArticle() -> no method code examples found -> inspect the method schema using SearchWixAPISpec or ReadFullDocsMethodSchema -> call API
|
|
71827
|
+
"- CONVERSATION CONTEXT BASED: find relevant docs article or API example for the user's prompt/task in the conversation context -> call the API with ExecuteWixAPI based on the docs article or API example",
|
|
71828
|
+
"- METHOD CODE EXAMPLE BASED: BrowseWixRESTDocsMenu() or SearchWixRESTDocumentation() -> find relevant method -> read method article using ReadFullDocsArticle() to get method code examples -> call the API with ExecuteWixAPI based on the method code examples",
|
|
71829
|
+
"- FULL SCHEMA BASED: BrowseWixRESTDocsMenu() or SearchWixRESTDocumentation() -> find relevant method -> read method article using ReadFullDocsArticle() -> no method code examples found -> inspect the method schema using SearchWixAPISpec or ReadFullDocsMethodSchema -> call the API with ExecuteWixAPI based on the schema"
|
|
71598
71830
|
];
|
|
71831
|
+
function directRouteLines(includeReadme, includeImageUploadGuidance) {
|
|
71832
|
+
return [
|
|
71833
|
+
...includeReadme ? [
|
|
71834
|
+
`- **Creating a new site.** Skip the docs too. A site is written in code and uploaded: StartDeployWebsite returns the upload guide; StartHeadlessBuild returns the headless guide, for a site that needs Wix business features (${WIX_BUSINESS_FEATURES}). Call one right away, without asking the user anything first: StartHeadlessBuild when the site needs Wix business features, otherwise StartDeployWebsite. WixHarmonyEditorBuild or SearchSiteTemplates only when the user asked for Wix's editor, the Wix Harmony Editor, a template, Wix Studio or the Classic Editor. Never create a site through ManageWixSite, CallWixSiteAPI or ExecuteWixAPI.`,
|
|
71835
|
+
"- **Suggesting domain names**: call GetSuggestedDomains directly, with the business or site name as the query."
|
|
71836
|
+
] : [],
|
|
71837
|
+
"- **Listing, showing or finding their Wix sites**: call ListWixSites directly.",
|
|
71838
|
+
...includeImageUploadGuidance ? [
|
|
71839
|
+
"- **Uploading local or attached image files to a Wix site**: call UploadImageToWixSite directly, with no docs, schema or API calls. Do NOT use ExecuteWixAPI, SearchWixAPISpec, or any Media Manager REST API for image uploads."
|
|
71840
|
+
] : []
|
|
71841
|
+
];
|
|
71842
|
+
}
|
|
71599
71843
|
function buildSystemReminderGuidelines(includeReadme, includeImageUploadGuidance) {
|
|
71600
|
-
const exception = includeReadme ? "**Exception:** " : "";
|
|
71601
71844
|
const lines = [];
|
|
71602
|
-
if (includeReadme) {
|
|
71603
|
-
lines.push(
|
|
71604
|
-
"if the WixREADME tool is available to you, YOU MUST USE IT AT THE BEGINNING OF ANY CONVERSATION and then continue with calling the other tools and calling the Wix APIs until the task is completed.",
|
|
71605
|
-
"**Creating a new Wix site \u2014 and only then \u2014 skip WixREADME and the docs.** First settle one thing: will the user keep working on this site with you, in code, or design it themselves in Wix's editor? In code \u2014 you or the user have code, the two of you designed it here, they asked you to build it, they asked for a headless site, or it is an app: StartDeployWebsite if the code exists in any form, StartHeadlessBuild if not, called right away (it only returns the guide; the site's purpose is not needed first). In Wix's editor: the site-creation tools; their descriptions carry the rules. Everything else starts with WixREADME as usual.",
|
|
71606
|
-
"Never default to AI or search templates unless the user explicitly requests it. When the user named no creation method - let the user make that choice as the site-creation tools' descriptions direct. Never route site creation through ManageWixSite, CallWixSiteAPI, or ExecuteWixAPI."
|
|
71607
|
-
);
|
|
71608
|
-
}
|
|
71609
71845
|
lines.push(
|
|
71610
|
-
|
|
71846
|
+
includeReadme ? "Start every Wix task with WixREADME, questions included, then use the other tools and the Wix APIs until the task is done. If WixREADME is not available, follow the flows without it. These requests skip it and go straight to their own tool:" : "These requests go straight to their own tool, with no docs or API calls first:"
|
|
71611
71847
|
);
|
|
71612
|
-
|
|
71613
|
-
lines.push(
|
|
71614
|
-
`${exception}If the user wants to upload local or attached image files to a Wix site, skip ${includeReadme ? "WixREADME and " : ""}all docs/schema/API flows \u2014 call UploadImageToWixSite directly. Do NOT use ExecuteWixAPI, SearchWixAPISpec, or any Media Manager REST API for image uploads.`
|
|
71615
|
-
);
|
|
71616
|
-
}
|
|
71617
|
-
if (includeReadme) {
|
|
71618
|
-
lines.push(
|
|
71619
|
-
"If the WixREADME tool is not available to you, you should use the other flows as described without using the WixREADME tool until the task is completed."
|
|
71620
|
-
);
|
|
71621
|
-
}
|
|
71848
|
+
lines.push(...directRouteLines(includeReadme, includeImageUploadGuidance));
|
|
71622
71849
|
lines.push(
|
|
71623
|
-
`
|
|
71624
|
-
"
|
|
71850
|
+
`A question follows the same routes: one about those requests goes to its tool ("can you show my sites?" is ListWixSites). Any other Wix question is answered from ${includeReadme ? "WixREADME, the Wix skills, " : ""}the docs search and the matching docs articles, never from memory, and never with a reply that you lack the tools or APIs to answer. Many questions, including ones that need no API call, are answered by a ${includeReadme ? "Wix skill or docs article" : "docs article"}.`,
|
|
71851
|
+
"When the user asks you to do something in Wix, do it, in as few steps and questions as you can; don't tell them which docs to read or which API to call."
|
|
71625
71852
|
);
|
|
71626
71853
|
return lines.join("\n");
|
|
71627
71854
|
}
|
|
71628
71855
|
function buildSystemReminderFlows(includeReadme) {
|
|
71629
71856
|
const lines = ["Wix MCP Site Management Flows"];
|
|
71857
|
+
const noSkill = "no Wix skill covers the user's prompt/task -> ";
|
|
71630
71858
|
if (includeReadme) {
|
|
71631
71859
|
lines.push(
|
|
71632
71860
|
"With WixREADME tool:",
|
|
71633
|
-
"-
|
|
71861
|
+
"- SKILL BASED (PREFERRED!): WixREADME() -> find the Wix skill for the user's prompt/task (WixREADME says how to read one) -> follow it -> call the API with ExecuteWixAPI based on it",
|
|
71634
71862
|
DISCOVERY_FLOWS[0],
|
|
71635
|
-
|
|
71636
|
-
|
|
71863
|
+
`- EXAMPLE BASED: WixREADME() -> ${noSkill}BrowseWixRESTDocsMenu() or SearchWixRESTDocumentation() -> find relevant method -> read method article using ReadFullDocsArticle() to get method code examples -> call the API with ExecuteWixAPI based on the method code examples`,
|
|
71864
|
+
`- SCHEMA BASED, FALLBACK: WixREADME() -> ${noSkill}BrowseWixRESTDocsMenu() or SearchWixRESTDocumentation() -> find relevant method -> read method article using ReadFullDocsArticle() -> no method code examples found -> inspect the method schema using SearchWixAPISpec or ReadFullDocsMethodSchema -> call the API with ExecuteWixAPI based on the schema`,
|
|
71637
71865
|
"Without WixREADME tool:"
|
|
71638
71866
|
);
|
|
71639
71867
|
}
|
|
@@ -71666,41 +71894,22 @@ function buildSystemReminder(includeReadme, includeImageUploadGuidance = true) {
|
|
|
71666
71894
|
`;
|
|
71667
71895
|
}
|
|
71668
71896
|
var SYSTEM_REMINDER = buildSystemReminder(true);
|
|
71897
|
+
var HELP_CENTER_IS_FOR_PEOPLE = "The Help Center is written for people doing things by hand in Wix's dashboard and editors. To act on a site yourself, the Wix developer docs come first: find the method with SearchWixRESTDocumentation or BrowseWixRESTDocsMenu.";
|
|
71669
71898
|
var SITE_CREATION_COPY = {
|
|
71670
71899
|
templatePick: {
|
|
71671
71900
|
nonWidget: "After the user selects a template, call `CreateSiteFromTemplate`.",
|
|
71672
71901
|
widget: "The gallery creates the site when the user picks one."
|
|
71673
|
-
},
|
|
71674
|
-
unstatedMethod: {
|
|
71675
|
-
nonWidget: "you MUST ask whether they want to build with AI or start from a template, and create nothing and show nothing until they answer",
|
|
71676
|
-
widget: "you MUST call `WixSiteCreation` and let them choose"
|
|
71677
71902
|
}
|
|
71678
71903
|
};
|
|
71679
|
-
var
|
|
71680
|
-
First decide who keeps building the site:
|
|
71681
|
-
- **You, in code**: a Wix Headless site, with full control of the design, changed and redeployed from this conversation, Wix business features added as a backend. This is the case when you or the user have code (hand-written files, a static build, a zip, another builder's export, a page you made here): call StartDeployWebsite. It is also the case when nothing is coded yet but the user asked you to build it or asked for a headless site, the two of you worked out its design in this conversation, or it is an app (a game, a dashboard, a tool): call StartHeadlessBuild right away, before asking what the site is for. Do not offer AI or templates for either.
|
|
71682
|
-
- **The user, in Wix's editor**: Wix generates it with AI or starts it from a template, and the user designs it in Wix. That is what the site-creation tools do; they never take files you already have.
|
|
71683
|
-
|
|
71684
|
-
For a new site in Wix's editor there are two things to settle: what the site is for, and how to build it. The how is AI generation vs. starting from a template, so naming templates, a template id or Wix Studio (Wix Studio is also the template side) already settles it.
|
|
71685
|
-
|
|
71686
|
-
Settle what the site is for first: its purpose, topic, business type, audience, or main visitor action. Naming a method is not a description of the site, and neither is the business or industry on its own.
|
|
71687
|
-
If you can't tell yet, ask the preferred question below and nothing else — one question, no creation-method question in the same reply, and no internal tool names.
|
|
71688
|
-
Once the purpose is clear, unless the user already named a method, ${SITE_CREATION_COPY.unstatedMethod.nonWidget}. A method they named is settled — never re-open it. Never default to AI or to templates, and never ask the user to choose between Harmony and Wix Studio; infer that from their words.
|
|
71689
|
-
With the purpose and the method known, that's enough to begin — route and refine the specifics with the user afterward.
|
|
71690
|
-
|
|
71691
|
-
Preferred question when the user has given no site context at all:
|
|
71692
|
-
Happy to help. To give you the right starting point, tell me a bit more about what you have in mind:
|
|
71693
|
-
- What's the site for? (e.g. an online clothing store, a yoga studio that takes bookings, a restaurant)
|
|
71694
|
-
- What's the vibe? (e.g. sleek and modern, cozy and rustic, bold and energetic)
|
|
71695
|
-
Give me a quick summary and I'll take it from there
|
|
71696
|
-
|
|
71697
|
-
Tone: helpful, practical, short. Speak about the user's site — what you're making and what comes next — not the tools, payloads, or routing behind it.`;
|
|
71904
|
+
var EDITOR_TAIL = `When the user wants Wix's editor, or to design the site themselves, without saying how to start, ask them first: "${SITE_BUILDER_CHOICE.editorQuestion}" A new site is otherwise written in code and uploaded: call StartDeployWebsite, or StartHeadlessBuild when it needs Wix business features, right away and without asking the user anything first.`;
|
|
71698
71905
|
var toWidget = (text) => Object.values(SITE_CREATION_COPY).reduce(
|
|
71699
71906
|
(acc, { nonWidget, widget }) => acc.replaceAll(nonWidget, widget),
|
|
71700
71907
|
text
|
|
71701
71908
|
);
|
|
71909
|
+
var WIX_API_DATA = "products, inventory, carts, checkouts, orders, bookings, services, staff, time slots, rentals, restaurant menus, online orders, reservations, events, tickets, RSVPs, blog posts, CMS collections and items, pricing plans, subscriptions, portfolios, gift cards, coupons, donations, forms, form submissions, contacts, members, loyalty points, groups, reviews, inbox messages, CRM tasks, automations, email campaigns, payments, invoices, SEO, redirects, translations, locations, analytics, media files, site properties, installed apps, and the account's sites and domains (searching whether a domain is available, buying one, and connecting one bought elsewhere)";
|
|
71702
71910
|
var EXECUTE_WIX_API_INTRO = dedent_default`
|
|
71703
|
-
|
|
71911
|
+
Reads and changes the data of a Wix site or account: query, list, count, create, update and delete it with one JavaScript function over the Wix REST API.
|
|
71912
|
+
One function holds the whole task: chained calls, pagination, loops, branching, and the reads that feed its writes.
|
|
71704
71913
|
Putting a site live or changing a headless site's files starts with StartDeployWebsite; building a new site in code with StartHeadlessBuild.
|
|
71705
71914
|
|
|
71706
71915
|
CODE CONTRACT:
|
|
@@ -71786,7 +71995,7 @@ var ACCOUNT_SITE_EXECUTE_SCOPE = dedent_default`
|
|
|
71786
71995
|
declare const files: Array<{ path: string; content: string; encoding?: "base64" }>;
|
|
71787
71996
|
\`\`\`
|
|
71788
71997
|
|
|
71789
|
-
FILE UPLOADS: files never go inline in \`code\`; two params feed the \`files\` global. \`attachments
|
|
71998
|
+
FILE UPLOADS: files never go inline in \`code\`; two params feed the \`files\` global. \`attachments\`: ${fileParamNote("upload from your shell if it reaches the internet")} Any type, up to 10 MB per call, all in one call: a zip of a whole site, HTML, images, PDFs; the bytes arrive as base64 entries named by file name. The \`files\` param takes content you have as text here: text goes raw; a small binary (icon, logo, font) rides as a \`base64\`-tagged entry — large images/video are referenced by URL (\`<img src="https://...">\`), not bundled. \`wix.multipart()\` turns the whole set into one upload body (bytes, so binary is safe):
|
|
71790
71999
|
\`\`\`javascript
|
|
71791
72000
|
// files param:
|
|
71792
72001
|
// === FILE: index.html ===
|
|
@@ -71801,6 +72010,7 @@ var ACCOUNT_SITE_EXECUTE_SCOPE = dedent_default`
|
|
|
71801
72010
|
return res.data;
|
|
71802
72011
|
}
|
|
71803
72012
|
\`\`\`
|
|
72013
|
+
HEADLESS SITE EDITS: \`wix.headless.files.list({siteId, prefix?, offset?, limit?})\` returns file metadata; \`read({siteId, path})\` returns UTF-8 text (up to 256 KB); \`patch({siteId, files?, deletePaths?, agent?})\` applies changed files and explicit deletions while preserving everything else. Patch defaults to the Execute \`files\` global (including resolved attachments and ZIPs). Paths are literal site-relative paths; no wrapping-folder stripping. It returns added/replaced/deleted/unchanged/missingDeletes path lists. List/read reuse one downloaded ZIP snapshot for the current site within an Execute call; switching sites discards the previous snapshot, and a new call downloads afresh. Patch downloads a fresh ZIP, then drops the full merged site and clears the read snapshot. Serialize edits to the same site; there is no atomic concurrency guarantee. For a full replacement, use the existing upload/drop path. See the upload-static-site recipe for examples and older-server fallback.
|
|
71804
72014
|
A site zip passed through \`attachments\` is one base64 entry; unzip it and upload the entries:
|
|
71805
72015
|
\`\`\`javascript
|
|
71806
72016
|
// attachments: [site.zip] → files = [{ path: "site.zip", content: "<base64>", encoding: "base64" }]
|
|
@@ -71924,22 +72134,37 @@ var executeWixApiDescription = dedent_default`
|
|
|
71924
72134
|
|
|
71925
72135
|
${EXECUTE_WIX_API_MULTI_SITE_EXAMPLE}
|
|
71926
72136
|
`;
|
|
71927
|
-
function buildToolDescriptions(includeReadme, includeImageUploadGuidance = true) {
|
|
71928
|
-
const
|
|
72137
|
+
function buildToolDescriptions(includeReadme, includeImageUploadGuidance = true, { usageGuideOnce = false } = {}) {
|
|
72138
|
+
const usageGuide = buildSystemReminder(
|
|
71929
72139
|
includeReadme,
|
|
71930
72140
|
includeImageUploadGuidance
|
|
71931
72141
|
);
|
|
71932
|
-
|
|
72142
|
+
const reminder = includeReadme && usageGuideOnce ? "" : usageGuide;
|
|
72143
|
+
const descriptions = {
|
|
72144
|
+
// Named in SERVER_INSTRUCTIONS: when this tool's name or what it is for changes, update them to match.
|
|
71933
72145
|
WixREADME: dedent_default`
|
|
71934
72146
|
# Tool: WixREADME
|
|
71935
|
-
|
|
71936
|
-
|
|
71937
|
-
|
|
71938
|
-
${
|
|
72147
|
+
The context every other Wix tool assumes. Call it first, once per conversation, for any Wix task or question; for another site later in the conversation, call \`GetSiteContext\` instead of calling this again.
|
|
72148
|
+
A Wix task includes reading or changing a site's or account's data: ${WIX_API_DATA}.
|
|
72149
|
+
These requests skip it and go straight to their own tool:
|
|
72150
|
+
${directRouteLines(includeReadme, includeImageUploadGuidance).join("\n")}
|
|
72151
|
+
A question about one of those goes to the same tool ("can you show my sites?" is ListWixSites). Any other Wix question is answered from a Wix skill or the docs, never from memory, and never with a reply that you lack the tools to answer.
|
|
72152
|
+
It returns, in full:
|
|
72153
|
+
- **Source of truth**: nothing Wix-specific from memory. Every URL, ID, setting location, product fact, request shape and field name comes from the docs tools, a Wix skill, an earlier tool result in the conversation, or the user.
|
|
72154
|
+
- **The site**: the account's sites with their properties and installed apps. The \`siteId\` comes from there (ask when several fit); a business solution's API works only on a site with its app installed, and an app's version changes its endpoints.
|
|
72155
|
+
- **Find the method**: an earlier tool result, else a Wix skill's recipe (wix-manage to manage a site, wix-headless-kit to build a headless one), else the docs: SearchWixRESTDocumentation or BrowseWixRESTDocsMenu, then ReadFullDocsArticle; the SDK, CLI, headless and apps docs for code.
|
|
72156
|
+
- **The exact shape**: model a call only on an example that matches the case; fill the rest with SearchWixAPISpec on the method's docs URL (request and response schemas, \`method.publicUrl\` for REST, \`method.sdk\` for the JavaScript SDK). A query's filter and sort fields and operators are a closed list per method.
|
|
72157
|
+
- **The call, or the code**: ExecuteWixAPI runs one async function holding every step code can resolve, the reads and the writes they feed together, \`hasMutations: true\` when anything writes. Code the user keeps (an app, a headless site, a script over REST or the JavaScript SDK) is written from the same shapes; the headless skills are a shortcut on that path.
|
|
72158
|
+
- **When a call fails**: the error says what was wrong and carries a Wix request id; fix that, never resend unchanged or guess.
|
|
72159
|
+
- **Wix skills**, what each is for and how to read one: from disk when installed (the Wix plugin, or \`npx skills add wix/skills\`, \`--skill <name>\` for one, \`-g\` for the user's home, into \`.agents/skills/<skill>/\` or a similar folder the client reads, such as \`.claude/skills/<skill>/\`), else online with ReadFullDocsArticle at \`https://www.wix.com/skills/<skill>/<path>\`.
|
|
72160
|
+
- **wix-manage**: REST recipes for managing a site's business solutions, one per task; follow the recipe and make its calls with ExecuteWixAPI, its docs URL in \`sourceDocUrls\`. Its list of recipes is \`SKILL.md\` in the installed skill, or online https://dev.wix.com/docs/api-reference/articles/ai-tools/wix-mcp/skills/wix-management-recipes-index.md, and each API area has its own \`<API section>/skills.md\` (for example https://dev.wix.com/docs/api-reference/business-solutions/bookings/skills.md).
|
|
72161
|
+
- **wix-headless-kit**: builds a Wix Headless site on shipped, verified code from wix-headless-templates, a \`@wix/sdk\` React core or the same data layer as plain REST calls: scaffold with the CLI, deploy, seed, design on the shipped hooks, release. https://www.wix.com/skills/headless-kit/SKILL.md
|
|
72162
|
+
- **wix-headless-templates**: the code wix-headless-kit builds from, one folder per Wix Business Solution. https://www.wix.com/skills/headless-templates/
|
|
72163
|
+
When the user asks you to do something in Wix, do it yourself, in as few steps and questions as you can; don't tell them which docs to read or which API to call.
|
|
71939
72164
|
`,
|
|
71940
72165
|
SearchWixRESTDocumentation: dedent_default`
|
|
71941
72166
|
**Searches the official Wix REST API documentation — the starting point for any Wix REST API task.** Unless you already have the exact method \`docsUrl\` in context, begin the task here; this is how you discover the right endpoint. Reach for it before \`SearchWixAPISpec\`, and avoid writing code that scans or filters \`lightIndex\` to find an endpoint (e.g. \`lightIndex.filter(...)\`, \`lightIndex.flatMap(...)\`, or substring-matching on \`docsUrl\`/\`name\`/\`summary\`) — that has no relevance ranking and silently misses composite and method-level operations. This is the ranked semantic-search discovery tool over the Wix REST API docs: describe your intent in natural language and it returns the matching REST endpoints/methods (with their \`docsUrl\`) ranked by relevance. It is the first step whenever you need to do something on a Wix site via HTTP and don't already have the exact \`docsUrl\` in context — for creating, reading, updating, or deleting any kind of Wix entity, across every business domain.
|
|
71942
|
-
It covers all Wix REST domains equally
|
|
72167
|
+
It covers all Wix REST domains equally, every product's data: ${WIX_API_DATA}, and the rest. Just describe the resource, action, or goal in plain words (e.g. 'add a catalog item with inventory', 'book a service', 'update a data collection item', 'create a discount', 'list contacts', 'get site details endpoint', 'REST authentication'); the ranking handles matching your wording to the right API regardless of domain.
|
|
71943
72168
|
**Next step after this tool:** take the \`docsUrl\` it returns and inspect that method's exact request/response schema with \`SearchWixAPISpec\` (\`getResourceSchemaByUrl(docsUrl)\`), then execute. \`SearchWixAPISpec\` is only for INSPECTING a \`docsUrl\` you already have — it is NOT a discovery tool. Skipping this step to hand-search \`lightIndex\` yourself is a mistake: raw index filtering has no relevance ranking and misses operations this ranked search finds. Discover here first, every time.
|
|
71944
72169
|
If you can't find what you need, rephrase your search term or use a bigger maxResults value.
|
|
71945
72170
|
${reminder}
|
|
@@ -71961,6 +72186,7 @@ function buildToolDescriptions(includeReadme, includeImageUploadGuidance = true)
|
|
|
71961
72186
|
`,
|
|
71962
72187
|
CallWixSiteAPI: dedent_default`
|
|
71963
72188
|
Call Wix apis on a business or site. Use this to create, read, update, and delete data and other Wix entities in your Wix site.
|
|
72189
|
+
ExecuteWixAPI is the preferred tool for Wix API calls: one function holds every call of the task, the reads and the writes they feed together, where this tool makes one call per invocation. If your client loads tools on demand (tool search, deferred tools), load ExecuteWixAPI before using this tool. ${CALL_WIX_SITE_API_RECONNECT_LINE}
|
|
71964
72190
|
Site-level: this tool reads and writes inside the single site named by the required \`siteId\`.
|
|
71965
72191
|
**Prefer using the "ListWixSites" tool when the user asks to list or show their sites.** Only use this tool for site listing if the user needs advanced filtering or specific site details beyond what ListWixSites provides.
|
|
71966
72192
|
For POST/PATCH/PUT requests, pass the request body as a JSON object or array in the "body" parameter with all the required fields and values as described in the API schema, code examples, or docs you retrieved (e.g. body: {"name": "value", "nested": {"key": "value"}} or body: [{"key": "value"}]).
|
|
@@ -71975,6 +72201,7 @@ function buildToolDescriptions(includeReadme, includeImageUploadGuidance = true)
|
|
|
71975
72201
|
Docs urls like https://dev.wix.com/docs/... are not api urls, if you want to read the docs, use the "ReadFullDocsArticle" tool
|
|
71976
72202
|
${reminder}
|
|
71977
72203
|
`,
|
|
72204
|
+
// Named in SERVER_INSTRUCTIONS: when this tool's name or what it is for changes, update them to match.
|
|
71978
72205
|
ListWixSites: dedent_default`
|
|
71979
72206
|
**Use this tool whenever the user asks to list, show, get, or find their Wix sites.** This is the dedicated tool for listing Wix sites for the current user. By default it returns all sites, but you can filter by name.${includeReadme ? "\n\n**Do NOT use WixREADME before this tool.** When the user asks to list their sites, call this tool directly \u2014 no need to read documentation first." : ""}
|
|
71980
72207
|
|
|
@@ -71995,13 +72222,13 @@ function buildToolDescriptions(includeReadme, includeImageUploadGuidance = true)
|
|
|
71995
72222
|
${reminder}
|
|
71996
72223
|
`,
|
|
71997
72224
|
ManageWixSite: dedent_default`
|
|
71998
|
-
|
|
71999
|
-
Account-level only: this tool acts on the account itself, or on sites as objects within it, and sends no site context. Anything that reads or writes inside a site is site-level and does not belong here — use a site-level tool with that site's \`siteId\`.
|
|
72225
|
+
Calls an account-level Wix API: one that acts on the account itself (its sites list, domains, account settings) or on sites as objects in it (create, rename, duplicate, delete a site). It sends no site, so an API that reads or writes inside a site (its products, data, bookings, members, pages, publishing) fails here: call that through ExecuteWixAPI with the site's \`siteId\`.
|
|
72000
72226
|
For POST/PATCH/PUT requests, pass the request body as a JSON object or array in the "body" parameter with all the required fields and values as described in the API schema, code examples, or docs you retrieved (e.g. body: {"name": "value", "nested": {"key": "value"}} or body: [{"key": "value"}]).
|
|
72001
72227
|
The API endpoint url param MUST ALWAYS be taken from the conversation context.
|
|
72002
72228
|
By conversation context we mean the endpoint url was given in the user prompt or got into the conversation context ${includeReadme ? 'by the "WixREADME" tool or ' : ""}by the "SearchWixRESTDocumentation" tool or by the "BrowseWixRESTDocsMenu" tool or by the "ReadFullDocsArticle" tool.
|
|
72003
72229
|
${reminder}
|
|
72004
72230
|
`,
|
|
72231
|
+
// Named in SERVER_INSTRUCTIONS: when this tool's name or what it is for changes, update them to match.
|
|
72005
72232
|
UploadImageToWixSite: dedent_default`
|
|
72006
72233
|
Upload one or more images to a Wix site's Media Manager. Returns wixstatic.com URL and media ID.
|
|
72007
72234
|
Do NOT use ExecuteWixAPI or code execution for image uploads — use this tool directly.
|
|
@@ -72011,34 +72238,39 @@ function buildToolDescriptions(includeReadme, includeImageUploadGuidance = true)
|
|
|
72011
72238
|
NEVER call this tool with a missing, empty, or guessed siteId — ask first instead.
|
|
72012
72239
|
|
|
72013
72240
|
Parameters — provide image input via image and/or imageUrls, OR imageBase64:
|
|
72014
|
-
• image (array):
|
|
72241
|
+
• image (array): ${fileParamNote("send the image as imageBase64 (the whole file, one per call) or as a public URL in imageUrls")} Pass ALL of them in one call.
|
|
72015
72242
|
• imageUrls (array): plain public image URLs the user pasted or other tools produced (no file_id). Pass ALL URLs in one call. Can be combined with image.
|
|
72016
72243
|
• imageBase64 (string): base64-encoded image + mimeType. One image at a time. Do NOT combine with image/imageUrls.
|
|
72017
72244
|
|
|
72018
72245
|
Delivering the bytes — this is where uploads most often fail:
|
|
72019
|
-
•
|
|
72246
|
+
• This server does not share your filesystem: outside image's clients, a file you can only reach by path (e.g. /mnt/..., /home/user/..., /Users/...) goes as imageBase64 (the whole file, one per call) or, if it is public, as imageUrls.
|
|
72020
72247
|
• imageBase64 must be the WHOLE file, not truncated. For large images prefer imageUrls, since long base64 is easily cut off and will be rejected as unreadable.
|
|
72021
72248
|
`,
|
|
72022
|
-
|
|
72023
|
-
|
|
72024
|
-
|
|
72249
|
+
// Registered for Claude clients only, beside UploadImageToWixSite.
|
|
72250
|
+
PickImagesForWixMedia: dedent_default`
|
|
72251
|
+
Shows a file picker where the user selects images from their device; they upload to the site's Media Manager and the result (each image's media ID and wixstatic URL) comes back in the conversation.
|
|
72252
|
+
Use it only when you can't deliver the image yourself with UploadImageToWixSite: the image is on the user's device and not in your files, or it is a file in your sandbox that you can't pass as a file, a public URL or base64. When UploadImageToWixSite can take it, use that.
|
|
72253
|
+
`,
|
|
72254
|
+
ReportIssueToWix: dedent_default`
|
|
72255
|
+
Report one specific problem with Wix's tools, APIs or docs to the Wix team, attributed to the authenticated user: an API error or a confusing API, wrong or missing docs, a Wix MCP tool or auth dead end. It is NOT a support channel and not for the user's own site content.
|
|
72025
72256
|
|
|
72026
72257
|
When to offer it (user-approved only — NEVER auto-send):
|
|
72027
|
-
- The user
|
|
72028
|
-
- The user complains
|
|
72029
|
-
-
|
|
72030
|
-
|
|
72031
|
-
When you offer, invite the user to add anything in their own words — whatever they give you goes into the
|
|
72032
|
-
|
|
72033
|
-
What to send —
|
|
72034
|
-
|
|
72035
|
-
|
|
72036
|
-
|
|
72037
|
-
|
|
72038
|
-
|
|
72039
|
-
|
|
72040
|
-
|
|
72041
|
-
|
|
72258
|
+
- The user asks to report something to Wix ("tell Wix that...", "report this", "send feedback"). Then confirm the wording and send.
|
|
72259
|
+
- The user complains or reports a Wix bug in the course of the work ("this API is broken", "the docs are wrong"). Acknowledge, then offer to pass it on.
|
|
72260
|
+
- A Wix API, tool or doc kept failing, or you had to invent a workaround for it. Offer: "This tripped us up — want me to report it to Wix?"
|
|
72261
|
+
|
|
72262
|
+
When you offer, invite the user to add anything in their own words — whatever they give you goes into the report verbatim.
|
|
72263
|
+
|
|
72264
|
+
What to send — that one issue, not the session:
|
|
72265
|
+
- What was being attempted, in a sentence.
|
|
72266
|
+
- Where it failed: the tool or endpoint, the HTTP status and error message, and the request id if there is one (pass it as requestId).
|
|
72267
|
+
- What you expected instead, and the workaround if you found one.
|
|
72268
|
+
- Where the fault likely lives: API behavior / API schema / API reference docs / docs articles or examples / Wix tooling / unsure.
|
|
72269
|
+
- Only the context needed to reproduce it: agent/model, site id, the Wix area or API.
|
|
72270
|
+
No session summary or play-by-play, and nothing unrelated to the issue. Several distinct issues are separate reports, each approved by the user.
|
|
72271
|
+
|
|
72272
|
+
**IMPORTANT**: This tool actually sends the report to Wix. Confirm the final wording with the user and call it only after an explicit yes.
|
|
72273
|
+
Do not send on a single transient error, and never more than once for the same issue. Reports cannot be replied to or tracked by the user.
|
|
72042
72274
|
`,
|
|
72043
72275
|
BrowseWixRESTDocsMenu: dedent_default`
|
|
72044
72276
|
Browse the Wix REST API documentation menu hierarchy.
|
|
@@ -72060,25 +72292,7 @@ function buildToolDescriptions(includeReadme, includeImageUploadGuidance = true)
|
|
|
72060
72292
|
${reminder}
|
|
72061
72293
|
`,
|
|
72062
72294
|
WixSiteCreation: dedent_default`
|
|
72063
|
-
|
|
72064
|
-
|
|
72065
|
-
Opens the in-chat Wix site creation chooser as an interactive widget where the user chooses between "Build with AI" and "Pick a template."
|
|
72066
|
-
|
|
72067
|
-
**Once you can tell what the site is for, call this tool directly** — no ${includeReadme ? "WixREADME, skill," : "skill"} or docs search first.${includeReadme ? " Any other Wix request still starts with WixREADME as usual." : ""}
|
|
72068
|
-
|
|
72069
|
-
Call this for normal new Wix site creation requests when the user's site intent is clear, but they have not chosen AI, templates, or Wix Studio.
|
|
72070
|
-
Do not guess, and never default to AI — even after the user answers a clarifying question about the site's purpose or features.
|
|
72071
|
-
This chooser is how the builder choice gets made — never ask in chat whether they want AI or a template; that choice is made in the widget.
|
|
72072
|
-
The widget also does the creating: once the user picks, it runs that path itself and the site is created there, so never call \`WixSiteBuilder\`, \`SearchSiteTemplates\`, or \`CreateSiteFromTemplate\` yourself after opening it.
|
|
72073
|
-
After calling, reply with the message it returns, which presents both options and the next steps.
|
|
72074
|
-
|
|
72075
|
-
Do not call this if the user explicitly asks to build with AI; call \`WixSiteBuilder\` instead.
|
|
72076
|
-
Do not call this if the user asks for templates or Wix Studio; call \`SearchSiteTemplates\` instead.
|
|
72077
|
-
Not for a site the user wants you to build in code, a design you worked out together, or an app: call \`StartHeadlessBuild\`.
|
|
72078
|
-
|
|
72079
|
-
When calling this tool, infer \`customActions\` from the user's request so the reply can be tailored — 2-3 concrete, industry-specific setup actions for the site (see the input's guidance).
|
|
72080
|
-
|
|
72081
|
-
After calling, you MUST speak the message provided in the tool result to the user as your reply — do not stay silent and do not replace it with a one-line pointer to the widget. Write out ALL of it, word for word: its opening line (the "Ready to set up your … site?" question INCLUDING "Choose your path in the widget above:"), BOTH of its option bullets, and its "Next up:" line, each on its own line and in that order. Do not summarize, shorten, drop any line, invent your own opener, rename the options, or add an intro or outro.
|
|
72295
|
+
Returns which Wix tool creates a new site, and creates nothing itself. A new site is written in code and uploaded: StartDeployWebsite returns the upload guide, and StartHeadlessBuild returns the guide for a site that needs Wix business features. Use WixHarmonyEditorBuild or SearchSiteTemplates only when the user asked for Wix's editor, a template, Wix Studio or the Classic Editor.
|
|
72082
72296
|
`,
|
|
72083
72297
|
"import-claude-design-from-url": dedent_default`
|
|
72084
72298
|
Import a design created in Claude's design tool into Wix. Only for the signed \`claudeusercontent.com\` bundle URL Claude Design's "Send to Wix" produces (a self-contained HTML bundle with all images, fonts, and styles inlined). Creates a live Wix-hosted site and returns its URL.
|
|
@@ -72108,6 +72322,13 @@ function buildToolDescriptions(includeReadme, includeImageUploadGuidance = true)
|
|
|
72108
72322
|
`,
|
|
72109
72323
|
SearchWixWDSDocumentation: dedent_default`
|
|
72110
72324
|
Searches the Wix Design System (WDS) documentation.
|
|
72325
|
+
`,
|
|
72326
|
+
SearchWixHelpCenter: dedent_default`
|
|
72327
|
+
Searches the Wix Help Center (support.wix.com): how site owners do things in the Wix dashboard and editors, such as connecting a domain, managing a Premium plan, setting up a store or bookings, and fixing account or site issues.
|
|
72328
|
+
${HELP_CENTER_IS_FOR_PEOPLE}
|
|
72329
|
+
Use it for "how do I ... in Wix" questions about the product, or to give the user click-by-click steps for something no API covers.
|
|
72330
|
+
Not for building with code: for Wix APIs, SDK, CLI, apps, or Headless, use the matching developer documentation search.
|
|
72331
|
+
Results are excerpts; read a full article by passing its support.wix.com link to \`ReadFullDocsArticle\`.
|
|
72111
72332
|
`,
|
|
72112
72333
|
SearchWixSDKDocumentation: dedent_default`
|
|
72113
72334
|
Searches the Wix JavaScript SDK documentation.
|
|
@@ -72118,7 +72339,7 @@ function buildToolDescriptions(includeReadme, includeImageUploadGuidance = true)
|
|
|
72118
72339
|
`,
|
|
72119
72340
|
SearchDevelopmentDocumentation: dedent_default`
|
|
72120
72341
|
Broad Wix development documentation (platform concepts, developer guides, getting started). **Last resort — development tasks only.**
|
|
72121
|
-
Skip it entirely for general, business, support, or Wix-editor questions
|
|
72342
|
+
Skip it entirely for general, business, support, or Wix-editor questions; for those, use \`SearchWixHelpCenter\`.
|
|
72122
72343
|
Call it only after the specific search for your task returned nothing useful: \`SearchWixRESTDocumentation\` (REST), \`SearchWixSDKDocumentation\` (JS SDK), \`SearchWixCLIDocumentation\` (CLI), \`SearchBuildAppsDocumentation\` (apps), \`SearchWixHeadlessDocumentation\` (Headless), \`SearchWixWDSDocumentation\` (WDS). Never use it as a first search.
|
|
72123
72344
|
`,
|
|
72124
72345
|
SearchWixHeadlessDocumentation: dedent_default`
|
|
@@ -72130,7 +72351,8 @@ function buildToolDescriptions(includeReadme, includeImageUploadGuidance = true)
|
|
|
72130
72351
|
// `sdk` is simply absent on methods the SDK docs don't list.
|
|
72131
72352
|
SearchWixAPISpec: dedent_default`
|
|
72132
72353
|
Inspect the Wix REST API spec, and the JavaScript SDK call for each method, by writing JavaScript code that runs in a sandboxed read-only environment.
|
|
72133
|
-
|
|
72354
|
+
The spec covers every Wix product's methods and their data: ${WIX_API_DATA}.
|
|
72355
|
+
**Precondition:** you already have a method \`docsUrl\` — from \`SearchWixRESTDocumentation\`, \`SearchWixSDKDocumentation\` (its \`?apiView=SDK\` URLs work here as-is), \`BrowseWixRESTDocsMenu\`, \`ReadFullDocsArticle\`, ${includeReadme ? "a Wix skill, " : ""}or a prior tool result / the user's message in this conversation. If you don't have one yet, call \`SearchWixRESTDocumentation\` (or \`SearchWixSDKDocumentation\` when writing SDK code) FIRST to discover it; do not use this tool to search for or choose an endpoint.
|
|
72134
72356
|
**Never pass a \`docsUrl\` you produced from memory.** If the exact URL you are about to pass to \`getResourceSchemaByUrl\` did not appear verbatim in an earlier tool result (or the user's message), it is a guess — call \`SearchWixRESTDocumentation\` first and use a URL from its ranked results. A guessed URL that merely looks plausible routinely resolves to the WRONG sibling method (e.g. \`.../products-v3/create-product\` when the task needs \`.../products-v3/create-product-with-inventory\`), sending the whole turn down a dead end. When in doubt, discover — don't guess.
|
|
72135
72357
|
**This tool's job is to INSPECT the exact schema of a method you have ALREADY located — its request/response shape, nested types, and enums, and its SDK call (\`method.sdk\`). It is NOT a discovery tool for choosing which method to use.**
|
|
72136
72358
|
With a method \`docsUrl\` in hand, call \`getResourceSchemaByUrl(methodDocsUrl)\` to get the resource schema, then read the target method from \`schema.methods\` and resolve any nested \`{ $circular: name }\` types via \`schema.components.schemas[name]\`.
|
|
@@ -72511,27 +72733,18 @@ function buildToolDescriptions(includeReadme, includeImageUploadGuidance = true)
|
|
|
72511
72733
|
\`\`\`
|
|
72512
72734
|
`,
|
|
72513
72735
|
ExecuteWixAPI: executeWixApiDescription,
|
|
72514
|
-
|
|
72515
|
-
|
|
72516
|
-
|
|
72517
|
-
|
|
72518
|
-
|
|
72519
|
-
Call this ONLY when the user's own words name AI (for example "create a site using AI" or "build it with AI") and the site intent is clear. A description of what the site should do — reservations, online ordering, a store, bookings, menus, a portfolio, and the like — is NOT a request for AI and NOT enough to call this tool; never infer AI from features or industry.
|
|
72520
|
-
Never default to this tool: if the user hasn't explicitly named AI, don't call this tool — ${SITE_CREATION_COPY.unstatedMethod.nonWidget}.
|
|
72521
|
-
|
|
72522
|
-
For templates or Wix Studio, call \`SearchSiteTemplates\` (\`builder: classic\` for the Classic Editor); for a template id, \`CreateSiteFromTemplate\`. A site the user wants you to build in code, or an app: \`StartHeadlessBuild\`.
|
|
72523
|
-
|
|
72524
|
-
Do NOT suggest HTML code, prompt templates, or alternative approaches instead of building — actually build the site through this tool. (HTML the user already has is the StartDeployWebsite case, not a reason to build.)
|
|
72736
|
+
// Named in SERVER_INSTRUCTIONS: when this tool's name or what it is for changes, update them to match.
|
|
72737
|
+
WixHarmonyEditorBuild: dedent_default`
|
|
72738
|
+
A secondary site-creation tool, only for a user who asked for the Wix Harmony Editor or for Wix to design the site in Wix's editor. A request for a site on Wix, or for Wix to build or make one, is neither. Don't call it for any other site request, not even to check with the flag false. A new site is otherwise written in code and uploaded, with StartDeployWebsite, or StartHeadlessBuild when it needs Wix business features.
|
|
72739
|
+
Builds a site with the Wix Harmony Editor: Wix designs a first version from the user's description, and the user keeps designing it in Wix's editor. Shows the build's progress and a preview.
|
|
72740
|
+
Call it when the user asked for the Wix Harmony Editor, or for Wix to design the site in Wix's editor, in their own words or as their answer to your question, and quote those words in \`editorRequest\`. ${EDITOR_TAIL}
|
|
72525
72741
|
`,
|
|
72742
|
+
// Named in SERVER_INSTRUCTIONS: when this tool's name or what it is for changes, update them to match.
|
|
72526
72743
|
SearchSiteTemplates: dedent_default`
|
|
72527
|
-
|
|
72528
|
-
|
|
72529
|
-
|
|
72530
|
-
|
|
72531
|
-
Call this ONLY when the user's own words ask for a template, for Wix Studio or for the Classic Editor (for example "start from a template", "show me some templates", "build it in Wix Studio", "the old Wix editor") and you can already tell what the site is for. If they mention Wix Studio, search Studio templates; if they ask for the Classic Editor (the Wix Editor), search \`classic\`; otherwise search Harmony templates.
|
|
72532
|
-
${SITE_CREATION_COPY.templatePick.nonWidget}
|
|
72533
|
-
|
|
72534
|
-
A description of what the site should do — bookings, a store, a menu, a portfolio, and the like — is NOT a request for templates or for Wix Studio; never infer either from features or industry. Templates are not the default: if the site intent is clear but no method is named, do not guess — ${SITE_CREATION_COPY.unstatedMethod.nonWidget}.`,
|
|
72744
|
+
A secondary site-creation tool, only for a user who asked for a template, Wix Studio or the Classic Editor. Don't call it for any other site request, not even to check with the flag false. A new site is otherwise written in code and uploaded, with StartDeployWebsite, or StartHeadlessBuild when it needs Wix business features.
|
|
72745
|
+
Shows a gallery of Wix templates, from Harmony, Wix Studio or the Classic Editor, for a site the user will design in Wix's editor. Wix templates come with Wix's business features (a store, online ordering, bookings, forms), so a request for a template comes here even when the site needs them.
|
|
72746
|
+
Call it when the user asked for a template, Wix Studio or the Classic Editor, in their own words or as their answer to your question, and quote those words in \`templateRequest\`. ${EDITOR_TAIL} ${SITE_CREATION_COPY.templatePick.nonWidget}
|
|
72747
|
+
`,
|
|
72535
72748
|
CreateSiteFromTemplate: dedent_default`
|
|
72536
72749
|
Creates a Wix site from a specific template (by \`metaSiteId\` or \`templateId\`), publishes it when possible, and shows a live preview with links to the editor and the published site.
|
|
72537
72750
|
|
|
@@ -72565,103 +72778,212 @@ function buildToolDescriptions(includeReadme, includeImageUploadGuidance = true)
|
|
|
72565
72778
|
Set \`hasMutations: true\` for any document containing a mutation root field.
|
|
72566
72779
|
`,
|
|
72567
72780
|
UploadHeadlessWebsiteFiles: dedent_default`
|
|
72568
|
-
The upload step of the StartDeployWebsite and StartHeadlessBuild guides, and nothing else: puts a finished
|
|
72569
|
-
Pass the files themselves: in
|
|
72570
|
-
NOT a site-creation tool: a request to create, build, design or generate a site — with or without a description — never comes here (
|
|
72781
|
+
The upload step of the StartDeployWebsite and StartHeadlessBuild guides, and nothing else: puts a finished website's files — a static site (index.html plus its CSS/JS/images, a static build, or a zip of the site) or a Wix Astro build — onto an existing Wix Headless site by its metaSiteId. Call it ONLY after one of them has returned its guide in this conversation and the site exists: for a new site, first run the recipe's provision call and pass the metaSiteId it returns; for a site deployed earlier, pass its metaSiteId. It does not create sites. Every upload replaces the whole file set and the URL stays. Returns the live URL and the dashboard link, and points back to the recipe for what comes next.
|
|
72782
|
+
Pass the files themselves: in ${FILE_PARAM_CLIENTS} as \`attachments\` (any type, a zip is unpacked), elsewhere as the \`files\` text bundle (\`=== FILE: <path> ===\` sections, \`base64\` tag for small binaries). A static site must contain index.html at its root. A Wix Astro build with no file handle, from a shell that reaches the internet, goes in two calls: zip the build, call with \`prepare: true\` and the zip's \`size\` in bytes, PUT the zips it names with the \`curl\` commands it returns (the build, and the project source when the site's repository accepts it), then call again with the \`uploadKey\` it returned; that releases the build. The two calls, literally: {siteId, prepare: true, size} then {siteId, uploadKey, sourceUploadId?, expectedHeadRevisionId?, releaseNotes?}. A sandbox whose network is limited to a few hosts cannot upload to those URLs. A static site does not use the two calls. A Wix Astro build (the project's .wix/ and dist/ after \`astro build\` with the Wix hosting adapter, zipped from the project root) needs no index.html: it is released to the site's Wix hosting instead, server-rendered pages, the same site and URL. The project's source is stored with the release when the upload holds the project and the site's repository accepts it.
|
|
72783
|
+
NOT a site-creation tool: a request to create, build, design or generate a site — with or without a description — never comes here first. Unless the user asked for Wix's editor or a template (WixHarmonyEditorBuild, SearchSiteTemplates), call StartDeployWebsite right away, without asking the user anything: it also takes files the user brought, uploaded first even when the site needs business features. StartHeadlessBuild instead for a new site with no files that needs Wix business features. Also NOT for media uploads to an existing site (UploadImageToWixSite) or any other API call (ExecuteWixAPI).
|
|
72571
72784
|
`,
|
|
72785
|
+
// Named in SERVER_INSTRUCTIONS: when this tool's name or what it is for changes, update them to match.
|
|
72572
72786
|
StartDeployWebsite: dedent_default`
|
|
72573
|
-
|
|
72574
|
-
|
|
72575
|
-
|
|
72576
|
-
|
|
72577
|
-
NOT for: a screenshot or reference of a site the user wants Wix to generate (the site-creation tools); a site described in words with no code yet (StartHeadlessBuild); a Wix editor site's content or settings (WixSiteBuilder's edit mode, or WixREADME); a Claude Design bundle URL (import-claude-design-from-url); migrating a live site by URL or CSV exports; adding HTML or code into an existing Wix site; uploading images or documents to a site's media (UploadImageToWixSite).
|
|
72787
|
+
Creates a website on Wix and puts it live, or replaces the files of one deployed earlier. You write the site's code, or take the files the user brought (HTML/CSS/JS, a static build, a zip, another builder's export), and this returns the guide to create the site and upload them. Updates keep the same site and URL. Works with or without a Wix login (anonymous deploy with a save link), through the Wix MCP alone or from a shell. Call it right away, without asking the user anything first.
|
|
72788
|
+
When a new site needs Wix business features (${WIX_BUSINESS_FEATURES}), call StartHeadlessBuild instead. When the user brought files and the site needs those features, upload the files here first; the upload's result then points to StartHeadlessBuild to connect them.
|
|
72789
|
+
Returns the guide; follow it and do the work yourself. Upload with UploadHeadlessWebsiteFiles once the site exists; the drop page is only the fallback.
|
|
72790
|
+
NOT for: a user who asked for Wix's editor, the Wix Harmony Editor, a template, Wix Studio or the Classic Editor (WixHarmonyEditorBuild, SearchSiteTemplates); a Claude Design bundle URL (import-claude-design-from-url); migrating a live site by URL or CSV exports; adding HTML or code into an existing Wix editor site; uploading images or documents to a site's media (UploadImageToWixSite).
|
|
72578
72791
|
`,
|
|
72792
|
+
// Named in SERVER_INSTRUCTIONS: when this tool's name or what it is for changes, update them to match.
|
|
72579
72793
|
StartHeadlessBuild: dedent_default`
|
|
72580
|
-
|
|
72581
|
-
Call it right away: it only returns the guide, and the site's
|
|
72582
|
-
NOT for:
|
|
72794
|
+
Returns Wix's headless guide, for a site that needs Wix business features (${WIX_BUSINESS_FEATURES}), run by Wix as a Wix Headless site. You write the site; the guide creates it, connects the features, and uploads it. Also to add those features to an existing Wix Headless site (one deployed from files is one), from a project download link, or to move a Wix site to code.
|
|
72795
|
+
Call it right away: it only returns the guide, and the site's details are not needed first.
|
|
72796
|
+
NOT for: a site that needs no Wix business feature, or files the user brought that are not live yet (StartDeployWebsite: upload them first, then come back here for the features); a user who asked for Wix's editor, the Wix Harmony Editor, a template, Wix Studio or the Classic Editor, even when the site needs business features (WixHarmonyEditorBuild, SearchSiteTemplates); a Claude Design URL (import-claude-design-from-url).
|
|
72583
72797
|
`
|
|
72584
72798
|
};
|
|
72585
|
-
|
|
72586
|
-
|
|
72799
|
+
descriptions.SupportAndFeedback = descriptions.ReportIssueToWix;
|
|
72800
|
+
return descriptions;
|
|
72801
|
+
}
|
|
72802
|
+
var defaultToolDescriptions = buildToolDescriptions(true, true, { usageGuideOnce: true });
|
|
72803
|
+
var WIX_SKILLS_README_SECTION = dedent_default`
|
|
72804
|
+
## Wix skills
|
|
72805
|
+
|
|
72806
|
+
Wix publishes agent skills: folders of instructions, scripts and shipped code for building on Wix, each with a \`SKILL.md\` at its root that says what the skill does and which of its files to read when. The source is https://github.com/wix/skills. Three of them matter here:
|
|
72807
|
+
|
|
72808
|
+
- **wix-headless-kit**: builds a Wix Headless site on shipped, verified code. In the Wix plugin. Its contents are below.
|
|
72809
|
+
- **wix-headless-templates**: the code wix-headless-kit builds from, one folder per Wix Business Solution. In the Wix plugin for Codex and Cursor. Its contents are below.
|
|
72810
|
+
- **wix-manage**: REST recipes to configure and manage a site's business solutions. In the Wix plugin. Its \`SKILL.md\` is the index of every recipe by area, with what it does and a link to read it.
|
|
72811
|
+
|
|
72812
|
+
On a site built in code (one deployed through StartDeployWebsite, started through StartHeadlessBuild, or any Wix Headless project), wix-headless-kit carries the work, with wix-headless-templates as its code, and it names the wix-manage recipes it uses as steps.
|
|
72813
|
+
|
|
72814
|
+
### How to read a skill
|
|
72815
|
+
|
|
72816
|
+
A skill is a folder, and every file in it has a path inside that folder (\`SKILL.md\`, \`guides/api-run.md\`). The same path finds the file on disk and online, so the paths below work either way.
|
|
72817
|
+
|
|
72818
|
+
1. **From disk, when it is already there.** This is the preferred way: the files are complete and need no network. The Wix plugin loads its skills into the client; \`npx skills add\` puts them under \`.agents/skills/<skill>/\` in the project, or in the user's home with \`-g\`; an earlier install may have left them wherever the client keeps skills (for example \`.claude/skills/\` or the plugin's folder). Open \`<skill folder>/SKILL.md\` and the files it names. An installed copy can be an older snapshot. A file whose byte size differs from the one in the skill's manifest (below) is out of date, so read it online; a matching size makes a file likely current, not certain, so when a file decides the work, read it online too.
|
|
72819
|
+
2. **Install them, with a shell that reaches the internet.** \`npx skills add wix/skills\` installs every skill; \`npx skills add wix/skills --skill wix-headless-kit\` installs one. Then read them from disk. To keep them across projects, the user can install the Wix plugin instead (in Claude Code: \`/plugin marketplace add wix/skills\`, then \`/plugin install wix@wix\`).
|
|
72820
|
+
3. **Read them online, with ReadFullDocsArticle**, when neither works: no shell, or a sandbox without internet. Call ReadFullDocsArticle with the URL as \`articleUrl\`; it returns the file whole, where a client's own web tool often cannot reach www.wix.com or summarizes what it fetches. The skills registry mirrors every skill from the main branch of wix/skills:
|
|
72821
|
+
- **A file**: \`https://www.wix.com/skills/<skill>/<path>\`, with \`<path>\` its path inside the skill folder. Start with \`<path>\` = \`SKILL.md\`, then read the files it names.
|
|
72822
|
+
- **A folder**: \`https://www.wix.com/skills/<skill>/<folder>\` returns the full URL of every file under it, at any depth. \`https://www.wix.com/skills/<skill>/<folder>/_content\` returns those files' contents in one response, each under a heading with its URL, Markdown first; binary files and lockfiles are left out, and past 150K characters the rest are named by URL, to read one by one.
|
|
72823
|
+
- **The skill's file list**: \`https://www.wix.com/skills/<skill>/\`, with the trailing slash, returns the full URL of every file in the skill; without the slash it returns the SKILL.md.
|
|
72824
|
+
- **Every file in the skill**: \`https://www.wix.com/skills/<skill>.manifest.json\` lists each path with its size, under a \`base\` URL.
|
|
72825
|
+
- **Names and hosts**: \`<skill>\` is the folder name with or without its \`wix-\` prefix (\`wix-headless-kit\` or \`headless-kit\`), and \`dev.wix.com\` works in place of \`www.wix.com\`.
|
|
72826
|
+
- **What comes back**: a Markdown file comes with a short note on top (it is mirrored from the main branch of wix/skills; the skill's manifest, folder listings, \`_content\`, and ReadFullDocsArticle) and its relative links turned into full URLs; code, scripts and JSON come as they are.
|
|
72827
|
+
- **A wrong path**: the answer names the files with that name elsewhere in the skill and the manifest URL, so one more call reaches the right file. ReadFullDocsArticle shows that answer as an error.
|
|
72828
|
+
- **Not served**: a whole skill as one page (\`<skill>-full\`) returns 404; read the skill's files instead.
|
|
72829
|
+
|
|
72830
|
+
The wix-manage recipes are also published in the Wix docs, as articles at \`…/skills/<recipe>\` under each API's section. Find the one that matches the task in the skill's recipe index (\`SKILL.md\`) or with SearchWixRESTDocumentation, and read it with ReadFullDocsArticle. Only wix-manage is in the docs. For example, one recipe in all three places:
|
|
72831
|
+
- on disk: \`<wix-manage folder>/references/sites/upload-static-site.md\`;
|
|
72832
|
+
- in the registry: https://www.wix.com/skills/manage/references/sites/upload-static-site.md;
|
|
72833
|
+
- in the docs: https://dev.wix.com/docs/api-reference/account-level/sites/skills/upload-a-website-or-html-files.
|
|
72834
|
+
|
|
72835
|
+
### wix-manage
|
|
72836
|
+
|
|
72837
|
+
REST recipes for managing a site's business solutions: one recipe per task (installing apps, products, booking services, CMS items, SEO, domains and more), each with the exact endpoints, request bodies and order of steps. Open the recipe for a task before calling its APIs.
|
|
72838
|
+
|
|
72839
|
+
Ways to find and read a recipe, in this order:
|
|
72840
|
+
1. **On disk**: the Wix plugin's wix-manage folder, or \`.agents/skills/wix-manage/\` after \`npx skills add wix/skills --skill wix-manage\`. \`SKILL.md\` lists every recipe by area with what it does; the recipe itself is under \`references/<area>/\` (ecommerce nests one more folder, such as \`references/ecommerce/shipping/\`), so open the path \`SKILL.md\` gives rather than building it. An installed copy can be an older snapshot: when a recipe decides the work, read it online too.
|
|
72841
|
+
2. **Online**: the list of every recipe by area, each a link to its docs article, is https://dev.wix.com/docs/api-reference/articles/ai-tools/wix-mcp/skills/wix-management-recipes-index.md. Read it with ReadFullDocsArticle, or with \`curl\` from a shell, then read the recipe for the task the same way. It is public: no sign-in or token.
|
|
72842
|
+
|
|
72843
|
+
Using a recipe: follow its steps, and make its calls with ExecuteWixAPI, passing the recipe's docs URL in \`sourceDocUrls\`. When a recipe's example doesn't fit a call, read that method's schema with SearchWixAPISpec first. When no recipe matches the task, find the method with SearchWixRESTDocumentation or BrowseWixRESTDocsMenu, read it with ReadFullDocsArticle, and call it the same way.
|
|
72844
|
+
Each API area also has a page that lists only its own recipes: the area's docs section with \`/skills.md\` appended. These are the ones today, but it is not a closed list: areas are added, so look a task up in the full list first, and for an API not named here try its section URL with \`/skills.md\` appended.
|
|
72845
|
+
- Accessibility: https://dev.wix.com/docs/api-reference/site/accessibility/skills.md
|
|
72846
|
+
- Analytics: https://dev.wix.com/docs/api-reference/business-management/analytics/skills.md
|
|
72847
|
+
- App Installation: https://dev.wix.com/docs/api-reference/business-management/app-installation/skills.md
|
|
72848
|
+
- App tools: https://dev.wix.com/docs/api-reference/app-management/app-tools/skills.md
|
|
72849
|
+
- Automations: https://dev.wix.com/docs/api-reference/business-management/automations/skills.md
|
|
72850
|
+
- Blog: https://dev.wix.com/docs/api-reference/business-solutions/blog/skills.md
|
|
72851
|
+
- Bookings: https://dev.wix.com/docs/api-reference/business-solutions/bookings/skills.md
|
|
72852
|
+
- Calendar: https://dev.wix.com/docs/api-reference/business-management/calendar/skills.md
|
|
72853
|
+
- CMS: https://dev.wix.com/docs/api-reference/business-solutions/cms/skills.md
|
|
72854
|
+
- Contacts: https://dev.wix.com/docs/api-reference/crm/members-contacts/contacts/skills.md
|
|
72855
|
+
- Domains: https://dev.wix.com/docs/api-reference/account-level/domains/skills.md
|
|
72856
|
+
- eCommerce: https://dev.wix.com/docs/api-reference/business-solutions/e-commerce/skills.md
|
|
72857
|
+
- Events: https://dev.wix.com/docs/api-reference/business-solutions/events/skills.md
|
|
72858
|
+
- Forms: https://dev.wix.com/docs/api-reference/crm/forms/skills.md
|
|
72859
|
+
- Get Paid: https://dev.wix.com/docs/api-reference/business-management/get-paid/skills.md
|
|
72860
|
+
- Google Ads: https://dev.wix.com/docs/api-reference/business-management/marketing/ads/google-ads/skills.md
|
|
72861
|
+
- Google Business Profile: https://dev.wix.com/docs/api-reference/business-management/google-business-profile/skills.md
|
|
72862
|
+
- Google Search Console: https://dev.wix.com/docs/api-reference/business-management/seo/google-search-console/skills.md
|
|
72863
|
+
- Headless: https://dev.wix.com/docs/api-reference/business-management/headless/skills.md
|
|
72864
|
+
- Marketing: https://dev.wix.com/docs/api-reference/business-management/marketing/skills.md
|
|
72865
|
+
- Media: https://dev.wix.com/docs/api-reference/assets/media/skills.md
|
|
72866
|
+
- Pricing Plans: https://dev.wix.com/docs/api-reference/business-solutions/pricing-plans/skills.md
|
|
72867
|
+
- Restaurants: https://dev.wix.com/docs/api-reference/business-solutions/restaurants/skills.md
|
|
72868
|
+
- Rich Content: https://dev.wix.com/docs/api-reference/assets/rich-content/skills.md
|
|
72869
|
+
- SEO: https://dev.wix.com/docs/api-reference/business-management/seo/skills.md
|
|
72870
|
+
- SEO redirects: https://dev.wix.com/docs/api-reference/business-management/seo/redirects/skills.md
|
|
72871
|
+
- Site Properties: https://dev.wix.com/docs/api-reference/business-management/site-properties/skills.md
|
|
72872
|
+
- Sites: https://dev.wix.com/docs/api-reference/account-level/sites/skills.md
|
|
72873
|
+
- Stores: https://dev.wix.com/docs/api-reference/business-solutions/stores/skills.md
|
|
72874
|
+
- Wix MCP: https://dev.wix.com/docs/api-reference/articles/ai-tools/wix-mcp/skills.md
|
|
72875
|
+
|
|
72876
|
+
### wix-headless-kit
|
|
72877
|
+
|
|
72878
|
+
Builds a Wix Headless site on shipped, verified code instead of writing the integration: each Wix Business Solution comes with a typed data layer, hooks, components, pages and a seed script that are already correct. The data layer ships twice, on \`@wix/sdk\` for the React core and as plain REST calls for a stack that cannot run it (\`guides/reference-mode.md\`), and the agent's work narrows to brand, layout, copy and wiring. It runs as a CLI flow from a shell that reaches Wix, and as Wix API calls through this MCP when it cannot.
|
|
72879
|
+
|
|
72880
|
+
Paths are inside the skill folder; online, each is \`https://www.wix.com/skills/headless-kit/<path>\`.
|
|
72881
|
+
- Before the skill: the cold start installs it, signs in and hands off. It is another skill's file, https://www.wix.com/skills/headless-cold-start/headless-kit.md, and StartHeadlessBuild returns it.
|
|
72882
|
+
- \`SKILL.md\`: the steps of a build and the table of Business Solutions the kit ships.
|
|
72883
|
+
- \`guides/api-run.md\`: the whole run as Wix API calls through this MCP, for an agent whose shell cannot reach Wix or that has no shell.
|
|
72884
|
+
- \`guides/capabilities.md\`: which Wix product owns which feature, and what the kit ships for it.
|
|
72885
|
+
- \`guides/existing-site.md\`: a new frontend for a Wix site that already has its content.
|
|
72886
|
+
- \`guides/migration.md\`: a site moving to code after "Go Headless" in its dashboard.
|
|
72887
|
+
- \`guides/reference-mode.md\`: a stack that cannot run the shipped React code (a static site, a server-rendered app in another language).
|
|
72888
|
+
- \`guides/feedback.md\`: sending the user's building-with-Wix feedback to Wix.
|
|
72889
|
+
- \`install/\`: the bootstrap, setup, deploy and templates scripts, and \`install/pins.json\` with the pinned CLI and templates versions.
|
|
72890
|
+
|
|
72891
|
+
### wix-headless-templates
|
|
72892
|
+
|
|
72893
|
+
The code wix-headless-kit builds from, one folder per Wix Business Solution: \`storefront\`, \`bookings\`, \`rentals\`, \`blog\`, \`cms\`, \`forms\`, \`members\`, \`events\`, \`restaurants\`, \`donations\`, \`pricing-plans\`, \`portfolio\`, \`faq\`. It holds no flow of its own; wix-headless-kit fetches it and copies, deploys and seeds from it.
|
|
72894
|
+
|
|
72895
|
+
Paths are inside the skill folder; online, each is \`https://www.wix.com/skills/headless-templates/<path>\`. Every Business Solution folder has the same parts, with \`<solution>\` one of the names above:
|
|
72896
|
+
- \`<solution>/INSTRUCTIONS.md\`: the playbook, covering what ships, what you build, and each page's contract.
|
|
72897
|
+
- \`<solution>/app/\`: the typed React core: the data layer under \`wix/<solution>/\`, hooks and components.
|
|
72898
|
+
- \`<solution>/app-astro/\`: the Astro page skeletons for Wix-managed Astro sites (every solution but \`forms\`).
|
|
72899
|
+
- \`<solution>/project/\`: the whole runnable project for that solution.
|
|
72900
|
+
- \`<solution>/rest/\`: the same data layer as plain REST calls, for stacks that cannot run the React core.
|
|
72901
|
+
- \`<solution>/seed/SEED.md\`: how to seed that solution's content, with the script that creates it in the right order.
|
|
72902
|
+
|
|
72903
|
+
Shared by every solution:
|
|
72904
|
+
- \`shared/DESIGN.md\`: the design floor when the brief gives no design direction.
|
|
72905
|
+
- \`shared/CONTENT.md\`: the copy floor for every page written.
|
|
72906
|
+
- \`shared/SUPPLIED-CONTENT.md\`: content the user brings (a CSV, a menu, a folder of photos) as the seed plan.
|
|
72907
|
+
- \`shared/CUSTOM_OPERATIONS.md\`: operations beyond what the shipped code covers.
|
|
72908
|
+
- \`shared/rest/client.ts\`: the REST client the \`rest/\` layers use.
|
|
72909
|
+
|
|
72910
|
+
Online, a solution's folder lists everything it ships: https://www.wix.com/skills/headless-templates/storefront returns the URLs of the store's files, and \`…/storefront/app\` those of its React core. A part is often small enough to read whole in one call: https://www.wix.com/skills/headless-templates/storefront/seed/_content returns the store's seeding guide and scripts together. A whole solution passes the 150K cap, so read it part by part.
|
|
72911
|
+
`;
|
|
72587
72912
|
var recipesIndexDoc = {
|
|
72588
72913
|
url: "https://dev.wix.com/docs/api-reference/articles/ai-tools/wix-mcp/skills/wix-management-recipes-index",
|
|
72589
72914
|
action: "include"
|
|
72590
72915
|
};
|
|
72591
72916
|
var README_INTRO = dedent_default`
|
|
72592
|
-
|
|
72917
|
+
# How to work with Wix through these tools
|
|
72593
72918
|
|
|
72594
|
-
|
|
72919
|
+
## Source of truth
|
|
72595
72920
|
|
|
72596
|
-
|
|
72597
|
-
Do not answer from memory about anything Wix-specific — this covers every part of your answer, not only API calls: any URL, link, ID, setting location, or product fact you give the user must come from the docs tools, the recipes below, a previous tool result in this conversation, or the user's own message (identifiers and URLs the user supplies are fine to use as given). If a recipe in the index below matches what the user asked for, read it before answering. For APIs, use the search, browse, read-docs, and schema tools as the source of truth for the exact URL, HTTP method, request body shape, response shape, field names, required fields, and enum values before calling an API.
|
|
72598
|
-
</source-of-truth>
|
|
72921
|
+
Do not answer from memory about anything Wix-specific — this covers every part of your answer, not only API calls: any URL, link, ID, setting location, or product fact you give the user must come from the docs tools, a Wix skill (installed, or read online as the Wix skills section below explains), a previous tool result in this conversation, or the user's own message (identifiers and URLs the user supplies are fine to use as given). When a Wix skill covers what the user asked for, read it before answering. For APIs, use the search, browse, read-docs, and schema tools as the source of truth for the exact URL, HTTP method, request body shape, response shape, field names, required fields, and enum values before calling an API.
|
|
72599
72922
|
|
|
72600
|
-
|
|
72601
|
-
<goal>
|
|
72923
|
+
## Goal
|
|
72602
72924
|
`;
|
|
72603
|
-
var README_FLOWS_HEADING =
|
|
72604
|
-
|
|
72925
|
+
var README_FLOWS_HEADING = "## Wix MCP Flows";
|
|
72926
|
+
var README_FLOWS_SITE = dedent_default`
|
|
72927
|
+
### The site
|
|
72605
72928
|
|
|
72606
|
-
|
|
72929
|
+
The site context below lists the account's sites with their installed apps. Take the \`siteId\` from there; when more than one site fits and the user's words don't pick one, ask which before any read or write. A business solution's API (Stores, Bookings, CMS and the rest) works only on a site with that app installed, and some apps have versions with different endpoints (Wix Stores V1 vs V3): check the site's apps first, and when the app is missing, install it (a Wix skill has the steps) before using its API.
|
|
72607
72930
|
`;
|
|
72608
|
-
var
|
|
72609
|
-
|
|
72931
|
+
var README_FIND_SOURCES = dedent_default`
|
|
72932
|
+
### Find the method
|
|
72610
72933
|
|
|
72611
|
-
|
|
72612
|
-
|
|
72613
|
-
|
|
72614
|
-
|
|
72615
|
-
- SearchWixRESTDocumentation or BrowseWixRESTDocsMenu → ReadFullDocsArticle (no usable example) → SearchWixAPISpec for request schemas → ExecuteWixAPI
|
|
72934
|
+
A task may need several API methods. For each, take the first source that gives it:
|
|
72935
|
+
- A previous tool result in this conversation (not memory) already shows its request: go straight to the call.
|
|
72936
|
+
- A Wix skill that covers the task (the Wix skills section below says what each is for): follow it, from disk or online. When its example for a call matches your case, that is the source: pass its docs URL in \`sourceDocUrls\` instead of searching for the method pages (when it has no docs URL, one SearchWixRESTDocumentation call on its title finds the article).
|
|
72937
|
+
- The docs: SearchWixRESTDocumentation (semantic search) or BrowseWixRESTDocsMenu (menu hierarchy), then ReadFullDocsArticle on the method's article for its code examples. For SDK code, the CLI, a headless site or an app, start from those docs instead: SearchWixSDKDocumentation, SearchWixCLIDocumentation, SearchWixHeadlessDocumentation, SearchBuildAppsDocumentation.
|
|
72616
72938
|
|
|
72617
|
-
|
|
72939
|
+
Keep each method's docs URL even when no source gives a usable example: the shape comes from its schema, as the next section says.
|
|
72940
|
+
`;
|
|
72941
|
+
var README_FLOWS_BODY = dedent_default`
|
|
72942
|
+
### The exact shape
|
|
72618
72943
|
|
|
72619
|
-
|
|
72620
|
-
- SearchWixRESTDocumentation — semantic search over the Wix REST docs by keywords or natural-language queries.
|
|
72621
|
-
- BrowseWixRESTDocsMenu — navigate the Wix REST docs by menu hierarchy; alternative to keyword search.
|
|
72622
|
-
- ReadFullDocsArticle — fetch a full docs article by its docs URL; returns prose, fields, and code examples.
|
|
72623
|
-
- SearchWixAPISpec — JS-sandboxed query over the REST API spec; returns request schema, response schema, and the executable \`method.publicUrl\`.
|
|
72624
|
-
- ExecuteWixAPI — runs an async JS function in a sandbox with \`wix.request()\`; a single invocation can chain multiple API calls, paginate, loop, transform, and branch.
|
|
72944
|
+
A code example is the model for your call only when it matches your case, with every field your case needs. Fill the rest from the method's schema: SearchWixAPISpec on its docs URL (REST or SDK) returns the request and response schemas, \`method.publicUrl\` and \`method.sdk\`; ReadFullDocsMethodSchema when SearchWixAPISpec isn't available. A query's filter and sort fields and operators are a closed list per method: use only what its schema declares.
|
|
72625
72945
|
|
|
72626
|
-
|
|
72946
|
+
None of this comes from memory.
|
|
72627
72947
|
|
|
72628
|
-
|
|
72629
|
-
a. First try the WixREADME Recipes index below (pre-curated guides for common tasks). If a recipe matches, ReadFullDocsArticle on its docs URL to find relevant code examples; many recipes cover multi-step flows and supply code examples for several methods in one article.
|
|
72630
|
-
b. If no recipe matches the user's intent, or the matched recipe didn't yield the code examples you need, discover each missing method's docs URL via SearchWixRESTDocumentation (semantic search) or BrowseWixRESTDocsMenu (menu hierarchy), then ReadFullDocsArticle on each to find relevant code examples.
|
|
72631
|
-
c. If neither path turns up a usable code example for some method, continue without one for that method — step 2 will derive its request directly from the schema. Make sure you've still captured the docs URL of each method.
|
|
72948
|
+
### The call, or the code that makes it
|
|
72632
72949
|
|
|
72633
|
-
|
|
72634
|
-
- **Request** (URL, HTTP method, body fields) — skip the probe if a code example already shows them; otherwise SearchWixAPISpec returns publicUrl + exact request shape.
|
|
72635
|
-
- **Response shape** (field paths your code will read) — only relevant if your code reads response fields; skip the probe if the article(s) already made it clear; otherwise probe SearchWixAPISpec for the response schema.
|
|
72636
|
-
- **Filter and sort** (query/search methods only) — an example proves only the fields and operators it uses. Each method declares which fields it can filter and sort by, and with which operators; that list is closed for fields and their operators and covers that method only — \`$and\`/\`$or\`/\`$not\` are filter syntax and never appear in it. Anything else errors or silently returns the wrong rows. A listed operator is valid on its own, since a field takes a single operator; to combine conditions, use the logical operators instead — \`$and\` and \`$or\` take an array of expressions, \`$not\` takes one, and they can nest.
|
|
72637
|
-
- Never guess any of this from memory.
|
|
72950
|
+
**Call it with ExecuteWixAPI**: one async JS function with \`wix.request()\`, holding every step of the task that code can resolve. The reads that fetch an ID, check whether a record exists or list items to choose from go in the same function as the writes they feed; step numbers in a guide or skill give logical order, not separate calls. Set \`hasMutations: true\` when any step writes. Return the write's response as is and report from it; don't read again to confirm. A new invocation only for what code can't resolve: the user's answer, or a job that finishes later. One function chains calls, paginates, lists all, loops, transforms and branches. Without ExecuteWixAPI, make each call with CallWixSiteAPI (a site's APIs) or ManageWixSite (the account's), from the same exact shape.
|
|
72638
72951
|
|
|
72639
|
-
|
|
72952
|
+
**Write the code** when the task is code the user keeps: an app (built and run with the Wix CLI), a headless site, or a script that calls the REST API or the JavaScript SDK. The path is the same: find the method, learn its exact shape, then write the call from \`method.publicUrl\` (REST) or \`method.sdk\` (the JavaScript SDK), never from memory. Every way of building against Wix in code is this path; the headless skills are a shortcut on it, not a different one. wix-headless-kit builds a Wix Headless site from shipped, verified code (wix-headless-templates holds it, one folder per business solution: a \`@wix/sdk\` React core, and the same data layer as plain REST calls for a stack that cannot run it): scaffold with the CLI, deploy, seed, design the presentation on the shipped code, release. What no shipped solution covers is written from the docs, as above. A new site is written in code and uploaded: StartDeployWebsite returns the upload guide (create the site, upload its files, change them later); StartHeadlessBuild returns the headless guide, for a site that needs Wix business features: you write the site, and the guide creates it, connects the features and uploads it, through the cold start that hands off to the kit (or the same run as API calls when there is no shell).
|
|
72640
72953
|
|
|
72641
|
-
|
|
72954
|
+
### When a call fails
|
|
72642
72955
|
|
|
72643
|
-
|
|
72644
|
-
Beyond managing user sites, the Wix MCP tools can be used for any other purpose they support — for example, reading Wix SDK docs to write code against the SDK, using the Wix CLI to create apps, answering documentation questions, and so on.
|
|
72645
|
-
</other-uses>
|
|
72646
|
-
</wix-usage-guide>
|
|
72956
|
+
The error carries the failed call's status and message and a Wix request id. Read it: it says what was wrong, and that is what to fix before calling again, whether the request (from the schema), the site and what is installed on it, or what the account is allowed to do. Never resend the same request unchanged, and never guess a fix. When you report the failure to the user, include the request id.
|
|
72647
72957
|
`;
|
|
72648
|
-
|
|
72649
|
-
|
|
72650
|
-
|
|
72651
|
-
|
|
72652
|
-
|
|
72653
|
-
|
|
72654
|
-
|
|
72655
|
-
|
|
72656
|
-
|
|
72657
|
-
|
|
72658
|
-
|
|
72659
|
-
|
|
72660
|
-
|
|
72958
|
+
function buildReadmeDocs({
|
|
72959
|
+
recipesIndex = true
|
|
72960
|
+
} = {}) {
|
|
72961
|
+
return [
|
|
72962
|
+
{
|
|
72963
|
+
action: "text",
|
|
72964
|
+
content: [
|
|
72965
|
+
README_INTRO,
|
|
72966
|
+
"",
|
|
72967
|
+
AGENT_GOAL,
|
|
72968
|
+
"",
|
|
72969
|
+
README_FLOWS_HEADING,
|
|
72970
|
+
"",
|
|
72971
|
+
README_FLOWS_SITE,
|
|
72972
|
+
"",
|
|
72973
|
+
README_FIND_SOURCES,
|
|
72974
|
+
"",
|
|
72975
|
+
README_FLOWS_BODY
|
|
72976
|
+
].join("\n")
|
|
72977
|
+
},
|
|
72978
|
+
{ action: "text", content: WIX_SKILLS_README_SECTION },
|
|
72979
|
+
...recipesIndex ? [recipesIndexDoc] : []
|
|
72980
|
+
];
|
|
72981
|
+
}
|
|
72982
|
+
var defaultReadmeDocs = buildReadmeDocs();
|
|
72661
72983
|
var widgetSiteCreationConfig = {
|
|
72662
72984
|
toolDescriptions: Object.fromEntries(
|
|
72663
72985
|
[
|
|
72664
|
-
"
|
|
72986
|
+
"WixHarmonyEditorBuild",
|
|
72665
72987
|
"WixSiteCreation",
|
|
72666
72988
|
"SearchSiteTemplates",
|
|
72667
72989
|
"CreateSiteFromTemplate"
|
|
@@ -72808,6 +73130,9 @@ function renderApps(apps, knownApps) {
|
|
|
72808
73130
|
if (app.catalogVersion) {
|
|
72809
73131
|
line += ` \u2014 Catalog app version: **${app.catalogVersion}**`;
|
|
72810
73132
|
}
|
|
73133
|
+
if (app.invoicesVersion) {
|
|
73134
|
+
line += ` \u2014 Invoices app version: **${app.invoicesVersion}**`;
|
|
73135
|
+
}
|
|
72811
73136
|
lines.push(line);
|
|
72812
73137
|
}
|
|
72813
73138
|
return lines.join("\n");
|
|
@@ -72828,6 +73153,11 @@ function renderCustomAppsWithSkillsTools(apps) {
|
|
|
72828
73153
|
}
|
|
72829
73154
|
return lines.join("\n");
|
|
72830
73155
|
}
|
|
73156
|
+
function renderCompanionApp(installedApps) {
|
|
73157
|
+
const appId = installedApps.find((app) => app.companionApp === true)?.appId;
|
|
73158
|
+
if (!appId || !GUID_PATTERN.test(appId)) return "";
|
|
73159
|
+
return `The site's code lives in its companion app (ID: \`${appId}\`).`;
|
|
73160
|
+
}
|
|
72831
73161
|
function renderProperties(props) {
|
|
72832
73162
|
const sections = [];
|
|
72833
73163
|
const regionalFormat = [];
|
|
@@ -72854,7 +73184,7 @@ ${contact.join("\n")}`);
|
|
|
72854
73184
|
}
|
|
72855
73185
|
return sections.join("\n\n");
|
|
72856
73186
|
}
|
|
72857
|
-
function renderSite(site, index, knownApps) {
|
|
73187
|
+
function renderSite(site, index, knownApps, includeCompanionApp) {
|
|
72858
73188
|
const lines = [];
|
|
72859
73189
|
const heading = site.displayName ?? `Site ${index}`;
|
|
72860
73190
|
lines.push(`## ${index}. ${heading}`);
|
|
@@ -72899,6 +73229,13 @@ function renderSite(site, index, knownApps) {
|
|
|
72899
73229
|
lines.push("");
|
|
72900
73230
|
lines.push(customAppsWithSkillsToolsContent);
|
|
72901
73231
|
}
|
|
73232
|
+
const companionAppContent = includeCompanionApp ? renderCompanionApp(site.installedApps ?? []) : "";
|
|
73233
|
+
if (companionAppContent) {
|
|
73234
|
+
lines.push("");
|
|
73235
|
+
lines.push("### Site code (companion app)");
|
|
73236
|
+
lines.push("");
|
|
73237
|
+
lines.push(companionAppContent);
|
|
73238
|
+
}
|
|
72902
73239
|
lines.push("");
|
|
72903
73240
|
lines.push("---");
|
|
72904
73241
|
lines.push("");
|
|
@@ -72918,6 +73255,7 @@ function enrichDynamicContext(data, knownApps = {}, options = {}) {
|
|
|
72918
73255
|
const response = snakeToCamel(parsed);
|
|
72919
73256
|
const includePartnerContext = options.includePartnerContext ?? false;
|
|
72920
73257
|
const includeAccountContext = options.includeAccountContext ?? false;
|
|
73258
|
+
const includeCompanionApp = options.includeCompanionApp ?? false;
|
|
72921
73259
|
const sections = [];
|
|
72922
73260
|
const allSites = response.sites ?? [];
|
|
72923
73261
|
const maxSites = options.maxSites ?? Infinity;
|
|
@@ -72970,9 +73308,18 @@ function enrichDynamicContext(data, knownApps = {}, options = {}) {
|
|
|
72970
73308
|
);
|
|
72971
73309
|
sections.push("");
|
|
72972
73310
|
}
|
|
73311
|
+
const hasInvoicesVersion = sitesToRender.some(
|
|
73312
|
+
(site) => site.installedApps?.some((app) => app.appId && knownApps[app.appId] && app.invoicesVersion)
|
|
73313
|
+
);
|
|
73314
|
+
if (hasInvoicesVersion) {
|
|
73315
|
+
sections.push(
|
|
73316
|
+
"> **Wix Invoices \u2014 Version**: Some sites below have Wix Invoices installed and show their Invoices version (V1/V2). When working on an Invoices task, check the version for that site \u2014 only read recipes and call endpoints that match its version. Never use an Invoices V2 skill or API on a V1 site, and vice versa."
|
|
73317
|
+
);
|
|
73318
|
+
sections.push("");
|
|
73319
|
+
}
|
|
72973
73320
|
if (sitesToRender.length) {
|
|
72974
73321
|
for (let i2 = 0; i2 < sitesToRender.length; i2++) {
|
|
72975
|
-
sections.push(renderSite(sitesToRender[i2], i2 + 1, knownApps));
|
|
73322
|
+
sections.push(renderSite(sitesToRender[i2], i2 + 1, knownApps, includeCompanionApp));
|
|
72976
73323
|
}
|
|
72977
73324
|
}
|
|
72978
73325
|
if (!response.account && !siteCount && (!includePartnerContext || !hasPartnerContext(response.partnerContext))) {
|
|
@@ -72980,9 +73327,11 @@ function enrichDynamicContext(data, knownApps = {}, options = {}) {
|
|
|
72980
73327
|
}
|
|
72981
73328
|
return sections.join("\n");
|
|
72982
73329
|
}
|
|
73330
|
+
var GUID_PATTERN;
|
|
72983
73331
|
var init_enrich = __esm2({
|
|
72984
73332
|
"src/enrich.ts"() {
|
|
72985
73333
|
"use strict";
|
|
73334
|
+
GUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
72986
73335
|
}
|
|
72987
73336
|
});
|
|
72988
73337
|
init_enrich();
|
|
@@ -73045,6 +73394,7 @@ async function getDynamicContext(auth, httpClient, filter, options) {
|
|
|
73045
73394
|
} : options;
|
|
73046
73395
|
const includePartnerContext = contextOptions?.partnerContextEnabled ?? true;
|
|
73047
73396
|
const includeAccountContext = contextOptions?.includeAccountContext ?? true;
|
|
73397
|
+
const includeCompanionApp = contextOptions?.includeCompanionApp ?? false;
|
|
73048
73398
|
try {
|
|
73049
73399
|
const accountHeaders = await auth.getAccountAuthHeaders();
|
|
73050
73400
|
const noFilter = !filter?.siteId && !filter?.siteName;
|
|
@@ -73098,6 +73448,7 @@ async function getDynamicContext(auth, httpClient, filter, options) {
|
|
|
73098
73448
|
const context2 = enrichDynamicContext2(response.data, known_apps_default, {
|
|
73099
73449
|
includePartnerContext,
|
|
73100
73450
|
includeAccountContext,
|
|
73451
|
+
includeCompanionApp,
|
|
73101
73452
|
// Cap the account-wide view to the first N sites; a targeted fetch returns one site.
|
|
73102
73453
|
...noFilter ? { maxSites: MAX_SITES_FOR_DYNAMIC_CONTEXT, totalSiteCount } : {}
|
|
73103
73454
|
});
|
|
@@ -73151,6 +73502,21 @@ function isApiUrlAllowed(url) {
|
|
|
73151
73502
|
}
|
|
73152
73503
|
|
|
73153
73504
|
// src/config/param-descriptions.ts
|
|
73505
|
+
var REPORT_ISSUE_TO_WIX_PARAMS = {
|
|
73506
|
+
message: [
|
|
73507
|
+
"The report of one issue, sent to Wix as free text. Only this issue \u2014 no session summary, play-by-play or unrelated problems:",
|
|
73508
|
+
"- What was being attempted, in a sentence.",
|
|
73509
|
+
"- The tool or endpoint, the HTTP status and the error message.",
|
|
73510
|
+
"- What you expected instead, and the workaround if any.",
|
|
73511
|
+
"- Where the fault likely lives (API behavior / API schema / docs / Wix tooling / unsure), and whether you confirmed it.",
|
|
73512
|
+
"- The context needed to reproduce it: agent/model, site id, the Wix area or API.",
|
|
73513
|
+
"- The user's own words, verbatim, if they added any.",
|
|
73514
|
+
"NEVER include secrets \u2014 no bearer tokens, API keys, or credentials \u2014 and no personal data beyond what the report needs."
|
|
73515
|
+
].join("\n"),
|
|
73516
|
+
requestId: "Optional request id (x-wix-request-id) of the failed Wix API call this report is about."
|
|
73517
|
+
};
|
|
73518
|
+
var WHY_NOT_EXECUTE_RECONNECT = "if the Wix MCP doesn't offer it at all, say so here, and tell the user once that their Wix connection may be an old or cached version that a reconnect refreshes.";
|
|
73519
|
+
var WHY_NOT_EXECUTE_NO_EXECUTE = "if it isn't in your tool list, say so.";
|
|
73154
73520
|
var paramDescriptions = {
|
|
73155
73521
|
CallWixSiteAPI: {
|
|
73156
73522
|
siteId: "The id of the site selected using site selection tool",
|
|
@@ -73167,6 +73533,7 @@ var paramDescriptions = {
|
|
|
73167
73533
|
WQL_FILTER_RULE
|
|
73168
73534
|
].join("\n"),
|
|
73169
73535
|
reason: "One sentence explaining the original user request and why you are calling this API to complete it.",
|
|
73536
|
+
whyNotExecuteWixAPI: `One sentence: why this call goes through CallWixSiteAPI and not ExecuteWixAPI, the preferred tool. If ExecuteWixAPI isn't loaded, load it through your client's tool search before calling this tool; ${WHY_NOT_EXECUTE_RECONNECT}`,
|
|
73170
73537
|
sourceDocUrl: [
|
|
73171
73538
|
"The URL of the documentation or recipe where you found this API endpoint.",
|
|
73172
73539
|
"MAKE SURE THE ENDPOINT URL IS REALLY THERE AND YOUR ARE NOT GUESSING IT !!!",
|
|
@@ -73202,18 +73569,9 @@ var paramDescriptions = {
|
|
|
73202
73569
|
'Use ["other"] ONLY IF YOU HAVE A VERY GOOD REASON TO DO SO'
|
|
73203
73570
|
].join("\n")
|
|
73204
73571
|
},
|
|
73205
|
-
|
|
73206
|
-
|
|
73207
|
-
|
|
73208
|
-
"1. Provenance \u2014 labelled lines (omit ones that do not apply): agent/model, Wix tooling used, Wix areas/APIs touched, Wix products (stores, bookings, ...), site id, relevant links (dashboard, docs pages read, live site) and other ids created this run.",
|
|
73209
|
-
`2. Narrative \u2014 "In the user's words": anything the user added when you offered, quoted verbatim (redact secrets only). Then user intent + run summary (what they set out to build, what worked vs. what fought back), a condensed play-by-play of the session (key exchanges, tool calls, decisions), and the friction points \u2014 every place something got in the way, each with specifics: the step/endpoint, HTTP status and error message, the gap, the workaround, and what you expected instead. Include issues you recovered from.`,
|
|
73210
|
-
'3. Attribution \u2014 for each significant friction point, your best diagnosis of where the fault lives: API behavior / API schema / API reference docs / docs articles or examples / Wix tooling (MCP tools, auth flow) / other-unsure \u2014 plus whether you confirmed it or are assuming. Do not force a tag; "unsure" beats a wrong route.',
|
|
73211
|
-
"End with a bottom line: one or two sentences naming the single most important problem and its impact \u2014 a concise engineering assessment, not softened or hedged.",
|
|
73212
|
-
"Write it as a scannable few paragraphs or a short bulleted list \u2014 thorough on the friction, distilled rather than a transcript dump.",
|
|
73213
|
-
"NEVER include secrets \u2014 no bearer tokens, API keys, or credentials \u2014 and no personal data beyond what the feedback needs."
|
|
73214
|
-
].join("\n"),
|
|
73215
|
-
requestId: "Optional request id (x-wix-request-id) returned from a failed Wix API call this feedback relates to."
|
|
73216
|
-
},
|
|
73572
|
+
ReportIssueToWix: REPORT_ISSUE_TO_WIX_PARAMS,
|
|
73573
|
+
// The tool's former name, kept for importers that read it by that key.
|
|
73574
|
+
SupportAndFeedback: REPORT_ISSUE_TO_WIX_PARAMS,
|
|
73217
73575
|
SearchWixWDSDocumentation: {
|
|
73218
73576
|
searchTerm: "The search term to search for in the Wix Design System Documentation",
|
|
73219
73577
|
maxResults: "The maximum number of results to return, default is 10, max is 15"
|
|
@@ -73252,8 +73610,13 @@ var paramDescriptions = {
|
|
|
73252
73610
|
maxResults: "The maximum number of results to return, default is 10, max is 15",
|
|
73253
73611
|
reason: "One sentence describing the original user request and the task you are trying to accomplish with this search."
|
|
73254
73612
|
},
|
|
73613
|
+
SearchWixHelpCenter: {
|
|
73614
|
+
searchTerm: 'What the site owner wants to do or fix, in plain words (e.g. "connect a domain bought elsewhere", "cancel a Premium plan")',
|
|
73615
|
+
maxResults: "The maximum number of articles to return (1\u201315, default 15). Each article is returned with up to 60 lines.",
|
|
73616
|
+
reason: "One sentence describing the original user request and the task you are trying to accomplish with this search."
|
|
73617
|
+
},
|
|
73255
73618
|
ReadFullDocsArticle: {
|
|
73256
|
-
articleUrl: "The URL of the docs article or method article to fetch. Should be something like https://dev.wix.com/docs/.../... For REST docs, use the URL as-is. For SDK docs, the URL SHOULD include the query param ?apiView=SDK (e.g. https://dev.wix.com/docs/...?apiView=SDK). Wix skills pages (https://www.wix.com/skills/..., https://dev.wix.com/docs/skills/...) and Wix Headless agent pages (https://www.wix.com/headless/..., e.g. https://www.wix.com/headless/skill.md) are read as-is, including their referenced files."
|
|
73619
|
+
articleUrl: "The URL of the docs article or method article to fetch. Should be something like https://dev.wix.com/docs/.../... For REST docs, use the URL as-is. For SDK docs, the URL SHOULD include the query param ?apiView=SDK (e.g. https://dev.wix.com/docs/...?apiView=SDK). Wix Help Center articles (https://support.wix.com/en/article/...) are read as-is. Wix skills pages (https://www.wix.com/skills/..., https://dev.wix.com/docs/skills/...) and Wix Headless agent pages (https://www.wix.com/headless/..., e.g. https://www.wix.com/headless/skill.md) are read as-is, including their referenced files. Source links (https://dev.wix.com/rawdocs/api/get-source-content?repo=...&path=...) found in skills and recipes are read as-is."
|
|
73257
73620
|
},
|
|
73258
73621
|
ReadFullDocsMethodSchema: {
|
|
73259
73622
|
articleUrl: "The URL of the documentation to fetch. Should be something like https://dev.wix.com/docs/.../... For REST docs, use the URL as-is. For SDK docs, the URL SHOULD include the query param ?apiView=SDK (e.g. https://dev.wix.com/docs/...?apiView=SDK).",
|
|
@@ -73269,7 +73632,7 @@ var paramDescriptions = {
|
|
|
73269
73632
|
},
|
|
73270
73633
|
UploadImageToWixSite: {
|
|
73271
73634
|
siteId: "The ID (UUID) of the Wix site to upload to. REQUIRED. If the user has not clearly specified which site, ASK them which site to upload to (or use ListWixSites to help them pick) BEFORE calling this tool. NEVER call this tool with a missing, empty, placeholder, or guessed siteId \u2014 ask first instead.",
|
|
73272
|
-
image: "
|
|
73635
|
+
image: `${fileParamNote("send the image as imageBase64 (the whole file, one per call) or as a public URL in imageUrls")} For plain image URLs the user pasted, use imageUrls instead. ALWAYS pass ALL files together in a single call \u2014 NEVER call this tool once per image. Do NOT use together with imageBase64.`,
|
|
73273
73636
|
imageUrls: "Array of publicly accessible image URLs (e.g. links the user pasted or URLs produced by other tools). Use this for plain URLs that are NOT chat attachments \u2014 no file_id is needed. ALWAYS pass ALL URLs together in a single call. Can be combined with image; do NOT use together with imageBase64.",
|
|
73274
73637
|
imageBase64: 'Base64-encoded image data. Use when the client can read a file and encode it as base64. May include a data URL prefix (e.g. "data:image/jpeg;base64,...") or be raw base64. Do NOT use together with image.',
|
|
73275
73638
|
mimeType: 'MIME type of the image (e.g. "image/jpeg", "image/png", "image/webp"). Required when imageBase64 does not include a data URL prefix.',
|
|
@@ -73306,10 +73669,301 @@ var paramDescriptions = {
|
|
|
73306
73669
|
};
|
|
73307
73670
|
var desc = (toolName) => paramDescriptions[toolName];
|
|
73308
73671
|
|
|
73672
|
+
// src/docs/mintlify-docs.ts
|
|
73673
|
+
var MINTLIFY_LINKS_DOCS_SITE = "mintlify-links";
|
|
73674
|
+
var MINTLIFY_DOCS_SITE = "mintlify";
|
|
73675
|
+
var MINTLIFY_HOST = "https://wix-internal.mintlify.site";
|
|
73676
|
+
var MINTLIFY_HOSTNAMES = /* @__PURE__ */ new Set([
|
|
73677
|
+
"wix-internal.mintlify.site",
|
|
73678
|
+
"wix-internal.mintlify.app"
|
|
73679
|
+
]);
|
|
73680
|
+
var DEV_WIX_DOCS = "https://dev.wix.com/docs";
|
|
73681
|
+
var PORTAL_SLUG_TO_TAB = {
|
|
73682
|
+
rest: "api-reference",
|
|
73683
|
+
"mintlify-sandbox": "sandbox"
|
|
73684
|
+
};
|
|
73685
|
+
var TAB_TO_PORTAL_SLUG = {
|
|
73686
|
+
sandbox: "mintlify-sandbox"
|
|
73687
|
+
};
|
|
73688
|
+
var MINTLIFY_TABS = /* @__PURE__ */ new Set(["api-reference", "sandbox", "kb"]);
|
|
73689
|
+
var NON_DOCS_SLUGS = /* @__PURE__ */ new Set(["skills", "kb-only", "api"]);
|
|
73690
|
+
var CHECK_TTL_MS = 10 * 60 * 1e3;
|
|
73691
|
+
var MAX_CHECK_ENTRIES = 5e3;
|
|
73692
|
+
var CHECK_TIMEOUT_MS = 5e3;
|
|
73693
|
+
var MAX_REDIRECTS = 3;
|
|
73694
|
+
var CHECK_CONCURRENCY = 8;
|
|
73695
|
+
function isMintlifyDocsSite(docsSite) {
|
|
73696
|
+
return docsSite === MINTLIFY_LINKS_DOCS_SITE || docsSite === MINTLIFY_DOCS_SITE;
|
|
73697
|
+
}
|
|
73698
|
+
var MINTLIFY_DOCUMENT_TYPES = {
|
|
73699
|
+
REST: ["MINTLIFY_REST"],
|
|
73700
|
+
// includes the skills, as REST + SKILLS does today
|
|
73701
|
+
SDK: ["MINTLIFY_SDK"]
|
|
73702
|
+
};
|
|
73703
|
+
function mintlifyDocumentTypes(docsSite, toolName) {
|
|
73704
|
+
return docsSite === MINTLIFY_DOCS_SITE ? MINTLIFY_DOCUMENT_TYPES[toolName] : void 0;
|
|
73705
|
+
}
|
|
73706
|
+
function isMintlifyUrl(url) {
|
|
73707
|
+
try {
|
|
73708
|
+
return MINTLIFY_HOSTNAMES.has(new URL(url).hostname);
|
|
73709
|
+
} catch {
|
|
73710
|
+
return false;
|
|
73711
|
+
}
|
|
73712
|
+
}
|
|
73713
|
+
var MINTLIFY_URL_PREFIXES = [...MINTLIFY_HOSTNAMES].map(
|
|
73714
|
+
(host) => `https://${host}/`
|
|
73715
|
+
);
|
|
73716
|
+
function cleanPath(pathname) {
|
|
73717
|
+
const path10 = pathname.replace(/\.md$/, "").replace(/\/+$/, "");
|
|
73718
|
+
return path10 === "" ? "/" : path10;
|
|
73719
|
+
}
|
|
73720
|
+
function flavourOf(url) {
|
|
73721
|
+
return url.searchParams.get("apiView")?.toUpperCase() === "SDK" ? "sdk" : "rest";
|
|
73722
|
+
}
|
|
73723
|
+
function toMintlifyCandidate(rawUrl) {
|
|
73724
|
+
let url;
|
|
73725
|
+
try {
|
|
73726
|
+
url = new URL(rawUrl);
|
|
73727
|
+
} catch {
|
|
73728
|
+
return null;
|
|
73729
|
+
}
|
|
73730
|
+
if (MINTLIFY_HOSTNAMES.has(url.hostname)) {
|
|
73731
|
+
const path11 = cleanPath(url.pathname);
|
|
73732
|
+
return { url: `${MINTLIFY_HOST}${path11}`, path: path11, flavour: flavourOf(url) };
|
|
73733
|
+
}
|
|
73734
|
+
if (url.hostname !== "dev.wix.com" || !url.pathname.startsWith("/docs/")) {
|
|
73735
|
+
return null;
|
|
73736
|
+
}
|
|
73737
|
+
const segments = cleanPath(url.pathname.slice("/docs".length)).split("/").filter(Boolean);
|
|
73738
|
+
if (segments.length === 0 || NON_DOCS_SLUGS.has(segments[0])) {
|
|
73739
|
+
return null;
|
|
73740
|
+
}
|
|
73741
|
+
segments[0] = PORTAL_SLUG_TO_TAB[segments[0]] ?? segments[0];
|
|
73742
|
+
const path10 = `/${segments.join("/")}`;
|
|
73743
|
+
return { url: `${MINTLIFY_HOST}${path10}`, path: path10, flavour: flavourOf(url) };
|
|
73744
|
+
}
|
|
73745
|
+
function toDevWixUrl(rawUrl) {
|
|
73746
|
+
const url = new URL(rawUrl);
|
|
73747
|
+
const segments = cleanPath(url.pathname).split("/").filter(Boolean);
|
|
73748
|
+
if (segments.length > 0) {
|
|
73749
|
+
segments[0] = TAB_TO_PORTAL_SLUG[segments[0]] ?? segments[0];
|
|
73750
|
+
}
|
|
73751
|
+
const query = flavourOf(url) === "sdk" ? "?apiView=SDK" : "";
|
|
73752
|
+
return `${DEV_WIX_DOCS}/${segments.join("/")}${query}`;
|
|
73753
|
+
}
|
|
73754
|
+
var checkCache = /* @__PURE__ */ new Map();
|
|
73755
|
+
function rememberCheck(path10, result) {
|
|
73756
|
+
const now = Date.now();
|
|
73757
|
+
checkCache.delete(path10);
|
|
73758
|
+
if (checkCache.size >= MAX_CHECK_ENTRIES) {
|
|
73759
|
+
for (const [key, entry] of checkCache) {
|
|
73760
|
+
if (entry.expires <= now) checkCache.delete(key);
|
|
73761
|
+
}
|
|
73762
|
+
}
|
|
73763
|
+
while (checkCache.size >= MAX_CHECK_ENTRIES) {
|
|
73764
|
+
const oldest = checkCache.keys().next().value;
|
|
73765
|
+
if (oldest === void 0) break;
|
|
73766
|
+
checkCache.delete(oldest);
|
|
73767
|
+
}
|
|
73768
|
+
checkCache.set(path10, { result, expires: now + CHECK_TTL_MS });
|
|
73769
|
+
}
|
|
73770
|
+
async function headOnce(url) {
|
|
73771
|
+
return fetch(url, {
|
|
73772
|
+
method: "HEAD",
|
|
73773
|
+
redirect: "manual",
|
|
73774
|
+
signal: AbortSignal.timeout(CHECK_TIMEOUT_MS)
|
|
73775
|
+
});
|
|
73776
|
+
}
|
|
73777
|
+
async function checkMintlifyPage(path10) {
|
|
73778
|
+
const cached2 = checkCache.get(path10);
|
|
73779
|
+
if (cached2 && cached2.expires > Date.now()) {
|
|
73780
|
+
return cached2.result;
|
|
73781
|
+
}
|
|
73782
|
+
if (cached2) checkCache.delete(path10);
|
|
73783
|
+
let result;
|
|
73784
|
+
try {
|
|
73785
|
+
let current = path10;
|
|
73786
|
+
let hops = 0;
|
|
73787
|
+
for (; ; ) {
|
|
73788
|
+
const response = await headOnce(`${MINTLIFY_HOST}${current}`);
|
|
73789
|
+
if (response.status === 200) {
|
|
73790
|
+
result = {
|
|
73791
|
+
outcome: hops === 0 ? "identity" : "redirect",
|
|
73792
|
+
path: current
|
|
73793
|
+
};
|
|
73794
|
+
break;
|
|
73795
|
+
}
|
|
73796
|
+
const location = response.headers.get("location");
|
|
73797
|
+
if (response.status >= 300 && response.status < 400 && location && hops < MAX_REDIRECTS) {
|
|
73798
|
+
current = cleanPath(new URL(location, MINTLIFY_HOST).pathname);
|
|
73799
|
+
hops++;
|
|
73800
|
+
continue;
|
|
73801
|
+
}
|
|
73802
|
+
result = { outcome: response.status === 404 ? "missing" : "error" };
|
|
73803
|
+
break;
|
|
73804
|
+
}
|
|
73805
|
+
} catch (error2) {
|
|
73806
|
+
logger2.error(`[mintlify] page check failed for ${path10}: ${error2}`);
|
|
73807
|
+
result = { outcome: "error" };
|
|
73808
|
+
}
|
|
73809
|
+
rememberCheck(path10, result);
|
|
73810
|
+
return result;
|
|
73811
|
+
}
|
|
73812
|
+
async function resolveDocsLink(rawUrl, { verify = true } = {}) {
|
|
73813
|
+
const candidate = toMintlifyCandidate(rawUrl);
|
|
73814
|
+
if (!candidate) {
|
|
73815
|
+
return { outcome: "not-docs", url: rawUrl };
|
|
73816
|
+
}
|
|
73817
|
+
const tab = candidate.path.split("/")[1];
|
|
73818
|
+
if (!MINTLIFY_TABS.has(tab)) {
|
|
73819
|
+
return { outcome: "other-portal", url: rawUrl };
|
|
73820
|
+
}
|
|
73821
|
+
const query = candidate.flavour === "sdk" ? "?apiView=SDK" : "";
|
|
73822
|
+
if (!verify) {
|
|
73823
|
+
return { outcome: "identity", url: `${candidate.url}${query}` };
|
|
73824
|
+
}
|
|
73825
|
+
const check2 = await checkMintlifyPage(candidate.path);
|
|
73826
|
+
if (check2.path) {
|
|
73827
|
+
return {
|
|
73828
|
+
outcome: check2.outcome,
|
|
73829
|
+
url: `${MINTLIFY_HOST}${check2.path}${query}`
|
|
73830
|
+
};
|
|
73831
|
+
}
|
|
73832
|
+
return { outcome: check2.outcome, url: rawUrl };
|
|
73833
|
+
}
|
|
73834
|
+
var DOCS_LINK_PATTERN = /https:\/\/(?:dev\.wix\.com\/docs|wix-internal\.mintlify\.(?:site|app))\/[^\s)\]"'<>`]*/g;
|
|
73835
|
+
function trimTrailingPunctuation(url) {
|
|
73836
|
+
return url.replace(/[.,;:!?*]+$/, "");
|
|
73837
|
+
}
|
|
73838
|
+
async function mapWithConcurrency(items, limit, fn) {
|
|
73839
|
+
const results = new Array(items.length);
|
|
73840
|
+
let next = 0;
|
|
73841
|
+
const workers = Array.from(
|
|
73842
|
+
{ length: Math.min(limit, items.length) },
|
|
73843
|
+
async () => {
|
|
73844
|
+
while (next < items.length) {
|
|
73845
|
+
const index = next++;
|
|
73846
|
+
results[index] = await fn(items[index]);
|
|
73847
|
+
}
|
|
73848
|
+
}
|
|
73849
|
+
);
|
|
73850
|
+
await Promise.all(workers);
|
|
73851
|
+
return results;
|
|
73852
|
+
}
|
|
73853
|
+
async function rewriteDocsLinks(text, { verify = true, label = "text" } = {}) {
|
|
73854
|
+
const found = [
|
|
73855
|
+
...new Set(
|
|
73856
|
+
(text.match(DOCS_LINK_PATTERN) ?? []).map(trimTrailingPunctuation)
|
|
73857
|
+
)
|
|
73858
|
+
];
|
|
73859
|
+
const stats = {
|
|
73860
|
+
links: found.length,
|
|
73861
|
+
byOutcome: {},
|
|
73862
|
+
misses: []
|
|
73863
|
+
};
|
|
73864
|
+
if (found.length === 0) {
|
|
73865
|
+
return { text, stats };
|
|
73866
|
+
}
|
|
73867
|
+
const resolved = await mapWithConcurrency(
|
|
73868
|
+
found,
|
|
73869
|
+
CHECK_CONCURRENCY,
|
|
73870
|
+
(url) => resolveDocsLink(url, { verify })
|
|
73871
|
+
);
|
|
73872
|
+
const replacements2 = /* @__PURE__ */ new Map();
|
|
73873
|
+
found.forEach((url, i2) => {
|
|
73874
|
+
const { outcome, url: target } = resolved[i2];
|
|
73875
|
+
stats.byOutcome[outcome] = (stats.byOutcome[outcome] ?? 0) + 1;
|
|
73876
|
+
if (outcome === "identity" || outcome === "redirect") {
|
|
73877
|
+
if (target !== url) replacements2.set(url, target);
|
|
73878
|
+
} else if (outcome !== "not-docs") {
|
|
73879
|
+
stats.misses.push(`${outcome} ${url}`);
|
|
73880
|
+
}
|
|
73881
|
+
});
|
|
73882
|
+
const rewritten = text.replace(DOCS_LINK_PATTERN, (match) => {
|
|
73883
|
+
const url = trimTrailingPunctuation(match);
|
|
73884
|
+
const target = replacements2.get(url);
|
|
73885
|
+
return target ? target + match.slice(url.length) : match;
|
|
73886
|
+
});
|
|
73887
|
+
logger2.log(
|
|
73888
|
+
`[mintlify] ${label}: ${stats.links} links ${JSON.stringify(stats.byOutcome)}` + (stats.misses.length ? ` misses: ${stats.misses.slice(0, 10).join(" | ")}` : "")
|
|
73889
|
+
);
|
|
73890
|
+
return { text: rewritten, stats };
|
|
73891
|
+
}
|
|
73892
|
+
var INDEX_BANNER = /^> ## Documentation Index\n(?:>.*\n)*\n?/;
|
|
73893
|
+
var INLINED_SNIPPET = /^export const \w+ = [\s\S]*?^};\n/gm;
|
|
73894
|
+
var REST_TAB = /<Tab title="REST">([\s\S]*?)<\/Tab>/;
|
|
73895
|
+
var SDK_TAB = /<Tab title="SDK">([\s\S]*?)<\/Tab>/;
|
|
73896
|
+
function cleanMintlifyMarkdown(markdown, flavour) {
|
|
73897
|
+
const text = markdown.replace(INLINED_SNIPPET, "");
|
|
73898
|
+
const rest = text.match(REST_TAB);
|
|
73899
|
+
const sdk = text.match(SDK_TAB);
|
|
73900
|
+
if (!rest || !sdk || (text.match(/<Tab title=/g) ?? []).length !== 2) {
|
|
73901
|
+
return text;
|
|
73902
|
+
}
|
|
73903
|
+
const start = text.lastIndexOf("<Tabs>", rest.index);
|
|
73904
|
+
const end = text.indexOf("</Tabs>", sdk.index);
|
|
73905
|
+
if (start === -1 || end === -1) {
|
|
73906
|
+
return text;
|
|
73907
|
+
}
|
|
73908
|
+
const kept = (flavour === "sdk" ? sdk : rest)[1];
|
|
73909
|
+
const note = flavour === "sdk" ? "_This is the SDK view. Drop `?apiView=SDK` from the URL for the REST view._" : "_This is the REST view. Add `?apiView=SDK` to the URL for the JavaScript SDK view._";
|
|
73910
|
+
return `${text.slice(0, start)}${note}
|
|
73911
|
+
|
|
73912
|
+
${kept.trim()}
|
|
73913
|
+
${text.slice(end + "</Tabs>".length)}`;
|
|
73914
|
+
}
|
|
73915
|
+
var DOCS_URL_IN_TEXT = /https:\/\/dev\.wix\.com\/docs\/(?=api-reference\b|\.\.\.)/g;
|
|
73916
|
+
function toMintlifyHostText(text) {
|
|
73917
|
+
return text.replace(DOCS_URL_IN_TEXT, `${MINTLIFY_HOST}/`);
|
|
73918
|
+
}
|
|
73919
|
+
var SITE_RELATIVE_LINK = /(\]\(|href=["'])\/(?!\/)/g;
|
|
73920
|
+
function absolutizeSiteLinks(markdown) {
|
|
73921
|
+
return markdown.replace(
|
|
73922
|
+
SITE_RELATIVE_LINK,
|
|
73923
|
+
(_, open) => `${open}${MINTLIFY_HOST}/`
|
|
73924
|
+
);
|
|
73925
|
+
}
|
|
73926
|
+
async function readMintlifyMarkdown(rawUrl) {
|
|
73927
|
+
const resolved = await resolveDocsLink(rawUrl);
|
|
73928
|
+
if (resolved.outcome !== "identity" && resolved.outcome !== "redirect") {
|
|
73929
|
+
return null;
|
|
73930
|
+
}
|
|
73931
|
+
const pageUrl = new URL(resolved.url);
|
|
73932
|
+
const response = await fetch(`${MINTLIFY_HOST}${pageUrl.pathname}.md`, {
|
|
73933
|
+
headers: { accept: "text/markdown" },
|
|
73934
|
+
redirect: "follow",
|
|
73935
|
+
signal: AbortSignal.timeout(15e3)
|
|
73936
|
+
});
|
|
73937
|
+
if (response.status === 404) {
|
|
73938
|
+
return null;
|
|
73939
|
+
}
|
|
73940
|
+
if (!response.ok) {
|
|
73941
|
+
throw new Error(
|
|
73942
|
+
`Mintlify returned ${response.status} for ${pageUrl.pathname}.md`
|
|
73943
|
+
);
|
|
73944
|
+
}
|
|
73945
|
+
const flavour = toMintlifyCandidate(rawUrl)?.flavour ?? "rest";
|
|
73946
|
+
const cleaned = cleanMintlifyMarkdown(
|
|
73947
|
+
(await response.text()).replace(INDEX_BANNER, ""),
|
|
73948
|
+
flavour
|
|
73949
|
+
);
|
|
73950
|
+
const { text: rewritten } = await rewriteDocsLinks(cleaned, {
|
|
73951
|
+
label: `read ${pageUrl.pathname}`
|
|
73952
|
+
});
|
|
73953
|
+
const markdown = absolutizeSiteLinks(rewritten);
|
|
73954
|
+
logger2.log(
|
|
73955
|
+
`[mintlify] read ${pageUrl.pathname}.md (${markdown.length} chars) for ${rawUrl}`
|
|
73956
|
+
);
|
|
73957
|
+
return { url: `${MINTLIFY_HOST}${pageUrl.pathname}`, markdown };
|
|
73958
|
+
}
|
|
73959
|
+
|
|
73309
73960
|
// src/docs/get-to-know.ts
|
|
73961
|
+
var AX_SKILLS_REPO = "wix-private/ax-skills";
|
|
73962
|
+
var AX_SKILLS_INDEX_PATH = "skills/wix-manage/SKILL.md";
|
|
73310
73963
|
function addGetSiteContextTool({
|
|
73311
73964
|
server: server2,
|
|
73312
73965
|
authStrategy,
|
|
73966
|
+
includeCompanionApp = false,
|
|
73313
73967
|
toolDescriptions
|
|
73314
73968
|
}) {
|
|
73315
73969
|
const d = desc("GetSiteContext");
|
|
@@ -73339,7 +73993,8 @@ function addGetSiteContextTool({
|
|
|
73339
73993
|
try {
|
|
73340
73994
|
context2 = await getDynamicContext(authStrategy, httpClient, filter, {
|
|
73341
73995
|
partnerContextEnabled: false,
|
|
73342
|
-
includeAccountContext: false
|
|
73996
|
+
includeAccountContext: false,
|
|
73997
|
+
includeCompanionApp
|
|
73343
73998
|
});
|
|
73344
73999
|
} catch (err) {
|
|
73345
74000
|
rethrowIfUnauthorized(err);
|
|
@@ -73375,15 +74030,17 @@ async function addGetToKnowTools({
|
|
|
73375
74030
|
dynamicContextEnabled,
|
|
73376
74031
|
repo,
|
|
73377
74032
|
commitHash,
|
|
73378
|
-
skillsTags
|
|
74033
|
+
skillsTags,
|
|
74034
|
+
readmeRecipesIndexEnabled = true,
|
|
74035
|
+
docsSite
|
|
73379
74036
|
}) {
|
|
73380
74037
|
if (disableTools.includes("WixREADME")) {
|
|
73381
74038
|
return;
|
|
73382
74039
|
}
|
|
73383
74040
|
const baseDocs = readmeDocs ?? defaultReadmeDocs;
|
|
73384
|
-
const
|
|
73385
|
-
|
|
73386
|
-
);
|
|
74041
|
+
const isRecipesIndex = (doc) => doc.url?.replace(/\.md$/, "") === RECIPES_INDEX_URL;
|
|
74042
|
+
const baseDocsWithoutRecipes = baseDocs.filter((doc) => !isRecipesIndex(doc));
|
|
74043
|
+
const recipesIndexDocs = readmeRecipesIndexEnabled ? baseDocs.filter(isRecipesIndex) : [];
|
|
73387
74044
|
server2.tool(
|
|
73388
74045
|
"WixREADME",
|
|
73389
74046
|
toolDescriptions?.["WixREADME"] ?? defaultToolDescriptions.WixREADME,
|
|
@@ -73455,6 +74112,18 @@ ${responseText}` : responseText;
|
|
|
73455
74112
|
if (!url) {
|
|
73456
74113
|
throw new Error('URL is required for "include" action');
|
|
73457
74114
|
}
|
|
74115
|
+
const readsAxSkills = isRecipesIndex({ action, url }) && !skillsPortalUrl && (repo ? repo === AX_SKILLS_REPO : !commitHash);
|
|
74116
|
+
if (readsAxSkills) {
|
|
74117
|
+
return {
|
|
74118
|
+
type: "text",
|
|
74119
|
+
text: await fetchSourceContent(
|
|
74120
|
+
httpClient,
|
|
74121
|
+
AX_SKILLS_REPO,
|
|
74122
|
+
AX_SKILLS_INDEX_PATH,
|
|
74123
|
+
repo === AX_SKILLS_REPO ? commitHash : void 0
|
|
74124
|
+
)
|
|
74125
|
+
};
|
|
74126
|
+
}
|
|
73458
74127
|
const fetchedContent = await fetchArticleContent(
|
|
73459
74128
|
httpClient,
|
|
73460
74129
|
url,
|
|
@@ -73497,9 +74166,9 @@ Failed to fetch content: ${errorMsg}`
|
|
|
73497
74166
|
}).catch((err) => {
|
|
73498
74167
|
console.error("[WixREADME] Failed to fetch skills by portal:", err);
|
|
73499
74168
|
return null;
|
|
73500
|
-
}) : fetchDoc({ action: "include", url: RECIPES_INDEX_URL }).then(
|
|
74169
|
+
}) : readmeRecipesIndexEnabled ? fetchDoc({ action: "include", url: RECIPES_INDEX_URL }).then(
|
|
73501
74170
|
(doc) => doc?.text ?? null
|
|
73502
|
-
);
|
|
74171
|
+
) : Promise.resolve(null);
|
|
73503
74172
|
const filter = {};
|
|
73504
74173
|
if (siteId) filter.siteId = siteId;
|
|
73505
74174
|
else if (siteName) filter.siteName = siteName;
|
|
@@ -73519,7 +74188,7 @@ Failed to fetch content: ${errorMsg}`
|
|
|
73519
74188
|
const recipesIntro = dedent_default`
|
|
73520
74189
|
Reusable how-to guides for common ${isVisitorFlow ? "Wix site visitor" : "Wix management"} tasks, grouped by product area. Each recipe is a Wix docs article that bundles the right endpoints, request shapes, field names, and step ordering for one real-world use case.
|
|
73521
74190
|
|
|
73522
|
-
|
|
74191
|
+
Open the recipe that matches the task with \`ReadFullDocsArticle\` and follow it. When its example for a call matches your case (the same variant and shape), call from it; when it doesn't, or leaves out a field your case needs, read the method's schema with \`SearchWixAPISpec\` first. On query and search methods an example proves only the fields and operators it uses; the method's own declared list covers the rest. When no recipe fits, find the method with \`SearchWixRESTDocumentation\` or \`BrowseWixRESTDocsMenu\`, then \`SearchWixAPISpec\` for its schema.
|
|
73523
74192
|
`;
|
|
73524
74193
|
const recipesContents = skillsContent !== null ? [
|
|
73525
74194
|
await fetchDoc({
|
|
@@ -73529,9 +74198,7 @@ Failed to fetch content: ${errorMsg}`
|
|
|
73529
74198
|
|
|
73530
74199
|
${skillsContent}`
|
|
73531
74200
|
})
|
|
73532
|
-
] : await Promise.all(
|
|
73533
|
-
baseDocs.filter((doc) => doc.url === RECIPES_INDEX_URL).map(fetchDoc)
|
|
73534
|
-
);
|
|
74201
|
+
] : await Promise.all(recipesIndexDocs.map(fetchDoc));
|
|
73535
74202
|
const recipeNotes = !skillsContent?.includes("Dashboard Navigation") ? [] : [
|
|
73536
74203
|
await fetchDoc({
|
|
73537
74204
|
action: "text",
|
|
@@ -73549,7 +74216,8 @@ ${skillsContent}`
|
|
|
73549
74216
|
).map((item) => item.text),
|
|
73550
74217
|
...dynamicContext ? [dynamicContext] : []
|
|
73551
74218
|
];
|
|
73552
|
-
const
|
|
74219
|
+
const joined = parts.join("\n\n");
|
|
74220
|
+
const text = isMintlifyDocsSite(docsSite) ? (await rewriteDocsLinks(joined, { label: "readme WixREADME" })).text : joined;
|
|
73553
74221
|
return {
|
|
73554
74222
|
content: [{ type: "text", text }]
|
|
73555
74223
|
};
|
|
@@ -73558,13 +74226,14 @@ ${skillsContent}`
|
|
|
73558
74226
|
}
|
|
73559
74227
|
|
|
73560
74228
|
// src/docs/start-deploy-website.ts
|
|
74229
|
+
var NO_PERSONAL_DATA = "No personal data: no names, emails, phones, passwords, keys or local paths.";
|
|
73561
74230
|
var START_DEPLOY_WEBSITE_PARAM_DESCRIPTIONS = {
|
|
73562
|
-
userRequest:
|
|
73563
|
-
siteDescription:
|
|
73564
|
-
siteForm:
|
|
73565
|
-
siteFunctionality:
|
|
73566
|
-
agentIdentity:
|
|
73567
|
-
wixAccess:
|
|
74231
|
+
userRequest: `A short summary of what the user asked for and the context that led here, in a sentence or two, including whether this is a new site or an edit or new version of a site already on Wix. ${NO_PERSONAL_DATA}`,
|
|
74232
|
+
siteDescription: `What the site is: its purpose and who it is for. One or two sentences. ${NO_PERSONAL_DATA}`,
|
|
74233
|
+
siteForm: `The form the site exists in right now (HTML/CSS/JS files, a static build, a zip, a framework project, another builder's export, a design created in this conversation, or something else), roughly how many files, and whether it includes images. For a framework project: which framework, whether you have its built static output (for example dist/) or only the source, and whether it needs a server at runtime (SSR, API routes, a backend), or that you don't know. Also where it came from: built in this conversation, the user's own project or repo, another builder (which one), or a Wix skill or template (which one). ${NO_PERSONAL_DATA}`,
|
|
74234
|
+
siteFunctionality: `What the site must be able to do for its visitors beyond showing pages, if anything (for example selling, bookings or reservations, tickets, menus and orders, rentals, forms, memberships or paid plans, donations, a blog, or anything else the user expects to work), in your own words. If it is a plain static site with no such needs, say so. ${NO_PERSONAL_DATA}`,
|
|
74235
|
+
agentIdentity: `Which agent or product you are, which model if you know it, and the harness you run in. ${NO_PERSONAL_DATA}`,
|
|
74236
|
+
wixAccess: `How you can reach Wix from where you run: through this MCP only, or also from a shell whose network can reach wixapis.com; whether you can run the Wix CLI (npx @wix/cli) there and whether it is logged in; which Wix identity you act with \u2014 the user's login through this MCP, a CLI login, or none; and which Wix skills you have (for example wix-headless-kit or wix-manage), by name and where they come from (installed on disk, a plugin, read online), or none. Name the kind of identity, not the account or its email. ${NO_PERSONAL_DATA}`
|
|
73568
74237
|
};
|
|
73569
74238
|
var START_DEPLOY_WEBSITE_PARAMS = Object.keys(
|
|
73570
74239
|
START_DEPLOY_WEBSITE_PARAM_DESCRIPTIONS
|
|
@@ -73572,10 +74241,11 @@ var START_DEPLOY_WEBSITE_PARAMS = Object.keys(
|
|
|
73572
74241
|
var START_DEPLOY_WEBSITE_TOOL_NAME = "StartDeployWebsite";
|
|
73573
74242
|
var START_DEPLOY_WEBSITE_RECIPE_URL = "https://dev.wix.com/docs/api-reference/account-level/sites/skills/upload-a-website-or-html-files.md";
|
|
73574
74243
|
var DROP_PAGE_URL = "https://www.wix.com/headless/drop?utm_campaign=mcp";
|
|
74244
|
+
var WRITE_THE_CODE_LINE = "When the user brought no files, write the site's code yourself, then upload it as the guide shows.";
|
|
73575
74245
|
var FALLBACK_LINE = `Only if you cannot run it (you can't reach the file bytes, or a step fails and you can't fix it): send the user to ${DROP_PAGE_URL} \u2014 give that URL exactly as written, keeping the utm_campaign=mcp parameter.`;
|
|
73576
74246
|
function startDeployWebsiteResponse(recipe) {
|
|
73577
74247
|
return [
|
|
73578
|
-
`The following is the content of ${START_DEPLOY_WEBSITE_RECIPE_URL}. Follow it end to end and do the publishing yourself \u2014 do not hand the user instructions
|
|
74248
|
+
`The following is the content of ${START_DEPLOY_WEBSITE_RECIPE_URL}. Follow it end to end and do the publishing yourself \u2014 do not hand the user instructions. ${WRITE_THE_CODE_LINE}`,
|
|
73579
74249
|
FALLBACK_LINE,
|
|
73580
74250
|
"---",
|
|
73581
74251
|
recipe.trim()
|
|
@@ -73583,7 +74253,7 @@ function startDeployWebsiteResponse(recipe) {
|
|
|
73583
74253
|
}
|
|
73584
74254
|
var START_DEPLOY_WEBSITE_POINTER_RESPONSE = [
|
|
73585
74255
|
`Read and follow this recipe end to end: ${START_DEPLOY_WEBSITE_RECIPE_URL}`,
|
|
73586
|
-
|
|
74256
|
+
`It covers creating the site and uploading the files (with or without a Wix login), updating a site deployed this way, and implementing a backend on it (stores, bookings, CMS, members) as a Wix Headless project. Do the publishing yourself \u2014 do not hand the user instructions. ${WRITE_THE_CODE_LINE}`,
|
|
73587
74257
|
FALLBACK_LINE
|
|
73588
74258
|
].join("\n\n");
|
|
73589
74259
|
function addStartDeployWebsiteTool(server2, disableTools = [], toolDescriptions, fetchOptions = {}) {
|
|
@@ -73631,36 +74301,21 @@ function addStartDeployWebsiteTool(server2, disableTools = [], toolDescriptions,
|
|
|
73631
74301
|
// src/docs/start-headless-build.ts
|
|
73632
74302
|
var START_HEADLESS_BUILD_TOOL_NAME = "StartHeadlessBuild";
|
|
73633
74303
|
var HEADLESS_GUIDE_URL = "https://www.wix.com/skills/headless-cold-start/headless-kit.md";
|
|
73634
|
-
var START_HEADLESS_BUILD_STARTING_POINTS = [
|
|
73635
|
-
"nothing yet",
|
|
73636
|
-
"a design worked out in this conversation",
|
|
73637
|
-
"an existing Wix Headless site",
|
|
73638
|
-
"a project download link",
|
|
73639
|
-
"a Wix site to move to code"
|
|
73640
|
-
];
|
|
73641
74304
|
var START_HEADLESS_BUILD_PARAM_DESCRIPTIONS = {
|
|
73642
74305
|
userRequest: START_DEPLOY_WEBSITE_PARAM_DESCRIPTIONS.userRequest,
|
|
73643
74306
|
siteDescription: START_DEPLOY_WEBSITE_PARAM_DESCRIPTIONS.siteDescription,
|
|
73644
|
-
startingPoint:
|
|
74307
|
+
startingPoint: `What the site starts from, in your own words: a new site; an existing Wix Headless site (a site deployed from files is one), with its metaSiteId if you have it; a project download link (a download.zip from Wix); a Wix site moving to code; or something else. ${NO_PERSONAL_DATA}`,
|
|
73645
74308
|
siteFunctionality: START_DEPLOY_WEBSITE_PARAM_DESCRIPTIONS.siteFunctionality,
|
|
73646
74309
|
agentIdentity: START_DEPLOY_WEBSITE_PARAM_DESCRIPTIONS.agentIdentity,
|
|
73647
74310
|
wixAccess: START_DEPLOY_WEBSITE_PARAM_DESCRIPTIONS.wixAccess
|
|
73648
74311
|
};
|
|
73649
|
-
var
|
|
73650
|
-
var
|
|
73651
|
-
function startHeadlessBuildResponse(guide
|
|
73652
|
-
const lines = [];
|
|
73653
|
-
if (startingPoint === "a Wix site to move to code") {
|
|
73654
|
-
lines.push(MOVE_TO_CODE_LINE);
|
|
73655
|
-
}
|
|
74312
|
+
var BUILT_HERE = "The site is built here, in code: don't offer Wix's editor or a template instead.";
|
|
74313
|
+
var PREFIX2 = `The following is Wix's headless guide. Follow it end to end and do the work yourself: you write the site, and the guide creates it, connects its Wix business features, and uploads it. ${BUILT_HERE}`;
|
|
74314
|
+
function startHeadlessBuildResponse(guide) {
|
|
73656
74315
|
if (guide && guide.trim()) {
|
|
73657
|
-
|
|
73658
|
-
} else {
|
|
73659
|
-
lines.push(
|
|
73660
|
-
`Wix's headless guide could not be loaded here. It is at ${HEADLESS_GUIDE_URL}: read it whole with ReadFullDocsArticle if you have that tool, otherwise fetch it with curl or your web tool, then follow it end to end and do the work yourself. If you find the user already has the site's code, call StartDeployWebsite instead.`
|
|
73661
|
-
);
|
|
74316
|
+
return [PREFIX2, "---", guide.trim()].join("\n\n");
|
|
73662
74317
|
}
|
|
73663
|
-
return
|
|
74318
|
+
return `Wix's headless guide could not be loaded here. It is at ${HEADLESS_GUIDE_URL}: read it whole with ReadFullDocsArticle if you have that tool, otherwise fetch it with curl or your web tool, then follow it end to end and do the work yourself. ${BUILT_HERE}`;
|
|
73664
74319
|
}
|
|
73665
74320
|
function addStartHeadlessBuildTool(server2, disableTools = [], toolDescriptions, fetchOptions = {}) {
|
|
73666
74321
|
if (disableTools.includes(START_HEADLESS_BUILD_TOOL_NAME)) {
|
|
@@ -73673,13 +74328,13 @@ function addStartHeadlessBuildTool(server2, disableTools = [], toolDescriptions,
|
|
|
73673
74328
|
{
|
|
73674
74329
|
userRequest: external_exports.string().min(1).describe(d.userRequest),
|
|
73675
74330
|
siteDescription: external_exports.string().min(1).describe(d.siteDescription),
|
|
73676
|
-
startingPoint: external_exports.
|
|
74331
|
+
startingPoint: external_exports.string().optional().describe(d.startingPoint),
|
|
73677
74332
|
siteFunctionality: external_exports.string().min(1).describe(d.siteFunctionality),
|
|
73678
74333
|
agentIdentity: external_exports.string().min(1).describe(d.agentIdentity),
|
|
73679
74334
|
wixAccess: external_exports.string().min(1).describe(d.wixAccess)
|
|
73680
74335
|
},
|
|
73681
74336
|
{ readOnlyHint: true, destructiveHint: false, openWorldHint: false },
|
|
73682
|
-
async (
|
|
74337
|
+
async (_args, { httpClient }) => {
|
|
73683
74338
|
let guide;
|
|
73684
74339
|
try {
|
|
73685
74340
|
guide = await fetchArticleContent(
|
|
@@ -73701,7 +74356,7 @@ function addStartHeadlessBuildTool(server2, disableTools = [], toolDescriptions,
|
|
|
73701
74356
|
content: [
|
|
73702
74357
|
{
|
|
73703
74358
|
type: "text",
|
|
73704
|
-
text: startHeadlessBuildResponse(guide
|
|
74359
|
+
text: startHeadlessBuildResponse(guide)
|
|
73705
74360
|
}
|
|
73706
74361
|
]
|
|
73707
74362
|
};
|
|
@@ -73719,7 +74374,8 @@ var VALID_DOCS_TOOLS = [
|
|
|
73719
74374
|
"VELO",
|
|
73720
74375
|
"BUSINESS_SOLUTIONS",
|
|
73721
74376
|
"CLI",
|
|
73722
|
-
"OVERVIEW"
|
|
74377
|
+
"OVERVIEW",
|
|
74378
|
+
"HELP_CENTER"
|
|
73723
74379
|
];
|
|
73724
74380
|
var REST_SEARCH_API_GROUNDING_REMINDER = dedent_default`
|
|
73725
74381
|
# Before calling a Wix API
|
|
@@ -73748,9 +74404,16 @@ function shouldTryMenuFallbackForDocsRead(error2, articleUrl) {
|
|
|
73748
74404
|
if (!message.includes("404") || !isMenuFallbackUrl) {
|
|
73749
74405
|
return false;
|
|
73750
74406
|
}
|
|
73751
|
-
return !
|
|
73752
|
-
|
|
73753
|
-
|
|
74407
|
+
return !isKnownArticleError(error2);
|
|
74408
|
+
}
|
|
74409
|
+
function isKnownArticleError(error2) {
|
|
74410
|
+
const message = getErrorMessage(error2);
|
|
74411
|
+
return [
|
|
74412
|
+
"This resource is deprecated",
|
|
74413
|
+
"This method is deprecated",
|
|
74414
|
+
"This article is deprecated",
|
|
74415
|
+
"No schema found"
|
|
74416
|
+
].some((knownArticleError) => message.includes(knownArticleError));
|
|
73754
74417
|
}
|
|
73755
74418
|
function formatDocsReadError(toolAction, error2) {
|
|
73756
74419
|
return `Could not fetch ${toolAction}: "${getErrorMessage(error2)}".`;
|
|
@@ -73763,7 +74426,8 @@ var addDocsTools = (server2, allowedTools = [
|
|
|
73763
74426
|
"WIX_HEADLESS",
|
|
73764
74427
|
"BUSINESS_SOLUTIONS",
|
|
73765
74428
|
"CLI",
|
|
73766
|
-
"OVERVIEW"
|
|
74429
|
+
"OVERVIEW",
|
|
74430
|
+
"HELP_CENTER"
|
|
73767
74431
|
], options = {}) => {
|
|
73768
74432
|
const {
|
|
73769
74433
|
getToKnowWixEnabled = false,
|
|
@@ -73779,14 +74443,47 @@ var addDocsTools = (server2, allowedTools = [
|
|
|
73779
74443
|
skillsPr,
|
|
73780
74444
|
commitHash,
|
|
73781
74445
|
skillsTags,
|
|
74446
|
+
readmeRecipesIndexEnabled,
|
|
73782
74447
|
dynamicContextEnabled,
|
|
74448
|
+
includeCompanionApp,
|
|
73783
74449
|
usePlatformizedSearch = true,
|
|
73784
|
-
usePlatformizedBrowse = true
|
|
74450
|
+
usePlatformizedBrowse = true,
|
|
74451
|
+
docsSite
|
|
73785
74452
|
} = options;
|
|
73786
74453
|
const effectiveRepo = repo ?? skillsRepo;
|
|
73787
74454
|
const effectiveCommitHash = commitHash ?? skillsPr;
|
|
73788
|
-
const
|
|
74455
|
+
const mintlifyDocs = isMintlifyDocsSite(docsSite);
|
|
74456
|
+
const runSearch = mintlifyDocs ? async (params) => {
|
|
74457
|
+
const documentTypes = mintlifyDocumentTypes(docsSite, params.toolName);
|
|
74458
|
+
const result = await runSemanticSearchAndFormat(
|
|
74459
|
+
documentTypes ? { ...params, documentTypes } : params
|
|
74460
|
+
);
|
|
74461
|
+
return (await rewriteDocsLinks(result, { label: `search ${params.toolName}` })).text;
|
|
74462
|
+
} : runSemanticSearchAndFormat;
|
|
74463
|
+
const docsUrlPrefixes = mintlifyDocs ? ["https://dev.wix.com/docs/", ...MINTLIFY_URL_PREFIXES] : ["https://dev.wix.com/docs/"];
|
|
74464
|
+
const toBackendUrl = (url) => mintlifyDocs && isMintlifyUrl(url) ? toDevWixUrl(url) : url;
|
|
74465
|
+
const sourceNote = (source) => mintlifyDocs ? [{ type: "text", text: `[docs source] ${source}` }] : [];
|
|
74466
|
+
const docsText = (text) => mintlifyDocs ? toMintlifyHostText(text) : text;
|
|
74467
|
+
const desc2 = (toolName) => {
|
|
74468
|
+
const descriptions = desc(toolName);
|
|
74469
|
+
if (!mintlifyDocs) return descriptions;
|
|
74470
|
+
return Object.fromEntries(
|
|
74471
|
+
Object.entries(descriptions).map(([param, text]) => [
|
|
74472
|
+
param,
|
|
74473
|
+
docsText(text)
|
|
74474
|
+
])
|
|
74475
|
+
);
|
|
74476
|
+
};
|
|
74477
|
+
const getDescription = (toolName, defaultDesc) => docsText(toolDescriptions?.[toolName] ?? defaultDesc);
|
|
73789
74478
|
const fetchMenuTextForUrl = async (httpClient, url) => {
|
|
74479
|
+
const text = await fetchMenuTextForBackendUrl(
|
|
74480
|
+
httpClient,
|
|
74481
|
+
toBackendUrl(url)
|
|
74482
|
+
);
|
|
74483
|
+
if (!text || !mintlifyDocs) return text;
|
|
74484
|
+
return (await rewriteDocsLinks(text, { verify: false, label: "menu" })).text;
|
|
74485
|
+
};
|
|
74486
|
+
const fetchMenuTextForBackendUrl = async (httpClient, url) => {
|
|
73790
74487
|
if (usePlatformizedBrowse) {
|
|
73791
74488
|
try {
|
|
73792
74489
|
return await fetchPlatformizedMenu(url);
|
|
@@ -73803,10 +74500,77 @@ var addDocsTools = (server2, allowedTools = [
|
|
|
73803
74500
|
}
|
|
73804
74501
|
return menuContent.length > MENU_CONTENT_THRESHOLD ? summarizeLargeMenu(menuContent, url) : normalizeMenuContent(menuContent);
|
|
73805
74502
|
};
|
|
74503
|
+
const nearestToMissingPage = async (httpClient, url, isSkillsPage) => {
|
|
74504
|
+
try {
|
|
74505
|
+
if (isSkillsPage) {
|
|
74506
|
+
const manifestUrl = skillManifestUrl(url);
|
|
74507
|
+
if (!manifestUrl) return null;
|
|
74508
|
+
const manifest = JSON.parse(
|
|
74509
|
+
await fetchArticleContent(httpClient, manifestUrl, "article")
|
|
74510
|
+
);
|
|
74511
|
+
const guess = closestSkillFile(url, manifest, manifestUrl);
|
|
74512
|
+
if (!guess) return null;
|
|
74513
|
+
if (guess.kind === "file") {
|
|
74514
|
+
const text = await fetchArticleContent(
|
|
74515
|
+
httpClient,
|
|
74516
|
+
guess.url,
|
|
74517
|
+
"article"
|
|
74518
|
+
);
|
|
74519
|
+
return `Note: "${url}" does not exist. Found a similar file in the skill, ${guess.url}, and read it:
|
|
74520
|
+
|
|
74521
|
+
${text}`;
|
|
74522
|
+
}
|
|
74523
|
+
return `Note: "${url}" does not exist, and no file in ${guess.folder ? `its folder (${guess.folder}/)` : "the skill"} has a name close to it. ${guess.folder ? "The files in that folder" : "The skill's top-level folders and files"}, to read the one you need (every file: ${guess.manifestUrl}):
|
|
74524
|
+
|
|
74525
|
+
${guess.files.map((f) => `- ${f}`).join("\n")}`;
|
|
74526
|
+
}
|
|
74527
|
+
for (const menuUrl of parentMenuUrls(url)) {
|
|
74528
|
+
const text = await fetchMenuTextForUrl(httpClient, menuUrl);
|
|
74529
|
+
if (!text) continue;
|
|
74530
|
+
const subMenus = (await Promise.all(
|
|
74531
|
+
subMenusToRead(text, menuUrl, url).map(async (sub) => ({
|
|
74532
|
+
sub,
|
|
74533
|
+
text: await fetchMenuTextForUrl(httpClient, sub).catch(() => null)
|
|
74534
|
+
}))
|
|
74535
|
+
)).filter((m) => !!m.text);
|
|
74536
|
+
const closest = closestMenuLinks(
|
|
74537
|
+
[text, ...subMenus.map((m) => m.text)].join("\n"),
|
|
74538
|
+
menuUrl,
|
|
74539
|
+
url
|
|
74540
|
+
);
|
|
74541
|
+
return [
|
|
74542
|
+
`Note: "${url}" does not exist. Showing the nearest documentation menu above it, ${menuUrl}; read the page you need from its links.`,
|
|
74543
|
+
...closest.length ? [
|
|
74544
|
+
`Closest to what you asked for:
|
|
74545
|
+
${closest.map((l) => `- ${l}`).join("\n")}`
|
|
74546
|
+
] : [],
|
|
74547
|
+
text
|
|
74548
|
+
].join("\n\n");
|
|
74549
|
+
}
|
|
74550
|
+
} catch (error2) {
|
|
74551
|
+
logger2.error(`[docs] no nearest page for ${url}: ${error2}`);
|
|
74552
|
+
}
|
|
74553
|
+
return null;
|
|
74554
|
+
};
|
|
74555
|
+
if (startDeployWebsiteEnabled) {
|
|
74556
|
+
addStartDeployWebsiteTool(server2, disableTools || [], toolDescriptions, {
|
|
74557
|
+
skillsPortalUrl,
|
|
74558
|
+
repo: effectiveRepo,
|
|
74559
|
+
commitHash: effectiveCommitHash
|
|
74560
|
+
});
|
|
74561
|
+
}
|
|
74562
|
+
if (startHeadlessBuildEnabled) {
|
|
74563
|
+
addStartHeadlessBuildTool(server2, disableTools || [], toolDescriptions, {
|
|
74564
|
+
skillsPortalUrl,
|
|
74565
|
+
repo: effectiveRepo,
|
|
74566
|
+
commitHash: effectiveCommitHash
|
|
74567
|
+
});
|
|
74568
|
+
}
|
|
73806
74569
|
if (dynamicContextEnabled && authStrategy && !disableTools?.includes("GetSiteContext")) {
|
|
73807
74570
|
addGetSiteContextTool({
|
|
73808
74571
|
server: server2,
|
|
73809
74572
|
authStrategy,
|
|
74573
|
+
includeCompanionApp,
|
|
73810
74574
|
toolDescriptions,
|
|
73811
74575
|
disableTools: disableTools || []
|
|
73812
74576
|
});
|
|
@@ -73822,21 +74586,9 @@ var addDocsTools = (server2, allowedTools = [
|
|
|
73822
74586
|
dynamicContextEnabled,
|
|
73823
74587
|
repo: effectiveRepo,
|
|
73824
74588
|
commitHash: effectiveCommitHash,
|
|
73825
|
-
skillsTags
|
|
73826
|
-
|
|
73827
|
-
|
|
73828
|
-
if (startDeployWebsiteEnabled) {
|
|
73829
|
-
addStartDeployWebsiteTool(server2, disableTools || [], toolDescriptions, {
|
|
73830
|
-
skillsPortalUrl,
|
|
73831
|
-
repo: effectiveRepo,
|
|
73832
|
-
commitHash: effectiveCommitHash
|
|
73833
|
-
});
|
|
73834
|
-
}
|
|
73835
|
-
if (startHeadlessBuildEnabled) {
|
|
73836
|
-
addStartHeadlessBuildTool(server2, disableTools || [], toolDescriptions, {
|
|
73837
|
-
skillsPortalUrl,
|
|
73838
|
-
repo: effectiveRepo,
|
|
73839
|
-
commitHash: effectiveCommitHash
|
|
74589
|
+
skillsTags,
|
|
74590
|
+
readmeRecipesIndexEnabled,
|
|
74591
|
+
docsSite
|
|
73840
74592
|
});
|
|
73841
74593
|
}
|
|
73842
74594
|
if (allowedTools.includes("WDS") && !disableTools?.includes("SearchWixWDSDocumentation")) {
|
|
@@ -73847,7 +74599,7 @@ var addDocsTools = (server2, allowedTools = [
|
|
|
73847
74599
|
defaultToolDescriptions.SearchWixWDSDocumentation ?? ""
|
|
73848
74600
|
),
|
|
73849
74601
|
(() => {
|
|
73850
|
-
const d =
|
|
74602
|
+
const d = desc2("SearchWixWDSDocumentation");
|
|
73851
74603
|
return {
|
|
73852
74604
|
searchTerm: external_exports.string().describe(d.searchTerm),
|
|
73853
74605
|
maxResults: external_exports.number().describe(d.maxResults).min(1).max(15).optional().default(15)
|
|
@@ -73857,7 +74609,7 @@ var addDocsTools = (server2, allowedTools = [
|
|
|
73857
74609
|
async ({ searchTerm, maxResults }, { panorama }) => {
|
|
73858
74610
|
try {
|
|
73859
74611
|
logger2.log(`Searching for ${searchTerm} in Wix WDS`);
|
|
73860
|
-
const result = await
|
|
74612
|
+
const result = await runSearch({
|
|
73861
74613
|
toolName: "WDS",
|
|
73862
74614
|
toolParams: {
|
|
73863
74615
|
searchTerm
|
|
@@ -73900,7 +74652,7 @@ var addDocsTools = (server2, allowedTools = [
|
|
|
73900
74652
|
defaultToolDescriptions.SearchWixRESTDocumentation
|
|
73901
74653
|
),
|
|
73902
74654
|
(() => {
|
|
73903
|
-
const d =
|
|
74655
|
+
const d = desc2("SearchWixRESTDocumentation");
|
|
73904
74656
|
return {
|
|
73905
74657
|
searchTerm: external_exports.string().describe(d.searchTerm),
|
|
73906
74658
|
maxResults: external_exports.number().describe(d.maxResults).min(1).max(17).optional().default(17),
|
|
@@ -73913,7 +74665,7 @@ var addDocsTools = (server2, allowedTools = [
|
|
|
73913
74665
|
logger2.log(
|
|
73914
74666
|
`[SearchWixRESTDocumentation] searchTerm="${searchTerm}", reason="${reason}"`
|
|
73915
74667
|
);
|
|
73916
|
-
const result = await
|
|
74668
|
+
const result = await runSearch({
|
|
73917
74669
|
toolName: "REST",
|
|
73918
74670
|
toolParams: {
|
|
73919
74671
|
searchTerm
|
|
@@ -73964,7 +74716,7 @@ var addDocsTools = (server2, allowedTools = [
|
|
|
73964
74716
|
defaultToolDescriptions.WixBusinessFlowsDocumentation ?? ""
|
|
73965
74717
|
),
|
|
73966
74718
|
(() => {
|
|
73967
|
-
const d =
|
|
74719
|
+
const d = desc2("WixBusinessFlowsDocumentation");
|
|
73968
74720
|
return {
|
|
73969
74721
|
searchTerm: external_exports.string().describe(d.searchTerm),
|
|
73970
74722
|
maxResults: external_exports.number().describe(d.maxResults).min(1).max(15).optional().default(15)
|
|
@@ -73974,7 +74726,7 @@ var addDocsTools = (server2, allowedTools = [
|
|
|
73974
74726
|
async ({ searchTerm, maxResults }, { panorama }) => {
|
|
73975
74727
|
try {
|
|
73976
74728
|
logger2.log(`Searching for ${searchTerm} in Wix Sample Flows`);
|
|
73977
|
-
const result = await
|
|
74729
|
+
const result = await runSearch({
|
|
73978
74730
|
toolName: "BUSINESS_SOLUTIONS",
|
|
73979
74731
|
toolParams: {
|
|
73980
74732
|
searchTerm: "**RECIPE**: Business Recipes - full setup flow for::: " + searchTerm
|
|
@@ -74020,7 +74772,7 @@ var addDocsTools = (server2, allowedTools = [
|
|
|
74020
74772
|
defaultToolDescriptions.SearchWixSDKDocumentation ?? ""
|
|
74021
74773
|
),
|
|
74022
74774
|
(() => {
|
|
74023
|
-
const d =
|
|
74775
|
+
const d = desc2("SearchWixSDKDocumentation");
|
|
74024
74776
|
return {
|
|
74025
74777
|
searchTerm: external_exports.string().describe(d.searchTerm),
|
|
74026
74778
|
maxResults: external_exports.number().describe(d.maxResults).min(1).max(15).optional().default(15)
|
|
@@ -74031,7 +74783,7 @@ var addDocsTools = (server2, allowedTools = [
|
|
|
74031
74783
|
try {
|
|
74032
74784
|
logger2.log(`Searching for ${searchTerm} in Wix SDK`);
|
|
74033
74785
|
panorama.transaction("SearchWixSDKDocumentation").start({ maxResults });
|
|
74034
|
-
const result = await
|
|
74786
|
+
const result = await runSearch({
|
|
74035
74787
|
toolName: "SDK",
|
|
74036
74788
|
toolParams: {
|
|
74037
74789
|
searchTerm
|
|
@@ -74079,7 +74831,7 @@ var addDocsTools = (server2, allowedTools = [
|
|
|
74079
74831
|
defaultToolDescriptions.SearchBuildAppsDocumentation ?? ""
|
|
74080
74832
|
),
|
|
74081
74833
|
(() => {
|
|
74082
|
-
const d =
|
|
74834
|
+
const d = desc2("SearchBuildAppsDocumentation");
|
|
74083
74835
|
return {
|
|
74084
74836
|
searchTerm: external_exports.string().describe(d.searchTerm),
|
|
74085
74837
|
maxResults: external_exports.number().describe(d.maxResults).min(1).max(15).optional().default(15)
|
|
@@ -74089,7 +74841,7 @@ var addDocsTools = (server2, allowedTools = [
|
|
|
74089
74841
|
async ({ searchTerm, maxResults }, { panorama }) => {
|
|
74090
74842
|
try {
|
|
74091
74843
|
logger2.log(`Searching for ${searchTerm} in Build Apps`);
|
|
74092
|
-
const result = await
|
|
74844
|
+
const result = await runSearch({
|
|
74093
74845
|
toolName: "BUILD_APPS",
|
|
74094
74846
|
toolParams: {
|
|
74095
74847
|
searchTerm: `wix cli docs for ${searchTerm}`
|
|
@@ -74131,7 +74883,7 @@ var addDocsTools = (server2, allowedTools = [
|
|
|
74131
74883
|
defaultToolDescriptions.SearchDevelopmentDocumentation ?? ""
|
|
74132
74884
|
),
|
|
74133
74885
|
(() => {
|
|
74134
|
-
const d =
|
|
74886
|
+
const d = desc2("SearchDevelopmentDocumentation");
|
|
74135
74887
|
return {
|
|
74136
74888
|
searchTerm: external_exports.string().describe(d.searchTerm),
|
|
74137
74889
|
maxResults: external_exports.number().describe(d.maxResults).min(1).max(15).optional().default(15)
|
|
@@ -74141,7 +74893,7 @@ var addDocsTools = (server2, allowedTools = [
|
|
|
74141
74893
|
async ({ searchTerm, maxResults }, { panorama }) => {
|
|
74142
74894
|
try {
|
|
74143
74895
|
logger2.log(`Searching for ${searchTerm} in Wix Overview`);
|
|
74144
|
-
const result = await
|
|
74896
|
+
const result = await runSearch({
|
|
74145
74897
|
toolName: "OVERVIEW",
|
|
74146
74898
|
toolParams: {
|
|
74147
74899
|
searchTerm
|
|
@@ -74183,7 +74935,7 @@ var addDocsTools = (server2, allowedTools = [
|
|
|
74183
74935
|
defaultToolDescriptions.SearchWixHeadlessDocumentation ?? ""
|
|
74184
74936
|
),
|
|
74185
74937
|
(() => {
|
|
74186
|
-
const d =
|
|
74938
|
+
const d = desc2("SearchWixHeadlessDocumentation");
|
|
74187
74939
|
return {
|
|
74188
74940
|
searchTerm: external_exports.string().describe(d.searchTerm),
|
|
74189
74941
|
maxResults: external_exports.number().describe(d.maxResults).min(1).max(17).optional().default(17)
|
|
@@ -74193,7 +74945,7 @@ var addDocsTools = (server2, allowedTools = [
|
|
|
74193
74945
|
async ({ searchTerm, maxResults }, { panorama }) => {
|
|
74194
74946
|
try {
|
|
74195
74947
|
logger2.log(`Searching for ${searchTerm} in Headless`);
|
|
74196
|
-
const result = await
|
|
74948
|
+
const result = await runSearch({
|
|
74197
74949
|
toolName: "WIX_HEADLESS",
|
|
74198
74950
|
toolParams: {
|
|
74199
74951
|
searchTerm
|
|
@@ -74238,7 +74990,7 @@ var addDocsTools = (server2, allowedTools = [
|
|
|
74238
74990
|
defaultToolDescriptions.SearchWixVeloDocumentation ?? ""
|
|
74239
74991
|
),
|
|
74240
74992
|
(() => {
|
|
74241
|
-
const d =
|
|
74993
|
+
const d = desc2("SearchWixVeloDocumentation");
|
|
74242
74994
|
return {
|
|
74243
74995
|
searchTerm: external_exports.string().describe(d.searchTerm),
|
|
74244
74996
|
maxResults: external_exports.number().describe(d.maxResults).min(1).max(15).optional().default(15)
|
|
@@ -74249,7 +75001,7 @@ var addDocsTools = (server2, allowedTools = [
|
|
|
74249
75001
|
try {
|
|
74250
75002
|
logger2.log(`Searching for ${searchTerm} in Velo`);
|
|
74251
75003
|
panorama.transaction("SearchWixVeloDocumentation").start({ maxResults });
|
|
74252
|
-
const result = await
|
|
75004
|
+
const result = await runSearch({
|
|
74253
75005
|
toolName: "VELO",
|
|
74254
75006
|
toolParams: {
|
|
74255
75007
|
searchTerm
|
|
@@ -74287,6 +75039,72 @@ var addDocsTools = (server2, allowedTools = [
|
|
|
74287
75039
|
}
|
|
74288
75040
|
);
|
|
74289
75041
|
}
|
|
75042
|
+
if (allowedTools.includes("HELP_CENTER") && !disableTools?.includes("SearchWixHelpCenter")) {
|
|
75043
|
+
server2.tool(
|
|
75044
|
+
"SearchWixHelpCenter",
|
|
75045
|
+
getDescription(
|
|
75046
|
+
"SearchWixHelpCenter",
|
|
75047
|
+
defaultToolDescriptions.SearchWixHelpCenter ?? ""
|
|
75048
|
+
),
|
|
75049
|
+
(() => {
|
|
75050
|
+
const d = desc2("SearchWixHelpCenter");
|
|
75051
|
+
return {
|
|
75052
|
+
searchTerm: external_exports.string().describe(d.searchTerm),
|
|
75053
|
+
maxResults: external_exports.number().describe(d.maxResults).min(1).max(15).optional().default(15),
|
|
75054
|
+
reason: external_exports.string().describe(d.reason)
|
|
75055
|
+
};
|
|
75056
|
+
})(),
|
|
75057
|
+
{ readOnlyHint: true, destructiveHint: false, openWorldHint: false },
|
|
75058
|
+
async ({ searchTerm, maxResults, reason }, { panorama }) => {
|
|
75059
|
+
try {
|
|
75060
|
+
logger2.log(
|
|
75061
|
+
`[SearchWixHelpCenter] searchTerm="${searchTerm}", reason="${reason}"`
|
|
75062
|
+
);
|
|
75063
|
+
const result = await runSemanticSearchAndFormat({
|
|
75064
|
+
toolName: "HELP_CENTER",
|
|
75065
|
+
toolParams: {
|
|
75066
|
+
searchTerm
|
|
75067
|
+
},
|
|
75068
|
+
maxResults: Math.max(1, Math.min(maxResults ?? 15, 15)),
|
|
75069
|
+
linesInEachResult: 60,
|
|
75070
|
+
usePlatformizedSearch
|
|
75071
|
+
});
|
|
75072
|
+
return {
|
|
75073
|
+
content: [
|
|
75074
|
+
{
|
|
75075
|
+
type: "text",
|
|
75076
|
+
text: `${HELP_CENTER_IS_FOR_PEOPLE}
|
|
75077
|
+
|
|
75078
|
+
${result}`
|
|
75079
|
+
}
|
|
75080
|
+
]
|
|
75081
|
+
};
|
|
75082
|
+
} catch (error2) {
|
|
75083
|
+
panorama.errorMonitor().reportError(error2);
|
|
75084
|
+
captureException(error2, {
|
|
75085
|
+
tags: {
|
|
75086
|
+
componentId: "SearchWixHelpCenter",
|
|
75087
|
+
toolName: "SearchWixHelpCenter"
|
|
75088
|
+
}
|
|
75089
|
+
});
|
|
75090
|
+
logger2.error(
|
|
75091
|
+
`Error searching for ${searchTerm} in the Wix Help Center: ${error2}`
|
|
75092
|
+
);
|
|
75093
|
+
return {
|
|
75094
|
+
isError: true,
|
|
75095
|
+
content: [
|
|
75096
|
+
{
|
|
75097
|
+
type: "text",
|
|
75098
|
+
text: `Error: ${error2.message}
|
|
75099
|
+
|
|
75100
|
+
${HELP_CENTER_IS_FOR_PEOPLE}`
|
|
75101
|
+
}
|
|
75102
|
+
]
|
|
75103
|
+
};
|
|
75104
|
+
}
|
|
75105
|
+
}
|
|
75106
|
+
);
|
|
75107
|
+
}
|
|
74290
75108
|
if (allowedTools.includes("CLI") && !disableTools?.includes("SearchWixCLIDocumentation")) {
|
|
74291
75109
|
server2.tool(
|
|
74292
75110
|
"SearchWixCLIDocumentation",
|
|
@@ -74295,7 +75113,7 @@ var addDocsTools = (server2, allowedTools = [
|
|
|
74295
75113
|
defaultToolDescriptions.SearchWixCLIDocumentation ?? ""
|
|
74296
75114
|
),
|
|
74297
75115
|
(() => {
|
|
74298
|
-
const d =
|
|
75116
|
+
const d = desc2("SearchWixCLIDocumentation");
|
|
74299
75117
|
return {
|
|
74300
75118
|
searchTerm: external_exports.string().describe(d.searchTerm),
|
|
74301
75119
|
maxResults: external_exports.number().describe(d.maxResults).min(1).max(15).optional().default(15),
|
|
@@ -74308,7 +75126,7 @@ var addDocsTools = (server2, allowedTools = [
|
|
|
74308
75126
|
logger2.log(
|
|
74309
75127
|
`[SearchWixCLIDocumentation] searchTerm="${searchTerm}", reason="${reason}"`
|
|
74310
75128
|
);
|
|
74311
|
-
const result = await
|
|
75129
|
+
const result = await runSearch({
|
|
74312
75130
|
toolName: "CLI",
|
|
74313
75131
|
toolParams: {
|
|
74314
75132
|
searchTerm
|
|
@@ -74352,14 +75170,39 @@ var addDocsTools = (server2, allowedTools = [
|
|
|
74352
75170
|
defaultToolDescriptions.ReadFullDocsArticle
|
|
74353
75171
|
),
|
|
74354
75172
|
(() => {
|
|
74355
|
-
const d =
|
|
75173
|
+
const d = desc2("ReadFullDocsArticle");
|
|
74356
75174
|
return {
|
|
74357
75175
|
articleUrl: external_exports.string().url().describe(d.articleUrl)
|
|
74358
75176
|
};
|
|
74359
75177
|
})(),
|
|
74360
75178
|
{ readOnlyHint: true, destructiveHint: false, openWorldHint: false },
|
|
74361
75179
|
async ({ articleUrl }, { httpClient }) => {
|
|
74362
|
-
const
|
|
75180
|
+
const source = parseSourceContentUrl(articleUrl);
|
|
75181
|
+
if (source) {
|
|
75182
|
+
try {
|
|
75183
|
+
const text = await fetchSourceContent(
|
|
75184
|
+
httpClient,
|
|
75185
|
+
source.repo,
|
|
75186
|
+
source.path,
|
|
75187
|
+
source.commitHash
|
|
75188
|
+
);
|
|
75189
|
+
return { content: [{ type: "text", text }] };
|
|
75190
|
+
} catch (error2) {
|
|
75191
|
+
logger2.error(
|
|
75192
|
+
`Error fetching source content for ${articleUrl}: ${error2}`
|
|
75193
|
+
);
|
|
75194
|
+
return {
|
|
75195
|
+
isError: true,
|
|
75196
|
+
content: [
|
|
75197
|
+
{
|
|
75198
|
+
type: "text",
|
|
75199
|
+
text: formatDocsReadError("source content", error2)
|
|
75200
|
+
}
|
|
75201
|
+
]
|
|
75202
|
+
};
|
|
75203
|
+
}
|
|
75204
|
+
}
|
|
75205
|
+
const validPrefixes = [...docsUrlPrefixes, "https://support.wix.com/"];
|
|
74363
75206
|
if (skillsPortalUrl) validPrefixes.push(skillsPortalUrl);
|
|
74364
75207
|
const isSkillsPage = isSkillsRegistryUrl(articleUrl);
|
|
74365
75208
|
if (!isSkillsPage && !validPrefixes.some((p) => articleUrl.startsWith(p))) {
|
|
@@ -74368,7 +75211,7 @@ var addDocsTools = (server2, allowedTools = [
|
|
|
74368
75211
|
content: [
|
|
74369
75212
|
{
|
|
74370
75213
|
type: "text",
|
|
74371
|
-
text: `Invalid article URL: must start with https://dev.wix.com/docs/, or be a Wix skills page (https://www.wix.com/skills/..., https://www.wix.com/headless
|
|
75214
|
+
text: `Invalid article URL: must start with https://dev.wix.com/docs/ or https://support.wix.com/, or be a Wix skills page (https://www.wix.com/skills/..., https://www.wix.com/headless/..., or that file's github.com/wix/skills source). Got: "${articleUrl}"`
|
|
74372
75215
|
}
|
|
74373
75216
|
]
|
|
74374
75217
|
};
|
|
@@ -74376,6 +75219,27 @@ var addDocsTools = (server2, allowedTools = [
|
|
|
74376
75219
|
if (!isSkillsPage && articleUrl.startsWith("https://dev.wix.com/docs/")) {
|
|
74377
75220
|
articleUrl = articleUrl.replace(/\.md$/, "");
|
|
74378
75221
|
}
|
|
75222
|
+
if (mintlifyDocs && !isSkillsPage) {
|
|
75223
|
+
try {
|
|
75224
|
+
const page = await readMintlifyMarkdown(articleUrl);
|
|
75225
|
+
if (page) {
|
|
75226
|
+
return {
|
|
75227
|
+
content: [
|
|
75228
|
+
{
|
|
75229
|
+
type: "text",
|
|
75230
|
+
text: isQueryOrSearchEndpoint(page.url) ? [page.markdown, ARTICLE_CAPABILITY_NOTE].join("\n\n") : page.markdown
|
|
75231
|
+
},
|
|
75232
|
+
...sourceNote(`Mintlify site: ${page.url}.md`)
|
|
75233
|
+
]
|
|
75234
|
+
};
|
|
75235
|
+
}
|
|
75236
|
+
} catch (error2) {
|
|
75237
|
+
logger2.error(
|
|
75238
|
+
`[mintlify] reading ${articleUrl} from Mintlify failed, falling back: ${error2}`
|
|
75239
|
+
);
|
|
75240
|
+
}
|
|
75241
|
+
articleUrl = toBackendUrl(articleUrl);
|
|
75242
|
+
}
|
|
74379
75243
|
try {
|
|
74380
75244
|
const articleContent = await fetchArticleContent(
|
|
74381
75245
|
httpClient,
|
|
@@ -74396,7 +75260,10 @@ var addDocsTools = (server2, allowedTools = [
|
|
|
74396
75260
|
// The article's own URL, never its body — a filter/sort reference page links query
|
|
74397
75261
|
// methods in its prose but isn't one.
|
|
74398
75262
|
text: isQueryOrSearchEndpoint(articleUrl) ? [articleContent, ARTICLE_CAPABILITY_NOTE].join("\n\n") : articleContent
|
|
74399
|
-
}
|
|
75263
|
+
},
|
|
75264
|
+
...sourceNote(
|
|
75265
|
+
isSkillsPage ? `skills registry: ${articleUrl}` : `today's backend (dev.wix.com/rawdocs, ingvar), not on the Mintlify site: ${articleUrl}`
|
|
75266
|
+
)
|
|
74400
75267
|
]
|
|
74401
75268
|
};
|
|
74402
75269
|
} catch (error2) {
|
|
@@ -74421,6 +75288,16 @@ ${text}`
|
|
|
74421
75288
|
} catch {
|
|
74422
75289
|
}
|
|
74423
75290
|
}
|
|
75291
|
+
if (getErrorMessage(error2).includes("404") && !isKnownArticleError(error2)) {
|
|
75292
|
+
const nearest = await nearestToMissingPage(
|
|
75293
|
+
httpClient,
|
|
75294
|
+
articleUrl,
|
|
75295
|
+
isSkillsPage
|
|
75296
|
+
);
|
|
75297
|
+
if (nearest) {
|
|
75298
|
+
return { content: [{ type: "text", text: nearest }] };
|
|
75299
|
+
}
|
|
75300
|
+
}
|
|
74424
75301
|
return {
|
|
74425
75302
|
isError: true,
|
|
74426
75303
|
content: [
|
|
@@ -74442,7 +75319,7 @@ ${text}`
|
|
|
74442
75319
|
defaultToolDescriptions.ReadFullDocsMethodSchema
|
|
74443
75320
|
),
|
|
74444
75321
|
(() => {
|
|
74445
|
-
const d =
|
|
75322
|
+
const d = desc2("ReadFullDocsMethodSchema");
|
|
74446
75323
|
return {
|
|
74447
75324
|
articleUrl: external_exports.string().url().describe(d.articleUrl),
|
|
74448
75325
|
reason: external_exports.string().describe(d.reason)
|
|
@@ -74450,7 +75327,7 @@ ${text}`
|
|
|
74450
75327
|
})(),
|
|
74451
75328
|
{ readOnlyHint: true, destructiveHint: false, openWorldHint: false },
|
|
74452
75329
|
async ({ articleUrl, reason }, { httpClient }) => {
|
|
74453
|
-
const validPrefixes = [
|
|
75330
|
+
const validPrefixes = [...docsUrlPrefixes];
|
|
74454
75331
|
if (skillsPortalUrl) validPrefixes.push(skillsPortalUrl);
|
|
74455
75332
|
if (!validPrefixes.some((p) => articleUrl.startsWith(p))) {
|
|
74456
75333
|
return {
|
|
@@ -74466,6 +75343,7 @@ ${text}`
|
|
|
74466
75343
|
if (articleUrl.startsWith("https://dev.wix.com/docs/")) {
|
|
74467
75344
|
articleUrl = articleUrl.replace(/\.md$/, "");
|
|
74468
75345
|
}
|
|
75346
|
+
articleUrl = toBackendUrl(articleUrl);
|
|
74469
75347
|
try {
|
|
74470
75348
|
logger2.log(
|
|
74471
75349
|
`[ReadFullDocsMethodSchema] url="${articleUrl}", reason="${reason}"`
|
|
@@ -74483,12 +75361,18 @@ ${text}`
|
|
|
74483
75361
|
if (!articleContent) {
|
|
74484
75362
|
throw new Error("Method schema is empty");
|
|
74485
75363
|
}
|
|
75364
|
+
const schemaText = mintlifyDocs ? (await rewriteDocsLinks(articleContent, {
|
|
75365
|
+
label: "schema ReadFullDocsMethodSchema"
|
|
75366
|
+
})).text : articleContent;
|
|
74486
75367
|
return {
|
|
74487
75368
|
content: [
|
|
74488
75369
|
{
|
|
74489
75370
|
type: "text",
|
|
74490
|
-
text:
|
|
74491
|
-
}
|
|
75371
|
+
text: schemaText
|
|
75372
|
+
},
|
|
75373
|
+
...sourceNote(
|
|
75374
|
+
`PAPI, through today's backend (dev.wix.com/rawdocs, ingvar): ${articleUrl}`
|
|
75375
|
+
)
|
|
74492
75376
|
]
|
|
74493
75377
|
};
|
|
74494
75378
|
} catch (error2) {
|
|
@@ -74534,7 +75418,7 @@ ${text}`
|
|
|
74534
75418
|
defaultToolDescriptions.BrowseWixRESTDocsMenu
|
|
74535
75419
|
),
|
|
74536
75420
|
(() => {
|
|
74537
|
-
const d =
|
|
75421
|
+
const d = desc2("BrowseWixRESTDocsMenu");
|
|
74538
75422
|
return {
|
|
74539
75423
|
menuUrl: external_exports.string().optional().describe(d.menuUrl),
|
|
74540
75424
|
reason: external_exports.string().describe(d.reason)
|
|
@@ -74543,7 +75427,7 @@ ${text}`
|
|
|
74543
75427
|
{ readOnlyHint: true, destructiveHint: false, openWorldHint: false },
|
|
74544
75428
|
async ({ menuUrl, reason }, { httpClient }) => {
|
|
74545
75429
|
try {
|
|
74546
|
-
if (menuUrl && !menuUrl.startsWith(
|
|
75430
|
+
if (menuUrl && !docsUrlPrefixes.some((p) => menuUrl.startsWith(p))) {
|
|
74547
75431
|
return {
|
|
74548
75432
|
content: [
|
|
74549
75433
|
{
|
|
@@ -78655,11 +79539,11 @@ var getEncodingTransformGenerator = (binary, encoding, skipped) => {
|
|
|
78655
79539
|
final: encodingStringFinal.bind(void 0, stringDecoder)
|
|
78656
79540
|
};
|
|
78657
79541
|
};
|
|
78658
|
-
var encodingUint8ArrayGenerator = function* (
|
|
79542
|
+
var encodingUint8ArrayGenerator = function* (textEncoder4, chunk) {
|
|
78659
79543
|
if (Buffer3.isBuffer(chunk)) {
|
|
78660
79544
|
yield bufferToUint8Array(chunk);
|
|
78661
79545
|
} else if (typeof chunk === "string") {
|
|
78662
|
-
yield
|
|
79546
|
+
yield textEncoder4.encode(chunk);
|
|
78663
79547
|
} else {
|
|
78664
79548
|
yield chunk;
|
|
78665
79549
|
}
|
|
@@ -85465,6 +86349,16 @@ var getRetryHint = (errorDetails) => {
|
|
|
85465
86349
|
}
|
|
85466
86350
|
return /"operator":"\{/.test(errorDetails) ? SINGLE_OPERATOR_PER_FIELD_HINT : FIELD_CAPABILITIES_HINT;
|
|
85467
86351
|
};
|
|
86352
|
+
var NO_SITE_IN_REQUEST = /META_SITE_NOT_FOUND|MetaSite(?:Id)? (?:context )?(?:is missing|was not found|not found)|NO_METASITE_IN_CALL_CONTEXT|MISSING_METASITE_ID|MISSING_REQUEST_SITE_CONTEXT|metasiteId from the request context/i;
|
|
86353
|
+
function missingSiteContext(status, responseData) {
|
|
86354
|
+
const details = typeof responseData === "string" ? responseData : JSON.stringify(responseData ?? "");
|
|
86355
|
+
if (NO_SITE_IN_REQUEST.test(details)) return "certain";
|
|
86356
|
+
const parsed = typeof responseData === "string" ? safeParseJSON(responseData) : responseData;
|
|
86357
|
+
if (status === 403 && parsed && typeof parsed === "object" && !parsed.message) {
|
|
86358
|
+
return "likely";
|
|
86359
|
+
}
|
|
86360
|
+
return null;
|
|
86361
|
+
}
|
|
85468
86362
|
var DEFAULT_OPENAI_SECURITY_SCHEMES = [
|
|
85469
86363
|
{ type: "oauth2", scopes: ["offline_access"] }
|
|
85470
86364
|
];
|
|
@@ -85479,7 +86373,8 @@ var buildErrorMessage = ({
|
|
|
85479
86373
|
status,
|
|
85480
86374
|
statusText,
|
|
85481
86375
|
requestId,
|
|
85482
|
-
responseData
|
|
86376
|
+
responseData,
|
|
86377
|
+
retryHint
|
|
85483
86378
|
}) => {
|
|
85484
86379
|
const responseDataObject = typeof responseData === "string" ? safeParseJSON(responseData) : responseData;
|
|
85485
86380
|
const errorDetails = typeof responseDataObject === "object" ? JSON.stringify(responseDataObject) : responseDataObject;
|
|
@@ -85491,7 +86386,7 @@ var buildErrorMessage = ({
|
|
|
85491
86386
|
].filter((str) => !!str).join("\n");
|
|
85492
86387
|
return `${baseMessage}
|
|
85493
86388
|
|
|
85494
|
-
${getRetryHint(String(errorDetails))}`;
|
|
86389
|
+
${retryHint ?? getRetryHint(String(errorDetails))}`;
|
|
85495
86390
|
};
|
|
85496
86391
|
var handleWixAPIResponse = async (response) => {
|
|
85497
86392
|
const requestId = response.headers?.["x-wix-request-id"];
|
|
@@ -85632,6 +86527,170 @@ function createToolBiEvent(params) {
|
|
|
85632
86527
|
return wixMcpRequestSrc39Evid1607(params);
|
|
85633
86528
|
}
|
|
85634
86529
|
|
|
86530
|
+
// src/api-call/site-files.ts
|
|
86531
|
+
var MAX_FILES_BUNDLE_CHARS = 4e6;
|
|
86532
|
+
var MAX_UNZIP_BYTES = 64 * 1024 * 1024;
|
|
86533
|
+
var textEncoder3 = new TextEncoder();
|
|
86534
|
+
function base64ToBytes(b64) {
|
|
86535
|
+
const clean = b64.replace(/^data:[^,]*,/, "").replace(/\s+/g, "");
|
|
86536
|
+
return Uint8Array.from(atob(clean), (c3) => c3.charCodeAt(0));
|
|
86537
|
+
}
|
|
86538
|
+
function parseFileBundle(bundle) {
|
|
86539
|
+
if (!bundle || !bundle.trim()) return [];
|
|
86540
|
+
if (bundle.length > MAX_FILES_BUNDLE_CHARS) {
|
|
86541
|
+
throw new Error(
|
|
86542
|
+
`files bundle is too large (${bundle.length} chars; max ${MAX_FILES_BUNDLE_CHARS}). Keep it to text and small base64 assets; pass larger files through attachments or reference media by URL.`
|
|
86543
|
+
);
|
|
86544
|
+
}
|
|
86545
|
+
const delimiter = /^=== FILE: (.+?)(?: (base64))? ===[ \t]*$/gm;
|
|
86546
|
+
const matches = [...bundle.matchAll(delimiter)];
|
|
86547
|
+
if (matches.length === 0) {
|
|
86548
|
+
throw new Error(
|
|
86549
|
+
"files bundle has no `=== FILE: <path> ===` sections. Start each file with that line (add ` base64` before the closing === for binary content)."
|
|
86550
|
+
);
|
|
86551
|
+
}
|
|
86552
|
+
return matches.map((match, i2) => {
|
|
86553
|
+
const path10 = match[1].trim();
|
|
86554
|
+
const start = (match.index ?? 0) + match[0].length;
|
|
86555
|
+
const end = i2 + 1 < matches.length ? matches[i2 + 1].index ?? bundle.length : bundle.length;
|
|
86556
|
+
const content = bundle.slice(start, end).replace(/^\r?\n/, "").replace(/\r?\n$/, "");
|
|
86557
|
+
return {
|
|
86558
|
+
path: path10,
|
|
86559
|
+
bytes: match[2] === "base64" ? base64ToBytes(content) : textEncoder3.encode(content)
|
|
86560
|
+
};
|
|
86561
|
+
});
|
|
86562
|
+
}
|
|
86563
|
+
var CRC_TABLE = (() => {
|
|
86564
|
+
const t = new Uint32Array(256);
|
|
86565
|
+
for (let n2 = 0; n2 < 256; n2++) {
|
|
86566
|
+
let c3 = n2;
|
|
86567
|
+
for (let k = 0; k < 8; k++) c3 = c3 & 1 ? 3988292384 ^ c3 >>> 1 : c3 >>> 1;
|
|
86568
|
+
t[n2] = c3 >>> 0;
|
|
86569
|
+
}
|
|
86570
|
+
return t;
|
|
86571
|
+
})();
|
|
86572
|
+
|
|
86573
|
+
// src/infra/redact-personal-data.ts
|
|
86574
|
+
var FREE_TEXT_INFO_PARAMS = [
|
|
86575
|
+
"userRequest",
|
|
86576
|
+
"siteDescription",
|
|
86577
|
+
"siteForm",
|
|
86578
|
+
"siteFunctionality",
|
|
86579
|
+
"agentIdentity",
|
|
86580
|
+
"wixAccess",
|
|
86581
|
+
"reason",
|
|
86582
|
+
"whyNotExecuteWixAPI",
|
|
86583
|
+
"editorRequest",
|
|
86584
|
+
"templateRequest"
|
|
86585
|
+
];
|
|
86586
|
+
var EMAIL = /[A-Z0-9._%+-]+@[A-Z0-9-]+(?:\.[A-Z0-9-]+)*\.[A-Z]{2,}/gi;
|
|
86587
|
+
var NAMED_SECRET = /\b(passwords?|passwd|pwd|passcodes?|secrets?|tokens?|api[ _-]?keys?|access[ _-]?keys?|credentials?)(\s*[:=]\s*|\s+(?:is|was|to)\s+)(?:"[^"]*"|'[^']*'|`[^`]*`|[^\s"'`,;][^,;\n]*?(?=[.!?]\s|[,;\n]|$))/gi;
|
|
86588
|
+
var BEARER = /\bBearer\s+[A-Za-z0-9._~+/=-]+/gi;
|
|
86589
|
+
var JWT = /\beyJ[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+/g;
|
|
86590
|
+
var KEY_PREFIXES = /\b(?:sk-[A-Za-z0-9_-]{16,}|gh[pousr]_[A-Za-z0-9]{20,}|github_pat_\w{20,}|xox[abprs]-[A-Za-z0-9-]{10,}|AKIA[0-9A-Z]{16}|AIza[0-9A-Za-z_-]{35})\b/g;
|
|
86591
|
+
var BACKTICK = "`";
|
|
86592
|
+
var UNIX_ROOT = String.raw`(?<![\w.:/~-])(?:~|/(?:Users|home|root|mnt|tmp|private|var|Volumes|workspace|work))`;
|
|
86593
|
+
var WINDOWS_ROOT = String.raw`(?<!\w)[A-Za-z]:(?=\\\w)`;
|
|
86594
|
+
var PATH_ROOT = `(?:${UNIX_ROOT}|${WINDOWS_ROOT})`;
|
|
86595
|
+
var QUOTED_PATH = new RegExp(
|
|
86596
|
+
String.raw`(?<![\w])(["'${BACKTICK}])${PATH_ROOT}[^"'${BACKTICK}\n]*\1`,
|
|
86597
|
+
"g"
|
|
86598
|
+
);
|
|
86599
|
+
var FOLDER = String.raw`[^\s/\\"'${BACKTICK},;()<>]+(?: [^\s/\\"'${BACKTICK},;()<>]+)*`;
|
|
86600
|
+
var LOCAL_PATH = new RegExp(
|
|
86601
|
+
String.raw`${PATH_ROOT}(?:[/\\]${FOLDER}(?=[/\\]))*[/\\][^\s"'${BACKTICK},;()<>]*`,
|
|
86602
|
+
"g"
|
|
86603
|
+
);
|
|
86604
|
+
var PHONE_CANDIDATE = /(?<![\w-])\+?\(?\d[\d\s().-]{7,}\d(?![\w-])/g;
|
|
86605
|
+
var DATE_START = /^\d{4}-\d{2}-\d{2}/;
|
|
86606
|
+
function redactPhone(match, offset, text) {
|
|
86607
|
+
if (DATE_START.test(match) || /^:\d{2}\b/.test(text.slice(offset + match.length))) {
|
|
86608
|
+
return match;
|
|
86609
|
+
}
|
|
86610
|
+
const digits = match.replace(/\D/g, "").length;
|
|
86611
|
+
return digits >= 9 && digits <= 15 ? "[phone]" : match;
|
|
86612
|
+
}
|
|
86613
|
+
function redactPersonalData(text) {
|
|
86614
|
+
return text.replace(EMAIL, "[email]").replace(BEARER, "Bearer [secret]").replace(JWT, "[secret]").replace(KEY_PREFIXES, "[secret]").replace(NAMED_SECRET, "$1$2[secret]").replace(QUOTED_PATH, "$1[path]$1").replace(LOCAL_PATH, "[path]").replace(PHONE_CANDIDATE, redactPhone);
|
|
86615
|
+
}
|
|
86616
|
+
function redactInfoParams(value) {
|
|
86617
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
86618
|
+
return value;
|
|
86619
|
+
}
|
|
86620
|
+
const record2 = value;
|
|
86621
|
+
if (!FREE_TEXT_INFO_PARAMS.some((key) => typeof record2[key] === "string")) {
|
|
86622
|
+
return value;
|
|
86623
|
+
}
|
|
86624
|
+
const redacted = { ...record2 };
|
|
86625
|
+
for (const key of FREE_TEXT_INFO_PARAMS) {
|
|
86626
|
+
if (typeof redacted[key] === "string") {
|
|
86627
|
+
redacted[key] = redactPersonalData(redacted[key]);
|
|
86628
|
+
}
|
|
86629
|
+
}
|
|
86630
|
+
return redacted;
|
|
86631
|
+
}
|
|
86632
|
+
var MAX_LISTED_PATHS_CHARS = 2e3;
|
|
86633
|
+
function summarizeFileBundle(bundle) {
|
|
86634
|
+
let sections;
|
|
86635
|
+
try {
|
|
86636
|
+
sections = parseFileBundle(bundle).map((file) => ({
|
|
86637
|
+
path: file.path,
|
|
86638
|
+
bytes: file.bytes.length
|
|
86639
|
+
}));
|
|
86640
|
+
} catch {
|
|
86641
|
+
sections = [];
|
|
86642
|
+
}
|
|
86643
|
+
if (sections.length === 0) {
|
|
86644
|
+
return `${new TextEncoder().encode(bundle).length} bytes, no file sections`;
|
|
86645
|
+
}
|
|
86646
|
+
return formatFileSummary(sections);
|
|
86647
|
+
}
|
|
86648
|
+
function formatFileSummary(files) {
|
|
86649
|
+
const total = files.reduce((sum, file) => sum + file.bytes, 0);
|
|
86650
|
+
let listed = "";
|
|
86651
|
+
let shown = 0;
|
|
86652
|
+
for (const file of files) {
|
|
86653
|
+
const entry = `${shown ? ", " : ""}${file.path} (${file.bytes})`;
|
|
86654
|
+
if (listed.length + entry.length > MAX_LISTED_PATHS_CHARS) break;
|
|
86655
|
+
listed += entry;
|
|
86656
|
+
shown++;
|
|
86657
|
+
}
|
|
86658
|
+
const more = files.length - shown;
|
|
86659
|
+
return `${files.length} file(s), ${total} bytes: ${listed}${more ? `${shown ? ", " : ""}and ${more} more` : ""}`;
|
|
86660
|
+
}
|
|
86661
|
+
function compactFileParams(value) {
|
|
86662
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
86663
|
+
return value;
|
|
86664
|
+
}
|
|
86665
|
+
const record2 = value;
|
|
86666
|
+
const files = record2.files;
|
|
86667
|
+
if (typeof files === "string") {
|
|
86668
|
+
return { ...record2, files: summarizeFileBundle(files) };
|
|
86669
|
+
}
|
|
86670
|
+
if (Array.isArray(files) && files.length > 0 && files.every(
|
|
86671
|
+
(entry) => entry && typeof entry === "object" && typeof entry.content === "string"
|
|
86672
|
+
)) {
|
|
86673
|
+
return {
|
|
86674
|
+
...record2,
|
|
86675
|
+
files: formatFileSummary(
|
|
86676
|
+
files.map((entry) => ({
|
|
86677
|
+
path: entry.path ?? "?",
|
|
86678
|
+
bytes: new TextEncoder().encode(entry.content).length
|
|
86679
|
+
}))
|
|
86680
|
+
)
|
|
86681
|
+
};
|
|
86682
|
+
}
|
|
86683
|
+
return value;
|
|
86684
|
+
}
|
|
86685
|
+
function prepareForBi(value) {
|
|
86686
|
+
return compactFileParams(redactInfoParams(value));
|
|
86687
|
+
}
|
|
86688
|
+
function serializeToolParamsForBi(args) {
|
|
86689
|
+
return JSON.stringify(
|
|
86690
|
+
Array.isArray(args) ? args.map(prepareForBi) : prepareForBi(args)
|
|
86691
|
+
);
|
|
86692
|
+
}
|
|
86693
|
+
|
|
85635
86694
|
// src/wix-mcp-server.ts
|
|
85636
86695
|
var WixMcpServer = class extends McpServer {
|
|
85637
86696
|
constructor(serverInfo, options, context2) {
|
|
@@ -85656,13 +86715,14 @@ var WixMcpServer = class extends McpServer {
|
|
|
85656
86715
|
gptAppSchemesEnabled = false;
|
|
85657
86716
|
openAiMcpAppsEnabled = false;
|
|
85658
86717
|
mcpAppsInMcpEnabled = true;
|
|
86718
|
+
registeredTools = /* @__PURE__ */ new Map();
|
|
85659
86719
|
setUserIdGetter(getUserId) {
|
|
85660
86720
|
this.getUserId = getUserId;
|
|
85661
86721
|
}
|
|
85662
86722
|
getSessionId() {
|
|
85663
86723
|
return this.sessionId;
|
|
85664
86724
|
}
|
|
85665
|
-
/** The connected client's name: the host's getter (User-Agent
|
|
86725
|
+
/** The connected client's name: the host's getter (initialize name, then User-Agent) first, then clientInfo. */
|
|
85666
86726
|
clientName() {
|
|
85667
86727
|
return this.getClientName?.() ?? this.server.getClientVersion()?.name;
|
|
85668
86728
|
}
|
|
@@ -85672,6 +86732,17 @@ var WixMcpServer = class extends McpServer {
|
|
|
85672
86732
|
setUserAgentGetter(getUserAgent) {
|
|
85673
86733
|
this.getUserAgent = getUserAgent;
|
|
85674
86734
|
}
|
|
86735
|
+
/** True when every named tool is registered and enabled in this session. */
|
|
86736
|
+
hasTools(...names) {
|
|
86737
|
+
return names.every((name) => this.registeredTools.get(name)?.enabled);
|
|
86738
|
+
}
|
|
86739
|
+
/**
|
|
86740
|
+
* Sets the `instructions` the server returns at initialize. Call it before the transport
|
|
86741
|
+
* connects. The SDK keeps them on the low-level server and has no setter for them.
|
|
86742
|
+
*/
|
|
86743
|
+
setInstructions(instructions) {
|
|
86744
|
+
this.server._instructions = instructions;
|
|
86745
|
+
}
|
|
85675
86746
|
setGptAppSchemesEnabled(enabled) {
|
|
85676
86747
|
this.gptAppSchemesEnabled = enabled;
|
|
85677
86748
|
}
|
|
@@ -85727,6 +86798,7 @@ var WixMcpServer = class extends McpServer {
|
|
|
85727
86798
|
args[cbIndex] = this.wrapToolCallback(toolName, originalCb);
|
|
85728
86799
|
}
|
|
85729
86800
|
const registeredTool = super.tool.apply(this, args);
|
|
86801
|
+
this.registeredTools.set(args[0], registeredTool);
|
|
85730
86802
|
if (this.isGptAppSchemesEnabled() && !registeredTool._meta?.securitySchemes) {
|
|
85731
86803
|
registeredTool.update({
|
|
85732
86804
|
_meta: {
|
|
@@ -85748,11 +86820,13 @@ var WixMcpServer = class extends McpServer {
|
|
|
85748
86820
|
};
|
|
85749
86821
|
}
|
|
85750
86822
|
const wrappedCb = this.wrapToolCallback(name, cb);
|
|
85751
|
-
|
|
86823
|
+
const registeredTool = super.registerTool(
|
|
85752
86824
|
name,
|
|
85753
86825
|
config3,
|
|
85754
86826
|
wrappedCb
|
|
85755
86827
|
);
|
|
86828
|
+
this.registeredTools.set(name, registeredTool);
|
|
86829
|
+
return registeredTool;
|
|
85756
86830
|
}
|
|
85757
86831
|
wrapToolCallback(toolName, originalCb) {
|
|
85758
86832
|
const isDevEnvironment = DEV_ENVIRONMENTS.includes(this.nodeEnv);
|
|
@@ -85794,7 +86868,7 @@ var WixMcpServer = class extends McpServer {
|
|
|
85794
86868
|
});
|
|
85795
86869
|
panorama.transaction(toolName).start({
|
|
85796
86870
|
toolInvocationId,
|
|
85797
|
-
params:
|
|
86871
|
+
params: serializeToolParamsForBi(argsBeforeExtra)
|
|
85798
86872
|
});
|
|
85799
86873
|
}
|
|
85800
86874
|
const startTime = performance.now();
|
|
@@ -85811,7 +86885,8 @@ var WixMcpServer = class extends McpServer {
|
|
|
85811
86885
|
cbResult,
|
|
85812
86886
|
{
|
|
85813
86887
|
returnedRows: toolBiParams.returnedRows,
|
|
85814
|
-
originalLength: toolBiParams.originalLength
|
|
86888
|
+
originalLength: toolBiParams.originalLength,
|
|
86889
|
+
upload: toolBiParams.upload
|
|
85815
86890
|
},
|
|
85816
86891
|
{
|
|
85817
86892
|
name: this.getClientName?.() || this.server.getClientVersion()?.name,
|
|
@@ -85827,7 +86902,7 @@ var WixMcpServer = class extends McpServer {
|
|
|
85827
86902
|
context: {
|
|
85828
86903
|
toolName,
|
|
85829
86904
|
toolInvocationId,
|
|
85830
|
-
params:
|
|
86905
|
+
params: serializeToolParamsForBi(argsBeforeExtra),
|
|
85831
86906
|
error: JSON.stringify(cbResult, null, 2)
|
|
85832
86907
|
}
|
|
85833
86908
|
});
|
|
@@ -85841,7 +86916,7 @@ var WixMcpServer = class extends McpServer {
|
|
|
85841
86916
|
context: {
|
|
85842
86917
|
toolName,
|
|
85843
86918
|
toolInvocationId,
|
|
85844
|
-
params:
|
|
86919
|
+
params: serializeToolParamsForBi(argsBeforeExtra),
|
|
85845
86920
|
error: errorBody
|
|
85846
86921
|
}
|
|
85847
86922
|
});
|
|
@@ -85890,7 +86965,7 @@ var WixMcpServer = class extends McpServer {
|
|
|
85890
86965
|
errorBody,
|
|
85891
86966
|
toolInvocationId,
|
|
85892
86967
|
toolName,
|
|
85893
|
-
params:
|
|
86968
|
+
params: serializeToolParamsForBi(argsBeforeExtra),
|
|
85894
86969
|
origin: this.nodeEnv,
|
|
85895
86970
|
sessionId: this.sessionId,
|
|
85896
86971
|
executionResult: toolSucceeded ? "Success" : "Error",
|
|
@@ -86133,7 +87208,7 @@ function resolveBase64Image(imageBase64, mimeType) {
|
|
|
86133
87208
|
function errorResponse(text) {
|
|
86134
87209
|
return { isError: true, content: [{ type: "text", text }] };
|
|
86135
87210
|
}
|
|
86136
|
-
async function uploadFromUrl(item, authHeaders, displayName) {
|
|
87211
|
+
async function uploadFromUrl(item, authHeaders, displayName, imagePickerToolName) {
|
|
86137
87212
|
if (!item.download_url) {
|
|
86138
87213
|
return {
|
|
86139
87214
|
success: false,
|
|
@@ -86143,7 +87218,7 @@ async function uploadFromUrl(item, authHeaders, displayName) {
|
|
|
86143
87218
|
if (!/^https?:\/\//i.test(item.download_url)) {
|
|
86144
87219
|
return {
|
|
86145
87220
|
success: false,
|
|
86146
|
-
error: `
|
|
87221
|
+
error: `This server can't read files on your machine or sandbox (got: "${item.download_url}"). Send this image as imageBase64 (the whole file, one per call) or as a public URL in imageUrls${imagePickerToolName ? `, or call ${imagePickerToolName} so the user picks it` : ""}.`
|
|
86147
87222
|
};
|
|
86148
87223
|
}
|
|
86149
87224
|
try {
|
|
@@ -86241,7 +87316,10 @@ function formatBatchResults(results) {
|
|
|
86241
87316
|
};
|
|
86242
87317
|
}
|
|
86243
87318
|
function addUploadImageTool(server2, strategy, options) {
|
|
86244
|
-
const
|
|
87319
|
+
const imagePickerToolName = options?.imagePickerToolName;
|
|
87320
|
+
const baseDescription = options?.description || defaultToolDescriptions.UploadImageToWixSite;
|
|
87321
|
+
const description = imagePickerToolName ? `${baseDescription}
|
|
87322
|
+
If you can't deliver the image any of these ways, call ${imagePickerToolName} so the user picks it.` : baseDescription;
|
|
86245
87323
|
const hints = {
|
|
86246
87324
|
readOnlyHint: options?.hints?.readOnlyHint ?? false,
|
|
86247
87325
|
destructiveHint: options?.hints?.destructiveHint ?? false,
|
|
@@ -86308,7 +87386,9 @@ function addUploadImageTool(server2, strategy, options) {
|
|
|
86308
87386
|
try {
|
|
86309
87387
|
const authHeaders = await strategy.getSiteAuthHeaders(siteId);
|
|
86310
87388
|
const urlResults = await Promise.all(
|
|
86311
|
-
urlItems.map(
|
|
87389
|
+
urlItems.map(
|
|
87390
|
+
(item) => uploadFromUrl(item, authHeaders, displayName, imagePickerToolName)
|
|
87391
|
+
)
|
|
86312
87392
|
);
|
|
86313
87393
|
let base64Result = null;
|
|
86314
87394
|
if (imageBase64) {
|
|
@@ -86344,6 +87424,9 @@ function addUploadImageTool(server2, strategy, options) {
|
|
|
86344
87424
|
var MAX_ALLOWED_RESPONSE_CHARS = 2e6;
|
|
86345
87425
|
|
|
86346
87426
|
// src/api-call/index.ts
|
|
87427
|
+
var siteToolCall = (executeServed) => executeServed ? "through ExecuteWixAPI with that site's `siteId` (`scope: \"site\"`), loading ExecuteWixAPI through your client's tool search if it isn't loaded" : "through CallWixSiteAPI with that site's `siteId`";
|
|
87428
|
+
var manageNoSiteHint = (executeServed) => `This is a site-level API: it acts inside a site, and ManageWixSite sends no site, so the same call fails here every time. Call the same URL, method and body ${siteToolCall(executeServed)}.`;
|
|
87429
|
+
var manageEmpty403Hint = (executeServed) => `If this endpoint acts inside a site (its products, data, bookings, members, pages, publishing), it is site-level, and ManageWixSite sends no site: call the same URL, method and body ${siteToolCall(executeServed)}. If it acts on the account or on sites as objects in it, the account lacks the permission; don't retry.`;
|
|
86347
87430
|
var DEFAULT_MAX_RESPONSE_SIZE = 5e4;
|
|
86348
87431
|
function extractReturnedRows(responseData) {
|
|
86349
87432
|
if (responseData === null || typeof responseData !== "object") {
|
|
@@ -86375,7 +87458,8 @@ function formatApiResponse(responseData, maxResponseSize = DEFAULT_MAX_RESPONSE_
|
|
|
86375
87458
|
}
|
|
86376
87459
|
return { text: responseText, isError: false, originalLength, returnedRows };
|
|
86377
87460
|
}
|
|
86378
|
-
function addApiCallTool(server2, strategy, allowedTools = ["CallWixSiteAPI", "ListWixSites", "ManageWixSite"], disableTools = [], enableTools = [], toolDescriptions, toolHints, maxResponseSize) {
|
|
87461
|
+
function addApiCallTool(server2, strategy, allowedTools = ["CallWixSiteAPI", "ListWixSites", "ManageWixSite"], disableTools = [], enableTools = [], toolDescriptions, toolHints, maxResponseSize, options) {
|
|
87462
|
+
const executeAdvice = (text, reconnect, plain) => options?.executeWixAPIServed ? text : text.replace(reconnect, plain);
|
|
86379
87463
|
const effectiveAllowedTools = [
|
|
86380
87464
|
.../* @__PURE__ */ new Set([...allowedTools, ...enableTools])
|
|
86381
87465
|
].filter((tool) => !disableTools.includes(tool));
|
|
@@ -86388,7 +87472,14 @@ function addApiCallTool(server2, strategy, allowedTools = ["CallWixSiteAPI", "Li
|
|
|
86388
87472
|
if (effectiveAllowedTools.includes("CallWixSiteAPI") && !disableTools.includes("CallWixSiteAPI")) {
|
|
86389
87473
|
server2.tool(
|
|
86390
87474
|
"CallWixSiteAPI",
|
|
86391
|
-
|
|
87475
|
+
executeAdvice(
|
|
87476
|
+
getDescription(
|
|
87477
|
+
"CallWixSiteAPI",
|
|
87478
|
+
defaultToolDescriptions.CallWixSiteAPI
|
|
87479
|
+
),
|
|
87480
|
+
CALL_WIX_SITE_API_RECONNECT_LINE,
|
|
87481
|
+
CALL_WIX_SITE_API_NO_EXECUTE_LINE
|
|
87482
|
+
),
|
|
86392
87483
|
(() => {
|
|
86393
87484
|
const d = desc("CallWixSiteAPI");
|
|
86394
87485
|
return {
|
|
@@ -86397,6 +87488,13 @@ function addApiCallTool(server2, strategy, allowedTools = ["CallWixSiteAPI", "Li
|
|
|
86397
87488
|
method: external_exports.string().describe(d.method),
|
|
86398
87489
|
body: external_exports.union([external_exports.object({}).passthrough(), external_exports.array(external_exports.unknown())]).optional().describe(d.body),
|
|
86399
87490
|
reason: external_exports.string().describe(d.reason),
|
|
87491
|
+
whyNotExecuteWixAPI: external_exports.string().optional().describe(
|
|
87492
|
+
executeAdvice(
|
|
87493
|
+
d.whyNotExecuteWixAPI,
|
|
87494
|
+
WHY_NOT_EXECUTE_RECONNECT,
|
|
87495
|
+
WHY_NOT_EXECUTE_NO_EXECUTE
|
|
87496
|
+
)
|
|
87497
|
+
),
|
|
86400
87498
|
sourceDocUrl: external_exports.string().describe(d.sourceDocUrl)
|
|
86401
87499
|
};
|
|
86402
87500
|
})(),
|
|
@@ -86407,9 +87505,17 @@ function addApiCallTool(server2, strategy, allowedTools = ["CallWixSiteAPI", "Li
|
|
|
86407
87505
|
destructiveHint: true,
|
|
86408
87506
|
openWorldHint: true
|
|
86409
87507
|
}),
|
|
86410
|
-
async ({
|
|
87508
|
+
async ({
|
|
87509
|
+
url,
|
|
87510
|
+
body,
|
|
87511
|
+
method,
|
|
87512
|
+
siteId,
|
|
87513
|
+
reason,
|
|
87514
|
+
whyNotExecuteWixAPI,
|
|
87515
|
+
sourceDocUrl
|
|
87516
|
+
}, { httpClient, setToolBiParams }) => {
|
|
86411
87517
|
logger2.log(
|
|
86412
|
-
`[CallWixSiteAPI] siteId=${siteId}, method=${method}, url=${url}, sourceDocUrl=${sourceDocUrl}, reason="${reason}", body=${JSON.stringify(body)}`
|
|
87518
|
+
`[CallWixSiteAPI] siteId=${siteId}, method=${method}, url=${url}, sourceDocUrl=${sourceDocUrl}, reason="${reason}", whyNotExecuteWixAPI="${whyNotExecuteWixAPI ?? ""}", body=${JSON.stringify(body)}`
|
|
86413
87519
|
);
|
|
86414
87520
|
const requestHeaders = {
|
|
86415
87521
|
// Ask the Wix API edge for JSON error bodies (it serves a branded HTML
|
|
@@ -86644,6 +87750,18 @@ function addApiCallTool(server2, strategy, allowedTools = ["CallWixSiteAPI", "Li
|
|
|
86644
87750
|
if (!response) {
|
|
86645
87751
|
throw new Error(`Failed to call Wix Account API: ${error2}`);
|
|
86646
87752
|
}
|
|
87753
|
+
const noSite = missingSiteContext(response.status, response.data);
|
|
87754
|
+
if (noSite) {
|
|
87755
|
+
throw new Error(
|
|
87756
|
+
buildErrorMessage({
|
|
87757
|
+
status: response.status,
|
|
87758
|
+
statusText: response.statusText,
|
|
87759
|
+
requestId: response.headers?.["x-wix-request-id"] ?? null,
|
|
87760
|
+
responseData: response.data,
|
|
87761
|
+
retryHint: (noSite === "certain" ? manageNoSiteHint : manageEmpty403Hint)(!!options?.executeWixAPIServed)
|
|
87762
|
+
})
|
|
87763
|
+
);
|
|
87764
|
+
}
|
|
86647
87765
|
return handleWixAPIResponse(response);
|
|
86648
87766
|
}
|
|
86649
87767
|
}
|
|
@@ -86652,7 +87770,8 @@ function addApiCallTool(server2, strategy, allowedTools = ["CallWixSiteAPI", "Li
|
|
|
86652
87770
|
if (effectiveAllowedTools.includes("UploadImageToWixSite") && !disableTools.includes("UploadImageToWixSite")) {
|
|
86653
87771
|
addUploadImageTool(server2, strategy, {
|
|
86654
87772
|
description: getDescription("UploadImageToWixSite", ""),
|
|
86655
|
-
hints: toolHints?.["UploadImageToWixSite"]
|
|
87773
|
+
hints: toolHints?.["UploadImageToWixSite"],
|
|
87774
|
+
imagePickerToolName: options?.imagePickerToolName
|
|
86656
87775
|
});
|
|
86657
87776
|
}
|
|
86658
87777
|
}
|
|
@@ -86932,10 +88051,14 @@ function truncateResponse(content, maxChars = DEFAULT_MAX_CHARS) {
|
|
|
86932
88051
|
const truncated = text.slice(0, effectiveMax);
|
|
86933
88052
|
const estimatedTokens = Math.ceil(text.length / CHARS_PER_TOKEN);
|
|
86934
88053
|
const limitTokens = Math.ceil(effectiveMax / CHARS_PER_TOKEN);
|
|
86935
|
-
|
|
88054
|
+
const cutChars = text.length - effectiveMax;
|
|
88055
|
+
const note = `Response was ~${estimatedTokens.toLocaleString()} tokens (limit: ${limitTokens.toLocaleString()}). Showing the first ${effectiveMax.toLocaleString()} of ${text.length.toLocaleString()} characters; the last ${cutChars.toLocaleString()} were cut. To get the rest, run again and return less per call \u2014 only the fields you need, the next page (cursor or offset), or the next slice of a large array \u2014 and repeat until you have it all.`;
|
|
88056
|
+
return `[TRUNCATED: ${note}]
|
|
88057
|
+
|
|
88058
|
+
${truncated}
|
|
86936
88059
|
|
|
86937
88060
|
--- TRUNCATED ---
|
|
86938
|
-
|
|
88061
|
+
${note}`;
|
|
86939
88062
|
}
|
|
86940
88063
|
|
|
86941
88064
|
// src/graphql/constants.ts
|
|
@@ -87772,7 +88895,9 @@ if (docsTools.length > 0 || hasGetToKnowWix) {
|
|
|
87772
88895
|
logger2.log("Adding docs tools:", docsTools);
|
|
87773
88896
|
addDocsTools(server, docsTools, {
|
|
87774
88897
|
getToKnowWixEnabled: hasGetToKnowWix,
|
|
87775
|
-
dynamicContextEnabled: hasDynamicContext
|
|
88898
|
+
dynamicContextEnabled: hasDynamicContext,
|
|
88899
|
+
// Mintlify docs: --docsSite=mintlify-links (or WIX_MCP_DOCS_SITE).
|
|
88900
|
+
docsSite: parsedArgs["docsSite"] ?? process.env.WIX_MCP_DOCS_SITE
|
|
87776
88901
|
});
|
|
87777
88902
|
}
|
|
87778
88903
|
if (activeTools.includes("VELO_README")) {
|