Skip to main content

agent_sdk_store_file/
provider_arguments.rs

1use std::path::PathBuf;
2
3use agent_sdk_core::{
4    AgentError, ProviderArgumentStore, domain::ContentRef, tool_records::CanonicalToolName,
5};
6
7use crate::util::{read_bytes, root_join, safe_segment, sha256_hex, write_bytes};
8
9#[derive(Clone, Debug)]
10/// Filesystem-backed raw provider argument store.
11pub struct FileProviderArgumentStore {
12    root: PathBuf,
13}
14
15impl FileProviderArgumentStore {
16    /// Creates a provider argument store rooted under the provided directory.
17    pub fn new(root: impl Into<PathBuf>) -> Self {
18        Self { root: root.into() }
19    }
20
21    fn argument_path(
22        &self,
23        provider_ref: &str,
24        call_id: &str,
25        canonical_tool_name: &CanonicalToolName,
26    ) -> PathBuf {
27        root_join(
28            &self.root,
29            &[
30                "provider_arguments".to_string(),
31                safe_segment(provider_ref),
32                safe_segment(canonical_tool_name.as_str()),
33                format!("{}.json", safe_segment(call_id)),
34            ],
35        )
36    }
37
38    fn argument_ref_path(&self, content_ref: &ContentRef) -> PathBuf {
39        root_join(
40            &self.root,
41            &[
42                "provider_arguments".to_string(),
43                "by_ref".to_string(),
44                format!("{}.json", safe_segment(content_ref.as_str())),
45            ],
46        )
47    }
48}
49
50impl ProviderArgumentStore for FileProviderArgumentStore {
51    fn store_provider_arguments(
52        &self,
53        provider_ref: &str,
54        call_id: &str,
55        canonical_tool_name: &CanonicalToolName,
56        raw_arguments: &str,
57    ) -> Result<Option<ContentRef>, AgentError> {
58        let path = self.argument_path(provider_ref, call_id, canonical_tool_name);
59        write_bytes(&path, raw_arguments.as_bytes())?;
60        let digest = sha256_hex(raw_arguments.as_bytes());
61        let content_ref = ContentRef::new(format!("content.provider_arguments.{}", &digest[..24]));
62        write_bytes(
63            &self.argument_ref_path(&content_ref),
64            raw_arguments.as_bytes(),
65        )?;
66        Ok(Some(content_ref))
67    }
68
69    fn load_provider_arguments_json(
70        &self,
71        content_ref: &ContentRef,
72    ) -> Result<serde_json::Value, AgentError> {
73        let bytes = read_bytes(&self.argument_ref_path(content_ref))?;
74        serde_json::from_slice(&bytes).map_err(|error| {
75            AgentError::contract_violation(format!(
76                "stored provider arguments are not valid JSON: {error}"
77            ))
78        })
79    }
80}