Skip to main content

netget/server/adc/
actions.rs

1use crate::llm::actions::{
2    protocol_trait::{ActionResult, Protocol, Server},
3    ActionDefinition,
4};
5use crate::protocol::{EventType, SpawnContext};
6use crate::server::p2p_support::{action, parameter};
7use crate::state::AppState;
8use anyhow::{ensure, Result};
9use serde_json::{json, Value};
10use std::{
11    future::Future,
12    net::SocketAddr,
13    pin::Pin,
14    sync::{Arc, LazyLock},
15};
16
17#[derive(Default)]
18pub struct AdcProtocol;
19impl AdcProtocol {
20    pub fn new() -> Self {
21        Self
22    }
23}
24pub fn reply() -> ActionDefinition {
25    action(
26        "adc_reply",
27        "Handler-approved identities, public/private chat, search and peer-connect routing",
28        vec![parameter(
29            "accepted",
30            "boolean",
31            "Approve identification or forwarding",
32            true,
33        )],
34        json!({"type":"adc_reply","accepted":false}),
35    )
36}
37impl Protocol for AdcProtocol {
38    fn protocol_name(&self) -> &'static str {
39        "ADC"
40    }
41    fn stack_name(&self) -> &'static str {
42        "ETH>IP>TCP>ADC"
43    }
44    fn keywords(&self) -> Vec<&'static str> {
45        vec!["adc", "adc"]
46    }
47    fn description(&self) -> &'static str {
48        "Selected ADC hub and peer operations listening role"
49    }
50    fn example_prompt(&self) -> &'static str {
51        "Listen on ADC port 1511; supply protocol decisions with handlers"
52    }
53    fn group_name(&self) -> &'static str {
54        "Peer-to-peer"
55    }
56    fn get_startup_parameters(&self) -> Vec<crate::llm::actions::ParameterDefinition> {
57        crate::server::p2p_support::tls_parameters(true)
58    }
59    fn get_startup_examples(&self) -> crate::llm::actions::StartupExamples {
60        let base = json!({"type":"open_server","base_stack":"adc","port":1511,"instruction":"Serve selected ADC operations"});
61        let mut fixed = base.clone();
62        fixed["event_handlers"] = json!([{"event_pattern":"adc_request","handler":{"type":"static","actions":[reply().example]}}]);
63        let mut script = base.clone();
64        script["event_handlers"] = json!([{"event_pattern":"adc_request","handler":{"type":"script","language":"python","code":"import json,sys\ne=json.load(sys.stdin)['event']\nprint(json.dumps({'actions':[{'type':'adc_reply','error':'denied'}]}))"}}]);
65        crate::llm::actions::StartupExamples::new(base, script, fixed)
66    }
67    fn get_async_actions(&self, _: &AppState) -> Vec<ActionDefinition> {
68        vec![action(
69            "disconnect",
70            "Close this peer",
71            vec![],
72            json!({"type":"disconnect"}),
73        )]
74    }
75    fn get_sync_actions(&self) -> Vec<ActionDefinition> {
76        vec![reply()]
77    }
78    fn get_event_types(&self) -> Vec<EventType> {
79        EVENTS.clone()
80    }
81    fn metadata(&self) -> crate::protocol::ProtocolMetadataV2 {
82        crate::protocol::ProtocolMetadataV2::builder().state(crate::protocol::metadata::DevelopmentState::Experimental).implementation("Native bounded ADC selected codec; TCP and optional implicit TLS").llm_control("Handler-approved identities, public/private chat, search and peer-connect routing").e2e_testing("Independent peer exchanges, malformed input, owner shutdown and standalone feature builds").notes("ADC 1.0 BASE/TIGR, anonymous identities with CID/PID validation and per-connection IDs. ADCS uses verified implicit TLS. Selected BINF/BMSG/DMSG/BSCH/DRES/DCTM/DRCM routing. No GPA/PAS password login, UDP search, NAT traversal or persistent hub account database. 256 connections, 30 s first frame, 600 s idle, 10 s handshake/exchange. No persistent protocol data; handlers supply content and decisions.").max_inbound_bytes(super::codec::MAX_COMMAND).well_known_port(1511).build()
83    }
84}
85impl Server for AdcProtocol {
86    fn spawn(&self, ctx: SpawnContext) -> Pin<Box<dyn Future<Output = Result<SocketAddr>> + Send>> {
87        {
88            let hub = Arc::new(super::codec::Hub::default());
89            Box::pin(crate::server::p2p_support::spawn(
90                ctx,
91                Arc::new(Self),
92                move || super::codec::Device::new(hub.clone()),
93                &EVENTS,
94            ))
95        }
96    }
97    fn execute_action(&self, v: Value) -> Result<ActionResult> {
98        if v["type"] == "disconnect" {
99            return Ok(ActionResult::CloseConnection);
100        }
101        ensure!(v["type"] == "adc_reply", "unknown action");
102        Ok(ActionResult::Custom {
103            name: "adc_reply".into(),
104            data: v,
105        })
106    }
107}
108pub static EVENTS: LazyLock<Vec<EventType>> = LazyLock::new(|| {
109    vec![EventType::new(
110        "adc_request",
111        "Handler-approved identities, public/private chat, search and peer-connect routing",
112        reply().example,
113    )
114    .with_actions(vec![reply()])
115    .with_parameters(vec![
116        parameter("operation", "string", "Selected protocol operation", true),
117        parameter(
118            "identifier",
119            "string",
120            "Requested object, message or file identifier",
121            false,
122        ),
123    ])]
124});