fixed chat

This commit is contained in:
2026-06-11 10:20:49 +03:00
parent 52ab7e1ac4
commit 363aca293a
2 changed files with 31 additions and 30 deletions
+2 -6
View File
@@ -243,9 +243,6 @@ class ChatService:
{"name": fn["name"], "result": json.loads(tool_result)}
)
if notices:
return "\n\n".join(notices), notices, pomodoro_events
followup = await self.llm.complete(
messages,
tools=None,
@@ -384,6 +381,7 @@ class ChatService:
{"name": fn["name"], "result": json.loads(result)},
)
yield self._sse("status", {"phase": "tools"})
for notice in round_notices:
yield self._sse("notice", {"content": notice})
@@ -394,9 +392,6 @@ class ChatService:
final_content = "".join(streamed_reply_parts).strip()
if not final_content and reasoning:
final_content = reasoning.strip()
if not final_content and all_tool_notices:
final_content = "\n\n".join(all_tool_notices)
yield self._sse("token", {"content": final_content})
if not final_content and tools_executed:
retry = await self.llm.complete(
messages,
@@ -407,6 +402,7 @@ class ChatService:
final_content = (retry.get("content") or "").strip()
if final_content:
yield self._sse("token", {"content": final_content})
# Notices уже в чате как role=notice — не дублируем в assistant.
if not final_content:
final_content, fb_notices, fb_pomodoro = await self._fallback_complete(
messages, session_id
+29 -24
View File
@@ -44,9 +44,9 @@ export default function Chat() {
const [input, setInput] = useState("");
const [loading, setLoading] = useState(false);
const [streaming, setStreaming] = useState("");
const [pendingPhase, setPendingPhase] = useState<"thinking" | "preparing" | "generating">(
"thinking",
);
const [pendingPhase, setPendingPhase] = useState<
"thinking" | "preparing" | "generating" | "tools"
>("thinking");
const [liveNotices, setLiveNotices] = useState<string[]>([]);
const [chatError, setChatError] = useState<string | null>(null);
const messagesRef = useRef<HTMLDivElement>(null);
@@ -54,6 +54,7 @@ export default function Chat() {
const scrollRafRef = useRef<number | null>(null);
const { status: pomodoroStatus, refresh: refreshPomodoro } = usePomodoro();
const [lastNotifySeq, setLastNotifySeq] = useState(0);
const pendingHistoryReload = useRef(false);
const loadSessions = async () => {
const data = await api.listSessions();
@@ -108,22 +109,27 @@ export default function Chat() {
const waitingForStream = loading && !streaming;
const pendingLabel =
liveNotices.length > 0
? "Обрабатываю…"
: pendingPhase === "preparing"
? "Собираю контекст…"
: pendingPhase === "generating"
? "Генерирую ответ…"
: "Думаю…";
pendingPhase === "tools"
? "Выполняю команды…"
: liveNotices.length > 0
? "Обрабатываю…"
: pendingPhase === "preparing"
? "Собираю контекст…"
: pendingPhase === "generating"
? "Генерирую ответ…"
: "Думаю…";
useEffect(() => {
const seq = pomodoroStatus?.cycle?.chat_notify_seq ?? 0;
if (seq > lastNotifySeq) {
setLastNotifySeq(seq);
refreshPomodoro().catch(console.error);
// Не перезагружать историю во время стрима — ломает UI и сбивает ответ.
if (activeId && !loading) {
loadMessages(activeId).catch(console.error);
if (activeId) {
if (loading) {
pendingHistoryReload.current = true;
} else {
loadMessages(activeId).catch(console.error);
}
}
}
}, [pomodoroStatus?.cycle?.chat_notify_seq, activeId, lastNotifySeq, refreshPomodoro, loading]);
@@ -178,9 +184,15 @@ export default function Chat() {
if (chunk.data.phase === "generating") {
setPendingPhase("generating");
}
if (chunk.data.phase === "tools") {
setPendingPhase("tools");
assistantText = "";
setStreaming("");
}
}
if (chunk.event === "token") {
assistantText += chunk.data.content;
setPendingPhase("generating");
setStreaming(assistantText);
}
if (chunk.event === "notice") {
@@ -196,17 +208,6 @@ export default function Chat() {
setStreaming("");
setLiveNotices([]);
setChatError(null);
if (assistantText.trim()) {
setMessages((prev) => [
...prev,
{
id: Date.now(),
role: "assistant",
content: assistantText,
created_at: new Date().toISOString(),
},
]);
}
await loadMessages(activeId);
await loadSessions();
}
@@ -224,6 +225,10 @@ export default function Chat() {
}
} finally {
setLoading(false);
if (pendingHistoryReload.current && activeId) {
pendingHistoryReload.current = false;
loadMessages(activeId).catch(console.error);
}
}
};