use crate::agentic::ExtendedAgentConfigDeclaration;
use crate::golem_agentic::golem::agent::host::get_config_value;
use crate::schema::wit::direct::{self, FromWire, WireSchema};
use crate::schema::{IntoSchema, SchemaGraph, SchemaType, SecretSpec};
use crate::secrets::GuestSecretHandle;
use std::marker::PhantomData;
pub use crate::bindings::golem::secrets::types::SecretError;
pub use crate::golem_agentic::golem::agent::host::ConfigValueError;
#[derive(Debug)]
pub enum SecretAccessError {
Config(ConfigValueError),
Reveal(SecretError),
}
pub struct Config<T>(PhantomData<T>);
impl<T> Default for Config<T> {
fn default() -> Self {
Self::new()
}
}
impl<T> Config<T> {
pub fn new() -> Self {
Self(PhantomData)
}
pub fn get(&self) -> Result<T, ConfigValueError>
where
T: ConfigSchema,
{
T::load(&[])
}
pub fn config_entries() -> Vec<ExtendedAgentConfigDeclaration>
where
T: ConfigSchema,
{
T::describe_config(&[])
}
pub fn wire_config_entries(
builder: &mut crate::schema::wit::direct::WireSchemaBuilder,
) -> Vec<crate::golem_agentic::golem::agent::common::AgentConfigDeclaration>
where
T: ConfigSchema,
{
T::describe_wire_config(&[], builder)
}
}
pub trait ConfigSchema: Sized {
type RpcType: IntoRpcConfigParam;
fn describe_config(path: &[String]) -> Vec<ExtendedAgentConfigDeclaration>;
fn describe_wire_config(
path: &[String],
builder: &mut crate::schema::wit::direct::WireSchemaBuilder,
) -> Vec<crate::golem_agentic::golem::agent::common::AgentConfigDeclaration>;
fn load(path: &[String]) -> Result<Self, ConfigValueError>;
}
impl ConfigSchema for () {
type RpcType = ();
fn describe_config(_path: &[String]) -> Vec<ExtendedAgentConfigDeclaration> {
Vec::new()
}
fn describe_wire_config(
_path: &[String],
_builder: &mut crate::schema::wit::direct::WireSchemaBuilder,
) -> Vec<crate::golem_agentic::golem::agent::common::AgentConfigDeclaration> {
Vec::new()
}
fn load(_path: &[String]) -> Result<Self, ConfigValueError> {
Ok(())
}
}
impl IntoRpcConfigParam for () {
fn into_rpc_param(
self,
_path: &[String],
) -> Vec<crate::golem_agentic::golem::agent::common::TypedAgentConfigValue> {
Vec::new()
}
}
#[doc(hidden)]
pub trait IntoRpcConfigParam: Sized {
fn into_rpc_param(
self,
path: &[String],
) -> Vec<crate::golem_agentic::golem::agent::common::TypedAgentConfigValue>;
}
pub struct Secret<T> {
path: Vec<String>,
config_type: PhantomData<T>,
}
impl<T> Secret<T> {
pub fn new(path: Vec<String>) -> Self {
Self {
path,
config_type: PhantomData::<T>,
}
}
pub fn get(&self) -> Result<T, SecretAccessError>
where
T: FromWire + WireSchema,
{
let handle = self.handle().map_err(SecretAccessError::Config)?;
let value = handle
.with_handle(|handle| {
crate::bindings::golem::secrets::reveal::reveal(handle, &direct::schema::<T>())
})
.expect("secret handle has already been transferred")
.map_err(SecretAccessError::Reveal)?;
Ok(direct::decode(value).expect("failed deserializing secret value"))
}
pub fn handle(&self) -> Result<GuestSecretHandle, ConfigValueError>
where
T: WireSchema,
{
let mut builder = direct::WireSchemaBuilder::default();
let inner = T::append_schema(&mut builder);
let root = builder.push(crate::schema::wit::wire::SchemaTypeBody::SecretType(
crate::schema::wit::wire::SecretSpec {
inner,
category: None,
},
));
let value = get_config_value(&self.path, &builder.finish(root))?;
Ok(direct::decode(value).expect("failed deserializing secret handle"))
}
}
pub fn secret_schema_graph<T>() -> Result<SchemaGraph, crate::schema::validation::SchemaError>
where
T: IntoSchema,
{
crate::schema::try_into_schema_graph::<T>().map(secret_schema_graph_from_inner)
}
fn secret_schema_graph_from_inner(inner_graph: SchemaGraph) -> SchemaGraph {
SchemaGraph {
defs: inner_graph.defs,
root: SchemaType::secret(SecretSpec {
inner: Box::new(inner_graph.root),
category: None,
}),
}
}
#[doc(hidden)]
pub trait InnerTypeHelper {
type Type;
}
impl<T> InnerTypeHelper for Secret<T> {
type Type = T;
}
impl<T> InnerTypeHelper for Config<T> {
type Type = T;
}