Files
ClawdDotNet/src/ClawdDotNet.Core/Runtimes/RuntimeConfig.cs
T

101 lines
3.9 KiB
C#

using System.Text.Json.Serialization;
namespace ClawdDotNet.Core.Runtimes;
/// <summary>#712: The runtimes an agent can work in.</summary>
public static class RuntimeKinds
{
/// <summary>Our engine with OpenRouter — the default, everything but programming.</summary>
public const string Native = "native";
/// <summary>Claude Code in headless mode, in the sandbox.</summary>
public const string ClaudeCode = "claude-code";
/// <summary>A program whose output is the result, in the sandbox.</summary>
public const string Command = "command";
public static readonly IReadOnlyList<string> All = [Native, ClaudeCode, Command];
public static bool IsKnown(string? kind) => All.Contains(Normalize(kind));
public static string Normalize(string? kind)
=> string.IsNullOrWhiteSpace(kind) ? Native : kind.Trim().ToLowerInvariant();
}
/// <summary>
/// #712: In which runtime an agent works (<c>runtime</c> in its configuration). Without it,
/// the agent is native, as before.
/// </summary>
public sealed class AgentRuntimeConfig
{
[JsonPropertyName("kind")]
public string Kind { get; set; } = RuntimeKinds.Native;
/// <summary>
/// Claude Code: the tools it may use without asking. Empty: <see cref="ClaudeCodeRuntime.DefaultAllowedTools"/>.
/// Anything not listed is denied — there is no one to ask.
/// </summary>
[JsonPropertyName("allowedTools")]
public List<string> AllowedTools { get; set; } = [];
/// <summary>Claude Code: the most turns of one run.</summary>
[JsonPropertyName("maxTurns")]
public int MaxTurns { get; set; } = 30;
[JsonPropertyName("timeoutMinutes")]
public int TimeoutMinutes { get; set; } = 30;
/// <summary>Command: the program — absolute, on the sandbox's PATH, or relative to the workspace.</summary>
[JsonPropertyName("command")]
public string Command { get; set; } = "";
[JsonPropertyName("arguments")]
public List<string> Arguments { get; set; } = [];
/// <summary>Hosts the run may reach beyond what the runtime itself needs.</summary>
[JsonPropertyName("egress")]
public List<string> Egress { get; set; } = [];
[JsonIgnore]
public bool IsForeign => RuntimeKinds.Normalize(Kind) != RuntimeKinds.Native;
[JsonIgnore]
public TimeSpan Timeout => TimeSpan.FromMinutes(Math.Clamp(TimeoutMinutes, 1, 240));
}
/// <summary>
/// #712: The Claude Code account of the instance (<c>claudeCode</c> in <c>instance.json</c>).
///
/// <para><b>Two ways to sign in, deliberately.</b> Whether an automated agent system may run
/// on a consumer subscription is not settled, and a subscription shares its quota with the
/// human who owns it. The API key is the default; the subscription (a token from
/// <c>claude setup-token</c>) is a matter of configuration, not of rebuilding.</para>
/// </summary>
public sealed class ClaudeCodeSettings
{
public const string ApiKeyAuth = "api-key";
public const string SubscriptionAuth = "subscription";
/// <summary>The <c>claude</c> program; empty: looked for in the usual places.</summary>
[JsonPropertyName("executable")]
public string Executable { get; set; } = "";
[JsonPropertyName("auth")]
public string Auth { get; set; } = ApiKeyAuth;
/// <summary>An Anthropic API key — best one of its own, with a spending limit.</summary>
[JsonPropertyName("apiKey")]
public string ApiKey { get; set; } = "";
/// <summary>A subscription's token from <c>claude setup-token</c>.</summary>
[JsonPropertyName("oauthToken")]
public string OAuthToken { get; set; } = "";
/// <summary>Further read-only host paths the program needs — Node and a package directory for an npm install.</summary>
[JsonPropertyName("readOnlyPaths")]
public List<string> ReadOnlyPaths { get; set; } = [];
[JsonIgnore]
public bool OnSubscription => string.Equals(Auth, SubscriptionAuth, StringComparison.OrdinalIgnoreCase);
}