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:
{ "messages": { "responseUsage": "tokens", // or: { "default": "off", "discord": "full" } },}Три различных состояния сессии
Поле responseUsage у сессии имеет три представимых состояния, каждое с
разной семантикой:
| Состояние | Сохраненное значение | Эффективный режим |
|---|---|---|
| Не задано / наследовать | undefined (отсутствует) |
Переходит к значению по умолчанию messages.responseUsage, затем к off. |
| Явно выключено | "off" (сохранено) |
Всегда выключено — значение конфигурации не off не может снова включить футер. |
| Явно включено | "tokens" или "full" (сохранено) |
Этот режим, независимо от значения конфигурации по умолчанию. |
Приоритет
Эффективный режим = переопределение сессии → запись конфигурации канала → default → off.
Явный /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-объект, и при валидности оно заменяет встроенный
футер:
{ "messages": { "usageTemplate": "~/.openclaw/usage-footer.json" }}Отсутствующие или пустые шаблоны тихо откатываются к встроенному футеру. Нечитаемые или недействительные настроенные шаблоны также откатываются к встроенному футеру и выводят предупреждение оператору.
Начните пользовательские шаблоны со встроенной формы, затем измените нужные части:
{ "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}" }, ], }, },}Форма
{ "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}" }: итерация по массиву.
Пример
{ "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.
- Использование JSON откатывается к
- 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. Необработанные поля MiniMaxusage_percent/usagePercentозначают оставшуюся квоту, поэтому OpenClaw инвертирует их перед отображением; поля на основе счетчиков имеют приоритет, когда присутствуют.- Метки окна Coding Plan берутся из полей часов/минут провайдера, когда
присутствуют, затем откатываются к интервалу
start_time/end_time. - Если конечная точка Coding Plan возвращает
model_remains, OpenClaw предпочитает запись модели чата, выводит метку окна из временных меток, когда явные поляwindow_hours/window_minutesотсутствуют, и включает имя модели в метку плана.
- Метки окна Coding Plan берутся из полей часов/минут провайдера, когда
присутствуют, затем откатываются к интервалу
- 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 из профилей аутентификации, переменных среды или конфигурации.