fix(cato_networks): harden output anonymize handling and restructure nested UI routes

Guard against empty redacted_output and empty all_redacted_messages from Cato.
Restructure nested admin UI HTML exports to index.html so extensionless routes work.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Sameer Kankute 2026-05-28 22:52:12 +05:30
parent 9b0a7c515c
commit f4d247d0b9
No known key found for this signature in database
16 changed files with 38 additions and 3 deletions

View file

@ -205,9 +205,11 @@ class CatoNetworksGuardrail(CustomGuardrail):
redacted_chat = res.get("redacted_chat", None)
if action_type and action_type == "anonymize_action" and redacted_chat:
return {
"redacted_output": redacted_chat["all_redacted_messages"][-1]["content"]
}
all_redacted = redacted_chat.get("all_redacted_messages") or []
if all_redacted:
return {
"redacted_output": all_redacted[-1]["content"]
}
return {"redacted_output": output}
def _handle_block_action_on_output(

View file

@ -703,6 +703,39 @@ async def test_post_call_success_hook_anonymize_action_applies_empty_redacted_ou
assert result.choices[0].message.content == ""
@pytest.mark.asyncio
async def test_post_call_success_hook_anonymize_action_empty_redacted_messages_keeps_content():
guard = _make_guardrail()
request_data = {"messages": [{"role": "user", "content": "hi"}]}
anonymize_response = _make_response(
{
"analysis_result": {"policy_drill_down": {"PII": {}}},
"required_action": {"action_type": "anonymize_action", "policy_name": "PII"},
"redacted_chat": {"all_redacted_messages": []},
}
)
llm_response = ModelResponse(
choices=[
{
"finish_reason": "stop",
"index": 0,
"message": {"content": "secret PII", "role": "assistant"},
}
]
)
with patch(
"litellm.llms.custom_httpx.http_handler.AsyncHTTPHandler.post",
return_value=anonymize_response,
):
result = await guard.async_post_call_success_hook(
data=request_data,
response=llm_response,
user_api_key_dict=UserAPIKeyAuth(),
)
assert isinstance(result, ModelResponse)
assert result.choices[0].message.content == "secret PII"
@pytest.mark.asyncio
async def test_post_call_success_hook_no_action_keeps_content():
guard = _make_guardrail()