diff --git a/apps/gui/components.json b/apps/gui/components.json new file mode 100644 index 0000000..8c21e30 --- /dev/null +++ b/apps/gui/components.json @@ -0,0 +1,24 @@ +{ + "$schema": "https://ui.shadcn.com/schema.json", + "style": "default", + "rsc": true, + "tsx": true, + "tailwind": { + "config": "", + "css": "src/app/globals.css", + "baseColor": "neutral", + "cssVariables": true, + "prefix": "" + }, + "aliases": { + "components": "@/components", + "utils": "@/lib/utils", + "ui": "@/components/ui", + "lib": "@/lib", + "hooks": "@/hooks" + }, + "registries": { + "@retroui": "https://retroui.dev/r/radix/{name}.json", + "@retroui-base": "https://retroui.dev/r/base/{name}.json" + } +} diff --git a/apps/gui/package.json b/apps/gui/package.json index b7ce140..013a8fa 100644 --- a/apps/gui/package.json +++ b/apps/gui/package.json @@ -18,18 +18,27 @@ "@omnia/memory": "workspace:*", "@omnia/scenario": "workspace:*", "@omnia/spatial": "workspace:*", + "@radix-ui/react-slot": "^1.3.0", + "class-variance-authority": "^0.7.1", + "clsx": "^2.1.1", "dotenv": "^17.4.2", + "lucide-react": "^1.24.0", "next": "^16.2.10", + "radix-ui": "^1.6.2", "react": "^19.2.0", - "react-dom": "^19.2.0" + "react-dom": "^19.2.0", + "tailwind-merge": "^3.6.0", + "tailwindcss-animate": "^1.0.7" }, "devDependencies": { + "@tailwindcss/postcss": "^4.3.2", "@types/node": "^26.1.0", "@types/react": "^19.2.0", "@types/react-dom": "^19.2.0", "autoprefixer": "^10.5.2", "postcss": "^8.5.16", - "tailwindcss": "^3.4.19", + "shadcn": "^4.13.0", + "tailwindcss": "^4.3.2", "typescript": "^6.0.3" } } diff --git a/apps/gui/postcss.config.mjs b/apps/gui/postcss.config.mjs index a982c64..61e3684 100644 --- a/apps/gui/postcss.config.mjs +++ b/apps/gui/postcss.config.mjs @@ -1,7 +1,6 @@ const config = { plugins: { - tailwindcss: {}, - autoprefixer: {}, + "@tailwindcss/postcss": {}, }, }; diff --git a/apps/gui/src/app/config/page.tsx b/apps/gui/src/app/config/page.tsx index af0174c..9dd6ebf 100644 --- a/apps/gui/src/app/config/page.tsx +++ b/apps/gui/src/app/config/page.tsx @@ -14,6 +14,26 @@ import { regenerateEmbeddings, } from "@/app/play/actions"; import type { ModelProviderInstance, ModelProviderMeta } from "@omnia/llm"; +import { Button } from "@/components/ui/button"; +import { Input } from "@/components/ui/input"; +import { Label } from "@/components/ui/label"; +import { Checkbox } from "@/components/ui/checkbox"; +import { Badge } from "@/components/ui/badge"; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from "@/components/ui/select"; +import { + Table, + TableBody, + TableCell, + TableHead, + TableHeader, + TableRow, +} from "@/components/ui/table"; interface ConfigStatus { apiKeySet: boolean; @@ -244,13 +264,13 @@ export default function ConfigPage() {

Instances

- +
{instances.length === 0 ? ( @@ -273,10 +293,10 @@ export default function ConfigPage() {
{inst.providerName} ({inst.type || "generative"}) - {inst.isActive && ( - + {inst.isActive && ( + Active - + )}
@@ -301,63 +321,53 @@ export default function ConfigPage() {
- - Friendly Name + setEditName(e.target.value)} placeholder="e.g. Gemini - Production" required - className="w-full rounded-md border border-gray-300 bg-white px-3 py-2 text-sm outline-none transition-[border-color,box-shadow] focus:border-blue-500 focus:ring-3 focus:ring-blue-500/15" />
- - + +
- - + + {editProvider && availableProviders.length > 0 && ( - + {availableProviders.find((p) => p.id === editProvider)?.description} )}
- - API Key +
- - Model Name + setEditModel(e.target.value)} placeholder="e.g. gemini-2.5-flash, gemini-2.5-pro" - className="w-full rounded-md border border-gray-300 bg-white px-3 py-2 text-sm outline-none transition-[border-color,box-shadow] focus:border-blue-500 focus:ring-3 focus:ring-blue-500/15" />
{editType === "generative" && (
- - Max Context Length (Tokens, 0 for infinite) + setEditMaxContext(parseInt(e.target.value) || 0)} min={0} placeholder="e.g. 32768" - className="w-full rounded-md border border-gray-300 bg-white px-3 py-2 text-sm outline-none transition-[border-color,box-shadow] focus:border-blue-500 focus:ring-3 focus:ring-blue-500/15" />
)}
- setEditIsActive(e.target.checked)} - className="h-4 w-4 cursor-pointer" + onCheckedChange={(v) => setEditIsActive(v === true)} /> -
-
+
{selectedInstanceId !== "new" && ( - + )}
- +
@@ -464,20 +463,20 @@ export default function ConfigPage() { ].map((task) => (
- + {task.label} - {task.desc} + {task.desc}
setSelectedScenario(e.target.value)} + className="w-full rounded border-2 bg-input px-3 py-2 text-sm shadow-sm outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary" > {scenarios.map((s) => (
-
-
-
-

Resume Simulation

+
+

Resume Simulation

{savedSessions.length === 0 ? ( -

No saved sessions found. Start a new one!

+

No saved sessions found. Start a new one!

) : ( -
+
{savedSessions.map((s) => ( -
-
- {s.scenarioName} - +
+
+ {s.scenarioName} + Turn {s.turn} · {s.entities.length} entities · {s.status} - + Session ID: {s.id}
-
- - +
))} @@ -774,50 +805,53 @@ export function PlayView() { {snapshot && ( <> -
-
-

{snapshot.scenarioName}

+
+
+

{snapshot.scenarioName}

{snapshot.status !== "done" && snapshot.status !== "error" && ( -
+
{snapshot.status === "running" && ( loading ? ( - + ) : ( - + ) )} - +
)}
-

{snapshot.scenarioDescription}

-

+

{snapshot.scenarioDescription}

+

{loading && "⏳ "} {statusMessage()}

-
+
{(() => { const playerEntity = snapshot.entities.find((e) => e.isPlayer); return snapshot.log.map((entry, i) => ( @@ -830,8 +864,8 @@ export function PlayView() { )); })()} {loading && ( -
- +
+ {statusText || "Processing..."}
)} @@ -839,50 +873,50 @@ export function PlayView() {
{snapshot.status === "waiting_player" && snapshot.waitingEntity && ( -
-
- +
+
+ Your context as {snapshot.waitingEntity.name} -
+                
                   {snapshot.waitingEntity.userContext}
                 
-
-