
    `gjv                       d Z ddlmZ ddlZddlZddlZddl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mZmZ ddlZddlmZmZ ddlmZ dd	lmZmZmZmZmZ dd
lm Z m!Z!m"Z"m#Z# ddl$m%Z% ddl&m'Z'  ejP                  e)      Z*h dZ+h dZ, G d de-      Z. G d de.      Z/ G d de.      Z0 G d de/      Z1ee2ee2   ge3e2ef   f   Z4edee3e2ef   e#z     f   Z5ee#e3e2ef   ee3e2ef      gee3e2ef      f   Z6e G d d             Z7 G d d      Z8 G d d      Z9 G d d      Z:d'd Z;d(d!Z<d)d"Z=	 	 	 	 	 	 	 	 d*d#Z>d+d$Z?d,d%Z@d-d&ZAy).z=Pipeline orchestration for Microsoft Teams meeting summaries.    )annotationsN)	dataclass)Path)Any	AwaitableCallableOptional)async_call_llmextract_content_or_reasoning)get_hermes_home)download_recording_artifactenrich_meeting_with_call_recordfetch_preferred_transcript_textlist_recording_artifactsresolve_meeting_reference)MeetingArtifactTeamsMeetingPipelineJobTeamsMeetingRefTeamsMeetingSummaryPayload)TeamsPipelineStore)transcribe_audio>   failed	completedretry_scheduled>	   receivedsummarizingsending_teamswriting_linearwriting_notionresolving_meetingtranscribing_audiofetching_transcriptdownloading_recordingc                      e Zd ZdZy)TeamsPipelineErrorz/Base class for Teams meeting pipeline failures.N__name__
__module____qualname____doc__     R/root/.hermes/venv/lib/python3.12/site-packages/plugins/teams_pipeline/pipeline.pyr%   r%   4   s    9r,   r%   c                      e Zd ZdZy)TeamsPipelineRetryableErrorz1Raised when the pipeline should be retried later.Nr&   r+   r,   r-   r/   r/   8   s    ;r,   r/   c                      e Zd ZdZy)TeamsPipelineSinkErrorz!Raised when an output sink fails.Nr&   r+   r,   r-   r1   r1   <   s    +r,   r1   c                      e Zd ZdZy)"TeamsPipelineArtifactNotFoundErrorz4Raised when meeting artifacts are not yet available.Nr&   r+   r,   r-   r3   r3   @   s    >r,   r3   .c                      e Zd ZU dZded<   dZded<   dZded<   dZded	<   dZded
<   dZ	ded<   dZ
ded<   dZded<   dZded<   dZded<   edd       Zy)TeamsPipelineConfigTbooltranscript_preferredFtranscript_requiredtranscription_fallbackN
str | None	stt_modelffmpeg_extract_audioP   inttranscript_min_charszPath | Nonetmp_dirzdict[str, Any] | Nonenotionlinearteams_deliveryc                d   t        |xs i       }|j                  d      xs |j                  d      } | t        |j                  dd            t        |j                  dd            t        |j                  dd            |j                  d      xs |j                  d	      t        |j                  d
d            t        |j                  dd            |rt	        |      nd |j                  d      |j                  d      |j                  d      xs |j                  d      
      S )Nr@   tmpDirr7   Tr8   Fr9   r;   sttModelr<   r?   r=   rA   rB   rC   teamsDelivery)
r7   r8   r9   r;   r<   r?   r@   rA   rB   rC   )dictgetr6   r>   r   )clspayloaddatar@   s       r-   	from_dictzTeamsPipelineConfig.from_dictY   s    GMr"((9%;();!%dhh/Et&L!M $TXX.CU%K L#'1I4(P#Qhh{+Ctxx
/C!%dhh/Et&L!M!$TXX.Db%I!J%,DM$88H%88H%88$45R/9R
 	
r,   )rK   Optional[dict[str, Any]]returnz'TeamsPipelineConfig')r'   r(   r)   r7   __annotations__r8   r9   r;   r<   r?   r@   rA   rB   rC   classmethodrM   r+   r,   r-   r5   r5   L   s    !%$% %%#'D' Iz !%$% "#"G[$(F!($(F!(,0N)0
 
r,   r5   c                  N    e Zd ZdZdZdddd	dZ	 d
	 	 	 	 	 	 	 ddZddZddZy)NotionWriterzhttps://api.notion.com/v1z
2025-09-03Napi_key	transportc               l    |xs t        j                  dd      j                         | _        || _        y )NNOTION_API_KEY osgetenvstriprU   
_transportselfrU   rV   s      r-   __init__zNotionWriter.__init__o   *    B299-=r#BIIK#r,   c           
       K   | j                   st        d      t        |j                  d      xs |j                  d      xs d      j	                         }|xs i j                  d      }|s|st        d      d| j                    | j
                  dd	}t        j                  d
| j                        4 d {   }|r^|j                  | j                   d| |d| j                  ||      i       d {   }|j                          |j                         }	nn|j                  | j                   d|d|i| j                  ||      | j                  |      d       d {   }|j                          |j                         }	d d d       d {    	d   |	j                  d      dS 7 7 7 O7 !# 1 d {  7  sw Y   1xY ww)Nz!NOTION_API_KEY is not configured.database_id
databaseIdrY   page_idz8Notion sink requires database_id or an existing page_id.zBearer application/json)AuthorizationzNotion-VersionContent-Type      >@timeoutrV   z/pages/
propertiesheadersjsonz/pages)parentrm   childrenidurl)rf   rt   )rU   r1   strrI   r]   API_VERSIONhttpxAsyncClientr^   patchAPI_BASE_build_propertiesraise_for_statusrp   post_build_blocks)
r`   rK   configexisting_recordrd   rf   ro   clientresponserecords
             r-   write_summaryzNotionWriter.write_summarys   s     ||()LMM&**]3Uvzz,7OUSUV\\^"(b--i87()cdd  't||n5"...

 $$TT__M 	) 	)QW!'}}oWWI6#&(>(>w(OP ". " 
 ))+!!'}}oV,##0+">&*&<&<Wf&M$($6$6w$? "- "  ))+!)	) 	), "$<

