Commit 867bda9d authored by Kantz's avatar Kantz
Browse files

tip und Lösungsbutton zum Feedbackmode hinzugefügt

parent 6c2341ba
......@@ -20,6 +20,10 @@ class ContextRequest(BaseModel):
draft: Optional[str] = None
class DraftRequest(BaseModel):
draft: str = Field(..., min_length=1)
@router.post("/api/context/retrieval")
def get_retrieval_context(request: ContextRequest) -> List[dict]:
if not request or not request.messages:
......@@ -35,3 +39,14 @@ def get_retrieval_context(request: ContextRequest) -> List[dict]:
if not sources:
return []
return [source.model_dump() for source in sources]
@router.post("/api/context/solution")
def get_context_solution(request: DraftRequest) -> dict[str, str]:
sheet = context_store.load_sheet(request.draft)
if not sheet:
raise HTTPException(status_code=404, detail="context sheet not found")
return {
"solution": context_store.context_store_new.get_solution(sheet),
}
......@@ -9,6 +9,8 @@ type ChatWindowProps = {
draft: string;
onDraftChange: (value: string) => void;
onSend: () => void;
onTip?: () => void;
onRevealSolution?: () => void;
isSending?: boolean;
onHistoryNavigate?: (direction: "older" | "newer") => boolean;
onToggleCanvas?: () => void;
......@@ -23,6 +25,8 @@ export default function ChatWindow({
draft,
onDraftChange,
onSend,
onTip,
onRevealSolution,
isSending = false,
onHistoryNavigate,
onToggleCanvas,
......@@ -44,6 +48,8 @@ export default function ChatWindow({
value={draft}
onChange={onDraftChange}
onSend={onSend}
onTip={onTip}
onRevealSolution={onRevealSolution}
isSending={isSending}
onHistoryNavigate={onHistoryNavigate}
onToggleCanvas={onToggleCanvas}
......
......@@ -6,6 +6,8 @@ type MessageInputProps = {
value: string;
onChange: (value: string) => void;
onSend: () => void;
onTip?: () => void;
onRevealSolution?: () => void;
isSending?: boolean;
onHistoryNavigate?: (direction: "older" | "newer") => boolean;
onToggleCanvas?: () => void;
......@@ -16,6 +18,8 @@ export default function MessageInput({
value,
onChange,
onSend,
onTip,
onRevealSolution,
isSending = false,
onHistoryNavigate,
onToggleCanvas,
......@@ -89,6 +93,30 @@ export default function MessageInput({
className="canvas-upload-input"
onChange={handleUploadChange}
/>
{onTip ? (
<button
className="btn"
type="button"
onClick={onTip}
disabled={isSending}
aria-label={t("tip")}
title={t("tip")}
>
{t("tip")}
</button>
) : null}
{onRevealSolution ? (
<button
className="btn"
type="button"
onClick={onRevealSolution}
disabled={isSending}
aria-label={t("revealSolution")}
title={t("revealSolution")}
>
{t("revealSolution")}
</button>
) : null}
<button
className="btn primary"
type="button"
......
......@@ -39,6 +39,8 @@
inspect: "Inspect",
cite: "Cite",
draw: "Draw",
tip: "Tip",
revealSolution: "Solution",
send: "Send",
roleUser: "user",
roleAssistant: "assistant",
......@@ -57,6 +59,7 @@
failedLoadTasks: "Could not load tasks.",
failedLoadOrchestratorConfig: "Could not load orchestrator config. Fallback mode active.",
chatRequestFailed: "The chat request failed. Please check backend logs.",
noStoredSolution: "No stored solution is available for this task yet.",
retrievalFailed: "Source retrieval failed. Please check backend logs.",
failedLoadSavedChats: "Could not load saved chats.",
failedLoadSelectedChat: "Could not load the selected chat.",
......@@ -137,6 +140,8 @@
inspect: "Ansehen",
cite: "Zitieren",
draw: "Zeichnen",
tip: "Tip",
revealSolution: "Lösung",
send: "Senden",
roleUser: "nutzer",
roleAssistant: "assistent",
......@@ -157,6 +162,8 @@
"Orchestrator-Konfiguration konnte nicht geladen werden. Fallback-Modus aktiv.",
chatRequestFailed:
"Da ist wohl die Chat-Anfrage fehlgeschlagen. Gib gerne deinem Dozenten bescheid. In vielen Fällen hilft es die Seite neu zu laden.",
noStoredSolution:
"Für diese Aufgabe ist aktuell keine gespeicherte Lösung verfügbar.",
retrievalFailed:
"Da ist wohl der Quellenabruf fehlgeschlagen. Gib gerne deinem Dozenten bescheid. In vielen Fällen hilft es die Seite neu zu laden.",
failedLoadSavedChats: "Gespeicherte Chats konnten nicht geladen werden.",
......
......@@ -619,12 +619,29 @@ export default function ChatPage() {
return true;
};
const handleSend = async () => {
const appendAssistantMessage = (text: string) => {
setMessages((prev) => [
...prev,
{
id: `m-${Date.now()}-assistant`,
role: "assistant",
text,
},
]);
};
const sendMessage = async ({
text,
clearDraft,
}: {
text: string;
clearDraft: boolean;
}) => {
if (isSending) {
return;
}
const trimmed = draft.trim();
const trimmed = text.trim();
if (!trimmed) {
return;
}
......@@ -636,8 +653,10 @@ export default function ChatPage() {
};
setMessages((prev) => [...prev, userMessage]);
setDraft("");
resetDraftHistoryNavigation();
if (clearDraft) {
setDraft("");
resetDraftHistoryNavigation();
}
setIsSending(true);
setRetrievalLoading(true);
......@@ -685,25 +704,11 @@ export default function ChatPage() {
const payload: { reply?: string } = await response.json();
const reply = payload.reply;
if (typeof reply === "string" && reply.length > 0) {
setMessages((prev) => [
...prev,
{
id: `m-${Date.now()}-assistant`,
role: "assistant",
text: reply,
},
]);
appendAssistantMessage(reply);
}
chatRequestSucceeded = true;
} catch (error) {
setMessages((prev) => [
...prev,
{
id: `m-${Date.now()}-assistant`,
role: "assistant",
text: t("chatRequestFailed"),
},
]);
appendAssistantMessage(t("chatRequestFailed"));
setRetrievalError(t("retrievalFailed"));
void error;
} finally {
......@@ -747,6 +752,57 @@ export default function ChatPage() {
setRetrievalLoading(false);
};
const handleSend = async () => {
await sendMessage({
text: draft,
clearDraft: true,
});
};
const handleFeedbackTip = async () => {
if (selectedOrchestrator !== "feedback") {
return;
}
await sendMessage({
text: "Gib mir einen Hinweis zum nächsten Schritt",
clearDraft: false,
});
};
const handleRevealSolution = async () => {
if (selectedOrchestrator !== "feedback" || isSending) {
return;
}
setIsSending(true);
try {
const response = await fetch(`/api/context/solution`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ draft: chatSessionId }),
});
if (response.status === 404) {
appendAssistantMessage(t("noStoredSolution"));
return;
}
if (!response.ok) {
throw new Error(`Solution failed: ${response.status}`);
}
const payload: { solution?: string } = await response.json();
const solution = typeof payload.solution === "string" ? payload.solution.trim() : "";
appendAssistantMessage(solution || t("noStoredSolution"));
} catch (error) {
appendAssistantMessage(t("chatRequestFailed"));
void error;
} finally {
setIsSending(false);
}
};
const handleToggleCanvas = () => {
setIsCanvasVisible((prev) => !prev);
};
......@@ -1181,6 +1237,10 @@ export default function ChatPage() {
draft={draft}
onDraftChange={handleDraftChange}
onSend={handleSend}
onTip={selectedOrchestrator === "feedback" ? handleFeedbackTip : undefined}
onRevealSolution={
selectedOrchestrator === "feedback" ? handleRevealSolution : undefined
}
isSending={isSending}
onHistoryNavigate={handleHistoryNavigate}
onToggleCanvas={handleToggleCanvas}
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment