fix: stuff
This commit is contained in:
parent
6e1251b136
commit
39143e1998
5 changed files with 69 additions and 12 deletions
|
|
@ -13,7 +13,7 @@ reqwest = { version = "0.12", features = ["json"] }
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
axum = "0.7"
|
axum = "0.7"
|
||||||
tower-http = { version = "0.5", features = ["cors"] }
|
tower-http = { version = "0.5", features = ["cors", "set-header", "limit"] }
|
||||||
sea-orm = { version = "1.1", features = ["sqlx-postgres", "runtime-tokio-rustls", "macros"] }
|
sea-orm = { version = "1.1", features = ["sqlx-postgres", "runtime-tokio-rustls", "macros"] }
|
||||||
sea-orm-migration = "1.1"
|
sea-orm-migration = "1.1"
|
||||||
uuid = { version = "1.8", features = ["v4", "serde"] }
|
uuid = { version = "1.8", features = ["v4", "serde"] }
|
||||||
|
|
|
||||||
|
|
@ -130,7 +130,7 @@ async function fetchTasks() {
|
||||||
const task = state.tasks.find((t) => t.id === state.selectedTaskId);
|
const task = state.tasks.find((t) => t.id === state.selectedTaskId);
|
||||||
if (task) {
|
if (task) {
|
||||||
if (shouldFollowLatest && task.runs && task.runs.length > 0) {
|
if (shouldFollowLatest && task.runs && task.runs.length > 0) {
|
||||||
state.selectedRunId = task.runs[task.runs.length - 1].id;
|
state.selectedRunId = task.runs[0].id;
|
||||||
}
|
}
|
||||||
|
|
||||||
renderRunHistory(task);
|
renderRunHistory(task);
|
||||||
|
|
@ -200,8 +200,8 @@ function selectTask(id, runId = null) {
|
||||||
if (runId) {
|
if (runId) {
|
||||||
state.selectedRunId = runId;
|
state.selectedRunId = runId;
|
||||||
} else if (task.runs && task.runs.length > 0) {
|
} else if (task.runs && task.runs.length > 0) {
|
||||||
// Default to latest run if not specified
|
// Default to latest run if not specified (index 0 is newest)
|
||||||
state.selectedRunId = task.runs[task.runs.length - 1].id;
|
state.selectedRunId = task.runs[0].id;
|
||||||
} else {
|
} else {
|
||||||
state.selectedRunId = null;
|
state.selectedRunId = null;
|
||||||
}
|
}
|
||||||
|
|
@ -472,6 +472,20 @@ newTaskForm.addEventListener('submit', async (e) => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
async function checkSession() {
|
||||||
|
try {
|
||||||
|
const response = await fetch(`${API_URL}/auth/session`, { credentials: 'include' });
|
||||||
|
if (response.ok) {
|
||||||
|
state.isAuthenticated = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Session check failed:', error);
|
||||||
|
}
|
||||||
|
state.isAuthenticated = false;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
let isPolling = false;
|
let isPolling = false;
|
||||||
async function startAutoRefresh() {
|
async function startAutoRefresh() {
|
||||||
setInterval(async () => {
|
setInterval(async () => {
|
||||||
|
|
@ -540,11 +554,16 @@ logoutBtn.addEventListener('click', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
async function initializeApp() {
|
async function initializeApp() {
|
||||||
|
const hasSession = await checkSession();
|
||||||
|
|
||||||
|
if (hasSession) {
|
||||||
appEl.classList.remove('hidden');
|
appEl.classList.remove('hidden');
|
||||||
loginOverlay.classList.add('hidden');
|
loginOverlay.classList.add('hidden');
|
||||||
|
|
||||||
await fetchTasks();
|
await fetchTasks();
|
||||||
startAutoRefresh();
|
startAutoRefresh();
|
||||||
|
} else {
|
||||||
|
showLogin();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for callback on load
|
// Check for callback on load
|
||||||
|
|
|
||||||
12
src/agent.rs
12
src/agent.rs
|
|
@ -71,8 +71,16 @@ impl Agent {
|
||||||
pub async fn run(&mut self) -> Result<(String, Option<String>), Box<dyn std::error::Error>> {
|
pub async fn run(&mut self) -> Result<(String, Option<String>), Box<dyn std::error::Error>> {
|
||||||
let mut finished = false;
|
let mut finished = false;
|
||||||
let start_time = Instant::now();
|
let start_time = Instant::now();
|
||||||
let max_duration = Duration::from_secs(120);
|
let max_duration_secs = std::env::var("AGENT_MAX_DURATION_SECS")
|
||||||
let max_turns = 20;
|
.ok()
|
||||||
|
.and_then(|s| s.parse().ok())
|
||||||
|
.unwrap_or(120);
|
||||||
|
let max_duration = Duration::from_secs(max_duration_secs);
|
||||||
|
|
||||||
|
let max_turns = std::env::var("AGENT_MAX_TURNS")
|
||||||
|
.ok()
|
||||||
|
.and_then(|s| s.parse().ok())
|
||||||
|
.unwrap_or(20);
|
||||||
let mut turns = 0;
|
let mut turns = 0;
|
||||||
|
|
||||||
while !finished {
|
while !finished {
|
||||||
|
|
|
||||||
|
|
@ -100,7 +100,11 @@ impl Scheduler {
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
let (logs, answer, status) = match agent.run().await {
|
let (logs, answer, status) = match agent.run().await {
|
||||||
Ok((logs, answer)) => (logs, answer, "completed".to_string()),
|
Ok((logs, answer)) => (logs, answer, "completed".to_string()),
|
||||||
Err(e) => (format!("Scheduled run failed: {}", e), None, "failed".to_string()),
|
Err(e) => (
|
||||||
|
format!("Scheduled run failed: {}", e),
|
||||||
|
None,
|
||||||
|
"failed".to_string(),
|
||||||
|
),
|
||||||
};
|
};
|
||||||
|
|
||||||
let run_complete = task_run::ActiveModel {
|
let run_complete = task_run::ActiveModel {
|
||||||
|
|
@ -110,7 +114,12 @@ impl Scheduler {
|
||||||
answer: Set(answer),
|
answer: Set(answer),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
let _ = run_complete.update(&db).await;
|
if let Err(e) = run_complete.update(&db).await {
|
||||||
|
eprintln!(
|
||||||
|
"Failed to update scheduled run status for task {}: {}",
|
||||||
|
task_id, e
|
||||||
|
);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
||||||
|
|
@ -128,10 +128,24 @@ pub async fn start(db_url: &str) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
.route("/api/tasks/:id", get(get_task).put(update_task))
|
.route("/api/tasks/:id", get(get_task).put(update_task))
|
||||||
.route("/api/tasks/:id/runs", post(rerun_task))
|
.route("/api/tasks/:id/runs", post(rerun_task))
|
||||||
.route("/api/runs/recent", get(get_recent_runs))
|
.route("/api/runs/recent", get(get_recent_runs))
|
||||||
|
.route("/api/auth/session", get(auth_session))
|
||||||
.route("/api/auth/callback", get(auth_callback))
|
.route("/api/auth/callback", get(auth_callback))
|
||||||
.route("/api/auth/refresh", post(auth_refresh))
|
.route("/api/auth/refresh", post(auth_refresh))
|
||||||
.route("/api/auth/logout", post(auth_logout))
|
.route("/api/auth/logout", post(auth_logout))
|
||||||
.layer(cors)
|
.layer(cors)
|
||||||
|
.layer(tower_http::set_header::SetResponseHeaderLayer::overriding(
|
||||||
|
axum::http::header::CONTENT_SECURITY_POLICY,
|
||||||
|
HeaderValue::from_static("default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data:;"),
|
||||||
|
))
|
||||||
|
.layer(tower_http::set_header::SetResponseHeaderLayer::overriding(
|
||||||
|
axum::http::header::X_CONTENT_TYPE_OPTIONS,
|
||||||
|
HeaderValue::from_static("nosniff"),
|
||||||
|
))
|
||||||
|
.layer(tower_http::set_header::SetResponseHeaderLayer::overriding(
|
||||||
|
axum::http::header::REFERRER_POLICY,
|
||||||
|
HeaderValue::from_static("strict-origin-when-cross-origin"),
|
||||||
|
))
|
||||||
|
.layer(tower_http::limit::RequestBodyLimitLayer::new(1024 * 1024)) // 1MB limit
|
||||||
.with_state(state);
|
.with_state(state);
|
||||||
|
|
||||||
let port = std::env::var("PORT").unwrap_or_else(|_| "3000".to_string());
|
let port = std::env::var("PORT").unwrap_or_else(|_| "3000".to_string());
|
||||||
|
|
@ -453,6 +467,13 @@ async fn auth_logout(jar: CookieJar) -> impl IntoResponse {
|
||||||
(jar, StatusCode::NO_CONTENT)
|
(jar, StatusCode::NO_CONTENT)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn auth_session(user: AuthenticatedUser) -> Json<serde_json::Value> {
|
||||||
|
Json(serde_json::json!({
|
||||||
|
"authenticated": true,
|
||||||
|
"user": user.0
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
fn secure() -> bool {
|
fn secure() -> bool {
|
||||||
std::env::var("COOKIE_SECURE")
|
std::env::var("COOKIE_SECURE")
|
||||||
.map(|value| value == "true")
|
.map(|value| value == "true")
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue