§
    øžyjãG  ã                  ó’   — d Z ddlmZ ddlZddlZddlZddlmZ ddlm	Z	 dZ
dZ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 gZdS )(u  CLI subcommand: ``hermes send`` â€” pipe text from shell scripts to any
configured messaging platform (Telegram, Discord, Slack, Signal, SMS, etc.).

This is a thin wrapper around ``tools.send_message_tool.send_message_tool``
that exposes its functionality as a standalone CLI entry point so ops
scripts, cron jobs, CI hooks, and monitoring daemons can reuse the gateway's
already-configured credentials without having to reimplement each platform's
REST API client.

Design notes:

* No LLM, no agent loop â€” the subcommand just resolves arguments, reads the
  message body, calls the shared tool function, and prints/returns the
  result. It is intentionally fast, cheap, and side-effect-only.
* For platforms that send via bot token (Telegram, Discord, Slack, Signal,
  SMS, WhatsApp-CloudAPI, â€¦) no running gateway is required. The tool
  talks directly to each platform's REST endpoint. For platforms that rely
  on a persistent adapter connection (plugin platforms, Matrix in some
  modes, â€¦) a live gateway is needed; the underlying tool surfaces that
  error to the caller.
* Exit codes follow the classic Unix convention:
    0 â€” delivery (or list) succeeded
    1 â€” delivery failed at the platform level
    2 â€” usage / argument / config error (argparse already uses 2)
é    )ÚannotationsN)ÚPath)ÚOptionalé   é   Ú
positionalúOptional[str]Ú	file_pathÚreturnc                ó\  — | r| S |rå|dk    rt           j                             ¦   «         S 	 t          |¦  «                             d¬¦  «        S # t
          $ rD t          d|› d|› d|› d|› d�	t           j        ¬	¦  «         t          j        t          ¦  «         Y nPt          $ rD}t          d
|› d|› �t           j        ¬	¦  «         t          j        t          ¦  «         Y d}~nd}~ww xY wt           j                             ¦   «         s"t           j                             ¦   «         }|r|S dS )u8  Resolve the message body from (in order):

    1. An explicit positional message argument.
    2. ``--file PATH`` or ``--file -`` (where ``-`` means stdin).
    3. Piped stdin when it is not attached to a TTY.

    Returns ``None`` when nothing is available â€” callers must treat that as
    a usage error.
    ú-zutf-8)Úencodingúhermes send: zæ is not a text file. --file reads the message *body* (logs, reports, markdown).
To send an image/document/audio file as a native attachment, reference it with MEDIA: in the message text instead:
  hermes send --to telegram "MEDIA:z6"
  hermes send --to telegram "optional caption MEDIA:zv"
Add [[as_document]] to deliver an image as an uncompressed file:
  hermes send --to telegram "[[as_document]] MEDIA:ú"©Úfilezhermes send: cannot read z: N)ÚsysÚstdinÚreadr   Ú	read_textÚUnicodeDecodeErrorÚprintÚstderrÚexitÚ_USAGE_EXITÚOSErrorÚisatty)r   r
   ÚexcÚdatas       ú9/home/ragecks/.hermes/hermes-agent/hermes_cli/send_cmd.pyÚ_read_message_bodyr!   )   s’  € ð ð ØÐàð "Ø˜ÒÐÝ”9—>’>Ñ#Ô#Ð#ð	"Ý˜	‘?”?×,Ò,°gÐ,Ñ>Ô>Ð>øÝ!ð 	"ð 	"ð 	"ÝðS 	ð Sð Sð 7@ð	Sð Sð
 HQðSð Sð GPðSð Sð Sõ ”Zð
