diff --git a/lib/app/app_controller_desktop_runtime_coordination_impl.dart b/lib/app/app_controller_desktop_runtime_coordination_impl.dart index c4c50d6b..3e1edd3a 100644 --- a/lib/app/app_controller_desktop_runtime_coordination_impl.dart +++ b/lib/app/app_controller_desktop_runtime_coordination_impl.dart @@ -162,6 +162,15 @@ String? assistantWorkingDirectoryForSessionRuntimeInternal( final normalizedSessionKey = controller.normalizedAssistantSessionKeyInternal( sessionKey, ); + final remoteCandidate = + controller + .assistantThreadRecordsInternal[normalizedSessionKey] + ?.lastRemoteWorkingDirectory + ?.trim() ?? + ''; + if (remoteCandidate.isNotEmpty) { + return remoteCandidate; + } final candidate = controller .assistantThreadRecordsInternal[normalizedSessionKey] @@ -186,11 +195,8 @@ String? resolveLocalAssistantWorkingDirectoryForSessionRuntimeInternal( if (record?.workspaceKind != WorkspaceKind.localFs) { return null; } - final candidate = assistantWorkingDirectoryForSessionRuntimeInternal( - controller, - sessionKey, - ); - if (candidate == null) { + final candidate = record?.workspaceBinding.workspacePath.trim() ?? ''; + if (candidate.isEmpty) { return null; } final directory = Directory(candidate); diff --git a/lib/app/app_controller_desktop_thread_binding.dart b/lib/app/app_controller_desktop_thread_binding.dart index bb678e8b..c359a668 100644 --- a/lib/app/app_controller_desktop_thread_binding.dart +++ b/lib/app/app_controller_desktop_thread_binding.dart @@ -189,15 +189,12 @@ extension AppControllerDesktopThreadBinding on AppController { required ThreadOwnerScope ownerScope, WorkspaceBinding? existingBinding, }) { - final remotePath = remoteThreadWorkspacePathInternal( - sessionKey, - ownerScope, - ); + final localPath = localThreadWorkspacePathInternal(sessionKey); return WorkspaceBinding( workspaceId: normalizedAssistantSessionKeyInternal(sessionKey), - workspaceKind: WorkspaceKind.remoteFs, - workspacePath: remotePath, - displayPath: remotePath, + workspaceKind: WorkspaceKind.localFs, + workspacePath: localPath, + displayPath: localPath, writable: existingBinding?.writable ?? true, ); } @@ -280,6 +277,11 @@ extension AppControllerDesktopThreadBinding on AppController { normalizedSessionKey, ownerScope: ownerScope, workspaceBinding: workspaceBinding, + lastRemoteWorkingDirectory: remoteThreadWorkspacePathInternal( + normalizedSessionKey, + ownerScope, + ), + lastRemoteWorkspaceRefKind: WorkspaceRefKind.remotePath, executionBinding: buildDesktopExecutionBindingInternal( executionTarget: snapshot.executionTarget, existingBinding: snapshot.record?.executionBinding, diff --git a/test/runtime/app_controller_thread_workspace_binding_test.dart b/test/runtime/app_controller_thread_workspace_binding_test.dart new file mode 100644 index 00000000..82d0f355 --- /dev/null +++ b/test/runtime/app_controller_thread_workspace_binding_test.dart @@ -0,0 +1,55 @@ +import 'dart:io'; + +import 'package:flutter_test/flutter_test.dart'; +import 'package:xworkmate/app/app_controller.dart'; +import 'package:xworkmate/app/app_controller_desktop_runtime_coordination_impl.dart'; +import 'package:xworkmate/runtime/runtime_models.dart'; + +void main() { + test( + 'keeps local workspace binding separate from remote execution workspace', + () { + final controller = AppController(); + addTearDown(controller.dispose); + + final localWorkspace = Directory.systemTemp.createTempSync( + 'xworkmate-local-workspace-', + ); + final remoteWorkspace = Directory.systemTemp.createTempSync( + 'xworkmate-remote-workspace-', + ); + addTearDown(() { + localWorkspace.deleteSync(recursive: true); + remoteWorkspace.deleteSync(recursive: true); + }); + + controller.upsertTaskThreadInternal( + 'session-1', + workspaceBinding: WorkspaceBinding( + workspaceId: 'session-1', + workspaceKind: WorkspaceKind.localFs, + workspacePath: localWorkspace.path, + displayPath: localWorkspace.path, + writable: true, + ), + lastRemoteWorkingDirectory: remoteWorkspace.path, + lastRemoteWorkspaceRefKind: WorkspaceRefKind.remotePath, + ); + + expect( + assistantWorkingDirectoryForSessionRuntimeInternal( + controller, + 'session-1', + ), + remoteWorkspace.path, + ); + expect( + resolveLocalAssistantWorkingDirectoryForSessionRuntimeInternal( + controller, + 'session-1', + ), + localWorkspace.path, + ); + }, + ); +}