Xj8*ddZddlZddlZddlZddlZddlmZddlmZm Z m Z ddl Z ddl m Z ddl mZddlmZmZddlmZej(d Zej,d k(rddlZddlZddlZddlZndZdZdZdZeZd ed efd ZGddZdej@dfd ede!ede"eefdzde dzdeezdzd eezf dZ#dej@dfd ede!ede"eefdzde dzdeezdzd ef dZ$d edzfdZ%deezdedzd dfdZ&ddeezde'd dfdZ(eddeezfdZ)y)z= Windows-specific functionality for stdio client operations. N)Path)BinaryIOTextIOcast) to_thread)Process)FileReadStreamFileWriteStream) deprecatedzclient.stdio.win32win32commandreturnc tj|x}r|SdD]#}||}tj|x}s!|cS|S#t$r|cYSwxYw)aB Get the correct executable command normalized for Windows. On Windows, commands might exist with specific extensions (.exe, .cmd, etc.) that need to be located for proper execution. Args: command: Base command (e.g., 'uvx', 'npx') Returns: str: Windows-appropriate command path )z.cmdz.batz.exez.ps1)shutilwhichOSError)r command_pathext ext_versionext_paths j/mnt/ssd/data/Dropbox/adrian/vault-secondbrain/venv/lib/python3.12/site-packages/mcp/os/win32/utilities.pyget_windows_executable_commandr$sv!<<0 0< 0 4 C$IcU+K!<< 44x4  s!A"AAA AAceZdZdZdej efdZdZde dzde dzde dzd dfd Z d Z d Z dd Zed efdZy)FallbackProcessa7 A fallback process wrapper for Windows to handle async I/O when using subprocess.Popen, which provides sync-only FileIO objects. This wraps stdin and stdout into async-compatible streams (FileReadStream, FileWriteStream), so that MCP clients expecting async streams can work properly. popen_objc\||_|j|_|j|_|j |_|jr#t tt|jnd|_|jr)ttt|j|_yd|_y)N) popenstdin stdin_rawstdout stdout_rawstderrr rrr )selfrs r__init__zFallbackProcess.__init__Nsr.7 "#**&& HL_T(DNN%CD\` IMnT(DOO%DE ^b cK|Sw)z$Support async context manager entry.r#s r __aenter__zFallbackProcess.__aenter__Ws  sexc_typeNexc_valexc_tbrcLK|jjtj|jjd{|j r"|j j d{|jr"|jj d{|jr|jj|jr|jj|jr|jjyy777|w)z3Terminate and wait on process exit inside a thread.N) r terminaterrun_syncwaitracloser rcloser!r")r#r*r+r,s r __aexit__zFallbackProcess.__aexit__[s   111 ::**##% % % ;;++$$& & & >> NN " ?? OO ! ! # ;; KK     2 & &s7AD$ D -D$7D 8-D$%D"&A9D$ D$"D$cpKtj|jjd{S7w)z"Async wait for process completion.N)rr/rr0r(s rr0zFallbackProcess.waitqs%'' 8888s -646c6|jjS)z%Terminate the subprocess immediately.)rr.r(s rr.zFallbackProcess.terminateuszz##%%r%c$|jy)z6Kill the subprocess immediately (alias for terminate).N)r.r(s rkillzFallbackProcess.killys  r%c.|jjS)zReturn the process ID.)rpidr(s rr9zFallbackProcess.pid}szz~~r%)rN)__name__ __module__ __qualname____doc__ subprocessPopenbytesr$r) BaseExceptionobjectr3r0r.r7propertyintr9r'r%rrrDsc*"2"25"9c $& %     ,9&Sr%rargsenverrlogcwdczKt}d} tj|g||ttdrtj nd||d{}t|||S7#t $rt|||||d{7}Y3t$r(tj|g||||d{7}YbwxYww)a Creates a subprocess in a Windows-compatible way with Job Object support. Attempt to use anyio's open_process for async subprocess creation. In some cases this will throw NotImplementedError on Windows, e.g. when using the SelectorEventLoop which does not support async subprocesses. In that case, we fall back to using subprocess.Popen. The process is automatically added to a Job Object to ensure all child processes are terminated when the parent is terminated. Args: command (str): The executable to run args (list[str]): List of command line arguments env (dict[str, str] | None): Environment variables errlog (TextIO | None): Where to send stderr output (defaults to sys.stderr) cwd (Path | str | None): Working directory for the subprocess Returns: Process | FallbackProcess: Async-compatible subprocess with stdin and stdout streams NCREATE_NO_WINDOWr)rF creationflagsr"rH)rFr"rH) _create_job_objectanyio open_processhasattrr>rJNotImplementedError _create_windows_fallback_process Exception_maybe_assign_process_to_job)r rErFrGrHjobprocesss rcreate_windows_processrVs8  CG **  t z#56%55   ,!#. N/   Z8$VUXYYY  **  t      s_ B;AA%A#A%B;#A%%B8BB8B;'B8/B20B85B;7B88B;c`K tj|g|tjtj|||dttdd}t |S#t$rHtj|g|tjtj|||d}Yt |SwxYww)z Create a subprocess using subprocess.Popen as a fallback when anyio fails. This function wraps the sync subprocess.Popen in an async-compatible interface. rrJ)rr r"rFrHbufsizerK)rr r"rFrHrX)r>r?PIPEgetattrrRr)r rErFrGrHrs rrQrQs $$  t //??!*.@!D  * 9 %%   $$  t //??  9 %%  s*B.A A B.AB+ B.*B++B.ctjdk7stsy tjdd}tj|tj }|ddxxtj zcc<tj|tj ||S#t$r"}tjd|Yd}~yd}~wwxYw)zX Create a Windows Job Object configured to terminate all processes when closed. r NBasicLimitInformation LimitFlagsz9Failed to create Job Object for process tree management: ) sysplatformwin32jobCreateJobObjectQueryInformationJobObject!JobObjectExtendedLimitInformation"JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSESetInformationJobObjectrRloggerwarning)rT extended_infoes rrLrLs ||wh &&tR0 ::3@j@jk -.|<@k@kk<((h.X.XZgh RSTRUVWsA>B C$CCrUrTcB|sytjdk7str trtsy tj tj tjzd|j}|s td t j||||_ tj|y#tj|wxYw#t$rO}tjd|jd|trtj|Yd}~yYd}~yd}~wwxYw)zt Try to assign a process to a job object. If assignment fails for any reason, the job handle is closed. Nr FzFailed to open process handlezFailed to assign process z to Job Object: )r_r`win32apiwin32conra OpenProcessPROCESS_SET_QUOTAPROCESS_TERMINATEr9rRAssignProcessToJobObject _job_object CloseHandlergrh)rUrTprocess_handlerjs rrSrSs  ||whhh&!--  & &)C)C CUGKK ;< < 1  - -c> B"%G    0H  0 &27;;-?OPQsST    % % &s1A C9B,C,CC DADDtimeout_secondscKtjdk7ryt|dd}|r9tr3 tj|dt r t j| |jy#t $rY9wxYw#t $rY,wxYw#t r& t j|w#t $rYwwxYwwxYw#t $rYywxYww)aD Terminate a process and all its children on Windows. If the process has an associated job object, it will be terminated. Otherwise, falls back to basic process termination. Args: process: The process to terminate timeout_seconds: Timeout in seconds before force killing (default: 2.0) r Nrr) r_r`rZraTerminateJobObjectrRrlrsr.)rUrurTs rterminate_windows_process_treerys ||w '=$ /C x   ' 'Q / ((-     !((-     s*CA1C B C0C1 A=:B<A==B B  C B  CB=B-,B=- B96B=8B99B==C C  C C  Czterminate_windows_process is deprecated and will be removed in a future version. Process termination is now handled internally by the stdio_client context manager.cK |jtjd5|jd{dddy7 #1swYyxYw#t$r|j YywxYww)aB Terminate a Windows process. Note: On Windows, terminating a process with process.terminate() doesn't always guarantee immediate process termination. So we give it 2s to exit, or we call process.kill() which sends a SIGKILL equivalent signal. Args: process: The process to terminate @N)r.rM fail_afterr0 TimeoutErrorr7)rUs rterminate_windows_processr~<sh    c " !,,.  ! !  ! !  s[A8%AA A A A A8 A  AAA8AA52A84A55A8)r{)*r=loggingrr>r_pathlibrtypingrrrrMr anyio.abcranyio.streams.filer r typing_extensionsr getLoggerrgr` pywintypesrlrmrarD JobHandlestrrrr"listdictrVrQrLrSfloatryr~r'r%rrs  )) >(   / 0<<7HHHJ  CC@<<N"&JJ! 8 8 s)8 c3h$ 8 TM 8 d  8   8|"&JJ! #& #& s)#& c3h$ #& TM #& d  #&  #&LC$J&&'O*C&)VZJZ&_c&:  'O2K  ^c  nr  F YW-F r%