hobots 3.3.0 → 3.4.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.
package/dist/index.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- import { RunLogLevel, RunAttachmentContentType, EventType, EnvironmentInput, MachineSnapshot, EventPayload, TransactionPayload, HeartbeatPayload, StepStatus, StepData, RunItemStatus, RunProgress } from './protocol.cjs';
1
+ import { RunAttachmentContentType, EventType, EnvironmentInput, MachineSnapshot, EventPayload, TransactionPayload, HeartbeatPayload, StepStatus, RunLogLevel, StepData, RunItemStatus, RunProgress } from './protocol.cjs';
2
2
  export { Breadcrumb, BreadcrumbLevel, Envelope, EnvelopeItem, Environment, EventUser, ExceptionData, InstanceInfo, ItemColumn, MachineProcess, PollRequest, PollResponse, RunAttachmentConfirmRequest, RunAttachmentConfirmResponse, RunAttachmentCreateRequest, RunAttachmentCreateResponse, RunCreateRequest, RunCreateResponse, RunDescriptor, RunError, RunItemInput, RunItemsCreateRequest, RunItemsCreateResponse, RunLogEntry, RunStatus, RunUpdateRequest, RunUpdateResponse, RunUpdateStatus, StackFrame, TaskItemsDeclaration } from './protocol.cjs';
3
3
 
4
4
  /** Espera entre tentativas: ms fixo ou função do número da tentativa que acabou de falhar (1-based). */
@@ -12,30 +12,29 @@ interface RetryOptions {
12
12
  shouldRetry?: (error: unknown) => boolean;
13
13
  }
14
14
 
