//! Integration test for file/folder response optimizations
//!
//! Tests that file/folder operations properly limit and paginate responses
//! Validates requirements from LMS-54
use letta_server::tools::file_folder_ops::{
FileFolderRequest, FileFolderResponse, FileMetadata, FolderMetadata,
};
#[test]
fn test_file_metadata_excludes_content() {
// Verify FileMetadata struct doesn't have content field
let file_meta = FileMetadata {
id: "file-123".to_string(),
filename: "test.txt".to_string(),
size: Some(1024),
mime_type: Some("text/plain".to_string()),
is_open: Some(false),
opened_at: None,
};
// Serialize to JSON and verify no content field exists
let json = serde_json::to_value(&file_meta).unwrap();
assert!(json.get("content").is_none());
assert!(json.get("data").is_none());
assert_eq!(json.get("id").unwrap().as_str().unwrap(), "file-123");
}
#[test]
fn test_list_files_response_structure() {
// Test that list_files response has proper pagination metadata
let response = FileFolderResponse {
success: true,
operation: "list_files".to_string(),
message: "Returned 25 of 100 files".to_string(),
agent_id: Some("agent-123".to_string()),
total: Some(100),
returned: Some(25),
offset: Some(0),
hints: Some(vec![
"File content is NEVER included in list operations".to_string(),
"More files available. Use offset=25 to see next page".to_string(),
]),
files: Some(vec![]),
file_id: None,
folder_id: None,
opened: None,
evicted_files: None,
closed: None,
closed_count: None,
closed_files: None,
folders: None,
attached: None,
detached: None,
agent_state: None,
agent_ids: None,
agents: None,
file_content: None,
content_length: None,
truncated: None,
};
assert_eq!(response.total, Some(100));
assert_eq!(response.returned, Some(25));
assert!(response.hints.is_some());
assert!(response.file_content.is_none());
}
#[test]
fn test_list_folders_response_structure() {
// Test that list_folders response has proper pagination
let response = FileFolderResponse {
success: true,
operation: "list_folders".to_string(),
message: "Returned 20 of 50 folders".to_string(),
total: Some(50),
returned: Some(20),
offset: Some(0),
hints: Some(vec![
"More folders available. Use offset=20 to see next page".to_string(),
]),
folders: Some(vec![]),
agent_id: None,
file_id: None,
folder_id: None,
files: None,
opened: None,
evicted_files: None,
closed: None,
closed_count: None,
closed_files: None,
attached: None,
detached: None,
agent_state: None,
agent_ids: None,
agents: None,
file_content: None,
content_length: None,
truncated: None,
};
assert_eq!(response.total, Some(50));
assert_eq!(response.returned, Some(20));
assert!(response.hints.is_some());
}
#[test]
fn test_open_file_minimal_response() {
// Test that open_file returns minimal confirmation
let response = FileFolderResponse {
success: true,
operation: "open_file".to_string(),
message: "File opened successfully".to_string(),
agent_id: Some("agent-123".to_string()),
file_id: Some("file-456".to_string()),
opened: Some(true),
evicted_files: Some(vec![]),
hints: Some(vec![
"File marked as open in agent context. Content retrieval requires separate API call."
.to_string(),
]),
folder_id: None,
files: None,
closed: None,
closed_count: None,
closed_files: None,
folders: None,
attached: None,
detached: None,
agent_state: None,
agent_ids: None,
agents: None,
total: None,
returned: None,
offset: None,
file_content: None,
content_length: None,
truncated: None,
};
assert_eq!(response.opened, Some(true));
assert!(response.file_content.is_none());
assert!(response.agent_state.is_none());
}
#[test]
fn test_close_file_minimal_response() {
// Test that close_file returns minimal confirmation
let response = FileFolderResponse {
success: true,
operation: "close_file".to_string(),
message: "File closed successfully".to_string(),
agent_id: Some("agent-123".to_string()),
file_id: Some("file-456".to_string()),
closed: Some(true),
folder_id: None,
files: None,
opened: None,
evicted_files: None,
closed_count: None,
closed_files: None,
folders: None,
attached: None,
detached: None,
agent_state: None,
agent_ids: None,
agents: None,
total: None,
returned: None,
offset: None,
hints: None,
file_content: None,
content_length: None,
truncated: None,
};
assert_eq!(response.closed, Some(true));
assert!(response.files.is_none());
assert!(response.agent_state.is_none());
}
#[test]
fn test_close_all_files_minimal_response() {
// Test that close_all_files returns minimal info
let response = FileFolderResponse {
success: true,
operation: "close_all_files".to_string(),
message: "Closed 5 files".to_string(),
agent_id: Some("agent-123".to_string()),
closed_count: Some(5),
closed_files: Some(vec![
"file-1".to_string(),
"file-2".to_string(),
"file-3".to_string(),
"file-4".to_string(),
"file-5".to_string(),
]),
file_id: None,
folder_id: None,
files: None,
opened: None,
evicted_files: None,
closed: None,
folders: None,
attached: None,
detached: None,
agent_state: None,
agent_ids: None,
agents: None,
total: None,
returned: None,
offset: None,
hints: None,
file_content: None,
content_length: None,
truncated: None,
};
assert_eq!(response.closed_count, Some(5));
assert!(response.closed_files.is_some());
assert_eq!(response.closed_files.unwrap().len(), 5);
}
#[test]
fn test_list_agents_in_folder_minimal_response() {
// Test that list_agents_in_folder returns IDs only
let response = FileFolderResponse {
success: true,
operation: "list_agents_in_folder".to_string(),
message: "Found 3 agents in folder".to_string(),
folder_id: Some("folder-789".to_string()),
agent_ids: Some(vec![
"agent-1".to_string(),
"agent-2".to_string(),
"agent-3".to_string(),
]),
agents: Some(vec![]),
agent_id: None,
file_id: None,
files: None,
opened: None,
evicted_files: None,
closed: None,
closed_count: None,
closed_files: None,
folders: None,
attached: None,
detached: None,
agent_state: None,
total: None,
returned: None,
offset: None,
hints: None,
file_content: None,
content_length: None,
truncated: None,
};
assert!(response.agent_ids.is_some());
assert_eq!(response.agent_ids.unwrap().len(), 3);
// Should not include full agent objects with names, configs, etc.
}
#[test]
fn test_attach_folder_excludes_agent_state() {
// Test that attach_folder doesn't return full agent state
let response = FileFolderResponse {
success: true,
operation: "attach_folder".to_string(),
message: "Folder attached to agent successfully".to_string(),
agent_id: Some("agent-123".to_string()),
folder_id: Some("folder-456".to_string()),
attached: Some(true),
file_id: None,
files: None,
opened: None,
evicted_files: None,
closed: None,
closed_count: None,
closed_files: None,
folders: None,
detached: None,
agent_state: None,
agent_ids: None,
agents: None,
total: None,
returned: None,
offset: None,
hints: None,
file_content: None,
content_length: None,
truncated: None,
};
assert_eq!(response.attached, Some(true));
assert!(response.agent_state.is_none());
}
#[test]
fn test_detach_folder_excludes_agent_state() {
// Test that detach_folder doesn't return full agent state
let response = FileFolderResponse {
success: true,
operation: "detach_folder".to_string(),
message: "Folder detached from agent successfully".to_string(),
agent_id: Some("agent-123".to_string()),
folder_id: Some("folder-456".to_string()),
detached: Some(true),
file_id: None,
files: None,
opened: None,
evicted_files: None,
closed: None,
closed_count: None,
closed_files: None,
folders: None,
attached: None,
agent_state: None,
agent_ids: None,
agents: None,
total: None,
returned: None,
offset: None,
hints: None,
file_content: None,
content_length: None,
truncated: None,
};
assert_eq!(response.detached, Some(true));
assert!(response.agent_state.is_none());
}
#[test]
fn test_folder_metadata_truncates_description() {
// Test that folder descriptions are truncated
let long_desc = "a".repeat(200);
let folder = FolderMetadata {
id: "folder-123".to_string(),
name: "Test Folder".to_string(),
description: Some(long_desc.clone()),
file_count: Some(50),
agent_count: Some(10),
};
// In actual implementation, truncation happens in handle_list_folders
// This test just validates the struct can hold the data
assert!(folder.description.is_some());
}
#[test]
fn test_file_folder_request_defaults() {
// Test that request parsing handles missing optional fields
let request = FileFolderRequest {
operation: "list_files".to_string(),
agent_id: Some("agent-123".to_string()),
file_id: None,
folder_id: None,
limit: None,
offset: None,
request_heartbeat: None,
};
assert_eq!(request.operation, "list_files");
assert!(request.limit.is_none());
assert!(request.offset.is_none());
}