157 lines
4.6 KiB
Markdown
157 lines
4.6 KiB
Markdown
# Balda Setup & Status
|
|
|
|
> Last updated: 2026-06-07
|
|
|
|
## Runtime
|
|
|
|
| Item | Value |
|
|
|------|-------|
|
|
| Binary | `~/Developer/balda/balda` (built from source) |
|
|
| Process | Managed by launchd (`com.normahq.balda`) |
|
|
| Log | `/private/tmp/balda.log` |
|
|
| Config | `~/Developer/balda/.config/balda/config.yaml` |
|
|
| State dir | `~/Developer/balda/.config/balda/` |
|
|
| Sessions | SQLite persistence |
|
|
| Provider | `deepseek` (openai type, model: `deepseek-chat`, via `https://api.deepseek.com/v1`) |
|
|
|
|
Balda is managed by launchd. Full restart (reloads plist env vars):
|
|
|
|
```bash
|
|
launchctl bootout gui/$(id -u) ~/Library/LaunchAgents/com.normahq.balda.plist
|
|
launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/com.normahq.balda.plist
|
|
```
|
|
|
|
Quick restart (does NOT reload plist env vars — use bootout/bootstrap for env changes):
|
|
|
|
```bash
|
|
launchctl kickstart -k gui/$(id -u)/com.normahq.balda
|
|
```
|
|
|
|
## 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`.
|
|
|
|
### Resolution
|
|
|
|
Webhook bot URL updated in Zulip DB via `docker exec psql` on 2026-06-07:
|
|
`http://host.docker.internal:8090/zulip/webhook` → `http://host.docker.internal:8091/zulip/webhook`
|
|
|
|
---
|
|
|
|
## DeepSeek Provider via norma-local Fork
|
|
|
|
Balda's `openai` provider type in norma hardcoded `api.openai.com`. To support
|
|
DeepSeek (or any OpenAI-compatible API), the norma source was forked locally:
|
|
|
|
- Fork path: `~/Developer/norma-local`
|
|
- Patched files:
|
|
- `pkg/runtime/hostedagent/openai.go` — added `openAIBaseURL()` reading `OPENAI_BASE_URL` env var
|
|
- `pkg/runtime/agentfactory/agentfactory.go` — removed MCP restriction for `openai` type
|
|
- Env var `OPENAI_BASE_URL=https://api.deepseek.com/v1` is set in the launchd plist
|
|
- go.mod `replace` directive (`normahq/norma v0.0.6 → ../norma-local`) is local only
|
|
(not committed to the PR branch — needs a separate norma upstream PR or fork)
|
|
|
|
To rebuild after patching norma:
|
|
|
|
```bash
|
|
cd ~/Developer/balda
|
|
go build -o balda ./cmd/balda/
|
|
```
|
|
|
|
---
|
|
|
|
## CLAUDECODE Environment Bug (Fixed 2026-06-07)
|
|
|
|
When launched from an Eagle terminal session, Balda inherited `CLAUDECODE=1`,
|
|
which caused the Claude Code CLI to refuse to start (it detected a nested invocation).
|
|
**Fix:** Use `launchctl bootout + bootstrap` to start Balda clean — launchd does
|
|
not inherit parent shell env vars.
|
|
|
|
---
|
|
|
|
## Config Snippet (key sections)
|
|
|
|
```yaml
|
|
balda:
|
|
global_instruction: |
|
|
<contents of soul.md>
|
|
|
|
runtime:
|
|
providers:
|
|
deepseek:
|
|
type: openai
|
|
openai:
|
|
api_key: "<DeepSeek API key>"
|
|
model: deepseek-chat
|
|
|
|
zulip:
|
|
webhook:
|
|
enabled: true
|
|
listen: "0.0.0.0:8091"
|
|
path: /zulip/webhook
|
|
allowed_owners:
|
|
- amartemyanov@duckduckgo.com
|
|
```
|