Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 54 additions & 2 deletions core/orchestrator.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@
from core.utils.openai_msg_parser import AgentConversationHandler, ConversationStorage
from core.utils.custom_exceptions import CustomException, PlannerError, BrowserNavigationError, SSAnalysisError, CritiqueError

import lucidicai as lai
import os
from dotenv import load_dotenv
load_dotenv()

tokenizer = tiktoken.encoding_for_model("gpt-4o")

Expand Down Expand Up @@ -286,6 +290,15 @@ async def run(self, command, start_url: Optional[str] = None):
if start_url and start_url != self.current_url:
await self.navigate_to_url(start_url)

lai.init(
"The Agentic Browser",
task=command,
# agent_id=os.getenv("LUCIDIC_AGENT_ID"), -> This is grabbed automatically from env
# lucidic_api_key=os.getenv("LUCIDIC_API_KEY") -> This is grabbed automatically from env
provider="openai",
# mass_sim_id=<FILL THIS IN> -> include this if this session should be part of a mass simulation
)

try:
logfire.info(f" Running Loop with User Query: {command}")
await self.notify_client(f"Executing command: {command}", MessageType.INFO)
Expand All @@ -310,19 +323,29 @@ async def run(self, command, start_url: Optional[str] = None):
self.iteration_counter = 0
while not self.terminate:
try:
# Create a new Lucidic step
lai.create_step()

self.iteration_counter += 1
logfire.debug(f"________Iteration {self.iteration_counter}________")
logfire.info("Running planner agent")
logfire.debug(f"\nMessage history : {message_history}\n")

# Planner Execution
try:
# Create a new Lucidic event to track Planner agent call
lai.create_event(
description=prompt_constructor(PA_prompt),
)
validated_history = ensure_tool_response_sequence(self.message_histories['planner'])
planner_response = await PA_agent.run(
user_prompt=prompt_constructor(PA_prompt),
message_history=validated_history
)
self.conversation_handler.add_planner_message(planner_response)

# Update event with result
lai.end_event(result=planner_response.all_messages_json().decode('utf-8'))

# Update planner's message history
self.message_histories['planner'].extend(planner_response.new_messages())
Expand All @@ -335,6 +358,12 @@ async def run(self, command, start_url: Optional[str] = None):
await self.notify_client(f"Plan Generated: {plan}", MessageType.INFO)
await self.notify_client(f"Current Step: {c_step}", MessageType.INFO)

# Update step with plan and current step
lai.update_step(
state=c_step,
goal=plan
)

try:
if self.iteration_counter == 1: # Only show plan on first iteration
await self.browser_manager.notify_user(
Expand Down Expand Up @@ -414,6 +443,10 @@ async def run(self, command, start_url: Optional[str] = None):
try:
logfire.info("Running browser agent")

# Create new Lucidic event to track Browser agent call
lai.create_event(
description=prompt_constructor(BA_prompt),
)
history = filter_dom_messages(self.message_histories['browser'])
browser_response = await BA_agent.run(
user_prompt=prompt_constructor(BA_prompt),
Expand All @@ -423,6 +456,9 @@ async def run(self, command, start_url: Optional[str] = None):
)
self.conversation_handler.add_browser_nav_message(browser_response)

# Update event with result
lai.end_event(result=browser_response.all_messages_json().decode('utf-8'))

# Extract new messages and get tool interactions
new_messages = browser_response.new_messages()
self.message_histories['browser'].extend(new_messages)
Expand All @@ -433,7 +469,10 @@ async def run(self, command, start_url: Optional[str] = None):
logfire.info(f"All Messages from Browser Agent: {browser_response.all_messages()}")
logfire.info(f"Tool Interactions: {tool_interactions_str}")


# Update step to include action
lai.update_step(
action=tool_interactions_str
)



Expand Down Expand Up @@ -499,7 +538,7 @@ async def run(self, command, start_url: Optional[str] = None):
try:
logfire.info("Running SS analysis")


# This gets captured automatically by the Lucidic OpenAI Handler
ss_analysis_response = ImageAnalyzer(
pre_action_ss,
post_action_ss,
Expand Down Expand Up @@ -535,12 +574,19 @@ async def run(self, command, start_url: Optional[str] = None):
f'browser_error="{browser_error if browser_error else "None"}"'
)

# Create new Lucidic event to track Critique agent call
lai.create_event(
description=prompt_constructor(CA_prompt),
)
critique_response = await CA_agent.run(
user_prompt=prompt_constructor(CA_prompt),
message_history=self.message_histories['critique']
)
self.conversation_handler.add_critique_message(critique_response)

# Update event with result
lai.end_event(result=critique_response.all_messages_json().decode('utf-8'))

# Update critique's message history
self.message_histories['critique'].extend(critique_response.new_messages())

Expand Down Expand Up @@ -613,6 +659,11 @@ async def run(self, command, start_url: Optional[str] = None):
)
# Optionally retry or continue to next iteration
continue

finally:
lai.end_step(
screenshot_path=post_action_ss,
)

except Exception as e:
error_msg = f"Critical Error in orchestrator: {str(e)}"
Expand All @@ -627,6 +678,7 @@ async def run(self, command, start_url: Optional[str] = None):

finally:
logfire.info("Orchestrator Execution Completed")
lai.reset()
await self.cleanup()

async def start(self):
Expand Down
2 changes: 2 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -117,3 +117,5 @@ websockets==13.1
wrapt==1.17.0
yarl==1.18.3
zipp==3.21.0

lucidicai