# Aviso de inicio de sesión

> Pide iniciar sesión y luego muestra el paso del navegador, un código y Cancelar. Componente de Pyzed para GUIs de escritorio en Python, con ejemplos y API.

Source: https://albakore.github.io/pyzed/es/library/auth-prompt/

:::tip[En pocas palabras]
Una caja que te pide iniciar sesión, con un botón para cada forma de hacerlo.
:::

`ui.AuthPrompt` es un componente que pide iniciar sesión, para un agente o un servicio que lo necesita. Muestra un título (`title`), un `detail` opcional y un botón por cada forma de entrar: `methods` son diccionarios con `id`, `name` y, opcionales, `description` (se ve como tooltip) e `icon`, y el primero es el botón principal. Elegir uno llega a `on_pick` con su id. Mientras `waiting` tiene ese id muestra un spinner y lo que está pasando (`waiting_text`, o "Esperando al navegador…"), el código que hay que escribir (`code`) con un botón para copiarlo si lo hay, Abrir la página otra vez si hay `url`, y Cancelar. `error` muestra un mensaje en rojo.

`ui.AuthPrompt` · Categoría: [Agentes de IA](https://albakore.github.io/pyzed/es/library/#agentes-de-ia) · [Referencia completa →](https://albakore.github.io/pyzed/es/reference/ui/#authprompt)

**Código:**

```python
pz.container(ui.AuthPrompt(
    title="Sign in to use the agent",
    detail="Your account is used to run the model.",
    methods=[{"id": "browser", "name": "Log in with the browser", "icon": "globe"},
             {"id": "key", "name": "Use an API key", "icon": "key-round"}],
    on_pick=on_pick,
), width=440)
```

:::note[Nuevo]
Este componente se añadió hace poco. Cuéntanos qué tal te funciona en el [gestor de incidencias](https://github.com/albakore/pyzed/issues).
:::

## Cuándo usarlo

- Donde un agente o un servicio conectado necesita que el usuario inicie sesión para funcionar.
- Para un inicio de sesión con código: muestra el `code` que el usuario escribe en la página que se abrió.

## Uso

```python
import pyzed as pz
from pyzed import ui

class Agent(pz.App):
    def __init__(self):
        self.waiting, self.code = "", ""

    def sign_in(self, method):
        self.waiting = method
        self.code = start_device_login()  # opens the browser and returns the code to type

    def view(self):
        return ui.AuthPrompt(title="Sign in to use the agent", waiting=self.waiting, code=self.code,
                             methods=[{"id": "browser", "name": "Log in with the browser"}],
                             on_pick=lambda e: self.sign_in(e.value),
                             on_cancel=lambda e: setattr(self, "waiting", ""),
                             on_copy=lambda e: pz.Command.copy(e.value))
```

## Variantes

:::note[Sobre estas capturas]
Cada captura la graba pyzed mismo, fuera de pantalla a 2x, en One Dark o One Light según el tema de este sitio, y recortada al componente para que se vea a su tamaño real. El puntero pasa por encima, pulsa o escribe en él; un componente que no reacciona al puntero recorre algunos temas. Con movimiento reducido ves el primer fotograma. Abre **Código** bajo una captura para ver el fragmento que la dibuja; los nombres libres como `on_save` son tus propios callbacks.
:::

### Formas de entrar

El primer método es el botón principal (relleno).

```python
pz.container(ui.AuthPrompt(title="Sign in to continue",
                           methods=[{"id": "browser", "name": "Log in with the browser"}]),
             width=380)
```

```python
pz.container(ui.AuthPrompt(title="Sign in to continue", methods=[
    {"id": "browser", "name": "Log in with the browser", "icon": "globe"},
    {"id": "key", "name": "Use an API key", "icon": "key-round"},
]), width=380)
```

```python
pz.container(ui.AuthPrompt(title="Sign in to continue", detail="The agent needs your account.",
                           methods=[{"id": "browser", "name": "Log in with the browser"}]),
             width=380)
```

```python
pz.container(ui.AuthPrompt(title="Sign in to continue", error="The sign-in was cancelled.",
                           methods=[{"id": "browser", "name": "Try again"}]),
             width=380)
```

### Esperando

```python
pz.container(ui.AuthPrompt(title="Sign in to continue", waiting="browser"), width=380)
```

```python
pz.container(ui.AuthPrompt(title="Sign in to continue", waiting="cli",
                           waiting_text="Finish signing in in the terminal."),
             width=380)
```

```python
pz.container(ui.AuthPrompt(title="Sign in to continue", waiting="device", code="WDJB-MJHT",
                           url="https://example.com/device"), width=380)
```

## Eventos

Aviso de inicio de sesión tiene **4 eventos propios**, en la tabla de abajo. Como todo widget, también tiene los **18 eventos comunes** (`click`, `double_click`, `right_click`, `mouse_enter`, `drag`, `key_down`, `resize`…), que se conectan con `.on(...)`: mira [Eventos](https://albakore.github.io/pyzed/es/guides/events/) y [Eventos de cada componente](https://albakore.github.io/pyzed/es/library/events/).

Es un `pz.Component`, así que también lanza `on_mount` y `on_unmount`, y sus handlers reciben un `pz.Event` cuyo `value` trae el dato.

| Evento | El handler recibe | Cuándo |
| --- | --- | --- |
| `on_pick` | `(event)` | Se eligió un método (`event.value` es su id). |
| `on_cancel` | `(event)` | Cancelar. |
| `on_open_url` | `(event)` | Abrir la página otra vez. |
| `on_copy` | `(event)` | Se copió el código. |

**El handler recibe** es lo que Pyzed le pasa a tu función: `()` es nada. Cualquier handler también puede ser un mensaje (un valor que no se puede llamar), que va a `update()`.

### Manejar los eventos

Los mismos eventos escritos de tres formas. **Imperativa**: métodos de la app que cambian `self`. **Declarativa**: los handlers producen mensajes y un único `update()` decide. **Funcional**: una función pura dibuja un estado inmutable y pide cambios con `set_state(...)`. Mira [Imperativo, declarativo y funcional](https://albakore.github.io/pyzed/es/guides/code-styles/).

**Imperativo:**

```python
class Agent(pz.App):
    def __init__(self):
        self.waiting, self.code = "", ""

    def sign_in(self, method):           # on_pick: event.value is the method's id
        self.waiting, self.code = method, "ABCD-1234"

    def view(self):
        return ui.AuthPrompt(title="Sign in to use the agent", waiting=self.waiting, code=self.code,
                             methods=[{"id": "browser", "name": "Log in with the browser"}],
                             on_pick=lambda e: self.sign_in(e.value),
                             on_cancel=lambda e: setattr(self, "waiting", ""),
                             on_copy=lambda e: pz.Command.copy(e.value))   # the code
```

**Declarativo:**

```python
from dataclasses import dataclass

@dataclass
class Picked:
    method: str

class Agent(pz.App):
    waiting = ""

    def update(self, message):
        match message:
            case Picked(method):
                self.waiting = method
            case "cancel":
                self.waiting = ""

    def view(self):
        return ui.AuthPrompt(title="Sign in", waiting=self.waiting,
                             methods=[{"id": "key", "name": "Use an API key"}],
                             on_pick=lambda e: Picked(e.value), on_cancel="cancel")
```

**Funcional:**

```python
from dataclasses import dataclass

@dataclass(frozen=True)
class State:
    waiting: str = ""

def view(state, set_state):
    return ui.AuthPrompt(title="Sign in", waiting=state.waiting,
                         methods=[{"id": "browser", "name": "Log in with the browser"}],
                         on_pick=lambda e: set_state(waiting=e.value),
                         on_cancel=lambda e: set_state(waiting=""))
```

## Consejos

:::tip
El botón de copiar solo avisa a `on_copy` con el código en `event.value`; devuelve `pz.Command.copy(e.value)` desde ahí para ponerlo en el portapapeles.
:::

## Propiedades y API

### `ui.AuthPrompt`

```python
class AuthPrompt
```

Un componente que pide iniciar sesión, como Zed cuando un agente lo necesita: un botón por cada forma de entrar y, mientras una está en curso, qué pasa (el navegador o una terminal está abierto), un código para escribir si lo hay, Abrir la página otra vez y Cancelar.

| Propiedad | Por defecto | Descripción |
| --- | --- | --- |
| `title` | `""` | El título. |
| `detail` | `""` | Una línea debajo. |
| `methods` | `None` | Dicts con `id`, `name` y, opcionalmente, `description` e `icon`; el primero es el principal. |
| `waiting` | `""` | El id del método en curso (`""` si no hay). |
| `waiting_text` | `""` | Lo que se muestra mientras espera. |
| `code` | `""` | Un código para escribir (inicio de sesión por dispositivo). |
| `url` | `""` | La página que se abrió. |
| `error` | `""` | Un error a mostrar. |
| `icon_name` | `"key-round"` | El icono. |
| `theme` | `None` | Tema. |

Eventos: `on_pick`, `on_cancel`, `on_open_url`, `on_copy` ([eventos](#eventos)).

[Referencia completa →](https://albakore.github.io/pyzed/es/reference/ui/#authprompt)

## Relacionados

- [Aviso](https://albakore.github.io/pyzed/es/library/callout/): Un aviso en línea con título, texto y acciones.
- [Botón](https://albakore.github.io/pyzed/es/library/button/): El botón con tema: variantes, tamaños, iconos y atajos.
- [Fila de servicio](https://albakore.github.io/pyzed/es/library/service-row/): Una fila de ajustes para un servidor MCP, un agente o una skill: estado, interruptor y menú.
