From 699da0decdd10a982942fa835aefc894b54e32ba Mon Sep 17 00:00:00 2001
From: "pre-commit-ci[bot]"
<66853113+pre-commit-ci[bot]@users.noreply.github.com>
Date: Fri, 22 May 2026 14:43:00 +0000
Subject: [PATCH] [pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
---
studio/backend/core/inference/llama_cpp.py | 76 +++++++++------
.../core/inference/safetensors_agentic.py | 71 +++++++-------
.../tests/test_validation_retry_loop.py | 97 ++++++++++++-------
3 files changed, 142 insertions(+), 102 deletions(-)
diff --git a/studio/backend/core/inference/llama_cpp.py b/studio/backend/core/inference/llama_cpp.py
index 762eeb22d5..da25d91678 100644
--- a/studio/backend/core/inference/llama_cpp.py
+++ b/studio/backend/core/inference/llama_cpp.py
@@ -5040,12 +5040,16 @@ class LlamaCppBackend:
_vdec = None
if not isinstance(_vdec, dict):
_validation_problem = (
- "malformed_args", _vtc, _vname,
+ "malformed_args",
+ _vtc,
+ _vname,
)
break
elif not isinstance(_vraw, dict):
_validation_problem = (
- "malformed_args", _vtc, _vname,
+ "malformed_args",
+ _vtc,
+ _vname,
)
break
@@ -5055,42 +5059,50 @@ class LlamaCppBackend:
_vcall_id = _vtc.get("id")
if _kind == "unknown_tool" and _vcall_id:
_allowed_list = ", ".join(sorted(_allowed_tool_names))
- conversation.append({
- "role": "tool",
- "tool_call_id": _vcall_id,
- "name": _vname,
- "content": (
- f"Error: tool '{_vname}' is not available. "
- f"Available tools: {_allowed_list}."
- ),
- })
+ conversation.append(
+ {
+ "role": "tool",
+ "tool_call_id": _vcall_id,
+ "name": _vname,
+ "content": (
+ f"Error: tool '{_vname}' is not available. "
+ f"Available tools: {_allowed_list}."
+ ),
+ }
+ )
elif _kind == "malformed_args" and _vcall_id:
- conversation.append({
- "role": "tool",
- "tool_call_id": _vcall_id,
- "name": _vname,
- "content": (
- f"Error: arguments to '{_vname}' could not "
- "be parsed as a JSON object. Call "
- f"'{_vname}' again with valid JSON object "
- "arguments."
- ),
- })
+ conversation.append(
+ {
+ "role": "tool",
+ "tool_call_id": _vcall_id,
+ "name": _vname,
+ "content": (
+ f"Error: arguments to '{_vname}' could not "
+ "be parsed as a JSON object. Call "
+ f"'{_vname}' again with valid JSON object "
+ "arguments."
+ ),
+ }
+ )
else:
# No usable call id: user-role correction since
# OpenAI tool messages require a matching id.
- conversation.append({
- "role": "user",
- "content": (
- "Your last tool call was malformed "
- "(missing id or function). Please "
- "re-issue it as a valid OpenAI "
- "function call."
- ),
- })
+ conversation.append(
+ {
+ "role": "user",
+ "content": (
+ "Your last tool call was malformed "
+ "(missing id or function). Please "
+ "re-issue it as a valid OpenAI "
+ "function call."
+ ),
+ }
+ )
logger.info(
"validation_retry kind=%s retries=%d/%d",
- _kind, _validation_retries, max_validation_retries,
+ _kind,
+ _validation_retries,
+ max_validation_retries,
)
yield {"type": "status", "text": ""}
continue
diff --git a/studio/backend/core/inference/safetensors_agentic.py b/studio/backend/core/inference/safetensors_agentic.py
index b7fbe680e5..196caf89f1 100644
--- a/studio/backend/core/inference/safetensors_agentic.py
+++ b/studio/backend/core/inference/safetensors_agentic.py
@@ -331,10 +331,7 @@ def run_safetensors_tool_loop(
v_decoded = json.loads(v_raw)
except (json.JSONDecodeError, ValueError):
v_decoded = None
- if (
- not isinstance(v_decoded, dict)
- and not auto_heal_tool_calls
- ):
+ if not isinstance(v_decoded, dict) and not auto_heal_tool_calls:
validation_problem = ("malformed_args", v_tc, v_name)
break
elif not isinstance(v_raw, dict):
@@ -348,39 +345,47 @@ def run_safetensors_tool_loop(
v_call_id = v_tc.get("id")
if v_kind == "unknown_tool" and v_call_id:
allowed_list = ", ".join(sorted(allowed_tool_names))
- conversation.append({
- "role": "tool",
- "tool_call_id": v_call_id,
- "name": v_name,
- "content": (
- f"Error: tool '{v_name}' is not available. "
- f"Available tools: {allowed_list}."
- ),
- })
+ conversation.append(
+ {
+ "role": "tool",
+ "tool_call_id": v_call_id,
+ "name": v_name,
+ "content": (
+ f"Error: tool '{v_name}' is not available. "
+ f"Available tools: {allowed_list}."
+ ),
+ }
+ )
elif v_kind == "malformed_args" and v_call_id:
- conversation.append({
- "role": "tool",
- "tool_call_id": v_call_id,
- "name": v_name,
- "content": (
- f"Error: arguments to '{v_name}' could not be "
- "parsed as a JSON object. Call "
- f"'{v_name}' again with valid JSON object "
- "arguments."
- ),
- })
+ conversation.append(
+ {
+ "role": "tool",
+ "tool_call_id": v_call_id,
+ "name": v_name,
+ "content": (
+ f"Error: arguments to '{v_name}' could not be "
+ "parsed as a JSON object. Call "
+ f"'{v_name}' again with valid JSON object "
+ "arguments."
+ ),
+ }
+ )
else:
- conversation.append({
- "role": "user",
- "content": (
- "Your last tool call was malformed (missing id "
- "or function). Please re-issue it as a valid "
- "OpenAI function call."
- ),
- })
+ conversation.append(
+ {
+ "role": "user",
+ "content": (
+ "Your last tool call was malformed (missing id "
+ "or function). Please re-issue it as a valid "
+ "OpenAI function call."
+ ),
+ }
+ )
logger.info(
"validation_retry kind=%s retries=%d/%d",
- v_kind, validation_retries, max_validation_retries,
+ v_kind,
+ validation_retries,
+ max_validation_retries,
)
yield {"type": "status", "text": ""}
continue
diff --git a/studio/backend/tests/test_validation_retry_loop.py b/studio/backend/tests/test_validation_retry_loop.py
index 719683e158..c137ba4271 100644
--- a/studio/backend/tests/test_validation_retry_loop.py
+++ b/studio/backend/tests/test_validation_retry_loop.py
@@ -21,7 +21,9 @@ class FakeExecuteTool:
self.results = list(results or [])
self.calls = []
- def __call__(self, name, arguments, *, cancel_event = None, timeout = None, session_id = None):
+ def __call__(
+ self, name, arguments, *, cancel_event = None, timeout = None, session_id = None
+ ):
self.calls.append((name, arguments))
return self.results.pop(0) if self.results else "OK"
@@ -62,11 +64,15 @@ class TestUnknownTool:
def test_unknown_tool_triggers_retry(self):
# Turn 1: hallucinated tool name "missing_tool".
# Turn 2: valid call after the corrective nudge.
- single_turn = _multi_turn([
- ['{"name":"missing_tool","arguments":{}}'],
- ['{"name":"web_search","arguments":{"query":"x"}}'],
- ["Done."],
- ])
+ single_turn = _multi_turn(
+ [
+ ['{"name":"missing_tool","arguments":{}}'],
+ [
+ '{"name":"web_search","arguments":{"query":"x"}}'
+ ],
+ ["Done."],
+ ]
+ )
exec_fn = FakeExecuteTool(["result"])
events = _collect(
run_safetensors_tool_loop(
@@ -87,12 +93,14 @@ class TestUnknownTool:
# the first two are retried; the third falls through to the
# existing per-tool error path (which never executes a real
# tool but emits an error result to the model).
- single_turn = _multi_turn([
- ['{"name":"missing_a","arguments":{}}'],
- ['{"name":"missing_b","arguments":{}}'],
- ['{"name":"missing_c","arguments":{}}'],
- ["Sorry, I cannot proceed."],
- ])
+ single_turn = _multi_turn(
+ [
+ ['{"name":"missing_a","arguments":{}}'],
+ ['{"name":"missing_b","arguments":{}}'],
+ ['{"name":"missing_c","arguments":{}}'],
+ ["Sorry, I cannot proceed."],
+ ]
+ )
exec_fn = FakeExecuteTool([])
events = _collect(
run_safetensors_tool_loop(
@@ -115,10 +123,12 @@ class TestUnknownTool:
# With max_validation_retries=0, the F3 arm never engages and
# behavior matches the pre-F3 path: the existing per-tool
# error message is emitted but no corrective re-entry happens.
- single_turn = _multi_turn([
- ['{"name":"missing","arguments":{}}'],
- ["bye"],
- ])
+ single_turn = _multi_turn(
+ [
+ ['{"name":"missing","arguments":{}}'],
+ ["bye"],
+ ]
+ )
exec_fn = FakeExecuteTool([])
events = _collect(
run_safetensors_tool_loop(
@@ -135,10 +145,7 @@ class TestUnknownTool:
tool_ends = [e for e in events if e["type"] == "tool_end"]
# Existing per-tool error path emits a tool_end with an Error
# result so the model sees the failure.
- assert any(
- "not enabled" in str(e.get("result", ""))
- for e in tool_ends
- )
+ assert any("not enabled" in str(e.get("result", "")) for e in tool_ends)
class TestMalformedArgs:
@@ -146,10 +153,14 @@ class TestMalformedArgs:
# With auto_heal_tool_calls=True (the default), string args are
# healed to {"query": "..."} for web_search. F3 leaves heal
# behavior intact and only catches strictly-impossible shapes.
- single_turn = _multi_turn([
- ['{"name":"web_search","arguments":"some text"}'],
- ["all done"],
- ])
+ single_turn = _multi_turn(
+ [
+ [
+ '{"name":"web_search","arguments":"some text"}'
+ ],
+ ["all done"],
+ ]
+ )
exec_fn = FakeExecuteTool(["ok"])
events = _collect(
run_safetensors_tool_loop(
@@ -168,11 +179,17 @@ class TestMalformedArgs:
def test_malformed_args_caught_when_heal_off(self):
# With auto_heal off, a non-dict arguments value is a hard
# malformed-args failure and the F3 arm catches it.
- single_turn = _multi_turn([
- ['{"name":"web_search","arguments":"not a dict"}'],
- ['{"name":"web_search","arguments":{"query":"sf"}}'],
- ["sunny"],
- ])
+ single_turn = _multi_turn(
+ [
+ [
+ '{"name":"web_search","arguments":"not a dict"}'
+ ],
+ [
+ '{"name":"web_search","arguments":{"query":"sf"}}'
+ ],
+ ["sunny"],
+ ]
+ )
exec_fn = FakeExecuteTool(["sunny in sf"])
events = _collect(
run_safetensors_tool_loop(
@@ -192,10 +209,12 @@ class TestNoOpCases:
def test_no_tools_no_validation(self):
# Empty tools list means allowed_tool_names is empty, so the
# F3 arm never engages.
- single_turn = _multi_turn([
- ['{"name":"anything","arguments":{}}'],
- ["done"],
- ])
+ single_turn = _multi_turn(
+ [
+ ['{"name":"anything","arguments":{}}'],
+ ["done"],
+ ]
+ )
exec_fn = FakeExecuteTool([])
events = _collect(
run_safetensors_tool_loop(
@@ -211,10 +230,14 @@ class TestNoOpCases:
def test_valid_call_no_retry_overhead(self):
# A clean valid call does not trigger F3 at all.
- single_turn = _multi_turn([
- ['{"name":"web_search","arguments":{"query":"x"}}'],
- ["final"],
- ])
+ single_turn = _multi_turn(
+ [
+ [
+ '{"name":"web_search","arguments":{"query":"x"}}'
+ ],
+ ["final"],
+ ]
+ )
exec_fn = FakeExecuteTool(["res"])
events = _collect(
run_safetensors_tool_loop(