
    Ji                       d dl mZ d dlZd dlZd dl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 d dlmZmZmZmZmZ d dl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 d dl m!Z! d dl"m#Z#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/m0Z0m1Z1m2Z2m3Z3m4Z4 d dl5m6Z6 d dl7m8Z8m9Z9m:Z:m;Z;m<Z<m=Z=m>Z>m?Z?m@Z@ d dlAmBZBmCZCmDZD d dlEmFZF d dlGmHZHmIZImJZJmKZK d dlLmMZM d dlNmOZO d dlPmQZR  ej                         ZT G d d      ZUe G d d              ZV G d! d"eW      ZXe G d# d$             ZYeZd%k(  rd dl[Z[ e[j                  d&'      Z]e]j                  d(e_d)d*+       e]j                         Za eU       Zbebj                         Zd eeeaj                  d,      5 Zg ej                  edd-eg.       ddd        eid/eaj                          yy# 1 sw Y    xY w)0    )annotationsN)asynccontextmanager)	dataclass)datetimetimezone)version)Path)AnyAsyncGenerator	AwaitableCallablecast)instrument_tags)	Starlette)HTTPException)
Middleware)CORSMiddleware)Request)JSONResponseStreamingResponse)Route)SchemaGenerator)StaticFiles)ContextWorkflow)EventInternalDispatchEvent
StartEvent	StepStateStepStateChanged	StopEvent)WorkflowHandler)	CancelHandlerResponseHandlerDataHandlersListResponseHealthResponseSendEventResponseWorkflowEventsListResponseWorkflowGraphResponseWorkflowSchemaResponseis_status_completed)EventEnvelopeEventEnvelopeWithMetadataEventValidationError)extract_workflow_structure)AbstractWorkflowStoreHandlerQueryPersistentHandlerStatus)MemoryWorkflowStore)
RunResultT)_nanoidc                  f   e Zd Zddddgd	 	 	 	 	 d dZ	 d!	 	 	 	 	 	 	 d"dZd#dZed$d       Zd%d	Z	 	 	 d&	 	 	 	 	 	 	 d'd
Z	d(dZ
d)dZd)dZd)dZd)dZd)dZd)dZd)dZd*dZd)dZd)dZd+dZd)dZd)dZd)dZd,dZ	 	 	 	 	 	 	 	 d-dZ	 	 d.	 	 	 	 	 	 	 	 	 d/dZ	 	 	 	 	 	 	 	 d0dZd1dZd2dZy)3WorkflowServerNg      ?   )
middlewareworkflow_storepersistence_backoffc               d    i  _         i  _        i  _        i  _        i  _        ||n	t                _        t        t              j                  dz   _
        t        |       _        |xs t        t        ddgdgd      g _        t!        d j"                  dg      t!        d	 j$                  d
