Metadata-Version: 2.5
Name: onerom-core
Version: 0.4.2
Summary: SDK oficial para automacoes ONEROM
License: MIT
Keywords: automation,onerom,rpa,sdk
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Software Development :: Libraries
Requires-Python: >=3.9
Requires-Dist: pydantic>=2.0
Requires-Dist: requests>=2.28
Provides-Extra: dev
Requires-Dist: pytest-cov; extra == 'dev'
Requires-Dist: pytest>=7.0; extra == 'dev'
Description-Content-Type: text/markdown

# onerom-core

SDK oficial Python para automações ONEROM.

Usado dentro de bots executados pelo ONEROM Runner.

## Instalação

```bash
pip install onerom-core
```

Ou via `pyproject.toml` do bot:

```toml
[project]
dependencies = ["onerom-core>=0.1.0"]
```

## Uso básico

```python
from onerom_core import OneromExecution
import logging

# Inicializa contexto da execução
# - Carrega parâmetros da execução automaticamente
# - Anexa handler de log estruturado ao logger raiz
exec = OneromExecution()

# Acesso a parâmetros tipados
nome = exec.params.nome
count = exec.params.count

# Logging — capturado pelo runner e enviado ao backend
logging.info(f"Processando {nome}")

# Contagem de itens
for item in get_items():
    try:
        process(item)
        exec.add_success_item()
    except Exception:
        exec.add_failed_item()

# Finaliza com sucesso
exec.finish_success()
```

## Uso com wrapper automático

```python
from onerom_core import OneromExecution

exec = OneromExecution()

def main():
    logging.info("Bot iniciado")
    # ... lógica do bot ...

# Gerencia mark_running → main() → finish_success/failed automaticamente
exec.run(main)
```

## Ciclo de vida

| Método | Descrição |
|--------|-----------|
| `mark_running()` | Notifica backend que a execução começou |
| `add_success_item(record=None)` | Incrementa contador de itens processados; com `record`, também devolve o dado |
| `add_failed_item()` | Incrementa contador de itens que falharam |
| `add_record(record)` | Acumula um registro para devolver a quem disparou a execução |
| `set_result(result)` | Define o resultado inteiro (lista de registros ou dict) |
| `report_progress(processed, total)` | Reporta progresso parcial |
| `finish_success(result=None)` | Finaliza como bem-sucedida (envia os registros acumulados) |
| `finish_failed(error_message)` | Finaliza como falha |
| `run(fn)` | Wrapper automático completo |

### Devolvendo dados para quem disparou

Quando a execução vem de uma integração (por exemplo, um **DataPull** do Onerom
Enterprise Operations), os registros acumulados voltam para o sistema que pediu e
viram casos no processo alvo. Bot que não usa isso continua igual — nada muda no
que já roda hoje.

```python
for cliente in consultar_clientes():
    exec.add_success_item({"cpf": cliente.cpf, "nome": cliente.nome})

exec.finish_success()   # os registros vão junto
```

## Parâmetros

Os parâmetros são injetados pelo runner via `ONEROM_CONTEXT` e `ONEROM_PARAMETERS`.

```python
exec = OneromExecution()

# Acesso por atributo
valor = exec.params.meu_parametro

# Acesso como dict (sem schema)
dados = exec.params.as_dict()
```

### Schema tipado (opcional)

Se `ONEROM_PARAM_SCHEMA` estiver definido, os parâmetros são validados com Pydantic:

```python
# Backend retorna schema:
# [{"name": "cnpj", "type": "string", "required": true}]
# Validação automática e acesso tipado:
cnpj: str = exec.params.cnpj
```

Tipos suportados: `string`, `int`, `double`, `bool`, `json`, `list`

## Logging

O `OneromLogHandler` é anexado automaticamente ao logger raiz. Cada chamada de log
gera uma linha JSON no stdout, que o runner captura e envia ao backend.

```python
import logging

logging.info("Processando item")    # → backend via runner
logging.warning("Item ignorado")
logging.error("Falha ao processar")

# Logger customizado
exec.attach_logger(logging.getLogger("meu_modulo"))
```

## Artefatos

Arquivos que devem virar evidência operacional — CSV de saída, PDF, captura de
tela — vão para o diretório oficial, não para um caminho local qualquer. Só o
que está lá é publicado pelo produto.

```python
exec = OneromExecution()

if exec.artifacts_dir:                      # None em modo offline
    destino = exec.artifact_path("relatorios/pagamentos.csv")
    destino.write_text(conteudo, encoding="utf-8")
```

`artifact_path()` monta o caminho e **recusa** o que sairia da pasta:

