Skip to content
Merged
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
21 changes: 21 additions & 0 deletions workflows/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,12 +57,32 @@ python cli.py run-workflow-no-ai my_workflow.json
- **Semantic Targeting**: Use `{variable}` in `target_text`
- **Auto-Extraction**: LLM suggests variables automatically

### 📊 Real-time Progress Tracking (NEW!)
- **Step-by-Step Visibility**: See each browser action as it's recorded
- **Status Updates**: Track workflow processing phases in real-time
- **Cloud Integration Ready**: Store progress in database for live UI updates
- **Debug Friendly**: Know exactly where workflow generation fails
- **Zero Overhead**: Optional callbacks, fully backward compatible

```python
# Track workflow generation progress in real-time
workflow = await service.generate_workflow_from_prompt(
prompt="Search for Python docs",
agent_llm=llm,
extraction_llm=llm,
on_step_recorded=lambda s: print(f"Step {s['step_number']}: {s['description']}"),
on_status_update=lambda msg: print(f"Status: {msg}"),
)
```

---

## Documentation

- **[docs/DETERMINISTIC.md](docs/DETERMINISTIC.md)** - Deterministic workflow generation
- **[docs/VARIABLES.md](docs/VARIABLES.md)** - Variables guide
- **[docs/PROGRESS_TRACKING.md](docs/PROGRESS_TRACKING.md)** - Real-time progress tracking ⭐ NEW
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Nov 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new docs/PROGRESS_TRACKING.md link points to a file that doesn’t exist, so following the README link will 404.

Prompt for AI agents
Address the following comment on workflows/README.md at line 84:

<comment>The new docs/PROGRESS_TRACKING.md link points to a file that doesn’t exist, so following the README link will 404.</comment>

<file context>
@@ -57,12 +57,32 @@ python cli.py run-workflow-no-ai my_workflow.json
 
 - **[docs/DETERMINISTIC.md](docs/DETERMINISTIC.md)** - Deterministic workflow generation
 - **[docs/VARIABLES.md](docs/VARIABLES.md)** - Variables guide
+- **[docs/PROGRESS_TRACKING.md](docs/PROGRESS_TRACKING.md)** - Real-time progress tracking ⭐ NEW
+- **[QUICK_START_PROGRESS_TRACKING.md](QUICK_START_PROGRESS_TRACKING.md)** - 5-minute integration guide
 - **[examples/README.md](examples/README.md)** - Example scripts
</file context>
Fix with Cubic

- **[QUICK_START_PROGRESS_TRACKING.md](QUICK_START_PROGRESS_TRACKING.md)** - 5-minute integration guide
- **[examples/README.md](examples/README.md)** - Example scripts

---
Expand Down Expand Up @@ -98,6 +118,7 @@ workflows/
│ │ ├── variables/ # Variable feature examples
│ │ ├── demos/ # Advanced demos
│ │ └── runner.py # Generic workflow runner
│ ├── progress_tracking_example.py # ⭐ NEW: Real-time progress tracking
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Nov 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The structure diagram advertises progress_tracking_example.py, but that file doesn’t exist anywhere in the repo, which misleads readers.

Prompt for AI agents
Address the following comment on workflows/README.md at line 121:

<comment>The structure diagram advertises progress_tracking_example.py, but that file doesn’t exist anywhere in the repo, which misleads readers.</comment>

<file context>
@@ -98,6 +118,7 @@ workflows/
 │   │   ├── variables/       # Variable feature examples
 │   │   ├── demos/           # Advanced demos
 │   │   └── runner.py        # Generic workflow runner
+│   ├── progress_tracking_example.py  # ⭐ NEW: Real-time progress tracking
 │   └── workflows/           # Example workflow JSON files
 │       ├── basic/           # Basic workflow examples
</file context>
Fix with Cubic

