swink-agent 0.10.0

Core scaffolding for running LLM-powered agentic loops
# Testing Setup

Step-by-step guide to get the project running against live LLM APIs.

## 1. Install Rust

Requires **Rust 1.95+** (edition 2024).

```bash
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
rustup update stable
rustc --version   # should print 1.95.0 or later
```

## 2. Build the Workspace

```bash
cargo build --workspace
```

This compiles all workspace crates: core library, adapters, local-llm, memory, eval, and TUI. First build pulls dependencies and takes a few minutes.

Workspace builds need LLVM/libclang (for `swink-agent-local-llm`) — see [getting_started.md](getting_started.md#build) if the build reports `Unable to find libclang`.

## 3. Run the Local Validation Gate

Verify the same local validation sequence required for PRs before connecting to live APIs:

```bash
just validate
```

`cargo test --workspace` is the default-feature workspace test baseline, not
the full local gate. `just validate` is the canonical source of truth and also
runs the `testkit` workspace tests, core plugin regression tests, no-default
feature sentinels, formatting, clippy, build, and package preflight. `just
check` is a backward-compatible alias for the same gate.

These validation commands intentionally do not load `.env`; they should not
inherit provider API keys or cloud credentials. Live-provider tests load
credentials from the environment only when you run those tests explicitly.

## 3a. Run Local Coverage

The repository includes a root `tarpaulin.toml` for local coverage runs. Install
`cargo-tarpaulin` once, then run:

```bash
cargo install cargo-tarpaulin
just coverage
```

Reports are written under `target/tarpaulin/`. Coverage is not part of
`just validate`; run it explicitly when working on coverage gaps or test
hardening.

## 4. Get API Keys

You need at least one provider. For remote providers, create a key in the console and set the env var(s) in `.env`:

| Provider | Console | Env var(s) |
|---|---|---|
| Anthropic | https://console.anthropic.com/ | `ANTHROPIC_API_KEY` |
| OpenAI | https://platform.openai.com/api-keys | `OPENAI_API_KEY` |
| Google Gemini | https://aistudio.google.com/ | `GEMINI_API_KEY` |
| Azure OpenAI | https://portal.azure.com/ | `AZURE_API_KEY`, `AZURE_BASE_URL` (deployment endpoint) |
| xAI (Grok) | https://console.x.ai/ | `XAI_API_KEY` |
| Mistral | https://console.mistral.ai/ | `MISTRAL_API_KEY` |
| AWS Bedrock | — (AWS credentials) | `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, `AWS_REGION`, optionally `AWS_SESSION_TOKEN` |

Bedrock: set `AWS_REGION` to a region with Bedrock access (e.g. `us-east-1`) and ensure your IAM role has `bedrock:InvokeModelWithResponseStream` permission.

### Ollama (Local, Free)

No API key, no account, no cost. Install and pull a model:

```bash
# macOS
brew install ollama

# Or download from https://ollama.ai/download

# Start the server
ollama serve

# Pull a model (default: llama3.2, ~2GB)
ollama pull llama3.2
```

### Local On-Device (swink-agent-local-llm)

No API key needed. Models are lazily downloaded from HuggingFace on first use and cached in `~/.cache/huggingface/hub/`:

- **SmolLM3-3B** (GGUF Q4_K_M, ~1.92 GB) — text generation, tool use, reasoning
- **EmbeddingGemma-300M** (<200 MB) — text vectorization/embeddings

Context is capped at 8192 tokens by default; override with the `LOCAL_CONTEXT_LENGTH` env var. First run downloads ~2.1 GB of model weights.

## 5. Configure Environment

```bash
cp .env.example .env
```

Edit `.env` and uncomment/fill in the keys for the providers you set up:

```bash
# For Anthropic testing:
ANTHROPIC_API_KEY=sk-ant-your-key-here

# For OpenAI testing:
OPENAI_API_KEY=sk-your-key-here

# For Ollama (usually no changes needed):
# OLLAMA_HOST=http://localhost:11434
# OLLAMA_MODEL=llama3.2
```

Leave variables commented out to skip that provider. The TUI auto-selects by priority — see the [provider priority table](getting_started.md#configure-a-provider).

## 6. Launch the TUI

```bash
cargo run -p swink-agent-tui
```

The TUI auto-loads `.env` via dotenvy — no need to source it manually. If no API keys are found (env or keychain), the first-run wizard prompts for provider selection and key entry.

The development `justfile` does not load `.env` globally. `just validate`,
`just check`, and `just package-preflight` therefore run without provider
secrets unless you exported them in your shell.

## 7. Verify Each Provider

Once the TUI is running, test each configured provider:

**Check current provider:**
```
#info
```

**Cycle available models in the TUI:**
```
Press F4
```
Note: `F4` cycles the models currently available to the TUI and applies the selected model on the next prompt. Use `#info` to confirm the active model. To test a different provider, update `.env` and restart the TUI.

**Test basic conversation:**
```
What is 2 + 2?
```

**Test tool execution (built-in bash tool):**
```
List the files in the current directory
```

**Test thinking mode (Anthropic, Google Gemini, Ollama with supported models):**
```
/thinking medium
Explain why the sky is blue
```
Thinking mode availability by provider:

| Provider | Thinking support |
|---|---|
| Anthropic | Full (`/thinking` levels: minimal, low, medium, high, extra-high) |
| Google Gemini | Supported on deep-think models |
| Ollama | Supported on models that emit `<think>` tags (e.g. DeepSeek) |
| Local (SmolLM3) | Emits `<think>` tags, parsed into thinking events |
| OpenAI, Azure, xAI, Mistral, Bedrock | Not supported |

## 8. Test Scenarios Checklist

| Scenario | What to verify |
|---|---|
| Basic chat | Assistant responds, tokens/cost update in status bar |
| Multi-turn | Context is preserved across messages |
| Tool use | Agent calls bash/read_file/write_file, tool panel shows spinner then result |
| Streaming | Text appears incrementally, not all at once |
| Thinking | Dimmed thinking section appears (Anthropic with `/thinking` enabled) |
| Abort | Press `Esc` during generation — stops cleanly |
| Long output | Conversation scrolls, manual scroll with arrow keys works |
| Session save/load | `#save` then `#load <id>` restores conversation |
| Error recovery | Send a prompt that exceeds context window — agent should recover |
| Model switching | Press `F4` to cycle available models; `#info` confirms the active model |

## 9. Logs

If something goes wrong, check the log file:

```bash
cat ~/.config/swink-agent/logs/swink-agent.log
```

Logs are daily rolling files with tracing output. Look for `ERROR` or `WARN` entries.

## 10. Cleanup

API keys stored in the OS keychain persist across sessions. To remove them:

```bash
# macOS — delete from Keychain Access app, search "swink-agent"
# Or from inside the TUI:
#keys            # see what's stored
```

To remove local config and sessions:

```bash
rm -rf ~/.config/swink-agent/
```