ozmoz 0.1.33 → 0.1.34

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/cli.cjs CHANGED
@@ -1,33 +1,33 @@
1
1
  #!/usr/bin/env node
2
- var i=require("fs"),c=require("path"),W=require("https"),ne=require("http"),b=require("os"),{exec:oe,spawnSync:N}=require("child_process"),re=[c.join(__dirname,"..","scripts","setup-lib.cjs"),c.join(__dirname,"..","..","scripts","setup-lib.cjs"),c.join(__dirname,"scripts","setup-lib.cjs")],se=re.find(i.existsSync)||c.join(__dirname,"..","scripts","setup-lib.cjs"),{runFullSetup:Y,handleAuthAndEnv:K,touchTsConfig:ie,attemptViteAutoImportPatch:ae,injectUniversalRuntime:ce,writeBrowserConfig:le,patchAllowScripts:de}=require(se),ue=!!(process.stdout&&process.stdout.isTTY&&typeof process.stdout.hasColors=="function"&&process.stdout.hasColors(16777216)),pe=ue?"\x1B[38;2;15;156;140m":"\x1B[36m",me="\x1B[31m",q="\x1B[0m";function d(e){console.log(e.replace(/OZmoz|\[|\]|→/g,t=>`${pe}${t}${q}`))}function O(e){console.error(`${me}${e}${q}`)}var x="ozmoz",G=/<!--\s*(?:ozmoz|fleetbo|OZmoz):start[^>]*-->[\s\S]*?<!--\s*(?:ozmoz|fleetbo|OZmoz):end\s*-->/i,fe="<!-- OZmoz:end -->",H="# OZMOZ DATA OS \u2014 DIRECTIVES SYST\xC8ME",F={claude:"Claude Code",cursor:"Cursor",windsurf:"Windsurf",devin:"Devin",codex:"Codex CLI",gemini:"Gemini CLI",antigravity:"Antigravity CLI",copilot:"GitHub Copilot"},j={created:"created",updated:"updated",unchanged:"already up to date",appended:"OZmoz block appended (your own content was kept)",migrated:"old file replaced (backup: <file>.ozmoz-legacy.bak)",invalid:"skipped: the file is not valid JSON, fix or delete it first"};function he(){try{return JSON.parse(i.readFileSync(c.join(__dirname,"..","package.json"),"utf8")).version||"dev"}catch{return"dev"}}var ge=Buffer.from("QUl6YVN5QUM1Uk94STNibklPMUR5TmZsTWhGUnJ0blItNDVwNFJF","base64").toString("utf8");function ye(e){try{let t=JSON.parse(Buffer.from(e.split(".")[1],"base64url").toString("utf8"));return typeof t.exp=="number"&&t.exp*1e3<Date.now()+6e4}catch{return!1}}async function Oe(e,t){let r=await fetch(`https://securetoken.googleapis.com/v1/token?key=${ge}`,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:`grant_type=refresh_token&refresh_token=${encodeURIComponent(t)}`});if(!r.ok)return null;let n=await r.json();return n.id_token?(i.writeFileSync(e,JSON.stringify({devToken:n.id_token,refreshToken:n.refresh_token||t,updatedAt:new Date().toISOString()},null,2)),n.id_token):null}async function ze(){if(process.env.FLEETBO_DEV_TOKEN)return process.env.FLEETBO_DEV_TOKEN;try{let e=c.join(b.homedir(),".fleetbo","credentials.json");if(i.existsSync(e)){let t=JSON.parse(i.readFileSync(e,"utf8"));if(t.devToken&&!ye(t.devToken))return t.devToken;if(t.refreshToken)try{let r=await Oe(e,t.refreshToken);if(r)return r}catch{}}}catch{}return null}async function X(){let e=c.join(b.homedir(),".fleetbo","guidelines.json"),t=await ze();t||O('[OZmoz] Not logged in: run "npx ozmoz login" first to load the full instructions. Using local cache if available.');try{d("[OZmoz] Fetching instructions from Cloud...");let r=await fetch("https://getagentdirectives-jqycakhlxa-uc.a.run.app",{method:"POST",headers:Object.assign({"Content-Type":"application/json"},t?{Authorization:`Bearer ${t}`}:{}),body:JSON.stringify({data:{}})});if(!r.ok)O("[OZmoz] Cloud error HTTP "+r.status);else{let n=await r.json(),s=n.result?.data||n.result||n.data;if(s&&s.protocol&&s.directives)return d("[OZmoz] Instructions loaded successfully."),i.existsSync(c.dirname(e))||i.mkdirSync(c.dirname(e),{recursive:!0}),i.writeFileSync(e,JSON.stringify(s,null,2),"utf8"),s;O("[OZmoz] Empty Cloud response.")}}catch(r){O("[OZmoz] Network error: "+r.message)}if(i.existsSync(e)){d("[OZmoz] Using local cache (~/.fleetbo/guidelines.json)");try{return JSON.parse(i.readFileSync(e,"utf8"))}catch{}}return{protocol:"",directives:"",version:"1.0.0"}}function V(e,t){return"<!-- ozmoz:start v"+e+` -->
2
+ var i=require("fs"),a=require("path"),W=require("https"),ne=require("http"),C=require("os"),{exec:oe,spawnSync:N}=require("child_process"),re=[a.join(__dirname,"..","scripts","setup-lib.cjs"),a.join(__dirname,"..","..","scripts","setup-lib.cjs"),a.join(__dirname,"scripts","setup-lib.cjs")],se=re.find(i.existsSync)||a.join(__dirname,"..","scripts","setup-lib.cjs"),{runFullSetup:Y,handleAuthAndEnv:K,touchTsConfig:ie,attemptViteAutoImportPatch:ae,injectUniversalRuntime:ce,writeBrowserConfig:le,patchAllowScripts:de}=require(se),ue=!!(process.stdout&&process.stdout.isTTY&&typeof process.stdout.hasColors=="function"&&process.stdout.hasColors(16777216)),pe=ue?"\x1B[38;2;15;156;140m":"\x1B[36m",me="\x1B[31m",q="\x1B[0m";function d(e){console.log(e.replace(/OZmoz|\[|\]|→/g,t=>`${pe}${t}${q}`))}function y(e){console.error(`${me}${e}${q}`)}var x="ozmoz",G=/<!--\s*(?:ozmoz|fleetbo|OZmoz):start[^>]*-->[\s\S]*?<!--\s*(?:ozmoz|fleetbo|OZmoz):end\s*-->/i,fe="<!-- OZmoz:end -->",H="# OZMOZ DATA OS \u2014 DIRECTIVES SYST\xC8ME",F={claude:"Claude Code",cursor:"Cursor",windsurf:"Windsurf",devin:"Devin",codex:"Codex CLI",gemini:"Gemini CLI",antigravity:"Antigravity CLI",copilot:"GitHub Copilot"},D={created:"created",updated:"updated",unchanged:"already up to date",appended:"OZmoz block appended (your own content was kept)",migrated:"old file replaced (backup: <file>.ozmoz-legacy.bak)",invalid:"skipped: the file is not valid JSON, fix or delete it first"};function he(){try{return JSON.parse(i.readFileSync(a.join(__dirname,"..","package.json"),"utf8")).version||"dev"}catch{return"dev"}}var ge=Buffer.from("QUl6YVN5QUM1Uk94STNibklPMUR5TmZsTWhGUnJ0blItNDVwNFJF","base64").toString("utf8");function ye(e){try{let t=JSON.parse(Buffer.from(e.split(".")[1],"base64url").toString("utf8"));return typeof t.exp=="number"&&t.exp*1e3<Date.now()+6e4}catch{return!1}}async function Oe(e,t){let r=await fetch(`https://securetoken.googleapis.com/v1/token?key=${ge}`,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:`grant_type=refresh_token&refresh_token=${encodeURIComponent(t)}`});if(!r.ok)return null;let n=await r.json();return n.id_token?(i.writeFileSync(e,JSON.stringify({devToken:n.id_token,refreshToken:n.refresh_token||t,updatedAt:new Date().toISOString()},null,2)),n.id_token):null}async function ze(){if(process.env.FLEETBO_DEV_TOKEN)return process.env.FLEETBO_DEV_TOKEN;try{let e=a.join(C.homedir(),".fleetbo","credentials.json");if(i.existsSync(e)){let t=JSON.parse(i.readFileSync(e,"utf8"));if(t.devToken&&!ye(t.devToken))return t.devToken;if(t.refreshToken)try{let r=await Oe(e,t.refreshToken);if(r)return r}catch{}}}catch{}return null}async function X(){let e=a.join(C.homedir(),".fleetbo","guidelines.json"),t=await ze();t||y('[OZmoz] Not logged in: run "npx ozmoz login" first to load the full instructions. Using local cache if available.');try{d("[OZmoz] Fetching instructions from Cloud...");let r=await fetch("https://getagentdirectives-jqycakhlxa-uc.a.run.app",{method:"POST",headers:Object.assign({"Content-Type":"application/json"},t?{Authorization:`Bearer ${t}`}:{}),body:JSON.stringify({data:{}})});if(!r.ok)y("[OZmoz] Cloud error HTTP "+r.status);else{let n=await r.json(),s=n.result?.data||n.result||n.data;if(s&&s.protocol&&s.directives)return d("[OZmoz] Instructions loaded successfully."),i.existsSync(a.dirname(e))||i.mkdirSync(a.dirname(e),{recursive:!0}),i.writeFileSync(e,JSON.stringify(s,null,2),"utf8"),s;y("[OZmoz] Empty Cloud response.")}}catch(r){y("[OZmoz] Network error: "+r.message)}if(i.existsSync(e)){d("[OZmoz] Using local cache (~/.fleetbo/guidelines.json)");try{return JSON.parse(i.readFileSync(e,"utf8"))}catch{}}return{protocol:"",directives:"",version:"1.0.0"}}function V(e,t){return"<!-- ozmoz:start v"+e+` -->
3
3
  `+t.trim()+`
4
4
  `+fe+`
5
5
  `}function ve(e,t,r){let n=i.existsSync(e)?i.readFileSync(e,"utf8"):null,s,o;return n===null?(s="created",o=t):G.test(n)?(o=n.replace(G,()=>t.trimEnd()),s=o===n?"unchanged":"updated"):n.includes(H)?(s="migrated",o=t):(s="appended",o=n.replace(/\s*$/,`
6
6
 
7
- `)+t),!r&&s!=="unchanged"&&(s==="migrated"&&i.writeFileSync(e+".ozmoz-legacy.bak",n,"utf8"),i.mkdirSync(c.dirname(e),{recursive:!0}),i.writeFileSync(e,o,"utf8")),s}function Q(){return[c.join(__dirname,"ozmoz-mcp.js"),c.join(__dirname,"..","bin","ozmoz-mcp.js"),c.join(__dirname,"bin","ozmoz-mcp.js"),c.join(__dirname,"..","src","bin","ozmoz-mcp.js")].find(t=>i.existsSync(t))||c.resolve(__dirname,"ozmoz-mcp.js")}function M(e,t,r){let n=Object.assign({command:process.execPath,args:[__filename,"mcp","--run"]},r||{}),s={};if(i.existsSync(e))try{let l=JSON.parse(i.readFileSync(e,"utf8"));if(!l||typeof l!="object"||Array.isArray(l))return"invalid";s=l}catch{return"invalid"}let o=s.mcpServers&&s.mcpServers[x];return o&&JSON.stringify(o)===JSON.stringify(n)?"unchanged":(s.mcpServers=s.mcpServers||{},s.mcpServers[x]=n,t||(i.mkdirSync(c.dirname(e),{recursive:!0}),i.writeFileSync(e,JSON.stringify(s,null,2)+`
8
- `,"utf8")),o?"updated":"created")}function R(e){let t=process.platform==="win32"?"where":"which";return N(t,[e],{stdio:"ignore"}).status===0}function $(e,t,r){let n=N(e,t,{encoding:"utf8",timeout:r||3e4,shell:process.platform==="win32"});return{ok:n.status===0,out:(n.stdout||"")+(n.stderr||"")}}function Se(e,t,r){let n=e==="claude"?["--scope",r||"user"]:[],s=Q(),o=["mcp","add"].concat(n,[x,"--",process.execPath,s]),l=["mcp","remove",x].concat(n),a=e+" "+o.join(" ");if(!R(e))return{status:"manual",detail:a};if(t)return{status:"planned",detail:a};let m=$(e,["mcp","list"],6e4),u=m.ok?m.out.split(`
9
- `):[],h=u.find(v=>/^[\s|│┃]*ozmoz(?![\w@-])/.test(v)),p=u.some(v=>/^\s*(?:fleetbo|ozmoz):\s/.test(v));if(h&&h.includes("ozmoz@latest"))return{status:"unchanged",legacy:p};if(h&&!$(e,l).ok)return{status:"manual",detail:e+" "+l.join(" ")+" && "+a,legacy:p};let g=$(e,o);return g.ok?{status:h?"updated":"created",legacy:p}:{status:"failed",detail:a,message:g.out.trim().split(`
10
- `).slice(-2).join(" "),legacy:p}}function Ee(e){let t={user:!1,local:!1,others:[]};try{let r=JSON.parse(i.readFileSync(c.join(b.homedir(),".claude.json"),"utf8")),n=a=>!!a&&typeof a=="object"&&/ozmoz|ozmoz/.test(String(a.command||"")+" "+JSON.stringify(a.args||[])),s=(a,m)=>{!a||typeof a!="object"||Object.keys(a).forEach(u=>{u===x?t[m]=!0:n(a[u])&&t.others.push({name:u,where:m})})};s(r.mcpServers,"user");let o=e;try{o=i.realpathSync(e)}catch{}let l=r.projects||{};Array.from(new Set([e,o])).forEach(a=>s((l[a]||{}).mcpServers,"local"))}catch{}return t}function we(e){let t=Ee(e);t.user&&d(" \u26A0\uFE0F A global (user-scope) '"+x+"' entry from a previous version also exists: the tools appear in every project. To keep them in OZmoz projects only: claude mcp remove "+x+" --scope user"),t.local&&d(" \u26A0\uFE0F A local-scope '"+x+"' entry exists for this folder and takes precedence over .mcp.json. Remove it: claude mcp remove "+x+" --scope local"),t.others.forEach(r=>{d(" \u26A0\uFE0F An old MCP entry named '"+r.name+"' ("+r.where+" scope) points to OZmoz/OZmoz. Remove it: claude mcp remove "+r.name+" --scope "+r.where)})}function Te(e){let t=b.homedir(),r=n=>i.existsSync(n);return{claude:R("claude")||r(c.join(t,".claude")),cursor:r(c.join(e,".cursor"))||r(c.join(t,".cursor"))||R("cursor"),windsurf:r(c.join(t,".codeium","windsurf"))||r(c.join(e,".windsurf")),devin:r(c.join(e,".devin")),codex:R("codex")||r(c.join(t,".codex")),gemini:R("gemini")||r(c.join(t,".gemini")),antigravity:R("agy")||r(c.join(t,".antigravity"))||r(c.join(e,".antigravity")),copilot:R("copilot")||r(c.join(t,".copilot"))}}var be={claude:{bin:"claude",launch:e=>[e]},gemini:{bin:"gemini",launch:e=>["-i",e]},codex:{bin:"codex",launch:e=>[e]},antigravity:{bin:"agy",launch:e=>["-i",e]}};function Ae(e){return String(e||"").replace(/[^\p{L}\p{N} '.,:\-_]/gu," ").replace(/\s+/g," ").trim().slice(0,4e3)}function Ce(e,t,r){let n=Ae(t),s=n?`The user already provided their project description and technical choices: "${n}".
7
+ `)+t),!r&&s!=="unchanged"&&(s==="migrated"&&i.writeFileSync(e+".ozmoz-legacy.bak",n,"utf8"),i.mkdirSync(a.dirname(e),{recursive:!0}),i.writeFileSync(e,o,"utf8")),s}function Q(){return[a.join(__dirname,"ozmoz-mcp.js"),a.join(__dirname,"..","bin","ozmoz-mcp.js"),a.join(__dirname,"bin","ozmoz-mcp.js"),a.join(__dirname,"..","src","bin","ozmoz-mcp.js")].find(t=>i.existsSync(t))||a.resolve(__dirname,"ozmoz-mcp.js")}function M(e,t,r){let n=Object.assign({command:process.execPath,args:[__filename,"mcp","--run"]},r||{}),s={};if(i.existsSync(e))try{let l=JSON.parse(i.readFileSync(e,"utf8"));if(!l||typeof l!="object"||Array.isArray(l))return"invalid";s=l}catch{return"invalid"}let o=s.mcpServers&&s.mcpServers[x];return o&&JSON.stringify(o)===JSON.stringify(n)?"unchanged":(s.mcpServers=s.mcpServers||{},s.mcpServers[x]=n,t||(i.mkdirSync(a.dirname(e),{recursive:!0}),i.writeFileSync(e,JSON.stringify(s,null,2)+`
8
+ `,"utf8")),o?"updated":"created")}function j(e){let t=process.platform==="win32"?"where":"which";return N(t,[e],{stdio:"ignore"}).status===0}function $(e,t,r){let n=N(e,t,{encoding:"utf8",timeout:r||3e4,shell:process.platform==="win32"});return{ok:n.status===0,out:(n.stdout||"")+(n.stderr||"")}}function Se(e,t,r){let n=e==="claude"?["--scope",r||"user"]:[],s=Q(),o=["mcp","add"].concat(n,[x,"--",process.execPath,s]),l=["mcp","remove",x].concat(n),c=e+" "+o.join(" ");if(!j(e))return{status:"manual",detail:c};if(t)return{status:"planned",detail:c};let f=$(e,["mcp","list"],6e4),p=f.ok?f.out.split(`
9
+ `):[],h=p.find(v=>/^[\s|│┃]*ozmoz(?![\w@-])/.test(v)),m=p.some(v=>/^\s*(?:fleetbo|ozmoz):\s/.test(v));if(h&&h.includes("ozmoz@latest"))return{status:"unchanged",legacy:m};if(h&&!$(e,l).ok)return{status:"manual",detail:e+" "+l.join(" ")+" && "+c,legacy:m};let g=$(e,o);return g.ok?{status:h?"updated":"created",legacy:m}:{status:"failed",detail:c,message:g.out.trim().split(`
10
+ `).slice(-2).join(" "),legacy:m}}function Ee(e){let t={user:!1,local:!1,others:[]};try{let r=JSON.parse(i.readFileSync(a.join(C.homedir(),".claude.json"),"utf8")),n=c=>!!c&&typeof c=="object"&&/ozmoz|ozmoz/.test(String(c.command||"")+" "+JSON.stringify(c.args||[])),s=(c,f)=>{!c||typeof c!="object"||Object.keys(c).forEach(p=>{p===x?t[f]=!0:n(c[p])&&t.others.push({name:p,where:f})})};s(r.mcpServers,"user");let o=e;try{o=i.realpathSync(e)}catch{}let l=r.projects||{};Array.from(new Set([e,o])).forEach(c=>s((l[c]||{}).mcpServers,"local"))}catch{}return t}function we(e){let t=Ee(e);t.user&&d(" \u26A0\uFE0F A global (user-scope) '"+x+"' entry from a previous version also exists: the tools appear in every project. To keep them in OZmoz projects only: claude mcp remove "+x+" --scope user"),t.local&&d(" \u26A0\uFE0F A local-scope '"+x+"' entry exists for this folder and takes precedence over .mcp.json. Remove it: claude mcp remove "+x+" --scope local"),t.others.forEach(r=>{d(" \u26A0\uFE0F An old MCP entry named '"+r.name+"' ("+r.where+" scope) points to OZmoz/OZmoz. Remove it: claude mcp remove "+r.name+" --scope "+r.where)})}function Te(e){let t=C.homedir(),r=n=>i.existsSync(n);return{claude:j("claude")||r(a.join(t,".claude")),cursor:r(a.join(e,".cursor"))||r(a.join(t,".cursor"))||j("cursor"),windsurf:r(a.join(t,".codeium","windsurf"))||r(a.join(e,".windsurf")),devin:r(a.join(e,".devin")),codex:j("codex")||r(a.join(t,".codex")),gemini:j("gemini")||r(a.join(t,".gemini")),antigravity:j("agy")||r(a.join(t,".antigravity"))||r(a.join(e,".antigravity")),copilot:j("copilot")||r(a.join(t,".copilot"))}}var be={claude:{bin:"claude",launch:e=>[e]},gemini:{bin:"gemini",launch:e=>["-i",e]},codex:{bin:"codex",launch:e=>[e]},antigravity:{bin:"agy",launch:e=>["-i",e]}};function Ae(e){return String(e||"").replace(/[^\p{L}\p{N} '.,:\-_]/gu," ").replace(/\s+/g," ").trim().slice(0,4e3)}function Ce(e,t,r){let n=Ae(t),s=n?`The user already provided their project description and technical choices: "${n}".
11
11
  - Check if the framework (e.g. React, Vue) is already specified.
12
12
  - If it is, DO NOT ask a generic "what tech do you want" question. Acknowledge their choice naturally (e.g. "J'ai bien not\xE9 que vous souhaitez utiliser React...") and only ask for the missing precision (TypeScript vs JavaScript) in a single friendly confirmation, or proceed directly if obvious.
13
- - Once the user answers, do NOT run exploratory bash commands. IMMEDIATELY call the MCP tool 'oz_create_project' with the application name.`:"Ask me the starter questions from your OZmoz instructions before installing anything: the technology first, then a one-sentence project description, one question at a time.",o=null,l=!0;try{let p=c.join(r,".env");if(i.existsSync(p)){let g=i.readFileSync(p,"utf8"),v=g.match(/^\s*OZ_DB_KEY\s*=\s*(.+?)\s*$/m);v&&(o=v[1].trim());let S=g.match(/^\s*OZ_PROTOTYPE\s*=\s*(.+?)\s*$/m);S&&(l=S[1].trim().toLowerCase()==="true")}}catch{}let a=i.existsSync(c.join(r,"svro.schema.json")),m=i.existsSync(c.join(r,"index.html"))||i.existsSync(c.join(r,"package.json")),u=l?"OZ_PROTOTYPE=true (mode essai / local sandbox)":"OZ_PROTOTYPE=false (mode r\xE9el / live database)",h=o||a?"This folder ALREADY contains an OZmoz project (OZ_DB_KEY="+o+", "+u+"). Do NOT call oz_create_project, and do NOT ask the starter questions. State this in one plain sentence to the user \u2014 then ask what I want to work on now.":m?'This folder does NOT have an OZmoz project yet, but a frontend project ALREADY exists here \u2014 do NOT run "npm create vite" or scaffold a new frontend. Skip the technology question and ask me only for a one-sentence project description, then call oz_create_project directly.':"This folder does NOT contain an OZmoz project yet (no .env, no svro.schema.json). "+s;return"Use OZmoz as the backend of my app. You are in the project folder ("+r+"). Follow your OZmoz local instructions (do NOT run bash commands or web searches to inspect instruction files, they are already active). "+h}function Ie(){let e=process.env;if(e.CLAUDECODE==="1"||e.GEMINI_CLI||e.CODEX_CLI||e.AI_AGENT||e.CURSOR_AGENT||e.ANTIGRAVITY_CLI)return!0;if(process.platform==="win32")return!1;try{let t=N("ps",["-A","-o","pid=,ppid=,args="],{encoding:"utf8"});if(t.status!==0)return!1;let r=new Map;t.stdout.split(`
14
- `).forEach(s=>{let o=s.match(/^\s*(\d+)\s+(\d+)\s+(.*)$/);o&&r.set(Number(o[1]),{ppid:Number(o[2]),args:o[3]})});let n=process.ppid;for(let s=0;n>1&&s<20&&r.has(n);s++){let{ppid:o,args:l}=r.get(n);if(l.split(/\s+/).slice(0,2).some(m=>/(^|\/)(gemini|claude|codex|antigravity|agy)$/.test(m))||/@google\/gemini-cli|@anthropic-ai\/claude-code|@openai\/codex/.test(l))return!0;n=o}}catch{}return!1}function ke(e){let t=process.platform==="win32"?"where":"which";return N(t,[e],{stdio:"ignore"}).status===0}function xe(e,t){let r=t.slice(1).filter(h=>!h.startsWith("--")),n=(r[0]||"").toLowerCase(),s=r.slice(1).join(" "),o=be[n];o||(O('Usage: npx ozmoz start <claude|gemini|codex> ["your app idea"]'),O('Cursor, Windsurf, Devin and GitHub Copilot have no terminal agent to launch: run "npx ozmoz mcp --agent=<cursor|windsurf|devin|copilot>" instead.'),process.exit(1));let l=!1;try{l=!!JSON.parse(i.readFileSync(c.join(b.homedir(),".fleetbo","credentials.json"),"utf8")).devToken}catch{}l||(d("[OZmoz] First use on this machine: sign in (your browser opens, approve once)."),N(process.execPath,[__filename,"login"],{stdio:"inherit",cwd:e,env:Object.assign({},process.env,{FLEETBO_START:"1"})}).status!==0&&(O('Sign-in did not complete. Run "npx ozmoz start '+n+'" again.'),process.exit(1))),N(process.execPath,[__filename,"mcp","--agent="+n],{stdio:"inherit",cwd:e,env:Object.assign({},process.env,{FLEETBO_START:"1"})}).status!==0&&(O("Could not configure "+o.bin+'. Run "npx ozmoz mcp --agent='+n+'" to see why.'),process.exit(1)),Ie()&&(d(`
13
+ - Once the user answers, do NOT run exploratory bash commands. IMMEDIATELY call the MCP tool 'oz_create_project' with the application name.`:"Ask me the starter questions from your OZmoz instructions before installing anything: the technology first, then a one-sentence project description, one question at a time.",o=null,l=!0;try{let m=a.join(r,".env");if(i.existsSync(m)){let g=i.readFileSync(m,"utf8"),v=g.match(/^\s*OZ_DB_KEY\s*=\s*(.+?)\s*$/m);v&&(o=v[1].trim());let S=g.match(/^\s*OZ_PROTOTYPE\s*=\s*(.+?)\s*$/m);S&&(l=S[1].trim().toLowerCase()==="true")}}catch{}let c=i.existsSync(a.join(r,"svro.schema.json")),f=i.existsSync(a.join(r,"index.html"))||i.existsSync(a.join(r,"package.json")),p=l?"OZ_PROTOTYPE=true (mode essai / local sandbox)":"OZ_PROTOTYPE=false (mode r\xE9el / live database)",h=o||c?"This folder ALREADY contains an OZmoz project (OZ_DB_KEY="+o+", "+p+"). Do NOT call oz_create_project, and do NOT ask the starter questions. State this in one plain sentence to the user \u2014 then ask what I want to work on now.":f?'This folder does NOT have an OZmoz project yet, but a frontend project ALREADY exists here \u2014 do NOT run "npm create vite" or scaffold a new frontend. Skip the technology question and ask me only for a one-sentence project description, then call oz_create_project directly.':"This folder does NOT contain an OZmoz project yet (no .env, no svro.schema.json). "+s;return"Use OZmoz as the backend of my app. You are in the project folder ("+r+"). Follow your OZmoz local instructions (do NOT run bash commands or web searches to inspect instruction files, they are already active). "+h}function Ie(){let e=process.env;if(e.CLAUDECODE==="1"||e.GEMINI_CLI||e.CODEX_CLI||e.AI_AGENT||e.CURSOR_AGENT||e.ANTIGRAVITY_CLI)return!0;if(process.platform==="win32")return!1;try{let t=N("ps",["-A","-o","pid=,ppid=,args="],{encoding:"utf8"});if(t.status!==0)return!1;let r=new Map;t.stdout.split(`
14
+ `).forEach(s=>{let o=s.match(/^\s*(\d+)\s+(\d+)\s+(.*)$/);o&&r.set(Number(o[1]),{ppid:Number(o[2]),args:o[3]})});let n=process.ppid;for(let s=0;n>1&&s<20&&r.has(n);s++){let{ppid:o,args:l}=r.get(n);if(l.split(/\s+/).slice(0,2).some(f=>/(^|\/)(gemini|claude|codex|antigravity|agy)$/.test(f))||/@google\/gemini-cli|@anthropic-ai\/claude-code|@openai\/codex/.test(l))return!0;n=o}}catch{}return!1}function ke(e){let t=process.platform==="win32"?"where":"which";return N(t,[e],{stdio:"ignore"}).status===0}function xe(e,t){let r=t.slice(1).filter(h=>!h.startsWith("--")),n=(r[0]||"").toLowerCase(),s=r.slice(1).join(" "),o=be[n];o||(y('Usage: npx ozmoz start <claude|gemini|codex> ["your app idea"]'),y('Cursor, Windsurf, Devin and GitHub Copilot have no terminal agent to launch: run "npx ozmoz mcp --agent=<cursor|windsurf|devin|copilot>" instead.'),process.exit(1));let l=!1;try{l=!!JSON.parse(i.readFileSync(a.join(C.homedir(),".fleetbo","credentials.json"),"utf8")).devToken}catch{}l||(d("[OZmoz] First use on this machine: sign in (your browser opens, approve once)."),N(process.execPath,[__filename,"login"],{stdio:"inherit",cwd:e,env:Object.assign({},process.env,{FLEETBO_START:"1"})}).status!==0&&(y('Sign-in did not complete. Run "npx ozmoz start '+n+'" again.'),process.exit(1))),N(process.execPath,[__filename,"mcp","--agent="+n],{stdio:"inherit",cwd:e,env:Object.assign({},process.env,{FLEETBO_START:"1"})}).status!==0&&(y("Could not configure "+o.bin+'. Run "npx ozmoz mcp --agent='+n+'" to see why.'),process.exit(1)),Ie()&&(d(`
15
15
  [OZmoz] OZmoz is set up in this folder (instruction file + MCP server).
16
- `),process.exit(0)),ke(o.bin)||(O('"'+o.bin+'" is not installed or not in your PATH. Install it, then run: npx ozmoz start '+n),process.exit(1));let m=Ce(o.rules,s,e);d(`
16
+ `),process.exit(0)),ke(o.bin)||(y('"'+o.bin+'" is not installed or not in your PATH. Install it, then run: npx ozmoz start '+n),process.exit(1));let f=Ce(o.rules,s,e);d(`
17
17
  [OZmoz] Launching `+o.bin+` in this folder...
18
- `);let u=N(o.bin,o.launch(process.platform==="win32"?'"'+m+'"':m),{stdio:"inherit",cwd:e,shell:process.platform==="win32"});process.exit(u.status===null?1:u.status)}async function ee(e,t){let r=t.includes("--dry-run"),n=t.find(f=>f.startsWith("--agent=")),s=n&&n.slice(8).trim()?n.slice(8).split(",").map(f=>f.trim().toLowerCase()).filter(Boolean):null,o=null;if(s){o=s.includes("all")?Object.keys(F):s;let f=o.filter(E=>!F[E]);f.length&&(O("Unknown agent(s): "+f.join(", ")+". Valid values: "+Object.keys(F).join(", ")+", all."),process.exit(1))}let l=t.find(f=>f.startsWith("--scope=")),a=l?l.slice(8).trim().toLowerCase():"project";["project","user","local"].includes(a)||(O("Unknown scope: "+a+". Valid values for Claude Code: project (default), user, local."),process.exit(1));let m=Te(e),u=o||Object.keys(F).filter(f=>m[f]),h=he();d(`
19
- [OZmoz] Configuring your AI agents`+(r?" (dry run: nothing is written)":"")+"...");let p=await X(),g=p.version||h,v=`# OZMOZ DATA OS \u2014 DIRECTIVES AGENT
18
+ `);let p=N(o.bin,o.launch(process.platform==="win32"?'"'+f+'"':f),{stdio:"inherit",cwd:e,shell:process.platform==="win32"});process.exit(p.status===null?1:p.status)}async function ee(e,t){let r=t.includes("--dry-run"),n=t.find(u=>u.startsWith("--agent=")),s=n&&n.slice(8).trim()?n.slice(8).split(",").map(u=>u.trim().toLowerCase()).filter(Boolean):null,o=null;if(s){o=s.includes("all")?Object.keys(F):s;let u=o.filter(w=>!F[w]);u.length&&(y("Unknown agent(s): "+u.join(", ")+". Valid values: "+Object.keys(F).join(", ")+", all."),process.exit(1))}let l=t.find(u=>u.startsWith("--scope=")),c=l?l.slice(8).trim().toLowerCase():"project";["project","user","local"].includes(c)||(y("Unknown scope: "+c+". Valid values for Claude Code: project (default), user, local."),process.exit(1));let f=Te(e),p=o||Object.keys(F).filter(u=>f[u]),h=he();d(`
19
+ [OZmoz] Configuring your AI agents`+(r?" (dry run: nothing is written)":"")+"...");let m=await X(),g=m.version||h,v=`# OZMOZ DATA OS \u2014 DIRECTIVES AGENT
20
20
 
21
- `+(p.directives||p.guidelines||"")+`
21
+ `+(m.directives||m.guidelines||"")+`
22
22
 
23
23
  ## PROTOCOLE DONN\xC9ES : QUI FAIT QUOI (AGENT FRONTEND \u2194 ALEX AI)
24
24
 
25
- `+(p.protocol||""),S=V(g,v),z=[["AGENTS.md",S],["GEMINI.md",S],["CLAUDE.md",V(g,`# OZMOZ DATA OS \u2014 DIRECTIVES AGENT
26
- @AGENTS.md`)]],y=c.join(e,".cursorrules");if(i.existsSync(y)){let f=i.readFileSync(y,"utf8");(G.test(f)||f.includes(H))&&z.push([".cursorrules",S])}for(let f of z)d("\u2192 "+f[0]+": "+j[ve(c.join(e,f[0]),f[1],r)]);for(let f of u){let E=F[f];if(f==="cursor")d("\u2192 "+E+" MCP (.cursor/mcp.json): "+j[M(c.join(e,".cursor","mcp.json"),r)]);else if(f==="windsurf")d("\u2192 "+E+" MCP (~/.codeium/windsurf/mcp_config.json): "+j[M(c.join(b.homedir(),".codeium","windsurf","mcp_config.json"),r)]);else if(f==="copilot")d("\u2192 "+E+" MCP (~/.copilot/mcp-config.json): "+j[M(c.join(b.homedir(),".copilot","mcp-config.json"),r,{type:"local",tools:["*"]})]);else if(f==="claude"&&a==="project"){let A=M(c.join(e,".mcp.json"),r);d("\u2192 "+E+" MCP (.mcp.json, project scope): "+j[A]),(A==="created"||A==="updated")&&d(" Claude Code asks you to approve a project server the first time you launch it. Commit .mcp.json to share it with your team (it contains no token)."),we(e)}else if(f==="gemini"){let A=[c.join(b.homedir(),".gemini","settings.json"),c.join(e,".gemini","settings.json"),c.join(e,".mcp.json")],w="unchanged";A.forEach(B=>{let D=M(B,r);(D==="created"||D==="updated")&&(w=D)}),d("\u2192 "+E+" MCP (settings.json & .mcp.json): "+j[w])}else if(f==="claude"||f==="codex"||f==="antigravity"){let A=f==="antigravity"?"agy":f,w=Se(A,r,a);w.status==="manual"?d("\u2192 "+E+": '"+A+"' not found or not scriptable. Run manually: "+w.detail):w.status==="planned"?d("\u2192 "+E+" MCP: would run: "+w.detail):w.status==="failed"?O("\u2192 "+E+" MCP: registration failed ("+w.message+"). Run manually: "+w.detail):d("\u2192 "+E+" MCP"+(f==="claude"?" ("+a+" scope)":"")+": "+j[w.status]),w.legacy&&d(" \u26A0\uFE0F An old MCP entry named 'fleetbo' exists. Remove it: "+A+" mcp remove fleetbo")}else f==="devin"&&d("\u2192 "+E+": reads AGENTS.md. Devin runs in its own environment: add the OZmoz MCP server from Devin's settings (not automated).")}!o&&u.length===0&&d("\u2192 No agent detected: instruction files were written; re-run with --agent=<name> to register the MCP server.");let C=!!(Z(e).FLEETBO_DEV_TOKEN||process.env.FLEETBO_DEV_TOKEN),_=c.join(b.homedir(),".fleetbo","credentials.json");if(i.existsSync(_))try{C=C||!!JSON.parse(i.readFileSync(_,"utf8")).devToken}catch{}C||O('\u26A0\uFE0F No developer token found. Run "npx ozmoz login" once.'),process.env.FLEETBO_START||d(`
25
+ `+(m.protocol||""),S=V(g,v),T=[["AGENTS.md",S],["GEMINI.md",S],["CLAUDE.md",V(g,`# OZMOZ DATA OS \u2014 DIRECTIVES AGENT
26
+ @AGENTS.md`)]],z=a.join(e,".cursorrules");if(i.existsSync(z)){let u=i.readFileSync(z,"utf8");(G.test(u)||u.includes(H))&&T.push([".cursorrules",S])}for(let u of T)d("\u2192 "+u[0]+": "+D[ve(a.join(e,u[0]),u[1],r)]);for(let u of p){let w=F[u];if(u==="cursor")d("\u2192 "+w+" MCP (.cursor/mcp.json): "+D[M(a.join(e,".cursor","mcp.json"),r)]);else if(u==="windsurf")d("\u2192 "+w+" MCP (~/.codeium/windsurf/mcp_config.json): "+D[M(a.join(C.homedir(),".codeium","windsurf","mcp_config.json"),r)]);else if(u==="copilot")d("\u2192 "+w+" MCP (~/.copilot/mcp-config.json): "+D[M(a.join(C.homedir(),".copilot","mcp-config.json"),r,{type:"local",tools:["*"]})]);else if(u==="claude"&&c==="project"){let A=M(a.join(e,".mcp.json"),r);d("\u2192 "+w+" MCP (.mcp.json, project scope): "+D[A]),(A==="created"||A==="updated")&&d(" Claude Code asks you to approve a project server the first time you launch it. Commit .mcp.json to share it with your team (it contains no token)."),we(e)}else if(u==="gemini"){let A=[a.join(C.homedir(),".gemini","settings.json"),a.join(e,".gemini","settings.json"),a.join(e,".mcp.json")],b="unchanged";A.forEach(B=>{let _=M(B,r);(_==="created"||_==="updated")&&(b=_)}),d("\u2192 "+w+" MCP (settings.json & .mcp.json): "+D[b])}else if(u==="claude"||u==="codex"||u==="antigravity"){let A=u==="antigravity"?"agy":u,b=Se(A,r,c);b.status==="manual"?d("\u2192 "+w+": '"+A+"' not found or not scriptable. Run manually: "+b.detail):b.status==="planned"?d("\u2192 "+w+" MCP: would run: "+b.detail):b.status==="failed"?y("\u2192 "+w+" MCP: registration failed ("+b.message+"). Run manually: "+b.detail):d("\u2192 "+w+" MCP"+(u==="claude"?" ("+c+" scope)":"")+": "+D[b.status]),b.legacy&&d(" \u26A0\uFE0F An old MCP entry named 'fleetbo' exists. Remove it: "+A+" mcp remove fleetbo")}else u==="devin"&&d("\u2192 "+w+": reads AGENTS.md. Devin runs in its own environment: add the OZmoz MCP server from Devin's settings (not automated).")}!o&&p.length===0&&d("\u2192 No agent detected: instruction files were written; re-run with --agent=<name> to register the MCP server.");let O=!!(U(e).FLEETBO_DEV_TOKEN||process.env.FLEETBO_DEV_TOKEN),E=a.join(C.homedir(),".fleetbo","credentials.json");if(i.existsSync(E))try{O=O||!!JSON.parse(i.readFileSync(E,"utf8")).devToken}catch{}O||y('\u26A0\uFE0F No developer token found. Run "npx ozmoz login" once.'),process.env.FLEETBO_START||d(`
27
27
  [OZmoz] Done.
28
- `)}function Ne(e){let t=process.platform==="darwin"?"open":process.platform==="win32"?"start":"xdg-open";oe(`${t} "${e}"`)}function _e(e){return new Promise((t,r)=>{let n=ne.createServer((s,o)=>{if(o.setHeader("Access-Control-Allow-Origin","*"),o.setHeader("Access-Control-Allow-Methods","GET, OPTIONS"),o.setHeader("Access-Control-Allow-Headers","Content-Type, Authorization"),o.setHeader("Access-Control-Allow-Private-Network","true"),s.method==="OPTIONS"){o.writeHead(204),o.end();return}let l=new URL(s.url,"http://127.0.0.1");if(l.pathname==="/callback"){let a=l.searchParams.get("token"),m=l.searchParams.get("refresh");if(!a){o.writeHead(400,{"Content-Type":"text/html; charset=utf-8"}),o.end("<h3>Error: Missing token.</h3>");return}let u=c.join(b.homedir(),".fleetbo");i.existsSync(u)||i.mkdirSync(u,{recursive:!0}),i.writeFileSync(c.join(u,"credentials.json"),JSON.stringify({devToken:a,refreshToken:m||null,updatedAt:new Date().toISOString()},null,2));let h=c.join(e,".env");if(i.existsSync(h)){let p=i.readFileSync(h,"utf8");p.includes("FLEETBO_DEV_TOKEN=")?p=p.replace(/FLEETBO_DEV_TOKEN=.*/g,`FLEETBO_DEV_TOKEN=${a}`):p+=`
29
- FLEETBO_DEV_TOKEN=${a}
30
- `,i.writeFileSync(h,p,"utf8")}o.writeHead(200,{"Content-Type":"text/html; charset=utf-8",Connection:"close"}),o.end(`
28
+ `)}function Ne(e){let t=process.platform==="darwin"?"open":process.platform==="win32"?"start":"xdg-open";oe(`${t} "${e}"`)}function _e(e){return new Promise((t,r)=>{let n=ne.createServer((s,o)=>{if(o.setHeader("Access-Control-Allow-Origin","*"),o.setHeader("Access-Control-Allow-Methods","GET, OPTIONS"),o.setHeader("Access-Control-Allow-Headers","Content-Type, Authorization"),o.setHeader("Access-Control-Allow-Private-Network","true"),s.method==="OPTIONS"){o.writeHead(204),o.end();return}let l=new URL(s.url,"http://127.0.0.1");if(l.pathname==="/callback"){let c=l.searchParams.get("token"),f=l.searchParams.get("refresh");if(!c){o.writeHead(400,{"Content-Type":"text/html; charset=utf-8"}),o.end("<h3>Error: Missing token.</h3>");return}let p=a.join(C.homedir(),".fleetbo");i.existsSync(p)||i.mkdirSync(p,{recursive:!0}),i.writeFileSync(a.join(p,"credentials.json"),JSON.stringify({devToken:c,refreshToken:f||null,updatedAt:new Date().toISOString()},null,2));let h=a.join(e,".env");if(i.existsSync(h)){let m=i.readFileSync(h,"utf8");m.includes("FLEETBO_DEV_TOKEN=")?m=m.replace(/FLEETBO_DEV_TOKEN=.*/g,`FLEETBO_DEV_TOKEN=${c}`):m+=`
29
+ FLEETBO_DEV_TOKEN=${c}
30
+ `,i.writeFileSync(h,m,"utf8")}o.writeHead(200,{"Content-Type":"text/html; charset=utf-8",Connection:"close"}),o.end(`
31
31
  <!DOCTYPE html>
32
32
  <html>
33
33
  <head>
@@ -46,22 +46,22 @@ FLEETBO_DEV_TOKEN=${a}
46
46
  </body>
47
47
  </html>
48
48
  `),d(`
49
- [OZmoz] Developer token received and stored successfully!`),!process.env.FLEETBO_START&&!["AGENTS.md","CLAUDE.md","GEMINI.md"].some(p=>i.existsSync(c.join(e,p)))&&(d(`
49
+ [OZmoz] Developer token received and stored successfully!`),!process.env.FLEETBO_START&&!["AGENTS.md","CLAUDE.md","GEMINI.md"].some(m=>i.existsSync(a.join(e,m)))&&(d(`
50
50
  Next step to connect your AI agents:`),d(` npx ozmoz mcp (Configure Claude Code, Cursor, Windsurf, Devin, Codex CLI, Gemini CLI, Antigravity CLI, GitHub Copilot)
51
51
  `)),typeof n.closeAllConnections=="function"&&n.closeAllConnections(),n.close(()=>t()),setTimeout(()=>t(),300)}});n.listen(0,"127.0.0.1",()=>{let o=`https://ozmoz.io/cli-auth?port=${n.address().port}`;d(`
52
- [OZmoz] Waiting for authentication...`),d(`If your browser does not open automatically, visit: ${o}`),Ne(o);let l=Number(process.env.FLEETBO_LOGIN_TIMEOUT_MS)||12e4;setTimeout(()=>{try{typeof n.closeAllConnections=="function"&&n.closeAllConnections()}catch{}n.close(),r(new Error(`Login timed out after ${Math.round(l/1e3)}s: browser approval not received. Run "npx ozmoz login" once more and approve in the browser.`))},l).unref()}),n.on("error",s=>r(s))})}function De(e,t,r){return new Promise((n,s)=>{let o=JSON.stringify({enterpriseID:e,schema:t,workflow:r}),l={hostname:"fleetbo-gatekeeper.fleetbo.workers.dev",path:"/sync-schema",method:"POST",headers:{"Content-Type":"application/json","Content-Length":Buffer.byteLength(o)}},a=W.request(l,m=>{let u="";m.on("data",h=>{u+=h}),m.on("end",()=>{m.statusCode>=200&&m.statusCode<300?n(JSON.parse(u)):s(new Error(`Edge sync failed with HTTP ${m.statusCode}`))})});a.on("error",m=>s(m)),a.write(o),a.end()})}function Z(e){let t=c.join(e,".env");if(!i.existsSync(t))return{};let r=i.readFileSync(t,"utf8"),n={};return r.split(`
53
- `).forEach(s=>{let[o,...l]=s.split("=");o&&l.length>0&&(n[o.trim()]=l.join("=").trim())}),n}function J(e,t){return new Promise((r,n)=>{let s=JSON.stringify({projectId:e,moduleName:t}),o={hostname:"getmodulecache-jqycakhlxa-uc.a.run.app",path:"/",method:"POST",headers:{"Content-Type":"application/json","Content-Length":Buffer.byteLength(s)}},l=W.request(o,a=>{let m="";a.on("data",u=>{m+=u}),a.on("end",()=>{if(a.statusCode>=200&&a.statusCode<300)try{let u=JSON.parse(m);if(u.success&&u.found&&u.module){let h=u.module.code||u.module.mockCode;r(typeof h=="string"?JSON.parse(h):h)}else r(null)}catch{n(new Error(`Invalid JSON response for ${t}.`))}else n(new Error(`Server error ${a.statusCode} while fetching ${t}`))})});l.on("error",a=>n(a)),l.write(s),l.end()})}var I=process.argv.slice(2),k=I[0],Pe=["id","_id","userId","author","dateCreated","createdAt","_schema_version"],te=e=>Pe.includes(e)||/^_/.test(e)||/^(created|updated|modified|deleted)(At|By)$/i.test(e);function U(e){return!e||typeof e!="object"?null:e.fields&&typeof e.fields=="object"?e.fields:e.schema&&typeof e.schema=="object"?e.schema:null}function je(e){let t=[];if(!e||typeof e!="object"||!e.collections)return{schema:e,changed:!1,notes:t};let r=JSON.parse(JSON.stringify(e));return Object.entries(r.collections).forEach(([n,s])=>{let o=U(s);o&&Object.keys(o).forEach(l=>{te(l)&&o[l]&&typeof o[l]=="object"&&o[l].required===!0&&(o[l].required=!1,t.push(n+"."+l))})}),{schema:r,changed:t.length>0,notes:t}}function Re(e){let t=String(typeof e=="string"?e:e&&e.type||"").toLowerCase(),r=e&&(e.enum||e.values||e.options);return Array.isArray(r)&&r.length?JSON.stringify(r[0]):t==="number"||t==="integer"||t==="float"?"0":t==="boolean"||t==="toggle"?"false":t==="date"||t==="datetime"||t==="timestamp"?"new Date().toISOString()":t==="reference"?"'<id du document li\xE9>'":t==="media"?"null /* image/fichier : oz.addWithMedia */":t==="array"?"[]":"'\u2026'"}function Le(e){let r=Object.entries(e&&e.collections||{}),n=`## \u{1F4E5} CE QUE LE CODE DOIT ENVOYER (MOD\xC8LES D'\xC9CRITURE)
52
+ [OZmoz] Waiting for authentication...`),d(`If your browser does not open automatically, visit: ${o}`),Ne(o);let l=Number(process.env.FLEETBO_LOGIN_TIMEOUT_MS)||12e4;setTimeout(()=>{try{typeof n.closeAllConnections=="function"&&n.closeAllConnections()}catch{}n.close(),r(new Error(`Login timed out after ${Math.round(l/1e3)}s: browser approval not received. Run "npx ozmoz login" once more and approve in the browser.`))},l).unref()}),n.on("error",s=>r(s))})}function Pe(e,t,r){return new Promise((n,s)=>{let o=JSON.stringify({enterpriseID:e,schema:t,workflow:r}),l={hostname:"fleetbo-gatekeeper.fleetbo.workers.dev",path:"/sync-schema",method:"POST",headers:{"Content-Type":"application/json","Content-Length":Buffer.byteLength(o)}},c=W.request(l,f=>{let p="";f.on("data",h=>{p+=h}),f.on("end",()=>{f.statusCode>=200&&f.statusCode<300?n(JSON.parse(p)):s(new Error(`Edge sync failed with HTTP ${f.statusCode}`))})});c.on("error",f=>s(f)),c.write(o),c.end()})}function U(e){let t=a.join(e,".env");if(!i.existsSync(t))return{};let r=i.readFileSync(t,"utf8"),n={};return r.split(`
53
+ `).forEach(s=>{let[o,...l]=s.split("=");o&&l.length>0&&(n[o.trim()]=l.join("=").trim())}),n}function J(e,t){return new Promise((r,n)=>{let s=JSON.stringify({projectId:e,moduleName:t}),o={hostname:"getmodulecache-jqycakhlxa-uc.a.run.app",path:"/",method:"POST",headers:{"Content-Type":"application/json","Content-Length":Buffer.byteLength(s)}},l=W.request(o,c=>{let f="";c.on("data",p=>{f+=p}),c.on("end",()=>{if(c.statusCode>=200&&c.statusCode<300)try{let p=JSON.parse(f);if(p.success&&p.found&&p.module){let h=p.module.code||p.module.mockCode;r(typeof h=="string"?JSON.parse(h):h)}else r(null)}catch{n(new Error(`Invalid JSON response for ${t}.`))}else n(new Error(`Server error ${c.statusCode} while fetching ${t}`))})});l.on("error",c=>n(c)),l.write(s),l.end()})}var I=process.argv.slice(2),k=I[0],De=["id","_id","userId","author","dateCreated","createdAt","_schema_version"],te=e=>De.includes(e)||/^_/.test(e)||/^(created|updated|modified|deleted)(At|By)$/i.test(e);function Z(e){return!e||typeof e!="object"?null:e.fields&&typeof e.fields=="object"?e.fields:e.schema&&typeof e.schema=="object"?e.schema:null}function je(e){let t=[];if(!e||typeof e!="object"||!e.collections)return{schema:e,changed:!1,notes:t};let r=JSON.parse(JSON.stringify(e));return Object.entries(r.collections).forEach(([n,s])=>{let o=Z(s);o&&Object.keys(o).forEach(l=>{te(l)&&o[l]&&typeof o[l]=="object"&&o[l].required===!0&&(o[l].required=!1,t.push(n+"."+l))})}),{schema:r,changed:t.length>0,notes:t}}function Re(e){let t=String(typeof e=="string"?e:e&&e.type||"").toLowerCase(),r=e&&(e.enum||e.values||e.options);return Array.isArray(r)&&r.length?JSON.stringify(r[0]):t==="number"||t==="integer"||t==="float"?"0":t==="boolean"||t==="toggle"?"false":t==="date"||t==="datetime"||t==="timestamp"?"new Date().toISOString()":t==="reference"?"'<id du document li\xE9>'":t==="media"?"null /* image/fichier : oz.addWithMedia */":t==="array"?"[]":"'\u2026'"}function Le(e){let r=Object.entries(e&&e.collections||{}),n=`## \u{1F4E5} CE QUE LE CODE DOIT ENVOYER (MOD\xC8LES D'\xC9CRITURE)
54
54
 
55
55
  `;n+=`### \u{1F194} Identifiants
56
- `,n+="* OZmoz attribue lui-m\xEAme `_id` (cha\xEEne) \xE0 chaque document. Utilise `doc._id` partout ; \xE0 la lecture, `doc.id` existe comme alias de `_id` (m\xEAme valeur), en prototype comme en production, mais la r\xE9f\xE9rence est `_id`.\n",n+="* N'envoie **jamais** `id` ni `_id` dans `oz.add` : `oz.add` renvoie `{ success, documentId }` (`documentId` = `_id`).\n",n+="* Pour lire, modifier ou supprimer un document : `oz.getDoc(table, doc._id)`, `oz.update(table, doc._id, {\u2026})`, `oz.delete(table, doc._id)`. Pour relier deux collections, stocke le `_id` du document li\xE9 dans un champ (ex. `playlistId`).\n",n+="* `userId`, `createdAt` et les autres champs de tra\xE7abilit\xE9 sont renseign\xE9s par le moteur : ne les envoie pas.\n\n";let s=r.filter(([,o])=>U(o)&&Object.keys(U(o)).length>0);return s.length===0?n+`_Aucune collection scell\xE9e pour l'instant : les mod\xE8les appara\xEEtront apr\xE8s la mod\xE9lisation d'Alex._
57
- `:(s.forEach(([o,l])=>{let a=U(l),m=Object.entries(a).filter(([p])=>!te(p));n+="### `"+o+`\`
56
+ `,n+="* OZmoz attribue lui-m\xEAme `_id` (cha\xEEne) \xE0 chaque document. Utilise `doc._id` partout ; \xE0 la lecture, `doc.id` existe comme alias de `_id` (m\xEAme valeur), en prototype comme en production, mais la r\xE9f\xE9rence est `_id`.\n",n+="* N'envoie **jamais** `id` ni `_id` dans `oz.add` : `oz.add` renvoie `{ success, documentId }` (`documentId` = `_id`).\n",n+="* Pour lire, modifier ou supprimer un document : `oz.getDoc(table, doc._id)`, `oz.update(table, doc._id, {\u2026})`, `oz.delete(table, doc._id)`. Pour relier deux collections, stocke le `_id` du document li\xE9 dans un champ (ex. `playlistId`).\n",n+="* `userId`, `createdAt` et les autres champs de tra\xE7abilit\xE9 sont renseign\xE9s par le moteur : ne les envoie pas.\n\n";let s=r.filter(([,o])=>Z(o)&&Object.keys(Z(o)).length>0);return s.length===0?n+`_Aucune collection scell\xE9e pour l'instant : les mod\xE8les appara\xEEtront apr\xE8s la mod\xE9lisation d'Alex._
57
+ `:(s.forEach(([o,l])=>{let c=Z(l),f=Object.entries(c).filter(([m])=>!te(m));n+="### `"+o+`\`
58
58
 
59
59
  | Champ | Type | Obligatoire | Valeurs / remarques |
60
60
  |---|---|---|---|
61
- `,m.forEach(([p,g])=>{let v=typeof g=="string"?g:g&&g.type||"any",S=g&&(g.enum||g.values||g.options),z=Array.isArray(S)&&S.length?"parmi : "+S.map(y=>"`"+y+"`").join(", "):"";n+="| `"+p+"` | "+v+" | "+(g&&g.required===!0?"\u2705 oui":"non")+" | "+z+` |
62
- `});let u=m.filter(([,p])=>p&&p.required===!0),h=m.filter(([,p])=>!(p&&p.required===!0));n+="\nInsertion valide :\n```js\nawait oz.add('"+o+`', {
63
- `,u.forEach(([p,g])=>{n+=" "+p+": "+Re(g)+`,
64
- `}),h.length&&(n+=" // optionnels : "+h.map(([p])=>p).join(", ")+`
61
+ `,f.forEach(([m,g])=>{let v=typeof g=="string"?g:g&&g.type||"any",S=g&&(g.enum||g.values||g.options),T=Array.isArray(S)&&S.length?"parmi : "+S.map(z=>"`"+z+"`").join(", "):"";n+="| `"+m+"` | "+v+" | "+(g&&g.required===!0?"\u2705 oui":"non")+" | "+T+` |
62
+ `});let p=f.filter(([,m])=>m&&m.required===!0),h=f.filter(([,m])=>!(m&&m.required===!0));n+="\nInsertion valide :\n```js\nawait oz.add('"+o+`', {
63
+ `,p.forEach(([m,g])=>{n+=" "+m+": "+Re(g)+`,
64
+ `}),h.length&&(n+=" // optionnels : "+h.map(([m])=>m).join(", ")+`
65
65
  `),n+=`}, {
66
66
  `,n+=" desc: 'Cr\xE9ation d\\'un \xE9l\xE9ment dans "+o+`',
67
67
  `,n+=` role: 'AUTHENTICATED' // ou 'ANONYMOUS', 'ADMIN'
@@ -626,27 +626,29 @@ ${JSON.stringify({...e||{},context:void 0},null,2)}
626
626
  \`\`\`json
627
627
  ${JSON.stringify(t||{},null,2)}
628
628
  \`\`\`
629
- `}function Me(e){return String(e).toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g,"").replace(/[^a-z0-9]/g,"_").replace(/^_+|_+$/g,"").slice(0,30)||"app"}async function Ue(e,t){let r=Z(e),n=i.existsSync(c.join(e,"svro.schema.json"));(r.OZ_DB_KEY||n)&&(O("Cannot create project: an OZmoz project already exists in this folder."),d('\u2192 Use "npx ozmoz sync" or evolve the existing contract instead.'),process.exit(1));let s=(t||"").trim();s||(O('Project name is required. Usage: npx ozmoz create "<name>"'),process.exit(1));let o=c.join(e,".ozmoz.lock");if(i.existsSync(o)){let a=!1;try{let m=Number(i.readFileSync(o,"utf8"));Date.now()-m>6e4&&(a=!0)}catch{a=!0}a||(O("A project creation is already running in this folder."),process.exit(1)),i.unlinkSync(o)}i.writeFileSync(o,String(Date.now()));let l=()=>{if(i.existsSync(o))try{i.unlinkSync(o)}catch{}};try{let a=process.env.FLEETBO_DEV_TOKEN;if(!a){let S=c.join(b.homedir(),".fleetbo","credentials.json");if(i.existsSync(S))try{a=JSON.parse(i.readFileSync(S,"utf8")).devToken}catch{}}a||(l(),O('Missing developer token. Please run "npx ozmoz login" first.'),process.exit(1)),d(`[OZmoz] Creating project "${s}" on Cloud...`);let m=Me(s),u=[m,`${m.slice(0,24)}_${Math.random().toString(36).slice(2,6)}`,`${m.slice(0,24)}_${Math.random().toString(36).slice(2,6)}`],h=null,p=null;for(let S of u)try{let z=await fetch("https://createprojectlight-jqycakhlxa-uc.a.run.app",{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${a}`},body:JSON.stringify({data:{name:s,keyApp:S}})}),y=await z.json();if(z.ok&&!y.error){h={keyApp:S,data:y.result?.data||y.data||{}};break}else p=y.error?.message||`HTTP ${z.status}`}catch(z){p=z.message}h||(l(),O(`Failed to create project on Cloud: ${p||"Unknown error"}`),process.exit(1));let g=h.data.bootstrapToken;await K(e,[`--keyApp=${h.keyApp}`,`--token=${g}`]);let v=c.join(e,"package.json");Y(e,v),await ee(e,[]),d(`
629
+ `}function Me(e){return String(e).toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g,"").replace(/[^a-z0-9]/g,"_").replace(/^_+|_+$/g,"").slice(0,30)||"app"}async function Ze(e,t){let r=U(e),n=i.existsSync(a.join(e,"svro.schema.json"));(r.OZ_DB_KEY||n)&&(y("Cannot create project: an OZmoz project already exists in this folder."),d('\u2192 Use "npx ozmoz sync" or evolve the existing contract instead.'),process.exit(1));let s=(t||"").trim();s||(y('Project name is required. Usage: npx ozmoz create "<name>"'),process.exit(1));let o=a.join(e,".ozmoz.lock");if(i.existsSync(o)){let c=!1;try{let f=Number(i.readFileSync(o,"utf8"));Date.now()-f>6e4&&(c=!0)}catch{c=!0}c||(y("A project creation is already running in this folder."),process.exit(1)),i.unlinkSync(o)}i.writeFileSync(o,String(Date.now()));let l=()=>{if(i.existsSync(o))try{i.unlinkSync(o)}catch{}};try{let c=process.env.FLEETBO_DEV_TOKEN;if(!c){let S=a.join(C.homedir(),".fleetbo","credentials.json");if(i.existsSync(S))try{c=JSON.parse(i.readFileSync(S,"utf8")).devToken}catch{}}c||(l(),y('Missing developer token. Please run "npx ozmoz login" first.'),process.exit(1)),d(`[OZmoz] Creating project "${s}" on Cloud...`);let f=Me(s),p=[f,`${f.slice(0,24)}_${Math.random().toString(36).slice(2,6)}`,`${f.slice(0,24)}_${Math.random().toString(36).slice(2,6)}`],h=null,m=null;for(let S of p)try{let T=await fetch("https://createprojectlight-jqycakhlxa-uc.a.run.app",{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${c}`},body:JSON.stringify({data:{name:s,keyApp:S}})}),z=await T.json();if(T.ok&&!z.error){h={keyApp:S,data:z.result?.data||z.data||{}};break}else m=z.error?.message||`HTTP ${T.status}`}catch(T){m=T.message}h||(l(),y(`Failed to create project on Cloud: ${m||"Unknown error"}`),process.exit(1));let g=h.data.bootstrapToken;await K(e,[`--keyApp=${h.keyApp}`,`--token=${g}`]);let v=a.join(e,"package.json");Y(e,v),await ee(e,[]),d(`
630
630
  [OZmoz] Project "${s}" (${h.keyApp}) created and configured successfully.`),d(`AI AGENTS: do NOT stop here and do NOT ask the user to restart. Continue NOW in the same turn: scaffold the frontend if missing, run "npx ozmoz sync", read ozmoz_contract.md, write ALL views in trial mode (OZ_PROTOTYPE=true), then start the dev server and ask the user to validate.
631
- `)}finally{if(i.existsSync(o))try{i.unlinkSync(o)}catch{}}}async function Ze(e){let t=process.env.FLEETBO_DEV_TOKEN;if(!t){let z=c.join(b.homedir(),".fleetbo","credentials.json");if(i.existsSync(z))try{t=JSON.parse(i.readFileSync(z,"utf8")).devToken}catch{}}let n=Z(e).OZ_KEY_APP;(!n||!t)&&(O("Cannot update: project uninitialized or dev token missing."),process.exit(1));let s=i.existsSync(c.join(e,"src"))?c.join(e,"src"):e,o=new Set([".jsx",".tsx",".vue",".svelte",".js",".ts",".html"]),l=[],a=0;function m(z){let y=[];try{y=i.readdirSync(z,{withFileTypes:!0})}catch{return}for(let T of y){if(/^(node_modules|\.git|dist|build|\.next|\.svelte-kit)$/.test(T.name))continue;let C=c.join(z,T.name);if(T.isDirectory())m(C);else if(o.has(c.extname(T.name))&&!T.name.endsWith(".d.ts"))try{let _=i.statSync(C);if(_.size>3e5)continue;let f=i.readFileSync(C,"utf8");/oz\.|<oz-/i.test(f)&&(a+=_.size,l.push({name:c.relative(e,C).split(c.sep).join("/"),content:f}))}catch{}}}m(s),l.length===0&&(O("Cannot update: no components using oz.* found."),process.exit(1)),a>8*1024*1024&&(O("Payload too large: total UI source files exceed 8 MB limit."),process.exit(1));let u=I.find(z=>z.startsWith("--rules=")),h=u?u.slice(8).trim():"",p=I.find(z=>z.startsWith("--reasoning=")),g=p?p.slice(12).trim().toLowerCase():void 0;g!=="standard"&&g!=="high"&&(O("Missing or invalid --reasoning=<standard|high>."),O("If you are an AI agent: ask the user which analysis depth they want (numbered [1]/[2] choice, recommended option first) before running this command, then pass --reasoning=standard or --reasoning=high accordingly. Never pick it yourself."),process.exit(1)),d(`[OZmoz] Sending ${l.length} component(s) to Cloud Engine for modeling...`);try{let z=await fetch("https://updateprojectlight-jqycakhlxa-uc.a.run.app",{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${t}`},body:JSON.stringify({data:{keyApp:n,name:n,newViewFiles:l,oz_rules:h,reasoning:g}})}),y=await z.json();(!z.ok||y.error)&&(O(`Update failed: ${y.error?.message||y.message||"Server error"}`),process.exit(1))}catch(z){O(`Network error: ${z.message}`),process.exit(1)}d("\u2192 Structure modeled. Sealing into OZmoz SVRO Kernel...");let v=N(process.execPath,[__filename,"sync"],{stdio:"inherit",cwd:e}),S=Date.now();for(let z=1;z<=5&&v.status===0;z++){let y=!0;try{let T=JSON.parse(i.readFileSync(c.join(e,"svro.schema.json"),"utf8"));y=Object.keys(T.collections||{}).length>0}catch{}if(y)break;d("\u2192 Contract still empty, waiting for the cloud (attempt "+z+"/5, "+Math.round((Date.now()-S)/1e3)+"s elapsed)..."),Atomics.wait(new Int32Array(new SharedArrayBuffer(4)),0,0,6e3),v=N(process.execPath,[__filename,"sync"],{stdio:"inherit",cwd:e})}v.status===0?d(`
632
- [OZmoz] Contract successfully locked into SVRO Kernel.
633
- `):(O(`
634
- [OZmoz] Kernel sync failed. Run "npx ozmoz sync" manually.
635
- `),process.exit(1))}async function Be(){let e=process.cwd(),t=c.join(e,"package.json");if(k==="init"||k==="doctor")d(`
631
+ `)}finally{if(i.existsSync(o))try{i.unlinkSync(o)}catch{}}}async function Ue(e){let t=process.env.FLEETBO_DEV_TOKEN;if(!t){let O=a.join(C.homedir(),".fleetbo","credentials.json");if(i.existsSync(O))try{t=JSON.parse(i.readFileSync(O,"utf8")).devToken}catch{}}let n=U(e).OZ_KEY_APP;(!n||!t)&&(y("Cannot update: project uninitialized or dev token missing."),process.exit(1));let s=i.existsSync(a.join(e,"src"))?a.join(e,"src"):e,o=new Set([".jsx",".tsx",".vue",".svelte",".js",".ts",".html"]),l=[],c=0;function f(O){let E=[];try{E=i.readdirSync(O,{withFileTypes:!0})}catch{return}for(let u of E){if(/^(node_modules|\.git|dist|build|\.next|\.svelte-kit)$/.test(u.name))continue;let w=a.join(O,u.name);if(u.isDirectory())f(w);else if(o.has(a.extname(u.name))&&!u.name.endsWith(".d.ts"))try{let A=i.statSync(w);if(A.size>3e5)continue;let b=i.readFileSync(w,"utf8");/oz\.|<oz-/i.test(b)&&(c+=A.size,l.push({name:a.relative(e,w).split(a.sep).join("/"),content:b}))}catch{}}}f(s);let p=I.find(O=>O.startsWith("--files=")),h=p?p.slice(8).split(",").map(O=>O.trim()).filter(Boolean):null;if(h&&h.length>0)for(let O of h){let E=a.resolve(e,O);if(i.existsSync(E)){let u=i.readFileSync(E,"utf8");c+=i.statSync(E).size,l.push({name:a.relative(e,E).split(a.sep).join("/"),content:u})}}else f(s);l.length===0&&(y("Cannot update: no components using oz.* found."),process.exit(1)),c>8*1024*1024&&(y("Payload too large: total UI source files exceed 8 MB limit."),process.exit(1));let m=I.find(O=>O.startsWith("--rules=")),g=m?m.slice(8).trim():"",v=I.find(O=>O.startsWith("--reasoning=")),S=v?v.slice(12).trim().toLowerCase():void 0;S!=="standard"&&S!=="high"&&(y("Missing or invalid --reasoning=<standard|high>."),y("If you are an AI agent: ask the user which analysis depth they want (numbered [1]/[2] choice, recommended option first) before running this command, then pass --reasoning=standard or --reasoning=high accordingly. Never pick it yourself."),process.exit(1)),d(`[OZmoz] Sending ${l.length} component(s) to Cloud Engine for modeling...`);try{let O=await fetch("https://updateprojectlight-jqycakhlxa-uc.a.run.app",{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${t}`},body:JSON.stringify({data:{keyApp:n,name:n,newViewFiles:l,oz_rules:g,reasoning:S}})}),E=await O.json();(!O.ok||E.error)&&(y(`Update failed: ${E.error?.message||E.message||"Server error"}`),process.exit(1)),d("\u2192 Cloud modeling response: "+JSON.stringify(E).slice(0,800))}catch(O){y(`Network error: ${O.message}`),process.exit(1)}d("\u2192 Structure modeled. Sealing into OZmoz SVRO Kernel...");let T=N(process.execPath,[__filename,"sync"],{stdio:"inherit",cwd:e}),z=Date.now();for(let O=1;O<=5&&T.status===0;O++){let E=!1;try{let u=JSON.parse(i.readFileSync(a.join(e,"svro.schema.json"),"utf8"));E=Object.keys(u.collections||{}).length>0}catch{}if(E)break;d("\u2192 Contract still empty, waiting for the cloud (attempt "+O+"/5, "+Math.round((Date.now()-z)/1e3)+"s elapsed)..."),await new Promise(u=>setTimeout(u,6e3)),T=N(process.execPath,[__filename,"sync"],{stdio:"inherit",cwd:e})}let R=!1;try{let O=JSON.parse(i.readFileSync(a.join(e,"svro.schema.json"),"utf8"));R=Object.keys(O.collections||{}).length>0}catch{}T.status===0&&R?d(`
632
+ [OZmoz] Contract locked into SVRO Kernel.
633
+ `):T.status===0&&!R?(y(`
634
+ [OZmoz] Sync completed with 0 collections. Rerun with --reasoning=high.
635
+ `),process.exit(1)):(y(`
636
+ [OZmoz] Sync failed. Run "npx ozmoz sync".
637
+ `),process.exit(1))}async function Be(){let e=process.cwd(),t=a.join(e,"package.json");if(k==="init"||k==="doctor")d(`
636
638
  [OZmoz] Initializing and configuring OZmoz...`),await K(e,I),Y(e,t),d(`
637
639
  [OZmoz] Configuration completed successfully!
638
640
  `),d(`
639
641
  Next step:`),d(` npx ozmoz sync (Sync cloud schema & generate IDE types)
640
- `);else if(k==="sync"){let r=I.includes("--dry-run"),n=I.includes("--check-only");d(`[OZmoz] Syncing schema...${r?" (dry-run)":""}${n?" (check-only, no network)":""}`),r||le(e);let s=c.join(e,"svro.schema.json"),o=c.join(e,"svro.workflow.json"),l=c.join(e,"ozmoz_contract.md"),a=c.join(e,"src","ozmoz.d.ts"),u=Z(e).OZ_ENTERPRISE_ID,h=null,p=null;if(n)d("\u2192 Mode check-only : Local contract used, no cloud fetch..");else if(u)try{d("\u2192 Fetching latest contracts from Cloud..."),h=await J(u,"svro.schema.json"),h&&(i.writeFileSync(s,JSON.stringify(h,null,2)+`
641
- `),d("\u2192 Local svro.schema.json updated.")),p=await J(u,"svro.workflow.json"),p&&(i.writeFileSync(o,JSON.stringify(p,null,2)+`
642
- `),d("\u2192 Local svro.workflow.json updated."))}catch(y){O(`\u26A0\uFE0F Cloud fetch bypassed: ${y.message}. Using local file fallback.`)}else O("\u26A0\uFE0F OZ_ENTERPRISE_ID missing in .env. Skipping cloud fetch.");let g=h;if(!g&&i.existsSync(s))try{g=JSON.parse(i.readFileSync(s,"utf8"))}catch{}g||(g={context:"Application en cours de mod\xE9lisation initiale.",collections:{}},i.writeFileSync(s,JSON.stringify(g,null,2)+`
643
- `,"utf8"),d("\u2192 Initial blank svro.schema.json created."));let v=p;if(!v&&i.existsSync(o))try{v=JSON.parse(i.readFileSync(o,"utf8"))}catch{}v||(v={actors:{},sequences:[]},i.writeFileSync(o,JSON.stringify(v,null,2)+`
644
- `,"utf8"),d("\u2192 Initial blank svro.workflow.json created."));{let y=je(g);y.changed&&(g=y.schema,i.writeFileSync(s,JSON.stringify(g,null,2)+`
645
- `,"utf8"),d("\u2192 Managed by system, no longer required from your code: "+y.notes.join(", ")+"."))}let{protocol:S}=await X(),z=Fe(g,v,S);i.writeFileSync(l,z,"utf8"),d("\u2192 Contract markdown successfully generated at project root.");try{let y=Object.keys(g.collections||{});if(u&&!n)try{await De(u,g,v),d("\u2192 Schema successfully sealed into SVRO Kernel (O(1)).")}catch(f){O(`\u26A0\uFE0F Kernel Shield sync warning: ${f.message}`)}let T=g.collections||{},C=Object.entries(T).map(([f,E])=>{let A=E.fields||E.schema||{},w=Object.entries(A).map(([B,D])=>{let L="any",P=String(typeof D=="string"?D:D.type||"").toLowerCase();return P==="string"||P==="text"||P==="media"?L="string":P==="number"?L="number":P==="boolean"||P==="toggle"?L="boolean":P==="array"&&(L="any[]"),` ${B}?:${L};`}).join(`
646
- `);return` ${f}: {
647
- ${w}
642
+ `);else if(k==="sync"){let r=I.includes("--dry-run"),n=I.includes("--check-only");d(`[OZmoz] Syncing schema...${r?" (dry-run)":""}${n?" (check-only, no network)":""}`),r||le(e);let s=a.join(e,"svro.schema.json"),o=a.join(e,"svro.workflow.json"),l=a.join(e,"ozmoz_contract.md"),c=a.join(e,"src","ozmoz.d.ts"),p=U(e).OZ_ENTERPRISE_ID,h=null,m=null;if(n)d("\u2192 Mode check-only : Local contract used, no cloud fetch..");else if(p)try{d("\u2192 Fetching latest contracts from Cloud..."),h=await J(p,"svro.schema.json"),h&&(i.writeFileSync(s,JSON.stringify(h,null,2)+`
643
+ `),d("\u2192 Local svro.schema.json updated.")),m=await J(p,"svro.workflow.json"),m&&(i.writeFileSync(o,JSON.stringify(m,null,2)+`
644
+ `),d("\u2192 Local svro.workflow.json updated."))}catch(z){y(`\u26A0\uFE0F Cloud fetch bypassed: ${z.message}. Using local file fallback.`)}else y("\u26A0\uFE0F OZ_ENTERPRISE_ID missing in .env. Skipping cloud fetch.");let g=h;if(!g&&i.existsSync(s))try{g=JSON.parse(i.readFileSync(s,"utf8"))}catch{}g||(g={context:"Application en cours de mod\xE9lisation initiale.",collections:{}},i.writeFileSync(s,JSON.stringify(g,null,2)+`
645
+ `,"utf8"),d("\u2192 Initial blank svro.schema.json created."));let v=m;if(!v&&i.existsSync(o))try{v=JSON.parse(i.readFileSync(o,"utf8"))}catch{}v||(v={actors:{},sequences:[]},i.writeFileSync(o,JSON.stringify(v,null,2)+`
646
+ `,"utf8"),d("\u2192 Initial blank svro.workflow.json created."));{let z=je(g);z.changed&&(g=z.schema,i.writeFileSync(s,JSON.stringify(g,null,2)+`
647
+ `,"utf8"),d("\u2192 Managed by system, no longer required from your code: "+z.notes.join(", ")+"."))}let{protocol:S}=await X(),T=Fe(g,v,S);i.writeFileSync(l,T,"utf8"),d("\u2192 Contract markdown successfully generated at project root.");try{let z=Object.keys(g.collections||{});if(p&&!n)try{await Pe(p,g,v),d("\u2192 Schema successfully sealed into SVRO Kernel (O(1)).")}catch(u){y(`\u26A0\uFE0F Kernel Shield sync warning: ${u.message}`)}let R=g.collections||{},O=Object.entries(R).map(([u,w])=>{let A=w.fields||w.schema||{},b=Object.entries(A).map(([B,_])=>{let L="any",P=String(typeof _=="string"?_:_.type||"").toLowerCase();return P==="string"||P==="text"||P==="media"?L="string":P==="number"?L="number":P==="boolean"||P==="toggle"?L="boolean":P==="array"&&(L="any[]"),` ${B}?:${L};`}).join(`
648
+ `);return` ${u}: {
649
+ ${b}
648
650
  };`}).join(`
649
- `),_=y.length>0?y.map(f=>`'${f}'`).join(" | "):"string";if(i.existsSync(c.dirname(a))){let f=`/* eslint-disable */
651
+ `),E=z.length>0?z.map(u=>`'${u}'`).join(" | "):"string";if(i.existsSync(a.dirname(c))){let u=`/* eslint-disable */
650
652
  /* prettier-ignore */
651
653
  // @ts-nocheck
652
654
  // Generated by OZmoz \u2014 Updated via sync
@@ -675,7 +677,7 @@ type OzProp = {
675
677
  };
676
678
 
677
679
  interface OzSchemaMap {
678
- ${C}
680
+ ${O}
679
681
  }
680
682
 
681
683
  declare global {
@@ -691,7 +693,7 @@ declare global {
691
693
  interface ImportMeta {
692
694
  readonly env: ImportMetaEnv;
693
695
  }
694
- type KnownOzTables = ${_};
696
+ type KnownOzTables = ${E};
695
697
  type OzTables = KnownOzTables | (string & { _ozPending?: never });
696
698
  type OzData<T extends string> = T extends KnownOzTables
697
699
  ? Partial<OzSchemaMap[T]>
@@ -794,7 +796,7 @@ declare module 'svelte/elements' {
794
796
  'oz-reference': OzProp;
795
797
  }
796
798
  }
797
- `;i.writeFileSync(a,f)}ie(e),ae(e,t),ce(e),de(e),d(`[OZmoz] Schema synced successfully (${y.length} collection(s)).`),r&&d("\u2192 [Dry-run] Schema is valid.")}catch(y){O(`Error during synchronization: ${y.message}`),process.exit(1)}}else if(k==="create"){let r=I.slice(1).filter(n=>!n.startsWith("--")).join(" ");await Ue(e,r),process.exit(0)}else if(k==="update")await Ze(e),process.exit(0);else if(k==="mcp"){let r=I.includes("--run"),n=!1;if(!r&&!process.stdin.isTTY&&(r=await new Promise(s=>{let o=process.stdin,l=null,a=h=>{clearTimeout(l),o.removeListener("data",m),o.removeListener("end",u),o.removeListener("error",u),s(h)},m=h=>{o.pause(),o.unshift(h),n=!0,a(!0)},u=()=>a(!1);l=setTimeout(()=>{o.pause(),a(!1)},1500),o.on("data",m),o.once("end",u),o.once("error",u)})),r){try{await import(`file://${Q()}`),n&&process.stdin.resume()}catch(s){O(`Failed to start MCP server: ${s.message}`),process.exit(1)}return}await ee(e,I),process.exit(0)}else k==="login"?(await _e(e),process.exit(0)):k==="start"?xe(e,I):["--help","-h","help"].includes(k)?(d(`OZmoz CLI
799
+ `;i.writeFileSync(c,u)}ie(e),ae(e,t),ce(e),de(e),d(`[OZmoz] Schema synced successfully (${z.length} collection(s)).`),r&&d("\u2192 [Dry-run] Schema is valid.")}catch(z){y(`Error during synchronization: ${z.message}`),process.exit(1)}}else if(k==="create"){let r=I.slice(1).filter(n=>!n.startsWith("--")).join(" ");await Ze(e,r),process.exit(0)}else if(k==="update")await Ue(e),process.exit(0);else if(k==="mcp"){let r=I.includes("--run"),n=!1;if(!r&&!process.stdin.isTTY&&(r=await new Promise(s=>{let o=process.stdin,l=null,c=h=>{clearTimeout(l),o.removeListener("data",f),o.removeListener("end",p),o.removeListener("error",p),s(h)},f=h=>{o.pause(),o.unshift(h),n=!0,c(!0)},p=()=>c(!1);l=setTimeout(()=>{o.pause(),c(!1)},1500),o.on("data",f),o.once("end",p),o.once("error",p)})),r){try{await import(`file://${Q()}`),n&&process.stdin.resume()}catch(s){y(`Failed to start MCP server: ${s.message}`),process.exit(1)}return}await ee(e,I),process.exit(0)}else k==="login"?(await _e(e),process.exit(0)):k==="start"?xe(e,I):["--help","-h","help"].includes(k)?(d(`OZmoz CLI
798
800
 
799
801
  Commands:
800
802
  login Authenticate this machine (opens the browser: approve once, the command exits by itself)
@@ -810,4 +812,4 @@ Commands:
810
812
 
811
813
  AI agents: to create a project, call the MCP tool "oz_create_project".
812
814
  To evolve schema/workflow from UI files, call the MCP tool "oz_update_project", then run "sync".
813
- `),process.exit(0)):(O('Unknown command. Run "npx ozmoz --help".'),process.exit(1))}Be().catch(e=>{O(`OZmoz CLI Error: ${e.message}`),process.exit(1)});
815
+ `),process.exit(0)):(y('Unknown command. Run "npx ozmoz --help".'),process.exit(1))}Be().catch(e=>{y(`OZmoz CLI Error: ${e.message}`),process.exit(1)});
package/dist/ozmoz-mcp.js CHANGED
@@ -79,7 +79,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
79
79
 
80
80
  Wait for their reply (Enter/'ok' for the recommended one, '2' or the other mode's name for the alternate).`;if(typeof t!="string")throw new Error("STOP: 'modeReply' is required and was not provided. "+s+" Then call this tool again with the exact same arguments, plus 'modeReply' set to the user's literal reply.");let c=t.trim();if(/\b(user|utilisateur|il|elle)\s+(a |ont |)(choisi|chose|picked|selected|confirmed|validated|approved|opté)\b|recommend(ed|é)|implicit|assumed|not applicable|n\/a/i.test(c))throw new Error("STOP: 'modeReply' must be the user's own literal short reply, not your description of what they picked. Show the choice again (same format as before), wait for their next reply, then call this tool again with their exact words.");let l=c.toLowerCase();if(/^(|ok|okay|d'accord|oui|yes|go|vas-?y|allez|sure|1)$/i.test(l)||l===i)return i;if(l==="2"||l===r)return r;throw new Error("STOP: 'modeReply' is missing or could not be mapped to a mode. "+s+" Then call this tool again with the exact same arguments, plus 'modeReply' set to their literal reply. Never write 'modeReply' yourself without an actual user reply.")}async function nC(e){let t=`1. If needed, scaffold the frontend (do not overwrite existing files), then run commandInit.
81
81
  2. Read 'ozmoz_contract.md', then IMMEDIATELY write the UI views in the same turn \u2014 do NOT stop or summarize progress before every view is written.
82
- 3. Once every view is written, start the dev server and ask the user to validate before calling 'oz_update_project'.`;try{let n=await fetch(`https://getagentdirectives-${Fh}`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${e}`},body:JSON.stringify({data:{}})});if(!n.ok)return t;let i=await n.json(),r=i.result?.data||i.result||i.data;return typeof r?.createProjectNextSteps=="string"&&r.createProjectNextSteps.trim()?r.createProjectNextSteps:t}catch{return t}}var Bo=new Yc({name:"ozmoz-mcp",version:"1.0.0"},{capabilities:{tools:{},prompts:{}}});Bo.setRequestHandler(Ep,async()=>({prompts:[{name:"oz_contract_rules",description:"Loads strict architectural rules, invariants, and integrity directives for OZmoz SVRO."}]}));Bo.setRequestHandler(Zp,async e=>{if(e.params.name==="oz_contract_rules")return{description:"Official OZmoz SVRO architecture directives",messages:[{role:"user",content:{type:"text",text:mS}}]};throw new Error(`Unknown prompt: ${e.params.name}`)});Bo.setRequestHandler(Up,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, including this tool's own JSON definition file (e.g. under ~/.gemini/.../mcp/ozmoz/oz_create_project.json) \u2014 you already have this schema in context via the tool list. 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). Do NOT read this tool's own JSON definition file from disk (e.g. under ~/.gemini/.../mcp/ozmoz/oz_update_project.json) before calling it \u2014 you already have this schema in context via the tool list; re-reading it wastes time and tokens for no new information. Before calling this tool, ask the user (like the framework question) which analysis depth they want for this modeling pass: briefly explain what this step does and what each mode costs, THEN show only the two options as a bare list (recommended option first) \u2014 and pass their LITERAL reply as 'modeReply' from your very first call. If you forget and call without it, the tool may fail and tell you to ask; that is a fallback, not the normal path. 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."},reasoning:{type:"string",enum:["standard","high"],description:"DEPRECATED \u2014 ignored. Omit this."},modeReply:{type:"string",description:"MANDATORY \u2014 never omit it, never invent it. Before calling this tool, show the user a numbered [1]/[2] choice for the analysis depth (recommended option first, like you do for the framework question), wait for their reply, then pass their LITERAL reply here (empty/'ok'/'oui' for [1], '2' for [2])."},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","modeReply"]}},{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:{}}}]}));Bo.setRequestHandler(ao,async e=>{let{name:t,arguments:n}=e.params;if(t==="oz_get_contract")return{content:[{type:"text",text:mS}]};let i=await YR();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 eC(o,async d=>{let f=await fetch(`https://createprojectlight-${Fh}`,{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:await nC(i)},null,2)}]}}if(t==="oz_update_project"){tC(n&&n.userApproval);let r=await rC(Gt.resolve(process.cwd()),n&&n.modeReply),o=KR(Gt.resolve(process.cwd()))||n?.keyApp?.trim();if(!o)throw new Error("keyApp not provided and OZ_KEY_APP not found in the project's .env. Pass 'keyApp' explicitly.");let{spawnSync:a}=await import("node:child_process"),{fileURLToPath:s}=await import("node:url"),c=Gt.dirname(s(import.meta.url)),l=[[Gt.join(c,"cli.cjs"),Gt.join(c,"cli.js")].find(fr.existsSync)||Gt.join(c,"cli.cjs"),"update",`--reasoning=${r}`];n?.rules&&l.push(`--rules=${n.rules}`);let d=a(process.execPath,l,{cwd:process.cwd(),stdio:"pipe",encoding:"utf8",env:process.env});if(d.status!==0){let f=(d.stderr||d.stdout||"").trim();throw new Error(`Modeling update failed via CLI: ${f||"Unknown execution error"}`)}return{content:[{type:"text",text:JSON.stringify({status:"SUCCESS",keyApp:o,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.
82
+ 3. Once every view is written, start the dev server and ask the user to validate before calling 'oz_update_project'.`;try{let n=await fetch(`https://getagentdirectives-${Fh}`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${e}`},body:JSON.stringify({data:{}})});if(!n.ok)return t;let i=await n.json(),r=i.result?.data||i.result||i.data;return typeof r?.createProjectNextSteps=="string"&&r.createProjectNextSteps.trim()?r.createProjectNextSteps:t}catch{return t}}var Bo=new Yc({name:"ozmoz-mcp",version:"1.0.0"},{capabilities:{tools:{},prompts:{}}});Bo.setRequestHandler(Ep,async()=>({prompts:[{name:"oz_contract_rules",description:"Loads strict architectural rules, invariants, and integrity directives for OZmoz SVRO."}]}));Bo.setRequestHandler(Zp,async e=>{if(e.params.name==="oz_contract_rules")return{description:"Official OZmoz SVRO architecture directives",messages:[{role:"user",content:{type:"text",text:mS}}]};throw new Error(`Unknown prompt: ${e.params.name}`)});Bo.setRequestHandler(Up,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, including this tool's own JSON definition file (e.g. under ~/.gemini/.../mcp/ozmoz/oz_create_project.json) \u2014 you already have this schema in context via the tool list. 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). Do NOT read this tool's own JSON definition file from disk (e.g. under ~/.gemini/.../mcp/ozmoz/oz_update_project.json) before calling it \u2014 you already have this schema in context via the tool list; re-reading it wastes time and tokens for no new information. Before calling this tool, ask the user (like the framework question) which analysis depth they want for this modeling pass: briefly explain what this step does and what each mode costs, THEN show only the two options as a bare list (recommended option first) \u2014 and pass their LITERAL reply as 'modeReply' from your very first call. If you forget and call without it, the tool may fail and tell you to ask; that is a fallback, not the normal path. 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."},reasoning:{type:"string",enum:["standard","high"],description:"DEPRECATED \u2014 ignored. Omit this."},modeReply:{type:"string",description:"MANDATORY \u2014 never omit it, never invent it. Before calling this tool, show the user a numbered [1]/[2] choice for the analysis depth (recommended option first, like you do for the framework question), wait for their reply, then pass their LITERAL reply here (empty/'ok'/'oui' for [1], '2' for [2])."},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","modeReply"]}},{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:{}}}]}));Bo.setRequestHandler(ao,async e=>{let{name:t,arguments:n}=e.params;if(t==="oz_get_contract")return{content:[{type:"text",text:mS}]};let i=await YR();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 eC(o,async d=>{let f=await fetch(`https://createprojectlight-${Fh}`,{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:await nC(i)},null,2)}]}}if(t==="oz_update_project"){tC(n&&n.userApproval);let r=await rC(Gt.resolve(process.cwd()),n&&n.modeReply),o=KR(Gt.resolve(process.cwd()))||n?.keyApp?.trim();if(!o)throw new Error("keyApp not provided and OZ_KEY_APP not found in the project's .env. Pass 'keyApp' explicitly.");let{spawnSync:a}=await import("node:child_process"),{fileURLToPath:s}=await import("node:url"),c=Gt.dirname(s(import.meta.url)),l=[[Gt.join(c,"cli.js"),Gt.join(c,"cli.cjs")].find(fr.existsSync)||Gt.join(c,"cli.js"),"update",`--reasoning=${r}`];n?.rules&&l.push(`--rules=${n.rules}`),n?.filePaths&&Array.isArray(n.filePaths)&&l.push(`--files=${n.filePaths.join(",")}`);let d=a(process.execPath,l,{cwd:process.cwd(),stdio:"pipe",encoding:"utf8",env:process.env});if(d.status!==0){let f=(d.stderr||d.stdout||"").trim();throw new Error(`Modeling update failed via CLI: ${f||"Unknown execution error"}`)}return{content:[{type:"text",text:JSON.stringify({status:"SUCCESS",keyApp:o,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.
83
83
  2. MANDATORY PHASE 2 CONCLUSION: Present the sync summary, then ask the user inside this exact visual frame:
84
84
  \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
85
85
  \u{1F449} PASSAGE EN MODE Live (R\xC9EL) : Voulez-vous activer la base de donn\xE9es r\xE9elle (OZ_PROTOTYPE=false) ?
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ozmoz",
3
- "version": "0.1.33",
3
+ "version": "0.1.34",
4
4
  "description": "SDK and CLI for the oz.* data API and the <oz-*> web components.",
5
5
  "license": "UNLICENSED",
6
6
  "keywords": [