77require "net/http"
88require "stagehand"
99
10- # Example: Using Playwright with Stagehand local mode
11- #
12- # This example mirrors the Python Playwright flow: launch the browser with Playwright,
13- # connect Stagehand to the same browser via CDP, and target the existing page by frame_id.
14- #
15- # Prerequisites:
16- # - Set MODEL_API_KEY or OPENAI_API_KEY environment variable
17- # - Chrome/Chromium installed locally
18- # - Install Playwright (outside this gem):
19- # gem install playwright-ruby-client
20- # npm install playwright
21- # ./node_modules/.bin/playwright install chromium
22- #
23- # Run:
24- # bundle exec ruby examples/local_playwright_example.rb
25-
10+ require_relative "env"
11+ ExampleEnv . load!
2612begin
2713 require ( "playwright" )
2814rescue LoadError
@@ -69,9 +55,43 @@ def fetch_page_target_id(port, page_url)
6955 target_id
7056end
7157
72- model_key = ENV [ "MODEL_API_KEY" ] || ENV [ "OPENAI_API_KEY" ]
58+ def print_stream_event ( label , event )
59+ case event . type
60+ when :log
61+ puts ( "[#{ label } ] log: #{ event . data . message } " )
62+ when :system
63+ status = event . data . status
64+ if event . data . respond_to? ( :error ) && event . data . error
65+ puts ( "[#{ label } ] system #{ status } : #{ event . data . error } " )
66+ elsif event . data . respond_to? ( :result ) && !event . data . result . nil?
67+ puts ( "[#{ label } ] system #{ status } : #{ event . data . result } " )
68+ else
69+ puts ( "[#{ label } ] system #{ status } " )
70+ end
71+ else
72+ puts ( "[#{ label } ] event: #{ event . inspect } " )
73+ end
74+ end
75+
76+ def stream_with_result ( label , stream )
77+ puts ( "#{ label } stream:" )
78+ result = nil
79+ stream . each do |event |
80+ print_stream_event ( label , event )
81+ if event . type == :system && event . data . respond_to? ( :result ) && !event . data . result . nil?
82+ result = event . data . result
83+ end
84+ if event . type == :system && event . data . respond_to? ( :status ) && event . data . status == :error
85+ error_message = event . data . respond_to? ( :error ) && event . data . error ? event . data . error : "unknown error"
86+ raise ( "#{ label } stream error: #{ error_message } " )
87+ end
88+ end
89+ result
90+ end
91+
92+ model_key = ENV [ "MODEL_API_KEY" ]
7393if model_key . to_s . empty?
74- warn "Set MODEL_API_KEY (or OPENAI_API_KEY) to run the local example."
94+ warn "Set MODEL_API_KEY to run the local example."
7595 exit 1
7696end
7797
@@ -110,23 +130,27 @@ def fetch_page_target_id(port, page_url)
110130 session_id = start_response . data . session_id
111131 puts ( "Session started: #{ session_id } " )
112132
113- observe_response = client . sessions . observe (
133+ observe_stream = client . sessions . observe_streaming (
114134 session_id ,
115135 frame_id : page_target_id ,
116136 instruction : "Find all clickable links on this page"
117137 )
118- puts ( "Found #{ observe_response . data . result . length } possible actions" )
138+ observe_result = stream_with_result ( "Observe" , observe_stream )
139+ observe_actions = observe_result || [ ]
140+ puts ( "Found #{ observe_actions . length } possible actions" )
119141
120- action = observe_response . data . result . first
142+ action = observe_actions . first
121143 act_input = action ? action . to_h . merge ( method : "click" ) : "Click the 'Learn more' link"
122- act_response = client . sessions . act (
144+ act_stream = client . sessions . act_streaming (
123145 session_id ,
124146 frame_id : page_target_id ,
125147 input : act_input
126148 )
127- puts ( "Act completed: #{ act_response . data . result [ :message ] } " )
149+ act_result = stream_with_result ( "Act" , act_stream )
150+ act_message = act_result . is_a? ( Hash ) ? ( act_result [ :message ] || act_result [ "message" ] ) : act_result
151+ puts ( "Act completed: #{ act_message } " )
128152
129- extract_response = client . sessions . extract (
153+ extract_stream = client . sessions . extract_streaming (
130154 session_id ,
131155 frame_id : page_target_id ,
132156 instruction : "Extract the main heading and any links on this page" ,
@@ -138,9 +162,10 @@ def fetch_page_target_id(port, page_url)
138162 }
139163 }
140164 )
141- puts ( "Extracted: #{ extract_response . data . result } " )
165+ extract_result = stream_with_result ( "Extract" , extract_stream )
166+ puts ( "Extracted: #{ extract_result } " )
142167
143- execute_response = client . sessions . execute (
168+ execute_stream = client . sessions . execute_streaming (
144169 session_id ,
145170 frame_id : page_target_id ,
146171 execute_options : {
@@ -155,8 +180,13 @@ def fetch_page_target_id(port, page_url)
155180 cua : false
156181 }
157182 )
158- puts ( "Agent completed: #{ execute_response . data . result [ :message ] } " )
159- puts ( "Agent success: #{ execute_response . data . result [ :success ] } " )
183+ execute_result = stream_with_result ( "Execute" , execute_stream )
184+ execute_message = execute_result . is_a? ( Hash ) ? ( execute_result [ :message ] || execute_result [ "message" ] ) : execute_result
185+ execute_success = execute_result . is_a? ( Hash ) ? ( execute_result [ :success ] || execute_result [ "success" ] ) : nil
186+ execute_actions = execute_result . is_a? ( Hash ) ? ( execute_result [ :actions ] || execute_result [ "actions" ] ) : nil
187+ puts ( "Agent completed: #{ execute_message } " )
188+ puts ( "Agent success: #{ execute_success } " )
189+ puts ( "Agent actions taken: #{ execute_actions &.length || 0 } " )
160190
161191 page . wait_for_load_state ( state : "domcontentloaded" )
162192 page . screenshot ( path : "screenshot_local_playwright.png" , fullPage : true )
0 commit comments