ozmoz 0.1.12 → 0.1.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.
package/dist/ozmoz-mcp.js CHANGED
@@ -109,7 +109,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
109
109
 
110
110
  2. FORBIDDEN "SCHEMA-FIRST" APPROACH:
111
111
  - The agent must NEVER design, imagine, or model a database schema before building the interface.
112
- - In ozmoZ vibe-coding, the UI interface ALWAYS dictates the data structure.
112
+ - In OZmoz vibe-coding, the UI interface ALWAYS dictates the data structure.
113
113
  - The development cycle is strictly Frontend-First: UI first \u2794 inference by Alex AI \u2794 sealing.
114
114
 
115
115
  3. STRICT SEPARATION OF RESPONSIBILITIES:
@@ -127,7 +127,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
127
127
  ================================================================================
128
128
  \u{1F6A8} DATA PROTOCOL: WHO DOES WHAT (FRONTEND AGENT \u2194 ALEX AI) \u{1F6A8}
129
129
  ================================================================================
130
- 1. YOUR FREEDOM: the entire frontend belongs to you (rendering, state, styles, navigation, components, UI logic). Only one exception: the technology (the framework), which the user chooses among supported options; you ask them before installing anything. ozmoZ only handles data, authentication, and storage. A change that does not touch data requires nobody's approval.
130
+ 1. YOUR FREEDOM: the entire frontend belongs to you (rendering, state, styles, navigation, components, UI logic). Only one exception: the technology (the framework), which the user chooses among supported options; you ask them before installing anything. OZmoz only handles data, authentication, and storage. A change that does not touch data requires nobody's approval.
131
131
 
132
132
  2. YOUR USER is not a developer. In your messages to the user (not in code), always speak in the user's language (detect it from their prompt, e.g. French if they write in French) in a plain, jargon-free manner: never say prototype, true, false, .env, contract, schema, sync, Edge, endpoint, collection, nor oz_update_project. Instead, say (adapt to their language):
133
133
  - "trial mode" (or \xAB mode essai \xBB) for OZ_PROTOTYPE=true, and "live mode" (or \xAB mode r\xE9el \xBB) for false;
@@ -139,11 +139,11 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
139
139
  3. PROTOTYPE MODE (OZ_PROTOTYPE=true, "trial mode" for the user): the goal is to validate screens and the user journey.
140
140
  - Write UI with real wiring: oz.getDocsG / getDocsU / getDoc / add / update / delete / join, final collection and field names, type casts, <oz-*> tags.
141
141
  - TRIAL AUTHENTICATION & DIAGNOSTICS: wire a real screen (oz.sendotpsvro / verifyotpsvro), just like the rest (Zero-Rewrite) \u2014 no separate mocked forms. The flow remains identical to production (the tester enters an email, confirms, then enters a code, confirms): behind the scenes, trial mode sends no real emails and always accepts "0000" as the code. Show this code directly on screen (e.g., a note "Trial mode \u2014 test code: 0000") so the tester knows what to input at step two without waiting for an email that will never arrive.
142
- In trial mode (OZ_PROTOTYPE=true), all auth and data operations are 100% simulated locally. The Edge Gatekeeper and Cloud functions are bypassed:
142
+ In trial mode (OZ_PROTOTYPE=true), all auth and data operations are 100% simulated locally. The Kernel Gatekeeper and Cloud functions are bypassed:
143
143
  \u2022 Any verification code other than "0000" will fail, and "0000" always succeeds.
144
144
  \u2022 If oz.sendotpsvro or oz.verifyotpsvro fails or behaves unexpectedly, THE FAULT IS 100% INSIDE YOUR FRONTEND LOGIC (bad arguments, lost state, hardcoded UI errors).
145
145
  \u2022 ABSOLUTELY FORBIDDEN to run shell commands, node scripts ('node -e'), or inspect package internals to debug authentication. Review and fix your UI component code directly.