50ABB-	)	) 	) 	) 	)sm   B=G?F9 G;G>F;?A.G-F=.$GGF?G;G=G?GGG
GGc                P   |j                  dd      }|j                  d      }|j                  d      }|ddd|j                  xs d|j                  j                   iigii}|rd	dd|j                  xs d
d d iigi||<   |r d	dd|j                  j                  iigi||<   |S )Ntitle_propertyNamesummary_propertymeeting_id_propertytitletextcontentMeeting 	rich_textrY   il  )rI   r   meeting_ref
meeting_idsummary)r`   rK   r   r   r   r   rm   s          r-   r{   zNotionWriter._build_properties   s    $4f=!::&89$jj)>? 6Iw}}/k(7K^K^KiKiJj@k#lmn&


 v	GOO4Ir5D3Q'RST,J'( v	73F3F3Q3Q'RST/J*+ r,   c           
        d|j                   xs dfddj                  d |j                  D              fddj                  d |j                  D              fddj                  d	 |j                  D              fg}g }|D ]A  \  }}|j                  d
dddd|iigid       |j                  d
dddd|xs diigid       C |S )NSummaryrY   zKey Decisions
c              3  &   K   | ]	  }d |   yw- Nr+   .0items     r-   	<genexpr>z-NotionWriter._build_blocks.<locals>.<genexpr>   s     'V"TF'V   zAction Itemsc              3  &   K   | ]	  }d |   ywr   r+   r   s     r-   r   z-NotionWriter._build_blocks.<locals>.<genexpr>   s     &TtD6{&Tr   Risksc              3  &   K   | ]	  }d |   ywr   r+   r   s     r-   r   z-NotionWriter._build_blocks.<locals>.<genexpr>   s     F"TFFr   block	heading_2r   r   r   )objecttyper   	paragraphNone)r   r   r   )r   joinkey_decisionsaction_itemsrisksappend)r`   rK   sectionsblocksheadingbodys         r-   r~   zNotionWriter._build_blocks   s    -2.dii'V@U@U'VVWTYY&Tw?S?S&TTUdiiFFFG	
 (*% 	MGTMM%'"-)W9M0N/O!P MM%'"-)T^V9T0U/V!W	 r,   rU   r:   rV   zhttpx.AsyncBaseTransport | NonerO   r   NrK   r   r   dict[str, Any]r   rN   rO   r   )rK   r   r   r   rO   r   )rK   r   rO   zlist[dict[str, Any]])	r'   r(   r)   rz   rv   ra   r   r{   r~   r+   r,   r-   rS   rS   k   sW    *HK04cg $ 59	)C+)C )C 2	)C
 
)CV(r,   rS   c                  :    e Zd ZdZdddddZ	 d	 	 	 	 	 	 	 ddZy)	LinearWriterzhttps://api.linear.app/graphqlNrT   c               l    |xs t        j                  dd      j                         | _        || _        y )NLINEAR_API_KEYrY   rZ   r_   s      r-   ra   zLinearWriter.__init__   rb   r,   c                  K   | j                   st        d      | j                   dd}t        |j                  d      xs |j                  d      xs d      j	                         }|j
                  xs d|j                  j                   }t        |      }|xs i j                  d      }t        j                  d	| j                  
      4 d {   }	|r0|	j                  | j                  |d|||ddd       d {   }
n<|st        d      |	j                  | j                  |dd|||did       d {   }
|
j                          |
j                         }d d d       d {    j                  d      xs i j                  d      xs i j                  d      xs7 |j                  d      xs i j                  d      xs i j                  d      }t!        |t"              r|j                  d      st        d|       |d   |j                  d      |j                  d      dS 7 i7 ;7 7 # 1 d {  7  sw Y   xY ww)Nz!LINEAR_API_KEY is not configured.rg   )rh   ri   team_idteamIdrY   zMeeting Summary: issue_idrj   rk   zmutation($id: String!, $input: IssueUpdateInput!) { issueUpdate(id: $id, input: $input) { success issue { id identifier url } } })r   description)rs   input)query	variablesrn   z7Linear sink requires team_id when creating a new issue.zjmutation($input: IssueCreateInput!) { issueCreate(input: $input) { success issue { id identifier url } } }r   )r   r   r   rL   issueUpdateissueissueCreaters   zLinear write failed: 
identifierrt   )r   r   rt   )rU   r1   ru   rI   r]   r   r   r   _render_summary_markdownrw   rx   r^   r}   API_URLr|   rp   
isinstancerH   )r`   rK   r   r   ro   r   r   r   existing_issue_idr   r   payload_jsonr   s                r-   r   zLinearWriter.write_summary   sU     ||()LMM$(LLBTUfjj+Ivzz(/CIrJPPRU#4W5H5H5S5S4T!U.w7,277
C$$TT__M 	+ 	+QW !'LL#n #4/4[%Q&	 "- "  01jkk!'LL#e '.'Ebm/n%o "- 
" 
 %%'#==?L?	+ 	+D '-222=AGRLLWU Z""6*0b55mDJOOPWX 	 %&eiio(+@)OPP!$Kuyy7NW\W`W`afWghhQ	+"
'	+ 	+ 	+ 	+sm   CIH=I-II <II$I'I2I3CI IIIIIIIr   r   r   )r'   r(   r)   r   ra   r   r+   r,   r-   r   r      sG    .G04cg $ 59	7i+7i 7i 2	7i
 
7ir,   r   c                      e Zd ZdZdedddd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y)TeamsMeetingPipelinezETranscript-first Teams meeting pipeline with durable lifecycle state.N)r   transcribe_fnsummarize_fnnotion_writerlinear_writerteams_senderc                   || _         || _        t        |t              r|nt        j	                  |      | _        || _        |xs | j                  | _        || _	        || _
        || _        y r   )graph_clientstorer   r5   rM   r   r   _generate_summary_payloadr   r   r   r   )	r`   r   r   r   r   r   r   r   r   s	            r-   ra   zTeamsMeetingPipeline.__init__  sf     )
 *63F GfM`MjMjkqMr*(JD,J,J**(r,   c                t   t        j                  |      }| j                  j                  ||       | j	                  |      }||S |j                  d      xs i }|j                  d      xsQ |j                  d      xs> t        t        |j                  d      xs d            xs |j                  d      xs |}t        dt        j                         j                  d d  |t        |j                  d      xs d	      |d
t        t        |      |j                  d      xs |j                  d      t        |      |j                  d      |j                  d      xs |j                  d      d            }| j                  j                  |j                  |j!                                |S )NresourceDatars   	meetingIdresourcerY   z
teams-job-   
changeTypezgraph.notificationr   tenantId
joinWebUrlcallRecordId)notificationjoin_web_urlcall_record_id)r   	tenant_idmetadata)job_idevent_idsource_event_type
dedupe_keystatusr   )r   build_notification_receipt_keyr   record_notification_receipt_find_job_by_dedupe_keyrI   !_extract_meeting_id_from_resourceru   r   uuiduuid4hexr   rH   
upsert_jobr   to_dict)r`   r   r   existing_jobresource_datar   jobs          r-   create_job_from_notificationz1TeamsMeetingPipeline.create_job_from_notification%  s   %DD\R

