mirror of
https://github.com/davidkaya/aryx.git
synced 2026-08-26 12:53:59 +02:00
Remove the entire patterns domain model, IPC channels, sidecar services, renderer components, and tests. Sessions now bind exclusively to workflows via workflowId. Builtin workflows replace builtin patterns. Backend: - Make AgentNodeConfig standalone (no longer extends PatternAgentDefinition) - Add WorkflowOrchestrationMode and WorkflowExecutionDefinition - Create builtin workflows (single-agent, sequential, concurrent, handoff, group-chat) - Rewrite session model config helpers for workflow-only - Remove pattern IPC channels, handlers, and preload bindings - Merge createSession/createWorkflowSession into single method - Remove sidecar PatternGraphResolver, PatternValidator, pattern DTOs - Add workspace migration for legacy sessions (patternId -> workflowId) Frontend: - Delete PatternEditor, pattern-graph components, patternGraph lib - Delete NewSessionModal (session creation uses workflows directly) - Remove PatternsSection from SettingsPanel - Update App.tsx, ChatPane, ActivityPanel, Sidebar, RunTimeline, AgentConfigFields, InlinePills, sessionActivity to use workflow types - Delete pattern.ts domain module 78 files changed across backend and frontend. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
186 lines
5.6 KiB
C#
186 lines
5.6 KiB
C#
using System.Text;
|
|
using Aryx.AgentHost.Contracts;
|
|
|
|
namespace Aryx.AgentHost.Services;
|
|
|
|
internal readonly record struct AgentIdentity(string AgentId, string AgentName);
|
|
|
|
internal static class AgentIdentityResolver
|
|
{
|
|
private const string GenericAssistantIdentifier = "assistant";
|
|
|
|
public static bool TryResolveKnownAgentIdentity(
|
|
WorkflowDefinitionDto workflow,
|
|
string? agentIdentifier,
|
|
out AgentIdentity agent)
|
|
{
|
|
agent = default;
|
|
|
|
WorkflowNodeDto? match = FindKnownAgent(workflow, agentIdentifier)
|
|
?? ResolveSingleAgentAssistantAlias(workflow, agentIdentifier);
|
|
if (match is null)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
agent = ToAgentIdentity(match);
|
|
return true;
|
|
}
|
|
|
|
public static bool TryResolveObservedAgentIdentity(
|
|
WorkflowDefinitionDto workflow,
|
|
string? agentIdentifier,
|
|
AgentIdentity? fallbackAgent,
|
|
out AgentIdentity agent)
|
|
{
|
|
if (TryResolveKnownAgentIdentity(workflow, agentIdentifier, out agent))
|
|
{
|
|
return true;
|
|
}
|
|
|
|
if (fallbackAgent.HasValue && IsGenericAssistantIdentifier(agentIdentifier))
|
|
{
|
|
agent = fallbackAgent.Value;
|
|
return true;
|
|
}
|
|
|
|
agent = default;
|
|
return false;
|
|
}
|
|
|
|
public static AgentIdentity ResolveAgentIdentity(
|
|
WorkflowDefinitionDto workflow,
|
|
string? agentId,
|
|
string? agentName)
|
|
{
|
|
WorkflowNodeDto? match = FindKnownAgent(workflow, agentId)
|
|
?? FindKnownAgent(workflow, agentName)
|
|
?? ResolveSingleAgentAssistantAlias(workflow, agentId, agentName);
|
|
|
|
return match is not null
|
|
? ToAgentIdentity(match)
|
|
: CreateFallbackIdentity(agentId, agentName);
|
|
}
|
|
|
|
public static string ResolveDisplayAuthorName(
|
|
WorkflowDefinitionDto workflow,
|
|
string? primaryIdentifier,
|
|
string? fallbackIdentifier = null)
|
|
{
|
|
if (TryResolveKnownAgentIdentity(workflow, primaryIdentifier, out AgentIdentity primaryAgent))
|
|
{
|
|
return primaryAgent.AgentName;
|
|
}
|
|
|
|
if (TryResolveKnownAgentIdentity(workflow, fallbackIdentifier, out AgentIdentity fallbackAgent))
|
|
{
|
|
return fallbackAgent.AgentName;
|
|
}
|
|
|
|
if (!string.IsNullOrWhiteSpace(primaryIdentifier))
|
|
{
|
|
return primaryIdentifier;
|
|
}
|
|
|
|
if (!string.IsNullOrWhiteSpace(fallbackIdentifier))
|
|
{
|
|
return fallbackIdentifier;
|
|
}
|
|
|
|
return GenericAssistantIdentifier;
|
|
}
|
|
|
|
internal static bool IsGenericAssistantIdentifier(string? candidate)
|
|
{
|
|
return string.Equals(
|
|
NormalizeComparisonKey(candidate),
|
|
GenericAssistantIdentifier,
|
|
StringComparison.Ordinal);
|
|
}
|
|
|
|
private static WorkflowNodeDto? ResolveSingleAgentAssistantAlias(
|
|
WorkflowDefinitionDto workflow,
|
|
params string?[] agentIdentifiers)
|
|
{
|
|
IReadOnlyList<WorkflowNodeDto> agentNodes = workflow.GetAgentNodes();
|
|
return agentNodes.Count == 1 && agentIdentifiers.Any(IsGenericAssistantIdentifier)
|
|
? agentNodes[0]
|
|
: null;
|
|
}
|
|
|
|
private static WorkflowNodeDto? FindKnownAgent(WorkflowDefinitionDto workflow, string? candidate)
|
|
{
|
|
return workflow.GetAgentNodes().FirstOrDefault(agent => MatchesAgent(agent, candidate));
|
|
}
|
|
|
|
private static AgentIdentity ToAgentIdentity(WorkflowNodeDto agent)
|
|
=> new(agent.GetAgentId(), agent.GetAgentName());
|
|
|
|
private static AgentIdentity CreateFallbackIdentity(string? agentId, string? agentName)
|
|
{
|
|
string resolvedAgentId = !string.IsNullOrWhiteSpace(agentId)
|
|
? agentId
|
|
: agentName ?? "agent";
|
|
string resolvedAgentName = !string.IsNullOrWhiteSpace(agentName)
|
|
? agentName
|
|
: resolvedAgentId;
|
|
|
|
return new AgentIdentity(resolvedAgentId, resolvedAgentName);
|
|
}
|
|
|
|
private static bool MatchesAgent(WorkflowNodeDto agent, string? candidate)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(candidate))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
string agentId = agent.GetAgentId();
|
|
string agentName = agent.GetAgentName();
|
|
if (string.Equals(agentId, candidate, StringComparison.OrdinalIgnoreCase)
|
|
|| string.Equals(agentName, candidate, StringComparison.OrdinalIgnoreCase))
|
|
{
|
|
return true;
|
|
}
|
|
|
|
string normalizedCandidate = NormalizeComparisonKey(candidate);
|
|
string normalizedId = NormalizeComparisonKey(agentId);
|
|
string normalizedName = NormalizeComparisonKey(agentName);
|
|
if (normalizedCandidate.Length == 0)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (normalizedCandidate == normalizedId
|
|
|| normalizedCandidate == normalizedName)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
return normalizedId.Length > 0
|
|
&& normalizedName.Length > 0
|
|
&& (normalizedCandidate.EndsWith(normalizedId, StringComparison.Ordinal)
|
|
|| normalizedCandidate.Contains(normalizedId, StringComparison.Ordinal)
|
|
&& normalizedCandidate.Contains(normalizedName, StringComparison.Ordinal));
|
|
}
|
|
|
|
private static string NormalizeComparisonKey(string? value)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(value))
|
|
{
|
|
return string.Empty;
|
|
}
|
|
|
|
StringBuilder builder = new(value.Length);
|
|
foreach (char character in value)
|
|
{
|
|
if (char.IsLetterOrDigit(character))
|
|
{
|
|
builder.Append(char.ToLowerInvariant(character));
|
|
}
|
|
}
|
|
|
|
return builder.ToString();
|
|
}
|
|
}
|