agecli-skill-protocol 0.1.0

Wire protocol contract for agecli skill ↔ host UDS communication (binary framing + payload types)
Documentation
use super::*;
use crate::reader::SkillMessageReader;

#[tokio::test]
async fn write_and_read_roundtrip() {
    let (client, server) = tokio::io::duplex(4096);
    let mut writer = SkillMessageWriter::new(client);
    let mut reader = SkillMessageReader::new(server);

    let payload = AckPayload {
        id: "test-1".into(),
        accepted: true,
    };
    writer.write_ack(&payload).await.unwrap();
    drop(writer); // close write side

    let msg = reader.read_message().await.unwrap().unwrap();
    assert_eq!(msg.msg_type, SkillMessageType::Ack);
    let parsed: AckPayload = msg.deserialize_payload().unwrap();
    assert_eq!(parsed.id, "test-1");
    assert!(parsed.accepted);
}

#[tokio::test]
async fn write_and_read_execute() {
    let (client, server) = tokio::io::duplex(4096);
    let mut writer = SkillMessageWriter::new(client);
    let mut reader = SkillMessageReader::new(server);

    let payload = ExecutePayload {
        execution_id: "exec-1".into(),
        command_name: "test:exec".into(),
        command: Some("ls -la".into()),
        args: None,
        working_directory: None,
        environment: None,
        timeout_ms: 30000,
    };
    writer.write_execute(&payload).await.unwrap();
    drop(writer);

    let msg = reader.read_message().await.unwrap().unwrap();
    assert_eq!(msg.msg_type, SkillMessageType::Execute);
    let parsed: ExecutePayload = msg.deserialize_payload().unwrap();
    assert_eq!(parsed.execution_id, "exec-1");
    assert_eq!(parsed.command.as_deref(), Some("ls -la"));
}