Signed-off-by: 未知时光 <732857315@qq.com>
This commit is contained in:
14
plugins/plugin-sdk/Cargo.toml
Normal file
14
plugins/plugin-sdk/Cargo.toml
Normal file
@@ -0,0 +1,14 @@
|
||||
[package]
|
||||
name = "agentsd-plugin-sdk"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
agentsd-proto = { path = "../../core/proto" }
|
||||
anyhow = { workspace = true }
|
||||
serde = { workspace = true }
|
||||
serde_json = { workspace = true }
|
||||
tonic = { workspace = true }
|
||||
tokio = { workspace = true }
|
||||
tokio-stream = { workspace = true }
|
||||
tracing = { workspace = true }
|
||||
132
plugins/plugin-sdk/src/lib.rs
Normal file
132
plugins/plugin-sdk/src/lib.rs
Normal file
@@ -0,0 +1,132 @@
|
||||
use agentsd_proto::agentsd::*;
|
||||
use anyhow::{anyhow, Context, Result};
|
||||
use serde::{de::DeserializeOwned, Serialize};
|
||||
use tonic::metadata::MetadataValue;
|
||||
use tonic::transport::Channel;
|
||||
use tonic::Request;
|
||||
|
||||
pub const DEFAULT_AGENTSD_ADDR: &str = "http://[::1]:50051";
|
||||
|
||||
pub fn agentsd_addr() -> String {
|
||||
std::env::var("AGENTSD_ADDR").unwrap_or_else(|_| DEFAULT_AGENTSD_ADDR.to_string())
|
||||
}
|
||||
|
||||
pub async fn connect() -> Result<Channel> {
|
||||
connect_to(&agentsd_addr()).await
|
||||
}
|
||||
|
||||
pub async fn connect_to(addr: &str) -> Result<Channel> {
|
||||
Channel::from_shared(addr.to_string())
|
||||
.with_context(|| format!("invalid agentsd address: {addr}"))?
|
||||
.connect()
|
||||
.await
|
||||
.with_context(|| format!("connect agentsd at {addr}"))
|
||||
}
|
||||
|
||||
pub fn request_with_plugin<T>(plugin_id: &str, message: T) -> Result<Request<T>> {
|
||||
let mut req = Request::new(message);
|
||||
let value = MetadataValue::try_from(plugin_id)
|
||||
.map_err(|_| anyhow!("invalid plugin id for metadata: {plugin_id}"))?;
|
||||
req.metadata_mut().insert("x-plugin-id", value);
|
||||
Ok(req)
|
||||
}
|
||||
|
||||
pub fn export(name: &str, description: &str) -> ExportDef {
|
||||
ExportDef {
|
||||
name: name.to_string(),
|
||||
description: description.to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn plugin_info(
|
||||
id: &str,
|
||||
name: &str,
|
||||
version: &str,
|
||||
plugin_type: &str,
|
||||
syscalls: &[&str],
|
||||
depends: &[&str],
|
||||
exports: Vec<ExportDef>,
|
||||
) -> PluginInfo {
|
||||
PluginInfo {
|
||||
id: id.to_string(),
|
||||
name: name.to_string(),
|
||||
version: version.to_string(),
|
||||
plugin_type: plugin_type.to_string(),
|
||||
syscalls: syscalls.iter().map(|s| s.to_string()).collect(),
|
||||
depends: depends.iter().map(|s| s.to_string()).collect(),
|
||||
exports,
|
||||
endpoint: String::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn plugin_info_with_endpoint(
|
||||
id: &str,
|
||||
name: &str,
|
||||
version: &str,
|
||||
plugin_type: &str,
|
||||
syscalls: &[&str],
|
||||
depends: &[&str],
|
||||
exports: Vec<ExportDef>,
|
||||
endpoint: &str,
|
||||
) -> PluginInfo {
|
||||
let mut info = plugin_info(id, name, version, plugin_type, syscalls, depends, exports);
|
||||
info.endpoint = endpoint.to_string();
|
||||
info
|
||||
}
|
||||
|
||||
pub async fn register(channel: Channel, info: PluginInfo) -> Result<RegisterResponse> {
|
||||
let mut bridge = plugin_bridge_client::PluginBridgeClient::new(channel);
|
||||
let resp = bridge.register(info).await?.into_inner();
|
||||
if !resp.ok {
|
||||
return Err(anyhow!(resp.error));
|
||||
}
|
||||
Ok(resp)
|
||||
}
|
||||
|
||||
pub fn decode_json<T: DeserializeOwned>(bytes: &[u8]) -> Result<T> {
|
||||
if bytes.is_empty() {
|
||||
serde_json::from_str("{}").context("decode empty JSON object")
|
||||
} else {
|
||||
serde_json::from_slice(bytes).context("decode JSON")
|
||||
}
|
||||
}
|
||||
|
||||
pub fn encode_json<T: Serialize>(value: &T) -> Result<Vec<u8>> {
|
||||
serde_json::to_vec(value).context("encode JSON")
|
||||
}
|
||||
|
||||
pub fn call_response_json<T: Serialize>(value: &T, ok: bool, error: impl Into<String>) -> CallResponse {
|
||||
match encode_json(value) {
|
||||
Ok(result) => CallResponse {
|
||||
result,
|
||||
ok,
|
||||
error: error.into(),
|
||||
},
|
||||
Err(e) => CallResponse {
|
||||
result: Vec::new(),
|
||||
ok: false,
|
||||
error: e.to_string(),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ok_json<T: Serialize>(value: &T) -> CallResponse {
|
||||
call_response_json(value, true, "")
|
||||
}
|
||||
|
||||
pub fn err_json(error: impl Into<String>) -> CallResponse {
|
||||
let error = error.into();
|
||||
let payload = serde_json::json!({ "error": error });
|
||||
call_response_json(&payload, false, error)
|
||||
}
|
||||
|
||||
pub fn plugin_endpoint_from_env(default_port: u16) -> String {
|
||||
if let Ok(endpoint) = std::env::var("PLUGIN_ENDPOINT") {
|
||||
return endpoint;
|
||||
}
|
||||
format!("http://[::1]:{}", default_port)
|
||||
}
|
||||
|
||||
pub fn listen_addr_from_env(default_port: u16) -> String {
|
||||
std::env::var("PLUGIN_LISTEN_ADDR").unwrap_or_else(|_| format!("[::1]:{}", default_port))
|
||||
}
|
||||
Reference in New Issue
Block a user