@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.
Files changed (49) hide show
  1. package/client.cjs.js +1 -0
  2. package/client.d.ts +1 -0
  3. package/client.es.js +4 -0
  4. package/index.cjs.js +1 -0
  5. package/index.d.ts +13 -0
  6. package/index.es.js +135 -0
  7. package/lib/ai-block-generation.cjs.js +5 -0
  8. package/lib/ai-block-generation.d.ts +21 -0
  9. package/lib/ai-block-generation.es.js +195 -0
  10. package/lib/ai-client.cjs.js +1 -0
  11. package/lib/ai-client.d.ts +48 -0
  12. package/lib/ai-client.es.js +141 -0
  13. package/lib/ai-config.cjs.js +1 -0
  14. package/lib/ai-config.d.ts +31 -0
  15. package/lib/ai-config.es.js +72 -0
  16. package/lib/ai-cortex-widget-builder.cjs.js +1 -0
  17. package/lib/ai-cortex-widget-builder.d.ts +14 -0
  18. package/lib/ai-cortex-widget-builder.es.js +72 -0
  19. package/lib/ai-global-agent-custom-block-tools.cjs.js +1 -0
  20. package/lib/ai-global-agent-custom-block-tools.d.ts +208 -0
  21. package/lib/ai-global-agent-custom-block-tools.es.js +220 -0
  22. package/lib/ai-global-agent-db-tools.cjs.js +1 -0
  23. package/lib/ai-global-agent-db-tools.d.ts +280 -0
  24. package/lib/ai-global-agent-db-tools.es.js +879 -0
  25. package/lib/ai-global-agent-ecommerce.cjs.js +1 -0
  26. package/lib/ai-global-agent-ecommerce.d.ts +2 -0
  27. package/lib/ai-global-agent-ecommerce.es.js +7 -0
  28. package/lib/ai-global-agent-tools.cjs.js +15 -0
  29. package/lib/ai-global-agent-tools.d.ts +3109 -0
  30. package/lib/ai-global-agent-tools.es.js +2812 -0
  31. package/lib/ai-key-crypto.cjs.js +1 -0
  32. package/lib/ai-key-crypto.d.ts +32 -0
  33. package/lib/ai-key-crypto.es.js +88 -0
  34. package/lib/ai-model-catalog.cjs.js +1 -0
  35. package/lib/ai-model-catalog.d.ts +7 -0
  36. package/lib/ai-model-catalog.es.js +25 -0
  37. package/lib/ai-model-registry.cjs.js +3 -0
  38. package/lib/ai-model-registry.d.ts +79 -0
  39. package/lib/ai-model-registry.es.js +279 -0
  40. package/lib/cortex-widget-registry.cjs.js +1 -0
  41. package/lib/cortex-widget-registry.d.ts +19 -0
  42. package/lib/cortex-widget-registry.es.js +47 -0
  43. package/lib/cortex-widget-schema.cjs.js +5 -0
  44. package/lib/cortex-widget-schema.d.ts +224 -0
  45. package/lib/cortex-widget-schema.es.js +316 -0
  46. package/lib/zod-config.cjs.js +1 -0
  47. package/lib/zod-config.d.ts +2 -0
  48. package/lib/zod-config.es.js +6 -0
  49. package/package.json +39 -0