ñ 
ô 
ð 
õ ŒH•[Ñ!Ô!Ð!Ð!Ð!Ýð 	"ð 	"ð 	"ÝÐ@¨iÐ@Ð@¸3Ð@Ð@ÅsÄzÐRÑRÔRÐRÝŒH•[Ñ!Ô!Ð!Ð!Ð!Ð!Ð!Ð!øøøøð	"øøøõ Œ9×ÒÑÔð ÝŒy�~Š~ÑÔˆØð 	ØˆKàˆ4s   ¬"A ÁAC)Â	C)Â%:C$Ã$C)Úarg_toc                óZ   — | r(|                       ¦   «         r|                       ¦   «         S dS )zAReturn a cleaned ``--to`` value, or ``None`` when nothing is set.N)Ústrip)r"   s    r    Ú_resolve_targetr%   Z   s,   € àð �&—,’,‘.”.ð Ø�|Š|‰~Œ~ÐØˆ4ó    Úresult_jsonÚstrÚ	json_modeÚboolÚquietÚintc               óÄ  — 	 | rt          j        | ¦  «        ni }n# t           j        $ r d| dœ}Y nw xY w|r$t          t          j        |d¬¦  «        ¦  «         n¬|rn©|                     d¦  «        r%t          d|d         › �t          j        ¬¦  «         no|                     d¦  «        r7|                     d	¦  «        }|rt          |¦  «         n3t          d
¦  «         n#t          t          j        |d¬¦  «        ¦  «         |                     d¦  «        rt          S |                     d¦  «        rt          S |                     d¦  «        rt          S t          S )zÕPrint the tool result in the requested format and return the exit code.

    The underlying ``send_message_tool`` always returns a JSON string. We
    parse it, decide success/failure, and format accordingly.
    z#invalid JSON from send_message_tool)ÚerrorÚrawr   )Úindentr.   r   r   ÚsuccessÚnoteÚsentÚskipped)
ÚjsonÚloadsÚJSONDecodeErrorr   ÚdumpsÚgetr   r   Ú_FAILURE_EXITÚ_SUCCESS_EXIT)r'   r)   r+   Úpayloadr2   s        r    Ú_emit_resultr=   a   s‚  € ðWØ-8Ð@•$”*˜[Ñ)Ô)Ð)¸bˆˆøÝÔð Wð Wð Wð BÈ+ÐVÐVˆˆˆðWøøøð
 ð 1Ý�dŒj˜¨Ð+Ñ+Ô+Ñ,Ô,Ð,Ð,Ø	ð 1Øà�;Š;�wÑÔð 
	1ÝÐ4 '¨'Ô"2Ð4Ð4½3¼:ÐFÑFÔFÐFÐFØ�[Š[˜Ñ#Ô#ð 	1Ø—;’;˜vÑ&Ô&ˆDØð Ý�d‘”��å�f‘”��õ •$”*˜W¨QÐ/Ñ/Ô/Ñ0Ô0Ð0à‡{‚{�7ÑÔð ÝÐØ‡{‚{�9ÑÔð ÝÐØ‡{‚{�9ÑÔð ÝÐåÐs   ‚ ›2±2Úplatform_filterc          
     ó  ‡— 	 ddl m}m} n<# t          $ r/}t	          d|› �t
          j        ¬¦  «         t          cY d}~S d}~ww xY w	  |¦   «         }n<# t          $ r/}t	          d|› �t
          j        ¬¦  «         t          cY d}~S d}~ww xY wt          | 	                    d¦  «        pi ¦  «        }	 ddl
m}  |¦   «         }|                     ¦   «         D ];}	t          |	d	t          |	¦  «        ¦  «        }
|
d
v rŒ%|                     |
g ¦  «         Œ<n# t          $ r Y nw xY w| r”|                      ¦   «                              ¦   «         Šˆfd„|                     ¦   «         D ¦   «         }|sJt	          d| › dd                     t)          |¦  «        ¦  «        pd› �t
          j        ¬¦  «         t          S |}|r2t	          t+          j        d|idt          ¬¦  «        ¦  «         t.          S |s4t	          d¦  «         t	          d¦  «         t	          d¦  «         t.          S | €t	           ||¦  «        ¦  «         t.          S t)          |¦  «        D ]ª}
||
         }t	          |
