fix: Sequential phase execution (DB→Files), compact header, remove URL duplicate
This commit is contained in:
parent
86ac5ca8f5
commit
f4aae20e05
2 changed files with 69 additions and 75 deletions
|
|
@ -885,72 +885,7 @@ impl AppGenerator {
|
||||||
self.add_terminal_output("## Phase 2: Generating content...", TerminalLineType::Progress);
|
self.add_terminal_output("## Phase 2: Generating content...", TerminalLineType::Progress);
|
||||||
self.update_manifest_stats_real(true);
|
self.update_manifest_stats_real(true);
|
||||||
|
|
||||||
// ========== PHASE 2: Generate content for each file ==========
|
// ========== PHASE 2A: DATABASE & MODELS (must come first!) ==========
|
||||||
let total_items = llm_app.files.len() + llm_app.tools.len() + llm_app.schedulers.len();
|
|
||||||
let mut generated_count = 0;
|
|
||||||
|
|
||||||
// Generate content for files that don't have it yet
|
|
||||||
let files_needing_content: Vec<usize> = llm_app.files.iter()
|
|
||||||
.enumerate()
|
|
||||||
.filter(|(_, f)| f.content.is_empty())
|
|
||||||
.map(|(i, _)| i)
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
info!("[PHASE2] Files needing content: {} out of {} total files", files_needing_content.len(), llm_app.files.len());
|
|
||||||
for (i, file) in llm_app.files.iter().enumerate() {
|
|
||||||
info!("[PHASE2] File {}: {} - content_len={}", i, file.filename, file.content.len());
|
|
||||||
}
|
|
||||||
|
|
||||||
if !files_needing_content.is_empty() {
|
|
||||||
info!("[PHASE2] Setting Files section to Running - manifest exists: {}", self.manifest.is_some());
|
|
||||||
|
|
||||||
// Debug: List all sections before update
|
|
||||||
if let Some(ref manifest) = self.manifest {
|
|
||||||
info!("[PHASE2] Current manifest sections:");
|
|
||||||
for (i, s) in manifest.sections.iter().enumerate() {
|
|
||||||
info!("[PHASE2] [{}] {:?} = '{}' status={:?}", i, s.section_type, s.name, s.status);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
self.update_manifest_section(SectionType::Files, SectionStatus::Running);
|
|
||||||
self.broadcast_manifest_update();
|
|
||||||
self.add_terminal_output(&format!("## Phase 2: Generating {} files...", files_needing_content.len()), TerminalLineType::Progress);
|
|
||||||
|
|
||||||
for idx in files_needing_content {
|
|
||||||
let filename = llm_app.files[idx].filename.clone();
|
|
||||||
generated_count += 1;
|
|
||||||
info!("[PHASE2] Starting generation for file: {}", filename);
|
|
||||||
self.add_terminal_output(&format!("Generating `{filename}`..."), TerminalLineType::Info);
|
|
||||||
self.update_item_status(SectionType::Files, &filename, crate::auto_task::ItemStatus::Running);
|
|
||||||
|
|
||||||
match self.generate_file_content(&llm_app, &filename, session.bot_id).await {
|
|
||||||
Ok(content) => {
|
|
||||||
let content_len = content.len();
|
|
||||||
info!("[PHASE2] Generated file {} with {} bytes", filename, content_len);
|
|
||||||
llm_app.files[idx].content = content;
|
|
||||||
self.add_terminal_output(&format!("✓ `{filename}` ({content_len} bytes)"), TerminalLineType::Success);
|
|
||||||
self.update_item_status(SectionType::Files, &filename, crate::auto_task::ItemStatus::Completed);
|
|
||||||
}
|
|
||||||
Err(e) => {
|
|
||||||
error!("[PHASE2] Failed to generate {}: {}", filename, e);
|
|
||||||
self.add_terminal_output(&format!("✗ `{filename}` failed: {e}"), TerminalLineType::Error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let activity = self.build_activity("generating", generated_count as u32, Some(total_items as u32), Some(&filename));
|
|
||||||
self.emit_activity("file_generated", &format!("Generated {filename}"), 3, TOTAL_STEPS, activity);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
info!("[PHASE2] No files need content generation - all {} files already have content", llm_app.files.len());
|
|
||||||
self.add_terminal_output(&format!("All {} files already generated", llm_app.files.len()), TerminalLineType::Success);
|
|
||||||
self.update_manifest_section(SectionType::Files, SectionStatus::Completed);
|
|
||||||
self.broadcast_manifest_update();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Mark Files section as completed
|
|
||||||
self.update_manifest_section(SectionType::Files, SectionStatus::Completed);
|
|
||||||
self.broadcast_manifest_update();
|
|
||||||
|
|
||||||
let activity = self.build_activity("parsing", 2, Some(TOTAL_STEPS as u32), Some(&format!("Processing {} structure", llm_app.name)));
|
let activity = self.build_activity("parsing", 2, Some(TOTAL_STEPS as u32), Some(&format!("Processing {} structure", llm_app.name)));
|
||||||
self.emit_activity("parse_structure", &format!("Parsing {} structure...", llm_app.name), 3, TOTAL_STEPS, activity);
|
self.emit_activity("parse_structure", &format!("Parsing {} structure...", llm_app.name), 3, TOTAL_STEPS, activity);
|
||||||
|
|
||||||
|
|
@ -1079,8 +1014,75 @@ impl AppGenerator {
|
||||||
TOTAL_STEPS,
|
TOTAL_STEPS,
|
||||||
activity
|
activity
|
||||||
);
|
);
|
||||||
|
} else {
|
||||||
|
// No tables - mark database section as skipped
|
||||||
|
self.update_manifest_section(SectionType::DatabaseModels, SectionStatus::Skipped);
|
||||||
|
self.broadcast_manifest_update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ========== PHASE 2B: GENERATE FILE CONTENT ==========
|
||||||
|
let total_items = llm_app.files.len() + llm_app.tools.len() + llm_app.schedulers.len();
|
||||||
|
let mut generated_count = 0;
|
||||||
|
|
||||||
|
// Generate content for files that don't have it yet
|
||||||
|
let files_needing_content: Vec<usize> = llm_app.files.iter()
|
||||||
|
.enumerate()
|
||||||
|
.filter(|(_, f)| f.content.is_empty())
|
||||||
|
.map(|(i, _)| i)
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
info!("[PHASE2B] Files needing content: {} out of {} total files", files_needing_content.len(), llm_app.files.len());
|
||||||
|
for (i, file) in llm_app.files.iter().enumerate() {
|
||||||
|
info!("[PHASE2B] File {}: {} - content_len={}", i, file.filename, file.content.len());
|
||||||
|
}
|
||||||
|
|
||||||
|
if !files_needing_content.is_empty() {
|
||||||
|
info!("[PHASE2B] Setting Files section to Running - manifest exists: {}", self.manifest.is_some());
|
||||||
|
|
||||||
|
// Debug: List all sections before update
|
||||||
|
if let Some(ref manifest) = self.manifest {
|
||||||
|
info!("[PHASE2B] Current manifest sections:");
|
||||||
|
for (i, s) in manifest.sections.iter().enumerate() {
|
||||||
|
info!("[PHASE2B] [{}] {:?} = '{}' status={:?}", i, s.section_type, s.name, s.status);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.update_manifest_section(SectionType::Files, SectionStatus::Running);
|
||||||
|
self.broadcast_manifest_update();
|
||||||
|
self.add_terminal_output(&format!("## Generating {} files...", files_needing_content.len()), TerminalLineType::Progress);
|
||||||
|
|
||||||
|
for idx in files_needing_content {
|
||||||
|
let filename = llm_app.files[idx].filename.clone();
|
||||||
|
generated_count += 1;
|
||||||
|
info!("[PHASE2B] Starting generation for file: {}", filename);
|
||||||
|
self.add_terminal_output(&format!("Generating `{filename}`..."), TerminalLineType::Info);
|
||||||
|
self.update_item_status(SectionType::Files, &filename, crate::auto_task::ItemStatus::Running);
|
||||||
|
|
||||||
|
match self.generate_file_content(&llm_app, &filename, session.bot_id).await {
|
||||||
|
Ok(content) => {
|
||||||
|
let content_len = content.len();
|
||||||
|
info!("[PHASE2B] Generated file {} with {} bytes", filename, content_len);
|
||||||
|
llm_app.files[idx].content = content;
|
||||||
|
self.add_terminal_output(&format!("✓ `{filename}` ({content_len} bytes)"), TerminalLineType::Success);
|
||||||
|
self.update_item_status(SectionType::Files, &filename, crate::auto_task::ItemStatus::Completed);
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
error!("[PHASE2B] Failed to generate {}: {}", filename, e);
|
||||||
|
self.add_terminal_output(&format!("✗ `{filename}` failed: {e}"), TerminalLineType::Error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let activity = self.build_activity("generating", generated_count as u32, Some(total_items as u32), Some(&filename));
|
||||||
|
self.emit_activity("file_generated", &format!("Generated {filename}"), 3, TOTAL_STEPS, activity);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
info!("[PHASE2B] No files need content generation - all {} files already have content", llm_app.files.len());
|
||||||
|
self.add_terminal_output(&format!("All {} files already generated", llm_app.files.len()), TerminalLineType::Success);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mark Files content generation as completed (writing happens next)
|
||||||
|
self.broadcast_manifest_update();
|
||||||
|
|
||||||
// Use bucket_name from state (e.g., "default.gbai") instead of deriving from bot name
|
// Use bucket_name from state (e.g., "default.gbai") instead of deriving from bot name
|
||||||
let bucket_name = self.state.bucket_name.clone();
|
let bucket_name = self.state.bucket_name.clone();
|
||||||
let sanitized_name = bucket_name.trim_end_matches(".gbai").to_string();
|
let sanitized_name = bucket_name.trim_end_matches(".gbai").to_string();
|
||||||
|
|
|
||||||
|
|
@ -508,9 +508,6 @@ pub async fn handle_task_get(
|
||||||
// Build terminal output from recent activity
|
// Build terminal output from recent activity
|
||||||
let terminal_html = build_terminal_html(&task.step_results, &task.status);
|
let terminal_html = build_terminal_html(&task.step_results, &task.status);
|
||||||
|
|
||||||
let task_url = format!("/tasks/{}", task_id);
|
|
||||||
|
|
||||||
|
|
||||||
// Extract app_url from step_results if task is completed
|
// Extract app_url from step_results if task is completed
|
||||||
let app_url = if task.status == "completed" || task.status == "done" {
|
let app_url = if task.status == "completed" || task.status == "done" {
|
||||||
extract_app_url_from_results(&task.step_results, &task.title)
|
extract_app_url_from_results(&task.step_results, &task.title)
|
||||||
|
|
@ -538,12 +535,8 @@ pub async fn handle_task_get(
|
||||||
|
|
||||||
let html = format!(r#"
|
let html = format!(r#"
|
||||||
<div class="task-detail-rich" data-task-id="{task_id}">
|
<div class="task-detail-rich" data-task-id="{task_id}">
|
||||||
<!-- Header -->
|
<!-- Header - compact -->
|
||||||
<div class="taskmd-header">
|
<div class="taskmd-header">
|
||||||
<div class="taskmd-url">
|
|
||||||
<span class="url-icon">🔗</span>
|
|
||||||
<span class="url-path">{task_url}</span>
|
|
||||||
</div>
|
|
||||||
<h1 class="taskmd-title">{title}</h1>
|
<h1 class="taskmd-title">{title}</h1>
|
||||||
<span class="taskmd-status-badge status-{status_class}">{status_label}</span>
|
<span class="taskmd-status-badge status-{status_class}">{status_label}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -594,7 +587,6 @@ pub async fn handle_task_get(
|
||||||
</div>
|
</div>
|
||||||
"#,
|
"#,
|
||||||
task_id = task_id,
|
task_id = task_id,
|
||||||
task_url = task_url,
|
|
||||||
title = task.title,
|
title = task.title,
|
||||||
status_class = status_class,
|
status_class = status_class,
|
||||||
status_label = status_label,
|
status_label = status_label,
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue