Extracts user content from an event dict and returns a types.Content object. Agent-emitted user-role events (e.g., task FRs synthesized by the Task Delegation API wrapper) are skipped — those are produced by the agent itself and carry a non-empty ``nodeInfo.path``. Re-feeding them to ``run
(event: dict)
| 278 | |
| 279 | |
| 280 | def _extract_user_content(event: dict) -> Optional[types.Content]: |
| 281 | """Extracts user content from an event dict and returns a types.Content object. |
| 282 | |
| 283 | Agent-emitted user-role events (e.g., task FRs synthesized by the Task |
| 284 | Delegation API wrapper) are skipped — those are produced by the agent |
| 285 | itself and carry a non-empty ``nodeInfo.path``. Re-feeding them to |
| 286 | ``runner.run`` would trigger extra LLM calls. |
| 287 | """ |
| 288 | if event.get("author") != "user": |
| 289 | return None |
| 290 | |
| 291 | # Real external user input has no node path; agent-emitted events do. |
| 292 | if event.get("nodeInfo", {}).get("path"): |
| 293 | return None |
| 294 | |
| 295 | content_dict = event.get("content", {}) |
| 296 | if not content_dict: |
| 297 | return None |
| 298 | |
| 299 | parts = content_dict.get("parts", []) |
| 300 | real_parts = [] |
| 301 | for p in parts: |
| 302 | if "functionResponse" in p: |
| 303 | fr = p["functionResponse"] |
| 304 | real_parts.append( |
| 305 | types.Part( |
| 306 | function_response=types.FunctionResponse( |
| 307 | id=fr.get("id"), |
| 308 | name=fr.get("name"), |
| 309 | response=fr.get("response"), |
| 310 | ) |
| 311 | ) |
| 312 | ) |
| 313 | elif "text" in p: |
| 314 | real_parts.append(types.Part(text=p["text"])) |
| 315 | elif "functionCall" in p: |
| 316 | fc = p["functionCall"] |
| 317 | real_parts.append( |
| 318 | types.Part( |
| 319 | function_call=types.FunctionCall( |
| 320 | id=fc.get("id"), |
| 321 | name=fc.get("name"), |
| 322 | args=fc.get("args"), |
| 323 | ) |
| 324 | ) |
| 325 | ) |
| 326 | |
| 327 | if real_parts: |
| 328 | return types.Content(role="user", parts=real_parts) |
| 329 | return None |
| 330 | |
| 331 | |
| 332 | def _remap_node_path(path: str, id_map: dict[str, str]) -> str: |
no test coverage detected