fix: keep manual task target selection
This commit is contained in:
parent
b739df27e4
commit
cd962b57fb
@ -196,6 +196,19 @@ extension AppControllerDesktopThreadBinding on AppController {
|
||||
);
|
||||
}
|
||||
|
||||
AssistantExecutionTarget resolveDraftThreadExecutionTargetInternal(
|
||||
String sessionKey, {
|
||||
required Iterable<AssistantExecutionTarget> supportedTargets,
|
||||
}) {
|
||||
return pickDraftThreadExecutionTargetInternal(
|
||||
currentTarget: assistantExecutionTargetForSession(sessionKey),
|
||||
visibleTargets: visibleAssistantExecutionTargets(supportedTargets),
|
||||
localWorkspaceAvailable: localThreadWorkspacePathInternal(
|
||||
sessionKey,
|
||||
).trim().isNotEmpty,
|
||||
);
|
||||
}
|
||||
|
||||
ExecutionBinding buildDesktopExecutionBindingInternal({
|
||||
required AssistantExecutionTarget executionTarget,
|
||||
required SingleAgentProvider singleAgentProvider,
|
||||
@ -276,3 +289,23 @@ extension AppControllerDesktopThreadBinding on AppController {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
AssistantExecutionTarget pickDraftThreadExecutionTargetInternal({
|
||||
required AssistantExecutionTarget currentTarget,
|
||||
required Iterable<AssistantExecutionTarget> visibleTargets,
|
||||
required bool localWorkspaceAvailable,
|
||||
}) {
|
||||
final orderedTargets = <AssistantExecutionTarget>[
|
||||
if (visibleTargets.contains(currentTarget)) currentTarget,
|
||||
...visibleTargets.where((target) => target != currentTarget),
|
||||
];
|
||||
for (final target in orderedTargets) {
|
||||
if (!localWorkspaceAvailable &&
|
||||
(target == AssistantExecutionTarget.singleAgent ||
|
||||
target == AssistantExecutionTarget.local)) {
|
||||
continue;
|
||||
}
|
||||
return target;
|
||||
}
|
||||
return currentTarget;
|
||||
}
|
||||
|
||||
@ -10,6 +10,7 @@ import '../widgets/detail_drawer.dart';
|
||||
import '../widgets/pane_resize_handle.dart';
|
||||
import '../widgets/sidebar_navigation.dart';
|
||||
import 'app_controller.dart';
|
||||
import 'app_controller_desktop_thread_binding.dart';
|
||||
import 'ui_feature_manifest.dart';
|
||||
import 'workspace_page_registry.dart';
|
||||
|
||||
@ -82,12 +83,13 @@ class _AppShellState extends State<AppShell> {
|
||||
List<AssistantExecutionTarget> visibleTargets,
|
||||
) async {
|
||||
final sessionKey = 'draft:${DateTime.now().millisecondsSinceEpoch}';
|
||||
final target =
|
||||
visibleTargets.contains(controller.currentAssistantExecutionTarget)
|
||||
? controller.currentAssistantExecutionTarget
|
||||
: (visibleTargets.isNotEmpty
|
||||
? visibleTargets.first
|
||||
: controller.currentAssistantExecutionTarget);
|
||||
final target = pickDraftThreadExecutionTargetInternal(
|
||||
currentTarget: controller.currentAssistantExecutionTarget,
|
||||
visibleTargets: visibleTargets,
|
||||
localWorkspaceAvailable: controller.settings.workspacePath
|
||||
.trim()
|
||||
.isNotEmpty,
|
||||
);
|
||||
controller.initializeAssistantThreadContext(
|
||||
sessionKey,
|
||||
title: appText('新对话', 'New conversation'),
|
||||
|
||||
@ -12,6 +12,7 @@ import 'package:markdown/markdown.dart' as md;
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
import 'package:super_clipboard/super_clipboard.dart';
|
||||
import '../../app/app_controller.dart';
|
||||
import '../../app/app_controller_desktop_thread_binding.dart';
|
||||
import '../../app/app_metadata.dart';
|
||||
import '../../app/ui_feature_manifest.dart';
|
||||
import '../../i18n/app_language.dart';
|
||||
@ -437,13 +438,17 @@ extension AssistantPageStateActionsInternal on AssistantPageStateInternal {
|
||||
|
||||
Future<void> createNewThreadInternal() async {
|
||||
final sessionKey = buildDraftSessionKeyInternal(widget.controller);
|
||||
final inheritedTarget = resolvedVisibleExecutionTargetInternal(
|
||||
widget.controller,
|
||||
supportedTargets: const <AssistantExecutionTarget>[
|
||||
AssistantExecutionTarget.singleAgent,
|
||||
AssistantExecutionTarget.local,
|
||||
AssistantExecutionTarget.remote,
|
||||
],
|
||||
final inheritedTarget = pickDraftThreadExecutionTargetInternal(
|
||||
currentTarget: widget.controller.currentAssistantExecutionTarget,
|
||||
visibleTargets: widget.controller
|
||||
.visibleAssistantExecutionTargets(const <AssistantExecutionTarget>[
|
||||
AssistantExecutionTarget.singleAgent,
|
||||
AssistantExecutionTarget.local,
|
||||
AssistantExecutionTarget.remote,
|
||||
]),
|
||||
localWorkspaceAvailable: widget.controller.settings.workspacePath
|
||||
.trim()
|
||||
.isNotEmpty,
|
||||
);
|
||||
final inheritedViewMode = widget.controller.currentAssistantMessageViewMode;
|
||||
setState(() {
|
||||
|
||||
49
test/runtime/app_controller_draft_thread_target_test.dart
Normal file
49
test/runtime/app_controller_draft_thread_target_test.dart
Normal file
@ -0,0 +1,49 @@
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:xworkmate/app/app_controller_desktop_thread_binding.dart';
|
||||
import 'package:xworkmate/runtime/runtime_models.dart';
|
||||
|
||||
void main() {
|
||||
group('pickDraftThreadExecutionTargetInternal', () {
|
||||
test('prefers the first visible manual target for new drafts', () {
|
||||
final target = pickDraftThreadExecutionTargetInternal(
|
||||
currentTarget: AssistantExecutionTarget.auto,
|
||||
visibleTargets: const <AssistantExecutionTarget>[
|
||||
AssistantExecutionTarget.singleAgent,
|
||||
AssistantExecutionTarget.local,
|
||||
AssistantExecutionTarget.remote,
|
||||
],
|
||||
localWorkspaceAvailable: true,
|
||||
);
|
||||
|
||||
expect(target, AssistantExecutionTarget.singleAgent);
|
||||
});
|
||||
|
||||
test('skips local targets when the local workspace is unavailable', () {
|
||||
final target = pickDraftThreadExecutionTargetInternal(
|
||||
currentTarget: AssistantExecutionTarget.auto,
|
||||
visibleTargets: const <AssistantExecutionTarget>[
|
||||
AssistantExecutionTarget.singleAgent,
|
||||
AssistantExecutionTarget.local,
|
||||
AssistantExecutionTarget.remote,
|
||||
],
|
||||
localWorkspaceAvailable: false,
|
||||
);
|
||||
|
||||
expect(target, AssistantExecutionTarget.remote);
|
||||
});
|
||||
|
||||
test('keeps the current visible manual target when it is usable', () {
|
||||
final target = pickDraftThreadExecutionTargetInternal(
|
||||
currentTarget: AssistantExecutionTarget.remote,
|
||||
visibleTargets: const <AssistantExecutionTarget>[
|
||||
AssistantExecutionTarget.singleAgent,
|
||||
AssistantExecutionTarget.local,
|
||||
AssistantExecutionTarget.remote,
|
||||
],
|
||||
localWorkspaceAvailable: false,
|
||||
);
|
||||
|
||||
expect(target, AssistantExecutionTarget.remote);
|
||||
});
|
||||
});
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user