[feat] modularized backend with plugin architecture, added module-api
, module-host
, and summarizer
crates, and integrated dynamic module loading into main.rs
This commit is contained in:
14
backend-rust/crates/modules/summarizer/Cargo.toml
Normal file
14
backend-rust/crates/modules/summarizer/Cargo.toml
Normal file
@@ -0,0 +1,14 @@
|
||||
[package]
|
||||
name = "owly-news-module-summarizer"
|
||||
version.workspace = true
|
||||
edition.workspace = true
|
||||
|
||||
[lib]
|
||||
crate-type = ["cdylib"]
|
||||
path = "src/lib.rs"
|
||||
|
||||
[dependencies]
|
||||
anyhow = { workspace = true }
|
||||
serde = { workspace = true, features = ["derive"] }
|
||||
serde_json = { workspace = true }
|
||||
owly-news-module-api = { path = "../../module-api" }
|
50
backend-rust/crates/modules/summarizer/src/lib.rs
Normal file
50
backend-rust/crates/modules/summarizer/src/lib.rs
Normal file
@@ -0,0 +1,50 @@
|
||||
use owly_news_module_api::{cstr_to_str, string_to_cstring_ptr};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::os::raw::c_char;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct SummarizeReq {
|
||||
text: String,
|
||||
#[serde(default = "default_ratio")]
|
||||
ratio: f32,
|
||||
}
|
||||
|
||||
fn default_ratio() -> f32 { 0.2 }
|
||||
|
||||
#[derive(Serialize)]
|
||||
struct SummarizeResp {
|
||||
summary: String,
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub extern "C" fn module_name() -> *const c_char {
|
||||
// IMPORTANT: string must live forever; use a const C string
|
||||
static NAME: &str = "summarizer\0";
|
||||
NAME.as_ptr() as *const c_char
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub extern "C" fn module_invoke(op: *const c_char, payload: *const c_char) -> *mut c_char {
|
||||
// SAFETY: called by trusted host with valid pointers
|
||||
let res = (|| -> anyhow::Result<String> {
|
||||
let op = unsafe { cstr_to_str(op)? };
|
||||
let payload = unsafe { cstr_to_str(payload)? };
|
||||
|
||||
match op {
|
||||
"summarize" => {
|
||||
let req: SummarizeReq = serde_json::from_str(payload)?;
|
||||
// Placeholder summarization logic. Replace with real algorithm.
|
||||
let words: Vec<&str> = req.text.split_whitespace().collect();
|
||||
let take = ((words.len() as f32) * req.ratio).max(1.0).round() as usize;
|
||||
let summary = words.into_iter().take(take).collect::<Vec<_>>().join(" ");
|
||||
let resp = SummarizeResp { summary };
|
||||
Ok(serde_json::to_string(&resp)?)
|
||||
}
|
||||
_ => anyhow::bail!("unknown op: {op}"),
|
||||
}
|
||||
})();
|
||||
|
||||
let json = res.unwrap_or_else(|e| serde_json::json!({ "error": e.to_string() }).to_string());
|
||||
|
||||
string_to_cstring_ptr(json)
|
||||
}
|
Reference in New Issue
Block a user