diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 85619cf7..793d9f79 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -13,12 +13,12 @@ repos: - repo: local hooks: - # - id: eslint - # name: eslint - # entry: bash -c 'cd wavefront/client && pnpm lint' - # language: system - # files: ^wavefront/client/.*\.(js|jsx|ts|tsx)$ - # pass_filenames: false # let eslint use its own ignore & config + - id: eslint + name: eslint + entry: bash -c 'cd wavefront/client && pnpm eslint $(printf "%s\n" "$@" | sed "s|^wavefront/client/||")' -- + language: system + files: ^wavefront/client/.*\.(js|jsx|ts|tsx)$ + pass_filenames: true - id: typescript-check name: typescript-check @@ -29,7 +29,7 @@ repos: - id: prettier name: prettier - entry: bash -c 'cd wavefront/client && pnpm format' + entry: bash -c 'cd wavefront/client && pnpm prettier --write $(printf "%s\n" "$@" | sed "s|^wavefront/client/||")' -- language: system - files: ^wavefront/client/ - pass_filenames: false + files: ^wavefront/client/.*\.(js|jsx|ts|tsx|json|css|md)$ + pass_filenames: true diff --git a/wavefront/client/src/api/agent-service.ts b/wavefront/client/src/api/agent-service.ts index fa0a9e07..743b4173 100644 --- a/wavefront/client/src/api/agent-service.ts +++ b/wavefront/client/src/api/agent-service.ts @@ -50,14 +50,21 @@ export class AgentService { async runInference( id: string, - variables: Record = {}, + variables: Record = {}, inputs: string | string[], llmInferenceConfigId?: string, toolNames?: string[] ): Promise { - const requestBody: any = { + const requestBody: { + variables: Record; + inputs: string | string[]; + llm_inference_config_id?: string; + tool_names?: string[]; + output_json_enabled: boolean; + } = { variables, inputs, + output_json_enabled: false, }; if (llmInferenceConfigId) { @@ -68,8 +75,6 @@ export class AgentService { requestBody.tool_names = toolNames; } - requestBody.output_json_enabled = false; - const response: IApiResponse = await this.http.post( `/v1/:appId/floware/v2/agents/${id}/inference`, requestBody diff --git a/wavefront/client/src/api/datasources-service.ts b/wavefront/client/src/api/datasources-service.ts index a36ec406..6a549fcb 100644 --- a/wavefront/client/src/api/datasources-service.ts +++ b/wavefront/client/src/api/datasources-service.ts @@ -21,7 +21,7 @@ export class DatasourcesService { async createDatasource( name: string, type: string, - config: Record, + config: Record, description?: string ): Promise { const response: IApiResponse = await this.http.post(`/v1/:appId/floware/v1/datasources`, { @@ -44,7 +44,7 @@ export class DatasourcesService { datasourceId: string, name: string, type: string, - config: Record, + config: Record, description?: string ): Promise { const response: IApiResponse = await this.http.patch( diff --git a/wavefront/client/src/api/knowledge-base-service.ts b/wavefront/client/src/api/knowledge-base-service.ts index 3db1c598..95ba6002 100644 --- a/wavefront/client/src/api/knowledge-base-service.ts +++ b/wavefront/client/src/api/knowledge-base-service.ts @@ -52,7 +52,7 @@ export type KnowledgeBaseDocumentsListResponse = IApiResponse; @@ -74,7 +74,7 @@ export interface AllConfigsData { display_name: string; type: string; base_url: string; - parameters: any; + parameters: Record; is_deleted: boolean; created_at: string; updated_at: string; @@ -108,11 +108,11 @@ export class KnowledgeBaseService { return response; } - async uploadDocument(kbId: string, file: File): Promise> { + async uploadDocument(kbId: string, file: File): Promise> { const formData = new FormData(); formData.append('file', file); - const response: IApiResponse = await this.http.post( + const response: IApiResponse = await this.http.post( `/v1/:appId/floware/v1/knowledge-bases/${kbId}/documents`, formData, { @@ -192,8 +192,8 @@ export class KnowledgeBaseService { return response; } - async deleteSystemPrompt(kbId: string, inferenceId: string): Promise> { - const response: IApiResponse = await this.http.delete( + async deleteSystemPrompt(kbId: string, inferenceId: string): Promise> { + const response: IApiResponse = await this.http.delete( `/v1/:appId/floware/v1/knowledge-base/${kbId}/inference/${inferenceId}` ); return response; @@ -206,13 +206,13 @@ export class KnowledgeBaseService { return response; } - async deleteKnowledgeBase(kbId: string): Promise> { - const response: IApiResponse = await this.http.delete(`/v1/:appId/floware/v1/knowledge-bases/${kbId}`); + async deleteKnowledgeBase(kbId: string): Promise> { + const response: IApiResponse = await this.http.delete(`/v1/:appId/floware/v1/knowledge-bases/${kbId}`); return response; } - async deleteDocument(kbId: string, documentId: string): Promise> { - const response: IApiResponse = await this.http.delete( + async deleteDocument(kbId: string, documentId: string): Promise> { + const response: IApiResponse = await this.http.delete( `/v1/:appId/floware/v1/knowledge-bases/${kbId}/documents/${documentId}` ); return response; diff --git a/wavefront/client/src/api/model-inference-service.ts b/wavefront/client/src/api/model-inference-service.ts index 22874a51..d73110e3 100644 --- a/wavefront/client/src/api/model-inference-service.ts +++ b/wavefront/client/src/api/model-inference-service.ts @@ -3,7 +3,7 @@ import { AxiosInstance } from 'axios'; export interface PreprocessingStep { preprocess_filter: string; - values: any[]; + values: unknown[]; } interface ModelUploadResponseData { @@ -45,9 +45,9 @@ export interface InferencePayload { preprocessing_steps?: PreprocessingStep[]; } -interface ModelInferenceResultData { +export interface ModelInferenceResultData { clarity_score: number; - infer_data: any; // Type not explicitly defined in backend, so using 'any' + infer_data: unknown; // Type not explicitly defined in backend, so using 'unknown' data_type: string; } diff --git a/wavefront/client/src/api/voice-agent-service.ts b/wavefront/client/src/api/voice-agent-service.ts index 9ac87811..a70703cb 100644 --- a/wavefront/client/src/api/voice-agent-service.ts +++ b/wavefront/client/src/api/voice-agent-service.ts @@ -44,7 +44,10 @@ export class VoiceAgentService { return response; } - async initiateCall(agentId: string, data: { to_number: string; from_number?: string }): Promise { + async initiateCall( + agentId: string, + data: { to_number: string; from_number?: string } + ): Promise> { const response = await this.http.post(`/v1/:appId/floware/v1/voice-agents/${agentId}/initiate`, data); return response; } diff --git a/wavefront/client/src/components/ChatBot.tsx b/wavefront/client/src/components/ChatBot.tsx index c5aedb5d..7131889d 100644 --- a/wavefront/client/src/components/ChatBot.tsx +++ b/wavefront/client/src/components/ChatBot.tsx @@ -3,6 +3,7 @@ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@ import { Spinner } from '@app/components/ui/spinner'; import { Textarea } from '@app/components/ui/textarea'; import { LLMInferenceConfig } from '@app/types/llm-inference-config'; +import { ChatMessageContent, ImageContent, DocumentContent } from '@app/types/chat-message'; import clsx from 'clsx'; import { ChevronDown, Plus, X } from 'lucide-react'; import React, { useRef, useState, type RefObject } from 'react'; @@ -19,7 +20,7 @@ const formatFileSize = (bytes: number): string => { }; interface ChatBotProps { - chatHistory: { role: 'user' | 'assistant'; content: any }[]; + chatHistory: { role: 'user' | 'assistant'; content: ChatMessageContent }[]; runningInference: boolean; selectedLLMConfigId: string; setSelectedLLMConfigId: React.Dispatch>; @@ -148,21 +149,21 @@ const ChatBot = ({ > {typeof chat.content === 'string' ? ( chat.content - ) : chat.content?.image_base64 ? ( + ) : typeof chat.content === 'object' && chat.content !== null && 'image_base64' in chat.content ? (
Uploaded

- Image ({chat.content.mime_type}) + Image ({(chat.content as ImageContent).mime_type || 'unknown'})

