
    ^(jY4                        d Z ddlmZ ddlmZ  G d d      Z eh d      Z eh d      Zde	d	e
fd
Zd Zded	efdZdZde	d	efdZded	eee   ee	   f   fdZde	ded	e
fdZdede	d	efdZd+de	dede
d	efdZded	eeee   f   fdZdee   de	de	d	ee   fd Zde	d!ed"ed#ed	ee   f
d$Z	 	 	 	 	 	 d,d!ed"ed#ed&eee	      d'ee	   de	de	d(ee   d)ed	eee   ef   fd*Zy%)-zp
Job utilities for the /api/jobs endpoint.
Provides normalization and helper functions for job status tracking.
    )Optional)
prune_dictc                   2    e Zd ZdZdZdZdZdZdZeeeeegZ	y)	JobStatuszJob status constants.pendingin_progress	completedfailed	cancelledN)
__name__
__module____qualname____doc__PENDINGIN_PROGRESS	COMPLETEDFAILED	CANCELLEDALL     >/Users/danicosta/Desktop/Flux2/ComfyUI/comfy_execution/jobs.pyr   r      s.    GKIFIKFI
>Cr   r   >   3dtextaudiovideoimages>   .fbx.glb.obj.gltf.usdzfilenamereturnc                 T    | j                         t        fdt        D              S )Nc              3   @   K   | ]  }j                  |        y wNendswith).0extlowers     r   	<genexpr>z#has_3d_extension.<locals>.<genexpr>   s     A.@su~~c".@   )r,   anyTHREE_D_EXTENSIONS)r#   r,   s    @r   has_3d_extensionr1      s!    NNEA.@AAAr   c                 t    | yt        | t              rt        |       r| ddddS yt        | t              r| S y)zNormalize a single output list item for the jobs API.

    Returns the normalized item, or None to exclude it.
    String items with 3D extensions become {filename, type, subfolder} dicts.
    Noutput r   )r#   type	subfolder	mediaType)
isinstancestrr1   dict)items    r   normalize_output_itemr<   "   sC     |$D! $hRVZ[[$r   outputsc                 <   i }| j                         D ]  \  }}t        |t              s|||<   i }|j                         D ]Q  \  }}|dk(  st        |t              s|||<   !g }|D ]%  }|t	        |      }	|j                  |	|	n|       ' |||<   S |||<    |S )zNormalize raw node outputs for the jobs API.

    Transforms string 3D filenames into file output dicts and removes
    None items. All other items (non-3D strings, dicts, etc.) are
    preserved as-is.
    animated)itemsr8   r:   listr<   append)
r=   
normalizednode_idnode_outputsnormalized_node
media_typer@   normalized_itemsr;   norms
             r   normalize_outputsrJ   3   s     J!(,-".Jw!-!3!3!5JZ'z%/F.3
+!<,T2 ''0@dK	 
 +;OJ' "6 .
7! "1" r   i   valuec                 F    t        |       t        k  rd| iS | dt         ddS )zCreate a text preview dict with optional truncation.

    Returns:
        dict with 'content' and optionally 'truncated' flag
    contentNT)rM   	truncated)lenTEXT_PREVIEW_MAX_LENGTH)rK   s    r   _create_text_previewrQ   R   s5     5z,,5!!112 r   
