134 lines
4.6 KiB
Dart
134 lines
4.6 KiB
Dart
import 'package:flutter_test/flutter_test.dart';
|
|
import 'package:xworkmate/app/app_controller_desktop_thread_binding.dart';
|
|
import 'package:xworkmate/app/app_controller_desktop_thread_sessions.dart';
|
|
import 'package:xworkmate/runtime/runtime_models.dart';
|
|
|
|
void main() {
|
|
group('resolveDesktopThreadBindingSnapshotInternal', () {
|
|
const localOwner = ThreadOwnerScope(
|
|
realm: ThreadRealm.local,
|
|
subjectType: ThreadSubjectType.user,
|
|
subjectId: 'u1',
|
|
displayName: 'User',
|
|
);
|
|
|
|
TaskThread buildThread({
|
|
required String threadId,
|
|
required ThreadExecutionMode mode,
|
|
required String providerId,
|
|
}) {
|
|
return TaskThread(
|
|
threadId: threadId,
|
|
ownerScope: localOwner,
|
|
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('prefers the latest record after async binding resumes', () {
|
|
final latestRecord = buildThread(
|
|
threadId: 'thread-1',
|
|
mode: ThreadExecutionMode.localAgent,
|
|
providerId: SingleAgentProvider.opencode.providerId,
|
|
);
|
|
|
|
final snapshot = resolveDesktopThreadBindingSnapshotInternal(
|
|
defaultExecutionTarget: AssistantExecutionTarget.local,
|
|
latestRecord: latestRecord,
|
|
);
|
|
|
|
expect(snapshot.executionTarget, AssistantExecutionTarget.singleAgent);
|
|
expect(snapshot.singleAgentProvider, SingleAgentProvider.opencode);
|
|
expect(snapshot.record, same(latestRecord));
|
|
});
|
|
|
|
test(
|
|
'keeps an explicit execution override while preserving latest provider',
|
|
() {
|
|
final latestRecord = buildThread(
|
|
threadId: 'thread-2',
|
|
mode: ThreadExecutionMode.localAgent,
|
|
providerId: SingleAgentProvider.opencode.providerId,
|
|
);
|
|
|
|
final snapshot = resolveDesktopThreadBindingSnapshotInternal(
|
|
defaultExecutionTarget: AssistantExecutionTarget.local,
|
|
executionTargetOverride: AssistantExecutionTarget.remote,
|
|
latestRecord: latestRecord,
|
|
);
|
|
|
|
expect(snapshot.executionTarget, AssistantExecutionTarget.remote);
|
|
expect(snapshot.singleAgentProvider, SingleAgentProvider.opencode);
|
|
},
|
|
);
|
|
|
|
test('does not recover provider from stale fallback-only records', () {
|
|
final staleRecord = buildThread(
|
|
threadId: 'thread-3',
|
|
mode: ThreadExecutionMode.gatewayRemote,
|
|
providerId: SingleAgentProvider.codex.providerId,
|
|
);
|
|
|
|
final snapshot = resolveDesktopThreadBindingSnapshotInternal(
|
|
defaultExecutionTarget: AssistantExecutionTarget.remote,
|
|
latestRecord: null,
|
|
);
|
|
|
|
expect(snapshot.executionTarget, AssistantExecutionTarget.remote);
|
|
expect(snapshot.singleAgentProvider, SingleAgentProvider.auto);
|
|
expect(snapshot.record, isNull);
|
|
expect(staleRecord.executionBinding.providerId, isNotEmpty);
|
|
});
|
|
});
|
|
|
|
group('resolveGatewayThreadConnectionStateInternal', () {
|
|
test('uses the thread target profile as the only address source', () {
|
|
final state = resolveGatewayThreadConnectionStateInternal(
|
|
target: AssistantExecutionTarget.remote,
|
|
connection:
|
|
GatewayConnectionSnapshot.initial(
|
|
mode: RuntimeConnectionMode.remote,
|
|
).copyWith(
|
|
status: RuntimeConnectionStatus.connected,
|
|
remoteAddress: '127.0.0.1:18789',
|
|
),
|
|
targetProfile: GatewayConnectionProfile.defaultsRemote(),
|
|
);
|
|
|
|
expect(state.status, RuntimeConnectionStatus.connected);
|
|
expect(state.detailLabel, 'openclaw.svc.plus:443');
|
|
expect(state.ready, isTrue);
|
|
});
|
|
|
|
test('marks mismatched local snapshot as offline for remote threads', () {
|
|
final state = resolveGatewayThreadConnectionStateInternal(
|
|
target: AssistantExecutionTarget.remote,
|
|
connection:
|
|
GatewayConnectionSnapshot.initial(
|
|
mode: RuntimeConnectionMode.local,
|
|
).copyWith(
|
|
status: RuntimeConnectionStatus.connected,
|
|
remoteAddress: '127.0.0.1:18789',
|
|
),
|
|
targetProfile: GatewayConnectionProfile.defaultsRemote(),
|
|
);
|
|
|
|
expect(state.status, RuntimeConnectionStatus.offline);
|
|
expect(state.detailLabel, 'openclaw.svc.plus:443');
|
|
expect(state.ready, isFalse);
|
|
expect(state.lastError, isNull);
|
|
});
|
|
});
|
|
}
|