Skip to main content

portalis_packaging/
lib.rs

1//! Packaging Agent - Artifact Assembly
2//!
3//! Creates deployable packages from WASM artifacts.
4
5use async_trait::async_trait;
6use portalis_core::{Agent, AgentCapability, AgentId, ArtifactMetadata, Result};
7use serde::{Deserialize, Serialize};
8
9#[derive(Debug, Clone, Serialize, Deserialize)]
10pub struct PackagingInput {
11    pub wasm_bytes: Vec<u8>,
12    pub test_results: serde_json::Value,
13}
14
15#[derive(Debug, Clone, Serialize, Deserialize)]
16pub struct PackagingOutput {
17    pub package_bytes: Vec<u8>,
18    pub manifest: serde_json::Value,
19    pub metadata: ArtifactMetadata,
20}
21
22pub struct PackagingAgent {
23    id: AgentId,
24}
25
26impl PackagingAgent {
27    pub fn new() -> Self {
28        Self { id: AgentId::new() }
29    }
30}
31
32impl Default for PackagingAgent {
33    fn default() -> Self {
34        Self::new()
35    }
36}
37
38#[async_trait]
39impl Agent for PackagingAgent {
40    type Input = PackagingInput;
41    type Output = PackagingOutput;
42
43    async fn execute(&self, input: Self::Input) -> Result<Self::Output> {
44        tracing::info!("Packaging WASM artifact");
45
46        let manifest = serde_json::json!({
47            "version": "0.1.0",
48            "wasm_size": input.wasm_bytes.len(),
49            "test_results": input.test_results,
50        });
51
52        let metadata = ArtifactMetadata::new(self.name())
53            .with_tag("size", input.wasm_bytes.len().to_string());
54
55        Ok(PackagingOutput {
56            package_bytes: input.wasm_bytes,
57            manifest,
58            metadata,
59        })
60    }
61
62    fn id(&self) -> AgentId {
63        self.id
64    }
65
66    fn name(&self) -> &str {
67        "PackagingAgent"
68    }
69
70    fn capabilities(&self) -> Vec<AgentCapability> {
71        vec![AgentCapability::Packaging]
72    }
73}
74
75#[cfg(test)]
76mod tests {
77    use super::*;
78    use serde_json::json;
79
80    #[tokio::test]
81    async fn test_package_creation() {
82        let agent = PackagingAgent::new();
83
84        let wasm_bytes = vec![0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00];
85        let test_results = json!({
86            "passed": 5,
87            "failed": 0
88        });
89
90        let input = PackagingInput {
91            wasm_bytes: wasm_bytes.clone(),
92            test_results,
93        };
94
95        let output = agent.execute(input).await.unwrap();
96
97        assert_eq!(output.package_bytes, wasm_bytes);
98        assert_eq!(output.manifest["version"], "0.1.0");
99        assert_eq!(output.manifest["wasm_size"], 8);
100    }
101
102    #[tokio::test]
103    async fn test_package_includes_test_results() {
104        let agent = PackagingAgent::new();
105
106        let test_results = json!({
107            "passed": 3,
108            "failed": 1
109        });
110
111        let input = PackagingInput {
112            wasm_bytes: vec![0x00; 100],
113            test_results: test_results.clone(),
114        };
115
116        let output = agent.execute(input).await.unwrap();
117
118        assert_eq!(output.manifest["test_results"], test_results);
119        assert_eq!(output.manifest["wasm_size"], 100);
120    }
121
122    #[test]
123    fn test_agent_metadata() {
124        let agent = PackagingAgent::new();
125
126        assert_eq!(agent.name(), "PackagingAgent");
127        assert_eq!(agent.capabilities(), vec![AgentCapability::Packaging]);
128    }
129}