Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
89 changes: 86 additions & 3 deletions src/libs/tryAGI.OpenAI.CLI/GeneratedApi/CliRuntime.cs
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,88 @@ public static TimeSpan ParseDuration(string value, string optionName)
}


public static async Task<T> PollUntilTerminalAsync<T>(
Func<CancellationToken, Task<T>> fetchAsync,
TimeSpan pollInterval,
TimeSpan waitTimeout,
JsonSerializerContext context,
CancellationToken cancellationToken)
{
if (pollInterval <= TimeSpan.Zero || waitTimeout <= TimeSpan.Zero)
{
throw new CliException("--poll-interval and --wait-timeout must be greater than zero.");
}

using var timeout = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
timeout.CancelAfter(waitTimeout);
try
{
while (true)
{
var response = await fetchAsync(timeout.Token).ConfigureAwait(false);
var status = FindJobStatus(ToJsonElement(response, context), depth: 0);
if (string.IsNullOrWhiteSpace(status))
{
throw new CliException("The status response did not contain a status value.");
}

switch (status.Trim().ToUpperInvariant())
{
case "COMPLETED":
case "SUCCEEDED":
case "SUCCESS":
case "DONE":
case "FINISHED":
return response;
case "FAILED":
case "ERRORED":
case "ERROR":
case "CANCELLED":
case "CANCELED":
case "ABORTED":
throw new CliException($"The job ended with status '{status}'.");
}

await Task.Delay(pollInterval, timeout.Token).ConfigureAwait(false);
}
}
catch (OperationCanceledException) when (timeout.IsCancellationRequested && !cancellationToken.IsCancellationRequested)
{
throw new CliException($"The job did not finish within {waitTimeout}.");
}
}

private static string? FindJobStatus(JsonElement element, int depth)
{
if (element.ValueKind != JsonValueKind.Object || depth > 3)
{
return null;
}

foreach (var property in element.EnumerateObject())
{
if (string.Equals(property.Name, "status", StringComparison.OrdinalIgnoreCase))
{
return property.Value.ValueKind == JsonValueKind.String
? property.Value.GetString()
: property.Value.ToString();
}
}

foreach (var property in element.EnumerateObject())
{
if (property.Name is "data" or "result" or "job" or "task")
{
var status = FindJobStatus(property.Value, depth + 1);
if (status is not null)
{
return status;
}
}
}

return null;
}

public static async global::System.Threading.Tasks.Task<string?> ReadInputAsync(
ParseResult parseResult,
Expand Down Expand Up @@ -355,9 +437,10 @@ public static TimeSpan ParseDuration(string value, string optionName)

public static T DeserializeJsonValue<T>(string json, JsonSerializerContext context)
{
_ = context;
return JsonSerializer.Deserialize<T>(json) ??
throw new CliException($"Unable to deserialize generated CLI value as {typeof(T).Name}.");
var value = JsonSerializer.Deserialize(json, typeof(T), context);
return value is T typed
? typed
: throw new CliException($"Unable to deserialize generated CLI value as {typeof(T).Name}.");
}

public static string SerializeKeyValuePairs(IEnumerable<string> pairs)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ private static string FormatResponse(ParseResult parseResult, global::tryAGI.Ope
static partial void CustomizeResponseFormatHints(Dictionary<string, CliFormatHint> hints);


static partial void CustomizeCommand(ref Command command);

public static Command Create()
{
var command = new Command(@"admin-api-keys-create", @"Create admin API key
Expand Down Expand Up @@ -104,6 +106,7 @@ await CliRuntime.WriteResponseAsync(
FormatResponse,
cancellationToken).ConfigureAwait(false);
}, cancellationToken).ConfigureAwait(false));
CustomizeCommand(ref command);
return command;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ private static string FormatResponse(ParseResult parseResult, global::tryAGI.Ope
static partial void CustomizeResponseFormatHints(Dictionary<string, CliFormatHint> hints);


static partial void CustomizeCommand(ref Command command);

public static Command Create()
{
var command = new Command(@"admin-api-keys-delete", @"Delete admin API key
Expand All @@ -59,6 +61,7 @@ await CliRuntime.WriteResponseAsync(
FormatResponse,
cancellationToken).ConfigureAwait(false);
}, cancellationToken).ConfigureAwait(false));
CustomizeCommand(ref command);
return command;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ private static string FormatResponse(ParseResult parseResult, global::tryAGI.Ope
static partial void CustomizeResponseFormatHints(Dictionary<string, CliFormatHint> hints);


static partial void CustomizeCommand(ref Command command);

public static Command Create()
{
var command = new Command(@"admin-api-keys-get", @"Retrieve admin API key
Expand All @@ -59,6 +61,7 @@ await CliRuntime.WriteResponseAsync(
FormatResponse,
cancellationToken).ConfigureAwait(false);
}, cancellationToken).ConfigureAwait(false));
CustomizeCommand(ref command);
return command;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ private static string FormatResponse(ParseResult parseResult, global::tryAGI.Ope
static partial void CustomizeResponseFormatHints(Dictionary<string, CliFormatHint> hints);


static partial void CustomizeCommand(ref Command command);

public static Command Create()
{
var command = new Command(@"admin-api-keys-list", @"List all organization and project API keys.
Expand Down Expand Up @@ -85,6 +87,7 @@ await CliRuntime.WriteResponseAsync(
cancellationToken).ConfigureAwait(false);
}
}, cancellationToken).ConfigureAwait(false));
CustomizeCommand(ref command);
return command;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@

