Metadata-Version: 2.4
Name: handsbot-maestro-sdk
Version: 0.7.0
Summary: SDK Python para criação de tarefas no Maestro (4HandsBot)
Project-URL: Homepage, https://github.com/fourhandsbot/maestro
Project-URL: Bug Tracker, https://github.com/fourhandsbot/maestro/issues
Keywords: maestro,handsbot,automation,rpa,sdk
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: License :: Other/Proprietary License
Classifier: Operating System :: OS Independent
Classifier: Intended Audience :: Developers
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.11
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: requests>=2.31.0
Dynamic: license-file

# handsbot-maestro-sdk

SDK Python para criar e enfileirar tarefas de automação no **Maestro** (4HandsBot).

## Instalação

```bash
pip install handsbot-maestro-sdk
```

No `requirements.txt` do bot, prefira fixar a faixa da versão menor:

```
handsbot-maestro-sdk~=0.7.0
```

Com `>=`, o bot passaria a usar sozinho cada versão nova publicada.

## Uso rápido

```python
from maestro import MaestroSDK

sdk = MaestroSDK(
    workspace="",
    login="",
    keypass="",
)

task = sdk.create_task(
    label="bot-sap-notas-fiscais",
    parameters=[
        {"label": "destinatario", "value": "admin@empresa.com"},
    ],
)

print(task.uuid, task.status)
```

## Configuração

### Bot executado pelo Maestro

Nada a configurar: use `MaestroSDK()` sem argumentos. Requer o SDK 0.4.0 ou mais
novo no `requirements.txt` do bot.

### Fora do Maestro (desenvolvimento local)

As credenciais podem ser passadas de duas formas (argumentos têm precedência).

### Via variáveis de ambiente

```bash
export MAESTRO_WORKSPACE=dev
export MAESTRO_LOGIN=empresa
export MAESTRO_KEYPASS=pass
```

```python
sdk = MaestroSDK()  # lê as variáveis automaticamente
```

### Via argumentos do construtor

```python
sdk = MaestroSDK(
    workspace="dev",
    login="empresa",
    keypass="pass",
)
```

## Ler parâmetros da execução (0.7)

```python
from maestro import MaestroSDK

nome = MaestroSDK.get_parameter("nome", default="Maestro")
```

O Executor recebe os parâmetros da API e entrega ao processo como `--label valor`.
O método lê esses argumentos sem HTTP ou autenticação e funciona também com
`python bot.py --nome "Ana"` no desenvolvimento local. Se você já criou `sdk`, pode usar
`sdk.get_parameter("nome", default="Maestro")`.

O retorno é texto, sem conversão de tipo. O label é exato, sem `--`. Ausência retorna
`default` (ou `None`); valor vazio é preservado; repetição usa o último valor. Também aceita
`--nome=Ana`. Uma opção solicitada sem valor gera `MaestroConfigError`. No formato de dois
argumentos, o próximo argumento é o valor, mesmo quando começa com `--`, como no Executor.
Um `--` isolado fora de um valor encerra a leitura. O padrão cadastrado na automação é
resolvido pelo Executor antes da chamada; `default` cobre a ausência do argumento no processo.

## Formato do `label`

`label` é o identificador da automação, do parâmetro e da credencial: é por ele
que o SDK encontra o registro. Letras, números e `-` ou `_` entre eles, de 3 a 64
caracteres (`bot-sap-notas-fiscais`, `data_corte`).

Maiúscula é aceita, mas duas grafias que só diferem na caixa não podem existir
na mesma organização. A busca é por **correspondência exata**: se o label
cadastrado é `Bot-SAP`, `create_task("bot-sap")` devolve 404.

Ele é **imutável e único dentro da organização**: uma vez criado, o painel não
deixa trocá-lo, justamente para que um bot em produção nunca deixe de achar a
automação que chama.

## `create_task`

```python
task = sdk.create_task(
    label="bot-sap-notas-fiscais",   # obrigatório: label cadastrado no Maestro
    parameters=[                      # opcional
        {"label": "param1", "value": "valor1"},
    ],
    priority=1,                       # opcional, padrão 1, máximo 5
    min_execution_date=datetime(...), # opcional: executa somente após esse momento
    idempotency_key="nf-2026-001",    # opcional: gerada sozinha se omitida
)
```

| Parâmetro            | Tipo         | Descrição                                                                                 |
| -------------------- | ------------ | ----------------------------------------------------------------------------------------- |
| `label`              | `str`        | Label da automação cadastrada no Maestro                                                  |
| `parameters`         | `list[dict]` | Lista de `{"label": ..., "value": ...}`                                                   |
| `priority`           | `int`        | Prioridade da tarefa (padrão: `1`)                                                        |
| `min_execution_date` | `datetime`   | Data/hora mínima para a tarefa ser executada. Sem `tzinfo`, vale o fuso da máquina do bot |
| `idempotency_key`    | `str`        | Evita tarefa duplicada quando a chamada é repetida                                        |

