@sashbot/uibridge
Version:
🤖 AI-friendly live session automation with REAL screenshot backgrounds (no transparency issues!) - control your EXISTING browser with visual debug panel. Perfect for AI agents!
803 lines (672 loc) • 23.2 kB
JavaScript
#!/usr/bin/env node
/**
* UIBridge Help System for AI Agents
*
* This script provides comprehensive help information designed specifically
* for AI agents and automated systems working with UIBridge.
*/
import { fileURLToPath } from 'url';
import { dirname } from 'path';
const colors = {
reset: '\x1b[0m',
bright: '\x1b[1m',
dim: '\x1b[2m',
red: '\x1b[31m',
green: '\x1b[32m',
yellow: '\x1b[33m',
blue: '\x1b[34m',
magenta: '\x1b[35m',
cyan: '\x1b[36m',
white: '\x1b[37m'
};
function colorize(text, color) {
return `${colors[color]}${text}${colors.reset}`;
}
function printHeader(title) {
console.log('\n' + colorize('='.repeat(60), 'cyan'));
console.log(colorize(`🤖 ${title}`, 'bright'));
console.log(colorize('='.repeat(60), 'cyan'));
}
function printSection(title, content) {
console.log('\n' + colorize(`📋 ${title}`, 'yellow'));
console.log(colorize('-'.repeat(40), 'dim'));
console.log(content);
}
function printCodeBlock(title, code) {
console.log('\n' + colorize(`💻 ${title}`, 'green'));
console.log(colorize('-'.repeat(40), 'dim'));
console.log(colorize(code, 'cyan'));
}
function printAIQuickStart() {
printHeader('AI Agent Quick Start Guide');
printSection('Package Installation',
'Install UIBridge in your project:\n' +
'• npm install @sashbot/uibridge\n' +
'• yarn add @sashbot/uibridge\n' +
'• pnpm add @sashbot/uibridge'
);
printSection('Server Setup for AI Agents',
'UIBridge includes a built-in HTTP API server:\n' +
'• Location: node_modules/@sashbot/uibridge/server-example.cjs\n' +
'• Start server: npm run server (after installation)\n' +
'• Default port: 3000 (configurable)\n' +
'• API endpoints: /api/uibridge/execute, /api/uibridge/health'
);
printCodeBlock('Start Server (Command Line)',
`# Option 1: Using npm script
npm run server
# Option 2: Direct execution
node node_modules/@sashbot/uibridge/server-example.cjs
# Option 3: Custom port
PORT=8080 node node_modules/@sashbot/uibridge/server-example.cjs`
);
printCodeBlock('HTTP API Usage',
`# Health check
curl http://localhost:3000/api/uibridge/health
# Execute click command
curl -X POST http://localhost:3000/api/uibridge/execute \\
-H "Content-Type: application/json" \\
-d '{
"command": "click",
"parameters": {"text": "Submit"}
}'
# Take screenshot
curl -X POST http://localhost:3000/api/uibridge/execute \\
-H "Content-Type: application/json" \\
-d '{
"command": "screenshot",
"parameters": {"fullPage": true}
}'`
);
printSection('Essential Commands',
'UIBridge provides three core commands for AI automation:\n' +
'• click - Interact with any clickable element\n' +
'• screenshot - Capture visual state for verification\n' +
'• help - Get command details and guidance'
);
printCodeBlock('Browser Integration Pattern',
`// 1. Check UIBridge availability
if (!window.uibridge?._isInitialized) {
throw new Error('UIBridge not available');
}
// 2. Execute commands with error handling
try {
await uibridge.execute('click', { text: 'Submit' });
await uibridge.execute('screenshot', { fullPage: true });
} catch (error) {
const help = await uibridge.execute('help', 'click');
console.log('Alternative selectors:', help.examples);
}`
);
}
function printSelectorStrategies() {
printHeader('AI Selector Strategies');
printSection('Priority Order (Highest to Lowest Reliability)',
'1. Test ID - { testId: "element-id" } (Most reliable)\n' +
'2. CSS ID - "#element-id" (High reliability)\n' +
'3. CSS Class - ".class-name" (Medium reliability)\n' +
'4. Text Content- { text: "Button Text" } (Medium reliability)\n' +
'5. Aria Label - { ariaLabel: "Label" } (Medium reliability)\n' +
'6. XPath - { xpath: "//button[@id=\'x\']" } (Advanced use)'
);
printCodeBlock('Smart Selector Fallback Pattern',
`async function smartClick(target) {
const selectors = [
{ testId: target },
\`#\${target}\`,
{ text: target },
{ ariaLabel: target },
\`.\${target}\`
];
for (const selector of selectors) {
try {
return await uibridge.execute('click', selector);
} catch (error) {
console.log(\`Failed: \${JSON.stringify(selector)}\`);
}
}
throw new Error(\`Element not found: \${target}\`);
}`
);
}
function printCommandReference() {
printHeader('AI Command Reference');
printSection('Click Command',
'Purpose: Interact with buttons, links, form elements\n' +
'Syntax: execute("click", selector, options?)\n' +
'Returns: { success: boolean, element: {...}, timestamp: string }'
);
printCodeBlock('Click Examples',
`// Basic clicks
await uibridge.execute('click', '#submit-btn');
await uibridge.execute('click', { text: 'Login' });
await uibridge.execute('click', { testId: 'user-menu' });
// With options
await uibridge.execute('click', '#btn', {
force: true, // Click even if covered
button: 'right', // Right-click instead
clickCount: 2 // Double-click
});`
);
printSection('Screenshot Command',
'Purpose: Capture visual state for verification and debugging\n' +
'Syntax: execute("screenshot", options?)\n' +
'Returns: { success: boolean, dataUrl: string, width: number, ... }'
);
printCodeBlock('Screenshot Examples',
`// Full page screenshot
await uibridge.execute('screenshot', { fullPage: true });
// Element screenshot
await uibridge.execute('screenshot', {
selector: '#main-content'
});
// Auto-save screenshot
await uibridge.execute('screenshot', {
saveConfig: {
autoSave: true,
folder: 'ai-screenshots',
prefix: 'verification',
timestamp: true
}
});`
);
printSection('Help Command',
'Purpose: Get detailed command information and AI guidance\n' +
'Syntax: execute("help", commandName?)\n' +
'Returns: Structured object with examples, patterns, and tips'
);
printCodeBlock('Help Examples',
`// General help
const help = await uibridge.execute('help');
console.log(help.aiBestPractices);
// Command-specific help
const clickHelp = await uibridge.execute('help', 'click');
console.log(clickHelp.aiTips);`
);
}
function printWorkflowPatterns() {
printHeader('AI Workflow Patterns');
printCodeBlock('Form Submission Pattern',
`async function submitForm() {
// 1. Take before screenshot
await uibridge.execute('screenshot', {
saveConfig: { prefix: 'before-submit' }
});
// 2. Find and click submit
await uibridge.execute('click', { text: 'Submit' });
// 3. Wait for response
await new Promise(resolve => setTimeout(resolve, 2000));
// 4. Verify with screenshot
await uibridge.execute('screenshot', {
saveConfig: { prefix: 'after-submit' }
});
}`
);
printCodeBlock('Navigation Pattern',
`async function navigateToPage(pageName) {
// 1. Current state
const beforeNav = await uibridge.execute('screenshot');
// 2. Navigate
await uibridge.execute('click', { text: pageName });
// 3. Wait for page load
await new Promise(resolve => setTimeout(resolve, 3000));
// 4. Verify navigation
const afterNav = await uibridge.execute('screenshot');
return { before: beforeNav, after: afterNav };
}`
);
printCodeBlock('Error Recovery Pattern',
`async function robustClick(target, maxRetries = 3) {
for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
return await uibridge.execute('click', target);
} catch (error) {
if (attempt === maxRetries) {
// Final attempt - get help
const help = await uibridge.execute('help', 'click');
console.log('Available options:', help.examples);
throw error;
}
// Wait before retry
await new Promise(resolve => setTimeout(resolve, 1000));
}
}
}`
);
}
function printDebuggingGuide() {
printHeader('AI Debugging Guide');
printSection('Status Checking',
'Always verify UIBridge availability before automation'
);
printCodeBlock('Diagnostic Function',
`async function diagnoseUIBridge() {
// Check environment
if (typeof window === 'undefined') {
throw new Error('Not in browser environment');
}
// Check UIBridge availability
if (!window.uibridge) {
throw new Error('UIBridge not loaded');
}
// Check initialization
if (!window.uibridge._isInitialized) {
throw new Error('UIBridge not initialized');
}
// Test functionality
try {
const help = await window.uibridge.execute('help');
console.log(\`✅ UIBridge working - \${help.commands.length} commands available\`);
return true;
} catch (error) {
console.log('❌ UIBridge test failed:', error.message);
return false;
}
}`
);
printSection('Common Issues & Solutions',
'• Element not found → Try multiple selector strategies\n' +
'• Click failed → Use force: true option\n' +
'• Screenshot empty → Check element visibility\n' +
'• Command unknown → Check available commands with discover()'
);
printCodeBlock('Debug Information',
`// Get current status
const status = uibridge.getStatus();
console.log('UIBridge Status:', status);
// Get command history
const history = uibridge.getHistory(5);
history.forEach((entry, i) => {
console.log(\`\${i + 1}. \${entry.command} - \${entry.status}\`);
});
// Get available commands
const commands = uibridge.discover();
console.log('Available commands:', commands.map(c => c.name));`
);
}
function printBestPractices() {
printHeader('AI Best Practices');
printSection('Essential Guidelines',
'1. Always use await when executing commands\n' +
'2. Wrap commands in try/catch blocks\n' +
'3. Use specific selectors (testId, ID) when possible\n' +
'4. Take screenshots to verify actions\n' +
'5. Check help system when commands fail\n' +
'6. Use multiple selector strategies for reliability\n' +
'7. Wait for dynamic content before interacting'
);
printCodeBlock('Production-Ready AI Pattern',
`class UIBridgeAI {
constructor() {
this.selectorCache = new Map();
this.retryCount = 3;
this.waitTime = 1000;
}
async execute(command, ...args) {
for (let attempt = 1; attempt <= this.retryCount; attempt++) {
try {
const result = await uibridge.execute(command, ...args);
console.log(\`✅ \${command} succeeded (attempt \${attempt})\`);
return result;
} catch (error) {
console.log(\`❌ \${command} failed (attempt \${attempt}): \${error.message}\`);
if (attempt === this.retryCount) {
await this.handleFailure(command, args, error);
throw error;
}
await new Promise(resolve => setTimeout(resolve, this.waitTime));
}
}
}
async handleFailure(command, args, error) {
// Take screenshot for debugging
await uibridge.execute('screenshot', {
saveConfig: { prefix: 'error', timestamp: true }
});
// Log detailed error information
const help = await uibridge.execute('help', command);
console.log('Command help:', help);
console.log('Failed arguments:', args);
}
}`
);
}
function printEnvironmentSetup() {
printHeader('Environment Setup for AI');
printSection('Browser Environment',
'UIBridge works in any modern browser environment'
);
printCodeBlock('Script Tag Method',
`<script src="https://unpkg.com/@sashbot/uibridge/dist/uibridge.min.js"></script>
<script>
// UIBridge automatically initializes as window.uibridge
window.addEventListener('load', async () => {
if (window.uibridge?._isInitialized) {
console.log('✅ UIBridge ready for AI automation');
}
});
</script>`
);
printCodeBlock('NPM Import Method',
`import UIBridge from '@sashbot/uibridge';
const bridge = new UIBridge({
debug: true, // Enable logging for AI debugging
autoInit: false // Manual initialization control
});
await bridge.init();
console.log('✅ UIBridge initialized for AI use');`
);
printSection('SvelteKit/SSR Environment',
'Special handling required for server-side rendering'
);
printCodeBody('SSR-Safe Import',
`import { onMount } from 'svelte';
import { browser } from '$app/environment';
onMount(async () => {
if (!browser) return; // Skip on server
const { default: UIBridge } = await import('@sashbot/uibridge');
const bridge = new UIBridge({ debug: true });
await bridge.init();
// AI automation ready
});`
);
}
function printPowerShellPatterns() {
printHeader('PowerShell REST API for AI Agents');
printSection('Server Setup',
'Start the UIBridge REST API server (dependencies included):\n' +
' node node_modules/@sashbot/uibridge/server-example.cjs\n\n' +
'Server runs on http://localhost:3001 by default'
);
printCodeBlock('Basic PowerShell Click Command',
`# Define parameters using hashtable splatting (PowerShell best practice)
$params = @{
Uri = 'http://localhost:3001/execute-command'
Method = 'POST'
Headers = @{
'Content-Type' = 'application/json'
'Accept' = 'application/json'
}
Body = @{
command = 'click'
selector = '#submit-button'
options = @{
force = $true
}
} | ConvertTo-Json
}
# Execute the request with error handling
try {
$response = Invoke-RestMethod @params
Write-Host "✅ Click successful: $($response.message)"
} catch {
Write-Error "❌ Click failed: $_"
}`
);
printCodeBlock('PowerShell Screenshot with Auto-Save',
`$params = @{
Uri = 'http://localhost:3001/execute-command'
Method = 'POST'
Headers = @{ 'Content-Type' = 'application/json' }
Body = @{
command = 'screenshot'
options = @{
fullPage = $true
saveConfig = @{
autoSave = $true
folder = 'ai-screenshots'
prefix = 'automation'
timestamp = $true
}
}
} | ConvertTo-Json -Depth 4 # Important: Use -Depth for nested objects
}
$response = Invoke-RestMethod @params
Write-Host "📸 Screenshot saved: $($response.command.result.fileName)"`
);
printCodeBlock('Reusable PowerShell Function',
`# Store common configuration globally
$global:UIBridgeConfig = @{
BaseUri = 'http://localhost:3001'
Headers = @{ 'Content-Type' = 'application/json' }
}
function Invoke-UIBridgeCommand {
param(
[string]$Command,
[hashtable]$Parameters = @{},
[hashtable]$Options = @{}
)
$params = @{
Uri = "$($global:UIBridgeConfig.BaseUri)/execute-command"
Method = 'POST'
Headers = $global:UIBridgeConfig.Headers
Body = @{
command = $Command
} | ConvertTo-Json -Depth 4
}
# Add parameters to body
$bodyObj = $params.Body | ConvertFrom-Json
if ($Parameters.Count -gt 0) {
foreach ($key in $Parameters.Keys) {
$bodyObj | Add-Member -NotePropertyName $key -NotePropertyValue $Parameters[$key]
}
}
if ($Options.Count -gt 0) {
$bodyObj | Add-Member -NotePropertyName 'options' -NotePropertyValue $Options
}
$params.Body = $bodyObj | ConvertTo-Json -Depth 4
try {
$response = Invoke-RestMethod @params
return $response
} catch {
Write-Error "UIBridge command '$Command' failed: $_"
throw
}
}
# Usage examples:
# Invoke-UIBridgeCommand -Command 'click' -Parameters @{selector='#btn'}
# Invoke-UIBridgeCommand -Command 'screenshot' -Options @{fullPage=$true}`
);
printCodeBlock('Complete AI Workflow in PowerShell',
`function Start-UIBridgeAutomation {
param([string]$TargetUrl = 'http://localhost:3000')
Write-Host "🤖 Starting UIBridge automation workflow..."
# 1. Check server status
try {
$status = Invoke-RestMethod -Uri 'http://localhost:3001/status'
Write-Host "✅ UIBridge server is running"
} catch {
Write-Error "❌ UIBridge server not available. Run: node server-example.cjs"
return
}
# 2. Take initial screenshot
$screenshot1 = Invoke-UIBridgeCommand -Command 'screenshot' -Options @{
fullPage = $true
saveConfig = @{
prefix = 'initial-state'
timestamp = $true
}
}
Write-Host "📸 Initial screenshot: $($screenshot1.command.result.fileName)"
# 3. Execute click action with multiple selector strategies
$clickTargets = @(
@{ testId = 'submit-btn' },
'#submit-button',
@{ text = 'Submit' },
@{ ariaLabel = 'Submit form' }
)
$clickSuccess = $false
foreach ($target in $clickTargets) {
try {
$clickResult = Invoke-UIBridgeCommand -Command 'click' -Parameters @{
selector = $target
} -Options @{ force = $true }
Write-Host "🖱️ Click successful with selector: $($target | ConvertTo-Json -Compress)"
$clickSuccess = $true
break
} catch {
Write-Host "⚠️ Click failed with selector: $($target | ConvertTo-Json -Compress)"
}
}
if (-not $clickSuccess) {
Write-Error "❌ All click attempts failed"
return
}
# 4. Wait for page response
Start-Sleep -Seconds 2
# 5. Take verification screenshot
$screenshot2 = Invoke-UIBridgeCommand -Command 'screenshot' -Options @{
fullPage = $true
saveConfig = @{
prefix = 'after-click'
timestamp = $true
}
}
Write-Host "📸 Verification screenshot: $($screenshot2.command.result.fileName)"
Write-Host "✅ Automation workflow completed!"
return @{
success = $true
beforeScreenshot = $screenshot1.command.result.fileName
afterScreenshot = $screenshot2.command.result.fileName
}
}
# Run the automation
Start-UIBridgeAutomation`
);
}
function printUsageExamples() {
printHeader('Complete AI Usage Examples');
printCodeBlock('E-commerce Automation',
`async function purchaseProduct(productName) {
try {
// 1. Search for product
await uibridge.execute('click', { placeholder: 'Search products' });
// Note: UIBridge focuses on clicking and screenshots
// For text input, you'd need additional tools
// 2. Click on product
await uibridge.execute('click', { text: productName });
// 3. Add to cart
await uibridge.execute('click', { text: 'Add to Cart' });
// 4. Verify addition with screenshot
const cartScreenshot = await uibridge.execute('screenshot', {
saveConfig: { prefix: 'cart-verification' }
});
// 5. Proceed to checkout
await uibridge.execute('click', { text: 'Checkout' });
return { success: true, screenshot: cartScreenshot };
} catch (error) {
await uibridge.execute('screenshot', {
saveConfig: { prefix: 'purchase-error' }
});
throw new Error(\`Purchase failed: \${error.message}\`);
}
}`
);
printCodeBlock('Form Testing Automation',
`async function testFormValidation() {
const results = [];
// Test required field validation
try {
await uibridge.execute('click', { text: 'Submit' });
// Capture validation errors
const errorScreenshot = await uibridge.execute('screenshot', {
saveConfig: { prefix: 'validation-errors' }
});
results.push({
test: 'Required field validation',
status: 'passed',
screenshot: errorScreenshot
});
} catch (error) {
results.push({
test: 'Required field validation',
status: 'failed',
error: error.message
});
}
return results;
}`
);
}
function main() {
const args = process.argv.slice(2);
const command = args[0];
// Handle --help or -h flags
if (command === '--help' || command === '-h' || command === 'help') {
printAIQuickStart();
printSelectorStrategies();
printCommandReference();
printPowerShellPatterns();
printWorkflowPatterns();
printDebuggingGuide();
printBestPractices();
printEnvironmentSetup();
printUsageExamples();
console.log('\n' + colorize('🎯 For specific help, use:', 'bright'));
console.log(colorize(' node uibridge-help.js quickstart', 'cyan'));
console.log(colorize(' node uibridge-help.js commands', 'cyan'));
console.log(colorize(' node uibridge-help.js powershell', 'cyan'));
console.log(colorize(' node uibridge-help.js patterns', 'cyan'));
console.log(colorize(' node uibridge-help.js debug', 'cyan'));
console.log(colorize(' node uibridge-help.js examples', 'cyan'));
return;
}
if (!command) {
// Full help
printAIQuickStart();
printSelectorStrategies();
printCommandReference();
printPowerShellPatterns();
printWorkflowPatterns();
printDebuggingGuide();
printBestPractices();
printEnvironmentSetup();
printUsageExamples();
console.log('\n' + colorize('🎯 For specific help, use:', 'bright'));
console.log(colorize(' node uibridge-help.js quickstart', 'cyan'));
console.log(colorize(' node uibridge-help.js commands', 'cyan'));
console.log(colorize(' node uibridge-help.js powershell', 'cyan'));
console.log(colorize(' node uibridge-help.js patterns', 'cyan'));
console.log(colorize(' node uibridge-help.js debug', 'cyan'));
console.log(colorize(' node uibridge-help.js examples', 'cyan'));
} else if (command === 'quickstart') {
printAIQuickStart();
printSelectorStrategies();
} else if (command === 'commands') {
printCommandReference();
} else if (command === 'powershell') {
printPowerShellPatterns();
} else if (command === 'patterns') {
printWorkflowPatterns();
} else if (command === 'debug') {
printDebuggingGuide();
} else if (command === 'best-practices') {
printBestPractices();
} else if (command === 'setup') {
printEnvironmentSetup();
} else if (command === 'examples') {
printUsageExamples();
} else {
console.log(colorize('❌ Unknown command:', 'red') + ` ${command}`);
console.log(colorize('Available commands: quickstart, commands, powershell, patterns, debug, best-practices, setup, examples', 'yellow'));
}
}
// ES module compatibility - run if this file is executed directly
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
// Check if this file is being run directly
if (process.argv[1] && fileURLToPath(import.meta.url) === process.argv[1]) {
main();
}
export {
printAIQuickStart,
printSelectorStrategies,
printCommandReference,
printPowerShellPatterns,
printWorkflowPatterns,
printDebuggingGuide,
printBestPractices,
printEnvironmentSetup,
printUsageExamples,
main
};