Metadata-Version: 2.4
Name: assistant
Version: 2.2.0a4
Summary: Your very own Assistant. Because you deserve it.
Home-page: https://gitlab.com/waser-technologies/technologies/assistant
Author: Danny Waser
Author-email: danny@waser.tech
License: MIT
Project-URL: Documentation, https://gitlab.com/waser-technologies/technologies/assistant/blob/master/README.md
Project-URL: Code, https://gitlab.com/waser-technologies/technologies/assistant
Project-URL: Issue tracker, https://gitlab.com/waser-technologies/technologies/assistant/issues
Platform: any
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Natural Language :: English
Classifier: Natural Language :: French
Classifier: Topic :: System :: Shells
Classifier: Programming Language :: Unix Shell
Classifier: Topic :: Terminals
Requires-Python: >=3.8,<4
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: pygments
Requires-Dist: xonsh
Requires-Dist: prompt_toolkit>3.0.36
Requires-Dist: questionary
Requires-Dist: colorama
Requires-Dist: rich
Requires-Dist: halo
Requires-Dist: requests
Requires-Dist: tomli-w
Requires-Dist: tiktoken
Requires-Dist: keyring
Dynamic: author
Dynamic: author-email
Dynamic: classifier
Dynamic: description
Dynamic: description-content-type
Dynamic: home-page
Dynamic: license
Dynamic: license-file
Dynamic: platform
Dynamic: project-url
Dynamic: requires-dist
Dynamic: requires-python
Dynamic: summary

<!-- ![Banner for Assistant](/assets/main-banner.png) -->

