
    JiW                       d dl mZ d dlZd dlZd dlZd dlZd dlmZmZm	Z	m
Z
mZmZmZ d dlmZmZ d dlmZ d dlmZ d dlmZmZ d dlmZmZmZ d d	lmZ d d
lmZ d dl m!Z! d dl"m#Z# d dl$m%Z%m&Z& d dl'm(Z( ddl)m*Z*m+Z+ ddl,m-Z-m.Z.m/Z/ erd dl0m1Z1  ede      Z2e3e4e5e   f   Z6 G d de7      Z8 ejr                  de8        G d de
e-         Z: ejv                  d      dd       Z< ejv                  d      dd       Z=y)    )annotationsN)TYPE_CHECKINGAnyAsyncGeneratorGenericTypeTypeVarcast)	BaseModelValidationError)SerializedContext)
StepConfig)ContextSerdeErrorWorkflowRuntimeError)Event
StartEvent	StopEvent)WorkflowHandler)basic_runtime)WorkflowBroker)BrokerState)PluginWorkflowRuntime)
RunResultT   )BaseSerializerJsonSerializer)MODEL_T	DictStateInMemoryStateStore)WorkflowT)boundc                      e Zd Zy)UnserializableKeyWarningN)__name__
__module____qualname__     k/var/www/html/BankruptcyAI-uat/bankruptcy-ai/venv/lib/python3.12/site-packages/workflows/context/context.pyr%   r%   4   s    r*   r%   oncec                  |   e Zd ZU dZdZded<   ded<   ded<   d	ed
<   ddef	 	 	 	 	 	 	 	 	 ddZedd       Z		 d	 	 	 	 	 d dZ
	 	 d!	 	 	 	 	 	 	 d"dZd#dZed$d       Zed%d       Zdd&dZe	 d	 	 	 	 	 	 	 d'd       Zd(dZ	 d	 	 	 	 	 	 	 d)dZdd*dZ	 	 	 	 d+	 	 	 	 	 	 	 	 	 	 	 d,dZd-dZd.dZd/dZed0d       Zy)1Contexta  
    Global, per-run context for a `Workflow`. Provides an interface into the
    underlying broker run, for both external (workflow run oberservers) and
    internal consumption by workflow steps.

    The `Context` coordinates event delivery between steps, tracks in-flight work,
    exposes a global state store, and provides utilities for streaming and
    synchronization. It is created by a `Workflow` at run time and can be
    persisted and restored.

    Args:
        workflow (Workflow): The owning workflow instance. Used to infer
            step configuration and instrumentation.
        previous_context: A previous context snapshot to resume from.
        serializer: A serializer to use for serializing and deserializing the current and previous context snapshots.

    Attributes:
        is_running (bool): Whether the workflow is currently running.
        store (InMemoryStateStore[MODEL_T]): Type-safe, async state store shared
            across steps. See also
            [InMemoryStateStore][workflows.context.state_store.InMemoryStateStore].

    Examples:
        Basic usage inside a step:

        ```python
        from workflows import step
        from workflows.events import StartEvent, StopEvent

        @step
        async def start(self, ctx: Context, ev: StartEvent) -> StopEvent:
            await ctx.store.set("query", ev.topic)
            ctx.write_event_to_stream(ev)  # surface progress to UI
            return StopEvent(result="ok")
        ```

        Persisting the state of a workflow across runs:

        ```python
        from workflows import Context

        # Create a context and run the workflow with the same context
        ctx = Context(my_workflow)
        result_1 = await my_workflow.run(..., ctx=ctx)
        result_2 = await my_workflow.run(..., ctx=ctx)

        # Serialize the context and restore it
        ctx_dict = ctx.to_dict()
        restored_ctx = Context.from_dict(my_workflow, ctx_dict)
        result_3 = await my_workflow.run(..., ctx=restored_ctx)
        ```


    See Also:
        - [Workflow][workflows.Workflow]
        - [Event][workflows.events.Event]
        - [InMemoryStateStore][workflows.context.state_store.InMemoryStateStore]
    )memoryInMemoryStateStore[MODEL_T]_state_storezWorkflowBroker[MODEL_T] | None_broker_runr   _pluginr!   	_workflowNc           	        |xs
 t               | _        d | _        || _        || _        |xs
 t               }|.	 t        j                  |      }t        j                  |||       n
