configurable rate limit, paths module, verify and bootstrap binaries
This commit is contained in:
parent
888eddf093
commit
0a1246d1f8
7 changed files with 310 additions and 33 deletions
70
src/main.rs
70
src/main.rs
|
|
@ -27,6 +27,7 @@ struct Config {
|
|||
homeserver: String,
|
||||
username: String,
|
||||
password: String,
|
||||
rate_limit_per_min: Option<u32>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
|
|
@ -50,11 +51,12 @@ struct DaemonState {
|
|||
room_history: std::collections::HashMap<OwnedRoomId, Vec<ChatMessage>>,
|
||||
pending_rooms: Vec<OwnedRoomId>,
|
||||
rate_budget: u32,
|
||||
rate_limit_per_min: u32,
|
||||
last_rate_reset: std::time::Instant,
|
||||
}
|
||||
|
||||
const MAX_HISTORY: usize = 20;
|
||||
const RATE_LIMIT_PER_MIN: u32 = 2;
|
||||
const DEFAULT_RATE_LIMIT_PER_MIN: u32 = 1;
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> anyhow::Result<()> {
|
||||
|
|
@ -65,28 +67,34 @@ async fn main() -> anyhow::Result<()> {
|
|||
tracing::info!("damocles-daemon starting");
|
||||
|
||||
let state_dir = paths::state_dir();
|
||||
let identity_dir = paths::identity_dir();
|
||||
fs::create_dir_all(&state_dir).await?;
|
||||
fs::create_dir_all(&identity_dir).await?;
|
||||
fs::create_dir_all(paths::identity_dir()).await?;
|
||||
fs::create_dir_all(state_dir.join("rooms")).await?;
|
||||
fs::create_dir_all(state_dir.join("people")).await?;
|
||||
|
||||
let session_file = paths::session_path();
|
||||
let db_path = paths::db_path();
|
||||
|
||||
let config = load_config().await?;
|
||||
let rate_limit_per_min = config
|
||||
.rate_limit_per_min
|
||||
.unwrap_or(DEFAULT_RATE_LIMIT_PER_MIN);
|
||||
|
||||
let (client, sync_token) = if session_file.exists() {
|
||||
restore_session(&session_file).await?
|
||||
} else {
|
||||
let config = load_config().await?;
|
||||
(login(&config, &db_path, &session_file).await?, None)
|
||||
};
|
||||
|
||||
let own_user_id = client.user_id().context("not logged in")?.to_owned();
|
||||
tracing::info!(user = %own_user_id, "ready");
|
||||
tracing::info!(user = %own_user_id, rate_limit = rate_limit_per_min, "ready");
|
||||
|
||||
let state = Arc::new(Mutex::new(DaemonState {
|
||||
own_user_id,
|
||||
room_history: std::collections::HashMap::new(),
|
||||
pending_rooms: Vec::new(),
|
||||
rate_budget: RATE_LIMIT_PER_MIN,
|
||||
rate_budget: rate_limit_per_min,
|
||||
rate_limit_per_min,
|
||||
last_rate_reset: std::time::Instant::now(),
|
||||
}));
|
||||
|
||||
|
|
@ -114,7 +122,7 @@ async fn restore_session(session_file: &Path) -> anyhow::Result<(Client, Option<
|
|||
|
||||
let client = Client::builder()
|
||||
.homeserver_url(&session.homeserver)
|
||||
.sqlite_store(&session.db_path, None)
|
||||
.sqlite_store(paths::db_path(), None)
|
||||
.build()
|
||||
.await?;
|
||||
|
||||
|
|
@ -259,7 +267,7 @@ async fn process_loop(state: Arc<Mutex<DaemonState>>, client: Client) {
|
|||
let mut state = state.lock().await;
|
||||
|
||||
if state.last_rate_reset.elapsed() >= std::time::Duration::from_secs(60) {
|
||||
state.rate_budget = RATE_LIMIT_PER_MIN;
|
||||
state.rate_budget = state.rate_limit_per_min;
|
||||
state.last_rate_reset = std::time::Instant::now();
|
||||
}
|
||||
|
||||
|
|
@ -339,26 +347,38 @@ async fn invoke_claude(
|
|||
writeln!(prompt, "{prefix}{}: {}", msg.sender, msg.body).unwrap();
|
||||
}
|
||||
|
||||
tracing::debug!("invoking claude with {} messages", history.len());
|
||||
tracing::info!("invoking claude with {} messages", history.len());
|
||||
tracing::debug!("prompt: {prompt}");
|
||||
|
||||
let output = tokio::process::Command::new("claude")
|
||||
.args([
|
||||
"--print",
|
||||
"--bare",
|
||||
"--add-dir",
|
||||
&identity_str,
|
||||
"--allowedTools",
|
||||
"Read Edit Write Glob Grep",
|
||||
])
|
||||
.current_dir(&identity_dir)
|
||||
.arg(&prompt)
|
||||
.output()
|
||||
.await
|
||||
.context("failed to run claude")?;
|
||||
use tokio::process::Command;
|
||||
let mut cmd = Command::new("claude");
|
||||
cmd.args([
|
||||
"--print",
|
||||
"--add-dir",
|
||||
&identity_str,
|
||||
"--allowedTools",
|
||||
"Read Edit Write Glob Grep",
|
||||
"-p",
|
||||
&prompt,
|
||||
]);
|
||||
cmd.current_dir(&identity_dir);
|
||||
cmd.stdin(std::process::Stdio::null());
|
||||
let output = cmd.output().await.context("failed to run claude")?;
|
||||
|
||||
let stderr = String::from_utf8_lossy(&output.stderr);
|
||||
let stdout = String::from_utf8_lossy(&output.stdout);
|
||||
|
||||
if !output.status.success() {
|
||||
let stderr = String::from_utf8_lossy(&output.stderr);
|
||||
bail!("claude exited with {}: {stderr}", output.status);
|
||||
bail!(
|
||||
"claude exited with {}:\nstdout: {}\nstderr: {}",
|
||||
output.status,
|
||||
stdout,
|
||||
stderr
|
||||
);
|
||||
}
|
||||
|
||||
if !stderr.is_empty() {
|
||||
tracing::warn!("claude stderr: {stderr}");
|
||||
}
|
||||
|
||||
let raw = String::from_utf8_lossy(&output.stdout).to_string();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue