hobots 1.10.0 → 2.0.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,5 +1,5 @@
1
1
  import { Breadcrumb, EventUser, Severity, EventPayload, TransactionPayload, HeartbeatPayload, StepStatus, RunLogLevel, StepData, RunItemStatus, RunAttachmentContentType } from './protocol.cjs';
2
- export { AgentInfo, Envelope, EnvelopeItem, ExceptionData, PollRequest, PollResponse, RunAttachmentConfirmRequest, RunAttachmentConfirmResponse, RunAttachmentCreateRequest, RunAttachmentCreateResponse, RunDescriptor, RunError, RunItemInput, RunItemsCreateRequest, RunItemsCreateResponse, RunLogEntry, RunStatus, RunUpdateRequest, RunUpdateResponse, RunUpdateStatus, StackFrame } from './protocol.cjs';
2
+ export { Envelope, EnvelopeItem, ExceptionData, InstanceInfo, PollRequest, PollResponse, RunAttachmentConfirmRequest, RunAttachmentConfirmResponse, RunAttachmentCreateRequest, RunAttachmentCreateResponse, RunDescriptor, RunError, RunItemInput, RunItemsCreateRequest, RunItemsCreateResponse, RunLogEntry, RunStatus, RunUpdateRequest, RunUpdateResponse, RunUpdateStatus, StackFrame } from './protocol.cjs';
3
3
 
4
4
  /** Aceita tudo que o handler pode ter em mãos: bytes ou um caminho de arquivo (só Node). */
5
5
  type AttachInput = Uint8Array | ArrayBuffer | string;
