fix(gateway): guard chained .get() against None intermediate values

.get("key", {}) only applies the default when the key is ABSENT.
When the key exists with value None (null in JSON), .get() returns
None and the subsequent .get() raises AttributeError.

Fix: replace .get("key", {}).get(...) with (.get("key") or {}).get(...)
which handles both missing keys AND None values.

8 instances across 6 files:
- gateway/run.py: tool_call function name check
- acp_adapter/server.py: tool name/description extraction
- gateway/platforms/qqbot/onboard.py: API response task_id
- gateway/platforms/yuanbao.py: message content parsing (x2)
- gateway/platforms/slack.py: block text extraction (x2)
- tui_gateway/server.py: error message extraction
This commit is contained in:
annguyenNous 2026-05-29 22:44:14 +07:00 committed by Teknium
parent 241bc112e8
commit c5b62fdbae
6 changed files with 10 additions and 10 deletions

View file

@ -1936,8 +1936,8 @@ class HermesACPAgent(acp.Agent):
return "No tools available."
lines = [f"Available tools ({len(tools)}):"]
for t in tools:
name = t.get("function", {}).get("name", "?")
desc = t.get("function", {}).get("description", "")
name = (t.get("function") or {}).get("name", "?")
desc = (t.get("function") or {}).get("description", "")
# Truncate long descriptions
if len(desc) > 80:
desc = desc[:77] + "..."

View file

@ -100,7 +100,7 @@ def _create_bind_task(timeout: float = ONBOARD_API_TIMEOUT) -> Tuple[str, str]:
if data.get("retcode") != 0:
raise RuntimeError(data.get("msg", "create_bind_task failed"))
task_id = data.get("data", {}).get("task_id")
task_id = (data.get("data") or {}).get("task_id")
if not task_id:
raise RuntimeError("create_bind_task: missing task_id in response")

View file

@ -2153,7 +2153,7 @@ class GroupAtGuardMiddleware(InboundMiddleware):
for elem in msg_body:
if elem.get("msg_type") != "TIMCustomElem":
continue
data_str = elem.get("msg_content", {}).get("data", "")
data_str = (elem.get("msg_content") or {}).get("data", "")
if not data_str:
continue
try:
@ -2172,7 +2172,7 @@ class GroupAtGuardMiddleware(InboundMiddleware):
for elem in msg_body:
if elem.get("msg_type") != "TIMCustomElem":
continue
data_str = elem.get("msg_content", {}).get("data", "")
data_str = (elem.get("msg_content") or {}).get("data", "")
if not data_str:
continue
try:

View file

@ -15110,7 +15110,7 @@ class GatewayRunner(GatewayAuthorizationMixin, GatewayKanbanWatchersMixin, Gatew
has_agent_tts = any(
msg.get("role") == "assistant"
and any(
tc.get("function", {}).get("name") == "text_to_speech"
(tc.get("function") or {}).get("name") == "text_to_speech"
for tc in (msg.get("tool_calls") or [])
)
for msg in agent_messages

View file

@ -6683,7 +6683,7 @@ class SlackAdapter(BasePlatformAdapter):
original_text = ""
for block in message.get("blocks", []):
if block.get("type") == "section":
original_text = block.get("text", {}).get("text", "")
original_text = (block.get("text") or {}).get("text", "")
break
# Slack re-escapes HTML entities in the interaction payload
@ -6862,7 +6862,7 @@ class SlackAdapter(BasePlatformAdapter):
original_text = ""
for block in message.get("blocks", []):
if block.get("type") == "section":
original_text = block.get("text", {}).get("text", "")
original_text = (block.get("text") or {}).get("text", "")
break
# Slack re-escapes HTML entities in the interaction payload
@ -6964,7 +6964,7 @@ class SlackAdapter(BasePlatformAdapter):
original_text = ""
for block in message.get("blocks", []):
if block.get("type") == "section":
original_text = block.get("text", {}).get("text", "")
original_text = (block.get("text") or {}).get("text", "")
break
from tools import clarify_gateway as _clarify_mod

View file

@ -10044,7 +10044,7 @@ def _(rid, params: dict) -> dict:
"error",
sid,
{
"message": err.get("error", {}).get(
"message": (err.get("error") or {}).get(
"message", "agent initialization failed"
)
},