zsynctech-sdk 1.4.9__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,208 @@
1
+ Metadata-Version: 2.3
2
+ Name: zsynctech-sdk
3
+ Version: 1.4.9
4
+ Summary: SDK Python para conectar robôs (RPA) à plataforma zsynctech-studio via Socket.IO
5
+ Author: Rodrigo Zavan
6
+ Author-email: Rodrigo Zavan <rodrigo.zavan@zsynctech.com.br>
7
+ Requires-Dist: loguru>=0.7
8
+ Requires-Dist: pydantic>=2.9
9
+ Requires-Dist: python-socketio[client]>=5.11
10
+ Requires-Dist: requests>=2.31
11
+ Requires-Python: >=3.13
12
+ Description-Content-Type: text/markdown
13
+
14
+ # zsynctech-sdk
15
+
16
+ SDK Python oficial para conectar robôs de RPA à plataforma **zsynctech-studio**: handshake,
17
+ heartbeat, ciclo de execução, consumo de fila e acesso ao cofre de credenciais, tudo via
18
+ Socket.IO (namespace `/robot`).
19
+
20
+ ## Uso rápido
21
+
22
+ `client.on_automation_start` registra o que rodar quando a plataforma disparar o botão
23
+ "Iniciar" para esse robô. `client.listen()` mantém o processo vivo aguardando esse evento,
24
+ até a conexão encerrar ou você pressionar Ctrl+C.
25
+
26
+ Há duas formas de reportar trabalho, dependendo de onde a lista de tasks vem:
27
+
28
+ ### Consumindo a fila da plataforma
29
+
30
+ Use quando as tasks vêm de uma planilha importada na plataforma - `client.queue.consume()`
31
+ entrega uma a uma até a fila esvaziar.
32
+
33
+ ```python
34
+ from zsynctech_studio_sdk import RobotClient, TaskStatus
35
+
36
+ client = RobotClient.from_api_key(
37
+ "<sua-api-key>",
38
+ backend_url="http://localhost:5000",
39
+ )
40
+
41
+ @client.on_automation_start
42
+ def handle_automation() -> None:
43
+ with client.execution.run(observation="Minha automação"):
44
+ for task in client.queue.consume():
45
+ with client.queue.processing(task) as outcome:
46
+ resultado = processar(task.payload)
47
+ outcome.success(result=resultado)
48
+
49
+ with client:
50
+ client.listen()
51
+ ```
52
+
53
+ ### Sem fila: robô que processa a própria fonte de dados
54
+
55
+ Use quando o robô lê de uma fonte própria (planilha local, API interna, scraping, banco de
56
+ dados...) em vez de uma fila importada na plataforma - pule `client.queue` inteiramente e
57
+ reporte cada resultado direto com `client.execution.report_tasks(...)`.
58
+
59
+ ```python
60
+ from zsynctech_studio_sdk import RobotClient, TaskItem, TaskStatus
61
+ from zsynctech_studio_sdk.utils import utc_now
62
+
63
+ client = RobotClient.from_api_key(
64
+ "<sua-api-key>",
65
+ backend_url="http://localhost:5000",
66
+ )
67
+
68
+ @client.on_automation_start
69
+ def handle_automation() -> None:
70
+ itens = buscar_itens_a_processar() # a fonte de dados é sua
71
+
72
+ with client.execution.run(observation="Processamento de itens próprios"):
73
+ for item in itens:
74
+ started_at = utc_now()
75
+ resultado = processar(item)
76
+
77
+ client.execution.report_tasks([
78
+ TaskItem(
79
+ external_id=item.id,
80
+ status=TaskStatus.SUCCESS,
81
+ result=resultado,
82
+ started_at=started_at,
83
+ finished_at=utc_now(),
84
+ )
85
+ ])
86
+
87
+ with client:
88
+ client.listen()
89
+ ```
90
+
91
+ Exemplos completos em [`examples/`](examples/):
92
+
93
+ - [`simulate_robot.py`](examples/simulate_robot.py) - robô completo consumindo tasks de uma
94
+ fila da plataforma (`client.queue.consume()`); também demonstra `client.credentials.reveal()`
95
+ logo após conectar.
96
+ - [`own_tasks_robot.py`](examples/own_tasks_robot.py) - robô que processa a própria fonte de
97
+ dados (planilha, API interna, etc.) e reporta os resultados direto na execução
98
+ (`client.execution.report_tasks()`), sem usar fila.
99
+
100
+ ### Observação da execução
101
+
102
+ `observation` descreve o que está acontecendo numa execução - visível na plataforma. Dá pra
103
+ atualizá-la quantas vezes quiser enquanto a execução está rodando, e sobrescrevê-la no
104
+ `finish()` com o resultado final. `execution.run()` (o atalho com `with`) sempre finaliza com a
105
+ `observation` original, então esse controle mais fino pede o par `start()`/`finish()` manual:
106
+
107
+ ```python
108
+ client.execution.start(observation="Boletagem VCOM")
109
+ try:
110
+ tasks = list(client.queue.consume())
111
+ if not tasks:
112
+ client.execution.finish(observation="Fila vazia, nada a processar")
113
+ else:
114
+ for i, task in enumerate(tasks, start=1):
115
+ client.execution.update_observation(f"Processando {i}/{len(tasks)}")
116
+ ...
117
+ client.execution.finish()
118
+ except Exception:
119
+ client.execution.finish(ExecutionFinishStatus.FAILED)
120
+ raise
121
+ ```
122
+
123
+ ## Credenciais
124
+
125
+ O cofre de credenciais é acessado via REST (`/robot/credentials`), sem precisar de uma conexão
126
+ `/robot` aberta - `client.credentials` funciona mesmo antes de `client.connect()`:
127
+
128
+ ```python
129
+ credencial = client.credentials.reveal("<credential-id>")
130
+ print(credencial.value) # str (TEXT), dict[str, str] (KEY_VALUE) ou JSON (JSON)
131
+
132
+ client.credentials.rotate("<credential-id>", "novo-valor")
133
+
134
+ client.credentials.expire("<credential-id>", "Login rejeitado pelo site do fornecedor")
135
+ ```
136
+
137
+ Veja `log_credential()` em [`examples/simulate_robot.py`](examples/simulate_robot.py) para um
138
+ exemplo em contexto (revela uma credencial e loga o valor assim que conecta).
139
+
140
+ ### Buscando por `key` em vez de `id`
141
+
142
+ `id` é o identificador interno da credencial - regenerado se o banco da plataforma for
143
+ restaurado/migrado, quebrando qualquer robô que o tenha fixo no `.env`. `key` é um identificador
144
+ estável, definido pelo admin na plataforma (ex.: `"financeiro/senha-sap"`) e independente de
145
+ `id`/`name`/pasta - renomear a credencial ou movê-la de pasta nunca muda a `key`. Prefira `key`
146
+ para qualquer credencial referenciada de fora da plataforma:
147
+
148
+ ```python
149
+ credencial = client.credentials.reveal_by_key("financeiro/senha-sap")
150
+
151
+ client.credentials.rotate_by_key("financeiro/senha-sap", "novo-valor")
152
+
153
+ client.credentials.expire_by_key("financeiro/senha-sap", "Login rejeitado pelo site do fornecedor")
154
+ ```
155
+
156
+ ## Arquitetura
157
+
158
+ | Módulo | Responsabilidade |
159
+ | --- | --- |
160
+ | `client.py` | `RobotClient` - fachada única que compõe as peças abaixo |
161
+ | `connection.py` | `SocketConnection` - handshake, heartbeat automático, reconexão, `call`/`emit` |
162
+ | `execution.py` | `ExecutionManager` - ciclo `execution:start` / `execution:task` / `execution:finish` |
163
+ | `queue.py` | `QueueConsumer` - `queue:next` / `queue:task-result`, iteração da fila |
164
+ | `credentials.py` | `CredentialManager` - `reveal`/`rotate`/`expire`, por `id` ou `key`, via REST |
165
+ | `protocol.py` | Constantes do protocolo (namespace, nomes de eventos, rotas REST) |
166
+ | `exceptions.py` | Hierarquia de exceções do SDK (`RobotSDKError` e subclasses) |
167
+ | `utils.py` | Funções utilitárias reutilizáveis (detecção de plataforma, hostname, timestamps) |
168
+ | `loggers.py` | Configuração do `loguru` compartilhada pelo SDK |
169
+ | `models/` | Modelos de dados e enums (Pydantic), espelhando os DTOs/enums do backend |
170
+
171
+ Cada classe tem uma única responsabilidade (SRP): a conexão bruta não sabe o que é uma
172
+ execução, a execução não sabe como a fila funciona, e o `RobotClient` só orquestra as três.
173
+ Novos comportamentos (ex.: outro jeito de processar tasks) se registram via
174
+ `on_automation_start`/`queue.processing`, sem precisar alterar essas classes.
175
+
176
+ ## Modelos e enums (`models/`)
177
+
178
+ Todos os payloads trocados com a plataforma são validados com **Pydantic** e convertidos
179
+ entre `snake_case` (Python) e `camelCase` (protocolo) automaticamente via `SdkBaseModel`.
180
+ Os enums (`TaskStatus`, `RobotInstanceStatus`, `Platform`, ...) espelham exatamente os
181
+ enums TypeScript usados por `RobotGateway` no backend.
182
+
183
+ ## Logs
184
+
185
+ O SDK usa [`loguru`](https://loguru.readthedocs.io/) e já vem configurado com um formato
186
+ legível por padrão. Para customizar (nível, arquivo de destino, JSON estruturado):
187
+
188
+ ```python
189
+ from zsynctech_studio_sdk.loggers import configure_logging
190
+
191
+ configure_logging(level="DEBUG", sink="robot.log")
192
+ ```
193
+
194
+ Chame antes de criar o `RobotClient`.
195
+
196
+ ## Desenvolvimento
197
+
198
+ ```bash
199
+ uv run pytest # testes
200
+ uv run ruff check src examples tests # lint
201
+ uv run ruff format src examples tests # formatação
202
+ uv run mypy src examples tests # checagem de tipos (modo strict)
203
+ ```
204
+
205
+ `ruff` e `mypy` só olham `src`/`examples`/`tests` (não o README) - a partir do ruff 0.12+ o
206
+ `ruff format` também reformata blocos de código Python dentro de Markdown, o que reescreveria
207
+ os exemplos deste arquivo com as convenções de um `.py` (2 linhas em branco antes de decorators
208
+ etc.) toda vez que rodasse. CI usa esse mesmo escopo (veja `.github/workflows/ci.yml`).
@@ -0,0 +1,195 @@
1
+ # zsynctech-sdk
2
+
3
+ SDK Python oficial para conectar robôs de RPA à plataforma **zsynctech-studio**: handshake,
4
+ heartbeat, ciclo de execução, consumo de fila e acesso ao cofre de credenciais, tudo via
5
+ Socket.IO (namespace `/robot`).
6
+
7
+ ## Uso rápido
8
+
9
+ `client.on_automation_start` registra o que rodar quando a plataforma disparar o botão
10
+ "Iniciar" para esse robô. `client.listen()` mantém o processo vivo aguardando esse evento,
11
+ até a conexão encerrar ou você pressionar Ctrl+C.
12
+
13
+ Há duas formas de reportar trabalho, dependendo de onde a lista de tasks vem:
14
+
15
+ ### Consumindo a fila da plataforma
16
+
17
+ Use quando as tasks vêm de uma planilha importada na plataforma - `client.queue.consume()`
18
+ entrega uma a uma até a fila esvaziar.
19
+
20
+ ```python
21
+ from zsynctech_studio_sdk import RobotClient, TaskStatus
22
+
23
+ client = RobotClient.from_api_key(
24
+ "<sua-api-key>",
25
+ backend_url="http://localhost:5000",
26
+ )
27
+
28
+ @client.on_automation_start
29
+ def handle_automation() -> None:
30
+ with client.execution.run(observation="Minha automação"):
31
+ for task in client.queue.consume():
32
+ with client.queue.processing(task) as outcome:
33
+ resultado = processar(task.payload)
34
+ outcome.success(result=resultado)
35
+
36
+ with client:
37
+ client.listen()
38
+ ```
39
+
40
+ ### Sem fila: robô que processa a própria fonte de dados
41
+
42
+ Use quando o robô lê de uma fonte própria (planilha local, API interna, scraping, banco de
43
+ dados...) em vez de uma fila importada na plataforma - pule `client.queue` inteiramente e
44
+ reporte cada resultado direto com `client.execution.report_tasks(...)`.
45
+
46
+ ```python
47
+ from zsynctech_studio_sdk import RobotClient, TaskItem, TaskStatus
48
+ from zsynctech_studio_sdk.utils import utc_now
49
+
50
+ client = RobotClient.from_api_key(
51
+ "<sua-api-key>",
52
+ backend_url="http://localhost:5000",
53
+ )
54
+
55
+ @client.on_automation_start
56
+ def handle_automation() -> None:
57
+ itens = buscar_itens_a_processar() # a fonte de dados é sua
58
+
59
+ with client.execution.run(observation="Processamento de itens próprios"):
60
+ for item in itens:
61
+ started_at = utc_now()
62
+ resultado = processar(item)
63
+
64
+ client.execution.report_tasks([
65
+ TaskItem(
66
+ external_id=item.id,
67
+ status=TaskStatus.SUCCESS,
68
+ result=resultado,
69
+ started_at=started_at,
70
+ finished_at=utc_now(),
71
+ )
72
+ ])
73
+
74
+ with client:
75
+ client.listen()
76
+ ```
77
+
78
+ Exemplos completos em [`examples/`](examples/):
79
+
80
+ - [`simulate_robot.py`](examples/simulate_robot.py) - robô completo consumindo tasks de uma
81
+ fila da plataforma (`client.queue.consume()`); também demonstra `client.credentials.reveal()`
82
+ logo após conectar.
83
+ - [`own_tasks_robot.py`](examples/own_tasks_robot.py) - robô que processa a própria fonte de
84
+ dados (planilha, API interna, etc.) e reporta os resultados direto na execução
85
+ (`client.execution.report_tasks()`), sem usar fila.
86
+
87
+ ### Observação da execução
88
+
89
+ `observation` descreve o que está acontecendo numa execução - visível na plataforma. Dá pra
90
+ atualizá-la quantas vezes quiser enquanto a execução está rodando, e sobrescrevê-la no
91
+ `finish()` com o resultado final. `execution.run()` (o atalho com `with`) sempre finaliza com a
92
+ `observation` original, então esse controle mais fino pede o par `start()`/`finish()` manual:
93
+
94
+ ```python
95
+ client.execution.start(observation="Boletagem VCOM")
96
+ try:
97
+ tasks = list(client.queue.consume())
98
+ if not tasks:
99
+ client.execution.finish(observation="Fila vazia, nada a processar")
100
+ else:
101
+ for i, task in enumerate(tasks, start=1):
102
+ client.execution.update_observation(f"Processando {i}/{len(tasks)}")
103
+ ...
104
+ client.execution.finish()
105
+ except Exception:
106
+ client.execution.finish(ExecutionFinishStatus.FAILED)
107
+ raise
108
+ ```
109
+
110
+ ## Credenciais
111
+
112
+ O cofre de credenciais é acessado via REST (`/robot/credentials`), sem precisar de uma conexão
113
+ `/robot` aberta - `client.credentials` funciona mesmo antes de `client.connect()`:
114
+
115
+ ```python
116
+ credencial = client.credentials.reveal("<credential-id>")
117
+ print(credencial.value) # str (TEXT), dict[str, str] (KEY_VALUE) ou JSON (JSON)
118
+
119
+ client.credentials.rotate("<credential-id>", "novo-valor")
120
+
121
+ client.credentials.expire("<credential-id>", "Login rejeitado pelo site do fornecedor")
122
+ ```
123
+
124
+ Veja `log_credential()` em [`examples/simulate_robot.py`](examples/simulate_robot.py) para um
125
+ exemplo em contexto (revela uma credencial e loga o valor assim que conecta).
126
+
127
+ ### Buscando por `key` em vez de `id`
128
+
129
+ `id` é o identificador interno da credencial - regenerado se o banco da plataforma for
130
+ restaurado/migrado, quebrando qualquer robô que o tenha fixo no `.env`. `key` é um identificador
131
+ estável, definido pelo admin na plataforma (ex.: `"financeiro/senha-sap"`) e independente de
132
+ `id`/`name`/pasta - renomear a credencial ou movê-la de pasta nunca muda a `key`. Prefira `key`
133
+ para qualquer credencial referenciada de fora da plataforma:
134
+
135
+ ```python
136
+ credencial = client.credentials.reveal_by_key("financeiro/senha-sap")
137
+
138
+ client.credentials.rotate_by_key("financeiro/senha-sap", "novo-valor")
139
+
140
+ client.credentials.expire_by_key("financeiro/senha-sap", "Login rejeitado pelo site do fornecedor")
141
+ ```
142
+
143
+ ## Arquitetura
144
+
145
+ | Módulo | Responsabilidade |
146
+ | --- | --- |
147
+ | `client.py` | `RobotClient` - fachada única que compõe as peças abaixo |
148
+ | `connection.py` | `SocketConnection` - handshake, heartbeat automático, reconexão, `call`/`emit` |
149
+ | `execution.py` | `ExecutionManager` - ciclo `execution:start` / `execution:task` / `execution:finish` |
150
+ | `queue.py` | `QueueConsumer` - `queue:next` / `queue:task-result`, iteração da fila |
151
+ | `credentials.py` | `CredentialManager` - `reveal`/`rotate`/`expire`, por `id` ou `key`, via REST |
152
+ | `protocol.py` | Constantes do protocolo (namespace, nomes de eventos, rotas REST) |
153
+ | `exceptions.py` | Hierarquia de exceções do SDK (`RobotSDKError` e subclasses) |
154
+ | `utils.py` | Funções utilitárias reutilizáveis (detecção de plataforma, hostname, timestamps) |
155
+ | `loggers.py` | Configuração do `loguru` compartilhada pelo SDK |
156
+ | `models/` | Modelos de dados e enums (Pydantic), espelhando os DTOs/enums do backend |
157
+
158
+ Cada classe tem uma única responsabilidade (SRP): a conexão bruta não sabe o que é uma
159
+ execução, a execução não sabe como a fila funciona, e o `RobotClient` só orquestra as três.
160
+ Novos comportamentos (ex.: outro jeito de processar tasks) se registram via
161
+ `on_automation_start`/`queue.processing`, sem precisar alterar essas classes.
162
+
163
+ ## Modelos e enums (`models/`)
164
+
165
+ Todos os payloads trocados com a plataforma são validados com **Pydantic** e convertidos
166
+ entre `snake_case` (Python) e `camelCase` (protocolo) automaticamente via `SdkBaseModel`.
167
+ Os enums (`TaskStatus`, `RobotInstanceStatus`, `Platform`, ...) espelham exatamente os
168
+ enums TypeScript usados por `RobotGateway` no backend.
169
+
170
+ ## Logs
171
+
172
+ O SDK usa [`loguru`](https://loguru.readthedocs.io/) e já vem configurado com um formato
173
+ legível por padrão. Para customizar (nível, arquivo de destino, JSON estruturado):
174
+
175
+ ```python
176
+ from zsynctech_studio_sdk.loggers import configure_logging
177
+
178
+ configure_logging(level="DEBUG", sink="robot.log")
179
+ ```
180
+
181
+ Chame antes de criar o `RobotClient`.
182
+
183
+ ## Desenvolvimento
184
+
185
+ ```bash
186
+ uv run pytest # testes
187
+ uv run ruff check src examples tests # lint
188
+ uv run ruff format src examples tests # formatação
189
+ uv run mypy src examples tests # checagem de tipos (modo strict)
190
+ ```
191
+
192
+ `ruff` e `mypy` só olham `src`/`examples`/`tests` (não o README) - a partir do ruff 0.12+ o
193
+ `ruff format` também reformata blocos de código Python dentro de Markdown, o que reescreveria
194
+ os exemplos deste arquivo com as convenções de um `.py` (2 linhas em branco antes de decorators
195
+ etc.) toda vez que rodasse. CI usa esse mesmo escopo (veja `.github/workflows/ci.yml`).
@@ -0,0 +1,61 @@
1
+ [project]
2
+ name = "zsynctech-sdk"
3
+ version = "1.4.9"
4
+ description = "SDK Python para conectar robôs (RPA) à plataforma zsynctech-studio via Socket.IO"
5
+ readme = "README.md"
6
+ requires-python = ">=3.13"
7
+ dependencies = [
8
+ "loguru>=0.7",
9
+ "pydantic>=2.9",
10
+ "python-socketio[client]>=5.11",
11
+ "requests>=2.31",
12
+ ]
13
+
14
+ [[project.authors]]
15
+ name = "Rodrigo Zavan"
16
+ email = "rodrigo.zavan@zsynctech.com.br"
17
+
18
+ [project.scripts]
19
+ zsynctech-sdk = "zsynctech_studio_sdk:main"
20
+
21
+ [build-system]
22
+ requires = ["uv_build>=0.12.8,<0.13.0"]
23
+ build-backend = "uv_build"
24
+
25
+ [tool.uv.build-backend]
26
+ module-name = "zsynctech_studio_sdk"
27
+
28
+ [tool.ruff]
29
+ line-length = 120
30
+ target-version = "py313"
31
+
32
+ [tool.ruff.lint]
33
+ select = [
34
+ "E",
35
+ "F",
36
+ "I",
37
+ "UP",
38
+ "B",
39
+ "SIM",
40
+ "N",
41
+ ]
42
+
43
+ [tool.mypy]
44
+ python_version = "3.13"
45
+ strict = true
46
+ plugins = ["pydantic.mypy"]
47
+
48
+ [[tool.mypy.overrides]]
49
+ module = "socketio.*"
50
+ ignore_missing_imports = true
51
+
52
+ [tool.pytest.ini_options]
53
+ testpaths = ["tests"]
54
+
55
+ [dependency-groups]
56
+ dev = [
57
+ "mypy>=1.13",
58
+ "pytest>=8.3",
59
+ "ruff>=0.7",
60
+ "types-requests>=2.31",
61
+ ]
@@ -0,0 +1,59 @@
1
+ [project]
2
+ name = "zsynctech-sdk"
3
+ version = "1.4.9"
4
+ description = "SDK Python para conectar robôs (RPA) à plataforma zsynctech-studio via Socket.IO"
5
+ readme = "README.md"
6
+ authors = [
7
+ { name = "Rodrigo Zavan", email = "rodrigo.zavan@zsynctech.com.br" }
8
+ ]
9
+ requires-python = ">=3.13"
10
+ dependencies = [
11
+ "loguru>=0.7",
12
+ "pydantic>=2.9",
13
+ "python-socketio[client]>=5.11",
14
+ "requests>=2.31",
15
+ ]
16
+
17
+ [project.scripts]
18
+ zsynctech-sdk = "zsynctech_studio_sdk:main"
19
+
20
+ [build-system]
21
+ requires = ["uv_build>=0.12.8,<0.13.0"]
22
+ build-backend = "uv_build"
23
+
24
+ # The importable module stays zsynctech_studio_sdk (src/zsynctech_studio_sdk/) even though the
25
+ # distribution was renamed to zsynctech-sdk on PyPI (the old "zsynctech-studio-sdk" name is
26
+ # stuck on a PyPI account we lost access to) - uv_build otherwise infers the module name from
27
+ # the project name (hyphens to underscores), which would no longer match this package's actual
28
+ # directory. Keeping the import path the same means every robot that already does
29
+ # `from zsynctech_studio_sdk import ...` only needs its pyproject.toml dependency line updated,
30
+ # not a single import statement.
31
+ [tool.uv.build-backend]
32
+ module-name = "zsynctech_studio_sdk"
33
+
34
+ [dependency-groups]
35
+ dev = [
36
+ "mypy>=1.13",
37
+ "pytest>=8.3",
38
+ "ruff>=0.7",
39
+ "types-requests>=2.31",
40
+ ]
41
+
42
+ [tool.ruff]
43
+ line-length = 120
44
+ target-version = "py313"
45
+
46
+ [tool.ruff.lint]
47
+ select = ["E", "F", "I", "UP", "B", "SIM", "N"]
48
+
49
+ [tool.mypy]
50
+ python_version = "3.13"
51
+ strict = true
52
+ plugins = ["pydantic.mypy"]
53
+
54
+ [[tool.mypy.overrides]]
55
+ module = "socketio.*"
56
+ ignore_missing_imports = true
57
+
58
+ [tool.pytest.ini_options]
59
+ testpaths = ["tests"]
@@ -0,0 +1,95 @@
1
+ """SDK Python para conectar robôs (RPA) à plataforma zsynctech-studio via `/robot` (Socket.IO).
2
+
3
+ Uso rápido:
4
+
5
+ from zsynctech_studio_sdk import RobotClient, TaskStatus
6
+
7
+ client = RobotClient.from_api_key("<sua-api-key>", backend_url="http://localhost:5000")
8
+
9
+ @client.on_automation_start
10
+ def handle_automation() -> None:
11
+ with client.execution.run(observation="Minha automação"):
12
+ for task in client.queue.consume():
13
+ with client.queue.processing(task) as outcome:
14
+ outcome.success(result={"ok": True})
15
+
16
+ with client:
17
+ client.listen()
18
+
19
+ O cofre de credenciais é acessado à parte, via REST (não precisa de conexão aberta):
20
+
21
+ credencial = client.credentials.reveal("<credential-id>")
22
+ print(credencial.value)
23
+
24
+ Veja `examples/simulate_robot.py` para um exemplo completo.
25
+ """
26
+
27
+ from .client import RobotClient
28
+ from .credentials import CredentialManager
29
+ from .exceptions import (
30
+ AckTimeoutError,
31
+ CredentialRequestError,
32
+ NoActiveExecutionError,
33
+ NotConnectedError,
34
+ RobotConnectionError,
35
+ RobotSDKError,
36
+ ServerRejectedError,
37
+ )
38
+ from .execution import ExecutionManager
39
+ from .models import (
40
+ ClaimedTask,
41
+ CredentialInfo,
42
+ CredentialStatus,
43
+ CredentialType,
44
+ ExecutionFinishResult,
45
+ ExecutionFinishStatus,
46
+ ExecutionStartResult,
47
+ Platform,
48
+ RevealedCredential,
49
+ RobotAvailability,
50
+ RobotClientConfig,
51
+ RobotConnection,
52
+ RobotInfo,
53
+ RobotInstanceStatus,
54
+ RobotStatus,
55
+ TaskItem,
56
+ TaskStatus,
57
+ )
58
+ from .queue import QueueConsumer, TaskOutcome
59
+
60
+ __all__ = [
61
+ "RobotClient",
62
+ "RobotClientConfig",
63
+ "ExecutionManager",
64
+ "QueueConsumer",
65
+ "TaskOutcome",
66
+ "CredentialManager",
67
+ "RobotSDKError",
68
+ "RobotConnectionError",
69
+ "NotConnectedError",
70
+ "AckTimeoutError",
71
+ "ServerRejectedError",
72
+ "NoActiveExecutionError",
73
+ "CredentialRequestError",
74
+ "ClaimedTask",
75
+ "TaskItem",
76
+ "RobotInfo",
77
+ "RobotConnection",
78
+ "ExecutionStartResult",
79
+ "ExecutionFinishResult",
80
+ "CredentialInfo",
81
+ "RevealedCredential",
82
+ "Platform",
83
+ "RobotStatus",
84
+ "RobotAvailability",
85
+ "RobotInstanceStatus",
86
+ "TaskStatus",
87
+ "ExecutionFinishStatus",
88
+ "CredentialStatus",
89
+ "CredentialType",
90
+ "main",
91
+ ]
92
+
93
+
94
+ def main() -> None:
95
+ print("zsynctech-studio-sdk - use RobotClient para conectar um robô à plataforma zsynctech-studio.")