15
- interface AttachOptions {
16
- /** Legenda curta, exibida sob a miniatura no app. Passa pelo scrub de segredos. */
15
+ /** Aceita tudo que o handler pode ter em mãos: bytes ou um caminho de arquivo (só Node). */
16
+ type AttachInput = Uint8Array | ArrayBuffer | string;
17
+ interface ImageOptions {
18
+ /** Legenda curta, exibida junto da imagem no app. Passa pelo scrub de segredos. */
17
19
  caption?: string;
18
- /** Nível da linha de log que carrega o anexo. Default: 'info' */
19
- level?: RunLogLevel;
20
- /** Texto da linha de log. Default: a legenda, ou 'captura de tela' */
21
- message?: string;
22
20
  /** Informe quando os magic bytes não bastarem (o SDK sempre prefere o que detectar). */
23
21
  contentType?: RunAttachmentContentType;
24
22
  }
25
- type AttachFailureReason =
26
- /** A instalação do Hobots não tem anexos habilitados (ou a API é anterior ao recurso) */
27
- 'unsupported' | 'too-large' | 'quota' | 'read-failed'
28
- /** Formato não reconhecido ou fora de PNG/JPEG/WEBP */
29
- | 'unsupported-format' | 'upload-failed' | 'canceled';
30
- interface AttachResult {
31
- /** Id do anexo, o mesmo referenciado na linha de log */
32
- id: string;
33
- ok: boolean;
34
- /** Motivo do insucesso — para diagnóstico; `attach` nunca lança */
35
- reason?: AttachFailureReason;
23
+ declare const IMAGE_BRAND: unique symbol;
24
+ /**
25
+ * Uma imagem pronta para ser pendurada num evento da run — o retorno de `hobots.image()`.
26
+ * É só um envelope (bytes/caminho + legenda); nenhum I/O acontece até o evento ser
27
+ * registrado por `hobots.log.*`, `hobots.items.*` ou `step.setStatus/setError`.
28
+ */
29
+ declare class ImageAttachment {
30
+ readonly input: AttachInput;
31
+ readonly caption?: string | undefined;
32
+ readonly contentType?: RunAttachmentContentType | undefined;
33
+ readonly [IMAGE_BRAND] = true;
34
+ constructor(input: AttachInput, caption?: string | undefined, contentType?: RunAttachmentContentType | undefined);
36
35
  }
37
- /** Aceita tudo que o handler pode ter em mãos: bytes ou um caminho de arquivo (só Node). */
38
- type AttachInput = Uint8Array | ArrayBuffer | string;
36
+ /** O que os métodos com imagem aceitam: bytes/caminho crus ou o envelope de `hobots.image()`. */
37
+ type ImageInput = AttachInput | ImageAttachment;
39
38
 
40
39
  interface Logger {
41
40
  debug: (...args: unknown[]) => void;
@@ -162,7 +161,7 @@ interface CaptureHint {
162
161
  * hobots.captureException(error, { attachment: { image: await page.screenshot(), caption: 'tela no momento do erro' } });
163
162
  * ```
164
163
  */
165
- attachment?: AttachInput | CaptureAttachment;
164
+ attachment?: ImageInput | CaptureAttachment;
166
165
  }
167
166
 
168
167
  interface ResolvedConfig {
@@ -245,6 +244,16 @@ declare class Client {
245
244
 
246
245
  /** Recebe os eventos de lifecycle da transaction para espelhá-los nos logs da run. */
247
246
  type LifecycleSink = (level: RunLogLevel, message: string) => void;
247
+ /**
248
+ * Recebe a imagem de uma step e dispara o upload pela run; devolve o id do anexo
249
+ * (já referenciável em `data.attachments`) ou undefined quando descartada.
250
+ */
251
+ type AttachmentSink = (image: ImageInput, ts: string) => string | undefined;
252
+ /** Opções dos desfechos de step que aceitam um print do estado da tela. */
253
+ interface StepOutcomeOptions {
254
+ /** Print da step (bytes/caminho ou `hobots.image(bytes, { caption })`) — botão de imagem no app. */
255
+ image?: ImageInput;
256
+ }
248
257
  declare class Step {
249
258
  private readonly transaction;
250
259
  readonly parentStepId: string;
@@ -259,13 +268,21 @@ declare class Step {
259
268
  /**
260
269
  * Desfecho da step. `message` (opcional) é o motivo legível — vai em `data.message`
261
270
  * e aparece na Central (performance e banner da execução) e no log de FINISH.
271
+ * `options.image` pendura um print do estado da tela em `data.attachments`.
262
272
  */
263
- setStatus(status: StepStatus, message?: string): this;
273
+ setStatus(status: StepStatus, message?: string, options?: StepOutcomeOptions): this;
264
274
  /**
265
275
  * Marca a step como `error` guardando o motivo em `data.error` ({ type, message }).
266
276
  * Aceita qualquer valor lançado; `message` sobrescreve a mensagem do erro.
277
+ * `options.image` pendura um print do estado da tela em `data.attachments`.
267
278
  */
268
- setError(error: unknown, message?: string): this;
279
+ setError(error: unknown, message?: string, options?: StepOutcomeOptions): this;
280
+ /**
281
+ * Dispara o upload pela run (sink do RunReporter) e referencia o anexo em
282
+ * `data.attachments` (chave reservada; teto igual ao das linhas de log). Fora de uma
283
+ * run não há onde pendurar a imagem — descarta com aviso único.
284
+ */
285
+ private attachImage;
269
286
  /** Motivo registrado via setStatus(…, message) ou setError — usado no log de FINISH. */
270
287
  private reason;
271
288
  setData(key: string, value: unknown): this;
@@ -292,6 +309,8 @@ declare class Transaction {
292
309
  private readonly tags;
293
310
  private finished;
294
311
  private lifecycleSink?;
312
+ private attachmentSink?;
313
+ private warnedNoAttachmentSink;
295
314
  private stepGuard?;
296
315
  private lifecycleBacklog;
297
316
  constructor(client: Client | undefined, name: string, op?: string | undefined,
@@ -306,6 +325,10 @@ declare class Transaction {
306
325
  emit(kind: 'transaction' | 'step', phase: 'start' | 'finish', label: string, startTs?: string, endTs?: string, status?: StepStatus | string, reason?: string): void;
307
326
  /** Conecta o espelho de lifecycle (RunReporter) e faz replay do backlog em ordem. */
308
327
  setLifecycleSink(sink: LifecycleSink): void;
328
+ /** Conecta o pipeline de anexos da run — é o que dá imagem às steps. */
329
+ setAttachmentSink(sink: AttachmentSink): void;
330
+ /** Imagem de uma step → id do anexo pela run; sem run, descarta com aviso único. */
331
+ attachImage(image: ImageInput): string | undefined;
309
332
  /**
310
333
  * Conecta a checagem de cancelamento chamada antes de cada step nova — é assim que
311
334
  * `hobots.transaction.startChild()` (e `step.startChild()`) param uma run cancelada.
@@ -323,6 +346,10 @@ declare class Transaction {
323
346
  /**
324
347
  * `hobots.log`: cada método aceita vários argumentos, como `console.log` — cada um vira
325
348
  * texto (`safeString`) e são unidos por espaço. Nunca lança, nem com a run cancelada.
349
+ *
350
+ * Um `hobots.image(...)` como **último** argumento não entra no texto: vira o print da
351
+ * linha (botão de imagem no app). O upload roda em segundo plano e nunca bloqueia:
352
+ * `hobots.log.error('login falhou', hobots.image(await page.screenshot()))`.
326
353
  */
327
354
  interface RunLogger {
328
355
  debug(message: unknown, ...rest: unknown[]): void;
@@ -331,10 +358,18 @@ interface RunLogger {
331
358
  error(message: unknown, ...rest: unknown[]): void;
332
359
  success(message: unknown, ...rest: unknown[]): void;
333
360
  }
334
- interface RunItemOptions {
361
+ interface RunItemImageOptions {
362
+ /**
363
+ * Print do item (bytes/caminho ou `hobots.image(bytes, { caption })`) — o estado da tela
364
+ * no momento do desfecho, com botão de imagem na tabela de itens do app. O upload roda
365
+ * em segundo plano e nunca bloqueia. PNG/JPEG/WEBP, até 5 MB, 20 por execução.
366
+ */
367
+ image?: ImageInput;
368
+ }
369
+ interface RunItemOptions extends RunItemImageOptions {
335
370
  /**
336
371
  * Identidade de negócio do item na run (ex.: nº da nota fiscal). Repetido na
337
- * mesma run = ignorado pelo servidor (registro único, retry idempotente).
372
+ * mesma run = o servidor atualiza o item (vale o último reporte, retry idempotente).
338
373
  * Omitido: o SDK gera um id único e cada chamada vira um item novo.
339
374
  */
340
375
  id?: string;
@@ -355,11 +390,11 @@ interface RunItemHandle {
355
390
  /** true depois do primeiro desfecho registrado (o SDK não sobrescreve o que o handler decidiu). */
356
391
  readonly reported: boolean;
357
392
  /** Item processado com sucesso. `payload` é mesclado sobre o payload base de `options.payload`. */
358
- succeeded(payload?: Record<string, unknown>): void;
359
- /** Falha sem lançar — o loop segue igual; a step vira `error` com o motivo. */
360
- failed(message: string, payload?: Record<string, unknown>): void;
361
- /** Ocorrência de negócio — a step vira `warning` com o motivo. */
362
- occurrence(message: string, payload?: Record<string, unknown>): void;
393
+ succeeded(payload?: Record<string, unknown>, options?: RunItemImageOptions): void;
394
+ /** Falha sem lançar — o loop segue igual; a step vira `error` com o motivo. A imagem vai no item. */
395
+ failed(message: string, payload?: Record<string, unknown>, options?: RunItemImageOptions): void;
396
+ /** Ocorrência de negócio — a step vira `warning` com o motivo. A imagem vai no item. */
397
+ occurrence(message: string, payload?: Record<string, unknown>, options?: RunItemImageOptions): void;
363
398
  }
364
399
  interface RunItemsEachOptions<T> {
365
400
  /** Identidade de negócio do item (ex.: nº do cliente). Omitido/null: o SDK gera um id único. */
@@ -397,6 +432,7 @@ interface RunItems {
397
432
  id?: string;
398
433
  message?: string;
399
434
  payload?: Record<string, unknown>;
435
+ image?: ImageInput;
400
436
  }): void;
401
437
  /** Item processado com sucesso. `payload` = atributos do item (viram colunas na plataforma). */
402
438
  succeeded(payload?: Record<string, unknown>, options?: RunItemOptions): void;
@@ -463,11 +499,6 @@ interface RunContext {
463
499
  throwIfCanceled(): void;
464
500
  /** Sleep cancelável: rejeita com `RunCanceled` se o signal disparar antes de ms. */
465
501
  sleep(ms: number): Promise<void>;
466
- /**
467
- * Anexa uma imagem (print) a uma linha de log da run — miniatura no app. Nunca lança nem
468
- * bloqueia: o upload roda em segundo plano. PNG/JPEG/WEBP, até 5 MB, 20 por execução.
469
- */
470
- attach(image: AttachInput, options?: AttachOptions): Promise<AttachResult>;
471
502
  /** async-retry ciente do cancelamento desta run (ver `RetryOptions`). */
472
503
  retry<T>(fn: (attempt: number) => T | Promise<T>, options?: RetryOptions): Promise<T>;
473
504
  }
@@ -488,6 +519,12 @@ interface Hobots extends RunContext {
488
519
  close(timeoutMs?: number): Promise<boolean>;
489
520
  /** Captura uma exceção como issue (módulo Issues). Retorna o event_id. */
490
521
  captureException(error: unknown, hint?: CaptureHint): string | undefined;
522
+ /**
523
+ * Embrulha um print para ir junto de um log, item ou step — `hobots.log.error('x', hobots.image(png))`,
524
+ * `hobots.items.failed('x', payload, { image: hobots.image(png, { caption }) })`,
525
+ * `step.setError(err, undefined, { image: png })`. Puro: nenhum I/O até o evento ser registrado.
526
+ */
527
+ image(input: AttachInput, options?: ImageOptions): ImageAttachment;
491
528
  }
492
529
  declare global {
493
530
  var hobots: Hobots;
@@ -498,5 +535,6 @@ declare const start: (task: string, handler: TaskHandler, options?: StartOptions
498
535
  declare const close: (timeoutMs?: number) => Promise<boolean>;
499
536
  declare const captureException: (error: unknown, hint?: CaptureHint) => string | undefined;
500
537
  declare const retry: <T>(fn: (attempt: number) => T | Promise<T>, options?: RetryOptions) => Promise<T>;
538
+ declare const image: (input: AttachInput, options?: ImageOptions) => ImageAttachment;
501
539
 
502
- export { type AttachFailureReason, type AttachInput, type AttachOptions, type AttachResult, type CaptureAttachment, type CaptureHint, EnvironmentInput, EventPayload, EventType, HeartbeatPayload, type Hobots, type HobotsOptions, type ItemColumnInput, MachineSnapshot, type RegisterOptions, type RetryDelay, type RetryOptions, RunAttachmentContentType, type RunContext, type RunItemHandle, type RunItemOptions, RunItemStatus, type RunItems, type RunItemsEachHandler, type RunItemsEachOptions, type RunItemsEachResult, RunLogLevel, type RunLogger, RunProgress, type RunProgressReporter, type StartOptions, Step, StepData, StepStatus, type TaskHandler, type TaskItemsOptions, type TaskOptions, Transaction, TransactionPayload, captureException, close, hobots as default, hobots, register, retry, start };
540
+ export { type AttachInput, type CaptureAttachment, type CaptureHint, EnvironmentInput, EventPayload, EventType, HeartbeatPayload, type Hobots, type HobotsOptions, ImageAttachment, type ImageInput, type ImageOptions, type ItemColumnInput, MachineSnapshot, type RegisterOptions, type RetryDelay, type RetryOptions, RunAttachmentContentType, type RunContext, type RunItemHandle, type RunItemImageOptions, type RunItemOptions, RunItemStatus, type RunItems, type RunItemsEachHandler, type RunItemsEachOptions, type RunItemsEachResult, RunLogLevel, type RunLogger, RunProgress, type RunProgressReporter, type StartOptions, Step, StepData, type StepOutcomeOptions, StepStatus, type TaskHandler, type TaskItemsOptions, type TaskOptions, Transaction, TransactionPayload, captureException, close, hobots as default, hobots, image, register, retry, start };
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { RunLogLevel, RunAttachmentContentType, EventType, EnvironmentInput, MachineSnapshot, EventPayload, TransactionPayload, HeartbeatPayload, StepStatus, StepData, RunItemStatus, RunProgress } from './protocol.js';
1
+ import { RunAttachmentContentType, EventType, EnvironmentInput, MachineSnapshot, EventPayload, TransactionPayload, HeartbeatPayload, StepStatus, RunLogLevel, StepData, RunItemStatus, RunProgress } from './protocol.js';
2
2
  export { Breadcrumb, BreadcrumbLevel, Envelope, EnvelopeItem, Environment, EventUser, ExceptionData, InstanceInfo, ItemColumn, MachineProcess, PollRequest, PollResponse, RunAttachmentConfirmRequest, RunAttachmentConfirmResponse, RunAttachmentCreateRequest, RunAttachmentCreateResponse, RunCreateRequest, RunCreateResponse, RunDescriptor, RunError, RunItemInput, RunItemsCreateRequest, RunItemsCreateResponse, RunLogEntry, RunStatus, RunUpdateRequest, RunUpdateResponse, RunUpdateStatus, StackFrame, TaskItemsDeclaration } from './protocol.js';
3
3
 
4
4
  /** Espera entre tentativas: ms fixo ou função do número da tentativa que acabou de falhar (1-based). */
@@ -12,30 +12,29 @@ interface RetryOptions {
12
12
  shouldRetry?: (error: unknown) => boolean;
13
13
  }
14
14
 
15
- interface AttachOptions {
16
- /** Legenda curta, exibida sob a miniatura no app. Passa pelo scrub de segredos. */
15
+ /** Aceita tudo que o handler pode ter em mãos: bytes ou um caminho de arquivo (só Node). */
16
+ type AttachInput = Uint8Array | ArrayBuffer | string;
17
+ interface ImageOptions {
18
+ /** Legenda curta, exibida junto da imagem no app. Passa pelo scrub de segredos. */
17
19
  caption?: string;
18
- /** Nível da linha de log que carrega o anexo. Default: 'info' */
19
- level?: RunLogLevel;
20
- /** Texto da linha de log. Default: a legenda, ou 'captura de tela' */
21
- message?: string;
22
20
  /** Informe quando os magic bytes não bastarem (o SDK sempre prefere o que detectar). */
23
21
  contentType?: RunAttachmentContentType;
24
22
  }
25
- type AttachFailureReason =
26
- /** A instalação do Hobots não tem anexos habilitados (ou a API é anterior ao recurso) */
27
- 'unsupported' | 'too-large' | 'quota' | 'read-failed'
28
- /** Formato não reconhecido ou fora de PNG/JPEG/WEBP */
29
- | 'unsupported-format' | 'upload-failed' | 'canceled';
30
- interface AttachResult {
31
- /** Id do anexo, o mesmo referenciado na linha de log */
32
- id: string;
33
- ok: boolean;
34
- /** Motivo do insucesso — para diagnóstico; `attach` nunca lança */
35
- reason?: AttachFailureReason;
23
+ declare const IMAGE_BRAND: unique symbol;
24
+ /**
25
+ * Uma imagem pronta para ser pendurada num evento da run — o retorno de `hobots.image()`.
26
+ * É só um envelope (bytes/caminho + legenda); nenhum I/O acontece até o evento ser
27
+ * registrado por `hobots.log.*`, `hobots.items.*` ou `step.setStatus/setError`.
28
+ */
29
+ declare class ImageAttachment {
30
+ readonly input: AttachInput;
31
+ readonly caption?: string | undefined;
32
+ readonly contentType?: RunAttachmentContentType | undefined;
33
+ readonly [IMAGE_BRAND] = true;
34
+ constructor(input: AttachInput, caption?: string | undefined, contentType?: RunAttachmentContentType | undefined);
36
35
  }
37
- /** Aceita tudo que o handler pode ter em mãos: bytes ou um caminho de arquivo (só Node). */
38
- type AttachInput = Uint8Array | ArrayBuffer | string;
36
+ /** O que os métodos com imagem aceitam: bytes/caminho crus ou o envelope de `hobots.image()`. */
37
+ type ImageInput = AttachInput | ImageAttachment;
39
38
 
40
39
  interface Logger {
41
40
  debug: (...args: unknown[]) => void;
@@ -162,7 +161,7 @@ interface CaptureHint {
162
161
  * hobots.captureException(error, { attachment: { image: await page.screenshot(), caption: 'tela no momento do erro' } });
163
162
  * ```
164
163
  */
165
- attachment?: AttachInput | CaptureAttachment;
164
+ attachment?: ImageInput | CaptureAttachment;
166
165
  }
167
166
 
168
167
  interface ResolvedConfig {
@@ -245,6 +244,16 @@ declare class Client {
245
244
 
246
245
  /** Recebe os eventos de lifecycle da transaction para espelhá-los nos logs da run. */
247
246
  type LifecycleSink = (level: RunLogLevel, message: string) => void;
247
+ /**
248
+ * Recebe a imagem de uma step e dispara o upload pela run; devolve o id do anexo
249
+ * (já referenciável em `data.attachments`) ou undefined quando descartada.
250
+ */
251
+ type AttachmentSink = (image: ImageInput, ts: string) => string | undefined;
252
+ /** Opções dos desfechos de step que aceitam um print do estado da tela. */
253
+ interface StepOutcomeOptions {
254
+ /** Print da step (bytes/caminho ou `hobots.image(bytes, { caption })`) — botão de imagem no app. */
255
+ image?: ImageInput;
256
+ }
248
257
  declare class Step {
249
258
  private readonly transaction;
250
259
  readonly parentStepId: string;
@@ -259,13 +268,21 @@ declare class Step {
259
268
  /**
260
269
  * Desfecho da step. `message` (opcional) é o motivo legível — vai em `data.message`
261
270
  * e aparece na Central (performance e banner da execução) e no log de FINISH.
271
+ * `options.image` pendura um print do estado da tela em `data.attachments`.
262
272
  */
263
- setStatus(status: StepStatus, message?: string): this;
273
+ setStatus(status: StepStatus, message?: string, options?: StepOutcomeOptions): this;
264
274
  /**
265
275
  * Marca a step como `error` guardando o motivo em `data.error` ({ type, message }).
266
276
  * Aceita qualquer valor lançado; `message` sobrescreve a mensagem do erro.
277
+ * `options.image` pendura um print do estado da tela em `data.attachments`.
267
278
  */
268
- setError(error: unknown, message?: string): this;
279
+ setError(error: unknown, message?: string, options?: StepOutcomeOptions): this;
280
+ /**
281
+ * Dispara o upload pela run (sink do RunReporter) e referencia o anexo em
282
+ * `data.attachments` (chave reservada; teto igual ao das linhas de log). Fora de uma
283
+ * run não há onde pendurar a imagem — descarta com aviso único.
284
+ */
285
+ private attachImage;
269
286
  /** Motivo registrado via setStatus(…, message) ou setError — usado no log de FINISH. */
270
287
  private reason;
271
288
  setData(key: string, value: unknown): this;
@@ -292,6 +309,8 @@ declare class Transaction {
292
309
  private readonly tags;
293
310
  private finished;
294
311
  private lifecycleSink?;
312
+ private attachmentSink?;
313
+ private warnedNoAttachmentSink;
295
314
  private stepGuard?;
296
315
  private lifecycleBacklog;
297
316
  constructor(client: Client | undefined, name: string, op?: string | undefined,
@@ -306,6 +325,10 @@ declare class Transaction {
306
325
  emit(kind: 'transaction' | 'step', phase: 'start' | 'finish', label: string, startTs?: string, endTs?: string, status?: StepStatus | string, reason?: string): void;
307
326
  /** Conecta o espelho de lifecycle (RunReporter) e faz replay do backlog em ordem. */
308
327
  setLifecycleSink(sink: LifecycleSink): void;
328
+ /** Conecta o pipeline de anexos da run — é o que dá imagem às steps. */
329
+ setAttachmentSink(sink: AttachmentSink): void;
330
+ /** Imagem de uma step → id do anexo pela run; sem run, descarta com aviso único. */
331
+ attachImage(image: ImageInput): string | undefined;
309
332
  /**
310
333
  * Conecta a checagem de cancelamento chamada antes de cada step nova — é assim que
311
334
  * `hobots.transaction.startChild()` (e `step.startChild()`) param uma run cancelada.
@@ -323,6 +346,10 @@ declare class Transaction {
323
346
  /**
324
347
  * `hobots.log`: cada método aceita vários argumentos, como `console.log` — cada um vira
325
348
  * texto (`safeString`) e são unidos por espaço. Nunca lança, nem com a run cancelada.
349
+ *
350
+ * Um `hobots.image(...)` como **último** argumento não entra no texto: vira o print da
351
+ * linha (botão de imagem no app). O upload roda em segundo plano e nunca bloqueia:
352
+ * `hobots.log.error('login falhou', hobots.image(await page.screenshot()))`.
326
353
  */
327
354
  interface RunLogger {
328
355
  debug(message: unknown, ...rest: unknown[]): void;
@@ -331,10 +358,18 @@ interface RunLogger {
331
358
  error(message: unknown, ...rest: unknown[]): void;
332
359
  success(message: unknown, ...rest: unknown[]): void;
333
360
  }
334
- interface RunItemOptions {
361
+ interface RunItemImageOptions {
362
+ /**
363
+ * Print do item (bytes/caminho ou `hobots.image(bytes, { caption })`) — o estado da tela
364
+ * no momento do desfecho, com botão de imagem na tabela de itens do app. O upload roda
365
+ * em segundo plano e nunca bloqueia. PNG/JPEG/WEBP, até 5 MB, 20 por execução.
366
+ */
367
+ image?: ImageInput;
368
+ }
369
+ interface RunItemOptions extends RunItemImageOptions {
335
370
  /**
336
371
  * Identidade de negócio do item na run (ex.: nº da nota fiscal). Repetido na
337
- * mesma run = ignorado pelo servidor (registro único, retry idempotente).
372
+ * mesma run = o servidor atualiza o item (vale o último reporte, retry idempotente).
338
373
  * Omitido: o SDK gera um id único e cada chamada vira um item novo.
339
374
  */
340
375
  id?: string;
@@ -355,11 +390,11 @@ interface RunItemHandle {
355
390
  /** true depois do primeiro desfecho registrado (o SDK não sobrescreve o que o handler decidiu). */
356
391
  readonly reported: boolean;
357
392
  /** Item processado com sucesso. `payload` é mesclado sobre o payload base de `options.payload`. */
358
- succeeded(payload?: Record<string, unknown>): void;
359
- /** Falha sem lançar — o loop segue igual; a step vira `error` com o motivo. */
360
- failed(message: string, payload?: Record<string, unknown>): void;
361
- /** Ocorrência de negócio — a step vira `warning` com o motivo. */
362
- occurrence(message: string, payload?: Record<string, unknown>): void;
393
+ succeeded(payload?: Record<string, unknown>, options?: RunItemImageOptions): void;
394
+ /** Falha sem lançar — o loop segue igual; a step vira `error` com o motivo. A imagem vai no item. */
395
+ failed(message: string, payload?: Record<string, unknown>, options?: RunItemImageOptions): void;
396
+ /** Ocorrência de negócio — a step vira `warning` com o motivo. A imagem vai no item. */
397
+ occurrence(message: string, payload?: Record<string, unknown>, options?: RunItemImageOptions): void;
363
398
  }
364
399
  interface RunItemsEachOptions<T> {
365
400
  /** Identidade de negócio do item (ex.: nº do cliente). Omitido/null: o SDK gera um id único. */
@@ -397,6 +432,7 @@ interface RunItems {
397
432
  id?: string;
398
433
  message?: string;
399
434
  payload?: Record<string, unknown>;
435
+ image?: ImageInput;
400
436
  }): void;
401
437
  /** Item processado com sucesso. `payload` = atributos do item (viram colunas na plataforma). */
402
438
  succeeded(payload?: Record<string, unknown>, options?: RunItemOptions): void;
@@ -463,11 +499,6 @@ interface RunContext {
463
499
  throwIfCanceled(): void;
464
500
  /** Sleep cancelável: rejeita com `RunCanceled` se o signal disparar antes de ms. */
465
501
  sleep(ms: number): Promise<void>;
466
- /**
467
- * Anexa uma imagem (print) a uma linha de log da run — miniatura no app. Nunca lança nem
468
- * bloqueia: o upload roda em segundo plano. PNG/JPEG/WEBP, até 5 MB, 20 por execução.
469
- */
470
- attach(image: AttachInput, options?: AttachOptions): Promise<AttachResult>;
471
502
  /** async-retry ciente do cancelamento desta run (ver `RetryOptions`). */
472
503
  retry<T>(fn: (attempt: number) => T | Promise<T>, options?: RetryOptions): Promise<T>;
473
504
  }
@@ -488,6 +519,12 @@ interface Hobots extends RunContext {
488
519
  close(timeoutMs?: number): Promise<boolean>;
489
520
  /** Captura uma exceção como issue (módulo Issues). Retorna o event_id. */
490
521
  captureException(error: unknown, hint?: CaptureHint): string | undefined;
522
+ /**
523
+ * Embrulha um print para ir junto de um log, item ou step — `hobots.log.error('x', hobots.image(png))`,
524
+ * `hobots.items.failed('x', payload, { image: hobots.image(png, { caption }) })`,
525
+ * `step.setError(err, undefined, { image: png })`. Puro: nenhum I/O até o evento ser registrado.
526
+ */
527
+ image(input: AttachInput, options?: ImageOptions): ImageAttachment;
491
528
  }
492
529
  declare global {
493
530
  var hobots: Hobots;
@@ -498,5 +535,6 @@ declare const start: (task: string, handler: TaskHandler, options?: StartOptions
498
535
  declare const close: (timeoutMs?: number) => Promise<boolean>;
499
536
  declare const captureException: (error: unknown, hint?: CaptureHint) => string | undefined;
500
537
  declare const retry: <T>(fn: (attempt: number) => T | Promise<T>, options?: RetryOptions) => Promise<T>;
538
+ declare const image: (input: AttachInput, options?: ImageOptions) => ImageAttachment;
501
539
 
502
- export { type AttachFailureReason, type AttachInput, type AttachOptions, type AttachResult, type CaptureAttachment, type CaptureHint, EnvironmentInput, EventPayload, EventType, HeartbeatPayload, type Hobots, type HobotsOptions, type ItemColumnInput, MachineSnapshot, type RegisterOptions, type RetryDelay, type RetryOptions, RunAttachmentContentType, type RunContext, type RunItemHandle, type RunItemOptions, RunItemStatus, type RunItems, type RunItemsEachHandler, type RunItemsEachOptions, type RunItemsEachResult, RunLogLevel, type RunLogger, RunProgress, type RunProgressReporter, type StartOptions, Step, StepData, StepStatus, type TaskHandler, type TaskItemsOptions, type TaskOptions, Transaction, TransactionPayload, captureException, close, hobots as default, hobots, register, retry, start };
540
+ export { type AttachInput, type CaptureAttachment, type CaptureHint, EnvironmentInput, EventPayload, EventType, HeartbeatPayload, type Hobots, type HobotsOptions, ImageAttachment, type ImageInput, type ImageOptions, type ItemColumnInput, MachineSnapshot, type RegisterOptions, type RetryDelay, type RetryOptions, RunAttachmentContentType, type RunContext, type RunItemHandle, type RunItemImageOptions, type RunItemOptions, RunItemStatus, type RunItems, type RunItemsEachHandler, type RunItemsEachOptions, type RunItemsEachResult, RunLogLevel, type RunLogger, RunProgress, type RunProgressReporter, type StartOptions, Step, StepData, type StepOutcomeOptions, StepStatus, type TaskHandler, type TaskItemsOptions, type TaskOptions, Transaction, TransactionPayload, captureException, close, hobots as default, hobots, image, register, retry, start };