
    /cj                     ,   d 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ZddlZ ej        ej        j                   ddlmZmZmZ ddlmZ 	 ddlZn# e$ r dZY nw xY wdadadadadadadadada da!da"d Z# G d de
          Z$d	 Z%dS )
z
HTTP REST API handler for the Qwen Pipeline.

Serves static files + REST APIs for profiles, conversations,
recordings, ACRS proxy, TTS test, translation, and tool generation.
    N)SimpleHTTPRequestHandler)QwenTtsRealtimeQwenTtsRealtimeCallbackAudioFormat)OpenAIc                 2    | a |a|a|a|a|a|a|a|a|	a	|
a
dS )zBInitialize module-level references. Called once at server startup.N)HTTP_DIRRECORDINGS_DIRPROFILES_COLLECTIONCONVERSATIONS_COLLECTIONAPI_KEYLLM_BASE	LLM_MODEL	TTS_MODELTTS_VC_MODEL
LANG_NAMES_cloned_voices_ref)http_dirrecordings_dirprofiles_collectionconversations_collectionapi_keyllm_base	llm_model	tts_modeltts_vc_model
lang_namescloned_voices_refs              I/home/m1-ai/DEPLOYMENTS/AI-PHONE/ZACK-UPDATE/fixing_leaked/http_routes.pyinit_http_routesr    /   sD     H#N-7GHIILJ*    c                        e Zd ZdZ fdZ fdZ fdZd Zd ZddZ	d	 Z
d
 Zd Zd Zd Zd Zed             Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Z xZ S )PipelineHTTPHandlerz<Serves static files + REST API for ChromaDB profile storage.c                 H     t                      j        |dt          i| d S )N	directory)super__init__r	   )selfargskwargs	__class__s      r   r'   zPipelineHTTPHandler.__init__F   s*    $=(=f=====r!   c                 t    | j                             d          r t                      j        |g|R   d S d S )Nz/api/)path
startswithr&   log_message)r(   formatr)   r+   s      r   r/   zPipelineHTTPHandler.log_messageJ   sJ    9(( 	/EGG.......	/ 	/r!   c                    t           j                            | j                  }|j        dk    r|                                 S |j        dk    r|                                 S |j                            d          rNt           j                            |j        t          d          d                    }| 	                    |          S |j                            d          rNt           j                            |j        t          d          d                    }| 
                    |          S |j        dk    r|                                 S |j        dk    r|                                 S |j                            d          rNt           j                            |j        t          d          d                    }|                     |          S t                                                      S )N/api/profilesz/api/conversations/api/conversations//api/recordings/z/api/config-varsz/api/audio-timingz/api/audio-timing/)urllibparseurlparser-   _list_profiles_list_conversationsr.   unquotelen_get_conversation_get_recording_get_config_vars_audio_timing_list_audio_timing_seriesr&   do_GET)r(   parsedcidr+   s      r   rA   zPipelineHTTPHandler.do_GETN   s   &&ty11;/))&&(((;...++---;!!"788 	/,&&v{37L3M3M3N3N'OPPC))#...;!!"455 	,,&&v{37I3J3J3K3K'LMMC&&s+++;,,,((***;---**,,,;!!"677 	2,&&v{37K3L3L3M3M'NOOC,,S111ww~~r!   c                    t           j                            | j                  }|j        dk    r|                                 S |j        dk    r|                                 S |j        dk    r|                                 S |j        dk    r|                                 S |j        dk    r|                                 S |j        dk    r| 	                                S |j        dk    r| 
                                S |j        dk    r|                                 S |j        d	k    r|                                 S |j        d
