Files
noc/src/config.rs
Fam Zheng dbd729ecb8 add Gitea Bot interface: webhook server, API tool, Caddy ingress
- Add src/gitea.rs: axum webhook server on :9800, handles @mention in
  issues and PRs, spawns claude -p for review, posts result as comment
- Add call_gitea_api tool: LLM can directly call Gitea REST API with
  pre-configured admin token (noc_bot identity)
- Add Caddy to Docker image as ingress layer (subdomain/path routing)
- Config: add gitea section with token_file support for auto-provisioned token
- Update suite.md: VPS-first deployment, SubAgent architecture, Caddy role
2026-04-10 21:09:15 +01:00

87 lines
1.9 KiB
Rust

use serde::Deserialize;
#[derive(Deserialize)]
pub struct Config {
#[serde(default = "default_name")]
pub name: String,
pub tg: TgConfig,
pub auth: AuthConfig,
pub session: SessionConfig,
#[serde(default)]
pub backend: BackendConfig,
#[serde(default)]
pub whisper_url: Option<String>,
#[serde(default)]
pub gitea: Option<GiteaConfig>,
}
#[derive(Deserialize, Clone)]
pub struct GiteaConfig {
pub url: String,
/// Direct token or read from token_file at startup
#[serde(default)]
pub token: String,
#[serde(default)]
pub token_file: Option<String>,
#[serde(default = "default_webhook_port")]
pub webhook_port: u16,
#[serde(default)]
pub webhook_secret: Option<String>,
}
impl GiteaConfig {
/// Resolve token: if token_file is set and token is empty, read from file
pub fn resolve_token(&mut self) {
if self.token.is_empty() {
if let Some(path) = &self.token_file {
match std::fs::read_to_string(path) {
Ok(t) => self.token = t.trim().to_string(),
Err(e) => tracing::error!("failed to read gitea token_file {path}: {e}"),
}
}
}
}
}
fn default_webhook_port() -> u16 {
9800
}
fn default_name() -> String {
"noc".to_string()
}
#[derive(Deserialize, Clone, Default)]
#[serde(tag = "type")]
pub enum BackendConfig {
#[serde(rename = "claude")]
#[default]
Claude,
#[serde(rename = "openai")]
OpenAI {
endpoint: String,
model: String,
#[serde(default = "default_api_key")]
api_key: String,
},
}
fn default_api_key() -> String {
"unused".to_string()
}
#[derive(Deserialize)]
pub struct TgConfig {
pub key: String,
}
#[derive(Deserialize)]
pub struct AuthConfig {
pub passphrase: String,
}
#[derive(Deserialize)]
pub struct SessionConfig {
pub refresh_hour: u32,
}