§
    ‰eîiÚ� ã                  ó|  — U 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
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mZ ddlmZmZ ddlmZmZ ddlmZ dd	lmZm Z m!Z!m"Z" dd
l#m$Z$m%Z%m&Z& ddl'Z'ddl(Z(ddl)m*Z*m+Z+m,Z, ddl-m.Z.  ej/        e0¦  «        Z1	 ddl2Z2n# e3$ r dZ2Y nw xY w	 ddl4Z4n# e3$ r dZ4Y nw xY wdZ5dZ6dZ7dZ8dZ9dZ:dZ;dZ<dZ=dZ>dZ?dZ@dZAdZBdZCdZDdZEdZFdZGdZHdZIdZJd ZKd!ZLd"ZMd#ZNd$ZOdZPd% Q                    d&¦  «        ZRd'd(iZSd)eTd*<   d+ZUd,ZVe G d-„ d.¦  «        ¦   «         ZWi d/ eWd/d0d1e7e8e9e:¬2¦  «        “d3 eWd3d4d5e>¬6¦  «        “d7 eWd7d8d5e?¬6¦  «        “d9 eWd9d:d5eU¬6¦  «        “d; eWd;d<d=e@d>d?¬@¦  «        “dA eWdAdBdCeAdD¬E¦  «        “dF eWdFdGd=dHdIdJ¬@¦  «        “dK eWdKdLd=dMdNdO¬@¦  «        “dP eWdPdQd=dRdSdT¬@¦  «        “dU eWdUdVd=dWdX¬Y¦  «        “dZ eWdZd[d=eCd\d]¬@¦  «        “d^ eWd^d_d=d`dadb¬@¦  «        “dc eWdcddd=dedfdg¬@¦  «        “dh eWdhdid=djdkdl¬@¦  «        “dm eWdmdnd=dodpdq¬@¦  «        “dr eWdrdsd=dtdudv¬@¦  «        “dw eWdwdxd=dydzd{¬@¦  «        “ eWd|d}d=d~dd€¬@¦  «         eWd�d‚d=dƒd„d…¬@¦  «         eWd†d‡d=dˆd‰dŠ¬@¦  «         eWd‹dŒd=d�dŽd�¬@¦  «         eWd�d‘d=d’d“d”¬@¦  «         eWd•d–d=d—d˜d™¬@¦  «         eWdšd›d=dœd�dž¬@¦  «         eWdŸd d=d¡d¢d£¬@¦  «         eWd¤d¥d=d¦d§d¨¬@¦  «         eWd©dªd=eBd«d¬¬@¦  «         eWd­d®d¯d°d±d²¬@¦  «         eWd³d´d=dµd¶d·¬@¦  «        d¸œ¥ZXd¹eTdº<   �d½d½„ZYd¾ZZ�d¾dÁ„Z[h dÂ£Z\dÃdÄœ�d¿dÊ„Z]�dÀdÎ„Z^dÏdMdÐgdÑfdÒdÓdÐgdÔfdÕdÖg d×¢dØfdÙdÚg d×¢dÛfgZ_�dÁ�dÂdà„Z`�d¾dá„Za G dâ„ dãeb¦  «        Zc�dÃdæ„Zd�dÄdé„Ze�dÅdê„Zfddëœ�dÆdð„Zg�dÇdò„Zh�dÇdó„Zi ejj        ¦   «         Zkee6f�dÈdõ„¦   «         Zl�dÉ�dÊdù„Zm�dËdû„Zn�dÌdý„Zo�dÍdÿ„Zp�d �dœ�dÎ�d„Zq�dÏ�d„Zr�dÐ�d„Zs�dÉ�dÑ�d„Zt�dÒ�d	„Zu�dÓ�d„Zv�dÔ�d„Zw�dÔ�d„Zx�dÕ�d„Zy�dÖ�d„Zz�dÏ�d„Z{�dÉ�d×�d„Z|�dØ�d„Z}�dÙ�d„Z~	 �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ˆeJf�dã�d*„Z‰�dä�då�d,„ZŠ�d-�d eJ�d.œ�dæ�d2„Z‹�dá�d3„ZŒ�d-�d4œ�dç�d5„Z��dá�d6„ZŽ�dÉ�dè�d9„Z��dÉ�dé�d:„Z�	 	 �dê�dë�d<„Z‘	 	 �dê�dë�d=„Z’�dÉ�dì�d>„Z“�dÉ�dì�d?„Z”�dí�dî�dB„Z•�dï�dD„Z–�dð�dJ„Z—�dñ�dL„Z˜�dò�dO„Z™�dP�dQœ�dó�dS„Zšd�dTœ�dô�dY„Z›�d+�dQœ�dõ�d[„Zœ�d+�dQœ�dö�d\„Z��d-�d eP�d.œ�dæ�d]„Zž�dá�d^„ZŸ�d÷�d`„Z �dØ�da„Z¡�dÅ�db„Z¢�d �dcœ�dø�de„Z£�dÉ�dù�dg„Z¤�d+�dQœ�dú�di„Z¥�dû�dj„Z¦�dü�dk„Z§�d-�d eG�d.œ�dæ�dl„Z¨�dý�dn„Z©ddd�doœ�dþ�dt„Zª�dÿ�dx„Z«�d �d{„Z¬�d�d|„Z­�d�d~„Z®d�d �dœ�d�dƒ„Z¯�d�d„„Z°ddde<�d…œ�d�d†„Z±�d‡e:dddde;ddd�d-�d-�dˆœ�d�d�„Z²e;d�d-�d-�d‘œ�d�d’„Z³�dyZ´d�d“œ�d�d–„Zµ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Ñ�dŸ„Z½�d
�d „Z¾�d
�d¡„Z¿	 �dÉ�d�d£„ZÀ�dÖ�d¤„ZÁ�d×�d¥„ZÂ�dÖ�d¦„ZÃ�dÇ�d§„ZÄ	 	 	 	 �d�d�d¯„ZÅ�d�d±„ZÆ�dØ�d²„ZÇ�d-�d³œ�d�dµ„ZÈ�dá�d¶„ZÉdddd�d d�d-d�d·�d¸œ	�d�dº„ZÊ�d�d»„ZË�dØ�d¼„ZÌdS (  aZ  
Multi-provider authentication system for Hermes Agent.

Supports OAuth device code flows (Nous Portal, future: OpenAI Codex) and
traditional API key providers (OpenRouter, custom endpoints). Auth state
is persisted in ~/.hermes/auth.json with cross-process file locking.

Architecture:
- ProviderConfig registry defines known OAuth providers
- Auth store (auth.json) holds per-provider credential state
- resolve_provider() picks the active provider via priority chain
- resolve_*_runtime_credentials() handles token refresh and key minting
- logout_command() is the CLI entry point for clearing auth
é    )ÚannotationsN)Úcontextmanager)Ú	dataclassÚfield)ÚdatetimeÚtimezone)ÚBaseHTTPRequestHandlerÚ
HTTPServer)ÚPath)ÚAnyÚDictÚListÚOptional)Úparse_qsÚ	urlencodeÚurlparse)Úget_hermes_homeÚget_config_pathÚread_raw_config)ÚOPENROUTER_BASE_URLé   ç      .@zhttps://portal.nousresearch.comz)https://inference-api.nousresearch.com/v1ú
hermes-clizinference:mint_agent_keyi  éx   z%https://chatgpt.com/backend-api/codexzhttps://portal.qwen.ai/v1zhttps://api.githubcopilot.comzacp://copilotzhttps://ollama.com/v1z#https://api.stepfun.ai/step_plan/v1z$https://api.stepfun.com/step_plan/v1Úapp_EMoamEEZ73f0CkXaXp7hrannz#https://auth.openai.com/oauth/tokenÚ f0304373b74a44d2b584a3fb70ca9e56z(https://chat.qwen.ai/api/v1/oauth2/tokenzhttps://accounts.spotify.comzhttps://api.spotify.com/v1z'http://127.0.0.1:43827/spotify/callbackzFhttps://hermes-agent.nousresearch.com/docs/user-guide/features/spotifyz'https://developer.spotify.com/dashboardÚ )
zuser-modify-playback-statezuser-read-playback-statezuser-read-currently-playingzuser-read-recently-playedzplaylist-read-privatezplaylist-read-collaborativezplaylist-modify-publiczplaylist-modify-privatezuser-library-readzuser-library-modifyÚspotifyÚSpotifyúDict[str, str]ÚSERVICE_PROVIDER_NAMESzcloudcode-pa://googleé<   c                  ó¨   — e Zd ZU dZded<   ded<   ded<   dZded<   dZded<   dZded	<   dZded
<    e	e
¬¦  «        Zded<   dZded<   dZded<   dS )ÚProviderConfigz%Describes a known inference provider.ÚstrÚidÚnameÚ	auth_typeÚ Úportal_base_urlÚinference_base_urlÚ	client_idÚscope)Údefault_factoryúDict[str, Any]Úextra© ÚtupleÚapi_key_env_varsÚbase_url_env_varN)Ú__name__Ú
__module__Ú__qualname__Ú__doc__Ú__annotations__r*   r+   r,   r-   r   Údictr0   r3   r4   r1   ó    ú1/home/div/.hermes/hermes-agent/hermes_cli/auth.pyr$   r$   u   s¶   € € € € € € à/Ð/Ø€G€G�GØ€I€I�IØ€N€N�NØ€OÐÐÐÑØ ÐÐ Ð Ð Ñ Ø€IÐÐÐÑØ€E€O€O€O�OØ!˜E°$Ð7Ñ7Ô7€EÐ7Ð7Ð7Ñ7à ÐÐ Ð Ð Ñ àÐÐÐÐÑÐÐr;   r$   ÚnouszNous PortalÚoauth_device_code)r&   r'   r(   r*   r+   r,   r-   úopenai-codexzOpenAI CodexÚoauth_external)r&   r'   r(   r+   ú
qwen-oauthz
Qwen OAuthúgoogle-gemini-clizGoogle Gemini (OAuth)ÚcopilotzGitHub CopilotÚapi_key)ÚCOPILOT_GITHUB_TOKENÚGH_TOKENÚGITHUB_TOKENÚCOPILOT_API_BASE_URL)r&   r'   r(   r+   r3   r4   úcopilot-acpzGitHub Copilot ACPÚexternal_processÚCOPILOT_ACP_BASE_URL)r&   r'   r(   r+   r4   ÚgeminizGoogle AI Studioz0https://generativelanguage.googleapis.com/v1beta)ÚGOOGLE_API_KEYÚGEMINI_API_KEYÚGEMINI_BASE_URLÚzaiz
Z.AI / GLMzhttps://api.z.ai/api/paas/v4)ÚGLM_API_KEYÚZAI_API_KEYÚZ_AI_API_KEYÚGLM_BASE_URLúkimi-codingzKimi / Moonshotzhttps://api.moonshot.ai/v1)ÚKIMI_API_KEYÚKIMI_CODING_API_KEYÚKIMI_BASE_URLúkimi-coding-cnzKimi / Moonshot (China)zhttps://api.moonshot.cn/v1)ÚKIMI_CN_API_KEY)r&   r'   r(   r+   r3   ÚstepfunzStepFun Step Plan)ÚSTEPFUN_API_KEYÚSTEPFUN_BASE_URLÚarceezArcee AIzhttps://api.arcee.ai/api/v1)ÚARCEEAI_API_KEYÚARCEE_BASE_URLÚminimaxÚMiniMaxz https://api.minimax.io/anthropic)ÚMINIMAX_API_KEYÚMINIMAX_BASE_URLÚ	anthropicÚ	Anthropiczhttps://api.anthropic.com)ÚANTHROPIC_API_KEYÚANTHROPIC_TOKENÚCLAUDE_CODE_OAUTH_TOKENÚANTHROPIC_BASE_URLÚalibabazAlibaba Cloud (DashScope)z6https://dashscope-intl.aliyuncs.com/compatible-mode/v1)ÚDASHSCOPE_API_KEYÚDASHSCOPE_BASE_URLúalibaba-coding-planzAlibaba Cloud (Coding Plan)z-https://coding-intl.dashscope.aliyuncs.com/v1)ÚALIBABA_CODING_PLAN_API_KEYrl   ÚALIBABA_CODING_PLAN_BASE_URLú
minimax-cnzMiniMax (China)z"https://api.minimaxi.com/anthropic)ÚMINIMAX_CN_API_KEYÚMINIMAX_CN_BASE_URLÚdeepseekÚDeepSeekzhttps://api.deepseek.com/v1)ÚDEEPSEEK_API_KEYÚDEEPSEEK_BASE_URLÚxaiÚxAIzhttps://api.x.ai/v1)ÚXAI_API_KEYÚXAI_BASE_URLÚnvidiaz
NVIDIA NIMz#https://integrate.api.nvidia.com/v1)ÚNVIDIA_API_KEYÚNVIDIA_BASE_URLú
ai-gatewayzVercel AI Gatewayzhttps://ai-gateway.vercel.sh/v1)ÚAI_GATEWAY_API_KEYÚAI_GATEWAY_BASE_URLúopencode-zenzOpenCode Zenzhttps://opencode.ai/zen/v1)ÚOPENCODE_ZEN_API_KEYÚOPENCODE_ZEN_BASE_URLúopencode-gozOpenCode Gozhttps://opencode.ai/zen/go/v1)ÚOPENCODE_GO_API_KEYÚOPENCODE_GO_BASE_URLÚkilocodez	Kilo Codezhttps://api.kilo.ai/api/gateway)ÚKILOCODE_API_KEYÚKILOCODE_BASE_URLÚhuggingfacezHugging Facez https://router.huggingface.co/v1)ÚHF_TOKENÚHF_BASE_URLÚxiaomizXiaomi MiMozhttps://api.xiaomimimo.com/v1)ÚXIAOMI_API_KEYÚXIAOMI_BASE_URLúollama-cloudzOllama Cloud)ÚOLLAMA_API_KEYÚOLLAMA_BASE_URLÚbedrockzAWS BedrockÚaws_sdkz/https://bedrock-runtime.us-east-1.amazonaws.comr1   ÚBEDROCK_BASE_URLúazure-foundryzAzure Foundryr)   )ÚAZURE_FOUNDRY_API_KEYÚAZURE_FOUNDRY_BASE_URL)rt   rx   r|   r   r‚   r…   rˆ   r‹   rŽ   r‘   r”   r—   zDict[str, ProviderConfig]ÚPROVIDER_REGISTRYÚreturnr%   c                 óˆ   — ddl m}  t          d         j        D ](} | |¦  «        pt	          j        |d¦  «        }|r|c S Œ)dS )aQ  Return the first usable Anthropic credential, or ``""``.

    Checks both the ``.env`` file (via ``get_env_value``) and the process
    environment (``os.getenv``).  The fallback order mirrors the
    ``PROVIDER_REGISTRY["anthropic"].api_key_env_vars`` tuple:

        ANTHROPIC_API_KEY -> ANTHROPIC_TOKEN -> CLAUDE_CODE_OAUTH_TOKEN
    r   ©Úget_env_valuere   r)   )Úhermes_cli.configrž   rš   r3   ÚosÚgetenv)rž   ÚvarÚvalues      r<   Úget_anthropic_keyr¤   v  sh   € ð 0Ð/Ð/Ð/Ð/Ð/å  Ô-Ô>ð ð ˆØ�˜cÑ"Ô"Ð8¥b¤i°°RÑ&8Ô&8ˆØð 	ØˆLˆLˆLð	àˆ2r;   zhttps://api.kimi.com/codingÚdefault_urlÚenv_overridec                óN   — |r|S | s|S |                       d¦  «        rt          S |S )zÎReturn the correct Kimi base URL based on the API key prefix.

    If the user has explicitly set KIMI_BASE_URL, that always wins.
    Otherwise, sk-kimi- prefixed keys route to api.kimi.com/coding/v1.
    zsk-kimi-)Ú
startswithÚKIMI_CODE_BASE_URL)rD   r¥   r¦   s      r<   Ú_resolve_kimi_base_urlrª   ™  sB   € ð ð ØÐàð ØÐØ×Ò˜*Ñ%Ô%ð "Ý!Ð!ØÐr;   >   ú**ú***úyour-api-keyÚ*ÚnoneÚnullÚdummyÚexampleÚchangemeÚplaceholderÚyour_api_keyé   )Ú
min_lengthr£   r   r·   ÚintÚboolc               óÀ   — t          | t          ¦  «        sdS |                      ¦   «         }t          |¦  «        |k     rdS |                     ¦   «         t
          v rdS dS )zIReturn True when a configured secret looks usable, not empty/placeholder.FT)Ú
isinstancer%   ÚstripÚlenÚlowerÚ_PLACEHOLDER_SECRET_VALUES)r£   r·   Úcleaneds      r<   Úhas_usable_secretrÁ   ¹  sZ   € å�e�SÑ!Ô!ð ØˆuØ�kŠk‰mŒm€GÝ
ˆ7�|„|�jÒ Ð ØˆuØ‡}‚}�„Õ4Ð4Ð4ØˆuØˆ4r;   Úprovider_idÚpconfigútuple[str, str]c                ó´  — | dk    re	 ddl m}m}  |¦   «         \  }}|r ||¦  «        |fS n=# t          $ r%}t                               d|¦  «         Y d}~nd}~wt          $ r Y nw xY wdS ddlm} |j	        D ]6} ||¦  «        pd 
                    ¦   «         }	t          |	¦  «        r|	|fc S Œ7	 dd	lm}
  |
| ¦  «        }|rƒ|                     ¦   «         ro|                     ¦   «         }|rYt!          |d
d¦  «        pt!          |dd¦  «        }t#          |¦  «         
                    ¦   «         }t          |¦  «        r|d| › �fS n# t          $ r Y nw xY wdS )zDResolve an API-key provider's token and indicate where it came from.rC   r   )Úresolve_copilot_tokenÚget_copilot_api_tokenz#Copilot token validation failed: %sN)r)   r)   r�   r)   ©Ú	load_poolÚaccess_tokenÚruntime_api_keyzcredential_pool:)Úhermes_cli.copilot_authrÆ   rÇ   Ú
ValueErrorÚloggerÚwarningÚ	ExceptionrŸ   rž   r3   r¼   rÁ   Úagent.credential_poolrÉ   Úhas_credentialsÚpeekÚgetattrr%   )rÂ   rÃ   rÆ   rÇ   ÚtokenÚsourceÚexcrž   Úenv_varÚvalrÉ   ÚpoolÚentryÚkeys                 r<   Ú _resolve_api_key_provider_secretrÝ   Å  s  € ð �iÒÐð	Ø\Ð\Ð\Ð\Ð\Ð\Ð\Ð\Ø1Ð1Ñ3Ô3‰MˆE�6Øð <Ø,Ð,¨UÑ3Ô3°VÐ;Ð;ð<øåð 	Gð 	Gð 	GÝ�NŠNÐ@À#ÑFÔFÐFÐFÐFÐFÐFÐFøøøøÝð 	ð 	ð 	ØˆDð	øøøàˆvà/Ð/Ð/Ð/Ð/Ð/ØÔ+ð  ð  ˆàˆ}˜WÑ%Ô%Ð+¨×2Ò2Ñ4Ô4ˆÝ˜SÑ!Ô!ð 	 Ø˜�<ÐÐÐð	 ðØ3Ð3Ð3Ð3Ð3Ð3Øˆy˜Ñ%Ô%ˆØð 	A�D×(Ò(Ñ*Ô*ð 	AØ—I’I‘K”KˆEØð AÝ˜e ^°RÑ8Ô8Ða½GÀEÐK\Ð^`Ñ<aÔ<a�Ý˜#‘h”h—n’nÑ&Ô&�Ý$ SÑ)Ô)ð AØÐ @°;Ð @Ð @Ð@Ð@øøÝð ð ð Øˆðøøøð ˆ6s-   ˆ#- ­
A'·AÁA'Á&A'Â1BE Å
EÅEÚglobalzglm-5ÚGlobalÚcnz$https://open.bigmodel.cn/api/paas/v4ÚChinazcoding-globalz#https://api.z.ai/api/coding/paas/v4)zglm-5.1zglm-5v-turbozglm-4.7zGlobal (Coding Plan)z	coding-cnz+https://open.bigmodel.cn/api/coding/paas/v4zChina (Coding Plan)ç       @ÚtimeoutÚfloatúOptional[Dict[str, str]]c                ó–  — t           D ]À\  }}}}|D ]¶}	 t          j        |› d�d| › �ddœ|ddddd	œgd
œ|¬¦  «        }|j        dk    r(t                               d|||¦  «         ||||dœc c S t                               d|||j        ¦  «         Œƒ# t          $ r'}t                               d|||¦  «         Y d}~Œ¯d}~ww xY wŒÁdS )a+  Probe z.ai endpoints to find one that accepts this API key.

    Returns {"id": ..., "base_url": ..., "model": ..., "label": ...} for the
    first working endpoint, or None if all fail.  For endpoints with multiple
    candidate models, tries each in order and returns the first that succeeds.
    z/chat/completionsúBearer úapplication/json)ÚAuthorizationúContent-TypeFr   ÚuserÚping)ÚroleÚcontent)ÚmodelÚstreamÚ
max_tokensÚmessages)ÚheadersÚjsonrã   éÈ   z(Z.AI endpoint probe: %s (%s) model=%s OK)r&   Úbase_urlrï   Úlabelz,Z.AI endpoint probe: %s model=%s returned %sz+Z.AI endpoint probe: %s model=%s failed: %sN)ÚZAI_ENDPOINTSÚhttpxÚpostÚstatus_coderÎ   ÚdebugrÐ   )	rD   rã   Úep_idrö   Úprobe_modelsr÷   rï   Úrespr×   s	            r<   Údetect_zai_endpointr     sn  € õ 1>ð _ð _Ñ,ˆˆx˜ uØ!ð 	_ð 	_ˆEð_Ý”zØÐ2Ð2Ð2à)<°7Ð)<Ð)<Ø(:ðð ð
 "'Ø"'Ø&'Ø.4ÀÐ%HÐ%HÐ$Ið	ð ð $ðñ ô �ð Ô# sÒ*Ð*Ý—L’LÐ!KÈUÐT\Ð^cÑdÔdÐdà#Ø$,Ø!&Ø!&ð	ð ð ð ð ð ð õ —’ÐKÈUÐTYÐ[_Ô[kÑlÔlÐlÐløÝð _ð _ð _Ý—’ÐJÈEÐSXÐZ]Ñ^Ô^Ð^Ð^Ð^Ð^Ð^Ð^øøøøð_øøøð3	_ð6 ˆ4s   ”ABÁ1"BÂ
CÂC Ã Cc                óø  — |r|S | s|S t          ¦   «         }t          |d¦  «        pi }|                     d¦  «        }t          |t          ¦  «        r˜|                     d¦  «        rƒ|                     dd¦  «        }|t          j        |                      ¦   «         ¦  «                             ¦   «         dd…         k    r)t           
                    d|d         ¦  «         |d         S t          | ¦  «        }|rã|                     d¦  «        rÎt          j        |                      ¦   «         ¦  «                             ¦   «         dd…         }|d         |                     d	d¦  «        |                     d
d¦  «        |                     dd¦  «        |dœ|d<   t          |d|¦  «         t                               d|d         |d         ¦  «         |d         S t           
                    d|¦  «         |S )aY  Return the correct Z.AI base URL by probing endpoints.

    If the user has explicitly set GLM_BASE_URL, that always wins.
    Otherwise, probe the candidate endpoints to find one that accepts the
    key.  The detected endpoint is cached in provider state (auth.json) keyed
    on a hash of the API key so subsequent starts skip the probe.
    rP   Údetected_endpointrö   Úkey_hashr)   Né   zZ.AI: using cached endpoint %sr&   rï   r÷   )rö   Úendpoint_idrï   r÷   r  z$Z.AI: auto-detected endpoint %s (%s)z.Z.AI: probe failed, falling back to default %s)Ú_load_auth_storeÚ_load_provider_stateÚgetr»   r:   ÚhashlibÚsha256ÚencodeÚ	hexdigestrÎ   rü   r   Ú_save_provider_stateÚinfo)rD   r¥   r¦   Ú
auth_storeÚstateÚcachedr  Údetecteds           r<   Ú_resolve_zai_base_urlr  (  sê  € ð ð ØÐð ð ØÐõ "Ñ#Ô#€JÝ  ¨UÑ3Ô3Ð9°r€EØ�YŠYÐ*Ñ+Ô+€FÝ�&�$ÑÔð & F§J¢J¨zÑ$:Ô$:ð &Ø—:’:˜j¨"Ñ-Ô-ˆØ•w”~ g§n¢nÑ&6Ô&6Ñ7Ô7×AÒAÑCÔCÀCÀRÀCÔHÒHÐHÝ�LŠLÐ9¸6À*Ô;MÑNÔNÐNØ˜*Ô%Ð%õ # 7Ñ+Ô+€HØð $�H—L’L Ñ,Ô,ð $å”> '§.¢.Ñ"2Ô"2Ñ3Ô3×=Ò=Ñ?Ô?ÀÀÀÔDˆà  Ô,Ø#Ÿ<š<¨¨bÑ1Ô1Ø—\’\ '¨2Ñ.Ô.Ø—\’\ '¨2Ñ.Ô.Ø ð&
ð &
ˆÐ!Ñ"õ 	˜Z¨°Ñ6Ô6Ð6Ý�ŠÐ:¸HÀWÔ<MÈxÐXbÔOcÑdÔdÐdØ˜
Ô#Ð#å
‡L‚LÐAÀ;ÑOÔOÐOØÐr;   c                  ó.   ‡ — e Zd ZdZddddœdˆ fd„Zˆ xZS )Ú	AuthErrorz,Structured auth error with UX mapping hints.r)   NF©ÚproviderÚcodeÚrelogin_requiredÚmessager%   r  r  úOptional[str]r  r¹   r›   ÚNonec               ót   •— t          ¦   «                              |¦  «         || _        || _        || _        d S ©N)ÚsuperÚ__init__r  r  r  )Úselfr  r  r  r  Ú	__class__s        €r<   r   zAuthError.__init__`  s9   ø€ õ 	‰Œ×Ò˜Ñ!Ô!Ð!Ø ˆŒØˆŒ	Ø 0ˆÔÐÐr;   )
r  r%   r  r%   r  r  r  r¹   r›   r  )r5   r6   r7   r8   r   Ú__classcell__)r"  s   @r<   r  r  ]  sX   ø€ € € € € Ø6Ð6ð Ø"Ø!&ð1ð 1ð 1ð 1ð 1ð 1ð 1ð 1ð 1ð 1ð 1ð 1r;   r  ÚerrorrÐ   c                óØ   — t          | t          ¦  «        st          | ¦  «        S | j        r| › d�S | j        dk    r	 dS | j        dk    r	 dS | j        dk    r| › d�S t          | ¦  «        S )z2Map auth failures to concise user-facing guidance.z' Run `hermes model` to re-authenticate.Úsubscription_requiredzfNo active paid subscription found on Nous Portal. Please purchase/activate a subscription, then retry.Úinsufficient_creditszTSubscription credits are exhausted. Top up/renew credits in Nous Portal, then retry.Útemporarily_unavailablez Please retry in a few seconds.)r»   r  r%   r  r  )r$  s    r<   Úformat_auth_errorr)  n  s£   € å�e�YÑ'Ô'ð Ý�5‰zŒzÐàÔð AØÐ@Ð@Ð@Ð@à„zÐ,Ò,Ð,ðCð	
ð 	
ð
 „zÐ+Ò+Ð+ð?ð	
ð 	
ð
 „zÐ.Ò.Ð.ØÐ8Ð8Ð8Ð8åˆu‰:Œ:Ðr;   rÕ   r  c                óâ   — t          | t          ¦  «        sdS |                      ¦   «         }|sdS t          j        |                     d¦  «        ¦  «                             ¦   «         dd…         S )zJReturn a short hash fingerprint for telemetry without leaking token bytes.Núutf-8é   )r»   r%   r¼   r	  r
  r  r  )rÕ   rÀ   s     r<   Ú_token_fingerprintr-  ˆ  sd   € å�e�SÑ!Ô!ð ØˆtØ�kŠk‰mŒm€GØð ØˆtÝŒ>˜'Ÿ.š.¨Ñ1Ô1Ñ2Ô2×<Ò<Ñ>Ô>¸sÀ¸sÔCÐCr;   c                 ó|   — t          j        dd¦  «                             ¦   «                              ¦   «         } | dv S )NÚHERMES_OAUTH_TRACEr)   >   Ú1ÚonÚyesÚtrue)r    r¡   r¼   r¾   )Úraws    r<   Ú_oauth_trace_enabledr5  ’  s8   € Ý
Œ)Ð(¨"Ñ
-Ô
-×
3Ò
3Ñ
5Ô
5×
;Ò
;Ñ
=Ô
=€CØÐ,Ð,Ð,r;   ©Úsequence_idÚeventr7  Úfieldsr  c               óÆ   — t          ¦   «         sd S d| i}|r||d<   |                     |¦  «         t                               dt	          j        |dd¬¦  «        ¦  «         d S )Nr8  r7  zoauth_trace %sTF)Ú	sort_keysÚensure_ascii)r5  ÚupdaterÎ   r  rô   Údumps)r8  r7  r9  Úpayloads       r<   Ú_oauth_tracer@  —  sp   € ÝÑ!Ô!ð ØˆØ&¨Ð.€GØð -Ø!,ˆ�ÑØ‡N‚N�6ÑÔÐÝ
‡K‚KÐ ¥$¤*¨WÀÐSXÐ"YÑ"YÔ"YÑZÔZÐZÐZÐZr;   r   c                 óF  — t          ¦   «         dz  } t          j                             d¦  «        rpt	          j        ¦   «         dz  dz                       d¬¦  «        }	 |                      d¬¦  «        }n# t          $ r | }Y nw xY w||k    rt          d| › d�¦  «        ‚| S )Nú	auth.jsonÚPYTEST_CURRENT_TESTz.hermesF)Ústrictz8Refusing to touch real user auth store during test run: zq. Set HERMES_HOME to a tmp_path in your test fixture, or run via scripts/run_tests.sh for hermetic CI-parity env.)	r   r    Úenvironr  r   ÚhomeÚresolverÐ   ÚRuntimeError)ÚpathÚreal_home_authÚresolveds      r<   Ú_auth_file_pathrL  ¥  sÎ   € ÝÑÔ˜{Ñ*€Dõ 
„z‡~‚~Ð+Ñ,Ô,ð Ýœ)™+œ+¨	Ñ1°KÑ?×HÒHÐPUÐHÑVÔVˆð	Ø—|’|¨5�|Ñ1Ô1ˆHˆHøÝð 	ð 	ð 	ØˆHˆHˆHð	øøøà�~Ò%Ð%ÝðGÈ4ð Gð Gð Gñô ð ð
 €Ks   ÁA6 Á6BÂBc                 óD   — t          ¦   «                              d¦  «        S )Nz.lock)rL  Úwith_suffixr1   r;   r<   Ú_auth_lock_pathrO  »  s   € ÝÑÔ×(Ò(¨Ñ1Ô1Ð1r;   Útimeout_secondsc              #  ó¬  K  — t          t          dd¦  «        dk    rLt          xj        dz  c_        	 dV — t          xj        dz  c_        n# t          xj        dz  c_        w xY wdS t          ¦   «         }|j                             dd¬¦  «         t          €8t          €1dt          _        	 dV — dt          _        n# dt          _        w xY wdS t          rH|                     ¦   «         r| 	                    ¦   «         j
        dk    r|                     dd¬	¦  «         |                     t          rd
nd¦  «        5 }t          j        ¦   «         t          d| ¦  «        z   }	 	 t          r?t          j        |                     ¦   «         t          j        t          j        z  ¦  «         nG|                     d¦  «         t          j        |                     ¦   «         t          j        d¦  «         nX# t,          t.          t0          f$ r= t          j        ¦   «         |k    rt3          d¦  «        ‚t          j        d¦  «         Y nw xY wŒçdt          _        	 dV — dt          _        t          r3t          j        |                     ¦   «         t          j        ¦  «         �nt          r`	 |                     d¦  «         t          j        |                     ¦   «         t          j        d¦  «         nÉ# t.          t:          f$ r Y n¶w xY wn±# dt          _        t          r2t          j        |                     ¦   «         t          j        ¦  «         w t          r`	 |                     d¦  «         t          j        |                     ¦   «         t          j        d¦  «         w # t.          t:          f$ r Y w w xY ww xY wddd¦  «         dS # 1 swxY w Y   dS )zCCross-process advisory lock for auth.json reads+writes.  Reentrant.Údepthr   r   NT©ÚparentsÚexist_okr   r+  ©Úencodingzr+za+ç      ð?z%Timed out waiting for auth store lockgš™™™™™©?)rÔ   Ú_auth_lock_holderrR  rO  ÚparentÚmkdirÚfcntlÚmsvcrtÚexistsÚstatÚst_sizeÚ
write_textÚopenÚtimeÚmaxÚflockÚfilenoÚLOCK_EXÚLOCK_NBÚseekÚlockingÚLK_NBLCKÚBlockingIOErrorÚOSErrorÚPermissionErrorÚTimeoutErrorÚsleepÚLOCK_UNÚLK_UNLCKÚIOError)rP  Ú	lock_pathÚ	lock_fileÚdeadlines       r<   Ú_auth_store_lockrw  Á  s  è è € õ Õ  '¨1Ñ-Ô-°Ò1Ð1ÝÐÔ 1Ñ$ÐÔð	)ØˆEˆEˆEåÐ#Ô# qÑ(Ð#Ô#Ð#øÕÐ#Ô# qÑ(Ð#Ô#Ð#Ð#Ð#Ð#ØˆåÑ!Ô!€IØÔ×Ò 4°$ÐÑ7Ô7Ð7å€}�˜Ø"#ÕÔð	(ØˆEˆEˆEà&'ÕÔ#Ð#ø aÕÔ#Ð'Ð'Ð'Ð'Øˆõ ð 4�y×'Ò'Ñ)Ô)ð 4¨Y¯^ª^Ñ-=Ô-=Ô-EÈÒ-JÐ-JØ×Ò˜S¨7ÐÑ3Ô3Ð3à	�Š¥Ð0˜˜¨DÑ	1Ô	1ð °YÝ”9‘;”;¥ S¨/Ñ!:Ô!:Ñ:ˆð	!ð
!Ýð KÝ”K 	× 0Ò 0Ñ 2Ô 2µE´MÅEÄMÑ4QÑRÔRÐRÐRà—N’N 1Ñ%Ô%Ð%Ý”N 9×#3Ò#3Ñ#5Ô#5µv´ÈÑJÔJÐJØøÝ#¥W­oÐ>ð !ð !ð !Ý”9‘;”; (Ò*Ð*Ý&Ð'NÑOÔOÐOÝ”
˜4Ñ Ô Ð Ð Ð ð!øøøð	!ð #$ÕÔð	ØˆEˆEˆEà&'ÕÔ#Ýð Ý”˜I×,Ò,Ñ.Ô.µ´Ñ>Ô>Ð>Ñ>Ýð ðØ—N’N 1Ñ%Ô%Ð%Ý”N 9×#3Ò#3Ñ#5Ô#5µv´ÈÑJÔJÐJÐJøÝ¥Ð)ð ð ð Ø�Dðøøøð	øð '(ÕÔ#Ýð Ý”˜I×,Ò,Ñ.Ô.µ´Ñ>Ô>Ð>Ð>Ýð ðØ—N’N 1Ñ%Ô%Ð%Ý”N 9×#3Ò#3Ñ#5Ô#5µv´ÈÑJÔJÐJÐJøÝ¥Ð)ð ð ð Ø�Dðøøøð	øøøð-ð ð ñ ô ð ð ð ð ð ð ð øøøð ð ð ð ð ð s³   ³A ÁA$Â.B? Â?CÄ?&O	Å&BG4Ç3O	Ç4AIÉO	ÉIÉO	ÉLÉAO	Ê+AK3Ë2O	Ë3LÌO	ÌLÌO	ÌAN9ÍAN!Î N9Î!N5	Î2N9Î4N5	Î5N9Î9O	Ï	OÏOÚ	auth_fileúOptional[Path]r/   c                óz  — | pt          ¦   «         } |                      ¦   «         s
t          i dœS 	 t          j        |                      ¦   «         ¦  «        }nz# t          $ rm}|                      d¦  «        }	 dd l} |j	        | |¦  «         n# t          $ r Y nw xY wt                               d| ||¦  «         t          i dœcY d }~S d }~ww xY wt          |t          ¦  «        rht          |                     d¦  «        t          ¦  «        s(t          |                     d¦  «        t          ¦  «        r|                     di ¦  «         |S t          |t          ¦  «        rPt          |                     d¦  «        t          ¦  «        r(|d         }i }d|v r|d         |d	<   t          ||rd	nd d
œS t          i dœS )N)ÚversionÚ	providersz.json.corruptr   uY   auth: failed to parse %s (%s) â€” starting with empty store. Corrupt file preserved at %sr|  Úcredential_poolÚsystemsÚnous_portalr=   )r{  r|  Úactive_provider)rL  r^  ÚAUTH_STORE_VERSIONrô   ÚloadsÚ	read_textrÐ   rN  ÚshutilÚcopy2rÎ   rÏ   r»   r:   r  Ú
setdefault)rx  r4  r×   Úcorrupt_pathr„  r~  r|  s          r<   r  r  û  s  € ØÐ.�_Ñ.Ô.€IØ×ÒÑÔð @Ý-¸BÐ?Ð?Ð?ð@ÝŒj˜×,Ò,Ñ.Ô.Ñ/Ô/ˆˆøÝð @ð @ð @Ø ×,Ò,¨_Ñ=Ô=ˆð	ØˆMˆMˆMØˆFŒL˜ LÑ1Ô1Ð1Ð1øÝð 	ð 	ð 	ØˆDð	øøøå�Šð+à�s˜Lñ	
ô 	
ð 	
õ
 .¸BÐ?Ð?Ð?Ð?Ð?Ð?Ð?Ð?øøøøð@øøøõ �#•tÑÔð Ý�3—7’7˜;Ñ'Ô'­Ñ.Ô.ðå�c—g’gÐ/Ñ0Ô0µ$Ñ7Ô7ðð 	�Š�{ BÑ'Ô'Ð'Øˆ