k    r|                                 S |j                            d          rNt           j                            |j        t!          d          d                    }|                     |          S |                     d           d S )Nr2   z/api/acrs/syncz/api/acrs/createz/api/tts-testz/api/translatez/api/tools/generatez/api/tools/generate-handlerz/api/tools/save-handlerz/api/tools/check-modelz/api/prompt/generater4     )r5   r6   r7   r-   _save_profile
_acrs_sync_acrs_create	_tts_test
_translate_generate_tool_generate_handler_save_handler_check_model_generate_promptr.   r:   r;   _save_recording
send_error)r(   rB   rC   s      r   do_POSTzPipelineHTTPHandler.do_POSTc   s   &&ty11;/))%%''';***??$$$;,,,$$&&&;/))>>###;***??$$$;///&&(((;777))+++;333%%''';222$$&&&;000((***;!!"455 	-,&&v{37I3J3J3K3K'LMMC'',,,r!   c                    t           j                            | j                  }|j                            d          rNt           j                            |j        t          d          d                    }|                     |          S |j                            d          rNt           j                            |j        t          d          d                    }|                     |          S | 	                    d           d S )Nz/api/profiles/r3   rE   )
r5   r6   r7   r-   r.   r:   r;   _delete_profile_delete_conversationrQ   )r(   rB   namerC   s       r   	do_DELETEzPipelineHTTPHandler.do_DELETE~   s    &&ty11;!!"233 	.<''C8H4I4I4J4J(KLLD''---;!!"788 	2,&&v{37L3M3M3N3N'OPPC,,S111r!      c                 L   t          j        |                              d          }|                     |           |                     dd           |                     dt          |                     |                                  | j                            |           d S )Nutf-8Content-Typeapplication/jsonContent-Length)	jsondumpsencodesend_responsesend_headerr;   end_headerswfilewrite)r(   datastatusbodys       r   _json_responsez"PipelineHTTPHandler._json_response   s    z$&&w//6""");<<<)3t99555
r!   c                    t           s|                     ddid          S 	 t                                           }i }t          |d                   D ]E\  }}	 t	          j        |d         |                   ||<   *# t          j        t          f$ r Y Bw xY w|                     |           d S # t          $ r0}|                     dt          |          id           Y d }~d S d }~ww xY w)NerrorChromaDB not available  ids	documents  )
r   ri   get	enumerater^   loadsJSONDecodeError
IndexError	Exceptionstr)r(   resultprofilesipides         r   r8   z"PipelineHTTPHandler._list_profiles   s   " 	Q&&1I'JCPPP
	8(,,..FH#F5M22  3$(Jvk/B1/E$F$FHSMM,j9   D))))) 	8 	8 	8#a&& 13777777777	8s;   5B. #A;:B. ;BB. BB. .
C(8%C##C(c                 d   t           s|                     ddid          S 	 t          | j                            dd                    }t          j        | j                            |                    }|d         }|d         }t           	                    |gt          j
        |          gdgg	           t          d
|            |                     ddi           d S # t          $ rB}t          d|            |                     dt          |          id           Y d }~d S d }~ww xY w)Nrk   rl   rm   r]   r   rV   rf   g        )rn   ro   
embeddingsz[Profiles] Saved: okTz[Profiles] Save error: rp   )r   ri   intheadersrq   r^   rs   rfilereadupsertr_   printrv   rw   )r(   lengthrh   rV   rf   r|   s         r   rF   z!PipelineHTTPHandler._save_profile   sT   " 	Q&&1I'JCPPP	8))*:A>>??F:djoof5566D<D<D&&F:d++, E7 '   
 -t--...t----- 	8 	8 	8/A//000#a&& 13777777777	8s   C C# #
D/-7D**D/c                 n   t           s|                     ddid          S 	 t                               |g           t          d|            |                     ddi           d S # t          $ rB}t          d|            |                     dt          |          id	           Y d }~d S d }~ww xY w)
Nrk   rl   rm   rn   z[Profiles] Deleted: r   Tz[Profiles] Delete error: rp   )r   ri   deleter   rv   rw   )r(   rV   r|   s      r   rT   z#PipelineHTTPHandler._delete_profile   s    " 	Q&&1I'JCPPP	8&&D6&222///000t----- 	8 	8 	81a11222#a&& 13777777777	8s   AA( (
B427B//B4c                    t           s|                     ddid          S 	 t                                           }g }t          |d                   D ]\  }}	 t	          j        |d         |                   }|                     |          }|                    dd          }|                    d          }d }	t          |t                    r,|                    d	          |                    d
d          d}	|
                    ||                    dd          |                    dd          |                    dd          |                    dg           |                    dd          t          j                            |          t          j                            |          |                    d          |	d
           }# t          j        t          f$ r Y w xY w|                    d d           |                     |           d S # t"          $ r0}
|                     dt%          |
          id           Y d }
~
d S d }
~
ww xY w)Nrk   rl   rm   rn   ro   .webm_caller.wavfaithfulnessrg   flagged_countr   )rg   r   profile agent_aagent_btransfer_agentsmessage_countcost_usd)
idr   r   r   r   r   has_recordinghas_caller_recordingr   r   c                     | d         S )Nr    )cs    r   <lambda>z9PipelineHTTPHandler._list_conversations.<locals>.<lambda>   s
    QtW r!   T)keyreverserp   )r   ri   rq   rr   r^   rs   _recording_pathreplace
isinstancedictappendosr-   isfilert   ru   sortrv   rw   )r(   rx   conversationsrz   rC   docrec_filecaller_file_fa_fa_summaryr|   s              r   r9   z'PipelineHTTPHandler._list_conversations   sd   ' 	Q&&1I'JCPPP 	8-1133FM#F5M22  3*VK%8%;<<C#33C88H"*"2"27M"J"JK''.11C"&K!#t,, &)ggh&7&7-0WW_a-H-H' ' "((!#&779b#9#9#&779b#9#9#&779b#9#9+.773Db+I+I),!)D)D)+)A)A02{0K0K$'GGJ$7$7(3* *     ,j9   D#4#4dCCC..... 	8 	8 	8#a&& 13777777777	8s<   6H E4GH G($H 'G((0H 
I$%IIc                    t           s|                     ddid          S 	 t                               |g          }|d         r7t          j        |d         d                   }|                     |           d S |                     ddid	           d S # t
          $ r0}|                     dt          |          id
           Y d }~d S d }~ww xY w)Nrk   rl   rm   r   rn   ro   r   z	Not foundrE   rp   )r   ri   rq   r^   rs   rv   rw   )r(   rC   rx   r   r|   s        r   r<   z%PipelineHTTPHandler._get_conversation   s    ' 	Q&&1I'JCPPP	8-11se1<<Fe} Aj!4Q!788##C(((((##Wk$:C@@@@@ 	8 	8 	8#a&& 13777777777	8s   AB <B 
