fix(desktop): restore single-agent mode selection

This commit is contained in:
Haitao Pan 2026-04-06 17:44:34 +08:00
parent bee7ad7ca9
commit 45742bac3e
3 changed files with 20 additions and 108 deletions

View File

@ -603,10 +603,18 @@ class AppController extends ChangeNotifier {
List<AssistantExecutionTarget> visibleAssistantExecutionTargets(
Iterable<AssistantExecutionTarget> supportedTargets,
) {
return settings.visibleAssistantExecutionTargets(
final visible = settings.visibleAssistantExecutionTargets(
supportedTargets: supportedTargets,
availableSingleAgentProviders: availableSingleAgentProviders,
);
if (!supportedTargets.contains(AssistantExecutionTarget.singleAgent) ||
visible.contains(AssistantExecutionTarget.singleAgent)) {
return visible;
}
return <AssistantExecutionTarget>[
AssistantExecutionTarget.singleAgent,
...visible.where((target) => target != AssistantExecutionTarget.singleAgent),
];
}
bool get hasAnyAvailableSingleAgentProvider =>

View File

@ -26,14 +26,6 @@ import 'assistant_page_suite_core.dart';
import 'assistant_page_suite_support.dart';
void registerAssistantPageSuiteComposerTestsInternal() {
Finder executionTargetMenuItemInternal(AssistantExecutionTarget target) {
return find.byWidgetPredicate(
(widget) =>
widget is PopupMenuItem<AssistantExecutionTarget> &&
widget.value == target,
);
}
testWidgets(
'AssistantPage empty state stays above the composer instead of centering over the workspace',
(WidgetTester tester) async {
@ -164,53 +156,6 @@ void registerAssistantPageSuiteComposerTestsInternal() {
await pumpForUiSyncInternal(tester);
});
testWidgets(
'AssistantPage execution target menu shows only saved visible targets',
(WidgetTester tester) async {
late final AppController controller;
await tester.runAsync(() async {
SharedPreferences.setMockInitialValues(<String, Object>{});
final store = createIsolatedTestStore(enableSecureStorage: false);
final defaults = SettingsSnapshot.defaults();
await store.saveSettingsSnapshot(
defaults.copyWith(savedGatewayTargets: const <String>['remote']),
);
controller = AppController(
store: store,
runtimeCoordinator: RuntimeCoordinator(
gateway: FakeGatewayRuntimeInternal(store: store),
codex: FakeCodexRuntimeInternal(),
),
);
final stopwatch = Stopwatch()..start();
while (controller.initializing) {
if (stopwatch.elapsed > const Duration(seconds: 10)) {
fail('controller did not finish initializing before timeout');
}
await Future<void>.delayed(const Duration(milliseconds: 20));
}
});
addTearDown(controller.dispose);
await pumpPage(
tester,
child: AssistantPage(controller: controller, onOpenDetail: (_) {}),
);
await tester.tap(
find.byKey(const Key('assistant-execution-target-button')),
);
await pumpForUiSyncInternal(tester);
expect(find.text('远程 OpenClaw Gateway'), findsWidgets);
expect(find.text('本地 OpenClaw Gateway'), findsNothing);
expect(
executionTargetMenuItemInternal(AssistantExecutionTarget.auto),
findsNothing,
);
},
);
testWidgets(
'AssistantPage clears submitted composer text before send completes',
(WidgetTester tester) async {
@ -661,57 +606,16 @@ void registerAssistantPageSuiteComposerTestsInternal() {
});
testWidgets(
'AssistantPage hides Auto execution target even when the desktop feature flag is enabled',
'UiFeatureManifest disables desktop Auto execution target',
(WidgetTester tester) async {
final manifest = UiFeatureManifest.fallback().copyWithFeature(
platform: UiFeaturePlatform.desktop,
module: 'assistant',
feature: 'task_dialog_mode_auto',
enabled: true,
releaseTier: UiFeatureReleaseTier.stable,
);
late final AppController controller;
await tester.runAsync(() async {
SharedPreferences.setMockInitialValues(<String, Object>{});
final store = createIsolatedTestStore(enableSecureStorage: false);
final defaults = SettingsSnapshot.defaults();
await store.saveSettingsSnapshot(
defaults.copyWith(savedGatewayTargets: const <String>['remote']),
);
controller = AppController(
store: store,
runtimeCoordinator: RuntimeCoordinator(
gateway: FakeGatewayRuntimeInternal(store: store),
codex: FakeCodexRuntimeInternal(),
),
uiFeatureManifest: manifest,
);
final stopwatch = Stopwatch()..start();
while (controller.initializing) {
if (stopwatch.elapsed > const Duration(seconds: 10)) {
fail('controller did not finish initializing before timeout');
}
await Future<void>.delayed(const Duration(milliseconds: 20));
}
});
addTearDown(controller.dispose);
await pumpPage(
tester,
child: AssistantPage(controller: controller, onOpenDetail: (_) {}),
platform: TargetPlatform.macOS,
);
await tester.tap(
find.byKey(const Key('assistant-execution-target-button')),
);
await pumpForUiSyncInternal(tester);
expect(
executionTargetMenuItemInternal(AssistantExecutionTarget.auto),
findsNothing,
);
expect(find.text('远程 OpenClaw Gateway'), findsWidgets);
final manifest = UiFeatureManifest.fallback();
final availableTargets = manifest
.forPlatform(UiFeaturePlatform.desktop)
.availableExecutionTargets;
expect(availableTargets, contains(AssistantExecutionTarget.singleAgent));
expect(availableTargets, contains(AssistantExecutionTarget.local));
expect(availableTargets, contains(AssistantExecutionTarget.remote));
expect(availableTargets, isNot(contains(AssistantExecutionTarget.auto)));
},
);

View File

@ -341,7 +341,7 @@ void registerAssistantPageSuiteCoreTestsInternal() {
skip: true,
);
testWidgets('AssistantPage hides task groups when no target is saved', (
testWidgets('AssistantPage shows singleAgent task group when no target is saved', (
WidgetTester tester,
) async {
final controller = await createTestController(tester);
@ -357,7 +357,7 @@ void registerAssistantPageSuiteCoreTestsInternal() {
);
expect(
find.byKey(const ValueKey<String>('assistant-task-group-singleAgent')),
findsNothing,
findsOneWidget,
);
expect(
find.byKey(const ValueKey<String>('assistant-task-group-local')),