@heygaia/cli 0.1.0 → 0.1.2

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 (3) hide show
  1. package/README.md +120 -35
  2. package/dist/index.js +15 -9
  3. package/package.json +10 -2
package/README.md CHANGED
@@ -1,25 +1,72 @@
1
1
  # @heygaia/cli
2
2
 
3
- CLI tool for setting up and managing GAIA - your proactive personal AI assistant.
3
+ CLI tool for setting up and managing [GAIA](https://heygaia.io) your proactive personal AI assistant.
4
+
5
+ The CLI provides an interactive terminal UI that guides you through cloning, configuring, and running a self-hosted GAIA instance.
6
+
7
+ ## Requirements
8
+
9
+ - **Node.js 18+** (for npm/npx) or **Bun** (alternative)
10
+ - **macOS or Linux** (Windows via WSL2)
11
+ - **Docker** installed and running
12
+ - **Git** installed
13
+
14
+ The CLI checks prerequisites at startup and tells you what's missing.
4
15
 
5
16
  ## Installation
6
17
 
18
+ ### curl (recommended)
19
+
20
+ Downloads and installs the CLI globally. Uses npm if available, falls back to bun.
21
+
7
22
  ```bash
8
- # Quick install (recommended)
9
23
  curl -fsSL https://heygaia.io/install.sh | sh
24
+ ```
10
25
 
11
- # Or via npm
26
+ ### npm
27
+
28
+ ```bash
12
29
  npm install -g @heygaia/cli
30
+ ```
31
+
32
+ ### npx (no install)
33
+
34
+ Run directly without a global install:
13
35
 
14
- # Or run without installing
36
+ ```bash
15
37
  npx @heygaia/cli init
16
38
  ```
17
39
 
40
+ ### Other package managers
41
+
42
+ ```bash
43
+ # pnpm
44
+ pnpm add -g @heygaia/cli
45
+
46
+ # bun
47
+ bun add -g @heygaia/cli
48
+ ```
49
+
50
+ ### Verify
51
+
52
+ ```bash
53
+ gaia --version
54
+ gaia --help
55
+ ```
56
+
57
+ ## What Happens When You Install
58
+
59
+ 1. The `@heygaia/cli` npm package is installed globally
60
+ 2. A `gaia` binary is added to your PATH (points to `dist/index.js`)
61
+ 3. No background processes, daemons, or services are started — the CLI only runs when you invoke it
62
+
63
+ The CLI itself is a single bundled JavaScript file (~300KB) with no native dependencies.
64
+
18
65
  ## Commands
19
66
 
20
67
  | Command | Description |
21
68
  |---------|-------------|
22
- | `gaia init` | Full setup from scratch - clones repo, installs tools, configures env, starts services |
69
+ | `gaia init` | Full setup from scratch clone repo, install tools, configure env, start services |
23
70
  | `gaia setup` | Configure an existing GAIA repository (env vars, dependencies) |
24
71
  | `gaia start` | Start all GAIA services (auto-detects selfhost vs developer mode) |
25
72
  | `gaia stop` | Stop all running GAIA services |
@@ -27,56 +74,93 @@ npx @heygaia/cli init
27
74
 
28
75
  ### `gaia init`
29
76
 
30
- Interactive wizard for first-time setup:
77
+ Interactive wizard for first-time setup. This is the main entry point for new users.
31
78
 
32
- 1. Prerequisites check (Git, Docker, Mise)
33
- 2. Repository cloning
34
- 3. Tool installation (Node.js, Python, uv, Nx)
35
- 4. Environment variable configuration
36
- 5. Project setup (`mise setup`)
37
- 6. Service startup (optional)
79
+ **What it does:**
80
+
81
+ 1. **Prerequisites check** Verifies Git, Docker, and [Mise](https://mise.jdx.dev) are installed. Auto-installs Mise if missing.
82
+ 2. **Port conflict detection** — Checks ports 3000, 5432, 6379, 8000, 8080, 27017, 5672. Suggests alternatives if any are in use.
83
+ 3. **Repository clone** Clones the GAIA repo to your chosen directory with progress tracking.
84
+ 4. **Tool installation** — Installs Node.js, Python, uv, and Nx via Mise.
85
+ 5. **Environment configuration** — Choose a setup mode and configure variables (see below).
86
+ 6. **Project setup** — Runs `mise setup` to install all dependencies, start Docker services, and seed the database.
87
+ 7. **Service startup** — Optionally starts all services immediately.
38
88
 
39
89
  ### `gaia setup`
40
90
 
41
- For existing repos that need configuration or reconfiguration. Run from within a cloned GAIA directory:
91
+ For existing repos that need configuration or reconfiguration. Skips cloning and tool installation, goes straight to environment setup.
42
92
 
43
93
  ```bash
44
- cd /path/to/gaia && gaia setup
94
+ cd /path/to/gaia
95
+ gaia setup
45
96
  ```
46
97
 
47
- ### `gaia start` / `gaia stop`
98
+ ### `gaia start`
99
+
100
+ Starts all services. Auto-detects the setup mode from your `.env` configuration:
48
101
 
49
- Start or stop services. Automatically detects selfhost vs developer mode from your `.env` configuration.
102
+ - **Self-host mode**: Runs `docker compose --profile all up -d`
103
+ - **Developer mode**: Runs `mise dev` for local API + web, Docker for databases
104
+
105
+ ### `gaia stop`
106
+
107
+ Stops all running services:
108
+ - Docker containers in the GAIA compose stack
109
+ - Local processes on ports 8000 (API) and 3000 (Web)
50
110
 
51
111
  ### `gaia status`
52
112
 
53
- Shows health and latency for: API (8000), Web (3000), PostgreSQL (5432), Redis (6379), MongoDB (27017), RabbitMQ (5672), ChromaDB (8080).
113
+ Shows a live health dashboard with latency for all services:
114
+
115
+ | Service | Port | Health Check |
116
+ |---------|------|--------------|
117
+ | API | 8000 | HTTP `GET /health` |
118
+ | Web | 3000 | HTTP `GET /` |
119
+ | PostgreSQL | 5432 | TCP connection |
120
+ | Redis | 6379 | TCP connection |
121
+ | MongoDB | 27017 | TCP connection |
122
+ | RabbitMQ | 5672 | TCP connection |
123
+ | ChromaDB | 8080 | TCP connection |
124
+
125
+ Press `r` to refresh.
54
126
 
55
127
  ## Setup Modes
56
128
 
57
- - **Self-Host (Docker)**: Everything runs in Docker. Best for deployment.
58
- - **Developer (Local)**: Databases in Docker, API + web run locally. Best for contributing.
129
+ During `gaia init` or `gaia setup`, you choose a mode:
130
+
131
+ - **Self-Host (Docker)** — Everything runs in Docker containers. Best for deployment and non-developers.
132
+ - **Developer (Local)** — Databases in Docker, API + web run locally with hot reload. Best for contributing.
59
133
 
60
- ## Environment Variable Auto-Discovery
134
+ ## Environment Variable Configuration
61
135
 
62
- The CLI discovers env vars from the codebase at runtime:
136
+ Two methods are available:
63
137
 
64
- - **API**: Extracted from `apps/api/app/config/settings.py` and `settings_validator.py` via Python AST
65
- - **Web**: Parsed from `apps/web/.env`
138
+ - **Manual** Interactive prompts for each variable with descriptions, documentation links, and defaults.
139
+ - **Infisical** Enter your Infisical credentials (token, project ID, machine identity) for centralized secret management.
66
140
 
67
- No CLI updates needed when new variables are added.
141
+ ### Auto-Discovery
142
+
143
+ The CLI discovers environment variables from the codebase at runtime:
144
+
145
+ - **API variables** — Extracted from `apps/api/app/config/settings.py` and `settings_validator.py` via Python AST parsing
146
+ - **Web variables** — Parsed from `apps/web/.env`
147
+
148
+ When a developer adds a new variable to either location, the CLI picks it up automatically — no CLI updates needed.
68
149
 
69
150
  ## Development
70
151
 
71
152
  ```bash
72
- # Dev mode (no build, uses current workspace)
73
- GAIA_CLI_DEV=true bun packages/cli/src/index.ts <command>
153
+ # Dev mode (watch, no build needed)
154
+ GAIA_CLI_DEV=true pnpm tsx packages/cli/src/index.ts <command>
74
155
 
75
156
  # Build
76
- cd packages/cli && bun run build
157
+ cd packages/cli && pnpm run build
77
158
 
78
- # Test built CLI
159
+ # Test the built CLI
79
160
  ./packages/cli/dist/index.js --help
161
+
162
+ # Run the test script
163
+ ./packages/cli/test-cli.sh
80
164
  ```
81
165
 
82
166
  ### Install Script
@@ -87,24 +171,25 @@ Source of truth: `packages/cli/install.sh`. After modifying, sync to the web app
87
171
  ./packages/cli/sync-install.sh
88
172
  ```
89
173
 
90
- This keeps `https://heygaia.io/install.sh` up to date.
174
+ This copies the script to `apps/web/public/install.sh`, which is served at `https://heygaia.io/install.sh`.
91
175
 
92
176
  ### Publishing
93
177
 
94
178
  1. Update version in `package.json`
95
- 2. Build: `bun run build`
179
+ 2. Build: `pnpm run build`
96
180
  3. Sync install script: `./sync-install.sh`
97
181
  4. Commit and tag: `git tag cli-v<version>`
98
182
  5. Push tag — GitHub Actions publishes to npm
99
183
 
100
- ### Troubleshooting
184
+ ## Troubleshooting
101
185
 
102
186
  | Issue | Fix |
103
187
  |-------|-----|
104
- | `command not found: gaia` | Ensure `~/.bun/bin` or `~/.npm-global/bin` is in PATH |
105
- | Raw mode not supported | CLI requires interactive terminal — don't run in background |
106
- | Port conflicts not detected | Ensure `lsof` is available (macOS/Linux) |
107
- | Env vars not discovered | Check `settings_validator.py` and `apps/web/.env` exist |
188
+ | `command not found: gaia` | Ensure the global bin directory is in PATH. For npm: `export PATH="$(npm config get prefix)/bin:$PATH"`. For bun: `export PATH="$HOME/.bun/bin:$PATH"` |
189
+ | Raw mode not supported | The CLI requires an interactive terminal — don't run in background or pipe |
190
+ | Port conflicts not detected | Ensure `lsof` is available (macOS/Linux). Windows requires WSL2 |
191
+ | Env vars not discovered | Check that `settings_validator.py` and `apps/web/.env` exist in the repo |
192
+ | Docker prerequisite fails | Ensure Docker Desktop/Engine is running, not just installed |
108
193
 
109
194
  ## License
110
195
 
package/dist/index.js CHANGED
@@ -1,10 +1,16 @@
1
1
  #!/usr/bin/env node
2
- import{Command as Or}from"commander";import{render as Er}from"ink";import wr from"react";import{Box as me,Text as z}from"ink";import ir from"react";import{ProgressBar as Qe,Select as Ke,Spinner as Je}from"@inkjs/ui";import{Box as l,Text as s,useInput as J}from"ink";import se from"ink-text-input";import{useEffect as de,useState as L}from"react";import{Box as ie,Text as Xe}from"ink";var S="#00bbff";import{Box as Gt,Text as Ce}from"ink";import{jsx as He,jsxs as We}from"react/jsx-runtime";var Ue=({status:e,step:t})=>t.toLowerCase()==="welcome"?null:We(Gt,{width:"100%",borderStyle:"single",borderColor:"gray",paddingX:1,justifyContent:"space-between",children:[We(Ce,{color:S,children:[He(Ce,{bold:!0,children:"Status:"})," ",t]}),He(Ce,{color:"white",dimColor:!0,children:e})]});import{Box as Ot}from"ink";import qt from"ink-big-text";import $t from"ink-gradient";import{jsx as Ie}from"react/jsx-runtime";var ee=()=>Ie(Ot,{flexDirection:"column",marginTop:1,marginBottom:1,children:Ie($t,{colors:[S,"#b0eaff",S],children:Ie(qt,{text:"GAIA",font:"3d"})})});import{jsx as te,jsxs as ue}from"react/jsx-runtime";var jt=["Welcome","Prerequisites","Repository Setup","Install Tools","Environment Setup","Project Setup","Finished"],Ye=["Detect Repo","Prerequisites","Environment Setup","Project Setup","Finished"],Vt=({currentStep:e,steps:t})=>{let o=t.indexOf(e);return te(ie,{marginBottom:1,children:t.map((r,n)=>{let i=r===e,p=o>n;return ue(ie,{marginRight:2,children:[ue(Xe,{color:i?S:p?"green":"gray",children:[p?"\u2713 ":i?"\u25CF ":"\u25CB ",r]}),n<t.length-1&&te(Xe,{color:"gray",children:" \u203A "})]},r)})})},pe=({children:e,status:t,step:o,steps:r=jt})=>ue(ie,{flexDirection:"column",height:"100%",width:"100%",children:[ue(ie,{flexGrow:1,flexDirection:"column",children:[te(ee,{}),te(Vt,{currentStep:o,steps:r}),te(ie,{flexDirection:"column",flexGrow:1,children:e})]}),te(Ue,{status:t,step:o})]});import{Fragment as uo,jsx as a,jsxs as c}from"react/jsx-runtime";var Ee=({label:e,status:t})=>c(l,{children:[a(l,{marginRight:1,children:t==="pending"?a(Je,{type:"dots"}):t==="success"?a(s,{color:S,children:"\u2714"}):t==="error"?a(s,{color:"red",children:"\u2716"}):a(s,{color:"yellow",children:"\u26A0"})}),a(s,{children:e})]}),Ht=({onConfirm:e})=>(J((t,o)=>{o.return&&e()}),c(l,{flexDirection:"column",paddingX:2,borderStyle:"round",borderColor:S,children:[a(s,{bold:!0,children:"Welcome to the Interactive GAIA Setup"}),c(l,{flexDirection:"column",marginTop:1,marginBottom:1,children:[a(s,{children:"This wizard will guide you through the setup process:"}),a(s,{children:" 1. Check Prerequisites (Git, Docker, Mise)"}),a(s,{children:" 2. Clone Repository (from GitHub)"}),a(s,{children:" 3. Install Tools (node, python, uv via mise)"}),a(s,{children:" 4. Configure Env Vars (databases, API keys, etc.)"}),a(s,{children:" 5. Setup Project (install all dependencies)"})]}),a(s,{color:S,children:"Press Enter to start..."})]})),Wt=({portResults:e,onAccept:t,onAbort:o})=>{J((n,i)=>{i.return?t():i.escape&&o()});let r=e.filter(n=>!n.available);return c(l,{flexDirection:"column",marginTop:1,paddingX:1,borderStyle:"round",borderColor:"yellow",children:[a(l,{marginBottom:1,children:a(s,{bold:!0,color:"yellow",children:"Port Conflicts Detected"})}),e.map(n=>c(l,{children:[c(s,{color:n.available?"green":n.alternative?"yellow":"red",children:[n.available?"\u2714":n.alternative?"\u26A0":"\u2716"," "]}),c(s,{children:[n.service," (:",n.port,")"]}),!n.available&&c(s,{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)),c(l,{marginTop:1,flexDirection:"column",children:[r.some(n=>!n.alternative)&&a(l,{borderStyle:"single",borderColor:"red",paddingX:1,marginBottom:1,children:a(s,{color:"red",children:"Some ports have no available alternative. Free them and retry."})}),!r.some(n=>!n.alternative)&&r.some(n=>n.alternative)&&a(s,{color:"gray",children:"Alternative ports will be used for conflicting services."}),a(l,{marginTop:1,children:c(s,{children:[a(s,{color:"green",bold:!0,children:"Enter"})," to continue with alternatives ",a(s,{color:"yellow",bold:!0,children:"Escape"})," to abort"]})})]})]})},Ut=({defaultValue:e,onSubmit:t})=>{let[o,r]=L(e);return c(l,{flexDirection:"column",marginTop:1,paddingX:1,borderStyle:"round",borderColor:S,children:[a(s,{children:"Where should we clone the repository?"}),c(l,{children:[a(s,{color:S,children:"\u279C "}),a(se,{value:o,onChange:r,onSubmit:t})]}),c(s,{color:"gray",children:["(Press Enter for default: ",e,")"]})]})},Xt=({setupMode:e,repoPath:t,portOverrides:o,onConfirm:r})=>{J((m,f)=>{f.return&&r()});let n=e||"developer",i=t||"./gaia",p=o?.[3e3]??3e3,u=o?.[8e3]??8e3;return c(l,{flexDirection:"column",marginTop:2,borderStyle:"round",borderColor:S,padding:1,children:[a(s,{color:S,bold:!0,children:"You are all set!"}),c(l,{marginTop:1,flexDirection:"column",children:[a(s,{bold:!0,children:"To start GAIA, run:"}),c(l,{marginTop:1,padding:1,borderStyle:"single",borderColor:"gray",flexDirection:"column",children:[c(s,{color:"cyan",children:["$ cd ",i]}),a(s,{color:"cyan",children:"$ gaia start"})]}),a(l,{marginTop:1,children:a(s,{color:"gray",dimColor:!0,children:n==="selfhost"?"Runs: docker compose --profile all up -d (background)":"Runs: mise dev (interactive \u2014 keep terminal open)"})})]}),c(l,{marginTop:1,flexDirection:"column",children:[a(s,{bold:!0,children:"Access GAIA at:"}),c(l,{marginLeft:2,flexDirection:"column",children:[c(s,{children:["Web:"," ",c(s,{color:"cyan",bold:!0,children:["http://localhost:",p]})]}),c(s,{children:["API:"," ",c(s,{color:"cyan",bold:!0,children:["http://localhost:",u]})]})]})]}),a(we,{}),a(l,{marginTop:1,children:a(s,{dimColor:!0,children:"Press Enter to exit"})})]})},we=()=>c(l,{marginTop:1,flexDirection:"column",children:[a(s,{bold:!0,children:"Available commands:"}),c(l,{marginLeft:2,flexDirection:"column",children:[c(s,{children:[c(s,{color:S,bold:!0,children:["gaia start"," "]}),a(s,{color:"gray",children:" Start all services"})]}),c(s,{children:[c(s,{color:S,bold:!0,children:["gaia stop"," "]}),a(s,{color:"gray",children:" Stop all services"})]}),c(s,{children:[a(s,{color:S,bold:!0,children:"gaia status"}),a(s,{color:"gray",children:" Check service health"})]}),c(s,{children:[c(s,{color:S,bold:!0,children:["gaia setup"," "]}),a(s,{color:"gray",children:" Reconfigure environment"})]})]})]}),Yt=({phase:e,progress:t,isComplete:o,logs:r,title:n})=>c(l,{flexDirection:"column",marginTop:1,paddingX:1,borderStyle:"round",borderColor:S,children:[a(l,{marginBottom:1,children:a(s,{bold:!0,color:S,children:n||"Installing Dependencies"})}),c(l,{flexDirection:"column",gap:1,children:[a(l,{children:o?c(s,{color:"green",children:["\u2713 ",e]}):a(Je,{label:e||"Preparing..."})}),!o&&t>0&&a(l,{width:50,children:a(Qe,{value:t})}),!o&&r&&r.length>0&&a(l,{flexDirection:"column",marginTop:1,borderStyle:"single",borderColor:"gray",paddingX:1,paddingY:0,minHeight:6,children:r.map((i,p)=>a(s,{color:"gray",wrap:"truncate",children:i},p))})]})]});var Pe=({onSelect:e})=>c(l,{flexDirection:"column",marginTop:1,paddingX:1,borderStyle:"round",borderColor:S,children:[a(s,{bold:!0,children:"Setup Mode"}),a(l,{marginTop:1,children:a(s,{color:"gray",children:"How do you want to run GAIA?"})}),a(l,{marginTop:1,children:a(Ke,{options:[{label:"Self-Host (Docker)",value:"selfhost"},{label:"Developer Mode (Local)",value:"developer"}],onChange:o=>e(o)})}),c(l,{marginTop:1,flexDirection:"column",children:[a(s,{color:"gray",dimColor:!0,children:"Self-Host: Run everything in Docker containers (recommended for deployment)"}),a(s,{color:"gray",dimColor:!0,children:"Developer: Run backend locally with Docker services (recommended for contributing)"})]})]}),De=({onSelect:e})=>c(l,{flexDirection:"column",marginTop:1,paddingX:1,borderStyle:"round",borderColor:S,children:[a(s,{bold:!0,children:"Environment Variables Setup"}),a(l,{marginTop:1,children:a(s,{color:"gray",children:"Choose how you want to configure environment variables:"})}),a(l,{marginTop:1,children:a(Ke,{options:[{label:"Manual Setup (Recommended)",value:"manual"},{label:"Infisical (Advanced)",value:"infisical"}],onChange:o=>e(o)})}),c(l,{marginTop:1,flexDirection:"column",children:[a(s,{color:"gray",dimColor:!0,children:"Manual Setup: Configure variables interactively (recommended for most users)"}),a(s,{color:"gray",dimColor:!0,children:"Infisical: All secrets managed in Infisical dashboard (requires pre-configuration)"})]})]}),Re=({onSubmit:e})=>{let[t,o]=L({INFISICAL_TOKEN:"",INFISICAL_PROJECT_ID:"",INFISICAL_MACHINE_IDENTITY_CLIENT_ID:"",INFISICAL_MACHINE_IDENTITY_CLIENT_SECRET:""}),[r,n]=L(0),[i,p]=L(null),u=[{key:"INFISICAL_TOKEN",description:"Service token from project settings (st.xxx...)"},{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"}];J((f,g)=>{if(g.tab||g.downArrow)n(d=>d<u.length-1?d+1:d);else if(g.upArrow)n(d=>d>0?d-1:d);else if(g.return){if(r<u.length-1){n(y=>y+1);return}let d=u.filter(y=>!t[y.key].trim());if(d.length>0){p(`Required: ${d.map(h=>h.key).join(", ")}`);let y=u.findIndex(h=>!t[h.key].trim());y>=0&&n(y);return}e(t)}});let m=u[r];return c(l,{flexDirection:"column",marginTop:1,paddingX:1,borderStyle:"round",borderColor:S,children:[a(l,{marginBottom:1,children:a(s,{bold:!0,color:S,children:"Infisical Configuration"})}),a(l,{marginBottom:1,borderStyle:"single",borderColor:"cyan",paddingX:1,children:a(s,{color:"cyan",children:"All environment variables (API keys, auth secrets, etc.) must be configured in your Infisical project. Only Infisical credentials will be stored locally."})}),c(l,{marginBottom:1,flexDirection:"column",children:[a(s,{color:"gray",children:"Configure your Infisical credentials."}),c(s,{color:"gray",dimColor:!0,children:["Visit"," ",a(s,{color:"cyan",underline:!0,children:"app.infisical.com"})," ","to get these values."]})]}),u.map((f,g)=>{let d=f.key.includes("SECRET")||f.key.includes("TOKEN");return c(l,{flexDirection:"column",marginBottom:1,children:[a(l,{children:c(s,{color:g===r?S:"white",children:[g===r?"\u25B8 ":" ",f.key,":"]})}),a(l,{marginLeft:2,children:a(s,{color:"gray",dimColor:!0,children:f.description})}),g===r?a(l,{marginLeft:2,children:a(se,{value:t[f.key],onChange:y=>{o(h=>({...h,[f.key]:y})),p(null)},placeholder:"Enter value...",mask:d?"*":void 0})}):a(l,{marginLeft:2,children:a(s,{color:t[f.key]?"green":"gray",children:t[f.key]?d?`\u2713 ${"*".repeat(8)}`:`\u2713 ${t[f.key]}`:"(not set)"})})]},f.key)}),i&&a(l,{marginTop:1,children:a(s,{color:"red",children:i})}),a(l,{marginTop:1,children:a(s,{color:"gray",dimColor:!0,children:"\u2191\u2193/Tab to navigate \u2022 Enter to confirm"})})]})},Be=({category:e,currentIndex:t,totalGroups:o,onSubmit:r})=>{let[n,i]=L(()=>{let y={};for(let h of e.variables)y[h.name]=h.defaultValue||"";return y}),[p,u]=L(0),[m,f]=L(null);de(()=>{let y={};for(let h of e.variables)y[h.name]=h.defaultValue||"";i(y),u(0),f(null)},[e.name]),J((y,h)=>{if(h.tab||h.downArrow)u(x=>x<e.variables.length-1?x+1:x);else if(h.upArrow)u(x=>x>0?x-1:x);else if(h.escape){let x=e.variables.filter(v=>v.required&&!n[v.name]?.trim());if(x.length>0){f(`Required fields cannot be skipped: ${x.map(v=>v.name).join(", ")}`);return}r(n)}});let g=()=>{if(p<e.variables.length-1)u(p+1);else{let y=e.variables.filter(h=>h.required&&!n[h.name]?.trim());if(y.length>0){f(`Required fields are missing: ${y.map(h=>h.name).join(", ")}`);return}f(null),r(n)}},d=e.variables.some(y=>y.required);return c(l,{flexDirection:"column",marginTop:1,paddingX:1,borderStyle:"round",borderColor:m?"red":S,children:[c(l,{justifyContent:"space-between",children:[c(s,{bold:!0,children:["Configure ",e.name]}),c(s,{color:"gray",children:["Group ",t+1," / ",o]})]}),c(l,{marginTop:1,flexDirection:"column",children:[c(l,{children:[c(s,{color:"cyan",bold:!0,children:["Purpose:"," "]}),a(s,{color:"white",children:e.description})]}),e.affectedFeatures&&c(l,{children:[c(s,{color:"cyan",bold:!0,children:["Affects:"," "]}),a(s,{color:"gray",children:e.affectedFeatures})]}),e.docsUrl&&c(l,{marginTop:1,children:[a(s,{color:"green",children:"\u{1F4D6} Docs: "}),a(s,{color:"blue",underline:!0,children:e.docsUrl})]})]}),a(l,{marginTop:1,flexDirection:"column",children:e.variables.map((y,h)=>{let x=h===p,v=!!y.defaultValue;return c(l,{flexDirection:"column",marginBottom:1,children:[c(l,{children:[c(s,{color:x?S:"gray",bold:x,children:[x?"\u279C ":" ",y.name]}),y.required&&c(s,{color:"red",bold:!0,children:[" ","*"]}),v&&!x&&c(s,{color:"gray",dimColor:!0,children:[" ","(default: ",y.defaultValue,")"]})]}),x&&a(l,{marginLeft:2,children:a(se,{value:n[y.name]||"",onChange:T=>{i(C=>({...C,[y.name]:T})),m&&f(null)},onSubmit:g,placeholder:v?`Default: ${y.defaultValue}`:y.required?"Enter a value (required)":"Press Enter to skip"})})]},y.name)})}),m&&a(l,{marginTop:1,children:c(s,{color:"red",bold:!0,children:["\u26A0 ",m]})}),a(l,{marginTop:1,flexDirection:"column",children:c(s,{color:"gray",dimColor:!0,children:["\u21B5 Enter to next field \u2022 Tab/\u2193 move down \u2022 \u2191 move up",!d&&" \u2022 ESC skip group"]})})]})},Ae=({alternatives:e,onSubmit:t})=>{let[o,r]=L(new Set),[n,i]=L({}),[p,u]=L(0),[m,f]=L(null);de(()=>{let T={};for(let C of e)for(let I of C.variables)T[I.name]=I.defaultValue||"";i(T)},[e]);let g=[];for(let T=0;T<e.length;T++)if(g.push({type:"provider",categoryIndex:T}),o.has(T)){let C=e[T];if(C)for(let I=0;I<C.variables.length;I++)g.push({type:"field",categoryIndex:T,fieldIndex:I})}g.push({type:"submit"});let d=g[p],y=d?.type==="field",h=d?.type==="submit";J((T,C)=>{let I=Math.min(p,g.length-1);if(I!==p){u(I);return}if(y)C.upArrow?u(E=>Math.max(0,E-1)):(C.downArrow||C.tab)&&u(E=>Math.min(g.length-1,E+1));else if(h)C.upArrow?u(E=>Math.max(0,E-1)):(C.return||T===" ")&&v();else if(C.upArrow)u(E=>Math.max(0,E-1));else if(C.downArrow||C.tab)u(E=>Math.min(g.length-1,E+1));else if((C.return||T===" ")&&d?.type==="provider"){let E=d.categoryIndex;r(V=>{let R=new Set(V);return R.has(E)?R.delete(E):R.add(E),R}),m&&f(null)}});let x=()=>{m&&f(null),u(T=>Math.min(g.length-1,T+1))},v=()=>{let T=[],C={};for(let I of o){let E=e[I];if(!E)continue;if(E.variables.some(R=>n[R.name]?.trim())){T.push(E.name);for(let R of E.variables){let le=n[R.name];le&&(C[R.name]=le)}}}if(T.length===0){o.size===0?f("Enable at least one provider (press Space or Enter)"):f("Enter a value for at least one field");return}t(T,C)};return c(l,{flexDirection:"column",marginTop:1,paddingX:1,borderStyle:"round",borderColor:m?"red":S,children:[c(l,{justifyContent:"space-between",children:[a(s,{bold:!0,children:"Configure AI Provider"}),a(s,{color:"yellow",children:"* At least one required"})]}),a(l,{marginTop:1,children:a(s,{color:"gray",children:"Enable and configure at least one AI provider below:"})}),a(l,{marginTop:1,flexDirection:"column",children:e.map((T,C)=>{let I=o.has(C),E=g.findIndex(R=>R.type==="provider"&&R.categoryIndex===C),V=p===E;return c(l,{flexDirection:"column",marginBottom:1,children:[c(l,{children:[a(s,{color:V?S:void 0,bold:V,children:V?"\u279C ":" "}),a(s,{color:I?"green":"gray",children:I?"[\u2714]":"[ ]"}),c(s,{color:I?S:"gray",bold:I,children:[" ",T.name]}),T.description&&c(s,{color:"gray",dimColor:!0,children:[" ","- ",T.description]})]}),V&&T.docsUrl&&c(l,{marginLeft:6,children:[a(s,{color:"yellow",children:"\u{1F4D6} "}),a(s,{color:"blue",underline:!0,children:T.docsUrl})]}),I&&a(l,{marginLeft:4,flexDirection:"column",marginTop:1,children:T.variables.map((R,le)=>{let Mt=g.findIndex(ae=>ae.type==="field"&&ae.categoryIndex===C&&ae.fieldIndex===le),Z=p===Mt,Ve=!!R.defaultValue,Te=n[R.name]||"";return c(l,{flexDirection:"column",marginBottom:1,children:[c(l,{children:[c(s,{color:Z?S:"gray",bold:Z,children:[Z?" \u279C ":" ",R.name]}),!Z&&Te&&a(s,{color:"green",children:" \u2713"}),!Z&&!Te&&Ve&&c(s,{color:"gray",dimColor:!0,children:[" ","(default: ",R.defaultValue,")"]})]}),Z&&a(l,{marginLeft:4,children:a(se,{value:Te,onChange:ae=>{i(Nt=>({...Nt,[R.name]:ae})),m&&f(null)},onSubmit:x,placeholder:Ve?`Default: ${R.defaultValue}`:"Enter value..."})})]},R.name)})})]},T.name)})}),m&&a(l,{marginTop:1,children:c(s,{color:"red",bold:!0,children:["\u26A0 ",m]})}),c(l,{marginTop:1,children:[a(s,{color:h?S:void 0,bold:h,children:h?"\u279C ":" "}),a(l,{borderStyle:"round",borderColor:h?S:"gray",paddingX:2,children:a(s,{color:h?S:"gray",bold:h,children:"Continue \u2192"})})]}),a(l,{marginTop:1,children:a(s,{color:"gray",dimColor:!0,children:"\u2191/\u2193 navigate \u2022 Space/Enter toggle/select \u2022 Tab skip field"})})]})},ke=({currentVar:e,currentIndex:t,totalCount:o,onSubmit:r,onSkip:n})=>{let[i,p]=L(e.defaultValue||""),[u,m]=L(null);de(()=>{p(e.defaultValue||""),m(null)},[e.name]),J((d,y)=>{if(y.escape){if(e.required&&!i.trim()){m("This field is required and cannot be skipped");return}n()}});let f=d=>{if(e.required&&!d.trim()){m("This field is required");return}m(null),r(d)},g=!!e.defaultValue;return c(l,{flexDirection:"column",marginTop:1,paddingX:1,borderStyle:"round",borderColor:u?"red":S,children:[c(l,{justifyContent:"space-between",children:[a(s,{bold:!0,children:"Configure Environment Variables"}),c(s,{color:"gray",children:[t+1," / ",o]})]}),c(l,{marginTop:1,flexDirection:"column",children:[c(l,{children:[a(s,{color:S,bold:!0,children:e.name}),e.required?c(s,{color:"red",bold:!0,children:[" ","* required"]}):c(s,{color:"gray",dimColor:!0,children:[" ","(optional)"]})]}),c(l,{marginTop:1,children:[c(s,{color:"cyan",bold:!0,children:["Category:"," "]}),a(s,{color:"white",children:e.category})]}),c(l,{children:[c(s,{color:"cyan",bold:!0,children:["Purpose:"," "]}),a(s,{color:"white",children:e.description})]}),e.affectedFeatures&&c(l,{children:[c(s,{color:"cyan",bold:!0,children:["Affects:"," "]}),a(s,{color:"gray",children:e.affectedFeatures})]}),e.docsUrl&&c(l,{marginTop:1,children:[a(s,{color:"green",children:"\u{1F4D6} Docs: "}),a(s,{color:"blue",underline:!0,children:e.docsUrl})]}),g&&c(l,{marginTop:1,children:[c(s,{color:"green",bold:!0,children:["Default:"," "]}),a(s,{color:"white",children:e.defaultValue})]})]}),c(l,{marginTop:1,children:[a(s,{color:S,children:"\u279C "}),a(se,{value:i,onChange:d=>{p(d),u&&m(null)},onSubmit:f,placeholder:g?"Press Enter to use default":e.required?"Enter a value (required)":"Press Enter to skip"})]}),u&&a(l,{marginTop:1,children:c(s,{color:"red",bold:!0,children:["\u26A0 ",u]})}),a(l,{marginTop:1,flexDirection:"column",children:e.required?a(s,{color:"yellow",dimColor:!0,children:"\u21B5 Enter to confirm (required field)"}):g?a(s,{color:"green",dimColor:!0,children:"\u21B5 Enter to use default \u2022 ESC to skip"}):a(s,{color:"gray",dimColor:!0,children:"\u21B5 Enter to confirm \u2022 ESC to skip"})})]})},ze=({store:e})=>{let[t,o]=L(e.currentState);return de(()=>{let r=()=>o({...e.currentState});return e.on("change",r),()=>{e.off("change",r)}},[e]),c(pe,{status:t.status,step:t.step,children:[t.step==="Welcome"&&t.inputRequest?.id==="welcome"&&a(Ht,{onConfirm:()=>e.submitInput(!0)}),t.step==="Prerequisites"&&t.data.checks&&c(l,{flexDirection:"column",borderStyle:"round",paddingX:1,borderColor:S,children:[a(s,{bold:!0,children:"System Checks"}),c(l,{flexDirection:"column",marginTop:1,children:[a(Ee,{label:"Git",status:t.data.checks.git}),a(Ee,{label:"Docker",status:t.data.checks.docker}),a(Ee,{label:"Mise",status:t.data.checks.mise})]})]}),t.inputRequest?.id==="port_conflicts"&&t.data.portConflicts&&a(Wt,{portResults:t.data.portConflicts,onAccept:()=>e.submitInput("accept"),onAbort:()=>e.submitInput("abort")}),t.inputRequest?.id==="repo_path"&&a(Ut,{defaultValue:t.inputRequest.meta.default,onSubmit:r=>e.submitInput(r)}),t.step==="Repository Setup"&&c(l,{flexDirection:"column",borderStyle:"round",padding:1,borderColor:S,children:[a(s,{bold:!0,children:"Cloning Repository"}),c(l,{marginTop:1,flexDirection:"column",children:[a(Qe,{value:t.data.repoProgress||0}),t.data.repoPhase&&a(l,{marginTop:1,children:a(s,{color:"gray",children:t.data.repoPhase})})]})]}),t.inputRequest?.id==="setup_mode"&&a(Pe,{onSelect:r=>e.submitInput(r)}),t.inputRequest?.id==="env_method"&&a(De,{onSelect:r=>e.submitInput(r)}),t.inputRequest?.id==="env_infisical"&&a(Re,{onSubmit:r=>e.submitInput(r)}),t.step==="Environment Setup"&&t.inputRequest?.id==="env_var"&&t.data.currentEnvVar&&a(ke,{categories:t.data.envCategories||[],currentVar:t.data.currentEnvVar,currentIndex:t.data.envVarIndex||0,totalCount:t.data.envVarTotal||0,onSubmit:r=>e.submitInput(r),onSkip:()=>e.submitInput("")}),t.step==="Environment Setup"&&t.inputRequest?.id==="env_group"&&t.data.currentEnvGroup&&a(Be,{category:t.data.currentEnvGroup,currentIndex:t.data.envGroupIndex||0,totalGroups:t.data.envGroupTotal||0,onSubmit:r=>e.submitInput(r)}),t.step==="Environment Setup"&&t.inputRequest?.id==="env_alternatives"&&t.data.alternativeGroups&&a(Ae,{alternatives:t.data.alternativeGroups,onSubmit:(r,n)=>e.submitInput({selectedGroups:r,values:n})}),t.step==="Finished"&&a(Xt,{setupMode:t.data.setupMode,repoPath:t.data.repoPath,portOverrides:t.data.portOverrides,onConfirm:()=>e.submitInput(!0)}),(t.step==="Install Tools"||t.step==="Project Setup")&&a(Yt,{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&&a(l,{borderStyle:"single",borderColor:"red",padding:1,marginTop:2,children:c(s,{color:"red",children:["Error: ",t.error.message]})})]})};import{Spinner as Qt}from"@inkjs/ui";import{Box as G,Text as F,useInput as Kt}from"ink";import{useEffect as Jt,useState as zt}from"react";import{jsx as N,jsxs as A}from"react/jsx-runtime";var Ze=({store:e,command:t})=>{let[o,r]=zt(e.currentState);Jt(()=>{let i=()=>r({...e.currentState});return e.on("change",i),()=>{e.off("change",i)}},[e]),Kt((i,p)=>{(p.return||p.escape)&&(o.data.started||o.data.stopped||o.error)&&e.submitInput("exit")});let n=t==="start";return A(G,{flexDirection:"column",width:"100%",children:[N(ee,{}),(o.step==="Starting"||o.step==="Stopping")&&A(G,{flexDirection:"column",marginTop:1,paddingX:2,borderStyle:"round",borderColor:S,children:[N(Qt,{label:o.status||"Working..."}),o.data.repoPath&&N(G,{marginTop:1,children:A(F,{color:"gray",children:["Repository: ",o.data.repoPath]})}),o.data.setupMode&&N(G,{children:A(F,{color:"gray",children:["Mode: ",o.data.setupMode]})})]}),o.step==="Running"&&o.data.started&&A(G,{flexDirection:"column",marginTop:1,paddingX:2,paddingY:1,borderStyle:"round",borderColor:"green",children:[A(F,{color:"green",bold:!0,children:["\u2713"," GAIA is running!"]}),o.data.setupMode!=="developer"&&A(G,{marginTop:1,flexDirection:"column",children:[A(F,{children:["Web:"," ",A(F,{color:"cyan",bold:!0,children:["http://localhost:",o.data.webPort||3e3]})]}),A(F,{children:["API:"," ",A(F,{color:"cyan",bold:!0,children:["http://localhost:",o.data.apiPort||8e3]})]})]}),o.data.setupMode==="developer"&&A(G,{marginTop:1,flexDirection:"column",children:[N(F,{color:"gray",children:"Dev servers started in background."}),A(F,{color:"gray",children:["Logs: ",N(F,{color:S,children:"dev-start.log"})," in your repo root."]}),A(F,{color:"gray",children:["Run ",N(F,{color:S,children:"gaia stop"})," to shut down."]})]}),N(G,{marginTop:1,children:N(F,{dimColor:!0,children:"Press Enter to exit"})})]}),o.step==="Stopped"&&o.data.stopped&&A(G,{flexDirection:"column",marginTop:1,paddingX:2,paddingY:1,borderStyle:"round",borderColor:S,children:[A(F,{color:S,bold:!0,children:["\u2713"," All GAIA services stopped."]}),N(G,{marginTop:1,children:N(F,{dimColor:!0,children:"Press Enter to exit"})})]}),o.error&&A(G,{borderStyle:"single",borderColor:"red",padding:1,marginTop:2,children:[A(F,{color:"red",children:["Error: ",o.error.message]}),N(G,{marginTop:1,children:N(F,{dimColor:!0,children:"Press Enter to exit"})})]})]})};import{ProgressBar as Zt,Spinner as Fe}from"@inkjs/ui";import{Box as D,Text as w,useInput as et}from"ink";import{useEffect as er,useState as tr}from"react";import{jsx as b,jsxs as B}from"react/jsx-runtime";var tt=({store:e})=>{let[t,o]=tr(e.currentState);return er(()=>{let r=()=>o({...e.currentState});return e.on("change",r),()=>{e.off("change",r)}},[e]),B(pe,{status:t.status,step:t.step,steps:Ye,children:[t.step==="Detect Repo"&&B(D,{flexDirection:"column",paddingX:2,borderStyle:"round",borderColor:S,children:[b(w,{bold:!0,children:"Detecting GAIA Repository"}),b(D,{marginTop:1,children:b(Fe,{label:"Searching for repository..."})}),t.data.repoPath&&b(D,{marginTop:1,children:B(w,{color:"green",children:["Found: ",t.data.repoPath]})})]}),t.step==="Prerequisites"&&t.data.checks&&B(D,{flexDirection:"column",borderStyle:"round",paddingX:1,borderColor:S,children:[b(w,{bold:!0,children:"System Checks"}),B(D,{flexDirection:"column",marginTop:1,children:[b(_e,{label:"Git",status:t.data.checks.git}),b(_e,{label:"Docker",status:t.data.checks.docker}),b(_e,{label:"Mise",status:t.data.checks.mise})]})]}),t.inputRequest?.id==="port_conflicts"&&t.data.portConflicts&&b(rr,{portResults:t.data.portConflicts,onAccept:()=>e.submitInput("accept"),onAbort:()=>e.submitInput("abort")}),t.inputRequest?.id==="setup_mode"&&b(Pe,{onSelect:r=>e.submitInput(r)}),t.inputRequest?.id==="env_method"&&b(De,{onSelect:r=>e.submitInput(r)}),t.inputRequest?.id==="env_infisical"&&b(Re,{onSubmit:r=>e.submitInput(r)}),t.step==="Environment Setup"&&t.inputRequest?.id==="env_var"&&t.data.currentEnvVar&&b(ke,{categories:t.data.envCategories||[],currentVar:t.data.currentEnvVar,currentIndex:t.data.envVarIndex||0,totalCount:t.data.envVarTotal||0,onSubmit:r=>e.submitInput(r),onSkip:()=>e.submitInput("")}),t.step==="Environment Setup"&&t.inputRequest?.id==="env_group"&&t.data.currentEnvGroup&&b(Be,{category:t.data.currentEnvGroup,currentIndex:t.data.envGroupIndex||0,totalGroups:t.data.envGroupTotal||0,onSubmit:r=>e.submitInput(r)}),t.step==="Environment Setup"&&t.inputRequest?.id==="env_alternatives"&&t.data.alternativeGroups&&b(Ae,{alternatives:t.data.alternativeGroups,onSubmit:(r,n)=>e.submitInput({selectedGroups:r,values:n})}),t.step==="Project Setup"&&B(D,{flexDirection:"column",marginTop:1,paddingX:1,borderStyle:"round",borderColor:S,children:[b(D,{marginBottom:1,children:b(w,{bold:!0,color:S,children:"Project Setup"})}),B(D,{flexDirection:"column",gap:1,children:[b(D,{children:t.data.dependencyComplete?B(w,{color:"green",children:["\u2713"," ",t.data.dependencyPhase]}):b(Fe,{label:t.data.dependencyPhase||"Preparing..."})}),!t.data.dependencyComplete&&t.data.dependencyProgress>0&&b(D,{width:50,children:b(Zt,{value:t.data.dependencyProgress})}),!t.data.dependencyComplete&&t.data.dependencyLogs?.length>0&&b(D,{flexDirection:"column",marginTop:1,borderStyle:"single",borderColor:"gray",paddingX:1,minHeight:6,children:t.data.dependencyLogs.map((r,n)=>b(w,{color:"gray",wrap:"truncate",children:r},n))})]})]}),t.step==="Finished"&&b(or,{setupMode:t.data.setupMode,repoPath:t.data.repoPath,onConfirm:()=>e.submitInput(!0)}),t.error&&b(D,{borderStyle:"single",borderColor:"red",padding:1,marginTop:2,children:B(w,{color:"red",children:["Error: ",t.error.message]})})]})},_e=({label:e,status:t})=>B(D,{children:[b(D,{marginRight:1,children:t==="pending"?b(Fe,{type:"dots"}):t==="success"?b(w,{color:S,children:"\u2714"}):t==="error"?b(w,{color:"red",children:"\u2716"}):b(w,{color:"yellow",children:"\u26A0"})}),b(w,{children:e})]}),rr=({portResults:e,onAccept:t,onAbort:o})=>(et((r,n)=>{n.return?t():n.escape&&o()}),B(D,{flexDirection:"column",marginTop:1,paddingX:1,borderStyle:"round",borderColor:"yellow",children:[b(w,{bold:!0,color:"yellow",children:"Port Conflicts Detected"}),e.map(r=>B(D,{children:[B(w,{color:r.available?"green":"red",children:[r.available?"\u2714":"\u2716"," "]}),B(w,{children:[r.service," (:",r.port,")"]}),!r.available&&B(w,{color:"gray",children:[" ","- in use",r.usedBy?` by ${r.usedBy}`:"",r.alternative?` (alt: :${r.alternative})`:""]})]},r.port)),b(D,{marginTop:1,children:B(w,{children:[b(w,{color:"green",bold:!0,children:"Enter"})," continue ",b(w,{color:"yellow",bold:!0,children:"Escape"})," abort"]})})]})),or=({setupMode:e,repoPath:t,onConfirm:o})=>(et((i,p)=>{p.return&&o()}),B(D,{flexDirection:"column",marginTop:2,borderStyle:"round",borderColor:S,padding:1,children:[b(w,{color:S,bold:!0,children:"Setup Complete!"}),B(D,{marginTop:1,flexDirection:"column",children:[b(w,{bold:!0,children:"To start GAIA, run:"}),B(D,{marginTop:1,padding:1,borderStyle:"single",borderColor:"gray",flexDirection:"column",children:[B(w,{color:"cyan",children:["$ cd ",t||"."]}),b(w,{color:"cyan",children:"$ gaia start"})]}),b(D,{marginTop:1,children:b(w,{color:"gray",dimColor:!0,children:(e||"developer")==="selfhost"?"Runs: docker compose --profile all up -d (background)":"Runs: mise dev (interactive \u2014 keep terminal open)"})})]}),b(we,{}),b(D,{marginTop:1,children:b(w,{dimColor:!0,children:"Press Enter to exit"})})]}));import{Spinner as nr}from"@inkjs/ui";import{Box as k,Text as _,useInput as ar}from"ink";import{useEffect as rt,useState as ot}from"react";import{jsx as P,jsxs as M}from"react/jsx-runtime";var nt=({store:e})=>{let[t,o]=ot(e.currentState),[r,n]=ot(!1);return rt(()=>{let i=()=>o({...e.currentState});return e.on("change",i),()=>{e.off("change",i)}},[e]),rt(()=>{t.step==="Results"&&n(!1)},[t.step]),ar((i,p)=>{(p.return||p.escape)&&t.step==="Results"&&e.submitInput("exit"),i==="r"&&t.step==="Results"&&t.data.refreshable&&!r&&(n(!0),e.submitInput("refresh"))}),M(k,{flexDirection:"column",width:"100%",children:[P(ee,{}),t.step==="Checking"&&P(k,{marginTop:1,children:P(nr,{label:t.data.services?"Refreshing service health...":"Checking service health..."})}),t.step==="Results"&&t.data.services&&M(k,{flexDirection:"column",children:[M(k,{flexDirection:"column",borderStyle:"round",borderColor:S,paddingX:2,paddingY:1,children:[P(_,{bold:!0,color:S,children:"GAIA Service Status"}),M(k,{marginTop:1,flexDirection:"column",children:[M(k,{children:[P(k,{width:22,children:P(_,{bold:!0,children:"Service"})}),P(k,{width:10,children:P(_,{bold:!0,children:"Status"})}),P(k,{width:10,children:P(_,{bold:!0,children:"Latency"})})]}),P(_,{color:"gray",children:"\u2500".repeat(42)}),t.data.services.map(i=>M(k,{children:[P(k,{width:22,children:M(_,{children:[i.name," (:",i.port,")"]})}),P(k,{width:10,children:P(_,{color:i.status==="up"?"green":"red",bold:!0,children:i.status==="up"?"\u2713 UP":"\u2717 DOWN"})}),P(k,{width:10,children:P(_,{color:"gray",children:i.latency?`${i.latency}ms`:"--"})})]},i.name))]})]}),t.data.docker&&M(k,{flexDirection:"column",borderStyle:"round",borderColor:"gray",paddingX:2,paddingY:1,marginTop:1,children:[P(_,{bold:!0,children:"Docker Containers"}),M(_,{color:"gray",children:["Docker:"," ",t.data.docker.running?P(_,{color:"green",children:"Running"}):P(_,{color:"red",children:"Not running"})]}),t.data.docker.containers?.length>0&&P(k,{marginTop:1,flexDirection:"column",children:t.data.docker.containers.map(i=>M(k,{children:[M(_,{color:i.status==="running"?"green":"red",children:[i.status==="running"?"\u2713":"\u2717"," "]}),P(_,{children:i.name}),i.health&&M(_,{color:"gray",children:[" (",i.health,")"]})]},i.name))})]}),P(k,{marginTop:1,children:M(_,{dimColor:!0,children:["Press Enter or Escape to exit \xB7 Press"," ",P(_,{color:S,children:"r"})," to refresh"]})})]}),t.error&&P(k,{borderStyle:"single",borderColor:"red",padding:1,marginTop:2,children:M(_,{color:"red",children:["Error: ",t.error.message]})})]})};import{jsx as O,jsxs as ce}from"react/jsx-runtime";var sr=["init","setup","status","start","stop"],Le=class extends ir.Component{constructor(t){super(t),this.state={error:null}}static getDerivedStateFromError(t){return{error:t}}render(){return this.state.error?ce(me,{flexDirection:"column",padding:1,children:[O(z,{color:"red",bold:!0,children:"An unexpected error occurred:"}),O(z,{color:"red",children:this.state.error.message}),this.state.error.stack&&O(me,{marginTop:1,children:O(z,{color:"gray",dimColor:!0,children:this.state.error.stack})})]}):this.props.children}},cr=({store:e,command:t})=>{switch(t){case"init":return O(ze,{store:e});case"setup":return O(tt,{store:e});case"status":return O(nt,{store:e});case"start":case"stop":return O(Ze,{store:e,command:t});default:return ce(me,{flexDirection:"column",padding:1,children:[ce(z,{color:"red",children:["Unknown command: ",t]}),ce(me,{marginTop:1,flexDirection:"column",children:[O(z,{bold:!0,children:"Available commands:"}),sr.map(o=>ce(z,{children:[" ",O(z,{color:"cyan",children:o})]},o))]})]})}},$=({store:e,command:t})=>O(Le,{children:O(cr,{store:e,command:t})});import{EventEmitter as lr}from"events";var Me=class extends lr{state={step:"init",status:"",error:null,data:{},inputRequest:null};inputResolver=null;get currentState(){return this.state}setStep(t){this.state.step=t,this.emit("change",this.state)}setStatus(t){this.state.status=t,this.emit("change",this.state)}setError(t){this.state.error=t,t!==null&&this.inputResolver&&(this.inputResolver(null),this.inputResolver=null,this.state.inputRequest=null),this.emit("change",this.state)}updateData(t,o){this.state.data={...this.state.data,[t]:o},this.emit("change",this.state)}waitForInput(t,o){return this.state.inputRequest={id:t,meta:o},this.emit("change",this.state),new Promise(r=>{this.inputResolver=r})}submitInput(t){this.inputResolver&&(this.inputResolver(t),this.inputResolver=null,this.state.inputRequest=null,this.emit("change",this.state))}},j=()=>new Me;import*as ne from"fs";import*as ht from"path";import*as oe from"node:fs";import*as re from"node:path";import{execa as at}from"execa";var it={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/"}},st={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 Ne(e,t){return it[t][e]??st[t][e]}async function ct(e){let t=re.join(e,"apps/api/scripts/dump_config_schema.py"),o=re.join(e,"apps/api/app/config/settings_validator.py"),r=re.join(e,"apps/api/app/config/settings.py");if(!oe.existsSync(t))throw new Error("dump_config_schema.py not found in apps/api/scripts");try{try{let{stdout:n}=await at("python3",[t,o,r],{cwd:e});return JSON.parse(n)}catch{let{stdout:n}=await at("python",[t,o,r],{cwd:e});return JSON.parse(n)}}catch(n){throw new Error(`Failed to parse settings schema: ${n.message}. Ensure python is installed.`)}}function lt(e){let t=re.join(e,"apps","web",".env.local"),o=oe.existsSync(t)?t:re.join(e,"apps","web",".env");if(!oe.existsSync(o))return[];let r=oe.readFileSync(o,"utf-8"),n=[],i="General";for(let p of r.split(`
3
- `)){let u=p.trim();if(u.startsWith("#")&&!u.startsWith("#=")){let d=u.replace(/^#+\s*/,"").trim();d&&!d.startsWith("These are")&&(i=d);continue}if(!u||u.startsWith("#"))continue;let m=u.indexOf("=");if(m===-1)continue;let f=u.substring(0,m).trim(),g=u.substring(m+1).trim();n.push({name:f,value:g,category:i})}return n}function ut(e,t){let o=t?.[8e3]??8e3,r=t?.[3e3]??3e3,n={NEXT_PUBLIC_API_BASE_URL:`http://localhost:${o}/api/v1/`,NEXT_PUBLIC_WS_URL:`ws://localhost:${o}/api/v1/`};return r!==3e3&&(n.NEXT_PUBLIC_APP_URL=`http://localhost:${r}`),n}function pt(e,t){for(let[o,r]of Object.entries(t)){let n=Number(o);for(let[i,p]of Object.entries(e)){let u=new RegExp(`:${n}(?=[/\\s]|$)`,"g");e[i]=p.replaceAll(u,`:${r}`)}}}function dt(e,t){return e.map(o=>({...o,variables:o.variables.map(r=>{let n=Ne(r.name,t);return{...r,defaultValue:n||r.defaultValue}})}))}function Ge(){return Object.keys(it.selfhost)}function mt(e){return{...st[e]}}import*as U from"fs";import*as Oe from"path";function ft(e){U.existsSync(e)&&U.copyFileSync(e,`${e}.bak`)}function gt(e,t){let o=Oe.join(e,".env");ft(o);let r=["# 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","MEM0","E2B","DODO","NEXT_PUBLIC","GAIA"];function i(u){for(let f of n)if(u===f||u.startsWith(`${f}_`))return f;let m=u.split("_");return m.length===1?"Core":m[0]||"Core"}let p=new Map;for(let[u,m]of Object.entries(t)){let f=i(u);p.has(f)||p.set(f,[]);let d=/[\s#"'\\]/.test(m)||m===""?`"${m.replace(/\\/g,"\\\\").replace(/"/g,'\\"')}"`:m;p.get(f).push(`${u}=${d}`)}for(let[u,m]of p.entries())r.push(`# ${u} Configuration`),r.push(...m),r.push("");U.writeFileSync(o,r.join(`
4
- `),"utf-8")}function xt(e,t,o){let r=Oe.join(e,"apps","web",".env.local");ft(r);let n=lt(e),i=ut(t,o),p=["# GAIA Web App Environment Configuration","# Generated by GAIA CLI",`# Created: ${new Date().toISOString()}`,""],u=new Map;for(let m of n){u.has(m.category)||u.set(m.category,[]);let f=i[m.name]??m.value;u.get(m.category).push({name:m.name,value:f})}if(n.length===0){p.push("# Core URLs");for(let[m,f]of Object.entries(i))p.push(`${m}=${f}`);p.push("")}else for(let[m,f]of u.entries()){p.push(`# ${m}`);for(let{name:g,value:d}of f)p.push(`${g}=${d}`);p.push("")}U.writeFileSync(r,p.join(`
5
- `),"utf-8")}var dr=e=>new Promise(t=>setTimeout(t,e));async function fe(e,t,o){e.setStep("Environment Setup"),e.setStatus("Configuring environment...");let r=await e.waitForInput("setup_mode");e.updateData("setupMode",r),e.setStatus("Configuring environment variables...");let n=await e.waitForInput("env_method"),i={};i.ENV=r==="selfhost"?"production":"development";let p=Ge();for(let m of p){let f=Ne(m,r);f&&(i[m]=f)}let u=mt(r);for(let[m,f]of Object.entries(u))i[m]=f;if(n==="infisical")await mr(e,i),e.setStatus("Infisical credentials saved. Ensure your Infisical project contains all required variables.");else try{await fr(e,t,i,r)}catch(m){e.setError(m);return}o&&pt(i,o);try{await gr(e,t,i,r,o)}catch(m){e.setError(m);return}await dr(1e3)}async function mr(e,t){e.setStatus("Configuring Infisical...");let o=await e.waitForInput("env_infisical");t.INFISICAL_PROJECT_ID=o.INFISICAL_PROJECT_ID,t.INFISICAL_MACHINE_IDENTITY_CLIENT_ID=o.INFISICAL_MACHINE_IDENTITY_CLIENT_ID,t.INFISICAL_MACHINE_IDENTITY_CLIENT_SECRET=o.INFISICAL_MACHINE_IDENTITY_CLIENT_SECRET}async function fr(e,t,o,r){e.setStatus("Parsing environment variables...");let n;try{n=await ct(t),n=dt(n,r)}catch(x){throw new Error(`Failed to parse settings: ${x.message}`)}let i=new Set,p=[],u=new Set;for(let x of n)if(x.alternativeGroup&&!u.has(x.name)){let v=n.find(T=>T.name===x.alternativeGroup);v&&(p.push([x,v]),i.add(x.name),i.add(v.name),u.add(x.name),u.add(v.name))}let m=n.filter(x=>x.variables.length===1&&!i.has(x.name)),f=n.filter(x=>x.variables.length>1&&!i.has(x.name));for(let x of p){e.updateData("alternativeGroups",x),e.setStatus("Choose an AI provider...");let v=await e.waitForInput("env_alternatives");for(let[T,C]of Object.entries(v.values))C&&(o[T]=C)}let g=Ge(),y=[...m.flatMap(x=>x.variables).filter(x=>!g.includes(x.name))].sort((x,v)=>x.required&&!v.required?-1:!x.required&&v.required?1:0);e.updateData("envVarTotal",y.length);for(let x=0;x<y.length;x++){let v=y[x];if(!v)continue;e.updateData("currentEnvVar",v),e.updateData("envVarIndex",x),e.setStatus(`Configuring ${v.name}...`);let T=await e.waitForInput("env_var",{varName:v.name});(T||v.required||v.defaultValue)&&(o[v.name]=T||v.defaultValue||"")}let h=[...f].filter(x=>!x.variables.every(v=>g.includes(v.name))).sort((x,v)=>{let T=x.variables.some(I=>I.required),C=v.variables.some(I=>I.required);return T&&!C?-1:!T&&C?1:0});e.updateData("envGroupTotal",h.length);for(let x=0;x<h.length;x++){let v=h[x];if(!v)continue;e.updateData("currentEnvGroup",v),e.updateData("envGroupIndex",x),e.setStatus(`Configuring ${v.name}...`);let T=await e.waitForInput("env_group",{groupName:v.name});for(let[C,I]of Object.entries(T)){let E=v.variables.find(V=>V.name===C);(I||E?.required||E?.defaultValue)&&(o[C]=I||E?.defaultValue||"")}}}async function gr(e,t,o,r,n){e.setStatus("Writing API environment file...");try{let i=ht.join(t,"apps","api");gt(i,o),e.setStatus("API environment variables configured!")}catch(i){throw new Error(`Failed to write API .env file: ${i.message}`)}e.setStatus("Writing web environment file...");try{xt(t,r,n),e.setStatus("Web environment variables configured!")}catch(i){throw new Error(`Failed to write web .env file: ${i.message}`)}}import{execa as xr}from"execa";import ge from"fs";import hr from"simple-git";async function St(e,t,o){if(ge.existsSync(e)){let r=`${e}/.git`;if(!ge.existsSync(r))throw new Error(`Directory ${e} exists but is not a git repository`);await hr().cwd(e).pull(),o(100,"Already exists, pulled latest")}else try{let r=xr("git",["clone","--progress",t,e]);r.stderr?.on("data",n=>{let i=n.toString();i.includes("Counting objects")?o(5,"Counting objects"):i.includes("Compressing objects")&&o(10,"Compressing objects");let p=i.match(/Receiving objects:\s+(\d+)%\s+\((\d+)\/(\d+)\)/);if(p?.[1]){let m=Math.min(100,parseInt(p[1],10)),f=p[2],g=p[3];o(10+Math.floor(m*.5),`Receiving objects: ${f}/${g}`)}let u=i.match(/Resolving deltas:\s+(\d+)%\s+\((\d+)\/(\d+)\)/);if(u?.[1]){let m=Math.min(100,parseInt(u[1],10)),f=u[2],g=u[3];o(60+Math.floor(m*.4),`Resolving deltas: ${f}/${g}`)}}),await r,o(100,"Clone complete")}catch(r){throw ge.existsSync(e)&&ge.rmSync(e,{recursive:!0,force:!0}),r}}import{execa as X}from"execa";var yr={8e3:"API Server",5432:"PostgreSQL",6379:"Redis",27017:"MongoDB",5672:"RabbitMQ",3e3:"Web Frontend",8080:"ChromaDB",8083:"Mongo Express"};async function xe(){try{return await X("git",["--version"]),"success"}catch{return"error"}}async function he(){try{return await X("docker",["info"]),"success"}catch{return"error"}}async function Se(){try{return await X("mise",["--version"]),"success"}catch{return"missing"}}async function ye(){if((await import("node:os")).platform()==="win32")try{return await X("powershell",["-Command","irm https://mise.jdx.dev/install.ps1 | iex"]),!0}catch{return!1}try{return await X("sh",["-c","curl https://mise.jdx.dev/install.sh | sh"]),!0}catch{return!1}}async function be(e){let t=await import("node:net"),o=[],r=n=>new Promise(i=>{let p=t.createServer();p.once("error",()=>i(!1)),p.once("listening",()=>{p.close(()=>i(!0))}),p.listen(n)});for(let n of e){let i=yr[n]||`Port ${n}`;if(await r(n))o.push({port:n,service:i,available:!0});else{let u=await br(n),m=await vr(n+1,n+100,r);o.push({port:n,service:i,available:!1,usedBy:u,alternative:m||void 0})}}return o}async function br(e){if((await import("node:os")).platform()==="win32"){try{let{stdout:r}=await X("netstat",["-ano","-p","TCP"]),n=r.trim().split(`
6
- `);for(let i of n)if(i.includes(`:${e}`)&&i.includes("LISTENING")){let p=i.trim().split(/\s+/),u=p[p.length-1];if(u)try{let{stdout:m}=await X("tasklist",["/FI",`PID eq ${u}`,"/FO","CSV","/NH"]);return m.trim().split(",")[0]?.replace(/"/g,"")||`PID ${u}`}catch{return`PID ${u}`}}}catch{}return}try{let{stdout:r}=await X("lsof",["-i",`:${e}`,"-sTCP:LISTEN","-P","-n"]),n=r.trim().split(`
7
- `);if(n.length>1)return n[1]?.split(/\s+/)?.[0]||void 0}catch{}}async function vr(e,t,o){for(let r=e;r<=t;r++)if(await o(r))return r;return null}import*as W from"fs";import*as H from"path";var Tr=e=>new Promise(t=>setTimeout(t,e)),Cr="dev-start.log";async function bt(e,t,o){if(t==="selfhost"){o?.("Starting all services in Docker (selfhost mode)...");let r=H.join(e,"infra/docker");await q("docker",["compose","-f","docker-compose.prod.yml","--profile","backend","--profile","web","up","-d","--build","--remove-orphans"],r),o?.("All services started in Docker!")}else{o?.("Starting development servers...");let{spawn:r}=await import("child_process"),n=H.join(e,Cr),i=W.openSync(n,"a"),p;try{p=r("mise",["dev"],{cwd:e,stdio:["ignore",i,i],detached:!0,shell:!0}),p.unref()}finally{W.closeSync(i)}if(await Tr(1500),p.pid!=null)try{process.kill(p.pid,0)}catch{throw new Error(`Development servers crashed on startup. Check logs at: ${n}`)}o?.(`Development servers started! Logs: ${n}`)}}async function vt(e,t,o){let r=H.join(e,"infra/docker"),n=await qe(e);t?.("Stopping Docker services...");try{await q("docker",n==="selfhost"?["compose","-f","docker-compose.prod.yml","down"]:["compose","down"],r)}catch{}t?.("Stopping local processes...");try{let i=o?.[8e3]??8e3,p=o?.[3e3]??3e3;if(process.platform==="win32")for(let u of[i,p])try{await q("powershell",["-Command",`Get-NetTCPConnection -LocalPort ${u} -ErrorAction SilentlyContinue | ForEach-Object { Stop-Process -Id $_.OwningProcess -Force -ErrorAction SilentlyContinue }`],e)}catch{}else for(let u of[i,p])try{await q("sh",["-c",`lsof -ti :${u} -sTCP:LISTEN | xargs kill 2>/dev/null || true`],e)}catch{}}catch{}t?.("All services stopped.")}async function qe(e){let t=H.join(e,"apps","api",".env");if(!W.existsSync(t))return null;let o=W.readFileSync(t,"utf-8"),r=o.match(/^SETUP_MODE=(.+)$/m);if(r?.[1]){let n=r[1].trim().replace(/^["']|["']$/g,"");if(n==="selfhost"||n==="developer")return n}return o.includes("mongodb://mongo:")?"selfhost":(o.includes("mongodb://localhost:"),"developer")}async function q(e,t,o,r,n){let{spawn:i}=await import("child_process");return new Promise((p,u)=>{let m=i(e,t,{cwd:o,stdio:["ignore","pipe","pipe"],shell:!0}),f="",g=0;m.stdout?.on("data",d=>{let y=d.toString();f+=y,n?.(y),g=Math.min(g+5,95),r?.(g)}),m.stderr?.on("data",d=>{let y=d.toString();f+=y,n?.(y),g=Math.min(g+5,95),r?.(g)}),m.on("close",d=>{d===0?(r?.(100),p()):u(new Error(`Command failed with code ${d}: ${f.slice(-500)}`))}),m.on("error",d=>{u(d)})})}function Y(e){let t=e||process.cwd();for(;t!==H.dirname(t);){if(W.existsSync(H.join(t,"apps/api/app/config/settings_validator.py")))return t;t=H.dirname(t)}return null}var Ir=process.env.GAIA_CLI_DEV==="true",Q=e=>new Promise(t=>setTimeout(t,e));async function Tt(e){e.setStep("Welcome"),e.setStatus("Waiting for user input..."),await e.waitForInput("welcome");let t=d=>{let y=e.currentState.data.dependencyLogs||[],h=d.split(`
8
- `).filter(v=>v.trim()!==""),x=[...y,...h].slice(-20);e.updateData("dependencyLogs",x)};e.setStep("Prerequisites"),e.setStatus("Checking system requirements..."),e.updateData("checks",{git:"pending",docker:"pending",mise:"pending"}),await Q(800),e.setStatus("Checking Git...");let o=await xe();e.updateData("checks",{...e.currentState.data.checks,git:o}),e.setStatus("Checking Docker...");let r=await he();e.updateData("checks",{...e.currentState.data.checks,docker:r}),e.setStatus("Checking Mise...");let n=await Se();e.updateData("checks",{...e.currentState.data.checks,mise:n}),n==="missing"&&(e.setStatus("Installing Mise..."),n=await ye()?"success":"error",e.updateData("checks",{...e.currentState.data.checks,mise:n}));let i=[];if(o==="error"&&i.push("Git"),r==="error"&&i.push("Docker"),n==="error"&&i.push("Mise"),i.length>0){e.setError(new Error(`Prerequisites failed: ${i.join(", ")} ${i.length===1?"is":"are"} not installed or not working. Please install and try again.`));return}e.setStatus("Checking Ports...");let u=await be([8e3,5432,6379,27017,5672,3e3,8080,8083]),m={},f=u.filter(d=>!d.available);if(f.length>0){let d=f.filter(h=>!h.alternative);if(d.length>0){e.setError(new Error(`Cannot find free alternative ports for: ${d.map(h=>`${h.port} (${h.service})`).join(", ")}. Free these ports and try again.`));return}if(e.updateData("portConflicts",u),await e.waitForInput("port_conflicts")==="abort"){e.setError(new Error("Port conflicts not resolved. Please free the ports and try again."));return}for(let h of u)!h.available&&h.alternative&&(m[h.port]=h.alternative)}e.updateData("portOverrides",m),e.setStatus("Prerequisites check complete!"),await Q(1e3);let g="";if(Ir){if(g=Y()||"",!g){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 Q(500),e.setStatus("Repository ready!")}else{for(e.setStep("Repository Setup");;){if(g=await e.waitForInput("repo_path",{default:"./gaia"}),ne.existsSync(g)){if(!ne.statSync(g).isDirectory()){e.setError(new Error(`Path ${g} exists and is not a directory.`)),await Q(2e3),e.setError(null);continue}if(ne.readdirSync(g).length>0){e.setError(new Error(`Directory ${g} is not empty. Please choose another path.`)),await Q(2e3),e.setError(null);continue}}break}e.setStep("Repository Setup"),e.setStatus("Preparing repository..."),e.updateData("repoProgress",0),e.updateData("repoPhase","");try{await St(g,"https://github.com/theexperiencecompany/gaia.git",(d,y)=>{e.updateData("repoProgress",d),y?(e.updateData("repoPhase",y),e.setStatus(`${y}...`)):e.setStatus(`Cloning repository to ${g}... ${d}%`)}),e.setStatus("Repository ready!")}catch(d){e.setError(d);return}}await Q(1e3),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 q("mise",["trust"],g,void 0,t),e.updateData("dependencyProgress",50),e.updateData("dependencyPhase","Installing tools (node, python, uv, nx)..."),await q("mise",["install"],g,d=>{e.updateData("dependencyProgress",50+d*.5)},t),e.updateData("dependencyProgress",100),e.updateData("toolComplete",!0)}catch(d){e.setError(new Error(`Failed to install tools: ${d.message}`));return}if(await Q(1e3),await fe(e,g,m),!e.currentState.error){e.setStep("Project Setup"),e.updateData("dependencyPhase","Setting up project..."),e.updateData("dependencyProgress",0),e.updateData("dependencyComplete",!1),e.updateData("repoPath",g),e.updateData("dependencyLogs",[]);try{e.updateData("dependencyProgress",0),e.updateData("dependencyPhase","Running mise setup (all dependencies)..."),await q("mise",["setup"],g,d=>{e.updateData("dependencyProgress",d)},t),e.updateData("dependencyProgress",100),e.updateData("dependencyPhase","Setup complete!"),e.updateData("dependencyComplete",!0)}catch(d){e.setError(new Error(`Failed to setup project: ${d.message}`));return}await Q(1e3),e.setStep("Finished"),e.setStatus("Setup complete!")}}async function Ct(){let e=j(),{unmount:t}=Er(wr.createElement($,{store:e,command:"init"}));try{await Tt(e)}catch(o){e.setError(o)}e.currentState.error&&await e.waitForInput("exit"),t(),process.exit(e.currentState.error?1:0)}import{render as Pr}from"ink";import Dr from"react";var ve=e=>new Promise(t=>setTimeout(t,e));async function It(e){e.setStep("Detect Repo"),e.setStatus("Looking for GAIA repository...");let t=Y();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}e.updateData("repoPath",t),e.setStatus(`Found repository at ${t}`),await ve(1e3),e.setStep("Prerequisites"),e.setStatus("Checking system requirements..."),e.updateData("checks",{git:"pending",docker:"pending",mise:"pending"}),await ve(500);let o=await xe();e.updateData("checks",{...e.currentState.data.checks,git:o});let r=await he();e.updateData("checks",{...e.currentState.data.checks,docker:r});let n=await Se();e.updateData("checks",{...e.currentState.data.checks,mise:n}),n==="missing"&&(e.setStatus("Installing Mise..."),n=await ye()?"success":"error",e.updateData("checks",{...e.currentState.data.checks,mise:n}));let i=[];if(o==="error"&&i.push("Git"),r==="error"&&i.push("Docker"),n==="error"&&i.push("Mise"),i.length>0){e.setError(new Error(`Prerequisites failed: ${i.join(", ")} ${i.length===1?"is":"are"} not installed or not working. Please install and try again.`));return}e.setStatus("Checking Ports...");let u=await be([8e3,5432,6379,27017,5672,3e3,8080,8083]),m={},f=u.filter(d=>!d.available);if(f.length>0){let d=f.filter(h=>!h.alternative);if(d.length>0){e.setError(new Error(`Cannot find free alternative ports for: ${d.map(h=>`${h.port} (${h.service})`).join(", ")}. Free these ports and try again.`));return}if(e.updateData("portConflicts",u),await e.waitForInput("port_conflicts")==="abort"){e.setError(new Error("Port conflicts not resolved. Please free the ports and try again."));return}for(let h of u)!h.available&&h.alternative&&(m[h.port]=h.alternative)}if(e.updateData("portOverrides",m),e.setStatus("Prerequisites check complete!"),await ve(1e3),await fe(e,t,m),e.currentState.error)return;e.setStep("Project Setup"),e.updateData("dependencyPhase","Setting up project..."),e.updateData("dependencyProgress",0),e.updateData("dependencyComplete",!1),e.updateData("dependencyLogs",[]);let g=d=>{let y=e.currentState.data.dependencyLogs||[],h=d.split(`
9
- `).filter(v=>v.trim()!==""),x=[...y,...h].slice(-20);e.updateData("dependencyLogs",x)};try{e.updateData("dependencyPhase","Trusting mise configuration..."),await q("mise",["trust"],t,void 0,g),e.updateData("dependencyProgress",20),e.updateData("dependencyPhase","Installing tools..."),await q("mise",["install"],t,d=>{e.updateData("dependencyProgress",20+d*.3)},g),e.updateData("dependencyPhase","Running mise setup..."),await q("mise",["setup"],t,d=>{e.updateData("dependencyProgress",50+d*.5)},g),e.updateData("dependencyProgress",100),e.updateData("dependencyPhase","Setup complete!"),e.updateData("dependencyComplete",!0)}catch(d){e.setError(new Error(`Failed to setup project: ${d.message}`));return}await ve(1e3),e.setStep("Finished"),e.setStatus("Setup complete!")}async function Et(){let e=j(),{unmount:t}=Pr(Dr.createElement($,{store:e,command:"setup"}));try{await It(e)}catch(o){e.setError(o)}e.currentState.error&&await e.waitForInput("exit"),t(),process.exit(e.currentState.error?1:0)}import{render as Rr}from"ink";import Br from"react";async function wt(e){e.setStep("Starting"),e.setStatus("Locating GAIA repository...");let t=Y();if(!t){e.setError(new Error("Could not find GAIA repository. Run from within a cloned gaia repo."));return}e.updateData("repoPath",t);let o=await qe(t);if(!o){e.setError(new Error("No .env file found. Run 'gaia setup' first to configure the environment."));return}e.updateData("setupMode",o),e.setStatus(`Starting GAIA in ${o} mode...`);try{await bt(t,o,r=>{e.setStatus(r)}),e.setStep("Running"),e.setStatus("GAIA is running!"),e.updateData("started",!0)}catch(r){e.setError(new Error(`Failed to start services: ${r.message}`));return}await e.waitForInput("exit")}async function Pt(){let e=j(),{unmount:t}=Rr(Br.createElement($,{store:e,command:"start"}));await new Promise(o=>setTimeout(o,50));try{await wt(e)}catch(o){e.setError(o)}e.currentState.error&&await e.waitForInput("exit"),t(),process.exit(e.currentState.error?1:0)}import{render as Lr}from"ink";import Mr from"react";import{execa as je}from"execa";var $e=["gaia-backend","gaia-web","chromadb","postgres","redis","mongo","rabbitmq","arq_worker"];async function Dt(){try{let{stdout:e}=await je("docker",["inspect","--format","{{.Name}}|{{.State.Status}}|{{if .State.Health}}{{.State.Health.Status}}{{else}}none{{end}}",...$e]),t=new Map;for(let o of e.trim().split(`
10
- `)){if(!o)continue;let[r,n,i]=o.split("|"),p=r?.replace(/^\//,"")??"";t.set(p,{name:p,status:n==="running"?"running":"stopped",health:i!=="none"?i:void 0})}return $e.map(o=>t.get(o)??{name:o,status:"not_found"})}catch{let e=$e.map(async t=>{try{let{stdout:o}=await je("docker",["inspect","--format","{{.State.Status}}|{{if .State.Health}}{{.State.Health.Status}}{{else}}none{{end}}",t]),[r,n]=o.trim().split("|");return{name:t,status:r==="running"?"running":"stopped",health:n!=="none"?n:void 0}}catch{return{name:t,status:"not_found"}}});return Promise.all(e)}}async function Rt(){try{return await je("docker",["info"]),!0}catch{return!1}}var Ar=[{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 Bt(e){let o=Ar.map(r=>({...r,port:e?.[r.port]??r.port})).map(r=>r.type==="http"?kr(r.name,r.port,r.path):_r(r.name,r.port));return Promise.all(o)}async function kr(e,t,o){let r=Date.now();try{let n=await fetch(`http://localhost:${t}${o}`,{signal:AbortSignal.timeout(5e3)}),i=Date.now()-r;return{name:e,port:t,status:"up",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 _r(e,t){let o=await import("node:net"),r=Date.now();return new Promise(n=>{let i=new o.Socket;i.setTimeout(3e3),i.on("connect",()=>{let p=Date.now()-r;i.destroy(),n({name:e,port:t,status:"up",latency:p})}),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 At(){return await Rt()?{running:!0,containers:await Dt()}:{running:!1,containers:[]}}async function Fr(e){e.setStep("Checking"),e.setStatus("Checking service health..."),e.updateData("refreshable",!1);let[t,o]=await Promise.all([Bt(),At()]);e.updateData("services",t),e.updateData("docker",o);let r=t.filter(i=>i.status==="up").length,n=t.length;e.setStep("Results"),e.setStatus(`${r}/${n} services running`),e.updateData("refreshable",!0)}async function kt(e){for(;await Fr(e),await e.waitForInput("exit_or_refresh")==="refresh";);}async function _t(){let e=j(),{unmount:t}=Lr(Mr.createElement($,{store:e,command:"status"}));await new Promise(o=>setTimeout(o,50));try{await kt(e)}catch(o){e.setError(o)}e.currentState.error&&await e.waitForInput("exit"),t(),process.exit(e.currentState.error?1:0)}import{render as Nr}from"ink";import Gr from"react";async function Ft(e){e.setStep("Stopping"),e.setStatus("Locating GAIA repository...");let t=Y();if(!t){e.setError(new Error("Could not find GAIA repository. Run from within a cloned gaia repo."));return}e.updateData("repoPath",t);try{await vt(t,o=>{e.setStatus(o)}),e.setStep("Stopped"),e.setStatus("All services stopped."),e.updateData("stopped",!0)}catch(o){e.setError(new Error(`Failed to stop services: ${o.message}`));return}await e.waitForInput("exit")}async function Lt(){let e=j(),{unmount:t}=Nr(Gr.createElement($,{store:e,command:"stop"}));await new Promise(o=>setTimeout(o,50));try{await Ft(e)}catch(o){e.setError(o)}e.currentState.error&&await e.waitForInput("exit"),t(),process.exit(e.currentState.error?1:0)}var K=new Or;K.name("gaia").description("CLI tool for setting up and managing GAIA").version("0.1.0");K.command("init").description("Full setup from scratch (clone, configure, start)").action(async()=>{await Ct()});K.command("setup").description("Configure an existing GAIA repository").action(async()=>{await Et()});K.command("status").description("Check health of all GAIA services").action(async()=>{await _t()});K.command("start").description("Start GAIA services").action(async()=>{await Pt()});K.command("stop").description("Stop all GAIA services").action(async()=>{await Lt()});process.argv.slice(2).length||(K.outputHelp(),process.exit(0));K.parse();
2
+ import{Command as Vr}from"commander";import{render as kr}from"ink";import Br from"react";import{Box as ge,Text as Z}from"ink";import ur from"react";import{ProgressBar as ze,Select as Ze,Spinner as et}from"@inkjs/ui";import{Box as p,Text as s,useInput as z}from"ink";import ce from"ink-text-input";import{useEffect as fe,useState as L}from"react";import{Box as se,Text as Ke}from"ink";var h="#00bbff";import{Box as jt,Text as we}from"ink";import{jsx as Xe,jsxs as Qe}from"react/jsx-runtime";var Ye=({status:e,step:t})=>t.toLowerCase()==="welcome"?null:Qe(jt,{width:"100%",borderStyle:"single",borderColor:"gray",paddingX:1,justifyContent:"space-between",children:[Qe(we,{color:h,children:[Xe(we,{bold:!0,children:"Status:"})," ",t]}),Xe(we,{color:"white",dimColor:!0,children:e})]});import{Box as Ht}from"ink";import Vt from"ink-big-text";import Ut from"ink-gradient";import{jsx as Pe}from"react/jsx-runtime";var te=()=>Pe(Ht,{flexDirection:"column",marginTop:1,marginBottom:1,children:Pe(Ut,{colors:[h,"#b0eaff",h],children:Pe(Vt,{text:"GAIA",font:"3d"})})});import{jsx as re,jsxs as de}from"react/jsx-runtime";var Wt=["Welcome","Prerequisites","Repository Setup","Install Tools","Environment Setup","Project Setup","Finished"],Je=["Detect Repo","Prerequisites","Environment Setup","Project Setup","Finished"],Xt=({currentStep:e,steps:t})=>{let o=t.indexOf(e);return re(se,{marginBottom:1,children:t.map((r,n)=>{let i=r===e,c=o>n;return de(se,{marginRight:2,children:[de(Ke,{color:i?h:c?"green":"gray",children:[c?"\u2713 ":i?"\u25CF ":"\u25CB ",r]}),n<t.length-1&&re(Ke,{color:"gray",children:" \u203A "})]},r)})})},me=({children:e,status:t,step:o,steps:r=Wt})=>de(se,{flexDirection:"column",height:"100%",width:"100%",children:[de(se,{flexGrow:1,flexDirection:"column",children:[re(te,{}),re(Xt,{currentStep:o,steps:r}),re(se,{flexDirection:"column",flexGrow:1,children:e})]}),re(Ye,{status:t,step:o})]});import{Fragment as xo,jsx as a,jsxs as u}from"react/jsx-runtime";var Re=({label:e,status:t})=>u(p,{children:[a(p,{marginRight:1,children:t==="pending"?a(et,{type:"dots"}):t==="success"?a(s,{color:h,children:"\u2714"}):t==="error"?a(s,{color:"red",children:"\u2716"}):a(s,{color:"yellow",children:"\u26A0"})}),a(s,{children:e})]}),Qt=({onConfirm:e})=>(z((t,o)=>{o.return&&e()}),u(p,{flexDirection:"column",paddingX:2,borderStyle:"round",borderColor:h,children:[a(s,{bold:!0,children:"Welcome to the Interactive GAIA Setup"}),u(p,{flexDirection:"column",marginTop:1,marginBottom:1,children:[a(s,{children:"This wizard will guide you through the setup process:"}),a(s,{children:" 1. Check Prerequisites (Git, Docker, Mise)"}),a(s,{children:" 2. Clone Repository (from GitHub)"}),a(s,{children:" 3. Install Tools (node, python, uv via mise)"}),a(s,{children:" 4. Configure Env Vars (databases, API keys, etc.)"}),a(s,{children:" 5. Setup Project (install all dependencies)"})]}),a(s,{color:h,children:"Press Enter to start..."})]})),Yt=({portResults:e,onAccept:t,onAbort:o})=>{z((n,i)=>{i.return?t():i.escape&&o()});let r=e.filter(n=>!n.available);return u(p,{flexDirection:"column",marginTop:1,paddingX:1,borderStyle:"round",borderColor:"yellow",children:[a(p,{marginBottom:1,children:a(s,{bold:!0,color:"yellow",children:"Port Conflicts Detected"})}),e.map(n=>u(p,{children:[u(s,{color:n.available?"green":n.alternative?"yellow":"red",children:[n.available?"\u2714":n.alternative?"\u26A0":"\u2716"," "]}),u(s,{children:[n.service," (:",n.port,")"]}),!n.available&&u(s,{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)),u(p,{marginTop:1,flexDirection:"column",children:[r.some(n=>!n.alternative)&&a(p,{borderStyle:"single",borderColor:"red",paddingX:1,marginBottom:1,children:a(s,{color:"red",children:"Some ports have no available alternative. Free them and retry."})}),!r.some(n=>!n.alternative)&&r.some(n=>n.alternative)&&a(s,{color:"gray",children:"Alternative ports will be used for conflicting services."}),a(p,{marginTop:1,children:u(s,{children:[a(s,{color:"green",bold:!0,children:"Enter"})," to continue with alternatives ",a(s,{color:"yellow",bold:!0,children:"Escape"})," to abort"]})})]})]})},Kt=({defaultValue:e,onSubmit:t})=>{let[o,r]=L(e);return u(p,{flexDirection:"column",marginTop:1,paddingX:1,borderStyle:"round",borderColor:h,children:[a(s,{children:"Where should we clone the repository?"}),u(p,{children:[a(s,{color:h,children:"\u279C "}),a(ce,{value:o,onChange:r,onSubmit:t})]}),u(s,{color:"gray",children:["(Press Enter for default: ",e,")"]})]})},Jt=({setupMode:e,repoPath:t,portOverrides:o,onConfirm:r})=>{z((m,g)=>{g.return&&r()});let n=e||"developer",i=t||"./gaia",c=o?.[3e3]??3e3,d=o?.[8e3]??8e3;return u(p,{flexDirection:"column",marginTop:2,borderStyle:"round",borderColor:h,padding:1,children:[a(s,{color:h,bold:!0,children:"You are all set!"}),u(p,{marginTop:1,flexDirection:"column",children:[a(s,{bold:!0,children:"To start GAIA, run:"}),u(p,{marginTop:1,padding:1,borderStyle:"single",borderColor:"gray",flexDirection:"column",children:[u(s,{color:"cyan",children:["$ cd ",i]}),a(s,{color:"cyan",children:"$ gaia start"})]}),a(p,{marginTop:1,children:a(s,{color:"gray",dimColor:!0,children:n==="selfhost"?"Runs: docker compose --profile all up -d (background)":"Runs: mise dev (interactive \u2014 keep terminal open)"})})]}),u(p,{marginTop:1,flexDirection:"column",children:[a(s,{bold:!0,children:"Access GAIA at:"}),u(p,{marginLeft:2,flexDirection:"column",children:[u(s,{children:["Web:"," ",u(s,{color:"cyan",bold:!0,children:["http://localhost:",c]})]}),u(s,{children:["API:"," ",u(s,{color:"cyan",bold:!0,children:["http://localhost:",d]})]})]})]}),a(De,{}),a(p,{marginTop:1,children:a(s,{dimColor:!0,children:"Press Enter to exit"})})]})},De=()=>u(p,{marginTop:1,flexDirection:"column",children:[a(s,{bold:!0,children:"Available commands:"}),u(p,{marginLeft:2,flexDirection:"column",children:[u(s,{children:[u(s,{color:h,bold:!0,children:["gaia start"," "]}),a(s,{color:"gray",children:" Start all services"})]}),u(s,{children:[u(s,{color:h,bold:!0,children:["gaia stop"," "]}),a(s,{color:"gray",children:" Stop all services"})]}),u(s,{children:[a(s,{color:h,bold:!0,children:"gaia status"}),a(s,{color:"gray",children:" Check service health"})]}),u(s,{children:[u(s,{color:h,bold:!0,children:["gaia setup"," "]}),a(s,{color:"gray",children:" Reconfigure environment"})]})]})]}),zt=({phase:e,progress:t,isComplete:o,logs:r,title:n})=>u(p,{flexDirection:"column",marginTop:1,paddingX:1,borderStyle:"round",borderColor:h,children:[a(p,{marginBottom:1,children:a(s,{bold:!0,color:h,children:n||"Installing Dependencies"})}),u(p,{flexDirection:"column",gap:1,children:[a(p,{children:o?u(s,{color:"green",children:["\u2713 ",e]}):a(et,{label:e||"Preparing..."})}),!o&&t>0&&a(p,{width:50,children:a(ze,{value:t})}),!o&&r&&r.length>0&&a(p,{flexDirection:"column",marginTop:1,borderStyle:"single",borderColor:"gray",paddingX:1,paddingY:0,minHeight:6,children:r.map((i,c)=>a(s,{color:"gray",wrap:"truncate",children:i},c))})]})]});var ke=({onSelect:e})=>u(p,{flexDirection:"column",marginTop:1,paddingX:1,borderStyle:"round",borderColor:h,children:[a(s,{bold:!0,children:"Setup Mode"}),a(p,{marginTop:1,children:a(s,{color:"gray",children:"How do you want to run GAIA?"})}),a(p,{marginTop:1,children:a(Ze,{options:[{label:"Self-Host (Docker)",value:"selfhost"},{label:"Developer Mode (Local)",value:"developer"}],onChange:o=>e(o)})}),u(p,{marginTop:1,flexDirection:"column",children:[a(s,{color:"gray",dimColor:!0,children:"Self-Host: Run everything in Docker containers (recommended for deployment)"}),a(s,{color:"gray",dimColor:!0,children:"Developer: Run backend locally with Docker services (recommended for contributing)"})]})]}),Be=({onSelect:e})=>u(p,{flexDirection:"column",marginTop:1,paddingX:1,borderStyle:"round",borderColor:h,children:[a(s,{bold:!0,children:"Environment Variables Setup"}),a(p,{marginTop:1,children:a(s,{color:"gray",children:"Choose how you want to configure environment variables:"})}),a(p,{marginTop:1,children:a(Ze,{options:[{label:"Manual Setup (Recommended)",value:"manual"},{label:"Infisical (Advanced)",value:"infisical"}],onChange:o=>e(o)})}),u(p,{marginTop:1,flexDirection:"column",children:[a(s,{color:"gray",dimColor:!0,children:"Manual Setup: Configure variables interactively (recommended for most users)"}),a(s,{color:"gray",dimColor:!0,children:"Infisical: All secrets managed in Infisical dashboard (requires pre-configuration)"})]})]}),Ae=({onSubmit:e})=>{let[t,o]=L({INFISICAL_TOKEN:"",INFISICAL_PROJECT_ID:"",INFISICAL_MACHINE_IDENTITY_CLIENT_ID:"",INFISICAL_MACHINE_IDENTITY_CLIENT_SECRET:""}),[r,n]=L(0),[i,c]=L(null),d=[{key:"INFISICAL_TOKEN",description:"Service token from project settings (st.xxx...)"},{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"}];z((g,y)=>{if(y.tab||y.downArrow)n(x=>x<d.length-1?x+1:x);else if(y.upArrow)n(x=>x>0?x-1:x);else if(y.return){if(r<d.length-1){n(l=>l+1);return}let x=d.filter(l=>!t[l.key].trim());if(x.length>0){c(`Required: ${x.map(S=>S.key).join(", ")}`);let l=d.findIndex(S=>!t[S.key].trim());l>=0&&n(l);return}e(t)}});let m=d[r];return u(p,{flexDirection:"column",marginTop:1,paddingX:1,borderStyle:"round",borderColor:h,children:[a(p,{marginBottom:1,children:a(s,{bold:!0,color:h,children:"Infisical Configuration"})}),a(p,{marginBottom:1,borderStyle:"single",borderColor:"cyan",paddingX:1,children:a(s,{color:"cyan",children:"All environment variables (API keys, auth secrets, etc.) must be configured in your Infisical project. Only Infisical credentials will be stored locally."})}),u(p,{marginBottom:1,flexDirection:"column",children:[a(s,{color:"gray",children:"Configure your Infisical credentials."}),u(s,{color:"gray",dimColor:!0,children:["Visit"," ",a(s,{color:"cyan",underline:!0,children:"app.infisical.com"})," ","to get these values."]})]}),d.map((g,y)=>{let x=g.key.includes("SECRET")||g.key.includes("TOKEN");return u(p,{flexDirection:"column",marginBottom:1,children:[a(p,{children:u(s,{color:y===r?h:"white",children:[y===r?"\u25B8 ":" ",g.key,":"]})}),a(p,{marginLeft:2,children:a(s,{color:"gray",dimColor:!0,children:g.description})}),y===r?a(p,{marginLeft:2,children:a(ce,{value:t[g.key],onChange:l=>{o(S=>({...S,[g.key]:l})),c(null)},placeholder:"Enter value...",mask:x?"*":void 0})}):a(p,{marginLeft:2,children:a(s,{color:t[g.key]?"green":"gray",children:t[g.key]?x?`\u2713 ${"*".repeat(8)}`:`\u2713 ${t[g.key]}`:"(not set)"})})]},g.key)}),i&&a(p,{marginTop:1,children:a(s,{color:"red",children:i})}),a(p,{marginTop:1,children:a(s,{color:"gray",dimColor:!0,children:"\u2191\u2193/Tab to navigate \u2022 Enter to confirm"})})]})},_e=({category:e,currentIndex:t,totalGroups:o,onSubmit:r})=>{let[n,i]=L(()=>{let l={};for(let S of e.variables)l[S.name]=S.defaultValue||"";return l}),[c,d]=L(0),[m,g]=L(null);fe(()=>{let l={};for(let S of e.variables)l[S.name]=S.defaultValue||"";i(l),d(0),g(null)},[e.name]),z((l,S)=>{if(S.tab||S.downArrow)d(f=>f<e.variables.length-1?f+1:f);else if(S.upArrow)d(f=>f>0?f-1:f);else if(S.escape){let f=e.variables.filter(T=>T.required&&!n[T.name]?.trim());if(f.length>0){g(`Required fields cannot be skipped: ${f.map(T=>T.name).join(", ")}`);return}r(n)}});let y=()=>{if(c<e.variables.length-1)d(c+1);else{let l=e.variables.filter(S=>S.required&&!n[S.name]?.trim());if(l.length>0){g(`Required fields are missing: ${l.map(S=>S.name).join(", ")}`);return}g(null),r(n)}},x=e.variables.some(l=>l.required);return u(p,{flexDirection:"column",marginTop:1,paddingX:1,borderStyle:"round",borderColor:m?"red":h,children:[u(p,{justifyContent:"space-between",children:[u(s,{bold:!0,children:["Configure ",e.name]}),u(s,{color:"gray",children:["Group ",t+1," / ",o]})]}),u(p,{marginTop:1,flexDirection:"column",children:[u(p,{children:[u(s,{color:"cyan",bold:!0,children:["Purpose:"," "]}),a(s,{color:"white",children:e.description})]}),e.affectedFeatures&&u(p,{children:[u(s,{color:"cyan",bold:!0,children:["Affects:"," "]}),a(s,{color:"gray",children:e.affectedFeatures})]}),e.docsUrl&&u(p,{marginTop:1,children:[a(s,{color:"green",children:"\u{1F4D6} Docs: "}),a(s,{color:"blue",underline:!0,children:e.docsUrl})]})]}),a(p,{marginTop:1,flexDirection:"column",children:e.variables.map((l,S)=>{let f=S===c,T=!!l.defaultValue;return u(p,{flexDirection:"column",marginBottom:1,children:[u(p,{children:[u(s,{color:f?h:"gray",bold:f,children:[f?"\u279C ":" ",l.name]}),l.required&&u(s,{color:"red",bold:!0,children:[" ","*"]}),T&&!f&&u(s,{color:"gray",dimColor:!0,children:[" ","(default: ",l.defaultValue,")"]})]}),f&&a(p,{marginLeft:2,children:a(ce,{value:n[l.name]||"",onChange:v=>{i(C=>({...C,[l.name]:v})),m&&g(null)},onSubmit:y,placeholder:T?`Default: ${l.defaultValue}`:l.required?"Enter a value (required)":"Press Enter to skip"})})]},l.name)})}),m&&a(p,{marginTop:1,children:u(s,{color:"red",bold:!0,children:["\u26A0 ",m]})}),a(p,{marginTop:1,flexDirection:"column",children:u(s,{color:"gray",dimColor:!0,children:["\u21B5 Enter to next field \u2022 Tab/\u2193 move down \u2022 \u2191 move up",!x&&" \u2022 ESC skip group"]})})]})},Me=({alternatives:e,onSubmit:t})=>{let[o,r]=L(new Set),[n,i]=L({}),[c,d]=L(0),[m,g]=L(null);fe(()=>{let v={};for(let C of e)for(let I of C.variables)v[I.name]=I.defaultValue||"";i(v)},[e]);let y=[];for(let v=0;v<e.length;v++)if(y.push({type:"provider",categoryIndex:v}),o.has(v)){let C=e[v];if(C)for(let I=0;I<C.variables.length;I++)y.push({type:"field",categoryIndex:v,fieldIndex:I})}y.push({type:"submit"});let x=y[c],l=x?.type==="field",S=x?.type==="submit";z((v,C)=>{let I=Math.min(c,y.length-1);if(I!==c){d(I);return}if(l)C.upArrow?d(E=>Math.max(0,E-1)):(C.downArrow||C.tab)&&d(E=>Math.min(y.length-1,E+1));else if(S)C.upArrow?d(E=>Math.max(0,E-1)):(C.return||v===" ")&&T();else if(C.upArrow)d(E=>Math.max(0,E-1));else if(C.downArrow||C.tab)d(E=>Math.min(y.length-1,E+1));else if((C.return||v===" ")&&x?.type==="provider"){let E=x.categoryIndex;r(W=>{let D=new Set(W);return D.has(E)?D.delete(E):D.add(E),D}),m&&g(null)}});let f=()=>{m&&g(null),d(v=>Math.min(y.length-1,v+1))},T=()=>{let v=[],C={};for(let I of o){let E=e[I];if(!E)continue;if(E.variables.some(D=>n[D.name]?.trim())){v.push(E.name);for(let D of E.variables){let pe=n[D.name];pe&&(C[D.name]=pe)}}}if(v.length===0){o.size===0?g("Enable at least one provider (press Space or Enter)"):g("Enter a value for at least one field");return}t(v,C)};return u(p,{flexDirection:"column",marginTop:1,paddingX:1,borderStyle:"round",borderColor:m?"red":h,children:[u(p,{justifyContent:"space-between",children:[a(s,{bold:!0,children:"Configure AI Provider"}),a(s,{color:"yellow",children:"* At least one required"})]}),a(p,{marginTop:1,children:a(s,{color:"gray",children:"Enable and configure at least one AI provider below:"})}),a(p,{marginTop:1,flexDirection:"column",children:e.map((v,C)=>{let I=o.has(C),E=y.findIndex(D=>D.type==="provider"&&D.categoryIndex===C),W=c===E;return u(p,{flexDirection:"column",marginBottom:1,children:[u(p,{children:[a(s,{color:W?h:void 0,bold:W,children:W?"\u279C ":" "}),a(s,{color:I?"green":"gray",children:I?"[\u2714]":"[ ]"}),u(s,{color:I?h:"gray",bold:I,children:[" ",v.name]}),v.description&&u(s,{color:"gray",dimColor:!0,children:[" ","- ",v.description]})]}),W&&v.docsUrl&&u(p,{marginLeft:6,children:[a(s,{color:"yellow",children:"\u{1F4D6} "}),a(s,{color:"blue",underline:!0,children:v.docsUrl})]}),I&&a(p,{marginLeft:4,flexDirection:"column",marginTop:1,children:v.variables.map((D,pe)=>{let $t=y.findIndex(ie=>ie.type==="field"&&ie.categoryIndex===C&&ie.fieldIndex===pe),ee=c===$t,We=!!D.defaultValue,Ee=n[D.name]||"";return u(p,{flexDirection:"column",marginBottom:1,children:[u(p,{children:[u(s,{color:ee?h:"gray",bold:ee,children:[ee?" \u279C ":" ",D.name]}),!ee&&Ee&&a(s,{color:"green",children:" \u2713"}),!ee&&!Ee&&We&&u(s,{color:"gray",dimColor:!0,children:[" ","(default: ",D.defaultValue,")"]})]}),ee&&a(p,{marginLeft:4,children:a(ce,{value:Ee,onChange:ie=>{i(qt=>({...qt,[D.name]:ie})),m&&g(null)},onSubmit:f,placeholder:We?`Default: ${D.defaultValue}`:"Enter value..."})})]},D.name)})})]},v.name)})}),m&&a(p,{marginTop:1,children:u(s,{color:"red",bold:!0,children:["\u26A0 ",m]})}),u(p,{marginTop:1,children:[a(s,{color:S?h:void 0,bold:S,children:S?"\u279C ":" "}),a(p,{borderStyle:"round",borderColor:S?h:"gray",paddingX:2,children:a(s,{color:S?h:"gray",bold:S,children:"Continue \u2192"})})]}),a(p,{marginTop:1,children:a(s,{color:"gray",dimColor:!0,children:"\u2191/\u2193 navigate \u2022 Space/Enter toggle/select \u2022 Tab skip field"})})]})},Le=({currentVar:e,currentIndex:t,totalCount:o,onSubmit:r,onSkip:n})=>{let[i,c]=L(e.defaultValue||""),[d,m]=L(null);fe(()=>{c(e.defaultValue||""),m(null)},[e.name]),z((x,l)=>{if(l.escape){if(e.required&&!i.trim()){m("This field is required and cannot be skipped");return}n()}});let g=x=>{if(e.required&&!x.trim()){m("This field is required");return}m(null),r(x)},y=!!e.defaultValue;return u(p,{flexDirection:"column",marginTop:1,paddingX:1,borderStyle:"round",borderColor:d?"red":h,children:[u(p,{justifyContent:"space-between",children:[a(s,{bold:!0,children:"Configure Environment Variables"}),u(s,{color:"gray",children:[t+1," / ",o]})]}),u(p,{marginTop:1,flexDirection:"column",children:[u(p,{children:[a(s,{color:h,bold:!0,children:e.name}),e.required?u(s,{color:"red",bold:!0,children:[" ","* required"]}):u(s,{color:"gray",dimColor:!0,children:[" ","(optional)"]})]}),u(p,{marginTop:1,children:[u(s,{color:"cyan",bold:!0,children:["Category:"," "]}),a(s,{color:"white",children:e.category})]}),u(p,{children:[u(s,{color:"cyan",bold:!0,children:["Purpose:"," "]}),a(s,{color:"white",children:e.description})]}),e.affectedFeatures&&u(p,{children:[u(s,{color:"cyan",bold:!0,children:["Affects:"," "]}),a(s,{color:"gray",children:e.affectedFeatures})]}),e.docsUrl&&u(p,{marginTop:1,children:[a(s,{color:"green",children:"\u{1F4D6} Docs: "}),a(s,{color:"blue",underline:!0,children:e.docsUrl})]}),y&&u(p,{marginTop:1,children:[u(s,{color:"green",bold:!0,children:["Default:"," "]}),a(s,{color:"white",children:e.defaultValue})]})]}),u(p,{marginTop:1,children:[a(s,{color:h,children:"\u279C "}),a(ce,{value:i,onChange:x=>{c(x),d&&m(null)},onSubmit:g,placeholder:y?"Press Enter to use default":e.required?"Enter a value (required)":"Press Enter to skip"})]}),d&&a(p,{marginTop:1,children:u(s,{color:"red",bold:!0,children:["\u26A0 ",d]})}),a(p,{marginTop:1,flexDirection:"column",children:e.required?a(s,{color:"yellow",dimColor:!0,children:"\u21B5 Enter to confirm (required field)"}):y?a(s,{color:"green",dimColor:!0,children:"\u21B5 Enter to use default \u2022 ESC to skip"}):a(s,{color:"gray",dimColor:!0,children:"\u21B5 Enter to confirm \u2022 ESC to skip"})})]})},tt=({store:e})=>{let[t,o]=L(e.currentState);return fe(()=>{let r=()=>o({...e.currentState});return e.on("change",r),()=>{e.off("change",r)}},[e]),u(me,{status:t.status,step:t.step,children:[t.step==="Welcome"&&t.inputRequest?.id==="welcome"&&a(Qt,{onConfirm:()=>e.submitInput(!0)}),t.step==="Prerequisites"&&t.data.checks&&u(p,{flexDirection:"column",borderStyle:"round",paddingX:1,borderColor:h,children:[a(s,{bold:!0,children:"System Checks"}),u(p,{flexDirection:"column",marginTop:1,children:[a(Re,{label:"Git",status:t.data.checks.git}),a(Re,{label:"Docker",status:t.data.checks.docker}),a(Re,{label:"Mise",status:t.data.checks.mise})]})]}),t.inputRequest?.id==="port_conflicts"&&t.data.portConflicts&&a(Yt,{portResults:t.data.portConflicts,onAccept:()=>e.submitInput("accept"),onAbort:()=>e.submitInput("abort")}),t.inputRequest?.id==="repo_path"&&a(Kt,{defaultValue:t.inputRequest.meta.default,onSubmit:r=>e.submitInput(r)}),t.step==="Repository Setup"&&u(p,{flexDirection:"column",borderStyle:"round",padding:1,borderColor:h,children:[a(s,{bold:!0,children:"Cloning Repository"}),u(p,{marginTop:1,flexDirection:"column",children:[a(ze,{value:t.data.repoProgress||0}),t.data.repoPhase&&a(p,{marginTop:1,children:a(s,{color:"gray",children:t.data.repoPhase})})]})]}),t.inputRequest?.id==="setup_mode"&&a(ke,{onSelect:r=>e.submitInput(r)}),t.inputRequest?.id==="env_method"&&a(Be,{onSelect:r=>e.submitInput(r)}),t.inputRequest?.id==="env_infisical"&&a(Ae,{onSubmit:r=>e.submitInput(r)}),t.step==="Environment Setup"&&t.inputRequest?.id==="env_var"&&t.data.currentEnvVar&&a(Le,{categories:t.data.envCategories||[],currentVar:t.data.currentEnvVar,currentIndex:t.data.envVarIndex||0,totalCount:t.data.envVarTotal||0,onSubmit:r=>e.submitInput(r),onSkip:()=>e.submitInput("")}),t.step==="Environment Setup"&&t.inputRequest?.id==="env_group"&&t.data.currentEnvGroup&&a(_e,{category:t.data.currentEnvGroup,currentIndex:t.data.envGroupIndex||0,totalGroups:t.data.envGroupTotal||0,onSubmit:r=>e.submitInput(r)}),t.step==="Environment Setup"&&t.inputRequest?.id==="env_alternatives"&&t.data.alternativeGroups&&a(Me,{alternatives:t.data.alternativeGroups,onSubmit:(r,n)=>e.submitInput({selectedGroups:r,values:n})}),t.step==="Finished"&&a(Jt,{setupMode:t.data.setupMode,repoPath:t.data.repoPath,portOverrides:t.data.portOverrides,onConfirm:()=>e.submitInput(!0)}),(t.step==="Install Tools"||t.step==="Project Setup")&&a(zt,{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&&a(p,{borderStyle:"single",borderColor:"red",padding:1,marginTop:2,children:u(s,{color:"red",children:["Error: ",t.error.message]})})]})};import{Spinner as Zt}from"@inkjs/ui";import{Box as N,Text as M,useInput as er}from"ink";import{useEffect as tr,useState as rr}from"react";import{jsx as F,jsxs as B}from"react/jsx-runtime";var rt=({store:e,command:t})=>{let[o,r]=rr(e.currentState);tr(()=>{let i=()=>r({...e.currentState});return e.on("change",i),()=>{e.off("change",i)}},[e]),er((i,c)=>{(c.return||c.escape)&&(o.data.started||o.data.stopped||o.error)&&e.submitInput("exit")});let n=t==="start";return B(N,{flexDirection:"column",width:"100%",children:[F(te,{}),(o.step==="Starting"||o.step==="Stopping")&&B(N,{flexDirection:"column",marginTop:1,paddingX:2,borderStyle:"round",borderColor:h,children:[F(Zt,{label:o.status||"Working..."}),o.data.repoPath&&F(N,{marginTop:1,children:B(M,{color:"gray",children:["Repository: ",o.data.repoPath]})}),o.data.setupMode&&F(N,{children:B(M,{color:"gray",children:["Mode: ",o.data.setupMode]})})]}),o.step==="Running"&&o.data.started&&B(N,{flexDirection:"column",marginTop:1,paddingX:2,paddingY:1,borderStyle:"round",borderColor:"green",children:[B(M,{color:"green",bold:!0,children:["\u2713"," GAIA is running!"]}),o.data.setupMode!=="developer"&&B(N,{marginTop:1,flexDirection:"column",children:[B(M,{children:["Web:"," ",B(M,{color:"cyan",bold:!0,children:["http://localhost:",o.data.webPort||3e3]})]}),B(M,{children:["API:"," ",B(M,{color:"cyan",bold:!0,children:["http://localhost:",o.data.apiPort||8e3]})]})]}),o.data.setupMode==="developer"&&B(N,{marginTop:1,flexDirection:"column",children:[F(M,{color:"gray",children:"Dev servers started in background."}),B(M,{color:"gray",children:["Logs: ",F(M,{color:h,children:"dev-start.log"})," in your repo root."]}),B(M,{color:"gray",children:["Run ",F(M,{color:h,children:"gaia stop"})," to shut down."]})]}),F(N,{marginTop:1,children:F(M,{dimColor:!0,children:"Press Enter to exit"})})]}),o.step==="Stopped"&&o.data.stopped&&B(N,{flexDirection:"column",marginTop:1,paddingX:2,paddingY:1,borderStyle:"round",borderColor:h,children:[B(M,{color:h,bold:!0,children:["\u2713"," All GAIA services stopped."]}),F(N,{marginTop:1,children:F(M,{dimColor:!0,children:"Press Enter to exit"})})]}),o.error&&B(N,{borderStyle:"single",borderColor:"red",padding:1,marginTop:2,children:[B(M,{color:"red",children:["Error: ",o.error.message]}),F(N,{marginTop:1,children:F(M,{dimColor:!0,children:"Press Enter to exit"})})]})]})};import{ProgressBar as or,Spinner as Fe}from"@inkjs/ui";import{Box as R,Text as w,useInput as ot}from"ink";import{useEffect as nr,useState as ar}from"react";import{jsx as b,jsxs as k}from"react/jsx-runtime";var nt=({store:e})=>{let[t,o]=ar(e.currentState);return nr(()=>{let r=()=>o({...e.currentState});return e.on("change",r),()=>{e.off("change",r)}},[e]),k(me,{status:t.status,step:t.step,steps:Je,children:[t.step==="Detect Repo"&&k(R,{flexDirection:"column",paddingX:2,borderStyle:"round",borderColor:h,children:[b(w,{bold:!0,children:"Detecting GAIA Repository"}),b(R,{marginTop:1,children:b(Fe,{label:"Searching for repository..."})}),t.data.repoPath&&b(R,{marginTop:1,children:k(w,{color:"green",children:["Found: ",t.data.repoPath]})})]}),t.step==="Prerequisites"&&t.data.checks&&k(R,{flexDirection:"column",borderStyle:"round",paddingX:1,borderColor:h,children:[b(w,{bold:!0,children:"System Checks"}),k(R,{flexDirection:"column",marginTop:1,children:[b(Oe,{label:"Git",status:t.data.checks.git}),b(Oe,{label:"Docker",status:t.data.checks.docker}),b(Oe,{label:"Mise",status:t.data.checks.mise})]})]}),t.inputRequest?.id==="port_conflicts"&&t.data.portConflicts&&b(ir,{portResults:t.data.portConflicts,onAccept:()=>e.submitInput("accept"),onAbort:()=>e.submitInput("abort")}),t.inputRequest?.id==="setup_mode"&&b(ke,{onSelect:r=>e.submitInput(r)}),t.inputRequest?.id==="env_method"&&b(Be,{onSelect:r=>e.submitInput(r)}),t.inputRequest?.id==="env_infisical"&&b(Ae,{onSubmit:r=>e.submitInput(r)}),t.step==="Environment Setup"&&t.inputRequest?.id==="env_var"&&t.data.currentEnvVar&&b(Le,{categories:t.data.envCategories||[],currentVar:t.data.currentEnvVar,currentIndex:t.data.envVarIndex||0,totalCount:t.data.envVarTotal||0,onSubmit:r=>e.submitInput(r),onSkip:()=>e.submitInput("")}),t.step==="Environment Setup"&&t.inputRequest?.id==="env_group"&&t.data.currentEnvGroup&&b(_e,{category:t.data.currentEnvGroup,currentIndex:t.data.envGroupIndex||0,totalGroups:t.data.envGroupTotal||0,onSubmit:r=>e.submitInput(r)}),t.step==="Environment Setup"&&t.inputRequest?.id==="env_alternatives"&&t.data.alternativeGroups&&b(Me,{alternatives:t.data.alternativeGroups,onSubmit:(r,n)=>e.submitInput({selectedGroups:r,values:n})}),t.step==="Project Setup"&&k(R,{flexDirection:"column",marginTop:1,paddingX:1,borderStyle:"round",borderColor:h,children:[b(R,{marginBottom:1,children:b(w,{bold:!0,color:h,children:"Project Setup"})}),k(R,{flexDirection:"column",gap:1,children:[b(R,{children:t.data.dependencyComplete?k(w,{color:"green",children:["\u2713"," ",t.data.dependencyPhase]}):b(Fe,{label:t.data.dependencyPhase||"Preparing..."})}),!t.data.dependencyComplete&&t.data.dependencyProgress>0&&b(R,{width:50,children:b(or,{value:t.data.dependencyProgress})}),!t.data.dependencyComplete&&t.data.dependencyLogs?.length>0&&b(R,{flexDirection:"column",marginTop:1,borderStyle:"single",borderColor:"gray",paddingX:1,minHeight:6,children:t.data.dependencyLogs.map((r,n)=>b(w,{color:"gray",wrap:"truncate",children:r},n))})]})]}),t.step==="Finished"&&b(sr,{setupMode:t.data.setupMode,repoPath:t.data.repoPath,onConfirm:()=>e.submitInput(!0)}),t.error&&b(R,{borderStyle:"single",borderColor:"red",padding:1,marginTop:2,children:k(w,{color:"red",children:["Error: ",t.error.message]})})]})},Oe=({label:e,status:t})=>k(R,{children:[b(R,{marginRight:1,children:t==="pending"?b(Fe,{type:"dots"}):t==="success"?b(w,{color:h,children:"\u2714"}):t==="error"?b(w,{color:"red",children:"\u2716"}):b(w,{color:"yellow",children:"\u26A0"})}),b(w,{children:e})]}),ir=({portResults:e,onAccept:t,onAbort:o})=>(ot((r,n)=>{n.return?t():n.escape&&o()}),k(R,{flexDirection:"column",marginTop:1,paddingX:1,borderStyle:"round",borderColor:"yellow",children:[b(w,{bold:!0,color:"yellow",children:"Port Conflicts Detected"}),e.map(r=>k(R,{children:[k(w,{color:r.available?"green":"red",children:[r.available?"\u2714":"\u2716"," "]}),k(w,{children:[r.service," (:",r.port,")"]}),!r.available&&k(w,{color:"gray",children:[" ","- in use",r.usedBy?` by ${r.usedBy}`:"",r.alternative?` (alt: :${r.alternative})`:""]})]},r.port)),b(R,{marginTop:1,children:k(w,{children:[b(w,{color:"green",bold:!0,children:"Enter"})," continue ",b(w,{color:"yellow",bold:!0,children:"Escape"})," abort"]})})]})),sr=({setupMode:e,repoPath:t,onConfirm:o})=>(ot((i,c)=>{c.return&&o()}),k(R,{flexDirection:"column",marginTop:2,borderStyle:"round",borderColor:h,padding:1,children:[b(w,{color:h,bold:!0,children:"Setup Complete!"}),k(R,{marginTop:1,flexDirection:"column",children:[b(w,{bold:!0,children:"To start GAIA, run:"}),k(R,{marginTop:1,padding:1,borderStyle:"single",borderColor:"gray",flexDirection:"column",children:[k(w,{color:"cyan",children:["$ cd ",t||"."]}),b(w,{color:"cyan",children:"$ gaia start"})]}),b(R,{marginTop:1,children:b(w,{color:"gray",dimColor:!0,children:(e||"developer")==="selfhost"?"Runs: docker compose --profile all up -d (background)":"Runs: mise dev (interactive \u2014 keep terminal open)"})})]}),b(De,{}),b(R,{marginTop:1,children:b(w,{dimColor:!0,children:"Press Enter to exit"})})]}));import{Spinner as cr}from"@inkjs/ui";import{Box as A,Text as _,useInput as lr}from"ink";import{useEffect as at,useState as it}from"react";import{jsx as P,jsxs as O}from"react/jsx-runtime";var st=({store:e})=>{let[t,o]=it(e.currentState),[r,n]=it(!1);return at(()=>{let i=()=>o({...e.currentState});return e.on("change",i),()=>{e.off("change",i)}},[e]),at(()=>{t.step==="Results"&&n(!1)},[t.step]),lr((i,c)=>{(c.return||c.escape)&&t.step==="Results"&&e.submitInput("exit"),i==="r"&&t.step==="Results"&&t.data.refreshable&&!r&&(n(!0),e.submitInput("refresh"))}),O(A,{flexDirection:"column",width:"100%",children:[P(te,{}),t.step==="Checking"&&P(A,{marginTop:1,children:P(cr,{label:t.data.services?"Refreshing service health...":"Checking service health..."})}),t.step==="Results"&&t.data.services&&O(A,{flexDirection:"column",children:[O(A,{flexDirection:"column",borderStyle:"round",borderColor:h,paddingX:2,paddingY:1,children:[P(_,{bold:!0,color:h,children:"GAIA Service Status"}),O(A,{marginTop:1,flexDirection:"column",children:[O(A,{children:[P(A,{width:22,children:P(_,{bold:!0,children:"Service"})}),P(A,{width:10,children:P(_,{bold:!0,children:"Status"})}),P(A,{width:10,children:P(_,{bold:!0,children:"Latency"})})]}),P(_,{color:"gray",children:"\u2500".repeat(42)}),t.data.services.map(i=>O(A,{children:[P(A,{width:22,children:O(_,{children:[i.name," (:",i.port,")"]})}),P(A,{width:10,children:P(_,{color:i.status==="up"?"green":"red",bold:!0,children:i.status==="up"?"\u2713 UP":"\u2717 DOWN"})}),P(A,{width:10,children:P(_,{color:"gray",children:i.latency?`${i.latency}ms`:"--"})})]},i.name))]})]}),t.data.docker&&O(A,{flexDirection:"column",borderStyle:"round",borderColor:"gray",paddingX:2,paddingY:1,marginTop:1,children:[P(_,{bold:!0,children:"Docker Containers"}),O(_,{color:"gray",children:["Docker:"," ",t.data.docker.running?P(_,{color:"green",children:"Running"}):P(_,{color:"red",children:"Not running"})]}),t.data.docker.containers?.length>0&&P(A,{marginTop:1,flexDirection:"column",children:t.data.docker.containers.map(i=>O(A,{children:[O(_,{color:i.status==="running"?"green":"red",children:[i.status==="running"?"\u2713":"\u2717"," "]}),P(_,{children:i.name}),i.health&&O(_,{color:"gray",children:[" (",i.health,")"]})]},i.name))})]}),P(A,{marginTop:1,children:O(_,{dimColor:!0,children:["Press Enter or Escape to exit \xB7 Press"," ",P(_,{color:h,children:"r"})," to refresh"]})})]}),t.error&&P(A,{borderStyle:"single",borderColor:"red",padding:1,marginTop:2,children:O(_,{color:"red",children:["Error: ",t.error.message]})})]})};import{jsx as G,jsxs as le}from"react/jsx-runtime";var pr=["init","setup","status","start","stop"],Ne=class extends ur.Component{constructor(t){super(t),this.state={error:null}}static getDerivedStateFromError(t){return{error:t}}render(){return this.state.error?le(ge,{flexDirection:"column",padding:1,children:[G(Z,{color:"red",bold:!0,children:"An unexpected error occurred:"}),G(Z,{color:"red",children:this.state.error.message}),this.state.error.stack&&G(ge,{marginTop:1,children:G(Z,{color:"gray",dimColor:!0,children:this.state.error.stack})})]}):this.props.children}},dr=({store:e,command:t})=>{switch(t){case"init":return G(tt,{store:e});case"setup":return G(nt,{store:e});case"status":return G(st,{store:e});case"start":case"stop":return G(rt,{store:e,command:t});default:return le(ge,{flexDirection:"column",padding:1,children:[le(Z,{color:"red",children:["Unknown command: ",t]}),le(ge,{marginTop:1,flexDirection:"column",children:[G(Z,{bold:!0,children:"Available commands:"}),pr.map(o=>le(Z,{children:[" ",G(Z,{color:"cyan",children:o})]},o))]})]})}},j=({store:e,command:t})=>G(Ne,{children:G(dr,{store:e,command:t})});import{EventEmitter as mr}from"events";var Ge=class extends mr{state={step:"init",status:"",error:null,data:{},inputRequest:null};inputResolver=null;get currentState(){return this.state}setStep(t){this.state.step=t,this.emit("change",this.state)}setStatus(t){this.state.status=t,this.emit("change",this.state)}setError(t){this.state.error=t,t!==null&&this.inputResolver&&(this.inputResolver(null),this.inputResolver=null,this.state.inputRequest=null),this.emit("change",this.state)}updateData(t,o){this.state.data={...this.state.data,[t]:o},this.emit("change",this.state)}waitForInput(t,o){return this.state.inputRequest={id:t,meta:o},this.emit("change",this.state),new Promise(r=>{this.inputResolver=r})}submitInput(t){this.inputResolver&&(this.inputResolver(t),this.inputResolver=null,this.state.inputRequest=null,this.emit("change",this.state))}},H=()=>new Ge;import*as ae from"fs";import*as bt from"path";import*as ne from"node:fs";import*as oe from"node:path";import{execa as ct}from"execa";var lt={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/"}},ut={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 $e(e,t){return lt[t][e]??ut[t][e]}async function pt(e){let t=oe.join(e,"apps/api/scripts/dump_config_schema.py"),o=oe.join(e,"apps/api/app/config/settings_validator.py"),r=oe.join(e,"apps/api/app/config/settings.py");if(!ne.existsSync(t))throw new Error("dump_config_schema.py not found in apps/api/scripts");try{try{let{stdout:n}=await ct("python3",[t,o,r],{cwd:e});return JSON.parse(n)}catch{let{stdout:n}=await ct("python",[t,o,r],{cwd:e});return JSON.parse(n)}}catch(n){throw new Error(`Failed to parse settings schema: ${n.message}. Ensure python is installed.`)}}function dt(e){let t=oe.join(e,"apps","web",".env.local"),o=ne.existsSync(t)?t:oe.join(e,"apps","web",".env");if(!ne.existsSync(o))return[];let r=ne.readFileSync(o,"utf-8"),n=[],i="General";for(let c of r.split(`
3
+ `)){let d=c.trim();if(d.startsWith("#")&&!d.startsWith("#=")){let x=d.replace(/^#+\s*/,"").trim();x&&!x.startsWith("These are")&&(i=x);continue}if(!d||d.startsWith("#"))continue;let m=d.indexOf("=");if(m===-1)continue;let g=d.substring(0,m).trim(),y=d.substring(m+1).trim();n.push({name:g,value:y,category:i})}return n}function mt(e,t){let o=t?.[8e3]??8e3,r=t?.[3e3]??3e3,n={NEXT_PUBLIC_API_BASE_URL:`http://localhost:${o}/api/v1/`,NEXT_PUBLIC_WS_URL:`ws://localhost:${o}/api/v1/`};return r!==3e3&&(n.NEXT_PUBLIC_APP_URL=`http://localhost:${r}`),n}function ft(e,t){for(let[o,r]of Object.entries(t)){let n=Number(o);for(let[i,c]of Object.entries(e)){let d=new RegExp(`:${n}(?=[/\\s]|$)`,"g");e[i]=c.replaceAll(d,`:${r}`)}}}function gt(e,t){return e.map(o=>({...o,variables:o.variables.map(r=>{let n=$e(r.name,t);return{...r,defaultValue:n||r.defaultValue}})}))}function qe(){return Object.keys(lt.selfhost)}function xt(e){return{...ut[e]}}import*as q from"fs";import*as ue from"path";function je(e){q.existsSync(e)&&q.copyFileSync(e,`${e}.bak`)}function St(e,t){let o=ue.join(e,".env");je(o);let r=["# 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","MEM0","E2B","DODO","NEXT_PUBLIC","GAIA"];function i(d){for(let g of n)if(d===g||d.startsWith(`${g}_`))return g;let m=d.split("_");return m.length===1?"Core":m[0]||"Core"}let c=new Map;for(let[d,m]of Object.entries(t)){let g=i(d);c.has(g)||c.set(g,[]);let x=/[\s#"'\\]/.test(m)||m===""?`"${m.replace(/\\/g,"\\\\").replace(/"/g,'\\"')}"`:m;c.get(g).push(`${d}=${x}`)}for(let[d,m]of c.entries())r.push(`# ${d} Configuration`),r.push(...m),r.push("");q.writeFileSync(o,r.join(`
4
+ `),"utf-8")}function yt(e,t,o){let r=ue.join(e,"apps","web",".env.local");je(r);let n=dt(e),i=mt(t,o),c=["# GAIA Web App Environment Configuration","# Generated by GAIA CLI",`# Created: ${new Date().toISOString()}`,""],d=new Map;for(let m of n){d.has(m.category)||d.set(m.category,[]);let g=i[m.name]??m.value;d.get(m.category).push({name:m.name,value:g})}if(n.length===0){c.push("# Core URLs");for(let[m,g]of Object.entries(i))c.push(`${m}=${g}`);c.push("")}else for(let[m,g]of d.entries()){c.push(`# ${m}`);for(let{name:y,value:x}of g)c.push(`${y}=${x}`);c.push("")}q.writeFileSync(r,c.join(`
5
+ `),"utf-8")}var gr={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 vt(e,t){let o=ue.join(e,"infra","docker",".env");je(o);let r=["# Docker Compose port overrides","# Generated by GAIA CLI to resolve port conflicts",`# Created: ${new Date().toISOString()}`,""];for(let[n,i]of Object.entries(t)){let c=Number(n),d=gr[c];d&&r.push(`${d}=${i}`)}r.push(""),q.writeFileSync(o,r.join(`
6
+ `),"utf-8")}var ht={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 xe(e){let t=ue.join(e,"infra","docker",".env"),o={};if(!q.existsSync(t))return o;let r=q.readFileSync(t,"utf-8");for(let n of r.split(`
7
+ `)){let i=n.trim();if(i&&!i.startsWith("#")){let[c,...d]=i.split("=");if(c&&ht[c]){let m=Number(d.join("=").trim());!Number.isNaN(m)&&m>0&&(o[ht[c]]=m)}}}return o}var hr=e=>new Promise(t=>setTimeout(t,e));async function he(e,t,o){e.setStep("Environment Setup"),e.setStatus("Configuring environment...");let r=await e.waitForInput("setup_mode");e.updateData("setupMode",r),e.setStatus("Configuring environment variables...");let n=await e.waitForInput("env_method"),i={};i.ENV=r==="selfhost"?"production":"development";let c=qe();for(let m of c){let g=$e(m,r);g&&(i[m]=g)}let d=xt(r);for(let[m,g]of Object.entries(d))i[m]=g;if(n==="infisical")await Sr(e,i),e.setStatus("Infisical credentials saved. Ensure your Infisical project contains all required variables.");else try{await yr(e,t,i,r)}catch(m){e.setError(m);return}o&&ft(i,o);try{await vr(e,t,i,r,o)}catch(m){e.setError(m);return}await hr(1e3)}async function Sr(e,t){e.setStatus("Configuring Infisical...");let o=await e.waitForInput("env_infisical");t.INFISICAL_PROJECT_ID=o.INFISICAL_PROJECT_ID,t.INFISICAL_MACHINE_IDENTITY_CLIENT_ID=o.INFISICAL_MACHINE_IDENTITY_CLIENT_ID,t.INFISICAL_MACHINE_IDENTITY_CLIENT_SECRET=o.INFISICAL_MACHINE_IDENTITY_CLIENT_SECRET}async function yr(e,t,o,r){e.setStatus("Parsing environment variables...");let n;try{n=await pt(t),n=gt(n,r)}catch(f){throw new Error(`Failed to parse settings: ${f.message}`)}let i=new Set,c=[],d=new Set;for(let f of n)if(f.alternativeGroup&&!d.has(f.name)){let T=n.find(v=>v.name===f.alternativeGroup);T&&(c.push([f,T]),i.add(f.name),i.add(T.name),d.add(f.name),d.add(T.name))}let m=n.filter(f=>f.variables.length===1&&!i.has(f.name)),g=n.filter(f=>f.variables.length>1&&!i.has(f.name));for(let f of c){e.updateData("alternativeGroups",f),e.setStatus("Choose an AI provider...");let T=await e.waitForInput("env_alternatives");for(let[v,C]of Object.entries(T.values))C&&(o[v]=C)}let y=qe(),l=[...m.flatMap(f=>f.variables).filter(f=>!y.includes(f.name))].sort((f,T)=>f.required&&!T.required?-1:!f.required&&T.required?1:0);e.updateData("envVarTotal",l.length);for(let f=0;f<l.length;f++){let T=l[f];if(!T)continue;e.updateData("currentEnvVar",T),e.updateData("envVarIndex",f),e.setStatus(`Configuring ${T.name}...`);let v=await e.waitForInput("env_var",{varName:T.name});(v||T.required||T.defaultValue)&&(o[T.name]=v||T.defaultValue||"")}let S=[...g].filter(f=>!f.variables.every(T=>y.includes(T.name))).sort((f,T)=>{let v=f.variables.some(I=>I.required),C=T.variables.some(I=>I.required);return v&&!C?-1:!v&&C?1:0});e.updateData("envGroupTotal",S.length);for(let f=0;f<S.length;f++){let T=S[f];if(!T)continue;e.updateData("currentEnvGroup",T),e.updateData("envGroupIndex",f),e.setStatus(`Configuring ${T.name}...`);let v=await e.waitForInput("env_group",{groupName:T.name});for(let[C,I]of Object.entries(v)){let E=T.variables.find(W=>W.name===C);(I||E?.required||E?.defaultValue)&&(o[C]=I||E?.defaultValue||"")}}}async function vr(e,t,o,r,n){e.setStatus("Writing API environment file...");try{let i=bt.join(t,"apps","api");St(i,o),e.setStatus("API environment variables configured!")}catch(i){throw new Error(`Failed to write API .env file: ${i.message}`)}e.setStatus("Writing web environment file...");try{yt(t,r,n),e.setStatus("Web environment variables configured!")}catch(i){throw new Error(`Failed to write web .env file: ${i.message}`)}if(n&&Object.keys(n).length>0){e.setStatus("Writing Docker Compose port overrides...");try{vt(t,n),e.setStatus("Docker Compose ports configured!")}catch(i){throw new Error(`Failed to write Docker Compose .env: ${i.message}`)}}}import{execa as br}from"execa";import Se from"fs";import Tr from"simple-git";async function Tt(e,t,o){if(Se.existsSync(e)){let r=`${e}/.git`;if(!Se.existsSync(r))throw new Error(`Directory ${e} exists but is not a git repository`);await Tr().cwd(e).pull(),o(100,"Already exists, pulled latest")}else try{let r=br("git",["clone","--progress",t,e]);r.stderr?.on("data",n=>{let i=n.toString();i.includes("Counting objects")?o(5,"Counting objects"):i.includes("Compressing objects")&&o(10,"Compressing objects");let c=i.match(/Receiving objects:\s+(\d+)%\s+\((\d+)\/(\d+)\)/);if(c?.[1]){let m=Math.min(100,parseInt(c[1],10)),g=c[2],y=c[3];o(10+Math.floor(m*.5),`Receiving objects: ${g}/${y}`)}let d=i.match(/Resolving deltas:\s+(\d+)%\s+\((\d+)\/(\d+)\)/);if(d?.[1]){let m=Math.min(100,parseInt(d[1],10)),g=d[2],y=d[3];o(60+Math.floor(m*.4),`Resolving deltas: ${g}/${y}`)}}),await r,o(100,"Clone complete")}catch(r){throw Se.existsSync(e)&&Se.rmSync(e,{recursive:!0,force:!0}),r}}import{execa as X}from"execa";var V={git:"https://git-scm.com/downloads",docker:"https://docs.docker.com/get-docker/",mise:"https://mise.jdx.dev/getting-started.html"},Ir={8e3:"API Server",5432:"PostgreSQL",6379:"Redis",27017:"MongoDB",5672:"RabbitMQ",3e3:"Web Frontend",8080:"ChromaDB",8083:"Mongo Express"};async function ye(){try{return await X("git",["--version"]),"success"}catch{return"error"}}async function ve(){let e=!1,t=!1,o;try{await X("docker",["--version"]),e=!0}catch{return{name:"Docker",installUrl:V.docker,installed:!1,working:!1,errorMessage:"Docker is not installed"}}try{await X("docker",["info"],{timeout:5e3}),t=!0}catch{o="Docker is installed but the daemon is not running. Please start Docker Desktop or the Docker daemon."}return{name:"Docker",installUrl:V.docker,installed:e,working:t,errorMessage:o}}async function be(){try{return await X("mise",["--version"]),"success"}catch{return"missing"}}async function Te(){if((await import("node:os")).platform()==="win32")try{return await X("powershell",["-Command","irm https://mise.jdx.dev/install.ps1 | iex"]),!0}catch{return!1}try{return await X("sh",["-c","curl https://mise.jdx.dev/install.sh | sh"]),!0}catch{return!1}}async function Ce(e){let t=await import("node:net"),o=[],r=n=>new Promise(i=>{let c=t.createServer();c.once("error",()=>i(!1)),c.once("listening",()=>{c.close(()=>i(!0))}),c.listen(n)});for(let n of e){let i=Ir[n]||`Port ${n}`;if(await r(n))o.push({port:n,service:i,available:!0});else{let d=await Er(n),m=await wr(n+1,n+100,r);o.push({port:n,service:i,available:!1,usedBy:d,alternative:m||void 0})}}return o}async function Er(e){if((await import("node:os")).platform()==="win32"){try{let{stdout:r}=await X("netstat",["-ano","-p","TCP"]),n=r.trim().split(`
8
+ `);for(let i of n)if(i.includes(`:${e}`)&&i.includes("LISTENING")){let c=i.trim().split(/\s+/),d=c[c.length-1];if(d)try{let{stdout:m}=await X("tasklist",["/FI",`PID eq ${d}`,"/FO","CSV","/NH"]);return m.trim().split(",")[0]?.replace(/"/g,"")||`PID ${d}`}catch{return`PID ${d}`}}}catch{}return}try{let{stdout:r}=await X("lsof",["-i",`:${e}`,"-sTCP:LISTEN","-P","-n"]),n=r.trim().split(`
9
+ `);if(n.length>1)return n[1]?.split(/\s+/)?.[0]||void 0}catch{}}async function wr(e,t,o){for(let r=e;r<=t;r++)if(await o(r))return r;return null}import*as Y from"fs";import*as Q from"path";var Pr=e=>new Promise(t=>setTimeout(t,e)),Rr="dev-start.log";async function It(e,t,o){if(t==="selfhost"){o?.("Starting all services in Docker (selfhost mode)...");let r=Q.join(e,"infra/docker");await $("docker",["compose","-f","docker-compose.prod.yml","--profile","backend","--profile","web","up","-d","--build","--remove-orphans"],r),o?.("All services started in Docker!")}else{o?.("Starting development servers...");let{spawn:r}=await import("child_process"),n=Q.join(e,Rr),i=Y.openSync(n,"a"),c;try{c=r("mise",["dev"],{cwd:e,stdio:["ignore",i,i],detached:!0,shell:!0}),c.unref()}finally{Y.closeSync(i)}if(await Pr(1500),c.pid!=null)try{process.kill(c.pid,0)}catch{throw new Error(`Development servers crashed on startup. Check logs at: ${n}`)}o?.(`Development servers started! Logs: ${n}`)}}async function Et(e,t,o){let r=Q.join(e,"infra/docker"),n=await He(e);t?.("Stopping Docker services...");try{await $("docker",n==="selfhost"?["compose","-f","docker-compose.prod.yml","down"]:["compose","down"],r)}catch{}t?.("Stopping local processes...");try{let i=o?.[8e3]??8e3,c=o?.[3e3]??3e3;if(process.platform==="win32")for(let d of[i,c])try{await $("powershell",["-Command",`Get-NetTCPConnection -LocalPort ${d} -ErrorAction SilentlyContinue | ForEach-Object { Stop-Process -Id $_.OwningProcess -Force -ErrorAction SilentlyContinue }`],e)}catch{}else for(let d of[i,c])try{await $("sh",["-c",`lsof -ti :${d} -sTCP:LISTEN | xargs kill 2>/dev/null || true`],e)}catch{}}catch{}t?.("All services stopped.")}async function He(e){let t=Q.join(e,"apps","api",".env");if(!Y.existsSync(t))return null;let o=Y.readFileSync(t,"utf-8"),r=o.match(/^SETUP_MODE=(.+)$/m);if(r?.[1]){let n=r[1].trim().replace(/^["']|["']$/g,"");if(n==="selfhost"||n==="developer")return n}return o.includes("mongodb://mongo:")?"selfhost":(o.includes("mongodb://localhost:"),"developer")}async function $(e,t,o,r,n){let{spawn:i}=await import("child_process");return new Promise((c,d)=>{let m=i(e,t,{cwd:o,stdio:["ignore","pipe","pipe"],shell:!0}),g="",y=0;m.stdout?.on("data",x=>{let l=x.toString();g+=l,n?.(l),y=Math.min(y+5,95),r?.(y)}),m.stderr?.on("data",x=>{let l=x.toString();g+=l,n?.(l),y=Math.min(y+5,95),r?.(y)}),m.on("close",x=>{x===0?(r?.(100),c()):d(new Error(`Command failed with code ${x}: ${g.slice(-500)}`))}),m.on("error",x=>{d(x)})})}function U(e){let t=e||process.cwd();for(;t!==Q.dirname(t);){if(Y.existsSync(Q.join(t,"apps/api/app/config/settings_validator.py")))return t;t=Q.dirname(t)}return null}var Dr=process.env.GAIA_CLI_DEV==="true",K=e=>new Promise(t=>setTimeout(t,e));async function wt(e){e.setStep("Welcome"),e.setStatus("Waiting for user input..."),await e.waitForInput("welcome");let t=l=>{let S=e.currentState.data.dependencyLogs||[],f=l.split(`
10
+ `).filter(v=>v.trim()!==""),T=[...S,...f].slice(-20);e.updateData("dependencyLogs",T)};e.setStep("Prerequisites"),e.setStatus("Checking system requirements..."),e.updateData("checks",{git:"pending",docker:"pending",mise:"pending"}),await K(800),e.setStatus("Checking Git...");let o=await ye();e.updateData("checks",{...e.currentState.data.checks,git:o}),e.setStatus("Checking Docker...");let r=await ve(),n=r.working?"success":"error";e.updateData("checks",{...e.currentState.data.checks,docker:n}),r.working||e.updateData("dockerError",r.errorMessage),e.setStatus("Checking Mise...");let i=await be();e.updateData("checks",{...e.currentState.data.checks,mise:i}),i==="missing"&&(e.setStatus("Installing Mise..."),i=await Te()?"success":"error",e.updateData("checks",{...e.currentState.data.checks,mise:i}));let c=[];if(o==="error"&&c.push({name:"Git"}),n==="error"&&c.push({name:"Docker",message:r.errorMessage}),i==="error"&&c.push({name:"Mise"}),c.length>0){let l=[];l.push("Prerequisites failed:");for(let S of c)l.push(` \u2022 ${S.name}: ${S.message||"Not installed or not working"}`);l.push(`
11
+ Installation guides:`),o==="error"&&l.push(` \u2022 Git: ${V.git}`),n==="error"&&(r.installed?l.push(" \u2022 Docker: Start Docker Desktop or run 'sudo systemctl start docker'"):l.push(` \u2022 Docker: ${V.docker}`)),i==="error"&&l.push(` \u2022 Mise: ${V.mise}`),e.setError(new Error(l.join(`
12
+ `)));return}e.setStatus("Checking Ports...");let m=await Ce([8e3,5432,6379,27017,5672,3e3,8080,8083]),g={},y=m.filter(l=>!l.available);if(y.length>0){let l=y.filter(f=>!f.alternative);if(l.length>0){e.setError(new Error(`Cannot find free alternative ports for: ${l.map(f=>`${f.port} (${f.service})`).join(", ")}. Free these ports and try again.`));return}if(e.updateData("portConflicts",m),await e.waitForInput("port_conflicts")==="abort"){e.setError(new Error("Port conflicts not resolved. Please free the ports and try again."));return}for(let f of m)!f.available&&f.alternative&&(g[f.port]=f.alternative)}e.updateData("portOverrides",g),e.setStatus("Prerequisites check complete!"),await K(1e3);let x="";if(Dr){if(x=U()||"",!x){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{for(e.setStep("Repository Setup");;){if(x=await e.waitForInput("repo_path",{default:"./gaia"}),ae.existsSync(x)){if(!ae.statSync(x).isDirectory()){e.setError(new Error(`Path ${x} exists and is not a directory.`)),await K(2e3),e.setError(null);continue}if(ae.readdirSync(x).length>0){e.setError(new Error(`Directory ${x} is not empty. Please choose another path.`)),await K(2e3),e.setError(null);continue}}break}e.setStep("Repository Setup"),e.setStatus("Preparing repository..."),e.updateData("repoProgress",0),e.updateData("repoPhase","");try{await Tt(x,"https://github.com/theexperiencecompany/gaia.git",(l,S)=>{e.updateData("repoProgress",l),S?(e.updateData("repoPhase",S),e.setStatus(`${S}...`)):e.setStatus(`Cloning repository to ${x}... ${l}%`)}),e.setStatus("Repository ready!")}catch(l){e.setError(l);return}}await K(1e3),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 $("mise",["trust"],x,void 0,t),e.updateData("dependencyProgress",50),e.updateData("dependencyPhase","Installing tools (node, python, uv, nx)..."),await $("mise",["install"],x,l=>{e.updateData("dependencyProgress",50+l*.5)},t),e.updateData("dependencyProgress",100),e.updateData("toolComplete",!0)}catch(l){e.setError(new Error(`Failed to install tools: ${l.message}`));return}if(await K(1e3),await he(e,x,g),!e.currentState.error){e.setStep("Project Setup"),e.updateData("dependencyPhase","Setting up project..."),e.updateData("dependencyProgress",0),e.updateData("dependencyComplete",!1),e.updateData("repoPath",x),e.updateData("dependencyLogs",[]);try{e.updateData("dependencyProgress",0),e.updateData("dependencyPhase","Running mise setup (all dependencies)..."),await $("mise",["setup"],x,l=>{e.updateData("dependencyProgress",l)},t),e.updateData("dependencyProgress",100),e.updateData("dependencyPhase","Setup complete!"),e.updateData("dependencyComplete",!0)}catch(l){e.setError(new Error(`Failed to setup project: ${l.message}`));return}await K(1e3),e.setStep("Finished"),e.setStatus("Setup complete!")}}async function Pt(){let e=H(),{unmount:t}=kr(Br.createElement(j,{store:e,command:"init"}));try{await wt(e)}catch(o){e.setError(o)}e.currentState.error&&await e.waitForInput("exit"),t(),process.exit(e.currentState.error?1:0)}import{render as Ar}from"ink";import _r from"react";var Ie=e=>new Promise(t=>setTimeout(t,e));async function Rt(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}e.updateData("repoPath",t),e.setStatus(`Found repository at ${t}`),await Ie(1e3),e.setStep("Prerequisites"),e.setStatus("Checking system requirements..."),e.updateData("checks",{git:"pending",docker:"pending",mise:"pending"}),await Ie(500);let o=await ye();e.updateData("checks",{...e.currentState.data.checks,git:o});let r=await ve(),n=r.working?"success":"error";e.updateData("checks",{...e.currentState.data.checks,docker:n}),r.working||e.updateData("dockerError",r.errorMessage);let i=await be();e.updateData("checks",{...e.currentState.data.checks,mise:i}),i==="missing"&&(e.setStatus("Installing Mise..."),i=await Te()?"success":"error",e.updateData("checks",{...e.currentState.data.checks,mise:i}));let c=[];if(o==="error"&&c.push({name:"Git"}),n==="error"&&c.push({name:"Docker",message:r.errorMessage}),i==="error"&&c.push({name:"Mise"}),c.length>0){let l=[];l.push("Prerequisites failed:");for(let S of c)l.push(` \u2022 ${S.name}: ${S.message||"Not installed or not working"}`);l.push(`
13
+ Installation guides:`),o==="error"&&l.push(` \u2022 Git: ${V.git}`),n==="error"&&(r.installed?l.push(" \u2022 Docker: Start Docker Desktop or run 'sudo systemctl start docker'"):l.push(` \u2022 Docker: ${V.docker}`)),i==="error"&&l.push(` \u2022 Mise: ${V.mise}`),e.setError(new Error(l.join(`
14
+ `)));return}e.setStatus("Checking Ports...");let m=await Ce([8e3,5432,6379,27017,5672,3e3,8080,8083]),g={},y=m.filter(l=>!l.available);if(y.length>0){let l=y.filter(f=>!f.alternative);if(l.length>0){e.setError(new Error(`Cannot find free alternative ports for: ${l.map(f=>`${f.port} (${f.service})`).join(", ")}. Free these ports and try again.`));return}if(e.updateData("portConflicts",m),await e.waitForInput("port_conflicts")==="abort"){e.setError(new Error("Port conflicts not resolved. Please free the ports and try again."));return}for(let f of m)!f.available&&f.alternative&&(g[f.port]=f.alternative)}if(e.updateData("portOverrides",g),e.setStatus("Prerequisites check complete!"),await Ie(1e3),await he(e,t,g),e.currentState.error)return;e.setStep("Project Setup"),e.updateData("dependencyPhase","Setting up project..."),e.updateData("dependencyProgress",0),e.updateData("dependencyComplete",!1),e.updateData("dependencyLogs",[]);let x=l=>{let S=e.currentState.data.dependencyLogs||[],f=l.split(`
15
+ `).filter(v=>v.trim()!==""),T=[...S,...f].slice(-20);e.updateData("dependencyLogs",T)};try{e.updateData("dependencyPhase","Trusting mise configuration..."),await $("mise",["trust"],t,void 0,x),e.updateData("dependencyProgress",20),e.updateData("dependencyPhase","Installing tools..."),await $("mise",["install"],t,l=>{e.updateData("dependencyProgress",20+l*.3)},x),e.updateData("dependencyPhase","Running mise setup..."),await $("mise",["setup"],t,l=>{e.updateData("dependencyProgress",50+l*.5)},x),e.updateData("dependencyProgress",100),e.updateData("dependencyPhase","Setup complete!"),e.updateData("dependencyComplete",!0)}catch(l){e.setError(new Error(`Failed to setup project: ${l.message}`));return}await Ie(1e3),e.setStep("Finished"),e.setStatus("Setup complete!")}async function Dt(){let e=H(),{unmount:t}=Ar(_r.createElement(j,{store:e,command:"setup"}));try{await Rt(e)}catch(o){e.setError(o)}e.currentState.error&&await e.waitForInput("exit"),t(),process.exit(e.currentState.error?1:0)}import{render as Mr}from"ink";import Lr from"react";async function kt(e){e.setStep("Starting"),e.setStatus("Locating GAIA repository...");let t=U();if(!t){e.setError(new Error("Could not find GAIA repository. Run from within a cloned gaia repo."));return}e.updateData("repoPath",t);let o=await He(t);if(!o){e.setError(new Error("No .env file found. Run 'gaia setup' first to configure the environment."));return}e.updateData("setupMode",o),e.setStatus(`Starting GAIA in ${o} mode...`);try{await It(t,o,r=>{e.setStatus(r)}),e.setStep("Running"),e.setStatus("GAIA is running!"),e.updateData("started",!0)}catch(r){e.setError(new Error(`Failed to start services: ${r.message}`));return}await e.waitForInput("exit")}async function Bt(){let e=H(),{unmount:t}=Mr(Lr.createElement(j,{store:e,command:"start"}));await new Promise(o=>setTimeout(o,50));try{await kt(e)}catch(o){e.setError(o)}e.currentState.error&&await e.waitForInput("exit"),t(),process.exit(e.currentState.error?1:0)}import{render as $r}from"ink";import qr from"react";import{execa as Ue}from"execa";var Ve=["gaia-backend","gaia-web","chromadb","postgres","redis","mongo","rabbitmq","arq_worker"];async function At(){try{let{stdout:e}=await Ue("docker",["inspect","--format","{{.Name}}|{{.State.Status}}|{{if .State.Health}}{{.State.Health.Status}}{{else}}none{{end}}",...Ve]),t=new Map;for(let o of e.trim().split(`
16
+ `)){if(!o)continue;let[r,n,i]=o.split("|"),c=r?.replace(/^\//,"")??"";t.set(c,{name:c,status:n==="running"?"running":"stopped",health:i!=="none"?i:void 0})}return Ve.map(o=>t.get(o)??{name:o,status:"not_found"})}catch{let e=Ve.map(async t=>{try{let{stdout:o}=await Ue("docker",["inspect","--format","{{.State.Status}}|{{if .State.Health}}{{.State.Health.Status}}{{else}}none{{end}}",t]),[r,n]=o.trim().split("|");return{name:t,status:r==="running"?"running":"stopped",health:n!=="none"?n:void 0}}catch{return{name:t,status:"not_found"}}});return Promise.all(e)}}async function _t(){try{return await Ue("docker",["info"]),!0}catch{return!1}}var Or=[{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 Mt(e){let o=Or.map(r=>({...r,port:e?.[r.port]??r.port})).map(r=>r.type==="http"?Fr(r.name,r.port,r.path):Nr(r.name,r.port));return Promise.all(o)}async function Fr(e,t,o){let r=Date.now();try{let n=await fetch(`http://localhost:${t}${o}`,{signal:AbortSignal.timeout(5e3)}),i=Date.now()-r;return{name:e,port:t,status:"up",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 Nr(e,t){let o=await import("node:net"),r=Date.now();return new Promise(n=>{let i=new o.Socket;i.setTimeout(3e3),i.on("connect",()=>{let c=Date.now()-r;i.destroy(),n({name:e,port:t,status:"up",latency:c})}),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 Lt(){return await _t()?{running:!0,containers:await At()}:{running:!1,containers:[]}}async function Gr(e){e.setStep("Checking"),e.setStatus("Checking service health..."),e.updateData("refreshable",!1);let t=U(),o=t?xe(t):void 0,[r,n]=await Promise.all([Mt(o),Lt()]);e.updateData("services",r),e.updateData("docker",n);let i=r.filter(d=>d.status==="up").length,c=r.length;e.setStep("Results"),e.setStatus(`${i}/${c} services running`),e.updateData("refreshable",!0)}async function Ot(e){for(;await Gr(e),await e.waitForInput("exit_or_refresh")==="refresh";);}async function Ft(){let e=H(),{unmount:t}=$r(qr.createElement(j,{store:e,command:"status"}));await new Promise(o=>setTimeout(o,50));try{await Ot(e)}catch(o){e.setError(o)}e.currentState.error&&await e.waitForInput("exit"),t(),process.exit(e.currentState.error?1:0)}import{render as jr}from"ink";import Hr from"react";async function Nt(e){e.setStep("Stopping"),e.setStatus("Locating GAIA repository...");let t=U();if(!t){e.setError(new Error("Could not find GAIA repository. Run from within a cloned gaia repo."));return}e.updateData("repoPath",t);let o=xe(t);try{await Et(t,r=>{e.setStatus(r)},o),e.setStep("Stopped"),e.setStatus("All services stopped."),e.updateData("stopped",!0)}catch(r){e.setError(new Error(`Failed to stop services: ${r.message}`));return}await e.waitForInput("exit")}async function Gt(){let e=H(),{unmount:t}=jr(Hr.createElement(j,{store:e,command:"stop"}));await new Promise(o=>setTimeout(o,50));try{await Nt(e)}catch(o){e.setError(o)}e.currentState.error&&await e.waitForInput("exit"),t(),process.exit(e.currentState.error?1:0)}var J=new Vr;J.name("gaia").description("CLI tool for setting up and managing GAIA").version("0.1.0");J.command("init").description("Full setup from scratch (clone, configure, start)").action(async()=>{await Pt()});J.command("setup").description("Configure an existing GAIA repository").action(async()=>{await Dt()});J.command("status").description("Check health of all GAIA services").action(async()=>{await Ft()});J.command("start").description("Start GAIA services").action(async()=>{await Bt()});J.command("stop").description("Stop all GAIA services").action(async()=>{await Gt()});process.argv.slice(2).length||(J.outputHelp(),process.exit(0));J.parse();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@heygaia/cli",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "CLI tool for setting up and managing GAIA",
5
5
  "type": "module",
6
6
  "bin": {
@@ -14,6 +14,12 @@
14
14
  "dev": "tsx watch src/index.ts",
15
15
  "build": "esbuild src/index.ts --bundle --platform=node --target=node18 --format=esm --packages=external --outfile=dist/index.js --minify && chmod +x dist/index.js",
16
16
  "start": "NODE_ENV=production node dist/index.js",
17
+ "type-check": "tsc --noEmit",
18
+ "check": "biome check src",
19
+ "fix": "biome check --write src",
20
+ "lint": "pnpm run check",
21
+ "lint:fix": "pnpm run fix",
22
+ "format": "biome format --write src",
17
23
  "prepublishOnly": "pnpm run build"
18
24
  },
19
25
  "engines": {
@@ -50,10 +56,12 @@
50
56
  "simple-git": "^3.30.0"
51
57
  },
52
58
  "devDependencies": {
59
+ "@biomejs/biome": "2.3.7",
53
60
  "@types/node": "^25.2.2",
54
61
  "@types/react": "^19",
55
62
  "@types/react-dom": "^19",
56
63
  "esbuild": "latest",
57
- "tsx": "latest"
64
+ "tsx": "latest",
65
+ "typescript": "^5.9.2"
58
66
  }
59
67
  }