# Artillect Provider

> [Обновление LLM API 2026-10-16 и действия для существующих интеграций](/docs/api-updates/2026-10-16.md). `GET /api/v1/provider/models/` содержит `api_update`; публичный `GET /api/v1/updates/` доступен без ключа.

<!-- provider-media-guide:start -->

## Provider + MCP: модели и медиа для агента
Hermes / OpenCode думает через Provider, создаёт медиа через MCP и исполняет задачи в harness.
Нужны только модели для кода/чата — подключите Provider. Нужны только медиа у уже настроенного агента — подключите MCP, менять его LLM не обязательно.
Оба подключения полезны для лендинга с оригинальными фото, рекламного комплекта с видео/озвучкой или игровых ассетов: агент связывает код и медиа, а проект сохраняет результат для Studio.
Provider — LLM inference: Chat Completions, Responses, Anthropic Messages; возвращает ответы и предложения tool calls, сам инструменты не исполняет.
MCP — инструменты Artillect: каталог, estimate, генерация изображений/видео/аудио/3D, get_task, проекты и доставка ассетов.
Harness (Hermes, OpenCode и другие клиенты) — агентский цикл: вызывает инструменты, а при наличии разрешённых shell/files пишет код и скачивает файлы.
Поиск публичной справки: https://app.artillect.pro/knowledge/#knowledge-search ; рецепты MCP: https://app.artillect.pro/docs/mcp/recipes.md . Поиск не читает личные проекты и файлы.
Подключения независимы: MCP работает с другим LLM-провайдером; Provider работает без MCP и без генерации медиа. Вместе дают агенту модели и медиаматериалы одного сервиса.
Setup: /provider/, /provider/hermes/, /provider/opencode/; MCP: /docs/mcp; API-ключ: /api/. Provider URL https://app.artillect.pro/api/v1/provider; MCP URL https://app.artillect.pro/mcp.
Для совместного API-key setup: provider:write, models:read, images:write (также audio/mesh), videos:write, projects:write. files:write — только для загрузки референсов. MCP отдельно поддерживает OAuth. Ключи не публикуйте и не коммитьте.
Бесплатно напрямую: GET /api/v1/provider/models/, GET /api/v1/me/; MCP initialize/tools list, get_started/get_balance. Это auth/discovery, не проверка платного inference. Сообщение LLM-агенту оплачивается, даже если инструмент бесплатный.
1. discover: Выбрать проект, найти модель и входы в каталоге. Зачем: project_id сохраняет медиа для продолжения в Studio; capabilities.input в живом Provider /models определяет vision.
2. estimate: Оценить точные параметры каждого ассета; сверить баланс и авторизованный бюджет. Зачем: Оценка до submit помогает контролировать расходы; уже разрешённый бюджет не требует повторных подтверждений.
3. submit: Сериализовать generate_*; заранее сохранить стабильный idempotency_key, затем task_id. Зачем: Media submit — платный. Тот же payload/key защищает повтор в пределах 24 часов; после окна сначала сверить историю.
4. poll: get_task с task_id/poll_args до terminal; ошибка останавливает polling, успех требует media_urls. Зачем: Асинхронная задача продолжается после обрыва; повторный submit может купить дубликат.
5. deliver: Показать результат; в coding host скачать существующий TASK_ID через artillect generate wait TASK_ID --out public/assets --json; вести artillect-assets.json. Зачем: Manifest хранит project/task IDs и проверенные local paths без ключей/capability URLs. Сбой скачивания чинится повторной доставкой, готовый файл переиспользуется.
6. verify: Проверить реальные файлы и сайт сборкой/тестами; скриншоты — только при поддержке vision в host. Зачем: Постер — один кадр, не просмотр видео. Сборка сайта и публикация различаются; hosting доступ и разрешение нужны отдельно.
Provider использует личный накопительный ledger: округляется общая стоимость, новый запрос списывает её прирост. Старые запросы остаются по прежней политике. Studio/media тарифы не меняются; project media может использовать другой баланс. Общего автоматического жёсткого бюджета LLM+media нет.
GET /api/v1/provider/requests/?id=<X-Artillect-Request-Id> с тем же user/API key и provider:write показывает исход и расчёт. Status lookup не воспроизводит ответ; inference idempotent replay отсутствует. При неоднозначном обрыве сначала status, не слепой retry.
MCP image/poster blocks предназначены user+assistant, но передачу байтов модели и показ превью решает host. Нужны vision-модель и поддержка клиента; сервер не гарантирует одинаковый UI или автоматическое зрение.
Studio Assistant направляет запросы на создание сайта или целого приложения к Artillect Provider в Hermes/OpenCode; не пишет целое приложение в чате. Он объясняет подключение и помогает подготовить задачу; для медиа предлагает MCP. Его catalog tools не устанавливают конфиги и не исполняют shell/deployment; generation offers подтверждаются через UI. Внешний агент пишет код и собирает проект в пределах своих прав и бюджета.
Каждый запрос Provider получает короткий контекст Artillect и условных возможностей MCP. Он сохраняет инструкции клиента; наличие контекста не подключает MCP и не добавляет инструментов. Дополнительный вход учитывается в резерве и фактической стоимости LLM.

