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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 1 addition & 7 deletions src/AgentOs.Modules.Pipeline/Agents/AgentsOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -84,13 +84,7 @@ public bool IsValid() => AgentRoles.All.All(r => For(r.Key) is { } a
&& a.MaxTokens > 0);

/// <summary>Every configured agent, for cross-cutting checks (startup validation).</summary>
public IEnumerable<AgentOptions> All()
{
foreach (var role in AgentRoles.All)
{
if (For(role.Key) is { } options) { yield return options; }
}
}
public IEnumerable<AgentOptions> All() => AgentRoles.All.Select(role => For(role.Key)).OfType<AgentOptions>();
}

/// <summary>Configuration for a single agent.</summary>
Expand Down
10 changes: 3 additions & 7 deletions src/AgentOs.Modules.Pipeline/Agents/TicketFlowDefinition.cs
Original file line number Diff line number Diff line change
Expand Up @@ -363,13 +363,9 @@ public static IReadOnlyList<TicketFlowProblem> Validate(TicketFlowDefinition? de
}

// Edges: known steps; pass = one next step each (none after Merge, none into Code); fail = back to Code only.
foreach (var e in definition.Edges)
{
if (!byId.ContainsKey(e.From) || !byId.ContainsKey(e.To))
{
problems.Add(new(null, $"An edge points at a step that doesn't exist ({e.From} → {e.To})."));
}
}
problems.AddRange(definition.Edges
.Where(e => !byId.ContainsKey(e.From) || !byId.ContainsKey(e.To))
.Select(e => new TicketFlowProblem(null, $"An edge points at a step that doesn't exist ({e.From} → {e.To}).")));
var edges = definition.Edges.Where(e => byId.ContainsKey(e.From) && byId.ContainsKey(e.To)).ToList();
var pass = edges.Where(e => e.When == TicketFlowEdgeWhen.Pass).ToList();
var fail = edges.Where(e => e.When == TicketFlowEdgeWhen.Fail).ToList();
Expand Down
9 changes: 4 additions & 5 deletions src/AgentOs.Web/Components/Pages/AgentProfilesApp.razor
Original file line number Diff line number Diff line change
Expand Up @@ -231,11 +231,10 @@ else
{
foreach (var field in RoleFields.Where(f => byKey.GetValueOrDefault(AgentSettings.Key(role, f))?.Source is null or SettingSource.Default))
{
if (await Legacy.ReadAsync(role, field, _tenantId) is { } old)
{
row.Loaded[field] = old;
row.Legacy = true;
}
var old = await Legacy.ReadAsync(role, field, _tenantId);
if (old is null) { continue; }
row.Loaded[field] = old;
row.Legacy = true;
}
}
row.Provider = row.Loaded.GetValueOrDefault(ProviderField, string.Empty);
Expand Down
2 changes: 1 addition & 1 deletion src/AgentOs.Web/Services/BoardTasks/BoardTaskService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -552,7 +552,7 @@ await sessRepo.UpdateRepoRunResultAsync(tenantId, outcome.SessionRepoId, "Failed
// It used to mark the repo Failed and drop the pull request link: Autopilot lost track of the open PR
// and started the ticket over on a new branch (VNChess #95 / PR #97, 2026-10-24).
var stood = children.FirstOrDefault(c => c.Id == outcome.SessionRepoId);
if (FailedFollowUpKeepsItsChange(change is not null, stood?.Status, stood?.PrUrl) && stood is not null)
if (stood is not null && FailedFollowUpKeepsItsChange(change is not null, stood.Status, stood.PrUrl))
{
await sessRepo.UpdateRepoRunResultAsync(tenantId, stood.Id, stood.Status, stood.BranchName, stood.PrUrl,
"The last fix attempt failed: " + (outcome.Error ?? "Agent failed.")).ConfigureAwait(false);
Expand Down
9 changes: 4 additions & 5 deletions tests/AgentOs.E2E.Tests/AgentOsUi/TicketFlowTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -63,11 +63,10 @@ private static async Task EnsureDefaultAsync(ILocator win)
var changed = false;
foreach (var step in new[] { "review", "test" })
{
if (await Card(win, step).GetAttributeAsync("class") is { } css && css.Contains("run-skipped", StringComparison.Ordinal))
{
await SetRunsAsync(win, step, on: true);
changed = true;
}
var css = await Card(win, step).GetAttributeAsync("class");
if (css is null || !css.Contains("run-skipped", StringComparison.Ordinal)) { continue; }
await SetRunsAsync(win, step, on: true);
changed = true;
}
if (changed)
{
Expand Down
15 changes: 7 additions & 8 deletions tests/AgentOs.Tests/Agents/AgentRegistryGuardTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -75,15 +75,14 @@ BinaryExpressionSyntax b when b.IsKind(SyntaxKind.AddExpression) => HardCoded(b.
_ => false,
};

foreach (var call in root.DescendantNodes().OfType<InvocationExpressionSyntax>())
foreach (var (call, provider) in root.DescendantNodes().OfType<InvocationExpressionSyntax>()
.Where(c => c.Expression is MemberAccessExpressionSyntax { Name.Identifier.ValueText: "Create" })
.Select(c => (Call: c, Provider: c.ArgumentList.Arguments.FirstOrDefault()))
.Where(x => x.Provider is { } p
&& p.NameColon is null or { Name.Identifier.ValueText: "providerName" }
&& HardCoded(p.Expression)))
{
if (call.Expression is MemberAccessExpressionSyntax { Name.Identifier.ValueText: "Create" }
&& call.ArgumentList.Arguments is [var provider, ..]
&& provider.NameColon is null or { Name.Identifier.ValueText: "providerName" }
&& HardCoded(provider.Expression))
{
yield return $"line {Line(call)}: ILlmClientFactory.Create({provider.Expression})";
}
yield return $"line {Line(call)}: ILlmClientFactory.Create({provider!.Expression})";
}

foreach (var creation in root.DescendantNodes().OfType<BaseObjectCreationExpressionSyntax>())
Expand Down
3 changes: 1 addition & 2 deletions tests/AgentOs.Tests/Web/TicketFlowDefinitionTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -229,9 +229,8 @@ public void Plan_WithoutAGate_IsUnsafe()
[Fact]
public void EveryStepKind_IsRegistered_WithRolesFromTheAgentRegistry()
{
foreach (var kind in System.Enum.GetValues<TicketStepKind>())
foreach (var info in System.Enum.GetValues<TicketStepKind>().Select(TicketStepKinds.Of))
{
var info = TicketStepKinds.Of(kind);
info.Roles.ShouldAllBe(r => AgentRoles.Find(r) != null);
}
TicketStepKinds.Of(TicketStepKind.Code).DefaultRole.ShouldBe(AgentRoles.IssueWork);
Expand Down
Loading