Metadata-Version: 2.4
Name: upivia-tui
Version: 0.1.0
Summary: Upivia Textual TUI — chat with Yupi, watch multi-agent delegation, reuse the platform's governed orchestration.
Project-URL: Homepage, https://www.upivia.com
Project-URL: Documentation, https://www.upivia.com/docs
Author: Upivia
License: MIT
License-File: LICENSE
Keywords: agents,ai-agents,cli,governance,terminal,tui,upivia
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Terminals
Requires-Python: >=3.10
Requires-Dist: httpx>=0.27.0
Requires-Dist: playwright>=1.45
Requires-Dist: textual>=0.80.0
Requires-Dist: upivia>=0.2.0
Requires-Dist: websockets>=12.0
Provides-Extra: dev
Requires-Dist: pytest>=8.0; extra == 'dev'
Description-Content-Type: text/markdown

# upivia-tui

The **Upivia terminal** — a [Textual](https://textual.textualize.io/) TUI and the
canonical CLI for Upivia (it replaced the older Node/OpenTUI CLI). It is a thin
presentation layer over the platform's governed chat-turn pipeline — all
orchestration, budgets, approvals, memory, and multi-agent delegation happen
server-side.

## What it does

- renders messages as bordered cards (OpenCode-style)
- renders markdown with Textual's native widget (clean tables/code/bold/italic)
- visualises multi-agent delegation in a live Team panel (+ worker detail view)
- lets the agent **read/write/edit/run** files in your launch directory, with
  per-session command permissions and inline +/- diff cards
- syncs in realtime with the web app over WebSocket, and can run headless
  (`--background`) so the web app edits files on this machine

## Install & authenticate

```bash
uv tool install upivia-tui        # or: pipx install upivia-tui  (Python 3.10+)
upivia-tui init                   # authenticate (writes ~/.upivia/config.json)
upivia-tui                        # launch
```

## Keyboard & commands

| Key | Action |
|---|---|
| `Ctrl+P` | Command palette (fuzzy) |
| `Ctrl+O` | Switch model (curated + full OpenRouter catalog) |
| `Ctrl+T` | Switch agent |
| `Ctrl+B` | Switch session (loads history) |
| `Ctrl+G` | Toggle Build / Plan mode |
| `Ctrl+L` | New / clear session |
| `Ctrl+Y` | Copy (selection, or last reply) — also drag-to-copy |
| `Ctrl+C` / `Ctrl+Q` | Quit |

All shortcuts work even while typing in the composer (priority bindings).
`Ctrl+S` is intentionally avoided (it triggers terminal flow-control on many
terminals).

Slash commands: `/models` `/model <id>` `/agent` `/sessions` `/session`
`/new` `/rename <title>` `/delete` `/mode` `/autonomy` `/requests` `/worker`
`/export` `/compact` `/clear` `/help`. The model picker and command palette
mirror the Node CLI; selecting a new model or agent starts a fresh session so
history stays consistent.

### Autocomplete & worker detail

- Type `@` in the composer to autocomplete **project files** (Tab/Enter to
  accept); mentioned files are read by the agent first.
- Type `/` to autocomplete **slash commands** from a fuzzy dropdown.
- Click a worker in the Team panel (or run `/worker`) to open its **full
  activity stream** — every thinking step, tool call, file write, and result.
- The agent can navigate large codebases with `local_code_graph` (Graphify);
  install with `uv tool install graphifyy`. It falls back to `local_search`
  when graphify isn't present.

## Copy & select

Textual runs in mouse-tracking mode, so the app handles selection itself:

- **Drag** with the mouse to select text — it **auto-copies on release** (via
  OSC 52, so it works over SSH and writes the system clipboard where available).
  This is the reliable path and needs no key.
- **Ctrl+Y** copies the current selection, or the last assistant reply if
  nothing is selected.
- `Ctrl+Shift+C` also works *where the terminal forwards it* — but many
  terminals intercept it for their own copy, which is why drag-to-copy and
  Ctrl+Y are the primary paths.
- Your terminal's native selection still works too: hold **Shift** (most
  terminals) or **Option/Alt** (iTerm2/macOS) while dragging.

## Local file editing
When the agent calls a local tool, the server pauses the turn with
`local_tools_pending`; this client executes it on disk and resumes. Supported
tools: `local_read_file`, `local_write_file`, `local_edit_file`,
`local_list_dir`, `local_search`, `local_run_command`.

- **Sandbox:** every path resolves under the directory you launched
  `upivia-tui` from and can never escape it.
- **Command gating:** the first time the agent wants to run a shell command,
  you're asked once which categories it may use (shell / install / servers /
  git / delete); the choice is enforced for the rest of the session.
