From 382507e71ad8ccd7e3b460e137efdc6635354cbe Mon Sep 17 00:00:00 2001 From: Aditya Gupta Date: Fri, 10 Jul 2026 22:36:03 +0530 Subject: [PATCH] minor(gui): Disable simulation button if no provider found --- apps/gui/src/app/config/page.tsx | 175 +++++++++++++--------- apps/gui/src/components/play/PlayView.tsx | 4 +- 2 files changed, 110 insertions(+), 69 deletions(-) diff --git a/apps/gui/src/app/config/page.tsx b/apps/gui/src/app/config/page.tsx index b49b27c..debd45b 100644 --- a/apps/gui/src/app/config/page.tsx +++ b/apps/gui/src/app/config/page.tsx @@ -25,11 +25,15 @@ export default function ConfigPage() { const [config, setConfig] = useState(null); const [instances, setInstances] = useState([]); const [mappings, setMappings] = useState>({}); - const [availableProviders, setAvailableProviders] = useState([]); + const [availableProviders, setAvailableProviders] = useState< + LLMProviderMeta[] + >([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(""); - const [selectedInstanceId, setSelectedInstanceId] = useState(null); + const [selectedInstanceId, setSelectedInstanceId] = useState( + null, + ); const [editName, setEditName] = useState(""); const [editProvider, setEditProvider] = useState("google-genai"); const [editKey, setEditKey] = useState(""); @@ -57,8 +61,12 @@ export default function ConfigPage() { setEditName(inst.name); setEditProvider(inst.providerName); setEditKey(""); - const pMeta = availableProviders.find((p) => p.id === inst.providerName); - setEditModel(inst.modelName || pMeta?.defaultModel || "gemini-2.5-flash"); + const pMeta = availableProviders.find( + (p) => p.id === inst.providerName, + ); + setEditModel( + inst.modelName || pMeta?.defaultModel || "gemini-2.5-flash", + ); setEditIsActive(inst.isActive); } } @@ -128,13 +136,24 @@ export default function ConfigPage() { setLoading(false); return; } - const created = await createProviderInstance(editName, editProvider, editKey, editModel || undefined); + const created = await createProviderInstance( + editName, + editProvider, + editKey, + editModel || undefined, + ); if (editIsActive) { await setActiveProviderInstance(created.id); } setSelectedInstanceId(created.id); } else { - await updateProviderInstance(selectedInstanceId, editName, editProvider, editKey || undefined, editModel || undefined); + await updateProviderInstance( + selectedInstanceId, + editName, + editProvider, + editKey || undefined, + editModel || undefined, + ); if (editIsActive) { await setActiveProviderInstance(selectedInstanceId); } @@ -151,7 +170,8 @@ export default function ConfigPage() { const handleDelete = async () => { if (selectedInstanceId === "new" || selectedInstanceId === null) return; - if (!confirm("Are you sure you want to delete this provider instance?")) return; + if (!confirm("Are you sure you want to delete this provider instance?")) + return; try { setLoading(true); @@ -167,7 +187,10 @@ export default function ConfigPage() { } }; - const handleUpdateMapping = async (task: string, providerInstanceId: string) => { + const handleUpdateMapping = async ( + task: string, + providerInstanceId: string, + ) => { try { setLoading(true); await setProviderMapping(task, providerInstanceId); @@ -192,13 +215,15 @@ export default function ConfigPage() { {config && !loading && ( <> -
+

LLM Provider Instances

{/* 30% area */}
-

Instances

+

+ Instances +

-
+

Task Provider Routing

- Configure which LLM Provider Key Instance should handle each specific simulation - task. Mappings default to the currently Active instance if not - specified. + Configure which LLM Provider Key Instance should handle each + specific simulation task. Mappings default to the currently{" "} + Active instance if not specified.

{[ - { key: "actor-prose", label: "Actor Prose Generation", desc: "Generates roleplay/narrative prose for Non-Player Characters." }, - { key: "llm-validator", label: "LLM Validator", desc: "Arbitrates and validates proposed actions against the world state rules." }, - { key: "intent-decoder", label: "Intent Decoder", desc: "Splits raw prose actions into structured intents (Player and NPC)." }, - { key: "timedelta", label: "TimeDelta Generator", desc: "Calculates the duration of character actions to advance the game clock." }, + { + key: "actor-prose", + label: "Actor Prose Generation", + desc: "Generates roleplay/narrative prose for Non-Player Characters.", + }, + { + key: "llm-validator", + label: "LLM Validator", + desc: "Arbitrates and validates proposed actions against the world state rules.", + }, + { + key: "intent-decoder", + label: "Intent Decoder", + desc: "Splits raw prose actions into structured intents (Player and NPC).", + }, + { + key: "timedelta", + label: "TimeDelta Generator", + desc: "Calculates the duration of character actions to advance the game clock.", + }, ].map((task) => (
- {task.label} + + {task.label} + {task.desc}
@@ -406,35 +476,15 @@ export default function ConfigPage() {
-
-

Environment Variables Default

-
- Default Model - - {config.model} - -
-
- Default API Key (.env) - - {config.apiKeySet - ? `✓ Set (${config.apiKeyPreview})` - : "✗ NOT SET"} - -
-
- -
+

Available Scenarios

{config.availableScenarios.length === 0 ? (

- No scenarios found in content/demo/scenarios/. + No scenarios found in{" "} + + content/demo/scenarios/ + + .

) : ( @@ -453,7 +503,9 @@ export default function ConfigPage() { ))} @@ -461,17 +513,6 @@ export default function ConfigPage() {
{s.name} - {s.path} + + {s.path} +
)}
- -
-

Engine Packages

-

- All @omnia/* workspace packages are - consumed via transpilePackages in{" "} - next.config.ts. The native{" "} - better-sqlite3 module is externalized - via serverExternalPackages. -

-
)} diff --git a/apps/gui/src/components/play/PlayView.tsx b/apps/gui/src/components/play/PlayView.tsx index f1ac424..3e25b75 100644 --- a/apps/gui/src/components/play/PlayView.tsx +++ b/apps/gui/src/components/play/PlayView.tsx @@ -510,7 +510,7 @@ export function PlayView() { )} - @@ -534,7 +534,7 @@ export function PlayView() {
-