### Idempotência

Um timeout de rede depois que a API já gravou a tarefa deixaria o bot achando
que falhou. Por isso `create_task` envia uma chave de idempotência e, em falha de
conexão, repete a chamada uma vez: a API devolve a tarefa já criada em vez de
criar outra.

A chave é gerada automaticamente a cada chamada. Informe a sua quando duas
execuções diferentes do bot precisarem se reconhecer como a mesma criação, por
exemplo usando o número da nota fiscal. A chave é permanente e vale por
organização: repetir a mesma chave meses depois devolve a mesma tarefa.

## Reportar o resultado da execução

Na automação configurada com **status reportado pelo bot**, a tarefa só termina
com sucesso se o bot chamar `report_success`. Sem relato, ou com
`report_failure`, ela termina como falha, qualquer que seja o código de saída.

```python
sdk.report_success("142 notas emitidas")
sdk.report_failure("Portal da prefeitura fora do ar")
```

Vale o primeiro relato da execução: o segundo levanta
`ResultAlreadyReportedError`. Fora de um bot executado pelo Maestro, os dois
levantam `MaestroConfigError`.

## Fila de itens

A fila precisa estar vinculada à automação do bot no painel (tela Filas). A
mensagem curta de cada item vai para o painel; não coloque senha no conteúdo
do item, use `get_credential`.

```python
from maestro import MaestroSDK, BusinessError

sdk = MaestroSDK()
fila = sdk.queue("notas-fiscais")

fila.add({"cnpj": "00.000.000/0001-00", "valor": 10.5}, reference="NF-2026-0001")

for item in fila.items():          # reserva um item por vez até a fila esvaziar
    with item:
        if not item.payload.get("cnpj"):
            raise BusinessError("CNPJ ausente")   # erro de negócio: não repete
        emitir(item.payload)                      # outra exceção: erro de sistema
        item.success(output={"numero": "123"})    # opcional: sair do with já é sucesso
```

- Erro de sistema volta o item para a fila enquanto houver tentativas (a fila
  define quantas e a espera entre elas). Erro de negócio fecha o item.
- Cada item tem um prazo. Se o bot passar dele, o item volta para a fila e
  pode ser processado de novo: escreva o processamento para tolerar repetição.
- Com `reference`, repetir `add` devolve o item já existente em vez de
  duplicar. Referência repetida com outro conteúdo levanta
  `ReferenceConflictError`.
- `add_many([{"payload": ..., "reference": ...}, ...])` envia em lotes de 100.
- `fila.next()` devolve um item ou `None` com a fila vazia.

## Exceções

Todas herdam de `MaestroError`, então `except MaestroError` continua pegando
tudo. A exceção é `BusinessError`, que é levantada pelo seu código e não pela
API: ela herda de `Exception` para um `except MaestroError` não engolir a regra
de negócio do bot.

| Exceção                   | Quando                                    |
| ------------------------- | ----------------------------------------- |
| `MaestroConfigError`      | Credenciais ausentes na inicialização     |
| `MaestroAuthError`        | Credenciais inválidas ou token expirado   |
| `MaestroConnectionError`  | Falha de rede ou `requests` não instalado |
| `AutomationNotFoundError` | Label de automação não encontrado         |
| `CredentialNotFoundError` | Label de credencial não encontrado        |
| `TaskNotFoundError`       | Tarefa não encontrada                     |
| `InvalidParametersError`  | Parâmetro fora dos labels cadastrados     |
| `PlanLimitReachedError`   | Cota do plano esgotada                    |
| `QueueNotFoundError`      | Fila inexistente ou não vinculada à automação |
| `QueueItemLockLostError`  | O prazo do item venceu ou ele já foi concluído |
| `ReferenceConflictError`  | Referência já usada com outro conteúdo (`.references`) |
| `ResultAlreadyReportedError` | A execução já tinha um relato          |
| `TaskTokenRequiredError`  | Relato fora do token da execução          |
| `PlanFeatureDisabledError` | Funcionalidade fora do plano             |
| `MaestroError`            | Qualquer outro erro devolvido pela API    |

Cada exceção carrega `.code` (o código estável devolvido pela API) e
`.status_code`. Quando a API não envia `code`, `.code` fica `None`.

## Licença

Copyright © 2026 4HandsBot. Todos os direitos reservados.

O uso deste SDK é permitido exclusivamente por clientes autorizados,
em conjunto com os serviços da plataforma. É proibida a redistribuição,
publicação, sublicenciamento ou utilização fora dessa finalidade, para saber mais, consulte nossos termos de serviço acessando https://maestro.4handsbot.com.br/termos-e-condicoes e nossa política de privacidade https://maestro.4handsbot.com.br/politica-privacidade.