<!-- provider-media-guide:end -->

Отдельный провайдер для агентской разработки поверх OpenRouter. Статус: подготовлен
к запуску, включается оператором после применения infra 107 через CI и запуска worker.
Существующие Studio, REST API, MCP и CLI сохраняют свои контракты и тарифы.

## Контракт

Base URL: `https://app.artillect.pro/api/v1/provider` (staging: замените host на `dev.artillect.pro`).
Создайте ключ `art_…` на `/api/`, желательно отдельный для агента.
Права: `provider:write` для completions, `models:read` для каталога; ключ `*` тоже подходит.
Передавайте `Authorization: Bearer art_…`. Ключ OpenRouter остаётся на сервере.

- `GET /models` — OpenAI model list с курируемыми ID.
- `POST /chat/completions` — стандартные `choices[].message` или SSE `choices[].delta`.
- Сохраняются function tool calls, tool results, structured outputs и reasoning.
- Изображения доступны моделям, у которых живой `GET /models` возвращает
  `capabilities.input: ["text", "image"]`. `image_tool_results` показывает возможность
  передавать картинки из инструментов обратно модели; `protocols` перечисляет API.
  Для текстовых моделей image input возвращает `IMAGE_INPUT_UNSUPPORTED` до резерва.
- Chat Completions: `image_url` в content пользователя или tool result;
  Responses: `input_image` в пользовательском content и массиве output
  `function_call_output` / `custom_tool_call_output`; Messages: `image` в user content
  или внутри `tool_result.content`. System/assistant image content отклоняется.
- Ссылки: публичный HTTPS без credentials, IP-адресов, локальных имён и нестандартных
  портов. Chat/Responses также принимают `data:image/...;base64,...`;
  Messages — `source: {type: "base64", media_type: "image/png", data: "..."}`.
  Форматы inline: PNG, JPEG, WebP, GIF; максимум 5 МиБ декодированных байт на картинку
  и 20 картинок на весь запрос, включая результаты инструментов. Общий лимит тела 8 МиБ.
  Ссылки загружает upstream: доступность, MIME, размер удалённого файла и разрешение
  проверяет выбранный провайдер. Provider не скачивает и не сохраняет изображения.
- `POST /responses` — stateless Responses API для Codex, нативные SSE events,
  function/custom tools и encrypted reasoning. Только `store=false`, без `previous_response_id`.
- `POST /anthropic/v1/messages` — нативные Messages/SSE для Claude Code;
  Anthropic base URL заканчивается на `/provider/anthropic` (SDK добавляет `/v1/messages`).
  Поддерживает также `x-api-key`; beta/version headers передаются OpenRouter.
- Максимум ответа зависит от модели и читается из живого каталога OpenRouter;
  `GET /models` возвращает `max_output_tokens` и `top_provider.max_completion_tokens`.
  По умолчанию максимум модели для Chat Completions, Responses и Messages. `n` только 1.
- Принимается `max_tokens` или `max_completion_tokens`, но не оба одновременно.
- Контекст соответствует модели: `GET /models` возвращает актуальный `context_length`.
  Точное число входных токенов проверяет провайдер. Байтовая оценка используется
  только для резерва оплаты и не отклоняет запросы как переполнение контекста.
  При изображениях резерв консервативно учитывает всё оставшееся окно входа,
  cache write и цену за каждое изображение: короткий URL не ограничивает vision tokens.
  Это может требовать большого доступного баланса; итог оплачивается по фактическому cost.
