storkit: merge 432_story_complete_setup_wizard_with_mcp_tools_and_agent_driven_file_generation

This commit is contained in:
dave
2026-03-28 14:21:13 +00:00
parent 93576e3f83
commit 49b78f3642
5 changed files with 864 additions and 2 deletions
+62
View File
@@ -1,4 +1,5 @@
use serde::{Deserialize, Serialize};
use serde_json;
use std::fs;
use std::path::Path;
@@ -190,6 +191,67 @@ impl WizardState {
}
}
/// Format a `WizardState` as a human-readable Markdown summary for display in
/// bot messages and MCP responses.
pub fn format_wizard_state(state: &WizardState) -> String {
let total = state.steps.len();
let current_idx = state.current_step_index();
let header = if state.completed {
format!("**Setup wizard — complete** ({total}/{total} steps done)")
} else {
format!("**Setup wizard — step {}/{}**", current_idx + 1, total)
};
let mut lines = vec![header, String::new()];
for (i, step) in state.steps.iter().enumerate() {
let marker = match step.status {
StepStatus::Confirmed => "",
StepStatus::Skipped => "~",
StepStatus::Generating => "",
StepStatus::AwaitingConfirmation => "?",
StepStatus::Pending => "",
};
let is_current = !state.completed && i == current_idx;
let suffix = if is_current { " ← current" } else { "" };
let status_str = serde_json::to_value(&step.status)
.ok()
.and_then(|v| v.as_str().map(String::from))
.unwrap_or_default();
lines.push(format!(
" {} {} ({}){suffix}",
marker,
step.step.label(),
status_str
));
}
if state.completed {
lines.push(String::new());
lines.push("All steps done. Your project is fully configured.".to_string());
} else {
let current = &state.steps[current_idx];
lines.push(String::new());
lines.push(format!("**Current:** {}", current.step.label()));
let hint = match current.status {
StepStatus::Pending => {
"Run `wizard_generate` to generate content for this step.".to_string()
}
StepStatus::Generating => "Agent is generating content…".to_string(),
StepStatus::AwaitingConfirmation => {
"Content ready for review. Run `wizard_confirm` to write to disk, `wizard_retry` to regenerate, or `wizard_skip` to skip.".to_string()
}
StepStatus::Confirmed | StepStatus::Skipped => String::new(),
};
if !hint.is_empty() {
lines.push(hint);
}
}
lines.join("\n")
}
#[cfg(test)]
mod tests {
use super::*;