› d�¦  «         |st	          d¦  «         Œ.|D ]k}| 	                    dd¦  «        }| 	                    d¦  «        p| 	                    d¦  «        pd}|r||k    rd|› d�nd}t	          d|
› d|› |› �¦  «         Œlt	          ¦   «          Œ«t.          S )u4  Print the channel directory (all configured targets across platforms).

    Uses ``load_directory()`` for structured JSON output and
    ``format_directory_for_display()`` for the human-readable rendering that
    the send_message tool itself shows to the model â€” keeps the two surfaces
    identical.
    r   )Úformat_directory_for_displayÚload_directoryz/hermes send: failed to load channel directory: r   Nz/hermes send: failed to read channel directory: Ú	platforms)Úload_gateway_configÚvalue)ÚlocalÚ
api_serverÚwebhookc                óL   •— i | ] \  }}|                      ¦   «         ‰k    ¯||“Œ!S © )Úlower)Ú.0ÚkÚvÚkeys      €r    ú
<dictcomp>z!_list_targets.<locals>.<dictcomp>½   s1   ø€ ÐKÐKÐK™T˜Q ¸!¿'º'¹)¼)ÀsÒ:JÐ:J�A�qÐ:JÐ:JÐ:Jr&   z,hermes send: no targets found for platform 'z'. Configured: z, z(none)r   )r0   Údefaultz@No messaging platforms configured or no channels discovered yet.zBSet one up with `hermes gateway setup`, or run the gateway once soz@channel discovery can populate ~/.hermes/channel_directory.json.ú:z  (no channels discovered yet)Únameú?ÚidÚchat_idÚ z  [Ú]z  )Úgateway.channel_directoryr@   rA   Ú	Exceptionr   r   r   r:   Údictr9   Úgateway.configrC   Úget_connected_platformsÚgetattrr(   Ú
setdefaultr$   rJ   ÚitemsÚjoinÚsortedr5   r8   r;   )r>   r)   r@   rA   r   r/   rB   rC   Ú	gw_configÚplatÚ	plat_nameÚfilteredÚchannelsÚchrR   rU   ÚsuffixrN   s                    @r    Ú_list_targetsri   Ž   sô  ø€ ðð	
ð 	
ð 	
ð 	
ð 	
ð 	
ð 	
ð 	
ð 	
øõ ð ð ð ÝÐEÀÐEÐEÍCÌJÐWÑWÔWÐWÝÐÐÐÐÐÐøøøøðøøøðØˆnÑÔˆˆøÝð ð ð ÝÐEÀÐEÐEÍCÌJÐWÑWÔWÐWÝÐÐÐÐÐÐøøøøðøøøõ �S—W’W˜[Ñ)Ô)Ð/¨RÑ0Ô0€IðØ6Ð6Ð6Ð6Ð6Ð6à'Ð'Ñ)Ô)ˆ	Ø×5Ò5Ñ7Ô7ð 	0ð 	0ˆDÝ  g­s°4©y¬yÑ9Ô9ˆIØÐ>Ð>Ð>ØØ× Ò  ¨BÑ/Ô/Ð/Ð/ð		0øõ
 ð ð ð ð 	ˆðøøøð
 ð 
Ø×#Ò#Ñ%Ô%×+Ò+Ñ-Ô-ˆØKÐKÐKÐK Y§_¢_Ñ%6Ô%6ÐKÑKÔKˆØð 	!ÝðJ¸ð Jð JØ#Ÿyšy­°	Ñ):Ô):Ñ;Ô;ÐG¸xðJð Jå”Zðñ ô ð õ
 !Ð Øˆ	àð Ý�dŒj˜+ yÐ1¸!ÅSÐIÑIÔIÑJÔJÐJÝÐàð ÝÐPÑQÔQÐQÝÐRÑSÔSÐSÝÐPÑQÔQÐQÝÐð
 ÐÝÐ*Ð*¨9Ñ5Ô5Ñ6Ô6Ð6ÝÐå˜IÑ&Ô&ð ð ˆ	Ø˜YÔ'ˆÝ�ˆoˆoˆoÑÔÐØð 	ÝÐ2Ñ3Ô3Ð3ØØð 	3ð 	3ˆBØ—6’6˜& #Ñ&Ô&ˆDØ—f’f˜T‘l”lÐ= b§f¢f¨YÑ&7Ô&7Ð=¸2ˆGØ)0ÐL°WÀ²_°_Ð%˜7Ð%Ð%Ð%Ð%È"ˆFÝÐ1�yÐ1Ð1 4Ð1¨Ð1Ð1Ñ2Ô2Ð2Ð2Ý‰ŒˆˆåÐsJ   ƒ Œ
