web: new-story form gets 'fire now' too — same pattern as continue form
Cobb tried creating a story via /stories/new tonight, ticked through the form, hit Create, then expected gen to fire. It didn't, because the fire-now checkbox only existed on the continue form. Story sat in 'seed' for 30 min before he asked. Fix: same path as continue. NewStoryForm picks up an optional 'fire' field; new_story_create spawns a tokio::spawn task that calls continue_story::run() with parent_story_id=None semantics: - Context is the story's own prompt (not parent's bible) - Audit pass is skipped (no parent to compare against) - Status flow: seed → generating → cleaning → complete The form copy explains the audit-skip for first chapters so the user isn't surprised to see no findings. Also fired Cobb's pending story manually via 'skald continue --story bd73dd19...' so it actually generates this round.
This commit is contained in:
parent
1e19305432
commit
20e262c85d
1 changed files with 47 additions and 4 deletions
|
|
@ -128,6 +128,8 @@ pub struct NewStoryForm {
|
|||
word_count_target: String,
|
||||
#[serde(default)]
|
||||
author_slug: String,
|
||||
#[serde(default)]
|
||||
fire: String, // "now" = spawn background gen; empty = just queue the seed row
|
||||
}
|
||||
|
||||
async fn new_story_form(State(state): State<Arc<WebState>>) -> Html<String> {
|
||||
|
|
@ -177,6 +179,39 @@ async fn new_story_create(
|
|||
}
|
||||
}
|
||||
|
||||
// Fire generation immediately if requested. No-parent gen path:
|
||||
// continue_story::run handles parent_story_id=None by using the
|
||||
// story's own prompt as the LLM context (instead of the parent
|
||||
// chain's bible/chapters). Audit pass is skipped — there's no
|
||||
// parent to compare against. So you get a single first-chapter
|
||||
// gen + cleanup pass and status flows to 'complete'.
|
||||
if form.fire == "now" {
|
||||
let database_url = std::env::var("DATABASE_URL")
|
||||
.unwrap_or_else(|_| "postgresql://skald:skald@localhost:5432/skald".into());
|
||||
let author_owned = if author_slug.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(author_slug.to_string())
|
||||
};
|
||||
tokio::spawn(async move {
|
||||
if let Err(e) = crate::continue_story::run(
|
||||
&database_url,
|
||||
id,
|
||||
author_owned.as_deref(),
|
||||
None, // direction (no parent — uses story.prompt instead)
|
||||
target,
|
||||
2, // recent_n
|
||||
true, // skip_audit (no parent → can't audit)
|
||||
)
|
||||
.await
|
||||
{
|
||||
tracing::error!(story_id = %id, error = %e, "background new-story task failed");
|
||||
} else {
|
||||
tracing::info!(story_id = %id, "background new-story task succeeded");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Ok(Redirect::to(&format!("/stories/{}", id)))
|
||||
}
|
||||
|
||||
|
|
@ -457,7 +492,11 @@ fn new_story_panel(err: Option<&str>, authors: &[AuthorOpt]) -> Markup {
|
|||
article.form-panel {
|
||||
h1 { "Begin a new saga" }
|
||||
(ornament())
|
||||
p.muted { "Create a story row + pick its author. The gen pipeline fires on " code { "skald continue --story <id>" } " or via the continue form once you've drafted the first chapter." }
|
||||
p.muted {
|
||||
"Create a story row, pick its author, and optionally fire the gen pipeline "
|
||||
"immediately. Without " strong { "fire now" } ", the seed row waits for "
|
||||
code { "skald continue --story <id>" } "."
|
||||
}
|
||||
@if let Some(e) = err { p.error { (e) } }
|
||||
form method="post" action="/stories/new" {
|
||||
label { "Title"
|
||||
|
|
@ -474,12 +513,16 @@ fn new_story_panel(err: Option<&str>, authors: &[AuthorOpt]) -> Markup {
|
|||
}
|
||||
}
|
||||
}
|
||||
label { "Seed prompt (optional)"
|
||||
textarea name="prompt" rows="4" placeholder="What is this saga about? Setting, frame, conflict." {}
|
||||
label { "Seed prompt"
|
||||
textarea name="prompt" rows="5" placeholder="What is this saga about? Setting, frame, conflict, vibe. The richer this is, the better the first chapter." {}
|
||||
}
|
||||
label { "Target word count per chapter (optional)"
|
||||
label { "Target word count for the first chapter"
|
||||
input type="number" name="word_count_target" min="500" step="500" placeholder="3000";
|
||||
}
|
||||
label.checkbox-label {
|
||||
input type="checkbox" name="fire" value="now";
|
||||
span { " fire generation now (background task, ~7 min — no audit pass on the first chapter since there's no parent yet)" }
|
||||
}
|
||||
button type="submit" { "Create" }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue