Prhub

#46512 [Rust Frontend] Add error context in tool parser failures

原始 PR 作者 cinnamonica02 合并时间 2026-07-01 12:48 文件变更 12 提交数 1 评论 12 代码增减 +57 / -19

执行摘要

在工具解析失败时添加输入片段上下文

PR 描述提到 'Adds 80-char buffer snippet to parse_buffered_event to enrich error messages on failed parsing',并直接响应了 utils.rs:324 的 TODO:'enrich context for error reporting'。

建议合并此 PR。它虽小但切实提升了可调试性,且安全权衡已在讨论中明确。值得关注的是 80 字符截断和日志安全的设计取舍。

讨论亮点

主要讨论:

  • Codex 机器人 (P1):指出新增的 near 前缀会使所有现有测试期望失效,要求更新。作者回复已更新了受影响解析器的测试。
  • depthfirst-app (安全低风险):指出错误消息中包含的输入片段(最多 80 字符)可能泄漏敏感用户内容到服务器日志。作者回应片段仅出现在结构异常时,并愿意进一步限制长度或改用 tracing::debug! 避免记录。

实现拆解

  1. 核心逻辑修改:在 rust/src/parser/src/utils.rsparse_buffered_event 函数中,将错误分支从直接输出 e.to_string() 改为构造 format!("near {snippet:?}: {e}"),其中 snippet 通过 buffer.char_indices().nth(80).map_or(buffer, |(i, _)| &buffer[..i]) 获取最多前 80 字符。

  2. 测试添加:在 utils.rs 的测试模块中新增两个测试函数 parse_buffered_event_error_includes_input_snippetparse_buffered_event_error_truncates_long_input,验证错误消息包含片段且长输入被截断。

  3. 更新各工具解析器的测试期望:修改了 11 个工具解析器源文件中的测试断言,将原有的精确错误字符串更新为包含 near "..." 前缀的新格式,涉及 granite4.rsllama.rsdeepseek_v3.rs 等所有基于 parse_buffered_event 的解析器。

文件 模块 状态 重要度
rust/src/parser/src/utils.rs 解析器 modified 7.11
rust/src/parser/src/tool/json/granite4.rs 解析器 modified 5.03
rust/src/parser/src/tool/json/llama.rs 解析器 modified 5.03
rust/src/parser/src/tool/deepseek_json/deepseek_v3.rs 解析器 modified 4.94
rust/src/parser/src/tool/kimi_k2.rs 解析器 modified 4.94
rust/src/parser/src/tool/minimax_m3.rs 解析器 modified 4.94
rust/src/parser/src/tool/qwen_coder.rs 解析器 modified 4.94
rust/src/parser/src/tool/deepseek_json/deepseek_v31.rs 解析器 modified 4.7
rust/src/parser/src/tool/minimax_m2.rs 解析器 modified 4.7
rust/src/parser/src/tool/json/internlm2.rs 解析器 modified 4.54
rust/src/parser/src/tool/json/mistral.rs 解析器 modified 4.54
rust/src/parser/src/tool/json/qwen.rs 解析器 modified 4.54

关键符号

parse_buffered_event

关键源码片段

rust/src/parser/src/utils.rs core-logic

核心变更文件:修改 parse_buffered_event 函数以包含输入片段,并新增两个测试用例

/// Parse one event from a buffered streaming input.
///
/// Returns:
/// - `Ok(Some((event, consumed_len)))` if an event was successfully parsed, along with the number
///   of bytes consumed from the buffer.
/// - `Ok(None)` if the buffer does not contain a full event yet, and more data is needed.
/// - `Err` if a parsing error occurred.
pub fn parse_buffered_event<E>(
    buffer: &str,
    parse: impl FnOnce(&mut Partial<&str>) -> ModalResult<E>,
) -> Result<Option<(E, usize)>> {
    let mut input = Partial::new(buffer);
    let checkpoint = input.checkpoint();
    let event = match parse(&mut input) {
        Ok(event) => event,
        Err(ErrMode::Incomplete(_)) => return Ok(None),
        Err(ErrMode::Backtrack(e) | ErrMode::Cut(e)) => {
            // 截取输入缓冲区前 80 字符作为上下文片段
            // 使用 char_indices().nth(80) 安全处理 Unicode 边界
            // 若输入不足 80 字符则使用整个 buffer
            let snippet = buffer.char_indices().nth(80).map_or(buffer, |(i, _)| &buffer[..i]);
            return Err(ToolParserError::ParsingFailed {
                // 格式:near " 输入片段 ": 原始错误描述
                message: format!("near {snippet:?}: {e}"),
            });
        }
    };
    let consumed_len = input.offset_from(&checkpoint);
    if consumed_len == 0 {
        return Ok(None);
    }    Ok(Some((event, consumed_len)))
}

评论区精华

更新测试期望以匹配新的错误前缀 测试

Codex 机器人指出新增的 `near` 前缀使所有测试期望失效,要求更新。

结论:作者已更新所有受影响解析器的测试期望。 · 已解决

错误片段包含的输入可能泄露敏感信息 安全

depthfirst-app 提示 80 字符片段可能记录敏感用户内容到日志。

结论:作者回应片段仅出现在结构异常时,愿意进一步限制长度或改用 tracing::debug!,但当前保持不变。 · 已解决

风险与影响

  • 安全风险:最多 80 字符的输入片段可能包含用户敏感信息(如 API 密钥),若记录到服务器日志可能导致泄漏。风险较低,因为解析失败通常发生在结构异常输入,但仍需留意。
  • 兼容性风险:错误消息字符串格式变更,依赖精确错误消息的监控或告警系统可能需要适配。
  • 性能风险char_indices().nth(80) 的复杂度为 O(1)(char_indices 是惰性的),几乎无性能影响。
  • 用户:开发者在调试工具解析错误时能直接获取失败输入片段,大大降低排查成本。
  • 系统:无功能或性能影响。
  • 团队:Rust 前端解析模块更容易诊断问题,提高开发效率。
敏感信息泄露风险 错误日志格式变更

关联 Issue

未识别关联 Issue

当前没有检测到明确关联的 Issue 链接,后续同步到相关引用后会出现在这里。

完整报告

参与讨论