Concept internals

Отслеживание использования

Что это

  • Получает данные об использовании/квоте провайдера напрямую из его endpoints использования.
  • Без расчетных затрат; только сообщаемые провайдером окна квот или сводки состояния аккаунта.
  • Удобочитаемый вывод статуса окна квоты нормализуется до X% left, даже когда вышестоящий API сообщает использованную квоту, оставшуюся квоту или только сырые счетчики. Провайдеры без сбрасываемых окон квоты могут вместо этого показывать текст сводки провайдера, например баланс.
  • Сессионные /status и session_status могут откатываться к последней записи использования в транскрипте, когда живой снимок сессии неполный. Этот fallback заполняет отсутствующие счетчики токенов/кэша, может восстановить метку активной runtime-модели и предпочитает больший prompt-ориентированный итог, когда метаданные сессии отсутствуют или меньше. Существующие ненулевые живые значения по-прежнему имеют приоритет.

Где это отображается

  • /status в чатах: статусная карточка с эмодзи, токенами сессии и расчетной стоимостью (только API-ключ). Использование провайдера показывается для провайдера текущей модели, когда доступно, как нормализованное окно X% left или текст сводки провайдера.
  • /usage off|tokens|full в чатах: футер использования для каждого ответа (OAuth показывает только токены).
  • /usage cost в чатах: локальная сводка стоимости, агрегированная из журналов сессий OpenClaw.
  • CLI: openclaw status --usage печатает полный разбор по провайдерам.
  • CLI: openclaw channels list печатает тот же снимок использования рядом с конфигурацией провайдера (используйте --no-usage, чтобы пропустить).
  • Строка меню macOS: раздел "Использование" в Context (только если доступно).

Режим футера использования по умолчанию

/usage off|tokens|full задает футер для сессии и запоминается для этой сессии. messages.responseUsage задает начальное значение этого режима для сессий, которые еще не выбрали его, поэтому футер может быть включен по умолчанию без ввода /usage каждый раз.

Задайте один режим для каждого канала или карту по каналам с fallback default:

