Skip to main content

codetether_agent/session/helper/runtime/
context.rs

1use super::{path::normalize_workspace_paths, provenance::insert_provenance_fields};
2use serde_json::{Map, Value, json};
3use std::path::Path;
4
5/// Enrich tool input with session metadata, provenance, and workspace-aware paths.
6///
7/// # Examples
8///
9/// ```rust
10/// use codetether_agent::session::helper::runtime::enrich_tool_input_with_runtime_context;
11/// use serde_json::json;
12/// use std::path::Path;
13///
14/// let enriched = enrich_tool_input_with_runtime_context(
15///     &json!({"path": "src/lib.rs"}),
16///     Path::new("/workspace"),
17///     Some("example/model"),
18///     "session-1",
19///     "agent-build",
20///     None,
21/// );
22///
23/// assert_eq!(enriched["path"], "/workspace/src/lib.rs");
24/// assert_eq!(enriched["__ct_session_id"], "session-1");
25/// ```
26pub fn enrich_tool_input_with_runtime_context(
27    tool_input: &Value,
28    workspace_dir: &Path,
29    current_model: Option<&str>,
30    session_id: &str,
31    agent_name: &str,
32    provenance: Option<&crate::provenance::ExecutionProvenance>,
33) -> Value {
34    let mut enriched = tool_input.clone();
35    if let Value::Object(ref mut obj) = enriched {
36        insert_field(obj, "__ct_current_model", current_model);
37        obj.entry("__ct_session_id".to_string())
38            .or_insert_with(|| json!(session_id));
39        obj.entry("__ct_agent_name".to_string())
40            .or_insert_with(|| json!(agent_name));
41        if let Some(provenance) = provenance {
42            insert_provenance_fields(obj, provenance);
43        }
44        normalize_workspace_paths(obj, workspace_dir);
45    }
46    enriched
47}
48
49/// Insert a string field into a JSON object only when the value is present.
50///
51/// # Examples
52///
53/// ```rust
54/// use codetether_agent::session::helper::runtime::insert_field;
55/// use serde_json::{Map, Value};
56///
57/// let mut obj = Map::<String, Value>::new();
58/// insert_field(&mut obj, "example", Some("value"));
59/// insert_field(&mut obj, "missing", None);
60///
61/// assert_eq!(obj["example"], "value");
62/// assert!(!obj.contains_key("missing"));
63/// ```
64pub fn insert_field(obj: &mut Map<String, Value>, key: &str, value: Option<&str>) {
65    if let Some(value) = value {
66        obj.entry(key.to_string()).or_insert_with(|| json!(value));
67    }
68}