Recover a session's context from the CLI's own file
A restarted server has been told nothing, so a Claude session that has not taken a turn since reported its context as unknown -- which was true, and useless, since the CLI had written the figure down at the time and it was sitting in the session's file the whole while. It now reads it from there at load, over the session's transport, in the background: the same three input fields the import list already reads, so it is a measurement rather than a guess. Only when nothing else has answered, and only for a provider that keeps such a file. A clear needs no special case even though it makes the last usage in a file stale, because clearing gives the CLI a new session id -- so the lookup lands on a file with no usage yet and answers unknown, which is what it is.
This commit is contained in:
1 parent
bc0a48799c
commit
0d623b7073
3 files changed
+76
No files matched your search
@@ -688,6 +688,50 @@ pub async fn line_count(transport: &Transport, path: &str) -> Result<usize> {
|
||||
.with_context(|| format!("couldn't read a line count out of {out:?}"))
|
||||
}
|
||||
|
||||
/// What the CLI's own file says a session is holding, for a session this
|
||||
/// server has no measurement of.
|
||||
///
|
||||
/// A restarting server has been told nothing, and a session that has not
|
||||
/// taken a turn since will not tell it -- so a conversation that is nearly
|
||||
/// full reads as one nobody has counted until somebody sends a message to
|
||||
/// it. The CLI records the figure on every assistant message, so it is
|
||||
/// there to be read rather than waited for, and reading it is a
|
||||
/// measurement rather than a guess: the same three fields, from the same
|
||||
/// file, that the import list reports.
|
||||
///
|
||||
/// A clear needs no special case here even though it makes the last usage
|
||||
/// in a file stale. Clearing gives the CLI a *new* session id, which the
|
||||
/// reader persists as the resume token, so this looks in a file that has
|
||||
/// no usage in it yet and answers `None` -- which is the true answer.
|
||||
///
|
||||
/// `None` for every way it cannot be read: no resume token, no file, a
|
||||
/// machine that cannot be reached, or a file with no assistant turn in it.
|
||||
/// Not knowing is a state the status row draws, so there is nothing to be
|
||||
/// gained by inventing a number here.
|
||||
pub async fn context_of(transport: &Transport, session_id: &str) -> Option<u64> {
|
||||
// The id crosses as an argument rather than as script text: it comes
|
||||
// from the CLI, but it reaches a shell on a machine that may not be
|
||||
// this one, and the rule there is that data never becomes syntax.
|
||||
let script = r#"
|
||||
for f in "$HOME"/.claude/projects/*/"$1".jsonl; do
|
||||
[ -f "$f" ] || continue
|
||||
grep -o '"usage":{[^}]*' "$f" | tail -1
|
||||
exit 0
|
||||
done
|
||||
"#;
|
||||
let launch = Launch::new(
|
||||
"sh",
|
||||
vec![
|
||||
"-c".to_string(),
|
||||
script.to_string(),
|
||||
"sh".to_string(),
|
||||
session_id.to_string(),
|
||||
],
|
||||
None,
|
||||
);
|
||||
context_tokens(&transport.capture(&launch).await.ok()?)
|
||||
}
|
||||
|
||||
/// Events from the lines after `after`, which is a 0-based count of lines
|
||||
/// already accounted for.
|
||||
pub async fn replay_after(
|
||||
|
||||
Reference in new issue
Block a user