feat: enhance turn display with time and diagnostics styling
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { FormEvent, useEffect, useState } from "react";
|
||||
import { FormEvent, useEffect, useMemo, useState } from "react";
|
||||
|
||||
type Entity = {
|
||||
id: string;
|
||||
@@ -28,7 +28,22 @@ type Turn = {
|
||||
validation: ValidationResult[];
|
||||
createdAt: number;
|
||||
interpreter?: {
|
||||
interpreterVersion: string;
|
||||
resolutionSource: "deterministic" | "llm" | "hybrid";
|
||||
minConfidence: number;
|
||||
status: "resolved" | "needs_clarification" | "rejected";
|
||||
selectedConfidence?: number;
|
||||
diagnostics: string[];
|
||||
clarification?: {
|
||||
reasonCode: string;
|
||||
question: string;
|
||||
field?: string;
|
||||
options?: Array<{
|
||||
id: string;
|
||||
label: string;
|
||||
value: string;
|
||||
}>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@@ -51,12 +66,15 @@ type ProcessTurnResponse = {
|
||||
worldState: WorldState;
|
||||
interpreter: {
|
||||
interpreterVersion: string;
|
||||
resolutionSource: "deterministic" | "llm" | "hybrid";
|
||||
minConfidence: number;
|
||||
status: "resolved" | "needs_clarification" | "rejected";
|
||||
selectedConfidence?: number;
|
||||
diagnostics: string[];
|
||||
clarification?: {
|
||||
reasonCode: string;
|
||||
question: string;
|
||||
field?: string;
|
||||
options?: Array<{
|
||||
id: string;
|
||||
label: string;
|
||||
@@ -94,11 +112,27 @@ type SceneRulebook = {
|
||||
const starterPrompts = [
|
||||
"look around",
|
||||
"take key",
|
||||
"take lantern",
|
||||
"give key to groundskeeper",
|
||||
"introduce jeff",
|
||||
"describe groundskeeper as patient",
|
||||
"open door",
|
||||
"move to exit",
|
||||
];
|
||||
|
||||
function formatConfidence(value: number | undefined): string {
|
||||
if (typeof value !== "number") return "n/a";
|
||||
return `${Math.round(value * 100)}%`;
|
||||
}
|
||||
|
||||
function formatTurnTime(epochMs: number): string {
|
||||
try {
|
||||
return new Date(epochMs).toLocaleTimeString([], { hour: "2-digit", minute: "2-digit", second: "2-digit" });
|
||||
} catch {
|
||||
return String(epochMs);
|
||||
}
|
||||
}
|
||||
|
||||
async function fetchJson<T>(input: RequestInfo, init?: RequestInit): Promise<T> {
|
||||
const response = await fetch(input, init);
|
||||
if (!response.ok) {
|
||||
@@ -198,6 +232,9 @@ function RulebookEditor() {
|
||||
<div className="rulebook-header">
|
||||
<div>
|
||||
<p className="rulebook-name">{rulebook.name}</p>
|
||||
<p className="rulebook-desc">
|
||||
Version {rulebook.version} | Updated {formatTurnTime(rulebook.updatedAt)}
|
||||
</p>
|
||||
{rulebook.description ? (
|
||||
<p className="rulebook-desc">{rulebook.description}</p>
|
||||
) : null}
|
||||
@@ -340,6 +377,15 @@ export default function App() {
|
||||
}
|
||||
|
||||
const entities = snapshot ? Object.values(snapshot.worldState.entities) : [];
|
||||
const turns = useMemo(() => snapshot?.turns.slice().reverse() ?? [], [snapshot]);
|
||||
|
||||
function applyClarificationOption(optionValue: string) {
|
||||
setInput((prev) => {
|
||||
const trimmed = prev.trim();
|
||||
if (!trimmed) return optionValue;
|
||||
return `${trimmed} ${optionValue}`;
|
||||
});
|
||||
}
|
||||
|
||||
return (
|
||||
<main className="page-shell">
|
||||
@@ -382,20 +428,32 @@ export default function App() {
|
||||
<p><strong>Input:</strong> {latest.rawText}</p>
|
||||
<p>
|
||||
<strong>Interpreter:</strong> {latest.interpreter.status}
|
||||
{typeof latest.interpreter.selectedConfidence === "number"
|
||||
? ` (${Math.round(latest.interpreter.selectedConfidence * 100)}% confidence)`
|
||||
: ""}
|
||||
{` via ${latest.interpreter.resolutionSource}`}
|
||||
{` | model threshold ${formatConfidence(latest.interpreter.minConfidence)}`}
|
||||
{` | selected ${formatConfidence(latest.interpreter.selectedConfidence)}`}
|
||||
</p>
|
||||
<p>
|
||||
<strong>Interpreter version:</strong> {latest.interpreter.interpreterVersion}
|
||||
</p>
|
||||
{latest.interpreter.clarification ? (
|
||||
<p>
|
||||
<strong>Clarification:</strong> {latest.interpreter.clarification.question}
|
||||
<strong>Clarification ({latest.interpreter.clarification.reasonCode}):</strong>{" "}
|
||||
{latest.interpreter.clarification.question}
|
||||
</p>
|
||||
) : null}
|
||||
{latest.interpreter.clarification?.options?.length ? (
|
||||
<p>
|
||||
<strong>Options:</strong>{" "}
|
||||
{latest.interpreter.clarification.options.map((o) => o.label).join(", ")}
|
||||
</p>
|
||||
<div className="chips">
|
||||
{latest.interpreter.clarification.options.map((o) => (
|
||||
<button
|
||||
key={o.id}
|
||||
type="button"
|
||||
className="chip"
|
||||
onClick={() => applyClarificationOption(o.value)}
|
||||
>
|
||||
clarify: {o.label}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
) : null}
|
||||
<ul className="timeline-list compact">
|
||||
{latest.validation.map((v) => (
|
||||
@@ -459,11 +517,25 @@ export default function App() {
|
||||
<article className="panel">
|
||||
<h2>Turn log</h2>
|
||||
<ul className="timeline-list">
|
||||
{snapshot?.turns.slice().reverse().map((turn) => (
|
||||
{turns.map((turn) => (
|
||||
<li key={turn.id}>
|
||||
<strong>{turn.rawText}</strong>
|
||||
<span className="turn-time"> at {formatTurnTime(turn.createdAt)}</span>
|
||||
{turn.interpreter ? (
|
||||
<span> [interp:{turn.interpreter.status}]</span>
|
||||
<span>
|
||||
{" "}[interp:{turn.interpreter.status} via {turn.interpreter.resolutionSource};
|
||||
conf {formatConfidence(turn.interpreter.selectedConfidence)}]
|
||||
</span>
|
||||
) : null}
|
||||
{turn.interpreter?.clarification ? (
|
||||
<p className="parser-hint">
|
||||
Clarification ({turn.interpreter.clarification.reasonCode}): {turn.interpreter.clarification.question}
|
||||
</p>
|
||||
) : null}
|
||||
{turn.interpreter?.diagnostics?.length ? (
|
||||
<p className="turn-diagnostics">
|
||||
Diagnostics: {turn.interpreter.diagnostics.join(" | ")}
|
||||
</p>
|
||||
) : null}
|
||||
{turn.validation.map((v) => (
|
||||
<span key={v.actionIndex}> [{v.success ? "ok" : v.reason}]</span>
|
||||
|
||||
@@ -376,3 +376,14 @@ pre {
|
||||
padding: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
.turn-time {
|
||||
opacity: 0.7;
|
||||
font-size: 0.82rem;
|
||||
}
|
||||
|
||||
.turn-diagnostics {
|
||||
margin: 6px 0 0;
|
||||
color: rgba(244, 239, 228, 0.74);
|
||||
font-size: 0.82rem;
|
||||
}
|
||||
Reference in New Issue
Block a user