t               }|| _        t               }|j                         j                         D ]j  \  }}	|	j                  }
|
j                   |
j                   t"        k7  s3t%        |
j                   t&              sN|
j                   }|j)                  |       l t+        |      dkD  r5t-        ddj/                  |D cg c]  }|j0                   c}      z         |r|j3                         nt"        }|j4                  r{t7        j8                  |j4                  |      }|j:                  |k7  r/t-        d|j0                   d|j:                  j0                         t=        t6        t>           |      | _         y 	 t=        t>         |             }t7        |      | _         y # t        $ r}t        d|       |d }~ww xY wc c}w # tB        $ r}tE        d| d|       |d }~ww xY w)	Nz-Context dict specified in an invalid format: r   zqMultiple state types are not supported. Make sure that each Context[...] has the same generic state type. Found: z, z/State type mismatch. Workflow context expected z, got z#Failed to initialize state of type zB. Does your state define defaults for all fields? Original error:
)#r   _serializerr2   r3   r4   r   from_dict_autor   from_serializedr   r   _init_snapshotset
_get_stepsitems_step_configcontext_state_typer   
issubclassr   addlen
ValueErrorjoinr&   popstater    	from_dict
state_typer
   r   r1   	Exceptionr   )selfworkflowprevious_context
serializerpluginprevious_context_parsedestate_types_	step_funcstep_configrG   store_statestate_instances                 r+   __init__zContext.__init__   sv    &9)9!  3>#3
'*;*J*J$+' +++Xz '8&9#5
 -0E$//1779 	,LAy&/&<&<K..:22i?{==yI(;;

+	, {a D));OZZ00OPQ  +6[__&9
"((,66'--zK %%3 EjFYFYEZZ`alawaw  bA  bA  aB  C  !%%7%@+ ND!%gz|!<$6~$F!U # 'CA3G4 P"  *9*  FI  JK  IL  Ms5   ,H 0H60%H; 	H3H..H3;	IIIc                r    | j                   | j                  j                  S | j                   j                  S )z*Whether the workflow is currently running.)r2   r9   
is_runningrI   s    r+   rX   zContext.is_running   s4     #&&111##...r*   c                    | j                   t        d      |xs6 | j                  j                  t	        t        j                                     }t        |t        d|       || j                        }|| _         |S )NzBroker already initializedzContext[MODEL_T])rJ   contextruntimerM   )	r2   r   r3   new_runtimestruuiduuid4r   r
   )rI   rJ   rM   r\   brokers        r+   _init_brokerzContext._init_broker   sq     '&'CDD#)#XT\\-E-Ec$**,FW-X*8+T2<<	+
 "r*   c                $   d| j                   | j                   d| _         | j                  |      | _         dfd}dfd}t        j                  | j                  || j
                        }| j                   j                  |||||      S )zJ
        called by package internally from the workflow to run it
        Nc                    K    	  j                          d {    j                          d {    y y 7  # t        $ r Y )w xY w7 wN)shutdownrH   acquire)prev_broker	semaphores   r+   before_startz+Context._workflow_run.<locals>.before_start   s_     &%..000 $''))) % 1   *s;   A= ;= AAA= 	A	AA		Ac                 4   K     j                          y y wre   )release)ri   s   r+   after_completez-Context._workflow_run.<locals>.after_complete   s     $!!# %s   )rJ   previousstart_eventrj   rm   returnNone)r2   rb   r   r8   r9   r6   start)rI   rJ   ro   ri   rj   rm   rE   rh   s      `   @r+   _workflow_runzContext._workflow_run   s     7;'**K#D,,X6	*	$ ++4+;+;
 %%#%) & 
 	
r*   c                8    | j                   j                          y)zN
        Called internally from the handler to cancel a context's run
        N)_running_broker
cancel_runrY   s    r+   _workflow_cancel_runzContext._workflow_cancel_run
  s     	'')r*   c                H    | j                   t        d      | j                   S )Nz}Workflow run is not yet running. Make sure to only call this method after the context has been passed to a workflow.run call.)r2   r   rY   s    r+   rv   zContext._running_broker  s/    #& P  r*   c                    | j                   S )a  Typed, process-local state store shared across steps.

        If no state was initialized yet, a default
        [DictState][workflows.context.state_store.DictState] store is created.

        Returns:
            InMemoryStateStore[MODEL_T]: The state store instance.
        )r1   rY   s    r+   storezContext.store  s        r*   c                d   |xs | j                   }i }| j                  | j                  j                  |      }| j                  | j                  j                  }n+t        j                  | j                  | j                  |      }|j                  |      }||_
        |j                  d      S )ai  Serialize the context to a JSON-serializable dict.

        Persists the global state store, event queues, buffers, accepted events,
        broker log, and running flag. This payload can be fed to
        [from_dict][workflows.context.context.Context.from_dict] to resume a run
        or carry state across runs.

        Args:
            serializer (BaseSerializer | None): Value serializer used for state
                and event payloads. Defaults to
                [JsonSerializer][workflows.context.serializers.JsonSerializer].

        Returns:
            dict[str, Any]: A dict suitable for JSON encoding and later
            restoration via `from_dict`.

        See Also:
            - [InMemoryStateStore.to_dict][workflows.context.state_store.InMemoryStateStore.to_dict]

        Examples:
            ```python
            ctx_dict = ctx.to_dict()
            my_db.set("key", json.dumps(ctx_dict))

            ctx_dict = my_db.get("key")
            restored_ctx = Context.from_dict(my_workflow, json.loads(ctx_dict))
            result = await my_workflow.run(..., ctx=restored_ctx)
            ```
        python)mode)r6   r1   to_dictr2   _stater   r8   r9   r4   to_serializedrE   
model_dump)rI   rL   
state_databroker_stater[   s        r+   r   zContext.to_dict$  s    <  34#3#3
 
(**22:>J '++22L '66##T^^ZL ,,Z8"!!x!00r*   c                X    	  | |||      S # t         $ r}d}t        |      |d}~ww xY w)a  Reconstruct a `Context` from a serialized payload.

        Args:
            workflow (Workflow): The workflow instance that will own this
                context.
            data (dict[str, Any]): Payload produced by
                [to_dict][workflows.context.context.Context.to_dict].
            serializer (BaseSerializer | None): Serializer used to decode state
                and events. Defaults to JSON.

        Returns:
            Context[MODEL_T]: A context instance initialized with the persisted
                state and queues.

        Raises:
            ContextSerdeError: If the payload is missing required fields or is
                in an incompatible format.

        Examples:
            ```python
            ctx_dict = ctx.to_dict()
            my_db.set("key", json.dumps(ctx_dict))

            ctx_dict = my_db.get("key")
            restored_ctx = Context.from_dict(my_workflow, json.loads(ctx_dict))
            result = await my_workflow.run(..., ctx=restored_ctx)
            ```
        )rK   rL   zRError creating a Context instance: the provided payload has a wrong or old format.N)KeyErrorr   )clsrJ   datarL   rO   msgs         r+   rF   zContext.from_dictX  s9    F	0x$:NN 	0fC#C(a/	0s   
 	)$)c                R   K   | j                   j                          d{   S 7 w)zReturn the list of currently running step names.

        Returns:
            list[str]: Names of steps that have at least one active worker.
        N)rv   running_stepsrY   s    r+   r   zContext.running_steps  s#      ))779999s   '%'c                <    | j                   j                  |||      S )a  
        Buffer events until all expected types are available, then return them.

        This utility is helpful when a step can receive multiple event types
        and needs to proceed only when it has a full set. The returned list is
        ordered according to `expected`.

        Args:
            ev (Event): The incoming event to add to the buffer.
            expected (list[Type[Event]]): Event types to collect, in order.
            buffer_id (str | None): Optional stable key to isolate buffers across
                steps or workers. Defaults to an internal key derived from the
                task name or expected types.

        Returns:
            list[Event] | None: The events in the requested order when complete,
            otherwise `None`.

        Examples:
            ```python
            @step
            async def synthesize(
                self, ctx: Context, ev: QueryEvent | RetrieveEvent
            ) -> StopEvent | None:
                events = ctx.collect_events(ev, [QueryEvent, RetrieveEvent])
                if events is None:
                    return None
                query_ev, retrieve_ev = events
                # ... proceed with both inputs present ...
            ```

        See Also:
            - [Event][workflows.events.Event]
        )rv   collect_events)rI   evexpected	buffer_ids       r+   r   zContext.collect_events  s     J ##222xKKr*   c                :    | j                   j                  ||      S )aG  Dispatch an event to one or all workflow steps.

        If `step` is omitted, the event is broadcast to all step queues and
        non-matching steps will ignore it. When `step` is provided, the target
        step must accept the event type or a
        [WorkflowRuntimeError][workflows.errors.WorkflowRuntimeError] is raised.

        Args:
            message (Event): The event to enqueue.
            step (str | None): Optional step name to target.

        Raises:
            WorkflowRuntimeError: If the target step does not exist or does not
                accept the event type.

        Examples:
            It's common to use this method to fan-out events:

            ```python
            @step
            async def my_step(self, ctx: Context, ev: StartEvent) -> WorkerEvent | GatherEvent:
                for i in range(10):
                    ctx.send_event(WorkerEvent(msg=i))
                return GatherEvent()
            ```

            You also see this method used from the caller side to send events into the workflow:

            ```python
            handler = my_workflow.run(...)
            async for ev in handler.stream_events():
                if isinstance(ev, SomeEvent):
                    handler.ctx.send_event(SomeOtherEvent(msg="Hello!"))

            result = await handler
            ```
        )rv   
