@@ -7,57 +7,90 @@ import (
77 "fmt"
88 "strings"
99 "time"
10+
1011 "github.com/chromedp/chromedp"
1112)
1213
1314func toolBrowserScreenshot (ctx context.Context , selector , qualityStr string ) (string , error ) {
14- if browserSession == nil { return "" , fmt .Errorf ("sin_browser_screenshot: no active browser session" ) }
15+ if browserSession == nil {
16+ return "" , fmt .Errorf ("sin_browser_screenshot: no active browser session" )
17+ }
1518 quality := 80
16- if qualityStr != "" { fmt .Sscanf (qualityStr , "%d" , & quality ) }
19+ if qualityStr != "" {
20+ fmt .Sscanf (qualityStr , "%d" , & quality )
21+ }
1722 var buf []byte
1823 var err error
1924 if selector != "" {
2025 err = chromedp .Run (browserSession .cdpCtx , chromedp .WaitVisible (selector , chromedp .ByQuery ), chromedp .Screenshot (selector , & buf , chromedp .ByQuery ))
2126 } else {
2227 err = chromedp .Run (browserSession .cdpCtx , chromedp .CaptureScreenshot (& buf ))
2328 }
24- if err != nil { return "" , fmt .Errorf ("sin_browser_screenshot: %w" , err ) }
29+ if err != nil {
30+ return "" , fmt .Errorf ("sin_browser_screenshot: %w" , err )
31+ }
2532 return "data:image/png;base64," + base64 .StdEncoding .EncodeToString (buf ), nil
2633}
2734
2835func toolBrowserClick (ctx context.Context , selector string ) (string , error ) {
29- if browserSession == nil { return "" , fmt .Errorf ("sin_browser_click: no active browser session" ) }
30- if selector == "" { return "" , fmt .Errorf ("selector required" ) }
36+ if browserSession == nil {
37+ return "" , fmt .Errorf ("sin_browser_click: no active browser session" )
38+ }
39+ if selector == "" {
40+ return "" , fmt .Errorf ("selector required" )
41+ }
3142 err := chromedp .Run (browserSession .cdpCtx , chromedp .WaitVisible (selector , chromedp .ByQuery ), chromedp .Click (selector , chromedp .ByQuery ))
32- if err != nil { return "" , fmt .Errorf ("sin_browser_click: %w" , err ) }
43+ if err != nil {
44+ return "" , fmt .Errorf ("sin_browser_click: %w" , err )
45+ }
3346 return "clicked: " + selector , nil
3447}
3548
3649func toolBrowserType (ctx context.Context , selector , text , submitStr string ) (string , error ) {
37- if browserSession == nil { return "" , fmt .Errorf ("no active browser session" ) }
38- if selector == "" { return "" , fmt .Errorf ("selector required" ) }
50+ if browserSession == nil {
51+ return "" , fmt .Errorf ("no active browser session" )
52+ }
53+ if selector == "" {
54+ return "" , fmt .Errorf ("selector required" )
55+ }
3956 submit := strings .ToLower (submitStr ) == "true"
4057 actions := []chromedp.Action {chromedp .WaitVisible (selector , chromedp .ByQuery ), chromedp .Focus (selector , chromedp .ByQuery ), chromedp .Clear (selector , chromedp .ByQuery ), chromedp .SendKeys (selector , text , chromedp .ByQuery )}
41- if submit { actions = append (actions , chromedp .SendKeys (selector , "\n " , chromedp .ByQuery )) }
58+ if submit {
59+ actions = append (actions , chromedp .SendKeys (selector , "\n " , chromedp .ByQuery ))
60+ }
4261 err := chromedp .Run (browserSession .cdpCtx , actions ... )
43- if err != nil { return "" , fmt .Errorf ("sin_browser_type: %w" , err ) }
62+ if err != nil {
63+ return "" , fmt .Errorf ("sin_browser_type: %w" , err )
64+ }
4465 r := "typed " + text + " into " + selector
45- if submit { r += " and submitted" }
66+ if submit {
67+ r += " and submitted"
68+ }
4669 return r , nil
4770}
4871
4972func toolBrowserEval (ctx context.Context , expr string ) (string , error ) {
50- if browserSession == nil { return "" , fmt .Errorf ("no active browser session" ) }
51- if expr == "" { return "" , fmt .Errorf ("expression required" ) }
73+ if browserSession == nil {
74+ return "" , fmt .Errorf ("no active browser session" )
75+ }
76+ if expr == "" {
77+ return "" , fmt .Errorf ("expression required" )
78+ }
5279 var result any
5380 err := chromedp .Run (browserSession .cdpCtx , chromedp .Evaluate (expr , & result ))
54- if err != nil { return "" , fmt .Errorf ("sin_browser_eval: %w" , err ) }
81+ if err != nil {
82+ return "" , fmt .Errorf ("sin_browser_eval: %w" , err )
83+ }
5584 return fmt .Sprintf ("%v" , result ), nil
5685}
5786
5887func toolBrowserWait (ctx context.Context , selector , timeoutStr string ) (string , error ) {
59- if browserSession == nil { return "" , fmt .Errorf ("no active browser session" ) }
60- if selector == "" { return "" , fmt .Errorf ("selector required" ) }
88+ if browserSession == nil {
89+ return "" , fmt .Errorf ("no active browser session" )
90+ }
91+ if selector == "" {
92+ return "" , fmt .Errorf ("selector required" )
93+ }
6194 timeout := 10 * time .Second
6295 if timeoutStr != "" {
6396 var sec int
@@ -68,13 +101,17 @@ func toolBrowserWait(ctx context.Context, selector, timeoutStr string) (string,
68101 waitCtx , cancel := context .WithTimeout (ctx , timeout )
69102 defer cancel ()
70103 err := chromedp .Run (waitCtx , chromedp .WaitVisible (selector , chromedp .ByQuery ))
71- if err != nil { return fmt .Sprintf ("wait failed: %v" , err ), nil }
104+ if err != nil {
105+ return fmt .Sprintf ("wait failed: %v" , err ), nil
106+ }
72107 return "element visible: " + selector , nil
73108}
74109
75110func registerBrowserInteractionSpecs () []agentloopToolSpecAlias {
76111 s := func (d string ) map [string ]any { return map [string ]any {"type" : "string" , "description" : d } }
77- o := func (p map [string ]any , r ... string ) map [string ]any { return map [string ]any {"type" : "object" , "properties" : p , "required" : r } }
112+ o := func (p map [string ]any , r ... string ) map [string ]any {
113+ return map [string ]any {"type" : "object" , "properties" : p , "required" : r }
114+ }
78115 return []agentloopToolSpecAlias {
79116 {Name : "sin_browser_screenshot" , Description : "Capture PNG screenshot as base64 data URI for visual understanding (issue #386)" , InputSchema : o (map [string ]any {"selector" : s ("CSS selector (optional)" ), "quality" : s ("1-100 default 80" )})},
80117 {Name : "sin_browser_click" , Description : "Click element by CSS selector (issue #382)" , InputSchema : o (map [string ]any {"selector" : s ("CSS selector" )}, "selector" )},
@@ -86,11 +123,31 @@ func registerBrowserInteractionSpecs() []agentloopToolSpecAlias {
86123
87124func dispatchBrowserInteraction (ctx context.Context , name string , args map [string ]any ) (string , bool , error ) {
88125 switch name {
89- case "sin_browser_screenshot" : s ,_ := args ["selector" ].(string ); q ,_ := args ["quality" ].(string ); out ,err := toolBrowserScreenshot (ctx ,s ,q ); return out ,true ,err
90- case "sin_browser_click" : s ,_ := args ["selector" ].(string ); out ,err := toolBrowserClick (ctx ,s ); return out ,true ,err
91- case "sin_browser_type" : s ,_ := args ["selector" ].(string ); t ,_ := args ["text" ].(string ); sub ,_ := args ["submit" ].(string ); out ,err := toolBrowserType (ctx ,s ,t ,sub ); return out ,true ,err
92- case "sin_browser_eval" : e ,_ := args ["expr" ].(string ); out ,err := toolBrowserEval (ctx ,e ); return out ,true ,err
93- case "sin_browser_wait" : s ,_ := args ["selector" ].(string ); t ,_ := args ["timeout" ].(string ); out ,err := toolBrowserWait (ctx ,s ,t ); return out ,true ,err
94- default : return "" ,false ,nil
126+ case "sin_browser_screenshot" :
127+ s , _ := args ["selector" ].(string )
128+ q , _ := args ["quality" ].(string )
129+ out , err := toolBrowserScreenshot (ctx , s , q )
130+ return out , true , err
131+ case "sin_browser_click" :
132+ s , _ := args ["selector" ].(string )
133+ out , err := toolBrowserClick (ctx , s )
134+ return out , true , err
135+ case "sin_browser_type" :
136+ s , _ := args ["selector" ].(string )
137+ t , _ := args ["text" ].(string )
138+ sub , _ := args ["submit" ].(string )
139+ out , err := toolBrowserType (ctx , s , t , sub )
140+ return out , true , err
141+ case "sin_browser_eval" :
142+ e , _ := args ["expr" ].(string )
143+ out , err := toolBrowserEval (ctx , e )
144+ return out , true , err
145+ case "sin_browser_wait" :
146+ s , _ := args ["selector" ].(string )
147+ t , _ := args ["timeout" ].(string )
148+ out , err := toolBrowserWait (ctx , s , t )
149+ return out , true , err
150+ default :
151+ return "" , false , nil
95152 }
96153}
0 commit comments