@@ -0,0 +1,31 @@
1
+ import { EncryptedOpenRouterKeyEnvelope } from './ai-key-crypto';
2
+ export declare const CORTEX_AI_PACKAGE_ID = "cortex-ai";
3
+ export declare const CORTEX_AI_PACKAGE_NAME = "NextBlock Cortex AI";
4
+ export declare const CORTEX_AI_OPENROUTER_SETTING_KEY = "cortex_ai_openrouter_api_key";
5
+ export declare const CORTEX_AI_OPENROUTER_MODEL_SELECTION_SETTING_KEY = "cortex_ai_openrouter_model_selection";
6
+ export declare function getOpenRouterEnvApiKey(): string | null;
7
+ export declare function getCortexAiEnvConfig(): {
8
+ encryptionKey: string | null;
9
+ freemiusSandboxKey: string | null;
10
+ hasEncryptionKey: boolean;
11
+ hasOpenRouterEnvKey: boolean;
12
+ openRouterEnvKeyLast4: string | null;
13
+ };
14
+ export declare function encryptStoredOpenRouterApiKey(apiKey: string): EncryptedOpenRouterKeyEnvelope;
15
+ export declare function decryptStoredOpenRouterApiKey(encryptedKey: unknown): string;
16
+ export declare function getStoredOpenRouterKeyStatus(value: unknown): {
17
+ hasStoredKey: boolean;
18
+ last4: string | null;
19
+ maskedKey: string;
20
+ updatedAt: string | null;
21
+ } | {
22
+ hasStoredKey: boolean;
23
+ last4: null;
24
+ maskedKey: null;
25
+ updatedAt: null;
26
+ };
27
+ export declare function getEnvOpenRouterKeyStatus(): {
28
+ hasEnvOpenRouterKey: boolean;
29
+ maskedEnvOpenRouterKey: string | null;
30
+ };
31
+ export type { EncryptedOpenRouterKeyEnvelope };
@@ -0,0 +1,72 @@
1
+ import { encryptOpenRouterApiKey as o, getMaskedOpenRouterKey as E, getOpenRouterKeyEnvelopeStatus as u } from "./ai-key-crypto.es.js";
2
+ import { tryDecryptWithEnvKey as i, hasSecretEncryptionKey as p, resolveSecretEncryptionKey as y } from "@nextblock-cms/db/secrets";
3
+ const c = "Cortex AI configuration can only be imported from server-side code.";
4
+ function n() {
5
+ if (!(typeof window > "u"))
6
+ throw new Error(c);
7
+ }
8
+ const a = "cortex-ai", A = "NextBlock Cortex AI", l = "cortex_ai_openrouter_api_key", d = "cortex_ai_openrouter_model_selection";
9
+ function t(e) {
10
+ return process.env[e]?.trim() || null;
11
+ }
12
+ function _() {
13
+ return n(), t("OPENROUTER_API_KEY");
14
+ }
15
+ function s() {
16
+ n();
17
+ const e = _();
18
+ return {
19
+ encryptionKey: t("CORTEX_AI_ENCRYPTION_KEY"),
20
+ freemiusSandboxKey: t("FREEMIUS_AI_SANDBOX_KEY"),
21
+ // True when ANY usable key exists: an explicit env key OR the service-role-derived
22
+ // fallback — so BYOK works on a one-click Vercel deploy with no extra env var.
23
+ hasEncryptionKey: p(),
24
+ hasOpenRouterEnvKey: !!e,
25
+ openRouterEnvKeyLast4: e ? e.slice(-4) : null
26
+ };
27
+ }
28
+ function R() {
29
+ n();
30
+ const e = y();
31
+ if (!e)
32
+ throw new Error(
33
+ "An encryption key (NEXTBLOCK_ENCRYPTION_KEY, CORTEX_AI_ENCRYPTION_KEY, or a Supabase service-role key) is required to manage stored OpenRouter keys."
34
+ );
35
+ return e;
36
+ }
37
+ function f(e) {
38
+ return o({
39
+ apiKey: e,
40
+ encryptionSecret: R()
41
+ });
42
+ }
43
+ function S(e) {
44
+ n();
45
+ const r = i(e);
46
+ if (r === null)
47
+ throw new Error("Failed to decrypt stored OpenRouter key.");
48
+ return r;
49
+ }
50
+ function v(e) {
51
+ return u(e);
52
+ }
53
+ function I() {
54
+ n();
55
+ const e = s();
56
+ return {
57
+ hasEnvOpenRouterKey: e.hasOpenRouterEnvKey,
58
+ maskedEnvOpenRouterKey: e.openRouterEnvKeyLast4 ? E(e.openRouterEnvKeyLast4) : null
59
+ };
60
+ }
61
+ export {
62
+ d as CORTEX_AI_OPENROUTER_MODEL_SELECTION_SETTING_KEY,
63
+ l as CORTEX_AI_OPENROUTER_SETTING_KEY,
64
+ a as CORTEX_AI_PACKAGE_ID,
65
+ A as CORTEX_AI_PACKAGE_NAME,
66
+ S as decryptStoredOpenRouterApiKey,
67
+ f as encryptStoredOpenRouterApiKey,
68
+ s as getCortexAiEnvConfig,
69
+ I as getEnvOpenRouterKeyStatus,
70
+ _ as getOpenRouterEnvApiKey,
71
+ v as getStoredOpenRouterKeyStatus
72
+ };
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const S=require("ai"),x=require("./ai-client.cjs.js"),o=require("./ai-model-registry.cjs.js"),r=require("./cortex-widget-schema.cjs.js"),f=6e4;function y(e){const t=o.getHttpStatusCode(e);if(t===401||t===402||t===403)return!1;if(o.isOpenRouterRecoverableRoutingError(e)||t&&t>=500)return!0;const n=e instanceof Error?e.message:String(e);return/NoObjectGenerated|No object generated|structured output|schema|validation|Invalid|aborted|abort|timeout|timed out/i.test(n)}async function I(e){const{apiKey:t,fallbackModelIds:n,modelId:c,modelSelection:m,...g}=e,a=r.cortexWidgetBuildRequestSchema.parse(g),i=await x.createCortexAiOpenRouterClient({apiKey:t,modelSelection:m}),d=o.buildCortexAiRoutingPolicy({credentialSource:i.credentialSource,fallbackModelIds:n,requestedModelId:c??a.modelId,selectedModel:i.modelSelection}),l=await o.runWithCortexAiModelFallback({modelIds:d.modelIds,shouldRetry:y,execute:async s=>{const u=new AbortController,p=setTimeout(()=>u.abort(),f);try{const b=o.omitUnsupportedCortexAiModelOptions({abortSignal:u.signal,maxOutputTokens:7e3,maxRetries:0,output:"no-schema",prompt:r.buildCortexWidgetBuilderPrompt(a),system:r.buildCortexWidgetBuilderSystemPrompt(),temperature:.15},{modelId:s,modelSelection:d.modelSelection}),C=await S.generateObject({...b,model:i.model(s)});return r.validateCortexWidgetDefinitionOutput(C.object)}finally{clearTimeout(p)}}});return{attempts:l.attempts,credentialSource:i.credentialSource,definition:l.result,modelId:l.modelId}}exports.generateCortexWidgetDefinition=I;
@@ -0,0 +1,14 @@
1
+ import { CortexAiModelAttempt, CortexAiOpenRouterModelId, CortexAiStoredModelSelection } from './ai-model-registry';
2
+ import { CortexWidgetDefinition, CortexWidgetBuildRequest } from './cortex-widget-schema';
3
+ export type GenerateCortexWidgetDefinitionResult = {
4
+ attempts: readonly CortexAiModelAttempt[];
5
+ credentialSource: 'env' | 'stored' | 'manual';
6
+ definition: CortexWidgetDefinition;
7
+ modelId: CortexAiOpenRouterModelId;
8
+ };
9
+ export declare function generateCortexWidgetDefinition(params: CortexWidgetBuildRequest & {
10
+ apiKey?: string;
11
+ fallbackModelIds?: readonly CortexAiOpenRouterModelId[];
12
+ modelId?: CortexAiOpenRouterModelId;
13
+ modelSelection?: CortexAiStoredModelSelection | null;
14
+ }): Promise<GenerateCortexWidgetDefinitionResult>;
@@ -0,0 +1,72 @@
1
+ import { generateObject as b } from "ai";
2
+ import { createCortexAiOpenRouterClient as f } from "./ai-client.es.js";
3
+ import { buildCortexAiRoutingPolicy as C, runWithCortexAiModelFallback as x, omitUnsupportedCortexAiModelOptions as S, getHttpStatusCode as I, isOpenRouterRecoverableRoutingError as y } from "./ai-model-registry.es.js";
4
+ import { cortexWidgetBuildRequestSchema as O, buildCortexWidgetBuilderSystemPrompt as R, buildCortexWidgetBuilderPrompt as T, validateCortexWidgetDefinitionOutput as W } from "./cortex-widget-schema.es.js";
5
+ const E = 6e4;
6
+ function M(e) {
7
+ const t = I(e);
8
+ if (t === 401 || t === 402 || t === 403)
9
+ return !1;
10
+ if (y(e) || t && t >= 500)
11
+ return !0;
12
+ const r = e instanceof Error ? e.message : String(e);
13
+ return /NoObjectGenerated|No object generated|structured output|schema|validation|Invalid|aborted|abort|timeout|timed out/i.test(
14
+ r
15
+ );
16
+ }
17
+ async function B(e) {
18
+ const { apiKey: t, fallbackModelIds: r, modelId: s, modelSelection: u, ...c } = e, n = O.parse(c), o = await f({ apiKey: t, modelSelection: u }), l = C({
19
+ credentialSource: o.credentialSource,
20
+ fallbackModelIds: r,
21
+ requestedModelId: s ?? n.modelId,
22
+ selectedModel: o.modelSelection
23
+ }), i = await x({
24
+ modelIds: l.modelIds,
25
+ shouldRetry: M,
26
+ execute: async (d) => {
27
+ const a = new AbortController(), m = setTimeout(
28
+ () => a.abort(),
29
+ E
30
+ );
31
+ try {
32
+ const p = S(
33
+ {
34
+ abortSignal: a.signal,
35
+ maxOutputTokens: 7e3,
36
+ maxRetries: 0,
37
+ // Use JSON mode WITHOUT a provider-side schema. The widget definition
38
+ // is a recursive, discriminated-union structure; sending it as a
39
+ // response_format json_schema is rejected by Google Gemini
40
+ // ("reference to undefined schema", recursion not supported) and by
41
+ // OpenAI ("'oneOf' is not permitted"). We instead describe the shape
42
+ // in the prompt and validate the returned JSON with our own Zod
43
+ // schema below, which works across every OpenRouter model.
44
+ output: "no-schema",
45
+ prompt: T(n),
46
+ system: R(),
47
+ temperature: 0.15
48
+ },
49
+ {
50
+ modelId: d,
51
+ modelSelection: l.modelSelection
52
+ }
53
+ ), g = await b({
54
+ ...p,
55
+ model: o.model(d)
56
+ });
57
+ return W(g.object);
58
+ } finally {
59
+ clearTimeout(m);
60
+ }
61
+ }
62
+ });
63
+ return {
64
+ attempts: i.attempts,
65
+ credentialSource: o.credentialSource,
66
+ definition: i.result,
67
+ modelId: i.modelId
68
+ };
69
+ }
70
+ export {
71
+ B as generateCortexWidgetDefinition
72
+ };
@@ -0,0 +1 @@
1
+ "use strict";var z=Object.create;var h=Object.defineProperty;var A=Object.getOwnPropertyDescriptor;var T=Object.getOwnPropertyNames;var U=Object.getPrototypeOf,D=Object.prototype.hasOwnProperty;var I=(e,t,s,i)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of T(t))!D.call(e,o)&&o!==s&&h(e,o,{get:()=>t[o],enumerable:!(i=A(t,o))||i.enumerable});return e};var L=(e,t,s)=>(s=e!=null?z(U(e)):{},I(t||!e||!e.__esModule?h(s,"default",{value:e,enumerable:!0}):s,e));Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const u=require("ai");require("./zod-config.cjs.js");const r=require("zod"),k="id, slug, name, description, fields, layout_schema, is_original",C=r.z.strictObject({context:r.z.string().trim().max(3e3).optional().describe("Optional extra constraints or brand/style guidance for the generated block."),prompt:r.z.string().trim().min(3).max(4e3).describe('Natural-language description of the custom block, including the fields it needs and the visual style. Example: "A product card with a title, image, price, and a button that links to the product page."')}),w=r.z.strictObject({prompt:r.z.string().trim().min(3).max(4e3).describe("Description of the changes to apply. The block is regenerated using its existing definition as context."),slug:r.z.string().trim().min(1).max(120).describe("Slug of the existing custom block to edit.")}),S=r.z.strictObject({slug:r.z.string().trim().min(1).max(120).describe("Slug of the custom block definition to delete.")}),_=r.z.strictObject({query:r.z.string().trim().max(120).optional().describe("Optional text filter on name or slug.")});function l(e){if(!e?.supabase)throw new Error("A Supabase service client is required to manage custom block definitions.");return e.supabase}function g(e){if(!e?.actorUserId)throw new Error("Managing custom block definitions requires an authenticated admin actor.");return e.actorUserId}function y(e){return JSON.parse(JSON.stringify(e))}function f(e){const t=Array.isArray(e?.fields)?e.fields:[];return{fieldCount:t.length,fields:t.map(s=>({key:s?.key,label:s?.label,type:s?.type})),id:e?.id,name:e?.name,slug:e?.slug}}function E(e,t){const s=t?.cortexAiApiKey||void 0;return{apiKey:s,context:e.context,modelSelection:s&&t?.cortexAiModelSelection?t.cortexAiModelSelection:void 0,prompt:e.prompt}}function p(e){try{const{revalidatePath:t,revalidateTag:s}=require("next/cache");s("custom-block-definitions","max"),e?.id&&s(`custom-block-definitions:${e.id}`,"max"),e?.slug&&s(`custom-block-definitions:${e.slug}`,"max"),s("dynamic-layout-engine","max"),t("/cms/custom-blocks"),t("/cms/blocks")}catch{}}function x(e){return(e||"").replace(/\s+/g," ").trim().toUpperCase()}function $(e){return`CONFIRM DELETE CUSTOM BLOCK ${e.toUpperCase()}`}function P(e,t){return e?.skipConfirmation?!0:x(e?.latestUserMessage).includes(x(t))}function m(e){if(e&&typeof e=="object"){const t=e;if(t.code==="23505")return"A custom block with that slug already exists. Choose a different name or edit the existing one.";if(typeof t.message=="string"&&t.message)return t.message}return e instanceof Error?e.message:"Unknown error."}async function B(e,t){try{const s=l(t);g(t);const[{generateCortexWidgetDefinition:i},{insertCortexWidgetDefinition:o}]=await Promise.all([Promise.resolve().then(()=>require("./ai-cortex-widget-builder.cjs.js")),Promise.resolve().then(()=>require("./cortex-widget-registry.cjs.js"))]),a=await i(E(e,t)),n=await o(s,a.definition);return p(n),{definition:f(n),editUrl:`/cms/custom-blocks/${n.id}/edit`,mutationExecuted:!0,success:!0}}catch(s){return{mutationExecuted:!1,message:m(s),success:!1}}}async function q(e,t){try{const s=l(t);g(t);const{data:i}=await s.from("custom_block_definitions").select(k).eq("slug",e.slug).maybeSingle();if(!i)return{mutationExecuted:!1,message:`No custom block found with slug "${e.slug}".`,success:!1};const[{generateCortexWidgetDefinition:o},{customBlockDefinitionCreateSchema:a}]=await Promise.all([Promise.resolve().then(()=>require("./ai-cortex-widget-builder.cjs.js")),import("@nextblock-cms/utils/custom-blocks")]),n=await o(E({context:`You are editing an existing custom block named "${i.name}". Keep its overall purpose and only apply the requested changes. Existing definition: ${JSON.stringify({fields:i.fields,layout_schema:i.layout_schema,name:i.name})}`,prompt:e.prompt},t)),c=a.parse({...n.definition,is_original:i.is_original,slug:i.slug}),{data:d,error:b}=await s.from("custom_block_definitions").update({description:c.description,fields:y(c.fields),layout_schema:y(c.layout_schema),name:c.name}).eq("id",i.id).select(k).single();return b||!d?{mutationExecuted:!1,message:b?.message??"Failed to update custom block.",success:!1}:(p(d),{definition:f(d),editUrl:`/cms/custom-blocks/${i.id}/edit`,mutationExecuted:!0,success:!0})}catch(s){return{mutationExecuted:!1,message:m(s),success:!1}}}async function O(e,t){try{const s=l(t);g(t);const{data:i}=await s.from("custom_block_definitions").select("id, slug, name").eq("slug",e.slug).maybeSingle();if(!i)return{mutationExecuted:!1,message:`No custom block found with slug "${e.slug}".`,success:!1};const o=$(i.slug);if(!P(t,o))return{confirmationPhrase:o,mutationExecuted:!1,preview:{summary:`Delete the custom block "${i.name}" (${i.slug}). Pages still using it will stop rendering it until replaced. This cannot be undone.`},requiresConfirmation:!0,success:!0};const{error:a}=await s.from("custom_block_definitions").delete().eq("id",i.id);return a?{mutationExecuted:!1,message:`Failed to delete custom block: ${a.message}`,success:!1}:(p(i),{deleted:{name:i.name,slug:i.slug},mutationExecuted:!0,success:!0})}catch(s){return{mutationExecuted:!1,message:m(s),success:!1}}}async function v(e,t){try{const s=l(t),{data:i,error:o}=await s.from("custom_block_definitions").select("id, slug, name, description, fields, is_original").order("name",{ascending:!0});if(o)return{message:o.message,success:!1};let a=Array.isArray(i)?i:[];if(e.query){const n=e.query.toLowerCase();a=a.filter(c=>String(c.name||"").toLowerCase().includes(n)||String(c.slug||"").toLowerCase().includes(n))}return{blocks:a.map(n=>f(n)),count:a.length,success:!0}}catch(s){return{message:m(s),success:!1}}}function M(e){return{create_custom_block:u.tool({description:'Create a brand-new reusable custom block definition from a natural-language description (for example "a product card with title, image, price, and a button linking to the product page"). This is a GLOBAL block-library builder and does NOT require an open page, post, or product. It generates the field schema and Tailwind layout and saves it so the block can be added to any page afterward. Additive and reversible; executes immediately without a confirmation phrase.',execute:t=>B(t,e),inputSchema:C,strict:!0}),delete_custom_block:u.tool({description:"Delete a custom block definition by slug. Mutating: first returns a confirmation phrase; only executes after the user replies with the exact phrase. Use list_custom_blocks first if you are unsure of the slug.",execute:t=>O(t,e),inputSchema:S,strict:!0}),list_custom_blocks:u.tool({description:"List the existing custom block definitions (slug, name, and fields). Read-only and does not require page context. Use it to find the slug of a block to edit or delete.",execute:t=>v(t,e),inputSchema:_,strict:!0}),update_custom_block:u.tool({description:"Edit an existing custom block definition (identified by slug) from a new natural-language description. The block is regenerated with its current definition as context and keeps its slug so existing placements keep working. Executes immediately.",execute:t=>q(t,e),inputSchema:w,strict:!0})}}exports.createCortexCustomBlockTools=M;exports.createCustomBlockInputSchema=C;exports.deleteCustomBlockInputSchema=S;exports.executeCreateCustomBlock=B;exports.executeDeleteCustomBlock=O;exports.executeListCustomBlocks=v;exports.executeUpdateCustomBlock=q;exports.listCustomBlocksInputSchema=_;exports.updateCustomBlockInputSchema=w;
@@ -0,0 +1,208 @@
1
+ import { z } from './zod-config';
2
+ type CustomBlockToolContext = {
3
+ actorUserId?: string | null;
4
+ cortexAiApiKey?: string | null;
5
+ cortexAiModelSelection?: unknown;
6
+ latestUserMessage?: string | null;
7
+ skipConfirmation?: boolean;
8
+ supabase?: {
9
+ from: (table: string) => any;
10
+ };
11
+ };
12
+ export declare const createCustomBlockInputSchema: z.ZodObject<{
13
+ context: z.ZodOptional<z.ZodString>;
14
+ prompt: z.ZodString;
15
+ }, z.core.$strict>;
16
+ export declare const updateCustomBlockInputSchema: z.ZodObject<{
17
+ prompt: z.ZodString;
18
+ slug: z.ZodString;
19
+ }, z.core.$strict>;
20
+ export declare const deleteCustomBlockInputSchema: z.ZodObject<{
21
+ slug: z.ZodString;
22
+ }, z.core.$strict>;
23
+ export declare const listCustomBlocksInputSchema: z.ZodObject<{
24
+ query: z.ZodOptional<z.ZodString>;
25
+ }, z.core.$strict>;
26
+ export declare function executeCreateCustomBlock(input: z.infer<typeof createCustomBlockInputSchema>, context?: CustomBlockToolContext): Promise<{
27
+ definition: {
28
+ fieldCount: any;
29
+ fields: any;
30
+ id: any;
31
+ name: any;
32
+ slug: any;
33
+ };
34
+ editUrl: string;
35
+ mutationExecuted: boolean;
36
+ success: boolean;
37
+ message?: undefined;
38
+ } | {
39
+ mutationExecuted: boolean;
40
+ message: string;
41
+ success: boolean;
42
+ definition?: undefined;
43
+ editUrl?: undefined;
44
+ }>;
45
+ export declare function executeUpdateCustomBlock(input: z.infer<typeof updateCustomBlockInputSchema>, context?: CustomBlockToolContext): Promise<{
46
+ mutationExecuted: boolean;
47
+ message: any;
48
+ success: boolean;
49
+ definition?: undefined;
50
+ editUrl?: undefined;
51
+ } | {
52
+ definition: {
53
+ fieldCount: any;
54
+ fields: any;
55
+ id: any;
56
+ name: any;
57
+ slug: any;
58
+ };
59
+ editUrl: string;
60
+ mutationExecuted: boolean;
61
+ success: boolean;
62
+ message?: undefined;
63
+ }>;
64
+ export declare function executeDeleteCustomBlock(input: z.infer<typeof deleteCustomBlockInputSchema>, context?: CustomBlockToolContext): Promise<{
65
+ mutationExecuted: boolean;
66
+ message: string;
67
+ success: boolean;
68
+ confirmationPhrase?: undefined;
69
+ preview?: undefined;
70
+ requiresConfirmation?: undefined;
71
+ deleted?: undefined;
72
+ } | {
73
+ confirmationPhrase: string;
74
+ mutationExecuted: boolean;
75
+ preview: {
76
+ summary: string;
77
+ };
78
+ requiresConfirmation: boolean;
79
+ success: boolean;
80
+ message?: undefined;
81
+ deleted?: undefined;
82
+ } | {
83
+ deleted: {
84
+ name: any;
85
+ slug: any;
86
+ };
87
+ mutationExecuted: boolean;
88
+ success: boolean;
89
+ message?: undefined;
90
+ confirmationPhrase?: undefined;
91
+ preview?: undefined;
92
+ requiresConfirmation?: undefined;
93
+ }>;
94
+ export declare function executeListCustomBlocks(input: z.infer<typeof listCustomBlocksInputSchema>, context?: CustomBlockToolContext): Promise<{
95
+ message: any;
96
+ success: boolean;
97
+ blocks?: undefined;
98
+ count?: undefined;
99
+ } | {
100
+ blocks: {
101
+ fieldCount: any;
102
+ fields: any;
103
+ id: any;
104
+ name: any;
105
+ slug: any;
106
+ }[];
107
+ count: number;
108
+ success: boolean;
109
+ message?: undefined;
110
+ }>;
111
+ export declare function createCortexCustomBlockTools(context?: CustomBlockToolContext): {
112
+ create_custom_block: import('ai').Tool<{
113
+ prompt: string;
114
+ context?: string | undefined;
115
+ }, {
116
+ definition: {
117
+ fieldCount: any;
118
+ fields: any;
119
+ id: any;
120
+ name: any;
121
+ slug: any;
122
+ };
123
+ editUrl: string;
124
+ mutationExecuted: boolean;
125
+ success: boolean;
126
+ message?: undefined;
127
+ } | {
128
+ mutationExecuted: boolean;
129
+ message: string;
130
+ success: boolean;
131
+ definition?: undefined;
132
+ editUrl?: undefined;
133
+ }>;
134
+ delete_custom_block: import('ai').Tool<{
135
+ slug: string;
136
+ }, {
137
+ mutationExecuted: boolean;
138
+ message: string;
139
+ success: boolean;
140
+ confirmationPhrase?: undefined;
141
+ preview?: undefined;
142
+ requiresConfirmation?: undefined;
143
+ deleted?: undefined;
144
+ } | {
145
+ confirmationPhrase: string;
146
+ mutationExecuted: boolean;
147
+ preview: {
148
+ summary: string;
149
+ };
150
+ requiresConfirmation: boolean;
151
+ success: boolean;
152
+ message?: undefined;
153
+ deleted?: undefined;
154
+ } | {
155
+ deleted: {
156
+ name: any;
157
+ slug: any;
158
+ };
159
+ mutationExecuted: boolean;
160
+ success: boolean;
161
+ message?: undefined;
162
+ confirmationPhrase?: undefined;
163
+ preview?: undefined;
164
+ requiresConfirmation?: undefined;
165
+ }>;
166
+ list_custom_blocks: import('ai').Tool<{
167
+ query?: string | undefined;
168
+ }, {
169
+ message: any;
170
+ success: boolean;
171
+ blocks?: undefined;
172
+ count?: undefined;
173
+ } | {
174
+ blocks: {
175
+ fieldCount: any;
176
+ fields: any;
177
+ id: any;
178
+ name: any;
179
+ slug: any;
180
+ }[];
181
+ count: number;
182
+ success: boolean;
183
+ message?: undefined;
184
+ }>;
185
+ update_custom_block: import('ai').Tool<{
186
+ prompt: string;
187
+ slug: string;
188
+ }, {
189
+ mutationExecuted: boolean;
190
+ message: any;
191
+ success: boolean;
192
+ definition?: undefined;
193
+ editUrl?: undefined;
194
+ } | {
195
+ definition: {
196
+ fieldCount: any;
197
+ fields: any;
198
+ id: any;
199
+ name: any;
200
+ slug: any;
201
+ };
202
+ editUrl: string;
203
+ mutationExecuted: boolean;
204
+ success: boolean;
205
+ message?: undefined;
206
+ }>;
207
+ };
208
+ export {};
@@ -0,0 +1,220 @@
1
+ import { tool as u } from "ai";
2
+ import "./zod-config.es.js";
3
+ import { z as n } from "zod";
4
+ const h = "id, slug, name, description, fields, layout_schema, is_original", C = n.strictObject({
5
+ context: n.string().trim().max(3e3).optional().describe("Optional extra constraints or brand/style guidance for the generated block."),
6
+ prompt: n.string().trim().min(3).max(4e3).describe(
7
+ 'Natural-language description of the custom block, including the fields it needs and the visual style. Example: "A product card with a title, image, price, and a button that links to the product page."'
8
+ )
9
+ }), w = n.strictObject({
10
+ prompt: n.string().trim().min(3).max(4e3).describe("Description of the changes to apply. The block is regenerated using its existing definition as context."),
11
+ slug: n.string().trim().min(1).max(120).describe("Slug of the existing custom block to edit.")
12
+ }), _ = n.strictObject({
13
+ slug: n.string().trim().min(1).max(120).describe("Slug of the custom block definition to delete.")
14
+ }), S = n.strictObject({
15
+ query: n.string().trim().max(120).optional().describe("Optional text filter on name or slug.")
16
+ });
17
+ function l(e) {
18
+ if (!e?.supabase)
19
+ throw new Error("A Supabase service client is required to manage custom block definitions.");
20
+ return e.supabase;
21
+ }
22
+ function g(e) {
23
+ if (!e?.actorUserId)
24
+ throw new Error("Managing custom block definitions requires an authenticated admin actor.");
25
+ return e.actorUserId;
26
+ }
27
+ function k(e) {
28
+ return JSON.parse(JSON.stringify(e));
29
+ }
30
+ function f(e) {
31
+ const t = Array.isArray(e?.fields) ? e.fields : [];
32
+ return {
33
+ fieldCount: t.length,
34
+ fields: t.map((s) => ({ key: s?.key, label: s?.label, type: s?.type })),
35
+ id: e?.id,
36
+ name: e?.name,
37
+ slug: e?.slug
38
+ };
39
+ }
40
+ function x(e, t) {
41
+ const s = t?.cortexAiApiKey || void 0;
42
+ return {
43
+ apiKey: s,
44
+ context: e.context,
45
+ modelSelection: s && t?.cortexAiModelSelection ? t.cortexAiModelSelection : void 0,
46
+ prompt: e.prompt
47
+ };
48
+ }
49
+ function p(e) {
50
+ try {
51
+ const { revalidatePath: t, revalidateTag: s } = require("next/cache");
52
+ s("custom-block-definitions", "max"), e?.id && s(`custom-block-definitions:${e.id}`, "max"), e?.slug && s(`custom-block-definitions:${e.slug}`, "max"), s("dynamic-layout-engine", "max"), t("/cms/custom-blocks"), t("/cms/blocks");
53
+ } catch {
54
+ }
55
+ }
56
+ function y(e) {
57
+ return (e || "").replace(/\s+/g, " ").trim().toUpperCase();
58
+ }
59
+ function E(e) {
60
+ return `CONFIRM DELETE CUSTOM BLOCK ${e.toUpperCase()}`;
61
+ }
62
+ function q(e, t) {
63
+ return e?.skipConfirmation ? !0 : y(e?.latestUserMessage).includes(y(t));
64
+ }
65
+ function m(e) {
66
+ if (e && typeof e == "object") {
67
+ const t = e;
68
+ if (t.code === "23505")
69
+ return "A custom block with that slug already exists. Choose a different name or edit the existing one.";
70
+ if (typeof t.message == "string" && t.message)
71
+ return t.message;
72
+ }
73
+ return e instanceof Error ? e.message : "Unknown error.";
74
+ }
75
+ async function O(e, t) {
76
+ try {
77
+ const s = l(t);
78
+ g(t);
79
+ const [{ generateCortexWidgetDefinition: i }, { insertCortexWidgetDefinition: r }] = await Promise.all([
80
+ import("./ai-cortex-widget-builder.es.js"),
81
+ import("./cortex-widget-registry.es.js")
82
+ ]), o = await i(x(e, t)), a = await r(s, o.definition);
83
+ return p(a), {
84
+ definition: f(a),
85
+ editUrl: `/cms/custom-blocks/${a.id}/edit`,
86
+ mutationExecuted: !0,
87
+ success: !0
88
+ };
89
+ } catch (s) {
90
+ return { mutationExecuted: !1, message: m(s), success: !1 };
91
+ }
92
+ }
93
+ async function A(e, t) {
94
+ try {
95
+ const s = l(t);
96
+ g(t);
97
+ const { data: i } = await s.from("custom_block_definitions").select(h).eq("slug", e.slug).maybeSingle();
98
+ if (!i)
99
+ return { mutationExecuted: !1, message: `No custom block found with slug "${e.slug}".`, success: !1 };
100
+ const [{ generateCortexWidgetDefinition: r }, { customBlockDefinitionCreateSchema: o }] = await Promise.all([
101
+ import("./ai-cortex-widget-builder.es.js"),
102
+ import("@nextblock-cms/utils/custom-blocks")
103
+ ]), a = await r(
104
+ x(
105
+ {
106
+ context: `You are editing an existing custom block named "${i.name}". Keep its overall purpose and only apply the requested changes. Existing definition: ${JSON.stringify(
107
+ { fields: i.fields, layout_schema: i.layout_schema, name: i.name }
108
+ )}`,
109
+ prompt: e.prompt
110
+ },
111
+ t
112
+ )
113
+ ), c = o.parse({
114
+ ...a.definition,
115
+ is_original: i.is_original,
116
+ slug: i.slug
117
+ }), { data: d, error: b } = await s.from("custom_block_definitions").update({
118
+ description: c.description,
119
+ fields: k(c.fields),
120
+ layout_schema: k(c.layout_schema),
121
+ name: c.name
122
+ }).eq("id", i.id).select(h).single();
123
+ return b || !d ? { mutationExecuted: !1, message: b?.message ?? "Failed to update custom block.", success: !1 } : (p(d), {
124
+ definition: f(d),
125
+ editUrl: `/cms/custom-blocks/${i.id}/edit`,
126
+ mutationExecuted: !0,
127
+ success: !0
128
+ });
129
+ } catch (s) {
130
+ return { mutationExecuted: !1, message: m(s), success: !1 };
131
+ }
132
+ }
133
+ async function B(e, t) {
134
+ try {
135
+ const s = l(t);
136
+ g(t);
137
+ const { data: i } = await s.from("custom_block_definitions").select("id, slug, name").eq("slug", e.slug).maybeSingle();
138
+ if (!i)
139
+ return { mutationExecuted: !1, message: `No custom block found with slug "${e.slug}".`, success: !1 };
140
+ const r = E(i.slug);
141
+ if (!q(t, r))
142
+ return {
143
+ confirmationPhrase: r,
144
+ mutationExecuted: !1,
145
+ preview: {
146
+ summary: `Delete the custom block "${i.name}" (${i.slug}). Pages still using it will stop rendering it until replaced. This cannot be undone.`
147
+ },
148
+ requiresConfirmation: !0,
149
+ success: !0
150
+ };
151
+ const { error: o } = await s.from("custom_block_definitions").delete().eq("id", i.id);
152
+ return o ? { mutationExecuted: !1, message: `Failed to delete custom block: ${o.message}`, success: !1 } : (p(i), {
153
+ deleted: { name: i.name, slug: i.slug },
154
+ mutationExecuted: !0,
155
+ success: !0
156
+ });
157
+ } catch (s) {
158
+ return { mutationExecuted: !1, message: m(s), success: !1 };
159
+ }
160
+ }
161
+ async function U(e, t) {
162
+ try {
163
+ const s = l(t), { data: i, error: r } = await s.from("custom_block_definitions").select("id, slug, name, description, fields, is_original").order("name", { ascending: !0 });
164
+ if (r)
165
+ return { message: r.message, success: !1 };
166
+ let o = Array.isArray(i) ? i : [];
167
+ if (e.query) {
168
+ const a = e.query.toLowerCase();
169
+ o = o.filter(
170
+ (c) => String(c.name || "").toLowerCase().includes(a) || String(c.slug || "").toLowerCase().includes(a)
171
+ );
172
+ }
173
+ return {
174
+ blocks: o.map((a) => f(a)),
175
+ count: o.length,
176
+ success: !0
177
+ };
178
+ } catch (s) {
179
+ return { message: m(s), success: !1 };
180
+ }
181
+ }
182
+ function $(e) {
183
+ return {
184
+ create_custom_block: u({
185
+ description: 'Create a brand-new reusable custom block definition from a natural-language description (for example "a product card with title, image, price, and a button linking to the product page"). This is a GLOBAL block-library builder and does NOT require an open page, post, or product. It generates the field schema and Tailwind layout and saves it so the block can be added to any page afterward. Additive and reversible; executes immediately without a confirmation phrase.',
186
+ execute: (t) => O(t, e),
187
+ inputSchema: C,
188
+ strict: !0
189
+ }),
190
+ delete_custom_block: u({
191
+ description: "Delete a custom block definition by slug. Mutating: first returns a confirmation phrase; only executes after the user replies with the exact phrase. Use list_custom_blocks first if you are unsure of the slug.",
192
+ execute: (t) => B(t, e),
193
+ inputSchema: _,
194
+ strict: !0
195
+ }),
196
+ list_custom_blocks: u({
197
+ description: "List the existing custom block definitions (slug, name, and fields). Read-only and does not require page context. Use it to find the slug of a block to edit or delete.",
198
+ execute: (t) => U(t, e),
199
+ inputSchema: S,
200
+ strict: !0
201
+ }),
202
+ update_custom_block: u({
203
+ description: "Edit an existing custom block definition (identified by slug) from a new natural-language description. The block is regenerated with its current definition as context and keeps its slug so existing placements keep working. Executes immediately.",
204
+ execute: (t) => A(t, e),
205
+ inputSchema: w,
206
+ strict: !0
207
+ })
208
+ };
209
+ }
210
+ export {
211
+ $ as createCortexCustomBlockTools,
212
+ C as createCustomBlockInputSchema,
213
+ _ as deleteCustomBlockInputSchema,
214
+ O as executeCreateCustomBlock,
215
+ B as executeDeleteCustomBlock,
216
+ U as executeListCustomBlocks,
217
+ A as executeUpdateCustomBlock,
218
+ S as listCustomBlocksInputSchema,
219
+ w as updateCustomBlockInputSchema
220
+ };