From 57cb1fa39160bbe922b01eb06a5bba2ae9c49e4f Mon Sep 17 00:00:00 2001 From: AIGameCreator App Date: Thu, 9 Jul 2026 15:00:35 +0800 Subject: [PATCH] =?UTF-8?q?=E6=8F=90=E7=A4=BAAgent=E8=81=8A=E5=A4=A9LLM?= =?UTF-8?q?=E9=85=8D=E7=BD=AE=E7=BC=BA=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 开发 Agent 聊天入口主动检查并展示当前 Agent LLM 配置状态 单 Agent 对话在 LLM 未就绪时显示配置提示并阻止发送 补充开发入口和项目对话入口的 LLM 缺口回归测试 --- apps/ai-game-creator-shell/src/App.tsx | 144 ++++++++++++++- apps/ai-game-creator-shell/src/styles.css | 32 +++- .../tests/appSurface.test.ts | 165 ++++++++++++++++++ 3 files changed, 335 insertions(+), 6 deletions(-) diff --git a/apps/ai-game-creator-shell/src/App.tsx b/apps/ai-game-creator-shell/src/App.tsx index 982cfd334..657e383c4 100644 --- a/apps/ai-game-creator-shell/src/App.tsx +++ b/apps/ai-game-creator-shell/src/App.tsx @@ -2190,6 +2190,10 @@ export function WorkspaceLauncher({ const [agentChatInput, setAgentChatInput] = useState(''); const [agentChatStatus, setAgentChatStatus] = useState('请选择项目和 Agent'); const [agentChatBusy, setAgentChatBusy] = useState(false); + const [agentChatLlmConfigStatus, setAgentChatLlmConfigStatus] = + useState(null); + const [agentChatLlmStatus, setAgentChatLlmStatus] = + useState('尚未检查 LLM 配置'); const agentChatLoadVersionRef = useRef(0); useEffect(() => { @@ -2270,6 +2274,13 @@ export function WorkspaceLauncher({ void loadWalletLedger(); }, [walletPanelOpen, walletLedgerStatus]); + useEffect(() => { + if (launcherView !== 'agent-chat') { + return; + } + void loadAgentChatLlmStatus(); + }, [launcherView, agentChatSelectedAgentId]); + useEffect(() => { function closeSidebarMenusIfOutside(target: EventTarget | null) { if (!(target instanceof Node)) { @@ -2799,6 +2810,51 @@ export function WorkspaceLauncher({ ); } + function getCurrentAgentChatLlmWarning( + agent = selectedLauncherAgentChatAgent(), + ) { + if (!agent) { + return null; + } + return formatAgentLlmConfigWarning(agentChatLlmConfigStatus, agent); + } + + async function loadAgentChatLlmStatus() { + const invoke = resolveTauriInvoke(); + if (!invoke) { + setAgentChatLlmConfigStatus(null); + setAgentChatLlmStatus('需要在 Tauri App 内检查 LLM 配置'); + return; + } + setAgentChatLlmStatus('正在检查 LLM 配置'); + try { + const status = await invoke( + 'check_game_creator_llm_config', + ); + setAgentChatLlmConfigStatus(status); + const agent = selectedLauncherAgentChatAgent(); + const agentStatus = agent ? llmStatusForAgentCard(status, agent) : null; + if (!agentStatus) { + setAgentChatLlmStatus('未找到当前 Agent 的 LLM 路由'); + return; + } + setAgentChatLlmStatus( + agentStatus.configured + ? `当前 Agent LLM 已配置:${ + agentStatus.model ?? '未命名模型' + },API Key ${agentStatus.apiKeyPresent ? '已读取' : '未读取'}` + : `当前 Agent LLM 未就绪:${ + agentStatus.error ?? '缺少 API Key 或模型配置' + }`, + ); + } catch (error) { + setAgentChatLlmConfigStatus(null); + setAgentChatLlmStatus( + `LLM 状态读取失败:${error instanceof Error ? error.message : String(error)}`, + ); + } + } + async function handleAgentChatPickProjectDirectory() { const invoke = resolveTauriInvoke(); if (!invoke) { @@ -2874,6 +2930,11 @@ export function WorkspaceLauncher({ if (!projectPathForChat || !agent || !content || agentChatBusy) { return; } + const llmWarning = getCurrentAgentChatLlmWarning(agent); + if (llmWarning) { + setAgentChatStatus(llmWarning); + return; + } const invoke = resolveTauriInvoke(); if (!invoke) { setAgentChatStatus('需要在 Tauri App 内运行'); @@ -3019,6 +3080,9 @@ export function WorkspaceLauncher({ homeAgentModeItems[0]!; const ActiveHomeModeIcon = activeHomeMode.icon; const currentAgentChatAgent = selectedLauncherAgentChatAgent(); + const currentAgentChatLlmWarning = getCurrentAgentChatLlmWarning( + currentAgentChatAgent, + ); const currentHelpTitle = launcherView === 'guide' ? '使用指南' @@ -3521,6 +3585,19 @@ export function WorkspaceLauncher({

{agentChatStatus}

+ +
{currentAgentChatAgent @@ -3598,6 +3676,17 @@ export function WorkspaceLauncher({ : '请选择 Agent'} + {currentAgentChatLlmWarning ? ( +
+ {currentAgentChatLlmWarning} + +
+ ) : null}
{agentChatMessages.length > 0 ? ( agentChatMessages.map((message, index) => ( @@ -3618,13 +3707,16 @@ export function WorkspaceLauncher({ > setAgentChatInput(event.currentTarget.value) } /> - @@ -10240,7 +10332,7 @@ function summarizeAgentLlmRoutes(status: GameCreatorLlmConfigStatus) { function llmStatusForAgentCard( status: GameCreatorLlmConfigStatus | null, - agent: AgentStatusCard, + agent: Pick, ) { return ( status?.agents?.find( @@ -10250,6 +10342,19 @@ function llmStatusForAgentCard( ); } +function formatAgentLlmConfigWarning( + status: GameCreatorLlmConfigStatus | null, + agent: Pick, +) { + const agentStatus = llmStatusForAgentCard(status, agent); + if (!agentStatus || agentStatus.configured) { + return null; + } + return `当前 Agent LLM 未就绪:${ + agentStatus.error ?? `${agentStatus.label} 缺少 API Key 或模型配置` + }`; +} + function formatAgentCardLlmStatus( status: GameCreatorLlmConfigStatus | null, agent: AgentStatusCard, @@ -11921,6 +12026,16 @@ export function App() { setAgentMemoryStatus('请先初始化本地项目'); return; } + try { + const status = await invoke( + 'check_game_creator_llm_config', + ); + if (agentConversationLoadVersionRef.current === loadVersion) { + setLlmConfigStatus(status); + } + } catch { + // Agent conversation history is still useful when config status is unavailable. + } try { if ( !skipConversationPolicyConfirm && @@ -12119,6 +12234,11 @@ export function App() { setAgentConversationStatus('请先初始化本地项目'); return; } + const llmWarning = formatAgentLlmConfigWarning(llmConfigStatus, agent); + if (llmWarning) { + setAgentConversationStatus(llmWarning); + return; + } const saveVersion = agentConversationLoadVersionRef.current; try { if ( @@ -18432,6 +18552,9 @@ export function App() { const selectedAgentLlmStatus = selectedAgent ? formatAgentDialogLlmStatus(llmConfigStatus, selectedAgent) : null; + const selectedAgentLlmWarning = selectedAgent + ? formatAgentLlmConfigWarning(llmConfigStatus, selectedAgent) + : null; function showEarlierConversationMessages() { setConversationVisibleCount((current) => @@ -19309,6 +19432,14 @@ export function App() {
+ {selectedAgentLlmWarning ? ( +
+ {selectedAgentLlmWarning} + +
+ ) : null}
setAgentConversationInput(event.currentTarget.value) } /> -