working on workflows

This commit is contained in:
2026-03-04 22:02:34 -06:00
parent b54aa3ec26
commit 7438f92502
63 changed files with 10231 additions and 731 deletions

View File

@@ -45,6 +45,8 @@ import {
generateUniqueTaskName,
generateTaskId,
builderStateToDefinition,
builderStateToGraph,
builderStateToActionYaml,
definitionToBuilderState,
validateWorkflow,
addTransitionTarget,
@@ -585,12 +587,14 @@ export default function WorkflowBuilderPage() {
doSave();
}, [startNodeWarning, doSave]);
// YAML preview — generate proper YAML from builder state
const yamlPreview = useMemo(() => {
// YAML previewstwo separate panels for the two-file model:
// 1. Action YAML (ref, label, parameters, output, tags, workflow_file)
// 2. Workflow YAML (version, vars, tasks, output_map — graph only)
const actionYamlPreview = useMemo(() => {
if (!showYamlPreview) return "";
try {
const definition = builderStateToDefinition(state, actionSchemaMap);
return yaml.dump(definition, {
const actionDef = builderStateToActionYaml(state);
return yaml.dump(actionDef, {
indent: 2,
lineWidth: 120,
noRefs: true,
@@ -599,7 +603,24 @@ export default function WorkflowBuilderPage() {
forceQuotes: false,
});
} catch {
return "# Error generating YAML preview";
return "# Error generating action YAML preview";
}
}, [state, showYamlPreview]);
const workflowYamlPreview = useMemo(() => {
if (!showYamlPreview) return "";
try {
const graphDef = builderStateToGraph(state, actionSchemaMap);
return yaml.dump(graphDef, {
indent: 2,
lineWidth: 120,
noRefs: true,
sortKeys: false,
quotingType: '"',
forceQuotes: false,
});
} catch {
return "# Error generating workflow YAML preview";
}
}, [state, showYamlPreview, actionSchemaMap]);
@@ -854,26 +875,64 @@ export default function WorkflowBuilderPage() {
{/* Main content area */}
<div className="flex-1 flex overflow-hidden">
{showYamlPreview ? (
/* Raw YAML mode — full-width YAML view */
<div className="flex-1 flex flex-col overflow-hidden bg-gray-900">
<div className="flex items-center gap-2 px-4 py-2 bg-gray-800 border-b border-gray-700 flex-shrink-0">
<FileCode className="w-4 h-4 text-gray-400" />
<span className="text-sm font-medium text-gray-300">
Workflow Definition
</span>
<span className="text-[10px] text-gray-500 ml-1">
(read-only preview of the generated YAML)
</span>
<div className="ml-auto">
/* Raw YAML mode — two-panel view: Action YAML + Workflow YAML */
<div className="flex-1 flex overflow-hidden">
{/* Left panel: Action YAML */}
<div className="w-2/5 flex flex-col overflow-hidden bg-gray-900 border-r border-gray-700">
<div className="flex items-center gap-2 px-4 py-2 bg-gray-800 border-b border-gray-700 flex-shrink-0">
<FileCode className="w-4 h-4 text-blue-400" />
<span className="text-sm font-medium text-gray-300">
Action YAML
</span>
<span className="text-[10px] text-gray-500 ml-1">
actions/{state.name}.yaml
</span>
<div className="flex-1" />
<button
onClick={() => {
navigator.clipboard.writeText(yamlPreview).then(() => {
setYamlCopied(true);
setTimeout(() => setYamlCopied(false), 2000);
});
navigator.clipboard.writeText(actionYamlPreview);
}}
className="flex items-center gap-1.5 px-2.5 py-1 text-xs font-medium rounded transition-colors text-gray-400 hover:text-gray-200 hover:bg-gray-700"
title="Copy YAML to clipboard"
className="flex items-center gap-1 px-2 py-1 text-xs text-gray-400 hover:text-gray-200 bg-gray-700 hover:bg-gray-600 rounded transition-colors"
title="Copy action YAML to clipboard"
>
<Copy className="w-3.5 h-3.5" />
<span>Copy</span>
</button>
</div>
<div className="px-4 py-2 bg-gray-800/50 border-b border-gray-700/50 flex-shrink-0">
<p className="text-[10px] text-gray-500 leading-relaxed">
Defines the action identity, parameters, and output schema.
References the workflow file via{" "}
<code className="text-gray-400">workflow_file</code>.
</p>
</div>
<pre className="flex-1 overflow-auto p-4 text-sm font-mono text-blue-300 whitespace-pre leading-relaxed">
{actionYamlPreview}
</pre>
</div>
{/* Right panel: Workflow YAML (graph only) */}
<div className="flex-1 flex flex-col overflow-hidden bg-gray-900">
<div className="flex items-center gap-2 px-4 py-2 bg-gray-800 border-b border-gray-700 flex-shrink-0">
<FileCode className="w-4 h-4 text-green-400" />
<span className="text-sm font-medium text-gray-300">
Workflow YAML
</span>
<span className="text-[10px] text-gray-500 ml-1">
actions/workflows/{state.name}.workflow.yaml
</span>
<div className="flex-1" />
<button
onClick={() => {
navigator.clipboard
.writeText(workflowYamlPreview)
.then(() => {
setYamlCopied(true);
setTimeout(() => setYamlCopied(false), 2000);
});
}}
className="flex items-center gap-1 px-2 py-1 text-xs text-gray-400 hover:text-gray-200 bg-gray-700 hover:bg-gray-600 rounded transition-colors"
title="Copy workflow YAML to clipboard"
>
{yamlCopied ? (
<>
@@ -883,15 +942,21 @@ export default function WorkflowBuilderPage() {
) : (
<>
<Copy className="w-3.5 h-3.5" />
Copy
<span>Copy</span>
</>
)}
</button>
</div>
<div className="px-4 py-2 bg-gray-800/50 border-b border-gray-700/50 flex-shrink-0">
<p className="text-[10px] text-gray-500 leading-relaxed">
Execution graph only tasks, transitions, variables. No
action-level metadata (those are in the action YAML).
</p>
</div>
<pre className="flex-1 overflow-auto p-4 text-sm font-mono text-green-400 whitespace-pre leading-relaxed">
{workflowYamlPreview}
</pre>
</div>
<pre className="flex-1 overflow-auto p-6 text-sm font-mono text-green-400 whitespace-pre leading-relaxed">
{yamlPreview}
</pre>
</div>
) : (
<>

View File

@@ -22,9 +22,9 @@ import { useState, useMemo } from "react";
import { RotateCcw, Loader2 } from "lucide-react";
import ExecuteActionModal from "@/components/common/ExecuteActionModal";
import EntityHistoryPanel from "@/components/common/EntityHistoryPanel";
import WorkflowTasksPanel from "@/components/common/WorkflowTasksPanel";
import ExecutionArtifactsPanel from "@/components/executions/ExecutionArtifactsPanel";
import ExecutionProgressBar from "@/components/executions/ExecutionProgressBar";
import WorkflowDetailsPanel from "@/components/executions/WorkflowDetailsPanel";
const getStatusColor = (status: string) => {
switch (status) {
@@ -279,6 +279,16 @@ export default function ExecutionDetailPage() {
)}
</div>
{/* Workflow Details — combined timeline + tasks panel (top of page for workflows) */}
{isWorkflow && (
<div className="mb-6">
<WorkflowDetailsPanel
parentExecution={execution}
actionRef={execution.action_ref}
/>
</div>
)}
{/* Re-Run Modal */}
{showRerunModal && actionData?.data && (
<ExecuteActionModal
@@ -542,13 +552,6 @@ export default function ExecutionDetailPage() {
</div>
</div>
{/* Workflow Tasks (shown only for workflow executions) */}
{isWorkflow && (
<div className="mt-6">
<WorkflowTasksPanel parentExecutionId={execution.id} />
</div>
)}
{/* Artifacts */}
<div className="mt-6">
<ExecutionArtifactsPanel