|
| 1 | +/** |
| 2 | + * Example: Agent with Cloud Tracing |
| 3 | + * |
| 4 | + * Demonstrates how to use cloud tracing with SentienceAgent to upload traces |
| 5 | + * and screenshots to cloud storage for remote viewing and analysis. |
| 6 | + * |
| 7 | + * Requirements: |
| 8 | + * - Pro or Enterprise tier API key (SENTIENCE_API_KEY) |
| 9 | + * - OpenAI API key (OPENAI_API_KEY) for LLM |
| 10 | + * |
| 11 | + * Usage: |
| 12 | + * ts-node examples/cloud-tracing-agent.ts |
| 13 | + * or |
| 14 | + * npm run example:cloud-tracing |
| 15 | + */ |
| 16 | + |
| 17 | +import { SentienceBrowser } from '../src/browser'; |
| 18 | +import { SentienceAgent } from '../src/agent'; |
| 19 | +import { OpenAIProvider } from '../src/llm-provider'; |
| 20 | +import { createTracer } from '../src/tracing/tracer-factory'; |
| 21 | + |
| 22 | +async function main() { |
| 23 | + // Get API keys from environment |
| 24 | + const sentienceKey = process.env.SENTIENCE_API_KEY; |
| 25 | + const openaiKey = process.env.OPENAI_API_KEY; |
| 26 | + |
| 27 | + if (!sentienceKey) { |
| 28 | + console.error('❌ Error: SENTIENCE_API_KEY not set'); |
| 29 | + console.error(' Cloud tracing requires Pro or Enterprise tier'); |
| 30 | + console.error(' Get your API key at: https://sentience.studio'); |
| 31 | + process.exit(1); |
| 32 | + } |
| 33 | + |
| 34 | + if (!openaiKey) { |
| 35 | + console.error('❌ Error: OPENAI_API_KEY not set'); |
| 36 | + process.exit(1); |
| 37 | + } |
| 38 | + |
| 39 | + console.log('🚀 Starting Agent with Cloud Tracing Demo\n'); |
| 40 | + |
| 41 | + // 1. Create tracer with automatic tier detection |
| 42 | + // If apiKey is Pro/Enterprise, uses CloudTraceSink |
| 43 | + // If apiKey is missing/invalid, falls back to local JsonlTraceSink |
| 44 | + const runId = 'cloud-tracing-demo'; |
| 45 | + const tracer = await createTracer({ |
| 46 | + apiKey: sentienceKey, |
| 47 | + runId: runId |
| 48 | + }); |
| 49 | + |
| 50 | + console.log(`🆔 Run ID: ${runId}\n`); |
| 51 | + |
| 52 | + // 2. Create browser and LLM |
| 53 | + console.log('🌐 Starting browser...'); |
| 54 | + const browser = new SentienceBrowser(sentienceKey, undefined, false); |
| 55 | + |
| 56 | + try { |
| 57 | + await browser.start(); |
| 58 | + console.log('✅ Browser started successfully'); |
| 59 | + } catch (error: any) { |
| 60 | + console.error(`❌ Failed to start browser: ${error.message}`); |
| 61 | + throw error; |
| 62 | + } |
| 63 | + |
| 64 | + const llm = new OpenAIProvider(openaiKey, 'gpt-4o-mini'); |
| 65 | + |
| 66 | + // 3. Create agent with tracer |
| 67 | + // Note: Screenshot capture is handled automatically by the tracer |
| 68 | + // The agent will capture screenshots for each step when tracer is provided |
| 69 | + const agent = new SentienceAgent(browser, llm, 50, true, tracer); |
| 70 | + |
| 71 | + try { |
| 72 | + // 5. Navigate and execute agent actions |
| 73 | + console.log('🌐 Navigating to Google...\n'); |
| 74 | + const page = browser.getPage(); |
| 75 | + console.log(' Getting page...'); |
| 76 | + |
| 77 | + try { |
| 78 | + console.log(' Navigating to Google...'); |
| 79 | + await page.goto('https://www.google.com', { waitUntil: 'domcontentloaded', timeout: 30000 }); |
| 80 | + console.log(' Page loaded!'); |
| 81 | + |
| 82 | + // Wait a bit for page to stabilize (instead of networkidle which can hang) |
| 83 | + console.log(' Waiting for page to stabilize...'); |
| 84 | + await new Promise(resolve => setTimeout(resolve, 2000)); |
| 85 | + |
| 86 | + // Wait for extension to inject (required for snapshot) |
| 87 | + console.log(' Waiting for Sentience extension to inject...'); |
| 88 | + try { |
| 89 | + await page.waitForFunction( |
| 90 | + () => typeof (window as any).sentience !== 'undefined', |
| 91 | + { timeout: 10000 } |
| 92 | + ); |
| 93 | + console.log(' ✅ Extension ready!\n'); |
| 94 | + } catch (error: any) { |
| 95 | + console.error(` ⚠️ Extension not ready after 10s: ${error.message}`); |
| 96 | + console.error(' Continuing anyway - snapshot may fail if extension not loaded'); |
| 97 | + } |
| 98 | + } catch (error: any) { |
| 99 | + console.error(` ❌ Navigation/extension error: ${error.message}`); |
| 100 | + throw error; |
| 101 | + } |
| 102 | + |
| 103 | + // All actions are automatically traced! |
| 104 | + console.log('📝 Executing agent actions (all automatically traced)...\n'); |
| 105 | + console.log(' Action 1: Click the search box...'); |
| 106 | + await agent.act('Click the search box'); |
| 107 | + console.log(' ✅ Action 1 complete'); |
| 108 | + console.log(' Action 2: Type into search field...'); |
| 109 | + await agent.act("Type 'Sentience AI agent SDK' into the search field"); |
| 110 | + console.log(' ✅ Action 2 complete'); |
| 111 | + |
| 112 | + console.log(' Action 3: Press Enter...'); |
| 113 | + await agent.act('Press Enter key'); |
| 114 | + console.log(' ✅ Action 3 complete'); |
| 115 | + |
| 116 | + // Wait for results |
| 117 | + console.log(' Waiting for search results...'); |
| 118 | + await new Promise(resolve => setTimeout(resolve, 2000)); |
| 119 | + |
| 120 | + console.log(' Action 4: Click first result...'); |
| 121 | + await agent.act('Click the first non-ad search result'); |
| 122 | + console.log(' ✅ Action 4 complete'); |
| 123 | + |
| 124 | + console.log('\n✅ Agent execution complete!'); |
| 125 | + |
| 126 | + // 6. Get token usage stats |
| 127 | + const stats = agent.getTokenStats(); |
| 128 | + console.log('\n📊 Token Usage:'); |
| 129 | + console.log(` Total tokens: ${stats.totalTokens}`); |
| 130 | + console.log(` Prompt tokens: ${stats.totalPromptTokens}`); |
| 131 | + console.log(` Completion tokens: ${stats.totalCompletionTokens}`); |
| 132 | + |
| 133 | + } catch (error: any) { |
| 134 | + console.error(`\n❌ Error during execution: ${error.message}`); |
| 135 | + throw error; |
| 136 | + } finally { |
| 137 | + // 7. Close tracer (uploads to cloud) |
| 138 | + console.log('\n📤 Uploading trace to cloud...'); |
| 139 | + try { |
| 140 | + await tracer.close(true); // Wait for upload to complete |
| 141 | + console.log('✅ Trace uploaded successfully!'); |
| 142 | + console.log(` View at: https://studio.sentienceapi.com (run_id: ${runId})`); |
| 143 | + } catch (error: any) { |
| 144 | + console.error(`⚠️ Upload failed: ${error.message}`); |
| 145 | + console.error(` Trace preserved locally at: ~/.sentience/traces/pending/${runId}.jsonl`); |
| 146 | + } |
| 147 | + |
| 148 | + await browser.close(); |
| 149 | + } |
| 150 | +} |
| 151 | + |
| 152 | +main().catch(console.error); |
| 153 | + |
0 commit comments