
    PmjX                    &   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	m
Z
 ddlmZmZ ddlmZ ddlmZmZ dd	lmZ dad
ed<   dZd
ed<   d,dZd,dZd-dZd.dZd.dZd.dZd/dZd0dZ d1d Z!d0d!Z"d2d#Z#d.d$Z$d3d%Z%d1d&Z&d'd(d4d+Z'dS )5u  
``hermes photon ...`` CLI subcommands — registered by the plugin via
``ctx.register_cli_command()``.

Subcommands:

    setup              full first-time setup (device login + project + user + sidecar)
    status             show login + project + sidecar dep state
    install-sidecar    npm install inside plugins/platforms/photon/sidecar/
    telemetry          show or toggle Spectrum SDK telemetry (on/off)

The device-code login runs automatically as the first step of ``setup``;
there is no standalone ``login`` verb (matching how every other Hermes
gateway channel onboards through a single setup surface).

Photon uses the spectrum-ts gRPC stream for inbound — there is no webhook
to register, so there are no webhook subcommands.
    )annotationsN)Path)Colorscolor   )auth)_NPM_ERROR_LOG_MAX_CHARSsidecar_deps_installed)resolve_sidecar_dirzPath | None_SIDECAR_DIR_NPM_ERROR_LOGreturnr   c                 :    t           t                      a t           S )zBSidecar runtime dir, resolved once on first use (never at import).)r   r        B/home/thesage/.hermes/hermes-agent/plugins/platforms/photon/cli.py_sidecar_dirr   0   s     *,,r   c                 @    t           t           S t                      dz  S )zEPath of the persisted npm-failure log (derived from the sidecar dir).Nz.photon-npm-error.log)r   r   r   r   r   _npm_error_logr   8   s    !>>333r   parserargparse.ArgumentParserNonec                   |                      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          "           dS )#z(Wire up `hermes photon ...` subcommands.photon_commandF)destrequiredsetupz:First-time setup (device login + project + user + sidecar))helpz--project-nameNz&Project name (default: 'Hermes Agent'))defaultr   z--phonez+Your E.164 phone number (e.g. +15551234567)z--first-name)r   z--last-namez--emailz--no-browser
