refactor: remove stale thread target fallback
This commit is contained in:
parent
5aed098e6c
commit
8d70cfedea
@ -835,28 +835,15 @@ extension AppControllerDesktopSettingsRuntime on AppController {
|
||||
final sessionKey = normalizedAssistantSessionKeyInternal(
|
||||
sessionsControllerInternal.currentSessionKey,
|
||||
);
|
||||
final thread = taskThreadForSessionInternal(sessionKey);
|
||||
final target = thread?.hasExplicitExecutionTargetSelection ?? false
|
||||
? assistantExecutionTargetForSession(sessionKey)
|
||||
: sanitizePersistedExecutionTargetInternal(
|
||||
snapshot.assistantExecutionTarget,
|
||||
);
|
||||
if (thread?.hasExplicitExecutionTargetSelection ?? false) {
|
||||
upsertTaskThreadInternal(
|
||||
sessionKey,
|
||||
gatewayEntryState: gatewayEntryStateForTargetInternal(target),
|
||||
latestResolvedRuntimeModel: '',
|
||||
updatedAtMs: DateTime.now().millisecondsSinceEpoch.toDouble(),
|
||||
);
|
||||
} else {
|
||||
upsertTaskThreadInternal(
|
||||
sessionKey,
|
||||
executionTarget: target,
|
||||
gatewayEntryState: gatewayEntryStateForTargetInternal(target),
|
||||
latestResolvedRuntimeModel: '',
|
||||
updatedAtMs: DateTime.now().millisecondsSinceEpoch.toDouble(),
|
||||
);
|
||||
}
|
||||
final target = assistantExecutionTargetForSession(sessionKey);
|
||||
upsertTaskThreadInternal(
|
||||
sessionKey,
|
||||
executionTarget: target,
|
||||
executionTargetSource: ThreadSelectionSource.explicit,
|
||||
gatewayEntryState: gatewayEntryStateForTargetInternal(target),
|
||||
latestResolvedRuntimeModel: '',
|
||||
updatedAtMs: DateTime.now().millisecondsSinceEpoch.toDouble(),
|
||||
);
|
||||
recomputeTasksInternal();
|
||||
notifyIfActiveInternal();
|
||||
await applyAssistantExecutionTargetInternal(
|
||||
|
||||
@ -292,7 +292,7 @@ extension AppControllerDesktopSkillPermissions on AppController {
|
||||
AssistantExecutionTarget.singleAgent,
|
||||
ThreadExecutionMode.gatewayLocal => AssistantExecutionTarget.local,
|
||||
ThreadExecutionMode.gatewayRemote => AssistantExecutionTarget.remote,
|
||||
null => settings.assistantExecutionTarget,
|
||||
null => AssistantExecutionTarget.singleAgent,
|
||||
};
|
||||
final nextImportedSkills =
|
||||
importedSkills ??
|
||||
|
||||
@ -48,6 +48,16 @@ import 'app_controller_desktop_thread_sessions_collaboration_impl.dart';
|
||||
|
||||
// ignore_for_file: invalid_use_of_visible_for_testing_member, invalid_use_of_protected_member
|
||||
extension AppControllerDesktopThreadSessions on AppController {
|
||||
AssistantExecutionTarget resolveAssistantExecutionTargetFromRecordsInternal(
|
||||
TaskThread? primaryRecord, {
|
||||
TaskThread? fallbackRecord,
|
||||
}) {
|
||||
return resolveAssistantExecutionTargetFromRecordsForTest(
|
||||
primaryRecord,
|
||||
fallbackRecord: fallbackRecord,
|
||||
);
|
||||
}
|
||||
|
||||
TaskThread? taskThreadForSessionInternal(String sessionKey) {
|
||||
final normalizedSessionKey = normalizedAssistantSessionKeyInternal(
|
||||
sessionKey,
|
||||
@ -544,12 +554,12 @@ extension AppControllerDesktopThreadSessions on AppController {
|
||||
sessionKey,
|
||||
);
|
||||
final record = taskThreadForSessionInternal(normalizedSessionKey);
|
||||
return sanitizePersistedExecutionTargetInternal(
|
||||
record == null
|
||||
? settings.assistantExecutionTarget
|
||||
: assistantExecutionTargetFromExecutionMode(
|
||||
record.executionBinding.executionMode,
|
||||
),
|
||||
final mainRecord = matchesSessionKey(normalizedSessionKey, 'main')
|
||||
? null
|
||||
: taskThreadForSessionInternal('main');
|
||||
return resolveAssistantExecutionTargetFromRecordsInternal(
|
||||
record,
|
||||
fallbackRecord: mainRecord,
|
||||
);
|
||||
}
|
||||
|
||||
@ -621,3 +631,15 @@ extension AppControllerDesktopThreadSessions on AppController {
|
||||
return items;
|
||||
}
|
||||
}
|
||||
|
||||
AssistantExecutionTarget resolveAssistantExecutionTargetFromRecordsForTest(
|
||||
TaskThread? primaryRecord, {
|
||||
TaskThread? fallbackRecord,
|
||||
}) {
|
||||
final record = primaryRecord ?? fallbackRecord;
|
||||
return record == null
|
||||
? AssistantExecutionTarget.singleAgent
|
||||
: assistantExecutionTargetFromExecutionMode(
|
||||
record.executionBinding.executionMode,
|
||||
);
|
||||
}
|
||||
|
||||
@ -323,15 +323,8 @@ List<String> assistantModelChoicesForSessionThreadSessionInternal(
|
||||
final normalizedSessionKey = normalizeAssistantSessionKeyThreadInternal(
|
||||
sessionKey,
|
||||
);
|
||||
final target = controller.sanitizePersistedExecutionTargetInternal(
|
||||
controller.taskThreadForSessionInternal(normalizedSessionKey) == null
|
||||
? controller.settings.assistantExecutionTarget
|
||||
: assistantExecutionTargetFromExecutionMode(
|
||||
controller
|
||||
.requireTaskThreadForSessionInternal(normalizedSessionKey)
|
||||
.executionBinding
|
||||
.executionMode,
|
||||
),
|
||||
final target = controller.assistantExecutionTargetForSession(
|
||||
normalizedSessionKey,
|
||||
);
|
||||
if (target == AssistantExecutionTarget.singleAgent) {
|
||||
final singleAgentUsesAiGatewayFallback =
|
||||
|
||||
@ -358,6 +358,7 @@ extension AppControllerDesktopWorkspaceExecution on AppController {
|
||||
title: title.trim(),
|
||||
ownerScope: initialOwnerScope,
|
||||
executionTarget: resolvedTarget,
|
||||
executionTargetSource: ThreadSelectionSource.explicit,
|
||||
workspaceBinding: initialWorkspaceBinding,
|
||||
messageViewMode:
|
||||
messageViewMode ??
|
||||
@ -365,6 +366,7 @@ extension AppControllerDesktopWorkspaceExecution on AppController {
|
||||
singleAgentProvider:
|
||||
singleAgentProvider ??
|
||||
singleAgentProviderForSession(currentSessionKey),
|
||||
singleAgentProviderSource: ThreadSelectionSource.explicit,
|
||||
updatedAtMs: DateTime.now().millisecondsSinceEpoch.toDouble(),
|
||||
);
|
||||
// Re-read the current thread target when the async binding sync runs so a
|
||||
@ -405,7 +407,9 @@ extension AppControllerDesktopWorkspaceExecution on AppController {
|
||||
return;
|
||||
}
|
||||
final authorizationOverride =
|
||||
await resolveSingleAgentAuthorizationHeaderForProviderInternal(provider);
|
||||
await resolveSingleAgentAuthorizationHeaderForProviderInternal(
|
||||
provider,
|
||||
);
|
||||
await replaceSingleAgentThreadSkillsInternal(
|
||||
normalizedSessionKey,
|
||||
localSkills,
|
||||
|
||||
94
test/app_controller_desktop_thread_target_cleanup_test.dart
Normal file
94
test/app_controller_desktop_thread_target_cleanup_test.dart
Normal file
@ -0,0 +1,94 @@
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:xworkmate/app/app_controller_desktop_thread_sessions.dart';
|
||||
import 'package:xworkmate/runtime/runtime_models.dart';
|
||||
|
||||
void main() {
|
||||
group('resolveAssistantExecutionTargetFromRecordsInternal', () {
|
||||
const owner = ThreadOwnerScope(
|
||||
realm: ThreadRealm.local,
|
||||
subjectType: ThreadSubjectType.user,
|
||||
subjectId: 'u1',
|
||||
displayName: 'User',
|
||||
);
|
||||
|
||||
TaskThread buildThread({
|
||||
required String threadId,
|
||||
required ThreadExecutionMode mode,
|
||||
String providerId = 'auto',
|
||||
}) {
|
||||
return TaskThread(
|
||||
threadId: threadId,
|
||||
ownerScope: owner,
|
||||
workspaceBinding: const WorkspaceBinding(
|
||||
workspaceId: 'ws-1',
|
||||
workspaceKind: WorkspaceKind.localFs,
|
||||
workspacePath: '/tmp/ws',
|
||||
displayPath: '/tmp/ws',
|
||||
writable: true,
|
||||
),
|
||||
executionBinding: ExecutionBinding(
|
||||
executionMode: mode,
|
||||
executorId: providerId,
|
||||
providerId: providerId,
|
||||
endpointId: '',
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
test('defaults to single-agent when no thread record exists', () {
|
||||
final resolved = _ThreadSessionTargetResolverHarness().resolveTarget(
|
||||
primary: null,
|
||||
);
|
||||
|
||||
expect(resolved, AssistantExecutionTarget.singleAgent);
|
||||
});
|
||||
|
||||
test('prefers the current thread record over the main thread fallback', () {
|
||||
final primary = buildThread(
|
||||
threadId: 'draft:1',
|
||||
mode: ThreadExecutionMode.gatewayRemote,
|
||||
);
|
||||
final fallback = buildThread(
|
||||
threadId: 'main',
|
||||
mode: ThreadExecutionMode.gatewayLocal,
|
||||
);
|
||||
|
||||
final resolved = _ThreadSessionTargetResolverHarness().resolveTarget(
|
||||
primary: primary,
|
||||
fallback: fallback,
|
||||
);
|
||||
|
||||
expect(resolved, AssistantExecutionTarget.remote);
|
||||
});
|
||||
|
||||
test(
|
||||
'uses main thread record instead of settings when current is missing',
|
||||
() {
|
||||
final fallback = buildThread(
|
||||
threadId: 'main',
|
||||
mode: ThreadExecutionMode.localAgent,
|
||||
providerId: SingleAgentProvider.opencode.providerId,
|
||||
);
|
||||
|
||||
final resolved = _ThreadSessionTargetResolverHarness().resolveTarget(
|
||||
primary: null,
|
||||
fallback: fallback,
|
||||
);
|
||||
|
||||
expect(resolved, AssistantExecutionTarget.singleAgent);
|
||||
},
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
class _ThreadSessionTargetResolverHarness {
|
||||
AssistantExecutionTarget resolveTarget({
|
||||
required TaskThread? primary,
|
||||
TaskThread? fallback,
|
||||
}) {
|
||||
return resolveAssistantExecutionTargetFromRecordsForTest(
|
||||
primary,
|
||||
fallbackRecord: fallback,
|
||||
);
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user