Skip to content

Commit 817b06b

Browse files
committed
fix(usage): tidy compact footer defaults
1 parent 90357ee commit 817b06b

5 files changed

Lines changed: 28 additions & 42 deletions

File tree

docs/concepts/usage-tracking.md

Lines changed: 15 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ title: "Usage tracking"
2424
## Where it shows up
2525

2626
- `/status` in chats: emoji-rich status card with session tokens + estimated cost (API key only). Provider usage shows for the **current model provider** when available as a normalized `X% left` window or provider summary text.
27-
- `/usage off|tokens|full` in chats: per-response usage footer (OAuth shows tokens only).
27+
- `/usage off|tokens|full` in chats: per-response usage footer.
2828
- `/usage cost` in chats: local cost summary aggregated from OpenClaw session logs.
2929
- CLI: `openclaw status --usage` prints a full per-provider breakdown.
3030
- CLI: `openclaw channels list` prints the same usage snapshot alongside provider config (use `--no-usage` to skip).
@@ -95,8 +95,8 @@ With no config the prior behavior holds (footer off until `/usage`). Use
9595
## Custom `/usage full` footer
9696

9797
`/usage full` shows a built-in compact footer with model, reasoning, fast/slow,
98-
context window, turn tokens, cache, and cost when those fields are available. No
99-
template file is required.
98+
context window, and cost when those fields are available. Token and cache fields
99+
remain available to custom templates. No template file is required.
100100

101101
`messages.usageTemplate` is only for advanced custom layouts. The value is a
102102
JSON file path (supports `~`) or an inline object, and it replaces the built-in
@@ -150,42 +150,30 @@ change:
150150
"output": {
151151
"sep": "",
152152
"default": [
153-
{ "text": "{model.provider}{identity.emoji|🤖} {model.display_name|alias:models}" },
154-
{ "map": "model.is_fallback", "cases": { "true": " 🔄" } },
155-
{ "map": "model.is_override", "cases": { "true": " 📌" } },
156-
{ "when": "model.reasoning", "text": " {model.reasoning|alias:reasoning}" },
157-
{ "map": "state.fast_mode", "cases": { "true": "", "false": " 🐌" } },
153+
{ "text": "{model.provider}{identity.emoji|🤖}{model.display_name|alias:models}" },
154+
{ "map": "model.is_fallback", "cases": { "true": "🔄" } },
155+
{ "map": "model.is_override", "cases": { "true": "📌" } },
156+
{ "when": "model.reasoning", "text": "{model.reasoning|alias:reasoning}" },
157+
{ "map": "state.fast_mode", "cases": { "true": "⚡️", "false": "🐌" } },
158158
{
159159
"when": "context.max_tokens",
160-
"text": " | 📚 [{context.pct_used|meter:5:braille}]{context.max_tokens|num}",
160+
"text": "\u00A0| 📚[{context.pct_used|meter:5:braille}]{context.max_tokens|num}",
161161
},
162-
{
163-
"when": "usage.has_split_tokens",
164-
"text": " ↕️ {usage.input_tokens|num|?}/{usage.output_tokens|num|?}",
165-
},
166-
{ "when": "usage.has_total_only_tokens", "text": " ↕️ {usage.total_tokens|num}" },
167-
{ "when": "usage.cache_hit_pct", "text": " 🗄 {usage.cache_hit_pct|pct}" },
168-
{ "when": "cost.turn_usd", "text": " 💰{cost.turn_usd|fixed:4}" },
162+
{ "when": "cost.turn_usd", "text": "\u00A0💰{cost.turn_usd|fixed:4}" },
169163
],
170164
"surfaces": {
171165
"discord": [
172166
{ "text": "-# -\n" },
173-
{ "text": "-# {model.provider}{identity.emoji|🤖} {model.display_name|alias:models}" },
167+
{ "text": "-# {model.provider}{identity.emoji|🤖}{model.display_name|alias:models}" },
174168
{ "map": "model.is_fallback", "cases": { "true": "🔄" } },
175169
{ "map": "model.is_override", "cases": { "true": "📌" } },
176-
{ "when": "model.reasoning", "text": " {model.reasoning|alias:reasoning}" },
177-
{ "map": "state.fast_mode", "cases": { "true": " ⚡️", "false": " 🐌" } },
170+
{ "when": "model.reasoning", "text": "{model.reasoning|alias:reasoning}" },
171+
{ "map": "state.fast_mode", "cases": { "true": "⚡️", "false": "🐌" } },
178172
{
179173
"when": "context.max_tokens",
180-
"text": " | 📚 [{context.pct_used|meter:5:braille}]{context.max_tokens|num}",
181-
},
182-
{
183-
"when": "usage.has_split_tokens",
184-
"text": " ↕️ {usage.input_tokens|num|?}/{usage.output_tokens|num|?}",
174+
"text": "\u00A0| 📚[{context.pct_used|meter:5:braille}]{context.max_tokens|num}",
185175
},
186-
{ "when": "usage.has_total_only_tokens", "text": " ↕️ {usage.total_tokens|num}" },
187-
{ "when": "usage.cache_hit_pct", "text": " 🗄 {usage.cache_hit_pct|pct}" },
188-
{ "when": "cost.turn_usd", "text": " 💰{cost.turn_usd|fixed:4}" },
176+
{ "when": "cost.turn_usd", "text": "\u00A0💰{cost.turn_usd|fixed:4}" },
189177
],
190178
},
191179
},

