1111from langrocks .client import WebBrowser as WebBrowserClient
1212from langrocks .common .models .web_browser import (
1313 WebBrowserCommand ,
14- WebBrowserCommandOutput ,
1514 WebBrowserCommandType ,
1615 WebBrowserContent ,
1716)
@@ -470,14 +469,7 @@ def _execute_anthropic_instruction_in_browser(
470469 )
471470 else :
472471 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
481473
482474 def _process_anthropic (self ) -> dict :
483475 client = get_llm_client_from_provider_config (
@@ -579,20 +571,18 @@ def _process_anthropic(self) -> dict:
579571 max_tokens = 4096 ,
580572 )
581573 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+ )
594584 )
595- )
585+
596586 choice = response .choices [0 ]
597587 # Append to history of messages
598588 messages .append (
@@ -601,6 +591,15 @@ def _process_anthropic(self) -> dict:
601591 "content" : choice .message .content ,
602592 }
603593 )
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+
604603 if choice .finish_reason == "tool_use" :
605604 tool_responses = []
606605 for message_content in choice .message .content :
@@ -618,7 +617,6 @@ def _process_anthropic(self) -> dict:
618617 )
619618 input_domain = urlparse (domain ).netloc or domain
620619
621- # Compare the extracted domains
622620 if credential_domain in input_domain or input_domain in credential_domain :
623621 credentials_to_use = credential
624622 break
@@ -627,16 +625,13 @@ def _process_anthropic(self) -> dict:
627625 {
628626 "role" : "user" ,
629627 "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+ )
640635 ],
641636 }
642637 )
@@ -647,52 +642,68 @@ def _process_anthropic(self) -> dict:
647642 web_browser = web_browser ,
648643 prev_browser_state = browser_response ,
649644 )
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 :
654646 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+ )
670652 )
671653 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 (
676690 {
677691 "type" : "text" ,
678- "text" : command_output . output ,
692+ "text" : screenshot_error_text if is_screenshot else output_error_text ,
679693 },
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+ )
685701 else :
686702 async_to_sync (self ._output_stream .write )(
687703 WebBrowserOutput (text = message_content .get ("text" , "" ) + "\n \n " ),
688704 )
689705 if tool_responses :
690- messages .append (
691- {
692- "role" : "user" ,
693- "content" : tool_responses ,
694- }
695- )
706+ messages .append ({"role" : "user" , "content" : tool_responses })
696707 continue
697708 elif choice .finish_reason == "end_turn" :
698709 browser_response = web_browser .run_commands (
0 commit comments