..xF33H=#$((8>Bd# ,0\5E5Ej5Q5WUW1XY 
+  	 &

 0 0" 567!,"2"2<"@"XDXY'z?'++J7W<;K;KJ;W$($6$1$5$5l$C&3&7&7&G&k<K[K[\jKk
  	

cjj#++-8
r,   c                   K   | j                  |      }|j                  t        v s|j                  t        dhz
  v r|S | j	                  |j
                         d {   S 7 w)Nr   )r   r   TERMINAL_PIPELINE_STATESACTIVE_PIPELINE_STATESrun_jobr   )r`   r   r   s      r-   run_notificationz%TeamsMeetingPipeline.run_notificationF  sV     //=::11SZZCY]g\hCh5hJ\\#**----s   AA#A!A#c           	       K   | j                  |      }|j                  }|t        d|j                   d      g }	 | j	                  |d      }t        |j                  t              r|j                  j                  d      ni }t        | j                  |j                  |j                  xs |j                  j                  d      |j                         d {   }||_        | j	                  ||j                               }d }| j                  j                   r{| j	                  |d	      }t#        | j                  |       d {   \  }}|rE|rC|j%                  |       t'        |j)                               | j                  j*                  k  rd }|s| j                  j,                  rt/        d
|j                   d      | j                  j0                  st3        d|j                   d      | j	                  |d      }t5        | j                  |       d {   }	|	st/        d|j                   d      |	d   }
|j%                  |
       | j7                  |||
       d {   }| j	                  |d      }n| j	                  |d      }|j                  d      xs |j                  xs i j                  d      }t9        | j                  ||       d {   }||j%                  |       | j	                  |d      }| j;                  ||xs d|       d {   }t        |t<              r|nt=        j>                  |      }||_         | j	                  ||j                               }| jC                  ||       d {    | j	                  |d      }|S 7 7 l7 7 K7 7 7 )# t.        $ r,}| j	                  |dtE        |      dd      }|cY d }~S d }~wtF        $ r?}| j	                  |dtE        |      tI        |      jJ                  d       }|cY d }~S d }~ww xY ww)!NzJob z has no meeting_ref.r    r   r   r   )r   r   r   )r   r"   z#Transcript unavailable for meeting .z@No transcript available and transcription fallback disabled for r#   z"Recording unavailable for meeting r   recording_stt_fallback)selected_artifact_strategytranscript_firstr   r   )r   r   rY   )resolved_meetingtranscript_text	artifacts)summary_payloadr   r   T)message	retryable)r   
error_infor   )r  r   )&_coerce_jobr   r%   r   _persist_jobr   r   rH   rI   r   r   r   r   r   r   r   r7   r   r   lenr]   r?   r8   r/   r9   r3   r   _transcribe_recordingr   r   r   rM   r  _write_sinksru   	Exceptionr   r'   )r`   	job_or_idr   r   r   r   r   r   transcript_artifact
recordings	recordingr   call_record	generatedr  excs                   r-   r   zTeamsMeetingPipeline.run_jobL  s^    y)oo$tCJJ<7K%LMM+-	U	##C0C#DCGQR]RfRfhlGm;//33NCsuL%>!!&11(55a9M9M9Q9QR`9a%//	&   /CO##C5E5M5M5O#PC*.O{{//''4I'J=\%%'7> 84#_ '?$$%89?0023dkk6V6VV*.";;225=>N>Y>Y=ZZ[\  {{99</::;1>  ''4K'L#;D<M<MO_#``
!5<=M=X=X<YYZ[  'qM	  +(,(B(B3HXZc(d"d''H`'a''HZ'[)--n=s+BVBVB\Z\AaAabrAsN ?!! -! K
 &  -##C#>C"//!1 / 52# 0  I i)CD /99)D 
 #2C##C9P9P9R#SC##C999##C#<CJI 8& a #e : + 	##('*3xdC $ C
 J 	##'*3xc9K9KL $ C
 J	s   ;Q	B!O N9 A0O N<CO +N?,AO 7O8A8O 0O1AO 6O7A(O O	 O 8Q	9O <O ?O O O O 	O 	Q!O;5Q6Q	;Q4Q;Q<Q	QQ	c                    t        |t              r|S | j                  j                  t	        |            }|st        d|       t        j                  |      S )NzUnknown Teams pipeline job: )r   r   r   get_jobru   r%   rM   )r`   r  rK   s      r-   r  z TeamsMeetingPipeline._coerce_job  sR    i!89**$$S^4$'CI;%OPP&0099r,   c                    | j                   j                         j                         D ]K  }t        |t              st        |j                  d      xs d      |k7  r6t        j                  |      c S  y )Nr   rY   )	r   	list_jobsvaluesr   rH   ru   rI   r   rM   )r`   r   rK   s      r-   r   z,TeamsMeetingPipeline._find_job_by_dedupe_key  sh    zz++-446 	>Ggt,7;;|,23zA*44W==	> r,   c                    |j                         }|j                  |       | j                  j                  |j                  |      }t        j                  |      S r   )r   updater   r   r   r   rM   )r`   r   updatesrK   storeds        r-   r  z!TeamsMeetingPipeline._persist_job  sD    ++-w&&szz7;&0088r,   c                  K   | j                   j                  xs t               dz  dz  }|j                  dd       t	        j
                  t        |      d      5 }|j                   d}|j                  xs |}t        |      j                  }|dv r|}t        |      |z  }	t        | j                  |||	       d {    | j                  |	       d {   }
| j                  |d	
      }t        j                   | j"                  t        |
      | j                   j$                         d {   }|j'                  d      s't)        t        |j'                  d      xs d            t        |j'                  d      xs d      j+                         }|st)        d      |cd d d        S 7 7 7 # 1 sw Y   y xY ww)Ntmpteams_pipelineT)parentsexist_okzteams-recording-)dirprefixz.mp4)rY   r   z..r!   r   successerrorzUnknown STT failure
transcriptrY   z!STT returned an empty transcript.)r   r@   r   mkdirtempfileTemporaryDirectoryru   artifact_iddisplay_namer   namer   r   _prepare_audio_pathr  asyncio	to_threadr   r;   rI   r/   r]   )r`   r   r   r  	temp_rootr@   fallback_nameraw_namerecording_namerecording_path
audio_pathresultr$  s                r-   r  z*TeamsMeetingPipeline._transcribe_recording  s     KK''YO,=,EHX,X	t4((S^DVW 	[b  )445T:M -->H!(^00N0!.!']^;N-!!	    $77GGJ##C0D#EC",,T-?-?ZRVR]R]RgRghhF::i(1#fjj6I6bMb2cddVZZ5;<BBDJ12UVV7	 	 Hh+	 	sW   AGA$F;F5F;F7AF;4F95A6F;+
G5F;7F;9F;;G Gc           	     f  K   |j                   j                         dv r|S | j                  j                  s|S t	        j
                  d      }|st        d      |j                  d      }t        j                  |ddt        |      t        |      t        j                  j                  t        j                  j                         d {   }|j                          d {   \  }}|j                  dk7  r/|j                  d	d
      j!                         }t        d|       |S 7 _7 Iw)N>   .aac.m4a.mp3.ogg.flac.webm.wavffmpegzRRecording fallback requires ffmpeg for audio extraction, but ffmpeg was not found.r<  z-yz-i)stdoutstderrr   zutf-8replace)errorsz ffmpeg audio extraction failed: )suffixlowerr   r<   shutilwhichr/   with_suffixr,  create_subprocess_execru   
