File size: 16,723 Bytes
8f16a6b | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 | # AgentBridge Terminal UI β user guide
The console app of AgentBridge is an interactive terminal UI built on
[Terminal.Gui](https://github.com/tui-cs/Terminal.Gui) (v2, instance-based API),
modelled on [Qwen Code](https://github.com/QwenLM/qwen-code)'s TUI: a menu bar,
an AGENT logo panel, a streaming chat panel with an input line at the bottom, a
status bar, `/` slash commands with a **filterable command palette**, `@` file
attachments, keyboard shortcuts, mouse support and online help β while the HTTP
server keeps serving every other client on the same port. **CLI and API are the
same conversation**: messages you send from the UI go through the exact same
`POST /v1/chat/completions` endpoint that OpenAI-compatible clients use, while MCP
clients can control the same runtime via `POST /mcp`, so both can drive the agents
at the same time (the UI holds one session; other
clients create their own).
## How Qwen Code's TUI works (the model we followed)
Qwen Code is a terminal-based agentic coding tool: you launch `qwen` in a
project and get a persistent TUI where:
- a **bottom input field** accepts plain-language prompts; a small **status
line** shows the model/provider and context usage;
- typing **`/`** opens a **slash-command palette** β a contextual help list
(name + one-line description per command) that **filters as you type**;
Enter runs the highlighted command, Tab completes it, Esc closes it;
- **`@`** opens file/context completion;
- a rich **keyboard-shortcut layer** covers editing (Ctrl+A/E/U/K/W, word
jumps), history (Up/Down, Ctrl+R reverse search), Ctrl+C cancel, Ctrl+L
clear screen, `?` shortcuts overlay, Tab ghost-text completion;
- **`/model`** switches the LLM on the fly, `/help` shows the command docs,
`/docs` opens the online documentation in the browser;
- agent replies **stream** into the conversation and can be cancelled.
## What AgentBridge does better
| Qwen Code | AgentBridge (this app) |
|---|---|
| TUI is the only front-end | TUI **and** the OpenAI-compatible API simultaneously, same process β any SDK/script can keep driving the agents while you chat |
| Model switch is provider-side | `/model` switches LLM **with a context-window guard** β the server refuses (409) when the conversation overflows the target provider's window and explains why |
| Mouse: scroll + click | native cross-platform mouse (Terminal.Gui): **wheel** scrolls the conversation and menus, **click** positions the input cursor or selects a list row, **double-click** runs the selected item |
| Menus | pickers are drawn inside the TUI layout β **Esc always cancels** (`/model`, `/agent`, `/attach`) with a clean screen, no residue |
| No voice | `/voice` β dictation from the server microphone (Windows), `/tts` β Kokoro neural TTS speaks the replies and plays the WAV |
| File completion via `@` | `@` palette of **uploaded** files (server-side `/v1/files`), `/files add <path>` uploads and attaches; attachments ride along as `file_ids` |
| Status shows context | status bar also shows **history tokens / context window**, the active **tools** (readable names, e.g. `File, Web, Git`), TTS/mic availability |
| `/docs` opens docs site | `/docs` opens **this project's** online README; `/help` lists commands, shortcuts, API endpoints and links |
| β | `/agent` opens the tools checklist (presets + individual tools), `/features` toggles feature flags, `/health` pings the server, `/retry` resends the last prompt, `/web` opens the auto-connected web client |
## Commands (type `/` for the live list)
| Command | What it does |
|---|---|
| `/help` Β· `/?` | Full help: commands, shortcuts, API endpoints, online docs |
| `/docs` | Open the online documentation in the browser |
| `/web` | Launch the Giraffe AI web client (auto-installed/updated), auto-connected to this server |
| `/modelsetup` | Configure LLM models & providers (add/edit/remove, active model, API keys) |
| `/model [name]` | Switch the LLM provider (menu when no name given; context-window checked) |
| `/agent [name]` | Choose the agent tools: quick presets or an individual-tool checklist (Space toggles; see below) |
| `/voice [lang]` | Dictate from the server microphone into the input |
| `/tts [text]` | Speak the last agent reply (or the given text) β Kokoro TTS, WAV playback |
| `/telegram status\|config [set <key> <value>\|reload]\|login-code <code>\|allow\|disallow <user>` | Telegram chat medium: bare `/telegram` opens the interactive panel (status, login code, allow-list, config), the subcommands cover the same actions (see [Telegram](#telegram-chat)) |
| `/features [name] [on\|off]` | Show or toggle session feature flags (voice, tts, ...) |
| `/new` Β· `/reset` | Start a new session (fresh conversation) |
| `/clear` | Reset the current session history (keeps the session) |
| `/status` | Session state + platform capabilities |
| `/files add <path>` Β· `/files rm <id>` Β· `/files` | Upload+attach a file, delete one, list uploads |
| `/attach [id]` | Toggle a file attachment for the chat (menu when no id) |
| `/shortcuts` Β· `/keys` | Keyboard shortcuts overlay (also press `?` on an empty input) |
| `/health` | Ping the server, report latency |
| `/retry` | Resend the last prompt (also Ctrl+Y) |
| `/exit` Β· `/quit` | Exit (also Ctrl+C twice, or Ctrl+D) |
## Web GUI
`/web` (or the menu **Web β GUI**) opens the agents in your browser. The
[Giraffe AI](https://github.com/Graphene-Lab/GiraffeAI) client β a single static
`index.html` plus its own launcher β is **not part of this repository**: on startup the
server installs it next to the executable (`GiraffeAIWebClient\` folder, from the client's
latest GitHub release). The first install is unconditional; the automatic **update** check
follows the app's auto-update toggle (`--no-update` / **File β Auto-Update**). Then `/web`
runs the platform launcher (`start.bat` / `start.sh`), which serves the client on
`http://localhost:8000` and opens the browser.
The launch passes `--provider` with this server's endpoint, so the client **registers the
AgentBridge provider (if not already present) and selects it immediately** β no manual
configuration, just start typing.
- The first download needs an internet connection (GitHub); afterwards the client is fully local.
- The client runs in its own launcher window/process and keeps serving after the TUI exits.
- The browser talks straight to this server (`POST /v1/chat/completions`), so CORS is enabled
and no API key is needed for local use.
## Agent tools
`/agent [name]` switches to a preset β full ids: `default-agent`, `web-agent`,
`search-agent`, `research-agent`, `document-files`, `spreadsheet-files`, `email-agent`,
`office-files`, `multi-files`, `all-files`. Bare `/agent` (or menu **Tools β Agent & Tools**)
opens the tool checklist dialog:
- **Core (always on)** β the first line lists the locked core tools (`FileTool`, `GitTool`):
always active, not toggleable; the only way to change their status is `tools.json`
(see [MANUAL.md](MANUAL.md) β the picker always reflects the effective state).
- **Active tools** below β every non-core tool actually loaded at runtime (core tools +
the plugins in `Tools/`), each with a one-line description. **Space** toggles a tool;
**Close/Esc** saves the marked set as a **custom combination** (sent to the server as
the additive `tools` field, which overrides the preset's `model`). The enabled core
tools are always part of the combination.
`all-files` is the dynamic all-in-one agent: every loaded tool the per-tool config leaves
enabled (class-A plugins ON by default; class-B `OfficeTool` OFF unless enabled in
`tools.json`).
The status bar shows the active tools with readable names (`tools: File, Web, Git`), so
you always know what the agent can do in this conversation.
## Telegram chat
`/telegram` turns AgentBridge into a **Telegram chat client** (a userbot): people write to
the account in a **private chat**, the message (text and/or file attachments) goes through
the same per-user chat session as the TUI and the HTML client, and the reply β text plus
any files the agent attaches β comes back into the same chat. Text chat only: the Telegram
Client API has no audio-call support, so Telegram is **not** a voice medium (see
[docs/telegram.md](telegram.md)).
**Bare `/telegram`** (or menu **Tools β Telegram**) opens an interactive panel: live
status plus the first-login code field, allow/disallow user, config, reload and
enable/disable β no slash-command syntax to remember. The subcommands below drive the
same actions from the command line:
| Command | What it does |
|---|---|
| `/telegram status` | Live state: enabled, phase (`off`/`conn`/`code`/`2fa`/`on`/`err`), logged-in user, allow-list, agent |
| `/telegram config` | Show the effective configuration (phone, session, allow-list, agent) |
| `/telegram config set <key> <value>` | Change one config key and persist it to `telegram.json` (connection keys restart the bridge) |
| `/telegram config reload` | Re-read `telegram.json` (hand edits made outside the TUI) and apply them |
| `/telegram login-code <code>` | Complete the pending first login (verification code or 2FA password) |
| `/telegram allow <user>` Β· `/telegram disallow <user>` | Add / remove an allow-list entry (numeric id or `@username`) |
The **status bar** shows a `tg:` segment (`off`/`conn`/`code`/`2fa`/`on`/`err`), refreshed
by the same 3-second poll as SIP. When an agent reply carries attached files, the chat
history shows them as **`[attachment: <path>]`** lines β the files are saved under an
`attachments/` folder next to the executable.
The first login is TUI-guided: `/telegram status` shows `code` while the verification code
is pending, `/telegram login-code <code>` completes it (a 2FA password, if the account has
one, is submitted the same way), and the session persists in `telegram.session` β no code
is asked again. Configuration lives in `telegram.json` next to the executable (excluded
from updates); edit it by hand, with the setup scripts (`scripts/setup-telegram.bat` on
Windows, `scripts/setup-telegram.sh` on Linux/macOS), or with these commands. Full
reference: [docs/telegram.md](telegram.md).
## Models & Providers setup
`/modelsetup` (or menu **File β Models & Providers**) opens a tabbed window that mirrors the
AIOffice settings panel:
| Tab | What you can edit |
|---|---|
| **LLM & Providers** | Active provider (dropdown, switches via the same path as `/model`) and a provider list with **Addβ¦ / Editβ¦ / Remove** β the CRUD operations apply immediately and persist to `providers.json` (see below) |
| **Email (SMTP)** | SMTP server, port, user, password and the recipient email |
| **Mail (IMAP)** | IMAP server, port, user and password |
| **General** | Step logging on/off (`logs/` folder) and the documents path (re-indexed on change) |
- Field edits (email, general) apply when you press **Save**; **Close** discards them.
- Adding a provider opens a small form (name, protocol OpenAI/Gemini/Anthropic, interaction
mode Default/API/CLI, model, base address, endpoint path, **API key**, context window,
timeout). The API-key field serves every cloud provider β any provider whose endpoint is
**not** on loopback (`localhost` / `127.0.0.1`) needs one; local providers simply leave it
empty. Keys are stored per-provider in `providers.json` (masked on screen while typing).
Editing replaces the config in place; removing refuses to delete the last remaining
provider. The interaction mode is optional: `Default` (the initial choice) leaves the
decision to the model size β CLI for small models, API for large ones; `API`/`CLI` force
one of the two. The active mode appears on the status page and is reported by
`GET /v1/models` as `interaction_mode`.
- The provider list also stays in sync with `GET /v1/models`, so an added provider can be
switched to right away.
## Auto-update
Menu **File β Auto-Update** toggles the automatic update check performed at startup
(checked = enabled, the default). The choice persists to the OS app-data folder
(`<AppData>\agent\autoupdate.json`), so it survives updates. When a newer release is
found, the app downloads it, swaps the files and restarts itself β see
[autoupdate.md](autoupdate.md) for the architecture and `--no-update` for services.
## Keyboard shortcuts
| Shortcut | Action |
|---|---|
| `Enter` | Send the message / run the selected command |
| `/` | Open the slash-command palette (live, filters as you type) |
| `@` | Open the file palette (toggle chat attachments) |
| `?` | Shortcuts overlay (empty input) |
| `Tab` | Complete the selected command in the palette |
| `Esc` | Close dialog Β· clear input Β· twice: exit |
| `Ctrl+C` | Cancel the reply Β· clear input Β· twice: exit |
| `Ctrl+D` | Exit (empty input) |
| `Ctrl+L` | Clear the session history (menu bar too) |
| `Ctrl+R` | Reverse-search prompt history |
| `Ctrl+Y` | Retry the last prompt |
| `Up` / `Down` | Prompt history (also Ctrl+P / Ctrl+N) |
| `β` / `β` | Move the cursor (with Ctrl: by word) |
| `Ctrl+A` / `Ctrl+E` | Select all / jump to end of the input |
| `Ctrl+U` / `Ctrl+K` | Delete to start / to end of the line |
| `Ctrl+W` | Delete the word before the cursor (also Ctrl+Backspace) |
| `PgUp` / `PgDn` | Scroll the conversation history |
| `F1` | Full help page |
| `F10` | Activate the menu bar |
The conversation auto-follows the stream while you are at the bottom; scrolling up
(wheel or `PgUp`) pauses the follow so you can read, and scrolling down or sending a
message resumes it.
## Mouse
Terminal.Gui provides native cross-platform mouse support: menus and dialogs are
rendered inside the layout and **Esc always cancels them** cleanly (`/model`,
`/agent`, `/attach`).
| Action | Effect |
|---|---|
| Mouse wheel (conversation) | Scroll the history |
| Mouse wheel (dialog/list) | Move the selection |
| Click the input line | Position the text cursor |
| Click a dialog/list row | Select it |
| Double-click a list row | Run it |
The terminal switches to the alternate screen buffer and restores it on exit.
## Localisation
The TUI is fully localised for **EN, IT, FR, ES, DE, RU** using the standard .NET
resource-file approach (`Resources/Dictionary.resx` + per-language satellites). The app
runs in the **system language when supported, otherwise English** β the correct file is
selected automatically via `CultureInfo.CurrentUICulture` (a French system picks `fr`, a
German one `de`, any other culture falls back to the neutral English resource).
| File | Language |
|---|---|
| `Resources/Dictionary.resx` | English (neutral default) |
| `Resources/Dictionary.it.resx` | Italian |
| `Resources/Dictionary.fr.resx` | French |
| `Resources/Dictionary.es.resx` | Spanish |
| `Resources/Dictionary.de.resx` | German |
| `Resources/Dictionary.ru.resx` | Russian |
Rules and conventions:
- **Command names are never translated** β `/help`, `/model`, `/agent`, `/voice`, `/tts`,
`/files`, β¦ keep their English names in every language (they are also the API contract).
Only the command *descriptions* shown in the palette/help are localised.
- All UI strings (menus, help pages, dialogs, status notes, picker hints) come from
`Dictionary.*` (the strongly typed Designer generated from the resx). New UI strings go
into the resx files, never hardcoded in `Tui.cs`.
- **System-generated agent results are localised too.** AIOrchestrator no longer returns
hardcoded English messages ("Max iterations reached", "LLM returned no response", the
"Done" fallback): it returns a locale-neutral `AgentResultCode` enum and AgentBridge maps
each code to the phrase in the dictionary for the current language (see
`AgentResult.cs` / `Program.cs` β `ResultText`). The agent's own LLM text passes through
untouched, since the model is instructed to reply in the language of the request.
- Voice/TTS languages (`/voice`, `/tts`) keep following `SystemLang` (machine `CurrentUICulture`
via `SystemLang.Get()`), independently of the UI dictionary.
To add a new language: copy `Resources/Dictionary.resx` to `Dictionary.XX.resx`
(XX = ISO 639-1 code), translate the values, and rebuild β the SDK picks the new satellite
up automatically.
## Launch modes
How the app starts β terminal UI, server only, or forced UI β is covered in
[docs-dev/ARCHITECTURE.md](../docs-dev/ARCHITECTURE.md#launch-modes).
---
See also: [README](../README.md) Β· [API reference](API.md) Β· [Architecture](../docs-dev/ARCHITECTURE.md) Β· [Developer guide](../docs-dev/TUI-DEVELOPMENT.md) (Terminal.Gui v2, for TUI code changes β developers, not shipped)
|