1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
//! Tests for debug logging functionality
//!
//! Tests that debug logs are emitted when images are serialized.
use open_agent::{
AgentOptions, Client, ContentBlock, ImageBlock, ImageDetail, Message, MessageRole, TextBlock,
};
#[tokio::test]
async fn test_image_logging_with_debug_enabled() {
// Initialize env_logger for this test
// Set to debug level to capture log::debug! calls
let _ = env_logger::builder()
.is_test(true)
.filter_level(log::LevelFilter::Debug)
.try_init();
// Create a message with images
let msg = Message::new(
MessageRole::User,
vec![
ContentBlock::Text(TextBlock::new("What's in this image?")),
ContentBlock::Image(
ImageBlock::from_url("https://example.com/test.jpg")
.unwrap()
.with_detail(ImageDetail::High),
),
],
);
// Create a client (logging will happen during message building)
let options = AgentOptions::builder()
.model("test-model")
.base_url("http://localhost:1234/v1")
.build()
.unwrap();
let mut client = Client::new(options).unwrap();
// Add the message with images
client.history_mut().push(msg);
// The logging happens when building OpenAI messages
// This is internal to the send() call, but we can verify
// the message was added to history
assert_eq!(client.history().len(), 1);
// Note: Actual log output would appear in test output with RUST_LOG=debug
// This test verifies the code compiles and runs without errors
}
#[tokio::test]
async fn test_image_logging_truncates_long_urls() {
let _ = env_logger::builder()
.is_test(true)
.filter_level(log::LevelFilter::Debug)
.try_init();
// Create a message with a very long data URI
let long_base64 = "A".repeat(200);
let img = ImageBlock::from_base64(&long_base64, "image/png").unwrap();
let msg = Message::new(MessageRole::User, vec![ContentBlock::Image(img)]);
let options = AgentOptions::builder()
.model("test-model")
.base_url("http://localhost:1234/v1")
.build()
.unwrap();
let mut client = Client::new(options).unwrap();
client.history_mut().push(msg);
// The URL should be >100 chars, so logging should truncate it
assert_eq!(client.history().len(), 1);
// Log output would show: "data:image/png;base64,AAAA... (227 chars)"
}
#[tokio::test]
async fn test_image_logging_includes_detail_level() {
let _ = env_logger::builder()
.is_test(true)
.filter_level(log::LevelFilter::Debug)
.try_init();
// Create messages with different detail levels
let messages = vec![
Message::new(
MessageRole::User,
vec![ContentBlock::Image(
ImageBlock::from_url("https://example.com/low.jpg")
.unwrap()
.with_detail(ImageDetail::Low),
)],
),
Message::new(
MessageRole::User,
vec![ContentBlock::Image(
ImageBlock::from_url("https://example.com/high.jpg")
.unwrap()
.with_detail(ImageDetail::High),
)],
),
Message::new(
MessageRole::User,
vec![ContentBlock::Image(
ImageBlock::from_url("https://example.com/auto.jpg")
.unwrap()
.with_detail(ImageDetail::Auto),
)],
),
];
let options = AgentOptions::builder()
.model("test-model")
.base_url("http://localhost:1234/v1")
.build()
.unwrap();
let mut client = Client::new(options).unwrap();
for msg in messages {
client.history_mut().push(msg);
}
assert_eq!(client.history().len(), 3);
// Log output would show:
// "- Image: https://example.com/low.jpg (detail: low)"
// "- Image: https://example.com/high.jpg (detail: high)"
// "- Image: https://example.com/auto.jpg (detail: auto)"
}
#[test]
fn test_no_warning_for_image_only_messages() {
// GIVEN: Message with only images (no text)
// This is a valid use case for vision models
let image = ImageBlock::from_url("https://example.com/test.jpg")
.unwrap()
.with_detail(ImageDetail::High);
let msg = Message::new(
MessageRole::User,
vec![
ContentBlock::Image(image.clone()),
ContentBlock::Image(image),
],
);
// THEN: Image-only messages are valid and should not trigger warnings
// The warning at src/client.rs:1200-1205 should be removed
assert_eq!(msg.content.len(), 2);
assert!(matches!(msg.content[0], ContentBlock::Image(_)));
assert!(matches!(msg.content[1], ContentBlock::Image(_)));
// This test documents that image-only messages are intentional,
// not bugs. Use cases include:
// - "What's in this image?" (text in system prompt)
// - Multi-image comparison without additional text
// - Visual question answering where the question is implicit
}