@nextblock-cms/cortex 0.12.13 → 0.12.15
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.
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const v=require("ai");require("./zod-config.cjs.js");const n=require("zod"),G=100,W=20,k=100,z=20,R="[REDACTED]",g="cortex_ai_openrouter_api_key",j={blocks:{columns:["id","page_id","post_id","language_id","block_type","content","order","created_at","updated_at"],description:"CMS page/post content blocks.",primaryKey:["id"]},coupon_freemius_mappings:{columns:["id","coupon_id","product_id","freemius_product_id","freemius_coupon_id","freemius_coupon_code","sync_status","sync_error","remote_payload","last_synced_at","created_at","updated_at"],description:"Freemius coupon sync mappings.",primaryKey:["id"]},coupon_products:{columns:["coupon_id","product_id","created_at"],description:"Coupon product allow-list rows.",primaryKey:["coupon_id","product_id"]},coupon_redemptions:{columns:["id","coupon_id","order_id","coupon_code","provider","discount_total","user_id","customer_email","metadata","redeemed_at"],description:"Coupon redemption records.",primaryKey:["id"]},coupons:{columns:["id","code","name","internal_note","provider_scope","discount_type","discount_amount","is_active","starts_at","ends_at","redemption_limit","redemptions_count","freemius_sync_status","freemius_sync_error","created_at","updated_at"],description:"Commerce coupons.",primaryKey:["id"]},cortex_ai_db_mutation_audit:{columns:["id","actor_user_id","tool_name","action_name","target_tables","operation_summary","payload_hash","payload","preview","status","error_message","created_at"],description:"Read-only Cortex AI database mutation audit trail.",primaryKey:["id"],readOnly:!0},currencies:{columns:["id","code","symbol","exchange_rate","is_default","is_active","rounding_mode","rounding_increment","rounding_charm_amount","auto_update_exchange_rate","exchange_rate_updated_at","exchange_rate_source","auto_sync_product_prices","created_at","updated_at"],description:"Storefront currencies and FX settings.",primaryKey:["id"]},freemius_plans:{columns:["id","product_id","name","title","created_at","updated_at"],description:"Freemius plan metadata.",primaryKey:["id"]},freemius_pricing:{columns:["id","plan_id","api_monthly_price","api_annual_price","api_lifetime_price","override_monthly_price","override_annual_price","override_lifetime_price","license_quota","is_active","created_at","updated_at"],description:"Freemius pricing metadata.",primaryKey:["id"]},inventory_items:{columns:["sku","quantity","created_at","updated_at"],description:"Source-of-truth inventory by SKU.",primaryKey:["sku"]},languages:{columns:["id","code","name","is_default","is_active","created_at","updated_at"],description:"CMS languages/locales.",primaryKey:["id"]},logos:{columns:["id","name","media_id","created_at"],description:"Brand logos.",primaryKey:["id"]},media:{columns:["id","uploader_id","file_name","object_key","file_type","size_bytes","description","width","height","blur_data_url","variants","file_path","folder","created_at","updated_at"],description:"Media metadata for uploaded assets.",primaryKey:["id"]},navigation_items:{columns:["id","language_id","menu_key","label","url","parent_id","order","page_id","translation_group_id","created_at","updated_at"],description:"CMS navigation tree items.",primaryKey:["id"]},order_items:{columns:["id","order_id","product_id","variant_id","quantity","price_at_purchase"],description:"Commerce order line items.",primaryKey:["id"]},orders:{columns:["id","user_id","status","total","stripe_session_id","payment_intent_id","customer_details","provider","freemius_product_id","freemius_plan_id","freemius_license_id","freemius_subscription_id","freemius_trial_id","freemius_user_id","freemius_trial_ends_at","freemius_last_event_type","freemius_last_synced_at","currency","subtotal","shipping_total","tax_total","tax_details","exchange_rate_at_purchase","inventory_deducted_at","invoice_number","paid_at","created_at","coupon_id","coupon_code","discount_total","discount_details"],description:"Commerce orders.",primaryKey:["id"]},package_activations:{columns:["id","license_key","instance_name","package_id","status","meta","last_validated_at","created_at"],description:"NextBlock package activations.",primaryKey:["id"]},page_revisions:{columns:["id","page_id","author_id","version","revision_type","content","created_at"],description:"Page revision history.",primaryKey:["id"]},pages:{columns:["id","language_id","author_id","title","slug","status","meta_title","meta_description","feature_image_id","version","translation_group_id","created_at","updated_at"],description:"CMS pages.",primaryKey:["id"]},post_revisions:{columns:["id","post_id","author_id","version","revision_type","content","created_at"],description:"Post revision history.",primaryKey:["id"]},posts:{columns:["id","language_id","author_id","title","slug","label","excerpt","subtitle","status","published_at","meta_title","meta_description","feature_image_id","version","translation_group_id","created_at","updated_at"],description:"CMS posts/articles.",primaryKey:["id"]},product_attribute_terms:{columns:["id","attribute_id","value","slug","sort_order","value_translations","created_at","updated_at"],description:"Product attribute terms.",primaryKey:["id"]},product_attributes:{columns:["id","name","slug","name_translations","created_at","updated_at"],description:"Product attribute definitions.",primaryKey:["id"]},product_media:{columns:["product_id","media_id","sort_order"],description:"Product media join rows.",primaryKey:["product_id","media_id"]},product_variants:{columns:["id","product_id","sku","price_adjustment","price","prices","sale_price","sale_prices","stock_quantity","upc","main_media_id","created_at","updated_at"],description:"Sellable product variants.",primaryKey:["id"]},products:{columns:["id","language_id","translation_group_id","sku","title","slug","product_type","payment_provider","price","prices","sale_price","sale_prices","stock","status","meta_title","meta_description","short_description","description_json","metadata","freemius_plan_id","freemius_product_id","trial_period_days","trial_requires_payment_method","upc","is_taxable","created_at","updated_at"],description:"Product catalog records.",primaryKey:["id"]},profiles:{columns:["id","updated_at","full_name","avatar_url","website","github_username","phone","role"],description:"Read-only user profiles. Never mutate through Cortex AI.",primaryKey:["id"],readOnly:!0},shipping_zone_locations:{columns:["id","zone_id","country_code","state_code","postal_code","created_at"],description:"Shipping zone location match rules.",primaryKey:["id"]},shipping_zone_methods:{columns:["id","zone_id","method_type","cost_amount","cost_currency","min_order_amount","name","name_translations","currency_pricing_mode","cost_amounts","min_order_amounts","created_at","updated_at"],description:"Shipping methods/rates.",primaryKey:["id"]},shipping_zones:{columns:["id","name","priority_order","created_at","updated_at"],description:"Shipping zones.",primaryKey:["id"]},site_settings:{columns:["key","value"],description:"Global site settings. Cortex AI API-key setting row is protected.",primaryKey:["key"]},tax_rates:{columns:["id","country_code","state_code","tax_name","tax_rate","created_at","updated_at"],description:"Manual tax rates.",primaryKey:["id"]},translations:{columns:["key","translations","created_at","updated_at"],description:"Shared translation strings.",primaryKey:["key"]},user_addresses:{columns:["id","user_id","address_type","is_default","recipient_name","company_name","line1","line2","city","state","postal_code","country_code","created_at","updated_at"],description:"Read-only user addresses. Never mutate through Cortex AI.",primaryKey:["id"],readOnly:!0},variant_attribute_mapping:{columns:["variant_id","attribute_term_id"],description:"Variant to attribute-term join rows.",primaryKey:["variant_id","attribute_term_id"]}},Y=n.z.enum(["eq","neq","gt","gte","lt","lte","ilike","in","is"]),N=n.z.strictObject({column:n.z.string().trim().min(1).max(120),operator:Y.default("eq"),value:n.z.unknown()}),H=n.z.strictObject({ascending:n.z.boolean().default(!0),column:n.z.string().trim().min(1).max(120)}),O=n.z.strictObject({includeReadOnly:n.z.boolean().default(!0),table:n.z.string().trim().min(1).max(120).optional()}),T=n.z.strictObject({columns:n.z.array(n.z.string().trim().min(1).max(120)).min(1).max(40).optional(),filters:n.z.array(N).max(12).default([]),limit:n.z.number().int().min(1).max(G).default(W),offset:n.z.number().int().min(0).max(1e4).default(0),orderBy:H.optional(),table:n.z.string().trim().min(1).max(120)}),S=n.z.strictObject({filters:n.z.array(N).max(12).optional(),operation:n.z.enum(["delete","insert","update","upsert"]),rows:n.z.array(n.z.record(n.z.string(),n.z.unknown())).min(1).max(z).optional(),summary:n.z.string().trim().min(1).max(500).optional(),table:n.z.string().trim().min(1).max(120),values:n.z.record(n.z.string(),n.z.unknown()).optional()}),D=n.z.strictObject({actions:n.z.array(S).min(1).max(8),summary:n.z.string().trim().min(1).max(500).optional()});function E(e){if(!e?.supabase)throw new Error("Cortex AI database tools require a Supabase client.");return e.supabase}function f(e){return e?typeof e=="object"&&"message"in e?String(e.message||"Unknown database error."):String(e):"Unknown database error."}function K(e){return e===null||typeof e!="object"?JSON.stringify(e):Array.isArray(e)?`[${e.map(t=>K(t)).join(",")}]`:`{${Object.keys(e).sort().map(t=>`${JSON.stringify(t)}:${K(e[t])}`).join(",")}}`}function L(e){let t=2166136261;const a=K(e);for(let r=0;r<a.length;r++)t^=a.charCodeAt(r),t=Math.imul(t,16777619);return(t>>>0).toString(16).padStart(8,"0")}function I(e){return e.replace(/\s+/g," ").trim().toUpperCase()}function Z(e,t,a){return`${I(`CONFIRM ${e} ${t}`)} #${L(a)}`}function ee(e){return{confirmationPhrase:Z(e.action,e.subject,e.payload),mutationExecuted:!1,preview:e.preview,requiresConfirmation:!0,success:!0}}function q(e){if(e.context?.skipConfirmation)return null;const t=ee(e),a=I(e.context?.latestUserMessage||""),r=I(t.confirmationPhrase);return a&&!a.includes(r)?{...t,message:"The database target changed or the confirmation did not match. Please review and confirm again."}:a.includes(r)?null:t}function te(e){return Object.prototype.hasOwnProperty.call(j,e)}function M(e){const t=e.trim();if(t.includes(".")||t.toLowerCase().startsWith("auth"))throw new Error("Cortex AI cannot access auth schema tables.");if(!te(t))throw new Error(`Table "${t}" is not available to Cortex AI database tools.`);return t}function _(e){return j[e]}function w(e){return/(?:password|token|secret|api[_-]?key|private[_-]?key|credential)/i.test(e)}function b(e,t){if(!_(e).columns.includes(t))throw new Error(`Column "${t}" is not available on table "${e}".`);if(w(t))throw new Error(`Column "${t}" is protected and cannot be used through Cortex AI.`)}function $(e,t="payload"){if(Array.isArray(e)){e.forEach((a,r)=>$(a,`${t}[${r}]`));return}if(!(!e||typeof e!="object"))for(const[a,r]of Object.entries(e)){if(w(a))throw new Error(`Protected field "${t}.${a}" cannot be written through Cortex AI.`);$(r,`${t}.${a}`)}}function h(e){if(Array.isArray(e))return e.map(a=>h(a));if(!e||typeof e!="object")return e;const t={};for(const[a,r]of Object.entries(e))t[a]=w(a)?R:h(r);return t}function ae(e){return e.map(t=>t&&typeof t=="object"&&!Array.isArray(t)&&t.key===g?{key:g,value:R}:h(t))}function re(e,t){if(e!=="site_settings")return;if(JSON.stringify(t).toLowerCase().includes(g))throw new Error("The Cortex AI OpenRouter API key site setting is protected.")}function ie(e,t){switch(t.operator){case"eq":return e.eq(t.column,t.value);case"neq":return e.neq(t.column,t.value);case"gt":return e.gt(t.column,t.value);case"gte":return e.gte(t.column,t.value);case"lt":return e.lt(t.column,t.value);case"lte":return e.lte(t.column,t.value);case"ilike":if(typeof t.value!="string")throw new Error(`Filter "${t.column}" with ilike requires a string value.`);return e.ilike(t.column,t.value);case"in":if(!Array.isArray(t.value))throw new Error(`Filter "${t.column}" with in requires an array value.`);return e.in(t.column,t.value);case"is":return e.is(t.column,t.value)}}function x(e,t,a){let r=t;for(const o of a)b(e,o.column),r=ie(r,o);return e==="site_settings"&&(r=r.neq("key",g)),r}function oe(e,t){const a=_(e),r=t?.length?t:a.columns.filter(o=>!w(o));return r.forEach(o=>b(e,o)),r.join(",")}function F(e,t){return t.map(a=>`${a}=${String(e[a]??"")}`).join("|")}async function U(e,t,a){const r=_(t);let o=e.from(t).select(r.primaryKey.join(",")).limit(k+1);o=x(t,o,a);const{data:i,error:s}=await o;if(s)throw new Error(`Failed to preview database mutation: ${f(s)}`);const d=Array.isArray(i)?i:[];if(d.length>k)throw new Error(`Refusing to mutate more than ${k} rows.`);return d}function B(e){const t=M(e.table),a=_(t),r=e.operation;if(a.readOnly)throw new Error(`Table "${t}" is read-only for Cortex AI.`);if(re(t,e),(r==="update"||r==="delete")&&(!e.filters||e.filters.length===0))throw new Error(`${r} operations require at least one filter.`);if((r==="insert"||r==="upsert")&&(!e.rows||e.rows.length===0))throw new Error(`${r} operations require rows.`);if(r==="update"&&(!e.values||Object.keys(e.values).length===0))throw new Error("update operations require values.");if(e.rows&&e.rows.length>z)throw new Error(`Refusing to mutate more than ${z} input rows.`);const o=e.rows??(e.values?[e.values]:[]);for(const i of o){$(i);for(const s of Object.keys(i))b(t,s)}for(const i of e.filters??[])b(t,i.column);return t}function X(e){const{input:t,table:a,targetRows:r}=e,o=_(a),i=r.map(m=>F(m,o.primaryKey)).sort(),s=t.rows?.length??0,d=t.operation==="insert"||t.operation==="upsert"?s:r.length,l=t.summary||`${t.operation} ${d} ${d===1?"row":"rows"} in ${a}.`;return{affectedCount:d,operation:t.operation,sampleTargetIds:i.slice(0,10),summary:l,table:a,targetIds:i}}async function A(e){const t=e.context?.actorUserId;if(!t)return{auditError:"Missing actor user id.",auditLogged:!1};try{const{error:a}=await E(e.context).from("cortex_ai_db_mutation_audit").insert({action_name:e.toolName,actor_user_id:t,error_message:e.errorMessage??null,operation_summary:e.summary,payload:h(e.input),payload_hash:L(e.input),preview:h(e.preview),status:e.status,target_tables:e.targetTables,tool_name:e.toolName});return a?{auditError:f(a),auditLogged:!1}:{auditLogged:!0}}catch(a){return{auditError:f(a),auditLogged:!1}}}async function ne(e,t,a){const o=_(t).primaryKey.join(",");let i;e.operation==="insert"?i=a.from(t).insert(e.rows).select(o):e.operation==="upsert"?i=a.from(t).upsert(e.rows).select(o):e.operation==="update"?(i=a.from(t).update(e.values),i=x(t,i,e.filters??[]),i=i.select(o)):(i=a.from(t).delete(),i=x(t,i,e.filters??[]),i=i.select(o));const{data:s,error:d}=await i;if(d)throw new Error(f(d));return Array.isArray(s)?s:[]}async function V(e){const t=O.parse(e),r=(t.table?[M(t.table)]:Object.keys(j)).filter(o=>t.includeReadOnly||!_(o).readOnly).map(o=>{const i=_(o);return{columns:i.columns.filter(s=>!w(s)),description:i.description,primaryKey:i.primaryKey,readOnly:!!i.readOnly,table:o}});return{safetyNotes:["Use read_database_records for reads and execute_database_mutation/action_plan for writes.","No auth schema access, no arbitrary SQL, no password/secret/API-key fields.","profiles, user_addresses, and cortex_ai_db_mutation_audit are read-only.",`site_settings.${g} is protected.`],success:!0,tables:r}}async function J(e,t){const a=T.parse(e),r=M(a.table),o=oe(r,a.columns);let i=E(t).from(r).select(o).range(a.offset,a.offset+a.limit-1);i=x(r,i,a.filters),a.orderBy&&(b(r,a.orderBy.column),i=i.order(a.orderBy.column,{ascending:a.orderBy.ascending}));const{data:s,error:d}=await i;if(d)throw new Error(`Failed to read database records: ${f(d)}`);const l=Array.isArray(s)?s:[];return{columns:o.split(","),limit:a.limit,offset:a.offset,rows:ae(l),success:!0,table:r}}async function P(e,t){const a=S.parse(e),r=B(a),o=E(t),i=a.operation==="update"||a.operation==="delete"?await U(o,r,a.filters??[]):[],s=X({input:a,table:r,targetRows:i}),d={input:a,targetIds:s.targetIds},l=q({action:`DATABASE ${a.operation}`,context:t,payload:d,preview:s,subject:r});if(l)return l;try{const m=await ne(a,r,o),p=t?.skipAudit?{auditLogged:!1}:await A({context:t,input:d,preview:s,status:"success",summary:String(s.summary),targetTables:[r],toolName:"execute_database_mutation"});return{affectedCount:m.length||s.affectedCount,auditLogged:p.auditLogged,...p.auditError?{auditError:p.auditError}:{},mutationExecuted:!0,operation:a.operation,sampleTargetIds:m.map(c=>F(c,_(r).primaryKey)).slice(0,10),success:!0,summary:s.summary,table:r}}catch(m){const p=f(m),c=t?.skipAudit?{auditLogged:!1}:await A({context:t,errorMessage:p,input:d,preview:s,status:"failure",summary:String(s.summary),targetTables:[r],toolName:"execute_database_mutation"});return{auditLogged:c.auditLogged,...c.auditError?{auditError:c.auditError}:{},message:`Database mutation failed: ${p}`,mutationExecuted:!1,operation:a.operation,success:!1,table:r}}}async function Q(e,t){const a=D.parse(e),r=[];for(const c of a.actions){const y=B(c),u=c.operation==="update"||c.operation==="delete"?await U(E(t),y,c.filters??[]):[];r.push({input:c,preview:X({input:c,table:y,targetRows:u}),table:y})}const o=r.map(({preview:c})=>String(c.summary)),i={actionCount:r.length,actionSummaries:o,summary:a.summary||`Run ${r.length} confirmed database actions.`,tables:Array.from(new Set(r.map(c=>c.table)))},s=r.map(({input:c,preview:y,table:u})=>({input:c,table:u,targetIds:y.targetIds})),d=q({action:"DATABASE ACTION PLAN",context:t,payload:s,preview:i,subject:`${r.length} actions`});if(d)return d;const l=[];let m=!1;for(const[c,y]of r.entries()){const u=await P(y.input,{...t,skipAudit:!0,skipConfirmation:!0});if(l.push(u),u&&typeof u=="object"&&u.mutationExecuted===!0&&(m=!0),!u||typeof u!="object"||u.success===!1){const C=await A({context:t,errorMessage:u&&typeof u=="object"&&typeof u.message=="string"?u.message:`Database action ${c+1} failed.`,input:s,preview:i,status:"failure",summary:String(i.summary),targetTables:i.tables,toolName:"execute_database_action_plan"});return{actionCount:r.length,auditLogged:C.auditLogged,...C.auditError?{auditError:C.auditError}:{},failedActionIndex:c,message:u&&typeof u=="object"&&typeof u.message=="string"?u.message:`Database action ${c+1} failed.`,mutationExecuted:m,results:l,success:!1}}}const p=await A({context:t,input:s,preview:i,status:"success",summary:String(i.summary),targetTables:i.tables,toolName:"execute_database_action_plan"});return{actionCount:r.length,auditLogged:p.auditLogged,...p.auditError?{auditError:p.auditError}:{},mutationExecuted:m,results:l,success:!0,summary:a.summary??null}}function se(e){return{describe_database_schema:v.tool({description:"Describe the public database tables Cortex AI can read or mutate, including read-only tables, primary keys, and writable columns. Use before broad database tasks when unsure about schema.",execute:t=>V(t),inputSchema:O,strict:!0}),execute_database_action_plan:v.tool({description:"Execute up to 8 typed database mutations as one confirmed plan. Mutating: first returns one combined confirmation preview and Confirm button; after confirmation, runs each action in order and stops on the first failure.",execute:t=>Q(t,e),inputSchema:D,strict:!0}),execute_database_mutation:v.tool({description:"Run one typed insert, update, upsert, or delete against an allowed public database table. Mutating: always previews affected rows and requires exact user confirmation before execution. Does not support arbitrary SQL.",execute:t=>P(t,e),inputSchema:S,strict:!0}),read_database_records:v.tool({description:"Read records from an allowed public database table with validated columns, filters, ordering, limit, and offset. Read-only and redacts protected secret-like values.",execute:t=>J(t,e),inputSchema:T,strict:!0})}}exports.createCortexDatabaseAgentTools=se;exports.describeDatabaseSchemaInputSchema=O;exports.executeDatabaseActionPlan=Q;exports.executeDatabaseActionPlanInputSchema=D;exports.executeDatabaseMutation=P;exports.executeDatabaseMutationInputSchema=S;exports.executeDescribeDatabaseSchema=V;exports.executeReadDatabaseRecords=J;exports.readDatabaseRecordsInputSchema=T;
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const v=require("ai");require("./zod-config.cjs.js");const n=require("zod"),G=100,W=20,k=100,z=20,R="[REDACTED]",g="cortex_ai_openrouter_api_key",j={blocks:{columns:["id","page_id","post_id","language_id","block_type","content","order","created_at","updated_at"],description:"CMS page/post content blocks.",primaryKey:["id"]},coupon_freemius_mappings:{columns:["id","coupon_id","product_id","freemius_product_id","freemius_coupon_id","freemius_coupon_code","sync_status","sync_error","remote_payload","last_synced_at","created_at","updated_at"],description:"Freemius coupon sync mappings.",primaryKey:["id"]},coupon_products:{columns:["coupon_id","product_id","created_at"],description:"Coupon product allow-list rows.",primaryKey:["coupon_id","product_id"]},coupon_redemptions:{columns:["id","coupon_id","order_id","coupon_code","provider","discount_total","user_id","customer_email","metadata","redeemed_at"],description:"Coupon redemption records.",primaryKey:["id"]},coupons:{columns:["id","code","name","internal_note","provider_scope","discount_type","discount_amount","is_active","starts_at","ends_at","redemption_limit","redemptions_count","freemius_sync_status","freemius_sync_error","created_at","updated_at"],description:"Commerce coupons.",primaryKey:["id"]},cortex_ai_db_mutation_audit:{columns:["id","actor_user_id","tool_name","action_name","target_tables","operation_summary","payload_hash","payload","preview","status","error_message","created_at"],description:"Read-only Cortex AI database mutation audit trail.",primaryKey:["id"],readOnly:!0},currencies:{columns:["id","code","symbol","exchange_rate","is_default","is_active","rounding_mode","rounding_increment","rounding_charm_amount","auto_update_exchange_rate","exchange_rate_updated_at","exchange_rate_source","auto_sync_product_prices","created_at","updated_at"],description:"Storefront currencies and FX settings.",primaryKey:["id"]},freemius_plans:{columns:["id","product_id","name","title","created_at","updated_at"],description:"Freemius plan metadata.",primaryKey:["id"]},freemius_pricing:{columns:["id","plan_id","api_monthly_price","api_annual_price","api_lifetime_price","override_monthly_price","override_annual_price","override_lifetime_price","license_quota","is_active","created_at","updated_at"],description:"Freemius pricing metadata.",primaryKey:["id"]},inventory_items:{columns:["sku","quantity","created_at","updated_at"],description:"Source-of-truth inventory by SKU.",primaryKey:["sku"]},languages:{columns:["id","code","name","is_default","is_active","created_at","updated_at"],description:"CMS languages/locales.",primaryKey:["id"]},logos:{columns:["id","name","media_id","created_at"],description:"Brand logos.",primaryKey:["id"]},media:{columns:["id","uploader_id","file_name","object_key","file_type","size_bytes","description","width","height","blur_data_url","variants","file_path","folder","created_at","updated_at"],description:"Media metadata for uploaded assets.",primaryKey:["id"]},navigation_items:{columns:["id","language_id","menu_key","label","url","parent_id","order","page_id","translation_group_id","created_at","updated_at"],description:"CMS navigation tree items.",primaryKey:["id"]},order_items:{columns:["id","order_id","product_id","variant_id","quantity","price_at_purchase"],description:"Commerce order line items.",primaryKey:["id"]},orders:{columns:["id","user_id","status","total","stripe_session_id","payment_intent_id","customer_details","provider","freemius_product_id","freemius_plan_id","freemius_license_id","freemius_subscription_id","freemius_trial_id","freemius_user_id","freemius_trial_ends_at","freemius_last_event_type","freemius_last_synced_at","currency","subtotal","shipping_total","tax_total","tax_details","exchange_rate_at_purchase","inventory_deducted_at","invoice_number","paid_at","created_at","coupon_id","coupon_code","discount_total","discount_details"],description:"Commerce orders.",primaryKey:["id"]},package_activations:{columns:["id","license_key","instance_name","package_id","status","meta","last_validated_at","created_at"],description:"NextBlock package activations.",primaryKey:["id"]},page_revisions:{columns:["id","page_id","author_id","version","revision_type","content","created_at"],description:"Page revision history.",primaryKey:["id"]},pages:{columns:["id","language_id","author_id","title","slug","status","meta_title","meta_description","feature_image_id","version","translation_group_id","created_at","updated_at"],description:"CMS pages.",primaryKey:["id"]},post_revisions:{columns:["id","post_id","author_id","version","revision_type","content","created_at"],description:"Post revision history.",primaryKey:["id"]},posts:{columns:["id","language_id","author_id","title","slug","label","excerpt","subtitle","status","published_at","meta_title","meta_description","feature_image_id","version","translation_group_id","created_at","updated_at"],description:"CMS posts/articles.",primaryKey:["id"]},product_attribute_terms:{columns:["id","attribute_id","value","slug","sort_order","value_translations","created_at","updated_at"],description:"Product attribute terms.",primaryKey:["id"]},product_attributes:{columns:["id","name","slug","name_translations","created_at","updated_at"],description:"Product attribute definitions.",primaryKey:["id"]},product_media:{columns:["product_id","media_id","sort_order"],description:"Product media join rows.",primaryKey:["product_id","media_id"]},product_variants:{columns:["id","product_id","sku","price_adjustment","price","prices","sale_price","sale_prices","stock_quantity","upc","main_media_id","created_at","updated_at"],description:"Sellable product variants.",primaryKey:["id"]},products:{columns:["id","language_id","translation_group_id","sku","title","slug","product_type","payment_provider","price","prices","sale_price","sale_prices","stock","status","meta_title","meta_description","short_description","description_json","metadata","freemius_plan_id","freemius_product_id","trial_period_days","trial_requires_payment_method","upc","is_taxable","created_at","updated_at"],description:"Product catalog records.",primaryKey:["id"]},profiles:{columns:["id","updated_at","full_name","avatar_url","website","phone","role"],description:"Read-only user profiles. Never mutate through Cortex AI.",primaryKey:["id"],readOnly:!0},shipping_zone_locations:{columns:["id","zone_id","country_code","state_code","postal_code","created_at"],description:"Shipping zone location match rules.",primaryKey:["id"]},shipping_zone_methods:{columns:["id","zone_id","method_type","cost_amount","cost_currency","min_order_amount","name","name_translations","currency_pricing_mode","cost_amounts","min_order_amounts","created_at","updated_at"],description:"Shipping methods/rates.",primaryKey:["id"]},shipping_zones:{columns:["id","name","priority_order","created_at","updated_at"],description:"Shipping zones.",primaryKey:["id"]},site_settings:{columns:["key","value"],description:"Global site settings. Cortex AI API-key setting row is protected.",primaryKey:["key"]},tax_rates:{columns:["id","country_code","state_code","tax_name","tax_rate","created_at","updated_at"],description:"Manual tax rates.",primaryKey:["id"]},translations:{columns:["key","translations","created_at","updated_at"],description:"Shared translation strings.",primaryKey:["key"]},user_addresses:{columns:["id","user_id","address_type","is_default","recipient_name","company_name","line1","line2","city","state","postal_code","country_code","created_at","updated_at"],description:"Read-only user addresses. Never mutate through Cortex AI.",primaryKey:["id"],readOnly:!0},variant_attribute_mapping:{columns:["variant_id","attribute_term_id"],description:"Variant to attribute-term join rows.",primaryKey:["variant_id","attribute_term_id"]}},Y=n.z.enum(["eq","neq","gt","gte","lt","lte","ilike","in","is"]),N=n.z.strictObject({column:n.z.string().trim().min(1).max(120),operator:Y.default("eq"),value:n.z.unknown()}),H=n.z.strictObject({ascending:n.z.boolean().default(!0),column:n.z.string().trim().min(1).max(120)}),O=n.z.strictObject({includeReadOnly:n.z.boolean().default(!0),table:n.z.string().trim().min(1).max(120).optional()}),T=n.z.strictObject({columns:n.z.array(n.z.string().trim().min(1).max(120)).min(1).max(40).optional(),filters:n.z.array(N).max(12).default([]),limit:n.z.number().int().min(1).max(G).default(W),offset:n.z.number().int().min(0).max(1e4).default(0),orderBy:H.optional(),table:n.z.string().trim().min(1).max(120)}),S=n.z.strictObject({filters:n.z.array(N).max(12).optional(),operation:n.z.enum(["delete","insert","update","upsert"]),rows:n.z.array(n.z.record(n.z.string(),n.z.unknown())).min(1).max(z).optional(),summary:n.z.string().trim().min(1).max(500).optional(),table:n.z.string().trim().min(1).max(120),values:n.z.record(n.z.string(),n.z.unknown()).optional()}),D=n.z.strictObject({actions:n.z.array(S).min(1).max(8),summary:n.z.string().trim().min(1).max(500).optional()});function E(e){if(!e?.supabase)throw new Error("Cortex AI database tools require a Supabase client.");return e.supabase}function f(e){return e?typeof e=="object"&&"message"in e?String(e.message||"Unknown database error."):String(e):"Unknown database error."}function K(e){return e===null||typeof e!="object"?JSON.stringify(e):Array.isArray(e)?`[${e.map(t=>K(t)).join(",")}]`:`{${Object.keys(e).sort().map(t=>`${JSON.stringify(t)}:${K(e[t])}`).join(",")}}`}function L(e){let t=2166136261;const a=K(e);for(let r=0;r<a.length;r++)t^=a.charCodeAt(r),t=Math.imul(t,16777619);return(t>>>0).toString(16).padStart(8,"0")}function I(e){return e.replace(/\s+/g," ").trim().toUpperCase()}function Z(e,t,a){return`${I(`CONFIRM ${e} ${t}`)} #${L(a)}`}function ee(e){return{confirmationPhrase:Z(e.action,e.subject,e.payload),mutationExecuted:!1,preview:e.preview,requiresConfirmation:!0,success:!0}}function q(e){if(e.context?.skipConfirmation)return null;const t=ee(e),a=I(e.context?.latestUserMessage||""),r=I(t.confirmationPhrase);return a&&!a.includes(r)?{...t,message:"The database target changed or the confirmation did not match. Please review and confirm again."}:a.includes(r)?null:t}function te(e){return Object.prototype.hasOwnProperty.call(j,e)}function M(e){const t=e.trim();if(t.includes(".")||t.toLowerCase().startsWith("auth"))throw new Error("Cortex AI cannot access auth schema tables.");if(!te(t))throw new Error(`Table "${t}" is not available to Cortex AI database tools.`);return t}function _(e){return j[e]}function w(e){return/(?:password|token|secret|api[_-]?key|private[_-]?key|credential)/i.test(e)}function b(e,t){if(!_(e).columns.includes(t))throw new Error(`Column "${t}" is not available on table "${e}".`);if(w(t))throw new Error(`Column "${t}" is protected and cannot be used through Cortex AI.`)}function $(e,t="payload"){if(Array.isArray(e)){e.forEach((a,r)=>$(a,`${t}[${r}]`));return}if(!(!e||typeof e!="object"))for(const[a,r]of Object.entries(e)){if(w(a))throw new Error(`Protected field "${t}.${a}" cannot be written through Cortex AI.`);$(r,`${t}.${a}`)}}function h(e){if(Array.isArray(e))return e.map(a=>h(a));if(!e||typeof e!="object")return e;const t={};for(const[a,r]of Object.entries(e))t[a]=w(a)?R:h(r);return t}function ae(e){return e.map(t=>t&&typeof t=="object"&&!Array.isArray(t)&&t.key===g?{key:g,value:R}:h(t))}function re(e,t){if(e!=="site_settings")return;if(JSON.stringify(t).toLowerCase().includes(g))throw new Error("The Cortex AI OpenRouter API key site setting is protected.")}function ie(e,t){switch(t.operator){case"eq":return e.eq(t.column,t.value);case"neq":return e.neq(t.column,t.value);case"gt":return e.gt(t.column,t.value);case"gte":return e.gte(t.column,t.value);case"lt":return e.lt(t.column,t.value);case"lte":return e.lte(t.column,t.value);case"ilike":if(typeof t.value!="string")throw new Error(`Filter "${t.column}" with ilike requires a string value.`);return e.ilike(t.column,t.value);case"in":if(!Array.isArray(t.value))throw new Error(`Filter "${t.column}" with in requires an array value.`);return e.in(t.column,t.value);case"is":return e.is(t.column,t.value)}}function x(e,t,a){let r=t;for(const o of a)b(e,o.column),r=ie(r,o);return e==="site_settings"&&(r=r.neq("key",g)),r}function oe(e,t){const a=_(e),r=t?.length?t:a.columns.filter(o=>!w(o));return r.forEach(o=>b(e,o)),r.join(",")}function F(e,t){return t.map(a=>`${a}=${String(e[a]??"")}`).join("|")}async function U(e,t,a){const r=_(t);let o=e.from(t).select(r.primaryKey.join(",")).limit(k+1);o=x(t,o,a);const{data:i,error:s}=await o;if(s)throw new Error(`Failed to preview database mutation: ${f(s)}`);const d=Array.isArray(i)?i:[];if(d.length>k)throw new Error(`Refusing to mutate more than ${k} rows.`);return d}function B(e){const t=M(e.table),a=_(t),r=e.operation;if(a.readOnly)throw new Error(`Table "${t}" is read-only for Cortex AI.`);if(re(t,e),(r==="update"||r==="delete")&&(!e.filters||e.filters.length===0))throw new Error(`${r} operations require at least one filter.`);if((r==="insert"||r==="upsert")&&(!e.rows||e.rows.length===0))throw new Error(`${r} operations require rows.`);if(r==="update"&&(!e.values||Object.keys(e.values).length===0))throw new Error("update operations require values.");if(e.rows&&e.rows.length>z)throw new Error(`Refusing to mutate more than ${z} input rows.`);const o=e.rows??(e.values?[e.values]:[]);for(const i of o){$(i);for(const s of Object.keys(i))b(t,s)}for(const i of e.filters??[])b(t,i.column);return t}function X(e){const{input:t,table:a,targetRows:r}=e,o=_(a),i=r.map(m=>F(m,o.primaryKey)).sort(),s=t.rows?.length??0,d=t.operation==="insert"||t.operation==="upsert"?s:r.length,l=t.summary||`${t.operation} ${d} ${d===1?"row":"rows"} in ${a}.`;return{affectedCount:d,operation:t.operation,sampleTargetIds:i.slice(0,10),summary:l,table:a,targetIds:i}}async function A(e){const t=e.context?.actorUserId;if(!t)return{auditError:"Missing actor user id.",auditLogged:!1};try{const{error:a}=await E(e.context).from("cortex_ai_db_mutation_audit").insert({action_name:e.toolName,actor_user_id:t,error_message:e.errorMessage??null,operation_summary:e.summary,payload:h(e.input),payload_hash:L(e.input),preview:h(e.preview),status:e.status,target_tables:e.targetTables,tool_name:e.toolName});return a?{auditError:f(a),auditLogged:!1}:{auditLogged:!0}}catch(a){return{auditError:f(a),auditLogged:!1}}}async function ne(e,t,a){const o=_(t).primaryKey.join(",");let i;e.operation==="insert"?i=a.from(t).insert(e.rows).select(o):e.operation==="upsert"?i=a.from(t).upsert(e.rows).select(o):e.operation==="update"?(i=a.from(t).update(e.values),i=x(t,i,e.filters??[]),i=i.select(o)):(i=a.from(t).delete(),i=x(t,i,e.filters??[]),i=i.select(o));const{data:s,error:d}=await i;if(d)throw new Error(f(d));return Array.isArray(s)?s:[]}async function V(e){const t=O.parse(e),r=(t.table?[M(t.table)]:Object.keys(j)).filter(o=>t.includeReadOnly||!_(o).readOnly).map(o=>{const i=_(o);return{columns:i.columns.filter(s=>!w(s)),description:i.description,primaryKey:i.primaryKey,readOnly:!!i.readOnly,table:o}});return{safetyNotes:["Use read_database_records for reads and execute_database_mutation/action_plan for writes.","No auth schema access, no arbitrary SQL, no password/secret/API-key fields.","profiles, user_addresses, and cortex_ai_db_mutation_audit are read-only.",`site_settings.${g} is protected.`],success:!0,tables:r}}async function J(e,t){const a=T.parse(e),r=M(a.table),o=oe(r,a.columns);let i=E(t).from(r).select(o).range(a.offset,a.offset+a.limit-1);i=x(r,i,a.filters),a.orderBy&&(b(r,a.orderBy.column),i=i.order(a.orderBy.column,{ascending:a.orderBy.ascending}));const{data:s,error:d}=await i;if(d)throw new Error(`Failed to read database records: ${f(d)}`);const l=Array.isArray(s)?s:[];return{columns:o.split(","),limit:a.limit,offset:a.offset,rows:ae(l),success:!0,table:r}}async function P(e,t){const a=S.parse(e),r=B(a),o=E(t),i=a.operation==="update"||a.operation==="delete"?await U(o,r,a.filters??[]):[],s=X({input:a,table:r,targetRows:i}),d={input:a,targetIds:s.targetIds},l=q({action:`DATABASE ${a.operation}`,context:t,payload:d,preview:s,subject:r});if(l)return l;try{const m=await ne(a,r,o),p=t?.skipAudit?{auditLogged:!1}:await A({context:t,input:d,preview:s,status:"success",summary:String(s.summary),targetTables:[r],toolName:"execute_database_mutation"});return{affectedCount:m.length||s.affectedCount,auditLogged:p.auditLogged,...p.auditError?{auditError:p.auditError}:{},mutationExecuted:!0,operation:a.operation,sampleTargetIds:m.map(c=>F(c,_(r).primaryKey)).slice(0,10),success:!0,summary:s.summary,table:r}}catch(m){const p=f(m),c=t?.skipAudit?{auditLogged:!1}:await A({context:t,errorMessage:p,input:d,preview:s,status:"failure",summary:String(s.summary),targetTables:[r],toolName:"execute_database_mutation"});return{auditLogged:c.auditLogged,...c.auditError?{auditError:c.auditError}:{},message:`Database mutation failed: ${p}`,mutationExecuted:!1,operation:a.operation,success:!1,table:r}}}async function Q(e,t){const a=D.parse(e),r=[];for(const c of a.actions){const y=B(c),u=c.operation==="update"||c.operation==="delete"?await U(E(t),y,c.filters??[]):[];r.push({input:c,preview:X({input:c,table:y,targetRows:u}),table:y})}const o=r.map(({preview:c})=>String(c.summary)),i={actionCount:r.length,actionSummaries:o,summary:a.summary||`Run ${r.length} confirmed database actions.`,tables:Array.from(new Set(r.map(c=>c.table)))},s=r.map(({input:c,preview:y,table:u})=>({input:c,table:u,targetIds:y.targetIds})),d=q({action:"DATABASE ACTION PLAN",context:t,payload:s,preview:i,subject:`${r.length} actions`});if(d)return d;const l=[];let m=!1;for(const[c,y]of r.entries()){const u=await P(y.input,{...t,skipAudit:!0,skipConfirmation:!0});if(l.push(u),u&&typeof u=="object"&&u.mutationExecuted===!0&&(m=!0),!u||typeof u!="object"||u.success===!1){const C=await A({context:t,errorMessage:u&&typeof u=="object"&&typeof u.message=="string"?u.message:`Database action ${c+1} failed.`,input:s,preview:i,status:"failure",summary:String(i.summary),targetTables:i.tables,toolName:"execute_database_action_plan"});return{actionCount:r.length,auditLogged:C.auditLogged,...C.auditError?{auditError:C.auditError}:{},failedActionIndex:c,message:u&&typeof u=="object"&&typeof u.message=="string"?u.message:`Database action ${c+1} failed.`,mutationExecuted:m,results:l,success:!1}}}const p=await A({context:t,input:s,preview:i,status:"success",summary:String(i.summary),targetTables:i.tables,toolName:"execute_database_action_plan"});return{actionCount:r.length,auditLogged:p.auditLogged,...p.auditError?{auditError:p.auditError}:{},mutationExecuted:m,results:l,success:!0,summary:a.summary??null}}function se(e){return{describe_database_schema:v.tool({description:"Describe the public database tables Cortex AI can read or mutate, including read-only tables, primary keys, and writable columns. Use before broad database tasks when unsure about schema.",execute:t=>V(t),inputSchema:O,strict:!0}),execute_database_action_plan:v.tool({description:"Execute up to 8 typed database mutations as one confirmed plan. Mutating: first returns one combined confirmation preview and Confirm button; after confirmation, runs each action in order and stops on the first failure.",execute:t=>Q(t,e),inputSchema:D,strict:!0}),execute_database_mutation:v.tool({description:"Run one typed insert, update, upsert, or delete against an allowed public database table. Mutating: always previews affected rows and requires exact user confirmation before execution. Does not support arbitrary SQL.",execute:t=>P(t,e),inputSchema:S,strict:!0}),read_database_records:v.tool({description:"Read records from an allowed public database table with validated columns, filters, ordering, limit, and offset. Read-only and redacts protected secret-like values.",execute:t=>J(t,e),inputSchema:T,strict:!0})}}exports.createCortexDatabaseAgentTools=se;exports.describeDatabaseSchemaInputSchema=O;exports.executeDatabaseActionPlan=Q;exports.executeDatabaseActionPlanInputSchema=D;exports.executeDatabaseMutation=P;exports.executeDatabaseMutationInputSchema=S;exports.executeDescribeDatabaseSchema=V;exports.executeReadDatabaseRecords=J;exports.readDatabaseRecordsInputSchema=T;
|
|
@@ -351,7 +351,7 @@ const V = 100, J = 20, C = 100, k = 20, M = "[REDACTED]", g = "cortex_ai_openrou
|
|
|
351
351
|
primaryKey: ["id"]
|
|
352
352
|
},
|
|
353
353
|
profiles: {
|
|
354
|
-
columns: ["id", "updated_at", "full_name", "avatar_url", "website", "
|
|
354
|
+
columns: ["id", "updated_at", "full_name", "avatar_url", "website", "phone", "role"],
|
|
355
355
|
description: "Read-only user profiles. Never mutate through Cortex AI.",
|
|
356
356
|
primaryKey: ["id"],
|
|
357
357
|
readOnly: !0
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nextblock-cms/cortex",
|
|
3
|
-
"version": "0.12.
|
|
3
|
+
"version": "0.12.15",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -27,9 +27,9 @@
|
|
|
27
27
|
},
|
|
28
28
|
"dependencies": {
|
|
29
29
|
"@ai-sdk/openai-compatible": "^2.0.42",
|
|
30
|
-
"@nextblock-cms/db": "^0.12.
|
|
31
|
-
"@nextblock-cms/ecommerce": "npm:@nextblock-cms/ecom@^0.12.
|
|
32
|
-
"@nextblock-cms/utils": "^0.12.
|
|
30
|
+
"@nextblock-cms/db": "^0.12.15",
|
|
31
|
+
"@nextblock-cms/ecommerce": "npm:@nextblock-cms/ecom@^0.12.15",
|
|
32
|
+
"@nextblock-cms/utils": "^0.12.15",
|
|
33
33
|
"ai": "^6.0.170",
|
|
34
34
|
"zod": "^4.3.6"
|
|
35
35
|
},
|