重构: 巨函数拆分 + 清理历史标记注释 + custom_prompt/停止按钮/tunnel 改进
This commit is contained in:
@@ -47,7 +47,7 @@ impl Default for TokenEstimator {
|
||||
impl TokenEstimator {
|
||||
/// 估算单条消息的 token 数(保守估计)
|
||||
///
|
||||
/// F-260614-05 多模态回归修正:`msg.parts` 中的 Image.base64 与 Text.text 同样计入预算。
|
||||
/// 多模态回归修正:`msg.parts` 中的 Image.base64 与 Text.text 同样计入预算。
|
||||
/// 此前只算 `content`,含图消息的大段 base64(可达 25 万 tokens)被完全忽略,致
|
||||
/// `history_tokens` 严重低估 → build_for_request 误判未超预算 → provider 超限 400/500。
|
||||
/// 这里把 parts 的文本/base64 按同一 chars_ratio 粗估累加(base64 视为密集字符,0.35 偏保守)。
|
||||
@@ -58,7 +58,7 @@ impl TokenEstimator {
|
||||
match p {
|
||||
crate::provider::ContentPart::Text { text } => char_count += text.chars().count(),
|
||||
crate::provider::ContentPart::Image { base64, url, .. } => {
|
||||
// CR-260618-11#2:0.35 按 base64 字节数粗估,显著高于厂商实际(OpenAI 按像素非字节)。
|
||||
// 0.35 按 base64 字节数粗估,显著高于厂商实际(OpenAI 按像素非字节)。
|
||||
// 偏保守致含图消息 token 高估、过度裁剪;降值(如 0.10~0.15)需独立评估裁剪边界,本次不改值仅标注。
|
||||
// base64 优先(多模态主载荷),url 次之;url 模式无字节,仅按 URL 长度估
|
||||
if let Some(b) = base64 {
|
||||
@@ -145,7 +145,7 @@ pub enum MessageGroup {
|
||||
|
||||
/// 带有 token 缓存和分组信息的消息条目
|
||||
///
|
||||
/// 字段 `pub`:供阶段2 IPC 经 `ContextManager::messages_mut()` 拿到可变切片后,
|
||||
/// 字段 `pub`:供 IPC 经 `ContextManager::messages_mut()` 拿到可变切片后,
|
||||
/// 直接改 `message.status` / 读 `token_count` 做 token 重算(Mutex 单线程访问,
|
||||
/// 同 crate 内安全)。结构体本身也 `pub`(返回类型对外可见)。
|
||||
pub struct TrackedMessage {
|
||||
@@ -408,7 +408,7 @@ pub fn extract_key_info(content: &str, tool_name: &str) -> String {
|
||||
*field = serde_json::Value::String(out.join("\n"));
|
||||
truncated = true;
|
||||
} else if s.chars().count() > TOOL_RESULT_JSON_STR_FIELD_MAX {
|
||||
// BUG-260628-01:单行/少行大字符串绕过行级截断(实测 53/94 次零效果)。
|
||||
// 单行/少行大字符串绕过行级截断(实测 53/94 次零效果)。
|
||||
// 按字符数截断保留头尾,保证压缩至少生效。
|
||||
let head: String = s.chars().take(TOOL_RESULT_JSON_STR_FIELD_MAX / 2).collect();
|
||||
let tail: String = s.chars().skip(s.chars().count().saturating_sub(TOOL_RESULT_JSON_STR_FIELD_MAX / 2)).collect();
|
||||
@@ -439,7 +439,7 @@ pub fn extract_key_info(content: &str, tool_name: &str) -> String {
|
||||
let total = lines.len();
|
||||
let kept_boundary = TOOL_RESULT_HEAD_LINES + TOOL_RESULT_TAIL_LINES;
|
||||
if total <= kept_boundary {
|
||||
// BUG-260628-01:行数少但内容超大的情况(单行 50KB),行级截断无效。
|
||||
// 行数少但内容超大的情况(单行 50KB),行级截断无效。
|
||||
// 按字符数截断保证压缩至少生效。
|
||||
let char_count = content.chars().count();
|
||||
if char_count > TOOL_RESULT_CHAR_LIMIT {
|
||||
@@ -524,7 +524,7 @@ fn is_error_line(line: &str) -> bool {
|
||||
|
||||
/// 淘汰单元:连续消息范围 [..end) + token 总和
|
||||
///
|
||||
/// `pub` 供 `build_eviction_units` 的返回类型对外可见(阶段2/3 调用方读 `end` / `token_sum`)。
|
||||
/// `pub` 供 `build_eviction_units` 的返回类型对外可见(调用方读 `end` / `token_sum`)。
|
||||
pub struct EvictionUnit {
|
||||
pub end: usize,
|
||||
pub token_sum: u32,
|
||||
@@ -541,7 +541,7 @@ pub const PROTECT_COUNT: usize = 6;
|
||||
/// 此类 id 必然无匹配 tool_result,是历史中毒的标志,sanitize 时据此剔除畸形三元组。
|
||||
pub const TOOL_MISSING_PREFIX: &str = "tool_missing_";
|
||||
|
||||
/// 阶段2(path_auth 审批链重构):占位配对完整性(解 400 orphan)常量开关。
|
||||
/// 占位配对完整性(解 400 orphan)常量开关。
|
||||
///
|
||||
/// 根因:审批挂起占位 tool_result(内容为 audit/cache.rs:PENDING_APPROVAL_PLACEHOLDER)
|
||||
/// 与其 tool_call 头经 sanitize/compress 裁剪后丢配对头 → orphan tool_result(无头)→
|
||||
@@ -1118,7 +1118,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn extract_key_info_single_huge_line_no_newline_compressed() {
|
||||
// BUG-260628-01:单行超大内容(50KB)原本逃逸压缩,现按字符数截断保留头尾。
|
||||
// 单行超大内容(50KB)原本逃逸压缩,现按字符数截断保留头尾。
|
||||
let content = "x".repeat(50_000);
|
||||
let result = extract_key_info(&content, "read_file");
|
||||
assert!(result.len() < content.len(), "单行超长应压缩: {} >= {}", result.len(), content.len());
|
||||
@@ -1130,7 +1130,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn extract_key_info_json_huge_string_field_truncated() {
|
||||
// BUG-260628-01:JSON 对象中大字符串字段(单行少行)逃逸压缩。
|
||||
// JSON 对象中大字符串字段(单行少行)逃逸压缩。
|
||||
// 如 `{"path":"src/main.rs","content":"单行超大文本..."}`。
|
||||
let large = "z".repeat(10_000);
|
||||
let content = format!("{{\"path\":\"src/main.rs\",\"content\":\"{}\"}}", large);
|
||||
@@ -1243,7 +1243,7 @@ mod tests {
|
||||
assert!(toks.contains(&"now".to_string()));
|
||||
}
|
||||
|
||||
// ── 阶段2 占位配对完整性:is_pending_placeholder / extract_pending_tc_id ──
|
||||
// ── 占位配对完整性:is_pending_placeholder / extract_pending_tc_id ──
|
||||
|
||||
#[test]
|
||||
fn is_pending_placeholder_new_with_marker() {
|
||||
|
||||
Reference in New Issue
Block a user