feat: 全栈 Logger 依赖注入 — DB/Route/AI 层传参 + 前端 Logger + 测试更新 + 归档 add-frontend-logger

This commit is contained in:
2026-06-01 20:32:19 +08:00
parent 4c72754739
commit 844562303c
60 changed files with 1648 additions and 778 deletions

View File

@@ -11,6 +11,7 @@ import {
fetchMessages,
updateConversation,
} from "../../../../hooks/use-conversations";
import { useLogger } from "../../../../hooks/use-logger";
import { useModelList } from "../../../../hooks/use-models";
import { ChatInputArea } from "./ChatInputArea";
import { ReasoningPart } from "./parts/ReasoningPart";
@@ -25,6 +26,7 @@ interface ChatPanelProps {
export function ChatPanel({ conversationId, onConversationCreated, projectId }: ChatPanelProps) {
const { message } = App.useApp();
const logger = useLogger().child({ component: "ChatPanel", page: "workbench" });
const queryClient = useQueryClient();
const [input, setInput] = useState("");
const [editingMessageId, setEditingMessageId] = useState<null | string>(null);
@@ -45,6 +47,7 @@ export function ChatPanel({ conversationId, onConversationCreated, projectId }:
const { messages, regenerate, sendMessage, setMessages, status, stop } = useChat({
onError: (err) => {
logger.error("聊天发送失败", { error: err.message });
void message.error(`发送失败:${err.message}`);
},
transport: new DefaultChatTransport({ api: `/api/projects/${projectId}/chat` }),
@@ -87,6 +90,7 @@ export function ChatPanel({ conversationId, onConversationCreated, projectId }:
} catch (err: unknown) {
if (!cancelled) {
const msg = err instanceof Error ? err.message : String(err);
logger.error("加载历史失败", { conversationId, error: msg, projectId });
void message.error(`加载历史失败:${msg}`);
}
} finally {
@@ -99,22 +103,27 @@ export function ChatPanel({ conversationId, onConversationCreated, projectId }:
return () => {
cancelled = true;
};
}, [conversationId, projectId, setMessages, message]);
}, [conversationId, projectId, setMessages, message, logger]);
useEffect(() => {
if (!conversationId) return;
const firstTextId = textModels[0]?.id;
if (!firstTextId) return;
void fetchConversation(projectId, conversationId).then((conv) => {
if (textModels.every((m) => m.id !== conv.modelId)) {
setSelectedModelId(firstTextId);
void updateConversation(projectId, conversationId, { modelId: firstTextId });
} else {
setSelectedModelId(conv.modelId);
}
});
}, [conversationId, textModels, projectId]);
void fetchConversation(projectId, conversationId)
.then((conv) => {
if (textModels.every((m) => m.id !== conv.modelId)) {
setSelectedModelId(firstTextId);
void updateConversation(projectId, conversationId, { modelId: firstTextId });
} else {
setSelectedModelId(conv.modelId);
}
})
.catch((err: unknown) => {
const msg = err instanceof Error ? err.message : String(err);
logger.warn("获取会话模型信息失败", { conversationId, error: msg, projectId });
});
}, [conversationId, textModels, projectId, logger]);
useEffect(() => {
scrollRef.current?.scrollTo({ behavior: "smooth", top: scrollRef.current.scrollHeight });
@@ -132,10 +141,13 @@ export function ChatPanel({ conversationId, onConversationCreated, projectId }:
(value: string) => {
setSelectedModelId(value);
if (conversationId) {
void updateConversation(projectId, conversationId, { modelId: value });
void updateConversation(projectId, conversationId, { modelId: value }).catch((err: unknown) => {
const msg = err instanceof Error ? err.message : String(err);
logger.warn("更新会话模型失败", { conversationId, error: msg, projectId });
});
}
},
[projectId, conversationId],
[projectId, conversationId, logger],
);
const handleSend = useCallback(async () => {
@@ -153,13 +165,27 @@ export function ChatPanel({ conversationId, onConversationCreated, projectId }:
} catch (err: unknown) {
setInput(text);
const msg = err instanceof Error ? err.message : String(err);
logger.error("创建会话失败", { error: msg, projectId });
void message.error(`创建会话失败:${msg}`);
}
return;
}
void sendMessage({ text }, { body: { conversationId } });
}, [input, sendMessage, conversationId, projectId, onConversationCreated, message, queryClient, displayModelId]);
void sendMessage({ text }, { body: { conversationId } }).catch((err: unknown) => {
const msg = err instanceof Error ? err.message : String(err);
logger.error("发送消息失败", { conversationId, error: msg, projectId });
});
}, [
input,
sendMessage,
conversationId,
projectId,
onConversationCreated,
message,
queryClient,
displayModelId,
logger,
]);
const extractText = useCallback((msg: UIMessage) => {
return msg.parts
@@ -171,11 +197,17 @@ export function ChatPanel({ conversationId, onConversationCreated, projectId }:
const handleCopy = useCallback(
(msg: UIMessage) => {
const text = extractText(msg);
void navigator.clipboard.writeText(text).then(() => {
void message.success("已复制");
});
void navigator.clipboard
.writeText(text)
.then(() => {
void message.success("已复制");
})
.catch((err: unknown) => {
const msg = err instanceof Error ? err.message : String(err);
logger.warn("复制失败", { error: msg });
});
},
[extractText, message],
[extractText, message, logger],
);
const handleEditStart = useCallback(
@@ -192,8 +224,11 @@ export function ChatPanel({ conversationId, onConversationCreated, projectId }:
const idx = messages.findIndex((m) => m.id === editingMessageId);
if (idx === -1) return;
setMessages(messages.slice(0, idx));
void sendMessage({ text: editText }, { body: { conversationId } });
}, [editText, conversationId, messages, editingMessageId, setMessages, sendMessage]);
void sendMessage({ text: editText }, { body: { conversationId } }).catch((err: unknown) => {
const msg = err instanceof Error ? err.message : String(err);
logger.error("重新发送消息失败", { conversationId, error: msg, projectId });
});
}, [editText, conversationId, messages, editingMessageId, setMessages, sendMessage, logger, projectId]);
const handleEditCancel = useCallback(() => {
setEditingMessageId(null);
@@ -202,8 +237,11 @@ export function ChatPanel({ conversationId, onConversationCreated, projectId }:
const handleRegenerate = useCallback(() => {
if (!conversationId) return;
void regenerate({ body: { conversationId } });
}, [regenerate, conversationId]);
void regenerate({ body: { conversationId } }).catch((err: unknown) => {
const msg = err instanceof Error ? err.message : String(err);
logger.error("重新生成失败", { conversationId, error: msg, projectId });
});
}, [regenerate, conversationId, logger, projectId]);
const getCardExtra = useCallback(
(msg: UIMessage, idx: number) => {
@@ -282,7 +320,10 @@ export function ChatPanel({ conversationId, onConversationCreated, projectId }:
void handleSend();
}}
onStop={() => {
void stop();
void stop().catch((err: unknown) => {
const msg = err instanceof Error ? err.message : String(err);
logger.warn("停止聊天失败", { error: msg });
});
}}
/>
</div>
@@ -350,7 +391,10 @@ export function ChatPanel({ conversationId, onConversationCreated, projectId }:
void handleSend();
}}
onStop={() => {
void stop();
void stop().catch((err: unknown) => {
const msg = err instanceof Error ? err.message : String(err);
logger.warn("停止聊天失败", { error: msg });
});
}}
/>
</div>