extra_datac                     | j                  d      }| j                  di       }|j                  di       j                  d      }||fS )zqExtract create_time and workflow_id from extra_data.

    Returns:
        tuple: (create_time, workflow_id)
    create_timeextra_pnginfoworkflowidget)rR   rT   rU   workflow_ids       r   _extract_job_metadatar[   `   sJ     ../KNN?B7M##J377=K##r   rG   r;   c                     | t         v ry|j                  dd      }|r#|j                  d      s|j                  d      ry|j                  dd      j                         t	        fdt
        D              ryy)	au  
    Check if an output item is previewable.
    Matches frontend logic in ComfyUI_frontend/src/stores/queueStore.ts
    Maintains backwards compatibility with existing logic.

    Priority:
    1. media_type is 'images', 'video', 'audio', or '3d'
    2. format field starts with 'video/' or 'audio/'
    3. filename has a 3D extension (.obj, .fbx, .gltf, .glb, .usdz)
    Tformatr4   zvideo/zaudio/r#   c              3   @   K   | ]  }j                  |        y wr'   r(   )r*   r+   r#   s     r   r-   z!is_previewable.<locals>.<genexpr>   s     
@-?c8S!-?r.   F)PREVIEWABLE_MEDIA_TYPESrY   
startswithr,   r/   r0   )rG   r;   fmtr#   s      @r   is_previewablerb   l   so     ,, ((8R
 C
x(CNN8,D xx
B'--/H

@-?
@@r   statusc           	      R    | \  }}}}}t        |      \  }}t        ||||d|d      S )zvConvert queue item tuple to unified job dict.

    Expects item with sensitive data already removed (5 elements).
    r   )rW   rc   priorityrT   outputs_countrZ   )r[   r   )r;   rc   re   	prompt_id_rR   rT   rZ   s           r   normalize_queue_itemri      sG    
 -1)HiJ4Z@K""  r   rg   history_iteminclude_outputsc                    |d   }|\  }}}}}t        |      \  }}	|j                  di       }
|
r|
j                  d      nd}|j                  di       }t        |      \  }}d}d}d}d}|
r|
j                  dg       }|D ]  }t        |t        t
        f      st        |      dk\  s)|d	   |d
   }}t        |t              sD|dk(  r|j                  d      }[|dv s`|j                  d      }|dk(  r|}y|dk(  sd} |dk(  rt        j                  }n8|dk(  r#|rt        j                  nt        j                  }nt        j                  }t        | |||||||||	d
      }|rt        |      |d<   |
|d<   ||d|d<   |S )zConvert history item dict to unified job dict.

    History items have sensitive data already removed (prompt tuple has 5 elements).
    promptrc   
status_strNr=   Fmessages   r      execution_start	timestamp)execution_successexecution_errorexecution_interruptedru   rv   Tsuccesserror)
rW   rc   re   rT   execution_start_timeexecution_end_timeru   rf   preview_outputrZ   execution_status)rm   rR   rV   )r[   rY   get_outputs_summaryr8   rA   tuplerO   r:   r   r   r   r   r   rJ   )rg   rj   rk   prompt_tuplere   rh   rm   rR   rT   rZ   status_inforn   r=   rf   r{   ru   ry   rz   was_interruptedro   entry
event_name
event_datarc   jobs                            r   normalize_history_itemr      s   
  )L)5&HaQ4Z@K""8R0K2=.4Jy"-G$7$@!M>OO??:r2E%$/CJ!O).q58J
j$/!%66/9~~k/J,#'hh-7^^K-H*%)::.8O'+BB.2O  Y$$	w	(7$$Y=M=M$$
" 40*&(" C *73I"-$
J
 Jr   c                 0   d}d}d}| j                         D ]  \  }}t        |t              s|j                         D ]  \  }}|dk(  st        |t              s|D ]  }t        |t              sYt	        |      }	|	J|dk(  rD|dz  }|=t        |t
              r
|r|d   nd}
nt        |      }
t        |
      }i |||d}||}j|	}|dz  }|tt        ||      si |d|i}d	|vr||d	<   |j                  d
      dk(  r|}||}   ||xs |fS )z
    Count outputs and find preview in a single pass.
    Returns (outputs_count, preview_output).

    Preview priority (matching frontend):
    1. type="output" with previewable media
    2. Any previewable media
    r   Nr?   r   rq   r4   )nodeIdr7   r   r7   r5   r3   )
