fix(tools): improve session_status cache-aware usage reporting

Co-authored-by: Lucian Feraru <1ucian@users.noreply.github.com>
This commit is contained in:
Peter Steinberger
2026-02-23 19:05:27 +00:00
parent 40db3fef49
commit cf38339f25
3 changed files with 17 additions and 3 deletions

View File

@@ -30,6 +30,7 @@ Docs: https://docs.openclaw.ai
- Agents/Compaction: cancel safeguard compaction when summary generation cannot run (missing model/API key or summarization failure), preserving history instead of truncating to fallback `"Summary unavailable"` text. (#10711) Thanks @DukeDeSouth and @vincentkoc.
- Agents/Config: support per-agent `params` overrides merged on top of model defaults (including `cacheRetention`) so mixed-traffic agents can tune cache behavior independently. (#17470, #17112) Thanks @rrenamed.
- Agents/Bootstrap: cache bootstrap file snapshots per session key and clear them on session reset/delete, reducing prompt-cache invalidations from in-session `AGENTS.md`/`MEMORY.md` writes. (#22220) Thanks @anisoptera.
- Agents/Tools: make `session_status` read transcript-derived usage mid-turn and tail-read session logs for cache-aware context reporting without full-log scans. (#22387) Thanks @1ucian.
- Agents/Overflow: detect additional provider context-overflow error shapes (including `input length` + `max_tokens` exceed-context variants) so failures route through compaction/recovery paths instead of leaking raw provider errors to users. (#9951) Thanks @echoVic and @Glucksberg.
- Agents/Overflow: add Chinese context-overflow pattern detection in `isContextOverflowError` so localized provider errors route through overflow recovery paths. (#22855) Thanks @Clawborn.
- Agents/Failover: treat HTTP 502/503/504 errors as failover-eligible transient timeouts so fallback chains can switch providers/models during upstream outages instead of retrying the same failing target. (#20999) Thanks @taw0002 and @vincentkoc.

View File

@@ -381,7 +381,7 @@ export function createSessionStatusTool(opts?: {
dropPolicy: queueSettings.dropPolicy,
showDetails: queueOverrides,
},
includeTranscriptUsage: false,
includeTranscriptUsage: true,
});
return {

View File

@@ -243,7 +243,20 @@ const readUsageFromSessionLog = (
}
try {
const lines = fs.readFileSync(logPath, "utf-8").split(/\n+/);
// Read the tail only; we only need the most recent usage entries.
const TAIL_BYTES = 8192;
const stat = fs.statSync(logPath);
const offset = Math.max(0, stat.size - TAIL_BYTES);
const buf = Buffer.alloc(Math.min(TAIL_BYTES, stat.size));
const fd = fs.openSync(logPath, "r");
try {
fs.readSync(fd, buf, 0, buf.length, offset);
} finally {
fs.closeSync(fd);
}
const tail = buf.toString("utf-8");
const lines = (offset > 0 ? tail.slice(tail.indexOf("\n") + 1) : tail).split(/\n+/);
let input = 0;
let output = 0;
let promptTokens = 0;
@@ -270,7 +283,7 @@ const readUsageFromSessionLog = (
}
model = parsed.message?.model ?? parsed.model ?? model;
} catch {
// ignore bad lines
// ignore bad lines (including a truncated first tail line)
}
}