Concept internals
ردیابی استفاده
چیست
- استفاده/سهمیهٔ ارائهدهنده را مستقیماً از endpointهای استفادهٔ خودشان میگیرد.
- بدون هزینههای تخمینی؛ فقط پنجرههای سهمیه یا خلاصههای وضعیت حساب که ارائهدهنده گزارش کرده است.
- خروجی وضعیت پنجرهٔ سهمیهٔ خوانا برای انسان به
X% leftنرمالسازی میشود، حتی وقتی API بالادستی سهمیهٔ مصرفشده، سهمیهٔ باقیمانده، یا فقط شمارشهای خام را گزارش کند. ارائهدهندگانی که پنجرههای سهمیهٔ قابل بازنشانی ندارند میتوانند بهجای آن متن خلاصهٔ ارائهدهنده را نشان دهند، مثل موجودی. /statusدر سطح نشست وsession_statusمیتوانند وقتی snapshot زندهٔ نشست کماطلاعات است، به آخرین ورودی استفادهٔ transcript برگردند. آن fallback شمارندههای token/cache جاافتاده را پر میکند، میتواند برچسب مدل runtime فعال را بازیابی کند، و وقتی فرادادهٔ نشست وجود ندارد یا کوچکتر است، مجموع بزرگترِ prompt-محور را ترجیح میدهد. مقدارهای زندهٔ غیرصفر موجود همچنان اولویت دارند.
کجا نمایش داده میشود
/statusدر چتها: کارت وضعیت پر از emoji با tokenهای نشست + هزینهٔ تخمینی (فقط کلید API). استفادهٔ ارائهدهنده برای ارائهدهندهٔ مدل فعلی وقتی در دسترس باشد بهصورت پنجرهٔ نرمالشدهٔX% leftیا متن خلاصهٔ ارائهدهنده نمایش داده میشود./usage off|tokens|fullدر چتها: footer استفاده برای هر پاسخ./usage costدر چتها: خلاصهٔ هزینهٔ محلی که از logهای نشست OpenClaw تجمیع شده است.- CLI:
openclaw status --usageیک تفکیک کامل برای هر ارائهدهنده چاپ میکند. - CLI:
openclaw channels listهمان snapshot استفاده را کنار پیکربندی ارائهدهنده چاپ میکند (برای رد کردن از--no-usageاستفاده کنید). - نوار منوی macOS: بخش «استفاده» زیر «زمینه» (فقط اگر در دسترس باشد).
حالت پیشفرض footer استفاده
/usage off|tokens|full footer را برای یک نشست تنظیم میکند و برای همان نشست به خاطر سپرده میشود. messages.responseUsage این حالت را برای نشستهایی که هنوز حالتی انتخاب نکردهاند seed میکند، بنابراین footer میتواند بدون تایپ کردن /usage در هر بار، بهصورت پیشفرض روشن باشد.
برای هر channel یک حالت تنظیم کنید، یا یک نگاشت برای هر channel با fallback به default:
{ "messages": { "responseUsage": "tokens", // or: { "default": "off", "discord": "full" } },}سه وضعیت متمایز نشست
فیلد responseUsage یک نشست سه وضعیت قابل نمایش دارد که هرکدام semantics متفاوتی دارند:
| وضعیت | مقدار ذخیرهشده | حالت مؤثر |
|---|---|---|
| تنظیمنشده / ارثبری | undefined (غایب) |
به پیشفرض پیکربندی messages.responseUsage و سپس off میرسد. |
| خاموشِ صریح | "off" (ذخیرهشده) |
همیشه خاموش است؛ پیشفرض پیکربندی غیرخاموش نمیتواند footer را دوباره فعال کند. |
| روشنِ صریح | "tokens" یا "full" (ذخیرهشده) |
همان حالت، صرفنظر از پیشفرض پیکربندی. |
اولویت
حالت مؤثر = override نشست → ورودی پیکربندی channel → default → off.
یک /usage off صریح بهعنوان مقدار literal "off" در نشست ماندگار میشود، نه مثل «تنظیمنشده». یعنی پیشفرض غیرخاموش messages.responseUsage نمیتواند بعد از اینکه کاربر صریحاً آن را غیرفعال کرده است، footer را دوباره روشن کند.
بازنشانی در برابر خاموش کردن
/usage off— footer را بهاجبار خاموش میکند و آن انتخاب را ماندگار میکند. پیشفرض غیرخاموشِ پیکربندیشده نمیتواند این را override کند./usage reset(aliasها:inherit،clear،default) — override نشست را پاک میکند. سپس نشست پیشفرض پیکربندی مؤثر (messages.responseUsage) را به ارث میبرد. اگر هیچ پیشفرضی پیکربندی نشده باشد، footer خاموش است (مثل قبل بدون تغییر). از این برای «بازگشت به پیشفرض» بدون روشن کردن صریح footer استفاده کنید.- بازنشانی کامل نشست (
/resetیا/new) یا rollover نشست، ترجیح صریح حالت استفاده را حفظ میکند تا انتخاب نمایشی کاربر در rolloverهای نشست باقی بماند. فقط/usage reset(و aliasهای آن) واقعاً override را پاک میکند.
رفتار toggle
/usage بدون آرگومان چرخه میزند: off → tokens → full → off. نقطهٔ شروع چرخه حالت فعلی مؤثر است (override نشست که هنگام تنظیمنبودن به پیشفرض پیکربندی میرسد)، بنابراین چرخه همیشه با چیزی که کاربر در footer میبیند سازگار است.
پیکربندی
بدون پیکربندی، رفتار قبلی برقرار میماند (footer تا /usage خاموش است). برای پاک کردن override نشست و ارثبری دوباره از پیشفرض پیکربندیشده، از /usage reset استفاده کنید.
footer سفارشی /usage full
/usage full وقتی فیلدها در دسترس باشند یک footer فشردهٔ داخلی با مدل، reasoning، fast/slow، پنجرهٔ context و هزینه نشان میدهد. فیلدهای token و cache برای templateهای سفارشی همچنان در دسترس میمانند. هیچ فایل template لازم نیست.
messages.usageTemplate فقط برای چیدمانهای سفارشی پیشرفته است. مقدار آن یک مسیر فایل JSON (با پشتیبانی از ~) یا یک object درونخطی است، و وقتی معتبر باشد footer داخلی را جایگزین میکند:
{ "messages": { "usageTemplate": "~/.openclaw/usage-footer.json" }}templateهای جاافتاده یا خالی بیصدا به footer داخلی برمیگردند. templateهای پیکربندیشدهٔ خواندنینبودنی یا نامعتبر نیز به footer داخلی برمیگردند و یک هشدار operator منتشر میکنند.
templateهای سفارشی را از شکل داخلی شروع کنید، سپس بخشهایی را که میخواهید تغییر دهید ویرایش کنید:
{ "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": "\u00A0| 📚[{context.pct_used|meter:5:braille}]{context.max_tokens|num}", }, { "when": "cost.turn_usd", "text": "\u00A0💰{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": "\u00A0| 📚[{context.pct_used|meter:5:braille}]{context.max_tokens|num}", }, { "when": "cost.turn_usd", "text": "\u00A0💰{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 */ ], }, },}هر surface یک فهرست مرتب از pieceها است؛ engine هرکدام را render میکند، خالیها را حذف میکند، و باقیماندهها را با sep به هم وصل میکند. surface بدون ورودی از output.default استفاده میکند.
مسیرهای contract
یک piece مقدارها را از contract هر turn با dot-path میخواند. مقدارهای غایب خالی هستند (پس یک guard با when یا یک |fallback، piece را تمیز نگه میدارد).
| مسیر | معنی |
|---|---|
surface |
شناسهٔ channel (discord/telegram/و غیره) |
model.provider / model.display_name |
شناسهٔ ارائهدهنده / شناسهٔ مدل |
model.reasoning |
effort (از off تا xhigh) |
model.is_fallback / model.is_override |
bool: fallback استفاده شده / مدل pin شده |
state.fast_mode |
bool: fast در برابر slow |
context.max_tokens / context.pct_used |
بودجهٔ پنجره / 0-100 مصرفشده |
usage.input_tokens / usage.output_tokens / usage.total_tokens |
تجمیع turn |
usage.has_split_tokens / usage.has_total_only_tokens / usage.cache_hit_pct |
guardهای نمایش token و درصد cache |
usage.last.input_tokens / usage.last.output_tokens / usage.last.cache_hit_pct |
فقط فراخوانی نهایی مدل |
cost.turn_usd |
هزینهٔ تخمینی turn |
identity.name / identity.emoji |
نام agent / emoji انتخابشده |
(پنجرههای rate-limit ارائهدهنده در این contract نیستند.)
فعلها
یک مقدار را از چپ به راست از میان فعلها pipe کنید؛ segment غیرفعل fallback است.
| فعل | اثر | مثال |
|---|---|---|
num |
شمارش فشرده | 272000 -> 272k |
fixed:N |
N رقم اعشار (پیشفرض 2) | 0.0377 |
dur |
ثانیه به duration | 14820 -> 4h07m |
pct |
افزودن % |
96 -> 96% |
inv |
100 - x |
برای تبدیل مصرفشده به باقیمانده |
alias:TABLE |
جستوجو در aliases، اگر فهرست نشده بود echo |
medium -> 🌗 |
meter:W:SCALE |
نوار glyph با W خانه روی مقدار 0-100 | [⣿⣿⠐⠐⠐] (meter:1 = یک glyph) |
شکلهای piece
{ "text": "📚 {context.max_tokens|num}" }: literal + interpolation.{ "when": "<path>", "text": "..." }: فقط اگر مسیر truthy باشد render میشود.{ "map": "<path>", "cases": { "true": "⚡", "false": "🐌" } }: مقدار به glyph.{ "each": "limits.windows", "item": "{label}" }: پیمایش یک array.
مثال
{ "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 را render میکند.
ارائهدهندگان + credentialها
- Anthropic (Claude): توکنهای OAuth در نمایههای احراز هویت.
- GitHub Copilot: توکنهای OAuth در نمایههای احراز هویت.
- Gemini CLI: توکنهای OAuth در نمایههای احراز هویت.
- کاربرد JSON به
statsبازمیگردد؛stats.cachedبهcacheReadنرمالسازی میشود.
- کاربرد JSON به
- OpenAI Codex: توکنهای OAuth در نمایههای احراز هویت (
accountIdدر صورت وجود استفاده میشود). - MiniMax: کلید API یا نمایه احراز هویت OAuth مربوط به MiniMax. OpenClaw
minimax،minimax-cnوminimax-portalرا بهعنوان سطح سهمیه یکسان MiniMax در نظر میگیرد، در صورت وجود OAuth ذخیرهشده MiniMax را ترجیح میدهد، و در غیر این صورت بهMINIMAX_CODE_PLAN_KEY،MINIMAX_CODING_API_KEYیاMINIMAX_API_KEYبازمیگردد. پایش کاربرد، میزبان Coding Plan را هنگام پیکربندی ازmodels.providers.minimax-portal.baseUrlیاmodels.providers.minimax.baseUrlاستخراج میکند، و در غیر این صورت از میزبان MiniMax CN استفاده میکند. فیلدهای خامusage_percent/usagePercentدر MiniMax به معنی سهمیه باقیمانده هستند، بنابراین OpenClaw پیش از نمایش آنها را وارونه میکند؛ فیلدهای مبتنی بر تعداد، در صورت وجود، اولویت دارند.- برچسبهای پنجره coding-plan، در صورت وجود، از فیلدهای ساعت/دقیقه ارائهدهنده
میآیند، سپس به بازه
start_time/end_timeبازمیگردند. - اگر نقطه پایانی coding-plan مقدار
model_remainsرا برگرداند، OpenClaw ورودی مدل گفتوگو را ترجیح میدهد، وقتی فیلدهای صریحwindow_hours/window_minutesوجود ندارند برچسب پنجره را از مُهرهای زمانی استخراج میکند، و نام مدل را در برچسب طرح قرار میدهد.
- برچسبهای پنجره coding-plan، در صورت وجود، از فیلدهای ساعت/دقیقه ارائهدهنده
میآیند، سپس به بازه
- Xiaomi MiMo: کلید API از طریق env/config/auth store (
XIAOMI_API_KEY). - z.ai: کلید API از طریق env/config/auth store.
- DeepSeek: کلید API از طریق env/config/auth store (
DEEPSEEK_API_KEY). OpenClaw نقطه پایانی موجودی DeepSeek را فراخوانی میکند و موجودی گزارششده توسط ارائهدهنده را بهجای پنجره سهمیه درصد باقیمانده، بهصورت متن نشان میدهد.
وقتی هیچ احراز هویت کاربرد ارائهدهنده قابلاستفادهای قابل resolve نباشد، کاربرد پنهان میشود. ارائهدهندگان میتوانند منطق احراز هویت کاربرد ویژه Plugin ارائه کنند؛ در غیر این صورت OpenClaw به اعتبارنامههای OAuth/API-key مطابق از نمایههای احراز هویت، متغیرهای محیطی، یا پیکربندی بازمیگردد.