hobots 4.0.0 → 4.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.
- package/README.md +2 -1
- package/dist/{chunk-5WIIACWC.js → chunk-HKCDMUA3.js} +1 -2
- package/dist/chunk-HKCDMUA3.js.map +1 -0
- package/dist/index.cjs +84 -24
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +20 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.js +85 -24
- package/dist/index.js.map +1 -1
- package/dist/protocol.cjs +0 -1
- package/dist/protocol.cjs.map +1 -1
- package/dist/protocol.d.cts +0 -2
- package/dist/protocol.d.ts +0 -2
- package/dist/protocol.js +1 -1
- package/docs/api-reference.md +2 -1
- package/docs/protocol.md +2 -2
- package/docs/runs.md +30 -2
- package/package.json +1 -1
- package/dist/chunk-5WIIACWC.js.map +0 -1
package/dist/index.d.cts
CHANGED
|
@@ -340,6 +340,18 @@ declare class Transaction {
|
|
|
340
340
|
setTag(key: string, value: string): this;
|
|
341
341
|
setStatus(status: string): this;
|
|
342
342
|
setName(name: string): this;
|
|
343
|
+
/**
|
|
344
|
+
* Envia já as steps raiz finalizadas (e todas as descendentes, fechando as que
|
|
345
|
+
* ficaram abertas) como transactions parciais da mesma run (`op` hobots.run.flush,
|
|
346
|
+
* `event_id` novo, até 200 steps cada) e as tira da memória. Steps raiz ainda abertas
|
|
347
|
+
* ficam para o próximo flush ou para o `finish()`. É assim que um agente sempre
|
|
348
|
+
* ligado (`start()`), cuja run não termina, entrega as etapas enquanto processa.
|
|
349
|
+
* Devolve quantas steps foram enviadas.
|
|
350
|
+
*/
|
|
351
|
+
flush(): number;
|
|
352
|
+
/** Entrega já (com teto) o que está na fila do transport — as transactions parciais inclusive. */
|
|
353
|
+
drain(timeoutMs: number): Promise<void>;
|
|
354
|
+
private payload;
|
|
343
355
|
finish(): void;
|
|
344
356
|
}
|
|
345
357
|
|
|
@@ -489,6 +501,14 @@ interface RunContext {
|
|
|
489
501
|
* medir as etapas (steps); elas aparecem como waterfall na aba de performance da execução.
|
|
490
502
|
*/
|
|
491
503
|
readonly transaction: Transaction;
|
|
504
|
+
/**
|
|
505
|
+
* Entrega já o que a execução fez: as steps raiz finalizadas viram transactions parciais
|
|
506
|
+
* (waterfall da Central sem esperar a run terminar) e itens, logs e progresso pendentes
|
|
507
|
+
* saem sem esperar o throttle. Quem decide quando chamar é o bot — num agente sempre
|
|
508
|
+
* ligado (`start()`), ao fim de cada rodada que processou itens. Aguarda a entrega com
|
|
509
|
+
* teto (`timeoutMs`, default 15s) e nunca lança.
|
|
510
|
+
*/
|
|
511
|
+
flush(timeoutMs?: number): Promise<void>;
|
|
492
512
|
/** Dispara em cancelamento (run cancelada no app), timeout ou shutdown — cancelamento cooperativo */
|
|
493
513
|
readonly signal: AbortSignal;
|
|
494
514
|
/**
|
package/dist/index.d.ts
CHANGED
|
@@ -340,6 +340,18 @@ declare class Transaction {
|
|
|
340
340
|
setTag(key: string, value: string): this;
|
|
341
341
|
setStatus(status: string): this;
|
|
342
342
|
setName(name: string): this;
|
|
343
|
+
/**
|
|
344
|
+
* Envia já as steps raiz finalizadas (e todas as descendentes, fechando as que
|
|
345
|
+
* ficaram abertas) como transactions parciais da mesma run (`op` hobots.run.flush,
|
|
346
|
+
* `event_id` novo, até 200 steps cada) e as tira da memória. Steps raiz ainda abertas
|
|
347
|
+
* ficam para o próximo flush ou para o `finish()`. É assim que um agente sempre
|
|
348
|
+
* ligado (`start()`), cuja run não termina, entrega as etapas enquanto processa.
|
|
349
|
+
* Devolve quantas steps foram enviadas.
|
|
350
|
+
*/
|
|
351
|
+
flush(): number;
|
|
352
|
+
/** Entrega já (com teto) o que está na fila do transport — as transactions parciais inclusive. */
|
|
353
|
+
drain(timeoutMs: number): Promise<void>;
|
|
354
|
+
private payload;
|
|
343
355
|
finish(): void;
|
|
344
356
|
}
|
|
345
357
|
|
|
@@ -489,6 +501,14 @@ interface RunContext {
|
|
|
489
501
|
* medir as etapas (steps); elas aparecem como waterfall na aba de performance da execução.
|
|
490
502
|
*/
|
|
491
503
|
readonly transaction: Transaction;
|
|
504
|
+
/**
|
|
505
|
+
* Entrega já o que a execução fez: as steps raiz finalizadas viram transactions parciais
|
|
506
|
+
* (waterfall da Central sem esperar a run terminar) e itens, logs e progresso pendentes
|
|
507
|
+
* saem sem esperar o throttle. Quem decide quando chamar é o bot — num agente sempre
|
|
508
|
+
* ligado (`start()`), ao fim de cada rodada que processou itens. Aguarda a entrega com
|
|
509
|
+
* teto (`timeoutMs`, default 15s) e nunca lança.
|
|
510
|
+
*/
|
|
511
|
+
flush(timeoutMs?: number): Promise<void>;
|
|
492
512
|
/** Dispara em cancelamento (run cancelada no app), timeout ou shutdown — cancelamento cooperativo */
|
|
493
513
|
readonly signal: AbortSignal;
|
|
494
514
|
/**
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
WIRE_LIMITS
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-HKCDMUA3.js";
|
|
4
4
|
|
|
5
5
|
// src/stacktrace.ts
|
|
6
6
|
var MAX_FRAMES = 50;
|
|
@@ -57,7 +57,7 @@ function scrubSecrets(text) {
|
|
|
57
57
|
|
|
58
58
|
// src/utils.ts
|
|
59
59
|
var SDK_NAME = "hobots";
|
|
60
|
-
var SDK_VERSION = true ? "4.
|
|
60
|
+
var SDK_VERSION = true ? "4.1.0" : "0.0.0-dev";
|
|
61
61
|
function isNode() {
|
|
62
62
|
return typeof process !== "undefined" && typeof process.versions?.node === "string";
|
|
63
63
|
}
|
|
@@ -1348,7 +1348,6 @@ var MAX_CANCEL_CHECK_INTERVAL_MS = 15e3;
|
|
|
1348
1348
|
var MAX_LOG_MESSAGE_CHARS = WIRE_LIMITS.MAX_LOG_MESSAGE_CHARS;
|
|
1349
1349
|
var MAX_LOGS_PER_PATCH = WIRE_LIMITS.MAX_LOGS_PER_PATCH;
|
|
1350
1350
|
var FLUSH_AT_BUFFERED = 20;
|
|
1351
|
-
var MAX_ITEMS_PER_RUN = WIRE_LIMITS.MAX_ITEMS_PER_RUN;
|
|
1352
1351
|
var MAX_ITEMS_PER_REQUEST = WIRE_LIMITS.MAX_ITEMS_PER_REQUEST;
|
|
1353
1352
|
var MAX_ITEM_MESSAGE_CHARS = WIRE_LIMITS.MAX_ITEM_MESSAGE_CHARS;
|
|
1354
1353
|
var MAX_ITEM_PAYLOAD_BYTES = WIRE_LIMITS.MAX_ITEM_PAYLOAD_BYTES;
|
|
@@ -1370,6 +1369,7 @@ var RunReporter = class {
|
|
|
1370
1369
|
this.api = api;
|
|
1371
1370
|
this.runId = runId;
|
|
1372
1371
|
this.logger = logger;
|
|
1372
|
+
this.tx = tx;
|
|
1373
1373
|
this.flushIntervalMs = flushIntervalMs ?? DEFAULT_LOG_FLUSH_INTERVAL_MS;
|
|
1374
1374
|
this.cancelCheckIntervalMs = Math.min(
|
|
1375
1375
|
MAX_CANCEL_CHECK_INTERVAL_MS,
|
|
@@ -1453,6 +1453,7 @@ var RunReporter = class {
|
|
|
1453
1453
|
items,
|
|
1454
1454
|
progress,
|
|
1455
1455
|
transaction: tx,
|
|
1456
|
+
flush: (timeoutMs) => this.flush(timeoutMs),
|
|
1456
1457
|
signal,
|
|
1457
1458
|
throwIfCanceled: checkCanceled,
|
|
1458
1459
|
sleep: sleep2,
|
|
@@ -1462,6 +1463,7 @@ var RunReporter = class {
|
|
|
1462
1463
|
api;
|
|
1463
1464
|
runId;
|
|
1464
1465
|
logger;
|
|
1466
|
+
tx;
|
|
1465
1467
|
context;
|
|
1466
1468
|
buffer = [];
|
|
1467
1469
|
dead = false;
|
|
@@ -1479,7 +1481,6 @@ var RunReporter = class {
|
|
|
1479
1481
|
itemsChain = Promise.resolve();
|
|
1480
1482
|
itemsTimer;
|
|
1481
1483
|
itemSeq = 0;
|
|
1482
|
-
itemCount = 0;
|
|
1483
1484
|
/** Servidor sem o recurso (404) — para de tentar (e de avisar) nesta run. */
|
|
1484
1485
|
itemsUnsupported = false;
|
|
1485
1486
|
/** Cap de itens por run atingido (client-side ou 429) — degrada com um aviso só. */
|
|
@@ -1602,6 +1603,21 @@ var RunReporter = class {
|
|
|
1602
1603
|
this.enqueue({ status: "running", logs: logs.slice(i, i + MAX_LOGS_PER_PATCH) });
|
|
1603
1604
|
}
|
|
1604
1605
|
}
|
|
1606
|
+
/**
|
|
1607
|
+
* `hobots.flush()`: o bot decide quando entregar o que já fez — steps raiz finalizadas
|
|
1608
|
+
* viram transactions parciais da run, e itens, logs e progresso pendentes saem já, sem
|
|
1609
|
+
* esperar o throttle. Aguarda a entrega com teto. Nunca lança (pode ir num `finally`).
|
|
1610
|
+
*/
|
|
1611
|
+
async flush(timeoutMs = ITEMS_DRAIN_MS) {
|
|
1612
|
+
this.tx.flush();
|
|
1613
|
+
this.flushItems();
|
|
1614
|
+
if (this.progressDirty) this.flushProgress();
|
|
1615
|
+
else this.flushLogs();
|
|
1616
|
+
await Promise.race([
|
|
1617
|
+
Promise.all([this.itemsChain, this.chain, this.tx.drain(timeoutMs)]).catch(() => void 0),
|
|
1618
|
+
new Promise((resolve2) => unrefTimer(setTimeout(resolve2, timeoutMs)))
|
|
1619
|
+
]);
|
|
1620
|
+
}
|
|
1605
1621
|
/** Primeiro PATCH (claimed → running). Retorna false se a run já morreu (cancelada). */
|
|
1606
1622
|
async reportRunning() {
|
|
1607
1623
|
this.enqueue({ status: "running" });
|
|
@@ -1712,14 +1728,6 @@ var RunReporter = class {
|
|
|
1712
1728
|
*/
|
|
1713
1729
|
addItem(status, message, payload, id, image3) {
|
|
1714
1730
|
if (this.itemsClosed || this.itemsUnsupported) return;
|
|
1715
|
-
if (this.itemCount >= MAX_ITEMS_PER_RUN) {
|
|
1716
|
-
if (!this.itemsQuotaExceeded) {
|
|
1717
|
-
this.itemsQuotaExceeded = true;
|
|
1718
|
-
this.log("warning", `itens descartados: limite de ${MAX_ITEMS_PER_RUN} por execu\xE7\xE3o atingido`);
|
|
1719
|
-
}
|
|
1720
|
-
return;
|
|
1721
|
-
}
|
|
1722
|
-
this.itemCount++;
|
|
1723
1731
|
let scrubbedPayload;
|
|
1724
1732
|
if (payload) {
|
|
1725
1733
|
scrubbedPayload = scrubPayloadValue(payload, 0);
|
|
@@ -2014,6 +2022,7 @@ function currentRunReporter() {
|
|
|
2014
2022
|
}
|
|
2015
2023
|
|
|
2016
2024
|
// src/transaction.ts
|
|
2025
|
+
var FLUSH_TRANSACTION_OP = "hobots.run.flush";
|
|
2017
2026
|
var MAX_STEP_MESSAGE_CHARS = 2e3;
|
|
2018
2027
|
function stepMessage(text) {
|
|
2019
2028
|
return truncate(scrubSecrets(text), MAX_STEP_MESSAGE_CHARS);
|
|
@@ -2235,6 +2244,60 @@ var Transaction = class {
|
|
|
2235
2244
|
this.name = name;
|
|
2236
2245
|
return this;
|
|
2237
2246
|
}
|
|
2247
|
+
/**
|
|
2248
|
+
* Envia já as steps raiz finalizadas (e todas as descendentes, fechando as que
|
|
2249
|
+
* ficaram abertas) como transactions parciais da mesma run (`op` hobots.run.flush,
|
|
2250
|
+
* `event_id` novo, até 200 steps cada) e as tira da memória. Steps raiz ainda abertas
|
|
2251
|
+
* ficam para o próximo flush ou para o `finish()`. É assim que um agente sempre
|
|
2252
|
+
* ligado (`start()`), cuja run não termina, entrega as etapas enquanto processa.
|
|
2253
|
+
* Devolve quantas steps foram enviadas.
|
|
2254
|
+
*/
|
|
2255
|
+
flush() {
|
|
2256
|
+
if (this.finished) return 0;
|
|
2257
|
+
const ready = /* @__PURE__ */ new Set();
|
|
2258
|
+
for (const step of this.steps) {
|
|
2259
|
+
if (step.parentStepId === this.stepId && step.endTimestamp) ready.add(step.stepId);
|
|
2260
|
+
}
|
|
2261
|
+
if (ready.size === 0) return 0;
|
|
2262
|
+
const batch = [];
|
|
2263
|
+
const remaining = [];
|
|
2264
|
+
for (const step of this.steps) {
|
|
2265
|
+
if (ready.has(step.stepId) || ready.has(step.parentStepId)) {
|
|
2266
|
+
ready.add(step.stepId);
|
|
2267
|
+
batch.push(step);
|
|
2268
|
+
} else {
|
|
2269
|
+
remaining.push(step);
|
|
2270
|
+
}
|
|
2271
|
+
}
|
|
2272
|
+
for (const step of batch) step.finish();
|
|
2273
|
+
this.steps.splice(0, this.steps.length, ...remaining);
|
|
2274
|
+
if (this.client) {
|
|
2275
|
+
for (let i = 0; i < batch.length; i += MAX_STEPS) {
|
|
2276
|
+
const chunk = batch.slice(i, i + MAX_STEPS);
|
|
2277
|
+
const startTimestamp = chunk.reduce((min, step) => step.startTimestamp < min ? step.startTimestamp : min, chunk[0].startTimestamp);
|
|
2278
|
+
const status = chunk.some((step) => step.status === "error") ? "error" : "ok";
|
|
2279
|
+
this.client.sendTransaction(this.payload(uuid4(), FLUSH_TRANSACTION_OP, status, startTimestamp, nowISO(), chunk));
|
|
2280
|
+
}
|
|
2281
|
+
}
|
|
2282
|
+
return batch.length;
|
|
2283
|
+
}
|
|
2284
|
+
/** Entrega já (com teto) o que está na fila do transport — as transactions parciais inclusive. */
|
|
2285
|
+
async drain(timeoutMs) {
|
|
2286
|
+
await this.client?.flush(timeoutMs);
|
|
2287
|
+
}
|
|
2288
|
+
payload(eventId, op, status, startTimestamp, timestamp, steps) {
|
|
2289
|
+
return {
|
|
2290
|
+
event_id: eventId,
|
|
2291
|
+
name: this.name,
|
|
2292
|
+
op,
|
|
2293
|
+
status,
|
|
2294
|
+
start_timestamp: startTimestamp,
|
|
2295
|
+
timestamp,
|
|
2296
|
+
steps: steps.map((step) => step.toJSON()),
|
|
2297
|
+
tags: Object.keys(this.tags).length > 0 ? { ...this.tags } : void 0,
|
|
2298
|
+
run_id: this.runId
|
|
2299
|
+
};
|
|
2300
|
+
}
|
|
2238
2301
|
finish() {
|
|
2239
2302
|
if (this.finished) return;
|
|
2240
2303
|
this.finished = true;
|
|
@@ -2249,18 +2312,15 @@ var Transaction = class {
|
|
|
2249
2312
|
this.status
|
|
2250
2313
|
);
|
|
2251
2314
|
if (!this.client) return;
|
|
2252
|
-
const
|
|
2253
|
-
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
status
|
|
2257
|
-
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
run_id: this.runId
|
|
2262
|
-
};
|
|
2263
|
-
this.client.sendTransaction(payload);
|
|
2315
|
+
const steps = this.steps;
|
|
2316
|
+
let first = 0;
|
|
2317
|
+
while (steps.length - first > MAX_STEPS) {
|
|
2318
|
+
const chunk = steps.slice(first, first + MAX_STEPS);
|
|
2319
|
+
const status = chunk.some((step) => step.status === "error") ? "error" : "ok";
|
|
2320
|
+
this.client.sendTransaction(this.payload(uuid4(), FLUSH_TRANSACTION_OP, status, chunk[0].startTimestamp, endTimestamp, chunk));
|
|
2321
|
+
first += MAX_STEPS;
|
|
2322
|
+
}
|
|
2323
|
+
this.client.sendTransaction(this.payload(this.eventId, this.op, this.status, this.startTimestamp, endTimestamp, steps.slice(first)));
|
|
2264
2324
|
}
|
|
2265
2325
|
};
|
|
2266
2326
|
|
|
@@ -2965,6 +3025,7 @@ var hobots = Object.defineProperties({}, {
|
|
|
2965
3025
|
signal: getter("signal", () => neverAborts),
|
|
2966
3026
|
throwIfCanceled: method(() => resolve("throwIfCanceled")?.throwIfCanceled()),
|
|
2967
3027
|
sleep: method((ms) => resolve("sleep")?.sleep(ms) ?? sleep(ms)),
|
|
3028
|
+
flush: method((timeoutMs) => resolve("flush")?.flush(timeoutMs) ?? Promise.resolve()),
|
|
2968
3029
|
retry: method((fn, options) => {
|
|
2969
3030
|
const reporter = currentReporter();
|
|
2970
3031
|
return reporter ? reporter.context.retry(fn, options) : retryWithBackoff(fn, options);
|