@nextblock-cms/cortex 0.12.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/client.cjs.js +1 -0
- package/client.d.ts +1 -0
- package/client.es.js +4 -0
- package/index.cjs.js +1 -0
- package/index.d.ts +13 -0
- package/index.es.js +135 -0
- package/lib/ai-block-generation.cjs.js +5 -0
- package/lib/ai-block-generation.d.ts +21 -0
- package/lib/ai-block-generation.es.js +195 -0
- package/lib/ai-client.cjs.js +1 -0
- package/lib/ai-client.d.ts +48 -0
- package/lib/ai-client.es.js +141 -0
- package/lib/ai-config.cjs.js +1 -0
- package/lib/ai-config.d.ts +31 -0
- package/lib/ai-config.es.js +72 -0
- package/lib/ai-cortex-widget-builder.cjs.js +1 -0
- package/lib/ai-cortex-widget-builder.d.ts +14 -0
- package/lib/ai-cortex-widget-builder.es.js +72 -0
- package/lib/ai-global-agent-custom-block-tools.cjs.js +1 -0
- package/lib/ai-global-agent-custom-block-tools.d.ts +208 -0
- package/lib/ai-global-agent-custom-block-tools.es.js +220 -0
- package/lib/ai-global-agent-db-tools.cjs.js +1 -0
- package/lib/ai-global-agent-db-tools.d.ts +280 -0
- package/lib/ai-global-agent-db-tools.es.js +879 -0
- package/lib/ai-global-agent-ecommerce.cjs.js +1 -0
- package/lib/ai-global-agent-ecommerce.d.ts +2 -0
- package/lib/ai-global-agent-ecommerce.es.js +7 -0
- package/lib/ai-global-agent-tools.cjs.js +15 -0
- package/lib/ai-global-agent-tools.d.ts +3109 -0
- package/lib/ai-global-agent-tools.es.js +2812 -0
- package/lib/ai-key-crypto.cjs.js +1 -0
- package/lib/ai-key-crypto.d.ts +32 -0
- package/lib/ai-key-crypto.es.js +88 -0
- package/lib/ai-model-catalog.cjs.js +1 -0
- package/lib/ai-model-catalog.d.ts +7 -0
- package/lib/ai-model-catalog.es.js +25 -0
- package/lib/ai-model-registry.cjs.js +3 -0
- package/lib/ai-model-registry.d.ts +79 -0
- package/lib/ai-model-registry.es.js +279 -0
- package/lib/cortex-widget-registry.cjs.js +1 -0
- package/lib/cortex-widget-registry.d.ts +19 -0
- package/lib/cortex-widget-registry.es.js +47 -0
- package/lib/cortex-widget-schema.cjs.js +5 -0
- package/lib/cortex-widget-schema.d.ts +224 -0
- package/lib/cortex-widget-schema.es.js +316 -0
- package/lib/zod-config.cjs.js +1 -0
- package/lib/zod-config.d.ts +2 -0
- package/lib/zod-config.es.js +6 -0
- package/package.json +39 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const o=require("crypto"),n="aes-256-gcm",u=1;function c(t){const e=t.trim();if(!e)throw new Error("CORTEX_AI_ENCRYPTION_KEY is required to manage stored OpenRouter keys.");return o.createHash("sha256").update(e).digest()}function p(t){if(!t||typeof t!="object")throw new Error("Invalid encrypted OpenRouter key payload.");const e=t;if(e.algorithm!==n||e.version!==u||typeof e.authTag!="string"||typeof e.ciphertext!="string"||typeof e.iv!="string")throw new Error("Invalid encrypted OpenRouter key payload.");return{algorithm:e.algorithm,authTag:e.authTag,ciphertext:e.ciphertext,iv:e.iv,last4:typeof e.last4=="string"?e.last4:"",updatedAt:typeof e.updatedAt=="string"?e.updatedAt:"",version:e.version}}function s(t){const e=(t||"").trim();return e?`**** ${e}`:"Stored key"}function l(t){const e=t.apiKey.trim();if(!e)throw new Error("OpenRouter API key is required.");const a=c(t.encryptionSecret),r=o.randomBytes(12),i=o.createCipheriv(n,a,r),y=Buffer.concat([i.update(e,"utf8"),i.final()]),d=i.getAuthTag();return{algorithm:n,authTag:d.toString("base64"),ciphertext:y.toString("base64"),iv:r.toString("base64"),last4:e.slice(-4),updatedAt:(t.now||new Date).toISOString(),version:u}}function f(t){const e=p(t.encryptedKey),a=c(t.encryptionSecret);try{const r=o.createDecipheriv(n,a,Buffer.from(e.iv,"base64"));return r.setAuthTag(Buffer.from(e.authTag,"base64")),Buffer.concat([r.update(Buffer.from(e.ciphertext,"base64")),r.final()]).toString("utf8")}catch{throw new Error("Failed to decrypt stored OpenRouter key.")}}function h(t){try{const e=p(t);return{hasStoredKey:!0,last4:e.last4||null,maskedKey:s(e.last4),updatedAt:e.updatedAt||null}}catch{return{hasStoredKey:!1,last4:null,maskedKey:null,updatedAt:null}}}exports.CORTEX_AI_KEY_ALGORITHM=n;exports.CORTEX_AI_KEY_ENVELOPE_VERSION=u;exports.decryptOpenRouterApiKey=f;exports.encryptOpenRouterApiKey=l;exports.getMaskedOpenRouterKey=s;exports.getOpenRouterKeyEnvelopeStatus=h;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export declare const CORTEX_AI_KEY_ALGORITHM = "aes-256-gcm";
|
|
2
|
+
export declare const CORTEX_AI_KEY_ENVELOPE_VERSION = 1;
|
|
3
|
+
export type EncryptedOpenRouterKeyEnvelope = {
|
|
4
|
+
algorithm: typeof CORTEX_AI_KEY_ALGORITHM;
|
|
5
|
+
authTag: string;
|
|
6
|
+
ciphertext: string;
|
|
7
|
+
iv: string;
|
|
8
|
+
last4: string;
|
|
9
|
+
updatedAt: string;
|
|
10
|
+
version: typeof CORTEX_AI_KEY_ENVELOPE_VERSION;
|
|
11
|
+
};
|
|
12
|
+
export declare function getMaskedOpenRouterKey(last4?: string | null): string;
|
|
13
|
+
export declare function encryptOpenRouterApiKey(params: {
|
|
14
|
+
apiKey: string;
|
|
15
|
+
encryptionSecret: string;
|
|
16
|
+
now?: Date;
|
|
17
|
+
}): EncryptedOpenRouterKeyEnvelope;
|
|
18
|
+
export declare function decryptOpenRouterApiKey(params: {
|
|
19
|
+
encryptedKey: unknown;
|
|
20
|
+
encryptionSecret: string;
|
|
21
|
+
}): string;
|
|
22
|
+
export declare function getOpenRouterKeyEnvelopeStatus(value: unknown): {
|
|
23
|
+
hasStoredKey: boolean;
|
|
24
|
+
last4: string | null;
|
|
25
|
+
maskedKey: string;
|
|
26
|
+
updatedAt: string | null;
|
|
27
|
+
} | {
|
|
28
|
+
hasStoredKey: boolean;
|
|
29
|
+
last4: null;
|
|
30
|
+
maskedKey: null;
|
|
31
|
+
updatedAt: null;
|
|
32
|
+
};
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { createDecipheriv as d, randomBytes as y, createCipheriv as l, createHash as f } from "crypto";
|
|
2
|
+
const n = "aes-256-gcm", i = 1;
|
|
3
|
+
function s(t) {
|
|
4
|
+
const e = t.trim();
|
|
5
|
+
if (!e)
|
|
6
|
+
throw new Error("CORTEX_AI_ENCRYPTION_KEY is required to manage stored OpenRouter keys.");
|
|
7
|
+
return f("sha256").update(e).digest();
|
|
8
|
+
}
|
|
9
|
+
function c(t) {
|
|
10
|
+
if (!t || typeof t != "object")
|
|
11
|
+
throw new Error("Invalid encrypted OpenRouter key payload.");
|
|
12
|
+
const e = t;
|
|
13
|
+
if (e.algorithm !== n || e.version !== i || typeof e.authTag != "string" || typeof e.ciphertext != "string" || typeof e.iv != "string")
|
|
14
|
+
throw new Error("Invalid encrypted OpenRouter key payload.");
|
|
15
|
+
return {
|
|
16
|
+
algorithm: e.algorithm,
|
|
17
|
+
authTag: e.authTag,
|
|
18
|
+
ciphertext: e.ciphertext,
|
|
19
|
+
iv: e.iv,
|
|
20
|
+
last4: typeof e.last4 == "string" ? e.last4 : "",
|
|
21
|
+
updatedAt: typeof e.updatedAt == "string" ? e.updatedAt : "",
|
|
22
|
+
version: e.version
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
function h(t) {
|
|
26
|
+
const e = (t || "").trim();
|
|
27
|
+
return e ? `**** ${e}` : "Stored key";
|
|
28
|
+
}
|
|
29
|
+
function E(t) {
|
|
30
|
+
const e = t.apiKey.trim();
|
|
31
|
+
if (!e)
|
|
32
|
+
throw new Error("OpenRouter API key is required.");
|
|
33
|
+
const o = s(t.encryptionSecret), r = y(12), a = l(n, o, r), u = Buffer.concat([
|
|
34
|
+
a.update(e, "utf8"),
|
|
35
|
+
a.final()
|
|
36
|
+
]), p = a.getAuthTag();
|
|
37
|
+
return {
|
|
38
|
+
algorithm: n,
|
|
39
|
+
authTag: p.toString("base64"),
|
|
40
|
+
ciphertext: u.toString("base64"),
|
|
41
|
+
iv: r.toString("base64"),
|
|
42
|
+
last4: e.slice(-4),
|
|
43
|
+
updatedAt: (t.now || /* @__PURE__ */ new Date()).toISOString(),
|
|
44
|
+
version: i
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
function m(t) {
|
|
48
|
+
const e = c(t.encryptedKey), o = s(t.encryptionSecret);
|
|
49
|
+
try {
|
|
50
|
+
const r = d(
|
|
51
|
+
n,
|
|
52
|
+
o,
|
|
53
|
+
Buffer.from(e.iv, "base64")
|
|
54
|
+
);
|
|
55
|
+
return r.setAuthTag(Buffer.from(e.authTag, "base64")), Buffer.concat([
|
|
56
|
+
r.update(Buffer.from(e.ciphertext, "base64")),
|
|
57
|
+
r.final()
|
|
58
|
+
]).toString("utf8");
|
|
59
|
+
} catch {
|
|
60
|
+
throw new Error("Failed to decrypt stored OpenRouter key.");
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
function v(t) {
|
|
64
|
+
try {
|
|
65
|
+
const e = c(t);
|
|
66
|
+
return {
|
|
67
|
+
hasStoredKey: !0,
|
|
68
|
+
last4: e.last4 || null,
|
|
69
|
+
maskedKey: h(e.last4),
|
|
70
|
+
updatedAt: e.updatedAt || null
|
|
71
|
+
};
|
|
72
|
+
} catch {
|
|
73
|
+
return {
|
|
74
|
+
hasStoredKey: !1,
|
|
75
|
+
last4: null,
|
|
76
|
+
maskedKey: null,
|
|
77
|
+
updatedAt: null
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
export {
|
|
82
|
+
n as CORTEX_AI_KEY_ALGORITHM,
|
|
83
|
+
i as CORTEX_AI_KEY_ENVELOPE_VERSION,
|
|
84
|
+
m as decryptOpenRouterApiKey,
|
|
85
|
+
E as encryptOpenRouterApiKey,
|
|
86
|
+
h as getMaskedOpenRouterKey,
|
|
87
|
+
v as getOpenRouterKeyEnvelopeStatus
|
|
88
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const o=require("./ai-model-registry.cjs.js"),r="Cortex AI OpenRouter model catalog can only be imported from server-side code.";function n(){if(!(typeof window>"u"))throw new Error(r)}function s(){const e=new URL(`${o.CORTEX_AI_OPENROUTER_BASE_URL}/models`);return e.searchParams.set("supported_parameters",o.CORTEX_AI_REQUIRED_MODEL_PARAMETERS.join(",")),e.searchParams.set("output_modalities","text"),e.toString()}async function i(e){n();const t=await(e?.fetch||globalThis.fetch)(s(),{cache:"no-store",headers:{Accept:"application/json"}});if(!t.ok)throw new Error(`Failed to load OpenRouter models: ${t.status} ${t.statusText}`);return o.filterCortexAiCompatibleOpenRouterModels(await t.json(),e?.now)}exports.listCortexAiCompatibleOpenRouterModels=i;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { CortexAiCompatibleOpenRouterModel } from './ai-model-registry';
|
|
2
|
+
type FetchFunction = typeof globalThis.fetch;
|
|
3
|
+
export declare function listCortexAiCompatibleOpenRouterModels(params?: {
|
|
4
|
+
fetch?: FetchFunction;
|
|
5
|
+
now?: Date;
|
|
6
|
+
}): Promise<CortexAiCompatibleOpenRouterModel[]>;
|
|
7
|
+
export {};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { filterCortexAiCompatibleOpenRouterModels as o, CORTEX_AI_OPENROUTER_BASE_URL as r, CORTEX_AI_REQUIRED_MODEL_PARAMETERS as n } from "./ai-model-registry.es.js";
|
|
2
|
+
const s = "Cortex AI OpenRouter model catalog can only be imported from server-side code.";
|
|
3
|
+
function a() {
|
|
4
|
+
if (!(typeof window > "u"))
|
|
5
|
+
throw new Error(s);
|
|
6
|
+
}
|
|
7
|
+
function i() {
|
|
8
|
+
const e = new URL(`${r}/models`);
|
|
9
|
+
return e.searchParams.set("supported_parameters", n.join(",")), e.searchParams.set("output_modalities", "text"), e.toString();
|
|
10
|
+
}
|
|
11
|
+
async function p(e) {
|
|
12
|
+
a();
|
|
13
|
+
const t = await (e?.fetch || globalThis.fetch)(i(), {
|
|
14
|
+
cache: "no-store",
|
|
15
|
+
headers: {
|
|
16
|
+
Accept: "application/json"
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
if (!t.ok)
|
|
20
|
+
throw new Error(`Failed to load OpenRouter models: ${t.status} ${t.statusText}`);
|
|
21
|
+
return o(await t.json(), e?.now);
|
|
22
|
+
}
|
|
23
|
+
export {
|
|
24
|
+
p as listCortexAiCompatibleOpenRouterModels
|
|
25
|
+
};
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const h=require("ai"),T="https://openrouter.ai/api/v1",C="openrouter/free",u=["qwen/qwen3-next-80b-a3b-instruct:free","nvidia/nemotron-3-super-120b-a12b:free","nvidia/nemotron-nano-9b-v2:free"],x=["tools","structured_outputs"],P={frequencyPenalty:"frequency_penalty",logitBias:"logit_bias",presencePenalty:"presence_penalty",seed:"seed",stopSequences:"stop",temperature:"temperature",topK:"top_k",topP:"top_p"},L={defaultFreeRouter:C,defaultStructuredOutputModel:u[0],defaultToolCallingModel:u[0],freeFallbacks:u,structuredJsonPreferred:u,toolCallingPreferred:u};class m extends Error{attempts;constructor(t,n,r){super(t),this.name="CortexAiRoutingError",this.attempts=n,this.cause=r}}function R(e){return Array.from(new Set(e.filter(Boolean)))}function c(e){return e&&typeof e=="object"&&!Array.isArray(e)?e:null}function p(e){return typeof e=="string"&&e.trim()?e.trim():null}function A(e){return Array.isArray(e)?e.filter(t=>typeof t=="string"&&t.trim().length>0):[]}function f(e){const t=typeof e=="number"?e:Number(e);return Number.isFinite(t)?t:null}function b(e){const t=c(e);return t?Object.fromEntries(Object.entries(t).filter(([,n])=>n!=null).map(([n,r])=>[n,String(r)])):{}}function I(e){const t=new Set(e);return x.every(n=>t.has(n))}function D(e){const t=c(e.architecture);return A(t?.output_modalities).includes("text")}function F(e){if(e==null)return null;if(typeof e=="number")return e>1e10?e:e*1e3;if(typeof e=="string"&&e.trim()){const t=Date.parse(e);return Number.isFinite(t)?t:null}return null}function w(e,t){const n=F(e);return n!==null&&n<=t.getTime()}function q(e){const t=c(e.top_provider);return f(e.context_length)??f(e.contextLength)??f(t?.context_length)??null}function k(e){const t=e.expiration_date??e.expirationDate;return typeof t=="string"&&t.trim()?t.trim():null}function S(e){return!!(e&&u.includes(e))}function N(e){const t=c(e);if(!t)return null;const n=p(t.modelId),r=p(t.name),s=A(t.supportedParameters),i=p(t.updatedAt);return!n||!r||!i||!I(s)?null:{contextLength:f(t.contextLength),modelId:n,name:r,pricing:b(t.pricing),supportedParameters:s,updatedAt:i}}function U(e,t=new Date){return{contextLength:e.contextLength,modelId:e.id,name:e.name,pricing:e.pricing,supportedParameters:[...e.supportedParameters],updatedAt:t.toISOString()}}function j(e,t=new Date){const n=c(e),r=Array.isArray(e)?e:Array.isArray(n?.data)?n.data:[],s=[];for(const i of r){const o=c(i),l=p(o?.id),a=p(o?.name),O=A(o?.supported_parameters);!o||!l||!a||!D(o)||w(o.expiration_date,t)||!I(O)||s.push({contextLength:q(o),created:f(o.created),expirationDate:k(o),id:l,name:a,pricing:b(o.pricing),supportedParameters:O})}return s.sort((i,o)=>i.name.localeCompare(o.name))}function X(e){return R([e?.modelId||u[0],...e?.fallbackModelIds||u])}function B(e){const t=e.requestedModelId?.trim()||null;if(e.credentialSource==="env")return{credentialSource:e.credentialSource,ignoredRequestedModelId:t&&!S(t)?t:null,modelIds:[...u],modelSelection:null};const n=R(e.fallbackModelIds?.length?e.fallbackModelIds:u),r=e.credentialSource==="stored"?e.selectedModel?.modelId||n[0]:t||e.selectedModel?.modelId||n[0];return{credentialSource:e.credentialSource,ignoredRequestedModelId:e.credentialSource==="stored"&&t&&t!==r?t:null,modelIds:R([r,...n]),modelSelection:e.selectedModel||null}}function K(e,t){const n=t.modelSelection;if(!n||n.modelId!==t.modelId)return e;const r=new Set(n.supportedParameters),s=Object.entries(P).filter(([o,l])=>o in e&&!r.has(l)).map(([o])=>o);if(s.length===0)return e;const i={...e};for(const o of s)delete i[o];return i}function E(e,t){if(!e||typeof e!="object"||!(t in e))return null;const n=e[t],r=typeof n=="number"?n:Number(n);return Number.isFinite(r)?r:null}function M(e){if(h.APICallError.isInstance(e))return e.statusCode??null;const t=E(e,"statusCode")??E(e,"status");if(t)return t;if(e&&typeof e=="object"&&"response"in e){const n=e.response,r=E(n,"status");if(r)return r}return e&&typeof e=="object"&&"cause"in e?M(e.cause):null}function _(e){return M(e)===429}function d(e){if(!e)return"";if(e instanceof Error){const t="cause"in e?d(e.cause):"";return[e.message,t].filter(Boolean).join(`
|
|
2
|
+
`)}if(typeof e=="object"){const t=e;return["message","error","text","cause"].map(n=>d(t[n])).filter(Boolean).join(`
|
|
3
|
+
`)}return String(e)}function y(e){return _(e)?!0:/No endpoints found|no longer available|not available as a free model|transitioned to a paid model/i.test(d(e))}function g(e,t=900){const n=e.replace(/\s+/g," ").trim();return n.length>t?`${n.slice(0,t-1).trimEnd()}...`:n}function G(e){const t=d(e);return t?g(t):"Unknown OpenRouter error."}function Y(e,t="Cortex AI request failed."){if(e instanceof m){const n=e.attempts.map(o=>o.errorMessage).filter(o=>!!o?.trim()),r=n[0],s=n[n.length-1],i=g(d(e.cause));return r&&s&&r!==s?`First model error: ${r} Last model error: ${s}`:s||r||i||e.message}return g(d(e))||t}async function $(e){const t=R(e.modelIds),n=e.shouldRetry||y;let r=[],s=null;for(const i of t)try{const o=await e.execute(i);return r=[...r,{modelId:i,rateLimited:!1,status:"success"}],{attempts:r,modelId:i,result:o}}catch(o){const l=_(o),a=n(o);if(s=o,r=[...r,{errorMessage:G(o),modelId:i,rateLimited:l,status:l?"rate_limited":a?"retried":"failed"}],!a)throw new m(`OpenRouter request failed for model "${i}".`,r,o)}throw new m("OpenRouter fallback exhausted all configured Cortex AI models.",r,s)}exports.CORTEX_AI_FREE_MODEL_FALLBACK_REGISTRY=u;exports.CORTEX_AI_MODEL_REGISTRY=L;exports.CORTEX_AI_OPENROUTER_BASE_URL=T;exports.CORTEX_AI_OPENROUTER_FREE_ROUTER_MODEL=C;exports.CORTEX_AI_REQUIRED_MODEL_PARAMETERS=x;exports.CortexAiRoutingError=m;exports.buildCortexAiModelFallbackChain=X;exports.buildCortexAiRoutingPolicy=B;exports.createCortexAiStoredModelSelection=U;exports.filterCortexAiCompatibleOpenRouterModels=j;exports.getHttpStatusCode=M;exports.isCortexAiFreeModelId=S;exports.isOpenRouterRateLimitError=_;exports.isOpenRouterRecoverableRoutingError=y;exports.omitUnsupportedCortexAiModelOptions=K;exports.runWithCortexAiModelFallback=$;exports.safeParseCortexAiModelSelection=N;exports.summarizeCortexAiRoutingError=Y;
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
export declare const CORTEX_AI_OPENROUTER_BASE_URL = "https://openrouter.ai/api/v1";
|
|
2
|
+
export declare const CORTEX_AI_OPENROUTER_FREE_ROUTER_MODEL = "openrouter/free";
|
|
3
|
+
export declare const CORTEX_AI_FREE_MODEL_FALLBACK_REGISTRY: readonly ["qwen/qwen3-next-80b-a3b-instruct:free", "nvidia/nemotron-3-super-120b-a12b:free", "nvidia/nemotron-nano-9b-v2:free"];
|
|
4
|
+
export declare const CORTEX_AI_REQUIRED_MODEL_PARAMETERS: readonly ["tools", "structured_outputs"];
|
|
5
|
+
export declare const CORTEX_AI_MODEL_REGISTRY: {
|
|
6
|
+
readonly defaultFreeRouter: "openrouter/free";
|
|
7
|
+
readonly defaultStructuredOutputModel: "qwen/qwen3-next-80b-a3b-instruct:free";
|
|
8
|
+
readonly defaultToolCallingModel: "qwen/qwen3-next-80b-a3b-instruct:free";
|
|
9
|
+
readonly freeFallbacks: readonly ["qwen/qwen3-next-80b-a3b-instruct:free", "nvidia/nemotron-3-super-120b-a12b:free", "nvidia/nemotron-nano-9b-v2:free"];
|
|
10
|
+
readonly structuredJsonPreferred: readonly ["qwen/qwen3-next-80b-a3b-instruct:free", "nvidia/nemotron-3-super-120b-a12b:free", "nvidia/nemotron-nano-9b-v2:free"];
|
|
11
|
+
readonly toolCallingPreferred: readonly ["qwen/qwen3-next-80b-a3b-instruct:free", "nvidia/nemotron-3-super-120b-a12b:free", "nvidia/nemotron-nano-9b-v2:free"];
|
|
12
|
+
};
|
|
13
|
+
export type CortexAiOpenRouterModelId = typeof CORTEX_AI_OPENROUTER_FREE_ROUTER_MODEL | (typeof CORTEX_AI_FREE_MODEL_FALLBACK_REGISTRY)[number] | (string & {});
|
|
14
|
+
export type CortexAiRoutingCredentialSource = 'env' | 'manual' | 'stored';
|
|
15
|
+
export type CortexAiOpenRouterModelPricing = Record<string, string>;
|
|
16
|
+
export type CortexAiCompatibleOpenRouterModel = {
|
|
17
|
+
contextLength: number | null;
|
|
18
|
+
created: number | null;
|
|
19
|
+
expirationDate: string | null;
|
|
20
|
+
id: CortexAiOpenRouterModelId;
|
|
21
|
+
name: string;
|
|
22
|
+
pricing: CortexAiOpenRouterModelPricing;
|
|
23
|
+
supportedParameters: readonly string[];
|
|
24
|
+
};
|
|
25
|
+
export type CortexAiStoredModelSelection = {
|
|
26
|
+
contextLength: number | null;
|
|
27
|
+
modelId: CortexAiOpenRouterModelId;
|
|
28
|
+
name: string;
|
|
29
|
+
pricing: CortexAiOpenRouterModelPricing;
|
|
30
|
+
supportedParameters: readonly string[];
|
|
31
|
+
updatedAt: string;
|
|
32
|
+
};
|
|
33
|
+
export type CortexAiRoutingPolicy = {
|
|
34
|
+
credentialSource: CortexAiRoutingCredentialSource;
|
|
35
|
+
ignoredRequestedModelId: CortexAiOpenRouterModelId | null;
|
|
36
|
+
modelIds: readonly CortexAiOpenRouterModelId[];
|
|
37
|
+
modelSelection: CortexAiStoredModelSelection | null;
|
|
38
|
+
};
|
|
39
|
+
export type CortexAiModelAttempt = {
|
|
40
|
+
errorMessage?: string;
|
|
41
|
+
modelId: CortexAiOpenRouterModelId;
|
|
42
|
+
rateLimited: boolean;
|
|
43
|
+
status: 'success' | 'rate_limited' | 'retried' | 'failed';
|
|
44
|
+
};
|
|
45
|
+
export declare class CortexAiRoutingError extends Error {
|
|
46
|
+
readonly attempts: readonly CortexAiModelAttempt[];
|
|
47
|
+
constructor(message: string, attempts: readonly CortexAiModelAttempt[], cause?: unknown);
|
|
48
|
+
}
|
|
49
|
+
export declare function isCortexAiFreeModelId(modelId: CortexAiOpenRouterModelId | null | undefined): boolean;
|
|
50
|
+
export declare function safeParseCortexAiModelSelection(value: unknown): CortexAiStoredModelSelection | null;
|
|
51
|
+
export declare function createCortexAiStoredModelSelection(model: CortexAiCompatibleOpenRouterModel, now?: Date): CortexAiStoredModelSelection;
|
|
52
|
+
export declare function filterCortexAiCompatibleOpenRouterModels(value: unknown, now?: Date): CortexAiCompatibleOpenRouterModel[];
|
|
53
|
+
export declare function buildCortexAiModelFallbackChain(params?: {
|
|
54
|
+
fallbackModelIds?: readonly CortexAiOpenRouterModelId[];
|
|
55
|
+
modelId?: CortexAiOpenRouterModelId | null;
|
|
56
|
+
}): CortexAiOpenRouterModelId[];
|
|
57
|
+
export declare function buildCortexAiRoutingPolicy(params: {
|
|
58
|
+
credentialSource: CortexAiRoutingCredentialSource;
|
|
59
|
+
fallbackModelIds?: readonly CortexAiOpenRouterModelId[];
|
|
60
|
+
requestedModelId?: CortexAiOpenRouterModelId | null;
|
|
61
|
+
selectedModel?: CortexAiStoredModelSelection | null;
|
|
62
|
+
}): CortexAiRoutingPolicy;
|
|
63
|
+
export declare function omitUnsupportedCortexAiModelOptions<TOptions extends Record<string, unknown>>(options: TOptions, params: {
|
|
64
|
+
modelId: CortexAiOpenRouterModelId;
|
|
65
|
+
modelSelection?: CortexAiStoredModelSelection | null;
|
|
66
|
+
}): TOptions;
|
|
67
|
+
export declare function getHttpStatusCode(error: unknown): number | null;
|
|
68
|
+
export declare function isOpenRouterRateLimitError(error: unknown): boolean;
|
|
69
|
+
export declare function isOpenRouterRecoverableRoutingError(error: unknown): boolean;
|
|
70
|
+
export declare function summarizeCortexAiRoutingError(error: unknown, fallbackMessage?: string): string;
|
|
71
|
+
export declare function runWithCortexAiModelFallback<T>(params: {
|
|
72
|
+
execute: (modelId: CortexAiOpenRouterModelId) => Promise<T>;
|
|
73
|
+
modelIds: readonly CortexAiOpenRouterModelId[];
|
|
74
|
+
shouldRetry?: (error: unknown) => boolean;
|
|
75
|
+
}): Promise<{
|
|
76
|
+
attempts: readonly CortexAiModelAttempt[];
|
|
77
|
+
modelId: CortexAiOpenRouterModelId;
|
|
78
|
+
result: T;
|
|
79
|
+
}>;
|
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
import { APICallError as y } from "ai";
|
|
2
|
+
const N = "https://openrouter.ai/api/v1", O = "openrouter/free", u = [
|
|
3
|
+
"qwen/qwen3-next-80b-a3b-instruct:free",
|
|
4
|
+
"nvidia/nemotron-3-super-120b-a12b:free",
|
|
5
|
+
"nvidia/nemotron-nano-9b-v2:free"
|
|
6
|
+
], S = ["tools", "structured_outputs"], h = {
|
|
7
|
+
frequencyPenalty: "frequency_penalty",
|
|
8
|
+
logitBias: "logit_bias",
|
|
9
|
+
presencePenalty: "presence_penalty",
|
|
10
|
+
seed: "seed",
|
|
11
|
+
stopSequences: "stop",
|
|
12
|
+
temperature: "temperature",
|
|
13
|
+
topK: "top_k",
|
|
14
|
+
topP: "top_p"
|
|
15
|
+
}, j = {
|
|
16
|
+
defaultFreeRouter: O,
|
|
17
|
+
defaultStructuredOutputModel: u[0],
|
|
18
|
+
defaultToolCallingModel: u[0],
|
|
19
|
+
freeFallbacks: u,
|
|
20
|
+
structuredJsonPreferred: u,
|
|
21
|
+
toolCallingPreferred: u
|
|
22
|
+
};
|
|
23
|
+
class R extends Error {
|
|
24
|
+
attempts;
|
|
25
|
+
constructor(t, n, r) {
|
|
26
|
+
super(t), this.name = "CortexAiRoutingError", this.attempts = n, this.cause = r;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
function m(e) {
|
|
30
|
+
return Array.from(new Set(e.filter(Boolean)));
|
|
31
|
+
}
|
|
32
|
+
function l(e) {
|
|
33
|
+
return e && typeof e == "object" && !Array.isArray(e) ? e : null;
|
|
34
|
+
}
|
|
35
|
+
function f(e) {
|
|
36
|
+
return typeof e == "string" && e.trim() ? e.trim() : null;
|
|
37
|
+
}
|
|
38
|
+
function E(e) {
|
|
39
|
+
return Array.isArray(e) ? e.filter((t) => typeof t == "string" && t.trim().length > 0) : [];
|
|
40
|
+
}
|
|
41
|
+
function p(e) {
|
|
42
|
+
const t = typeof e == "number" ? e : Number(e);
|
|
43
|
+
return Number.isFinite(t) ? t : null;
|
|
44
|
+
}
|
|
45
|
+
function _(e) {
|
|
46
|
+
const t = l(e);
|
|
47
|
+
return t ? Object.fromEntries(
|
|
48
|
+
Object.entries(t).filter(([, n]) => n != null).map(([n, r]) => [n, String(r)])
|
|
49
|
+
) : {};
|
|
50
|
+
}
|
|
51
|
+
function b(e) {
|
|
52
|
+
const t = new Set(e);
|
|
53
|
+
return S.every((n) => t.has(n));
|
|
54
|
+
}
|
|
55
|
+
function C(e) {
|
|
56
|
+
const t = l(e.architecture);
|
|
57
|
+
return E(t?.output_modalities).includes("text");
|
|
58
|
+
}
|
|
59
|
+
function P(e) {
|
|
60
|
+
if (e == null)
|
|
61
|
+
return null;
|
|
62
|
+
if (typeof e == "number")
|
|
63
|
+
return e > 1e10 ? e : e * 1e3;
|
|
64
|
+
if (typeof e == "string" && e.trim()) {
|
|
65
|
+
const t = Date.parse(e);
|
|
66
|
+
return Number.isFinite(t) ? t : null;
|
|
67
|
+
}
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
function L(e, t) {
|
|
71
|
+
const n = P(e);
|
|
72
|
+
return n !== null && n <= t.getTime();
|
|
73
|
+
}
|
|
74
|
+
function T(e) {
|
|
75
|
+
const t = l(e.top_provider);
|
|
76
|
+
return p(e.context_length) ?? p(e.contextLength) ?? p(t?.context_length) ?? null;
|
|
77
|
+
}
|
|
78
|
+
function w(e) {
|
|
79
|
+
const t = e.expiration_date ?? e.expirationDate;
|
|
80
|
+
return typeof t == "string" && t.trim() ? t.trim() : null;
|
|
81
|
+
}
|
|
82
|
+
function D(e) {
|
|
83
|
+
return !!(e && u.includes(e));
|
|
84
|
+
}
|
|
85
|
+
function B(e) {
|
|
86
|
+
const t = l(e);
|
|
87
|
+
if (!t)
|
|
88
|
+
return null;
|
|
89
|
+
const n = f(t.modelId), r = f(t.name), s = E(t.supportedParameters), i = f(t.updatedAt);
|
|
90
|
+
return !n || !r || !i || !b(s) ? null : {
|
|
91
|
+
contextLength: p(t.contextLength),
|
|
92
|
+
modelId: n,
|
|
93
|
+
name: r,
|
|
94
|
+
pricing: _(t.pricing),
|
|
95
|
+
supportedParameters: s,
|
|
96
|
+
updatedAt: i
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
function U(e, t = /* @__PURE__ */ new Date()) {
|
|
100
|
+
return {
|
|
101
|
+
contextLength: e.contextLength,
|
|
102
|
+
modelId: e.id,
|
|
103
|
+
name: e.name,
|
|
104
|
+
pricing: e.pricing,
|
|
105
|
+
supportedParameters: [...e.supportedParameters],
|
|
106
|
+
updatedAt: t.toISOString()
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
function X(e, t = /* @__PURE__ */ new Date()) {
|
|
110
|
+
const n = l(e), r = Array.isArray(e) ? e : Array.isArray(n?.data) ? n.data : [], s = [];
|
|
111
|
+
for (const i of r) {
|
|
112
|
+
const o = l(i), c = f(o?.id), a = f(o?.name), A = E(o?.supported_parameters);
|
|
113
|
+
!o || !c || !a || !C(o) || L(o.expiration_date, t) || !b(A) || s.push({
|
|
114
|
+
contextLength: T(o),
|
|
115
|
+
created: p(o.created),
|
|
116
|
+
expirationDate: w(o),
|
|
117
|
+
id: c,
|
|
118
|
+
name: a,
|
|
119
|
+
pricing: _(o.pricing),
|
|
120
|
+
supportedParameters: A
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
return s.sort((i, o) => i.name.localeCompare(o.name));
|
|
124
|
+
}
|
|
125
|
+
function K(e) {
|
|
126
|
+
return m([
|
|
127
|
+
e?.modelId || u[0],
|
|
128
|
+
...e?.fallbackModelIds || u
|
|
129
|
+
]);
|
|
130
|
+
}
|
|
131
|
+
function $(e) {
|
|
132
|
+
const t = e.requestedModelId?.trim() || null;
|
|
133
|
+
if (e.credentialSource === "env")
|
|
134
|
+
return {
|
|
135
|
+
credentialSource: e.credentialSource,
|
|
136
|
+
ignoredRequestedModelId: t && !D(t) ? t : null,
|
|
137
|
+
modelIds: [...u],
|
|
138
|
+
modelSelection: null
|
|
139
|
+
};
|
|
140
|
+
const n = m(
|
|
141
|
+
e.fallbackModelIds?.length ? e.fallbackModelIds : u
|
|
142
|
+
), r = e.credentialSource === "stored" ? e.selectedModel?.modelId || n[0] : t || e.selectedModel?.modelId || n[0];
|
|
143
|
+
return {
|
|
144
|
+
credentialSource: e.credentialSource,
|
|
145
|
+
ignoredRequestedModelId: e.credentialSource === "stored" && t && t !== r ? t : null,
|
|
146
|
+
modelIds: m([r, ...n]),
|
|
147
|
+
modelSelection: e.selectedModel || null
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
function z(e, t) {
|
|
151
|
+
const n = t.modelSelection;
|
|
152
|
+
if (!n || n.modelId !== t.modelId)
|
|
153
|
+
return e;
|
|
154
|
+
const r = new Set(n.supportedParameters), s = Object.entries(h).filter(([o, c]) => o in e && !r.has(c)).map(([o]) => o);
|
|
155
|
+
if (s.length === 0)
|
|
156
|
+
return e;
|
|
157
|
+
const i = { ...e };
|
|
158
|
+
for (const o of s)
|
|
159
|
+
delete i[o];
|
|
160
|
+
return i;
|
|
161
|
+
}
|
|
162
|
+
function g(e, t) {
|
|
163
|
+
if (!e || typeof e != "object" || !(t in e))
|
|
164
|
+
return null;
|
|
165
|
+
const n = e[t], r = typeof n == "number" ? n : Number(n);
|
|
166
|
+
return Number.isFinite(r) ? r : null;
|
|
167
|
+
}
|
|
168
|
+
function x(e) {
|
|
169
|
+
if (y.isInstance(e))
|
|
170
|
+
return e.statusCode ?? null;
|
|
171
|
+
const t = g(e, "statusCode") ?? g(e, "status");
|
|
172
|
+
if (t)
|
|
173
|
+
return t;
|
|
174
|
+
if (e && typeof e == "object" && "response" in e) {
|
|
175
|
+
const n = e.response, r = g(n, "status");
|
|
176
|
+
if (r)
|
|
177
|
+
return r;
|
|
178
|
+
}
|
|
179
|
+
return e && typeof e == "object" && "cause" in e ? x(e.cause) : null;
|
|
180
|
+
}
|
|
181
|
+
function I(e) {
|
|
182
|
+
return x(e) === 429;
|
|
183
|
+
}
|
|
184
|
+
function d(e) {
|
|
185
|
+
if (!e)
|
|
186
|
+
return "";
|
|
187
|
+
if (e instanceof Error) {
|
|
188
|
+
const t = "cause" in e ? d(e.cause) : "";
|
|
189
|
+
return [e.message, t].filter(Boolean).join(`
|
|
190
|
+
`);
|
|
191
|
+
}
|
|
192
|
+
if (typeof e == "object") {
|
|
193
|
+
const t = e;
|
|
194
|
+
return ["message", "error", "text", "cause"].map((n) => d(t[n])).filter(Boolean).join(`
|
|
195
|
+
`);
|
|
196
|
+
}
|
|
197
|
+
return String(e);
|
|
198
|
+
}
|
|
199
|
+
function q(e) {
|
|
200
|
+
return I(e) ? !0 : /No endpoints found|no longer available|not available as a free model|transitioned to a paid model/i.test(
|
|
201
|
+
d(e)
|
|
202
|
+
);
|
|
203
|
+
}
|
|
204
|
+
function M(e, t = 900) {
|
|
205
|
+
const n = e.replace(/\s+/g, " ").trim();
|
|
206
|
+
return n.length > t ? `${n.slice(0, t - 1).trimEnd()}...` : n;
|
|
207
|
+
}
|
|
208
|
+
function F(e) {
|
|
209
|
+
const t = d(e);
|
|
210
|
+
return t ? M(t) : "Unknown OpenRouter error.";
|
|
211
|
+
}
|
|
212
|
+
function G(e, t = "Cortex AI request failed.") {
|
|
213
|
+
if (e instanceof R) {
|
|
214
|
+
const n = e.attempts.map((o) => o.errorMessage).filter((o) => !!o?.trim()), r = n[0], s = n[n.length - 1], i = M(d(e.cause));
|
|
215
|
+
return r && s && r !== s ? `First model error: ${r} Last model error: ${s}` : s || r || i || e.message;
|
|
216
|
+
}
|
|
217
|
+
return M(d(e)) || t;
|
|
218
|
+
}
|
|
219
|
+
async function Y(e) {
|
|
220
|
+
const t = m(e.modelIds), n = e.shouldRetry || q;
|
|
221
|
+
let r = [], s = null;
|
|
222
|
+
for (const i of t)
|
|
223
|
+
try {
|
|
224
|
+
const o = await e.execute(i);
|
|
225
|
+
return r = [
|
|
226
|
+
...r,
|
|
227
|
+
{
|
|
228
|
+
modelId: i,
|
|
229
|
+
rateLimited: !1,
|
|
230
|
+
status: "success"
|
|
231
|
+
}
|
|
232
|
+
], {
|
|
233
|
+
attempts: r,
|
|
234
|
+
modelId: i,
|
|
235
|
+
result: o
|
|
236
|
+
};
|
|
237
|
+
} catch (o) {
|
|
238
|
+
const c = I(o), a = n(o);
|
|
239
|
+
if (s = o, r = [
|
|
240
|
+
...r,
|
|
241
|
+
{
|
|
242
|
+
errorMessage: F(o),
|
|
243
|
+
modelId: i,
|
|
244
|
+
rateLimited: c,
|
|
245
|
+
status: c ? "rate_limited" : a ? "retried" : "failed"
|
|
246
|
+
}
|
|
247
|
+
], !a)
|
|
248
|
+
throw new R(
|
|
249
|
+
`OpenRouter request failed for model "${i}".`,
|
|
250
|
+
r,
|
|
251
|
+
o
|
|
252
|
+
);
|
|
253
|
+
}
|
|
254
|
+
throw new R(
|
|
255
|
+
"OpenRouter fallback exhausted all configured Cortex AI models.",
|
|
256
|
+
r,
|
|
257
|
+
s
|
|
258
|
+
);
|
|
259
|
+
}
|
|
260
|
+
export {
|
|
261
|
+
u as CORTEX_AI_FREE_MODEL_FALLBACK_REGISTRY,
|
|
262
|
+
j as CORTEX_AI_MODEL_REGISTRY,
|
|
263
|
+
N as CORTEX_AI_OPENROUTER_BASE_URL,
|
|
264
|
+
O as CORTEX_AI_OPENROUTER_FREE_ROUTER_MODEL,
|
|
265
|
+
S as CORTEX_AI_REQUIRED_MODEL_PARAMETERS,
|
|
266
|
+
R as CortexAiRoutingError,
|
|
267
|
+
K as buildCortexAiModelFallbackChain,
|
|
268
|
+
$ as buildCortexAiRoutingPolicy,
|
|
269
|
+
U as createCortexAiStoredModelSelection,
|
|
270
|
+
X as filterCortexAiCompatibleOpenRouterModels,
|
|
271
|
+
x as getHttpStatusCode,
|
|
272
|
+
D as isCortexAiFreeModelId,
|
|
273
|
+
I as isOpenRouterRateLimitError,
|
|
274
|
+
q as isOpenRouterRecoverableRoutingError,
|
|
275
|
+
z as omitUnsupportedCortexAiModelOptions,
|
|
276
|
+
Y as runWithCortexAiModelFallback,
|
|
277
|
+
B as safeParseCortexAiModelSelection,
|
|
278
|
+
G as summarizeCortexAiRoutingError
|
|
279
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const n=require("@nextblock-cms/utils/custom-blocks"),a="id, slug, name, description, fields, layout_schema, is_original";class c extends Error{code;status;constructor(e,i){super(e),this.name="CortexWidgetRegistryInsertError",this.code=i?.code,this.status=i?.status??500}}function s(t){return JSON.parse(JSON.stringify(t))}function d(t){return t==="23505"?409:t==="42501"?403:500}function u(t){const e=n.customBlockDefinitionCreateSchema.parse({...t,is_original:!0});return{description:e.description,fields:s(e.fields),is_original:!0,layout_schema:s(e.layout_schema),name:e.name,slug:e.slug}}async function l(t,e){const i=u(e),{data:o,error:r}=await t.from("custom_block_definitions").insert(i).select(a).single();if(r||!o)throw new c(r?.message??"Failed to insert Cortex custom block definition.",{code:r?.code,status:d(r?.code)});return n.customBlockDefinitionRowSchema.parse(o)}exports.CORTEX_WIDGET_DEFINITION_SELECT=a;exports.CortexWidgetRegistryInsertError=c;exports.buildCortexWidgetDefinitionInsertPayload=u;exports.insertCortexWidgetDefinition=l;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { Database } from '../../../db/src/lib/supabase/types.ts';
|
|
2
|
+
import { CustomBlockDefinition } from '../../../utils/src/lib/custom-blocks';
|
|
3
|
+
import { CortexWidgetDefinition } from './cortex-widget-schema';
|
|
4
|
+
export declare const CORTEX_WIDGET_DEFINITION_SELECT = "id, slug, name, description, fields, layout_schema, is_original";
|
|
5
|
+
type CustomBlockDefinitionInsert = Database['public']['Tables']['custom_block_definitions']['Insert'];
|
|
6
|
+
type SupabaseInsertClient = {
|
|
7
|
+
from: (table: string) => any;
|
|
8
|
+
};
|
|
9
|
+
export declare class CortexWidgetRegistryInsertError extends Error {
|
|
10
|
+
readonly code?: string;
|
|
11
|
+
readonly status: number;
|
|
12
|
+
constructor(message: string, params?: {
|
|
13
|
+
code?: string;
|
|
14
|
+
status?: number;
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
export declare function buildCortexWidgetDefinitionInsertPayload(definition: CortexWidgetDefinition): CustomBlockDefinitionInsert;
|
|
18
|
+
export declare function insertCortexWidgetDefinition(supabase: SupabaseInsertClient, definition: CortexWidgetDefinition): Promise<CustomBlockDefinition>;
|
|
19
|
+
export {};
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { customBlockDefinitionCreateSchema as n, customBlockDefinitionRowSchema as a } from "@nextblock-cms/utils/custom-blocks";
|
|
2
|
+
const c = "id, slug, name, description, fields, layout_schema, is_original";
|
|
3
|
+
class u extends Error {
|
|
4
|
+
code;
|
|
5
|
+
status;
|
|
6
|
+
constructor(e, i) {
|
|
7
|
+
super(e), this.name = "CortexWidgetRegistryInsertError", this.code = i?.code, this.status = i?.status ?? 500;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
function o(t) {
|
|
11
|
+
return JSON.parse(JSON.stringify(t));
|
|
12
|
+
}
|
|
13
|
+
function d(t) {
|
|
14
|
+
return t === "23505" ? 409 : t === "42501" ? 403 : 500;
|
|
15
|
+
}
|
|
16
|
+
function l(t) {
|
|
17
|
+
const e = n.parse({
|
|
18
|
+
...t,
|
|
19
|
+
is_original: !0
|
|
20
|
+
});
|
|
21
|
+
return {
|
|
22
|
+
description: e.description,
|
|
23
|
+
fields: o(e.fields),
|
|
24
|
+
is_original: !0,
|
|
25
|
+
layout_schema: o(e.layout_schema),
|
|
26
|
+
name: e.name,
|
|
27
|
+
slug: e.slug
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
async function g(t, e) {
|
|
31
|
+
const i = l(e), { data: s, error: r } = await t.from("custom_block_definitions").insert(i).select(c).single();
|
|
32
|
+
if (r || !s)
|
|
33
|
+
throw new u(
|
|
34
|
+
r?.message ?? "Failed to insert Cortex custom block definition.",
|
|
35
|
+
{
|
|
36
|
+
code: r?.code,
|
|
37
|
+
status: d(r?.code)
|
|
38
|
+
}
|
|
39
|
+
);
|
|
40
|
+
return a.parse(s);
|
|
41
|
+
}
|
|
42
|
+
export {
|
|
43
|
+
c as CORTEX_WIDGET_DEFINITION_SELECT,
|
|
44
|
+
u as CortexWidgetRegistryInsertError,
|
|
45
|
+
l as buildCortexWidgetDefinitionInsertPayload,
|
|
46
|
+
g as insertCortexWidgetDefinition
|
|
47
|
+
};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const o=require("@nextblock-cms/utils/custom-blocks");require("./zod-config.cjs.js");const e=require("zod"),r=["pages","posts","products","media","categories","profiles","languages"],d=e.z.enum(["article","aside","blockquote","div","figure","figcaption","h2","h3","img","p","section","span"]).describe("A safe semantic element supported by the dynamic layout renderer."),c=e.z.string().trim().max(4e3).describe("Tailwind utility classes only. Do not include CSS, style tags, or JavaScript."),l=e.z.strictObject({description:e.z.string().trim().max(500).optional(),key:o.customBlockFieldKeySchema.describe("Lowercase snake_case field key."),label:e.z.string().trim().min(1).max(120),required:e.z.boolean().default(!1)}),m=l.extend({default_value:e.z.string().max(5e3).optional(),max_length:e.z.number().int().positive().max(1e4).optional(),min_length:e.z.number().int().min(0).max(1e4).optional(),placeholder:e.z.string().max(250).optional(),type:e.z.literal("text")}),u=l.extend({default_value:e.z.string().max(5e4).optional(),placeholder:e.z.string().max(250).optional(),type:e.z.literal("rich-text")}),p=l.extend({accept:e.z.array(e.z.string().trim().min(1).max(120)).max(20).optional(),default_value:e.z.strictObject({alt:e.z.string().max(300).optional(),file_name:e.z.string().trim().min(1).max(255).optional(),file_type:e.z.string().trim().min(1).max(120).optional(),height:e.z.number().int().positive().optional(),object_key:e.z.string().trim().min(1).max(1024),size_bytes:e.z.number().int().positive().optional(),url:e.z.string().trim().min(1).max(2048),width:e.z.number().int().positive().optional()}).optional(),max_bytes:e.z.number().int().positive().max(50*1024*1024).optional(),type:e.z.literal("image_r2")}),f=l.extend({default_value:e.z.union([e.z.string(),e.z.array(e.z.string()),e.z.null()]).optional(),display_column:e.z.string().trim().min(1).max(80).default("title"),filters:e.z.record(e.z.string(),e.z.unknown()).optional(),multiple:e.z.boolean().default(!1),table:e.z.enum(r),type:e.z.literal("db_relation"),value_column:e.z.string().trim().min(1).max(80).default("id")}),y=e.z.discriminatedUnion("type",[m,u,p,f]).describe("A NextBlock custom block field. Allowed types: text, rich-text, image_r2, db_relation."),s=e.z.lazy(()=>e.z.discriminatedUnion("type",[e.z.strictObject({as:d.optional(),children:e.z.array(s).max(200).default([]),className:c.optional(),type:e.z.literal("container")}),e.z.strictObject({as:d.optional(),className:c.optional(),column:e.z.string().trim().min(1).max(80).optional().describe("For a db_relation field, the related record column to display (e.g. title, price)."),emptyFallback:e.z.string().max(300).optional(),field_key:o.customBlockFieldKeySchema,type:e.z.literal("field_render")})])),_=e.z.strictObject({context:e.z.string().trim().max(3e3).optional(),modelId:e.z.string().trim().min(1).max(200).optional(),prompt:e.z.string().trim().min(3).max(4e3)});function g(t){return t.type==="field_render"?[t.field_key]:t.children.flatMap(i=>g(i))}function k(t,i){const n=new Set;t.fields.forEach((a,b)=>{n.has(a.key)&&i.addIssue({code:"custom",message:`Duplicate field key "${a.key}".`,path:["fields",b,"key"]}),n.add(a.key)});for(const a of g(t.layout_schema))n.has(a)||i.addIssue({code:"custom",message:`Layout references unknown field "${a}".`,path:["layout_schema"]})}const h=e.z.strictObject({description:e.z.string().trim().max(1e3).default(""),fields:e.z.array(y).min(1).max(80),is_original:e.z.boolean().default(!0),layout_schema:s,name:e.z.string().trim().min(1).max(160),slug:o.customBlockSlugSchema.describe("Lowercase kebab-case slug.")}).superRefine(k).describe("A complete NextBlock custom block definition stored as database JSONB.");function x(t){const i=h.parse(t);return o.customBlockDefinitionCreateSchema.parse({...i,is_original:!0})}function z(){return["You are NextBlock Cortex, an expert web platform engineer building database-rendered custom CMS widgets.","Return ONLY one clean raw JSON object with the exact structure described in the user message. Do not include markdown fences, comments, prose, or explanatory text.","Never emit TSX, JSX, React components, JavaScript, CSS blocks, style attributes, script tags, or runtime code.","Use only these field types: text, rich-text, image_r2, db_relation.",`Use db_relation.table only from this allowlist: ${r.join(", ")}.`,"Use lowercase kebab-case for slug and lowercase snake_case for field keys.","Build layout_schema as a self-referential tree: container nodes may contain nested container or field_render nodes to any needed depth.","Use Tailwind utility classes in className strings. Use responsive utilities where helpful.",'The "as" property of any node MUST be exactly one of: article, aside, blockquote, div, figure, figcaption, h2, h3, img, p, section, span. Never use a, button, ul, ol, li, table, or any other tag. For a call-to-action or "more info" button, use a span or p styled with button-like Tailwind classes (rounded, padded, colored background).',"Every field_render.field_key must match one field key exactly.","For relation fields, set value_column to id and set display_column to a column that actually exists on the chosen table: use title for pages, posts, and products; sku for product_variants; full_name for profiles; name for categories and languages; file_name for media. Do not invent display columns.",`Entity images: when a block displays an image that belongs to a related product, page, or post (for example a product card photo or a post thumbnail), do NOT add an image_r2 upload field for it. Instead add a single db_relation field to that table (products, product_variants, pages, or posts) and add a field_render node that references it with "as": "img". The renderer automatically resolves the related record's primary image — a product or variant main_image/object_key, or a page/post feature image — so keep the table's normal display_column (for example title for a products relation).`,'You may reference the same db_relation field from more than one field_render node: for example one node with "as": "img" for the image and another text node for its title, plus the relation value to drive a "more info" link. This builds a product/page/post card from a single relation field.',`To display a SPECIFIC column of a related record (its title, price, sku, etc.), set the field_render node's "column" property to that column name. The "column" overrides the field display_column for that one node, so a single product relation can show its image (as "img"), title (column "title"), and price (column "price") from three field_render nodes.`,'Available record columns by table — only reference these in a node "column": products: title, sku, price, sale_price, stock, short_description, slug, status; product_variants: sku, price, sale_price, stock_quantity; pages: title, slug, status; posts: title, slug, excerpt, subtitle; profiles: full_name; categories: name, slug, description; media: file_name; languages: name, code. Use "as": "img" (no column) to show a record image.','Do NOT create a standalone text field for data that lives on a related record. For example, a product price must come from a products db_relation field rendered with column "price" — never a separate "text" field the editor types by hand.',"Monetary columns (price, sale_price, price_adjustment) are stored in integer cents and are automatically formatted as currency on display, so reference them directly; never multiply, divide, or add currency symbols yourself.","Only use image_r2 for standalone images uploaded directly by the editor that are not tied to any database record (for example a decorative banner or icon). Only use text or rich-text fields for free-form copy the editor writes, not for values that exist on a related record."].join(" ")}function v(t){return["Create a NextBlock custom block definition for this request:",t.prompt,t.context?`Additional CMS context:
|
|
2
|
+
${t.context}`:null,["Return ONLY a JSON object with EXACTLY these top-level keys:",'- "name": string (human-friendly block name).','- "slug": lowercase kebab-case string.','- "description": short string.','- "is_original": true.','- "fields": a non-empty array of field objects. Each field is { "key": lowercase snake_case string, "label": string, "required": boolean, "type": one of "text" | "rich-text" | "image_r2" | "db_relation" }.',` For "db_relation" fields also include "table" (one of: ${r.join(", ")}), "display_column" (e.g. title, name, full_name, file_name, code), "value_column": "id", and "multiple": boolean.`,'- "layout_schema": a single root layout node (a tree). Every node is one of:',' container: { "type": "container", "as": an HTML tag like div/section/article/figure, "className": Tailwind utility classes, "children": array of nodes }.',' field render: { "type": "field_render", "field_key": one of the field keys above, "as": an HTML tag like p/span/img/h2/h3/div, "className": Tailwind utility classes, "emptyFallback": optional placeholder string }.',' Containers may nest other containers to any depth. Every field_render.field_key MUST match one of the fields. Render image_r2 fields with "as": "img".'].join(`
|
|
3
|
+
`)].filter(Boolean).join(`
|
|
4
|
+
|
|
5
|
+
`)}function S(){return x({description:"A multi-tier profile card with an R2 image asset slot and a live customer relation list.",fields:[{accept:["image/png","image/jpeg","image/webp"],key:"profile_photo",label:"Profile Photo",max_bytes:10485760,required:!1,type:"image_r2"},{key:"profile_name",label:"Profile Name",placeholder:"Ada Lovelace",required:!0,type:"text"},{key:"profile_role",label:"Profile Role",placeholder:"Principal Architect",required:!1,type:"text"},{key:"profile_summary",label:"Profile Summary",placeholder:"<p>Short profile biography.</p>",required:!1,type:"rich-text"},{display_column:"full_name",key:"customer_list",label:"Customer List",multiple:!0,required:!1,table:"profiles",type:"db_relation",value_column:"id"}],is_original:!0,layout_schema:{as:"article",children:[{as:"div",children:[{as:"div",children:[{as:"div",children:[{as:"img",className:"h-24 w-24 rounded-full border object-cover shadow-sm",emptyFallback:"Upload profile photo",field_key:"profile_photo",type:"field_render"},{as:"span",className:"rounded-full bg-muted px-3 py-1 text-center text-xs font-medium text-muted-foreground",emptyFallback:"No customers linked",field_key:"customer_list",type:"field_render"}],className:"flex flex-col items-center gap-4 md:w-48",type:"container"},{as:"div",children:[{as:"div",children:[{as:"h2",className:"text-2xl font-semibold leading-tight",emptyFallback:"Untitled profile",field_key:"profile_name",type:"field_render"},{as:"p",className:"text-sm font-medium text-muted-foreground",emptyFallback:"Role pending",field_key:"profile_role",type:"field_render"}],className:"flex flex-col gap-1",type:"container"},{as:"div",children:[{as:"div",className:"prose prose-sm max-w-none text-muted-foreground",emptyFallback:"<p>Add a concise profile summary.</p>",field_key:"profile_summary",type:"field_render"}],className:"rounded-md border bg-muted/30 p-4",type:"container"}],className:"flex min-w-0 flex-1 flex-col gap-4",type:"container"}],className:"flex flex-col gap-6 md:flex-row",type:"container"}],className:"rounded-lg border bg-background p-6 shadow-sm",type:"container"}],className:"mx-auto max-w-3xl p-4",type:"container"},name:"Cortex Profile Card",slug:"cortex-profile-card"})}exports.CORTEX_WIDGET_ALLOWED_RELATION_TABLES=r;exports.buildCortexProfileCardVerificationDefinition=S;exports.buildCortexWidgetBuilderPrompt=v;exports.buildCortexWidgetBuilderSystemPrompt=z;exports.cortexWidgetBuildRequestSchema=_;exports.cortexWidgetDbRelationFieldSchema=f;exports.cortexWidgetDefinitionSchema=h;exports.cortexWidgetFieldSchema=y;exports.cortexWidgetImageR2FieldSchema=p;exports.cortexWidgetLayoutNodeSchema=s;exports.cortexWidgetRichTextFieldSchema=u;exports.cortexWidgetTextFieldSchema=m;exports.validateCortexWidgetDefinitionOutput=x;
|