11
11
from langrocks .client import WebBrowser as WebBrowserClient
12
12
from langrocks .common .models .web_browser import (
13
13
WebBrowserCommand ,
14
- WebBrowserCommandOutput ,
15
14
WebBrowserCommandType ,
16
15
WebBrowserContent ,
17
16
)
@@ -470,14 +469,7 @@ def _execute_anthropic_instruction_in_browser(
470
469
)
471
470
else :
472
471
logger .error (f"Invalid instruction: { instruction_input } " )
473
- return WebBrowserContent (
474
- command_outputs = [
475
- WebBrowserCommandOutput (
476
- index = 0 ,
477
- output = "We do not currently support this action" ,
478
- )
479
- ],
480
- )
472
+ return None
481
473
482
474
def _process_anthropic (self ) -> dict :
483
475
client = get_llm_client_from_provider_config (
@@ -579,20 +571,18 @@ def _process_anthropic(self) -> dict:
579
571
max_tokens = 4096 ,
580
572
)
581
573
if response .usage :
582
- self ._usage_data .append (
583
- (
584
- f"{ self ._config .provider_config .provider } /*/{ self ._config .provider_config .model .model_name ()} /*" ,
585
- MetricType .INPUT_TOKENS ,
586
- (provider_config .provider_config_source , response .usage .get_input_tokens ()),
587
- )
588
- )
589
- self ._usage_data .append (
590
- (
591
- f"{ self ._config .provider_config .provider } /*/{ self ._config .provider_config .model .model_name ()} /*" ,
592
- MetricType .OUTPUT_TOKENS ,
593
- (provider_config .provider_config_source , response .usage .get_output_tokens ()),
574
+ for metric_type , token_getter in [
575
+ (MetricType .INPUT_TOKENS , response .usage .get_input_tokens ),
576
+ (MetricType .OUTPUT_TOKENS , response .usage .get_output_tokens ),
577
+ ]:
578
+ self ._usage_data .append (
579
+ (
580
+ f"{ self ._config .provider_config .provider } /*/{ self ._config .provider_config .model .model_name ()} /*" ,
581
+ metric_type ,
582
+ (provider_config .provider_config_source , token_getter ()),
583
+ )
594
584
)
595
- )
585
+
596
586
choice = response .choices [0 ]
597
587
# Append to history of messages
598
588
messages .append (
@@ -601,6 +591,15 @@ def _process_anthropic(self) -> dict:
601
591
"content" : choice .message .content ,
602
592
}
603
593
)
594
+
595
+ def create_tool_response (content , tool_use_id , is_error = False ):
596
+ return {
597
+ "type" : "tool_result" ,
598
+ "content" : [content ],
599
+ "tool_use_id" : tool_use_id ,
600
+ "is_error" : is_error ,
601
+ }
602
+
604
603
if choice .finish_reason == "tool_use" :
605
604
tool_responses = []
606
605
for message_content in choice .message .content :
@@ -618,7 +617,6 @@ def _process_anthropic(self) -> dict:
618
617
)
619
618
input_domain = urlparse (domain ).netloc or domain
620
619
621
- # Compare the extracted domains
622
620
if credential_domain in input_domain or input_domain in credential_domain :
623
621
credentials_to_use = credential
624
622
break
@@ -627,16 +625,13 @@ def _process_anthropic(self) -> dict:
627
625
{
628
626
"role" : "user" ,
629
627
"content" : [
630
- {
631
- "type" : "tool_result" ,
632
- "content" : [
633
- {
634
- "type" : "text" ,
635
- "text" : f"Credentials for { domain } : username: { credentials_to_use .get ('username' )} , password: { credentials_to_use .get ('password' )} " ,
636
- }
637
- ],
638
- "tool_use_id" : message_content ["id" ],
639
- }
628
+ create_tool_response (
629
+ {
630
+ "type" : "text" ,
631
+ "text" : f"Credentials for { domain } : username: { credentials_to_use .get ('username' )} , password: { credentials_to_use .get ('password' )} " ,
632
+ },
633
+ message_content ["id" ],
634
+ )
640
635
],
641
636
}
642
637
)
@@ -647,52 +642,68 @@ def _process_anthropic(self) -> dict:
647
642
web_browser = web_browser ,
648
643
prev_browser_state = browser_response ,
649
644
)
650
- if browser_response .downloads :
651
- browser_downloads .extend (browser_response .downloads )
652
- command_output = browser_response .command_outputs [0 ]
653
- if message_content .get ("input" , {}).get ("action" ) == "screenshot" :
645
+ if browser_response is None :
654
646
tool_responses .append (
655
- {
656
- "type" : "tool_result" ,
657
- "content" : [
658
- {
659
- "type" : "image" ,
660
- "source" : {
661
- "type" : "base64" ,
662
- "media_type" : "image/png" ,
663
- "data" : command_output .output ,
664
- },
665
- },
666
- ],
667
- "tool_use_id" : message_content ["id" ],
668
- "is_error" : False ,
669
- }
647
+ create_tool_response (
648
+ {"type" : "text" , "text" : "We do not currently support this action" },
649
+ message_content ["id" ],
650
+ is_error = True ,
651
+ )
670
652
)
671
653
else :
672
- tool_responses .append (
673
- {
674
- "type" : "tool_result" ,
675
- "content" : [
654
+ if browser_response .downloads :
655
+ browser_downloads .extend (browser_response .downloads )
656
+
657
+ is_screenshot = message_content .get ("input" , {}).get ("action" ) == "screenshot"
658
+ command_output = (
659
+ browser_response .command_outputs [0 ] if browser_response .command_outputs else None
660
+ )
661
+ command_error = (
662
+ browser_response .command_errors [0 ].error
663
+ if browser_response .command_errors
664
+ else None
665
+ )
666
+
667
+ if command_output and command_output .output :
668
+ content = {
669
+ "type" : "image" if is_screenshot else "text" ,
670
+ "source"
671
+ if is_screenshot
672
+ else "text" : (
673
+ {
674
+ "type" : "base64" ,
675
+ "media_type" : "image/png" ,
676
+ "data" : command_output .output ,
677
+ }
678
+ if is_screenshot
679
+ else command_output .output
680
+ ),
681
+ }
682
+ tool_responses .append (create_tool_response (content , message_content ["id" ]))
683
+ else :
684
+ screenshot_error_text = (
685
+ command_error .error if command_error else "No screenshot available"
686
+ )
687
+ output_error_text = command_error .error if command_error else "No output available"
688
+ tool_responses .append (
689
+ create_tool_response (
676
690
{
677
691
"type" : "text" ,
678
- "text" : command_output . output ,
692
+ "text" : screenshot_error_text if is_screenshot else output_error_text ,
679
693
},
680
- ],
681
- "tool_use_id" : message_content ["id" ],
682
- "is_error" : False ,
683
- }
684
- )
694
+ message_content ["id" ],
695
+ is_error = True ,
696
+ )
697
+ )
698
+ logger .error (
699
+ f"No command output for tool use: { message_content .get ('input' , {})} . Error: { command_error } " ,
700
+ )
685
701
else :
686
702
async_to_sync (self ._output_stream .write )(
687
703
WebBrowserOutput (text = message_content .get ("text" , "" ) + "\n \n " ),
688
704
)
689
705
if tool_responses :
690
- messages .append (
691
- {
692
- "role" : "user" ,
693
- "content" : tool_responses ,
694
- }
695
- )
706
+ messages .append ({"role" : "user" , "content" : tool_responses })
696
707
continue
697
708
elif choice .finish_reason == "end_turn" :
698
709
browser_response = web_browser .run_commands (
0 commit comments