namespace tryAGI.OpenAI.Cli.GeneratedApi.Commands;

internal static class AgentsApiGroupCommand
internal static partial class AgentsApiGroupCommand
{
static partial void CustomizeCommand(ref Command command);

public static Command Create()
{
var command = new Command(@"agents", @"Agents endpoint commands.");
Expand Down Expand Up @@ -43,6 +45,7 @@ public static Command Create()
command.Subcommands.Add(AgentsUpdateAgentCommandApiCommand.Create());
command.Subcommands.Add(AgentsUpdateAgentEnvironmentTemplateCommandApiCommand.Create());
command.Subcommands.Add(AgentsUpdateAgentSessionCommandApiCommand.Create());
CustomizeCommand(ref command);
return command;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@ private static string FormatResponse(ParseResult parseResult, global::tryAGI.Ope
static partial void CustomizeResponseFormatHints(Dictionary<string, CliFormatHint> hints);


static partial void CustomizeCommand(ref Command command);

public static Command Create()
{
var command = new Command(@"create-agent", @"Create an agent
Expand Down Expand Up @@ -183,6 +185,7 @@ await CliRuntime.WriteResponseAsync(
cancellationToken).ConfigureAwait(false);
}
}, cancellationToken).ConfigureAwait(false));
CustomizeCommand(ref command);
return command;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ private static string FormatResponse(ParseResult parseResult, global::tryAGI.Ope
static partial void CustomizeResponseFormatHints(Dictionary<string, CliFormatHint> hints);


static partial void CustomizeCommand(ref Command command);

public static Command Create()
{
var command = new Command(@"create-agent-environment-file", @"Create an agent environment file
Expand Down Expand Up @@ -96,6 +98,7 @@ await CliRuntime.WriteResponseAsync(
FormatResponse,
cancellationToken).ConfigureAwait(false);
}, cancellationToken).ConfigureAwait(false));
CustomizeCommand(ref command);
return command;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,8 @@ private static string FormatResponse(ParseResult parseResult, global::tryAGI.Ope
static partial void CustomizeResponseFormatHints(Dictionary<string, CliFormatHint> hints);


static partial void CustomizeCommand(ref Command command);

public static Command Create()
{
var command = new Command(@"create-agent-environment-template", @"Create an agent environment template
Expand Down Expand Up @@ -185,6 +187,7 @@ await CliRuntime.WriteResponseAsync(
FormatResponse,
cancellationToken).ConfigureAwait(false);
}, cancellationToken).ConfigureAwait(false));
CustomizeCommand(ref command);
return command;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ internal static partial class AgentsCreateAgentSessionAsStreamCommandApiCommand
Hidden = true,
};

static partial void CustomizeCommand(ref Command command);

public static Command Create()
{
var command = new Command(@"create-agent-session-as-stream", @"Create an agent session
Expand Down Expand Up @@ -117,6 +119,7 @@ await CliRuntime.WriteResponseLineAsync(
cancellationToken: cancellationToken).ConfigureAwait(false);
}
}, cancellationToken).ConfigureAwait(false));
CustomizeCommand(ref command);
return command;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,22 @@ internal static partial class AgentsCreateAgentSessionCommandApiCommand
Description = "Path to a JSON request file, or '-' for stdin.",
Hidden = true,
};
private static Option<bool> Wait { get; } = new("--wait")
{
Description = "Poll the generated wait helper until the resource reaches a terminal state.",
};

