Agent loop state machine refactor, unified LLM interface, and UI improvements
- Rewrite agent loop as Planning→Executing(N)→Completed state machine with per-step context isolation to prevent token explosion - Split tools and prompts by phase (planning vs execution) - Add advance_step/save_memo tools for step transitions and cross-step memory - Unify LLM interface: remove duplicate types, single chat_with_tools path - Add UTF-8 safe truncation (truncate_str) to prevent panics on Chinese text - Extract CreateForm component, add auto-scroll to execution log - Add report generation with app access URL, non-blocking title generation - Add timer system, file serving, app proxy, exec module - Update Dockerfile with uv, deployment config Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -11,6 +11,11 @@ use crate::AppState;
|
||||
use crate::agent::AgentEvent;
|
||||
use crate::db::{Workflow, PlanStep, Comment};
|
||||
|
||||
#[derive(serde::Serialize)]
|
||||
struct ReportResponse {
|
||||
report: String,
|
||||
}
|
||||
|
||||
type ApiResult<T> = Result<Json<T>, Response>;
|
||||
|
||||
fn db_err(e: sqlx::Error) -> Response {
|
||||
@@ -33,6 +38,7 @@ pub fn router(state: Arc<AppState>) -> Router {
|
||||
.route("/projects/{id}/workflows", get(list_workflows).post(create_workflow))
|
||||
.route("/workflows/{id}/steps", get(list_steps))
|
||||
.route("/workflows/{id}/comments", get(list_comments).post(create_comment))
|
||||
.route("/workflows/{id}/report", get(get_report))
|
||||
.with_state(state)
|
||||
}
|
||||
|
||||
@@ -134,3 +140,22 @@ async fn create_comment(
|
||||
|
||||
Ok(Json(comment))
|
||||
}
|
||||
|
||||
async fn get_report(
|
||||
State(state): State<Arc<AppState>>,
|
||||
Path(workflow_id): Path<String>,
|
||||
) -> Result<Json<ReportResponse>, Response> {
|
||||
let wf = sqlx::query_as::<_, Workflow>(
|
||||
"SELECT * FROM workflows WHERE id = ?"
|
||||
)
|
||||
.bind(&workflow_id)
|
||||
.fetch_optional(&state.db.pool)
|
||||
.await
|
||||
.map_err(db_err)?;
|
||||
|
||||
match wf {
|
||||
Some(w) if !w.report.is_empty() => Ok(Json(ReportResponse { report: w.report })),
|
||||
Some(_) => Err((StatusCode::NOT_FOUND, "Report not yet generated").into_response()),
|
||||
None => Err((StatusCode::NOT_FOUND, "Workflow not found").into_response()),
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user