send_event)rI   messagesteps      r+   r   zContext.send_event  s    L ##..w==r*   c                \   K   | j                   j                  |||||       d{   S 7 w)a   Wait for the next matching event of type `event_type`.

        Optionally emits a `waiter_event` to the event stream once per `waiter_id` to
        inform callers that the workflow is waiting for external input.
        This helps to prevent duplicate waiter events from being sent to the event stream.

        Args:
            event_type (type[T]): Concrete event class to wait for.
            waiter_event (Event | None): Optional event to write to the stream
                once when the wait begins.
            waiter_id (str | None): Stable identifier to avoid emitting multiple
                waiter events for the same logical wait.
            requirements (dict[str, Any] | None): Key/value filters that must be
                satisfied by the event via `event.get(key) == value`.
            timeout (float | None): Max seconds to wait. `None` means no
                timeout. Defaults to 2000 seconds.

        Returns:
            T: The received event instance of the requested type.

        Raises:
            asyncio.TimeoutError: If the timeout elapses.

        Examples:
            ```python
            @step
            async def my_step(self, ctx: Context, ev: StartEvent) -> StopEvent:
                response = await ctx.wait_for_event(
                    HumanResponseEvent,
                    waiter_event=InputRequiredEvent(msg="What's your name?"),
                    waiter_id="user_name",
                    timeout=60,
                )
                return StopEvent(result=response.response)
            ```
        N)rv   wait_for_event)rI   
event_typewaiter_event	waiter_idrequirementstimeouts         r+   r   zContext.wait_for_event  s7     X ))88iw
 
 	
 
s   #,*,c                :    | j                   j                  |       y)a  Enqueue an event for streaming to [WorkflowHandler]](workflows.handler.WorkflowHandler).

        Args:
            ev (Event | None): The event to stream. `None` can be used as a
                sentinel in some streaming modes.

        Examples:
            ```python
            @step
            async def my_step(self, ctx: Context, ev: StartEvent) -> StopEvent:
                ctx.write_event_to_stream(ev)
                return StopEvent(result="ok")
            ```
        N)rv   write_event_to_stream)rI   r   s     r+   r   zContext.write_event_to_stream  s     	2226r*   c                    t                | j                  j                  t        d      | j                  j                  j	                         S )a<  Return the final result of the workflow run.

        Deprecated:
            This method is deprecated and will be removed in a future release.
            Prefer awaiting the handler returned by `Workflow.run`, e.g.:
            `result = await workflow.run(..., ctx=ctx)`.

        Examples:
            ```python
            # Preferred
            result = await my_workflow.run(..., ctx=ctx)

            # Deprecated
            result_agent = ctx.get_result()
            ```

        Returns:
            RunResultT: The value provided via a `StopEvent`.
        zWorkflow handler is not set)_warn_get_resultrv   _handlerr   resultrY   s    r+   