g      t!        d j&                  d
g      t!        d j(                  dg      t!        d j*                  dg      t!        d j,                  dg      t!        d j.                  d
g      t!        d j0                  dg      t!        d j2                  dg      t!        d j4                  dg      t!        d j6                  d
g      t!        d j8                  dg      t!        d j:                  dg      g _        t>        d fd       }tA         j<                   j                  |       _!         jB                  jE                  dtG         j                  d      d       y )Nstaticz.**T)allow_origin_regexallow_methodsallow_headersallow_credentialsz
/workflowsGET)methodsz/workflows/{name}/runPOSTz/workflows/{name}/run-nowaitz/workflows/{name}/schemaz/results/{handler_id}z/events/{handler_id}z/healthz	/handlersz/handlers/{handler_id}z/handlers/{handler_id}/cancelz /workflows/{name}/representationz/workflows/{name}/eventsc                  K   j                         4 d {    d  d d d       d {    y 7 7 # 1 d {  7  sw Y   y xY wwN)contextmanager)appselfs    i/var/www/html/BankruptcyAI-uat/bankruptcy-ai/venv/lib/python3.12/site-packages/workflows/server/server.pylifespanz)WorkflowServer.__init__.<locals>.lifespan   sE     **,        s:   A3A7A5AAA	A A	A)routesr:   rM   /)	directoryhtmlui)rJ   name)rJ   r   returnzAsyncGenerator[None, None])$
_workflows_additional_events	_contexts	_handlers_resultsr4   _workflow_storer	   __file__parent_assets_pathlist_persistence_backoffr   r   _middlewarer   _list_workflows_run_workflow_run_workflow_nowait_get_events_schema_get_workflow_result_stream_events_post_event_health_check_get_handlers_get_workflow_handler_cancel_handler_get_workflow_representation_list_workflow_events_routesr   r   rJ   mountr   )rK   r:   r;   r<   rM   s   `    rL   __init__zWorkflowServer.__init__F   s^    02GI-/68/1,8N>Q>S 	 !N11H<$()<$=!% 	
#'"e"e"&	*
 $$
 '""
 .))
 *''
 '))
 &##
 &  
 ""
 ""
 (**
 /$$
 211
 ***{B
H 
	 
	 <<''
 	[4+<+<4Ht 	 	
    c                F    || j                   |<   ||| j                  |<   y y rH   )rU   rV   )rK   rS   workflowadditional_eventss       rL   add_workflowzWorkflowServer.add_workflow   s-     !)(,=D##D) )rq   c                  K   | j                   j                  t        dgt        | j                  j                                            d{   }|D ]v  }| j                  |j                     }	 | j                  t        |j                  |      |j                  t        j                  ||j                               d{    x | S 7 7 
# t        $ r}t        j                  d|j                   d|j                   d	|        	 t!        j"                  t$        j&                        }| j                   j)                  t+        |j                  |j                  d
|j,                  t/        |      d|j0                  |||j                  
             d{  7   n# t        $ r Y nw xY wY d}~fd}~ww xY ww)zPResumes previously running workflows, if they were not complete at last shutdownrunning	status_inworkflow_name_inNrS   rs   rs   data)rs   
handler_idcontextzFailed to resume handler z for workflow z: failed
r~   workflow_namestatusrun_iderrorresult
started_at
updated_atcompleted_atctx)rZ   queryr1   r^   rU   keysr   _start_workflow_NamedWorkflowr~   r   	from_dictr   	Exceptionloggerr   r   nowr   utcupdater2   r   strr   )rK   handlers
persistentrs   er   s         rL   startzWorkflowServer.start   s    --33$+T__=Q=Q=S8T
 

 # !	Jz'?'?@H**+'55  *44#--xjnnU +   !	F Q
  /
0E0E/FnU_UmUmTnnpqrpst",,x||4C..55)'1'<'<*4*B*B#+#-#4#4"%a&#''1'<'<'*), *   ! /s   AGC"G2ACCCGC	G 2F;BF&F" F&%F;&	F2/F;1F22F;5G;G  Gc                  K   | j                          d{    	 |  | j                          d{    y7 #7 # | j                          d{  7   w xY ww)z9Use this server as a context manager to start and stop itNr   stoprK   s    rL   rI   zWorkflowServer.contextmanager   sJ      jjl	J))+	 	 $))+s<   A:A> A<AAAAAAc                  K   t         j                  dt        | j                         d       t	        j
                  t        | j                  j                               D cg c]  }| j                  |       c}  d {    | j                  j                          | j                  j                          y c c}w 7 >w)Nz*Shutting down Workflow server. Cancelling z
 handlers.)r   infolenrX   asynciogatherr^   values_close_handlerclearrY   rK   handlers     rL   r   zWorkflowServer.stop   s     8T^^9L8MZX	
 nn:>t~~?T?T?V:WXwd!!'*X
 	
 	
 	 Y	
s   A!C#B<;CC?Cc           
       K   |xs i }t        j                  | j                  f||d|}t        j                  |      }t        j                  d| d| |j                  dd              |j                          d{    y7 w)zRun the server.)hostportz#Starting Workflow server at http://:	root_pathrO   N)uvicornConfigrJ   Serverr   r   getserve)rK   r   r   uvicorn_configconfigservers         rL   r   zWorkflowServer.serve   s      (-2Qt$Q.Q'1$q~?Q?QR]_b?c>de	
 llns   A?B	BB	c                <   | j                   }t        ddt        d      dddddiddd	id
dd	idd	idddgdddd	idd	id	ddd	g ddd	ddd	dddd	dddd	dddddiddigdd	g dddddddid
idgddid      }|j                  |j                        S ) Nz3.0.0zWorkflows APIzllama-index-workflows)titler   schemasobjecttypearraystring)r   items)valuetypesr   qualified_namer   )r   
propertiesrequiredT)r   nullable)rw   	completedr   	cancelled)r   enumz	date-time)r   format)r   r   r   zWorkflow result valuez$refz.#/components/schemas/EventEnvelopeWithMetadatanull)descriptiononeOf	r~   r   r   r   r   r   r   r   r   )r~   r   r   r   r   z#/components/schemas/Handler)r-   HandlerHandlersList)openapir   
components)rJ   r   r   
get_schemarN   )rK   rJ   gens      rL   openapi_schemazWorkflowServer.openapi_schema  sQ   hh",&'>?
 $,*0();29VXDV)W)/(:3982D	+ *1&(9	6 %-/5x.@28(1C3;*N,4-&+" 8@;.W,4.904/" -5.9041"
 3;)M3J -34d)* *0(8	.&+"3"+F)K+$Z %- *,3.46T-U-"+ *4	)oA CJL
\ ~~cjj))rq   c                P   K   t        t        d      j                               S w)a  
        ---
        summary: Health check
        description: Returns the server health status.
        responses:
          200:
            description: Successful health check
            content:
              application/json:
                schema:
                  type: object
                  properties:
                    status:
                      type: string
                      example: healthy
                  required: [status]
        healthyr   )r   r&   
model_dump)rK   requests     rL   rh   zWorkflowServer._health_checkg  s!     $ N)<GGIJJs   $&c                j   K   t        | j                  j                               }t        d|i      S w)a  
        ---
        summary: List workflows
        description: Returns the list of registered workflow names.
        responses:
          200:
            description: List of workflows
            content:
              application/json:
                schema:
                  type: object
                  properties:
                    workflows:
                      type: array
                      items:
                        type: string
                  required: [workflows]
        	workflows)r^   rU   r   r   )rK   r   workflow_namess      rL   ra   zWorkflowServer._list_workflows{  s/     & doo2245[.9::s   13c                  K   d|j                   vrt        dd      |j                   d   }|| j                  vrt        dd| d      | j                  |   j                  }| j                  j                  |g       }|r|j                  |       g }|D ]!  }|j                  |j                                # t        t        |      j                               S w)	a  
        ---
        summary: List workflow events
        description: Returns the list of registered workflow event schemas.
        parameters:
          - in: path
            name: name
            required: true
            schema:
              type: string
            description: Registered workflow name.
        responses:
          200:
            description: List of workflow event schemas
            content:
              application/json:
                schema:
                  type: object
                  properties:
                    events:
                      type: array
                      description: List of workflow event JSON schemas
                      items:
                        type: object
                  required: [events]
        rS     zname param is required)status_codedetail  z
Workflow 'z' not found)events)path_paramsr   rU   r   rV   r   extendappendmodel_json_schemar   r(   r   )rK   r   rS   r   rt   
event_objsevents          rL   rm   z$WorkflowServer._list_workflow_events  s     6 ,,,C8PQQ""6*t&C*TF+8VWW&-- 3377bAMM+,
 	9Ee5578	9 6jITTVWWs   CCc                h  K   | j                  |      }| j                  ||j                  |j                         d{   \  }}}|&|j                  j                  j                  |      }nd}	 | j                  t        |j                  |j                        |||       d{   }|j                  }	 | d{    d}	|j                  	 |j                   d{    | j                  |       d{    t        |j                         j!                         |		      S 7 7 7 m# t        $ r&}
d}	t        j                  d|
 d       Y d}
~
d}
~
ww xY w7 ~# t        $ r Y w xY w7 v# t        $ r1}
d}	t        j                  d|
 d       t#        d|
 |	
      d}
~
ww xY ww)a  
        ---
        summary: Run workflow (wait)
        description: |
          Runs the specified workflow synchronously and returns the final result.
          The request body may include an optional serialized start event, an optional
          context object, and optional keyword arguments passed to the workflow run.
        parameters:
          - in: path
            name: name
            required: true
            schema:
              type: string
            description: Registered workflow name.
        requestBody:
          required: false
          content:
            application/json:
              schema:
                type: object
                properties:
                  start_event:
                    type: object
                    description: 'Plain JSON object representing the start event (e.g., {"message": "..."}).'
                  context:
                    type: object
                    description: Serialized workflow Context.
                  handler_id:
                    type: string
                    description: Workflow handler identifier to continue from a previous completed run.
                  kwargs:
                    type: object
                    description: Additional keyword arguments for the workflow.
        responses:
          200:
            description: Workflow completed successfully
            content:
              application/json:
                schema:
                  $ref: '#/components/schemas/Handler'
          400:
            description: Invalid start_event payload
          404:
            description: Workflow or handler identifier not found
          500:
            description: Error running workflow or invalid request body
        Nr{   rs   r~   r   start_event     zError running workflow: Texc_infor   r   r   )_extract_workflow_extract_run_paramsrs   rS   start_event_classmodel_validater   r   run_handlerr   r   r   taskr   r   to_response_modelr   r   )rK   r   rs   r   r   r~   input_evwrapperr   r   r   s              rL   rb   zWorkflowServer._run_workflow  s    ` ))'2151I1IX&&2
 ,
(j "((::II+VHH	 00'X]]XEVEVW%$	 1  G ))GL ||'!,,&&
 %%g...))+668f A,
  L7s;dKKL
 '   /
  	FLL3A37$LG1!56 	s   <F2D*2F227E5 )D,*E5 ;D0  D.D0 E5 E$ #E"$E$ (E5 <E3=,E5 )F2,E5 .D0 0	E9EE5 EE5 "E$ $	E0-E5 /E00E5 5	F/>,F**F//F2c                  K   | j                  |      }	 |j                  j                  j                         }	 |j                  j                  j                         }t        t        ||      j                               S # t        $ r}t        d| d      d}~ww xY w# t        $ r}t        d| d      d}~ww xY ww)ac  
        ---
        summary: Get JSON schema for start event
        description: |
          Gets the JSON schema of the start and stop events from the specified workflow and returns it under "start" (start event) and "stop" (stop event)
        parameters:
          - in: path
            name: name
            required: true
            schema:
              type: string
            description: Registered workflow name.
        requestBody:
          required: false
        responses:
          200:
            description: JSON schema successfully retrieved for start event
            content:
              application/json:
                schema:
                  type: object
                  properties:
                    start:
                      description: JSON schema for the start event
                    stop:
                      description: JSON schema for the stop event
                  required: [start, stop]
          404:
            description: Workflow not found
          500:
            description: Error while getting the JSON schema for the start or stop event
        z2Error getting schema of start event for workflow: r   r   Nz1Error getting schema of stop event for workflow: r   )
r   rs   r   r   r   r   stop_event_classr   r*   r   )rK   r   rs   start_event_schemar   stop_event_schemas         rL   rd   z!WorkflowServer._get_events_schema  s     B ))'2	!)!2!2!D!D!V!V!X	 ( 1 1 B B T T V "(/@jl
 	
  	KA3O 	  	J1#N 	sE   C$B $B# $C	B BB  C#	C,B<<CCc                   K   | j                  |      }	 t        |j                        }t        t        |j                               j                               S # t        $ r}t	        d| d      d}~ww xY ww)a  
        ---
        summary: Get the representation of the workflow
        description: |
          Get the representation of the workflow as a directed graph in JSON format
        parameters:
          - in: path
            name: name
            required: true
            schema:
              type: string
            description: Registered workflow name.
        requestBody:
          required: false
        responses:
          200:
            description: JSON representation successfully retrieved
            content:
              application/json:
                schema:
                  type: object
                  properties:
                    graph:
                      description: the elements of the JSON representation of the workflow
                  required: [graph]
          404:
            description: Workflow not found
          500:
            description: Error while getting JSON workflow representation
        z2Error while getting JSON workflow representation: r   r   N)graph)	r   r/   rs   r   r   r   r)   r   r   )rK   r   rs   workflow_graphr   s        rL   rl   z+WorkflowServer._get_workflow_representationP  s     > ))'2	78I8IJN !(H(H(JKVVX
 	
  	KA3O 	s'   A<A 1A<	A9$A44A99A<c                  K   | j                  |      }| j                  ||j                  |j                         d{   \  }}}|&|j                  j                  j                  |      }nd}	 | j                  t        |j                  |j                        |||       d{   }t        |j                         j                               S 7 7 -# t        $ r}t        d| d      d}~ww xY ww)a  
        ---
        summary: Run workflow (no-wait)
        description: |
          Starts the specified workflow asynchronously and returns a handler identifier
          which can be used to query results or stream events.
        parameters:
          - in: path
            name: name
            required: true
            schema:
              type: string
            description: Registered workflow name.
        requestBody:
          required: false
          content:
            application/json:
              schema:
                type: object
                properties:
                  start_event:
                    type: object
                    description: 'Plain JSON object representing the start event (e.g., {"message": "..."}).'
                  context:
                    type: object
                    description: Serialized workflow Context.
                  handler_id:
                    type: string
                    description: Workflow handler identifier to continue from a previous completed run.
                  kwargs:
                    type: object
                    description: Additional keyword arguments for the workflow.
        responses:
          200:
            description: Workflow started
            content:
              application/json:
                schema:
                  $ref: '#/components/schemas/Handler'
          400:
            description: Invalid start_event payload
          404:
            description: Workflow or handler identifier not found
        Nr{   r   zInitial persistence failed: r   r   )r   r   rs   rS   r   r   r   r   r   r   r   r   r   )	rK   r   rs   r   r   r~   r   r   r   s	            rL   rc   z#WorkflowServer._run_workflow_nowait{  s     Z ))'2151I1IX&&2
 ,
(j "((::II+VHH	 00'X]]XEVEVW%$	 1  G G557BBDEE+,
  	5aS9s 	sE   <C:C2C:27C )C*C .(C:C 	C7"C22C77C:c                  K   | j                   j                  |      }|W| j                  j                  t	        |g             d {   }|st        dd      |d   }t        j                  |      S |j                  j                         r1|j                  %	 |j                   d {    |j                         S |j                         S 7 7 &# t        $ r Y |j                         S w xY ww)Nhandler_id_inHandler not foundr   r   r   )rX   r   rZ   r   r1   r   _WorkflowHandlerhandler_data_from_persistentr   doner   r   r   )rK   r~   r   foundexistings        rL   _load_handlerzWorkflowServer._load_handler  s     ..$$Z0?..44J<8 E #+>CPPQxH#@@JJ""'')gll.F!,,&&
 ,,..7,,.. '  ,,..	sI   AC4	C
AC4C -C.C 2!C4C 	C1C40C11C4c                  K   |j                   d   }|st        dd      | j                  |       d{   }|j                  dv rdn|j                  dk(  rd	nd
}|j	                         }|j
                  sd|d<   nY|j
                  j                  }|dk(  r%|j
                  j                  j                  d      n|j
                  j                  |d<   t        ||      S 7 w)a/  
        ---
        summary: Get workflow result (deprecated)
        description: |
          Deprecated. Use GET /handlers/{handler_id} instead. Returns the final result of an asynchronously started workflow, if available.
        parameters:
          - in: path
            name: handler_id
            required: true
            schema:
              type: string
            description: Workflow run identifier returned from the no-wait run endpoint.
        deprecated: true
        responses:
          200:
            description: Result is available
            content:
              application/json:
                schema:
                  type: object
          202:
            description: Result not ready yet
            content:
              application/json:
                schema:
                  type: object
          404:
            description: Handler not found
          500:
            description: Error computing result
            content:
              text/plain:
                schema:
                  type: string
        r~   Handler ID is requiredr   r   Nrw      r   r   r   r   zworkflows.events.StopEventr   )
r   r   r	  r   r   r   r   r   r   r   )rK   r   r~   handler_datar   response_modelr   s          rL   re   z#WorkflowServer._get_workflow_result  s     H ((6
'?SQQ!//
;; ""i/  ""k1  	 &002 ""'+N8$&&55D 77 ##))--h7!((.. 8$
 N??) <s   3C'C%B0C'c                   K   |j                   d   }|st        dd      | j                  |       d{   }|j                  dv rdn|j                  dk(  rd	nd
}t	        |j                         |      S 7 Bw)a  
        ---
        summary: Get workflow handler
        description: Returns the final result of an asynchronously started workflow, if available
        parameters:
          - in: path
            name: handler_id
            required: true
            schema:
              type: string
            description: Workflow run identifier returned from the no-wait run endpoint.
        responses:
          200:
            description: Result is available
            content:
              application/json:
                schema:
                  $ref: '#/components/schemas/Handler'
          202:
            description: Result not ready yet
            content:
              application/json:
                schema:
                  $ref: '#/components/schemas/Handler'
          404:
            description: Handler not found
          500:
            description: Error computing result
            content:
              text/plain:
                schema:
                  type: string
        r~   r  r   r   Nrw   r  r   r   r   r   )r   r   r	  r   r   r   )rK   r   r~   r  r   s        rL   rj   z$WorkflowServer._get_workflow_handler  s     D ((6
'?SQQ!//
;; ""i/  ""k1  	 L3356JJ <s   3A:A8AA:c                <  
K   |j                   d   }|j                  j                  dd      j                         }|j                  j                  dd      j                         dk(  |j                  j                  dd      j                         dk(  |j                  j                  dd      j                         dk(  	 t	        |      }| j                  j                  |      }|]| j                  j                  t        |g             d{   }|r |d   j                  }|dv rt        dd      t        dd      |j                  j                         r3|j                  '|j                  j                         rt        dd      rdnd}	 |j!                  |       d{   
d
fd}	t%         |	|      |      S # t
        $ r t        d	| d
d      w xY w7 7 @# t"        $ r}t        d| dd      |d}~ww xY ww)a<  
        ---
        summary: Stream workflow events
        description: |
          Streams events produced by a workflow execution. Events are emitted as
          newline-delimited JSON by default, or as Server-Sent Events when `sse=true`.
          Event data is returned as an envelope that preserves backward-compatible fields
          and adds metadata for type-safety on the client:
          {
            "value": <pydantic serialized value>,
            "types": [<class names from MRO excluding the event class and base Event>],
            "type": <class name>,
            "qualified_name": <python module path + class name>,
          }

          Event queue is mutable. Elements are added to the queue by the workflow handler, and removed by any consumer of the queue.
          The queue is protected by a lock that is acquired by the consumer, so only one consumer of the queue at a time is allowed.

        parameters:
          - in: path
            name: handler_id
            required: true
            schema:
              type: string
            description: Identifier returned from the no-wait run endpoint.
          - in: query
            name: sse
            required: false
            schema:
              type: boolean
              default: true
            description: If false, as NDJSON instead of Server-Sent Events.
          - in: query
            name: include_internal
            required: false
            schema:
              type: boolean
              default: false
            description: If true, include internal workflow events (e.g., step state changes).
          - in: query
            name: acquire_timeout
            required: false
            schema:
              type: number
              default: 1
            description: Timeout for acquiring the lock to iterate over the events.
          - in: query
            name: include_qualified_name
            required: false
            schema:
              type: boolean
              default: true
            description: If true, include the qualified name of the event in the response body.
        responses:
          200:
            description: Streaming started
            content:
              text/event-stream:
                schema:
                  type: object
                  description: Server-Sent Events stream of event data.
                  properties:
                    value:
                      type: object
                      description: The event value.
                    type:
                      type: string
                      description: The class name of the event.
                    types:
                      type: array
                      description: Superclass names from MRO (excluding the event class and base Event).
                      items:
                        type: string
                    qualified_name:
                      type: string
                      description: The qualified name of the event.
                  required: [value, type]
          404:
            description: Handler not found
        r~   acquire_timeout1include_internalfalsetrueinclude_qualified_namessezInvalid acquire_timeout: ''r   r   Nr  r   >   r   r   r   zHandler is completed   r  r   ztext/event-streamzapplication/x-ndjsontimeout#No lock available to acquire after 	s timeout  c                 K   2 3 d {   }st        |t              rt        j                  |      }|j	                         }r
d| d n| d t        j                  d       d {    u7 p7 6 y w)N)r  zdata: z


r   )
isinstancer   r-   
from_eventmodel_dump_jsonr   sleep)r   r   envelopepayload	generatorr  r  r  s       rL   event_streamz3WorkflowServer._stream_events.<locals>.event_stream  s     ( ' 'e'Ju>S,T4??2H #224"7)400$IR.(mmA&&&' '  )s8   BA?A;A?A'B5A=6B;A?=B?B)
media_type)r   r  rT   zAsyncGenerator[str, None])r   query_paramsr   lowerfloat
ValueErrorr   rX   rZ   r   r1   r   queueemptyr   r  acquire_events_streamNoLockAvailabler   )rK   r   r~   r  r   	persistedr   r)  r   r(  r'  r  r  r  s             @@@@rL   rf   zWorkflowServer._stream_eventsB  s*    b ((6
&&**+<cBHHJ  $$%7AGGIVS 	   $$%=vFLLNRXX 	 ""&&uf5;;=G	GnG ..$$Z0?"2288J<8 I "1,,AA'/ESVWW':LL== W\\%=',,BSBSBU  '=3OO -0(5K
	%;;G;LLI	' 	'  !g!6:NNa  	3G9A>C 	$ M 	<WIYO 	sb   CHG AHG5BH!G9 6G77G9 ;HG22H7G9 9	HHHHc                J  K   d
fd} |d      } |d      }h d}|8t        t        t           t        t        |      j	                  |                  nd}| j
                  j                  t        ||             d{   }|D cg c]  }t        |j                  |j                  |j                  |j                  |j                  r|j                  j                         nd|j                  r|j                  j                         nd|j                   r|j                   j                         nd|j"                  |j$                  rt'        j(                  |j$                        nd	       }	}t+        t-        |		      j/                               S 7 c c}w w)a  
        ---
        summary: Get handlers
        description: Returns workflow handlers, optionally filtered by query parameters.
        parameters:
          - in: query
            name: status
            required: false
            schema:
              type: array
              items:
                type: string
                enum: [running, completed, failed, cancelled]
            style: form
            explode: true
            description: |
              Filter by handler status. Can be provided multiple times (e.g., status=running&status=failed)
          - in: query
            name: workflow_name
            required: false
            schema:
              type: array
              items:
                type: string
            style: form
            explode: true
            description: |
              Filter by workflow name. Can be provided multiple times (e.g., workflow_name=test&workflow_name=other)
        responses:
          200:
            description: List of handlers
            content:
              application/json:
                schema:
                  $ref: '#/components/schemas/HandlersList'
        c                   t        j                  j                  |             }|s"j                  j                  |       xs d}|g}|D cg c]#  }|j	                         s|j	                         % }}|sy |S c c}w )N )r^   r*  getlistr   strip)
