feat: workflow graph system — blocks 1-20 complete checkpoint
Full graph-based workflow execution engine with: - WorkflowGraphRuntime with two-phase dispatch (collect → fire Celery tasks) - Node registry with contract validation, socket types, execution kinds - WorkflowRuntimeServices: preflight, context resolution, shadow-mode A/B - WorkflowRouter: CRUD + dispatch/preflight/run-history API endpoints - OutputTypeContracts: workflow binding, rollout-mode resolution - Admin router: output-type workflow binding endpoints - Frontend: complete workflow editor with drag-drop canvas, node inspector, module bundles, reference bundles, preflight panel, validation banner, authoring guidance, blueprint templates, shadow/rollout gate UI - Tests: comprehensive coverage for all workflow modules - Docs: NODE_CONTRACT_AUDIT and VALIDATION_ERROR_INVENTORY All 20 blocks from NEXT_20_BLOCK_BATCH_PLAN completed. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,103 @@
|
||||
import { ArrowRight } from 'lucide-react'
|
||||
|
||||
import type {
|
||||
WorkflowAuthoringSection,
|
||||
WorkflowAuthoringSectionConfig,
|
||||
} from './workflowAuthoringSections'
|
||||
|
||||
type WorkflowAuthoringSectionSelectorProps = {
|
||||
sections: WorkflowAuthoringSectionConfig[]
|
||||
activeSection: WorkflowAuthoringSection
|
||||
onSelectSection: (section: WorkflowAuthoringSection) => void
|
||||
variant?: 'pill' | 'card'
|
||||
}
|
||||
|
||||
export function WorkflowAuthoringSectionSelector({
|
||||
sections,
|
||||
activeSection,
|
||||
onSelectSection,
|
||||
variant = 'pill',
|
||||
}: WorkflowAuthoringSectionSelectorProps) {
|
||||
if (variant === 'card') {
|
||||
return (
|
||||
<div className="grid gap-2 sm:grid-cols-2">
|
||||
{sections.map(section => {
|
||||
const Icon = section.icon
|
||||
const isActive = activeSection === section.key
|
||||
const toneLabel = section.tone === 'Escape Hatch' ? 'Direct' : section.tone
|
||||
|
||||
return (
|
||||
<button
|
||||
key={section.key}
|
||||
type="button"
|
||||
onClick={() => onSelectSection(section.key)}
|
||||
aria-label={section.label}
|
||||
className={`min-h-[76px] rounded-2xl border px-3 py-2.5 text-left transition-colors ${
|
||||
isActive
|
||||
? 'border-accent/40 bg-accent-light'
|
||||
: 'border-border-default bg-surface hover:bg-surface-hover'
|
||||
}`}
|
||||
title={section.helper}
|
||||
>
|
||||
<div className="flex h-full items-start justify-between gap-2">
|
||||
<div className="min-w-0">
|
||||
<span className="inline-flex items-center gap-2 text-sm font-medium text-content">
|
||||
<Icon size={14} />
|
||||
{section.label}
|
||||
</span>
|
||||
<div className="mt-1 flex flex-wrap items-center gap-1.5 text-[11px] text-content-muted">
|
||||
<span
|
||||
className={`rounded-full px-2 py-0.5 font-medium ${
|
||||
section.tone === 'Escape Hatch'
|
||||
? 'border border-border-default bg-surface text-content-muted'
|
||||
: 'bg-slate-100 text-slate-700 dark:bg-slate-900/40 dark:text-slate-300'
|
||||
}`}
|
||||
>
|
||||
{toneLabel}
|
||||
</span>
|
||||
{section.summaryLabel && (
|
||||
<span className="rounded-full border border-border-default bg-surface px-2 py-0.5">
|
||||
{section.summaryLabel}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
<p className="mt-1 line-clamp-1 text-[11px] text-content-muted">
|
||||
{section.helper}
|
||||
</p>
|
||||
</div>
|
||||
<div className="flex shrink-0 items-center gap-1.5 self-center">
|
||||
{isActive && <ArrowRight size={14} className="text-content-secondary" />}
|
||||
</div>
|
||||
</div>
|
||||
</button>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="flex flex-wrap gap-2">
|
||||
{sections.map(section => {
|
||||
const Icon = section.icon
|
||||
const isActive = activeSection === section.key
|
||||
return (
|
||||
<button
|
||||
key={section.key}
|
||||
type="button"
|
||||
onClick={() => onSelectSection(section.key)}
|
||||
className={`inline-flex items-center gap-1 rounded-full px-3 py-1.5 text-xs font-medium transition-colors ${
|
||||
isActive
|
||||
? 'bg-accent text-white'
|
||||
: 'border border-border-default bg-surface text-content-secondary hover:bg-surface-hover'
|
||||
}`}
|
||||
title={section.helper}
|
||||
>
|
||||
<Icon size={12} />
|
||||
{section.label}
|
||||
</button>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user