feat(batch_execute): improve error handling with success detection and fail-fast support (#531)
- Add DetermineCallSucceeded() to check command success via IMcpResponse interface or JObject/JToken 'success' field - Track invocationFailureCount and set anyCommandFailed flag when commands fail - Implement fail-fast behavior to stop batch execution on first failure when failFast=true - Update commandResults to use computed callSucceeded value instead of hardcoded true feat(game_object_create): enhance assetmain
parent
ea55c443bf
commit
a17df1e4c9
|
|
@ -91,14 +91,28 @@ namespace MCPForUnity.Editor.Tools
|
|||
try
|
||||
{
|
||||
var result = await CommandRegistry.InvokeCommandAsync(toolName, commandParams).ConfigureAwait(true);
|
||||
invocationSuccessCount++;
|
||||
bool callSucceeded = DetermineCallSucceeded(result);
|
||||
if (callSucceeded)
|
||||
{
|
||||
invocationSuccessCount++;
|
||||
}
|
||||
else
|
||||
{
|
||||
invocationFailureCount++;
|
||||
anyCommandFailed = true;
|
||||
}
|
||||
|
||||
commandResults.Add(new
|
||||
{
|
||||
tool = toolName,
|
||||
callSucceeded = true,
|
||||
callSucceeded,
|
||||
result
|
||||
});
|
||||
|
||||
if (!callSucceeded && failFast)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
|
@ -134,6 +148,39 @@ namespace MCPForUnity.Editor.Tools
|
|||
: new ErrorResponse("One or more commands failed.", data);
|
||||
}
|
||||
|
||||
private static bool DetermineCallSucceeded(object result)
|
||||
{
|
||||
if (result == null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (result is IMcpResponse response)
|
||||
{
|
||||
return response.Success;
|
||||
}
|
||||
|
||||
if (result is JObject obj)
|
||||
{
|
||||
var successToken = obj["success"];
|
||||
if (successToken != null && successToken.Type == JTokenType.Boolean)
|
||||
{
|
||||
return successToken.Value<bool>();
|
||||
}
|
||||
}
|
||||
|
||||
if (result is JToken token)
|
||||
{
|
||||
var successToken = token["success"];
|
||||
if (successToken != null && successToken.Type == JTokenType.Boolean)
|
||||
{
|
||||
return successToken.Value<bool>();
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static JObject NormalizeParameterKeys(JObject source)
|
||||
{
|
||||
if (source == null)
|
||||
|
|
|
|||
|
|
@ -29,9 +29,11 @@ namespace MCPForUnity.Editor.Tools.GameObjects
|
|||
|
||||
// --- Try Instantiating Prefab First ---
|
||||
string originalPrefabPath = prefabPath;
|
||||
if (!string.IsNullOrEmpty(prefabPath))
|
||||
if (!saveAsPrefab && !string.IsNullOrEmpty(prefabPath))
|
||||
{
|
||||
if (!prefabPath.Contains("/") && !prefabPath.EndsWith(".prefab", StringComparison.OrdinalIgnoreCase))
|
||||
string extension = System.IO.Path.GetExtension(prefabPath);
|
||||
|
||||
if (!prefabPath.Contains("/") && (string.IsNullOrEmpty(extension) || extension.Equals(".prefab", StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
string prefabNameOnly = prefabPath;
|
||||
McpLog.Info($"[ManageGameObject.Create] Searching for prefab named: '{prefabNameOnly}'");
|
||||
|
|
@ -51,11 +53,38 @@ namespace MCPForUnity.Editor.Tools.GameObjects
|
|||
McpLog.Info($"[ManageGameObject.Create] Found unique prefab at path: '{prefabPath}'");
|
||||
}
|
||||
}
|
||||
else if (!prefabPath.EndsWith(".prefab", StringComparison.OrdinalIgnoreCase))
|
||||
else if (prefabPath.Contains("/") && string.IsNullOrEmpty(extension))
|
||||
{
|
||||
McpLog.Warn($"[ManageGameObject.Create] Provided prefabPath '{prefabPath}' does not end with .prefab. Assuming it's missing and appending.");
|
||||
McpLog.Warn($"[ManageGameObject.Create] Provided prefabPath '{prefabPath}' has no extension. Assuming it's a prefab and appending .prefab.");
|
||||
prefabPath += ".prefab";
|
||||
}
|
||||
else if (!prefabPath.Contains("/") && !string.IsNullOrEmpty(extension) && !extension.Equals(".prefab", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
string fileName = prefabPath;
|
||||
string fileNameWithoutExtension = System.IO.Path.GetFileNameWithoutExtension(fileName);
|
||||
McpLog.Info($"[ManageGameObject.Create] Searching for asset file named: '{fileName}'");
|
||||
|
||||
string[] guids = AssetDatabase.FindAssets(fileNameWithoutExtension);
|
||||
var matches = guids
|
||||
.Select(g => AssetDatabase.GUIDToAssetPath(g))
|
||||
.Where(p => p.EndsWith("/" + fileName, StringComparison.OrdinalIgnoreCase) || p.Equals(fileName, StringComparison.OrdinalIgnoreCase))
|
||||
.ToArray();
|
||||
|
||||
if (matches.Length == 0)
|
||||
{
|
||||
return new ErrorResponse($"Asset file '{fileName}' not found anywhere in the project.");
|
||||
}
|
||||
else if (matches.Length > 1)
|
||||
{
|
||||
string foundPaths = string.Join(", ", matches);
|
||||
return new ErrorResponse($"Multiple assets found matching file name '{fileName}': {foundPaths}. Please provide a more specific path.");
|
||||
}
|
||||
else
|
||||
{
|
||||
prefabPath = matches[0];
|
||||
McpLog.Info($"[ManageGameObject.Create] Found unique asset at path: '{prefabPath}'");
|
||||
}
|
||||
}
|
||||
|
||||
GameObject prefabAsset = AssetDatabase.LoadAssetAtPath<GameObject>(prefabPath);
|
||||
if (prefabAsset != null)
|
||||
|
|
@ -83,7 +112,7 @@ namespace MCPForUnity.Editor.Tools.GameObjects
|
|||
}
|
||||
else
|
||||
{
|
||||
McpLog.Warn($"[ManageGameObject.Create] Prefab asset not found at path: '{prefabPath}'. Will proceed to create new object if specified.");
|
||||
return new ErrorResponse($"Asset not found or not a GameObject at path: '{prefabPath}'.");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue