
    ֞iq                    |    d Z ddlmZ ddlZddlZddlZddlmZmZ ddl	m
Z
  ej                  e      ZddZd	dZy)
aE  
core/observability/decorators.py

Decorator patterns for automatic LLM tracing in Genesis agents.

Usage:
    @traced("agent_spawn")
    async def spawn_agent(prompt: str, model: str) -> str:
        ...

    @generation_tracked
    async def call_gemini(prompt: str) -> dict:
        return {
            "model": "gemini-flash",
            "prompt": prompt,
            "completion": response_text,
            "usage": {"input": 120, "output": 40},
        }

VERIFICATION_STAMP
Story: OBS-003
Verified By: parallel-builder
Verified At: 2026-02-25
Tests: 21/21
Coverage: 100%
    )annotationsN)AnyCallable)
get_tracerc                     d fd}|S )a>  
    Decorator that wraps an **async** function in a Langfuse trace.

    Creates a trace on entry, records a completion or error span on exit,
    and re-raises any exception unchanged so calling code is unaffected.

    Parameters
    ----------
    operation_name : str
        Human-readable name passed to ``GenesisTracer.trace()``.

    Returns
    -------
    Callable
        Decorated async function with identical signature.

    Example
    -------
    ::

        @traced("rlm_ingest")
        async def ingest_document(doc_id: str) -> bool:
            ...
    c                H     t        j                         d fd       }|S )Nc            
     .  K   dd l mc m} |j                         }|j	                  
	j
                  t        |       d      }t        j                         }	  	| i | d {   }t        j                         |z
  }|j                  |j                  
 dt        |d      dd       |S 7 K# t        $ rU}t        j                         |z
  }|j                  |j                  
 d	t        |d      d
t        |      d        d }~ww xY ww)Nr   )function
args_count)namemetadata	_complete   success)
duration_sstatus)trace_idr   r   _errorerror)r   r   r   )core.observability.decoratorsobservability
decoratorsr   trace__name__lentime	monotonicspanidround	Exceptionstr)argskwargs	_self_modtracerr   startresultdurationexcfnoperation_names            6/mnt/e/genesis-system/core/observability/decorators.pywrapperz*traced.<locals>.decorator.<locals>.wrapperE   s     >=))+FLL#&(kkTK ! E
 NN$E!42622>>+e3"XX*+95&+Ha&8"+    3  >>+e3"XX*+62&+Ha&8")!$S   s>   ADB4 &B2'A
B4 1D2B4 4	D=ADDDr#   r   r$   r   returnr   	functoolswraps)r+   r.   r,   s   ` r-   	decoratorztraced.<locals>.decoratorD   s&    		#	 
#	J     r+   r   r0   r    )r,   r4   s   ` r-   tracedr8   *   s    4'R r5   c                D     t        j                         d fd       }|S )a  
    Decorator for **async** LLM API call functions that records model,
    prompt, completion, and token usage.

    The decorated function must return a ``dict`` containing at minimum a
    ``"model"`` key for full generation recording.  Any other return type
    is passed through unchanged with only timing captured.

    Expected dict shape
    -------------------
    ::

        {
            "model": "gemini-flash",
            "prompt": "...",          # str, list, or dict
            "completion": "...",      # str, list, or dict
            "usage": {"input": N, "output": N},  # optional
        }

    Parameters
    ----------
    fn : Callable
        Async function to wrap.

    Returns
    -------
    Callable
        Decorated async function with identical signature.
    c                 0  K   dd l mc m} |j                         }|j	                  dj
                         }t        j                         }	  | i | d {   }t        j                         |z
  }t        |t              r|d|v rx|j                  |j                  j
                  |j                  dd      |j                  dd      |j                  dd      |j                  d	i       d
t        |d      i       |S 7 # t        $ r  w xY ww)Nr   generation_)r   modelunknownprompt 
completionusager   r   )r   r   r<   r>   r@   rA   r   )r   r   r   r   r   r   r   r   
isinstancedict
generationr   getr    r!   )	r#   r$   r%   r&   r   r'   r(   r)   r+   s	           r-   r.   z#generation_tracked.<locals>.wrapper   s    99%%'K}"=> 	t.v..F~~'%/H &$'Gv,=!!"XX **Wi8!::h3%zz,; **Wb1*E(A,>? "  M /   		s1   ADD DB(D DD DDr/   r1   )r+   r.   s   ` r-   generation_trackedrF   p   s'    > __R 6 Nr5   )r,   r"   r0   r   r6   )__doc__
__future__r   r2   loggingr   typingr   r   "core.observability.langfuse_clientr   	getLoggerr   loggerr8   rF   r7   r5   r-   <module>rN      s>   6 #      :			8	$CL;r5   