
    kKjjr                     h   U d 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ZddlZddlZddlmZ ddlmZ ddlmZmZ dd	lmZ dd
lmZ ddlmZ  ed      Z e       Zh dZdee e	f   de!fdZ"dee e	f   de#e!e dz  f   fdZ$dee e	f   de#e e!f   fdZ%dee e	f   de fdZ&de ee e	f   z  ez  de#e e'e    f   fdZ(de de fdZ)dejT                  jV                  de fdZ,de de de de'e    de-ejT                  jV                     de fdZ.d d!d"d#d$d%d&d'Z/ee e f   e0d(<   d)e de fd*Z1d+ee e	f   de fd,Z2dejT                  jV                  d-e de fd.Z3de d-e de-ejT                  jV                     de fd/Z4	 dFd0ddd0d1dee  ejj                  d23      f   d4ee  ejj                  d53      f   d6ee! ejj                  d7d8gd9:      f   d;ee6dz   ejj                  d<d=3      f   d>ee dz   ejj                  d?d@3      f   dAee! ejj                  dBdC3      f   ddfdDZ7de de fdEZ8y)GzDGenerate a standalone CLI script and agent skill from an MCP server.    N)Path)	AnnotatedAny)urlparse)McpError)Console)_build_clientresolve_server_spec)ClientTransport)StdioTransport)
get_loggerzcli.generate>   nullnumberstringbooleanintegerschemareturnc                 x    | j                  d      }t        |t              rt        d |D              S |t        v S )z9Check if a schema represents a simple (non-complex) type.typec              3   ,   K   | ]  }|t         v   y wN)_SIMPLE_TYPES).0ts     e/Users/ahmed/devFolder/Ultron/claude-voice/.venv/lib/python3.12/site-packages/fastmcp/cli/generate.py	<genexpr>z"_is_simple_type.<locals>.<genexpr>%   s     ;{!1%{s   )get
isinstancelistallr   )r   schema_types     r   _is_simple_typer#       s6    **V$K+t$;{;;;-''    c                     | j                  d      dk7  ry| j                  di       }t        |      sy|j                  dd      }t        |t              rydddd	d
}|j                  |      }|yd|fS )z`Check if schema is an array of simple types.

    Returns (is_simple_array, item_type_str).
    r   array)FNitemsr   strintfloatbool)r   r   r   r   T)r   r#   r   r    )r   r'   	item_typetype_mappy_types        r   _is_simple_arrayr/   )   s    
 zz&W$JJw#E5! 		&(+I)T"	H ll9%G=r$   c                 D   t        |       \  }}|rd| ddfS t        |       rx| j                  dd      }t        |t              r:dddd	d
d}|D cg c]  }|j                  |d       }}dj                  |      dfS dddd	d
d}|j                  |d      dfS yc c}w )zkConvert a JSON Schema to a Python type annotation.

    Returns (type_annotation, needs_json_parsing).
    list[]Fr   r   r(   r)   r*   r+   None)r   r   r   r   r    | )r(   T)r/   r#   r   r   r    join)r   is_simple_arrr,   r"   r-   r   partss          r   _schema_to_python_typer8   E   s      07M9yk#U** vjj2k4(   !!H 6AA[X\\!U+[EA::e$e++ 
 ||K/66  Bs   Bc                     t        j                  | d      j                         }|j                  d      }dj	                  |      }d| S )z.Format a JSON schema for display in help text.   )indent
z
                          zJSON Schema: )pydantic_coreto_jsondecodesplitr5   )r   
schema_strlinesindenteds       r   _format_schema_for_helprD   k   sL     &&va8??AJT"E-2259H8*%%r$   resolvedc                    t        | t              rt        |       t               fS t        | t              rd| j
                  d| j                  g}| j                  r|j                  d| j                         | j                  r|j                  d| j                         ddj                  |       d}dh}||fS t        | t              rt        |       t               fS t        |       t               fS )	zSerialize a resolved transport to a Python expression string.

    Returns ``(expression, extra_imports)`` where *extra_imports* is a set of
    import lines needed by the expression.
    zcommand=zargs=zenv=zcwd=zStdioTransport(, )z4from fastmcp.client.transports import StdioTransport)r   r(   reprsetr   commandargsenvappendcwdr5   dict)rE   r7   exprimportss       r   serialize_transportrS   z   s     (C H~su$$(N+H,,/0E(--9J2KL<<LL4/01<<LL4/01 5!1 2!4IJW}(D!H~su$$ >35  r$   namec                     t        j                  dd|       }|r|d   j                         rd| }|xs d}t        j                  |      r| d}|S )z1Sanitize a string into a valid Python identifier.z[^a-zA-Z0-9_]_r   _unnamed)resubisdigitkeyword	iskeyword)rT   safes     r   _to_python_identifierr^      sX    66"C.DQ!4&z:DqzKr$   toolc                    | j                   }|j                  di       }t        |j                  dg             }g }g }g }i }|j                         D ]  \  }t	        |      \  }	}
|j                  dd      }|v }t              }||v rt        d d||    d| d      ||<   |
r)t        |      }|r| d	| n|}|j                  |f       |j                  d
d      j                  dd      j                  dd	      }|r"d|	 d| d}|j                  d| d| d       n|j                  d      }|u|
rNt        j                  |t              j                         }d|	 d| d}|j                  d| d| d|d       nyd|	 d| d}|j                  d| d| d|d       nT|	j                  d      r"d|	 d| d}|j                  d| d| d       n!d|	 d| d}|j                  d| d| d       |j                  d|         t        | j                        }| j                   xs dj                  d
d      j                  dd      }g }|j                  d       |j                  d| j                  d       |j                  d| d        |r"|j                  d!       |j#                  |       |j                  d"       |j                  d#| d$       |rI|j                  d%       |D ]"  \  }}|j                  d| d&| d'| d(|        $ |j                  d       g }|D ]O  t              }t%        fd)|D              r|j                  d| d*       :|j                  d|        Q d+j'                  |      }|j                  d,| j                  d-| d.       |j                  d       dj'                  |      S )/zEGenerate the source for a single ``@call_tool_app.command`` function.
propertiesrequireddescription zParameter name collision: 'z' and 'z' both sanitize to ''z\n\\\"\"r<   z
Annotated[z, cyclopts.Parameter(help="z")]z    z: ,default)fallbackz = r1   z = [],z" | None, cyclopts.Parameter(help="z = None,z\'z@call_tool_app.command(name=rH   z
async def (z    *,z
) -> None:z    '''z'''z    # Parse JSON parametersz_parsed = json.loads(z) if isinstance(z, str) else c              3   .   K   | ]  \  }}|k(    y wr    )r   pnrV   	prop_names      r   r   z(_tool_function_source.<locals>.<genexpr>
  s     8K52qrYKs   _parsedrG   z    await _call_tool(z, {z}))inputSchemar   rJ   r'   r8   r^   
ValueErrorrD   rN   replacer=   r>   r(   r?   
startswithrT   rc   extendanyr5   )r_   r   ra   rb   param_lines	call_argsjson_params
seen_namesprop_schemar.   
needs_json	help_textis_required	safe_nameschema_helphelp_escaped
annotationrk   default_strfn_namerc   rB   
_prop_namecall_arg_parts
dict_itemsrq   s                            @r   _tool_function_sourcer      s   F!'L"!=J6::j"-.H  KI)+K!#J","2"2"4	;4[AOOM26	8+))4	 
"-i[
9@U?V W%%.Kq2  !*
9 1+>K:C9+S6I	956 dF+33C?GGeT 	
 WI%@cR  i[:,a@A!ooi0G""/"7"7#"N"U"U"WK#-gY6QR^Q__b!cJ&&ykJ<s;/K $.gY6QR^Q__b!cJ&&i[:,c'TU'VW %%g.#-gY6QR^Q__b!cJ&&i[:,f'MN#-gY6XYeXffi!jJ&&i[:,h'OPI=9+67k #5p $DII.G ##)r224@HHeTKE	LL 
LL/		}A>?	LL:gYa()X[!	LL	LL7;-s+, 23%0!J	LLyk!6ykAQR[Q\\hirhst &1 	R N	))4	8K88!!YMI;g"FG!!YMI;"?@   >*J	LL(T*SIJ	LL99Ur$   server_nameserver_spectransport_codeextra_importstoolsc                    | j                  dd      j                         j                  dd      j                  dd      }g }|j                  d       |j                  d|  d	       |j                  d
       |j                  d|        |j                  d       |j                  d
       |j                  d       |j                  d       |j                  d       |j                  d
       |j                  d       |j                  d       |j                  d       |j                  d
       |j                  d       |j                  t	        |             |j                  d
       |j                  d       |j                  d|        |j                  d
       | j                  dd      j                  dd      }|j                  d| d| d       |j                  d       |j                  d       |j                  d
       |j                  d       |j                  d
       |j                  d
       |j                  t        j                  d             |j                  d
       |j                  d
       |j                  t        j                  d             |j                  d
       |j                  d
       |rK|j                  d       |j                  d       |j                  d       |j                  d  |D               |j                  d
       |j                  d!       |j                  d"       |j                  d
       d#j                  |      S )$z)Generate the full CLI script source code. -rf   rg   rh   ri   z#!/usr/bin/env python3z"""CLI for z MCP server.rd   z#Generated by: fastmcp generate-cli z"""zimport jsonz
import syszfrom typing import Annotatedzimport cycloptszimport mcp.typesz from rich.console import Consolezfrom fastmcp import Clientz?# Modify this to change how the CLI connects to the MCP server.zCLIENT_SPEC = zapp = cyclopts.App(name="z", help="CLI for z MCP server")zPcall_tool_app = cyclopts.App(name="call-tool", help="Call a tool on the server")zapp.command(call_tool_app)zconsole = Console()ao          # ---------------------------------------------------------------------------
        # Helpers
        # ---------------------------------------------------------------------------


        def _print_tool_result(result):
            if result.is_error:
                for block in result.content:
                    if isinstance(block, mcp.types.TextContent):
                        console.print(f"[bold red]Error:[/bold red] {block.text}")
                    else:
                        console.print(f"[bold red]Error:[/bold red] {block}")
                sys.exit(1)

            if result.structured_content is not None:
                console.print_json(json.dumps(result.structured_content))
                return

            for block in result.content:
                if isinstance(block, mcp.types.TextContent):
                    console.print(block.text)
                elif isinstance(block, mcp.types.ImageContent):
                    size = len(block.data) * 3 // 4
                    console.print(f"[dim][Image: {block.mimeType}, ~{size} bytes][/dim]")
                elif isinstance(block, mcp.types.AudioContent):
                    size = len(block.data) * 3 // 4
                    console.print(f"[dim][Audio: {block.mimeType}, ~{size} bytes][/dim]")


        async def _call_tool(tool_name: str, arguments: dict) -> None:
            # Filter out None values and empty lists (defaults for optional array params)
            filtered = {
                k: v
                for k, v in arguments.items()
                if v is not None and (not isinstance(v, list) or len(v) > 0)
            }
            async with Client(CLIENT_SPEC) as client:
                result = await client.call_tool(tool_name, filtered, raise_on_error=False)
                _print_tool_result(result)
                if result.is_error:
                    sys.exit(1)u          # ---------------------------------------------------------------------------
        # List / read commands
        # ---------------------------------------------------------------------------


        @app.command
        async def list_tools() -> None:
            """List available tools."""
            async with Client(CLIENT_SPEC) as client:
                tools = await client.list_tools()
                if not tools:
                    console.print("[dim]No tools found.[/dim]")
                    return
                for tool in tools:
                    sig_parts = []
                    props = tool.inputSchema.get("properties", {})
                    required = set(tool.inputSchema.get("required", []))
                    for pname, pschema in props.items():
                        ptype = pschema.get("type", "string")
                        if pname in required:
                            sig_parts.append(f"{pname}: {ptype}")
                        else:
                            sig_parts.append(f"{pname}: {ptype} = ...")
                    sig = f"{tool.name}({', '.join(sig_parts)})"
                    console.print(f"  [cyan]{sig}[/cyan]")
                    if tool.description:
                        console.print(f"    {tool.description}")
                    console.print()


        @app.command
        async def list_resources() -> None:
            """List available resources."""
            async with Client(CLIENT_SPEC) as client:
                resources = await client.list_resources()
                if not resources:
                    console.print("[dim]No resources found.[/dim]")
                    return
                for r in resources:
                    console.print(f"  [cyan]{r.uri}[/cyan]")
                    desc_parts = [r.name or "", r.description or ""]
                    desc = " — ".join(p for p in desc_parts if p)
                    if desc:
                        console.print(f"    {desc}")
                console.print()


        @app.command
        async def read_resource(uri: Annotated[str, cyclopts.Parameter(help="Resource URI")]) -> None:
            """Read a resource by URI."""
            async with Client(CLIENT_SPEC) as client:
                contents = await client.read_resource(uri)
                for block in contents:
                    if isinstance(block, mcp.types.TextResourceContents):
                        console.print(block.text)
                    elif isinstance(block, mcp.types.BlobResourceContents):
                        size = len(block.blob) * 3 // 4
                        console.print(f"[dim][Blob: {block.mimeType}, ~{size} bytes][/dim]")


        @app.command
        async def list_prompts() -> None:
            """List available prompts."""
            async with Client(CLIENT_SPEC) as client:
                prompts = await client.list_prompts()
                if not prompts:
                    console.print("[dim]No prompts found.[/dim]")
                    return
                for p in prompts:
                    args_str = ""
                    if p.arguments:
                        parts = [a.name for a in p.arguments]
                        args_str = f"({', '.join(parts)})"
                    console.print(f"  [cyan]{p.name}{args_str}[/cyan]")
                    if p.description:
                        console.print(f"    {p.description}")
                console.print()


        @app.command
        async def get_prompt(
            name: Annotated[str, cyclopts.Parameter(help="Prompt name")],
            *arguments: str,
        ) -> None:
            """Get a prompt by name. Pass arguments as key=value pairs."""
            parsed: dict[str, str] = {}
            for arg in arguments:
                if "=" not in arg:
                    console.print(f"[bold red]Error:[/bold red] Invalid argument {arg!r} — expected key=value")
                    sys.exit(1)
                key, value = arg.split("=", 1)
                parsed[key] = value

            async with Client(CLIENT_SPEC) as client:
                result = await client.get_prompt(name, parsed or None)
                for msg in result.messages:
                    console.print(f"[bold]{msg.role}:[/bold]")
                    if isinstance(msg.content, mcp.types.TextContent):
                        console.print(f"  {msg.content.text}")
                    elif isinstance(msg.content, mcp.types.ImageContent):
                        size = len(msg.content.data) * 3 // 4
                        console.print(f"  [dim][Image: {msg.content.mimeType}, ~{size} bytes][/dim]")
                    else:
                        console.print(f"  {msg.content}")
                    console.print()zM# ---------------------------------------------------------------------------z.# Tool commands (generated from server schema)c              3   2   K   | ]  }t        |        y wr   )r   )r   r_   s     r   r   z&generate_cli_script.<locals>.<genexpr>  s     CUT*40Us   zif __name__ == "__main__":z	    app()r<   )ru   lowerrN   rw   sortedtextwrapdedentr5   )r   r   r   r   r   app_namerB   server_name_escapeds           r   generate_cli_scriptr     s    	C%++-55dFCKKCQVW 
 E	LL)*	LL;{m<89	LL	LL6{mDE	LL	LL 
LL	LL	LL/0	LL	LL"#	LL#$	LL34	LL	LL-.	LL&'	LL 
LLRS	LL>.!123	LL &--dF;CCCO	LL
#H:->?R>SS`a 
LLZ 
LL-.	LL	LL&'	LL	LL 
LL )# )	$+X 
LL	LL 
LL i' i	(kX 
LL	LL [	
 	EF[	
 	CUCC 
LL	LL-.	LL	LL99Ur$   r   r   r   r   r   r&   object)r   r   r   r   r   r&   r   _JSON_SCHEMA_TYPE_LABELSrq   c                     t        |       }t        j                  dd|      }t        j                  dd|      }|j                         j	                  dd      j                  d      }|rd| S dS )u   Convert a JSON Schema property name to its CLI flag form.

    Replicates cyclopts' default_name_transform: camelCase → snake_case,
    lowercase, underscores → hyphens, strip leading/trailing hyphens.
    z(.)([A-Z][a-z]+)z\1_\2z([a-z0-9])([A-Z])rV   r   z--z--arg)r^   rX   rY   r   ru   strip)rq   r]   s     r   _param_to_cli_flagr     sj     !+D66%x6D66&$7D::<S)//4DRv;+G+r$   r}   c                 v   | j                  dd      }t        |t              r4|D cg c]  }t        j                  ||       }}dj	                  |      S t        j                  ||      }|dk(  rB| j                  di       }|j                  dd      }t        |t
              r|t        v rd| dS |S c c}w )	z9Return a human-readable type label for a property schema.r   r   r4   r&   r'   rd   zarray[r2   )r   r   r    r   r5   r(   )r}   r"   r   labelslabelr'   r,   s          r   _schema_type_labelr   $  s    //&(3K+t$>IJk*..q!4kJzz&!!$((kBE g,IIfb)	i%)7O*OI;a((L Ks   B6cli_filenamec                 z   | j                   }|j                  di       }t        |j                  dg             }g }|j                         D ]f  \  }}t	        |      }|j                  d      }	|	dk(  xs t        |	t              xr d|	v }
