fix(provider): align native tool system-flattening and add regressions

This commit is contained in:
Chummy 2026-02-19 17:36:57 +08:00
parent 48eb1d1f30
commit d6dca4b890
3 changed files with 76 additions and 1 deletions

View file

@ -348,4 +348,25 @@ mod tests {
assert!(prompt.contains("test_tool"));
assert!(prompt.contains("instr"));
}
#[test]
fn datetime_section_includes_timestamp_and_timezone() {
let tools: Vec<Box<dyn Tool>> = vec![];
let ctx = PromptContext {
workspace_dir: Path::new("/tmp"),
model_name: "test-model",
tools: &tools,
skills: &[],
identity_config: None,
dispatcher_instructions: "instr",
};
let rendered = DateTimeSection.build(&ctx).unwrap();
assert!(rendered.starts_with("## Current Date & Time\n\n"));
let payload = rendered.trim_start_matches("## Current Date & Time\n\n");
assert!(payload.chars().any(|c| c.is_ascii_digit()));
assert!(payload.contains(" ("));
assert!(payload.ends_with(')'));
}
}

View file

@ -1117,7 +1117,12 @@ impl Provider for OpenAiCompatibleProvider {
)
})?;
let api_messages: Vec<Message> = messages
let effective_messages = if self.merge_system_into_user {
Self::flatten_system_messages(messages)
} else {
messages.to_vec()
};
let api_messages: Vec<Message> = effective_messages
.iter()
.map(|m| Message {
role: m.role.clone(),
@ -1863,6 +1868,54 @@ mod tests {
assert_eq!(converted[0].content.as_deref(), Some("done"));
}
#[test]
fn flatten_system_messages_merges_into_first_user() {
let input = vec![
ChatMessage::system("core policy"),
ChatMessage::assistant("ack"),
ChatMessage::system("delivery rules"),
ChatMessage::user("hello"),
ChatMessage::assistant("post-user"),
];
let output = OpenAiCompatibleProvider::flatten_system_messages(&input);
assert_eq!(output.len(), 3);
assert_eq!(output[0].role, "assistant");
assert_eq!(output[0].content, "ack");
assert_eq!(output[1].role, "user");
assert_eq!(output[1].content, "core policy\n\ndelivery rules\n\nhello");
assert_eq!(output[2].role, "assistant");
assert_eq!(output[2].content, "post-user");
assert!(output.iter().all(|m| m.role != "system"));
}
#[test]
fn flatten_system_messages_inserts_user_when_missing() {
let input = vec![
ChatMessage::system("core policy"),
ChatMessage::assistant("ack"),
];
let output = OpenAiCompatibleProvider::flatten_system_messages(&input);
assert_eq!(output.len(), 2);
assert_eq!(output[0].role, "user");
assert_eq!(output[0].content, "core policy");
assert_eq!(output[1].role, "assistant");
assert_eq!(output[1].content, "ack");
}
#[test]
fn strip_think_tags_removes_multiple_blocks() {
let input = "a<think>x</think>b<think>y</think>c";
assert_eq!(strip_think_tags(input), "abc");
}
#[test]
fn strip_think_tags_drops_unclosed_block_suffix() {
let input = "visible<think>hidden";
assert_eq!(strip_think_tags(input), "visible");
}
#[test]
fn native_tool_schema_unsupported_detection_is_precise() {
assert!(OpenAiCompatibleProvider::is_native_tool_schema_unsupported(

View file

@ -691,6 +691,7 @@ mod tests {
assert!(p.is_command_allowed("cargo build --release"));
assert!(p.is_command_allowed("cat file.txt"));
assert!(p.is_command_allowed("grep -r pattern ."));
assert!(p.is_command_allowed("date"));
}
#[test]