private static Option<string> PollInterval { get; } = new("--poll-interval")
{
Description = "Polling interval, for example 250ms, 2s, 30m, or 01:00:00.",
DefaultValueFactory = _ => "2s",
};

private static Option<string> WaitTimeout { get; } = new("--wait-timeout")
{
Description = "Maximum time to wait before timing out, for example 30m or 00:30:00.",
DefaultValueFactory = _ => "30m",
};

private static string FormatResponse(ParseResult parseResult, global::tryAGI.OpenAI.SessionResource value, global::System.Text.Json.Serialization.JsonSerializerContext context, bool truncateLongStrings)
{
Expand All @@ -65,6 +81,8 @@ private static string FormatResponse(ParseResult parseResult, global::tryAGI.Ope
static partial void CustomizeResponseFormatHints(Dictionary<string, CliFormatHint> hints);


static partial void CustomizeCommand(ref Command command);

public static Command Create()
{
var command = new Command(@"create-agent-session", @"Create an agent session
Expand All @@ -88,7 +106,9 @@ public static Command Create()
result.AddError(@"Specify at most one of --request-input, --request-json, or --request-file.");
}
});

command.Options.Add(Wait);
command.Options.Add(PollInterval);
command.Options.Add(WaitTimeout);
command.SetAction(async (ParseResult parseResult, CancellationToken cancellationToken) =>
await CliRuntime.RunAsync(async () =>
{
Expand All @@ -115,9 +135,44 @@ await CliRuntime.RunAsync(async () =>
Instructions = agentInstructions,

}
: __AgentBase;
: __AgentBase; var wait = parseResult.GetValue(Wait);
var pollInterval = wait ? CliRuntime.ParseDuration(parseResult.GetRequiredValue(PollInterval), PollInterval.Name) : default;
var waitTimeout = wait ? CliRuntime.ParseDuration(parseResult.GetRequiredValue(WaitTimeout), WaitTimeout.Name) : default;
using var client = await CliRuntime.CreateClientAsync(parseResult, cancellationToken).ConfigureAwait(false);

if (wait)
{
var createResponse = await client.Agents.CreateAgentSessionAsync(
metadata: metadata,
environment: environment,
input: input,
agentId: agentId,
vaultIds: vaultIds,
agent: agent,
cancellationToken: cancellationToken).ConfigureAwait(false);
var resourceId = global::System.Convert.ToString(
createResponse.Id,
global::System.Globalization.CultureInfo.InvariantCulture);
if (string.IsNullOrWhiteSpace(resourceId))
{
throw new CliException("The create response did not contain a job id.");
}

var waitResponse = await CliRuntime.PollUntilTerminalAsync(
fetchAsync: token => client.Agents.RetrieveAgentSessionAsync(
sessionId: resourceId,
cancellationToken: token),
pollInterval: pollInterval,
waitTimeout: waitTimeout,
context: global::tryAGI.OpenAI.SourceGenerationContext.Default,
cancellationToken: cancellationToken).ConfigureAwait(false);
await CliRuntime.WriteResponseAsync(
parseResult,
waitResponse,
global::tryAGI.OpenAI.SourceGenerationContext.Default,
cancellationToken: cancellationToken).ConfigureAwait(false);
return;
}

var response = await client.Agents.CreateAgentSessionAsync(
metadata: metadata,
Expand All @@ -136,6 +191,7 @@ await CliRuntime.WriteResponseAsync(
FormatResponse,
cancellationToken).ConfigureAwait(false);
}, cancellationToken).ConfigureAwait(false));
CustomizeCommand(ref command);
return command;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ internal static partial class AgentsCreateAgentSessionEventsCommandApiCommand
Required = true,
};

static partial void CustomizeCommand(ref Command command);

public static Command Create()
{
var command = new Command(@"create-agent-session-events", @"Create agent session input events
Expand All @@ -52,6 +54,7 @@ await client.Agents.CreateAgentSessionEventsAsync(

await CliRuntime.WriteSuccessAsync(parseResult, cancellationToken).ConfigureAwait(false);
}, cancellationToken).ConfigureAwait(false));
CustomizeCommand(ref command);
return command;
}
}
Loading
Loading