fix: support server.api config, preserve api across onboard, fix load error logging

Three bugs fixed:

1. server.api is now the canonical location for API server config (port,
   host, CORS). Users naturally nest api under server -- this now works.
   Top-level api still accepted with a deprecation warning.

2. Onboarding no longer silently drops api and attachments config when
   saving. Both interactive and non-interactive paths now preserve
   unmanaged top-level fields from the existing config.

3. When YAML parsing fails, the log no longer misleadingly says
   "Loaded from lettabot.yaml". A didLoadFail() flag enables accurate
   status reporting without changing 17+ loadConfig() call sites.

Written by Cameron ◯ Letta Code

"The map is not the territory, but a good map sure helps you find port 6702."
This commit is contained in:
Cameron
2026-02-10 20:16:36 -08:00
parent 83569d968e
commit c4c8b17018
6 changed files with 309 additions and 35 deletions

View File

@@ -23,6 +23,10 @@ For global installs (`npm install -g`), either:
server:
mode: cloud # 'cloud' or 'selfhosted'
apiKey: letta_... # Required for cloud mode
api:
port: 8080 # Default: 8080 (or PORT env var)
# host: 0.0.0.0 # Uncomment for Docker/Railway
# corsOrigin: https://my.app # Uncomment for cross-origin access
# Agent settings (single agent mode)
# For multiple agents, use `agents:` array instead -- see Multi-Agent section
@@ -87,11 +91,6 @@ attachments:
maxMB: 20
maxAgeDays: 14
# API server (health checks, CLI messaging)
api:
port: 8080 # Default: 8080 (or PORT env var)
# host: 0.0.0.0 # Uncomment for Docker/Railway
# corsOrigin: https://my.app # Uncomment for cross-origin access
```
## Server Configuration
@@ -226,7 +225,7 @@ agents:
cron: true
```
The `server:`, `transcription:`, `attachments:`, and `api:` sections remain at the top level (shared across all agents).
The `server:` (including `server.api:`), `transcription:`, and `attachments:` sections remain at the top level (shared across all agents).
### Known limitations
@@ -449,9 +448,9 @@ The top-level `polling` section takes priority if both are present.
|--------------|--------------------------|
| `GMAIL_ACCOUNT` | `polling.gmail.account` (comma-separated list allowed) |
| `POLLING_INTERVAL_MS` | `polling.intervalMs` |
| `PORT` | `api.port` |
| `API_HOST` | `api.host` |
| `API_CORS_ORIGIN` | `api.corsOrigin` |
| `PORT` | `server.api.port` |
| `API_HOST` | `server.api.host` |
| `API_CORS_ORIGIN` | `server.api.corsOrigin` |
## Transcription Configuration
@@ -478,18 +477,25 @@ Attachments are stored in `/tmp/lettabot/attachments/`.
The built-in API server provides health checks, CLI messaging, and a chat endpoint for programmatic agent access.
Configure it under `server.api:` in your `lettabot.yaml`:
```yaml
api:
port: 9090 # Default: 8080
host: 0.0.0.0 # Default: 127.0.0.1 (localhost only)
corsOrigin: "*" # Default: same-origin only
server:
mode: selfhosted
baseUrl: http://localhost:8283
api:
port: 9090 # Default: 8080
host: 0.0.0.0 # Default: 127.0.0.1 (localhost only)
corsOrigin: "*" # Default: same-origin only
```
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `api.port` | number | `8080` | Port for the API/health server |
| `api.host` | string | `127.0.0.1` | Bind address. Use `0.0.0.0` for Docker/Railway |
| `api.corsOrigin` | string | _(none)_ | CORS origin header for cross-origin access |
| `server.api.port` | number | `8080` | Port for the API/health server |
| `server.api.host` | string | `127.0.0.1` | Bind address. Use `0.0.0.0` for Docker/Railway |
| `server.api.corsOrigin` | string | _(none)_ | CORS origin header for cross-origin access |
> **Note:** Top-level `api:` is still accepted for backward compatibility but deprecated. Move it under `server:` to avoid warnings.
### Chat Endpoint