hobots 0.3.1 → 1.1.0

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.
Files changed (102) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +389 -0
  3. package/dist/index.cjs +1203 -0
  4. package/dist/index.cjs.map +1 -0
  5. package/dist/index.d.cts +312 -0
  6. package/dist/index.d.ts +312 -0
  7. package/dist/index.js +1180 -0
  8. package/dist/index.js.map +1 -0
  9. package/dist/manager/protocol.cjs +19 -0
  10. package/dist/manager/protocol.cjs.map +1 -0
  11. package/dist/manager/protocol.d.cts +72 -0
  12. package/dist/manager/protocol.d.ts +72 -0
  13. package/dist/manager/protocol.js +1 -0
  14. package/dist/manager/protocol.js.map +1 -0
  15. package/dist/protocol.cjs +19 -0
  16. package/dist/protocol.cjs.map +1 -0
  17. package/dist/protocol.d.cts +129 -0
  18. package/dist/protocol.d.ts +129 -0
  19. package/dist/protocol.js +1 -0
  20. package/dist/protocol.js.map +1 -0
  21. package/docs/README.md +41 -0
  22. package/docs/api-reference.md +153 -0
  23. package/docs/getting-started.md +103 -0
  24. package/docs/manager.md +95 -0
  25. package/docs/monitor.md +138 -0
  26. package/docs/protocol.md +101 -0
  27. package/package.json +46 -3
  28. package/auth/index.d.ts +0 -10
  29. package/csv/index.d.ts +0 -9
  30. package/datasets/index.d.ts +0 -2
  31. package/db/drizzle.config.d.ts +0 -8
  32. package/db/index.d.ts +0 -9
  33. package/db/migrate.d.ts +0 -3
  34. package/db/schema.d.ts +0 -215
  35. package/db/storages/base.d.ts +0 -23
  36. package/db/storages/index.d.ts +0 -3
  37. package/db/storages/job.d.ts +0 -233
  38. package/exceptions/break.d.ts +0 -6
  39. package/exceptions/ignore.d.ts +0 -6
  40. package/exceptions/index.d.ts +0 -4
  41. package/exceptions/warning.d.ts +0 -6
  42. package/foreach/foreach.d.ts +0 -7
  43. package/foreach/index.d.ts +0 -5
  44. package/foreach/item.d.ts +0 -13
  45. package/hobots/samples/bot.d.ts +0 -2
  46. package/hobots/samples/index.d.ts +0 -2
  47. package/hobots/src/auth/index.d.ts +0 -10
  48. package/hobots/src/csv/index.d.ts +0 -9
  49. package/hobots/src/datasets/index.d.ts +0 -2
  50. package/hobots/src/db/drizzle.config.d.ts +0 -8
  51. package/hobots/src/db/index.d.ts +0 -9
  52. package/hobots/src/db/migrate.d.ts +0 -3
  53. package/hobots/src/db/schema.d.ts +0 -215
  54. package/hobots/src/db/storages/base.d.ts +0 -23
  55. package/hobots/src/db/storages/index.d.ts +0 -3
  56. package/hobots/src/db/storages/job.d.ts +0 -233
  57. package/hobots/src/exceptions/break.d.ts +0 -6
  58. package/hobots/src/exceptions/ignore.d.ts +0 -6
  59. package/hobots/src/exceptions/index.d.ts +0 -4
  60. package/hobots/src/exceptions/warning.d.ts +0 -6
  61. package/hobots/src/foreach/foreach.d.ts +0 -7
  62. package/hobots/src/foreach/index.d.ts +0 -5
  63. package/hobots/src/foreach/item.d.ts +0 -13
  64. package/hobots/src/index.d.ts +0 -9
  65. package/hobots/src/reports/data-report.d.ts +0 -9
  66. package/hobots/src/reports/index.d.ts +0 -3
  67. package/hobots/src/reports/job-report.d.ts +0 -22
  68. package/hobots/src/setup.d.ts +0 -20
  69. package/hobots/src/sheets/index.d.ts +0 -13
  70. package/hobots/src/types/hobots-types.d.ts +0 -20
  71. package/hobots/src/utils/date.d.ts +0 -117
  72. package/hobots/src/utils/dist.d.ts +0 -8
  73. package/hobots/src/utils/garbage.d.ts +0 -2
  74. package/hobots/src/utils/index.d.ts +0 -10
  75. package/hobots/src/utils/logger.d.ts +0 -21
  76. package/hobots/src/utils/manifest.d.ts +0 -2
  77. package/hobots/src/utils/path.d.ts +0 -13
  78. package/hobots/src/utils/publish.d.ts +0 -2
  79. package/hobots/src/utils/retry.d.ts +0 -5
  80. package/hobots/src/utils/text.d.ts +0 -74
  81. package/hobots/src/utils/timer.d.ts +0 -3
  82. package/index.d.ts +0 -9
  83. package/index.js +0 -131866
  84. package/index.js.map +0 -1
  85. package/reports/data-report.d.ts +0 -9
  86. package/reports/index.d.ts +0 -3
  87. package/reports/job-report.d.ts +0 -22
  88. package/setup.d.ts +0 -20
  89. package/sheets/index.d.ts +0 -13
  90. package/types/hobots-types.d.ts +0 -20
  91. package/utils/date.d.ts +0 -117
  92. package/utils/dist.d.ts +0 -8
  93. package/utils/garbage.d.ts +0 -2
  94. package/utils/index.d.ts +0 -10
  95. package/utils/logger.d.ts +0 -21
  96. package/utils/manifest.d.ts +0 -2
  97. package/utils/path.d.ts +0 -13
  98. package/utils/publish.d.ts +0 -2
  99. package/utils/retry.d.ts +0 -5
  100. package/utils/src/path.d.ts +0 -14
  101. package/utils/text.d.ts +0 -74
  102. package/utils/timer.d.ts +0 -3
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Hobots
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,389 @@
1
+ # hobots
2
+
3
+ SDK JavaScript/TypeScript da **Hobots** para instrumentar funcionários digitais (RPAs) e integrações.
4
+
5
+ - **Monitor** — telemetria que o programa **emite** sozinho: erros com stack trace, performance (transactions/spans), check-ins de cron e heartbeats de uptime.
6
+ - **Manager** — execução **sob demanda**: o agente faz polling no app da Hobots, executa handlers registrados e reporta status e logs.
7
+
8
+ **Um único import e um único `init()`** cobrem as duas capabilities. Cliente HTTP puro, **sem dependências de runtime**. Requer **Node 18+** (usa o `fetch` global); o Monitor também roda no browser para captura de erros.
9
+
10
+ ---
11
+
12
+ ## Instalação
13
+
14
+ ```bash
15
+ npm install hobots
16
+ # ou: pnpm add hobots · yarn add hobots
17
+ ```
18
+
19
+ ```js
20
+ import * as Hobots from 'hobots'; // um import só — Monitor e Manager
21
+ ```
22
+
23
+ Também funciona em CommonJS: `const Hobots = require('hobots')`.
24
+
25
+ ---
26
+
27
+ ## Um SDK, duas capabilities, um `init()`
28
+
29
+ O SDK expõe **duas capabilities** autenticadas pela **mesma DSN única do projeto**, configuradas em um único `init()`:
30
+
31
+ | Capability | Como habilita | Para quê | Ciclo de vida |
32
+ | --- | --- | --- | --- |
33
+ | **Monitor** | sempre ativo no `init()` | Telemetria emitida pelo próprio programa: erros, transactions/spans, crons, heartbeat. | Timers `unref`'d — **não** segura o processo. Chame `close()` no fim. |
34
+ | **Manager** | `manager: true` (ou opções) no `init()` | Execução remota sob demanda via polling. | `start()` **segura o processo vivo** até `stop()`/`close()`. |
35
+
36
+ Você usa **uma, outra ou as duas**:
37
+
38
+ - Só saber se o robô quebrou, quanto demora e se está vivo? → `init({ dsn, heartbeat: true })`.
39
+ - Disparar o robô sob demanda a partir de um formulário no app? → `init({ dsn, manager: true })` + `register()` + `start()`.
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
+
42
+ ```js
43
+ Hobots.init({
44
+ dsn: 'https://<secretKey>@<host>/<projectSlug>',
45
+ instanceId: 'vm-cliente-01',
46
+ heartbeat: true, // Monitor: "estou vivo" a cada 30s
47
+ manager: { pollIntervalMs: 5_000 }, // Manager: execução sob demanda
48
+ });
49
+
50
+ Hobots.register('processar-nfe', async (params, ctx) => {
51
+ ctx.log('info', 'começando…');
52
+ return { processadas: 12 };
53
+ });
54
+
55
+ Hobots.start(); // inicia o polling do Manager (segura o processo vivo)
56
+ ```
57
+
58
+ ---
59
+
60
+ ## O DSN
61
+
62
+ Cada projeto tem **uma única DSN** — a mesma credencial autentica o Monitor **e** o Manager:
63
+
64
+ ```
65
+ https://<secretKey>@<host>/<projectSlug>
66
+ ```
67
+
68
+ A `secretKey` (64 hex) é **secreta**: vai embutida na DSN só por conveniência — nas requisições viaja sempre no header `Authorization: Bearer`, nunca na URL. O `projectSlug` do path é informativo; a identidade do projeto vem da chave. Copie a DSN pronta no app, em **Configurações → Agentes** — os snippets de integração já vêm prontos.
69
+
70
+ ---
71
+
72
+ ## Monitor
73
+
74
+ Todas as funções abaixo são **no-op seguras** se `Hobots.init()` não foi chamado (com aviso no console).
75
+
76
+ ### `init(options)`
77
+
78
+ Inicialize **uma vez**, o mais cedo possível no processo. Cria o cliente, instala handlers globais de erro (a menos que `captureUnhandled: false`) e inicia o heartbeat se configurado.
79
+
80
+ ```js
81
+ Hobots.init({
82
+ dsn: 'https://<secretKey>@<host>/<projectSlug>',
83
+ environment: 'production',
84
+ release: 'robo-nfe@1.4.2',
85
+ instanceId: 'vm-cliente-01',
86
+ tags: { squad: 'automacoes' },
87
+ heartbeat: true, // "estou vivo" a cada 30s
88
+ });
89
+ ```
90
+
91
+ | Opção | Tipo | Default | Descrição |
92
+ | --- | --- | --- | --- |
93
+ | `dsn` | `string` | **obrigatório** | a DSN única do projeto: `https://<secretKey>@host/<projectSlug>` |
94
+ | `environment` | `string` | `'production'` | ambiente lógico |
95
+ | `release` | `string` | — | versão do programa, ex. `robo-nfe@1.4.2` |
96
+ | `instanceId` | `string` | **obrigatório** | identidade única da instância — heartbeat do Monitor e agente do Manager convergem nela |
97
+ | `tags` | `Record<string,string>` | — | tags aplicadas a todos os eventos |
98
+ | `sampleRate` | `number` | `1` | amostragem de erros (0..1) |
99
+ | `tracesSampleRate` | `number` | `1` | amostragem de transactions (0..1) |
100
+ | `maxBreadcrumbs` | `number` | `100` | tamanho do buffer de breadcrumbs |
101
+ | `captureUnhandled` | `boolean` | `true` | handlers globais de erro (`uncaughtException`/`unhandledRejection`) |
102
+ | `heartbeat` | `boolean \| HeartbeatOptions` | `false` | heartbeat periódico (`true` usa defaults) |
103
+ | `manager` | `boolean \| ManagerOptions` | `false` | habilita o agente Manager (`true` usa defaults) — veja [Manager](#manager) |
104
+ | `beforeSend` | `(event) => event \| null` | — | edita/descarta evento (retorne `null` para descartar) |
105
+ | `debug` | `boolean` | `false` | loga atividade do SDK |
106
+ | `flushIntervalMs` | `number` | `2000` | intervalo do flush automático do transport |
107
+ | `maxBatchSize` | `number` | `10` | itens por envelope antes do flush imediato |
108
+
109
+ ### Captura de erros e mensagens
110
+
111
+ ```js
112
+ try {
113
+ await processarNota(nota);
114
+ } catch (error) {
115
+ Hobots.captureException(error, {
116
+ level: 'error',
117
+ tags: { cliente: 'acme' },
118
+ fingerprint: ['sefaz-timeout'], // agrupa manualmente; sem isso o servidor agrupa pelo stack
119
+ });
120
+ throw error;
121
+ }
122
+
123
+ Hobots.captureMessage('Lote processado com sucesso', 'info');
124
+ ```
125
+
126
+ Ambas retornam o `event_id` (ou `undefined` se não inicializado). O hint aceita `level`, `tags`, `extra` e `fingerprint`. Erros **não tratados** são capturados e flushados automaticamente antes do processo sair — desligue com `captureUnhandled: false`.
127
+
128
+ `Severity = 'fatal' | 'error' | 'warning' | 'info' | 'debug'`.
129
+
130
+ ### Breadcrumbs
131
+
132
+ Trilha do que aconteceu antes do erro; enviada junto do próximo evento (buffer limitado por `maxBreadcrumbs`, mais antigos descartados).
133
+
134
+ ```js
135
+ Hobots.addBreadcrumb({ category: 'nfe', message: 'Baixou XML da nota 123', level: 'info' });
136
+ ```
137
+
138
+ ### Escopo: tags, usuário, contexto, extras
139
+
140
+ Dados anexados a **todos** os eventos seguintes:
141
+
142
+ ```js
143
+ Hobots.setTag('regiao', 'nordeste');
144
+ Hobots.setTags({ squad: 'automacoes', cliente: 'acme' });
145
+ Hobots.setUser({ id: 'op-42', email: 'op@acme.com' });
146
+ Hobots.setContext('vm', { cpu: 4, ram: '8GB' });
147
+ Hobots.setExtra('ultimoLote', 128);
148
+ ```
149
+
150
+ Para um escopo **isolado** (sem vazar para o global), use `withScope`:
151
+
152
+ ```js
153
+ Hobots.withScope((scope) => {
154
+ scope.setTag('lote', '128').setFingerprint(['reprocessamento']);
155
+ Hobots.captureMessage('Reprocessando lote 128');
156
+ });
157
+ ```
158
+
159
+ ### Performance: transactions e spans
160
+
161
+ ```js
162
+ const tx = Hobots.startTransaction('processar-lote', 'rpa.job');
163
+
164
+ const span = tx.startChild('http.client', 'GET /api/notas');
165
+ await api.buscarNotas();
166
+ span.setData('notas', 42).finish();
167
+
168
+ const filho = span.startChild('db.query', 'INSERT INTO notas'); // spans aninham
169
+ await gravar();
170
+ filho.finish();
171
+
172
+ tx.setStatus('ok'); // ou 'error'
173
+ tx.finish(); // só aqui a transaction é enviada (respeitando tracesSampleRate)
174
+ ```
175
+
176
+ - `startChild(op?, description?)` existe em `Transaction` **e** `Span` (aninhamento arbitrário).
177
+ - Métodos encadeáveis: `setStatus`, `setData` (span), `setTag`/`setName` (transaction).
178
+ - `finish()` na transaction fecha os spans abertos e envia o payload; nada é enviado se ela não foi amostrada.
179
+
180
+ ### Crons (check-ins)
181
+
182
+ Monitora jobs agendados: check-in `in_progress` na entrada, `ok`/`error` na saída, com duração medida. O jeito recomendado é `withMonitor`, que faz o par e captura exceções:
183
+
184
+ ```js
185
+ await Hobots.withMonitor(
186
+ 'sync-notas',
187
+ () => executarSync(),
188
+ { schedule: '0 */2 * * *', timezone: 'America/Fortaleza' }
189
+ );
190
+ ```
191
+
192
+ O `schedule` (expressão cron) faz o servidor **criar/atualizar o monitor automaticamente** (upsert) e habilita a detecção de **execução perdida**. Para controle manual:
193
+
194
+ ```js
195
+ const id = Hobots.checkIn({ monitorSlug: 'sync-notas', status: 'in_progress' });
196
+ // … trabalho …
197
+ Hobots.checkIn({ monitorSlug: 'sync-notas', status: 'ok', checkInId: id, durationMs: 1234 });
198
+ ```
199
+
200
+ ### Heartbeat (uptime)
201
+
202
+ Bate "estou vivo" periodicamente; o servidor acusa o robô **offline** quando os batimentos param.
203
+
204
+ ```js
205
+ Hobots.init({
206
+ dsn,
207
+ heartbeat: { intervalMs: 30_000, name: 'Robô NFe — VM 01' },
208
+ });
209
+ ```
210
+
211
+ `heartbeat: true` usa os defaults. A identidade é o `instanceId` do `init()`. Campos: `intervalMs` (30000), `name` (default: o `instanceId`), `metadata`.
212
+
213
+ ### Flush e close
214
+
215
+ ```js
216
+ await Hobots.flush(2000); // envia o buffer, mantém o SDK vivo
217
+ await Hobots.close(2000); // flush final + para o heartbeat + fecha o transport
218
+ ```
219
+
220
+ Chame `close` antes do processo sair. Os timers do Monitor são `unref`'d — ele **não** segura o processo vivo sozinho.
221
+
222
+ ---
223
+
224
+ ## Manager
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. Mesma DSN, mesmo `debug` e o `instanceId` como identidade — nenhum handler global extra é instalado.
227
+
228
+ ### Ciclo de vida
229
+
230
+ ```js
231
+ Hobots.init({
232
+ dsn: 'https://<secretKey>@<host>/<projectSlug>',
233
+ instanceId: 'vm-cliente-01',
234
+ manager: true, // ou { pollIntervalMs, concurrency, ... }
235
+ });
236
+
237
+ Hobots.register('processar-nfe', async (params, ctx) => {
238
+ ctx.log('info', `processando lote ${params.lote}…`);
239
+ if (ctx.signal.aborted) return; // cancelamento cooperativo
240
+ ctx.log('info', '12 notas processadas');
241
+ });
242
+
243
+ Hobots.start(); // começa o polling e MANTÉM O PROCESSO VIVO
244
+
245
+ process.on('SIGINT', () => {
246
+ void Hobots.close(15_000).then(() => process.exit(0));
247
+ });
248
+ ```
249
+
250
+ - `init({ manager })` — cria o agente. Chamar `init()` de novo para o agente anterior e o substitui (o registry de handlers é preservado).
251
+ - `register(task, handler)` — `task` é o `task_slug` configurado no formulário do app. Registre **antes** de `start()`. Funciona até antes do `init()`; com o Manager desabilitado, avisa no console.
252
+ - `start()` — começa o polling. Lança se o `init()` não configurou `manager` ou se nenhuma task foi registrada.
253
+ - `stop(timeoutMs?)` — para **só o Manager**: encerra o polling e aguarda as runs ativas (default 30s); a telemetria continua. Retorna `false` se estourou o timeout.
254
+ - `close(timeoutMs?)` — encerra **tudo**: agente (aguardando runs em voo) → heartbeat → flush final do transport.
255
+
256
+ | Opção (`ManagerOptions`) | Tipo | Default | Descrição |
257
+ | --- | --- | --- | --- |
258
+ | `pollIntervalMs` | `number` | `5000` | intervalo entre polls sem trabalho (mínimo `1000`) |
259
+ | `concurrency` | `number` | `1` | runs simultâneas (clamp 1..5) |
260
+ | `taskTimeoutMs` | `number` | — | timeout client-side por run (não mata o handler; servidor é o backstop) |
261
+ | `logFlushIntervalMs` | `number` | `2000` | intervalo do envio incremental de logs |
262
+
263
+ A DSN, 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
+
265
+ ### O handler e o `RunContext`
266
+
267
+ ```ts
268
+ type ManagerTaskHandler<P = Record<string, unknown>> =
269
+ (params: P, ctx: RunContext) => void | Promise<void>;
270
+
271
+ interface RunContext {
272
+ runId: string;
273
+ task: string;
274
+ log(level: 'debug' | 'info' | 'warning' | 'error', message: string): void;
275
+ signal: AbortSignal;
276
+ }
277
+ ```
278
+
279
+ - **`params`** — os dados do formulário configurado no app (JSON validado). Tipável: `Hobots.register<{ lote: number }>(...)`.
280
+ - **`ctx.log(level, message)`** — logs enviados **incrementalmente** ao app (PATCHes com throttle), visíveis na run quase em tempo real.
281
+ - **`ctx.signal`** — `AbortSignal` que dispara quando a run é **cancelada no app**, em **timeout** ou no **shutdown**.
282
+ - **Retorno** — **ignorado**: o SDK não captura nem envia o valor retornado pelo handler (resultados podem conter dados sensíveis e não são coletados).
283
+ - **Erro lançado** — a run é reportada como `failed` (mensagem cap 10k, stack 20k).
284
+
285
+ > **Dados sensíveis:** `ctx.log()` e mensagens/stack de erros **são enviados ao servidor** e ficam visíveis no app. Não inclua senhas, tokens, dados pessoais ou qualquer informação sensível em logs e mensagens de erro.
286
+
287
+ ### Cancelamento cooperativo
288
+
289
+ Uma run cancelada no app **não mata** o handler — o SDK apenas dispara `ctx.signal`. **Verifique `ctx.signal.aborted`** em loops longos:
290
+
291
+ ```js
292
+ Hobots.register('processar-nfe', async (params, ctx) => {
293
+ for (const nota of params.notas) {
294
+ if (ctx.signal.aborted) {
295
+ ctx.log('warning', 'cancelamento detectado — parando');
296
+ return;
297
+ }
298
+ await processar(nota);
299
+ }
300
+ });
301
+ ```
302
+
303
+ ### Concorrência
304
+
305
+ `concurrency` (default 1, máx 5) controla quantas runs o agente executa em paralelo. Com 1, as runs são sequenciais. O agente só reivindica o que consegue rodar (`max = concurrency - runs ativas`) e entra em **drain mode**: re-pesquisa imediatamente enquanto vem trabalho; quando não vem, espera `pollIntervalMs`.
306
+
307
+ ### Timeout por run
308
+
309
+ `taskTimeoutMs` é **client-side**. No estouro o SDK **não mata** o handler — dispara `ctx.signal`, libera o slot e reporta a run como falha (`TaskTimeout`). Respeite o `signal` para parar de verdade. Sem ele, o backstop é o servidor.
310
+
311
+ ### Idempotência (at-least-once)
312
+
313
+ A entrega é **at-least-once**: se o agente morre logo após capturar uma run (antes de reportar a conclusão), ela é re-entregue quando o agente voltar. Escreva handlers **idempotentes** (use uma chave de deduplicação sua, como o número da nota).
314
+
315
+ ---
316
+
317
+ ## Encerramento gracioso
318
+
319
+ `close(timeoutMs?)` encerra tudo na ordem certa: para o Manager (aguardando a run atual), para o heartbeat e faz o flush final do transport.
320
+
321
+ ```js
322
+ // só Monitor: não segura o processo, mas faça o flush final para não perder eventos
323
+ await Hobots.close(2_000);
324
+
325
+ // com Manager: segura o processo por design — aguarde a run atual
326
+ process.on('SIGINT', () => {
327
+ void Hobots.close(15_000).then(() => process.exit(0));
328
+ });
329
+ ```
330
+
331
+ Para parar de aceitar execuções **sem** derrubar a telemetria, use `stop(timeoutMs?)`.
332
+
333
+ ---
334
+
335
+ ## Entry points / exports
336
+
337
+ | Import | Conteúdo |
338
+ | --- | --- |
339
+ | `hobots` | Tudo: `init`, Monitor (captura, transactions, crons, heartbeat), Manager (`register`/`start`/`stop`), `close`, classes e tipos. |
340
+ | `hobots/protocol` | Tipos do wire format (Monitor e Manager). |
341
+
342
+ Empacotado em **ESM e CommonJS** com **definições de tipos** (`.d.ts`) para todas as entradas. (`hobots/manager/protocol` segue existindo como alias transitório de tipos.)
343
+
344
+ ---
345
+
346
+ ## Migração 1.x → 2.x
347
+
348
+ A 2.0 unifica o Manager no import raiz — `hobots/manager` **foi removido**:
349
+
350
+ ```diff
351
+ -import * as Monitor from 'hobots';
352
+ -import * as Manager from 'hobots/manager';
353
+ +import * as Hobots from 'hobots';
354
+
355
+ -Monitor.init({ dsn, serverName: 'vm-01', heartbeat: true });
356
+ -Manager.init({ dsn, agentName: 'vm-01' });
357
+ +Hobots.init({ dsn, instanceId: 'vm-01', heartbeat: true, manager: true });
358
+
359
+ -Manager.register('minha-task', handler);
360
+ -Manager.start();
361
+ +Hobots.register('minha-task', handler);
362
+ +Hobots.start();
363
+
364
+ -await Manager.stop(15_000);
365
+ -await Monitor.close(3_000);
366
+ +await Hobots.close(15_000);
367
+ ```
368
+
369
+ - `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()`; `dsn` e `debug` não se repetem.
371
+ - Tipos (`ManagerTaskHandler`, `RunContext`, `ManagerOptions`) e classes (`ManagerAgent`, `ManagerApi`) agora vêm de `hobots`; o wire format vem de `hobots/protocol`.
372
+
373
+ ---
374
+
375
+ ## Documentação completa
376
+
377
+ Guias detalhados acompanham o pacote em [`docs/`](./docs/README.md):
378
+
379
+ - [Getting started](./docs/getting-started.md) — instalação, DSN, primeiro `init`, Monitor vs Hobots.
380
+ - [Monitor](./docs/monitor.md) — erros, breadcrumbs, escopo, transactions/spans, crons, heartbeat.
381
+ - [Manager](./docs/manager.md) — handlers, `RunContext`, cancelamento, concorrência, idempotência.
382
+ - [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) — a DSN única, endpoints, envelope, retries.
384
+
385
+ ---
386
+
387
+ ## Licença
388
+
389
+ [MIT](./LICENSE) © Hobots