| 228 | } |
| 229 | |
| 230 | async fn query(&self, query: &ContextQuery) -> anyhow::Result<ContextResult> { |
| 231 | let files = self.get_files().await?; |
| 232 | let results = self |
| 233 | .search_simple(&query.query, &files, query.max_results) |
| 234 | .await; |
| 235 | |
| 236 | let items: Vec<ContextItem> = results |
| 237 | .into_iter() |
| 238 | .map(|(file, score)| { |
| 239 | let content = match query.depth { |
| 240 | crate::context::ContextDepth::Abstract => { |
| 241 | file.content.chars().take(500).collect::<String>() |
| 242 | } |
| 243 | crate::context::ContextDepth::Overview => { |
| 244 | file.content.chars().take(2000).collect::<String>() |
| 245 | } |
| 246 | crate::context::ContextDepth::Full => file.content.clone(), |
| 247 | }; |
| 248 | |
| 249 | let token_count = content.split_whitespace().count(); |
| 250 | |
| 251 | ContextItem::new( |
| 252 | file.path.to_string_lossy().to_string(), |
| 253 | ContextType::Resource, |
| 254 | content, |
| 255 | ) |
| 256 | .with_token_count(token_count) |
| 257 | .with_relevance(score) |
| 258 | .with_source(format!("file:{}", file.path.display())) |
| 259 | .with_provenance("file_system") |
| 260 | .with_priority(0.55) |
| 261 | .with_trust(0.8) |
| 262 | .with_freshness(0.75) |
| 263 | .with_metadata("path", serde_json::json!(file.path.to_string_lossy())) |
| 264 | .with_metadata("size", serde_json::json!(file.size)) |
| 265 | }) |
| 266 | .collect(); |
| 267 | |
| 268 | let total_tokens: usize = items.iter().map(|item| item.token_count).sum(); |
| 269 | let truncated = items.len() < files.len(); |
| 270 | |
| 271 | Ok(ContextResult { |
| 272 | items, |
| 273 | total_tokens, |
| 274 | provider: self.name().to_string(), |
| 275 | truncated, |
| 276 | }) |
| 277 | } |
| 278 | } |
| 279 | |
| 280 | #[cfg(test)] |