C %CCc                    t           s|                     ddid          S 	 t                               |g           |                     |          }|                    dd          }||fD ]5}t
          j                            |          rt          j        |           6|                     ddi           d S # t          $ r0}|                     dt          |          id	           Y d }~d S d }~ww xY w)
Nrk   rl   rm   r   r   r   r   Trp   )r   ri   r   r   r   r   r-   r   removerv   rw   )r(   rC   r   r   fr|   s         r   rU   z(PipelineHTTPHandler._delete_conversation   s   ' 	Q&&1I'JCPPP
	8$+++666++C00H"**7MBBK, ! !7>>!$$ !IaLLLt----- 	8 	8 	8#a&& 13777777777	8s   BB; ;
C5%C00C5c                 ~    t          j        dd|           }t          j                            t
          |dz             S )z,Return safe filesystem path for a recording.z[^\w\-]_r   )resubr   r-   joinr
   )rC   safes     r   r   z#PipelineHTTPHandler._recording_path   s1     vj#s++w||ND7N;;;r!   c                    	 t          | j                            dd                    }|dk    r|                     ddid          S | j                            |          }|                     |          }t          |d          5 }|                    |           ddd           n# 1 swxY w Y   t          dt          j                            |           d	t          |           d
           |                     ddi           dS # t          $ r0}|                     dt          |          id           Y d}~dS d}~ww xY w)z1Save uploaded audio recording for a conversation.r]   r   rk   zNo data  wbNz[Recording] Saved:  (z bytes)r   Trp   )r   r   rq   ri   r   r   r   openre   r   r   r-   basenamer;   rv   rw   )r(   rC   r   rf   filepathr   r|   s          r   rP   z#PipelineHTTPHandler._save_recording  s   	8))*:A>>??F{{**GY+?EEE:??6**D++C00Hh%%               X(8(8(B(BXXc$iiXXXYYYt----- 	8 	8 	8#a&& 13777777777	8sC   AD ?D B)D )B--D 0B-1AD 
E%EEc                    |                     d          rD|dt          d                    }|                     |                              dd          }d}n|                     |          }d}t          j                            |          s|                     d          S 	 t          j                            |          }t          |d          5 }|
                                }ddd           n# 1 swxY w Y   |                     d	           |                     d
