working through the plan + UI/ UX

This commit is contained in:
itsamejms
2026-07-12 22:13:43 +01:00
parent 5b256242be
commit a24f3615e0
38 changed files with 5295 additions and 328 deletions
+37 -4
View File
@@ -1,6 +1,10 @@
import { parseLlmJson, ensureArray, flattenValue } from "../lib/llm-parse";
import { useState } from "react";
import { invoke } from "@tauri-apps/api/core";
import { addToLore } from "../lib/lore";
import { useToast } from "./Toast";
import { addGeneration, extractTitle, type Generation } from "../lib/generations";
import { usePrefillEffect } from "../lib/usePrefill";
interface WorldResponse {
name: string;
@@ -11,11 +15,25 @@ interface WorldResponse {
cultures: string[];
}
export function WorldBuilder() {
interface Props {
prefill?: Generation | null;
onPrefillConsumed?: () => void;
}
export function WorldBuilder({ prefill, onPrefillConsumed }: Props = {}) {
const [theme, setTheme] = useState("high fantasy");
const [world, setWorld] = useState<WorldResponse | null>(null);
const [loading, setLoading] = useState(false);
const [error, setError] = useState("");
const { addToast } = useToast();
usePrefillEffect(prefill ?? null, "world", () => onPrefillConsumed?.(), (g) => {
const parsed = parseLlmJson<WorldResponse>(g.data);
if (parsed) {
setWorld(parsed);
addToast(`Loaded "${g.title}" from history`, "info");
}
});
async function generate() {
setLoading(true);
@@ -38,16 +56,31 @@ IMPORTANT: Return ONLY a raw JSON object. NO markdown fences, NO code blocks, NO
system: "You are a creative world-building DM. You MUST respond with ONLY valid JSON. No markdown fences, no code blocks, no explanation. Just the JSON object.",
temperature: 0.9,
max_tokens: 600,
ragQuery: `fantasy world ${theme} regions landmarks cultures`,
},
});
const parsed = parseLlmJson<WorldResponse>(result);
if (parsed) {
setWorld(parsed);
addToast("World generated", "success");
const title = extractTitle("world", result, theme);
const source = `Theme: ${theme}`;
void addGeneration({ kind: "world", title, data: result, source });
const regions = ensureArray(parsed.regions).map(flattenValue).join("; ");
const landmarks = ensureArray(parsed.landmarks).map(flattenValue).join("; ");
const conflicts = ensureArray(parsed.conflicts).map(flattenValue).join("; ");
const cultures = ensureArray(parsed.cultures).map(flattenValue).join("; ");
void addToLore(
`World: ${parsed.name || theme}`,
`${parsed.name || "World"} (${theme}). ${parsed.description}\nRegions: ${regions}\nLandmarks: ${landmarks}\nConflicts: ${conflicts}\nCultures: ${cultures}`,
);
} else {
setError("Could not parse LLM response. Try again or check your LLM connection.");
addToast("LLM returned an unparseable response", "error");
}
} catch (e) {
setError(String(e));
addToast(`World generation failed: ${e}`, "error");
}
setLoading(false);
}
@@ -122,7 +155,7 @@ IMPORTANT: Return ONLY a raw JSON object. NO markdown fences, NO code blocks, NO
))}
</div>
</div>
)})
)}
{/* Conflicts */}
{world.conflicts?.length > 0 && (
@@ -138,7 +171,7 @@ IMPORTANT: Return ONLY a raw JSON object. NO markdown fences, NO code blocks, NO
))}
</div>
</div>
)})
)}
{/* Cultures */}
{world.cultures?.length > 0 && (
@@ -154,7 +187,7 @@ IMPORTANT: Return ONLY a raw JSON object. NO markdown fences, NO code blocks, NO
))}
</div>
</div>
)})
)}
</div>
)}
</div>