param_namer   singler   r   s       rL   _parse_list_paramz7WorkflowServer._get_handlers.<locals>._parse_list_param  su    '..66zBCF --11*=C 17I5;;=ekkmIFIM Js   A=$A=r   r   >   r   rw   r   r   Nrx   r5  r   )r   )r8  r   rT   zlist[str] | None)r   r^   r3   setintersectionrZ   r   r1   r$   r~   r   r   r   r   	isoformatr   r   r   r   r-   r"  r   r%   r   )
rK   r   r:  status_valuesrz   allowed_status_valuesry   persistent_handlershr   s
    `        rL   ri   zWorkflowServer._get_handlers  sf    L		 *(3,_=.
 (	 VS./<<]KL
  	 %)$8$8$>$>9?OP%
 
" )
  <<ooxxxx78||1<<11378||1<<113;<>>Q^^557tgg88 1;;AHHE
 
  0%@KKMNN'

s%   B F#FF#C*F6&F#F#c                B  K   |j                   d   }| j                  j                  |      }|"t        |j                        rt        dd      |a| j                  |       d{   }t        |j                        rt        dd      t        j                  d| d       t        dd      |j                  }|j                  }|t        d	d
      	 |j                          d{   }|j                  d      }|j                  d      }	|st        dd      	 t        j                  || j                  |j                              }
	 |j'                  |
|	       t)        t+        d      j-                               S 7 %7 # t         $ r}t        t#        |      d      d}~wt$        $ r}t        d| d      d}~ww xY w# t$        $ r}t        d| d      d}~ww xY w# t
        $ r  t$        $ r}t        d| d
      d}~ww xY ww)a  
        ---
        summary: Send event to workflow
        description: Sends an event to a running workflow's context.
        parameters:
          - in: path
            name: handler_id
            required: true
            schema:
              type: string
            description: Workflow handler identifier.
        requestBody:
          required: true
          content:
            application/json:
              schema:
                type: object
                properties:
                  event:
                    description: Serialized event. Accepts object or JSON-encoded string for backward compatibility.
                    oneOf:
                      - type: string
                        description: JSON string of the event envelope or value.
                        examples:
                          - '{"type": "ExternalEvent", "value": {"response": "hi"}}'
                      - type: object
                        properties:
                          type:
                            type: string
                            description: The class name of the event.
                          value:
                            type: object
                            description: The event value object (preferred over data).
                        additionalProperties: true
                  step:
                    type: string
                    description: Optional target step name. If not provided, event is sent to all steps.
                required: [event]
        responses:
          200:
            description: Event sent successfully
            content:
              application/json:
                schema:
                  type: object
                  properties:
                    status:
                      type: string
                      enum: [sent]
                  required: [status]
          400:
            description: Invalid event data
          404:
            description: Handler not found
          409:
            description: Workflow already completed
        r~   NzWorkflow already completedr  r   zHandler z is running but not in memory.zHandler expiredzContext not availabler   r   stepzEvent data is requiredr   zFailed to deserialize event: )rC  zFailed to send event: sentr   zError processing request: )r   rX   r   r+   r   r   r	  r   warningr   r   jsonr,   parse_event_registryr   r.   r   r   
send_eventr   r'   r   )rK   r   r~   r   r  r   r   body	event_strrC  r   r   s               rL   rg   zWorkflowServer._post_event*  s%    t ((6
 ..$$Z0#6w~~#F'CQTUU?!%!3!3J!??L"<#6#67#7S  *5STU#+<#NN%% kk;'>CPP$	 'D)I88F#D#+CQTUU	%++t33G4I4IJu40   1 @ K K MNNa @( ( ( D#3q6sCC #:1#>C   #3A37S   	 	3A37S 	s   A%H'F(A3HG5 /F05G5 &/F G )"G5 HG5 	GF00G<GGG5 	G2G--G22G5 5HHHHc                  K   |j                   d   }|j                  j                  dd      j                         dk(  }| j                  j                  |      }||st        dd      || j                  |       d{    |r@| j                  j                  t        |g	             d{   }|d
k(  rt        dd      t        t        |rdnd      j                               S 7 m7 ?w)a  
        ---
        summary: Stop and delete handler
        description: |
          Stops a running workflow handler by cancelling its tasks. Optionally removes the
          handler from the persistence store if purge=true.
        parameters:
          - in: path
            name: handler_id
            required: true
            schema:
              type: string
            description: Workflow handler identifier.
          - in: query
            name: purge
            required: false
            schema:
              type: boolean
              default: false
            description: If true, also deletes the handler from the store, otherwise updates the status to cancelled.
        responses:
          200:
            description: Handler cancelled and deleted or cancelled only
            content:
              application/json:
                schema:
                  type: object
                  properties:
                    status:
                      type: string
                      enum: [deleted, cancelled]
                  required: [status]
          404:
            description: Handler not found
        r~   purger  r  Nr  r   r   r  r   deletedr   r   )r   r*  r   r+  rX   r   r   rZ   deleter1   r   r#   r   )rK   r   r~   rM  r   	n_deleteds         rL   rk   zWorkflowServer._cancel_handler  s     H ((6
$$((':@@BfL..$$Z0?5':LL %%g... "2299J<8 I A~#+>CPP!$)y{jl
 	
 /s$   A?C3C//C31C12>C31C3c                    d|j                   vrt        dd      |j                   d   }|| j                  vrt        dd      t        || j                  |         S )NrS   z'name' parameter missingr   r   zWorkflow not foundr   r{   )r   r   rU   r   )rK   r   rS   s      rL   r   z WorkflowServer._extract_workflow  s^    ,,,'AsSS""6*t&';MM4$//$2GHHrq   c                  K   	 	 |j                          d {   }|j                  d      }|j                  di       }|j                  d|      }|j                  d      }	d }
|d	 t	        j
                  || j                  |      |j                        }
|
0t        |
|j                        st        d
|j                   d      d }|rt        j                  ||      }nr|	rp| j                  j                  t        |	g|gdg             d {   }t        |      dk(  rt        dd      t        j                  ||d   j                        }|	xs
 t!               }	||
|	fS 7 T# t        $ r}t        d| d      d }~ww xY w# t        $ r}t        d	| d      d }~ww xY w7 # t        $ r  t        $ r}t        d| d      d }~ww xY ww)NzInvalid JSON body: r   r   r   kwargsr   r~   )explicit_eventz$Validation error for 'start_event': z#Start event must be an instance of r|   r   )r  rz   ry   r   r  r   zError processing request body: r   )rF  r   r   r   r,   rG  rH  r   r!  r   r   rZ   r   r1   r   r   nanoid)rK   r   rs   r   rJ  r   context_data
run_kwargsstart_event_datar~   r   r   persisted_handlerss                rL   r   z"WorkflowServer._extract_run_params  s    ;	W$\\^+  88I.L(B/J#xxzB,/J K+"/"5"5(,,];'/'A'A#K *:!;!;4 (!DXE_E_D`a$'  G!++XLQ+/+?+?+E+E '1l*7#.-, &" )*a/'/BPSTT!++H6H6K6O6OP#/vxJ[*55c , W#-@+DRUVVW" ! '!EaSI$' $&  	 	8<# 	s   GE/ E,E/ A
F3 (1F A=F3 F1AF3 +G,E/ /	F8FFF3 	F.F))F..F3 3GGGGc                   K   t        d|i      5  |j                  j                  ||      }| j                  ||j                  |       d{   }|cddd       S 7 # 1 sw Y   yxY ww)z6Start a workflow and return a wrapper for the handler.r~   )r   r   N)r   rs   run_run_workflow_handlerrS   )rK   rs   r~   r   r   r   r   s          rL   r   zWorkflowServer._start_workflow/  s|      lJ78 	''++' , G !66HMM7 G 	 	
	 	s.   A,>A AA 
A,A  A)%A,c                |   K   t        j                         }t        j                  t        j
                        }t        ||dt        j                         |||d j                   j                        }|j                          d{    | j                  <   d fd}|j                  |       |S 7 .w)zP
        Creates a wrapper for the handler and starts streaming events.
        N)r   r.  r   consumer_mutexr~   r   r   r   r   rZ   r_   c                 ~   K   j                   j                   d        j                  j                   d        y wrH   )rX   poprY   )r~   rK   s   rL   	on_finishz7WorkflowServer._run_workflow_handler.<locals>.on_finish\  s/     NNz40MMj$/s   :=ra  rT   None)r   Queuer   r   r   r   r  LockrZ   r_   
