Skip to content

Commit 65c6cdf

Browse files
committed
refactor
1 parent 416bebf commit 65c6cdf

36 files changed

+4726
-13
lines changed

litewebagent/agents/FunctionCallingAgents/ContextAwarePlanningAgent.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@
77
from openai import OpenAI
88
from dotenv import load_dotenv
99
import os
10-
from webagent_utils_sync.utils.utils import encode_image
10+
from ...webagent_utils_sync.utils.utils import encode_image
1111
import time
12-
from webagent_utils_sync.browser_env.observation import (
12+
from ...webagent_utils_sync.browser_env.observation import (
1313
_pre_extract,
1414
extract_dom_snapshot,
1515
extract_merged_axtree,

litewebagent/agents/PromptAgents/PromptAgent.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
from typing import Dict
22
from openai import OpenAI
3-
from webagent_utils_sync.action.highlevel import HighLevelActionSet
4-
from webagent_utils_sync.action.utils import execute_action
5-
from webagent_utils_sync.action.prompt_functions import extract_top_actions, is_goal_finished
6-
from webagent_utils_sync.browser_env.observation import extract_page_info
7-
from webagent_utils_sync.evaluation.feedback import capture_post_action_feedback
3+
from ...webagent_utils_sync.action.highlevel import HighLevelActionSet
4+
from ...webagent_utils_sync.action.utils import execute_action
5+
from ...webagent_utils_sync.action.prompt_functions import extract_top_actions, is_goal_finished
6+
from ...webagent_utils_sync.browser_env.observation import extract_page_info
7+
from ...webagent_utils_sync.evaluation.feedback import capture_post_action_feedback
88
import time
99
import logging
1010

litewebagent/api/server.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
from fastapi.middleware.cors import CORSMiddleware
33
from pydantic import BaseModel
44
from typing import Optional
5-
from litewebagent.core.agent_factory import setup_prompting_web_agent
6-
from webagent_utils_sync.utils.playwright_manager import setup_playwright
5+
from ..core.agent_factory import setup_prompting_web_agent
6+
from ..webagent_utils_sync.utils.playwright_manager import setup_playwright
77
import argparse
88

99
app = FastAPI()

litewebagent/core/agent_factory.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@
99
from ..agents.FunctionCallingAgents.HighLevelPlanningAgent import HighLevelPlanningAgent
1010
from ..agents.FunctionCallingAgents.ContextAwarePlanningAgent import ContextAwarePlanningAgent
1111
from ..agents.PromptAgents.PromptAgent import PromptAgent
12-
from webagent_utils_sync.utils.utils import setup_logger
13-
from webagent_utils_sync.utils.playwright_manager import setup_playwright
14-
from webagent_utils_sync.tools.registry import ToolRegistry
12+
from ..webagent_utils_sync.utils.utils import setup_logger
13+
from ..webagent_utils_sync.utils.playwright_manager import setup_playwright
14+
from ..webagent_utils_sync.tools.registry import ToolRegistry
1515

1616
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
1717

litewebagent/webagent_utils_sync/__init__.py

Whitespace-only changes.

litewebagent/webagent_utils_sync/action/__init__.py

Whitespace-only changes.
Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
# copied and modified from https://github.com/ServiceNow/BrowserGym
2+
import playwright.sync_api
3+
from abc import ABC, abstractmethod
4+
import ast
5+
import sys
6+
import os
7+
import importlib.util
8+
import logging
9+
from typing import Any, Callable, Optional, Tuple
10+
from pathlib import Path
11+
import ast
12+
from typing import Any, Callable, Dict, Optional
13+
import os
14+
from datetime import datetime
15+
import sys
16+
from typing import Any, Callable, Optional
17+
import importlib.util
18+
19+
logger = logging.getLogger(__name__)
20+
21+
def validate_python_syntax(code: str) -> Tuple[bool, str]:
22+
"""
23+
Validate Python code syntax using AST parser.
24+
25+
Args:
26+
code: String containing Python code
27+
28+
Returns:
29+
Tuple of (is_valid, error_message)
30+
"""
31+
try:
32+
ast.parse(code)
33+
return True, ""
34+
except SyntaxError as e:
35+
error_msg = f"Syntax error at line {e.lineno}, column {e.offset}: {e.msg}"
36+
return False, error_msg
37+
except Exception as e:
38+
return False, f"Parsing error: {str(e)}"
39+
40+
41+
class AbstractActionSet(ABC):
42+
def __init__(self, strict: bool = False):
43+
self.strict = strict
44+
45+
@abstractmethod
46+
def describe(self, with_long_description: bool = True, with_examples: bool = True) -> str:
47+
"""
48+
Returns a textual description of this action space.
49+
"""
50+
51+
@abstractmethod
52+
def example_action(self, abstract: bool) -> str:
53+
"""
54+
Returns an example action as a string.
55+
"""
56+
57+
@abstractmethod
58+
def to_python_code(self, action) -> str:
59+
"""
60+
Converts the given action to browsergym-compatible python code.
61+
62+
Args:
63+
action: the action to convert.
64+
65+
Returns:
66+
Executable python code that performs the action in a browsergym environment.
67+
"""
68+
69+
70+
def save_code_to_file(code: str, log_folder: str) -> str:
71+
"""Save code to a file and return the file path."""
72+
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S_%f")
73+
code_logs_dir = os.path.join(log_folder, "code_logs")
74+
os.makedirs(code_logs_dir, exist_ok=True)
75+
filename = f"code_{timestamp}.py"
76+
file_path = os.path.join(code_logs_dir, filename)
77+
78+
header = f"""# Generated Code
79+
# Timestamp: {datetime.now().isoformat()}
80+
# File: {filename}
81+
"""
82+
83+
with open(file_path, 'w', encoding='utf-8') as f:
84+
f.write(header + '\n' + code)
85+
86+
logger.info(f"Saved code to: {file_path}")
87+
return file_path
88+
89+
90+
def execute_python_code_safely(
91+
code: str,
92+
page: 'playwright.sync_api.Page',
93+
context: Any,
94+
log_folder: str,
95+
send_message_to_user: Optional[Callable[[str], None]] = None,
96+
report_infeasible_instructions: Optional[Callable[[str], None]] = None
97+
) -> str:
98+
"""Execute Python code from file with provided context."""
99+
100+
# Save the code to a file
101+
file_path = save_code_to_file(code, log_folder)
102+
103+
try:
104+
# Add the code directory to Python path
105+
sys.path.insert(0, os.path.dirname(file_path))
106+
107+
# Import the module using importlib
108+
spec = importlib.util.spec_from_file_location("generated_code", file_path)
109+
if spec is None or spec.loader is None:
110+
raise ImportError(f"Could not load spec for {file_path}")
111+
112+
module = importlib.util.module_from_spec(spec)
113+
114+
# Set the global variables in the module
115+
module.page = page
116+
module.context = context
117+
module.send_message_to_user = send_message_to_user
118+
module.report_infeasible_instructions = report_infeasible_instructions
119+
120+
# Execute the module
121+
spec.loader.exec_module(module)
122+
123+
except Exception as e:
124+
logger.error(f"Error executing code: {e}")
125+
raise
126+
127+
finally:
128+
# Remove the directory from sys.path
129+
if os.path.dirname(file_path) in sys.path:
130+
sys.path.remove(os.path.dirname(file_path))
131+
132+
return file_path

0 commit comments

Comments
 (0)