Merge branch 'codex/remove-auto-mode'
This commit is contained in:
commit
fd9ddbb792
@ -588,11 +588,7 @@ class AppController extends ChangeNotifier {
|
||||
);
|
||||
|
||||
List<SingleAgentProvider> get configuredSingleAgentProviders =>
|
||||
normalizeSingleAgentProviderList(
|
||||
bridgeAdvertisedProvidersInternal.where(
|
||||
(item) => item != SingleAgentProvider.auto,
|
||||
),
|
||||
);
|
||||
normalizeSingleAgentProviderList(bridgeAdvertisedProvidersInternal);
|
||||
|
||||
List<SingleAgentProvider> get availableSingleAgentProviders =>
|
||||
availableSingleAgentProvidersOverrideInternal != null
|
||||
@ -638,11 +634,10 @@ class AppController extends ChangeNotifier {
|
||||
bool canUseSingleAgentProviderInternal(SingleAgentProvider provider) {
|
||||
final override = availableSingleAgentProvidersOverrideInternal;
|
||||
if (override != null) {
|
||||
return provider != SingleAgentProvider.auto &&
|
||||
override.contains(provider);
|
||||
return !provider.isUnspecified && override.contains(provider);
|
||||
}
|
||||
if (provider == SingleAgentProvider.auto) {
|
||||
return hasAnyAvailableSingleAgentProvider;
|
||||
if (provider.isUnspecified) {
|
||||
return false;
|
||||
}
|
||||
final capabilities = singleAgentCapabilitiesByProviderInternal[provider];
|
||||
return capabilities?.available == true &&
|
||||
@ -652,7 +647,7 @@ class AppController extends ChangeNotifier {
|
||||
SingleAgentProvider? resolvedSingleAgentProviderInternal(
|
||||
SingleAgentProvider selection,
|
||||
) {
|
||||
if (selection == SingleAgentProvider.auto) {
|
||||
if (selection.isUnspecified) {
|
||||
return null;
|
||||
}
|
||||
return canUseSingleAgentProviderInternal(selection) ? selection : null;
|
||||
|
||||
@ -235,7 +235,7 @@ extension AppControllerDesktopRuntimeHelpers on AppController {
|
||||
);
|
||||
final provider =
|
||||
resolvedSingleAgentProviderInternal(selection) ?? selection;
|
||||
final providerLabel = provider == SingleAgentProvider.auto
|
||||
final providerLabel = provider.isUnspecified
|
||||
? appText('Bridge Provider', 'Bridge Provider')
|
||||
: provider.label;
|
||||
final address = _extractGatewayAddressFromErrorInternal(raw);
|
||||
|
||||
@ -311,7 +311,7 @@ extension AppControllerDesktopSettings on AppController {
|
||||
currentSettings.assistantExecutionTarget,
|
||||
),
|
||||
messageViewMode: AssistantMessageViewMode.rendered,
|
||||
singleAgentProvider: SingleAgentProvider.auto,
|
||||
singleAgentProvider: SingleAgentProvider.unspecified,
|
||||
);
|
||||
await setCurrentAssistantSessionKeyInternal(
|
||||
'main',
|
||||
|
||||
@ -98,7 +98,7 @@ Future<void> sendSingleAgentMessageDesktopGoTaskFlowInternal(
|
||||
effectiveProvider == null)
|
||||
? (routingResolution.unavailableMessage.isNotEmpty
|
||||
? routingResolution.unavailableMessage
|
||||
: selection == SingleAgentProvider.auto
|
||||
: selection.isUnspecified
|
||||
? appText(
|
||||
'当前没有可用的 GoTaskService Provider。',
|
||||
'No GoTaskService provider is currently available.',
|
||||
@ -177,7 +177,7 @@ Future<void> sendSingleAgentMessageDesktopGoTaskFlowInternal(
|
||||
routingResolution,
|
||||
),
|
||||
routingHint: 'single-agent',
|
||||
provider: effectiveProvider ?? SingleAgentProvider.auto,
|
||||
provider: effectiveProvider ?? SingleAgentProvider.unspecified,
|
||||
remoteWorkingDirectoryHint:
|
||||
controller
|
||||
.requireTaskThreadForSessionInternal(sessionKey)
|
||||
|
||||
@ -306,7 +306,7 @@ extension AppControllerDesktopSkillPermissions on AppController {
|
||||
executionBinding?.providerId ??
|
||||
existing?.executionBinding.providerId,
|
||||
))
|
||||
: SingleAgentProvider.auto;
|
||||
: SingleAgentProvider.unspecified;
|
||||
final nextProviderSource =
|
||||
nextExecutionTarget == AssistantExecutionTarget.singleAgent
|
||||
? (singleAgentProviderSource ??
|
||||
|
||||
@ -258,7 +258,7 @@ extension AppControllerDesktopThreadBinding on AppController {
|
||||
final sanitizedProvider =
|
||||
executionTarget == AssistantExecutionTarget.singleAgent
|
||||
? settings.sanitizeSingleAgentProviderSelection(singleAgentProvider)
|
||||
: SingleAgentProvider.auto;
|
||||
: SingleAgentProvider.unspecified;
|
||||
return (existingBinding ??
|
||||
ExecutionBinding(
|
||||
executionMode: ThreadExecutionMode.localAgent,
|
||||
|
||||
@ -254,7 +254,12 @@ extension AppControllerDesktopThreadSessions on AppController {
|
||||
)?.executionBinding.providerId ??
|
||||
'',
|
||||
);
|
||||
return settings.sanitizeSingleAgentProviderSelection(stored);
|
||||
final sanitized = settings.sanitizeSingleAgentProviderSelection(stored);
|
||||
if (!sanitized.isUnspecified) {
|
||||
return sanitized;
|
||||
}
|
||||
final options = singleAgentProviderOptions;
|
||||
return options.isEmpty ? SingleAgentProvider.unspecified : options.first;
|
||||
}
|
||||
|
||||
SingleAgentProvider get currentSingleAgentProvider =>
|
||||
@ -304,7 +309,7 @@ extension AppControllerDesktopThreadSessions on AppController {
|
||||
return false;
|
||||
}
|
||||
final selection = singleAgentProviderForSession(normalizedSessionKey);
|
||||
if (selection == SingleAgentProvider.auto) {
|
||||
if (selection.isUnspecified) {
|
||||
return false;
|
||||
}
|
||||
return !canUseSingleAgentProviderInternal(selection) &&
|
||||
@ -385,7 +390,7 @@ extension AppControllerDesktopThreadSessions on AppController {
|
||||
return resolvedProvider.label;
|
||||
}
|
||||
final provider = currentSingleAgentProvider;
|
||||
if (provider != SingleAgentProvider.auto) {
|
||||
if (!provider.isUnspecified) {
|
||||
return provider.label;
|
||||
}
|
||||
return appText('单机智能体', 'Single Agent');
|
||||
|
||||
@ -693,7 +693,7 @@ extension AppControllerDesktopThreadStorage on AppController {
|
||||
record.executionBinding.providerId,
|
||||
),
|
||||
)
|
||||
: SingleAgentProvider.auto;
|
||||
: SingleAgentProvider.unspecified;
|
||||
final workspaceBinding = record.workspaceBinding.copyWith(
|
||||
workspaceId: sessionKey,
|
||||
displayPath: record.workspaceKind == WorkspaceKind.localFs
|
||||
|
||||
@ -361,7 +361,7 @@ extension AppControllerDesktopWorkspaceExecution on AppController {
|
||||
singleAgentProvider:
|
||||
singleAgentProvider ??
|
||||
singleAgentProviderForSession(currentSessionKey),
|
||||
singleAgentProviderSource: ThreadSelectionSource.explicit,
|
||||
singleAgentProviderSource: ThreadSelectionSource.inherited,
|
||||
updatedAtMs: DateTime.now().millisecondsSinceEpoch.toDouble(),
|
||||
);
|
||||
// Re-read the current thread target when the async binding sync runs so a
|
||||
|
||||
@ -219,24 +219,19 @@ class SingleAgentProviderBadgeInternal extends StatelessWidget {
|
||||
final candidate = provider.badge.trim().isEmpty
|
||||
? provider.label
|
||||
: provider.badge;
|
||||
final display = candidate.length <= 2
|
||||
final display = candidate.trim().isEmpty
|
||||
? '?'
|
||||
: candidate.length <= 2
|
||||
? candidate
|
||||
: candidate.substring(0, 2);
|
||||
final isAuto = provider == SingleAgentProvider.auto;
|
||||
return Container(
|
||||
width: 18,
|
||||
height: 18,
|
||||
alignment: Alignment.center,
|
||||
decoration: BoxDecoration(
|
||||
color: isAuto
|
||||
? palette.accent.withValues(alpha: 0.16)
|
||||
: palette.surfaceSecondary,
|
||||
color: palette.surfaceSecondary,
|
||||
borderRadius: BorderRadius.circular(999),
|
||||
border: Border.all(
|
||||
color: isAuto
|
||||
? palette.accent.withValues(alpha: 0.4)
|
||||
: palette.strokeSoft,
|
||||
),
|
||||
border: Border.all(color: palette.strokeSoft),
|
||||
),
|
||||
child: Text(
|
||||
display,
|
||||
|
||||
@ -43,11 +43,12 @@ String executionTargetTooltipInternal(AssistantExecutionTarget target) =>
|
||||
'Task dialog mode: ${target.compactLabel}',
|
||||
);
|
||||
|
||||
String singleAgentProviderTooltipInternal(SingleAgentProvider provider) =>
|
||||
appText(
|
||||
'Bridge Provider: ${provider.label}',
|
||||
'Bridge Provider: ${provider.label}',
|
||||
);
|
||||
String singleAgentProviderTooltipInternal(
|
||||
SingleAgentProvider provider,
|
||||
) => appText(
|
||||
'Bridge Provider: ${provider.label.trim().isEmpty ? appText('未配置', 'Unconfigured') : provider.label}',
|
||||
'Bridge Provider: ${provider.label.trim().isEmpty ? appText('未配置', 'Unconfigured') : provider.label}',
|
||||
);
|
||||
|
||||
String modelTooltipInternal(String modelLabel) =>
|
||||
appText('模型: $modelLabel', 'Model: $modelLabel');
|
||||
|
||||
@ -201,7 +201,7 @@ class ExternalCodeAgentAcpDesktopTransport
|
||||
providerId,
|
||||
label: label?.isNotEmpty == true ? label : null,
|
||||
);
|
||||
if (provider != SingleAgentProvider.auto) {
|
||||
if (!provider.isUnspecified) {
|
||||
providers.add(provider);
|
||||
}
|
||||
}
|
||||
|
||||
@ -158,7 +158,7 @@ class GatewayAcpClient {
|
||||
providerId,
|
||||
label: label?.isNotEmpty == true ? label : null,
|
||||
);
|
||||
if (provider != SingleAgentProvider.auto) {
|
||||
if (!provider.isUnspecified) {
|
||||
providers.add(provider);
|
||||
}
|
||||
}
|
||||
|
||||
@ -219,7 +219,7 @@ class GoTaskServiceRequest {
|
||||
required this.metadata,
|
||||
this.routing,
|
||||
this.routingHint = '',
|
||||
this.provider = SingleAgentProvider.auto,
|
||||
this.provider = SingleAgentProvider.unspecified,
|
||||
this.remoteWorkingDirectoryHint = '',
|
||||
this.resumeSession = false,
|
||||
this.collaborationMode = GoTaskServiceCollaborationMode.standard,
|
||||
@ -322,7 +322,7 @@ class GoTaskServiceRequest {
|
||||
},
|
||||
)
|
||||
.toList(growable: false),
|
||||
if (provider != SingleAgentProvider.auto) 'provider': provider.providerId,
|
||||
if (!provider.isUnspecified) 'provider': provider.providerId,
|
||||
if (remoteWorkingDirectoryHint.trim().isNotEmpty)
|
||||
'remoteWorkingDirectoryHint': remoteWorkingDirectoryHint.trim(),
|
||||
if (model.trim().isNotEmpty) 'model': model.trim(),
|
||||
@ -353,7 +353,7 @@ class GoTaskServiceRequest {
|
||||
AssistantExecutionTarget.remote => 'remote',
|
||||
AssistantExecutionTarget.singleAgent => 'singleAgent',
|
||||
};
|
||||
final explicitProviderId = provider == SingleAgentProvider.auto
|
||||
final explicitProviderId = provider.isUnspecified
|
||||
? ''
|
||||
: provider.providerId;
|
||||
final explicitModelValue = model.trim();
|
||||
|
||||
@ -167,7 +167,7 @@ String normalizeSingleAgentProviderId(String value) {
|
||||
String singleAgentProviderFallbackLabelInternal(String providerId) {
|
||||
final normalized = normalizeSingleAgentProviderId(providerId);
|
||||
if (normalized.isEmpty) {
|
||||
return 'Custom Agent';
|
||||
return appText('Bridge Provider', 'Bridge Provider');
|
||||
}
|
||||
return normalized
|
||||
.split(RegExp(r'[-_.]+'))
|
||||
@ -182,7 +182,6 @@ String singleAgentProviderFallbackBadgeInternal({
|
||||
}) {
|
||||
final normalized = normalizeSingleAgentProviderId(providerId);
|
||||
final known = <String, String>{
|
||||
'auto': 'A',
|
||||
'codex': 'C',
|
||||
'opencode': 'O',
|
||||
'claude': 'Cl',
|
||||
@ -225,10 +224,10 @@ class SingleAgentProvider {
|
||||
this.source = SingleAgentProviderSource.externalExtension,
|
||||
});
|
||||
|
||||
static const SingleAgentProvider auto = SingleAgentProvider(
|
||||
providerId: 'auto',
|
||||
label: 'Auto',
|
||||
badge: 'A',
|
||||
static const SingleAgentProvider unspecified = SingleAgentProvider(
|
||||
providerId: '',
|
||||
label: '',
|
||||
badge: '',
|
||||
);
|
||||
|
||||
static const SingleAgentProvider codex = SingleAgentProvider(
|
||||
@ -260,7 +259,7 @@ class SingleAgentProvider {
|
||||
final String badge;
|
||||
final SingleAgentProviderSource source;
|
||||
|
||||
bool get isAuto => providerId == auto.providerId;
|
||||
bool get isUnspecified => providerId.trim().isEmpty;
|
||||
bool get isExternalExtension =>
|
||||
source == SingleAgentProviderSource.externalExtension;
|
||||
|
||||
@ -301,7 +300,7 @@ class SingleAgentProvider {
|
||||
'opencode' => opencode,
|
||||
'claude' => claude,
|
||||
'gemini' => gemini,
|
||||
'auto' || '' => auto,
|
||||
'auto' || '' => unspecified,
|
||||
_ => SingleAgentProvider(
|
||||
providerId: normalized,
|
||||
label: singleAgentProviderFallbackLabelInternal(normalized),
|
||||
|
||||
@ -100,7 +100,7 @@ class ExternalAcpEndpointProfile {
|
||||
json['providerKey']?.toString() ?? '',
|
||||
);
|
||||
final builtin = SingleAgentProviderCopy.fromJsonValue(providerKey);
|
||||
final fallbackLabel = builtin.isAuto ? providerKey : builtin.label;
|
||||
final fallbackLabel = builtin.isUnspecified ? providerKey : builtin.label;
|
||||
final label = json['label']?.toString().trim().isNotEmpty == true
|
||||
? json['label'].toString().trim()
|
||||
: fallbackLabel;
|
||||
@ -132,9 +132,6 @@ List<ExternalAcpEndpointProfile> normalizeExternalAcpEndpoints({
|
||||
) {
|
||||
final key = profile.providerKey.trim().toLowerCase();
|
||||
for (final provider in kKnownSingleAgentProviders) {
|
||||
if (provider.isAuto) {
|
||||
continue;
|
||||
}
|
||||
if (provider.providerId == key) {
|
||||
return provider;
|
||||
}
|
||||
@ -142,9 +139,6 @@ List<ExternalAcpEndpointProfile> normalizeExternalAcpEndpoints({
|
||||
final label = profile.label.trim();
|
||||
final badge = profile.badge.trim();
|
||||
for (final provider in kKnownSingleAgentProviders) {
|
||||
if (provider.isAuto) {
|
||||
continue;
|
||||
}
|
||||
if (provider.label == label && provider.badge == badge) {
|
||||
return provider;
|
||||
}
|
||||
|
||||
@ -1019,8 +1019,8 @@ class TaskThread {
|
||||
executionBinding ??
|
||||
ExecutionBinding(
|
||||
executionMode: ThreadExecutionMode.localAgent,
|
||||
executorId: SingleAgentProvider.auto.providerId,
|
||||
providerId: SingleAgentProvider.auto.providerId,
|
||||
executorId: SingleAgentProvider.unspecified.providerId,
|
||||
providerId: SingleAgentProvider.unspecified.providerId,
|
||||
endpointId: '',
|
||||
),
|
||||
contextState =
|
||||
|
||||
@ -447,8 +447,8 @@ class SettingsSnapshot {
|
||||
}
|
||||
|
||||
SingleAgentProvider resolveSingleAgentProvider(SingleAgentProvider provider) {
|
||||
if (provider.isAuto) {
|
||||
return SingleAgentProvider.auto;
|
||||
if (provider.isUnspecified) {
|
||||
return SingleAgentProvider.unspecified;
|
||||
}
|
||||
final profile = providerSyncDefinitionForProviderId(provider.providerId);
|
||||
if (profile != null) {
|
||||
@ -459,8 +459,8 @@ class SettingsSnapshot {
|
||||
|
||||
SingleAgentProvider singleAgentProviderForId(String providerId) {
|
||||
final resolved = normalizeSingleAgentProviderId(providerId);
|
||||
if (resolved.isEmpty || resolved == SingleAgentProvider.auto.providerId) {
|
||||
return SingleAgentProvider.auto;
|
||||
if (resolved.isEmpty || resolved == 'auto') {
|
||||
return SingleAgentProvider.unspecified;
|
||||
}
|
||||
final normalizedSelection = SingleAgentProvider.fromJsonValue(resolved);
|
||||
final profile = providerSyncDefinitionForProviderId(
|
||||
@ -476,8 +476,8 @@ class SettingsSnapshot {
|
||||
SingleAgentProvider provider,
|
||||
) {
|
||||
final resolved = resolveSingleAgentProvider(provider);
|
||||
if (resolved.isAuto) {
|
||||
return SingleAgentProvider.auto;
|
||||
if (resolved.isUnspecified) {
|
||||
return SingleAgentProvider.unspecified;
|
||||
}
|
||||
if (kKnownSingleAgentProviders.any(
|
||||
(item) => item.providerId == resolved.providerId,
|
||||
|
||||
@ -175,6 +175,63 @@ void main() {
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
test(
|
||||
'single-agent threads default to bridge catalog providers without reviving auto mode',
|
||||
() async {
|
||||
final root = Directory.systemTemp.createTempSync(
|
||||
'xworkmate-provider-selection-test-',
|
||||
);
|
||||
final store = SecureConfigStore(
|
||||
enableSecureStorage: false,
|
||||
appDataRootPathResolver: () async => root.path,
|
||||
secretRootPathResolver: () async => root.path,
|
||||
supportRootPathResolver: () async => root.path,
|
||||
);
|
||||
final controller = AppController(
|
||||
store: store,
|
||||
desktopPlatformService: UnsupportedDesktopPlatformService(),
|
||||
skillDirectoryAccessService: _FakeSkillDirectoryAccessService(
|
||||
root.path,
|
||||
),
|
||||
goTaskServiceClient: const _FakeGoTaskServiceClient(),
|
||||
singleAgentSharedSkillScanRootOverrides: const <String>[],
|
||||
availableSingleAgentProvidersOverride: const <SingleAgentProvider>[
|
||||
SingleAgentProvider.codex,
|
||||
],
|
||||
);
|
||||
addTearDown(() async {
|
||||
controller.dispose();
|
||||
if (root.existsSync()) {
|
||||
await root.delete(recursive: true);
|
||||
}
|
||||
});
|
||||
|
||||
expect(
|
||||
controller.singleAgentProviderForSession('draft:bridge-default'),
|
||||
SingleAgentProvider.codex,
|
||||
);
|
||||
|
||||
controller.initializeAssistantThreadContext(
|
||||
'draft:bridge-default',
|
||||
executionTarget: AssistantExecutionTarget.singleAgent,
|
||||
);
|
||||
|
||||
final thread = controller.taskThreadForSessionInternal(
|
||||
'draft:bridge-default',
|
||||
);
|
||||
expect(thread, isNotNull);
|
||||
expect(
|
||||
thread!.executionBinding.providerId,
|
||||
SingleAgentProvider.codex.providerId,
|
||||
);
|
||||
expect(
|
||||
thread.executionBinding.providerSource,
|
||||
ThreadSelectionSource.inherited,
|
||||
);
|
||||
expect(thread.hasExplicitProviderSelection, isFalse);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
class _FakeSkillDirectoryAccessService implements SkillDirectoryAccessService {
|
||||
|
||||
@ -102,7 +102,7 @@ void main() {
|
||||
);
|
||||
|
||||
expect(snapshot.executionTarget, AssistantExecutionTarget.remote);
|
||||
expect(snapshot.singleAgentProvider, SingleAgentProvider.auto);
|
||||
expect(snapshot.singleAgentProvider.isUnspecified, isTrue);
|
||||
expect(snapshot.record, isNull);
|
||||
expect(staleRecord.executionBinding.providerId, isNotEmpty);
|
||||
});
|
||||
|
||||
@ -14,7 +14,7 @@ void main() {
|
||||
TaskThread buildThread({
|
||||
required String threadId,
|
||||
required ThreadExecutionMode mode,
|
||||
String providerId = 'auto',
|
||||
String providerId = '',
|
||||
}) {
|
||||
return TaskThread(
|
||||
threadId: threadId,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user