checkpointrX   start_streaming)rK   r~   r   r   r.  r   r   ra  s   ``      rL   r\  z$WorkflowServer._run_workflow_handlerA  s      '.mmo\\(,,/
""<<>!'!! 00!%!:!:
   """%,z"	0 	)4 	#s   BB<B:/B<c                  K   |j                   j                         s>	 |j                   j                          	 |j                   j	                          d{    |j
                  |j
                   d{    | j                  j                  |j                  d       | j                  j                  |j                  d       y# t        $ r Y w xY w7 # t        $ r Y w xY w7 qw)zClose and cleanup a handler.N)
r   r  cancelr   
cancel_runr   rX   r`  r~   rY   r   s     rL   r   zWorkflowServer._close_handlerd  s      ""'')##**,))44666 <<#,,7--t4',,d3   7  sd   C*C C CC C*6C(7AC*	CC*CC*C 	C%"C*$C%%C*c                   | j                   |   j                  D ci c]  }|j                  | }}|j                  | j                  j                  |d       xs g D ci c]  }|j                  | c}       |S c c}w c c}w rH   )rU   r   __name__r   rV   r   )rK   r   r   r   s       rL   rH  zWorkflowServer._event_registryw  s    (,(F(M(MN1QNN 0044]DIOR 

A	
  Os   A<B)r:   zlist[Middleware] | Noner;   zAbstractWorkflowStore | Noner<   list[float]rH   )rS   r   rs   r   rt   zlist[type[Event]] | NonerT   rd  )rT   z'WorkflowServer')rT   z&AsyncGenerator['WorkflowServer', None]rc  )	localhostP   N)r   r   r   intr   zdict[str, Any] | NonerT   rd  )rT   dict)r   r   rT   r   )r~   r   rT   r$   )r   r   rT   r   )r   r   rT   r   )r   r   rs   r   r   r   rT   z-tuple[Context | None, StartEvent | None, str])NN)
rs   r   r~   r   r   zStartEvent | Noner   zContext | NonerT   r  )r~   r   r   r   r   r"   rT   r  )r   r  rT   rd  )r   r   rT   zdict[str, type[Event]])rm  
__module____qualname__rp   ru   r   r   rI   r   r   r   rh   ra   rm   rb   rd   rl   rc   r	  re   rj   rf   ri   rg   rk   r   r   r   r\  r   rH   rq   rL   r8   r8   E   s    /37;,/8o
 ,o
 5	o
 )o
j 7;	>> > 4	>
 
>*X    04	  .	
 
"P*lK(;,+XZYv5
n)
VCFJ/(<@|.K`LO\XOtxt<
BI>>*2>CF>	6>H *."&   '	
   
$!!.1!<K!	!F4&rq   r8   c                  "   e Zd ZU dZded<   ded<   ded<   ded	<   d
ed<   d
ed<   ded<   ded<   ded<   ded<   ded<   dZded<   d%dZd&dZd'dZd(dZ	e
d)d       Zed*d       Zed+d       Zed,d        Zd-d!Zd-d"Z	 d.	 	 	 d/d#Zd.d/d$Zy)0r  zvA wrapper around a handler: WorkflowHandler. Necessary to monitor and dispatch events from the handler's stream_eventsr"   r   zasyncio.Queue[Event]r.  zasyncio.Task[None] | Noner   zasyncio.Lockr^  r   r~   r   r   r   r   zdatetime | Noner   r0   rZ   rn  r_   Nz$Callable[[], Awaitable[None]] | None
_on_finishc                   t        j                  t        j                        | _        | j
                  dv r| j                  | _        t        | j                  | j                  | j
                  | j                  j                  | j                  | j                  | j                  | j                  | j                  | j                  j                  r$| j                  j                  j!                         ni 
      }|S )zDPersist the current handler state immediately to the workflow store.)r   r   r   r   )r   r   r   r   r   r   r   r2   r~   r   r   r   r   r   r   r   to_dictrK   r   s     rL   _as_persistentz_WorkflowHandler._as_persistent  s    ",,x||4;;>> $D&,,;;##****;;**262B2B2F2F  $$,,.B

 rq   c                V   K   | j                   j                  |       d {    y 7 wrH   )rZ   r   rz  s     rL   persistz_WorkflowHandler.persist  s      ""))*555s   )')c           	       K   t        | j                        }	 | j                         }	 	 | j                  |       d{    y# t        $ r-}t        j                  d| j                   d| d        d}~ww xY w7 ># t        $ r}|r|j                  d      nd}|Pt        j                  d| j                   dd       	 | j                  j                           # t        $ r Y  w xY wt        j                  d| j                   d| d	|        t        j                  |       d{  7   Y d}~nd}~ww xY ww)
zBPersist with retry/backoff; cancel handler when retries exhausted.zFailed to checkpoint handler zV to persistent state. Is there non-serializable state in an event or the state store? Tr   Nr   z* after final attempt. Failing the handler.z. Retrying in z
 seconds: )r^   r_   r{  r   r   r   r~   r}  r`  r   rj  r   r$  )rK   backoffsr   r   backoffs        rL   rg  z_WorkflowHandler.checkpoint  se    112	,,.J -ll:...  	LL//@  AW  XY  WZ  [   	 / --5(,,q/4?LL77HHrs!% ! 
((//1  %  3DOO3DNSZR[[efgehi mmG,,,!-	 s   EA EB  A> B  E	A;(A66A;;E>B   	E 	<D;C! D;!	C-*D;,C--AD;0D31D;6E;E  Ec                   t        | j                  | j                  | j                  j                  | j
                  | j                  j                         | j                  j                         | j                  | j                  j                         nd| j                  | j                  $t        j                  | j                        	      S d	      S )z.Convert runtime handler to API response model.Nr   )r$   r~   r   r   r   r   r   r=  r   r   r   r   r-   r"  r   s    rL   r   z"_WorkflowHandler.to_response_model  s    ,,##**;;002002  , **446**{{& -77D
 	
 
 	
rq   c                0   t        | j                  | j                  | j                  | j                  | j
                  | j
                  j                         n0t        j                  t        j                        j                         | j                  | j                  j                         nd | j                  | j                  j                         nd | j                  | j                  $t        j                   | j                        	      S d 	      S )Nr   )r$   r~   r   r   r   r   r=  r   r   r   r   r   r   r   r   r-   r"  )r   s    rL   r  z-_WorkflowHandler.handler_data_from_persistent  s    !,,$22$$$$$$0 ",,668hll+557$$0 ",,668&&2 $00::<""  , -77
8I8IJ
 	
" #
 	
rq   c                    | j                   j                         sy| j                   j                         ry| j                   j                         }|yy)z7Get the current status by inspecting the handler state.rw   r   r   r   )r   r  r   	exceptionrK   excs     rL   r   z_WorkflowHandler.status  sM     $$&%%'((*?rq   c                    | j                   j                         sy 	 | j                   j                         }|t        |      S d S # t        j                  $ r Y y w xY wrH   )r   r  r  r   CancelledErrorr   r  s     rL   r   z_WorkflowHandler.error  s_    $$&	"",,.C ?s3x44 %% 		s   A AAc                    | j                   j                         sy 	 | j                   j                         S # t        j                  $ r Y y t
        $ r Y y w xY wrH   )r   r  get_stop_eventr   r  r   r   s    rL   r   z_WorkflowHandler.result  sT    $$&	##2244%% 	 		s   7 AAAc                X    t        j                  | j                  |            | _        y)z;Start streaming events from the handler and managing state.rb  N)r   create_taskrf   r   )rK   ra  s     rL   rh  z _WorkflowHandler.start_streaming  s"    ''(;(;i(;(PQ	rq   c                  K   t        d| j                  i      5  | j                          d{    || _        | j                  j                  d      2 3 d{   }t        |t              r|j                  t        j                  k(  rz| j                  j                  r$| j                  j                  j                         nd}|$t        j                  d| j                   d       | j                          d{    | j                  j!                  |       7 7 7 $6 	 | j                   d{  7   nt# t"        j$                  $ r& t        j'                  d| j                   d       Y n<t(        $ r1}t        j+                  d| j                   d	| d
       Y d}~nd}~ww xY w| j                          d{  7   ddd       y# 1 sw Y   yxY ww)zHInternal method that streams events, updates status, and persists state.r~   NT)expose_internalz"Context state is None for handler z. This is not expected.zWorkflow run z was cancelledz	 failed! r   )r   r~   rg  rw  r   stream_eventsr!  r    
step_stater   NOT_RUNNINGr   ry  r   rE  r.  
put_nowaitr   r  r   r   r   )rK   ra  r   stater   s        rL   rf   z_WorkflowHandler._stream_events  s    lDOO<= 	$//###'DO#//==d=S - -eu&67((I,A,AA ;?:J:J:N:N((,,446TX  }@@QQhi !//+++

%%e,# $- ,  T"	&&&&)) MmDOO+<NKL #DOO#4IaSAD   
 //###?	$ 	$ 	$s   G"GD"'GD(D$D(B#GD&!G$D(&G(G*E 9D<:E ?G 6F16G8F1 'F,'G,F11GG
G	G"GG"c                   K   	 t        j                  | j                  j                         |       d{    | j                  |      S 7 # t         j                  $ r t        d| d      w xY ww)z`
        Acquires the lock to iterate over the events, and returns generator of events.
        r  Nr  r  )r   wait_forr^  acquireTimeoutErrorr1  _iter_events)rK   r  s     rL   r0  z&_WorkflowHandler.acquire_events_streamB  sy     	""4#6#6#>#>#@'RRR
    11 S## 	!5gYiH 	s+   A52A AA A5A #A22A5c                 K   	 | j                   j                         r(| j                  ^| j                  j                         sCg }| j                   j                         sD|j	                  | j                   j                                | j                   j                         sD|D ]  }| 	 t        j                  | j                   j                               }| j                  }t        j                  |||hn|ht        j                         d{   \  }}||v r| d{    n|j                          nD| j                   j                         s| j                  | j                  j                         sC| j                  2| j                  j                         r| j                          d{    | j                  j                          y7 7 7 ## | j                  3| j                  j                         r| j                          d{  7   | j                  j                          w xY ww)z
        Converts the queue to an async generator while the workflow is still running, and there are still events.
        For better or worse, multiple consumers will compete for events
        N)return_when)r.  r/  r   r  r   
get_nowaitr   r  r   waitFIRST_COMPLETEDrj  rw  r   r^  release)rK   r  available_eventsr   queue_get_tasktask_waitabler  pendings           rL   r  z_WorkflowHandler._iter_eventsP  s    	*jj&&(		%diinn.>#% ****,$++DJJ,A,A,CD ****,-  EK 6=6I6IJJNN$7 !%		&-ll$0 $]3() ' 7 7	' !g "T) ..."))+- jj&&(		%diinn.>. *t/?/?/D/D/Foo''''')! / ( *t/?/?/D/D/Foo''''')sl   IB!G( &A4G( G"G( +G$,3G( !&G( 	9IG&I"G( $G( &I(:I"H%# II)rT   r2   )r   r2   rT   rd  rc  )rT   r$   )r   r2   rT   r$   )rT   r3   )rT   z
str | None)rT   zStopEvent | None)ra  zCallable[[], Awaitable[None]]rT   rd  )   )r  r,  rT   zAsyncGenerator[Event, None])rm  rs  rt  __doc____annotations__rw  r{  r}  rg  r   staticmethodr  propertyr   r   r   rh  rf   r0  r  ru  rq   rL   r  r    s     A  
##   O!! +*%%7;J4;(6-B
$ 
 
*   5 5  R!$H  !22	$2"*rq   r  c                      e Zd ZdZy)r1  z;Raised when no lock is available to acquire after a timeoutN)rm  rs  rt  r  ru  rq   rL   r1  r1  u  s    Erq   r1  c                  "    e Zd ZU ded<   ded<   y)r   r   rS   r   rs   N)rm  rs  rt  r  ru  rq   rL   r   r   {  s    
Irq   r   __main__zGenerate OpenAPI schema)r   z--outputzopenapi.jsonzOutput file path)r   defaulthelpw   )indentfpzOpenAPI schema written to )j
__future__r   r   rF  logging
contextlibr   dataclassesr   r   r   importlib.metadatar   pathlibr	   typingr
   r   r   r   r   r   &llama_index_instrumentation.dispatcherr   starlette.applicationsr   starlette.exceptionsr   starlette.middlewarer   starlette.middleware.corsr   starlette.requestsr   starlette.responsesr   r   starlette.routingr   starlette.schemasr   starlette.staticfilesr   r   r   r   workflows.eventsr   r   r   r   r    r!   workflows.handlerr"   workflows.protocolr#   r$   r%   r&   r'   r(   r)   r*   r+   &workflows.protocol.serializable_eventsr,   r-   r.   workflows.representation_utilsr/   (workflows.server.abstract_workflow_storer0   r1   r2   r3   &workflows.server.memory_workflow_storer4   workflows.typesr5   workflows.utilsr6   rU  	getLoggerr   r8   r  r   r1  r   rm  argparseArgumentParserparseradd_argumentr   
parse_argsargsr   r   dict_schemaopenoutputfdumpprintru  rq   rL   <module>r     s   #    * ! ' &  A A  B , . + 4 & ? # - - '  .
 
 
 
 F  G & .				z zz) o* o* o*d	i 	   
 z$X$$1JKF
n;M   DF'')K	dkk3	 /1		+aA./	&t{{m
45 / /s   G		G