docs/reference/prompt-caching.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -333,7 +333,7 @@ Defaults:
333333
### What to inspect
334334

335335
- Cache trace events are JSONL and include staged snapshots like `session:loaded`, `prompt:before`, `stream:context`, and `session:after`.
336-
- Per-turn cache token impact is visible in normal usage surfaces via `cacheRead` and `cacheWrite` (for example `/usage full` and session usage summaries).
336+
- Per-turn cache token impact is visible in normal usage surfaces via `cacheRead` and `cacheWrite` (for example `/usage tokens`, `/status`, session usage summaries, and custom `messages.usageTemplate` layouts).
337337
- For Anthropic, expect both `cacheRead` and `cacheWrite` when caching is active.
338338
- For OpenAI, expect `cacheRead` on cache hits. GPT-5.6 Responses can also report `cacheWrite` while prompt segments are written; other Responses payloads that omit the write counter keep it at `0`.
339339
- If you need request tracing, log request IDs and rate-limit headers separately from cache metrics. OpenClaw's current cache-trace output is focused on prompt/session shape and normalized token usage rather than raw provider response headers.

docs/reference/token-use.md

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,10 @@ Use these in chat:
7878
- Persists per session (stored as `responseUsage`).
7979
- `/usage reset` (aliases: `inherit`, `clear`, `default`) — clears the session
8080
override so the session re-inherits the configured default.
81-
- `/usage full` shows estimated cost only when OpenClaw has usage metadata and
82-
local pricing for the active model. Otherwise it shows tokens only.
81+
- `/usage tokens` shows turn token/cache details.
82+
- `/usage full` shows compact model/context/cost details; estimated cost appears
83+
only when OpenClaw has usage metadata and local pricing for the active model.
84+
Custom `messages.usageTemplate` layouts can include token/cache fields.
8385
- `/usage cost` → shows a local cost summary from OpenClaw session logs.
8486

8587
Other surfaces:
@@ -131,10 +133,11 @@ models.providers.<provider>.models[].cost
131133
```
132134

133135
These are **USD per 1M tokens** for `input`, `output`, `cacheRead`, and
134-
`cacheWrite`. If pricing is missing, OpenClaw shows tokens only. Cost display is
135-
not limited to API-key auth: non-API-key providers such as `aws-sdk` can show
136-
estimated cost when their configured model entry includes local pricing and the
137-
provider returns usage metadata.
136+
`cacheWrite`. If pricing is missing, `/usage full` omits cost; use `/usage tokens`
137+
or a custom `messages.usageTemplate` when you need token/cache details in every
138+
reply. Cost display is not limited to API-key auth: non-API-key providers such
139+
as `aws-sdk` can show estimated cost when their configured model entry includes
140+
local pricing and the provider returns usage metadata.
138141

139142
After sidecars and channels reach the Gateway ready path, OpenClaw starts an
140143
optional background pricing bootstrap for configured model refs that do not

src/auto-reply/reply/agent-runner.misc.runreplyagent.test.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2776,6 +2776,8 @@ describe("runReplyAgent response usage footer", () => {
27762776
const res = await createRun({ responseUsage: "full", sessionKey });
27772777
const payload = Array.isArray(res) ? res[0] : res;
27782778
const text = payload?.text ?? "";
2779+
expect(text).toContain("ok\nanthropic🤖claude🌘🐌");
2780+
expect(text).not.toContain("ok\n\nanthropic");
27792781
expect(text).toContain("anthropic🤖claude🌘🐌");
27802782
expect(text).not.toContain("↕️");
27812783
expect(text).not.toContain("🗄");

src/auto-reply/usage-bar/default-template.ts

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,8 @@ export const DEFAULT_USAGE_BAR_TEMPLATE: UsageBarTemplate = {
2424
},
2525
output: {
2626
sep: "",
27-
// Telegram (and any surface without its own list) falls through to `default`,
28-
// so the default is built to read well on a narrow phone screen:
29-
// - Tight badges: no separators between model/flags/reasoning/fast.
30-
// - NBSP (\u00A0) before "|" and before 💰 keeps those joins non-breaking.
31-
// - 📚 is glued hard to the meter so it can't wrap between books and bars.
32-
// - The single regular space after "|" is the only sanctioned wrap point.
33-
// - Leading \n drops the footer onto its own line, below the message body.
3427
default: [
35-
{ text: "\n{model.provider}{identity.emoji|🤖}{model.display_name|alias:models}" },
28+
{ text: "{model.provider}{identity.emoji|🤖}{model.display_name|alias:models}" },
3629
{ map: "model.is_fallback", cases: { true: "🔄" } },
3730
{ map: "model.is_override", cases: { true: "📌" } },
3831
{ when: "model.reasoning", text: "{model.reasoning|alias:reasoning}" },

0 commit comments

Comments
 (0)