fix: resolve cascade correlation, update KNOWN_ISSUES

- MitmStore: added active_cascade_id field with set/get/clear methods
- record_usage() now falls back to active_cascade_id when the heuristic
  cascade hint is absent (fixes usage always going to _latest)
- All three API handlers set active cascade before send_message
- KNOWN_ISSUES: moved 3 issues to resolved:
  - Request modification (already true, was stale entry)
  - Cascade correlation (fixed via active_cascade_id)
  - Progressive thinking streaming (fixed via MITM bypass)
This commit is contained in:
Nikketryhard
2026-02-15 01:10:34 -06:00
parent b3af73cebd
commit 981fb3b18d
5 changed files with 59 additions and 26 deletions

View File

@@ -207,6 +207,7 @@ pub(crate) async fn handle_completions(
};
// Send message
state.mitm_store.set_active_cascade(&cascade_id).await;
match state
.backend
.send_message(&cascade_id, &user_text, model.model_enum)

View File

@@ -155,6 +155,7 @@ pub(crate) async fn handle_gemini(
};
// Send message
state.mitm_store.set_active_cascade(&cascade_id).await;
match state
.backend
.send_message(&cascade_id, &user_text, model.model_enum)

View File

@@ -278,6 +278,7 @@ pub(crate) async fn handle_responses(
};
// Send message
state.mitm_store.set_active_cascade(&cascade_id).await;
match state
.backend
.send_message(&cascade_id, &user_text, model.model_enum)

View File

@@ -89,6 +89,11 @@ pub struct MitmStore {
/// Last captured function calls (for conversation history rewriting).
last_function_calls: Arc<RwLock<Vec<CapturedFunctionCall>>>,
// ── Cascade correlation ──────────────────────────────────────────────
/// Active cascade ID set by the API layer before sending a message.
/// Used by the MITM proxy to correlate intercepted traffic to cascades.
active_cascade_id: Arc<RwLock<Option<String>>>,
// ── Direct response capture (bypasses LS) ────────────────────────────
/// Captured response text from MITM when custom tools are active.
/// The completions/responses handler reads this instead of polling LS steps.
@@ -135,6 +140,7 @@ impl MitmStore {
pending_tool_results: Arc::new(RwLock::new(Vec::new())),
call_id_to_name: Arc::new(RwLock::new(HashMap::new())),
last_function_calls: Arc::new(RwLock::new(Vec::new())),
active_cascade_id: Arc::new(RwLock::new(None)),
captured_response_text: Arc::new(RwLock::new(None)),
captured_thinking_text: Arc::new(RwLock::new(None)),
response_complete: Arc::new(AtomicBool::new(false)),
@@ -186,7 +192,13 @@ impl MitmStore {
// Call 2: thinking summary text (thinking_output_tokens == 0, response_text has the summary)
//
// When Call 2 arrives, we merge its response_text as thinking_text into Call 1's usage.
let key = cascade_id.map(|s| s.to_string()).unwrap_or_else(|| "_latest".to_string());
let key = if let Some(cid) = cascade_id {
cid.to_string()
} else if let Some(active) = self.active_cascade_id.read().await.as_ref() {
active.clone()
} else {
"_latest".to_string()
};
let mut latest = self.latest_usage.write().await;
if let Some(existing) = latest.get_mut(&key) {
@@ -436,4 +448,22 @@ impl MitmStore {
pub async fn take_thinking_text(&self) -> Option<String> {
self.captured_thinking_text.write().await.take()
}
// ── Cascade correlation ──────────────────────────────────────────────
/// Set the active cascade ID (called by API handlers before sending a message).
/// The MITM proxy will use this to correlate intercepted traffic.
pub async fn set_active_cascade(&self, cascade_id: &str) {
*self.active_cascade_id.write().await = Some(cascade_id.to_string());
}
/// Get the active cascade ID.
pub async fn get_active_cascade(&self) -> Option<String> {
self.active_cascade_id.read().await.clone()
}
/// Clear the active cascade ID (called after response is complete).
pub async fn clear_active_cascade(&self) {
*self.active_cascade_id.write().await = None;
}
}