Skip to content

Commit 45fd684

Browse files
he-yufengKBVsent
authored andcommitted
Fix TypeError when API returns null choices (AstrBotDevs#6313)
* Fix CreateSkillPayloadTool array schema missing items field The payload parameter's anyOf array variant lacked an items field, causing Gemini API to reject the tool declaration with 400 Bad Request: 'parameters.properties[payload].any_of[1].items: missing field.' Add items: {type: object} to the array variant to satisfy the Gemini API requirement for array type schemas. Fixes AstrBotDevs#6279 * Fix TypeError when OpenAI-compatible API returns null choices Some providers (e.g. OpenRouter) may return a completion where choices is None rather than an empty list — for instance on rate limiting, content filtering, or transient errors. The existing code used len(completion.choices) which throws TypeError on None. Replace all len(...choices) == 0 checks with 'not ... .choices' which handles both None and empty list. Affects _query_stream, _parse_openai_completion, and _extract_reasoning_content. Fixes AstrBotDevs#6252
1 parent edfca31 commit 45fd684

File tree

2 files changed

+4
-4
lines changed

2 files changed

+4
-4
lines changed

astrbot/core/computer/tools/neo_skills.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ class CreateSkillPayloadTool(NeoSkillToolBase):
164164
"type": "object",
165165
"properties": {
166166
"payload": {
167-
"anyOf": [{"type": "object"}, {"type": "array"}],
167+
"anyOf": [{"type": "object"}, {"type": "array", "items": {"type": "object"}}],
168168
"description": (
169169
"Skill payload JSON. Typical schema: {skill_markdown, inputs, outputs, meta}. "
170170
"This only stores content and returns payload_ref; it does not create a candidate or release."

astrbot/core/provider/sources/openai_source.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -311,7 +311,7 @@ async def _query_stream(
311311
state.handle_chunk(chunk)
312312
except Exception as e:
313313
logger.warning("Saving chunk state error: " + str(e))
314-
if len(chunk.choices) == 0:
314+
if not chunk.choices:
315315
continue
316316
delta = chunk.choices[0].delta
317317
# logger.debug(f"chunk delta: {delta}")
@@ -345,7 +345,7 @@ def _extract_reasoning_content(
345345
) -> str:
346346
"""Extract reasoning content from OpenAI ChatCompletion if available."""
347347
reasoning_text = ""
348-
if len(completion.choices) == 0:
348+
if not completion.choices:
349349
return reasoning_text
350350
if isinstance(completion, ChatCompletion):
351351
choice = completion.choices[0]
@@ -468,7 +468,7 @@ async def _parse_openai_completion(
468468
"""Parse OpenAI ChatCompletion into LLMResponse"""
469469
llm_response = LLMResponse("assistant")
470470

471-
if len(completion.choices) == 0:
471+
if not completion.choices:
472472
raise Exception("API 返回的 completion 为空。")
473473
choice = completion.choices[0]
474474

0 commit comments

Comments
 (0)