WorkflowDesigner.razor line ~282: HandleSave calls getWorkflowDefinition from JS but ignores the result — creates a new empty WorkflowDefinitionDto { Name = _workflowName } with no steps. Nothing saves.
Fix: Parse the JS-returned definition (nodes + edges + configs) into WorkflowDefinitionDto with StepDefinitionApiDto steps including Config dictionaries. This requires a CanvasToDefinition() converter that reconstructs the tree from flat nodes/edges.
Same issue — validates an empty definition instead of the actual canvas content.
New file: Services/DashboardSettingsService.cs
- In-memory settings store (Dictionary<string, string>)
- GET /api/settings → all settings
- PUT /api/settings → bulk update
- Sections: "providers", "general"
Settings model:
public class DashboardSettings
{
// AI Providers
public string? OllamaUrl { get; set; } // default: http://localhost:11434
public string? OpenAiApiKey { get; set; }
public string? AnthropicApiKey { get; set; }
public string? HuggingFaceApiKey { get; set; }
// Provider-specific
public string? OpenAiBaseUrl { get; set; } // for Azure OpenAI or proxies
public string? DefaultProvider { get; set; } // "ollama" | "openai" | "anthropic" | "huggingface"
public string? DefaultModel { get; set; }
// Execution
public int DefaultTimeoutSeconds { get; set; } = 300;
public int MaxConcurrentRuns { get; set; } = 5;
}New file: Components/Pages/Settings.razor
- Route:
/settings - Nav link in sidebar/header
- Sections with cards:
- AI Providers — Ollama URL (text), OpenAI Key (password), Anthropic Key (password), HuggingFace Key (password), Default Provider (dropdown), Default Model (dropdown populated from provider)
- Execution — Default timeout, max concurrent runs
- Save button, toast on success
- "Test Connection" button for Ollama (pings /api/tags)
New endpoint: GET /api/providers/{provider}/models
- For Ollama: calls
{ollamaUrl}/api/tags→ returns model names - For OpenAI: returns hardcoded list (gpt-4o, gpt-4o-mini, gpt-4-turbo, gpt-3.5-turbo, o1, o1-mini, o3-mini)
- For Anthropic: returns hardcoded list (claude-sonnet-4-20250514, claude-haiku-4-20250414, claude-opus-4-0520, claude-3-haiku)
- For HuggingFace: returns hardcoded popular inference models
Current schema only has type and enum. Extend StepTypeRegistry schemas with:
{
"properties": {
"provider": {
"type": "string",
"enum": ["ollama", "openai", "anthropic", "huggingface"],
"uiType": "providerSelect",
"label": "AI Provider",
"required": true,
"helpText": "Select the AI provider for this step"
},
"model": {
"type": "string",
"uiType": "modelSelect",
"label": "Model",
"required": true,
"dependsOn": "provider",
"helpText": "Model to use (populated from provider)"
},
"prompt": {
"type": "string",
"uiType": "textarea",
"label": "Prompt",
"rows": 6,
"helpText": "The prompt template. Use {variableName} for context variables."
},
"temperature": {
"type": "number",
"uiType": "slider",
"min": 0,
"max": 2,
"step": 0.1,
"default": 0.7
}
}
}Replace the current "everything is a text input" approach. Parse uiType from schema:
Also show:
- Required indicator (red asterisk)
- Help text below field
- Default value as placeholder
- Validation state (red border if required + empty)
AI/Agent steps (AgentLoopStep, LlmCallStep, AgentDecisionStep, AgentPlanStep):
provider→ providerSelect dropdownmodel→ modelSelect (dynamic from API, depends on provider)prompt/systemPrompt→ textarea (6 rows)temperature→ slider 0-2maxTokens→ number inputmaxIterations→ number input with defaulttools→ future: multi-select from registered tools; for now: textarea with comma-separated hint
HTTP steps (HttpStep, WebhookTriggerStep):
method→ select dropdown (already has enum)url→ text with URL validationheaders→ json textareabody→ json textareacontentType→ select (application/json, text/plain, application/xml, multipart/form-data)
Human Tasks (HumanTaskStep, ApprovalStep):
priority→ select dropdown (already has enum)assignee→ textdescription/message→ textarea
Data steps:
sourceFormat/targetFormat→ select (already has enum)mappings/schema→ json textarea
New method in WorkflowDesigner.razor: CanvasToDefinition()
- Calls
workflowEditor.getWorkflowDefinition()which returns{nodes: [...], edges: [...]} - Builds a tree from the flat graph:
- Find root nodes (no incoming edges)
- Walk edges to build sequential chain
- Detect container patterns (Conditional with then/else edges, Parallel with fan-out, etc.)
- Convert each node's
configdict back toStepDefinitionApiDto.Config
- Returns
WorkflowDefinitionDto
private async Task HandleSave()
{
var definition = await CanvasToDefinition();
definition.Name = _workflowName;
var request = new CreateWorkflowRequest { Definition = definition };
// ... save via API
}Same — validate the actual canvas definition.
WorkflowRunService.StartRunAsync currently stubs "Completed" immediately. Replace with:
- Build an
IWorkflowfrom theWorkflowDefinitionDtousing config - Resolve AI providers from settings (Ollama URL, API keys)
- Execute with real
WorkflowContext - Stream step status updates via SignalR
- Track actual duration, errors, output
This is the biggest piece — the WorkflowDefinitionDto → IWorkflow bridge. Need a WorkflowDefinitionCompiler that:
- Reads each
StepDefinitionDto - Based on
Type, creates the actual step instance - Wires up config (provider, model, prompt, etc.)
- Handles structural types (Conditional, Parallel, etc.) recursively
When executing, the compiler needs to create real IAgentProvider instances:
"ollama"→OllamaAgentProvider(settings.OllamaUrl)"openai"→OpenAiAgentProvider(settings.OpenAiApiKey)- etc.
Already have WorkflowExecutionHub / WorkflowExecutionNotifier — just need to wire them to real execution events.
Given token constraints, prioritize:
- Phase 3 (save round-trip fix) — without this, nothing works at all
- Phase 2a+2b (rich properties) — makes the UI usable
- Phase 1 (settings) — needed before execution
- Phase 4 (execution) — the ultimate goal
Each phase is a clean sub-agent task.
src/WorkflowFramework.Dashboard.Api/Services/DashboardSettingsService.cssrc/WorkflowFramework.Dashboard.Api/Services/WorkflowDefinitionCompiler.cssrc/WorkflowFramework.Dashboard.Web/Components/Pages/Settings.razor
src/WorkflowFramework.Dashboard.Api/Services/StepTypeRegistry.cs— enhanced schemassrc/WorkflowFramework.Dashboard.Api/Services/WorkflowRunService.cs— real executionsrc/WorkflowFramework.Dashboard.Api/DashboardApiExtensions.cs— settings + models endpointssrc/WorkflowFramework.Dashboard.Web/Components/Designer/PropertiesPanel.razor— rich controlssrc/WorkflowFramework.Dashboard.Web/Components/Designer/WorkflowDesigner.razor— save fix + canvas→definitionsrc/WorkflowFramework.Dashboard.Web/Models/ApiModels.cs— settings modelssrc/WorkflowFramework.Dashboard.Web/Services/DashboardApiClient.cs— settings + models API callssrc/WorkflowFramework.Dashboard.Web/wwwroot/js/workflow-editor.js— ensure getWorkflowDefinition returns config
tests/WorkflowFramework.Dashboard.Tests/— settings page teststests/WorkflowFramework.Dashboard.Api.Tests/— settings API, compiler, execution tests