|           |                     dt          |                     |                     dd| d           |                                  | j                            |           dS # t           $ r0}|                     dt%          |          id           Y d}~dS d}~ww xY w)z6Serve a recording file (browser .webm or caller .wav)._callerNr   r   z	audio/wavz
audio/webmrE   rbrX   r[   r]   zContent-Dispositionzattachment; filename=""rk   rp   )endswithr;   r   r   r   r-   r   rQ   r   r   r   ra   rb   rc   rd   re   rv   ri   rw   )	r(   rC   real_cidr   content_typefilenamer   rf   r|   s	            r   r=   z"PipelineHTTPHandler._get_recording  s   <<	"" 	(+S^^O+,H++H55==g}UUH&LL ++C00H'Lw~~h'' 	(??3'''	8w''11Hh%%  vvxx                             s###^\:::-s4yy9992AhAAAC C CJT""""" 	8 	8 	8#a&& 13777777777	8s=   &/F C6*F 6C::F =C:>BF 
G#%GGc                     ddl }t          |di           }t          dt          |                                                      |                     g d|d           dS )z;Return last-seen config vars per profile for the dashboard.r   N_LAST_CONFIG_VARSu7   [ConfigVars] GET /api/config-vars — profiles stored: )CURRENTTIMECURRENTDATECALLERPHONE	AGENTDATA
EXTENSIONSOUTGOING)builtins
lastConfig)__main__getattrr   listkeysri   )r(   r   r   s      r   r>   z$PipelineHTTPHandler._get_config_vars2  s    #H.A2FFhM^McMcMeMeHfHfhhiiilll+
 
 	 	 	 	 	r!   c                    t           s|                     ddid          S 	 |                     t          j                               dS # t          $ r0}|                     dt	          |          id           Y d}~dS d}~ww xY w)zFSummary of recorded calls: recv (from cloud) vs send (to bridge) gaps.rk   tracer unavailablerm   rp   N)audio_timing_traceri   	get_callsrv   rw   )r(   r|   s     r   r?   z&PipelineHTTPHandler._audio_timing_list>  s    ! 	M&&1E'FLLL	8 2 < > >????? 	8 	8 	8#a&& 13777777777	8s   &A	 	
B%A>>Bc                 F   t           s|                     ddid          S 	 t          j        |          }||                     ddid          S |                     |           dS # t          $ r0}|                     dt	          |          id           Y d}~dS d}~ww xY w)z%Full per-piece timeline for one call.rk   r   rm   Nz	not foundrE   rp   )r   ri   
get_seriesrv   rw   )r(   rC   rf   r|   s       r   r@   z(PipelineHTTPHandler._audio_timing_seriesG  s    ! 	M&&1E'FLLL	8%055D|**G[+A3GGG%%%%% 	8 	8 	8#a&& 13777777777	8s   -A& A& &
B 0%BB c                 2   	 t          | j                            dd                    }t          j        | j                            |                    }|                    dd          }|                    dd          }|r|s|                     ddid          S |                    d	d
          d         }|dd}i }dD ]}	 t          j        | d| |dd          }	|	j
        dk    r|	                                ng ||                    dd          <   Y# t          $ r g ||                    dd          <   Y ~w xY w|                     |           dS # t          $ r0}
|                     dt          |
          id           Y d}
~
dS d}
~
ww xY w)z5Proxy: fetch all ACRS entities and return to browser.r]   r   api_urlr   r   rk   zapi_url and api_key requiredr   /dispatches   r\   )	X-API-KEYAccept)departments
categoriestypeszsub-categoriesratings/
   F)r   timeoutverifyrX   -r   rp   N)r   r   rq   r^   rs   r   r   ri   rsplitrequestsstatus_coder   rv   rw   )r(   r   rh   r   r   baser   rx   entityrespr|   s              r   rG   zPipelineHTTPHandler._acrs_syncU  s   	8))*:A>>??F:djoof5566Dhhy"--Ghhy"--G [' [**G5S+TVYZZZ>>-33A6D$+7IJJGF] : ::#<4(:(:&(:(:GUW`efffDFJFVZ]F]F]tyy{{{ceF6>>#s3344  : : :79F6>>#s33444:''''' 	8 	8 	8#a&& 13777777777	8sC   BE 'E ADE #E?E EE 
F&%FFc                    	 t          | j                            dd                    }t          j        | j                            |                    }|                    dd          }|                    dd          }|                    dd          }|                    di           }|r|r|s|                     dd	id
          S |                    dd          d         }|dd}t          j
        | d| ||dd          }	i }
	 |	                                }
n!# t          $ r d|	j        dd         i}
Y nw xY w|	j        dv r|                     |
           dS |                     d|
i|	j                   dS # t          $ r0}|                     dt          |          id           Y d}~dS d}~ww xY w)z Proxy: create an entity in ACRS.r]   r   r   r   r   r   rf   rk   z!api_url, api_key, entity requiredr   r   r   r\   )r   r[   r   r   F)r^   r   r   r   rawNrp   )rX      )r   r   rq   r^   rs   r   r   ri   r   r   postrv   textr   rw   )r(   r   rh   r   r   entity_typerf   r   r   r   	resp_datar|   s               r   rH   z PipelineHTTPHandler._acrs_createk  s   	8))*:A>>??F:djoof5566Dhhy"--Ghhy"--G((8R00K88FB''D `' ` `**G5X+Y[^___>>-33A6D$+=OPPG=D!8!8;!8!8t)0"UL L LDI5 IIKK		 5 5 5"DIdsdO4			5:--##I.....##Wi$8$:JKKKKK 	8 	8 	8#a&& 13777777777	8sI   C	F AF D# "F #E>F  E!F $F 
F=%F88F=c                    	 t          | j                            dd                    }t          j        | j                            |                    }|                    dd                                          }|                    dd          }t          |                    dd                    }t          |                    d	d                    }t          |                    d
d                    }|s| 	                    ddid          S g t          j                     G fddt                    } |            }	t          }
t          D ]+}|d         |k    r|                    dt                    }
 n,t!          |
|	d          }|                                 |                    |t&          j        d|||           d}t+          dt-          |          |          D ]6}|                    ||||z                       t1          j        d           7|                                                     d           d}D ]}|t9          j        |          z  }t9          j        |                              d          }| 	                    d|i           d S # t@          $ rB}tC          d|            | 	                    dtE          |          id           Y d }~d S d }~ww xY w)!z,Synthesize text and return base64 PCM audio.r]   r   r   r   voiceEthanspeech_rateg      ?
pitch_ratevolume2   rk   ztext is requiredr   c                   ,    e Zd Zd ZfdZ fdZdS )8PipelineHTTPHandler._tts_test.<locals>.CollectorCallbackc                     d S Nr   )r(   s    r   on_openz@PipelineHTTPHandler._tts_test.<locals>.CollectorCallback.on_open  s      r!   c                 0                                      d S r   )set)r(   r)   
done_events     r   on_closezAPipelineHTTPHandler._tts_test.<locals>.CollectorCallback.on_close  s    :>>+;+;+;+;+;r!   c                     	 |                     dd          }|dk    r1|                     dd          }|r                    |           d S d S |dk    r                                 d S d S # t          $ r Y d S w xY w)Ntyper   zresponse.audio.deltadeltazsession.finished)rq   r   r  rv   )r(   responseetypeaudioaudio_chunksr  s       r   on_eventzAPipelineHTTPHandler._tts_test.<locals>.CollectorCallback.on_event  s    	 (VR 8 8 $:::$,LL"$=$=E$ ; , 3 3E : : : : :; ;"&888&NN,,,,, 98$   s   A	A. A. .
A<;A<N)__name__
__module____qualname__r  r  r  )r  r  s   r   CollectorCallbackr     sK        ''';;;;;
 
 
 
 
 
 
 
r!   r  r   target_modelz4wss://dashscope-intl.aliyuncs.com/api-ws/v1/realtime)modelcallbackurlserver_commit)r   response_formatmoder   r   r   P   gQ?   )r   r!   asciir  z[TTS Test] Error: rp   N)#r   r   rq   r^   rs   r   r   stripfloatri   	threadingEventr   r   r   r   r   connectupdate_sessionr   PCM_24000HZ_MONO_16BITranger;   append_texttimesleepfinishwaitbase64	b64decode	b64encodedecoderv   r   rw   )r(   r   rh   r   r   r   r   r   r  r  r   cvtts
chunk_sizerz   	all_audiochunkcombined_b64r|   r  r  s                      @@r   rI   zPipelineHTTPHandler._tts_test  s9   B	8))*:A>>??F:djoof5566D88FB''--//DHHWg..E < <==Ktxxc::;;J(B//00F O**G5G+H#NNNL"**J       $;    )(**H!I(  d8u$$ "~| D DIE % "(J  C KKMMM + B$'%     J1c$ii44 ! !Qq:~%5 6777
4    JJLLLOOBO''' I% 5 5V-e444		!+I66==gFFL, 788888 	8 	8 	8*q**+++#a&& 13777777777	8s   DJ2 FJ2 2
K><7K99K>c           
      x   	 t          | j                            dd                    }t          j        | j                            |                    }|                    dd                                          }|                    d          pd                                }|                    d          pd                                }|r|r|s|                     ddid	          S ||k    r|                     d
|i          S t          t                    }d|d<   |                    ||          }|                    ||          }d| d| d| }	t          t          t                    }
|
j        j                            t"          d|	dgdddi          }|j        d         j        j        pd                                }t+          |          dk    rL|d         dk    r|d         dk    s|d         dk    r(|d         dk    r|dd                                         }t-          d| d| dt+          |           d           |                     d
|i           d"S # t.          $ rB}t-          d |            |                     dt1          |          id!           Y d"}~d"S d"}~ww xY w)#z:Translate text from one language to another using the LLM.r]   r   r   r   source_langtarget_langrk   z'text, source_lang, target_lang requiredr   translationzChinese (Simplified)zhz;You are a professional translator. Translate the following z text into a~  .

Rules:
- Preserve the original formatting, line breaks, bullet points, and section headings exactly.
- Keep placeholders, variable names, code, URLs, and identifiers unchanged (e.g. {name}, $var, REFERENCE DATA, TRANSFER CAPABILITY).
- Translate only natural-language content.
- Output ONLY the translated text. No preamble, no explanations, no surrounding quotes.

Source text:
r   base_urluserrolecontent皙?enable_thinkingFr  messagestemperature
extra_body   r   'r   z[Translate] z -> r   z chars)z[Translate] Error: rp   N)r   r   rq   r^   rs   r   r   r  ri   r   r   r   r   r   chatcompletionscreater   choicesmessager=  r;   r   rv   rw   )r(   r   rh   r   sourcetargetr   src_nametgt_namepromptllmr	  r6  r|   s                 r   rJ   zPipelineHTTPHandler._translate  s   1	8))*:A>>??F:djoof5566D88FB''--//Dhh}--3::<<Fhh}--3::<<F Ov OV O**GH#O O O**M4+@AAAj))J5Jt!~~ff55H!~~ff55H
(
( 
((0
( 
( "&
( 
(  8<<<Cx+22#)f==>-u5	 3  H $+A.6>D"KKMMK;1$$Q3&&;r?c+A+AQ3&&;r?c+A+A)!B$/5577IIIVIIs4yyIIIJJJ <===== 	8 	8 	8+++,,,#a&& 13777777777	8s%   C+I- .I- E I- -
J977J44J9c                 n   d}	 t          | j                            dd                    }t          j        | j                            |                    }|                    dd                                          }|                    dd                                          pt          }|s| 	                    ddid          S d	| }t          t          t          
          }|j        j                            |d|dgdddi          }|j        d         j        j        pd                                }|                    d          r@t)          j        dd|          }t)          j        dd|          }|                                }t          j        |          }	t-          d|	                    dd           dt/          |	                    dg                      d| d           | 	                    |	           dS # t          j        $ rP}
t-          d|
 d|dd                     | 	                    ddt3          |
           id            Y d}
~
dS d}
~
wt4          $ rB}
t-          d!|
            | 	                    dt3          |
          id           Y d}
~
dS d}
~
ww xY w)"zGUse LLM to generate a structured tool definition from natural language.r   r]   r   descriptionr  rk   zdescription is requiredr   af  You are a tool definition generator for an OpenAI-compatible function calling system.

The user will describe an API tool in natural language. Your job is to extract structured information and return ONLY a JSON object (no markdown, no explanation, no code fences) with exactly these fields:

{
  "name": "snake_case_function_name",
  "description": "Clear description of what this tool does",
  "parameters": [
    {
      "name": "param_name",
      "type": "string",
      "description": "What this parameter is for",
      "required": true
    }
  ],
  "endpoint": "https://api.example.com/path",
  "headers": {}
}

Rules:
- name MUST be snake_case (lowercase, underscores only, no spaces)
- type must be one of: string, number, integer, boolean
- Extract the API endpoint URL if mentioned; leave as empty string if not mentioned
- Extract any custom headers if mentioned (e.g. Authorization); default to empty object
- Infer reasonable parameter names, types, and descriptions from context
- Mark parameters as required=true unless they are clearly optional
- Output ONLY the JSON object, nothing else

User description:
r8  r:  r;  r>  r?  Fr@  ```z^```(?:json)?\s*\n?
\n?```\s*$z[ToolGen] Generated: rV   ?r   
parametersz params, model=)z[ToolGen] JSON parse error: z
Raw: Nrp   zLLM returned invalid JSON: i  z[ToolGen] Error: )r   r   rq   r^   rs   r   r   r  r   ri   r   r   r   rG  rH  rI  rJ  rK  r=  r.   r   r   r   r;   rt   rw   rv   )r(   r   r   rh   rS  r  rP  rQ  r	  rx   r|   s              r   rK   z"PipelineHTTPHandler._generate_tool  s,   @	8))*:A>>??F:djoof5566D((="55;;==KHHWb))//11>YE ?**78#? ? ?44 '254 4 < 8<<<Cx+22#)f==>-u5	 3  H #A&.6<"CCEEC ~~e$$ "f3R==f]B44iikkZ__F Q&**VS*A*A Q Q&**\26677Q QHMQ Q Q R R R'''''# 	H 	H 	HFFF3tt9FFGGG@A@@A3H H H H H H H H H 	8 	8 	8)a))***#a&& 13777777777	8s,   CH 	E H J4AI%%J427J//J4c                 N   d}	 t          | j                            dd                    }t          j        | j                            |                    }|                    dd                                          }|                    dd                                          }|                    dg           }|                    dd                                          }|                    dd                                          pt          }|r|s| 	                    d	d
id          S d
                    d |D                       pd}	d| d| d| d|	 d| d}
t          t          t                    }|j        j                            |d|
dgdddi          }|j        d         j        j        pd                                }|                    d          r@t+          j        dd|          }t+          j        dd|          }|                                }t/          d| d | d!           | 	                    ||d"           d%S # t0          $ rB}t/          d#|            | 	                    d	t3          |          id$           Y d%}~d%S d%}~ww xY w)&z9Use LLM to generate a Python handler function for a tool.r   r]   r   	tool_namerS  rW  handler_descriptionr  rk   z.tool_name and handler_description are requiredr   
c           
   3      K   | ]=}d |d          d|                     dd           d|                     dd           V  >dS )	z  - rV   r   r  string): rS  r   N)rq   ).0ps     r   	<genexpr>z8PipelineHTTPHandler._generate_handler.<locals>.<genexpr>X  sp       $ $ [qyZZAEE&($;$;ZZmUW@X@XZZ$ $ $ $ $ $r!   z  (none)zYou are a Python code generator for a phone system's tool handler.

Generate a handler function that will be registered with @register_handler.

SIGNATURE (must be exactly this):
@register_handler('z')
def handle_an  (args, tool_def=None):

AVAILABLE (already imported, do NOT add import statements):
  - requests (for HTTP calls)
  - json (for JSON handling)
  - re (for regex)

HANDLER RULES:
  - args is a dict containing the tool parameters
  - Must return a string (the result sent back to the AI)
  - Use args.get('param_name', '') to safely get parameters
  - For API calls, use requests.post/get with timeout=15, verify=False
  - Handle errors with try/except and return error messages as strings
  - Do NOT use: import, os, subprocess, exec, eval, open, __import__, sys
  - Do NOT include any import statements

TOOL DESCRIPTION: z

PARAMETERS:
z

HANDLER LOGIC: z

Output ONLY the Python function code (with the @register_handler decorator line). No markdown code fences, no explanation, no imports.r8  r:  r;  r>  r?  Fr@  rT  z^```(?:python)?\s*\n?rU  z$[HandlerGen] Generated handler for: z (model=rX  )rZ  handler_codez[HandlerGen] Error: rp   N)r   r   rq   r^   rs   r   r   r  r   ri   r   r   r   r   rG  rH  rI  rJ  rK  r=  r.   r   r   r   rv   rw   )r(   r   r   rh   rZ  rS  rW  r[  r  params_textrP  rQ  r	  r|   s                 r   rL   z%PipelineHTTPHandler._generate_handlerH  s(   >	8))*:A>>??F:djoof5566Db117799I((="55;;==K,33J"&((+@""E"E"K"K"M"MHHWb))//11>YE V$7 V**NOQTV V V )) $ $#$ $ $     G '0G G (	G G" &1#G G$ !,%G G& #6'G G G 2 8<<<Cx+22#)f==>-u5	 3  H #A&.6<"CCEEC ~~e$$ "f5r3??f]B44iikkTTTETTTUUUi M MNNNNN 	8 	8 	8,,,---#a&& 13777777777	8s   D,I 1D%I 
J$"7JJ$c           	         	 t          | j                            dd                    }t          j        | j                            |                    }|                    dd                                          }|                    dg           }|                    dd                                          pd}|                    dd                                          pt          }|s|s| 	                    d	d
id          S d}|rg }|D ]}	|	                    di           }
|
                    dd          }|
                    dd          }|ry|dk    rs|
                    di                               di           }|r'd
                    |                                          nd}|                    d| d| d|            |rdd
                    |          z   }d}|rd| }d| d| | d}t          t          t                    }|j        j                            |d|dgdd d!i"          }|j        d         j        j        pd                                }|                    d#          r@t/          j        d$d|          }t/          j        d%d|          }|                                }t3          d&| d't5          |           d(| d)           | 	                    d*|i           d-S # t6          $ rB}t3          d+|            | 	                    d	t9          |          id,           Y d-}~d-S d-}~ww xY w).z9Use LLM to generate a system prompt for a transfer agent.r]   r   rS  r   tools
agent_namezTransfer Agentr  rk   z%Provide a description, tools, or bothr   functionrV   transfer_backrW  
propertiesz, nonez- (r_  z!

TOOLS AVAILABLE TO THIS AGENT:
r\  z

AGENT PURPOSE (from user):
zxYou are a system prompt writer for a phone call AI agent.

Generate a concise system prompt for a transfer agent named "zY". This agent handles live phone calls after being transferred from a main receptionist.
u  

RULES FOR THE GENERATED PROMPT:
- Write in second person ("You are...")
- Keep it concise but comprehensive (a few paragraphs max)
- Mention this is a live phone call — responses must be brief (2-3 sentences per turn)
- If tools are provided, explain WHEN to use each one (not the parameter details — the agent already has tool definitions)
- Include a transfer_back instruction: tell the agent to transfer back to the main receptionist if the caller's request is outside this agent's scope
- Do NOT include greetings or opening lines — those are handled separately
- Output ONLY the system prompt text, no markdown formatting, no code fences, no explanation
r8  r:  r;  g?r?  Fr@  rT  z^```(?:\w+)?\s*\n?rU  z"[PromptGen] Generated prompt for: r   z chars, model=rX  rP  z[PromptGen] Error: rp   N)r   r   rq   r^   rs   r   r   r  r   ri   r   r   r   r   r   r   rG  rH  rI  rJ  rK  r=  r.   r   r   r   r;   rv   rw   )r(   r   rh   rS  rf  rg  r  tools_context
tool_linestfnfn_namefn_descparamsparam_namesdesc_contextrP  rQ  r	  r   r|   s                        r   rO   z$PipelineHTTPHandler._generate_prompt  s   N	8))*:A>>??F:djoof5566D((="55;;==KHHWb))E,3399;;O?OJHHWb))//11>YE Mu M**EFM M M M 
 F FAz2..B ffVR00G ff]B77G F7o#=#=!#b!9!9!=!=lB!O!OBH&Tdii&>&>&>f"))DDD;DD7DDF F F >))J//0 "
 L PO+OO33 3  	3
 !3 3 3 . 8<<<Cx+22#)f==>-u5	 3  H #A&.6<"CCEEC ~~e$$ "f2B<<f]B44iikk 7z 7 7#hh7 7.37 7 7 8 8 8300000 	8 	8 	8+++,,,#a&& 13777777777	8s   DL 	G7L 
M7M		Mc                    	 t          | j                            dd                    }t          j        | j                            |                    }|                    dd                                          }ddl}|	                    |                    dd                                                    }|r|s| 
                    ddid	          S g d
}|D ]#}||v r| 
                    dd| id	          c S $	 t          |dd           n2# t          $ r%}| 
                    dd| id	          cY d}~S d}~ww xY wd| d|vr| 
                    dd| did	          S ddlm}	 t          j                            t          j                            t$                    d          }
|	                                                    d          }t+          |
|||           ddlm}m} i dddddddt           dt2          dt4          dt6          dt8          d t:          d!t<          d"t>          d#t@          d$tB          d%tD          d&tF          d'tH          d(tJ          tL          tN          tP          tR          tT          tV          tX          tZ          t\          t^          t`          tb          d)}|||td          t          tf          d*}ti          ||           tI          d+|            | 
                    d|d,           dS # tb          $ rB}tI          d-|            | 
                    dt5          |          id.           Y d}~dS d}~ww xY w)/z1Validate, save, and activate a generated handler.r]   r   rZ  r   Nrc  rk   z'tool_name and handler_code are requiredr   )zimport 
__import__zexec(zeval(zcompile(zopen(zos.zsys.
subprocessshutilzglobals(zlocals(zsetattr(zgetattr(zdelattr(__builtins__zForbidden pattern detected: z<generated>execzSyntax error: z@register_handler('z')z$Handler must use @register_handler(')datetimezgenerated_handlers.pyz%Y-%m-%d %H:%M:%S)register_handlerCUSTOM_HANDLERSTrueTFalseFNoner   r  rw   boolr   r   tupler  r;   r#  rr   r   r   min)maxabsroundsortedreversedzipmapfilter
ValueError	TypeErrorKeyErrorrv   )rz  r}  r~  r   r^   r   z*[HandlerGen] Saved and activated handler: )r   rZ  z[HandlerGen] Save error: rp   )5r   r   rq   r^   rs   r   r   r  textwrapdedentri   compileSyntaxErrorr|  r   r-   r   dirname__file__nowstrftime_replace_or_append_handlertool_handlersr}  r~  r  rw   r  r   r   r  r  r;   r#  rr   r   r   r  r  r  r  r  r  r  r  r  r  r  r  rv   r   r   r{  )r(   r   rh   rZ  r  rc  	forbiddenpatternr|   r|  gen_file	timestampr}  r~  safe_builtinsexec_nss                   r   rM   z!PipelineHTTPHandler._save_handler  sO   E	8))*:A>>??F:djoof5566Db117799IOOO#??488NB+G+GHHNNPPL OL O**GH#O O O  I % R Rl**.. "J"J"JKSR R R R R +
:mV<<<< : : :**2q223S: : : : : : : ::
 3Y222,FF**RYRRRSUXZ Z Z *)))))w||BGOOH$=$=?VWWH //0CDDI&xL)TTT HGGGGGGG%u.4ds#U,138>  %d -4U =B3 s	 $U	 -8	
 j
 +25 s $'sU h3&(y$9  M !.$4#2$ G w'''JyJJKKKt) D DEEEEE 	8 	8 	81a11222#a&& 13777777777	8s[   CL (L L D L 
E E :E;L  E&L ,F!L 
M7MMc                 ,   	 t          | j                            dd                    }t          j        | j                            |                    }|                    dd                                          }|s|                     ddid          S t          t          t                    }|j        j                            |d	d
dgddddi          }|j        d         j        j        pd                                                                }t'          d| d| d           |                     d| dd           dS # t(          $ r<}t'          d| d| d           |                     dd| d           Y d}~dS d}~ww xY w)z2Test if a model exists and can generate responses.r]   r   r  r   rk   zModel name is requiredr   r8  r:  zReply with only the word "ok".r;     r?  F)r  rA  rB  
max_tokensrC  z[ModelCheck] z: ok (reply=rX  Tz is available)r   rK  z
: failed (zModel not available: )r   rk   N)r   r   rq   r^   rs   r   r   r  ri   r   r   r   rG  rH  rI  rJ  rK  r=  lowerr   rv   )r(   r   rh   r  rQ  r	  replyr|   s           r   rN   z PipelineHTTPHandler._check_model&  s   	U))*:A>>??F:djoof5566DHHWb))//11E U**G5M+NPSTTT8<<<Cx+22#)6VWWX-u5 3  H %a(08>BEEGGMMOOE=%==U===>>>t58O8O8O P PQQQQQ 	U 	U 	U7%771777888u7Rq7R7R S STTTTTTTTT	Us   BE B3E 
F1FF)rX   )!r  r  r  __doc__r'   r/   rA   rR   rW   ri   r8   rF   rT   r9   r<   rU   staticmethodr   rP   r=   r>   r?   r@   rG   rH   rI   rJ   rK   rL   rO   rM   rN   __classcell__)r+   s   @r   r#   r#   C   s       FF> > > > >/ / / / /         *  6     8 8 88 8 8&	8 	8 	8#8 #8 #8J8 8 88 8 8 < < \<
8 8 88 8 8:  8 8 8
8 
8 
88 8 8,8 8 8:D8 D8 D8L38 38 38jC8 C8 C8JA8 A8 A8FP8 P8 P8dG8 G8 G8RU U U U U U Ur!   r#   c                    d| d}d| d| d| d}t           j                            |           rt          | dd	          5 }|                                }d
d
d
           n# 1 swxY w Y   ||v rQt          j        |          dz   }t          j        |d|t
          j                  }|	                                |z   }n|	                                |z   }t          | dd	          5 }|
                    |           d
d
d
           d
S # 1 swxY w Y   d
S d}	t          | dd	          5 }|
                    |	|z              d
d
d
           d
S # 1 swxY w Y   d
S )zKReplace existing handler for tool_name in generated_handlers.py, or append.z# --- Generated:  z

rl  z) ---
r\  rrZ   )encodingNz)\(.*?\) ---\n.*?(?=\n# --- Generated:|\Z)r   )flagswaG  """
Auto-generated tool handlers.
Managed by AI Tool Builder. Each handler below was generated by the LLM
and reviewed by the user before activation.
"""

import json
import re
import requests
from tool_handlers import register_handler

# Generated handlers below
# ============================================================
)r   r-   r   r   r   r   escaper   DOTALLrstripre   )
r   rZ  coder  marker	new_blockr   r=  r  headers
             r   r  r  ?  sC   ----F:v::	::$:::I	w~~h ((C'222 	affhhG	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 Wi''*VVGfWb'CCCGnn&&2GGnn&&2G(C'222 	aGGG	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	
# 	 (C'222 	(aGGFY&'''	( 	( 	( 	( 	( 	( 	( 	( 	( 	( 	( 	( 	( 	( 	( 	( 	( 	(s6   A%%A),A).DDD2EEE)&r  r^   r   r   r%  r  r)  urllib.parser5   http.serverr   r   urllib3disable_warnings
exceptionsInsecureRequestWarning!dashscope.audio.qwen_tts_realtimer   r   r   openair   r   rv   r	   r
   r   r   r   r   r   r   r   r   r   r    r#   r  r   r!   r   <module>r     s     				 				           0 0 0 0 0 0    +B C C C                  
   
		
 + + +(yU yU yU yU yU2 yU yU yUx"( "( "( "( "(s   A A'&A'