Skip to main content

distri_filesystem/
config.rs

1use distri_types::configuration::ObjectStorageConfig;
2use distri_types::Part;
3use serde::{Deserialize, Serialize};
4
5/// Configuration for the FileStore
6#[derive(Debug, Clone)]
7pub struct FileSystemConfig {
8    /// Object store backing the filesystem operations
9    pub object_store: ObjectStorageConfig,
10    /// Optional prefix applied to all stored paths (used for run namespacing)
11    pub root_prefix: Option<String>,
12}
13
14impl Default for FileSystemConfig {
15    fn default() -> Self {
16        Self {
17            object_store: ObjectStorageConfig::FileSystem {
18                base_path: ".distri/files".to_string(),
19            },
20            root_prefix: Some("runs/default".to_string()),
21        }
22    }
23}
24
25/// Configuration for intelligent artifact storage decisions
26#[derive(Debug, Clone)]
27pub struct ArtifactStorageConfig {
28    /// Token threshold for Part::Data (approximate token count)
29    pub data_token_threshold: usize,
30    /// Token threshold for Part::Text (approximate token count)
31    pub text_token_threshold: usize,
32    /// Always store images/files as artifacts (typically large binary data)
33    pub always_store_images: bool,
34    /// For testing: always store everything as artifacts to test the behavior
35    pub always_store_for_testing: bool,
36}
37
38impl Default for ArtifactStorageConfig {
39    fn default() -> Self {
40        Self {
41            data_token_threshold: 1000,
42            text_token_threshold: 1000,
43            always_store_images: true,
44            always_store_for_testing: true,
45        }
46    }
47}
48
49impl ArtifactStorageConfig {
50    /// Create configuration for testing - stores everything as artifacts
51    pub fn for_testing() -> Self {
52        Self {
53            data_token_threshold: 0,
54            text_token_threshold: 0,
55            always_store_images: true,
56            always_store_for_testing: true,
57        }
58    }
59
60    /// Create configuration for production - stores based on intelligent thresholds
61    pub fn for_production() -> Self {
62        Self {
63            data_token_threshold: 10000,
64            text_token_threshold: 10000,
65            always_store_images: false,
66            always_store_for_testing: false,
67        }
68    }
69
70    /// Check if part content should be stored separately based on this configuration
71    pub fn should_store(&self, part: &Part) -> bool {
72        if self.always_store_for_testing {
73            return match part {
74                Part::ToolCall(_) => false,
75                Part::Artifact(_) => false,
76                _ => true,
77            };
78        }
79
80        match part {
81            Part::Data(value) => {
82                let estimated_tokens = estimate_json_tokens(value);
83                estimated_tokens > self.data_token_threshold
84            }
85            Part::Text(text) => {
86                let estimated_tokens = estimate_text_tokens(text);
87                estimated_tokens > self.text_token_threshold
88            }
89            Part::ToolCall(_) => false,
90            Part::ToolResult(response) => response.parts.iter().any(|p| self.should_store(p)),
91            Part::Image(_) => self.always_store_images,
92            Part::Artifact(_) => false,
93        }
94    }
95}
96
97/// Parameters for reading files
98#[derive(Debug, Clone, Serialize, Deserialize, Default)]
99pub struct ReadParams {
100    pub start_line: Option<u64>,
101    pub end_line: Option<u64>,
102}
103
104/// File read result with content and metadata
105#[derive(Debug, Clone, Serialize, Deserialize)]
106pub struct FileReadResult {
107    pub content: String,
108    pub start_line: u64,
109    pub end_line: u64,
110    pub total_lines: u64,
111}
112
113/// Directory listing result
114#[derive(Debug, Clone, Serialize, Deserialize)]
115pub struct DirectoryListing {
116    pub path: String,
117    pub entries: Vec<DirectoryEntry>,
118}
119
120/// Directory entry information
121#[derive(Debug, Clone, Serialize, Deserialize)]
122pub struct DirectoryEntry {
123    pub name: String,
124    pub is_file: bool,
125    pub is_dir: bool,
126    pub size: Option<u64>,
127}
128
129/// Search result containing matches
130#[derive(Debug, Clone, Serialize, Deserialize)]
131pub struct SearchResult {
132    pub path: String,
133    pub matches: Vec<SearchMatch>,
134}
135
136/// Individual search match
137#[derive(Debug, Clone, Serialize, Deserialize)]
138pub struct SearchMatch {
139    pub file_path: String,
140    pub line_number: Option<u64>,
141    pub line_content: String,
142    pub match_text: String,
143}
144
145/// Estimate token count for JSON data (rough approximation)
146fn estimate_json_tokens(value: &serde_json::Value) -> usize {
147    let json_string = serde_json::to_string(value).unwrap_or_default();
148    json_string.len() / 4
149}
150
151/// Estimate token count for text (rough approximation)
152fn estimate_text_tokens(text: &str) -> usize {
153    text.len() / 4
154}