Skip to main content

ldp_protocol/types/
capability.rs

1//! LDP capability manifest types.
2//!
3//! Each delegate advertises capabilities with associated quality, latency,
4//! and cost metadata — richer than A2A/MCP skill listings.
5
6use serde::{Deserialize, Serialize};
7use serde_json::Value;
8
9/// How a quality claim was established — addresses the provenance paradox.
10#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
11#[serde(rename_all = "snake_case")]
12pub enum ClaimType {
13    /// Quality scores reported by the delegate itself.
14    SelfClaimed,
15    /// Quality scores attested by a trusted third-party issuer.
16    IssuerAttested,
17    /// Quality scores measured by the LDP runtime during actual invocations.
18    RuntimeObserved,
19    /// Quality scores verified by an external benchmarking service.
20    ExternallyBenchmarked,
21}
22
23impl Default for ClaimType {
24    fn default() -> Self {
25        ClaimType::SelfClaimed
26    }
27}
28
29/// An LDP capability — a skill with quality/latency/cost metadata.
30#[derive(Debug, Clone, Serialize, Deserialize)]
31pub struct LdpCapability {
32    /// Capability name (e.g. "code-review", "mathematical-reasoning").
33    pub name: String,
34
35    /// Human-readable description.
36    pub description: Option<String>,
37
38    /// Input schema (JSON Schema).
39    pub input_schema: Option<Value>,
40
41    /// Output schema (JSON Schema).
42    pub output_schema: Option<Value>,
43
44    /// Quality and performance metrics for this capability.
45    pub quality: Option<QualityMetrics>,
46
47    /// Domains this capability applies to (e.g. ["rust", "python"]).
48    #[serde(default)]
49    pub domains: Vec<String>,
50}
51
52/// Quality, latency, and cost metrics for a capability.
53///
54/// These metrics enable intelligent routing: the JamJet workflow engine
55/// can select among multiple delegates based on quality-cost tradeoffs.
56#[derive(Debug, Clone, Serialize, Deserialize)]
57pub struct QualityMetrics {
58    /// Self-reported quality score (0.0 – 1.0).
59    pub quality_score: Option<f64>,
60
61    /// Expected latency in milliseconds (p50).
62    pub latency_p50_ms: Option<u64>,
63
64    /// Expected latency in milliseconds (p99).
65    pub latency_p99_ms: Option<u64>,
66
67    /// Cost per invocation in USD (approximate).
68    pub cost_per_call_usd: Option<f64>,
69
70    /// Maximum tokens this capability can process per call.
71    pub max_tokens: Option<u64>,
72
73    /// Whether this capability supports streaming responses.
74    pub supports_streaming: bool,
75
76    /// How this quality claim was established.
77    #[serde(default)]
78    pub claim_type: ClaimType,
79}
80
81impl Default for QualityMetrics {
82    fn default() -> Self {
83        Self {
84            quality_score: None,
85            latency_p50_ms: None,
86            latency_p99_ms: None,
87            cost_per_call_usd: None,
88            max_tokens: None,
89            supports_streaming: false,
90            claim_type: ClaimType::default(),
91        }
92    }
93}
94
95#[cfg(test)]
96mod tests {
97    use super::*;
98
99    #[test]
100    fn default_claim_type_is_self_claimed() {
101        let metrics = QualityMetrics::default();
102        assert_eq!(metrics.claim_type, ClaimType::SelfClaimed);
103    }
104
105    #[test]
106    fn claim_type_serialization() {
107        let metrics = QualityMetrics {
108            claim_type: ClaimType::IssuerAttested,
109            quality_score: Some(0.95),
110            ..Default::default()
111        };
112        let json = serde_json::to_value(&metrics).unwrap();
113        assert_eq!(json["claim_type"], "issuer_attested");
114        let restored: QualityMetrics = serde_json::from_value(json).unwrap();
115        assert_eq!(restored.claim_type, ClaimType::IssuerAttested);
116    }
117
118    #[test]
119    fn all_claim_types_exist() {
120        let _ = ClaimType::SelfClaimed;
121        let _ = ClaimType::IssuerAttested;
122        let _ = ClaimType::RuntimeObserved;
123        let _ = ClaimType::ExternallyBenchmarked;
124    }
125}