# SPDX-License-Identifier: AGPL-3.0-only # Copyright 2026-present the Unsloth AI Inc. team. All rights reserved. See /studio/LICENSE.AGPL-3.0 from __future__ import annotations import json import sys from pathlib import Path _BACKEND_DIR = str(Path(__file__).resolve().parent.parent) if _BACKEND_DIR not in sys.path: sys.path.insert(0, _BACKEND_DIR) from core.inference.tool_loop_controller import ( ToolLoopController, canonical_tool_call_key, coerce_tool_arguments, status_for_tool, strip_result_for_model, tool_event_provenance, ) def _tool(name: str) -> dict: return {"type": "function", "function": {"name": name}} def _call( name: str, args, call_id: str = "call_0", ) -> dict: return { "id": call_id, "type": "function", "function": { "name": name, "arguments": json.dumps(args) if isinstance(args, dict) else args, }, } def test_canonical_tool_call_key_sorts_arguments(): a = canonical_tool_call_key("web_search", {"query": "gpu", "limit": 5}) b = canonical_tool_call_key("web_search", {"limit": 5, "query": "gpu"}) c = canonical_tool_call_key("python", {"limit": 5, "query": "gpu"}) assert a == b assert a != c assert a == 'web_search:{"limit":5,"query":"gpu"}' def test_coerce_tool_arguments_parses_json_and_heals_raw_strings(): parsed = coerce_tool_arguments('{"query":"gpu prices"}', heal = True) healed = coerce_tool_arguments("print(1)", heal = True, tool_name = "python") raw = coerce_tool_arguments("not-json", heal = False, tool_name = "python") assert parsed.arguments == {"query": "gpu prices"} assert not parsed.healed assert healed.arguments == {"code": "print(1)"} assert healed.healed assert raw.arguments == {"raw": "not-json"} assert not raw.healed def test_status_and_provenance_match_local_event_conventions(): assert status_for_tool("web_search", {"query": "gpus"}) == "Searching: gpus" assert ( status_for_tool("web_search", {"url": "https://www.example.com/a"}) == "Reading: example.com" ) assert status_for_tool("python", {"code": "print(1)\nprint(2)"}) == "Running Python: print(1)" assert tool_event_provenance(healed = True, forced = False, provisional = None) == { "source": "local", "healed": True, } def test_prepare_execute_builds_visible_events_and_model_tool_message(): controller = ToolLoopController(tools = [_tool("web_search")]) decision = controller.prepare_call(_call("web_search", {"query": "gpu prices"})) assert decision.should_execute assert decision.emit_visible_events assert decision.status_text == "Searching: gpu prices" assert decision.tool_start_payload()["arguments"] == {"query": "gpu prices"} assert decision.tool_start_event()["type"] == "tool_start" assert decision.as_assistant_tool_call()["function"]["arguments"] == '{"query":"gpu prices"}' completion = controller.record_result(decision, "Search result\n__IMAGES__:{...}") assert completion.tool_end_payload()["result"] == "Search result\n__IMAGES__:{...}" assert completion.tool_end_event()["type"] == "tool_end" assert completion.tool_message() == { "role": "tool", "name": "web_search", "content": "Search result", "tool_call_id": "call_0", } def test_successful_duplicate_is_internal_noop_and_keeps_remaining_tools(): controller = ToolLoopController(tools = [_tool("web_search"), _tool("python")]) first = controller.prepare_call(_call("web_search", {"query": "gpu prices"}, "call_a")) controller.record_result(first, "ok") duplicate = controller.prepare_call(_call("web_search", {"query": "gpu prices"}, "call_b")) completion = controller.record_noop(duplicate) assert duplicate.action == "duplicate" assert not duplicate.should_execute assert not duplicate.emit_visible_events duplicate_nudge = completion.model_message()["content"] assert "already completed successfully" in duplicate_nudge assert "different enabled tool" in duplicate_nudge assert completion.model_message()["role"] == "user" assert not controller.force_final_answer assert [tool["function"]["name"] for tool in controller.active_tools()] == [ "web_search", "python", ] def test_repeated_successful_duplicate_becomes_terminal_after_one_recovery_nudge(): controller = ToolLoopController(tools = [_tool("web_search"), _tool("python")]) first = controller.prepare_call(_call("web_search", {"query": "gpu prices"}, "call_a")) controller.record_result(first, "ok") duplicate_one = controller.prepare_call(_call("web_search", {"query": "gpu prices"}, "call_b")) completion_one = controller.record_noop(duplicate_one) assert duplicate_one.action == "duplicate" assert "already completed successfully" in completion_one.model_message()["content"] assert not controller.force_final_answer assert [tool["function"]["name"] for tool in controller.active_tools()] == [ "web_search", "python", ] duplicate_two = controller.prepare_call(_call("web_search", {"query": "gpu prices"}, "call_c")) completion_two = controller.record_noop(duplicate_two) assert duplicate_two.action == "duplicate" assert "already completed successfully" in completion_two.model_message()["content"] assert controller.force_final_answer assert controller.active_tools() == [] def test_failed_call_does_not_block_retry(): controller = ToolLoopController(tools = [_tool("web_search")]) first = controller.prepare_call(_call("web_search", {"query": "gpu prices"})) controller.record_result(first, "Error: temporary failure") retry = controller.prepare_call(_call("web_search", {"query": "gpu prices"})) assert retry.should_execute assert retry.action == "execute" def test_empty_enabled_tool_list_blocks_all_tool_calls(): controller = ToolLoopController(tools = []) decision = controller.prepare_call(_call("web_search", {"query": "gpu prices"})) completion = controller.record_noop(decision) assert decision.action == "disabled" assert not decision.emit_visible_events assert completion.model_message()["role"] == "user" assert "not enabled" in completion.model_message()["content"] assert controller.force_final_answer assert controller.active_tools() == [] def test_disabled_tool_is_internal_noop_not_visible_tool_error(): controller = ToolLoopController(tools = [_tool("web_search")]) decision = controller.prepare_call(_call("python", {"code": "print(1)"})) completion = controller.record_noop(decision) assert decision.action == "disabled" assert not decision.emit_visible_events assert completion.model_message()["role"] == "user" assert "not enabled" in completion.model_message()["content"] assert controller.force_final_answer assert controller.active_tools() == [] def test_render_html_success_filters_active_tools_and_repeat_is_internal(): controller = ToolLoopController(tools = [_tool("render_html"), _tool("web_search")]) assert [t["function"]["name"] for t in controller.active_tools()] == [ "render_html", "web_search", ] first = controller.prepare_call(_call("render_html", {"code": ""}, "call_html_1")) controller.record_result(first, "Rendered HTML canvas: Demo") assert [t["function"]["name"] for t in controller.active_tools()] == ["web_search"] repeat = controller.prepare_call(_call("render_html", {"code": ""}, "call_html_2")) completion = controller.record_noop(repeat) assert repeat.action == "render_html_repeat" assert not repeat.emit_visible_events assert completion.model_message()["role"] == "user" assert "Do not call render_html again" in completion.model_message()["content"] assert controller.force_final_answer assert controller.active_tools() == [] def test_strip_result_for_model_removes_frontend_image_sentinel(): assert strip_result_for_model('text\n__IMAGES__:{"paths":[]}') == "text" assert strip_result_for_model("text __IMAGES__:payload") == "text" assert strip_result_for_model("plain text") == "plain text"