subprocessPIPEcommunicate
returncodedecoder]   )r`   r2  r=  r3  proc_stdoutr?  details           r-   r+  z(TeamsMeetingPipeline._prepare_audio_path  s      &&(,ff!!{{//!!h'-d  $//7
33
O%%**%%**
 
 !% 0 0 22??a]]79]=CCEF-0PQWPX.YZZ
 3s%   CD1D-D1%D/&AD1/D1c          
       K   t        |||      }	 t        ddddd|dgdd       d {   }t        |      }t        |      }t        |      }	t        d#i d
|dt        |j                  j                  d      xs d|j                         d|j                  j                  d      d|j                  j                  d      dt        |      d|d|j                  d      dt        |j                  d      xs g       dt        |j                  d      xs g       dt        |j                  d      xs g       d|	d|d|j                  d      d|j                  d      d| j                   j"                  xs i j                  d      d| j                   j$                  xs i j                  d      d | j                   j&                  xs i j                  d!      xs) | j                   j&                  xs i j                  d"      S 7 # t        $ r,}t
        j                  d	|       t        |      }Y d }~	d }~ww xY ww)$NcallsystemzYou summarize meeting transcripts. Return only valid JSON with keys: summary, key_decisions, action_items, risks, confidence, confidence_notes.)roler   userg?i  )taskmessagestemperature
max_tokenszCTeams pipeline LLM summary unavailable, using heuristic summary: %sr   r   subjectr   
start_timestartDateTimeend_timeendDateTimeparticipantsr   r   r   r   r   call_metricssource_artifacts
confidenceconfidence_notesnotion_targetrd   linear_targetr   teams_target
channel_idchat_idr+   )_build_summary_promptr
   r   _parse_summary_jsonr
  loggerinfo_heuristic_summary_collect_call_metricsr   ru   r   rI   r   _collect_participantslistr   rA   rB   rC   )
r`   r   r   r   promptr   r   parsedr  metricss
             r-   r   z.TeamsMeetingPipeline._generate_summary_payload  st     ''7)T	9+ !)i $7	   H 38<G(1F
 (	2) 
(
&//33I>jHM]MhMhLiBjk
 (0044_E
 &..22=A	

 //?@
 ,
 JJy)
 vzz/:@bA
 fjj8>B?
 vzz'*0b1
 !
 '
 zz,/
 $ZZ(:;
  ;;--388G
   ;;--388C!
$ ++1r66|D EKK..4"99)D'
 	
-"  	9KK]_bc'8F	9s?   IH HH GIH 	I(!I	IIIc                  K   | j                   j                  r| j                   j                  j                  d      r| j                  r| j	                  |d      }d|j
                  j                   }| j                  j                  |      }| j                  j                  || j                   j                  |       d {   }| j                  j                  ||       | j                   j                  r| j                   j                  j                  d      r| j                  r| j	                  |d      }d|j
                  j                   }| j                  j                  |      }| j                  j                  || j                   j                  |       d {   }| j                  j                  ||       | j                   j                  r| j                   j                  j                  d      r| j                  r| j	                  |d      }d|j
                  j                   }| j                  j                  |      }t        | j                  d	      r:| j                  j                  || j                   j                  |       d {   }n/| j                  || j                   j                  |       d {   }| j                  j                  ||       y y y y 7 27 R7 Z7 ,w)