- Максимум тела 8 МиБ. Неизвестные параметры отклоняются: клиент не может
  изменить routing, добавить fallback models или платные серверные plugins.
- `Idempotency-Key` пока не поддерживается и отклоняется до списания. Каждый новый
  POST — отдельный оплачиваемый запрос; при сетевом сбое избегайте слепых повторов.
- `stream_options.include_usage=true` включает usage в потоке.
- Ошибки: `{ "error": { "message": "…", "type": "…", "code": "…", "param": null } }`.
  `OUTPUT_LIMIT` требует уменьшить лимит ответа; `CONTEXT_LIMIT` — сжать историю.
  Ошибки upstream содержат безопасное описание и ID для сопоставления с серверными логами.

Модели: `openai/gpt-6-luna`, `openai/gpt-6.1-sol`, `anthropic/claude-opus-5.5`,
`google/gemini-3.8-flash`, `deepseek/deepseek-v4.1-flash`, `qwen/qwen3.8-max-prime`,
`anthropic/claude-sonnet-5.5`, `deepseek/deepseek-v4-pro-0813`, `qwen/qwen3.8-flash`, `x-ai/grok-4.7`.
Sonnet — средняя ценовая категория для кода, DeepSeek Pro — рассуждения,
Qwen Flash — быстрая доступная альтернатива, Grok — универсальная альтернативная модель.
Актуальный список — `GET /models`; изменения allowlist принадлежат `src/lib/agentProvider/catalog.ts`.

## Изображения из инструментов

Пример Chat Completions после выполненного MCP-вызова (сохраняйте предыдущий
assistant `tool_calls` с тем же ID в истории):

```json
{
  "role": "tool",
  "tool_call_id": "call_generate_image",
  "content": [
    { "type": "text", "text": "Готовый ассет; проверь композицию и читаемость" },
    {
      "type": "image_url",
      "image_url": { "url": "https://cdn.example.com/asset.png", "detail": "high" }
    }
  ]
}
```

Harness выполняет MCP-инструмент и возвращает image block модели. Отображение картинки
в интерфейсе зависит от клиента; Provider не исполняет MCP и не генерирует медиа сам.
Видео передавайте кадрами, аудио — транскрипцией; нативные audio/video/file blocks и
серверные paid plugins в этих контрактах не поддерживаются. Для локальных screenshots
используйте raster base64, для готовых ассетов — действующую HTTPS-ссылку.