|
r|j                  |       S|j                  | d       h dj                  |      }d| d| j                   }|r|d| z  }g }|j                         D ]  \  }}d	t	        |       d	}t        |      j                  d
d      }||v rdnd}|j                  dd      }t        |      \  }}|r	|r| dnd}|j                  dd      j                  d
d      }|j                  d| d| d| d| d	        d}|rd}d| ddj                  |      z   dz   }d| j                   g}| j                  r|j                  d| j                  g       |j                  dd|dg       |r"|j                  d|j                  d      g       dj                  |      S )z.Generate a SKILL.md section for a single tool.ra   rb   r   r   z <value>r   uv run --with fastmcp python z call-tool `|z\|yesnorc   rd   z (JSON string)zJSON stringr<   z| r4   z |zQ| Flag | Type | Required | Description |
|------|------|----------|-------------|z### ```bash```)rs   r   rJ   r'   r   r   r    rN   r5   rT   r   ru   r8   rc   rw   r   )r_   r   r   ra   rb   flag_parts_listpp_schemaflagr"   is_bool
flag_parts
invocationrowsrq   r}   
type_labelr   rc   rV   r~   param_tableheaderrB   s                           r   _tool_skill_sectionr   7  si   F!'L"!=J6::j"-.H "$O!'')8!!$ll6** 
{D)Fi;.F 	 ""4(""dV8#45 * /*J0k$))UJ*&&
 D","2"2"4	;%i013'4<<S%H
(H4e$!oomR8.{;:2=;-~.=  "))$4<<S%Hbc*SSRPQ #5 Ke6("o		$7$>tyyk*+Eb$**+,	LL"iU34b+++D12399Ur$   c                    | j                  dd      j                         j                  dd      j                  dd      }| j                  dd      j                  dd      }d| d}dd	| d
d| dddd|  ddg}|r/dj                  fd|D              }|j                  dd|dg       |j                  dddd dd dd dd dd dddg
       dj                  |      S )z4Generate a SKILL.md file for a generated CLI script.r   r   rf   rd   rh   zCLI for the z9 MCP server. Call tools, list resources, and get prompts.z---zname: "z-cli"zdescription: "z# z CLIz

