Merge origin/main into main

Integrate upstream updates while preserving the local analytics dashboards and schema-only migration changes.

Combine user account analysis with upstream user/group usage statistics in separate tabs, retain all migration versions, and keep the deleted audit document removed.

Validation: gateway all-target cargo check, frontend type check and 57 focused tests, 48 migration tests, schema composition checks, and diff whitespace checks.
This commit is contained in:
elky
2026-10-02 11:57:18 +08:00
343 changed files with 27929 additions and 2549 deletions
+64 -5
View File
@@ -17,9 +17,10 @@ use crate::body_capture::{
};
use crate::request_metadata::{
attach_client_request_body_metadata, attach_provider_actual_service_tier_metadata,
attach_provider_request_body_metadata, build_usage_request_metadata_seed,
merge_usage_request_metadata, merge_usage_request_metadata_owned,
refresh_provider_response_body_metadata, sanitize_usage_request_metadata,
attach_provider_request_body_metadata, attach_provider_response_model_metadata,
build_usage_request_metadata_seed, merge_usage_request_metadata,
merge_usage_request_metadata_owned, refresh_provider_response_body_metadata,
refresh_provider_response_model_metadata, sanitize_usage_request_metadata,
sanitize_usage_request_metadata_ref,
};
use crate::{
@@ -727,6 +728,15 @@ fn build_terminal_usage_event_from_seed_impl(
Some(model.as_str()),
provider_request.as_ref(),
);
let request_metadata = attach_provider_response_model_metadata(
request_metadata,
request_body.as_ref(),
body_states.request_body_state,
Some(client_contract.as_str()),
provider_response.as_ref(),
body_states.response_body_state,
Some(provider_contract.as_str()),
);
let mut data = UsageEventData {
user_id,
@@ -1073,6 +1083,15 @@ pub fn build_sync_terminal_usage_seed(
context_seed.request_metadata,
provider_response_full.as_ref(),
);
let request_metadata = refresh_provider_response_model_metadata(
request_metadata,
context_seed.request_body.as_ref(),
context_seed.body_states.request_body_state,
Some(context_seed.client_contract.as_str()),
provider_response_full.as_ref(),
provider_response_body_state,
Some(context_seed.provider_contract.as_str()),
);
TerminalUsageSeed {
token_measurement_source,
@@ -1252,6 +1271,15 @@ pub fn build_stream_terminal_usage_seed(
context_seed.request_metadata,
provider_response_full.as_ref(),
);
let request_metadata = refresh_provider_response_model_metadata(
request_metadata,
context_seed.request_body.as_ref(),
context_seed.body_states.request_body_state,
Some(context_seed.client_contract.as_str()),
provider_response_full.as_ref(),
provider_response_body_state,
Some(context_seed.provider_contract.as_str()),
);
// The parser's terminal summary is authoritative when a response body is truncated or the
// body and summary disagree; attach it after the body refresh so it wins.
let request_metadata = attach_provider_actual_service_tier_metadata(
@@ -3080,14 +3108,26 @@ fn parse_sse_body_for_storage(text: &str) -> Option<Value> {
let mut chunks = Vec::new();
let mut total_chunks = 0_u64;
let mut saw_done = false;
let mut first_parse_error = None;
for_each_sse_payload(text, |payload| {
if payload == "[DONE]" {
saw_done = true;
return;
}
total_chunks += 1;
if let Ok(json_body) = serde_json::from_str::<Value>(payload) {
chunks.push(json_body);
match serde_json::from_str::<Value>(payload) {
Ok(json_body) => chunks.push(json_body),
Err(error) if first_parse_error.is_none() => {
// A later valid event must not hide an earlier broken one.
// Store diagnostics only, without duplicating raw user content.
first_parse_error = Some(json!({
"chunk_index": total_chunks - 1,
"line": error.line(),
"column": error.column(),
"message": error.to_string(),
}));
}
Err(_) => {}
}
});
if total_chunks == 0 && !saw_done {
@@ -3104,6 +3144,11 @@ fn parse_sse_body_for_storage(text: &str) -> Option<Value> {
if saw_done {
metadata.insert("has_completion".to_string(), Value::Bool(true));
}
if let Some(error) = first_parse_error {
// Capture truncation can also cause a parse error; this describes the
// captured payload, not an assertion that the provider sent bad JSON.
metadata.insert("first_parse_error".to_string(), error);
}
if stored_chunks < total_chunks {
metadata.insert(
"dropped_chunks".to_string(),
@@ -7221,6 +7266,20 @@ mod tests {
);
}
#[test]
fn parse_sse_body_for_storage_reports_bad_event_before_valid_terminal() {
let body = concat!(
"data: {\"tools\":[}\n\n",
"data: {\"type\":\"response.completed\"}\n\n",
);
let parsed = parse_sse_body_for_storage(body).unwrap();
assert_eq!(parsed["metadata"]["dropped_chunks"], 1);
assert_eq!(parsed["metadata"]["first_parse_error"]["chunk_index"], 0);
assert!(parsed["metadata"]["first_parse_error"]["message"].is_string());
assert_eq!(parsed["chunks"][0]["type"], "response.completed");
assert!(parsed.get("raw_response").is_none());
}
#[test]
fn extract_token_counts_from_value_handles_crlf_and_cr_sse_text() {
let sse_body = concat!(