fix: add database migration for backend column and fix agent selection race condition
- Add run_migrations() to SQLite store that adds 'backend' column to existing missions tables (CREATE TABLE IF NOT EXISTS doesn't add columns to existing tables) - Fix race condition in new-mission-dialog when switching backends: wait for backendAgents to finish loading before setting default agent, and only use fallback agents for opencode backend
This commit is contained in:
@@ -65,7 +65,7 @@ export function NewMissionDialog({
|
||||
});
|
||||
|
||||
// SWR: fetch agents for selected backend
|
||||
const { data: backendAgents } = useSWR<BackendAgent[]>(
|
||||
const { data: backendAgents, isLoading: backendAgentsLoading } = useSWR<BackendAgent[]>(
|
||||
newMissionBackend ? `backend-${newMissionBackend}-agents` : null,
|
||||
() => listBackendAgents(newMissionBackend),
|
||||
{ revalidateOnFocus: false, dedupingInterval: 30000 }
|
||||
@@ -81,8 +81,11 @@ export function NewMissionDialog({
|
||||
dedupingInterval: 30000,
|
||||
});
|
||||
|
||||
// Parse agents from either backend API or fallback
|
||||
const agents = backendAgents?.map(a => a.name) || parseAgentNames(agentsPayload);
|
||||
// Parse agents from backend API (only use fallback for opencode backend)
|
||||
// For non-opencode backends, wait for backendAgents to load to avoid race condition
|
||||
const agents = newMissionBackend === 'opencode'
|
||||
? (backendAgents?.map(a => a.name) || parseAgentNames(agentsPayload))
|
||||
: (backendAgents?.map(a => a.name) || []);
|
||||
|
||||
const formatWorkspaceType = (type: Workspace['workspace_type']) =>
|
||||
type === 'host' ? 'host' : 'isolated';
|
||||
@@ -104,9 +107,13 @@ export function NewMissionDialog({
|
||||
// Set default agent when dialog opens (only once per open)
|
||||
// Wait for both agents AND config to load before setting defaults
|
||||
useEffect(() => {
|
||||
if (!open || defaultSet || agents.length === 0) return;
|
||||
if (!open || defaultSet) return;
|
||||
// Wait for config to finish loading (undefined = still loading, null/object = loaded)
|
||||
if (config === undefined) return;
|
||||
// Wait for backend agents to finish loading (avoid race condition when switching backends)
|
||||
if (backendAgentsLoading) return;
|
||||
// If no agents available yet, wait
|
||||
if (agents.length === 0) return;
|
||||
|
||||
if (config?.default_agent && agents.includes(config.default_agent)) {
|
||||
setNewMissionAgent(config.default_agent);
|
||||
@@ -114,7 +121,7 @@ export function NewMissionDialog({
|
||||
setNewMissionAgent('Sisyphus');
|
||||
}
|
||||
setDefaultSet(true);
|
||||
}, [open, defaultSet, agents, config]);
|
||||
}, [open, defaultSet, agents, config, backendAgentsLoading]);
|
||||
|
||||
const resetForm = () => {
|
||||
setNewMissionWorkspace('');
|
||||
|
||||
@@ -106,6 +106,9 @@ impl SqliteMissionStore {
|
||||
conn.execute_batch(SCHEMA)
|
||||
.map_err(|e| format!("Failed to run schema: {}", e))?;
|
||||
|
||||
// Run migrations for existing databases
|
||||
Self::run_migrations(&conn)?;
|
||||
|
||||
Ok::<_, String>(conn)
|
||||
})
|
||||
.await
|
||||
@@ -155,6 +158,29 @@ impl SqliteMissionStore {
|
||||
String::new()
|
||||
}
|
||||
}
|
||||
|
||||
/// Run database migrations for existing databases.
|
||||
/// CREATE TABLE IF NOT EXISTS doesn't add columns to existing tables,
|
||||
/// so we need to handle schema changes manually.
|
||||
fn run_migrations(conn: &Connection) -> Result<(), String> {
|
||||
// Check if 'backend' column exists in missions table
|
||||
let has_backend_column: bool = conn
|
||||
.prepare("SELECT 1 FROM pragma_table_info('missions') WHERE name = 'backend'")
|
||||
.map_err(|e| format!("Failed to check for backend column: {}", e))?
|
||||
.exists([])
|
||||
.map_err(|e| format!("Failed to query table info: {}", e))?;
|
||||
|
||||
if !has_backend_column {
|
||||
tracing::info!("Running migration: adding 'backend' column to missions table");
|
||||
conn.execute(
|
||||
"ALTER TABLE missions ADD COLUMN backend TEXT NOT NULL DEFAULT 'opencode'",
|
||||
[],
|
||||
)
|
||||
.map_err(|e| format!("Failed to add backend column: {}", e))?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_status(s: &str) -> MissionStatus {
|
||||
|
||||
Reference in New Issue
Block a user