/** Workflow service for robotics-webapp frontend. */
const API_BASE_URL = import.meta.env.VITE_API_URL || 'http://localhost:8354/api';
export interface Workflow {
id: string;
name: string;
description: string;
category: 'avatar' | 'vbot' | 'sync' | 'custom';
version: string;
author: string;
tags: string[];
steps: WorkflowStep[];
variables: WorkflowVariable[];
error_handling: ErrorHandlingConfig;
metadata: Record<string, any>;
}
export interface WorkflowStep {
id: string;
order: number;
name: string;
type: 'mcp_tool' | 'app_launch' | 'condition' | 'loop' | 'parallel' | 'delay' | 'user_input';
mcp_server?: string;
tool_name?: string;
arguments?: Record<string, any>;
app_id?: string;
app_config?: AppLaunchConfig;
condition?: StepCondition;
on_success?: string[];
on_failure?: string[];
retry?: RetryConfig;
timeout?: number;
required: boolean;
output_variable?: string;
}
export interface WorkflowVariable {
name: string;
type: 'string' | 'number' | 'boolean' | 'file_path' | 'mcp_response';
default_value?: any;
description: string;
required: boolean;
source?: 'user_input' | 'step_output' | 'environment' | 'file';
}
export interface ErrorHandlingConfig {
on_error: 'stop' | 'continue' | 'retry' | 'rollback';
retry_count: number;
rollback_steps: string[];
error_notification: boolean;
}
export interface StepCondition {
expression: string;
true_branch: string[];
false_branch: string[];
}
export interface RetryConfig {
max_retries: number;
retry_delay: number;
exponential_backoff: boolean;
}
export interface AppLaunchConfig {
desktop?: number;
monitor?: number;
project_path?: string;
fullscreen: boolean;
}
export interface WorkflowExecution {
id: string;
workflow_id: string;
status: 'pending' | 'running' | 'paused' | 'debugging' | 'completed' | 'failed' | 'cancelled';
variables: Record<string, any>;
step_results: StepExecutionResult[];
started_at: string;
completed_at?: string;
error_message?: string;
current_step_id?: string;
debug_mode?: boolean;
step_outputs?: Record<string, any>;
}
export interface StepExecutionResult {
step_id: string;
step_name: string;
status: 'pending' | 'running' | 'completed' | 'failed' | 'skipped';
started_at?: string;
completed_at?: string;
output_data?: Record<string, any>;
error_message?: string;
retry_count: number;
mcp_tool_call?: {
mcp_server: string;
tool_name: string;
arguments: Record<string, any>;
original_arguments: Record<string, any>;
};
mcp_tool_response?: Record<string, any>;
}
export interface WorkflowTemplate {
id: string;
name: string;
description: string;
category: string;
steps: WorkflowStep[];
variables: WorkflowVariable[];
}
class WorkflowService {
async createWorkflow(workflowData: Partial<Workflow>): Promise<Workflow> {
const response = await fetch(`${API_BASE_URL}/workflows`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ workflow_data: workflowData }),
});
if (!response.ok) throw new Error(`Failed to create workflow: ${response.statusText}`);
const data = await response.json();
return data.workflow;
}
async getWorkflow(workflowId: string): Promise<Workflow> {
const response = await fetch(`${API_BASE_URL}/workflows/${workflowId}`);
if (!response.ok) throw new Error(`Failed to get workflow: ${response.statusText}`);
const data = await response.json();
return data.workflow;
}
async updateWorkflow(workflowId: string, workflowData: Partial<Workflow>): Promise<Workflow> {
const response = await fetch(`${API_BASE_URL}/workflows/${workflowId}`, {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ workflow_data: workflowData }),
});
if (!response.ok) throw new Error(`Failed to update workflow: ${response.statusText}`);
const data = await response.json();
return data.workflow;
}
async deleteWorkflow(workflowId: string): Promise<void> {
const response = await fetch(`${API_BASE_URL}/workflows/${workflowId}`, {
method: 'DELETE',
});
if (!response.ok) throw new Error(`Failed to delete workflow: ${response.statusText}`);
}
async listWorkflows(category?: string, tags?: string[], search?: string): Promise<Workflow[]> {
const params = new URLSearchParams();
if (category) params.append('category', category);
if (tags) params.append('tags', tags.join(','));
if (search) params.append('search', search);
const response = await fetch(`${API_BASE_URL}/workflows?${params.toString()}`);
if (!response.ok) throw new Error(`Failed to list workflows: ${response.statusText}`);
const data = await response.json();
return data.workflows;
}
async executeWorkflow(
workflowId: string,
variables: Record<string, any>,
debugMode: boolean = false
): Promise<{ execution_id: string }> {
const response = await fetch(`${API_BASE_URL}/workflows/${workflowId}/execute`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ variables, debug_mode: debugMode }),
});
if (!response.ok) throw new Error(`Failed to execute workflow: ${response.statusText}`);
const data = await response.json();
return { execution_id: data.execution_id };
}
async pauseExecution(executionId: string): Promise<void> {
const response = await fetch(`${API_BASE_URL}/workflows/executions/${executionId}/pause`, {
method: 'POST',
});
if (!response.ok) throw new Error(`Failed to pause execution: ${response.statusText}`);
}
async resumeExecution(executionId: string): Promise<void> {
const response = await fetch(`${API_BASE_URL}/workflows/executions/${executionId}/resume`, {
method: 'POST',
});
if (!response.ok) throw new Error(`Failed to resume execution: ${response.statusText}`);
}
async stepExecution(executionId: string): Promise<void> {
const response = await fetch(`${API_BASE_URL}/workflows/executions/${executionId}/step`, {
method: 'POST',
});
if (!response.ok) throw new Error(`Failed to step execution: ${response.statusText}`);
}
async continueExecution(executionId: string): Promise<void> {
const response = await fetch(`${API_BASE_URL}/workflows/executions/${executionId}/continue`, {
method: 'POST',
});
if (!response.ok) throw new Error(`Failed to continue execution: ${response.statusText}`);
}
async getExecutionStatus(executionId: string): Promise<WorkflowExecution> {
const response = await fetch(`${API_BASE_URL}/workflows/executions/${executionId}`);
if (!response.ok) throw new Error(`Failed to get execution status: ${response.statusText}`);
const data = await response.json();
return data.execution;
}
async getTemplates(): Promise<WorkflowTemplate[]> {
const response = await fetch(`${API_BASE_URL}/workflows/templates`);
if (!response.ok) throw new Error(`Failed to get templates: ${response.statusText}`);
const data = await response.json();
return data.templates;
}
async importWorkflow(workflowData: Partial<Workflow>): Promise<Workflow> {
const response = await fetch(`${API_BASE_URL}/workflows/import`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ workflow_data: workflowData }),
});
if (!response.ok) throw new Error(`Failed to import workflow: ${response.statusText}`);
const data = await response.json();
return data.workflow;
}
async exportWorkflow(workflowId: string): Promise<{ workflow_json: string; workflow: Workflow }> {
const response = await fetch(`${API_BASE_URL}/workflows/${workflowId}/export`);
if (!response.ok) throw new Error(`Failed to export workflow: ${response.statusText}`);
const data = await response.json();
return { workflow_json: data.workflow_json, workflow: data.workflow };
}
}
export const workflowService = new WorkflowService();