hobots 1.1.0 → 1.1.1
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.
- package/README.md +19 -18
- package/dist/index.cjs +29 -29
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +20 -20
- package/dist/index.d.ts +20 -20
- package/dist/index.js +29 -29
- package/dist/index.js.map +1 -1
- package/docs/README.md +11 -6
- package/docs/api-reference.md +9 -10
- package/docs/getting-started.md +13 -11
- package/docs/manager.md +2 -2
- package/docs/monitor.md +2 -2
- package/docs/protocol.md +8 -8
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -26,7 +26,7 @@ Também funciona em CommonJS: `const Hobots = require('hobots')`.
|
|
|
26
26
|
|
|
27
27
|
## Um SDK, duas capabilities, um `init()`
|
|
28
28
|
|
|
29
|
-
O SDK expõe **duas capabilities** autenticadas
|
|
29
|
+
O SDK expõe **duas capabilities** autenticadas pelo **mesmo Client Secret do projeto**, configuradas em um único `init()`:
|
|
30
30
|
|
|
31
31
|
| Capability | Como habilita | Para quê | Ciclo de vida |
|
|
32
32
|
| --- | --- | --- | --- |
|
|
@@ -35,13 +35,13 @@ O SDK expõe **duas capabilities** autenticadas pela **mesma DSN única do proje
|
|
|
35
35
|
|
|
36
36
|
Você usa **uma, outra ou as duas**:
|
|
37
37
|
|
|
38
|
-
- Só saber se o robô quebrou, quanto demora e se está vivo? → `init({
|
|
39
|
-
- Disparar o robô sob demanda a partir de um formulário no app? → `init({
|
|
38
|
+
- Só saber se o robô quebrou, quanto demora e se está vivo? → `init({ clientSecret, heartbeat: true })`.
|
|
39
|
+
- Disparar o robô sob demanda a partir de um formulário no app? → `init({ clientSecret, manager: true })` + `register()` + `start()`.
|
|
40
40
|
- Ambos? Passe `heartbeat` e `manager` no mesmo `init()` — o `instanceId` é a identidade única, e os dois canais convergem em **um agente** no painel.
|
|
41
41
|
|
|
42
42
|
```js
|
|
43
43
|
Hobots.init({
|
|
44
|
-
|
|
44
|
+
clientSecret: 'hb_<64 hex>',
|
|
45
45
|
instanceId: 'vm-cliente-01',
|
|
46
46
|
heartbeat: true, // Monitor: "estou vivo" a cada 30s
|
|
47
47
|
manager: { pollIntervalMs: 5_000 }, // Manager: execução sob demanda
|
|
@@ -57,15 +57,15 @@ Hobots.start(); // inicia o polling do Manager (segura o processo vivo)
|
|
|
57
57
|
|
|
58
58
|
---
|
|
59
59
|
|
|
60
|
-
## O
|
|
60
|
+
## O Client Secret
|
|
61
61
|
|
|
62
|
-
Cada projeto tem **
|
|
62
|
+
Cada projeto tem **um único Client Secret** — a mesma credencial autentica o Monitor **e** o Manager:
|
|
63
63
|
|
|
64
64
|
```
|
|
65
|
-
|
|
65
|
+
hb_<64 hex>
|
|
66
66
|
```
|
|
67
67
|
|
|
68
|
-
|
|
68
|
+
(Chaves antigas, 64 hex puros, continuam válidas no servidor.) A credencial é **secreta** e viaja sempre no header `Authorization: Bearer` — nunca na URL. Copie o Client Secret no app, em **Configurações → Projetos** — os snippets de integração já vêm prontos. O SDK fala com a API oficial `https://api.hobots.app` automaticamente; em desenvolvimento, aponte para outro host com a env `HOBOTS_API_URL` (ex.: `HOBOTS_API_URL=http://localhost:3001`).
|
|
69
69
|
|
|
70
70
|
---
|
|
71
71
|
|
|
@@ -79,7 +79,7 @@ Inicialize **uma vez**, o mais cedo possível no processo. Cria o cliente, insta
|
|
|
79
79
|
|
|
80
80
|
```js
|
|
81
81
|
Hobots.init({
|
|
82
|
-
|
|
82
|
+
clientSecret: 'hb_<64 hex>',
|
|
83
83
|
environment: 'production',
|
|
84
84
|
release: 'robo-nfe@1.4.2',
|
|
85
85
|
instanceId: 'vm-cliente-01',
|
|
@@ -90,7 +90,7 @@ Hobots.init({
|
|
|
90
90
|
|
|
91
91
|
| Opção | Tipo | Default | Descrição |
|
|
92
92
|
| --- | --- | --- | --- |
|
|
93
|
-
| `
|
|
93
|
+
| `clientSecret` | `string` | **obrigatório** | o Client Secret do projeto (`hb_<64 hex>`), copiado em **Configurações → Projetos** |
|
|
94
94
|
| `environment` | `string` | `'production'` | ambiente lógico |
|
|
95
95
|
| `release` | `string` | — | versão do programa, ex. `robo-nfe@1.4.2` |
|
|
96
96
|
| `instanceId` | `string` | **obrigatório** | identidade única da instância — heartbeat do Monitor e agente do Manager convergem nela |
|
|
@@ -203,7 +203,7 @@ Bate "estou vivo" periodicamente; o servidor acusa o robô **offline** quando os
|
|
|
203
203
|
|
|
204
204
|
```js
|
|
205
205
|
Hobots.init({
|
|
206
|
-
|
|
206
|
+
clientSecret,
|
|
207
207
|
heartbeat: { intervalMs: 30_000, name: 'Robô NFe — VM 01' },
|
|
208
208
|
});
|
|
209
209
|
```
|
|
@@ -223,13 +223,13 @@ Chame `close` antes do processo sair. Os timers do Monitor são `unref`'d — el
|
|
|
223
223
|
|
|
224
224
|
## Manager
|
|
225
225
|
|
|
226
|
-
Capability de **execução remota sob demanda**, habilitada com `manager: true` (ou opções) no `init()`. O agente faz polling no app, executa os handlers registrados quando aparece trabalho e reporta status e logs incrementais.
|
|
226
|
+
Capability de **execução remota sob demanda**, habilitada com `manager: true` (ou opções) no `init()`. O agente faz polling no app, executa os handlers registrados quando aparece trabalho e reporta status e logs incrementais. Mesmo Client Secret, mesmo `debug` e o `instanceId` como identidade — nenhum handler global extra é instalado.
|
|
227
227
|
|
|
228
228
|
### Ciclo de vida
|
|
229
229
|
|
|
230
230
|
```js
|
|
231
231
|
Hobots.init({
|
|
232
|
-
|
|
232
|
+
clientSecret: 'hb_<64 hex>',
|
|
233
233
|
instanceId: 'vm-cliente-01',
|
|
234
234
|
manager: true, // ou { pollIntervalMs, concurrency, ... }
|
|
235
235
|
});
|
|
@@ -260,7 +260,7 @@ process.on('SIGINT', () => {
|
|
|
260
260
|
| `taskTimeoutMs` | `number` | — | timeout client-side por run (não mata o handler; servidor é o backstop) |
|
|
261
261
|
| `logFlushIntervalMs` | `number` | `2000` | intervalo do envio incremental de logs |
|
|
262
262
|
|
|
263
|
-
|
|
263
|
+
O Client Secret, o `debug` e a identidade do agente (`instanceId`) vêm do `init()` — o heartbeat do Monitor e o agente do Manager convergem em **um agente** no painel automaticamente.
|
|
264
264
|
|
|
265
265
|
### O handler e o `RunContext`
|
|
266
266
|
|
|
@@ -354,7 +354,7 @@ A 2.0 unifica o Manager no import raiz — `hobots/manager` **foi removido**:
|
|
|
354
354
|
|
|
355
355
|
-Monitor.init({ dsn, serverName: 'vm-01', heartbeat: true });
|
|
356
356
|
-Manager.init({ dsn, agentName: 'vm-01' });
|
|
357
|
-
+Hobots.init({
|
|
357
|
+
+Hobots.init({ clientSecret, instanceId: 'vm-01', heartbeat: true, manager: true });
|
|
358
358
|
|
|
359
359
|
-Manager.register('minha-task', handler);
|
|
360
360
|
-Manager.start();
|
|
@@ -366,8 +366,9 @@ A 2.0 unifica o Manager no import raiz — `hobots/manager` **foi removido**:
|
|
|
366
366
|
+await Hobots.close(15_000);
|
|
367
367
|
```
|
|
368
368
|
|
|
369
|
+
- A `dsn` (mecanismo antigo, `https://<secretKey>@host/<slug>`) não existe mais — passe `clientSecret` (em desenvolvimento, aponte para outro host com a env `HOBOTS_API_URL`). Copie o Client Secret em **Configurações → Projetos**.
|
|
369
370
|
- `agentName` e `serverName` não existem mais — a identidade do agente é o `instanceId` (obrigatório, sem fallback).
|
|
370
|
-
- As opções do Manager (`pollIntervalMs`, `concurrency`, `taskTimeoutMs`, `logFlushIntervalMs`) vão no campo `manager` do `init()`; `
|
|
371
|
+
- As opções do Manager (`pollIntervalMs`, `concurrency`, `taskTimeoutMs`, `logFlushIntervalMs`) vão no campo `manager` do `init()`; `clientSecret` e `debug` não se repetem.
|
|
371
372
|
- Tipos (`ManagerTaskHandler`, `RunContext`, `ManagerOptions`) e classes (`ManagerAgent`, `ManagerApi`) agora vêm de `hobots`; o wire format vem de `hobots/protocol`.
|
|
372
373
|
|
|
373
374
|
---
|
|
@@ -376,11 +377,11 @@ A 2.0 unifica o Manager no import raiz — `hobots/manager` **foi removido**:
|
|
|
376
377
|
|
|
377
378
|
Guias detalhados acompanham o pacote em [`docs/`](./docs/README.md):
|
|
378
379
|
|
|
379
|
-
- [Getting started](./docs/getting-started.md) — instalação,
|
|
380
|
+
- [Getting started](./docs/getting-started.md) — instalação, Client Secret, primeiro `init`, Monitor vs Hobots.
|
|
380
381
|
- [Monitor](./docs/monitor.md) — erros, breadcrumbs, escopo, transactions/spans, crons, heartbeat.
|
|
381
382
|
- [Manager](./docs/manager.md) — handlers, `RunContext`, cancelamento, concorrência, idempotência.
|
|
382
383
|
- [Referência de API](./docs/api-reference.md) — todas as funções e tabelas de opções com defaults.
|
|
383
|
-
- [Protocolo & transporte](./docs/protocol.md) —
|
|
384
|
+
- [Protocolo & transporte](./docs/protocol.md) — o Client Secret, endpoints, envelope, retries.
|
|
384
385
|
|
|
385
386
|
---
|
|
386
387
|
|
package/dist/index.cjs
CHANGED
|
@@ -21,6 +21,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
21
21
|
var src_exports = {};
|
|
22
22
|
__export(src_exports, {
|
|
23
23
|
Client: () => Client,
|
|
24
|
+
DEFAULT_BASE_URL: () => DEFAULT_BASE_URL,
|
|
24
25
|
ManagerAgent: () => ManagerAgent,
|
|
25
26
|
ManagerApi: () => ManagerApi,
|
|
26
27
|
ManagerApiError: () => ManagerApiError,
|
|
@@ -35,8 +36,8 @@ __export(src_exports, {
|
|
|
35
36
|
flush: () => flush,
|
|
36
37
|
getClient: () => getClient,
|
|
37
38
|
init: () => init,
|
|
38
|
-
parseDsn: () => parseDsn,
|
|
39
39
|
register: () => register,
|
|
40
|
+
resolveConfig: () => resolveConfig,
|
|
40
41
|
setContext: () => setContext,
|
|
41
42
|
setExtra: () => setExtra,
|
|
42
43
|
setTag: () => setTag,
|
|
@@ -50,29 +51,28 @@ __export(src_exports, {
|
|
|
50
51
|
});
|
|
51
52
|
module.exports = __toCommonJS(src_exports);
|
|
52
53
|
|
|
53
|
-
// src/
|
|
54
|
-
|
|
55
|
-
|
|
54
|
+
// src/config.ts
|
|
55
|
+
var DEFAULT_BASE_URL = "https://api.hobots.app";
|
|
56
|
+
function envBaseUrl() {
|
|
57
|
+
if (typeof process === "undefined" || !process.env) return void 0;
|
|
58
|
+
return process.env.HOBOTS_API_URL?.trim() || void 0;
|
|
59
|
+
}
|
|
60
|
+
function resolveConfig(options, prefix = "[hobots]") {
|
|
61
|
+
const key = options.clientSecret?.trim();
|
|
62
|
+
if (!key) {
|
|
63
|
+
throw new Error(`${prefix} clientSecret ausente \u2014 copie o Client Secret do projeto em Configura\xE7\xF5es \u2192 Projetos`);
|
|
64
|
+
}
|
|
65
|
+
const baseUrl = (envBaseUrl() ?? DEFAULT_BASE_URL).replace(/\/+$/, "");
|
|
56
66
|
try {
|
|
57
|
-
|
|
67
|
+
new URL(baseUrl);
|
|
58
68
|
} catch {
|
|
59
|
-
throw new Error(`${prefix}
|
|
69
|
+
throw new Error(`${prefix} HOBOTS_API_URL inv\xE1lida: "${baseUrl}" \u2014 esperado ex.: http://localhost:3001`);
|
|
60
70
|
}
|
|
61
|
-
const key = url.username;
|
|
62
|
-
const path = url.pathname.replace(/^\/+/, "");
|
|
63
|
-
if (!key || !path) {
|
|
64
|
-
throw new Error(`${prefix} DSN inv\xE1lido: "${dsn}" \u2014 esperado https://<key>@host/<projeto>`);
|
|
65
|
-
}
|
|
66
|
-
return { key, path, origin: `${url.protocol}//${url.host}` };
|
|
67
|
-
}
|
|
68
|
-
function parseDsn(dsn) {
|
|
69
|
-
const { key, path, origin } = parseDsnUrl(dsn, "[hobots]");
|
|
70
71
|
return {
|
|
71
72
|
key,
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
managerBaseUrl: `${origin}/api/manager`
|
|
73
|
+
baseUrl,
|
|
74
|
+
ingestEndpoint: `${baseUrl}/api/ingest`,
|
|
75
|
+
managerBaseUrl: `${baseUrl}/api/manager`
|
|
76
76
|
};
|
|
77
77
|
}
|
|
78
78
|
|
|
@@ -308,16 +308,16 @@ function runtimeContexts() {
|
|
|
308
308
|
}
|
|
309
309
|
var Client = class {
|
|
310
310
|
options;
|
|
311
|
-
|
|
311
|
+
config;
|
|
312
312
|
logger;
|
|
313
313
|
transport;
|
|
314
314
|
constructor(options) {
|
|
315
315
|
this.options = options;
|
|
316
316
|
this.logger = makeLogger(!!options.debug);
|
|
317
|
-
this.
|
|
317
|
+
this.config = resolveConfig(options);
|
|
318
318
|
this.transport = new Transport({
|
|
319
|
-
endpoint: this.
|
|
320
|
-
key: this.
|
|
319
|
+
endpoint: this.config.ingestEndpoint,
|
|
320
|
+
key: this.config.key,
|
|
321
321
|
logger: this.logger,
|
|
322
322
|
flushIntervalMs: options.flushIntervalMs,
|
|
323
323
|
maxBatchSize: options.maxBatchSize
|
|
@@ -891,14 +891,14 @@ var ManagerAgent = class {
|
|
|
891
891
|
this.options = options;
|
|
892
892
|
this.registry = registry2;
|
|
893
893
|
this.logger = makeLogger(options.debug ?? false, "[hobots-manager]");
|
|
894
|
-
const
|
|
895
|
-
this.api = new ManagerApi({ baseUrl:
|
|
894
|
+
const config = resolveConfig(options, "[hobots-manager]");
|
|
895
|
+
this.api = new ManagerApi({ baseUrl: config.managerBaseUrl, key: config.key, logger: this.logger });
|
|
896
896
|
this.pollIntervalMs = Math.max(MIN_POLL_INTERVAL_MS, options.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS);
|
|
897
897
|
this.concurrency = Math.min(MAX_CONCURRENCY, Math.max(1, options.concurrency ?? 1));
|
|
898
898
|
this.instanceId = options.instanceId;
|
|
899
899
|
this.taskTimeoutMs = options.taskTimeoutMs;
|
|
900
900
|
this.logFlushIntervalMs = options.logFlushIntervalMs;
|
|
901
|
-
this.logger.debug("agente configurado", { baseUrl:
|
|
901
|
+
this.logger.debug("agente configurado", { baseUrl: config.managerBaseUrl });
|
|
902
902
|
}
|
|
903
903
|
logger;
|
|
904
904
|
api;
|
|
@@ -995,7 +995,7 @@ var ManagerAgent = class {
|
|
|
995
995
|
if (error instanceof ManagerApiError && error.status === 401) {
|
|
996
996
|
this.consecutiveAuthFailures++;
|
|
997
997
|
if (this.consecutiveAuthFailures === 1 || this.consecutiveAuthFailures % 10 === 0) {
|
|
998
|
-
this.logger.error("chave rejeitada (401) \u2014 verifique
|
|
998
|
+
this.logger.error("chave rejeitada (401) \u2014 verifique o Client Secret do projeto em Configura\xE7\xF5es \u2192 Projetos");
|
|
999
999
|
}
|
|
1000
1000
|
return Math.max(this.pollIntervalMs, AUTH_FAILURE_INTERVAL_MS);
|
|
1001
1001
|
}
|
|
@@ -1109,11 +1109,11 @@ function init(options) {
|
|
|
1109
1109
|
if (options.manager) {
|
|
1110
1110
|
const managerOptions = options.manager === true ? {} : options.manager;
|
|
1111
1111
|
agent = new ManagerAgent(
|
|
1112
|
-
{ ...managerOptions,
|
|
1112
|
+
{ ...managerOptions, clientSecret: options.clientSecret, instanceId: options.instanceId, debug: options.debug },
|
|
1113
1113
|
registry
|
|
1114
1114
|
);
|
|
1115
1115
|
}
|
|
1116
|
-
client.logger.debug("inicializado", { endpoint: client.
|
|
1116
|
+
client.logger.debug("inicializado", { endpoint: client.config.ingestEndpoint });
|
|
1117
1117
|
}
|
|
1118
1118
|
function getClient() {
|
|
1119
1119
|
return client;
|