@umbraco-cms/mcp-dev 17.4.1 → 17.4.2
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/dist/{chunk-H5ZIS43M.cjs → chunk-Q4LCXM42.cjs} +338 -66
- package/dist/chunk-Q4LCXM42.cjs.map +1 -0
- package/dist/{chunk-XVBYRUFE.js → chunk-VLJ3JQ46.js} +796 -524
- package/dist/chunk-VLJ3JQ46.js.map +1 -0
- package/dist/collections.cjs +2 -2
- package/dist/collections.js +1 -1
- package/dist/index.cjs +90 -90
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +4 -4
- package/dist/index.js.map +1 -1
- package/dist/tool-types.d.ts +8261 -24
- package/package.json +3 -3
- package/dist/chunk-H5ZIS43M.cjs.map +0 -1
- package/dist/chunk-XVBYRUFE.js.map +0 -1
|
@@ -18711,7 +18711,7 @@ async function validateFilePath(filePath, allowedPaths) {
|
|
|
18711
18711
|
try {
|
|
18712
18712
|
const realAllowedPath = fs.realpathSync(allowedPath);
|
|
18713
18713
|
return normalizedPath.startsWith(realAllowedPath);
|
|
18714
|
-
} catch (
|
|
18714
|
+
} catch (e2) {
|
|
18715
18715
|
return false;
|
|
18716
18716
|
}
|
|
18717
18717
|
});
|
|
@@ -18729,7 +18729,7 @@ async function validateFilePath(filePath, allowedPaths) {
|
|
|
18729
18729
|
try {
|
|
18730
18730
|
const realAllowedPath = fs.realpathSync(allowedPath);
|
|
18731
18731
|
return realPath.startsWith(realAllowedPath);
|
|
18732
|
-
} catch (
|
|
18732
|
+
} catch (e3) {
|
|
18733
18733
|
return false;
|
|
18734
18734
|
}
|
|
18735
18735
|
});
|
|
@@ -18756,6 +18756,7 @@ async function validateFilePath(filePath, allowedPaths) {
|
|
|
18756
18756
|
|
|
18757
18757
|
|
|
18758
18758
|
|
|
18759
|
+
var BASE64_MAX_BYTES = 10 * 1024;
|
|
18759
18760
|
function getExtensionFromMimeType(mimeType) {
|
|
18760
18761
|
if (!mimeType) return void 0;
|
|
18761
18762
|
const baseMimeType = mimeType.split(";")[0].trim();
|
|
@@ -18877,6 +18878,13 @@ async function createFilePayload(sourceType, filePath, fileUrl, fileAsBase64, fi
|
|
|
18877
18878
|
if (!fileAsBase64) {
|
|
18878
18879
|
throw new Error("fileAsBase64 is required when sourceType is 'base64'");
|
|
18879
18880
|
}
|
|
18881
|
+
const padding = fileAsBase64.endsWith("==") ? 2 : fileAsBase64.endsWith("=") ? 1 : 0;
|
|
18882
|
+
const estimatedBytes = Math.floor(fileAsBase64.length * 3 / 4) - padding;
|
|
18883
|
+
if (estimatedBytes > BASE64_MAX_BYTES) {
|
|
18884
|
+
throw new Error(
|
|
18885
|
+
`base64 upload rejected: decoded payload is ~${estimatedBytes.toLocaleString()} bytes (limit is ${BASE64_MAX_BYTES.toLocaleString()} bytes). Use sourceType="url" with a public direct-download URL, or sourceType="file" if the file is attached to the chat.`
|
|
18886
|
+
);
|
|
18887
|
+
}
|
|
18880
18888
|
const buffer = Buffer.from(fileAsBase64, "base64");
|
|
18881
18889
|
let filename = fileName;
|
|
18882
18890
|
if (!fileName.includes(".")) {
|
|
@@ -18958,6 +18966,174 @@ function buildSourceTypeSection(allowFilePath, otherSources) {
|
|
|
18958
18966
|
return sources.map((s, i) => ` ${i + 1}. ${s}`).join("\n");
|
|
18959
18967
|
}
|
|
18960
18968
|
|
|
18969
|
+
// src/umb-management-api/tools/media/post/helpers/streaming-upload.ts
|
|
18970
|
+
|
|
18971
|
+
|
|
18972
|
+
var _mcphosted = require('@umbraco-cms/mcp-hosted');
|
|
18973
|
+
|
|
18974
|
+
|
|
18975
|
+
|
|
18976
|
+
|
|
18977
|
+
|
|
18978
|
+
|
|
18979
|
+
var authContext = null;
|
|
18980
|
+
function isStreamingAuthContextConfigured() {
|
|
18981
|
+
return authContext !== null;
|
|
18982
|
+
}
|
|
18983
|
+
async function resolveAuth() {
|
|
18984
|
+
if (!authContext) {
|
|
18985
|
+
throw new Error(
|
|
18986
|
+
"Streaming auth context not configured. setStreamingAuthContext() must be called in worker init()."
|
|
18987
|
+
);
|
|
18988
|
+
}
|
|
18989
|
+
const entry = await _mcphosted.getStoredUmbracoToken.call(void 0, authContext.env.OAUTH_KV, authContext.tokenKey);
|
|
18990
|
+
if (!_optionalChain([entry, 'optionalAccess', _48 => _48.tokens, 'optionalAccess', _49 => _49.access_token])) {
|
|
18991
|
+
throw new Error("No Umbraco access token in KV. Reconnect the MCP connector.");
|
|
18992
|
+
}
|
|
18993
|
+
const baseUrl = _nullishCoalesce(_nullishCoalesce(_nullishCoalesce(_optionalChain([entry, 'access', _50 => _50.site, 'optionalAccess', _51 => _51.serverUrl]), () => ( _optionalChain([entry, 'access', _52 => _52.site, 'optionalAccess', _53 => _53.baseUrl]))), () => ( authContext.env.UMBRACO_SERVER_URL)), () => ( authContext.env.UMBRACO_BASE_URL));
|
|
18994
|
+
if (!baseUrl) {
|
|
18995
|
+
throw new Error("No Umbraco base URL resolvable from site or env.");
|
|
18996
|
+
}
|
|
18997
|
+
return { accessToken: entry.tokens.access_token, baseUrl: _mcpserversdk.normalizeBaseUrl.call(void 0, baseUrl) };
|
|
18998
|
+
}
|
|
18999
|
+
function ensureExtension(name, contentType, urlPath) {
|
|
19000
|
+
if (name.includes(".")) return name;
|
|
19001
|
+
const fromUrl = _optionalChain([urlPath, 'access', _54 => _54.match, 'call', _55 => _55(/\.([a-z0-9]{1,8})$/i), 'optionalAccess', _56 => _56[0]]);
|
|
19002
|
+
if (fromUrl) return `${name}${fromUrl}`;
|
|
19003
|
+
if (contentType) {
|
|
19004
|
+
const subtype = contentType.split(";")[0].split("/")[1];
|
|
19005
|
+
if (subtype && /^[a-z0-9]{1,8}$/i.test(subtype)) {
|
|
19006
|
+
return `${name}.${subtype === "jpeg" ? "jpg" : subtype}`;
|
|
19007
|
+
}
|
|
19008
|
+
}
|
|
19009
|
+
return `${name}.bin`;
|
|
19010
|
+
}
|
|
19011
|
+
async function streamingUploadFromUrl(params) {
|
|
19012
|
+
const client = UmbracoManagementClient3.getClient();
|
|
19013
|
+
const validatedMediaTypeName = validateMediaTypeForSvg(
|
|
19014
|
+
void 0,
|
|
19015
|
+
params.sourceUrl,
|
|
19016
|
+
params.name,
|
|
19017
|
+
params.mediaTypeName
|
|
19018
|
+
);
|
|
19019
|
+
const [mediaTypeId, auth] = await Promise.all([
|
|
19020
|
+
fetchMediaTypeId(client, validatedMediaTypeName),
|
|
19021
|
+
(async () => {
|
|
19022
|
+
await client.getTemporaryFileConfiguration().catch(() => void 0);
|
|
19023
|
+
return resolveAuth();
|
|
19024
|
+
})()
|
|
19025
|
+
]);
|
|
19026
|
+
const { accessToken, baseUrl } = auth;
|
|
19027
|
+
const ctl = new AbortController();
|
|
19028
|
+
const overallTimeout = setTimeout(() => ctl.abort(), 6e4);
|
|
19029
|
+
try {
|
|
19030
|
+
const sourceResp = await fetch(params.sourceUrl, { signal: ctl.signal });
|
|
19031
|
+
if (!sourceResp.ok || !sourceResp.body) {
|
|
19032
|
+
throw new Error(
|
|
19033
|
+
`Failed to fetch source URL: HTTP ${sourceResp.status} ${sourceResp.statusText}`
|
|
19034
|
+
);
|
|
19035
|
+
}
|
|
19036
|
+
const sourceContentType = _nullishCoalesce(sourceResp.headers.get("content-type"), () => ( "application/octet-stream"));
|
|
19037
|
+
const sourceUrl = new URL(params.sourceUrl);
|
|
19038
|
+
const filename = ensureExtension(params.name, sourceContentType, sourceUrl.pathname);
|
|
19039
|
+
const temporaryFileId = crypto.randomUUID();
|
|
19040
|
+
const boundary = `----mcp-stream-${crypto.randomUUID()}`;
|
|
19041
|
+
const encoder = new TextEncoder();
|
|
19042
|
+
const prefix = encoder.encode(
|
|
19043
|
+
`--${boundary}\r
|
|
19044
|
+
Content-Disposition: form-data; name="Id"\r
|
|
19045
|
+
\r
|
|
19046
|
+
${temporaryFileId}\r
|
|
19047
|
+
--${boundary}\r
|
|
19048
|
+
Content-Disposition: form-data; name="File"; filename="${filename}"\r
|
|
19049
|
+
Content-Type: ${sourceContentType}\r
|
|
19050
|
+
\r
|
|
19051
|
+
`
|
|
19052
|
+
);
|
|
19053
|
+
const suffix = encoder.encode(`\r
|
|
19054
|
+
--${boundary}--\r
|
|
19055
|
+
`);
|
|
19056
|
+
const sourceBody = sourceResp.body;
|
|
19057
|
+
const multipartBody = new ReadableStream({
|
|
19058
|
+
async start(controller) {
|
|
19059
|
+
const reader = sourceBody.getReader();
|
|
19060
|
+
try {
|
|
19061
|
+
controller.enqueue(prefix);
|
|
19062
|
+
while (true) {
|
|
19063
|
+
const { done, value } = await reader.read();
|
|
19064
|
+
if (done) break;
|
|
19065
|
+
if (value) controller.enqueue(value);
|
|
19066
|
+
}
|
|
19067
|
+
controller.enqueue(suffix);
|
|
19068
|
+
controller.close();
|
|
19069
|
+
} catch (e) {
|
|
19070
|
+
controller.error(e);
|
|
19071
|
+
} finally {
|
|
19072
|
+
reader.releaseLock();
|
|
19073
|
+
}
|
|
19074
|
+
},
|
|
19075
|
+
cancel(reason) {
|
|
19076
|
+
sourceBody.cancel(reason).catch(() => void 0);
|
|
19077
|
+
}
|
|
19078
|
+
});
|
|
19079
|
+
const tempResp = await fetch(`${baseUrl}/umbraco/management/api/v1/temporary-file`, {
|
|
19080
|
+
method: "POST",
|
|
19081
|
+
body: multipartBody,
|
|
19082
|
+
// @ts-expect-error — `duplex` is required by Workers/undici for streaming bodies
|
|
19083
|
+
duplex: "half",
|
|
19084
|
+
signal: ctl.signal,
|
|
19085
|
+
headers: {
|
|
19086
|
+
"Content-Type": `multipart/form-data; boundary=${boundary}`,
|
|
19087
|
+
Authorization: `Bearer ${accessToken}`,
|
|
19088
|
+
Accept: "application/json"
|
|
19089
|
+
}
|
|
19090
|
+
});
|
|
19091
|
+
if (!tempResp.ok) {
|
|
19092
|
+
const errBody = await tempResp.text().catch(() => "");
|
|
19093
|
+
throw new Error(
|
|
19094
|
+
`Umbraco temporary-file POST failed: HTTP ${tempResp.status} ${tempResp.statusText} - ${errBody}`
|
|
19095
|
+
);
|
|
19096
|
+
}
|
|
19097
|
+
const valueStructure = buildValueStructure(validatedMediaTypeName, temporaryFileId);
|
|
19098
|
+
const response = await client.postMedia(
|
|
19099
|
+
{
|
|
19100
|
+
mediaType: { id: mediaTypeId },
|
|
19101
|
+
variants: [{ culture: null, segment: null, name: params.name }],
|
|
19102
|
+
values: [valueStructure],
|
|
19103
|
+
parent: params.parentId ? { id: params.parentId } : null
|
|
19104
|
+
},
|
|
19105
|
+
_mcpserversdk.CAPTURE_RAW_HTTP_RESPONSE
|
|
19106
|
+
);
|
|
19107
|
+
if (response.status < 200 || response.status >= 300) {
|
|
19108
|
+
throw new Error(`postMedia failed with status ${response.status}`);
|
|
19109
|
+
}
|
|
19110
|
+
const locationHeader = _nullishCoalesce(_optionalChain([response, 'access', _57 => _57.headers, 'optionalAccess', _58 => _58.location]), () => ( _optionalChain([response, 'access', _59 => _59.headers, 'optionalAccess', _60 => _60.Location])));
|
|
19111
|
+
const idMatch = _optionalChain([locationHeader, 'optionalAccess', _61 => _61.match, 'call', _62 => _62(/\/([a-f0-9-]{36})$/i)]);
|
|
19112
|
+
if (!idMatch) {
|
|
19113
|
+
throw new Error(
|
|
19114
|
+
`Could not extract media id from Location header: ${_nullishCoalesce(locationHeader, () => ( "(missing)"))}`
|
|
19115
|
+
);
|
|
19116
|
+
}
|
|
19117
|
+
return { name: params.name, id: idMatch[1] };
|
|
19118
|
+
} finally {
|
|
19119
|
+
clearTimeout(overallTimeout);
|
|
19120
|
+
}
|
|
19121
|
+
}
|
|
19122
|
+
async function streamingUploadToToolResult(params) {
|
|
19123
|
+
try {
|
|
19124
|
+
const { name, id } = await streamingUploadFromUrl(params);
|
|
19125
|
+
return _mcpserversdk.createToolResult.call(void 0, {
|
|
19126
|
+
message: `Media "${name}" created successfully`,
|
|
19127
|
+
name,
|
|
19128
|
+
id
|
|
19129
|
+
});
|
|
19130
|
+
} catch (error) {
|
|
19131
|
+
return _mcpserversdk.createToolResultError.call(void 0, {
|
|
19132
|
+
detail: `Error creating media: ${error.message}`
|
|
19133
|
+
});
|
|
19134
|
+
}
|
|
19135
|
+
}
|
|
19136
|
+
|
|
18961
19137
|
// src/umb-management-api/tools/media/post/create-media.ts
|
|
18962
19138
|
|
|
18963
19139
|
|
|
@@ -18970,31 +19146,48 @@ function buildSourceTypeSection(allowFilePath, otherSources) {
|
|
|
18970
19146
|
|
|
18971
19147
|
|
|
18972
19148
|
|
|
19149
|
+
var fileObjectSchema = _zod.z.object({
|
|
19150
|
+
download_url: _zod.z.string().describe("Temporary URL the host provides to fetch the file bytes"),
|
|
19151
|
+
file_id: _zod.z.string().describe("Persistent file identifier from the host"),
|
|
19152
|
+
mime_type: _zod.z.string().optional().describe("MIME type if the host knows it"),
|
|
19153
|
+
file_name: _zod.z.string().optional().describe("Original file name if the host knows it")
|
|
19154
|
+
});
|
|
18973
19155
|
var createMediaOutputSchema = _zod.z.object({
|
|
18974
19156
|
message: _zod.z.string(),
|
|
18975
19157
|
name: _zod.z.string(),
|
|
18976
19158
|
id: _zod.z.string().guid()
|
|
18977
19159
|
});
|
|
18978
19160
|
function createCreateMediaTool(options) {
|
|
18979
|
-
const sourceTypeValues = options.allowFilePath ? ["filePath", "url", "base64"] : ["url", "base64"];
|
|
18980
|
-
const
|
|
19161
|
+
const sourceTypeValues = options.allowFilePath ? ["filePath", "url", "file", "base64"] : ["url", "file", "base64"];
|
|
19162
|
+
const base64Kib = BASE64_MAX_BYTES / 1024;
|
|
19163
|
+
const filePathPrefix = options.allowFilePath ? "'filePath' for local files (Node stdio only), " : "";
|
|
19164
|
+
const sourceTypeDescription = `Media source type: ${filePathPrefix}'url' for public direct-download URLs (streamed; preferred for everything not already attached to the chat), 'file' for host-injected attachments \u2014 the connector populates the 'file' object automatically when the user attached a file or you generated one in this chat, 'base64' for TINY inline payloads only \u2014 the server rejects base64 above ${base64Kib} KiB decoded to stop LLM-truncated or thumbnail-preview base64 from persisting as corrupt files`;
|
|
18981
19165
|
const schema = _zod.z.object({
|
|
18982
19166
|
sourceType: _zod.z.enum(sourceTypeValues).describe(sourceTypeDescription),
|
|
18983
19167
|
name: _zod.z.string().describe("The name of the media item"),
|
|
18984
19168
|
mediaTypeName: _zod.z.string().describe(`Media type: '${_mcpserversdk.MEDIA_TYPE_IMAGE}', '${_mcpserversdk.MEDIA_TYPE_ARTICLE}', '${_mcpserversdk.MEDIA_TYPE_AUDIO}', '${_mcpserversdk.MEDIA_TYPE_VIDEO}', '${_mcpserversdk.MEDIA_TYPE_VECTOR_GRAPHICS}', '${_mcpserversdk.MEDIA_TYPE_FILE}', or custom media type name`),
|
|
18985
19169
|
filePath: _zod.z.string().optional().describe("Absolute path to the file (required if sourceType is 'filePath')"),
|
|
18986
|
-
fileUrl: _zod.z.string().url().optional().describe("[raw] URL to fetch the file from (required if sourceType is 'url')"),
|
|
18987
|
-
|
|
19170
|
+
fileUrl: _zod.z.string().url().optional().describe("[raw] Public, direct-download URL to fetch the file from (required if sourceType is 'url'). Must be reachable without authentication. Share/viewer links (e.g. drive.google.com/file/d/<id>/view, Dropbox ?dl=0, OneDrive view URLs) must be converted to their direct-download equivalent first \u2014 Google Drive: drive.google.com/uc?export=download&id=<id>. Uploads are streamed, so multi-MB files round-trip without timing out."),
|
|
19171
|
+
file: fileObjectSchema.optional().describe(
|
|
19172
|
+
"[raw] Host-injected file object (required if sourceType is 'file'). ChatGPT's connector populates this automatically when the user attached a file or you generated one in this chat \u2014 leave it for the host to fill, do not synthesise it yourself."
|
|
19173
|
+
),
|
|
19174
|
+
fileAsBase64: _zod.z.string().optional().describe(`Base64-encoded file data (required if sourceType is 'base64'). HARD LIMIT: decoded payload must be \u2264${base64Kib} KiB; the server rejects anything larger because LLMs reliably truncate big base64 strings or substitute thumbnail previews, both producing corrupt files. Use sourceType='url' or 'file' for everything bigger.`),
|
|
18988
19175
|
parentId: _zod.z.string().uuid().optional().describe("Parent folder ID (defaults to root)")
|
|
18989
19176
|
});
|
|
18990
19177
|
const filePathSection = buildSourceTypeSection(options.allowFilePath, [
|
|
18991
|
-
|
|
18992
|
-
|
|
19178
|
+
`url - Stream from any public direct-download URL (Drive / Dropbox / etc.). Use this for anything above ${base64Kib} KiB that isn't already attached to the chat.`,
|
|
19179
|
+
`file - Stream a host-attached file. The connector injects { download_url, file_id, mime_type, file_name } on the 'file' field automatically when the user attached a file or you generated one in this chat \u2014 prefer this over url for chat-bound files.`,
|
|
19180
|
+
`base64 - ONLY for tiny inline payloads; server hard-rejects decoded base64 over ${base64Kib} KiB to prevent LLM-truncated corrupt files.`
|
|
18993
19181
|
]);
|
|
18994
19182
|
const tool = {
|
|
18995
19183
|
name: "create-media",
|
|
18996
19184
|
description: `Upload any media file to Umbraco (images, documents, audio, video, SVG, or custom types).
|
|
18997
19185
|
|
|
19186
|
+
Pick the sourceType that matches where the file lives:
|
|
19187
|
+
- If the file is attached to this chat or you just generated it \u2192 sourceType="file" (the host fills in the file reference automatically).
|
|
19188
|
+
- If you have a public direct-download URL \u2192 sourceType="url".
|
|
19189
|
+
- For tiny inline payloads (\u2264${base64Kib} KiB decoded) \u2192 sourceType="base64".
|
|
19190
|
+
|
|
18998
19191
|
Media Types:
|
|
18999
19192
|
- ${_mcpserversdk.MEDIA_TYPE_IMAGE}: jpg, png, gif, webp, etc. (supports cropping)
|
|
19000
19193
|
- ${_mcpserversdk.MEDIA_TYPE_ARTICLE}: pdf, docx, doc (documents)
|
|
@@ -19015,16 +19208,43 @@ ${filePathSection}
|
|
|
19015
19208
|
inputSchema: schema.shape,
|
|
19016
19209
|
outputSchema: createMediaOutputSchema.shape,
|
|
19017
19210
|
slices: ["create"],
|
|
19211
|
+
_meta: { "openai/fileParams": ["file"] },
|
|
19018
19212
|
handler: (async (model) => {
|
|
19213
|
+
let effectiveSourceType;
|
|
19214
|
+
let effectiveFileUrl = model.fileUrl;
|
|
19215
|
+
if (model.sourceType === "file") {
|
|
19216
|
+
if (!_optionalChain([model, 'access', _63 => _63.file, 'optionalAccess', _64 => _64.download_url])) {
|
|
19217
|
+
return _mcpserversdk.createToolResultError.call(void 0, {
|
|
19218
|
+
detail: "Error creating media: sourceType is 'file' but no file object was provided. ChatGPT's connector should inject this automatically when a file is attached \u2014 if it didn't, the user has nothing attached or your client doesn't support openai/fileParams."
|
|
19219
|
+
});
|
|
19220
|
+
}
|
|
19221
|
+
effectiveSourceType = "url";
|
|
19222
|
+
effectiveFileUrl = model.file.download_url;
|
|
19223
|
+
} else {
|
|
19224
|
+
effectiveSourceType = model.sourceType;
|
|
19225
|
+
}
|
|
19226
|
+
if (effectiveSourceType === "url" && isStreamingAuthContextConfigured()) {
|
|
19227
|
+
if (!effectiveFileUrl) {
|
|
19228
|
+
return _mcpserversdk.createToolResultError.call(void 0, {
|
|
19229
|
+
detail: "Error creating media: fileUrl is required when sourceType is 'url'"
|
|
19230
|
+
});
|
|
19231
|
+
}
|
|
19232
|
+
return streamingUploadToToolResult({
|
|
19233
|
+
sourceUrl: effectiveFileUrl,
|
|
19234
|
+
name: model.name,
|
|
19235
|
+
mediaTypeName: model.mediaTypeName,
|
|
19236
|
+
parentId: model.parentId
|
|
19237
|
+
});
|
|
19238
|
+
}
|
|
19019
19239
|
try {
|
|
19020
19240
|
const client = UmbracoManagementClient3.getClient();
|
|
19021
19241
|
const temporaryFileId = _uuid.v4.call(void 0, );
|
|
19022
19242
|
const { name: actualName, id } = await uploadMediaFile(client, {
|
|
19023
|
-
sourceType:
|
|
19243
|
+
sourceType: effectiveSourceType,
|
|
19024
19244
|
name: model.name,
|
|
19025
19245
|
mediaTypeName: model.mediaTypeName,
|
|
19026
19246
|
filePath: model.filePath,
|
|
19027
|
-
fileUrl:
|
|
19247
|
+
fileUrl: effectiveFileUrl,
|
|
19028
19248
|
fileAsBase64: model.fileAsBase64,
|
|
19029
19249
|
parentId: model.parentId,
|
|
19030
19250
|
temporaryFileId
|
|
@@ -19068,73 +19288,125 @@ var createMediaMultipleOutputSchema = _zod.z.object({
|
|
|
19068
19288
|
error: _zod.z.string().optional()
|
|
19069
19289
|
}))
|
|
19070
19290
|
});
|
|
19291
|
+
var fileObjectSchema2 = _zod.z.object({
|
|
19292
|
+
download_url: _zod.z.string().describe("Temporary URL the host provides to fetch the file bytes"),
|
|
19293
|
+
file_id: _zod.z.string().describe("Persistent file identifier from the host"),
|
|
19294
|
+
mime_type: _zod.z.string().optional().describe("MIME type if the host knows it"),
|
|
19295
|
+
file_name: _zod.z.string().optional().describe("Original file name if the host knows it")
|
|
19296
|
+
});
|
|
19297
|
+
var UPLOAD_CONCURRENCY = 4;
|
|
19298
|
+
var MAX_BATCH_SIZE = 20;
|
|
19299
|
+
async function mapWithConcurrency(items, concurrency, producer) {
|
|
19300
|
+
const results = new Array(items.length);
|
|
19301
|
+
let nextIndex = 0;
|
|
19302
|
+
async function worker() {
|
|
19303
|
+
while (true) {
|
|
19304
|
+
const current = nextIndex++;
|
|
19305
|
+
if (current >= items.length) return;
|
|
19306
|
+
results[current] = await producer(items[current], current);
|
|
19307
|
+
}
|
|
19308
|
+
}
|
|
19309
|
+
const workers = Array.from({ length: Math.min(concurrency, items.length) }, () => worker());
|
|
19310
|
+
await Promise.all(workers);
|
|
19311
|
+
return results;
|
|
19312
|
+
}
|
|
19071
19313
|
function createCreateMediaMultipleTool(options) {
|
|
19072
|
-
const sourceTypeValues = options.allowFilePath ? ["filePath", "url"] : ["url"];
|
|
19073
|
-
const
|
|
19314
|
+
const sourceTypeValues = options.allowFilePath ? ["filePath", "url", "file"] : ["url", "file"];
|
|
19315
|
+
const filePathPrefix = options.allowFilePath ? "'filePath' for local files (most efficient, Node stdio only), " : "";
|
|
19316
|
+
const sourceTypeDescription = `Media source type: ${filePathPrefix}'url' for public direct-download URLs (streamed), 'file' for host-injected attachments \u2014 the connector populates each entry's 'file' object automatically when the user attached or generated files in this chat. Base64 is not supported for batch uploads due to token usage \u2014 use single-file create-media for tiny inline payloads.`;
|
|
19074
19317
|
const schema = _zod.z.object({
|
|
19075
19318
|
sourceType: _zod.z.enum(sourceTypeValues).describe(sourceTypeDescription),
|
|
19076
19319
|
files: _zod.z.array(_zod.z.object({
|
|
19077
19320
|
name: _zod.z.string().describe("The name of the media item"),
|
|
19078
19321
|
filePath: _zod.z.string().optional().describe("Absolute path to the file (required if sourceType is 'filePath')"),
|
|
19079
|
-
fileUrl: _zod.z.string().url().optional().describe("
|
|
19322
|
+
fileUrl: _zod.z.string().url().optional().describe("[raw] Public direct-download URL (required if sourceType is 'url'). Drive / Dropbox share links must be converted to their direct-download equivalent first \u2014 see the create-media tool description for the format. Streamed, so multi-MB files round-trip without timing out."),
|
|
19323
|
+
file: fileObjectSchema2.optional().describe("[raw] Host-injected file reference (required if sourceType is 'file'). ChatGPT's connector populates this per entry automatically when files are attached."),
|
|
19080
19324
|
mediaTypeName: _zod.z.string().optional().describe(`Optional override: '${_mcpserversdk.MEDIA_TYPE_IMAGE}', '${_mcpserversdk.MEDIA_TYPE_ARTICLE}', '${_mcpserversdk.MEDIA_TYPE_AUDIO}', '${_mcpserversdk.MEDIA_TYPE_VIDEO}', '${_mcpserversdk.MEDIA_TYPE_VECTOR_GRAPHICS}', '${_mcpserversdk.MEDIA_TYPE_FILE}', or custom media type name. If not specified, defaults to '${_mcpserversdk.MEDIA_TYPE_FILE}'`)
|
|
19081
|
-
})).describe(
|
|
19325
|
+
})).max(MAX_BATCH_SIZE).describe(`Array of files to upload (maximum ${MAX_BATCH_SIZE} files per batch)`),
|
|
19082
19326
|
parentId: _zod.z.string().uuid().optional().describe("Parent folder ID (defaults to root)")
|
|
19083
19327
|
});
|
|
19084
19328
|
const filePathSection = buildSourceTypeSection(options.allowFilePath, [
|
|
19085
|
-
"url -
|
|
19329
|
+
"url - Stream from any public direct-download URL (Drive / Dropbox / etc.).",
|
|
19330
|
+
"file - Stream a host-attached file. The connector injects { download_url, file_id, ... } per entry automatically when the user attached or generated files in this chat \u2014 prefer this over 'url' for chat-bound files."
|
|
19086
19331
|
]);
|
|
19087
19332
|
const tool = {
|
|
19088
19333
|
name: "create-media-multiple",
|
|
19089
|
-
description: `Batch upload multiple media files to Umbraco (maximum
|
|
19334
|
+
description: `Batch upload multiple media files to Umbraco (maximum ${MAX_BATCH_SIZE} files per batch).
|
|
19090
19335
|
|
|
19091
|
-
|
|
19336
|
+
Use this \u2014 not several separate create-media calls \u2014 when the user attached or generated multiple files in this chat (sourceType="file"), or has a list of public URLs to upload (sourceType="url"). ChatGPT's connector populates each entry's 'file' field automatically.
|
|
19092
19337
|
|
|
19093
19338
|
Source Types:
|
|
19094
19339
|
${filePathSection}
|
|
19095
19340
|
|
|
19096
19341
|
Note: base64 is not supported for batch uploads due to token usage.
|
|
19097
19342
|
|
|
19098
|
-
The tool processes
|
|
19099
|
-
If some files fail, others will continue processing (continue-on-error strategy).`,
|
|
19343
|
+
The tool processes up to ${UPLOAD_CONCURRENCY} uploads in parallel and returns detailed results for each file in input order. If some files fail, others continue processing (continue-on-error strategy).`,
|
|
19100
19344
|
inputSchema: schema.shape,
|
|
19101
19345
|
outputSchema: createMediaMultipleOutputSchema.shape,
|
|
19102
19346
|
slices: ["create"],
|
|
19347
|
+
_meta: { "openai/fileParams": ["files"] },
|
|
19103
19348
|
handler: (async (model) => {
|
|
19104
|
-
if (model.files.length >
|
|
19349
|
+
if (model.files.length > MAX_BATCH_SIZE) {
|
|
19105
19350
|
return _mcpserversdk.createToolResultError.call(void 0, {
|
|
19106
|
-
detail: `Batch upload limited to
|
|
19351
|
+
detail: `Batch upload limited to ${MAX_BATCH_SIZE} files per call. You provided ${model.files.length} files. Please split into multiple batches.`
|
|
19107
19352
|
});
|
|
19108
19353
|
}
|
|
19109
|
-
const results = [];
|
|
19110
19354
|
const client = UmbracoManagementClient3.getClient();
|
|
19111
|
-
|
|
19112
|
-
|
|
19113
|
-
|
|
19114
|
-
|
|
19115
|
-
|
|
19116
|
-
|
|
19117
|
-
|
|
19118
|
-
|
|
19119
|
-
|
|
19120
|
-
|
|
19121
|
-
|
|
19122
|
-
|
|
19123
|
-
|
|
19124
|
-
|
|
19125
|
-
|
|
19126
|
-
|
|
19127
|
-
|
|
19128
|
-
|
|
19129
|
-
|
|
19130
|
-
|
|
19131
|
-
|
|
19132
|
-
|
|
19133
|
-
|
|
19134
|
-
|
|
19135
|
-
|
|
19355
|
+
const streamingAvailable = isStreamingAuthContextConfigured();
|
|
19356
|
+
const results = await mapWithConcurrency(
|
|
19357
|
+
model.files,
|
|
19358
|
+
UPLOAD_CONCURRENCY,
|
|
19359
|
+
async (file) => {
|
|
19360
|
+
try {
|
|
19361
|
+
const mediaTypeName = file.mediaTypeName || _mcpserversdk.MEDIA_TYPE_FILE;
|
|
19362
|
+
let effectiveSourceType;
|
|
19363
|
+
let effectiveFileUrl = file.fileUrl;
|
|
19364
|
+
if (model.sourceType === "file") {
|
|
19365
|
+
if (!_optionalChain([file, 'access', _65 => _65.file, 'optionalAccess', _66 => _66.download_url])) {
|
|
19366
|
+
return {
|
|
19367
|
+
success: false,
|
|
19368
|
+
name: file.name,
|
|
19369
|
+
error: "sourceType is 'file' but no file object was provided for this entry. The host connector should inject this automatically when a file is attached."
|
|
19370
|
+
};
|
|
19371
|
+
}
|
|
19372
|
+
effectiveSourceType = "url";
|
|
19373
|
+
effectiveFileUrl = file.file.download_url;
|
|
19374
|
+
} else {
|
|
19375
|
+
effectiveSourceType = model.sourceType;
|
|
19376
|
+
}
|
|
19377
|
+
if (effectiveSourceType === "url" && streamingAvailable) {
|
|
19378
|
+
if (!effectiveFileUrl) {
|
|
19379
|
+
return {
|
|
19380
|
+
success: false,
|
|
19381
|
+
name: file.name,
|
|
19382
|
+
error: "fileUrl is required when sourceType is 'url'."
|
|
19383
|
+
};
|
|
19384
|
+
}
|
|
19385
|
+
const { name: actualName2, id: mediaId2 } = await streamingUploadFromUrl({
|
|
19386
|
+
sourceUrl: effectiveFileUrl,
|
|
19387
|
+
name: file.name,
|
|
19388
|
+
mediaTypeName,
|
|
19389
|
+
parentId: model.parentId
|
|
19390
|
+
});
|
|
19391
|
+
return { success: true, name: actualName2, id: mediaId2 };
|
|
19392
|
+
}
|
|
19393
|
+
const temporaryFileId = _uuid.v4.call(void 0, );
|
|
19394
|
+
const { name: actualName, id: mediaId } = await uploadMediaFile(client, {
|
|
19395
|
+
sourceType: effectiveSourceType,
|
|
19396
|
+
name: file.name,
|
|
19397
|
+
mediaTypeName,
|
|
19398
|
+
filePath: file.filePath,
|
|
19399
|
+
fileUrl: effectiveFileUrl,
|
|
19400
|
+
fileAsBase64: void 0,
|
|
19401
|
+
parentId: model.parentId,
|
|
19402
|
+
temporaryFileId
|
|
19403
|
+
});
|
|
19404
|
+
return { success: true, name: actualName, id: mediaId };
|
|
19405
|
+
} catch (error) {
|
|
19406
|
+
return { success: false, name: file.name, error: error.message };
|
|
19407
|
+
}
|
|
19136
19408
|
}
|
|
19137
|
-
|
|
19409
|
+
);
|
|
19138
19410
|
const successCount = results.filter((r) => r.success).length;
|
|
19139
19411
|
const failureCount = results.filter((r) => !r.success).length;
|
|
19140
19412
|
return _mcpserversdk.createToolResult.call(void 0, {
|
|
@@ -19189,7 +19461,7 @@ var CreateMediaFolderTool = {
|
|
|
19189
19461
|
if (response.status < 200 || response.status >= 300) {
|
|
19190
19462
|
throw new Error(`Request failed with status code ${response.status}`);
|
|
19191
19463
|
}
|
|
19192
|
-
const locationHeader = _optionalChain([response, 'access',
|
|
19464
|
+
const locationHeader = _optionalChain([response, 'access', _67 => _67.headers, 'optionalAccess', _68 => _68.location]) || _optionalChain([response, 'access', _69 => _69.headers, 'optionalAccess', _70 => _70.Location]);
|
|
19193
19465
|
if (!locationHeader) {
|
|
19194
19466
|
throw new Error("No Location header in response - cannot determine created folder ID");
|
|
19195
19467
|
}
|
|
@@ -20426,7 +20698,7 @@ var CreateMediaTypeFolderTool = {
|
|
|
20426
20698
|
validateStatus: () => true
|
|
20427
20699
|
});
|
|
20428
20700
|
if (response.status === 201) {
|
|
20429
|
-
const locationHeader = _optionalChain([response, 'access',
|
|
20701
|
+
const locationHeader = _optionalChain([response, 'access', _71 => _71.headers, 'optionalAccess', _72 => _72["location"]]) || _optionalChain([response, 'access', _73 => _73.headers, 'optionalAccess', _74 => _74["Location"]]);
|
|
20430
20702
|
let createdId = model.id || "";
|
|
20431
20703
|
if (locationHeader) {
|
|
20432
20704
|
const idMatch = locationHeader.match(/([0-9a-f-]{36})$/i);
|
|
@@ -20560,7 +20832,7 @@ var CreateMediaTypeTool = {
|
|
|
20560
20832
|
validateStatus: () => true
|
|
20561
20833
|
});
|
|
20562
20834
|
if (response.status === 201) {
|
|
20563
|
-
const locationHeader = _optionalChain([response, 'access',
|
|
20835
|
+
const locationHeader = _optionalChain([response, 'access', _75 => _75.headers, 'optionalAccess', _76 => _76["location"]]) || _optionalChain([response, 'access', _77 => _77.headers, 'optionalAccess', _78 => _78["Location"]]);
|
|
20564
20836
|
let createdId = model.id || "";
|
|
20565
20837
|
if (locationHeader) {
|
|
20566
20838
|
const idMatch = locationHeader.match(/([0-9a-f-]{36})$/i);
|
|
@@ -20611,7 +20883,7 @@ var CopyMediaTypeTool = {
|
|
|
20611
20883
|
validateStatus: () => true
|
|
20612
20884
|
});
|
|
20613
20885
|
if (response.status === 201) {
|
|
20614
|
-
const locationHeader = _optionalChain([response, 'access',
|
|
20886
|
+
const locationHeader = _optionalChain([response, 'access', _79 => _79.headers, 'optionalAccess', _80 => _80["location"]]) || _optionalChain([response, 'access', _81 => _81.headers, 'optionalAccess', _82 => _82["Location"]]);
|
|
20615
20887
|
let createdId = "";
|
|
20616
20888
|
if (locationHeader) {
|
|
20617
20889
|
const idMatch = locationHeader.match(/([0-9a-f-]{36})$/i);
|
|
@@ -20821,7 +21093,7 @@ var CreateMemberTool = {
|
|
|
20821
21093
|
validateStatus: () => true
|
|
20822
21094
|
});
|
|
20823
21095
|
if (response.status === 201) {
|
|
20824
|
-
const locationHeader = _optionalChain([response, 'access',
|
|
21096
|
+
const locationHeader = _optionalChain([response, 'access', _83 => _83.headers, 'optionalAccess', _84 => _84["location"]]) || _optionalChain([response, 'access', _85 => _85.headers, 'optionalAccess', _86 => _86["Location"]]);
|
|
20825
21097
|
let createdId = model.id || "";
|
|
20826
21098
|
if (locationHeader) {
|
|
20827
21099
|
const idMatch = locationHeader.match(/([0-9a-f-]{36})$/i);
|
|
@@ -21372,7 +21644,7 @@ var CreateMemberTypeTool = {
|
|
|
21372
21644
|
validateStatus: () => true
|
|
21373
21645
|
});
|
|
21374
21646
|
if (response.status === 201) {
|
|
21375
|
-
const locationHeader = _optionalChain([response, 'access',
|
|
21647
|
+
const locationHeader = _optionalChain([response, 'access', _87 => _87.headers, 'optionalAccess', _88 => _88["location"]]) || _optionalChain([response, 'access', _89 => _89.headers, 'optionalAccess', _90 => _90["Location"]]);
|
|
21376
21648
|
let createdId = model.id || "";
|
|
21377
21649
|
if (locationHeader) {
|
|
21378
21650
|
const idMatch = locationHeader.match(/([0-9a-f-]{36})$/i);
|
|
@@ -21542,7 +21814,7 @@ var CopyMemberTypeTool = {
|
|
|
21542
21814
|
validateStatus: () => true
|
|
21543
21815
|
});
|
|
21544
21816
|
if (response.status === 201) {
|
|
21545
|
-
const locationHeader = _optionalChain([response, 'access',
|
|
21817
|
+
const locationHeader = _optionalChain([response, 'access', _91 => _91.headers, 'optionalAccess', _92 => _92["location"]]) || _optionalChain([response, 'access', _93 => _93.headers, 'optionalAccess', _94 => _94["Location"]]);
|
|
21546
21818
|
let createdId = "";
|
|
21547
21819
|
if (locationHeader) {
|
|
21548
21820
|
const idMatch = locationHeader.match(/([0-9a-f-]{36})$/i);
|
|
@@ -21902,7 +22174,7 @@ var CreatePartialViewTool = {
|
|
|
21902
22174
|
validateStatus: () => true
|
|
21903
22175
|
});
|
|
21904
22176
|
if (response.status === 201) {
|
|
21905
|
-
const locationHeader = _optionalChain([response, 'access',
|
|
22177
|
+
const locationHeader = _optionalChain([response, 'access', _95 => _95.headers, 'optionalAccess', _96 => _96["location"]]) || _optionalChain([response, 'access', _97 => _97.headers, 'optionalAccess', _98 => _98["Location"]]);
|
|
21906
22178
|
let createdPath = "";
|
|
21907
22179
|
if (locationHeader) {
|
|
21908
22180
|
const pathMatch = locationHeader.match(/partial-view\/(.+)$/);
|
|
@@ -21949,7 +22221,7 @@ var CreatePartialViewFolderTool = {
|
|
|
21949
22221
|
validateStatus: () => true
|
|
21950
22222
|
});
|
|
21951
22223
|
if (response.status === 201) {
|
|
21952
|
-
const locationHeader = _optionalChain([response, 'access',
|
|
22224
|
+
const locationHeader = _optionalChain([response, 'access', _99 => _99.headers, 'optionalAccess', _100 => _100["location"]]) || _optionalChain([response, 'access', _101 => _101.headers, 'optionalAccess', _102 => _102["Location"]]);
|
|
21953
22225
|
let createdPath = "";
|
|
21954
22226
|
if (locationHeader) {
|
|
21955
22227
|
const pathMatch = locationHeader.match(/partial-view\/folder\/(.+)$/);
|
|
@@ -22771,7 +23043,7 @@ var CreateScriptTool = {
|
|
|
22771
23043
|
validateStatus: () => true
|
|
22772
23044
|
});
|
|
22773
23045
|
if (response.status === 201) {
|
|
22774
|
-
const locationHeader = _optionalChain([response, 'access',
|
|
23046
|
+
const locationHeader = _optionalChain([response, 'access', _103 => _103.headers, 'optionalAccess', _104 => _104["location"]]) || _optionalChain([response, 'access', _105 => _105.headers, 'optionalAccess', _106 => _106["Location"]]);
|
|
22775
23047
|
let createdPath = "";
|
|
22776
23048
|
if (locationHeader) {
|
|
22777
23049
|
const pathMatch = locationHeader.match(/script\/(.+)$/);
|
|
@@ -22818,7 +23090,7 @@ var CreateScriptFolderTool = {
|
|
|
22818
23090
|
validateStatus: () => true
|
|
22819
23091
|
});
|
|
22820
23092
|
if (response.status === 201) {
|
|
22821
|
-
const locationHeader = _optionalChain([response, 'access',
|
|
23093
|
+
const locationHeader = _optionalChain([response, 'access', _107 => _107.headers, 'optionalAccess', _108 => _108["location"]]) || _optionalChain([response, 'access', _109 => _109.headers, 'optionalAccess', _110 => _110["Location"]]);
|
|
22822
23094
|
let createdPath = "";
|
|
22823
23095
|
if (locationHeader) {
|
|
22824
23096
|
const pathMatch = locationHeader.match(/script\/folder\/(.+)$/);
|
|
@@ -23415,7 +23687,7 @@ var CreateStylesheetTool = {
|
|
|
23415
23687
|
validateStatus: () => true
|
|
23416
23688
|
});
|
|
23417
23689
|
if (response.status === 201) {
|
|
23418
|
-
const locationHeader = _optionalChain([response, 'access',
|
|
23690
|
+
const locationHeader = _optionalChain([response, 'access', _111 => _111.headers, 'optionalAccess', _112 => _112["location"]]) || _optionalChain([response, 'access', _113 => _113.headers, 'optionalAccess', _114 => _114["Location"]]);
|
|
23419
23691
|
let createdPath = "";
|
|
23420
23692
|
if (locationHeader) {
|
|
23421
23693
|
const pathMatch = locationHeader.match(/stylesheet\/(.+)$/);
|
|
@@ -23462,7 +23734,7 @@ var CreateStylesheetFolderTool = {
|
|
|
23462
23734
|
validateStatus: () => true
|
|
23463
23735
|
});
|
|
23464
23736
|
if (response.status === 201) {
|
|
23465
|
-
const locationHeader = _optionalChain([response, 'access',
|
|
23737
|
+
const locationHeader = _optionalChain([response, 'access', _115 => _115.headers, 'optionalAccess', _116 => _116["location"]]) || _optionalChain([response, 'access', _117 => _117.headers, 'optionalAccess', _118 => _118["Location"]]);
|
|
23466
23738
|
let createdPath = "";
|
|
23467
23739
|
if (locationHeader) {
|
|
23468
23740
|
const pathMatch = locationHeader.match(/stylesheet\/folder\/(.+)$/);
|
|
@@ -23826,7 +24098,7 @@ var CreateTemplateTool = {
|
|
|
23826
24098
|
validateStatus: () => true
|
|
23827
24099
|
});
|
|
23828
24100
|
if (response.status === 201) {
|
|
23829
|
-
const locationHeader = _optionalChain([response, 'access',
|
|
24101
|
+
const locationHeader = _optionalChain([response, 'access', _119 => _119.headers, 'optionalAccess', _120 => _120["location"]]) || _optionalChain([response, 'access', _121 => _121.headers, 'optionalAccess', _122 => _122["Location"]]);
|
|
23830
24102
|
let createdId = "";
|
|
23831
24103
|
if (locationHeader) {
|
|
23832
24104
|
const idMatch = locationHeader.match(/template\/([a-f0-9-]+)$/i);
|
|
@@ -24736,7 +25008,7 @@ var CreateUserDataTool = {
|
|
|
24736
25008
|
validateStatus: () => true
|
|
24737
25009
|
});
|
|
24738
25010
|
if (response.status === 201) {
|
|
24739
|
-
const locationHeader = _optionalChain([response, 'access',
|
|
25011
|
+
const locationHeader = _optionalChain([response, 'access', _123 => _123.headers, 'optionalAccess', _124 => _124["location"]]) || _optionalChain([response, 'access', _125 => _125.headers, 'optionalAccess', _126 => _126["Location"]]);
|
|
24740
25012
|
let createdId = "";
|
|
24741
25013
|
if (locationHeader) {
|
|
24742
25014
|
const idMatch = locationHeader.match(/user-data\/([a-f0-9-]+)$/i);
|
|
@@ -24974,7 +25246,7 @@ var CreateUserGroupTool = {
|
|
|
24974
25246
|
validateStatus: () => true
|
|
24975
25247
|
});
|
|
24976
25248
|
if (response.status === 201) {
|
|
24977
|
-
const locationHeader = _optionalChain([response, 'access',
|
|
25249
|
+
const locationHeader = _optionalChain([response, 'access', _127 => _127.headers, 'optionalAccess', _128 => _128["location"]]) || _optionalChain([response, 'access', _129 => _129.headers, 'optionalAccess', _130 => _130["Location"]]);
|
|
24978
25250
|
let createdId = "";
|
|
24979
25251
|
if (locationHeader) {
|
|
24980
25252
|
const idMatch = locationHeader.match(/user-group\/([a-f0-9-]+)$/i);
|
|
@@ -25272,7 +25544,7 @@ var CreateWebhookTool = {
|
|
|
25272
25544
|
validateStatus: () => true
|
|
25273
25545
|
});
|
|
25274
25546
|
if (response.status === 201) {
|
|
25275
|
-
const locationHeader = _optionalChain([response, 'access',
|
|
25547
|
+
const locationHeader = _optionalChain([response, 'access', _131 => _131.headers, 'optionalAccess', _132 => _132["location"]]) || _optionalChain([response, 'access', _133 => _133.headers, 'optionalAccess', _134 => _134["Location"]]);
|
|
25276
25548
|
let createdId = "";
|
|
25277
25549
|
if (locationHeader) {
|
|
25278
25550
|
const idMatch = locationHeader.match(/webhook\/([a-f0-9-]+)$/i);
|
|
@@ -25508,4 +25780,4 @@ var allSliceNames = [...toolSliceNames, "other"];
|
|
|
25508
25780
|
|
|
25509
25781
|
|
|
25510
25782
|
exports.__commonJS = __commonJS; exports.__toESM = __toESM; exports.UmbracoManagementClient = UmbracoManagementClient3; exports.setAllowFilePathUploads = setAllowFilePathUploads; exports.setUmbracoVersion = setUmbracoVersion; exports.availableCollections = availableCollections; exports.allModes = allModes; exports.allModeNames = allModeNames; exports.allSliceNames = allSliceNames;
|
|
25511
|
-
//# sourceMappingURL=chunk-
|
|
25783
|
+
//# sourceMappingURL=chunk-Q4LCXM42.cjs.map
|