@nextblock-cms/cortex 0.20.3 → 0.21.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/client.cjs.js +1 -1
- package/client.es.js +3 -7
- package/index.cjs.js +1 -1
- package/index.es.js +24 -277
- package/lib/ai-block-generation.cjs.js +3 -4
- package/lib/ai-block-generation.es.js +143 -182
- package/lib/ai-client.cjs.js +1 -1
- package/lib/ai-client.d.ts +1 -1
- package/lib/ai-client.es.js +101 -135
- package/lib/ai-config.cjs.js +1 -1
- package/lib/ai-config.es.js +89 -108
- package/lib/ai-cortex-widget-builder.cjs.js +1 -1
- package/lib/ai-cortex-widget-builder.es.js +56 -70
- package/lib/ai-global-agent-content-ops-tools.cjs.js +1 -1
- package/lib/ai-global-agent-content-ops-tools.d.ts +1943 -68
- package/lib/ai-global-agent-content-ops-tools.es.js +185 -199
- package/lib/ai-global-agent-custom-block-tools.cjs.js +1 -1
- package/lib/ai-global-agent-custom-block-tools.d.ts +2160 -95
- package/lib/ai-global-agent-custom-block-tools.es.js +226 -223
- package/lib/ai-global-agent-db-tools.cjs.js +1 -1
- package/lib/ai-global-agent-db-tools.d.ts +2708 -98
- package/lib/ai-global-agent-db-tools.es.js +1013 -986
- package/lib/ai-global-agent-ecommerce.cjs.js +1 -1
- package/lib/ai-global-agent-ecommerce.es.js +3 -7
- package/lib/ai-global-agent-site-tools.cjs.js +2 -3
- package/lib/ai-global-agent-site-tools.d.ts +10695 -500
- package/lib/ai-global-agent-site-tools.es.js +750 -757
- package/lib/ai-global-agent-theming-tools.cjs.js +1 -3
- package/lib/ai-global-agent-theming-tools.d.ts +2905 -105
- package/lib/ai-global-agent-theming-tools.es.js +326 -396
- package/lib/ai-global-agent-tools.cjs.js +2 -2
- package/lib/ai-global-agent-tools.d.ts +4 -2230
- package/lib/ai-global-agent-tools.es.js +3899 -4328
- package/lib/ai-key-crypto.cjs.js +1 -1
- package/lib/ai-key-crypto.es.js +63 -82
- package/lib/ai-key-verification.cjs.js +1 -1
- package/lib/ai-key-verification.es.js +74 -63
- package/lib/ai-model-catalog.cjs.js +1 -1
- package/lib/ai-model-catalog.es.js +18 -22
- package/lib/ai-model-registry.cjs.js +2 -2
- package/lib/ai-model-registry.es.js +246 -309
- package/lib/ai-seo-metadata.cjs.js +2 -3
- package/lib/ai-seo-metadata.es.js +143 -185
- package/lib/ai-vision.cjs.js +2 -2
- package/lib/ai-vision.d.ts +6 -6
- package/lib/ai-vision.es.js +161 -215
- package/lib/block-content-schemas.cjs.js +1 -1
- package/lib/block-content-schemas.es.js +324 -254
- package/lib/cortex-widget-registry.cjs.js +1 -1
- package/lib/cortex-widget-registry.es.js +35 -43
- package/lib/cortex-widget-schema.cjs.js +2 -3
- package/lib/cortex-widget-schema.es.js +280 -309
- package/lib/editor-document-from-html.cjs.js +1 -1
- package/lib/editor-document-from-html.es.js +334 -278
- package/lib/fetch-host-guard.cjs.js +1 -0
- package/lib/fetch-host-guard.d.ts +2 -0
- package/lib/fetch-host-guard.es.js +30 -0
- package/lib/mcp-server.cjs.js +1 -1
- package/lib/mcp-server.es.js +155 -173
- package/lib/mcp-tokens.cjs.js +1 -1
- package/lib/mcp-tokens.es.js +95 -107
- package/lib/mcp-tool-registry.cjs.js +5 -6
- package/lib/mcp-tool-registry.es.js +533 -411
- package/lib/site-brief.cjs.js +2 -2
- package/lib/site-brief.es.js +102 -108
- package/lib/vision-image-download.cjs.js +1 -0
- package/lib/vision-image-download.d.ts +43 -0
- package/lib/vision-image-download.es.js +120 -0
- package/lib/zod-config.cjs.js +1 -1
- package/lib/zod-config.es.js +5 -6
- package/package.json +8 -8
package/lib/ai-vision.es.js
CHANGED
|
@@ -1,227 +1,173 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
1
|
+
import { getHttpStatusCode as e, isOpenRouterRecoverableRoutingError as t, omitUnsupportedCortexAiModelOptions as n, runWithCortexAiModelFallback as r } from "./ai-model-registry.es.js";
|
|
2
|
+
import { truncateOnWordBoundary as i } from "./ai-seo-metadata.es.js";
|
|
3
|
+
import { generateText as a } from "ai";
|
|
4
|
+
//#region libs/cortex/src/lib/ai-vision.ts
|
|
5
|
+
var o = "Cortex AI vision generation can only be imported from server-side code.";
|
|
6
|
+
function s() {
|
|
7
|
+
if (typeof window < "u") throw Error(o);
|
|
8
8
|
}
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
],
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
]), v = /^(?:here(?:'s|’s| is)\s+)?(?:the\s+)?alt(?:[-\s]?text)?\s*[:–—-]\s*/i, N = /^(?:this\s+is\s+)?(?:an?|the)?\s*(?:image|photo|photograph|picture|pic|graphic|illustration|rendering|render)\s+(?:of|showing|depicting|that\s+shows)\s+/i;
|
|
51
|
-
function U(e) {
|
|
52
|
-
const o = /* @__PURE__ */ new Set(), t = [];
|
|
53
|
-
for (const n of e) {
|
|
54
|
-
const r = n?.trim();
|
|
55
|
-
!r || o.has(r) || (o.add(r), t.push(r));
|
|
56
|
-
}
|
|
57
|
-
return t;
|
|
9
|
+
var c = [
|
|
10
|
+
"google/gemma-4-31b-it:free",
|
|
11
|
+
"google/gemma-4-26b-a4b-it:free",
|
|
12
|
+
"google/gemini-2.5-flash-lite",
|
|
13
|
+
"qwen/qwen3-vl-32b-instruct",
|
|
14
|
+
"openai/gpt-4o-mini",
|
|
15
|
+
"google/gemini-2.5-flash"
|
|
16
|
+
], l = [
|
|
17
|
+
/(?:^|\/)[^/]*-vl(?:[-:]|$)/i,
|
|
18
|
+
/vision/i,
|
|
19
|
+
/(?:^|\/)gemini-/i,
|
|
20
|
+
/(?:^|\/)gemma-[3-9]/i,
|
|
21
|
+
/(?:^|\/)gpt-(?:4o|4\.1|5)/i,
|
|
22
|
+
/(?:^|\/)claude-/i,
|
|
23
|
+
/(?:^|\/)llama-4/i,
|
|
24
|
+
/(?:^|\/)pixtral/i,
|
|
25
|
+
/(?:^|\/)mistral-(?:small|medium|large)-3/i,
|
|
26
|
+
/(?:^|\/)nova-(?:lite|pro|premier)/i
|
|
27
|
+
], u = 125, d = {
|
|
28
|
+
max: 1e3,
|
|
29
|
+
min: 20
|
|
30
|
+
}, f = 6e4, p = /* @__PURE__ */ new Set([
|
|
31
|
+
"\"",
|
|
32
|
+
"'",
|
|
33
|
+
"«",
|
|
34
|
+
"»",
|
|
35
|
+
"‘",
|
|
36
|
+
"’",
|
|
37
|
+
"‚",
|
|
38
|
+
"“",
|
|
39
|
+
"”",
|
|
40
|
+
"„",
|
|
41
|
+
"`"
|
|
42
|
+
]), m = /^(?:here(?:'s|’s| is)\s+)?(?:the\s+)?alt(?:[-\s]?text)?\s*[:–—-]\s*/i, h = /^(?:this\s+is\s+)?(?:an?|the)?\s*(?:image|photo|photograph|picture|pic|graphic|illustration|rendering|render)\s+(?:of|showing|depicting|that\s+shows)\s+/i;
|
|
43
|
+
function g(e) {
|
|
44
|
+
let t = /* @__PURE__ */ new Set(), n = [];
|
|
45
|
+
for (let r of e) {
|
|
46
|
+
let e = r?.trim();
|
|
47
|
+
e && !t.has(e) && (t.add(e), n.push(e));
|
|
48
|
+
}
|
|
49
|
+
return n;
|
|
58
50
|
}
|
|
59
|
-
function
|
|
60
|
-
|
|
61
|
-
|
|
51
|
+
function _(e) {
|
|
52
|
+
let t = e?.trim();
|
|
53
|
+
return t ? c.includes(t) ? !0 : l.some((e) => e.test(t)) : !1;
|
|
62
54
|
}
|
|
63
|
-
function
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
])
|
|
71
|
-
};
|
|
55
|
+
function v(e) {
|
|
56
|
+
let t = e.requestedModelId?.trim() || null, n = e.selectedModel?.modelId?.trim() || null;
|
|
57
|
+
return { modelIds: g([
|
|
58
|
+
t,
|
|
59
|
+
e.credentialSource !== "env" && n && _(n) ? n : null,
|
|
60
|
+
...c
|
|
61
|
+
]) };
|
|
72
62
|
}
|
|
73
|
-
function
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
return o;
|
|
63
|
+
function y(e) {
|
|
64
|
+
let t = e.trim();
|
|
65
|
+
for (; t.length >= 2 && p.has(t[0]) && p.has(t[t.length - 1]);) t = t.slice(1, -1).trim();
|
|
66
|
+
return t;
|
|
78
67
|
}
|
|
79
|
-
function
|
|
80
|
-
|
|
68
|
+
function b(e) {
|
|
69
|
+
return !e.endsWith(".") || e.endsWith("...") || e.endsWith("…") ? e : (e.match(/[.!?](?=\s|$)/g) || []).length === 1 ? e.slice(0, -1).trimEnd() : e;
|
|
81
70
|
}
|
|
82
|
-
function
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
71
|
+
function x(e, t = 125) {
|
|
72
|
+
let n = e.replace(/\s+/g, " ").trim(), r = !1;
|
|
73
|
+
for (let e = 0; e < 2; e++) {
|
|
74
|
+
n = y(n);
|
|
75
|
+
let e = n.replace(m, "");
|
|
76
|
+
e !== n && (n = e.trim(), r = !0), n = y(n);
|
|
77
|
+
let t = n.replace(h, "");
|
|
78
|
+
t !== n && (n = t.trim(), r = !0);
|
|
79
|
+
}
|
|
80
|
+
return r && n && (n = n.charAt(0).toUpperCase() + n.slice(1)), i(b(n), t);
|
|
92
81
|
}
|
|
93
|
-
function
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
}
|
|
105
|
-
if (t.protocol !== "http:" && t.protocol !== "https:")
|
|
106
|
-
throw new Error(
|
|
107
|
-
`Cortex AI alt text generation requires an http(s) image URL, received the "${t.protocol}" scheme.`
|
|
108
|
-
);
|
|
109
|
-
return t;
|
|
82
|
+
function S(e) {
|
|
83
|
+
let t = e.trim();
|
|
84
|
+
if (!t) throw Error("Cortex AI alt text generation requires an image URL.");
|
|
85
|
+
let n;
|
|
86
|
+
try {
|
|
87
|
+
n = new URL(t);
|
|
88
|
+
} catch {
|
|
89
|
+
throw Error(`Cortex AI alt text generation requires an absolute http(s) image URL, received "${t}". A storage key or site-relative path must be resolved to a publicly fetchable URL first, because the model provider downloads the image server-side.`);
|
|
90
|
+
}
|
|
91
|
+
if (n.protocol !== "http:" && n.protocol !== "https:") throw Error(`Cortex AI alt text generation requires an http(s) image URL, received the "${n.protocol}" scheme.`);
|
|
92
|
+
return n;
|
|
110
93
|
}
|
|
111
|
-
function
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
94
|
+
function C(e) {
|
|
95
|
+
return [
|
|
96
|
+
"You are NextBlock Cortex AI, writing the alt attribute for an image on a website.",
|
|
97
|
+
"You are writing for a person using a screen reader who cannot see the image at all.",
|
|
98
|
+
"Describe only what is visibly present in the image: subjects, their appearance, what they are doing, the setting, and any text that appears in the image.",
|
|
99
|
+
"Never state or guess anything you cannot see — no names, no locations, no dates, no brands, no emotions, and no backstory unless they are legible in the image itself.",
|
|
100
|
+
`Write one short factual description of at most ${e} characters.`,
|
|
101
|
+
"Do not begin with \"image of\", \"photo of\", \"picture of\", \"graphic of\", or any similar phrase; the screen reader already announces that this is an image.",
|
|
102
|
+
"Do not add a label such as \"Alt text:\" and do not wrap the description in quotation marks.",
|
|
103
|
+
"Do not keyword-stuff, do not list search terms, and do not repeat a word for emphasis.",
|
|
104
|
+
"Return plain text only: one line, no markdown, no HTML, no JSON, no commentary, no alternatives to choose between.",
|
|
105
|
+
"If surrounding page context is supplied, use it ONLY to disambiguate what you can already see — for example to choose the right word for an object or to know which product is pictured. Never use it to add detail that is not visible in the image."
|
|
106
|
+
].join(" ");
|
|
124
107
|
}
|
|
125
|
-
function
|
|
126
|
-
|
|
127
|
-
`Write the alt attribute for this image, at most ${e.maxLength} characters.`,
|
|
128
|
-
e.context ? `Surrounding page context, for disambiguation only: ${e.context}` : null
|
|
129
|
-
].filter(Boolean).join(`
|
|
130
|
-
|
|
131
|
-
`);
|
|
108
|
+
function w(e) {
|
|
109
|
+
return [`Write the alt attribute for this image, at most ${e.maxLength} characters.`, e.context ? `Surrounding page context, for disambiguation only: ${e.context}` : null].filter(Boolean).join("\n\n");
|
|
132
110
|
}
|
|
133
|
-
function
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
const t = e instanceof Error ? e.message : String(e);
|
|
140
|
-
return /NoContentGenerated|No content generated|Provider returned error|empty alt text|image|modality|multimodal|not support|unsupported|aborted|abort|timeout|timed out/i.test(
|
|
141
|
-
t
|
|
142
|
-
);
|
|
111
|
+
function T(n) {
|
|
112
|
+
let r = e(n);
|
|
113
|
+
if (r === 401 || r === 402 || r === 403) return !1;
|
|
114
|
+
if (t(n) || r && r >= 500) return !0;
|
|
115
|
+
let i = n instanceof Error ? n.message : String(n);
|
|
116
|
+
return /NoContentGenerated|No content generated|Provider returned error|empty alt text|image|modality|multimodal|not support|unsupported|aborted|abort|timeout|timed out/i.test(i);
|
|
143
117
|
}
|
|
144
|
-
async function
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
{
|
|
198
|
-
modelId: c,
|
|
199
|
-
modelSelection: i.modelSelection
|
|
200
|
-
}
|
|
201
|
-
), E = await _({
|
|
202
|
-
...A,
|
|
203
|
-
model: i.model(c)
|
|
204
|
-
}), u = D(E.text, n);
|
|
205
|
-
if (!u)
|
|
206
|
-
throw new Error("Cortex AI returned empty alt text.");
|
|
207
|
-
return u;
|
|
208
|
-
} finally {
|
|
209
|
-
clearTimeout(x), e.abortSignal?.removeEventListener("abort", d);
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
});
|
|
213
|
-
return {
|
|
214
|
-
altText: l.result,
|
|
215
|
-
attempts: l.attempts.length,
|
|
216
|
-
credentialSource: i.credentialSource,
|
|
217
|
-
modelId: l.modelId
|
|
218
|
-
};
|
|
118
|
+
async function E(e) {
|
|
119
|
+
s();
|
|
120
|
+
let t = S(e.imageUrl), i = Number.isFinite(e.maxLength) ? Math.round(e.maxLength) : 125, o = Math.min(d.max, Math.max(d.min, i)), c = e.context?.replace(/\s+/g, " ").trim() || null, { createCortexAiOpenRouterClient: l } = await import("./ai-client.es.js"), u = await l({ apiKey: e.apiKey || void 0 }), p = v({
|
|
121
|
+
credentialSource: u.credentialSource,
|
|
122
|
+
requestedModelId: e.modelId,
|
|
123
|
+
selectedModel: u.modelSelection
|
|
124
|
+
}), { downloadCortexVisionImage: m } = await import("./vision-image-download.es.js"), h = await m(t, { abortSignal: e.abortSignal }), g = [{
|
|
125
|
+
content: [{
|
|
126
|
+
text: w({
|
|
127
|
+
context: c,
|
|
128
|
+
maxLength: o
|
|
129
|
+
}),
|
|
130
|
+
type: "text"
|
|
131
|
+
}, {
|
|
132
|
+
data: h.data,
|
|
133
|
+
mediaType: h.mediaType,
|
|
134
|
+
type: "file"
|
|
135
|
+
}],
|
|
136
|
+
role: "user"
|
|
137
|
+
}], _ = await r({
|
|
138
|
+
modelIds: p.modelIds,
|
|
139
|
+
shouldRetry: T,
|
|
140
|
+
execute: async (t) => {
|
|
141
|
+
let r = new AbortController(), i = setTimeout(() => r.abort(), f), s = () => r.abort();
|
|
142
|
+
e.abortSignal?.addEventListener("abort", s, { once: !0 }), e.abortSignal?.aborted && r.abort();
|
|
143
|
+
try {
|
|
144
|
+
let e = n({
|
|
145
|
+
abortSignal: r.signal,
|
|
146
|
+
maxOutputTokens: 400,
|
|
147
|
+
maxRetries: 0,
|
|
148
|
+
messages: g,
|
|
149
|
+
instructions: C(o),
|
|
150
|
+
temperature: .2
|
|
151
|
+
}, {
|
|
152
|
+
modelId: t,
|
|
153
|
+
modelSelection: u.modelSelection
|
|
154
|
+
}), i = x((await a({
|
|
155
|
+
...e,
|
|
156
|
+
model: u.model(t)
|
|
157
|
+
})).text, o);
|
|
158
|
+
if (!i) throw Error("Cortex AI returned empty alt text.");
|
|
159
|
+
return i;
|
|
160
|
+
} finally {
|
|
161
|
+
clearTimeout(i), e.abortSignal?.removeEventListener("abort", s);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
});
|
|
165
|
+
return {
|
|
166
|
+
altText: _.result,
|
|
167
|
+
attempts: _.attempts.length,
|
|
168
|
+
credentialSource: u.credentialSource,
|
|
169
|
+
modelId: _.modelId
|
|
170
|
+
};
|
|
219
171
|
}
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
p as CORTEX_AI_VISION_MODEL_FALLBACK_REGISTRY,
|
|
223
|
-
P as buildCortexAiVisionRoutingPolicy,
|
|
224
|
-
H as generateCortexAiAltText,
|
|
225
|
-
X as isKnownVisionCapableCortexAiModelId,
|
|
226
|
-
D as normalizeGeneratedAltText
|
|
227
|
-
};
|
|
172
|
+
//#endregion
|
|
173
|
+
export { u as CORTEX_AI_DEFAULT_ALT_TEXT_MAX_LENGTH, c as CORTEX_AI_VISION_MODEL_FALLBACK_REGISTRY, v as buildCortexAiVisionRoutingPolicy, E as generateCortexAiAltText, _ as isKnownVisionCapableCortexAiModelId, x as normalizeGeneratedAltText };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
require("./zod-config.cjs.js");let e=require("zod");var t=[`text`,`heading`,`image`,`button`,`posts_grid`,`video_embed`,`section`,`form`,`testimonial`,`product_grid`,`featured_product`,`cart`,`checkout`,`product_details`],n=e.z.enum(t),r=e.z.object({direction:e.z.string().optional(),stops:e.z.array(e.z.object({color:e.z.string(),position:e.z.number()})),type:e.z.enum([`linear`,`radial`])}),i=e.z.object({gradient:r.optional(),image:e.z.object({alt_text:e.z.string().optional(),blur_data_url:e.z.string().optional(),external_url:e.z.string().optional(),height:e.z.number().optional(),media_id:e.z.string().optional(),object_key:e.z.string().optional(),overlay:e.z.object({gradient:r,type:e.z.literal(`gradient`)}).optional(),position:e.z.enum([`center`,`top`,`bottom`,`left`,`right`]),quality:e.z.number().nullable().optional(),size:e.z.enum([`cover`,`contain`]),width:e.z.number().optional()}).optional(),min_height:e.z.string().optional(),solid_color:e.z.string().optional(),theme:e.z.enum([`primary`,`secondary`,`muted`,`accent`,`destructive`]).optional(),type:e.z.enum([`none`,`theme`,`solid`,`gradient`,`image`])}),a=e.z.string().regex(/^[a-z][a-z0-9-]*$/),o=e.z.object({block_type:e.z.union([n,a]),content:e.z.record(e.z.string(),e.z.any()),temp_id:e.z.string().optional()}),s=e.z.object({background:i,column_blocks:e.z.array(e.z.array(o))}),c=e.z.object({autoplay:e.z.boolean().optional(),background:i,column_blocks:e.z.array(e.z.array(o)),column_gap:e.z.enum([`none`,`sm`,`md`,`lg`,`xl`]),container_type:e.z.enum([`full-width`,`container`,`container-sm`,`container-lg`,`container-xl`]),is_hero:e.z.boolean().optional(),padding:e.z.object({bottom:e.z.enum([`none`,`sm`,`md`,`lg`,`xl`]),top:e.z.enum([`none`,`sm`,`md`,`lg`,`xl`])}),responsive_columns:e.z.object({desktop:e.z.union([e.z.literal(1),e.z.literal(2),e.z.literal(3),e.z.literal(4)]),mobile:e.z.union([e.z.literal(1),e.z.literal(2)]),tablet:e.z.union([e.z.literal(1),e.z.literal(2),e.z.literal(3)])}),slider:e.z.boolean().optional(),slides:e.z.array(s).optional(),timeframe:e.z.number().optional(),vertical_alignment:e.z.enum([`start`,`center`,`end`,`stretch`]).optional()}),l={button:e.z.object({position:e.z.enum([`left`,`center`,`right`]).optional(),size:e.z.enum([`default`,`sm`,`lg`,`full`]).optional(),text:e.z.string(),url:e.z.string(),variant:e.z.enum([`default`,`outline`,`secondary`,`ghost`,`link`]).optional()}),cart:e.z.object({}),checkout:e.z.object({}),featured_product:e.z.object({imagePosition:e.z.enum([`left`,`right`]).default(`left`),productId:e.z.string().min(1),showBackground:e.z.boolean().default(!1)}),form:e.z.object({fields:e.z.array(e.z.object({field_type:e.z.enum([`text`,`email`,`tel`,`url`,`number`,`textarea`,`select`,`radio`,`checkbox`]),is_required:e.z.boolean(),label:e.z.string(),options:e.z.array(e.z.object({label:e.z.string(),value:e.z.string()})).optional(),placeholder:e.z.string().optional(),temp_id:e.z.string()})),form_key:e.z.string().optional(),recipient_email:e.z.string().email().optional(),submit_button_text:e.z.string(),success_message:e.z.string()}),heading:e.z.object({level:e.z.union([e.z.literal(1),e.z.literal(2),e.z.literal(3),e.z.literal(4),e.z.literal(5),e.z.literal(6)]),textAlign:e.z.enum([`left`,`center`,`right`,`justify`]).optional(),textColor:e.z.union([e.z.enum([`foreground`,`primary`,`secondary`,`accent`,`muted`,`destructive`,`background`]),e.z.string().regex(/^(#(?:[0-9a-f]{3,4}|[0-9a-f]{6}|[0-9a-f]{8})|rgba?\([^)]+\)|hsla?\([^)]+\))$/i,`Must be a hex, rgb(a) or hsl(a) colour`)]).optional().describe(`Prefer a theme token so the heading adapts to dark mode; use a CSS colour only when the brand requires an exact value`),text_content:e.z.string()}),image:e.z.object({alt_text:e.z.string().optional(),caption:e.z.string().optional(),external_url:e.z.string().nullable().optional(),height:e.z.number().nullable().optional(),media_id:e.z.string().nullable().optional(),object_key:e.z.string().nullable().optional(),width:e.z.number().nullable().optional()}),posts_grid:e.z.object({columns:e.z.number().min(1).max(6),postsPerPage:e.z.number().min(1).max(50),showPagination:e.z.boolean(),title:e.z.string().optional()}),product_details:e.z.object({}),product_grid:e.z.object({categoryId:e.z.string().optional(),categoryIds:e.z.array(e.z.string()).max(20).optional(),limit:e.z.number().min(0).max(48).default(6),productIds:e.z.array(e.z.string()).max(24).optional(),showPagination:e.z.boolean().default(!1),title:e.z.string().optional(),type:e.z.enum([`latest`,`category`,`manual`]).default(`latest`)}),section:c,testimonial:e.z.object({author_name:e.z.string().min(1),author_title:e.z.string().optional(),image_url:e.z.string().url().optional().or(e.z.literal(``)),quote:e.z.string().min(1)}),text:e.z.object({html_content:e.z.string()}),video_embed:e.z.object({autoplay:e.z.boolean().optional(),controls:e.z.boolean().optional(),title:e.z.string().optional(),url:e.z.string()})};function u(e){return t.includes(e)}function d(e){return typeof e?.validateBlockContent==`function`?e.validateBlockContent:null}function f(e,t,n){let r=d(n);if(r)return r(e,t);let i=l[e].safeParse(t);return i.success?{errors:[],isValid:!0,warnings:[]}:{errors:i.error.issues.map(e=>{let t=e.path.join(`.`);return t?`${t}: ${e.message}`:e.message}),isValid:!1,warnings:[]}}function p(e){return Array.isArray(e.fields)?e.fields.filter(e=>!!e&&typeof e==`object`&&typeof e.key==`string`&&typeof e.type==`string`):[]}function m(e){return e==null||typeof e==`string`&&e.trim()===``||Array.isArray(e)&&e.length===0}function h(e,t){if(!t||typeof t!=`object`||Array.isArray(t))return{errors:[`content must be a JSON object of { field_key: value } pairs.`],isValid:!1,warnings:[]};let n=p(e),r=new Set(n.map(e=>e.key)),i=[],a=[];for(let n of Object.keys(t))r.has(n)||i.push(`Unknown field "${n}" for custom block "${e.slug}". Known fields: ${[...r].join(`, `)||`(none)`}.`);for(let e of n){let n=t[e.key];if(m(n)){e.required&&i.push(`Field "${e.key}" is required.`);continue}if(e.type===`text`||e.type===`rich-text`){if(typeof n!=`string`){i.push(`Field "${e.key}" must be a string${e.type===`rich-text`?` of HTML`:``}.`);continue}typeof e.max_length==`number`&&n.length>e.max_length&&i.push(`Field "${e.key}" exceeds its ${e.max_length}-character limit.`),typeof e.min_length==`number`&&n.length<e.min_length&&i.push(`Field "${e.key}" is shorter than its ${e.min_length}-character minimum.`);continue}if(e.type===`image_r2`){let t=n;(typeof n!=`object`||Array.isArray(n)||typeof t.object_key!=`string`||typeof t.url!=`string`)&&i.push(`Field "${e.key}" must be an uploaded image object with object_key and url (upload it with upload_media first) or null.`);continue}if(e.type===`db_relation`){let t=e=>typeof e==`string`||typeof e==`number`;e.multiple?(!Array.isArray(n)||!n.every(t))&&i.push(`Field "${e.key}" must be an array of related record ids.`):t(n)||i.push(`Field "${e.key}" must be a single related record id.`);continue}a.push(`Field "${e.key}" has an unrecognised type "${String(e.type)}"; it was not validated.`)}return{errors:i,isValid:i.length===0,warnings:a}}async function g(e){let{data:t,error:n}=await e.from(`custom_block_definitions`).select(`slug, name, fields`);if(n)throw Error(`Could not read the custom block definitions: ${typeof n==`object`&&n&&`message`in n?String(n.message):String(n)}`);return(Array.isArray(t)?t:[]).filter(e=>!!e&&typeof e.slug==`string`)}exports.availableCortexAiBlockTypes=t,exports.cortexAiBlockTypeSchema=n,exports.customBlockSlugPatternSchema=a,exports.fallbackBlockSchemas=l,exports.isValidBlockType=u,exports.loadCustomBlockDefinitions=g,exports.readCustomBlockFields=p,exports.sectionBlockFallbackSchema=c,exports.validateCortexBlockContent=f,exports.validateCustomBlockInstanceContent=h;
|