ó
    1¼„jR  ã                  ó¶   • S r SSKJr  SSKrSSKrSSKrSSKJr  SSK	J
r
Jr  SSKJr  SSKJr  SrS	rS
r\S\4         SS jjrSS jrSS jr\4SS jjrg)uL  Landing.AI ADE parse client.

`parse_document` submits one PDF or image through the async Parse Jobs API,
polls the job to completion, and returns the full parse response as a dict.
Polling is the only completion signal the platform offers; there is no
webhook. Results over the inline size limit arrive as a presigned URL that
expires shortly after the poll that returned it, so the download happens
immediately.

Two API generations are in play. The generally-available dpt-2 model line
rides the v1 jobs API; the preview dpt-3 line rides the v2 jobs API. The
model name picks the route.

`custom_prompts` passes per-chunk-type instruction to the v1 model line, keyed
by chunk type (`figure`, `text`, ...). It cannot change the shape of what comes
back â€” an instruction to emit a chart as an HTML table returns the same prose
description â€” so it is for content-level instruction only, and it is the
caller's to supply.

A parse that reports failed pages raises instead of returning: a silently
missing page in a financial document is a liability, so a partial parse
never looks like a success.
é    )ÚannotationsN)ÚPath)ÚAnyÚOptional)Úlogger)Úget_settingszdpt-2g      @g      œ@c                ó”  • [        5       n[        U5      (       a&  UR                  R                  nUR	                  XS9nO-UR                  nU(       a  SU0O0 nUR                  " SXS.UD6n[
        R                  " SUR                  U R                  U R                  5       R                  U5        [        XVR                  U5      $ )uW  Parse one local PDF or image through ADE; return the raw parse response.

`custom_prompts` reaches the v1 model line only; the v2 API takes no such
argument, so it is dropped for a dpt-3 model. `poll_seconds` sets how often
the job is polled â€” a single-page submission finishes in seconds and wants
a shorter interval than a whole document.
)ÚdocumentÚmodelÚcustom_promptsz3ADE parse job {} submitted: {} ({} bytes, model={})© )Úbuild_clientÚis_v2_modelÚv2Ú
parse_jobsÚcreater   ÚinfoÚjob_idÚnameÚstatÚst_sizeÚ_await_result)Úsourcer   r   Úpoll_secondsÚclientÚjobsÚjobÚextras           Ú</home/mande/repo/quber/src/quber/providers/landing/client.pyÚparse_documentr    ,   s§   € ô ‹^€FÜ�5×ÑØ�y‰y×#Ñ#ˆØ�k‰k 6ˆkÐ7‰à× Ñ ˆÞ6DÐ! >Ñ2È"ˆØ�kŠkÐ@ 6Ñ@¸%Ñ@ˆÜ
‡K‚KØ=Ø�
‰
Ø�‰Ø�‰‹×ÑØôô ˜Ÿz™z¨<Ó8Ð8ó    c                ó$   • U R                  S5      $ )z?True for the dpt-3 model line, which lives on the v2 parse API.zdpt-3)Ú
startswith)r   s    r   r   r   K   s   € à×Ñ˜GÓ$Ð$r!   c                 óz   • SSK Jn   [        5       R                  R                  nU(       d  [        S5      eU " US9$ )z?An authenticated SDK client, keyed from settings (ADE_API_KEY).r   )ÚLandingAIADEz=No Landing.AI key: set ADE_API_KEY in the environment or .env)Úapikey)Úlandingai_ader%   r   ÚlandingÚapi_keyÚRuntimeError)r%   Úkeys     r   r   r   P   s2   € å*ä
‹.×
 Ñ
 ×
(Ñ
(€CÞÜÐZÓ[Ð[Ù˜sÑ#Ð#r!   c                óT  • [         R                   " 5       nSn U R                  U5      nUR                  UR                  4nXd:w  aO  [        R
                  " SUUR                  UR                  =(       d    S[         R                   " 5       U-
  5        UnUR                  S;   a  OO[         R                   " 5       U-
  [        :”  a  [        SU S[        S S35      e[         R                  " U5        MÝ  UR                  S	:w  a?  [        US
S5      =(       d    [        USS5      n[        SU SUR                   SU 35      e[        USS5      =(       d    [        USS5      n[        USS5      =(       d%    [        USS5      =(       d    0 R                  S5      n	Ub%  [        R                  " UR                  5       5      n
OzU	(       ad  [        R
                  " SU5        [        R                  R                  U	5       n[        R                  " UR!                  5       5      n
SSS5        O[        SU S35      eW
R                  S5      =(       d    0 nUR                  S5      =(       d    / nU(       a  [        SU S35      eUR                  S5      nUc)  UR                  S5      =(       d    0 R                  S5      n[        R
                  " SUR                  S5      UUR                  S5      =(       d    UR                  S5      5        U
$ ! , (       d  f       Næ= f)z>Poll one parse job to completion and return its response dict.Nz5ADE job {}: status={} progress={:.0%} elapsed={:.0f}sg        )Ú	completedÚfailedÚ	cancelledzADE job z timed out after z.0fÚsr-   Úfailure_reasonÚerrorÚ z: ÚdataÚresultÚ
output_urlÚrawzAADE job {}: result over inline limit, downloading from output_urlz5 completed with neither inline payload nor output_urlÚmetadataÚfailed_pageszADE parse failed on pages z$; refusing to return a partial parseÚcredit_usageÚbillingÚtotal_creditsz2ADE parse complete: pages={} credits={} version={}Ú
page_countÚversionÚmodel_version)ÚtimeÚgetÚstatusÚprogressr   r   ÚTIMEOUT_SECONDSr*   ÚsleepÚgetattrÚjsonÚloadsÚmodel_dump_jsonÚurllibÚrequestÚurlopenÚread)r   r   r   Út0ÚlastÚrÚstateÚreasonÚpayloadr6   ÚdocÚrespÚmetar.   Úcreditss                  r   r   r   Z   s‘  € ä	�Š‹€BØ€DØ
Ø�H‰H�VÓˆØ—‘˜1Ÿ:™:Ð&ˆØ‹=Ü�KŠKØGØØ—‘Ø—
‘
×!˜cÜ—	’	“˜bÑ ôð ˆDØ�8‰8Ð;Ó;ØÜ�9Š9‹;˜ÑœoÓ-Ü ¨&¨Ð1BÄ?ÐSVÐBWÐWXÐYÓZÐZÜ�
Š
�<Ô ñ! ð$ 	‡x�x�;Óä˜Ð,¨dÓ3×P´w¸qÀ'È4Ó7PˆÜ˜X f X¨Q¨q¯x©x¨j¸¸6¸(ÐCÓDÐDô �a˜ Ó&×D¬'°!°X¸tÓ*D€GÜ˜˜L¨$Ó/×d´G¸A¸uÀdÓ4K×4QÈr×3VÑ3VÐWcÓ3d€JØÑÜ�jŠj˜×0Ñ0Ó2Ó3‰Þ	Ü�ŠÐWÐY_Ô`Ü�^‰^×#Ñ# JÔ/°4Ü—*’*˜TŸY™Y›[Ó)ˆC÷ 0Ð/ô ˜X f XÐ-bÐcÓdÐdà�7‰7�:Ó×$ "€DØ�X‰X�nÓ%×+¨€FÞÜÐ7¸°xÐ?cÐdÓeÐeð �h‰h�~Ó&€GØ�Ø—8‘8˜IÓ&×,¨"×1Ñ1°/ÓBˆÜ
‡K‚KØ<Ø�‰�ÓØØ�‰�Ó×8˜tŸx™x¨Ó8ô	ð €J÷) 0Õ/ús   È%LÌ
L')
r   r   r   Ústrr   zOptional[dict[str, str]]r   ÚfloatÚreturnúdict[str, Any])r   rX   rZ   Úbool)rZ   r   )r   r   r   rX   r   rY   rZ   r[   )Ú__doc__Ú
__future__r   rG   r@   Úurllib.requestrJ   Úpathlibr   Útypingr   r   Úlogurur   Úquber.settingsr   ÚDEFAULT_MODELÚPOLL_SECONDSrD   r    r   r   r   r   r!   r   Ú<module>rf      s‰   ðñõ0 #ã Û Û Ý ß  å å 'ð €à€Ø€ð
 Ø/3Ø&ð	9Øð9àð9ð -ð9ð ð	9ð
 õ9ô>%ô
$ð AM÷ 6r!   