diff --git a/README.md b/README.md index 81d9206..ad2e662 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ -# Paseo — Agent Orchestration on the Home Lab +# Paseo — Agent Orchestration, Native on .13 -**Multi-agent orchestration GUI (Paseo 0.7.2) self-hosted in Docker on `.13`, driving real pi -coding agents (0.82.1) through OmniRoute.** +**Multi-agent orchestration (Paseo 0.7.2) running as a native daemon on `.13` — driving the host's +pi (0.82.1) with full filesystem access, LLM via OmniRoute.** > Maintained by Sam · Gitea — [sam/paseo](https://gitea.lab.audasmedia.com.au/sam/paseo) · > interactive map: [maps.lab → Paseo](https://maps.lab.audasmedia.com.au/paseo/docs/system-map.html) @@ -11,14 +11,17 @@ coding agents (0.82.1) through OmniRoute.** ## What it is [Paseo](https://github.com/getpaseo/paseo) is a client-server orchestration layer for AI coding -agents: one **daemon** manages agent processes and streams their output to desktop, CLI, mobile and -web clients. On this lab it runs **inside Docker on the always-on host `.13`**, with **pi** (the -coding agent) baked into the image and LLM traffic routed through the existing **OmniRoute** proxy -on `.13:20129`. +agents: one **daemon** manages agent processes and streams output to CLI, web and mobile clients. -- **Local-first** — agents run on our machines/dev environment; no telemetry. -- **Pi is a first-class provider** — the daemon spawns `pi --mode rpc` (pi 0.82.1, no Nix changes). -- **One console** — `paseo ls` / `attach` / `logs` from anywhere: `.27`, `.51`, mobile, web UI. +On this lab it runs **natively on the always-on NixOS host `.13`** (no container): the daemon spawns +the **host's own pi 0.82.1** (`pi --mode rpc`) as user `sam`, giving agents **direct access to the +real filesystem** — projects, the Obsidian vault, photos — with the user's real permissions. LLM +traffic routes through the existing **OmniRoute** proxy on `.13:20129`. + +- **Local-first** — no telemetry, no cloud dependency (Tailscale/LAN only). +- **No sandbox** — this is deliberate: the daemon *is* `sam`. Guardrails come from pi's own + protections (filechanges, approvals), not a container boundary. +- **One console** — `paseo ls` / `attach` / `logs` from .27, .51, and mobile web UI. ## Architecture @@ -27,27 +30,25 @@ flowchart LR subgraph CLIENTS["Clients"] D27[".27 desktop
paseo CLI"] D51[".51 laptop
paseo CLI"] - M["Mobile / web UI
browser"] + M["Mobile / web UI
browser / Tailscale"] end - subgraph S13["Paseo daemon (.13 — Docker, always-on)"] - D["Paseo daemon 0.7.2
:6767 · auth"] - PI["pi agent 0.82.1
pi --mode rpc
@earendil pi + omni ext"] - CFG["pi config
/home/paseo/.pi"] - W["workspaces
/workspace/demo"] - PWD["PASEO_PASSWORD
.env (600)"] + subgraph N13["Native daemon on .13 (NixOS, always-on)"] + D["Paseo daemon 0.7.2
systemd user service
0.0.0.0:6767"] + PI["pi 0.82.1 (Nix)
pi --mode rpc
host ~/.pi + ~/.agents"] + FS[("Host filesystem as `sam`
projects: ~/paseo/projects/
obsidian vault, photos, /mnt/*")] + FW["NixOS firewall
port 6767 open"] end subgraph LLM["LLM routing"] - OR["OmniRoute
.13:20129"] - OP["OpenCode-Go /
OpenRouter / DeepSeek / Gemini"] + OR["OmniRoute .13:20129"] + OP["OpenRouter / DeepSeek /
OpenCode-Go (deferred)"] end D27 -->|"PASEO_HOST + password"| D D51 -->|"PASEO_HOST + password"| D - M -->|"https :6767"| D - D -->|"spawns / manages"| PI - PI -->|"reads settings + models"| CFG - PI -->|"works in"| W - D -->|"protects"| PWD - PI -->|"httpx /v1 (omni provider)"| OR + M -->|"Tailscale / LAN :6767"| D + D -->|"spawns / manages (no sandbox)"| PI + PI -->|"direct access, real permissions"| FS + D -.->|"listen allowed"| FW + PI -->|"omni provider /v1"| OR OR -->|"combo routing"| OP ``` @@ -68,70 +69,64 @@ paseo/ ## Quick start (client) ```bash -# .27 / .51 (one-time) -npm install -g @getpaseo/cli@0.7.2 +npm install -g @getpaseo/cli@0.7.2 # one-time, per machine -export PASEO_HOST=192.168.20.13:6767 -export PASEO_PASSWORD= +export PASEO_HOST=192.168.20.13:6767 # or in ~/.config/environment.d/10-secrets.conf +export PASEO_PASSWORD= # on .13's secrets file paseo status # daemon reachable? paseo ls # running agents -paseo run --provider pi --model omni/openrouter/qwen/qwen3.7-flash \ - --cwd /workspace/demo "describe this workspace" +paseo run --provider pi "your task" # defaults to combo model, cwd = your folder paseo logs # full activity timeline ``` -Web UI: `http://192.168.20.13:6767` (password). Mobile: browser over LAN/Tailscale. +Web UI: `http://192.168.20.13:6767` (LAN) · `http://100.114.62.46:6767` (Tailscale/mobile). ## Deployment (server, `.13`) | Item | Value | |---|---| -| Compose dir | `/home/sam/Docker/Containers/paseo/` | -| Image | `ghcr.io/getpaseo/paseo:latest` + custom stage | -| Daemon | 0.7.2 · `restart: always` · :6767 | -| pi | `@earendil-works/pi-coding-agent@0.82.1` (baked, `--mode rpc`) | -| Extensions | `omniroute-pi-ext-integration` (baked) | -| Config | `./paseo-home:/home/paseo` (persists pi + paseo config) | -| Workspace | `./workspace:/workspace` (agent project area) | +| Daemon | Paseo 0.7.2 · **native** · systemd user service `paseo.service` · `0.0.0.0:6767`, enabled | +| pi | Host Nix pi 0.82.1 (`/etc/profiles/per-user/sam/bin/pi`) — used directly via `--mode rpc` | +| Config | `~/.paseo/` (daemon) · `~/.pi/` + `~/.agents/` (host pi, Gitea `pi-config` clone) | +| Projects | `~/paseo/projects//` — real paths, direct FS access | | LLM | pi → omni provider → `http://192.168.20.13:20129/v1` (OmniRoute) | -| Secrets | `.env` (chmod 600) — `PASEO_PASSWORD`, `OMNIROUTE_API_KEY` | +| Firewall | `networking.firewall.allowedTCPPorts` includes **6767** (NixOS configuration.nix) | +| Secrets | `PASEO_PASSWORD` in `.13` `~/.config/environment.d/10-secrets.conf` (chmod 600) | -**Build note:** base image runs as user `paseo` (uid 1000) with root-owned `/usr/local` — so pi and -the extension are installed at **build time** under `USER root` in the Dockerfile, then dropped back -to `USER paseo` for runtime. +**Start/stop/status:** `systemctl --user {start,stop,status} paseo` · logs: `journalctl --user -u paseo`. -## Verified end-to-end (2026-09-09) +## Verified end-to-end (2026-09-16) ``` -$ paseo run --provider pi --model omni/openrouter/qwen/qwen3.7-flash \ - --cwd /workspace/demo --title paseo-demo --background \ - "List files, read HELLO.txt, write DEMO_SUMMARY.md" - -AGENT ID 560ffca0-… STATUS running PROVIDER pi CWD /workspace/demo - ↓ -AGENT ID 560ffca0-… STATUS idle PROVIDER pi/omni/openrouter/qwen/qwen3.7-flash - ↓ → wrote ./workspace/demo/DEMO_SUMMARY.md (correct content) - ↓ → `paseo logs` shows full timeline (user → thought → shell → read) - ↓ → web UI :6767 → HTTP 200 +$ paseo run --provider pi "…" # bare run — model defaults to combo +Model omni/default-opencode-go-ds-flash # healthy combo (OpenRouter → DeepSeek → OpenCode-Go) +Cwd /home/sam/paseo/projects/obsidian_cleanup_tool +Status idle ✅ (agent replied NATIVE_OK / NEWPATH_OK) ``` -## Known findings +- Clients: .27 CLI · .51 CLI · mobile web UI all reach the daemon (LAN + Tailscale). ✅ +- Migration from the earlier Docker deployment completed; Docker removed (legacy backup in + `~/paseo/docker-legacy-backup-…`). -- **OmniRoute combo regression:** the default `default-opencode-go-ds-flash` combo currently returns - `400 missing x-opencode-session` (OpenCode-Go leg) — affects host pi too, not just the container. - Working legs verified: `openrouter/qwen/qwen3.7-flash`, `openrouter/openai/gpt-5.6-sol`, - `aug/claude-haiku-4.5`. Fix the combo/credentials on OmniRoute to restore the default path. -- Paseo is pre-1.0 (0.7.2) — pin the version; expect breaking changes between releases. -- CLI runtime install on `.27` carries 3 low/medium CVEs in transitive deps (`qs`, `uuid`, - `@ai-sdk/provider-utils`) — vet/npq scanned clean, author verified. +## Known notes + +- **Model default:** the pi model catalog was reordered so `default-opencode-go-ds-flash` is first + (bare `paseo run` picks it instead of a flaky free leg). If the combo's OpenCode-Go leg is + sub-rate-limited, the combo still falls back OpenRouter → DeepSeek. +- **Skills:** the host pi (`~/.agents`) carries the full skill set (nixos-workflow, system-architect, + project-ops, obsidian-cli, etc.). Per-project `.pi/settings.json selects which are loaded. +- **Security model:** native = full user permissions. Do not expose the daemon publicly; keep + LAN/Tailscale + password (no public Caddy vhost; use Paseo relay only if internet access is ever + required). ## Why it matters -- **Proof the stack composes:** Nix pi binary stays untouched; the lab's OmniRoute routing powers a - third-party orchestrator; one always-on Docker host (.13) gives fleet control from any device. -- **A pattern for multi-agent work:** workspaces + `pi --mode rpc` + OmniRoute is a base for - coordinating several pi agents on real projects — exactly the coordination layer the lab needs. +- **Full-control autonomy: the daemon is `sam`, so agents manage real files (photos, vault, + projects) with no mount plumbing. +- One always-on control plane for pi across all devices — the "phone control plane" use case. +- n8n/Prefect email→agent workflows, scheduled runs, and browser tasks (pi-browser-harness) can be + layered on top. --- diff --git a/docs/diagrams/system.png b/docs/diagrams/system.png index c10fc12..aeb1f6e 100644 Binary files a/docs/diagrams/system.png and b/docs/diagrams/system.png differ diff --git a/docs/diagrams/system.svg b/docs/diagrams/system.svg index fc989d7..b978358 100644 --- a/docs/diagrams/system.svg +++ b/docs/diagrams/system.svg @@ -1 +1 @@ -

LLM routing

Paseo daemon (.13 — Docker, always-on)

Clients

PASEO_HOST + password

PASEO_HOST + password

https :6767

spawns / manages

reads settings + models

works in

protects

httpx /v1 (omni provider)

combo routing

.27 desktop
paseo CLI

.51 laptop
paseo CLI

Mobile / web UI
browser

Paseo daemon 0.7.2
:6767 · auth

pi agent 0.82.1
pi --mode rpc
@earendil pi + omni ext

pi config
/home/paseo/.pi

workspaces
/workspace/demo

PASEO_PASSWORD
.env (600)

OmniRoute
.13:20129

OpenCode-Go /
OpenRouter / DeepSeek / Gemini

\ No newline at end of file +

LLM routing

Native daemon on .13 (NixOS, always-on)

Clients

PASEO_HOST + password

PASEO_HOST + password

Tailscale / LAN :6767

spawns / manages (no sandbox)

direct access, real permissions

listen allowed

omni provider /v1

combo routing

.27 desktop
paseo CLI

.51 laptop
paseo CLI

Mobile / web UI
browser / Tailscale

Paseo daemon 0.7.2
systemd user service
0.0.0.0:6767

pi 0.82.1 (Nix)
pi --mode rpc
host ~/.pi + ~/.agents

Host filesystem as `sam`
projects: ~/paseo/projects/
obsidian vault, photos, /mnt/*

NixOS firewall
port 6767 open

OmniRoute .13:20129

OpenRouter / DeepSeek /
OpenCode-Go (deferred)

\ No newline at end of file diff --git a/docs/system-map.html b/docs/system-map.html index bc1681b..f72e3d8 100644 --- a/docs/system-map.html +++ b/docs/system-map.html @@ -4,7 +4,7 @@ - Paseo on the Home Lab Diagram + Paseo — Native Daemon on .13 Diagram