File size: 1,453 Bytes
96341d9
f4111a5
 
 
96341d9
 
 
 
 
 
 
 
 
 
 
 
 
f4111a5
 
 
96341d9
 
 
 
f4111a5
 
 
 
 
 
 
 
 
 
 
96341d9
 
 
f4111a5
 
 
96341d9
 
 
f4111a5
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
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