diff --git a/src/web/pages/ModelTester.tsx b/src/web/pages/ModelTester.tsx
index 64de6e3..f3ae2d5 100644
--- a/src/web/pages/ModelTester.tsx
+++ b/src/web/pages/ModelTester.tsx
@@ -53,6 +53,7 @@ import {
isConversationUploadedFileSupported,
resolveConversationFileCapability,
} from './helpers/conversationFileCapabilities.js';
+import DebugPanel from './model-tester/DebugPanel.js';
import ModernSelect from '../components/ModernSelect.js';
import { useAnimatedVisibility } from '../components/useAnimatedVisibility.js';
import { useIsMobile } from '../components/useIsMobile.js';
@@ -3104,102 +3105,15 @@ export default function ModelTester() {
- {debugPanelPresence.shouldRender && (
-
-
-
调试
-
- {debugTimestamp ? new Date(debugTimestamp).toLocaleString() : '--'}
-
-
-
-
-
-
-
-
-
-
-
- {debugTabContent || '// 暂无数据'}
-
-
-
-
时间线
-
- {debugTimeline.length === 0 ? (
-
暂无事件。
- ) : (
-
- {debugTimeline.map((item, index) => (
-
-
- {item.level}
-
-
- {new Date(item.at).toLocaleTimeString()}
-
- {item.text}
-
- ))}
-
- )}
-
-
- )}
+
);
diff --git a/src/web/pages/model-tester/DebugPanel.tsx b/src/web/pages/model-tester/DebugPanel.tsx
new file mode 100644
index 0000000..69705ee
--- /dev/null
+++ b/src/web/pages/model-tester/DebugPanel.tsx
@@ -0,0 +1,144 @@
+import React from 'react';
+import { DEBUG_TABS, type DebugTab } from '../helpers/modelTesterSession.js';
+
+type DebugTimelineEntry = {
+ at: string;
+ level: 'info' | 'warn' | 'error';
+ text: string;
+};
+
+type DebugPanelPresence = {
+ shouldRender: boolean;
+ isVisible: boolean;
+};
+
+type DebugPanelProps = {
+ presence: DebugPanelPresence;
+ isMobile: boolean;
+ debugTimestamp: number | null;
+ activeDebugTab: DebugTab;
+ onTabChange: (tab: DebugTab) => void;
+ debugTabContent: string;
+ debugTimeline: DebugTimelineEntry[];
+};
+
+export default function DebugPanel({
+ presence,
+ isMobile,
+ debugTimestamp,
+ activeDebugTab,
+ onTabChange,
+ debugTabContent,
+ debugTimeline,
+}: DebugPanelProps) {
+ if (!presence.shouldRender) {
+ return null;
+ }
+
+ return (
+
+
+
调试
+
+ {debugTimestamp ? new Date(debugTimestamp).toLocaleString() : '--'}
+
+
+
+
+
+
+
+
+
+
+
+ {debugTabContent || '// 暂无数据'}
+
+
+
+
时间线
+
+ {debugTimeline.length === 0 ? (
+
暂无事件。
+ ) : (
+
+ {debugTimeline.map((item, index) => (
+
+
+ {item.level}
+
+
+ {new Date(item.at).toLocaleTimeString()}
+
+ {item.text}
+
+ ))}
+
+ )}
+
+
+ );
+}
diff --git a/src/web/pages/modelTester.debug-panel.architecture.test.tsx b/src/web/pages/modelTester.debug-panel.architecture.test.tsx
new file mode 100644
index 0000000..6d6ad18
--- /dev/null
+++ b/src/web/pages/modelTester.debug-panel.architecture.test.tsx
@@ -0,0 +1,12 @@
+import { describe, expect, it } from 'vitest';
+import { readFileSync } from 'node:fs';
+import { resolve } from 'node:path';
+
+describe('ModelTester debug panel extraction', () => {
+ it('delegates the debug sidebar to a dedicated model-tester component', () => {
+ const source = readFileSync(resolve(process.cwd(), 'src/web/pages/ModelTester.tsx'), 'utf8').replace(/\r\n/g, '\n');
+
+ expect(source).toContain("import DebugPanel from './model-tester/DebugPanel.js'");
+ expect(source).not.toContain('时间线');
+ });
+});