frontend_nyla/src/api/workflowApi.ts
2025-12-01 17:01:25 +01:00

309 lines
8 KiB
TypeScript

import { ApiRequestOptions } from '../hooks/useApi';
// ============================================================================
// TYPES & INTERFACES
// ============================================================================
// Workflow interfaces
export interface Workflow {
id: string;
mandateId: string;
status: string;
name?: string;
workflowMode?: string;
[key: string]: any; // Allow additional properties
}
export interface WorkflowMessage {
[key: string]: any;
}
export interface WorkflowStats {
[key: string]: any;
}
export interface WorkflowDocument {
[key: string]: any;
}
export interface WorkflowLog {
[key: string]: any;
}
// Request/Response interfaces based on API documentation
export interface FileAttachment {
id: string;
name: string;
}
export interface UserInputRequest {
input: string;
files?: FileAttachment[]; // optional file attachments - array of {id, name} objects
metadata?: Record<string, any>; // optional metadata
}
export interface StartWorkflowRequest {
prompt: string;
listFileId?: string[]; // Array of file ID strings (files must be uploaded first via /api/files/upload)
userLanguage?: string; // Optional, defaults to "en"
metadata?: Record<string, any>;
}
export interface StartWorkflowResponse extends Workflow {
// Workflow object returned from start endpoint
}
export interface ChatDataResponse {
messages: WorkflowMessage[];
logs: WorkflowLog[];
stats: WorkflowStats[];
documents: WorkflowDocument[];
}
// Type for the request function passed to API functions
export type ApiRequestFunction = (options: ApiRequestOptions<any>) => Promise<any>;
// ============================================================================
// API REQUEST FUNCTIONS
// ============================================================================
/**
* Fetch all workflows for the current user
* Endpoint: GET /api/workflows/
*/
export async function fetchWorkflows(request: ApiRequestFunction): Promise<Workflow[]> {
const data = await request<Workflow[]>({
url: '/api/workflows/',
method: 'get'
});
return Array.isArray(data) ? data : [];
}
/**
* Fetch a single workflow by ID
* Endpoint: GET /api/workflows/{workflowId}
*/
export async function fetchWorkflow(
request: ApiRequestFunction,
workflowId: string
): Promise<Workflow> {
return await request<Workflow>({
url: `/api/workflows/${workflowId}`,
method: 'get'
});
}
/**
* Fetch workflow status (lightweight status check)
* Endpoint: GET /api/workflows/{workflowId}/status
*/
export async function fetchWorkflowStatus(
request: ApiRequestFunction,
workflowId: string
): Promise<Workflow> {
return await request<Workflow>({
url: `/api/workflows/${workflowId}/status`,
method: 'get'
});
}
/**
* Fetch workflow messages
* Endpoint: GET /api/workflows/{workflowId}/messages
* Query params: messageId (optional) - fetch only newer messages
*/
export async function fetchWorkflowMessages(
request: ApiRequestFunction,
workflowId: string,
messageId?: string
): Promise<WorkflowMessage[]> {
const params = messageId ? { messageId } : undefined;
const data = await request<WorkflowMessage[]>({
url: `/api/workflows/${workflowId}/messages`,
method: 'get',
params
});
return Array.isArray(data) ? data : [];
}
/**
* Fetch workflow logs
* Endpoint: GET /api/workflows/{workflowId}/logs
* Query params: logId (optional) - fetch only newer logs
*/
export async function fetchWorkflowLogs(
request: ApiRequestFunction,
workflowId: string,
logId?: string
): Promise<WorkflowLog[]> {
const params = logId ? { logId } : undefined;
const data = await request<WorkflowLog[]>({
url: `/api/workflows/${workflowId}/logs`,
method: 'get',
params
});
return Array.isArray(data) ? data : [];
}
/**
* Fetch unified chat data (messages, logs, stats, documents)
* Endpoint: GET /api/chat/playground/{workflowId}/chatData
* Query params: afterTimestamp (optional) - fetch only data created after this time
*/
export async function fetchChatData(
request: ApiRequestFunction,
workflowId: string,
afterTimestamp?: number
): Promise<ChatDataResponse> {
const params = afterTimestamp ? { afterTimestamp: afterTimestamp.toString() } : undefined;
const requestConfig = {
url: `/api/chat/playground/${workflowId}/chatData`,
method: 'get' as const,
params
};
console.log('📤 fetchChatData request:', requestConfig);
const data = await request<ChatDataResponse>(requestConfig);
console.log('📥 fetchChatData response:', data);
// Ensure all arrays exist
return {
messages: Array.isArray(data.messages) ? data.messages : [],
logs: Array.isArray(data.logs) ? data.logs : [],
stats: Array.isArray(data.stats) ? data.stats : [],
documents: Array.isArray(data.documents) ? data.documents : []
};
}
/**
* Start a new workflow or continue an existing one
* Endpoint: POST /api/chat/playground/start
* Query params: workflowId (optional), workflowMode (default: "Actionplan")
*/
export async function startWorkflowApi(
request: ApiRequestFunction,
workflowData: StartWorkflowRequest,
options?: { workflowId?: string; workflowMode?: 'Actionplan' | 'React' }
): Promise<StartWorkflowResponse> {
const params: Record<string, string> = {};
if (options?.workflowId) {
params.workflowId = options.workflowId;
}
if (options?.workflowMode) {
params.workflowMode = options.workflowMode;
}
const requestConfig = {
url: '/api/chat/playground/start',
method: 'post' as const,
data: workflowData,
params: Object.keys(params).length > 0 ? params : undefined
};
console.log('📤 startWorkflow request:', requestConfig);
const response = await request<StartWorkflowResponse>(requestConfig);
console.log('📥 startWorkflow response:', response);
return response;
}
/**
* Stop a running workflow
* Endpoint: POST /api/chat/playground/{workflowId}/stop
*/
export async function stopWorkflowApi(
request: ApiRequestFunction,
workflowId: string
): Promise<void> {
await request({
url: `/api/chat/playground/${workflowId}/stop`,
method: 'post'
});
}
/**
* Update workflow properties
* Endpoint: PUT /api/workflows/{workflowId}
*/
export async function updateWorkflowApi(
request: ApiRequestFunction,
workflowId: string,
updateData: Partial<{ name: string; description?: string; tags?: string[] }>
): Promise<Workflow> {
return await request<Workflow>({
url: `/api/workflows/${workflowId}`,
method: 'put',
data: updateData
});
}
/**
* Delete a workflow and all associated data
* Endpoint: DELETE /api/workflows/{workflowId}
*/
export async function deleteWorkflowApi(
request: ApiRequestFunction,
workflowId: string
): Promise<void> {
await request({
url: `/api/workflows/${workflowId}`,
method: 'delete'
});
}
/**
* Delete multiple workflows
*/
export async function deleteWorkflowsApi(
request: ApiRequestFunction,
workflowIds: string[]
): Promise<void> {
// Delete workflows one by one since there's no bulk delete endpoint
const deletePromises = workflowIds.map(workflowId =>
request({
url: `/api/workflows/${workflowId}`,
method: 'delete'
}).catch(error => {
console.error(`Failed to delete workflow ${workflowId}:`, error);
throw error;
})
);
await Promise.all(deletePromises);
}
/**
* Delete a message from a workflow
* Endpoint: DELETE /api/workflows/{workflowId}/messages/{messageId}
*/
export async function deleteMessageApi(
request: ApiRequestFunction,
workflowId: string,
messageId: string
): Promise<void> {
await request({
url: `/api/workflows/${workflowId}/messages/${messageId}`,
method: 'delete'
});
}
/**
* Delete a file reference from a message
* Endpoint: DELETE /api/workflows/{workflowId}/messages/{messageId}/files/{fileId}
*/
export async function deleteFileFromMessageApi(
request: ApiRequestFunction,
workflowId: string,
messageId: string,
fileId: string
): Promise<void> {
await request({
url: `/api/workflows/${workflowId}/messages/${messageId}/files/${fileId}`,
method: 'delete'
});
}