r@   r8   r:   rA   r<   r~   r9   rQ   rb   rY   )r=   countr{   fallback_previewrD   rE   rG   r@   r;   rC   
text_valuetext_previewenricheds                r   r}   r}      sw    EN!(,-!-!3!3!5JZ'z%/F!$-!6t!<J!)%/!QJE-5#-dE#:<@abJ14TJ/CJ/O,"&2,".51;,"
 $4#;7?$4 %D
!-!*d3   ' H #$.0:-xx'83)1)1+3(Q  "6 "1d .4$444r   jobssort_by
sort_orderc                 @    |dk(  }|dk(  rd }nd }t        | ||      S )z,Sort jobs list by specified field and order.descexecution_durationc                 `    | j                  dd      }| j                  dd      }|r|r||z
  S dS )Nry   r   rz   rX   )r   startends      r   get_sort_keyz#apply_sorting.<locals>.get_sort_key"  s7    GG2A6E''.2C"%%3;6Q6r   c                 &    | j                  dd      S )NrT   r   rX   )r   s    r   r   z#apply_sorting.<locals>.get_sort_key'  s    77=!,,r   )keyreverse)sorted)r   r   r   r   r   s        r   apply_sortingr     s0    V#G&&	7
	- $L'::r   runningqueuedhistoryc                     | |v rt        | ||    d      S |D ]&  }|d   | k(  st        |t        j                        c S  |D ]&  }|d   | k(  st        |t        j                        c S  y)aY  
    Get a single job by prompt_id from history or queue.

    Args:
        prompt_id: The prompt ID to look up
        running: List of currently running queue items
        queued: List of pending queue items
        history: Dict of history items keyed by prompt_id

    Returns:
        Job dict with full details, or None if not found
    T)rk   rq   N)r   ri   r   r   r   )rg   r   r   r   r;   s        r   get_jobr   -  sz     G%i1CUYZZ7i'i.C.CDD  7i'i.?.?@@  r   Nstatus_filterrZ   limitoffsetc	                    g }	|t         j                  }t         j                  |v r0| D ]+  }
|	j                  t	        |
t         j                               - t         j
                  |v r0|D ]+  }
|	j                  t	        |
t         j
                               - t         j                  t         j                  t         j                  h}|t        |      z  }|rI|j                         D ]6  \  }}t        ||      }|j                  d      |v s&|	j                  |       8 |r$|	D cg c]  }|j                  d      |k(  s| }	}t        |	||      }	t        |	      }|dkD  r|	|d }	||	d| }	|	|fS c c}w )ae  
    Get all jobs (running, pending, completed) with filtering and sorting.

    Args:
        running: List of currently running queue items
        queued: List of pending queue items
        history: Dict of history items keyed by prompt_id
        status_filter: List of statuses to include (from JobStatus.ALL)
        workflow_id: Filter by workflow ID
        sort_by: Field to sort by ('created_at', 'execution_duration')
        sort_order: 'asc' or 'desc'
        limit: Maximum number of items to return
        offset: Number of items to skip

    Returns:
        tuple: (jobs_list, total_count)
    Nrc   rZ   r   )r   r   r   rB   ri   r   r   r   r   setr@   r   rY   r   rO   )r   r   r   r   rZ   r   r   r   r   r   r;   history_statusesrequested_history_statusesrg   rj   r   jtotal_counts                     r   get_all_jobsr   H  se   8 D!-DKK,T93H3HIJ  M)DKK,T93D3DEF  "++Y-=-=y?R?RS!1C4F!F!'.}}#I|(LACwwx $>>C  (7
 G4a155#7;#F4Gw
3Dd)KzFG}FU|+ Hs   'E4E4)F)NN
created_atr   Nr   )r   typingr   comfy_api.internalr   r   	frozensetr_   r0   r9   boolr1   r<   r:   rJ   rP   rQ   r~   intr[   rb   ri   r   r}   rA   r   r   r   r   r   r   <module>r      s  
  )? ? $$NO  IJ Bs Bt B
"t  8    	$d 	$uXc]HSM5Q/R 	$s $ 4 8u c d $>c > >PT >ae >B?5 ?5%Xd^0C*D ?5D;T
 ;S ;c ;d4j ; s T 4 $ 8TX> > *.!%=== = DI&	=
 #= = = C== = 4:s?=r   