pando-ai 0.7.8 → 0.8.0

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.
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env node
2
+ "use strict";var N=Object.create;var E=Object.defineProperty;var D=Object.getOwnPropertyDescriptor;var T=Object.getOwnPropertyNames;var j=Object.getPrototypeOf,w=Object.prototype.hasOwnProperty;var C=(e,o,r,n)=>{if(o&&typeof o=="object"||typeof o=="function")for(let t of T(o))!w.call(e,t)&&t!==r&&E(e,t,{get:()=>o[t],enumerable:!(n=D(o,t))||n.enumerable});return e};var h=(e,o,r)=>(r=e!=null?N(j(e)):{},C(o||!e||!e.__esModule?E(r,"default",{value:e,enumerable:!0}):r,e));var u=h(require("fs")),y=h(require("net")),O=h(require("os")),d=h(require("path")),_=require("child_process");var A=h(require("os")),l=h(require("path")),k=["/usr","/bin","/sbin","/System","/Library","/etc","/private/etc","/var","/private/var","/opt","/dev","/Applications"],I=["/Volumes","/mnt","/media","/srv","/tmp","/private/tmp","/private/var/folders"];function L(e){return[l.default.join(e,".ssh"),l.default.join(e,".aws"),l.default.join(e,".gnupg"),l.default.join(e,".config"),l.default.join(e,".pando-ai"),l.default.join(e,".pando-data"),l.default.join(e,"Library")]}function $(e){return["/",e,"/Users","/home"]}function g(e){let o=l.default.resolve(e);return o.length>1&&o.endsWith(l.default.sep)?o.slice(0,-1):o}function S(e,o){if(e===o)return!0;let r=l.default.relative(o,e);return r!==""&&!r.startsWith("..")&&!l.default.isAbsolute(r)}function b(e,o){let r=g(o?.home??A.default.homedir()),n=g(e),t=process.env.PANDO_ALLOW_TEMP_ROOTS==="1",i=new Set(["/var","/private/var"]),c=$(r).map(g);for(let s of c)if(n===s)return s;for(let s of c)if(S(s,n))return s;let p=[...t?k.filter(s=>!i.has(s)):k,...t?[]:I,...L(r)].map(g);for(let s of p)if(S(n,s)||S(s,n))return s;for(let s of["/Users","/home"].map(g)){let a=l.default.relative(s,n);if(a&&!a.startsWith("..")&&!l.default.isAbsolute(a)&&a.split(l.default.sep).filter(Boolean).length===1)return s}return null}var U="/var/run/pando-security-helper.sock",H="PANDO_INTERNAL_SERVE",B="PANDO_HELPER_EXTRA_ROOTS",M="PANDO_REAL_PROJECT_ROOT",R="PANDO_SECURITY_DATA_ROOT",Y="PANDO_SECURITY_SANDBOX_ROOT",V={core:"pando-ai-core",workspace:"pando-ai-ws"},G=["LANG","LC_ALL","LC_CTYPE","LC_MESSAGES"],X=["PANDO_MCP_OUTPUT","PANDO_MCP_CLIENT","CODEX_THREAD_ID","CODEX_SANDBOX","CODEX_MANAGED_BY_NPM"];function f(e,o={}){let r=process.env[R]||d.default.join(O.default.homedir(),".pando-data"),n=process.env.PANDO_GATEWAY_LOG_FILE||d.default.join(r,"gateway-debug.jsonl");try{u.default.mkdirSync(d.default.dirname(n),{recursive:!0}),u.default.appendFileSync(n,`${JSON.stringify({ts:new Date().toISOString(),event:`security_daemon_${e}`,pid:process.pid,...o})}
3
+ `,"utf8")}catch{}}function m(e){let o=d.default.resolve(e);try{return u.default.realpathSync.native(o)}catch{return o}}function v(e,o){let r=d.default.relative(o,e);return r===""||r.length>0&&!r.startsWith("..")&&!d.default.isAbsolute(r)}function q(){return m(process.env[Y]||d.default.join(O.default.homedir(),".pando","sandboxes"))}function J(){let e=process.env[R];if(!e)return null;try{let o=u.default.statSync(e);return{uid:o.uid,gid:o.gid}}catch{return null}}function F(e){if(typeof process.getuid!="function"||process.getuid()!==0)return{ok:!1,error:"security daemon must run as root"};let o=process.env.PANDO_SECURITY_HELPER_SOCKET||U;for(let r=0;r<e.length;r+=1){let n=e[r];if(n==="--socket"){let t=e[++r];if(!t||t.startsWith("--"))return{ok:!1,error:"--socket requires a value"};o=t;continue}return{ok:!1,error:`Unknown security daemon option: ${n}`}}return d.default.isAbsolute(o)?{ok:!0,socketPath:o,cliPath:process.env.PANDO_HELPER_CLI_PATH||d.default.join(d.default.dirname(__dirname),"dist","cli.js"),execPath:process.execPath}:{ok:!1,error:"--socket must be an absolute path"}}function W(e){let o;try{o=JSON.parse(e)}catch{return{ok:!1,error:"Invalid helper request JSON"}}if(!o||typeof o!="object"||Array.isArray(o))return{ok:!1,error:"Invalid helper request"};let r=o,n=new Set(["command","role","projectRoot","realProjectRoot","extraSandboxRoots","stdio"]);for(let t of Object.keys(r))if(!n.has(t))return{ok:!1,error:`Unknown helper request field: ${t}`};return r.command!=="launch"?{ok:!1,error:"Unsupported helper command"}:r.role!=="core"&&r.role!=="workspace"?{ok:!1,error:"Invalid helper launch role"}:typeof r.projectRoot!="string"||!r.projectRoot?{ok:!1,error:"Invalid helper projectRoot"}:r.realProjectRoot!==void 0&&(typeof r.realProjectRoot!="string"||!r.realProjectRoot)?{ok:!1,error:"Invalid helper realProjectRoot"}:r.extraSandboxRoots!==void 0&&(!Array.isArray(r.extraSandboxRoots)||!r.extraSandboxRoots.every(t=>typeof t=="string"&&t.length>0))?{ok:!1,error:"Invalid helper extraSandboxRoots"}:r.stdio!==!0?{ok:!1,error:"Only stdio helper launch is supported"}:{ok:!0,request:{command:"launch",role:r.role,projectRoot:r.projectRoot,realProjectRoot:r.realProjectRoot,extraSandboxRoots:r.extraSandboxRoots,stdio:!0}}}function K(e){let o=(0,_.spawnSync)("id",["-u",e],{encoding:"utf8"});if(o.status!==0)return{ok:!1,error:`Dedicated user '${e}' does not exist`};let r=(0,_.spawnSync)("id",["-g",e],{encoding:"utf8"});if(r.status!==0)return{ok:!1,error:`Could not resolve primary group for '${e}'`};let n=Number(String(o.stdout||"").trim()),t=Number(String(r.stdout||"").trim());return!Number.isInteger(n)||!Number.isInteger(t)?{ok:!1,error:`Invalid uid/gid for '${e}'`}:{ok:!0,uid:n,gid:t}}function z(e,o){let r=d.default.join(e.projectRoot,".pando-sandbox","home",".pando-data"),n={PATH:process.env.PATH||["/opt/homebrew/bin","/usr/local/bin","/usr/bin","/bin","/usr/sbin","/sbin"].join(d.default.delimiter),PANDO_PROCESS_ROLE:e.role,PANDO_SECURITY_HELPER_LAUNCHED:"1",[H]:"1",PANDO_DATA_DIR:r,PANDO_AGENT_SANDBOX_CONTEXT:"1"};for(let t of G)process.env[t]&&(n[t]=process.env[t]);for(let t of X)process.env[t]&&(n[t]=process.env[t]);return e.role==="workspace"&&(n.PANDO_BROKERED_AUTH="1"),n[M]=o,e.role==="workspace"&&(n.PANDO_PUBLISH_TARGET_ROOT=o),e.extraSandboxRoots?.length&&(n[B]=JSON.stringify(e.extraSandboxRoots)),process.env[R]&&(n[R]=process.env[R]),n}function Q(e,o){if(!e.realProjectRoot)return{ok:!1,error:"Helper launch requires realProjectRoot"};let r=m(e.realProjectRoot),n=b(r);if(n)return{ok:!1,error:`Refusing to launch Pando for forbidden project root '${r}' (matches protected path '${n}')`};let t=m(e.projectRoot),i=q();if(!v(t,i))return{ok:!1,error:`Refusing sandbox root outside configured sandbox base: ${t}`};for(let s of e.extraSandboxRoots??[]){let a=m(s);if(!v(a,i))return{ok:!1,error:`Refusing extra sandbox root outside configured sandbox base: ${a}`}}try{if(!u.default.statSync(t).isDirectory())return{ok:!1,error:`Sandbox root is not a directory: ${t}`}}catch(s){return{ok:!1,error:`Sandbox root does not exist: ${t}: ${s?.message||s}`}}let c=K(V[e.role]);if(!c.ok)return c;let p={cwd:t,env:z(e,r),stdio:["pipe","pipe","inherit"]};return p.uid=c.uid,p.gid=c.gid,{ok:!0,child:(0,_.spawn)(o.execPath,[o.cliPath,"serve",t],p)}}function Z(e,o){f("connection");let r=Buffer.alloc(0),n=t=>{r=Buffer.concat([r,t]);let i=r.indexOf(10);if(i===-1){r.length>8192&&(f("request_too_large",{bytes:r.length}),e.end(`Helper request too large
4
+ `));return}e.off("data",n);let c=W(r.slice(0,i).toString("utf8")),p=r.slice(i+1);if(!c.ok){f("parse_failed",{error:c.error}),e.end(`${c.error}
5
+ `);return}let s=Q(c.request,o);if(!s.ok){f("launch_failed",{role:c.request.role,projectRoot:c.request.projectRoot,error:s.error}),console.error(`Pando helper failed to launch MCP server: ${s.error}`),e.end(`${s.error}
6
+ `);return}let a=s.child;f("child_spawned",{childPid:a.pid,role:c.request.role,projectRoot:c.request.projectRoot}),p.length&&a.stdin?.write(p),e.pipe(a.stdin),a.stdout?.pipe(e),e.on("close",()=>{f("socket_closed",{childPid:a.pid});try{a.kill("SIGTERM")}catch{}}),a.on("exit",(P,x)=>{f("child_exit",{childPid:a.pid,code:P,signal:x}),e.end()}),a.on("error",P=>{f("child_error",{childPid:a.pid,error:P.message}),e.end(`Failed to launch Pando MCP server: ${P.message}
7
+ `)})};e.on("data",n)}async function ee(){let e=F(process.argv.slice(2));if(!e.ok)return console.error(e.error),1;try{u.default.mkdirSync(d.default.dirname(e.socketPath),{recursive:!0}),u.default.rmSync(e.socketPath,{force:!0})}catch(o){return console.error(`Could not prepare helper socket ${e.socketPath}: ${o?.message||o}`),1}return await new Promise((o,r)=>{let n=y.default.createServer(i=>Z(i,e));n.on("error",r),n.listen(e.socketPath,()=>{try{let i=J();if(!i)throw new Error(`${R} is not configured or cannot be statted`);u.default.chownSync(e.socketPath,i.uid,i.gid),u.default.chmodSync(e.socketPath,384)}catch(i){f("socket_permission_failed",{socketPath:e.socketPath,error:i?.message||String(i)}),console.error(`Could not secure helper socket ${e.socketPath}: ${i?.message||i}`),n.close(()=>o());return}f("listening",{socketPath:e.socketPath,cliPath:e.cliPath}),console.error(`pando security helper daemon listening on ${e.socketPath}`)});let t=()=>{n.close(()=>{try{u.default.rmSync(e.socketPath,{force:!0})}catch{}o()})};process.once("SIGINT",t),process.once("SIGTERM",t)}),0}ee().then(e=>process.exit(e)).catch(e=>{console.error(`security helper daemon failed: ${e?.message||e}`),process.exit(1)});