Merge branch 'codex/fix-thread-target-gateway-check' into codex/merge-temp-all

This commit is contained in:
Haitao Pan 2026-04-11 12:02:53 +08:00
commit d907c355b1
6 changed files with 52 additions and 1 deletions

View File

@ -1,5 +1,7 @@
import 'dart:async';
import 'package:flutter/foundation.dart';
import 'gateway_acp_client.dart';
import 'go_acp_stdio_bridge.dart';
import 'go_task_service_client.dart';
@ -14,6 +16,9 @@ class ExternalCodeAgentAcpDesktopTransport
List<ExternalCodeAgentAcpSyncedProvider> _syncedProviders =
const <ExternalCodeAgentAcpSyncedProvider>[];
@visibleForTesting
GoAcpStdioBridge get bridgeForTest => _bridge;
@override
Future<void> syncExternalProviders(
List<ExternalCodeAgentAcpSyncedProvider> providers,

View File

@ -103,6 +103,9 @@ class GatewayRuntime extends ChangeNotifier with GatewayRuntimeHelpersInternal {
@visibleForTesting
bool get usesSessionClient => sessionClientInternal != null;
@visibleForTesting
GatewayRuntimeSessionClient? get sessionClientForTest => sessionClientInternal;
Future<void> initialize() async {
sessionUpdatesInternal ??= sessionClientInternal?.updates.listen(
_handleSessionUpdateInternal,

View File

@ -41,6 +41,7 @@ class GoAcpStdioBridge {
StreamSubscription<String>? _stdoutSubscription;
StreamSubscription<String>? _stderrSubscription;
Future<void>? _startupFuture;
Future<void>? _disposeFuture;
int _requestCounter = 0;
Stream<Map<String, dynamic>> get notifications =>
@ -84,6 +85,16 @@ class GoAcpStdioBridge {
}
Future<void> dispose() async {
final inFlight = _disposeFuture;
if (inFlight != null) {
return inFlight;
}
final next = _disposeInternal();
_disposeFuture = next;
return next;
}
Future<void> _disposeInternal() async {
final process = _process;
_process = null;
_startupFuture = null;
@ -111,7 +122,9 @@ class GoAcpStdioBridge {
// Best effort only.
}
}
await _notificationsController.close();
if (!_notificationsController.isClosed) {
await _notificationsController.close();
}
}
Future<void> _ensureStarted() async {

View File

@ -1,5 +1,7 @@
import 'dart:async';
import 'package:flutter/foundation.dart';
import 'gateway_runtime_errors.dart';
import 'gateway_runtime_session_client.dart';
import 'go_acp_stdio_bridge.dart';
@ -20,6 +22,9 @@ class GoGatewayRuntimeDesktopClient implements GatewayRuntimeSessionClient {
final StreamController<GatewayRuntimeSessionUpdate> _updatesController =
StreamController<GatewayRuntimeSessionUpdate>.broadcast();
@visibleForTesting
GoAcpStdioBridge get bridgeForTest => _bridge;
@override
Stream<GatewayRuntimeSessionUpdate> get updates => _updatesController.stream;

View File

@ -1,6 +1,7 @@
import 'gateway_runtime.dart';
import 'go_task_service_client.dart';
import 'runtime_models.dart';
import 'package:flutter/foundation.dart';
class DesktopGoTaskService implements GoTaskServiceClient {
DesktopGoTaskService({
@ -69,6 +70,9 @@ class DesktopGoTaskService implements GoTaskServiceClient {
threadId: threadId,
);
@visibleForTesting
ExternalCodeAgentAcpTransport get acpTransportForTest => _acpTransport;
@override
Future<void> dispose() async {
await _acpTransport.dispose();

View File

@ -1,5 +1,8 @@
import 'package:flutter_test/flutter_test.dart';
import 'package:xworkmate/app/app_controller_desktop_core.dart';
import 'package:xworkmate/runtime/external_code_agent_acp_desktop_transport.dart';
import 'package:xworkmate/runtime/go_gateway_runtime_desktop_client.dart';
import 'package:xworkmate/runtime/go_task_service_desktop_service.dart';
void main() {
TestWidgetsFlutterBinding.ensureInitialized();
@ -10,4 +13,22 @@ void main() {
expect(controller.runtime.usesSessionClient, isTrue);
});
test(
'default desktop controller shares one ACP bridge between gateway runtime and task transport',
() {
final controller = AppController();
addTearDown(controller.dispose);
final sessionClient =
controller.runtime.sessionClientForTest
as GoGatewayRuntimeDesktopClient;
final taskService =
controller.goTaskServiceClientForTest as DesktopGoTaskService;
final transport =
taskService.acpTransportForTest as ExternalCodeAgentAcpDesktopTransport;
expect(sessionClient.bridgeForTest, same(transport.bridgeForTest));
},
);
}