mission canvas: add Refine button + markdown-rendered description
Adds a Refine button to the left of Refresh + Launch on the mission
detail toolbar (draft-only). Clicking it POSTs to a new endpoint that
calls Gemini 2.5 Flash to rewrite the user's freeform description into
a coherent, sectioned Markdown brief (Objective / Context / Scope /
Constraints / Acceptance Criteria / Open Questions) ready for the
research + coding agents to ingest cleanly.
Backend:
- crates/cm-api/src/mission_refiner.rs — Gemini call with a
system prompt that preserves user-provided facts, avoids
invention, and emits raw markdown (not JSON).
- POST /api/missions/{id}/refine — draft-only, 400 on empty
description or non-draft state.
- cm-db::repo::missions::set_description helper.
Frontend:
- MarkdownBlock — tiny zero-dep renderer for h1/h2/h3, bullet +
numbered lists, **bold**, `code`, paragraphs. Deliberately
small; the refiner emits a bounded subset.
- MissionCanvas — Refine button (Sparkles icon, secondary style)
to the left of Refresh; description now renders through
MarkdownBlock instead of a single <p>. Disabled while
description is empty or a refine is in flight.
- lib/api/missions — refineMission client.
This commit is contained in:
@@ -233,6 +233,25 @@ pub async fn list_by_workspace(
|
||||
.collect())
|
||||
}
|
||||
|
||||
pub async fn set_description(
|
||||
pool: &PgPool,
|
||||
id: Uuid,
|
||||
workspace_id: Uuid,
|
||||
description: &str,
|
||||
) -> Result<(), DbError> {
|
||||
sqlx::query(
|
||||
"UPDATE missions
|
||||
SET description = $3, updated_at = now()
|
||||
WHERE id = $1 AND workspace_id = $2",
|
||||
)
|
||||
.bind(id)
|
||||
.bind(workspace_id)
|
||||
.bind(description)
|
||||
.execute(pool)
|
||||
.await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn set_status(
|
||||
pool: &PgPool,
|
||||
id: Uuid,
|
||||
|
||||
Reference in New Issue
Block a user