diff --git a/lib/app/app_controller_desktop_runtime_helpers.dart b/lib/app/app_controller_desktop_runtime_helpers.dart index 116b5d6d..1304df69 100644 --- a/lib/app/app_controller_desktop_runtime_helpers.dart +++ b/lib/app/app_controller_desktop_runtime_helpers.dart @@ -750,9 +750,6 @@ extension AppControllerDesktopRuntimeHelpers on AppController { ); final artifacts = result.artifacts; if (artifacts.isEmpty) { - final requiredExts = - existingThread.openClawTaskAssociation?.requiredArtifactExtensions ?? - const []; 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 = {}; 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); diff --git a/lib/app/app_controller_desktop_thread_actions.dart b/lib/app/app_controller_desktop_thread_actions.dart index 820f4301..4845f3fe 100644 --- a/lib/app/app_controller_desktop_thread_actions.dart +++ b/lib/app/app_controller_desktop_thread_actions.dart @@ -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 ['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); diff --git a/lib/runtime/runtime_models_runtime_payloads.dart b/lib/runtime/runtime_models_runtime_payloads.dart index d138a22e..9f2fbf79 100644 --- a/lib/runtime/runtime_models_runtime_payloads.dart +++ b/lib/runtime/runtime_models_runtime_payloads.dart @@ -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(); diff --git a/test/runtime/assistant_execution_target_test.dart b/test/runtime/assistant_execution_target_test.dart index f7d3b83f..ab1e9f1a 100644 --- a/test/runtime/assistant_execution_target_test.dart +++ b/test/runtime/assistant_execution_target_test.dart @@ -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 {