hobots 1.0.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 CHANGED
@@ -3,9 +3,9 @@
3
3
  SDK JavaScript/TypeScript da **Hobots** para instrumentar funcionários digitais (RPAs) e integrações.
4
4
 
5
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, logs e resultado.
6
+ - **Manager** — execução **sob demanda**: o agente faz polling no app da Hobots, executa handlers registrados e reporta status e logs.
7
7
 
8
- 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.
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
9
 
10
10
  ---
11
11
 
@@ -17,63 +17,72 @@ npm install hobots
17
17
  ```
18
18
 
19
19
  ```js
20
- import * as Monitor from 'hobots'; // capability Monitor (import raiz)
21
- import * as Manager from 'hobots/manager'; // capability Manager
20
+ import * as Hobots from 'hobots'; // um import só — Monitor e Manager
22
21
  ```
23
22
 
24
- Também funciona em CommonJS: `const Monitor = require('hobots')`.
23
+ Também funciona em CommonJS: `const Hobots = require('hobots')`.
25
24
 
26
25
  ---
27
26
 
28
- ## As duas capabilities
27
+ ## Um SDK, duas capabilities, um `init()`
29
28
 
30
- O SDK expõe **duas capabilities independentes** — credenciais, entry points e ciclos de vida separados — que podem conviver no mesmo processo.
29
+ O SDK expõe **duas capabilities** autenticadas pelo **mesmo Client Secret do projeto**, configuradas em um único `init()`:
31
30
 
32
- | Capability | Import | Para quê | Ciclo de vida |
31
+ | Capability | Como habilita | Para quê | Ciclo de vida |
33
32
  | --- | --- | --- | --- |
34
- | **Monitor** | `hobots` | Telemetria emitida pelo próprio programa: erros, transactions/spans, crons, heartbeat. | Timers `unref`'d — **não** segura o processo. Chame `close()` no fim. |
35
- | **Manager** | `hobots/manager` | Execução remota sob demanda via polling. | `start()` **segura o processo vivo** até `stop()`. |
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()`. |
36
35
 
37
36
  Você usa **uma, outra ou as duas**:
38
37
 
39
- - Só saber se o robô quebrou, quanto demora e se está vivo? → **Monitor**.
40
- - Disparar o robô sob demanda a partir de um formulário no app? → **Manager**.
41
- - Ambos? Inicialize os dois no mesmo processo, com credenciais separadas.
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
+ - 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
+ clientSecret: 'hb_<64 hex>',
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
+ ```
42
57
 
43
58
  ---
44
59
 
45
- ## O DSN
60
+ ## O Client Secret
46
61
 
47
- Toda credencial do SDK é um **DSN** no formato `<protocolo>://<key>@<host>[:porta]/<projeto>`. A `key` vai embutida na URL e o `host` aponta para o app da Hobots. Copie o DSN pronto na página do projeto no app.
62
+ Cada projeto tem **um único Client Secret** — a mesma credencial autentica o Monitor **e** o Manager:
48
63
 
49
64
  ```
50
- Monitor: https://<publicKey>@<host>/<projectId> ← public key (ingestão), na URL
51
- Manager: https://<managerKey>@<host>/<projectSlug> ← manager key (secreta), via Bearer
65
+ hb_<64 hex>
52
66
  ```
53
67
 
54
- - **Monitor** usa a **public key** (chave de ingestão) e o `projectId`. É a chave do snippet de integração em `/monitor`.
55
- - **Manager** usa a **manager key** (chave secreta do agente, criada em `/manager/agents`) e o `projectSlug`. **Não** é a chave de ingestão; nunca vai na URL da requisição, só no header `Authorization: Bearer`.
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`).
56
69
 
57
70
  ---
58
71
 
59
72
  ## Monitor
60
73
 
61
- ```js
62
- import * as Monitor from 'hobots';
63
- ```
64
-
65
- Todas as funções abaixo são **no-op seguras** se `Monitor.init()` não foi chamado (com aviso no console).
74
+ Todas as funções abaixo são **no-op seguras** se `Hobots.init()` não foi chamado (com aviso no console).
66
75
 
67
76
  ### `init(options)`
68
77
 
69
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.
70
79
 
71
80
  ```js
