Metadata-Version: 2.4
Name: keycall
Version: 0.2.0
Summary: One consistent interface for validating AI-provider API keys, listing and filtering their models, and making normalized calls.
Project-URL: Homepage, https://github.com/shehuphd/keycall
Project-URL: Documentation, https://github.com/shehuphd/keycall/blob/main/USAGE.md
Project-URL: Changelog, https://github.com/shehuphd/keycall/blob/main/CHANGELOG.md
Project-URL: Issues, https://github.com/shehuphd/keycall/issues
Project-URL: Source, https://github.com/shehuphd/keycall
Author: Mo Shehu
License-Expression: AGPL-3.0-or-later
License-File: LICENSE
Keywords: anthropic,api-key-validation,api-keys,gemini,llm,model-picker,openai
Classifier: Development Status :: 3 - Alpha
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
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 :: Scientific/Engineering :: Artificial Intelligence
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Typing :: Typed
Requires-Python: >=3.10
Requires-Dist: httpx>=0.27
Requires-Dist: tomli>=2.0; python_version < '3.11'
Requires-Dist: typing-extensions>=4.0; python_version < '3.11'
Provides-Extra: dev
Requires-Dist: mypy>=1.10; extra == 'dev'
Requires-Dist: pytest>=8; extra == 'dev'
Requires-Dist: ruff>=0.5; extra == 'dev'
Requires-Dist: traceact>=0.13; extra == 'dev'
Provides-Extra: traceact
Requires-Dist: traceact>=0.13; extra == 'traceact'
Description-Content-Type: text/markdown

# KeyCall

One consistent interface for validating AI-provider API keys, listing and filtering the models available to them, and making normalized calls, so every product stops rebuilding the same model-picker filters and provider wrappers.

**Status: early release (0.2.0).** Key validation, model listing and filtering,
text generation, and native web search with normalized citations all work and
are live-verified against every supported provider. Streaming, structured
output, general tool calling, and non-text modalities are not implemented yet.
The API is settled but may still shift before 1.0.

Docs: [USAGE.md](USAGE.md) for the full API and CLI reference · [CHANGELOG.md](CHANGELOG.md) for version history.

## Quick start

```python
from keycall import KeyCall, Message, ModelCategory, TextInput

with KeyCall(provider="openai", api_key=secret) as client:
    discovery = client.list_models(categories={ModelCategory.TEXT_GENERATION})

    result = client.generate_text(
        model=discovery.models[0].id,
        messages=[Message(role="user", content=[TextInput(text="Hello.")])],
    )

print(result.text)
print(result.usage.total_tokens)
print(result.round_trip_duration_ms)
```

- **Explicit provider, always.** KeyCall never guesses which vendor issued a key and never sends a credential to more than the one provider you name.
- **No credential storage.** Keys live in memory for the client's lifetime, wrapped in a redacting type that keeps them out of reprs, logs, traces, exceptions, and pickles. Your app decides how to store them.
- **Model filtering built in.** Text-generation models by default; embeddings, image, audio, and other categories on request; unknown models never silently enter the default picker.
- **Typed errors.** Invalid key, rate limit, provider outage, timeout, and malformed response are distinguishable, never collapsed into "invalid key."
- **Web search with citations.** `web_search=True` turns on the provider's native search tool (OpenAI, Anthropic, Gemini; Perplexity always searches) and returns sources normalized to one `Citation` shape.
- **Hardened transport.** TLS always verified, redirects refused, response sizes capped, SSRF and DNS-rebinding guards on custom endpoints, and generation is never silently retried.

## Provider support

Live-verified 2026-08-05 (one model-list call plus one bounded generation per provider):

| Provider | Protocol | Listing | Generation |
|---|---|---|---|
| OpenAI | openai | verified | verified |
| Anthropic | anthropic | verified | verified |
| Google Gemini | gemini | verified | verified |
| DeepSeek | openai-compatible | verified | verified |
| Perplexity | openai-compatible | verified | verified |
| Moonshot/Kimi | openai-compatible | verified | verified |
| Custom endpoint (explicit `base_url`) | openai-compatible | fixtures only | fixtures only |

Two provider quirks worth knowing, both handled:

**Gemini** keeps retired models in its list endpoint (`gemini-2.5-flash` returns
"no longer available to new users") with no lifecycle field to pre-filter on,
and meters quota per model and tier, so one model's 429 says nothing about the
next. Its `supportedGenerationMethods` is also a transport signal rather than a
modality claim: TTS variants advertise `generateContent` and then refuse a text
response, so KeyCall lets a distinctive identifier modality outrank it.

**Perplexity**'s `GET /v1/models` is scoped to the Agent API and returns
vendor-prefixed router models (`anthropic/...`, `perplexity/sonar`) that the
Sonar route rejects. Sonar's own models are not API-discoverable, so KeyCall
maintains them in its catalog and uses the list call purely as a credential
check.

Because of quirks like these, `keycall verify --generate` walks the filtered
models in provider order and prints the outcome of every attempt until one
succeeds, so drift stays visible rather than being masked by a silent retry.

## Local viewer

```bash
keycall view --source ./keys.toml
```

Opens a token-protected local web app over your loaded targets: a dashboard
with live key checks, a sortable model browser with category filters, a
playground for real generation calls (web search included), and a verify
report. Keys never leave the server process and never appear in the browser.

Or double-click / run a launcher from a fresh clone — it creates the venv,
installs KeyCall, finds your key file, and starts the viewer:
`launch.command` (macOS), `launch.sh` (Linux/macOS), `launch.bat` (Windows).

## Verifying keys from the command line

```bash
keycall verify --source ./keys.toml
```

```bash
keycall verify --source ./keys.toml --generate
```

`--generate` also makes one small bounded call per target. Sources can be TXT,
JSON, or TOML, an explicit `env:VAR_NAME` reference, or an interactive prompt.
See `keycall-test-keys.example.toml` for the format and
[USAGE.md](USAGE.md#the-verify-cli) for the full reference. Keys never appear
in output, and KeyCall never writes to or deletes your credential file.

## Installation

```bash
pip install keycall
```

## Development

```bash
pip install -e ".[dev]"
pytest
```

## Author

Built by [Mo Shehu](https://mohammedshehu.com).

## License

AGPL-3.0-or-later. See [LICENSE](LICENSE).
