AI assistant pane is displayed for supported screens when the AI assistant feature flag is enabled  (#9591)

diff --git a/packages/devtools_app/integration_test/test/live_connection/memory_screen_helpers.dart b/packages/devtools_app/integration_test/test/live_connection/memory_screen_helpers.dart
index 87efb70..2753d97 100644
--- a/packages/devtools_app/integration_test/test/live_connection/memory_screen_helpers.dart
+++ b/packages/devtools_app/integration_test/test/live_connection/memory_screen_helpers.dart
@@ -3,9 +3,9 @@
 // found in the LICENSE file or at https://developers.google.com/open-source/licenses/bsd.
 
 import 'package:devtools_app/devtools_app.dart';
+import 'package:devtools_app/src/framework/scaffold/bottom_pane.dart';
 import 'package:devtools_app/src/screens/memory/panes/control/widgets/primary_controls.dart';
 import 'package:devtools_app/src/screens/memory/panes/diff/widgets/snapshot_list.dart';
-import 'package:devtools_app/src/shared/console/widgets/console_pane.dart';
 import 'package:devtools_test/helpers.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_test/flutter_test.dart';
@@ -45,7 +45,7 @@
     // but not too big to make classes in snapshot hidden.
     const dragDistance = -320.0;
     await tester.drag(
-      find.byType(ConsolePaneHeader),
+      find.byKey(BottomPane.splitterKey),
       const Offset(0, dragDistance),
     );
     await tester.pumpAndSettle();
diff --git a/packages/devtools_app/lib/src/framework/scaffold/bottom_pane.dart b/packages/devtools_app/lib/src/framework/scaffold/bottom_pane.dart
new file mode 100644
index 0000000..bba85e2
--- /dev/null
+++ b/packages/devtools_app/lib/src/framework/scaffold/bottom_pane.dart
@@ -0,0 +1,38 @@
+// Copyright 2025 The Flutter Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file or at https://developers.google.com/open-source/licenses/bsd.
+
+import 'package:flutter/material.dart';
+
+import '../../shared/ui/tab.dart';
+
+/// A widget that displays a tabbed view at the bottom of the DevTools screen.
+///
+/// This widget is used to host views like the console and the AI Assistant.
+class BottomPane extends StatelessWidget {
+  const BottomPane({super.key, required this.screenId, required this.tabs})
+    : assert(tabs.length > 0);
+
+  static const splitterKey = Key('Bottom Pane Splitter');
+
+  final String screenId;
+  final List<TabbedPane> tabs;
+
+  @override
+  Widget build(BuildContext context) {
+    return AnalyticsTabbedView(
+      gaScreen: screenId,
+      tabs: tabs
+          .map((tabbedPane) => (tab: tabbedPane.tab, tabView: tabbedPane))
+          .toList(),
+      staticSingleTab: true,
+    );
+  }
+}
+
+/// An interface for a widget that should be displayed as a tab in the
+/// [BottomPane].
+abstract class TabbedPane implements Widget {
+  /// The tab to display for this pane.
+  DevToolsTab get tab;
+}
diff --git a/packages/devtools_app/lib/src/framework/scaffold/scaffold.dart b/packages/devtools_app/lib/src/framework/scaffold/scaffold.dart
index 823ad42..978f7b3 100644
--- a/packages/devtools_app/lib/src/framework/scaffold/scaffold.dart
+++ b/packages/devtools_app/lib/src/framework/scaffold/scaffold.dart
@@ -11,6 +11,7 @@
 import '../../app.dart';
 import '../../extensions/extension_settings.dart';
 import '../../screens/debugger/debugger_screen.dart';
+import '../../shared/ai_assistant/widgets/ai_assistant_pane.dart';
 import '../../shared/analytics/prompt.dart';
 import '../../shared/config_specific/drag_and_drop/drag_and_drop.dart';
 import '../../shared/config_specific/import_export/import_export.dart';
@@ -25,6 +26,7 @@
 import '../../shared/title.dart';
 import 'about_dialog.dart';
 import 'app_bar.dart';
+import 'bottom_pane.dart';
 import 'report_feedback_button.dart';
 import 'settings_dialog.dart';
 import 'status_line.dart';
@@ -310,10 +312,16 @@
     return Provider<ImportController>.value(
       value: _importController,
       builder: (context, _) {
-        final showConsole =
+        final isConnectedAppView =
             serviceConnection.serviceManager.connectedAppInitialized &&
-            !offlineDataController.showingOfflineData.value &&
-            _currentScreen.showConsole(widget.embedMode);
+            !offlineDataController.showingOfflineData.value;
+        final showConsole =
+            isConnectedAppView && _currentScreen.showConsole(widget.embedMode);
+        final showAiAssistant =
+            FeatureFlags.aiAssistant.isEnabled &&
+            isConnectedAppView &&
+            _currentScreen.showAiAssistant();
+        final showBottomPane = showConsole || showAiAssistant;
         final containsSingleSimpleScreen =
             widget.screens.length == 1 && widget.screens.first is SimpleScreen;
         final showAppBar =
@@ -345,20 +353,24 @@
               body: OutlineDecoration.onlyTop(
                 child: Padding(
                   padding: widget.appPadding,
-                  child: showConsole
+                  child: showBottomPane
                       ? SplitPane(
                           axis: Axis.vertical,
-                          splitters: [ConsolePaneHeader()],
                           initialFractions: const [0.8, 0.2],
-                          children: [
-                            Padding(
-                              padding: const EdgeInsets.only(
-                                bottom: intermediateSpacing,
-                              ),
-                              child: content,
+                          splitters: const [
+                            DefaultSplitter(
+                              key: BottomPane.splitterKey,
+                              isHorizontal: true,
                             ),
-                            RoundedOutlinedBorder.onlyBottom(
-                              child: const ConsolePane(),
+                          ],
+                          children: [
+                            content,
+                            BottomPane(
+                              screenId: _currentScreen.screenId,
+                              tabs: [
+                                if (showConsole) const ConsolePane(),
+                                if (showAiAssistant) const AiAssistantPane(),
+                              ],
                             ),
                           ],
                         )
diff --git a/packages/devtools_app/lib/src/screens/inspector_shared/inspector_screen.dart b/packages/devtools_app/lib/src/screens/inspector_shared/inspector_screen.dart
index b8b7744..710743d 100644
--- a/packages/devtools_app/lib/src/screens/inspector_shared/inspector_screen.dart
+++ b/packages/devtools_app/lib/src/screens/inspector_shared/inspector_screen.dart
@@ -26,6 +26,9 @@
   bool showConsole(EmbedMode embedMode) => !embedMode.embedded;
 
   @override
+  bool showAiAssistant() => true;
+
+  @override
   String get docPageId => screenId;
 
   @override
diff --git a/packages/devtools_app/lib/src/screens/network/network_screen.dart b/packages/devtools_app/lib/src/screens/network/network_screen.dart
index cd52632..5171c5e 100644
--- a/packages/devtools_app/lib/src/screens/network/network_screen.dart
+++ b/packages/devtools_app/lib/src/screens/network/network_screen.dart
@@ -40,6 +40,9 @@
   String get docPageId => screenId;
 
   @override
+  bool showAiAssistant() => true;
+
+  @override
   Widget buildScreenBody(BuildContext context) => const NetworkScreenBody();
 
   @override
diff --git a/packages/devtools_app/lib/src/shared/ai_assistant/widgets/ai_assistant_pane.dart b/packages/devtools_app/lib/src/shared/ai_assistant/widgets/ai_assistant_pane.dart
new file mode 100644
index 0000000..b3d2128
--- /dev/null
+++ b/packages/devtools_app/lib/src/shared/ai_assistant/widgets/ai_assistant_pane.dart
@@ -0,0 +1,29 @@
+// Copyright 2025 The Flutter Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file or at https://developers.google.com/open-source/licenses/bsd.
+
+import 'package:flutter/material.dart';
+
+import '../../../framework/scaffold/bottom_pane.dart';
+import '../../ui/tab.dart';
+
+class AiAssistantPane extends StatelessWidget implements TabbedPane {
+  const AiAssistantPane({super.key});
+
+  @override
+  DevToolsTab get tab =>
+      DevToolsTab.create(tabName: _tabName, gaPrefix: _gaPrefix);
+
+  static const _tabName = 'AI Assistant';
+
+  static const _gaPrefix = 'aiAssistant';
+
+  @override
+  Widget build(BuildContext context) {
+    return const Column(
+      children: [
+        Expanded(child: Center(child: Text('TODO: Implement AI Assistant.'))),
+      ],
+    );
+  }
+}
diff --git a/packages/devtools_app/lib/src/shared/console/widgets/console_pane.dart b/packages/devtools_app/lib/src/shared/console/widgets/console_pane.dart
index 5a40db7..4d661cc 100644
--- a/packages/devtools_app/lib/src/shared/console/widgets/console_pane.dart
+++ b/packages/devtools_app/lib/src/shared/console/widgets/console_pane.dart
@@ -6,8 +6,10 @@
 import 'package:flutter/foundation.dart';
 import 'package:flutter/material.dart';
 
+import '../../../framework/scaffold/bottom_pane.dart';
 import '../../globals.dart';
 import '../../ui/common_widgets.dart';
+import '../../ui/tab.dart';
 import '../console.dart';
 import '../console_service.dart';
 import 'evaluate.dart';
@@ -15,31 +17,8 @@
 
 // TODO(devoncarew): Show some small UI indicator when we receive stdout/stderr.
 
-class ConsolePaneHeader extends AreaPaneHeader {
-  ConsolePaneHeader({super.key})
-    : super(
-        title: const Text('Console'),
-        roundedTopBorder: true,
-        actions: [
-          const ConsoleHelpLink(),
-          const SizedBox(width: densePadding),
-          CopyToClipboardControl(
-            dataProvider: () =>
-                serviceConnection.consoleService.stdio.value.join('\n'),
-            buttonKey: ConsolePane.copyToClipboardButtonKey,
-          ),
-          const SizedBox(width: densePadding),
-          DeleteControl(
-            buttonKey: ConsolePane.clearStdioButtonKey,
-            tooltip: 'Clear console output',
-            onPressed: () => serviceConnection.consoleService.clearStdio(),
-          ),
-        ],
-      );
-}
-
 /// Display the stdout and stderr output from the process under debug.
-class ConsolePane extends StatelessWidget {
+class ConsolePane extends StatelessWidget implements TabbedPane {
   const ConsolePane({super.key});
 
   static const copyToClipboardButtonKey = Key(
@@ -47,6 +26,17 @@
   );
   static const clearStdioButtonKey = Key('console_clear_stdio_button');
 
+  static const _tabName = 'Console';
+
+  static const _gaPrefix = 'consolePane';
+
+  @override
+  DevToolsTab get tab => DevToolsTab.create(
+    tabName: _tabName,
+    gaPrefix: _gaPrefix,
+    trailing: const _ConsoleActions(),
+  );
+
   ValueListenable<List<ConsoleLine>> get stdio =>
       serviceConnection.consoleService.stdio;
 
@@ -61,10 +51,30 @@
       footer = const ExpressionEvalField();
     }
 
-    return Column(
-      children: [
-        Expanded(
-          child: Console(lines: stdio, footer: footer),
+    return Console(lines: stdio, footer: footer);
+  }
+}
+
+class _ConsoleActions extends StatelessWidget {
+  const _ConsoleActions();
+
+  @override
+  Widget build(BuildContext context) {
+    return Row(
+      mainAxisSize: MainAxisSize.min,
+      children: <Widget>[
+        const ConsoleHelpLink(),
+        const SizedBox(width: densePadding),
+        CopyToClipboardControl(
+          dataProvider: () =>
+              serviceConnection.consoleService.stdio.value.join('\n'),
+          buttonKey: ConsolePane.copyToClipboardButtonKey,
+        ),
+        const SizedBox(width: densePadding),
+        DeleteControl(
+          buttonKey: ConsolePane.clearStdioButtonKey,
+          tooltip: 'Clear console output',
+          onPressed: () => serviceConnection.consoleService.clearStdio(),
         ),
       ],
     );
diff --git a/packages/devtools_app/lib/src/shared/feature_flags.dart b/packages/devtools_app/lib/src/shared/feature_flags.dart
index e15d825..88a8b24 100644
--- a/packages/devtools_app/lib/src/shared/feature_flags.dart
+++ b/packages/devtools_app/lib/src/shared/feature_flags.dart
@@ -85,6 +85,14 @@
     enabled: true,
   );
 
+  /// Flag to enable the AI Assistant.
+  ///
+  /// https://github.com/flutter/devtools/issues/9590
+  static final aiAssistant = BooleanFeatureFlag(
+    name: 'aiAssistant',
+    enabled: enableExperiments,
+  );
+
   /// A set of all the boolean feature flags for debugging purposes.
   ///
   /// When adding a new boolean flag, you are responsible for adding it to this
@@ -95,6 +103,7 @@
     devToolsExtensions,
     dapDebugging,
     inspectorV2,
+    aiAssistant,
   };
 
   /// A set of all the Flutter channel feature flags for debugging purposes.
diff --git a/packages/devtools_app/lib/src/shared/framework/screen.dart b/packages/devtools_app/lib/src/shared/framework/screen.dart
index c3b4931..0cdc840 100644
--- a/packages/devtools_app/lib/src/shared/framework/screen.dart
+++ b/packages/devtools_app/lib/src/shared/framework/screen.dart
@@ -290,6 +290,9 @@
   /// Whether to show the console for this screen.
   bool showConsole(EmbedMode embedMode) => false;
 
+  /// Whether to show the AI Assistant for this screen.
+  bool showAiAssistant() => false;
+
   /// Which keyboard shortcuts should be enabled for this screen.
   ShortcutsConfiguration buildKeyboardShortcuts(BuildContext context) =>
       ShortcutsConfiguration.empty();
diff --git a/packages/devtools_app/lib/src/shared/ui/tab.dart b/packages/devtools_app/lib/src/shared/ui/tab.dart
index ebd6e2a..6961b55 100644
--- a/packages/devtools_app/lib/src/shared/ui/tab.dart
+++ b/packages/devtools_app/lib/src/shared/ui/tab.dart
@@ -81,6 +81,7 @@
     this.onTabChanged,
     this.initialSelectedIndex,
     this.analyticsSessionIdentifier,
+    this.staticSingleTab = false,
   }) : trailingWidgets = List.generate(
          tabs.length,
          (index) => tabs[index].tab.trailing ?? const SizedBox(),
@@ -106,6 +107,10 @@
   /// events.
   final String? analyticsSessionIdentifier;
 
+  /// When there is only a single tab, whether to display that tab as a static
+  /// title instead of in a [TabBar].
+  final bool staticSingleTab;
+
   /// Whether to send analytics events to GA.
   ///
   /// Only set this to false if [AnalyticsTabbedView] is being used for
@@ -202,13 +207,10 @@
         child: Row(
           mainAxisAlignment: MainAxisAlignment.spaceBetween,
           children: [
-            Expanded(
-              child: TabBar(
-                labelColor: Theme.of(context).colorScheme.onSurface,
-                controller: _tabController,
-                tabs: widget.tabs.map((t) => t.tab).toList(),
-                isScrollable: true,
-              ),
+            _AnalyticsTabBar(
+              tabs: widget.tabs.map((t) => t.tab).toList(),
+              tabController: _tabController,
+              staticSingleTab: widget.staticSingleTab,
             ),
             widget.trailingWidgets[_currentTabControllerIndex],
           ],
@@ -233,3 +235,34 @@
     );
   }
 }
+
+/// A [TabBar] used by [AnalyticsTabbedView].
+///
+/// When there is only a single tab and [staticSingleTab] is true, this tab bar
+/// will be displayed as a static title.
+class _AnalyticsTabBar extends StatelessWidget {
+  const _AnalyticsTabBar({
+    required this.tabs,
+    required this.tabController,
+    required this.staticSingleTab,
+  });
+
+  static const _tabPadding = 14.0;
+
+  final List<DevToolsTab> tabs;
+  final TabController? tabController;
+  final bool staticSingleTab;
+
+  @override
+  Widget build(BuildContext context) => (staticSingleTab && tabs.length == 1)
+      ? Padding(
+          padding: const EdgeInsets.symmetric(horizontal: _tabPadding),
+          child: tabs.first,
+        )
+      : TabBar(
+          labelColor: Theme.of(context).colorScheme.onSurface,
+          controller: tabController,
+          tabs: tabs,
+          isScrollable: true,
+        );
+}
diff --git a/packages/devtools_app/test/framework/scaffold/scaffold_ai_assistant_test.dart b/packages/devtools_app/test/framework/scaffold/scaffold_ai_assistant_test.dart
new file mode 100644
index 0000000..8b3d04f
--- /dev/null
+++ b/packages/devtools_app/test/framework/scaffold/scaffold_ai_assistant_test.dart
@@ -0,0 +1,159 @@
+// Copyright 2025 The Flutter Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file or at https://developers.google.com/open-source/licenses/bsd.
+
+import 'package:devtools_app/devtools_app.dart';
+import 'package:devtools_app/src/framework/scaffold/scaffold.dart';
+import 'package:devtools_app/src/shared/ai_assistant/widgets/ai_assistant_pane.dart';
+import 'package:devtools_app/src/shared/feature_flags.dart';
+import 'package:devtools_app/src/shared/framework/framework_controller.dart';
+import 'package:devtools_app/src/shared/managers/survey.dart';
+import 'package:devtools_app_shared/service.dart';
+import 'package:devtools_app_shared/ui.dart';
+import 'package:devtools_app_shared/utils.dart';
+import 'package:devtools_test/devtools_test.dart';
+import 'package:devtools_test/helpers.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_test/flutter_test.dart';
+import 'package:mockito/mockito.dart';
+
+void main() {
+  late MockServiceConnectionManager mockServiceConnection;
+  late MockServiceManager mockServiceManager;
+
+  setUp(() {
+    mockServiceConnection = createMockServiceConnectionWithDefaults();
+    mockServiceManager =
+        mockServiceConnection.serviceManager as MockServiceManager;
+    when(
+      mockServiceManager.connectedState,
+    ).thenReturn(ValueNotifier<ConnectedState>(const ConnectedState(false)));
+    final mockErrorBadgeManager = MockErrorBadgeManager();
+    when(
+      mockServiceConnection.errorBadgeManager,
+    ).thenReturn(mockErrorBadgeManager);
+    when(
+      mockErrorBadgeManager.errorCountNotifier(any),
+    ).thenReturn(ValueNotifier<int>(0));
+
+    setGlobal(ServiceConnectionManager, mockServiceConnection);
+    setGlobal(FrameworkController, FrameworkController());
+    setGlobal(SurveyService, SurveyService());
+    setGlobal(IdeTheme, IdeTheme());
+    setGlobal(NotificationService, NotificationService());
+    setGlobal(BannerMessagesController, BannerMessagesController());
+  });
+
+  Future<void> pumpScaffold(
+    WidgetTester tester, {
+    required Screen screen,
+    bool withConnectedApp = true,
+    bool withOfflineData = false,
+  }) async {
+    if (withOfflineData) {
+      final offlineController = MockOfflineDataController();
+      offlineController.showingOfflineData.value = true;
+      setGlobal(OfflineDataController, offlineController);
+    }
+
+    MockConnectedApp? connectedApp;
+    if (withConnectedApp) {
+      connectedApp = MockConnectedApp();
+      mockConnectedApp(connectedApp);
+    }
+    when(
+      mockServiceManager.connectedAppInitialized,
+    ).thenReturn(withConnectedApp);
+    when(mockServiceManager.connectedApp).thenReturn(connectedApp);
+
+    await tester.pumpWidget(
+      wrapWithControllers(
+        DevToolsScaffold(screens: [screen]),
+        analytics: AnalyticsController(
+          enabled: false,
+          shouldShowConsentMessage: false,
+          consentMessage: 'fake message',
+        ),
+      ),
+    );
+  }
+
+  group('AI Assistant pane', () {
+    testWidgets('is visible for supported screens', (
+      WidgetTester tester,
+    ) async {
+      FeatureFlags.aiAssistant.setEnabledForTests(true);
+
+      await pumpScaffold(tester, screen: const _TestScreenWithAi());
+
+      expect(find.byType(AiAssistantPane), findsOneWidget);
+    });
+
+    testWidgets('is not visible for unsupported screens', (
+      WidgetTester tester,
+    ) async {
+      FeatureFlags.aiAssistant.setEnabledForTests(true);
+
+      await pumpScaffold(tester, screen: const _TestScreenWithoutAi());
+
+      expect(find.byType(AiAssistantPane), findsNothing);
+    });
+
+    testWidgets('is not visible when app is not connected', (
+      WidgetTester tester,
+    ) async {
+      FeatureFlags.aiAssistant.setEnabledForTests(true);
+
+      await pumpScaffold(
+        tester,
+        screen: const _TestScreenWithAi(),
+        withConnectedApp: false,
+      );
+
+      expect(find.byType(AiAssistantPane), findsNothing);
+    });
+
+    testWidgets('is not visible when feature flag is disabled', (
+      WidgetTester tester,
+    ) async {
+      FeatureFlags.aiAssistant.setEnabledForTests(false);
+
+      await pumpScaffold(tester, screen: const _TestScreenWithAi());
+
+      expect(find.byType(AiAssistantPane), findsNothing);
+    });
+
+    testWidgets('is not visible when in offline mode', (
+      WidgetTester tester,
+    ) async {
+      FeatureFlags.aiAssistant.setEnabledForTests(true);
+
+      await pumpScaffold(
+        tester,
+        screen: const _TestScreenWithAi(),
+        withOfflineData: true,
+      );
+
+      expect(find.byType(AiAssistantPane), findsNothing);
+    });
+  });
+}
+
+class _TestScreenWithAi extends Screen {
+  const _TestScreenWithAi()
+    : super('test_screen_with_ai', showFloatingDebuggerControls: false);
+
+  @override
+  bool showAiAssistant() => true;
+
+  @override
+  Widget buildScreenBody(BuildContext context) => const SizedBox();
+}
+
+class _TestScreenWithoutAi extends Screen {
+  const _TestScreenWithoutAi()
+    : super('test_screen_without_ai', showFloatingDebuggerControls: false);
+
+  @override
+  Widget buildScreenBody(BuildContext context) => const SizedBox();
+}
diff --git a/packages/devtools_app/test/screens/debugger/debugger_console_test.dart b/packages/devtools_app/test/screens/debugger/debugger_console_test.dart
index 3552e90..392bc0d 100644
--- a/packages/devtools_app/test/screens/debugger/debugger_console_test.dart
+++ b/packages/devtools_app/test/screens/debugger/debugger_console_test.dart
@@ -3,6 +3,7 @@
 // found in the LICENSE file or at https://developers.google.com/open-source/licenses/bsd.
 
 import 'package:devtools_app/devtools_app.dart';
+import 'package:devtools_app/src/framework/scaffold/bottom_pane.dart';
 import 'package:devtools_app/src/shared/console/widgets/console_pane.dart';
 import 'package:devtools_app_shared/ui.dart';
 import 'package:devtools_app_shared/utils.dart';
@@ -51,8 +52,12 @@
       wrapWithControllers(
         Row(
           children: [
-            Flexible(child: ConsolePaneHeader()),
-            const Expanded(child: ConsolePane()),
+            Expanded(
+              child: BottomPane(
+                screenId: 'debugger',
+                tabs: const [ConsolePane()],
+              ),
+            ),
           ],
         ),
         debugger: controller,
diff --git a/packages/devtools_app/test/screens/debugger/debugger_screen_test.dart b/packages/devtools_app/test/screens/debugger/debugger_screen_test.dart
index 63bc094..daa2f64 100644
--- a/packages/devtools_app/test/screens/debugger/debugger_screen_test.dart
+++ b/packages/devtools_app/test/screens/debugger/debugger_screen_test.dart
@@ -4,6 +4,7 @@
 
 import 'package:collection/collection.dart';
 import 'package:devtools_app/devtools_app.dart';
+import 'package:devtools_app/src/framework/scaffold/bottom_pane.dart';
 import 'package:devtools_app/src/screens/debugger/debugger_model.dart';
 import 'package:devtools_app/src/shared/console/widgets/console_pane.dart';
 import 'package:devtools_app_shared/ui.dart';
@@ -85,8 +86,12 @@
       wrapWithControllers(
         Row(
           children: [
-            Flexible(child: ConsolePaneHeader()),
-            const Expanded(child: ConsolePane()),
+            Expanded(
+              child: BottomPane(
+                screenId: 'debugger',
+                tabs: const [ConsolePane()],
+              ),
+            ),
           ],
         ),
         debugger: controller,
diff --git a/packages/devtools_app/test/shared/ansi_output_test.dart b/packages/devtools_app/test/shared/ansi_output_test.dart
index e0de53d..639593c 100644
--- a/packages/devtools_app/test/shared/ansi_output_test.dart
+++ b/packages/devtools_app/test/shared/ansi_output_test.dart
@@ -252,12 +252,7 @@
     ) async {
       await tester.pumpWidget(
         wrapWithControllers(
-          Row(
-            children: [
-              Flexible(child: ConsolePaneHeader()),
-              const Expanded(child: ConsolePane()),
-            ],
-          ),
+          const Row(children: [Expanded(child: ConsolePane())]),
           debugger: controller,
         ),
       );
diff --git a/packages/devtools_app/test/shared/primitives/feature_flags_test.dart b/packages/devtools_app/test/shared/primitives/feature_flags_test.dart
index 1ac9a1a..826708d 100644
--- a/packages/devtools_app/test/shared/primitives/feature_flags_test.dart
+++ b/packages/devtools_app/test/shared/primitives/feature_flags_test.dart
@@ -21,6 +21,7 @@
     expect(FeatureFlags.devToolsExtensions.isEnabled, isExternalBuild);
     expect(FeatureFlags.dapDebugging.isEnabled, false);
     expect(FeatureFlags.inspectorV2.isEnabled, true);
+    expect(FeatureFlags.aiAssistant.isEnabled, false);
   });
 
   group('FlutterChannelFeatureFlag', () {
diff --git a/packages/devtools_app_shared/lib/src/ui/split_pane.dart b/packages/devtools_app_shared/lib/src/ui/split_pane.dart
index b870cec..59e5ef5 100644
--- a/packages/devtools_app_shared/lib/src/ui/split_pane.dart
+++ b/packages/devtools_app_shared/lib/src/ui/split_pane.dart
@@ -295,7 +295,8 @@
   }
 }
 
-final class DefaultSplitter extends StatelessWidget {
+final class DefaultSplitter extends StatelessWidget
+    implements PreferredSizeWidget {
   const DefaultSplitter({super.key, required this.isHorizontal});
 
   static const iconSize = 24.0;
@@ -304,6 +305,9 @@
   final bool isHorizontal;
 
   @override
+  Size get preferredSize => const Size(splitterWidth, iconSize);
+
+  @override
   Widget build(BuildContext context) {
     return Transform.rotate(
       angle: isHorizontal ? degToRad(90.0) : degToRad(0.0),