Modernize provider support
This commit is contained in:
+91
-1
@@ -8,7 +8,8 @@ from cmdforge.runner import (
|
||||
execute_prompt_step,
|
||||
execute_code_step,
|
||||
run_tool,
|
||||
create_argument_parser
|
||||
create_argument_parser,
|
||||
collect_custom_args
|
||||
)
|
||||
from cmdforge.tool import Tool, ToolArgument, PromptStep, CodeStep
|
||||
from cmdforge.providers import ProviderResult
|
||||
@@ -246,6 +247,47 @@ class TestExecutePromptStep:
|
||||
# Should use override, not step's provider
|
||||
assert mock_call.call_args[0][0] == "gpt4"
|
||||
|
||||
@patch('cmdforge.runner.call_provider')
|
||||
def test_prompt_file_loaded_relative_to_tool_dir(self, mock_call, tmp_path):
|
||||
mock_call.return_value = ProviderResult(text="response", success=True)
|
||||
tool_dir = tmp_path / "tool"
|
||||
tool_dir.mkdir()
|
||||
(tool_dir / "prompt.txt").write_text("Summarize: {input}")
|
||||
|
||||
step = PromptStep(
|
||||
prompt="",
|
||||
provider="claude",
|
||||
output_var="out",
|
||||
prompt_file="prompt.txt",
|
||||
plain_text=True,
|
||||
)
|
||||
output, success = execute_prompt_step(
|
||||
step,
|
||||
{"input": "file text"},
|
||||
base_dir=tool_dir,
|
||||
)
|
||||
|
||||
assert success is True
|
||||
assert output == "response"
|
||||
assert mock_call.call_args[0][1] == "Summarize: file text"
|
||||
|
||||
def test_prompt_file_rejects_path_traversal(self, tmp_path):
|
||||
tool_dir = tmp_path / "tool"
|
||||
tool_dir.mkdir()
|
||||
(tmp_path / "outside.txt").write_text("Nope")
|
||||
|
||||
step = PromptStep(
|
||||
prompt="",
|
||||
provider="mock",
|
||||
output_var="out",
|
||||
prompt_file="../outside.txt",
|
||||
plain_text=True,
|
||||
)
|
||||
output, success = execute_prompt_step(step, {"input": ""}, base_dir=tool_dir)
|
||||
|
||||
assert success is False
|
||||
assert output == ""
|
||||
|
||||
|
||||
class TestStructuredOutput:
|
||||
"""Tests for structured output enforcement."""
|
||||
@@ -685,6 +727,38 @@ result = multiply_all([1, 2, 3])
|
||||
assert success is True
|
||||
assert outputs["result"] == [10, 20, 30]
|
||||
|
||||
def test_code_file_loaded_relative_to_tool_dir(self, tmp_path):
|
||||
tool_dir = tmp_path / "tool"
|
||||
tool_dir.mkdir()
|
||||
(tool_dir / "process.py").write_text("result = input.upper()")
|
||||
|
||||
step = CodeStep(code="", code_file="process.py", output_var="result")
|
||||
outputs, success = execute_code_step(
|
||||
step,
|
||||
{"input": "hello"},
|
||||
step_num=1,
|
||||
base_dir=tool_dir,
|
||||
)
|
||||
|
||||
assert success is True
|
||||
assert outputs["result"] == "HELLO"
|
||||
|
||||
def test_code_file_rejects_path_traversal(self, tmp_path):
|
||||
tool_dir = tmp_path / "tool"
|
||||
tool_dir.mkdir()
|
||||
(tmp_path / "outside.py").write_text("result = 'bad'")
|
||||
|
||||
step = CodeStep(code="", code_file="../outside.py", output_var="result")
|
||||
outputs, success = execute_code_step(
|
||||
step,
|
||||
{"input": ""},
|
||||
step_num=1,
|
||||
base_dir=tool_dir,
|
||||
)
|
||||
|
||||
assert success is False
|
||||
assert outputs == {}
|
||||
|
||||
|
||||
class TestRunTool:
|
||||
"""Tests for run_tool function."""
|
||||
@@ -920,3 +994,19 @@ class TestCreateArgumentParser:
|
||||
|
||||
assert args.input_file == "input.txt"
|
||||
assert args.output_file == "output.txt"
|
||||
|
||||
def test_collect_custom_args_uses_parser_namespace(self):
|
||||
tool = Tool(
|
||||
name="test",
|
||||
arguments=[
|
||||
ToolArgument(flag="--max-size", variable="max_size", default="100"),
|
||||
ToolArgument(flag="-f", variable="format"),
|
||||
]
|
||||
)
|
||||
parser = create_argument_parser(tool)
|
||||
args = parser.parse_args(["--max-size", "50", "-f", "json"])
|
||||
|
||||
assert collect_custom_args(tool, args) == {
|
||||
"max_size": "50",
|
||||
"format": "json",
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user