mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-10-20 09:09:35 +02:00
feat(telemetry): read out Claude Code's prompt cache state per session
Claude Code's statusline has carried a prompt_cache object since v2.1.251, and Codeman's statusline exporter already received it, but StatusTelemetrySchema stripped the whole object, so Codeman never knew whether a session's conversation was still cached. Keep it and show it. StatusTelemetrySchema now lists every documented scalar field null-tolerant (several are documented as possibly null, and the object gains fields across CLI versions, so a strict shape would 400 the post and blank the footer), while parsePromptCache normalizes only the subset Codeman stores, so a hostile localhost payload cannot bloat state. Session.promptCache rides toState with a change-only session:promptCache event, and the route broadcasts the stored object. The Session Options (Respawn tab) readout shows warm-until or cold with the re-read stake, the cache hit rate, the last miss's causes, and, for Claude Code's own idle compaction (recache_tokens_if_cold null while expected_rebuilds rose), a "compacted at HH:MM" note that is never raised as an alert. setPromptCache stamps that on a new object rather than mutating the parsed report, so the stamp reaches the broadcast. Sessions without a statusline of their own also get a cache:until HH:MM / cache:cold group in the terminal footer. The last report is restored on a Codeman restart (like displayModel) so the readout is not blank until the pane's next render; the readout is time-aware, so a value whose expiry has passed reads as cold, not stale-warm. A launch without the exporter records why (collection off, workspace statusline, remote) so the row says the cause instead of "not reported yet" forever. This is the sensor a later opt-in keep-warm would read, and the TTL it reports is the source of truth rather than the plan tier.
This commit is contained in:
1 parent
aa3730aace
commit
551a7f2792
24 files changed
+946
-30
No files matched your search
@@ -625,6 +625,35 @@ most 64 characters, but treat it as untrusted text. A `statusline` or `screen` v
|
||||
persisted and restored after a server restart until the next report replaces it; a
|
||||
`config` value is read again at every pane start, attach and relaunch instead.
|
||||
|
||||
## Prompt cache (`promptCache`)
|
||||
|
||||
Claude-mode session state (`GET /api/v1/sessions`) carries the main conversation's
|
||||
prompt-cache state as Claude Code last reported it on the statusline (v2.1.251+), with a
|
||||
change-only `session:promptCache` event (`{ sessionId, ...promptCache }`):
|
||||
|
||||
```json
|
||||
"promptCache": { "warm": true, "ttl": "1h", "expiresAt": 1791653039000, "recacheTokensIfCold": 45000, "misses": 2, "expectedRebuilds": 1, "hitRatio": 0.91, "lastMissCauses": ["ttl_expired_1h"], "compactedAt": 1791649439872 }
|
||||
```
|
||||
|
||||
| Field | Meaning |
|
||||
| --------------------- | --------------------------------------------------------------------------------------------------------- |
|
||||
| `warm` | Whether the cached prefix is still within its TTL. The only field always present. |
|
||||
| `ttl` | `5m` or `1h`; absent when Claude reported neither. |
|
||||
| `expiresAt` | Epoch MILLISECONDS when the prefix goes cold (the statusline reports seconds). Absent once cold. |
|
||||
| `recacheTokensIfCold` | Tokens the next request re-writes if the cache has gone cold. Absent right after a compaction. |
|
||||
| `misses` | Requests that re-processed content the cache already held. |
|
||||
| `expectedRebuilds` | Cache rebuilds that followed a compaction or a clearing of old tool results. |
|
||||
| `hitRatio` | Cache read tokens as a fraction of all input tokens this session, 0 to 1. |
|
||||
| `lastMissCauses` | Claude Code's diagnosis of the last miss (e.g. `ttl_expired_1h`, `tools_changed`); untrusted text. |
|
||||
| `compactedAt` | Epoch MILLISECONDS when Codeman first saw Claude Code's own idle compaction of the current prefix (derived, not reported). |
|
||||
|
||||
The whole object is absent until the first report, and restored after a server restart
|
||||
(so the readout is not blank until the pane's next render) rather than recomputed; a value
|
||||
whose `expiresAt` has passed reads as cold. The statusline re-runs when a warm cache hits
|
||||
`expiresAt`, so the cold flip arrives on its own. A post-`/clear` conversation switch drops
|
||||
it. Shown in Session Options → Respawn and, for sessions without a statusline of their own,
|
||||
as a `cache:until HH:MM` / `cache:cold` group in the terminal footer.
|
||||
|
||||
## Approvals Inbox
|
||||
|
||||
Cross-session queue of prompts waiting on a human (permission dialogs,
|
||||
|
||||
Reference in new issue
Block a user