Files
2026-03-09 17:50:20 +08:00

145 lines
5.5 KiB
C#

using System;
using System.Collections.Generic;
namespace UnityTcp.Editor.Helpers
{
/// <summary>
/// Provides static methods for creating standardized success and error response objects.
/// Ensures consistent JSON structure for communication back to the Codely client.
///
/// Response format aligns with the OpenAPI spec:
/// - ImmediateResponse: { success, message, data?, state?, state_delta? }
/// - PendingResponse: { _mcp_status, op_id, poll_interval, message, state?, state_delta? }
/// </summary>
public static class Response
{
/// <summary>
/// Creates a standardized success response object with optional state.
/// </summary>
/// <param name="message">A message describing the successful operation.</param>
/// <param name="data">Optional additional data to include in the response.</param>
/// <param name="includeState">Whether to include full state snapshot (default: false).</param>
/// <param name="stateDelta">Optional state delta for incremental updates.</param>
/// <returns>An object representing the success response.</returns>
public static object Success(string message, object data = null, bool includeState = false, object stateDelta = null)
{
var response = new Dictionary<string, object>
{
{ "success", true },
{ "message", message },
// Always include current state revision so clients can keep client_state_rev in sync
{ "rev", StateComposer.GetCurrentRevision() }
};
if (data != null)
{
response["data"] = data;
}
// Include state if explicitly requested
if (includeState)
{
response["state"] = StateComposer.BuildFullState();
}
// Include state_delta if provided
if (stateDelta != null)
{
response["state_delta"] = stateDelta;
}
return response;
}
/// <summary>
/// Creates a standardized success response with automatic state delta.
/// Use this for write operations that modify Unity state.
/// </summary>
public static object SuccessWithDelta(string message, object data = null, object stateDelta = null)
{
StateComposer.IncrementRevision();
return Success(message, data, includeState: false, stateDelta: stateDelta);
}
/// <summary>
/// Creates a standardized success response with full state snapshot.
/// Use this for operations that require the client to have the latest state.
/// </summary>
public static object SuccessWithState(string message, object data = null)
{
StateComposer.IncrementRevision();
return Success(message, data, includeState: true);
}
/// <summary>
/// Creates a standardized error response object.
/// </summary>
/// <param name="errorCodeOrMessage">A message describing the error.</param>
/// <param name="data">Optional additional data (e.g., error details) to include.</param>
/// <param name="includeState">Whether to include full state snapshot for recovery (default: false).</param>
/// <returns>An object representing the error response.</returns>
public static object Error(string errorCodeOrMessage, object data = null, bool includeState = false)
{
var response = new Dictionary<string, object>
{
{ "success", false },
{ "code", errorCodeOrMessage },
{ "error", errorCodeOrMessage }
};
if (data != null)
{
response["data"] = data;
}
// Include state on error for recovery scenarios
if (includeState)
{
response["state"] = StateComposer.BuildFullState();
}
return response;
}
/// <summary>
/// Creates a conflict response for state revision mismatches.
/// This is returned when client_state_rev doesn't match server's revision.
/// </summary>
/// <param name="clientRev">The client's provided revision.</param>
/// <param name="serverRev">The server's current revision.</param>
/// <returns>A conflict response with full state for synchronization.</returns>
public static object Conflict(int clientRev, int serverRev)
{
return new Dictionary<string, object>
{
{ "success", false },
{ "code", "state_revision_conflict" },
{ "error", $"State revision mismatch. Client: {clientRev}, Server: {serverRev}. Please refresh state." },
{ "state", StateComposer.BuildFullState() }
};
}
/// <summary>
/// Legacy overload for backward compatibility.
/// </summary>
[Obsolete("Use Success(message, data, includeState, stateDelta) instead.")]
public static object SuccessLegacy(string message, object data = null)
{
if (data != null)
{
return new
{
success = true,
message = message,
data = data,
};
}
else
{
return new { success = true, message = message };
}
}
}
}