õ �#•tÑÔð B¥¨C¯GªG°IÑ,>Ô,>ÅÑ!EÔ!Eð BØ�i”.ˆØˆ	Ø˜GÐ#Ð#Ø '¨Ô 6ˆI�fÑÝ-¸IØ-6Ð#@ 6 6¸DðBð Bð 	Bõ *¸Ð;Ð;Ð;sA   °&A Á
CÁ!C	Á7BÂC	Â
BÂC	ÂBÂ)C	ÃCÃ	Cr  c                óB  — t          ¦   «         }|j                             dd¬¦  «         t          | d<   t	          j        t          j        ¦  «                             ¦   «         | d<   t          j
        | d¬¦  «        dz   }|                     |j        › dt          j        ¦   «         › d	t          j        ¦   «         j        › �¦  «        }	 |                     d
d¬¦  «        5 }|                     |¦  «         |                     ¦   «          t          j        |                     ¦   «         ¦  «         d d d ¦  «         n# 1 swxY w Y   t          j        ||¦  «         	 t          j        t1          |j        ¦  «        t          j        ¦  «        }n# t4          $ r d }Y nw xY w|�C	 t          j        |¦  «         t          j        |¦  «         n# t          j        |¦  «         w xY w	 |                     ¦   «         r|                     ¦   «          nO# t4          $ r Y nCw xY w# 	 |                     ¦   «         r|                     ¦   «          w w # t4          $ r Y w w xY wxY w	 |                     t>          j         t>          j!        z  ¦  «         n# t4          $ r Y nw xY w|S )NTrS  r{  Ú
updated_até   )ÚindentÚ
z.tmp.ú.Úwr+  rV  )"rL  rZ  r[  r�  r   Únowr   ÚutcÚ	isoformatrô   r>  Ú	with_namer'   r    ÚgetpidÚuuidÚuuid4Úhexrb  ÚwriteÚflushÚfsyncrf  Úreplacer%   ÚO_RDONLYrm  Úcloser^  ÚunlinkÚchmodr_  ÚS_IRUSRÚS_IWUSR)r  rx  r?  Útmp_pathÚhandleÚdir_fds         r<   Ú_save_auth_storer¤  #  sÑ  € ÝÑ!Ô!€IØÔ×Ò 4°$ÐÑ7Ô7Ð7Ý.€JˆyÑÝ'œ|­H¬LÑ9Ô9×CÒCÑEÔE€Jˆ|ÑÝŒj˜¨AÐ.Ñ.Ô.°Ñ5€GØ×"Ò" i¤nÐ#[Ð#[½2¼9¹;¼;Ð#[Ð#[ÍÌÉÌÔIYÐ#[Ð#[Ñ\Ô\€HðØ�]Š]˜3¨ˆ]Ñ1Ô1ð 	&°VØ�LŠL˜Ñ!Ô!Ð!Ø�LŠL‰NŒNˆNÝŒH�V—]’]‘_”_Ñ%Ô%Ð%ð	&ð 	&ð 	&ñ 	&ô 	&ð 	&ð 	&ð 	&ð 	&ð 	&ð 	&øøøð 	&ð 	&ð 	&ð 	&õ 	Œ
�8˜YÑ'Ô'Ð'ð	Ý”W�S Ô!1Ñ2Ô2µB´KÑ@Ô@ˆFˆFøÝð 	ð 	ð 	ØˆFˆFˆFð	øøøàÐð!Ý”˜Ñ Ô Ð å”˜Ñ Ô Ð Ð ø•”˜Ñ Ô Ð Ð øøøð	Ø�ŠÑ Ô ð "Ø—’Ñ!Ô!Ð!øøÝð 	ð 	ð 	ØˆDð	øøøøð	Ø�ŠÑ Ô ð "Ø—’Ñ!Ô!Ð!Ð!ð"øåð 	ð 	ð 	ØˆDð	øøøøøøðØ�Š�œ¥t¤|Ñ3Ñ4Ô4Ð4Ð4øÝð ð ð ØˆðøøøàÐsµ   ÃH" Ã"AD>Ä2H" Ä>EÅH" ÅEÅH" Å1F ÆH" ÆF ÆH" ÆF Æ H" Æ&G Æ:H" ÇG%Ç%H" Ç)(H È
HÈHÈ"IÈ$(IÉIÉ
IÉIÉIÉIÉ",J Ê
JÊJúOptional[Dict[str, Any]]c                óÐ   — |                       d¦  «        }t          |t          ¦  «        sd S |                      |¦  «        }t          |t          ¦  «        rt          |¦  «        nd S )Nr|  )r  r»   r:   )r  rÂ   r|  r  s       r<   r  r  G  sZ   € Ø—’˜{Ñ+Ô+€IÝ�i¥Ñ&Ô&ð ØˆtØ�MŠM˜+Ñ&Ô&€EÝ$ U­DÑ1Ô1Ð;�4�‰;Œ;ˆ;°tÐ;r;   r  c                óŠ   — |                       di ¦  «        }t          |t          ¦  «        si | d<   | d         }|||<   || d<   d S ©Nr|  r€  ©r†  r»   r:   )r  rÂ   r  r|  s       r<   r  r  O  sX   € Ø×%Ò% k°2Ñ6Ô6€IÝ�i¥Ñ&Ô&ð ,Ø"$ˆ
�;ÑØ˜{Ô+ˆ	Ø"€IˆkÑØ$/€JÐ Ñ!Ð!Ð!r;   T©Ú
set_activer«  c               ó’   — |                       di ¦  «        }t          |t          ¦  «        si | d<   | d         }|||<   |r|| d<   d S d S r¨  r©  )r  rÂ   r  r«  r|  s        r<   Ú_store_provider_stater­  X  sl   € ð ×%Ò% k°2Ñ6Ô6€IÝ�i¥Ñ&Ô&ð ,Ø"$ˆ
�;ÑØ˜{Ô+ˆ	Ø"€IˆkÑØð 4Ø(3ˆ
Ð$Ñ%Ð%Ð%ð4ð 4r;   c                óv   — | pd                      ¦   «                              ¦   «         }|t          v p|t          v S ©Nr)   )r¼   r¾   rš   r!   ©rÂ   Ú
normalizeds     r<   Úis_known_auth_providerr²  h  s;   € ØÐ# ×*Ò*Ñ,Ô,×2Ò2Ñ4Ô4€JØÕ*Ð*ÐR¨jÕ<RÐ.RÐRr;   c                ó¾   — | pd                      ¦   «                              ¦   «         }|t          v rt          |         j        S t                               || ¦  «        S r¯  )r¼   r¾   rš   r'   r!   r  r°  s     r<   Úget_auth_provider_display_namer´  m  sT   € ØÐ# ×*Ò*Ñ,Ô,×2Ò2Ñ4Ô4€JØÕ&Ð&Ð&Ý  Ô,Ô1Ð1Ý!×%Ò% j°+Ñ>Ô>Ð>r;   c                ó  — t          ¦   «         }|                     d¦  «        }t          |t          ¦  «        si }| €t          |¦  «        S |                     | ¦  «        }t          |t          ¦  «        rt	          |¦  «        ng S )z<Return the persisted credential pool, or one provider slice.r}  )r  r  r»   r:   Úlist)rÂ   r  rÚ   Úprovider_entriess       r<   Úread_credential_poolr¸  t  s~   € å!Ñ#Ô#€JØ�>Š>Ð+Ñ,Ô,€DÝ�d�DÑ!Ô!ð ØˆØÐÝ�D‰zŒzÐØ—x’x Ñ,Ô,ÐÝ%/Ð0@Å$Ñ%GÔ%GÐO�4Ð Ñ!Ô!Ð!ÈRÐOr;   ÚentriesúList[Dict[str, Any]]c                ó  — t          ¦   «         5  t          ¦   «         }|                     d¦  «        }t          |t          ¦  «        si }||d<   t          |¦  «        || <   t          |¦  «        cddd¦  «         S # 1 swxY w Y   dS )z7Persist one provider's credential pool under auth.json.r}  N)rw  r  r  r»   r:   r¶  r¤  )rÂ   r¹  r  rÚ   s       r<   Úwrite_credential_poolr¼  €  sÌ   € å	Ñ	Ô	ð ,ð ,Ý%Ñ'Ô'ˆ
Ø�~Š~Ð/Ñ0Ô0ˆÝ˜$¥Ñ%Ô%ð 	1ØˆDØ,0ˆJÐ(Ñ)Ý  ™MœMˆˆ[ÑÝ 
Ñ+Ô+ð,ð ,ð ,ð ,ñ ,ô ,ð ,ð ,ð ,ð ,ð ,ð ,øøøð ,ð ,ð ,ð ,ð ,ð ,s   �A A<Á<B ÂB rÖ   c                ó  — t          ¦   «         5  t          ¦   «         }|                     di ¦  «        }|                     | g ¦  «        }||vr|                     |¦  «         t	          |¦  «         ddd¦  «         dS # 1 swxY w Y   dS )z@Mark a credential source as suppressed so it won't be re-seeded.Úsuppressed_sourcesN)rw  r  r†  Úappendr¤  ©rÂ   rÖ   r  Ú
suppressedÚprovider_lists        r<   Úsuppress_credential_sourcerÃ  Œ  sÕ   € å	Ñ	Ô	ð %ð %Ý%Ñ'Ô'ˆ
Ø×*Ò*Ð+?ÀÑDÔDˆ
Ø"×-Ò-¨k¸2Ñ>Ô>ˆØ˜Ð&Ð&Ø× Ò  Ñ(Ô(Ð(Ý˜Ñ$Ô$Ð$ð%ð %ð %ñ %ô %ð %ð %ð %ð %ð %ð %ð %øøøð %ð %ð %ð %ð %ð %s   �A#A?Á?BÂBc                óž   — 	 t          ¦   «         }|                     di ¦  «        }||                     | g ¦  «        v S # t          $ r Y dS w xY w)z=Check if a credential source has been suppressed by the user.r¾  F)r  r  rÐ   )rÂ   rÖ   r  rÁ  s       r<   Úis_source_suppressedrÅ  —  sa   € ðÝ%Ñ'Ô'ˆ
Ø—^’^Ð$8¸"Ñ=Ô=ˆ
Ø˜Ÿš¨°RÑ8Ô8Ð8Ð8øÝð ð ð Øˆuˆuðøøøs   ‚;> ¾
AÁAc                ó  — t          ¦   «         5  t          ¦   «         }|                     d¦  «        }t          |t          ¦  «        s	 ddd¦  «         dS |                     | ¦  «        }t          |t
          ¦  «        r||vr	 ddd¦  «         dS |                     |¦  «         |s|                     | d¦  «         |s|                     dd¦  «         t          |¦  «         	 ddd¦  «         dS # 1 swxY w Y   dS )z˜Clear a suppression marker so the source will be re-seeded on the next load.

    Returns True if a marker was cleared, False if no marker existed.
    r¾  NFT)	rw  r  r  r»   r:   r¶  ÚremoveÚpopr¤  rÀ  s        r<   Úunsuppress_credential_sourcerÉ  ¡  sˆ  € õ
 
Ñ	Ô	ð ð Ý%Ñ'Ô'ˆ
Ø—^’^Ð$8Ñ9Ô9ˆ
Ý˜*¥dÑ+Ô+ð 	Øð	ð ð ñ ô ð ð ð ð
 #Ÿš {Ñ3Ô3ˆÝ˜-­Ñ.Ô.ð 	°&ÀÐ2MÐ2MØðð ð ñ ô ð ð ð ð 	×Ò˜VÑ$Ô$Ð$Øð 	.Ø�NŠN˜;¨Ñ-Ô-Ð-Øð 	7Ø�NŠNÐ/°Ñ6Ô6Ð6Ý˜Ñ$Ô$Ð$Øðð ð ñ ô ð ð ð ð ð ð ð øøøð ð ð ð ð ð s   �:C4Á/C4ÂAC4Ã4C8Ã;C8c                ó>   — t          ¦   «         }t          || ¦  «        S )z4Return persisted auth state for a provider, or None.)r  r  )rÂ   r  s     r<   Úget_provider_auth_staterË  ·  s   € å!Ñ#Ô#€JÝ 
¨KÑ8Ô8Ð8r;   c                 óH   — t          ¦   «         } |                      d¦  «        S )z8Return the currently active provider ID from auth store.r€  )r  r  ©r  s    r<   Úget_active_providerrÎ  ½  s    € å!Ñ#Ô#€JØ�>Š>Ð+Ñ,Ô,Ð,r;   c                óú  — | pd                      ¦   «                              ¦   «         }	 t          ¦   «         }|                     d¦  «        pd                      ¦   «                              ¦   «         }|r||k    rdS n# t          $ r Y nw xY w	 ddlm}  |¦   «         }|                     d¦  «        }t          |t          ¦  «        rC|                     d¦  «        pd                      ¦   «                              ¦   «         }||k    rdS n# t          $ r Y nw xY wdh}t                               |¦  «        }	|	r?|	j
        d	k    r4|	j        D ],}
|
|v rŒt          t          j        |
d¦  «        ¦  «        r dS Œ-d
S )a÷  Return True only if the user has explicitly configured this provider.

    Checks:
      1. active_provider in auth.json matches
      2. model.provider in config.yaml matches
      3. Provider-specific env vars are set (e.g. ANTHROPIC_API_KEY)

    This is used to gate auto-discovery of external credentials (e.g.
    Claude Code's ~/.claude/.credentials.json) so they are never used
    without the user's explicit choice.  See PR #4210 for the same
    pattern applied to the setup wizard gate.
    r)   r€  Tr   )Úload_configrï   r  ri   rD   F)r¼   r¾   r  r  rÐ   rŸ   rÐ  r»   r:   rš   r(   r3   rÁ   r    r¡   )rÂ   r±  r  ÚactiverÐ  ÚcfgÚ	model_cfgÚcfg_providerÚ_IMPLICIT_ENV_VARSrÃ   rØ   s              r<   Ú!is_provider_explicitly_configuredrÖ  Ã  sÄ  € ð Ð# ×*Ò*Ñ,Ô,×2Ò2Ñ4Ô4€JðÝ%Ñ'Ô'ˆ
Ø—.’.Ð!2Ñ3Ô3Ð9°r×@Ò@ÑBÔB×HÒHÑJÔJˆØð 	�f 
Ò*Ð*Ø�4øøÝð ð ð Øˆðøøøð	Ø1Ð1Ð1Ð1Ð1Ð1Øˆk‰mŒmˆØ—G’G˜GÑ$Ô$ˆ	Ý�i¥Ñ&Ô&ð 	Ø%ŸMšM¨*Ñ5Ô5Ð;¸×BÒBÑDÔD×JÒJÑLÔLˆLØ˜zÒ)Ð)Ø�tøøÝð ð ð Øˆðøøøð 4Ð4ÐÝ×#Ò# JÑ/Ô/€GØð �7Ô$¨	Ò1Ð1ØÔ/ð 	ð 	ˆGØÐ,Ð,Ð,ØÝ ¥¤¨7°BÑ!7Ô!7Ñ8Ô8ð Ø�t�tðð ˆ5s%   ªAA> Á>
BÂ
BÂA;D Ä
DÄDc                ó(  — t          ¦   «         5  t          ¦   «         }| p|                     d¦  «        }|s	 ddd¦  «         dS |                     di ¦  «        }t          |t          ¦  «        si }||d<   |                     d¦  «        }t          |t          ¦  «        si }||d<   d}||v r||= d}||v r||= d}|                     d¦  «        |k    rd|d<   d}|s	 ddd¦  «         dS t          |¦  «         ddd¦  «         n# 1 swxY w Y   dS )z¦
    Clear auth state for a provider. Used by `hermes logout`.
    If provider_id is None, clears the active provider.
    Returns True if something was cleared.
    r€  NFr|  r}  T)rw  r  r  r»   r:   r¤  )rÂ   r  Útargetr|  rÚ   Úcleareds         r<   Úclear_provider_authrÚ  ö  sÈ  € õ 
Ñ	Ô	ð %ð %Ý%Ñ'Ô'ˆ
ØÐA 
§¢Ð/@Ñ AÔ AˆØð 	Øð	%ð %ð %ñ %ô %ð %ð %ð %ð —N’N ;°Ñ3Ô3ˆ	Ý˜)¥TÑ*Ô*ð 	0ØˆIØ&/ˆJ�{Ñ#à�~Š~Ð/Ñ0Ô0ˆÝ˜$¥Ñ%Ô%ð 	1ØˆDØ,0ˆJÐ(Ñ)àˆØ�YÐÐØ˜&Ð!ØˆGØ�Tˆ>ˆ>Ø�V�ØˆGà�>Š>Ð+Ñ,Ô,°Ò6Ð6Ø,0ˆJÐ(Ñ)ØˆGàð 	Øð;%ð %ð %ñ %ô %ð %ð %ð %õ< 	˜Ñ$Ô$Ð$ð=%ð %ð %ñ %ô %ð %ð %ð %ð %ð %ð %øøøð %ð %ð %ð %ð> ˆ4s   �)DÁBDÃ,DÄDÄDc                 ó˜   — t          ¦   «         5  t          ¦   «         } d| d<   t          | ¦  «         ddd¦  «         dS # 1 swxY w Y   dS )z×
    Clear active_provider in auth.json without deleting credentials.
    Used when the user switches to a non-OAuth provider (OpenRouter, custom)
    so auto-resolution doesn't keep picking the OAuth provider.
    Nr€  )rw  r  r¤  rÍ  s    r<   Údeactivate_providerrÜ    s˜   € õ 
Ñ	Ô	ð %ð %Ý%Ñ'Ô'ˆ
Ø(,ˆ
Ð$Ñ%Ý˜Ñ$Ô$Ð$ð%ð %ð %ñ %ô %ð %ð %ð %ð %ð %ð %ð %øøøð %ð %ð %ð %ð %ð %s   �#?¿AÁAÚprovider_namec                ój  — 	 ddl m}  |¦   «         }|sdS dg}|D ]s}|j        dk    rdnd}|                     d|› d	|j        › �¦  «         |j        r|j                             ¦   «         d         nd}|r|                     d
|› �¦  «         Œtd                     |¦  «        S # t          $ r Y dS w xY w)zßReturn a helpful hint string when provider resolution fails.

    Checks for common config.yaml mistakes (malformed custom_providers, etc.)
    and returns a human-readable diagnostic, or empty string if nothing found.
    r   )Úvalidate_config_structurer)   uC   Config issue detected â€” run 'hermes doctor' for full diagnostics:r$  ÚERRORÚWARNINGz  [z] u       â†’ rŒ  )	rŸ   rß  Úseverityr¿  r  ÚhintÚ
splitlinesÚjoinrÐ   )rÝ  rß  ÚissuesÚlinesÚciÚprefixÚ
first_hints          r<   Ú%_get_config_hint_for_unknown_providerrë  /  s  € ðØ?Ð?Ð?Ð?Ð?Ð?Ø*Ð*Ñ,Ô,ˆØð 	Ø�2àVÐWˆØð 	6ð 	6ˆBØ "¤¨wÒ 6Ð 6�W�W¸IˆFØ�LŠLÐ5˜vÐ5Ð5¨¬Ð5Ð5Ñ6Ô6Ð6à46´GÐC˜œ×+Ò+Ñ-Ô-¨aÔ0Ð0ÀˆJØð 6Ø—’Ð4¨
Ð4Ð4Ñ5Ô5Ð5øØ�yŠy˜ÑÔÐøÝð ð ð Øˆrˆrðøøøs   ‚B$ –BB$ Â$
B2Â1B2)Úexplicit_api_keyÚexplicit_base_urlÚ	requestedrì  rí  c               ód  — | pd                      ¦   «                              ¦   «         }i dd“dd“dd“dd“dd“d	d“d
d“dd“dd“dd“dd“dd“dd“dd“dd“dd“dd“i dd“dd“dd“dd“dd “d!d “d"d “d#d$“d%d$“d&d'“d(d'“d)d'“d*d'“d+d,“d-d,“d.d/“d0d/“¥i d1d/“d2d3“d4d3“d5d6“d7d6“d6d6“d8d8“d9d8“d:d8“d;d<“d=d<“d>d<“d?d@“dAd@“dBdC“dDdC“dEdC“¥dCdFdFdGdGdGdHdHdHdHdIdHdHdHdHdJœ¥}|                     ||¦  «        }|dKk    rdKS |dHk    rdHS |t          v r|S |dk    r6t	          |¦  «        }dL|› dM�}|r	|dN|› �z  }n|dOz  }t          |dP¬Q¦  «        ‚|s|rdKS 	 t          ¦   «         }|                     dR¦  «        }|r/|t          v r&t          |¦  «        }	|	                     dS¦  «        r|S n2# t          $ r%}
t           
                    dT|
¦  «         Y dU}
~
ndU}
~
ww xY wt          t          j        dV¦  «        ¦  «        s!t          t          j        dW¦  «        ¦  «        rdKS t                               ¦   «         D ]J\  }}|j        dXk    rŒ|d'k    rŒ|j        D ]*}t          t          j        |dY¦  «        ¦  «        r|c c S Œ+ŒK	 dZd[lm}  |¦   «         rdCS n# t&          $ r Y nw xY wt          d\d]¬Q¦  «        ‚)^a~  
    Determine which inference provider to use.

    Priority (when requested="auto" or None):
    1. active_provider in auth.json with valid credentials
    2. Explicit CLI api_key/base_url -> "openrouter"
    3. OPENAI_API_KEY or OPENROUTER_API_KEY env vars -> "openrouter"
    4. Provider-specific API keys (GLM, Kimi, MiniMax) -> that provider
    5. Fallback: "openrouter"
    ÚautoÚglmrP   zz-aizz.aiÚzhipuÚgooglerL   zgoogle-geminizgoogle-ai-studiozx-airx   zx.aiÚgrokÚkimirU   zkimi-for-codingÚmoonshotzkimi-cnrY   zmoonshot-cnÚstepr[   zstepfun-coding-planzarcee-air^   Úarceeaizminimax-chinarq   Ú
minimax_cnÚalibaba_codingrn   zalibaba-codingÚalibaba_coding_planÚclaudere   zclaude-codeÚgithubrC   zgithub-copilotzgithub-modelszgithub-modelzgithub-copilot-acprI   zcopilot-acp-agentÚ	aigatewayr   Úvercelzvercel-ai-gatewayÚopencoder‚   Úzenzqwen-portalrA   úqwen-clirB   z
gemini-clizgemini-oauthÚhfr‹   zhugging-facezhuggingface-hubÚmimorŽ   zxiaomi-mimoÚawsr”   zaws-bedrockzamazon-bedrockr…   rˆ   Úcustomr‘   )ÚamazonÚgozopencode-go-subÚkiloz	kilo-codezkilo-gatewayÚlmstudioz	lm-studioÚ	lm_studioÚollamaÚollama_cloudÚvllmÚllamacppz	llama.cppz	llama-cppÚ
openrouterzUnknown provider 'z'.z

