diff --git a/apps/ai-game-creator-shell/src/features/runtime-config/RuntimeConfigDialog.tsx b/apps/ai-game-creator-shell/src/features/runtime-config/RuntimeConfigDialog.tsx index c8c9fdd23..df6e2469e 100644 --- a/apps/ai-game-creator-shell/src/features/runtime-config/RuntimeConfigDialog.tsx +++ b/apps/ai-game-creator-shell/src/features/runtime-config/RuntimeConfigDialog.tsx @@ -1,5 +1,19 @@ -import { Plus, Trash2, Zap } from 'lucide-react'; -import { type FormEvent, Fragment, useEffect, useRef, useState } from 'react'; +import { + Bot, + Cable, + CheckCircle2, + CircleAlert, + LoaderCircle, + Plus, + RotateCcw, + Save, + Settings2, + SlidersHorizontal, + Trash2, + X, + Zap, +} from 'lucide-react'; +import { type FormEvent, useEffect, useRef, useState } from 'react'; import { createGameCreationAppSeedTasks } from '../../../../../packages/shared/src/contracts/gameCreationApp'; import { @@ -82,6 +96,40 @@ const runtimeAgentModes = new Set([ 'provider', ]); +type RuntimeSettingsSection = 'general' | 'agents' | 'connections' | 'advanced'; + +const runtimeSettingsSections = [ + { + id: 'general', + label: '常用设置', + description: '运行方式与默认模型', + icon: Settings2, + }, + { + id: 'agents', + label: 'Agent 模型', + description: '按角色覆盖默认模型', + icon: Bot, + }, + { + id: 'connections', + label: '连接与工具', + description: 'MCP 与外部服务', + icon: Cable, + }, + { + id: 'advanced', + label: '高级参数', + description: '上下文、超时与重试', + icon: SlidersHorizontal, + }, +] as const satisfies ReadonlyArray<{ + id: RuntimeSettingsSection; + label: string; + description: string; + icon: typeof Settings2; +}>; + const defaultRuntimeMcpServerConfig: GameCreatorMcpServerConfig = { enabled: true, required: false, @@ -534,6 +582,9 @@ export function RuntimeConfigDialog({ const [runtimeConfigDraft, setRuntimeConfigDraft] = useState(defaultRuntimeConfigDraft); const [runtimeConfigBusy, setRuntimeConfigBusy] = useState(false); + const [activeSection, setActiveSection] = + useState('general'); + const [expandedAgentIds, setExpandedAgentIds] = useState([]); const [newMcpServerId, setNewMcpServerId] = useState(''); const [mcpStructuredDrafts, setMcpStructuredDrafts] = useState< Record @@ -858,6 +909,24 @@ export function RuntimeConfigDialog({ } } + const selectedSection = + runtimeSettingsSections.find((section) => section.id === activeSection) ?? + runtimeSettingsSections[0]; + const configuredAgentCount = Object.values( + runtimeConfigDraft.agentLlm ?? {}, + ).filter((config) => + Object.values(config).some((value) => value !== undefined && value !== ''), + ).length; + const runtimeConfigStatusTone = runtimeConfigBusy + ? 'busy' + : /^(已保存|已读取|已恢复默认|已添加|已移除|MCP 已连接)/.test( + runtimeConfigStatus, + ) + ? 'success' + : runtimeConfigStatus === '未读取' + ? 'neutral' + : 'warning'; + return (
closeDialogOnBackdropMouseDown(event, onClose)} >
closeDialogOnEscape(event, onClose)} > -
-

运行时配置

-
+
+
+ AI GAME CREATOR +

Agent 设置

+
+ +
+
+ +
+
+
+

{selectedSection.label}

+

{selectedSection.description}

+
+ {activeSection === 'agents' ? ( + {configuredAgentCount} 个角色已覆盖 + ) : activeSection === 'connections' ? ( + + {Object.keys(runtimeConfigDraft.mcpServers).length} 个 MCP + + ) : null} +
+
+ {activeSection === 'general' ? ( + <> + + {runtimeConfigDraft.agentMode !== 'codex_cli' ? ( + <> + + + + + + + + + + ) : null} + + ) : null} + {activeSection === 'advanced' && + runtimeConfigDraft.agentMode !== 'codex_cli' ? ( + <> + + + + + + + + ) : null} + {activeSection === 'agents' && + runtimeConfigDraft.agentMode !== 'codex_cli' ? ( +
+ {runtimeAgentLlmRows.map((agent) => { + const agentLlm = + runtimeConfigDraft.agentLlm?.[agent.id] ?? {}; + const defaultReasoningEffort = + runtimeAgentReasoningEffortDefaults[ + agent.id as keyof typeof runtimeAgentReasoningEffortDefaults + ]; + return ( +
+ + {expandedAgentIds.includes(agent.id) ? ( +
+ + + + + + + + + + + +
+ ) : null} +
+ ); + })} +
+ ) : null} + {activeSection === 'connections' ? ( + <> + + + + ) : null} + {activeSection === 'connections' ? ( +
+
+
+

MCP servers

+ {`${Object.keys(runtimeConfigDraft.mcpServers).length} 个配置`} +
+ +
+
+ + +
+ {Object.entries(runtimeConfigDraft.mcpServers).length === + 0 ? ( +

尚未配置 MCP server

+ ) : ( +
+ {Object.entries(runtimeConfigDraft.mcpServers).map( + ([serverId, server]) => { + const structuredDraft = + mcpStructuredDrafts[serverId] ?? + runtimeMcpStructuredDraft(server); + const serverStatus = mcpCatalog?.servers.find( + (candidate) => candidate.serverId === serverId, + ); + return ( +
+
+
+ {serverId} + + {!server.enabled + ? '已停用' + : serverStatus + ? serverStatus.connected + ? `已连接 · ${serverStatus.toolCount} 个工具` + : '连接失败' + : server.transport === 'stdio' + ? 'STDIO · 未测试' + : 'HTTP · 未测试'} + +
+ +
+
+ 配置 +
+ + + + + {server.transport === 'stdio' ? ( + <> + + +