- **Diffs:** writes and edits render a colorised +/- diff card inline.

## Local browser automation

The TUI ships with **built-in Playwright browser tools** — install the TUI and
the agent can pilot a real local Chromium with zero manual setup. On the very
first browser call, the Chromium engine is auto-installed (one-time,
`python -m playwright install chromium`, with a "Installing local browser
engine (one-time setup)…" status line); after that it's instant. One persistent
headless browser/page is kept alive across tool calls for the session.

Tools: `local_browser_open`, `local_browser_snapshot`, `local_browser_click`,
`local_browser_type`, `local_browser_press`, `local_browser_select`,
`local_browser_wait`, `local_browser_extract`, `local_browser_screenshot`,
`local_browser_close`, `local_browser_health`.

**Ref-based interaction contract:** the agent calls `local_browser_snapshot`
first (or reads the snapshot embedded in `open`/`click`/`type` results), which
tags interactive elements with stable refs like `e12` and returns them in an
LLM-friendly digest (role, name, text, visibility, links, forms, console
errors). Clicks/typing then target those refs, with visible-text and CSS
selectors as fallbacks. Refs refresh automatically after every action, so they
never go stale silently.

Safety notes:

- no tool ever returns cookies, localStorage, or other secrets
- downloads are disabled (`accept_downloads=False`)
- screenshots are saved as PNG files under `.upivia-screenshots/` in your
  project directory — only the file path is returned, never inline image data
- navigating to banking/payment-looking hosts attaches a warning to the result
- every failure returns a structured error with suggestions (valid refs,
  repair hints) instead of crashing the turn

## Auth

It reads the **same** `~/.upivia/config.json` that `upivia init` (the Node CLI)
writes. If you've authenticated the Node CLI, you're authenticated here.

Override for dev:

```bash
export UPIVIA_BASE_URL=http://localhost:3000
export UPIVIA_PAT=upivia_pat_...
```

## Run

```bash
cd packages/upivia-tui
uv run upivia-tui              # full TUI in the current directory
uv run upivia-tui --dir PATH  # full TUI rooted at PATH
uv run upivia-tui --background # headless device daemon (no UI)
uv run upivia-tui --browser-headful # show the built-in browser window
```

### Built-in local browser: headless vs headful

The `local_browser_*` tools drive a local Chromium that is **headless by
default**. To watch the agent work (or complete a login/captcha yourself),
opt in to a visible window with any of:

- `--browser-headful` CLI flag
- `UPIVIA_BROWSER_HEADFUL=1` environment variable
- `"browserHeadful": true` in `~/.upivia/config.json`

## Realtime sync + machine-wide device

The TUI connects to the platform's WebSocket companion (`wss://…/ws`) and
registers as a **live device**:

- Chat turns flow over WS, so the **web app and the TUI share one live
  session** — messages and tool calls appear in both in real time (SSE fallback
  if the socket can't connect).
- While the TUI is open **or** `upivia-tui --background` is running, **any web
  session attached to this device can read/write/edit/run files on this
  machine** through the governed `local_tools_pending` → execute →
  `tool_result` loop. Attach a device from the web app's Sessions view.
- The TopBar shows `● live` (WS connected / device online) or `○ local`.

### Set the working directory from the web app

When a device is live, the web Sessions header shows a subtle folder chip. Click
it to browse the device's directories and `cd` into one — type a path (Tab
completes against available sub-directories, Enter applies) or click a listed
folder. This rebases the directory the agent reads/writes/runs in, sandboxed to
the chosen root.

## How it talks to the platform

REST + SSE go through the official Python SDK (`upivia`,
`packages/sdk-py`): `upivia_tui/client.py` is a thin adapter over
`upivia.AsyncUpiviaClient` (PAT auth). The realtime WebSocket
device link (`upivia_tui/wsclient.py`) speaks to the WS companion directly.

| Action            | Endpoint                                  |
|-------------------|-------------------------------------------|
| List agents       | `GET /api/v1/agents`                      |
| Balance           | `GET /api/v1/balance`                     |
| Create session    | `POST /api/v1/chat/sessions`              |
| Stream a turn     | `POST /api/v1/chat/turn` (SSE)            |

Delegation is driven by the `delegation_started` and `agent_event` SSE events
emitted by the chat route when Yupi spawns/delegates to worker agents.

## Yupi delegates by default

The orchestration system prompt in `app/api/v1/chat/turn/route.ts` instructs
Yupi to delegate any non-trivial or multi-step work to specialist agents, only
working solo for genuinely trivial single-step actions.