z` Check 'hermes model' for available providers, or run 'hermes doctor' to diagnose config issues.Úinvalid_provider)r  r€  Ú	logged_inz)Could not detect active auth provider: %sNÚOPENAI_API_KEYÚOPENROUTER_API_KEYrD   r)   r   ©Úhas_aws_credentialsz¤No inference provider configured. Run 'hermes model' to choose a provider and model, or set an API key (OPENROUTER_API_KEY, OPENAI_API_KEY, etc.) in ~/.hermes/.env.Úno_provider_configured)r¼   r¾   r  rš   rë  r  r  Úget_auth_statusrÐ   rÎ   rü   rÁ   r    r¡   Úitemsr(   r3   Úagent.bedrock_adapterr  ÚImportError)rî  rì  rí  r±  Ú_PROVIDER_ALIASESÚ_config_hintÚmsgr  rÑ  ÚstatusÚeÚpidrÃ   rØ   r  s                  r<   Úresolve_providerr"  H  s–  € ð  Ð%˜v×,Ò,Ñ.Ô.×4Ò4Ñ6Ô6€JðØˆuðØ˜eðØ%+¨UðØ4;¸Uðà�(ðà+¨Xðà7IÈ8ðð 	�ðð ˜uðð '-¨eðð 	�ð	ð  1°-ð	ð BLÈ]ð	ð
 	Ð#ðð
 &3Ð4Dðð 	�	ðð 1°)ðð ð 	�Gðð '¨ðð 	˜ðð (4°\ðð 	Ð/ðð 2BÐCXðð 	Ð4ðð 	�+ðð  -¨kðð 	�)ðð .¨yðð 	˜ðð %3°Iðð 	˜mðð .AÀ-ðð 	�\ðð $,¨\ðð ð ð <OÐP\ðð  	�Nð!ð  %*¨>ð!ð" 	�|ð#ð" &0°ð#ð" @LÈ\ð#ð" \oð  qDð#ð" FRð  Tgð#ð" iwð  yLð#ð$ 	ˆmð%ð$ ,¨]ð%ð$ =NÈ}ð%ð& 	�ð'ð& (¨ð'ð( 	ˆyð)ð( (¨ð)ð( 5EÀið)ð ð( \eØ°Ø¨ÀZà¨8À(Ø¨NØ hØ¨Hð7ð ð Ðð: #×&Ò& z°:Ñ>Ô>€Jà�\Ò!Ð!Øˆ|Ø�XÒÐØˆxØÕ&Ð&Ð&ØÐØ�VÒÐå<¸ZÑHÔHˆØ1 :Ð1Ð1Ð1ˆØð 	vØÐ(˜,Ð(Ð(Ñ(ˆCˆCàÐuÑuˆCÝ˜Ð"4Ð5Ñ5Ô5Ð5ð ð Ð,ð Øˆ|ðEÝ%Ñ'Ô'ˆ
Ø—’Ð 1Ñ2Ô2ˆØð 	�fÕ 1Ð1Ð1Ý$ VÑ,Ô,ˆFØ�zŠz˜+Ñ&Ô&ð Ø�øøÝð Eð Eð EÝ�ŠÐ@À!ÑDÔDÐDÐDÐDÐDÐDÐDøøøøðEøøøõ �œÐ#3Ñ4Ô4Ñ5Ô5ð Õ9JÍ2Ì9ÐUiÑKjÔKjÑ9kÔ9kð Øˆ|õ *×/Ò/Ñ1Ô1ð 
ð 
‰ˆˆWØÔ 	Ò)Ð)Øð �)ÒÐØØÔ/ð 	ð 	ˆGÝ ¥¤¨7°BÑ!7Ô!7Ñ8Ô8ð Ø�
�
�
�
�
ðð	ðØ=Ð=Ð=Ð=Ð=Ð=ØÐÑ Ô ð 	Ø�9ð	øåð ð ð Øˆðøøøõ ð	3ð &ð	ñ ô ð s+   ÅAF# Æ#
GÆ-GÇGÉ>J Ê
JÊJúOptional[float]c                ól  — t          | t          ¦  «        r| sd S |                      ¦   «         }|sd S |                     d¦  «        r|d d…         dz   }	 t	          j        |¦  «        }n# t          $ r Y d S w xY w|j        € |                     t          j
        ¬¦  «        }|                     ¦   «         S )NÚZéÿÿÿÿú+00:00)Útzinfo)r»   r%   r¼   Úendswithr   ÚfromisoformatrÐ   r(  rš  r   r�  Ú	timestamp)r£   ÚtextÚparseds      r<   Ú_parse_iso_timestampr.  ¾  sÈ   € Ý�e�SÑ!Ô!ð ¨ð ØˆtØ�;Š;‰=Œ=€DØð ØˆtØ‡}‚}�SÑÔð $Ø�C�R�CŒy˜8Ñ#ˆðÝÔ'¨Ñ-Ô-ˆˆøÝð ð ð Øˆtˆtðøøøà„}ÐØ—’¥x¤|�Ñ4Ô4ˆØ×ÒÑÔÐs   ÁA* Á*
A8Á7A8Úexpires_at_isoÚskew_secondsc                ó\   — t          | ¦  «        }|€dS |t          j        ¦   «         |z   k    S )NT)r.  rc  )r/  r0  Úexpires_epochs      r<   Ú_is_expiringr3  Ï  s0   € Ý(¨Ñ8Ô8€MØÐØˆtØ�TœY™[œ[¨<Ñ7Ò8Ð8r;   Ú
expires_inc                óh   — 	 t          | ¦  «        }n# t          $ r d}Y nw xY wt          d|¦  «        S )Nr   )r¸   rÐ   rd  )r4  Úttls     r<   Ú_coerce_ttl_secondsr7  Ö  sF   € ðÝ�*‰oŒoˆˆøÝð ð ð Øˆˆˆðøøøåˆq�#‰;Œ;Ðs   ‚ ’! !c                óŠ   — t          | t          ¦  «        sd S |                      ¦   «                              d¦  «        }|r|nd S )Nú/)r»   r%   r¼   Úrstrip)r£   rÀ   s     r<   Ú_optional_base_urlr;  Þ  sC   € Ý�e�SÑ!Ô!ð ØˆtØ�kŠk‰mŒm×"Ò" 3Ñ'Ô'€GØÐ'ˆ7ˆ7 4Ð'r;   c                óÊ  — t          | t          ¦  «        r|                      d¦  «        dk    ri S |                      d¦  «        d         }|ddt	          |¦  «        dz  z
  dz  z  z  }	 t          j        |                     d¦  «        ¦  «        }t          j	        | 
                    d¦  «        ¦  «        }n# t          $ r i cY S w xY wt          |t          ¦  «        r|ni S )Nr�  rŠ  r   Ú=r¶   r+  )r»   r%   ÚcountÚsplitr½   Úbase64Úurlsafe_b64decoder  rô   r‚  ÚdecoderÐ   r:   )rÕ   r?  r4  Úclaimss       r<   Ú_decode_jwt_claimsrD  å  sä   € Ý�e�SÑ!Ô!ð  U§[¢[°Ñ%5Ô%5¸Ò%:Ð%:Øˆ	Ø�kŠk˜#ÑÔ˜qÔ!€GØˆs�q�3˜w™<œ<¨!Ñ+Ñ+¨qÑ0Ñ1Ñ1€GðÝÔ& w§~¢~°gÑ'>Ô'>Ñ?Ô?ˆÝ”˜CŸJšJ wÑ/Ô/Ñ0Ô0ˆˆøÝð ð ð Øˆ	ˆ	ˆ	ðøøøå ­Ñ-Ô-Ð5ˆ6ˆ6°2Ð5s   Á+AB: Â:C	ÃC	rÊ   c                ó
  — t          | ¦  «        }|                     d¦  «        }t          |t          t          f¦  «        sdS t	          |¦  «        t          j        ¦   «         t          dt          |¦  «        ¦  «        z   k    S )NÚexpFr   )rD  r  r»   r¸   rä   rc  rd  )rÊ   r0  rC  rF  s       r<   Ú_codex_access_token_is_expiringrG  ò  si   € Ý Ñ-Ô-€FØ
�*Š*�UÑ
Ô
€CÝ�c�C¥˜<Ñ(Ô(ð ØˆuÝ�‰:Œ:�$œ)™+œ+­¨A­s°<Ñ/@Ô/@Ñ(AÔ(AÑAÒBÐBr;   c                 ó4   — t          j        ¦   «         dz  dz  S )Nz.qwenzoauth_creds.json)r   rF  r1   r;   r<   Ú_qwen_cli_auth_pathrI  ú  s   € ÝŒ9‰;Œ;˜Ñ Ð#5Ñ5Ð5r;   c                 ón  — t          ¦   «         } |                      ¦   «         st          ddd¬¦  «        ‚	 t          j        |                      d¬¦  «        ¦  «        }n+# t          $ r}t          d| › d|› �dd	¬¦  «        |‚d }~ww xY wt          |t          ¦  «        st          d
| › d�dd¬¦  «        ‚|S )NzAQwen CLI credentials not found. Run 'qwen auth qwen-oauth' first.rA   Úqwen_auth_missing©r  r  r+  rV  z)Failed to read Qwen CLI credentials from ú: Úqwen_auth_read_failedz Invalid Qwen CLI credentials in r�  Úqwen_auth_invalid)	rI  r^  r  rô   r‚  rƒ  rÐ   r»   r:   )Ú	auth_pathÚdatar×   s      r<   Ú_read_qwen_cli_tokensrR  þ  s  € Ý#Ñ%Ô%€IØ×ÒÑÔð 
ÝØOØ!Ø$ð
ñ 
ô 
ð 	
ð
ÝŒz˜)×-Ò-°wÐ-Ñ?Ô?Ñ@Ô@ˆˆøÝð ð ð ÝØJ¸	ÐJÐJÀSÐJÐJØ!Ø(ð
ñ 
ô 
ð ð		øøøøðøøøõ �d�DÑ!Ô!ð 
ÝØ;¨yÐ;Ð;Ð;Ø!Ø$ð
ñ 
ô 
ð 	
ð
 €Ks   ¶(A Á
BÁ)BÂBÚtokensc                ód  — t          ¦   «         }|j                             dd¬¦  «         |                     d¦  «        }|                     t          j        | dd¬¦  «        dz   d¬¦  «         t          j        |t          j
        t          j        z  ¦  «         |                     |¦  «         |S )	NTrS  z.tmprŠ  )r‹  r;  rŒ  r+  rV  )rI  rZ  r[  rN  ra  rô   r>  r    rž  r_  rŸ  r   rš  )rS  rP  r¡  s      r<   Ú_save_qwen_cli_tokensrU    s¡   € Ý#Ñ%Ô%€IØÔ×Ò 4°$ÐÑ7Ô7Ð7Ø×$Ò$ VÑ,Ô,€HØ×Ò�œ
 6°!¸tÐDÑDÔDÀtÑKÐV]ÐÑ^Ô^Ð^Ý„HˆX•t”|¥d¤lÑ2Ñ3Ô3Ð3Ø×Ò�YÑÔÐØÐr;   Úexpiry_date_msc                ó¶   — 	 t          | ¦  «        }n# t          $ r Y dS w xY wt          j        ¦   «         t          dt          |¦  «        ¦  «        z   dz  |k    S )NTr   éè  )r¸   rÐ   rc  rd  )rV  r0  Ú	expiry_mss      r<   Ú_qwen_access_token_is_expiringrZ  !  se   € ðÝ˜Ñ'Ô'ˆ	ˆ	øÝð ð ð ØˆtˆtðøøøåŒI‰KŒK�#˜a¥ \Ñ!2Ô!2Ñ3Ô3Ñ3°tÑ;¸yÒHÐHs   ‚ ’
 Ÿ ç      4@c                óþ  — t          |                      dd¦  «        pd¦  «                             ¦   «         }|st          ddd¬¦  «        ‚	 t	          j        t          ddd	œd|t          d
œ|¬¦  «        }n(# t          $ r}t          d|› �dd¬¦  «        |‚d }~ww xY w|j	        dk    r5|j
                             ¦   «         }t          d|rd|› �ndz   dd¬¦  «        ‚	 |                     ¦   «         }n(# t          $ r}t          d|› �dd¬¦  «        |‚d }~ww xY wt          |t          ¦  «        r7t          |                     dd¦  «        pd¦  «                             ¦   «         st          ddd¬¦  «        ‚|                     d¦  «        }	 t          |¦  «        }n# t          $ r d}Y nw xY wt          |                     dd¦  «        pd¦  «                             ¦   «         t          |                     d|¦  «        p|¦  «                             ¦   «         t          |                     d|                      dd¦  «        ¦  «        pd¦  «                             ¦   «         pdt          |                     d|                      dd¦  «        ¦  «        pd¦  «                             ¦   «         t          t          j        ¦   «         dz  ¦  «        t!          d|¦  «        dz  z   dœ}	t#          |	¦  «         |	S )NÚrefresh_tokenr)   z@Qwen OAuth refresh token missing. Re-run 'qwen auth qwen-oauth'.rA   Úqwen_refresh_token_missingrL  ú!application/x-www-form-urlencodedrè   )rê   ÚAccept©Ú
grant_typer]  r,   ©ró   rQ  rã   zQwen OAuth refresh failed: Úqwen_refresh_failedé�  z9Qwen OAuth refresh failed. Re-run 'qwen auth qwen-oauth'.ú Response: z*Qwen OAuth refresh returned invalid JSON: Úqwen_refresh_invalid_jsonrÊ   z1Qwen OAuth refresh response missing access_token.Úqwen_refresh_invalid_responser4  i`T  Ú
token_typeÚBearerÚresource_urlzportal.qwen.airX  r   )rÊ   r]  ri  rk  Úexpiry_date)r%   r  r¼   r  rù   rú   ÚQWEN_OAUTH_TOKEN_URLÚQWEN_OAUTH_CLIENT_IDrÐ   rû   r,  rô   r»   r:   r¸   rc  rd  rU  )
rS  rP  r]  Úresponser×   Úbodyr?  r4  Úexpires_in_secondsÚ	refresheds
             r<   Ú_refresh_qwen_cli_tokensrs  )  s…  € Ý˜Ÿ
š
 ?°BÑ7Ô7Ð=¸2Ñ>Ô>×DÒDÑFÔF€MØð 
ÝØNØ!Ø-ð
ñ 
ô 
ð 	
ðÝ”:Ý à CØ,ðð ð
 .Ø!.Ý1ðð ð
 $ð
ñ 
ô 
ˆˆøõ ð ð ð ÝØ/¨#Ð/Ð/Ø!Ø&ð
ñ 
ô 
ð ð		øøøøðøøøð Ô˜sÒ"Ð"ØŒ}×"Ò"Ñ$Ô$ˆÝØGØ'+Ð3Ð#˜TÐ#Ð#Ð#°ñ5à!Ø&ð	
ñ 
ô 
ð 	
ðØ—-’-‘/”/ˆˆøÝð ð ð ÝØ>¸Ð>Ð>Ø!Ø,ð
ñ 
ô 
ð ð		øøøøðøøøõ �g�tÑ$Ô$ð 
­C°·²¸NÈBÑ0OÔ0OÐ0UÐSUÑ,VÔ,V×,\Ò,\Ñ,^Ô,^ð 
ÝØ?Ø!Ø0ð
ñ 
ô 
ð 	
ð —’˜\Ñ*Ô*€Jð)Ý  ™_œ_ÐÐøÝð )ð )ð )Ø(ÐÐÐð)øøøõ ˜GŸKšK¨¸Ñ;Ô;ÐA¸rÑBÔB×HÒHÑJÔJÝ˜WŸ[š[¨¸-ÑHÔHÐYÈMÑZÔZ×`Ò`ÑbÔbÝ˜'Ÿ+š+ l°F·J²J¸|ÈXÑ4VÔ4VÑWÔWÐcÐ[cÑdÔd×jÒjÑlÔlÐxÐpxÝ˜GŸKšK¨¸¿
º
À>ÐScÑ8dÔ8dÑeÔeÐyÐiyÑzÔz÷  Aò  Añ  Cô  CÝ�4œ9™;œ;¨Ñ-Ñ.Ô.µ°QÐ8JÑ1KÔ1KÈdÑ1RÑRðð €Iõ ˜)Ñ$Ô$Ð$ØÐsB   Á)A7 Á7
BÂBÂBÃ C5 Ã5
DÃ?DÄDÆF! Æ!F0Æ/F0F)Úforce_refreshÚrefresh_if_expiringÚrefresh_skew_secondsrt  ru  rv  c           	     óœ  — t          ¦   «         }t          |                     dd¦  «        pd¦  «                             ¦   «         }t	          | ¦  «        }|s%|r#t          |                     d¦  «        |¦  «        }|rFt          |¦  «        }t          |                     dd¦  «        pd¦  «                             ¦   «         }|st          ddd¬¦  «        ‚t          j	        dd¦  «                             ¦   «          
                    d	¦  «        pt          }d||d
|                     d¦  «        t          t          ¦   «         ¦  «        dœS )NrÊ   r)   rl  z?Qwen OAuth access token missing. Re-run 'qwen auth qwen-oauth'.rA   Úqwen_access_token_missingrL  ÚHERMES_QWEN_BASE_URLr9  r  )r  rö   rD   rÖ   Úexpires_at_msrx  )rR  r%   r  r¼   r¹   rZ  rs  r  r    r¡   r:  ÚDEFAULT_QWEN_BASE_URLrI  )rt  ru  rv  rS  rÊ   Úshould_refreshrö   s          r<   Ú resolve_qwen_runtime_credentialsr}  q  sP  € õ #Ñ$Ô$€FÝ�v—z’z .°"Ñ5Ô5Ð;¸Ñ<Ô<×BÒBÑDÔD€LÝ˜-Ñ(Ô(€NØð iÐ1ð iÝ7¸¿
º
À=Ñ8QÔ8QÐSgÑhÔhˆØð IÝ)¨&Ñ1Ô1ˆÝ˜6Ÿ:š: n°bÑ9Ô9Ð?¸RÑ@Ô@×FÒFÑHÔHˆØð 
ÝØMØ!Ø,ð
ñ 
ô 
ð 	
õ ŒyÐ/°Ñ4Ô4×:Ò:Ñ<Ô<×CÒCÀCÑHÔHÐaÕLa€Hà ØØØØŸš MÑ2Ô2ÝÕ,Ñ.Ô.Ñ/Ô/ðð ð r;   c                 óJ  — t          ¦   «         } 	 t          d¬¦  «        }dt          | ¦  «        |                     d¦  «        |                     d¦  «        |                     d¦  «        dœS # t          $ r*}dt          | ¦  «        t          |¦  «        dœcY d }~S d }~ww xY w)	NF)ru  TrÖ   rD   rz  )r  rx  rÖ   rD   rz  ©r  rx  r$  )rI  r}  r%   r  r  )rP  Úcredsr×   s      r<   Úget_qwen_auth_statusr�  ‘  sÈ   € Ý#Ñ%Ô%€Ið
Ý0ÀUÐKÑKÔKˆàÝ˜Y™œØ—i’i Ñ)Ô)Ø—y’y Ñ+Ô+Ø"ŸYšY Ñ7Ô7ð
ð 
ð 	
øõ ð 
ð 
ð 
àÝ˜Y™œÝ˜‘X”Xð
ð 
ð 	
ð 	
ð 	
ð 	
ð 	
ð 	
øøøøð
øøøs   �AA. Á.
B"Á8BÂB"ÂB"©rt  c           	     óŽ  — 	 ddl m}m}m}m} n(# t
          $ r}t          d|› �dd¬¦  «        |‚d}~ww xY w	  || ¬¦  «        }n2# |$ r*}t          t          |¦  «        d|j        ¬¦  «        |‚d}~ww xY w |¦   «         }t          }d||d	|r|j
        ndt           |¦   «         ¦  «        |r|j        nd
pd
|r|j        nd
pd
dœS )z2Resolve runtime OAuth creds for google-gemini-cli.r   )ÚGoogleOAuthErrorÚ_credentials_pathÚget_valid_access_tokenÚload_credentialsz&agent.google_oauth is not importable: rB   Úgoogle_oauth_module_missingrL  Nr‚  úgoogle-oauthr)   )r  rö   rD   rÖ   rz  rx  ÚemailÚ
project_id)Úagent.google_oauthr„  r…  r†  r‡  r  r  r%   r  Ú!DEFAULT_GEMINI_CLOUDCODE_BASE_URLÚ
expires_msrŠ  r‹  )	rt  r„  r…  r†  r‡  r×   rÊ   r€  rö   s	            r<   Ú(resolve_gemini_oauth_runtime_credentialsr�  ­  sy  € ð
ð	
ð 	
ð 	
ð 	
ð 	
ð 	
ð 	
ð 	
ð 	
ð 	
ð 	
ð 	
ð 	
øõ ð ð ð ÝØ:°SÐ:Ð:Ø(Ø.ð
ñ 
ô 
ð ð		øøøøðøøøðØ-Ð-¸MÐJÑJÔJˆˆøØð ð ð ÝÝ�‰HŒHØ(Ø”ð
ñ 
ô 
ð ð		øøøøðøøøð ÐÑÔ€EÝ0€Hà'ØØØ Ø.3Ð=˜%Ô*Ð*¸ÝÐ*Ð*Ñ,Ô,Ñ-Ô-Ø!&Ð.�%”+�+¨BÐ5°2Ø+0Ð8�uÔ'Ð'°bÐ?¸Rð	ð 	ð 	s'   ‚ �
4™/¯4¸A ÁA4Á
%A/Á/A4c                 óö   — 	 ddl m} m} n# t          $ r dddœcY S w xY w | ¦   «         } |¦   «         }|�|j        sdt          |¦  «        ddœS d	t          |¦  «        d
|j        |j        |j        |j        dœS )z>Return a status dict for `hermes auth list` / `hermes status`.r   )r…  r‡  Fzagent.google_oauth unavailable)r  r$  Nznot logged inr  Tr‰  )r  rx  rÖ   rD   rz  rŠ  r‹  )	rŒ  r…  r‡  r  rÊ   r%   rŽ  rŠ  r‹  )r…  r‡  rP  r€  s       r<   Úget_gemini_oauth_auth_statusr‘  ×  sÔ   € ðOØJÐJÐJÐJÐJÐJÐJÐJÐJøÝð Oð Oð OØ"Ð-MÐNÐNÐNÐNÐNðOøøøà!Ð!Ñ#Ô#€IØÐÑÔ€EØ€}˜EÔ.€}àÝ˜Y™œØ$ð
ð 
ð 	
ð Ý˜‘^”^Ø ØÔ%ØÔ)Ø”ØÔ&ðð ð s   ‚ ‹œÚ	raw_scopeú	List[str]c                óþ   — | pt                                ¦   «         }d„ |                     ¦   «         D ¦   «         }t          ¦   «         }g }|D ]0}||vr*|                     |¦  «         |                     |¦  «         Œ1|S )Nc                ó   — g | ]}|¯|‘ŒS r1   r1   )Ú.0Úparts     r<   ú
<listcomp>z'_spotify_scope_list.<locals>.<listcomp>ô  s   € Ð:Ð:Ð:�t°TÐ:ˆdÐ:Ð:Ð:r;   )ÚDEFAULT_SPOTIFY_SCOPEr¼   r?  ÚsetÚaddr¿  )r’  Ú
scope_textÚscopesÚseenÚorderedr-   s         r<   Ú_spotify_scope_listr   ò  s‡   € ØÐ4Õ4×;Ò;Ñ=Ô=€JØ:Ð:˜z×/Ò/Ñ1Ô1Ð:Ñ:Ô:€FÝ‘U”U€DØ€GØð "ð "ˆØ˜ÐÐØ�HŠH�U‰OŒOˆOØ�NŠN˜5Ñ!Ô!Ð!øØ€Nr;   c                óF   — d                      t          | ¦  «        ¦  «        S )Nr   )rå  r   )r’  s    r<   Ú_spotify_scope_stringr¢  þ  s   € Ø�8Š8Õ'¨	Ñ2Ô2Ñ3Ô3Ð3r;   Úexplicitc                ó  — ddl m} |  |d¦  «         |d¦  «        t          |t          ¦  «        r|                     d¦  «        nd f}|D ]+}t          |pd¦  «                             ¦   «         }|r|c S Œ,t          ddd	¬
¦  «        ‚)Nr   r�   ÚHERMES_SPOTIFY_CLIENT_IDÚSPOTIFY_CLIENT_IDr,   r)   zPSpotify client_id is required. Set HERMES_SPOTIFY_CLIENT_ID or pass --client-id.r   Úspotify_client_id_missingrL  )rŸ   rž   r»   r:   r  r%   r¼   r  ©r£  r  rž   Ú
candidatesÚ	candidaterÀ   s         r<   Ú_spotify_client_idr«    sÅ   € ð 0Ð/Ð/Ð/Ð/Ð/ð 	ØˆÐ0Ñ1Ô1ØˆÐ)Ñ*Ô*Ý",¨UµDÑ"9Ô"9ÐCˆ�	Š	�+ÑÔÐ¸tð	€Jð  ð ð ˆ	Ý�i�o 2Ñ&Ô&×,Ò,Ñ.Ô.ˆØð 	ØˆNˆNˆNð	å
ØZØØ(ðñ ô ð r;   c                ó  — ddl m} |  |d¦  «         |d¦  «        t          |t          ¦  «        r|                     d¦  «        nd t
          f}|D ]+}t          |pd¦  «                             ¦   «         }|r|c S Œ,t
          S )Nr   r�   ÚHERMES_SPOTIFY_REDIRECT_URIÚSPOTIFY_REDIRECT_URIÚredirect_urir)   )rŸ   rž   r»   r:   r  ÚDEFAULT_SPOTIFY_REDIRECT_URIr%   r¼   r¨  s         r<   Ú_spotify_redirect_urir±    s®   € ð 0Ð/Ð/Ð/Ð/Ð/ð 	ØˆÐ3Ñ4Ô4ØˆÐ,Ñ-Ô-Ý%/°µtÑ%<Ô%<ÐFˆ�	Š	�.Ñ!Ô!Ð!À$Ý$ð€Jð  ð ð ˆ	Ý�i�o 2Ñ&Ô&×,Ò,Ñ.Ô.ˆØð 	ØˆNˆNˆNð	å'Ð'r;   c                ó  — ddl m}  |d¦  «        t          | t          ¦  «        r|                      d¦  «        nd t
          f}|D ]>}t          |pd¦  «                             ¦   «                              d¦  «        }|r|c S Œ?t
          S )Nr   r�   ÚHERMES_SPOTIFY_API_BASE_URLÚapi_base_urlr)   r9  )	rŸ   rž   r»   r:   r  ÚDEFAULT_SPOTIFY_API_BASE_URLr%   r¼   r:  ©r  rž   r©  rª  rÀ   s        r<   Ú_spotify_api_base_urlr·  -  s©   € Ø/Ð/Ð/Ð/Ð/Ð/ð 	ˆÐ3Ñ4Ô4Ý%/°µtÑ%<Ô%<ÐFˆ�	Š	�.Ñ!Ô!Ð!À$Ý$ð€Jð
  ð ð ˆ	Ý�i�o 2Ñ&Ô&×,Ò,Ñ.Ô.×5Ò5°cÑ:Ô:ˆØð 	ØˆNˆNˆNð	å'Ð'r;   c                ó  — ddl m}  |d¦  «        t          | t          ¦  «        r|                      d¦  «        nd t
          f}|D ]>}t          |pd¦  «                             ¦   «                              d¦  «        }|r|c S Œ?t
          S )Nr   r�   Ú HERMES_SPOTIFY_ACCOUNTS_BASE_URLÚaccounts_base_urlr)   r9  )	rŸ   rž   r»   r:   r  Ú!DEFAULT_SPOTIFY_ACCOUNTS_BASE_URLr%   r¼   r:  r¶  s        r<   Ú_spotify_accounts_base_urlr¼  <  sª   € Ø/Ð/Ð/Ð/Ð/Ð/ð 	ˆÐ8Ñ9Ô9Ý*4°U½DÑ*AÔ*AÐKˆ�	Š	Ð%Ñ&Ô&Ð&ÀtÝ)ð€Jð
  ð ð ˆ	Ý�i�o 2Ñ&Ô&×,Ò,Ñ.Ô.×5Ò5°cÑ:Ô:ˆØð 	ØˆNˆNˆNð	å,Ð,r;   é@   Úlengthc                ó®   — t          j        t          j        | ¦  «        ¦  «                             d¦  «        }|                     d¦  «        d d…         S )NÚasciir=  é€   )r@  Úurlsafe_b64encoder    ÚurandomrB  r:  )r¾  r4  s     r<   Ú_spotify_code_verifierrÄ  K  sC   € Ý
Ô
"¥2¤:¨fÑ#5Ô#5Ñ
6Ô
6×
=Ò
=¸gÑ
FÔ
F€CØ�:Š:�c‰?Œ?˜4˜C˜4Ô Ð r;   Úcode_verifierc                óè   — t          j        |                      d¦  «        ¦  «                             ¦   «         }t	          j        |¦  «                             d¦  «                             d¦  «        S )Nr+  rÀ  r=  )r	  r
  r  Údigestr@  rÂ  rB  r:  )rÅ  rÇ  s     r<   Ú_spotify_code_challengerÈ  P  sX   € ÝŒ^˜M×0Ò0°Ñ9Ô9Ñ:Ô:×AÒAÑCÔC€FÝÔ# FÑ+Ô+×2Ò2°7Ñ;Ô;×BÒBÀ3ÑGÔGÐGr;   r,   r¯  r-   Úcode_challengerº  c           
     ó>   — t          | d|||d|dœ¦  «        }|› d|› �S )Nr  ÚS256)r,   Úresponse_typer¯  r-   r  Úcode_challenge_methodrÉ  z/authorize?)r   )r,   r¯  r-   r  rÉ  rº  Úquerys          r<   Ú_spotify_build_authorize_urlrÏ  U  sH   € õ ØØØ$ØØØ!'Ø(ðð ñ ô €Eð  Ð3Ð3¨EÐ3Ð3Ð3r;   útuple[str, int, str]c                óì   — t          | ¦  «        }|j        dk    rt          ddd¬¦  «        ‚|j        pd}|dvrt          ddd¬¦  «        ‚|j        st          d	dd¬¦  «        ‚||j        |j        pd
fS )NÚhttpzHSpotify PKCE redirect_uri must use http://localhost or http://127.0.0.1.r   Úspotify_redirect_invalidrL  r)   >   ú	127.0.0.1Ú	localhostz?Spotify PKCE redirect_uri must point to localhost or 127.0.0.1.zBSpotify PKCE redirect_uri must include an explicit localhost port.r9  )r   Úschemer  ÚhostnameÚportrI  )r¯  r-  Úhosts      r<   Ú_spotify_validate_redirect_urirÚ  j  sº   € Ý�lÑ#Ô#€FØ„}˜ÒÐÝØVØØ+ð
ñ 
ô 
ð 	
ð
 Œ?Ð ˜b€DØÐ-Ð-Ð-ÝØMØØ+ð
ñ 
ô 
ð 	
ð
 Œ;ð 
ÝØPØØ+ð
ñ 
ô 
ð 	
ð
 �”˜fœkÐ0¨SÐ0Ð0r;   Úexpected_pathú3tuple[type[BaseHTTPRequestHandler], dict[str, Any]]c                óH   ‡ ‡— d d d d dœŠ G ˆ ˆfd„dt           ¦  «        }|‰fS )N)r  r  r$  Úerror_descriptionc                  ó&   •— e Zd Zd
ˆ ˆfd„Zdd„Zd	S )ú?_make_spotify_callback_handler.<locals>._SpotifyCallbackHandlerr›   r  c                óê  •— t          | j        ¦  «        }|j        ‰k    rE|                      d¦  «         |                      ¦   «          | j                             d¦  «         d S t          |j        ¦  «        }|                     dd g¦  «        d         ‰d<   |                     dd g¦  «        d         ‰d<   |                     dd g¦  «        d         ‰d<   |                     dd g¦  «        d         ‰d<   |                      d¦  «         |  	                    d	d
¦  «         |                      ¦   «          ‰d         rd}nd}| j                             | 
                    d¦  «        ¦  «         d S )Né”  s
   Not found.r  r   r  r$  rÞ  rõ   rê   ztext/html; charset=utf-8zW<html><body><h1>Spotify authorization failed.</h1>You can close this tab.</body></html>zY<html><body><h1>Spotify authorization received.</h1>You can close this tab.</body></html>r+  )r   rI  Úsend_responseÚend_headersÚwfiler—  r   rÎ  r  Úsend_headerr  )r!  r-  Úparamsrp  rÛ  Úresults       €€r<   Údo_GETzF_make_spotify_callback_handler.<locals>._SpotifyCallbackHandler.do_GET‹  si  ø€ Ý˜dœiÑ(Ô(ˆFØŒ{˜mÒ+Ð+Ø×"Ò" 3Ñ'Ô'Ð'Ø× Ò Ñ"Ô"Ð"Ø”
× Ò  Ñ/Ô/Ð/Ø�å˜fœlÑ+Ô+ˆFØ#ŸZšZ¨°°Ñ7Ô7¸Ô:ˆF�6‰NØ$Ÿjšj¨°4°&Ñ9Ô9¸!Ô<ˆF�7‰OØ$Ÿjšj¨°4°&Ñ9Ô9¸!Ô<ˆF�7‰OØ*0¯*ª*Ð5HÈ4È&Ñ*QÔ*QÐRSÔ*TˆFÐ&Ñ'à×Ò˜sÑ#Ô#Ð#Ø×Ò˜^Ð-GÑHÔHÐHØ×ÒÑÔÐØ�gŒð sØp��àr�ØŒJ×Ò˜TŸ[š[¨Ñ1Ô1Ñ2Ô2Ð2Ð2Ð2r;   Úformatr%   Úargsr   c                ó   — d S r  r1   )r!  rê  rë  s      r<   Úlog_messagezK_make_spotify_callback_handler.<locals>._SpotifyCallbackHandler.log_message¢  s   € ØˆFr;   N©r›   r  )rê  r%   rë  r   r›   r  )r5   r6   r7   ré  rí  )rÛ  rè  s   €€r<   Ú_SpotifyCallbackHandlerrà  Š  sL   ø€ € € € € ð	3ð 	3ð 	3ð 	3ð 	3ð 	3ð 	3ð.	ð 	ð 	ð 	ð 	ð 	r;   rï  )r	   )rÛ  rï  rè  s   ` @r<   Ú_make_spotify_callback_handlerrð  ‚  sc   øø€ àØØØ!ð	ð €Fðð ð ð ð ð ð ð Õ"8ñ ô ð ð6 # FÐ*Ð*r;   ç     €f@©rP  údict[str, Any]c          	     óè  — t          | ¦  «        \  }}}t          |¦  «        \  }} G d„ dt          ¦  «        }	  |||f|¦  «        }n.# t          $ r!}	t	          d|› d|› d|	› �dd¬¦  «        |	‚d }	~	ww xY wt          j        |j        d	d
id¬¦  «        }
|
                     ¦   «          t          j	        ¦   «         t          d|¦  «        z   }	 t          j	        ¦   «         |k     r{|d         s|d         r@||                     ¦   «          |                     ¦   «          |
                     d¬¦  «         S t          j        d
¦  «         t          j	        ¦   «         |k     °{|                     ¦   «          |                     ¦   «          |
                     d¬¦  «         nC# |                     ¦   «          |                     ¦   «          |
                     d¬¦  «         w xY wt	          ddd¬¦  «        ‚)Nc                  ó   — e Zd ZdZdS )ú4_spotify_wait_for_callback.<locals>._ReuseHTTPServerTN)r5   r6   r7   Úallow_reuse_addressr1   r;   r<   Ú_ReuseHTTPServerrö  °  s   € € € € € Ø"ÐÐÐr;   rø  z*Could not bind Spotify callback server on ú:rM  r   Úspotify_callback_bind_failedrL  Úpoll_intervalgš™™™™™¹?T)rØ  ÚkwargsÚdaemonç      @r  r$  rX  ©rã   z?Spotify authorization timed out waiting for the local callback.Úspotify_callback_timeout)rÚ  rð  r
   rm  r  Ú	threadingÚThreadÚserve_foreverÚstartrc  rd  ÚshutdownÚserver_closerå  rp  )r¯  rP  rÙ  rØ  rI  Úhandler_clsrè  rø  Úserverr×   Úthreadrv  s               r<   Ú_spotify_wait_for_callbackr
  ¨  s>  € õ
 6°lÑCÔCÑ€Dˆ$�Ý8¸Ñ>Ô>Ñ€K�ð#ð #ð #ð #ð #�:ñ #ô #ð #ðØ!Ð! 4¨ ,°Ñ<Ô<ˆˆøÝð ð ð ÝØM¸ÐMÐMÀÐMÐMÈÐMÐMØØ/ð
ñ 
ô 
ð ð		øøøøðøøøõ Ô VÔ%9À?ÐTWÐBXÐaeÐfÑfÔf€FØ
‡L‚L�N„N€NÝŒy‰{Œ{�S  oÑ6Ô6Ñ6€Hð!ÝŒi‰kŒk˜HÒ$Ð$Ø�fŒ~ð  ¨¤ð Øð 	�ŠÑÔÐØ×ÒÑÔÐØ�Š˜CˆÑ Ô Ð Ð õ	 ŒJ�s‰OŒOˆOõ Œi‰kŒk˜HÒ$Ð$ð
 	�ŠÑÔÐØ×ÒÑÔÐØ�Š˜CˆÑ Ô Ð Ð øð 	�ŠÑÔÐØ×ÒÑÔÐØ�Š˜CˆÑ Ô Ð Ð øøøÝ
ØIØØ'ðñ ô ð s*   ºA	 Á	
A4ÁA/Á/A4Ã(F Ä5+F ÆA G)Úprevious_stateÚtoken_payloadÚrequested_scoper´  r  c               ót  — t          j        t          j        ¦  «        }t	          |                      dd¦  «        ¦  «        }t          j        |                     ¦   «         |z   t          j        ¬¦  «        }	t          |pi ¦  «        }
|
 	                    |||||t          |                      d¦  «        p|¦  «                             ¦   «         t          |                      dd¦  «        pd¦  «                             ¦   «         pdt          |                      dd¦  «        pd¦  «                             ¦   «         t          |                      d	¦  «        p|
                     d	¦  «        pd¦  «                             ¦   «         |                     ¦   «         |	                     ¦   «         |d
dœ¦  «         |
S )Nr4  r   ©Útzr-   ri  rj  rÊ   r)   r]  Ú
oauth_pkce)r,   r¯  rº  r´  r-   Úgranted_scoperi  rÊ   r]  Úobtained_atÚ
expires_atr4  r(   )r   r�  r   r�  r7  r  Úfromtimestampr+  r:   r=  r%   r¼   r‘  )r  r,   r¯  r  rº  r´  r  r�  r4  r  r  s              r<   Ú_spotify_token_payload_to_stater  Ï  s‹  € õ Œ,•x”|Ñ
$Ô
$€CÝ$ ]×%6Ò%6°|ÀQÑ%GÔ%GÑHÔH€JÝÔ'¨¯ª©¬¸*Ñ(DÍÌÐVÑVÔV€JÝ�Ð% 2Ñ&Ô&€EØ	‡L‚LØØ$Ø.Ø$Ø Ý˜]×.Ò.¨wÑ7Ô7ÐJ¸?ÑKÔK×QÒQÑSÔSÝ˜-×+Ò+¨L¸(ÑCÔCÐOÀxÑPÔP×VÒVÑXÔXÐdÐ\dÝ˜M×-Ò-¨n¸bÑAÔAÐGÀRÑHÔH×NÒNÑPÔPÝØ×Ò˜oÑ.Ô.ð Ø�yŠy˜Ñ)Ô)ðàñ
ô 
÷ Š%‰'Œ'Ø—}’}‘”Ø ×*Ò*Ñ,Ô,Ø Ø!ð#ð ñ ô ð ð& €Lr;   r  c           
     ó  — 	 t          j        |› d�ddi| d|||dœ|¬¦  «        }n(# t          $ r}t          d|› �dd	¬
¦  «        |‚d }~ww xY w|j        dk    r5|j                             ¦   «         }t          d|rd|› �ndz   dd	¬
¦  «        ‚|                     ¦   «         }	t          |	t          ¦  «        r7t          |	                     dd¦  «        pd¦  «                             ¦   «         st          ddd¬
¦  «        ‚|	S )Nú
/api/tokenrê   r_  Úauthorization_code)r,   rb  r  r¯  rÅ  rc  zSpotify token exchange failed: r   Úspotify_token_exchange_failedrL  re  zSpotify token exchange failed.rf  r)   rÊ   z7Spotify token response did not include an access_token.Úspotify_token_exchange_invalid)rù   rú   rÐ   r  rû   r,  r¼   rô   r»   r:   r%   r  )
r,   r  r¯  rÅ  rº  rP  ro  r×   Údetailr?  s
             r<   Ú!_spotify_exchange_code_for_tokensr  ó  su  € ðÝ”:Ø Ð,Ð,Ð,Ø#Ð%HÐIà&Ø2ØØ ,Ø!.ðð ð $ð