72
- Monitor.init({
73
- dsn: 'https://<publicKey>@<host>/<projectId>',
81
+ Hobots.init({
82
+ clientSecret: 'hb_<64 hex>',
74
83
  environment: 'production',
75
84
  release: 'robo-nfe@1.4.2',
76
- serverName: 'vm-cliente-01',
85
+ instanceId: 'vm-cliente-01',
77
86
  tags: { squad: 'automacoes' },
78
87
  heartbeat: true, // "estou vivo" a cada 30s
79
88
  });
@@ -81,16 +90,17 @@ Monitor.init({
81
90
 
82
91
  | Opção | Tipo | Default | Descrição |
83
92
  | --- | --- | --- | --- |
84
- | `dsn` | `string` | **obrigatório** | `https://<publicKey>@host/<projectId>` |
93
+ | `clientSecret` | `string` | **obrigatório** | o Client Secret do projeto (`hb_<64 hex>`), copiado em **Configurações → Projetos** |
85
94
  | `environment` | `string` | `'production'` | ambiente lógico |
86
95
  | `release` | `string` | — | versão do programa, ex. `robo-nfe@1.4.2` |
87
- | `serverName` | `string` | hostname | identifica a máquina; também vira `instanceId` do heartbeat |
96
+ | `instanceId` | `string` | **obrigatório** | identidade única da instância — heartbeat do Monitor e agente do Manager convergem nela |
88
97
  | `tags` | `Record<string,string>` | — | tags aplicadas a todos os eventos |
89
98
  | `sampleRate` | `number` | `1` | amostragem de erros (0..1) |
90
99
  | `tracesSampleRate` | `number` | `1` | amostragem de transactions (0..1) |
91
100
  | `maxBreadcrumbs` | `number` | `100` | tamanho do buffer de breadcrumbs |
92
101
  | `captureUnhandled` | `boolean` | `true` | handlers globais de erro (`uncaughtException`/`unhandledRejection`) |
93
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) |
94
104
  | `beforeSend` | `(event) => event \| null` | — | edita/descarta evento (retorne `null` para descartar) |
95
105
  | `debug` | `boolean` | `false` | loga atividade do SDK |
96
106
  | `flushIntervalMs` | `number` | `2000` | intervalo do flush automático do transport |
@@ -102,7 +112,7 @@ Monitor.init({
102
112
  try {
103
113
  await processarNota(nota);
104
114
  } catch (error) {
105
- Monitor.captureException(error, {
115
+ Hobots.captureException(error, {
106
116
  level: 'error',
107
117
  tags: { cliente: 'acme' },
108
118
  fingerprint: ['sefaz-timeout'], // agrupa manualmente; sem isso o servidor agrupa pelo stack
@@ -110,7 +120,7 @@ try {
110
120
  throw error;
111
121
  }
112
122
 
113
- Monitor.captureMessage('Lote processado com sucesso', 'info');
123
+ Hobots.captureMessage('Lote processado com sucesso', 'info');
114
124
  ```
115
125
 
116
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`.
@@ -122,7 +132,7 @@ Ambas retornam o `event_id` (ou `undefined` se não inicializado). O hint aceita
122
132
  Trilha do que aconteceu antes do erro; enviada junto do próximo evento (buffer limitado por `maxBreadcrumbs`, mais antigos descartados).
123
133
 
124
134
  ```js
125
- Monitor.addBreadcrumb({ category: 'nfe', message: 'Baixou XML da nota 123', level: 'info' });
135
+ Hobots.addBreadcrumb({ category: 'nfe', message: 'Baixou XML da nota 123', level: 'info' });
126
136
  ```
127
137
 
128
138
  ### Escopo: tags, usuário, contexto, extras
@@ -130,26 +140,26 @@ Monitor.addBreadcrumb({ category: 'nfe', message: 'Baixou XML da nota 123', leve
130
140
  Dados anexados a **todos** os eventos seguintes:
131
141
 
132
142
  ```js
133
- Monitor.setTag('regiao', 'nordeste');
134
- Monitor.setTags({ squad: 'automacoes', cliente: 'acme' });
135
- Monitor.setUser({ id: 'op-42', email: 'op@acme.com' });
136
- Monitor.setContext('vm', { cpu: 4, ram: '8GB' });
137
- Monitor.setExtra('ultimoLote', 128);
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);
138
148
  ```
139
149
 
140
150
  Para um escopo **isolado** (sem vazar para o global), use `withScope`:
141
151
 
142
152
  ```js
143
- Monitor.withScope((scope) => {
153
+ Hobots.withScope((scope) => {
144
154
  scope.setTag('lote', '128').setFingerprint(['reprocessamento']);
145
- Monitor.captureMessage('Reprocessando lote 128');
155
+ Hobots.captureMessage('Reprocessando lote 128');
146
156
  });
147
157
  ```
148
158
 
149
159
  ### Performance: transactions e spans
150
160
 
151
161
  ```js
152
- const tx = Monitor.startTransaction('processar-lote', 'rpa.job');
162
+ const tx = Hobots.startTransaction('processar-lote', 'rpa.job');
153
163
 
154
164
  const span = tx.startChild('http.client', 'GET /api/notas');
155
165
  await api.buscarNotas();
@@ -172,7 +182,7 @@ tx.finish(); // só aqui a transaction é enviada (respeitando tracesSam
172
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:
173
183
 
174
184
  ```js
175
- await Monitor.withMonitor(
185
+ await Hobots.withMonitor(
176
186
  'sync-notas',
177
187
  () => executarSync(),
178
188
  { schedule: '0 */2 * * *', timezone: 'America/Fortaleza' }
@@ -182,9 +192,9 @@ await Monitor.withMonitor(
182
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:
183
193
 
184
194
  ```js
185
- const id = Monitor.checkIn({ monitorSlug: 'sync-notas', status: 'in_progress' });
195
+ const id = Hobots.checkIn({ monitorSlug: 'sync-notas', status: 'in_progress' });
186
196
  // … trabalho …
187
- Monitor.checkIn({ monitorSlug: 'sync-notas', status: 'ok', checkInId: id, durationMs: 1234 });
197
+ Hobots.checkIn({ monitorSlug: 'sync-notas', status: 'ok', checkInId: id, durationMs: 1234 });
188
198
  ```
189
199
 
190
200
  ### Heartbeat (uptime)
@@ -192,19 +202,19 @@ Monitor.checkIn({ monitorSlug: 'sync-notas', status: 'ok', checkInId: id, durati
192
202
  Bate "estou vivo" periodicamente; o servidor acusa o robô **offline** quando os batimentos param.
193
203
 
194
204
  ```js
195
- Monitor.init({
196
- dsn,
205
+ Hobots.init({
206
+ clientSecret,
197
207
  heartbeat: { intervalMs: 30_000, name: 'Robô NFe — VM 01' },
198
208
  });
199
209
  ```
200
210
 
201
- `heartbeat: true` usa os defaults. Campos: `intervalMs` (30000), `instanceId` (default `serverName`/`HOSTNAME`/id aleatório), `name`, `metadata`.
211
+ `heartbeat: true` usa os defaults. A identidade é o `instanceId` do `init()`. Campos: `intervalMs` (30000), `name` (default: o `instanceId`), `metadata`.
202
212
 
203
213
  ### Flush e close
204
214
 
205
215
  ```js
206
- await Monitor.flush(2000); // envia o buffer, mantém o SDK vivo
207
- await Monitor.close(2000); // flush final + para o heartbeat + fecha o transport
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
208
218
  ```
209
219
 
210
220
  Chame `close` antes do processo sair. Os timers do Monitor são `unref`'d — ele **não** segura o processo vivo sozinho.
@@ -213,50 +223,50 @@ Chame `close` antes do processo sair. Os timers do Monitor são `unref`'d — el
213
223
 
214
224
  ## Manager
215
225
 
216
- ```js
217
- import * as Manager from 'hobots/manager';
218
- ```
219
-
220
- Capability de **execução remota sob demanda**. O agente faz polling no app, executa os handlers registrados quando aparece trabalho e reporta status, logs incrementais e resultado. Credencial própria (**manager key**), singletons próprios, nenhum handler global instalado.
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.
221
227
 
222
228
  ### Ciclo de vida
223
229
 
224
230
  ```js
225
- Manager.init({ dsn: 'https://<managerKey>@<host>/<projectSlug>', agentName: 'VM Cliente 01' });
231
+ Hobots.init({
232
+ clientSecret: 'hb_<64 hex>',
233
+ instanceId: 'vm-cliente-01',
234
+ manager: true, // ou { pollIntervalMs, concurrency, ... }
235
+ });
226
236
 
227
- Manager.register('processar-nfe', async (params, ctx) => {
237
+ Hobots.register('processar-nfe', async (params, ctx) => {
228
238
  ctx.log('info', `processando lote ${params.lote}…`);
229
239
  if (ctx.signal.aborted) return; // cancelamento cooperativo
230
- return { processadas: 12 }; // vira o resultado da execução no app
240
+ ctx.log('info', '12 notas processadas');
231
241
  });
232
242
 
233
- Manager.start(); // começa o polling e MANTÉM O PROCESSO VIVO
243
+ Hobots.start(); // começa o polling e MANTÉM O PROCESSO VIVO
234
244
 
235
245
  process.on('SIGINT', () => {
236
- void Manager.stop(15_000).then(() => process.exit(0));
246
+ void Hobots.close(15_000).then(() => process.exit(0));
237
247
  });
238
248
  ```
239
249
 
240
- - `init(options)` — cria o agente (singleton). Chamar de novo para o anterior e substitui.
241
- - `register(task, handler)` — `task` é o `task_slug` configurado no formulário do app. Registre **antes** de `start()`.
242
- - `start()` — começa o polling. Lança se `init()` não foi chamado ou se nenhuma task foi registrada.
243
- - `stop(timeoutMs?)` — para o polling e aguarda as runs ativas (default 30s). Retorna `false` se estourou o timeout.
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.
244
255
 
245
- | Opção (`ManagerInitOptions`) | Tipo | Default | Descrição |
256
+ | Opção (`ManagerOptions`) | Tipo | Default | Descrição |
246
257
  | --- | --- | --- | --- |
247
- | `dsn` | `string` | **obrigatório** | com a **manager key** (não a chave de ingestão) |
248
258
  | `pollIntervalMs` | `number` | `5000` | intervalo entre polls sem trabalho (mínimo `1000`) |
249
259
  | `concurrency` | `number` | `1` | runs simultâneas (clamp 1..5) |
250
- | `agentName` | `string` | hostname | nome exibido no dashboard |
251
260
  | `taskTimeoutMs` | `number` | — | timeout client-side por run (não mata o handler; servidor é o backstop) |
252
261
  | `logFlushIntervalMs` | `number` | `2000` | intervalo do envio incremental de logs |
253
- | `debug` | `boolean` | `false` | loga atividade do agente |
262
+
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.
254
264
 
255
265
  ### O handler e o `RunContext`
256
266
 
257
267
  ```ts
258
- type ManagerTaskHandler<P = Record<string, unknown>, R = unknown> =
259
- (params: P, ctx: RunContext) => R | Promise<R>;
268
+ type ManagerTaskHandler<P = Record<string, unknown>> =
269
+ (params: P, ctx: RunContext) => void | Promise<void>;
260
270
 
261
271
  interface RunContext {
262
272
  runId: string;
@@ -266,22 +276,24 @@ interface RunContext {
266
276
  }
267
277
  ```
268
278
 
269
- - **`params`** — os dados do formulário configurado no app (JSON validado). Tipável: `Manager.register<{ lote: number }, { processadas: number }>(...)`.
279
+ - **`params`** — os dados do formulário configurado no app (JSON validado). Tipável: `Hobots.register<{ lote: number }>(...)`.
270
280
  - **`ctx.log(level, message)`** — logs enviados **incrementalmente** ao app (PATCHes com throttle), visíveis na run quase em tempo real.
271
281
  - **`ctx.signal`** — `AbortSignal` que dispara quando a run é **cancelada no app**, em **timeout** ou no **shutdown**.
272
- - **Retorno** — vira o resultado exibido no app (JSON, cap ~100KB; maiores/circulares são descartados com marcador `__truncated`).
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).
273
283
  - **Erro lançado** — a run é reportada como `failed` (mensagem cap 10k, stack 20k).
274
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
+
275
287
  ### Cancelamento cooperativo
276
288
 
277
289
  Uma run cancelada no app **não mata** o handler — o SDK apenas dispara `ctx.signal`. **Verifique `ctx.signal.aborted`** em loops longos:
278
290
 
279
291
  ```js
280
- Manager.register('processar-nfe', async (params, ctx) => {
292
+ Hobots.register('processar-nfe', async (params, ctx) => {
281
293
  for (const nota of params.notas) {
282
294
  if (ctx.signal.aborted) {
283
295
  ctx.log('warning', 'cancelamento detectado — parando');
284
- return { canceladas: true };
296
+ return;
285
297
  }
286
298
  await processar(nota);
287
299
  }
@@ -298,34 +310,66 @@ Manager.register('processar-nfe', async (params, ctx) => {
298
310
 
299
311
  ### Idempotência (at-least-once)
300
312
 
301
- A entrega é **at-least-once**: se o agente morre logo após capturar uma run (antes de reportar o resultado), ela é re-entregue quando o agente voltar. Escreva handlers **idempotentes** (use uma chave de deduplicação sua, como o número da nota).
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).
302
314
 
303
315
  ---
304
316
 
305
317
  ## Encerramento gracioso
306
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
+
307
321
  ```js
308
- // Monitor: não segura o processo, mas faça o flush final para não perder eventos
309
- await Monitor.close(2000);
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);
310
324
 
311
- // Manager: segura o processo por design — aguarde a run atual
325
+ // com Manager: segura o processo por design — aguarde a run atual
312
326
  process.on('SIGINT', () => {
313
- void Manager.stop(15_000).then(() => process.exit(0));
327
+ void Hobots.close(15_000).then(() => process.exit(0));
314
328
  });
315
329
  ```
316
330
 
331
+ Para parar de aceitar execuções **sem** derrubar a telemetria, use `stop(timeoutMs?)`.
332
+
317
333
  ---
318
334
 
319
335
  ## Entry points / exports
320
336
 
321
337
  | Import | Conteúdo |
322
338
  | --- | --- |
323
- | `hobots` | Monitor: funções, `Client`, `Scope`, `Transaction`, `Span`, `parseDsn`, tipos. |
324
- | `hobots/protocol` | Tipos do wire format do Monitor. |
325
- | `hobots/manager` | Manager: `init`/`register`/`start`/`stop`, `ManagerAgent`, `ManagerApi`, `ManagerApiError`, `parseManagerDsn`, tipos. |
326
- | `hobots/manager/protocol` | Tipos do wire format do Manager. |
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({ clientSecret, 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
+ ```
327
368
 
328
- Empacotado em **ESM e CommonJS** com **definições de tipos** (`.d.ts`) para todas as entradas.
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**.
370
+ - `agentName` e `serverName` não existem mais — a identidade do agente é o `instanceId` (obrigatório, sem fallback).
371
+ - As opções do Manager (`pollIntervalMs`, `concurrency`, `taskTimeoutMs`, `logFlushIntervalMs`) vão no campo `manager` do `init()`; `clientSecret` e `debug` não se repetem.
372
+ - Tipos (`ManagerTaskHandler`, `RunContext`, `ManagerOptions`) e classes (`ManagerAgent`, `ManagerApi`) agora vêm de `hobots`; o wire format vem de `hobots/protocol`.
329
373
 
330
374
  ---
331
375
 
@@ -333,11 +377,11 @@ Empacotado em **ESM e CommonJS** com **definições de tipos** (`.d.ts`) para to
333
377
 
334
378
  Guias detalhados acompanham o pacote em [`docs/`](./docs/README.md):
335
379
 
336
- - [Getting started](./docs/getting-started.md) — instalação, DSN, primeiro `init`, Monitor vs Manager.
380
+ - [Getting started](./docs/getting-started.md) — instalação, Client Secret, primeiro `init`, Monitor vs Hobots.
337
381
  - [Monitor](./docs/monitor.md) — erros, breadcrumbs, escopo, transactions/spans, crons, heartbeat.
338
382
  - [Manager](./docs/manager.md) — handlers, `RunContext`, cancelamento, concorrência, idempotência.
339
383
  - [Referência de API](./docs/api-reference.md) — todas as funções e tabelas de opções com defaults.
340
- - [Protocolo & transporte](./docs/protocol.md) — DSNs, endpoints, envelope, retries.
384
+ - [Protocolo & transporte](./docs/protocol.md) — o Client Secret, endpoints, envelope, retries.
341
385
 
342
386
  ---
343
387