Metadata-Version: 2.5
Name: shade-sdk
Version: 0.6.0
Summary: O runtime dos robôs da ShadeOne: ledger por chave de negócio, recuperação, relatório e o protocolo com o executor.
Author: ShadeOne
License-Expression: Apache-2.0
License-File: LICENSE
Requires-Python: >=3.11
Requires-Dist: loguru>=0.7.0
Requires-Dist: openpyxl>=3.1.0
Requires-Dist: pydantic-settings>=2.0.0
Requires-Dist: pydantic>=2.0.0
Description-Content-Type: text/markdown

# shade-sdk

O runtime e o framework dos robôs da ShadeOne. O robô gerado pela plataforma importa este
pacote, na versão fixada pelo `requirements.lock` da imagem do sandbox, e o robô escrito à mão
importa o mesmo pacote (ADR 019, D1). O import é `shade_sdk`.

```python
from decimal import Decimal

from pydantic import BaseModel, Field
from shade_sdk import Alvo, Item, Pagina, Retentativa, Robo


class Pedido(BaseModel):
    cliente: str = Field(min_length=1)
    valor: Decimal = Field(gt=0)


class TelaDePedido(Pagina):
    url = "/pedidos/novo"  # relativa ao [config] base_url
    pronta = Alvo(papel="heading", nome="Novo pedido")  # abrir() espera por ela
    cliente = Alvo(rotulo="Cliente")
    salvar = Alvo(papel="button", nome="Salvar")


class CadastroDePedido(Robo):
    chave = ("cliente", "pedido")  # a chave de negócio do item
    modelo = Pedido  # o item inválido fica retido antes de abrir o navegador
    retentativas = Retentativa(sistema=3)  # erro de sistema repete; negócio nunca

    def entrar(self, pagina) -> None:  # opcional: ao abrir a sessão e se ela cair
        ...

    def processar(self, item: Item[Pedido], pagina) -> None:
        tela = TelaDePedido(pagina)
        with item.etapa("preencher"):  # tempo, resultado e erro no relatório
            tela.abrir()
            tela.cliente.fill(item.dados.cliente)  # item.dados é o Pedido validado
        with item.efetivar("salvar pedido"):  # o ensaio para aqui; o real registra antes
            tela.salvar.click()
```

`main.py` na raiz do projeto: `CadastroDePedido.main()`. Sem flag, roda em modo real, como o
robô gerado; `--rehearsal` é o ensaio. A entrada é `--input <arquivo>`, ou `data/input.json`
(onde a plataforma a deixa), ou `[itens] exemplo` do `shade.toml`: JSON, CSV (o delimitador é
detectado) ou XLSX (`[itens] aba` escolhe a aba). Planilha chega como texto, e o `modelo`
converte.

- `Robo` (uma lista de itens) e `Tarefa` (uma execução única, `executar(item, pagina)`).
- `Item`: `item.dados` (a instância do `modelo`, ou a linha), `item["campo"]` (a linha como
  veio), `item.chave`, `with item.efetivar(nome)`, `with item.etapa(nome)`,
  `item.saida(**campos)`, `item.reter(motivo)`, `item.log(texto)`.
- `modelo = <pydantic.BaseModel>`: cada item é validado antes de abrir o navegador; o inválido
  fica retido com o campo e a regra (sem o valor), e sem item válido o navegador nem abre.
- `Pagina` (`url`, `pronta`, `abrir()`, `esperar_pronta()`) e `Alvo(papel=, nome=)`,
  `Alvo(rotulo=)`, `Alvo(test_id=)`, `Alvo(texto=)` e, por último, `Alvo(css=)`: o `Locator` do
  Playwright (`tela.salvar.click()`; `tela.salvar.locator` é o cru). Quando a ação falha,
  `ErroDoAlvo` diz o alvo, a URL (sem a query), se não achou nada, se achou mais de um (e
  quais) ou em que elemento caiu, e os candidatos parecidos. `diagnosticar(pagina, alvo)` dá o
  mesmo texto sem agir.
- `shade_sdk.entradas.ler_entrada(caminho, aba=None)`: os itens de um JSON, CSV ou XLSX.
- `Retentativa(sistema=N, espera=Exponencial(base, teto), sessao_perdida="reentrar" | "falhar")`:
  a política por classe de falha. Negócio nunca repete, e nada repete depois do `__enter__` de
  `efetivar()`.
- O item que falha deixa a tela e o trecho do trace do Playwright em
  `evidencias/<sha256 da chave>/`, com teto por item e por run e os dados do item mascarados
  (`SHADE_MASCARAR_PII=0` desliga); o que passa não guarda nada.
- `self.segredo(nome)`: só a credencial declarada em `[credenciais] nomes`; `self.config`: a
  tabela `[config]`.
- Erros: `ErroDeNegocio` (não repete), `SessaoPerdida` (entra de novo e refaz),
  `ErroDeContrato`, e os sinais `ParadaDoEnsaio` e `ItemRetido` (`BaseException`: um
  `except Exception` não os engole).
- `shade_sdk.testing`: `ExecutorLocal` (o lado do executor do protocolo, com o robô em
  subprocesso) e `pagina_local` (um site local que conta os efeitos).

O runtime:

- `shade_sdk.runtime.laco`: o laço por item (ledger, retomada, política de retentativa,
  `efetivar`, etapas, resumo).
- `shade_sdk.runtime.evidencia`: o trace por item, a tela, a máscara e os tetos.
- `shade_sdk.runtime.ledger`: identidade do item por chave de negócio, o `incerto` gravado
  antes de efetivar e o canal do registro com o executor.
- `shade_sdk.runtime.recovery`: classificação da falha, sessão perdida e modal inesperado.
- `shade_sdk.runtime.report`: relatório HTML da execução e o histórico.
- `shade_sdk.runtime.config`: `Settings` e a carga do `.env`.
- `shade_sdk.runtime.output`: a planilha de saída, com ou sem mascaramento de PII.
- `shade_sdk.runtime.protocolo`: o número e o formato do contrato robô ↔ executor, inclusive a
  entrada (`main.py`, argv e ambiente).

Testes do pacote: `cd sdk && uv run pytest` (Chromium do Playwright instalado).

Licença: Apache-2.0.