ñ 
ô 
ˆˆøõ ð ð ð ÝØ3¨cÐ3Ð3ØØ0ð
ñ 
ô 
ð ð		øøøøðøøøð Ô˜sÒ"Ð"Ø”×$Ò$Ñ&Ô&ˆÝØ,Ø)/Ð7Ð%˜VÐ%Ð%Ð%°Rñ9àØ0ð	
ñ 
ô 
ð 	
ð �mŠm‰oŒo€GÝ�g�tÑ$Ô$ð 
­C°·²¸NÈBÑ0OÔ0OÐ0UÐSUÑ,VÔ,V×,\Ò,\Ñ,^Ô,^ð 
ÝØEØØ1ð
ñ 
ô 
ð 	
ð
 €Ns   ‚#& ¦
A°AÁAc          
     ó†  — t          |                      dd¦  «        pd¦  «                             ¦   «         }|st          dddd¬¦  «        ‚t	          | ¬¦  «        }t          | ¦  «        }	 t          j        |› d	�d
did||dœ|¬¦  «        }n(# t          $ r}t          d|› �dd¬¦  «        |‚d }~ww xY w|j	        dk    r6|j
                             ¦   «         }t          d|rd|› �ndz   ddd¬¦  «        ‚|                     ¦   «         }t          |t          ¦  «        r7t          |                     dd¦  «        pd¦  «                             ¦   «         st          dddd¬¦  «        ‚t          ||t          | ¬¦  «        t          |                      d¦  «        pt           ¦  «        |t#          | ¦  «        | ¬¦  «        S )Nr]  r)   z?Spotify refresh token missing. Run `hermes auth spotify` again.r   Úspotify_refresh_token_missingTr  ©r  r  rê   r_  ra  rc  zSpotify token refresh failed: Úspotify_refresh_failedrL  re  z>Spotify token refresh failed. Run `hermes auth spotify` again.rf  rÊ   z9Spotify refresh response did not include an access_token.Úspotify_refresh_invalidr-   )r,   r¯  r  rº  r´  r  )r%   r  r¼   r  r«  r¼  rù   rú   rÐ   rû   r,  rô   r»   r:   r  r±  r™  r·  )	r  rP  r]  r,   rº  ro  r×   r  r?  s	            r<   Ú_refresh_spotify_oauth_stater#  "  sB  € õ
 ˜Ÿ	š	 /°2Ñ6Ô6Ð<¸"Ñ=Ô=×CÒCÑEÔE€MØð 
ÝØMØØ0Ø!ð	
ñ 
ô 
ð 	
õ #¨Ð/Ñ/Ô/€IÝ2°5Ñ9Ô9ÐðÝ”:Ø Ð,Ð,Ð,Ø#Ð%HÐIà-Ø!.Ø&ðð ð
 $ð	
ñ 	
ô 	
ˆˆøõ ð ð ð ÝØ2¨SÐ2Ð2ØØ)ð
ñ 
ô 
ð ð		øøøøðøøøð Ô˜sÒ"Ð"Ø”×$Ò$Ñ&Ô&ˆÝØLØ)/Ð7Ð%˜VÐ%Ð%Ð%°Rñ9àØ)Ø!ð
ñ 
ô 
ð 	
ð �mŠm‰oŒo€GÝ�g�tÑ$Ô$ð 
­C°·²¸NÈBÑ0OÔ0OÐ0UÐSUÑ,VÔ,V×,\Ò,\Ñ,^Ô,^ð 
ÝØGØØ*Ø!ð	
ñ 
ô 
ð 	
õ +ØØÝ*°Ð7Ñ7Ô7Ý˜EŸIšI gÑ.Ô.ÐGÕ2GÑHÔHØ+Ý*¨5Ñ1Ô1Øðñ ô ð s   Á-!B Â
B4ÂB/Â/B4c                óò  — t          ¦   «         5  t          ¦   «         }t          |d¦  «        }|st          dddd¬¦  «        ‚t	          | ¦  «        }|s%|r#t          |                     d¦  «        |¦  «        }|r1t          |¦  «        }t          |d|d¬¦  «         t          |¦  «         d d d ¦  «         n# 1 swxY w Y   t          |                     d	d
¦  «        pd
¦  «                             ¦   «         }|st          dddd¬¦  «        ‚d||t          |                     dd¦  «        pd¦  «        t          |¦  «        t          |                     d¦  «        p|                     d¦  «        pd
¦  «                             ¦   «         t          |¬¦  «        t          |¬¦  «        |                     d¦  «        t          |                     dd
¦  «        pd
¦  «                             ¦   «         dœ
S )Nr   z>Spotify is not authenticated. Run `hermes auth spotify` first.Úspotify_auth_missingTr  r  Frª  rÊ   r)   z>Spotify access token missing. Run `hermes auth spotify` again.Úspotify_access_token_missingri  rj  r  r-   r   r]  )
r  rÊ   rD   ri  rö   r-   r,   r¯  r  r]  )rw  r  r  r  r¹   r3  r  r#  r­  r¤  r%   r¼   r·  r«  r±  )rt  ru  rv  r  r  r|  rÊ   s          r<   Ú#resolve_spotify_runtime_credentialsr'  b  sK  € õ 
Ñ	Ô	ð )ð )Ý%Ñ'Ô'ˆ
Ý$ Z°Ñ;Ô;ˆØð 	ÝØPØ"Ø+Ø!%ð	ñ ô ð õ ˜mÑ,Ô,ˆØð 	YÐ"5ð 	YÝ)¨%¯)ª)°LÑ*AÔ*AÐCWÑXÔXˆNØð 	)Ý0°Ñ7Ô7ˆEÝ! *¨i¸È5ÐQÑQÔQÐQÝ˜ZÑ(Ô(Ð(ð#)ð )ð )ñ )ô )ð )ð )ð )ð )ð )ð )øøøð )ð )ð )ð )õ& �u—y’y °Ñ4Ô4Ð:¸Ñ;Ô;×AÒAÑCÔC€LØð 
ÝØLØØ/Ø!ð	
ñ 
ô 
ð 	
ð Ø$ØÝ˜%Ÿ)š) L°(Ñ;Ô;ÐG¸xÑHÔHÝ)¨%Ñ0Ô0Ý�U—Y’Y˜Ñ/Ô/ÐK°5·9²9¸WÑ3EÔ3EÐKÈÑLÔL×RÒRÑTÔTÝ'¨eÐ4Ñ4Ô4Ý-°EÐ:Ñ:Ô:Ø—i’i Ñ-Ô-Ý˜UŸYšY ¸Ñ;Ô;ÐA¸rÑBÔB×HÒHÑJÔJðð ð s   �BB8Â8B<Â?B<c            
     ó  — t          d¦  «        } | sddiS |                      d¦  «        }t          |                      dd¦  «        pd¦  «                             ¦   «         }t	          |pt          |d¦  «         ¦  «        |                      dd	¦  «        |                      d
¦  «        |                      d¦  «        |                      d¦  «        p|                      d¦  «        ||                      d¦  «        t	          |¦  «        dœS )Nr   r  Fr  r]  r)   r   r(   r  r,   r¯  r  r-   r´  )r  r(   r,   r¯  r-   r  r´  Úhas_refresh_token)rË  r  r%   r¼   r¹   r3  )r  r  r]  s      r<   Úget_spotify_auth_statusr*  ’  s÷   € Ý# IÑ.Ô.€EØð $Ø˜UÐ#Ð#à—’˜<Ñ(Ô(€JÝ˜Ÿ	š	 /°2Ñ6Ô6Ð<¸"Ñ=Ô=×CÒCÑEÔE€Må˜-ÐJ­|¸JÈÑ/JÔ/JÐ+JÑKÔKØ—Y’Y˜{¨LÑ9Ô9Ø—Y’Y˜{Ñ+Ô+ØŸ	š	 .Ñ1Ô1Ø—’˜?Ñ+Ô+ÐA¨u¯yªy¸Ñ/AÔ/AØ ØŸ	š	 .Ñ1Ô1Ý! -Ñ0Ô0ð	ð 	ð 	r;   Úredirect_uri_hintc                óî  — ddl m} t          ¦   «          t          d¦  «         t          d¦  «         t          d¦  «         t          ¦   «          t          d¦  «         t          d¦  «         t          d¦  «         t          ¦   «          t          dt          › �¦  «         t          ¦   «          t          d	¦  «         t          d
t          › d�¦  «         t          d¦  «         t          d¦  «         t          d¦  «         t          d| › �¦  «         t          d¦  «         t          d¦  «         t          d¦  «         t          d¦  «         t          ¦   «          t          ¦   «         s+	 t          j        t          ¦  «         n# t          $ r Y nw xY w	 t          d¦  «         
                    ¦   «         }n2# t          t          f$ r t          ¦   «          t          d¦  «        ‚w xY w|s5t          ¦   «          t          dt          › d�¦  «         t          d¦  «        ‚ |d|¦  «         | r| t          k    r |d| ¦  «         t          ¦   «          t          d¦  «         t          ¦   «          |S )zÇWalk the user through creating a Spotify developer app, persist the
    resulting client_id to ~/.hermes/.env, and return it.

    Raises SystemExit if the user aborts or submits an empty value.
    r   )Úsave_env_valuezF======================================================================zSpotify first-time setupz=Spotify requires every user to register their own lightweightz>developer app. This takes about two minutes and only has to bezdone once per machine.zFull guide: zSteps:z  1. Opening z in your browser...z$  2. Click 'Create app' and fill in:z1       App name:     anything (e.g. hermes-agent)z       Description:  anythingz       Redirect URI: z       API/SDK:      Web APIz$  3. Agree to the terms, click Save.z9  4. Open the app's Settings page and copy the Client ID.z  5. Paste it below.zSpotify Client ID: zSpotify setup cancelled.zNo Client ID entered. See z for the full guide.z)Spotify setup cancelled: empty Client ID.r¥  r­  z0Saved HERMES_SPOTIFY_CLIENT_ID to ~/.hermes/.env)rŸ   r-  ÚprintÚSPOTIFY_DOCS_URLÚSPOTIFY_DASHBOARD_URLÚ_is_remote_sessionÚ
webbrowserrb  rÐ   Úinputr¼   ÚEOFErrorÚKeyboardInterruptÚ
SystemExitr°  )r+  r-  r4  s      r<   Ú_spotify_interactive_setupr7  ¥  s™  € ð 1Ð0Ð0Ð0Ð0Ð0å	�G„G€GÝ	ˆ(�O„O€OÝ	Ð
$Ñ%Ô%Ð%Ý	ˆ(�O„O€OÝ	�G„G€GÝ	Ð
IÑJÔJÐJÝ	Ð
JÑKÔKÐKÝ	Ð
"Ñ#Ô#Ð#Ý	�G„G€GÝ	Ð
+Õ)Ð
+Ð
+Ñ,Ô,Ð,Ý	�G„G€GÝ	ˆ(�O„O€OÝ	Ð
DÕ/Ð
DÐ
DÐ
DÑEÔEÐEÝ	Ð
0Ñ1Ô1Ð1Ý	Ð
=Ñ>Ô>Ð>Ý	Ð
)Ñ*Ô*Ð*Ý	Ð
5Ð"3Ð
5Ð
5Ñ6Ô6Ð6Ý	Ð
(Ñ)Ô)Ð)Ý	Ð
0Ñ1Ô1Ð1Ý	Ð
EÑFÔFÐFÝ	Ð
 Ñ!Ô!Ð!Ý	�G„G€GåÑÔð ð	ÝŒOÕ1Ñ2Ô2Ð2Ð2øÝð 	ð 	ð 	ØˆDð	øøøð5ÝÐ)Ñ*Ô*×0Ò0Ñ2Ô2ˆˆøÝÕ'Ð(ð 5ð 5ð 5Ý‰ŒˆÝÐ3Ñ4Ô4Ð4ð5øøøð ð FÝ‰ŒˆÝÐQÕ+;ÐQÐQÐQÑRÔRÐRÝÐDÑEÔEÐEð €NÐ-¨sÑ3Ô3Ð3ð ð IÐ.Õ2NÒNÐNØˆÐ4Ð6GÑHÔHÐHå	�G„G€GÝ	Ð
<Ñ=Ô=Ð=Ý	�G„G€GØ€Js   Å/F	 Æ	
FÆFÆ!F< Æ</G+c                óä  — t          d¦  «        pi }t          | dd ¦  «        }	 t          ||¦  «        }nS# t          $ rF}t          |dd¦  «        dk    r‚ t	          t          | dd ¦  «        pt
          ¬¦  «        }Y d }~nd }~ww xY wt          t          | dd ¦  «        |¦  «        }t          t          | dd ¦  «        p|                     d¦  «        ¦  «        }t          |¦  «        }t          |¦  «        }t          | d	d
¦  «         }	t          ¦   «         }
t          |
¦  «        }t          j        ¦   «         j        }t!          ||||||¬¦  «        }t#          d¦  «         t#          d|› �¦  «         t#          d|› �¦  «         t#          d¦  «         t#          ¦   «          t#          d¦  «         t#          |¦  «         t#          ¦   «          t#          dt$          › �¦  «         t#          ¦   «          |	rWt'          ¦   «         sI	 t)          j        |¦  «        }n# t,          $ r d
}Y nw xY w|rt#          d¦  «         nt#          d¦  «         t/          |t1          t          | dd ¦  «        pd¦  «        ¬¦  «        }|                     d¦  «        r/|                     d¦  «        p|d         }t3          d|› �¦  «        ‚|                     d¦  «        |k    rt3          d¦  «        ‚t5          |t7          |                     d¦  «        pd¦  «        ||
|t1          t          | dd ¦  «        pd¦  «        ¬¦  «        }t9          ||||||¬¦  «        }t;          ¦   «         5  t=          ¦   «         }t?          |d|d
¬¦  «         tA          |¦  «        }d d d ¦  «         n# 1 swxY w Y   t#          d ¦  «         t#          d!|› �¦  «         t#          d"¦  «         t#          d#t$          › �¦  «         d S )$Nr   r,   r  r)   r§  r¯  )r+  r-   Ú
no_browserF)r,   r¯  r-   r  rÉ  rº  zStarting Spotify PKCE login...zClient ID: zRedirect URI: zIMake sure this redirect URI is allow-listed in your Spotify app settings.z"Open this URL to authorize Hermes:zFull setup guide: z)Browser opened for Spotify authorization.z<Could not open the browser automatically; use the URL above.rã   rñ  rò  r$  rÞ  zSpotify authorization failed: r  z-Spotify authorization failed: state mismatch.r[  )r,   r  r¯  rÅ  rº  rP  )r,   r¯  r  rº  r´  rª  zSpotify login successful!ú  Auth state: z.  Provider state saved under providers.spotifyz  Docs: )!rË  rÔ   r«  r  r7  r°  r±  r¢  r  r¼  r·  rÄ  rÈ  r”  r•  r–  rÏ  r.  r/  r1  r2  rb  rÐ   r
  rä   r6  r  r%   r  rw  r  r­  r¤  )rë  Úexisting_stateÚexplicit_client_idr,   r×   r¯  r-   rº  r´  Úopen_browserrÅ  rÉ  Ústate_nonceÚauthorize_urlÚopenedÚcallbackr  r  Úspotify_stater  Úsaved_tos                        r<   Úlogin_spotify_commandrD  â  s•  € Ý,¨YÑ7Ô7Ð=¸2€Nõ
 !  {°DÑ9Ô9Ðð
Ý&Ð'9¸>ÑJÔJˆ	ˆ	øÝð 
ð 
ð 
Ý�3˜ Ñ#Ô#Ð'BÒBÐBØÝ.Ý% d¨N¸DÑAÔAÐaÕEað
ñ 
ô 
ˆ	ˆ	ˆ	ˆ	ˆ	ˆ	øøøøð
øøøõ )­°°~ÀtÑ)LÔ)LÈnÑ]Ô]€LÝ!¥'¨$°¸Ñ">Ô">Ð"]À.×BTÒBTÐU\ÑB]ÔB]Ñ^Ô^€EÝ2°>ÑBÔBÐÝ(¨Ñ8Ô8€LÝ˜t \°5Ñ9Ô9Ð9€Lå*Ñ,Ô,€MÝ,¨]Ñ;Ô;€NÝ”*‘,”,Ô"€KÝ0ØØ!ØØØ%Ø+ðñ ô €Mõ 
Ð
*Ñ+Ô+Ð+Ý	Ð
#˜	Ð
#Ð
#Ñ$Ô$Ð$Ý	Ð
)˜<Ð
)Ð
)Ñ*Ô*Ð*Ý	Ð
UÑVÔVÐVÝ	�G„G€GÝ	Ð
.Ñ/Ô/Ð/Ý	ˆ-ÑÔÐÝ	�G„G€GÝ	Ð
1Õ/Ð
1Ð
1Ñ2Ô2Ð2Ý	�G„G€Gàð RÕ.Ñ0Ô0ð Rð	Ý”_ ]Ñ3Ô3ˆFˆFøÝð 	ð 	ð 	ØˆFˆFˆFð	øøøàð 	RÝÐ=Ñ>Ô>Ð>Ð>åÐPÑQÔQÐQå)ØÝ�g d¨I°tÑ<Ô<ÐEÀÑFÔFðñ ô €Hð ‡|‚|�GÑÔð DØ—’Ð1Ñ2Ô2ÐG°h¸wÔ6GˆÝÐB¸&ÐBÐBÑCÔCÐCØ‡|‚|�GÑÔ Ò+Ð+ÝÐHÑIÔIÐIå5ØÝ�—’˜fÑ%Ô%Ð+¨Ñ,Ô,Ø!Ø#Ø+Ý�g d¨I°tÑ<Ô<ÐDÀÑEÔEðñ ô €Mõ 4ØØØ!ØØ+Ø!ðñ ô €Mõ 
Ñ	Ô	ð 0ð 0Ý%Ñ'Ô'ˆ
Ý˜j¨)°]ÈuÐUÑUÔUÐUÝ# JÑ/Ô/ˆð0ð 0ð 0ñ 0ô 0ð 0ð 0ð 0ð 0ð 0ð 0øøøð 0ð 0ð 0ð 0õ
 
Ð
%Ñ&Ô&Ð&Ý	Ð
%˜8Ð
%Ð
%Ñ&Ô&Ð&Ý	Ð
:Ñ;Ô;Ð;Ý	Ð
'Õ%Ð
'Ð
'Ñ(Ô(Ð(Ð(Ð(s8   ¤5 µ
B¿<B Â BÈH ÈH*È)H*Í!1NÎN"Î%N"c                 ól   — t          t          j        d¦  «        pt          j        d¦  «        ¦  «        S )zGDetect if running in an SSH session where webbrowser.open() won't work.Ú
SSH_CLIENTÚSSH_TTY)r¹   r    r¡   r1   r;   r<   r1  r1  B  s)   € å•”	˜,Ñ'Ô'Ð?­2¬9°YÑ+?Ô+?Ñ@Ô@Ð@r;   ©Ú_lockrI  c                óÄ  — | r5t          ¦   «         5  t          ¦   «         }ddd¦  «         n# 1 swxY w Y   nt          ¦   «         }t          |d¦  «        }|st          dddd¬¦  «        ‚|                     d¦  «        }t          |t          ¦  «        st          ddd	d¬¦  «        ‚|                     d
¦  «        }|                     d¦  «        }t          |t          ¦  «        r|                     ¦   «         st          dddd¬¦  «        ‚t          |t          ¦  «        r|                     ¦   «         st          dddd¬¦  «        ‚||                     d¦  «        dœS )zÔRead Codex OAuth tokens from Hermes auth store (~/.hermes/auth.json).
    
    Returns dict with 'tokens' (access_token, refresh_token) and 'last_refresh'.
    Raises AuthError if no Codex tokens are stored.
    Nr?   z?No Codex credentials stored. Run `hermes auth` to authenticate.Úcodex_auth_missingTr  rS  zICodex auth state is missing tokens. Run `hermes auth` to re-authenticate.Úcodex_auth_invalid_shaperÊ   r]  zICodex auth is missing access_token. Run `hermes auth` to re-authenticate.Úcodex_auth_missing_access_tokenúJCodex auth is missing refresh_token. Run `hermes auth` to re-authenticate.Ú codex_auth_missing_refresh_tokenÚlast_refresh)rS  rP  )	rw  r  r  r  r  r»   r:   r%   r¼   )rI  r  r  rS  rÊ   r]  s         r<   Ú_read_codex_tokensrQ  O  sá  € ð ð (ÝÑÔð 	,ð 	,Ý)Ñ+Ô+ˆJð	,ð 	,ð 	,ñ 	,ô 	,ð 	,ð 	,ð 	,ð 	,ð 	,ð 	,øøøð 	,ð 	,ð 	,ð 	,øõ &Ñ'Ô'ˆ
Ý  ¨^Ñ<Ô<€EØð 
ÝØMØ#Ø%Ø!ð	
ñ 
ô 
ð 	
ð �YŠY�xÑ Ô €FÝ�f�dÑ#Ô#ð 
ÝØWØ#Ø+Ø!ð	
ñ 
ô 
ð 	
ð —:’:˜nÑ-Ô-€LØ—J’J˜Ñ/Ô/€MÝ�l¥CÑ(Ô(ð 
°×0BÒ0BÑ0DÔ0Dð 
ÝØWØ#Ø2Ø!ð	
ñ 
ô 
ð 	
õ �m¥SÑ)Ô)ð 
°×1DÒ1DÑ1FÔ1Fð 
ÝØXØ#Ø3Ø!ð	
ñ 
ô 
ð 	
ð ØŸ	š	 .Ñ1Ô1ðð ð s   ‘,¬0³0rP  c                ó~  — |€Dt          j        t          j        ¦  «                             ¦   «                              dd¦  «        }t          ¦   «         5  t          ¦   «         }t          |d¦  «        pi }| |d<   ||d<   d|d<   t          |d|¦  «         t          |¦  «         ddd¦  «         dS # 1 swxY w Y   dS )	zCSave Codex OAuth tokens to Hermes auth store (~/.hermes/auth.json).Nr'  r%  r?   rS  rP  ÚchatgptÚ	auth_mode)r   r�  r   r�  r‘  rš  rw  r  r  r  r¤  )rS  rP  r  r  s       r<   Ú_save_codex_tokensrU  €  s  € àÐÝ”|¥H¤LÑ1Ô1×;Ò;Ñ=Ô=×EÒEÀhÐPSÑTÔTˆÝ	Ñ	Ô	ð %ð %Ý%Ñ'Ô'ˆ
Ý$ Z°Ñ@Ô@ÐFÀBˆØ ˆˆh‰Ø ,ˆˆnÑØ&ˆˆkÑÝ˜Z¨¸Ñ?Ô?Ð?Ý˜Ñ$Ô$Ð$ð%ð %ð %ñ %ô %ð %ð %ð %ð %ð %ð %ð %øøøð %ð %ð %ð %ð %ð %s   ÁAB2Â2B6Â9B6r]  c          	     óT  — ~ t          |t          ¦  «        r|                     ¦   «         st          dddd¬¦  «        ‚t	          j        t          dt          |¦  «        ¦  «        ¦  «        }t	          j        |ddi¬	¦  «        5 }| 	                    t          d
did|t          dœ¬¦  «        }ddd¦  «         n# 1 swxY w Y   |j        dk    �r	d}d|j        › d�}d}	 |                     ¦   «         }	t          |	t          ¦  «        �rŽ|	                     d¦  «        }
t          |
t          ¦  «        r½|
                     d¦  «        p|
                     d¦  «        }t          |t          ¦  «        r(|                     ¦   «         r|                     ¦   «         }|
                     d¦  «        }t          |t          ¦  «        r+|                     ¦   «         rd|                     ¦   «         › �}n§t          |
t          ¦  «        r’|
                     ¦   «         r~|
                     ¦   «         }|	                     d¦  «        p|	                     d¦  «        }t          |t          ¦  «        r+|                     ¦   «         rd|                     ¦   «         › �}n# t           $ r Y nw xY w|dv rd}|dk    rd}d}|j        dv r|sd}t          |d||¬¦  «        ‚	 |                     ¦   «         }n&# t           $ r}t          ddd d¬¦  «        |‚d}~ww xY w|                     d!¦  «        }t          |t          ¦  «        r|                     ¦   «         st          d"dd#d¬¦  «        ‚|                     ¦   «         |                     ¦   «         t#          j        t&          j        ¦  «                             ¦   «                              d$d%¦  «        d&œ}|                     d¦  «        }t          |t          ¦  «        r+|                     ¦   «         r|                     ¦   «         |d<   |S )'z>Refresh Codex OAuth tokens without mutating Hermes auth state.rN  r?   rO  Tr  rþ  r`  rè   )rã   ró   rê   r_  r]  ra  )ró   rQ  Nrõ   Úcodex_refresh_failedz'Codex token refresh failed with status r�  Fr$  r  Útyper  zCodex token refresh failed: rÞ  >   Úinvalid_grantÚinvalid_tokenÚinvalid_requestÚrefresh_token_reusedzÃCodex refresh token was already consumed by another client (e.g. Codex CLI or VS Code extension). Run `codex` in your terminal to generate fresh tokens, then run `hermes auth` to re-authenticate.)i‘  é“  z*Codex token refresh returned invalid JSON.Úcodex_refresh_invalid_jsonrÊ   z6Codex token refresh response was missing access_token.Ú"codex_refresh_missing_access_tokenr'  r%  )rÊ   r]  rP  )r»   r%   r¼   r  rù   ÚTimeoutrd  rä   ÚClientrú   ÚCODEX_OAUTH_TOKEN_URLÚCODEX_OAUTH_CLIENT_IDrû   rô   r:   r  rÐ   r   r�  r   r�  r‘  rš  )rÊ   r]  rP  rã   Úclientro  r  r  r  ÚerrÚerr_objÚnested_codeÚ
nested_msgÚerr_descÚrefresh_payloadr×   Úrefreshed_accessÚupdatedÚnext_refreshs                      r<   Úrefresh_codex_oauth_purern  Ž  s¿  € ð 	Ý�m¥SÑ)Ô)ð 
°×1DÒ1DÑ1FÔ1Fð 
ÝØXØ#Ø3Ø!ð	
ñ 
ô 
ð 	
õ Œm�C ¥U¨?Ñ%;Ô%;Ñ<Ô<Ñ=Ô=€GÝ	Œ˜g°Ð:LÐ/MÐ	NÑ	NÔ	Nð 	
ÐRXØ—;’;Ý!Ø#Ð%HÐIà-Ø!.Ý2ðð ð ñ 
ô 
ˆð	
ð 	
ð 	
ñ 	
ô 	
ð 	
ð 	
ð 	
ð 	
ð 	
ð 	
øøøð 	
ð 	
ð 	
ð 	
ð Ô˜sÒ"Ñ"Ø%ˆØS¸HÔ<PÐSÐSÐSˆØ Ðð	Ø—-’-‘/”/ˆCÝ˜#�tÑ$Ô$ñ TØŸ'š' 'Ñ*Ô*�å˜g¥tÑ,Ô,ð TØ")§+¢+¨fÑ"5Ô"5Ð"L¸¿ºÀVÑ9LÔ9L�KÝ! +­sÑ3Ô3ð 3¸×8IÒ8IÑ8KÔ8Kð 3Ø*×0Ò0Ñ2Ô2˜Ø!(§¢¨YÑ!7Ô!7�JÝ! *­cÑ2Ô2ð V°z×7GÒ7GÑ7IÔ7Ið VØ"UÀ×AQÒAQÑASÔASÐ"UÐ"U˜øå ­Ñ-Ô-ð T°'·-²-±/´/ð TØ"Ÿ=š=™?œ?�DØ"ŸwšwÐ':Ñ;Ô;ÐQ¸s¿wºwÀyÑ?QÔ?Q�HÝ! (­CÑ0Ô0ð T°X·^²^Ñ5EÔ5Eð TØ"SÀÇÂÑAQÔAQÐ"SÐ"S˜øøÝð 	ð 	ð 	ØˆDð	øøøàÐHÐHÐHØ#ÐØÐ)Ò)Ð)ð=ð ð  $Ðð Ô :Ð-Ð-Ð6FÐ-Ø#ÐÝØØ#ØØ-ð	
ñ 
ô 
ð 	
ðØ"Ÿ-š-™/œ/ˆˆøÝð ð ð ÝØ8Ø#Ø-Ø!ð	
ñ 
ô 
ð
 ð	øøøøðøøøð '×*Ò*¨>Ñ:Ô:ÐÝÐ&­Ñ,Ô,ð 
Ð4D×4JÒ4JÑ4LÔ4Lð 
ÝØDØ#Ø5Ø!ð	
ñ 
ô 
ð 	
ð )×.Ò.Ñ0Ô0Ø&×,Ò,Ñ.Ô.Ý œ¥X¤\Ñ2Ô2×<Ò<Ñ>Ô>×FÒFÀxÐQTÑUÔUðð €Gð
 #×&Ò& Ñ7Ô7€LÝ�,¥Ñ$Ô$ð 8¨×);Ò);Ñ)=Ô)=ð 8Ø#/×#5Ò#5Ñ#7Ô#7ˆ�Ñ Ø€Ns=   Â)B:Â:B>ÃB>Ã!F8J Ê
J'Ê&J'ËK0 Ë0
LË:LÌLc           	     ó  — t          t          |                      dd¦  «        pd¦  «        t          |                      dd¦  «        pd¦  «        |¬¦  «        }t          | ¦  «        }|d         |d<   |d         |d<   t	          |¦  «         |S )zzRefresh Codex access token using the refresh token.
    
    Saves the new tokens to Hermes auth store automatically.
    rÊ   r)   r]  rò  )rn  r%   r  r:   rU  )rS  rP  rr  Úupdated_tokenss       r<   Ú_refresh_codex_auth_tokensrq  ö  s–   € õ )ÝˆF�JŠJ�~ rÑ*Ô*Ð0¨bÑ1Ô1ÝˆF�JŠJ�¨Ñ+Ô+Ð1¨rÑ2Ô2Ø'ðñ ô €Iõ
 ˜&‘\”\€NØ%.¨~Ô%>€N�>Ñ"Ø&/°Ô&@€N�?Ñ#å�~Ñ&Ô&Ð&ØÐr;   c                 ó®  — t          j        dd¦  «                             ¦   «         } | s#t          t	          j        ¦   «         dz  ¦  «        } t	          | ¦  «                             ¦   «         dz  }|                     ¦   «         sdS 	 t          j	        | 
                    ¦   «         ¦  «        }|                     d¦  «        }t          |t          ¦  «        sdS |                     d¦  «        }|                     d¦  «        }|r|sdS t          |d	¦  «        rt                               d
|¦  «         dS t          |¦  «        S # t"          $ r Y dS w xY w)z¶Try to read tokens from ~/.codex/auth.json (Codex CLI shared file).
    
    Returns tokens dict if valid and not expired, None otherwise.
    Does NOT write to the shared file.
    Ú
CODEX_HOMEr)   z.codexrB  NrS  rÊ   r]  r   u7   Codex CLI tokens at %s are expired â€” skipping import.)r    r¡   r¼   r%   r   rF  Ú
expanduserÚis_filerô   r‚  rƒ  r  r»   r:   rG  rÎ   rü   rÐ   )Ú
codex_homerP  r?  rS  rÊ   r]  s         r<   Ú_import_codex_cli_tokensrw  	  sZ  € õ ”˜<¨Ñ,Ô,×2Ò2Ñ4Ô4€JØð 1Ý�œ™œ xÑ/Ñ0Ô0ˆ
Ý�ZÑ Ô ×+Ò+Ñ-Ô-°Ñ;€IØ×ÒÑÔð ØˆtðÝ”*˜Y×0Ò0Ñ2Ô2Ñ3Ô3ˆØ—’˜XÑ&Ô&ˆÝ˜&¥$Ñ'Ô'ð 	Ø�4Ø—z’z .Ñ1Ô1ˆØŸ
š
 ?Ñ3Ô3ˆØð 	 =ð 	Ø�4õ +¨<¸Ñ;Ô;ð 	Ý�LŠLØIÈ9ñô ð ð �4Ý�F‰|Œ|ÐøÝð ð ð Øˆtˆtðøøøs%   ÂAE Ã.E Ä
