- ClawdDotNet.Web: Kestrel im Prozess der Anwendung, Token-Absicherung (TokenGate mit FixedTimeEquals), Endpunkte unter /api, Ereignisstrom unter /events (Server-Sent Events) und fortlaufendes Log-Streaming. - Weboberflaeche (wwwroot/): Vollstaendiges Single-Page-Frontend mit nativem HTML5, CSS3 und ES-Modulen ohne Buildschritt (strikt textContent, #-Routing, sofortiger Login-Sprung bei fehlendem Token, Light/Dark-Theme, lokale Barlow-Schriften). - ClawdDotNet.App: Fachlogik aus den Avalonia-ViewModels in Dienste herausgeloest (AgentAdministration, JobAdministration, ServiceAdministration, RunCoordinator) und ueber InstanceChange synchronisiert. - Tests: ClawdDotNet.Web.Tests und ClawdDotNet.App.Tests hinzugefuegt, alle 684 Tests erfolgreich.
This commit is contained in:
@@ -0,0 +1,177 @@
|
||||
namespace ClawdDotNet.Web.Contracts;
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
// Die Übertragungstypen der Weboberfläche.
|
||||
//
|
||||
// Warum es sie gibt, statt die Kerntypen zu serialisieren:
|
||||
//
|
||||
// 1. AgentConfig trägt Zugangsdaten. Ein `return agent;` hätte den
|
||||
// Werkzeug-Konfigurationsbaum samt Passwörtern ins Netz geschickt — die Sorte
|
||||
// Fehler, die niemandem auffällt, weil alles funktioniert.
|
||||
// 2. Die Kerntypen ändern sich mit dem Kern. Ein neues Feld in TaskItem wäre sonst
|
||||
// still eine API-Änderung, auf die sich jemand verlassen hat.
|
||||
// 3. Die Grenze soll einen Prozesswechsel überstehen (siehe WebUiHost). Über eine
|
||||
// Prozessgrenze geht nur, was hier steht.
|
||||
//
|
||||
// Namen auf Englisch in camelCase wie im übrigen Code; die Beschreibungen auf Deutsch.
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
/// <summary>Antwort auf einen verwaltenden Aufruf — dieselbe Form wie <c>AdminResult</c>.</summary>
|
||||
public sealed record OutcomeDto(bool Ok, string Message);
|
||||
|
||||
/// <summary>Version, Bau und Instanz. Was auf der Info-Seite steht.</summary>
|
||||
public sealed record InfoDto(
|
||||
string AppVersion,
|
||||
string BuildSummary,
|
||||
string InstanceId,
|
||||
string InstanceName,
|
||||
bool EngineActive,
|
||||
bool SchedulerActive,
|
||||
bool StagingActive,
|
||||
bool DeploymentcenterActive);
|
||||
|
||||
/// <summary>Erreichbarkeit und Guthaben bei OpenRouter.</summary>
|
||||
public sealed record StatusDto(
|
||||
bool ApiReachable,
|
||||
string StatusText,
|
||||
string CreditsText,
|
||||
double? CreditBalance,
|
||||
double? CreditRemaining);
|
||||
|
||||
/// <summary>Ein Agent, ohne alles, was ein Zugangsdatum sein könnte.</summary>
|
||||
public sealed record AgentDto(
|
||||
string AgentId,
|
||||
string DisplayName,
|
||||
string Model,
|
||||
string Description,
|
||||
string PromptCaching,
|
||||
int MaxToolResultChars,
|
||||
int MaxSteps,
|
||||
int MaxContextTokens,
|
||||
int TimeoutSeconds,
|
||||
decimal DailyCostUsd,
|
||||
long DailyTokens,
|
||||
bool IsRunning,
|
||||
IReadOnlyList<AgentToolDto> Tools);
|
||||
|
||||
/// <summary>
|
||||
/// Ein Werkzeug am Agenten. <b>Ohne die Einstellungen</b> — die stehen in einem freien
|
||||
/// Wörterbuch und enthalten regelmäßig Passwörter und Schlüssel. Was einstellbar ist und
|
||||
/// ob etwas gesetzt ist, sagt <see cref="ToolSettingsDto"/>.
|
||||
/// </summary>
|
||||
public sealed record AgentToolDto(string Name, string Description, bool Enabled);
|
||||
|
||||
/// <summary>
|
||||
/// Die Einstellungen eines Werkzeugs, maskiert.
|
||||
///
|
||||
/// <para>Ein Wert, dessen Name ein Zugangsdatum bezeichnet, kommt nie heraus. Statt
|
||||
/// seiner steht in <see cref="Secrets"/>, ob überhaupt etwas gesetzt ist — mehr braucht
|
||||
/// eine Anzeige nicht, und mehr darf sie nicht wissen.</para>
|
||||
/// </summary>
|
||||
public sealed record ToolSettingsDto(
|
||||
string Name,
|
||||
IReadOnlyDictionary<string, object?> Values,
|
||||
IReadOnlyDictionary<string, bool> Secrets);
|
||||
|
||||
/// <summary>Eine Zeile im Chatverlauf.</summary>
|
||||
public sealed record ChatEntryDto(
|
||||
string Role,
|
||||
string Content,
|
||||
DateTime Timestamp,
|
||||
string? Source);
|
||||
|
||||
/// <summary>Was der Browser schickt, wenn jemand etwas in den Chat tippt.</summary>
|
||||
public sealed record SendMessageDto(string Message);
|
||||
|
||||
/// <summary>Ein geplanter Lauf.</summary>
|
||||
public sealed record JobDto(
|
||||
string Kind,
|
||||
string JobId,
|
||||
string AgentId,
|
||||
string AgentName,
|
||||
string ToolName,
|
||||
string Cron,
|
||||
string Message,
|
||||
bool RunOnStart,
|
||||
DateTime? NextRunUtc,
|
||||
DateTime? LastRunLocal,
|
||||
bool CronValid,
|
||||
bool Enabled);
|
||||
|
||||
/// <summary>Was einen geplanten Lauf ausmacht — beim Anlegen wie beim Ändern.</summary>
|
||||
public sealed record JobInputDto(
|
||||
string AgentId,
|
||||
string Kind,
|
||||
string ToolName = "",
|
||||
string JobTypeId = "",
|
||||
string Cron = "",
|
||||
string TaskMessage = "",
|
||||
bool RunOnStart = false);
|
||||
|
||||
/// <summary>Ein Dienst der Instanz.</summary>
|
||||
public sealed record ServiceDto(
|
||||
string ServiceId,
|
||||
string Name,
|
||||
string Type,
|
||||
int Port,
|
||||
bool Enabled,
|
||||
bool BuiltIn,
|
||||
string Description);
|
||||
|
||||
/// <summary>Was einen neuen Dienst ausmacht.</summary>
|
||||
public sealed record ServiceInputDto(string Name, string Type, int Port, string Description = "");
|
||||
|
||||
/// <summary>Ein neuer Agent.</summary>
|
||||
public sealed record NewAgentDto(string AgentId, string DisplayName, string Model, string Description = "");
|
||||
|
||||
/// <summary>Eine Aufgabe vom Taskboard.</summary>
|
||||
public sealed record TaskDto(
|
||||
string Id,
|
||||
string Title,
|
||||
string Status,
|
||||
string Type,
|
||||
int Priority,
|
||||
string Assignee,
|
||||
bool RequireApproval,
|
||||
string Acceptance,
|
||||
IReadOnlyList<string> BlockedBy,
|
||||
string Body,
|
||||
DateTime CreatedAt,
|
||||
DateTime UpdatedAt);
|
||||
|
||||
/// <summary>Ein eingefrorener Aufruf, der auf Freigabe wartet.</summary>
|
||||
public sealed record StagedCallDto(
|
||||
long Id,
|
||||
string RunId,
|
||||
string AgentId,
|
||||
string Tool,
|
||||
string? Action,
|
||||
string Proposal,
|
||||
string Status,
|
||||
string ArgumentsJson);
|
||||
|
||||
/// <summary>Warum ein Vorschlag abgelehnt wurde.</summary>
|
||||
public sealed record RejectDto(string Reason);
|
||||
|
||||
/// <summary>
|
||||
/// Ein Lauf mit dem, was er gekostet hat.
|
||||
///
|
||||
/// <para><see cref="CostIsKnown"/> ist nicht schmückendes Beiwerk: Ohne geladene
|
||||
/// Preisliste steht in <see cref="CostUsd"/> eine Null, die „kostenlos" heißen könnte
|
||||
/// und „unbekannt" heißt. Eine Anzeige, die das nicht unterscheidet, lügt.</para>
|
||||
/// </summary>
|
||||
public sealed record UsageDto(
|
||||
long Id,
|
||||
string AgentId,
|
||||
string Model,
|
||||
int PromptTokens,
|
||||
int CompletionTokens,
|
||||
int CachedTokens,
|
||||
decimal CostUsd,
|
||||
bool CostIsKnown,
|
||||
string Status,
|
||||
int StepCount,
|
||||
DateTime OccurredAt);
|
||||
|
||||
/// <summary>Eine Protokollzeile.</summary>
|
||||
public sealed record LogLineDto(string Module, string Level, string Text);
|
||||
Reference in New Issue
Block a user