Initial commit: AIGame Unity client with URP, HybridCLR, YooAsset and tooling.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,208 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace Unity.Pipeline.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// Response model for /api/exec endpoint.
|
||||
/// Contains execution result and metadata for remote command execution.
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class CommandExecutionResponse : BaseResponse
|
||||
{
|
||||
/// <summary>
|
||||
/// Whether the command executed successfully.
|
||||
/// </summary>
|
||||
[JsonProperty("success")]
|
||||
public bool Success { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Name of the command that was executed.
|
||||
/// </summary>
|
||||
[JsonProperty("command")]
|
||||
public string Command { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Result returned by the command (if any).
|
||||
/// </summary>
|
||||
[JsonProperty("result")]
|
||||
public object Result { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Execution duration in milliseconds.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Like <c>command</c> and <c>executedAt</c>, emitted on the /api/exec wire only in verbose
|
||||
/// mode — the gating lives in <c>ExecResponseSerializer</c>, not on this model. (AUTHAPI-21)
|
||||
/// </remarks>
|
||||
[JsonProperty("executionTimeMs")]
|
||||
public long? ExecutionTimeMs { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Coarse machine-readable server state marker. Set to "busy" when the command was not
|
||||
/// executed because the server's host cannot service it yet (e.g. the Editor is still
|
||||
/// settling after a cold start). Omitted from the JSON on ordinary success/failure
|
||||
/// responses, so existing envelopes are unchanged.
|
||||
/// </summary>
|
||||
[JsonProperty("status", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public string Status { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// True when the failure is transient and the same request is expected to succeed after a
|
||||
/// short wait (poll /api/status until it reports "ready"). Omitted from the JSON on
|
||||
/// ordinary success/failure responses.
|
||||
/// </summary>
|
||||
[JsonProperty("retryable", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public bool? Retryable { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Stable, machine-readable failure discriminator (e.g. <c>INVALID_COMMAND_ARGS</c>).
|
||||
///
|
||||
/// HTTP status cannot serve as the discriminator here: every /api/exec failure is 400, so
|
||||
/// status alone cannot separate "your arguments are wrong" from "the command threw".
|
||||
/// Spelled to match the <c>unity</c> CLI's own InvalidArgsCode literal, so neither side
|
||||
/// needs a translation table.
|
||||
/// </summary>
|
||||
[JsonProperty("errorCode", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public string ErrorCode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Every argument-binding defect found, one entry each — the binder accumulates rather
|
||||
/// than bailing, so a user fixing a command line sees all of its problems at once.
|
||||
/// Machine-readable rather than prose, because the <c>unity</c> CLI renders and localizes
|
||||
/// these itself; <see cref="BaseResponse.ErrorDetails"/> carries the English fallback for
|
||||
/// clients that do not.
|
||||
/// </summary>
|
||||
[JsonProperty("argProblems", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public List<ArgProblem> ArgProblems { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The resolved command's catalog entry, shaped like a /api/commands <c>commands[]</c>
|
||||
/// element. Sent with an argument error so a client can render usage without a separate
|
||||
/// schema request. Free to produce - the command is already resolved at that point.
|
||||
/// </summary>
|
||||
[JsonProperty("commandSchema", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public JObject CommandSchema { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// What the server bound from a raw command line. Set ONLY for argv/commandLine requests,
|
||||
/// leaving the structured path's envelope unchanged. A client that does not bind locally
|
||||
/// has no other way to report what the command actually received.
|
||||
/// </summary>
|
||||
[JsonProperty("parameters", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public JObject BoundParameters { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Create the argument-binding failure response (sent with HTTP 400): the command was
|
||||
/// resolved but its arguments could not be bound, so nothing executed.
|
||||
/// </summary>
|
||||
internal static CommandExecutionResponse CmdInvalidArgs(string cmd, string details,
|
||||
List<ArgProblem> problems, JObject commandSchema)
|
||||
{
|
||||
return new CommandExecutionResponse
|
||||
{
|
||||
Command = cmd,
|
||||
Success = false,
|
||||
ExecutedAt = DateTime.UtcNow,
|
||||
Error = "Invalid Command Arguments",
|
||||
ErrorDetails = details,
|
||||
ErrorCode = "INVALID_COMMAND_ARGS",
|
||||
ArgProblems = problems,
|
||||
CommandSchema = commandSchema
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The specific cause of a "busy" response, matching /api/status's own "status" values for
|
||||
/// the same conditions ("settling", "blocked_by_dialog") — a caller can branch on this
|
||||
/// directly instead of inferring the cause from whether "dialogs" happens to be populated.
|
||||
/// Omitted from the JSON on ordinary success/failure responses.
|
||||
/// </summary>
|
||||
[JsonProperty("busyReason", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public string BusyReason { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Dialogs (see EditorDialogEvents) that opened at or after this call started. Omitted
|
||||
/// when none occurred, so existing envelopes are unchanged. Lets a caller learn "this
|
||||
/// call took 40s because a dialog was shown" even without polling /api/dialog
|
||||
/// concurrently.
|
||||
/// </summary>
|
||||
[JsonProperty("dialogsDuringExecution", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public List<object> DialogsDuringExecution { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Currently-open dialog(s) (see EditorDialogEvents), attached to a busy response when a
|
||||
/// MainThreadRequired command was rejected because a modal dialog is blocking the main
|
||||
/// thread. Omitted otherwise.
|
||||
/// </summary>
|
||||
[JsonProperty("dialogs", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public List<object> Dialogs { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Create a successful execution response.
|
||||
/// </summary>
|
||||
/// <param name="command">Name of the executed command.</param>
|
||||
/// <param name="result">The command's result payload.</param>
|
||||
/// <param name="executionTimeMs">How long the command took to execute, in milliseconds.</param>
|
||||
/// <returns>A successful response wrapping <paramref name="result"/>.</returns>
|
||||
public static CommandExecutionResponse CmdSuccess(string command, object result = null, long? executionTimeMs = null)
|
||||
{
|
||||
return new CommandExecutionResponse
|
||||
{
|
||||
Success = true,
|
||||
Command = command,
|
||||
ExecutedAt = DateTime.UtcNow,
|
||||
Result = result,
|
||||
ExecutionTimeMs = executionTimeMs
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a failed execution response.
|
||||
/// </summary>
|
||||
/// <param name="cmd">Name of the executed command.</param>
|
||||
/// <param name="error">Error message.</param>
|
||||
/// <param name="errorDetails">Additional error details for debugging.</param>
|
||||
/// <returns>A failed response with <see cref="BaseResponse.Error"/>/<see cref="BaseResponse.ErrorDetails"/> set.</returns>
|
||||
public static CommandExecutionResponse CmdFailure(string cmd, string error, string errorDetails)
|
||||
{
|
||||
return new CommandExecutionResponse
|
||||
{
|
||||
Command = cmd,
|
||||
Success = false,
|
||||
ExecutedAt = DateTime.UtcNow,
|
||||
Error = error,
|
||||
ErrorDetails = errorDetails
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create the retryable "server busy" response (sent with HTTP 503): the command was not
|
||||
/// executed because the host cannot service it yet — distinguishable from a genuine
|
||||
/// command failure via status/retryable so callers know to retry shortly instead of
|
||||
/// guessing (AUTHAPI-35). <paramref name="busyReason"/> is the specific cause ("settling",
|
||||
/// "blocked_by_dialog", ...); omit it only for a generic/legacy busy state.
|
||||
/// </summary>
|
||||
/// <param name="cmd">Name of the command that could not be serviced yet.</param>
|
||||
/// <param name="details">Human-readable reason the host is busy.</param>
|
||||
/// <param name="busyReason">The specific cause of the busy state, or null for a generic/legacy busy state.</param>
|
||||
/// <returns>A retryable "server busy" response.</returns>
|
||||
public static CommandExecutionResponse CmdBusy(string cmd, string details, string busyReason = null)
|
||||
{
|
||||
return new CommandExecutionResponse
|
||||
{
|
||||
Command = cmd,
|
||||
Success = false,
|
||||
ExecutedAt = DateTime.UtcNow,
|
||||
Error = "Server Busy",
|
||||
ErrorDetails = details,
|
||||
Status = "busy",
|
||||
Retryable = true,
|
||||
BusyReason = busyReason
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user