+E Ä7E Å
EÅEc                ó&  — t          ¦   «         }t          |d         ¦  «        }t          |                     dd¦  «        pd¦  «                             ¦   «         }t          t          j        dd¦  «        ¦  «        }t          | ¦  «        }|s|rt          ||¦  «        }|�rt          t          t          t          ¦  «        |dz   ¦  «        ¬¦  «        5  t          d¬	¦  «        }t          |d         ¦  «        }t          |                     dd¦  «        pd¦  «                             ¦   «         }t          | ¦  «        }|s|rt          ||¦  «        }|rGt          ||¦  «        }t          |                     dd¦  «        pd¦  «                             ¦   «         }d
d
d
¦  «         n# 1 swxY w Y   t          j        dd¦  «                             ¦   «                              d¦  «        pt          }d||d|                     d¦  «        ddœS )z@Resolve runtime credentials from Hermes's own Codex token store.rS  rÊ   r)   Ú$HERMES_CODEX_REFRESH_TIMEOUT_SECONDSÚ20rþ  rò  FrH  NÚHERMES_CODEX_BASE_URLr9  r?   zhermes-auth-storerP  rS  )r  rö   rD   rÖ   rP  rT  )rQ  r:   r%   r  r¼   rä   r    r¡   r¹   rG  rw  rd  ÚAUTH_LOCK_TIMEOUT_SECONDSrq  r:  ÚDEFAULT_CODEX_BASE_URL)	rt  ru  rv  rQ  rS  rÊ   Úrefresh_timeout_secondsr|  rö   s	            r<   Ú!resolve_codex_runtime_credentialsr  -	  sZ  € õ ÑÔ€DÝ�$�x”.Ñ!Ô!€FÝ�v—z’z .°"Ñ5Ô5Ð;¸Ñ<Ô<×BÒBÑDÔD€LÝ#¥B¤IÐ.TÐVZÑ$[Ô$[Ñ\Ô\Ðå˜-Ñ(Ô(€NØð ]Ð 3ð ]Ý8¸ÐG[Ñ\Ô\ˆØñ Qå­cµ%Õ8QÑ2RÔ2RÐTkÐnqÑTqÑ.rÔ.rÐsÑsÔsð 	Qð 	QÝ%¨EÐ2Ñ2Ô2ˆDÝ˜$˜xœ.Ñ)Ô)ˆFÝ˜vŸzšz¨.¸"Ñ=Ô=ÐCÀÑDÔD×JÒJÑLÔLˆLå! -Ñ0Ô0ˆNØ"ð eÐ(;ð eÝ!@ÀÐOcÑ!dÔ!d�àð QÝ3°FÐ<SÑTÔT�Ý" 6§:¢:¨n¸bÑ#AÔ#AÐ#GÀRÑHÔH×NÒNÑPÔP�ð	Qð 	Qð 	Qñ 	Qô 	Qð 	Qð 	Qð 	Qð 	Qð 	Qð 	Qøøøð 	Qð 	Qð 	Qð 	Qõ 	Œ	Ð)¨2Ñ.Ô.×4Ò4Ñ6Ô6×=Ò=¸cÑBÔBð 	"Ý!ð ð #ØØØ%ØŸš Ñ0Ô0Øðð ð s   ÃC	F+Æ+F/Æ2F/úbool | ssl.SSLContextc                 óž   — t           j        dk    r<	 ddl} t          j        |                      ¦   «         ¬¦  «        S # t          $ r Y nw xY wdS )a~  Platform-aware default SSL verify for httpx clients.

    On macOS with Homebrew Python, the system OpenSSL cannot locate the
    system trust store and valid public certs fail verification. When
    certifi is importable we pin its bundle explicitly; elsewhere we
    defer to httpx's built-in default (certifi via its own dependency).
    Mirrors the weixin fix in 3a0ec1d93.
    Údarwinr   N©ÚcafileT)ÚsysÚplatformÚcertifiÚsslÚcreate_default_contextÚwherer  )r‡  s    r<   Ú_default_verifyr‹  ^	  s`   € õ „|�xÒÐð	ØˆNˆNˆNÝÔ-°W·]²]±_´_ÐEÑEÔEÐEøÝð 	ð 	ð 	ØˆDð	øøøàˆ4s   ’*= ½
A
Á	A
©ÚinsecureÚ	ca_bundleÚ
auth_stater�  úOptional[bool]rŽ  r�  c                óš  — t          |t          ¦  «        r|                     d¦  «        ni }t          |t          ¦  «        r|ni }| �t          | ¦  «        n"t          |                     dd¦  «        ¦  «        }|pP|                     d¦  «        p;t	          j        d¦  «        p't	          j        d¦  «        pt	          j        d¦  «        }|rdS |rlt          |¦  «        }t          j                             |¦  «        s)t           
                    d|¦  «         t          ¦   «         S t          j        |¬	¦  «        S t          ¦   «         S )
NÚtlsr�  FrŽ  ÚHERMES_CA_BUNDLEÚSSL_CERT_FILEÚREQUESTS_CA_BUNDLEuJ   CA bundle path does not exist: %s â€” falling back to default certificatesrƒ  )r»   r:   r  r¹   r    r¡   r%   rI  ÚisfilerÎ   rÏ   r‹  rˆ  r‰  )r�  rŽ  r�  Ú	tls_stateÚeffective_insecureÚeffective_caÚca_paths          r<   Ú_resolve_verifyr›  p	  sO  € õ *4°JÅÑ)EÔ)EÐM�
—’˜uÑ%Ô%Ð%È2€IÝ'¨	µ4Ñ8Ô8Ð@�	�	¸b€Ið #Ð.�ˆX‰ŒˆÝ�)—-’- 
¨EÑ2Ô2Ñ3Ô3ð ð
 	ð 	+Ø�=Š=˜Ñ%Ô%ð	+åŒ9Ð'Ñ(Ô(ð	+õ Œ9�_Ñ%Ô%ð	+õ Œ9Ð)Ñ*Ô*ð ð ð ØˆuØð :Ý�lÑ#Ô#ˆÝŒw�~Š~˜gÑ&Ô&ð 	%Ý�NŠNØ\Øñô ð õ #Ñ$Ô$Ð$ÝÔ)°Ð9Ñ9Ô9Ð9ÝÑÔÐr;   rd  úhttpx.Clientr*   c                ó  ‡— |                       |› d�d|i|rd|ini ¥¬¦  «        }|                     ¦   «          |                     ¦   «         Šg d¢}ˆfd„|D ¦   «         }|r%t          dd                     |¦  «        › �¦  «        ‚‰S )	zFPOST to the device code endpoint. Returns device_code, user_code, etc.z/api/oauth/device/coder,   r-   ©rQ  )Údevice_codeÚ	user_codeÚverification_uriÚverification_uri_completer4  Úintervalc                ó   •— g | ]}|‰v¯|‘Œ	S r1   r1   )r–  ÚfrQ  s     €r<   r˜  z(_request_device_code.<locals>.<listcomp>¬	  s   ø€ Ð;Ð;Ð;�Q¨Q°d¨]¨]ˆq¨]¨]¨]r;   z%Device code response missing fields: z, )rú   Úraise_for_statusrô   rÍ   rå  )rd  r*   r,   r-   ro  Úrequired_fieldsÚmissingrQ  s          @r<   Ú_request_device_coder©  —	  sÈ   ø€ ð �{Š{ØÐ2Ð2Ð2à˜ð
à#(Ð0�˜ÐÐ¨bð
ð ñ ô €Hð ×ÒÑÔÐØ�=Š=‰?Œ?€Dðð ð €Oð <Ð;Ð;Ð;˜/Ð;Ñ;Ô;€GØð WÝÐUÀÇÂÈ7ÑASÔASÐUÐUÑVÔVÐVØ€Kr;   rŸ  rû  c                ó&  — t          j         ¦   «         t          d|¦  «        z   }t          dt          |t          ¦  «        ¦  «        }t          j         ¦   «         |k     �r$|                      |› d�d||dœ¬¦  «        }|j        dk    r)|                     ¦   «         }	d|	vrt          d¦  «        ‚|	S 	 |                     ¦   «         }
n1# t          $ r$ | 	                    ¦   «          t          d	¦  «        ‚w xY w|
                     d
d¦  «        }|dk    rt          j        |¦  «         Œâ|dk    r)t          |dz   d¦  «        }t          j        |¦  «         �Œ|
                     d¦  «        pd}t          |› d|› �¦  «        ‚t          d¦  «        ‚)zDPoll the token endpoint until the user approves or the code expires.r   ú/api/oauth/tokenz,urn:ietf:params:oauth:grant-type:device_code)rb  r,   rŸ  rž  rõ   rÊ   z+Token response did not include access_tokenz1Token endpoint returned a non-JSON error responser$  r)   Úauthorization_pendingÚ	slow_downé   rÞ  zUnknown authentication errorrM  z*Timed out waiting for device authorization)rc  rd  ÚminÚ%DEVICE_AUTH_POLL_INTERVAL_CAP_SECONDSrú   rû   rô   rÍ   rÐ   r¦  rH  r  rp  ro  )rd  r*   r,   rŸ  r4  rû  rv  Úcurrent_intervalro  r?  Úerror_payloadÚ
error_codeÚdescriptions                r<   Ú_poll_for_tokenrµ  ²	  sÃ  € õ Œy‰{Œ{�S  JÑ/Ô/Ñ/€HÝ˜1�c -Õ1VÑWÔWÑXÔXÐå
Œ)‰+Œ+˜Ò
 Ñ
 Ø—;’;ØÐ0Ð0Ð0àLØ&Ø*ðð ð ñ 
ô 
ˆð Ô 3Ò&Ð&Ø—m’m‘o”oˆGØ WÐ,Ð,Ý Ð!NÑOÔOÐOØˆNð	TØ$ŸMšM™OœOˆMˆMøÝð 	Tð 	Tð 	TØ×%Ò%Ñ'Ô'Ð'ÝÐRÑSÔSÐSð	Tøøøð #×&Ò& w°Ñ3Ô3ˆ
ØÐ0Ò0Ð0ÝŒJÐ'Ñ(Ô(Ð(ØØ˜Ò$Ð$Ý"Ð#3°aÑ#7¸Ñ<Ô<ÐÝŒJÐ'Ñ(Ô(Ð(Ùà#×'Ò'Ð(;Ñ<Ô<Ð^Ð@^ˆÝ˜jÐ9Ð9¨KÐ9Ð9Ñ:Ô:Ð:å
ÐCÑ
DÔ
DÐDs   Â3C Ã.C6c                ó  — |                       |› d�d||dœ¬¦  «        }|j        dk    r-|                     ¦   «         }d|vrt          ddd	d
¬¦  «        ‚|S 	 |                     ¦   «         }n%# t          $ r}t          ddd
¬¦  «        |‚d }~ww xY wt          |                     dd¦  «        ¦  «        }t          |                     d¦  «        pd¦  «        }	|dv }
|	                     ¦   «         }d|v sd|v rd}	t          |	d||
¬¦  «        ‚)Nr«  r]  )rb  r,   r]  rž  rõ   rÊ   z%Refresh response missing access_tokenr=   rZ  Tr  zRefresh token exchange failed©r  r  r$  rY  rÞ  ¾   rY  rZ  Úreusezreuse detecteduá  Nous Portal detected refresh-token reuse and revoked this session.
This usually means an external process (monitoring script, custom self-heal hook, or another Hermes install sharing ~/.hermes/auth.json) called POST /api/oauth/token with Hermes's refresh token without persisting the rotated token back.
Nous refresh tokens are single-use â€” only Hermes may call the refresh endpoint. For health checks, use `hermes auth status` instead.
Re-authenticate with: hermes auth add nous)rú   rû   rô   r  rÐ   r%   r  r¾   )rd  r*   r,   r]  ro  r?  r²  r×   r  r´  ÚreloginÚlowereds               r<   Ú_refresh_access_tokenr¼  ç	  s„  € ð �{Š{ØÐ,Ð,Ð,à)Ø"Ø*ð
ð 
ð ñ ô €Hð Ô˜sÒ"Ð"Ø—-’-‘/”/ˆØ Ð(Ð(ÝÐCØ%+°/ÐTXðZñ Zô Zð ZàˆðIØ Ÿš™œˆˆøÝð Ið Ið IÝÐ7Ø!'¸$ð@ñ @ô @ØEHð	IøøøøðIøøøõ ˆ}× Ò  ¨/Ñ:Ô:Ñ;Ô;€DÝ�m×'Ò'Ð(;Ñ<Ô<Ð_Ð@_Ñ`Ô`€KØÐ8Ð8€Gð ×ÒÑ!Ô!€GØ�'ÐÐÐ-°Ð8Ð8ð9ð 	õ �K¨&°tÈgÐ
VÑ
VÔ
VÐVs   ÁA- Á-
BÁ7B
Â
BÚmin_ttl_secondsc                ó  — |                       |› d�dd|› �idt          dt          |¦  «        ¦  «        i¬¦  «        }|j        dk    r,|                     ¦   «         }d|vrt          d	d
d¬¦  «        ‚|S 	 |                     ¦   «         }n%# t          $ r}t          dd
d¬¦  «        |‚d}~ww xY wt          |                     dd¦  «        ¦  «        }t          |                     d¦  «        pd¦  «        }	|dv }
t          |	d
||
¬¦  «        ‚)z0Mint (or reuse) a short-lived inference API key.z/api/oauth/agent-keyré   rç   r½  r"   )ró   rô   rõ   rD   zMint response missing api_keyr=   Úserver_errorrL  zAgent key mint request failedNr$  rÞ  r¸  r  )	rú   rd  r¸   rû   rô   r  rÐ   r%   r  )rd  r*   rÊ   r½  ro  r?  r²  r×   r  r´  rº  s              r<   Ú_mint_agent_keyrÀ   
  sa  € ð �{Š{ØÐ0Ð0Ð0Ø Ð":¨LÐ":Ð":Ð;Ø¥ R­¨_Ñ)=Ô)=Ñ!>Ô!>Ð?ð ñ ô €Hð Ô˜sÒ"Ð"Ø—-’-‘/”/ˆØ˜GÐ#Ð#ÝÐ;Ø%+°.ðBñ Bô Bð BàˆðGØ Ÿš™œˆˆøÝð Gð Gð GÝÐ7Ø!'¨nð>ñ >ô >ØCFð	GøøøøðGøøøõ ˆ}× Ò  ¨.Ñ9Ô9Ñ:Ô:€DÝ�m×'Ò'Ð(;Ñ<Ô<Ð_Ð@_Ñ`Ô`€KØÐ8Ð8€GÝ
�K¨&°tÈgÐ
VÑ
VÔ
VÐVs   Á6B Â
B-ÂB(Â(B-)rP  Úverifyr+   rÁ  ú
bool | strc                óx  — t          j        |¦  «        }t          j        |ddi|¬¦  «        5 }|                     |                      d¦  «        › d�dd|› �i¬¦  «        }d	d	d	¦  «         n# 1 swxY w Y   |j        d
k    r�d|j        › �}	 |                     ¦   «         }t          |                     d¦  «        p|                     d¦  «        p|¦  «        }n2# t          $ r%}	t           
                    d|	¦  «         Y d	}	~	nd	}	~	ww xY wt          |dd¬¦  «        ‚|                     ¦   «         }
|
                     d¦  «        }t          |t          ¦  «        sg S g }|D ]–}t          |t          ¦  «        sŒ|                     d¦  «        }t          |t          ¦  «        rT|                     ¦   «         r@|                     ¦   «         }d|                     ¦   «         v rŒ�|                     |¦  «         Œ—dd„}|                     |¬¦  «         t          t                               |¦  «        ¦  «        S )z6Fetch available model IDs from the Nous inference API.r`  rè   ©rã   ró   rÁ  r9  z/modelsré   rç   )ró   Nrõ   z#/models request failed with status rÞ  r$  z'Could not parse error response JSON: %sr=   Úmodels_fetch_failedrL  rQ  r&   ÚhermesÚmidr%   r›   r2   c                ój   — |                       ¦   «         }d|v rd| fS d|v rd|vrd| fS d|v rd| fS d| fS )NÚopusr   ÚproÚsonnetr   é   rŠ  )r¾   )rÇ  Úlows     r<   Ú_model_priorityz*fetch_nous_models.<locals>._model_priorityl
  sX   € Ø�iŠi‰kŒkˆØ�Sˆ=ˆ=Ø�s�8ˆOØ�Cˆ<ˆ<˜H¨CÐ/Ð/Ø�s�8ˆOØ�sˆ?ˆ?Ø�s�8ˆOØ�3ˆxˆr;   ©rÜ   )rÇ  r%   r›   r2   )rù   r`  ra  r  r:  rû   rô   r%   rÐ   rÎ   rü   r  r»   r¶  r:   r¼   r¾   r¿  ÚsortÚfromkeys)r+   rD   rP  rÁ  rã   rd  ro  r´  re  r   r?  rQ  Ú	model_idsÚitemÚmodel_idrÇ  rÎ  s                    r<   Úfetch_nous_modelsrÕ  A
  s˜  € õ Œm˜OÑ,Ô,€GÝ	Œ˜g°Ð:LÐ/MÐV\Ð	]Ñ	]Ô	]ð 
ÐagØ—:’:Ø!×(Ò(¨Ñ-Ô-Ð6Ð6Ð6Ø$Ð&9°Ð&9Ð&9Ð:ð ñ 
ô 
ˆð
ð 
ð 
ñ 
ô 
ð 
ð 
ð 
ð 
ð 
ð 
øøøð 
ð 
ð 
ð 
ð Ô˜sÒ"Ð"ØR¸HÔ<PÐRÐRˆð	GØ—-’-‘/”/ˆCÝ˜cŸgšgÐ&9Ñ:Ô:Ð]¸c¿gºgÀgÑ>NÔ>NÐ]ÐR]Ñ^Ô^ˆKˆKøÝð 	Gð 	Gð 	GÝ�LŠLÐBÀAÑFÔFÐFÐFÐFÐFÐFÐFøøøøð	Gøøøå˜¨fÐ;PÐQÑQÔQÐQà�mŠm‰oŒo€GØ�;Š;�vÑÔ€DÝ�d�DÑ!Ô!ð Øˆ	à€IØð 	"ð 	"ˆÝ˜$¥Ñ%Ô%ð 	ØØ—8’8˜D‘>”>ˆÝ�h¥Ñ$Ô$ð 	"¨¯ªÑ)9Ô)9ð 	"Ø—.’.Ñ"Ô"ˆCà˜3Ÿ9š9™;œ;Ð&Ð&ØØ×Ò˜SÑ!Ô!Ð!øðð ð ð ð ‡N‚N�€NÑ'Ô'Ð'Ý•—’˜iÑ(Ô(Ñ)Ô)Ð)s*   ®3A-Á-A1Á4A1ÂAC Ã
DÃ&DÄDc                óÊ   — |                       d¦  «        }t          |t          ¦  «        r|                     ¦   «         sdS t	          |                       d¦  «        |¦  «         S )NÚ	agent_keyFÚagent_key_expires_at)r  r»   r%   r¼   r3  )r  r½  rÜ   s      r<   Ú_agent_key_is_usablerÙ  z
  sY   € Ø
�)Š)�KÑ
 Ô
 €CÝ�c�3ÑÔð  s§y¢y¡{¤{ð ØˆuÝ˜EŸIšIÐ&<Ñ=Ô=¸ÑOÔOÐOÐOr;   )rP  r�  rŽ  rv  c                óú  — t          ¦   «         5  t          ¦   «         }t          |d¦  «        }|st          ddd¬¦  «        ‚t	          |                     d¦  «        ¦  «        p.t          j        d¦  «        pt          j        d¦  «        pt           	                    d¦  «        }t          |                     d	¦  «        pt          ¦  «        }t          |||¬
¦  «        }|                     d¦  «        }	|                     d¦  «        }
t          |	t          ¦  «        r|	st          ddd¬¦  «        ‚t          |                     d¦  «        |¦  «        s|	cddd¦  «         S t          |
t          ¦  «        r|
st          ddd¬¦  «        ‚t          j        | r| nd¦  «        }t          j        |ddi|¬¦  «        5 }t%          ||||
¬¦  «        }ddd¦  «         n# 1 swxY w Y   t'          j        t*          j        ¦  «        }t/          |                     d¦  «        ¦  «        }|d         |d<   |                     d¦  «        p|
|d<   |                     d¦  «        p|                     d¦  «        pd|d<   |                     d¦  «        p|                     d¦  «        |d<   |                     ¦   «         |d<   ||d<   t'          j        |                     ¦   «         |z   t*          j        ¬¦  «                             ¦   «         |d<   ||d<   ||d	<   |du t          |t          ¦  «        r|nddœ|d<   t7          |d|¦  «         t9          |¦  «         |d         cddd¦  «         S # 1 swxY w Y   dS )zKResolve a refresh-aware Nous Portal access token for managed tool gateways.r=   ú&Hermes is not logged into Nous Portal.Tr·  r*   ÚHERMES_PORTAL_BASE_URLÚNOUS_PORTAL_BASE_URLr9  r,   rŒ  rÊ   r]  ú,No access token found for Nous Portal login.r  Nú2Session expired and no refresh token is available.r   r`  rè   rÄ  ©rd  r*   r,   r]  r4  ri  rj  r-   r  r  F©r�  rŽ  r’  )rw  r  r  r  r;  r  r    r¡   ÚDEFAULT_NOUS_PORTAL_URLr:  r%   ÚDEFAULT_NOUS_CLIENT_IDr›  r»   r3  rù   r`  ra  r¼  r   r�  r   r�  r7  r‘  r  r+  r  r¤  )rP  r�  rŽ  rv  r  r  r*   r,   rÁ  rÊ   r]  rã   rd  rr  r�  Ú
access_ttls                   r<   Úresolve_nous_access_tokenrå  �
  sm  € õ 
Ñ	Ô	ð H%ð H%Ý%Ñ'Ô'ˆ
Ý$ Z°Ñ8Ô8ˆàð 	ÝØ8ØØ!%ðñ ô ð õ ˜uŸyšyÐ):Ñ;Ô;Ñ<Ô<ð 'ÝŒyÐ1Ñ2Ô2ð'åŒyÐ/Ñ0Ô0ð'õ 'ß
Š&�‰+Œ+ð 	õ ˜Ÿ	š	 +Ñ.Ô.ÐHÕ2HÑIÔIˆ	Ý ¨(¸iÐTYÐZÑZÔZˆà—y’y Ñ0Ô0ˆØŸ	š	 /Ñ2Ô2ˆÝ˜,­Ñ,Ô,ð 	°Lð 	ÝØ>ØØ!%ðñ ô ð õ ˜EŸIšI lÑ3Ô3Ð5IÑJÔJð 	 Øð=H%ð H%ð H%ð H%ñ H%ô H%ð H%ð H%õ@ ˜-­Ñ-Ô-ð 	°]ð 	ÝØDØØ!%ðñ ô ð õ ”-°?Ð L  ÈÑMÔMˆÝŒ\ØØÐ1Ð2Øð
ñ 
ô 
ð 
	ð Ý-ØØ /Ø#Ø+ð	ñ ô ˆIð
	ð 
	ð 
	ñ 
	ô 
	ð 
	ð 
	ð 
	ð 
	ð 
	ð 
	øøøð 
	ð 
	ð 
	ð 
	õ Œl�8œ<Ñ(Ô(ˆÝ(¨¯ª°|Ñ)DÔ)DÑEÔEˆ
Ø )¨.Ô 9ˆˆnÑØ!*§¢¨Ñ!?Ô!?Ð!PÀ=ˆˆoÑØ'Ÿmšm¨LÑ9Ô9Ð`¸U¿YºYÀ|Ñ=TÔ=TÐ`ÐX`ˆˆlÑØ"Ÿš wÑ/Ô/ÐE°5·9²9¸WÑ3EÔ3Eˆˆg‰Ø"Ÿ}š}™œˆˆmÑØ(ˆˆlÑÝ&Ô4Ø�MŠM‰OŒO˜jÑ(ÝŒ|ð
ñ 
ô 
÷ Š)‰+Œ+ð 	ˆlÑð $3ˆÐÑ Ø&ˆˆkÑà %˜Ý#-¨fµcÑ#:Ô#:ÐD˜˜Àð
ð 
ˆˆe‰õ 	˜Z¨°Ñ7Ô7Ð7Ý˜Ñ$Ô$Ð$Ø�^Ô$ðQH%ð H%ð H%ð H%ñ H%ô H%ð H%ð H%ð H%ð H%ð H%ð H%øøøð H%ð H%ð H%ð H%ð H%ð H%s>   �E	M0Å%AM0Æ?GÇM0ÇG#	Ç#M0Ç&G#	Ç'E<M0Í0M4Í7M4rj  ©ri  r-   r  r  r×  rØ  Úmin_key_ttl_secondsrP  r�  rŽ  rt  Ú
force_mintri  r  r  r×  rØ  rç  rè  c               ó0  — | ||pt           |pt                               d¦  «        |pt                               d¦  «        |pd|pt          |||	|
t          |¦  «        |dœdœ}t          |||¬¦  «        }t          j        |r|nd¦  «        }t          j	        |ddi|¬	¦  «        5 }|s)t          |                     d
¦  «        t          ¦  «        �r{t          ||d         |d         |d         ¬¦  «        }t          j        t           j        ¦  «        }t%          |                     d¦  «        ¦  «        }|d         |d<   |                     d¦  «        p|d         |d<   |                     d¦  «        p|                     d¦  «        pd|d<   |                     d¦  «        p|                     d¦  «        |d<   t'          |                     d¦  «        ¦  «        }|r||d<   |                     ¦   «         |d<   ||d<   t          j        |                     ¦   «         |z   t           j        ¬¦  «                             ¦   «         |d
<   |s,t/          |t1          dt3          |¦  «        ¦  «        ¦  «        �st5          ||d         |d         |¬¦  «        }t          j        t           j        ¦  «        }|                     d¦  «        |d<   |                     d¦  «        |d<   |                     d
¦  «        |d<   |                     d¦  «        |d<   t          |                     dd¦  «        ¦  «        |d <   |                     ¦   «         |d!<   t'          |                     d¦  «        ¦  «        }|r||d<   d"d"d"¦  «         n# 1 swxY w Y   |S )#z4Refresh Nous OAuth state without mutating auth.json.r9  rj  rá  )rÊ   r]  r,   r*   r+   ri  r-   r  r  r×  rØ  r’  rŒ  r   r`  rè   rÄ  r  r*   r,   r]  rà  r4  rÊ   ri  r-   r+   r  r  r"   ©rd  r*   rÊ   r½  rD   r×  Úkey_idÚagent_key_idrØ  Úagent_key_expires_inÚreusedFÚagent_key_reusedÚagent_key_obtained_atN)rã  râ  r:  ÚDEFAULT_NOUS_INFERENCE_URLÚDEFAULT_NOUS_SCOPEr¹   r›  rù   r`  ra  r3  r  Ú!ACCESS_TOKEN_REFRESH_SKEW_SECONDSr¼  r   r�  r   r�  r7  r;  r‘  r  r+  rÙ  rd  r¸   rÀ  )rÊ   r]  r,   r*   r+   ri  r-   r  r  r×  rØ  rç  rP  r�  rŽ  rt  rè  r  rÁ  rã   rd  rr  r�  rä  Úrefreshed_urlÚmint_payloadÚ
minted_urls                              r<   Úrefresh_nous_oauth_purer÷  Ô
  sç  € ð, %Ø&ØÐ8Õ"8Ø+ÐFÕ/F×NÒNÈsÑSÔSØ1ÐOÕ5O×WÒWÐX[Ñ\Ô\Ø Ð, HØÐ,Õ,Ø"Ø ØØ 4å˜X™œØ"ð
ð 
ðð €Eõ"  h¸)ÐPUÐVÑVÔV€FÝŒm¨ÐH˜O˜OÀDÑIÔI€Gå	Œ˜g°Ð:LÐ/MÐV\Ð	]Ñ	]Ô	]ð '9ÐagØð 	�L¨¯ª°<Ñ)@Ô)@ÕBcÑdÔdñ 	Ý-ØØ %Ð&7Ô 8Ø Ô,Ø# OÔ4ð	ñ ô ˆIõ ”,�xœ|Ñ,Ô,ˆCÝ,¨Y¯]ª]¸<Ñ-HÔ-HÑIÔIˆJØ$-¨nÔ$=ˆE�.Ñ!Ø%.§]¢]°?Ñ%CÔ%CÐ%]ÀuÈ_ÔG]ˆE�/Ñ"Ø"+§-¢-°Ñ"=Ô"=Ð"dÀÇÂÈ<ÑAXÔAXÐ"dÐ\dˆE�,ÑØ&Ÿ]š]¨7Ñ3Ô3ÐI°u·y²yÀÑ7IÔ7IˆE�'‰NÝ.¨y¯}ª}Ð=QÑ/RÔ/RÑSÔSˆMØð <Ø.;�Ð*Ñ+Ø#&§=¢=¡?¤?ˆE�-Ñ Ø",ˆE�,ÑÝ"*Ô"8Ø—’‘” *Ñ,µ´ð#ñ #ô #çŠi‰kŒkð �,Ñð ð 	9Õ1°%½¸RÅÐEXÑAYÔAYÑ9ZÔ9ZÑ[Ô[ñ 	9Ý*ØØ %Ð&7Ô 8Ø" >Ô2Ø 3ð	ñ ô ˆLõ ”,�xœ|Ñ,Ô,ˆCØ!-×!1Ò!1°)Ñ!<Ô!<ˆE�+ÑØ$0×$4Ò$4°XÑ$>Ô$>ˆE�.Ñ!Ø,8×,<Ò,<¸\Ñ,JÔ,JˆEÐ(Ñ)Ø,8×,<Ò,<¸\Ñ,JÔ,JˆEÐ(Ñ)Ý(,¨\×-=Ò-=¸hÈÑ-NÔ-NÑ(OÔ(OˆEÐ$Ñ%Ø-0¯]ª]©_¬_ˆEÐ)Ñ*Ý+¨L×,<Ò,<Ð=QÑ,RÔ,RÑSÔSˆJØð 9Ø.8�Ð*Ñ+ðO'9ð '9ð '9ñ '9ô '9ð '9ð '9ð '9ð '9ð '9ð '9øøøð '9ð '9ð '9ð '9ðR €Ls   Â'KNÎNÎN©rç  rP  rt  rè  c               óŠ  — |                       d¦  «        pi }t          |                       dd¦  «        |                       dd¦  «        |                       dd¦  «        |                       dt          ¦  «        |                       dt          ¦  «        |                       d	d
¦  «        |                       dt          ¦  «        |                       d¦  «        |                       d¦  «        |                       d¦  «        |                       d¦  «        |||                      d¦  «        |                      d¦  «        ||¬¦  «        S )zRRefresh Nous OAuth from a state dict. Thin wrapper around refresh_nous_oauth_pure.r’  rÊ   r)   r]  r,   r   r*   r+   ri  rj  r-   r  r  r×  rØ  r�  rŽ  ræ  )r  r÷  râ  rñ  rò  )r  rç  rP  rt  rè  r’  s         r<   Úrefresh_nous_oauth_from_staterú  )  s  € ð �)Š)�EÑ
Ô
Ð
 ˜b€CÝ"Ø�	Š	�. "Ñ%Ô%Ø�	Š	�/ 2Ñ&Ô&Ø�	Š	�+˜|Ñ,Ô,Ø�	Š	Ð#Õ%<Ñ=Ô=Ø�	Š	Ð&Õ(BÑCÔCØ—9’9˜\¨8Ñ4Ô4Ø�iŠi˜Õ!3Ñ4Ô4Ø—I’I˜mÑ,Ô,Ø—9’9˜\Ñ*Ô*Ø—)’)˜KÑ(Ô(Ø"ŸYšYÐ'=Ñ>Ô>Ø/Ø'Ø—’˜Ñ$Ô$Ø—'’'˜+Ñ&Ô&Ø#Øð#ñ ô ð r;   )r÷   r€  r÷   c               óÐ  — ddl m} t          | ¦  «        }|rEt          |¦  «                             ¦   «         r$t          |¦  «                             ¦   «         |d<   t          ¦   «         5  t          ¦   «         }t          |d|¦  «         t          |¦  «         ddd¦  «         n# 1 swxY w Y    |d¦  «        }t          d„ | 
                    ¦   «         D ¦   «         d¦  «        S )u4  Persist minted Nous OAuth credentials as the singleton provider state
    and ensure the credential pool is in sync.

    Nous credentials are read at runtime from two independent locations:

    - ``providers.nous``: singleton state read by
      ``resolve_nous_runtime_credentials()`` during 401 recovery and by
      ``_seed_from_singletons()`` during pool load.
    - ``credential_pool.nous``: used by the runtime ``pool.select()`` path.

    Historically ``hermes auth add nous`` wrote a ``manual:device_code`` pool
    entry only, skipping ``providers.nous``.  When the 24h agent_key TTL
    expired, the recovery path read the empty singleton state and raised
    ``AuthError`` silently (``logger.debug`` at INFO level).

    This helper writes ``providers.nous`` then calls ``load_pool("nous")`` so
    ``_seed_from_singletons`` materialises the canonical ``device_code`` pool
    entry from the singleton.  Re-running login upserts the same entry in
    place; the pool never accumulates duplicate device_code rows.

    ``label`` is an optional user-chosen display name (from
    ``hermes auth add nous --label <name>``).  It gets embedded in the
    singleton state so that ``_seed_from_singletons`` uses it as the pool
    entry's label on every subsequent ``load_pool("nous")`` instead of the
    auto-derived token fingerprint.  When ``None``, the auto-derived label
    via ``label_from_token`` is used (unchanged default behaviour).

    Returns the upserted :class:`PooledCredential` entry (or ``None`` if
    seeding somehow produced no match â€” shouldn't happen).
    r   rÈ   r÷   r=   Nc              3  ó:   K  — | ]}|j         t          k    ¯|V — Œd S r  )rÖ   ÚNOUS_DEVICE_CODE_SOURCE)r–  r   s     r<   ú	<genexpr>z+persist_nous_credentials.<locals>.<genexpr>{  s/   è è € ÐJÐJˆq a¤hÕ2IÒ&IÐ&IˆÐ&IÐ&IÐ&IÐ&IÐJÐJr;   )rÑ   rÉ   r:   r%   r¼   rw  r  r  r¤  Únextr¹  )r€  r÷   rÉ   r  r  rÚ   s         r<   Úpersist_nous_credentialsr   K  s)  € ðF 0Ð/Ð/Ð/Ð/Ð/å�‰KŒK€EØð ,•�U‘”×!Ò!Ñ#Ô#ð ,Ý˜U™œ×)Ò)Ñ+Ô+ˆˆg‰å	Ñ	Ô	ð %ð %Ý%Ñ'Ô'ˆ
