diff --git a/personal/projects/balda/setup.md b/personal/projects/balda/setup.md new file mode 100644 index 00000000..3f52cfa0 --- /dev/null +++ b/personal/projects/balda/setup.md @@ -0,0 +1,124 @@ +# Balda Setup & Status + +> Last updated: 2026-06-07 + +## Runtime + +| Item | Value | +|------|-------| +| Binary | `~/.local/bin/balda` | +| Process | Native Mac process (PID changes on restart) | +| Log | `/private/tmp/balda.log` | +| Config | `~/Developer/balda/.config/balda/config.yaml` | +| State dir | `~/Developer/balda/.config/balda/` | +| Sessions | SQLite persistence | +| Provider | `claude_code_acp` (Claude Code ACP, model: claude-sonnet-4-6) | + +## Zulip Webhook + +| Item | Value | +|------|-------| +| Status | ENABLED | +| Listen address | `0.0.0.0:8091` | +| Path | `/zulip/webhook` | +| Webhook bot URL | `http://host.docker.internal:8091/zulip/webhook` | + +Port was **changed from 8090 → 8091** on 2026-06-07 (see Port Conflict below). + +## Architecture + +Balda uses the **outgoing webhook** mechanism — Zulip pushes events to Balda's +HTTP endpoint. This differs from Eagle/Kit which use polling. + +- Zulip runs in Docker (container: `zulip-zulip-1`), exposed on `127.0.0.1:8000` +- Balda runs natively on Mac (not in Docker) +- Colima maps `host.docker.internal:PORT → 127.0.0.1:PORT` on the Mac host, + so the bot URL uses `host.docker.internal` to reach Balda from inside Docker + +## Soul / Prompt + +The `global_instruction` field in `config.yaml` defines Balda's persona (Валера). +The canonical source is `soul.md` in this folder — sync manually to config after edits, +then restart Balda. + +Provider-level `system_instructions` are documented in `workspace-context.md`. + +--- + +## Bug Fixed 2026-06-07 — Context Canceled on First DB Operation + +**File:** `zulip_handler.go`, line 236 + +**Root cause:** The message-processing goroutine was launched with the HTTP +request context: + +```go +// Before (broken) +go h.processMessage(r.Context(), payload) +``` + +When the handler returns HTTP 200, Go cancels `r.Context()`. The goroutine then +hits its first database operation and fails with `context canceled`. + +**Fix:** + +```go +// After (fixed) +go h.processMessage(context.WithoutCancel(r.Context()), payload) +``` + +`context.WithoutCancel` creates a copy of the parent context that is never +canceled when the parent is — so the goroutine lives past the HTTP handler return. + +--- + +## Port Conflict 2026-06-07 — Moved 8090 → 8091 + +**Root cause:** Colima (Docker runtime) maps `host.docker.internal:PORT → +127.0.0.1:PORT` on the Mac host. `openclaw/claude-proxy` was occupying +`127.0.0.1:8090`, intercepting Balda's webhook traffic before it reached Balda. + +**Solution:** Changed Balda's listen port from `8090` to `8091` in `config.yaml`. + +### Pending + +- [ ] Update Zulip webhook bot URL from `8090` to `8091` + - In Zulip admin: Settings → Bots → edit the outgoing webhook bot + - Or via `docker exec zulip-zulip-1 python manage.py ...` + - New URL: `http://host.docker.internal:8091/zulip/webhook` + +--- + +## Starting / Restarting Balda + +```bash +# View logs +tail -f /private/tmp/balda.log + +# Start (runs in background, logs to /private/tmp/balda.log) +~/.local/bin/balda serve >> /private/tmp/balda.log 2>&1 & + +# Check if running +pgrep -l balda +``` + +## Config Snippet (key sections) + +```yaml +balda: + global_instruction: | + + +runtime: + providers: + claude_code: + type: claude_code_acp + claude_code_acp: + model: claude-sonnet-4-6 + +zulip: + webhook: + enabled: true + listen: "0.0.0.0:8091" + path: /zulip/webhook +```