From 255c67de3fee4c393e104878c856068ecf78e0d5 Mon Sep 17 00:00:00 2001 From: Jonas H Date: Thu, 11 Jun 2026 09:08:28 +0200 Subject: [PATCH] Fix session key extraction for Claude Code 2.1.x user_id format MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit metadata.user_id is now a JSON-ish blob containing "session_id":"" (verified against the 2.1.173 binary: user_id is built from an object with device_id/account_uuid/session_id). split("session_") was matching inside "session_id":" and producing mangled keys like `id":"a78…`, which broke the embed-session match — so the pane never grew for interactive prompts. New session_key() handles both the JSON blob and the legacy user_…_session_ format, with tests. Co-Authored-By: Claude Fable 5 --- src/proxy.rs | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/src/proxy.rs b/src/proxy.rs index ca95ec7..3132b19 100644 --- a/src/proxy.rs +++ b/src/proxy.rs @@ -10,6 +10,16 @@ use serde_json::Value; const UPSTREAM: &str = "https://api.anthropic.com"; +/// Extract the session UUID from `metadata.user_id`. Claude Code ≥2.1.x +/// sends a JSON-ish blob containing `"session_id":""`; older builds +/// used `user__account__session_`. +fn session_key(u: &str) -> Option<&str> { + if let Some(rest) = u.split(r#"session_id":""#).nth(1) { + return rest.split('"').next(); + } + u.split("session_").nth(1) +} + #[derive(Clone)] struct Ctx { client: reqwest::Client, @@ -66,7 +76,7 @@ async fn forward_inner(ctx: Ctx, req: Request) -> anyhow::Result { let key = v .pointer("/metadata/user_id") .and_then(Value::as_str) - .and_then(|u| u.split("session_").nth(1)) + .and_then(session_key) .unwrap_or("unknown") .to_string(); // Tool results ride along in the request body; surface them @@ -127,3 +137,23 @@ async fn forward_inner(ctx: Ctx, req: Request) -> anyhow::Result { }; Ok(builder.body(body)?) } + +#[cfg(test)] +mod tests { + use super::session_key; + + #[test] + fn session_key_handles_both_user_id_formats() { + // Claude Code ≥2.1.x: JSON blob + assert_eq!( + session_key(r#"{"device_id":"d","account_uuid":"a","session_id":"a78d91b6-1234-5678-9abc-def012345678"}"#), + Some("a78d91b6-1234-5678-9abc-def012345678") + ); + // Legacy underscore format + assert_eq!( + session_key("user_abc123_account_acc-uuid_session_29bd3436-aaaa-bbbb-cccc-111122223333"), + Some("29bd3436-aaaa-bbbb-cccc-111122223333") + ); + assert_eq!(session_key("no session here"), None); + } +}