Ý˜Z¨°Ñ7Ô7Ð7Ý˜Ñ$Ô$Ð$ð%ð %ð %ñ %ô %ð %ð %ð %ð %ð %ð %øøøð %ð %ð %ð %ð
 ˆ9�VÑÔ€DÝØJÐJ�D—L’L‘N”NÐJÑJÔJØñô ð s   Á+/B&Â&B*Â-B*)rç  rP  r�  rŽ  rè  c                ó²  ‡‡‡— t          dt          | ¦  «        ¦  «        } t          j        ¦   «         j        dd…         Št          ¦   «         5  t          ¦   «         Št          ‰d¦  «        Š‰st          ddd¬¦  «        ‚t          ‰ 
                    d¦  «        ¦  «        p.t          j        d	¦  «        pt          j        d
¦  «        pt                               d¦  «        }t          ‰ 
                    d¦  «        ¦  «        pt          j        d¦  «        pt                               d¦  «        }t!          ‰ 
                    d¦  «        pt"          ¦  «        }dMˆˆˆfd„}t%          ||‰¬¦  «        }	t'          j        |r|nd¦  «        }
t+          d‰t-          |¦  «        | t/          ‰ 
                    d¦  «        ¦  «        ¬¦  «         t'          j        |
ddi|	¬¦  «        5 }‰ 
                    d¦  «        }‰ 
                    d¦  «        }t3          |t           ¦  «        r|st          ddd¬¦  «        ‚t5          ‰ 
                    d¦  «        t6          ¦  «        �rôt3          |t           ¦  «        r|st          ddd¬¦  «        ‚t+          d ‰d!t/          |¦  «        ¬"¦  «         t9          ||||¬#¦  «        }t;          j        t>          j         ¦  «        }tC          | 
                    d$¦  «        ¦  «        }|}|d         ‰d<   | 
                    d¦  «        p|‰d<   | 
                    d%¦  «        p‰ 
                    d%¦  «        pd&‰d%<   | 
                    d'¦  «        p‰ 
                    d'¦  «        ‰d'<   t          | 
                    d¦  «        ¦  «        }|r|}| "                    ¦   «         ‰d(<   |‰d$<   t;          j#        | $                    ¦   «         |z   t>          j         ¬)¦  «         "                    ¦   «         ‰d<   ‰d         }‰d         }t+          d*‰d!t/          |¦  «        t/          |¦  «        ¬+¦  «          |d,¦  «         d-}d}|s%tK          ‰| ¦  «        rd}t+          d.‰¬/¦  «         �nz	 t+          d0‰t/          |¦  «        ¬1¦  «         tM          |||| ¬2¦  «        }�nE# t          $ �r7}t+          d3‰|j'        ¬4¦  «         ‰ 
                    d¦  «        }|j'        d5v �röt3          |t           ¦  «        �rà|�rÝt+          d ‰d6t/          |¦  «        ¬"¦  «         t9          ||||¬#¦  «        }t;          j        t>          j         ¦  «        }tC          | 
                    d$¦  «        ¦  «        }|d         ‰d<   | 
                    d¦  «        p|‰d<   | 
                    d%¦  «        p‰ 
                    d%¦  «        pd&‰d%<   | 
                    d'¦  «        p‰ 
                    d'¦  «        ‰d'<   t          | 
                    d¦  «        ¦  «        }|r|}| "                    ¦   «         ‰d(<   |‰d$<   t;          j#        | $                    ¦   «         |z   t>          j         ¬)¦  «         "                    ¦   «         ‰d<   ‰d         }‰d         }t+          d*‰d6t/          |¦  «        t/          |¦  «        ¬+¦  «          |d7¦  «         tM          |||| ¬2¦  «        }n‚ Y d}~nd}~ww xY w|��t;          j        t>          j         ¦  «        }| 
                    d8¦  «        ‰d9<   | 
                    d:¦  «        ‰d;<   | 
                    d¦  «        ‰d<<   | 
                    d$¦  «        ‰d=<   t-          | 
                    d>d-¦  «        ¦  «        ‰d?<   | "                    ¦   «         ‰d@<   t          | 
                    d¦  «        ¦  «        }|r|}t+          dA‰t-          | 
                    d>d-¦  «        ¦  «        ¬B¦  «         |‰d<   |‰d<   |‰d<   |	d-u t3          |	t           ¦  «        r|	nddCœ‰dD<   ddd¦  «         n# 1 swxY w Y    |dE¦  «         ddd¦  «         n# 1 swxY w Y   ‰ 
                    d9¦  «        }t3          |t           ¦  «        r|st          dFddG¬H¦  «        ‚‰ 
                    d<¦  «        }tQ          |¦  «        }|�1t          dIt          |tS          j)        ¦   «         z
  ¦  «        ¦  «        n!tC          ‰ 
                    d=¦  «        ¦  «        }d||‰ 
                    d;¦  «        |||rdJndKdLœS )Na�  
    Resolve Nous inference credentials for runtime use.

    Ensures access_token is valid (refreshes if needed) and a short-lived
    inference key is present with minimum TTL (mints/reuses as needed).
    Concurrent processes coordinate through the auth store file lock.

    Returns dict with: provider, base_url, api_key, key_id, expires_at,
    expires_in, source ("cache" or "portal").
    r"   Nr,  r=   rÛ  Tr·  r*   rÜ  rÝ  r9  r+   ÚNOUS_INFERENCE_BASE_URLr,   Úreasonr%   r›   r  c                ód  •— 	 t          ‰d‰¦  «         t          ‰¦  «         n8# t          $ r+}t          d‰| t	          |¦  «        j        ¬¦  «         ‚ d }~ww xY wt          d‰| t          ‰                     d¦  «        ¦  «        t          ‰                     d¦  «        ¦  «        ¬¦  «         d S )Nr=   Únous_state_persist_failed)r7  r  Ú
error_typeÚnous_state_persistedr]  rÊ   )r7  r  Úrefresh_token_fpÚaccess_token_fp)r  r¤  rÐ   r@  rX  r5   r-  r  )r  r×   r  r7  r  s     €€€r<   Ú_persist_statez8resolve_nous_runtime_credentials.<locals>._persist_stateª  sÕ   ø€ ð
Ý$ Z°¸Ñ?Ô?Ð?Ý  Ñ,Ô,Ð,Ð,øÝð ð ð ÝØ/Ø +Ø!Ý# C™yœyÔ1ð	ñ ô ð ð øøøøðøøøõ Ø&Ø'ØÝ!3°E·I²I¸oÑ4NÔ4NÑ!OÔ!OÝ 2°5·9²9¸^Ñ3LÔ3LÑ MÔ Mðñ ô ð ð ð s   ƒ $ ¤
A®&AÁArŒ  r   Únous_runtime_credentials_startr]  )r7  rè  rç  r  r`  rè   rÄ  rÊ   rÞ  r  rß  Úrefresh_startÚaccess_expiring)r7  r  r  rà  r4  ri  rj  r-   r  r  Úrefresh_success)r7  r  Úprevious_refresh_token_fpÚnew_refresh_token_fpÚpost_refresh_access_expiringFÚagent_key_reuser6  Ú
mint_start)r7  r	  rê  Ú
mint_error)r7  r  r¸  Úmint_retry_after_invalid_tokenÚpost_refresh_mint_retryrD   r×  rë  rì  rØ  rí  rî  rï  rð  Úmint_success)r7  rî  rá  r’  Ú&resolve_nous_runtime_credentials_finalz*Failed to resolve a Nous inference API keyr¿  rL  r   ÚcacheÚportal)r  rö   rD   rë  r  r4  rÖ   )r  r%   r›   r  )*rd  r¸   r”  r•  r–  rw  r  r  r  r;  r  r    r¡   râ  r:  rñ  r%   rã  r›  rù   r`  r@  r¹   r-  ra  r»   r3  ró  r¼  r   r�  r   r�  r7  r‘  r  r+  rÙ  rÀ  r  r.  rc  )rç  rP  r�  rŽ  rè  r*   r+   r,   r
  rÁ  rã   rd  rÊ   r]  rr  r�  rä  Úprevious_refresh_tokenrô  Úused_cached_keyrõ  r×   Úlatest_refresh_tokenrö  rD   r  r2  r4  r  r7  r  s                               @@@r<   Ú resolve_nous_runtime_credentialsr  €  s  øøø€ õ$ ˜b¥#Ð&9Ñ":Ô":Ñ;Ô;ÐÝ”*‘,”,Ô" 3 B 3Ô'€Kå	Ñ	Ô	ð JAð JAÝ%Ñ'Ô'ˆ
Ý$ Z°Ñ8Ô8ˆàð 	DÝÐDØ%+¸dðDñ Dô Dð Dõ ˜uŸyšyÐ):Ñ;Ô;Ñ<Ô<ð 'ÝŒyÐ1Ñ2Ô2ð'åŒyÐ/Ñ0Ô0ð'õ 'ß
Š&�‰+Œ+ð 	õ ˜uŸyšyÐ)=Ñ>Ô>Ñ?Ô?ð *ÝŒyÐ2Ñ3Ô3ð*å)ß
Š&�‰+Œ+ð	 	õ
 ˜Ÿ	š	 +Ñ.Ô.ÐHÕ2HÑIÔIˆ	ð	ð 	ð 	ð 	ð 	ð 	ð 	ð 	õ( !¨(¸iÐTYÐZÑZÔZˆÝ”-°?Ð L  ÈÑMÔMˆÝØ,Ø#Ý˜JÑ'Ô'Ø 3Ý/°·	²	¸/Ñ0JÔ0JÑKÔKð	
ñ 	
ô 	
ð 	
õ Œ\ '°HÐ>PÐ3QÐZ`ÐaÑaÔað U	ÐekØ Ÿ9š9 ^Ñ4Ô4ˆLØ!ŸIšI oÑ6Ô6ˆMå˜l­CÑ0Ô0ð H¸ð HÝÐ NØ)/À$ðHñ Hô Hð Hõ ˜EŸIšI lÑ3Ô3Õ5VÑWÔWñ (?Ý! -µÑ5Ô5ð L¸]ð LÝ#Ð$XØ-3ÀdðLñ Lô Lð Lõ Ø#Ø +Ø,Ý%7¸Ñ%FÔ%Fð	ñ ô ð õ 2Ø!°?Ø'°}ðñ ô �	õ ”l¥8¤<Ñ0Ô0�Ý0°·²¸|Ñ1LÔ1LÑMÔM�
Ø)6Ð&Ø(1°.Ô(A��nÑ%Ø)2¯ª°Ñ)GÔ)GÐ)XÈ=��oÑ&Ø&/§m¢m°LÑ&AÔ&AÐ&hÀUÇYÂYÈ|ÑE\ÔE\Ð&hÐ`h��lÑ#Ø!*§¢¨wÑ!7Ô!7Ð!M¸5¿9º9ÀWÑ;MÔ;M��g‘Ý 2°9·=²=ÐAUÑ3VÔ3VÑ WÔ W�Ø ð 7Ø)6Ð&Ø'*§}¢}¡¤��mÑ$Ø&0��lÑ#Ý&.Ô&<Ø—M’M‘O”O jÑ0µX´\ð'ñ 'ô 'ç’)‘+”+ð �lÑ#ð  % ^Ô4�Ø % oÔ 6�ÝØ%Ø +Ø,Ý.@ÐAWÑ.XÔ.XÝ);¸MÑ)JÔ)Jðñ ô ð ð �Ð=Ñ>Ô>Ð>ð $ˆOØ59ˆLàð DÕ"6°uÐ>QÑ"RÔ"Rð DØ"&�ÝÐ.¸KÐHÑHÔHÐHÑHð@Ý Ø$Ø$/Ý(:¸<Ñ(HÔ(Hðñ ô ð õ
 $3Ø%°Ø%1ÐCVð$ñ $ô $�L‘Løõ !ð 6ñ 6ð 6Ý Ø$Ø$/Ø œXðñ ô ð ð ,1¯9ª9°_Ñ+EÔ+EÐ(àœÐ$FÐFÑFÝ&Ð';½SÑAÔAñ Gà0ñ Gõ %Ø+Ø(3Ø#CÝ-?Ð@TÑ-UÔ-Uð	ñ ô ð õ %:Ø#)¸?Ø&/Ð?Sð%ñ %ô %˜	õ 'œl­8¬<Ñ8Ô8˜Ý%8¸¿ºÀ|Ñ9TÔ9TÑ%UÔ%U˜
Ø09¸.Ô0I˜˜nÑ-Ø1:·²¸Ñ1OÔ1OÐ1gÐSg˜˜oÑ.Ø.7¯mªm¸LÑ.IÔ.IÐ.pÈUÏYÊYÐWcÑMdÔMdÐ.pÐhp˜˜lÑ+Ø)2¯ª°wÑ)?Ô)?Ð)UÀ5Ç9Â9ÈWÑCUÔCU˜˜g™Ý(:¸9¿=º=ÐI]Ñ;^Ô;^Ñ(_Ô(_˜Ø(ð ?Ø1>Ð.Ø/2¯}ª}©¬˜˜mÑ,Ø.8˜˜lÑ+Ý.6Ô.DØŸMšM™OœO¨jÑ8½X¼\ð/ñ /ô /ç#š)™+œ+ð ˜lÑ+ð (-¨^Ô'<˜Ø(-¨oÔ(>˜Ý$Ø-Ø(3Ø#CÝ6HÐI]Ñ6^Ô6^Ý1CÀMÑ1RÔ1Rðñ ô ð ð '˜Ð'@ÑAÔAÐAå'6Ø#)¸?Ø)5ÐGZð(ñ (ô (˜˜ð
 ð %˜˜˜˜øøøøðc6øøøðp Ñ'Ý”l¥8¤<Ñ0Ô0�Ø%1×%5Ò%5°iÑ%@Ô%@��kÑ"Ø(4×(8Ò(8¸Ñ(BÔ(B��nÑ%Ø0<×0@Ò0@ÀÑ0NÔ0N�Ð,Ñ-Ø0<×0@Ò0@ÀÑ0NÔ0N�Ð,Ñ-Ý,0°×1AÒ1AÀ(ÈEÑ1RÔ1RÑ,SÔ,S�Ð(Ñ)Ø14·²±´�Ð-Ñ.Ý/°×0@Ò0@ÐAUÑ0VÔ0VÑWÔW�
Øð 4Ø)3Ð&ÝØ"Ø +Ý × 0Ò 0°¸5Ñ AÔ AÑBÔBðñ ô ð ð (7ˆEÐ#Ñ$Ø*<ˆEÐ&Ñ'Ø!*ˆE�+Ñà" e˜OÝ'1°&½#Ñ'>Ô'>ÐH˜V˜VÀDðð ˆE�%‰LðeU	ð U	ð U	ñ U	ô U	ð U	ð U	ð U	ð U	ð U	ð U	øøøð U	ð U	ð U	ð U	ðn 	ˆÐ?Ñ@Ô@Ð@ðUJAð JAð JAñ JAô JAð JAð JAð JAð JAð JAð JAøøøð JAð JAð JAð JAðX �iŠi˜Ñ$Ô$€GÝ�g�sÑ#Ô#ð >¨7ð >ÝÐDØ!'¨nð>ñ >ô >ð 	>ð —’Ð1Ñ2Ô2€JÝ(¨Ñ4Ô4€Mð Ð$õ 	ˆA�s�=¥4¤9¡;¤;Ñ.Ñ/Ô/Ñ0Ô0Ð0å  §¢Ð+AÑ!BÔ!BÑCÔCð ð Ø&ØØ—)’)˜NÑ+Ô+Ø Ø Ø,Ð:�'�'°(ðð ð sd   ÁFa6Ç+JaÒ2R<Ò:aÒ<[>ÓH-[9Û4aÛ9[>Û>E
aáa6áa	áa6áa	áa6á6a:á=a:c                 ó   — dd d d d ddœS )NF)r  r*   r+   Úaccess_expires_atrØ  r)  r1   r1   r;   r<   Ú_empty_nous_auth_statusr!  }  s#   € àØØ"Ø!Ø $Ø"ðð ð r;   c                 óÈ  — 	 ddl m}   | d¦  «        }|r|                     ¦   «         st          ¦   «         S t	          |                     ¦   «         ¦  «        }|st          ¦   «         S dd„}t          ||¬	¦  «        }t          |d
d¦  «        pt          |dd¦  «        }|st          ¦   «         S dt          |dd¦  «        pt          |dd¦  «        t          |dd¦  «        pt          |dd¦  «        |t          |dd¦  «        t          |dd¦  «        t          t          |dd¦  «        ¦  «        dt          |dd¦  «        › �dœS # t          $ r t          ¦   «         cY S w xY w)zëBest-effort status from the credential pool.

    This is a fallback only. The auth-store provider state is the runtime source
    of truth because it is what ``resolve_nous_runtime_credentials()`` refreshes
    and mints against.
    r   rÈ   r=   rÛ   r   r›   útuple[float, float, int]c                óÎ   — t          t          | dd ¦  «        ¦  «        pd}t          t          | dd ¦  «        ¦  «        pd}t          t          | dd¦  «        pd¦  «        }||| fS )NrØ  g        r  Úpriorityr   )r.  rÔ   r¸   )rÛ   Ú	agent_expÚ
access_expr%  s       r<   Ú_entry_sort_keyz3_snapshot_nous_pool_status.<locals>._entry_sort_keyš  so   € Ý,­W°UÐ<RÐTXÑ-YÔ-YÑZÔZÐaÐ^aˆIÝ-­g°e¸\È4Ñ.PÔ.PÑQÔQÐXÐUXˆJÝ�7 5¨*°aÑ8Ô8Ð=¸AÑ>Ô>ˆHØ˜z¨H¨9Ð5Ð5r;   rÏ  rÊ   NrË   r)   Tr*   rö   r+   r  rØ  r]  úpool:r÷   Úunknown)r  r*   r+   rÊ   r   rØ  r)  rÖ   )rÛ   r   r›   r#  )
rÑ   rÉ   rÒ   r!  r¶  r¹  rd  rÔ   r¹   rÐ   )rÉ   rÚ   r¹  r(  rÛ   rÊ   s         r<   Ú_snapshot_nous_pool_statusr+  ˆ  sº  € ð&)Ø3Ð3Ð3Ð3Ð3Ð3àˆy˜Ñ Ô ˆØð 	-˜4×/Ò/Ñ1Ô1ð 	-Ý*Ñ,Ô,Ð,å�t—|’|‘~”~Ñ&Ô&ˆØð 	-Ý*Ñ,Ô,Ð,ð	6ð 	6ð 	6ð 	6õ �G Ð1Ñ1Ô1ˆå�E˜>¨4Ñ0Ô0ð 5Ý�uÐ/°Ñ4Ô4ð 	ð ð 	-Ý*Ñ,Ô,Ð,ð Ý& uÐ.?ÀÑFÔFð  0Ý�u˜j¨$Ñ/Ô/Ý")¨%Ð1EÀtÑ"LÔ"Lð #0Ý�u˜j¨$Ñ/Ô/Ø(Ý!(¨°¸dÑ!CÔ!CÝ$+¨EÐ3IÈ4Ñ$PÔ$PÝ!%¥g¨e°_ÀdÑ&KÔ&KÑ!LÔ!LØB�g e¨W°iÑ@Ô@ÐBÐBð
ð 
ð 	
øõ ð )ð )ð )Ý&Ñ(Ô(Ð(Ð(Ð(ð)øøøs$   ‚4E ·0E Á(AE Â/BE ÅE!Å E!c                 ó  — t          d¦  «        } | �rkt          |                      d¦  «        ¦  «        |                      d¦  «        |                      d¦  «        |                      d¦  «        |                      d¦  «        t          |                      d¦  «        ¦  «        |                      d¦  «        dd	œ}	 t          d
¬¦  «        }t          d¦  «        p| }|                     d|                     d¦  «        p|                     d¦  «        |                     d¦  «        p)|                     d¦  «        p|                     d¦  «        |                     d¦  «        p|                     d¦  «        |                     d¦  «        p)|                     d¦  «        p|                     d¦  «        t          |                     d¦  «        ¦  «        d|                     dd¦  «        › �|                     d¦  «        dœ¦  «         |S # t
          $ r^}|                     dt          |¦  «        t          t          |dd¦  «        ¦  «        t          |dd¦  «        dœ¦  «         |cY d}~S d}~ww xY wt          ¦   «         S )aœ  Status snapshot for Nous auth.

    Prefer the auth-store provider state, because that is the live source of
    truth for refresh + mint operations. When provider state exists, validate it
    by resolving runtime credentials so revoked refresh sessions do not show up
    as a healthy login. If provider state is absent, fall back to the credential
    pool for the just-logged-in / not-yet-promoted case.
    r=   rÊ   r*   r+   r  rØ  r]  r  )r  r*   r+   r   rØ  r)  rÊ   rÖ   r"   )rç  Trö   r   zruntime:rÖ   r  rë  )r  r*   r+   r   rØ  r)  rÖ   rë  Fr  r  N)r  r$  r  r³  )	rË  r¹   r  r  r=  r  r%   rÔ   r+  )r  Úbase_statusr€  Úrefreshed_stater×   s        r<   Úget_nous_auth_statusr/  ¸  s’  € õ $ FÑ+Ô+€EØñ &å˜eŸiši¨Ñ7Ô7Ñ8Ô8Ø$ŸyšyÐ):Ñ;Ô;Ø"'§)¢)Ð,@Ñ"AÔ"AØ!&§¢¨<Ñ!8Ô!8Ø$)§I¢IÐ.DÑ$EÔ$EÝ!% e§i¢i°Ñ&@Ô&@Ñ!AÔ!AØ!ŸIšI nÑ5Ô5Ø"ð	
ð 	
ˆð	Ý4ÈÐLÑLÔLˆEÝ5°fÑ=Ô=ÐFÀˆOØ×Òà!%Ø'6×':Ò':Ð;LÑ'MÔ'MÐ'sÐQ\×Q`ÒQ`ÐarÑQsÔQsØ*/¯)ª)°JÑ*?Ô*?ð +=Ø&×*Ò*Ð+?Ñ@Ô@ð+=à"—’Ð';Ñ<Ô<Ø)8×)<Ò)<¸\Ñ)JÔ)JÐ)rÈkÏoÊoÐ^qÑNrÔNrØ,1¯IªI°lÑ,CÔ,Cð -?Ø&×*Ò*Ð+AÑBÔBð-?à"—’Ð'=Ñ>Ô>Ý)-¨o×.AÒ.AÀ/Ñ.RÔ.RÑ)SÔ)SØH¨¯ª°8¸XÑ)FÔ)FÐHÐHØ#Ÿiši¨Ñ1Ô1ðð ñô ð ð  ÐøÝð 	ð 	ð 	Ø×ÒØ"Ý˜S™œÝ$(­°Ð6HÈ%Ñ)PÔ)PÑ$QÔ$QÝ% c¨6°4Ñ8Ô8ð	 ð  ñ ô ð ð ÐÐÐÐÐÐøøøøð	øøøõ &Ñ'Ô'Ð's    Â>EH È
I;ÈAI6É0I;É6I;c            
     ó  — 	 ddl m}   | d¦  «        }|r¡|                     ¦   «         r�|                     ¦   «         }|�wt	          |dd¦  «        pt	          |dd¦  «        }|rSt          |d¦  «        sCdt          t          ¦   «         ¦  «        t	          |d	d¦  «        d
dt	          |dd¦  «        › �|dœS n# t          $ r Y nw xY w	 t          ¦   «         }dt          t          ¦   «         ¦  «        | 
                    d	¦  «        | 
                    d¦  «        | 
                    d¦  «        | 
                    d¦  «        dœS # t          $ r6}dt          t          ¦   «         ¦  «        t          |¦  «        dœcY d}~S d}~ww xY w)zªStatus snapshot for Codex auth.
    
    Checks the credential pool first (where `hermes auth` stores credentials),
    then falls back to the legacy provider state.
    r   rÈ   r?   NrË   rÊ   r)   TrP  rS  r)  r÷   r*  )r  r  rP  rT  rÖ   rD   rT  rÖ   rD   F)r  r  r$  )rÑ   rÉ   rÒ   ÚselectrÔ   rG  r%   rL  rÐ   r  r  r  )rÉ   rÚ   rÛ   rD   r€  r×   s         r<   Úget_codex_auth_statusr2  í  sâ  € ðØ3Ð3Ð3Ð3Ð3Ð3Øˆy˜Ñ(Ô(ˆØð 	�D×(Ò(Ñ*Ô*ð 	Ø—K’K‘M”MˆEØÐ å˜EÐ#4°dÑ;Ô;ð :Ý˜u n°bÑ9Ô9ð ð ð Õ#BÀ7ÈAÑ#NÔ#Nð à%)Ý&)­/Ñ*;Ô*;Ñ&<Ô&<Ý(/°°~ÀtÑ(LÔ(LØ%.Ø"N­'°%¸À)Ñ*LÔ*LÐ"NÐ"NØ#*ðð ð øøõ ð ð ð Øˆðøøøð
Ý1Ñ3Ô3ˆàÝ�oÑ/Ô/Ñ0Ô0Ø!ŸIšI nÑ5Ô5ØŸš ;Ñ/Ô/Ø—i’i Ñ)Ô)Ø—y’y Ñ+Ô+ð
ð 
ð 	
øõ ð 
ð 
ð 
àÝ�oÑ/Ô/Ñ0Ô0Ý˜‘X”Xð
ð 
ð 	
ð 	
ð 	
ð 	
ð 	
ð 	
øøøøð
øøøs1   ‚B3B7 Â7
CÃCÃA;E Å
FÅ+E?Å9FÅ?Fc                óŽ  — t                                | ¦  «        }|r|j        dk    rddiS d}d}t          | |¦  «        \  }}d}|j        r,t          j        |j        d¦  «                             ¦   «         }| dv rt          ||j	        |¦  «        }n|r|}n|j	        }t          |¦  «        | |j        ||t          |¦  «        dœS )z<Status snapshot for API-key providers (z.ai, Kimi, MiniMax).rD   Ú
configuredFr)   ©rU   rY   )r4  r  r'   Ú
key_sourcerö   r  )rš   r  r(   rÝ   r4   r    r¡   r¼   rª   r+   r¹   r'   ©rÂ   rÃ   rD   r6  Úenv_urlrö   s         r<   Úget_api_key_provider_statusr9    sî   € å×#Ò# KÑ0Ô0€GØð %�gÔ'¨9Ò4Ð4Ø˜eÐ$Ð$à€GØ€JÝ:¸;ÈÑPÔPÑ€GˆZà€GØÔð BÝ”)˜GÔ4°bÑ9Ô9×?Ò?ÑAÔAˆàÐ7Ð7Ð7Ý)¨'°7Ô3MÈwÑWÔWˆˆØ	ð .ØˆˆàÔ-ˆõ ˜7‘m”mØØ”Ø ØÝ˜'‘]”]ðð ð r;   c                óÎ  — t                                | ¦  «        }|r|j        dk    rddiS t          j        dd¦  «                             ¦   «         p(t          j        dd¦  «                             ¦   «         pd}t          j        dd¦  «                             ¦   «         }|rt          j        |¦  «        nd	d
g}|j        r,t          j        |j        d¦  «                             ¦   «         nd}|s|j	        }|rt          j        |¦  «        nd}t          |p|                     d¦  «        ¦  «        | |j        ||||t          |p|                     d¦  «        ¦  «        dœS )z:Status snapshot for providers that run a local subprocess.rJ   r4  FÚHERMES_COPILOT_ACP_COMMANDr)   ÚCOPILOT_CLI_PATHrC   ÚHERMES_COPILOT_ACP_ARGSú--acpú--stdioNú
acp+tcp://)r4  r  r'   Úcommandrë  Úresolved_commandrö   r  )rš   r  r(   r    r¡   r¼   Úshlexr?  r4   r+   r„  Úwhichr¹   r¨   r'   )rÂ   rÃ   rA  Úraw_argsrë  rö   rB  s          r<   Ú$get_external_process_provider_statusrF  =  sy  € å×#Ò# KÑ0Ô0€GØð %�gÔ'Ð+=Ò=Ð=Ø˜eÐ$Ð$õ 	Œ	Ð.°Ñ3Ô3×9Ò9Ñ;Ô;ð 	ÝŒ9Ð'¨Ñ,Ô,×2Ò2Ñ4Ô4ð	àð õ
 ŒyÐ2°BÑ7Ô7×=Ò=Ñ?Ô?€HØ$,ÐF�5Œ;�xÑ Ô Ð °7¸IÐ2F€DØBIÔBZÐb�rŒy˜Ô1°2Ñ6Ô6×<Ò<Ñ>Ô>Ð>Ð`b€HØð .ØÔ-ˆà07ÐA•v”| GÑ,Ô,Ð,¸TÐåÐ+ÐP¨x×/BÒ/BÀ<Ñ/PÔ/PÑQÔQØØ”ØØØ,ØÝÐ*ÐO¨h×.AÒ.AÀ,Ñ.OÔ.OÑPÔPð	ð 	ð 	r;   c                óö  — | pt          ¦   «         }|dk    rt          ¦   «         S |dk    rt          ¦   «         S |dk    rt          ¦   «         S |dk    rt	          ¦   «         S |dk    rt          ¦   «         S |dk    rt          |¦  «        S t                               |¦  «        }|r|j	        dk    rt          |¦  «        S |r5|j	        dk    r*	 d	d
lm}  |¦   «         |dœS # t          $ r	 d|ddœcY S w xY wddiS )zGeneric auth status dispatcher.r   r=   r?   rA   rB   rI   rD   r•   r   r  )r  r  Fzboto3 not installed)r  r  r$  r  )rÎ  r*  r/  r2  r�  r‘  rF  rš   r  r(   r9  r  r  r  )rÂ   rØ  rÃ   r  s       r<   r  r  [  s\  € àÐ1Õ/Ñ1Ô1€FØ�ÒÐÝ&Ñ(Ô(Ð(Ø�ÒÐÝ#Ñ%Ô%Ð%Ø�ÒÐÝ$Ñ&Ô&Ð&Ø�ÒÐÝ#Ñ%Ô%Ð%ØÐ$Ò$Ð$Ý+Ñ-Ô-Ð-Ø�ÒÐÝ3°FÑ;Ô;Ð;å×#Ò# FÑ+Ô+€GØð 3�7Ô$¨	Ò1Ð1Ý*¨6Ñ2Ô2Ð2àð \�7Ô$¨	Ò1Ð1ð	\ØAÐAÐAÐAÐAÐAØ!4Ð!4Ñ!6Ô!6ÀFÐKÐKÐKøÝð 	\ð 	\ð 	\Ø!&°FÐEZÐ[Ð[Ð[Ð[Ð[ð	\øøøà˜ÐÐs   ÃC! Ã!C4Ã3C4c                óú  — t                                | ¦  «        }|r|j        dk    rt          d| › d�| d¬¦  «        ‚d}d}t	          | |¦  «        \  }}d}|j        r,t          j        |j        d¦  «                             ¦   «         }| dv rt          ||j
        |¦  «        }n<| dk    rt          ||j
        |¦  «        }n|r|                     d	¦  «        }n|j
        }| ||                     d	¦  «        |pd
dœS )zwResolve API key and base URL for an API-key provider.

    Returns dict with: provider, api_key, base_url, source.
    rD   ú
Provider 'z' is not an API-key provider.r  rL  r)   r5  rP   r9  Údefault)r  rD   rö   rÖ   )rš   r  r(   r  rÝ   r4   r    r¡   r¼   rª   r+   r  r:  r7  s         r<   Ú$resolve_api_key_provider_credentialsrK  x  s<  € õ
  ×#Ò# KÑ0Ô0€GØð 
�gÔ'¨9Ò4Ð4ÝØC˜ÐCÐCÐCØ Ø#ð
ñ 
ô 
ð 	
ð €GØ€JÝ:¸;ÈÑPÔPÑ€GˆZà€GØÔð BÝ”)˜GÔ4°bÑ9Ô9×?Ò?ÑAÔAˆàÐ7Ð7Ð7Ý)¨'°7Ô3MÈwÑWÔWˆˆØ	˜Ò	Ð	Ý(¨°'Ô2LÈgÑVÔVˆˆØ	ð .Ø—>’> #Ñ&Ô&ˆˆàÔ-ˆð  ØØ—O’O CÑ(Ô(ØÐ) 	ð	ð ð r;   c                óà  — t                                | ¦  «        }|r|j        dk    rt          d| › d�| d¬¦  «        ‚|j        r,t          j        |j        d¦  «                             ¦   «         nd}|s|j        }t          j        dd¦  «                             ¦   «         p(t          j        dd¦  «                             ¦   «         pd	}t          j        d
d¦  «                             ¦   «         }|rt          j
        |¦  «        nddg}|rt          j        |¦  «        nd}|s+|                     d¦  «        st          d|› d�| d¬¦  «        ‚| d|                     d¦  «        |p||ddœS )z>Resolve runtime details for local subprocess-backed providers.rJ   rI  z&' is not an external-process provider.r  rL  r)   r;  r<  rC   r=  r>  r?  Nr@  z(Could not find the Copilot CLI command 'zQ'. Install GitHub Copilot CLI or set HERMES_COPILOT_ACP_COMMAND/COPILOT_CLI_PATH.Úmissing_copilot_clirI   r9  Úprocess)r  rD   rö   rA  rë  rÖ   )rš   r  r(   r  r4   r    r¡   r¼   r+   rC  r?  r„  rD  r¨   r:  )rÂ   rÃ   rö   rA  rE  rë  rB  s          r<   Ú-resolve_external_process_provider_credentialsrO  ž  sÄ  € å×#Ò# KÑ0Ô0€GØð 
