# @ivydigital/paperclip-adapter-openrouter

External [Paperclip](https://github.com/paperclipai/paperclip) adapter for
[OpenRouter](https://openrouter.ai). Run any Paperclip agent on any free or
paid OpenRouter model — DeepSeek, Claude, GPT, Gemini, Llama, Hermes, Qwen,
Kimi — without spawning an external CLI. The adapter speaks OpenRouter's
HTTP API directly.

## Install (from inside Paperclip)

In a Paperclip deployment, install this package as an external adapter
plugin so the server registers it on next startup:

```bash
npm install --prefix $PAPERCLIP_DATA_DIR/adapter-plugins @ivydigital/paperclip-adapter-openrouter
```

Then restart the server (or POST to the adapter-plugin reload endpoint).
The new adapter type `openrouter` will appear in the Agent config picker.

## Contract

This package is a Paperclip *external adapter*. It exports a top-level
`createServerAdapter()` factory, which Paperclip's plugin loader calls to
get a [`ServerAdapterModule`](https://www.npmjs.com/package/@paperclipai/adapter-utils):

```ts
import { createServerAdapter } from "@ivydigital/paperclip-adapter-openrouter";

const adapter = createServerAdapter();
// adapter.type === "openrouter"
// adapter.execute, .testEnvironment, .listModels, .sessionCodec, .models, .agentConfigurationDoc
```

## Agent configuration

| Field | Type | Default | Description |
|-------|------|---------|-------------|
| `apiKey` | string (secret) | — | Required. OpenRouter API key. |
| `model` | string | `deepseek/deepseek-chat-v3-0324:free` | Any OpenRouter model id. |
| `baseUrl` | string | `https://openrouter.ai/api/v1` | Override for staging or self-hosted gateways. |
| `temperature` | number | `0.2` | Sampling temperature. |
| `maxTokens` | number | (provider default) | Hard cap on output tokens. |
| `systemPrompt` | string | (built-in) | Replace the default system prompt. |
| `timeoutMs` | number | `300000` | Per-request timeout in ms. |
| `extraHeaders` | object | `{}` | Extra HTTP headers (e.g. ranking headers). |
| `provider` | object | — | Forwarded to OpenRouter as the `provider` block (routing/fallback). |

`apiKey` falls back to the `OPENROUTER_API_KEY` environment variable when
not set explicitly — useful for containerized deployments.

## Free vs paid models

OpenRouter exposes both free and paid models behind the same API. Free
models include the `:free` suffix in their id (e.g.
`deepseek/deepseek-r1:free`). Free tiers have stricter rate limits.
`listModels()` returns the full live catalog, sorted by label.

## Development

```bash
npm install
npm run typecheck
npm run build
npm test
```

## Publishing

This adapter is published to npm. Bump the version in `package.json`,
then:

```bash
npm run build
npm publish --access public
```

CI uses an `NPM_TOKEN` from the org secret store; do not run `npm publish`
with a personal token.

## License

MIT
