Files
aryx/src/renderer/components/settings/WorkspaceAgentEditor.tsx
T
David KayaandCopilot 805e369b67 refactor: remove legacy patterns system, unify on workflows
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>
2026-04-06 22:37:00 +02:00

139 lines
5.1 KiB
TypeScript

import { FormField, TextInput, TextareaInput } from '@renderer/components/ui';
import { ModelSelect, ReasoningEffortSelect } from '@renderer/components/AgentConfigFields';
import { findModel, type ModelDefinition } from '@shared/domain/models';
import { resolveReasoningEffort } from '@shared/domain/models';
import type { WorkspaceAgentDefinition } from '@shared/domain/workspaceAgent';
import type { WorkflowDefinition } from '@shared/domain/workflow';
import { findWorkspaceAgentUsages } from '@shared/domain/workspaceAgent';
import { ToolingEditorShell } from './ToolingEditorShell';
import { Link2, Workflow } from 'lucide-react';
function validateWorkspaceAgent(agent: WorkspaceAgentDefinition): string | undefined {
if (!agent.name.trim()) return 'Agent name is required.';
if (!agent.model.trim()) return 'Model is required.';
return undefined;
}
export function WorkspaceAgentEditor({
agent,
onChange,
onBack,
onSave,
onDelete,
availableModels,
workflows,
}: {
agent: WorkspaceAgentDefinition;
onChange: (agent: WorkspaceAgentDefinition) => void;
onBack: () => void;
onSave: () => Promise<void>;
onDelete?: () => Promise<void>;
availableModels: ReadonlyArray<ModelDefinition>;
workflows: WorkflowDefinition[];
}) {
const validationError = validateWorkspaceAgent(agent);
const usages = findWorkspaceAgentUsages(agent.id, workflows);
return (
<ToolingEditorShell
disableSave={Boolean(validationError)}
error={validationError}
onBack={onBack}
onDelete={onDelete}
onSave={onSave}
subtitle="Reusable agent definition"
title={agent.name || 'Untitled Agent'}
>
<section className="space-y-4">
<h4 className="text-[12px] font-semibold uppercase tracking-wider text-[var(--color-text-muted)]">
General
</h4>
<FormField label="Name" required>
<TextInput
onChange={(value) => onChange({ ...agent, name: value })}
placeholder="e.g. Code Reviewer, Architect, QA Agent"
value={agent.name}
/>
</FormField>
</section>
<section className="space-y-4">
<h4 className="text-[12px] font-semibold uppercase tracking-wider text-[var(--color-text-muted)]">
AI Configuration
</h4>
<div className="grid gap-4 sm:grid-cols-2">
<div>
<ModelSelect
models={availableModels}
onChange={(model) => {
const m = findModel(model, availableModels);
onChange({
...agent,
model,
reasoningEffort: resolveReasoningEffort(m, agent.reasoningEffort),
});
}}
value={agent.model}
/>
</div>
<div>
<ReasoningEffortSelect
onChange={(value) => onChange({ ...agent, reasoningEffort: value })}
supportedEfforts={findModel(agent.model, availableModels)?.supportedReasoningEfforts}
value={agent.reasoningEffort}
/>
</div>
</div>
</section>
<section className="space-y-4">
<h4 className="text-[12px] font-semibold uppercase tracking-wider text-[var(--color-text-muted)]">
Agent Identity
</h4>
<FormField label="Description">
<TextareaInput
onChange={(value) => onChange({ ...agent, description: value })}
placeholder="A short description of this agent's role and purpose"
rows={2}
value={agent.description}
/>
</FormField>
<FormField label="Instructions">
<TextareaInput
onChange={(value) => onChange({ ...agent, instructions: value })}
placeholder="System instructions that define this agent's behavior"
rows={8}
value={agent.instructions}
/>
</FormField>
</section>
{usages.length > 0 && (
<section className="space-y-3">
<h4 className="text-[12px] font-semibold uppercase tracking-wider text-[var(--color-text-muted)]">
Used By
</h4>
<div className="rounded-lg border border-[var(--color-border)] bg-[var(--color-glass)]">
{usages.map((usage) => (
<div
className="flex items-center gap-2.5 border-b border-[var(--color-border)] px-3.5 py-2.5 last:border-b-0"
key={usage.workflowId}
>
<Workflow className="size-3.5 shrink-0 text-[var(--color-text-muted)]" />
<span className="text-[13px] text-[var(--color-text-secondary)]">
{usage.workflowName}
</span>
<Link2 className="ml-auto size-3 text-[var(--color-accent)]" />
</div>
))}
</div>
<p className="text-[11px] text-[var(--color-text-muted)]">
Referenced by {usages.length} workflow{usages.length === 1 ? '' : 's'}.
Changes to this agent will affect all linked workflows.
</p>
</section>
)}
</ToolingEditorShell>
);
}