�gÔ'Ð+=Ò=Ð=ÝØL˜ÐLÐLÐLØ Ø#ð
ñ 
ô 
ð 	
ð CJÔBZÐb�rŒy˜Ô1°2Ñ6Ô6×<Ò<Ñ>Ô>Ð>Ð`b€HØð .ØÔ-ˆõ 	Œ	Ð.°Ñ3Ô3×9Ò9Ñ;Ô;ð 	ÝŒ9Ð'¨Ñ,Ô,×2Ò2Ñ4Ô4ð	àð õ
 ŒyÐ2°BÑ7Ô7×=Ò=Ñ?Ô?€HØ$,ÐF�5Œ;�xÑ Ô Ð °7¸IÐ2F€DØ07ÐA•v”| GÑ,Ô,Ð,¸TÐØð 
 H×$7Ò$7¸Ñ$EÔ$Eð 
Ýð]°wð ]ð ]ð ]à Ø&ð	
ñ 
ô 
ð 	
ð  Ø Ø—O’O CÑ(Ô(Ø#Ð. wØØðð ð r;   Údefault_modelc                óŒ  — t          ¦   «         5  t          ¦   «         }| |d<   t          |¦  «         ddd¦  «         n# 1 swxY w Y   t          ¦   «         }|j                             dd¬¦  «         t          ¦   «         }|                     d¦  «        }t          |t          ¦  «        rt          |¦  «        }nBt          |t          ¦  «        r+|                     ¦   «         rd|                     ¦   «         i}ni }| |d<   |r-|                     ¦   «         r|                     d¦  «        |d	<   n|                     d	d¦  «         |                     d
d¦  «         |                     dd¦  «         |r!|                     dd¦  «        }|rd|v r||d<   ||d<   |                     t          j        |d¬¦  «        ¦  «         |S )aÀ  Update config.yaml and auth.json to reflect the active provider.

    When *default_model* is provided the function also writes it as the
    ``model.default`` value.  This prevents a race condition where the
    gateway (which re-reads config per-message) picks up the new provider
    before the caller has finished model selection, resulting in a
    mismatched model/provider (e.g. ``anthropic/claude-opus-4.6`` sent to
    MiniMax's API).
    r€  NTrS  rï   rJ  r  r9  rö   rD   Úapi_moder)   F©r;  )rw  r  r¤  r   rZ  r[  r   r  r»   r:   r%   r¼   r:  rÈ  ra  ÚyamlÚ	safe_dump)	rÂ   r+   rP  r  Úconfig_pathÚconfigÚcurrent_modelrÓ  Úcur_defaults	            r<   Ú_update_config_for_providerrZ  Ê  s  € õ 
Ñ	Ô	ð %ð %Ý%Ñ'Ô'ˆ
Ø(3ˆ
Ð$Ñ%Ý˜Ñ$Ô$Ð$ð%ð %ð %ñ %ô %ð %ð %ð %ð %ð %ð %øøøð %ð %ð %ð %õ "Ñ#Ô#€KØÔ×Ò T°DÐÑ9Ô9Ð9åÑÔ€Fà—J’J˜wÑ'Ô'€MÝ�-¥Ñ&Ô&ð Ý˜Ñ'Ô'ˆ	ˆ	Ý	�M¥3Ñ	'Ô	'ð ¨M×,?Ò,?Ñ,AÔ,Að Ø × 3Ò 3Ñ 5Ô 5Ð6ˆ	ˆ	àˆ	à'€IˆjÑØð (Ð0×6Ò6Ñ8Ô8ð (Ø 2× 9Ò 9¸#Ñ >Ô >ˆ	�*ÑÐð 	�Š�j $Ñ'Ô'Ð'ð ‡M‚M�)˜TÑ"Ô"Ð"Ø‡M‚M�*˜dÑ#Ô#Ð#ð
 ð 1Ø—m’m I¨rÑ2Ô2ˆØð 	1˜c [Ð0Ð0Ø#0ˆI�iÑ à€Fˆ7�Oà×Ò�4œ>¨&¸EÐBÑBÔBÑCÔCÐCØÐs   �#>¾AÁAc                 óP  — 	 t          ¦   «         } n# t          $ r Y dS w xY w| sdS |                      d¦  «        }t          |t          ¦  «        sdS |                     d¦  «        }t          |t
          ¦  «        sdS |                     ¦   «                              ¦   «         }|pdS )z?Return model.provider from config.yaml, normalized, if present.Nrï   r  )r   rÐ   r  r»   r:   r%   r¼   r¾   )rW  rï   r  s      r<   Ú_get_config_providerr\    s¹   € ðÝ Ñ"Ô"ˆˆøÝð ð ð Øˆtˆtðøøøàð ØˆtØ�JŠJ�wÑÔ€EÝ�e�TÑ"Ô"ð ØˆtØ�yŠy˜Ñ$Ô$€HÝ�h¥Ñ$Ô$ð ØˆtØ�~Š~ÑÔ×%Ò%Ñ'Ô'€HØÐ�tÐs   ‚ ‘
žc                óv   — | sdS t          ¦   «         |                      ¦   «                              ¦   «         k    S )z=Return True when config.yaml currently selects *provider_id*.F)r\  r¼   r¾   )rÂ   s    r<   Ú_config_provider_matchesr^    s8   € àð ØˆuÝÑ!Ô! [×%6Ò%6Ñ%8Ô%8×%>Ò%>Ñ%@Ô%@Ò@Ð@r;   c                 ó.   — t          ¦   «         } | dv r| S dS )a¼  Fallback logout target when auth.json has no active provider.

    `hermes logout` historically keyed off auth.json.active_provider only.
    That left users stuck when auth state had already been cleared but
    config.yaml still selected an OAuth provider such as openai-codex for the
    agent model: there was no active auth provider to target, so logout printed
    "No provider is currently logged in" and never reset model.provider.
    >   r=   r?   N)r\  )r  s    r<   Ú$_logout_default_provider_from_configr`  %  s%   € õ $Ñ%Ô%€HØÐ+Ð+Ð+ØˆØˆ4r;   c                 ó>  — t          ¦   «         } |                      ¦   «         s| S t          ¦   «         }|s| S |                     d¦  «        }t	          |t
          ¦  «        rd|d<   d|v r
t          |d<   |                      t          j	        |d¬¦  «        ¦  «         | S )z5Reset config.yaml provider back to auto after logout.rï   rð  r  rö   FrS  )
r   r^  r   r  r»   r:   r   ra  rT  rU  )rV  rW  rï   s      r<   Ú_reset_config_providerrb  4  s«   € å!Ñ#Ô#€KØ×ÒÑÔð ØÐåÑÔ€FØð ØÐà�JŠJ�wÑÔ€EÝ�%�ÑÔð 4Ø"ˆˆjÑØ˜ÐÐÝ 3ˆE�*ÑØ×Ò�4œ>¨&¸EÐBÑBÔBÑCÔCÐCØÐr;   rÒ  rX  Úpricingú#Optional[Dict[str, Dict[str, str]]]Úunavailable_modelsúOptional[List[str]]Ú
portal_urlc           
     óF  ‡‡‡!‡"‡#‡$‡%‡&‡'— ddl m} |pg }g }‰r‰| v r|                     ‰¦  «         | D ]}||vr|                     |¦  «         Œt          |¦  «        t          |¦  «        z   }	t	          ‰ot          ˆfd„|	D ¦   «         ¦  «        ¦  «        Š%‰%rt          d„ |	D ¦   «         d¬¦  «        dz   ndŠ&i Š"dŠ'dŠ#dŠ$‰%rì|	D ]×}‰                     |¦  «        }
|
rh ||
                     d	d
¦  «        ¦  «        } ||
                     dd
¦  «        ¦  «        }|
                     dd
¦  «        }|r ||¦  «        nd
}|rdŠ$nd\  }}}|||f‰"|<   t          ‰'t          |¦  «        t          |¦  «        ¦  «        Š't          ‰#t          |¦  «        ¦  «        Š#ŒØ‰$rt          ‰#d¦  «        Š#ˆ"ˆ#ˆˆ$ˆ%ˆ&ˆ'fd„Š!d}d}‰%r1d}d|› d
d‰&› �›ddd‰'› �›ddd‰'› �›�}‰$r|ddd‰#› �›�z  }||dz   z  }d}d}	 ddl	m
} ˆ!fd„|D ¦   «         }|                     d¦  «         |                     d ¦  «         |pt                               d!¦  «        }|rwt          |¦  «         t          ¦   «          |D ]!}t          |› d ‰!|¦  «        › |› �¦  «         Œ"t          ¦   «          t          |› d"|› d#|› �¦  «         t          ¦   «          d$}n|} |||d%d&d'dd|¬(¦  «        }|                     ¦   «         }dd)lm}  |¦   «          |€d*S t          ¦   «          |t          |¦  «        k     r||         S |t          |¦  «        k    r't#          d+¦  «                             ¦   «         }|r|nd*S d*S # t&          t(          t*          t,          j        f$ r Y nw xY wt          |¦  «         t          t1          t          |¦  «        dz   ¦  «        ¦  «        }t3          |d,¦  «        D ]'\  }}t          d|d|› �›d- ‰!|¦  «        › �¦  «         Œ(t          |¦  «        }t          d|d,z   d|› �›d.�¦  «         t          d|dz   d|› �›d/�¦  «         |rm|pt                               d!¦  «        }t          ¦   «          t          d|› d0|› d1|› �¦  «         |D ](}t          dd
d|› �›d|›  ‰!|¦  «        › |› �¦  «         Œ)t          ¦   «          	 	 t#          d2|dz   › d3�¦  «                             ¦   «         } | sd*S t5          | ¦  «        }d,|cxk    r|k    rn n||d,z
           S ||d,z   k    r't#          d+¦  «                             ¦   «         }|r|nd*S ||dz   k    rd*S t          d4|dz   › �¦  «         n2# t6          $ r t          d5¦  «         Y nt8          t:          f$ r Y d*S w xY wŒÛ)6a†  Interactive model selection. Puts current_model first with a marker. Returns chosen model ID or None.

    If *pricing* is provided (``{model_id: {prompt, completion}}``), a compact
    price indicator is shown next to each model in aligned columns.

    If *unavailable_models* is provided, those models are shown grayed out
    and unselectable, with an upgrade link to *portal_url*.
    r   )Ú_format_price_per_mtokc              3  óB   •K  — | ]}‰                      |¦  «        V — Œd S r  ©r  )r–  Úmrc  s     €r<   rþ  z*_prompt_model_selection.<locals>.<genexpr>f  s-   øè è € Ð&JÐ&J¸! w§{¢{°1¡~¤~Ð&JÐ&JÐ&JÐ&JÐ&JÐ&Jr;   c              3  ó4   K  — | ]}t          |¦  «        V — Œd S r  )r½   )r–  rl  s     r<   rþ  z*_prompt_model_selection.<locals>.<genexpr>g  s(   è è € Ð/Ð/˜q•C˜‘F”FÐ/Ð/Ð/Ð/Ð/Ð/r;   )rJ  rŠ  rÌ  FÚpromptr)   Ú
completionÚinput_cache_readT©r)   r)   r)   é   c                ó¬   •— ‰
rC‰                      | d¦  «        \  }}}d|d‰› �›d|d‰› �›�}‰	r|d|d‰› �›�z  }| d‰› �›|› �}n| }| ‰k    r|dz  }|S )Nrq  r   Ú>ú  Ú<u     â†� currently in userk  )rÇ  ÚinpÚoutr  Ú
price_partÚbaseÚ_price_cacheÚ	cache_colrX  Ú	has_cacheÚhas_pricingÚname_colÚ	price_cols         €€€€€€€r<   Ú_labelz'_prompt_model_selection.<locals>._label€  s´   ø€ Øð 	Ø*×.Ò.¨s°LÑAÔA‰OˆC��eØC˜SÐC 9ÐCÐCÐCÐC°ÐC°yÐCÐCÐCÐCˆJØð 8ØÐ7 5Ð7¨9Ð7Ð7Ð7Ð7Ñ7�
ØÐ3˜HÐ3Ð3Ð3 zÐ3Ð3ˆDˆDàˆDØ�-ÒÐØÐ,Ñ,ˆDØˆr;   zSelect default model:z     rŒ  rt  r   ÚInru  ÚOutÚCachez  /Mtokz[2mz[0m)ÚTerminalMenuc                ó,   •— g | ]}d  ‰|¦  «        › �‘ŒS )ru  r1   )r–  rÇ  r�  s     €r<   r˜  z+_prompt_model_selection.<locals>.<listcomp>¤  s*   ø€ Ð9Ð9Ð9¨#Ð%˜˜˜s™œÐ%Ð%Ð9Ð9Ð9r;   z  Enter custom model namez  Skip (keep current)r9  u     â”€â”€ Upgrade at u    for paid models â”€â”€zAvailable free models:z-> )Úfg_greenÚbold)r‡  )Úcursor_indexÚmenu_cursorÚmenu_cursor_styleÚmenu_highlight_styleÚcycle_cursorÚclear_screenÚtitle)Úflush_stdinNzEnter model name: r   z. z. Enter custom model namez. Skip (keep current)u=   â”€â”€ Unavailable models (requires paid tier â€” upgrade at u   ) â”€â”€z
Choice [1-z] (default: skip): zPlease enter 1-zPlease enter a number)Úhermes_cli.modelsri  r¿  r¶  r¹   Úanyrd  r  r½   Úsimple_term_menur…  râ  r:  r.  ÚshowÚhermes_cli.curses_uir�  r3  r¼   r  ÚNotImplementedErrorrm  Ú
subprocessÚSubprocessErrorr%   Ú	enumerater¸   rÍ   r5  r4  )(rÒ  rX  rc  re  rg  ri  Ú_unavailablerŸ  rÇ  Ú
all_modelsÚprw  rx  Ú
cache_readr  Údefault_idxÚ
menu_titleÚpadÚheaderÚ_DIMÚ_RESETr…  ÚchoicesÚ_upgrade_urlÚeffective_titleÚmenuÚidxr�  r  Ú	num_widthÚiÚnÚchoicer�  r{  r|  r}  r~  r  r€  s(    ``                              @@@@@@@r<   Ú_prompt_model_selectionr­  G  sµ  øøøøøøøøø€ ð 9Ð8Ð8Ð8Ð8Ð8à%Ð+¨€Lð €GØð &˜¨)Ð3Ð3Ø�Š�}Ñ%Ô%Ð%Øð  ð  ˆØ�gÐÐØ�NŠN˜3ÑÔÐøõ �g‘”¥ lÑ!3Ô!3Ñ3€Jõ �wÐJ¥3Ð&JÐ&JÐ&JÐ&J¸zÐ&JÑ&JÔ&JÑ#JÔ#JÑKÔK€KØCNÐU�sÐ/Ð/ JÐ/Ñ/Ô/¸Ð;Ñ;Ô;¸aÑ?Ð?ÐTU€Hð 57€LØ€IØ€IØ€IØð *Øð 	3ð 	3ˆCØ—’˜CÑ Ô ˆAØð -Ø,Ð,¨Q¯UªU°8¸RÑ-@Ô-@ÑAÔA�Ø,Ð,¨Q¯UªU°<ÀÑ-DÔ-DÑEÔE�ØŸUšUÐ#5°rÑ:Ô:�
Ø>HÐPÐ.Ð.¨zÑ:Ô:Ð:Èb�Øð %Ø $�Iøà",‘��S˜%Ø!$ c¨5Ð 1ˆL˜ÑÝ˜I¥s¨3¡x¤xµ°S±´Ñ:Ô:ˆIÝ˜I¥s¨5¡z¤zÑ2Ô2ˆIˆIØð 	*Ý˜I qÑ)Ô)ˆIðð ð ð ð ð ð ð ð ð ð ð €Kð )€JØð )ð ˆØU�cÐU˜2ÐU ÐUÐUÐUÐU¨DÐU°9ÐUÐUÐUÐUÀÐUÈÐUÐUÐUÐUˆØð 	2ØÐ1˜7Ð1 YÐ1Ð1Ð1Ð1Ñ1ˆFØ�f˜yÑ(Ñ(ˆ
ð €DØ€Fð/Ø1Ð1Ð1Ð1Ð1Ð1à9Ð9Ð9Ð9°Ð9Ñ9Ô9ˆØ�ŠÐ2Ñ3Ô3Ð3Ø�ŠÐ.Ñ/Ô/Ð/ð #Ð=Õ&=×EÒEÀcÑJÔJˆØð 
	)Ý�*ÑÔÐÝ‰GŒGˆGØ#ð ;ð ;�Ý˜Ð9Ð9 F F¨3¡K¤KÐ9°Ð9Ð9Ñ:Ô:Ð:Ð:Ý‰GŒGˆGÝ�TÐ\Ð\¨|Ð\Ð\ÐTZÐ\Ð\Ñ]Ô]Ð]Ý‰GŒGˆGØ6ˆOˆOà(ˆOàˆ|ØØ$ØØ2Ø!.ØØØ!ð	
ñ 	
ô 	
ˆð �iŠi‰kŒkˆØ4Ð4Ð4Ð4Ð4Ð4Øˆ‰ŒˆØˆ;Ø�4Ý‰ŒˆØ•�W‘”ÒÐØ˜3”<ÐØ•C˜‘L”LÒ Ð ÝÐ/Ñ0Ô0×6Ò6Ñ8Ô8ˆFØ#Ð-�6�6¨Ð-ØˆtøÝÕ,­gµzÔ7QÐRð ð ð Øˆðøøøõ 
ˆ*ÑÔÐÝ•C�˜G™œ qÑ(Ñ)Ô)Ñ*Ô*€IÝ˜G QÑ'Ô'ð 4ð 4‰ˆˆ3ÝÐ2�1Ð2�yÐ2Ð2Ð2Ð2 V V¨C¡[¤[Ð2Ð2Ñ3Ô3Ð3Ð3ÝˆG‰Œ€AÝ	Ð
<ˆq�1‰uÐ
<�yÐ
<Ð
<Ð
<Ð
<Ð
<Ñ=Ô=Ð=Ý	Ð
8ˆq�1‰uÐ
8�yÐ
8Ð
8Ð
8Ð
8Ð
8Ñ9Ô9Ð9àð GØ"Ð=Õ&=×EÒEÀcÑJÔJˆÝ‰ŒˆÝÐt�4ÐtÐtÐVbÐtÐtÐlrÐtÐtÑuÔuÐuØð 	Gð 	GˆCÝÐE�rÐE˜IÐEÐEÐEÐE¨$ÐE°°°s±´ÐE¸VÐEÐEÑFÔFÐFÐFÝ	�G„G€Gðð	ÝÐB¨¨A©ÐBÐBÐBÑCÔC×IÒIÑKÔKˆFØð Ø�tÝ�f‘+”+ˆCØ�Cˆ}ˆ}Š}ˆ}˜1Š}ˆ}ˆ}ˆ}ˆ}Ø˜s Q™wÔ'Ð'Ø˜˜A™’�ÝÐ3Ñ4Ô4×:Ò:Ñ<Ô<�Ø!'Ð1�v�v¨TÐ1Ø˜˜A™’�Ø�tÝÐ+ A¨¡EÐ+Ð+Ñ,Ô,Ð,Ð,øÝð 	+ð 	+ð 	+ÝÐ)Ñ*Ô*Ð*Ð*Ð*Ý!¥8Ð,ð 	ð 	ð 	Ø�4�4ð	øøøð!sO   Ç7DM, Ì(M, Ì09M, Í,"NÎNÓ	*U0 Ó5)U0 Ô/U0 Õ	U0 ÕU0 Õ0VÖVÖVrÔ  c                ó¶   — ddl m}m}  |¦   «         }t          |                     d¦  «        t
          ¦  «        r| |d         d<   nd| i|d<    ||¦  «         dS )uÛ   Save the selected model to config.yaml (single source of truth).

    The model is stored in config.yaml only â€” NOT in .env.  This avoids
    conflicts in multi-agent setups where env vars would stomp each other.
    r   )Úsave_configrÐ  rï   rJ  N)rŸ   r¯  rÐ  r»   r  r:   )rÔ  r¯  rÐ  rW  s       r<   Ú_save_model_choicer°  ÷  sz   € ð ;Ð:Ð:Ð:Ð:Ð:Ð:Ð:àˆ[‰]Œ]€Få�&—*’*˜WÑ%Ô%¥tÑ,Ô,ð 0Ø%-ˆˆwŒ˜	Ñ"Ð"à$ hÐ/ˆˆw‰Ø€K�ÑÔÐÐÐr;   c                óz   — t          d¦  «         t          d¦  «         t          d¦  «         t          d¦  «        ‚)z9Deprecated: use 'hermes model' or 'hermes setup' instead.z,The 'hermes login' command has been removed.z(Use 'hermes auth' to manage credentials,zF'hermes model' to select a provider, or 'hermes setup' for full setup.r   )r.  r6  )rë  s    r<   Úlogin_commandr²    s;   € å	Ð
8Ñ9Ô9Ð9Ý	Ð
4Ñ5Ô5Ð5Ý	Ð
RÑSÔSÐSÝ
�Q‰-Œ-Ðr;   )Úforce_new_loginr³  c               ó‚  — ~ ~|�s)	 t          ¦   «         }|                     dd¦  «        }t          |t          ¦  «        rÏ|rÍt	          |d¦  «        s½t          d¦  «         	 t          d¦  «                             ¦   «                              ¦   «         }n# t          t          f$ r d}Y nw xY w|dv r[t          d|                     d	t          ¦  «        ¦  «        }t          ¦   «          t          d
¦  «         t          d|› d�¦  «         dS nt          d¦  «         n# t          $ r Y nw xY w|�s"t          ¦   «         }|�rt          d¦  «         t          d¦  «         	 t          d¦  «                             ¦   «                              ¦   «         }n# t          t          f$ r d}Y nw xY w|dv r¡t          |¦  «         t!          j        dd¦  «                             ¦   «                              d¦  «        pt          }	t          d|	¦  «        }t          ¦   «          t          d¦  «         t          d¦  «         t          d|› d�¦  «         dS t          ¦   «          t          d¦  «         t          d¦  «         t          ¦   «          t'          ¦   «         }
t          |
d         |
                     d¦  «        ¦  «         t          d|
                     d	t          ¦  «        ¦  «        }t          ¦   «          t          d
¦  «         ddlm} t          d |¦   «         › d�¦  «         t          d|› d�¦  «         dS ) zNOpenAI Codex login via device code flow. Tokens stored in ~/.hermes/auth.json.rD   r)   r"   z6Existing Codex credentials found in Hermes auth store.z!Use existing credentials? [Y/n]: Úy)r)   rµ  r2  r?   rö   úLogin successful!ú  Config updated: z (model.provider=openai-codex)Nz?Existing Codex credentials are expired. Starting fresh login...z:Found existing Codex CLI credentials at ~/.codex/auth.jsonzOHermes will create its own session to avoid conflicts with Codex CLI / VS Code.zCImport these credentials? (a separate login is recommended) [y/N]: r«  )rµ  r2  r{  r9  z=Credentials imported. Note: if Codex CLI refreshes its token,z<Hermes will keep working independently with its own session.zSigning in to OpenAI Codex...uF   (Hermes creates its own session â€” won't affect Codex CLI or VS Code)rS  rP  r   )Údisplay_hermes_homer:  z
/auth.json)r  r  r»   r%   rG  r.  r3  r¼   r¾   r4  r5  rZ  r}  r  rw  rU  r    r¡   r:  Ú_codex_device_code_loginÚhermes_constantsr¸  )rë  rÃ   r³  ÚexistingÚ_resolved_keyr¹  rV  Ú
cli_tokensÚ	do_importrö   r€  Ú_dhhs               r<   Ú_login_openai_codexrÀ    s�  € ð 	ˆgð ñ ð	Ý8Ñ:Ô:ˆHð
 %ŸLšL¨°BÑ7Ô7ˆMÝ˜-­Ñ-Ô-ð Y°-ð YÕHgÐhuÐwyÑHzÔHzð YÝÐNÑOÔOÐOð Ý!Ð"EÑFÔF×LÒLÑNÔN×TÒTÑVÔV�E�EøÝ Õ"3Ð4ð  ð  ð  Ø�E�E�Eð øøøàÐ,Ð,Ð,Ý"=¸nÈhÏlÊlÐ[eÕg}ÑN~ÔN~Ñ"Ô"�KÝ‘G”G�GÝÐ-Ñ.Ô.Ð.ÝÐZ¨{ÐZÐZÐZÑ[Ô[Ð[Ø�Fð -õ ÐWÑXÔXÐXøøÝð 	ð 	ð 	ØˆDð	øøøð ñ Ý-Ñ/Ô/ˆ
Øñ 	ÝÐNÑOÔOÐOÝÐcÑdÔdÐdð Ý!Ð"gÑhÔh×nÒnÑpÔp×vÒvÑxÔx�	�	øÝÕ/Ð0ð  ð  ð  Ø�	�	�	ð øøøà˜LÐ(Ð(Ý" :Ñ.Ô.Ð.Ýœ9Ð%<¸bÑAÔA×GÒGÑIÔI×PÒPÐQTÑUÔUÐoÕYo�Ý9¸.È(ÑSÔS�Ý‘”�ÝÐUÑVÔVÐVÝÐTÑUÔUÐUÝÐV¨;ÐVÐVÐVÑWÔWÐWØ�õ 
�G„G€GÝ	Ð
)Ñ*Ô*Ð*Ý	Ð
RÑSÔSÐSÝ	�G„G€Gå$Ñ&Ô&€Eõ �u˜X”¨¯	ª	°.Ñ(AÔ(AÑBÔBÐBÝ-¨n¸e¿iºiÈ
ÕTjÑ>kÔ>kÑlÔl€KÝ	�G„G€GÝ	Ð
ÑÔÐØ<Ð<Ð<Ð<Ð<Ð<Ý	Ð
-˜4˜4™6œ6Ð
-Ð
-Ð
-Ñ.Ô.Ð.Ý	Ð
J˜{Ð
JÐ
JÐ
JÑKÔKÐKÐKÐKsO   ‡AD Á"3B ÂD ÂB,Â)D Â+B,Â,A D ÄD Ä
D,Ä+D,Å"3F ÆF,Æ+F,c            
     ó\	  — ddl } d}t          }	 t          j        t          j        d¦  «        ¬¦  «        5 }|                     |› d�d|idd	i¬
¦  «        }ddd¦  «         n# 1 swxY w Y   n'# t          $ r}t          d|› �dd¬¦  «        ‚d}~ww xY w|j        dk    rt          d|j        › d�dd¬¦  «        ‚| 	                    ¦   «         }| 
                    dd¦  «        }| 
                    dd¦  «        }t          dt          | 
                    dd¦  «        ¦  «        ¦  «        }	|r|st          ddd¬¦  «        ‚t          d¦  «         t          d¦  «         t          d|› d�¦  «         t          d¦  «         t          d|› d �¦  «         t          d!¦  «         d"}
|                      ¦   «         }d}	 t          j        t          j        d¦  «        ¬¦  «        5 }|                      ¦   «         |z
  |
k     rz|                      |	¦  «         |                     |› d#�||d$œdd	i¬
¦  «        }|j        dk    r| 	                    ¦   «         }n%|j        d%v rŒzt          d&|j        › d�dd'¬¦  «        ‚ddd¦  «         n# 1 swxY w Y   n,# t           $ r t          d(¦  «         t#          d)¦  «        ‚w xY w|€t          d*dd+¬¦  «        ‚| 
                    d,d¦  «        }| 
                    d-d¦  «        }|› d.�}|r|st          d/dd0¬¦  «        ‚	 t          j        t          j        d¦  «        ¬¦  «        5 }|                     t$          d,||||d1œdd2i¬3¦  «        }ddd¦  «         n# 1 swxY w Y   n'# t          $ r}t          d4|› �dd5¬¦  «        ‚d}~ww xY w|j        dk    rt          d6|j        › d�dd7¬¦  «        ‚| 	                    ¦   «         }| 
                    d8d¦  «        }| 
                    d9d¦  «        }|st          d:dd;¬¦  «        ‚t'          j        d<d¦  «                             ¦   «                              d=¦  «        pt.          }||d>œ|t1          j        t4          j        ¦  «                             ¦   «                              d?d@¦  «        dAdBdCœS )DzBRun the OpenAI device code login flow and return credentials dict.r   Nzhttps://auth.openai.comr   rÿ  z!/api/accounts/deviceauth/usercoder,   rê   rè   )rô   ró   zFailed to request device code: r?   Údevice_code_request_failedrL  rõ   z$Device code request returned status r�  Údevice_code_request_errorr   r)   Údevice_auth_idrÌ  r£  Ú5z-Device code response missing required fields.Údevice_code_incompletez!To continue, follow these steps:
z#  1. Open this URL in your browser:z
     [94mz/codex/device[0m
z  2. Enter this code:z[0m
z/Waiting for sign-in... (press Ctrl+C to cancel)i„  z/api/accounts/deviceauth/token)rÄ  r   )r]  râ  z$Device auth polling returned status Údevice_code_poll_errorú
Login cancelled.é‚   z!Login timed out after 15 minutes.Údevice_code_timeoutr  rÅ  z/deviceauth/callbackzADevice auth response missing authorization_code or code_verifier.Údevice_code_incomplete_exchange)rb  r  r¯  r,   rÅ  r_  )rQ  ró   zToken exchange failed: Útoken_exchange_failedzToken exchange returned status Útoken_exchange_errorrÊ   r]  z.Token exchange did not return an access_token.Útoken_exchange_no_access_tokenr{  r9  )rÊ   r]  r'  r%  rS  zdevice-code)rS  rö   rP  rT  rÖ   )rc  rc  rù   ra  r`  rú   rÐ   r  rû   rô   r  rd  r¸   r.  Ú	monotonicrp  r5  r6  rb  r    r¡   r¼   r:  r}  r   r�  r   r�  r‘  rš  )Ú_timeÚissuerr,   rd  rÿ   r×   Údevice_datar   rÄ  rû  Úmax_waitr  Ú	code_respÚ	poll_respr  rÅ  r¯  Ú
token_resprS  rÊ   r]  rö   s                         r<   r¹  r¹  Z  sŒ  € àÐÐÐà&€FÝ%€Ið
ÝŒ\¥%¤-°Ñ"5Ô"5Ð6Ñ6Ô6ð 	¸&Ø—;’;ØÐ<Ð<Ð<Ø! 9Ð-Ø'Ð);Ð<ð ñ ô ˆDð	ð 	ð 	ñ 	ô 	ð 	ð 	ð 	ð 	ð 	ð 	øøøð 	ð 	ð 	ð 	øøõ ð 
ð 
ð 
ÝØ3¨cÐ3Ð3Ø#Ð*Fð
ñ 
ô 
ð 	
øøøøð
øøøð Ô˜3ÒÐÝØF°4Ô3CÐFÐFÐFØ#Ð*Eð
ñ 
ô 
ð 	
ð
 —)’)‘+”+€KØ—’ ¨RÑ0Ô0€IØ —_’_Ð%5°rÑ:Ô:€NÝ˜�3˜{Ÿš¨z¸3Ñ?Ô?Ñ@Ô@ÑAÔA€Màð 
˜Nð 
ÝØ;Ø#Ð*Bð
ñ 
ô 
ð 	
õ 
Ð
.Ñ/Ô/Ð/Ý	Ð
/Ñ0Ô0Ð0Ý	Ð
8˜&Ð
8Ð
8Ð
8Ñ9Ô9Ð9Ý	Ð
!Ñ"Ô"Ð"Ý	Ð
.˜)Ð
.Ð
.Ð
.Ñ/Ô/Ð/Ý	Ð
;Ñ<Ô<Ð<ð €HØ�OŠOÑÔ€EØ€IðÝŒ\¥%¤-°Ñ"5Ô"5Ð6Ñ6Ô6ð 	¸&Ø—/’/Ñ#Ô# eÑ+¨hÒ6Ð6Ø—’˜MÑ*Ô*Ð*Ø"ŸKšKØÐ=Ð=Ð=Ø,:ÈÐSÐSØ+Ð-?Ð@ð (ñ ô �	ð Ô(¨CÒ/Ð/Ø )§¢Ñ 0Ô 0�IØØÔ*¨jÐ8Ð8Øå#ØW¸yÔ?TÐWÐWÐWØ!/Ð6Nðñ ô ð ð	ð 	ð 	ñ 	ô 	ð 	ð 	ð 	ð 	ð 	ð 	øøøð 	ð 	ð 	ð 	øøõ& ð ð ð ÝÐ"Ñ#Ô#Ð#Ý˜‰oŒoÐðøøøð ÐÝØ/Ø#Ð*?ð
ñ 
ô 
ð 	
ð #ŸšÐ';¸RÑ@Ô@ÐØ—M’M /°2Ñ6Ô6€MØÐ2Ð2Ð2€Làð 
 ]ð 
ÝØOØ#Ð*Kð
ñ 
ô 
ð 	
ð

ÝŒ\¥%¤-°Ñ"5Ô"5Ð6Ñ6Ô6ð 	¸&ØŸšÝ%à"6Ø.Ø$0Ø!*Ø%2ðð ð (Ð)LÐMð %ñ 
ô 
ˆJð	ð 	ð 	ñ 	ô 	ð 	ð 	ð 	ð 	ð 	ð 	øøøð 	ð 	ð 	ð 	øøõ ð 
ð 
ð 
ÝØ+ cÐ+Ð+Ø#Ð*Að
ñ 
ô 
ð 	
øøøøð
øøøð Ô Ò$Ð$ÝØG¨jÔ.DÐGÐGÐGØ#Ð*@ð
ñ 
ô 
ð 	
ð
 �_Š_ÑÔ€FØ—:’:˜n¨bÑ1Ô1€LØ—J’J˜°Ñ3Ô3€Màð 
