Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 23 additions & 10 deletions app/components/DocsAssistant.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,28 +34,33 @@ export function DocsAssistant({ pageContext }: DocsAssistantProps) {
function DocsAssistantInner({ pageContext }: DocsAssistantProps) {
const { provider, openaiApiKey, geminiApiKey } = useAssistantSettings();

const apiKey =
provider === "openai"
? openaiApiKey
: provider === "gemini"
? geminiApiKey
: "";

const transport = useMemo(
() =>
new DefaultChatTransport({
api: "/api/chat",
body: () => {
const apiKey =
provider === "openai"
? openaiApiKey
: provider === "gemini"
? geminiApiKey
: ""; // intern provider doesn't need API key

return { pageContext, provider, apiKey };
body: {
pageContext,
provider,
apiKey,
},
}),
[geminiApiKey, openaiApiKey, pageContext, provider],
[pageContext, provider, apiKey],
);

const chat = useChat({
id: `assistant-${provider}-${apiKey}`, // Force chat reset when provider OR key changes
// 当 Provider 或 Key 更改时强制重置聊天
transport,
onFinish: () => {
// 当对话结束时(流式传输完成),记录一次查询行为
// Track AI query when chat finishes (streaming completes)
if (window.umami) {
window.umami.track("ai_assistant_query");
}
Expand All @@ -68,6 +73,12 @@ function DocsAssistantInner({ pageContext }: DocsAssistantProps) {
clearError: clearChatError,
} = chat;

// Clear previous error when Provider changes
// 当 Provider 更改时清除之前的错误
useEffect(() => {
clearChatError();
}, [provider, clearChatError]);

useEffect(() => {
if (chatStatus === "submitted" || chatStatus === "streaming") {
clearChatError();
Expand Down Expand Up @@ -175,6 +186,7 @@ function deriveAssistantError(
let showSettingsCTA = false;

// For intern provider, don't show settings CTA for API key related errors
// 对于书生,不要显示 API 密钥相关的错误
if (
provider !== "intern" &&
(statusCode === 400 ||
Expand Down Expand Up @@ -244,6 +256,7 @@ function extractErrorFromResponseBody(body: string): string | undefined {
}
} catch {
// Ignore JSON parsing issues and fall back to the raw body text.
// 忽略 JSON 解析问题,回退到原始正文文本。
}

return trimmed;
Expand Down
4 changes: 3 additions & 1 deletion app/hooks/useAssistantSettings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ interface AssistantSettingsContextValue extends AssistantSettingsState {
const SETTINGS_KEY = "assistant-settings-storage";

const defaultSettings: AssistantSettingsState = {
provider: "openai",
provider: "intern",
openaiApiKey: "",
geminiApiKey: "",
saveToLocalStorage: false,
Expand All @@ -56,6 +56,7 @@ const parseStoredSettings = (raw: string | null): AssistantSettingsState => {
: parsed.provider === "intern"
? "intern"
: "openai",
// Use only stored key if saveToLocalStorage is true
// 只有在saveToLocalStorage为true时才使用存储的key
openaiApiKey:
saveToLocalStorage && typeof parsed.openaiApiKey === "string"
Expand Down Expand Up @@ -100,6 +101,7 @@ export const AssistantSettingsProvider = ({
}

try {
// Decide whether to save API keys based on saveToLocalStorage
// 根据saveToLocalStorage决定是否保存API key
const dataToSave = settings.saveToLocalStorage
? settings
Expand Down
Loading