mirror of
https://github.com/fawney19/Aether.git
synced 2026-10-10 19:29:50 +08:00
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:
@@ -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!(
|
||||
|
||||
Reference in New Issue
Block a user