
    epjxE                        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.
    -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/thesage/.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@@sz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 )zPrint 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,   payloadr3   s        r!   _emit_resultr>   a   s   W-8@$*[)))b W W W B+VVW
  1dj+++,,,,	 1;;w 
	14''"2443:FFFFF[[## 	1;;v&&D df $*WQ///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KTQ!''))s:J:JAq:J:J:Jr'   z,hermes send: no targets found for platform 'z'. Configured: z, z(none)r   )r1   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_directoryrA   rB   	Exceptionr   r   r   r;   dictr:   gateway.configrD   get_connected_platformsgetattrr)   
setdefaultr%   rK   itemsjoinsortedr6   r9   r<   )r?   r*   rA   rB   r   r0   rC   rD   	gw_configplat	plat_namefilteredchannelschrS   rV   suffixrO   s                    @r!   _list_targetsrj      s   	
 	
 	
 	
 	
 	
 	
 	
 	
    EEECJWWWWn   EEECJWWWW SWW[))/R00I666666''))	5577 	0 	0Dgs4yy99I>>>  B////		0
     	
  
##%%++--KKKKY__%6%6KKK 	!J J J#yy	):):;;GxJ JZ   
 ! 	 dj+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'ooo 	2333 	3 	3B66&#&&DffTll=bffY&7&7=2G)0LW__%7%%%%"F1y114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  }| ry|                                re	  | t          |          dd           nH# t          $ r0 	  | t          |          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          t"          t$          t&          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.envTr   )overrider   zlatin-1zconfig.yaml)read_user_config_raw)_expand_env_vars)managed_scope)dotenvrm   rZ   hermes_cli.configrn   existsr)   r   osrp   rq   
hermes_clirr   apply_managed_overlay
isinstancer[   r`   r-   floatr+   environ)rm   rn   homeenv_pathrv   config_pathrp   r0   rq   rr   rO   vals               r!   _load_hermes_envr      s   (&&&&&&&   555555      f}H 	x(( 		KHwGGGGG! 	 	 	CMMD9MMMMM    	 	 	D	 III&K  	;:::::"";//   666666s##   
,,,,,,11C9N9N2V##TVWW    c4   IIKK # #S#S%677 	"*c((
3# #s   	 - 
;;A6 6
B;BB;
B*'B;)B**B;/	B;:B;C0 0
C>=C>D 
D! D!%2E 
E%$E%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messageNr6   )r*   tozhermes 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^   rj   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   <  s     t^U++  "$	488!/WT6SX=Y=YZZZ	WT46677F 	A
 	
 	
 	
 	
 	 i&&fd## G gmmooA	
 	
 	
 	

 	 dIt,,G 544'.."2"244 :99999  I y))F$..dGU++  I
 HY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 )&zCreate 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TARGETNzDelivery 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.)metavarrQ   r   r   rT   z4Message text. If omitted, read from --file or stdin.)nargsrQ   r   z-fz--filePATHzRead 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   rQ   r   z-qz--quietz,Suppress stdout on success (exit code only).)r   rQ   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 !<- #  F2 #     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   rk   )r   r   r   rk   )r   r   )__doc__
__future__r   r   r6   r   pathlibr   typingr   r   r;   r<   r"   r&   r>   rj   r   r   r   __all__rJ   r'   r!   <module>r      s&   4 # " " " " "   



             . . . .b   * * * *ZW W W WtQ# Q# Q# Q#hC C C CLd d d dN 0
1r'   