From 4cecd2a164b7c68414500351d44f5978f1967f3d Mon Sep 17 00:00:00 2001 From: vedant-theagentic Date: Thu, 27 Nov 2025 18:42:27 +0530 Subject: [PATCH 01/16] test push from new account From cd62e828e923715edc25230837e755d225c988bd Mon Sep 17 00:00:00 2001 From: vedant-theagentic Date: Thu, 27 Nov 2025 19:09:57 +0530 Subject: [PATCH 02/16] Create persistenceMiddleware.ts --- .../src/dataStore/persistenceMiddleware.ts | 105 ++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 frontend/src/dataStore/persistenceMiddleware.ts diff --git a/frontend/src/dataStore/persistenceMiddleware.ts b/frontend/src/dataStore/persistenceMiddleware.ts new file mode 100644 index 0000000..b607419 --- /dev/null +++ b/frontend/src/dataStore/persistenceMiddleware.ts @@ -0,0 +1,105 @@ +import {Middleware} from "@reduxjs/toolkit"; +import {Message} from "@/types/chatTypes"; + +const CONVERSATIONS_STORAGE_KEY = "cortexon_conversations"; +const CURRENT_CONVERSATION_KEY = "cortexon_current_conversation"; + +export interface Conversation { + id: string; + title: string; + messages: Message[]; + createdAt: string; + updatedAt: string; +} + +// Load conversations from localStorage +export const loadConversations = (): Conversation[] => { + try { + const stored = localStorage.getItem(CONVERSATIONS_STORAGE_KEY); + if (stored) { + return JSON.parse(stored); + } + } catch (error) { + console.error("Error loading conversations from localStorage:", error); + } + return []; +}; + +// Save conversations to localStorage +export const saveConversations = (conversations: Conversation[]): void => { + try { + localStorage.setItem(CONVERSATIONS_STORAGE_KEY, JSON.stringify(conversations)); + } catch (error) { + console.error("Error saving conversations to localStorage:", error); + // Handle quota exceeded error + if (error instanceof Error && error.name === "QuotaExceededError") { + // Remove oldest conversations if storage is full + const sorted = [...conversations].sort( + (a, b) => new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime() + ); + // Keep only the 50 most recent conversations + const trimmed = sorted.slice(-50); + localStorage.setItem(CONVERSATIONS_STORAGE_KEY, JSON.stringify(trimmed)); + } + } +}; + +// Load current conversation from localStorage +export const loadCurrentConversation = (): Message[] => { + try { + const stored = localStorage.getItem(CURRENT_CONVERSATION_KEY); + if (stored) { + return JSON.parse(stored); + } + } catch (error) { + console.error("Error loading current conversation from localStorage:", error); + } + return []; +}; + +// Save current conversation to localStorage +export const saveCurrentConversation = (messages: Message[]): void => { + try { + localStorage.setItem(CURRENT_CONVERSATION_KEY, JSON.stringify(messages)); + } catch (error) { + console.error("Error saving current conversation to localStorage:", error); + } +}; + +// Generate a title from the first user message +export const generateConversationTitle = (messages: Message[]): string => { + const firstUserMessage = messages.find((msg) => msg.role === "user" && msg.prompt); + if (firstUserMessage?.prompt) { + // Take first 50 characters of the prompt + const title = firstUserMessage.prompt.substring(0, 50); + return title.length < firstUserMessage.prompt.length ? `${title}...` : title; + } + return "New Conversation"; +}; + +// Create a new conversation from messages +export const createConversation = (messages: Message[]): Conversation => { + const now = new Date().toISOString(); + return { + id: `conv_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`, + title: generateConversationTitle(messages), + messages, + createdAt: now, + updatedAt: now, + }; +}; + +// Persistence middleware for Redux +export const persistenceMiddleware: Middleware = (store) => (next) => (action) => { + const result = next(action); + const state = store.getState(); + + // Save current conversation whenever messages change + if (action.type === "messagesState/setMessages") { + const messages = state.messagesState.messages; + saveCurrentConversation(messages); + } + + return result; +}; + From 086fa095a51e32f5dd34b0ead13a33c6e8aa0f45 Mon Sep 17 00:00:00 2001 From: vedant-theagentic Date: Thu, 27 Nov 2025 19:11:07 +0530 Subject: [PATCH 03/16] Create conversationUtils.ts --- frontend/src/utils/conversationUtils.ts | 113 ++++++++++++++++++++++++ 1 file changed, 113 insertions(+) create mode 100644 frontend/src/utils/conversationUtils.ts diff --git a/frontend/src/utils/conversationUtils.ts b/frontend/src/utils/conversationUtils.ts new file mode 100644 index 0000000..b613bae --- /dev/null +++ b/frontend/src/utils/conversationUtils.ts @@ -0,0 +1,113 @@ +import {Message} from "@/types/chatTypes"; +import { + Conversation, + createConversation, + loadConversations, + saveConversations, + generateConversationTitle, +} from "@/dataStore/persistenceMiddleware"; + +// Save current conversation to the conversations list +export const saveConversation = (messages: Message[]): Conversation => { + if (messages.length === 0) { + throw new Error("Cannot save empty conversation"); + } + + const conversations = loadConversations(); + const newConversation = createConversation(messages); + + // Check if this is an update to an existing conversation + // (e.g., if we're continuing an existing conversation) + const existingIndex = conversations.findIndex( + (conv) => conv.id === newConversation.id + ); + + if (existingIndex >= 0) { + // Update existing conversation + conversations[existingIndex] = { + ...newConversation, + id: conversations[existingIndex].id, // Keep original ID + createdAt: conversations[existingIndex].createdAt, // Keep original creation date + updatedAt: new Date().toISOString(), + }; + } else { + // Add new conversation + conversations.push(newConversation); + } + + // Sort by updatedAt (most recent first) + conversations.sort( + (a, b) => new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime() + ); + + saveConversations(conversations); + return newConversation; +}; + +// Delete a conversation +export const deleteConversation = (conversationId: string): void => { + const conversations = loadConversations(); + const filtered = conversations.filter((conv) => conv.id !== conversationId); + saveConversations(filtered); +}; + +// Get a conversation by ID +export const getConversation = (conversationId: string): Conversation | null => { + const conversations = loadConversations(); + return conversations.find((conv) => conv.id === conversationId) || null; +}; + +// Export conversation as JSON +export const exportConversationAsJSON = (conversation: Conversation): string => { + return JSON.stringify(conversation, null, 2); +}; + +// Export conversation as Markdown +export const exportConversationAsMarkdown = (conversation: Conversation): string => { + let markdown = `# ${conversation.title}\n\n`; + markdown += `**Created:** ${new Date(conversation.createdAt).toLocaleString()}\n`; + markdown += `**Updated:** ${new Date(conversation.updatedAt).toLocaleString()}\n\n`; + markdown += `---\n\n`; + + conversation.messages.forEach((message, index) => { + if (message.role === "user" && message.prompt) { + markdown += `## User Message ${index + 1}\n\n`; + markdown += `${message.prompt}\n\n`; + } else if (message.role === "assistant" && message.data) { + markdown += `## Assistant Response ${index + 1}\n\n`; + message.data.forEach((systemMessage) => { + markdown += `### ${systemMessage.agent_name}\n\n`; + if (systemMessage.instructions) { + markdown += `**Instructions:** ${systemMessage.instructions}\n\n`; + } + if (systemMessage.steps && systemMessage.steps.length > 0) { + markdown += `**Steps:**\n`; + systemMessage.steps.forEach((step) => { + markdown += `- ${step}\n`; + }); + markdown += `\n`; + } + if (systemMessage.output) { + markdown += `**Output:**\n\n${systemMessage.output}\n\n`; + } + markdown += `---\n\n`; + }); + } + }); + + return markdown; +}; + +// Download file helper +export const downloadFile = (content: string, filename: string, mimeType: string): void => { + const blob = new Blob([content], {type: mimeType}); + const url = URL.createObjectURL(blob); + const link = document.createElement("a"); + link.href = url; + link.download = filename; + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); + URL.revokeObjectURL(url); +}; + From 8d96d1a5898a34780d7413df2f6c21c6e7c3ea4e Mon Sep 17 00:00:00 2001 From: vedant-theagentic Date: Thu, 27 Nov 2025 19:12:07 +0530 Subject: [PATCH 04/16] Create ConversationList.tsx --- .../src/components/home/ConversationList.tsx | 251 ++++++++++++++++++ 1 file changed, 251 insertions(+) create mode 100644 frontend/src/components/home/ConversationList.tsx diff --git a/frontend/src/components/home/ConversationList.tsx b/frontend/src/components/home/ConversationList.tsx new file mode 100644 index 0000000..c034834 --- /dev/null +++ b/frontend/src/components/home/ConversationList.tsx @@ -0,0 +1,251 @@ +import {useState, useEffect} from "react"; +import {useDispatch} from "react-redux"; +import { + MessageSquare, + Trash2, + Download, + X, + FileText, + FileJson, + Plus, + History, +} from "lucide-react"; +import {Button} from "../ui/button"; +import {Card} from "../ui/card"; +import {ScrollArea} from "../ui/scroll-area"; +import { + Conversation, + loadConversations, +} from "@/dataStore/persistenceMiddleware"; +import { + saveConversation, + deleteConversation, + exportConversationAsJSON, + exportConversationAsMarkdown, + downloadFile, +} from "@/utils/conversationUtils"; +import {setMessages, clearMessages} from "@/dataStore/messagesSlice"; +import {Message} from "@/types/chatTypes"; + +interface ConversationListProps { + isOpen: boolean; + onClose: () => void; + currentMessages: Message[]; +} + +export const ConversationList = ({ + isOpen, + onClose, + currentMessages, +}: ConversationListProps) => { + const [conversations, setConversations] = useState([]); + const dispatch = useDispatch(); + + useEffect(() => { + if (isOpen) { + loadConversationsList(); + } + }, [isOpen]); + + const loadConversationsList = () => { + const loaded = loadConversations(); + setConversations(loaded); + }; + + const handleSaveCurrent = () => { + if (currentMessages.length === 0) { + alert("No messages to save"); + return; + } + try { + saveConversation(currentMessages); + loadConversationsList(); + alert("Conversation saved successfully!"); + } catch (error) { + alert(`Error saving conversation: ${error}`); + } + }; + + const handleLoadConversation = (conversation: Conversation) => { + dispatch(setMessages(conversation.messages)); + onClose(); + }; + + const handleDeleteConversation = ( + e: React.MouseEvent, + conversationId: string + ) => { + e.stopPropagation(); + if (confirm("Are you sure you want to delete this conversation?")) { + deleteConversation(conversationId); + loadConversationsList(); + } + }; + + const handleExportJSON = ( + e: React.MouseEvent, + conversation: Conversation + ) => { + e.stopPropagation(); + const json = exportConversationAsJSON(conversation); + const filename = `conversation_${conversation.id}_${new Date().toISOString().split("T")[0]}.json`; + downloadFile(json, filename, "application/json"); + }; + + const handleExportMarkdown = ( + e: React.MouseEvent, + conversation: Conversation + ) => { + e.stopPropagation(); + const markdown = exportConversationAsMarkdown(conversation); + const filename = `conversation_${conversation.id}_${new Date().toISOString().split("T")[0]}.md`; + downloadFile(markdown, filename, "text/markdown"); + }; + + const handleNewConversation = () => { + if (currentMessages.length > 0) { + if ( + confirm( + "Starting a new conversation will clear current messages. Do you want to save the current conversation first?" + ) + ) { + handleSaveCurrent(); + } + } + dispatch(clearMessages()); + onClose(); + }; + + const formatDate = (dateString: string) => { + const date = new Date(dateString); + const now = new Date(); + const diffMs = now.getTime() - date.getTime(); + const diffMins = Math.floor(diffMs / 60000); + const diffHours = Math.floor(diffMs / 3600000); + const diffDays = Math.floor(diffMs / 86400000); + + if (diffMins < 1) return "Just now"; + if (diffMins < 60) return `${diffMins}m ago`; + if (diffHours < 24) return `${diffHours}h ago`; + if (diffDays < 7) return `${diffDays}d ago`; + return date.toLocaleDateString(); + }; + + if (!isOpen) return null; + + return ( +
+ {/* Backdrop */} + + ); +}; + From 219b18a29458214ccbfd74f27f8d7f60d7fc6f70 Mon Sep 17 00:00:00 2001 From: vedant-theagentic Date: Thu, 27 Nov 2025 19:13:39 +0530 Subject: [PATCH 05/16] Create ConversationContext.tsx --- frontend/src/contexts/ConversationContext.tsx | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 frontend/src/contexts/ConversationContext.tsx diff --git a/frontend/src/contexts/ConversationContext.tsx b/frontend/src/contexts/ConversationContext.tsx new file mode 100644 index 0000000..d8abfe0 --- /dev/null +++ b/frontend/src/contexts/ConversationContext.tsx @@ -0,0 +1,38 @@ +import {createContext, useContext, useState, ReactNode} from "react"; + +interface ConversationContextType { + isOpen: boolean; + openConversationList: () => void; + closeConversationList: () => void; +} + +const ConversationContext = createContext( + undefined +); + +export const ConversationProvider = ({children}: {children: ReactNode}) => { + const [isOpen, setIsOpen] = useState(false); + + return ( + setIsOpen(true), + closeConversationList: () => setIsOpen(false), + }} + > + {children} + + ); +}; + +export const useConversationContext = () => { + const context = useContext(ConversationContext); + if (!context) { + throw new Error( + "useConversationContext must be used within ConversationProvider" + ); + } + return context; +}; + From 7d6052706222f11fdc6c90fe11c6a774642668b5 Mon Sep 17 00:00:00 2001 From: vedant-theagentic Date: Thu, 27 Nov 2025 19:14:38 +0530 Subject: [PATCH 06/16] Update store.ts --- frontend/src/dataStore/store.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/frontend/src/dataStore/store.ts b/frontend/src/dataStore/store.ts index c3be4e6..18cf0a1 100644 --- a/frontend/src/dataStore/store.ts +++ b/frontend/src/dataStore/store.ts @@ -1,13 +1,15 @@ import vaultApi from "@/services/vaultApi"; import {configureStore} from "@reduxjs/toolkit"; import messagesSlice from "./messagesSlice"; +import {persistenceMiddleware} from "./persistenceMiddleware"; + export const store = configureStore({ reducer: { [messagesSlice.name]: messagesSlice.reducer, [vaultApi.reducerPath]: vaultApi.reducer, }, middleware: (getDefaultMiddleware) => - getDefaultMiddleware().concat(vaultApi.middleware), + getDefaultMiddleware().concat(vaultApi.middleware, persistenceMiddleware), }); export type RootState = ReturnType; From b82d7d02a6729d098fa70def8b46e3da3a8d49b8 Mon Sep 17 00:00:00 2001 From: vedant-theagentic Date: Thu, 27 Nov 2025 19:14:56 +0530 Subject: [PATCH 07/16] Update messagesSlice.ts --- frontend/src/dataStore/messagesSlice.ts | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/frontend/src/dataStore/messagesSlice.ts b/frontend/src/dataStore/messagesSlice.ts index 6a6baac..ad5d50c 100644 --- a/frontend/src/dataStore/messagesSlice.ts +++ b/frontend/src/dataStore/messagesSlice.ts @@ -1,10 +1,22 @@ import {Message} from "@/types/chatTypes"; import {createSlice} from "@reduxjs/toolkit"; +import {loadCurrentConversation} from "./persistenceMiddleware"; + +// Load messages from localStorage on initialization +const loadInitialMessages = (): Message[] => { + try { + const saved = loadCurrentConversation(); + return saved.length > 0 ? saved : []; + } catch (error) { + console.error("Error loading initial messages:", error); + return []; + } +}; export const initialState: { messages: Message[]; } = { - messages: [], + messages: loadInitialMessages(), }; export const messagesSlice = createSlice({ @@ -14,9 +26,12 @@ export const messagesSlice = createSlice({ setMessages: (state, action) => { state.messages = action.payload; }, + clearMessages: (state) => { + state.messages = []; + }, }, }); -export const {setMessages} = messagesSlice.actions; +export const {setMessages, clearMessages} = messagesSlice.actions; export default messagesSlice; From f01b04f3387dfc4e69c02761f7c89586a132926c Mon Sep 17 00:00:00 2001 From: vedant-theagentic Date: Thu, 27 Nov 2025 19:15:59 +0530 Subject: [PATCH 08/16] Update Header.tsx --- frontend/src/components/home/Header.tsx | 47 +++++++++++++++++-------- 1 file changed, 33 insertions(+), 14 deletions(-) diff --git a/frontend/src/components/home/Header.tsx b/frontend/src/components/home/Header.tsx index d6217fd..18d3760 100644 --- a/frontend/src/components/home/Header.tsx +++ b/frontend/src/components/home/Header.tsx @@ -1,14 +1,19 @@ import {setMessages} from "@/dataStore/messagesSlice"; -import {MessageCirclePlus} from "lucide-react"; +import {MessageCirclePlus, History} from "lucide-react"; import {useDispatch} from "react-redux"; import {useLocation, useNavigate} from "react-router-dom"; import Logo from "../../assets/CortexON_logo_dark.svg"; import {Button} from "../ui/button"; +import {useConversationContext} from "@/contexts/ConversationContext"; const Header = () => { const nav = useNavigate(); - const location = useLocation().pathname; + const location = useLocation(); const dispatch = useDispatch(); + const {openConversationList} = useConversationContext(); + + // Only show conversation button on home page + const showConversationButton = location.pathname === "/"; return (
@@ -25,7 +30,7 @@ const Header = () => {
nav("/vault")} className={`w-[10%] h-full flex justify-center items-center cursor-pointer border-b-2 hover:border-[#BD24CA] ${ - location.includes("/vault") + location.pathname.includes("/vault") ? "border-[#BD24CA]" : "border-background" }`} @@ -33,17 +38,31 @@ const Header = () => {

Vault

- +
+ {showConversationButton && ( + + )} + +
); }; From fc643c4f95e58a12c06451534c593930cb02cb81 Mon Sep 17 00:00:00 2001 From: vedant-theagentic Date: Thu, 27 Nov 2025 19:16:19 +0530 Subject: [PATCH 09/16] Update Chat.tsx --- frontend/src/components/home/Chat.tsx | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/frontend/src/components/home/Chat.tsx b/frontend/src/components/home/Chat.tsx index dda5a60..01fc646 100644 --- a/frontend/src/components/home/Chat.tsx +++ b/frontend/src/components/home/Chat.tsx @@ -3,22 +3,32 @@ import {useState} from "react"; import {useSelector} from "react-redux"; import ChatList from "./ChatList"; import Landing from "./Landing"; +import {ConversationList} from "./ConversationList"; +import {useConversationContext} from "@/contexts/ConversationContext"; const Chat = () => { const [isLoading, setIsLoading] = useState(false); + const {isOpen, closeConversationList} = useConversationContext(); const messages = useSelector( (state: RootState) => state.messagesState.messages ); return ( -
- {messages.length === 0 ? ( - - ) : ( - - )} -
+ <> +
+ {messages.length === 0 ? ( + + ) : ( + + )} +
+ + ); }; From 5b9416f5503aed4b565a479724da5f7c69aaf8cf Mon Sep 17 00:00:00 2001 From: vedant-theagentic Date: Thu, 27 Nov 2025 19:16:50 +0530 Subject: [PATCH 10/16] Update App.tsx --- frontend/src/App.tsx | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index ed4c83e..65a4140 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -2,17 +2,20 @@ import {BrowserRouter, Route, Routes} from "react-router-dom"; import Home from "./pages/Home"; import {Layout} from "./pages/Layout"; import {Vault} from "./pages/Vault"; +import {ConversationProvider} from "./contexts/ConversationContext"; function App() { return ( - - - }> - } /> - } /> - - - + + + + }> + } /> + } /> + + + + ); } From 3872deb76a8467c90e7c6982838ad4cdb9ec6f7c Mon Sep 17 00:00:00 2001 From: vedant-theagentic Date: Thu, 27 Nov 2025 19:17:19 +0530 Subject: [PATCH 11/16] Update main.py --- cortex_on/main.py | 34 ++++++++++++++++++++++++++++++---- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/cortex_on/main.py b/cortex_on/main.py index a8dd4de..5b93e5c 100644 --- a/cortex_on/main.py +++ b/cortex_on/main.py @@ -1,8 +1,10 @@ # Standard library imports +import json from typing import List, Optional # Third-party imports -from fastapi import FastAPI, WebSocket +from fastapi import FastAPI, WebSocket, WebSocketDisconnect +import logfire # Local application imports from instructor import SystemInstructor @@ -22,6 +24,30 @@ async def agent_chat(task: str) -> List: @app.websocket("/ws") async def websocket_endpoint(websocket: WebSocket): await websocket.accept() - while True: - data = await websocket.receive_text() - await generate_response(data, websocket) + try: + while True: + try: + data = await websocket.receive_text() + await generate_response(data, websocket) + except WebSocketDisconnect: + logfire.info("Client disconnected from WebSocket") + break + except Exception as e: + logfire.error(f"Error processing WebSocket message: {str(e)}") + # Try to send error to client if still connected + try: + if websocket.client_state.CONNECTED: + await websocket.send_text(json.dumps({"error": str(e)})) + except: + pass + break + except WebSocketDisconnect: + logfire.info("WebSocket connection closed by client") + except Exception as e: + logfire.error(f"WebSocket endpoint error: {str(e)}") + finally: + try: + if websocket.client_state.CONNECTED: + await websocket.close() + except: + pass From 45f68e34b3880c420fff976dbba64f96899f1c8c Mon Sep 17 00:00:00 2001 From: vedant-theagentic Date: Thu, 27 Nov 2025 19:18:17 +0530 Subject: [PATCH 12/16] Update web_surfer.py --- cortex_on/agents/web_surfer.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/cortex_on/agents/web_surfer.py b/cortex_on/agents/web_surfer.py index 34e2cfd..b9efba8 100644 --- a/cortex_on/agents/web_surfer.py +++ b/cortex_on/agents/web_surfer.py @@ -29,7 +29,13 @@ TIMEOUT = 9999999999999999999999999999999999999999999 class WebSurfer: - def __init__(self, api_url: str = "http://localhost:8000/api/v1/web/stream"): + def __init__(self, api_url: Optional[str] = None): + # Use environment variable or default to Docker service name, fallback to localhost + if api_url is None: + api_url = os.getenv( + "AGENTIC_BROWSER_URL", + "http://agentic_browser:8000/api/v1/web/stream" + ) self.api_url = api_url self.name = "Web Surfer Agent" self.description = "An agent that is a websurfer and a webscraper that can access any web-page to extract information or perform actions." @@ -148,4 +154,4 @@ async def generate_reply( timestamp=datetime.utcnow(), ) - return False, error_message, [error_response] \ No newline at end of file + return False, error_message, [error_response] From d52a570979f5cfbfc4e3417d1c3acdc18711cb62 Mon Sep 17 00:00:00 2001 From: vedant-theagentic Date: Thu, 27 Nov 2025 19:18:53 +0530 Subject: [PATCH 13/16] Update orchestrator_agent.py --- cortex_on/agents/orchestrator_agent.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cortex_on/agents/orchestrator_agent.py b/cortex_on/agents/orchestrator_agent.py index 6b001ba..23f05d2 100644 --- a/cortex_on/agents/orchestrator_agent.py +++ b/cortex_on/agents/orchestrator_agent.py @@ -307,8 +307,8 @@ async def web_surfer_task(ctx: RunContext[orchestrator_deps], task: str) -> str: await _safe_websocket_send(ctx.deps.websocket, web_surfer_stream_output) - # Initialize WebSurfer agent - web_surfer_agent = WebSurfer(api_url="http://localhost:8000/api/v1/web/stream") + # Initialize WebSurfer agent - will use environment variable or Docker service name + web_surfer_agent = WebSurfer() # Run WebSurfer with its own stream_output success, message, messages = await web_surfer_agent.generate_reply( @@ -484,7 +484,7 @@ async def planner_agent_update(ctx: RunContext[orchestrator_deps], completed_tas logfire.error(error_msg, exc_info=True) planner_stream_output.steps.append(f"Plan update failed: {str(e)}") - planner_stream_output.status_code = a500 + planner_stream_output.status_code = 500 await _safe_websocket_send(ctx.deps.websocket, planner_stream_output) return f"Failed to update the plan: {error_msg}" @@ -511,4 +511,4 @@ async def _safe_websocket_send(websocket: Optional[WebSocket], message: Any) -> return False except Exception as e: logfire.error(f"WebSocket send failed: {str(e)}") - return False \ No newline at end of file + return False From 6b931d880c7cd3cc56a759f639b36bf72ebc084a Mon Sep 17 00:00:00 2001 From: vedant-theagentic Date: Thu, 27 Nov 2025 19:19:44 +0530 Subject: [PATCH 14/16] Update docker-compose.yaml --- docker-compose.yaml | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/docker-compose.yaml b/docker-compose.yaml index e9f951a..8e0de6d 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -1,5 +1,3 @@ -version: '3.8' - services: cortex_on: build: @@ -9,8 +7,9 @@ services: - ./cortex_on:/app env_file: - .env + ports: + - "8081:8081" restart: always - network_mode: host agentic_browser: build: @@ -20,8 +19,9 @@ services: - ./ta-browser:/app env_file: - .env + ports: + - "8000:8000" restart: always - network_mode: host frontend: build: @@ -32,8 +32,9 @@ services: - /app/node_modules env_file: - .env + ports: + - "3000:3000" depends_on: - cortex_on - agentic_browser restart: always - network_mode: host From 3b3cd18655e3bf04b65a8f16f02a2663126dcdd2 Mon Sep 17 00:00:00 2001 From: vedant-theagentic Date: Thu, 27 Nov 2025 19:20:11 +0530 Subject: [PATCH 15/16] Update Dockerfile --- ta-browser/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ta-browser/Dockerfile b/ta-browser/Dockerfile index 4fb2065..149a01c 100644 --- a/ta-browser/Dockerfile +++ b/ta-browser/Dockerfile @@ -1,4 +1,4 @@ -FROM python:3.11 +FROM python:3.11-slim-bullseye WORKDIR /app From 27ba0bc67d6d3ede7d8a7d55accf85e4acf21fed Mon Sep 17 00:00:00 2001 From: vedant-theagentic Date: Thu, 27 Nov 2025 19:20:55 +0530 Subject: [PATCH 16/16] Update Dockerfile --- cortex_on/Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cortex_on/Dockerfile b/cortex_on/Dockerfile index 8d7373e..42041f7 100644 --- a/cortex_on/Dockerfile +++ b/cortex_on/Dockerfile @@ -1,4 +1,4 @@ -FROM python:3.10-slim +FROM python:3.11-slim-bullseye WORKDIR /app @@ -20,4 +20,4 @@ COPY . . EXPOSE 8081 -CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8081"] \ No newline at end of file +CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8081"]