c              3   6   K   | ]  }t        |        y wr   )r   )r   r_   r   s     r   r   z)generate_skill_content.<locals>.<genexpr>  s      "
@El3s   z## Tool Commandsz## Utility Commandsr   r   z list-toolsz list-resourcesz read-resource <uri>z list-promptsz" get-prompt <name> [key=value ...]r   r<   )ru   r   r5   rw   )r   r   r   
skill_namer   rc   rB   tool_bodiess    `      r   generate_skill_contentr   k  sM    	C%++-55dB?GGRP  ##D"-55c2>I +deK 	
*U#
Q'

[M
E kk "
@E"
 
 	("k2>?	LL!+L>E+L>I+L>9MN+L>G+L>9[\	
 99Ur$   F)forcetimeoutauthno_skillzEServer URL, Python file, MCPConfig JSON, discovered name, or .js file)helpoutputz"Output file path (default: cli.py)r   z-fz--forcez"Overwrite output file if it exists)rT   r   r   z	--timeoutzConnection timeout in secondsr   z--authzAAuth method: 'oauth', a bearer token string, or 'none' to disabler   z
--no-skillz8Skip generating a SKILL.md agent skill alongside the CLIc                  K   t        |      }|j                  dz  }g }|j                         r|s|j                  |       |s#|j                         r|s|j                  |       |rFdj	                  d |D              }	t
        j                  d|	 d       t        j                  d       t        |       }
t        |
      \  }}t        |       }t        |
||      }	 |4 d{    |j                          d{   }t
        j                  d	t        |       d
|  d       ddd      d{    t'        || ||      }|j)                  |       |j+                  |j-                         j.                  dz         t
        j                  d| dt        |       d       |sBt1        ||j2                  |      }|j)                  |       t
        j                  d| d       t
        j                  d| d       y7 "7 7 # 1 d{  7  sw Y   xY w# t        t         t"        t$        f$ r8}t
        j                  d|        t        j                  d       Y d}~9d}~ww xY ww)a  Generate a standalone CLI script from an MCP server.

    Connects to the server, reads its tools/resources/prompts, and writes
    a Python script that can invoke them directly. Also generates a SKILL.md
    agent skill file unless --no-skill is passed.

    Examples:
        fastmcp generate-cli weather
        fastmcp generate-cli weather my_cli.py
        fastmcp generate-cli http://localhost:8000/mcp
        fastmcp generate-cli server.py output.py -f
        fastmcp generate-cli weather --no-skill
    zSKILL.mdrG   c              3   (   K   | ]
  }d | d  yw)z[cyan][/cyan]Nro   )r   r   s     r   r   z'generate_cli_command.<locals>.<genexpr>  s     @x!F1#W-xs   z[bold red]Error:[/bold red] z4 already exist(s). Use [cyan]-f[/cyan] to overwrite.   )r   r   Nz[dim]Discovered z tool(s) from z[/dim]z/[bold red]Error:[/bold red] Could not connect: )r   r   r   r   r   I   u   [green]✓[/green] Wrote [cyan]z[/cyan] with z tool command(s))r   r   r   r   z[dim]Run: python z --help[/dim])r   parentexistsrN   r5   consoleprintsysexitr
   rS   _derive_server_namer	   
list_toolslenRuntimeErrorTimeoutErrorr   OSErrorr   
write_textchmodstatst_moder   rT   )r   r   r   r   r   r   output_path
skill_pathexistingnamesrE   r   r   r   clientr   excscriptskill_contents                      r   generate_cli_commandr     s=    j v,K##j0J HE$
))+E
#		@x@@*5' 20 1	
 	 #;/H$7$A!NM &k2K 8W4@F	6 ++--EMM"3u:,n[MP 6 !%#F 6"k&&(00589MM
)+ 7E
|+	-
 .#$))

 	m,7
|7KLMM%k]-@AI - 666 ,': GuMNs   CI;"H' (H
)H' ,H H)H*H' 5H6H' :CI;
H' HH' H$HH$ H' 'I8 -I3-I;3I88I;c                    | j                  d      rt        |       }|j                  xs dS | j                  d      rt	        |       j
                  S d| v r.| j                  dd      d   }|xs | j                  dd      d   S | S )z0Derive a human-friendly name from a server spec.)zhttp://zhttps://server)z.pyz.jsz.json:r   r   )rv   r   hostnameendswithr   stemr@   )r   parsedrT   s      r   r   r     s     56+&*(* 34K %%% k  a(+3{((a033r$   )zcli.py)9__doc__r[   rX   r   r   pathlibr   typingr   r   urllib.parser   cyclopts	mcp.typesmcpr=   r   rich.consoler   fastmcp.cli.clientr	   r
   fastmcp.client.transports.baser   fastmcp.client.transports.stdior   fastmcp.utilities.loggingr   loggerr   r   rP   r(   r+   r#   tupler/   r8   rD   rJ   rS   r^   typesToolr   r    r   r   __annotations__r   r   r   r   	Parameterr*   r   r   ro   r$   r   <module>r      s   J  	 
   ! !       A : : 0	N	#
) C(DcN (t (T#s(^ dC$J6F0G 8#4S> #eCI6F #L&DcN &s &!DcN"_4!
3C=!B  m		 m3 mjiii i s8	i
 		i 	ib , $sCx. ,# ,# ,DcN s &1ciinn 1C 1C 1h+++ 		+ 		+~ 	uB( 	 	 	 	MuBX	
	uB 5	
	uB 	"5	
	uB* ;-LM	O+uB2 d
T	
	3uB@ K	
	AuBN 
OuBpS S r$   