agent_core_runtime/agent/
environment.rs1use std::env;
7use std::path::PathBuf;
8
9use chrono::Local;
10
11#[derive(Debug, Clone)]
16pub struct EnvironmentContext {
17 pub working_directory: PathBuf,
19 pub platform: String,
21 pub os_version: Option<String>,
23 pub date: String,
25}
26
27impl EnvironmentContext {
28 pub fn gather() -> Self {
36 let working_directory = env::current_dir().unwrap_or_else(|_| PathBuf::from("."));
37 let platform = env::consts::OS.to_string();
38 let os_version = Self::get_os_version();
39 let date = Local::now().format("%Y-%m-%d").to_string();
40
41 Self {
42 working_directory,
43 platform,
44 os_version,
45 date,
46 }
47 }
48
49 #[cfg(unix)]
51 fn get_os_version() -> Option<String> {
52 use std::process::Command;
53
54 let output = Command::new("uname").arg("-rs").output().ok()?;
55
56 if output.status.success() {
57 String::from_utf8(output.stdout)
58 .ok()
59 .map(|s| s.trim().to_string())
60 } else {
61 None
62 }
63 }
64
65 #[cfg(windows)]
67 fn get_os_version() -> Option<String> {
68 use std::process::Command;
69
70 let output = Command::new("cmd").args(["/C", "ver"]).output().ok()?;
71
72 if output.status.success() {
73 String::from_utf8(output.stdout)
74 .ok()
75 .map(|s| s.trim().to_string())
76 } else {
77 None
78 }
79 }
80
81 #[cfg(not(any(unix, windows)))]
83 fn get_os_version() -> Option<String> {
84 None
85 }
86
87 pub fn to_prompt_section(&self) -> String {
92 let mut lines = Vec::new();
93
94 lines.push(format!(
95 "Working directory: {}",
96 self.working_directory.display()
97 ));
98 lines.push(format!("Platform: {}", self.platform));
99
100 if let Some(ref version) = self.os_version {
101 lines.push(format!("OS Version: {}", version));
102 }
103
104 lines.push(format!("Today's date: {}", self.date));
105
106 format!("<env>\n{}\n</env>", lines.join("\n"))
107 }
108}
109
110impl Default for EnvironmentContext {
111 fn default() -> Self {
112 Self::gather()
113 }
114}
115
116#[cfg(test)]
117mod tests {
118 use super::*;
119
120 #[test]
121 fn test_gather_environment() {
122 let ctx = EnvironmentContext::gather();
123
124 assert!(!ctx.working_directory.as_os_str().is_empty());
126
127 assert!(!ctx.platform.is_empty());
129
130 assert_eq!(ctx.date.len(), 10);
132 assert!(ctx.date.contains('-'));
133 }
134
135 #[test]
136 fn test_to_prompt_section() {
137 let ctx = EnvironmentContext {
138 working_directory: PathBuf::from("/test/path"),
139 platform: "darwin".to_string(),
140 os_version: Some("Darwin 25.2.0".to_string()),
141 date: "2026-01-31".to_string(),
142 };
143
144 let section = ctx.to_prompt_section();
145
146 assert!(section.starts_with("<env>"));
147 assert!(section.ends_with("</env>"));
148 assert!(section.contains("Working directory: /test/path"));
149 assert!(section.contains("Platform: darwin"));
150 assert!(section.contains("OS Version: Darwin 25.2.0"));
151 assert!(section.contains("Today's date: 2026-01-31"));
152 }
153
154 #[test]
155 fn test_to_prompt_section_without_os_version() {
156 let ctx = EnvironmentContext {
157 working_directory: PathBuf::from("/test/path"),
158 platform: "unknown".to_string(),
159 os_version: None,
160 date: "2026-01-31".to_string(),
161 };
162
163 let section = ctx.to_prompt_section();
164
165 assert!(!section.contains("OS Version:"));
166 assert!(section.contains("Platform: unknown"));
167 }
168}