@@ -50,6 +50,8 @@ interface Logger {
50
50
  declare class Client {
51
51
  #private;
52
52
  readonly logger: Logger;
53
+ /** Eco de lifecycle (Transaction.emit) e afins só imprimem no terminal com debug ligado. */
54
+ readonly debug: boolean;
53
55
  private readonly transport;
54
56
  constructor(options: InitOptions, config?: ResolvedConfig);
55
57
  get options(): InitOptions;
@@ -110,9 +112,10 @@ declare class Transaction {
110
112
  /** Correlaciona a uma execução de task — preenchido automaticamente em ctx.tx */
111
113
  runId?: string | undefined);
112
114
  /**
113
- * Ecoa no terminal o início/fim de uma step ou transaction (sempre, independente de
114
- * sampling ou do debug) e espelha a linha no sink de lifecycle, se conectado — é
115
- * assim que os eventos de performance também aparecem nos logs da run no app.
115
+ * Registra o início/fim de uma step ou transaction: espelha a linha no sink de
116
+ * lifecycle, se conectado (é assim que os eventos de performance aparecem nos
117
+ * logs da run no app), e ecoa no terminal apenas com `debug: true` — o SDK não
118
+ * escreve no stdout do processo do usuário sem permissão.
116
119
  */
117
120
  emit(kind: 'transaction' | 'step', phase: 'start' | 'finish', label: string, startTs?: string, endTs?: string, status?: StepStatus | string): void;
118
121
  /** Conecta o espelho de lifecycle (RunReporter) e faz replay do backlog em ordem. */
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { Breadcrumb, EventUser, Severity, EventPayload, TransactionPayload, HeartbeatPayload, StepStatus, RunLogLevel, StepData, RunItemStatus, RunAttachmentContentType } from './protocol.js';
2
- export { AgentInfo, Envelope, EnvelopeItem, ExceptionData, PollRequest, PollResponse, RunAttachmentConfirmRequest, RunAttachmentConfirmResponse, RunAttachmentCreateRequest, RunAttachmentCreateResponse, RunDescriptor, RunError, RunItemInput, RunItemsCreateRequest, RunItemsCreateResponse, RunLogEntry, RunStatus, RunUpdateRequest, RunUpdateResponse, RunUpdateStatus, StackFrame } from './protocol.js';
2
+ export { Envelope, EnvelopeItem, ExceptionData, InstanceInfo, PollRequest, PollResponse, RunAttachmentConfirmRequest, RunAttachmentConfirmResponse, RunAttachmentCreateRequest, RunAttachmentCreateResponse, RunDescriptor, RunError, RunItemInput, RunItemsCreateRequest, RunItemsCreateResponse, RunLogEntry, RunStatus, RunUpdateRequest, RunUpdateResponse, RunUpdateStatus, StackFrame } from './protocol.js';
3
3
 
4
4
  /** Aceita tudo que o handler pode ter em mãos: bytes ou um caminho de arquivo (só Node). */
5
5
  type AttachInput = Uint8Array | ArrayBuffer | string;
@@ -50,6 +50,8 @@ interface Logger {
50
50
  declare class Client {
51
51
  #private;
52
52
  readonly logger: Logger;
53
+ /** Eco de lifecycle (Transaction.emit) e afins só imprimem no terminal com debug ligado. */
54
+ readonly debug: boolean;
53
55
  private readonly transport;
54
56
  constructor(options: InitOptions, config?: ResolvedConfig);
55
57
  get options(): InitOptions;
@@ -110,9 +112,10 @@ declare class Transaction {
110
112
  /** Correlaciona a uma execução de task — preenchido automaticamente em ctx.tx */
111
113
  runId?: string | undefined);
112
114
  /**
113
- * Ecoa no terminal o início/fim de uma step ou transaction (sempre, independente de
114
- * sampling ou do debug) e espelha a linha no sink de lifecycle, se conectado — é
115
- * assim que os eventos de performance também aparecem nos logs da run no app.
115
+ * Registra o início/fim de uma step ou transaction: espelha a linha no sink de
116
+ * lifecycle, se conectado (é assim que os eventos de performance aparecem nos
117
+ * logs da run no app), e ecoa no terminal apenas com `debug: true` — o SDK não
118
+ * escreve no stdout do processo do usuário sem permissão.
116
119
  */
117
120
  emit(kind: 'transaction' | 'step', phase: 'start' | 'finish', label: string, startTs?: string, endTs?: string, status?: StepStatus | string): void;
118
121
  /** Conecta o espelho de lifecycle (RunReporter) e faz replay do backlog em ordem. */
package/dist/index.js CHANGED
@@ -103,7 +103,7 @@ function scrubSecrets(text) {
103
103
 
104
104
  // src/utils.ts
105
105
  var SDK_NAME = "hobots";
106
- var SDK_VERSION = true ? "1.10.0" : "0.0.0-dev";
106
+ var SDK_VERSION = true ? "2.0.0" : "0.0.0-dev";
107
107
  function isNode() {
108
108
  return typeof process !== "undefined" && typeof process.versions?.node === "string";
109
109
  }
@@ -296,7 +296,8 @@ var Transport = class {
296
296
  return;
297
297
  }
298
298
  if (this.buffer.length >= this.maxQueueSize) {
299
- this.buffer.shift();
299
+ const dropIndex = this.buffer.findIndex((queued) => queued.type !== "heartbeat");
300
+ this.buffer.splice(dropIndex === -1 ? 0 : dropIndex, 1);
300
301
  this.logger.warn("fila cheia, item mais antigo descartado");
301
302
  }
302
303
  this.buffer.push(item);
@@ -387,6 +388,8 @@ function runtimeContexts() {
387
388
  }
388
389
  var Client = class {
389
390
  logger;
391
+ /** Eco de lifecycle (Transaction.emit) e afins só imprimem no terminal com debug ligado. */
392
+ debug;
390
393
  // campos privados + getters de protótipo: o clientSecret não aparece em
391
394
  // JSON.stringify/serialização enumerável do Client (ex.: um objeto capturado
392
395
  // que referencie o client), mas client.options/config seguem funcionando
@@ -395,7 +398,8 @@ var Client = class {
395
398
  transport;
396
399
  constructor(options, config = resolveConfig(options)) {
397
400
  this.#options = options;
398
- this.logger = makeLogger(!!options.debug);
401
+ this.debug = !!options.debug;
402
+ this.logger = makeLogger(this.debug);
399
403
  this.#config = config;
400
404
  this.transport = new Transport({
401
405
  endpoint: this.#config.ingestEndpoint,
@@ -482,6 +486,8 @@ var Client = class {
482
486
 
483
487
  // src/heartbeat.ts
484
488
  var DEFAULT_INTERVAL_MS = 3e4;
489
+ var MIN_REPORTED_INTERVAL_MS = 1e3;
490
+ var MAX_REPORTED_INTERVAL_MS = 9e5;
485
491
  var Heartbeat = class {
486
492
  constructor(client2, options = {}, instanceId) {
487
493
  this.client = client2;
@@ -498,12 +504,22 @@ var Heartbeat = class {
498
504
  start() {
499
505
  if (this.timer) return;
500
506
  this.beat();
501
- this.timer = setInterval(() => this.beat(), this.intervalMs);
507
+ this.schedule();
508
+ }
509
+ /** Jitter de ±10%: uma frota iniciada junto não sincroniza todos os beats no mesmo segundo. */
510
+ schedule() {
511
+ this.timer = setTimeout(
512
+ () => {
513
+ this.beat();
514
+ this.schedule();
515
+ },
516
+ this.intervalMs * (0.9 + Math.random() * 0.2)
517
+ );
502
518
  unrefTimer(this.timer);
503
519
  }
504
520
  stop() {
505
521
  if (this.timer) {
506
- clearInterval(this.timer);
522
+ clearTimeout(this.timer);
507
523
  this.timer = void 0;
508
524
  }
509
525
  }
@@ -511,7 +527,7 @@ var Heartbeat = class {
511
527
  this.client.sendHeartbeat({
512
528
  instance_id: this.instanceId,
513
529
  name: this.name,
514
- interval_ms: this.intervalMs,
530
+ interval_ms: Math.min(Math.max(this.intervalMs, MIN_REPORTED_INTERVAL_MS), MAX_REPORTED_INTERVAL_MS),
515
531
  timestamp: nowISO(),
516
532
  metadata: this.metadata
517
533
  });
@@ -758,15 +774,18 @@ var Transaction = class {
758
774
  // antes do RunReporter conectar) — replay no setLifecycleSink
759
775
  lifecycleBacklog = [];
760
776
  /**
761
- * Ecoa no terminal o início/fim de uma step ou transaction (sempre, independente de
762
- * sampling ou do debug) e espelha a linha no sink de lifecycle, se conectado — é
763
- * assim que os eventos de performance também aparecem nos logs da run no app.
777
+ * Registra o início/fim de uma step ou transaction: espelha a linha no sink de
778
+ * lifecycle, se conectado (é assim que os eventos de performance aparecem nos
779
+ * logs da run no app), e ecoa no terminal apenas com `debug: true` — o SDK não
780
+ * escreve no stdout do processo do usuário sem permissão.
764
781
  */
765
782
  emit(kind, phase, label, startTs, endTs, status) {
766
783
  const durationMs = startTs && endTs ? new Date(endTs).getTime() - new Date(startTs).getTime() : void 0;
767
- const tag = colorize(`[hobots:${kind}] ${phase.toUpperCase()}`, phase === "finish" ? colorForStatus(status ?? "ok") : "cyan");
768
784
  const suffix = durationMs != null ? ` (${durationMs}ms)` : "";
769
- console.log(`${tag} ${label}${suffix}`);
785
+ if (this.client?.debug) {
786
+ const tag = colorize(`[hobots:${kind}] ${phase.toUpperCase()}`, phase === "finish" ? colorForStatus(status ?? "ok") : "cyan");
787
+ console.log(`${tag} ${label}${suffix}`);
788
+ }
770
789
  const level = phase === "finish" ? levelForStatus(status ?? "ok") : "info";
771
790
  const message = `[${kind}] ${phase.toUpperCase()} ${label}${suffix}`;
772
791
  if (this.lifecycleSink) this.lifecycleSink(level, message);
@@ -1813,13 +1832,17 @@ var TaskAgent = class {
1813
1832
  try {
1814
1833
  const response = await this.api.poll(
1815
1834
  {
1816
- agent: {
1835
+ instance: {
1817
1836
  // identidade canônica do agente no painel — o mesmo instanceId do
1818
1837
  // heartbeat da Telemetria, então os dois canais convergem em um agente
1819
1838
  instance_id: this.instanceId,
1820
1839
  version: SDK_VERSION,
1821
1840
  host: hostname(),
1822
- tasks: [...this.registry.keys()]
1841
+ tasks: [...this.registry.keys()],
1842
+ // o servidor calcula a tolerância de offline (3×) a partir disto em
1843
+ // agentes poll-only — sem o campo, um poll lento flaparia offline/online.
1844
+ // Clampado à faixa aceita pelo schema do poll (1s..15min).
1845
+ poll_interval_ms: Math.min(Math.max(this.pollIntervalMs, 1e3), 9e5)
1823
1846
  },
1824
1847
  max: Math.min(MAX_CONCURRENCY, this.concurrency - this.activeRuns.size),
1825
1848
  tasks: [...this.registry.keys()]