| from collections.abc import Mapping |
| from typing import Any |
|
|
|
|
| def _mapping_get(value: Any, key: str) -> Any: |
| if isinstance(value, Mapping): |
| return value.get(key) |
|
|
| getter = getattr(value, "get", None) |
| if callable(getter): |
| try: |
| return getter(key, None) |
| except TypeError: |
| return getter(key) |
| return None |
|
|
|
|
| def get_runtime_context(runtime: Any) -> dict[str, Any]: |
| """Return runtime context as dict; tolerate missing/None context.""" |
| context = getattr(runtime, "context", None) |
| if isinstance(context, Mapping): |
| return dict(context) |
| if context is not None and hasattr(context, "items"): |
| return dict(context.items()) |
| return {} |
|
|
|
|
| def get_runtime_thread_id(runtime: Any) -> str | None: |
| """Resolve thread_id from runtime context first, then runtime config fallbacks.""" |
| context = get_runtime_context(runtime) |
| thread_id = context.get("thread_id") |
| if thread_id: |
| return str(thread_id) |
|
|
| config = getattr(runtime, "config", None) |
| metadata = _mapping_get(config, "metadata") |
| if metadata is not None: |
| thread_id = _mapping_get(metadata, "thread_id") |
| if thread_id: |
| return str(thread_id) |
|
|
| configurable = _mapping_get(config, "configurable") |
| if configurable is not None: |
| thread_id = _mapping_get(configurable, "thread_id") |
| if thread_id: |
| return str(thread_id) |
|
|
| return None |
|
|