persistent auth in SQLite, API chat/logs, agent completion via channel
- Auth: move from state.json to SQLite authed_chats table, with memory cache - Remove Persistent/state.json, all state now in noc.db - HTTP API: POST /api/chat (end-to-end LLM), GET /api/logs (failed API requests) - API logging: store raw request/response for 400 errors in api_log table - Agent completion: spawn_agent sends LifeEvent::AgentDone via channel, life loop picks up with full conversation context and responds - Config structs: derive Clone for HTTP server - System prompt: instruct LLM not to add timestamps - Makefile: rsync without --delete to preserve VPS-only tools
This commit is contained in:
31
src/main.rs
31
src/main.rs
@@ -77,10 +77,12 @@ async fn main() {
|
||||
gitea.resolve_token();
|
||||
}
|
||||
|
||||
let state_path = std::env::var("NOC_STATE")
|
||||
.map(PathBuf::from)
|
||||
.unwrap_or_else(|_| PathBuf::from("state.json"));
|
||||
let state = Arc::new(AppState::load(state_path));
|
||||
// channel: http/agents → life loop
|
||||
let (life_tx, life_rx) = tokio::sync::mpsc::channel(16);
|
||||
|
||||
let config_path = std::env::var("NOC_CONFIG").unwrap_or_else(|_| "config.yaml".into());
|
||||
let db_dir = Path::new(&config_path).parent().unwrap_or(Path::new("."));
|
||||
let state = Arc::new(AppState::load(db_dir, life_tx.clone()));
|
||||
|
||||
let _ = std::fs::create_dir_all(incoming_dir());
|
||||
|
||||
@@ -93,18 +95,15 @@ async fn main() {
|
||||
|
||||
let config = Arc::new(config);
|
||||
|
||||
// channel: http server → life loop
|
||||
let (life_tx, life_rx) = tokio::sync::mpsc::channel(16);
|
||||
|
||||
// start life loop
|
||||
tokio::spawn(life::life_loop(bot.clone(), state.clone(), config.clone(), life_rx));
|
||||
|
||||
// start http server (API + gitea webhook)
|
||||
{
|
||||
let srv_config = config.clone();
|
||||
let http_config = config.as_ref().clone();
|
||||
let srv_state = state.clone();
|
||||
tokio::spawn(async move {
|
||||
http::start_http_server(&srv_config, srv_state, life_tx).await;
|
||||
http::start_http_server(&http_config, srv_state, life_tx).await;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -173,20 +172,10 @@ async fn handle(
|
||||
let is_private = msg.chat.is_private();
|
||||
let text = msg.text().or(msg.caption()).unwrap_or("").to_string();
|
||||
let raw_id = chat_id.0;
|
||||
let date = session_date(config.session.refresh_hour);
|
||||
|
||||
let is_authed = {
|
||||
let p = state.persist.read().await;
|
||||
p.authed.get(&raw_id) == Some(&date)
|
||||
};
|
||||
|
||||
if !is_authed {
|
||||
if !state.is_authed(raw_id).await {
|
||||
if text.trim() == config.auth.passphrase {
|
||||
{
|
||||
let mut p = state.persist.write().await;
|
||||
p.authed.insert(raw_id, date);
|
||||
}
|
||||
state.save().await;
|
||||
state.set_authed(raw_id).await;
|
||||
bot.send_message(chat_id, "authenticated").await?;
|
||||
info!(chat = raw_id, "authed");
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user