diff --git a/e2e/testdata/cassettes/TestExec_Anthropic_ToolCall.yaml b/e2e/testdata/cassettes/TestExec_Anthropic_ToolCall.yaml index eaa34ee5f..569baffca 100644 --- a/e2e/testdata/cassettes/TestExec_Anthropic_ToolCall.yaml +++ b/e2e/testdata/cassettes/TestExec_Anthropic_ToolCall.yaml @@ -8,7 +8,7 @@ interactions: proto_minor: 1 content_length: 0 host: api.anthropic.com - body: '{"max_tokens":64000,"messages":[{"content":[{"text":"How many files in testdata/working_dir? Only output the number.","cache_control":{"type":"ephemeral"},"type":"text"}],"role":"user"}],"model":"claude-sonnet-4-0","system":[{"text":"You are a knowledgeable assistant that helps users with various tasks.\nBe helpful, accurate, and concise in your responses.","type":"text"},{"text":"## Filesystem Tool Instructions\n\nThis toolset provides comprehensive filesystem operations.\n\n### Working Directory\n- Relative paths (like \".\" or \"src/main.go\") are resolved relative to the working directory\n- Absolute paths (like \"/etc/hosts\") access files directly\n- Paths starting with \"..\" can access parent directories\n\n### Common Patterns\n- Always check if directories exist before creating files\n- Prefer read_multiple_files for batch operations\n- Use search_files_content for finding specific code or text\n\n### Performance Tips\n- Use read_multiple_files instead of multiple read_file calls\n- Use directory_tree with max_depth to limit large traversals\n- Use appropriate exclude patterns in search operations","cache_control":{"type":"ephemeral"},"type":"text"}],"tools":[{"input_schema":{"properties":{"path":{"description":"The directory path to traverse (relative to working directory)","type":"string"}},"required":["path"],"type":"object"},"name":"directory_tree","description":"Get a recursive tree view of files and directories as a JSON structure."},{"input_schema":{"properties":{"edits":{"description":"Array of edit operations","items":{"additionalProperties":false,"properties":{"newText":{"description":"The replacement text","type":"string"},"oldText":{"description":"The exact text to replace","type":"string"}},"required":["oldText","newText"],"type":"object"},"type":["null","array"]},"path":{"description":"The file path to edit","type":"string"}},"required":["path","edits"],"type":"object"},"name":"edit_file","description":"Make line-based edits to a text file. Each edit replaces exact line sequences with new content."},{"input_schema":{"properties":{"path":{"description":"The directory path to list","type":"string"}},"required":["path"],"type":"object"},"name":"list_directory","description":"Get a detailed listing of all files and directories in a specified path."},{"input_schema":{"properties":{"path":{"description":"The file path to read","type":"string"}},"required":["path"],"type":"object"},"name":"read_file","description":"Read the complete contents of a file from the file system."},{"input_schema":{"properties":{"json":{"description":"Whether to return the result as JSON","type":"boolean"},"paths":{"description":"Array of file paths to read","items":{"type":"string"},"type":["null","array"]}},"required":["paths"],"type":"object"},"name":"read_multiple_files","description":"Read the contents of multiple files simultaneously."},{"input_schema":{"properties":{"excludePatterns":{"description":"Patterns to exclude from search","items":{"type":"string"},"type":["null","array"]},"is_regex":{"description":"If true, treat query as regex; otherwise literal text","type":"boolean"},"path":{"description":"The starting directory path","type":"string"},"query":{"description":"The text or regex pattern to search for","type":"string"}},"required":["path","query"],"type":"object"},"name":"search_files_content","description":"Searches for text or regex patterns in the content of files matching a GLOB pattern."},{"input_schema":{"properties":{"content":{"description":"The content to write to the file","type":"string"},"path":{"description":"The file path to write","type":"string"}},"required":["path","content"],"type":"object"},"name":"write_file","description":"Create a new file or completely overwrite an existing file with new content."}],"stream":true}' + body: '{"max_tokens":64000,"messages":[{"content":[{"text":"How many files in testdata/working_dir? Only output the number.","cache_control":{"type":"ephemeral"},"type":"text"}],"role":"user"}],"model":"claude-sonnet-4-0","system":[{"text":"You are a knowledgeable assistant that helps users with various tasks.\nBe helpful, accurate, and concise in your responses.","type":"text"},{"text":"## Filesystem Tool Instructions\n\nThis toolset provides comprehensive filesystem operations.\n\n### Working Directory\n- Relative paths (like \".\" or \"src/main.go\") are resolved relative to the working directory\n- Absolute paths (like \"/etc/hosts\") access files directly\n- Paths starting with \"..\" can access parent directories\n\n### Common Patterns\n- Always check if directories exist before creating files\n- Prefer read_multiple_files for batch operations\n- Use search_files_content for finding specific code or text\n\n### Performance Tips\n- Use read_multiple_files instead of multiple read_file calls\n- Use directory_tree with max_depth to limit large traversals\n- Use appropriate exclude patterns in search operations\n\n### Reading Large Files\n- read_file and read_multiple_files support offset and line_count parameters for pagination\n- When a file is large, read it in chunks: start with offset=1 and a reasonable line_count\n- The response includes total_lines so you know how many more lines remain\n- Continue reading with an incremented offset until you have read all required content","cache_control":{"type":"ephemeral"},"type":"text"}],"tools":[{"input_schema":{"properties":{"path":{"description":"The directory path to traverse (relative to working directory)","type":"string"}},"required":["path"],"type":"object"},"name":"directory_tree","description":"Get a recursive tree view of files and directories as a JSON structure."},{"input_schema":{"properties":{"edits":{"description":"Array of edit operations","items":{"additionalProperties":false,"properties":{"newText":{"description":"The replacement text","type":"string"},"oldText":{"description":"The exact text to replace","type":"string"}},"required":["oldText","newText"],"type":"object"},"type":["null","array"]},"path":{"description":"The file path to edit","type":"string"}},"required":["path","edits"],"type":"object"},"name":"edit_file","description":"Make line-based edits to a text file. Each edit replaces exact line sequences with new content."},{"input_schema":{"properties":{"path":{"description":"The directory path to list","type":"string"}},"required":["path"],"type":"object"},"name":"list_directory","description":"Get a detailed listing of all files and directories in a specified path."},{"input_schema":{"properties":{"line_count":{"description":"Maximum number of lines to return (default: all remaining lines)","type":"integer"},"offset":{"description":"1-based line number to start reading from (default: 1)","type":"integer"},"path":{"description":"The file path to read","type":"string"}},"required":["path"],"type":"object"},"name":"read_file","description":"Read the contents of a file from the file system."},{"input_schema":{"properties":{"json":{"description":"Whether to return the result as JSON","type":"boolean"},"line_count":{"description":"Maximum number of lines to return per file (default: all remaining lines)","type":"integer"},"offset":{"description":"1-based line number to start reading from, applied to all files (default: 1)","type":"integer"},"paths":{"description":"Array of file paths to read","items":{"type":"string"},"type":["null","array"]}},"required":["paths"],"type":"object"},"name":"read_multiple_files","description":"Read the contents of multiple files simultaneously."},{"input_schema":{"properties":{"excludePatterns":{"description":"Patterns to exclude from search","items":{"type":"string"},"type":["null","array"]},"is_regex":{"description":"If true, treat query as regex; otherwise literal text","type":"boolean"},"path":{"description":"The starting directory path","type":"string"},"query":{"description":"The text or regex pattern to search for","type":"string"}},"required":["path","query"],"type":"object"},"name":"search_files_content","description":"Searches for text or regex patterns in the content of files matching a GLOB pattern."},{"input_schema":{"properties":{"content":{"description":"The content to write to the file","type":"string"},"path":{"description":"The file path to write","type":"string"}},"required":["path","content"],"type":"object"},"name":"write_file","description":"Create a new file or completely overwrite an existing file with new content."}],"stream":true}' url: https://api.anthropic.com/v1/messages method: POST response: @@ -18,36 +18,36 @@ interactions: content_length: -1 body: |+ event: message_start - data: {"type":"message_start","message":{"model":"claude-sonnet-4-20250514","id":"msg_01BKqBqWhk1BNCFCGJKBuURw","type":"message","role":"assistant","content":[],"stop_reason":null,"stop_sequence":null,"usage":{"input_tokens":3,"cache_creation_input_tokens":1276,"cache_read_input_tokens":0,"cache_creation":{"ephemeral_5m_input_tokens":1276,"ephemeral_1h_input_tokens":0},"output_tokens":1,"service_tier":"standard"}} } + data: {"type":"message_start","message":{"model":"claude-sonnet-4-20250514","id":"msg_012N32DiE5GDd1Dtqw7TKTDw","type":"message","role":"assistant","content":[],"stop_reason":null,"stop_sequence":null,"usage":{"input_tokens":3,"cache_creation_input_tokens":1480,"cache_read_input_tokens":0,"cache_creation":{"ephemeral_5m_input_tokens":1480,"ephemeral_1h_input_tokens":0},"output_tokens":1,"service_tier":"standard","inference_geo":"not_available"}} } event: content_block_start - data: {"type":"content_block_start","index":0,"content_block":{"type":"tool_use","id":"toolu_012gmfqnoTX8c5aV3vMWUnas","name":"list_directory","input":{}} } + data: {"type":"content_block_start","index":0,"content_block":{"type":"tool_use","id":"toolu_01NLzPakRDxb9151yibLtj2j","name":"list_directory","input":{},"caller":{"type":"direct"}} } event: ping data: {"type": "ping"} event: content_block_delta - data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":""} } + data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":""} } event: content_block_delta - data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"{\"path\": \"testdata/working_dir"} } + data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"{\"path\": \"testdata/working_dir"} } event: content_block_delta - data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"\"}"} } + data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"\"}"} } event: content_block_stop - data: {"type":"content_block_stop","index":0 } + data: {"type":"content_block_stop","index":0 } event: message_delta - data: {"type":"message_delta","delta":{"stop_reason":"tool_use","stop_sequence":null},"usage":{"input_tokens":3,"cache_creation_input_tokens":1276,"cache_read_input_tokens":0,"output_tokens":58} } + data: {"type":"message_delta","delta":{"stop_reason":"tool_use","stop_sequence":null},"usage":{"input_tokens":3,"cache_creation_input_tokens":1480,"cache_read_input_tokens":0,"output_tokens":58} } event: message_stop - data: {"type":"message_stop" } + data: {"type":"message_stop" } headers: {} status: 200 OK code: 200 - duration: 1.588085084s + duration: 1.14679975s - id: 1 request: proto: HTTP/1.1 @@ -55,7 +55,7 @@ interactions: proto_minor: 1 content_length: 0 host: api.anthropic.com - body: '{"max_tokens":64000,"messages":[{"content":[{"text":"How many files in testdata/working_dir? Only output the number.","type":"text"}],"role":"user"},{"content":[{"id":"toolu_012gmfqnoTX8c5aV3vMWUnas","input":{"path":"testdata/working_dir"},"name":"list_directory","cache_control":{"type":"ephemeral"},"type":"tool_use"}],"role":"assistant"},{"content":[{"tool_use_id":"toolu_012gmfqnoTX8c5aV3vMWUnas","is_error":false,"cache_control":{"type":"ephemeral"},"content":[{"text":"FILE README.me","type":"text"}],"type":"tool_result"}],"role":"user"}],"model":"claude-sonnet-4-0","system":[{"text":"You are a knowledgeable assistant that helps users with various tasks.\nBe helpful, accurate, and concise in your responses.","type":"text"},{"text":"## Filesystem Tool Instructions\n\nThis toolset provides comprehensive filesystem operations.\n\n### Working Directory\n- Relative paths (like \".\" or \"src/main.go\") are resolved relative to the working directory\n- Absolute paths (like \"/etc/hosts\") access files directly\n- Paths starting with \"..\" can access parent directories\n\n### Common Patterns\n- Always check if directories exist before creating files\n- Prefer read_multiple_files for batch operations\n- Use search_files_content for finding specific code or text\n\n### Performance Tips\n- Use read_multiple_files instead of multiple read_file calls\n- Use directory_tree with max_depth to limit large traversals\n- Use appropriate exclude patterns in search operations","cache_control":{"type":"ephemeral"},"type":"text"}],"tools":[{"input_schema":{"properties":{"path":{"description":"The directory path to traverse (relative to working directory)","type":"string"}},"required":["path"],"type":"object"},"name":"directory_tree","description":"Get a recursive tree view of files and directories as a JSON structure."},{"input_schema":{"properties":{"edits":{"description":"Array of edit operations","items":{"additionalProperties":false,"properties":{"newText":{"description":"The replacement text","type":"string"},"oldText":{"description":"The exact text to replace","type":"string"}},"required":["oldText","newText"],"type":"object"},"type":["null","array"]},"path":{"description":"The file path to edit","type":"string"}},"required":["path","edits"],"type":"object"},"name":"edit_file","description":"Make line-based edits to a text file. Each edit replaces exact line sequences with new content."},{"input_schema":{"properties":{"path":{"description":"The directory path to list","type":"string"}},"required":["path"],"type":"object"},"name":"list_directory","description":"Get a detailed listing of all files and directories in a specified path."},{"input_schema":{"properties":{"path":{"description":"The file path to read","type":"string"}},"required":["path"],"type":"object"},"name":"read_file","description":"Read the complete contents of a file from the file system."},{"input_schema":{"properties":{"json":{"description":"Whether to return the result as JSON","type":"boolean"},"paths":{"description":"Array of file paths to read","items":{"type":"string"},"type":["null","array"]}},"required":["paths"],"type":"object"},"name":"read_multiple_files","description":"Read the contents of multiple files simultaneously."},{"input_schema":{"properties":{"excludePatterns":{"description":"Patterns to exclude from search","items":{"type":"string"},"type":["null","array"]},"is_regex":{"description":"If true, treat query as regex; otherwise literal text","type":"boolean"},"path":{"description":"The starting directory path","type":"string"},"query":{"description":"The text or regex pattern to search for","type":"string"}},"required":["path","query"],"type":"object"},"name":"search_files_content","description":"Searches for text or regex patterns in the content of files matching a GLOB pattern."},{"input_schema":{"properties":{"content":{"description":"The content to write to the file","type":"string"},"path":{"description":"The file path to write","type":"string"}},"required":["path","content"],"type":"object"},"name":"write_file","description":"Create a new file or completely overwrite an existing file with new content."}],"stream":true}' + body: '{"max_tokens":64000,"messages":[{"content":[{"text":"How many files in testdata/working_dir? Only output the number.","type":"text"}],"role":"user"},{"content":[{"id":"toolu_01NLzPakRDxb9151yibLtj2j","input":{"path":"testdata/working_dir"},"name":"list_directory","cache_control":{"type":"ephemeral"},"type":"tool_use"}],"role":"assistant"},{"content":[{"tool_use_id":"toolu_01NLzPakRDxb9151yibLtj2j","is_error":false,"cache_control":{"type":"ephemeral"},"content":[{"text":"FILE README.me","type":"text"}],"type":"tool_result"}],"role":"user"}],"model":"claude-sonnet-4-0","system":[{"text":"You are a knowledgeable assistant that helps users with various tasks.\nBe helpful, accurate, and concise in your responses.","type":"text"},{"text":"## Filesystem Tool Instructions\n\nThis toolset provides comprehensive filesystem operations.\n\n### Working Directory\n- Relative paths (like \".\" or \"src/main.go\") are resolved relative to the working directory\n- Absolute paths (like \"/etc/hosts\") access files directly\n- Paths starting with \"..\" can access parent directories\n\n### Common Patterns\n- Always check if directories exist before creating files\n- Prefer read_multiple_files for batch operations\n- Use search_files_content for finding specific code or text\n\n### Performance Tips\n- Use read_multiple_files instead of multiple read_file calls\n- Use directory_tree with max_depth to limit large traversals\n- Use appropriate exclude patterns in search operations\n\n### Reading Large Files\n- read_file and read_multiple_files support offset and line_count parameters for pagination\n- When a file is large, read it in chunks: start with offset=1 and a reasonable line_count\n- The response includes total_lines so you know how many more lines remain\n- Continue reading with an incremented offset until you have read all required content","cache_control":{"type":"ephemeral"},"type":"text"}],"tools":[{"input_schema":{"properties":{"path":{"description":"The directory path to traverse (relative to working directory)","type":"string"}},"required":["path"],"type":"object"},"name":"directory_tree","description":"Get a recursive tree view of files and directories as a JSON structure."},{"input_schema":{"properties":{"edits":{"description":"Array of edit operations","items":{"additionalProperties":false,"properties":{"newText":{"description":"The replacement text","type":"string"},"oldText":{"description":"The exact text to replace","type":"string"}},"required":["oldText","newText"],"type":"object"},"type":["null","array"]},"path":{"description":"The file path to edit","type":"string"}},"required":["path","edits"],"type":"object"},"name":"edit_file","description":"Make line-based edits to a text file. Each edit replaces exact line sequences with new content."},{"input_schema":{"properties":{"path":{"description":"The directory path to list","type":"string"}},"required":["path"],"type":"object"},"name":"list_directory","description":"Get a detailed listing of all files and directories in a specified path."},{"input_schema":{"properties":{"line_count":{"description":"Maximum number of lines to return (default: all remaining lines)","type":"integer"},"offset":{"description":"1-based line number to start reading from (default: 1)","type":"integer"},"path":{"description":"The file path to read","type":"string"}},"required":["path"],"type":"object"},"name":"read_file","description":"Read the contents of a file from the file system."},{"input_schema":{"properties":{"json":{"description":"Whether to return the result as JSON","type":"boolean"},"line_count":{"description":"Maximum number of lines to return per file (default: all remaining lines)","type":"integer"},"offset":{"description":"1-based line number to start reading from, applied to all files (default: 1)","type":"integer"},"paths":{"description":"Array of file paths to read","items":{"type":"string"},"type":["null","array"]}},"required":["paths"],"type":"object"},"name":"read_multiple_files","description":"Read the contents of multiple files simultaneously."},{"input_schema":{"properties":{"excludePatterns":{"description":"Patterns to exclude from search","items":{"type":"string"},"type":["null","array"]},"is_regex":{"description":"If true, treat query as regex; otherwise literal text","type":"boolean"},"path":{"description":"The starting directory path","type":"string"},"query":{"description":"The text or regex pattern to search for","type":"string"}},"required":["path","query"],"type":"object"},"name":"search_files_content","description":"Searches for text or regex patterns in the content of files matching a GLOB pattern."},{"input_schema":{"properties":{"content":{"description":"The content to write to the file","type":"string"},"path":{"description":"The file path to write","type":"string"}},"required":["path","content"],"type":"object"},"name":"write_file","description":"Create a new file or completely overwrite an existing file with new content."}],"stream":true}' url: https://api.anthropic.com/v1/messages method: POST response: @@ -65,22 +65,22 @@ interactions: content_length: -1 body: |+ event: message_start - data: {"type":"message_start","message":{"model":"claude-sonnet-4-20250514","id":"msg_01J7Njwj72NPagJ5aEQWDKAH","type":"message","role":"assistant","content":[],"stop_reason":null,"stop_sequence":null,"usage":{"input_tokens":6,"cache_creation_input_tokens":72,"cache_read_input_tokens":1276,"cache_creation":{"ephemeral_5m_input_tokens":72,"ephemeral_1h_input_tokens":0},"output_tokens":1,"service_tier":"standard"}} } + data: {"type":"message_start","message":{"model":"claude-sonnet-4-20250514","id":"msg_019Qumscfip4icf3eh173htX","type":"message","role":"assistant","content":[],"stop_reason":null,"stop_sequence":null,"usage":{"input_tokens":6,"cache_creation_input_tokens":72,"cache_read_input_tokens":1480,"cache_creation":{"ephemeral_5m_input_tokens":72,"ephemeral_1h_input_tokens":0},"output_tokens":1,"service_tier":"standard","inference_geo":"not_available"}} } event: content_block_start - data: {"type":"content_block_start","index":0,"content_block":{"type":"text","text":""} } + data: {"type":"content_block_start","index":0,"content_block":{"type":"text","text":""} } event: ping data: {"type": "ping"} event: content_block_delta - data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"1"} } + data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"1"} } event: content_block_stop - data: {"type":"content_block_stop","index":0 } + data: {"type":"content_block_stop","index":0 } event: message_delta - data: {"type":"message_delta","delta":{"stop_reason":"end_turn","stop_sequence":null},"usage":{"input_tokens":6,"cache_creation_input_tokens":72,"cache_read_input_tokens":1276,"output_tokens":4} } + data: {"type":"message_delta","delta":{"stop_reason":"end_turn","stop_sequence":null},"usage":{"input_tokens":6,"cache_creation_input_tokens":72,"cache_read_input_tokens":1480,"output_tokens":4} } event: message_stop data: {"type":"message_stop" } @@ -88,4 +88,4 @@ interactions: headers: {} status: 200 OK code: 200 - duration: 968.753458ms + duration: 2.822775167s diff --git a/e2e/testdata/cassettes/TestExec_Gemini_ToolCall.yaml b/e2e/testdata/cassettes/TestExec_Gemini_ToolCall.yaml index 4715c4b23..88d9cb9ac 100644 --- a/e2e/testdata/cassettes/TestExec_Gemini_ToolCall.yaml +++ b/e2e/testdata/cassettes/TestExec_Gemini_ToolCall.yaml @@ -9,7 +9,7 @@ interactions: content_length: 0 host: generativelanguage.googleapis.com body: | - {"contents":[{"parts":[{"text":"You are a knowledgeable assistant that helps users with various tasks.\nBe helpful, accurate, and concise in your responses.\n"}],"role":"user"},{"parts":[{"text":"## Filesystem Tool Instructions\n\nThis toolset provides comprehensive filesystem operations.\n\n### Working Directory\n- Relative paths (like \".\" or \"src/main.go\") are resolved relative to the working directory\n- Absolute paths (like \"/etc/hosts\") access files directly\n- Paths starting with \"..\" can access parent directories\n\n### Common Patterns\n- Always check if directories exist before creating files\n- Prefer read_multiple_files for batch operations\n- Use search_files_content for finding specific code or text\n\n### Performance Tips\n- Use read_multiple_files instead of multiple read_file calls\n- Use directory_tree with max_depth to limit large traversals\n- Use appropriate exclude patterns in search operations"}],"role":"user"},{"parts":[{"text":"How many files in testdata/working_dir? Only output the number."}],"role":"user"}],"generationConfig":{},"toolConfig":{"functionCallingConfig":{"mode":"AUTO"}},"tools":[{"functionDeclarations":[{"description":"Get a recursive tree view of files and directories as a JSON structure.","name":"directory_tree","parameters":{"properties":{"path":{"description":"The directory path to traverse (relative to working directory)","type":"string"}},"required":["path"],"type":"object"}},{"description":"Make line-based edits to a text file. Each edit replaces exact line sequences with new content.","name":"edit_file","parameters":{"properties":{"edits":{"description":"Array of edit operations","items":{"properties":{"newText":{"description":"The replacement text","type":"string"},"oldText":{"description":"The exact text to replace","type":"string"}},"required":["oldText","newText"],"type":"object"},"type":"array"},"path":{"description":"The file path to edit","type":"string"}},"required":["path","edits"],"type":"object"}},{"description":"Get a detailed listing of all files and directories in a specified path.","name":"list_directory","parameters":{"properties":{"path":{"description":"The directory path to list","type":"string"}},"required":["path"],"type":"object"}},{"description":"Read the complete contents of a file from the file system.","name":"read_file","parameters":{"properties":{"path":{"description":"The file path to read","type":"string"}},"required":["path"],"type":"object"}},{"description":"Read the contents of multiple files simultaneously.","name":"read_multiple_files","parameters":{"properties":{"json":{"description":"Whether to return the result as JSON","type":"boolean"},"paths":{"description":"Array of file paths to read","items":{"type":"string"},"type":"array"}},"required":["paths"],"type":"object"}},{"description":"Searches for text or regex patterns in the content of files matching a GLOB pattern.","name":"search_files_content","parameters":{"properties":{"excludePatterns":{"description":"Patterns to exclude from search","items":{"type":"string"},"type":"array"},"is_regex":{"description":"If true, treat query as regex; otherwise literal text","type":"boolean"},"path":{"description":"The starting directory path","type":"string"},"query":{"description":"The text or regex pattern to search for","type":"string"}},"required":["path","query"],"type":"object"}},{"description":"Create a new file or completely overwrite an existing file with new content.","name":"write_file","parameters":{"properties":{"content":{"description":"The content to write to the file","type":"string"},"path":{"description":"The file path to write","type":"string"}},"required":["path","content"],"type":"object"}}]}]} + {"contents":[{"parts":[{"text":"You are a knowledgeable assistant that helps users with various tasks.\nBe helpful, accurate, and concise in your responses.\n"}],"role":"user"},{"parts":[{"text":"## Filesystem Tool Instructions\n\nThis toolset provides comprehensive filesystem operations.\n\n### Working Directory\n- Relative paths (like \".\" or \"src/main.go\") are resolved relative to the working directory\n- Absolute paths (like \"/etc/hosts\") access files directly\n- Paths starting with \"..\" can access parent directories\n\n### Common Patterns\n- Always check if directories exist before creating files\n- Prefer read_multiple_files for batch operations\n- Use search_files_content for finding specific code or text\n\n### Performance Tips\n- Use read_multiple_files instead of multiple read_file calls\n- Use directory_tree with max_depth to limit large traversals\n- Use appropriate exclude patterns in search operations\n\n### Reading Large Files\n- read_file and read_multiple_files support offset and line_count parameters for pagination\n- When a file is large, read it in chunks: start with offset=1 and a reasonable line_count\n- The response includes total_lines so you know how many more lines remain\n- Continue reading with an incremented offset until you have read all required content"}],"role":"user"},{"parts":[{"text":"How many files in testdata/working_dir? Only output the number."}],"role":"user"}],"generationConfig":{},"toolConfig":{"functionCallingConfig":{"mode":"AUTO"}},"tools":[{"functionDeclarations":[{"description":"Get a recursive tree view of files and directories as a JSON structure.","name":"directory_tree","parameters":{"properties":{"path":{"description":"The directory path to traverse (relative to working directory)","type":"string"}},"required":["path"],"type":"object"}},{"description":"Make line-based edits to a text file. Each edit replaces exact line sequences with new content.","name":"edit_file","parameters":{"properties":{"edits":{"description":"Array of edit operations","items":{"properties":{"newText":{"description":"The replacement text","type":"string"},"oldText":{"description":"The exact text to replace","type":"string"}},"required":["oldText","newText"],"type":"object"},"type":"array"},"path":{"description":"The file path to edit","type":"string"}},"required":["path","edits"],"type":"object"}},{"description":"Get a detailed listing of all files and directories in a specified path.","name":"list_directory","parameters":{"properties":{"path":{"description":"The directory path to list","type":"string"}},"required":["path"],"type":"object"}},{"description":"Read the contents of a file from the file system.","name":"read_file","parameters":{"properties":{"line_count":{"description":"Maximum number of lines to return (default: all remaining lines)","type":"integer"},"offset":{"description":"1-based line number to start reading from (default: 1)","type":"integer"},"path":{"description":"The file path to read","type":"string"}},"required":["path"],"type":"object"}},{"description":"Read the contents of multiple files simultaneously.","name":"read_multiple_files","parameters":{"properties":{"json":{"description":"Whether to return the result as JSON","type":"boolean"},"line_count":{"description":"Maximum number of lines to return per file (default: all remaining lines)","type":"integer"},"offset":{"description":"1-based line number to start reading from, applied to all files (default: 1)","type":"integer"},"paths":{"description":"Array of file paths to read","items":{"type":"string"},"type":"array"}},"required":["paths"],"type":"object"}},{"description":"Searches for text or regex patterns in the content of files matching a GLOB pattern.","name":"search_files_content","parameters":{"properties":{"excludePatterns":{"description":"Patterns to exclude from search","items":{"type":"string"},"type":"array"},"is_regex":{"description":"If true, treat query as regex; otherwise literal text","type":"boolean"},"path":{"description":"The starting directory path","type":"string"},"query":{"description":"The text or regex pattern to search for","type":"string"}},"required":["path","query"],"type":"object"}},{"description":"Create a new file or completely overwrite an existing file with new content.","name":"write_file","parameters":{"properties":{"content":{"description":"The content to write to the file","type":"string"},"path":{"description":"The file path to write","type":"string"}},"required":["path","content"],"type":"object"}}]}]} form: alt: - sse @@ -33,7 +33,7 @@ interactions: content_length: 0 host: generativelanguage.googleapis.com body: | - {"contents":[{"parts":[{"text":"You are a knowledgeable assistant that helps users with various tasks.\nBe helpful, accurate, and concise in your responses.\n"}],"role":"user"},{"parts":[{"text":"## Filesystem Tool Instructions\n\nThis toolset provides comprehensive filesystem operations.\n\n### Working Directory\n- Relative paths (like \".\" or \"src/main.go\") are resolved relative to the working directory\n- Absolute paths (like \"/etc/hosts\") access files directly\n- Paths starting with \"..\" can access parent directories\n\n### Common Patterns\n- Always check if directories exist before creating files\n- Prefer read_multiple_files for batch operations\n- Use search_files_content for finding specific code or text\n\n### Performance Tips\n- Use read_multiple_files instead of multiple read_file calls\n- Use directory_tree with max_depth to limit large traversals\n- Use appropriate exclude patterns in search operations"}],"role":"user"},{"parts":[{"text":"How many files in testdata/working_dir? Only output the number."}],"role":"user"},{"parts":[{"functionCall":{"args":{"path":"testdata/working_dir"},"name":"list_directory"},"thoughtSignature":"CiQBcsjafMGuAqvsBDG58t91BS0jdQCVmj82BAGhSeduON/zWekKYgFyyNp8msXzfYDBKOEyeEzNR8Gbcah0mXk3cjfrZxK/PzX3JobM72PLCha6j8JmjIKT/GrvEvm1UELCv94iDJcN+CfsFa8Nml+++DbLexS1TLRvRaKxHHM1NNrHvR5THsxtCtEBAXLI2nxjociaq+7MxUltbFjcIsKbqq9zQmmlB7/vE5JzCpgYxXAzI4L10dfs209ufBy1iK81bspBUAeAl+lhOUGvIBaLmha+v0g/w2xx+Qju5M36RLuo8se2ChZ6bztfAmC5y1uIByvjJmmYoKEWNYU1t1GxyzPNU/qZ1UtsDccPB2eAsBo+FsA63Nqsj6eV2tU99ErjHPP1hcE1m6Xbg3tAdyd8WxKYDeESYnXx4qiNOEiq1gRThcQcb3AwIzh4aIQwPjnxzzrc7EVpOEp+b94="}],"role":"model"},{"parts":[{"functionResponse":{"name":"call_cf745b87-8b05-45bb-9b07-489204d82f21","response":{"result":"FILE README.me\n"}}}],"role":"user"}],"generationConfig":{},"toolConfig":{"functionCallingConfig":{"mode":"AUTO"}},"tools":[{"functionDeclarations":[{"description":"Get a recursive tree view of files and directories as a JSON structure.","name":"directory_tree","parameters":{"properties":{"path":{"description":"The directory path to traverse (relative to working directory)","type":"string"}},"required":["path"],"type":"object"}},{"description":"Make line-based edits to a text file. Each edit replaces exact line sequences with new content.","name":"edit_file","parameters":{"properties":{"edits":{"description":"Array of edit operations","items":{"properties":{"newText":{"description":"The replacement text","type":"string"},"oldText":{"description":"The exact text to replace","type":"string"}},"required":["oldText","newText"],"type":"object"},"type":"array"},"path":{"description":"The file path to edit","type":"string"}},"required":["path","edits"],"type":"object"}},{"description":"Get a detailed listing of all files and directories in a specified path.","name":"list_directory","parameters":{"properties":{"path":{"description":"The directory path to list","type":"string"}},"required":["path"],"type":"object"}},{"description":"Read the complete contents of a file from the file system.","name":"read_file","parameters":{"properties":{"path":{"description":"The file path to read","type":"string"}},"required":["path"],"type":"object"}},{"description":"Read the contents of multiple files simultaneously.","name":"read_multiple_files","parameters":{"properties":{"json":{"description":"Whether to return the result as JSON","type":"boolean"},"paths":{"description":"Array of file paths to read","items":{"type":"string"},"type":"array"}},"required":["paths"],"type":"object"}},{"description":"Searches for text or regex patterns in the content of files matching a GLOB pattern.","name":"search_files_content","parameters":{"properties":{"excludePatterns":{"description":"Patterns to exclude from search","items":{"type":"string"},"type":"array"},"is_regex":{"description":"If true, treat query as regex; otherwise literal text","type":"boolean"},"path":{"description":"The starting directory path","type":"string"},"query":{"description":"The text or regex pattern to search for","type":"string"}},"required":["path","query"],"type":"object"}},{"description":"Create a new file or completely overwrite an existing file with new content.","name":"write_file","parameters":{"properties":{"content":{"description":"The content to write to the file","type":"string"},"path":{"description":"The file path to write","type":"string"}},"required":["path","content"],"type":"object"}}]}]} + {"contents":[{"parts":[{"text":"You are a knowledgeable assistant that helps users with various tasks.\nBe helpful, accurate, and concise in your responses.\n"}],"role":"user"},{"parts":[{"text":"## Filesystem Tool Instructions\n\nThis toolset provides comprehensive filesystem operations.\n\n### Working Directory\n- Relative paths (like \".\" or \"src/main.go\") are resolved relative to the working directory\n- Absolute paths (like \"/etc/hosts\") access files directly\n- Paths starting with \"..\" can access parent directories\n\n### Common Patterns\n- Always check if directories exist before creating files\n- Prefer read_multiple_files for batch operations\n- Use search_files_content for finding specific code or text\n\n### Performance Tips\n- Use read_multiple_files instead of multiple read_file calls\n- Use directory_tree with max_depth to limit large traversals\n- Use appropriate exclude patterns in search operations\n\n### Reading Large Files\n- read_file and read_multiple_files support offset and line_count parameters for pagination\n- When a file is large, read it in chunks: start with offset=1 and a reasonable line_count\n- The response includes total_lines so you know how many more lines remain\n- Continue reading with an incremented offset until you have read all required content"}],"role":"user"},{"parts":[{"text":"How many files in testdata/working_dir? Only output the number."}],"role":"user"},{"parts":[{"functionCall":{"args":{"path":"testdata/working_dir"},"name":"list_directory"},"thoughtSignature":"CiQBcsjafMGuAqvsBDG58t91BS0jdQCVmj82BAGhSeduON/zWekKYgFyyNp8msXzfYDBKOEyeEzNR8Gbcah0mXk3cjfrZxK/PzX3JobM72PLCha6j8JmjIKT/GrvEvm1UELCv94iDJcN+CfsFa8Nml+++DbLexS1TLRvRaKxHHM1NNrHvR5THsxtCtEBAXLI2nxjociaq+7MxUltbFjcIsKbqq9zQmmlB7/vE5JzCpgYxXAzI4L10dfs209ufBy1iK81bspBUAeAl+lhOUGvIBaLmha+v0g/w2xx+Qju5M36RLuo8se2ChZ6bztfAmC5y1uIByvjJmmYoKEWNYU1t1GxyzPNU/qZ1UtsDccPB2eAsBo+FsA63Nqsj6eV2tU99ErjHPP1hcE1m6Xbg3tAdyd8WxKYDeESYnXx4qiNOEiq1gRThcQcb3AwIzh4aIQwPjnxzzrc7EVpOEp+b94="}],"role":"model"},{"parts":[{"functionResponse":{"name":"call_cf745b87-8b05-45bb-9b07-489204d82f21","response":{"result":"FILE README.me\n"}}}],"role":"user"}],"generationConfig":{},"toolConfig":{"functionCallingConfig":{"mode":"AUTO"}},"tools":[{"functionDeclarations":[{"description":"Get a recursive tree view of files and directories as a JSON structure.","name":"directory_tree","parameters":{"properties":{"path":{"description":"The directory path to traverse (relative to working directory)","type":"string"}},"required":["path"],"type":"object"}},{"description":"Make line-based edits to a text file. Each edit replaces exact line sequences with new content.","name":"edit_file","parameters":{"properties":{"edits":{"description":"Array of edit operations","items":{"properties":{"newText":{"description":"The replacement text","type":"string"},"oldText":{"description":"The exact text to replace","type":"string"}},"required":["oldText","newText"],"type":"object"},"type":"array"},"path":{"description":"The file path to edit","type":"string"}},"required":["path","edits"],"type":"object"}},{"description":"Get a detailed listing of all files and directories in a specified path.","name":"list_directory","parameters":{"properties":{"path":{"description":"The directory path to list","type":"string"}},"required":["path"],"type":"object"}},{"description":"Read the contents of a file from the file system.","name":"read_file","parameters":{"properties":{"line_count":{"description":"Maximum number of lines to return (default: all remaining lines)","type":"integer"},"offset":{"description":"1-based line number to start reading from (default: 1)","type":"integer"},"path":{"description":"The file path to read","type":"string"}},"required":["path"],"type":"object"}},{"description":"Read the contents of multiple files simultaneously.","name":"read_multiple_files","parameters":{"properties":{"json":{"description":"Whether to return the result as JSON","type":"boolean"},"line_count":{"description":"Maximum number of lines to return per file (default: all remaining lines)","type":"integer"},"offset":{"description":"1-based line number to start reading from, applied to all files (default: 1)","type":"integer"},"paths":{"description":"Array of file paths to read","items":{"type":"string"},"type":"array"}},"required":["paths"],"type":"object"}},{"description":"Searches for text or regex patterns in the content of files matching a GLOB pattern.","name":"search_files_content","parameters":{"properties":{"excludePatterns":{"description":"Patterns to exclude from search","items":{"type":"string"},"type":"array"},"is_regex":{"description":"If true, treat query as regex; otherwise literal text","type":"boolean"},"path":{"description":"The starting directory path","type":"string"},"query":{"description":"The text or regex pattern to search for","type":"string"}},"required":["path","query"],"type":"object"}},{"description":"Create a new file or completely overwrite an existing file with new content.","name":"write_file","parameters":{"properties":{"content":{"description":"The content to write to the file","type":"string"},"path":{"description":"The file path to write","type":"string"}},"required":["path","content"],"type":"object"}}]}]} form: alt: - sse diff --git a/e2e/testdata/cassettes/TestExec_Mistral_ToolCall.yaml b/e2e/testdata/cassettes/TestExec_Mistral_ToolCall.yaml index 7cdec25e1..06ad72626 100644 --- a/e2e/testdata/cassettes/TestExec_Mistral_ToolCall.yaml +++ b/e2e/testdata/cassettes/TestExec_Mistral_ToolCall.yaml @@ -8,7 +8,7 @@ interactions: proto_minor: 1 content_length: 0 host: api.mistral.ai - body: '{"messages":[{"content":"You are a knowledgeable assistant that helps users with various tasks.\nBe helpful, accurate, and concise in your responses.\n","role":"system"},{"content":"## Filesystem Tool Instructions\n\nThis toolset provides comprehensive filesystem operations.\n\n### Working Directory\n- Relative paths (like \".\" or \"src/main.go\") are resolved relative to the working directory\n- Absolute paths (like \"/etc/hosts\") access files directly\n- Paths starting with \"..\" can access parent directories\n\n### Common Patterns\n- Always check if directories exist before creating files\n- Prefer read_multiple_files for batch operations\n- Use search_files_content for finding specific code or text\n\n### Performance Tips\n- Use read_multiple_files instead of multiple read_file calls\n- Use directory_tree with max_depth to limit large traversals\n- Use appropriate exclude patterns in search operations","role":"system"},{"content":"How many files in testdata/working_dir? Only output the number.","role":"user"}],"model":"mistral-small","max_tokens":32000,"stream_options":{"include_usage":true},"tools":[{"function":{"name":"directory_tree","description":"Get a recursive tree view of files and directories as a JSON structure.","parameters":{"additionalProperties":false,"properties":{"path":{"description":"The directory path to traverse (relative to working directory)","type":"string"}},"required":["path"],"type":"object"}},"type":"function"},{"function":{"name":"edit_file","description":"Make line-based edits to a text file. Each edit replaces exact line sequences with new content.","parameters":{"additionalProperties":false,"properties":{"edits":{"description":"Array of edit operations","items":{"additionalProperties":false,"properties":{"newText":{"description":"The replacement text","type":"string"},"oldText":{"description":"The exact text to replace","type":"string"}},"required":["newText","oldText"],"type":"object"},"type":["null","array"]},"path":{"description":"The file path to edit","type":"string"}},"required":["edits","path"],"type":"object"}},"type":"function"},{"function":{"name":"list_directory","description":"Get a detailed listing of all files and directories in a specified path.","parameters":{"additionalProperties":false,"properties":{"path":{"description":"The directory path to list","type":"string"}},"required":["path"],"type":"object"}},"type":"function"},{"function":{"name":"read_file","description":"Read the complete contents of a file from the file system.","parameters":{"additionalProperties":false,"properties":{"path":{"description":"The file path to read","type":"string"}},"required":["path"],"type":"object"}},"type":"function"},{"function":{"name":"read_multiple_files","description":"Read the contents of multiple files simultaneously.","parameters":{"additionalProperties":false,"properties":{"json":{"description":"Whether to return the result as JSON","type":["boolean","null"]},"paths":{"description":"Array of file paths to read","items":{"type":"string"},"type":["null","array"]}},"required":["json","paths"],"type":"object"}},"type":"function"},{"function":{"name":"search_files_content","description":"Searches for text or regex patterns in the content of files matching a GLOB pattern.","parameters":{"additionalProperties":false,"properties":{"excludePatterns":{"description":"Patterns to exclude from search","items":{"type":"string"},"type":["null","array"]},"is_regex":{"description":"If true, treat query as regex; otherwise literal text","type":["boolean","null"]},"path":{"description":"The starting directory path","type":"string"},"query":{"description":"The text or regex pattern to search for","type":"string"}},"required":["excludePatterns","is_regex","path","query"],"type":"object"}},"type":"function"},{"function":{"name":"write_file","description":"Create a new file or completely overwrite an existing file with new content.","parameters":{"additionalProperties":false,"properties":{"content":{"description":"The content to write to the file","type":"string"},"path":{"description":"The file path to write","type":"string"}},"required":["content","path"],"type":"object"}},"type":"function"}],"stream":true}' + body: '{"messages":[{"content":"You are a knowledgeable assistant that helps users with various tasks.\nBe helpful, accurate, and concise in your responses.\n","role":"system"},{"content":"## Filesystem Tool Instructions\n\nThis toolset provides comprehensive filesystem operations.\n\n### Working Directory\n- Relative paths (like \".\" or \"src/main.go\") are resolved relative to the working directory\n- Absolute paths (like \"/etc/hosts\") access files directly\n- Paths starting with \"..\" can access parent directories\n\n### Common Patterns\n- Always check if directories exist before creating files\n- Prefer read_multiple_files for batch operations\n- Use search_files_content for finding specific code or text\n\n### Performance Tips\n- Use read_multiple_files instead of multiple read_file calls\n- Use directory_tree with max_depth to limit large traversals\n- Use appropriate exclude patterns in search operations\n\n### Reading Large Files\n- read_file and read_multiple_files support offset and line_count parameters for pagination\n- When a file is large, read it in chunks: start with offset=1 and a reasonable line_count\n- The response includes total_lines so you know how many more lines remain\n- Continue reading with an incremented offset until you have read all required content","role":"system"},{"content":"How many files in testdata/working_dir? Only output the number.","role":"user"}],"model":"mistral-small","max_tokens":32000,"stream_options":{"include_usage":true},"tools":[{"function":{"name":"directory_tree","description":"Get a recursive tree view of files and directories as a JSON structure.","parameters":{"additionalProperties":false,"properties":{"path":{"description":"The directory path to traverse (relative to working directory)","type":"string"}},"required":["path"],"type":"object"}},"type":"function"},{"function":{"name":"edit_file","description":"Make line-based edits to a text file. Each edit replaces exact line sequences with new content.","parameters":{"additionalProperties":false,"properties":{"edits":{"description":"Array of edit operations","items":{"additionalProperties":false,"properties":{"newText":{"description":"The replacement text","type":"string"},"oldText":{"description":"The exact text to replace","type":"string"}},"required":["newText","oldText"],"type":"object"},"type":["null","array"]},"path":{"description":"The file path to edit","type":"string"}},"required":["edits","path"],"type":"object"}},"type":"function"},{"function":{"name":"list_directory","description":"Get a detailed listing of all files and directories in a specified path.","parameters":{"additionalProperties":false,"properties":{"path":{"description":"The directory path to list","type":"string"}},"required":["path"],"type":"object"}},"type":"function"},{"function":{"name":"read_file","description":"Read the contents of a file from the file system.","parameters":{"additionalProperties":false,"properties":{"line_count":{"description":"Maximum number of lines to return (default: all remaining lines)","type":["integer","null"]},"offset":{"description":"1-based line number to start reading from (default: 1)","type":["integer","null"]},"path":{"description":"The file path to read","type":"string"}},"required":["line_count","offset","path"],"type":"object"}},"type":"function"},{"function":{"name":"read_multiple_files","description":"Read the contents of multiple files simultaneously.","parameters":{"additionalProperties":false,"properties":{"json":{"description":"Whether to return the result as JSON","type":["boolean","null"]},"line_count":{"description":"Maximum number of lines to return per file (default: all remaining lines)","type":["integer","null"]},"offset":{"description":"1-based line number to start reading from, applied to all files (default: 1)","type":["integer","null"]},"paths":{"description":"Array of file paths to read","items":{"type":"string"},"type":["null","array"]}},"required":["json","line_count","offset","paths"],"type":"object"}},"type":"function"},{"function":{"name":"search_files_content","description":"Searches for text or regex patterns in the content of files matching a GLOB pattern.","parameters":{"additionalProperties":false,"properties":{"excludePatterns":{"description":"Patterns to exclude from search","items":{"type":"string"},"type":["null","array"]},"is_regex":{"description":"If true, treat query as regex; otherwise literal text","type":["boolean","null"]},"path":{"description":"The starting directory path","type":"string"},"query":{"description":"The text or regex pattern to search for","type":"string"}},"required":["excludePatterns","is_regex","path","query"],"type":"object"}},"type":"function"},{"function":{"name":"write_file","description":"Create a new file or completely overwrite an existing file with new content.","parameters":{"additionalProperties":false,"properties":{"content":{"description":"The content to write to the file","type":"string"},"path":{"description":"The file path to write","type":"string"}},"required":["content","path"],"type":"object"}},"type":"function"}],"stream":true}' url: https://api.mistral.ai/v1/chat/completions method: POST response: @@ -34,7 +34,7 @@ interactions: proto_minor: 1 content_length: 0 host: api.mistral.ai - body: '{"messages":[{"content":"You are a knowledgeable assistant that helps users with various tasks.\nBe helpful, accurate, and concise in your responses.\n","role":"system"},{"content":"## Filesystem Tool Instructions\n\nThis toolset provides comprehensive filesystem operations.\n\n### Working Directory\n- Relative paths (like \".\" or \"src/main.go\") are resolved relative to the working directory\n- Absolute paths (like \"/etc/hosts\") access files directly\n- Paths starting with \"..\" can access parent directories\n\n### Common Patterns\n- Always check if directories exist before creating files\n- Prefer read_multiple_files for batch operations\n- Use search_files_content for finding specific code or text\n\n### Performance Tips\n- Use read_multiple_files instead of multiple read_file calls\n- Use directory_tree with max_depth to limit large traversals\n- Use appropriate exclude patterns in search operations","role":"system"},{"content":"How many files in testdata/working_dir? Only output the number.","role":"user"},{"tool_calls":[{"id":"j5EBzKUla","function":{"arguments":"{\"path\": \"testdata/working_dir\"}","name":"list_directory"},"type":"function"}],"role":"assistant"},{"content":"FILE README.me\n","tool_call_id":"j5EBzKUla","role":"tool"}],"model":"mistral-small","max_tokens":32000,"stream_options":{"include_usage":true},"tools":[{"function":{"name":"directory_tree","description":"Get a recursive tree view of files and directories as a JSON structure.","parameters":{"additionalProperties":false,"properties":{"path":{"description":"The directory path to traverse (relative to working directory)","type":"string"}},"required":["path"],"type":"object"}},"type":"function"},{"function":{"name":"edit_file","description":"Make line-based edits to a text file. Each edit replaces exact line sequences with new content.","parameters":{"additionalProperties":false,"properties":{"edits":{"description":"Array of edit operations","items":{"additionalProperties":false,"properties":{"newText":{"description":"The replacement text","type":"string"},"oldText":{"description":"The exact text to replace","type":"string"}},"required":["newText","oldText"],"type":"object"},"type":["null","array"]},"path":{"description":"The file path to edit","type":"string"}},"required":["edits","path"],"type":"object"}},"type":"function"},{"function":{"name":"list_directory","description":"Get a detailed listing of all files and directories in a specified path.","parameters":{"additionalProperties":false,"properties":{"path":{"description":"The directory path to list","type":"string"}},"required":["path"],"type":"object"}},"type":"function"},{"function":{"name":"read_file","description":"Read the complete contents of a file from the file system.","parameters":{"additionalProperties":false,"properties":{"path":{"description":"The file path to read","type":"string"}},"required":["path"],"type":"object"}},"type":"function"},{"function":{"name":"read_multiple_files","description":"Read the contents of multiple files simultaneously.","parameters":{"additionalProperties":false,"properties":{"json":{"description":"Whether to return the result as JSON","type":["boolean","null"]},"paths":{"description":"Array of file paths to read","items":{"type":"string"},"type":["null","array"]}},"required":["json","paths"],"type":"object"}},"type":"function"},{"function":{"name":"search_files_content","description":"Searches for text or regex patterns in the content of files matching a GLOB pattern.","parameters":{"additionalProperties":false,"properties":{"excludePatterns":{"description":"Patterns to exclude from search","items":{"type":"string"},"type":["null","array"]},"is_regex":{"description":"If true, treat query as regex; otherwise literal text","type":["boolean","null"]},"path":{"description":"The starting directory path","type":"string"},"query":{"description":"The text or regex pattern to search for","type":"string"}},"required":["excludePatterns","is_regex","path","query"],"type":"object"}},"type":"function"},{"function":{"name":"write_file","description":"Create a new file or completely overwrite an existing file with new content.","parameters":{"additionalProperties":false,"properties":{"content":{"description":"The content to write to the file","type":"string"},"path":{"description":"The file path to write","type":"string"}},"required":["content","path"],"type":"object"}},"type":"function"}],"stream":true}' + body: '{"messages":[{"content":"You are a knowledgeable assistant that helps users with various tasks.\nBe helpful, accurate, and concise in your responses.\n","role":"system"},{"content":"## Filesystem Tool Instructions\n\nThis toolset provides comprehensive filesystem operations.\n\n### Working Directory\n- Relative paths (like \".\" or \"src/main.go\") are resolved relative to the working directory\n- Absolute paths (like \"/etc/hosts\") access files directly\n- Paths starting with \"..\" can access parent directories\n\n### Common Patterns\n- Always check if directories exist before creating files\n- Prefer read_multiple_files for batch operations\n- Use search_files_content for finding specific code or text\n\n### Performance Tips\n- Use read_multiple_files instead of multiple read_file calls\n- Use directory_tree with max_depth to limit large traversals\n- Use appropriate exclude patterns in search operations\n\n### Reading Large Files\n- read_file and read_multiple_files support offset and line_count parameters for pagination\n- When a file is large, read it in chunks: start with offset=1 and a reasonable line_count\n- The response includes total_lines so you know how many more lines remain\n- Continue reading with an incremented offset until you have read all required content","role":"system"},{"content":"How many files in testdata/working_dir? Only output the number.","role":"user"},{"tool_calls":[{"id":"j5EBzKUla","function":{"arguments":"{\"path\": \"testdata/working_dir\"}","name":"list_directory"},"type":"function"}],"role":"assistant"},{"content":"FILE README.me\n","tool_call_id":"j5EBzKUla","role":"tool"}],"model":"mistral-small","max_tokens":32000,"stream_options":{"include_usage":true},"tools":[{"function":{"name":"directory_tree","description":"Get a recursive tree view of files and directories as a JSON structure.","parameters":{"additionalProperties":false,"properties":{"path":{"description":"The directory path to traverse (relative to working directory)","type":"string"}},"required":["path"],"type":"object"}},"type":"function"},{"function":{"name":"edit_file","description":"Make line-based edits to a text file. Each edit replaces exact line sequences with new content.","parameters":{"additionalProperties":false,"properties":{"edits":{"description":"Array of edit operations","items":{"additionalProperties":false,"properties":{"newText":{"description":"The replacement text","type":"string"},"oldText":{"description":"The exact text to replace","type":"string"}},"required":["newText","oldText"],"type":"object"},"type":["null","array"]},"path":{"description":"The file path to edit","type":"string"}},"required":["edits","path"],"type":"object"}},"type":"function"},{"function":{"name":"list_directory","description":"Get a detailed listing of all files and directories in a specified path.","parameters":{"additionalProperties":false,"properties":{"path":{"description":"The directory path to list","type":"string"}},"required":["path"],"type":"object"}},"type":"function"},{"function":{"name":"read_file","description":"Read the contents of a file from the file system.","parameters":{"additionalProperties":false,"properties":{"line_count":{"description":"Maximum number of lines to return (default: all remaining lines)","type":["integer","null"]},"offset":{"description":"1-based line number to start reading from (default: 1)","type":["integer","null"]},"path":{"description":"The file path to read","type":"string"}},"required":["line_count","offset","path"],"type":"object"}},"type":"function"},{"function":{"name":"read_multiple_files","description":"Read the contents of multiple files simultaneously.","parameters":{"additionalProperties":false,"properties":{"json":{"description":"Whether to return the result as JSON","type":["boolean","null"]},"line_count":{"description":"Maximum number of lines to return per file (default: all remaining lines)","type":["integer","null"]},"offset":{"description":"1-based line number to start reading from, applied to all files (default: 1)","type":["integer","null"]},"paths":{"description":"Array of file paths to read","items":{"type":"string"},"type":["null","array"]}},"required":["json","line_count","offset","paths"],"type":"object"}},"type":"function"},{"function":{"name":"search_files_content","description":"Searches for text or regex patterns in the content of files matching a GLOB pattern.","parameters":{"additionalProperties":false,"properties":{"excludePatterns":{"description":"Patterns to exclude from search","items":{"type":"string"},"type":["null","array"]},"is_regex":{"description":"If true, treat query as regex; otherwise literal text","type":["boolean","null"]},"path":{"description":"The starting directory path","type":"string"},"query":{"description":"The text or regex pattern to search for","type":"string"}},"required":["excludePatterns","is_regex","path","query"],"type":"object"}},"type":"function"},{"function":{"name":"write_file","description":"Create a new file or completely overwrite an existing file with new content.","parameters":{"additionalProperties":false,"properties":{"content":{"description":"The content to write to the file","type":"string"},"path":{"description":"The file path to write","type":"string"}},"required":["content","path"],"type":"object"}},"type":"function"}],"stream":true}' url: https://api.mistral.ai/v1/chat/completions method: POST response: diff --git a/e2e/testdata/cassettes/TestExec_OpenAI_HideToolCalls.yaml b/e2e/testdata/cassettes/TestExec_OpenAI_HideToolCalls.yaml index c08cd2d8f..80688a7a7 100644 --- a/e2e/testdata/cassettes/TestExec_OpenAI_HideToolCalls.yaml +++ b/e2e/testdata/cassettes/TestExec_OpenAI_HideToolCalls.yaml @@ -8,7 +8,7 @@ interactions: proto_minor: 1 content_length: 0 host: api.openai.com - body: '{"messages":[{"content":"You are a knowledgeable assistant that helps users with various tasks.\nBe helpful, accurate, and concise in your responses.\n","role":"system"},{"content":"## Filesystem Tool Instructions\n\nThis toolset provides comprehensive filesystem operations.\n\n### Working Directory\n- Relative paths (like \".\" or \"src/main.go\") are resolved relative to the working directory\n- Absolute paths (like \"/etc/hosts\") access files directly\n- Paths starting with \"..\" can access parent directories\n\n### Common Patterns\n- Always check if directories exist before creating files\n- Prefer read_multiple_files for batch operations\n- Use search_files_content for finding specific code or text\n\n### Performance Tips\n- Use read_multiple_files instead of multiple read_file calls\n- Use directory_tree with max_depth to limit large traversals\n- Use appropriate exclude patterns in search operations","role":"system"},{"content":"How many files in testdata/working_dir? Only output the number.","role":"user"}],"model":"gpt-4o","max_tokens":16384,"stream_options":{"include_usage":true},"tools":[{"function":{"name":"directory_tree","description":"Get a recursive tree view of files and directories as a JSON structure.","parameters":{"additionalProperties":false,"properties":{"path":{"description":"The directory path to traverse (relative to working directory)","type":"string"}},"required":["path"],"type":"object"}},"type":"function"},{"function":{"name":"edit_file","description":"Make line-based edits to a text file. Each edit replaces exact line sequences with new content.","parameters":{"additionalProperties":false,"properties":{"edits":{"description":"Array of edit operations","items":{"additionalProperties":false,"properties":{"newText":{"description":"The replacement text","type":"string"},"oldText":{"description":"The exact text to replace","type":"string"}},"required":["newText","oldText"],"type":"object"},"type":["null","array"]},"path":{"description":"The file path to edit","type":"string"}},"required":["edits","path"],"type":"object"}},"type":"function"},{"function":{"name":"list_directory","description":"Get a detailed listing of all files and directories in a specified path.","parameters":{"additionalProperties":false,"properties":{"path":{"description":"The directory path to list","type":"string"}},"required":["path"],"type":"object"}},"type":"function"},{"function":{"name":"read_file","description":"Read the complete contents of a file from the file system.","parameters":{"additionalProperties":false,"properties":{"path":{"description":"The file path to read","type":"string"}},"required":["path"],"type":"object"}},"type":"function"},{"function":{"name":"read_multiple_files","description":"Read the contents of multiple files simultaneously.","parameters":{"additionalProperties":false,"properties":{"json":{"description":"Whether to return the result as JSON","type":["boolean","null"]},"paths":{"description":"Array of file paths to read","items":{"type":"string"},"type":["null","array"]}},"required":["json","paths"],"type":"object"}},"type":"function"},{"function":{"name":"search_files_content","description":"Searches for text or regex patterns in the content of files matching a GLOB pattern.","parameters":{"additionalProperties":false,"properties":{"excludePatterns":{"description":"Patterns to exclude from search","items":{"type":"string"},"type":["null","array"]},"is_regex":{"description":"If true, treat query as regex; otherwise literal text","type":["boolean","null"]},"path":{"description":"The starting directory path","type":"string"},"query":{"description":"The text or regex pattern to search for","type":"string"}},"required":["excludePatterns","is_regex","path","query"],"type":"object"}},"type":"function"},{"function":{"name":"write_file","description":"Create a new file or completely overwrite an existing file with new content.","parameters":{"additionalProperties":false,"properties":{"content":{"description":"The content to write to the file","type":"string"},"path":{"description":"The file path to write","type":"string"}},"required":["content","path"],"type":"object"}},"type":"function"}],"stream":true}' + body: '{"messages":[{"content":"You are a knowledgeable assistant that helps users with various tasks.\nBe helpful, accurate, and concise in your responses.\n","role":"system"},{"content":"## Filesystem Tool Instructions\n\nThis toolset provides comprehensive filesystem operations.\n\n### Working Directory\n- Relative paths (like \".\" or \"src/main.go\") are resolved relative to the working directory\n- Absolute paths (like \"/etc/hosts\") access files directly\n- Paths starting with \"..\" can access parent directories\n\n### Common Patterns\n- Always check if directories exist before creating files\n- Prefer read_multiple_files for batch operations\n- Use search_files_content for finding specific code or text\n\n### Performance Tips\n- Use read_multiple_files instead of multiple read_file calls\n- Use directory_tree with max_depth to limit large traversals\n- Use appropriate exclude patterns in search operations\n\n### Reading Large Files\n- read_file and read_multiple_files support offset and line_count parameters for pagination\n- When a file is large, read it in chunks: start with offset=1 and a reasonable line_count\n- The response includes total_lines so you know how many more lines remain\n- Continue reading with an incremented offset until you have read all required content","role":"system"},{"content":"How many files in testdata/working_dir? Only output the number.","role":"user"}],"model":"gpt-4o","max_tokens":16384,"stream_options":{"include_usage":true},"tools":[{"function":{"name":"directory_tree","description":"Get a recursive tree view of files and directories as a JSON structure.","parameters":{"additionalProperties":false,"properties":{"path":{"description":"The directory path to traverse (relative to working directory)","type":"string"}},"required":["path"],"type":"object"}},"type":"function"},{"function":{"name":"edit_file","description":"Make line-based edits to a text file. Each edit replaces exact line sequences with new content.","parameters":{"additionalProperties":false,"properties":{"edits":{"description":"Array of edit operations","items":{"additionalProperties":false,"properties":{"newText":{"description":"The replacement text","type":"string"},"oldText":{"description":"The exact text to replace","type":"string"}},"required":["newText","oldText"],"type":"object"},"type":["null","array"]},"path":{"description":"The file path to edit","type":"string"}},"required":["edits","path"],"type":"object"}},"type":"function"},{"function":{"name":"list_directory","description":"Get a detailed listing of all files and directories in a specified path.","parameters":{"additionalProperties":false,"properties":{"path":{"description":"The directory path to list","type":"string"}},"required":["path"],"type":"object"}},"type":"function"},{"function":{"name":"read_file","description":"Read the contents of a file from the file system.","parameters":{"additionalProperties":false,"properties":{"line_count":{"description":"Maximum number of lines to return (default: all remaining lines)","type":["integer","null"]},"offset":{"description":"1-based line number to start reading from (default: 1)","type":["integer","null"]},"path":{"description":"The file path to read","type":"string"}},"required":["line_count","offset","path"],"type":"object"}},"type":"function"},{"function":{"name":"read_multiple_files","description":"Read the contents of multiple files simultaneously.","parameters":{"additionalProperties":false,"properties":{"json":{"description":"Whether to return the result as JSON","type":["boolean","null"]},"line_count":{"description":"Maximum number of lines to return per file (default: all remaining lines)","type":["integer","null"]},"offset":{"description":"1-based line number to start reading from, applied to all files (default: 1)","type":["integer","null"]},"paths":{"description":"Array of file paths to read","items":{"type":"string"},"type":["null","array"]}},"required":["json","line_count","offset","paths"],"type":"object"}},"type":"function"},{"function":{"name":"search_files_content","description":"Searches for text or regex patterns in the content of files matching a GLOB pattern.","parameters":{"additionalProperties":false,"properties":{"excludePatterns":{"description":"Patterns to exclude from search","items":{"type":"string"},"type":["null","array"]},"is_regex":{"description":"If true, treat query as regex; otherwise literal text","type":["boolean","null"]},"path":{"description":"The starting directory path","type":"string"},"query":{"description":"The text or regex pattern to search for","type":"string"}},"required":["excludePatterns","is_regex","path","query"],"type":"object"}},"type":"function"},{"function":{"name":"write_file","description":"Create a new file or completely overwrite an existing file with new content.","parameters":{"additionalProperties":false,"properties":{"content":{"description":"The content to write to the file","type":"string"},"path":{"description":"The file path to write","type":"string"}},"required":["content","path"],"type":"object"}},"type":"function"}],"stream":true}' url: https://api.openai.com/v1/chat/completions method: POST response: @@ -17,36 +17,36 @@ interactions: proto_minor: 0 content_length: -1 body: |+ - data: {"id":"chatcmpl-D8pFsmrBRzmoPNjwamdE0NavgIf99","object":"chat.completion.chunk","created":1770996020,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_ad98c18a04","choices":[{"index":0,"delta":{"role":"assistant","content":null,"tool_calls":[{"index":0,"id":"call_45PoYwbnIoUmX0W2kXCQqm9W","type":"function","function":{"name":"list_directory","arguments":""}}],"refusal":null},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"HL2eEa"} + data: {"id":"chatcmpl-DCjR4QljTrYXb0jX8EZQsBei3jHK2","object":"chat.completion.chunk","created":1771926962,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_64dfa806c7","choices":[{"index":0,"delta":{"role":"assistant","content":null,"tool_calls":[{"index":0,"id":"call_8p4SZZruoZHzbVqo3yb3rK61","type":"function","function":{"name":"list_directory","arguments":""}}],"refusal":null},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"7QY5TH"} - data: {"id":"chatcmpl-D8pFsmrBRzmoPNjwamdE0NavgIf99","object":"chat.completion.chunk","created":1770996020,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_ad98c18a04","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"{\""}}]},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"Juz"} + data: {"id":"chatcmpl-DCjR4QljTrYXb0jX8EZQsBei3jHK2","object":"chat.completion.chunk","created":1771926962,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_64dfa806c7","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"{\""}}]},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"C9z"} - data: {"id":"chatcmpl-D8pFsmrBRzmoPNjwamdE0NavgIf99","object":"chat.completion.chunk","created":1770996020,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_ad98c18a04","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"path"}}]},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"EH"} + data: {"id":"chatcmpl-DCjR4QljTrYXb0jX8EZQsBei3jHK2","object":"chat.completion.chunk","created":1771926962,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_64dfa806c7","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"path"}}]},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"Cz"} - data: {"id":"chatcmpl-D8pFsmrBRzmoPNjwamdE0NavgIf99","object":"chat.completion.chunk","created":1770996020,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_ad98c18a04","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"\":\""}}]},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"a"} + data: {"id":"chatcmpl-DCjR4QljTrYXb0jX8EZQsBei3jHK2","object":"chat.completion.chunk","created":1771926962,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_64dfa806c7","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"\":\""}}]},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"F"} - data: {"id":"chatcmpl-D8pFsmrBRzmoPNjwamdE0NavgIf99","object":"chat.completion.chunk","created":1770996020,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_ad98c18a04","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"test"}}]},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"t7"} + data: {"id":"chatcmpl-DCjR4QljTrYXb0jX8EZQsBei3jHK2","object":"chat.completion.chunk","created":1771926962,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_64dfa806c7","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"test"}}]},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"Yw"} - data: {"id":"chatcmpl-D8pFsmrBRzmoPNjwamdE0NavgIf99","object":"chat.completion.chunk","created":1770996020,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_ad98c18a04","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"data"}}]},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"Kg"} + data: {"id":"chatcmpl-DCjR4QljTrYXb0jX8EZQsBei3jHK2","object":"chat.completion.chunk","created":1771926962,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_64dfa806c7","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"data"}}]},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"tP"} - data: {"id":"chatcmpl-D8pFsmrBRzmoPNjwamdE0NavgIf99","object":"chat.completion.chunk","created":1770996020,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_ad98c18a04","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"/"}}]},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"vDLyl"} + data: {"id":"chatcmpl-DCjR4QljTrYXb0jX8EZQsBei3jHK2","object":"chat.completion.chunk","created":1771926962,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_64dfa806c7","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"/"}}]},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"CzHUT"} - data: {"id":"chatcmpl-D8pFsmrBRzmoPNjwamdE0NavgIf99","object":"chat.completion.chunk","created":1770996020,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_ad98c18a04","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"working"}}]},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"ZgLOv9g1bNndkH0"} + data: {"id":"chatcmpl-DCjR4QljTrYXb0jX8EZQsBei3jHK2","object":"chat.completion.chunk","created":1771926962,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_64dfa806c7","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"working"}}]},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"8J20IR0IfJr0maY"} - data: {"id":"chatcmpl-D8pFsmrBRzmoPNjwamdE0NavgIf99","object":"chat.completion.chunk","created":1770996020,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_ad98c18a04","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"_dir"}}]},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"vy"} + data: {"id":"chatcmpl-DCjR4QljTrYXb0jX8EZQsBei3jHK2","object":"chat.completion.chunk","created":1771926962,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_64dfa806c7","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"_dir"}}]},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"3E"} - data: {"id":"chatcmpl-D8pFsmrBRzmoPNjwamdE0NavgIf99","object":"chat.completion.chunk","created":1770996020,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_ad98c18a04","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"\"}"}}]},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"HCM"} + data: {"id":"chatcmpl-DCjR4QljTrYXb0jX8EZQsBei3jHK2","object":"chat.completion.chunk","created":1771926962,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_64dfa806c7","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"\"}"}}]},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"DuU"} - data: {"id":"chatcmpl-D8pFsmrBRzmoPNjwamdE0NavgIf99","object":"chat.completion.chunk","created":1770996020,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_ad98c18a04","choices":[{"index":0,"delta":{},"logprobs":null,"finish_reason":"tool_calls"}],"usage":null,"obfuscation":"ba8F"} + data: {"id":"chatcmpl-DCjR4QljTrYXb0jX8EZQsBei3jHK2","object":"chat.completion.chunk","created":1771926962,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_64dfa806c7","choices":[{"index":0,"delta":{},"logprobs":null,"finish_reason":"tool_calls"}],"usage":null,"obfuscation":"3MV7"} - data: {"id":"chatcmpl-D8pFsmrBRzmoPNjwamdE0NavgIf99","object":"chat.completion.chunk","created":1770996020,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_ad98c18a04","choices":[],"usage":{"prompt_tokens":656,"completion_tokens":18,"total_tokens":674,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0},"completion_tokens_details":{"reasoning_tokens":0,"audio_tokens":0,"accepted_prediction_tokens":0,"rejected_prediction_tokens":0}},"obfuscation":"YFbzavNqvY3KS"} + data: {"id":"chatcmpl-DCjR4QljTrYXb0jX8EZQsBei3jHK2","object":"chat.completion.chunk","created":1771926962,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_64dfa806c7","choices":[],"usage":{"prompt_tokens":961,"completion_tokens":18,"total_tokens":979,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0},"completion_tokens_details":{"reasoning_tokens":0,"audio_tokens":0,"accepted_prediction_tokens":0,"rejected_prediction_tokens":0}},"obfuscation":"lY0u3rzxUI1DX"} data: [DONE] headers: {} status: 200 OK code: 200 - duration: 681.77925ms + duration: 1.0339785s - id: 1 request: proto: HTTP/1.1 @@ -54,7 +54,7 @@ interactions: proto_minor: 1 content_length: 0 host: api.openai.com - body: '{"messages":[{"content":"You are a knowledgeable assistant that helps users with various tasks.\nBe helpful, accurate, and concise in your responses.\n","role":"system"},{"content":"## Filesystem Tool Instructions\n\nThis toolset provides comprehensive filesystem operations.\n\n### Working Directory\n- Relative paths (like \".\" or \"src/main.go\") are resolved relative to the working directory\n- Absolute paths (like \"/etc/hosts\") access files directly\n- Paths starting with \"..\" can access parent directories\n\n### Common Patterns\n- Always check if directories exist before creating files\n- Prefer read_multiple_files for batch operations\n- Use search_files_content for finding specific code or text\n\n### Performance Tips\n- Use read_multiple_files instead of multiple read_file calls\n- Use directory_tree with max_depth to limit large traversals\n- Use appropriate exclude patterns in search operations","role":"system"},{"content":"How many files in testdata/working_dir? Only output the number.","role":"user"},{"tool_calls":[{"id":"call_45PoYwbnIoUmX0W2kXCQqm9W","function":{"arguments":"{\"path\":\"testdata/working_dir\"}","name":"list_directory"},"type":"function"}],"role":"assistant"},{"content":"FILE README.me\n","tool_call_id":"call_45PoYwbnIoUmX0W2kXCQqm9W","role":"tool"}],"model":"gpt-4o","max_tokens":16384,"stream_options":{"include_usage":true},"tools":[{"function":{"name":"directory_tree","description":"Get a recursive tree view of files and directories as a JSON structure.","parameters":{"additionalProperties":false,"properties":{"path":{"description":"The directory path to traverse (relative to working directory)","type":"string"}},"required":["path"],"type":"object"}},"type":"function"},{"function":{"name":"edit_file","description":"Make line-based edits to a text file. Each edit replaces exact line sequences with new content.","parameters":{"additionalProperties":false,"properties":{"edits":{"description":"Array of edit operations","items":{"additionalProperties":false,"properties":{"newText":{"description":"The replacement text","type":"string"},"oldText":{"description":"The exact text to replace","type":"string"}},"required":["newText","oldText"],"type":"object"},"type":["null","array"]},"path":{"description":"The file path to edit","type":"string"}},"required":["edits","path"],"type":"object"}},"type":"function"},{"function":{"name":"list_directory","description":"Get a detailed listing of all files and directories in a specified path.","parameters":{"additionalProperties":false,"properties":{"path":{"description":"The directory path to list","type":"string"}},"required":["path"],"type":"object"}},"type":"function"},{"function":{"name":"read_file","description":"Read the complete contents of a file from the file system.","parameters":{"additionalProperties":false,"properties":{"path":{"description":"The file path to read","type":"string"}},"required":["path"],"type":"object"}},"type":"function"},{"function":{"name":"read_multiple_files","description":"Read the contents of multiple files simultaneously.","parameters":{"additionalProperties":false,"properties":{"json":{"description":"Whether to return the result as JSON","type":["boolean","null"]},"paths":{"description":"Array of file paths to read","items":{"type":"string"},"type":["null","array"]}},"required":["json","paths"],"type":"object"}},"type":"function"},{"function":{"name":"search_files_content","description":"Searches for text or regex patterns in the content of files matching a GLOB pattern.","parameters":{"additionalProperties":false,"properties":{"excludePatterns":{"description":"Patterns to exclude from search","items":{"type":"string"},"type":["null","array"]},"is_regex":{"description":"If true, treat query as regex; otherwise literal text","type":["boolean","null"]},"path":{"description":"The starting directory path","type":"string"},"query":{"description":"The text or regex pattern to search for","type":"string"}},"required":["excludePatterns","is_regex","path","query"],"type":"object"}},"type":"function"},{"function":{"name":"write_file","description":"Create a new file or completely overwrite an existing file with new content.","parameters":{"additionalProperties":false,"properties":{"content":{"description":"The content to write to the file","type":"string"},"path":{"description":"The file path to write","type":"string"}},"required":["content","path"],"type":"object"}},"type":"function"}],"stream":true}' + body: '{"messages":[{"content":"You are a knowledgeable assistant that helps users with various tasks.\nBe helpful, accurate, and concise in your responses.\n","role":"system"},{"content":"## Filesystem Tool Instructions\n\nThis toolset provides comprehensive filesystem operations.\n\n### Working Directory\n- Relative paths (like \".\" or \"src/main.go\") are resolved relative to the working directory\n- Absolute paths (like \"/etc/hosts\") access files directly\n- Paths starting with \"..\" can access parent directories\n\n### Common Patterns\n- Always check if directories exist before creating files\n- Prefer read_multiple_files for batch operations\n- Use search_files_content for finding specific code or text\n\n### Performance Tips\n- Use read_multiple_files instead of multiple read_file calls\n- Use directory_tree with max_depth to limit large traversals\n- Use appropriate exclude patterns in search operations\n\n### Reading Large Files\n- read_file and read_multiple_files support offset and line_count parameters for pagination\n- When a file is large, read it in chunks: start with offset=1 and a reasonable line_count\n- The response includes total_lines so you know how many more lines remain\n- Continue reading with an incremented offset until you have read all required content","role":"system"},{"content":"How many files in testdata/working_dir? Only output the number.","role":"user"},{"tool_calls":[{"id":"call_8p4SZZruoZHzbVqo3yb3rK61","function":{"arguments":"{\"path\":\"testdata/working_dir\"}","name":"list_directory"},"type":"function"}],"role":"assistant"},{"content":"FILE README.me\n","tool_call_id":"call_8p4SZZruoZHzbVqo3yb3rK61","role":"tool"}],"model":"gpt-4o","max_tokens":16384,"stream_options":{"include_usage":true},"tools":[{"function":{"name":"directory_tree","description":"Get a recursive tree view of files and directories as a JSON structure.","parameters":{"additionalProperties":false,"properties":{"path":{"description":"The directory path to traverse (relative to working directory)","type":"string"}},"required":["path"],"type":"object"}},"type":"function"},{"function":{"name":"edit_file","description":"Make line-based edits to a text file. Each edit replaces exact line sequences with new content.","parameters":{"additionalProperties":false,"properties":{"edits":{"description":"Array of edit operations","items":{"additionalProperties":false,"properties":{"newText":{"description":"The replacement text","type":"string"},"oldText":{"description":"The exact text to replace","type":"string"}},"required":["newText","oldText"],"type":"object"},"type":["null","array"]},"path":{"description":"The file path to edit","type":"string"}},"required":["edits","path"],"type":"object"}},"type":"function"},{"function":{"name":"list_directory","description":"Get a detailed listing of all files and directories in a specified path.","parameters":{"additionalProperties":false,"properties":{"path":{"description":"The directory path to list","type":"string"}},"required":["path"],"type":"object"}},"type":"function"},{"function":{"name":"read_file","description":"Read the contents of a file from the file system.","parameters":{"additionalProperties":false,"properties":{"line_count":{"description":"Maximum number of lines to return (default: all remaining lines)","type":["integer","null"]},"offset":{"description":"1-based line number to start reading from (default: 1)","type":["integer","null"]},"path":{"description":"The file path to read","type":"string"}},"required":["line_count","offset","path"],"type":"object"}},"type":"function"},{"function":{"name":"read_multiple_files","description":"Read the contents of multiple files simultaneously.","parameters":{"additionalProperties":false,"properties":{"json":{"description":"Whether to return the result as JSON","type":["boolean","null"]},"line_count":{"description":"Maximum number of lines to return per file (default: all remaining lines)","type":["integer","null"]},"offset":{"description":"1-based line number to start reading from, applied to all files (default: 1)","type":["integer","null"]},"paths":{"description":"Array of file paths to read","items":{"type":"string"},"type":["null","array"]}},"required":["json","line_count","offset","paths"],"type":"object"}},"type":"function"},{"function":{"name":"search_files_content","description":"Searches for text or regex patterns in the content of files matching a GLOB pattern.","parameters":{"additionalProperties":false,"properties":{"excludePatterns":{"description":"Patterns to exclude from search","items":{"type":"string"},"type":["null","array"]},"is_regex":{"description":"If true, treat query as regex; otherwise literal text","type":["boolean","null"]},"path":{"description":"The starting directory path","type":"string"},"query":{"description":"The text or regex pattern to search for","type":"string"}},"required":["excludePatterns","is_regex","path","query"],"type":"object"}},"type":"function"},{"function":{"name":"write_file","description":"Create a new file or completely overwrite an existing file with new content.","parameters":{"additionalProperties":false,"properties":{"content":{"description":"The content to write to the file","type":"string"},"path":{"description":"The file path to write","type":"string"}},"required":["content","path"],"type":"object"}},"type":"function"}],"stream":true}' url: https://api.openai.com/v1/chat/completions method: POST response: @@ -63,17 +63,17 @@ interactions: proto_minor: 0 content_length: -1 body: |+ - data: {"id":"chatcmpl-D8pFt0tWnBk9BaNRplerHJ0KdYN8d","object":"chat.completion.chunk","created":1770996021,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_ad98c18a04","choices":[{"index":0,"delta":{"role":"assistant","content":"","refusal":null},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"Vn1hlPMHz0tPnV"} + data: {"id":"chatcmpl-DCjR5WEeUs6ZUJ7PZcq4fizS9BSow","object":"chat.completion.chunk","created":1771926963,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_64dfa806c7","choices":[{"index":0,"delta":{"role":"assistant","content":"","refusal":null},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"dXpG6Xx2vFkCCy"} - data: {"id":"chatcmpl-D8pFt0tWnBk9BaNRplerHJ0KdYN8d","object":"chat.completion.chunk","created":1770996021,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_ad98c18a04","choices":[{"index":0,"delta":{"content":"1"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"qd9Ih0YatpjWJgQ"} + data: {"id":"chatcmpl-DCjR5WEeUs6ZUJ7PZcq4fizS9BSow","object":"chat.completion.chunk","created":1771926963,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_64dfa806c7","choices":[{"index":0,"delta":{"content":"1"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"LEVzKSD0yreZQu8"} - data: {"id":"chatcmpl-D8pFt0tWnBk9BaNRplerHJ0KdYN8d","object":"chat.completion.chunk","created":1770996021,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_ad98c18a04","choices":[{"index":0,"delta":{},"logprobs":null,"finish_reason":"stop"}],"usage":null,"obfuscation":"Rhkg3myiQQ"} + data: {"id":"chatcmpl-DCjR5WEeUs6ZUJ7PZcq4fizS9BSow","object":"chat.completion.chunk","created":1771926963,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_64dfa806c7","choices":[{"index":0,"delta":{},"logprobs":null,"finish_reason":"stop"}],"usage":null,"obfuscation":"FSSxjMVM1z"} - data: {"id":"chatcmpl-D8pFt0tWnBk9BaNRplerHJ0KdYN8d","object":"chat.completion.chunk","created":1770996021,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_ad98c18a04","choices":[],"usage":{"prompt_tokens":686,"completion_tokens":2,"total_tokens":688,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0},"completion_tokens_details":{"reasoning_tokens":0,"audio_tokens":0,"accepted_prediction_tokens":0,"rejected_prediction_tokens":0}},"obfuscation":"t2KiIbtSOjrOVj"} + data: {"id":"chatcmpl-DCjR5WEeUs6ZUJ7PZcq4fizS9BSow","object":"chat.completion.chunk","created":1771926963,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_64dfa806c7","choices":[],"usage":{"prompt_tokens":991,"completion_tokens":2,"total_tokens":993,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0},"completion_tokens_details":{"reasoning_tokens":0,"audio_tokens":0,"accepted_prediction_tokens":0,"rejected_prediction_tokens":0}},"obfuscation":"4BgsLpEjNhGvLl"} data: [DONE] headers: {} status: 200 OK code: 200 - duration: 428.712708ms + duration: 750.893125ms diff --git a/e2e/testdata/cassettes/TestExec_OpenAI_ToolCall.yaml b/e2e/testdata/cassettes/TestExec_OpenAI_ToolCall.yaml index 92d5a6f68..0d724582e 100644 --- a/e2e/testdata/cassettes/TestExec_OpenAI_ToolCall.yaml +++ b/e2e/testdata/cassettes/TestExec_OpenAI_ToolCall.yaml @@ -8,7 +8,7 @@ interactions: proto_minor: 1 content_length: 0 host: api.openai.com - body: '{"messages":[{"content":"You are a knowledgeable assistant that helps users with various tasks.\nBe helpful, accurate, and concise in your responses.\n","role":"system"},{"content":"## Filesystem Tool Instructions\n\nThis toolset provides comprehensive filesystem operations.\n\n### Working Directory\n- Relative paths (like \".\" or \"src/main.go\") are resolved relative to the working directory\n- Absolute paths (like \"/etc/hosts\") access files directly\n- Paths starting with \"..\" can access parent directories\n\n### Common Patterns\n- Always check if directories exist before creating files\n- Prefer read_multiple_files for batch operations\n- Use search_files_content for finding specific code or text\n\n### Performance Tips\n- Use read_multiple_files instead of multiple read_file calls\n- Use directory_tree with max_depth to limit large traversals\n- Use appropriate exclude patterns in search operations","role":"system"},{"content":"How many files in testdata/working_dir? Only output the number.","role":"user"}],"model":"gpt-4o","max_tokens":16384,"stream_options":{"include_usage":true},"tools":[{"function":{"name":"directory_tree","description":"Get a recursive tree view of files and directories as a JSON structure.","parameters":{"additionalProperties":false,"properties":{"path":{"description":"The directory path to traverse (relative to working directory)","type":"string"}},"required":["path"],"type":"object"}},"type":"function"},{"function":{"name":"edit_file","description":"Make line-based edits to a text file. Each edit replaces exact line sequences with new content.","parameters":{"additionalProperties":false,"properties":{"edits":{"description":"Array of edit operations","items":{"additionalProperties":false,"properties":{"newText":{"description":"The replacement text","type":"string"},"oldText":{"description":"The exact text to replace","type":"string"}},"required":["newText","oldText"],"type":"object"},"type":["null","array"]},"path":{"description":"The file path to edit","type":"string"}},"required":["edits","path"],"type":"object"}},"type":"function"},{"function":{"name":"list_directory","description":"Get a detailed listing of all files and directories in a specified path.","parameters":{"additionalProperties":false,"properties":{"path":{"description":"The directory path to list","type":"string"}},"required":["path"],"type":"object"}},"type":"function"},{"function":{"name":"read_file","description":"Read the complete contents of a file from the file system.","parameters":{"additionalProperties":false,"properties":{"path":{"description":"The file path to read","type":"string"}},"required":["path"],"type":"object"}},"type":"function"},{"function":{"name":"read_multiple_files","description":"Read the contents of multiple files simultaneously.","parameters":{"additionalProperties":false,"properties":{"json":{"description":"Whether to return the result as JSON","type":["boolean","null"]},"paths":{"description":"Array of file paths to read","items":{"type":"string"},"type":["null","array"]}},"required":["json","paths"],"type":"object"}},"type":"function"},{"function":{"name":"search_files_content","description":"Searches for text or regex patterns in the content of files matching a GLOB pattern.","parameters":{"additionalProperties":false,"properties":{"excludePatterns":{"description":"Patterns to exclude from search","items":{"type":"string"},"type":["null","array"]},"is_regex":{"description":"If true, treat query as regex; otherwise literal text","type":["boolean","null"]},"path":{"description":"The starting directory path","type":"string"},"query":{"description":"The text or regex pattern to search for","type":"string"}},"required":["excludePatterns","is_regex","path","query"],"type":"object"}},"type":"function"},{"function":{"name":"write_file","description":"Create a new file or completely overwrite an existing file with new content.","parameters":{"additionalProperties":false,"properties":{"content":{"description":"The content to write to the file","type":"string"},"path":{"description":"The file path to write","type":"string"}},"required":["content","path"],"type":"object"}},"type":"function"}],"stream":true}' + body: '{"messages":[{"content":"You are a knowledgeable assistant that helps users with various tasks.\nBe helpful, accurate, and concise in your responses.\n","role":"system"},{"content":"## Filesystem Tool Instructions\n\nThis toolset provides comprehensive filesystem operations.\n\n### Working Directory\n- Relative paths (like \".\" or \"src/main.go\") are resolved relative to the working directory\n- Absolute paths (like \"/etc/hosts\") access files directly\n- Paths starting with \"..\" can access parent directories\n\n### Common Patterns\n- Always check if directories exist before creating files\n- Prefer read_multiple_files for batch operations\n- Use search_files_content for finding specific code or text\n\n### Performance Tips\n- Use read_multiple_files instead of multiple read_file calls\n- Use directory_tree with max_depth to limit large traversals\n- Use appropriate exclude patterns in search operations\n\n### Reading Large Files\n- read_file and read_multiple_files support offset and line_count parameters for pagination\n- When a file is large, read it in chunks: start with offset=1 and a reasonable line_count\n- The response includes total_lines so you know how many more lines remain\n- Continue reading with an incremented offset until you have read all required content","role":"system"},{"content":"How many files in testdata/working_dir? Only output the number.","role":"user"}],"model":"gpt-4o","max_tokens":16384,"stream_options":{"include_usage":true},"tools":[{"function":{"name":"directory_tree","description":"Get a recursive tree view of files and directories as a JSON structure.","parameters":{"additionalProperties":false,"properties":{"path":{"description":"The directory path to traverse (relative to working directory)","type":"string"}},"required":["path"],"type":"object"}},"type":"function"},{"function":{"name":"edit_file","description":"Make line-based edits to a text file. Each edit replaces exact line sequences with new content.","parameters":{"additionalProperties":false,"properties":{"edits":{"description":"Array of edit operations","items":{"additionalProperties":false,"properties":{"newText":{"description":"The replacement text","type":"string"},"oldText":{"description":"The exact text to replace","type":"string"}},"required":["newText","oldText"],"type":"object"},"type":["null","array"]},"path":{"description":"The file path to edit","type":"string"}},"required":["edits","path"],"type":"object"}},"type":"function"},{"function":{"name":"list_directory","description":"Get a detailed listing of all files and directories in a specified path.","parameters":{"additionalProperties":false,"properties":{"path":{"description":"The directory path to list","type":"string"}},"required":["path"],"type":"object"}},"type":"function"},{"function":{"name":"read_file","description":"Read the contents of a file from the file system.","parameters":{"additionalProperties":false,"properties":{"line_count":{"description":"Maximum number of lines to return (default: all remaining lines)","type":["integer","null"]},"offset":{"description":"1-based line number to start reading from (default: 1)","type":["integer","null"]},"path":{"description":"The file path to read","type":"string"}},"required":["line_count","offset","path"],"type":"object"}},"type":"function"},{"function":{"name":"read_multiple_files","description":"Read the contents of multiple files simultaneously.","parameters":{"additionalProperties":false,"properties":{"json":{"description":"Whether to return the result as JSON","type":["boolean","null"]},"line_count":{"description":"Maximum number of lines to return per file (default: all remaining lines)","type":["integer","null"]},"offset":{"description":"1-based line number to start reading from, applied to all files (default: 1)","type":["integer","null"]},"paths":{"description":"Array of file paths to read","items":{"type":"string"},"type":["null","array"]}},"required":["json","line_count","offset","paths"],"type":"object"}},"type":"function"},{"function":{"name":"search_files_content","description":"Searches for text or regex patterns in the content of files matching a GLOB pattern.","parameters":{"additionalProperties":false,"properties":{"excludePatterns":{"description":"Patterns to exclude from search","items":{"type":"string"},"type":["null","array"]},"is_regex":{"description":"If true, treat query as regex; otherwise literal text","type":["boolean","null"]},"path":{"description":"The starting directory path","type":"string"},"query":{"description":"The text or regex pattern to search for","type":"string"}},"required":["excludePatterns","is_regex","path","query"],"type":"object"}},"type":"function"},{"function":{"name":"write_file","description":"Create a new file or completely overwrite an existing file with new content.","parameters":{"additionalProperties":false,"properties":{"content":{"description":"The content to write to the file","type":"string"},"path":{"description":"The file path to write","type":"string"}},"required":["content","path"],"type":"object"}},"type":"function"}],"stream":true}' url: https://api.openai.com/v1/chat/completions method: POST response: @@ -17,36 +17,36 @@ interactions: proto_minor: 0 content_length: -1 body: |+ - data: {"id":"chatcmpl-D8pFSp0PTZRurIl1YK5uSIQpaDYR8","object":"chat.completion.chunk","created":1770995994,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_64dfa806c7","choices":[{"index":0,"delta":{"role":"assistant","content":null,"tool_calls":[{"index":0,"id":"call_b1xfQl8yj71KXoQm5v0BKn0f","type":"function","function":{"name":"list_directory","arguments":""}}],"refusal":null},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"1k7RVe"} + data: {"id":"chatcmpl-DCjQyDThJpxz90fWufHfh58dCi8gv","object":"chat.completion.chunk","created":1771926956,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_64dfa806c7","choices":[{"index":0,"delta":{"role":"assistant","content":null,"tool_calls":[{"index":0,"id":"call_JRWFgFBIpEdF7s2MAAMjYbHn","type":"function","function":{"name":"list_directory","arguments":""}}],"refusal":null},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"xzLuQQ"} - data: {"id":"chatcmpl-D8pFSp0PTZRurIl1YK5uSIQpaDYR8","object":"chat.completion.chunk","created":1770995994,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_64dfa806c7","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"{\""}}]},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"oWi"} + data: {"id":"chatcmpl-DCjQyDThJpxz90fWufHfh58dCi8gv","object":"chat.completion.chunk","created":1771926956,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_64dfa806c7","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"{\""}}]},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"yHh"} - data: {"id":"chatcmpl-D8pFSp0PTZRurIl1YK5uSIQpaDYR8","object":"chat.completion.chunk","created":1770995994,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_64dfa806c7","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"path"}}]},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"HD"} + data: {"id":"chatcmpl-DCjQyDThJpxz90fWufHfh58dCi8gv","object":"chat.completion.chunk","created":1771926956,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_64dfa806c7","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"path"}}]},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"zJ"} - data: {"id":"chatcmpl-D8pFSp0PTZRurIl1YK5uSIQpaDYR8","object":"chat.completion.chunk","created":1770995994,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_64dfa806c7","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"\":\""}}]},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"3"} + data: {"id":"chatcmpl-DCjQyDThJpxz90fWufHfh58dCi8gv","object":"chat.completion.chunk","created":1771926956,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_64dfa806c7","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"\":\""}}]},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"2"} - data: {"id":"chatcmpl-D8pFSp0PTZRurIl1YK5uSIQpaDYR8","object":"chat.completion.chunk","created":1770995994,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_64dfa806c7","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"test"}}]},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"SW"} + data: {"id":"chatcmpl-DCjQyDThJpxz90fWufHfh58dCi8gv","object":"chat.completion.chunk","created":1771926956,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_64dfa806c7","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"test"}}]},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"MO"} - data: {"id":"chatcmpl-D8pFSp0PTZRurIl1YK5uSIQpaDYR8","object":"chat.completion.chunk","created":1770995994,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_64dfa806c7","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"data"}}]},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"Uw"} + data: {"id":"chatcmpl-DCjQyDThJpxz90fWufHfh58dCi8gv","object":"chat.completion.chunk","created":1771926956,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_64dfa806c7","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"data"}}]},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"AO"} - data: {"id":"chatcmpl-D8pFSp0PTZRurIl1YK5uSIQpaDYR8","object":"chat.completion.chunk","created":1770995994,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_64dfa806c7","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"/"}}]},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"4lG94"} + data: {"id":"chatcmpl-DCjQyDThJpxz90fWufHfh58dCi8gv","object":"chat.completion.chunk","created":1771926956,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_64dfa806c7","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"/"}}]},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"th1f9"} - data: {"id":"chatcmpl-D8pFSp0PTZRurIl1YK5uSIQpaDYR8","object":"chat.completion.chunk","created":1770995994,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_64dfa806c7","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"working"}}]},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"jtkFjef5nvUv0rY"} + data: {"id":"chatcmpl-DCjQyDThJpxz90fWufHfh58dCi8gv","object":"chat.completion.chunk","created":1771926956,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_64dfa806c7","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"working"}}]},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"LN3KzDNlfuY41GD"} - data: {"id":"chatcmpl-D8pFSp0PTZRurIl1YK5uSIQpaDYR8","object":"chat.completion.chunk","created":1770995994,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_64dfa806c7","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"_dir"}}]},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"rf"} + data: {"id":"chatcmpl-DCjQyDThJpxz90fWufHfh58dCi8gv","object":"chat.completion.chunk","created":1771926956,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_64dfa806c7","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"_dir"}}]},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"em"} - data: {"id":"chatcmpl-D8pFSp0PTZRurIl1YK5uSIQpaDYR8","object":"chat.completion.chunk","created":1770995994,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_64dfa806c7","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"\"}"}}]},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"sfm"} + data: {"id":"chatcmpl-DCjQyDThJpxz90fWufHfh58dCi8gv","object":"chat.completion.chunk","created":1771926956,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_64dfa806c7","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"\"}"}}]},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"JcB"} - data: {"id":"chatcmpl-D8pFSp0PTZRurIl1YK5uSIQpaDYR8","object":"chat.completion.chunk","created":1770995994,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_64dfa806c7","choices":[{"index":0,"delta":{},"logprobs":null,"finish_reason":"tool_calls"}],"usage":null,"obfuscation":"zKGT"} + data: {"id":"chatcmpl-DCjQyDThJpxz90fWufHfh58dCi8gv","object":"chat.completion.chunk","created":1771926956,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_64dfa806c7","choices":[{"index":0,"delta":{},"logprobs":null,"finish_reason":"tool_calls"}],"usage":null,"obfuscation":"DMSh"} - data: {"id":"chatcmpl-D8pFSp0PTZRurIl1YK5uSIQpaDYR8","object":"chat.completion.chunk","created":1770995994,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_64dfa806c7","choices":[],"usage":{"prompt_tokens":656,"completion_tokens":18,"total_tokens":674,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0},"completion_tokens_details":{"reasoning_tokens":0,"audio_tokens":0,"accepted_prediction_tokens":0,"rejected_prediction_tokens":0}},"obfuscation":"UgaXFljcFpu16"} + data: {"id":"chatcmpl-DCjQyDThJpxz90fWufHfh58dCi8gv","object":"chat.completion.chunk","created":1771926956,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_64dfa806c7","choices":[],"usage":{"prompt_tokens":961,"completion_tokens":18,"total_tokens":979,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0},"completion_tokens_details":{"reasoning_tokens":0,"audio_tokens":0,"accepted_prediction_tokens":0,"rejected_prediction_tokens":0}},"obfuscation":"TbposUMzrI0Pp"} data: [DONE] headers: {} status: 200 OK code: 200 - duration: 1.059753583s + duration: 4.2718405s - id: 1 request: proto: HTTP/1.1 @@ -54,7 +54,7 @@ interactions: proto_minor: 1 content_length: 0 host: api.openai.com - body: '{"messages":[{"content":"You are a knowledgeable assistant that helps users with various tasks.\nBe helpful, accurate, and concise in your responses.\n","role":"system"},{"content":"## Filesystem Tool Instructions\n\nThis toolset provides comprehensive filesystem operations.\n\n### Working Directory\n- Relative paths (like \".\" or \"src/main.go\") are resolved relative to the working directory\n- Absolute paths (like \"/etc/hosts\") access files directly\n- Paths starting with \"..\" can access parent directories\n\n### Common Patterns\n- Always check if directories exist before creating files\n- Prefer read_multiple_files for batch operations\n- Use search_files_content for finding specific code or text\n\n### Performance Tips\n- Use read_multiple_files instead of multiple read_file calls\n- Use directory_tree with max_depth to limit large traversals\n- Use appropriate exclude patterns in search operations","role":"system"},{"content":"How many files in testdata/working_dir? Only output the number.","role":"user"},{"tool_calls":[{"id":"call_b1xfQl8yj71KXoQm5v0BKn0f","function":{"arguments":"{\"path\":\"testdata/working_dir\"}","name":"list_directory"},"type":"function"}],"role":"assistant"},{"content":"FILE README.me\n","tool_call_id":"call_b1xfQl8yj71KXoQm5v0BKn0f","role":"tool"}],"model":"gpt-4o","max_tokens":16384,"stream_options":{"include_usage":true},"tools":[{"function":{"name":"directory_tree","description":"Get a recursive tree view of files and directories as a JSON structure.","parameters":{"additionalProperties":false,"properties":{"path":{"description":"The directory path to traverse (relative to working directory)","type":"string"}},"required":["path"],"type":"object"}},"type":"function"},{"function":{"name":"edit_file","description":"Make line-based edits to a text file. Each edit replaces exact line sequences with new content.","parameters":{"additionalProperties":false,"properties":{"edits":{"description":"Array of edit operations","items":{"additionalProperties":false,"properties":{"newText":{"description":"The replacement text","type":"string"},"oldText":{"description":"The exact text to replace","type":"string"}},"required":["newText","oldText"],"type":"object"},"type":["null","array"]},"path":{"description":"The file path to edit","type":"string"}},"required":["edits","path"],"type":"object"}},"type":"function"},{"function":{"name":"list_directory","description":"Get a detailed listing of all files and directories in a specified path.","parameters":{"additionalProperties":false,"properties":{"path":{"description":"The directory path to list","type":"string"}},"required":["path"],"type":"object"}},"type":"function"},{"function":{"name":"read_file","description":"Read the complete contents of a file from the file system.","parameters":{"additionalProperties":false,"properties":{"path":{"description":"The file path to read","type":"string"}},"required":["path"],"type":"object"}},"type":"function"},{"function":{"name":"read_multiple_files","description":"Read the contents of multiple files simultaneously.","parameters":{"additionalProperties":false,"properties":{"json":{"description":"Whether to return the result as JSON","type":["boolean","null"]},"paths":{"description":"Array of file paths to read","items":{"type":"string"},"type":["null","array"]}},"required":["json","paths"],"type":"object"}},"type":"function"},{"function":{"name":"search_files_content","description":"Searches for text or regex patterns in the content of files matching a GLOB pattern.","parameters":{"additionalProperties":false,"properties":{"excludePatterns":{"description":"Patterns to exclude from search","items":{"type":"string"},"type":["null","array"]},"is_regex":{"description":"If true, treat query as regex; otherwise literal text","type":["boolean","null"]},"path":{"description":"The starting directory path","type":"string"},"query":{"description":"The text or regex pattern to search for","type":"string"}},"required":["excludePatterns","is_regex","path","query"],"type":"object"}},"type":"function"},{"function":{"name":"write_file","description":"Create a new file or completely overwrite an existing file with new content.","parameters":{"additionalProperties":false,"properties":{"content":{"description":"The content to write to the file","type":"string"},"path":{"description":"The file path to write","type":"string"}},"required":["content","path"],"type":"object"}},"type":"function"}],"stream":true}' + body: '{"messages":[{"content":"You are a knowledgeable assistant that helps users with various tasks.\nBe helpful, accurate, and concise in your responses.\n","role":"system"},{"content":"## Filesystem Tool Instructions\n\nThis toolset provides comprehensive filesystem operations.\n\n### Working Directory\n- Relative paths (like \".\" or \"src/main.go\") are resolved relative to the working directory\n- Absolute paths (like \"/etc/hosts\") access files directly\n- Paths starting with \"..\" can access parent directories\n\n### Common Patterns\n- Always check if directories exist before creating files\n- Prefer read_multiple_files for batch operations\n- Use search_files_content for finding specific code or text\n\n### Performance Tips\n- Use read_multiple_files instead of multiple read_file calls\n- Use directory_tree with max_depth to limit large traversals\n- Use appropriate exclude patterns in search operations\n\n### Reading Large Files\n- read_file and read_multiple_files support offset and line_count parameters for pagination\n- When a file is large, read it in chunks: start with offset=1 and a reasonable line_count\n- The response includes total_lines so you know how many more lines remain\n- Continue reading with an incremented offset until you have read all required content","role":"system"},{"content":"How many files in testdata/working_dir? Only output the number.","role":"user"},{"tool_calls":[{"id":"call_JRWFgFBIpEdF7s2MAAMjYbHn","function":{"arguments":"{\"path\":\"testdata/working_dir\"}","name":"list_directory"},"type":"function"}],"role":"assistant"},{"content":"FILE README.me\n","tool_call_id":"call_JRWFgFBIpEdF7s2MAAMjYbHn","role":"tool"}],"model":"gpt-4o","max_tokens":16384,"stream_options":{"include_usage":true},"tools":[{"function":{"name":"directory_tree","description":"Get a recursive tree view of files and directories as a JSON structure.","parameters":{"additionalProperties":false,"properties":{"path":{"description":"The directory path to traverse (relative to working directory)","type":"string"}},"required":["path"],"type":"object"}},"type":"function"},{"function":{"name":"edit_file","description":"Make line-based edits to a text file. Each edit replaces exact line sequences with new content.","parameters":{"additionalProperties":false,"properties":{"edits":{"description":"Array of edit operations","items":{"additionalProperties":false,"properties":{"newText":{"description":"The replacement text","type":"string"},"oldText":{"description":"The exact text to replace","type":"string"}},"required":["newText","oldText"],"type":"object"},"type":["null","array"]},"path":{"description":"The file path to edit","type":"string"}},"required":["edits","path"],"type":"object"}},"type":"function"},{"function":{"name":"list_directory","description":"Get a detailed listing of all files and directories in a specified path.","parameters":{"additionalProperties":false,"properties":{"path":{"description":"The directory path to list","type":"string"}},"required":["path"],"type":"object"}},"type":"function"},{"function":{"name":"read_file","description":"Read the contents of a file from the file system.","parameters":{"additionalProperties":false,"properties":{"line_count":{"description":"Maximum number of lines to return (default: all remaining lines)","type":["integer","null"]},"offset":{"description":"1-based line number to start reading from (default: 1)","type":["integer","null"]},"path":{"description":"The file path to read","type":"string"}},"required":["line_count","offset","path"],"type":"object"}},"type":"function"},{"function":{"name":"read_multiple_files","description":"Read the contents of multiple files simultaneously.","parameters":{"additionalProperties":false,"properties":{"json":{"description":"Whether to return the result as JSON","type":["boolean","null"]},"line_count":{"description":"Maximum number of lines to return per file (default: all remaining lines)","type":["integer","null"]},"offset":{"description":"1-based line number to start reading from, applied to all files (default: 1)","type":["integer","null"]},"paths":{"description":"Array of file paths to read","items":{"type":"string"},"type":["null","array"]}},"required":["json","line_count","offset","paths"],"type":"object"}},"type":"function"},{"function":{"name":"search_files_content","description":"Searches for text or regex patterns in the content of files matching a GLOB pattern.","parameters":{"additionalProperties":false,"properties":{"excludePatterns":{"description":"Patterns to exclude from search","items":{"type":"string"},"type":["null","array"]},"is_regex":{"description":"If true, treat query as regex; otherwise literal text","type":["boolean","null"]},"path":{"description":"The starting directory path","type":"string"},"query":{"description":"The text or regex pattern to search for","type":"string"}},"required":["excludePatterns","is_regex","path","query"],"type":"object"}},"type":"function"},{"function":{"name":"write_file","description":"Create a new file or completely overwrite an existing file with new content.","parameters":{"additionalProperties":false,"properties":{"content":{"description":"The content to write to the file","type":"string"},"path":{"description":"The file path to write","type":"string"}},"required":["content","path"],"type":"object"}},"type":"function"}],"stream":true}' url: https://api.openai.com/v1/chat/completions method: POST response: @@ -63,17 +63,17 @@ interactions: proto_minor: 0 content_length: -1 body: |+ - data: {"id":"chatcmpl-D8pFTh8xolpWY1i8oJKZMoxOtGspI","object":"chat.completion.chunk","created":1770995995,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_64dfa806c7","choices":[{"index":0,"delta":{"role":"assistant","content":"","refusal":null},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"KDlKAVp92GYPLd"} + data: {"id":"chatcmpl-DCjR3LeDmrft8KDbjnwyRhqpfSzkB","object":"chat.completion.chunk","created":1771926961,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_64dfa806c7","choices":[{"index":0,"delta":{"role":"assistant","content":"","refusal":null},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"1SaYpu7sq7pcei"} - data: {"id":"chatcmpl-D8pFTh8xolpWY1i8oJKZMoxOtGspI","object":"chat.completion.chunk","created":1770995995,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_64dfa806c7","choices":[{"index":0,"delta":{"content":"1"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"1pZAb9PYI4wDyI9"} + data: {"id":"chatcmpl-DCjR3LeDmrft8KDbjnwyRhqpfSzkB","object":"chat.completion.chunk","created":1771926961,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_64dfa806c7","choices":[{"index":0,"delta":{"content":"1"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"KSrtyUAcHfXjOaW"} - data: {"id":"chatcmpl-D8pFTh8xolpWY1i8oJKZMoxOtGspI","object":"chat.completion.chunk","created":1770995995,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_64dfa806c7","choices":[{"index":0,"delta":{},"logprobs":null,"finish_reason":"stop"}],"usage":null,"obfuscation":"VytIgX7pnA"} + data: {"id":"chatcmpl-DCjR3LeDmrft8KDbjnwyRhqpfSzkB","object":"chat.completion.chunk","created":1771926961,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_64dfa806c7","choices":[{"index":0,"delta":{},"logprobs":null,"finish_reason":"stop"}],"usage":null,"obfuscation":"dunihSdncQ"} - data: {"id":"chatcmpl-D8pFTh8xolpWY1i8oJKZMoxOtGspI","object":"chat.completion.chunk","created":1770995995,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_64dfa806c7","choices":[],"usage":{"prompt_tokens":686,"completion_tokens":2,"total_tokens":688,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0},"completion_tokens_details":{"reasoning_tokens":0,"audio_tokens":0,"accepted_prediction_tokens":0,"rejected_prediction_tokens":0}},"obfuscation":"H29MEt5yOj0ujz"} + data: {"id":"chatcmpl-DCjR3LeDmrft8KDbjnwyRhqpfSzkB","object":"chat.completion.chunk","created":1771926961,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_64dfa806c7","choices":[],"usage":{"prompt_tokens":991,"completion_tokens":2,"total_tokens":993,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0},"completion_tokens_details":{"reasoning_tokens":0,"audio_tokens":0,"accepted_prediction_tokens":0,"rejected_prediction_tokens":0}},"obfuscation":"O6xPiREEoiILo2"} data: [DONE] headers: {} status: 200 OK code: 200 - duration: 670.828083ms + duration: 589.338375ms diff --git a/e2e/testdata/cassettes/TestExec_ToolCallsNeedAcceptance.yaml b/e2e/testdata/cassettes/TestExec_ToolCallsNeedAcceptance.yaml index c9dac0975..890d7787e 100644 --- a/e2e/testdata/cassettes/TestExec_ToolCallsNeedAcceptance.yaml +++ b/e2e/testdata/cassettes/TestExec_ToolCallsNeedAcceptance.yaml @@ -8,7 +8,7 @@ interactions: proto_minor: 1 content_length: 0 host: api.openai.com - body: '{"input":[{"content":[{"text":"You are a knowledgeable assistant that can write test files.","type":"input_text"}],"role":"system"},{"content":[{"text":"## Filesystem Tool Instructions\n\nThis toolset provides comprehensive filesystem operations.\n\n### Working Directory\n- Relative paths (like \".\" or \"src/main.go\") are resolved relative to the working directory\n- Absolute paths (like \"/etc/hosts\") access files directly\n- Paths starting with \"..\" can access parent directories\n\n### Common Patterns\n- Always check if directories exist before creating files\n- Prefer read_multiple_files for batch operations\n- Use search_files_content for finding specific code or text\n\n### Performance Tips\n- Use read_multiple_files instead of multiple read_file calls\n- Use directory_tree with max_depth to limit large traversals\n- Use appropriate exclude patterns in search operations","type":"input_text"}],"role":"system"},{"content":"Create a hello.txt file with \"Hello, World!\" content. Try only once. On error, exit without further message.","role":"user"}],"model":"gpt-5-mini","tools":[{"strict":true,"parameters":{"additionalProperties":false,"properties":{"content":{"description":"The content to write to the file","type":"string"},"path":{"description":"The file path to write","type":"string"}},"required":["content","path"],"type":"object"},"name":"write_file","description":"Create a new file or completely overwrite an existing file with new content.","type":"function"}],"stream":true}' + body: '{"input":[{"content":[{"text":"You are a knowledgeable assistant that can write test files.","type":"input_text"}],"role":"system"},{"content":[{"text":"## Filesystem Tool Instructions\n\nThis toolset provides comprehensive filesystem operations.\n\n### Working Directory\n- Relative paths (like \".\" or \"src/main.go\") are resolved relative to the working directory\n- Absolute paths (like \"/etc/hosts\") access files directly\n- Paths starting with \"..\" can access parent directories\n\n### Common Patterns\n- Always check if directories exist before creating files\n- Prefer read_multiple_files for batch operations\n- Use search_files_content for finding specific code or text\n\n### Performance Tips\n- Use read_multiple_files instead of multiple read_file calls\n- Use directory_tree with max_depth to limit large traversals\n- Use appropriate exclude patterns in search operations\n\n### Reading Large Files\n- read_file and read_multiple_files support offset and line_count parameters for pagination\n- When a file is large, read it in chunks: start with offset=1 and a reasonable line_count\n- The response includes total_lines so you know how many more lines remain\n- Continue reading with an incremented offset until you have read all required content","type":"input_text"}],"role":"system"},{"content":"Create a hello.txt file with \"Hello, World!\" content. Try only once. On error, exit without further message.","role":"user"}],"model":"gpt-5-mini","tools":[{"strict":true,"parameters":{"additionalProperties":false,"properties":{"content":{"description":"The content to write to the file","type":"string"},"path":{"description":"The file path to write","type":"string"}},"required":["content","path"],"type":"object"},"name":"write_file","description":"Create a new file or completely overwrite an existing file with new content.","type":"function"}],"stream":true}' url: https://api.openai.com/v1/responses method: POST response: @@ -91,7 +91,7 @@ interactions: proto_minor: 1 content_length: 0 host: api.openai.com - body: '{"input":[{"content":[{"text":"You are a knowledgeable assistant that can write test files.","type":"input_text"}],"role":"system"},{"content":[{"text":"## Filesystem Tool Instructions\n\nThis toolset provides comprehensive filesystem operations.\n\n### Working Directory\n- Relative paths (like \".\" or \"src/main.go\") are resolved relative to the working directory\n- Absolute paths (like \"/etc/hosts\") access files directly\n- Paths starting with \"..\" can access parent directories\n\n### Common Patterns\n- Always check if directories exist before creating files\n- Prefer read_multiple_files for batch operations\n- Use search_files_content for finding specific code or text\n\n### Performance Tips\n- Use read_multiple_files instead of multiple read_file calls\n- Use directory_tree with max_depth to limit large traversals\n- Use appropriate exclude patterns in search operations","type":"input_text"}],"role":"system"},{"content":"Create a hello.txt file with \"Hello, World!\" content. Try only once. On error, exit without further message.","role":"user"},{"arguments":"{\"content\":\"Hello, World!\",\"path\":\"hello.txt\"}","call_id":"call_5W18F6XkDh9NllAH9r0P9GuF","name":"write_file","type":"function_call"},{"call_id":"call_5W18F6XkDh9NllAH9r0P9GuF","output":"The user rejected the tool call.","type":"function_call_output"}],"model":"gpt-5-mini","tools":[{"strict":true,"parameters":{"additionalProperties":false,"properties":{"content":{"description":"The content to write to the file","type":"string"},"path":{"description":"The file path to write","type":"string"}},"required":["content","path"],"type":"object"},"name":"write_file","description":"Create a new file or completely overwrite an existing file with new content.","type":"function"}],"stream":true}' + body: '{"input":[{"content":[{"text":"You are a knowledgeable assistant that can write test files.","type":"input_text"}],"role":"system"},{"content":[{"text":"## Filesystem Tool Instructions\n\nThis toolset provides comprehensive filesystem operations.\n\n### Working Directory\n- Relative paths (like \".\" or \"src/main.go\") are resolved relative to the working directory\n- Absolute paths (like \"/etc/hosts\") access files directly\n- Paths starting with \"..\" can access parent directories\n\n### Common Patterns\n- Always check if directories exist before creating files\n- Prefer read_multiple_files for batch operations\n- Use search_files_content for finding specific code or text\n\n### Performance Tips\n- Use read_multiple_files instead of multiple read_file calls\n- Use directory_tree with max_depth to limit large traversals\n- Use appropriate exclude patterns in search operations\n\n### Reading Large Files\n- read_file and read_multiple_files support offset and line_count parameters for pagination\n- When a file is large, read it in chunks: start with offset=1 and a reasonable line_count\n- The response includes total_lines so you know how many more lines remain\n- Continue reading with an incremented offset until you have read all required content","type":"input_text"}],"role":"system"},{"content":"Create a hello.txt file with \"Hello, World!\" content. Try only once. On error, exit without further message.","role":"user"},{"arguments":"{\"content\":\"Hello, World!\",\"path\":\"hello.txt\"}","call_id":"call_5W18F6XkDh9NllAH9r0P9GuF","name":"write_file","type":"function_call"},{"call_id":"call_5W18F6XkDh9NllAH9r0P9GuF","output":"The user rejected the tool call.","type":"function_call_output"}],"model":"gpt-5-mini","tools":[{"strict":true,"parameters":{"additionalProperties":false,"properties":{"content":{"description":"The content to write to the file","type":"string"},"path":{"description":"The file path to write","type":"string"}},"required":["content","path"],"type":"object"},"name":"write_file","description":"Create a new file or completely overwrite an existing file with new content.","type":"function"}],"stream":true}' url: https://api.openai.com/v1/responses method: POST response: diff --git a/pkg/tools/builtin/filesystem.go b/pkg/tools/builtin/filesystem.go index 9581243ae..ae360fa73 100644 --- a/pkg/tools/builtin/filesystem.go +++ b/pkg/tools/builtin/filesystem.go @@ -91,7 +91,13 @@ This toolset provides comprehensive filesystem operations. ### Performance Tips - Use read_multiple_files instead of multiple read_file calls - Use directory_tree with max_depth to limit large traversals -- Use appropriate exclude patterns in search operations` +- Use appropriate exclude patterns in search operations + +### Reading Large Files +- read_file and read_multiple_files support offset and line_count parameters for pagination +- When a file is large, read it in chunks: start with offset=1 and a reasonable line_count +- The response includes total_lines so you know how many more lines remain +- Continue reading with an incremented offset until you have read all required content` } type DirectoryTreeArgs struct { @@ -104,8 +110,10 @@ type WriteFileArgs struct { } type ReadMultipleFilesArgs struct { - Paths []string `json:"paths" jsonschema:"Array of file paths to read"` - JSON bool `json:"json,omitempty" jsonschema:"Whether to return the result as JSON"` + Paths []string `json:"paths" jsonschema:"Array of file paths to read"` + JSON bool `json:"json,omitempty" jsonschema:"Whether to return the result as JSON"` + Offset int `json:"offset,omitempty" jsonschema:"1-based line number to start reading from, applied to all files (default: 1)"` + LineCount int `json:"line_count,omitempty" jsonschema:"Maximum number of lines to return per file (default: all remaining lines)"` } type ReadMultipleFilesMeta struct { @@ -141,14 +149,16 @@ type DirectoryTreeMeta struct { } type ReadFileArgs struct { - Path string `json:"path" jsonschema:"The file path to read"` + Path string `json:"path" jsonschema:"The file path to read"` + Offset int `json:"offset,omitempty" jsonschema:"1-based line number to start reading from (default: 1)"` + LineCount int `json:"line_count,omitempty" jsonschema:"Maximum number of lines to return (default: all remaining lines)"` } type ReadFileMeta struct { - Path string `json:"path"` - Content string `json:"content"` - LineCount int `json:"lineCount"` - Error string `json:"error,omitempty"` + Path string `json:"path"` + Content string `json:"content"` + TotalLines int `json:"totalLines"` + Error string `json:"error,omitempty"` } type Edit struct { @@ -226,7 +236,7 @@ func (t *FilesystemTool) Tools(context.Context) ([]tools.Tool, error) { { Name: ToolNameReadFile, Category: "filesystem", - Description: "Read the complete contents of a file from the file system.", + Description: "Read the contents of a file from the file system.", Parameters: tools.MustSchemaFor[ReadFileArgs](), OutputSchema: tools.MustSchemaFor[string](), Handler: tools.NewHandler(t.handleReadFile), @@ -483,6 +493,38 @@ func (t *FilesystemTool) handleListDirectory(_ context.Context, args ListDirecto }, nil } +// applyLineWindow slices lines from a file's content according to offset (1-based) and +// lineCount (0 means all remaining lines). It returns the windowed content and the total +// line count of the original. A header is prepended when only a subset is returned. +func applyLineWindow(content, path string, offset, lineCount int) (windowed string, totalLines int) { + lines := strings.Split(content, "\n") + totalLines = len(lines) + + // Normalise offset: default to 1, clamp to valid range + if offset <= 0 { + offset = 1 + } + if offset > totalLines { + offset = totalLines + } + + // Convert to 0-based index + from := offset - 1 + to := totalLines + if lineCount > 0 && from+lineCount < totalLines { + to = from + lineCount + } + + windowed = strings.Join(lines[from:to], "\n") + + // Prepend a header only when we are returning a subset of the file + if from > 0 || to < totalLines { + windowed = fmt.Sprintf("[Showing lines %d-%d of %d from %s]\n%s", offset, to, totalLines, path, windowed) + } + + return windowed, totalLines +} + func (t *FilesystemTool) handleReadFile(_ context.Context, args ReadFileArgs) (*tools.ToolCallResult, error) { resolvedPath := t.resolvePath(args.Path) @@ -504,10 +546,11 @@ func (t *FilesystemTool) handleReadFile(_ context.Context, args ReadFileArgs) (* }, nil } + windowed, totalLines := applyLineWindow(string(content), args.Path, args.Offset, args.LineCount) return &tools.ToolCallResult{ - Output: string(content), + Output: windowed, Meta: ReadFileMeta{ - LineCount: strings.Count(string(content), "\n") + 1, + TotalLines: totalLines, }, }, nil } @@ -545,12 +588,13 @@ func (t *FilesystemTool) handleReadMultipleFiles(ctx context.Context, args ReadM continue } + windowed, totalLines := applyLineWindow(string(content), path, args.Offset, args.LineCount) contents = append(contents, PathContent{ Path: path, - Content: string(content), + Content: windowed, }) - entry.Content = string(content) - entry.LineCount = strings.Count(string(content), "\n") + 1 + entry.Content = windowed + entry.TotalLines = totalLines meta.Files = append(meta.Files, entry) } diff --git a/pkg/tui/components/tool/readfile/readfile.go b/pkg/tui/components/tool/readfile/readfile.go index 60e619b8d..e56afcba6 100644 --- a/pkg/tui/components/tool/readfile/readfile.go +++ b/pkg/tui/components/tool/readfile/readfile.go @@ -28,5 +28,5 @@ func extractResult(msg *types.Message) string { if meta.Error != "" { return meta.Error } - return fmt.Sprintf("%d lines", meta.LineCount) + return fmt.Sprintf("%d lines", meta.TotalLines) } diff --git a/pkg/tui/components/tool/readmultiplefiles/readmultiplefiles.go b/pkg/tui/components/tool/readmultiplefiles/readmultiplefiles.go index 6f386ef3a..776d3cad9 100644 --- a/pkg/tui/components/tool/readmultiplefiles/readmultiplefiles.go +++ b/pkg/tui/components/tool/readmultiplefiles/readmultiplefiles.go @@ -99,7 +99,7 @@ func formatSummaryLines(meta *builtin.ReadMultipleFilesMeta) []fileSummary { if file.Error != "" { output = " " + file.Error } else { - output = fmt.Sprintf(" %d lines", file.LineCount) + output = fmt.Sprintf(" %d lines", file.TotalLines) } summaries = append(summaries, fileSummary{