HomePilot / frontend /src /ui /interactive /wizardState.ts
HomePilot Deploy Bot
chore(hf): sync HomePilot to HF Space
921d377
Raw
History Blame Contribute Delete
4.65 kB
/**
* Form state for the new-project wizard.
*
* Lives in its own module so the step components and the parent
* Wizard can both import the same type without circular deps.
* The shape is wire-friendly: `toCreatePayload` and `toPlanPayload`
* project this struct directly into the `/v1/interactive/*`
* request bodies — no field renames at the boundary.
*/
import type { ExperienceMode } from "./types";
/**
* Which ComfyUI workflow bucket the player calls per scene.
* "video" — full Animate/SVD clip. Default. Higher VRAM.
* "image" — still-image txt2img. Cheap on GPU; lets operators
* validate the whole interactive flow without owning
* a beefy video model.
*/
export type RenderMediaType = "video" | "image";
export interface WizardForm {
// Interaction type (Step 0 header)
interaction_type: "standard_project" | "persona_live_play";
persona_project_id: string;
persona_label: string;
/** Scene render bucket — image or video. See RenderMediaType. */
render_media_type: RenderMediaType;
// Step 0
title: string;
prompt: string;
experience_mode: ExperienceMode;
// Step 1
audience_role: string;
audience_level: "beginner" | "intermediate" | "advanced";
audience_language: string;
audience_locale_hint: string;
// Step 2
branch_count: number;
depth: number;
scenes_per_branch: number;
// Step 3
policy_profile_id: string;
/** Override LLM model id used by the storyteller (scene graph
* generation + persona_live runtime). Empty string means
* "use the server default". Surfaced in the wizard only when
* ``experience_mode === "mature_gated"`` because the default
* Llama 3 / Llama 3.2 models refuse explicit content with
* "I cannot create content that describes explicit sexual
* situations." Operators can pick from the abliterated /
* uncensored models they already installed (see Models tab —
* rows tagged "🌶️ Adult" / "🔥 NSFW Pick"). The backend
* reads ``audience_profile.adult_llm`` at every LLM call site
* for the experience. */
adult_llm: string;
}
export const DEFAULT_WIZARD_FORM: WizardForm = {
interaction_type: "standard_project",
persona_project_id: "",
persona_label: "",
render_media_type: "video",
title: "",
prompt: "",
experience_mode: "sfw_general",
audience_role: "viewer",
audience_level: "beginner",
audience_language: "en",
audience_locale_hint: "",
branch_count: 3,
depth: 3,
scenes_per_branch: 3,
policy_profile_id: "sfw_general",
adult_llm: "",
};
export function toCreatePayload(f: WizardForm) {
return {
title: f.title.trim(),
description: f.prompt.trim(),
experience_mode: f.experience_mode,
policy_profile_id: f.policy_profile_id,
project_type: f.interaction_type === "persona_live_play" ? "persona_live" : "standard",
audience_profile: {
role: f.audience_role,
level: f.audience_level,
language: f.audience_language,
locale_hint: f.audience_locale_hint,
interaction_type: f.interaction_type,
persona_project_id: f.persona_project_id || undefined,
persona_label: f.persona_label || undefined,
render_media_type: f.render_media_type,
// Stored only for mature_gated experiences. Empty string is
// wire-equivalent to "use the server default" — backend treats
// both as fall-through to the configured Ollama model.
adult_llm:
f.experience_mode === "mature_gated" && f.adult_llm
? f.adult_llm
: undefined,
},
};
}
export function toPlanPayload(f: WizardForm) {
return {
prompt: f.prompt.trim(),
mode: f.experience_mode,
audience_hints: {
role: f.audience_role,
level: f.audience_level,
language: f.audience_language,
locale_hint: f.audience_locale_hint,
interaction_type: f.interaction_type,
persona_project_id: f.persona_project_id || undefined,
persona_label: f.persona_label || undefined,
render_media_type: f.render_media_type,
// Plan-auto runs BEFORE create-experience so it can't read
// audience_profile.adult_llm — pass the operator's Step 0
// pick directly so the title/topic LLM call uses the
// uncensored model the user selected. Without this, the
// default Llama refuses with "I cannot create a brief for
// an interactive video that focuses on sexual experiences."
// and the wizard's title/description land as that refusal.
adult_llm:
f.experience_mode === "mature_gated" && f.adult_llm
? f.adult_llm
: undefined,
},
};
}