mirror of
https://github.com/microsoft/agent-framework.git
synced 2026-06-16 21:04:09 +08:00
fixes Python: DevUI fails when uploading Pdf file (tested on Python Foundry Agent) (#2675)
Fixes #2652
This commit is contained in:
committed by
GitHub
Unverified
parent
551219cb55
commit
0675000f4b
@@ -182,14 +182,29 @@ class EntityDiscovery:
|
||||
f"{entity_id}.workflow",
|
||||
]
|
||||
|
||||
# Track import errors to provide meaningful feedback
|
||||
import_errors: list[tuple[str, Exception]] = []
|
||||
|
||||
for pattern in import_patterns:
|
||||
module = self._load_module_from_pattern(pattern)
|
||||
module, error = self._load_module_from_pattern(pattern)
|
||||
if error:
|
||||
import_errors.append((pattern, error))
|
||||
if module:
|
||||
# Find entity in module - pass entity_id so registration uses correct ID
|
||||
entity_obj = await self._find_entity_in_module(module, entity_id, str(dir_path))
|
||||
if entity_obj:
|
||||
return entity_obj
|
||||
|
||||
# If we have import errors, raise the most informative one
|
||||
if import_errors:
|
||||
# Prefer errors from the main module pattern (entity_id) or agent submodule
|
||||
for pattern, error in import_errors:
|
||||
if pattern == entity_id or pattern.endswith(".agent"):
|
||||
raise ValueError(f"Failed to load entity '{entity_id}': {error}") from error
|
||||
# Fall back to first error
|
||||
pattern, error = import_errors[0]
|
||||
raise ValueError(f"Failed to load entity '{entity_id}': {error}") from error
|
||||
|
||||
raise ValueError(f"No valid entity found in {dir_path}")
|
||||
# File-based entity
|
||||
module = self._load_module_from_file(dir_path, entity_id)
|
||||
@@ -632,31 +647,32 @@ class EntityDiscovery:
|
||||
return True
|
||||
return False
|
||||
|
||||
def _load_module_from_pattern(self, pattern: str) -> Any | None:
|
||||
def _load_module_from_pattern(self, pattern: str) -> tuple[Any | None, Exception | None]:
|
||||
"""Load module using import pattern.
|
||||
|
||||
Args:
|
||||
pattern: Import pattern to try
|
||||
|
||||
Returns:
|
||||
Loaded module or None if failed
|
||||
Tuple of (loaded module or None, error or None)
|
||||
"""
|
||||
try:
|
||||
# Check if module exists first
|
||||
spec = importlib.util.find_spec(pattern)
|
||||
if spec is None:
|
||||
return None
|
||||
return None, None
|
||||
|
||||
module = importlib.import_module(pattern)
|
||||
logger.debug(f"Successfully imported {pattern}")
|
||||
return module
|
||||
return module, None
|
||||
|
||||
except ModuleNotFoundError:
|
||||
logger.debug(f"Import pattern {pattern} not found")
|
||||
return None
|
||||
return None, None
|
||||
except Exception as e:
|
||||
# Capture the actual error for better error messages
|
||||
logger.warning(f"Error importing {pattern}: {e}")
|
||||
return None
|
||||
return None, e
|
||||
|
||||
def _load_module_from_file(self, file_path: Path, module_name: str) -> Any | None:
|
||||
"""Load module directly from file path.
|
||||
|
||||
@@ -642,12 +642,26 @@ class AgentFrameworkExecutor:
|
||||
media_type = "audio/mp4" if ext == "m4a" else f"audio/{ext}"
|
||||
|
||||
# Use file_data or file_url
|
||||
# Include filename in additional_properties for OpenAI/Azure file handling
|
||||
additional_props = {"filename": filename} if filename else None
|
||||
if file_data:
|
||||
# Assume file_data is base64, create data URI
|
||||
data_uri = f"data:{media_type};base64,{file_data}"
|
||||
contents.append(DataContent(uri=data_uri, media_type=media_type))
|
||||
contents.append(
|
||||
DataContent(
|
||||
uri=data_uri,
|
||||
media_type=media_type,
|
||||
additional_properties=additional_props,
|
||||
)
|
||||
)
|
||||
elif file_url:
|
||||
contents.append(DataContent(uri=file_url, media_type=media_type))
|
||||
contents.append(
|
||||
DataContent(
|
||||
uri=file_url,
|
||||
media_type=media_type,
|
||||
additional_properties=additional_props,
|
||||
)
|
||||
)
|
||||
|
||||
elif content_type == "function_approval_response":
|
||||
# Handle function approval response (DevUI extension)
|
||||
|
||||
@@ -537,9 +537,14 @@ class DevServer:
|
||||
except HTTPException:
|
||||
raise
|
||||
except ValueError as e:
|
||||
# ValueError from load_entity indicates entity not found or invalid
|
||||
# ValueError from load_entity - could be "not found" or "failed to load"
|
||||
error_str = str(e)
|
||||
error_msg = self._format_error(e, "Entity loading")
|
||||
raise HTTPException(status_code=404, detail=error_msg) from e
|
||||
# Use 404 for "not found", 422 for load failures (entity exists but can't load)
|
||||
if "not found" in error_str.lower() and "failed to load" not in error_str.lower():
|
||||
raise HTTPException(status_code=404, detail=error_msg) from e
|
||||
# Entity exists but failed to load (e.g., missing env vars, import errors)
|
||||
raise HTTPException(status_code=422, detail=error_msg) from e
|
||||
except Exception as e:
|
||||
error_msg = self._format_error(e, "Entity info retrieval")
|
||||
raise HTTPException(status_code=500, detail=error_msg) from e
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user