store_truez@Don't try to open a browser for device login; print the URL only)actionr   z--skip-sidecar-installz/Skip `npm install` inside the sidecar directorystatusz(Show login + project + sidecar dep stateinstall-sidecarz,Run npm install inside the sidecar directory	telemetryz.Show or toggle Spectrum SDK telemetry (on/off)state?)onoffz9Turn telemetry on or off (omit to show the current state))nargschoicesr   )func)add_subparsers
add_parseradd_argumentset_defaultsdispatch)r   subsp_setupp_telemetrys       r   register_clir4   B   s     &6 GGDooI   G )4F  H H HDK  M M M666555D111`  b b b1,O  Q Q Q 	OOH#MONNNOO%,ZO[[[//= "  K sMH    
 X&&&&&r   argsargparse.Namespaceintc                .   t          | dd           }|t          |           S |dk    rt          |           S |dk    rt          |           S |dk    rt          |           S |dk    rt	          |           S t          d| t          j                   dS )	Nr   r   r"   r#   r$   zunknown subcommand: file   )getattr_cmd_status
_cmd_setup_cmd_install_sidecar_cmd_telemetryprintsysstderr)r5   subs     r   r0   r0   h   s    
$($
/
/C
{4   
g~~$
h4   
#D)))
kd###	
&
&
&SZ88881r   c                    d }	 t          j        | j         |          }n6# t          $ r)}t	          d| t
          j                   Y d}~dS d}~ww xY w|}t	          dt          j                                dS )	u  Run the RFC 8628 device-code login flow and persist the token.

    Internal helper — invoked as the first step of ``setup``. There is
    no standalone ``hermes photon login`` command; Photon onboards
    through the single ``setup`` surface like every other channel.
    c                   | j         p| j        }t                       t          d           t          d|            t          d| j                    t          d           t          d           t                       d S )Nu   ┌─ Photon device login ────────────────────────────────────────u   │  Open this URL:  u   │  Enter the code: u0   │  (waiting for approval — Ctrl-C to cancel)   └──────────────────────────────────────────────────────────────)verification_uri_completeverification_urirA   	user_code)codetargets     r   _print_codez&_run_device_login.<locals>._print_code   s    /H43H  d  	e  	e  	e.f..///6dn66777@AAA  N  	O  	O  	Or   )open_browseron_user_codezlogin failed: r9   Nr   u!   ✓ logged in — token saved to r   )photon_authlogin_device_flow
no_browser	ExceptionrA   rB   rC   _auth_json_path)r5   rM   tokene_s        r   _run_device_loginrX   |   s      -!_,$
 
 
    "q""4444qqqqq
 	A	
Mk.I.K.K
M
MNNN1s   " 
AAAc                @   t          j                    }|rWt          d           t          j        |          rt          d           n$t          d           t          j                     d }|sYt          d           t          |           }|dk    r|S t          j                    }|st          dt          j                   dS nt          d	           | j        pt           j	        }t          j
                    }	 |rt          d
           nt          j        ||          }|r1|                    d          r|d         }t          d| d           nMt          d| d           t          j        ||          }|                    d          }t          d           n6# t          $ r)}t          d| t          j                   Y d }~dS d }~ww xY w|st          dt          j                   dS 	 t          d           |}t          j                    \  }	}
d}d}|	r/|
r-	 t          j        |	|
           |
}d}n# t          $ r d}Y nw xY w|st          j        ||          }t          j        ||||           |rt          d| d           n"t          d| d           t          d           n6# t          $ r)}t          d| t          j                   Y d }~dS d }~ww xY w| j        p&t)          t+          dt,          j                            }d }d }d }|st          d           n| j        }| j        }	 t          j        ||||| j        |           \  }}ng# t8          $ r)}t          d!| t          j                   Y d }~dS d }~wt          $ r)}t          d"| t          j                   Y d }~dS d }~ww xY wt          |rd#nd$           |}|                    d          }t          j        |          }t=          |           |sd	 t          j        ||          }|r|                    d%          }n6# t          $ r)}t          d&| d't          j                   Y d }~nd }~ww xY w|rt                       t          t+          d(t,          j                              t          t+          d)t,          j                   t+          tC          |          t,          j         t,          j"                  z              t          t+          d*t,          j                              t          t+          d+t,          j                              nt          d,           |ra	 t          j#        |||rtC          |          nd |-           n6# t          $ r)}t          d.| d't          j                   Y d }~nd }~ww xY w| j$        rt          d/           n%t          d0           tK                      }|dk    r|S 	 dd1l&m'}  |d2d3dd4           t          d5           n6# t          $ r)}t          d6| d't          j                   Y d }~nd }~ww xY wt                       t          d7           t          d8           dS )9Nz'[1/5] Checking existing Photon token...u     ✓ token is validuB     ✗ token is stale (dashboard rejected it) — re-authenticatingu=   [1/5] No valid Photon token found — running device login...r   z(login completed but token was not storedr9   r   z#[1/5] Reusing existing Photon tokenz'[2/5] Reusing configured Photon projectidz[2/5] Found existing project ''z[2/5] Creating Photon project 'z'...)nameu     ✓ project createdzproject setup failed: z%could not resolve a Photon project idz*[3/5] Provisioning Spectrum credentials... FT)spectrum_project_idproject_secretdashboard_project_idr\   u!     ✓ Spectrum ready (project id u    ) — existing credentials validu   ) — new secret savedu     ⚠ Project secret was regenerated. If the gateway is running, restart it so the sidecar picks up the new secret:
      hermes gateway restartzspectrum provisioning failed: z=[4/5] Your iMessage phone number (E.164, e.g. +15551234567): zL      Skipped user registration (no phone given). Re-run with --phone later.)phone_number
first_name	last_nameemailz      invalid phone number: z       user registration failed: u     ✓ phone registeredu     ✓ phone already registeredphoneNumberz*      (could not fetch the assigned line: )u   ┌─ Your agent's iMessage number ───────────────────────────────u
   │  📱 u<   │  Text this number from your phone to talk to your agent.rG   uC         No iMessage line assigned yet — check the Photon dashboard.)ra   assigned_phone_numberuser_idr`   z.      (could not save Photon status metadata: z;[5/5] Skipping sidecar npm install (--skip-sidecar-install)z3[5/5] Installing Node sidecar deps (spectrum-ts)...)write_platform_config_fieldphotonenabled)rawu,     ✓ photon platform enabled in config.yamlz*      (could not enable Photon in config: u   ✓ Photon setup complete.z*  Start the gateway:  hermes gateway start)(rP   load_photon_tokenrA   check_photon_token_validclear_photon_tokenrX   rB   rC   project_nameDEFAULT_PROJECT_NAMEload_dashboard_project_idfind_project_by_namegetcreate_projectrS   load_project_credentials
list_usersregenerate_project_secretstore_project_credentialsphone_promptr   r   CYANrb   rd   register_user_if_absentrc   
ValueErroruser_assigned_line_autoconfigure_accessget_imessage_lineGREENstrBOLDstore_user_numbersskip_sidecar_install_install_sidecarhermes_cli.configri   )r5   rU   rcr\   dashboard_idexistingcreatedrV   spectrum_idexisting_idexisting_secretsecretreusedrz   agent_numberregistered_phoneregistered_user_idrb   rd   userlineri   s                         r   r>   r>      sd   )++E  	7888/66 	())))VWWW*,,,E 
5MNNNt$$77I-// 	<3:NNNN1	 	3444 @ @D8::L 	/;<<<<"7tDDH /HLL.. /'~>t>>>????BBBBCCC%4UFFF&{{400-...   *q**<<<<qqqqq  5CJGGGGq":;;;"'2'K'M'M$_ 	? 	&{ODDD(    	P :5,OOF- +!!-		
 	
 	
 	
  	ckcccddddYkYYYZZZ/  
    2q22DDDDqqqqq
 J 'KK	
 	
 E L  %\]]]] _

	'?V"%.  MD''  	 	 	4443:FFFF11111 	 	 	8Q88szJJJJ11111	 	'W&&7WXXX !XXd^^
 #5d;; 	e$$$  V	V0EED 7#xx66 	V 	V 	VCqCCC#*UUUUUUUUU	V 