│ └── workflows/ # Example workflow JSON files
│ ├── basic/ # Basic workflow examples
│ ├── form_filling/ # Form filling examples
Expand Down
256 changes: 256 additions & 0 deletions workflows/examples/progress_tracking_example.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,256 @@
"""
Example: Real-time Progress Tracking for Workflow Generation

This example demonstrates how to use the new on_step_recorded and on_status_update
callbacks to track workflow generation progress in real-time.

Usage:
python examples/progress_tracking_example.py
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Nov 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new usage instructions reference examples/progress_tracking_example.py, but the script actually lives under workflows/examples/, so the documented command fails when run from the repo root. Update the path to the real file so the example can be executed as written.

Prompt for AI agents
Address the following comment on workflows/examples/progress_tracking_example.py at line 8:

<comment>The new usage instructions reference `examples/progress_tracking_example.py`, but the script actually lives under `workflows/examples/`, so the documented command fails when run from the repo root. Update the path to the real file so the example can be executed as written.</comment>

<file context>
@@ -3,12 +3,15 @@
 callbacks to track workflow generation progress in real-time.
+
+Usage:
+    python examples/progress_tracking_example.py
 &quot;&quot;&quot;
 
</file context>
Suggested change
python examples/progress_tracking_example.py
python workflows/examples/progress_tracking_example.py
Fix with Cubic

"""

import asyncio
from datetime import datetime

from browser_use.llm import ChatBrowserUse

from workflow_use.healing.service import HealingService


# Example 1: Simple console logging
async def simple_console_example():
"""Basic example: Print steps to console as they're recorded."""
print('=' * 80)
print('EXAMPLE 1: Simple Console Logging')
print('=' * 80)

def step_callback(step_data: dict):
"""Called each time a step is recorded."""
print(f'\n📍 Step {step_data["step_number"]}: {step_data["description"]}')
print(f' Type: {step_data["action_type"]}')
print(f' URL: {step_data["url"]}')
if step_data.get('target_text'):
print(f' Target: {step_data["target_text"]}')
if step_data.get('extracted_data'):
print(f' Extracted: {step_data["extracted_data"]}')

def status_callback(status: str):
"""Called for general status updates."""
print(f'\n🔄 {status}')

# Initialize service
llm = ChatBrowserUse(model='bu-latest')
healing_service = HealingService(
llm=llm,
use_deterministic_conversion=True,
enable_variable_extraction=True,
)

# Generate workflow with callbacks
workflow = await healing_service.generate_workflow_from_prompt(
prompt='Go to example.com and extract the page title',
agent_llm=llm,
extraction_llm=llm,
use_cloud=False,
on_step_recorded=step_callback,
on_status_update=status_callback,
)

print(f'\n✅ Generated workflow with {len(workflow.steps)} steps!')


# Example 2: Store steps in a list (for database storage)
async def database_storage_example():
"""Example: Store steps in memory (simulates database storage)."""
print('\n' + '=' * 80)
print('EXAMPLE 2: Database Storage Pattern')
print('=' * 80)

# Simulated database storage
stored_steps = []
status_history = []

async def step_callback(step_data: dict):
"""Store step in database (simulated with list)."""
stored_steps.append(step_data)
print(f'✓ Stored step {step_data["step_number"]} in database')

async def status_callback(status: str):
"""Store status update in database."""
status_history.append({'timestamp': datetime.now().isoformat(), 'status': status})
print(f'ℹ️ {status}')

# Initialize service
llm = ChatBrowserUse(model='bu-latest')
healing_service = HealingService(
llm=llm,
use_deterministic_conversion=True,
enable_variable_extraction=True,
)

# Generate workflow with async callbacks
workflow = await healing_service.generate_workflow_from_prompt(
prompt='Go to example.com and extract the page title',
agent_llm=llm,
extraction_llm=llm,
use_cloud=False,
on_step_recorded=lambda data: asyncio.create_task(step_callback(data)),
on_status_update=lambda status: asyncio.create_task(status_callback(status)),
)

# Display stored data
print(f'\n📊 Stored {len(stored_steps)} steps and {len(status_history)} status updates')
print('\nStored Steps:')
for step in stored_steps:
print(f' {step["step_number"]}. {step["description"]}')

print('\nStatus History:')
for status in status_history:
print(f' [{status["timestamp"]}] {status["status"]}')


# Example 3: Real-time progress bar
async def progress_bar_example():
"""Example: Show progress with a simple progress indicator."""
print('\n' + '=' * 80)
print('EXAMPLE 3: Progress Bar')
print('=' * 80)

step_count = {'count': 0}

def step_callback(step_data: dict):
"""Update progress bar as steps are recorded."""
step_count['count'] = step_data['step_number']
# Simple progress indicator
bar = '█' * step_data['step_number'] + '░' * (10 - step_data['step_number'])
print(f'\rProgress: [{bar}] Step {step_data["step_number"]}: {step_data["description"][:40]}...', end='')

