@heygaia/cli 0.1.14 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +34 -190
  2. package/dist/index.js +48 -33
  3. package/package.json +44 -41
package/README.md CHANGED
@@ -1,239 +1,104 @@
1
1
  # @heygaia/cli
2
2
 
3
- CLI tool for setting up and managing [GAIA](https://heygaia.io) — your proactive personal AI assistant.
3
+ ![GAIA CLI](../../apps/web/public/images/screenshots/cli.png)
4
4
 
5
- The CLI provides an interactive terminal UI that guides you through cloning, configuring, and running a self-hosted GAIA instance.
5
+ CLI tool for setting up and managing [GAIA](https://heygaia.io).
6
6
 
7
7
  ## Requirements
8
8
 
9
- - **Node.js 18+** (for npm/npx) or **Bun** (alternative)
9
+ - **Node.js 20+** and one package manager (npm, pnpm, or bun)
10
10
  - **macOS or Linux** (Windows via WSL2)
11
11
  - **Docker** installed and running
12
12
  - **Git** installed
13
13
 
14
- The CLI checks prerequisites at startup and tells you what's missing.
14
+ The CLI checks prerequisites at startup and reports what is missing.
15
15
 
16
16
  ## Installation
17
17
 
18
- **Global installation is required** to use the `gaia` command. Choose your preferred method:
19
-
20
- ### Quick Install (Recommended)
21
-
22
- Downloads and installs the CLI globally using the install script:
23
-
24
- ```bash
25
- curl -fsSL https://heygaia.io/install.sh | sh
26
- ```
27
-
28
- This automatically detects your system and installs using npm or bun.
29
-
30
- ### Manual Installation
31
-
32
- #### npm
18
+ Install globally with your preferred package manager:
33
19
 
34
20
  ```bash
35
21
  npm install -g @heygaia/cli
36
- ```
37
-
38
- #### pnpm
39
-
40
- ```bash
41
22
  pnpm add -g @heygaia/cli
42
- ```
43
-
44
- #### bun
45
-
46
- ```bash
47
23
  bun add -g @heygaia/cli
48
24
  ```
49
25
 
50
- ### Verify Installation
51
-
52
- After installation, verify the `gaia` command is available:
53
-
54
- ```bash
55
- gaia --version
56
- gaia --help
57
- ```
58
-
59
- ### Alternative: Run Without Installing (Not Recommended)
60
-
61
- You can run commands directly with `npx`, but this won't add the `gaia` command to your PATH:
62
-
63
- ```bash
64
- npx @heygaia/cli init
65
- ```
66
-
67
- **Note:** Using `npx` means you'll need to prefix every command with `npx @heygaia/cli` instead of just using `gaia`. We recommend installing globally for the best experience.
68
-
69
- ## What Happens When You Install
70
-
71
- 1. The `@heygaia/cli` npm package is installed globally
72
- 2. A `gaia` binary is added to your PATH (points to `dist/index.js`)
73
- 3. No background processes, daemons, or services are started — the CLI only runs when you invoke it
74
-
75
- The CLI itself is a single bundled JavaScript file (~300KB) with no native dependencies.
76
-
77
26
  ## Commands
78
27
 
79
- Once installed, you can use these commands from anywhere in your terminal:
80
-
81
- ### Quick Reference
82
-
83
28
  ```bash
84
29
  gaia init # Full setup from scratch
85
30
  gaia setup # Configure existing repo
86
- gaia start # Start all services
31
+ gaia start # Start services in self-host mode
32
+ gaia dev # Developer mode (Nx TUI)
33
+ gaia dev full # Developer mode + workers (Nx TUI)
34
+ gaia logs # Stream running logs
87
35
  gaia stop # Stop all services
88
36
  gaia status # Check service health
89
37
  gaia --version # Show CLI version
90
38
  gaia --help # Show all commands
91
39
  ```
92
40
 
93
- ### Command Details
94
-
95
- | Command | Description |
96
- |---------|-------------|
97
- | `gaia init` | Full setup from scratch — clone repo, install tools, configure env, start services |
98
- | `gaia setup` | Configure an existing GAIA repository (env vars, dependencies) |
99
- | `gaia start` | Start all GAIA services (auto-detects selfhost vs developer mode) |
100
- | `gaia stop` | Stop all running GAIA services |
101
- | `gaia status` | Check health of all services with latency |
102
- | `gaia --version` | Display the current CLI version |
103
- | `gaia --help` | Show help and list all available commands |
104
-
105
41
  ### `gaia init`
106
42
 
107
- Interactive wizard for first-time setup. This is the main entry point for new users.
43
+ Interactive first-time setup.
108
44
 
109
- **Usage:**
110
-
111
- ```bash
112
- gaia init
113
- ```
114
-
115
- **What it does:**
116
-
117
- 1. **Prerequisites check** — Verifies Git, Docker, and [Mise](https://mise.jdx.dev) are installed. Auto-installs Mise if missing.
118
- 2. **Port conflict detection** — Checks ports 3000, 5432, 6379, 8000, 8080, 27017, 5672. Suggests alternatives if any are in use.
119
- 3. **Repository clone** — Clones the GAIA repo to your chosen directory with progress tracking.
120
- 4. **Tool installation** — Installs Node.js, Python, uv, and Nx via Mise.
121
- 5. **Environment configuration** — Choose a setup mode and configure variables (see below).
122
- 6. **Project setup** — Runs `mise setup` to install all dependencies, start Docker services, and seed the database.
123
- 7. **Service startup** — Optionally starts all services immediately.
124
-
125
- **First-time users:** This is the command you want! It handles everything from zero to a running GAIA instance.
45
+ | Flag | Description |
46
+ |------|-------------|
47
+ | `--branch <name>` | Clone a specific branch |
126
48
 
127
49
  ### `gaia setup`
128
50
 
129
- For existing repos that need configuration or reconfiguration. Skips cloning and tool installation, goes straight to environment setup.
130
-
131
- **Usage:**
51
+ Reconfigure an existing GAIA repo:
132
52
 
133
53
  ```bash
134
54
  cd /path/to/gaia
135
55
  gaia setup
136
56
  ```
137
57
 
138
- **When to use:**
139
- - You already have the GAIA repo cloned
140
- - You want to reconfigure environment variables
141
- - You need to switch between self-host and developer modes
142
- - Dependencies need to be reinstalled
143
-
144
58
  ### `gaia start`
145
59
 
146
- Starts all GAIA services. Auto-detects the setup mode from your `.env` configuration.
147
-
148
- **Usage:**
60
+ Starts services for **self-host mode**.
149
61
 
150
62
  ```bash
151
63
  gaia start
152
64
  ```
153
65
 
154
- **What it does:**
66
+ Optional flags:
155
67
 
156
- - **Self-host mode**: Runs `docker compose --profile all up -d` (everything in Docker, runs in background)
157
- - **Developer mode**: Runs `mise dev` (databases in Docker, API + web locally with hot reload)
68
+ - `--build` rebuild Docker images before starting
69
+ - `--pull` pull latest base images before starting
158
70
 
159
- **Access your instance:**
160
- - Web: http://localhost:3000
161
- - API: http://localhost:8000
162
- - API Docs: http://localhost:8000/docs
71
+ ### `gaia dev` / `gaia dev full`
163
72
 
164
- ### `gaia stop`
73
+ Runs developer mode in foreground Nx TUI:
165
74
 
166
- Stops all running GAIA services gracefully.
75
+ - `gaia dev` -> `mise dev`
76
+ - `gaia dev full` -> `mise dev:full`
167
77
 
168
- **Usage:**
78
+ ### `gaia logs`
169
79
 
170
- ```bash
171
- gaia stop
172
- ```
80
+ Streams logs for currently running services.
173
81
 
174
- **What it stops:**
175
- - All Docker containers in the GAIA compose stack
176
- - Local processes on ports 8000 (API) and 3000 (Web)
177
- - Background workers and services
82
+ ### `gaia stop`
178
83
 
179
- **Note:** Your data is preserved — stopping services doesn't delete any databases or configurations.
84
+ Stops running GAIA services.
180
85
 
181
86
  ### `gaia status`
182
87
 
183
- Shows a live health dashboard with latency for all services.
184
-
185
- **Usage:**
186
-
187
- ```bash
188
- gaia status
189
- ```
190
-
191
- **Service checks:**
192
-
193
- | Service | Port | Health Check |
194
- |---------|------|--------------|
195
- | API | 8000 | HTTP `GET /health` |
196
- | Web | 3000 | HTTP `GET /` |
197
- | PostgreSQL | 5432 | TCP connection |
198
- | Redis | 6379 | TCP connection |
199
- | MongoDB | 27017 | TCP connection |
200
- | RabbitMQ | 5672 | TCP connection |
201
- | ChromaDB | 8080 | TCP connection |
202
-
203
- **Interactive controls:**
204
- - Press `r` to refresh status
205
- - Status indicators: ✓ (healthy), ✗ (down), - (checking)
206
- - Shows response time for each service
88
+ Shows health and latency for core services.
207
89
 
208
90
  ## Setup Modes
209
91
 
210
- During `gaia init` or `gaia setup`, you choose a mode:
211
-
212
- - **Self-Host (Docker)** — Everything runs in Docker containers. Best for deployment and non-developers.
213
- - **Developer (Local)** — Databases in Docker, API + web run locally with hot reload. Best for contributing.
214
-
215
- ## Environment Variable Configuration
216
-
217
- Two methods are available:
218
-
219
- - **Manual** — Interactive prompts for each variable with descriptions, documentation links, and defaults.
220
- - **Infisical** — Enter your Infisical credentials (token, project ID, machine identity) for centralized secret management.
221
-
222
- ### Auto-Discovery
92
+ - **Self-Host (Docker)** everything in Docker
93
+ - **Developer (Local)** — infra in Docker, app in local Nx TUI
223
94
 
224
- The CLI discovers environment variables from the codebase at runtime:
95
+ ## Port Overrides
225
96
 
226
- - **API variables** Extracted from `apps/api/app/config/settings.py` and `settings_validator.py` via Python AST parsing
227
- - **Web variables** — Parsed from `apps/web/.env`
228
-
229
- When a developer adds a new variable to either location, the CLI picks it up automatically — no CLI updates needed.
97
+ When port conflicts are detected, overrides are written to `infra/docker/.env`.
230
98
 
231
99
  ## Development
232
100
 
233
101
  ```bash
234
- # Dev mode (watch, no build needed)
235
- GAIA_CLI_DEV=true pnpm tsx packages/cli/src/index.ts <command>
236
-
237
102
  # Build
238
103
  cd packages/cli && pnpm run build
239
104
 
@@ -244,33 +109,12 @@ cd packages/cli && pnpm run build
244
109
  ./packages/cli/test-cli.sh
245
110
  ```
246
111
 
247
- ### Install Script
248
-
249
- Source of truth: `packages/cli/install.sh`. After modifying, sync to the web app:
250
-
251
- ```bash
252
- ./packages/cli/sync-install.sh
253
- ```
254
-
255
- This copies the script to `apps/web/public/install.sh`, which is served at `https://heygaia.io/install.sh`.
256
-
257
- ### Publishing
112
+ ## Publishing
258
113
 
259
114
  1. Update version in `package.json`
260
115
  2. Build: `pnpm run build`
261
- 3. Sync install script: `./sync-install.sh`
262
- 4. Commit and tag: `git tag cli-v<version>`
263
- 5. Push tag — GitHub Actions publishes to npm
264
-
265
- ## Troubleshooting
266
-
267
- | Issue | Fix |
268
- |-------|-----|
269
- | `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"` |
270
- | Raw mode not supported | The CLI requires an interactive terminal — don't run in background or pipe |
271
- | Port conflicts not detected | Ensure `lsof` is available (macOS/Linux). Windows requires WSL2 |
272
- | Env vars not discovered | Check that `settings_validator.py` and `apps/web/.env` exist in the repo |
273
- | Docker prerequisite fails | Ensure Docker Desktop/Engine is running, not just installed |
116
+ 3. Commit and tag: `git tag cli-v<version>`
117
+ 4. Push tag GitHub Actions publishes to npm
274
118
 
275
119
  ## License
276
120
 
package/dist/index.js CHANGED
@@ -1,37 +1,52 @@
1
1
  #!/usr/bin/env node
2
- import{Command as Mo}from"commander";import{render as bo}from"ink";import Io from"react";import{Box as Me,Text as pe}from"ink";import Yr from"react";import{ProgressBar as Et,Select as Ke,Spinner as Ye}from"@inkjs/ui";import{Box as f,Text as u,useInput as ie}from"ink";import we from"ink-text-input";import{useEffect as Pe,useRef as _r,useState as H}from"react";import{Box as Ce,Text as _e}from"ink";var b="#00bbff";import{Box as Ir,Text as Cr}from"ink";import{jsx as bt}from"react/jsx-runtime";var It=({status:e,step:t})=>t.toLowerCase()==="welcome"?null:bt(Ir,{width:"100%",paddingX:1,marginTop:1,children:bt(Cr,{color:"gray",dimColor:!0,children:e})});import{Box as Er}from"ink";import wr from"ink-big-text";import Pr from"ink-gradient";import{jsx as Qe}from"react/jsx-runtime";var fe=()=>Qe(Er,{flexDirection:"column",marginTop:1,marginBottom:1,children:Qe(Pr,{colors:[b,"#b0eaff",b],children:Qe(wr,{text:"GAIA",font:"3d"})})});import{jsx as le,jsxs as Ee}from"react/jsx-runtime";var Rr=["Welcome","Prerequisites","Setup Mode","Repository Setup","Environment Setup","Install Tools","Project Setup","Installing CLI","Finished"],Ct=["Detect Repo","Prerequisites","Environment Setup","Project Setup","Finished"],Dr={Welcome:"Welcome",Prerequisites:"Prereqs","Setup Mode":"Mode","Repository Setup":"Repo","Environment Setup":"Env","Install Tools":"Tools","Project Setup":"Setup","Installing CLI":"CLI","Detect Repo":"Detect",Finished:"Done"},kr=({currentStep:e,steps:t})=>{let o=t.indexOf(e);return le(Ce,{marginBottom:1,flexWrap:"nowrap",children:t.map((r,n)=>{let s=n<o,c=n===o,a=Dr[r]??r;return Ee(Ce,{flexShrink:0,children:[n>0&&Ee(_e,{color:"gray",dimColor:!0,children:[" ","\xB7"," "]}),s&&Ee(_e,{color:"green",children:["\u2713 ",a]}),c&&le(_e,{color:b,bold:!0,children:a}),!s&&!c&&le(_e,{color:"gray",dimColor:!0,children:a})]},r)})})},Le=({children:e,status:t,step:o,steps:r=Rr})=>Ee(Ce,{flexDirection:"column",height:"100%",width:"100%",children:[Ee(Ce,{flexGrow:1,flexDirection:"column",children:[le(fe,{}),le(kr,{currentStep:o,steps:r}),le(Ce,{flexDirection:"column",flexGrow:1,children:e})]}),le(It,{status:t,step:o})]});import{Spinner as Ar}from"@inkjs/ui";import{Box as oe,Text as U,useInput as Br}from"ink";import{jsx as j,jsxs as ue}from"react/jsx-runtime";var ne=({label:e,status:t})=>ue(oe,{children:[j(oe,{marginRight:1,children:t==="pending"?j(Ar,{type:"dots"}):t==="success"?j(U,{color:"green",children:"\u2714"}):t==="error"?j(U,{color:"red",children:"\u2716"}):j(U,{color:"yellow",children:"\u26A0"})}),j(U,{children:e})]}),Oe=({portResults:e,onAccept:t,onAbort:o})=>{Br((n,s)=>{s.return?t():s.escape&&o()});let r=e.filter(n=>!n.available);return ue(oe,{flexDirection:"column",marginTop:1,paddingX:1,borderStyle:"round",borderColor:"yellow",children:[j(oe,{marginBottom:1,children:j(U,{bold:!0,color:"yellow",children:"Port Conflicts Detected"})}),e.map(n=>ue(oe,{children:[ue(U,{color:n.available?"green":n.alternative?"yellow":"red",children:[n.available?"\u2714":n.alternative?"\u26A0":"\u2716"," "]}),ue(U,{children:[n.service," (:",n.port,")"]}),!n.available&&ue(U,{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)),r.some(n=>!n.alternative)&&j(oe,{marginTop:1,children:j(U,{color:"red",children:"Some ports have no available alternative. Free them and retry."})}),!r.some(n=>!n.alternative)&&r.some(n=>n.alternative)&&j(oe,{marginTop:1,children:j(U,{color:"gray",children:"Alternative ports will be used for conflicting services."})}),j(oe,{marginTop:1,children:ue(U,{dimColor:!0,children:[j(U,{bold:!0,children:"Enter"})," continue \xB7 ",j(U,{bold:!0,children:"ESC"})," abort"]})})]})};import{Fragment as dn,jsx as i,jsxs as g}from"react/jsx-runtime";var Lr=({onConfirm:e})=>(ie((t,o)=>{o.return&&e()}),g(f,{flexDirection:"column",paddingX:2,borderStyle:"round",borderColor:b,children:[i(u,{bold:!0,children:"Welcome to GAIA Setup"}),g(f,{flexDirection:"column",marginTop:1,marginBottom:1,children:[i(u,{children:"This wizard will guide you through the setup process:"}),i(u,{children:" 1. Check prerequisites and choose setup mode"}),i(u,{children:" 2. Clone repository"}),i(u,{children:" 3. Configure environment variables"}),i(u,{children:" 4. Install tools and dependencies"})]}),i(u,{dimColor:!0,children:"~5-15 min depending on network speed"}),i(f,{marginTop:1,children:g(u,{color:b,children:[i(u,{bold:!0,children:"Enter"})," to start"]})})]})),Or=({defaultValue:e,onSubmit:t})=>{let[o,r]=H(e);return g(f,{flexDirection:"column",marginTop:1,paddingX:1,borderStyle:"round",borderColor:b,children:[i(u,{children:"Clone repository to:"}),i(u,{color:"gray",dimColor:!0,children:"Press Enter for default, or type a custom path"}),g(f,{marginTop:1,children:[i(u,{color:b,children:"\u2192 "}),i(we,{value:o,onChange:r,onSubmit:t})]})]})},Mr=({repoPath:e,onAction:t})=>g(f,{flexDirection:"column",marginTop:1,paddingX:1,borderStyle:"round",borderColor:"yellow",children:[i(f,{marginBottom:1,children:i(u,{bold:!0,color:"yellow",children:"Existing Installation Found"})}),g(u,{children:["Found a GAIA installation at"," ",i(u,{color:"cyan",bold:!0,children:e})]}),i(f,{marginTop:1,children:i(u,{color:"gray",children:"What would you like to do?"})}),i(f,{marginTop:1,children:i(Ke,{options:[{label:"Use existing installation",value:"use_existing"},{label:"Delete and re-clone",value:"delete_reclone"},{label:"Choose a different path",value:"different_path"},{label:"Exit setup",value:"exit"}],onChange:r=>t(r)})})]}),Fr=({setupMode:e,portOverrides:t,onConfirm:o})=>{ie((s,c)=>{c.return&&o()});let r=t?.[3e3]??3e3,n=t?.[8e3]??8e3;return e==="selfhost"?g(f,{flexDirection:"column",marginTop:2,borderStyle:"round",borderColor:"green",padding:1,children:[i(u,{bold:!0,color:"green",children:"GAIA is Running!"}),i(f,{marginTop:1,children:i(u,{color:"green",children:"\u2713 All services started"})}),g(f,{marginTop:1,flexDirection:"column",children:[g(u,{children:["Web:"," ",g(u,{color:"cyan",bold:!0,children:["http://localhost:",r]})]}),g(u,{children:["API:"," ",g(u,{color:"cyan",bold:!0,children:["http://localhost:",n]})]})]}),i(f,{marginTop:1,children:i(u,{color:"gray",children:"gaia stop \xB7 gaia status \xB7 gaia setup"})}),i(f,{marginTop:1,children:g(u,{dimColor:!0,children:[i(u,{bold:!0,children:"Enter"})," to exit"]})})]}):g(f,{flexDirection:"column",marginTop:2,borderStyle:"round",borderColor:b,padding:1,children:[i(u,{color:b,bold:!0,children:"You're all set!"}),g(f,{marginTop:1,children:[i(u,{bold:!0,children:"Run: "}),i(u,{color:"cyan",children:"$ gaia start"})]}),g(f,{marginTop:1,flexDirection:"column",children:[g(u,{children:["Web:"," ",g(u,{color:"cyan",bold:!0,children:["http://localhost:",r]})]}),g(u,{children:["API:"," ",g(u,{color:"cyan",bold:!0,children:["http://localhost:",n]})]})]}),i(f,{marginTop:1,children:i(u,{color:"gray",children:"gaia stop \xB7 gaia status \xB7 gaia setup"})}),i(f,{marginTop:1,children:g(u,{dimColor:!0,children:[i(u,{bold:!0,children:"Enter"})," to exit"]})})]})},Nr=8,wt=({logs:e,height:t=Nr})=>{let[o,r]=H(0),n=_r(e.length);Pe(()=>{e.length!==n.current&&(n.current=e.length,r(0))},[e.length]),ie((T,y)=>{y.upArrow?r(S=>Math.min(S+1,Math.max(0,e.length-t))):y.downArrow&&r(S=>Math.max(0,S-1))});let s=e.length,c=Math.max(0,s-t-o),a=Math.max(0,s-o),l=e.slice(c,a),p=c,x=o;return g(f,{flexDirection:"column",marginTop:1,marginLeft:1,children:[p>0&&g(u,{color:"gray",dimColor:!0,children:["\u2191 ",p," more line",p!==1?"s":""]}),i(f,{flexDirection:"column",height:t,overflow:"hidden",children:l.map((T,y)=>i(u,{color:"gray",wrap:"truncate",children:T},`${c}-${y}`))}),x>0?g(u,{color:"gray",dimColor:!0,children:["\u2193 ",x," more line",x!==1?"s":""]}):i(u,{color:"gray",dimColor:!0,children:"\u2191\u2193 scroll"})]})},Gr=({phase:e,progress:t,isComplete:o,logs:r,title:n})=>g(f,{flexDirection:"column",marginTop:1,paddingX:1,borderStyle:"round",borderColor:b,children:[i(f,{marginBottom:1,children:i(u,{bold:!0,color:b,children:n||"Installing Dependencies"})}),g(f,{flexDirection:"column",gap:1,children:[i(f,{children:o?g(u,{color:"green",children:["\u2713 ",e]}):i(Ye,{label:e||"Preparing..."})}),!o&&t>0&&i(f,{width:50,children:i(Et,{value:t})}),!o&&r&&r.length>0&&i(wt,{logs:r}),!o&&i(f,{marginTop:1,children:i(u,{color:"gray",dimColor:!0,children:"This may take a few minutes..."})})]})]});var Je=({onSelect:e})=>g(f,{flexDirection:"column",marginTop:1,paddingX:1,borderStyle:"round",borderColor:b,children:[i(u,{bold:!0,children:"Setup Mode"}),i(f,{marginTop:1,children:i(u,{color:"gray",children:"How do you want to run GAIA?"})}),i(f,{marginTop:1,children:i(Ke,{options:[{label:"Self-Host \u2014 run everything in Docker",value:"selfhost"},{label:"Developer \u2014 local dev with hot reload",value:"developer"}],onChange:o=>e(o)})})]}),ze=({onSelect:e})=>g(f,{flexDirection:"column",marginTop:1,paddingX:1,borderStyle:"round",borderColor:b,children:[i(u,{bold:!0,children:"Environment Variables Setup"}),i(f,{marginTop:1,children:i(u,{color:"gray",children:"Choose how you want to configure environment variables:"})}),i(f,{marginTop:1,children:i(Ke,{options:[{label:"Manual Setup (Recommended)",value:"manual"},{label:"Infisical (Advanced)",value:"infisical"}],onChange:o=>e(o)})}),g(f,{marginTop:1,flexDirection:"column",children:[i(u,{color:"gray",dimColor:!0,children:"Manual Setup: Configure variables interactively (recommended for most users)"}),i(u,{color:"gray",dimColor:!0,children:"Infisical: All secrets managed in Infisical dashboard (requires pre-configuration)"})]})]}),Ze=({onSubmit:e})=>{let[t,o]=H({INFISICAL_TOKEN:"",INFISICAL_PROJECT_ID:"",INFISICAL_MACHINE_IDENTITY_CLIENT_ID:"",INFISICAL_MACHINE_IDENTITY_CLIENT_SECRET:""}),[r,n]=H(0),[s,c]=H(null),a=[{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"}];ie((p,x)=>{if(x.tab||x.downArrow)n(T=>T<a.length-1?T+1:T);else if(x.upArrow)n(T=>T>0?T-1:T);else if(x.return){if(r<a.length-1){n(y=>y+1);return}let T=a.filter(y=>!t[y.key].trim());if(T.length>0){c(`Required: ${T.map(S=>S.key).join(", ")}`);let y=a.findIndex(S=>!t[S.key].trim());y>=0&&n(y);return}e(t)}});let l=a[r];return g(f,{flexDirection:"column",marginTop:1,paddingX:1,borderStyle:"round",borderColor:b,children:[i(f,{marginBottom:1,children:i(u,{bold:!0,color:b,children:"Infisical Configuration"})}),i(f,{marginBottom:1,children:i(u,{color:"gray",children:"All secrets managed in your Infisical project. Only credentials stored locally."})}),g(f,{marginBottom:1,flexDirection:"column",children:[i(u,{color:"gray",children:"Configure your Infisical credentials."}),g(u,{color:"gray",dimColor:!0,children:["Visit"," ",i(u,{color:"cyan",underline:!0,children:"app.infisical.com"})," ","to get these values."]})]}),a.map((p,x)=>{let T=p.key.includes("SECRET")||p.key.includes("TOKEN");return g(f,{flexDirection:"column",marginBottom:1,children:[i(f,{children:g(u,{color:x===r?b:"white",children:[x===r?"\u25B8 ":" ",p.key,":"]})}),i(f,{marginLeft:2,children:i(u,{color:"gray",dimColor:!0,children:p.description})}),x===r?i(f,{marginLeft:2,children:i(we,{value:t[p.key],onChange:y=>{o(S=>({...S,[p.key]:y})),c(null)},placeholder:"Enter value...",mask:T?"*":void 0})}):i(f,{marginLeft:2,children:i(u,{color:t[p.key]?"green":"gray",children:t[p.key]?T?`\u2713 ${"*".repeat(8)}`:`\u2713 ${t[p.key]}`:"(not set)"})})]},p.key)}),s&&i(f,{marginTop:1,children:i(u,{color:"red",children:s})}),i(f,{marginTop:1,children:g(u,{dimColor:!0,children:[i(u,{bold:!0,children:"Enter"})," confirm \xB7 ",i(u,{bold:!0,children:"\u2191\u2193"})," navigate"]})})]})},et=({category:e,currentIndex:t,totalGroups:o,onSubmit:r})=>{let[n,s]=H(()=>{let y={};for(let S of e.variables)y[S.name]=S.defaultValue||"";return y}),[c,a]=H(0),[l,p]=H(null);Pe(()=>{let y={};for(let S of e.variables)y[S.name]=S.defaultValue||"";s(y),a(0),p(null)},[e.name]),ie((y,S)=>{if(S.tab||S.downArrow)a(m=>m<e.variables.length-1?m+1:m);else if(S.upArrow)a(m=>m>0?m-1:m);else if(S.escape){let m=e.variables.filter(d=>d.required&&!n[d.name]?.trim());if(m.length>0){p(`Required fields cannot be skipped: ${m.map(d=>d.name).join(", ")}`);return}r(n)}});let x=()=>{if(c<e.variables.length-1)a(c+1);else{let y=e.variables.filter(S=>S.required&&!n[S.name]?.trim());if(y.length>0){p(`Required fields are missing: ${y.map(S=>S.name).join(", ")}`);return}p(null),r(n)}},T=e.variables.some(y=>y.required);return g(f,{flexDirection:"column",marginTop:1,paddingX:1,borderStyle:"round",borderColor:l?"red":b,children:[g(f,{justifyContent:"space-between",children:[g(u,{bold:!0,children:["Configure ",e.name]}),g(u,{color:"gray",children:["Group ",t+1," / ",o]})]}),i(f,{marginTop:1,children:i(u,{color:"gray",children:e.description})}),i(f,{marginTop:1,flexDirection:"column",children:e.variables.map((y,S)=>{let m=S===c,d=!!y.defaultValue;return g(f,{flexDirection:"column",marginBottom:1,children:[g(f,{children:[g(u,{color:m?b:"gray",bold:m,children:[m?"\u279C ":" ",y.name]}),y.required&&g(u,{color:"red",bold:!0,children:[" ","*"]}),d&&!m&&g(u,{color:"gray",dimColor:!0,children:[" ","(default: ",y.defaultValue,")"]})]}),m&&i(f,{marginLeft:2,children:i(we,{value:n[y.name]||"",onChange:h=>{s(v=>({...v,[y.name]:h})),l&&p(null)},onSubmit:x,placeholder:d?`Default: ${y.defaultValue}`:y.required?"Enter a value (required)":"Press Enter to skip"})})]},y.name)})}),l&&i(f,{marginTop:1,children:g(u,{color:"red",bold:!0,children:["\u26A0 ",l]})}),i(f,{marginTop:1,children:g(u,{dimColor:!0,children:[i(u,{bold:!0,children:"Enter"})," next \xB7 ",i(u,{bold:!0,children:"\u2191\u2193"})," navigate",!T&&g(u,{children:[" ","\xB7 ",i(u,{bold:!0,children:"ESC"})," skip"]})]})})]})},tt=({alternatives:e,onSubmit:t})=>{let[o,r]=H(new Set),[n,s]=H({}),[c,a]=H(0),[l,p]=H(null);Pe(()=>{let h={};for(let v of e)for(let I of v.variables)h[I.name]=I.defaultValue||"";s(h)},[e]);let x=[];for(let h=0;h<e.length;h++)if(x.push({type:"provider",categoryIndex:h}),o.has(h)){let v=e[h];if(v)for(let I=0;I<v.variables.length;I++)x.push({type:"field",categoryIndex:h,fieldIndex:I})}x.push({type:"submit"});let T=x[c],y=T?.type==="field",S=T?.type==="submit";ie((h,v)=>{let I=Math.min(c,x.length-1);if(I!==c){a(I);return}if(y)v.upArrow?a(C=>Math.max(0,C-1)):(v.downArrow||v.tab)&&a(C=>Math.min(x.length-1,C+1));else if(S)v.upArrow?a(C=>Math.max(0,C-1)):(v.return||h===" ")&&d();else if(v.upArrow)a(C=>Math.max(0,C-1));else if(v.downArrow||v.tab)a(C=>Math.min(x.length-1,C+1));else if((v.return||h===" ")&&T?.type==="provider"){let C=T.categoryIndex;r(k=>{let P=new Set(k);return P.has(C)?P.delete(C):P.add(C),P}),l&&p(null)}});let m=()=>{l&&p(null),a(h=>Math.min(x.length-1,h+1))},d=()=>{let h=[],v={};for(let I of o){let C=e[I];if(!C)continue;if(C.variables.some(P=>n[P.name]?.trim())){h.push(C.name);for(let P of C.variables){let de=n[P.name];de&&(v[P.name]=de)}}}if(h.length===0){o.size===0?p("Enable at least one provider (press Space or Enter)"):p("Enter a value for at least one field");return}t(h,v)};return g(f,{flexDirection:"column",marginTop:1,paddingX:1,borderStyle:"round",borderColor:l?"red":b,children:[g(f,{justifyContent:"space-between",children:[i(u,{bold:!0,children:"Configure AI Provider"}),i(u,{color:"yellow",children:"* At least one required"})]}),i(f,{marginTop:1,children:i(u,{color:"gray",children:"Enable and configure at least one AI provider below:"})}),i(f,{marginTop:1,flexDirection:"column",children:e.map((h,v)=>{let I=o.has(v),C=x.findIndex(P=>P.type==="provider"&&P.categoryIndex===v),k=c===C;return g(f,{flexDirection:"column",marginBottom:1,children:[g(f,{children:[i(u,{color:k?b:void 0,bold:k,children:k?"\u279C ":" "}),i(u,{color:I?"green":"gray",children:I?"[\u2714]":"[ ]"}),g(u,{color:I?b:"gray",bold:I,children:[" ",h.name]}),h.description&&g(u,{color:"gray",dimColor:!0,children:[" ","- ",h.description]})]}),k&&h.docsUrl&&g(f,{marginLeft:6,children:[i(u,{color:"yellow",children:"\u{1F4D6} "}),i(u,{color:"blue",underline:!0,children:h.docsUrl})]}),I&&i(f,{marginLeft:4,flexDirection:"column",marginTop:1,children:h.variables.map((P,de)=>{let be=x.findIndex(Ie=>Ie.type==="field"&&Ie.categoryIndex===v&&Ie.fieldIndex===de),me=c===be,vt=!!P.defaultValue,Xe=n[P.name]||"";return g(f,{flexDirection:"column",marginBottom:1,children:[g(f,{children:[g(u,{color:me?b:"gray",bold:me,children:[me?" \u279C ":" ",P.name]}),!me&&Xe&&i(u,{color:"green",children:" \u2713"}),!me&&!Xe&&vt&&g(u,{color:"gray",dimColor:!0,children:[" ","(default: ",P.defaultValue,")"]})]}),me&&i(f,{marginLeft:4,children:i(we,{value:Xe,onChange:Ie=>{s(br=>({...br,[P.name]:Ie})),l&&p(null)},onSubmit:m,placeholder:vt?`Default: ${P.defaultValue}`:"Enter value..."})})]},P.name)})})]},h.name)})}),l&&i(f,{marginTop:1,children:g(u,{color:"red",bold:!0,children:["\u26A0 ",l]})}),g(f,{marginTop:1,children:[i(u,{color:S?b:void 0,bold:S,children:S?"\u279C ":" "}),i(f,{borderStyle:"round",borderColor:S?b:"gray",paddingX:2,children:i(u,{color:S?b:"gray",bold:S,children:"Continue \u2192"})})]}),i(f,{marginTop:1,children:i(u,{color:"gray",dimColor:!0,children:"\u2191/\u2193 navigate \u2022 Space/Enter toggle/select \u2022 Tab skip field"})})]})},rt=({currentVar:e,currentIndex:t,totalCount:o,onSubmit:r,onSkip:n})=>{let[s,c]=H(e.defaultValue||""),[a,l]=H(null);Pe(()=>{c(e.defaultValue||""),l(null)},[e.name]),ie((T,y)=>{if(y.escape){if(e.required&&!s.trim()){l("This field is required and cannot be skipped");return}n()}});let p=T=>{if(e.required&&!T.trim()){l("This field is required");return}l(null),r(T)},x=!!e.defaultValue;return g(f,{flexDirection:"column",marginTop:1,paddingX:1,borderStyle:"round",borderColor:a?"red":b,children:[g(f,{justifyContent:"space-between",children:[g(f,{children:[i(u,{color:b,bold:!0,children:e.name}),e.required?i(u,{color:"red",children:" *"}):g(u,{color:"gray",dimColor:!0,children:[" ","optional"]})]}),g(u,{color:"gray",children:[t+1,"/",o]})]}),i(f,{marginLeft:1,children:i(u,{color:"gray",children:e.description})}),g(f,{marginTop:1,children:[i(u,{color:b,children:"\u2192 "}),i(we,{value:s,onChange:T=>{c(T),a&&l(null)},onSubmit:p,placeholder:x?`Default: ${e.defaultValue}`:e.required?"required":"skip with Enter"})]}),a&&i(f,{marginTop:1,children:i(u,{color:"red",children:a})}),i(f,{marginTop:1,children:g(u,{dimColor:!0,children:[i(u,{bold:!0,children:"Enter"})," confirm",!e.required&&g(u,{children:[" ","\xB7 ",i(u,{bold:!0,children:"ESC"})," skip"]})]})})]})},Pt=({store:e})=>{let[t,o]=H(e.currentState);return Pe(()=>{let r=()=>o({...e.currentState});return e.on("change",r),()=>{e.off("change",r)}},[e]),ie((r,n)=>{(n.return||n.escape)&&t.error&&e.submitInput("exit")}),g(Le,{status:t.status,step:t.step,children:[t.step==="Welcome"&&t.inputRequest?.id==="welcome"&&i(Lr,{onConfirm:()=>e.submitInput(!0)}),t.step==="Prerequisites"&&t.data.checks&&g(f,{flexDirection:"column",borderStyle:"round",paddingX:1,borderColor:b,children:[i(u,{bold:!0,children:"System Checks"}),g(f,{flexDirection:"column",marginTop:1,children:[i(ne,{label:"Git",status:t.data.checks.git}),i(ne,{label:"Docker",status:t.data.checks.docker}),i(ne,{label:"Mise",status:t.data.checks.mise})]})]}),t.inputRequest?.id==="port_conflicts"&&t.data.portConflicts&&i(Oe,{portResults:t.data.portConflicts,onAccept:()=>e.submitInput("accept"),onAbort:()=>e.submitInput("abort")}),t.inputRequest?.id==="repo_path"&&i(Or,{defaultValue:t.inputRequest.meta.default,onSubmit:r=>e.submitInput(r)}),t.inputRequest?.id==="existing_repo"&&t.data.existingRepoPath&&i(Mr,{repoPath:t.data.existingRepoPath,onAction:r=>e.submitInput(r)}),t.step==="Repository Setup"&&!t.inputRequest&&g(f,{flexDirection:"column",borderStyle:"round",padding:1,borderColor:b,children:[i(u,{bold:!0,children:"Cloning Repository"}),g(f,{marginTop:1,flexDirection:"column",children:[i(Et,{value:t.data.repoProgress||0}),t.data.repoPhase&&i(f,{marginTop:1,children:i(u,{color:"gray",children:t.data.repoPhase})})]})]}),t.inputRequest?.id==="setup_mode"&&i(Je,{onSelect:r=>e.submitInput(r)}),t.inputRequest?.id==="env_method"&&i(ze,{onSelect:r=>e.submitInput(r)}),t.inputRequest?.id==="env_infisical"&&i(Ze,{onSubmit:r=>e.submitInput(r)}),t.step==="Environment Setup"&&t.inputRequest?.id==="env_var"&&t.data.currentEnvVar&&i(rt,{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&&i(et,{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&&i(tt,{alternatives:t.data.alternativeGroups,onSubmit:(r,n)=>e.submitInput({selectedGroups:r,values:n})}),t.step==="Environment Setup"&&!t.inputRequest&&g(f,{flexDirection:"column",marginTop:1,paddingX:1,borderStyle:"round",borderColor:b,children:[i(u,{bold:!0,children:"Environment Setup"}),i(f,{marginTop:1,children:i(Ye,{label:t.status||"Configuring environment..."})})]}),t.step==="Finished"&&i(Fr,{setupMode:t.data.setupMode,portOverrides:t.data.portOverrides,onConfirm:()=>e.submitInput("exit")}),(t.step==="Install Tools"||t.step==="Project Setup")&&i(Gr,{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.step==="Installing CLI"&&g(f,{flexDirection:"column",borderStyle:"round",padding:1,borderColor:b,children:[i(u,{bold:!0,color:b,children:"Installing CLI"}),i(f,{marginTop:1,children:i(Ye,{label:t.status||"Installing gaia CLI globally..."})}),t.data.cliInstallLogs&&t.data.cliInstallLogs.length>0&&i(wt,{logs:t.data.cliInstallLogs})]}),t.error&&g(f,{flexDirection:"column",borderStyle:"single",borderColor:"red",padding:1,marginTop:2,children:[g(u,{color:"red",children:["Error: ",t.error.message]}),i(f,{marginTop:1,children:g(u,{dimColor:!0,children:[i(u,{bold:!0,children:"Enter"})," to exit"]})})]})]})};import{Spinner as $r}from"@inkjs/ui";import{Box as G,Text as R,useInput as Rt}from"ink";import{useEffect as Dt,useRef as qr,useState as kt}from"react";import{jsx as F,jsxs as w}from"react/jsx-runtime";var ot=8,jr=({logs:e})=>{let[t,o]=kt(0),r=qr(e.length);Dt(()=>{e.length!==r.current&&(r.current=e.length,o(0))},[e.length]),Rt((x,T)=>{T.upArrow?o(y=>Math.min(y+1,Math.max(0,e.length-ot))):T.downArrow&&o(y=>Math.max(0,y-1))});let n=e.length,s=Math.max(0,n-ot-t),c=Math.max(0,n-t),a=e.slice(s,c),l=s,p=t;return w(G,{flexDirection:"column",marginTop:1,marginLeft:1,children:[l>0&&w(R,{color:"gray",dimColor:!0,children:["\u2191 ",l," more line",l!==1?"s":""]}),F(G,{flexDirection:"column",height:ot,overflow:"hidden",children:a.map((x,T)=>F(R,{color:"gray",wrap:"truncate",children:x},s+T))}),p>0?w(R,{color:"gray",dimColor:!0,children:["\u2193 ",p," more line",p!==1?"s":""]}):F(R,{color:"gray",dimColor:!0,children:"\u2191\u2193 scroll"})]})},At=({store:e})=>{let[t,o]=kt(e.currentState);return Dt(()=>{let r=()=>o({...e.currentState});return e.on("change",r),()=>{e.off("change",r)}},[e]),Rt((r,n)=>{(n.return||n.escape)&&(t.data.started||t.data.stopped||t.error)&&e.submitInput("exit")}),w(G,{flexDirection:"column",width:"100%",children:[F(fe,{}),(t.step==="Starting"||t.step==="Stopping")&&w(G,{flexDirection:"column",marginTop:1,paddingX:2,borderStyle:"round",borderColor:b,children:[F($r,{label:t.status||"Working..."}),t.data.repoPath&&F(G,{marginTop:1,children:w(R,{color:"gray",children:["Repository: ",t.data.repoPath]})}),t.data.setupMode&&F(G,{children:w(R,{color:"gray",children:["Mode: ",t.data.setupMode]})}),t.data.dockerLogs&&t.data.dockerLogs.length>0&&F(jr,{logs:t.data.dockerLogs})]}),t.step==="Running"&&t.data.started&&w(G,{flexDirection:"column",marginTop:1,paddingX:2,paddingY:1,borderStyle:"round",borderColor:"green",children:[w(R,{color:"green",bold:!0,children:["\u2713"," GAIA is running!"]}),t.data.setupMode!=="developer"&&w(G,{marginTop:1,flexDirection:"column",children:[w(R,{children:["Web:"," ",w(R,{color:"cyan",bold:!0,children:["http://localhost:",t.data.webPort||3e3]})]}),w(R,{children:["API:"," ",w(R,{color:"cyan",bold:!0,children:["http://localhost:",t.data.apiPort||8e3]})]})]}),t.data.setupMode==="developer"&&w(G,{marginTop:1,flexDirection:"column",children:[w(G,{flexDirection:"column",children:[w(R,{children:["Web:"," ",w(R,{color:"cyan",bold:!0,children:["http://localhost:",t.data.webPort||3e3]})]}),w(R,{children:["API:"," ",w(R,{color:"cyan",bold:!0,children:["http://localhost:",t.data.apiPort||8e3]})]})]}),w(G,{marginTop:1,flexDirection:"column",children:[F(R,{color:"gray",children:"Dev servers started in background."}),w(R,{color:"gray",children:["Logs: ",F(R,{color:b,children:"dev-start.log"})," in your repo root."]}),w(R,{color:"gray",children:["Run ",F(R,{color:b,children:"gaia stop"})," to shut down."]})]})]}),F(G,{marginTop:1,children:w(R,{dimColor:!0,children:[F(R,{bold:!0,children:"Enter"})," to exit"]})})]}),t.step==="Stopped"&&t.data.stopped&&w(G,{flexDirection:"column",marginTop:1,paddingX:2,paddingY:1,borderStyle:"round",borderColor:b,children:[w(R,{color:b,bold:!0,children:["\u2713"," All GAIA services stopped."]}),F(G,{marginTop:1,children:w(R,{dimColor:!0,children:[F(R,{bold:!0,children:"Enter"})," to exit"]})})]}),t.error&&w(G,{borderStyle:"single",borderColor:"red",padding:1,marginTop:2,children:[w(R,{color:"red",children:["Error: ",t.error.message]}),F(G,{marginTop:1,children:w(R,{dimColor:!0,children:[F(R,{bold:!0,children:"Enter"})," to exit"]})})]})]})};import{ProgressBar as Hr,Spinner as nt}from"@inkjs/ui";import{Box as B,Text as L,useInput as Bt}from"ink";import{useEffect as Wr,useState as Vr}from"react";import{jsx as E,jsxs as _}from"react/jsx-runtime";var _t=({store:e})=>{let[t,o]=Vr(e.currentState);return Wr(()=>{let r=()=>o({...e.currentState});return e.on("change",r),()=>{e.off("change",r)}},[e]),Bt((r,n)=>{(n.return||n.escape)&&t.error&&e.submitInput("exit")}),_(Le,{status:t.status,step:t.step,steps:Ct,children:[t.step==="Detect Repo"&&_(B,{flexDirection:"column",paddingX:2,borderStyle:"round",borderColor:b,children:[E(L,{bold:!0,children:"Detecting GAIA Repository"}),E(B,{marginTop:1,children:E(nt,{label:"Searching for repository..."})}),t.data.repoPath&&E(B,{marginTop:1,children:_(L,{color:"green",children:["Found: ",t.data.repoPath]})})]}),t.step==="Prerequisites"&&t.data.checks&&_(B,{flexDirection:"column",borderStyle:"round",paddingX:1,borderColor:b,children:[E(L,{bold:!0,children:"System Checks"}),_(B,{flexDirection:"column",marginTop:1,children:[E(ne,{label:"Git",status:t.data.checks.git}),E(ne,{label:"Docker",status:t.data.checks.docker}),E(ne,{label:"Mise",status:t.data.checks.mise})]})]}),t.inputRequest?.id==="port_conflicts"&&t.data.portConflicts&&E(Oe,{portResults:t.data.portConflicts,onAccept:()=>e.submitInput("accept"),onAbort:()=>e.submitInput("abort")}),t.inputRequest?.id==="setup_mode"&&E(Je,{onSelect:r=>e.submitInput(r)}),t.inputRequest?.id==="env_method"&&E(ze,{onSelect:r=>e.submitInput(r)}),t.inputRequest?.id==="env_infisical"&&E(Ze,{onSubmit:r=>e.submitInput(r)}),t.step==="Environment Setup"&&t.inputRequest?.id==="env_var"&&t.data.currentEnvVar&&E(rt,{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&&E(et,{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&&E(tt,{alternatives:t.data.alternativeGroups,onSubmit:(r,n)=>e.submitInput({selectedGroups:r,values:n})}),t.step==="Environment Setup"&&!t.inputRequest&&_(B,{flexDirection:"column",marginTop:1,paddingX:1,borderStyle:"round",borderColor:b,children:[E(L,{bold:!0,children:"Environment Setup"}),E(B,{marginTop:1,children:E(nt,{label:t.status||"Configuring environment..."})})]}),t.step==="Project Setup"&&_(B,{flexDirection:"column",marginTop:1,paddingX:1,borderStyle:"round",borderColor:b,children:[E(B,{marginBottom:1,children:E(L,{bold:!0,color:b,children:"Project Setup"})}),_(B,{flexDirection:"column",gap:1,children:[E(B,{children:t.data.dependencyComplete?_(L,{color:"green",children:["\u2713"," ",t.data.dependencyPhase]}):E(nt,{label:t.data.dependencyPhase||"Preparing..."})}),!t.data.dependencyComplete&&t.data.dependencyProgress>0&&E(B,{width:50,children:E(Hr,{value:t.data.dependencyProgress})}),!t.data.dependencyComplete&&t.data.dependencyLogs?.length>0&&E(B,{flexDirection:"column",marginTop:1,marginLeft:1,children:t.data.dependencyLogs.map((r,n)=>E(L,{color:"gray",wrap:"truncate",children:r},n))})]})]}),t.step==="Finished"&&E(Ur,{setupMode:t.data.setupMode,portOverrides:t.data.portOverrides,onConfirm:()=>e.submitInput("exit")}),t.error&&_(B,{flexDirection:"column",borderStyle:"single",borderColor:"red",padding:1,marginTop:2,children:[_(L,{color:"red",children:["Error: ",t.error.message]}),E(B,{marginTop:1,children:_(L,{dimColor:!0,children:[E(L,{bold:!0,children:"Enter"})," to exit"]})})]})]})},Ur=({portOverrides:e,onConfirm:t})=>{Bt((n,s)=>{s.return&&t()});let o=e?.[3e3]??3e3,r=e?.[8e3]??8e3;return _(B,{flexDirection:"column",marginTop:2,borderStyle:"round",borderColor:b,padding:1,children:[E(L,{color:b,bold:!0,children:"Setup Complete!"}),_(B,{marginTop:1,children:[E(L,{bold:!0,children:"Run: "}),E(L,{color:"cyan",children:"$ gaia start"})]}),_(B,{marginTop:1,flexDirection:"column",children:[_(L,{children:["Web:"," ",_(L,{color:"cyan",bold:!0,children:["http://localhost:",o]})]}),_(L,{children:["API:"," ",_(L,{color:"cyan",bold:!0,children:["http://localhost:",r]})]})]}),E(B,{marginTop:1,children:E(L,{color:"gray",children:"gaia stop \xB7 gaia status \xB7 gaia setup"})}),E(B,{marginTop:1,children:_(L,{dimColor:!0,children:[E(L,{bold:!0,children:"Enter"})," to exit"]})})]})};import{Spinner as Xr}from"@inkjs/ui";import{Box as O,Text as A,useInput as Qr}from"ink";import{useEffect as Lt,useState as it}from"react";import{jsx as D,jsxs as $}from"react/jsx-runtime";var Ot=({store:e})=>{let[t,o]=it(e.currentState),[r,n]=it(!1),[s,c]=it(null);return Lt(()=>{let a=()=>o({...e.currentState});return e.on("change",a),()=>{e.off("change",a)}},[e]),Lt(()=>{n(!1),c(new Date().toLocaleTimeString())},[t.data.services]),Qr((a,l)=>{(l.return||l.escape)&&t.step==="Results"&&e.submitInput("exit"),a==="r"&&t.step==="Results"&&t.data.refreshable&&!r&&(n(!0),e.submitInput("refresh"))}),$(O,{flexDirection:"column",width:"100%",children:[D(fe,{}),t.step==="Checking"&&D(O,{marginTop:1,children:D(Xr,{label:t.data.services?"Refreshing service health...":"Checking service health..."})}),t.step==="Results"&&t.data.services&&$(O,{flexDirection:"column",children:[$(O,{flexDirection:"column",borderStyle:"round",borderColor:b,paddingX:2,paddingY:1,children:[$(O,{justifyContent:"space-between",children:[D(A,{bold:!0,color:b,children:"GAIA Service Status"}),s&&$(A,{color:"gray",dimColor:!0,children:["checked ",s," \xB7 ",D(A,{bold:!0,children:"r"})," refresh"]})]}),$(O,{marginTop:1,flexDirection:"column",children:[$(O,{children:[D(O,{width:22,children:D(A,{bold:!0,children:"Service"})}),D(O,{width:10,children:D(A,{bold:!0,children:"Status"})}),D(O,{width:10,children:D(A,{bold:!0,children:"Latency"})})]}),D(A,{color:"gray",children:"\u2500".repeat(42)}),[...t.data.services].sort((a,l)=>a.status==="down"&&l.status!=="down"?-1:a.status!=="down"&&l.status==="down"?1:a.name.localeCompare(l.name)).map(a=>$(O,{children:[D(O,{width:22,children:$(A,{children:[a.name," (:",a.port,")"]})}),D(O,{width:10,children:D(A,{color:a.status==="up"?"green":"red",bold:!0,children:a.status==="up"?"\u2713 UP":"\u2717 DOWN"})}),D(O,{width:10,children:D(A,{color:"gray",children:a.latency?`${a.latency}ms`:"--"})})]},a.name))]})]}),t.data.docker&&$(O,{flexDirection:"column",borderStyle:"round",borderColor:"gray",paddingX:2,paddingY:1,marginTop:1,children:[D(A,{bold:!0,children:"Docker Containers"}),$(A,{color:"gray",children:["Docker:"," ",t.data.docker.running?D(A,{color:"green",children:"Running"}):D(A,{color:"red",children:"Not running"})]}),t.data.docker.containers?.length>0&&D(O,{marginTop:1,flexDirection:"column",children:t.data.docker.containers.map(a=>$(O,{children:[$(A,{color:a.status==="running"?"green":"red",children:[a.status==="running"?"\u2713":"\u2717"," "]}),D(A,{children:a.name}),a.health&&$(A,{color:"gray",children:[" (",a.health,")"]})]},a.name))})]}),D(O,{marginTop:1,children:$(A,{dimColor:!0,children:[D(A,{bold:!0,children:"Enter"})," exit \xB7 ",D(A,{bold:!0,children:"r"})," refresh"]})})]}),t.error&&D(O,{borderStyle:"single",borderColor:"red",padding:1,marginTop:2,children:$(A,{color:"red",children:["Error: ",t.error.message]})})]})};import{jsx as Y,jsxs as Re}from"react/jsx-runtime";var Kr=["init","setup","status","start","stop"],at=class extends Yr.Component{constructor(t){super(t),this.state={error:null}}static getDerivedStateFromError(t){return{error:t}}render(){return this.state.error?Re(Me,{flexDirection:"column",padding:1,children:[Y(pe,{color:"red",bold:!0,children:"An unexpected error occurred:"}),Y(pe,{color:"red",children:this.state.error.message}),this.state.error.stack&&Y(Me,{marginTop:1,children:Y(pe,{color:"gray",dimColor:!0,children:this.state.error.stack})})]}):this.props.children}},Jr=({store:e,command:t})=>{switch(t){case"init":return Y(Pt,{store:e});case"setup":return Y(_t,{store:e});case"status":return Y(Ot,{store:e});case"start":case"stop":return Y(At,{store:e,command:t});default:return Re(Me,{flexDirection:"column",padding:1,children:[Re(pe,{color:"red",children:["Unknown command: ",t]}),Re(Me,{marginTop:1,flexDirection:"column",children:[Y(pe,{bold:!0,children:"Available commands:"}),Kr.map(o=>Re(pe,{children:[" ",Y(pe,{color:"cyan",children:o})]},o))]})]})}},K=({store:e,command:t})=>Y(at,{children:Y(Jr,{store:e,command:t})});import{EventEmitter as zr}from"events";var Zr=150,st=class extends zr{state={step:"init",status:"",error:null,data:{},inputRequest:null};inputResolver=null;emitTimer=null;emitPending=!1;get currentState(){return this.state}scheduleEmit(){this.emitPending=!0,this.emitTimer||(this.emitTimer=setTimeout(()=>{this.emitTimer=null,this.emitPending&&(this.emitPending=!1,this.emit("change",this.state))},Zr))}emitNow(){this.emitTimer&&(clearTimeout(this.emitTimer),this.emitTimer=null),this.emitPending=!1,this.emit("change",this.state)}setStep(t){this.state.step=t,this.emitNow()}setStatus(t){this.state.status=t,this.scheduleEmit()}setError(t){this.state.error=t,t!==null&&this.inputResolver&&(this.inputResolver(null),this.inputResolver=null,this.state.inputRequest=null),this.emitNow()}updateData(t,o){this.state.data={...this.state.data,[t]:o},this.scheduleEmit()}waitForInput(t,o,r){return this.state.inputRequest={id:t,meta:o},this.emitNow(),new Promise(n=>{if(this.inputResolver=n,r!=null){let s=setTimeout(()=>{this.inputResolver&&(this.inputResolver=null,this.state.inputRequest=null,this.emitNow(),n(null))},r),c=this.inputResolver;this.inputResolver=a=>{clearTimeout(s),c(a)}}})}submitInput(t){this.inputResolver&&(this.inputResolver(t),this.inputResolver=null,this.state.inputRequest=null,this.emitNow())}},J=()=>new st;import*as re from"fs";import*as sr from"os";import*as se from"path";import*as ee from"fs";import*as Mt from"os";import*as ut from"path";var ct=ut.join(Mt.homedir(),".gaia"),lt=ut.join(ct,"config.json"),Fe="0.1.10";function eo(){ee.existsSync(ct)||ee.mkdirSync(ct,{recursive:!0})}function pt(){try{if(!ee.existsSync(lt))return null;let e=ee.readFileSync(lt,"utf-8");return JSON.parse(e)}catch{return null}}function Ne(e){eo(),ee.writeFileSync(lt,`${JSON.stringify(e,null,2)}
3
- `)}function De(e){let o={...pt()??{version:Fe,setupComplete:!1,setupMethod:"manual",repoPath:"",createdAt:new Date().toISOString(),updatedAt:new Date().toISOString()},...e,updatedAt:new Date().toISOString()};Ne(o)}import*as Jt from"path";import*as he from"node:fs";import*as ge from"node:path";import{execa as Ft}from"execa";var dt={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/"}},Nt={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 mt(e,t){return dt[t][e]??Nt[t][e]}async function Gt(e){let t=ge.join(e,"apps/api/scripts/dump_config_schema.py"),o=ge.join(e,"apps/api/app/config/settings_validator.py"),r=ge.join(e,"apps/api/app/config/settings.py");if(!he.existsSync(t))throw new Error("dump_config_schema.py not found in apps/api/scripts");try{try{let{stdout:n}=await Ft("python3",[t,o,r],{cwd:e});return JSON.parse(n)}catch{let{stdout:n}=await Ft("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 $t(e){let t=ge.join(e,"apps","web",".env.local"),o=he.existsSync(t)?t:ge.join(e,"apps","web",".env");if(!he.existsSync(o))return[];let r=he.readFileSync(o,"utf-8"),n=[],s="General";for(let c of r.split(`
4
- `)){let a=c.trim();if(a.startsWith("#")&&!a.startsWith("#=")){let T=a.replace(/^#+\s*/,"").trim();T&&!T.startsWith("These are")&&(s=T);continue}if(!a||a.startsWith("#"))continue;let l=a.indexOf("=");if(l===-1)continue;let p=a.substring(0,l).trim(),x=a.substring(l+1).trim();n.push({name:p,value:x,category:s})}return n}function qt(e,t){return{NEXT_PUBLIC_API_BASE_URL:`http://localhost:${t?.[8e3]??8e3}/api/v1/`}}function jt(e,t,o){let r=o==="selfhost"?new Set(Object.keys(dt.selfhost)):new Set;for(let[n,s]of Object.entries(t)){let c=Number(n),a=Number(s);for(let[l,p]of Object.entries(e)){if(r.has(l))continue;if(p===String(c)){e[l]=String(a);continue}let x=new RegExp(`:${c}(?=[/\\s]|$)`,"g");e[l]=p.replaceAll(x,`:${a}`)}}}function Ht(e,t){return e.map(o=>({...o,variables:o.variables.map(r=>{let n=mt(r.name,t);return{...r,defaultValue:n||r.defaultValue}})}))}function ft(){return Object.keys(dt.selfhost)}function Wt(e){return{...Nt[e]}}import*as W from"fs";import*as Se from"path";function gt(e){W.existsSync(e)&&W.copyFileSync(e,`${e}.bak`)}function Ut(e,t){let o=Se.join(e,".env");gt(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 s(a){for(let p of n)if(a===p||a.startsWith(`${p}_`))return p;let l=a.split("_");return l.length===1?"Core":l[0]||"Core"}let c=new Map;for(let[a,l]of Object.entries(t)){let p=s(a);c.has(p)||c.set(p,[]);let T=/[\s#"'\\]/.test(l)||l===""?`"${l.replace(/\\/g,"\\\\").replace(/"/g,'\\"')}"`:l;c.get(p).push(`${a}=${T}`)}for(let[a,l]of c.entries())r.push(`# ${a} Configuration`),r.push(...l),r.push("");W.writeFileSync(o,r.join(`
5
- `),"utf-8")}function Xt(e,t,o){let r=Se.join(e,"apps","web",".env.local");gt(r);let n=$t(e),s=qt(t,o),c=["# GAIA Web App Environment Configuration","# Generated by GAIA CLI",`# Created: ${new Date().toISOString()}`,""],a=new Map;for(let l of n){a.has(l.category)||a.set(l.category,[]);let p=s[l.name]??l.value;a.get(l.category).push({name:l.name,value:p})}if(n.length===0){c.push("# Core URLs");for(let[l,p]of Object.entries(s))c.push(`${l}=${p}`);c.push("")}else for(let[l,p]of a.entries()){c.push(`# ${l}`);for(let{name:x,value:T}of p)c.push(`${x}=${T}`);c.push("")}W.writeFileSync(r,c.join(`
6
- `),"utf-8")}var Qt={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 Yt(e,t,o){let r=Se.join(e,"infra","docker",".env");gt(r);let n=["# Docker Compose environment overrides","# Generated by GAIA CLI",`# Created: ${new Date().toISOString()}`,""];for(let[s,c]of Object.entries(t)){let a=Number(s),l=Qt[a];l&&n.push(`${l}=${c}`)}if(o==="selfhost"){let s=t[8e3]??8e3;n.push(""),n.push("# Web build args"),n.push(`NEXT_PUBLIC_API_BASE_URL=http://localhost:${s}/api/v1/`)}n.push(""),W.writeFileSync(r,n.join(`
7
- `),"utf-8")}function xe(e){let t={};for(let[o,r]of Object.entries(e)){let n=Number(o),s=Qt[n];s&&(t[s]=String(r))}return t}function Kt(e){let t=Se.join(e,"infra","docker","docker-compose.yml");if(!W.existsSync(t))return;let o=W.readFileSync(t,"utf-8"),r=[{varName:"API_HOST_PORT",hostPort:8e3,containerPort:80},{varName:"CHROMADB_HOST_PORT",hostPort:8080,containerPort:8e3},{varName:"POSTGRES_HOST_PORT",hostPort:5432,containerPort:5432},{varName:"REDIS_HOST_PORT",hostPort:6379,containerPort:6379},{varName:"MONGO_HOST_PORT",hostPort:27017,containerPort:27017},{varName:"RABBITMQ_HOST_PORT",hostPort:5672,containerPort:5672},{varName:"MONGO_EXPRESS_HOST_PORT",hostPort:8083,containerPort:8081},{varName:"WEB_HOST_PORT",hostPort:3e3,containerPort:3e3}],n=!1;for(let{varName:s,hostPort:c,containerPort:a}of r){let l=`"${c}:${a}"`,p=`"\${${s}:-${c}}:${a}"`;o.includes(l)&&(o=o.replaceAll(l,p),n=!0)}n&&W.writeFileSync(t,o,"utf-8")}var Vt={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 ye(e){let t=Se.join(e,"infra","docker",".env"),o={};if(!W.existsSync(t))return o;let r=W.readFileSync(t,"utf-8");for(let n of r.split(`
8
- `)){let s=n.trim();if(s&&!s.startsWith("#")){let[c,...a]=s.split("=");if(c&&Vt[c]){let l=a.join("=").trim().replace(/^["']|["']$/g,""),p=Number(l);!Number.isNaN(p)&&p>0&&p<=65535&&(o[Vt[c]]=p)}}}return o}var oo=e=>new Promise(t=>setTimeout(t,e));async function Ge(e){e.setStep("Setup Mode"),e.setStatus("Choose how to run GAIA...");let t=await e.waitForInput("setup_mode");return e.updateData("setupMode",t),t}async function $e(e,t,o,r){e.setStep("Environment Setup"),e.setStatus("Configuring environment..."),e.updateData("setupMode",o),e.setStatus("Configuring environment variables...");let n=await e.waitForInput("env_method");e.updateData("envMethod",n);let s={};s.ENV="development";let c=ft();for(let l of c){let p=mt(l,o);p&&(s[l]=p)}let a=Wt(o);for(let[l,p]of Object.entries(a))s[l]=p;if(n==="infisical")await no(e,s),e.setStatus("Infisical credentials saved. Ensure your Infisical project contains all required variables.");else try{await io(e,t,s,o)}catch(l){e.setError(l);return}r&&jt(s,r,o);try{await ao(e,t,s,o,r)}catch(l){e.setError(l);return}await oo(1e3)}async function no(e,t){e.setStatus("Configuring Infisical...");let o=await e.waitForInput("env_infisical");t.INFISICAL_TOKEN=o.INFISICAL_TOKEN,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 io(e,t,o,r){e.setStatus("Parsing environment variables...");let n;try{n=await Gt(t),n=Ht(n,r)}catch(m){throw r==="selfhost"?new Error(`Manual environment setup requires Python to parse config schema.
2
+ import{Command as qi}from"commander";var ie={init:"Full setup from scratch (clone, configure, start)",setup:"Configure an existing GAIA repository",status:"Check health of all GAIA services",start:"Start GAIA services (self-host mode)",dev:"Run developer mode in Nx TUI (`gaia dev` or `gaia dev full`)",logs:"Stream logs for running GAIA services",stop:"Stop all GAIA services (safe mode by default)"};import{homedir as Ar}from"node:os";import{join as Tn,resolve as Cn}from"node:path";import{Command as In}from"commander";import{existsSync as qe,mkdirSync as Wo,readFileSync as ir,writeFileSync as wt}from"node:fs";import{homedir as Vo}from"node:os";import{join as bt}from"node:path";var j={PING:"ping",MCP_OPEN:"mcp.open",MCP_CLOSE:"mcp.close",MCP_MSG:"mcp.msg",REVOKE:"revoke",PONG:"pong",HELLO:"hello",MCP_OPENED:"mcp.opened",MCP_ERROR:"mcp.error"},Zt="https://api.heygaia.io",ye="filesystem",er=500,tr=6e4,rr=5e3,or=1e6,nr=5e6;var je=bt(Vo(),".gaia","bridge"),De=bt(je,"credentials.json"),xt=bt(je,"config.json");function sr(){qe(je)||Wo(je,{recursive:!0,mode:448})}function de(){if(!qe(De))return null;try{return JSON.parse(ir(De,"utf-8"))}catch{return null}}function xe(e){sr(),wt(De,JSON.stringify(e,null,2),{mode:384})}function ar(){qe(De)&&wt(De,"{}",{mode:384})}function q(){if(!qe(xt))return{servers:[]};try{return{servers:JSON.parse(ir(xt,"utf-8")).servers??[]}}catch{return{servers:[]}}}function cr(e){sr(),wt(xt,JSON.stringify(e,null,2),{mode:384})}function Ue(e){let t=q(),r=t.servers.findIndex(o=>o.key===e.key);r>=0?t.servers[r]=e:t.servers.push(e),cr(t)}function lr(e){let t=q(),r=t.servers.length;return t.servers=t.servers.filter(o=>o.key!==e),cr(t),t.servers.length<r}function pr(){return q().servers.find(e=>e.type==="filesystem"&&e.key===ye)}function He(e){if(e)return e.replace(/\/$/,"");let t=de();return t?.apiUrl?t.apiUrl.replace(/\/$/,""):(process.env.GAIA_API_URL??Zt).replace(/\/$/,"")}import{hostname as Xo,platform as Jo}from"node:os";var ur={name:"@heygaia/cli",description:"CLI tool for setting up and managing GAIA",version:"0.5.0",type:"module",files:["dist","README.md"],scripts:{build:"esbuild src/index.ts --bundle --platform=node --target=node18 --format=esm --packages=external --outfile=dist/index.js --minify && chmod +x dist/index.js",check:"biome check src",dev:"tsx watch src/index.ts",fix:"biome check --write src",format:"biome format --write src",lint:"pnpm run check","lint:fix":"pnpm run fix",prepublishOnly:"pnpm run build",start:"NODE_ENV=production node dist/index.js","type-check":"tsc --noEmit"},dependencies:{"@inkjs/ui":"^2.0.0","@modelcontextprotocol/sdk":"^1.29.0",commander:"^14.0.3",execa:"^9.6.1",ink:"^6.8.0","ink-big-text":"^2.0.0","ink-gradient":"^3.0.0","ink-text-input":"^6.0.0",react:"19.1.0","react-dom":"19.1.0","simple-git":"^3.36.0",ws:"^8.21.0",zod:"^4.3.6"},devDependencies:{"@biomejs/biome":"^2.5.7","@types/node":"^24.13.3","@types/react":"^19.2.17","@types/react-dom":"^19.2.3","@types/ws":"^8.18.1",esbuild:"^0.25.12",tsx:"^4.23.11",typescript:"^7.0.2",vite:"^7.3.6",vitest:"^4.1.10"},bin:{gaia:"./dist/index.js"},engines:{node:">=20"},keywords:["ai-assistant","cli","gaia","setup"],license:"MIT",publishConfig:{access:"public"},repository:{type:"git",url:"git+https://github.com/theexperiencecompany/gaia.git",directory:"packages/cli"}};var ee=ur.version;var ke=class extends Error{constructor(r,o){super(r);this.status=o;this.name="ApiError"}};async function We(e,t,r,o){let n=await fetch(`${e}/api/v1${t}`,{method:"POST",headers:{"content-type":"application/json",...o?{authorization:`Bearer ${o}`}:{}},body:JSON.stringify(r)});if(!n.ok){let i=`${n.status} ${n.statusText}`;try{let a=await n.json();a.detail&&(i=a.detail)}catch{}throw new ke(i,n.status)}return await n.json()}function dr(e,t,r,o){return We(e,"/device/pair/start",{name:t,platform:r,daemon_version:o})}function mr(e,t){return We(e,"/device/pair/poll",{device_code:t})}function Ve(e,t){return We(e,"/device/token",{refresh_token:t})}function fr(e,t,r,o){return We(e,"/device/servers",{server_key:r,display_name:o},t)}async function Ko(e){await new Promise(t=>setTimeout(t,e))}function gr(){return!!de()?.refreshToken}async function Ye(e={}){let t=He(e.api),r=e.name||Xo(),o=await dr(t,r,Jo(),ee);console.info(`
3
+ To pair this device, open:
4
+ `),console.info(` ${o.verification_url}`),console.info(`
5
+ and enter this code: ${o.user_code}
6
+ `),console.info("Waiting for approval\u2026");let n=Date.now()+o.expires_in*1e3;for(;Date.now()<n;){await Ko(o.interval*1e3);let i;try{i=await mr(t,o.device_code)}catch(a){console.error(`[gaia bridge] poll failed, retrying: ${a instanceof Error?a.message:a}`);continue}if(i.status==="approved"&&i.device_id&&i.refresh_token){xe({apiUrl:t,deviceId:i.device_id,refreshToken:i.refresh_token}),console.info(`
7
+ Paired as "${r}".
8
+ `);return}if(i.status==="denied"||i.status==="expired")throw new Error(`pairing ${i.status}`)}throw new Error("pairing timed out")}import{randomInt as mn}from"node:crypto";import Cr from"ws";import{Client as cn}from"@modelcontextprotocol/sdk/client/index.js";import{getDefaultEnvironment as ln,StdioClientTransport as pn}from"@modelcontextprotocol/sdk/client/stdio.js";import{StreamableHTTPClientTransport as un}from"@modelcontextprotocol/sdk/client/streamableHttp.js";import{InMemoryTransport as dn}from"@modelcontextprotocol/sdk/inMemory.js";import{lstat as Qo,readdir as yr,readFile as hr,realpath as zo,stat as Zo,writeFile as en}from"node:fs/promises";import{dirname as vr,extname as tn,join as xr,resolve as rn,sep as on}from"node:path";import{McpServer as nn}from"@modelcontextprotocol/sdk/server/mcp.js";import{z as we}from"zod";var sn={".png":"image/png",".jpg":"image/jpeg",".jpeg":"image/jpeg",".webp":"image/webp",".gif":"image/gif"},be=class extends Error{};async function Tt(e){try{return await zo(e)}catch{return null}}async function an(e){try{return(await Qo(e)).isSymbolicLink()}catch{return!1}}function Sr(e,t){return e===t||e.startsWith(t+on)}async function Xe(e,t,r){let o=rn(e),n=await Tt(o);if(n){if(t.some(a=>Sr(n,a)))return n;throw new be(`Path is outside your approved folders: ${e}`)}if(r)throw new be(`No such file or directory: ${e}`);let i=await Tt(vr(o));if(!i||!t.some(a=>Sr(i,a)))throw new be(`Path is outside your approved folders: ${e}`);if(await an(o))throw new be(`Refusing to write through a symlink: ${e}`);return xr(i,o.slice(vr(o).length+1))}async function wr(e,t,r,o){if(o.length>=r)return;let n;try{n=await yr(e,{withFileTypes:!0})}catch{return}for(let i of n){if(o.length>=r)return;let a=xr(e,i.name);i.name.toLowerCase().includes(t.toLowerCase())&&o.push(a),i.isDirectory()&&!i.isSymbolicLink()&&await wr(a,t,r,o)}}function br(e){let t=new nn({name:"gaia-filesystem",version:"0.1.0"}),r=null,o=()=>(r||(r=Promise.all(e.allow.map(Tt)).then(i=>i.filter(a=>a!==null))),r),n=i=>({isError:!0,content:[{type:"text",text:i}]});return t.registerTool("list_directory",{description:"List the entries (files and folders) in a directory on the user's machine.",inputSchema:{path:we.string().describe("Absolute path to a directory")}},async({path:i})=>{try{let a=await Xe(i,await o(),!0);return{content:[{type:"text",text:(await yr(a,{withFileTypes:!0})).map(p=>`${p.isDirectory()?"dir ":"file"} ${p.name}`).join(`
9
+ `)||"(empty)"}]}}catch(a){return n(a instanceof Error?a.message:String(a))}}),t.registerTool("read_file",{description:"Read the contents of a text or image file on the user's machine.",inputSchema:{path:we.string().describe("Absolute path to a file")}},async({path:i})=>{try{let a=await Xe(i,await o(),!0),s=await Zo(a);if(!s.isFile())return n(`Not a file: ${i}`);let c=sn[tn(a).toLowerCase()];if(c){if(s.size>nr)return n(`Image is too large to read (${s.size} bytes).`);let f=await hr(a);return{content:[{type:"text",text:`Image file ${a} (${c}, ${s.size} bytes) \u2014 shown below.`},{type:"image",data:f.toString("base64"),mimeType:c}]}}return s.size>or?n(`File is too large to read (${s.size} bytes).`):{content:[{type:"text",text:await hr(a,"utf-8")}]}}catch(a){return n(a instanceof Error?a.message:String(a))}}),t.registerTool("search_files",{description:"Recursively find files/folders whose name contains a query, under a directory.",inputSchema:{path:we.string().describe("Absolute path to the directory to search under"),query:we.string().describe("Substring to match against names")}},async({path:i,query:a})=>{try{let s=await Xe(i,await o(),!0),c=[];return await wr(s,a,200,c),{content:[{type:"text",text:c.join(`
10
+ `)||"(no matches)"}]}}catch(s){return n(s instanceof Error?s.message:String(s))}}),e.allowWrite&&t.registerTool("write_file",{description:"Write text to a file on the user's machine (overwrites if it exists).",inputSchema:{path:we.string().describe("Absolute path to the file to write"),content:we.string().describe("Text content to write")}},async({path:i,content:a})=>{try{let s=await Xe(i,await o(),!1);return await en(s,a,"utf-8"),{content:[{type:"text",text:`Wrote ${a.length} bytes to ${i}`}]}}catch(s){return n(s instanceof Error?s.message:String(s))}}),t}async function Ct(e){if(e.type==="url"){let n=new un(new URL(e.url));return{transport:n,close:()=>n.close()}}if(e.type==="stdio"){let n=new pn({command:e.command,args:e.args,env:{...ln(),...e.env}});return{transport:n,close:()=>n.close()}}let[t,r]=dn.createLinkedPair(),o=br(e);return await o.connect(r),{transport:t,close:async()=>{await o.close(),await t.close()}}}async function Tr(e){let t=await Ct(e),r=new cn({name:"gaia-bridge-test",version:"0.1.0"});try{await r.connect(t.transport);let{tools:o}=await r.listTools();return o.map(n=>n.name)}finally{try{await r.close(),await t.close()}catch{}}}var Je=class{constructor(t){this.creds=t}ws=null;sessions=new Map;reconnectDelay=er;stopped=!1;async run(){for(;!this.stopped;){try{await this.connectOnce()}catch(t){t instanceof ke&&t.status===401?(console.error("[gaia bridge] this device is no longer authorized (revoked or unpaired). Re-pair with: gaia bridge login"),this.stopped=!0):console.error(`[gaia bridge] connection error: ${t instanceof Error?t.message:t}`)}if(this.stopped)break;await this.backoff()}}async stop(){this.stopped=!0,await this.closeAllSessions(),this.ws?.close()}async connectOnce(){let t=await Ve(this.creds.apiUrl,this.creds.refreshToken);this.creds={...this.creds,refreshToken:t.refresh_token},xe(this.creds);let r=`${this.creds.apiUrl.replace(/^http/,"ws")}/api/v1/ws/device`,o=new Cr(r,{headers:{authorization:`Bearer ${t.access_token}`}});this.ws=o,await new Promise((n,i)=>{let a=!1,s=!1,c=p=>{s||(s=!0,p())};o.on("open",()=>{a=!0,this.reconnectDelay=rr;let p=q().servers.map(f=>f.key);this.send({t:j.HELLO,servers:p}),console.error(`[gaia bridge] connected \u2014 exposing: ${p.join(", ")||"(nothing configured)"}`)}),o.on("message",p=>{this.onFrame(p.toString())}),o.on("close",()=>{this.closeAllSessions(),this.ws=null,c(()=>a?n():i(new Error("socket closed before open")))}),o.on("error",p=>{a||c(()=>i(p))})})}async onFrame(t){let r;try{r=JSON.parse(t)}catch{return}switch(r.t){case j.PING:this.send({t:j.PONG});return;case j.MCP_OPEN:await this.openSession(r);return;case j.MCP_MSG:await this.forwardToServer(r);return;case j.MCP_CLOSE:await this.closeSession(r.sid);return;case j.REVOKE:console.error("[gaia bridge] this device was revoked \u2014 exiting."),await this.stop();return;default:return}}async openSession(t){let r=t.sid,o=t.server,n=t.pod;if(!r||!o)return;let i=q().servers.find(a=>a.key===o);if(!i){this.send({t:j.MCP_ERROR,sid:r,pod:n,error:`Unknown server '${o}'`});return}try{let a=await Ct(i);a.transport.onmessage=s=>{this.send({t:j.MCP_MSG,sid:r,pod:n,data:JSON.stringify(s)})},a.transport.onclose=()=>{this.sessions.has(r)&&this.send({t:j.MCP_ERROR,sid:r,pod:n,error:`Local server '${o}' exited`}),this.closeSession(r)},await a.transport.start(),this.sessions.set(r,a),this.send({t:j.MCP_OPENED,sid:r,pod:n})}catch(a){this.send({t:j.MCP_ERROR,sid:r,pod:n,error:a instanceof Error?a.message:String(a)})}}async forwardToServer(t){let r=t.sid?this.sessions.get(t.sid):void 0;if(!(!r||!t.data))try{let o=JSON.parse(t.data);await r.transport.send(o)}catch(o){console.error(`[gaia bridge] forward error: ${o instanceof Error?o.message:o}`)}}async closeSession(t){if(!t)return;let r=this.sessions.get(t);if(r){this.sessions.delete(t);try{await r.close()}catch{}}}async closeAllSessions(){let t=[...this.sessions.keys()];await Promise.all(t.map(r=>this.closeSession(r)))}send(t){this.ws?.readyState===Cr.OPEN&&this.ws.send(JSON.stringify(t))}async backoff(){let t=mn(this.reconnectDelay);console.error(`[gaia bridge] reconnecting in ${t}ms\u2026`),await new Promise(r=>setTimeout(r,t)),this.reconnectDelay=Math.min(this.reconnectDelay*2,tr)}};async function Ke(){let e=de();if(!e?.refreshToken)throw new Error("not paired \u2014 run: gaia bridge login");if(q().servers.length===0)throw new Error("no servers configured \u2014 run: gaia bridge add");pr()?.allowWrite&&console.error("[gaia bridge] filesystem WRITES are enabled for this device.");let t=await Ve(e.apiUrl,e.refreshToken);xe({...e,refreshToken:t.refresh_token});for(let n of q().servers)await fr(e.apiUrl,t.access_token,n.key,n.name);let r=new Je({...e,refreshToken:t.refresh_token}),o=async()=>{console.error(`
11
+ [gaia bridge] shutting down\u2026`),await r.stop(),process.exit(0)};process.on("SIGINT",()=>void o()),process.on("SIGTERM",()=>void o()),await r.run()}import{basename as Rr}from"node:path";import{createInterface as Ir}from"node:readline/promises";import{Writable as fn}from"node:stream";async function me(e,t){let r=Ir({input:process.stdin,output:process.stdout});try{let o=t?` [${t}]`:"";return(await r.question(`${e}${o}: `)).trim()||t||""}finally{r.close()}}async function Er(e){process.stdout.write(`${e}: `);let t=new fn({write(o,n,i){i()}}),r=Ir({input:process.stdin,output:t,terminal:!0});try{let o=(await r.question("")).trim();return process.stdout.write(`
12
+ `),o}finally{r.close()}}async function _e(e,t=!0){let r=await me(`${e} (${t?"Y/n":"y/N"})`);return r?/^y(es)?$/i.test(r):t}async function It(e,t){for(process.stdout.write(`
13
+ ${e}
14
+ `),t.forEach((r,o)=>{process.stdout.write(` ${o+1}. ${r}
15
+ `)});;){let r=await me(`Choose 1-${t.length}`),o=Number.parseInt(r,10)-1;if(o>=0&&o<t.length)return o;process.stdout.write(`Invalid choice, try again.
16
+ `)}}function gn(e){return e.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"").slice(0,60)}function hn(e){let t=[],r="",o=null;for(let a of e.trim())o?a===o?o=null:r+=a:a==='"'||a==="'"?o=a:/\s/.test(a)?r&&(t.push(r),r=""):r+=a;r&&t.push(r);let[n,...i]=t;if(!n)throw new Error("Empty command");return{command:n,args:i}}function vn(e,t){let o=[...t].reverse().filter(n=>!n.startsWith("-"))[0]??e;return Rr(o).replace(/@[^@]*$/,"")}function Sn(e){try{let t=new URL(e);return t.port?`local-${t.port}`:t.hostname}catch{return""}}async function Dr(e){for(;;){let t=await me("Name for this server",e),r=gn(t);if(!t||!r||r===ye){console.info("Pick a different name.");continue}if(!(q().servers.some(o=>o.key===r)&&!await _e(`'${r}' already exists \u2014 overwrite?`,!1)))return{name:t,key:r}}}function yn(e,t){if(Rr(e)!=="docker")return[];let r=[];for(let o=0;o<t.length;o++){let n=t[o];if(n!==void 0)if(n==="-e"||n==="--env"){let i=t[o+1];i&&!i.includes("=")&&r.push(i)}else n.startsWith("-e")&&n.length>2&&!n.includes("=")&&r.push(n.slice(2))}return[...new Set(r)]}async function Pr(e){let t=process.env[e];if(t!==void 0&&t!==""&&await _e(` Found ${e} in your environment \u2014 use that value?`,!0))return t;for(;;){let r=await Er(` Paste ${e}`);if(r)return console.info(` Got it (${r.length} characters).`),r;console.info(" Empty \u2014 paste the value, or Ctrl+C to abort.")}}async function kr(e,t){let r={};for(let n of yn(e,t))console.info(`
17
+ The command needs ${n}.`),r[n]=await Pr(n);let o=Object.keys(r).length?"Any other environment variables to add?":"Does the server need environment variables (API keys, tokens\u2026)?";if(!await _e(o,!1))return r;for(console.info("Enter each variable's name; leave blank when done.");;){let n=(await me(" Variable name")).trim();if(!n)break;if(n in r){console.info(" Already added.");continue}r[n]=await Pr(n)}return r}async function xn(){console.info(`
18
+ Examples: npx -y my-mcp-server \xB7 uvx my-server \xB7 docker run -i --rm my/image`);let e=await me("Command that starts your MCP server");if(!e)throw new Error("a command is required");let{command:t,args:r}=hn(e),o=await kr(t,r),{name:n,key:i}=await Dr(vn(t,r));return{type:"stdio",key:i,name:n,command:t,args:r,env:o}}async function wn(){let e=await me("Server URL (e.g. http://localhost:3000/mcp)");if(!e)throw new Error("a URL is required");let{name:t,key:r}=await Dr(Sn(e));return{type:"url",key:r,name:t,url:e}}async function bn(e){for(;;){console.info(`
19
+ Testing the connection (this may download/start the server)\u2026`);try{let t=await Tr(e),r=t.slice(0,5).join(", ");return console.info(`Connected \u2014 ${t.length} tools found${r?` (${r}${t.length>5?", \u2026":""})`:""}.`),!0}catch(t){console.error(`Connection failed: ${t instanceof Error?t.message:t}`);let r=["Retry the test"];e.type==="stdio"&&r.push("Re-enter environment variables"),r.push("Save anyway (fix it later)","Abort");let o=r[await It("What now?",r)];if(o==="Re-enter environment variables"&&e.type==="stdio")e.env=await kr(e.command,e.args);else{if(o==="Save anyway (fix it later)")return!0;if(o==="Abort")return!1}}}}async function _r(){gr()||(console.info("This device isn't paired with GAIA yet \u2014 let's do that first."),await Ye());let t=await It("How does your MCP server run?",["A command starts it (stdio) \u2014 npx / uvx / docker / python \u2026","It's already running at a local URL \u2014 e.g. http://localhost:3000/mcp"])===0?await xn():await wn();if(!await bn(t))throw new Error("aborted");Ue(t),console.info(`
20
+ Saved '${t.key}'.`),await _e("Connect to GAIA now (gaia bridge up)?")?await Ke():console.info("Run `gaia bridge up` whenever you're ready.")}function En(e){return e==="~"?Ar():e.startsWith("~/")?Tn(Ar(),e.slice(2)):e}function Pn(e,t){let r=e.map(o=>Cn(En(o)));Ue({type:"filesystem",key:ye,name:"Local Files",allow:r,allowWrite:t}),console.info(`Filesystem access configured for:
21
+ ${r.join(`
22
+ `)}
23
+ Writes: ${t?"ENABLED":"disabled (read-only)"}
24
+ Run: gaia bridge up`)}function Rn(){let e=de();console.info(e?.deviceId?`Paired (device ${e.deviceId}, ${He()})`:"Not paired \u2014 run: gaia bridge login");let t=q().servers;if(t.length===0){console.info("No servers configured \u2014 run: gaia bridge add");return}console.info(`
25
+ Configured servers:`);for(let r of t)if(r.type==="filesystem")console.info(` [${r.key}] filesystem${r.allowWrite?" (rw)":" (ro)"}: ${r.allow.join(", ")}`);else if(r.type==="stdio"){let o=Object.keys(r.env);console.info(` [${r.key}] ${r.name}: ${r.command} ${r.args.join(" ")}`),o.length&&console.info(` env: ${o.join(", ")}`)}else console.info(` [${r.key}] ${r.name}: ${r.url}`)}async function fe(e){try{await e()}catch(t){console.error(`Error: ${t instanceof Error?t.message:String(t)}`),process.exit(1)}}var te=new In("bridge").description("Connect this machine's local MCP servers and files to GAIA (outbound-only, no inbound ports)").addHelpText("after",`
26
+ Revoke a device anytime from GAIA \u2192 Settings \u2192 Devices.`);te.command("add").description("Connect a local MCP server (guided \u2014 start here!)").action(async()=>{await fe(_r)});te.command("login").description("Pair this machine with your GAIA account").option("--api <url>","GAIA API base URL").option("--name <name>","Name to show for this device in Settings").action(async e=>{await fe(async()=>{await Ye({...e.api!==void 0?{api:e.api}:{},...e.name!==void 0?{name:e.name}:{}}),console.info("Next: gaia bridge add")})});te.command("fs").description("Expose folders for file access (read-only unless --write)").argument("<dirs...>","Folders to expose, e.g. ~/Documents").option("--write","Allow GAIA to write to these folders").action(async(e,t)=>{await fe(()=>Pn(e,t.write===!0))});te.command("ls").alias("list").description("Show pairing status and configured servers").action(async()=>{await fe(Rn)});te.command("rm").alias("remove").description("Remove a configured server").argument("<key>","Server key from `gaia bridge ls`").action(async e=>{await fe(()=>{console.info(lr(e)?`Removed '${e}'`:`No server '${e}'`)})});te.command("up").alias("start").description("Connect and serve (holds the tunnel; Ctrl+C to stop)").action(async()=>{await fe(Ke)});te.command("logout").description("Forget local credentials").action(async()=>{await fe(()=>{ar(),console.info("Logged out. Your device record remains until you revoke it in GAIA settings.")})});import*as tt from"fs";import*as Qr from"path";import{spawn as Dn}from"child_process";async function Te(e,t,r,o,n,i=!1){await Qe([{cmd:e,args:t,cwd:r,env:o,onSpawn:n,detached:i}])}async function Qe(e){e.length!==0&&await new Promise((t,r)=>{let o=e.map(d=>Dn(d.cmd,d.args,{cwd:d.cwd,stdio:"inherit",shell:!1,detached:d.detached??!1,env:d.env?{...process.env,...d.env}:process.env}));o.forEach((d,m)=>{e[m]?.onSpawn?.(d.pid)});let n=!1,i=0,a=!1,s,c=()=>{process.off("SIGINT",f),process.off("SIGTERM",f)},p=()=>{if(!a){a=!0;for(let[d,m]of o.entries()){let S=e[d];try{process.platform!=="win32"&&S?.detached&&typeof m.pid=="number"?process.kill(-m.pid,"SIGTERM"):m.kill("SIGTERM")}catch{}}s=setTimeout(()=>{for(let[d,m]of o.entries()){let S=e[d];try{process.platform!=="win32"&&S?.detached&&typeof m.pid=="number"?process.kill(-m.pid,"SIGKILL"):m.kill("SIGKILL")}catch{}}},1e3)}},f=()=>{p()};process.on("SIGINT",f),process.on("SIGTERM",f),o.forEach((d,m)=>{let S=e[m];d.on("error",v=>{n||(n=!0,c(),p(),r(v))}),d.on("close",(v,y)=>{if(i+=1,!(v===0||(y==="SIGINT"||y==="SIGTERM"||v===130||v===143||a))&&!n){n=!0,c(),p(),r(new Error(`Command failed with code ${String(v)}: ${S?.cmd??"unknown"} ${S?.args.join(" ")??""}`));return}i>=o.length&&!n&&(n=!0,c(),s&&clearTimeout(s),t())})})})}import*as J from"fs";import*as W from"path";import*as re from"fs";import*as Or from"os";import*as Rt from"path";var Et=Rt.join(Or.homedir(),".gaia"),Pt=Rt.join(Et,"config.json");function kn(){re.existsSync(Et)||re.mkdirSync(Et,{recursive:!0})}function Dt(){try{if(!re.existsSync(Pt))return null;let e=re.readFileSync(Pt,"utf-8");return JSON.parse(e)}catch{return null}}function ze(e){kn(),re.writeFileSync(Pt,`${JSON.stringify(e,null,2)}
27
+ `)}function Ae(e){let r={...Dt()??{version:ee,setupComplete:!1,setupMethod:"manual",repoPath:"",createdAt:new Date().toISOString(),updatedAt:new Date().toISOString()},...e,updatedAt:new Date().toISOString()};ze(r)}import*as F from"fs";import*as Ee from"path";import*as Ie from"node:fs";import*as Ce from"node:path";import{execa as Mr}from"execa";var kt={selfhost:{MONGO_DB:"mongodb://mongo:27017/gaia",REDIS_URL:"redis://redis:6379",POSTGRES_URL:"postgresql://postgres:postgres@postgres:5432/langgraph",CHROMADB_HOST:"chromadb",CHROMADB_PORT:"8000",RABBITMQ_URL:"amqp://guest:guest@rabbitmq:5672/"},developer:{MONGO_DB:"mongodb://localhost:27017/gaia",REDIS_URL:"redis://localhost:6379",POSTGRES_URL:"postgresql://postgres:postgres@localhost:5432/postgres",CHROMADB_HOST:"localhost",CHROMADB_PORT:"8080",RABBITMQ_URL:"amqp://guest:guest@localhost:5672/"}},Nr={selfhost:{HOST:"http://localhost:8000",FRONTEND_URL:"http://localhost:3000",GAIA_BACKEND_URL:"http://gaia-backend:80",SETUP_MODE:"selfhost"},developer:{HOST:"http://localhost:8000",FRONTEND_URL:"http://localhost:3000",GAIA_BACKEND_URL:"http://host.docker.internal:8000",SETUP_MODE:"developer"}};function _t(e,t){return kt[t][e]??Nr[t][e]}async function Lr(e){let t=Ce.join(e,"apps/api/scripts/dump_config_schema.py"),r=Ce.join(e,"apps/api/app/config/settings_validator.py"),o=Ce.join(e,"apps/api/app/config/settings.py");if(!Ie.existsSync(t))throw new Error("dump_config_schema.py not found in apps/api/scripts");try{try{let{stdout:n}=await Mr("python3",[t,r,o],{cwd:e});return JSON.parse(n)}catch{let{stdout:n}=await Mr("python",[t,r,o],{cwd:e});return JSON.parse(n)}}catch(n){throw new Error(`Failed to parse settings schema: ${n.message}. Ensure python is installed.`)}}function Br(e){let t=Ce.join(e,"apps","web",".env.local"),r=Ie.existsSync(t)?t:Ce.join(e,"apps","web",".env");if(!Ie.existsSync(r))return[];let o=Ie.readFileSync(r,"utf-8"),n=[],i="General";for(let a of o.split(`
28
+ `)){let s=a.trim();if(s.startsWith("#")&&!s.startsWith("#=")){let d=s.replace(/^#+\s*/,"").trim();d&&!d.startsWith("These are")&&(i=d);continue}if(!s||s.startsWith("#"))continue;let c=s.indexOf("=");if(c===-1)continue;let p=s.substring(0,c).trim(),f=s.substring(c+1).trim();n.push({name:p,value:f,category:i})}return n}function Fr(e,t){return{NEXT_PUBLIC_API_BASE_URL:`http://localhost:${t?.[8e3]??8e3}/api/v1/`}}function $r(e,t,r){let o=r==="selfhost"?new Set(Object.keys(kt.selfhost)):new Set;for(let[n,i]of Object.entries(t)){let a=Number(n),s=Number(i);for(let[c,p]of Object.entries(e)){if(o.has(c))continue;if(p===String(a)){e[c]=String(s);continue}let f=new RegExp(`:${a}(?=[/\\s]|$)`,"g");e[c]=p.replaceAll(f,`:${s}`)}}}function Gr(e,t){return e.map(r=>({...r,variables:r.variables.map(o=>{let n=_t(o.name,t);return{...o,defaultValue:n||o.defaultValue}})}))}function At(){return Object.keys(kt.selfhost)}function jr(e){return{...Nr[e]}}function Ot(e){F.existsSync(e)&&F.copyFileSync(e,`${e}.bak`)}function Ur(e,t){let r=Ee.join(e,".env");Ot(r);let o=["# GAIA Environment Configuration","# Generated by GAIA CLI",`# Created: ${new Date().toISOString()}`,""],n=["MONGO","REDIS","POSTGRES","CHROMADB","RABBITMQ","WORKOS","GOOGLE","OPENAI","INFISICAL","LANGSMITH","DISCORD","SLACK","TELEGRAM","CLOUDINARY","COMPOSIO","FIRECRAWL","LIVEKIT","DEEPGRAM","ELEVENLABS","RESEND","SENTRY","POSTHOG","E2B","DODO","NEXT_PUBLIC","GAIA"];function i(s){for(let p of n)if(s===p||s.startsWith(`${p}_`))return p;let c=s.split("_");return c.length===1?"Core":c[0]||"Core"}let a=new Map;for(let[s,c]of Object.entries(t)){let p=i(s);a.has(p)||a.set(p,[]);let d=/[\s#"'\\]/.test(c)||c===""?`"${c.replace(/\\/g,"\\\\").replace(/"/g,'\\"')}"`:c;a.get(p).push(`${s}=${d}`)}for(let[s,c]of a.entries())o.push(`# ${s} Configuration`),o.push(...c),o.push("");F.writeFileSync(r,o.join(`
29
+ `),"utf-8")}function Hr(e,t,r){let o=Ee.join(e,"apps","web",".env.local");Ot(o);let n=Br(e),i=Fr(t,r),a=["# GAIA Web App Environment Configuration","# Generated by GAIA CLI",`# Created: ${new Date().toISOString()}`,""],s=new Map;for(let c of n){s.has(c.category)||s.set(c.category,[]);let p=i[c.name]??c.value;s.get(c.category).push({name:c.name,value:p})}if(n.length===0){a.push("# Core URLs");for(let[c,p]of Object.entries(i))a.push(`${c}=${p}`);a.push("")}else for(let[c,p]of s.entries()){a.push(`# ${c}`);for(let{name:f,value:d}of p)a.push(`${f}=${d}`);a.push("")}F.writeFileSync(o,a.join(`
30
+ `),"utf-8")}var Wr={8e3:"API_HOST_PORT",5432:"POSTGRES_HOST_PORT",6379:"REDIS_HOST_PORT",27017:"MONGO_HOST_PORT",5672:"RABBITMQ_HOST_PORT",8080:"CHROMADB_HOST_PORT",8083:"MONGO_EXPRESS_HOST_PORT",3e3:"WEB_HOST_PORT"};function Vr(e,t,r){let o=Ee.join(e,"infra","docker",".env");Ot(o);let n=["# Docker Compose environment overrides","# Generated by GAIA CLI",`# Created: ${new Date().toISOString()}`,""];for(let[i,a]of Object.entries(t)){let s=Number(i),c=Wr[s];c&&n.push(`${c}=${a}`)}if(r==="selfhost"){let i=t[8e3]??8e3;n.push(""),n.push("# Web build args"),n.push(`NEXT_PUBLIC_API_BASE_URL=http://localhost:${i}/api/v1/`)}n.push(""),F.writeFileSync(o,n.join(`
31
+ `),"utf-8")}function se(e){let t={};for(let[r,o]of Object.entries(e)){let n=Number(r),i=Wr[n];i&&(t[i]=String(o))}return t}function Yr(e){let t=Ee.join(e,"infra","docker","docker-compose.yml");if(!F.existsSync(t))return;let r=F.readFileSync(t,"utf-8"),o=[{varName:"API_HOST_PORT",hostPort:8e3,containerPort:80},{varName:"CHROMADB_HOST_PORT",hostPort:8080,containerPort:8e3},{varName:"POSTGRES_HOST_PORT",hostPort:5432,containerPort:5432},{varName:"REDIS_HOST_PORT",hostPort:6379,containerPort:6379},{varName:"MONGO_HOST_PORT",hostPort:27017,containerPort:27017},{varName:"RABBITMQ_HOST_PORT",hostPort:5672,containerPort:5672},{varName:"MONGO_EXPRESS_HOST_PORT",hostPort:8083,containerPort:8081},{varName:"WEB_HOST_PORT",hostPort:3e3,containerPort:3e3}],n=!1;for(let{varName:i,hostPort:a,containerPort:s}of o){let c=`"${a}:${s}"`,p=`"\${${i}:-${a}}:${s}"`;r.includes(c)&&(r=r.replaceAll(c,p),n=!0)}n&&F.writeFileSync(t,r,"utf-8")}var qr={API_HOST_PORT:8e3,POSTGRES_HOST_PORT:5432,REDIS_HOST_PORT:6379,MONGO_HOST_PORT:27017,RABBITMQ_HOST_PORT:5672,CHROMADB_HOST_PORT:8080,MONGO_EXPRESS_HOST_PORT:8083,WEB_HOST_PORT:3e3};function ae(e){let t=Ee.join(e,"infra","docker",".env"),r={};if(!F.existsSync(t))return r;let o=F.readFileSync(t,"utf-8");for(let n of o.split(`
32
+ `)){let i=n.trim();if(i&&!i.startsWith("#")){let[a,...s]=i.split("=");if(a&&qr[a]){let c=s.join("=").trim().replace(/^["']|["']$/g,""),p=Number(c);!Number.isNaN(p)&&p>0&&p<=65535&&(r[qr[a]]=p)}}}return r}var On=e=>new Promise(t=>setTimeout(t,e)),Xr="dev-start.log",et=".gaia-dev.pid";function Jr(e){let t=W.join(e,".env");return J.existsSync(t)?["--env-file",".env"]:[]}var Mn=60;function Nn(){let e=process.env.GAIA_START_TIMEOUT_MIN?.trim(),t=e?Number(e):Number.NaN,r=Number.isFinite(t)&&t>=0?t:Mn;return r===0?void 0:r*60*1e3}function Ln(e,t){let r=["compose","-f","docker-compose.selfhost.yml",...e,"up","-d","--remove-orphans"];return t?.build&&r.push("--build"),t?.pull&&r.push("--pull","always"),r}function Mt(e){let t=W.join(e,et);if(!J.existsSync(t))return null;try{let r=Number.parseInt(J.readFileSync(t,"utf-8").trim(),10);return Number.isNaN(r)||r<=0?null:r}catch{return null}}function Ze(e){try{return process.kill(e,0),!0}catch(t){return t.code==="EPERM"}}async function Oe(e,t,r,o,n,i){if(t!=="selfhost")throw r?.("Developer mode must run in foreground."),new Error("Developer mode runs in foreground. Use 'gaia dev' or 'gaia dev full' instead of 'gaia start'.");r?.(i?.build?"Building and starting all services in Docker...":"Starting all services in Docker (selfhost mode)...");let a=W.join(e,"infra/docker"),s=o&&Object.keys(o).length>0?se(o):void 0;await U("docker",Ln(Jr(a),i),a,void 0,n,s,Nn()),r?.("All services started in Docker!")}async function Kr(e,t,r,o){let n=W.join(e,"infra/docker"),i=await ge(e);t?.("Stopping Docker services...");try{let a=Jr(n),s=i==="selfhost"?["compose","-f","docker-compose.selfhost.yml",...a,"down"]:["compose",...a,"down"];await U("docker",s,n)}catch{}if(i!=="selfhost"){t?.("Stopping GAIA-managed local processes (safe mode)...");let a=W.join(e,et),s=!1,c=Mt(e),p=typeof c=="number";if(c&&Ze(c))try{if(process.platform==="win32")await U("taskkill",["/PID",String(c),"/T","/F"],e),s=!0;else{try{process.kill(-c,"SIGTERM"),s=!0}catch{process.kill(c,"SIGTERM"),s=!0}if(await On(800),Ze(c))try{process.kill(-c,"SIGKILL")}catch{process.kill(c,"SIGKILL")}}}catch{}try{J.unlinkSync(a)}catch{}if(!s&&o?.forcePorts){t?.("No GAIA PID found. Force-stopping listeners on app ports...");try{let f=r?.[8e3]??8e3,d=r?.[3e3]??3e3;if(process.platform==="win32")for(let m of[f,d])try{await U("powershell",["-Command",`Get-NetTCPConnection -LocalPort ${m} -ErrorAction SilentlyContinue | ForEach-Object { Stop-Process -Id $_.OwningProcess -Force -ErrorAction SilentlyContinue }`],e)}catch{}else for(let m of[f,d])try{await U("sh",["-c",`lsof -ti :${m} -sTCP:LISTEN | xargs kill 2>/dev/null || true`],e)}catch{}}catch{}}else s||t?.(p?"Stored GAIA PID is stale. Skipping port cleanup in safe mode. Use `gaia stop --force-ports` for aggressive cleanup.":"No GAIA-managed PID found. Skipping port cleanup in safe mode. Use `gaia stop --force-ports` for aggressive cleanup.")}t?.("All services stopped.")}async function ge(e){let t=W.join(e,"apps","api",".env");if(!J.existsSync(t))return null;let r=J.readFileSync(t,"utf-8"),o=r.match(/^SETUP_MODE=(.+)$/m);if(o?.[1]){let n=o[1].trim().replace(/^["']|["']$/g,"");if(n==="selfhost"||n==="developer")return n}return r.includes("mongodb://mongo:")?"selfhost":(r.includes("mongodb://localhost:"),"developer")}async function U(e,t,r,o,n,i,a){let{spawn:s}=await import("child_process");return new Promise((c,p)=>{let f=s(e,t,{cwd:r,stdio:["ignore","pipe","pipe"],shell:!0,env:i?{...process.env,...i}:void 0}),d="",m=0,S=!1,v;a&&(v=setTimeout(()=>{S=!0,f.kill("SIGTERM"),p(new Error(`Command timed out after ${Math.round(a/6e4)}m. Check \`docker compose logs\` to debug.`))},a)),f.stdout?.on("data",y=>{let w=y.toString();d+=w,n?.(w),m=Math.min(m+5,95),o?.(m)}),f.stderr?.on("data",y=>{let w=y.toString();d+=w,n?.(w),m=Math.min(m+5,95),o?.(m)}),f.on("close",y=>{v&&clearTimeout(v),!S&&(y===0?(o?.(100),c()):p(new Error(`Command failed with code ${y}: ${d.slice(-500)}`)))}),f.on("error",y=>{v&&clearTimeout(v),!S&&p(y)})})}function $(e){let t=e||process.cwd();for(;t!==W.dirname(t);){if(J.existsSync(W.join(t,"apps/api/app/config/settings_validator.py")))return t;t=W.dirname(t)}let r=Dt();if(r?.repoPath){if(J.existsSync(W.join(r.repoPath,"apps/api/app/config/settings_validator.py")))return r.repoPath;console.warn(`Warning: Saved repo path "${r.repoPath}" is no longer a valid GAIA installation. Resetting config.`),Ae({repoPath:"",setupComplete:!1})}return null}async function zr(e){if(e&&e!=="full")throw new Error(`Invalid developer profile: '${e}'. Use 'gaia dev' or 'gaia dev full'.`);let t=$();if(!t)throw new Error("Could not find GAIA repository. Run from within a cloned gaia repo.");let r=await ge(t);if(!r)throw new Error("No .env file found. Run 'gaia init' for fresh setup, or 'gaia setup' to configure an existing repo.");if(r!=="developer")throw new Error("Developer mode is not enabled for this repo. Use 'gaia start' for self-host mode.");let o=Qr.join(t,et);try{await Te("mise",[e==="full"?"dev:full":"dev"],t,void 0,n=>{typeof n=="number"&&n>0&&tt.writeFileSync(o,`${n}
33
+ `)},process.platform!=="win32")}finally{try{tt.unlinkSync(o)}catch{}}}import{render as fi}from"ink";import gi from"react";import{Box as ct,Text as ve}from"ink";import li from"react";import{ProgressBar as oo,Select as Bt,Spinner as Vn}from"@inkjs/ui";import{Box as g,Text as u,useInput as ce}from"ink";import Le from"ink-text-input";import{useEffect as Be,useRef as Yn,useState as B}from"react";import{Box as Me,Text as rt}from"ink";var x="#00bbff";import{Box as Bn,Text as Fn}from"ink";import{jsx as Zr}from"react/jsx-runtime";var eo=({status:e,step:t})=>t.toLowerCase()==="welcome"?null:Zr(Bn,{width:"100%",paddingX:1,marginTop:1,children:Zr(Fn,{color:"gray",dimColor:!0,children:e})});import{Box as $n}from"ink";import Gn from"ink-big-text";import jn from"ink-gradient";import{jsx as Nt}from"react/jsx-runtime";var Pe=()=>Nt($n,{flexDirection:"column",marginTop:1,marginBottom:1,children:Nt(jn,{colors:[x,"#b0eaff",x],children:Nt(Gn,{text:"GAIA",font:"3d"})})});import{jsx as he,jsxs as Ne}from"react/jsx-runtime";var qn=["Welcome","Prerequisites","Setup Mode","Repository Setup","Environment Setup","Install Tools","Project Setup","Finished"],to=["Detect Repo","Prerequisites","Environment Setup","Project Setup","Finished"],Un={Welcome:"Welcome",Prerequisites:"Prereqs","Setup Mode":"Mode","Repository Setup":"Repo","Environment Setup":"Env","Install Tools":"Tools","Project Setup":"Setup","Detect Repo":"Detect",Finished:"Done"},Hn=({currentStep:e,steps:t})=>{let r=t.indexOf(e);return he(Me,{marginBottom:1,flexWrap:"nowrap",children:t.map((o,n)=>{let i=n<r,a=n===r,s=Un[o]??o;return Ne(Me,{flexShrink:0,children:[n>0&&Ne(rt,{color:"gray",dimColor:!0,children:[" ","\xB7"," "]}),i&&Ne(rt,{color:"green",children:["\u2713 ",s]}),a&&he(rt,{color:x,bold:!0,children:s}),!i&&!a&&he(rt,{color:"gray",dimColor:!0,children:s})]},o)})})},ot=({children:e,status:t,step:r,steps:o=qn})=>Ne(Me,{flexDirection:"column",height:"100%",width:"100%",children:[Ne(Me,{flexGrow:1,flexDirection:"column",children:[he(Pe,{}),he(Hn,{currentStep:r,steps:o}),he(Me,{flexDirection:"column",flexGrow:1,children:e})]}),he(eo,{status:t,step:r})]});import{Spinner as ro}from"@inkjs/ui";import{Box as G,Text as M,useInput as Wn}from"ink";import{jsx as R,jsxs as H}from"react/jsx-runtime";var nt=({checks:e})=>H(G,{flexDirection:"column",borderStyle:"round",paddingX:1,borderColor:x,children:[R(M,{bold:!0,children:"System Checks"}),H(G,{flexDirection:"column",marginTop:1,children:[R(Lt,{label:"Git",status:e.git}),R(Lt,{label:"Docker",status:e.docker}),e.mise&&R(Lt,{label:"Mise",status:e.mise})]})]}),it=({status:e})=>H(G,{flexDirection:"column",marginTop:1,paddingX:1,borderStyle:"round",borderColor:x,children:[R(M,{bold:!0,children:"Environment Setup"}),R(G,{marginTop:1,children:R(ro,{label:e||"Configuring environment..."})})]}),st=({message:e})=>H(G,{flexDirection:"column",borderStyle:"single",borderColor:"red",padding:1,marginTop:2,children:[H(M,{color:"red",children:["Error: ",e]}),R(G,{marginTop:1,children:H(M,{dimColor:!0,children:[R(M,{bold:!0,children:"Enter"})," to exit"]})})]}),Lt=({label:e,status:t})=>H(G,{children:[R(G,{marginRight:1,children:t==="pending"?R(ro,{type:"dots"}):t==="success"?R(M,{color:"green",children:"\u2714"}):t==="error"?R(M,{color:"red",children:"\u2716"}):R(M,{color:"yellow",children:"\u26A0"})}),R(M,{children:e})]}),at=({portResults:e,onAccept:t,onAbort:r})=>{Wn((n,i)=>{i.return?t():i.escape&&r()});let o=e.filter(n=>!n.available);return H(G,{flexDirection:"column",marginTop:1,paddingX:1,borderStyle:"round",borderColor:"yellow",children:[R(G,{marginBottom:1,children:R(M,{bold:!0,color:"yellow",children:"Port Conflicts Detected"})}),e.map(n=>H(G,{children:[H(M,{color:n.available?"green":n.alternative?"yellow":"red",children:[n.available?"\u2714":n.alternative?"\u26A0":"\u2716"," "]}),H(M,{children:[n.service," (:",n.port,")"]}),!n.available&&H(M,{color:n.alternative?"gray":"red",children:[" ","- in use",n.usedBy?` by ${n.usedBy}`:"",n.alternative?` \u2192 will use :${n.alternative}`:" \u2014 NO ALTERNATIVE FOUND"]})]},n.port)),o.some(n=>!n.alternative)&&R(G,{marginTop:1,children:R(M,{color:"red",children:"Some ports have no available alternative. Free them and retry."})}),!o.some(n=>!n.alternative)&&o.some(n=>n.alternative)&&R(G,{marginTop:1,children:R(M,{color:"gray",children:"Alternative ports will be used for conflicting services."})}),R(G,{marginTop:1,children:H(M,{dimColor:!0,children:[R(M,{bold:!0,children:"Enter"})," continue \xB7 ",R(M,{bold:!0,children:"ESC"})," abort"]})})]})};import{jsx as l,jsxs as h}from"react/jsx-runtime";var Xn=({onConfirm:e})=>(ce((t,r)=>{r.return&&e()}),h(g,{flexDirection:"column",paddingX:2,borderStyle:"round",borderColor:x,children:[l(u,{bold:!0,children:"Welcome to GAIA Setup"}),h(g,{flexDirection:"column",marginTop:1,marginBottom:1,children:[l(u,{children:"This wizard will guide you through the setup process:"}),l(u,{children:" 1. Check prerequisites and choose setup mode"}),l(u,{children:" 2. Clone repository"}),l(u,{children:" 3. Configure environment variables"}),l(u,{children:" 4. Install tools and dependencies"})]}),l(u,{dimColor:!0,children:"~5-15 min depending on network speed"}),l(g,{marginTop:1,children:h(u,{color:x,children:[l(u,{bold:!0,children:"Enter"})," to start"]})})]})),Jn=({defaultValue:e,onSubmit:t})=>{let[r,o]=B(e);return h(g,{flexDirection:"column",marginTop:1,paddingX:1,borderStyle:"round",borderColor:x,children:[l(u,{children:"Clone repository to:"}),l(u,{color:"gray",dimColor:!0,children:"Press Enter for default, or type a custom path"}),h(g,{marginTop:1,children:[l(u,{color:x,children:"\u2192 "}),l(Le,{value:r,onChange:o,onSubmit:t})]})]})},Kn=({repoPath:e,onAction:t})=>h(g,{flexDirection:"column",marginTop:1,paddingX:1,borderStyle:"round",borderColor:"yellow",children:[l(g,{marginBottom:1,children:l(u,{bold:!0,color:"yellow",children:"Existing Installation Found"})}),h(u,{children:["Found a GAIA installation at"," ",l(u,{color:"cyan",bold:!0,children:e})]}),l(g,{marginTop:1,children:l(u,{color:"gray",children:"What would you like to do?"})}),l(g,{marginTop:1,children:l(Bt,{options:[{label:"Use existing installation",value:"use_existing"},{label:"Delete and re-clone",value:"delete_reclone"},{label:"Choose a different path",value:"different_path"},{label:"Exit setup",value:"exit"}],onChange:o=>t(o)})})]}),Qn=({setupMode:e,portOverrides:t,onConfirm:r})=>{ce((i,a)=>{a.return&&r()});let o=t?.[3e3]??3e3,n=t?.[8e3]??8e3;return e==="selfhost"?h(g,{flexDirection:"column",marginTop:2,borderStyle:"round",borderColor:"green",padding:1,children:[l(u,{bold:!0,color:"green",children:"GAIA is Running!"}),l(g,{marginTop:1,children:l(u,{color:"green",children:"\u2713 All services started"})}),h(g,{marginTop:1,flexDirection:"column",children:[h(u,{children:["Web:"," ",h(u,{color:"cyan",bold:!0,children:["http://localhost:",o]})]}),h(u,{children:["API:"," ",h(u,{color:"cyan",bold:!0,children:["http://localhost:",n]})]})]}),l(g,{marginTop:1,children:l(u,{color:"gray",children:"gaia logs \xB7 gaia stop \xB7 gaia status \xB7 gaia setup"})}),l(g,{marginTop:1,children:h(u,{dimColor:!0,children:[l(u,{bold:!0,children:"Enter"})," to exit"]})})]}):h(g,{flexDirection:"column",marginTop:2,borderStyle:"round",borderColor:x,padding:1,children:[l(u,{color:x,bold:!0,children:"You're all set!"}),h(g,{marginTop:1,children:[l(u,{bold:!0,children:"Run: "}),l(u,{color:"cyan",children:"$ gaia dev"})]}),h(g,{marginTop:1,flexDirection:"column",children:[h(u,{children:["Web:"," ",h(u,{color:"cyan",bold:!0,children:["http://localhost:",o]})]}),h(u,{children:["API:"," ",h(u,{color:"cyan",bold:!0,children:["http://localhost:",n]})]})]}),l(g,{marginTop:1,children:l(u,{color:"gray",children:"gaia dev full \xB7 gaia logs \xB7 gaia stop \xB7 gaia status \xB7 gaia setup"})}),l(g,{marginTop:1,children:h(u,{dimColor:!0,children:[l(u,{bold:!0,children:"Enter"})," to exit"]})})]})},zn=8,Zn=({logs:e,height:t=zn})=>{let[r,o]=B(0),n=Yn(e.length);Be(()=>{e.length!==n.current&&(n.current=e.length,o(0))},[e.length]),ce((d,m)=>{m.upArrow?o(S=>Math.min(S+1,Math.max(0,e.length-t))):m.downArrow&&o(S=>Math.max(0,S-1))});let i=e.length,a=Math.max(0,i-t-r),s=Math.max(0,i-r),c=e.slice(a,s),p=a,f=r;return h(g,{flexDirection:"column",marginTop:1,marginLeft:1,children:[p>0&&h(u,{color:"gray",dimColor:!0,children:["\u2191 ",p," more line",p!==1?"s":""]}),l(g,{flexDirection:"column",height:t,overflow:"hidden",children:c.map((d,m)=>l(u,{color:"gray",wrap:"truncate",children:d},`${a}-${m}`))}),f>0?h(u,{color:"gray",dimColor:!0,children:["\u2193 ",f," more line",f!==1?"s":""]}):l(u,{color:"gray",dimColor:!0,children:"\u2191\u2193 scroll"})]})},Ft=({phase:e,progress:t,isComplete:r,logs:o,title:n})=>h(g,{flexDirection:"column",marginTop:1,paddingX:1,borderStyle:"round",borderColor:x,children:[l(g,{marginBottom:1,children:l(u,{bold:!0,color:x,children:n||"Installing Dependencies"})}),h(g,{flexDirection:"column",gap:1,children:[l(g,{children:r?h(u,{color:"green",children:["\u2713 ",e]}):l(Vn,{label:e||"Preparing..."})}),!r&&t>0&&l(g,{width:50,children:l(oo,{value:t})}),!r&&o&&o.length>0&&l(Zn,{logs:o}),!r&&l(g,{marginTop:1,children:l(u,{color:"gray",dimColor:!0,children:"This may take a few minutes..."})})]})]}),$t=({onSelect:e})=>h(g,{flexDirection:"column",marginTop:1,paddingX:1,borderStyle:"round",borderColor:x,children:[l(u,{bold:!0,children:"Setup Mode"}),l(g,{marginTop:1,children:l(u,{color:"gray",children:"How do you want to run GAIA?"})}),l(g,{marginTop:1,children:l(Bt,{options:[{label:"Self-Host \u2014 run everything in Docker",value:"selfhost"},{label:"Developer \u2014 local dev with hot reload",value:"developer"}],onChange:r=>e(r)})})]}),Gt=({onSelect:e})=>h(g,{flexDirection:"column",marginTop:1,paddingX:1,borderStyle:"round",borderColor:x,children:[l(u,{bold:!0,children:"Environment Variables Setup"}),l(g,{marginTop:1,children:l(u,{color:"gray",children:"Choose how you want to configure environment variables:"})}),l(g,{marginTop:1,children:l(Bt,{options:[{label:"Manual Setup (Recommended)",value:"manual"},{label:"Infisical (Advanced)",value:"infisical"}],onChange:r=>e(r)})}),h(g,{marginTop:1,flexDirection:"column",children:[l(u,{color:"gray",dimColor:!0,children:"Manual Setup: Configure variables interactively (recommended for most users)"}),l(u,{color:"gray",dimColor:!0,children:"Infisical: All secrets managed in Infisical dashboard (requires pre-configuration)"})]})]}),jt=({onSubmit:e})=>{let[t,r]=B({INFISICAL_PROJECT_ID:"",INFISICAL_MACHINE_IDENTITY_CLIENT_ID:"",INFISICAL_MACHINE_IDENTITY_CLIENT_SECRET:""}),[o,n]=B(0),[i,a]=B(null),s=[{key:"INFISICAL_PROJECT_ID",description:"Found in your Infisical project settings"},{key:"INFISICAL_MACHINE_IDENTITY_CLIENT_ID",description:"From Access Control \u2192 Machine Identities"},{key:"INFISICAL_MACHINE_IDENTITY_CLIENT_SECRET",description:"Generated when creating the machine identity"}];ce((p,f)=>{if(f.tab||f.downArrow)n(d=>d<s.length-1?d+1:d);else if(f.upArrow)n(d=>d>0?d-1:d);else if(f.return){if(o<s.length-1){n(m=>m+1);return}let d=s.filter(m=>!t[m.key].trim());if(d.length>0){a(`Required: ${d.map(S=>S.key).join(", ")}`);let m=s.findIndex(S=>!t[S.key].trim());m>=0&&n(m);return}e(t)}});let c=s[o];return h(g,{flexDirection:"column",marginTop:1,paddingX:1,borderStyle:"round",borderColor:x,children:[l(g,{marginBottom:1,children:l(u,{bold:!0,color:x,children:"Infisical Configuration"})}),l(g,{marginBottom:1,children:l(u,{color:"gray",children:"All secrets managed in your Infisical project. Only credentials stored locally."})}),h(g,{marginBottom:1,flexDirection:"column",children:[l(u,{color:"gray",children:"Configure your Infisical credentials."}),h(u,{color:"gray",dimColor:!0,children:["Visit"," ",l(u,{color:"cyan",underline:!0,children:"app.infisical.com"})," ","to get these values."]})]}),s.map((p,f)=>{let d=p.key.includes("SECRET")||p.key.includes("TOKEN");return h(g,{flexDirection:"column",marginBottom:1,children:[l(g,{children:h(u,{color:f===o?x:"white",children:[f===o?"\u25B8 ":" ",p.key,":"]})}),l(g,{marginLeft:2,children:l(u,{color:"gray",dimColor:!0,children:p.description})}),f===o?l(g,{marginLeft:2,children:l(Le,{value:t[p.key],onChange:m=>{r(S=>({...S,[p.key]:m})),a(null)},placeholder:"Enter value...",mask:d?"*":void 0})}):l(g,{marginLeft:2,children:l(u,{color:t[p.key]?"green":"gray",children:t[p.key]?d?`\u2713 ${"*".repeat(8)}`:`\u2713 ${t[p.key]}`:"(not set)"})})]},p.key)}),i&&l(g,{marginTop:1,children:l(u,{color:"red",children:i})}),l(g,{marginTop:1,children:h(u,{dimColor:!0,children:[l(u,{bold:!0,children:"Enter"})," confirm \xB7 ",l(u,{bold:!0,children:"\u2191\u2193"})," navigate"]})})]})},qt=({category:e,currentIndex:t,totalGroups:r,onSubmit:o})=>{let[n,i]=B(()=>{let m={};for(let S of e.variables)m[S.name]=S.defaultValue||"";return m}),[a,s]=B(0),[c,p]=B(null);Be(()=>{let m={};for(let S of e.variables)m[S.name]=S.defaultValue||"";i(m),s(0),p(null)},[e.name]),ce((m,S)=>{if(S.tab||S.downArrow)s(v=>v<e.variables.length-1?v+1:v);else if(S.upArrow)s(v=>v>0?v-1:v);else if(S.escape){let v=e.variables.filter(y=>y.required&&!n[y.name]?.trim());if(v.length>0){p(`Required fields cannot be skipped: ${v.map(y=>y.name).join(", ")}`);return}o(n)}});let f=()=>{if(a<e.variables.length-1)s(a+1);else{let m=e.variables.filter(S=>S.required&&!n[S.name]?.trim());if(m.length>0){p(`Required fields are missing: ${m.map(S=>S.name).join(", ")}`);return}p(null),o(n)}},d=e.variables.some(m=>m.required);return h(g,{flexDirection:"column",marginTop:1,paddingX:1,borderStyle:"round",borderColor:c?"red":x,children:[h(g,{justifyContent:"space-between",children:[h(u,{bold:!0,children:["Configure ",e.name]}),h(u,{color:"gray",children:["Group ",t+1," / ",r]})]}),l(g,{marginTop:1,children:l(u,{color:"gray",children:e.description})}),l(g,{marginTop:1,flexDirection:"column",children:e.variables.map((m,S)=>{let v=S===a,y=!!m.defaultValue;return h(g,{flexDirection:"column",marginBottom:1,children:[h(g,{children:[h(u,{color:v?x:"gray",bold:v,children:[v?"\u279C ":" ",m.name]}),m.required&&h(u,{color:"red",bold:!0,children:[" ","*"]}),y&&!v&&h(u,{color:"gray",dimColor:!0,children:[" ","(default: ",m.defaultValue,")"]})]}),v&&l(g,{marginLeft:2,children:l(Le,{value:n[m.name]||"",onChange:w=>{i(b=>({...b,[m.name]:w})),c&&p(null)},onSubmit:f,placeholder:y?`Default: ${m.defaultValue}`:m.required?"Enter a value (required)":"Press Enter to skip"})})]},m.name)})}),c&&l(g,{marginTop:1,children:h(u,{color:"red",bold:!0,children:["\u26A0 ",c]})}),l(g,{marginTop:1,children:h(u,{dimColor:!0,children:[l(u,{bold:!0,children:"Enter"})," next \xB7 ",l(u,{bold:!0,children:"\u2191\u2193"})," navigate",!d&&h(u,{children:[" ","\xB7 ",l(u,{bold:!0,children:"ESC"})," skip"]})]})})]})},Ut=({alternatives:e,onSubmit:t})=>{let[r,o]=B(new Set),[n,i]=B({}),[a,s]=B(0),[c,p]=B(null);Be(()=>{let w={};for(let b of e)for(let E of b.variables)w[E.name]=E.defaultValue||"";i(w)},[e]);let f=[];for(let w=0;w<e.length;w++)if(f.push({type:"provider",categoryIndex:w}),r.has(w)){let b=e[w];if(b)for(let E=0;E<b.variables.length;E++)f.push({type:"field",categoryIndex:w,fieldIndex:E})}f.push({type:"submit"});let d=f[a],m=d?.type==="field",S=d?.type==="submit";ce((w,b)=>{let E=Math.min(a,f.length-1);if(E!==a){s(E);return}if(m)b.upArrow?s(P=>Math.max(0,P-1)):(b.downArrow||b.tab)&&s(P=>Math.min(f.length-1,P+1));else if(S)b.upArrow?s(P=>Math.max(0,P-1)):(b.return||w===" ")&&y();else if(b.upArrow)s(P=>Math.max(0,P-1));else if(b.downArrow||b.tab)s(P=>Math.min(f.length-1,P+1));else if((b.return||w===" ")&&d?.type==="provider"){let P=d.categoryIndex;o(Z=>{let _=new Set(Z);return _.has(P)?_.delete(P):_.add(P),_}),c&&p(null)}});let v=()=>{c&&p(null),s(w=>Math.min(f.length-1,w+1))},y=()=>{let w=[],b={};for(let E of r){let P=e[E];if(!P)continue;if(P.variables.some(_=>n[_.name]?.trim())){w.push(P.name);for(let _ of P.variables){let Ge=n[_.name];Ge&&(b[_.name]=Ge)}}}if(w.length===0){r.size===0?p("Enable at least one provider (press Space or Enter)"):p("Enter a value for at least one field");return}t(w,b)};return h(g,{flexDirection:"column",marginTop:1,paddingX:1,borderStyle:"round",borderColor:c?"red":x,children:[h(g,{justifyContent:"space-between",children:[l(u,{bold:!0,children:"Configure AI Provider"}),l(u,{color:"yellow",children:"* At least one required"})]}),l(g,{marginTop:1,children:l(u,{color:"gray",children:"Enable and configure at least one AI provider below:"})}),l(g,{marginTop:1,flexDirection:"column",children:e.map((w,b)=>{let E=r.has(b),P=f.findIndex(_=>_.type==="provider"&&_.categoryIndex===b),Z=a===P;return h(g,{flexDirection:"column",marginBottom:1,children:[h(g,{children:[l(u,{color:Z?x:void 0,bold:Z,children:Z?"\u279C ":" "}),l(u,{color:E?"green":"gray",children:E?"[\u2714]":"[ ]"}),h(u,{color:E?x:"gray",bold:E,children:[" ",w.name]}),w.description&&h(u,{color:"gray",dimColor:!0,children:[" ","- ",w.description]})]}),Z&&w.docsUrl&&h(g,{marginLeft:6,children:[l(u,{color:"yellow",children:"\u{1F4D6} "}),l(u,{color:"blue",underline:!0,children:w.docsUrl})]}),E&&l(g,{marginLeft:4,flexDirection:"column",marginTop:1,children:w.variables.map((_,Ge)=>{let Uo=f.findIndex(Re=>Re.type==="field"&&Re.categoryIndex===b&&Re.fieldIndex===Ge),Se=a===Uo,zt=!!_.defaultValue,yt=n[_.name]||"";return h(g,{flexDirection:"column",marginBottom:1,children:[h(g,{children:[h(u,{color:Se?x:"gray",bold:Se,children:[Se?" \u279C ":" ",_.name]}),!Se&&yt&&l(u,{color:"green",children:" \u2713"}),!Se&&!yt&&zt&&h(u,{color:"gray",dimColor:!0,children:[" ","(default: ",_.defaultValue,")"]})]}),Se&&l(g,{marginLeft:4,children:l(Le,{value:yt,onChange:Re=>{i(Ho=>({...Ho,[_.name]:Re})),c&&p(null)},onSubmit:v,placeholder:zt?`Default: ${_.defaultValue}`:"Enter value..."})})]},_.name)})})]},w.name)})}),c&&l(g,{marginTop:1,children:h(u,{color:"red",bold:!0,children:["\u26A0 ",c]})}),h(g,{marginTop:1,children:[l(u,{color:S?x:void 0,bold:S,children:S?"\u279C ":" "}),l(g,{borderStyle:"round",borderColor:S?x:"gray",paddingX:2,children:l(u,{color:S?x:"gray",bold:S,children:"Continue \u2192"})})]}),l(g,{marginTop:1,children:l(u,{color:"gray",dimColor:!0,children:"\u2191/\u2193 navigate \u2022 Space/Enter toggle/select \u2022 Tab skip field"})})]})},Ht=({currentVar:e,currentIndex:t,totalCount:r,onSubmit:o,onSkip:n})=>{let[i,a]=B(e.defaultValue||""),[s,c]=B(null);Be(()=>{a(e.defaultValue||""),c(null)},[e.name]),ce((d,m)=>{if(m.escape){if(e.required&&!i.trim()){c("This field is required and cannot be skipped");return}n()}});let p=d=>{if(e.required&&!d.trim()){c("This field is required");return}c(null),o(d)},f=!!e.defaultValue;return h(g,{flexDirection:"column",marginTop:1,paddingX:1,borderStyle:"round",borderColor:s?"red":x,children:[h(g,{justifyContent:"space-between",children:[h(g,{children:[l(u,{color:x,bold:!0,children:e.name}),e.required?l(u,{color:"red",children:" *"}):h(u,{color:"gray",dimColor:!0,children:[" ","optional"]})]}),h(u,{color:"gray",children:[t+1,"/",r]})]}),l(g,{marginLeft:1,children:l(u,{color:"gray",children:e.description})}),h(g,{marginTop:1,children:[l(u,{color:x,children:"\u2192 "}),l(Le,{value:i,onChange:d=>{a(d),s&&c(null)},onSubmit:p,placeholder:f?`Default: ${e.defaultValue}`:e.required?"required":"skip with Enter"})]}),s&&l(g,{marginTop:1,children:l(u,{color:"red",children:s})}),l(g,{marginTop:1,children:h(u,{dimColor:!0,children:[l(u,{bold:!0,children:"Enter"})," confirm",!e.required&&h(u,{children:[" ","\xB7 ",l(u,{bold:!0,children:"ESC"})," skip"]})]})})]})},no=({store:e})=>{let[t,r]=B(e.currentState);return Be(()=>{let o=()=>r({...e.currentState});return e.on("change",o),()=>{e.off("change",o)}},[e]),ce((o,n)=>{(n.return||n.escape)&&t.error&&e.submitInput("exit")}),h(ot,{status:t.status,step:t.step,children:[t.step==="Welcome"&&t.inputRequest?.id==="welcome"&&l(Xn,{onConfirm:()=>e.submitInput(!0)}),t.step==="Prerequisites"&&t.data.checks&&l(nt,{checks:t.data.checks}),t.inputRequest?.id==="port_conflicts"&&t.data.portConflicts&&l(at,{portResults:t.data.portConflicts,onAccept:()=>e.submitInput("accept"),onAbort:()=>e.submitInput("abort")}),t.inputRequest?.id==="repo_path"&&l(Jn,{defaultValue:t.inputRequest.meta.default,onSubmit:o=>e.submitInput(o)}),t.inputRequest?.id==="existing_repo"&&t.data.existingRepoPath&&l(Kn,{repoPath:t.data.existingRepoPath,onAction:o=>e.submitInput(o)}),t.step==="Repository Setup"&&!t.inputRequest&&h(g,{flexDirection:"column",borderStyle:"round",padding:1,borderColor:x,children:[l(u,{bold:!0,children:"Cloning Repository"}),h(g,{marginTop:1,flexDirection:"column",children:[l(oo,{value:t.data.repoProgress||0}),t.data.repoPhase&&l(g,{marginTop:1,children:l(u,{color:"gray",children:t.data.repoPhase})})]})]}),t.inputRequest?.id==="setup_mode"&&l($t,{onSelect:o=>e.submitInput(o)}),t.inputRequest?.id==="env_method"&&l(Gt,{onSelect:o=>e.submitInput(o)}),t.inputRequest?.id==="env_infisical"&&l(jt,{onSubmit:o=>e.submitInput(o)}),t.step==="Environment Setup"&&t.inputRequest?.id==="env_var"&&t.data.currentEnvVar&&l(Ht,{categories:t.data.envCategories||[],currentVar:t.data.currentEnvVar,currentIndex:t.data.envVarIndex||0,totalCount:t.data.envVarTotal||0,onSubmit:o=>e.submitInput(o),onSkip:()=>e.submitInput("")}),t.step==="Environment Setup"&&t.inputRequest?.id==="env_group"&&t.data.currentEnvGroup&&l(qt,{category:t.data.currentEnvGroup,currentIndex:t.data.envGroupIndex||0,totalGroups:t.data.envGroupTotal||0,onSubmit:o=>e.submitInput(o)}),t.step==="Environment Setup"&&t.inputRequest?.id==="env_alternatives"&&t.data.alternativeGroups&&l(Ut,{alternatives:t.data.alternativeGroups,onSubmit:(o,n)=>e.submitInput({selectedGroups:o,values:n})}),t.step==="Environment Setup"&&!t.inputRequest&&l(it,{status:t.status}),t.step==="Finished"&&l(Qn,{setupMode:t.data.setupMode,portOverrides:t.data.portOverrides,onConfirm:()=>e.submitInput("exit")}),(t.step==="Install Tools"||t.step==="Project Setup")&&l(Ft,{title:t.step==="Install Tools"?"Installing Tools":"Project Setup",phase:t.data.dependencyPhase||"",progress:t.data.dependencyProgress||0,isComplete:t.step==="Install Tools"?t.data.toolComplete||!1:t.data.dependencyComplete||!1,logs:t.data.dependencyLogs||[]}),t.error&&l(st,{message:t.error.message})]})};import{Spinner as ei}from"@inkjs/ui";import{Box as N,Text as C,useInput as io}from"ink";import{useEffect as so,useRef as ti,useState as ao}from"react";import{jsx as A,jsxs as T}from"react/jsx-runtime";var Wt=8,ri=({logs:e})=>{let[t,r]=ao(0),o=ti(e.length);so(()=>{e.length!==o.current&&(o.current=e.length,r(0))},[e.length]),io((f,d)=>{d.upArrow?r(m=>Math.min(m+1,Math.max(0,e.length-Wt))):d.downArrow&&r(m=>Math.max(0,m-1))});let n=e.length,i=Math.max(0,n-Wt-t),a=Math.max(0,n-t),s=e.slice(i,a),c=i,p=t;return T(N,{flexDirection:"column",marginTop:1,marginLeft:1,children:[c>0&&T(C,{color:"gray",dimColor:!0,children:["\u2191 ",c," more line",c!==1?"s":""]}),A(N,{flexDirection:"column",height:Wt,overflow:"hidden",children:s.map((f,d)=>A(C,{color:"gray",wrap:"truncate",children:f},i+d))}),p>0?T(C,{color:"gray",dimColor:!0,children:["\u2193 ",p," more line",p!==1?"s":""]}):A(C,{color:"gray",dimColor:!0,children:"\u2191\u2193 scroll"})]})},co=({store:e})=>{let[t,r]=ao(e.currentState);return so(()=>{let o=()=>r({...e.currentState});return e.on("change",o),()=>{e.off("change",o)}},[e]),io((o,n)=>{(n.return||n.escape)&&(t.data.started||t.data.stopped||t.error)&&e.submitInput("exit")}),T(N,{flexDirection:"column",width:"100%",children:[A(Pe,{}),(t.step==="Starting"||t.step==="Stopping")&&T(N,{flexDirection:"column",marginTop:1,paddingX:2,borderStyle:"round",borderColor:x,children:[A(ei,{label:t.status||"Working..."}),t.data.repoPath&&A(N,{marginTop:1,children:T(C,{color:"gray",children:["Repository: ",t.data.repoPath]})}),t.data.setupMode&&A(N,{children:T(C,{color:"gray",children:["Mode: ",t.data.setupMode]})}),t.data.dockerLogs&&t.data.dockerLogs.length>0&&A(ri,{logs:t.data.dockerLogs})]}),t.step==="Running"&&t.data.started&&T(N,{flexDirection:"column",marginTop:1,paddingX:2,paddingY:1,borderStyle:"round",borderColor:"green",children:[T(C,{color:"green",bold:!0,children:["\u2713"," GAIA is running!"]}),t.data.setupMode!=="developer"&&T(N,{marginTop:1,flexDirection:"column",children:[T(C,{children:["Web:"," ",T(C,{color:"cyan",bold:!0,children:["http://localhost:",t.data.webPort||3e3]})]}),T(C,{children:["API:"," ",T(C,{color:"cyan",bold:!0,children:["http://localhost:",t.data.apiPort||8e3]})]})]}),t.data.setupMode==="developer"&&T(N,{marginTop:1,flexDirection:"column",children:[T(N,{flexDirection:"column",children:[T(C,{children:["Web:"," ",T(C,{color:"cyan",bold:!0,children:["http://localhost:",t.data.webPort||3e3]})]}),T(C,{children:["API:"," ",T(C,{color:"cyan",bold:!0,children:["http://localhost:",t.data.apiPort||8e3]})]})]}),T(N,{marginTop:1,flexDirection:"column",children:[A(C,{color:"gray",children:"Use gaia dev / gaia dev full for foreground Nx TUI."}),T(C,{color:"gray",children:["Run ",A(C,{color:x,children:"gaia logs"})," to stream logs."]}),T(C,{color:"gray",children:["Run ",A(C,{color:x,children:"gaia stop"})," to shut down."]})]})]}),A(N,{marginTop:1,children:T(C,{dimColor:!0,children:[A(C,{bold:!0,children:"Enter"})," to exit"]})})]}),t.step==="Stopped"&&t.data.stopped&&T(N,{flexDirection:"column",marginTop:1,paddingX:2,paddingY:1,borderStyle:"round",borderColor:x,children:[T(C,{color:x,bold:!0,children:["\u2713"," ",t.status||"All GAIA services stopped."]}),t.data.stopMode==="force-ports"&&A(N,{marginTop:1,children:A(C,{color:"yellow",children:"Force-port cleanup was enabled and may have stopped non-GAIA listeners on app ports."})}),A(N,{marginTop:1,children:T(C,{dimColor:!0,children:[A(C,{bold:!0,children:"Enter"})," to exit"]})})]}),t.error&&T(N,{borderStyle:"single",borderColor:"red",padding:1,marginTop:2,children:[T(C,{color:"red",children:["Error: ",t.error.message]}),A(N,{marginTop:1,children:T(C,{dimColor:!0,children:[A(C,{bold:!0,children:"Enter"})," to exit"]})})]})]})};import{Spinner as oi}from"@inkjs/ui";import{Box as le,Text as V,useInput as lo}from"ink";import{useEffect as ni,useState as ii}from"react";import{jsx as D,jsxs as K}from"react/jsx-runtime";var po=({store:e})=>{let[t,r]=ii(e.currentState);return ni(()=>{let o=()=>r({...e.currentState});return e.on("change",o),()=>{e.off("change",o)}},[e]),lo((o,n)=>{(n.return||n.escape)&&t.error&&e.submitInput("exit")}),K(ot,{status:t.status,step:t.step,steps:to,children:[t.step==="Detect Repo"&&K(le,{flexDirection:"column",paddingX:2,borderStyle:"round",borderColor:x,children:[D(V,{bold:!0,children:"Detecting GAIA Repository"}),D(le,{marginTop:1,children:D(oi,{label:"Searching for repository..."})}),t.data.repoPath&&D(le,{marginTop:1,children:K(V,{color:"green",children:["Found: ",t.data.repoPath]})})]}),t.step==="Prerequisites"&&t.data.checks&&D(nt,{checks:t.data.checks}),t.inputRequest?.id==="port_conflicts"&&t.data.portConflicts&&D(at,{portResults:t.data.portConflicts,onAccept:()=>e.submitInput("accept"),onAbort:()=>e.submitInput("abort")}),t.inputRequest?.id==="setup_mode"&&D($t,{onSelect:o=>e.submitInput(o)}),t.inputRequest?.id==="env_method"&&D(Gt,{onSelect:o=>e.submitInput(o)}),t.inputRequest?.id==="env_infisical"&&D(jt,{onSubmit:o=>e.submitInput(o)}),t.step==="Environment Setup"&&t.inputRequest?.id==="env_var"&&t.data.currentEnvVar&&D(Ht,{categories:t.data.envCategories||[],currentVar:t.data.currentEnvVar,currentIndex:t.data.envVarIndex||0,totalCount:t.data.envVarTotal||0,onSubmit:o=>e.submitInput(o),onSkip:()=>e.submitInput("")}),t.step==="Environment Setup"&&t.inputRequest?.id==="env_group"&&t.data.currentEnvGroup&&D(qt,{category:t.data.currentEnvGroup,currentIndex:t.data.envGroupIndex||0,totalGroups:t.data.envGroupTotal||0,onSubmit:o=>e.submitInput(o)}),t.step==="Environment Setup"&&t.inputRequest?.id==="env_alternatives"&&t.data.alternativeGroups&&D(Ut,{alternatives:t.data.alternativeGroups,onSubmit:(o,n)=>e.submitInput({selectedGroups:o,values:n})}),t.step==="Environment Setup"&&!t.inputRequest&&D(it,{status:t.status}),t.step==="Project Setup"&&D(Ft,{title:"Project Setup",phase:t.data.dependencyPhase||"",progress:t.data.dependencyProgress||0,isComplete:t.data.dependencyComplete||!1,logs:t.data.dependencyLogs||[]}),t.step==="Finished"&&D(si,{setupMode:t.data.setupMode,portOverrides:t.data.portOverrides,onConfirm:()=>e.submitInput("exit")}),t.error&&D(st,{message:t.error.message})]})},si=({setupMode:e,portOverrides:t,onConfirm:r})=>{lo((a,s)=>{s.return&&r()});let o=t?.[3e3]??3e3,n=t?.[8e3]??8e3,i=e==="selfhost";return K(le,{flexDirection:"column",marginTop:2,borderStyle:"round",borderColor:x,padding:1,children:[D(V,{color:x,bold:!0,children:"Setup Complete!"}),K(le,{marginTop:1,children:[D(V,{bold:!0,children:"Run: "}),D(V,{color:"cyan",children:i?"$ gaia start":"$ gaia dev"})]}),K(le,{marginTop:1,flexDirection:"column",children:[K(V,{children:["Web:"," ",K(V,{color:"cyan",bold:!0,children:["http://localhost:",o]})]}),K(V,{children:["API:"," ",K(V,{color:"cyan",bold:!0,children:["http://localhost:",n]})]})]}),D(le,{marginTop:1,children:D(V,{color:"gray",children:i?"gaia logs \xB7 gaia stop \xB7 gaia status \xB7 gaia setup":"gaia dev full \xB7 gaia logs \xB7 gaia stop \xB7 gaia status \xB7 gaia setup"})}),D(le,{marginTop:1,children:K(V,{dimColor:!0,children:[D(V,{bold:!0,children:"Enter"})," to exit"]})})]})};import{Spinner as ai}from"@inkjs/ui";import{Box as O,Text as k,useInput as ci}from"ink";import{useEffect as uo,useState as Vt}from"react";import{jsx as I,jsxs as L}from"react/jsx-runtime";var mo=({store:e})=>{let[t,r]=Vt(e.currentState),[o,n]=Vt(!1),[i,a]=Vt(null);return uo(()=>{let s=()=>r({...e.currentState});return e.on("change",s),()=>{e.off("change",s)}},[e]),uo(()=>{n(!1),a(new Date().toLocaleTimeString())},[t.data.services]),ci((s,c)=>{(c.return||c.escape)&&t.step==="Results"&&e.submitInput("exit"),s==="r"&&t.step==="Results"&&t.data.refreshable&&!o&&(n(!0),e.submitInput("refresh"))}),L(O,{flexDirection:"column",width:"100%",children:[I(Pe,{}),t.step==="Checking"&&I(O,{marginTop:1,children:I(ai,{label:t.data.services?"Refreshing service health...":"Checking service health..."})}),t.step==="Results"&&t.data.services&&L(O,{flexDirection:"column",children:[L(O,{flexDirection:"column",borderStyle:"round",borderColor:x,paddingX:2,paddingY:1,children:[L(O,{justifyContent:"space-between",children:[I(k,{bold:!0,color:x,children:"GAIA Service Status"}),i&&L(k,{color:"gray",dimColor:!0,children:["checked ",i," \xB7 ",I(k,{bold:!0,children:"r"})," refresh"]})]}),L(O,{marginTop:1,flexDirection:"column",children:[L(O,{children:[I(O,{width:22,children:I(k,{bold:!0,children:"Service"})}),I(O,{width:10,children:I(k,{bold:!0,children:"Status"})}),I(O,{width:10,children:I(k,{bold:!0,children:"Latency"})})]}),I(k,{color:"gray",children:"\u2500".repeat(42)}),[...t.data.services].sort((s,c)=>s.status==="down"&&c.status!=="down"?-1:s.status!=="down"&&c.status==="down"?1:s.name.localeCompare(c.name)).map(s=>L(O,{children:[I(O,{width:22,children:L(k,{children:[s.name," (:",s.port,")"]})}),I(O,{width:10,children:I(k,{color:s.status==="up"?"green":"red",bold:!0,children:s.status==="up"?"\u2713 UP":"\u2717 DOWN"})}),I(O,{width:10,children:I(k,{color:"gray",children:s.latency?`${s.latency}ms`:"--"})})]},s.name))]})]}),t.data.docker&&L(O,{flexDirection:"column",borderStyle:"round",borderColor:"gray",paddingX:2,paddingY:1,marginTop:1,children:[I(k,{bold:!0,children:"Docker Containers"}),L(k,{color:"gray",children:["Docker:"," ",t.data.docker.running?I(k,{color:"green",children:"Running"}):I(k,{color:"red",children:"Not running"})]}),t.data.docker.containers?.length>0&&I(O,{marginTop:1,flexDirection:"column",children:t.data.docker.containers.map(s=>L(O,{children:[L(k,{color:s.status==="running"?"green":"red",children:[s.status==="running"?"\u2713":"\u2717"," "]}),I(k,{children:s.name}),s.health&&L(k,{color:"gray",children:[" (",s.health,")"]})]},s.name))})]}),I(O,{marginTop:1,children:L(k,{dimColor:!0,children:[I(k,{bold:!0,children:"Enter"})," exit \xB7 ",I(k,{bold:!0,children:"r"})," refresh"]})})]}),t.error&&I(O,{borderStyle:"single",borderColor:"red",padding:1,marginTop:2,children:L(k,{color:"red",children:["Error: ",t.error.message]})})]})};import{jsx as Y,jsxs as Fe}from"react/jsx-runtime";var pi=["init","setup","status","start","stop"],Yt=class extends li.Component{constructor(t){super(t),this.state={error:null}}static getDerivedStateFromError(t){return{error:t}}render(){return this.state.error?Fe(ct,{flexDirection:"column",padding:1,children:[Y(ve,{color:"red",bold:!0,children:"An unexpected error occurred:"}),Y(ve,{color:"red",children:this.state.error.message}),this.state.error.stack&&Y(ct,{marginTop:1,children:Y(ve,{color:"gray",dimColor:!0,children:this.state.error.stack})})]}):this.props.children}},ui=({store:e,command:t})=>{switch(t){case"init":return Y(no,{store:e});case"setup":return Y(po,{store:e});case"status":return Y(mo,{store:e});case"start":case"stop":return Y(co,{store:e,command:t});default:return Fe(ct,{flexDirection:"column",padding:1,children:[Fe(ve,{color:"red",children:["Unknown command: ",t]}),Fe(ct,{marginTop:1,flexDirection:"column",children:[Y(ve,{bold:!0,children:"Available commands:"}),pi.map(r=>Fe(ve,{children:[" ",Y(ve,{color:"cyan",children:r})]},r))]})]})}},fo=({store:e,command:t})=>Y(Yt,{children:Y(ui,{store:e,command:t})});import{EventEmitter as di}from"events";var mi=150,Xt=class extends di{state={step:"init",status:"",error:null,data:{},inputRequest:null};inputResolver=null;emitTimer=null;emitPending=!1;autoResolveInputs=new Map;setAutoResolve(t,r="exit"){this.autoResolveInputs.set(t,r)}get currentState(){return this.state}scheduleEmit(){this.emitPending=!0,this.emitTimer||(this.emitTimer=setTimeout(()=>{this.emitTimer=null,this.emitPending&&(this.emitPending=!1,this.emit("change",this.state))},mi))}emitNow(){this.emitTimer&&(clearTimeout(this.emitTimer),this.emitTimer=null),this.emitPending=!1,this.emit("change",this.state)}setStep(t){this.state.step=t,this.emitNow()}setStatus(t){this.state.status=t,this.scheduleEmit()}setError(t){this.state.error=t,t!==null&&this.inputResolver&&(this.inputResolver(null),this.inputResolver=null,this.state.inputRequest=null),this.emitNow()}updateData(t,r){this.state.data={...this.state.data,[t]:r},this.scheduleEmit()}waitForInput(t,r,o){return this.autoResolveInputs.has(t)?(this.state.inputRequest=null,this.emitNow(),Promise.resolve(this.autoResolveInputs.get(t))):(this.state.inputRequest={id:t,meta:r},this.emitNow(),new Promise(n=>{if(this.inputResolver=n,o!=null){let i=setTimeout(()=>{this.inputResolver&&(this.inputResolver=null,this.state.inputRequest=null,this.emitNow(),n(null))},o),a=this.inputResolver;this.inputResolver=s=>{clearTimeout(i),a(s)}}}))}submitInput(t){this.inputResolver&&(this.inputResolver(t),this.inputResolver=null,this.state.inputRequest=null,this.emitNow())}},go=()=>new Xt;function Jt(){return process.stdin.isTTY===!0&&process.stdout.isTTY===!0}function ho(e){if(Jt())return;let t=e?`'gaia ${e}'`:"this command";console.error(`Error: ${t} needs an interactive terminal (TTY) to prompt for input.`),console.error("Re-run it from a regular shell session \u2014 not a pipe, redirect, or non-TTY environment."),process.exit(1)}function vo(e){let t="",r="",o="";e.on("change",n=>{n.step&&n.step!==t&&(t=n.step,console.info(`
34
+ [${n.step}]`)),n.status&&n.status!==r&&(r=n.status,console.info(` ${n.status}`)),n.error&&n.error.message!==o&&(o=n.error.message,console.error(` Error: ${n.error.message}`))})}var hi=50,vi=130;async function z(e){let t=go();if(e.whenNonInteractive==="fail"){ho(e.command),await So(t,e);return}Jt()?await So(t,e):await Si(t,e)}async function Si(e,t){vo(e);for(let[r,o]of t.autoResolve??[])e.setAutoResolve(r,o);try{await t.runFlow(e),t.onPlainComplete?.(e)}catch(r){e.setError(r)}yo(e)}async function So(e,t){let{unmount:r}=fi(gi.createElement(fo,{store:e,command:t.command})),o=()=>{r(),process.exit(vi)};process.once("SIGINT",o),process.once("SIGTERM",o),await new Promise(n=>setTimeout(n,hi));try{await t.runFlow(e)}catch(n){e.setError(n)}finally{process.off("SIGINT",o),process.off("SIGTERM",o)}e.currentState.error&&await e.waitForInput("exit"),r(),yo(e)}function yo(e){let t=e.currentState.error?1:0,r=[process.stdout,process.stderr].filter(n=>n.writableLength>0);r.length===0&&process.exit(t);let o=r.length;for(let n of r)n.once("drain",()=>{o-=1,o===0&&process.exit(t)})}import*as ne from"fs";import*as Po from"os";import*as ue from"path";import*as xo from"path";var yi=e=>new Promise(t=>setTimeout(t,e));async function lt(e){e.setStep("Setup Mode"),e.setStatus("Choose how to run GAIA...");let t=await e.waitForInput("setup_mode");return e.updateData("setupMode",t),t}async function pt(e,t,r,o){e.setStep("Environment Setup"),e.setStatus("Configuring environment..."),e.updateData("setupMode",r),e.setStatus("Configuring environment variables...");let n=await e.waitForInput("env_method");e.updateData("envMethod",n);let i={};i.ENV="development";let a=At();for(let c of a){let p=_t(c,r);p&&(i[c]=p)}let s=jr(r);for(let[c,p]of Object.entries(s))i[c]=p;if(n==="infisical")await xi(e,i),e.setStatus("Infisical credentials saved. Ensure your Infisical project contains all required variables.");else try{await wi(e,t,i,r)}catch(c){e.setError(c);return}o&&$r(i,o,r);try{await bi(e,t,i,r,o)}catch(c){e.setError(c);return}await yi(1e3)}async function xi(e,t){e.setStatus("Configuring Infisical...");let r=await e.waitForInput("env_infisical");t.INFISICAL_PROJECT_ID=r.INFISICAL_PROJECT_ID,t.INFISICAL_MACHINE_IDENTITY_CLIENT_ID=r.INFISICAL_MACHINE_IDENTITY_CLIENT_ID,t.INFISICAL_MACHINE_IDENTITY_CLIENT_SECRET=r.INFISICAL_MACHINE_IDENTITY_CLIENT_SECRET}async function wi(e,t,r,o){e.setStatus("Parsing environment variables...");let n;try{n=await Lr(t),n=Gr(n,o)}catch(v){throw o==="selfhost"?new Error(`Manual environment setup requires Python to parse config schema.
9
35
  For self-host mode, we recommend using Infisical for secret management.
10
36
  Alternatively, install Python 3.11+ and try again.
11
37
 
12
- Original error: ${m.message}`):new Error(`Failed to parse settings: ${m.message}`)}let s=new Set,c=[],a=new Set;for(let m of n)if(m.alternativeGroup&&!a.has(m.name)){let d=n.find(h=>h.name===m.alternativeGroup);d&&(c.push([m,d]),s.add(m.name),s.add(d.name),a.add(m.name),a.add(d.name))}let l=n.filter(m=>m.variables.length===1&&!s.has(m.name)),p=n.filter(m=>m.variables.length>1&&!s.has(m.name));for(let m of c){e.updateData("alternativeGroups",m),e.setStatus("Choose an AI provider...");let d=await e.waitForInput("env_alternatives");for(let[h,v]of Object.entries(d.values))v&&(o[h]=v)}let x=ft(),y=[...l.flatMap(m=>m.variables).filter(m=>!x.includes(m.name))].sort((m,d)=>m.required&&!d.required?-1:!m.required&&d.required?1:0);e.updateData("envVarTotal",y.length);for(let m=0;m<y.length;m++){let d=y[m];if(!d)continue;e.updateData("currentEnvVar",d),e.updateData("envVarIndex",m),e.setStatus(`Configuring ${d.name}...`);let h=await e.waitForInput("env_var",{varName:d.name});(h||d.required||d.defaultValue)&&(o[d.name]=h||d.defaultValue||"")}let S=[...p].filter(m=>!m.variables.every(d=>x.includes(d.name))).sort((m,d)=>{let h=m.variables.some(I=>I.required),v=d.variables.some(I=>I.required);return h&&!v?-1:!h&&v?1:0});e.updateData("envGroupTotal",S.length);for(let m=0;m<S.length;m++){let d=S[m];if(!d)continue;e.updateData("currentEnvGroup",d),e.updateData("envGroupIndex",m),e.setStatus(`Configuring ${d.name}...`);let h=await e.waitForInput("env_group",{groupName:d.name});for(let[v,I]of Object.entries(h)){let C=d.variables.find(k=>k.name===v);(I||C?.required||C?.defaultValue)&&(o[v]=I||C?.defaultValue||"")}}}async function ao(e,t,o,r,n){e.setStatus("Writing API environment file...");try{let c=Jt.join(t,"apps","api");Ut(c,o),e.setStatus("API environment variables configured!")}catch(c){throw new Error(`Failed to write API .env file: ${c.message}`)}e.setStatus("Writing web environment file...");try{Xt(t,r,n),e.setStatus("Web environment variables configured!")}catch(c){throw new Error(`Failed to write web .env file: ${c.message}`)}let s=n&&Object.keys(n).length>0;if(s||r==="selfhost"){e.setStatus("Writing Docker Compose environment...");try{s&&Kt(t),Yt(t,n??{},r),e.setStatus("Docker Compose environment configured!")}catch(c){throw new Error(`Failed to write Docker Compose .env: ${c.message}`)}}}import{execa as so}from"execa";import qe from"fs";import co from"simple-git";async function zt(e,t,o,r){if(qe.existsSync(e)){let n=`${e}/.git`;if(!qe.existsSync(n))throw new Error(`Directory ${e} exists but is not a git repository`);await co().cwd(e).pull(),o(100,"Already exists, pulled latest")}else try{let n=["clone","--progress"];r&&n.push("--branch",r),n.push(t,e);let s=so("git",n);s.stderr?.on("data",c=>{let a=c.toString();a.includes("Counting objects")?o(5,"Counting objects"):a.includes("Compressing objects")&&o(10,"Compressing objects");let l=a.match(/Receiving objects:\s+(\d+)%\s+\((\d+)\/(\d+)\)/);if(l?.[1]){let x=Math.min(100,parseInt(l[1],10)),T=l[2],y=l[3];o(10+Math.floor(x*.5),`Receiving objects: ${T}/${y}`)}let p=a.match(/Resolving deltas:\s+(\d+)%\s+\((\d+)\/(\d+)\)/);if(p?.[1]){let x=Math.min(100,parseInt(p[1],10)),T=p[2],y=p[3];o(60+Math.floor(x*.4),`Resolving deltas: ${T}/${y}`)}}),await s,o(100,"Clone complete")}catch(n){throw qe.existsSync(e)&&qe.rmSync(e,{recursive:!0,force:!0}),n}}import{execSync as ht}from"child_process";import*as M from"fs";import*as je from"os";import*as q from"path";var ke=process.platform==="win32";function Ae(e){try{return ht(e,{encoding:"utf-8",stdio:["pipe","pipe","pipe"]}).trim()}catch{return null}}function Zt(){let e=Ae("npm config get prefix");return e?ke?e:q.join(e,"bin"):null}function er(){let e=Ae("pnpm bin -g");if(e&&M.existsSync(e))return e;let t=Ae("pnpm root -g");if(t){let o=q.join(q.dirname(t),"bin");if(M.existsSync(o))return o}return null}function tr(){let e=q.join(je.homedir(),".bun","bin");return M.existsSync(e)?e:null}function rr(){let e=Ae("yarn global bin");return e&&M.existsSync(e)?e:null}function uo(){let e=ke?"gaia.cmd":"gaia";for(let t of[Zt,er,tr,rr]){let o=t();if(o&&M.existsSync(q.join(o,e)))return o}if(ke)for(let t of[Zt,er,tr,rr]){let o=t();if(o&&M.existsSync(q.join(o,"gaia")))return o}return null}function po(){try{return ht(ke?"where gaia":"command -v gaia",{stdio:["pipe","pipe","pipe"]}),!0}catch{return!1}}function mo(){let e=process.env.SHELL||"",t=je.homedir();if(e.includes("zsh"))return q.join(t,".zshrc");if(e.includes("bash")){let o=q.join(t,".bashrc"),r=q.join(t,".bash_profile");return M.existsSync(o)?o:r}return e.includes("fish")?q.join(t,".config","fish","config.fish"):null}function fo(e,t){try{if((M.existsSync(t)?M.readFileSync(t,"utf-8"):"").includes(e))return!0;let n=t.includes("fish")?`
13
- set -gx PATH "${e}" $PATH # Added by GAIA CLI
14
- `:`
15
- export PATH="${e}:$PATH" # Added by GAIA CLI
16
- `;return M.appendFileSync(t,n),!0}catch{return!1}}function go(e){try{let t=Ae(`powershell -Command "[Environment]::GetEnvironmentVariable('Path', 'User')"`);if(t&&t.includes(e))return!0;ht(`setx PATH "${e};${t||""}"`,{stdio:["pipe","pipe","pipe"]});let o=q.join(je.homedir(),"Documents","PowerShell","Microsoft.PowerShell_profile.ps1"),r=q.dirname(o);return M.existsSync(r)||M.mkdirSync(r,{recursive:!0}),(M.existsSync(o)?M.readFileSync(o,"utf-8"):"").includes(e)||M.appendFileSync(o,`
17
- $env:Path = "${e};" + $env:Path # Added by GAIA CLI
18
- `),!0}catch{return!1}}async function St(){if(po())return{success:!0,message:"gaia command is ready.",inPath:!0,pathAdded:!1};let e=uo();if(!e)return{success:!1,message:"Could not find gaia binary. Run manually: npm install -g @heygaia/cli",inPath:!1,pathAdded:!1};if(ke)return go(e)?{success:!0,message:"Added to PATH. Restart your terminal for the 'gaia' command to be available.",inPath:!1,pathAdded:!0}:{success:!1,message:`Add to your PATH manually: setx PATH "${e};%PATH%"`,inPath:!1,pathAdded:!1};let t=mo();if(!t)return{success:!1,message:`Add to your PATH: export PATH="${e}:$PATH"`,inPath:!1,pathAdded:!1};if(fo(e,t)){let r=q.basename(t);return{success:!0,message:`Added to PATH via ~/${r}. Restart terminal or run: source ~/${r}`,inPath:!1,pathAdded:!0}}return{success:!1,message:`Could not write to ${t}. Add manually: export PATH="${e}:$PATH"`,inPath:!1,pathAdded:!1}}import{execa as te}from"execa";var X={git:"https://git-scm.com/downloads",docker:"https://docs.docker.com/get-docker/",mise:"https://mise.jdx.dev/getting-started.html"},ho={8e3:"API Server",5432:"PostgreSQL",6379:"Redis",27017:"MongoDB",5672:"RabbitMQ",3e3:"Web Frontend",8080:"ChromaDB",8083:"Mongo Express"};async function He(){try{return await te("git",["--version"]),"success"}catch{return"error"}}async function Te(){let e=!1,t=!1,o;try{await te("docker",["--version"]),e=!0}catch{return{name:"Docker",installUrl:X.docker,installed:!1,working:!1,errorMessage:"Docker is not installed"}}try{await te("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:X.docker,installed:e,working:t,errorMessage:o}}async function ve(){try{return await te("mise",["--version"]),"success"}catch{return"missing"}}async function We(){if((await import("node:os")).platform()==="win32")try{return await te("powershell",["-Command","irm https://mise.jdx.dev/install.ps1 | iex"]),!0}catch{return!1}try{return await te("sh",["-c","curl https://mise.jdx.dev/install.sh | sh"]),!0}catch{return!1}}async function Ve(e){let t=await import("node:net"),o=[],r=n=>new Promise(s=>{let c=t.createServer();c.once("error",()=>s(!1)),c.once("listening",()=>{c.close(()=>s(!0))}),c.listen(n)});for(let n of e){let s=ho[n]||`Port ${n}`;if(await r(n))o.push({port:n,service:s,available:!0});else{let a=await So(n),l=await xo(n+1,n+100,r);o.push({port:n,service:s,available:!1,usedBy:a,alternative:l||void 0})}}return o}async function So(e){if((await import("node:os")).platform()==="win32"){try{let{stdout:r}=await te("netstat",["-ano","-p","TCP"]),n=r.trim().split(`
19
- `);for(let s of n)if(s.includes(`:${e}`)&&s.includes("LISTENING")){let c=s.trim().split(/\s+/),a=c[c.length-1];if(a)try{let{stdout:l}=await te("tasklist",["/FI",`PID eq ${a}`,"/FO","CSV","/NH"]);return l.trim().split(",")[0]?.replace(/"/g,"")||`PID ${a}`}catch{return`PID ${a}`}}}catch{}return}try{let{stdout:r}=await te("lsof",["-i",`:${e}`,"-sTCP:LISTEN","-P","-n"]),n=r.trim().split(`
20
- `);if(n.length>1)return n[1]?.split(/\s+/)?.[0]||void 0}catch{}}async function xo(e,t,o){for(let r=e;r<=t;r++)if(await o(r))return r;return null}import*as N from"fs";import*as Q from"path";var yo=e=>new Promise(t=>setTimeout(t,e)),To="dev-start.log";var nr=".gaia-dev.pid";function ir(e){let t=Q.join(e,".env");return N.existsSync(t)?["--env-file",".env"]:[]}async function Be(e,t,o,r,n,s){if(t==="selfhost"){let c=s?.build??!1,a=s?.pull??!1;o?.(c?"Building and starting all services in Docker...":"Starting all services in Docker (selfhost mode)...");let l=Q.join(e,"infra/docker"),p=ir(l),x=r&&Object.keys(r).length>0?xe(r):void 0,T=["compose","-f","docker-compose.selfhost.yml",...p,"up","-d","--remove-orphans"];c&&T.push("--build"),a&&T.push("--pull","always");let y=c?900*1e3:300*1e3;await V("docker",T,l,void 0,n,x,y),o?.("All services started in Docker!")}else{o?.("Starting development servers...");let{spawn:c}=await import("child_process"),a=Q.join(e,To),l=Q.join(e,nr),p=N.openSync(a,"w"),x;try{x=c("mise",["dev"],{cwd:e,stdio:["ignore",p,p],detached:!0,shell:!0}),x.unref()}finally{N.closeSync(p)}if(x.pid!=null&&N.writeFileSync(l,String(x.pid),"utf-8"),await yo(1500),x.pid!=null)try{process.kill(x.pid,0)}catch{throw new Error(`Development servers crashed on startup. Check logs at: ${a}`)}o?.(`Development servers started! Logs: ${a}`)}}async function ar(e,t,o){let r=Q.join(e,"infra/docker"),n=await xt(e);t?.("Stopping Docker services...");try{let s=ir(r),c=n==="selfhost"?["compose","-f","docker-compose.selfhost.yml",...s,"down"]:["compose",...s,"down"];await V("docker",c,r)}catch{}if(n!=="selfhost"){t?.("Stopping local processes...");let s=Q.join(e,nr),c=!1;if(N.existsSync(s)){try{let a=Number.parseInt(N.readFileSync(s,"utf-8").trim(),10);if(!Number.isNaN(a)&&a>0)try{process.kill(-a,"SIGTERM"),c=!0}catch{}}catch{}try{N.unlinkSync(s)}catch{}}if(!c)try{let a=o?.[8e3]??8e3,l=o?.[3e3]??3e3;if(process.platform==="win32")for(let p of[a,l])try{await V("powershell",["-Command",`Get-NetTCPConnection -LocalPort ${p} -ErrorAction SilentlyContinue | ForEach-Object { Stop-Process -Id $_.OwningProcess -Force -ErrorAction SilentlyContinue }`],e)}catch{}else for(let p of[a,l])try{await V("sh",["-c",`lsof -ti :${p} -sTCP:LISTEN | xargs kill 2>/dev/null || true`],e)}catch{}}catch{}}t?.("All services stopped.")}async function xt(e){let t=Q.join(e,"apps","api",".env");if(!N.existsSync(t))return null;let o=N.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 V(e,t,o,r,n,s,c){let{spawn:a}=await import("child_process");return new Promise((l,p)=>{let x=a(e,t,{cwd:o,stdio:["ignore","pipe","pipe"],shell:!0,env:s?{...process.env,...s}:void 0}),T="",y=0,S=!1,m;c&&(m=setTimeout(()=>{S=!0,x.kill("SIGTERM"),p(new Error(`Command timed out after ${Math.round(c/6e4)}m. Check \`docker compose logs\` to debug.`))},c)),x.stdout?.on("data",d=>{let h=d.toString();T+=h,n?.(h),y=Math.min(y+5,95),r?.(y)}),x.stderr?.on("data",d=>{let h=d.toString();T+=h,n?.(h),y=Math.min(y+5,95),r?.(y)}),x.on("close",d=>{m&&clearTimeout(m),!S&&(d===0?(r?.(100),l()):p(new Error(`Command failed with code ${d}: ${T.slice(-500)}`)))}),x.on("error",d=>{m&&clearTimeout(m),!S&&p(d)})})}function z(e){let t=e||process.cwd();for(;t!==Q.dirname(t);){if(N.existsSync(Q.join(t,"apps/api/app/config/settings_validator.py")))return t;t=Q.dirname(t)}let o=pt();if(o?.repoPath){if(N.existsSync(Q.join(o.repoPath,"apps/api/app/config/settings_validator.py")))return o.repoPath;console.warn(`Warning: Saved repo path "${o.repoPath}" is no longer a valid GAIA installation. Resetting config.`),De({repoPath:"",setupComplete:!1})}return null}var vo=process.env.GAIA_CLI_DEV==="true",Z=e=>new Promise(t=>setTimeout(t,e));async function cr(e,t){e.setStep("Welcome"),e.setStatus("Waiting for user input..."),await e.waitForInput("welcome");let o=d=>{let h=e.currentState.data.dependencyLogs||[],v=d.split(`
21
- `).filter(C=>C.trim()!==""),I=[...h,...v].slice(-30);e.updateData("dependencyLogs",I)};e.setStep("Prerequisites"),e.setStatus("Checking system requirements..."),e.updateData("checks",{git:"pending",docker:"pending",mise:"pending"}),await Z(800),e.setStatus("Checking Git...");let r=await He();e.updateData("checks",{...e.currentState.data.checks,git:r}),e.setStatus("Checking Docker...");let n=await Te(),s=n.working?"success":"error";e.updateData("checks",{...e.currentState.data.checks,docker:s}),n.working||e.updateData("dockerError",n.errorMessage),e.setStatus("Checking Mise...");let c=await ve();e.updateData("checks",{...e.currentState.data.checks,mise:c}),c==="missing"&&(e.setStatus("Installing Mise..."),c=await We()?"success":"error",e.updateData("checks",{...e.currentState.data.checks,mise:c}));let a=[];if(r==="error"&&a.push({name:"Git"}),s==="error"&&a.push({name:"Docker",message:n.errorMessage}),a.length>0){let d=[];d.push("Prerequisites failed:");for(let h of a)d.push(` \u2022 ${h.name}: ${h.message||"Not installed or not working"}`);d.push(`
22
- Installation guides:`),r==="error"&&d.push(` \u2022 Git: ${X.git}`),s==="error"&&(n.installed?d.push(" \u2022 Docker: Start Docker Desktop or run 'sudo systemctl start docker'"):d.push(` \u2022 Docker: ${X.docker}`)),e.setError(new Error(d.join(`
23
- `)));return}e.setStatus("Checking Ports...");let p=await Ve([8e3,5432,6379,27017,5672,3e3,8080,8083]),x={},T=p.filter(d=>!d.available);if(T.length>0){let d=T.filter(v=>!v.alternative);if(d.length>0){e.setError(new Error(`Cannot find free alternative ports for: ${d.map(v=>`${v.port} (${v.service})`).join(", ")}. Free these ports and try again.`));return}if(e.updateData("portConflicts",p),await e.waitForInput("port_conflicts")==="abort"){e.setError(new Error("Port conflicts not resolved. Please free the ports and try again."));return}for(let v of p)!v.available&&v.alternative&&(x[v.port]=v.alternative)}e.updateData("portOverrides",x),e.setStatus("Prerequisites check complete!"),await Z(1e3);let y=await Ge(e),S="";if(vo){if(S=z()||"",!S){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 Z(500),e.setStatus("Repository ready!")}else{e.setStep("Repository Setup");let d=y==="selfhost"?se.join(sr.homedir(),"gaia"):se.resolve("gaia"),h=!0;for(S=d;;){if(S=await e.waitForInput("repo_path",{default:d}),se.isAbsolute(S)||(S=se.resolve(S)),re.existsSync(S)){if(!re.statSync(S).isDirectory()){e.setError(new Error(`Path ${S} exists and is not a directory.`)),await Z(2e3),e.setError(null);continue}if(re.existsSync(se.join(S,"apps/api/app/config/settings_validator.py"))){e.updateData("existingRepoPath",S);let k=await e.waitForInput("existing_repo");if(k==="use_existing"){h=!1;break}else if(k==="delete_reclone"){e.setStatus("Removing existing installation...");try{re.rmSync(S,{recursive:!0,force:!0})}catch(P){e.setError(new Error(`Failed to remove directory: ${P.message}
24
- Try removing it manually: rm -rf "${S}"`));return}break}else{if(k==="different_path")continue;e.setError(new Error("Setup cancelled by user."));return}}if(re.readdirSync(S).length>0){e.setError(new Error(`Directory ${S} is not empty and is not a GAIA installation. Please choose another path.`)),await Z(2e3),e.setError(null);continue}}break}if(h){e.setStep("Repository Setup"),e.setStatus("Preparing repository..."),e.updateData("repoProgress",0),e.updateData("repoPhase","");try{await zt(S,"https://github.com/theexperiencecompany/gaia.git",(v,I)=>{e.updateData("repoProgress",v),I?(e.updateData("repoPhase",I),e.setStatus(`${I}...`)):e.setStatus(`Cloning repository to ${S}... ${v}%`)},t),e.setStatus("Repository ready!")}catch(v){e.setError(v);return}}else e.setStatus("Using existing repository!")}if(await Z(1e3),await $e(e,S,y,x),e.currentState.error)return;if(y==="selfhost"){e.setStep("Installing CLI"),e.setStatus("Installing gaia CLI globally...");try{await V("npm",["install","-g","@heygaia/cli"],S,void 0,k=>{let P=k.split(`
25
- `).map(be=>be.replace(/\x1b\[[0-9;]*m/g,"").trim()).filter(be=>be.length>0);if(P.length===0)return;let de=e.currentState.data.cliInstallLogs||[];e.updateData("cliInstallLogs",[...de,...P].slice(-30))}),e.setStatus("Verifying PATH...");let C=await St();C.inPath?e.setStatus("CLI installed! gaia command is ready."):(C.pathAdded,e.setStatus(C.message))}catch{e.setStatus("CLI install failed. Install manually: npm install -g @heygaia/cli")}await Z(500),e.setStep("Project Setup"),e.setStatus("Building and starting all services in Docker..."),e.updateData("dependencyPhase","Building and starting Docker services..."),e.updateData("dependencyProgress",0),e.updateData("dependencyLogs",[]),e.updateData("dependencyComplete",!1);let d=I=>{let C=I.split(`
26
- `).map(P=>P.replace(/\x1b\[[0-9;]*m/g,"").trim()).filter(P=>P.length>0);if(C.length===0)return;let k=e.currentState.data.dependencyLogs||[];e.updateData("dependencyLogs",[...k,...C].slice(-30))},h=!1;try{e.setStatus("Pulling pre-built images from registry..."),await Be(S,"selfhost",I=>e.setStatus(I),x,d,{pull:!0}),h=!0}catch(I){let C=I.message?.split(`
27
- `)[0]??"unknown error";e.setStatus(`Registry pull failed (${C}) \u2014 building images locally (this takes a few minutes)...`)}if(!h)try{await Be(S,"selfhost",I=>e.setStatus(I),x,d,{build:!0})}catch(I){e.setError(new Error(`Failed to start services: ${I.message}`));return}e.updateData("dependencyProgress",100),e.updateData("dependencyComplete",!0);let v=e.currentState.data.envMethod||"manual";Ne({version:Fe,setupComplete:!0,setupMethod:v,repoPath:S,createdAt:new Date().toISOString(),updatedAt:new Date().toISOString()}),e.updateData("setupMode",y),e.setStep("Finished"),e.setStatus("Setup complete! GAIA is running."),await e.waitForInput("exit");return}if(c==="error"){e.setError(new Error(`Developer mode requires Mise but it failed to install.
28
- \u2022 Mise: ${X.mise}`));return}e.setStep("Install Tools"),e.setStatus("Installing toolchain..."),e.updateData("dependencyPhase","Initializing mise..."),e.updateData("dependencyProgress",0),e.updateData("dependencyLogs",[]);try{e.updateData("dependencyPhase","Trusting mise configuration..."),await V("mise",["trust"],S,void 0,o),e.updateData("dependencyProgress",50),e.updateData("dependencyPhase","Installing tools (node, python, uv, nx)..."),await V("mise",["install"],S,d=>{e.updateData("dependencyProgress",50+d*.5)},o),e.updateData("dependencyProgress",100),e.updateData("toolComplete",!0)}catch(d){e.setError(new Error(`Failed to install tools: ${d.message}`));return}await Z(1e3),e.setStep("Project Setup"),e.updateData("dependencyPhase","Setting up project..."),e.updateData("dependencyProgress",0),e.updateData("dependencyComplete",!1),e.updateData("repoPath",S),e.updateData("dependencyLogs",[]);try{e.updateData("dependencyProgress",0),e.updateData("dependencyPhase","Running mise setup (all dependencies)...");let d=Object.keys(x).length>0?xe(x):void 0;await V("mise",["setup"],S,h=>{e.updateData("dependencyProgress",h)},o,d),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 Z(1e3);let m=e.currentState.data.envMethod||"manual";Ne({version:Fe,setupComplete:!0,setupMethod:m,repoPath:S,createdAt:new Date().toISOString(),updatedAt:new Date().toISOString()}),e.setStep("Installing CLI"),e.setStatus("Installing gaia CLI globally...");try{await V("npm",["install","-g","@heygaia/cli"],S,void 0,v=>{let I=v.split(`
29
- `).map(k=>k.replace(/\x1b\[[0-9;]*m/g,"").trim()).filter(k=>k.length>0);if(I.length===0)return;let C=e.currentState.data.cliInstallLogs||[];e.updateData("cliInstallLogs",[...C,...I].slice(-30))}),e.setStatus("Verifying PATH...");let h=await St();h.inPath?e.setStatus("CLI installed! gaia command is ready."):(h.pathAdded,e.setStatus(h.message))}catch{e.setStatus("CLI install failed. Install manually: npm install -g @heygaia/cli")}await Z(500),e.setStep("Finished"),e.setStatus("Setup complete!"),await e.waitForInput("exit")}async function lr(e={}){let t=J(),{unmount:o}=bo(Io.createElement(K,{store:t,command:"init"})),r=()=>{o(),process.exit(130)};process.once("SIGINT",r),process.once("SIGTERM",r);try{await cr(t,e.branch)}catch(n){t.setError(n)}finally{process.off("SIGINT",r),process.off("SIGTERM",r)}t.currentState.error&&await t.waitForInput("exit"),o(),process.exit(t.currentState.error?1:0)}import{render as Co}from"ink";import Eo from"react";var Ue=e=>new Promise(t=>setTimeout(t,e));async function ur(e){e.setStep("Detect Repo"),e.setStatus("Looking for GAIA repository...");let t=z();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 Ue(1e3),e.setStep("Prerequisites"),e.setStatus("Checking system requirements..."),e.updateData("checks",{git:"pending",docker:"pending",mise:"pending"}),await Ue(500);let o=await He();e.updateData("checks",{...e.currentState.data.checks,git:o});let r=await Te(),n=r.working?"success":"error";e.updateData("checks",{...e.currentState.data.checks,docker:n}),r.working||e.updateData("dockerError",r.errorMessage);let s=await ve();e.updateData("checks",{...e.currentState.data.checks,mise:s}),s==="missing"&&(e.setStatus("Installing Mise..."),s=await We()?"success":"error",e.updateData("checks",{...e.currentState.data.checks,mise:s}));let c=[];if(o==="error"&&c.push({name:"Git"}),n==="error"&&c.push({name:"Docker",message:r.errorMessage}),c.length>0){let m=[];m.push("Prerequisites failed:");for(let d of c)m.push(` \u2022 ${d.name}: ${d.message||"Not installed or not working"}`);m.push(`
30
- Installation guides:`),o==="error"&&m.push(` \u2022 Git: ${X.git}`),n==="error"&&(r.installed?m.push(" \u2022 Docker: Start Docker Desktop or run 'sudo systemctl start docker'"):m.push(` \u2022 Docker: ${X.docker}`)),e.setError(new Error(m.join(`
31
- `)));return}e.setStatus("Checking Ports...");let l=await Ve([8e3,5432,6379,27017,5672,3e3,8080,8083]),p={},x=l.filter(m=>!m.available);if(x.length>0){let m=x.filter(h=>!h.alternative);if(m.length>0){e.setError(new Error(`Cannot find free alternative ports for: ${m.map(h=>`${h.port} (${h.service})`).join(", ")}. Free these ports and try again.`));return}if(e.updateData("portConflicts",l),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 l)!h.available&&h.alternative&&(p[h.port]=h.alternative)}e.updateData("portOverrides",p),e.setStatus("Prerequisites check complete!"),await Ue(1e3);let T=await Ge(e);if(await $e(e,t,T,p),e.currentState.error)return;if(T==="selfhost"){let m=e.currentState.data.envMethod||"manual";De({setupComplete:!0,setupMethod:m,repoPath:t}),e.setStep("Finished"),e.setStatus("Setup complete! Run 'gaia start' to build and start all services in Docker."),await e.waitForInput("exit");return}if(s==="error"){e.setError(new Error(`Developer mode requires Mise but it failed to install.
32
- \u2022 Mise: ${X.mise}`));return}e.setStep("Project Setup"),e.updateData("dependencyPhase","Setting up project..."),e.updateData("dependencyProgress",0),e.updateData("dependencyComplete",!1),e.updateData("dependencyLogs",[]);let y=m=>{let d=e.currentState.data.dependencyLogs||[],h=m.split(`
33
- `).filter(I=>I.trim()!==""),v=[...d,...h].slice(-30);e.updateData("dependencyLogs",v)};try{e.updateData("dependencyPhase","Trusting mise configuration..."),await V("mise",["trust"],t,void 0,y),e.updateData("dependencyProgress",20),e.updateData("dependencyPhase","Installing tools..."),await V("mise",["install"],t,d=>{e.updateData("dependencyProgress",20+d*.3)},y),e.updateData("dependencyPhase","Running mise setup...");let m=Object.keys(p).length>0?xe(p):void 0;await V("mise",["setup"],t,d=>{e.updateData("dependencyProgress",50+d*.5)},y,m),e.updateData("dependencyProgress",100),e.updateData("dependencyPhase","Setup complete!"),e.updateData("dependencyComplete",!0)}catch(m){e.setError(new Error(`Failed to setup project: ${m.message}`));return}await Ue(1e3);let S=e.currentState.data.envMethod||"manual";De({setupComplete:!0,setupMethod:S,repoPath:t}),e.setStep("Finished"),e.setStatus("Setup complete!"),await e.waitForInput("exit")}async function pr(){let e=J(),{unmount:t}=Co(Eo.createElement(K,{store:e,command:"setup"})),o=()=>{t(),process.exit(130)};process.once("SIGINT",o),process.once("SIGTERM",o);try{await ur(e)}catch(r){e.setError(r)}finally{process.off("SIGINT",o),process.off("SIGTERM",o)}e.currentState.error&&await e.waitForInput("exit"),t(),process.exit(e.currentState.error?1:0)}import{render as wo}from"ink";import Po from"react";async function dr(e,t){e.setStep("Starting"),e.setStatus("Locating GAIA repository...");let o=z();if(!o){e.setError(new Error("Could not find GAIA repository. Run from within a cloned gaia repo."));return}e.updateData("repoPath",o);let r=await xt(o);if(!r){e.setError(new Error("No .env file found. Run 'gaia init' for fresh setup, or 'gaia setup' to configure an existing repo."));return}if(r==="selfhost"){e.setStatus("Checking Docker...");let l=await Te();if(!l.working){e.setError(new Error(l.errorMessage||`Docker is not running. Please start Docker and try again.
34
- ${X.docker}`));return}}else{e.setStatus("Checking Mise...");let l=await ve();if(l==="missing"||l==="error"){e.setError(new Error(`Developer mode requires Mise but it is not installed.
35
- Install: ${X.mise}`));return}}let n=ye(o),s=n[3e3]??3e3,c=n[8e3]??8e3;e.updateData("setupMode",r),e.updateData("webPort",s),e.updateData("apiPort",c),e.updateData("dockerLogs",[]),e.setStatus(`Starting GAIA in ${r} mode...`);let a=l=>{let p=l.split(`
36
- `).map(T=>T.replace(/\x1b\[[0-9;]*m/g,"").trim()).filter(T=>T.length>0);if(p.length===0)return;let x=e.currentState.data.dockerLogs||[];e.updateData("dockerLogs",[...x,...p].slice(-30))};try{await Be(o,r,l=>{e.setStatus(l)},n,a,t),e.setStep("Running"),e.setStatus("GAIA is running!"),e.updateData("started",!0)}catch(l){e.setError(new Error(`Failed to start services: ${l.message}`));return}await e.waitForInput("exit")}async function mr(e){let t=J(),{unmount:o}=wo(Po.createElement(K,{store:t,command:"start"})),r=()=>{o(),process.exit(130)};process.once("SIGINT",r),process.once("SIGTERM",r),await new Promise(n=>setTimeout(n,50));try{await dr(t,e)}catch(n){t.setError(n)}finally{process.off("SIGINT",r),process.off("SIGTERM",r)}t.currentState.error&&await t.waitForInput("exit"),o(),process.exit(t.currentState.error?1:0)}import{render as Bo}from"ink";import _o from"react";import{execa as Tt}from"execa";var yt=["gaia-backend","gaia-web","chromadb","postgres","redis","mongo","rabbitmq","arq_worker"];async function fr(){try{let{stdout:e}=await Tt("docker",["inspect","--format","{{.Name}}|{{.State.Status}}|{{if .State.Health}}{{.State.Health.Status}}{{else}}none{{end}}",...yt]),t=new Map;for(let o of e.trim().split(`
37
- `)){if(!o)continue;let[r,n,s]=o.split("|"),c=r?.replace(/^\//,"")??"";t.set(c,{name:c,status:n==="running"?"running":"stopped",health:s!=="none"?s:void 0})}return yt.map(o=>t.get(o)??{name:o,status:"not_found"})}catch{let e=yt.map(async t=>{try{let{stdout:o}=await Tt("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 gr(){try{return await Tt("docker",["info"]),!0}catch{return!1}}var Ro=[{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 hr(e){let o=Ro.map(r=>({...r,port:e?.[r.port]??r.port})).map(r=>r.type==="http"?Do(r.name,r.port,r.path):ko(r.name,r.port));return Promise.all(o)}async function Do(e,t,o){let r=Date.now();try{let n=await fetch(`http://localhost:${t}${o}`,{signal:AbortSignal.timeout(5e3)}),s=Date.now()-r;return{name:e,port:t,status:n.ok?"up":"down",latency:s,details:n.ok?`HTTP ${n.status}`:`HTTP ${n.status} (error)`}}catch{return{name:e,port:t,status:"down",details:"Connection failed"}}}async function ko(e,t){let o=await import("node:net"),r=Date.now();return new Promise(n=>{let s=new o.Socket;s.setTimeout(3e3),s.on("connect",()=>{let c=Date.now()-r;s.destroy(),n({name:e,port:t,status:"up",latency:c})}),s.on("timeout",()=>{s.destroy(),n({name:e,port:t,status:"down"})}),s.on("error",()=>{s.destroy(),n({name:e,port:t,status:"down"})}),s.connect(t,"localhost")})}async function Sr(){return await gr()?{running:!0,containers:await fr()}:{running:!1,containers:[]}}async function Ao(e){e.setStep("Checking"),e.setStatus("Checking service health..."),e.updateData("refreshable",!1);let t=z(),o=t?ye(t):void 0,[r,n]=await Promise.all([hr(o),Sr()]);e.updateData("services",r),e.updateData("docker",n);let s=r.filter(a=>a.status==="up").length,c=r.length;e.setStep("Results"),e.setStatus(`${s}/${c} services running`),e.updateData("refreshable",!0)}async function xr(e){for(;await Ao(e),await e.waitForInput("exit_or_refresh")==="refresh";);}async function yr(){let e=J(),{unmount:t}=Bo(_o.createElement(K,{store:e,command:"status"}));await new Promise(o=>setTimeout(o,50));try{await xr(e)}catch(o){e.setError(o)}e.currentState.error&&await e.waitForInput("exit"),t(),process.exit(e.currentState.error?1:0)}import{render as Lo}from"ink";import Oo from"react";async function Tr(e){e.setStep("Stopping"),e.setStatus("Locating GAIA repository...");let t=z();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=ye(t);try{await ar(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 vr(){let e=J(),{unmount:t}=Lo(Oo.createElement(K,{store:e,command:"stop"})),o=()=>{t(),process.exit(130)};process.once("SIGINT",o),process.once("SIGTERM",o),await new Promise(r=>setTimeout(r,50));try{await Tr(e)}catch(r){e.setError(r)}finally{process.off("SIGINT",o),process.off("SIGTERM",o)}e.currentState.error&&await e.waitForInput("exit"),t(),process.exit(e.currentState.error?1:0)}var ce=new Mo;ce.name("gaia").description("CLI tool for setting up and managing GAIA").version("0.1.0");ce.command("init").description("Full setup from scratch (clone, configure, start)").option("--branch <branch>","Git branch to clone").action(async e=>{await lr({branch:e.branch})});ce.command("setup").description("Configure an existing GAIA repository").action(async()=>{await pr()});ce.command("status").description("Check health of all GAIA services").action(async()=>{await yr()});ce.command("start").description("Start GAIA services").option("-b, --build","Rebuild Docker images before starting").option("--pull","Pull latest base images before starting").action(async e=>{await mr({build:e.build,pull:e.pull})});ce.command("stop").description("Stop all GAIA services").action(async()=>{await vr()});process.argv.slice(2).length||(ce.outputHelp(),process.exit(0));ce.parse();
38
+ Original error: ${v.message}`):new Error(`Failed to parse settings: ${v.message}`)}let i=new Set,a=[],s=new Set;for(let v of n)if(v.alternativeGroup&&!s.has(v.name)){let y=n.find(w=>w.name===v.alternativeGroup);y&&(a.push([v,y]),i.add(v.name),i.add(y.name),s.add(v.name),s.add(y.name))}let c=n.filter(v=>v.variables.length===1&&!i.has(v.name)),p=n.filter(v=>v.variables.length>1&&!i.has(v.name));for(let v of a){e.updateData("alternativeGroups",v),e.setStatus("Choose an AI provider...");let y=await e.waitForInput("env_alternatives");for(let[w,b]of Object.entries(y.values))b&&(r[w]=b)}let f=At(),m=[...c.flatMap(v=>v.variables).filter(v=>!f.includes(v.name))].sort((v,y)=>v.required&&!y.required?-1:!v.required&&y.required?1:0);e.updateData("envVarTotal",m.length);for(let v=0;v<m.length;v++){let y=m[v];if(!y)continue;e.updateData("currentEnvVar",y),e.updateData("envVarIndex",v),e.setStatus(`Configuring ${y.name}...`);let w=await e.waitForInput("env_var",{varName:y.name});(w||y.required||y.defaultValue)&&(r[y.name]=w||y.defaultValue||"")}let S=[...p].filter(v=>!v.variables.every(y=>f.includes(y.name))).sort((v,y)=>{let w=v.variables.some(E=>E.required),b=y.variables.some(E=>E.required);return w&&!b?-1:!w&&b?1:0});e.updateData("envGroupTotal",S.length);for(let v=0;v<S.length;v++){let y=S[v];if(!y)continue;e.updateData("currentEnvGroup",y),e.updateData("envGroupIndex",v),e.setStatus(`Configuring ${y.name}...`);let w=await e.waitForInput("env_group",{groupName:y.name});for(let[b,E]of Object.entries(w)){let P=y.variables.find(Z=>Z.name===b);(E||P?.required||P?.defaultValue)&&(r[b]=E||P?.defaultValue||"")}}}async function bi(e,t,r,o,n){e.setStatus("Writing API environment file...");try{let a=xo.join(t,"apps","api");Ur(a,r),e.setStatus("API environment variables configured!")}catch(a){throw new Error(`Failed to write API .env file: ${a.message}`)}e.setStatus("Writing web environment file...");try{Hr(t,o,n),e.setStatus("Web environment variables configured!")}catch(a){throw new Error(`Failed to write web .env file: ${a.message}`)}let i=n&&Object.keys(n).length>0;if(i||o==="selfhost"){e.setStatus("Writing Docker Compose environment...");try{i&&Yr(t),Vr(t,n??{},o),e.setStatus("Docker Compose environment configured!")}catch(a){throw new Error(`Failed to write Docker Compose .env: ${a.message}`)}}}import{execa as oe}from"execa";var pe={git:"https://git-scm.com/downloads",docker:"https://docs.docker.com/get-docker/",mise:"https://mise.jdx.dev/getting-started.html"},Ti={8e3:"API Server",5432:"PostgreSQL",6379:"Redis",27017:"MongoDB",5672:"RabbitMQ",3e3:"Web Frontend",8080:"ChromaDB",8083:"Mongo Express"};async function wo(){try{return await oe("git",["--version"]),"success"}catch{return"error"}}async function ut(){let e=!1,t=!1,r;try{await oe("docker",["--version"]),e=!0}catch{return{name:"Docker",installUrl:pe.docker,installed:!1,working:!1,errorMessage:"Docker is not installed"}}try{await oe("docker",["info"],{timeout:5e3}),t=!0}catch{r="Docker is installed but the daemon is not running. Please start Docker Desktop or the Docker daemon."}return{name:"Docker",installUrl:pe.docker,installed:e,working:t,errorMessage:r}}async function bo(){try{return await oe("mise",["--version"]),"success"}catch{return"missing"}}async function To(){if((await import("node:os")).platform()==="win32")try{return await oe("powershell",["-Command","irm https://mise.jdx.dev/install.ps1 | iex"]),!0}catch{return!1}try{return await oe("sh",["-c","curl https://mise.jdx.dev/install.sh | sh"]),!0}catch{return!1}}async function Co(e){let t=await import("node:net"),r=[],o=n=>new Promise(i=>{let a=t.createServer();a.once("error",()=>i(!1)),a.once("listening",()=>{a.close(()=>i(!0))}),a.listen(n)});for(let n of e){let i=Ti[n]||`Port ${n}`;if(await o(n))r.push({port:n,service:i,available:!0});else{let s=await Ci(n),c=await Ii(n+1,n+100,o);r.push({port:n,service:i,available:!1,usedBy:s,alternative:c||void 0})}}return r}async function Ci(e){if((await import("node:os")).platform()==="win32"){try{let{stdout:o}=await oe("netstat",["-ano","-p","TCP"]),n=o.trim().split(`
39
+ `);for(let i of n)if(i.includes(`:${e}`)&&i.includes("LISTENING")){let a=i.trim().split(/\s+/),s=a[a.length-1];if(s)try{let{stdout:c}=await oe("tasklist",["/FI",`PID eq ${s}`,"/FO","CSV","/NH"]);return c.trim().split(",")[0]?.replace(/"/g,"")||`PID ${s}`}catch{return`PID ${s}`}}}catch{}return}try{let{stdout:o}=await oe("lsof",["-i",`:${e}`,"-sTCP:LISTEN","-P","-n"]),n=o.trim().split(`
40
+ `);if(n.length>1)return n[1]?.split(/\s+/)?.[0]||void 0}catch{}}async function Ii(e,t,r){for(let o=e;o<=t;o++)if(await r(o))return o;return null}var X=e=>new Promise(t=>setTimeout(t,e)),dt=(e,t="dependencyLogs")=>r=>{let o=e.currentState.data[t]||[],n=r.split(`
41
+ `).filter(i=>i.trim()!=="");e.updateData(t,[...o,...n].slice(-30))};async function mt(e){e.updateData("checks",{git:"pending",docker:"pending"}),await X(500);let t=await wo();e.updateData("checks",{...e.currentState.data.checks,git:t});let r=await ut(),o=r.working?"success":"error";e.updateData("checks",{...e.currentState.data.checks,docker:o}),r.working||e.updateData("dockerError",r.errorMessage);let n=[];if(t==="error"&&n.push({name:"Git"}),o==="error"&&n.push({name:"Docker",message:r.errorMessage}),n.length>0){let i=["Prerequisites failed:"];for(let a of n)i.push(` \u2022 ${a.name}: ${a.message||"Not installed or not working"}`);return i.push(`
42
+ Installation guides:`),t==="error"&&i.push(` \u2022 Git: ${pe.git}`),o==="error"&&(r.installed?i.push(" \u2022 Docker: Start Docker Desktop or run 'sudo systemctl start docker'"):i.push(` \u2022 Docker: ${pe.docker}`)),e.setError(new Error(i.join(`
43
+ `))),null}return{gitStatus:t,dockerStatus:o,dockerInfo:r}}async function ft(e){e.updateData("checks",{...e.currentState.data.checks,mise:"pending"});let t=await bo();return e.updateData("checks",{...e.currentState.data.checks,mise:t}),t==="missing"&&(e.setStatus("Installing Mise..."),t=await To()?"success":"error",e.updateData("checks",{...e.currentState.data.checks,mise:t})),t==="error"?(e.setError(new Error(`Developer mode requires Mise but it failed to install.
44
+ \u2022 Mise: ${pe.mise}`)),null):"success"}async function gt(e){e.setStatus("Checking Ports...");let r=await Co([8e3,5432,6379,27017,5672,3e3,8080,8083]),o={},n=r.filter(i=>!i.available);if(n.length>0){let i=n.filter(s=>!s.alternative);if(i.length>0)return e.setError(new Error(`Cannot find free alternative ports for: ${i.map(s=>`${s.port} (${s.service})`).join(", ")}. Free these ports and try again.`)),null;if(e.updateData("portConflicts",r),await e.waitForInput("port_conflicts")==="abort")return e.setError(new Error("Port conflicts not resolved. Please free the ports and try again.")),null;for(let s of r)!s.available&&s.alternative&&(o[s.port]=s.alternative)}return e.updateData("portOverrides",o),e.setStatus("Prerequisites check complete!"),await X(1e3),o}async function Io(e,t,r,o){e.setStep("Project Setup"),e.updateData("dependencyPhase","Setting up project..."),e.updateData("dependencyProgress",0),e.updateData("dependencyComplete",!1),e.updateData("dependencyLogs",[]);try{e.updateData("dependencyPhase","Trusting mise configuration..."),await U("mise",["trust"],t,void 0,o),e.updateData("dependencyProgress",20),e.updateData("dependencyPhase","Installing tools..."),await U("mise",["install"],t,i=>{e.updateData("dependencyProgress",20+i*.3)},o),e.updateData("dependencyPhase","Running mise setup...");let n=Object.keys(r).length>0?se(r):void 0;return await U("mise",["setup"],t,i=>{e.updateData("dependencyProgress",50+i*.5)},o,n),e.updateData("dependencyProgress",100),e.updateData("dependencyPhase","Setup complete!"),e.updateData("dependencyComplete",!0),!0}catch(n){return e.setError(new Error(`Failed to setup project: ${n.message}`)),!1}}import{execa as Pi}from"execa";import ht from"fs";import Ri from"simple-git";async function Eo(e,t,r,o){if(ht.existsSync(e)){let n=`${e}/.git`;if(!ht.existsSync(n))throw new Error(`Directory ${e} exists but is not a git repository`);await Ri().cwd(e).pull(),r(100,"Already exists, pulled latest")}else try{let n=["clone","--progress"];o&&n.push("--branch",o),n.push(t,e);let i=Pi("git",n);i.stderr?.on("data",a=>{let s=a.toString();s.includes("Counting objects")?r(5,"Counting objects"):s.includes("Compressing objects")&&r(10,"Compressing objects");let c=s.match(/Receiving objects:\s+(\d+)%\s+\((\d+)\/(\d+)\)/);if(c?.[1]){let f=Math.min(100,parseInt(c[1],10)),d=c[2],m=c[3];r(10+Math.floor(f*.5),`Receiving objects: ${d}/${m}`)}let p=s.match(/Resolving deltas:\s+(\d+)%\s+\((\d+)\/(\d+)\)/);if(p?.[1]){let f=Math.min(100,parseInt(p[1],10)),d=p[2],m=p[3];r(60+Math.floor(f*.4),`Resolving deltas: ${d}/${m}`)}}),await i,r(100,"Clone complete")}catch(n){throw ht.existsSync(e)&&ht.rmSync(e,{recursive:!0,force:!0}),n}}var ki=process.env.GAIA_CLI_DEV==="true",_i=new RegExp("\x1B\\[[0-9;]*m","g");async function Ro(e,t){e.setStep("Welcome"),e.setStatus("Waiting for user input..."),await e.waitForInput("welcome");let r=dt(e);if(e.setStep("Prerequisites"),e.setStatus("Checking system requirements..."),!await mt(e))return;let o=await gt(e);if(o===null)return;let n=await lt(e);if(n==="developer"&&!await ft(e))return;let i="";if(ki){if(i=$()||"",!i){e.setError(new Error("DEV_MODE: Could not find workspace root. Run from within the gaia repo."));return}e.setStep("Repository Setup"),e.setStatus("[DEV MODE] Using current workspace..."),await X(500),e.setStatus("Repository ready!")}else{e.setStep("Repository Setup");let s=n==="selfhost"?ue.join(Po.homedir(),"gaia"):ue.resolve("gaia"),c=!0;for(i=s;;){if(i=await e.waitForInput("repo_path",{default:s}),ue.isAbsolute(i)||(i=ue.resolve(i)),ne.existsSync(i)){if(!ne.statSync(i).isDirectory()){e.setError(new Error(`Path ${i} exists and is not a directory.`)),await X(2e3),e.setError(null);continue}if(ne.existsSync(ue.join(i,"apps/api/app/config/settings_validator.py"))){e.updateData("existingRepoPath",i);let m=await e.waitForInput("existing_repo");if(m==="use_existing"){c=!1;break}else if(m==="delete_reclone"){e.setStatus("Removing existing installation...");try{ne.rmSync(i,{recursive:!0,force:!0})}catch(S){e.setError(new Error(`Failed to remove directory: ${S.message}
45
+ Try removing it manually: rm -rf "${i}"`));return}break}else{if(m==="different_path")continue;e.setError(new Error("Setup cancelled by user."));return}}if(ne.readdirSync(i).length>0){e.setError(new Error(`Directory ${i} is not empty and is not a GAIA installation. Please choose another path.`)),await X(2e3),e.setError(null);continue}}break}if(c){e.setStep("Repository Setup"),e.setStatus("Preparing repository..."),e.updateData("repoProgress",0),e.updateData("repoPhase","");try{await Eo(i,"https://github.com/theexperiencecompany/gaia.git",(p,f)=>{e.updateData("repoProgress",p),f?(e.updateData("repoPhase",f),e.setStatus(`${f}...`)):e.setStatus(`Cloning repository to ${i}... ${p}%`)},t),e.setStatus("Repository ready!")}catch(p){e.setError(p);return}}else e.setStatus("Using existing repository!")}if(await X(1e3),await pt(e,i,n,o),e.currentState.error)return;if(n==="selfhost"){e.setStep("Project Setup"),e.setStatus("Building and starting all services in Docker..."),e.updateData("dependencyPhase","Building and starting Docker services..."),e.updateData("dependencyProgress",0),e.updateData("dependencyLogs",[]),e.updateData("dependencyComplete",!1);let s=f=>{let d=f.split(`
46
+ `).map(S=>S.replace(_i,"").trim()).filter(S=>S.length>0);if(d.length===0)return;let m=e.currentState.data.dependencyLogs||[];e.updateData("dependencyLogs",[...m,...d].slice(-30))},c=!1;try{e.setStatus("Pulling pre-built images from registry..."),await Oe(i,"selfhost",f=>e.setStatus(f),o,s,{pull:!0}),c=!0}catch(f){let d=f.message?.split(`
47
+ `)[0]??"unknown error";e.setStatus(`Registry pull failed (${d}) \u2014 building images locally (this takes a few minutes)...`)}if(!c)try{await Oe(i,"selfhost",f=>e.setStatus(f),o,s,{build:!0})}catch(f){e.setError(new Error(`Failed to start services: ${f.message}`));return}e.updateData("dependencyProgress",100),e.updateData("dependencyComplete",!0);let p=e.currentState.data.envMethod||"manual";ze({version:ee,setupComplete:!0,setupMethod:p,repoPath:i,createdAt:new Date().toISOString(),updatedAt:new Date().toISOString()}),e.updateData("setupMode",n),e.setStep("Finished"),e.setStatus("Setup complete! GAIA is running."),await e.waitForInput("exit");return}e.setStep("Install Tools"),e.setStatus("Installing toolchain..."),e.updateData("dependencyPhase","Initializing mise..."),e.updateData("dependencyProgress",0),e.updateData("dependencyLogs",[]);try{e.updateData("dependencyPhase","Trusting mise configuration..."),await U("mise",["trust"],i,void 0,r),e.updateData("dependencyProgress",50),e.updateData("dependencyPhase","Installing tools (node, python, uv, nx)..."),await U("mise",["install"],i,s=>{e.updateData("dependencyProgress",50+s*.5)},r),e.updateData("dependencyProgress",100),e.updateData("toolComplete",!0)}catch(s){e.setError(new Error(`Failed to install tools: ${s.message}`));return}await X(1e3),e.setStep("Project Setup"),e.updateData("dependencyPhase","Setting up project..."),e.updateData("dependencyProgress",0),e.updateData("dependencyComplete",!1),e.updateData("repoPath",i),e.updateData("dependencyLogs",[]);try{e.updateData("dependencyProgress",0),e.updateData("dependencyPhase","Running mise setup (all dependencies)...");let s=Object.keys(o).length>0?se(o):void 0;await U("mise",["setup"],i,c=>{e.updateData("dependencyProgress",c)},r,s),e.updateData("dependencyProgress",100),e.updateData("dependencyPhase","Setup complete!"),e.updateData("dependencyComplete",!0)}catch(s){e.setError(new Error(`Failed to setup project: ${s.message}`));return}await X(1e3);let a=e.currentState.data.envMethod||"manual";ze({version:ee,setupComplete:!0,setupMethod:a,repoPath:i,createdAt:new Date().toISOString(),updatedAt:new Date().toISOString()}),e.setStep("Finished"),e.setStatus("Setup complete! Run 'gaia dev' to start development mode."),await e.waitForInput("exit")}async function Do(e={}){await z({command:"init",whenNonInteractive:"fail",runFlow:t=>Ro(t,e.branch)})}async function ko(e){e.setStep("Detect Repo"),e.setStatus("Looking for GAIA repository...");let t=$();if(!t){e.setError(new Error("Could not find GAIA repository. Run this command from within a cloned gaia repo, or use 'gaia init' to set up from scratch."));return}if(e.updateData("repoPath",t),e.setStatus(`Found repository at ${t}`),await X(1e3),e.setStep("Prerequisites"),e.setStatus("Checking system requirements..."),!await mt(e))return;let r=await gt(e);if(r===null)return;let o=await lt(e);if(o==="developer"&&!await ft(e)||(await pt(e,t,o,r),e.currentState.error))return;if(o==="selfhost"){let s=e.currentState.data.envMethod||"manual";Ae({setupComplete:!0,setupMethod:s,repoPath:t}),e.updateData("setupMode",o),e.setStep("Finished"),e.setStatus("Setup complete! Run 'gaia start' to build and start all services in Docker."),await e.waitForInput("exit");return}let n=dt(e);if(!await Io(e,t,r,n))return;await X(1e3);let a=e.currentState.data.envMethod||"manual";Ae({setupComplete:!0,setupMethod:a,repoPath:t}),e.updateData("setupMode",o),e.setStep("Finished"),e.setStatus("Setup complete! Run 'gaia dev' to start development mode."),await e.waitForInput("exit")}async function _o(){await z({command:"setup",whenNonInteractive:"fail",runFlow:ko})}var Ai=new RegExp("\x1B\\[[0-9;]*m","g");async function Ao(e,t){e.setStep("Starting"),e.setStatus("Locating GAIA repository...");let r=$();if(!r){e.setError(new Error("Could not find GAIA repository. Run from within a cloned gaia repo."));return}e.updateData("repoPath",r);let o=await ge(r);if(!o){e.setError(new Error("No .env file found. Run 'gaia init' for fresh setup, or 'gaia setup' to configure an existing repo."));return}if(o==="developer"){e.setError(new Error("Developer mode runs in foreground. Use 'gaia dev' or 'gaia dev full' instead of 'gaia start'."));return}if(o==="selfhost"){e.setStatus("Checking Docker...");let c=await ut();if(!c.working){e.setError(new Error(c.errorMessage||`Docker is not running. Please start Docker and try again.
48
+ ${pe.docker}`));return}}let n=ae(r),i=n[3e3]??3e3,a=n[8e3]??8e3;e.updateData("setupMode",o),e.updateData("webPort",i),e.updateData("apiPort",a),e.updateData("dockerLogs",[]),e.setStatus(`Starting GAIA in ${o} mode...`);let s=c=>{let p=c.split(`
49
+ `).map(d=>d.replace(Ai,"").trim()).filter(d=>d.length>0);if(p.length===0)return;let f=e.currentState.data.dockerLogs||[];e.updateData("dockerLogs",[...f,...p].slice(-30))};try{await Oe(r,o,c=>{e.setStatus(c)},n,s,t),e.setStep("Running"),e.setStatus("GAIA is running!"),e.updateData("started",!0)}catch(c){e.setError(new Error(`Failed to start services: ${c.message}`));return}await e.waitForInput("exit")}async function Oo(e){await z({command:"start",whenNonInteractive:"plain",autoResolve:[["exit"]],runFlow:t=>Ao(t,e)})}import{execa as Qt}from"execa";var Kt=["gaia-backend","gaia-web","chromadb","postgres","redis","mongo","rabbitmq","arq_worker"];async function Mo(){try{let{stdout:e}=await Qt("docker",["inspect","--format","{{.Name}}|{{.State.Status}}|{{if .State.Health}}{{.State.Health.Status}}{{else}}none{{end}}",...Kt]),t=new Map;for(let r of e.trim().split(`
50
+ `)){if(!r)continue;let[o,n,i]=r.split("|"),a=o?.replace(/^\//,"")??"";t.set(a,{name:a,status:n==="running"?"running":"stopped",health:i!=="none"?i:void 0})}return Kt.map(r=>t.get(r)??{name:r,status:"not_found"})}catch{let e=Kt.map(async t=>{try{let{stdout:r}=await Qt("docker",["inspect","--format","{{.State.Status}}|{{if .State.Health}}{{.State.Health.Status}}{{else}}none{{end}}",t]),[o,n]=r.trim().split("|");return{name:t,status:o==="running"?"running":"stopped",health:n!=="none"?n:void 0}}catch{return{name:t,status:"not_found"}}});return Promise.all(e)}}async function No(){try{return await Qt("docker",["info"]),!0}catch{return!1}}var Oi=[{name:"API",port:8e3,type:"http",path:"/health"},{name:"Web",port:3e3,type:"http",path:"/"},{name:"PostgreSQL",port:5432,type:"tcp"},{name:"Redis",port:6379,type:"tcp"},{name:"MongoDB",port:27017,type:"tcp"},{name:"RabbitMQ",port:5672,type:"tcp"},{name:"ChromaDB",port:8080,type:"tcp"}];async function Lo(e){let r=Oi.map(o=>({...o,port:e?.[o.port]??o.port})).map(o=>o.type==="http"?Mi(o.name,o.port,o.path):Ni(o.name,o.port));return Promise.all(r)}async function Mi(e,t,r){let o=Date.now();try{let n=await fetch(`http://localhost:${t}${r}`,{signal:AbortSignal.timeout(5e3)}),i=Date.now()-o;return{name:e,port:t,status:n.ok?"up":"down",latency:i,details:n.ok?`HTTP ${n.status}`:`HTTP ${n.status} (error)`}}catch{return{name:e,port:t,status:"down",details:"Connection failed"}}}async function Ni(e,t){let r=await import("node:net"),o=Date.now();return new Promise(n=>{let i=new r.Socket;i.setTimeout(3e3),i.on("connect",()=>{let a=Date.now()-o;i.destroy(),n({name:e,port:t,status:"up",latency:a})}),i.on("timeout",()=>{i.destroy(),n({name:e,port:t,status:"down"})}),i.on("error",()=>{i.destroy(),n({name:e,port:t,status:"down"})}),i.connect(t,"localhost")})}async function Bo(){return await No()?{running:!0,containers:await Mo()}:{running:!1,containers:[]}}async function Li(e){e.setStep("Checking"),e.setStatus("Checking service health..."),e.updateData("refreshable",!1);let t=$(),r=t?ae(t):void 0,[o,n]=await Promise.all([Lo(r),Bo()]);e.updateData("services",o),e.updateData("docker",n);let i=o.filter(s=>s.status==="up").length,a=o.length;e.setStep("Results"),e.setStatus(`${i}/${a} services running`),e.updateData("refreshable",!0)}async function Fo(e){for(;await Li(e),await e.waitForInput("exit_or_refresh")==="refresh";);}async function $o(){await z({command:"status",whenNonInteractive:"plain",autoResolve:[["exit_or_refresh","exit"]],runFlow:Fo,onPlainComplete:Bi})}function Bi(e){let t=e.currentState.data.services??[],r=e.currentState.data.docker;$i(t),Gi(r)}function Fi(e){return e==="up"?"UP":e==="down"?"DOWN":"UNKNOWN"}function $i(e){if(e.length!==0){console.log(`
51
+ Services:`);for(let t of e){let r=Fi(t.status),o=t.latency===void 0?"--":`${t.latency}ms`,n=t.name.padEnd(12);console.log(` ${n} :${t.port} ${r} ${o}`)}}}function Gi(e){if(e){console.log(`
52
+ Docker: ${e.running?"running":"not running"}`);for(let t of e.containers??[]){let r=t.health?` (${t.health})`:"",o=t.name.padEnd(14);console.log(` ${o} ${t.status}${r}`)}}}async function Go(e,t){e.setStep("Stopping"),e.setStatus("Locating GAIA repository...");let r=$();if(!r){e.setError(new Error("Could not find GAIA repository. Run from within a cloned gaia repo."));return}e.updateData("repoPath",r),e.updateData("stopMode",t?.forcePorts?"force-ports":"safe");let o=ae(r);try{await Kr(r,n=>{e.setStatus(n)},o,t),e.setStep("Stopped"),e.setStatus(t?.forcePorts?"All services stopped (force-port mode).":"All services stopped (safe mode)."),e.updateData("stopped",!0)}catch(n){e.setError(new Error(`Failed to stop services: ${n.message}`));return}await e.waitForInput("exit")}async function jo(e){await z({command:"stop",whenNonInteractive:"plain",autoResolve:[["exit"]],runFlow:t=>Go(t,e)})}import*as vt from"fs";import*as St from"path";function ji(e){let t=St.join(e,".env");return vt.existsSync(t)?["--env-file",".env"]:[]}async function qo(){let e=$();if(!e)throw new Error("Could not find GAIA repository. Run from within a cloned gaia repo.");let t=await ge(e);if(!t)throw new Error("No .env file found. Run 'gaia init' for fresh setup, or 'gaia setup' to configure an existing repo.");let r=St.join(e,"infra","docker"),o=ji(r),n=ae(e),i=Object.keys(n).length>0?se(n):void 0;if(t==="selfhost"){await Te("docker",["compose","-f","docker-compose.selfhost.yml",...o,"logs","-f","--tail","200"],r,i);return}let a=["compose",...o,"logs","-f","--tail","200"],s=St.join(e,Xr),c=Mt(e),p=typeof c=="number"&&Ze(c);if(vt.existsSync(s)&&p){console.log("Streaming app and infrastructure logs..."),process.platform==="win32"?await Qe([{cmd:"powershell",args:["-Command",`Get-Content -Path '${s.replace(/'/g,"''")}' -Wait -Tail 200`],cwd:e},{cmd:"docker",args:a,cwd:r,env:i}]):await Qe([{cmd:"tail",args:["-n","200","-f",s],cwd:e},{cmd:"docker",args:a,cwd:r,env:i}]);return}vt.existsSync(s)&&!p?(console.log("Detected stale developer app logs from a previous run. Streaming Docker logs only."),await Te("docker",a,r,i)):(console.log("No active developer process detected. Streaming Docker service logs. Run `gaia dev` in another terminal for live Nx app logs."),await Te("docker",a,r,i))}var Q=new qi;Q.name("gaia").description("CLI tool for setting up and managing GAIA").version(ee);Q.addCommand(te);Q.command("init").description(ie.init).option("--branch <branch>","Git branch to clone").action(async e=>{await Do({branch:e.branch})});Q.command("setup").description(ie.setup).action(async()=>{await _o()});Q.command("status").description(ie.status).action(async()=>{await $o()});Q.command("start").description(ie.start).option("-b, --build","Rebuild Docker images before starting").option("--pull","Pull latest base images before starting").action(async e=>{await Oo({build:e.build,pull:e.pull})});Q.command("dev [profile]").description(ie.dev).action(async e=>{try{await zr(e)}catch(t){console.error(t instanceof Error?t.message:String(t)),process.exit(1)}});Q.command("logs").description(ie.logs).action(async()=>{try{await qo()}catch(e){console.error(e instanceof Error?e.message:String(e)),process.exit(1)}});Q.command("stop").description(ie.stop).option("--force-ports","Aggressively stop processes listening on API/Web ports (may affect non-GAIA processes)").action(async e=>{await jo({forcePorts:e.forcePorts})});process.argv.slice(2).length||(Q.outputHelp(),process.exit(0));Q.parse();
package/package.json CHANGED
@@ -1,67 +1,70 @@
1
1
  {
2
2
  "name": "@heygaia/cli",
3
- "version": "0.1.14",
4
3
  "description": "CLI tool for setting up and managing GAIA",
4
+ "version": "0.5.0",
5
5
  "type": "module",
6
- "bin": {
7
- "gaia": "./dist/index.js"
8
- },
9
6
  "files": [
10
7
  "dist",
11
8
  "README.md"
12
9
  ],
13
10
  "scripts": {
14
- "dev": "tsx watch src/index.ts",
15
11
  "build": "esbuild src/index.ts --bundle --platform=node --target=node18 --format=esm --packages=external --outfile=dist/index.js --minify && chmod +x dist/index.js",
16
- "start": "NODE_ENV=production node dist/index.js",
17
- "type-check": "tsc --noEmit",
18
12
  "check": "biome check src",
13
+ "dev": "tsx watch src/index.ts",
19
14
  "fix": "biome check --write src",
15
+ "format": "biome format --write src",
20
16
  "lint": "pnpm run check",
21
17
  "lint:fix": "pnpm run fix",
22
- "format": "biome format --write src",
23
- "prepublishOnly": "pnpm run build"
24
- },
25
- "engines": {
26
- "node": ">=18"
27
- },
28
- "repository": {
29
- "type": "git",
30
- "url": "https://github.com/heygaia/gaia.git",
31
- "directory": "packages/cli"
32
- },
33
- "publishConfig": {
34
- "access": "public"
18
+ "prepublishOnly": "pnpm run build",
19
+ "start": "NODE_ENV=production node dist/index.js",
20
+ "type-check": "tsc --noEmit"
35
21
  },
36
- "keywords": [
37
- "gaia",
38
- "cli",
39
- "ai-assistant",
40
- "setup"
41
- ],
42
- "license": "MIT",
43
22
  "dependencies": {
44
23
  "@inkjs/ui": "^2.0.0",
24
+ "@modelcontextprotocol/sdk": "^1.29.0",
45
25
  "commander": "^14.0.3",
46
26
  "execa": "^9.6.1",
47
- "ink": "^6.6.0",
27
+ "ink": "^6.8.0",
48
28
  "ink-big-text": "^2.0.0",
49
29
  "ink-gradient": "^3.0.0",
50
- "ink-image": "^2.0.0",
51
- "ink-progress-bar": "^3.0.0",
52
30
  "ink-text-input": "^6.0.0",
53
- "react": "^19",
54
- "react-dom": "^19",
55
- "remove": "^0.1.5",
56
- "simple-git": "^3.30.0"
31
+ "react": "19.1.0",
32
+ "react-dom": "19.1.0",
33
+ "simple-git": "^3.36.0",
34
+ "ws": "^8.21.0",
35
+ "zod": "^4.3.6"
57
36
  },
58
37
  "devDependencies": {
59
- "@biomejs/biome": "2.3.7",
60
- "@types/node": "^25.2.2",
61
- "@types/react": "^19",
62
- "@types/react-dom": "^19",
63
- "esbuild": "latest",
64
- "tsx": "latest",
65
- "typescript": "^5.9.2"
38
+ "@biomejs/biome": "^2.5.7",
39
+ "@types/node": "^24.13.3",
40
+ "@types/react": "^19.2.17",
41
+ "@types/react-dom": "^19.2.3",
42
+ "@types/ws": "^8.18.1",
43
+ "esbuild": "^0.25.12",
44
+ "tsx": "^4.23.11",
45
+ "typescript": "^7.0.2",
46
+ "vite": "^7.3.6",
47
+ "vitest": "^4.1.10"
48
+ },
49
+ "bin": {
50
+ "gaia": "./dist/index.js"
51
+ },
52
+ "engines": {
53
+ "node": ">=20"
54
+ },
55
+ "keywords": [
56
+ "ai-assistant",
57
+ "cli",
58
+ "gaia",
59
+ "setup"
60
+ ],
61
+ "license": "MIT",
62
+ "publishConfig": {
63
+ "access": "public"
64
+ },
65
+ "repository": {
66
+ "type": "git",
67
+ "url": "git+https://github.com/theexperiencecompany/gaia.git",
68
+ "directory": "packages/cli"
66
69
  }
67
70
  }