merge: preserve openclaw failure artifacts
This commit is contained in:
commit
a307762385
@ -1324,11 +1324,15 @@ extension AppControllerDesktopThreadActions on AppController {
|
||||
return;
|
||||
}
|
||||
if (!result.success) {
|
||||
clearGatewayTaskArtifactStateInternal(
|
||||
sessionKey,
|
||||
completedAtMs: completedAtMs,
|
||||
syncStatus: 'failed',
|
||||
);
|
||||
if (hasCurrentRunArtifacts) {
|
||||
await persistGoTaskArtifactsForSessionInternal(sessionKey, result);
|
||||
} else {
|
||||
clearGatewayTaskArtifactStateInternal(
|
||||
sessionKey,
|
||||
completedAtMs: completedAtMs,
|
||||
syncStatus: 'failed',
|
||||
);
|
||||
}
|
||||
appendLocalSessionMessageInternal(
|
||||
sessionKey,
|
||||
assistantErrorMessageInternal(
|
||||
|
||||
@ -621,15 +621,19 @@ Object? _firstGoTaskArtifactList(Map<String, dynamic> result) {
|
||||
final artifacts = <Object?>[];
|
||||
for (final candidate in <Object?>[
|
||||
result['artifacts'],
|
||||
result['finalArtifacts'],
|
||||
result['files'],
|
||||
result['attachments'],
|
||||
_castMap(result['payload'])['artifacts'],
|
||||
_castMap(result['payload'])['finalArtifacts'],
|
||||
_castMap(result['payload'])['files'],
|
||||
_castMap(result['payload'])['attachments'],
|
||||
_castMap(result['result'])['artifacts'],
|
||||
_castMap(result['result'])['finalArtifacts'],
|
||||
_castMap(result['result'])['files'],
|
||||
_castMap(result['result'])['attachments'],
|
||||
_castMap(result['data'])['artifacts'],
|
||||
_castMap(result['data'])['finalArtifacts'],
|
||||
_castMap(result['data'])['files'],
|
||||
_castMap(result['data'])['attachments'],
|
||||
]) {
|
||||
|
||||
@ -1953,6 +1953,55 @@ void main() {
|
||||
},
|
||||
);
|
||||
|
||||
test(
|
||||
'sendChatMessage keeps partial OpenClaw artifacts on terminal artifact failure',
|
||||
() async {
|
||||
final fakeGoTaskService = _RecordingGoTaskServiceClient()
|
||||
..outcomes.add(
|
||||
const GoTaskServiceResult(
|
||||
success: false,
|
||||
message: 'OpenClaw completed without required final artifacts.',
|
||||
turnId: 'turn-1',
|
||||
raw: <String, dynamic>{
|
||||
'status': 'failed',
|
||||
'code': 'OPENCLAW_REQUIRED_ARTIFACT_MISSING',
|
||||
'artifacts': <Map<String, dynamic>>[
|
||||
<String, dynamic>{
|
||||
'relativePath': 'stages/chapter.md',
|
||||
'content': 'partial chapter',
|
||||
'contentType': 'text/markdown',
|
||||
},
|
||||
],
|
||||
},
|
||||
errorMessage:
|
||||
'openclaw returned partial artifacts without required final deliverables',
|
||||
resolvedModel: '',
|
||||
route: GoTaskServiceRoute.externalAcpSingle,
|
||||
),
|
||||
);
|
||||
final controller = _connectedController(fakeGoTaskService);
|
||||
addTearDown(controller.dispose);
|
||||
|
||||
await controller.sessionsController.switchSession(
|
||||
'unit-fixture-task-a',
|
||||
);
|
||||
|
||||
await controller.sendChatMessage('first turn');
|
||||
|
||||
final failedThread = controller.taskThreadForSessionInternal(
|
||||
'unit-fixture-task-a',
|
||||
);
|
||||
expect(
|
||||
failedThread?.lifecycleState.lastResultCode,
|
||||
'OPENCLAW_REQUIRED_ARTIFACT_MISSING',
|
||||
);
|
||||
expect(failedThread?.lastArtifactSyncStatus, 'synced');
|
||||
expect(failedThread?.lastTaskArtifactRelativePaths, <String>[
|
||||
'stages/chapter.md',
|
||||
]);
|
||||
},
|
||||
);
|
||||
|
||||
test(
|
||||
'sendChatMessage treats nested OpenClaw artifact errors as terminal failures',
|
||||
() async {
|
||||
|
||||
@ -251,6 +251,33 @@ void main() {
|
||||
'https://xworkmate-bridge.svc.plus/artifacts/summary.pdf',
|
||||
);
|
||||
});
|
||||
|
||||
test('uses OpenClaw finalArtifacts as required deliverables', () {
|
||||
final result = goTaskServiceResultFromAcpResponse(<String, dynamic>{
|
||||
'jsonrpc': '2.0',
|
||||
'id': 'request-id',
|
||||
'result': <String, dynamic>{
|
||||
'success': true,
|
||||
'message': 'created final deliverable',
|
||||
'finalArtifacts': <Map<String, dynamic>>[
|
||||
<String, dynamic>{
|
||||
'relativePath': 'exports/final.pdf',
|
||||
'downloadUrl':
|
||||
'https://xworkmate-bridge.svc.plus/artifacts/final.pdf',
|
||||
'contentType': 'application/pdf',
|
||||
},
|
||||
],
|
||||
},
|
||||
}, route: GoTaskServiceRoute.externalAcpSingle);
|
||||
|
||||
expect(result.success, isTrue);
|
||||
expect(result.artifacts, hasLength(1));
|
||||
expect(result.artifacts.single.relativePath, 'exports/final.pdf');
|
||||
expect(
|
||||
result.artifacts.single.downloadUrl,
|
||||
'https://xworkmate-bridge.svc.plus/artifacts/final.pdf',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
group('GatewayAcpClient authorization', () {
|
||||
@ -2128,8 +2155,6 @@ void main() {
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user