ÝØ<Ø#Ð*Jð
ñ 
ô 
ð 	
õ 	Œ	Ð)¨2Ñ.Ô.×4Ò4Ñ6Ô6×=Ò=¸cÑBÔBð 	"Ý!ð ð )Ø*ð
ð 
ð Ý œ¥X¤\Ñ2Ô2×<Ò<Ñ>Ô>×FÒFÀxÐQTÑUÔUØØð	ð 	ð 	s§   �'A. ¶ A"ÁA. Á"A&Á&A. Á)A&Á*A. Á.
BÁ8BÂBÆ='J Ç$BJÉ:J ÊJ
Ê
J ÊJ
ÊJ Ê)J;Ì'M? Í&M3Í'M? Í3M7Í7M? Í:M7Í;M? Í?
N#Î	NÎN#é,  ©	r*   r+   r,   r-   r=  rP  r�  rŽ  rç  r=  c        	   
     óN	  — t           d         }	| p.t          j        d¦  «        pt          j        d¦  «        p|	j                             d¦  «        } |pt          j        d¦  «        p|	j                             d¦  «        }
|p|	j        }|p|	j        }t          j	        |¦  «        }|rdn|r|nd}t          ¦   «         rd}t          d|	j        › d	�¦  «         t          d
| › �¦  «         |rt          d¦  «         n|rt          d|› d�¦  «         t          j        |ddi|¬¦  «        5 }t          || ||¬¦  «        }t          |d         ¦  «        }t          |d         ¦  «        }t!          |d         ¦  «        }t!          |d         ¦  «        }t          ¦   «          t          d¦  «         t          d|› �¦  «         t          d|› �¦  «         |r5t#          j        |¦  «        }|rt          d¦  «         nt          d¦  «         t'          dt)          |t*          ¦  «        ¦  «        }t          d|› d�¦  «         t-          || |t          |d         ¦  «        ||¬¦  «        }d d d ¦  «         n# 1 swxY w Y   t/          j        t2          j        ¦  «        }t7          |                     dd!¦  «        ¦  «        }|                     ¦   «         |z   }t=          |                     d"¦  «        ¦  «        p|
}||
k    rt          d#|› �¦  «         i d$| “d"|“d%|“d&|                     d&¦  «        p|“d'|                     d'd(¦  «        “d)|d)         “d*|                     d*¦  «        “d+|                     ¦   «         “d,t/          j         |t2          j        ¬-¦  «                             ¦   «         “d|“d.|du tC          |t          ¦  «        r|nd d/œ“d0d “d1d “d2d “d3d “d4d “d5d “}	 tE          |||dd¬6¦  «        S # tF          $ r›}|j$        d7k    rŠ|                     d$tJ          ¦  «                             d¦  «        }t          ¦   «          t          d8¦  «         t          d9|› d:�¦  «         t          ¦   «          t          d;¦  «         tM          d¦  «        ‚‚ d }~ww xY w)<zMRun the Nous device-code flow and return full OAuth state without persisting.r=   rÜ  rÝ  r9  r  FTzStarting Hermes login via z...zPortal: z'TLS verification: disabled (--insecure)z$TLS verification: custom CA bundle (ú)r`  rè   rÄ  )rd  r*   r,   r-   r¢  r   r4  r£  zTo continue:z  1. Open: z  2. If prompted, enter code: z#  (Opened browser for verification)u=     Could not open browser automatically â€” use the URL above.r   z$Waiting for approval (polling every zs)...rŸ  )rd  r*   r,   rŸ  r4  rû  Nr   r+   z%Using portal-provided inference URL: r*   r,   r-   ri  rj  rÊ   r]  r  r  r  r’  rá  r×  rì  rØ  rí  rï  rð  rø  r&  z>Your Nous Portal account does not have an active subscription.z  Subscribe here: z/billingz<After subscribing, run `hermes model` again to finish setup.)'rš   r    r¡   r*   r:  r+   r,   r-   rù   r`  r1  r.  r'   ra  r©  r%   r¸   r2  rb  rd  r¯  r°  rµ  r   r�  r   r�  r7  r  r+  r;  r‘  r  r»   rú  r  r  râ  r6  )r*   r+   r,   r-   r=  rP  r�  rŽ  rç  rÃ   Úrequested_inference_urlrã   rÁ  rd  rÒ  Úverification_urlr   r4  r£  r@  Úeffective_intervalÚ
token_datar�  Útoken_expires_inr  Úresolved_inference_urlr�  r×   rg  s                                r<   Ú_nous_device_code_loginrá  ë  sÑ  € õ   Ô'€Gàð 	#ÝŒ9Ð-Ñ.Ô.ð	#åŒ9Ð+Ñ,Ô,ð	#ð Ô"ß‚fˆS�k„kð ð 	ð 	&ÝŒ9Ð.Ñ/Ô/ð	&àÔ%ß‚fˆS�k„kð	 ð
 Ð.˜WÔ.€IØÐ"�W”]€EÝŒm˜OÑ,Ô,€GØ"*ÐR˜˜¸iÐ1Q°°ÈT€FåÑÔð Øˆå	Ð
8 w¤|Ð
8Ð
8Ð
8Ñ9Ô9Ð9Ý	Ð
&�_Ð
&Ð
&Ñ'Ô'Ð'Øð CÝÐ7Ñ8Ô8Ð8Ð8Ø	ð CÝÐA°YÐAÐAÐAÑBÔBÐBå	Œ˜g°Ð:LÐ/MÐV\Ð	]Ñ	]Ô	]ð #
ÐagÝ*ØØ+ØØð	
ñ 
ô 
ˆõ ˜{Ð+FÔGÑHÔHÐÝ˜ KÔ0Ñ1Ô1ˆ	Ý˜ \Ô2Ñ3Ô3ˆ
Ý�{ :Ô.Ñ/Ô/ˆå‰ŒˆÝˆnÑÔÐÝÐ.Ð,Ð.Ð.Ñ/Ô/Ð/ÝÐ:¨yÐ:Ð:Ñ;Ô;Ð;àð 	WÝ”_Ð%5Ñ6Ô6ˆFØð WÝÐ;Ñ<Ô<Ð<Ð<åÐUÑVÔVÐVå  ¥C¨Õ2WÑ$XÔ$XÑYÔYÐÝÐNÐ5GÐNÐNÐNÑOÔOÐOå$ØØ+ØÝ˜K¨Ô6Ñ7Ô7Ø!Ø"ð
ñ 
ô 
ˆ
ð9#
ð #
ð #
ñ #
ô #
ð #
ð #
ð #
ð #
ð #
ð #
øøøð #
ð #
ð #
ð #
õJ Œ,•x”|Ñ
$Ô
$€CÝ*¨:¯>ª>¸,ÈÑ+JÔ+JÑKÔKÐØ—’‘”Ð#3Ñ3€Jå˜:Ÿ>š>Ð*>Ñ?Ô?Ñ@Ô@ð 	#Ø"ð ð Ð!8Ò8Ð8ÝÐNÐ6LÐNÐNÑOÔOÐOðØ˜?ðàÐ4ðð 	�Yðð 	�—’ Ñ(Ô(Ð1¨Eð	ð
 	�j—n’n \°8Ñ<Ô<ðð 	˜
 >Ô2ðð 	˜Ÿš¨Ñ8Ô8ðð 	�s—}’}‘”ðð 	•hÔ,¨Z½H¼LÐIÑIÔI×SÒSÑUÔUðð 	Ð&ðð 	Ø %˜Ý#-¨fµcÑ#:Ô#:ÐD˜˜Àð
ð 
ðð 	�Tðð  	˜ð!ð" 	 ð#ð$ 	 ð%ð& 	˜Dð'ð( 	  ð)€Jð,Ý,ØØ 3Ø+ØØð
ñ 
ô 
ð 	
øõ ð ð ð ØŒ8Ð.Ò.Ð.Ø#ŸšØ!Õ#:ñô çŠf�S‰kŒkð õ ‰GŒGˆGÝÐRÑSÔSÐSÝÐ; zÐ;Ð;Ð;Ñ<Ô<Ð<Ý‰GŒGˆGÝÐPÑQÔQÐQÝ˜Q‘-”-ÐØøøøøðøøøs,   Ä,D>I6É6I:É=I:Ï+O? Ï?
R$Ð	BRÒR$c                ó(	  — t          | dd¦  «        pd}t          t          | dd¦  «        ¦  «        }t          | dd¦  «        p't          j        d¦  «        pt          j        d¦  «        }	 t	          t          | d	d¦  «        t          | d
d¦  «        t          | dd¦  «        p|j        t          | dd¦  «        p|j        t          | dd¦  «         |||d¬¦	  «	        }|d         }t          ¦   «         5  t          ¦   «         }| 	                    d¦  «        }ddd¦  «         n# 1 swxY w Y   t          ¦   «         5  t          ¦   «         }	t          |	d|¦  «         t          |	¦  «        }
ddd¦  «         n# 1 swxY w Y   t          ¦   «          t          d¦  «         t          d|
› �¦  «         d}	 | 	                    d¦  «        p| 	                    d¦  «        }t          |t          ¦  «        r|st          ddd¬¦  «        ‚ddlm}m}m}m}  |¦   «         }t          ¦   «          g }|r( |d¦  «        } |¦   «         }|r |||d¬¦  «        \  }}| 	                    dd¦  «        }|r4t          d t+          |¦  «        › d!�¦  «         t-          ||||¬"¦  «        }nP|r?|pt.                               d#¦  «        }t          d$¦  «         t          d%|› d&�¦  «         nt          d'¦  «         nj# t2          $ r]}t          |t          ¦  «        rt5          |¦  «        nt          |¦  «        }t          ¦   «          t          d(|› �¦  «         Y d}~nd}~ww xY w|s�t          ¦   «         5  t          ¦   «         }	|r||	d<   n|	                     dd¦  «         t          |	¦  «         ddd¦  «         n# 1 swxY w Y   t          ¦   «          t          d)¦  «         t          d*¦  «         dS t9          d||¬+¦  «        }|r!t;          |¦  «         t          d,|› �¦  «         t          d-|› d.�¦  «         dS # t<          $ r t          d/¦  «         t?          d0¦  «        ‚t2          $ r&}t          d1|› �¦  «         t?          d2¦  «        ‚d}~ww xY w)3z&Nous Portal device authorization flow.rã   Nr   r�  FrŽ  r“  r”  rg  Úinference_urlr,   r-   r9  r×  rØ  r+   r€  r=   r¶  r:  r×  rÊ   z,No runtime API key available to fetch modelsrZ  rL  r   )Úget_curated_nous_model_idsÚget_pricing_for_providerÚcheck_nous_free_tierÚpartition_nous_models_by_tierT)Ú	free_tierr*   r)   zShowing u=    curated models â€” use "Enter custom model name" for others.)rc  re  rg  r9  z#No free models currently available.zUpgrade at z to access paid models.z,No curated models available for Nous Portal.z?Login succeeded, but could not fetch available models. Reason: z:No provider change. Nous credentials saved for future use.z4  Run `hermes model` again to switch to Nous Portal.)rP  zDefault model set to: r·  z (model.provider=nous)rÈ  rÉ  zLogin failed: r   ) rÔ   r¹   r    r¡   rá  r,   r-   rw  r  r  r  r¤  r.  r»   r%   r  r‘  rä  rå  ræ  rç  r½   r­  râ  r:  rÐ   r)  rÈ  rZ  r°  r5  r6  )rë  rÃ   rP  r�  rŽ  r�  r+   Ú_prior_storeÚprior_active_providerr  rC  Úselected_modelÚruntime_keyrä  rå  ræ  rç  rÒ  re  rc  rè  Ú_portalÚ_urlr×   r  rV  s                             r<   Ú_login_nousrï  n  sZ  € å˜d I¨tÑ4Ô4Ð<¸€OÝ•G˜D *¨eÑ4Ô4Ñ5Ô5€Hå��k 4Ñ(Ô(ð 	&ÝŒ9Ð'Ñ(Ô(ð	&åŒ9�_Ñ%Ô%ð ðsÝ,Ý# D¨,¸Ñ=Ô=Ý& t¨_¸dÑCÔCÝ˜d K°Ñ6Ô6ÐK¸'Ô:KÝ˜$ ¨Ñ.Ô.Ð?°'´-Ý$ T¨<¸Ñ?Ô?Ð?Ø+ØØØ &ð

ñ 

ô 

ˆ
ð (Ð(<Ô=Ðõ ÑÔð 	Hð 	HÝ+Ñ-Ô-ˆLØ$0×$4Ò$4Ð5FÑ$GÔ$GÐ!ð	Hð 	Hð 	Hñ 	Hô 	Hð 	Hð 	Hð 	Hð 	Hð 	Hð 	Høøøð 	Hð 	Hð 	Hð 	Hõ ÑÔð 	4ð 	4Ý)Ñ+Ô+ˆJÝ  ¨V°ZÑ@Ô@Ð@Ý'¨
Ñ3Ô3ˆHð	4ð 	4ð 	4ñ 	4ô 	4ð 	4ð 	4ð 	4ð 	4ð 	4ð 	4øøøð 	4ð 	4ð 	4ð 	4õ
 	‰ŒˆÝÐ!Ñ"Ô"Ð"ÝÐ)˜xÐ)Ð)Ñ*Ô*Ð*ð ˆð)	_Ø$Ÿ.š.¨Ñ5Ô5ÐW¸¿ºÈÑ9WÔ9WˆKÝ˜k­3Ñ/Ô/ð °{ð ÝØBØ#Ø(ðñ ô ð ðð ð ð ð ð ð ð ð ð ð ð ð 3Ð2Ñ4Ô4ˆIå‰GŒGˆGØ')ÐØð Ø2Ð2°6Ñ:Ô:�Ø0Ð0Ñ2Ô2�	Øð Ø4QÐ4QØ! 7°dð5ñ 5ô 5Ñ1�IÐ1ð !—n’nÐ%6¸Ñ;Ô;ˆGØð FÝÐp¥ Y¡¤ÐpÐpÐpÑqÔqÐqÝ!8Ø wØ'9Ø&ð"ñ "ô "��ð
 $ð FØÐ:Õ#:×BÒBÀ3ÑGÔG�ÝÐ;Ñ<Ô<Ð<ÝÐA DÐAÐAÐAÑBÔBÐBÐBåÐDÑEÔEÐEøøÝð 	_ð 	_ð 	_Ý0:¸3Å	Ñ0JÔ0JÐXÕ'¨Ñ,Ô,Ð,ÕPSÐTWÑPXÔPXˆGÝ‰GŒGˆGÝÐ]ÐT[Ð]Ð]Ñ^Ô^Ð^Ð^Ð^Ð^Ð^Ð^øøøøð	_øøøð ð 	õ "Ñ#Ô#ð -ð -Ý-Ñ/Ô/�
Ø(ð <Ø4I�JÐ0Ñ1Ð1à—N’NÐ#4°dÑ;Ô;Ð;Ý  Ñ,Ô,Ð,ð-ð -ð -ñ -ô -ð -ð -ð -ð -ð -ð -øøøð -ð -ð -ð -õ ‰GŒGˆGÝÐNÑOÔOÐOÝÐHÑIÔIÐIØˆFå1ØÐ&°nð
ñ 
ô 
ˆð ð 	=Ý˜~Ñ.Ô.Ð.ÝÐ;¨>Ð;Ð;Ñ<Ô<Ð<ÝÐF ;ÐFÐFÐFÑGÔGÐGÐGÐGøåð ð ð ÝÐ"Ñ#Ô#Ð#Ý˜‰oŒoÐÝð ð ð ÝÐ$˜sÐ$Ð$Ñ%Ô%Ð%Ý˜‰mŒmÐøøøøðøøøs¸   Á,BP: Ã4$D$ÄP: Ä$D(Ä(P: Ä+D(Ä,P: Ä=/E8Å,P: Å8E<Å<P: Å?E<Æ 4P: Æ5D?K5 Ë4P: Ë5
MË?AMÍP: ÍMÍP: Í/<N7Î+P: Î7N;Î;P: Î>N;Î?/P: Ï0AP: Ð:1RÑ+!RÒRc                ó$  — t          | dd¦  «        }|r0t          |¦  «        s!t          d|› �¦  «         t          d¦  «        ‚t	          ¦   «         }|p|pt          ¦   «         }|st          d¦  «         dS t          |¦  «        }t          |¦  «        }t          |¦  «        s|rWt          ¦   «          t          d|› d�¦  «         t          j        d¦  «        rt          d	¦  «         dS t          d
¦  «         dS t          d|› d�¦  «         dS )z Clear auth state for a provider.r  NzUnknown provider: r   z#No provider is currently logged in.zLogged out of r�  r  z)Hermes will use OpenRouter for inference.z9Run `hermes model` or configure an API key to use Hermes.zNo auth state found for )rÔ   r²  r.  r6  rÎ  r`  r^  r´  rÚ  rb  r    r¡   )rë  rÂ   rÑ  rØ  Úconfig_matchesrÝ  s         r<   Úlogout_commandrò  î  s@  € å˜$ 
¨DÑ1Ô1€Kàð Õ1°+Ñ>Ô>ð ÝÐ0 ;Ð0Ð0Ñ1Ô1Ð1Ý˜‰mŒmÐå Ñ"Ô"€FØÐL˜FÐLÕ&JÑ&LÔ&L€Fàð ÝÐ3Ñ4Ô4Ð4Øˆå-¨fÑ5Ô5€NÝ2°6Ñ:Ô:€Må˜6Ñ"Ô"ð ; nð ;ÝÑ Ô Ð ÝÐ/˜}Ð/Ð/Ð/Ñ0Ô0Ð0ÝŒ9Ð)Ñ*Ô*ð 	OÝÐ=Ñ>Ô>Ð>Ð>Ð>åÐMÑNÔNÐNÐNÐNåÐ9¨Ð9Ð9Ð9Ñ:Ô:Ð:Ð:Ð:r;   )r›   r%   )rD   r%   r¥   r%   r¦   r%   r›   r%   )r£   r   r·   r¸   r›   r¹   )rÂ   r%   rÃ   r$   r›   rÄ   )râ   )rD   r%   rã   rä   r›   rå   )r$  rÐ   r›   r%   )rÕ   r   r›   r  )r›   r¹   )r8  r%   r7  r  r9  r   r›   r  )r›   r   )rP  rä   r  )rx  ry  r›   r/   )r  r/   r›   r   )r  r/   rÂ   r%   r›   r¥  )r  r/   rÂ   r%   r  r/   r›   r  )
r  r/   rÂ   r%   r  r/   r«  r¹   r›   r  )rÂ   r%   r›   r¹   )rÂ   r%   r›   r%   )rÂ   r  r›   r/   )rÂ   r%   r¹  rº  r›   r   )rÂ   r%   rÖ   r%   r›   r  )rÂ   r%   rÖ   r%   r›   r¹   )rÂ   r%   r›   r¥  )r›   r  )rÂ   r  r›   r¹   rî  )rÝ  r%   r›   r%   )rî  r  rì  r  rí  r  r›   r%   )r£   r   r›   r#  )r/  r   r0  r¸   r›   r¹   )r4  r   r›   r¸   )r£   r   r›   r  )rÕ   r   r›   r/   )rÊ   r   r0  r¸   r›   r¹   )r›   r/   )rS  r/   r›   r   )rV  r   r0  r¸   r›   r¹   )r[  )rS  r/   rP  rä   r›   r/   )rt  r¹   ru  r¹   rv  r¸   r›   r/   )rt  r¹   r›   r/   )r’  r  r›   r“  )r’  r  r›   r%   )NN)r£  r  r  r¥  r›   r%   )r  r¥  r›   r%   )r½  )r¾  r¸   r›   r%   )rÅ  r%   r›   r%   )r,   r%   r¯  r%   r-   r%   r  r%   rÉ  r%   rº  r%   r›   r%   )r¯  r%   r›   rÐ  )rÛ  r%   r›   rÜ  )r¯  r%   rP  rä   r›   ró  )r  r/   r,   r%   r¯  r%   r  r%   rº  r%   r´  r%   r  r¥  r›   r/   )r,   r%   r  r%   r¯  r%   rÅ  r%   rº  r%   rP  rä   r›   r/   )r  r/   rP  rä   r›   r/   )r+  r%   r›   r%   )rI  r¹   r›   r/   )rS  r    rP  r%   r›   r  )rÊ   r%   r]  r%   rP  rä   r›   r/   )rS  r    rP  rä   r›   r    )r›   rå   )r›   r€  )r�  r�  rŽ  r  r�  r¥  r›   r€  )
rd  rœ  r*   r%   r,   r%   r-   r  r›   r/   )rd  rœ  r*   r%   r,   r%   rŸ  r%   r4  r¸   rû  r¸   r›   r/   )
rd  rœ  r*   r%   r,   r%   r]  r%   r›   r/   )
rd  rœ  r*   r%   rÊ   r%   r½  r¸   r›   r/   )
r+   r%   rD   r%   rP  rä   rÁ  rÂ  r›   r“  )r  r/   r½  r¸   r›   r¹   )
rP  rä   r�  r�  rŽ  r  rv  r¸   r›   r%   )$rÊ   r%   r]  r%   r,   r%   r*   r%   r+   r%   ri  r%   r-   r%   r  r  r  r  r×  r  rØ  r  rç  r¸   rP  rä   r�  r�  rŽ  r  rt  r¹   rè  r¹   r›   r/   )r  r/   rç  r¸   rP  rä   rt  r¹   rè  r¹   r›   r/   )r€  r/   r÷   r  )rç  r¸   rP  rä   r�  r�  rŽ  r  rè  r¹   r›   r/   )rÂ   r%   r›   r/   )rÂ   r%   r+   r%   rP  r  r›   r   )r)   NNr)   )rÒ  r“  rX  r%   rc  rd  re  rf  rg  r%   r›   r  )rÔ  r%   r›   r  )rÃ   r$   r³  r¹   r›   r  )r*   r  r+   r  r,   r  r-   r  r=  r¹   rP  rä   r�  r¹   rŽ  r  rç  r¸   r›   r/   )rÃ   r$   r›   r  )Ír8   Ú
__future__r   rô   Úloggingr    r„  rC  rˆ  r_  r…  r@  r	  r—  r  rc  r”  r2  Ú
contextlibr   Údataclassesr   r   r   r   Úhttp.serverr	   r
   Úpathlibr   Útypingr   r   r   r   Úurllib.parser   r   r   rù   rT  rŸ   r   r   r   rº  r   Ú	getLoggerr5   rÎ   r\  rÐ   r]  r�  r|  râ  rñ  rã  rò  Ú!DEFAULT_AGENT_KEY_MIN_TTL_SECONDSró  r°  r}  r{  ÚDEFAULT_GITHUB_MODELS_BASE_URLÚDEFAULT_COPILOT_ACP_BASE_URLÚDEFAULT_OLLAMA_CLOUD_BASE_URLÚSTEPFUN_STEP_PLAN_INTL_BASE_URLÚSTEPFUN_STEP_PLAN_CN_BASE_URLrc  rb  Ú'CODEX_ACCESS_TOKEN_REFRESH_SKEW_SECONDSrn  rm  Ú&QWEN_ACCESS_TOKEN_REFRESH_SKEW_SECONDSr»  rµ  r°  r/  r0  Ú)SPOTIFY_ACCESS_TOKEN_REFRESH_SKEW_SECONDSrå  r™  r!   r9   r�  Ú.GEMINI_OAUTH_ACCESS_TOKEN_REFRESH_SKEW_SECONDSr$   rš   r¤   r©   rª   r¿   rÁ   rÝ   rø   r   r  rH  r  r)  r-  r5  r@  rL  rO  ÚlocalrY  rw  r  r¤  r  r  r­  r²  r´  r¸  r¼  rÃ  rÅ  rÉ  rË  rÎ  rÖ  rÚ  rÜ  rë  r"  r.  r3  r7  r;  rD  rG  rI  rR  rU  rZ  rs  r}  r�  r�  r‘  r   r¢  r«  r±  r·  r¼  rÄ  rÈ  rÏ  rÚ  rð  r
  r  r  r#  r'  r*  r7  rD  r1  rQ  rU  rn  rq  rw  r  r‹  r›  r©  rµ  r¼  rÀ  rÕ  rÙ  rå  r÷  rú  rý  r   r  r!  r+  r/  r2  r9  rF  r  rK  rO  rZ  r\  r^  r`  rb  r­  r°  r²  rÀ  r¹  rá  rï  rò  r1   r;   r<   ú<module>r     sß  ððð ð ð #Ð "Ð "Ð "Ð "Ð "à €€€Ø €€€Ø 	€	€	€	Ø €€€Ø €€€Ø 
€
€
€
Ø €€€Ø 
€
€
€
Ø €€€Ø €€€Ø Ð Ð Ð Ø Ð Ð Ð Ø €€€Ø €€€Ø Ð Ð Ð Ø %Ð %Ð %Ð %Ð %Ð %Ø (Ð (Ð (Ð (Ð (Ð (Ð (Ð (Ø 'Ð 'Ð 'Ð 'Ð 'Ð 'Ð 'Ð 'Ø :Ð :Ð :Ð :Ð :Ð :Ð :Ð :Ø Ð Ð Ð Ð Ð Ø ,Ð ,Ð ,Ð ,Ð ,Ð ,Ð ,Ð ,Ð ,Ð ,Ð ,Ð ,Ø 6Ð 6Ð 6Ð 6Ð 6Ð 6Ð 6Ð 6Ð 6Ð 6à €€€Ø €€€à OÐ OÐ OÐ OÐ OÐ OÐ OÐ OÐ OÐ OØ 0Ð 0Ð 0Ð 0Ð 0Ð 0à	ˆÔ	˜8Ñ	$Ô	$€ðØ€L€L€L€LøØð ð ð Ø€E€E€EðøøøðØ€M€M€M€MøØð ð ð Ø€F€F€Fðøøøð Ð Ø Ð ð <Ð ØHÐ Ø%Ð Ø/Ð Ø$+Ð !Ø$'Ð !Ø()Ð %Ø@Ð Ø3Ð Ø!@Ð Ø.Ð Ø 7Ð Ø"GÐ Ø FÐ Ø6Ð Ø=Ð Ø*-Ð 'Ø9Ð ØAÐ Ø),Ð &Ø$BÐ !Ø;Ð ØHÐ Ø[Ð ØAÐ Ø,/Ð )ØŸšð "ñ ô Ð ð ˆyð*Ð ð ð ð ñ ð
 %<Ð !Ø13Ð .ð ðð ð ð ð ñ ô ñ „ðð i0Ø
ˆNˆNØØØ%Ø/Ø5Ø(Ø ðñ ô ði0ð �N�NØØØ"Ø1ð	ñ ô ði0ð  �.�.ØØØ"Ø0ð	ñ ô ð!i0ð, ˜˜ØØ$Ø"Ø<ð	ñ ô ð-i0ð8 ˆ~ˆ~ØØØØ9ØMØ/ðñ ô ð9i0ðH �>�>ØØ!Ø$Ø7Ø/ðñ ô ðIi0ðV ˆnˆnØØØØMØ=Ø*ðñ ô ðWi0ðf 
ˆ>ˆ>ØØØØ9ØGØ'ðñ ô ðgi0ðv �>�>ØØØð 8Ø@Ø(ð
ñ 
ô 
ðwi0ðL �n�nØØ&ØØ7Ø-ðñ ô ðMi0ðZ ˆ~ˆ~ØØ ØØ:Ø-Ø+ðñ ô ð[i0ðj ˆ^ˆ^ØØØØ8Ø-Ø)ðñ ô ðki0ðz ˆ~ˆ~ØØØØ=Ø-Ø+ðñ ô ð{i0ðJ ��ØØØØ6Ø\Ø-ðñ ô ðKi0ðZ ˆ~ˆ~ØØ(ØØSØ/Ø-ðñ ô ð[i0ðj ˜>˜>Ø Ø*ØØJØMØ7ðñ ô ðki0ðz �.�.ØØØØ?Ø0Ø.ðñ ô ð{i0ðJ �ØØØØ8Ø.Ø,ðñ ô ð ˆ>ØØØØ0Ø)Ø'ðñ ô ð ˆnØØØØ@Ø,Ø*ðñ ô ð !�.ØØ ØØ<Ø0Ø.ðñ ô ð #�NØØØØ7Ø2Ø0ðñ ô ð "�>ØØØð
 ;Ø1Ø/ðñ ô ð �ØØØØ<Ø.Ø,ðñ ô ð "�>ØØØØ=Ø&Ø&ðñ ô ð ˆnØØØØ:Ø,Ø*ðñ ô ð #�NØØØØ8Ø,Ø*ðñ ô ð ˆ~ØØØØLØØ+ðñ ô ð $�^ØØØØØ3Ø1ðñ ô ðCi0ð i0ð i0Ð ð ið ið iñ iñ`ð ð ð ð@ 3Ð ñð ð ð ð"ð ð Ð ð 89ð 	ð 	ñ 	ð 	ð 	ð 	ñ&ð &ð &ð &ðl Ð4¸g¸YÈ(ÐSØ	Ð<¸w¸iÈ7ÐSØÐ;Ð>dÐ>dÐ>dÐf|Ð}ØÐCÐEkÐEkÐEkð  nCð  Dð€ñ#ñ #ð #ð #ð #ñL.ð .ð .ð .ðj1ð 1ð 1ð 1ð 1�ñ 1ô 1ð 1ñ"ð ð ð ñ4Dð Dð Dð Dñ-ð -ð -ð -ð
 >Bð [ð [ñ [ð [ð [ð [ñð ð ð ñ,2ð 2ð 2ð 2ð $�I”OÑ%Ô%Ð àØ.Gð 6ñ 6ð 6ð 6ñ „ð6ñr%<ñ %<ð %<ð %<ð %<ñP!ð !ð !ð !ñH<ð <ð <ð <ñ0ð 0ð 0ð 0ñ ñ4ð 4ñ 4ñ 4ð 4ð 4ñ Sñ Sð Sð Sñ
?ñ ?ð ?ð ?ñ	Pñ 	Pñ 	Pð 	Pð 	Pñ	,ñ 	,ð 	,ð 	,ñ%ñ %ð %ð %ññ ð ð ññ ð ð ñ,9ñ 9ð 9ð 9ñ-ñ -ð -ð -ñ0ñ 0ð 0ð 0ñf%ñ %ñ %ð %ð %ñP	%ñ 	%ð 	%ð 	%ñ"ñ ð ð ð4  $ñoð '+Ø'+ñ	oð oñ oñ oð oð oñlñ ð ð ñ"9ñ 9ð 9ð 9ññ ð ð ñ(ñ (ð (ð (ñ
6ñ 
6ð 
6ð 
6ñCñ Cð Cð Cñ6ñ 6ð 6ð 6ññ ð ð ñ2ñ ð ð ð Msð Iñ Iñ Ið Ið IñEñ Eñ Eð Eð EñT  Ù $Ø Fñ	ð ñ ñ ð ð ñ@
ñ 
ð 
ð 
ñ<  ñ'ð 'ñ 'ñ 'ð 'ð 'ñTñ ð ð ñ6	ñ 	ñ 	ð 	ð 	ñ4ñ 4ñ 4ð 4ð 4ð
 #Ø&*ññ ñ ð ð ð0 #Ø&*ñ(ñ (ñ (ð (ð (ñ((ñ (ñ (ð (ð (ñ-ñ -ñ -ð -ð -ñ!ñ !ñ !ð !ð !ñ
Hñ Hð Hð Hñ
4ñ 4ð 4ð 4ñ*1ñ 1ð 1ð 1ñ0#+ñ #+ð #+ð #+ñR #ñ$ð $ñ $ñ $ð $ð $ð^ 04ñ!ð !ñ !ñ !ð !ð !ñV "ñ,ð ,ñ ,ñ ,ð ,ð ,ñd "ñ=ð =ñ =ñ =ð =ð =ñD  Ù $Ø Iñ	-ð -ñ -ñ -ð -ð -ñ`ñ ð ð ñ&:ñ :ð :ð :ñzZ)ñ Z)ð Z)ð Z)ñ@Añ Að Að Añ )-ñ .ð .ñ .ñ .ð .ð .ñb%ñ %ñ %ð %ð %ñ$ "ñ	eð eñ eñ eð eð eñPñ ð ð ñ*ñ ð ð ñH  Ù $Ø Gñ	*ð *ñ *ñ *ð *ð *ñbñ ð ð ð(  $Ø#Ø+/ñ	 ð  ñ  ñ  ð  ð  ñNñ ð ð ñ6.Eñ .Eð .Eð .Eñj6Wñ 6Wð 6Wð 6WñrWñ Wð Wð WðJ "Ùñ6*ð 6*ñ 6*ñ 6*ð 6*ð 6*ñrPñ Pð Pð Pð "Ø#Ø#Ø AñP%ð P%ñ P%ñ P%ð P%ð P%ñt Ø#Ø!%Ø $Ø#Ø*.Ø@Ø!Ø#Ø#ÙÙñ%Rð Rñ Rñ Rð Rð Rðp  AØ!ÙÙñð ñ ñ ð ð ñ> (Ð ð  ñ2ð 2ñ 2ñ 2ð 2ð 2ðn  AØ!Ø#Ø#Ùñvð vñ vñ vð vð vñzñ ð ð ñ-)ñ -)ð -)ð -)ñ`2(ñ 2(ð 2(ð 2(ñj.
ñ .
ð .
ð .
ñbñ ð ð ñ>ñ ð ð ñ< ñ  ñ  ð  ð  ñ:#ñ #ð #ð #ñL%ñ %ð %ð %ð^ $(ñ?ñ ?ñ ?ð ?ð ?ñDñ ð ð ñ$Añ Að Að Aññ ð ð ññ ð ð ð* Ø37Ø.2Øñmñ mñ mð mð mñ`ñ ð ð ñ"ñ ð ð ñ "ñ	GLð GLñ GLñ GLð GLð GLñTNñ Nð Nð Nðf &*Ø(,Ø#ØÙØ!ÙØ#Ù%ñ@ð @ñ @ñ @ð @ð @ñF}ñ }ð }ð }ñ@;ñ ;ð ;ð ;ð ;ð ;s$   Â)B. Â.B8Â7B8Â<C ÃCÃ
C