feat: enhance safety filters for shell commands by normalizing ANSI-C quoting
This commit is contained in:
@@ -65,10 +65,11 @@ impl SseParser {
|
||||
events.extend(self.flush_event());
|
||||
} else if let Some(ty) = line.strip_prefix("event: ") {
|
||||
self.event_type = Some(ty.trim().to_string());
|
||||
} else if let Some(data) = line.strip_prefix("data: ") {
|
||||
self.data_lines.push(data.to_string());
|
||||
} else if line.starts_with("data:") {
|
||||
self.data_lines.push(String::new());
|
||||
} else if let Some(data) = line.strip_prefix("data:") {
|
||||
// Handle both "data: {...}" (with space) and "data:{...}"
|
||||
// (without space). Some providers omit the trailing space.
|
||||
let data = data.trim_start().to_string();
|
||||
self.data_lines.push(data);
|
||||
}
|
||||
}
|
||||
events
|
||||
@@ -119,7 +120,21 @@ impl SseParser {
|
||||
tracing::warn!("[stream] total_tokens missing in usage chunk");
|
||||
prompt_tokens + completion_tokens
|
||||
});
|
||||
return vec![StreamEvent::Usage { prompt_tokens, completion_tokens, total_tokens }];
|
||||
// Only emit Usage as a standalone event if this chunk
|
||||
// contains nothing else (no choices, no delta). Some
|
||||
// non-standard providers may bundle usage WITH content
|
||||
// in the same chunk; emitting both prevents content loss.
|
||||
let has_other_content = value.get("choices")
|
||||
.and_then(|c| c.as_array())
|
||||
.map(|arr| arr.iter().any(|ch| {
|
||||
ch.get("delta").and_then(|d| d.get("content")).is_some()
|
||||
|| ch.get("delta").and_then(|d| d.get("reasoning_content")).is_some()
|
||||
|| ch.get("delta").and_then(|d| d.get("tool_calls")).is_some()
|
||||
}))
|
||||
.unwrap_or(false);
|
||||
if !has_other_content {
|
||||
return vec![StreamEvent::Usage { prompt_tokens, completion_tokens, total_tokens }];
|
||||
}
|
||||
}
|
||||
}
|
||||
match event_type.as_str() {
|
||||
|
||||
Reference in New Issue
Block a user