fix(chat): drop root-level expectedArtifactDirs to satisfy chat.send schema

- Remove the unexpected property at the root of gateway task metadata.
  Keep the value nested in xworkmateTaskArtifactContract where the
  OpenClaw chat.send schema allows it (-32002: invalid chat.send params).
- Drop dead local vars and the unused asInt helper in OpenClaw task
  association parsing.
- Remove the obsolete 'sendChatMessage restarts before handling
  OpenClaw artifact guard results' test superseded by the new terminal
  artifact failure test.
This commit is contained in:
Haitao Pan 2026-06-05 19:12:31 +08:00
parent fff0ea5633
commit 3a548717ba
4 changed files with 6 additions and 23 deletions

View File

@ -750,9 +750,6 @@ extension AppControllerDesktopRuntimeHelpers on AppController {
);
final artifacts = result.artifacts;
if (artifacts.isEmpty) {
final requiredExts =
existingThread.openClawTaskAssociation?.requiredArtifactExtensions ??
const <String>[];
final currentTaskArtifactRelativePaths =
await _workspaceArtifactPathsModifiedSinceInternal(
root,
@ -782,7 +779,6 @@ extension AppControllerDesktopRuntimeHelpers on AppController {
var wroteArtifact = false;
var failedArtifact = false;
var skippedArtifact = false;
var rejectedArtifact = false;
final currentTaskArtifactPaths = <String>{};
for (final artifact in artifacts) {
final relativePath = _sanitizeArtifactRelativePathInternal(
@ -813,7 +809,6 @@ extension AppControllerDesktopRuntimeHelpers on AppController {
continue;
}
if (artifactSyncPolicy.rejects(artifact, relativePath, bytes)) {
rejectedArtifact = true;
continue;
}
final target = await _nextArtifactTargetFileInternal(root, relativePath);

View File

@ -771,10 +771,12 @@ extension AppControllerDesktopThreadActions on AppController {
}
if (aiGatewayPendingSessionKeysInternal.contains(sessionKey)) {
final hasRequiredExts = current.requiredArtifactExtensions.isNotEmpty;
final hasEnoughArtifacts = !hasRequiredExts ||
final hasEnoughArtifacts =
!hasRequiredExts ||
current.requiredArtifactExtensions.every((ext) {
return result.artifacts.any(
(a) => a.relativePath.toLowerCase().endsWith(ext.toLowerCase()),
(a) =>
a.relativePath.toLowerCase().endsWith(ext.toLowerCase()),
);
});
if (!hasEnoughArtifacts && artifactRetries < 3) {
@ -959,6 +961,7 @@ extension AppControllerDesktopThreadActions on AppController {
'finalDeliverableDetection': 'remote-runtime',
'requiresExportBeforeFinalResponse': true,
'rejectTextOnlyFileClaims': true,
'expectedArtifactDirs': const <String>['artifacts/'],
'currentTaskWorkspace': executionWorkspace.isNotEmpty
? executionWorkspace
: (remoteHint.isNotEmpty ? remoteHint : localWorkspace),
@ -1373,10 +1376,7 @@ extension AppControllerDesktopThreadActions on AppController {
required Object error,
}) async {
clearAiGatewayStreamingTextInternal(sessionKey);
clearPendingToolCallsForGatewaySessionInternal(
sessionKey,
hasError: true,
);
clearPendingToolCallsForGatewaySessionInternal(sessionKey, hasError: true);
final completedAtMs = DateTime.now().millisecondsSinceEpoch.toDouble();
final recoveredArtifactPaths =
await recoverGatewayFailureArtifactPathsInternal(sessionKey, error);

View File

@ -1013,16 +1013,6 @@ class OpenClawTaskAssociation {
if (runId.isEmpty || artifactScope.isEmpty) {
return null;
}
int asInt(Object? raw) {
if (raw is int) {
return raw;
}
if (raw is num) {
return raw.toInt();
}
return int.tryParse(raw?.toString() ?? '') ?? 60;
}
double asDouble(Object? raw) {
if (raw is num) {
return raw.toDouble();

View File

@ -1818,8 +1818,6 @@ void main() {
},
);
test(
'sendChatMessage restarts before handling OpenClaw artifact guard results',
test(
'sendChatMessage starts a new session after OpenClaw terminal artifact failure',
() async {