Spaces:
Paused
Paused
Trisha Tomy
commited on
Commit
·
c73909d
1
Parent(s):
a279659
fixes + cleanup flow
Browse files
README.md
CHANGED
|
@@ -7,73 +7,135 @@ sdk: docker
|
|
| 7 |
pinned: false
|
| 8 |
---
|
| 9 |
|
| 10 |
-
# Proxy-lite Salesforce Automation
|
| 11 |
|
| 12 |
-
|
| 13 |
|
| 14 |
-
##
|
| 15 |
|
| 16 |
-
|
| 17 |
-
|
| 18 |
-
|
| 19 |
-
✅ **Efficient Architecture**: One browser instance for login and task execution
|
| 20 |
|
| 21 |
-
## Quick
|
| 22 |
|
| 23 |
-
###
|
| 24 |
|
| 25 |
-
1. Install dependencies:
|
| 26 |
```bash
|
| 27 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 28 |
```
|
| 29 |
|
| 30 |
-
2
|
| 31 |
-
```bash
|
| 32 |
-
# API Keys (set at least one)
|
| 33 |
-
export GEMINI_API_KEY=your_gemini_api_key
|
| 34 |
-
export HF_API_TOKEN=your_hf_token
|
| 35 |
|
| 36 |
-
|
| 37 |
-
|
| 38 |
-
|
| 39 |
-
|
| 40 |
|
| 41 |
-
3
|
| 42 |
-
|
| 43 |
-
|
| 44 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 45 |
|
| 46 |
-
###
|
| 47 |
|
| 48 |
-
|
| 49 |
|
| 50 |
-
|
| 51 |
-
|
| 52 |
-
|
| 53 |
-
|
| 54 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 55 |
```
|
| 56 |
|
| 57 |
-
##
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 58 |
|
| 59 |
-
|
| 60 |
-
1. Initializes a browser session
|
| 61 |
-
2. Performs Salesforce login using provided credentials
|
| 62 |
-
3. Navigates to the target URL
|
| 63 |
-
4. Executes the requested task
|
| 64 |
-
5. Returns structured results
|
| 65 |
|
| 66 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 67 |
|
| 68 |
-
|
| 69 |
-
- **Convergence AI** (fallback if only `HF_API_TOKEN` is set)
|
| 70 |
|
| 71 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 72 |
|
| 73 |
-
|
| 74 |
-
- More efficient (no separate browser instance)
|
| 75 |
-
- Better session management
|
| 76 |
-
- More reliable navigation
|
| 77 |
-
- Easier to maintain and debug
|
| 78 |
|
| 79 |
-
|
|
|
|
| 7 |
pinned: false
|
| 8 |
---
|
| 9 |
|
| 10 |
+
# Proxy-lite Salesforce Automation
|
| 11 |
|
| 12 |
+
A Salesforce automation system using Proxy-lite that works with any Salesforce org. The backend is already deployed and ready to use - you just need to add the Lightning Web Component to your org.
|
| 13 |
|
| 14 |
+
## ✅ What You Need
|
| 15 |
|
| 16 |
+
- A Salesforce org (any org)
|
| 17 |
+
- Salesforce CLI (sfdx)
|
| 18 |
+
- Your Salesforce username and password
|
|
|
|
| 19 |
|
| 20 |
+
## 🚀 Quick Setup (5 minutes)
|
| 21 |
|
| 22 |
+
### Step 1: Deploy the Lightning Web Component
|
| 23 |
|
|
|
|
| 24 |
```bash
|
| 25 |
+
# Clone this repository
|
| 26 |
+
git clone [your-repo-url]
|
| 27 |
+
cd proxy-litev2\ copy
|
| 28 |
+
|
| 29 |
+
# Deploy to your Salesforce org
|
| 30 |
+
cd proxy-lite-work
|
| 31 |
+
sfdx force:auth:web:login -a yourorg
|
| 32 |
+
sfdx force:source:push -u yourorg
|
| 33 |
```
|
| 34 |
|
| 35 |
+
### Step 2: Add Component to Your Page
|
|
|
|
|
|
|
|
|
|
|
|
|
| 36 |
|
| 37 |
+
1. Go to **Setup** → **Lightning App Builder**
|
| 38 |
+
2. Edit any Lightning page (like Home page)
|
| 39 |
+
3. Add the **"Salesforce Automation with Proxy Lite"** component
|
| 40 |
+
4. Save and activate
|
| 41 |
|
| 42 |
+
### Step 3: Use the Component
|
| 43 |
+
|
| 44 |
+
1. Open the Lightning page where you added the component
|
| 45 |
+
2. Select a target page from the dropdown
|
| 46 |
+
3. Enter your automation task (e.g., "Enable the toggle switch")
|
| 47 |
+
4. Click "Run Automation"
|
| 48 |
+
|
| 49 |
+
**That's it!** The component will connect to the already-deployed backend automatically.
|
| 50 |
+
|
| 51 |
+
## 🔧 How It Works
|
| 52 |
+
|
| 53 |
+
- **Backend**: Already deployed on Hugging Face Spaces (no setup needed)
|
| 54 |
+
- **Frontend**: Lightning Web Component in your Salesforce org
|
| 55 |
+
- **Authentication**: Uses your Salesforce credentials automatically
|
| 56 |
+
- **URLs**: Dynamically adapts to your org's domain
|
| 57 |
+
|
| 58 |
+
## 📋 Supported Automation Tasks
|
| 59 |
+
|
| 60 |
+
The system can automate various Salesforce setup pages:
|
| 61 |
+
- Warranty Lifecycle Management
|
| 62 |
+
- Account Forecasting Settings
|
| 63 |
+
- Sales Agreements
|
| 64 |
+
- Account Manager Targets
|
| 65 |
+
- Custom tasks on any setup page
|
| 66 |
+
|
| 67 |
+
## 🛠️ Advanced Configuration (Optional)
|
| 68 |
|
| 69 |
+
### Custom Endpoint (Enterprise Users)
|
| 70 |
|
| 71 |
+
If you need your own private instance:
|
| 72 |
|
| 73 |
+
1. **Fork this repository**
|
| 74 |
+
2. **Deploy to Hugging Face Spaces**:
|
| 75 |
+
- Create a new Space
|
| 76 |
+
- Connect your forked repo
|
| 77 |
+
- Set environment variables:
|
| 78 |
+
```
|
| 79 |
+
GEMINI_API_KEY=your_key
|
| 80 |
+
SALESFORCE_USERNAME=your_username
|
| 81 |
+
SALESFORCE_PASSWORD=your_password
|
| 82 |
+
```
|
| 83 |
+
|
| 84 |
+
3. **Update Apex Class**:
|
| 85 |
+
- Go to **Setup** → **Apex Classes** → **ProxyLiteService**
|
| 86 |
+
- Update the endpoint URL in `getProxyLiteEndpoint()` method
|
| 87 |
+
|
| 88 |
+
### Environment Variables for Custom Deployment
|
| 89 |
+
|
| 90 |
+
Only needed if deploying your own instance:
|
| 91 |
+
|
| 92 |
+
```env
|
| 93 |
+
# Required: At least one API key
|
| 94 |
+
GEMINI_API_KEY=your_gemini_api_key
|
| 95 |
+
HF_API_TOKEN=your_hf_token
|
| 96 |
+
|
| 97 |
+
# Required: Your Salesforce credentials
|
| 98 | |
| 99 |
+
SALESFORCE_PASSWORD=your_salesforce_password
|
| 100 |
+
|
| 101 |
+
# Optional: Browser settings
|
| 102 |
+
BROWSER_HEADLESS=true
|
| 103 |
+
BROWSER_VIEWPORT_WIDTH=1280
|
| 104 |
+
BROWSER_VIEWPORT_HEIGHT=720
|
| 105 |
```
|
| 106 |
|
| 107 |
+
## 🔍 Troubleshooting
|
| 108 |
+
|
| 109 |
+
### Common Issues
|
| 110 |
+
|
| 111 |
+
1. **Component not showing**: Check if you've pushed the LWC to your org
|
| 112 |
+
2. **"Endpoint not configured" error**: The Apex class needs the correct endpoint URL
|
| 113 |
+
3. **Authentication errors**: Verify your Salesforce credentials work
|
| 114 |
+
4. **Timeout errors**: Large tasks may take time - be patient
|
| 115 |
+
|
| 116 |
+
### Debug Steps
|
| 117 |
+
|
| 118 |
+
1. Check browser console for errors
|
| 119 |
+
2. Verify the LWC is properly deployed
|
| 120 |
+
3. Test with a simple task first
|
| 121 |
+
4. Check Salesforce debug logs
|
| 122 |
|
| 123 |
+
## 💡 Why This Approach?
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 124 |
|
| 125 |
+
- **No Python setup needed** - Backend already deployed
|
| 126 |
+
- **Works with any Salesforce org** - No hardcoded URLs
|
| 127 |
+
- **Free to use** - Powered by Hugging Face Spaces
|
| 128 |
+
- **Secure** - Uses your org's authentication
|
| 129 |
+
- **Simple deployment** - Just add the LWC component
|
| 130 |
|
| 131 |
+
## 🆘 Support
|
|
|
|
| 132 |
|
| 133 |
+
If you encounter issues:
|
| 134 |
+
1. Check the troubleshooting section above
|
| 135 |
+
2. Verify your Salesforce org permissions
|
| 136 |
+
3. Test with a different browser
|
| 137 |
+
4. Check the component is properly added to your page
|
| 138 |
|
| 139 |
+
## 📄 License
|
|
|
|
|
|
|
|
|
|
|
|
|
| 140 |
|
| 141 |
+
This project is licensed under the MIT License.
|
app.py
CHANGED
|
@@ -28,6 +28,44 @@ app = Flask(__name__)
|
|
| 28 |
|
| 29 |
_runner: Runner | None = None
|
| 30 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 31 |
async def initialize_runner_with_single_browser_login(username: str, password: str, target_url: str):
|
| 32 |
"""Initialize Proxy-lite Runner with single-browser login approach."""
|
| 33 |
global _runner
|
|
@@ -147,46 +185,12 @@ async def run_proxy_task_endpoint():
|
|
| 147 |
return jsonify({"error": "Salesforce credentials not configured. Please set SALESFORCE_USERNAME and SALESFORCE_PASSWORD as Space secrets."}), 500
|
| 148 |
|
| 149 |
runner = await initialize_runner_with_single_browser_login(salesforce_username, salesforce_password, target_url)
|
| 150 |
-
logger.info("Proxy-lite Runner initialized with
|
| 151 |
|
| 152 |
logger.info("Agent will use mandatory new tab tool to bypass loading issues.")
|
| 153 |
|
| 154 |
-
#
|
| 155 |
-
agent_task =
|
| 156 |
-
CRITICAL FIRST STEP - MANDATORY:
|
| 157 |
-
Your VERY FIRST action must be to use the open_new_tab_and_go_to tool to navigate to {target_url}
|
| 158 |
-
|
| 159 |
-
DO NOT skip this step. DO NOT use goto. You MUST use: open_new_tab_and_go_to(url='{target_url}')
|
| 160 |
-
|
| 161 |
-
This is necessary because direct navigation to this URL gets stuck loading. The new tab approach bypasses this issue.
|
| 162 |
-
|
| 163 |
-
STEP 1: Use open_new_tab_and_go_to(url='{target_url}')
|
| 164 |
-
STEP 2: Wait for the page to be fully loaded (no loading spinners visible)
|
| 165 |
-
STEP 3: {request_task_instruction}
|
| 166 |
-
|
| 167 |
-
CRITICAL WORKFLOW - FOLLOW THESE EXACT STEPS IN SEQUENCE:
|
| 168 |
-
|
| 169 |
-
STEP A: Select Permission Set
|
| 170 |
-
- Use select_option_by_text tool to find and select the target permission set from Available list
|
| 171 |
-
- Wait for "[ACTION COMPLETED]" response before proceeding
|
| 172 |
-
|
| 173 |
-
STEP B: Click Add Button
|
| 174 |
-
- After successful selection, immediately click the "Add" button to move permission set to Enabled list
|
| 175 |
-
- Do NOT repeat the selection - proceed directly to Add button
|
| 176 |
-
|
| 177 |
-
STEP C: Click Save Button
|
| 178 |
-
- After clicking Add, immediately click "Save" to persist the changes
|
| 179 |
-
- After Save, Salesforce redirects to User page indicating SUCCESS
|
| 180 |
-
|
| 181 |
-
CRITICAL: Do NOT repeat actions. Each step should happen exactly once in sequence.
|
| 182 |
-
|
| 183 |
-
GENERAL INSTRUCTIONS:
|
| 184 |
-
- You must EXECUTE all actions immediately - do NOT just describe what you plan to do
|
| 185 |
-
- Do NOT wait for user input or ask "what should I do next?"
|
| 186 |
-
- Complete the entire task autonomously using the available tools
|
| 187 |
-
- After completing all steps, use the return_value tool to provide your final response
|
| 188 |
-
- If you make a plan, IMMEDIATELY execute it step by step using the appropriate tools
|
| 189 |
-
"""
|
| 190 |
|
| 191 |
logger.info("Executing agent task with mandatory new tab navigation...")
|
| 192 |
result = await runner.run(task=agent_task)
|
|
@@ -202,16 +206,15 @@ GENERAL INSTRUCTIONS:
|
|
| 202 |
"message": "Task completed successfully",
|
| 203 |
"data": {
|
| 204 |
"task_result": task_result,
|
| 205 |
-
|
| 206 |
-
|
| 207 |
-
|
| 208 |
-
|
| 209 |
-
|
| 210 |
-
|
| 211 |
-
|
| 212 |
"environment": {
|
| 213 |
"target_url": target_url,
|
| 214 |
-
"cookies_count": 0, # No explicit cookie count for single-browser login
|
| 215 |
"navigation_method": "new_tab_bypass"
|
| 216 |
}
|
| 217 |
},
|
|
@@ -228,42 +231,8 @@ GENERAL INSTRUCTIONS:
|
|
| 228 |
|
| 229 |
logger.info("Agent will use mandatory new tab tool to bypass loading issues.")
|
| 230 |
|
| 231 |
-
#
|
| 232 |
-
agent_task =
|
| 233 |
-
CRITICAL FIRST STEP - MANDATORY:
|
| 234 |
-
Your VERY FIRST action must be to use the open_new_tab_and_go_to tool to navigate to {target_url}
|
| 235 |
-
|
| 236 |
-
DO NOT skip this step. DO NOT use goto. You MUST use: open_new_tab_and_go_to(url='{target_url}')
|
| 237 |
-
|
| 238 |
-
This is necessary because direct navigation to this URL gets stuck loading. The new tab approach bypasses this issue.
|
| 239 |
-
|
| 240 |
-
STEP 1: Use open_new_tab_and_go_to(url='{target_url}')
|
| 241 |
-
STEP 2: Wait for the page to be fully loaded (no loading spinners visible)
|
| 242 |
-
STEP 3: {request_task_instruction}
|
| 243 |
-
|
| 244 |
-
CRITICAL WORKFLOW - FOLLOW THESE EXACT STEPS IN SEQUENCE:
|
| 245 |
-
|
| 246 |
-
STEP A: Select Permission Set
|
| 247 |
-
- Use select_option_by_text tool to find and select the target permission set from Available list
|
| 248 |
-
- Wait for "[ACTION COMPLETED]" response before proceeding
|
| 249 |
-
|
| 250 |
-
STEP B: Click Add Button
|
| 251 |
-
- After successful selection, immediately click the "Add" button to move permission set to Enabled list
|
| 252 |
-
- Do NOT repeat the selection - proceed directly to Add button
|
| 253 |
-
|
| 254 |
-
STEP C: Click Save Button
|
| 255 |
-
- After clicking Add, immediately click "Save" to persist the changes
|
| 256 |
-
- After Save, Salesforce redirects to User page indicating SUCCESS
|
| 257 |
-
|
| 258 |
-
CRITICAL: Do NOT repeat actions. Each step should happen exactly once in sequence.
|
| 259 |
-
|
| 260 |
-
GENERAL INSTRUCTIONS:
|
| 261 |
-
- You must EXECUTE all actions immediately - do NOT just describe what you plan to do
|
| 262 |
-
- Do NOT wait for user input or ask "what should I do next?"
|
| 263 |
-
- Complete the entire task autonomously using the available tools
|
| 264 |
-
- After completing all steps, use the return_value tool to provide your final response
|
| 265 |
-
- If you make a plan, IMMEDIATELY execute it step by step using the appropriate tools
|
| 266 |
-
"""
|
| 267 |
|
| 268 |
logger.info("Executing agent task with mandatory new tab navigation...")
|
| 269 |
result = await runner.run(task=agent_task)
|
|
@@ -280,14 +249,13 @@ GENERAL INSTRUCTIONS:
|
|
| 280 |
"data": {
|
| 281 |
"task_result": task_result,
|
| 282 |
"steps_completed": [
|
| 283 |
-
"Browser session initialized
|
| 284 |
"New tab navigation executed",
|
| 285 |
-
"Target
|
| 286 |
"Task execution completed successfully"
|
| 287 |
],
|
| 288 |
"environment": {
|
| 289 |
"target_url": target_url,
|
| 290 |
-
"cookies_count": 0, # No explicit cookie count for single-browser login
|
| 291 |
"navigation_method": "new_tab_bypass"
|
| 292 |
}
|
| 293 |
},
|
|
|
|
| 28 |
|
| 29 |
_runner: Runner | None = None
|
| 30 |
|
| 31 |
+
def create_agent_task(target_url: str, request_task_instruction: str) -> str:
|
| 32 |
+
"""Create the agent task with mandatory new tab navigation."""
|
| 33 |
+
return f"""
|
| 34 |
+
CRITICAL FIRST STEP - MANDATORY:
|
| 35 |
+
Your VERY FIRST action must be to use the open_new_tab_and_go_to tool to navigate to {target_url}
|
| 36 |
+
|
| 37 |
+
DO NOT skip this step. DO NOT use goto. You MUST use: open_new_tab_and_go_to(url='{target_url}')
|
| 38 |
+
|
| 39 |
+
This is necessary because direct navigation to this URL gets stuck loading. The new tab approach bypasses this issue.
|
| 40 |
+
|
| 41 |
+
STEP 1: Use open_new_tab_and_go_to(url='{target_url}')
|
| 42 |
+
STEP 2: Wait for the page to be fully loaded (no loading spinners visible)
|
| 43 |
+
STEP 3: {request_task_instruction}
|
| 44 |
+
|
| 45 |
+
CRITICAL WORKFLOW - FOLLOW THESE EXACT STEPS IN SEQUENCE:
|
| 46 |
+
|
| 47 |
+
STEP A: Select Permission Set
|
| 48 |
+
- Use select_option_by_text tool to find and select the target permission set from Available list
|
| 49 |
+
- Wait for "[ACTION COMPLETED]" response before proceeding
|
| 50 |
+
|
| 51 |
+
STEP B: Click Add Button
|
| 52 |
+
- After successful selection, immediately click the "Add" button to move permission set to Enabled list
|
| 53 |
+
- Do NOT repeat the selection - proceed directly to Add button
|
| 54 |
+
|
| 55 |
+
STEP C: Click Save Button
|
| 56 |
+
- After clicking Add, immediately click "Save" to persist the changes
|
| 57 |
+
- After Save, Salesforce redirects to User page indicating SUCCESS
|
| 58 |
+
|
| 59 |
+
CRITICAL: Do NOT repeat actions. Each step should happen exactly once in sequence.
|
| 60 |
+
|
| 61 |
+
GENERAL INSTRUCTIONS:
|
| 62 |
+
- You must EXECUTE all actions immediately - do NOT just describe what you plan to do
|
| 63 |
+
- Do NOT wait for user input or ask "what should I do next?"
|
| 64 |
+
- Complete the entire task autonomously using the available tools
|
| 65 |
+
- After completing all steps, use the return_value tool to provide your final response
|
| 66 |
+
- If you make a plan, IMMEDIATELY execute it step by step using the appropriate tools
|
| 67 |
+
"""
|
| 68 |
+
|
| 69 |
async def initialize_runner_with_single_browser_login(username: str, password: str, target_url: str):
|
| 70 |
"""Initialize Proxy-lite Runner with single-browser login approach."""
|
| 71 |
global _runner
|
|
|
|
| 185 |
return jsonify({"error": "Salesforce credentials not configured. Please set SALESFORCE_USERNAME and SALESFORCE_PASSWORD as Space secrets."}), 500
|
| 186 |
|
| 187 |
runner = await initialize_runner_with_single_browser_login(salesforce_username, salesforce_password, target_url)
|
| 188 |
+
logger.info("Proxy-lite Runner initialized with Salesforce login." if salesforce_username and salesforce_password else "Proxy-lite Runner initialized for general web browsing.")
|
| 189 |
|
| 190 |
logger.info("Agent will use mandatory new tab tool to bypass loading issues.")
|
| 191 |
|
| 192 |
+
# Create the agent task using the centralized function
|
| 193 |
+
agent_task = create_agent_task(target_url, request_task_instruction)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 194 |
|
| 195 |
logger.info("Executing agent task with mandatory new tab navigation...")
|
| 196 |
result = await runner.run(task=agent_task)
|
|
|
|
| 206 |
"message": "Task completed successfully",
|
| 207 |
"data": {
|
| 208 |
"task_result": task_result,
|
| 209 |
+
"steps_completed": [
|
| 210 |
+
"Salesforce login completed",
|
| 211 |
+
"Browser session initialized",
|
| 212 |
+
"New tab navigation executed",
|
| 213 |
+
"Target Salesforce setup page accessed",
|
| 214 |
+
"Task execution completed successfully"
|
| 215 |
+
],
|
| 216 |
"environment": {
|
| 217 |
"target_url": target_url,
|
|
|
|
| 218 |
"navigation_method": "new_tab_bypass"
|
| 219 |
}
|
| 220 |
},
|
|
|
|
| 231 |
|
| 232 |
logger.info("Agent will use mandatory new tab tool to bypass loading issues.")
|
| 233 |
|
| 234 |
+
# Create the agent task using the centralized function
|
| 235 |
+
agent_task = create_agent_task(target_url, request_task_instruction)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 236 |
|
| 237 |
logger.info("Executing agent task with mandatory new tab navigation...")
|
| 238 |
result = await runner.run(task=agent_task)
|
|
|
|
| 249 |
"data": {
|
| 250 |
"task_result": task_result,
|
| 251 |
"steps_completed": [
|
| 252 |
+
"Browser session initialized",
|
| 253 |
"New tab navigation executed",
|
| 254 |
+
"Target page accessed",
|
| 255 |
"Task execution completed successfully"
|
| 256 |
],
|
| 257 |
"environment": {
|
| 258 |
"target_url": target_url,
|
|
|
|
| 259 |
"navigation_method": "new_tab_bypass"
|
| 260 |
}
|
| 261 |
},
|
proxy-lite-demo-v2/src/proxy_lite/environments/webbrowser.py
CHANGED
|
@@ -30,8 +30,6 @@ class WebBrowserEnvironmentConfig(BaseEnvironmentConfig):
|
|
| 30 |
keep_original_image: bool = False
|
| 31 |
no_pois_in_image: bool = False
|
| 32 |
# --- MODIFICATION START ---
|
| 33 |
-
# Added to accept initial cookies from the RunnerConfig
|
| 34 |
-
initial_cookies: Optional[List[dict]] = None
|
| 35 |
# Added for automatic login functionality
|
| 36 |
perform_login: bool = False
|
| 37 |
salesforce_login_url: Optional[str] = None
|
|
@@ -61,14 +59,6 @@ class WebBrowserEnvironment(BaseEnvironment):
|
|
| 61 |
)
|
| 62 |
await self.browser.__aenter__()
|
| 63 |
# Initialize other resources if necessary
|
| 64 |
-
# --- MODIFICATION START ---
|
| 65 |
-
# Changed to use self.config.initial_cookies
|
| 66 |
-
if config.initial_cookies: # type: ignore
|
| 67 |
-
if self.logger:
|
| 68 |
-
self.logger.info(f"🌐 [bold blue]Adding {len(config.initial_cookies)} initial cookies to browser context.[/]") # type: ignore
|
| 69 |
-
if self.browser.context:
|
| 70 |
-
await self.browser.context.add_cookies(config.initial_cookies) # type: ignore
|
| 71 |
-
# --- MODIFICATION END ---
|
| 72 |
if self.logger:
|
| 73 |
self.logger.info("🌐 [bold blue]Browser session started.[/]")
|
| 74 |
return self
|
|
@@ -92,14 +82,9 @@ class WebBrowserEnvironment(BaseEnvironment):
|
|
| 92 |
def browser_session(self) -> type[BrowserSession]:
|
| 93 |
return BrowserSession
|
| 94 |
|
| 95 |
-
# --- MODIFICATION START ---
|
| 96 |
-
# Modified this property to return cookies from the config.
|
| 97 |
-
# It was previously hardcoded to return an empty list.
|
| 98 |
@property
|
| 99 |
def cookies(self) -> list[dict]:
|
| 100 |
-
|
| 101 |
-
return config.initial_cookies if config.initial_cookies is not None else [] # type: ignore
|
| 102 |
-
# --- MODIFICATION END ---
|
| 103 |
|
| 104 |
async def initialise(self) -> Observation:
|
| 105 |
if self.browser is None:
|
|
@@ -160,16 +145,7 @@ class WebBrowserEnvironment(BaseEnvironment):
|
|
| 160 |
|
| 161 |
if self.logger:
|
| 162 |
self.logger.info(f"🔑 Login completed successfully. Current URL: {self.browser.current_url}")
|
| 163 |
-
|
| 164 |
-
# Navigate to target URL if specified
|
| 165 |
-
if config.target_url: # type: ignore
|
| 166 |
-
if self.logger:
|
| 167 |
-
self.logger.debug(f"🔑 Navigating to target URL: {config.target_url}") # type: ignore
|
| 168 |
-
await self.browser.goto(config.target_url) # type: ignore
|
| 169 |
-
if self.browser.current_page:
|
| 170 |
-
await self.browser.current_page.wait_for_load_state('networkidle', timeout=30000)
|
| 171 |
-
if self.logger:
|
| 172 |
-
self.logger.info(f"🔑 Successfully navigated to target URL: {self.browser.current_url}")
|
| 173 |
|
| 174 |
except Exception as e:
|
| 175 |
if self.logger:
|
|
|
|
| 30 |
keep_original_image: bool = False
|
| 31 |
no_pois_in_image: bool = False
|
| 32 |
# --- MODIFICATION START ---
|
|
|
|
|
|
|
| 33 |
# Added for automatic login functionality
|
| 34 |
perform_login: bool = False
|
| 35 |
salesforce_login_url: Optional[str] = None
|
|
|
|
| 59 |
)
|
| 60 |
await self.browser.__aenter__()
|
| 61 |
# Initialize other resources if necessary
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 62 |
if self.logger:
|
| 63 |
self.logger.info("🌐 [bold blue]Browser session started.[/]")
|
| 64 |
return self
|
|
|
|
| 82 |
def browser_session(self) -> type[BrowserSession]:
|
| 83 |
return BrowserSession
|
| 84 |
|
|
|
|
|
|
|
|
|
|
| 85 |
@property
|
| 86 |
def cookies(self) -> list[dict]:
|
| 87 |
+
return []
|
|
|
|
|
|
|
| 88 |
|
| 89 |
async def initialise(self) -> Observation:
|
| 90 |
if self.browser is None:
|
|
|
|
| 145 |
|
| 146 |
if self.logger:
|
| 147 |
self.logger.info(f"🔑 Login completed successfully. Current URL: {self.browser.current_url}")
|
| 148 |
+
self.logger.info("🔑 Login process complete - agent will handle navigation using open_new_tab_and_go_to")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 149 |
|
| 150 |
except Exception as e:
|
| 151 |
if self.logger:
|
proxy-lite-demo-v2/src/proxy_lite/runner.py
CHANGED
|
@@ -122,6 +122,10 @@ class Runner(BaseModel):
|
|
| 122 |
self.solver(config=self.config.solver, logger=self.logger) as solver,
|
| 123 |
):
|
| 124 |
run.env_info = await environment.get_info()
|
|
|
|
|
|
|
|
|
|
|
|
|
| 125 |
await solver.initialise(
|
| 126 |
task,
|
| 127 |
environment.tools,
|
|
@@ -129,9 +133,7 @@ class Runner(BaseModel):
|
|
| 129 |
)
|
| 130 |
self.logger.debug("Solver initialised.")
|
| 131 |
run.solver_history = solver.history # type: ignore
|
| 132 |
-
initial_observation: Observation = await environment.initialise()
|
| 133 |
await event_queue.put(initial_observation)
|
| 134 |
-
self.logger.debug("Environment initialised.")
|
| 135 |
step_count = 0
|
| 136 |
while step_count < self.config.max_steps:
|
| 137 |
event = await event_queue.get()
|
|
|
|
| 122 |
self.solver(config=self.config.solver, logger=self.logger) as solver,
|
| 123 |
):
|
| 124 |
run.env_info = await environment.get_info()
|
| 125 |
+
# Initialize environment first (includes login) before solver gets control
|
| 126 |
+
initial_observation: Observation = await environment.initialise()
|
| 127 |
+
self.logger.debug("Environment initialised.")
|
| 128 |
+
# Only after successful environment initialization (login) should solver get initialized
|
| 129 |
await solver.initialise(
|
| 130 |
task,
|
| 131 |
environment.tools,
|
|
|
|
| 133 |
)
|
| 134 |
self.logger.debug("Solver initialised.")
|
| 135 |
run.solver_history = solver.history # type: ignore
|
|
|
|
| 136 |
await event_queue.put(initial_observation)
|
|
|
|
| 137 |
step_count = 0
|
| 138 |
while step_count < self.config.max_steps:
|
| 139 |
event = await event_queue.get()
|
proxy-lite-work/force-app/main/default/lwc/lwcProxyLiteAutomation/lwcProxyLiteAutomation.js
CHANGED
|
@@ -36,13 +36,22 @@ export default class LwcProxyLiteAutomation extends LightningElement {
|
|
| 36 |
}
|
| 37 |
];
|
| 38 |
|
| 39 |
-
// URL
|
| 40 |
-
|
| 41 |
-
'
|
| 42 |
-
|
| 43 |
-
|
| 44 |
-
|
| 45 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 46 |
|
| 47 |
// Handles changes in the page selection dropdown
|
| 48 |
handlePageChange(event) {
|
|
@@ -56,7 +65,7 @@ export default class LwcProxyLiteAutomation extends LightningElement {
|
|
| 56 |
}
|
| 57 |
|
| 58 |
// Handles the click event on the "Run Automation" button
|
| 59 |
-
|
| 60 |
// Basic input validation
|
| 61 |
if (!this.selectedPage) {
|
| 62 |
this.showToast('Error', 'Please select a target page.', 'error');
|
|
@@ -71,16 +80,15 @@ export default class LwcProxyLiteAutomation extends LightningElement {
|
|
| 71 |
this.isProcessing = true; // Show spinner, disable button
|
| 72 |
this.clearResults(); // Clear previous results
|
| 73 |
|
| 74 |
-
|
| 75 |
-
|
| 76 |
-
|
| 77 |
-
|
| 78 |
-
|
| 79 |
-
|
| 80 |
-
|
| 81 |
-
|
| 82 |
-
|
| 83 |
-
|
| 84 |
// Parse the result if it's a JSON string
|
| 85 |
let parsedResult;
|
| 86 |
if (typeof result === 'string') {
|
|
@@ -114,8 +122,8 @@ export default class LwcProxyLiteAutomation extends LightningElement {
|
|
| 114 |
|
| 115 |
this.showToast('Error', 'Automation task failed.', 'error');
|
| 116 |
}
|
| 117 |
-
|
| 118 |
-
|
| 119 |
// Handle errors from the Apex callout
|
| 120 |
console.error('Proxy Lite Automation Error:', error);
|
| 121 |
|
|
@@ -149,9 +157,10 @@ export default class LwcProxyLiteAutomation extends LightningElement {
|
|
| 149 |
}
|
| 150 |
|
| 151 |
this.showToast('Error', 'Failed to run automation task.', 'error');
|
| 152 |
-
}
|
|
|
|
| 153 |
this.isProcessing = false; // Hide spinner, enable button
|
| 154 |
-
}
|
| 155 |
}
|
| 156 |
|
| 157 |
// Helper method to clear results
|
|
|
|
| 36 |
}
|
| 37 |
];
|
| 38 |
|
| 39 |
+
// Dynamic URL generation based on current org
|
| 40 |
+
get currentOrgDomain() {
|
| 41 |
+
// Get the current org's domain dynamically
|
| 42 |
+
return window.location.origin;
|
| 43 |
+
}
|
| 44 |
+
|
| 45 |
+
// Dynamic URL mapping for different pages
|
| 46 |
+
get pageUrls() {
|
| 47 |
+
const baseUrl = this.currentOrgDomain;
|
| 48 |
+
return {
|
| 49 |
+
'warranty_lifecycle': `${baseUrl}/lightning/setup/MfgServiceSettings/home`,
|
| 50 |
+
'account_forecasting': `${baseUrl}/lightning/setup/AccountForecastSettings/home`,
|
| 51 |
+
'sales_agreements': `${baseUrl}/lightning/setup/SalesAgreementSettings/home`,
|
| 52 |
+
'account_manager_targets': `${baseUrl}/lightning/setup/AcctMgrTargetSettings/home`
|
| 53 |
+
};
|
| 54 |
+
}
|
| 55 |
|
| 56 |
// Handles changes in the page selection dropdown
|
| 57 |
handlePageChange(event) {
|
|
|
|
| 65 |
}
|
| 66 |
|
| 67 |
// Handles the click event on the "Run Automation" button
|
| 68 |
+
handleRunAutomation() {
|
| 69 |
// Basic input validation
|
| 70 |
if (!this.selectedPage) {
|
| 71 |
this.showToast('Error', 'Please select a target page.', 'error');
|
|
|
|
| 80 |
this.isProcessing = true; // Show spinner, disable button
|
| 81 |
this.clearResults(); // Clear previous results
|
| 82 |
|
| 83 |
+
// Get the URL for the selected page
|
| 84 |
+
const targetUrl = this.pageUrls[this.selectedPage];
|
| 85 |
+
|
| 86 |
+
// Call the Apex method with both task and URL using .then() instead of async/await
|
| 87 |
+
runProxyLiteTask({
|
| 88 |
+
userTask: this.taskInput,
|
| 89 |
+
targetUrl: targetUrl
|
| 90 |
+
})
|
| 91 |
+
.then(result => {
|
|
|
|
| 92 |
// Parse the result if it's a JSON string
|
| 93 |
let parsedResult;
|
| 94 |
if (typeof result === 'string') {
|
|
|
|
| 122 |
|
| 123 |
this.showToast('Error', 'Automation task failed.', 'error');
|
| 124 |
}
|
| 125 |
+
})
|
| 126 |
+
.catch(error => {
|
| 127 |
// Handle errors from the Apex callout
|
| 128 |
console.error('Proxy Lite Automation Error:', error);
|
| 129 |
|
|
|
|
| 157 |
}
|
| 158 |
|
| 159 |
this.showToast('Error', 'Failed to run automation task.', 'error');
|
| 160 |
+
})
|
| 161 |
+
.finally(() => {
|
| 162 |
this.isProcessing = false; // Hide spinner, enable button
|
| 163 |
+
});
|
| 164 |
}
|
| 165 |
|
| 166 |
// Helper method to clear results
|