Nenabledr   r   znotion:r   zlinear:r   zteams:r   )r   rA   rI   r   r  r   r   r   get_sink_recordr   upsert_sink_recordrB   r   rC   r   hasattr)r`   r   rK   sink_keyexistingr4  s         r-   r	  z!TeamsMeetingPipeline._write_sinks7  s^    ;;$++"4"4"8"8"CHZHZ##C0@#AC !4!4!?!? @AHzz11(;H--;;GT[[EWEWYabbFJJ))(F;;;$++"4"4"8"8"CHZHZ##C0@#AC !4!4!?!? @AHzz11(;H--;;GT[[EWEWYabbFJJ))(F;;;%%$++*D*D*H*H*SX\XiXi##C#@C 3 3 > >?@Hzz11(;Ht((/:#00>>wHbHbdlmm#00$++:T:TV^__JJ))(F; Yj*S% c c n_sJ   CLK7C"L(K:)C9L"K=#/LK?%L:L=L?L)r   r   r   r   r   z+TeamsPipelineConfig | dict[str, Any] | Noner   TranscribeFnr   zOptional[SummarizeFn]r   zOptional[NotionWriter]r   zOptional[LinearWriter]r   zOptional[SinkFn]rO   r   )r   r   rO   r   )r  zTeamsMeetingPipelineJob | strrO   r   )r   ru   rO   zTeamsMeetingPipelineJob | None)r   r   r  r   rO   r   )r   r   r   r   r  r   rO   ru   )r2  r   rO   r   )r   r   r   ru   r   list[MeetingArtifact]rO   r   )r   r   rK   r   rO   r   )r'   r(   r)   r*   r   ra   r   r   r   r  r   r  r  r+  r   r	  r+   r,   r-   r   r     s    O ?C&6.20404)-) ) "	)
 <) $) ,) .) .) ') 
)*B.]~:9#$# %# #	#
 
#J44
 *4
 	4

 )4
 
$4
l<r,   r   c                    i }| D ]I  }|j                   dk(  s|j                  t        |j                  j	                  d      xs i              K t        |       |d<   |S )Nr  rr  artifact_count)artifact_typer  rH   r   rI   r  )r   rr  artifacts      r-   rm  rm  Q  sc     G I!!]2NN4 1 1 5 5i @ FBGHI !$IGNr,   c                f   | j                   j                  d      xs g }g }t        |t              r|D ]z  }t        |t              s|j                  d      xs7 |j                  d      xs i j                  d      xs i j                  d      }|sa|j                  t        |             | |S )Nr^  displayNameidentityrT  )r   rI   r   ro  rH   r   ru   )r   r^  r4  r   r*  s        r-   rn  rn  Z  s    ''++N;ArLF,%  	-D$%xx.wTXXj5I5OR4T4TU[4\4b`b3g3ghu3vMM#d),		-
 Mr,   c                    | sy | j                  d      D cg c]  }|s|	 }}|sy d|v r*|j                  d      }|dz   t        |      k  r||dz      S |d   S c c}w )N/onlineMeetings   )splitindexr  )r   partpartsr  s       r-   r   r   f  sq    &nnS1:dTT:E:5 ,-19s5z!##9 ;s
   AAc           
     (   |D cg c]/  }d|j                    d|j                   d|j                  xs d 1 }}d| j                   d| j                  j                  d      xs d dt        d	      j                  |      xs d
 d|d d  S c c}w )Nr   :rY   zMeeting ID: z
