Merge branch 'main' into chore/runtime-state-event-bus

# Conflicts:
#	lib/crewai/src/crewai/llms/providers/openai/completion.py
#	lib/devtools/pyproject.toml
#	uv.lock
This commit is contained in:
Greyson LaLonde
2026-04-07 00:45:42 +08:00
3 changed files with 124 additions and 106 deletions

View File

@@ -17,7 +17,15 @@ from openai.types.chat import (
)
from openai.types.chat.chat_completion import Choice
from openai.types.chat.chat_completion_chunk import ChoiceDelta
from openai.types.responses import Response
from openai.types.responses import (
Response,
ResponseCodeInterpreterToolCall,
ResponseComputerToolCall,
ResponseFileSearchToolCall,
ResponseFunctionToolCall,
ResponseFunctionWebSearch,
ResponseReasoningItem,
)
from pydantic import BaseModel, PrivateAttr, model_validator
from crewai.events.types.llm_events import LLMCallType
@@ -1350,18 +1358,16 @@ class OpenAICompletion(BaseLLM):
)
for item in response.output:
item_type = item.type
if item_type == "web_search_call":
if isinstance(item, ResponseFunctionWebSearch):
result.web_search_results.append(
WebSearchResult(
id=item.id,
status=item.status, # type: ignore[union-attr]
type=item_type,
status=item.status,
type=item.type,
)
)
elif item_type == "file_search_call":
elif isinstance(item, ResponseFileSearchToolCall):
file_results: list[FileSearchResultItem] = (
[
FileSearchResultItem(
@@ -1371,84 +1377,83 @@ class OpenAICompletion(BaseLLM):
score=r.score,
attributes=r.attributes,
)
for r in item.results # type: ignore[union-attr]
for r in item.results
]
if item.results # type: ignore[union-attr]
if item.results
else []
)
result.file_search_results.append(
FileSearchResult(
id=item.id,
status=item.status, # type: ignore[union-attr]
type=item_type,
queries=list(item.queries), # type: ignore[union-attr]
status=item.status,
type=item.type,
queries=list(item.queries),
results=file_results,
)
)
elif item_type == "code_interpreter_call":
elif isinstance(item, ResponseCodeInterpreterToolCall):
code_results: list[
CodeInterpreterLogResult | CodeInterpreterFileResult
] = []
for r in item.results: # type: ignore[union-attr]
if r.type == "logs": # type: ignore[union-attr]
for r in item.outputs or []:
if r.type == "logs":
code_results.append(
CodeInterpreterLogResult(type="logs", logs=r.logs) # type: ignore[union-attr]
CodeInterpreterLogResult(type="logs", logs=r.logs)
)
elif r.type == "files": # type: ignore[union-attr]
files_data = [
{"file_id": f.file_id, "mime_type": f.mime_type}
for f in r.files # type: ignore[union-attr]
]
elif r.type == "image":
code_results.append(
CodeInterpreterFileResult(type="files", files=files_data)
CodeInterpreterFileResult(
type="files",
files=[{"url": r.url}],
)
)
result.code_interpreter_results.append(
CodeInterpreterResult(
id=item.id,
status=item.status, # type: ignore[union-attr]
type=item_type,
code=item.code, # type: ignore[union-attr]
container_id=item.container_id, # type: ignore[union-attr]
status=item.status,
type=item.type,
code=item.code,
container_id=item.container_id,
results=code_results,
)
)
elif item_type == "computer_call":
action_dict = item.action.model_dump() if item.action else {} # type: ignore[union-attr]
elif isinstance(item, ResponseComputerToolCall):
action_dict = item.action.model_dump() if item.action else {}
safety_checks = [
{"id": c.id, "code": c.code, "message": c.message}
for c in item.pending_safety_checks # type: ignore[union-attr]
for c in item.pending_safety_checks
]
result.computer_use_results.append(
ComputerUseResult(
id=item.id,
status=item.status, # type: ignore[union-attr]
type=item_type,
call_id=item.call_id, # type: ignore[union-attr]
status=item.status,
type=item.type,
call_id=item.call_id,
action=action_dict,
pending_safety_checks=safety_checks,
)
)
elif item_type == "reasoning":
summaries = [{"type": s.type, "text": s.text} for s in item.summary] # type: ignore[union-attr]
elif isinstance(item, ResponseReasoningItem):
summaries = [{"type": s.type, "text": s.text} for s in item.summary]
result.reasoning_summaries.append(
ReasoningSummary(
id=item.id,
status=item.status, # type: ignore[union-attr]
type=item_type,
status=item.status,
type=item.type,
summary=summaries,
encrypted_content=item.encrypted_content, # type: ignore[union-attr]
encrypted_content=item.encrypted_content,
)
)
elif item_type == "function_call":
elif isinstance(item, ResponseFunctionToolCall):
result.function_calls.append(
{
"id": item.call_id, # type: ignore[union-attr]
"name": item.name, # type: ignore[union-attr]
"arguments": item.arguments, # type: ignore[union-attr]
"id": item.call_id,
"name": item.name,
"arguments": item.arguments,
}
)

View File

@@ -12,7 +12,7 @@ private = true
dependencies = [
"click~=8.1.7",
"toml~=0.10.2",
"openai~=2.30.0",
"openai>=1.83.0,<3",
"python-dotenv~=1.1.1",
"pygithub~=1.59.1",
"rich>=13.9.4",