fix(llm): handle_no_tool_calls 仍会落盘空 assistant 行——#168 的同族遗留通道
Los mantenedores suelen responder en 1 día
Nadie ha tomado este issue todavía.
Evaluación
- Dificultad
- 3/5
- Tiempo estimado
- 1-2 días
- Aptitud para principiantes
- 68/100
Línea de trabajo
Read src/run_core.rs around handle_no_tool_calls (lines 835–857) and compare its empty-content handling with the has_persistable_interrupt logic from issue #168. Add a test for a normal stop with empty content and no tool calls, then run cargo test --lib and cargo test --test invariants. Done means the transcript has no empty assistant row, with the predicate covered by an assertion or equivalent reasoning.
Escrito por el modelo de indexación a partir del texto del issue.
Descripción
优先级 P3 · 依赖:无(同族于已修复的 #168)
基线 HEAD = e9e314ec
Summary
#168 修复了「中断在 tool_call 阶段落盘空 assistant 消息」的中断路径,但交付说明
(infra4agent#8)已指出:同族通道 run_core::handle_no_tool_calls 未被处理,
且当时标记为「超范围,故未动」——但没有开跟进单。本单补上这个跟踪项。
src/run_core.rs:835-857:
fn handle_no_tool_calls(&mut self, completion: &Completion, step: usize) -> Option<FinishReason> {
if !completion.tool_calls.is_empty() { return None; }
let mut msg = Message::assistant(completion.content.clone()); // ← content 可为空串
msg.reasoning_content = completion.reasoning_content.clone();
self.push_message(step, msg); // ← 无条件落盘
...
}
即:正常停止(非中断)且 content 为空时,仍会落盘一条
{"role":"assistant","content":""} 的 transcript 行。
为什么目前危害低(但不该长期如此)
#168 的三层防线已把「空 assistant」在出网与读取两侧都拦住了,已实测确认:
serialize_messages_anthropic/ openaibuild_request的is_empty_assistant过滤;SessionReader::load_messages与load_messages_with_orphan_results的加载期过滤。
→ 不会污染线上请求,因此本单是 P3 而非 P2。
建议
两种方向,择一即可(建议 ①):
- 不落盘:
handle_no_tool_calls在content与reasoning_content均为空时
不 push(与#168的has_persistable_interrupt判据保持一致的语义); - 落盘但标记:保留行以便审计,明确标注其为「无内容终止」,
并确保所有 serializer/loader 一致丢弃。
验收条件
- 构造「模型返回
finish_reason=stop+ 空content+ 无 tool_calls」的场景,
断言 transcript 不含空的 assistant 行(或按方向 ② 断言其被一致丢弃); - 回归:
cargo test --lib0 failed;cargo test --test invariants0 failed; - 若为
is_empty_assistant/has_persistable_interrupt类判据,
必须补断言或补等价性论证,不得使用#[mutants::skip](#168 的既定纪律,
已实测该门禁对本修复有效:撤销 skip 后变异可被杀死)。
- Lenguaje dominante
- Rust
- Estrellas
- 4
- Forks
- 0
- Merge medio
- 5 h 32 min
- PR fusionados (30 d)
- 7
Preparar el entorno
- Incluye un Dockerfile o un archivo de Docker Compose
- Sin plantilla de pull request
- Sin guía de contribución
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Más de jeffkit/recursive
-
Dificultad 3/5 1-2 días Aptitud para principiantes 53/100
jeffkit/recursive#195 · 4 comentarios ·
Los mantenedores suelen responder en 1 día
-
Dificultad 4/5 3-5 días Aptitud para principiantes 15/100
Los mantenedores suelen responder en 1 día
-
Dificultad 4/5 3-5 días Aptitud para principiantes 15/100
Los mantenedores suelen responder en 1 día
-
tracking: 安全面闭环——已落地机制的绕过(4 项)Abierto
Dificultad 5/5 Más de una semana Aptitud para principiantes 8/100
Los mantenedores suelen responder en 1 día
-
Dificultad 5/5 Más de una semana Aptitud para principiantes 12/100
Los mantenedores suelen responder en 1 día
Todos los issues de jeffkit/recursive
Issues similares
-
rustix::termios::Termios::OutputModes does not expost some const e.g. OLCUC for musl and macOSAbierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 62/100
bytecodealliance/rustix#1706 · 1 comentario ·
Los mantenedores suelen responder en 11 días
-
`LazyFrameRemote` and `ExecuteRemote` sinks do not accept `Path`, like `LazyFrame` sinks do.Abierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 62/100
-
Bump anybuf version to ^1.0.0Abierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 72/100
wormhole-foundation/wormhole#5062 ·
Los mantenedores suelen responder en 1 día
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 82/100
Los mantenedores suelen responder en 1 día
-
RUSTSEC-2026-0348: Brotli certificate decompression can allocate up to 1 GiB before authenticationAbierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 60/100