A–$A ºAÁ AÁ	
A Á
BÁ$BÂBÂBÂ5A D Ä
D#Ä"D#ÚNonec                 óž  — 	 ddl m}  n# t          $ r d} Y nw xY w	 ddlm}  |¦   «         }n# t          $ r Y dS w xY w|dz  }| rã|                     ¦   «         rÏ	  | t          |¦  «        dd¬¦  «         n²# t          $ rš 	 ddl}ddl	}| 
                    ¦   «         }|                     |j        ¦  «        r|t          |j        ¦  «        d…         } | |                     |                     d	¦  «        ¦  «        d¬
¦  «         n# t          $ r Y nw xY wY nt          $ r Y nw xY wddl}|dz  }|                     ¦   «         sdS 	 ddlm}	  |	|¦  «        }n# t          $ r Y dS w xY w	 ddlm}
  |
|¦  «        }n# t          $ r Y nw xY w	 ddlm} |                     t-          |t.          ¦  «        r|ni ¦  «        }n# t          $ r Y nw xY wt-          |t.          ¦  «        sdS |                     ¦   «         D ]O\  }}t-          |t          t2          t4          t6          f¦  «        sŒ.||j        v rŒ8t          |¦  «        |j        |<   ŒPdS )uÙ  Populate ``os.environ`` from ``~/.hermes/.env`` AND bridge top-level
    ``config.yaml`` keys into the environment so the underlying gateway
    config loader sees platform credentials and home channel IDs.

    ``send_message_tool`` reads tokens and home-channel IDs via
    ``os.getenv(...)`` on each call. The gateway process does two things at
    startup that ``hermes send`` must replicate when invoked standalone:

    1. ``load_dotenv(~/.hermes/.env)`` â€” brings bot tokens into the env.
    2. Bridge top-level simple values from ``~/.hermes/config.yaml`` into
       ``os.environ`` (without overriding existing env vars). This is where
       ``TELEGRAM_HOME_CHANNEL`` and friends live when the user saved them
       via ``hermes config set``.

    See ``gateway/run.py`` for the canonical version of this bridge â€” we
    intentionally reimplement the minimum needed here so ``hermes send``
    doesn't pull in the full gateway module just to resolve a home channel.
    r   )Úload_dotenvN)Úget_hermes_homez.envTz	utf-8-sig)Úoverrider   zlatin-1)Ústreamrn   zconfig.yaml)Úread_user_config_raw)Ú_expand_env_vars)Úmanaged_scope)Údotenvrl   rY   Úhermes_cli.configrm   Úexistsr(   r   ÚcodecsÚioÚ
read_bytesÚ
startswithÚBOM_UTF8ÚlenÚStringIOÚdecodeÚosrp   rq   Ú
hermes_clirr   Úapply_managed_overlayÚ
isinstancerZ   r_   r,   Úfloatr*   Úenviron)rl   rm   ÚhomeÚenv_pathrv   rw   r/   r~   Úconfig_pathrp   rq   rr   rN   Úvals                 r    Ú_load_hermes_envrˆ   è   sS  € ð(Ø&Ð&Ð&Ð&Ð&Ð&Ð&øÝð ð ð ØˆˆˆðøøøðØ5Ð5Ð5Ð5Ð5Ð5ØˆÑ Ô ˆˆøÝð ð ð Øˆˆðøøøð �f‰}€HØð �x—’Ñ(Ô(ð ð	ð ˆK�˜H™œ°¸{ÐKÑKÔKÐKÐKøÝ!ð 	ð 	ð 	ð
à���Ø�	�	�	à×)Ò)Ñ+Ô+�Ø—>’> &¤/Ñ2Ô2ð 6Ø�c &¤/Ñ2Ô2Ð4Ð4Ô5�CØ� 2§;¢;¨s¯zªz¸)Ñ/DÔ/DÑ#EÔ#EÐPTÐUÑUÔUÐUÐUøÝð ð ð Ø�ðøøøøøåð 	ð 	ð 	ØˆDð	øøøð €I€I€IØ˜Ñ&€KØ×ÒÑÔð Øˆðð 	;Ð:Ð:Ð:Ð:Ð:Ø"Ð" ;Ñ/Ô/ˆˆøÝð ð ð ØˆˆðøøøðØ6Ð6Ð6Ð6Ð6Ð6ØÐ˜sÑ#Ô#ˆˆøÝð ð ð Øˆðøøøð
Ø,Ð,Ð,Ð,Ð,Ð,Ø×1Ò1½ÀCÍÑ9NÔ9NÐ2V°#°#ÐTVÑWÔWˆˆøÝð ð ð Øˆðøøøõ �c�4Ñ Ô ð Øˆà—I’I‘K”Kð #ð #‰ˆˆSÝ˜#¥¥S­%µÐ6Ñ7Ô7ð 	ØØ�"”*ÐÐØÝ˜c™(œ(ˆŒ
�3‰ˆð#ð #s‹   ‚	 ‰—œ- ­
;º;ÁA6 Á6
D%ÂBDÄD%Ä
DÄD%ÄDÄD%Ä	D%Ä$D%ÅE Å
E(Å'E(Å,E> Å>
FÆ
FÆ2G Ç
GÇGÚargsúargparse.Namespacec           	     ót  — t          ¦   «          t          | dd¦  «        rEt          | dd¦  «        }t          |t          | dd¦  «        ¬¦  «        }t          j        |¦  «         t          t          | dd¦  «        ¦  «        }|s4t          dt          j        ¬	¦  «         t          j        t          ¦  «         t          t          | dd¦  «        t          | d
d¦  «        ¦  «        }|�| 
                    ¦   «         s4t          dt          j        ¬	¦  «         t          j        t          ¦  «         t          | dd¦  «        }|r|› d|                     ¦   «         › �}ddlm} d||dœ} ||¦  «        }t          |t          | dd¦  «        t          | dd¦  «        ¬¦  «        }t          j        |¦  «         dS )z9Entry point wired into the top-level argparse dispatcher.Úlist_targetsFÚmessageNr5   )r)   ÚtozËhermes send: --to PLATFORM[:channel[:thread]] is required