| recusa | por quê |
|---|---|
| caminho enraizado (`/tmp/x.csv`, `C:x.csv`, `\\srv\share\x.csv`) | escaparia do diretório oficial |
| `..` em qualquer parte | o mesmo, por outro caminho |
| nome com `token`, `secret`, `password`, `.env`… | artefato é evidência, não lugar de credencial |
| extensão fora de `.csv .json .pdf .png .jpg .jpeg .webp .txt .xlsx` | o runner não publica outros formatos |

Além das regras acima, que olham o texto, ele confere **onde o arquivo cai de
fato** — um jeito de escapar que ninguém previu morre ali, e não no disco.

> No Windows, `Path("/tmp/x.csv").is_absolute()` responde **False** (não tem
> letra de unidade), e `pasta / "/tmp/x.csv"` cai na raiz do disco. Foi
> exatamente assim que a primeira versão desta guarda falhava.

---

## Fila de demandas

Um bot comum recebe um payload e termina. Um **worker de fila** drena itens
enquanto houver trabalho. É opt-in: só entra em ação quando o runner define
`ONEROM_DEMANDA_POOL_ID`, o que só acontece em execução criada pelo autoscaler.

```python
exec = OneromExecution()

for item in exec.pull():
    try:
        item.success(processa(item.data))
    except ErroTransiente as e:
        item.retry(e)        # volta para a fila até max_attempts
    except Exception as e:
        item.reject(e)       # vai direto para o dead-letter
```

Se o corpo do laço terminar sem finalizar o item, ele é marcado como sucesso.

**O que cada item traz:** `id`, `data` (o payload), `attempts`, `priority`,
`external_ref`, `deadline_at`.

**Duas propriedades que parecem a mesma coisa e não são:**

| propriedade | significa |
|---|---|
| `finished` | o bot **declarou** um desfecho |
| `confirmed` | o backend **soube** do desfecho |

A distinção existe por um motivo concreto: se o sucesso automático do fim do
laço dependesse da confirmação, um `reject()` que não chegou ao backend seria
seguido de um `success()` — a rejeição viraria sucesso por causa de uma falha
de rede.

**Quando a rede oscila:**

- reportar o desfecho é tentado **4 vezes** com recuo exponencial. Sem
  confirmação, o item volta à fila pelo lease e será reprocessado — ruim, mas
  melhor que dar por concluído algo que o backend nunca soube;
- consultar a fila distingue **vazia** de **inacessível**. Falha de rede não
  conta como ociosidade; o laço insiste com recuo e, depois de 5 falhas
  seguidas, **levanta** `RuntimeError` em vez de encerrar anunciando "fila
  vazia". O worker morre visível e o autoscaler sobe outro.

O lease do item em processamento é renovado em segundo plano enquanto o corpo
do laço roda, e o laço verifica cancelamento a cada volta (scale-down gracioso).

---

## Variáveis de ambiente

Injetadas automaticamente pelo runner:

| Variável | Descrição |
|----------|-----------|
| `ONEROM_EXECUTION_ID` | ID da execução atual |
| `ONEROM_BOT_NAME` | Nome do bot |
| `ONEROM_RUNNER_ID` | ID do runner |
| `ONEROM_PARAMETERS` | JSON com parâmetros da execução |
| `ONEROM_CONTEXT` | JSON com contexto completo |
| `ONEROM_METRICS_FILE` | Caminho do arquivo de métricas |
| `ONEROM_API_URL` | Base da API runner-agent (`.../api/v1/runner-agent`) |
| `ONEROM_RUNNER_KEY` | Chave de autenticação do runner |
| `ONEROM_API_TOKEN` | Token da empresa, quando o bot fala com a API pública |
| `ONEROM_ARTIFACTS_DIR` | Diretório oficial de artefatos. Ausente ⇒ `artifacts_dir` é `None` |
| `ONEROM_DEMANDA_POOL_ID` | Id da fila a drenar. Presente **só** em worker de fila; é o que habilita `pull()` |
| `ONEROM_PARAM_SCHEMA` | JSON com o schema dos parâmetros, para validação tipada |

Contrato oficial: `../RUNNER_ENV_CONTRACT.md`

---

## Modelo de trabalho IA - 2026-05-22

Projeto: `onerom_core`. Stack: Biblioteca Python, pytest. Este arquivo segue o modelo oficial em `PATHS.toml` e deve ser atualizado ao iniciar ou alterar o projeto.

## Modelo de trabalho

- `MAPA_MENTAL_MARKMAP.md` contem o mapa completo para visualizar no Markmap; `MAPA_EXECUTIVO_MARKMAP.md` contem a versao resumida.
