split-brain-harness 1.1.0

Soul-injected two-stage LLM telemetry pipeline. Wraps any LLM with affective/intent/cognitive analysis, deterministic verification, and a Stage 0 deobfuscation normalizer. Drop-in OpenAI-compatible proxy.
Documentation
use super::InferenceEngine;
use async_trait::async_trait;
use reqwest::Client;
use serde_json::json;

pub struct AnthropicEngine {
    pub endpoint: String,
    pub model: String,
    pub api_key: String,
    pub client: Client,
}

#[async_trait]
impl InferenceEngine for AnthropicEngine {
    async fn generate(&self, system_prompt: &str, prompt_payload: &str) -> Result<String, String> {
        if self.api_key.is_empty() {
            return Err("SBH_API_KEY is required for the Anthropic backend".into());
        }

        let body = json!({
            "model": self.model,
            "max_tokens": 2048,
            "system": system_prompt,
            "messages": [
                { "role": "user", "content": prompt_payload }
            ]
        });

        let resp = self
            .client
            .post(format!(
                "{}/v1/messages",
                self.endpoint.trim_end_matches('/')
            ))
            .header("x-api-key", &self.api_key)
            .header("anthropic-version", "2023-06-01")
            .header("content-type", "application/json")
            .json(&body)
            .send()
            .await
            .map_err(|e| e.to_string())?;

        let status = resp.status();
        let json: serde_json::Value = resp.json().await.map_err(|e| e.to_string())?;

        if !status.is_success() {
            let msg = json["error"]["message"].as_str().unwrap_or("unknown error");
            return Err(format!("Anthropic API error {status}: {msg}"));
        }

        json["content"][0]["text"]
            .as_str()
            .map(|s| s.to_string())
            .ok_or_else(|| "missing content[0].text in Anthropic response".into())
    }
}