fix: isolate openclaw e2e artifacts

This commit is contained in:
Haitao Pan 2026-05-29 10:41:46 +08:00
parent e54a97bd36
commit 8c29172fdf
4 changed files with 76 additions and 22 deletions

View File

@ -60,7 +60,9 @@ class DesktopThreadArtifactService {
final taskArtifactPaths = normalizeTaskArtifactPathsInternal(
artifactRelativePaths,
);
final allFiles = await collectFilesInternal(root);
final allFiles = taskArtifactPaths.isEmpty
? const <File>[]
: await collectFilesInternal(root);
final fileEntries = await buildEntriesInternal(allFiles, normalizedRef);
final taskFiles = taskArtifactPaths.isEmpty
? const <File>[]
@ -91,7 +93,9 @@ class DesktopThreadArtifactService {
? 'No task artifacts recorded for this run.'
: 'No current task artifacts found. Showing all files for this thread.'
: '';
final filesMessage = fileEntries.isEmpty
final filesMessage = taskArtifactPaths.isEmpty
? ''
: fileEntries.isEmpty
? 'No files found in the recorded working directory.'
: '';
final changesMessage = changes.isEmpty

View File

@ -1310,10 +1310,8 @@ void main() {
sessionKey: 'unit-fixture-task-a',
);
expect(snapshot.resultEntries, isEmpty);
expect(
snapshot.fileEntries.map((entry) => entry.relativePath),
contains('old-task-report.md'),
);
expect(snapshot.fileEntries, isEmpty);
expect(snapshot.resultMessage, 'No task artifacts recorded for this run.');
});
test('skips download URL artifacts outside the bridge host', () async {

View File

@ -2263,9 +2263,10 @@ void main() {
);
expect(taskBSnapshot.fileEntries, isEmpty);
expect(
taskBSnapshot.filesMessage,
'No files found in the recorded working directory.',
taskBSnapshot.resultMessage,
'No task artifacts recorded for this run.',
);
expect(taskBSnapshot.filesMessage, isEmpty);
},
);
@ -2404,9 +2405,10 @@ void main() {
sessionKey: 'terminal-failure-task',
);
expect(snapshot.resultEntries, isEmpty);
expect(snapshot.fileEntries, isEmpty);
expect(
snapshot.fileEntries.map((entry) => entry.relativePath),
contains('first.md'),
snapshot.resultMessage,
'No task artifacts recorded for this run.',
);
},
);
@ -2709,6 +2711,57 @@ void main() {
},
);
test(
'OpenClaw gateway admits five representative E2E tasks without queueing',
() async {
final fakeGoTaskService = _BlockingGoTaskServiceClient();
final controller = _connectedGatewayController(fakeGoTaskService);
addTearDown(() {
fakeGoTaskService.completeAll();
controller.dispose();
});
const prompts = <String>[
'从单机权限 → 网络边界 → Web安全 → 云身份 → Zero Trust → AI Agent 身份 → AI模型与知识保护 演进 制作 使用codex 制作连续制作 7张的一些列图片',
'参考附件模版制作 ,围绕 从单机权限 → 网络边界 → Web安全 → 云身份 → Zero Trust → AI Agent 身份 → AI模型与知识保护 演进 连续制作 7张的一些列图片',
'拆章节 -> 每章调用 Codex -> 每章 GPT images2 生成图 -> 汇总排版 -> 输出 PDF',
'围绕 从单机权限 → 网络边界 → Web安全 → 云身份 → Zero Trust → AI Agent 身份 → AI模型与知识保护 演进 右侧是当下 测试制作视频',
'从单机权限 → 网络边界 → Web安全 → 云身份 → Zero Trust → AI Agent 身份 → AI模型与知识保护 演进 拆章节 -> 每章调用 Codex -> 每章 GPT images2 生成图 -> 汇总排版 -> 制作视频',
];
for (var index = 0; index < prompts.length; index += 1) {
final sessionKey = 'openclaw-e2e-$index';
await _selectGatewaySession(controller, sessionKey);
await expectLater(
controller
.sendChatMessage(prompts[index])
.timeout(const Duration(seconds: 2)),
completes,
);
}
await fakeGoTaskService.waitForRequestCount(prompts.length);
expect(fakeGoTaskService.requests, hasLength(prompts.length));
expect(controller.openClawGatewayActiveTasksInternal, prompts.length);
expect(controller.openClawGatewayQueuedTurnsInternal, isEmpty);
for (var index = 0; index < prompts.length; index += 1) {
final sessionKey = 'openclaw-e2e-$index';
expect(
controller
.requireTaskThreadForSessionInternal(sessionKey)
.lifecycleState
.status,
'running',
);
expect(fakeGoTaskService.requests[index].sessionId, sessionKey);
expect(
fakeGoTaskService.requests[index].prompt,
contains(prompts[index]),
);
}
},
);
test('OpenClaw gateway task uses the server default model', () async {
final fakeGoTaskService = _BlockingGoTaskServiceClient();
final controller = _connectedGatewayController(fakeGoTaskService);

View File

@ -1,12 +1,13 @@
import 'dart:io';
import 'package:flutter_test/flutter_test.dart';
import 'package:xworkmate/runtime/assistant_artifacts.dart';
import 'package:xworkmate/runtime/desktop_thread_artifact_service.dart';
import 'package:xworkmate/runtime/runtime_models.dart';
void main() {
test(
'loadSnapshot exposes all local workspace files when current run has no artifacts',
'loadSnapshot hides historical workspace files when current run has no artifacts',
() async {
final workspace = await Directory.systemTemp.createTemp(
'xworkmate-artifact-snapshot-',
@ -25,10 +26,7 @@ void main() {
);
expect(snapshot.resultEntries, isEmpty);
expect(
snapshot.fileEntries.map((entry) => entry.relativePath),
contains('historical.md'),
);
expect(snapshot.fileEntries, isEmpty);
expect(
snapshot.resultMessage,
'No task artifacts recorded for this run.',
@ -80,13 +78,14 @@ void main() {
}
});
await File('${workspace.path}/historical.md').writeAsString('# Old\n');
final snapshot = await DesktopThreadArtifactService().loadSnapshot(
workspacePath: workspace.path,
workspaceKind: WorkspaceRefKind.localPath,
artifactRelativePaths: const <String>[],
);
final historical = snapshot.fileEntries.singleWhere(
(entry) => entry.relativePath == 'historical.md',
const historical = AssistantArtifactEntry(
id: 'historical.md',
label: 'historical.md',
relativePath: 'historical.md',
kind: AssistantArtifactEntryKind.file,
mimeType: 'text/markdown',
previewable: true,
workspacePath: '',
);
final preview = await DesktopThreadArtifactService().loadPreview(