Metadata-Version: 2.4
Name: ifs-rag-assistant-cli
Version: 2.2.2
Summary: Command-line interface for IFS RAG Assistant Q&A system
Home-page: https://github.com/maricaantonacci/ifs-rag-assistant-cli
Author: Marica Antonacci
Author-email: Marica Antonacci <marica.antonacci@ecmwf.int>
License: MIT
Project-URL: Homepage, https://github.com/maricaantonacci/ifs-rag-assistant-cli
Project-URL: Repository, https://github.com/maricaantonacci/ifs-rag-assistant-cli
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
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
Requires-Python: >=3.9
Description-Content-Type: text/markdown
Requires-Dist: typer[all]>=0.9.0
Requires-Dist: requests>=2.28.0
Requires-Dist: pyyaml>=6.0
Requires-Dist: rich>=10.0.0
Dynamic: author
Dynamic: home-page
Dynamic: requires-python

# IFS RAG Assistant CLI

[![Tests](https://github.com/maricaantonacci/ifs-rag-assistant-cli/actions/workflows/test.yml/badge.svg)](https://github.com/maricaantonacci/ifs-rag-assistant-cli/actions/workflows/test.yml)
[![Security](https://github.com/maricaantonacci/ifs-rag-assistant-cli/actions/workflows/security.yml/badge.svg)](https://github.com/maricaantonacci/ifs-rag-assistant-cli/actions/workflows/security.yml)
[![Semantic Release](https://github.com/maricaantonacci/ifs-rag-assistant-cli/actions/workflows/release.yml/badge.svg)](https://github.com/maricaantonacci/ifs-rag-assistant-cli/actions/workflows/release.yml)
[![Python Version](https://img.shields.io/badge/python-3.9%2B-blue.svg)](https://www.python.org/downloads/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

Command-line interface for the IFS RAG Assistant (Retrieval-Augmented Generation) Q&A system.

## Features

- 🔐 **OAuth 2.0 Device Flow Authentication** - Secure authentication using Keycloak
- 💬 **Interactive Chat Mode** - Conversational interface with context preservation
- 🔍 **Search** - Search the Fortran codebase index
- 📚 **Citations** - View source code references with line numbers
- 👍 **Interactive Feedback** - Provide thumbs up/down feedback on answers
- 🎨 **Rich Output** - Beautiful terminal output with tables and formatting
- 💾 **Session Caching** - Automatic session management for seamless use

## Installation

### Prerequisites

- Python 3.9 or higher

### Install from PyPI (Recommended)

You can install the CLI directly from PyPI:

```bash
pip install ifs-rag-assistant-cli
```

Check installation:

```bash
ifs-rag-assistant-cli --version
```

### Should I create a virtual environment first?

Short answer: not strictly required, but strongly recommended.

- Use a virtual environment if you want to avoid dependency conflicts with other Python tools.
- Skip it only if you already manage Python globally in another way.

Recommended setup:

```bash
python -m venv .venv
source .venv/bin/activate
pip install --upgrade pip
pip install ifs-rag-assistant-cli
```

### Install from source

```bash
# Clone the repository
git clone https://github.com/maricaantonacci/ifs-rag-assistant-cli.git
cd ifs-rag-assistant-cli

# Install the package
pip install .
```

For development (editable install):

```bash
pip install -e .
```

## Quick Start

### For ECMWF Users

If you're using the ECMWF production environment, setup is simple:

1. **Initialize configuration** (pre-configured for ECMWF):

   ```bash
   ifs-rag-assistant-cli init
   ```

2. **Start using the CLI**:

   ```bash
   ifs-rag-assistant-cli chat
   ```

   On first use, you'll be prompted to authenticate via OAuth Device Flow.

That's it! The configuration is already set up for ECMWF's production environment.

### For Custom Environments

1. **Initialize and customize configuration**:

   ```bash
   ifs-rag-assistant-cli init
   # Edit ~/.ifs-rag-assistant-cli/config.yaml to match your setup
   ```

   Or manually create the config:

   ```bash
   mkdir -p ~/.ifs-rag-assistant-cli
   cp config.yaml.example ~/.ifs-rag-assistant-cli/config.yaml
   # Edit ~/.ifs-rag-assistant-cli/config.yaml as needed
   ```

2. **Check the backend is running**:

   ```bash
   ifs-rag-assistant-cli health
   ```

3. **Start chatting**:

   ```bash
   ifs-rag-assistant-cli chat
   ```

## Configuration

The CLI loads configuration from multiple sources in this priority order:

1. Explicit `--config` flag
2. `~/.ifs-rag-assistant-cli/config.yaml` (user config)
3. `./config.yaml` (current directory)
4. Environment variables
5. Default values

### Configuration File

The easiest way to create a configuration file is using the `init` command:

```bash
ifs-rag-assistant-cli init
```

This creates `~/.ifs-rag-assistant-cli/config.yaml` with the following defaults for ECMWF production:

```yaml
# Backend API (ECMWF Production)
api_root: "https://ifs-assistant-api.apps.ifs-llm.ewcloud.host"
timeout: 300

# OAuth configuration (ECMWF Production)
oauth_device_flow_mode: "custom_wrapper"
oauth_custom_wrapper_url: "https://accounts.ecmwf.int/ecmwf-token-generator"
keycloak_client_id: "ifs-rag"

# Session cache
cache_dir: "~/.ifs-rag-assistant-cli"
verbose: false
```

For **local development** or **custom environments**, edit the file to use standard Keycloak:

```yaml
api_root: "http://localhost:8000"
timeout: 300
oauth_device_flow_mode: "standard"
keycloak_server_url: "http://localhost:8080"
keycloak_realm: "master"
keycloak_client_id: "ifs-rag"
auth_mode: "oauth"
cache_dir: "~/.ifs-rag-assistant-cli"
verbose: true
```

For **local development without authentication**, you can disable OAuth:

```yaml
api_root: "http://localhost:8000"
timeout: 300
auth_mode: "disabled"
cache_dir: "~/.ifs-rag-assistant-cli"
verbose: true
```

> **Security note:** `auth_mode: "disabled"` is intended for local development only. The CLI will reject this mode when `api_root` is not localhost/loopback.

### Configuration Parameters

| Parameter | Description | Required | Notes |
|-----------|-------------|----------|-------|
| `api_root` | Backend API base URL | Mandatory | ECMWF production URL or local dev server |
| `timeout` | Request timeout in seconds | Optional | Default: `300.0` (5 minutes) |
| `oauth_device_flow_mode` | OAuth mode: `standard` or `custom_wrapper` | Optional | Default: `custom_wrapper` (ECMWF) |
| `oauth_custom_wrapper_url` | Custom wrapper API URL | Mandatory* | Required for `custom_wrapper` mode |
| `keycloak_client_id` | OAuth client ID | Mandatory | Default: `ifs-rag`, used for both modes |
| `keycloak_server_url` | Keycloak server base URL | Optional* | Required only for `standard` OAuth mode |
| `keycloak_realm` | Keycloak realm name | Optional* | Required only for `standard` OAuth mode |
| `auth_mode` | Authentication mode: `oauth` or `disabled` | Optional | Default: `oauth`; `disabled` allowed only for localhost/loopback `api_root` |
| `cache_dir` | Session cache directory | Optional | Default: `~/.ifs-rag-assistant-cli` |

> **Note on OAuth Modes:**  
> The `standard` mode implements the OAuth 2.0 Device Flow (RFC 8628) for use with public clients when available. However, some environments like ECMWF enforce policies that prohibit public clients. In such cases, the `custom_wrapper` mode uses a specialized wrapper around the Keycloak server that enables device flow authentication while issuing offline tokens (refresh tokens) for users, maintaining security without requiring public client support.

### Environment Variables

```bash
export IFS_RAG_API_ROOT="http://localhost:8000"
export IFS_RAG_TIMEOUT="30"
export IFS_RAG_KEYCLOAK_SERVER_URL="http://localhost:8080"
export IFS_RAG_KEYCLOAK_REALM="master"
export IFS_RAG_KEYCLOAK_CLIENT_ID="ifs-rag"
export IFS_RAG_CACHE_DIR="~/.ifs-rag-assistant-cli"
export IFS_RAG_OAUTH_DEVICE_FLOW_MODE="standard"
export IFS_RAG_AUTH_MODE="oauth"
```

## Usage

### Available Commands

```bash
ifs-rag-assistant-cli --help
```

**Commands:**
- `init` - Initialize configuration file (pre-configured for ECMWF)
- `chat` - Start an interactive chat session
- `ask` - Ask a single question
- `search` - Search the RAG index
- `logout` - Logout and clear cached session
- `health` - Check backend health status
- `models` - List available models from the backend
- `usage` - Display usage guide from the backend
- `version` - Display version information (also: `--version`, `-v`)

### Interactive Chat

Start a conversational session with automatic feedback prompts:

```bash
ifs-rag-assistant-cli chat
```

Resume a previous conversation:

```bash
ifs-rag-assistant-cli chat --resume <conversation-id>
```

Plain text output (for copy-paste):

```bash
ifs-rag-assistant-cli chat --plain
```

**Chat Features:**
- Ask multiple questions in sequence
- Conversation context is maintained
- Optional feedback after each answer (thumbs up/down with comments)
- Type `exit` or `quit` to end the session

### Single Question

Ask a single question:

```bash
ifs-rag-assistant-cli ask "What is RRTM?"
```

Plain text output:

```bash
ifs-rag-assistant-cli ask "Explain subroutine X" --plain
```

**Ask Features:**
- Get an immediate answer with citations
- Optional interactive feedback prompt
- Shows conversation ID to continue in chat mode

### Search

Search the codebase index:

```bash
ifs-rag-assistant-cli search "subroutine"
ifs-rag-assistant-cli search "RRTM radiative transfer"
```

Returns relevant code citations with file paths, line numbers, and symbol types.

### Models

List available LLM models:

```bash
ifs-rag-assistant-cli models
```

### Usage Guide

View the backend's usage guide:

```bash
ifs-rag-assistant-cli usage
```

Raw markdown output:

```bash
ifs-rag-assistant-cli usage --raw
```

### Authentication

Logout and clear cached session:

```bash
ifs-rag-assistant-cli logout
```

### Initialize Configuration

Create a configuration file pre-configured for ECMWF production:

```bash
ifs-rag-assistant-cli init
```

The configuration file will be created at `~/.ifs-rag-assistant-cli/config.yaml`.

**For ECMWF users:**
- No manual editing required - works out of the box
- Backend endpoint: ECMWF IFS RAG Assistant production service
- OAuth: Pre-configured with ECMWF's authentication system

**For other environments:**
- Edit the generated file to match your setup
- Update both backend endpoint and OAuth settings
- See comments in the file for guidance

Overwrite an existing configuration:

```bash
ifs-rag-assistant-cli init --force
```

### Health Check

Check backend status:

```bash
ifs-rag-assistant-cli health
```

## Interactive Feedback

After receiving an answer from the `ask` or `chat` commands, you'll be prompted to provide optional feedback:

```
💬 Would you like to provide feedback for this answer? [Y/n]:
```

**Note:** The default is **Yes** - just press Enter to provide feedback, or type `n` to skip.

If you choose to provide feedback:

1. **Select a vote:**
   - 1 = 👍 Up (helpful)
   - 2 = 👎 Down (not helpful)
   - 3 = Skip

2. **Optionally add a comment** explaining your feedback

Your feedback helps improve the RAG system's quality and accuracy.

## OAuth Authentication

The CLI uses OAuth 2.0 Device Flow for authentication. On first use:

1. You'll see a device code (e.g., `ABCD-EFGH`)
2. Visit the verification URL in your browser
3. Enter the device code
4. Log in with your credentials
5. The CLI will automatically continue once authorized

Sessions are cached in `~/.ifs-rag-assistant-cli/session` and valid for 24 hours.

### OAuth Modes

#### Standard Mode (RFC 8628)

Works with standard Keycloak OIDC endpoints:

```yaml
oauth_device_flow_mode: "standard"
keycloak_server_url: "http://localhost:8080"
keycloak_realm: "master"
```

#### Custom Wrapper Mode

For custom OAuth wrapper APIs (e.g., ECMWF):

```yaml
oauth_device_flow_mode: "custom_wrapper"
oauth_custom_wrapper_url: "https://api.example.com"
```

## Development

### Project Structure

```
ifs-rag-assistant-cli/
├── ifs_rag_assistant_cli/
│   ├── __init__.py
│   ├── auth_client.py      # Authentication client
│   ├── backend_client.py   # Backend API client
│   ├── cli.py              # CLI commands
│   ├── config.py           # Configuration management
│   ├── models.py           # Data models
│   ├── oauth.py            # OAuth Device Flow
│   └── session.py          # Session management
├── setup.py
├── requirements.txt
├── config.yaml.example
└── README.md
```

### Contributing

We use conventional commits and semantic versioning for automated releases. See [CONTRIBUTING.md](CONTRIBUTING.md) for detailed guidelines.

#### Commit Convention

Follow the [Conventional Commits](https://www.conventionalcommits.org/) specification:

```
<type>(<scope>): <description>

[optional body]

[optional footer(s)]
```

**Types:**
- `feat`: New feature (triggers minor version bump)
- `fix`: Bug fix (triggers patch version bump)
- `docs`: Documentation changes
- `style`: Code style changes (formatting, etc.)
- `refactor`: Code refactoring
- `perf`: Performance improvements (triggers patch version bump)
- `test`: Adding or updating tests
- `build`: Build system changes
- `ci`: CI/CD changes
- `chore`: Other changes

**Examples:**
```
feat(cli): add support for streaming responses
fix(auth): resolve token refresh issue
docs(readme): update installation instructions
```

### CI/CD Workflows

The project uses GitHub Actions for automated testing, security checks, and releases:

#### 🔒 Security Checks (`.github/workflows/security.yml`)
- Runs on push, pull requests, and weekly schedule
- **Bandit**: Python security vulnerability scanner (fails on HIGH severity)
- **pip-audit**: Official PyPA dependency vulnerability checker (fails on any CVE)

#### 🚀 Semantic Release (`.github/workflows/release.yml`)
- Automatically triggered on push to `main` branch
- Analyzes commit messages to determine version bump
- Updates `CHANGELOG.md`
- Creates GitHub releases with release notes
- Publishes the package to PyPI (requires repository secret `PYPI_TOKEN`)

#### ✅ Tests (`.github/workflows/test.yml`)
- Tests across Python 3.9, 3.10, 3.11, and 3.12
- Linting with `ruff`
- Type checking with `mypy`
- CLI installation verification

#### 🔄 Dependabot
- Automated dependency updates
- Weekly schedule for Python and GitHub Actions dependencies

## Requirements

- Python >= 3.9
- Access to an IFS RAG Assistant backend
  - ECMWF users: Backend is already deployed and configured
  - Custom setups: Requires a running backend instance
- OAuth authentication provider
  - ECMWF users: Authentication is pre-configured
  - Custom setups: Keycloak server or compatible OAuth provider

## License

MIT License

## Support

For issues and questions, please open an issue on GitHub.