146
- \u2022 AUTH STATUS CHECK: ozmoZ automatically attaches an anonymous session on load. Calling oz.getUser() always returns an anonymous user. To check if an actual user is logged in, you MUST call 'await oz.isAuthenticated()' or check '!currentUser.isAnonymous'.
146
+ \u2022 AUTH STATUS CHECK: OZmoz automatically attaches an anonymous session on load. Calling oz.getUser() always returns an anonymous user. To check if an actual user is logged in, you MUST call 'await oz.isAuthenticated()' or check '!currentUser.isAnonymous'.
147
147
  - Data is virtual: oz.seed('collection', [...]) then normal read.
148
148
  - Zero-Rewrite also applies to UI: NEVER hardcode trial-specific text unconditionally (banner "Trial mode", hint "code 0000", etc.) \u2014 this text only makes sense in trial mode and would be false/misleading in production. Condition any such element on import.meta.env.OZ_PROTOTYPE === 'true', so it disappears on its own in production without rewriting a line. NEVER hardcode a fallback like "0000" on the client: trust the actual response from oz.sendotpsvro/verifyotpsvro, whatever it returns.
149
149
  - The contract can be blank: do not wait for it and do not design it. The UI dictates the fields.
@@ -158,7 +158,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
158
158
  - On the first switch to live mode, the database is empty (oz.seed is inert): warn the user in one sentence and verify that the app allows creating data (creation forms).
159
159
 
160
160
  5. WHEN TO HAND OVER TO ALEX (in these cases, and only these cases):
161
- a) The user confirms the screens look good and wants to switch to real data: first save of their data structure. Never assume this approval. If the moment seems right, explain the situation with pedagogical empathy: remind them in simple, jargon-free words that the app currently runs in sandbox/trial mode with dummy data to test the experience safely, and that validating the visual flow is what will unlock creating their real live ozmoZ database. Ask them naturally if the interface and user journey suit their needs. DO NOT recite a robotic template: adapt your phrasing naturally to the tone and flow of the conversation. HARD STOP: NEVER call oz_update_project in the same turn...
161
+ a) The user confirms the screens look good and wants to switch to real data: first save of their data structure. Never assume this approval. If the moment seems right, explain the situation with pedagogical empathy: remind them in simple, jargon-free words that the app currently runs in sandbox/trial mode with dummy data to test the experience safely, and that validating the visual flow is what will unlock creating their real live OZmoz database. Ask them naturally if the interface and user journey suit their needs. DO NOT recite a robotic template: adapt your phrasing naturally to the tone and flow of the conversation. HARD STOP: NEVER call oz_update_project in the same turn...
162
162
  b) After this first save, data is added, modified, or deleted (collection, field, type, relation, business rule, permission): hand over as soon as the view is written.
163
163
  c) The user asks you to.