- ) : chat.content?.document_type ? ( + ) : typeof chat.content === 'object' && chat.content !== null && 'document_type' in chat.content ? (
📄 - {chat.content.metadata?.filename || 'Document'} + {(chat.content as DocumentContent).metadata?.filename || 'Document'}
) : ( JSON.stringify(chat.content, null, 2) diff --git a/wavefront/client/src/config/authenticators.ts b/wavefront/client/src/config/authenticators.ts index 1ea584ad..08f55c80 100644 --- a/wavefront/client/src/config/authenticators.ts +++ b/wavefront/client/src/config/authenticators.ts @@ -4,7 +4,7 @@ export type ParameterType = 'string' | 'number' | 'boolean' | 'select' | 'array' export interface ParameterConfig { type: ParameterType; - default: any; + default: unknown; min?: number; max?: number; step?: number; @@ -303,15 +303,15 @@ export function getProviderBadge(authType: AuthenticatorType): { bg: string; tex } // Helper function to initialize parameters with defaults -export function initializeParameters(authType: AuthenticatorType): Record { +export function initializeParameters(authType: AuthenticatorType): Record { const config = getProviderConfig(authType); if (!config) return {}; - const params: Record = {}; + const params: Record = {}; Object.entries(config.parameters).forEach(([key, paramConfig]) => { if (paramConfig.type === 'object' && paramConfig.fields) { // Handle nested object parameters - const nestedParams: Record = {}; + const nestedParams: Record = {}; Object.entries(paramConfig.fields).forEach(([nestedKey, nestedConfig]) => { if (nestedConfig.default !== undefined) { nestedParams[nestedKey] = nestedConfig.default; @@ -328,8 +328,8 @@ export function initializeParameters(authType: AuthenticatorType): Record | null | undefined -): Record { + savedParams: Record | null | undefined +): Record { const defaultParams = initializeParameters(authType); if (!savedParams) return defaultParams; @@ -348,8 +348,8 @@ export function mergeParameters( } // Helper function to clean parameters (remove empty/undefined values) -export function cleanParameters(params: Record): Record { - const cleaned: Record = {}; +export function cleanParameters(params: Record): Record { + const cleaned: Record = {}; Object.entries(params).forEach(([key, value]) => { if (value === undefined || value === null) return; diff --git a/wavefront/client/src/config/llm-providers.ts b/wavefront/client/src/config/llm-providers.ts index e8705e18..fdf3b974 100644 --- a/wavefront/client/src/config/llm-providers.ts +++ b/wavefront/client/src/config/llm-providers.ts @@ -9,7 +9,7 @@ export type ParameterType = 'string' | 'number' | 'boolean' | 'select'; export interface ParameterConfig { type: ParameterType; - default: any; + default: unknown; min?: number; max?: number; step?: number; @@ -464,11 +464,11 @@ export function getProviderBadge(provider: InferenceEngineType): { bg: string; t /** * Initialize parameters with defaults for a provider */ -export function initializeParameters(provider: InferenceEngineType): Record { +export function initializeParameters(provider: InferenceEngineType): Record { const config = getProviderConfig(provider); if (!config) return {}; - const params: Record = {}; + const params: Record = {}; Object.entries(config.parameters).forEach(([key, paramConfig]) => { // Only include parameters with defined defaults if (paramConfig.default !== undefined) { @@ -485,8 +485,8 @@ export function initializeParameters(provider: InferenceEngineType): Record | null | undefined -): Record { + savedParams: Record | null | undefined +): Record { const defaultParams = initializeParameters(provider); if (!savedParams) return defaultParams; @@ -505,8 +505,8 @@ export function mergeParameters( /** * Clean parameters by removing undefined, null, and empty string values */ -export function cleanParameters(params: Record): Record { - const cleaned: Record = {}; +export function cleanParameters(params: Record): Record { + const cleaned: Record = {}; Object.entries(params).forEach(([key, value]) => { if (value !== undefined && value !== null && value !== '') { cleaned[key] = value; diff --git a/wavefront/client/src/config/voice-providers.ts b/wavefront/client/src/config/voice-providers.ts index af9c679d..1fa3be1d 100644 --- a/wavefront/client/src/config/voice-providers.ts +++ b/wavefront/client/src/config/voice-providers.ts @@ -9,7 +9,7 @@ export type ParameterType = 'string' | 'number' | 'boolean' | 'array'; export interface ParameterConfig { type: ParameterType; - default: any; + default: unknown; min?: number; max?: number; step?: number; @@ -257,11 +257,11 @@ export function getProviders(type: 'tts' | 'stt'): readonly string[] { /** * Initialize parameters with defaults for a provider */ -export function initializeParameters(type: 'tts' | 'stt', provider: string): Record { +export function initializeParameters(type: 'tts' | 'stt', provider: string): Record { const config = getProviderConfig(type, provider); if (!config) return {}; - const params: Record = {}; + const params: Record = {}; Object.entries(config.parameters).forEach(([key, paramConfig]) => { params[key] = paramConfig.default; }); @@ -275,8 +275,8 @@ export function initializeParameters(type: 'tts' | 'stt', provider: string): Rec export function mergeParameters( type: 'tts' | 'stt', provider: string, - savedParams: Record | null -): Record { + savedParams: Record | null +): Record { const defaultParams = initializeParameters(type, provider); if (!savedParams) return defaultParams; diff --git a/wavefront/client/src/hooks/data/query-functions.ts b/wavefront/client/src/hooks/data/query-functions.ts index 9542f837..39f7e225 100644 --- a/wavefront/client/src/hooks/data/query-functions.ts +++ b/wavefront/client/src/hooks/data/query-functions.ts @@ -40,7 +40,14 @@ const getAllDatasourcesQueryFn = async () => { const getDatasourceQueryFn = async (datasourceId: string): Promise => { const response = await floConsoleService.datasourcesService.getDatasource(datasourceId); if (response.data?.data) { - const responseData = response.data.data as any; + const responseData = response.data.data as { + name?: string; + type?: string; + config?: string | Record; + description?: string; + created_at?: string; + updated_at?: string; + }; return { id: datasourceId, name: responseData.name || 'Unknown', diff --git a/wavefront/client/src/lib/axios.ts b/wavefront/client/src/lib/axios.ts index f429f344..e422398f 100644 --- a/wavefront/client/src/lib/axios.ts +++ b/wavefront/client/src/lib/axios.ts @@ -8,12 +8,12 @@ export interface Meta { code: number; error?: string; } -export interface ApiResponse { +export interface ApiResponse { meta: Meta; data?: T; } export type IAxiosError = AxiosError; -export type IApiResponse = AxiosResponse>; +export type IApiResponse = AxiosResponse>; const axiosInstance = axios.create({ baseURL: appEnv.baseURL, diff --git a/wavefront/client/src/lib/utils.ts b/wavefront/client/src/lib/utils.ts index 5bfc5af4..8096427e 100644 --- a/wavefront/client/src/lib/utils.ts +++ b/wavefront/client/src/lib/utils.ts @@ -6,9 +6,68 @@ export function cn(...inputs: ClassValue[]) { return twMerge(clsx(inputs)); } +/** + * Extracts error message from various error object structures. + * Prioritizes the backend response format: + * - error.response.data.meta.error (primary backend format: { meta: { status: 'failure', code: -1, error: 'message' } }) + * - error.response.data.error.message (nested error object) + * - error.response.data.error (string) + * - error.response.data.message + * - error.message + * + * @param error - The error object (unknown type) + * @returns The extracted error message string, or undefined if no message found + */ +export function extractErrorMessage(error: unknown): string | undefined { + if (!error || typeof error !== 'object') { + return undefined; + } + + // Check if it's an axios-like error with response + if ('response' in error) { + const response = (error as { response?: { data?: unknown } }).response; + if (response?.data && typeof response.data === 'object' && response.data !== null) { + const data = response.data as Record; + + // Primary: Try meta.error (backend format: ResponseModel with meta.error) + if (data.meta && typeof data.meta === 'object' && data.meta !== null) { + const meta = data.meta as Record; + if (typeof meta.error === 'string' && meta.error) { + return meta.error; + } + } + + // Fallback: Try error.message (nested error object) + if (data.error && typeof data.error === 'object' && data.error !== null) { + const errorObj = data.error as Record; + if (typeof errorObj.message === 'string') { + return errorObj.message; + } + } + + // Fallback: Try error as string + if (typeof data.error === 'string' && data.error) { + return data.error; + } + + // Fallback: Try data.message + if (typeof data.message === 'string' && data.message) { + return data.message; + } + } + } + + // Fallback: Try direct error.message + if ('message' in error && typeof (error as { message?: unknown }).message === 'string') { + return (error as { message: string }).message; + } + + return undefined; +} + export const validateDynamicQueryYaml = (yaml_str: string) => { try { - const data = yaml.load(yaml_str) as Record; + const data = yaml.load(yaml_str) as Record; // top require keys const requiredTop = ['id', 'name', 'queries']; @@ -82,7 +141,7 @@ export const validateDynamicQueryYaml = (yaml_str: string) => { } } return { valid: true, error: '' }; - } catch (err) { + } catch { return { valid: false, error: 'Invalid YAML format' }; } }; diff --git a/wavefront/client/src/pages/apps/[appId]/agents/CreateAgentDialog.tsx b/wavefront/client/src/pages/apps/[appId]/agents/CreateAgentDialog.tsx index b003f582..4171ec4f 100644 --- a/wavefront/client/src/pages/apps/[appId]/agents/CreateAgentDialog.tsx +++ b/wavefront/client/src/pages/apps/[appId]/agents/CreateAgentDialog.tsx @@ -20,6 +20,7 @@ import { } from '@app/components/ui/form'; import { Input } from '@app/components/ui/input'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@app/components/ui/select'; +import { extractErrorMessage } from '@app/lib/utils'; import { useDashboardStore, useNotifyStore } from '@app/store'; import { zodResolver } from '@hookform/resolvers/zod'; import { langs } from '@uiw/codemirror-extensions-langs'; @@ -106,19 +107,8 @@ const CreateAgentDialog: React.FC = ({ } } catch (error) { console.error('Error creating agent:', error); - - let errorMessage = 'Failed to create agent'; - - if (error && typeof error === 'object' && 'response' in error) { - const response = (error as any).response; - if (response?.data?.meta?.error) { - errorMessage = response.data.meta.error; - } else if (response?.data?.message) { - errorMessage = response.data.message; - } - } - - notifyError(errorMessage); + const errorMessage = extractErrorMessage(error); + notifyError(errorMessage || 'Failed to create agent'); } }; diff --git a/wavefront/client/src/pages/apps/[appId]/agents/EditAgentDialog.tsx b/wavefront/client/src/pages/apps/[appId]/agents/EditAgentDialog.tsx index 49ccd3b1..5e0d38a9 100644 --- a/wavefront/client/src/pages/apps/[appId]/agents/EditAgentDialog.tsx +++ b/wavefront/client/src/pages/apps/[appId]/agents/EditAgentDialog.tsx @@ -95,9 +95,9 @@ const EditAgentDialog: React.FC = ({ localSelectedTools.some((selected) => selected.value === tool.display_name) ); - let parsedYaml: any; + let parsedYaml: unknown; try { - parsedYaml = yaml.load(localYamlContent) as any; + parsedYaml = yaml.load(localYamlContent); } catch (error) { console.error('Failed to parse YAML:', error); notifyError('Invalid YAML format. Please fix the YAML syntax before adding tools.'); diff --git a/wavefront/client/src/pages/apps/[appId]/agents/[id].tsx b/wavefront/client/src/pages/apps/[appId]/agents/[id].tsx index 7fc00061..26ed918b 100644 --- a/wavefront/client/src/pages/apps/[appId]/agents/[id].tsx +++ b/wavefront/client/src/pages/apps/[appId]/agents/[id].tsx @@ -14,6 +14,7 @@ import { useDeleteAgent } from '@app/hooks'; import { useGetAgent, useGetLLMConfigs, useGetTools } from '@app/hooks/data/fetch-hooks'; import { getAgentKey } from '@app/hooks/data/query-keys'; import { useNotifyStore } from '@app/store'; +import { ChatMessage, ChatMessageContent } from '@app/types/chat-message'; import { scrollToBottom } from '@app/utils/scroll'; import { useQueryClient } from '@tanstack/react-query'; import yaml from 'js-yaml'; @@ -67,7 +68,7 @@ const AgentDetail: React.FC = () => { }> >([]); const [uploadingDocument, setUploadingDocument] = useState(false); - const [chatHistory, setChatHistory] = useState<{ role: 'user' | 'assistant'; content: any }[]>([]); + const [chatHistory, setChatHistory] = useState([]); // Datasource and tool selection state const [selectedTools, setSelectedTools] = useState<{ id: string; value: string }[]>([]); @@ -129,7 +130,7 @@ const AgentDetail: React.FC = () => { if (isUpdatingYamlRef.current || !yamlContent || toolsDetails.length === 0) return; const tools = toolsDetails.filter((tool) => selectedTools.some((selected) => selected.value === tool.display_name)); - const parsedYaml = yaml.load(yamlContent) as any; + const parsedYaml = yaml.load(yamlContent) as { agent?: { tools?: unknown[] } } | null; if (parsedYaml && parsedYaml.agent) { if (!parsedYaml.agent.tools) { parsedYaml.agent.tools = []; @@ -161,7 +162,7 @@ const AgentDetail: React.FC = () => { const existingTools = parsedYaml.agent.tools || []; const toolsChanged = existingTools.length !== newTools.length || - existingTools.some((existingTool: any, index: number) => { + existingTools.some((existingTool: unknown, index: number) => { const newTool = newTools[index]; if (!newTool) return true; return ( @@ -398,8 +399,7 @@ const AgentDetail: React.FC = () => { let inputs: string | any[]; const finalTextInput = inferenceInput.trim(); // Handle different input combinations - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const conversationInputs: any[] = []; + const conversationInputs: Array<{ role: string; content: ChatMessageContent }> = []; // Add previous chat history chatHistory.forEach((message) => { @@ -472,7 +472,7 @@ const AgentDetail: React.FC = () => { selectedLLMConfigId || undefined, selectedTools.length > 0 ? selectedTools.map((tool) => tool.value) : undefined ); - const responseData = (result as any).data?.data?.data; + const responseData = (result as { data?: { data?: { data?: { result?: string | object } } } }).data?.data?.data; const agentResponse = typeof responseData?.result === 'string' ? responseData.result : JSON.stringify(responseData?.result, null, 2); setChatHistory((prev) => [...prev, { role: 'assistant', content: agentResponse }]); diff --git a/wavefront/client/src/pages/apps/[appId]/api-services/CreateApiServiceDialog.tsx b/wavefront/client/src/pages/apps/[appId]/api-services/CreateApiServiceDialog.tsx index 49be985f..d2c3ed4f 100644 --- a/wavefront/client/src/pages/apps/[appId]/api-services/CreateApiServiceDialog.tsx +++ b/wavefront/client/src/pages/apps/[appId]/api-services/CreateApiServiceDialog.tsx @@ -17,6 +17,7 @@ import { FormLabel, FormMessage, } from '@app/components/ui/form'; +import { extractErrorMessage } from '@app/lib/utils'; import { useDashboardStore, useNotifyStore } from '@app/store'; import { zodResolver } from '@hookform/resolvers/zod'; import { langs } from '@uiw/codemirror-extensions-langs'; @@ -97,19 +98,8 @@ const CreateApiServiceDialog: React.FC = ({ isOpen, } } catch (error) { console.error('Error creating API service:', error); - - let errorMessage = 'Failed to create API service'; - - if (error && typeof error === 'object' && 'response' in error) { - const response = (error as any).response; - if (response?.data?.meta?.error) { - errorMessage = response.data.meta.error; - } else if (response?.data?.message) { - errorMessage = response.data.message; - } - } - - notifyError(errorMessage); + const errorMessage = extractErrorMessage(error); + notifyError(errorMessage || 'Failed to create API service'); } }; diff --git a/wavefront/client/src/pages/apps/[appId]/api-services/[id].tsx b/wavefront/client/src/pages/apps/[appId]/api-services/[id].tsx index 12b392af..e3bb279b 100644 --- a/wavefront/client/src/pages/apps/[appId]/api-services/[id].tsx +++ b/wavefront/client/src/pages/apps/[appId]/api-services/[id].tsx @@ -16,6 +16,7 @@ import { Label } from '@app/components/ui/label'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@app/components/ui/select'; import { useGetApiService } from '@app/hooks'; import { getApiServiceKey } from '@app/hooks/data/query-keys'; +import { extractErrorMessage } from '@app/lib/utils'; import { useNotifyStore } from '@app/store'; import { ApiServiceItem } from '@app/types/api-service'; import { zodResolver } from '@hookform/resolvers/zod'; @@ -150,7 +151,7 @@ const ApiServiceDetail: React.FC = () => { if (h.key && h.value) apiHeadersObj[h.key] = h.value; }); - const backendQueryParamsObj: Record = {}; + const backendQueryParamsObj: Record = {}; api.backend_query_params.forEach((p) => { if (p.key && p.value) backendQueryParamsObj[p.key] = p.value; }); @@ -189,7 +190,7 @@ const ApiServiceDetail: React.FC = () => { const parseYaml = (yamlStr: string): ApiServiceForm | null => { try { - const parsed: any = yaml.load(yamlStr); + const parsed = yaml.load(yamlStr) as { service?: unknown } | null; if (!parsed || !parsed.service) return null; const s = parsed.service; @@ -216,37 +217,39 @@ const ApiServiceDetail: React.FC = () => { api_key_header: s.auth?.api_key_header || 'X-API-Key', additional_headers: auth_additional_headers, }, - apis: (s.apis || []).map((api: any) => { - const apiHeaders = api.additional_headers || {}; - const api_additional_headers = Object.entries(apiHeaders).map(([key, value]) => ({ - key, - value: String(value), - })); - - const backendQueryParams = api.backend_query_params || {}; - const backend_query_params = Object.entries(backendQueryParams).map(([key, value]) => ({ - key, - value: String(value), - })); - - const outputMapper = api.output_mapper || {}; - const output_mapper = Object.entries(outputMapper).map(([key, value]) => ({ - key, - value: String(value), - })); - - return { - id: api.id || '', - version: api.version || 'v1', - path: api.path || '', - backend_path: api.backend_path || '', - method: (api.method as 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH') || 'GET', - additional_headers: api_additional_headers, - backend_query_params: backend_query_params, - output_mapper_enabled: api.output_mapper_enabled || false, - output_mapper: output_mapper, - }; - }), + apis: ((s.apis || []) as Array<{ additional_headers?: Record; [key: string]: unknown }>).map( + (api) => { + const apiHeaders = api.additional_headers || {}; + const api_additional_headers = Object.entries(apiHeaders).map(([key, value]) => ({ + key, + value: String(value), + })); + + const backendQueryParams = api.backend_query_params || {}; + const backend_query_params = Object.entries(backendQueryParams).map(([key, value]) => ({ + key, + value: String(value), + })); + + const outputMapper = api.output_mapper || {}; + const output_mapper = Object.entries(outputMapper).map(([key, value]) => ({ + key, + value: String(value), + })); + + return { + id: api.id || '', + version: api.version || 'v1', + path: api.path || '', + backend_path: api.backend_path || '', + method: (api.method as 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH') || 'GET', + additional_headers: api_additional_headers, + backend_query_params: backend_query_params, + output_mapper_enabled: api.output_mapper_enabled || false, + output_mapper: output_mapper, + }; + } + ), }; } catch (e) { console.error('Error parsing YAML', e); @@ -388,10 +391,10 @@ const ApiServiceDetail: React.FC = () => { setEditing(false); notifySuccess('API Service updated successfully'); - } catch (error: any) { + } catch (error) { console.error('Error updating API service:', error); - const errorMessage = error?.response?.data?.meta?.error || error?.message || 'Failed to update API service'; - notifyError(errorMessage); + const errorMessage = extractErrorMessage(error); + notifyError(errorMessage || 'Failed to update API service'); } finally { setSaving(false); } @@ -923,7 +926,7 @@ const ApiServiceDetail: React.FC = () => {
{(form.watch(`apis.${index}.additional_headers`) || []).map( - (_header: any, hIndex: number) => ( + (_header: unknown, hIndex: number) => (
{
{(form.watch(`apis.${index}.backend_query_params`) || []).map( - (_param: any, pIndex: number) => ( + (_param: unknown, pIndex: number) => (
{ {form.watch(`apis.${index}.output_mapper_enabled`) && (
{(form.watch(`apis.${index}.output_mapper`) || []).map( - (_mapper: any, mIndex: number) => ( + (_mapper: unknown, mIndex: number) => (
= ({ const { notifySuccess, notifyError } = useNotifyStore(); const { selectedApp } = useDashboardStore(); const [authType, setAuthType] = useState('google_oauth'); - const [parameters, setParameters] = useState>(() => initializeParameters(authType)); + const [parameters, setParameters] = useState>(() => initializeParameters(authType)); const [loading, setLoading] = useState(false); const form = useForm({ @@ -94,11 +96,11 @@ const CreateAuthenticatorDialog: React.FC = ({ } }, [isOpen, form]); - const setParameter = (key: string, value: any) => { + const setParameter = (key: string, value: unknown) => { setParameters((prev) => ({ ...prev, [key]: value })); }; - const setNestedParameter = (parentKey: string, childKey: string, value: any) => { + const setNestedParameter = (parentKey: string, childKey: string, value: unknown) => { setParameters((prev) => ({ ...prev, [parentKey]: { @@ -170,10 +172,10 @@ const CreateAuthenticatorDialog: React.FC = ({ navigate(`/apps/${appId}/authenticators/${response.data.data.authenticator.auth_id}`); } } - } catch (error: any) { + } catch (error) { console.error('Error creating authenticator:', error); - const errorMessage = error?.response?.data?.meta?.error || error?.message || 'Failed to create authenticator'; - notifyError(errorMessage); + const errorMessage = extractErrorMessage(error); + notifyError(errorMessage || 'Failed to create authenticator'); } finally { setLoading(false); } @@ -318,7 +320,7 @@ const CreateAuthenticatorDialog: React.FC = ({ ); }; - const renderNestedField = (parentKey: string, childKey: string, config: any) => { + const renderNestedField = (parentKey: string, childKey: string, config: ParameterConfig) => { const value = parameters[parentKey]?.[childKey]; if (config.type === 'boolean') { diff --git a/wavefront/client/src/pages/apps/[appId]/authenticators/[authId].tsx b/wavefront/client/src/pages/apps/[appId]/authenticators/[authId].tsx index 98315451..2562105d 100644 --- a/wavefront/client/src/pages/apps/[appId]/authenticators/[authId].tsx +++ b/wavefront/client/src/pages/apps/[appId]/authenticators/[authId].tsx @@ -1,6 +1,13 @@ import floConsoleService from '@app/api'; -import { cleanParameters, getProviderBadge, getProviderConfig, mergeParameters } from '@app/config/authenticators'; +import { + cleanParameters, + getProviderBadge, + getProviderConfig, + mergeParameters, + ParameterConfig, +} from '@app/config/authenticators'; import { useGetAuthenticator } from '@app/hooks/data/fetch-hooks'; +import { extractErrorMessage } from '@app/lib/utils'; import { useNotifyStore } from '@app/store'; import { useQueryClient } from '@tanstack/react-query'; import clsx from 'clsx'; @@ -20,7 +27,7 @@ const AuthenticatorDetailPage: React.FC = () => { // Form state const [authDesc, setAuthDesc] = useState(''); - const [parameters, setParameters] = useState>({}); + const [parameters, setParameters] = useState>({}); // Fetch authenticator const { data: authenticator, isLoading: authenticatorLoading } = useGetAuthenticator(app, authId); @@ -33,11 +40,11 @@ const AuthenticatorDetailPage: React.FC = () => { } }, [authenticator]); - const setParameter = (key: string, value: any) => { + const setParameter = (key: string, value: unknown) => { setParameters((prev) => ({ ...prev, [key]: value })); }; - const setNestedParameter = (parentKey: string, childKey: string, value: any) => { + const setNestedParameter = (parentKey: string, childKey: string, value: unknown) => { setParameters((prev) => ({ ...prev, [parentKey]: { @@ -70,8 +77,9 @@ const AuthenticatorDetailPage: React.FC = () => { queryKey: ['authenticator', app, authId], }); queryClient.invalidateQueries({ queryKey: ['authenticators', app] }); - } catch (error: any) { - notifyError(error?.response?.data?.meta?.error || 'Failed to update authenticator'); + } catch (error) { + const errorMessage = extractErrorMessage(error); + notifyError(errorMessage || 'Failed to update authenticator'); } finally { setSaveLoading(false); } @@ -84,8 +92,9 @@ const AuthenticatorDetailPage: React.FC = () => { await floConsoleService.authenticatorService.deleteAuthenticator(authId); notifySuccess('Authenticator deleted successfully'); navigate(`/apps/${app}/authenticators`); - } catch (error: any) { - notifyError(error?.response?.data?.meta?.error || 'Failed to delete authenticator'); + } catch (error) { + const errorMessage = extractErrorMessage(error); + notifyError(errorMessage || 'Failed to delete authenticator'); } }; @@ -105,8 +114,9 @@ const AuthenticatorDetailPage: React.FC = () => { queryKey: ['authenticator', app, authId], }); queryClient.invalidateQueries({ queryKey: ['authenticators', app] }); - } catch (error: any) { - notifyError(error?.response?.data?.meta?.error || 'Failed to toggle authenticator'); + } catch (error) { + const errorMessage = extractErrorMessage(error); + notifyError(errorMessage || 'Failed to toggle authenticator'); } finally { setTogglingEnabled(false); } @@ -274,7 +284,7 @@ const AuthenticatorDetailPage: React.FC = () => { ); }; - const renderNestedField = (parentKey: string, childKey: string, config: any, disabled: boolean) => { + const renderNestedField = (parentKey: string, childKey: string, config: ParameterConfig, disabled: boolean) => { const value = parameters[parentKey]?.[childKey]; if (config.type === 'boolean') { diff --git a/wavefront/client/src/pages/apps/[appId]/authenticators/index.tsx b/wavefront/client/src/pages/apps/[appId]/authenticators/index.tsx index 3e61029a..60455b2e 100644 --- a/wavefront/client/src/pages/apps/[appId]/authenticators/index.tsx +++ b/wavefront/client/src/pages/apps/[appId]/authenticators/index.tsx @@ -14,6 +14,7 @@ import { Button } from '@app/components/ui/button'; import { Input } from '@app/components/ui/input'; import { useGetAuthenticators } from '@app/hooks'; import { getAuthenticatorsKey } from '@app/hooks/data/query-keys'; +import { extractErrorMessage } from '@app/lib/utils'; import { useDashboardStore, useNotifyStore } from '@app/store'; import { Authenticator } from '@app/types/authenticator'; import { useQueryClient } from '@tanstack/react-query'; @@ -50,8 +51,9 @@ const AuthenticatorsPage: React.FC = () => { notifySuccess('Authenticator deleted successfully'); queryClient.invalidateQueries({ queryKey: getAuthenticatorsKey(app) }); setDeleteItem(null); - } catch (error: any) { - notifyError(error?.response?.data?.meta?.error || 'Failed to delete authenticator'); + } catch (error) { + const errorMessage = extractErrorMessage(error); + notifyError(errorMessage || 'Failed to delete authenticator'); } finally { setDeleting(false); } diff --git a/wavefront/client/src/pages/apps/[appId]/datasources/CreateDatasourceDialog.tsx b/wavefront/client/src/pages/apps/[appId]/datasources/CreateDatasourceDialog.tsx index bb22bdbb..6fe7bca9 100644 --- a/wavefront/client/src/pages/apps/[appId]/datasources/CreateDatasourceDialog.tsx +++ b/wavefront/client/src/pages/apps/[appId]/datasources/CreateDatasourceDialog.tsx @@ -12,6 +12,7 @@ import { } from '@app/components/ui/form'; import { Input } from '@app/components/ui/input'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@app/components/ui/select'; +import { extractErrorMessage } from '@app/lib/utils'; import { useNotifyStore } from '@app/store'; import { zodResolver } from '@hookform/resolvers/zod'; import { langs } from '@uiw/codemirror-extensions-langs'; @@ -92,7 +93,7 @@ const CreateDatasourceDialog: React.FC = ({ isOpen, let parsedConfig; try { parsedConfig = JSON.parse(data.connectionConfig); - } catch (error) { + } catch { notifyError('Invalid JSON in connection configuration'); return; } @@ -105,7 +106,7 @@ const CreateDatasourceDialog: React.FC = ({ isOpen, data.description?.trim() || undefined ); - const responseData = response.data?.data as any; + const responseData = response.data?.data as { datasource_id?: string } | undefined; notifySuccess('Datasource created successfully'); if (onSuccess) { @@ -119,19 +120,8 @@ const CreateDatasourceDialog: React.FC = ({ isOpen, } } catch (error) { console.error('Error creating datasource:', error); - - let errorMessage = 'Failed to create datasource'; - - if (error && typeof error === 'object' && 'response' in error) { - const response = (error as any).response; - if (response?.data?.meta?.error) { - errorMessage = response.data.meta.error; - } else if (response?.data?.message) { - errorMessage = response.data.message; - } - } - - notifyError(errorMessage); + const errorMessage = extractErrorMessage(error); + notifyError(errorMessage || 'Failed to create datasource'); } }; diff --git a/wavefront/client/src/pages/apps/[appId]/datasources/EditDatasourceDialog.tsx b/wavefront/client/src/pages/apps/[appId]/datasources/EditDatasourceDialog.tsx index 3b496bfb..7adc71bb 100644 --- a/wavefront/client/src/pages/apps/[appId]/datasources/EditDatasourceDialog.tsx +++ b/wavefront/client/src/pages/apps/[appId]/datasources/EditDatasourceDialog.tsx @@ -12,6 +12,7 @@ import { } from '@app/components/ui/form'; import { Input } from '@app/components/ui/input'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@app/components/ui/select'; +import { extractErrorMessage } from '@app/lib/utils'; import { useNotifyStore } from '@app/store'; import { Datasource } from '@app/types/datasource'; import { zodResolver } from '@hookform/resolvers/zod'; @@ -74,7 +75,7 @@ const EditDatasourceDialog: React.FC = ({ let parsedConfig; try { parsedConfig = JSON.parse(data.connectionConfig); - } catch (error) { + } catch { notifyError('Invalid JSON in connection configuration'); return; } @@ -97,19 +98,8 @@ const EditDatasourceDialog: React.FC = ({ onOpenChange(false); } catch (error) { console.error('Error updating datasource:', error); - - let errorMessage = 'Failed to update datasource'; - - if (error && typeof error === 'object' && 'response' in error) { - const response = (error as any).response; - if (response?.data?.meta?.error) { - errorMessage = response.data.meta.error; - } else if (response?.data?.message) { - errorMessage = response.data.message; - } - } - - notifyError(errorMessage); + const errorMessage = extractErrorMessage(error); + notifyError(errorMessage || 'Failed to update datasource'); } }; diff --git a/wavefront/client/src/pages/apps/[appId]/datasources/YamlView.tsx b/wavefront/client/src/pages/apps/[appId]/datasources/YamlView.tsx index a94eb8a8..72700ce3 100644 --- a/wavefront/client/src/pages/apps/[appId]/datasources/YamlView.tsx +++ b/wavefront/client/src/pages/apps/[appId]/datasources/YamlView.tsx @@ -50,8 +50,8 @@ const YamlView = ({ handleYamlEdit: (yamlContent: string) => void; handleClose: () => void; handleYamlExecute: (params: Record) => void; - yamlExecuteResult: Record[]; - setYamlExecuteResult: React.Dispatch[]>>; + yamlExecuteResult: Record[]; + setYamlExecuteResult: React.Dispatch[]>>; executing: boolean; }) => { const [yamlContent, setYamlContent] = useState(''); diff --git a/wavefront/client/src/pages/apps/[appId]/datasources/[datasourceId].tsx b/wavefront/client/src/pages/apps/[appId]/datasources/[datasourceId].tsx index 25028938..efd12c17 100644 --- a/wavefront/client/src/pages/apps/[appId]/datasources/[datasourceId].tsx +++ b/wavefront/client/src/pages/apps/[appId]/datasources/[datasourceId].tsx @@ -78,7 +78,7 @@ const DatasourceDetail: React.FC = () => { const [yamlContent, setYamlContent] = useState(''); const [yamlQueries, setYamlQueries] = useState([]); const [yamlName, setYamlName] = useState(''); - const [yamlExecuteResult, setYamlExecuteResult] = useState[]>([]); + const [yamlExecuteResult, setYamlExecuteResult] = useState[]>([]); // Update yamlQueries and yamlName when yamlData changes useEffect(() => { @@ -105,7 +105,7 @@ const DatasourceDetail: React.FC = () => { notifyError('Error while creating yaml'); return; } - } catch (error) { + } catch { notifyError('Error while creating yaml'); } finally { setYamlCreation(false); @@ -164,11 +164,11 @@ const DatasourceDetail: React.FC = () => { const responseCode = response?.data.meta?.code; if (responseCode === 1) { notifySuccess('Yaml executed successfully'); - setYamlExecuteResult((response.data.data as unknown as Record[]) || []); + setYamlExecuteResult((response.data.data as unknown as Record[]) || []); } else { notifyError('Error while executing yaml'); } - } catch (error) { + } catch { notifyError('Error while executing yaml'); } finally { setExecuting(false); @@ -188,7 +188,7 @@ const DatasourceDetail: React.FC = () => { await floConsoleService.datasourcesService.deleteDatasource(datasourceId); notifySuccess('Datasource deleted successfully'); navigate(`/apps/${appId}/datasources`); - } catch (error) { + } catch { console.error('Error deleting datasource'); } finally { setDeleting(false); @@ -204,14 +204,14 @@ const DatasourceDetail: React.FC = () => { const result = await floConsoleService.datasourcesService.testDatasource(datasourceId); // Based on updated API, test-connection now returns boolean directly - const isConnected = (result.data as any) === true; + const isConnected = (result.data as unknown) === true; if (isConnected) { notifySuccess('Connection test successful'); } else { notifyError('Connection test failed'); } - } catch (error) { + } catch { notifyError('Failed to test connection'); } finally { setTestingConnection(false); diff --git a/wavefront/client/src/pages/apps/[appId]/functions/CreateFunctionDialog.tsx b/wavefront/client/src/pages/apps/[appId]/functions/CreateFunctionDialog.tsx index 6576b1bf..aedf38a1 100644 --- a/wavefront/client/src/pages/apps/[appId]/functions/CreateFunctionDialog.tsx +++ b/wavefront/client/src/pages/apps/[appId]/functions/CreateFunctionDialog.tsx @@ -107,9 +107,8 @@ const CreateMessageProcessorDialog: React.FC } else { notifyError('Failed to create message processor'); } - } catch (error: any) { + } catch (error) { console.error('Error creating message processor:', error); - notifyError(error?.message || 'Failed to create message processor'); } }; diff --git a/wavefront/client/src/pages/apps/[appId]/knowledge-bases/CreateKnowledgeBaseDialog.tsx b/wavefront/client/src/pages/apps/[appId]/knowledge-bases/CreateKnowledgeBaseDialog.tsx index 2d0fb475..5a507ac3 100644 --- a/wavefront/client/src/pages/apps/[appId]/knowledge-bases/CreateKnowledgeBaseDialog.tsx +++ b/wavefront/client/src/pages/apps/[appId]/knowledge-bases/CreateKnowledgeBaseDialog.tsx @@ -106,10 +106,8 @@ const CreateKnowledgeBaseDialog: React.FC = ({ } else { notifyError('Failed to get knowledge base ID after creation.'); } - } catch (error: any) { + } catch (error) { console.error('Error creating knowledge base:', error); - const errorMessage = error?.message || 'Failed to create knowledge base'; - notifyError(errorMessage); } }; diff --git a/wavefront/client/src/pages/apps/[appId]/knowledge-bases/[kbId]/index.tsx b/wavefront/client/src/pages/apps/[appId]/knowledge-bases/[kbId]/index.tsx index c7b1ad0f..f72c76c1 100644 --- a/wavefront/client/src/pages/apps/[appId]/knowledge-bases/[kbId]/index.tsx +++ b/wavefront/client/src/pages/apps/[appId]/knowledge-bases/[kbId]/index.tsx @@ -61,7 +61,7 @@ const KnowledgeBaseDetailPage: React.FC = () => { const [testInferenceId, setTestInferenceId] = useState(null); const [testQuery, setTestQuery] = useState(''); const [chatMessages, setChatMessages] = useState< - Array<{ role: 'user' | 'assistant'; content: string; sources?: any[] }> + Array<{ role: 'user' | 'assistant'; content: string; sources?: unknown[] }> >([]); const [loadingRag, setLoadingRag] = useState(false); const [messagesContainerRef, setMessagesContainerRef] = useState(null); diff --git a/wavefront/client/src/pages/apps/[appId]/knowledge-bases/index.tsx b/wavefront/client/src/pages/apps/[appId]/knowledge-bases/index.tsx index 31b55b69..d929c301 100644 --- a/wavefront/client/src/pages/apps/[appId]/knowledge-bases/index.tsx +++ b/wavefront/client/src/pages/apps/[appId]/knowledge-bases/index.tsx @@ -15,6 +15,7 @@ import { Button } from '@app/components/ui/button'; import { Input } from '@app/components/ui/input'; import { useGetKnowledgeBases } from '@app/hooks'; import { getKnowledgeBasesKey } from '@app/hooks/data/query-keys'; +import { extractErrorMessage } from '@app/lib/utils'; import { useDashboardStore, useNotifyStore } from '@app/store'; import { useQueryClient } from '@tanstack/react-query'; import React, { useState } from 'react'; @@ -51,17 +52,8 @@ const KnowledgeBasesListPage: React.FC = () => { setDeleteItem(null); } catch (error) { console.error('Error deleting knowledge base:', error); - let errorMessage = 'Failed to delete knowledge base'; - - if (error && typeof error === 'object' && 'response' in error) { - const response = (error as any).response; - if (response?.data?.meta?.error) { - errorMessage = response.data.meta.error; - } else if (response?.data?.message) { - errorMessage = response.data.message; - } - } - notifyError(errorMessage); + const errorMessage = extractErrorMessage(error); + notifyError(errorMessage || 'Failed to delete knowledge base'); } finally { setDeleting(false); } diff --git a/wavefront/client/src/pages/apps/[appId]/llm-inference/CreateLLMInferenceDialog.tsx b/wavefront/client/src/pages/apps/[appId]/llm-inference/CreateLLMInferenceDialog.tsx index 6d718ebb..176f2c2c 100644 --- a/wavefront/client/src/pages/apps/[appId]/llm-inference/CreateLLMInferenceDialog.tsx +++ b/wavefront/client/src/pages/apps/[appId]/llm-inference/CreateLLMInferenceDialog.tsx @@ -93,7 +93,7 @@ const CreateLLMInferenceDialog: React.FC = ({ const navigate = useNavigate(); const { notifySuccess, notifyError } = useNotifyStore(); const [type, setType] = useState('openai'); - const [parameters, setParameters] = useState>({}); + const [parameters, setParameters] = useState>({}); const [creating, setCreating] = useState(false); const { selectedApp } = useDashboardStore(); @@ -147,7 +147,7 @@ const CreateLLMInferenceDialog: React.FC = ({ return ['ollama', 'vllm', 'azure_openai', 'openai', 'anthropic', 'gemini', 'groq'].includes(engineType); }; - const setParameter = (key: string, value: any) => { + const setParameter = (key: string, value: unknown) => { setParameters((prev) => ({ ...prev, [key]: value })); }; @@ -197,18 +197,8 @@ const CreateLLMInferenceDialog: React.FC = ({ } } catch (error) { console.error('Error creating LLM inference config:', error); - - let errorMessage = 'Failed to add model to repository'; - if (error && typeof error === 'object' && 'response' in error) { - const response = (error as any).response; - if (response?.data?.error) { - errorMessage = response.data.error; - } else if (response?.data?.message) { - errorMessage = response.data.message; - } - } - - notifyError(errorMessage); + const errorMessage = extractErrorMessage(error); + notifyError(errorMessage || 'Failed to add model to repository'); } finally { setCreating(false); } diff --git a/wavefront/client/src/pages/apps/[appId]/llm-inference/[configId].tsx b/wavefront/client/src/pages/apps/[appId]/llm-inference/[configId].tsx index f58a6628..6e1dc374 100644 --- a/wavefront/client/src/pages/apps/[appId]/llm-inference/[configId].tsx +++ b/wavefront/client/src/pages/apps/[appId]/llm-inference/[configId].tsx @@ -23,8 +23,9 @@ import { } from '@app/config/llm-providers'; import { useGetLLMConfig } from '@app/hooks'; import { getLLMConfigKey, getLLMConfigsKey } from '@app/hooks/data/query-keys'; +import { extractErrorMessage } from '@app/lib/utils'; import { useNotifyStore } from '@app/store'; -import { InferenceEngineType } from '@app/types/llm-inference-config'; +import { InferenceEngineType, UpdateLLMConfigRequest } from '@app/types/llm-inference-config'; import { zodResolver } from '@hookform/resolvers/zod'; import { useQueryClient } from '@tanstack/react-query'; import clsx from 'clsx'; @@ -66,7 +67,7 @@ const LLMInferenceConfigDetail: React.FC = () => { const [editing, setEditing] = useState(false); const [saving, setSaving] = useState(false); const [showDeleteConfirm, setShowDeleteConfirm] = useState(false); - const [parameters, setParameters] = useState>({}); + const [parameters, setParameters] = useState>({}); const form = useForm({ resolver: zodResolver(llmConfigFormSchema), @@ -130,7 +131,7 @@ const LLMInferenceConfigDetail: React.FC = () => { const cleanedParams = cleanParameters(parameters); // Only include fields that have changed or are explicitly set - const updateData: any = { + const updateData: UpdateLLMConfigRequest = { display_name: data.display_name.trim(), llm_model: data.llm_model.trim(), type: data.type, @@ -157,18 +158,8 @@ const LLMInferenceConfigDetail: React.FC = () => { notifySuccess('Model updated successfully'); } catch (error) { console.error('Error updating LLM inference config:', error); - - let errorMessage = 'Failed to update model'; - if (error && typeof error === 'object' && 'response' in error) { - const response = (error as any).response; - if (response?.data?.error) { - errorMessage = response.data.error; - } else if (response?.data?.message) { - errorMessage = response.data.message; - } - } - - notifyError(errorMessage); + const errorMessage = extractErrorMessage(error); + notifyError(errorMessage || 'Failed to update model'); } finally { setSaving(false); } diff --git a/wavefront/client/src/pages/apps/[appId]/llm-inference/index.tsx b/wavefront/client/src/pages/apps/[appId]/llm-inference/index.tsx index 5fd4b2e1..670f5cd8 100644 --- a/wavefront/client/src/pages/apps/[appId]/llm-inference/index.tsx +++ b/wavefront/client/src/pages/apps/[appId]/llm-inference/index.tsx @@ -14,6 +14,7 @@ import { Button } from '@app/components/ui/button'; import { Input } from '@app/components/ui/input'; import { useGetLLMConfigs } from '@app/hooks'; import { getLLMConfigsKey } from '@app/hooks/data/query-keys'; +import { extractErrorMessage } from '@app/lib/utils'; import { useDashboardStore, useNotifyStore } from '@app/store'; import { LLMInferenceConfig } from '@app/types/llm-inference-config'; import { useQueryClient } from '@tanstack/react-query'; @@ -75,18 +76,8 @@ const LLMInferenceConfigsManagement: React.FC = () => { setDeleteItem(null); } catch (error) { console.error('Error deleting LLM inference config:', error); - - let errorMessage = 'Failed to delete model'; - if (error && typeof error === 'object' && 'response' in error) { - const response = (error as any).response; - if (response?.data?.error) { - errorMessage = response.data.error; - } else if (response?.data?.message) { - errorMessage = response.data.message; - } - } - - notifyError(errorMessage); + const errorMessage = extractErrorMessage(error); + notifyError(errorMessage || 'Failed to delete model'); } finally { setDeleting(false); } diff --git a/wavefront/client/src/pages/apps/[appId]/model-inference/CreateModelInferenceDialog.tsx b/wavefront/client/src/pages/apps/[appId]/model-inference/CreateModelInferenceDialog.tsx index be3bb9fd..645506aa 100644 --- a/wavefront/client/src/pages/apps/[appId]/model-inference/CreateModelInferenceDialog.tsx +++ b/wavefront/client/src/pages/apps/[appId]/model-inference/CreateModelInferenceDialog.tsx @@ -53,7 +53,7 @@ const CreateModelInferenceDialog: React.FC = ({ resolver: zodResolver(createModelInferenceSchema), defaultValues: { modelType: '', - modelFile: undefined as any, + modelFile: undefined as File | undefined, }, mode: 'onChange', }); @@ -63,7 +63,7 @@ const CreateModelInferenceDialog: React.FC = ({ if (!isOpen) { form.reset({ modelType: '', - modelFile: undefined as any, + modelFile: undefined as File | undefined, }); } }, [isOpen, form]); @@ -89,10 +89,8 @@ const CreateModelInferenceDialog: React.FC = ({ } else { notifyError('Failed to get model ID after upload.'); } - } catch (error: any) { + } catch (error) { console.error('Error creating model:', error); - const errorMessage = error?.message || 'Failed to create model'; - notifyError(errorMessage); } finally { setCreating(false); } diff --git a/wavefront/client/src/pages/apps/[appId]/model-inference/[modelId].tsx b/wavefront/client/src/pages/apps/[appId]/model-inference/[modelId].tsx index a42d4228..f84ba153 100644 --- a/wavefront/client/src/pages/apps/[appId]/model-inference/[modelId].tsx +++ b/wavefront/client/src/pages/apps/[appId]/model-inference/[modelId].tsx @@ -1,5 +1,5 @@ import floConsoleService from '@app/api'; -import { InferencePayload, PreprocessingStep } from '@app/api/model-inference-service'; +import { InferencePayload, ModelInferenceResultData, PreprocessingStep } from '@app/api/model-inference-service'; import DeleteConfirmationDialog from '@app/components/DeleteConfirmationDialog'; import { Breadcrumb, @@ -23,6 +23,7 @@ import { Label } from '@app/components/ui/label'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@app/components/ui/select'; import { useGetModel } from '@app/hooks'; import { getModelsKey } from '@app/hooks/data/query-keys'; +import { extractErrorMessage } from '@app/lib/utils'; import { useNotifyStore } from '@app/store'; import { Plus, Trash2 } from 'lucide-react'; import { useQueryClient } from '@tanstack/react-query'; @@ -59,7 +60,7 @@ const ModelDetail: React.FC = () => { // Inference state const [inferenceImageFile, setInferenceImageFile] = useState(null); const [jsonPayload, setJsonPayload] = useState(defaultJsonPayload); - const [inferenceResult, setInferenceResult] = useState(null); + const [inferenceResult, setInferenceResult] = useState(null); const [runningInference, setRunningInference] = useState(false); const [preprocessingSteps, setPreprocessingSteps] = useState([]); @@ -85,11 +86,10 @@ const ModelDetail: React.FC = () => { customPayload ); - setInferenceResult(response.data.data); + setInferenceResult(response.data.data ?? null); notifySuccess('Inference successful!'); - } catch (error: any) { + } catch (error) { console.error('Error running inference:', error); - notifyError(error.message || 'Failed to run inference'); } finally { setRunningInference(false); } @@ -114,20 +114,22 @@ const ModelDetail: React.FC = () => { navigate(`/apps/${appId}/model-inference`); } catch (error) { console.error('Error deleting model:', error); - let errorMessage = 'Failed to delete model'; - - if (error && typeof error === 'object' && 'response' in error) { - const response = (error as any).response; - if (response?.data?.meta?.error) { - errorMessage = response.data.meta.error; - } else if (response?.data?.message) { - errorMessage = response.data.message; - } - } - notifyError(errorMessage); + const errorMessage = extractErrorMessage(error); + notifyError(errorMessage || 'Failed to delete model'); } }; + const formatInferenceResult = (result: ModelInferenceResultData): string => { + return JSON.stringify( + { + ...result, + infer_data: typeof result.infer_data === 'number' ? Math.round(result.infer_data * 100) : result.infer_data, + }, + null, + 2 + ); + }; + return (
@@ -300,19 +302,7 @@ const ModelDetail: React.FC = () => {
-
-                        {JSON.stringify(
-                          {
-                            ...inferenceResult,
-                            infer_data:
-                              typeof inferenceResult.infer_data === 'number'
-                                ? Math.round(inferenceResult.infer_data * 100)
-                                : inferenceResult.infer_data,
-                          },
-                          null,
-                          2
-                        )}
-                      
+
{formatInferenceResult(inferenceResult)}
)} diff --git a/wavefront/client/src/pages/apps/[appId]/model-inference/index.tsx b/wavefront/client/src/pages/apps/[appId]/model-inference/index.tsx index 061da0b7..33f51ac7 100644 --- a/wavefront/client/src/pages/apps/[appId]/model-inference/index.tsx +++ b/wavefront/client/src/pages/apps/[appId]/model-inference/index.tsx @@ -15,6 +15,7 @@ import { Button } from '@app/components/ui/button'; import { Input } from '@app/components/ui/input'; import { useGetModels } from '@app/hooks'; import { getModelsKey } from '@app/hooks/data/query-keys'; +import { extractErrorMessage } from '@app/lib/utils'; import { useDashboardStore, useNotifyStore } from '@app/store'; import { useQueryClient } from '@tanstack/react-query'; import React, { useState } from 'react'; @@ -73,23 +74,8 @@ const ModelManagement: React.FC = () => { setDeleteItem(null); } catch (error) { console.error('Error deleting model:', error); - let errorMessage = 'Failed to delete model'; - - if (error && typeof error === 'object' && 'response' in error) { - const response = ( - error as { - response: { - data?: { meta?: { error?: string }; message?: string }; - }; - } - ).response; - if (response?.data?.meta?.error) { - errorMessage = response.data.meta.error; - } else if (response?.data?.message) { - errorMessage = response.data.message; - } - } - notifyError(errorMessage); + const errorMessage = extractErrorMessage(error); + notifyError(errorMessage || 'Failed to delete model'); } finally { setDeleting(false); } diff --git a/wavefront/client/src/pages/apps/[appId]/pipelines/[pipelineId].tsx b/wavefront/client/src/pages/apps/[appId]/pipelines/[pipelineId].tsx index ff5080ac..77f0aed2 100644 --- a/wavefront/client/src/pages/apps/[appId]/pipelines/[pipelineId].tsx +++ b/wavefront/client/src/pages/apps/[appId]/pipelines/[pipelineId].tsx @@ -1,5 +1,6 @@ import floConsoleService from '@app/api'; import { useGetPipeline, useGetPipelineFiles } from '@app/hooks/data/fetch-hooks'; +import { extractErrorMessage } from '@app/lib/utils'; import { useNotifyStore } from '@app/store'; import { FileType, PipelineFile } from '@app/types/pipeline'; import { useQueryClient } from '@tanstack/react-query'; @@ -54,8 +55,9 @@ const PipelineDetail: React.FC = () => { await pipelineService.publishPipeline('default', pipeline.pipeline_id); notifySuccess('Pipeline published successfully'); queryClient.invalidateQueries({ queryKey: ['pipeline', app, pipelineId] }); - } catch (error: any) { - notifyError(error?.response?.data?.error?.message || 'Failed to publish pipeline'); + } catch (error) { + const errorMessage = extractErrorMessage(error); + notifyError(errorMessage || 'Failed to publish pipeline'); } finally { setPublishLoading(false); } @@ -73,7 +75,7 @@ const PipelineDetail: React.FC = () => { notifySuccess('Pipeline unpaused successfully'); } queryClient.invalidateQueries({ queryKey: ['pipeline', app, pipelineId] }); - } catch (error) { + } catch { notifyError('Failed to update pipeline status'); } finally { setPauseLoading(false); @@ -86,7 +88,7 @@ const PipelineDetail: React.FC = () => { try { await pipelineService.triggerDagRun('default', pipeline.pipeline_id); notifySuccess('Pipeline triggered successfully'); - } catch (error) { + } catch { notifyError('Failed to trigger pipeline'); } finally { setTriggerLoading(false); @@ -99,7 +101,7 @@ const PipelineDetail: React.FC = () => { setSelectedFile(file); setFileContent(response.data?.data?.content || ''); setIsEditing(false); - } catch (error) { + } catch { notifyError('Failed to load file content'); } }; @@ -112,7 +114,7 @@ const PipelineDetail: React.FC = () => { notifySuccess('File saved successfully'); setIsEditing(false); queryClient.invalidateQueries({ queryKey: ['pipeline-files', app, pipelineId] }); - } catch (error) { + } catch { notifyError('Failed to save file'); } finally { setSaveLoading(false); @@ -168,10 +170,11 @@ const PipelineDetail: React.FC = () => { setIsEditing(false); } }, 500); - } catch (error: any) { - const errorMsg = error?.response?.data?.error?.message || 'Failed to create file'; - notifyError(errorMsg); - setFilePathError(errorMsg); + } catch (error) { + const errorMsg = extractErrorMessage(error); + const finalErrorMsg = errorMsg || 'Failed to create file'; + notifyError(finalErrorMsg); + setFilePathError(finalErrorMsg); } finally { setCreateLoading(false); } @@ -193,7 +196,7 @@ const PipelineDetail: React.FC = () => { setFileToDelete(null); queryClient.invalidateQueries({ queryKey: ['pipeline-files', app, pipelineId] }); - } catch (error) { + } catch { notifyError('Failed to delete file'); } }; @@ -213,8 +216,9 @@ const PipelineDetail: React.FC = () => { notifySuccess('Schedule updated successfully'); setShowScheduleModal(false); queryClient.invalidateQueries({ queryKey: ['pipeline', app, pipelineId] }); - } catch (error: any) { - notifyError(error?.response?.data?.error?.message || 'Failed to update schedule'); + } catch (error) { + const errorMessage = extractErrorMessage(error); + notifyError(errorMessage || 'Failed to update schedule'); } finally { setScheduleLoading(false); } diff --git a/wavefront/client/src/pages/apps/[appId]/pipelines/index.tsx b/wavefront/client/src/pages/apps/[appId]/pipelines/index.tsx index 85dbb03c..17f25142 100644 --- a/wavefront/client/src/pages/apps/[appId]/pipelines/index.tsx +++ b/wavefront/client/src/pages/apps/[appId]/pipelines/index.tsx @@ -48,7 +48,7 @@ const PipelineManagement: React.FC = () => { notifySuccess(`Pipeline "${pipeline.project_name}" unpaused successfully`); } queryClient.invalidateQueries({ queryKey: ['pipelines', app] }); - } catch (error) { + } catch { notifyError('Failed to update pipeline status'); } }; @@ -58,7 +58,7 @@ const PipelineManagement: React.FC = () => { try { await floConsoleService.dataPipelineService.triggerDagRun('default', pipeline.pipeline_id); notifySuccess(`Pipeline "${pipeline.project_name}" triggered successfully`); - } catch (error) { + } catch { notifyError('Failed to trigger pipeline'); } }; diff --git a/wavefront/client/src/pages/apps/[appId]/voice-agents/CreateVoiceAgentDialog.tsx b/wavefront/client/src/pages/apps/[appId]/voice-agents/CreateVoiceAgentDialog.tsx index 6c7db447..a7d91e68 100644 --- a/wavefront/client/src/pages/apps/[appId]/voice-agents/CreateVoiceAgentDialog.tsx +++ b/wavefront/client/src/pages/apps/[appId]/voice-agents/CreateVoiceAgentDialog.tsx @@ -25,6 +25,7 @@ import { useGetTelephonyConfigs, useGetTtsConfigs, } from '@app/hooks/data/fetch-hooks'; +import { extractErrorMessage } from '@app/lib/utils'; import { useDashboardStore, useNotifyStore } from '@app/store'; import { CreateVoiceAgentRequest } from '@app/types/voice-agent'; import { zodResolver } from '@hookform/resolvers/zod'; @@ -109,7 +110,7 @@ const CreateVoiceAgentDialog: React.FC = ({ isOpen, if (data.conversation_config?.trim() && data.conversation_config.trim() !== '{}') { try { conversationConfig = JSON.parse(data.conversation_config); - } catch (error) { + } catch { notifyError('Invalid JSON in conversation configuration'); return; } @@ -146,14 +147,10 @@ const CreateVoiceAgentDialog: React.FC = ({ isOpen, navigate(`/apps/${appId}/voice-agents/${response.data.data.voice_agent_id}`); } } - } catch (error: any) { + } catch (error) { console.error('Error creating voice agent:', error); - const errorMessage = - error?.response?.data?.error?.message || - error?.response?.data?.meta?.error || - error?.message || - 'Failed to create voice agent'; - notifyError(errorMessage); + const errorMessage = extractErrorMessage(error); + notifyError(errorMessage || 'Failed to create voice agent'); } finally { setCreating(false); } diff --git a/wavefront/client/src/pages/apps/[appId]/voice-agents/EditVoiceAgentDialog.tsx b/wavefront/client/src/pages/apps/[appId]/voice-agents/EditVoiceAgentDialog.tsx index 8e800e9b..245d7b59 100644 --- a/wavefront/client/src/pages/apps/[appId]/voice-agents/EditVoiceAgentDialog.tsx +++ b/wavefront/client/src/pages/apps/[appId]/voice-agents/EditVoiceAgentDialog.tsx @@ -25,6 +25,7 @@ import { useGetTelephonyConfigs, useGetTtsConfigs, } from '@app/hooks/data/fetch-hooks'; +import { extractErrorMessage } from '@app/lib/utils'; import { useDashboardStore, useNotifyStore } from '@app/store'; import { UpdateVoiceAgentRequest, VoiceAgent } from '@app/types/voice-agent'; import { zodResolver } from '@hookform/resolvers/zod'; @@ -114,7 +115,7 @@ const EditVoiceAgentDialog: React.FC = ({ if (data.conversation_config?.trim() && data.conversation_config.trim() !== '{}') { try { conversationConfig = JSON.parse(data.conversation_config); - } catch (error) { + } catch { notifyError('Invalid JSON in conversation configuration'); return; } @@ -144,14 +145,10 @@ const EditVoiceAgentDialog: React.FC = ({ } onOpenChange(false); - } catch (error: any) { + } catch (error) { console.error('Error updating voice agent:', error); - const errorMessage = - error?.response?.data?.error?.message || - error?.response?.data?.meta?.error || - error?.message || - 'Failed to update voice agent'; - notifyError(errorMessage); + const errorMessage = extractErrorMessage(error); + notifyError(errorMessage || 'Failed to update voice agent'); } finally { setUpdating(false); } diff --git a/wavefront/client/src/pages/apps/[appId]/voice-agents/OutboundCallDialog.tsx b/wavefront/client/src/pages/apps/[appId]/voice-agents/OutboundCallDialog.tsx index 55299f97..5934baee 100644 --- a/wavefront/client/src/pages/apps/[appId]/voice-agents/OutboundCallDialog.tsx +++ b/wavefront/client/src/pages/apps/[appId]/voice-agents/OutboundCallDialog.tsx @@ -12,6 +12,7 @@ import { Input } from '@app/components/ui/input'; import { Label } from '@app/components/ui/label'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@app/components/ui/select'; import { useGetTelephonyConfig } from '@app/hooks/data/fetch-hooks'; +import { extractErrorMessage } from '@app/lib/utils'; import { useNotifyStore } from '@app/store'; import { VoiceAgent } from '@app/types/voice-agent'; import React, { useState } from 'react'; @@ -63,7 +64,7 @@ const OutboundCallDialog: React.FC = ({ isOpen, onOpenC setCallLoading(true); try { - const callData: any = { + const callData: { to_number: string; from_number?: string } = { to_number: toNumber.trim(), }; @@ -82,8 +83,9 @@ const OutboundCallDialog: React.FC = ({ isOpen, onOpenC setToNumber(''); setFromNumber(''); onOpenChange(false); - } catch (error: any) { - notifyError(error?.response?.data?.error?.message || 'Failed to initiate call'); + } catch (error) { + const errorMessage = extractErrorMessage(error); + notifyError(errorMessage || 'Failed to initiate call'); } finally { setCallLoading(false); } diff --git a/wavefront/client/src/pages/apps/[appId]/voice-agents/index.tsx b/wavefront/client/src/pages/apps/[appId]/voice-agents/index.tsx index 6b67e86f..a37858ed 100644 --- a/wavefront/client/src/pages/apps/[appId]/voice-agents/index.tsx +++ b/wavefront/client/src/pages/apps/[appId]/voice-agents/index.tsx @@ -6,6 +6,7 @@ import { Input } from '@app/components/ui/input'; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@app/components/ui/table'; import { useGetVoiceAgents } from '@app/hooks'; import { getVoiceAgentsKey } from '@app/hooks/data/query-keys'; +import { extractErrorMessage } from '@app/lib/utils'; import { useNotifyStore } from '@app/store'; import { VoiceAgent } from '@app/types/voice-agent'; import { useQueryClient } from '@tanstack/react-query'; @@ -60,8 +61,9 @@ const VoiceAgentsPage: React.FC = () => { notifySuccess('Voice agent deleted successfully'); queryClient.invalidateQueries({ queryKey: getVoiceAgentsKey(app || '') }); setDeleteItem(null); - } catch (error: any) { - notifyError(error?.response?.data?.error?.message || 'Failed to delete voice agent'); + } catch (error) { + const errorMessage = extractErrorMessage(error); + notifyError(errorMessage || 'Failed to delete voice agent'); } finally { setDeleting(false); } diff --git a/wavefront/client/src/pages/apps/[appId]/voice-agents/stt-configs/CreateSttConfigDialog.tsx b/wavefront/client/src/pages/apps/[appId]/voice-agents/stt-configs/CreateSttConfigDialog.tsx index 16029cbd..63a942b8 100644 --- a/wavefront/client/src/pages/apps/[appId]/voice-agents/stt-configs/CreateSttConfigDialog.tsx +++ b/wavefront/client/src/pages/apps/[appId]/voice-agents/stt-configs/CreateSttConfigDialog.tsx @@ -25,6 +25,7 @@ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@ import { Slider } from '@app/components/ui/slider'; import { Textarea } from '@app/components/ui/textarea'; import { VOICE_PROVIDERS_CONFIG, getProviderConfig, initializeParameters } from '@app/config/voice-providers'; +import { extractErrorMessage } from '@app/lib/utils'; import { useNotifyStore } from '@app/store'; import { zodResolver } from '@hookform/resolvers/zod'; import React, { useEffect, useState } from 'react'; @@ -50,7 +51,7 @@ interface CreateSttConfigDialogProps { const CreateSttConfigDialog: React.FC = ({ isOpen, onOpenChange, onSuccess }) => { const { notifySuccess, notifyError } = useNotifyStore(); - const [parameters, setParameters] = useState>({}); + const [parameters, setParameters] = useState>({}); const [loading, setLoading] = useState(false); const form = useForm({ @@ -87,7 +88,7 @@ const CreateSttConfigDialog: React.FC = ({ isOpen, o } }, [isOpen, form]); - const setParameter = (key: string, value: any) => { + const setParameter = (key: string, value: unknown) => { setParameters((prev) => ({ ...prev, [key]: value })); }; @@ -95,7 +96,7 @@ const CreateSttConfigDialog: React.FC = ({ isOpen, o const config = getProviderConfig('stt', watchedProvider); if (!config) return null; - const params: Record = {}; + const params: Record = {}; Object.entries(parameters).forEach(([key, value]) => { const paramConfig = config.parameters[key]; @@ -115,7 +116,7 @@ const CreateSttConfigDialog: React.FC = ({ isOpen, o await floConsoleService.sttConfigService.createSttConfig({ display_name: data.display_name.trim(), description: data.description?.trim() || null, - provider: data.provider as any, + provider: data.provider, api_key: data.api_key.trim(), language: data.language?.trim() || null, parameters: buildParameters(), @@ -123,8 +124,9 @@ const CreateSttConfigDialog: React.FC = ({ isOpen, o notifySuccess('STT configuration created successfully'); onSuccess?.(); onOpenChange(false); - } catch (error: any) { - notifyError(error?.response?.data?.error?.message || 'Failed to create STT configuration'); + } catch (error) { + const errorMessage = extractErrorMessage(error); + notifyError(errorMessage || 'Failed to create STT configuration'); } finally { setLoading(false); } diff --git a/wavefront/client/src/pages/apps/[appId]/voice-agents/stt-configs/EditSttConfigDialog.tsx b/wavefront/client/src/pages/apps/[appId]/voice-agents/stt-configs/EditSttConfigDialog.tsx index 8fff1fd6..b8c83810 100644 --- a/wavefront/client/src/pages/apps/[appId]/voice-agents/stt-configs/EditSttConfigDialog.tsx +++ b/wavefront/client/src/pages/apps/[appId]/voice-agents/stt-configs/EditSttConfigDialog.tsx @@ -25,6 +25,7 @@ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@ import { Slider } from '@app/components/ui/slider'; import { Textarea } from '@app/components/ui/textarea'; import { VOICE_PROVIDERS_CONFIG, getProviderConfig, mergeParameters } from '@app/config/voice-providers'; +import { extractErrorMessage } from '@app/lib/utils'; import { useNotifyStore } from '@app/store'; import { SttConfig, UpdateSttConfigRequest } from '@app/types/stt-config'; import { zodResolver } from '@hookform/resolvers/zod'; @@ -52,7 +53,7 @@ interface EditSttConfigDialogProps { const EditSttConfigDialog: React.FC = ({ isOpen, onOpenChange, config, onSuccess }) => { const { notifySuccess, notifyError } = useNotifyStore(); - const [parameters, setParameters] = useState>({}); + const [parameters, setParameters] = useState>({}); const [loading, setLoading] = useState(false); const form = useForm({ @@ -90,7 +91,7 @@ const EditSttConfigDialog: React.FC = ({ isOpen, onOpe } }, [watchedProvider, isOpen, config.provider]); - const setParameter = (key: string, value: any) => { + const setParameter = (key: string, value: unknown) => { setParameters((prev) => ({ ...prev, [key]: value })); }; @@ -98,7 +99,7 @@ const EditSttConfigDialog: React.FC = ({ isOpen, onOpe const providerConfig = getProviderConfig('stt', watchedProvider); if (!providerConfig) return null; - const params: Record = {}; + const params: Record = {}; Object.entries(parameters).forEach(([key, value]) => { const paramConfig = providerConfig.parameters[key]; @@ -118,7 +119,7 @@ const EditSttConfigDialog: React.FC = ({ isOpen, onOpe const updateData: UpdateSttConfigRequest = { display_name: data.display_name.trim(), description: data.description?.trim() || null, - provider: data.provider as any, + provider: data.provider, language: data.language?.trim() || null, parameters: buildParameters(), }; @@ -131,8 +132,9 @@ const EditSttConfigDialog: React.FC = ({ isOpen, onOpe notifySuccess('STT configuration updated successfully'); onSuccess?.(); onOpenChange(false); - } catch (error: any) { - notifyError(error?.response?.data?.error?.message || 'Failed to update STT configuration'); + } catch (error) { + const errorMessage = extractErrorMessage(error); + notifyError(errorMessage || 'Failed to update STT configuration'); } finally { setLoading(false); } diff --git a/wavefront/client/src/pages/apps/[appId]/voice-agents/stt-configs/index.tsx b/wavefront/client/src/pages/apps/[appId]/voice-agents/stt-configs/index.tsx index 14183155..d9a7fd0b 100644 --- a/wavefront/client/src/pages/apps/[appId]/voice-agents/stt-configs/index.tsx +++ b/wavefront/client/src/pages/apps/[appId]/voice-agents/stt-configs/index.tsx @@ -6,6 +6,7 @@ import { Input } from '@app/components/ui/input'; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@app/components/ui/table'; import { useGetSttConfigs } from '@app/hooks'; import { getSttConfigsKey } from '@app/hooks/data/query-keys'; +import { extractErrorMessage } from '@app/lib/utils'; import { useNotifyStore } from '@app/store'; import { SttConfig } from '@app/types/stt-config'; import { useQueryClient } from '@tanstack/react-query'; @@ -53,8 +54,9 @@ const SttConfigsPage: React.FC = () => { notifySuccess('STT configuration deleted successfully'); queryClient.invalidateQueries({ queryKey: getSttConfigsKey(app || '') }); setDeleteItem(null); - } catch (error: any) { - notifyError(error?.response?.data?.error?.message || 'Failed to delete STT configuration'); + } catch (error) { + const errorMessage = extractErrorMessage(error); + notifyError(errorMessage || 'Failed to delete STT configuration'); } finally { setDeleting(false); } diff --git a/wavefront/client/src/pages/apps/[appId]/voice-agents/telephony-configs/CreateTelephonyConfigDialog.tsx b/wavefront/client/src/pages/apps/[appId]/voice-agents/telephony-configs/CreateTelephonyConfigDialog.tsx index 2efaa93c..95a3424a 100644 --- a/wavefront/client/src/pages/apps/[appId]/voice-agents/telephony-configs/CreateTelephonyConfigDialog.tsx +++ b/wavefront/client/src/pages/apps/[appId]/voice-agents/telephony-configs/CreateTelephonyConfigDialog.tsx @@ -28,8 +28,9 @@ import { isValidE164PhoneNumber, requiresSipConfig, } from '@app/config/telephony-providers'; +import { extractErrorMessage } from '@app/lib/utils'; import { useNotifyStore } from '@app/store'; -import { SipTransport } from '@app/types/telephony-config'; +import { ConnectionType, SipTransport, TelephonyProvider } from '@app/types/telephony-config'; import { zodResolver } from '@hookform/resolvers/zod'; import React, { useEffect, useState } from 'react'; import { useForm } from 'react-hook-form'; @@ -154,7 +155,7 @@ const CreateTelephonyConfigDialog: React.FC = } // Validate SIP config if required - if (requiresSipConfig(data.provider as any, data.connection_type)) { + if (requiresSipConfig(data.provider as TelephonyProvider, data.connection_type)) { if (!data.sip_domain?.trim()) { notifyError('SIP domain is required for SIP connection type'); return; @@ -165,10 +166,19 @@ const CreateTelephonyConfigDialog: React.FC = setLoading(true); try { - const requestData: any = { + const requestData: { + display_name: string; + description?: string; + provider: TelephonyProvider; + connection_type: ConnectionType; + credentials: { account_sid: string; auth_token: string }; + phone_numbers: string[]; + webhook_config: null; + sip_config?: { sip_domain: string; port?: number; transport?: SipTransport }; + } = { display_name: data.display_name.trim(), description: data.description?.trim() || undefined, - provider: data.provider as any, + provider: data.provider as TelephonyProvider, connection_type: data.connection_type, credentials: { account_sid: data.account_sid.trim(), @@ -179,7 +189,7 @@ const CreateTelephonyConfigDialog: React.FC = }; // Add SIP config if required - if (requiresSipConfig(data.provider as any, data.connection_type) && data.sip_domain?.trim()) { + if (requiresSipConfig(data.provider as TelephonyProvider, data.connection_type) && data.sip_domain?.trim()) { requestData.sip_config = { sip_domain: data.sip_domain.trim(), port: data.sip_port, @@ -191,15 +201,16 @@ const CreateTelephonyConfigDialog: React.FC = notifySuccess('Telephony configuration created successfully'); onSuccess?.(); onOpenChange(false); - } catch (error: any) { - notifyError(error?.response?.data?.error?.message || 'Failed to create telephony configuration'); + } catch (error) { + const errorMessage = extractErrorMessage(error); + notifyError(errorMessage || 'Failed to create telephony configuration'); } finally { setLoading(false); } }; - const providerConfig = getTelephonyProviderConfig(watchedProvider as any); - const showSipConfig = requiresSipConfig(watchedProvider as any, watchedConnectionType); + const providerConfig = getTelephonyProviderConfig(watchedProvider as TelephonyProvider); + const showSipConfig = requiresSipConfig(watchedProvider as TelephonyProvider, watchedConnectionType); return ( @@ -293,7 +304,7 @@ const CreateTelephonyConfigDialog: React.FC = - {getConnectionTypeOptions(watchedProvider as any).map((ct) => ( + {getConnectionTypeOptions(watchedProvider as TelephonyProvider).map((ct) => ( {ct.label} - {ct.description} diff --git a/wavefront/client/src/pages/apps/[appId]/voice-agents/telephony-configs/EditTelephonyConfigDialog.tsx b/wavefront/client/src/pages/apps/[appId]/voice-agents/telephony-configs/EditTelephonyConfigDialog.tsx index 78bc4db1..0feb1c41 100644 --- a/wavefront/client/src/pages/apps/[appId]/voice-agents/telephony-configs/EditTelephonyConfigDialog.tsx +++ b/wavefront/client/src/pages/apps/[appId]/voice-agents/telephony-configs/EditTelephonyConfigDialog.tsx @@ -28,8 +28,14 @@ import { isValidE164PhoneNumber, requiresSipConfig, } from '@app/config/telephony-providers'; +import { extractErrorMessage } from '@app/lib/utils'; import { useNotifyStore } from '@app/store'; -import { SipTransport, TelephonyConfig, UpdateTelephonyConfigRequest } from '@app/types/telephony-config'; +import { + SipTransport, + TelephonyConfig, + TelephonyProvider, + UpdateTelephonyConfigRequest, +} from '@app/types/telephony-config'; import { zodResolver } from '@hookform/resolvers/zod'; import React, { useEffect, useState } from 'react'; import { useForm } from 'react-hook-form'; @@ -156,7 +162,7 @@ const EditTelephonyConfigDialog: React.FC = ({ } // Validate SIP config if required - if (requiresSipConfig(data.provider as any, data.connection_type)) { + if (requiresSipConfig(data.provider as TelephonyProvider, data.connection_type)) { if (!data.sip_domain?.trim()) { notifyError('SIP domain is required for SIP connection type'); return; @@ -170,7 +176,7 @@ const EditTelephonyConfigDialog: React.FC = ({ const updateData: UpdateTelephonyConfigRequest = { display_name: data.display_name.trim(), description: data.description?.trim() || null, - provider: data.provider as any, + provider: data.provider as TelephonyProvider, connection_type: data.connection_type, phone_numbers: filledPhoneNumbers, }; @@ -190,13 +196,13 @@ const EditTelephonyConfigDialog: React.FC = ({ } // Add SIP config if required - if (requiresSipConfig(data.provider as any, data.connection_type) && data.sip_domain?.trim()) { + if (requiresSipConfig(data.provider as TelephonyProvider, data.connection_type) && data.sip_domain?.trim()) { updateData.sip_config = { sip_domain: data.sip_domain.trim(), port: data.sip_port, transport: data.sip_transport, }; - } else if (!requiresSipConfig(data.provider as any, data.connection_type)) { + } else if (!requiresSipConfig(data.provider as TelephonyProvider, data.connection_type)) { updateData.sip_config = null; } @@ -204,15 +210,16 @@ const EditTelephonyConfigDialog: React.FC = ({ notifySuccess('Telephony configuration updated successfully'); onSuccess?.(); onOpenChange(false); - } catch (error: any) { - notifyError(error?.response?.data?.error?.message || 'Failed to update telephony configuration'); + } catch (error) { + const errorMessage = extractErrorMessage(error); + notifyError(errorMessage || 'Failed to update telephony configuration'); } finally { setLoading(false); } }; - const providerConfig = getTelephonyProviderConfig(watchedProvider as any); - const showSipConfig = requiresSipConfig(watchedProvider as any, watchedConnectionType); + const providerConfig = getTelephonyProviderConfig(watchedProvider as TelephonyProvider); + const showSipConfig = requiresSipConfig(watchedProvider as TelephonyProvider, watchedConnectionType); return ( @@ -306,7 +313,7 @@ const EditTelephonyConfigDialog: React.FC = ({ - {getConnectionTypeOptions(watchedProvider as any).map((ct) => ( + {getConnectionTypeOptions(watchedProvider as TelephonyProvider).map((ct) => ( {ct.label} - {ct.description} diff --git a/wavefront/client/src/pages/apps/[appId]/voice-agents/telephony-configs/index.tsx b/wavefront/client/src/pages/apps/[appId]/voice-agents/telephony-configs/index.tsx index 4c80e9d5..71bc2dc2 100644 --- a/wavefront/client/src/pages/apps/[appId]/voice-agents/telephony-configs/index.tsx +++ b/wavefront/client/src/pages/apps/[appId]/voice-agents/telephony-configs/index.tsx @@ -6,6 +6,7 @@ import { Input } from '@app/components/ui/input'; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@app/components/ui/table'; import { useGetTelephonyConfigs } from '@app/hooks'; import { getTelephonyConfigsKey } from '@app/hooks/data/query-keys'; +import { extractErrorMessage } from '@app/lib/utils'; import { useNotifyStore } from '@app/store'; import { TelephonyConfig } from '@app/types/telephony-config'; import { useQueryClient } from '@tanstack/react-query'; @@ -53,8 +54,9 @@ const TelephonyConfigsPage: React.FC = () => { notifySuccess('Telephony configuration deleted successfully'); queryClient.invalidateQueries({ queryKey: getTelephonyConfigsKey(app || '') }); setDeleteItem(null); - } catch (error: any) { - notifyError(error?.response?.data?.error?.message || 'Failed to delete telephony configuration'); + } catch (error) { + const errorMessage = extractErrorMessage(error); + notifyError(errorMessage || 'Failed to delete telephony configuration'); } finally { setDeleting(false); } diff --git a/wavefront/client/src/pages/apps/[appId]/voice-agents/tts-configs/CreateTtsConfigDialog.tsx b/wavefront/client/src/pages/apps/[appId]/voice-agents/tts-configs/CreateTtsConfigDialog.tsx index f29339ca..1b22d19c 100644 --- a/wavefront/client/src/pages/apps/[appId]/voice-agents/tts-configs/CreateTtsConfigDialog.tsx +++ b/wavefront/client/src/pages/apps/[appId]/voice-agents/tts-configs/CreateTtsConfigDialog.tsx @@ -25,6 +25,7 @@ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@ import { Slider } from '@app/components/ui/slider'; import { Textarea } from '@app/components/ui/textarea'; import { VOICE_PROVIDERS_CONFIG, getProviderConfig, initializeParameters } from '@app/config/voice-providers'; +import { extractErrorMessage } from '@app/lib/utils'; import { useNotifyStore } from '@app/store'; import { zodResolver } from '@hookform/resolvers/zod'; import React, { useEffect, useState } from 'react'; @@ -51,7 +52,7 @@ interface CreateTtsConfigDialogProps { const CreateTtsConfigDialog: React.FC = ({ isOpen, onOpenChange, onSuccess }) => { const { notifySuccess, notifyError } = useNotifyStore(); - const [parameters, setParameters] = useState>({}); + const [parameters, setParameters] = useState>({}); const [loading, setLoading] = useState(false); const form = useForm({ @@ -90,7 +91,7 @@ const CreateTtsConfigDialog: React.FC = ({ isOpen, o } }, [isOpen, form]); - const setParameter = (key: string, value: any) => { + const setParameter = (key: string, value: unknown) => { setParameters((prev) => ({ ...prev, [key]: value })); }; @@ -98,7 +99,7 @@ const CreateTtsConfigDialog: React.FC = ({ isOpen, o const config = getProviderConfig('tts', watchedProvider); if (!config) return null; - const params: Record = {}; + const params: Record = {}; Object.entries(parameters).forEach(([key, value]) => { const paramConfig = config.parameters[key]; @@ -130,7 +131,7 @@ const CreateTtsConfigDialog: React.FC = ({ isOpen, o await floConsoleService.ttsConfigService.createTtsConfig({ display_name: data.display_name.trim(), description: data.description?.trim() || null, - provider: data.provider as any, + provider: data.provider, voice_id: data.voice_id.trim(), api_key: data.api_key.trim(), language: data.language?.trim() || null, @@ -139,8 +140,9 @@ const CreateTtsConfigDialog: React.FC = ({ isOpen, o notifySuccess('TTS configuration created successfully'); onSuccess?.(); onOpenChange(false); - } catch (error: any) { - notifyError(error?.response?.data?.error?.message || 'Failed to create TTS configuration'); + } catch (error) { + const errorMessage = extractErrorMessage(error); + notifyError(errorMessage || 'Failed to create TTS configuration'); } finally { setLoading(false); } diff --git a/wavefront/client/src/pages/apps/[appId]/voice-agents/tts-configs/EditTtsConfigDialog.tsx b/wavefront/client/src/pages/apps/[appId]/voice-agents/tts-configs/EditTtsConfigDialog.tsx index 66883e28..1e345ade 100644 --- a/wavefront/client/src/pages/apps/[appId]/voice-agents/tts-configs/EditTtsConfigDialog.tsx +++ b/wavefront/client/src/pages/apps/[appId]/voice-agents/tts-configs/EditTtsConfigDialog.tsx @@ -25,6 +25,7 @@ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@ import { Slider } from '@app/components/ui/slider'; import { Textarea } from '@app/components/ui/textarea'; import { VOICE_PROVIDERS_CONFIG, getProviderConfig, mergeParameters } from '@app/config/voice-providers'; +import { extractErrorMessage } from '@app/lib/utils'; import { useNotifyStore } from '@app/store'; import { TtsConfig, UpdateTtsConfigRequest } from '@app/types/tts-config'; import { zodResolver } from '@hookform/resolvers/zod'; @@ -53,7 +54,7 @@ interface EditTtsConfigDialogProps { const EditTtsConfigDialog: React.FC = ({ isOpen, onOpenChange, config, onSuccess }) => { const { notifySuccess, notifyError } = useNotifyStore(); - const [parameters, setParameters] = useState>({}); + const [parameters, setParameters] = useState>({}); const [loading, setLoading] = useState(false); const form = useForm({ @@ -93,7 +94,7 @@ const EditTtsConfigDialog: React.FC = ({ isOpen, onOpe } }, [watchedProvider, isOpen, config.provider]); - const setParameter = (key: string, value: any) => { + const setParameter = (key: string, value: unknown) => { setParameters((prev) => ({ ...prev, [key]: value })); }; @@ -101,7 +102,7 @@ const EditTtsConfigDialog: React.FC = ({ isOpen, onOpe const providerConfig = getProviderConfig('tts', watchedProvider); if (!providerConfig) return null; - const params: Record = {}; + const params: Record = {}; Object.entries(parameters).forEach(([key, value]) => { const paramConfig = providerConfig.parameters[key]; @@ -121,7 +122,7 @@ const EditTtsConfigDialog: React.FC = ({ isOpen, onOpe const updateData: UpdateTtsConfigRequest = { display_name: data.display_name.trim(), description: data.description?.trim() || null, - provider: data.provider as any, + provider: data.provider, voice_id: data.voice_id.trim(), language: data.language?.trim() || null, parameters: buildParameters(), @@ -135,8 +136,9 @@ const EditTtsConfigDialog: React.FC = ({ isOpen, onOpe notifySuccess('TTS configuration updated successfully'); onSuccess?.(); onOpenChange(false); - } catch (error: any) { - notifyError(error?.response?.data?.error?.message || 'Failed to update TTS configuration'); + } catch (error) { + const errorMessage = extractErrorMessage(error); + notifyError(errorMessage || 'Failed to update TTS configuration'); } finally { setLoading(false); } diff --git a/wavefront/client/src/pages/apps/[appId]/voice-agents/tts-configs/index.tsx b/wavefront/client/src/pages/apps/[appId]/voice-agents/tts-configs/index.tsx index 5f0db96f..e1bb1565 100644 --- a/wavefront/client/src/pages/apps/[appId]/voice-agents/tts-configs/index.tsx +++ b/wavefront/client/src/pages/apps/[appId]/voice-agents/tts-configs/index.tsx @@ -6,6 +6,7 @@ import { Input } from '@app/components/ui/input'; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@app/components/ui/table'; import { useGetTtsConfigs } from '@app/hooks'; import { getTtsConfigsKey } from '@app/hooks/data/query-keys'; +import { extractErrorMessage } from '@app/lib/utils'; import { useNotifyStore } from '@app/store'; import { TtsConfig } from '@app/types/tts-config'; import { useQueryClient } from '@tanstack/react-query'; @@ -53,8 +54,9 @@ const TtsConfigsPage: React.FC = () => { notifySuccess('TTS configuration deleted successfully'); queryClient.invalidateQueries({ queryKey: getTtsConfigsKey(app || '') }); setDeleteItem(null); - } catch (error: any) { - notifyError(error?.response?.data?.error?.message || 'Failed to delete TTS configuration'); + } catch (error) { + const errorMessage = extractErrorMessage(error); + notifyError(errorMessage || 'Failed to delete TTS configuration'); } finally { setDeleting(false); } diff --git a/wavefront/client/src/pages/apps/[appId]/workflows/CreateWorkflowDialog.tsx b/wavefront/client/src/pages/apps/[appId]/workflows/CreateWorkflowDialog.tsx index 945dcca0..081caf48 100644 --- a/wavefront/client/src/pages/apps/[appId]/workflows/CreateWorkflowDialog.tsx +++ b/wavefront/client/src/pages/apps/[appId]/workflows/CreateWorkflowDialog.tsx @@ -18,6 +18,7 @@ import { FormMessage, } from '@app/components/ui/form'; import { Input } from '@app/components/ui/input'; +import { extractErrorMessage } from '@app/lib/utils'; import { useNotifyStore } from '@app/store'; import { zodResolver } from '@hookform/resolvers/zod'; import { langs } from '@uiw/codemirror-extensions-langs'; @@ -156,10 +157,10 @@ const CreateWorkflowDialog: React.FC = ({ isOpen, onO onOpenChange(false); navigate(`/apps/${appId}/workflows/${createdWorkflowId}`); } - } catch (error: any) { + } catch (error) { console.error('Error creating workflow:', error); - const errorMessage = error?.response?.data?.meta?.error || error?.message || 'Failed to create workflow'; - notifyError(errorMessage); + const errorMessage = extractErrorMessage(error); + notifyError(errorMessage || 'Failed to create workflow'); } finally { setLoading(false); } diff --git a/wavefront/client/src/pages/apps/[appId]/workflows/[id].tsx b/wavefront/client/src/pages/apps/[appId]/workflows/[id].tsx index 41d2506d..b15d8688 100644 --- a/wavefront/client/src/pages/apps/[appId]/workflows/[id].tsx +++ b/wavefront/client/src/pages/apps/[appId]/workflows/[id].tsx @@ -4,6 +4,7 @@ import { Button } from '@app/components/ui/button'; import { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle } from '@app/components/ui/dialog'; import { appEnv } from '@app/config/env'; import { useNotifyStore } from '@app/store'; +import { ChatMessage, ChatMessageContent } from '@app/types/chat-message'; import { Workflow, WorkflowEvent } from '@app/types/workflow'; import { scrollToBottom } from '@app/utils/scroll'; import { langs } from '@uiw/codemirror-extensions-langs'; @@ -12,6 +13,8 @@ import React, { useCallback, useEffect, useRef, useState } from 'react'; import { flushSync } from 'react-dom'; import { useParams } from 'react-router'; +type MessageInput = { role: 'user' | 'assistant'; content: ChatMessageContent }; + const WorkflowDetail: React.FC = () => { const { app: appId, id } = useParams<{ app: string; id: string }>(); const { notifySuccess, notifyError } = useNotifyStore(); @@ -42,7 +45,7 @@ const WorkflowDetail: React.FC = () => { >([]); // Chat history and menu states - const [chatHistory, setChatHistory] = useState<{ role: 'user' | 'assistant'; content: any }[]>([]); + const [chatHistory, setChatHistory] = useState([]); const [showUploadMenu, setShowUploadMenu] = useState(false); const [showVariablesInput, setShowVariablesInput] = useState(false); const [selectedLLMConfigId, setSelectedLLMConfigId] = useState(''); @@ -348,13 +351,11 @@ const WorkflowDetail: React.FC = () => { } } - // Prepare inputs based on what's provided // eslint-disable-next-line @typescript-eslint/no-explicit-any let inputs: string | any[]; // Handle different input combinations - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const messageInputs: any[] = []; + const messageInputs: MessageInput[] = []; chatHistory.forEach((message) => { messageInputs.push({ role: message.role, @@ -435,7 +436,10 @@ const WorkflowDetail: React.FC = () => { } }; - const handleSSEInference = async (inputs: string | any[], variables: Record) => { + const handleSSEInference = async ( + inputs: string | Array<{ role: 'user' | 'assistant'; content: ChatMessageContent }>, + variables: Record + ) => { if (!id) return; try { diff --git a/wavefront/client/src/pages/apps/[appId]/workflows/pipelines/CreateWorkflowPipelineDialog.tsx b/wavefront/client/src/pages/apps/[appId]/workflows/pipelines/CreateWorkflowPipelineDialog.tsx index 9cf720f0..11b83d45 100644 --- a/wavefront/client/src/pages/apps/[appId]/workflows/pipelines/CreateWorkflowPipelineDialog.tsx +++ b/wavefront/client/src/pages/apps/[appId]/workflows/pipelines/CreateWorkflowPipelineDialog.tsx @@ -12,6 +12,7 @@ import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from ' import { Input } from '@app/components/ui/input'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@app/components/ui/select'; import { useGetWorkflows } from '@app/hooks/data/fetch-hooks'; +import { extractErrorMessage } from '@app/lib/utils'; import { useNotifyStore } from '@app/store'; import { zodResolver } from '@hookform/resolvers/zod'; import React, { useEffect, useState } from 'react'; @@ -77,9 +78,10 @@ const CreateWorkflowPipelineDialog: React.FC } else { notifyError('Failed to create pipeline'); } - } catch (error: any) { + } catch (error) { console.error('Error creating pipeline:', error); - notifyError(error?.response?.data?.meta?.error || 'Failed to create pipeline'); + const errorMessage = extractErrorMessage(error); + notifyError(errorMessage || 'Failed to create pipeline'); } finally { setLoading(false); } diff --git a/wavefront/client/src/pages/apps/edit/[appId].tsx b/wavefront/client/src/pages/apps/edit/[appId].tsx index 71c4d814..afc78f07 100644 --- a/wavefront/client/src/pages/apps/edit/[appId].tsx +++ b/wavefront/client/src/pages/apps/edit/[appId].tsx @@ -24,7 +24,7 @@ const EditApp: React.FC = () => { const queryClient = useQueryClient(); const { mutate: updateApp, isPending: isUpdating } = useUpdateApp(queryClient, notifySuccess, notifyError); // Extract app data from response - adjust based on actual API response structure - const appData = (response as any)?.data?.data?.app || (response as any)?.data?.app || response; + const appData = response; const form = useForm({ resolver: zodResolver(createAppSchema), diff --git a/wavefront/client/src/pages/types.ts b/wavefront/client/src/pages/types.ts index 0703e385..4e8b629b 100644 --- a/wavefront/client/src/pages/types.ts +++ b/wavefront/client/src/pages/types.ts @@ -68,7 +68,7 @@ export interface ILoanDeepDiveItem { item_risk_identified: IRiskCriterion[]; item_risk_identified_count: number; item_risk_flag: string; - item_coordinates: Record | null; + item_coordinates: Record | null; } export interface IUser { id: string; @@ -111,11 +111,11 @@ export interface ILoanDeepDiveData { image_risk_flag: string; clarity_score: number; overlap_score: number; - metadata_1: Record | null; - metadata_2: Record | null; - metadata_3: Record | null; - metadata_4: Record | null; - metadata_5: Record | null; + metadata_1: Record | null; + metadata_2: Record | null; + metadata_3: Record | null; + metadata_4: Record | null; + metadata_5: Record | null; filter_1: string | null; filter_2: string | null; filter_3: string | null; diff --git a/wavefront/client/src/types/agent.ts b/wavefront/client/src/types/agent.ts index 5208ccf4..2b7e363c 100644 --- a/wavefront/client/src/types/agent.ts +++ b/wavefront/client/src/types/agent.ts @@ -42,7 +42,7 @@ export interface AppConfig { id: string; name: string; description: string; - icon: React.ComponentType; + icon: React.ComponentType>; appId: string; defaultNamespace: string; color: string; @@ -117,7 +117,7 @@ export interface Agent { export interface Tool { name: string; description: string; - parameters?: Record; + parameters?: Record; } export interface Router { diff --git a/wavefront/client/src/types/api-service.ts b/wavefront/client/src/types/api-service.ts index 2cc594f6..1110dd4e 100644 --- a/wavefront/client/src/types/api-service.ts +++ b/wavefront/client/src/types/api-service.ts @@ -21,7 +21,7 @@ export interface ApiEndpoint { backend_path: string; method: string; additional_headers?: Record; - backend_query_params?: Record; + backend_query_params?: Record; output_mapper_enabled: boolean; output_mapper?: Record; } diff --git a/wavefront/client/src/types/authenticator.ts b/wavefront/client/src/types/authenticator.ts index b61f8e31..6fd54886 100644 --- a/wavefront/client/src/types/authenticator.ts +++ b/wavefront/client/src/types/authenticator.ts @@ -9,7 +9,7 @@ export interface Authenticator { auth_name: string; auth_type: AuthenticatorType; auth_desc: string | null; - config: Record | null; + config: Record | null; is_enabled: boolean; created_at: string; updated_at: string; @@ -20,13 +20,13 @@ export interface CreateAuthenticatorRequest { auth_name: string; auth_type: AuthenticatorType; auth_desc?: string | null; - config: Record; + config: Record; } // Update request interface (all fields optional except config) export interface UpdateAuthenticatorRequest { auth_desc?: string | null; - config: Record; + config: Record; } // Response data interfaces diff --git a/wavefront/client/src/types/chat-message.ts b/wavefront/client/src/types/chat-message.ts new file mode 100644 index 00000000..e80dbf36 --- /dev/null +++ b/wavefront/client/src/types/chat-message.ts @@ -0,0 +1,22 @@ +// Types for chat message content +export interface ImageContent { + image_base64: string; + mime_type?: string; +} + +export interface DocumentContent { + document_type: string; + document_base64?: string; + mime_type?: string; + metadata?: { + filename?: string; + size?: number; + }; +} + +export type ChatMessageContent = string | ImageContent | DocumentContent | Record; + +export interface ChatMessage { + role: 'user' | 'assistant'; + content: ChatMessageContent; +} diff --git a/wavefront/client/src/types/datasource.ts b/wavefront/client/src/types/datasource.ts index 9d0482b2..a19759b3 100644 --- a/wavefront/client/src/types/datasource.ts +++ b/wavefront/client/src/types/datasource.ts @@ -4,7 +4,7 @@ export interface Datasource { id: string; name: string; type: string; - config: Record; + config: Record; description?: string; created_at?: string; updated_at?: string; @@ -80,7 +80,7 @@ export interface DeleteYamlData { message: string; } export interface ExecuteYamlData { - results: Record[]; + results: Record[]; } export type TestDatasourceResponse = IApiResponse; diff --git a/wavefront/client/src/types/llm-inference-config.ts b/wavefront/client/src/types/llm-inference-config.ts index f86ffc2a..27094e40 100644 --- a/wavefront/client/src/types/llm-inference-config.ts +++ b/wavefront/client/src/types/llm-inference-config.ts @@ -8,7 +8,7 @@ export interface LLMInferenceConfig { display_name: string; type: InferenceEngineType; base_url?: string; - parameters?: Record | null; + parameters?: Record | null; is_deleted: boolean; created_at: string; updated_at: string; @@ -20,7 +20,7 @@ export interface CreateLLMConfigRequest { api_key?: string; type: InferenceEngineType; base_url?: string; - parameters?: Record | null; + parameters?: Record | null; } export interface UpdateLLMConfigRequest { @@ -29,7 +29,7 @@ export interface UpdateLLMConfigRequest { api_key?: string | null; type?: InferenceEngineType; base_url?: string | null; - parameters?: Record | null; + parameters?: Record | null; } export interface LLMConfigListData { diff --git a/wavefront/client/src/types/message-processor.ts b/wavefront/client/src/types/message-processor.ts index 0e0a4b6e..bb7e21b1 100644 --- a/wavefront/client/src/types/message-processor.ts +++ b/wavefront/client/src/types/message-processor.ts @@ -41,12 +41,12 @@ export interface UpdateMessageProcessorRequest { } export interface ExecuteMessageProcessorRequest { - input_data: Record; - execution_context?: Record; + input_data: Record; + execution_context?: Record; } export interface ExecuteMessageProcessorData { - result: any; + result: unknown; } export type MessageProcessorResponse = IApiResponse; diff --git a/wavefront/client/src/types/pipeline.ts b/wavefront/client/src/types/pipeline.ts index 1eff4d53..ff1720dd 100644 --- a/wavefront/client/src/types/pipeline.ts +++ b/wavefront/client/src/types/pipeline.ts @@ -36,7 +36,7 @@ export interface UpdateScheduleRequest { } export interface TriggerDagRunRequest { - conf?: Record; + conf?: Record; logical_date?: string; note?: string; } @@ -74,7 +74,7 @@ export interface TriggerDagRunData { state: string; logical_date: string; execution_date: string; - conf?: Record; + conf?: Record; } // Pipeline API Response Types diff --git a/wavefront/client/src/types/stt-config.ts b/wavefront/client/src/types/stt-config.ts index 9856c22e..a4029a15 100644 --- a/wavefront/client/src/types/stt-config.ts +++ b/wavefront/client/src/types/stt-config.ts @@ -8,7 +8,7 @@ export interface SttConfig { description: string | null; provider: SttProvider; language: string | null; - parameters: Record | null; + parameters: Record | null; is_deleted: boolean; created_at: string; updated_at: string; @@ -20,7 +20,7 @@ export interface CreateSttConfigRequest { provider: SttProvider; api_key: string; language?: string | null; - parameters?: Record | null; + parameters?: Record | null; } export interface UpdateSttConfigRequest { @@ -29,7 +29,7 @@ export interface UpdateSttConfigRequest { provider?: SttProvider; api_key?: string; language?: string | null; - parameters?: Record | null; + parameters?: Record | null; } export interface SttConfigData { diff --git a/wavefront/client/src/types/tts-config.ts b/wavefront/client/src/types/tts-config.ts index 26f33c12..0ece8947 100644 --- a/wavefront/client/src/types/tts-config.ts +++ b/wavefront/client/src/types/tts-config.ts @@ -9,7 +9,7 @@ export interface TtsConfig { provider: TtsProvider; voice_id: string; language: string | null; - parameters: Record | null; + parameters: Record | null; is_deleted: boolean; created_at: string; updated_at: string; @@ -22,7 +22,7 @@ export interface CreateTtsConfigRequest { voice_id: string; api_key: string; language?: string | null; - parameters?: Record | null; + parameters?: Record | null; } export interface UpdateTtsConfigRequest { @@ -32,7 +32,7 @@ export interface UpdateTtsConfigRequest { voice_id?: string; api_key?: string; language?: string | null; - parameters?: Record | null; + parameters?: Record | null; } export interface TtsConfigData { diff --git a/wavefront/client/src/types/voice-agent.ts b/wavefront/client/src/types/voice-agent.ts index 93334b04..bca1a3bc 100644 --- a/wavefront/client/src/types/voice-agent.ts +++ b/wavefront/client/src/types/voice-agent.ts @@ -13,7 +13,7 @@ export interface VoiceAgent { telephony_config_id: string; system_prompt: string; welcome_message: string; - conversation_config: Record | null; + conversation_config: Record | null; status: 'active' | 'inactive'; is_deleted: boolean; created_at: string; @@ -32,7 +32,7 @@ export interface CreateVoiceAgentRequest { telephony_config_id: string; system_prompt: string; welcome_message: string; - conversation_config?: Record | null; + conversation_config?: Record | null; status?: 'active' | 'inactive'; } @@ -49,7 +49,7 @@ export interface UpdateVoiceAgentRequest { telephony_config_id?: string; system_prompt?: string; welcome_message?: string; - conversation_config?: Record | null; + conversation_config?: Record | null; status?: 'active' | 'inactive'; }