def status_callback(status: str):
"""Display status updates."""
print(f'\n\n🔄 {status}')

# Initialize service
llm = ChatBrowserUse(model='bu-latest')
healing_service = HealingService(
llm=llm,
use_deterministic_conversion=True,
enable_variable_extraction=True,
)

# Generate workflow with callbacks
workflow = await healing_service.generate_workflow_from_prompt(
prompt='Go to example.com and extract the page title',
agent_llm=llm,
extraction_llm=llm,
use_cloud=False,
on_step_recorded=step_callback,
on_status_update=status_callback,
)

print(f'\n\n✅ Completed! Generated workflow with {step_count["count"]} steps')


# Example 4: Real-world pattern for Browser-Use Cloud backend
async def cloud_backend_pattern():
"""
Example: Pattern for Browser-Use Cloud backend integration.

This shows how to integrate with your database to store steps
in real-time for frontend polling.
"""
print('\n' + '=' * 80)
print('EXAMPLE 4: Browser-Use Cloud Backend Pattern')
print('=' * 80)

# Simulated workflow_id (would come from your database)
workflow_id = 'wf_123abc'
generation_metadata = {'steps': [], 'status_history': []}

async def step_callback(step_data: dict):
"""
Store step immediately in database for real-time display.

In your actual implementation, this would be:
async with await database.get_session() as session:
workflow = await get_workflow(session, workflow_id)
if workflow and workflow.generation_metadata:
steps = workflow.generation_metadata.get('steps', [])
steps.append(step_data)
workflow.generation_metadata['steps'] = steps
await session.commit()
"""
# Simulated database storage
generation_metadata['steps'].append(step_data)

print(f'💾 Stored step {step_data["step_number"]} to workflow {workflow_id}')
print(f' Description: {step_data["description"]}')
print(f' Type: {step_data["action_type"]}')
print(f' Timestamp: {step_data["timestamp"]}')

async def status_callback(status: str):
"""Store status updates for display in the frontend."""
status_entry = {'timestamp': datetime.now().isoformat(), 'message': status}
generation_metadata['status_history'].append(status_entry)

print(f'ℹ️ Status update: {status}')

# Initialize service
llm = ChatBrowserUse(model='bu-latest')
healing_service = HealingService(
llm=llm,
use_deterministic_conversion=True,
enable_variable_extraction=True,
)

# Generate workflow with progress tracking
print(f'\n🚀 Starting workflow generation for {workflow_id}...')

workflow = await healing_service.generate_workflow_from_prompt(
prompt='Go to example.com and extract the page title',
agent_llm=llm,
extraction_llm=llm,
use_cloud=False,
on_step_recorded=lambda data: asyncio.create_task(step_callback(data)),
on_status_update=lambda status: asyncio.create_task(status_callback(status)),
)

# Display final metadata (what would be in your database)
print('\n' + '=' * 80)
print('FINAL DATABASE STATE')
print('=' * 80)
print(f'\nWorkflow ID: {workflow_id}')
print(f'Total Steps Recorded: {len(generation_metadata["steps"])}')
print(f'Total Status Updates: {len(generation_metadata["status_history"])}')

print('\n📋 Steps Timeline:')
for step in generation_metadata['steps']:
print(f' [{step["timestamp"]}] Step {step["step_number"]}: {step["description"]}')

print('\n📊 Status Timeline:')
for status in generation_metadata['status_history']:
print(f' [{status["timestamp"]}] {status["message"]}')

print(f'\n✅ Workflow generation complete! Final workflow has {len(workflow.steps)} steps')


# Run all examples
async def main():
"""Run all examples (commented out to avoid actual API calls)."""
print('Progress Tracking Examples')
print('=' * 80)
print('\nThese examples demonstrate different patterns for tracking')
print('workflow generation progress in real-time.')
print('\nNote: Examples are commented out to avoid actual API calls.')
print('Uncomment the examples you want to run.\n')

# Uncomment the examples you want to run:

# await simple_console_example()
# await database_storage_example()
# await progress_bar_example()
# await cloud_backend_pattern()

print('\n✅ Examples completed!')


if __name__ == '__main__':
asyncio.run(main())
2 changes: 1 addition & 1 deletion workflows/pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "workflow-use"
version = "0.2.10"
version = "0.2.11"
authors = [{ name = "Gregor Zunic" }]
description = "Create, edit, run deterministic workflows"
readme = "README.md"
Expand Down
Loading
Loading