Concept internals
การติดตามการใช้งาน
คืออะไร
- ดึงข้อมูลการใช้งาน/โควตาของผู้ให้บริการโดยตรงจากเอนด์พอยต์การใช้งานของผู้ให้บริการนั้น
- ไม่มีต้นทุนโดยประมาณ มีเฉพาะหน้าต่างโควตาที่ผู้ให้บริการรายงาน หรือสรุปสถานะบัญชีเท่านั้น
- เอาต์พุตสถานะหน้าต่างโควตาที่มนุษย์อ่านได้จะถูกทำให้เป็นรูปแบบเดียวกันเป็น
X% leftแม้เมื่อ API ต้นทางรายงานโควตาที่ใช้ไปแล้ว โควตาที่เหลือ หรือมีเพียงจำนวนดิบเท่านั้น ผู้ให้บริการที่ไม่มีหน้าต่างโควตาแบบรีเซ็ตได้สามารถแสดงข้อความสรุปของผู้ให้บริการแทน เช่น ยอดคงเหลือ /statusระดับเซสชันและsession_statusสามารถ fallback ไปยังรายการการใช้งานล่าสุดในบันทึกถอดความได้เมื่อสแนปช็อตเซสชันแบบสดมีข้อมูลน้อย fallback นั้นเติมตัวนับ token/cache ที่ขาดหายไป สามารถกู้คืนป้ายกำกับโมเดลรันไทม์ที่ใช้งานอยู่ และเลือกยอดรวมที่เน้นพรอมป์ซึ่งมากกว่าเมื่อเมทาดาทาเซสชันขาดหายหรือมีค่าน้อยกว่า ค่าแบบสดที่ไม่เป็นศูนย์ที่มีอยู่ยังคงชนะ
แสดงที่ใด
/statusในแชต: การ์ดสถานะพร้อมอีโมจิจำนวนมาก โดยมีโทเค็นเซสชัน + ต้นทุนโดยประมาณ (เฉพาะคีย์ API) การใช้งานของผู้ให้บริการจะแสดงสำหรับ ผู้ให้บริการโมเดลปัจจุบัน เมื่อพร้อมใช้งาน โดยเป็นหน้าต่างX% leftที่ปรับเป็นรูปแบบเดียวกัน หรือข้อความสรุปของผู้ให้บริการ/usage off|tokens|fullในแชต: ส่วนท้ายการใช้งานต่อคำตอบ/usage costในแชต: สรุปต้นทุนภายในเครื่องที่รวบรวมจากบันทึกเซสชัน OpenClaw- CLI:
openclaw status --usageพิมพ์รายละเอียดแยกตามผู้ให้บริการแบบเต็ม - CLI:
openclaw channels listพิมพ์สแนปช็อตการใช้งานเดียวกันพร้อมกับการกำหนดค่าผู้ให้บริการ (ใช้--no-usageเพื่อข้าม) - แถบเมนู macOS: ส่วน "การใช้งาน" ใต้บริบท (เฉพาะเมื่อพร้อมใช้งาน)
โหมดส่วนท้ายการใช้งานเริ่มต้น
/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 โหมดเร็ว/ช้า หน้าต่างบริบท และต้นทุนเมื่อฟิลด์เหล่านั้นพร้อมใช้งาน ฟิลด์ token และ cache ยังคงพร้อมใช้งานสำหรับเทมเพลตแบบกำหนดเอง ไม่จำเป็นต้องมีไฟล์เทมเพลต
messages.usageTemplate มีไว้สำหรับเลย์เอาต์แบบกำหนดเองขั้นสูงเท่านั้น ค่านี้เป็นพาธไฟล์ JSON (รองรับ ~) หรืออ็อบเจกต์แบบ inline และจะแทนที่ส่วนท้ายในตัวเมื่อถูกต้อง:
{ "messages": { "usageTemplate": "~/.openclaw/usage-footer.json" }}เทมเพลตที่ขาดหายหรือว่างเปล่าจะ fallback ไปยังส่วนท้ายในตัวอย่างเงียบๆ เทมเพลตที่กำหนดค่าไว้แต่ไม่สามารถอ่านได้หรือไม่ถูกต้องก็จะ fallback ไปยังส่วนท้ายในตัวเช่นกัน และส่งคำเตือนสำหรับผู้ดูแลระบบ
เริ่มเทมเพลตแบบกำหนดเองจากรูปทรงในตัว แล้วแก้ไขส่วนที่ต้องการเปลี่ยน:
{ "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 */ ], }, },}แต่ละพื้นผิวเป็นรายการ ชิ้นส่วน ที่เรียงลำดับไว้ เอนจินจะแสดงผลแต่ละชิ้น ทิ้งรายการว่าง และเชื่อมรายการที่เหลือด้วย sep พื้นผิวที่ไม่มีรายการจะใช้ output.default
พาธสัญญา
ชิ้นส่วนอ่านค่าจากสัญญาต่อเทิร์นด้วยพาธแบบจุด ค่าที่ไม่มีอยู่จะว่างเปล่า (ดังนั้น guard when หรือ |fallback จะทำให้ชิ้นส่วนนั้นสะอาด)
| พาธ | ความหมาย |
|---|---|
surface |
รหัสช่องทาง (discord/telegram/ฯลฯ) |
model.provider / model.display_name |
รหัสผู้ให้บริการ / รหัสโมเดล |
model.reasoning |
ระดับความพยายาม (off ถึง xhigh) |
model.is_fallback / model.is_override |
บูลีน: ใช้ fallback / ปักหมุดโมเดล |
state.fast_mode |
บูลีน: เร็วเทียบกับช้า |
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 |
guard การแสดงผลโทเค็นและเปอร์เซ็นต์ cache |
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 |
แถบ glyph กว้าง W ช่องจากค่า 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 หรือโปรไฟล์การยืนยันตัวตน 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_remainsOpenClaw จะเลือกใช้ รายการโมเดลแชท อนุมานป้ายกำกับหน้าต่างจากเวลาประทับเมื่อไม่มีฟิลด์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 และแสดงยอดคงเหลือที่ผู้ให้บริการรายงาน เป็นข้อความแทนหน้าต่างโควตาเปอร์เซ็นต์ที่เหลือ
การใช้งานจะถูกซ่อนเมื่อไม่สามารถระบุการยืนยันตัวตนการใช้งานของผู้ให้บริการที่ใช้งานได้ ผู้ให้บริการ สามารถระบุตรรกะการยืนยันตัวตนการใช้งานเฉพาะ Plugin ได้; มิฉะนั้น OpenClaw จะถอยกลับไปใช้ ข้อมูลรับรอง OAuth/คีย์ API ที่ตรงกันจากโปรไฟล์การยืนยันตัวตน ตัวแปรสภาพแวดล้อม หรือการกำหนดค่า