164
164
  How: call oz_update_project with name, filePaths, rules, and userApproval (the EXACT verbatim quote of the user's message authorizing this call: their approval of the screens or their request to change data; never write it yourself), then apply point 7.
@@ -169,7 +169,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
169
169
 
170
170
  6. DO NOT HAND OVER TO ALEX for: styling, layout, copy, navigation, components, UI state or logic, frontend bug fixes, demo data (oz.seed).
171
171
 
172
- 7. SYNCHRONIZATION: after a REAL update of the backend contract (oz_update_project, or Alex in ozmoZ confirmed by the user), run npx ozmoz sync (without flags) before continuing to code, then tell the user in one sentence that the new structure has been saved. For any OTHER reason to re-verify code (ozmoz package update, simple code refactoring, compliance doubt): run npx ozmoz sync --check-only instead \u2014 never a full sync, which would contact the cloud and reseal the Edge when no data has changed.
172
+ 7. SYNCHRONIZATION: after a REAL update of the backend contract (oz_update_project, or Alex in OZmoz confirmed by the user), run npx ozmoz sync (without flags) before continuing to code, then tell the user in one sentence that the new structure has been saved. For any OTHER reason to re-verify code (ozmoz package update, simple code refactoring, compliance doubt): run npx ozmoz sync --check-only instead \u2014 never a full sync, which would contact the cloud and reseal the Edge when no data has changed.
173
173
 
174
174
  8. NEVER: modify OZ_PROTOTYPE on your own initiative (only with explicit user consent, after explaining the difference between trial mode and live mode in one sentence); design or edit svro.schema.json and svro.workflow.json (Alex's authority); write a backend, API route, or ORM; invent oz.* methods or <oz-*> tags.
175
175
 
@@ -180,18 +180,18 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
180
180
 
181
181
  ## \u{1F6E0}\uFE0F CANONICAL OZMOZ SDK SYNTAX
182
182
  - BARE IDENTIFIER: ALWAYS call 'oz.*' directly. NEVER use 'window.oz' or 'window.oz?.'.
183
- - CREATE: await oz.add('collection', { name: String(n).trim(), price: Number(p) }, { desc: 'Create item', role: 'AUTHENTICATED' });
184
- - READ (All): const docs = await oz.getDocsG('collection');
185
- - READ (Single): const doc = await oz.getDoc('collection', doc._id);
186
- - READ (User): const docs = await oz.getDocsU('collection');
187
- - UPDATE: await oz.update('collection', doc._id, { price: Number(p) }, { desc: 'Update price', role: 'MANAGER' });
188
- - DELETE: await oz.delete('collection', doc._id, { desc: 'Delete item', role: 'ADMIN' });
189
- - JOIN: await oz.join('orders', { innerJoin: { collection: 'users', on: ['userId', '==', '_id'], as: 'user' } });
183
+ - READ ALL (Direct Array, NO .success): const docs = await oz.getDocsG('collection'); // returns []
184
+ - READ SINGLE (Direct Doc or null, NO .success): const doc = await oz.getDoc('collection', doc._id);
185
+ - READ USER (Direct Array, NO .success): const userDocs = await oz.getDocsU('collection'); // returns []
186
+ - CREATE (Has .success): const res = await oz.add('collection', { name: String(n).trim(), price: Number(p) }, { desc: 'Create item', role: 'AUTHENTICATED' });
187
+ - UPDATE (Has .success): const res = await oz.update('collection', doc._id, { price: Number(p) }, { desc: 'Update price', role: 'MANAGER' });
188
+ - DELETE (Has .success): const res = await oz.delete('collection', doc._id, { desc: 'Delete item', role: 'ADMIN' });
189
+ - JOIN (Direct Array, NO .success): const docs = await oz.join('orders', { innerJoin: { collection: 'users', on: ['userId', '==', '_id'], as: 'user' } });
190
190
  - SEED (prototype only, inert in production): await oz.seed('collection', [{ _id: 'demo1', name: 'Demo', price: 10 }]);
191
191
  - CLOUD FUNCTION: const res = await oz.call.processCheckout(payload);
192
- `;function QA(e){return String(e).toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g,"").replace(/[^a-z0-9]/g,"_").replace(/^_+|_+$/g,"").slice(0,30)||"app"}async function e4({name:e,keyApp:t},n){let i=t&&t.trim(),r=QA(e),o=i?[i]:[r].concat(Array.from({length:3},()=>r.slice(0,24)+"_"+Math.random().toString(36).slice(2,6))),a=c=>!!(c&&c.error)&&(c.error.status==="ALREADY_EXISTS"||/déjà réservée|already.exists/i.test(c.error.message||"")),s=null;for(let c of o){let{res:u,json:l}=await n(c);if(u.ok&&!l.error)return{keyApp:c,json:l};if(s={json:l,taken:a(l),candidate:c},!s.taken)break}throw s&&s.taken?new Error(i?"The keyApp '"+i+"' is already taken. Call this tool again WITHOUT keyApp: a unique one is generated.":"No free keyApp found after "+o.length+" attempts. Call this tool again with a more specific name."):new Error(s&&s.json&&s.json.error&&s.json.error.message||"Failed to create project on Cloud.")}function t4(e){let t=typeof e=="string"?e.trim():"",n=/approv(ed|al) by|user (has |already )?(approved|validated|confirmed|agreed)|the user (approved|validated|confirmed|said)|implicit|assumed|not applicable|no approval|awaiting|pending|placeholder|^n\/?a$|^none$|^null$|^undefined$/i;if(t.length<2||t.length>600||n.test(t))throw new Error("STOP: 'userApproval' must be the user's own words (a verbatim quote of a message they sent AFTER you showed them the screens, or their request to change the data). Do not write it yourself and do not call this tool in the same turn as writing code. If they have not answered yet, ask your validation question and stop: wait for their next message.");return t}var Mo=new Xc({name:"ozmoz-mcp",version:"1.0.0"},{capabilities:{tools:{},prompts:{}}});Mo.setRequestHandler(Ep,async()=>({prompts:[{name:"oz_contract_rules",description:"Loads strict architectural rules, invariants, and integrity directives for ozmoZ SVRO."}]}));Mo.setRequestHandler(jp,async e=>{if(e.params.name==="oz_contract_rules")return{description:"Official ozmoZ SVRO architecture directives",messages:[{role:"user",content:{type:"text",text:mx}}]};throw new Error(`Unknown prompt: ${e.params.name}`)});Mo.setRequestHandler(Cp,async()=>({tools:[{name:"oz_create_project",description:"Creates a NEW ozmoZ Cloud project. Call this ONLY when starting a brand new application from scratch. DO NOT call it if the project is already initialized (OZ_DB_KEY present in .env, or svro.schema.json exists): use 'oz_update_project' instead. This tool is already authenticated and returns the exact next command to run: no shell command or filesystem search is needed before calling it. Only if it returns a missing-token error: run 'npx ozmoz login' once, wait for it to finish, then call this tool again.",inputSchema:{type:"object",properties:{name:{type:"string",description:"Nom de l'application"},keyApp:{type:"string",description:"Slug unique (optionnel, auto-d\xE9duit si omis)"}},required:["name"]}},{name:"oz_update_project",description:"HARD STOP: call this tool ONLY after the user has explicitly approved the screens in a message that arrived AFTER you gave them the dev-server address (first sealing), or when they ask for a data change (later). NEVER in the same turn as writing UI code or asking for their approval: if they have not answered yet, ask and STOP. 'userApproval' must be their exact words. Models / updates the project's data contract (svro.schema.json + svro.workflow.json) from UI component files and business rules, additively. This is the ONLY way to evolve the contract: there is no shell command for it. Pass 'filePaths' (e.g. ['src/components/DeskList.jsx']); 'keyApp' is optional (read from .env). Afterwards run 'npx ozmoz sync' once.",inputSchema:{type:"object",properties:{keyApp:{type:"string",description:"Unique application key (e.g. coworking_prod). Optional: if omitted, it is read from OZ_KEY_APP in the project's .env."},name:{type:"string",description:"Application name"},userApproval:{type:"string",description:"The user's EXACT words authorizing this call: their approval of the screens, or their request to change the data. Never write it yourself."},rules:{type:"string",description:"New business rules, calculations, or state transitions."},filePaths:{type:"array",items:{type:"string"},description:"Relative paths of ALL files that call oz.* or define data fields."},viewFiles:{type:"array",items:{type:"object",properties:{name:{type:"string"},content:{type:"string"}},required:["name","content"]},description:"View files already loaded in memory [{ name, content }]."}},required:["name","userApproval"]}},{name:"oz_publish_function",description:"Deploys a private or public cloud utility function executed in a secure serverless environment.",inputSchema:{type:"object",properties:{enterpriseID:{type:"string",description:"Project enterpriseID infrastructure identifier"},functionName:{type:"string",description:"Function name (alphanumeric 3-40 chars, e.g. calculateTotal)"},code:{type:"string",description:"JS source code (e.g. async function calculateTotal(payload, oz) { ... })"},description:{type:"string",description:"Action documentation for the catalog and Alex AI"},isPublic:{type:"boolean",description:"true to publish to the global Marketplace, false for private function"}},required:["enterpriseID","functionName","code"]}},{name:"oz_get_contract",description:"Provides the official data contract, SDK directives, production lifecycle and canonical blueprint.",inputSchema:{type:"object",properties:{}}}]}));Mo.setRequestHandler(ao,async e=>{let{name:t,arguments:n}=e.params;if(t==="oz_get_contract")return{content:[{type:"text",text:mx}]};let i=await XA();if(!i)return{isError:!0,content:[{type:"text",text:"Error: FLEETBO_DEV_TOKEN missing. Run 'npx ozmoz login' ONCE, wait for it to finish (the developer approves in the browser), then call this tool again \u2014 no restart needed."}]};try{if(t==="oz_create_project"){let o=ot.object({name:ot.string().min(2),keyApp:ot.string().optional()}).parse(n),{keyApp:a,json:s}=await e4(o,async d=>{let f=await fetch(`https://createprojectlight-${fx}`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${i}`},body:JSON.stringify({data:{name:o.name,keyApp:d}})});return{res:f,json:await f.json()}}),c=s.result?.data||s.data||{},u=c.enterpriseId||c.referenceId||c.id,l=`npx ozmoz init --keyApp=${a} --token=${c.bootstrapToken} && npx ozmoz sync`;return{content:[{type:"text",text:JSON.stringify({status:"SUCCESS",message:`Project "${o.name}" successfully created. Ready for bootstrap and modeling.`,enterpriseID:u,keyApp:a,bootstrapToken:c.bootstrapToken,commandInit:l,directive:"Do NOT start any dev server yet. If the folder has no package.json, scaffold the frontend first (step 1), then run commandInit.",nextSteps:["1. Scaffold the frontend ONLY if there is no package.json: run EXACTLY `npm create vite@latest ozmoz-tmp -- --template <react|vue|svelte|vanilla> --no-interactive --no-immediate` (the technology the user chose), move its contents to the project root WITHOUT overwriting existing files, delete ozmoz-tmp, then run `npm install`.","2. Run commandInit to bootstrap the local env, fetch the initial contracts and generate src/ozmoz.d.ts + ozmoz_contract.md.","3. CRITICAL: READ 'ozmoz_contract.md' NOW, before writing any UI code.","4. STEP 1, UI/UX: write ALL the views using global oz.* and <oz-*> tags, in trial mode (OZ_PROTOTYPE=true, demo data with oz.seed). Do NOT start the dev server before every view is written.","5. When every view is written: start the dev server, give the user the address, ask them to validate or adjust the UI/UX, then STOP.","6. STEP 2, data (only after user approval): call 'oz_update_project' with userApproval = their exact words, then run 'npx ozmoz sync'."]},null,2)}]}}if(t==="oz_update_project"){t4(n&&n.userApproval);let r=YA(Mr.resolve(process.cwd()))||n?.keyApp?.trim();if(!r)throw new Error("keyApp not provided and OZ_KEY_APP not found in the project's .env. Pass 'keyApp' explicitly.");let{spawnSync:o}=await import("node:child_process"),{fileURLToPath:a}=await import("node:url"),s=Mr.dirname(a(import.meta.url)),u=[[Mr.join(s,"cli.cjs"),Mr.join(s,"cli.js")].find(Qn.existsSync)||Mr.join(s,"cli.cjs"),"update"];n?.rules&&u.push(`--rules=${n.rules}`);let l=o(process.execPath,u,{cwd:process.cwd(),stdio:"pipe",encoding:"utf8",env:process.env});if(l.status!==0){let d=(l.stderr||l.stdout||"").trim();throw new Error(`Modeling update failed via CLI: ${d||"Unknown execution error"}`)}return{content:[{type:"text",text:JSON.stringify({status:"SUCCESS",keyApp:r,message:"Alex AI a mod\xE9lis\xE9 le contrat \xE0 partir du contractDraft extrait localement et l'a scell\xE9 \xE0 l'Edge.",actionRequired:"none",directive:`1. La structure des donn\xE9es a \xE9t\xE9 extraite et scell\xE9e \xE0 l'Edge via cli.js.
192
+ `;function QA(e){return String(e).toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g,"").replace(/[^a-z0-9]/g,"_").replace(/^_+|_+$/g,"").slice(0,30)||"app"}async function e4({name:e,keyApp:t},n){let i=t&&t.trim(),r=QA(e),o=i?[i]:[r].concat(Array.from({length:3},()=>r.slice(0,24)+"_"+Math.random().toString(36).slice(2,6))),a=c=>!!(c&&c.error)&&(c.error.status==="ALREADY_EXISTS"||/déjà réservée|already.exists/i.test(c.error.message||"")),s=null;for(let c of o){let{res:u,json:l}=await n(c);if(u.ok&&!l.error)return{keyApp:c,json:l};if(s={json:l,taken:a(l),candidate:c},!s.taken)break}throw s&&s.taken?new Error(i?"The keyApp '"+i+"' is already taken. Call this tool again WITHOUT keyApp: a unique one is generated.":"No free keyApp found after "+o.length+" attempts. Call this tool again with a more specific name."):new Error(s&&s.json&&s.json.error&&s.json.error.message||"Failed to create project on Cloud.")}function t4(e){let t=typeof e=="string"?e.trim():"",n=/approv(ed|al) by|user (has |already )?(approved|validated|confirmed|agreed)|the user (approved|validated|confirmed|said)|implicit|assumed|not applicable|no approval|awaiting|pending|placeholder|^n\/?a$|^none$|^null$|^undefined$/i;if(t.length<2||t.length>600||n.test(t))throw new Error("STOP: 'userApproval' must be the user's own words (a verbatim quote of a message they sent AFTER you showed them the screens, or their request to change the data). Do not write it yourself and do not call this tool in the same turn as writing code. If they have not answered yet, ask your validation question and stop: wait for their next message.");return t}var Mo=new Xc({name:"ozmoz-mcp",version:"1.0.0"},{capabilities:{tools:{},prompts:{}}});Mo.setRequestHandler(Ep,async()=>({prompts:[{name:"oz_contract_rules",description:"Loads strict architectural rules, invariants, and integrity directives for OZmoz SVRO."}]}));Mo.setRequestHandler(jp,async e=>{if(e.params.name==="oz_contract_rules")return{description:"Official OZmoz SVRO architecture directives",messages:[{role:"user",content:{type:"text",text:mx}}]};throw new Error(`Unknown prompt: ${e.params.name}`)});Mo.setRequestHandler(Cp,async()=>({tools:[{name:"oz_create_project",description:"Creates a NEW OZmoz Cloud project. Call this ONLY when starting a brand new application from scratch. DO NOT call it if the project is already initialized (OZ_DB_KEY present in .env, or svro.schema.json exists): use 'oz_update_project' instead. This tool is already authenticated and returns the exact next command to run: no shell command or filesystem search is needed before calling it. Only if it returns a missing-token error: run 'npx ozmoz login' once, wait for it to finish, then call this tool again.",inputSchema:{type:"object",properties:{name:{type:"string",description:"Nom de l'application"},keyApp:{type:"string",description:"Slug unique (optionnel, auto-d\xE9duit si omis)"}},required:["name"]}},{name:"oz_update_project",description:"HARD STOP: call this tool ONLY after the user has explicitly approved the screens in a message that arrived AFTER you gave them the dev-server address (first sealing), or when they ask for a data change (later). NEVER in the same turn as writing UI code or asking for their approval: if they have not answered yet, ask and STOP. 'userApproval' must be their exact words. Models / updates the project's data contract (svro.schema.json + svro.workflow.json) from UI component files and business rules, additively. This is the ONLY way to evolve the contract: there is no shell command for it. Pass 'filePaths' (e.g. ['src/components/DeskList.jsx']); 'keyApp' is optional (read from .env). Afterwards run 'npx ozmoz sync' once.",inputSchema:{type:"object",properties:{keyApp:{type:"string",description:"Unique application key (e.g. coworking_prod). Optional: if omitted, it is read from OZ_KEY_APP in the project's .env."},name:{type:"string",description:"Application name"},userApproval:{type:"string",description:"The user's EXACT words authorizing this call: their approval of the screens, or their request to change the data. Never write it yourself."},rules:{type:"string",description:"New business rules, calculations, or state transitions."},filePaths:{type:"array",items:{type:"string"},description:"Relative paths of ALL files that call oz.* or define data fields."},viewFiles:{type:"array",items:{type:"object",properties:{name:{type:"string"},content:{type:"string"}},required:["name","content"]},description:"View files already loaded in memory [{ name, content }]."}},required:["name","userApproval"]}},{name:"oz_publish_function",description:"Deploys a private or public cloud utility function executed in a secure serverless environment.",inputSchema:{type:"object",properties:{enterpriseID:{type:"string",description:"Project enterpriseID infrastructure identifier"},functionName:{type:"string",description:"Function name (alphanumeric 3-40 chars, e.g. calculateTotal)"},code:{type:"string",description:"JS source code (e.g. async function calculateTotal(payload, oz) { ... })"},description:{type:"string",description:"Action documentation for the catalog and Alex AI"},isPublic:{type:"boolean",description:"true to publish to the global Marketplace, false for private function"}},required:["enterpriseID","functionName","code"]}},{name:"oz_get_contract",description:"Provides the official data contract, SDK directives, production lifecycle and canonical blueprint.",inputSchema:{type:"object",properties:{}}}]}));Mo.setRequestHandler(ao,async e=>{let{name:t,arguments:n}=e.params;if(t==="oz_get_contract")return{content:[{type:"text",text:mx}]};let i=await XA();if(!i)return{isError:!0,content:[{type:"text",text:"Error: FLEETBO_DEV_TOKEN missing. Run 'npx ozmoz login' ONCE, wait for it to finish (the developer approves in the browser), then call this tool again \u2014 no restart needed."}]};try{if(t==="oz_create_project"){let o=ot.object({name:ot.string().min(2),keyApp:ot.string().optional()}).parse(n),{keyApp:a,json:s}=await e4(o,async d=>{let f=await fetch(`https://createprojectlight-${fx}`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${i}`},body:JSON.stringify({data:{name:o.name,keyApp:d}})});return{res:f,json:await f.json()}}),c=s.result?.data||s.data||{},u=c.enterpriseId||c.referenceId||c.id,l=`npx ozmoz init --keyApp=${a} --token=${c.bootstrapToken} && npx ozmoz sync`;return{content:[{type:"text",text:JSON.stringify({status:"SUCCESS",message:`Project "${o.name}" successfully created. Ready for bootstrap and modeling.`,enterpriseID:u,keyApp:a,bootstrapToken:c.bootstrapToken,commandInit:l,directive:"Do NOT start any dev server yet. If the folder has no package.json, scaffold the frontend first (step 1), then run commandInit.",nextSteps:["1. Scaffold the frontend ONLY if there is no package.json: run EXACTLY `npm create vite@latest ozmoz-tmp -- --template <react|vue|svelte|vanilla> --no-interactive --no-immediate` (the technology the user chose), move its contents to the project root WITHOUT overwriting existing files, delete ozmoz-tmp, then run `npm install`.","2. Run commandInit to bootstrap the local env, fetch the initial contracts and generate src/ozmoz.d.ts + ozmoz_contract.md.","3. CRITICAL: READ 'ozmoz_contract.md' NOW, before writing any UI code.","4. STEP 1, UI/UX: write ALL the views using global oz.* and <oz-*> tags, in trial mode (OZ_PROTOTYPE=true, demo data with oz.seed). Do NOT start the dev server before every view is written.","5. When every view is written: start the dev server, give the user the address, ask them to validate or adjust the UI/UX, then STOP.","6. STEP 2, data (only after user approval): call 'oz_update_project' with userApproval = their exact words, then run 'npx ozmoz sync'."]},null,2)}]}}if(t==="oz_update_project"){t4(n&&n.userApproval);let r=YA(Mr.resolve(process.cwd()))||n?.keyApp?.trim();if(!r)throw new Error("keyApp not provided and OZ_KEY_APP not found in the project's .env. Pass 'keyApp' explicitly.");let{spawnSync:o}=await import("node:child_process"),{fileURLToPath:a}=await import("node:url"),s=Mr.dirname(a(import.meta.url)),u=[[Mr.join(s,"cli.cjs"),Mr.join(s,"cli.js")].find(Qn.existsSync)||Mr.join(s,"cli.cjs"),"update"];n?.rules&&u.push(`--rules=${n.rules}`);let l=o(process.execPath,u,{cwd:process.cwd(),stdio:"pipe",encoding:"utf8",env:process.env});if(l.status!==0){let d=(l.stderr||l.stdout||"").trim();throw new Error(`Modeling update failed via CLI: ${d||"Unknown execution error"}`)}return{content:[{type:"text",text:JSON.stringify({status:"SUCCESS",keyApp:r,message:"Alex AI a mod\xE9lis\xE9 le contrat \xE0 partir du contractDraft extrait localement et l'a scell\xE9 \xE0 l'Edge.",actionRequired:"none",directive:`1. La structure des donn\xE9es a \xE9t\xE9 extraite et scell\xE9e \xE0 l'Edge via cli.js.
193
193
  2. MANDATORY PHASE 2 CONCLUSION: Present the sync summary, then ask the user inside this exact visual frame:
194
194
  \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550
195
195
  \u{1F449} PASSAGE EN MODE Live (R\xC9EL) : Voulez-vous activer la base de donn\xE9es r\xE9elle (OZ_PROTOTYPE=false) ?
196
196
  Note : Vos donn\xE9es d'essai seront d\xE9sactiv\xE9es et la base sera initialement vide.
197
- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550`},null,2)}]}}if(t==="oz_publish_function"){let o=ot.object({enterpriseID:ot.string(),functionName:ot.string().min(3).max(40),code:ot.string().min(10),description:ot.string().optional(),isPublic:ot.boolean().optional()}).parse(n),a=await fetch(`https://publishfunction-${fx}`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${i}`},body:JSON.stringify({data:{enterpriseID:o.enterpriseID,functionName:o.functionName,targetType:"inline",code:o.code,description:o.description||"",isPublic:o.isPublic??!1}})}),s=await a.json();if(!a.ok||s.error)throw new Error(s.error?.message||"Failed to deploy function.");return{content:[{type:"text",text:JSON.stringify({status:"SUCCESS",functionName:`$${o.functionName}`,isPublic:o.isPublic??!1,usageHint:`Direct client usage: const res = await oz.call.$${o.functionName}(payload);`},null,2)}]}}throw new Error(`Unknown tool: ${t}`)}catch(r){return{isError:!0,content:[{type:"text",text:`ozmoZ MCP Error: ${r.message}`}]}}});var r4=new Qc;await Mo.connect(r4);
197
+ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550`},null,2)}]}}if(t==="oz_publish_function"){let o=ot.object({enterpriseID:ot.string(),functionName:ot.string().min(3).max(40),code:ot.string().min(10),description:ot.string().optional(),isPublic:ot.boolean().optional()}).parse(n),a=await fetch(`https://publishfunction-${fx}`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${i}`},body:JSON.stringify({data:{enterpriseID:o.enterpriseID,functionName:o.functionName,targetType:"inline",code:o.code,description:o.description||"",isPublic:o.isPublic??!1}})}),s=await a.json();if(!a.ok||s.error)throw new Error(s.error?.message||"Failed to deploy function.");return{content:[{type:"text",text:JSON.stringify({status:"SUCCESS",functionName:`$${o.functionName}`,isPublic:o.isPublic??!1,usageHint:`Direct client usage: const res = await oz.call.$${o.functionName}(payload);`},null,2)}]}}throw new Error(`Unknown tool: ${t}`)}catch(r){return{isError:!0,content:[{type:"text",text:`OZmoz MCP Error: ${r.message}`}]}}});var r4=new Qc;await Mo.connect(r4);