feat: ship agent-first mission control v0.2.57
This commit is contained in:
@@ -0,0 +1,135 @@
|
||||
namespace Nexus.Api.Data;
|
||||
|
||||
/// <summary>
|
||||
/// Durable, secret-free proposal for creating one OpenClaw-owned agent.
|
||||
/// Nexus owns the approval workflow only; the resulting agent remains owned by
|
||||
/// OpenClaw.
|
||||
/// </summary>
|
||||
public sealed class AgentProposal
|
||||
{
|
||||
public Guid Id { get; init; } = Guid.NewGuid();
|
||||
public required string Source { get; set; }
|
||||
public required string RequestedName { get; set; }
|
||||
public required string RequestedAgentId { get; set; }
|
||||
public string? Role { get; set; }
|
||||
public string? Description { get; set; }
|
||||
public string? Model { get; set; }
|
||||
public string? Emoji { get; set; }
|
||||
public string? Avatar { get; set; }
|
||||
public required string Workspace { get; set; }
|
||||
public required string StandardFilesJson { get; set; }
|
||||
public required string StandardFilesHash { get; set; }
|
||||
public string Status { get; set; } = AgentProposalStates.AwaitingApproval;
|
||||
public required string RequestedBy { get; set; }
|
||||
public string? ApprovedBy { get; set; }
|
||||
public string? RejectedBy { get; set; }
|
||||
public string? RejectionReason { get; set; }
|
||||
public string? OpenClawAgentId { get; set; }
|
||||
public string? OpenClawWorkspace { get; set; }
|
||||
public string? LastErrorCode { get; set; }
|
||||
public string? LastErrorMessage { get; set; }
|
||||
public int Revision { get; set; } = 1;
|
||||
public DateTimeOffset CreatedAt { get; set; } = DateTimeOffset.UtcNow;
|
||||
public DateTimeOffset UpdatedAt { get; set; } = DateTimeOffset.UtcNow;
|
||||
public DateTimeOffset? ApprovedAt { get; set; }
|
||||
public DateTimeOffset? RejectedAt { get; set; }
|
||||
public DateTimeOffset? CompletedAt { get; set; }
|
||||
public ICollection<AgentProvisionRequest> ProvisionRequests { get; set; } =
|
||||
new List<AgentProvisionRequest>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// One explicitly authorized provisioning attempt. A request that reached the
|
||||
/// dispatch boundary is never silently re-queued after a restart.
|
||||
/// </summary>
|
||||
public sealed class AgentProvisionRequest
|
||||
{
|
||||
public Guid Id { get; init; } = Guid.NewGuid();
|
||||
public Guid ProposalId { get; set; }
|
||||
public AgentProposal Proposal { get; set; } = null!;
|
||||
public int Attempt { get; set; }
|
||||
public required string Stage { get; set; }
|
||||
public string Status { get; set; } = AgentProvisionRequestStates.Queued;
|
||||
public required string IdempotencyKeyHash { get; set; }
|
||||
public required string Actor { get; set; }
|
||||
public required string CorrelationId { get; set; }
|
||||
public string? TraceParent { get; set; }
|
||||
public string? OpenClawAgentId { get; set; }
|
||||
public string? LastErrorCode { get; set; }
|
||||
public string? LastErrorMessage { get; set; }
|
||||
public string? LeaseOwner { get; set; }
|
||||
public DateTimeOffset? LeaseUntil { get; set; }
|
||||
public int Revision { get; set; } = 1;
|
||||
public DateTimeOffset CreatedAt { get; set; } = DateTimeOffset.UtcNow;
|
||||
public DateTimeOffset UpdatedAt { get; set; } = DateTimeOffset.UtcNow;
|
||||
public DateTimeOffset? DispatchStartedAt { get; set; }
|
||||
public DateTimeOffset? CompletedAt { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Hash-only idempotency claim. Raw idempotency keys and request content are
|
||||
/// deliberately not persisted.
|
||||
/// </summary>
|
||||
public sealed class OperationClaim
|
||||
{
|
||||
public Guid Id { get; init; } = Guid.NewGuid();
|
||||
public required string Operation { get; set; }
|
||||
public required string IdempotencyKeyHash { get; set; }
|
||||
public required string RequestHash { get; set; }
|
||||
public Guid? ResourceId { get; set; }
|
||||
public required string State { get; set; }
|
||||
public string? ResultCode { get; set; }
|
||||
public DateTimeOffset CreatedAt { get; set; } = DateTimeOffset.UtcNow;
|
||||
public DateTimeOffset? CompletedAt { get; set; }
|
||||
public DateTimeOffset ExpiresAt { get; set; } =
|
||||
DateTimeOffset.UtcNow.AddDays(7);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Transactional, content-minimized domain event. The payload may contain
|
||||
/// identifiers and states, but never proposal markdown or credentials.
|
||||
/// </summary>
|
||||
public sealed class OutboxEvent
|
||||
{
|
||||
public long Sequence { get; init; }
|
||||
public Guid EventId { get; init; } = Guid.NewGuid();
|
||||
public required string Type { get; set; }
|
||||
public required string AggregateType { get; set; }
|
||||
public required string AggregateId { get; set; }
|
||||
public int AggregateRevision { get; set; }
|
||||
public required string PayloadJson { get; set; }
|
||||
public DateTimeOffset OccurredAt { get; set; } = DateTimeOffset.UtcNow;
|
||||
public DateTimeOffset? PublishedAt { get; set; }
|
||||
public int PublishAttempts { get; set; }
|
||||
public string? LastErrorCode { get; set; }
|
||||
}
|
||||
|
||||
public static class AgentProposalStates
|
||||
{
|
||||
public const string Draft = "draft";
|
||||
public const string AwaitingApproval = "awaiting_approval";
|
||||
public const string Provisioning = "provisioning";
|
||||
public const string Ready = "ready";
|
||||
public const string Partial = "partial";
|
||||
public const string Failed = "failed";
|
||||
public const string InDoubt = "in_doubt";
|
||||
public const string Rejected = "rejected";
|
||||
}
|
||||
|
||||
public static class AgentProvisionStages
|
||||
{
|
||||
public const string CreateAgent = "create_agent";
|
||||
public const string ReconcileAgent = "reconcile_agent";
|
||||
public const string FinalizeFiles = "finalize_files";
|
||||
}
|
||||
|
||||
public static class AgentProvisionRequestStates
|
||||
{
|
||||
public const string Queued = "queued";
|
||||
public const string Dispatching = "dispatching";
|
||||
public const string Completed = "completed";
|
||||
public const string Failed = "failed";
|
||||
public const string Partial = "partial";
|
||||
public const string InDoubt = "in_doubt";
|
||||
public const string Blocked = "blocked";
|
||||
}
|
||||
+552
@@ -0,0 +1,552 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using Nexus.Api.Data;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Nexus.Api.Migrations
|
||||
{
|
||||
[DbContext(typeof(NexusDbContext))]
|
||||
[Migration("20260730130442_AddOpenClawRunProjection")]
|
||||
partial class AddOpenClawRunProjection
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasAnnotation("ProductVersion", "10.0.8")
|
||||
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||
|
||||
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||
|
||||
modelBuilder.Entity("Nexus.Api.Data.ActivityEvent", b =>
|
||||
{
|
||||
b.Property<long>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("bigint");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<long>("Id"));
|
||||
|
||||
b.Property<DateTimeOffset>("CreatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("Message")
|
||||
.IsRequired()
|
||||
.HasMaxLength(1000)
|
||||
.HasColumnType("character varying(1000)");
|
||||
|
||||
b.Property<Guid?>("TaskId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("Type")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("CreatedAt");
|
||||
|
||||
b.HasIndex("TaskId");
|
||||
|
||||
b.ToTable("Activity");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Nexus.Api.Data.NexusUser", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<DateTimeOffset>("CreatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("DisplayName")
|
||||
.IsRequired()
|
||||
.HasMaxLength(100)
|
||||
.HasColumnType("character varying(100)");
|
||||
|
||||
b.Property<string>("Email")
|
||||
.IsRequired()
|
||||
.HasMaxLength(120)
|
||||
.HasColumnType("character varying(120)");
|
||||
|
||||
b.Property<DateTimeOffset?>("LastLoginAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("NormalizedEmail")
|
||||
.IsRequired()
|
||||
.HasMaxLength(120)
|
||||
.HasColumnType("character varying(120)");
|
||||
|
||||
b.Property<string>("PasswordHash")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Role")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<DateTimeOffset>("UpdatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("NormalizedEmail")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("Users");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Nexus.Api.Data.Notification", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<DateTimeOffset>("CreatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("ForUser")
|
||||
.IsRequired()
|
||||
.HasMaxLength(60)
|
||||
.HasColumnType("character varying(60)");
|
||||
|
||||
b.Property<bool>("IsRead")
|
||||
.HasColumnType("boolean");
|
||||
|
||||
b.Property<string>("Message")
|
||||
.HasMaxLength(1000)
|
||||
.HasColumnType("character varying(1000)");
|
||||
|
||||
b.Property<Guid?>("TaskId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("Title")
|
||||
.IsRequired()
|
||||
.HasMaxLength(240)
|
||||
.HasColumnType("character varying(240)");
|
||||
|
||||
b.Property<string>("Type")
|
||||
.IsRequired()
|
||||
.HasMaxLength(60)
|
||||
.HasColumnType("character varying(60)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("ForUser", "IsRead", "CreatedAt");
|
||||
|
||||
b.ToTable("Notifications");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Nexus.Api.Data.OpenClawRun", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("Actor")
|
||||
.IsRequired()
|
||||
.HasMaxLength(240)
|
||||
.HasColumnType("character varying(240)");
|
||||
|
||||
b.Property<string>("AgentId")
|
||||
.IsRequired()
|
||||
.HasMaxLength(200)
|
||||
.HasColumnType("character varying(200)");
|
||||
|
||||
b.Property<string>("CorrelationId")
|
||||
.IsRequired()
|
||||
.HasMaxLength(200)
|
||||
.HasColumnType("character varying(200)");
|
||||
|
||||
b.Property<DateTimeOffset>("CreatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<DateTimeOffset?>("FinishedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("LastError")
|
||||
.HasMaxLength(2000)
|
||||
.HasColumnType("character varying(2000)");
|
||||
|
||||
b.Property<long?>("LastGatewaySequence")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.Property<string>("OpenClawRunId")
|
||||
.HasMaxLength(240)
|
||||
.HasColumnType("character varying(240)");
|
||||
|
||||
b.Property<Guid?>("ProjectId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("Prompt")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<Guid?>("RetriedFromRunId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<int>("Revision")
|
||||
.IsConcurrencyToken()
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<bool>("SequenceGapDetected")
|
||||
.HasColumnType("boolean");
|
||||
|
||||
b.Property<string>("SessionKey")
|
||||
.IsRequired()
|
||||
.HasMaxLength(500)
|
||||
.HasColumnType("character varying(500)");
|
||||
|
||||
b.Property<string>("StartIdempotencyKey")
|
||||
.IsRequired()
|
||||
.HasMaxLength(200)
|
||||
.HasColumnType("character varying(200)");
|
||||
|
||||
b.Property<DateTimeOffset?>("StartedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("Status")
|
||||
.IsRequired()
|
||||
.HasMaxLength(40)
|
||||
.HasColumnType("character varying(40)");
|
||||
|
||||
b.Property<Guid?>("TaskId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("Title")
|
||||
.IsRequired()
|
||||
.HasMaxLength(160)
|
||||
.HasColumnType("character varying(160)");
|
||||
|
||||
b.Property<string>("TraceParent")
|
||||
.HasMaxLength(128)
|
||||
.HasColumnType("character varying(128)");
|
||||
|
||||
b.Property<DateTimeOffset>("UpdatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("OpenClawRunId")
|
||||
.IsUnique();
|
||||
|
||||
b.HasIndex("ProjectId");
|
||||
|
||||
b.HasIndex("RetriedFromRunId");
|
||||
|
||||
b.HasIndex("SessionKey");
|
||||
|
||||
b.HasIndex("StartIdempotencyKey")
|
||||
.IsUnique();
|
||||
|
||||
b.HasIndex("TaskId");
|
||||
|
||||
b.HasIndex("Status", "UpdatedAt");
|
||||
|
||||
b.ToTable("OpenClawRuns");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Nexus.Api.Data.OpenClawRunHistory", b =>
|
||||
{
|
||||
b.Property<long>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("bigint");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<long>("Id"));
|
||||
|
||||
b.Property<string>("Action")
|
||||
.IsRequired()
|
||||
.HasMaxLength(80)
|
||||
.HasColumnType("character varying(80)");
|
||||
|
||||
b.Property<string>("Actor")
|
||||
.IsRequired()
|
||||
.HasMaxLength(240)
|
||||
.HasColumnType("character varying(240)");
|
||||
|
||||
b.Property<string>("CorrelationId")
|
||||
.IsRequired()
|
||||
.HasMaxLength(200)
|
||||
.HasColumnType("character varying(200)");
|
||||
|
||||
b.Property<string>("FromStatus")
|
||||
.IsRequired()
|
||||
.HasMaxLength(40)
|
||||
.HasColumnType("character varying(40)");
|
||||
|
||||
b.Property<string>("GatewayEventId")
|
||||
.HasMaxLength(120)
|
||||
.HasColumnType("character varying(120)");
|
||||
|
||||
b.Property<long?>("GatewaySequence")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.Property<string>("IdempotencyKey")
|
||||
.HasMaxLength(200)
|
||||
.HasColumnType("character varying(200)");
|
||||
|
||||
b.Property<string>("Message")
|
||||
.IsRequired()
|
||||
.HasMaxLength(2000)
|
||||
.HasColumnType("character varying(2000)");
|
||||
|
||||
b.Property<DateTimeOffset>("OccurredAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<Guid?>("ResultRunId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<Guid>("RunId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<bool>("SequenceGapDetected")
|
||||
.HasColumnType("boolean");
|
||||
|
||||
b.Property<string>("ToStatus")
|
||||
.IsRequired()
|
||||
.HasMaxLength(40)
|
||||
.HasColumnType("character varying(40)");
|
||||
|
||||
b.Property<string>("TraceParent")
|
||||
.HasMaxLength(128)
|
||||
.HasColumnType("character varying(128)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("GatewayEventId")
|
||||
.IsUnique();
|
||||
|
||||
b.HasIndex("RunId", "OccurredAt");
|
||||
|
||||
b.HasIndex("RunId", "Action", "IdempotencyKey")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("OpenClawRunHistory");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Nexus.Api.Data.Project", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("Description")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasMaxLength(160)
|
||||
.HasColumnType("character varying(160)");
|
||||
|
||||
b.Property<int>("Progress")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<int>("Status")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<DateTimeOffset>("UpdatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("Projects");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Nexus.Api.Data.RefreshToken", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<Guid>("ConcurrencyStamp")
|
||||
.IsConcurrencyToken()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<DateTimeOffset>("CreatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<DateTimeOffset>("ExpiresAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<Guid>("FamilyId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("ReplacedByTokenHash")
|
||||
.HasMaxLength(64)
|
||||
.HasColumnType("character varying(64)");
|
||||
|
||||
b.Property<DateTimeOffset?>("RevokedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("TokenHash")
|
||||
.IsRequired()
|
||||
.HasMaxLength(64)
|
||||
.HasColumnType("character varying(64)");
|
||||
|
||||
b.Property<Guid>("UserId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("TokenHash")
|
||||
.IsUnique();
|
||||
|
||||
b.HasIndex("UserId", "FamilyId");
|
||||
|
||||
b.ToTable("RefreshTokens");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Nexus.Api.Data.SeedAudit", b =>
|
||||
{
|
||||
b.Property<string>("Key")
|
||||
.HasMaxLength(80)
|
||||
.HasColumnType("character varying(80)");
|
||||
|
||||
b.Property<DateTimeOffset>("CreatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.HasKey("Key");
|
||||
|
||||
b.ToTable("SeedAudit");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Nexus.Api.Data.WorkTask", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("AssignedTo")
|
||||
.HasMaxLength(60)
|
||||
.HasColumnType("character varying(60)");
|
||||
|
||||
b.Property<DateTimeOffset>("CreatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("Detail")
|
||||
.HasMaxLength(2000)
|
||||
.HasColumnType("character varying(2000)");
|
||||
|
||||
b.Property<DateTimeOffset?>("DueDate")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("ExpectedFrom")
|
||||
.HasMaxLength(60)
|
||||
.HasColumnType("character varying(60)");
|
||||
|
||||
b.Property<bool>("IsAgentTask")
|
||||
.HasColumnType("boolean");
|
||||
|
||||
b.Property<Guid?>("ParentTaskId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("Priority")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<Guid?>("ProjectId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("Source")
|
||||
.IsRequired()
|
||||
.HasMaxLength(60)
|
||||
.HasColumnType("character varying(60)");
|
||||
|
||||
b.Property<string>("State")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Title")
|
||||
.IsRequired()
|
||||
.HasMaxLength(240)
|
||||
.HasColumnType("character varying(240)");
|
||||
|
||||
b.Property<DateTimeOffset>("UpdatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("AssignedTo");
|
||||
|
||||
b.HasIndex("ExpectedFrom");
|
||||
|
||||
b.HasIndex("IsAgentTask");
|
||||
|
||||
b.HasIndex("ParentTaskId");
|
||||
|
||||
b.HasIndex("Source");
|
||||
|
||||
b.ToTable("Tasks");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Nexus.Api.Data.OpenClawRun", b =>
|
||||
{
|
||||
b.HasOne("Nexus.Api.Data.Project", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("ProjectId")
|
||||
.OnDelete(DeleteBehavior.SetNull);
|
||||
|
||||
b.HasOne("Nexus.Api.Data.WorkTask", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("TaskId")
|
||||
.OnDelete(DeleteBehavior.SetNull);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Nexus.Api.Data.OpenClawRunHistory", b =>
|
||||
{
|
||||
b.HasOne("Nexus.Api.Data.OpenClawRun", "Run")
|
||||
.WithMany("History")
|
||||
.HasForeignKey("RunId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Run");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Nexus.Api.Data.RefreshToken", b =>
|
||||
{
|
||||
b.HasOne("Nexus.Api.Data.NexusUser", "User")
|
||||
.WithMany("RefreshTokens")
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("User");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Nexus.Api.Data.WorkTask", b =>
|
||||
{
|
||||
b.HasOne("Nexus.Api.Data.WorkTask", "ParentTask")
|
||||
.WithMany("ChildTasks")
|
||||
.HasForeignKey("ParentTaskId")
|
||||
.OnDelete(DeleteBehavior.SetNull);
|
||||
|
||||
b.Navigation("ParentTask");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Nexus.Api.Data.NexusUser", b =>
|
||||
{
|
||||
b.Navigation("RefreshTokens");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Nexus.Api.Data.OpenClawRun", b =>
|
||||
{
|
||||
b.Navigation("History");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Nexus.Api.Data.WorkTask", b =>
|
||||
{
|
||||
b.Navigation("ChildTasks");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,156 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Nexus.Api.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class AddOpenClawRunProjection : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: "OpenClawRuns",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
Title = table.Column<string>(type: "character varying(160)", maxLength: 160, nullable: false),
|
||||
Prompt = table.Column<string>(type: "text", nullable: false),
|
||||
AgentId = table.Column<string>(type: "character varying(200)", maxLength: 200, nullable: false),
|
||||
SessionKey = table.Column<string>(type: "character varying(500)", maxLength: 500, nullable: false),
|
||||
Status = table.Column<string>(type: "character varying(40)", maxLength: 40, nullable: false),
|
||||
TaskId = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
ProjectId = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
OpenClawRunId = table.Column<string>(type: "character varying(240)", maxLength: 240, nullable: true),
|
||||
RetriedFromRunId = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
StartIdempotencyKey = table.Column<string>(type: "character varying(200)", maxLength: 200, nullable: false),
|
||||
CorrelationId = table.Column<string>(type: "character varying(200)", maxLength: 200, nullable: false),
|
||||
Actor = table.Column<string>(type: "character varying(240)", maxLength: 240, nullable: false),
|
||||
TraceParent = table.Column<string>(type: "character varying(128)", maxLength: 128, nullable: true),
|
||||
LastError = table.Column<string>(type: "character varying(2000)", maxLength: 2000, nullable: true),
|
||||
LastGatewaySequence = table.Column<long>(type: "bigint", nullable: true),
|
||||
SequenceGapDetected = table.Column<bool>(type: "boolean", nullable: false),
|
||||
Revision = table.Column<int>(type: "integer", nullable: false),
|
||||
CreatedAt = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false),
|
||||
UpdatedAt = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false),
|
||||
StartedAt = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true),
|
||||
FinishedAt = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_OpenClawRuns", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_OpenClawRuns_Projects_ProjectId",
|
||||
column: x => x.ProjectId,
|
||||
principalTable: "Projects",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
table.ForeignKey(
|
||||
name: "FK_OpenClawRuns_Tasks_TaskId",
|
||||
column: x => x.TaskId,
|
||||
principalTable: "Tasks",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "OpenClawRunHistory",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<long>(type: "bigint", nullable: false)
|
||||
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
|
||||
RunId = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
Action = table.Column<string>(type: "character varying(80)", maxLength: 80, nullable: false),
|
||||
FromStatus = table.Column<string>(type: "character varying(40)", maxLength: 40, nullable: false),
|
||||
ToStatus = table.Column<string>(type: "character varying(40)", maxLength: 40, nullable: false),
|
||||
Message = table.Column<string>(type: "character varying(2000)", maxLength: 2000, nullable: false),
|
||||
Actor = table.Column<string>(type: "character varying(240)", maxLength: 240, nullable: false),
|
||||
CorrelationId = table.Column<string>(type: "character varying(200)", maxLength: 200, nullable: false),
|
||||
IdempotencyKey = table.Column<string>(type: "character varying(200)", maxLength: 200, nullable: true),
|
||||
TraceParent = table.Column<string>(type: "character varying(128)", maxLength: 128, nullable: true),
|
||||
GatewayEventId = table.Column<string>(type: "character varying(120)", maxLength: 120, nullable: true),
|
||||
GatewaySequence = table.Column<long>(type: "bigint", nullable: true),
|
||||
SequenceGapDetected = table.Column<bool>(type: "boolean", nullable: false),
|
||||
ResultRunId = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
OccurredAt = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_OpenClawRunHistory", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_OpenClawRunHistory_OpenClawRuns_RunId",
|
||||
column: x => x.RunId,
|
||||
principalTable: "OpenClawRuns",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_OpenClawRunHistory_GatewayEventId",
|
||||
table: "OpenClawRunHistory",
|
||||
column: "GatewayEventId",
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_OpenClawRunHistory_RunId_Action_IdempotencyKey",
|
||||
table: "OpenClawRunHistory",
|
||||
columns: new[] { "RunId", "Action", "IdempotencyKey" },
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_OpenClawRunHistory_RunId_OccurredAt",
|
||||
table: "OpenClawRunHistory",
|
||||
columns: new[] { "RunId", "OccurredAt" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_OpenClawRuns_OpenClawRunId",
|
||||
table: "OpenClawRuns",
|
||||
column: "OpenClawRunId",
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_OpenClawRuns_ProjectId",
|
||||
table: "OpenClawRuns",
|
||||
column: "ProjectId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_OpenClawRuns_RetriedFromRunId",
|
||||
table: "OpenClawRuns",
|
||||
column: "RetriedFromRunId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_OpenClawRuns_SessionKey",
|
||||
table: "OpenClawRuns",
|
||||
column: "SessionKey");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_OpenClawRuns_StartIdempotencyKey",
|
||||
table: "OpenClawRuns",
|
||||
column: "StartIdempotencyKey",
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_OpenClawRuns_Status_UpdatedAt",
|
||||
table: "OpenClawRuns",
|
||||
columns: new[] { "Status", "UpdatedAt" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_OpenClawRuns_TaskId",
|
||||
table: "OpenClawRuns",
|
||||
column: "TaskId");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "OpenClawRunHistory");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "OpenClawRuns");
|
||||
}
|
||||
}
|
||||
}
|
||||
+619
@@ -0,0 +1,619 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using Nexus.Api.Data;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Nexus.Api.Data.Migrations
|
||||
{
|
||||
[DbContext(typeof(NexusDbContext))]
|
||||
[Migration("20260730191613_AddOpenClawConnectionProfile")]
|
||||
partial class AddOpenClawConnectionProfile
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasAnnotation("ProductVersion", "10.0.8")
|
||||
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||
|
||||
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||
|
||||
modelBuilder.Entity("Nexus.Api.Data.ActivityEvent", b =>
|
||||
{
|
||||
b.Property<long>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("bigint");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<long>("Id"));
|
||||
|
||||
b.Property<DateTimeOffset>("CreatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("Message")
|
||||
.IsRequired()
|
||||
.HasMaxLength(1000)
|
||||
.HasColumnType("character varying(1000)");
|
||||
|
||||
b.Property<Guid?>("TaskId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("Type")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("CreatedAt");
|
||||
|
||||
b.HasIndex("TaskId");
|
||||
|
||||
b.ToTable("Activity");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Nexus.Api.Data.NexusUser", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<DateTimeOffset>("CreatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("DisplayName")
|
||||
.IsRequired()
|
||||
.HasMaxLength(100)
|
||||
.HasColumnType("character varying(100)");
|
||||
|
||||
b.Property<string>("Email")
|
||||
.IsRequired()
|
||||
.HasMaxLength(120)
|
||||
.HasColumnType("character varying(120)");
|
||||
|
||||
b.Property<DateTimeOffset?>("LastLoginAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("NormalizedEmail")
|
||||
.IsRequired()
|
||||
.HasMaxLength(120)
|
||||
.HasColumnType("character varying(120)");
|
||||
|
||||
b.Property<string>("PasswordHash")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Role")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<DateTimeOffset>("UpdatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("NormalizedEmail")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("Users");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Nexus.Api.Data.Notification", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<DateTimeOffset>("CreatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("ForUser")
|
||||
.IsRequired()
|
||||
.HasMaxLength(60)
|
||||
.HasColumnType("character varying(60)");
|
||||
|
||||
b.Property<bool>("IsRead")
|
||||
.HasColumnType("boolean");
|
||||
|
||||
b.Property<string>("Message")
|
||||
.HasMaxLength(1000)
|
||||
.HasColumnType("character varying(1000)");
|
||||
|
||||
b.Property<Guid?>("TaskId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("Title")
|
||||
.IsRequired()
|
||||
.HasMaxLength(240)
|
||||
.HasColumnType("character varying(240)");
|
||||
|
||||
b.Property<string>("Type")
|
||||
.IsRequired()
|
||||
.HasMaxLength(60)
|
||||
.HasColumnType("character varying(60)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("ForUser", "IsRead", "CreatedAt");
|
||||
|
||||
b.ToTable("Notifications");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Nexus.Api.Data.OpenClawConnectionProfile", b =>
|
||||
{
|
||||
b.Property<string>("ProfileId")
|
||||
.HasMaxLength(40)
|
||||
.HasColumnType("character varying(40)");
|
||||
|
||||
b.Property<DateTimeOffset?>("AdoptedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("AdoptionState")
|
||||
.IsRequired()
|
||||
.HasMaxLength(40)
|
||||
.HasColumnType("character varying(40)");
|
||||
|
||||
b.Property<string>("CapabilityHash")
|
||||
.HasMaxLength(128)
|
||||
.HasColumnType("character varying(128)");
|
||||
|
||||
b.Property<DateTimeOffset>("CreatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("DeviceId")
|
||||
.HasMaxLength(240)
|
||||
.HasColumnType("character varying(240)");
|
||||
|
||||
b.Property<string>("DiscoverySource")
|
||||
.IsRequired()
|
||||
.HasMaxLength(80)
|
||||
.HasColumnType("character varying(80)");
|
||||
|
||||
b.Property<string>("Endpoint")
|
||||
.IsRequired()
|
||||
.HasMaxLength(2048)
|
||||
.HasColumnType("character varying(2048)");
|
||||
|
||||
b.Property<DateTimeOffset?>("LastProbedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<DateTimeOffset?>("LastVerifiedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<bool>("ManagementEnabled")
|
||||
.HasColumnType("boolean");
|
||||
|
||||
b.Property<string>("RequiredVersion")
|
||||
.HasMaxLength(120)
|
||||
.HasColumnType("character varying(120)");
|
||||
|
||||
b.Property<int>("Revision")
|
||||
.IsConcurrencyToken()
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<string>("TlsCertificateFingerprint")
|
||||
.HasMaxLength(128)
|
||||
.HasColumnType("character varying(128)");
|
||||
|
||||
b.Property<DateTimeOffset>("UpdatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.HasKey("ProfileId");
|
||||
|
||||
b.ToTable("OpenClawConnectionProfiles", null, t =>
|
||||
{
|
||||
t.HasCheckConstraint("CK_OpenClawConnectionProfiles_Primary", "\"ProfileId\" = 'primary'");
|
||||
});
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Nexus.Api.Data.OpenClawRun", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("Actor")
|
||||
.IsRequired()
|
||||
.HasMaxLength(240)
|
||||
.HasColumnType("character varying(240)");
|
||||
|
||||
b.Property<string>("AgentId")
|
||||
.IsRequired()
|
||||
.HasMaxLength(200)
|
||||
.HasColumnType("character varying(200)");
|
||||
|
||||
b.Property<string>("CorrelationId")
|
||||
.IsRequired()
|
||||
.HasMaxLength(200)
|
||||
.HasColumnType("character varying(200)");
|
||||
|
||||
b.Property<DateTimeOffset>("CreatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<DateTimeOffset?>("FinishedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("LastError")
|
||||
.HasMaxLength(2000)
|
||||
.HasColumnType("character varying(2000)");
|
||||
|
||||
b.Property<long?>("LastGatewaySequence")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.Property<string>("OpenClawRunId")
|
||||
.HasMaxLength(240)
|
||||
.HasColumnType("character varying(240)");
|
||||
|
||||
b.Property<Guid?>("ProjectId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("Prompt")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<Guid?>("RetriedFromRunId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<int>("Revision")
|
||||
.IsConcurrencyToken()
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<bool>("SequenceGapDetected")
|
||||
.HasColumnType("boolean");
|
||||
|
||||
b.Property<string>("SessionKey")
|
||||
.IsRequired()
|
||||
.HasMaxLength(500)
|
||||
.HasColumnType("character varying(500)");
|
||||
|
||||
b.Property<string>("StartIdempotencyKey")
|
||||
.IsRequired()
|
||||
.HasMaxLength(200)
|
||||
.HasColumnType("character varying(200)");
|
||||
|
||||
b.Property<DateTimeOffset?>("StartedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("Status")
|
||||
.IsRequired()
|
||||
.HasMaxLength(40)
|
||||
.HasColumnType("character varying(40)");
|
||||
|
||||
b.Property<Guid?>("TaskId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("Title")
|
||||
.IsRequired()
|
||||
.HasMaxLength(160)
|
||||
.HasColumnType("character varying(160)");
|
||||
|
||||
b.Property<string>("TraceParent")
|
||||
.HasMaxLength(128)
|
||||
.HasColumnType("character varying(128)");
|
||||
|
||||
b.Property<DateTimeOffset>("UpdatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("OpenClawRunId")
|
||||
.IsUnique();
|
||||
|
||||
b.HasIndex("ProjectId");
|
||||
|
||||
b.HasIndex("RetriedFromRunId");
|
||||
|
||||
b.HasIndex("SessionKey");
|
||||
|
||||
b.HasIndex("StartIdempotencyKey")
|
||||
.IsUnique();
|
||||
|
||||
b.HasIndex("TaskId");
|
||||
|
||||
b.HasIndex("Status", "UpdatedAt");
|
||||
|
||||
b.ToTable("OpenClawRuns");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Nexus.Api.Data.OpenClawRunHistory", b =>
|
||||
{
|
||||
b.Property<long>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("bigint");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<long>("Id"));
|
||||
|
||||
b.Property<string>("Action")
|
||||
.IsRequired()
|
||||
.HasMaxLength(80)
|
||||
.HasColumnType("character varying(80)");
|
||||
|
||||
b.Property<string>("Actor")
|
||||
.IsRequired()
|
||||
.HasMaxLength(240)
|
||||
.HasColumnType("character varying(240)");
|
||||
|
||||
b.Property<string>("CorrelationId")
|
||||
.IsRequired()
|
||||
.HasMaxLength(200)
|
||||
.HasColumnType("character varying(200)");
|
||||
|
||||
b.Property<string>("FromStatus")
|
||||
.IsRequired()
|
||||
.HasMaxLength(40)
|
||||
.HasColumnType("character varying(40)");
|
||||
|
||||
b.Property<string>("GatewayEventId")
|
||||
.HasMaxLength(120)
|
||||
.HasColumnType("character varying(120)");
|
||||
|
||||
b.Property<long?>("GatewaySequence")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.Property<string>("IdempotencyKey")
|
||||
.HasMaxLength(200)
|
||||
.HasColumnType("character varying(200)");
|
||||
|
||||
b.Property<string>("Message")
|
||||
.IsRequired()
|
||||
.HasMaxLength(2000)
|
||||
.HasColumnType("character varying(2000)");
|
||||
|
||||
b.Property<DateTimeOffset>("OccurredAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<Guid?>("ResultRunId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<Guid>("RunId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<bool>("SequenceGapDetected")
|
||||
.HasColumnType("boolean");
|
||||
|
||||
b.Property<string>("ToStatus")
|
||||
.IsRequired()
|
||||
.HasMaxLength(40)
|
||||
.HasColumnType("character varying(40)");
|
||||
|
||||
b.Property<string>("TraceParent")
|
||||
.HasMaxLength(128)
|
||||
.HasColumnType("character varying(128)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("GatewayEventId")
|
||||
.IsUnique();
|
||||
|
||||
b.HasIndex("RunId", "OccurredAt");
|
||||
|
||||
b.HasIndex("RunId", "Action", "IdempotencyKey")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("OpenClawRunHistory");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Nexus.Api.Data.Project", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("Description")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasMaxLength(160)
|
||||
.HasColumnType("character varying(160)");
|
||||
|
||||
b.Property<int>("Progress")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<int>("Status")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<DateTimeOffset>("UpdatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("Projects");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Nexus.Api.Data.RefreshToken", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<Guid>("ConcurrencyStamp")
|
||||
.IsConcurrencyToken()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<DateTimeOffset>("CreatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<DateTimeOffset>("ExpiresAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<Guid>("FamilyId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("ReplacedByTokenHash")
|
||||
.HasMaxLength(64)
|
||||
.HasColumnType("character varying(64)");
|
||||
|
||||
b.Property<DateTimeOffset?>("RevokedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("TokenHash")
|
||||
.IsRequired()
|
||||
.HasMaxLength(64)
|
||||
.HasColumnType("character varying(64)");
|
||||
|
||||
b.Property<Guid>("UserId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("TokenHash")
|
||||
.IsUnique();
|
||||
|
||||
b.HasIndex("UserId", "FamilyId");
|
||||
|
||||
b.ToTable("RefreshTokens");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Nexus.Api.Data.SeedAudit", b =>
|
||||
{
|
||||
b.Property<string>("Key")
|
||||
.HasMaxLength(80)
|
||||
.HasColumnType("character varying(80)");
|
||||
|
||||
b.Property<DateTimeOffset>("CreatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.HasKey("Key");
|
||||
|
||||
b.ToTable("SeedAudit");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Nexus.Api.Data.WorkTask", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("AssignedTo")
|
||||
.HasMaxLength(60)
|
||||
.HasColumnType("character varying(60)");
|
||||
|
||||
b.Property<DateTimeOffset>("CreatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("Detail")
|
||||
.HasMaxLength(2000)
|
||||
.HasColumnType("character varying(2000)");
|
||||
|
||||
b.Property<DateTimeOffset?>("DueDate")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("ExpectedFrom")
|
||||
.HasMaxLength(60)
|
||||
.HasColumnType("character varying(60)");
|
||||
|
||||
b.Property<bool>("IsAgentTask")
|
||||
.HasColumnType("boolean");
|
||||
|
||||
b.Property<Guid?>("ParentTaskId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("Priority")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<Guid?>("ProjectId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("Source")
|
||||
.IsRequired()
|
||||
.HasMaxLength(60)
|
||||
.HasColumnType("character varying(60)");
|
||||
|
||||
b.Property<string>("State")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Title")
|
||||
.IsRequired()
|
||||
.HasMaxLength(240)
|
||||
.HasColumnType("character varying(240)");
|
||||
|
||||
b.Property<DateTimeOffset>("UpdatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("AssignedTo");
|
||||
|
||||
b.HasIndex("ExpectedFrom");
|
||||
|
||||
b.HasIndex("IsAgentTask");
|
||||
|
||||
b.HasIndex("ParentTaskId");
|
||||
|
||||
b.HasIndex("Source");
|
||||
|
||||
b.ToTable("Tasks");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Nexus.Api.Data.OpenClawRun", b =>
|
||||
{
|
||||
b.HasOne("Nexus.Api.Data.Project", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("ProjectId")
|
||||
.OnDelete(DeleteBehavior.SetNull);
|
||||
|
||||
b.HasOne("Nexus.Api.Data.WorkTask", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("TaskId")
|
||||
.OnDelete(DeleteBehavior.SetNull);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Nexus.Api.Data.OpenClawRunHistory", b =>
|
||||
{
|
||||
b.HasOne("Nexus.Api.Data.OpenClawRun", "Run")
|
||||
.WithMany("History")
|
||||
.HasForeignKey("RunId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Run");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Nexus.Api.Data.RefreshToken", b =>
|
||||
{
|
||||
b.HasOne("Nexus.Api.Data.NexusUser", "User")
|
||||
.WithMany("RefreshTokens")
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("User");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Nexus.Api.Data.WorkTask", b =>
|
||||
{
|
||||
b.HasOne("Nexus.Api.Data.WorkTask", "ParentTask")
|
||||
.WithMany("ChildTasks")
|
||||
.HasForeignKey("ParentTaskId")
|
||||
.OnDelete(DeleteBehavior.SetNull);
|
||||
|
||||
b.Navigation("ParentTask");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Nexus.Api.Data.NexusUser", b =>
|
||||
{
|
||||
b.Navigation("RefreshTokens");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Nexus.Api.Data.OpenClawRun", b =>
|
||||
{
|
||||
b.Navigation("History");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Nexus.Api.Data.WorkTask", b =>
|
||||
{
|
||||
b.Navigation("ChildTasks");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Nexus.Api.Data.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class AddOpenClawConnectionProfile : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: "OpenClawConnectionProfiles",
|
||||
columns: table => new
|
||||
{
|
||||
ProfileId = table.Column<string>(type: "character varying(40)", maxLength: 40, nullable: false),
|
||||
Endpoint = table.Column<string>(type: "character varying(2048)", maxLength: 2048, nullable: false),
|
||||
DiscoverySource = table.Column<string>(type: "character varying(80)", maxLength: 80, nullable: false),
|
||||
RequiredVersion = table.Column<string>(type: "character varying(120)", maxLength: 120, nullable: true),
|
||||
TlsCertificateFingerprint = table.Column<string>(type: "character varying(128)", maxLength: 128, nullable: true),
|
||||
AdoptionState = table.Column<string>(type: "character varying(40)", maxLength: 40, nullable: false),
|
||||
ManagementEnabled = table.Column<bool>(type: "boolean", nullable: false),
|
||||
CapabilityHash = table.Column<string>(type: "character varying(128)", maxLength: 128, nullable: true),
|
||||
DeviceId = table.Column<string>(type: "character varying(240)", maxLength: 240, nullable: true),
|
||||
Revision = table.Column<int>(type: "integer", nullable: false),
|
||||
CreatedAt = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false),
|
||||
UpdatedAt = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false),
|
||||
LastProbedAt = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true),
|
||||
LastVerifiedAt = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true),
|
||||
AdoptedAt = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_OpenClawConnectionProfiles", x => x.ProfileId);
|
||||
table.CheckConstraint("CK_OpenClawConnectionProfiles_Primary", "\"ProfileId\" = 'primary'");
|
||||
});
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "OpenClawConnectionProfiles");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,261 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Nexus.Api.Data;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Nexus.Api.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
[DbContext(typeof(NexusDbContext))]
|
||||
[Migration("20260730224500_AddAgentProvisioningAndBoardIndexes")]
|
||||
public partial class AddAgentProvisioningAndBoardIndexes : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: "AgentProposals",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
Source = table.Column<string>(type: "character varying(40)", maxLength: 40, nullable: false),
|
||||
RequestedName = table.Column<string>(type: "character varying(80)", maxLength: 80, nullable: false),
|
||||
RequestedAgentId = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: false),
|
||||
Role = table.Column<string>(type: "character varying(160)", maxLength: 160, nullable: true),
|
||||
Description = table.Column<string>(type: "character varying(4000)", maxLength: 4000, nullable: true),
|
||||
Model = table.Column<string>(type: "character varying(240)", maxLength: 240, nullable: true),
|
||||
Emoji = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: true),
|
||||
Avatar = table.Column<string>(type: "character varying(2048)", maxLength: 2048, nullable: true),
|
||||
Workspace = table.Column<string>(type: "character varying(2048)", maxLength: 2048, nullable: false),
|
||||
StandardFilesJson = table.Column<string>(type: "jsonb", nullable: false),
|
||||
StandardFilesHash = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: false),
|
||||
Status = table.Column<string>(type: "character varying(40)", maxLength: 40, nullable: false),
|
||||
RequestedBy = table.Column<string>(type: "character varying(240)", maxLength: 240, nullable: false),
|
||||
ApprovedBy = table.Column<string>(type: "character varying(240)", maxLength: 240, nullable: true),
|
||||
RejectedBy = table.Column<string>(type: "character varying(240)", maxLength: 240, nullable: true),
|
||||
RejectionReason = table.Column<string>(type: "character varying(1000)", maxLength: 1000, nullable: true),
|
||||
OpenClawAgentId = table.Column<string>(type: "character varying(128)", maxLength: 128, nullable: true),
|
||||
OpenClawWorkspace = table.Column<string>(type: "character varying(2048)", maxLength: 2048, nullable: true),
|
||||
LastErrorCode = table.Column<string>(type: "character varying(120)", maxLength: 120, nullable: true),
|
||||
LastErrorMessage = table.Column<string>(type: "character varying(2000)", maxLength: 2000, nullable: true),
|
||||
Revision = table.Column<int>(type: "integer", nullable: false),
|
||||
CreatedAt = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false),
|
||||
UpdatedAt = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false),
|
||||
ApprovedAt = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true),
|
||||
RejectedAt = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true),
|
||||
CompletedAt = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_AgentProposals", x => x.Id);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "OperationClaims",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
Operation = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: false),
|
||||
IdempotencyKeyHash = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: false),
|
||||
RequestHash = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: false),
|
||||
ResourceId = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
State = table.Column<string>(type: "character varying(40)", maxLength: 40, nullable: false),
|
||||
ResultCode = table.Column<string>(type: "character varying(120)", maxLength: 120, nullable: true),
|
||||
CreatedAt = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false),
|
||||
CompletedAt = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true),
|
||||
ExpiresAt = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_OperationClaims", x => x.Id);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "OutboxEvents",
|
||||
columns: table => new
|
||||
{
|
||||
Sequence = table.Column<long>(type: "bigint", nullable: false)
|
||||
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
|
||||
EventId = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
Type = table.Column<string>(type: "character varying(120)", maxLength: 120, nullable: false),
|
||||
AggregateType = table.Column<string>(type: "character varying(80)", maxLength: 80, nullable: false),
|
||||
AggregateId = table.Column<string>(type: "character varying(128)", maxLength: 128, nullable: false),
|
||||
AggregateRevision = table.Column<int>(type: "integer", nullable: false),
|
||||
PayloadJson = table.Column<string>(type: "jsonb", nullable: false),
|
||||
OccurredAt = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false),
|
||||
PublishedAt = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true),
|
||||
PublishAttempts = table.Column<int>(type: "integer", nullable: false),
|
||||
LastErrorCode = table.Column<string>(type: "character varying(120)", maxLength: 120, nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_OutboxEvents", x => x.Sequence);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "AgentProvisionRequests",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
ProposalId = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
Attempt = table.Column<int>(type: "integer", nullable: false),
|
||||
Stage = table.Column<string>(type: "character varying(40)", maxLength: 40, nullable: false),
|
||||
Status = table.Column<string>(type: "character varying(40)", maxLength: 40, nullable: false),
|
||||
IdempotencyKeyHash = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: false),
|
||||
Actor = table.Column<string>(type: "character varying(240)", maxLength: 240, nullable: false),
|
||||
CorrelationId = table.Column<string>(type: "character varying(200)", maxLength: 200, nullable: false),
|
||||
TraceParent = table.Column<string>(type: "character varying(128)", maxLength: 128, nullable: true),
|
||||
OpenClawAgentId = table.Column<string>(type: "character varying(128)", maxLength: 128, nullable: true),
|
||||
LastErrorCode = table.Column<string>(type: "character varying(120)", maxLength: 120, nullable: true),
|
||||
LastErrorMessage = table.Column<string>(type: "character varying(2000)", maxLength: 2000, nullable: true),
|
||||
LeaseOwner = table.Column<string>(type: "character varying(160)", maxLength: 160, nullable: true),
|
||||
LeaseUntil = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true),
|
||||
Revision = table.Column<int>(type: "integer", nullable: false),
|
||||
CreatedAt = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false),
|
||||
UpdatedAt = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false),
|
||||
DispatchStartedAt = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true),
|
||||
CompletedAt = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_AgentProvisionRequests", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_AgentProvisionRequests_AgentProposals_ProposalId",
|
||||
column: x => x.ProposalId,
|
||||
principalTable: "AgentProposals",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Activity_TaskId_CreatedAt_Id",
|
||||
table: "Activity",
|
||||
columns: new[] { "TaskId", "CreatedAt", "Id" },
|
||||
descending: new[] { false, true, true },
|
||||
filter: "\"TaskId\" IS NOT NULL");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_AgentProposals_OpenClawAgentId",
|
||||
table: "AgentProposals",
|
||||
column: "OpenClawAgentId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_AgentProposals_RequestedAgentId",
|
||||
table: "AgentProposals",
|
||||
column: "RequestedAgentId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_AgentProposals_Status_UpdatedAt",
|
||||
table: "AgentProposals",
|
||||
columns: new[] { "Status", "UpdatedAt" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_AgentProvisionRequests_LeaseUntil",
|
||||
table: "AgentProvisionRequests",
|
||||
column: "LeaseUntil");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_AgentProvisionRequests_ProposalId_Attempt",
|
||||
table: "AgentProvisionRequests",
|
||||
columns: new[] { "ProposalId", "Attempt" },
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_AgentProvisionRequests_Status_CreatedAt",
|
||||
table: "AgentProvisionRequests",
|
||||
columns: new[] { "Status", "CreatedAt" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_OperationClaims_ExpiresAt",
|
||||
table: "OperationClaims",
|
||||
column: "ExpiresAt");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_OperationClaims_Operation_IdempotencyKeyHash",
|
||||
table: "OperationClaims",
|
||||
columns: new[] { "Operation", "IdempotencyKeyHash" },
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_OutboxEvents_EventId",
|
||||
table: "OutboxEvents",
|
||||
column: "EventId",
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_OutboxEvents_OccurredAt",
|
||||
table: "OutboxEvents",
|
||||
column: "OccurredAt");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_OutboxEvents_PublishedAt_Sequence",
|
||||
table: "OutboxEvents",
|
||||
columns: new[] { "PublishedAt", "Sequence" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Tasks_Done_UpdatedAt_Id",
|
||||
table: "Tasks",
|
||||
columns: new[] { "UpdatedAt", "Id" },
|
||||
descending: new[] { true, true },
|
||||
filter: "\"State\" = 'Done'");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Tasks_AgentWorkflow",
|
||||
table: "Tasks",
|
||||
columns: new[] { "ExpectedFrom", "State", "UpdatedAt", "Id" },
|
||||
descending: new[] { false, false, true, false },
|
||||
filter: "\"IsAgentTask\" = TRUE");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Tasks_ParentTaskId_State",
|
||||
table: "Tasks",
|
||||
columns: new[] { "ParentTaskId", "State" },
|
||||
filter: "\"ParentTaskId\" IS NOT NULL");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Tasks_State_UpdatedAt_Id_Board",
|
||||
table: "Tasks",
|
||||
columns: new[] { "State", "UpdatedAt", "Id" },
|
||||
descending: new[] { false, true, false });
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropIndex(
|
||||
name: "IX_Activity_TaskId_CreatedAt_Id",
|
||||
table: "Activity");
|
||||
|
||||
migrationBuilder.DropIndex(
|
||||
name: "IX_Tasks_Done_UpdatedAt_Id",
|
||||
table: "Tasks");
|
||||
|
||||
migrationBuilder.DropIndex(
|
||||
name: "IX_Tasks_AgentWorkflow",
|
||||
table: "Tasks");
|
||||
|
||||
migrationBuilder.DropIndex(
|
||||
name: "IX_Tasks_ParentTaskId_State",
|
||||
table: "Tasks");
|
||||
|
||||
migrationBuilder.DropIndex(
|
||||
name: "IX_Tasks_State_UpdatedAt_Id_Board",
|
||||
table: "Tasks");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "AgentProvisionRequests");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "OperationClaims");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "OutboxEvents");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "AgentProposals");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -51,9 +51,225 @@ namespace Nexus.Api.Migrations
|
||||
|
||||
b.HasIndex("TaskId");
|
||||
|
||||
b.HasIndex("TaskId", "CreatedAt", "Id")
|
||||
.IsDescending(false, true, true)
|
||||
.HasDatabaseName("IX_Activity_TaskId_CreatedAt_Id")
|
||||
.HasFilter("\"TaskId\" IS NOT NULL");
|
||||
|
||||
b.ToTable("Activity");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Nexus.Api.Data.AgentProposal", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("ApprovedBy")
|
||||
.HasMaxLength(240)
|
||||
.HasColumnType("character varying(240)");
|
||||
|
||||
b.Property<DateTimeOffset?>("ApprovedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("Avatar")
|
||||
.HasMaxLength(2048)
|
||||
.HasColumnType("character varying(2048)");
|
||||
|
||||
b.Property<DateTimeOffset?>("CompletedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<DateTimeOffset>("CreatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("Description")
|
||||
.HasMaxLength(4000)
|
||||
.HasColumnType("character varying(4000)");
|
||||
|
||||
b.Property<string>("Emoji")
|
||||
.HasMaxLength(32)
|
||||
.HasColumnType("character varying(32)");
|
||||
|
||||
b.Property<string>("LastErrorCode")
|
||||
.HasMaxLength(120)
|
||||
.HasColumnType("character varying(120)");
|
||||
|
||||
b.Property<string>("LastErrorMessage")
|
||||
.HasMaxLength(2000)
|
||||
.HasColumnType("character varying(2000)");
|
||||
|
||||
b.Property<string>("Model")
|
||||
.HasMaxLength(240)
|
||||
.HasColumnType("character varying(240)");
|
||||
|
||||
b.Property<string>("OpenClawAgentId")
|
||||
.HasMaxLength(128)
|
||||
.HasColumnType("character varying(128)");
|
||||
|
||||
b.Property<string>("OpenClawWorkspace")
|
||||
.HasMaxLength(2048)
|
||||
.HasColumnType("character varying(2048)");
|
||||
|
||||
b.Property<string>("RejectedBy")
|
||||
.HasMaxLength(240)
|
||||
.HasColumnType("character varying(240)");
|
||||
|
||||
b.Property<DateTimeOffset?>("RejectedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("RejectionReason")
|
||||
.HasMaxLength(1000)
|
||||
.HasColumnType("character varying(1000)");
|
||||
|
||||
b.Property<string>("RequestedAgentId")
|
||||
.IsRequired()
|
||||
.HasMaxLength(64)
|
||||
.HasColumnType("character varying(64)");
|
||||
|
||||
b.Property<string>("RequestedBy")
|
||||
.IsRequired()
|
||||
.HasMaxLength(240)
|
||||
.HasColumnType("character varying(240)");
|
||||
|
||||
b.Property<string>("RequestedName")
|
||||
.IsRequired()
|
||||
.HasMaxLength(80)
|
||||
.HasColumnType("character varying(80)");
|
||||
|
||||
b.Property<int>("Revision")
|
||||
.IsConcurrencyToken()
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<string>("Role")
|
||||
.HasMaxLength(160)
|
||||
.HasColumnType("character varying(160)");
|
||||
|
||||
b.Property<string>("Source")
|
||||
.IsRequired()
|
||||
.HasMaxLength(40)
|
||||
.HasColumnType("character varying(40)");
|
||||
|
||||
b.Property<string>("StandardFilesHash")
|
||||
.IsRequired()
|
||||
.HasMaxLength(64)
|
||||
.HasColumnType("character varying(64)");
|
||||
|
||||
b.Property<string>("StandardFilesJson")
|
||||
.IsRequired()
|
||||
.HasColumnType("jsonb");
|
||||
|
||||
b.Property<string>("Status")
|
||||
.IsRequired()
|
||||
.HasMaxLength(40)
|
||||
.HasColumnType("character varying(40)");
|
||||
|
||||
b.Property<DateTimeOffset>("UpdatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("Workspace")
|
||||
.IsRequired()
|
||||
.HasMaxLength(2048)
|
||||
.HasColumnType("character varying(2048)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("OpenClawAgentId");
|
||||
|
||||
b.HasIndex("RequestedAgentId");
|
||||
|
||||
b.HasIndex("Status", "UpdatedAt");
|
||||
|
||||
b.ToTable("AgentProposals");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Nexus.Api.Data.AgentProvisionRequest", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("Actor")
|
||||
.IsRequired()
|
||||
.HasMaxLength(240)
|
||||
.HasColumnType("character varying(240)");
|
||||
|
||||
b.Property<int>("Attempt")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<DateTimeOffset?>("CompletedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("CorrelationId")
|
||||
.IsRequired()
|
||||
.HasMaxLength(200)
|
||||
.HasColumnType("character varying(200)");
|
||||
|
||||
b.Property<DateTimeOffset>("CreatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<DateTimeOffset?>("DispatchStartedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("IdempotencyKeyHash")
|
||||
.IsRequired()
|
||||
.HasMaxLength(64)
|
||||
.HasColumnType("character varying(64)");
|
||||
|
||||
b.Property<string>("LastErrorCode")
|
||||
.HasMaxLength(120)
|
||||
.HasColumnType("character varying(120)");
|
||||
|
||||
b.Property<string>("LastErrorMessage")
|
||||
.HasMaxLength(2000)
|
||||
.HasColumnType("character varying(2000)");
|
||||
|
||||
b.Property<string>("LeaseOwner")
|
||||
.HasMaxLength(160)
|
||||
.HasColumnType("character varying(160)");
|
||||
|
||||
b.Property<DateTimeOffset?>("LeaseUntil")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("OpenClawAgentId")
|
||||
.HasMaxLength(128)
|
||||
.HasColumnType("character varying(128)");
|
||||
|
||||
b.Property<Guid>("ProposalId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<int>("Revision")
|
||||
.IsConcurrencyToken()
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<string>("Stage")
|
||||
.IsRequired()
|
||||
.HasMaxLength(40)
|
||||
.HasColumnType("character varying(40)");
|
||||
|
||||
b.Property<string>("Status")
|
||||
.IsRequired()
|
||||
.HasMaxLength(40)
|
||||
.HasColumnType("character varying(40)");
|
||||
|
||||
b.Property<string>("TraceParent")
|
||||
.HasMaxLength(128)
|
||||
.HasColumnType("character varying(128)");
|
||||
|
||||
b.Property<DateTimeOffset>("UpdatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("LeaseUntil");
|
||||
|
||||
b.HasIndex("ProposalId", "Attempt")
|
||||
.IsUnique();
|
||||
|
||||
b.HasIndex("Status", "CreatedAt");
|
||||
|
||||
b.ToTable("AgentProvisionRequests");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Nexus.Api.Data.NexusUser", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
@@ -141,6 +357,370 @@ namespace Nexus.Api.Migrations
|
||||
b.ToTable("Notifications");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Nexus.Api.Data.OpenClawConnectionProfile", b =>
|
||||
{
|
||||
b.Property<string>("ProfileId")
|
||||
.HasMaxLength(40)
|
||||
.HasColumnType("character varying(40)");
|
||||
|
||||
b.Property<DateTimeOffset?>("AdoptedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("AdoptionState")
|
||||
.IsRequired()
|
||||
.HasMaxLength(40)
|
||||
.HasColumnType("character varying(40)");
|
||||
|
||||
b.Property<string>("CapabilityHash")
|
||||
.HasMaxLength(128)
|
||||
.HasColumnType("character varying(128)");
|
||||
|
||||
b.Property<DateTimeOffset>("CreatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("DeviceId")
|
||||
.HasMaxLength(240)
|
||||
.HasColumnType("character varying(240)");
|
||||
|
||||
b.Property<string>("DiscoverySource")
|
||||
.IsRequired()
|
||||
.HasMaxLength(80)
|
||||
.HasColumnType("character varying(80)");
|
||||
|
||||
b.Property<string>("Endpoint")
|
||||
.IsRequired()
|
||||
.HasMaxLength(2048)
|
||||
.HasColumnType("character varying(2048)");
|
||||
|
||||
b.Property<DateTimeOffset?>("LastProbedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<DateTimeOffset?>("LastVerifiedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<bool>("ManagementEnabled")
|
||||
.HasColumnType("boolean");
|
||||
|
||||
b.Property<string>("RequiredVersion")
|
||||
.HasMaxLength(120)
|
||||
.HasColumnType("character varying(120)");
|
||||
|
||||
b.Property<int>("Revision")
|
||||
.IsConcurrencyToken()
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<string>("TlsCertificateFingerprint")
|
||||
.HasMaxLength(128)
|
||||
.HasColumnType("character varying(128)");
|
||||
|
||||
b.Property<DateTimeOffset>("UpdatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.HasKey("ProfileId");
|
||||
|
||||
b.ToTable("OpenClawConnectionProfiles", null, t =>
|
||||
{
|
||||
t.HasCheckConstraint("CK_OpenClawConnectionProfiles_Primary", "\"ProfileId\" = 'primary'");
|
||||
});
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Nexus.Api.Data.OpenClawRun", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("Actor")
|
||||
.IsRequired()
|
||||
.HasMaxLength(240)
|
||||
.HasColumnType("character varying(240)");
|
||||
|
||||
b.Property<string>("AgentId")
|
||||
.IsRequired()
|
||||
.HasMaxLength(200)
|
||||
.HasColumnType("character varying(200)");
|
||||
|
||||
b.Property<string>("CorrelationId")
|
||||
.IsRequired()
|
||||
.HasMaxLength(200)
|
||||
.HasColumnType("character varying(200)");
|
||||
|
||||
b.Property<DateTimeOffset>("CreatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<DateTimeOffset?>("FinishedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("LastError")
|
||||
.HasMaxLength(2000)
|
||||
.HasColumnType("character varying(2000)");
|
||||
|
||||
b.Property<long?>("LastGatewaySequence")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.Property<string>("OpenClawRunId")
|
||||
.HasMaxLength(240)
|
||||
.HasColumnType("character varying(240)");
|
||||
|
||||
b.Property<Guid?>("ProjectId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("Prompt")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<Guid?>("RetriedFromRunId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<int>("Revision")
|
||||
.IsConcurrencyToken()
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<bool>("SequenceGapDetected")
|
||||
.HasColumnType("boolean");
|
||||
|
||||
b.Property<string>("SessionKey")
|
||||
.IsRequired()
|
||||
.HasMaxLength(500)
|
||||
.HasColumnType("character varying(500)");
|
||||
|
||||
b.Property<string>("StartIdempotencyKey")
|
||||
.IsRequired()
|
||||
.HasMaxLength(200)
|
||||
.HasColumnType("character varying(200)");
|
||||
|
||||
b.Property<DateTimeOffset?>("StartedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("Status")
|
||||
.IsRequired()
|
||||
.HasMaxLength(40)
|
||||
.HasColumnType("character varying(40)");
|
||||
|
||||
b.Property<Guid?>("TaskId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("Title")
|
||||
.IsRequired()
|
||||
.HasMaxLength(160)
|
||||
.HasColumnType("character varying(160)");
|
||||
|
||||
b.Property<string>("TraceParent")
|
||||
.HasMaxLength(128)
|
||||
.HasColumnType("character varying(128)");
|
||||
|
||||
b.Property<DateTimeOffset>("UpdatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("OpenClawRunId")
|
||||
.IsUnique();
|
||||
|
||||
b.HasIndex("ProjectId");
|
||||
|
||||
b.HasIndex("RetriedFromRunId");
|
||||
|
||||
b.HasIndex("SessionKey");
|
||||
|
||||
b.HasIndex("StartIdempotencyKey")
|
||||
.IsUnique();
|
||||
|
||||
b.HasIndex("TaskId");
|
||||
|
||||
b.HasIndex("Status", "UpdatedAt");
|
||||
|
||||
b.ToTable("OpenClawRuns");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Nexus.Api.Data.OpenClawRunHistory", b =>
|
||||
{
|
||||
b.Property<long>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("bigint");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<long>("Id"));
|
||||
|
||||
b.Property<string>("Action")
|
||||
.IsRequired()
|
||||
.HasMaxLength(80)
|
||||
.HasColumnType("character varying(80)");
|
||||
|
||||
b.Property<string>("Actor")
|
||||
.IsRequired()
|
||||
.HasMaxLength(240)
|
||||
.HasColumnType("character varying(240)");
|
||||
|
||||
b.Property<string>("CorrelationId")
|
||||
.IsRequired()
|
||||
.HasMaxLength(200)
|
||||
.HasColumnType("character varying(200)");
|
||||
|
||||
b.Property<string>("FromStatus")
|
||||
.IsRequired()
|
||||
.HasMaxLength(40)
|
||||
.HasColumnType("character varying(40)");
|
||||
|
||||
b.Property<string>("GatewayEventId")
|
||||
.HasMaxLength(120)
|
||||
.HasColumnType("character varying(120)");
|
||||
|
||||
b.Property<long?>("GatewaySequence")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.Property<string>("IdempotencyKey")
|
||||
.HasMaxLength(200)
|
||||
.HasColumnType("character varying(200)");
|
||||
|
||||
b.Property<string>("Message")
|
||||
.IsRequired()
|
||||
.HasMaxLength(2000)
|
||||
.HasColumnType("character varying(2000)");
|
||||
|
||||
b.Property<DateTimeOffset>("OccurredAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<Guid?>("ResultRunId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<Guid>("RunId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<bool>("SequenceGapDetected")
|
||||
.HasColumnType("boolean");
|
||||
|
||||
b.Property<string>("ToStatus")
|
||||
.IsRequired()
|
||||
.HasMaxLength(40)
|
||||
.HasColumnType("character varying(40)");
|
||||
|
||||
b.Property<string>("TraceParent")
|
||||
.HasMaxLength(128)
|
||||
.HasColumnType("character varying(128)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("GatewayEventId")
|
||||
.IsUnique();
|
||||
|
||||
b.HasIndex("RunId", "OccurredAt");
|
||||
|
||||
b.HasIndex("RunId", "Action", "IdempotencyKey")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("OpenClawRunHistory");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Nexus.Api.Data.OperationClaim", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<DateTimeOffset?>("CompletedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<DateTimeOffset>("CreatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<DateTimeOffset>("ExpiresAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("IdempotencyKeyHash")
|
||||
.IsRequired()
|
||||
.HasMaxLength(64)
|
||||
.HasColumnType("character varying(64)");
|
||||
|
||||
b.Property<string>("Operation")
|
||||
.IsRequired()
|
||||
.HasMaxLength(100)
|
||||
.HasColumnType("character varying(100)");
|
||||
|
||||
b.Property<string>("RequestHash")
|
||||
.IsRequired()
|
||||
.HasMaxLength(64)
|
||||
.HasColumnType("character varying(64)");
|
||||
|
||||
b.Property<Guid?>("ResourceId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("ResultCode")
|
||||
.HasMaxLength(120)
|
||||
.HasColumnType("character varying(120)");
|
||||
|
||||
b.Property<string>("State")
|
||||
.IsRequired()
|
||||
.HasMaxLength(40)
|
||||
.HasColumnType("character varying(40)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("ExpiresAt");
|
||||
|
||||
b.HasIndex("Operation", "IdempotencyKeyHash")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("OperationClaims");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Nexus.Api.Data.OutboxEvent", b =>
|
||||
{
|
||||
b.Property<long>("Sequence")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("bigint");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<long>("Sequence"));
|
||||
|
||||
b.Property<string>("AggregateId")
|
||||
.IsRequired()
|
||||
.HasMaxLength(128)
|
||||
.HasColumnType("character varying(128)");
|
||||
|
||||
b.Property<int>("AggregateRevision")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<string>("AggregateType")
|
||||
.IsRequired()
|
||||
.HasMaxLength(80)
|
||||
.HasColumnType("character varying(80)");
|
||||
|
||||
b.Property<Guid>("EventId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("LastErrorCode")
|
||||
.HasMaxLength(120)
|
||||
.HasColumnType("character varying(120)");
|
||||
|
||||
b.Property<DateTimeOffset>("OccurredAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("PayloadJson")
|
||||
.IsRequired()
|
||||
.HasColumnType("jsonb");
|
||||
|
||||
b.Property<DateTimeOffset?>("PublishedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<int>("PublishAttempts")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<string>("Type")
|
||||
.IsRequired()
|
||||
.HasMaxLength(120)
|
||||
.HasColumnType("character varying(120)");
|
||||
|
||||
b.HasKey("Sequence");
|
||||
|
||||
b.HasIndex("EventId")
|
||||
.IsUnique();
|
||||
|
||||
b.HasIndex("OccurredAt");
|
||||
|
||||
b.HasIndex("PublishedAt", "Sequence");
|
||||
|
||||
b.ToTable("OutboxEvents");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Nexus.Api.Data.Project", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
@@ -294,9 +874,51 @@ namespace Nexus.Api.Migrations
|
||||
|
||||
b.HasIndex("Source");
|
||||
|
||||
b.HasIndex("ExpectedFrom", "State", "UpdatedAt", "Id")
|
||||
.IsDescending(false, false, true, false)
|
||||
.HasDatabaseName("IX_Tasks_AgentWorkflow")
|
||||
.HasFilter("\"IsAgentTask\" = TRUE");
|
||||
|
||||
b.HasIndex("ParentTaskId", "State")
|
||||
.HasDatabaseName("IX_Tasks_ParentTaskId_State")
|
||||
.HasFilter("\"ParentTaskId\" IS NOT NULL");
|
||||
|
||||
b.HasIndex("State", "UpdatedAt", "Id")
|
||||
.IsDescending(false, true, false)
|
||||
.HasDatabaseName("IX_Tasks_State_UpdatedAt_Id_Board");
|
||||
|
||||
b.HasIndex("UpdatedAt", "Id")
|
||||
.IsDescending(true, true)
|
||||
.HasDatabaseName("IX_Tasks_Done_UpdatedAt_Id")
|
||||
.HasFilter("\"State\" = 'Done'");
|
||||
|
||||
b.ToTable("Tasks");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Nexus.Api.Data.OpenClawRun", b =>
|
||||
{
|
||||
b.HasOne("Nexus.Api.Data.Project", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("ProjectId")
|
||||
.OnDelete(DeleteBehavior.SetNull);
|
||||
|
||||
b.HasOne("Nexus.Api.Data.WorkTask", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("TaskId")
|
||||
.OnDelete(DeleteBehavior.SetNull);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Nexus.Api.Data.OpenClawRunHistory", b =>
|
||||
{
|
||||
b.HasOne("Nexus.Api.Data.OpenClawRun", "Run")
|
||||
.WithMany("History")
|
||||
.HasForeignKey("RunId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Run");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Nexus.Api.Data.RefreshToken", b =>
|
||||
{
|
||||
b.HasOne("Nexus.Api.Data.NexusUser", "User")
|
||||
@@ -323,6 +945,27 @@ namespace Nexus.Api.Migrations
|
||||
b.Navigation("RefreshTokens");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Nexus.Api.Data.AgentProposal", b =>
|
||||
{
|
||||
b.Navigation("ProvisionRequests");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Nexus.Api.Data.AgentProvisionRequest", b =>
|
||||
{
|
||||
b.HasOne("Nexus.Api.Data.AgentProposal", "Proposal")
|
||||
.WithMany("ProvisionRequests")
|
||||
.HasForeignKey("ProposalId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Proposal");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Nexus.Api.Data.OpenClawRun", b =>
|
||||
{
|
||||
b.Navigation("History");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Nexus.Api.Data.WorkTask", b =>
|
||||
{
|
||||
b.Navigation("ChildTasks");
|
||||
|
||||
@@ -11,9 +11,20 @@ public sealed class NexusDbContext(DbContextOptions<NexusDbContext> options) : D
|
||||
public DbSet<NexusUser> Users => Set<NexusUser>();
|
||||
public DbSet<RefreshToken> RefreshTokens => Set<RefreshToken>();
|
||||
public DbSet<SeedAudit> SeedAudits => Set<SeedAudit>();
|
||||
public DbSet<OpenClawRun> OpenClawRuns => Set<OpenClawRun>();
|
||||
public DbSet<OpenClawRunHistory> OpenClawRunHistory => Set<OpenClawRunHistory>();
|
||||
public DbSet<OpenClawConnectionProfile> OpenClawConnectionProfiles =>
|
||||
Set<OpenClawConnectionProfile>();
|
||||
public DbSet<AgentProposal> AgentProposals => Set<AgentProposal>();
|
||||
public DbSet<AgentProvisionRequest> AgentProvisionRequests =>
|
||||
Set<AgentProvisionRequest>();
|
||||
public DbSet<OperationClaim> OperationClaims => Set<OperationClaim>();
|
||||
public DbSet<OutboxEvent> OutboxEvents => Set<OutboxEvent>();
|
||||
|
||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||
{
|
||||
modelBuilder.ApplyConfiguration(new OpenClawConnectionProfileConfiguration());
|
||||
ConfigureAgentProvisioning(modelBuilder);
|
||||
modelBuilder.Entity<Project>().Property(x => x.Name).HasMaxLength(160);
|
||||
modelBuilder.Entity<WorkTask>(entity =>
|
||||
{
|
||||
@@ -26,6 +37,20 @@ public sealed class NexusDbContext(DbContextOptions<NexusDbContext> options) : D
|
||||
entity.HasIndex(x => x.AssignedTo);
|
||||
entity.HasIndex(x => x.IsAgentTask);
|
||||
entity.HasIndex(x => x.ExpectedFrom);
|
||||
entity.HasIndex(x => new { x.State, x.UpdatedAt, x.Id })
|
||||
.IsDescending(false, true, false)
|
||||
.HasDatabaseName("IX_Tasks_State_UpdatedAt_Id_Board");
|
||||
entity.HasIndex(x => new { x.UpdatedAt, x.Id })
|
||||
.IsDescending(true, true)
|
||||
.HasFilter("\"State\" = 'Done'")
|
||||
.HasDatabaseName("IX_Tasks_Done_UpdatedAt_Id");
|
||||
entity.HasIndex(x => new { x.ParentTaskId, x.State })
|
||||
.HasFilter("\"ParentTaskId\" IS NOT NULL")
|
||||
.HasDatabaseName("IX_Tasks_ParentTaskId_State");
|
||||
entity.HasIndex(x => new { x.ExpectedFrom, x.State, x.UpdatedAt, x.Id })
|
||||
.IsDescending(false, false, true, false)
|
||||
.HasFilter("\"IsAgentTask\" = TRUE")
|
||||
.HasDatabaseName("IX_Tasks_AgentWorkflow");
|
||||
entity.HasOne(x => x.ParentTask)
|
||||
.WithMany(x => x.ChildTasks)
|
||||
.HasForeignKey(x => x.ParentTaskId)
|
||||
@@ -44,6 +69,10 @@ public sealed class NexusDbContext(DbContextOptions<NexusDbContext> options) : D
|
||||
{
|
||||
entity.Property(x => x.Message).HasMaxLength(1000);
|
||||
entity.HasIndex(x => x.TaskId);
|
||||
entity.HasIndex(x => new { x.TaskId, x.CreatedAt, x.Id })
|
||||
.IsDescending(false, true, true)
|
||||
.HasFilter("\"TaskId\" IS NOT NULL")
|
||||
.HasDatabaseName("IX_Activity_TaskId_CreatedAt_Id");
|
||||
});
|
||||
modelBuilder.Entity<NexusUser>().HasIndex(u => u.NormalizedEmail).IsUnique();
|
||||
modelBuilder.Entity<RefreshToken>().HasIndex(r => r.TokenHash).IsUnique();
|
||||
@@ -56,5 +85,134 @@ public sealed class NexusDbContext(DbContextOptions<NexusDbContext> options) : D
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
modelBuilder.Entity<ActivityEvent>().HasIndex(x => x.CreatedAt);
|
||||
|
||||
modelBuilder.Entity<OpenClawRun>(entity =>
|
||||
{
|
||||
entity.Property(x => x.Title).HasMaxLength(160);
|
||||
entity.Property(x => x.Prompt).HasColumnType("text");
|
||||
entity.Property(x => x.AgentId).HasMaxLength(200);
|
||||
entity.Property(x => x.SessionKey).HasMaxLength(500);
|
||||
entity.Property(x => x.Status).HasMaxLength(40);
|
||||
entity.Property(x => x.OpenClawRunId).HasMaxLength(240);
|
||||
entity.Property(x => x.StartIdempotencyKey).HasMaxLength(200);
|
||||
entity.Property(x => x.CorrelationId).HasMaxLength(200);
|
||||
entity.Property(x => x.Actor).HasMaxLength(240);
|
||||
entity.Property(x => x.TraceParent).HasMaxLength(128);
|
||||
entity.Property(x => x.LastError).HasMaxLength(2000);
|
||||
entity.Property(x => x.Revision).IsConcurrencyToken();
|
||||
entity.HasIndex(x => x.StartIdempotencyKey).IsUnique();
|
||||
entity.HasIndex(x => x.OpenClawRunId).IsUnique();
|
||||
entity.HasIndex(x => new { x.Status, x.UpdatedAt });
|
||||
entity.HasIndex(x => x.TaskId);
|
||||
entity.HasIndex(x => x.ProjectId);
|
||||
entity.HasIndex(x => x.SessionKey);
|
||||
entity.HasIndex(x => x.RetriedFromRunId);
|
||||
entity.HasOne<WorkTask>()
|
||||
.WithMany()
|
||||
.HasForeignKey(x => x.TaskId)
|
||||
.OnDelete(DeleteBehavior.SetNull);
|
||||
entity.HasOne<Project>()
|
||||
.WithMany()
|
||||
.HasForeignKey(x => x.ProjectId)
|
||||
.OnDelete(DeleteBehavior.SetNull);
|
||||
});
|
||||
|
||||
modelBuilder.Entity<OpenClawRunHistory>(entity =>
|
||||
{
|
||||
entity.Property(x => x.Action).HasMaxLength(80);
|
||||
entity.Property(x => x.FromStatus).HasMaxLength(40);
|
||||
entity.Property(x => x.ToStatus).HasMaxLength(40);
|
||||
entity.Property(x => x.Message).HasMaxLength(2000);
|
||||
entity.Property(x => x.Actor).HasMaxLength(240);
|
||||
entity.Property(x => x.CorrelationId).HasMaxLength(200);
|
||||
entity.Property(x => x.IdempotencyKey).HasMaxLength(200);
|
||||
entity.Property(x => x.TraceParent).HasMaxLength(128);
|
||||
entity.Property(x => x.GatewayEventId).HasMaxLength(120);
|
||||
entity.HasIndex(x => new { x.RunId, x.OccurredAt });
|
||||
entity.HasIndex(x => new { x.RunId, x.Action, x.IdempotencyKey }).IsUnique();
|
||||
entity.HasIndex(x => x.GatewayEventId).IsUnique();
|
||||
entity.HasOne(x => x.Run)
|
||||
.WithMany(x => x.History)
|
||||
.HasForeignKey(x => x.RunId)
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
}
|
||||
|
||||
private static void ConfigureAgentProvisioning(ModelBuilder modelBuilder)
|
||||
{
|
||||
modelBuilder.Entity<AgentProposal>(entity =>
|
||||
{
|
||||
entity.Property(x => x.Source).HasMaxLength(40);
|
||||
entity.Property(x => x.RequestedName).HasMaxLength(80);
|
||||
entity.Property(x => x.RequestedAgentId).HasMaxLength(64);
|
||||
entity.Property(x => x.Role).HasMaxLength(160);
|
||||
entity.Property(x => x.Description).HasMaxLength(4000);
|
||||
entity.Property(x => x.Model).HasMaxLength(240);
|
||||
entity.Property(x => x.Emoji).HasMaxLength(32);
|
||||
entity.Property(x => x.Avatar).HasMaxLength(2048);
|
||||
entity.Property(x => x.Workspace).HasMaxLength(2048);
|
||||
entity.Property(x => x.StandardFilesJson).HasColumnType("jsonb");
|
||||
entity.Property(x => x.StandardFilesHash).HasMaxLength(64);
|
||||
entity.Property(x => x.Status).HasMaxLength(40);
|
||||
entity.Property(x => x.RequestedBy).HasMaxLength(240);
|
||||
entity.Property(x => x.ApprovedBy).HasMaxLength(240);
|
||||
entity.Property(x => x.RejectedBy).HasMaxLength(240);
|
||||
entity.Property(x => x.RejectionReason).HasMaxLength(1000);
|
||||
entity.Property(x => x.OpenClawAgentId).HasMaxLength(128);
|
||||
entity.Property(x => x.OpenClawWorkspace).HasMaxLength(2048);
|
||||
entity.Property(x => x.LastErrorCode).HasMaxLength(120);
|
||||
entity.Property(x => x.LastErrorMessage).HasMaxLength(2000);
|
||||
entity.Property(x => x.Revision).IsConcurrencyToken();
|
||||
entity.HasIndex(x => new { x.Status, x.UpdatedAt });
|
||||
entity.HasIndex(x => x.RequestedAgentId);
|
||||
entity.HasIndex(x => x.OpenClawAgentId);
|
||||
});
|
||||
|
||||
modelBuilder.Entity<AgentProvisionRequest>(entity =>
|
||||
{
|
||||
entity.Property(x => x.Stage).HasMaxLength(40);
|
||||
entity.Property(x => x.Status).HasMaxLength(40);
|
||||
entity.Property(x => x.IdempotencyKeyHash).HasMaxLength(64);
|
||||
entity.Property(x => x.Actor).HasMaxLength(240);
|
||||
entity.Property(x => x.CorrelationId).HasMaxLength(200);
|
||||
entity.Property(x => x.TraceParent).HasMaxLength(128);
|
||||
entity.Property(x => x.OpenClawAgentId).HasMaxLength(128);
|
||||
entity.Property(x => x.LastErrorCode).HasMaxLength(120);
|
||||
entity.Property(x => x.LastErrorMessage).HasMaxLength(2000);
|
||||
entity.Property(x => x.LeaseOwner).HasMaxLength(160);
|
||||
entity.Property(x => x.Revision).IsConcurrencyToken();
|
||||
entity.HasIndex(x => new { x.ProposalId, x.Attempt }).IsUnique();
|
||||
entity.HasIndex(x => new { x.Status, x.CreatedAt });
|
||||
entity.HasIndex(x => x.LeaseUntil);
|
||||
entity.HasOne(x => x.Proposal)
|
||||
.WithMany(x => x.ProvisionRequests)
|
||||
.HasForeignKey(x => x.ProposalId)
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
|
||||
modelBuilder.Entity<OperationClaim>(entity =>
|
||||
{
|
||||
entity.Property(x => x.Operation).HasMaxLength(100);
|
||||
entity.Property(x => x.IdempotencyKeyHash).HasMaxLength(64);
|
||||
entity.Property(x => x.RequestHash).HasMaxLength(64);
|
||||
entity.Property(x => x.State).HasMaxLength(40);
|
||||
entity.Property(x => x.ResultCode).HasMaxLength(120);
|
||||
entity.HasIndex(x => new { x.Operation, x.IdempotencyKeyHash }).IsUnique();
|
||||
entity.HasIndex(x => x.ExpiresAt);
|
||||
});
|
||||
|
||||
modelBuilder.Entity<OutboxEvent>(entity =>
|
||||
{
|
||||
entity.HasKey(x => x.Sequence);
|
||||
entity.Property(x => x.Sequence).ValueGeneratedOnAdd();
|
||||
entity.Property(x => x.Type).HasMaxLength(120);
|
||||
entity.Property(x => x.AggregateType).HasMaxLength(80);
|
||||
entity.Property(x => x.AggregateId).HasMaxLength(128);
|
||||
entity.Property(x => x.PayloadJson).HasColumnType("jsonb");
|
||||
entity.Property(x => x.LastErrorCode).HasMaxLength(120);
|
||||
entity.HasIndex(x => x.EventId).IsUnique();
|
||||
entity.HasIndex(x => new { x.PublishedAt, x.Sequence });
|
||||
entity.HasIndex(x => x.OccurredAt);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||
using Nexus.Api.Models;
|
||||
|
||||
namespace Nexus.Api.Data;
|
||||
|
||||
/// <summary>
|
||||
/// Secret-free metadata for Nexus' one active OpenClaw connection.
|
||||
/// Device private keys, device tokens, bootstrap tokens and provider credentials
|
||||
/// are intentionally outside this entity.
|
||||
/// </summary>
|
||||
[Table("OpenClawConnectionProfiles")]
|
||||
public sealed class OpenClawConnectionProfile
|
||||
{
|
||||
public const string PrimaryProfileId = "primary";
|
||||
|
||||
[Key]
|
||||
[MaxLength(40)]
|
||||
public string ProfileId { get; set; } = PrimaryProfileId;
|
||||
|
||||
[MaxLength(2048)]
|
||||
public required string Endpoint { get; set; }
|
||||
|
||||
[MaxLength(80)]
|
||||
public required string DiscoverySource { get; set; }
|
||||
|
||||
[MaxLength(120)]
|
||||
public string? RequiredVersion { get; set; }
|
||||
|
||||
[MaxLength(128)]
|
||||
public string? TlsCertificateFingerprint { get; set; }
|
||||
|
||||
[MaxLength(40)]
|
||||
public string AdoptionState { get; set; } = OpenClawAdoptionStates.None;
|
||||
|
||||
public bool ManagementEnabled { get; set; }
|
||||
|
||||
[MaxLength(128)]
|
||||
public string? CapabilityHash { get; set; }
|
||||
|
||||
[MaxLength(240)]
|
||||
public string? DeviceId { get; set; }
|
||||
|
||||
public int Revision { get; set; }
|
||||
|
||||
public DateTimeOffset CreatedAt { get; set; } = DateTimeOffset.UtcNow;
|
||||
|
||||
public DateTimeOffset UpdatedAt { get; set; } = DateTimeOffset.UtcNow;
|
||||
|
||||
public DateTimeOffset? LastProbedAt { get; set; }
|
||||
|
||||
public DateTimeOffset? LastVerifiedAt { get; set; }
|
||||
|
||||
public DateTimeOffset? AdoptedAt { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Kept next to the entity so the root integration only has to apply this
|
||||
/// configuration from NexusDbContext.OnModelCreating.
|
||||
/// </summary>
|
||||
public sealed class OpenClawConnectionProfileConfiguration
|
||||
: IEntityTypeConfiguration<OpenClawConnectionProfile>
|
||||
{
|
||||
public void Configure(EntityTypeBuilder<OpenClawConnectionProfile> entity)
|
||||
{
|
||||
entity.ToTable(
|
||||
"OpenClawConnectionProfiles",
|
||||
table => table.HasCheckConstraint(
|
||||
"CK_OpenClawConnectionProfiles_Primary",
|
||||
"\"ProfileId\" = 'primary'"));
|
||||
entity.HasKey(profile => profile.ProfileId);
|
||||
entity.Property(profile => profile.Revision).IsConcurrencyToken();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
namespace Nexus.Api.Data;
|
||||
|
||||
/// <summary>
|
||||
/// Durable Nexus projection of one OpenClaw chat run. Nexus owns the
|
||||
/// correlation and audit metadata; OpenClaw remains the execution authority.
|
||||
/// </summary>
|
||||
public sealed class OpenClawRun
|
||||
{
|
||||
public Guid Id { get; init; } = Guid.NewGuid();
|
||||
public required string Title { get; set; }
|
||||
public required string Prompt { get; set; }
|
||||
public required string AgentId { get; set; }
|
||||
public required string SessionKey { get; set; }
|
||||
public string Status { get; set; } = OpenClawRunStates.Dispatching;
|
||||
public Guid? TaskId { get; set; }
|
||||
public Guid? ProjectId { get; set; }
|
||||
public string? OpenClawRunId { get; set; }
|
||||
public Guid? RetriedFromRunId { get; set; }
|
||||
public required string StartIdempotencyKey { get; set; }
|
||||
public required string CorrelationId { get; set; }
|
||||
public required string Actor { get; set; }
|
||||
public string? TraceParent { get; set; }
|
||||
public string? LastError { get; set; }
|
||||
public long? LastGatewaySequence { get; set; }
|
||||
public bool SequenceGapDetected { get; set; }
|
||||
public int Revision { get; set; }
|
||||
public DateTimeOffset CreatedAt { get; set; } = DateTimeOffset.UtcNow;
|
||||
public DateTimeOffset UpdatedAt { get; set; } = DateTimeOffset.UtcNow;
|
||||
public DateTimeOffset? StartedAt { get; set; }
|
||||
public DateTimeOffset? FinishedAt { get; set; }
|
||||
public ICollection<OpenClawRunHistory> History { get; set; } = new List<OpenClawRunHistory>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Append-only action and state-transition ledger for an OpenClaw run.
|
||||
/// </summary>
|
||||
public sealed class OpenClawRunHistory
|
||||
{
|
||||
public long Id { get; init; }
|
||||
public Guid RunId { get; set; }
|
||||
public OpenClawRun Run { get; set; } = null!;
|
||||
public required string Action { get; set; }
|
||||
public required string FromStatus { get; set; }
|
||||
public required string ToStatus { get; set; }
|
||||
public required string Message { get; set; }
|
||||
public required string Actor { get; set; }
|
||||
public required string CorrelationId { get; set; }
|
||||
public string? IdempotencyKey { get; set; }
|
||||
public string? TraceParent { get; set; }
|
||||
public string? GatewayEventId { get; set; }
|
||||
public long? GatewaySequence { get; set; }
|
||||
public bool SequenceGapDetected { get; set; }
|
||||
public Guid? ResultRunId { get; set; }
|
||||
public DateTimeOffset OccurredAt { get; set; } = DateTimeOffset.UtcNow;
|
||||
}
|
||||
|
||||
public static class OpenClawRunStates
|
||||
{
|
||||
public const string Dispatching = "dispatching";
|
||||
public const string Running = "running";
|
||||
public const string Stopping = "stopping";
|
||||
public const string Stopped = "stopped";
|
||||
public const string Completed = "completed";
|
||||
public const string Failed = "failed";
|
||||
public const string Blocked = "blocked";
|
||||
public const string Unsupported = "unsupported";
|
||||
|
||||
public static bool IsTerminal(string state)
|
||||
=> state is Stopped or Completed or Failed or Blocked or Unsupported;
|
||||
}
|
||||
Reference in New Issue
Block a user