<div align="center">

  [![assistant](https://images.weserv.nl/?url=https://gitlab.com/waser-technologies/technologies/assistant/-/raw/main/assets/assistant.jpeg?ref_type=heads?v=4&h=300&w=300&fit=cover&mask=circle&maxage=7d)](https://gitlab.com/waser-technologies/technologies/assistant)

  # Assistant

  *Your very own Assistant. Because you deserve it.*

  [![pipeline status](https://gitlab.com/waser-technologies/technologies/assistant/badges/main/pipeline.svg)](https://gitlab.com/waser-technologies/technologies/assistant/-/commits/main)
  [![Latest Release](https://gitlab.com/waser-technologies/technologies/assistant/-/badges/release.svg)](https://gitlab.com/waser-technologies/technologies/assistant/-/releases)
  [![PyPi Status](https://img.shields.io/pypi/v/assistant.svg)](https://pypi.org/project/assistant)

</div>

---

## What is Assistant?

**Assistant** is an AI-powered shell that blends a full [Xonsh](https://github.com/xonsh/xonsh) terminal with a multi-agent LLM system. Talk to it in natural language, run shell commands, browse the web, read and edit files — all from the same prompt.

Under the hood it uses a **multi-agent orchestrator**: a main agent receives your input and can delegate tasks to specialised agents (system operations, web research, etc.). Every agent, model, and provider is declared in a single TOML configuration file.

### Key Features

| Feature | Description |
|---|---|
| 🤖 **Multi-Agent Architecture** | Orchestrator + specialised agents (system, web researcher, memory, completer) |
| 🔌 **Multi-Provider Support** | Ollama, vLLM, LM Studio, OpenRouter, Google, NVIDIA, OpenAI — or any OpenAI-compatible API |
| 🛠️ **Rich Tool Set** | Shell execution, web search (SearXNG), read/edit/write files, read web pages |
| 🧙 **Setup Wizard** | Interactive wizard generates the TOML config on first launch |
| 🗂️ **TOML Configuration** | One file (`~/.assistant/config.toml`) to manage providers, models and agents |
| 💬 **Natural Language Shell** | Type plain English (or French, etc.) alongside regular commands — SyntaxError lines are auto-routed to NLP |
| 🧠 **Context Management** | Automatic conversation compaction with sliding window and summarisation |
| 🔍 **Web Search** | Integrated SearXNG web search with a dedicated research agent |
| 📁 **File Operations** | Agents can read, write and edit files directly |
| 🖥️ **TUI Passthrough** | Full-screen apps (vim, htop, less, etc.) run without hijacking |
| 🗣️ **Voice (optional)** | TTS via [say](https://gitlab.com/waser-technologies/technologies/say) and STT via [listen](https://gitlab.com/waser-technologies/technologies/listen) |
| ⚡ **Fast Startup** | Ultra-fast path for simple commands (< 200ms), lazy NLP init, deferred imports |
| 🎙️ **Streaming TTS** | Karaoke-style TTS playback with sentence-by-sentence streaming during response generation |

---

## Quick Start

### 1. Install

```bash
pip install assistant
```

<details>
<summary>Other installation methods</summary>

**From source (latest development):**

```bash
pip install -U git+https://gitlab.com/waser-technologies/technologies/assistant.git@v2
```

**From a local clone:**

```bash
git clone https://gitlab.com/waser-technologies/technologies/assistant.git
cd assistant
pip install -U .
```

**Arch Linux ([AUR](https://aur.archlinux.org/packages/python-assistant)):**

```bash
pacman -S python-assistant
```

</details>

### 2. Run the Configuration Wizard

On the first launch the wizard starts automatically. You can also re-run it at any time:

```bash
assistant config
```

The wizard asks you to choose:

1. **Provider** — Ollama *(local)*, vLLM *(local)*, LM Studio, OpenRouter, Google, NVIDIA, or OpenAI *(API)*.
2. **Endpoint** — API base URL (e.g. `http://localhost:11434/v1`).
3. **API Key** — leave the default for local providers, or enter your API key.
4. **Store in keyring** — optionally store the API key securely in your system keyring.
5. **Model** — model identifier (e.g. `qwen3.6:latest`, `gpt-4o`).
6. **Context length** — how many tokens the model supports.
7. **Reasoning** — enable/disable thinking traces.
8. **Web search** — enable SearXNG and configure its URL.

The configuration is saved to `~/.assistant/config.toml`.

### 3. Start Assistant

```bash
assistant
```

That's it — you're in. Type commands, ask questions, or mix both.

---

## Requirements

- **Python 3.9+**
- An **LLM backend** — one of:
  - [Ollama](https://ollama.com/) running locally *(recommended)*
  - [vLLM](https://docs.vllm.ai/) running locally
  - [LM Studio](https://lmstudio.ai/) running locally
  - Any OpenAI-compatible API (OpenAI, Together, Groq, OpenRouter, etc.)
- *(optional)* [SearXNG](https://docs.searxng.org/) instance for web search
- *(optional)* [`say`](https://gitlab.com/waser-technologies/technologies/say) for text-to-speech
- *(optional)* [`listen`](https://gitlab.com/waser-technologies/technologies/listen) for speech-to-text

> **Note:** Unlike v1, there is **no local model to download and host yourself**. Assistant connects to whichever LLM endpoint you configure. The RAM/VRAM requirements depend entirely on your chosen model and provider.

---

## Usage

### CLI options

```text
assistant --help
assistant --version
assistant config              # (re)run the configuration wizard
assistant -c "what time is it" # single query, then exit
assistant -n                   # skip the interactive intro message (warmup)
assistant Hello Assistant      # one-shot query
assistant                      # interactive mode
```

### Interactive Mode

<!-- [![](https://markdown-videos-api.jorgenkh.no/youtube/OAgLgq0aGhI)](https://youtu.be/OAgLgq0aGhI?si=8kIrj24neGD8sWec) -->
[![Loading interactive demo preview... (Click to open in full)](assets/assistant_v2_flashdemo.gif)](https://youtu.be/OAgLgq0aGhI?si=8kIrj24neGD8sWec)

```text
waser@host ~ 
❯ Hi Assistant.
Hello! How can I assist you today?
waser@host ~ 
❯ What is the current working directory?

ℹ Executing: echo $PWD
/home/waser

You are currently in your home directory.
waser@host ~ 
❯ How many moons does Saturn have?

ℹ Searching the Web for: How many moons does Saturn have?

Saturn has 146 confirmed moons as of 2024.
```

### Mix Shell and Natural Language

You can run any valid shell command or Python expression, and when Assistant
does not recognise a command it treats your input as a question:

```text
❯ ls -la
❯ echo $USER
❯ Can you count the files in this directory?

ℹ Executing: ls -1 | wc -l
20

There are 20 entries in the current directory.
```

Natural language with syntax errors (e.g. single quotes like `c'est quoi?`) is
automatically routed to the NLP agent instead of raising a Python `SyntaxError`.

### Multi-Agent Hand-offs

The Orchestrator can hand off tasks to specialised agents:

- **System agent** — runs shell commands, manages files, executes Python code in the shared xonsh session.
- **Web researcher** — searches the web via SearXNG, reads web pages, and produces reports with citations.
- **Memory agent** — stores and retrieves persistent information from the memory database.
- **Completer agent** — provides text completion suggestions for the CLI.

Hand-offs happen automatically based on the query context.

### Exit the Session

Type any exit-like command and Assistant will understand:

```text
❯ exit
❯ Q
❯ :q
❯ quit
❯ stop()
❯ terminate
❯ This conversation is over.
```

---

## Configuration

The configuration lives in `~/.assistant/config.toml`. Here is an example:

```toml
[provider.ollama]
endpoint = "http://localhost:11434/v1"
credential = "keyring:ollama"

[model.qwen]
id = "qwen3.6:latest"
name = "Qwen 3.6 (9B)"
provider = "ollama"
context_length = 256000
think = false
temperature = 0.1

[agent.orchestrator]
name = "Orchestrator"
model = "qwen"
description = "Main orchestrator; handles general conversations and delegates tasks."
instructions = "You are Assistant, a sentient artificial intelligence..."
tools = ["xonsh", "web_search"]
handoffs = ["system", "web", "memory"]

[agent.system]
name = "System"
model = "qwen"
description = "System shell agent for OS interaction."
tools = ["xonsh"]
handoffs = []

[agent.web]
name = "Web Researcher"
model = "qwen"
description = "Web research agent with search and page reading."
tools = ["web_search"]
handoffs = []

[agent.memory]
name = "Memory"
model = "qwen"
description = "Memory management agent for persistent storage."
tools = ["memory_search", "memory_add"]
handoffs = []

[web_search]
enabled = true
searxng_url = "http://localhost:8888"

[completion]
enabled = true
wait_timeout = 1
request_timeout = [10.0, 300.0]

[execution]
max_turns = 50
temperature = 0.1
max_command_output_length = 10000
command_timeout = 180

[memory]
enabled = false
max_entries = 100

[context]
compaction_threshold = 0.8
sliding_window_first = 2
sliding_window_last = 8
use_summarization = true
```

### Adding a New Provider

Just add a new section under `[provider]`:

```toml
[provider.openai]
endpoint = "https://api.openai.com/v1"
credential = "keyring:openai"

[model.gpt4o]
id = "gpt-4o"
name = "GPT-4o"
provider = "openai"
context_length = 128000
```

Then reference `model = "gpt4o"` in any agent.

### Credential Storage

Credentials are resolved in this order:

1. **Environment variable** — `ASSISTANT_{PROVIDER}_API_KEY` (e.g., `ASSISTANT_OPENAI_API_KEY`)
2. **System keyring** — if credential starts with `keyring:`, the value after `keyring:` is used as the keyring service name
3. **OpenAI fallback** — for OpenAI provider, also checks `OPENAI_API_KEY` standard env var
4. **Plain text** — last resort (not recommended)

To store credentials securely in your system keyring, use `assistant config` and select "Store in keyring" when prompted, or manually:

```python
import keyring
keyring.set_password("assistant", "openai", "sk-...")
```

---

## Available Tools

| Tool | Description |
|---|---|
| `xonsh` | Execute shell commands or Python code in the shared xonsh session |
| `web_search` | Search the web via SearXNG |
| `read_webpage` | Fetch and extract readable text from a URL |
| `read_file` | Read file contents with optional line range |
| `write_file` | Create or overwrite files |
| `edit_file` | Find-and-replace text in existing files |
| `memory_search` | Search persistent memory *(when memory is enabled)* |
| `memory_add` | Add entries to persistent memory *(when memory is enabled)* |

---

## Using Voice

### Text-To-Speech

Install [`say`](https://gitlab.com/waser-technologies/technologies/say) and make sure the service is running:

```bash
assistant say Hello World and welcome to everyone.
```

Assistant supports **streaming TTS** — sentences are spoken as they arrive during
the LLM response, with a karaoke-style display showing which sentence is being
pronounced. Press **Ctrl+C** to stop TTS playback at any time.

### Speech-To-Text

Install [`listen`](https://gitlab.com/waser-technologies/technologies/listen) and enable the listen services.

### Keyboard Shortcuts

| Shortcut | Action |
|---|---|
| **Ctrl+O** | Toggle TTS on/off (enable or disable text-to-speech) |
| **Ctrl+Q** | Toggle STT on/off (enable or disable speech-to-text) |
| **Ctrl+Space** | Trigger one-shot speech recognition (listen for a sentence) |
| **Ctrl+C** | Stop TTS playback immediately |

> **Note:** These shortcuts require a terminal that supports the Kitty keyboard protocol or xterm `modifyOtherKeys` mode (enabled automatically by Assistant).

### Voice Configuration

Voice settings are stored in the `voice` section of `~/.assistant/config.toml`:

```toml
[voice]
tts_enabled = true
stt_enabled = true
tts_key = "Ctrl+O"
stt_key = "Ctrl+Q"
listen_key = "Ctrl+Space"
```

You can configure voice settings in three ways:

1. **Configuration wizard** — `config` → "Voice Settings"
2. **Direct CLI** — `config voice <key> <value>` (e.g., `config voice tts_enabled false`)
3. **Manual edit** — edit `~/.assistant/config.toml` directly

Toggle shortcuts (Ctrl+O, Ctrl+Q) update the config automatically when pressed, so the runtime state persists across sessions.

---

## Use Assistant as Your Default Shell

> **This is not recommended in beta!**

You should be able to add the location of `assistant` at the end of `/etc/shells`. You'll then be able to set `Assistant` as your default shell using `chsh`.

```bash
sudo sh -c 'w=$(which assistant); echo $w >> /etc/shells'
chsh -s $(which assistant)
```

Log out and when you come back, `Assistant` should be your default shell.

---

## Performance Optimizations

Assistant includes several performance optimizations:

- **Lazy NLP init**: The LLM interface is deferred until first use, avoiding ~4s warmup on startup
- **Deferred imports**: Heavy ASR/TTS dependencies (numpy, scipy, pyaudio) are only loaded when voice features are actually used

---

## Contributions

Want to improve the project? Check out [`CONTRIBUTING.md`](CONTRIBUTING.md).

---

## Credits

Thanks to all the projects that make this possible:

- [Xonsh](https://github.com/xonsh/xonsh) — the best snail in the jungle
- [Rich](https://github.com/Textualize/rich) and [Halo](https://github.com/manrajgrover/halo) — beautiful terminal output
- And many, many more.
