Skip to main content

everruns_core/capabilities/
sample_data.rs

1//! Sample Data Capability
2//!
3//! A demonstration capability that shows how capabilities can mount files and
4//! directories in the session filesystem. This capability mounts sample data
5//! files that agents can read during execution.
6//!
7//! Mount points:
8//! - `/samples/users.json` - Sample user data
9//! - `/samples/config.yaml` - Sample configuration
10//! - `/samples/README.md` - Documentation about the sample files
11
12use super::{
13    Capability, CapabilityLocalization, CapabilityStatus, MountDirectoryBuilder, MountPoint,
14};
15
16pub const SAMPLE_DATA_CAPABILITY_ID: &str = "sample_data";
17
18/// Sample Data capability - demonstrates capability mounting
19pub struct SampleDataCapability;
20
21impl SampleDataCapability {
22    /// Sample users JSON data
23    const USERS_JSON: &'static str = r#"[
24  {
25    "id": 1,
26    "name": "Alice Johnson",
27    "email": "alice@example.com",
28    "role": "admin",
29    "active": true
30  },
31  {
32    "id": 2,
33    "name": "Bob Smith",
34    "email": "bob@example.com",
35    "role": "user",
36    "active": true
37  },
38  {
39    "id": 3,
40    "name": "Carol Davis",
41    "email": "carol@example.com",
42    "role": "user",
43    "active": false
44  }
45]"#;
46
47    /// Sample configuration YAML
48    const CONFIG_YAML: &'static str = r#"# Sample Configuration
49application:
50  name: "Sample App"
51  version: "1.0.0"
52  debug: false
53
54database:
55  host: localhost
56  port: 5432
57  name: sample_db
58  pool_size: 10
59
60features:
61  enable_notifications: true
62  enable_analytics: false
63  max_upload_size_mb: 50
64
65logging:
66  level: info
67  format: json
68"#;
69
70    /// README content
71    const README: &'static str = r#"# Sample Data Files
72
73This directory contains sample data files mounted by the Sample Data capability.
74
75## Available Files
76
77- `users.json` - A JSON array of sample user records with fields:
78  - `id`: Unique user identifier
79  - `name`: User's full name
80  - `email`: User's email address
81  - `role`: User role (admin/user)
82  - `active`: Whether the account is active
83
84- `config.yaml` - A sample YAML configuration file demonstrating:
85  - Application settings
86  - Database configuration
87  - Feature flags
88  - Logging settings
89
90## Usage
91
92These files are read-only and provided for demonstration purposes.
93You can read them using the file system tools to see examples of
94data formats commonly used in applications.
95
96## Notes
97
98- Files in this directory cannot be modified (read-only mount)
99- Use `read_file` tool to read the contents
100- Use `list_directory` to see available files
101"#;
102}
103
104impl Capability for SampleDataCapability {
105    fn id(&self) -> &str {
106        SAMPLE_DATA_CAPABILITY_ID
107    }
108
109    fn name(&self) -> &str {
110        "Sample Data"
111    }
112
113    fn description(&self) -> &str {
114        "Mounts sample data files in the session filesystem for demonstration and testing. Includes example JSON, YAML, and documentation files."
115    }
116
117    fn localizations(&self) -> Vec<CapabilityLocalization> {
118        vec![CapabilityLocalization::text(
119            "uk",
120            "Зразкові дані",
121            "Монтує файли зі зразковими даними у файлову систему сесії для демонстрації та тестування. Містить приклади JSON, YAML і файлів документації.",
122        )]
123    }
124
125    fn status(&self) -> CapabilityStatus {
126        CapabilityStatus::Available
127    }
128
129    fn icon(&self) -> Option<&str> {
130        Some("database")
131    }
132
133    fn category(&self) -> Option<&str> {
134        Some("Data")
135    }
136
137    fn system_prompt_addition(&self) -> Option<&str> {
138        Some(
139            "Read-only sample files are mounted at `/samples` (`users.json`, `config.yaml`, `README.md`) for demos, tests, and templates.",
140        )
141    }
142
143    fn mounts(&self) -> Vec<MountPoint> {
144        let samples_dir = MountDirectoryBuilder::new()
145            .file("users.json", Self::USERS_JSON)
146            .file("config.yaml", Self::CONFIG_YAML)
147            .file("README.md", Self::README)
148            .build();
149
150        vec![MountPoint::readonly("/samples", samples_dir, self.id())]
151    }
152
153    fn dependencies(&self) -> Vec<&'static str> {
154        // Sample Data depends on Session File System for file operations
155        vec!["session_file_system"]
156    }
157
158    fn features(&self) -> Vec<&'static str> {
159        vec!["file_system"]
160    }
161}
162
163#[cfg(test)]
164mod tests {
165    use super::*;
166    use crate::capability_types::MountSource;
167
168    // Metadata constants covered by builtin_capabilities_satisfy_registry_invariants.
169
170    #[test]
171    fn test_capability_has_system_prompt() {
172        let cap = SampleDataCapability;
173        let prompt = cap.system_prompt_addition().unwrap();
174        assert!(prompt.contains("/samples"));
175        assert!(prompt.contains("users.json"));
176        assert!(prompt.contains("config.yaml"));
177    }
178
179    #[test]
180    fn test_capability_has_mounts() {
181        let cap = SampleDataCapability;
182        let mounts = cap.mounts();
183
184        assert_eq!(mounts.len(), 1);
185
186        let mount = &mounts[0];
187        assert_eq!(mount.path, "/samples");
188        assert!(mount.is_readonly());
189        assert_eq!(mount.capability_id, "sample_data");
190
191        // Check directory structure
192        match &mount.source {
193            MountSource::InlineDirectory { entries } => {
194                assert_eq!(entries.len(), 3);
195                assert!(entries.contains_key("users.json"));
196                assert!(entries.contains_key("config.yaml"));
197                assert!(entries.contains_key("README.md"));
198            }
199            _ => panic!("Expected InlineDirectory"),
200        }
201    }
202
203    #[test]
204    fn test_sample_users_json_is_valid() {
205        let json: serde_json::Value =
206            serde_json::from_str(SampleDataCapability::USERS_JSON).unwrap();
207        assert!(json.is_array());
208        let users = json.as_array().unwrap();
209        assert_eq!(users.len(), 3);
210    }
211
212    #[test]
213    fn test_sample_config_yaml_is_valid() {
214        // Just check it's not empty and looks like YAML
215        assert!(SampleDataCapability::CONFIG_YAML.contains("application:"));
216        assert!(SampleDataCapability::CONFIG_YAML.contains("database:"));
217    }
218}