feat: 添加 GBK 解码支持,优化 BashTool 中的输出处理逻辑

This commit is contained in:
oudecheng 2026-05-14 18:54:08 +08:00
parent 23b7497b12
commit b33350c410
2 changed files with 35 additions and 8 deletions

View File

@ -36,3 +36,4 @@ meval = "0.2"
rusqlite = { version = "0.32", features = ["bundled"] }
rustls = { version = "0.23", features = ["ring"] }
wechatbot = { path = "vendor/wechatbot" }
encoding_rs = "0.8"

View File

@ -5,7 +5,7 @@ use std::time::Duration;
use async_trait::async_trait;
use serde_json::json;
use tokio::io::{AsyncBufReadExt, AsyncRead, AsyncReadExt, BufReader};
use tokio::io::{AsyncRead, AsyncReadExt, BufReader};
use tokio::process::Command;
use tokio::sync::{Mutex, mpsc};
use tokio::time::{Instant, sleep_until};
@ -392,25 +392,51 @@ where
R: AsyncRead + Unpin + Send + 'static,
{
let mut reader = BufReader::new(stream);
let mut line = String::new();
let mut buffer = Vec::new();
loop {
line.clear();
match reader.read_line(&mut line).await {
let mut chunk = [0u8; 4096];
match reader.read(&mut chunk).await {
Ok(0) => break,
Ok(_) => {
let _ = tx.send((is_stderr, line.clone()));
Ok(n) => {
buffer.extend_from_slice(&chunk[..n]);
// 处理完整的行
while let Some(pos) = buffer.iter().position(|&b| b == b'\n') {
let line_bytes = &buffer[..pos + 1];
let line = decode_bytes(line_bytes);
let _ = tx.send((is_stderr, line));
buffer.drain(..pos + 1);
}
}
Err(_) => break,
}
}
let mut remainder = String::new();
if reader.read_to_string(&mut remainder).await.is_ok() && !remainder.is_empty() {
// 处理剩余的字节
if !buffer.is_empty() {
let remainder = decode_bytes(&buffer);
let _ = tx.send((is_stderr, remainder));
}
}
/// 尝试 UTF-8 解码,失败则尝试 GBK 解码
fn decode_bytes(bytes: &[u8]) -> String {
// 首先尝试 UTF-8
if let Ok(s) = std::str::from_utf8(bytes) {
return s.to_string();
}
// 尝试 GBK 解码
let (cow, _, had_errors) = encoding_rs::GBK.decode(bytes);
if !had_errors {
return cow.to_string();
}
// 如果 GBK 也失败,使用 lossy 转换
String::from_utf8_lossy(bytes).to_string()
}
fn format_command_output(stdout: &str, stderr: &str, exit_code: Option<i32>) -> String {
let mut output = String::new();