From fd4504fb178598444ddf9fa98cef60638aa449d1 Mon Sep 17 00:00:00 2001 From: vishnu r kumar Date: Fri, 6 Mar 2026 20:00:28 +0530 Subject: [PATCH] fix: enable json output for workflows and update logs --- wavefront/client/src/api/workflow-service.ts | 5 ++- wavefront/client/src/components/ChatBot.tsx | 29 ++++++--------- .../src/pages/apps/[appId]/workflows/[id].tsx | 37 +++++++++++-------- .../controllers/workflow_controller.py | 2 +- .../message_processor_controller.py | 4 +- wavefront/server/uv.lock | 4 ++ 6 files changed, 43 insertions(+), 38 deletions(-) diff --git a/wavefront/client/src/api/workflow-service.ts b/wavefront/client/src/api/workflow-service.ts index c341d093..8d5107d3 100644 --- a/wavefront/client/src/api/workflow-service.ts +++ b/wavefront/client/src/api/workflow-service.ts @@ -57,12 +57,13 @@ export class WorkflowService { async runInference( id: string, inputs: string | unknown[], - variables: Record = {} + variables: Record = {}, + outputJsonEnabled: boolean = false ): Promise { const requestBody: Record = { inputs, variables, - output_json_enabled: false, + output_json_enabled: outputJsonEnabled, }; const response: IApiResponse = await this.http.post( diff --git a/wavefront/client/src/components/ChatBot.tsx b/wavefront/client/src/components/ChatBot.tsx index 7131889d..12711a74 100644 --- a/wavefront/client/src/components/ChatBot.tsx +++ b/wavefront/client/src/components/ChatBot.tsx @@ -1,4 +1,6 @@ import { Button } from '@app/components/ui/button'; +import { Label } from '@app/components/ui/label'; +import { Switch } from '@app/components/ui/switch'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@app/components/ui/select'; import { Spinner } from '@app/components/ui/spinner'; import { Textarea } from '@app/components/ui/textarea'; @@ -102,7 +104,7 @@ const ChatBot = ({ isModelSwitchEnabled = true, }: ChatBotProps) => { const variablesModalRef = useRef(null); - const [showLogic, setShowLogic] = useState(false); + const [showLogic, setShowLogic] = useState(true); const [selectValue, setSelectValue] = useState(''); return ( @@ -111,23 +113,14 @@ const ChatBot = ({ {listenEventsEnabled !== undefined && setListenEventsEnabled !== undefined && (
- - + +

{listenEventsEnabled ? 'Stream real-time workflow execution events' : 'Standard inference response only'} diff --git a/wavefront/client/src/pages/apps/[appId]/workflows/[id].tsx b/wavefront/client/src/pages/apps/[appId]/workflows/[id].tsx index b15d8688..1af4600e 100644 --- a/wavefront/client/src/pages/apps/[appId]/workflows/[id].tsx +++ b/wavefront/client/src/pages/apps/[appId]/workflows/[id].tsx @@ -1,6 +1,8 @@ import floConsoleService from '@app/api'; import ChatBot from '@app/components/ChatBot'; import { Button } from '@app/components/ui/button'; +import { Label } from '@app/components/ui/label'; +import { Switch } from '@app/components/ui/switch'; import { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle } from '@app/components/ui/dialog'; import { appEnv } from '@app/config/env'; import { useNotifyStore } from '@app/store'; @@ -61,17 +63,17 @@ const WorkflowDetail: React.FC = () => { }> >([]); const [uploadingDocument, setUploadingDocument] = useState(false); - - // JSON output state + const [outputJsonEnabled, setOutputJsonEnabled] = useState(false); // SSE state const [listenEventsEnabled, setListenEventsEnabled] = useState(false); - const [abortController, setAbortController] = useState(null); const [streamingEvents, setStreamingEvents] = useState([]); const [isStreaming, setIsStreaming] = useState(false); // Ref for auto-scrolling events container const eventsContainerRef = useRef(null); + // Ref for current abort controller - used so unmount cleanup doesn't depend on state + const abortControllerRef = useRef(null); const loadWorkflow = useCallback(async () => { if (!id) return; @@ -187,15 +189,13 @@ const WorkflowDetail: React.FC = () => { }); }, []); - // Cleanup fetchEventSource on unmount and when switching between SSE/normal inference + // Cleanup SSE request only on unmount (avoid aborting when abortController state changes) useEffect(() => { return () => { - if (abortController) { - abortController.abort(); - setAbortController(null); - } + abortControllerRef.current?.abort(); + abortControllerRef.current = null; }; - }, [abortController]); + }, []); const handleDocumentUpload = useCallback( (event: React.ChangeEvent) => { const files = event.target.files; @@ -331,9 +331,9 @@ const WorkflowDetail: React.FC = () => { setRunningInference(true); // Abort any existing fetchEventSource - if (abortController) { - abortController.abort(); - setAbortController(null); + if (abortControllerRef.current) { + abortControllerRef.current.abort(); + abortControllerRef.current = null; } // Clear previous results @@ -421,7 +421,7 @@ const WorkflowDetail: React.FC = () => { await handleSSEInference(inputs, variables); } else { // Handle normal inference - const result = await floConsoleService.workflowService.runInference(id, inputs, variables); + const result = await floConsoleService.workflowService.runInference(id, inputs, variables, outputJsonEnabled); const resultContent = result.data?.data?.data?.result; if (resultContent) { setChatHistory((prev) => [...prev, { role: 'assistant', content: resultContent }]); @@ -458,13 +458,14 @@ const WorkflowDetail: React.FC = () => { inputs, variables, listen_events: true, + output_json_enabled: outputJsonEnabled, }; const url = `${baseUrl}/v1/${appId}/floware/v2/workflows/${id}/inference`; // Create abort controller for cleanup const controller = new AbortController(); - setAbortController(controller); + abortControllerRef.current = controller; // RAW FETCH with immediate ReadableStream processing const response = await fetch(url, { @@ -646,7 +647,7 @@ const WorkflowDetail: React.FC = () => { function cleanup() { setRunningInference(false); setIsStreaming(false); - setAbortController(null); + abortControllerRef.current = null; } }; @@ -679,6 +680,12 @@ const WorkflowDetail: React.FC = () => {

+
+ + +