get_resultzContext.get_result  sC    ( 	((0&'DEE##,,3355r*   c                6    | j                   j                         S )z8The internal queue used for streaming events to callers.)rv   stream_published_eventsrY   s    r+   stream_eventszContext.stream_events2  s    ##;;==r*   c                     t                t        j                         d fd}	 t        j                   |              S # t        $ r. t        j
                         }|j                   |              Y S w xY w)zDeprecated queue-based event stream.

        Returns an asyncio.Queue that is populated by iterating this context's
        stream_events(). A deprecation warning is emitted once per process.
        c                    K   j                         2 3 d {   } j                  |        d {    t        | t              s3 y 7 07 6 y wre   )r   put
isinstancer   )r   qrI   s    r+   _pumpz&Context.streaming_queue.<locals>._pump@  sJ      ..0  beeBib), 1s;   AAA	AAAAA	AAArp   )_warn_streaming_queueasyncioQueuecreate_taskRuntimeErrorget_event_loop)rI   r   loopr   s   `  @r+   streaming_queuezContext.streaming_queue6  sk     	")--/		&(   	&))+DUW%	&s   A 3A<;A<)
rJ   r!   rK   dict[str, Any] | NonerL   BaseSerializer | NonerM   r   rq   rr   )rq   boolre   )rJ   r!   rM   zWorkflowRuntime | Nonerq   WorkflowBroker[MODEL_T])NN)rJ   r!   ro   zStartEvent | Noneri   zasyncio.Semaphore | Nonerq   r   rp   )rq   r   )rq   r0   )rL   r   rq   dict[str, Any])rJ   z
'Workflow'r   r   rL   r   rq   z'Context[MODEL_T]')rq   z	list[str])r   r   r   zlist[Type[Event]]r   
str | Nonerq   zlist[Event] | None)r   r   r   r   rq   rr   )NNNi  )r   zType[T]r   Event | Noner   r   r   r   r   zfloat | Nonerq   r"   )r   r   rq   rr   )rq   r   )rq   zAsyncGenerator[Event, None])rq   zasyncio.Queue)r&   r'   r(   __doc__known_unserializable_keys__annotations__r   rV   propertyrX   rb   rt   rx   rv   r{   r   classmethodrF   r   r   r   r   r   r   r   r   r)   r*   r+   r.   r.   ;   s   9z !, .-//O
 37,0&FF 0F *	F
 F 
FP / / DH *@	 ( *..2	&
&
 '&
 ,	&

 
&
P*     	! 	!21h 
 -1	&0&0 &0 *	&0
 
&0 &0P: OS%L%L#4%LAK%L	%LN&>V &* $.2 $.
.
 #.
 	.

 ,.
 .
 
.
`7"62>  r*   r.   )maxsizec                 <    t        j                  dt        d       y )NzContext.get_result() is deprecated and will be removed in a future release. Prefer awaiting the WorkflowHandler returned by Workflow.run: `result = await workflow.run(..., ctx=ctx)`.   
stacklevelwarningswarnDeprecationWarningr)   r*   r+   r   r   N  s    MMI 	r*   c                 <    t        j                  dt        d       y )NzContext.streaming_queue is deprecated and will be removed in a future release. Prefer iterating Context.stream_events(): `async for ev in ctx.stream_events(): ...`r   r   r   r)   r*   r+   r   r   [  s    MM9 	r*   rp   )>
__future__r   r   	functoolsr_   r   typingr   r   r   r   r   r	   r
   pydanticr   r   workflows.context.context_typesr   workflows.decoratorsr   workflows.errorsr   r   workflows.eventsr   r   r   workflows.handlerr   workflows.plugins.basicr   workflows.runtime.brokerr   &workflows.runtime.types.internal_stater   workflows.runtime.types.pluginr   r   workflows.typesr   serializersr   r   state_storer   r   r    	workflowsr!   r"   dictr^   listEventBufferWarningr%   simplefilterr.   	lru_cacher   r   r)   r*   r+   <module>r      s    #       0 = + 
 . 1 3 > B & 7 ? ?" Cu3U#$	w 	   f6 7Pgg Pf Q	  	 Q	  	r*   