# pi-provider-freellmapi

A [pi](https://pi.dev) extension that registers the **FreeLLM API** gateway
([freeapi.n.cofire.cn](https://freeapi.n.cofire.cn)) as three pi providers —
`openai-completions`, `openai-responses`, and `anthropic-messages` — with
automatic model discovery and custom tools for non-chat endpoints.

It only exposes models your API key can actually use (the gateway reports ~250
models, but most are `available: false` for a free key — this extension filters
those out), and it reads each model's real context window and reasoning/vision
capabilities.

## Install

```bash
pi install npm:pi-provider-freellmapi
```

## Providers

The extension registers three pi providers sharing the same model list from the
gateway so you can pick whichever API shape suits your use case:

| Provider | API type | Endpoint |
|----------|----------|----------|
| `freellmapi` | `openai-completions` | `/v1/chat/completions` |
| `freellmapi-responses` | `openai-responses` | `/v1/responses` |
| `freellmapi-anthropic` | `anthropic-messages` | `/v1/messages` |

Select a provider in the TUI with `/model`, or from the CLI:

```bash
pi --provider freellmapi --model auto
pi --provider freellmapi-responses --model auto
pi --provider freellmapi-anthropic --model auto
```

Disable extra providers via the `endpoints` config (see below).

## Configure

Copy the example config to `~/.pi/agent/freellmapi.json` and fill in your key:

```bash
cp "$(pi config-dir 2>/dev/null || echo ~/.pi/agent)/freellmapi.json" freellmapi.example.json
# or just:
mkdir -p ~/.pi/agent
cp freellmapi.example.json ~/.pi/agent/freellmapi.json
```

```json
{
  "name": "freellmapi",
  "label": "FreeLLM API",
  "baseUrl": "https://freeapi.n.cofire.cn",
  "apiKey": "$FREELLM_API_KEY",
  "fetchModels": true,
  "contextWindow": 131072,
  "maxTokens": 16384,
  "compat": { "supportsDeveloperRole": false },
  "endpoints": {
    "embeddings":     { "enabled": true, "model": "auto" },
    "images":         { "enabled": true, "model": "auto" },
    "videos":         { "enabled": true, "model": "inkling" },
    "speech":         { "enabled": true, "model": "auto" },
    "transcriptions": { "enabled": true, "model": "whisper-1" },
    "responses":      { "enabled": true },
    "anthropic":      { "enabled": true }
  }
}
```

The `apiKey` supports pi's value syntax: a literal, `$ENV_VAR`, `${ENV_VAR}`,
or `!command`. You can also skip the config file entirely and set either env var.

Environment variables (fallback chain, config file wins):

| Variable | Purpose |
|----------|---------|
| `FREELLM_API_KEY` | API key |
| `FREELLM_API_BASE_URL` | Override the base URL (default: `https://freeapi.n.cofire.cn`) |
| `PI_FREELLMAPI_CONFIG` | Path to config JSON (default: `~/.pi/agent/freellmapi.json`) |

- Set `"fetchModels": false` to use only the static `models` list.
- Set `"endpoints": { "responses": false }` to disable a provider/tool.

## Endpoint tools

In addition to the chat providers, the extension registers custom tools that
wrap the gateway's other OpenAI-compatible endpoints. They are enabled by
default; set `"enabled": false` (`"endpoints": { "images": false }`) or set a
default `model` per endpoint to customize them.

| Tool | Endpoint | What it does |
|------|----------|--------------|
| `freellm_embed` | `POST /embeddings` | Generates embeddings; writes JSON to a file |
| `freellm_image` | `POST /images/generations` | Generates image(s), returned inline |
| `freellm_video` | `POST /videos/generations` | Generates a video, polls the task, downloads the file |
| `freellm_speech` | `POST /audio/speech` | Synthesizes speech, writes audio to a file |
| `freellm_transcribe` | `POST /audio/transcriptions` | Transcribes a local path or URL, returns text |

Each tool accepts an optional `model` argument. When omitted, the extension
picks a default from (in priority order): the endpoint's `model` config, model
ids discovered from `{baseUrl}/models` matching that endpoint, or a conventional
OpenAI id (e.g. `auto` for embeddings/images/speech, `inkling`, `whisper-1`).
If the gateway rejects a default, set the endpoint's `model` in config.

Files written by the tools land in the session working directory with
`freellm-*` names, or an `outputFile` path you pass to the tool.

## Config reference

| Field | Default | Description |
|-------|---------|-------------|
| `name` | `freellmapi` | Provider id (`--provider <name>`) |
| `label` | `FreeLLM API` | Display label shown in `/model` |
| `baseUrl` | `https://freeapi.n.cofire.cn` | Base URL (auto-appends `/v1`) |
| `apiKey` | `$FREELLM_API_KEY` | API key (literal / env / command) |
| `fetchModels` | `true` | Discover models from `{baseUrl}/models` |
| `contextWindow` | `131072` | Fallback context window per model |
| `maxTokens` | `16384` | Fallback max output tokens |
| `compat` | `{"supportsDeveloperRole":false}` | Provider compatibility flags |
| `models` | `[]` | Static models (override discovered models by id) |
| `headers` | `{}` | Extra headers merged into every tool request |
| `endpoints` | all enabled | Per-endpoint `enabled` flag and default `model` |

## License

MIT