Examples:
  hermes send --to telegram "hello"
  hermes send --to discord:#ops --file report.md
  hermes send --list      # list available targetsr   r   znhermes send: no message provided. Pass text as a positional argument, use --file PATH, or pipe data via stdin.Úsubjectz

r   )Úsend_message_toolÚsend)ÚactionÚtargetr�   r+   )r)   r+   )rˆ   r]   ri   r   r   r%   r   r   r   r!   r$   ÚlstripÚtools.send_message_toolr�   r=   )	r‰   r>   Ú	exit_coder“   r�   r�   r�   Ú	tool_argsÚresults	            r    Úcmd_sendr™   H  sõ  € õ ÑÔÐõ ˆt�^ UÑ+Ô+ð õ " $¨	°4Ñ8Ô8ˆÝ! /½WÀTÈ6ÐSXÑ=YÔ=YÐZÑZÔZˆ	ÝŒ�ÑÔÐå�W T¨4°Ñ6Ô6Ñ7Ô7€FØð 	ÝðAõ
 ”ð	
ñ 	
ô 	
ð 	
õ 	Œ•ÑÔÐå Ý��i Ñ&Ô&Ý��f˜dÑ#Ô#ñô €Gð €˜gŸmšm™oœo€ÝðAå”ð	
ñ 	
ô 	
ð 	
õ
 	Œ•ÑÔÐõ �d˜I tÑ,Ô,€GØð 5ØÐ4Ð4 '§.¢.Ñ"2Ô"2Ð4Ð4ˆð :Ð9Ð9Ð9Ð9Ð9ð ØØðð €Ið Ð˜yÑ)Ô)€FÝØÝ˜$ ¨Ñ.Ô.Ý�d˜G UÑ+Ô+ðñ ô €Iõ
 „HˆYÑÔÐÐÐr&   úargparse.ArgumentParserc                óî  — |                       ddddt          j        ¬¦  «        }|                     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$¬"¦  «         |                     t
          ¬%¦  «         |S )&zåCreate the ``send`` subparser and return it.

    Kept as a standalone function so the top-level parser builder can wire
    it in next to the other messaging subcommands without cluttering
    ``_parser.py`` or ``main.py``.
    r‘   zASend a message to a configured platform (scripts, cron jobs, CI).u!  Pipe text from any shell script to any messaging platform Hermes is already configured for. Reuses the gateway's platform credentials (~/.hermes/.env + ~/.hermes/config.yaml) â€” no LLM, no agent loop, no running gateway required for bot-token platforms like Telegram/Discord/Slack/Signal.aå  Examples:
  hermes send --to telegram "deploy finished"
  echo "RAM 92%" | hermes send --to telegram:-1001234567890
  hermes send --to discord:#ops --file /tmp/report.md
  hermes send --to slack:#eng --subject "[CI]" --file build.log
  hermes send --to telegram "MEDIA:/tmp/chart.png"   # send a media attachment
  hermes send --list                  # all platforms
  hermes send --list telegram         # filter by platform