Ue  X  Z`  Zf  g  g  	h  	h  	h,--C%%v|V[AAB	
 	
 	
 	eRTZT`aabbbe  T  V\  Vb  c  c  	d  	d  	d  	dSTTT 	Z	Z*-&23EO.///4%1	      	Z 	Z 	ZG1GGGcjYYYYYYYYY	Z   KLLLLCDDD77IRAAAAAA##Hi4HHHH<==== R R R?1???cjQQQQQQQQQR 
GGG	
&'''	
67771s   >B'F& &
G0GG</K  ,I K  IK  IA*K   
K3
K..K3"M. .
O8NO)OO%,Q 
RR  R:)V$ $
W.WW$X< <
Y/Y**Y/rz   r   c                @   	 ddl m}m} n# t          $ r Y dS w xY wdD ]\  }}	  ||          rt	          d| d           % |||            t	          d| d| d	           H# t
          $ r+}t	          d
| d| t          j                   Y d}~xd}~ww xY wdS )a  Allowlist the operator and set their DM as the cron home channel.

    Writes ``PHOTON_ALLOWED_USERS`` (so the gateway authorizes the operator's
    own inbound messages instead of denying them) and ``PHOTON_HOME_CHANNEL``
    (the default space for cron delivery) to the operator's E.164 number. Each
    is only filled when unset, so a hand-tuned allowlist / home channel is
    never clobbered on a re-run.
    r   )get_env_valuesave_env_valueN))PHOTON_ALLOWED_USERSzallowlisted your number)PHOTON_HOME_CHANNELz$set your DM as the cron home channelz      u"    already set — leaving it as-is.u     ✓ z (rf   z      could not set z: r9   )r   r   r   ImportErrorrA   rS   rB   rC   )rz   r   r   keylabelrV   s         r   r   r   c  s+   CCCCCCCCC    F F
U	F}S!! FsFFFGGGN3&&&*5**C***++++ 	F 	F 	F33333#*EEEEEEEEE	FF Fs)    
A&"A&&
B0!BB_argsc                Z   t                       t          j        t                     t	          j        d          pt          j        d          }t                      }t          d|pd            t          d|rdnd            t          dt                      rd	nd
 d           dS )NPHOTON_NODE_BINnodez  node binary         : u   ✗ missing (install Node 18+)z  sidecar deps        : u   ✓ installedu'   ✗ run `hermes photon install-sidecar`z  telemetry           : r'   r(   z# (`hermes photon telemetry on|off`)r   )
_refresh_status_numbersrP   print_credential_summaryrA   osgetenvshutilwhichr
   _telemetry_enabled)r   node_binsidecar_installeds      r   r=   r=   ~  s     (///y*++Cv|F/C/CH.00	
SX%Q1Q
S
STTT	
z8I%x__Ox
z
z{{{	
q-?-A-A%LTTu
q
q
qrrr1r   c                    t          j                    \  } }| r|rd S t          j                    \  }}|r|sd S 	 t          j        ||           d S # t          $ r*}t          d| dt          j                   Y d }~d S d }~ww xY w)Nz.      (could not refresh Photon user numbers: rf   r9   )rP   load_user_numbersrv   refresh_user_numbersrS   rA   rB   rC   )rz   assignedr   r_   rV   s        r   r   r     s    !355OE8  "-"F"H"HK n V(nEEEEE V V VCqCCC#*UUUUUUUUUUVs   A 
BB  Bc                    t                      S )N)r   )r   s    r   r?   r?     s    r   boolc                     	 ddl m}   | d          }n$# t          $ r t          j        d          }Y nw xY w|pd                                                                dv S )zRead PHOTON_TELEMETRY from the env / ~/.hermes/.env.

    Mirrors the sidecar's truthy set (index.mjs) so the state shown here
    always matches what the sidecar will actually do.
    r   )r   PHOTON_TELEMETRYr]   )1trueyesr'   )r   r   r   r   r   striplower)r   rl   s     r   r   r     s    ,333333m.// , , ,i*++,I2$$&&*DDDs    55c                z   t          | dd           }|3t          dt                      rdnd            t          d           dS 	 ddlm}  |d|dk    rd	nd
           n6# t
          $ r)}t          d| t          j                   Y d }~dS d }~ww xY wt          d| d           t          d           dS )Nr%   zPhoton telemetry: r'   r(   zK  Toggle with `hermes photon telemetry on` / `hermes photon telemetry off`.r   )r   r   r   falsez!could not save PHOTON_TELEMETRY: r9   r   u   ✓ Spectrum telemetry turned z% (PHOTON_TELEMETRY in ~/.hermes/.env)zL  Restart the gateway for the sidecar to pick it up:  hermes gateway restart)r<   rA   r   r   r   rS   rB   rC   )r5   r%   r   rV   s       r   r@   r@     s   D'4((E}L+=+?+?#J44ULLMMM[\\\q444444)Ud]]66PPPP   5!55CJGGGGqqqqq 

W5
W
W
WXXX	
XYYY1s   A# #
B-BBc                 &   t          j        d          pd} t          j        |           st          dt          j                   dS t          dt                       d|  d           t          j        | dgt          t                                d	t          j	        d
          }|j        r!t          |j        dt          j                   |j
        dk    ryt          d|  d           t          j        | dgt          t                                d	t          j	        d
          }|j        r!t          |j        dt          j                   |j
        dk    r{t          dt          j                   |j        pd                                d t                   }|r5	 t                                          |d           nC# t          $ r Y n7w xY wn2	 t                                                       n# t          $ r Y nw xY w|j
        S )NnpmzInpm is not on PATH. Install Node.js 18+ (https://nodejs.org/) and re-run.r9   r   z  $ cd z && z ciciFT)cwdcheckrC   textr]   )endr:   r   u&     npm ci failed — falling back to:  z installinstallznpm install failedzutf-8)encoding)r   r   rA   rB   rC   r   
subprocessrunr   PIPE
returncoder   r	   r   
write_textOSErrorunlink)r   procerrors      r   r   r     s?   
,u


&C< 	
 	
 	
 	

 q 

0LNN
0
0
0
0
0111 >	d  D { 4dkr
3333!DsDDDEEE~)LNN##?
 
 
 ; 	8$+2CJ7777!"4444 "))++,E-E,EF 	  ++EG+DDDD   		##%%%% 	 	 	D	?s$   %#G	 	
GG G< <
H	H	c            
     \    t          j        dddddddd          } t          |            dS )zCRun Photon first-time setup from the `hermes gateway setup` wizard.r   NF)r   rp   rz   rb   rc   rd   rR   r   )argparse	Namespacer>   )r5   s    r   gateway_setupr     sG    "	 	 	D tr   F)r   promptr   c               "   t           j                                        sdS 	 |r&t          j        |                                           S t          |                                           S # t          t          f$ r t                       Y dS w xY w)Nr]   )	rB   stdinisattygetpassr   inputKeyboardInterruptEOFErrorrA   )r   r   s     r   r{   r{     s    9 r 	3?6**00222V}}""$$$x(   rrs   'A+ 
 A+ +BB)r   r   )r   r   r   r   )r5   r6   r   r7   )rz   r   r   r   )r   r6   r   r7   )r   r   )r   r   )r   r7   )r   r   r   r   r   r   )(__doc__
__future__r   r   r   r   r   r   rB   pathlibr   hermes_cli.colorsr   r   r]   r   rP   adapterr	   r
   sidecar_pathsr   r   __annotations__r   r   r   r4   r0   rX   r>   r   r=   r   r?   r   r@   r   r   r{   r   r   r   <module>r      sF    $ # " " " " "   				      



       + + + + + + + + ! ! ! ! ! ! E E E E E E E E . . . . . . !         # " " " "   4 4 4 4 '  '  '  'L   (   @D D D DNF F F F6   
V 
V 
V 
V   E E E E   "8 8 8 8J   $ ,1 	 	 	 	 	 	 	 	r   