Форматы и цены upstream:
[OpenRouter vision](https://openrouter.ai/blog/tutorials/send-image-to-llm/),
[Responses](https://openrouter.ai/docs/api/api-reference/responses/create-responses),
[Messages](https://openrouter.ai/docs/api/api-reference/anthropic-messages/create-messages),
[max_price.image](https://openrouter.ai/docs/guides/routing/provider-selection#max-price).

## Страницы подключения

В интерфейсе: `/provider/` → отдельные страницы
`/provider/claude-code/`, `/provider/codex/`, `/provider/opencode/`,
`/provider/hermes/`, `/provider/omp/`, `/provider/cline/`, `/provider/roo-code/`,
`/provider/aider/`, `/provider/cursor/`. Примеры на страницах — канонические
`src/lib/agentProvider/integrations.ts`; Cursor помечен с ограничениями клиента.
Клиентские подключения требуют живого smoke после запуска и не означают,
что все proprietary-функции этих клиентов поддерживаются внешним провайдером.

Codex: custom provider `wire_api="responses"`, HTTP/SSE, `env_key="ARTILLECT_API_KEY"`,
без OpenAI login и WebSocket; не меняйте существующий профиль, добавьте новый.
Claude Code: `ANTHROPIC_AUTH_TOKEN` = ключ Artillect, пустой `ANTHROPIC_API_KEY`,
base URL `/api/v1/provider/anthropic` и закреплённые слоты моделей из allowlist.
Hermes/OpenCode страницы дают сразу два подключения: inference Provider и hosted MCP.
Для сценария сайта ключу нужны `provider:write`, `models:read`, `images:write`,
`videos:write`, `projects:write`; для uploads добавьте `files:write`.
Бесплатная проверка: прямые HTTP `GET /provider/models` и `GET /me`, затем MCP
list tools, `get_started`, `get_balance`. Если попросить LLM выполнить проверку,
сам inference оплачивается по Provider-тарифу.

MCP prompt `website_media` ведёт через проект, estimate, идемпотентный submit медиа,
polling и локальную доставку `artillect generate wait TASK_ID --out public/assets --json`.
Manifest `artillect-assets.json` хранит task ID и файлы: после обрыва продолжайте
ожидание/скачивание той же задачи, не создавайте новую генерацию. Harness пишет
и проверяет сайт в локальной рабочей папке; публикация требует доступа к хостингу.
Общий жёсткий бюджет inference+медиа пока не реализован.

Native protocols: [OpenRouter Responses](https://openrouter.ai/docs/api_reference/responses/overview),
[Claude Code gateway protocol](https://code.claude.com/docs/en/llm-gateway-protocol),
[Codex config](https://learn.chatgpt.com/docs/config-file/config-reference).

## OpenCode

`opencode.json`, ключ в переменной окружения `ARTILLECT_API_KEY`:

```json
{
  "$schema": "https://opencode.ai/config.json",
  "provider": {
    "artillect": {
      "npm": "@ai-sdk/openai-compatible",
      "name": "Artillect",
      "options": {
        "baseURL": "https://app.artillect.pro/api/v1/provider",
        "apiKey": "{env:ARTILLECT_API_KEY}"
      },
      "models": {
        "openai/gpt-6-luna": {
          "name": "GPT-6 Luna",
          "limit": { "context": 1050000, "output": 128000 }
        }
      }
    }
  },
  "model": "artillect/openai/gpt-6-luna"
}
```

Другие модели добавляются с точным ID из каталога. Протокол — Chat Completions.
Схема настройки: [официальная документация OpenCode](https://opencode.ai/docs/providers/#custom-provider).

## Hermes Agent

В Hermes Desktop откройте **Settings → Providers → Custom Endpoints**.
Проверьте, что **Applies to** указывает на профиль текущего чата. Добавьте:

- **Name:** `Artillect`
- **Base URL:** `https://app.artillect.pro/api/v1/provider`
- **API Key:** ваш ключ Artillect со страницы `/api/` с правами `provider:write`,
  `models:read`, `images:write`, `videos:write` и `projects:write`; нужен баланс аккаунта.
- **Model:** `openai/gpt-6-luna`
- **API Mode:** `Chat Completions`

Нажмите **Test**, чтобы загрузить каталог и проверить запрос, затем **Save**.
Test делает небольшой оплачиваемый запрос и сам по себе не сохраняет провайдера.
После Save выберите Artillect в списке моделей возле поля сообщения или в
**Settings → Model**. Если модели скрыты, включите их в **Edit models**;
если список не обновился, перезапустите Hermes.

Для CLI запустите `hermes model` вне чата и выберите **Custom endpoint**.
Для ручной регистрации именованного провайдера добавьте в существующий
`~/.hermes/config.yaml`, сохранив остальные настройки:

```yaml
providers:
  artillect:
    name: Artillect
    api: https://app.artillect.pro/api/v1/provider
    key_env: ARTILLECT_API_KEY
    transport: chat_completions
    session_affinity_header: X-Session-Id
    default_model: openai/gpt-6-luna
    context_length: 1050000
    models:
      - openai/gpt-6-luna
      - openai/gpt-6.1-sol
      - anthropic/claude-opus-5.5
      - google/gemini-3.8-flash
      - deepseek/deepseek-v4.1-flash
      - qwen/qwen3.8-max-prime
      - anthropic/claude-sonnet-5.5
      - deepseek/deepseek-v4-pro-0813
      - qwen/qwen3.8-flash
      - x-ai/grok-4.7

model:
  provider: custom:artillect
  default: openai/gpt-6-luna
  api_mode: chat_completions
  context_length: 1050000

mcp_servers:
  artillect:
    url: https://app.artillect.pro/mcp
    headers:
      Authorization: "Bearer art_YOUR_KEY"
    timeout: 90
```

В `~/.hermes/.env`: `ARTILLECT_API_KEY=art_YOUR_KEY`. Нужен ключ Artillect,
а не OpenRouter. Замените `art_YOUR_KEY` в заголовке MCP и `.env` одним ключом;
храните оба файла только локально. В Desktop добавьте `mcp_servers` в
`config.yaml` выбранного профиля и перезапустите Hermes.
Для переключения в текущем чате:
`/model custom:artillect:openai/gpt-6-luna`.
Схема настройки: [Hermes Desktop](https://hermes-agent.nousresearch.com/docs/user-guide/desktop#settings--onboarding)
и [именованные провайдеры](https://hermes-agent.nousresearch.com/docs/integrations/providers#named-custom-providers).

Ключу нужны также права `models:read` для обнаружения лимитов. Значение
`context_length` в примере — окно GPT-6 Luna; при смене модели используйте
значение из `GET /models`. Актуальный Hermes не читает `model.max_tokens`:
лимит вывода проверяет сервер, включая запросы сжатия истории.

## OMP / Oh My Pi

В `~/.omp/agent/models.yml`, ключ — переменная окружения `ARTILLECT_API_KEY`:

```yaml
providers:
  artillect:
    baseUrl: https://app.artillect.pro/api/v1/provider
    apiKey: ARTILLECT_API_KEY
    api: openai-completions
    models:
      - id: openai/gpt-6-luna
        name: GPT-6 Luna
        reasoning: true
        input: [text, image]
        contextWindow: 1050000
        maxTokens: 128000
        compat:
          maxTokensField: max_tokens
```

Выберите `artillect` и модель через selector OMP.
Схема настройки: [официальная документация OMP](https://github.com/can1357/oh-my-pi/blob/main/docs/models.md).

## Дефолтный биллинг и восстановление

Новые запросы используют `openrouter-cumulative-v2`: стоимость накапливается на пользователя
по всем его Provider-ключам в целых единицах $0.0000000001 (меньшие дроби округляются вверх).
Списание = `ceil(накопленная USD стоимость × 100)` минус ранее списанная сумма ledger.
Отдельный ход может стоить 0 Artillect-токенов; это центы, а не входные/выходные LLM-токены.
Порядок settlement определяет, как итоговые списания распределяются по ключам и дневным
лимитам; суммарное списание пользователя не зависит от порядка. Старые запросы
`openrouter-cost-v1` рассчитываются по прежней политике `ceil(usage.cost × 100)`.
Studio, генерация медиа и действующие Public API тарифы не меняются.
Цены для резерва читаются из живого каталога OpenRouter (кэш 60 секунд), routing
ограничен этими ценами, включая тарифные ступени длинного контекста и максимальные
временные тарифы. Резерв использует максимум обычной цены входа и записи кеша,
а не их сумму. Тариф записи на час используется только при `cache_control.ttl=1h`.
Chat Completions принимает `cache_control` в текстовых блоках и на уровне запроса;
для Claude по умолчанию включается автоматическое кеширование с коротким TTL.
Неподдерживаемые sampling-параметры удаляются с записью в diagnostics;
tools, схемы ответа и требования reasoning сохраняются.
Резерв учитывает вход, лимит выхода и image pricing;
для изображений routing дополнительно ограничен `max_price.image`.
При окончательном расчёте используется авторитетная `usage.cost` OpenRouter,
включающая cached/reasoning usage; остаток резерва возвращается атомарно.
При отсутствии cost не выдумываем стоимость: worker запрашивает `/generation`.
Механика cost: [OpenRouter usage accounting](https://openrouter.ai/docs/cookbook/administration/usage-accounting).

`GET /api/v1/provider/requests/?id=<X-Artillect-Request-Id>` с правом `provider:write`
показывает модель, state, резерв, списание, строковую `cost_usd`, `billing_policy` и
безопасную диагностику. Запрос должен принадлежать тому же пользователю и тому же ключу.
Диагностика: протокол, outcome, HTTP/error classification upstream, input/output/cache usage,
время первого content delta, длительность и завершение потока. Также сохраняются
request ID, хеш session ID, имена параметров и удалённых sampling-настроек,
размер тела, число сообщений/инструментов/изображений, лимит ответа,
расчётная граница входа и использованные цены, cache-write/reasoning usage,
категория upstream-отказа и HTTP-статус последующей проверки стоимости.

В конфигурации Hermes `session_affinity_header: X-Session-Id` объединяет вызовы
основного агента и вспомогательные вызовы одной сессии; ID передаётся OpenRouter,
а в нашей диагностике хранится только SHA-256.

После пяти безрезультатных попыток и двух часов pending с известным provider ID
переходит в `needs_review`; резерв сохраняется до проверки оператором.
Промпты, исходники, аргументы инструментов, изображения, URL и auth headers не сохраняются.
Статус помогает разобрать обрыв, но не повторяет inference: идемпотентность POST отсутствует.

HTTP заголовки: `X-Artillect-Request-Id` (ID записи), `X-Artillect-Reserved-Tokens`;
для sync также `X-Artillect-Billing-State` и после расчёта `X-Artillect-Cost-Tokens`.
Отключение клиента не отменяет уже отправленный upstream запрос: поток дочитывается
и оплачивается. После 180 секунд upstream timeout расчёт может остаться pending.
Отказ upstream 4xx возвращает резерв; 5xx/сетевой сбой считаются неоднозначными.

## Оператору

Production `deploy-prod` запускает отдельный контейнер `artillect-agent-provider-worker`
и проверяет успешный проход расчётов до переключения приложения. Это новый worker;
генерации и платежи продолжают обслуживаться существующими процессами.
Используется существующий серверный `OPENROUTER_API_KEY`; новый ключ не обязателен.
Все запросы, каталог и восстановление стоимости используют `OPENROUTER_RELAY_URL`
так же, как существующий чат. Клиентам выдаются ключи Artillect, не OpenRouter.
В production CI пилот включается по умолчанию; `AGENT_PROVIDER_ENABLED=0`
выключает только новый API. Локальный `.env.example` оставляет его выключенным.

1. Выключить admission Provider (`AGENT_PROVIDER_ENABLED=0`) и остановить **все старые**
   recovery workers до перехода на `openrouter-cumulative-v2`.
2. Применить `db/infra/107_agent_provider_requests.sql` и
   `108_agent_provider_requests_grants.sql`, затем
   `111_agent_provider_cumulative.sql` через штатный CI infra.
3. Настроить серверный `OPENROUTER_API_KEY`; выкатить новый worker, поддерживающий v1 и v2,
   и запустить отдельный процесс `AGENT_PROVIDER_RECONCILE_ENABLED=1 pnpm worker:agent-provider`
   с обычным DB env. Затем выкатить новое приложение.
4. Включить `AGENT_PROVIDER_ENABLED=1` и `AGENT_PROVIDER_RECONCILE_ENABLED=1` в app env.
   Не включать без реально работающего нового worker. По умолчанию endpoints отвечают 503.
5. Проверить аутентификацию, `/models`, затем реальный tool round trip каждым клиентом.

Старый worker игнорирует `billing_policy` и **не должен** обрабатывать v2-запросы.
Additive схема совместима со старым приложением, money runtime — нет.
При rollback выключить admission и сохранить новый worker до расчёта всех unresolved v2;
**не запускать старый worker**, пока такие запросы остаются. Схема и ledger сохраняются
при откате. Порядок выката и отката: [Public API internal](../../docs/PUBLIC_API_INTERNAL.md).

Worker проходит максимум 50 доступных к повторной попытке записей за тик, раз в минуту;
неудачные расчёты получают backoff от 10 минут до 24 часов, чтобы не блокировать новые записи;
`pnpm worker:agent-provider --once` — один проход. Двойные расчёты защищены транзакцией
и блокировкой записи. Отдельная таблица хранит ID, модель, цену, владельца,
состояние и безопасную диагностику: ни промптов, ни исходного кода, ни аргументов инструментов.

`reserved` без dispatch старше 10 минут возвращается автоматически. `pending` с
provider ID восстанавливается через OpenRouter; сохранённая cost имеет приоритет.
`pending` без ID переводится в `needs_review`: оператор сопоставляет запрос с Activity
OpenRouter, устанавливает правильные provider ID/cost и возвращает state в `pending`.
Не возвращать резерв автоматически при неоднозначном сетевом сбое: inference мог состояться.
Следить за ростом `needs_review`, возрастом pending и здоровьем процесса worker.

Per-key дневной лимит использует `PUBLIC_API_KEY_DAILY_TOKEN_CAP`: отдельно учитываются
резервы нового продукта (сериализация через баланс), плюс действующий public API preflight.
Это не единый жёсткий лимит совокупного расхода Studio/REST/Provider.
API-key `tokens_spent` обновляется по итоговой стоимости в транзакции.

Следующие тарифные решения: маржа,
подписки, проектный баланс и отдельные лимиты. Менять в `src/lib/agentProvider/pricing.ts`,
с новой версией политики; Studio pricing при этом не меняется.
