fix: next server fetch error (#374)

This commit is contained in:
JeffJiang
2025-06-27 14:23:04 +08:00
committed by GitHub
parent f27c96e692
commit 52dfdd83ae
5 changed files with 37 additions and 45 deletions

View File

@@ -15,7 +15,7 @@ import { Tooltip } from "~/components/deer-flow/tooltip";
import { BorderBeam } from "~/components/magicui/border-beam"; import { BorderBeam } from "~/components/magicui/border-beam";
import { Button } from "~/components/ui/button"; import { Button } from "~/components/ui/button";
import { enhancePrompt } from "~/core/api"; import { enhancePrompt } from "~/core/api";
import { getConfig } from "~/core/api/config"; import { useConfig } from "~/core/api/hooks";
import type { Option, Resource } from "~/core/messages"; import type { Option, Resource } from "~/core/messages";
import { import {
setEnableDeepThinking, setEnableDeepThinking,
@@ -52,7 +52,7 @@ export function InputBox({
const backgroundInvestigation = useSettingsStore( const backgroundInvestigation = useSettingsStore(
(state) => state.general.enableBackgroundInvestigation, (state) => state.general.enableBackgroundInvestigation,
); );
const reasoningModel = useMemo(() => getConfig().models.reasoning?.[0], []); const { config, loading } = useConfig();
const reportStyle = useSettingsStore((state) => state.general.reportStyle); const reportStyle = useSettingsStore((state) => state.general.reportStyle);
const containerRef = useRef<HTMLDivElement>(null); const containerRef = useRef<HTMLDivElement>(null);
const inputRef = useRef<MessageInputRef>(null); const inputRef = useRef<MessageInputRef>(null);
@@ -203,13 +203,15 @@ export function InputBox({
isEnhanceAnimating && "transition-all duration-500", isEnhanceAnimating && "transition-all duration-500",
)} )}
ref={inputRef} ref={inputRef}
loading={loading}
config={config}
onEnter={handleSendMessage} onEnter={handleSendMessage}
onChange={setCurrentPrompt} onChange={setCurrentPrompt}
/> />
</div> </div>
<div className="flex items-center px-4 py-2"> <div className="flex items-center px-4 py-2">
<div className="flex grow gap-2"> <div className="flex grow gap-2">
{reasoningModel && ( {config?.models.reasoning?.[0] && (
<Tooltip <Tooltip
className="max-w-60" className="max-w-60"
title={ title={
@@ -219,7 +221,8 @@ export function InputBox({
</h3> </h3>
<p> <p>
When enabled, DeerFlow will use reasoning model ( When enabled, DeerFlow will use reasoning model (
{reasoningModel}) to generate more thoughtful plans. {config.models.reasoning?.[0]}) to generate more thoughtful
plans.
</p> </p>
</div> </div>
} }

View File

@@ -8,7 +8,6 @@ import { Geist } from "next/font/google";
import Script from "next/script"; import Script from "next/script";
import { ThemeProviderWrapper } from "~/components/deer-flow/theme-provider-wrapper"; import { ThemeProviderWrapper } from "~/components/deer-flow/theme-provider-wrapper";
import { loadConfig } from "~/core/api/config";
import { env } from "~/env"; import { env } from "~/env";
import { Toaster } from "../components/deer-flow/toaster"; import { Toaster } from "../components/deer-flow/toaster";
@@ -28,11 +27,9 @@ const geist = Geist({
export default async function RootLayout({ export default async function RootLayout({
children, children,
}: Readonly<{ children: React.ReactNode }>) { }: Readonly<{ children: React.ReactNode }>) {
const conf = await loadConfig();
return ( return (
<html lang="en" className={`${geist.variable}`} suppressHydrationWarning> <html lang="en" className={`${geist.variable}`} suppressHydrationWarning>
<head> <head>
<script>{`window.__deerflowConfig = ${JSON.stringify(conf)}`}</script>
{/* Define isSpace function globally to fix markdown-it issues with Next.js + Turbopack {/* Define isSpace function globally to fix markdown-it issues with Next.js + Turbopack
https://github.com/markdown-it/markdown-it/issues/1082#issuecomment-2749656365 */} https://github.com/markdown-it/markdown-it/issues/1082#issuecomment-2749656365 */}
<Script id="markdown-it-fix" strategy="beforeInteractive"> <Script id="markdown-it-fix" strategy="beforeInteractive">

View File

@@ -20,8 +20,9 @@ import "~/styles/prosemirror.css";
import { resourceSuggestion } from "./resource-suggestion"; import { resourceSuggestion } from "./resource-suggestion";
import React, { forwardRef, useEffect, useMemo, useRef } from "react"; import React, { forwardRef, useEffect, useMemo, useRef } from "react";
import type { Resource } from "~/core/messages"; import type { Resource } from "~/core/messages";
import { useRAGProvider } from "~/core/api/hooks"; import { useConfig } from "~/core/api/hooks";
import { LoadingOutlined } from "@ant-design/icons"; import { LoadingOutlined } from "@ant-design/icons";
import type { DeerFlowConfig } from "~/core/config";
export interface MessageInputRef { export interface MessageInputRef {
focus: () => void; focus: () => void;
@@ -32,6 +33,8 @@ export interface MessageInputRef {
export interface MessageInputProps { export interface MessageInputProps {
className?: string; className?: string;
placeholder?: string; placeholder?: string;
loading?: boolean;
config?: DeerFlowConfig | null;
onChange?: (markdown: string) => void; onChange?: (markdown: string) => void;
onEnter?: (message: string, resources: Array<Resource>) => void; onEnter?: (message: string, resources: Array<Resource>) => void;
} }
@@ -75,7 +78,10 @@ function formatItem(item: JSONContent): {
} }
const MessageInput = forwardRef<MessageInputRef, MessageInputProps>( const MessageInput = forwardRef<MessageInputRef, MessageInputProps>(
({ className, onChange, onEnter }: MessageInputProps, ref) => { (
{ className, loading, config, onChange, onEnter }: MessageInputProps,
ref,
) => {
const editorRef = useRef<Editor>(null); const editorRef = useRef<Editor>(null);
const handleEnterRef = useRef< const handleEnterRef = useRef<
((message: string, resources: Array<Resource>) => void) | undefined ((message: string, resources: Array<Resource>) => void) | undefined
@@ -115,8 +121,6 @@ const MessageInput = forwardRef<MessageInputRef, MessageInputProps>(
handleEnterRef.current = onEnter; handleEnterRef.current = onEnter;
}, [onEnter]); }, [onEnter]);
const { provider, loading } = useRAGProvider();
const extensions = useMemo(() => { const extensions = useMemo(() => {
const extensions = [ const extensions = [
StarterKit, StarterKit,
@@ -132,7 +136,7 @@ const MessageInput = forwardRef<MessageInputRef, MessageInputProps>(
}), }),
Placeholder.configure({ Placeholder.configure({
showOnlyCurrent: false, showOnlyCurrent: false,
placeholder: provider placeholder: config?.rag.provider
? "What can I do for you? \nYou may refer to RAG resources by using @." ? "What can I do for you? \nYou may refer to RAG resources by using @."
: "What can I do for you?", : "What can I do for you?",
emptyEditorClass: "placeholder", emptyEditorClass: "placeholder",
@@ -154,7 +158,7 @@ const MessageInput = forwardRef<MessageInputRef, MessageInputProps>(
}, },
}), }),
]; ];
if (provider) { if (config?.rag.provider) {
extensions.push( extensions.push(
Mention.configure({ Mention.configure({
HTMLAttributes: { HTMLAttributes: {
@@ -165,7 +169,7 @@ const MessageInput = forwardRef<MessageInputRef, MessageInputProps>(
); );
} }
return extensions; return extensions;
}, [provider]); }, [config]);
if (loading) { if (loading) {
return ( return (

View File

@@ -1,25 +0,0 @@
import { type DeerFlowConfig } from "../config/types";
import { resolveServiceURL } from "./resolve-service-url";
declare global {
interface Window {
__deerflowConfig: DeerFlowConfig;
}
}
export async function loadConfig() {
const res = await fetch(resolveServiceURL("./config"));
const config = await res.json();
return config;
}
export function getConfig(): DeerFlowConfig {
if (
typeof window === "undefined" ||
typeof window.__deerflowConfig === "undefined"
) {
throw new Error("Config not loaded");
}
return window.__deerflowConfig;
}

View File

@@ -5,10 +5,11 @@ import { useEffect, useRef, useState } from "react";
import { env } from "~/env"; import { env } from "~/env";
import type { DeerFlowConfig } from "../config";
import { useReplay } from "../replay"; import { useReplay } from "../replay";
import { fetchReplayTitle } from "./chat"; import { fetchReplayTitle } from "./chat";
import { getConfig } from "./config"; import { resolveServiceURL } from "./resolve-service-url";
export function useReplayMetadata() { export function useReplayMetadata() {
const { isReplay } = useReplay(); const { isReplay } = useReplay();
@@ -43,18 +44,30 @@ export function useReplayMetadata() {
return { title, isLoading, hasError: error }; return { title, isLoading, hasError: error };
} }
export function useRAGProvider() { export function useConfig(): {
config: DeerFlowConfig | null;
loading: boolean;
} {
const [loading, setLoading] = useState(true); const [loading, setLoading] = useState(true);
const [provider, setProvider] = useState<string | null>(null); const [config, setConfig] = useState<DeerFlowConfig | null>(null);
useEffect(() => { useEffect(() => {
if (env.NEXT_PUBLIC_STATIC_WEBSITE_ONLY) { if (env.NEXT_PUBLIC_STATIC_WEBSITE_ONLY) {
setLoading(false); setLoading(false);
return; return;
} }
setProvider(getConfig().rag.provider); fetch(resolveServiceURL("./config"))
setLoading(false); .then((res) => res.json())
.then((config) => {
setConfig(config);
setLoading(false);
})
.catch((err) => {
console.error("Failed to fetch config", err);
setConfig(null);
setLoading(false);
});
}, []); }, []);
return { provider, loading }; return { config, loading };
} }