Exit codes: 0 ok, 1 delivery/backend error, 2 usage error.)ÚhelpÚdescriptionÚepilogÚformatter_classz-tz--toÚTARGETNzéDelivery target. Format: 'platform' (home channel), 'platform:chat_id', 'platform:chat_id:thread_id', or 'platform:#channel-name'. Examples: telegram, telegram:-1001234567890:17585, discord:#ops, slack:C0123ABCD, signal:+15551234567.)ÚmetavarrP   rœ   r�   rS   z4Message text. If omitted, read from --file or stdin.)ÚnargsrP   rœ   z-fz--fileÚPATHzšRead message body from PATH (text only). Use '-' to force stdin. To send an image/document as an attachment, use MEDIA:<path> in the message text instead.z-sz	--subjectÚLINEz6Prepend a subject/header line before the message body.z-lz--listrŒ   Ú
store_trueFzRList available targets. Optional positional filter: `hermes send --list telegram`.)Údestr’   rP   rœ   z-qz--quietz,Suppress stdout on success (exit code only).)r’   rP   rœ   z--jsonz6Emit raw JSON result instead of human-readable output.)Úfunc)Ú
add_parserÚargparseÚRawDescriptionHelpFormatterÚadd_argumentÚset_defaultsr™   )Ú
subparsersÚparsers     r    Úregister_send_subparserr¯   Ž  s˜  € ð ×"Ò"ØØPð<ð	Iõ !Ô<ð- #ñ ô €Fð2 ×ÒØØØØð#ð ñ ô ð ð ×ÒØØØØCð	 ñ ô ð ð ×ÒØØØØð(ð ñ 
ô 
ð 
ð ×ÒØØØØØEð ñ ô ð ð ×ÒØØØØØØað ñ ô ð ð ×ÒØØØØØ;ð ñ ô ð ð ×ÒØØØØEð	 ñ ô ð ð ×Ò�XÐÑ&Ô&Ð&Ø€Mr&   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   rj   )r‰   rŠ   r   rj   )r   rš   )Ú__doc__Ú
__future__r   r©   r5   r   Úpathlibr   Útypingr   r   r:   r;   r!   r%   r=   ri   rˆ   r™   r¯   Ú__all__rI   r&   r    ú<module>rµ      s&  ððð ð4 #Ð "Ð "Ð "Ð "Ð "à €€€Ø €€€Ø 
€
€
€
Ø Ð Ð Ð Ð Ð Ø Ð Ð Ð Ð Ð ð €Ø€Ø€ð.ð .ð .ð .ðbð ð ð ð*ð *ð *ð *ðZWð Wð Wð Wðt]#ð ]#ð ]#ð ]#ð@Cð Cð Cð CðLdð dð dð dðN Ð0Ð
1€€€r&   