//! Phase 4: factory that builds a stub `LangfuseStream`. Task 22 upgrades //! it to read credentials from params and construct a real client. use std::sync::Arc; use async_trait::async_trait; use dirigent_core::sharing::{StreamBuildError, StreamConfig, StreamFactory}; use dirigent_protocol::streaming::SessionStream; use crate::client::{LangfuseConfig, LangfuseStream}; pub struct LangfuseFactory; #[async_trait] impl StreamFactory for LangfuseFactory { fn kind(&self) -> &'static str { "langfuse" } async fn build(&self, cfg: &StreamConfig) -> Result, StreamBuildError> { // Parse params. Required fields: // host: String (URL) // public_key: String // secret_key: String // // Phase 4 stub: parse-or-fail, then construct LangfuseStream with // the parsed config. Task 22 uses the host to build a reqwest client. let host = cfg.params .get("host").and_then(|v| v.as_str()) .ok_or_else(|| StreamBuildError::Config("missing `host` (url string)".into()))?; let public_key = cfg.params .get("public_key").and_then(|v| v.as_str()) .ok_or_else(|| StreamBuildError::Config("missing `public_key`".into()))?; let secret_key = cfg.params .get("secret_key").and_then(|v| v.as_str()) .ok_or_else(|| StreamBuildError::Config("missing `secret_key`".into()))?; let lf_cfg = LangfuseConfig { host: host.to_string(), public_key: public_key.to_string(), secret_key: secret_key.to_string(), }; let stream = LangfuseStream::new(cfg.name.clone(), lf_cfg, cfg.scope.clone()) .map_err(|e| StreamBuildError::Transport(e.to_string()))?; Ok(stream as Arc) } }