jsonc
{  "messages": {    "responseUsage": "tokens",    // or: { "default": "off", "discord": "full" }  },}

Три различных состояния сессии

Поле responseUsage у сессии имеет три представимых состояния, каждое с разной семантикой:

Состояние Сохраненное значение Эффективный режим
Не задано / наследовать undefined (отсутствует) Переходит к значению по умолчанию messages.responseUsage, затем к off.
Явно выключено "off" (сохранено) Всегда выключено — значение конфигурации не off не может снова включить футер.
Явно включено "tokens" или "full" (сохранено) Этот режим, независимо от значения конфигурации по умолчанию.

Приоритет

Эффективный режим = переопределение сессии → запись конфигурации канала → defaultoff.

Явный /usage off сохраняется как буквальное значение "off" в сессии, а не как "не задано". Это означает, что значение messages.responseUsage по умолчанию, отличное от off, не может снова включить футер после того, как пользователь явно отключил его.

Сброс и выключение

  • /usage off — принудительно выключает футер и сохраняет этот выбор. Настроенное значение по умолчанию, отличное от off, не может переопределить это.
  • /usage reset (алиасы: inherit, clear, default) — очищает сессионное переопределение. Затем сессия наследует эффективное значение конфигурации по умолчанию (messages.responseUsage). Если значение по умолчанию не настроено, футер выключен (как и раньше). Используйте это, чтобы "вернуться к значению по умолчанию", не включая футер явно.
  • Полный сброс сессии (/reset или /new) или rollover сессии сохраняет явное предпочтение режима использования, чтобы выбор отображения пользователя переживал rollover сессии. Только /usage reset (и его алиасы) действительно очищает переопределение.

Поведение переключателя

/usage без аргументов циклически переключает: off → tokens → full → off. Начальная точка цикла — эффективный текущий режим (переопределение сессии с переходом к значению конфигурации по умолчанию, если оно не задано), поэтому цикл всегда согласуется с тем, что пользователь видит в футере.

Конфигурация

Без конфигурации сохраняется прежнее поведение (футер выключен до /usage). Используйте /usage reset, чтобы очистить сессионное переопределение и снова унаследовать настроенное значение по умолчанию.

Пользовательский футер /usage full

/usage full показывает встроенный компактный футер с моделью, reasoning, fast/slow, окном контекста, токенами хода, кэшем и стоимостью, когда эти поля доступны. Файл шаблона не требуется.

messages.usageTemplate предназначен только для расширенных пользовательских макетов. Значение — это путь к JSON-файлу (поддерживает ~) или inline-объект, и при валидности оно заменяет встроенный футер:

json
{  "messages": {    "usageTemplate": "~/.openclaw/usage-footer.json"  }}

Отсутствующие или пустые шаблоны тихо откатываются к встроенному футеру. Нечитаемые или недействительные настроенные шаблоны также откатываются к встроенному футеру и выводят предупреждение оператору.

Начните пользовательские шаблоны со встроенной формы, затем измените нужные части:

jsonc
{  "schema": "openclaw.usageBar.v1",  "scales": {    "braille": "⠐⡀⡄⡆⡇⣇⣧⣷⣿",    "block": "░▏▎▍▌▋▊▉█",    "shade": "░▒▓█",    "moon": "🌑🌘🌗🌖🌕",    "level": "▁▂▃▄▅▆▇█",    "weather": ["🥶", "☁️", "🌥", "⛅️", "🌤", "☀️"],    "plants": ["🪾", "🍂", "🌱", "☘️", "🍀", "🌿"],    "moons6": ["🌑", "🌚", "🌘", "🌗", "🌖", "🌝"],  },  "aliases": {    "models": {      "claude-opus-4-6": "opus46",      "claude-opus-4-8": "opus48",      "claude-sonnet-4-6": "sonnet46",      "claude-haiku-4-5": "haiku45",      "gpt-5.5": "gpt5.5",    },    "reasoning": {      "off": "🌑",      "minimal": "🌚",      "low": "🌘",      "medium": "🌗",      "high": "🌕",      "xhigh": "🌝",    },  },  "output": {    "sep": "",    "default": [      { "text": "{model.provider}{identity.emoji|🤖} {model.display_name|alias:models}" },      { "map": "model.is_fallback", "cases": { "true": " 🔄" } },      { "map": "model.is_override", "cases": { "true": " 📌" } },      { "when": "model.reasoning", "text": " {model.reasoning|alias:reasoning}" },      { "map": "state.fast_mode", "cases": { "true": " ⚡", "false": " 🐌" } },      {        "when": "context.max_tokens",        "text": " | 📚 [{context.pct_used|meter:5:braille}]{context.max_tokens|num}",      },      {        "when": "usage.has_split_tokens",        "text": " ↕️ {usage.input_tokens|num|?}/{usage.output_tokens|num|?}",      },      { "when": "usage.has_total_only_tokens", "text": " ↕️ {usage.total_tokens|num}" },      { "when": "usage.cache_hit_pct", "text": " 🗄 {usage.cache_hit_pct|pct}" },      { "when": "cost.turn_usd", "text": " 💰{cost.turn_usd|fixed:4}" },    ],    "surfaces": {      "discord": [        { "text": "-# -\n" },        { "text": "-# {model.provider}{identity.emoji|🤖} {model.display_name|alias:models}" },        { "map": "model.is_fallback", "cases": { "true": "🔄" } },        { "map": "model.is_override", "cases": { "true": "📌" } },        { "when": "model.reasoning", "text": " {model.reasoning|alias:reasoning}" },        { "map": "state.fast_mode", "cases": { "true": " ⚡️", "false": " 🐌" } },        {          "when": "context.max_tokens",          "text": " | 📚 [{context.pct_used|meter:5:braille}]{context.max_tokens|num}",        },        {          "when": "usage.has_split_tokens",          "text": " ↕️ {usage.input_tokens|num|?}/{usage.output_tokens|num|?}",        },        { "when": "usage.has_total_only_tokens", "text": " ↕️ {usage.total_tokens|num}" },        { "when": "usage.cache_hit_pct", "text": " 🗄 {usage.cache_hit_pct|pct}" },        { "when": "cost.turn_usd", "text": " 💰{cost.turn_usd|fixed:4}" },      ],    },  },}

Форма

jsonc
{  "schema": "openclaw.usageBar.v1",  "scales": { "<name>": "low-to-high glyphs" }, // string (1 glyph/char) or array  "aliases": { "<table>": { "<value>": "<label>" } },  "output": {    "sep": "", // joins surviving pieces    "default": [      /* pieces */    ], // fallback for any surface    "surfaces": {      "discord": [        /* pieces */      ],      "telegram": [        /* pieces */      ],    },  },}

Каждая поверхность — это упорядоченный список фрагментов; движок рендерит каждый, отбрасывает пустые и соединяет оставшиеся через sep. Поверхность без записи использует output.default.

Пути контракта

Фрагмент читает значения из контракта для каждого хода по dot-path. Отсутствующие значения пусты (поэтому guard when или |fallback сохраняет фрагмент чистым).

Путь Значение
surface id канала (discord/telegram/и т. д.)
model.provider / model.display_name id провайдера / id модели
model.reasoning effort (от off до xhigh)
model.is_fallback / model.is_override bool: использован fallback / модель закреплена
state.fast_mode bool: fast или slow
context.max_tokens / context.pct_used бюджет окна / 0-100 использовано
usage.input_tokens / usage.output_tokens / usage.total_tokens агрегат хода
usage.has_split_tokens / usage.has_total_only_tokens / usage.cache_hit_pct guards отображения токенов и процент кэша
usage.last.input_tokens / usage.last.output_tokens / usage.last.cache_hit_pct только финальный вызов модели
cost.turn_usd расчетная стоимость хода
identity.name / identity.emoji имя агента / выбранный эмодзи

(Окна rate-limit провайдера не входят в этот контракт.)

Глаголы

Пропускайте значение через глаголы слева направо; сегмент, не являющийся глаголом, — это fallback.

Глагол Эффект Пример
num компактный счетчик 272000 -> 272k
fixed:N N десятичных знаков (по умолчанию 2) 0.0377
dur секунды в длительность 14820 -> 4h07m
pct добавить % 96 -> 96%
inv 100 - x из использованного в оставшееся
alias:TABLE поиск в aliases, эхо, если нет в списке medium -> 🌗
meter:W:SCALE W-ячеечная glyph-полоса по значению 0-100 [⣿⣿⠐⠐⠐] (meter:1 = один glyph)

Формы фрагментов

  • { "text": "📚 {context.max_tokens|num}" }: литерал + интерполяция.
  • { "when": "<path>", "text": "..." }: рендерить только если путь truthy.
  • { "map": "<path>", "cases": { "true": "⚡", "false": "🐌" } }: значение в glyph.
  • { "each": "limits.windows", "item": "{label}" }: итерация по массиву.

Пример

jsonc
{  "schema": "openclaw.usageBar.v1",  "scales": { "braille": "⠐⡀⡄⡆⡇⣇⣧⣷⣿" },  "aliases": { "reasoning": { "medium": "🌗", "high": "🌕" } },  "output": {    "surfaces": {      "discord": [        { "text": "{model.display_name}" },        { "when": "model.reasoning", "text": " {model.reasoning|alias:reasoning}" },        { "map": "state.fast_mode", "cases": { "true": " ⚡", "false": " 🐌" } },        {          "when": "context.max_tokens",          "text": " | 📚 [{context.pct_used|meter:5:braille}]{context.max_tokens|num}",        },      ],    },  },}

отображается, например, как claude-sonnet-4-6 🌗 🐌 | 📚 [⣿⣿⣿⣿⣧]272k.

Провайдеры + учетные данные

  • Anthropic (Claude): токены OAuth в профилях аутентификации.
  • GitHub Copilot: токены OAuth в профилях аутентификации.
  • Gemini CLI: токены OAuth в профилях аутентификации.
    • Использование JSON откатывается к stats; stats.cached нормализуется в cacheRead.
  • OpenAI Codex: токены OAuth в профилях аутентификации (accountId используется, когда присутствует).
  • MiniMax: ключ API или профиль аутентификации MiniMax OAuth. OpenClaw рассматривает minimax, minimax-cn и minimax-portal как одну и ту же поверхность квоты MiniMax, предпочитает сохраненный MiniMax OAuth, когда он присутствует, а в остальных случаях откатывается к MINIMAX_CODE_PLAN_KEY, MINIMAX_CODING_API_KEY или MINIMAX_API_KEY. Опрос использования выводит хост Coding Plan из models.providers.minimax-portal.baseUrl или models.providers.minimax.baseUrl, когда они настроены, а в остальных случаях использует хост MiniMax CN. Необработанные поля MiniMax usage_percent / usagePercent означают оставшуюся квоту, поэтому OpenClaw инвертирует их перед отображением; поля на основе счетчиков имеют приоритет, когда присутствуют.
    • Метки окна Coding Plan берутся из полей часов/минут провайдера, когда присутствуют, затем откатываются к интервалу start_time / end_time.
    • Если конечная точка Coding Plan возвращает model_remains, OpenClaw предпочитает запись модели чата, выводит метку окна из временных меток, когда явные поля window_hours / window_minutes отсутствуют, и включает имя модели в метку плана.
  • Xiaomi MiMo: ключ API через хранилище env/config/auth (XIAOMI_API_KEY).
  • z.ai: ключ API через хранилище env/config/auth.
  • DeepSeek: ключ API через хранилище env/config/auth (DEEPSEEK_API_KEY). OpenClaw вызывает конечную точку баланса DeepSeek и показывает сообщенный провайдером баланс как текст вместо окна квоты с оставшимся процентом.

Использование скрывается, когда не удается определить пригодную аутентификацию использования провайдера. Провайдеры могут предоставлять логику аутентификации использования, специфичную для Plugin; в остальных случаях OpenClaw откатывается к сопоставлению учетных данных OAuth/ключа API из профилей аутентификации, переменных среды или конфигурации.

Связанные материалы

Was this useful?
On this page

On this page