ó
    §\Fj‚  ã                  óì   • S r SSKJr  SSKJr  SSKJr  SSKJrJ	r	J
r
Jr  SSKJrJr  SSKJrJr  SSKJrJr   " S	 S
\5      r " S S\5      rSr\ " S S\
5      5       r " S S5      r\SS j5       rg)u?  Pick, by tag, the exact text a combined cell's source piece came from.

The structure-correction agent reports, for every cell it built by joining two
or more Camelot cells, the exact source strings it combined. Each string's
occurrences within the table frame are found deterministically; when a string
occurs more than once, a small numbered tag is drawn directly on each
occurrence and this agent answers one multiple-choice question per ambiguous
piece: WHICH TAG sits on the text that piece came from.

The model never produces a coordinate. It reads printed tag numbers off the
image and names one â€” the same identification-over-geometry premise as the
grid locator, taken to its end. The answer resolves to an exact box by lookup,
because the tag was drawn on the box; there is nothing to snap and no
tolerance to police.
é    )Úannotations)Úcache)ÚPath)ÚDictÚOptionalÚProtocolÚruntime_checkable)Ú	BaseModelÚField)ÚLangSmithTracerÚusage_metadata_from)ÚDEFAULT_LLM_MODELÚget_settingsc                  óF   • \ rS rSr% Sr\" SS9rS\S'   \" SS9rS\S'   S	r	g
)ÚTagPické   zDOne answered question: the tag on the text a source piece came from.z"The question number being answered)ÚdescriptionÚintÚquestionz=The tag number sitting on the exact text this piece came fromÚtag© N)
Ú__name__Ú
__module__Ú__qualname__Ú__firstlineno__Ú__doc__r   r   Ú__annotations__r   Ú__static_attributes__r   ó    Ú9/home/mande/repo/quber/src/quber/agents/source_locator.pyr   r      s%   ‡ ÙNáÐ&JÑK€HˆcÓKÙÐ!`Ña€CˆÖar   r   c                  ó.   • \ rS rSr% \" \SS9rS\S'   Srg)ÚTagPicksé$   z,One pick per question; answer every question)Údefault_factoryr   zlist[TagPick]Úpicksr   N)	r   r   r   r   r   Úlistr%   r   r   r   r   r    r"   r"   $   s   ‡ Ù ØÐ*Xñ€Eˆ=ö r   r"   uK  The image is one table. Small red numbered tags are drawn directly on specific
pieces of text; each tag marks one occurrence of a piece.

You are given numbered questions. Each question names a corrected cell that was
built by combining several text pieces, names one of those pieces, and lists
the tag numbers that are valid options for it. For every question, pick the ONE
tag sitting on the text that piece was actually taken from â€” the occurrence
that belongs to that cell's own row and column context. Use only tag numbers
from that question's options, and answer every question.
c                  ó   • \ rS rSrSS jrSrg)ÚSourceLocatoré7   c              ƒ  ó   #   • g 7f)Nr   )ÚselfÚtagged_cropÚ	questionss      r    Ú	pick_tagsÚSourceLocator.pick_tags9   s   é € ÐTWùs   ‚r   N©r,   r   r-   ÚstrÚreturnzDict[int, int])r   r   r   r   r.   r   r   r   r    r(   r(   7   s   † çWr   r(   c                  óN   • \ rS rSrSrSrSSS\4         SS jjrS	S jrSrg)
ÚPydanticAISourceLocatoré<   u  SourceLocator backed by pydantic-ai with an Anthropic vision model.

Same auth resolution and greedy decoding as the grid locator, and runs on
the same stronger vision model â€” reading small printed tags in a dense
table is the fidelity the smaller model lacks.
g        Nc                ó  • SSK Jn  SSKJn  SSKJn  SSKJn  [        5       R                  n	U=(       d?    U	R                  =(       d,    U	R                  =(       d    U	R                  =(       d    [        nU=(       d    U	R                  n
U=(       d    U	R                  nU
(       a  SSKJn  U" X5      nOU(       a  U" US9nU" XS9nO[%        S	5      eXl        Uc  S OU" US
9nU" U[&        [(        US9U l        [-        SS9U l        g )Nr   )ÚAgent)ÚAnthropicModel)ÚAnthropicProvider)ÚModelSettings)Úmake_oauth_anthropic_model)Úapi_key)ÚproviderzwPydanticAISourceLocator: neither ANTHROPIC_AUTH_TOKEN nor ANTHROPIC_API_KEY is set. Provide one via env or constructor.)Útemperature)Úoutput_typeÚsystem_promptÚmodel_settingszquber-source-locator)Úrun_name)Úpydantic_air7   Úpydantic_ai.models.anthropicr8   Úpydantic_ai.providers.anthropicr9   Úpydantic_ai.settingsr:   r   ÚllmÚsource_locator_modelÚgrid_locator_modelÚmodelr   Úanthropic_auth_tokenÚanthropic_api_keyÚquber.agents._oauth_gater;   ÚRuntimeErrorr"   Ú
TAG_PROMPTÚagentr   Útracer)r+   rJ   Ú
auth_tokenr<   r>   r7   r8   r9   r:   Úllm_settingsÚresolved_authÚresolved_keyr;   Ú
anth_modelr=   rA   s                   r    Ú__init__Ú PydanticAISourceLocator.__init__F   só   € õ 	&Ý?ÝEÝ6ä#“~×)Ñ)ˆà÷ 9Ø×0Ñ0÷9à×.Ñ.÷9ð ×"Ñ"×7Ô&7ð	 	ð #×G l×&GÑ&GˆØ×@ ,×"@Ñ"@ˆæÝKá3°EÓI‰JÞÙ(°Ñ>ˆHÙ'¨ÑA‰JäðPóð ð
 Œ
Ø!,Ñ!4™¹-ÐT_Ñ:`ˆÙØÜ Ü$Ø)ñ	
ˆŒ
ô &Ð/EÑFˆ�r   c              ƒ  ód  #   • SSK Jn  U" UR                  5       SS9nSS[        S.SS	US
.SSS
./S./0nU R                  R                  SXPR                  S9 ISh  v•N nU R                  R                  X$/5      I Sh  v•N nSUR                  R                  5       S./[        UR                  5      S.Ul        SSS5      ISh  v•N   WR                  R                   Vs0 s H  oˆR                  UR                   _M     sn$  N¬ NŠ NC! , ISh  v•N  (       d  f       NX= fs  snf 7f)zBAnswer the tag questions against the tagged crop; {question: tag}.r   )ÚBinaryContentz	image/png)ÚdataÚ
media_typeÚmessagesÚsystem)ÚroleÚcontentÚuserÚtext)Útyperb   Úimagez[tagged table crop attached]Úsource_tags)rJ   NÚ	assistant)r]   Úusage_metadata)rC   rZ   Ú
read_bytesrO   rQ   Úllm_runrJ   rP   ÚrunÚoutputÚmodel_dump_jsonr   ÚusageÚoutputsr%   r   r   )	r+   r,   r-   rZ   rd   Úinputsrj   ÚresultÚps	            r    r.   Ú!PydanticAISourceLocator.pick_tagss   s  é € å-á ;×#9Ñ#9Ó#;ÈÑTˆàØ!¬jÑ9à"à!'°Ñ;Ø!(Ð2PÑQð ñð	ð
ˆð —;‘;×&Ñ& }°fÇJÁJÐ&×OÑOÐSVØŸ:™:Ÿ>™>¨9Ð*<Ó=×=ˆFà&1¸f¿m¹m×>[Ñ>[Ó>]Ñ^Ð_Ü"5°f·l±lÓ"CñˆCŒK÷ P×Oð ,2¯=©=×+>Ò+>Ó?Ò+> a—
‘
˜AŸE™EÒ!Ñ+>Ñ?Ð?ñ PÙ=÷ P×O×OÐOüò @ùsf   ‚AD0ÁDÁD0Á" DÂDÂ=DÃ D0ÃDÃD0Ã( D+ÄD0ÄDÄD0ÄD(ÄDÄD(Ä$D0)rP   rJ   rQ   )
rJ   úOptional[str]rR   rs   r<   rs   r>   zOptional[float]r2   ÚNoner0   )	r   r   r   r   r   ÚDEFAULT_TEMPERATURErW   r.   r   r   r   r    r4   r4   <   s_   † ñð Ðð  $Ø$(Ø!%Ø':ð+Gàð+Gð "ð+Gð ð	+Gð
 %ð+Gð 
õ+G÷Z@r   r4   c                 ó   • [        5       $ )zGProcess-wide singleton source locator (agent construction is not free).)r4   r   r   r    Úget_source_locatorrw   �   s   € ô #Ó$Ð$r   N)r2   r(   )r   Ú
__future__r   Ú	functoolsr   Úpathlibr   Útypingr   r   r   r	   Úpydanticr
   r   Úquber.agents.langsmith_tracerr   r   Úquber.settingsr   r   r   r"   rO   r(   r4   rw   r   r   r    Ú<module>r      s†   ðñõ  #å Ý ß >Ó >ç %ç Nß :ôbˆiô bôˆyô ð
€
ð ôX�Hó Xó ðX÷N@ñ N@ðb ó%ó ñ%r   