Перейти к содержимому

pi

pi это терминальный coding-агент. Он умеет работать с произвольным провайдером, поэтому Waibee подключается одним конфигом: писать расширение не нужно.

Установка pi (см. его документацию):

Окно терминала
npm install -g --ignore-scripts @earendil-works/pi-coding-agent
Окно терминала
export WAIBEE_API_KEY="sk_live_..."

Кастомные провайдеры pi читает из ~/.pi/agent/models.json. Создайте файл, если его нет. Минимальный рабочий вариант это адрес, протокол, ключ и хотя бы один идентификатор модели:

~/.pi/agent/models.json
{
"providers": {
"waibee": {
"baseUrl": "https://api.waibee.com",
"api": "anthropic-messages",
"apiKey": "$WAIBEE_API_KEY",
"models": [
{ "id": "anthropic/claude-sonnet-4.6" },
{ "id": "waibee/auto" }
]
}
}
}

Так уже можно работать. Остальные поля модели необязательны и влияют на то, что pi показывает и разрешает: без них он считает окно контекста равным 128K, лимит вывода 16.4K, стоимость нулевой, а флаг --thinking и картинки на входе недоступными.

Собственный каталог pi для кастомного провайдера не запрашивает, поэтому список моделей задаётся в конфиге. Идентификаторы, окна контекста и цены берутся из GET /v1/models, см. Модели.

Чтобы не переписывать модели руками, соберите файл из каталога. Цены при этом переводятся из «за токен» в ожидаемые pi «за миллион»:

Окно терминала
curl -s https://api.waibee.com/v1/models \
-H "Authorization: Bearer $WAIBEE_API_KEY" -o /tmp/waibee-models.json
jq '{providers: {waibee: {
baseUrl: "https://api.waibee.com",
api: "anthropic-messages",
apiKey: "$WAIBEE_API_KEY",
models: [ .data[]
| { id: .id,
name: .name,
reasoning: (((.capabilities.features // []) | index("reasoning")) != null),
input: ([(.capabilities.modality_input // [])[] | select(. == "text" or . == "image")]
| if length == 0 then ["text"] else . end),
contextWindow: (.context_length // 128000),
maxTokens: (.max_completion_tokens // 16384),
cost: {
input: ((.pricing.prompt // "0") | tonumber * 1000000),
output: ((.pricing.completion // "0") | tonumber * 1000000),
cacheRead: ((.pricing.input_cache_read // "0") | tonumber * 1000000),
cacheWrite: ((.pricing.input_cache_write // "0") | tonumber * 1000000) } } ] } } }' \
/tmp/waibee-models.json > ~/.pi/agent/models.json

Каталог меняется, так что команду имеет смысл повторять после появления новых моделей.

Подходит, если нужен короткий список с точными параметрами. Значения ниже это образец формы: окна и цены берите из каталога своим запросом, а не отсюда.

~/.pi/agent/models.json
{
"providers": {
"waibee": {
"name": "Waibee Router",
"baseUrl": "https://api.waibee.com",
"api": "anthropic-messages",
"apiKey": "$WAIBEE_API_KEY",
"models": [
{
"id": "anthropic/claude-sonnet-4.6",
"name": "Claude Sonnet 4.6",
"reasoning": true,
"input": ["text", "image"],
"contextWindow": 1000000,
"maxTokens": 128000,
"cost": { "input": 3, "output": 15, "cacheRead": 0.3, "cacheWrite": 3.75 }
}
]
}
}
}

api: "anthropic-messages" направляет запросы на POST /v1/messages, поэтому baseUrl указывается без /v1: путь клиент добавляет сам. Через этот эндпоинт доступны все модели каталога, не только Claude.

Окно терминала
pi --list-models | grep waibee # проверить, что провайдер подхватился
pi --provider waibee --model anthropic/claude-sonnet-4.6

В интерактивном режиме модель переключается командой /model. Чтобы не указывать флаги каждый раз, задайте значения по умолчанию:

~/.pi/agent/settings.json
{ "defaultProvider": "waibee", "defaultModel": "anthropic/claude-sonnet-4.6" }

Разовый запуск без интерфейса:

Окно терминала
pi -p --provider waibee --model anthropic/claude-sonnet-4.6 "какие эндпоинты объявлены в этом репозитории?"
Поле Значение
baseUrl https://api.waibee.com для anthropic-messages, https://api.waibee.com/v1 для openai-completions
api Протокол: anthropic-messages или openai-completions
apiKey "$WAIBEE_API_KEY" читает переменную окружения; можно вписать ключ строкой
models[].id Обязательное поле. Идентификатор из каталога, строго <провайдер>/<модель>
models[].cost Цены за миллион токенов. Поле необязательное, но если оно есть, нужны все четыре ключа: input, output, cacheRead, cacheWrite
models[].reasoning true включает флаг --thinking для этой модели
models[].input ["text"] или ["text", "image"]
models[].contextWindow, models[].maxTokens Окно контекста и лимит вывода. Без них pi берёт свои значения: 128000 и 16384

Быстро посмотреть идентификаторы, окна и цены:

Окно терминала
curl -s https://api.waibee.com/v1/models \
-H "Authorization: Bearer $WAIBEE_API_KEY" | jq -r '.data[] | "\(.id)\t\(.context_length)\t\(.pricing.prompt)"'

Цены в каталоге указаны за один токен, а pi ждёт их за миллион: умножайте на 1 000 000. См. Токены и usage.

Если привычнее Chat Completions, тот же провайдер описывается так:

~/.pi/agent/models.json
{
"providers": {
"waibee-openai": {
"baseUrl": "https://api.waibee.com/v1",
"api": "openai-completions",
"apiKey": "$WAIBEE_API_KEY",
"models": [
{ "id": "anthropic/claude-haiku-4.5" }
]
}
}
}

Провайдеров может быть несколько в одном файле: они не мешают друг другу.

Оба варианта рабочие. anthropic-messages предпочтительнее: на нём доступен уровень рассуждений max и нативно работает кэширование промптов для моделей Claude.

Окно терминала
pi --provider waibee --model anthropic/claude-sonnet-4.6 --thinking high

Значения off, minimal, low, medium, high, xhigh, max. На openai-completions уровень max не поддерживается роутером и вернёт ошибку, на anthropic-messages работает. Подробнее в Reasoning.

Провайдера нет в --list-models, а --provider waibee отвечает Unknown provider. Файл не прошёл проверку схемы, и pi молча игнорирует его целиком. Самая частая причина это неполный cost: нужны все четыре ключа, даже нулевые. Проверьте JSON на валидность и добавьте отсутствующие поля.

401 unauthorized. WAIBEE_API_KEY не экспортирован в той же оболочке, где запускается pi. Проверьте echo $WAIBEE_API_KEY.

422 validation_error про формат модели. В models[].id попало имя без провайдера. Нужен полный идентификатор из каталога, например anthropic/claude-sonnet-4.6.

Стоимость в интерфейсе выглядит неправдоподобно. pi считает её по блоку cost из вашего конфига, а не по данным роутера. Обновите цифры из каталога.