Title: rY  Unknownz
Artifacts:

   z- nonez

Transcript:
iPF  )r~  r(  r)  r   r   rI   chrr   )r   r   r   r  artifact_liness        r-   rh  rh  s  s    
 zC  Dmu8112!H4H4H3I8K`K`KfdfJgh  DN  D
{--. /&&**95BC D2w||N3?x@ A6E"
#		% Ds   4Bc           
        | xs dj                         }|st        d      S |j                  d      }|j                  d      }|dk\  r||kD  r|||dz    }t	        j
                  |      }t        |j                  d      xs d      j                         |j                  dg       D cg c]5  }t        |      j                         st        |      j                         7 c}|j                  dg       D cg c]5  }t        |      j                         st        |      j                         7 c}|j                  d	g       D cg c]5  }t        |      j                         st        |      j                         7 c}t        |j                  d
      xs d      j                         t        |j                  d      xs d      j                         dS c c}w c c}w c c}w )NrY   {}r   r  r   r   r   r   ra  mediumrb  r   r   r   r   ra  rb  )r]   rl  findrfindrp   loadsru   rI   )r   r   startendrK   r   s         r-   ri  ri    sx   Mr  "D!"%%IIcNE
**S/CzcEkEC!G$jjGw{{9-34::<8?OUW8Xn\_`d\e\k\k\m#d)//+n7>{{>SU7VltZ]^bZcZiZiZkT*l07GR0H^CPTIOOL]#d)//#^'++l3?x@FFH,> ? E2FLLN nl^s$   *G	G:G$G$
G)
)G)
c                r   | j                         D cg c]$  }|j                         s|j                  d      & }}dj                  |d d       d d xs d}|D cg c]$  }|j                         j	                  d      s#|& c}d d }|D cg c])  }d|j                         v sd	|j                         v s(|+ c}d d
 }|D cg c])  }d|j                         v sd|j                         v s(|+ c}d d
 }t        | j                               dk  rdnd}|||||ddS c c}w c c}w c c}w c c}w )Nz -*	    i  z=Transcript unavailable or too sparse for a confident summary.)zaction:ztodo:z
next step:z
follow up:   riskblocker   decidedecisioni,  lowr  zPGenerated with heuristic fallback because no LLM summary response was available.r  )
splitlinesr]   r   rC  
startswithr  )r   linelinesr   r   r   	decisionsra  s           r-   rl  rl    s;   -<-G-G-IZTTZZ\TZZ ZEZhhuRay!%4(k,kG$**,"9"9:j"kq
L $[dv'=djjlAZT[\^]^_E"'b$8tzz|+CzUYU_U_UaGabcedefIo3356<(J"$ n  [ \bs.   D%D%$D*D*)D/:D/)D42D4c                    d| j                   xs d| j                  j                    dd| j                  xs dddg| j                  D cg c]  }d| 	 c}xs dgdd	| j
                  D cg c]  }d| 	 c}xs dgdd
| j                  D cg c]  }d| 	 c}xs dgdd| j                  xs d | j                  xs d}dj                  |      j                         S c c}w c c}w c c}w )Nz# r   rY   z
## SummaryzNo summary available.z## Key Decisionsr   z- Nonez## Action Itemsz## RiskszConfidence: unknownr   )r   r   r   r   r   r   r   ra  rb  r   r]   )rK   r   r  s      r-   r   r     sM   
W]]I)<)<)G)G(HIJK
22
 $+#8#8
94Rv;
9
GhZ 	 	 $+#7#7
84Rv;
8
FXJ 	 	 $+==
14Rv;
1
?hZ 	 w))6Y78  	  &B!E$ 99U!!## : 9 2s   C12C6C;)r   r{  rO   r   )r   r   rO   z	list[str])r   ru   rO   r:   )r   r   r   ru   r   r{  rO   ru   )r   ru   rO   r   )r   ru   rO   r   )rK   r   rO   ru   )Br*   
__future__r   r,  rp   loggingr[   rD  r&  r   dataclassesr   pathlibr   typingr   r   r   r	   rw   agent.auxiliary_clientr
   r   hermes_constantsr   plugins.teams_pipeline.meetingsr   r   r   r   r   plugins.teams_pipeline.modelsr   r   r   r   plugins.teams_pipeline.storer   tools.transcription_toolsr   	getLoggerr'   rj  r   r   RuntimeErrorr%   r/   r1   r3   ru   rH   rz  SummarizeFnSinkFnr5   rS   r   r   rm  rn  r   rh  ri  rl  r   r+   r,   r-   <module>r     s   C "    	    !  5 5  O ,   < 6			8	$E 
 : :<"4 <,/ ,?)D ? hsm,d38n<=sId38n7Q&QRRS	c3h$sCx.1IJd38n
 
 
 
<^ ^B>i >iBA< A<H
	
  % 		&&$r,   