@heygaia/cli 0.5.0 → 0.6.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.
Files changed (2) hide show
  1. package/dist/index.js +51 -45
  2. package/package.json +3 -2
package/dist/index.js CHANGED
@@ -1,52 +1,58 @@
1
1
  #!/usr/bin/env node
2
- import{Command as qi}from"commander";var ie={init:"Full setup from scratch (clone, configure, start)",setup:"Configure an existing GAIA repository",status:"Check health of all GAIA services",start:"Start GAIA services (self-host mode)",dev:"Run developer mode in Nx TUI (`gaia dev` or `gaia dev full`)",logs:"Stream logs for running GAIA services",stop:"Stop all GAIA services (safe mode by default)"};import{homedir as Ar}from"node:os";import{join as Tn,resolve as Cn}from"node:path";import{Command as In}from"commander";import{existsSync as qe,mkdirSync as Wo,readFileSync as ir,writeFileSync as wt}from"node:fs";import{homedir as Vo}from"node:os";import{join as bt}from"node:path";var j={PING:"ping",MCP_OPEN:"mcp.open",MCP_CLOSE:"mcp.close",MCP_MSG:"mcp.msg",REVOKE:"revoke",PONG:"pong",HELLO:"hello",MCP_OPENED:"mcp.opened",MCP_ERROR:"mcp.error"},Zt="https://api.heygaia.io",ye="filesystem",er=500,tr=6e4,rr=5e3,or=1e6,nr=5e6;var je=bt(Vo(),".gaia","bridge"),De=bt(je,"credentials.json"),xt=bt(je,"config.json");function sr(){qe(je)||Wo(je,{recursive:!0,mode:448})}function de(){if(!qe(De))return null;try{return JSON.parse(ir(De,"utf-8"))}catch{return null}}function xe(e){sr(),wt(De,JSON.stringify(e,null,2),{mode:384})}function ar(){qe(De)&&wt(De,"{}",{mode:384})}function q(){if(!qe(xt))return{servers:[]};try{return{servers:JSON.parse(ir(xt,"utf-8")).servers??[]}}catch{return{servers:[]}}}function cr(e){sr(),wt(xt,JSON.stringify(e,null,2),{mode:384})}function Ue(e){let t=q(),r=t.servers.findIndex(o=>o.key===e.key);r>=0?t.servers[r]=e:t.servers.push(e),cr(t)}function lr(e){let t=q(),r=t.servers.length;return t.servers=t.servers.filter(o=>o.key!==e),cr(t),t.servers.length<r}function pr(){return q().servers.find(e=>e.type==="filesystem"&&e.key===ye)}function He(e){if(e)return e.replace(/\/$/,"");let t=de();return t?.apiUrl?t.apiUrl.replace(/\/$/,""):(process.env.GAIA_API_URL??Zt).replace(/\/$/,"")}import{hostname as Xo,platform as Jo}from"node:os";var ur={name:"@heygaia/cli",description:"CLI tool for setting up and managing GAIA",version:"0.5.0",type:"module",files:["dist","README.md"],scripts:{build:"esbuild src/index.ts --bundle --platform=node --target=node18 --format=esm --packages=external --outfile=dist/index.js --minify && chmod +x dist/index.js",check:"biome check src",dev:"tsx watch src/index.ts",fix:"biome check --write src",format:"biome format --write src",lint:"pnpm run check","lint:fix":"pnpm run fix",prepublishOnly:"pnpm run build",start:"NODE_ENV=production node dist/index.js","type-check":"tsc --noEmit"},dependencies:{"@inkjs/ui":"^2.0.0","@modelcontextprotocol/sdk":"^1.29.0",commander:"^14.0.3",execa:"^9.6.1",ink:"^6.8.0","ink-big-text":"^2.0.0","ink-gradient":"^3.0.0","ink-text-input":"^6.0.0",react:"19.1.0","react-dom":"19.1.0","simple-git":"^3.36.0",ws:"^8.21.0",zod:"^4.3.6"},devDependencies:{"@biomejs/biome":"^2.5.7","@types/node":"^24.13.3","@types/react":"^19.2.17","@types/react-dom":"^19.2.3","@types/ws":"^8.18.1",esbuild:"^0.25.12",tsx:"^4.23.11",typescript:"^7.0.2",vite:"^7.3.6",vitest:"^4.1.10"},bin:{gaia:"./dist/index.js"},engines:{node:">=20"},keywords:["ai-assistant","cli","gaia","setup"],license:"MIT",publishConfig:{access:"public"},repository:{type:"git",url:"git+https://github.com/theexperiencecompany/gaia.git",directory:"packages/cli"}};var ee=ur.version;var ke=class extends Error{constructor(r,o){super(r);this.status=o;this.name="ApiError"}};async function We(e,t,r,o){let n=await fetch(`${e}/api/v1${t}`,{method:"POST",headers:{"content-type":"application/json",...o?{authorization:`Bearer ${o}`}:{}},body:JSON.stringify(r)});if(!n.ok){let i=`${n.status} ${n.statusText}`;try{let a=await n.json();a.detail&&(i=a.detail)}catch{}throw new ke(i,n.status)}return await n.json()}function dr(e,t,r,o){return We(e,"/device/pair/start",{name:t,platform:r,daemon_version:o})}function mr(e,t){return We(e,"/device/pair/poll",{device_code:t})}function Ve(e,t){return We(e,"/device/token",{refresh_token:t})}function fr(e,t,r,o){return We(e,"/device/servers",{server_key:r,display_name:o},t)}async function Ko(e){await new Promise(t=>setTimeout(t,e))}function gr(){return!!de()?.refreshToken}async function Ye(e={}){let t=He(e.api),r=e.name||Xo(),o=await dr(t,r,Jo(),ee);console.info(`
2
+ import{Command as Qs}from"commander";var le={init:"Full setup from scratch (clone, configure, start)",setup:"Configure an existing GAIA repository",status:"Check health of all GAIA services",start:"Start GAIA services (self-host mode)",dev:"Run developer mode in Nx TUI (`gaia dev` or `gaia dev full`)",logs:"Stream logs for running GAIA services",stop:"Stop all GAIA services (safe mode by default)"};import{Command as Ni}from"commander";import{existsSync as ot,mkdirSync as Jn,readFileSync as Ur,writeFileSync as Gt}from"node:fs";import{homedir as jr}from"node:os";import{join as jt}from"node:path";import{sep as kn}from"node:path";var A={PING:"ping",MCP_OPEN:"mcp.open",MCP_CLOSE:"mcp.close",MCP_MSG:"mcp.msg",REVOKE:"revoke",SERVER_REMOVE:"server.remove",PONG:"pong",HELLO:"hello",MCP_OPENED:"mcp.opened",MCP_ERROR:"mcp.error",EXEC_OPEN:"exec.open",EXEC_STDOUT:"exec.stdout",EXEC_STDERR:"exec.stderr",EXEC_EXIT:"exec.exit"},Dt="https://api.heygaia.io",ye="filesystem",Qe=kn,At=500,Ot=6e4,Lt=5e3,Mt=1e6,Nt=5e6,ze=9e4,Ze=1e6;import{homedir as _n}from"node:os";import{join as Dn}from"node:path";var An={info:e=>console.error(e),error:e=>console.error(e)},Bt={},On=null;function B(){return On??An}function ee(){return{stateDir:Bt.stateDir??Dn(_n(),".gaia","bridge"),env:Bt.env??process.env,shell:Bt.shell??process.env.SHELL??"/bin/sh"}}import{Client as qn}from"@modelcontextprotocol/sdk/client/index.js";import{getDefaultEnvironment as Hn,StdioClientTransport as Vn}from"@modelcontextprotocol/sdk/client/stdio.js";import{StreamableHTTPClientTransport as Wn}from"@modelcontextprotocol/sdk/client/streamableHttp.js";import{InMemoryTransport as Xn}from"@modelcontextprotocol/sdk/inMemory.js";import{lstat as Ln,readdir as Mr,readFile as Ar,realpath as Mn,stat as Nn,writeFile as Bn}from"node:fs/promises";import{dirname as Or,extname as Fn,join as Nr,resolve as $n,sep as Ft}from"node:path";import{McpServer as Gn}from"@modelcontextprotocol/sdk/server/mcp.js";import{z as Ie}from"zod";var jn={".png":"image/png",".jpg":"image/jpeg",".jpeg":"image/jpeg",".webp":"image/webp",".gif":"image/gif"},Pe=class extends Error{};async function $t(e){try{return await Mn(e)}catch{return null}}async function Un(e){try{return(await Ln(e)).isSymbolicLink()}catch{return!1}}function Lr(e,t){return t===Ft?e.startsWith(Ft):e===t||e.startsWith(t+Ft)}async function et(e,t,r){let o=$n(e),n=await $t(o);if(n){if(t.some(a=>Lr(n,a)))return n;throw new Pe(`Path is outside your approved folders: ${e}`)}if(r)throw new Pe(`No such file or directory: ${e}`);let i=await $t(Or(o));if(!i||!t.some(a=>Lr(i,a)))throw new Pe(`Path is outside your approved folders: ${e}`);if(await Un(o))throw new Pe(`Refusing to write through a symlink: ${e}`);return Nr(i,o.slice(Or(o).length+1))}async function Br(e,t,r,o){if(o.length>=r)return;let n;try{n=await Mr(e,{withFileTypes:!0})}catch{return}for(let i of n){if(o.length>=r)return;let a=Nr(e,i.name);i.name.toLowerCase().includes(t.toLowerCase())&&o.push(a),i.isDirectory()&&!i.isSymbolicLink()&&await Br(a,t,r,o)}}function Fr(e){let t=new Gn({name:"gaia-filesystem",version:"0.1.0"}),r=null,o=()=>(r||(r=Promise.all(e.allow.map($t)).then(i=>i.filter(a=>a!==null))),r),n=i=>({isError:!0,content:[{type:"text",text:i}]});return t.registerTool("list_directory",{description:"List the entries (files and folders) in a directory on the user's machine.",inputSchema:{path:Ie.string().describe("Absolute path to a directory")}},async({path:i})=>{try{let a=await et(i,await o(),!0);return{content:[{type:"text",text:(await Mr(a,{withFileTypes:!0})).map(u=>`${u.isDirectory()?"dir ":"file"} ${u.name}`).join(`
3
+ `)||"(empty)"}]}}catch(a){return n(a instanceof Error?a.message:String(a))}}),t.registerTool("read_file",{description:"Read the contents of a text or image file on the user's machine.",inputSchema:{path:Ie.string().describe("Absolute path to a file")}},async({path:i})=>{try{let a=await et(i,await o(),!0),s=await Nn(a);if(!s.isFile())return n(`Not a file: ${i}`);let c=jn[Fn(a).toLowerCase()];if(c){if(s.size>Nt)return n(`Image is too large to read (${s.size} bytes).`);let d=await Ar(a);return{content:[{type:"text",text:`Image file ${a} (${c}, ${s.size} bytes) \u2014 shown below.`},{type:"image",data:d.toString("base64"),mimeType:c}]}}return s.size>Mt?n(`File is too large to read (${s.size} bytes).`):{content:[{type:"text",text:await Ar(a,"utf-8")}]}}catch(a){return n(a instanceof Error?a.message:String(a))}}),t.registerTool("search_files",{description:"Recursively find files/folders whose name contains a query, under a directory.",inputSchema:{path:Ie.string().describe("Absolute path to the directory to search under"),query:Ie.string().describe("Substring to match against names")}},async({path:i,query:a})=>{try{let s=await et(i,await o(),!0),c=[];return await Br(s,a,200,c),{content:[{type:"text",text:c.join(`
4
+ `)||"(no matches)"}]}}catch(s){return n(s instanceof Error?s.message:String(s))}}),e.allowWrite&&t.registerTool("write_file",{description:"Write text to a file on the user's machine (overwrites if it exists).",inputSchema:{path:Ie.string().describe("Absolute path to the file to write"),content:Ie.string().describe("Text content to write")}},async({path:i,content:a})=>{try{let s=await et(i,await o(),!1);return await Bn(s,a,"utf-8"),{content:[{type:"text",text:`Wrote ${a.length} bytes to ${i}`}]}}catch(s){return n(s instanceof Error?s.message:String(s))}}),t}var Yn=new Set(["localhost","127.0.0.1","::1"]),$r=5;function ue(e){let t=new URL(e);if(t.protocol!=="http:"&&t.protocol!=="https:")throw new Error(`url servers must be http(s), got ${t.protocol}`);let r=t.hostname.replace(/^\[|\]$/g,"");if(!Yn.has(r))throw new Error("url servers must point at this machine (localhost / 127.0.0.1 / ::1)");return t}function Kn(e){return new URL(typeof e=="string"?e:e instanceof URL?e.href:e.url)}async function Gr(e,t){let r=Kn(e),o={...t,redirect:"manual"};for(let n=0;;n++){let i=await fetch(r,o);if(i.status<300||i.status>=400)return i;let a=i.headers.get("location"),s=a?new URL(a,r.href):null;if(await i.body?.cancel(),!s||s.origin!==r.origin)throw new Error(`refusing ${i.status} redirect to ${a??"(no location)"} \u2014 an MCP server must be addressed directly, not via a redirect`);if(n>=$r)throw new Error(`too many redirects (>${$r}) \u2014 refusing to follow`);r=s,o={...t,redirect:"manual"}}}async function tt(e){if(e.type==="url"){let n=ue(e.url),i=new Wn(n,{requestInit:{...e.headers?{headers:e.headers}:{}},fetch:Gr});return{transport:i,close:()=>i.close()}}if(e.type==="stdio"){let n=ee().env,i=new Vn({command:e.command,args:e.args,env:{...Hn(),...n.PATH!==void 0?{PATH:n.PATH}:{},...n.HOME!==void 0?{HOME:n.HOME}:{},...e.env}});return{transport:i,close:()=>i.close()}}let[t,r]=Xn.createLinkedPair(),o=Fr(e);return await o.connect(r),{transport:t,close:async()=>{await o.close(),await t.close()}}}async function rt(e){let t=await tt(e),r=new qn({name:"gaia-bridge-test",version:"0.1.0"});try{await r.connect(t.transport);let{tools:o}=await r.listTools();return o.map(n=>n.name)}finally{try{await r.close(),await t.close()}catch{}}}function Ut(){return ee().stateDir}function qt(){return jt(Ut(),"credentials.json")}function qr(){return jt(Ut(),"config.json")}function Hr(){let e=Ut();ot(e)||Jn(e,{recursive:!0,mode:448})}function te(){let e=qt();if(!ot(e))return null;try{return JSON.parse(Ur(e,"utf-8"))}catch{return null}}function Ne(e){Hr(),Gt(qt(),JSON.stringify(e,null,2),{mode:384})}function Be(){let e=qt();ot(e)&&Gt(e,"{}",{mode:384})}function $(){let e=qr();if(!ot(e))return{servers:[]};try{return{servers:JSON.parse(Ur(e,"utf-8")).servers??[]}}catch{return{servers:[]}}}function Vr(e){Hr(),Gt(qr(),JSON.stringify(e,null,2),{mode:384})}function nt(e){e.type==="url"&&ue(e.url);let t=$(),r=t.servers.findIndex(o=>o.key===e.key);r>=0?t.servers[r]=e:t.servers.push(e),Vr(t)}function Fe(e){let t=$(),r=t.servers.length;return t.servers=t.servers.filter(o=>o.key!==e),Vr(t),t.servers.length<r}function Ht(e){return e==="~"?jr():e.startsWith("~/")?jt(jr(),e.slice(2)):e}function Vt(e,t){return{type:"filesystem",key:ye,name:"Local Files",allow:e,allowWrite:t}}function $e(e){if(e)return e.replace(/\/$/,"");let t=te();return t?.apiUrl?t.apiUrl.replace(/\/$/,""):(process.env.GAIA_API_URL??Dt).replace(/\/$/,"")}import{hostname as zn,platform as Zn}from"node:os";var J=class extends Error{constructor(r,o){super(r);this.status=o;this.name="ApiError"}};async function it(e,t,r,o){let n=await fetch(`${e}/api/v1${t}`,{method:"POST",headers:{"content-type":"application/json",...o?{authorization:`Bearer ${o}`}:{}},body:JSON.stringify(r)});if(!n.ok){let i=`${n.status} ${n.statusText}`;try{let a=await n.json();a.detail&&(i=a.detail)}catch{}throw new J(i,n.status)}return await n.json()}async function Qn(e,t,r){let o=await fetch(`${e}/api/v1${t}`,{method:"DELETE",headers:{authorization:`Bearer ${r}`}});if(!o.ok){let n=`${o.status} ${o.statusText}`;try{let i=await o.json();i.detail&&(n=i.detail)}catch{}throw new J(n,o.status)}return await o.json()}function Wt(e,t,r,o){return it(e,"/device/pair/start",{name:t,platform:r,daemon_version:o})}function Xt(e,t){return it(e,"/device/pair/poll",{device_code:t})}function Yt(e,t){return it(e,"/device/token",{refresh_token:t})}function Kt(e,t,r,o,n){return it(e,"/device/servers",{server_key:r,display_name:o,kind:n},t)}function Wr(e,t,r){return Qn(e,`/device/servers/${encodeURIComponent(r)}`,t)}async function ei(e){await new Promise(t=>setTimeout(t,e))}function Jt(){return!!te()?.refreshToken}async function Xr(e,t){let r=$e(t.api),o=t.name||zn(),n=await Wt(r,o,Zn(),t.daemonVersion);e.onPrompt(n.verification_url,n.user_code),e.onStatus?.("Waiting for approval\u2026");let i=Date.now()+n.expires_in*1e3;for(;Date.now()<i;){await ei(n.interval*1e3);let a;try{a=await Xt(r,n.device_code)}catch(s){B().error(`[gaia bridge] poll failed, retrying: ${s instanceof Error?s.message:s}`);continue}if(a.status==="approved"&&a.device_id&&a.refresh_token){Ne({apiUrl:r,deviceId:a.device_id,refreshToken:a.refresh_token}),e.onStatus?.(`
5
+ Paired as "${o}".
6
+ `);return}if(a.status==="denied"||a.status==="expired")throw new Error(`pairing ${a.status}`)}throw new Error("pairing timed out")}var Yr={name:"@heygaia/cli",description:"CLI tool for setting up and managing GAIA",version:"0.6.0",type:"module",files:["dist","README.md"],scripts:{build:"node esbuild.config.mjs && chmod +x dist/index.js",check:"biome check src",dev:"tsx watch src/index.ts",fix:"biome check --write src",format:"biome format --write src",lint:"pnpm run check","lint:fix":"pnpm run fix",prepublishOnly:"pnpm run build",start:"NODE_ENV=production node dist/index.js","type-check":"tsc --noEmit"},dependencies:{"@inkjs/ui":"^2.0.0","@modelcontextprotocol/sdk":"^1.29.0",commander:"^14.0.3",execa:"^9.6.1",ink:"^6.8.0","ink-big-text":"^2.0.0","ink-gradient":"^3.0.0","ink-text-input":"^6.0.0",react:"19.1.0","react-dom":"19.1.0","simple-git":"^3.36.0",ws:"^8.21.0",zod:"^4.3.6"},devDependencies:{"@biomejs/biome":"^2.5.7","@gaia/shared":"workspace:*","@types/node":"^24.13.3","@types/react":"^19.2.17","@types/react-dom":"^19.2.3","@types/ws":"^8.18.1",esbuild:"^0.25.12",tsx:"^4.23.11",typescript:"^7.0.2",vite:"^7.3.6",vitest:"^4.1.10"},bin:{gaia:"./dist/index.js"},engines:{node:">=20"},keywords:["ai-assistant","cli","gaia","setup"],license:"MIT",publishConfig:{access:"public"},repository:{type:"git",url:"git+https://github.com/theexperiencecompany/gaia.git",directory:"packages/cli"}};var ne=Yr.version;var ri={onPrompt(e,t){console.info(`
3
7
  To pair this device, open:
4
- `),console.info(` ${o.verification_url}`),console.info(`
5
- and enter this code: ${o.user_code}
6
- `),console.info("Waiting for approval\u2026");let n=Date.now()+o.expires_in*1e3;for(;Date.now()<n;){await Ko(o.interval*1e3);let i;try{i=await mr(t,o.device_code)}catch(a){console.error(`[gaia bridge] poll failed, retrying: ${a instanceof Error?a.message:a}`);continue}if(i.status==="approved"&&i.device_id&&i.refresh_token){xe({apiUrl:t,deviceId:i.device_id,refreshToken:i.refresh_token}),console.info(`
7
- Paired as "${r}".
8
- `);return}if(i.status==="denied"||i.status==="expired")throw new Error(`pairing ${i.status}`)}throw new Error("pairing timed out")}import{randomInt as mn}from"node:crypto";import Cr from"ws";import{Client as cn}from"@modelcontextprotocol/sdk/client/index.js";import{getDefaultEnvironment as ln,StdioClientTransport as pn}from"@modelcontextprotocol/sdk/client/stdio.js";import{StreamableHTTPClientTransport as un}from"@modelcontextprotocol/sdk/client/streamableHttp.js";import{InMemoryTransport as dn}from"@modelcontextprotocol/sdk/inMemory.js";import{lstat as Qo,readdir as yr,readFile as hr,realpath as zo,stat as Zo,writeFile as en}from"node:fs/promises";import{dirname as vr,extname as tn,join as xr,resolve as rn,sep as on}from"node:path";import{McpServer as nn}from"@modelcontextprotocol/sdk/server/mcp.js";import{z as we}from"zod";var sn={".png":"image/png",".jpg":"image/jpeg",".jpeg":"image/jpeg",".webp":"image/webp",".gif":"image/gif"},be=class extends Error{};async function Tt(e){try{return await zo(e)}catch{return null}}async function an(e){try{return(await Qo(e)).isSymbolicLink()}catch{return!1}}function Sr(e,t){return e===t||e.startsWith(t+on)}async function Xe(e,t,r){let o=rn(e),n=await Tt(o);if(n){if(t.some(a=>Sr(n,a)))return n;throw new be(`Path is outside your approved folders: ${e}`)}if(r)throw new be(`No such file or directory: ${e}`);let i=await Tt(vr(o));if(!i||!t.some(a=>Sr(i,a)))throw new be(`Path is outside your approved folders: ${e}`);if(await an(o))throw new be(`Refusing to write through a symlink: ${e}`);return xr(i,o.slice(vr(o).length+1))}async function wr(e,t,r,o){if(o.length>=r)return;let n;try{n=await yr(e,{withFileTypes:!0})}catch{return}for(let i of n){if(o.length>=r)return;let a=xr(e,i.name);i.name.toLowerCase().includes(t.toLowerCase())&&o.push(a),i.isDirectory()&&!i.isSymbolicLink()&&await wr(a,t,r,o)}}function br(e){let t=new nn({name:"gaia-filesystem",version:"0.1.0"}),r=null,o=()=>(r||(r=Promise.all(e.allow.map(Tt)).then(i=>i.filter(a=>a!==null))),r),n=i=>({isError:!0,content:[{type:"text",text:i}]});return t.registerTool("list_directory",{description:"List the entries (files and folders) in a directory on the user's machine.",inputSchema:{path:we.string().describe("Absolute path to a directory")}},async({path:i})=>{try{let a=await Xe(i,await o(),!0);return{content:[{type:"text",text:(await yr(a,{withFileTypes:!0})).map(p=>`${p.isDirectory()?"dir ":"file"} ${p.name}`).join(`
9
- `)||"(empty)"}]}}catch(a){return n(a instanceof Error?a.message:String(a))}}),t.registerTool("read_file",{description:"Read the contents of a text or image file on the user's machine.",inputSchema:{path:we.string().describe("Absolute path to a file")}},async({path:i})=>{try{let a=await Xe(i,await o(),!0),s=await Zo(a);if(!s.isFile())return n(`Not a file: ${i}`);let c=sn[tn(a).toLowerCase()];if(c){if(s.size>nr)return n(`Image is too large to read (${s.size} bytes).`);let f=await hr(a);return{content:[{type:"text",text:`Image file ${a} (${c}, ${s.size} bytes) \u2014 shown below.`},{type:"image",data:f.toString("base64"),mimeType:c}]}}return s.size>or?n(`File is too large to read (${s.size} bytes).`):{content:[{type:"text",text:await hr(a,"utf-8")}]}}catch(a){return n(a instanceof Error?a.message:String(a))}}),t.registerTool("search_files",{description:"Recursively find files/folders whose name contains a query, under a directory.",inputSchema:{path:we.string().describe("Absolute path to the directory to search under"),query:we.string().describe("Substring to match against names")}},async({path:i,query:a})=>{try{let s=await Xe(i,await o(),!0),c=[];return await wr(s,a,200,c),{content:[{type:"text",text:c.join(`
10
- `)||"(no matches)"}]}}catch(s){return n(s instanceof Error?s.message:String(s))}}),e.allowWrite&&t.registerTool("write_file",{description:"Write text to a file on the user's machine (overwrites if it exists).",inputSchema:{path:we.string().describe("Absolute path to the file to write"),content:we.string().describe("Text content to write")}},async({path:i,content:a})=>{try{let s=await Xe(i,await o(),!1);return await en(s,a,"utf-8"),{content:[{type:"text",text:`Wrote ${a.length} bytes to ${i}`}]}}catch(s){return n(s instanceof Error?s.message:String(s))}}),t}async function Ct(e){if(e.type==="url"){let n=new un(new URL(e.url));return{transport:n,close:()=>n.close()}}if(e.type==="stdio"){let n=new pn({command:e.command,args:e.args,env:{...ln(),...e.env}});return{transport:n,close:()=>n.close()}}let[t,r]=dn.createLinkedPair(),o=br(e);return await o.connect(r),{transport:t,close:async()=>{await o.close(),await t.close()}}}async function Tr(e){let t=await Ct(e),r=new cn({name:"gaia-bridge-test",version:"0.1.0"});try{await r.connect(t.transport);let{tools:o}=await r.listTools();return o.map(n=>n.name)}finally{try{await r.close(),await t.close()}catch{}}}var Je=class{constructor(t){this.creds=t}ws=null;sessions=new Map;reconnectDelay=er;stopped=!1;async run(){for(;!this.stopped;){try{await this.connectOnce()}catch(t){t instanceof ke&&t.status===401?(console.error("[gaia bridge] this device is no longer authorized (revoked or unpaired). Re-pair with: gaia bridge login"),this.stopped=!0):console.error(`[gaia bridge] connection error: ${t instanceof Error?t.message:t}`)}if(this.stopped)break;await this.backoff()}}async stop(){this.stopped=!0,await this.closeAllSessions(),this.ws?.close()}async connectOnce(){let t=await Ve(this.creds.apiUrl,this.creds.refreshToken);this.creds={...this.creds,refreshToken:t.refresh_token},xe(this.creds);let r=`${this.creds.apiUrl.replace(/^http/,"ws")}/api/v1/ws/device`,o=new Cr(r,{headers:{authorization:`Bearer ${t.access_token}`}});this.ws=o,await new Promise((n,i)=>{let a=!1,s=!1,c=p=>{s||(s=!0,p())};o.on("open",()=>{a=!0,this.reconnectDelay=rr;let p=q().servers.map(f=>f.key);this.send({t:j.HELLO,servers:p}),console.error(`[gaia bridge] connected \u2014 exposing: ${p.join(", ")||"(nothing configured)"}`)}),o.on("message",p=>{this.onFrame(p.toString())}),o.on("close",()=>{this.closeAllSessions(),this.ws=null,c(()=>a?n():i(new Error("socket closed before open")))}),o.on("error",p=>{a||c(()=>i(p))})})}async onFrame(t){let r;try{r=JSON.parse(t)}catch{return}switch(r.t){case j.PING:this.send({t:j.PONG});return;case j.MCP_OPEN:await this.openSession(r);return;case j.MCP_MSG:await this.forwardToServer(r);return;case j.MCP_CLOSE:await this.closeSession(r.sid);return;case j.REVOKE:console.error("[gaia bridge] this device was revoked \u2014 exiting."),await this.stop();return;default:return}}async openSession(t){let r=t.sid,o=t.server,n=t.pod;if(!r||!o)return;let i=q().servers.find(a=>a.key===o);if(!i){this.send({t:j.MCP_ERROR,sid:r,pod:n,error:`Unknown server '${o}'`});return}try{let a=await Ct(i);a.transport.onmessage=s=>{this.send({t:j.MCP_MSG,sid:r,pod:n,data:JSON.stringify(s)})},a.transport.onclose=()=>{this.sessions.has(r)&&this.send({t:j.MCP_ERROR,sid:r,pod:n,error:`Local server '${o}' exited`}),this.closeSession(r)},await a.transport.start(),this.sessions.set(r,a),this.send({t:j.MCP_OPENED,sid:r,pod:n})}catch(a){this.send({t:j.MCP_ERROR,sid:r,pod:n,error:a instanceof Error?a.message:String(a)})}}async forwardToServer(t){let r=t.sid?this.sessions.get(t.sid):void 0;if(!(!r||!t.data))try{let o=JSON.parse(t.data);await r.transport.send(o)}catch(o){console.error(`[gaia bridge] forward error: ${o instanceof Error?o.message:o}`)}}async closeSession(t){if(!t)return;let r=this.sessions.get(t);if(r){this.sessions.delete(t);try{await r.close()}catch{}}}async closeAllSessions(){let t=[...this.sessions.keys()];await Promise.all(t.map(r=>this.closeSession(r)))}send(t){this.ws?.readyState===Cr.OPEN&&this.ws.send(JSON.stringify(t))}async backoff(){let t=mn(this.reconnectDelay);console.error(`[gaia bridge] reconnecting in ${t}ms\u2026`),await new Promise(r=>setTimeout(r,t)),this.reconnectDelay=Math.min(this.reconnectDelay*2,tr)}};async function Ke(){let e=de();if(!e?.refreshToken)throw new Error("not paired \u2014 run: gaia bridge login");if(q().servers.length===0)throw new Error("no servers configured \u2014 run: gaia bridge add");pr()?.allowWrite&&console.error("[gaia bridge] filesystem WRITES are enabled for this device.");let t=await Ve(e.apiUrl,e.refreshToken);xe({...e,refreshToken:t.refresh_token});for(let n of q().servers)await fr(e.apiUrl,t.access_token,n.key,n.name);let r=new Je({...e,refreshToken:t.refresh_token}),o=async()=>{console.error(`
11
- [gaia bridge] shutting down\u2026`),await r.stop(),process.exit(0)};process.on("SIGINT",()=>void o()),process.on("SIGTERM",()=>void o()),await r.run()}import{basename as Rr}from"node:path";import{createInterface as Ir}from"node:readline/promises";import{Writable as fn}from"node:stream";async function me(e,t){let r=Ir({input:process.stdin,output:process.stdout});try{let o=t?` [${t}]`:"";return(await r.question(`${e}${o}: `)).trim()||t||""}finally{r.close()}}async function Er(e){process.stdout.write(`${e}: `);let t=new fn({write(o,n,i){i()}}),r=Ir({input:process.stdin,output:t,terminal:!0});try{let o=(await r.question("")).trim();return process.stdout.write(`
12
- `),o}finally{r.close()}}async function _e(e,t=!0){let r=await me(`${e} (${t?"Y/n":"y/N"})`);return r?/^y(es)?$/i.test(r):t}async function It(e,t){for(process.stdout.write(`
8
+ `),console.info(` ${e}`),console.info(`
9
+ and enter this code: ${t}
10
+ `)},onStatus(e){console.info(e)}};async function Re(e={}){await Xr(ri,{...e,daemonVersion:ne})}import{spawn as yi}from"node:child_process";import{existsSync as zt,mkdirSync as xi,openSync as wi,readFileSync as Ei,unlinkSync as to,writeFileSync as bi}from"node:fs";import{homedir as Ti}from"node:os";import{join as Zt}from"node:path";import{mkdirSync as Kr,readFileSync as oi,rmSync as Jr,writeFileSync as ni}from"node:fs";import{dirname as ii,join as Qr}from"node:path";var si=3e4,ai=3e4,ci=50,li=e=>new Promise(t=>setTimeout(t,e));function zr(){return Qr(ee().stateDir,"credentials.lock")}function ui(){return Qr(zr(),"stamp")}async function pi(e){let t=zr(),r=ui();Kr(ii(t),{recursive:!0});let o=Date.now()+ai;for(;;){try{Kr(t);break}catch(i){if(i?.code!=="EEXIST")throw i}let n=null;try{let i=Number(oi(r,"utf-8"));n=Number.isFinite(i)?Date.now()-i:Number.POSITIVE_INFINITY}catch(i){i?.code!=="ENOENT"&&(n=Number.POSITIVE_INFINITY)}if(n===null||n<si){if(Date.now()>o)throw new Error("another gaia process is rotating the device credential \u2014 try again");await li(ci);continue}try{Jr(t,{recursive:!0,force:!0})}catch{}}try{return ni(r,String(Date.now()),{mode:384}),await e()}finally{try{Jr(t,{recursive:!0,force:!0})}catch{}}}async function Ge(){return pi(async()=>{let e=te();if(!e?.refreshToken)throw new J("not paired \u2014 run: gaia bridge login",401);let t=await Yt(e.apiUrl,e.refreshToken),r={...e,refreshToken:t.refresh_token};return Ne(r),{creds:r,accessToken:t.access_token}})}async function ke(){let e=$().servers;if(e.length===0)throw new Error("no servers configured \u2014 run: gaia bridge add");let{creds:t,accessToken:r}=await Ge();await Promise.all(e.map(o=>Kt(t.apiUrl,r,o.key,o.name,o.type)))}async function Qt(e){let t=Fe(e);try{let{creds:r,accessToken:o}=await Ge();await Wr(r.apiUrl,o,e)}catch(r){B().info(`[gaia bridge] removed '${e}' locally; the cloud will reconcile on next connect (${r instanceof Error?r.message:String(r)})`)}return t}import{randomInt as Si}from"node:crypto";import eo from"ws";import{spawn as di}from"node:child_process";import{appendFileSync as mi,mkdirSync as fi}from"node:fs";import{homedir as gi}from"node:os";import{join as hi}from"node:path";function vi(e,t){try{let r=ee().stateDir;fi(r,{recursive:!0,mode:448});let o=t?` (cwd: ${t})`:"";mi(hi(r,"exec-audit.log"),`${new Date().toISOString()}${o} $ ${e}
11
+ `)}catch{}}async function Zr(e,t,r){vi(e,t);let o=di(ee().shell,["-c",e],{cwd:t||gi(),env:ee().env,stdio:["ignore","pipe","pipe"]}),n=0,i=!1,a=c=>u=>{if(i)return;let d=Ze-n,m=u.length>d?u.subarray(0,d):u;m.length>0&&(n+=m.length,r[c](m.toString("utf-8"))),n>=Ze&&(i=!0,r.stderr(`
12
+ [gaia bridge] output truncated \u2014 cap reached
13
+ `),o.kill("SIGKILL"))};o.stdout.on("data",a("stdout")),o.stderr.on("data",a("stderr"));let s=setTimeout(()=>{r.stderr(`
14
+ [gaia bridge] killed \u2014 exceeded ${ze/1e3}s timeout
15
+ `),o.kill("SIGKILL")},ze);await new Promise(c=>{o.on("error",u=>{clearTimeout(s),r.stderr(`[gaia bridge] could not start command: ${u.message}
16
+ `),r.exit(127),c()}),o.on("close",u=>{clearTimeout(s),r.exit(u??-1),c()})})}var je=class{constructor(t){this.creds=t}ws=null;sessions=new Map;reconnectDelay=At;stopped=!1;async run(){for(;!this.stopped;){try{await this.connectOnce()}catch(t){t instanceof J&&t.status===401?(B().error("[gaia bridge] this device is no longer authorized (revoked or unpaired). Re-pair with: gaia bridge login"),this.stopped=!0):B().error(`[gaia bridge] connection error: ${t instanceof Error?t.message:t}`)}if(this.stopped)break;await this.backoff()}}async stop(){this.stopped=!0,await this.closeAllSessions(),this.ws?.close()}async connectOnce(){let{creds:t,accessToken:r}=await Ge();this.creds=t;let o=`${this.creds.apiUrl.replace(/^http/,"ws")}/api/v1/ws/device`,n=new eo(o,{headers:{authorization:`Bearer ${r}`}});this.ws=n,await new Promise((i,a)=>{let s=!1,c=!1,u=d=>{c||(c=!0,d())};n.on("open",()=>{s=!0,this.reconnectDelay=Lt;let d=$().servers.map(m=>m.key);this.send({t:A.HELLO,servers:d}),B().info(`[gaia bridge] connected \u2014 exposing: ${d.join(", ")||"(nothing configured)"}`)}),n.on("message",d=>{this.guardRejection(this.onFrame(d.toString()),"frame handler error")}),n.on("close",()=>{this.guardRejection(this.closeAllSessions(),"session cleanup error"),this.ws=null,u(()=>s?i():a(new Error("socket closed before open")))}),n.on("error",d=>{s||u(()=>a(d))})})}async onFrame(t){let r;try{r=JSON.parse(t)}catch{return}switch(r.t){case A.PING:this.send({t:A.PONG});return;case A.MCP_OPEN:await this.openSession(r);return;case A.MCP_MSG:await this.forwardToServer(r);return;case A.MCP_CLOSE:await this.closeSession(r.sid);return;case A.EXEC_OPEN:await this.runExec(r);return;case A.REVOKE:B().error("[gaia bridge] this device was revoked \u2014 exiting."),await this.stop();return;case A.SERVER_REMOVE:r.key&&Fe(r.key)&&B().info(`[gaia bridge] removed server '${r.key}' (deleted in GAIA).`);return;default:return}}async openSession(t){let r=t.sid,o=t.server,n=t.pod;if(!r||!o)return;let i=$().servers.find(s=>s.key===o);if(!i){this.send({t:A.MCP_ERROR,sid:r,pod:n,error:`Unknown server '${o}'`});return}let a=Date.now();B().info(`[gaia bridge] opening MCP session for '${o}'\u2026`);try{let s=await tt(i);s.transport.onmessage=c=>{this.send({t:A.MCP_MSG,sid:r,pod:n,data:JSON.stringify(c)})},s.transport.onclose=()=>{this.sessions.has(r)&&this.send({t:A.MCP_ERROR,sid:r,pod:n,error:`Local server '${o}' exited`}),this.guardRejection(this.closeSession(r),"session close error")},await s.transport.start(),this.sessions.set(r,s),this.send({t:A.MCP_OPENED,sid:r,pod:n}),B().info(`[gaia bridge] MCP session for '${o}' ready in ${Date.now()-a}ms`)}catch(s){let c=s instanceof Error?s.message:String(s);B().error(`[gaia bridge] MCP session for '${o}' failed after ${Date.now()-a}ms: ${c}`),this.send({t:A.MCP_ERROR,sid:r,pod:n,error:c})}}async forwardToServer(t){let r=t.sid?this.sessions.get(t.sid):void 0;if(!(!r||!t.data))try{let o=JSON.parse(t.data);await r.transport.send(o)}catch(o){B().error(`[gaia bridge] forward error: ${o instanceof Error?o.message:o}`)}}async runExec(t){let r=t.sid,o=t.pod,n=t.command;!r||!n||await Zr(n,t.cwd,{stdout:i=>this.send({t:A.EXEC_STDOUT,sid:r,pod:o,data:i}),stderr:i=>this.send({t:A.EXEC_STDERR,sid:r,pod:o,data:i}),exit:i=>this.send({t:A.EXEC_EXIT,sid:r,pod:o,code:i})})}async closeSession(t){if(!t)return;let r=this.sessions.get(t);if(r){this.sessions.delete(t);try{await r.close()}catch{}}}async closeAllSessions(){let t=[...this.sessions.keys()];await Promise.all(t.map(r=>this.closeSession(r)))}send(t){this.ws?.readyState===eo.OPEN&&this.ws.send(JSON.stringify(t))}guardRejection(t,r){t.catch(o=>{B().error(`[gaia bridge] ${r}: ${o instanceof Error?o.message:o}`)})}async backoff(){let t=Si(this.reconnectDelay);B().info(`[gaia bridge] reconnecting in ${t}ms\u2026`),await new Promise(r=>setTimeout(r,t)),this.reconnectDelay=Math.min(this.reconnectDelay*2,Ot)}};var er=Zt(Ti(),".gaia","bridge"),xe=Zt(er,"daemon.pid"),ro=Zt(er,"daemon.log");function tr(){if(!zt(xe))return null;let e=Number(Ei(xe,"utf-8").trim());if(!e)return null;try{return process.kill(e,0),e}catch{return null}}function oo(){let e=tr();return e?`Tunnel: running in the background (pid ${e}) \u2014 stop with: gaia bridge down`:"Tunnel: not running \u2014 start with: gaia bridge up"}function no(){let e=tr();if(!e){zt(xe)&&to(xe),console.info("No bridge tunnel is running.");return}try{process.kill(e,"SIGTERM")}catch{}zt(xe)&&to(xe),console.info(`Stopped the bridge tunnel (pid ${e}).`)}async function st(){let e=tr();if(e){console.info(`Bridge tunnel is already running (pid ${e}) \u2014 it already serves your configured servers, including any you just added. Nothing else to do.`);return}console.error("[gaia bridge] connected: GAIA can run commands and access files on this machine.");let t=$().servers.filter(a=>a.type==="url"&&a.headers&&Object.keys(a.headers).length>0);t.length>0&&console.error(`[gaia bridge] forwarding request headers (credentials) to ${t.length} local url server(s).`);try{await ke()}catch(a){if(a instanceof J&&a.status===401)console.error(`[gaia bridge] this device is no longer authorized (revoked or unpaired). Let's re-pair.
17
+ `),Be(),await Re(),await ke();else throw a}let r=process.argv[1];if(!r)throw new Error("cannot locate the gaia CLI entrypoint to start the daemon");xi(er,{recursive:!0,mode:448});let o=wi(ro,"a"),n={detached:!0,stdio:["ignore",o,o]},i=yi(process.execPath,[...process.execArgv,r,"bridge","up","--serve"],n);i.unref(),bi(xe,String(i.pid??""),{mode:384}),console.info(`
18
+ Bridge tunnel started in the background (pid ${i.pid}).
19
+ Logs: ${ro}
20
+ Stop: gaia bridge down`)}async function io(){let e=te();if(!e?.refreshToken)throw new Error("not paired \u2014 run: gaia bridge login");let t=new je(e),r=async()=>{await t.stop(),process.exit(0)};process.on("SIGINT",()=>void r()),process.on("SIGTERM",()=>void r()),await t.run()}import{basename as po}from"node:path";import{resolve as Ci}from"node:path";function rr(e){return e.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"").slice(0,60)}function or(e){let t=[],r="",o=null;for(let a of e.trim())o?a===o?o=null:r+=a:a==='"'||a==="'"?o=a:/\s/.test(a)?r&&(t.push(r),r=""):r+=a;r&&t.push(r);let[n,...i]=t;if(!n)throw new Error("Empty command");return{command:n,args:i}}function so(e,t,r){let o={};for(let n of e??[]){let i=n.indexOf(t);if(i<=0)throw new Error(`invalid ${r} '${n}', expected KEY${t}VALUE`);o[n.slice(0,i).trim()]=n.slice(i+1)}return o}function ao(e){let t=rr(e??"");if(!e||!t||t===ye)throw new Error("--name is required and must contain letters or digits");return t}function co(e){if(e.type==="stdio"){if(!e.command)throw new Error("--command is required for --type stdio");let{command:t,args:r}=or(e.command);return{type:"stdio",key:ao(e.name),name:e.name,command:t,args:r,env:so(e.env,"=","--env")}}if(e.type==="url"){if(!e.url)throw new Error("--url is required for --type url");ue(e.url);let t=so(e.header,":","--header");return Object.keys(t).length>0&&new URL(e.url).protocol==="http:"&&console.warn("warning: --header values travel unencrypted over local HTTP \u2014 prefer an https: URL for credential headers"),{type:"url",key:ao(e.name),name:e.name,url:e.url,...Object.keys(t).length?{headers:t}:{}}}if(e.type==="filesystem"){let t=e.path??[];if(t.length===0)throw new Error("--path is required for --type filesystem");let r=t.includes(Qe)?[Qe]:t.map(o=>Ci(Ht(o)));return Vt(r,!!e.write)}throw new Error("--type must be one of: stdio, url, filesystem")}import{createInterface as lo}from"node:readline/promises";import{Writable as Ii}from"node:stream";async function pe(e,t){let r=lo({input:process.stdin,output:process.stdout});try{let o=t?` [${t}]`:"";return(await r.question(`${e}${o}: `)).trim()||t||""}finally{r.close()}}async function uo(e){process.stdout.write(`${e}: `);let t=new Ii({write(o,n,i){i()}}),r=lo({input:process.stdin,output:t,terminal:!0});try{let o=(await r.question("")).trim();return process.stdout.write(`
21
+ `),o}finally{r.close()}}async function de(e,t=!0){let r=await pe(`${e} (${t?"Y/n":"y/N"})`);return r?/^y(es)?$/i.test(r):t}async function at(e,t){for(process.stdout.write(`
13
22
  ${e}
14
23
  `),t.forEach((r,o)=>{process.stdout.write(` ${o+1}. ${r}
15
- `)});;){let r=await me(`Choose 1-${t.length}`),o=Number.parseInt(r,10)-1;if(o>=0&&o<t.length)return o;process.stdout.write(`Invalid choice, try again.
16
- `)}}function gn(e){return e.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"").slice(0,60)}function hn(e){let t=[],r="",o=null;for(let a of e.trim())o?a===o?o=null:r+=a:a==='"'||a==="'"?o=a:/\s/.test(a)?r&&(t.push(r),r=""):r+=a;r&&t.push(r);let[n,...i]=t;if(!n)throw new Error("Empty command");return{command:n,args:i}}function vn(e,t){let o=[...t].reverse().filter(n=>!n.startsWith("-"))[0]??e;return Rr(o).replace(/@[^@]*$/,"")}function Sn(e){try{let t=new URL(e);return t.port?`local-${t.port}`:t.hostname}catch{return""}}async function Dr(e){for(;;){let t=await me("Name for this server",e),r=gn(t);if(!t||!r||r===ye){console.info("Pick a different name.");continue}if(!(q().servers.some(o=>o.key===r)&&!await _e(`'${r}' already exists \u2014 overwrite?`,!1)))return{name:t,key:r}}}function yn(e,t){if(Rr(e)!=="docker")return[];let r=[];for(let o=0;o<t.length;o++){let n=t[o];if(n!==void 0)if(n==="-e"||n==="--env"){let i=t[o+1];i&&!i.includes("=")&&r.push(i)}else n.startsWith("-e")&&n.length>2&&!n.includes("=")&&r.push(n.slice(2))}return[...new Set(r)]}async function Pr(e){let t=process.env[e];if(t!==void 0&&t!==""&&await _e(` Found ${e} in your environment \u2014 use that value?`,!0))return t;for(;;){let r=await Er(` Paste ${e}`);if(r)return console.info(` Got it (${r.length} characters).`),r;console.info(" Empty \u2014 paste the value, or Ctrl+C to abort.")}}async function kr(e,t){let r={};for(let n of yn(e,t))console.info(`
17
- The command needs ${n}.`),r[n]=await Pr(n);let o=Object.keys(r).length?"Any other environment variables to add?":"Does the server need environment variables (API keys, tokens\u2026)?";if(!await _e(o,!1))return r;for(console.info("Enter each variable's name; leave blank when done.");;){let n=(await me(" Variable name")).trim();if(!n)break;if(n in r){console.info(" Already added.");continue}r[n]=await Pr(n)}return r}async function xn(){console.info(`
18
- Examples: npx -y my-mcp-server \xB7 uvx my-server \xB7 docker run -i --rm my/image`);let e=await me("Command that starts your MCP server");if(!e)throw new Error("a command is required");let{command:t,args:r}=hn(e),o=await kr(t,r),{name:n,key:i}=await Dr(vn(t,r));return{type:"stdio",key:i,name:n,command:t,args:r,env:o}}async function wn(){let e=await me("Server URL (e.g. http://localhost:3000/mcp)");if(!e)throw new Error("a URL is required");let{name:t,key:r}=await Dr(Sn(e));return{type:"url",key:r,name:t,url:e}}async function bn(e){for(;;){console.info(`
19
- Testing the connection (this may download/start the server)\u2026`);try{let t=await Tr(e),r=t.slice(0,5).join(", ");return console.info(`Connected \u2014 ${t.length} tools found${r?` (${r}${t.length>5?", \u2026":""})`:""}.`),!0}catch(t){console.error(`Connection failed: ${t instanceof Error?t.message:t}`);let r=["Retry the test"];e.type==="stdio"&&r.push("Re-enter environment variables"),r.push("Save anyway (fix it later)","Abort");let o=r[await It("What now?",r)];if(o==="Re-enter environment variables"&&e.type==="stdio")e.env=await kr(e.command,e.args);else{if(o==="Save anyway (fix it later)")return!0;if(o==="Abort")return!1}}}}async function _r(){gr()||(console.info("This device isn't paired with GAIA yet \u2014 let's do that first."),await Ye());let t=await It("How does your MCP server run?",["A command starts it (stdio) \u2014 npx / uvx / docker / python \u2026","It's already running at a local URL \u2014 e.g. http://localhost:3000/mcp"])===0?await xn():await wn();if(!await bn(t))throw new Error("aborted");Ue(t),console.info(`
20
- Saved '${t.key}'.`),await _e("Connect to GAIA now (gaia bridge up)?")?await Ke():console.info("Run `gaia bridge up` whenever you're ready.")}function En(e){return e==="~"?Ar():e.startsWith("~/")?Tn(Ar(),e.slice(2)):e}function Pn(e,t){let r=e.map(o=>Cn(En(o)));Ue({type:"filesystem",key:ye,name:"Local Files",allow:r,allowWrite:t}),console.info(`Filesystem access configured for:
21
- ${r.join(`
22
- `)}
23
- Writes: ${t?"ENABLED":"disabled (read-only)"}
24
- Run: gaia bridge up`)}function Rn(){let e=de();console.info(e?.deviceId?`Paired (device ${e.deviceId}, ${He()})`:"Not paired \u2014 run: gaia bridge login");let t=q().servers;if(t.length===0){console.info("No servers configured \u2014 run: gaia bridge add");return}console.info(`
25
- Configured servers:`);for(let r of t)if(r.type==="filesystem")console.info(` [${r.key}] filesystem${r.allowWrite?" (rw)":" (ro)"}: ${r.allow.join(", ")}`);else if(r.type==="stdio"){let o=Object.keys(r.env);console.info(` [${r.key}] ${r.name}: ${r.command} ${r.args.join(" ")}`),o.length&&console.info(` env: ${o.join(", ")}`)}else console.info(` [${r.key}] ${r.name}: ${r.url}`)}async function fe(e){try{await e()}catch(t){console.error(`Error: ${t instanceof Error?t.message:String(t)}`),process.exit(1)}}var te=new In("bridge").description("Connect this machine's local MCP servers and files to GAIA (outbound-only, no inbound ports)").addHelpText("after",`
26
- Revoke a device anytime from GAIA \u2192 Settings \u2192 Devices.`);te.command("add").description("Connect a local MCP server (guided \u2014 start here!)").action(async()=>{await fe(_r)});te.command("login").description("Pair this machine with your GAIA account").option("--api <url>","GAIA API base URL").option("--name <name>","Name to show for this device in Settings").action(async e=>{await fe(async()=>{await Ye({...e.api!==void 0?{api:e.api}:{},...e.name!==void 0?{name:e.name}:{}}),console.info("Next: gaia bridge add")})});te.command("fs").description("Expose folders for file access (read-only unless --write)").argument("<dirs...>","Folders to expose, e.g. ~/Documents").option("--write","Allow GAIA to write to these folders").action(async(e,t)=>{await fe(()=>Pn(e,t.write===!0))});te.command("ls").alias("list").description("Show pairing status and configured servers").action(async()=>{await fe(Rn)});te.command("rm").alias("remove").description("Remove a configured server").argument("<key>","Server key from `gaia bridge ls`").action(async e=>{await fe(()=>{console.info(lr(e)?`Removed '${e}'`:`No server '${e}'`)})});te.command("up").alias("start").description("Connect and serve (holds the tunnel; Ctrl+C to stop)").action(async()=>{await fe(Ke)});te.command("logout").description("Forget local credentials").action(async()=>{await fe(()=>{ar(),console.info("Logged out. Your device record remains until you revoke it in GAIA settings.")})});import*as tt from"fs";import*as Qr from"path";import{spawn as Dn}from"child_process";async function Te(e,t,r,o,n,i=!1){await Qe([{cmd:e,args:t,cwd:r,env:o,onSpawn:n,detached:i}])}async function Qe(e){e.length!==0&&await new Promise((t,r)=>{let o=e.map(d=>Dn(d.cmd,d.args,{cwd:d.cwd,stdio:"inherit",shell:!1,detached:d.detached??!1,env:d.env?{...process.env,...d.env}:process.env}));o.forEach((d,m)=>{e[m]?.onSpawn?.(d.pid)});let n=!1,i=0,a=!1,s,c=()=>{process.off("SIGINT",f),process.off("SIGTERM",f)},p=()=>{if(!a){a=!0;for(let[d,m]of o.entries()){let S=e[d];try{process.platform!=="win32"&&S?.detached&&typeof m.pid=="number"?process.kill(-m.pid,"SIGTERM"):m.kill("SIGTERM")}catch{}}s=setTimeout(()=>{for(let[d,m]of o.entries()){let S=e[d];try{process.platform!=="win32"&&S?.detached&&typeof m.pid=="number"?process.kill(-m.pid,"SIGKILL"):m.kill("SIGKILL")}catch{}}},1e3)}},f=()=>{p()};process.on("SIGINT",f),process.on("SIGTERM",f),o.forEach((d,m)=>{let S=e[m];d.on("error",v=>{n||(n=!0,c(),p(),r(v))}),d.on("close",(v,y)=>{if(i+=1,!(v===0||(y==="SIGINT"||y==="SIGTERM"||v===130||v===143||a))&&!n){n=!0,c(),p(),r(new Error(`Command failed with code ${String(v)}: ${S?.cmd??"unknown"} ${S?.args.join(" ")??""}`));return}i>=o.length&&!n&&(n=!0,c(),s&&clearTimeout(s),t())})})})}import*as J from"fs";import*as W from"path";import*as re from"fs";import*as Or from"os";import*as Rt from"path";var Et=Rt.join(Or.homedir(),".gaia"),Pt=Rt.join(Et,"config.json");function kn(){re.existsSync(Et)||re.mkdirSync(Et,{recursive:!0})}function Dt(){try{if(!re.existsSync(Pt))return null;let e=re.readFileSync(Pt,"utf-8");return JSON.parse(e)}catch{return null}}function ze(e){kn(),re.writeFileSync(Pt,`${JSON.stringify(e,null,2)}
27
- `)}function Ae(e){let r={...Dt()??{version:ee,setupComplete:!1,setupMethod:"manual",repoPath:"",createdAt:new Date().toISOString(),updatedAt:new Date().toISOString()},...e,updatedAt:new Date().toISOString()};ze(r)}import*as F from"fs";import*as Ee from"path";import*as Ie from"node:fs";import*as Ce from"node:path";import{execa as Mr}from"execa";var kt={selfhost:{MONGO_DB:"mongodb://mongo:27017/gaia",REDIS_URL:"redis://redis:6379",POSTGRES_URL:"postgresql://postgres:postgres@postgres:5432/langgraph",CHROMADB_HOST:"chromadb",CHROMADB_PORT:"8000",RABBITMQ_URL:"amqp://guest:guest@rabbitmq:5672/"},developer:{MONGO_DB:"mongodb://localhost:27017/gaia",REDIS_URL:"redis://localhost:6379",POSTGRES_URL:"postgresql://postgres:postgres@localhost:5432/postgres",CHROMADB_HOST:"localhost",CHROMADB_PORT:"8080",RABBITMQ_URL:"amqp://guest:guest@localhost:5672/"}},Nr={selfhost:{HOST:"http://localhost:8000",FRONTEND_URL:"http://localhost:3000",GAIA_BACKEND_URL:"http://gaia-backend:80",SETUP_MODE:"selfhost"},developer:{HOST:"http://localhost:8000",FRONTEND_URL:"http://localhost:3000",GAIA_BACKEND_URL:"http://host.docker.internal:8000",SETUP_MODE:"developer"}};function _t(e,t){return kt[t][e]??Nr[t][e]}async function Lr(e){let t=Ce.join(e,"apps/api/scripts/dump_config_schema.py"),r=Ce.join(e,"apps/api/app/config/settings_validator.py"),o=Ce.join(e,"apps/api/app/config/settings.py");if(!Ie.existsSync(t))throw new Error("dump_config_schema.py not found in apps/api/scripts");try{try{let{stdout:n}=await Mr("python3",[t,r,o],{cwd:e});return JSON.parse(n)}catch{let{stdout:n}=await Mr("python",[t,r,o],{cwd:e});return JSON.parse(n)}}catch(n){throw new Error(`Failed to parse settings schema: ${n.message}. Ensure python is installed.`)}}function Br(e){let t=Ce.join(e,"apps","web",".env.local"),r=Ie.existsSync(t)?t:Ce.join(e,"apps","web",".env");if(!Ie.existsSync(r))return[];let o=Ie.readFileSync(r,"utf-8"),n=[],i="General";for(let a of o.split(`
28
- `)){let s=a.trim();if(s.startsWith("#")&&!s.startsWith("#=")){let d=s.replace(/^#+\s*/,"").trim();d&&!d.startsWith("These are")&&(i=d);continue}if(!s||s.startsWith("#"))continue;let c=s.indexOf("=");if(c===-1)continue;let p=s.substring(0,c).trim(),f=s.substring(c+1).trim();n.push({name:p,value:f,category:i})}return n}function Fr(e,t){return{NEXT_PUBLIC_API_BASE_URL:`http://localhost:${t?.[8e3]??8e3}/api/v1/`}}function $r(e,t,r){let o=r==="selfhost"?new Set(Object.keys(kt.selfhost)):new Set;for(let[n,i]of Object.entries(t)){let a=Number(n),s=Number(i);for(let[c,p]of Object.entries(e)){if(o.has(c))continue;if(p===String(a)){e[c]=String(s);continue}let f=new RegExp(`:${a}(?=[/\\s]|$)`,"g");e[c]=p.replaceAll(f,`:${s}`)}}}function Gr(e,t){return e.map(r=>({...r,variables:r.variables.map(o=>{let n=_t(o.name,t);return{...o,defaultValue:n||o.defaultValue}})}))}function At(){return Object.keys(kt.selfhost)}function jr(e){return{...Nr[e]}}function Ot(e){F.existsSync(e)&&F.copyFileSync(e,`${e}.bak`)}function Ur(e,t){let r=Ee.join(e,".env");Ot(r);let o=["# GAIA Environment Configuration","# Generated by GAIA CLI",`# Created: ${new Date().toISOString()}`,""],n=["MONGO","REDIS","POSTGRES","CHROMADB","RABBITMQ","WORKOS","GOOGLE","OPENAI","INFISICAL","LANGSMITH","DISCORD","SLACK","TELEGRAM","CLOUDINARY","COMPOSIO","FIRECRAWL","LIVEKIT","DEEPGRAM","ELEVENLABS","RESEND","SENTRY","POSTHOG","E2B","DODO","NEXT_PUBLIC","GAIA"];function i(s){for(let p of n)if(s===p||s.startsWith(`${p}_`))return p;let c=s.split("_");return c.length===1?"Core":c[0]||"Core"}let a=new Map;for(let[s,c]of Object.entries(t)){let p=i(s);a.has(p)||a.set(p,[]);let d=/[\s#"'\\]/.test(c)||c===""?`"${c.replace(/\\/g,"\\\\").replace(/"/g,'\\"')}"`:c;a.get(p).push(`${s}=${d}`)}for(let[s,c]of a.entries())o.push(`# ${s} Configuration`),o.push(...c),o.push("");F.writeFileSync(r,o.join(`
29
- `),"utf-8")}function Hr(e,t,r){let o=Ee.join(e,"apps","web",".env.local");Ot(o);let n=Br(e),i=Fr(t,r),a=["# GAIA Web App Environment Configuration","# Generated by GAIA CLI",`# Created: ${new Date().toISOString()}`,""],s=new Map;for(let c of n){s.has(c.category)||s.set(c.category,[]);let p=i[c.name]??c.value;s.get(c.category).push({name:c.name,value:p})}if(n.length===0){a.push("# Core URLs");for(let[c,p]of Object.entries(i))a.push(`${c}=${p}`);a.push("")}else for(let[c,p]of s.entries()){a.push(`# ${c}`);for(let{name:f,value:d}of p)a.push(`${f}=${d}`);a.push("")}F.writeFileSync(o,a.join(`
30
- `),"utf-8")}var Wr={8e3:"API_HOST_PORT",5432:"POSTGRES_HOST_PORT",6379:"REDIS_HOST_PORT",27017:"MONGO_HOST_PORT",5672:"RABBITMQ_HOST_PORT",8080:"CHROMADB_HOST_PORT",8083:"MONGO_EXPRESS_HOST_PORT",3e3:"WEB_HOST_PORT"};function Vr(e,t,r){let o=Ee.join(e,"infra","docker",".env");Ot(o);let n=["# Docker Compose environment overrides","# Generated by GAIA CLI",`# Created: ${new Date().toISOString()}`,""];for(let[i,a]of Object.entries(t)){let s=Number(i),c=Wr[s];c&&n.push(`${c}=${a}`)}if(r==="selfhost"){let i=t[8e3]??8e3;n.push(""),n.push("# Web build args"),n.push(`NEXT_PUBLIC_API_BASE_URL=http://localhost:${i}/api/v1/`)}n.push(""),F.writeFileSync(o,n.join(`
31
- `),"utf-8")}function se(e){let t={};for(let[r,o]of Object.entries(e)){let n=Number(r),i=Wr[n];i&&(t[i]=String(o))}return t}function Yr(e){let t=Ee.join(e,"infra","docker","docker-compose.yml");if(!F.existsSync(t))return;let r=F.readFileSync(t,"utf-8"),o=[{varName:"API_HOST_PORT",hostPort:8e3,containerPort:80},{varName:"CHROMADB_HOST_PORT",hostPort:8080,containerPort:8e3},{varName:"POSTGRES_HOST_PORT",hostPort:5432,containerPort:5432},{varName:"REDIS_HOST_PORT",hostPort:6379,containerPort:6379},{varName:"MONGO_HOST_PORT",hostPort:27017,containerPort:27017},{varName:"RABBITMQ_HOST_PORT",hostPort:5672,containerPort:5672},{varName:"MONGO_EXPRESS_HOST_PORT",hostPort:8083,containerPort:8081},{varName:"WEB_HOST_PORT",hostPort:3e3,containerPort:3e3}],n=!1;for(let{varName:i,hostPort:a,containerPort:s}of o){let c=`"${a}:${s}"`,p=`"\${${i}:-${a}}:${s}"`;r.includes(c)&&(r=r.replaceAll(c,p),n=!0)}n&&F.writeFileSync(t,r,"utf-8")}var qr={API_HOST_PORT:8e3,POSTGRES_HOST_PORT:5432,REDIS_HOST_PORT:6379,MONGO_HOST_PORT:27017,RABBITMQ_HOST_PORT:5672,CHROMADB_HOST_PORT:8080,MONGO_EXPRESS_HOST_PORT:8083,WEB_HOST_PORT:3e3};function ae(e){let t=Ee.join(e,"infra","docker",".env"),r={};if(!F.existsSync(t))return r;let o=F.readFileSync(t,"utf-8");for(let n of o.split(`
32
- `)){let i=n.trim();if(i&&!i.startsWith("#")){let[a,...s]=i.split("=");if(a&&qr[a]){let c=s.join("=").trim().replace(/^["']|["']$/g,""),p=Number(c);!Number.isNaN(p)&&p>0&&p<=65535&&(r[qr[a]]=p)}}}return r}var On=e=>new Promise(t=>setTimeout(t,e)),Xr="dev-start.log",et=".gaia-dev.pid";function Jr(e){let t=W.join(e,".env");return J.existsSync(t)?["--env-file",".env"]:[]}var Mn=60;function Nn(){let e=process.env.GAIA_START_TIMEOUT_MIN?.trim(),t=e?Number(e):Number.NaN,r=Number.isFinite(t)&&t>=0?t:Mn;return r===0?void 0:r*60*1e3}function Ln(e,t){let r=["compose","-f","docker-compose.selfhost.yml",...e,"up","-d","--remove-orphans"];return t?.build&&r.push("--build"),t?.pull&&r.push("--pull","always"),r}function Mt(e){let t=W.join(e,et);if(!J.existsSync(t))return null;try{let r=Number.parseInt(J.readFileSync(t,"utf-8").trim(),10);return Number.isNaN(r)||r<=0?null:r}catch{return null}}function Ze(e){try{return process.kill(e,0),!0}catch(t){return t.code==="EPERM"}}async function Oe(e,t,r,o,n,i){if(t!=="selfhost")throw r?.("Developer mode must run in foreground."),new Error("Developer mode runs in foreground. Use 'gaia dev' or 'gaia dev full' instead of 'gaia start'.");r?.(i?.build?"Building and starting all services in Docker...":"Starting all services in Docker (selfhost mode)...");let a=W.join(e,"infra/docker"),s=o&&Object.keys(o).length>0?se(o):void 0;await U("docker",Ln(Jr(a),i),a,void 0,n,s,Nn()),r?.("All services started in Docker!")}async function Kr(e,t,r,o){let n=W.join(e,"infra/docker"),i=await ge(e);t?.("Stopping Docker services...");try{let a=Jr(n),s=i==="selfhost"?["compose","-f","docker-compose.selfhost.yml",...a,"down"]:["compose",...a,"down"];await U("docker",s,n)}catch{}if(i!=="selfhost"){t?.("Stopping GAIA-managed local processes (safe mode)...");let a=W.join(e,et),s=!1,c=Mt(e),p=typeof c=="number";if(c&&Ze(c))try{if(process.platform==="win32")await U("taskkill",["/PID",String(c),"/T","/F"],e),s=!0;else{try{process.kill(-c,"SIGTERM"),s=!0}catch{process.kill(c,"SIGTERM"),s=!0}if(await On(800),Ze(c))try{process.kill(-c,"SIGKILL")}catch{process.kill(c,"SIGKILL")}}}catch{}try{J.unlinkSync(a)}catch{}if(!s&&o?.forcePorts){t?.("No GAIA PID found. Force-stopping listeners on app ports...");try{let f=r?.[8e3]??8e3,d=r?.[3e3]??3e3;if(process.platform==="win32")for(let m of[f,d])try{await U("powershell",["-Command",`Get-NetTCPConnection -LocalPort ${m} -ErrorAction SilentlyContinue | ForEach-Object { Stop-Process -Id $_.OwningProcess -Force -ErrorAction SilentlyContinue }`],e)}catch{}else for(let m of[f,d])try{await U("sh",["-c",`lsof -ti :${m} -sTCP:LISTEN | xargs kill 2>/dev/null || true`],e)}catch{}}catch{}}else s||t?.(p?"Stored GAIA PID is stale. Skipping port cleanup in safe mode. Use `gaia stop --force-ports` for aggressive cleanup.":"No GAIA-managed PID found. Skipping port cleanup in safe mode. Use `gaia stop --force-ports` for aggressive cleanup.")}t?.("All services stopped.")}async function ge(e){let t=W.join(e,"apps","api",".env");if(!J.existsSync(t))return null;let r=J.readFileSync(t,"utf-8"),o=r.match(/^SETUP_MODE=(.+)$/m);if(o?.[1]){let n=o[1].trim().replace(/^["']|["']$/g,"");if(n==="selfhost"||n==="developer")return n}return r.includes("mongodb://mongo:")?"selfhost":(r.includes("mongodb://localhost:"),"developer")}async function U(e,t,r,o,n,i,a){let{spawn:s}=await import("child_process");return new Promise((c,p)=>{let f=s(e,t,{cwd:r,stdio:["ignore","pipe","pipe"],shell:!0,env:i?{...process.env,...i}:void 0}),d="",m=0,S=!1,v;a&&(v=setTimeout(()=>{S=!0,f.kill("SIGTERM"),p(new Error(`Command timed out after ${Math.round(a/6e4)}m. Check \`docker compose logs\` to debug.`))},a)),f.stdout?.on("data",y=>{let w=y.toString();d+=w,n?.(w),m=Math.min(m+5,95),o?.(m)}),f.stderr?.on("data",y=>{let w=y.toString();d+=w,n?.(w),m=Math.min(m+5,95),o?.(m)}),f.on("close",y=>{v&&clearTimeout(v),!S&&(y===0?(o?.(100),c()):p(new Error(`Command failed with code ${y}: ${d.slice(-500)}`)))}),f.on("error",y=>{v&&clearTimeout(v),!S&&p(y)})})}function $(e){let t=e||process.cwd();for(;t!==W.dirname(t);){if(J.existsSync(W.join(t,"apps/api/app/config/settings_validator.py")))return t;t=W.dirname(t)}let r=Dt();if(r?.repoPath){if(J.existsSync(W.join(r.repoPath,"apps/api/app/config/settings_validator.py")))return r.repoPath;console.warn(`Warning: Saved repo path "${r.repoPath}" is no longer a valid GAIA installation. Resetting config.`),Ae({repoPath:"",setupComplete:!1})}return null}async function zr(e){if(e&&e!=="full")throw new Error(`Invalid developer profile: '${e}'. Use 'gaia dev' or 'gaia dev full'.`);let t=$();if(!t)throw new Error("Could not find GAIA repository. Run from within a cloned gaia repo.");let r=await ge(t);if(!r)throw new Error("No .env file found. Run 'gaia init' for fresh setup, or 'gaia setup' to configure an existing repo.");if(r!=="developer")throw new Error("Developer mode is not enabled for this repo. Use 'gaia start' for self-host mode.");let o=Qr.join(t,et);try{await Te("mise",[e==="full"?"dev:full":"dev"],t,void 0,n=>{typeof n=="number"&&n>0&&tt.writeFileSync(o,`${n}
33
- `)},process.platform!=="win32")}finally{try{tt.unlinkSync(o)}catch{}}}import{render as fi}from"ink";import gi from"react";import{Box as ct,Text as ve}from"ink";import li from"react";import{ProgressBar as oo,Select as Bt,Spinner as Vn}from"@inkjs/ui";import{Box as g,Text as u,useInput as ce}from"ink";import Le from"ink-text-input";import{useEffect as Be,useRef as Yn,useState as B}from"react";import{Box as Me,Text as rt}from"ink";var x="#00bbff";import{Box as Bn,Text as Fn}from"ink";import{jsx as Zr}from"react/jsx-runtime";var eo=({status:e,step:t})=>t.toLowerCase()==="welcome"?null:Zr(Bn,{width:"100%",paddingX:1,marginTop:1,children:Zr(Fn,{color:"gray",dimColor:!0,children:e})});import{Box as $n}from"ink";import Gn from"ink-big-text";import jn from"ink-gradient";import{jsx as Nt}from"react/jsx-runtime";var Pe=()=>Nt($n,{flexDirection:"column",marginTop:1,marginBottom:1,children:Nt(jn,{colors:[x,"#b0eaff",x],children:Nt(Gn,{text:"GAIA",font:"3d"})})});import{jsx as he,jsxs as Ne}from"react/jsx-runtime";var qn=["Welcome","Prerequisites","Setup Mode","Repository Setup","Environment Setup","Install Tools","Project Setup","Finished"],to=["Detect Repo","Prerequisites","Environment Setup","Project Setup","Finished"],Un={Welcome:"Welcome",Prerequisites:"Prereqs","Setup Mode":"Mode","Repository Setup":"Repo","Environment Setup":"Env","Install Tools":"Tools","Project Setup":"Setup","Detect Repo":"Detect",Finished:"Done"},Hn=({currentStep:e,steps:t})=>{let r=t.indexOf(e);return he(Me,{marginBottom:1,flexWrap:"nowrap",children:t.map((o,n)=>{let i=n<r,a=n===r,s=Un[o]??o;return Ne(Me,{flexShrink:0,children:[n>0&&Ne(rt,{color:"gray",dimColor:!0,children:[" ","\xB7"," "]}),i&&Ne(rt,{color:"green",children:["\u2713 ",s]}),a&&he(rt,{color:x,bold:!0,children:s}),!i&&!a&&he(rt,{color:"gray",dimColor:!0,children:s})]},o)})})},ot=({children:e,status:t,step:r,steps:o=qn})=>Ne(Me,{flexDirection:"column",height:"100%",width:"100%",children:[Ne(Me,{flexGrow:1,flexDirection:"column",children:[he(Pe,{}),he(Hn,{currentStep:r,steps:o}),he(Me,{flexDirection:"column",flexGrow:1,children:e})]}),he(eo,{status:t,step:r})]});import{Spinner as ro}from"@inkjs/ui";import{Box as G,Text as M,useInput as Wn}from"ink";import{jsx as R,jsxs as H}from"react/jsx-runtime";var nt=({checks:e})=>H(G,{flexDirection:"column",borderStyle:"round",paddingX:1,borderColor:x,children:[R(M,{bold:!0,children:"System Checks"}),H(G,{flexDirection:"column",marginTop:1,children:[R(Lt,{label:"Git",status:e.git}),R(Lt,{label:"Docker",status:e.docker}),e.mise&&R(Lt,{label:"Mise",status:e.mise})]})]}),it=({status:e})=>H(G,{flexDirection:"column",marginTop:1,paddingX:1,borderStyle:"round",borderColor:x,children:[R(M,{bold:!0,children:"Environment Setup"}),R(G,{marginTop:1,children:R(ro,{label:e||"Configuring environment..."})})]}),st=({message:e})=>H(G,{flexDirection:"column",borderStyle:"single",borderColor:"red",padding:1,marginTop:2,children:[H(M,{color:"red",children:["Error: ",e]}),R(G,{marginTop:1,children:H(M,{dimColor:!0,children:[R(M,{bold:!0,children:"Enter"})," to exit"]})})]}),Lt=({label:e,status:t})=>H(G,{children:[R(G,{marginRight:1,children:t==="pending"?R(ro,{type:"dots"}):t==="success"?R(M,{color:"green",children:"\u2714"}):t==="error"?R(M,{color:"red",children:"\u2716"}):R(M,{color:"yellow",children:"\u26A0"})}),R(M,{children:e})]}),at=({portResults:e,onAccept:t,onAbort:r})=>{Wn((n,i)=>{i.return?t():i.escape&&r()});let o=e.filter(n=>!n.available);return H(G,{flexDirection:"column",marginTop:1,paddingX:1,borderStyle:"round",borderColor:"yellow",children:[R(G,{marginBottom:1,children:R(M,{bold:!0,color:"yellow",children:"Port Conflicts Detected"})}),e.map(n=>H(G,{children:[H(M,{color:n.available?"green":n.alternative?"yellow":"red",children:[n.available?"\u2714":n.alternative?"\u26A0":"\u2716"," "]}),H(M,{children:[n.service," (:",n.port,")"]}),!n.available&&H(M,{color:n.alternative?"gray":"red",children:[" ","- in use",n.usedBy?` by ${n.usedBy}`:"",n.alternative?` \u2192 will use :${n.alternative}`:" \u2014 NO ALTERNATIVE FOUND"]})]},n.port)),o.some(n=>!n.alternative)&&R(G,{marginTop:1,children:R(M,{color:"red",children:"Some ports have no available alternative. Free them and retry."})}),!o.some(n=>!n.alternative)&&o.some(n=>n.alternative)&&R(G,{marginTop:1,children:R(M,{color:"gray",children:"Alternative ports will be used for conflicting services."})}),R(G,{marginTop:1,children:H(M,{dimColor:!0,children:[R(M,{bold:!0,children:"Enter"})," continue \xB7 ",R(M,{bold:!0,children:"ESC"})," abort"]})})]})};import{jsx as l,jsxs as h}from"react/jsx-runtime";var Xn=({onConfirm:e})=>(ce((t,r)=>{r.return&&e()}),h(g,{flexDirection:"column",paddingX:2,borderStyle:"round",borderColor:x,children:[l(u,{bold:!0,children:"Welcome to GAIA Setup"}),h(g,{flexDirection:"column",marginTop:1,marginBottom:1,children:[l(u,{children:"This wizard will guide you through the setup process:"}),l(u,{children:" 1. Check prerequisites and choose setup mode"}),l(u,{children:" 2. Clone repository"}),l(u,{children:" 3. Configure environment variables"}),l(u,{children:" 4. Install tools and dependencies"})]}),l(u,{dimColor:!0,children:"~5-15 min depending on network speed"}),l(g,{marginTop:1,children:h(u,{color:x,children:[l(u,{bold:!0,children:"Enter"})," to start"]})})]})),Jn=({defaultValue:e,onSubmit:t})=>{let[r,o]=B(e);return h(g,{flexDirection:"column",marginTop:1,paddingX:1,borderStyle:"round",borderColor:x,children:[l(u,{children:"Clone repository to:"}),l(u,{color:"gray",dimColor:!0,children:"Press Enter for default, or type a custom path"}),h(g,{marginTop:1,children:[l(u,{color:x,children:"\u2192 "}),l(Le,{value:r,onChange:o,onSubmit:t})]})]})},Kn=({repoPath:e,onAction:t})=>h(g,{flexDirection:"column",marginTop:1,paddingX:1,borderStyle:"round",borderColor:"yellow",children:[l(g,{marginBottom:1,children:l(u,{bold:!0,color:"yellow",children:"Existing Installation Found"})}),h(u,{children:["Found a GAIA installation at"," ",l(u,{color:"cyan",bold:!0,children:e})]}),l(g,{marginTop:1,children:l(u,{color:"gray",children:"What would you like to do?"})}),l(g,{marginTop:1,children:l(Bt,{options:[{label:"Use existing installation",value:"use_existing"},{label:"Delete and re-clone",value:"delete_reclone"},{label:"Choose a different path",value:"different_path"},{label:"Exit setup",value:"exit"}],onChange:o=>t(o)})})]}),Qn=({setupMode:e,portOverrides:t,onConfirm:r})=>{ce((i,a)=>{a.return&&r()});let o=t?.[3e3]??3e3,n=t?.[8e3]??8e3;return e==="selfhost"?h(g,{flexDirection:"column",marginTop:2,borderStyle:"round",borderColor:"green",padding:1,children:[l(u,{bold:!0,color:"green",children:"GAIA is Running!"}),l(g,{marginTop:1,children:l(u,{color:"green",children:"\u2713 All services started"})}),h(g,{marginTop:1,flexDirection:"column",children:[h(u,{children:["Web:"," ",h(u,{color:"cyan",bold:!0,children:["http://localhost:",o]})]}),h(u,{children:["API:"," ",h(u,{color:"cyan",bold:!0,children:["http://localhost:",n]})]})]}),l(g,{marginTop:1,children:l(u,{color:"gray",children:"gaia logs \xB7 gaia stop \xB7 gaia status \xB7 gaia setup"})}),l(g,{marginTop:1,children:h(u,{dimColor:!0,children:[l(u,{bold:!0,children:"Enter"})," to exit"]})})]}):h(g,{flexDirection:"column",marginTop:2,borderStyle:"round",borderColor:x,padding:1,children:[l(u,{color:x,bold:!0,children:"You're all set!"}),h(g,{marginTop:1,children:[l(u,{bold:!0,children:"Run: "}),l(u,{color:"cyan",children:"$ gaia dev"})]}),h(g,{marginTop:1,flexDirection:"column",children:[h(u,{children:["Web:"," ",h(u,{color:"cyan",bold:!0,children:["http://localhost:",o]})]}),h(u,{children:["API:"," ",h(u,{color:"cyan",bold:!0,children:["http://localhost:",n]})]})]}),l(g,{marginTop:1,children:l(u,{color:"gray",children:"gaia dev full \xB7 gaia logs \xB7 gaia stop \xB7 gaia status \xB7 gaia setup"})}),l(g,{marginTop:1,children:h(u,{dimColor:!0,children:[l(u,{bold:!0,children:"Enter"})," to exit"]})})]})},zn=8,Zn=({logs:e,height:t=zn})=>{let[r,o]=B(0),n=Yn(e.length);Be(()=>{e.length!==n.current&&(n.current=e.length,o(0))},[e.length]),ce((d,m)=>{m.upArrow?o(S=>Math.min(S+1,Math.max(0,e.length-t))):m.downArrow&&o(S=>Math.max(0,S-1))});let i=e.length,a=Math.max(0,i-t-r),s=Math.max(0,i-r),c=e.slice(a,s),p=a,f=r;return h(g,{flexDirection:"column",marginTop:1,marginLeft:1,children:[p>0&&h(u,{color:"gray",dimColor:!0,children:["\u2191 ",p," more line",p!==1?"s":""]}),l(g,{flexDirection:"column",height:t,overflow:"hidden",children:c.map((d,m)=>l(u,{color:"gray",wrap:"truncate",children:d},`${a}-${m}`))}),f>0?h(u,{color:"gray",dimColor:!0,children:["\u2193 ",f," more line",f!==1?"s":""]}):l(u,{color:"gray",dimColor:!0,children:"\u2191\u2193 scroll"})]})},Ft=({phase:e,progress:t,isComplete:r,logs:o,title:n})=>h(g,{flexDirection:"column",marginTop:1,paddingX:1,borderStyle:"round",borderColor:x,children:[l(g,{marginBottom:1,children:l(u,{bold:!0,color:x,children:n||"Installing Dependencies"})}),h(g,{flexDirection:"column",gap:1,children:[l(g,{children:r?h(u,{color:"green",children:["\u2713 ",e]}):l(Vn,{label:e||"Preparing..."})}),!r&&t>0&&l(g,{width:50,children:l(oo,{value:t})}),!r&&o&&o.length>0&&l(Zn,{logs:o}),!r&&l(g,{marginTop:1,children:l(u,{color:"gray",dimColor:!0,children:"This may take a few minutes..."})})]})]}),$t=({onSelect:e})=>h(g,{flexDirection:"column",marginTop:1,paddingX:1,borderStyle:"round",borderColor:x,children:[l(u,{bold:!0,children:"Setup Mode"}),l(g,{marginTop:1,children:l(u,{color:"gray",children:"How do you want to run GAIA?"})}),l(g,{marginTop:1,children:l(Bt,{options:[{label:"Self-Host \u2014 run everything in Docker",value:"selfhost"},{label:"Developer \u2014 local dev with hot reload",value:"developer"}],onChange:r=>e(r)})})]}),Gt=({onSelect:e})=>h(g,{flexDirection:"column",marginTop:1,paddingX:1,borderStyle:"round",borderColor:x,children:[l(u,{bold:!0,children:"Environment Variables Setup"}),l(g,{marginTop:1,children:l(u,{color:"gray",children:"Choose how you want to configure environment variables:"})}),l(g,{marginTop:1,children:l(Bt,{options:[{label:"Manual Setup (Recommended)",value:"manual"},{label:"Infisical (Advanced)",value:"infisical"}],onChange:r=>e(r)})}),h(g,{marginTop:1,flexDirection:"column",children:[l(u,{color:"gray",dimColor:!0,children:"Manual Setup: Configure variables interactively (recommended for most users)"}),l(u,{color:"gray",dimColor:!0,children:"Infisical: All secrets managed in Infisical dashboard (requires pre-configuration)"})]})]}),jt=({onSubmit:e})=>{let[t,r]=B({INFISICAL_PROJECT_ID:"",INFISICAL_MACHINE_IDENTITY_CLIENT_ID:"",INFISICAL_MACHINE_IDENTITY_CLIENT_SECRET:""}),[o,n]=B(0),[i,a]=B(null),s=[{key:"INFISICAL_PROJECT_ID",description:"Found in your Infisical project settings"},{key:"INFISICAL_MACHINE_IDENTITY_CLIENT_ID",description:"From Access Control \u2192 Machine Identities"},{key:"INFISICAL_MACHINE_IDENTITY_CLIENT_SECRET",description:"Generated when creating the machine identity"}];ce((p,f)=>{if(f.tab||f.downArrow)n(d=>d<s.length-1?d+1:d);else if(f.upArrow)n(d=>d>0?d-1:d);else if(f.return){if(o<s.length-1){n(m=>m+1);return}let d=s.filter(m=>!t[m.key].trim());if(d.length>0){a(`Required: ${d.map(S=>S.key).join(", ")}`);let m=s.findIndex(S=>!t[S.key].trim());m>=0&&n(m);return}e(t)}});let c=s[o];return h(g,{flexDirection:"column",marginTop:1,paddingX:1,borderStyle:"round",borderColor:x,children:[l(g,{marginBottom:1,children:l(u,{bold:!0,color:x,children:"Infisical Configuration"})}),l(g,{marginBottom:1,children:l(u,{color:"gray",children:"All secrets managed in your Infisical project. Only credentials stored locally."})}),h(g,{marginBottom:1,flexDirection:"column",children:[l(u,{color:"gray",children:"Configure your Infisical credentials."}),h(u,{color:"gray",dimColor:!0,children:["Visit"," ",l(u,{color:"cyan",underline:!0,children:"app.infisical.com"})," ","to get these values."]})]}),s.map((p,f)=>{let d=p.key.includes("SECRET")||p.key.includes("TOKEN");return h(g,{flexDirection:"column",marginBottom:1,children:[l(g,{children:h(u,{color:f===o?x:"white",children:[f===o?"\u25B8 ":" ",p.key,":"]})}),l(g,{marginLeft:2,children:l(u,{color:"gray",dimColor:!0,children:p.description})}),f===o?l(g,{marginLeft:2,children:l(Le,{value:t[p.key],onChange:m=>{r(S=>({...S,[p.key]:m})),a(null)},placeholder:"Enter value...",mask:d?"*":void 0})}):l(g,{marginLeft:2,children:l(u,{color:t[p.key]?"green":"gray",children:t[p.key]?d?`\u2713 ${"*".repeat(8)}`:`\u2713 ${t[p.key]}`:"(not set)"})})]},p.key)}),i&&l(g,{marginTop:1,children:l(u,{color:"red",children:i})}),l(g,{marginTop:1,children:h(u,{dimColor:!0,children:[l(u,{bold:!0,children:"Enter"})," confirm \xB7 ",l(u,{bold:!0,children:"\u2191\u2193"})," navigate"]})})]})},qt=({category:e,currentIndex:t,totalGroups:r,onSubmit:o})=>{let[n,i]=B(()=>{let m={};for(let S of e.variables)m[S.name]=S.defaultValue||"";return m}),[a,s]=B(0),[c,p]=B(null);Be(()=>{let m={};for(let S of e.variables)m[S.name]=S.defaultValue||"";i(m),s(0),p(null)},[e.name]),ce((m,S)=>{if(S.tab||S.downArrow)s(v=>v<e.variables.length-1?v+1:v);else if(S.upArrow)s(v=>v>0?v-1:v);else if(S.escape){let v=e.variables.filter(y=>y.required&&!n[y.name]?.trim());if(v.length>0){p(`Required fields cannot be skipped: ${v.map(y=>y.name).join(", ")}`);return}o(n)}});let f=()=>{if(a<e.variables.length-1)s(a+1);else{let m=e.variables.filter(S=>S.required&&!n[S.name]?.trim());if(m.length>0){p(`Required fields are missing: ${m.map(S=>S.name).join(", ")}`);return}p(null),o(n)}},d=e.variables.some(m=>m.required);return h(g,{flexDirection:"column",marginTop:1,paddingX:1,borderStyle:"round",borderColor:c?"red":x,children:[h(g,{justifyContent:"space-between",children:[h(u,{bold:!0,children:["Configure ",e.name]}),h(u,{color:"gray",children:["Group ",t+1," / ",r]})]}),l(g,{marginTop:1,children:l(u,{color:"gray",children:e.description})}),l(g,{marginTop:1,flexDirection:"column",children:e.variables.map((m,S)=>{let v=S===a,y=!!m.defaultValue;return h(g,{flexDirection:"column",marginBottom:1,children:[h(g,{children:[h(u,{color:v?x:"gray",bold:v,children:[v?"\u279C ":" ",m.name]}),m.required&&h(u,{color:"red",bold:!0,children:[" ","*"]}),y&&!v&&h(u,{color:"gray",dimColor:!0,children:[" ","(default: ",m.defaultValue,")"]})]}),v&&l(g,{marginLeft:2,children:l(Le,{value:n[m.name]||"",onChange:w=>{i(b=>({...b,[m.name]:w})),c&&p(null)},onSubmit:f,placeholder:y?`Default: ${m.defaultValue}`:m.required?"Enter a value (required)":"Press Enter to skip"})})]},m.name)})}),c&&l(g,{marginTop:1,children:h(u,{color:"red",bold:!0,children:["\u26A0 ",c]})}),l(g,{marginTop:1,children:h(u,{dimColor:!0,children:[l(u,{bold:!0,children:"Enter"})," next \xB7 ",l(u,{bold:!0,children:"\u2191\u2193"})," navigate",!d&&h(u,{children:[" ","\xB7 ",l(u,{bold:!0,children:"ESC"})," skip"]})]})})]})},Ut=({alternatives:e,onSubmit:t})=>{let[r,o]=B(new Set),[n,i]=B({}),[a,s]=B(0),[c,p]=B(null);Be(()=>{let w={};for(let b of e)for(let E of b.variables)w[E.name]=E.defaultValue||"";i(w)},[e]);let f=[];for(let w=0;w<e.length;w++)if(f.push({type:"provider",categoryIndex:w}),r.has(w)){let b=e[w];if(b)for(let E=0;E<b.variables.length;E++)f.push({type:"field",categoryIndex:w,fieldIndex:E})}f.push({type:"submit"});let d=f[a],m=d?.type==="field",S=d?.type==="submit";ce((w,b)=>{let E=Math.min(a,f.length-1);if(E!==a){s(E);return}if(m)b.upArrow?s(P=>Math.max(0,P-1)):(b.downArrow||b.tab)&&s(P=>Math.min(f.length-1,P+1));else if(S)b.upArrow?s(P=>Math.max(0,P-1)):(b.return||w===" ")&&y();else if(b.upArrow)s(P=>Math.max(0,P-1));else if(b.downArrow||b.tab)s(P=>Math.min(f.length-1,P+1));else if((b.return||w===" ")&&d?.type==="provider"){let P=d.categoryIndex;o(Z=>{let _=new Set(Z);return _.has(P)?_.delete(P):_.add(P),_}),c&&p(null)}});let v=()=>{c&&p(null),s(w=>Math.min(f.length-1,w+1))},y=()=>{let w=[],b={};for(let E of r){let P=e[E];if(!P)continue;if(P.variables.some(_=>n[_.name]?.trim())){w.push(P.name);for(let _ of P.variables){let Ge=n[_.name];Ge&&(b[_.name]=Ge)}}}if(w.length===0){r.size===0?p("Enable at least one provider (press Space or Enter)"):p("Enter a value for at least one field");return}t(w,b)};return h(g,{flexDirection:"column",marginTop:1,paddingX:1,borderStyle:"round",borderColor:c?"red":x,children:[h(g,{justifyContent:"space-between",children:[l(u,{bold:!0,children:"Configure AI Provider"}),l(u,{color:"yellow",children:"* At least one required"})]}),l(g,{marginTop:1,children:l(u,{color:"gray",children:"Enable and configure at least one AI provider below:"})}),l(g,{marginTop:1,flexDirection:"column",children:e.map((w,b)=>{let E=r.has(b),P=f.findIndex(_=>_.type==="provider"&&_.categoryIndex===b),Z=a===P;return h(g,{flexDirection:"column",marginBottom:1,children:[h(g,{children:[l(u,{color:Z?x:void 0,bold:Z,children:Z?"\u279C ":" "}),l(u,{color:E?"green":"gray",children:E?"[\u2714]":"[ ]"}),h(u,{color:E?x:"gray",bold:E,children:[" ",w.name]}),w.description&&h(u,{color:"gray",dimColor:!0,children:[" ","- ",w.description]})]}),Z&&w.docsUrl&&h(g,{marginLeft:6,children:[l(u,{color:"yellow",children:"\u{1F4D6} "}),l(u,{color:"blue",underline:!0,children:w.docsUrl})]}),E&&l(g,{marginLeft:4,flexDirection:"column",marginTop:1,children:w.variables.map((_,Ge)=>{let Uo=f.findIndex(Re=>Re.type==="field"&&Re.categoryIndex===b&&Re.fieldIndex===Ge),Se=a===Uo,zt=!!_.defaultValue,yt=n[_.name]||"";return h(g,{flexDirection:"column",marginBottom:1,children:[h(g,{children:[h(u,{color:Se?x:"gray",bold:Se,children:[Se?" \u279C ":" ",_.name]}),!Se&&yt&&l(u,{color:"green",children:" \u2713"}),!Se&&!yt&&zt&&h(u,{color:"gray",dimColor:!0,children:[" ","(default: ",_.defaultValue,")"]})]}),Se&&l(g,{marginLeft:4,children:l(Le,{value:yt,onChange:Re=>{i(Ho=>({...Ho,[_.name]:Re})),c&&p(null)},onSubmit:v,placeholder:zt?`Default: ${_.defaultValue}`:"Enter value..."})})]},_.name)})})]},w.name)})}),c&&l(g,{marginTop:1,children:h(u,{color:"red",bold:!0,children:["\u26A0 ",c]})}),h(g,{marginTop:1,children:[l(u,{color:S?x:void 0,bold:S,children:S?"\u279C ":" "}),l(g,{borderStyle:"round",borderColor:S?x:"gray",paddingX:2,children:l(u,{color:S?x:"gray",bold:S,children:"Continue \u2192"})})]}),l(g,{marginTop:1,children:l(u,{color:"gray",dimColor:!0,children:"\u2191/\u2193 navigate \u2022 Space/Enter toggle/select \u2022 Tab skip field"})})]})},Ht=({currentVar:e,currentIndex:t,totalCount:r,onSubmit:o,onSkip:n})=>{let[i,a]=B(e.defaultValue||""),[s,c]=B(null);Be(()=>{a(e.defaultValue||""),c(null)},[e.name]),ce((d,m)=>{if(m.escape){if(e.required&&!i.trim()){c("This field is required and cannot be skipped");return}n()}});let p=d=>{if(e.required&&!d.trim()){c("This field is required");return}c(null),o(d)},f=!!e.defaultValue;return h(g,{flexDirection:"column",marginTop:1,paddingX:1,borderStyle:"round",borderColor:s?"red":x,children:[h(g,{justifyContent:"space-between",children:[h(g,{children:[l(u,{color:x,bold:!0,children:e.name}),e.required?l(u,{color:"red",children:" *"}):h(u,{color:"gray",dimColor:!0,children:[" ","optional"]})]}),h(u,{color:"gray",children:[t+1,"/",r]})]}),l(g,{marginLeft:1,children:l(u,{color:"gray",children:e.description})}),h(g,{marginTop:1,children:[l(u,{color:x,children:"\u2192 "}),l(Le,{value:i,onChange:d=>{a(d),s&&c(null)},onSubmit:p,placeholder:f?`Default: ${e.defaultValue}`:e.required?"required":"skip with Enter"})]}),s&&l(g,{marginTop:1,children:l(u,{color:"red",children:s})}),l(g,{marginTop:1,children:h(u,{dimColor:!0,children:[l(u,{bold:!0,children:"Enter"})," confirm",!e.required&&h(u,{children:[" ","\xB7 ",l(u,{bold:!0,children:"ESC"})," skip"]})]})})]})},no=({store:e})=>{let[t,r]=B(e.currentState);return Be(()=>{let o=()=>r({...e.currentState});return e.on("change",o),()=>{e.off("change",o)}},[e]),ce((o,n)=>{(n.return||n.escape)&&t.error&&e.submitInput("exit")}),h(ot,{status:t.status,step:t.step,children:[t.step==="Welcome"&&t.inputRequest?.id==="welcome"&&l(Xn,{onConfirm:()=>e.submitInput(!0)}),t.step==="Prerequisites"&&t.data.checks&&l(nt,{checks:t.data.checks}),t.inputRequest?.id==="port_conflicts"&&t.data.portConflicts&&l(at,{portResults:t.data.portConflicts,onAccept:()=>e.submitInput("accept"),onAbort:()=>e.submitInput("abort")}),t.inputRequest?.id==="repo_path"&&l(Jn,{defaultValue:t.inputRequest.meta.default,onSubmit:o=>e.submitInput(o)}),t.inputRequest?.id==="existing_repo"&&t.data.existingRepoPath&&l(Kn,{repoPath:t.data.existingRepoPath,onAction:o=>e.submitInput(o)}),t.step==="Repository Setup"&&!t.inputRequest&&h(g,{flexDirection:"column",borderStyle:"round",padding:1,borderColor:x,children:[l(u,{bold:!0,children:"Cloning Repository"}),h(g,{marginTop:1,flexDirection:"column",children:[l(oo,{value:t.data.repoProgress||0}),t.data.repoPhase&&l(g,{marginTop:1,children:l(u,{color:"gray",children:t.data.repoPhase})})]})]}),t.inputRequest?.id==="setup_mode"&&l($t,{onSelect:o=>e.submitInput(o)}),t.inputRequest?.id==="env_method"&&l(Gt,{onSelect:o=>e.submitInput(o)}),t.inputRequest?.id==="env_infisical"&&l(jt,{onSubmit:o=>e.submitInput(o)}),t.step==="Environment Setup"&&t.inputRequest?.id==="env_var"&&t.data.currentEnvVar&&l(Ht,{categories:t.data.envCategories||[],currentVar:t.data.currentEnvVar,currentIndex:t.data.envVarIndex||0,totalCount:t.data.envVarTotal||0,onSubmit:o=>e.submitInput(o),onSkip:()=>e.submitInput("")}),t.step==="Environment Setup"&&t.inputRequest?.id==="env_group"&&t.data.currentEnvGroup&&l(qt,{category:t.data.currentEnvGroup,currentIndex:t.data.envGroupIndex||0,totalGroups:t.data.envGroupTotal||0,onSubmit:o=>e.submitInput(o)}),t.step==="Environment Setup"&&t.inputRequest?.id==="env_alternatives"&&t.data.alternativeGroups&&l(Ut,{alternatives:t.data.alternativeGroups,onSubmit:(o,n)=>e.submitInput({selectedGroups:o,values:n})}),t.step==="Environment Setup"&&!t.inputRequest&&l(it,{status:t.status}),t.step==="Finished"&&l(Qn,{setupMode:t.data.setupMode,portOverrides:t.data.portOverrides,onConfirm:()=>e.submitInput("exit")}),(t.step==="Install Tools"||t.step==="Project Setup")&&l(Ft,{title:t.step==="Install Tools"?"Installing Tools":"Project Setup",phase:t.data.dependencyPhase||"",progress:t.data.dependencyProgress||0,isComplete:t.step==="Install Tools"?t.data.toolComplete||!1:t.data.dependencyComplete||!1,logs:t.data.dependencyLogs||[]}),t.error&&l(st,{message:t.error.message})]})};import{Spinner as ei}from"@inkjs/ui";import{Box as N,Text as C,useInput as io}from"ink";import{useEffect as so,useRef as ti,useState as ao}from"react";import{jsx as A,jsxs as T}from"react/jsx-runtime";var Wt=8,ri=({logs:e})=>{let[t,r]=ao(0),o=ti(e.length);so(()=>{e.length!==o.current&&(o.current=e.length,r(0))},[e.length]),io((f,d)=>{d.upArrow?r(m=>Math.min(m+1,Math.max(0,e.length-Wt))):d.downArrow&&r(m=>Math.max(0,m-1))});let n=e.length,i=Math.max(0,n-Wt-t),a=Math.max(0,n-t),s=e.slice(i,a),c=i,p=t;return T(N,{flexDirection:"column",marginTop:1,marginLeft:1,children:[c>0&&T(C,{color:"gray",dimColor:!0,children:["\u2191 ",c," more line",c!==1?"s":""]}),A(N,{flexDirection:"column",height:Wt,overflow:"hidden",children:s.map((f,d)=>A(C,{color:"gray",wrap:"truncate",children:f},i+d))}),p>0?T(C,{color:"gray",dimColor:!0,children:["\u2193 ",p," more line",p!==1?"s":""]}):A(C,{color:"gray",dimColor:!0,children:"\u2191\u2193 scroll"})]})},co=({store:e})=>{let[t,r]=ao(e.currentState);return so(()=>{let o=()=>r({...e.currentState});return e.on("change",o),()=>{e.off("change",o)}},[e]),io((o,n)=>{(n.return||n.escape)&&(t.data.started||t.data.stopped||t.error)&&e.submitInput("exit")}),T(N,{flexDirection:"column",width:"100%",children:[A(Pe,{}),(t.step==="Starting"||t.step==="Stopping")&&T(N,{flexDirection:"column",marginTop:1,paddingX:2,borderStyle:"round",borderColor:x,children:[A(ei,{label:t.status||"Working..."}),t.data.repoPath&&A(N,{marginTop:1,children:T(C,{color:"gray",children:["Repository: ",t.data.repoPath]})}),t.data.setupMode&&A(N,{children:T(C,{color:"gray",children:["Mode: ",t.data.setupMode]})}),t.data.dockerLogs&&t.data.dockerLogs.length>0&&A(ri,{logs:t.data.dockerLogs})]}),t.step==="Running"&&t.data.started&&T(N,{flexDirection:"column",marginTop:1,paddingX:2,paddingY:1,borderStyle:"round",borderColor:"green",children:[T(C,{color:"green",bold:!0,children:["\u2713"," GAIA is running!"]}),t.data.setupMode!=="developer"&&T(N,{marginTop:1,flexDirection:"column",children:[T(C,{children:["Web:"," ",T(C,{color:"cyan",bold:!0,children:["http://localhost:",t.data.webPort||3e3]})]}),T(C,{children:["API:"," ",T(C,{color:"cyan",bold:!0,children:["http://localhost:",t.data.apiPort||8e3]})]})]}),t.data.setupMode==="developer"&&T(N,{marginTop:1,flexDirection:"column",children:[T(N,{flexDirection:"column",children:[T(C,{children:["Web:"," ",T(C,{color:"cyan",bold:!0,children:["http://localhost:",t.data.webPort||3e3]})]}),T(C,{children:["API:"," ",T(C,{color:"cyan",bold:!0,children:["http://localhost:",t.data.apiPort||8e3]})]})]}),T(N,{marginTop:1,flexDirection:"column",children:[A(C,{color:"gray",children:"Use gaia dev / gaia dev full for foreground Nx TUI."}),T(C,{color:"gray",children:["Run ",A(C,{color:x,children:"gaia logs"})," to stream logs."]}),T(C,{color:"gray",children:["Run ",A(C,{color:x,children:"gaia stop"})," to shut down."]})]})]}),A(N,{marginTop:1,children:T(C,{dimColor:!0,children:[A(C,{bold:!0,children:"Enter"})," to exit"]})})]}),t.step==="Stopped"&&t.data.stopped&&T(N,{flexDirection:"column",marginTop:1,paddingX:2,paddingY:1,borderStyle:"round",borderColor:x,children:[T(C,{color:x,bold:!0,children:["\u2713"," ",t.status||"All GAIA services stopped."]}),t.data.stopMode==="force-ports"&&A(N,{marginTop:1,children:A(C,{color:"yellow",children:"Force-port cleanup was enabled and may have stopped non-GAIA listeners on app ports."})}),A(N,{marginTop:1,children:T(C,{dimColor:!0,children:[A(C,{bold:!0,children:"Enter"})," to exit"]})})]}),t.error&&T(N,{borderStyle:"single",borderColor:"red",padding:1,marginTop:2,children:[T(C,{color:"red",children:["Error: ",t.error.message]}),A(N,{marginTop:1,children:T(C,{dimColor:!0,children:[A(C,{bold:!0,children:"Enter"})," to exit"]})})]})]})};import{Spinner as oi}from"@inkjs/ui";import{Box as le,Text as V,useInput as lo}from"ink";import{useEffect as ni,useState as ii}from"react";import{jsx as D,jsxs as K}from"react/jsx-runtime";var po=({store:e})=>{let[t,r]=ii(e.currentState);return ni(()=>{let o=()=>r({...e.currentState});return e.on("change",o),()=>{e.off("change",o)}},[e]),lo((o,n)=>{(n.return||n.escape)&&t.error&&e.submitInput("exit")}),K(ot,{status:t.status,step:t.step,steps:to,children:[t.step==="Detect Repo"&&K(le,{flexDirection:"column",paddingX:2,borderStyle:"round",borderColor:x,children:[D(V,{bold:!0,children:"Detecting GAIA Repository"}),D(le,{marginTop:1,children:D(oi,{label:"Searching for repository..."})}),t.data.repoPath&&D(le,{marginTop:1,children:K(V,{color:"green",children:["Found: ",t.data.repoPath]})})]}),t.step==="Prerequisites"&&t.data.checks&&D(nt,{checks:t.data.checks}),t.inputRequest?.id==="port_conflicts"&&t.data.portConflicts&&D(at,{portResults:t.data.portConflicts,onAccept:()=>e.submitInput("accept"),onAbort:()=>e.submitInput("abort")}),t.inputRequest?.id==="setup_mode"&&D($t,{onSelect:o=>e.submitInput(o)}),t.inputRequest?.id==="env_method"&&D(Gt,{onSelect:o=>e.submitInput(o)}),t.inputRequest?.id==="env_infisical"&&D(jt,{onSubmit:o=>e.submitInput(o)}),t.step==="Environment Setup"&&t.inputRequest?.id==="env_var"&&t.data.currentEnvVar&&D(Ht,{categories:t.data.envCategories||[],currentVar:t.data.currentEnvVar,currentIndex:t.data.envVarIndex||0,totalCount:t.data.envVarTotal||0,onSubmit:o=>e.submitInput(o),onSkip:()=>e.submitInput("")}),t.step==="Environment Setup"&&t.inputRequest?.id==="env_group"&&t.data.currentEnvGroup&&D(qt,{category:t.data.currentEnvGroup,currentIndex:t.data.envGroupIndex||0,totalGroups:t.data.envGroupTotal||0,onSubmit:o=>e.submitInput(o)}),t.step==="Environment Setup"&&t.inputRequest?.id==="env_alternatives"&&t.data.alternativeGroups&&D(Ut,{alternatives:t.data.alternativeGroups,onSubmit:(o,n)=>e.submitInput({selectedGroups:o,values:n})}),t.step==="Environment Setup"&&!t.inputRequest&&D(it,{status:t.status}),t.step==="Project Setup"&&D(Ft,{title:"Project Setup",phase:t.data.dependencyPhase||"",progress:t.data.dependencyProgress||0,isComplete:t.data.dependencyComplete||!1,logs:t.data.dependencyLogs||[]}),t.step==="Finished"&&D(si,{setupMode:t.data.setupMode,portOverrides:t.data.portOverrides,onConfirm:()=>e.submitInput("exit")}),t.error&&D(st,{message:t.error.message})]})},si=({setupMode:e,portOverrides:t,onConfirm:r})=>{lo((a,s)=>{s.return&&r()});let o=t?.[3e3]??3e3,n=t?.[8e3]??8e3,i=e==="selfhost";return K(le,{flexDirection:"column",marginTop:2,borderStyle:"round",borderColor:x,padding:1,children:[D(V,{color:x,bold:!0,children:"Setup Complete!"}),K(le,{marginTop:1,children:[D(V,{bold:!0,children:"Run: "}),D(V,{color:"cyan",children:i?"$ gaia start":"$ gaia dev"})]}),K(le,{marginTop:1,flexDirection:"column",children:[K(V,{children:["Web:"," ",K(V,{color:"cyan",bold:!0,children:["http://localhost:",o]})]}),K(V,{children:["API:"," ",K(V,{color:"cyan",bold:!0,children:["http://localhost:",n]})]})]}),D(le,{marginTop:1,children:D(V,{color:"gray",children:i?"gaia logs \xB7 gaia stop \xB7 gaia status \xB7 gaia setup":"gaia dev full \xB7 gaia logs \xB7 gaia stop \xB7 gaia status \xB7 gaia setup"})}),D(le,{marginTop:1,children:K(V,{dimColor:!0,children:[D(V,{bold:!0,children:"Enter"})," to exit"]})})]})};import{Spinner as ai}from"@inkjs/ui";import{Box as O,Text as k,useInput as ci}from"ink";import{useEffect as uo,useState as Vt}from"react";import{jsx as I,jsxs as L}from"react/jsx-runtime";var mo=({store:e})=>{let[t,r]=Vt(e.currentState),[o,n]=Vt(!1),[i,a]=Vt(null);return uo(()=>{let s=()=>r({...e.currentState});return e.on("change",s),()=>{e.off("change",s)}},[e]),uo(()=>{n(!1),a(new Date().toLocaleTimeString())},[t.data.services]),ci((s,c)=>{(c.return||c.escape)&&t.step==="Results"&&e.submitInput("exit"),s==="r"&&t.step==="Results"&&t.data.refreshable&&!o&&(n(!0),e.submitInput("refresh"))}),L(O,{flexDirection:"column",width:"100%",children:[I(Pe,{}),t.step==="Checking"&&I(O,{marginTop:1,children:I(ai,{label:t.data.services?"Refreshing service health...":"Checking service health..."})}),t.step==="Results"&&t.data.services&&L(O,{flexDirection:"column",children:[L(O,{flexDirection:"column",borderStyle:"round",borderColor:x,paddingX:2,paddingY:1,children:[L(O,{justifyContent:"space-between",children:[I(k,{bold:!0,color:x,children:"GAIA Service Status"}),i&&L(k,{color:"gray",dimColor:!0,children:["checked ",i," \xB7 ",I(k,{bold:!0,children:"r"})," refresh"]})]}),L(O,{marginTop:1,flexDirection:"column",children:[L(O,{children:[I(O,{width:22,children:I(k,{bold:!0,children:"Service"})}),I(O,{width:10,children:I(k,{bold:!0,children:"Status"})}),I(O,{width:10,children:I(k,{bold:!0,children:"Latency"})})]}),I(k,{color:"gray",children:"\u2500".repeat(42)}),[...t.data.services].sort((s,c)=>s.status==="down"&&c.status!=="down"?-1:s.status!=="down"&&c.status==="down"?1:s.name.localeCompare(c.name)).map(s=>L(O,{children:[I(O,{width:22,children:L(k,{children:[s.name," (:",s.port,")"]})}),I(O,{width:10,children:I(k,{color:s.status==="up"?"green":"red",bold:!0,children:s.status==="up"?"\u2713 UP":"\u2717 DOWN"})}),I(O,{width:10,children:I(k,{color:"gray",children:s.latency?`${s.latency}ms`:"--"})})]},s.name))]})]}),t.data.docker&&L(O,{flexDirection:"column",borderStyle:"round",borderColor:"gray",paddingX:2,paddingY:1,marginTop:1,children:[I(k,{bold:!0,children:"Docker Containers"}),L(k,{color:"gray",children:["Docker:"," ",t.data.docker.running?I(k,{color:"green",children:"Running"}):I(k,{color:"red",children:"Not running"})]}),t.data.docker.containers?.length>0&&I(O,{marginTop:1,flexDirection:"column",children:t.data.docker.containers.map(s=>L(O,{children:[L(k,{color:s.status==="running"?"green":"red",children:[s.status==="running"?"\u2713":"\u2717"," "]}),I(k,{children:s.name}),s.health&&L(k,{color:"gray",children:[" (",s.health,")"]})]},s.name))})]}),I(O,{marginTop:1,children:L(k,{dimColor:!0,children:[I(k,{bold:!0,children:"Enter"})," exit \xB7 ",I(k,{bold:!0,children:"r"})," refresh"]})})]}),t.error&&I(O,{borderStyle:"single",borderColor:"red",padding:1,marginTop:2,children:L(k,{color:"red",children:["Error: ",t.error.message]})})]})};import{jsx as Y,jsxs as Fe}from"react/jsx-runtime";var pi=["init","setup","status","start","stop"],Yt=class extends li.Component{constructor(t){super(t),this.state={error:null}}static getDerivedStateFromError(t){return{error:t}}render(){return this.state.error?Fe(ct,{flexDirection:"column",padding:1,children:[Y(ve,{color:"red",bold:!0,children:"An unexpected error occurred:"}),Y(ve,{color:"red",children:this.state.error.message}),this.state.error.stack&&Y(ct,{marginTop:1,children:Y(ve,{color:"gray",dimColor:!0,children:this.state.error.stack})})]}):this.props.children}},ui=({store:e,command:t})=>{switch(t){case"init":return Y(no,{store:e});case"setup":return Y(po,{store:e});case"status":return Y(mo,{store:e});case"start":case"stop":return Y(co,{store:e,command:t});default:return Fe(ct,{flexDirection:"column",padding:1,children:[Fe(ve,{color:"red",children:["Unknown command: ",t]}),Fe(ct,{marginTop:1,flexDirection:"column",children:[Y(ve,{bold:!0,children:"Available commands:"}),pi.map(r=>Fe(ve,{children:[" ",Y(ve,{color:"cyan",children:r})]},r))]})]})}},fo=({store:e,command:t})=>Y(Yt,{children:Y(ui,{store:e,command:t})});import{EventEmitter as di}from"events";var mi=150,Xt=class extends di{state={step:"init",status:"",error:null,data:{},inputRequest:null};inputResolver=null;emitTimer=null;emitPending=!1;autoResolveInputs=new Map;setAutoResolve(t,r="exit"){this.autoResolveInputs.set(t,r)}get currentState(){return this.state}scheduleEmit(){this.emitPending=!0,this.emitTimer||(this.emitTimer=setTimeout(()=>{this.emitTimer=null,this.emitPending&&(this.emitPending=!1,this.emit("change",this.state))},mi))}emitNow(){this.emitTimer&&(clearTimeout(this.emitTimer),this.emitTimer=null),this.emitPending=!1,this.emit("change",this.state)}setStep(t){this.state.step=t,this.emitNow()}setStatus(t){this.state.status=t,this.scheduleEmit()}setError(t){this.state.error=t,t!==null&&this.inputResolver&&(this.inputResolver(null),this.inputResolver=null,this.state.inputRequest=null),this.emitNow()}updateData(t,r){this.state.data={...this.state.data,[t]:r},this.scheduleEmit()}waitForInput(t,r,o){return this.autoResolveInputs.has(t)?(this.state.inputRequest=null,this.emitNow(),Promise.resolve(this.autoResolveInputs.get(t))):(this.state.inputRequest={id:t,meta:r},this.emitNow(),new Promise(n=>{if(this.inputResolver=n,o!=null){let i=setTimeout(()=>{this.inputResolver&&(this.inputResolver=null,this.state.inputRequest=null,this.emitNow(),n(null))},o),a=this.inputResolver;this.inputResolver=s=>{clearTimeout(i),a(s)}}}))}submitInput(t){this.inputResolver&&(this.inputResolver(t),this.inputResolver=null,this.state.inputRequest=null,this.emitNow())}},go=()=>new Xt;function Jt(){return process.stdin.isTTY===!0&&process.stdout.isTTY===!0}function ho(e){if(Jt())return;let t=e?`'gaia ${e}'`:"this command";console.error(`Error: ${t} needs an interactive terminal (TTY) to prompt for input.`),console.error("Re-run it from a regular shell session \u2014 not a pipe, redirect, or non-TTY environment."),process.exit(1)}function vo(e){let t="",r="",o="";e.on("change",n=>{n.step&&n.step!==t&&(t=n.step,console.info(`
34
- [${n.step}]`)),n.status&&n.status!==r&&(r=n.status,console.info(` ${n.status}`)),n.error&&n.error.message!==o&&(o=n.error.message,console.error(` Error: ${n.error.message}`))})}var hi=50,vi=130;async function z(e){let t=go();if(e.whenNonInteractive==="fail"){ho(e.command),await So(t,e);return}Jt()?await So(t,e):await Si(t,e)}async function Si(e,t){vo(e);for(let[r,o]of t.autoResolve??[])e.setAutoResolve(r,o);try{await t.runFlow(e),t.onPlainComplete?.(e)}catch(r){e.setError(r)}yo(e)}async function So(e,t){let{unmount:r}=fi(gi.createElement(fo,{store:e,command:t.command})),o=()=>{r(),process.exit(vi)};process.once("SIGINT",o),process.once("SIGTERM",o),await new Promise(n=>setTimeout(n,hi));try{await t.runFlow(e)}catch(n){e.setError(n)}finally{process.off("SIGINT",o),process.off("SIGTERM",o)}e.currentState.error&&await e.waitForInput("exit"),r(),yo(e)}function yo(e){let t=e.currentState.error?1:0,r=[process.stdout,process.stderr].filter(n=>n.writableLength>0);r.length===0&&process.exit(t);let o=r.length;for(let n of r)n.once("drain",()=>{o-=1,o===0&&process.exit(t)})}import*as ne from"fs";import*as Po from"os";import*as ue from"path";import*as xo from"path";var yi=e=>new Promise(t=>setTimeout(t,e));async function lt(e){e.setStep("Setup Mode"),e.setStatus("Choose how to run GAIA...");let t=await e.waitForInput("setup_mode");return e.updateData("setupMode",t),t}async function pt(e,t,r,o){e.setStep("Environment Setup"),e.setStatus("Configuring environment..."),e.updateData("setupMode",r),e.setStatus("Configuring environment variables...");let n=await e.waitForInput("env_method");e.updateData("envMethod",n);let i={};i.ENV="development";let a=At();for(let c of a){let p=_t(c,r);p&&(i[c]=p)}let s=jr(r);for(let[c,p]of Object.entries(s))i[c]=p;if(n==="infisical")await xi(e,i),e.setStatus("Infisical credentials saved. Ensure your Infisical project contains all required variables.");else try{await wi(e,t,i,r)}catch(c){e.setError(c);return}o&&$r(i,o,r);try{await bi(e,t,i,r,o)}catch(c){e.setError(c);return}await yi(1e3)}async function xi(e,t){e.setStatus("Configuring Infisical...");let r=await e.waitForInput("env_infisical");t.INFISICAL_PROJECT_ID=r.INFISICAL_PROJECT_ID,t.INFISICAL_MACHINE_IDENTITY_CLIENT_ID=r.INFISICAL_MACHINE_IDENTITY_CLIENT_ID,t.INFISICAL_MACHINE_IDENTITY_CLIENT_SECRET=r.INFISICAL_MACHINE_IDENTITY_CLIENT_SECRET}async function wi(e,t,r,o){e.setStatus("Parsing environment variables...");let n;try{n=await Lr(t),n=Gr(n,o)}catch(v){throw o==="selfhost"?new Error(`Manual environment setup requires Python to parse config schema.
24
+ `)});;){let r=await pe(`Choose 1-${t.length}`),o=Number.parseInt(r,10)-1;if(o>=0&&o<t.length)return o;process.stdout.write(`Invalid choice, try again.
25
+ `)}}function Pi(e,t){let o=[...t].reverse().filter(n=>!n.startsWith("-"))[0]??e;return po(o).replace(/@[^@]*$/,"")}function Ri(e){try{let t=new URL(e);return t.port?`local-${t.port}`:t.hostname}catch{return""}}async function mo(e){for(;;){let t=await pe("Name for this server",e),r=rr(t);if(!t||!r||r===ye){console.info("Pick a different name.");continue}if(!($().servers.some(o=>o.key===r)&&!await de(`'${r}' already exists \u2014 overwrite?`,!1)))return{name:t,key:r}}}function ki(e,t){if(po(e)!=="docker")return[];let r=[];for(let o=0;o<t.length;o++){let n=t[o];if(n!==void 0)if(n==="-e"||n==="--env"){let i=t[o+1];i&&!i.includes("=")&&r.push(i)}else n.startsWith("-e")&&n.length>2&&!n.includes("=")&&r.push(n.slice(2))}return[...new Set(r)]}async function nr(e){let t=process.env[e];if(t!==void 0&&t!==""&&await de(` Found ${e} in your environment \u2014 use that value?`,!0))return t;for(;;){let r=await uo(` Paste ${e}`);if(r)return console.info(` Got it (${r.length} characters).`),r;console.info(" Empty \u2014 paste the value, or Ctrl+C to abort.")}}async function fo(e,t){let r={};for(let n of ki(e,t))console.info(`
26
+ The command needs ${n}.`),r[n]=await nr(n);let o=Object.keys(r).length?"Any other environment variables to add?":"Does the server need environment variables (API keys, tokens\u2026)?";if(!await de(o,!1))return r;for(console.info("Enter each variable's name; leave blank when done.");;){let n=(await pe(" Variable name")).trim();if(!n)break;if(n in r){console.info(" Already added.");continue}r[n]=await nr(n)}return r}async function _i(){console.info(`
27
+ Examples: npx -y my-mcp-server \xB7 uvx my-server \xB7 docker run -i --rm my/image`);let e=await pe("Command that starts your MCP server");if(!e)throw new Error("a command is required");let{command:t,args:r}=or(e),o=await fo(t,r),{name:n,key:i}=await mo(Pi(t,r));return{type:"stdio",key:i,name:n,command:t,args:r,env:o}}async function Di(){let e={};if(!await de("Does the server need request headers (e.g. Authorization)?",!1))return e;for(console.info("Enter each header's name; leave blank when done.");;){let t=(await pe(" Header name")).trim();if(!t)break;if(t in e){console.info(" Already added.");continue}e[t]=await nr(t)}return e}async function Ai(){let e=await pe("Server URL (e.g. http://localhost:3000/mcp)");if(!e)throw new Error("a URL is required");ue(e);let t=await Di();if(Object.keys(t).length>0&&new URL(e).protocol==="http:"&&(console.info(`
28
+ Heads up: these headers travel unencrypted over local HTTP. Anyone else on this machine (or the receiving server's logs) can read them.`),!await de("Send these headers over unencrypted HTTP anyway?",!1)))throw new Error("aborted \u2014 use an https: URL or drop the headers");let{name:r,key:o}=await mo(Ri(e));return{type:"url",key:o,name:r,url:e,...Object.keys(t).length?{headers:t}:{}}}async function Oi(e){for(;;){console.info(`
29
+ Testing the connection (this may download/start the server)\u2026`);try{let t=await rt(e),r=t.slice(0,5).join(", ");return console.info(`Connected \u2014 ${t.length} tools found${r?` (${r}${t.length>5?", \u2026":""})`:""}.`),!0}catch(t){console.error(`Connection failed: ${t instanceof Error?t.message:t}`);let r=["Retry the test"];e.type==="stdio"&&r.push("Re-enter environment variables"),r.push("Save anyway (fix it later)","Abort");let o=r[await at("What now?",r)];if(o==="Re-enter environment variables"&&e.type==="stdio")e.env=await fo(e.command,e.args);else{if(o==="Save anyway (fix it later)")return!0;if(o==="Abort")return!1}}}}async function Li(e){let t=co(e),r;try{r=await rt(t)}catch(o){throw new Error(`Could not start '${t.key}': ${o instanceof Error?o.message:o}`)}nt(t),await ke(),console.info(`Saved '${t.key}' (${r.length} tools) and registered with GAIA. A running 'gaia bridge up' daemon serves it automatically; otherwise start one.`)}async function go(e={}){if(!Jt()){if(e.type)throw new Error("This device isn't paired yet. Run `gaia bridge login` on it first.");console.info("This device isn't paired with GAIA yet, let's do that first."),await Re()}if(e.type){await Li(e);return}let r=await at("What do you want to connect?",["A command starts an MCP server (stdio) \u2014 npx / uvx / docker / python \u2026","An MCP server already running at a local URL \u2014 e.g. http://localhost:3000/mcp"])===0?await _i():await Ai();if(!await Oi(r))throw new Error("aborted");nt(r),console.info(`
30
+ Saved '${r.key}'.`);try{await ke(),console.info("Registered with GAIA.")}catch(o){console.error(`Could not register with GAIA (will retry on \`gaia bridge up\`): ${o instanceof Error?o.message:o}`)}await de("Keep this device connected in the background now?")?await st():console.info("Run `gaia bridge up` whenever you're ready.")}function Mi(e){let t=e.type==="url"?e.url:e.type==="stdio"?e.command:e.allow.join(", ");return`${e.name} \u2014 ${e.type} (${t})`}async function ho(e){if(e){let n=await Qt(e);console.info(n?`Removed '${e}' from this device and GAIA.`:`No server '${e}'.`);return}let t=$().servers;if(t.length===0){console.info("No servers configured \u2014 nothing to remove.");return}let r=await at("Which server do you want to remove?",t.map(Mi)),o=t[r];if(o){if(!await de(`Remove '${o.key}'?`,!1)){console.info("Left it in place.");return}await Qt(o.key),console.info(`Removed '${o.key}'. The tunnel stops serving it right away, and GAIA drops it too.`)}}function Bi(){let e=te();console.info(e?.deviceId?`Paired (device ${e.deviceId}, ${$e()})`:"Not paired \u2014 run: gaia bridge login"),console.info(oo());let t=$().servers;if(t.length===0){console.info("No servers configured \u2014 run: gaia bridge add");return}console.info(`
31
+ Configured servers:`);for(let r of t)if(r.type==="filesystem")console.info(` [${r.key}] filesystem${r.allowWrite?" (rw)":" (ro)"}: ${r.allow.join(", ")}`);else if(r.type==="stdio"){let o=Object.keys(r.env);console.info(` [${r.key}] ${r.name}: ${r.command} ${r.args.join(" ")}`),o.length&&console.info(` env: ${o.join(", ")}`)}else{console.info(` [${r.key}] ${r.name}: ${r.url}`);let o=r.headers?Object.keys(r.headers):[];o.length&&console.info(` headers: ${o.join(", ")}`)}}async function we(e){try{await e()}catch(t){console.error(`Error: ${t instanceof Error?t.message:String(t)}`),process.exit(1)}}var ie=new Ni("bridge").description("Connect this machine's local MCP servers and files to GAIA (outbound-only, no inbound ports)").addHelpText("after",`
32
+ Revoke a device anytime from GAIA \u2192 Settings \u2192 Devices.`);ie.command("add").description("Connect a local MCP server (guided; or non-interactive with --type)").option("--type <type>","stdio | url \u2014 enables non-interactive mode (no prompts)").option("--name <name>","display name").option("--command <command>","stdio: the command that starts the server").option("--url <url>","url: the local MCP server URL").option("--env <pair...>","stdio: KEY=VALUE env var (repeatable)").option("--header <pair...>","url: Header:Value request header (repeatable)").action(async e=>{await we(()=>go(e))});ie.command("login").description("Pair this machine with your GAIA account").option("--api <url>","GAIA API base URL").option("--name <name>","Name to show for this device in Settings").action(async e=>{await we(async()=>{await Re({...e.api!==void 0?{api:e.api}:{},...e.name!==void 0?{name:e.name}:{}}),console.info("Next: gaia bridge add")})});ie.command("ls").alias("list").description("Show pairing status and configured servers").action(async()=>{await we(Bi)});ie.command("remove").alias("rm").description("Remove a configured server (interactive picker if no key given)").argument("[key]","Server key from `gaia bridge ls` (optional)").action(async e=>{await we(()=>ho(e))});ie.command("up").alias("start").description("Connect with full file access + serve in the background (stop with: gaia bridge down)").option("--serve","(internal) hold the tunnel in the foreground; used by the background daemon").action(async e=>{await we(e.serve?io:st)});ie.command("down").alias("stop").description("Stop the background tunnel started by `gaia bridge up`").action(async()=>{await we(no)});ie.command("logout").description("Forget local credentials").action(async()=>{await we(()=>{Be(),console.info("Logged out. Your device record remains until you revoke it in GAIA settings.")})});import*as dt from"fs";import*as Mo from"path";import{spawn as Fi}from"child_process";async function _e(e,t,r,o,n,i=!1){await ct([{cmd:e,args:t,cwd:r,env:o,onSpawn:n,detached:i}])}async function ct(e){e.length!==0&&await new Promise((t,r)=>{let o=e.map(m=>Fi(m.cmd,m.args,{cwd:m.cwd,stdio:"inherit",shell:!1,detached:m.detached??!1,env:m.env?{...process.env,...m.env}:process.env}));o.forEach((m,f)=>{e[f]?.onSpawn?.(m.pid)});let n=!1,i=0,a=!1,s,c=()=>{process.off("SIGINT",d),process.off("SIGTERM",d)},u=()=>{if(!a){a=!0;for(let[m,f]of o.entries()){let S=e[m];try{process.platform!=="win32"&&S?.detached&&typeof f.pid=="number"?process.kill(-f.pid,"SIGTERM"):f.kill("SIGTERM")}catch{}}s=setTimeout(()=>{for(let[m,f]of o.entries()){let S=e[m];try{process.platform!=="win32"&&S?.detached&&typeof f.pid=="number"?process.kill(-f.pid,"SIGKILL"):f.kill("SIGKILL")}catch{}}},1e3)}},d=()=>{u()};process.on("SIGINT",d),process.on("SIGTERM",d),o.forEach((m,f)=>{let S=e[f];m.on("error",v=>{n||(n=!0,c(),u(),r(v))}),m.on("close",(v,y)=>{if(i+=1,!(v===0||(y==="SIGINT"||y==="SIGTERM"||v===130||v===143||a))&&!n){n=!0,c(),u(),r(new Error(`Command failed with code ${String(v)}: ${S?.cmd??"unknown"} ${S?.args.join(" ")??""}`));return}i>=o.length&&!n&&(n=!0,c(),s&&clearTimeout(s),t())})})})}import*as Q from"fs";import*as W from"path";import*as se from"fs";import*as vo from"os";import*as ar from"path";var ir=ar.join(vo.homedir(),".gaia"),sr=ar.join(ir,"config.json");function $i(){se.existsSync(ir)||se.mkdirSync(ir,{recursive:!0})}function cr(){try{if(!se.existsSync(sr))return null;let e=se.readFileSync(sr,"utf-8");return JSON.parse(e)}catch{return null}}function lt(e){$i(),se.writeFileSync(sr,`${JSON.stringify(e,null,2)}
33
+ `)}function Ue(e){let r={...cr()??{version:ne,setupComplete:!1,setupMethod:"manual",repoPath:"",createdAt:new Date().toISOString(),updatedAt:new Date().toISOString()},...e,updatedAt:new Date().toISOString()};lt(r)}import*as j from"fs";import*as Oe from"path";import*as Ae from"node:fs";import*as De from"node:path";import{execa as So}from"execa";var lr={selfhost:{MONGO_DB:"mongodb://mongo:27017/gaia",REDIS_URL:"redis://redis:6379",POSTGRES_URL:"postgresql://postgres:postgres@postgres:5432/langgraph",CHROMADB_HOST:"chromadb",CHROMADB_PORT:"8000",RABBITMQ_URL:"amqp://guest:guest@rabbitmq:5672/"},developer:{MONGO_DB:"mongodb://localhost:27017/gaia",REDIS_URL:"redis://localhost:6379",POSTGRES_URL:"postgresql://postgres:postgres@localhost:5432/postgres",CHROMADB_HOST:"localhost",CHROMADB_PORT:"8080",RABBITMQ_URL:"amqp://guest:guest@localhost:5672/"}},yo={selfhost:{HOST:"http://localhost:8000",FRONTEND_URL:"http://localhost:3000",GAIA_BACKEND_URL:"http://gaia-backend:80",SETUP_MODE:"selfhost"},developer:{HOST:"http://localhost:8000",FRONTEND_URL:"http://localhost:3000",GAIA_BACKEND_URL:"http://host.docker.internal:8000",SETUP_MODE:"developer"}};function ur(e,t){return lr[t][e]??yo[t][e]}async function xo(e){let t=De.join(e,"apps/api/scripts/dump_config_schema.py"),r=De.join(e,"apps/api/app/config/settings_validator.py"),o=De.join(e,"apps/api/app/config/settings.py");if(!Ae.existsSync(t))throw new Error("dump_config_schema.py not found in apps/api/scripts");try{try{let{stdout:n}=await So("python3",[t,r,o],{cwd:e});return JSON.parse(n)}catch{let{stdout:n}=await So("python",[t,r,o],{cwd:e});return JSON.parse(n)}}catch(n){throw new Error(`Failed to parse settings schema: ${n.message}. Ensure python is installed.`)}}function wo(e){let t=De.join(e,"apps","web",".env.local"),r=Ae.existsSync(t)?t:De.join(e,"apps","web",".env");if(!Ae.existsSync(r))return[];let o=Ae.readFileSync(r,"utf-8"),n=[],i="General";for(let a of o.split(`
34
+ `)){let s=a.trim();if(s.startsWith("#")&&!s.startsWith("#=")){let m=s.replace(/^#+\s*/,"").trim();m&&!m.startsWith("These are")&&(i=m);continue}if(!s||s.startsWith("#"))continue;let c=s.indexOf("=");if(c===-1)continue;let u=s.substring(0,c).trim(),d=s.substring(c+1).trim();n.push({name:u,value:d,category:i})}return n}function Eo(e,t){return{NEXT_PUBLIC_API_BASE_URL:`http://localhost:${t?.[8e3]??8e3}/api/v1/`}}function bo(e,t,r){let o=r==="selfhost"?new Set(Object.keys(lr.selfhost)):new Set;for(let[n,i]of Object.entries(t)){let a=Number(n),s=Number(i);for(let[c,u]of Object.entries(e)){if(o.has(c))continue;if(u===String(a)){e[c]=String(s);continue}let d=new RegExp(`:${a}(?=[/\\s]|$)`,"g");e[c]=u.replaceAll(d,`:${s}`)}}}function To(e,t){return e.map(r=>({...r,variables:r.variables.map(o=>{let n=ur(o.name,t);return{...o,defaultValue:n||o.defaultValue}})}))}function pr(){return Object.keys(lr.selfhost)}function Co(e){return{...yo[e]}}function dr(e){j.existsSync(e)&&j.copyFileSync(e,`${e}.bak`)}function Po(e,t){let r=Oe.join(e,".env");dr(r);let o=["# GAIA Environment Configuration","# Generated by GAIA CLI",`# Created: ${new Date().toISOString()}`,""],n=["MONGO","REDIS","POSTGRES","CHROMADB","RABBITMQ","WORKOS","GOOGLE","OPENAI","INFISICAL","LANGSMITH","DISCORD","SLACK","TELEGRAM","CLOUDINARY","COMPOSIO","FIRECRAWL","LIVEKIT","DEEPGRAM","ELEVENLABS","RESEND","SENTRY","POSTHOG","E2B","DODO","NEXT_PUBLIC","GAIA"];function i(s){for(let u of n)if(s===u||s.startsWith(`${u}_`))return u;let c=s.split("_");return c.length===1?"Core":c[0]||"Core"}let a=new Map;for(let[s,c]of Object.entries(t)){let u=i(s);a.has(u)||a.set(u,[]);let m=/[\s#"'\\]/.test(c)||c===""?`"${c.replace(/\\/g,"\\\\").replace(/"/g,'\\"')}"`:c;a.get(u).push(`${s}=${m}`)}for(let[s,c]of a.entries())o.push(`# ${s} Configuration`),o.push(...c),o.push("");j.writeFileSync(r,o.join(`
35
+ `),"utf-8")}function Ro(e,t,r){let o=Oe.join(e,"apps","web",".env.local");dr(o);let n=wo(e),i=Eo(t,r),a=["# GAIA Web App Environment Configuration","# Generated by GAIA CLI",`# Created: ${new Date().toISOString()}`,""],s=new Map;for(let c of n){s.has(c.category)||s.set(c.category,[]);let u=i[c.name]??c.value;s.get(c.category).push({name:c.name,value:u})}if(n.length===0){a.push("# Core URLs");for(let[c,u]of Object.entries(i))a.push(`${c}=${u}`);a.push("")}else for(let[c,u]of s.entries()){a.push(`# ${c}`);for(let{name:d,value:m}of u)a.push(`${d}=${m}`);a.push("")}j.writeFileSync(o,a.join(`
36
+ `),"utf-8")}var ko={8e3:"API_HOST_PORT",5432:"POSTGRES_HOST_PORT",6379:"REDIS_HOST_PORT",27017:"MONGO_HOST_PORT",5672:"RABBITMQ_HOST_PORT",8080:"CHROMADB_HOST_PORT",8083:"MONGO_EXPRESS_HOST_PORT",3e3:"WEB_HOST_PORT"};function _o(e,t,r){let o=Oe.join(e,"infra","docker",".env");dr(o);let n=["# Docker Compose environment overrides","# Generated by GAIA CLI",`# Created: ${new Date().toISOString()}`,""];for(let[i,a]of Object.entries(t)){let s=Number(i),c=ko[s];c&&n.push(`${c}=${a}`)}if(r==="selfhost"){let i=t[8e3]??8e3;n.push(""),n.push("# Web build args"),n.push(`NEXT_PUBLIC_API_BASE_URL=http://localhost:${i}/api/v1/`)}n.push(""),j.writeFileSync(o,n.join(`
37
+ `),"utf-8")}function me(e){let t={};for(let[r,o]of Object.entries(e)){let n=Number(r),i=ko[n];i&&(t[i]=String(o))}return t}function Do(e){let t=Oe.join(e,"infra","docker","docker-compose.yml");if(!j.existsSync(t))return;let r=j.readFileSync(t,"utf-8"),o=[{varName:"API_HOST_PORT",hostPort:8e3,containerPort:80},{varName:"CHROMADB_HOST_PORT",hostPort:8080,containerPort:8e3},{varName:"POSTGRES_HOST_PORT",hostPort:5432,containerPort:5432},{varName:"REDIS_HOST_PORT",hostPort:6379,containerPort:6379},{varName:"MONGO_HOST_PORT",hostPort:27017,containerPort:27017},{varName:"RABBITMQ_HOST_PORT",hostPort:5672,containerPort:5672},{varName:"MONGO_EXPRESS_HOST_PORT",hostPort:8083,containerPort:8081},{varName:"WEB_HOST_PORT",hostPort:3e3,containerPort:3e3}],n=!1;for(let{varName:i,hostPort:a,containerPort:s}of o){let c=`"${a}:${s}"`,u=`"\${${i}:-${a}}:${s}"`;r.includes(c)&&(r=r.replaceAll(c,u),n=!0)}n&&j.writeFileSync(t,r,"utf-8")}var Io={API_HOST_PORT:8e3,POSTGRES_HOST_PORT:5432,REDIS_HOST_PORT:6379,MONGO_HOST_PORT:27017,RABBITMQ_HOST_PORT:5672,CHROMADB_HOST_PORT:8080,MONGO_EXPRESS_HOST_PORT:8083,WEB_HOST_PORT:3e3};function fe(e){let t=Oe.join(e,"infra","docker",".env"),r={};if(!j.existsSync(t))return r;let o=j.readFileSync(t,"utf-8");for(let n of o.split(`
38
+ `)){let i=n.trim();if(i&&!i.startsWith("#")){let[a,...s]=i.split("=");if(a&&Io[a]){let c=s.join("=").trim().replace(/^["']|["']$/g,""),u=Number(c);!Number.isNaN(u)&&u>0&&u<=65535&&(r[Io[a]]=u)}}}return r}var Ui=e=>new Promise(t=>setTimeout(t,e)),Ao="dev-start.log",pt=".gaia-dev.pid";function Oo(e){let t=W.join(e,".env");return Q.existsSync(t)?["--env-file",".env"]:[]}var qi=60;function Hi(){let e=process.env.GAIA_START_TIMEOUT_MIN?.trim(),t=e?Number(e):Number.NaN,r=Number.isFinite(t)&&t>=0?t:qi;return r===0?void 0:r*60*1e3}function Vi(e,t){let r=["compose","-f","docker-compose.selfhost.yml",...e,"up","-d","--remove-orphans"];return t?.build&&r.push("--build"),t?.pull&&r.push("--pull","always"),r}function mr(e){let t=W.join(e,pt);if(!Q.existsSync(t))return null;try{let r=Number.parseInt(Q.readFileSync(t,"utf-8").trim(),10);return Number.isNaN(r)||r<=0?null:r}catch{return null}}function ut(e){try{return process.kill(e,0),!0}catch(t){return t.code==="EPERM"}}async function qe(e,t,r,o,n,i){if(t!=="selfhost")throw r?.("Developer mode must run in foreground."),new Error("Developer mode runs in foreground. Use 'gaia dev' or 'gaia dev full' instead of 'gaia start'.");r?.(i?.build?"Building and starting all services in Docker...":"Starting all services in Docker (selfhost mode)...");let a=W.join(e,"infra/docker"),s=o&&Object.keys(o).length>0?me(o):void 0;await H("docker",Vi(Oo(a),i),a,void 0,n,s,Hi()),r?.("All services started in Docker!")}async function Lo(e,t,r,o){let n=W.join(e,"infra/docker"),i=await Ee(e);t?.("Stopping Docker services...");try{let a=Oo(n),s=i==="selfhost"?["compose","-f","docker-compose.selfhost.yml",...a,"down"]:["compose",...a,"down"];await H("docker",s,n)}catch{}if(i!=="selfhost"){t?.("Stopping GAIA-managed local processes (safe mode)...");let a=W.join(e,pt),s=!1,c=mr(e),u=typeof c=="number";if(c&&ut(c))try{if(process.platform==="win32")await H("taskkill",["/PID",String(c),"/T","/F"],e),s=!0;else{try{process.kill(-c,"SIGTERM"),s=!0}catch{process.kill(c,"SIGTERM"),s=!0}if(await Ui(800),ut(c))try{process.kill(-c,"SIGKILL")}catch{process.kill(c,"SIGKILL")}}}catch{}try{Q.unlinkSync(a)}catch{}if(!s&&o?.forcePorts){t?.("No GAIA PID found. Force-stopping listeners on app ports...");try{let d=r?.[8e3]??8e3,m=r?.[3e3]??3e3;if(process.platform==="win32")for(let f of[d,m])try{await H("powershell",["-Command",`Get-NetTCPConnection -LocalPort ${f} -ErrorAction SilentlyContinue | ForEach-Object { Stop-Process -Id $_.OwningProcess -Force -ErrorAction SilentlyContinue }`],e)}catch{}else for(let f of[d,m])try{await H("sh",["-c",`lsof -ti :${f} -sTCP:LISTEN | xargs kill 2>/dev/null || true`],e)}catch{}}catch{}}else s||t?.(u?"Stored GAIA PID is stale. Skipping port cleanup in safe mode. Use `gaia stop --force-ports` for aggressive cleanup.":"No GAIA-managed PID found. Skipping port cleanup in safe mode. Use `gaia stop --force-ports` for aggressive cleanup.")}t?.("All services stopped.")}async function Ee(e){let t=W.join(e,"apps","api",".env");if(!Q.existsSync(t))return null;let r=Q.readFileSync(t,"utf-8"),o=r.match(/^SETUP_MODE=(.+)$/m);if(o?.[1]){let n=o[1].trim().replace(/^["']|["']$/g,"");if(n==="selfhost"||n==="developer")return n}return r.includes("mongodb://mongo:")?"selfhost":(r.includes("mongodb://localhost:"),"developer")}async function H(e,t,r,o,n,i,a){let{spawn:s}=await import("child_process");return new Promise((c,u)=>{let d=s(e,t,{cwd:r,stdio:["ignore","pipe","pipe"],shell:!0,env:i?{...process.env,...i}:void 0}),m="",f=0,S=!1,v;a&&(v=setTimeout(()=>{S=!0,d.kill("SIGTERM"),u(new Error(`Command timed out after ${Math.round(a/6e4)}m. Check \`docker compose logs\` to debug.`))},a)),d.stdout?.on("data",y=>{let w=y.toString();m+=w,n?.(w),f=Math.min(f+5,95),o?.(f)}),d.stderr?.on("data",y=>{let w=y.toString();m+=w,n?.(w),f=Math.min(f+5,95),o?.(f)}),d.on("close",y=>{v&&clearTimeout(v),!S&&(y===0?(o?.(100),c()):u(new Error(`Command failed with code ${y}: ${m.slice(-500)}`)))}),d.on("error",y=>{v&&clearTimeout(v),!S&&u(y)})})}function U(e){let t=e||process.cwd();for(;t!==W.dirname(t);){if(Q.existsSync(W.join(t,"apps/api/app/config/settings_validator.py")))return t;t=W.dirname(t)}let r=cr();if(r?.repoPath){if(Q.existsSync(W.join(r.repoPath,"apps/api/app/config/settings_validator.py")))return r.repoPath;console.warn(`Warning: Saved repo path "${r.repoPath}" is no longer a valid GAIA installation. Resetting config.`),Ue({repoPath:"",setupComplete:!1})}return null}async function No(e){if(e&&e!=="full")throw new Error(`Invalid developer profile: '${e}'. Use 'gaia dev' or 'gaia dev full'.`);let t=U();if(!t)throw new Error("Could not find GAIA repository. Run from within a cloned gaia repo.");let r=await Ee(t);if(!r)throw new Error("No .env file found. Run 'gaia init' for fresh setup, or 'gaia setup' to configure an existing repo.");if(r!=="developer")throw new Error("Developer mode is not enabled for this repo. Use 'gaia start' for self-host mode.");let o=Mo.join(t,pt);try{await _e("mise",[e==="full"?"dev:full":"dev"],t,void 0,n=>{typeof n=="number"&&n>0&&dt.writeFileSync(o,`${n}
39
+ `)},process.platform!=="win32")}finally{try{dt.unlinkSync(o)}catch{}}}import{render as bs}from"ink";import Ts from"react";import{Box as yt,Text as Te}from"ink";import Ss from"react";import{ProgressBar as jo,Select as hr,Spinner as ts}from"@inkjs/ui";import{Box as g,Text as p,useInput as ge}from"ink";import We from"ink-text-input";import{useEffect as Xe,useRef as rs,useState as G}from"react";import{Box as He,Text as mt}from"ink";var x="#00bbff";import{Box as Wi,Text as Xi}from"ink";import{jsx as Bo}from"react/jsx-runtime";var Fo=({status:e,step:t})=>t.toLowerCase()==="welcome"?null:Bo(Wi,{width:"100%",paddingX:1,marginTop:1,children:Bo(Xi,{color:"gray",dimColor:!0,children:e})});import{Box as Yi}from"ink";import Ki from"ink-big-text";import Ji from"ink-gradient";import{jsx as fr}from"react/jsx-runtime";var Le=()=>fr(Yi,{flexDirection:"column",marginTop:1,marginBottom:1,children:fr(Ji,{colors:[x,"#b0eaff",x],children:fr(Ki,{text:"GAIA",font:"3d"})})});import{jsx as be,jsxs as Ve}from"react/jsx-runtime";var Qi=["Welcome","Prerequisites","Setup Mode","Repository Setup","Environment Setup","Install Tools","Project Setup","Finished"],$o=["Detect Repo","Prerequisites","Environment Setup","Project Setup","Finished"],zi={Welcome:"Welcome",Prerequisites:"Prereqs","Setup Mode":"Mode","Repository Setup":"Repo","Environment Setup":"Env","Install Tools":"Tools","Project Setup":"Setup","Detect Repo":"Detect",Finished:"Done"},Zi=({currentStep:e,steps:t})=>{let r=t.indexOf(e);return be(He,{marginBottom:1,flexWrap:"nowrap",children:t.map((o,n)=>{let i=n<r,a=n===r,s=zi[o]??o;return Ve(He,{flexShrink:0,children:[n>0&&Ve(mt,{color:"gray",dimColor:!0,children:[" ","\xB7"," "]}),i&&Ve(mt,{color:"green",children:["\u2713 ",s]}),a&&be(mt,{color:x,bold:!0,children:s}),!i&&!a&&be(mt,{color:"gray",dimColor:!0,children:s})]},o)})})},ft=({children:e,status:t,step:r,steps:o=Qi})=>Ve(He,{flexDirection:"column",height:"100%",width:"100%",children:[Ve(He,{flexGrow:1,flexDirection:"column",children:[be(Le,{}),be(Zi,{currentStep:r,steps:o}),be(He,{flexDirection:"column",flexGrow:1,children:e})]}),be(Fo,{status:t,step:r})]});import{Spinner as Go}from"@inkjs/ui";import{Box as q,Text as M,useInput as es}from"ink";import{jsx as R,jsxs as V}from"react/jsx-runtime";var gt=({checks:e})=>V(q,{flexDirection:"column",borderStyle:"round",paddingX:1,borderColor:x,children:[R(M,{bold:!0,children:"System Checks"}),V(q,{flexDirection:"column",marginTop:1,children:[R(gr,{label:"Git",status:e.git}),R(gr,{label:"Docker",status:e.docker}),e.mise&&R(gr,{label:"Mise",status:e.mise})]})]}),ht=({status:e})=>V(q,{flexDirection:"column",marginTop:1,paddingX:1,borderStyle:"round",borderColor:x,children:[R(M,{bold:!0,children:"Environment Setup"}),R(q,{marginTop:1,children:R(Go,{label:e||"Configuring environment..."})})]}),vt=({message:e})=>V(q,{flexDirection:"column",borderStyle:"single",borderColor:"red",padding:1,marginTop:2,children:[V(M,{color:"red",children:["Error: ",e]}),R(q,{marginTop:1,children:V(M,{dimColor:!0,children:[R(M,{bold:!0,children:"Enter"})," to exit"]})})]}),gr=({label:e,status:t})=>V(q,{children:[R(q,{marginRight:1,children:t==="pending"?R(Go,{type:"dots"}):t==="success"?R(M,{color:"green",children:"\u2714"}):t==="error"?R(M,{color:"red",children:"\u2716"}):R(M,{color:"yellow",children:"\u26A0"})}),R(M,{children:e})]}),St=({portResults:e,onAccept:t,onAbort:r})=>{es((n,i)=>{i.return?t():i.escape&&r()});let o=e.filter(n=>!n.available);return V(q,{flexDirection:"column",marginTop:1,paddingX:1,borderStyle:"round",borderColor:"yellow",children:[R(q,{marginBottom:1,children:R(M,{bold:!0,color:"yellow",children:"Port Conflicts Detected"})}),e.map(n=>V(q,{children:[V(M,{color:n.available?"green":n.alternative?"yellow":"red",children:[n.available?"\u2714":n.alternative?"\u26A0":"\u2716"," "]}),V(M,{children:[n.service," (:",n.port,")"]}),!n.available&&V(M,{color:n.alternative?"gray":"red",children:[" ","- in use",n.usedBy?` by ${n.usedBy}`:"",n.alternative?` \u2192 will use :${n.alternative}`:" \u2014 NO ALTERNATIVE FOUND"]})]},n.port)),o.some(n=>!n.alternative)&&R(q,{marginTop:1,children:R(M,{color:"red",children:"Some ports have no available alternative. Free them and retry."})}),!o.some(n=>!n.alternative)&&o.some(n=>n.alternative)&&R(q,{marginTop:1,children:R(M,{color:"gray",children:"Alternative ports will be used for conflicting services."})}),R(q,{marginTop:1,children:V(M,{dimColor:!0,children:[R(M,{bold:!0,children:"Enter"})," continue \xB7 ",R(M,{bold:!0,children:"ESC"})," abort"]})})]})};import{jsx as l,jsxs as h}from"react/jsx-runtime";var os=({onConfirm:e})=>(ge((t,r)=>{r.return&&e()}),h(g,{flexDirection:"column",paddingX:2,borderStyle:"round",borderColor:x,children:[l(p,{bold:!0,children:"Welcome to GAIA Setup"}),h(g,{flexDirection:"column",marginTop:1,marginBottom:1,children:[l(p,{children:"This wizard will guide you through the setup process:"}),l(p,{children:" 1. Check prerequisites and choose setup mode"}),l(p,{children:" 2. Clone repository"}),l(p,{children:" 3. Configure environment variables"}),l(p,{children:" 4. Install tools and dependencies"})]}),l(p,{dimColor:!0,children:"~5-15 min depending on network speed"}),l(g,{marginTop:1,children:h(p,{color:x,children:[l(p,{bold:!0,children:"Enter"})," to start"]})})]})),ns=({defaultValue:e,onSubmit:t})=>{let[r,o]=G(e);return h(g,{flexDirection:"column",marginTop:1,paddingX:1,borderStyle:"round",borderColor:x,children:[l(p,{children:"Clone repository to:"}),l(p,{color:"gray",dimColor:!0,children:"Press Enter for default, or type a custom path"}),h(g,{marginTop:1,children:[l(p,{color:x,children:"\u2192 "}),l(We,{value:r,onChange:o,onSubmit:t})]})]})},is=({repoPath:e,onAction:t})=>h(g,{flexDirection:"column",marginTop:1,paddingX:1,borderStyle:"round",borderColor:"yellow",children:[l(g,{marginBottom:1,children:l(p,{bold:!0,color:"yellow",children:"Existing Installation Found"})}),h(p,{children:["Found a GAIA installation at"," ",l(p,{color:"cyan",bold:!0,children:e})]}),l(g,{marginTop:1,children:l(p,{color:"gray",children:"What would you like to do?"})}),l(g,{marginTop:1,children:l(hr,{options:[{label:"Use existing installation",value:"use_existing"},{label:"Delete and re-clone",value:"delete_reclone"},{label:"Choose a different path",value:"different_path"},{label:"Exit setup",value:"exit"}],onChange:o=>t(o)})})]}),ss=({setupMode:e,portOverrides:t,onConfirm:r})=>{ge((i,a)=>{a.return&&r()});let o=t?.[3e3]??3e3,n=t?.[8e3]??8e3;return e==="selfhost"?h(g,{flexDirection:"column",marginTop:2,borderStyle:"round",borderColor:"green",padding:1,children:[l(p,{bold:!0,color:"green",children:"GAIA is Running!"}),l(g,{marginTop:1,children:l(p,{color:"green",children:"\u2713 All services started"})}),h(g,{marginTop:1,flexDirection:"column",children:[h(p,{children:["Web:"," ",h(p,{color:"cyan",bold:!0,children:["http://localhost:",o]})]}),h(p,{children:["API:"," ",h(p,{color:"cyan",bold:!0,children:["http://localhost:",n]})]})]}),l(g,{marginTop:1,children:l(p,{color:"gray",children:"gaia logs \xB7 gaia stop \xB7 gaia status \xB7 gaia setup"})}),l(g,{marginTop:1,children:h(p,{dimColor:!0,children:[l(p,{bold:!0,children:"Enter"})," to exit"]})})]}):h(g,{flexDirection:"column",marginTop:2,borderStyle:"round",borderColor:x,padding:1,children:[l(p,{color:x,bold:!0,children:"You're all set!"}),h(g,{marginTop:1,children:[l(p,{bold:!0,children:"Run: "}),l(p,{color:"cyan",children:"$ gaia dev"})]}),h(g,{marginTop:1,flexDirection:"column",children:[h(p,{children:["Web:"," ",h(p,{color:"cyan",bold:!0,children:["http://localhost:",o]})]}),h(p,{children:["API:"," ",h(p,{color:"cyan",bold:!0,children:["http://localhost:",n]})]})]}),l(g,{marginTop:1,children:l(p,{color:"gray",children:"gaia dev full \xB7 gaia logs \xB7 gaia stop \xB7 gaia status \xB7 gaia setup"})}),l(g,{marginTop:1,children:h(p,{dimColor:!0,children:[l(p,{bold:!0,children:"Enter"})," to exit"]})})]})},as=8,cs=({logs:e,height:t=as})=>{let[r,o]=G(0),n=rs(e.length);Xe(()=>{e.length!==n.current&&(n.current=e.length,o(0))},[e.length]),ge((m,f)=>{f.upArrow?o(S=>Math.min(S+1,Math.max(0,e.length-t))):f.downArrow&&o(S=>Math.max(0,S-1))});let i=e.length,a=Math.max(0,i-t-r),s=Math.max(0,i-r),c=e.slice(a,s),u=a,d=r;return h(g,{flexDirection:"column",marginTop:1,marginLeft:1,children:[u>0&&h(p,{color:"gray",dimColor:!0,children:["\u2191 ",u," more line",u!==1?"s":""]}),l(g,{flexDirection:"column",height:t,overflow:"hidden",children:c.map((m,f)=>l(p,{color:"gray",wrap:"truncate",children:m},`${a}-${f}`))}),d>0?h(p,{color:"gray",dimColor:!0,children:["\u2193 ",d," more line",d!==1?"s":""]}):l(p,{color:"gray",dimColor:!0,children:"\u2191\u2193 scroll"})]})},vr=({phase:e,progress:t,isComplete:r,logs:o,title:n})=>h(g,{flexDirection:"column",marginTop:1,paddingX:1,borderStyle:"round",borderColor:x,children:[l(g,{marginBottom:1,children:l(p,{bold:!0,color:x,children:n||"Installing Dependencies"})}),h(g,{flexDirection:"column",gap:1,children:[l(g,{children:r?h(p,{color:"green",children:["\u2713 ",e]}):l(ts,{label:e||"Preparing..."})}),!r&&t>0&&l(g,{width:50,children:l(jo,{value:t})}),!r&&o&&o.length>0&&l(cs,{logs:o}),!r&&l(g,{marginTop:1,children:l(p,{color:"gray",dimColor:!0,children:"This may take a few minutes..."})})]})]}),Sr=({onSelect:e})=>h(g,{flexDirection:"column",marginTop:1,paddingX:1,borderStyle:"round",borderColor:x,children:[l(p,{bold:!0,children:"Setup Mode"}),l(g,{marginTop:1,children:l(p,{color:"gray",children:"How do you want to run GAIA?"})}),l(g,{marginTop:1,children:l(hr,{options:[{label:"Self-Host \u2014 run everything in Docker",value:"selfhost"},{label:"Developer \u2014 local dev with hot reload",value:"developer"}],onChange:r=>e(r)})})]}),yr=({onSelect:e})=>h(g,{flexDirection:"column",marginTop:1,paddingX:1,borderStyle:"round",borderColor:x,children:[l(p,{bold:!0,children:"Environment Variables Setup"}),l(g,{marginTop:1,children:l(p,{color:"gray",children:"Choose how you want to configure environment variables:"})}),l(g,{marginTop:1,children:l(hr,{options:[{label:"Manual Setup (Recommended)",value:"manual"},{label:"Infisical (Advanced)",value:"infisical"}],onChange:r=>e(r)})}),h(g,{marginTop:1,flexDirection:"column",children:[l(p,{color:"gray",dimColor:!0,children:"Manual Setup: Configure variables interactively (recommended for most users)"}),l(p,{color:"gray",dimColor:!0,children:"Infisical: All secrets managed in Infisical dashboard (requires pre-configuration)"})]})]}),xr=({onSubmit:e})=>{let[t,r]=G({INFISICAL_PROJECT_ID:"",INFISICAL_MACHINE_IDENTITY_CLIENT_ID:"",INFISICAL_MACHINE_IDENTITY_CLIENT_SECRET:""}),[o,n]=G(0),[i,a]=G(null),s=[{key:"INFISICAL_PROJECT_ID",description:"Found in your Infisical project settings"},{key:"INFISICAL_MACHINE_IDENTITY_CLIENT_ID",description:"From Access Control \u2192 Machine Identities"},{key:"INFISICAL_MACHINE_IDENTITY_CLIENT_SECRET",description:"Generated when creating the machine identity"}];ge((u,d)=>{if(d.tab||d.downArrow)n(m=>m<s.length-1?m+1:m);else if(d.upArrow)n(m=>m>0?m-1:m);else if(d.return){if(o<s.length-1){n(f=>f+1);return}let m=s.filter(f=>!t[f.key].trim());if(m.length>0){a(`Required: ${m.map(S=>S.key).join(", ")}`);let f=s.findIndex(S=>!t[S.key].trim());f>=0&&n(f);return}e(t)}});let c=s[o];return h(g,{flexDirection:"column",marginTop:1,paddingX:1,borderStyle:"round",borderColor:x,children:[l(g,{marginBottom:1,children:l(p,{bold:!0,color:x,children:"Infisical Configuration"})}),l(g,{marginBottom:1,children:l(p,{color:"gray",children:"All secrets managed in your Infisical project. Only credentials stored locally."})}),h(g,{marginBottom:1,flexDirection:"column",children:[l(p,{color:"gray",children:"Configure your Infisical credentials."}),h(p,{color:"gray",dimColor:!0,children:["Visit"," ",l(p,{color:"cyan",underline:!0,children:"app.infisical.com"})," ","to get these values."]})]}),s.map((u,d)=>{let m=u.key.includes("SECRET")||u.key.includes("TOKEN");return h(g,{flexDirection:"column",marginBottom:1,children:[l(g,{children:h(p,{color:d===o?x:"white",children:[d===o?"\u25B8 ":" ",u.key,":"]})}),l(g,{marginLeft:2,children:l(p,{color:"gray",dimColor:!0,children:u.description})}),d===o?l(g,{marginLeft:2,children:l(We,{value:t[u.key],onChange:f=>{r(S=>({...S,[u.key]:f})),a(null)},placeholder:"Enter value...",mask:m?"*":void 0})}):l(g,{marginLeft:2,children:l(p,{color:t[u.key]?"green":"gray",children:t[u.key]?m?`\u2713 ${"*".repeat(8)}`:`\u2713 ${t[u.key]}`:"(not set)"})})]},u.key)}),i&&l(g,{marginTop:1,children:l(p,{color:"red",children:i})}),l(g,{marginTop:1,children:h(p,{dimColor:!0,children:[l(p,{bold:!0,children:"Enter"})," confirm \xB7 ",l(p,{bold:!0,children:"\u2191\u2193"})," navigate"]})})]})},wr=({category:e,currentIndex:t,totalGroups:r,onSubmit:o})=>{let[n,i]=G(()=>{let f={};for(let S of e.variables)f[S.name]=S.defaultValue||"";return f}),[a,s]=G(0),[c,u]=G(null);Xe(()=>{let f={};for(let S of e.variables)f[S.name]=S.defaultValue||"";i(f),s(0),u(null)},[e.name]),ge((f,S)=>{if(S.tab||S.downArrow)s(v=>v<e.variables.length-1?v+1:v);else if(S.upArrow)s(v=>v>0?v-1:v);else if(S.escape){let v=e.variables.filter(y=>y.required&&!n[y.name]?.trim());if(v.length>0){u(`Required fields cannot be skipped: ${v.map(y=>y.name).join(", ")}`);return}o(n)}});let d=()=>{if(a<e.variables.length-1)s(a+1);else{let f=e.variables.filter(S=>S.required&&!n[S.name]?.trim());if(f.length>0){u(`Required fields are missing: ${f.map(S=>S.name).join(", ")}`);return}u(null),o(n)}},m=e.variables.some(f=>f.required);return h(g,{flexDirection:"column",marginTop:1,paddingX:1,borderStyle:"round",borderColor:c?"red":x,children:[h(g,{justifyContent:"space-between",children:[h(p,{bold:!0,children:["Configure ",e.name]}),h(p,{color:"gray",children:["Group ",t+1," / ",r]})]}),l(g,{marginTop:1,children:l(p,{color:"gray",children:e.description})}),l(g,{marginTop:1,flexDirection:"column",children:e.variables.map((f,S)=>{let v=S===a,y=!!f.defaultValue;return h(g,{flexDirection:"column",marginBottom:1,children:[h(g,{children:[h(p,{color:v?x:"gray",bold:v,children:[v?"\u279C ":" ",f.name]}),f.required&&h(p,{color:"red",bold:!0,children:[" ","*"]}),y&&!v&&h(p,{color:"gray",dimColor:!0,children:[" ","(default: ",f.defaultValue,")"]})]}),v&&l(g,{marginLeft:2,children:l(We,{value:n[f.name]||"",onChange:w=>{i(E=>({...E,[f.name]:w})),c&&u(null)},onSubmit:d,placeholder:y?`Default: ${f.defaultValue}`:f.required?"Enter a value (required)":"Press Enter to skip"})})]},f.name)})}),c&&l(g,{marginTop:1,children:h(p,{color:"red",bold:!0,children:["\u26A0 ",c]})}),l(g,{marginTop:1,children:h(p,{dimColor:!0,children:[l(p,{bold:!0,children:"Enter"})," next \xB7 ",l(p,{bold:!0,children:"\u2191\u2193"})," navigate",!m&&h(p,{children:[" ","\xB7 ",l(p,{bold:!0,children:"ESC"})," skip"]})]})})]})},Er=({alternatives:e,onSubmit:t})=>{let[r,o]=G(new Set),[n,i]=G({}),[a,s]=G(0),[c,u]=G(null);Xe(()=>{let w={};for(let E of e)for(let I of E.variables)w[I.name]=I.defaultValue||"";i(w)},[e]);let d=[];for(let w=0;w<e.length;w++)if(d.push({type:"provider",categoryIndex:w}),r.has(w)){let E=e[w];if(E)for(let I=0;I<E.variables.length;I++)d.push({type:"field",categoryIndex:w,fieldIndex:I})}d.push({type:"submit"});let m=d[a],f=m?.type==="field",S=m?.type==="submit";ge((w,E)=>{let I=Math.min(a,d.length-1);if(I!==a){s(I);return}if(f)E.upArrow?s(P=>Math.max(0,P-1)):(E.downArrow||E.tab)&&s(P=>Math.min(d.length-1,P+1));else if(S)E.upArrow?s(P=>Math.max(0,P-1)):(E.return||w===" ")&&y();else if(E.upArrow)s(P=>Math.max(0,P-1));else if(E.downArrow||E.tab)s(P=>Math.min(d.length-1,P+1));else if((E.return||w===" ")&&m?.type==="provider"){let P=m.categoryIndex;o(oe=>{let D=new Set(oe);return D.has(P)?D.delete(P):D.add(P),D}),c&&u(null)}});let v=()=>{c&&u(null),s(w=>Math.min(d.length-1,w+1))},y=()=>{let w=[],E={};for(let I of r){let P=e[I];if(!P)continue;if(P.variables.some(D=>n[D.name]?.trim())){w.push(P.name);for(let D of P.variables){let Je=n[D.name];Je&&(E[D.name]=Je)}}}if(w.length===0){r.size===0?u("Enable at least one provider (press Space or Enter)"):u("Enter a value for at least one field");return}t(w,E)};return h(g,{flexDirection:"column",marginTop:1,paddingX:1,borderStyle:"round",borderColor:c?"red":x,children:[h(g,{justifyContent:"space-between",children:[l(p,{bold:!0,children:"Configure AI Provider"}),l(p,{color:"yellow",children:"* At least one required"})]}),l(g,{marginTop:1,children:l(p,{color:"gray",children:"Enable and configure at least one AI provider below:"})}),l(g,{marginTop:1,flexDirection:"column",children:e.map((w,E)=>{let I=r.has(E),P=d.findIndex(D=>D.type==="provider"&&D.categoryIndex===E),oe=a===P;return h(g,{flexDirection:"column",marginBottom:1,children:[h(g,{children:[l(p,{color:oe?x:void 0,bold:oe,children:oe?"\u279C ":" "}),l(p,{color:I?"green":"gray",children:I?"[\u2714]":"[ ]"}),h(p,{color:I?x:"gray",bold:I,children:[" ",w.name]}),w.description&&h(p,{color:"gray",dimColor:!0,children:[" ","- ",w.description]})]}),oe&&w.docsUrl&&h(g,{marginLeft:6,children:[l(p,{color:"yellow",children:"\u{1F4D6} "}),l(p,{color:"blue",underline:!0,children:w.docsUrl})]}),I&&l(g,{marginLeft:4,flexDirection:"column",marginTop:1,children:w.variables.map((D,Je)=>{let Pn=d.findIndex(Me=>Me.type==="field"&&Me.categoryIndex===E&&Me.fieldIndex===Je),Ce=a===Pn,Dr=!!D.defaultValue,_t=n[D.name]||"";return h(g,{flexDirection:"column",marginBottom:1,children:[h(g,{children:[h(p,{color:Ce?x:"gray",bold:Ce,children:[Ce?" \u279C ":" ",D.name]}),!Ce&&_t&&l(p,{color:"green",children:" \u2713"}),!Ce&&!_t&&Dr&&h(p,{color:"gray",dimColor:!0,children:[" ","(default: ",D.defaultValue,")"]})]}),Ce&&l(g,{marginLeft:4,children:l(We,{value:_t,onChange:Me=>{i(Rn=>({...Rn,[D.name]:Me})),c&&u(null)},onSubmit:v,placeholder:Dr?`Default: ${D.defaultValue}`:"Enter value..."})})]},D.name)})})]},w.name)})}),c&&l(g,{marginTop:1,children:h(p,{color:"red",bold:!0,children:["\u26A0 ",c]})}),h(g,{marginTop:1,children:[l(p,{color:S?x:void 0,bold:S,children:S?"\u279C ":" "}),l(g,{borderStyle:"round",borderColor:S?x:"gray",paddingX:2,children:l(p,{color:S?x:"gray",bold:S,children:"Continue \u2192"})})]}),l(g,{marginTop:1,children:l(p,{color:"gray",dimColor:!0,children:"\u2191/\u2193 navigate \u2022 Space/Enter toggle/select \u2022 Tab skip field"})})]})},br=({currentVar:e,currentIndex:t,totalCount:r,onSubmit:o,onSkip:n})=>{let[i,a]=G(e.defaultValue||""),[s,c]=G(null);Xe(()=>{a(e.defaultValue||""),c(null)},[e.name]),ge((m,f)=>{if(f.escape){if(e.required&&!i.trim()){c("This field is required and cannot be skipped");return}n()}});let u=m=>{if(e.required&&!m.trim()){c("This field is required");return}c(null),o(m)},d=!!e.defaultValue;return h(g,{flexDirection:"column",marginTop:1,paddingX:1,borderStyle:"round",borderColor:s?"red":x,children:[h(g,{justifyContent:"space-between",children:[h(g,{children:[l(p,{color:x,bold:!0,children:e.name}),e.required?l(p,{color:"red",children:" *"}):h(p,{color:"gray",dimColor:!0,children:[" ","optional"]})]}),h(p,{color:"gray",children:[t+1,"/",r]})]}),l(g,{marginLeft:1,children:l(p,{color:"gray",children:e.description})}),h(g,{marginTop:1,children:[l(p,{color:x,children:"\u2192 "}),l(We,{value:i,onChange:m=>{a(m),s&&c(null)},onSubmit:u,placeholder:d?`Default: ${e.defaultValue}`:e.required?"required":"skip with Enter"})]}),s&&l(g,{marginTop:1,children:l(p,{color:"red",children:s})}),l(g,{marginTop:1,children:h(p,{dimColor:!0,children:[l(p,{bold:!0,children:"Enter"})," confirm",!e.required&&h(p,{children:[" ","\xB7 ",l(p,{bold:!0,children:"ESC"})," skip"]})]})})]})},Uo=({store:e})=>{let[t,r]=G(e.currentState);return Xe(()=>{let o=()=>r({...e.currentState});return e.on("change",o),()=>{e.off("change",o)}},[e]),ge((o,n)=>{(n.return||n.escape)&&t.error&&e.submitInput("exit")}),h(ft,{status:t.status,step:t.step,children:[t.step==="Welcome"&&t.inputRequest?.id==="welcome"&&l(os,{onConfirm:()=>e.submitInput(!0)}),t.step==="Prerequisites"&&t.data.checks&&l(gt,{checks:t.data.checks}),t.inputRequest?.id==="port_conflicts"&&t.data.portConflicts&&l(St,{portResults:t.data.portConflicts,onAccept:()=>e.submitInput("accept"),onAbort:()=>e.submitInput("abort")}),t.inputRequest?.id==="repo_path"&&l(ns,{defaultValue:t.inputRequest.meta.default,onSubmit:o=>e.submitInput(o)}),t.inputRequest?.id==="existing_repo"&&t.data.existingRepoPath&&l(is,{repoPath:t.data.existingRepoPath,onAction:o=>e.submitInput(o)}),t.step==="Repository Setup"&&!t.inputRequest&&h(g,{flexDirection:"column",borderStyle:"round",padding:1,borderColor:x,children:[l(p,{bold:!0,children:"Cloning Repository"}),h(g,{marginTop:1,flexDirection:"column",children:[l(jo,{value:t.data.repoProgress||0}),t.data.repoPhase&&l(g,{marginTop:1,children:l(p,{color:"gray",children:t.data.repoPhase})})]})]}),t.inputRequest?.id==="setup_mode"&&l(Sr,{onSelect:o=>e.submitInput(o)}),t.inputRequest?.id==="env_method"&&l(yr,{onSelect:o=>e.submitInput(o)}),t.inputRequest?.id==="env_infisical"&&l(xr,{onSubmit:o=>e.submitInput(o)}),t.step==="Environment Setup"&&t.inputRequest?.id==="env_var"&&t.data.currentEnvVar&&l(br,{categories:t.data.envCategories||[],currentVar:t.data.currentEnvVar,currentIndex:t.data.envVarIndex||0,totalCount:t.data.envVarTotal||0,onSubmit:o=>e.submitInput(o),onSkip:()=>e.submitInput("")}),t.step==="Environment Setup"&&t.inputRequest?.id==="env_group"&&t.data.currentEnvGroup&&l(wr,{category:t.data.currentEnvGroup,currentIndex:t.data.envGroupIndex||0,totalGroups:t.data.envGroupTotal||0,onSubmit:o=>e.submitInput(o)}),t.step==="Environment Setup"&&t.inputRequest?.id==="env_alternatives"&&t.data.alternativeGroups&&l(Er,{alternatives:t.data.alternativeGroups,onSubmit:(o,n)=>e.submitInput({selectedGroups:o,values:n})}),t.step==="Environment Setup"&&!t.inputRequest&&l(ht,{status:t.status}),t.step==="Finished"&&l(ss,{setupMode:t.data.setupMode,portOverrides:t.data.portOverrides,onConfirm:()=>e.submitInput("exit")}),(t.step==="Install Tools"||t.step==="Project Setup")&&l(vr,{title:t.step==="Install Tools"?"Installing Tools":"Project Setup",phase:t.data.dependencyPhase||"",progress:t.data.dependencyProgress||0,isComplete:t.step==="Install Tools"?t.data.toolComplete||!1:t.data.dependencyComplete||!1,logs:t.data.dependencyLogs||[]}),t.error&&l(vt,{message:t.error.message})]})};import{Spinner as ls}from"@inkjs/ui";import{Box as N,Text as T,useInput as qo}from"ink";import{useEffect as Ho,useRef as us,useState as Vo}from"react";import{jsx as O,jsxs as b}from"react/jsx-runtime";var Tr=8,ps=({logs:e})=>{let[t,r]=Vo(0),o=us(e.length);Ho(()=>{e.length!==o.current&&(o.current=e.length,r(0))},[e.length]),qo((d,m)=>{m.upArrow?r(f=>Math.min(f+1,Math.max(0,e.length-Tr))):m.downArrow&&r(f=>Math.max(0,f-1))});let n=e.length,i=Math.max(0,n-Tr-t),a=Math.max(0,n-t),s=e.slice(i,a),c=i,u=t;return b(N,{flexDirection:"column",marginTop:1,marginLeft:1,children:[c>0&&b(T,{color:"gray",dimColor:!0,children:["\u2191 ",c," more line",c!==1?"s":""]}),O(N,{flexDirection:"column",height:Tr,overflow:"hidden",children:s.map((d,m)=>O(T,{color:"gray",wrap:"truncate",children:d},i+m))}),u>0?b(T,{color:"gray",dimColor:!0,children:["\u2193 ",u," more line",u!==1?"s":""]}):O(T,{color:"gray",dimColor:!0,children:"\u2191\u2193 scroll"})]})},Wo=({store:e})=>{let[t,r]=Vo(e.currentState);return Ho(()=>{let o=()=>r({...e.currentState});return e.on("change",o),()=>{e.off("change",o)}},[e]),qo((o,n)=>{(n.return||n.escape)&&(t.data.started||t.data.stopped||t.error)&&e.submitInput("exit")}),b(N,{flexDirection:"column",width:"100%",children:[O(Le,{}),(t.step==="Starting"||t.step==="Stopping")&&b(N,{flexDirection:"column",marginTop:1,paddingX:2,borderStyle:"round",borderColor:x,children:[O(ls,{label:t.status||"Working..."}),t.data.repoPath&&O(N,{marginTop:1,children:b(T,{color:"gray",children:["Repository: ",t.data.repoPath]})}),t.data.setupMode&&O(N,{children:b(T,{color:"gray",children:["Mode: ",t.data.setupMode]})}),t.data.dockerLogs&&t.data.dockerLogs.length>0&&O(ps,{logs:t.data.dockerLogs})]}),t.step==="Running"&&t.data.started&&b(N,{flexDirection:"column",marginTop:1,paddingX:2,paddingY:1,borderStyle:"round",borderColor:"green",children:[b(T,{color:"green",bold:!0,children:["\u2713"," GAIA is running!"]}),t.data.setupMode!=="developer"&&b(N,{marginTop:1,flexDirection:"column",children:[b(T,{children:["Web:"," ",b(T,{color:"cyan",bold:!0,children:["http://localhost:",t.data.webPort||3e3]})]}),b(T,{children:["API:"," ",b(T,{color:"cyan",bold:!0,children:["http://localhost:",t.data.apiPort||8e3]})]})]}),t.data.setupMode==="developer"&&b(N,{marginTop:1,flexDirection:"column",children:[b(N,{flexDirection:"column",children:[b(T,{children:["Web:"," ",b(T,{color:"cyan",bold:!0,children:["http://localhost:",t.data.webPort||3e3]})]}),b(T,{children:["API:"," ",b(T,{color:"cyan",bold:!0,children:["http://localhost:",t.data.apiPort||8e3]})]})]}),b(N,{marginTop:1,flexDirection:"column",children:[O(T,{color:"gray",children:"Use gaia dev / gaia dev full for foreground Nx TUI."}),b(T,{color:"gray",children:["Run ",O(T,{color:x,children:"gaia logs"})," to stream logs."]}),b(T,{color:"gray",children:["Run ",O(T,{color:x,children:"gaia stop"})," to shut down."]})]})]}),O(N,{marginTop:1,children:b(T,{dimColor:!0,children:[O(T,{bold:!0,children:"Enter"})," to exit"]})})]}),t.step==="Stopped"&&t.data.stopped&&b(N,{flexDirection:"column",marginTop:1,paddingX:2,paddingY:1,borderStyle:"round",borderColor:x,children:[b(T,{color:x,bold:!0,children:["\u2713"," ",t.status||"All GAIA services stopped."]}),t.data.stopMode==="force-ports"&&O(N,{marginTop:1,children:O(T,{color:"yellow",children:"Force-port cleanup was enabled and may have stopped non-GAIA listeners on app ports."})}),O(N,{marginTop:1,children:b(T,{dimColor:!0,children:[O(T,{bold:!0,children:"Enter"})," to exit"]})})]}),t.error&&b(N,{borderStyle:"single",borderColor:"red",padding:1,marginTop:2,children:[b(T,{color:"red",children:["Error: ",t.error.message]}),O(N,{marginTop:1,children:b(T,{dimColor:!0,children:[O(T,{bold:!0,children:"Enter"})," to exit"]})})]})]})};import{Spinner as ds}from"@inkjs/ui";import{Box as he,Text as X,useInput as Xo}from"ink";import{useEffect as ms,useState as fs}from"react";import{jsx as k,jsxs as z}from"react/jsx-runtime";var Yo=({store:e})=>{let[t,r]=fs(e.currentState);return ms(()=>{let o=()=>r({...e.currentState});return e.on("change",o),()=>{e.off("change",o)}},[e]),Xo((o,n)=>{(n.return||n.escape)&&t.error&&e.submitInput("exit")}),z(ft,{status:t.status,step:t.step,steps:$o,children:[t.step==="Detect Repo"&&z(he,{flexDirection:"column",paddingX:2,borderStyle:"round",borderColor:x,children:[k(X,{bold:!0,children:"Detecting GAIA Repository"}),k(he,{marginTop:1,children:k(ds,{label:"Searching for repository..."})}),t.data.repoPath&&k(he,{marginTop:1,children:z(X,{color:"green",children:["Found: ",t.data.repoPath]})})]}),t.step==="Prerequisites"&&t.data.checks&&k(gt,{checks:t.data.checks}),t.inputRequest?.id==="port_conflicts"&&t.data.portConflicts&&k(St,{portResults:t.data.portConflicts,onAccept:()=>e.submitInput("accept"),onAbort:()=>e.submitInput("abort")}),t.inputRequest?.id==="setup_mode"&&k(Sr,{onSelect:o=>e.submitInput(o)}),t.inputRequest?.id==="env_method"&&k(yr,{onSelect:o=>e.submitInput(o)}),t.inputRequest?.id==="env_infisical"&&k(xr,{onSubmit:o=>e.submitInput(o)}),t.step==="Environment Setup"&&t.inputRequest?.id==="env_var"&&t.data.currentEnvVar&&k(br,{categories:t.data.envCategories||[],currentVar:t.data.currentEnvVar,currentIndex:t.data.envVarIndex||0,totalCount:t.data.envVarTotal||0,onSubmit:o=>e.submitInput(o),onSkip:()=>e.submitInput("")}),t.step==="Environment Setup"&&t.inputRequest?.id==="env_group"&&t.data.currentEnvGroup&&k(wr,{category:t.data.currentEnvGroup,currentIndex:t.data.envGroupIndex||0,totalGroups:t.data.envGroupTotal||0,onSubmit:o=>e.submitInput(o)}),t.step==="Environment Setup"&&t.inputRequest?.id==="env_alternatives"&&t.data.alternativeGroups&&k(Er,{alternatives:t.data.alternativeGroups,onSubmit:(o,n)=>e.submitInput({selectedGroups:o,values:n})}),t.step==="Environment Setup"&&!t.inputRequest&&k(ht,{status:t.status}),t.step==="Project Setup"&&k(vr,{title:"Project Setup",phase:t.data.dependencyPhase||"",progress:t.data.dependencyProgress||0,isComplete:t.data.dependencyComplete||!1,logs:t.data.dependencyLogs||[]}),t.step==="Finished"&&k(gs,{setupMode:t.data.setupMode,portOverrides:t.data.portOverrides,onConfirm:()=>e.submitInput("exit")}),t.error&&k(vt,{message:t.error.message})]})},gs=({setupMode:e,portOverrides:t,onConfirm:r})=>{Xo((a,s)=>{s.return&&r()});let o=t?.[3e3]??3e3,n=t?.[8e3]??8e3,i=e==="selfhost";return z(he,{flexDirection:"column",marginTop:2,borderStyle:"round",borderColor:x,padding:1,children:[k(X,{color:x,bold:!0,children:"Setup Complete!"}),z(he,{marginTop:1,children:[k(X,{bold:!0,children:"Run: "}),k(X,{color:"cyan",children:i?"$ gaia start":"$ gaia dev"})]}),z(he,{marginTop:1,flexDirection:"column",children:[z(X,{children:["Web:"," ",z(X,{color:"cyan",bold:!0,children:["http://localhost:",o]})]}),z(X,{children:["API:"," ",z(X,{color:"cyan",bold:!0,children:["http://localhost:",n]})]})]}),k(he,{marginTop:1,children:k(X,{color:"gray",children:i?"gaia logs \xB7 gaia stop \xB7 gaia status \xB7 gaia setup":"gaia dev full \xB7 gaia logs \xB7 gaia stop \xB7 gaia status \xB7 gaia setup"})}),k(he,{marginTop:1,children:z(X,{dimColor:!0,children:[k(X,{bold:!0,children:"Enter"})," to exit"]})})]})};import{Spinner as hs}from"@inkjs/ui";import{Box as L,Text as _,useInput as vs}from"ink";import{useEffect as Ko,useState as Cr}from"react";import{jsx as C,jsxs as F}from"react/jsx-runtime";var Jo=({store:e})=>{let[t,r]=Cr(e.currentState),[o,n]=Cr(!1),[i,a]=Cr(null);return Ko(()=>{let s=()=>r({...e.currentState});return e.on("change",s),()=>{e.off("change",s)}},[e]),Ko(()=>{n(!1),a(new Date().toLocaleTimeString())},[t.data.services]),vs((s,c)=>{(c.return||c.escape)&&t.step==="Results"&&e.submitInput("exit"),s==="r"&&t.step==="Results"&&t.data.refreshable&&!o&&(n(!0),e.submitInput("refresh"))}),F(L,{flexDirection:"column",width:"100%",children:[C(Le,{}),t.step==="Checking"&&C(L,{marginTop:1,children:C(hs,{label:t.data.services?"Refreshing service health...":"Checking service health..."})}),t.step==="Results"&&t.data.services&&F(L,{flexDirection:"column",children:[F(L,{flexDirection:"column",borderStyle:"round",borderColor:x,paddingX:2,paddingY:1,children:[F(L,{justifyContent:"space-between",children:[C(_,{bold:!0,color:x,children:"GAIA Service Status"}),i&&F(_,{color:"gray",dimColor:!0,children:["checked ",i," \xB7 ",C(_,{bold:!0,children:"r"})," refresh"]})]}),F(L,{marginTop:1,flexDirection:"column",children:[F(L,{children:[C(L,{width:22,children:C(_,{bold:!0,children:"Service"})}),C(L,{width:10,children:C(_,{bold:!0,children:"Status"})}),C(L,{width:10,children:C(_,{bold:!0,children:"Latency"})})]}),C(_,{color:"gray",children:"\u2500".repeat(42)}),[...t.data.services].sort((s,c)=>s.status==="down"&&c.status!=="down"?-1:s.status!=="down"&&c.status==="down"?1:s.name.localeCompare(c.name)).map(s=>F(L,{children:[C(L,{width:22,children:F(_,{children:[s.name," (:",s.port,")"]})}),C(L,{width:10,children:C(_,{color:s.status==="up"?"green":"red",bold:!0,children:s.status==="up"?"\u2713 UP":"\u2717 DOWN"})}),C(L,{width:10,children:C(_,{color:"gray",children:s.latency?`${s.latency}ms`:"--"})})]},s.name))]})]}),t.data.docker&&F(L,{flexDirection:"column",borderStyle:"round",borderColor:"gray",paddingX:2,paddingY:1,marginTop:1,children:[C(_,{bold:!0,children:"Docker Containers"}),F(_,{color:"gray",children:["Docker:"," ",t.data.docker.running?C(_,{color:"green",children:"Running"}):C(_,{color:"red",children:"Not running"})]}),t.data.docker.containers?.length>0&&C(L,{marginTop:1,flexDirection:"column",children:t.data.docker.containers.map(s=>F(L,{children:[F(_,{color:s.status==="running"?"green":"red",children:[s.status==="running"?"\u2713":"\u2717"," "]}),C(_,{children:s.name}),s.health&&F(_,{color:"gray",children:[" (",s.health,")"]})]},s.name))})]}),C(L,{marginTop:1,children:F(_,{dimColor:!0,children:[C(_,{bold:!0,children:"Enter"})," exit \xB7 ",C(_,{bold:!0,children:"r"})," refresh"]})})]}),t.error&&C(L,{borderStyle:"single",borderColor:"red",padding:1,marginTop:2,children:F(_,{color:"red",children:["Error: ",t.error.message]})})]})};import{jsx as Y,jsxs as Ye}from"react/jsx-runtime";var ys=["init","setup","status","start","stop"],Ir=class extends Ss.Component{constructor(t){super(t),this.state={error:null}}static getDerivedStateFromError(t){return{error:t}}render(){return this.state.error?Ye(yt,{flexDirection:"column",padding:1,children:[Y(Te,{color:"red",bold:!0,children:"An unexpected error occurred:"}),Y(Te,{color:"red",children:this.state.error.message}),this.state.error.stack&&Y(yt,{marginTop:1,children:Y(Te,{color:"gray",dimColor:!0,children:this.state.error.stack})})]}):this.props.children}},xs=({store:e,command:t})=>{switch(t){case"init":return Y(Uo,{store:e});case"setup":return Y(Yo,{store:e});case"status":return Y(Jo,{store:e});case"start":case"stop":return Y(Wo,{store:e,command:t});default:return Ye(yt,{flexDirection:"column",padding:1,children:[Ye(Te,{color:"red",children:["Unknown command: ",t]}),Ye(yt,{marginTop:1,flexDirection:"column",children:[Y(Te,{bold:!0,children:"Available commands:"}),ys.map(r=>Ye(Te,{children:[" ",Y(Te,{color:"cyan",children:r})]},r))]})]})}},Qo=({store:e,command:t})=>Y(Ir,{children:Y(xs,{store:e,command:t})});import{EventEmitter as ws}from"events";var Es=150,Pr=class extends ws{state={step:"init",status:"",error:null,data:{},inputRequest:null};inputResolver=null;emitTimer=null;emitPending=!1;autoResolveInputs=new Map;setAutoResolve(t,r="exit"){this.autoResolveInputs.set(t,r)}get currentState(){return this.state}scheduleEmit(){this.emitPending=!0,this.emitTimer||(this.emitTimer=setTimeout(()=>{this.emitTimer=null,this.emitPending&&(this.emitPending=!1,this.emit("change",this.state))},Es))}emitNow(){this.emitTimer&&(clearTimeout(this.emitTimer),this.emitTimer=null),this.emitPending=!1,this.emit("change",this.state)}setStep(t){this.state.step=t,this.emitNow()}setStatus(t){this.state.status=t,this.scheduleEmit()}setError(t){this.state.error=t,t!==null&&this.inputResolver&&(this.inputResolver(null),this.inputResolver=null,this.state.inputRequest=null),this.emitNow()}updateData(t,r){this.state.data={...this.state.data,[t]:r},this.scheduleEmit()}waitForInput(t,r,o){return this.autoResolveInputs.has(t)?(this.state.inputRequest=null,this.emitNow(),Promise.resolve(this.autoResolveInputs.get(t))):(this.state.inputRequest={id:t,meta:r},this.emitNow(),new Promise(n=>{if(this.inputResolver=n,o!=null){let i=setTimeout(()=>{this.inputResolver&&(this.inputResolver=null,this.state.inputRequest=null,this.emitNow(),n(null))},o),a=this.inputResolver;this.inputResolver=s=>{clearTimeout(i),a(s)}}}))}submitInput(t){this.inputResolver&&(this.inputResolver(t),this.inputResolver=null,this.state.inputRequest=null,this.emitNow())}},zo=()=>new Pr;function Rr(){return process.stdin.isTTY===!0&&process.stdout.isTTY===!0}function Zo(e){if(Rr())return;let t=e?`'gaia ${e}'`:"this command";console.error(`Error: ${t} needs an interactive terminal (TTY) to prompt for input.`),console.error("Re-run it from a regular shell session \u2014 not a pipe, redirect, or non-TTY environment."),process.exit(1)}function en(e){let t="",r="",o="";e.on("change",n=>{n.step&&n.step!==t&&(t=n.step,console.info(`
40
+ [${n.step}]`)),n.status&&n.status!==r&&(r=n.status,console.info(` ${n.status}`)),n.error&&n.error.message!==o&&(o=n.error.message,console.error(` Error: ${n.error.message}`))})}var Cs=50,Is=130;async function re(e){let t=zo();if(e.whenNonInteractive==="fail"){Zo(e.command),await tn(t,e);return}Rr()?await tn(t,e):await Ps(t,e)}async function Ps(e,t){en(e);for(let[r,o]of t.autoResolve??[])e.setAutoResolve(r,o);try{await t.runFlow(e),t.onPlainComplete?.(e)}catch(r){e.setError(r)}rn(e)}async function tn(e,t){let{unmount:r}=bs(Ts.createElement(Qo,{store:e,command:t.command})),o=()=>{r(),process.exit(Is)};process.once("SIGINT",o),process.once("SIGTERM",o),await new Promise(n=>setTimeout(n,Cs));try{await t.runFlow(e)}catch(n){e.setError(n)}finally{process.off("SIGINT",o),process.off("SIGTERM",o)}e.currentState.error&&await e.waitForInput("exit"),r(),rn(e)}function rn(e){let t=e.currentState.error?1:0,r=[process.stdout,process.stderr].filter(n=>n.writableLength>0);r.length===0&&process.exit(t);let o=r.length;for(let n of r)n.once("drain",()=>{o-=1,o===0&&process.exit(t)})}import*as ce from"fs";import*as pn from"os";import*as Se from"path";import*as on from"path";var Rs=e=>new Promise(t=>setTimeout(t,e));async function xt(e){e.setStep("Setup Mode"),e.setStatus("Choose how to run GAIA...");let t=await e.waitForInput("setup_mode");return e.updateData("setupMode",t),t}async function wt(e,t,r,o){e.setStep("Environment Setup"),e.setStatus("Configuring environment..."),e.updateData("setupMode",r),e.setStatus("Configuring environment variables...");let n=await e.waitForInput("env_method");e.updateData("envMethod",n);let i={};i.ENV="development";let a=pr();for(let c of a){let u=ur(c,r);u&&(i[c]=u)}let s=Co(r);for(let[c,u]of Object.entries(s))i[c]=u;if(n==="infisical")await ks(e,i),e.setStatus("Infisical credentials saved. Ensure your Infisical project contains all required variables.");else try{await _s(e,t,i,r)}catch(c){e.setError(c);return}o&&bo(i,o,r);try{await Ds(e,t,i,r,o)}catch(c){e.setError(c);return}await Rs(1e3)}async function ks(e,t){e.setStatus("Configuring Infisical...");let r=await e.waitForInput("env_infisical");t.INFISICAL_PROJECT_ID=r.INFISICAL_PROJECT_ID,t.INFISICAL_MACHINE_IDENTITY_CLIENT_ID=r.INFISICAL_MACHINE_IDENTITY_CLIENT_ID,t.INFISICAL_MACHINE_IDENTITY_CLIENT_SECRET=r.INFISICAL_MACHINE_IDENTITY_CLIENT_SECRET}async function _s(e,t,r,o){e.setStatus("Parsing environment variables...");let n;try{n=await xo(t),n=To(n,o)}catch(v){throw o==="selfhost"?new Error(`Manual environment setup requires Python to parse config schema.
35
41
  For self-host mode, we recommend using Infisical for secret management.
36
42
  Alternatively, install Python 3.11+ and try again.
37
43
 
38
- Original error: ${v.message}`):new Error(`Failed to parse settings: ${v.message}`)}let i=new Set,a=[],s=new Set;for(let v of n)if(v.alternativeGroup&&!s.has(v.name)){let y=n.find(w=>w.name===v.alternativeGroup);y&&(a.push([v,y]),i.add(v.name),i.add(y.name),s.add(v.name),s.add(y.name))}let c=n.filter(v=>v.variables.length===1&&!i.has(v.name)),p=n.filter(v=>v.variables.length>1&&!i.has(v.name));for(let v of a){e.updateData("alternativeGroups",v),e.setStatus("Choose an AI provider...");let y=await e.waitForInput("env_alternatives");for(let[w,b]of Object.entries(y.values))b&&(r[w]=b)}let f=At(),m=[...c.flatMap(v=>v.variables).filter(v=>!f.includes(v.name))].sort((v,y)=>v.required&&!y.required?-1:!v.required&&y.required?1:0);e.updateData("envVarTotal",m.length);for(let v=0;v<m.length;v++){let y=m[v];if(!y)continue;e.updateData("currentEnvVar",y),e.updateData("envVarIndex",v),e.setStatus(`Configuring ${y.name}...`);let w=await e.waitForInput("env_var",{varName:y.name});(w||y.required||y.defaultValue)&&(r[y.name]=w||y.defaultValue||"")}let S=[...p].filter(v=>!v.variables.every(y=>f.includes(y.name))).sort((v,y)=>{let w=v.variables.some(E=>E.required),b=y.variables.some(E=>E.required);return w&&!b?-1:!w&&b?1:0});e.updateData("envGroupTotal",S.length);for(let v=0;v<S.length;v++){let y=S[v];if(!y)continue;e.updateData("currentEnvGroup",y),e.updateData("envGroupIndex",v),e.setStatus(`Configuring ${y.name}...`);let w=await e.waitForInput("env_group",{groupName:y.name});for(let[b,E]of Object.entries(w)){let P=y.variables.find(Z=>Z.name===b);(E||P?.required||P?.defaultValue)&&(r[b]=E||P?.defaultValue||"")}}}async function bi(e,t,r,o,n){e.setStatus("Writing API environment file...");try{let a=xo.join(t,"apps","api");Ur(a,r),e.setStatus("API environment variables configured!")}catch(a){throw new Error(`Failed to write API .env file: ${a.message}`)}e.setStatus("Writing web environment file...");try{Hr(t,o,n),e.setStatus("Web environment variables configured!")}catch(a){throw new Error(`Failed to write web .env file: ${a.message}`)}let i=n&&Object.keys(n).length>0;if(i||o==="selfhost"){e.setStatus("Writing Docker Compose environment...");try{i&&Yr(t),Vr(t,n??{},o),e.setStatus("Docker Compose environment configured!")}catch(a){throw new Error(`Failed to write Docker Compose .env: ${a.message}`)}}}import{execa as oe}from"execa";var pe={git:"https://git-scm.com/downloads",docker:"https://docs.docker.com/get-docker/",mise:"https://mise.jdx.dev/getting-started.html"},Ti={8e3:"API Server",5432:"PostgreSQL",6379:"Redis",27017:"MongoDB",5672:"RabbitMQ",3e3:"Web Frontend",8080:"ChromaDB",8083:"Mongo Express"};async function wo(){try{return await oe("git",["--version"]),"success"}catch{return"error"}}async function ut(){let e=!1,t=!1,r;try{await oe("docker",["--version"]),e=!0}catch{return{name:"Docker",installUrl:pe.docker,installed:!1,working:!1,errorMessage:"Docker is not installed"}}try{await oe("docker",["info"],{timeout:5e3}),t=!0}catch{r="Docker is installed but the daemon is not running. Please start Docker Desktop or the Docker daemon."}return{name:"Docker",installUrl:pe.docker,installed:e,working:t,errorMessage:r}}async function bo(){try{return await oe("mise",["--version"]),"success"}catch{return"missing"}}async function To(){if((await import("node:os")).platform()==="win32")try{return await oe("powershell",["-Command","irm https://mise.jdx.dev/install.ps1 | iex"]),!0}catch{return!1}try{return await oe("sh",["-c","curl https://mise.jdx.dev/install.sh | sh"]),!0}catch{return!1}}async function Co(e){let t=await import("node:net"),r=[],o=n=>new Promise(i=>{let a=t.createServer();a.once("error",()=>i(!1)),a.once("listening",()=>{a.close(()=>i(!0))}),a.listen(n)});for(let n of e){let i=Ti[n]||`Port ${n}`;if(await o(n))r.push({port:n,service:i,available:!0});else{let s=await Ci(n),c=await Ii(n+1,n+100,o);r.push({port:n,service:i,available:!1,usedBy:s,alternative:c||void 0})}}return r}async function Ci(e){if((await import("node:os")).platform()==="win32"){try{let{stdout:o}=await oe("netstat",["-ano","-p","TCP"]),n=o.trim().split(`
39
- `);for(let i of n)if(i.includes(`:${e}`)&&i.includes("LISTENING")){let a=i.trim().split(/\s+/),s=a[a.length-1];if(s)try{let{stdout:c}=await oe("tasklist",["/FI",`PID eq ${s}`,"/FO","CSV","/NH"]);return c.trim().split(",")[0]?.replace(/"/g,"")||`PID ${s}`}catch{return`PID ${s}`}}}catch{}return}try{let{stdout:o}=await oe("lsof",["-i",`:${e}`,"-sTCP:LISTEN","-P","-n"]),n=o.trim().split(`
40
- `);if(n.length>1)return n[1]?.split(/\s+/)?.[0]||void 0}catch{}}async function Ii(e,t,r){for(let o=e;o<=t;o++)if(await r(o))return o;return null}var X=e=>new Promise(t=>setTimeout(t,e)),dt=(e,t="dependencyLogs")=>r=>{let o=e.currentState.data[t]||[],n=r.split(`
41
- `).filter(i=>i.trim()!=="");e.updateData(t,[...o,...n].slice(-30))};async function mt(e){e.updateData("checks",{git:"pending",docker:"pending"}),await X(500);let t=await wo();e.updateData("checks",{...e.currentState.data.checks,git:t});let r=await ut(),o=r.working?"success":"error";e.updateData("checks",{...e.currentState.data.checks,docker:o}),r.working||e.updateData("dockerError",r.errorMessage);let n=[];if(t==="error"&&n.push({name:"Git"}),o==="error"&&n.push({name:"Docker",message:r.errorMessage}),n.length>0){let i=["Prerequisites failed:"];for(let a of n)i.push(` \u2022 ${a.name}: ${a.message||"Not installed or not working"}`);return i.push(`
42
- Installation guides:`),t==="error"&&i.push(` \u2022 Git: ${pe.git}`),o==="error"&&(r.installed?i.push(" \u2022 Docker: Start Docker Desktop or run 'sudo systemctl start docker'"):i.push(` \u2022 Docker: ${pe.docker}`)),e.setError(new Error(i.join(`
43
- `))),null}return{gitStatus:t,dockerStatus:o,dockerInfo:r}}async function ft(e){e.updateData("checks",{...e.currentState.data.checks,mise:"pending"});let t=await bo();return e.updateData("checks",{...e.currentState.data.checks,mise:t}),t==="missing"&&(e.setStatus("Installing Mise..."),t=await To()?"success":"error",e.updateData("checks",{...e.currentState.data.checks,mise:t})),t==="error"?(e.setError(new Error(`Developer mode requires Mise but it failed to install.
44
- \u2022 Mise: ${pe.mise}`)),null):"success"}async function gt(e){e.setStatus("Checking Ports...");let r=await Co([8e3,5432,6379,27017,5672,3e3,8080,8083]),o={},n=r.filter(i=>!i.available);if(n.length>0){let i=n.filter(s=>!s.alternative);if(i.length>0)return e.setError(new Error(`Cannot find free alternative ports for: ${i.map(s=>`${s.port} (${s.service})`).join(", ")}. Free these ports and try again.`)),null;if(e.updateData("portConflicts",r),await e.waitForInput("port_conflicts")==="abort")return e.setError(new Error("Port conflicts not resolved. Please free the ports and try again.")),null;for(let s of r)!s.available&&s.alternative&&(o[s.port]=s.alternative)}return e.updateData("portOverrides",o),e.setStatus("Prerequisites check complete!"),await X(1e3),o}async function Io(e,t,r,o){e.setStep("Project Setup"),e.updateData("dependencyPhase","Setting up project..."),e.updateData("dependencyProgress",0),e.updateData("dependencyComplete",!1),e.updateData("dependencyLogs",[]);try{e.updateData("dependencyPhase","Trusting mise configuration..."),await U("mise",["trust"],t,void 0,o),e.updateData("dependencyProgress",20),e.updateData("dependencyPhase","Installing tools..."),await U("mise",["install"],t,i=>{e.updateData("dependencyProgress",20+i*.3)},o),e.updateData("dependencyPhase","Running mise setup...");let n=Object.keys(r).length>0?se(r):void 0;return await U("mise",["setup"],t,i=>{e.updateData("dependencyProgress",50+i*.5)},o,n),e.updateData("dependencyProgress",100),e.updateData("dependencyPhase","Setup complete!"),e.updateData("dependencyComplete",!0),!0}catch(n){return e.setError(new Error(`Failed to setup project: ${n.message}`)),!1}}import{execa as Pi}from"execa";import ht from"fs";import Ri from"simple-git";async function Eo(e,t,r,o){if(ht.existsSync(e)){let n=`${e}/.git`;if(!ht.existsSync(n))throw new Error(`Directory ${e} exists but is not a git repository`);await Ri().cwd(e).pull(),r(100,"Already exists, pulled latest")}else try{let n=["clone","--progress"];o&&n.push("--branch",o),n.push(t,e);let i=Pi("git",n);i.stderr?.on("data",a=>{let s=a.toString();s.includes("Counting objects")?r(5,"Counting objects"):s.includes("Compressing objects")&&r(10,"Compressing objects");let c=s.match(/Receiving objects:\s+(\d+)%\s+\((\d+)\/(\d+)\)/);if(c?.[1]){let f=Math.min(100,parseInt(c[1],10)),d=c[2],m=c[3];r(10+Math.floor(f*.5),`Receiving objects: ${d}/${m}`)}let p=s.match(/Resolving deltas:\s+(\d+)%\s+\((\d+)\/(\d+)\)/);if(p?.[1]){let f=Math.min(100,parseInt(p[1],10)),d=p[2],m=p[3];r(60+Math.floor(f*.4),`Resolving deltas: ${d}/${m}`)}}),await i,r(100,"Clone complete")}catch(n){throw ht.existsSync(e)&&ht.rmSync(e,{recursive:!0,force:!0}),n}}var ki=process.env.GAIA_CLI_DEV==="true",_i=new RegExp("\x1B\\[[0-9;]*m","g");async function Ro(e,t){e.setStep("Welcome"),e.setStatus("Waiting for user input..."),await e.waitForInput("welcome");let r=dt(e);if(e.setStep("Prerequisites"),e.setStatus("Checking system requirements..."),!await mt(e))return;let o=await gt(e);if(o===null)return;let n=await lt(e);if(n==="developer"&&!await ft(e))return;let i="";if(ki){if(i=$()||"",!i){e.setError(new Error("DEV_MODE: Could not find workspace root. Run from within the gaia repo."));return}e.setStep("Repository Setup"),e.setStatus("[DEV MODE] Using current workspace..."),await X(500),e.setStatus("Repository ready!")}else{e.setStep("Repository Setup");let s=n==="selfhost"?ue.join(Po.homedir(),"gaia"):ue.resolve("gaia"),c=!0;for(i=s;;){if(i=await e.waitForInput("repo_path",{default:s}),ue.isAbsolute(i)||(i=ue.resolve(i)),ne.existsSync(i)){if(!ne.statSync(i).isDirectory()){e.setError(new Error(`Path ${i} exists and is not a directory.`)),await X(2e3),e.setError(null);continue}if(ne.existsSync(ue.join(i,"apps/api/app/config/settings_validator.py"))){e.updateData("existingRepoPath",i);let m=await e.waitForInput("existing_repo");if(m==="use_existing"){c=!1;break}else if(m==="delete_reclone"){e.setStatus("Removing existing installation...");try{ne.rmSync(i,{recursive:!0,force:!0})}catch(S){e.setError(new Error(`Failed to remove directory: ${S.message}
45
- Try removing it manually: rm -rf "${i}"`));return}break}else{if(m==="different_path")continue;e.setError(new Error("Setup cancelled by user."));return}}if(ne.readdirSync(i).length>0){e.setError(new Error(`Directory ${i} is not empty and is not a GAIA installation. Please choose another path.`)),await X(2e3),e.setError(null);continue}}break}if(c){e.setStep("Repository Setup"),e.setStatus("Preparing repository..."),e.updateData("repoProgress",0),e.updateData("repoPhase","");try{await Eo(i,"https://github.com/theexperiencecompany/gaia.git",(p,f)=>{e.updateData("repoProgress",p),f?(e.updateData("repoPhase",f),e.setStatus(`${f}...`)):e.setStatus(`Cloning repository to ${i}... ${p}%`)},t),e.setStatus("Repository ready!")}catch(p){e.setError(p);return}}else e.setStatus("Using existing repository!")}if(await X(1e3),await pt(e,i,n,o),e.currentState.error)return;if(n==="selfhost"){e.setStep("Project Setup"),e.setStatus("Building and starting all services in Docker..."),e.updateData("dependencyPhase","Building and starting Docker services..."),e.updateData("dependencyProgress",0),e.updateData("dependencyLogs",[]),e.updateData("dependencyComplete",!1);let s=f=>{let d=f.split(`
46
- `).map(S=>S.replace(_i,"").trim()).filter(S=>S.length>0);if(d.length===0)return;let m=e.currentState.data.dependencyLogs||[];e.updateData("dependencyLogs",[...m,...d].slice(-30))},c=!1;try{e.setStatus("Pulling pre-built images from registry..."),await Oe(i,"selfhost",f=>e.setStatus(f),o,s,{pull:!0}),c=!0}catch(f){let d=f.message?.split(`
47
- `)[0]??"unknown error";e.setStatus(`Registry pull failed (${d}) \u2014 building images locally (this takes a few minutes)...`)}if(!c)try{await Oe(i,"selfhost",f=>e.setStatus(f),o,s,{build:!0})}catch(f){e.setError(new Error(`Failed to start services: ${f.message}`));return}e.updateData("dependencyProgress",100),e.updateData("dependencyComplete",!0);let p=e.currentState.data.envMethod||"manual";ze({version:ee,setupComplete:!0,setupMethod:p,repoPath:i,createdAt:new Date().toISOString(),updatedAt:new Date().toISOString()}),e.updateData("setupMode",n),e.setStep("Finished"),e.setStatus("Setup complete! GAIA is running."),await e.waitForInput("exit");return}e.setStep("Install Tools"),e.setStatus("Installing toolchain..."),e.updateData("dependencyPhase","Initializing mise..."),e.updateData("dependencyProgress",0),e.updateData("dependencyLogs",[]);try{e.updateData("dependencyPhase","Trusting mise configuration..."),await U("mise",["trust"],i,void 0,r),e.updateData("dependencyProgress",50),e.updateData("dependencyPhase","Installing tools (node, python, uv, nx)..."),await U("mise",["install"],i,s=>{e.updateData("dependencyProgress",50+s*.5)},r),e.updateData("dependencyProgress",100),e.updateData("toolComplete",!0)}catch(s){e.setError(new Error(`Failed to install tools: ${s.message}`));return}await X(1e3),e.setStep("Project Setup"),e.updateData("dependencyPhase","Setting up project..."),e.updateData("dependencyProgress",0),e.updateData("dependencyComplete",!1),e.updateData("repoPath",i),e.updateData("dependencyLogs",[]);try{e.updateData("dependencyProgress",0),e.updateData("dependencyPhase","Running mise setup (all dependencies)...");let s=Object.keys(o).length>0?se(o):void 0;await U("mise",["setup"],i,c=>{e.updateData("dependencyProgress",c)},r,s),e.updateData("dependencyProgress",100),e.updateData("dependencyPhase","Setup complete!"),e.updateData("dependencyComplete",!0)}catch(s){e.setError(new Error(`Failed to setup project: ${s.message}`));return}await X(1e3);let a=e.currentState.data.envMethod||"manual";ze({version:ee,setupComplete:!0,setupMethod:a,repoPath:i,createdAt:new Date().toISOString(),updatedAt:new Date().toISOString()}),e.setStep("Finished"),e.setStatus("Setup complete! Run 'gaia dev' to start development mode."),await e.waitForInput("exit")}async function Do(e={}){await z({command:"init",whenNonInteractive:"fail",runFlow:t=>Ro(t,e.branch)})}async function ko(e){e.setStep("Detect Repo"),e.setStatus("Looking for GAIA repository...");let t=$();if(!t){e.setError(new Error("Could not find GAIA repository. Run this command from within a cloned gaia repo, or use 'gaia init' to set up from scratch."));return}if(e.updateData("repoPath",t),e.setStatus(`Found repository at ${t}`),await X(1e3),e.setStep("Prerequisites"),e.setStatus("Checking system requirements..."),!await mt(e))return;let r=await gt(e);if(r===null)return;let o=await lt(e);if(o==="developer"&&!await ft(e)||(await pt(e,t,o,r),e.currentState.error))return;if(o==="selfhost"){let s=e.currentState.data.envMethod||"manual";Ae({setupComplete:!0,setupMethod:s,repoPath:t}),e.updateData("setupMode",o),e.setStep("Finished"),e.setStatus("Setup complete! Run 'gaia start' to build and start all services in Docker."),await e.waitForInput("exit");return}let n=dt(e);if(!await Io(e,t,r,n))return;await X(1e3);let a=e.currentState.data.envMethod||"manual";Ae({setupComplete:!0,setupMethod:a,repoPath:t}),e.updateData("setupMode",o),e.setStep("Finished"),e.setStatus("Setup complete! Run 'gaia dev' to start development mode."),await e.waitForInput("exit")}async function _o(){await z({command:"setup",whenNonInteractive:"fail",runFlow:ko})}var Ai=new RegExp("\x1B\\[[0-9;]*m","g");async function Ao(e,t){e.setStep("Starting"),e.setStatus("Locating GAIA repository...");let r=$();if(!r){e.setError(new Error("Could not find GAIA repository. Run from within a cloned gaia repo."));return}e.updateData("repoPath",r);let o=await ge(r);if(!o){e.setError(new Error("No .env file found. Run 'gaia init' for fresh setup, or 'gaia setup' to configure an existing repo."));return}if(o==="developer"){e.setError(new Error("Developer mode runs in foreground. Use 'gaia dev' or 'gaia dev full' instead of 'gaia start'."));return}if(o==="selfhost"){e.setStatus("Checking Docker...");let c=await ut();if(!c.working){e.setError(new Error(c.errorMessage||`Docker is not running. Please start Docker and try again.
48
- ${pe.docker}`));return}}let n=ae(r),i=n[3e3]??3e3,a=n[8e3]??8e3;e.updateData("setupMode",o),e.updateData("webPort",i),e.updateData("apiPort",a),e.updateData("dockerLogs",[]),e.setStatus(`Starting GAIA in ${o} mode...`);let s=c=>{let p=c.split(`
49
- `).map(d=>d.replace(Ai,"").trim()).filter(d=>d.length>0);if(p.length===0)return;let f=e.currentState.data.dockerLogs||[];e.updateData("dockerLogs",[...f,...p].slice(-30))};try{await Oe(r,o,c=>{e.setStatus(c)},n,s,t),e.setStep("Running"),e.setStatus("GAIA is running!"),e.updateData("started",!0)}catch(c){e.setError(new Error(`Failed to start services: ${c.message}`));return}await e.waitForInput("exit")}async function Oo(e){await z({command:"start",whenNonInteractive:"plain",autoResolve:[["exit"]],runFlow:t=>Ao(t,e)})}import{execa as Qt}from"execa";var Kt=["gaia-backend","gaia-web","chromadb","postgres","redis","mongo","rabbitmq","arq_worker"];async function Mo(){try{let{stdout:e}=await Qt("docker",["inspect","--format","{{.Name}}|{{.State.Status}}|{{if .State.Health}}{{.State.Health.Status}}{{else}}none{{end}}",...Kt]),t=new Map;for(let r of e.trim().split(`
50
- `)){if(!r)continue;let[o,n,i]=r.split("|"),a=o?.replace(/^\//,"")??"";t.set(a,{name:a,status:n==="running"?"running":"stopped",health:i!=="none"?i:void 0})}return Kt.map(r=>t.get(r)??{name:r,status:"not_found"})}catch{let e=Kt.map(async t=>{try{let{stdout:r}=await Qt("docker",["inspect","--format","{{.State.Status}}|{{if .State.Health}}{{.State.Health.Status}}{{else}}none{{end}}",t]),[o,n]=r.trim().split("|");return{name:t,status:o==="running"?"running":"stopped",health:n!=="none"?n:void 0}}catch{return{name:t,status:"not_found"}}});return Promise.all(e)}}async function No(){try{return await Qt("docker",["info"]),!0}catch{return!1}}var Oi=[{name:"API",port:8e3,type:"http",path:"/health"},{name:"Web",port:3e3,type:"http",path:"/"},{name:"PostgreSQL",port:5432,type:"tcp"},{name:"Redis",port:6379,type:"tcp"},{name:"MongoDB",port:27017,type:"tcp"},{name:"RabbitMQ",port:5672,type:"tcp"},{name:"ChromaDB",port:8080,type:"tcp"}];async function Lo(e){let r=Oi.map(o=>({...o,port:e?.[o.port]??o.port})).map(o=>o.type==="http"?Mi(o.name,o.port,o.path):Ni(o.name,o.port));return Promise.all(r)}async function Mi(e,t,r){let o=Date.now();try{let n=await fetch(`http://localhost:${t}${r}`,{signal:AbortSignal.timeout(5e3)}),i=Date.now()-o;return{name:e,port:t,status:n.ok?"up":"down",latency:i,details:n.ok?`HTTP ${n.status}`:`HTTP ${n.status} (error)`}}catch{return{name:e,port:t,status:"down",details:"Connection failed"}}}async function Ni(e,t){let r=await import("node:net"),o=Date.now();return new Promise(n=>{let i=new r.Socket;i.setTimeout(3e3),i.on("connect",()=>{let a=Date.now()-o;i.destroy(),n({name:e,port:t,status:"up",latency:a})}),i.on("timeout",()=>{i.destroy(),n({name:e,port:t,status:"down"})}),i.on("error",()=>{i.destroy(),n({name:e,port:t,status:"down"})}),i.connect(t,"localhost")})}async function Bo(){return await No()?{running:!0,containers:await Mo()}:{running:!1,containers:[]}}async function Li(e){e.setStep("Checking"),e.setStatus("Checking service health..."),e.updateData("refreshable",!1);let t=$(),r=t?ae(t):void 0,[o,n]=await Promise.all([Lo(r),Bo()]);e.updateData("services",o),e.updateData("docker",n);let i=o.filter(s=>s.status==="up").length,a=o.length;e.setStep("Results"),e.setStatus(`${i}/${a} services running`),e.updateData("refreshable",!0)}async function Fo(e){for(;await Li(e),await e.waitForInput("exit_or_refresh")==="refresh";);}async function $o(){await z({command:"status",whenNonInteractive:"plain",autoResolve:[["exit_or_refresh","exit"]],runFlow:Fo,onPlainComplete:Bi})}function Bi(e){let t=e.currentState.data.services??[],r=e.currentState.data.docker;$i(t),Gi(r)}function Fi(e){return e==="up"?"UP":e==="down"?"DOWN":"UNKNOWN"}function $i(e){if(e.length!==0){console.log(`
51
- Services:`);for(let t of e){let r=Fi(t.status),o=t.latency===void 0?"--":`${t.latency}ms`,n=t.name.padEnd(12);console.log(` ${n} :${t.port} ${r} ${o}`)}}}function Gi(e){if(e){console.log(`
52
- Docker: ${e.running?"running":"not running"}`);for(let t of e.containers??[]){let r=t.health?` (${t.health})`:"",o=t.name.padEnd(14);console.log(` ${o} ${t.status}${r}`)}}}async function Go(e,t){e.setStep("Stopping"),e.setStatus("Locating GAIA repository...");let r=$();if(!r){e.setError(new Error("Could not find GAIA repository. Run from within a cloned gaia repo."));return}e.updateData("repoPath",r),e.updateData("stopMode",t?.forcePorts?"force-ports":"safe");let o=ae(r);try{await Kr(r,n=>{e.setStatus(n)},o,t),e.setStep("Stopped"),e.setStatus(t?.forcePorts?"All services stopped (force-port mode).":"All services stopped (safe mode)."),e.updateData("stopped",!0)}catch(n){e.setError(new Error(`Failed to stop services: ${n.message}`));return}await e.waitForInput("exit")}async function jo(e){await z({command:"stop",whenNonInteractive:"plain",autoResolve:[["exit"]],runFlow:t=>Go(t,e)})}import*as vt from"fs";import*as St from"path";function ji(e){let t=St.join(e,".env");return vt.existsSync(t)?["--env-file",".env"]:[]}async function qo(){let e=$();if(!e)throw new Error("Could not find GAIA repository. Run from within a cloned gaia repo.");let t=await ge(e);if(!t)throw new Error("No .env file found. Run 'gaia init' for fresh setup, or 'gaia setup' to configure an existing repo.");let r=St.join(e,"infra","docker"),o=ji(r),n=ae(e),i=Object.keys(n).length>0?se(n):void 0;if(t==="selfhost"){await Te("docker",["compose","-f","docker-compose.selfhost.yml",...o,"logs","-f","--tail","200"],r,i);return}let a=["compose",...o,"logs","-f","--tail","200"],s=St.join(e,Xr),c=Mt(e),p=typeof c=="number"&&Ze(c);if(vt.existsSync(s)&&p){console.log("Streaming app and infrastructure logs..."),process.platform==="win32"?await Qe([{cmd:"powershell",args:["-Command",`Get-Content -Path '${s.replace(/'/g,"''")}' -Wait -Tail 200`],cwd:e},{cmd:"docker",args:a,cwd:r,env:i}]):await Qe([{cmd:"tail",args:["-n","200","-f",s],cwd:e},{cmd:"docker",args:a,cwd:r,env:i}]);return}vt.existsSync(s)&&!p?(console.log("Detected stale developer app logs from a previous run. Streaming Docker logs only."),await Te("docker",a,r,i)):(console.log("No active developer process detected. Streaming Docker service logs. Run `gaia dev` in another terminal for live Nx app logs."),await Te("docker",a,r,i))}var Q=new qi;Q.name("gaia").description("CLI tool for setting up and managing GAIA").version(ee);Q.addCommand(te);Q.command("init").description(ie.init).option("--branch <branch>","Git branch to clone").action(async e=>{await Do({branch:e.branch})});Q.command("setup").description(ie.setup).action(async()=>{await _o()});Q.command("status").description(ie.status).action(async()=>{await $o()});Q.command("start").description(ie.start).option("-b, --build","Rebuild Docker images before starting").option("--pull","Pull latest base images before starting").action(async e=>{await Oo({build:e.build,pull:e.pull})});Q.command("dev [profile]").description(ie.dev).action(async e=>{try{await zr(e)}catch(t){console.error(t instanceof Error?t.message:String(t)),process.exit(1)}});Q.command("logs").description(ie.logs).action(async()=>{try{await qo()}catch(e){console.error(e instanceof Error?e.message:String(e)),process.exit(1)}});Q.command("stop").description(ie.stop).option("--force-ports","Aggressively stop processes listening on API/Web ports (may affect non-GAIA processes)").action(async e=>{await jo({forcePorts:e.forcePorts})});process.argv.slice(2).length||(Q.outputHelp(),process.exit(0));Q.parse();
44
+ Original error: ${v.message}`):new Error(`Failed to parse settings: ${v.message}`)}let i=new Set,a=[],s=new Set;for(let v of n)if(v.alternativeGroup&&!s.has(v.name)){let y=n.find(w=>w.name===v.alternativeGroup);y&&(a.push([v,y]),i.add(v.name),i.add(y.name),s.add(v.name),s.add(y.name))}let c=n.filter(v=>v.variables.length===1&&!i.has(v.name)),u=n.filter(v=>v.variables.length>1&&!i.has(v.name));for(let v of a){e.updateData("alternativeGroups",v),e.setStatus("Choose an AI provider...");let y=await e.waitForInput("env_alternatives");for(let[w,E]of Object.entries(y.values))E&&(r[w]=E)}let d=pr(),f=[...c.flatMap(v=>v.variables).filter(v=>!d.includes(v.name))].sort((v,y)=>v.required&&!y.required?-1:!v.required&&y.required?1:0);e.updateData("envVarTotal",f.length);for(let v=0;v<f.length;v++){let y=f[v];if(!y)continue;e.updateData("currentEnvVar",y),e.updateData("envVarIndex",v),e.setStatus(`Configuring ${y.name}...`);let w=await e.waitForInput("env_var",{varName:y.name});(w||y.required||y.defaultValue)&&(r[y.name]=w||y.defaultValue||"")}let S=[...u].filter(v=>!v.variables.every(y=>d.includes(y.name))).sort((v,y)=>{let w=v.variables.some(I=>I.required),E=y.variables.some(I=>I.required);return w&&!E?-1:!w&&E?1:0});e.updateData("envGroupTotal",S.length);for(let v=0;v<S.length;v++){let y=S[v];if(!y)continue;e.updateData("currentEnvGroup",y),e.updateData("envGroupIndex",v),e.setStatus(`Configuring ${y.name}...`);let w=await e.waitForInput("env_group",{groupName:y.name});for(let[E,I]of Object.entries(w)){let P=y.variables.find(oe=>oe.name===E);(I||P?.required||P?.defaultValue)&&(r[E]=I||P?.defaultValue||"")}}}async function Ds(e,t,r,o,n){e.setStatus("Writing API environment file...");try{let a=on.join(t,"apps","api");Po(a,r),e.setStatus("API environment variables configured!")}catch(a){throw new Error(`Failed to write API .env file: ${a.message}`)}e.setStatus("Writing web environment file...");try{Ro(t,o,n),e.setStatus("Web environment variables configured!")}catch(a){throw new Error(`Failed to write web .env file: ${a.message}`)}let i=n&&Object.keys(n).length>0;if(i||o==="selfhost"){e.setStatus("Writing Docker Compose environment...");try{i&&Do(t),_o(t,n??{},o),e.setStatus("Docker Compose environment configured!")}catch(a){throw new Error(`Failed to write Docker Compose .env: ${a.message}`)}}}import{execa as ae}from"execa";var ve={git:"https://git-scm.com/downloads",docker:"https://docs.docker.com/get-docker/",mise:"https://mise.jdx.dev/getting-started.html"},As={8e3:"API Server",5432:"PostgreSQL",6379:"Redis",27017:"MongoDB",5672:"RabbitMQ",3e3:"Web Frontend",8080:"ChromaDB",8083:"Mongo Express"};async function nn(){try{return await ae("git",["--version"]),"success"}catch{return"error"}}async function Et(){let e=!1,t=!1,r;try{await ae("docker",["--version"]),e=!0}catch{return{name:"Docker",installUrl:ve.docker,installed:!1,working:!1,errorMessage:"Docker is not installed"}}try{await ae("docker",["info"],{timeout:5e3}),t=!0}catch{r="Docker is installed but the daemon is not running. Please start Docker Desktop or the Docker daemon."}return{name:"Docker",installUrl:ve.docker,installed:e,working:t,errorMessage:r}}async function sn(){try{return await ae("mise",["--version"]),"success"}catch{return"missing"}}async function an(){if((await import("node:os")).platform()==="win32")try{return await ae("powershell",["-Command","irm https://mise.jdx.dev/install.ps1 | iex"]),!0}catch{return!1}try{return await ae("sh",["-c","curl https://mise.jdx.dev/install.sh | sh"]),!0}catch{return!1}}async function cn(e){let t=await import("node:net"),r=[],o=n=>new Promise(i=>{let a=t.createServer();a.once("error",()=>i(!1)),a.once("listening",()=>{a.close(()=>i(!0))}),a.listen(n)});for(let n of e){let i=As[n]||`Port ${n}`;if(await o(n))r.push({port:n,service:i,available:!0});else{let s=await Os(n),c=await Ls(n+1,n+100,o);r.push({port:n,service:i,available:!1,usedBy:s,alternative:c||void 0})}}return r}async function Os(e){if((await import("node:os")).platform()==="win32"){try{let{stdout:o}=await ae("netstat",["-ano","-p","TCP"]),n=o.trim().split(`
45
+ `);for(let i of n)if(i.includes(`:${e}`)&&i.includes("LISTENING")){let a=i.trim().split(/\s+/),s=a[a.length-1];if(s)try{let{stdout:c}=await ae("tasklist",["/FI",`PID eq ${s}`,"/FO","CSV","/NH"]);return c.trim().split(",")[0]?.replace(/"/g,"")||`PID ${s}`}catch{return`PID ${s}`}}}catch{}return}try{let{stdout:o}=await ae("lsof",["-i",`:${e}`,"-sTCP:LISTEN","-P","-n"]),n=o.trim().split(`
46
+ `);if(n.length>1)return n[1]?.split(/\s+/)?.[0]||void 0}catch{}}async function Ls(e,t,r){for(let o=e;o<=t;o++)if(await r(o))return o;return null}var K=e=>new Promise(t=>setTimeout(t,e)),bt=(e,t="dependencyLogs")=>r=>{let o=e.currentState.data[t]||[],n=r.split(`
47
+ `).filter(i=>i.trim()!=="");e.updateData(t,[...o,...n].slice(-30))};async function Tt(e){e.updateData("checks",{git:"pending",docker:"pending"}),await K(500);let t=await nn();e.updateData("checks",{...e.currentState.data.checks,git:t});let r=await Et(),o=r.working?"success":"error";e.updateData("checks",{...e.currentState.data.checks,docker:o}),r.working||e.updateData("dockerError",r.errorMessage);let n=[];if(t==="error"&&n.push({name:"Git"}),o==="error"&&n.push({name:"Docker",message:r.errorMessage}),n.length>0){let i=["Prerequisites failed:"];for(let a of n)i.push(` \u2022 ${a.name}: ${a.message||"Not installed or not working"}`);return i.push(`
48
+ Installation guides:`),t==="error"&&i.push(` \u2022 Git: ${ve.git}`),o==="error"&&(r.installed?i.push(" \u2022 Docker: Start Docker Desktop or run 'sudo systemctl start docker'"):i.push(` \u2022 Docker: ${ve.docker}`)),e.setError(new Error(i.join(`
49
+ `))),null}return{gitStatus:t,dockerStatus:o,dockerInfo:r}}async function Ct(e){e.updateData("checks",{...e.currentState.data.checks,mise:"pending"});let t=await sn();return e.updateData("checks",{...e.currentState.data.checks,mise:t}),t==="missing"&&(e.setStatus("Installing Mise..."),t=await an()?"success":"error",e.updateData("checks",{...e.currentState.data.checks,mise:t})),t==="error"?(e.setError(new Error(`Developer mode requires Mise but it failed to install.
50
+ \u2022 Mise: ${ve.mise}`)),null):"success"}async function It(e){e.setStatus("Checking Ports...");let r=await cn([8e3,5432,6379,27017,5672,3e3,8080,8083]),o={},n=r.filter(i=>!i.available);if(n.length>0){let i=n.filter(s=>!s.alternative);if(i.length>0)return e.setError(new Error(`Cannot find free alternative ports for: ${i.map(s=>`${s.port} (${s.service})`).join(", ")}. Free these ports and try again.`)),null;if(e.updateData("portConflicts",r),await e.waitForInput("port_conflicts")==="abort")return e.setError(new Error("Port conflicts not resolved. Please free the ports and try again.")),null;for(let s of r)!s.available&&s.alternative&&(o[s.port]=s.alternative)}return e.updateData("portOverrides",o),e.setStatus("Prerequisites check complete!"),await K(1e3),o}async function ln(e,t,r,o){e.setStep("Project Setup"),e.updateData("dependencyPhase","Setting up project..."),e.updateData("dependencyProgress",0),e.updateData("dependencyComplete",!1),e.updateData("dependencyLogs",[]);try{e.updateData("dependencyPhase","Trusting mise configuration..."),await H("mise",["trust"],t,void 0,o),e.updateData("dependencyProgress",20),e.updateData("dependencyPhase","Installing tools..."),await H("mise",["install"],t,i=>{e.updateData("dependencyProgress",20+i*.3)},o),e.updateData("dependencyPhase","Running mise setup...");let n=Object.keys(r).length>0?me(r):void 0;return await H("mise",["setup"],t,i=>{e.updateData("dependencyProgress",50+i*.5)},o,n),e.updateData("dependencyProgress",100),e.updateData("dependencyPhase","Setup complete!"),e.updateData("dependencyComplete",!0),!0}catch(n){return e.setError(new Error(`Failed to setup project: ${n.message}`)),!1}}import{execa as Ns}from"execa";import Pt from"fs";import Bs from"simple-git";async function un(e,t,r,o){if(Pt.existsSync(e)){let n=`${e}/.git`;if(!Pt.existsSync(n))throw new Error(`Directory ${e} exists but is not a git repository`);await Bs().cwd(e).pull(),r(100,"Already exists, pulled latest")}else try{let n=["clone","--progress"];o&&n.push("--branch",o),n.push(t,e);let i=Ns("git",n);i.stderr?.on("data",a=>{let s=a.toString();s.includes("Counting objects")?r(5,"Counting objects"):s.includes("Compressing objects")&&r(10,"Compressing objects");let c=s.match(/Receiving objects:\s+(\d+)%\s+\((\d+)\/(\d+)\)/);if(c?.[1]){let d=Math.min(100,parseInt(c[1],10)),m=c[2],f=c[3];r(10+Math.floor(d*.5),`Receiving objects: ${m}/${f}`)}let u=s.match(/Resolving deltas:\s+(\d+)%\s+\((\d+)\/(\d+)\)/);if(u?.[1]){let d=Math.min(100,parseInt(u[1],10)),m=u[2],f=u[3];r(60+Math.floor(d*.4),`Resolving deltas: ${m}/${f}`)}}),await i,r(100,"Clone complete")}catch(n){throw Pt.existsSync(e)&&Pt.rmSync(e,{recursive:!0,force:!0}),n}}var $s=process.env.GAIA_CLI_DEV==="true",Gs=new RegExp("\x1B\\[[0-9;]*m","g");async function dn(e,t){e.setStep("Welcome"),e.setStatus("Waiting for user input..."),await e.waitForInput("welcome");let r=bt(e);if(e.setStep("Prerequisites"),e.setStatus("Checking system requirements..."),!await Tt(e))return;let o=await It(e);if(o===null)return;let n=await xt(e);if(n==="developer"&&!await Ct(e))return;let i="";if($s){if(i=U()||"",!i){e.setError(new Error("DEV_MODE: Could not find workspace root. Run from within the gaia repo."));return}e.setStep("Repository Setup"),e.setStatus("[DEV MODE] Using current workspace..."),await K(500),e.setStatus("Repository ready!")}else{e.setStep("Repository Setup");let s=n==="selfhost"?Se.join(pn.homedir(),"gaia"):Se.resolve("gaia"),c=!0;for(i=s;;){if(i=await e.waitForInput("repo_path",{default:s}),Se.isAbsolute(i)||(i=Se.resolve(i)),ce.existsSync(i)){if(!ce.statSync(i).isDirectory()){e.setError(new Error(`Path ${i} exists and is not a directory.`)),await K(2e3),e.setError(null);continue}if(ce.existsSync(Se.join(i,"apps/api/app/config/settings_validator.py"))){e.updateData("existingRepoPath",i);let f=await e.waitForInput("existing_repo");if(f==="use_existing"){c=!1;break}else if(f==="delete_reclone"){e.setStatus("Removing existing installation...");try{ce.rmSync(i,{recursive:!0,force:!0})}catch(S){e.setError(new Error(`Failed to remove directory: ${S.message}
51
+ Try removing it manually: rm -rf "${i}"`));return}break}else{if(f==="different_path")continue;e.setError(new Error("Setup cancelled by user."));return}}if(ce.readdirSync(i).length>0){e.setError(new Error(`Directory ${i} is not empty and is not a GAIA installation. Please choose another path.`)),await K(2e3),e.setError(null);continue}}break}if(c){e.setStep("Repository Setup"),e.setStatus("Preparing repository..."),e.updateData("repoProgress",0),e.updateData("repoPhase","");try{await un(i,"https://github.com/theexperiencecompany/gaia.git",(u,d)=>{e.updateData("repoProgress",u),d?(e.updateData("repoPhase",d),e.setStatus(`${d}...`)):e.setStatus(`Cloning repository to ${i}... ${u}%`)},t),e.setStatus("Repository ready!")}catch(u){e.setError(u);return}}else e.setStatus("Using existing repository!")}if(await K(1e3),await wt(e,i,n,o),e.currentState.error)return;if(n==="selfhost"){e.setStep("Project Setup"),e.setStatus("Building and starting all services in Docker..."),e.updateData("dependencyPhase","Building and starting Docker services..."),e.updateData("dependencyProgress",0),e.updateData("dependencyLogs",[]),e.updateData("dependencyComplete",!1);let s=d=>{let m=d.split(`
52
+ `).map(S=>S.replace(Gs,"").trim()).filter(S=>S.length>0);if(m.length===0)return;let f=e.currentState.data.dependencyLogs||[];e.updateData("dependencyLogs",[...f,...m].slice(-30))},c=!1;try{e.setStatus("Pulling pre-built images from registry..."),await qe(i,"selfhost",d=>e.setStatus(d),o,s,{pull:!0}),c=!0}catch(d){let m=d.message?.split(`
53
+ `)[0]??"unknown error";e.setStatus(`Registry pull failed (${m}) \u2014 building images locally (this takes a few minutes)...`)}if(!c)try{await qe(i,"selfhost",d=>e.setStatus(d),o,s,{build:!0})}catch(d){e.setError(new Error(`Failed to start services: ${d.message}`));return}e.updateData("dependencyProgress",100),e.updateData("dependencyComplete",!0);let u=e.currentState.data.envMethod||"manual";lt({version:ne,setupComplete:!0,setupMethod:u,repoPath:i,createdAt:new Date().toISOString(),updatedAt:new Date().toISOString()}),e.updateData("setupMode",n),e.setStep("Finished"),e.setStatus("Setup complete! GAIA is running."),await e.waitForInput("exit");return}e.setStep("Install Tools"),e.setStatus("Installing toolchain..."),e.updateData("dependencyPhase","Initializing mise..."),e.updateData("dependencyProgress",0),e.updateData("dependencyLogs",[]);try{e.updateData("dependencyPhase","Trusting mise configuration..."),await H("mise",["trust"],i,void 0,r),e.updateData("dependencyProgress",50),e.updateData("dependencyPhase","Installing tools (node, python, uv, nx)..."),await H("mise",["install"],i,s=>{e.updateData("dependencyProgress",50+s*.5)},r),e.updateData("dependencyProgress",100),e.updateData("toolComplete",!0)}catch(s){e.setError(new Error(`Failed to install tools: ${s.message}`));return}await K(1e3),e.setStep("Project Setup"),e.updateData("dependencyPhase","Setting up project..."),e.updateData("dependencyProgress",0),e.updateData("dependencyComplete",!1),e.updateData("repoPath",i),e.updateData("dependencyLogs",[]);try{e.updateData("dependencyProgress",0),e.updateData("dependencyPhase","Running mise setup (all dependencies)...");let s=Object.keys(o).length>0?me(o):void 0;await H("mise",["setup"],i,c=>{e.updateData("dependencyProgress",c)},r,s),e.updateData("dependencyProgress",100),e.updateData("dependencyPhase","Setup complete!"),e.updateData("dependencyComplete",!0)}catch(s){e.setError(new Error(`Failed to setup project: ${s.message}`));return}await K(1e3);let a=e.currentState.data.envMethod||"manual";lt({version:ne,setupComplete:!0,setupMethod:a,repoPath:i,createdAt:new Date().toISOString(),updatedAt:new Date().toISOString()}),e.setStep("Finished"),e.setStatus("Setup complete! Run 'gaia dev' to start development mode."),await e.waitForInput("exit")}async function mn(e={}){await re({command:"init",whenNonInteractive:"fail",runFlow:t=>dn(t,e.branch)})}async function fn(e){e.setStep("Detect Repo"),e.setStatus("Looking for GAIA repository...");let t=U();if(!t){e.setError(new Error("Could not find GAIA repository. Run this command from within a cloned gaia repo, or use 'gaia init' to set up from scratch."));return}if(e.updateData("repoPath",t),e.setStatus(`Found repository at ${t}`),await K(1e3),e.setStep("Prerequisites"),e.setStatus("Checking system requirements..."),!await Tt(e))return;let r=await It(e);if(r===null)return;let o=await xt(e);if(o==="developer"&&!await Ct(e)||(await wt(e,t,o,r),e.currentState.error))return;if(o==="selfhost"){let s=e.currentState.data.envMethod||"manual";Ue({setupComplete:!0,setupMethod:s,repoPath:t}),e.updateData("setupMode",o),e.setStep("Finished"),e.setStatus("Setup complete! Run 'gaia start' to build and start all services in Docker."),await e.waitForInput("exit");return}let n=bt(e);if(!await ln(e,t,r,n))return;await K(1e3);let a=e.currentState.data.envMethod||"manual";Ue({setupComplete:!0,setupMethod:a,repoPath:t}),e.updateData("setupMode",o),e.setStep("Finished"),e.setStatus("Setup complete! Run 'gaia dev' to start development mode."),await e.waitForInput("exit")}async function gn(){await re({command:"setup",whenNonInteractive:"fail",runFlow:fn})}var js=new RegExp("\x1B\\[[0-9;]*m","g");async function hn(e,t){e.setStep("Starting"),e.setStatus("Locating GAIA repository...");let r=U();if(!r){e.setError(new Error("Could not find GAIA repository. Run from within a cloned gaia repo."));return}e.updateData("repoPath",r);let o=await Ee(r);if(!o){e.setError(new Error("No .env file found. Run 'gaia init' for fresh setup, or 'gaia setup' to configure an existing repo."));return}if(o==="developer"){e.setError(new Error("Developer mode runs in foreground. Use 'gaia dev' or 'gaia dev full' instead of 'gaia start'."));return}if(o==="selfhost"){e.setStatus("Checking Docker...");let c=await Et();if(!c.working){e.setError(new Error(c.errorMessage||`Docker is not running. Please start Docker and try again.
54
+ ${ve.docker}`));return}}let n=fe(r),i=n[3e3]??3e3,a=n[8e3]??8e3;e.updateData("setupMode",o),e.updateData("webPort",i),e.updateData("apiPort",a),e.updateData("dockerLogs",[]),e.setStatus(`Starting GAIA in ${o} mode...`);let s=c=>{let u=c.split(`
55
+ `).map(m=>m.replace(js,"").trim()).filter(m=>m.length>0);if(u.length===0)return;let d=e.currentState.data.dockerLogs||[];e.updateData("dockerLogs",[...d,...u].slice(-30))};try{await qe(r,o,c=>{e.setStatus(c)},n,s,t),e.setStep("Running"),e.setStatus("GAIA is running!"),e.updateData("started",!0)}catch(c){e.setError(new Error(`Failed to start services: ${c.message}`));return}await e.waitForInput("exit")}async function vn(e){await re({command:"start",whenNonInteractive:"plain",autoResolve:[["exit"]],runFlow:t=>hn(t,e)})}import{execa as _r}from"execa";var kr=["gaia-backend","gaia-web","chromadb","postgres","redis","mongo","rabbitmq","arq_worker"];async function Sn(){try{let{stdout:e}=await _r("docker",["inspect","--format","{{.Name}}|{{.State.Status}}|{{if .State.Health}}{{.State.Health.Status}}{{else}}none{{end}}",...kr]),t=new Map;for(let r of e.trim().split(`
56
+ `)){if(!r)continue;let[o,n,i]=r.split("|"),a=o?.replace(/^\//,"")??"";t.set(a,{name:a,status:n==="running"?"running":"stopped",health:i!=="none"?i:void 0})}return kr.map(r=>t.get(r)??{name:r,status:"not_found"})}catch{let e=kr.map(async t=>{try{let{stdout:r}=await _r("docker",["inspect","--format","{{.State.Status}}|{{if .State.Health}}{{.State.Health.Status}}{{else}}none{{end}}",t]),[o,n]=r.trim().split("|");return{name:t,status:o==="running"?"running":"stopped",health:n!=="none"?n:void 0}}catch{return{name:t,status:"not_found"}}});return Promise.all(e)}}async function yn(){try{return await _r("docker",["info"]),!0}catch{return!1}}var Us=[{name:"API",port:8e3,type:"http",path:"/health"},{name:"Web",port:3e3,type:"http",path:"/"},{name:"PostgreSQL",port:5432,type:"tcp"},{name:"Redis",port:6379,type:"tcp"},{name:"MongoDB",port:27017,type:"tcp"},{name:"RabbitMQ",port:5672,type:"tcp"},{name:"ChromaDB",port:8080,type:"tcp"}];async function xn(e){let r=Us.map(o=>({...o,port:e?.[o.port]??o.port})).map(o=>o.type==="http"?qs(o.name,o.port,o.path):Hs(o.name,o.port));return Promise.all(r)}async function qs(e,t,r){let o=Date.now();try{let n=await fetch(`http://localhost:${t}${r}`,{signal:AbortSignal.timeout(5e3)}),i=Date.now()-o;return{name:e,port:t,status:n.ok?"up":"down",latency:i,details:n.ok?`HTTP ${n.status}`:`HTTP ${n.status} (error)`}}catch{return{name:e,port:t,status:"down",details:"Connection failed"}}}async function Hs(e,t){let r=await import("node:net"),o=Date.now();return new Promise(n=>{let i=new r.Socket;i.setTimeout(3e3),i.on("connect",()=>{let a=Date.now()-o;i.destroy(),n({name:e,port:t,status:"up",latency:a})}),i.on("timeout",()=>{i.destroy(),n({name:e,port:t,status:"down"})}),i.on("error",()=>{i.destroy(),n({name:e,port:t,status:"down"})}),i.connect(t,"localhost")})}async function wn(){return await yn()?{running:!0,containers:await Sn()}:{running:!1,containers:[]}}async function Vs(e){e.setStep("Checking"),e.setStatus("Checking service health..."),e.updateData("refreshable",!1);let t=U(),r=t?fe(t):void 0,[o,n]=await Promise.all([xn(r),wn()]);e.updateData("services",o),e.updateData("docker",n);let i=o.filter(s=>s.status==="up").length,a=o.length;e.setStep("Results"),e.setStatus(`${i}/${a} services running`),e.updateData("refreshable",!0)}async function En(e){for(;await Vs(e),await e.waitForInput("exit_or_refresh")==="refresh";);}async function bn(){await re({command:"status",whenNonInteractive:"plain",autoResolve:[["exit_or_refresh","exit"]],runFlow:En,onPlainComplete:Ws})}function Ws(e){let t=e.currentState.data.services??[],r=e.currentState.data.docker;Ys(t),Ks(r)}function Xs(e){return e==="up"?"UP":e==="down"?"DOWN":"UNKNOWN"}function Ys(e){if(e.length!==0){console.log(`
57
+ Services:`);for(let t of e){let r=Xs(t.status),o=t.latency===void 0?"--":`${t.latency}ms`,n=t.name.padEnd(12);console.log(` ${n} :${t.port} ${r} ${o}`)}}}function Ks(e){if(e){console.log(`
58
+ Docker: ${e.running?"running":"not running"}`);for(let t of e.containers??[]){let r=t.health?` (${t.health})`:"",o=t.name.padEnd(14);console.log(` ${o} ${t.status}${r}`)}}}async function Tn(e,t){e.setStep("Stopping"),e.setStatus("Locating GAIA repository...");let r=U();if(!r){e.setError(new Error("Could not find GAIA repository. Run from within a cloned gaia repo."));return}e.updateData("repoPath",r),e.updateData("stopMode",t?.forcePorts?"force-ports":"safe");let o=fe(r);try{await Lo(r,n=>{e.setStatus(n)},o,t),e.setStep("Stopped"),e.setStatus(t?.forcePorts?"All services stopped (force-port mode).":"All services stopped (safe mode)."),e.updateData("stopped",!0)}catch(n){e.setError(new Error(`Failed to stop services: ${n.message}`));return}await e.waitForInput("exit")}async function Cn(e){await re({command:"stop",whenNonInteractive:"plain",autoResolve:[["exit"]],runFlow:t=>Tn(t,e)})}import*as Rt from"fs";import*as kt from"path";function Js(e){let t=kt.join(e,".env");return Rt.existsSync(t)?["--env-file",".env"]:[]}async function In(){let e=U();if(!e)throw new Error("Could not find GAIA repository. Run from within a cloned gaia repo.");let t=await Ee(e);if(!t)throw new Error("No .env file found. Run 'gaia init' for fresh setup, or 'gaia setup' to configure an existing repo.");let r=kt.join(e,"infra","docker"),o=Js(r),n=fe(e),i=Object.keys(n).length>0?me(n):void 0;if(t==="selfhost"){await _e("docker",["compose","-f","docker-compose.selfhost.yml",...o,"logs","-f","--tail","200"],r,i);return}let a=["compose",...o,"logs","-f","--tail","200"],s=kt.join(e,Ao),c=mr(e),u=typeof c=="number"&&ut(c);if(Rt.existsSync(s)&&u){console.log("Streaming app and infrastructure logs..."),process.platform==="win32"?await ct([{cmd:"powershell",args:["-Command",`Get-Content -Path '${s.replace(/'/g,"''")}' -Wait -Tail 200`],cwd:e},{cmd:"docker",args:a,cwd:r,env:i}]):await ct([{cmd:"tail",args:["-n","200","-f",s],cwd:e},{cmd:"docker",args:a,cwd:r,env:i}]);return}Rt.existsSync(s)&&!u?(console.log("Detected stale developer app logs from a previous run. Streaming Docker logs only."),await _e("docker",a,r,i)):(console.log("No active developer process detected. Streaming Docker service logs. Run `gaia dev` in another terminal for live Nx app logs."),await _e("docker",a,r,i))}var Z=new Qs;Z.name("gaia").description("CLI tool for setting up and managing GAIA").version(ne);Z.addCommand(ie);Z.command("init").description(le.init).option("--branch <branch>","Git branch to clone").action(async e=>{await mn({branch:e.branch})});Z.command("setup").description(le.setup).action(async()=>{await gn()});Z.command("status").description(le.status).action(async()=>{await bn()});Z.command("start").description(le.start).option("-b, --build","Rebuild Docker images before starting").option("--pull","Pull latest base images before starting").action(async e=>{await vn({build:e.build,pull:e.pull})});Z.command("dev [profile]").description(le.dev).action(async e=>{try{await No(e)}catch(t){console.error(t instanceof Error?t.message:String(t)),process.exit(1)}});Z.command("logs").description(le.logs).action(async()=>{try{await In()}catch(e){console.error(e instanceof Error?e.message:String(e)),process.exit(1)}});Z.command("stop").description(le.stop).option("--force-ports","Aggressively stop processes listening on API/Web ports (may affect non-GAIA processes)").action(async e=>{await Cn({forcePorts:e.forcePorts})});process.argv.slice(2).length||(Z.outputHelp(),process.exit(0));Z.parse();
package/package.json CHANGED
@@ -1,14 +1,14 @@
1
1
  {
2
2
  "name": "@heygaia/cli",
3
3
  "description": "CLI tool for setting up and managing GAIA",
4
- "version": "0.5.0",
4
+ "version": "0.6.0",
5
5
  "type": "module",
6
6
  "files": [
7
7
  "dist",
8
8
  "README.md"
9
9
  ],
10
10
  "scripts": {
11
- "build": "esbuild src/index.ts --bundle --platform=node --target=node18 --format=esm --packages=external --outfile=dist/index.js --minify && chmod +x dist/index.js",
11
+ "build": "node esbuild.config.mjs && chmod +x dist/index.js",
12
12
  "check": "biome check src",
13
13
  "dev": "tsx watch src/index.ts",
14
14
  "fix": "biome check --write src",
@@ -36,6 +36,7 @@
36
36
  },
37
37
  "devDependencies": {
38
38
  "@biomejs/biome": "^2.5.7",
39
+ "@gaia/shared": "workspace:*",
39
40
  "@types/node": "^24.13.3",
40
41
  "@types/react": "^19.2.17",
41
42
  "@types/react-dom": "^19.2.3",