hobots 6.0.0 → 6.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 +1 -0
- package/dist/index.cjs +76 -25
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +76 -25
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/utils.ts","../src/env.ts","../src/stacktrace.ts","../src/scrub.ts","../src/eventbuilder.ts","../src/transport.ts","../src/client.ts","../src/config.ts","../src/heartbeat.ts","../src/internal-handlers.ts","../src/instrument.ts","../src/machine.ts","../src/tasks/api.ts","../src/tasks/backoff.ts","../src/tasks/errors.ts","../src/tasks/attachments.ts","../src/tasks/run-context-store.ts","../src/retry.ts","../src/transaction.ts","../src/tasks/each.ts","../src/tasks/files.ts","../src/tasks/context.ts","../src/tasks/runner.ts","../src/tasks/agent.ts","../src/tasks/single-run.ts","../src/tasks/attached.ts","../src/tasks/item-columns.ts","../src/tasks/local.ts","../src/tasks/local-transport.ts","../src/tasks/local-run.ts","../src/tasks/registry.ts","../src/tasks/shutdown.ts","../src/runtime.ts","../src/hobots.ts","../src/index.ts"],"sourcesContent":["/** Injetada pelo `define` do tsup a partir da versão do package.json. */\ndeclare const __SDK_VERSION__: string | undefined;\n\nexport const SDK_NAME = 'hobots';\n/* v8 ignore start -- o `define` do tsup/vitest sempre injeta a versão; o fallback é só para builds sem define */\nexport const SDK_VERSION = typeof __SDK_VERSION__ === 'string' ? __SDK_VERSION__ : '0.0.0-dev';\n/* v8 ignore stop */\n\nexport function isNode(): boolean {\n return typeof process !== 'undefined' && typeof process.versions?.node === 'string';\n}\n\n/** uuid v4 sem hífens (32 hex). Fallback para contextos sem crypto.randomUUID. */\nexport function uuid4(): string {\n const cryptoRef = (globalThis as { crypto?: Crypto }).crypto;\n if (cryptoRef && typeof cryptoRef.randomUUID === 'function') {\n return cryptoRef.randomUUID().replace(/-/g, '');\n }\n if (cryptoRef && typeof cryptoRef.getRandomValues === 'function') {\n const bytes = cryptoRef.getRandomValues(new Uint8Array(16));\n bytes[6] = (bytes[6]! & 0x0f) | 0x40;\n bytes[8] = (bytes[8]! & 0x3f) | 0x80;\n return Array.from(bytes, b => b.toString(16).padStart(2, '0')).join('');\n }\n // último recurso (runtimes sem crypto algum) — ids aqui são só de correlação\n let out = '';\n for (let i = 0; i < 32; i++) {\n out += Math.floor(Math.random() * 16).toString(16);\n }\n return out;\n}\n\nexport function nowISO(): string {\n return new Date().toISOString();\n}\n\n/** Timers não devem segurar o processo Node aberto. */\nexport function unrefTimer(timer: unknown): void {\n (timer as { unref?: () => void } | undefined)?.unref?.();\n}\n\nexport function sleep(ms: number): Promise<void> {\n return new Promise(resolve => {\n const timer = setTimeout(resolve, ms);\n unrefTimer(timer);\n });\n}\n\n/**\n * Sleep que RESOLVE (não rejeita) quando `signal` aborta antes do prazo. Timer não\n * unref'd: quem espera assim está no meio de trabalho legítimo (ex.: abrindo a run\n * do modo start) e deve segurar o processo vivo.\n */\nexport function abortableSleep(ms: number, signal?: AbortSignal): Promise<void> {\n return new Promise(resolve => {\n if (signal?.aborted) {\n resolve();\n return;\n }\n const onAbort = (): void => {\n clearTimeout(timer);\n resolve();\n };\n const timer = setTimeout(() => {\n signal?.removeEventListener('abort', onAbort);\n resolve();\n }, ms);\n signal?.addEventListener('abort', onAbort, { once: true });\n });\n}\n\n/** Equal jitter: metade fixa + metade aleatória, evita thundering herd nos retries. */\nexport function jitter(baseMs: number): number {\n return Math.floor(baseMs / 2 + Math.random() * (baseMs / 2));\n}\n\nexport const TRUNCATION_SUFFIX = '… [truncado]';\n\nexport function truncate(value: string, max: number): string {\n return value.length > max ? `${value.slice(0, max)}${TRUNCATION_SUFFIX}` : value;\n}\n\n/**\n * Como `truncate`, mas o resultado (sufixo incluído) **cabe** em `max` — para os tetos do\n * servidor, onde um caractere a mais recusa o envelope inteiro.\n */\nexport function clip(value: string, max: number): string {\n if (value.length <= max) return value;\n return `${value.slice(0, Math.max(0, max - TRUNCATION_SUFFIX.length))}${TRUNCATION_SUFFIX}`;\n}\n\n/**\n * Converte qualquer valor para `string` sem lançar — usado nos pontos de entrada\n * de `hobots.*` que aceitam \"mensagem\" do usuário (log, attach, items, transaction)\n * e são documentados como \"nunca lança\": tipagem estática não impede alguém de\n * passar um `number`, um `Error` ou um objeto onde o contrato pede `string`.\n */\nexport function safeString(value: unknown): string {\n if (typeof value === 'string') return value;\n try {\n const json = JSON.stringify(value);\n if (json && json !== '{}') return json;\n } catch {\n // objetos circulares etc. caem no String()\n }\n return String(value);\n}\n\nexport const DEFAULT_RETRY_DELAYS_MS: readonly number[] = [1_000, 4_000, 16_000];\n\n/**\n * Executa `send` com retry em falha de rede/5xx/429 (respeitando Retry-After + jitter).\n * Devolve a Response tanto em ok quanto em 4xx≠429 — a rejeição definitiva é decisão\n * do chamador (o transport descarta logando; a API de tasks lança erro tipado).\n * Lança o último erro quando o ladder de retries esgota.\n */\nexport async function fetchWithRetry(\n send: () => Promise<Response>,\n options: {\n delays?: readonly number[];\n logger: Logger;\n label: string;\n /**\n * Códigos que normalmente seriam retriáveis mas que neste endpoint são PERMANENTES —\n * devolvidos como Response, sem insistir (anexos: 503 = instalação sem S3, 429 = cota\n * da execução; itens: 429 = cap por run). Insistir só faria o handler esperar a ladder.\n */\n noRetryStatuses?: readonly number[];\n /**\n * Cancelamento (ex.: `ctx.signal` da run): depois que dispara, a falha atual sobe na\n * hora — sem esperar o resto da ladder — e a espera entre tentativas é interrompida\n * sem disparar nova tentativa.\n */\n signal?: AbortSignal;\n }\n): Promise<Response> {\n const delays = options.delays ?? DEFAULT_RETRY_DELAYS_MS;\n const noRetry = options.noRetryStatuses ?? [];\n for (let attempt = 0; ; attempt++) {\n let retriable: unknown;\n let serverDelay: number | undefined;\n try {\n const response = await send();\n if (response.ok) return response;\n if (response.status >= 400 && response.status < 500 && response.status !== 429) return response;\n if (noRetry.includes(response.status)) return response;\n if (response.status === 429) serverDelay = retryAfterMs(response);\n retriable = new Error(`HTTP ${response.status}`);\n } catch (error) {\n retriable = error;\n }\n const failure = retriable instanceof Error ? retriable : new Error(String(retriable));\n const base = delays[attempt];\n if (base === undefined || options.signal?.aborted) throw failure;\n const delay = serverDelay ?? jitter(base);\n options.logger.warn(`${options.label}: falha (${String(retriable)}), retry em ${delay}ms`);\n await (options.signal ? abortableSleep(delay, options.signal) : sleep(delay));\n // abortado durante a espera: a falha atual sobe sem gastar mais uma requisição\n if (options.signal?.aborted) throw failure;\n }\n}\n\nconst MAX_RETRY_AFTER_MS = 60_000;\n\n/** Parse do header Retry-After (segundos ou HTTP-date), clampado a [0, 60s]. */\nexport function retryAfterMs(response: Response): number | undefined {\n const header = response.headers.get('retry-after');\n if (!header) return undefined;\n const seconds = Number(header);\n if (Number.isFinite(seconds)) {\n return Math.min(MAX_RETRY_AFTER_MS, Math.max(0, seconds * 1_000));\n }\n const date = Date.parse(header);\n if (Number.isNaN(date)) return undefined;\n return Math.min(MAX_RETRY_AFTER_MS, Math.max(0, date - Date.now()));\n}\n\n/**\n * Signal com timeout composável com um signal externo (stop/cancelamento).\n * Node 18 não tem AbortSignal.any — composição manual; chame cleanup() em finally\n * para não acumular listeners num signal externo reutilizado.\n */\nexport function withTimeoutSignal(timeoutMs: number, external?: AbortSignal): { signal: AbortSignal; cleanup: () => void } {\n const controller = new AbortController();\n const onAbort = (): void => controller.abort(external?.reason);\n if (external?.aborted) {\n onAbort();\n } else {\n external?.addEventListener('abort', onAbort, { once: true });\n }\n const timer = setTimeout(() => {\n controller.abort(Object.assign(new Error(`timeout após ${timeoutMs}ms`), { name: 'TimeoutError' }));\n }, timeoutMs);\n unrefTimer(timer);\n return {\n signal: controller.signal,\n cleanup: () => {\n clearTimeout(timer);\n external?.removeEventListener('abort', onAbort);\n },\n };\n}\n\nexport interface Logger {\n debug: (...args: unknown[]) => void;\n warn: (...args: unknown[]) => void;\n error: (...args: unknown[]) => void;\n}\n\nconst PREFIX = '[hobots]';\n\nexport function makeLogger(enabled: boolean, prefix: string = PREFIX): Logger {\n return {\n debug: (...args) => enabled && console.debug(colorize(prefix, 'gray'), ...args),\n warn: (...args) => enabled && console.warn(colorize(prefix, 'yellow'), ...args),\n error: (...args) => console.error(colorize(prefix, 'red'), ...args),\n };\n}\n\nconst ANSI = {\n reset: '\\x1b[0m',\n gray: '\\x1b[90m',\n cyan: '\\x1b[36m',\n yellow: '\\x1b[33m',\n red: '\\x1b[31m',\n green: '\\x1b[32m',\n} as const;\n\nfunction colorEnabled(): boolean {\n /* v8 ignore start -- ramo de browser: a suíte roda em Node e o isNode() interno não é mockável daqui */\n if (!isNode()) return false;\n /* v8 ignore stop */\n return Boolean(process.stdout?.isTTY) && !process.env.NO_COLOR;\n}\n\n/** Envolve `text` em código ANSI — vira no-op fora de um TTY Node (ou com NO_COLOR definido). */\nexport function colorize(text: string, color: keyof typeof ANSI): string {\n if (!colorEnabled()) return text;\n return `${ANSI[color]}${text}${ANSI.reset}`;\n}\n","import type { EnvironmentInput } from './environment-protocol';\nimport { isNode } from './utils';\n\nexport const INSTANCE_ID_ENV = 'HOBOTS_INSTANCE_ID';\nexport const ENVIRONMENT_ENV = 'HOBOTS_ENVIRONMENT';\nexport const RUN_ID_ENV = 'HOBOTS_RUN_ID';\n/** Modo local (teste sem a Central): `HOBOTS_LOCAL_RUN=1` — handler uma vez, sem rede, params de `HOBOTS_RUN_PARAMS`. */\nexport const LOCAL_RUN_ENV = 'HOBOTS_LOCAL_RUN';\n/** Params da execução no modo local: um objeto JSON (ausente/vazio = `{}`). */\nexport const RUN_PARAMS_ENV = 'HOBOTS_RUN_PARAMS';\n\nlet dotenvLoaded = false;\n\n/**\n * Carrega o `.env` da pasta de trabalho (`process.cwd()`) em `process.env`, uma vez por\n * processo: o bot não precisa de `dotenv` nem de `--env-file` para o SDK (e o próprio\n * código do bot) acharem `HOBOTS_CLIENT_SECRET` & cia. Usa o parser nativo do Node\n * (`process.loadEnvFile`, Node ≥ 20.12) — síncrono, porque `register()`/`start()` resolvem\n * as credenciais na hora. A env já definida no ambiente **vence** o arquivo. Sem `.env`\n * (ou em runtime sem `loadEnvFile`), não faz nada; erro de leitura vira um aviso que cita\n * só o código do erro, nunca o conteúdo do arquivo.\n */\nexport function loadDotenv(): void {\n if (dotenvLoaded) return;\n dotenvLoaded = true;\n if (!isNode() || typeof process.loadEnvFile !== 'function') return;\n try {\n process.loadEnvFile('.env');\n } catch (err) {\n const code = (err as { code?: unknown } | null)?.code;\n if (code === 'ENOENT') return;\n console.warn(`[hobots] não foi possível ler o .env da pasta de trabalho (${typeof code === 'string' ? code : 'erro desconhecido'}) — seguindo só com as variáveis do ambiente`);\n }\n}\n\n/** Só para testes: permite carregar o `.env` de novo. */\nexport function _resetDotenvForTesting(): void {\n dotenvLoaded = false;\n}\n\n/** instanceId da opção ou da env — sem os dois, `undefined` (o fallback é o hostname, assíncrono). */\nexport function resolveInstanceId(option: string | undefined): string | undefined {\n const fromOption = option?.trim();\n if (fromOption) return fromOption;\n if (typeof process === 'undefined' || !process.env) return undefined;\n return process.env[INSTANCE_ID_ENV]?.trim() || undefined;\n}\n\n/**\n * Run a que o register() se anexa (opção → env HOBOTS_RUN_ID). Sem as duas, `undefined`:\n * o agente segue no poll de sempre.\n */\nexport function resolveRunId(option: string | undefined): string | undefined {\n const fromOption = option?.trim();\n if (fromOption) return fromOption;\n if (typeof process === 'undefined' || !process.env) return undefined;\n return process.env[RUN_ID_ENV]?.trim() || undefined;\n}\n\n/** Modo local ligado (`HOBOTS_LOCAL_RUN=1`): sem Central, sem secret, sem rede. */\nexport function isLocalRun(): boolean {\n if (typeof process === 'undefined' || !process.env) return false;\n return process.env[LOCAL_RUN_ENV]?.trim() === '1';\n}\n\n/**\n * Params do modo local: JSON de `HOBOTS_RUN_PARAMS` (ausente ou vazio = `{}`). Lança com o\n * motivo quando o valor não é um objeto JSON válido — quem chama imprime e encerra com código 2.\n */\nexport function resolveLocalRunParams(): Record<string, unknown> {\n const raw = process.env[RUN_PARAMS_ENV]?.trim();\n if (!raw) return {};\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch {\n throw new Error(`${RUN_PARAMS_ENV} inválido: não é JSON válido`);\n }\n if (parsed === null || typeof parsed !== 'object' || Array.isArray(parsed)) {\n throw new Error(`${RUN_PARAMS_ENV} inválido: esperado um objeto JSON`);\n }\n return parsed as Record<string, unknown>;\n}\n\n/** environment da opção ou da env — sem os dois, `undefined` (quem decide o default 'production' é o Client). */\nexport function resolveEnvironmentOption(option: EnvironmentInput | undefined): EnvironmentInput | undefined {\n const fromOption = option?.trim();\n if (fromOption) return fromOption;\n if (typeof process === 'undefined' || !process.env) return undefined;\n return process.env[ENVIRONMENT_ENV]?.trim() || undefined;\n}\n\n/**\n * Último recurso para a identidade da instância: o hostname da máquina. Import dinâmico\n * de node:os (o bundle é neutro); fora de Node, 'browser'.\n */\nexport async function fallbackInstanceId(): Promise<string> {\n if (!isNode()) return 'browser';\n try {\n const os = await import('node:os');\n return os.hostname() || 'unknown-host';\n } catch {\n return 'unknown-host';\n }\n}\n","import type { StackFrame } from './protocol';\n\nconst MAX_FRAMES = 50;\n/** Teto do servidor para `filename` (zod). */\nconst MAX_FILENAME_CHARS = 1_024;\n\n// \" at fn (file:1:2)\" | \" at file:1:2\" | \" at async fn (file:1:2)\"\nconst FRAME_RE = /^\\s*at\\s+(?:async\\s+)?(?:(.+?)\\s+\\()?(.+?)\\)?$/;\nconst LOCATION_RE = /^(.*?):(\\d+):(\\d+)$/;\n\nfunction isInApp(filename: string | undefined): boolean {\n if (!filename) return false;\n if (filename.startsWith('node:')) return false;\n if (filename.startsWith('internal/')) return false;\n if (filename.includes('node_modules')) return false;\n if (filename === '<anonymous>') return false;\n return true;\n}\n\n/** Converte um `error.stack` do V8 em frames (ordem innermost-first, como o V8 imprime). */\nexport function parseStacktrace(stack: string | undefined | null): StackFrame[] {\n if (!stack) return [];\n\n const frames: StackFrame[] = [];\n for (const line of stack.split('\\n')) {\n if (frames.length >= MAX_FRAMES) break;\n const match = FRAME_RE.exec(line);\n if (!match || !line.trimStart().startsWith('at ')) continue;\n\n const [, fn, location] = match;\n /* v8 ignore start -- o grupo 2 do FRAME_RE é obrigatório: `location` nunca é undefined após o match */\n const loc = LOCATION_RE.exec(location ?? '');\n /* v8 ignore stop */\n const filename = loc ? loc[1] : location;\n frames.push({\n function: fn || '<anonymous>',\n filename: filename ? filename.slice(0, MAX_FILENAME_CHARS) : undefined,\n lineno: loc?.[2] ? Number(loc[2]) : undefined,\n colno: loc?.[3] ? Number(loc[3]) : undefined,\n in_app: isInApp(filename),\n });\n }\n return frames;\n}\n","/**\n * Redação de segredos em texto que sai do processo (mensagens de erro, stacks,\n * logs de run). Padrões conservadores — falso positivo é preferível a vazar\n * uma credencial para o painel.\n */\nconst SECRET_PATTERNS: ReadonlyArray<readonly [RegExp, string]> = [\n // client secret da Hobots\n [/hb_[a-f0-9]{16,}/gi, '[REDACTED]'],\n // tokens bearer em headers/mensagens\n [/\\b(authorization:?\\s*)?bearer\\s+[a-z0-9._~+/=-]{8,}/gi, 'Bearer [REDACTED]'],\n // chaves no formato sk-… (OpenAI e afins)\n [/\\bsk-[a-z0-9_-]{16,}\\b/gi, '[REDACTED]'],\n // credenciais embutidas em URL (https://user:pass@host)\n [/\\/\\/[^/\\s:@]+:[^/\\s@]+@/g, '//[REDACTED]@'],\n];\n\nexport function scrubSecrets(text: string): string {\n let out = text;\n for (const [pattern, replacement] of SECRET_PATTERNS) {\n out = out.replace(pattern, replacement);\n }\n return out;\n}\n","import type { EventPayload, EventType } from './protocol';\nimport { parseStacktrace } from './stacktrace';\nimport { scrubSecrets } from './scrub';\nimport { nowISO, safeString, truncate, uuid4 } from './utils';\n\n/** Teto do servidor para `exception.value` (zod). */\nexport const MAX_EXCEPTION_VALUE_CHARS = 8_192;\n\nexport function eventFromException(error: unknown, type: EventType = 'error'): EventPayload {\n let exceptionType: string;\n let value: string;\n let frames = [] as ReturnType<typeof parseStacktrace>;\n\n if (error instanceof Error) {\n exceptionType = error.name || 'Error';\n value = truncate(scrubSecrets(error.message), MAX_EXCEPTION_VALUE_CHARS);\n frames = parseStacktrace(error.stack);\n } else {\n exceptionType = 'NonError';\n value = truncate(scrubSecrets(safeString(error)), MAX_EXCEPTION_VALUE_CHARS);\n }\n\n return {\n event_id: uuid4(),\n timestamp: nowISO(),\n type,\n exception: {\n type: exceptionType,\n value,\n ...(frames.length > 0 ? { stacktrace: { frames } } : {}),\n },\n };\n}\n","import type { Envelope, EnvelopeItem } from './protocol';\nimport { SDK_NAME, SDK_VERSION, fetchWithRetry, nowISO, sleep, unrefTimer, type Logger } from './utils';\nimport { WIRE_LIMITS } from './wire-limits';\n\nconst REQUEST_TIMEOUT_MS = 10_000;\nconst DEFAULT_FLUSH_INTERVAL_MS = 2_000;\nconst DEFAULT_MAX_BATCH_SIZE = 10;\nconst DEFAULT_MAX_QUEUE_SIZE = 200;\n/**\n * Teto de itens por envelope — espelha o `.max(50)` de `envelopeSchema.items`\n * (apps/api/lib/ingest/schemas.ts). Acima disso a API responde 422 e o envelope é\n * descartado sem retry, então a fila é fatiada em envelopes deste tamanho antes de enviar.\n * Ao mudar um dos dois lados, mude o outro.\n */\nconst MAX_ITEMS_PER_ENVELOPE = WIRE_LIMITS.MAX_ITEMS_PER_ENVELOPE;\n\nexport interface TransportOptions {\n endpoint: string;\n /** Chave secreta do agente — enviada como Authorization: Bearer */\n key: string;\n logger: Logger;\n flushIntervalMs?: number;\n maxBatchSize?: number;\n maxQueueSize?: number;\n}\n\n/** Fila em memória com batch + retry. Envia envelopes via fetch (Node 18+/browser). */\nexport class Transport {\n private readonly endpoint: string;\n private readonly key: string;\n private readonly logger: Logger;\n private readonly flushIntervalMs: number;\n private readonly maxBatchSize: number;\n private readonly maxQueueSize: number;\n\n private buffer: EnvelopeItem[] = [];\n private timer: ReturnType<typeof setTimeout> | undefined;\n private pending = new Set<Promise<void>>();\n private closed = false;\n\n constructor(options: TransportOptions) {\n this.endpoint = options.endpoint;\n this.key = options.key;\n this.logger = options.logger;\n this.flushIntervalMs = options.flushIntervalMs ?? DEFAULT_FLUSH_INTERVAL_MS;\n this.maxBatchSize = options.maxBatchSize ?? DEFAULT_MAX_BATCH_SIZE;\n this.maxQueueSize = options.maxQueueSize ?? DEFAULT_MAX_QUEUE_SIZE;\n }\n\n enqueue(item: EnvelopeItem): void {\n if (this.closed) {\n this.logger.warn('transport fechado, item descartado:', item.type);\n return;\n }\n if (this.buffer.length >= this.maxQueueSize) {\n // nunca descarta heartbeat: um burst de erros não pode derrubar a presença —\n // o servidor marcaria offline um agente vivo (e gritando)\n const dropIndex = this.buffer.findIndex(queued => queued.type !== 'heartbeat');\n this.buffer.splice(dropIndex === -1 ? 0 : dropIndex, 1);\n this.logger.warn('fila cheia, item mais antigo descartado');\n }\n this.buffer.push(item);\n\n if (this.buffer.length >= this.maxBatchSize) {\n void this.flushBuffer();\n } else {\n this.schedule();\n }\n }\n\n private schedule(): void {\n if (this.timer) return;\n this.timer = setTimeout(() => {\n this.timer = undefined;\n void this.flushBuffer();\n }, this.flushIntervalMs);\n unrefTimer(this.timer);\n }\n\n private flushBuffer(): Promise<void> {\n if (this.timer) {\n clearTimeout(this.timer);\n this.timer = undefined;\n }\n if (this.buffer.length === 0) return Promise.resolve();\n\n // maxBatchSize decide *quando* flushar, não quanto cabe num envelope: um burst de\n // captures (ou uma janela de rede ruim em que a fila cresceu até maxQueueSize) junta\n // mais itens do que a API aceita, então quebra em lotes de MAX_ITEMS_PER_ENVELOPE.\n const taken = this.buffer.splice(0, this.buffer.length);\n const sends: Promise<void>[] = [];\n for (let offset = 0; offset < taken.length; offset += MAX_ITEMS_PER_ENVELOPE) {\n sends.push(this.send(taken.slice(offset, offset + MAX_ITEMS_PER_ENVELOPE)));\n }\n return Promise.all(sends).then(() => undefined);\n }\n\n /** Registra o envio em `this.pending` para que `flush()` aguarde todos os envelopes. */\n private send(items: EnvelopeItem[]): Promise<void> {\n const envelope: Envelope = {\n sdk: { name: SDK_NAME, version: SDK_VERSION },\n sent_at: nowISO(),\n items,\n };\n\n const request: Promise<void> = this.sendWithRetry(envelope).finally(() => {\n this.pending.delete(request);\n });\n this.pending.add(request);\n return request;\n }\n\n private async sendWithRetry(envelope: Envelope): Promise<void> {\n let response: Response;\n try {\n response = await fetchWithRetry(\n () =>\n fetch(this.endpoint, {\n redirect: 'error',\n method: 'POST',\n headers: { 'content-type': 'application/json', authorization: `Bearer ${this.key}` },\n body: JSON.stringify(envelope),\n signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS),\n }),\n { logger: this.logger, label: 'envio de envelope' }\n );\n } catch (error) {\n this.logger.error('envelope descartado após retries:', error);\n return;\n }\n if (response.ok) {\n this.logger.debug(`envelope enviado (${envelope.items.length} itens)`);\n return;\n }\n // 4xx (exceto 429) não é recuperável — descarta sem retry\n this.logger.error(`envelope rejeitado (HTTP ${response.status}), descartado (${envelope.items.length} itens)`);\n }\n\n /** Envia o que estiver na fila e aguarda envios em andamento (até timeoutMs). */\n async flush(timeoutMs = 5_000): Promise<boolean> {\n void this.flushBuffer();\n const all = Promise.allSettled([...this.pending]).then(() => true);\n return Promise.race([all, sleep(timeoutMs).then(() => false)]);\n }\n\n async close(timeoutMs = 5_000): Promise<boolean> {\n const result = await this.flush(timeoutMs);\n this.closed = true;\n return result;\n }\n}\n","import type { EnvironmentInput, EventPayload, HeartbeatPayload, StepData, TransactionPayload } from './protocol';\nimport type { CaptureHint } from './types';\nimport type { ResolvedConfig } from './config';\nimport { eventFromException } from './eventbuilder';\nimport type { MachineSampler } from './machine';\nimport { Transport } from './transport';\nimport { SDK_NAME, SDK_VERSION, clip, isNode, makeLogger, truncate, type Logger } from './utils';\n\n// Limites do servidor (zod). Um único campo acima do limite devolve 422 para o\n// envelope INTEIRO — que pode carregar até 50 itens. Vale truncar no cliente.\nexport const MAX_TAG_VALUE_CHARS = 512;\nexport const MAX_FINGERPRINT_ITEMS = 10;\nexport const MAX_FINGERPRINT_ITEM_CHARS = 255;\nexport const MAX_TRANSACTION_NAME_CHARS = 500;\nexport const MAX_STEPS = 200;\n/** Teto do nome da etapa (`description`) — acima disso o envelope inteiro era recusado. */\nexport const MAX_STEP_DESCRIPTION_CHARS = 2_048;\n/** Teto do `op` de uma etapa. */\nexport const MAX_STEP_OP_CHARS = 255;\n\nfunction clipTags(tags: Record<string, string>): Record<string, string> {\n return Object.fromEntries(Object.entries(tags).map(([key, value]) => [key, truncate(String(value), MAX_TAG_VALUE_CHARS)]));\n}\n\n/** Tetos do servidor por etapa: uma etapa com nome maior fazia o envelope inteiro ser recusado (422). */\nfunction clipStep(step: StepData): StepData {\n return {\n ...step,\n ...(step.op ? { op: clip(step.op, MAX_STEP_OP_CHARS) } : {}),\n ...(step.description ? { description: clip(step.description, MAX_STEP_DESCRIPTION_CHARS) } : {}),\n };\n}\n\nfunction clipFingerprint(fingerprint: string[] | undefined): string[] | undefined {\n if (fingerprint === undefined) return undefined;\n return fingerprint.slice(0, MAX_FINGERPRINT_ITEMS).map(item => truncate(String(item), MAX_FINGERPRINT_ITEM_CHARS));\n}\n\n/** Opções de telemetria resolvidas pelo runtime a partir do primeiro register()/start(). */\nexport interface ClientOptions {\n environment?: EnvironmentInput;\n release?: string;\n /** Tags aplicadas a todos os eventos e transactions */\n tags?: Record<string, string>;\n debug?: boolean;\n /**\n * O erro final que escapou do handler de uma run também vira issue (além de falhar a run).\n * Ligado pelo runtime junto com `captureUnhandled`; desligado no client cru (testes).\n */\n captureRunErrors?: boolean;\n /** Knobs internos do transport (testes) — não fazem parte da API pública */\n flushIntervalMs?: number;\n maxBatchSize?: number;\n}\n\n// erros já enviados como issue: o runner não reenvia o que o bot capturou e relançou\nconst captured = new WeakSet<object>();\n\n/** O erro já foi enviado por captureException (só objetos são marcáveis). */\nexport function wasCaptured(error: unknown): boolean {\n return typeof error === 'object' && error !== null && captured.has(error);\n}\n\nfunction runtimeContexts(): Record<string, Record<string, unknown>> {\n if (isNode()) {\n return {\n runtime: { name: 'node', version: process.version },\n os: { name: process.platform, arch: process.arch },\n };\n }\n return { runtime: { name: 'browser' } };\n}\n\nexport class Client {\n readonly logger: Logger;\n /** Eco de lifecycle (Transaction.emit) e afins só imprimem no terminal com debug ligado. */\n readonly debug: boolean;\n // campos privados + getters de protótipo: o clientSecret não aparece em\n // JSON.stringify/serialização enumerável do Client (ex.: um objeto capturado\n // que referencie o client), mas client.options/config seguem funcionando\n readonly #options: ClientOptions;\n readonly #config: ResolvedConfig;\n private readonly transport: Transport;\n private machine: MachineSampler | undefined;\n\n constructor(options: ClientOptions, config: ResolvedConfig) {\n this.#options = options;\n this.debug = !!options.debug;\n this.logger = makeLogger(this.debug);\n this.#config = config;\n this.transport = new Transport({\n endpoint: this.#config.ingestEndpoint,\n key: this.#config.key,\n logger: this.logger,\n flushIntervalMs: options.flushIntervalMs,\n maxBatchSize: options.maxBatchSize,\n });\n }\n\n get options(): ClientOptions {\n return this.#options;\n }\n\n get config(): ResolvedConfig {\n return this.#config;\n }\n\n /** Sampler de recursos da máquina — cada evento passa a levar `contexts.machine`. */\n attachMachineSampler(sampler: MachineSampler | undefined): void {\n this.machine = sampler;\n }\n\n /** Serialização explícita nunca inclui o secret. */\n toJSON(): Record<string, unknown> {\n return { sdk: SDK_NAME, version: SDK_VERSION, baseUrl: this.#config.baseUrl };\n }\n\n [Symbol.for('nodejs.util.inspect.custom')](): string {\n return `Client { baseUrl: '${this.#config.baseUrl}' }`;\n }\n\n /** `contexts` é interno ao SDK (ex.: `contexts.run` com o print do captureException) — o evento ainda pode sobrescrever. */\n captureException(error: unknown, hint?: CaptureHint, contexts?: Record<string, Record<string, unknown>>): string {\n if (typeof error === 'object' && error !== null) captured.add(error);\n return this.captureEvent(eventFromException(error, hint?.type ?? 'error'), hint, contexts);\n }\n\n captureEvent(event: EventPayload, hint?: CaptureHint, contexts?: Record<string, Record<string, unknown>>): string {\n const final = this.prepareEvent(contexts ? { ...event, contexts: { ...contexts, ...event.contexts } } : event, hint);\n this.transport.enqueue({ type: 'event', payload: final });\n return final.event_id;\n }\n\n private prepareEvent(event: EventPayload, hint: CaptureHint | undefined): EventPayload {\n const tags = { ...this.options.tags, ...event.tags, ...hint?.tags };\n const extra = { ...event.extra, ...hint?.extra };\n // como estava a máquina no momento do erro — o evento ainda pode sobrescrever.\n // `contexts` é Record<string, Record<string, unknown>>; o snapshot tipado entra como tal.\n const sampled = this.machine?.sample();\n const machine: Record<string, Record<string, unknown>> = sampled ? { machine: sampled as unknown as Record<string, unknown> } : {};\n\n return {\n ...event,\n type: hint?.type ?? event.type ?? 'error',\n release: event.release ?? this.options.release,\n environment: this.resolveEnvironment(event.environment),\n tags: Object.keys(tags).length > 0 ? clipTags(tags) : undefined,\n extra: Object.keys(extra).length > 0 ? extra : undefined,\n contexts: { ...runtimeContexts(), ...machine, ...event.contexts },\n fingerprint: clipFingerprint(hint?.fingerprint ?? event.fingerprint),\n };\n }\n\n sendTransaction(payload: TransactionPayload): void {\n let steps = payload.steps;\n if (steps.length > MAX_STEPS) {\n this.logger.warn(`transaction com ${steps.length} etapas — enviando as primeiras ${MAX_STEPS}`);\n steps = steps.slice(0, MAX_STEPS);\n }\n steps = steps.map(clipStep);\n this.transport.enqueue({\n type: 'transaction',\n payload: {\n ...payload,\n name: clip(payload.name || '(sem nome)', MAX_TRANSACTION_NAME_CHARS),\n steps,\n release: payload.release ?? this.options.release,\n environment: this.resolveEnvironment(payload.environment),\n tags: clipTags({ ...this.options.tags, ...payload.tags }),\n },\n });\n }\n\n sendHeartbeat(payload: HeartbeatPayload): void {\n this.transport.enqueue({\n type: 'heartbeat',\n payload: {\n ...payload,\n release: payload.release ?? this.options.release,\n // o ambiente viaja no beat: é assim que a instância se classifica no app\n environment: this.resolveEnvironment(payload.environment),\n },\n });\n }\n\n /**\n * Ambiente do item: o dele, senão o das opções, senão produção. Centralizado\n * porque evento, transaction e heartbeat precisam responder igual — o servidor\n * normaliza apelidos legados, então aqui basta repassar.\n */\n private resolveEnvironment(value: EnvironmentInput | undefined): EnvironmentInput {\n return value ?? this.options.environment ?? 'production';\n }\n\n flush(timeoutMs?: number): Promise<boolean> {\n return this.transport.flush(timeoutMs);\n }\n\n close(timeoutMs?: number): Promise<boolean> {\n return this.transport.close(timeoutMs);\n }\n}\n","/** API oficial da Hobots — o SDK sempre fala com ela em produção. */\nexport const DEFAULT_BASE_URL = 'https://api2.hobots.app';\n\nexport interface ResolvedConfig {\n /** Client Secret do agente (enviado como Authorization: Bearer, nunca na URL) */\n key: string;\n baseUrl: string;\n /** Ingestão de telemetria: <baseUrl>/v1/ingest */\n ingestEndpoint: string;\n /** API de execuções (poll, runs, itens, anexos): <baseUrl>/v1/runs */\n runsBaseUrl: string;\n}\n\ninterface ConfigInput {\n /** Ausente: lê a env HOBOTS_CLIENT_SECRET (como as libs da AWS fazem com as credenciais). */\n clientSecret?: string;\n}\n\nexport const CLIENT_SECRET_ENV = 'HOBOTS_CLIENT_SECRET';\n\nfunction envClientSecret(): string | undefined {\n if (typeof process === 'undefined' || !process.env) return undefined;\n return process.env[CLIENT_SECRET_ENV]?.trim() || undefined;\n}\n\n/** hb_<64 hex>. */\nconst SECRET_PATTERN = /^hb_[a-f0-9]{64}$/i;\n\n/**\n * Override de desenvolvimento via env HOBOTS_API_URL — a única forma de apontar\n * o SDK para outro host. Em produção a URL é sempre a API oficial.\n */\nfunction envBaseUrl(): string | undefined {\n // browser: `process` pode não existir\n if (typeof process === 'undefined' || !process.env) return undefined;\n return process.env.HOBOTS_API_URL?.trim() || undefined;\n}\n\nfunction isLoopbackHost(hostname: string): boolean {\n return (\n hostname === 'localhost' ||\n hostname.endsWith('.localhost') ||\n hostname.startsWith('127.') ||\n hostname === '[::1]' ||\n hostname === '::1' ||\n hostname === '0.0.0.0'\n );\n}\n\n/**\n * Valida a baseUrl sem nunca ecoar o valor completo em erro/log — a env pode\n * conter credenciais embutidas por engano.\n */\nfunction validateBaseUrl(raw: string, prefix: string): string {\n let url: URL;\n try {\n url = new URL(raw);\n } catch {\n throw new Error(`${prefix} HOBOTS_API_URL inválida — esperado URL http(s), ex.: http://localhost:3001`);\n }\n if (url.protocol !== 'http:' && url.protocol !== 'https:') {\n throw new Error(`${prefix} HOBOTS_API_URL com esquema \"${url.protocol}\" não suportado — use http(s)`);\n }\n if (url.username || url.password) {\n throw new Error(`${prefix} HOBOTS_API_URL não pode conter credenciais na URL — a autenticação é só pelo Client Secret`);\n }\n // http só em loopback: para um host remoto o Client Secret iria em claro na rede — recusa, não avisa\n if (url.protocol === 'http:' && !isLoopbackHost(url.hostname)) {\n throw new Error(`${prefix} HOBOTS_API_URL usa http para o host remoto \"${url.hostname}\" — o Client Secret trafegaria sem TLS; use https`);\n }\n return raw.replace(/\\/+$/, '');\n}\n\n/** Resolve o clientSecret (opção ou env) nos endpoints de telemetria e de execuções. */\nexport function resolveConfig(options: ConfigInput = {}, prefix = '[hobots]'): ResolvedConfig {\n const fromOption = options.clientSecret?.trim();\n const key = fromOption || envClientSecret();\n const origin = fromOption ? 'clientSecret' : `env ${CLIENT_SECRET_ENV}`;\n if (!key) {\n throw new Error(\n `${prefix} Client Secret ausente — defina a env ${CLIENT_SECRET_ENV} (ou passe clientSecret nas opções do register/start); copie o Client Secret na Central: abra o agente → Configurações → agente → aba credenciais`\n );\n }\n if (!SECRET_PATTERN.test(key)) {\n // nunca incluir o valor na mensagem — só o tamanho e a origem, como pista de diagnóstico\n throw new Error(\n `${prefix} ${origin} com formato inválido (${key.length} caracteres) — esperado \"hb_\" + 64 hex; copie o Client Secret na Central: abra o agente → Configurações → agente → aba credenciais`\n );\n }\n\n const baseUrl = validateBaseUrl(envBaseUrl() ?? DEFAULT_BASE_URL, prefix);\n\n return {\n key,\n baseUrl,\n ingestEndpoint: `${baseUrl}/v1/ingest`,\n runsBaseUrl: `${baseUrl}/v1/runs`,\n };\n}\n","import type { Client } from './client';\nimport type { MachineSampler } from './machine';\nimport { nowISO, unrefTimer } from './utils';\nimport { WIRE_LIMITS } from './wire-limits';\n\nconst DEFAULT_INTERVAL_MS = WIRE_LIMITS.HEARTBEAT_DEFAULT_INTERVAL_MS;\n// faixa aceita pelo servidor para interval_ms (WIRE_LIMITS; a api aplica a mesma) — o valor\n// REPORTADO é clampado para o envelope não ser rejeitado; a cadência real fica como configurada.\n// Janelas maiores que 15 min são caso para o timeout de presença do agente, no app.\nconst MIN_REPORTED_INTERVAL_MS = WIRE_LIMITS.HEARTBEAT_MIN_INTERVAL_MS;\nconst MAX_REPORTED_INTERVAL_MS = WIRE_LIMITS.HEARTBEAT_MAX_INTERVAL_MS;\n\nexport interface HeartbeatOptions {\n /** Intervalo entre batimentos. Default: 30_000 */\n intervalMs?: number;\n /** Nome amigável exibido no dashboard. Default: o instanceId */\n name?: string;\n metadata?: Record<string, unknown>;\n /**\n * Timer ref'd: o heartbeat segura o processo vivo até stop(). É o que mantém um bot\n * no modo start rodando depois que o handler retorna — \"o SDK fica sempre vivo\".\n * Default: false (unref'd — não segura o processo).\n */\n keepAlive?: boolean;\n}\n\n/** Batimento periódico \"estou vivo\" — o servidor marca a instância offline quando ele para. */\nexport class Heartbeat {\n private readonly intervalMs: number;\n private readonly instanceId: string;\n private readonly name: string;\n private readonly metadata?: Record<string, unknown>;\n private readonly keepAlive: boolean;\n private timer: ReturnType<typeof setTimeout> | undefined;\n\n constructor(\n private readonly client: Client,\n options: HeartbeatOptions = {},\n instanceId: string,\n private readonly sampler?: MachineSampler\n ) {\n this.intervalMs = options.intervalMs ?? DEFAULT_INTERVAL_MS;\n this.instanceId = instanceId;\n this.name = options.name ?? instanceId;\n this.metadata = options.metadata;\n this.keepAlive = options.keepAlive ?? false;\n }\n\n start(): void {\n if (this.timer) return;\n this.beat();\n this.schedule();\n }\n\n /** Jitter de ±10%: uma frota iniciada junto não sincroniza todos os beats no mesmo segundo. */\n private schedule(): void {\n this.timer = setTimeout(\n () => {\n this.beat();\n this.schedule();\n },\n this.intervalMs * (0.9 + Math.random() * 0.2)\n );\n if (!this.keepAlive) unrefTimer(this.timer);\n }\n\n stop(): void {\n if (this.timer) {\n clearTimeout(this.timer);\n this.timer = undefined;\n }\n }\n\n private beat(): void {\n this.client.sendHeartbeat({\n instance_id: this.instanceId,\n name: this.name,\n interval_ms: Math.min(Math.max(this.intervalMs, MIN_REPORTED_INTERVAL_MS), MAX_REPORTED_INTERVAL_MS),\n timestamp: nowISO(),\n metadata: this.metadata,\n // recursos da máquina a cada beat — a série da instância no app\n machine: this.sampler?.sample(),\n });\n }\n}\n","import { sleep } from './utils';\n\n/**\n * Coordenação entre os handlers de processo do SDK (instrument + tasks/shutdown):\n * marca os listeners internos para que a checagem de \"o programa tem handler próprio?\"\n * não conte os nossos, e agrega os reportes de emergência que o exit precisa aguardar.\n */\nconst INTERNAL = Symbol.for('hobots.sdk.internalListener');\n\ntype Marked = { [INTERNAL]?: true };\n\nexport function markInternal<T extends (...args: never[]) => unknown>(listener: T): T {\n (listener as Marked)[INTERNAL] = true;\n return listener;\n}\n\n/** Listeners do programa (não-SDK) para o evento — decide se o SDK preserva o exit default. */\nexport function externalListenerCount(event: string): number {\n const listeners = process.listeners(event as 'uncaughtException');\n return listeners.filter(listener => !(listener as Marked)[INTERNAL]).length;\n}\n\nconst emergencyTasks: Promise<unknown>[] = [];\n\n/** Reporte best-effort em voo (ex: run → AgentTerminated) que um exit iminente deve aguardar. */\nexport function addEmergencyTask(task: Promise<unknown>): void {\n emergencyTasks.push(task);\n // sai da lista ao resolver/rejeitar: um processo longo não acumula promises já encerradas\n const forget = (): void => {\n const index = emergencyTasks.indexOf(task);\n /* v8 ignore start -- defensivo: cada push tem exatamente um forget, a tarefa sempre está na lista */\n if (index !== -1) emergencyTasks.splice(index, 1);\n /* v8 ignore stop */\n };\n task.then(forget, forget);\n}\n\n/** Apenas para testes: quantas tarefas ainda estão pendentes. */\nexport function _pendingEmergencyTasksForTesting(): number {\n return emergencyTasks.length;\n}\n\nexport async function awaitEmergencyTasks(capMs: number): Promise<void> {\n if (emergencyTasks.length === 0) return;\n await Promise.race([Promise.allSettled(emergencyTasks), sleep(capMs)]);\n}\n","import type { Client } from './client';\nimport { awaitEmergencyTasks, externalListenerCount, markInternal } from './internal-handlers';\nimport { isNode } from './utils';\n\nconst EMERGENCY_REPORT_CAP_MS = 3_000;\n\nlet installed = false;\n\n/** O tasks/shutdown consulta para saber se o exit de uncaughtException já tem dono. */\nexport function hasInstalledGlobalHandlers(): boolean {\n return installed;\n}\n\n/**\n * Registra handlers globais de erro e devolve a função que os remove.\n * Node: preserva a semântica padrão — após capturar e flushar um uncaughtException,\n * o processo encerra com código 1 (a menos que o programa tenha handler próprio).\n */\nexport function installGlobalHandlers(client: Client): () => void {\n if (installed) return () => undefined;\n installed = true;\n\n if (isNode()) {\n const onUncaught = markInternal((error: Error) => {\n client.captureException(error, { type: 'fatal', tags: { mechanism: 'uncaughtException' } });\n void client.flush(2_000).then(async () => {\n // conta só handlers do programa — os do próprio SDK (este e o de tasks) não\n // impedem o exit default\n if (externalListenerCount('uncaughtException') === 0) {\n // aguarda o reporte de emergência do agente de tasks (runs → AgentTerminated), se houver\n await awaitEmergencyTasks(EMERGENCY_REPORT_CAP_MS);\n console.error(error);\n process.exit(1);\n }\n });\n });\n\n const onRejection = markInternal((reason: unknown) => {\n client.captureException(reason, { type: 'error', tags: { mechanism: 'unhandledRejection' } });\n // fetch em andamento segura o processo aberto até o envio terminar\n void client.flush(2_000);\n });\n\n // rede de segurança: envia o que restou na fila quando o event loop esvazia\n const onBeforeExit = markInternal(() => {\n void client.flush(2_000);\n });\n\n process.on('uncaughtException', onUncaught);\n process.on('unhandledRejection', onRejection);\n process.on('beforeExit', onBeforeExit);\n\n return () => {\n process.off('uncaughtException', onUncaught);\n process.off('unhandledRejection', onRejection);\n process.off('beforeExit', onBeforeExit);\n installed = false;\n };\n }\n\n if (typeof window !== 'undefined') {\n const onError = (event: ErrorEvent): void => {\n client.captureException(event.error ?? event.message, { tags: { mechanism: 'onerror' } });\n };\n const onRejection = (event: PromiseRejectionEvent): void => {\n client.captureException(event.reason, { tags: { mechanism: 'onunhandledrejection' } });\n };\n const onPageHide = (): void => {\n void client.flush(1_000);\n };\n window.addEventListener('error', onError);\n window.addEventListener('unhandledrejection', onRejection);\n window.addEventListener('pagehide', onPageHide);\n\n return () => {\n window.removeEventListener('error', onError);\n window.removeEventListener('unhandledrejection', onRejection);\n window.removeEventListener('pagehide', onPageHide);\n installed = false;\n };\n }\n\n return () => {\n installed = false;\n };\n}\n\n/** Apenas para testes internos. */\nexport function resetGlobalHandlersForTesting(): void {\n installed = false;\n}\n","import type { MachineSnapshot } from './machine-protocol';\nimport { isNode, nowISO, type Logger } from './utils';\n\ntype OsModule = typeof import('node:os');\n/** `fs.statfsSync` só existe a partir do Node 18.15 — tipado à parte para não depender da versão dos @types. */\ntype StatFs = { bsize: number; blocks: number; bavail: number };\ntype FsModule = { statfsSync?: (path: string) => StatFs };\n\n/** Janela mínima entre duas leituras de CPU: abaixo disso o delta é ruído e reutilizamos a última média. */\nconst MIN_CPU_WINDOW_MS = 1_000;\n\ninterface CpuTotals {\n busy: number;\n total: number;\n}\n\nconst round1 = (value: number): number => Math.round(value * 10) / 10;\nconst clampPercent = (value: number): number => Math.min(100, Math.max(0, value));\n\n/**\n * Coleta CPU/memória/disco da máquina e do processo — só em Node (no browser é no-op).\n *\n * Os módulos `node:*` entram por import dinâmico (o bundle é `platform: neutral`), e\n * `sample()` é síncrono e barato: `os.cpus()` + `statfsSync` + `process.memoryUsage()`.\n * Nunca lança — telemetria de recurso não pode derrubar o bot nem o capture de um erro.\n */\nexport class MachineSampler {\n private os: OsModule | undefined;\n private fs: FsModule | undefined;\n private ready = false;\n\n private prevCpu: CpuTotals | undefined;\n private prevProcessCpu: NodeJS.CpuUsage | undefined;\n private prevAt = 0;\n private lastCpuPercent: number | null = null;\n private lastProcessCpuPercent: number | null = null;\n\n constructor(\n private readonly instanceId: string,\n private readonly logger: Logger\n ) {}\n\n /** Carrega os módulos e tira a leitura-base de CPU (a primeira amostra ainda sai com cpu_percent null). */\n async start(): Promise<void> {\n if (!isNode()) return;\n try {\n this.os = await import('node:os');\n this.fs = (await import('node:fs')) as unknown as FsModule;\n this.prevCpu = this.cpuTotals();\n this.prevProcessCpu = process.cpuUsage();\n this.prevAt = Date.now();\n this.ready = true;\n } catch (error) {\n this.logger.debug('métricas de máquina indisponíveis neste runtime', error);\n }\n }\n\n sample(): MachineSnapshot | undefined {\n if (!this.ready || !this.os) return undefined;\n try {\n const os = this.os;\n const cpuCount = Math.max(1, os.cpus().length);\n this.updateCpu(cpuCount);\n\n const snapshot: MachineSnapshot = {\n sampled_at: nowISO(),\n instance_id: this.instanceId,\n hostname: os.hostname(),\n os: process.platform,\n arch: process.arch,\n cpu_count: cpuCount,\n cpu_percent: this.lastCpuPercent,\n process: {\n pid: process.pid,\n uptime_s: Math.round(process.uptime()),\n cpu_percent: this.lastProcessCpuPercent,\n },\n source: 'stdlib',\n };\n\n // load average só faz sentido em POSIX — no Windows o Node devolve [0,0,0]\n if (process.platform !== 'win32') {\n const load = os.loadavg()[0];\n if (typeof load === 'number' && Number.isFinite(load)) snapshot.load_1 = round1(load);\n }\n\n const memTotal = os.totalmem();\n const memFree = os.freemem();\n if (memTotal > 0) {\n snapshot.mem_total_bytes = memTotal;\n snapshot.mem_available_bytes = memFree;\n snapshot.mem_percent = round1(clampPercent(((memTotal - memFree) / memTotal) * 100));\n }\n\n const disk = this.diskUsage();\n if (disk) Object.assign(snapshot, disk);\n\n const mem = process.memoryUsage();\n snapshot.process.rss_bytes = mem.rss;\n snapshot.process.heap_used_bytes = mem.heapUsed;\n\n return snapshot;\n } catch (error) {\n this.logger.debug('falha ao coletar métricas de máquina', error);\n return undefined;\n }\n }\n\n private cpuTotals(): CpuTotals {\n let busy = 0;\n let total = 0;\n for (const cpu of this.os!.cpus()) {\n const t = cpu.times;\n const cpuBusy = t.user + t.nice + t.sys + t.irq;\n busy += cpuBusy;\n total += cpuBusy + t.idle;\n }\n return { busy, total };\n }\n\n /** Média desde a leitura anterior; leituras com menos de 1s de janela reutilizam a última média. */\n private updateCpu(cpuCount: number): void {\n const now = Date.now();\n const elapsedMs = now - this.prevAt;\n if (elapsedMs < MIN_CPU_WINDOW_MS) return;\n\n const cpu = this.cpuTotals();\n if (this.prevCpu) {\n const total = cpu.total - this.prevCpu.total;\n if (total > 0) this.lastCpuPercent = round1(clampPercent(((cpu.busy - this.prevCpu.busy) / total) * 100));\n }\n this.prevCpu = cpu;\n\n const usage = process.cpuUsage(this.prevProcessCpu);\n const usedMicros = usage.user + usage.system;\n this.lastProcessCpuPercent = round1(clampPercent((usedMicros / (elapsedMs * 1_000 * cpuCount)) * 100));\n this.prevProcessCpu = process.cpuUsage();\n this.prevAt = now;\n }\n\n private diskUsage(): Pick<MachineSnapshot, 'disk_path' | 'disk_total_bytes' | 'disk_free_bytes' | 'disk_percent'> | undefined {\n const statfs = this.fs?.statfsSync;\n if (typeof statfs !== 'function') return undefined;\n try {\n const path = process.cwd();\n const stat = statfs(path);\n const total = stat.bsize * stat.blocks;\n const free = stat.bsize * stat.bavail;\n if (total <= 0) return undefined;\n return {\n disk_path: path,\n disk_total_bytes: total,\n disk_free_bytes: free,\n disk_percent: round1(clampPercent(((total - free) / total) * 100)),\n };\n } catch {\n return undefined;\n }\n }\n}\n","import type {\n FileDownloadResponse,\n PollRequest,\n PollResponse,\n RunAttachmentConfirmRequest,\n RunCreateRequest,\n RunAttachmentCreateRequest,\n RunAttachmentCreateResponse,\n RunDescriptor,\n RunItemsCreateRequest,\n RunItemsCreateResponse,\n RunItemsDoneRequest,\n RunItemsDoneResponse,\n RunStartRequest,\n RunUpdateRequest,\n} from './protocol';\nimport { fetchWithRetry, withTimeoutSignal, type Logger } from '../utils';\n\nconst POLL_TIMEOUT_MS = 30_000;\nconst UPDATE_TIMEOUT_MS = 10_000;\n/**\n * No registro de anexo estes códigos são PERMANENTES, não falha transitória: 429 = cota\n * de 20 por execução, 501/503 = instalação sem bucket S3. Sem isto o handler esperaria\n * a ladder inteira (~21s) por um erro definitivo — e o `isUnsupported`/`quota` do\n * RunReporter nunca era acionado (chegava um TimeoutError genérico).\n */\nexport const ATTACHMENT_TERMINAL_STATUSES: readonly number[] = [429, 501, 503];\n/** No envio de itens o 429 é o cap de itens da run — permanente, sem retry. */\nexport const ITEMS_TERMINAL_STATUSES: readonly number[] = [429];\n/** O PUT carrega o binário inteiro — ladder mais curta e timeout mais folgado que os PATCHes. */\nconst UPLOAD_TIMEOUT_MS = 30_000;\nconst UPLOAD_RETRY_DELAYS_MS: readonly number[] = [1_000, 4_000];\n/**\n * Arquivos do formulário: 404 (não existe nesta run) e 410 (já baixado/expirado) são\n * definitivos por natureza (4xx); 429 aqui seria rate limit — retriável, como nos updates.\n */\nconst FILE_RETRY_DELAYS_MS: readonly number[] = [1_000, 4_000];\n\nexport class TasksApiError extends Error {\n constructor(\n message: string,\n readonly status: number\n ) {\n super(message);\n this.name = 'TasksApiError';\n }\n}\n\nexport interface TasksApiOptions {\n baseUrl: string;\n key: string;\n logger: Logger;\n}\n\n/**\n * O que UMA run em execução precisa do transporte — reporter (status, logs, itens, anexos),\n * arquivos do formulário e o exit path do tracker. A `TasksApi` (rede) e o\n * `LocalRunTransport` (modo local, sem rede) implementam a mesma superfície: o pipeline\n * da run não sabe em qual dos dois está.\n */\nexport interface RunTransport {\n updateRun(runId: string, update: RunUpdateRequest): Promise<void>;\n updateRunOnce(runId: string, update: RunUpdateRequest, timeoutMs?: number): Promise<void>;\n createItems(runId: string, request: RunItemsCreateRequest): Promise<RunItemsCreateResponse>;\n listDoneItems(runId: string, request: RunItemsDoneRequest): Promise<RunItemsDoneResponse>;\n createAttachment(runId: string, request: RunAttachmentCreateRequest, signal?: AbortSignal): Promise<RunAttachmentCreateResponse>;\n uploadAttachment(url: string, headers: Record<string, string>, body: Uint8Array, signal?: AbortSignal): Promise<void>;\n confirmAttachment(runId: string, attachmentId: string, request: RunAttachmentConfirmRequest): Promise<void>;\n requestFileDownload(runId: string, fileId: string, signal?: AbortSignal): Promise<FileDownloadResponse>;\n fetchFile(url: string, signal: AbortSignal): Promise<Response>;\n confirmFileDownload(runId: string, fileId: string): Promise<void>;\n}\n\n/** Cliente HTTP do agente — bearer auth, retry com backoff nos updates. */\n/** Um `withTimeoutSignal` por tentativa, sempre limpo — composto com o signal externo (stop/cancelamento). */\nasync function withRequestTimeout(\n timeoutMs: number,\n external: AbortSignal | undefined,\n send: (signal: AbortSignal) => Promise<Response>\n): Promise<Response> {\n const { signal, cleanup } = withTimeoutSignal(timeoutMs, external);\n try {\n return await send(signal);\n } finally {\n cleanup();\n }\n}\n\nexport class TasksApi implements RunTransport {\n private readonly baseUrl: string;\n private readonly key: string;\n private readonly logger: Logger;\n\n constructor(options: TasksApiOptions) {\n this.baseUrl = options.baseUrl;\n this.key = options.key;\n this.logger = options.logger;\n }\n\n private headers(): Record<string, string> {\n return {\n 'content-type': 'application/json',\n authorization: `Bearer ${this.key}`,\n };\n }\n\n /** Um request só — o loop de polling é quem decide o backoff entre tentativas. */\n async poll(request: PollRequest, signal?: AbortSignal): Promise<PollResponse> {\n const { signal: timeoutSignal, cleanup } = withTimeoutSignal(POLL_TIMEOUT_MS, signal);\n let response: Response;\n try {\n response = await fetch(`${this.baseUrl}/poll`, {\n redirect: 'error',\n method: 'POST',\n headers: this.headers(),\n body: JSON.stringify(request),\n signal: timeoutSignal,\n });\n } finally {\n cleanup();\n }\n if (!response.ok) {\n throw new TasksApiError(`poll falhou (HTTP ${response.status})`, response.status);\n }\n return this.parsePollResponse(await response.json(), request.max ?? 1);\n }\n\n /**\n * Abre uma run por conta própria (modo start). Um request só — como no poll, o\n * ladder de espera entre tentativas é decisão do chamador (LocalRunner).\n * 4xx (401 = chave rejeitada) vira TasksApiError com o status.\n */\n async createRun(request: RunCreateRequest, signal?: AbortSignal): Promise<RunDescriptor> {\n const { signal: timeoutSignal, cleanup } = withTimeoutSignal(UPDATE_TIMEOUT_MS, signal);\n let response: Response;\n try {\n response = await fetch(`${this.baseUrl}`, {\n redirect: 'error',\n method: 'POST',\n headers: this.headers(),\n body: JSON.stringify(request),\n signal: timeoutSignal,\n });\n } finally {\n cleanup();\n }\n if (!response.ok) {\n throw new TasksApiError(`criação da run falhou (HTTP ${response.status})`, response.status);\n }\n const body = (await response.json().catch(() => null)) as Record<string, unknown> | null;\n if (typeof body?.id !== 'string') {\n throw new TasksApiError('resposta inválida da criação de run (id ausente)', 0);\n }\n return {\n id: body.id,\n params: body.params && typeof body.params === 'object' && !Array.isArray(body.params) ? (body.params as Record<string, unknown>) : {},\n form: null,\n source: typeof body.source === 'string' ? body.source : 'agent',\n created_at: typeof body.created_at === 'string' ? body.created_at : new Date().toISOString(),\n };\n }\n\n /**\n * Anexa o processo a uma run já reivindicada para esta instância (env HOBOTS_RUN_ID):\n * POST /v1/runs/:id/start. Um request só — quem decide o retry é o AttachedRunner.\n * 404 (não existe) e 409 (cancelada, já iniciada ou de outra instância) viram\n * TasksApiError com o status.\n */\n async startRun(runId: string, request: RunStartRequest, signal?: AbortSignal): Promise<RunDescriptor> {\n const { signal: timeoutSignal, cleanup } = withTimeoutSignal(UPDATE_TIMEOUT_MS, signal);\n let response: Response;\n try {\n response = await fetch(`${this.baseUrl}/${encodeURIComponent(runId)}/start`, {\n redirect: 'error',\n method: 'POST',\n headers: this.headers(),\n body: JSON.stringify(request),\n signal: timeoutSignal,\n });\n } finally {\n cleanup();\n }\n if (!response.ok) {\n throw new TasksApiError(`início da run falhou (HTTP ${response.status})`, response.status);\n }\n const body = (await response.json().catch(() => null)) as Record<string, unknown> | null;\n if (typeof body?.id !== 'string') {\n throw new TasksApiError('resposta inválida do início da run (id ausente)', 0);\n }\n const form = body.form as Record<string, unknown> | null | undefined;\n return {\n id: body.id,\n params: body.params && typeof body.params === 'object' && !Array.isArray(body.params) ? (body.params as Record<string, unknown>) : {},\n form: typeof form?.id === 'string' && typeof form.name === 'string' ? { id: form.id, name: form.name } : null,\n source: typeof body.source === 'string' ? body.source : 'hobots',\n created_at: typeof body.created_at === 'string' ? body.created_at : new Date().toISOString(),\n };\n }\n\n /** Nunca confia no shape da resposta: runs malformadas são descartadas e o `max` é respeitado. */\n private parsePollResponse(body: unknown, max: number): PollResponse {\n const runs = (body as { runs?: unknown } | null)?.runs;\n if (!Array.isArray(runs)) {\n throw new TasksApiError('resposta inválida do poll (campo runs ausente)', 0);\n }\n const valid: RunDescriptor[] = [];\n for (const run of runs.slice(0, Math.max(0, max)) as Array<Record<string, unknown> | null>) {\n if (typeof run?.id !== 'string') continue;\n const params = run.params && typeof run.params === 'object' && !Array.isArray(run.params) ? run.params : {};\n valid.push({ ...run, id: run.id, params } as RunDescriptor);\n }\n if (valid.length < runs.length) {\n this.logger.warn(`poll retornou ${runs.length - valid.length} run(s) inválida(s)/excedente(s) — descartadas`);\n }\n return { runs: valid };\n }\n\n /**\n * PATCH de status/logs com retry em falha de rede/5xx/429.\n * 4xx é definitivo e vira TasksApiError imediato (409 = run cancelada/transição inválida).\n */\n async updateRun(runId: string, update: RunUpdateRequest): Promise<void> {\n let response: Response;\n try {\n response = await fetchWithRetry(\n () =>\n fetch(`${this.baseUrl}/${encodeURIComponent(runId)}`, {\n redirect: 'error',\n method: 'PATCH',\n headers: this.headers(),\n body: JSON.stringify(update),\n signal: AbortSignal.timeout(UPDATE_TIMEOUT_MS),\n }),\n { logger: this.logger, label: `update da run ${runId}` }\n );\n } catch (error) {\n throw new Error(`update da run ${runId} descartado após retries: ${String(error)}`);\n }\n if (!response.ok) {\n // 4xx definitivo (409 = run cancelada/transição inválida) — o RunReporter trata por status\n throw new TasksApiError(`update rejeitado (HTTP ${response.status})`, response.status);\n }\n }\n\n /**\n * Um único PATCH com timeout curto — exit path (o processo está morrendo, o retry\n * ladder do updateRun é proibido aqui). Status HTTP é ignorado: 409/404 significa\n * que a run já foi cancelada/finalizada, o que é aceitável nesse caminho.\n */\n async updateRunOnce(runId: string, update: RunUpdateRequest, timeoutMs = 2_000): Promise<void> {\n await fetch(`${this.baseUrl}/${encodeURIComponent(runId)}`, {\n redirect: 'error',\n method: 'PATCH',\n headers: this.headers(),\n body: JSON.stringify(update),\n signal: AbortSignal.timeout(timeoutMs),\n });\n }\n\n /**\n * Envia um lote de itens de execução. Retry em falha de rede/5xx/429-transporte;\n * 4xx é definitivo (404 = servidor sem o recurso, 429 = cap de itens por run) —\n * o RunReporter trata por status.\n */\n async createItems(runId: string, request: RunItemsCreateRequest): Promise<RunItemsCreateResponse> {\n let response: Response;\n try {\n response = await fetchWithRetry(\n () =>\n fetch(`${this.baseUrl}/${encodeURIComponent(runId)}/items`, {\n redirect: 'error',\n method: 'POST',\n headers: this.headers(),\n body: JSON.stringify(request),\n signal: AbortSignal.timeout(UPDATE_TIMEOUT_MS),\n }),\n { logger: this.logger, label: `itens da run ${runId}`, noRetryStatuses: ITEMS_TERMINAL_STATUSES }\n );\n } catch (error) {\n throw new Error(`envio de itens da run ${runId} descartado após retries: ${String(error)}`);\n }\n if (!response.ok) {\n throw new TasksApiError(`envio de itens rejeitado (HTTP ${response.status})`, response.status);\n }\n const body = (await response.json().catch(() => null)) as Partial<RunItemsCreateResponse> | null;\n return {\n accepted: typeof body?.accepted === 'number' ? body.accepted : request.items.length,\n duplicates: typeof body?.duplicates === 'number' ? body.duplicates : 0,\n };\n }\n\n /**\n * Uma página dos ids já concluídos neste trabalho (`items.each` pula). Retry em falha\n * de rede/5xx; 4xx é definitivo (404 = servidor sem o recurso).\n */\n async listDoneItems(runId: string, request: RunItemsDoneRequest): Promise<RunItemsDoneResponse> {\n let response: Response;\n try {\n response = await fetchWithRetry(\n () =>\n fetch(`${this.baseUrl}/${encodeURIComponent(runId)}/items/done`, {\n redirect: 'error',\n method: 'POST',\n headers: this.headers(),\n body: JSON.stringify(request),\n signal: AbortSignal.timeout(UPDATE_TIMEOUT_MS),\n }),\n { logger: this.logger, label: `itens concluídos da run ${runId}` }\n );\n } catch (error) {\n throw new Error(`consulta de itens concluídos da run ${runId} descartada após retries: ${String(error)}`);\n }\n if (!response.ok) {\n throw new TasksApiError(`consulta de itens concluídos rejeitada (HTTP ${response.status})`, response.status);\n }\n const body = (await response.json().catch(() => null)) as Partial<RunItemsDoneResponse> | null;\n if (!Array.isArray(body?.ids)) throw new TasksApiError('consulta de itens concluídos: resposta malformada', 0);\n return {\n ids: body.ids.map(id => String(id)),\n next: typeof body.next === 'string' && body.next.length > 0 ? body.next : null,\n };\n }\n\n /**\n * Registra o anexo e obtém a URL presignada de upload. 404/501/503 significam\n * \"esta instalação não tem anexos\" — o RunReporter degrada em silêncio a partir daí.\n */\n async createAttachment(\n runId: string,\n request: RunAttachmentCreateRequest,\n signal?: AbortSignal\n ): Promise<RunAttachmentCreateResponse> {\n // timeout POR requisição (não um só cobrindo a ladder inteira: os 1s+4s+16s de\n // espera já passariam de 10s e todo retry chegaria como TimeoutError)\n const response = await fetchWithRetry(\n () =>\n withRequestTimeout(UPDATE_TIMEOUT_MS, signal, timeoutSignal =>\n fetch(`${this.baseUrl}/${encodeURIComponent(runId)}/attachments`, {\n redirect: 'error',\n method: 'POST',\n headers: this.headers(),\n body: JSON.stringify(request),\n signal: timeoutSignal,\n })\n ),\n {\n logger: this.logger,\n label: `anexo da run ${runId}`,\n noRetryStatuses: ATTACHMENT_TERMINAL_STATUSES,\n // run abortada (timeout, 409, kill): o create em voo rejeita por abort e não entra na ladder\n signal,\n }\n );\n if (!response.ok) {\n throw new TasksApiError(`criação de anexo rejeitada (HTTP ${response.status})`, response.status);\n }\n const body = (await response.json()) as Partial<RunAttachmentCreateResponse> | null;\n if (typeof body?.upload_url !== 'string') {\n throw new TasksApiError('resposta inválida do anexo (upload_url ausente)', 0);\n }\n return {\n id: body.id ?? request.id,\n upload_url: body.upload_url,\n headers: body.headers ?? { 'content-type': request.content_type },\n expires_in: body.expires_in ?? 900,\n };\n }\n\n /**\n * PUT do binário direto no S3. Deliberadamente sem `authorization`: a autorização\n * está na assinatura da URL, e mandar o client secret para fora da API seria vazamento.\n */\n async uploadAttachment(\n url: string,\n headers: Record<string, string>,\n body: Uint8Array,\n signal?: AbortSignal\n ): Promise<void> {\n const response = await fetchWithRetry(\n () =>\n withRequestTimeout(UPLOAD_TIMEOUT_MS, signal, timeoutSignal =>\n fetch(url, {\n redirect: 'error',\n method: 'PUT',\n headers,\n // BodyInit não aceita Uint8Array<ArrayBufferLike> em todos os lib.dom; o buffer é o mesmo\n body: body as BodyInit,\n signal: timeoutSignal,\n })\n ),\n { delays: UPLOAD_RETRY_DELAYS_MS, logger: this.logger, label: 'upload de anexo', signal }\n );\n if (!response.ok) {\n throw new TasksApiError(`upload de anexo rejeitado (HTTP ${response.status})`, response.status);\n }\n }\n\n /** Marca o anexo como enviado (ou falho). Best-effort — a leitura não depende disso. */\n async confirmAttachment(\n runId: string,\n attachmentId: string,\n request: RunAttachmentConfirmRequest\n ): Promise<void> {\n const response = await fetch(\n `${this.baseUrl}/${encodeURIComponent(runId)}/attachments/${encodeURIComponent(attachmentId)}`,\n {\n redirect: 'error',\n method: 'PATCH',\n headers: this.headers(),\n body: JSON.stringify(request),\n signal: AbortSignal.timeout(UPDATE_TIMEOUT_MS),\n }\n );\n if (!response.ok) {\n throw new TasksApiError(`confirmação de anexo rejeitada (HTTP ${response.status})`, response.status);\n }\n }\n\n /**\n * Pede a URL pré-assinada de GET de um arquivo do formulário. 404 (não existe nesta run)\n * e 410 (já baixado/expirado) viram `TasksApiError` com o status — quem chama traduz.\n */\n async requestFileDownload(runId: string, fileId: string, signal?: AbortSignal): Promise<FileDownloadResponse> {\n const response = await fetchWithRetry(\n () =>\n withRequestTimeout(UPDATE_TIMEOUT_MS, signal, timeoutSignal =>\n fetch(`${this.baseUrl}/${encodeURIComponent(runId)}/files/${encodeURIComponent(fileId)}/download`, {\n redirect: 'error',\n method: 'POST',\n headers: this.headers(),\n signal: timeoutSignal,\n })\n ),\n { delays: FILE_RETRY_DELAYS_MS, logger: this.logger, label: `download do arquivo ${fileId}`, signal }\n );\n if (!response.ok) {\n throw new TasksApiError(`download de arquivo rejeitado (HTTP ${response.status})`, response.status);\n }\n const body = (await response.json().catch(() => null)) as Partial<FileDownloadResponse> | null;\n if (typeof body?.url !== 'string') {\n throw new TasksApiError('resposta inválida do download de arquivo (url ausente)', 0);\n }\n return {\n url: body.url,\n expires_in: typeof body.expires_in === 'number' ? body.expires_in : 0,\n name: typeof body.name === 'string' ? body.name : '',\n size: typeof body.size === 'number' ? body.size : -1,\n content_type: typeof body.content_type === 'string' ? body.content_type : '',\n };\n }\n\n /**\n * GET do binário direto no S3 — deliberadamente sem `authorization` (a autorização\n * está na assinatura da URL; mandar o client secret para fora da API seria vazamento).\n * Devolve a Response com o corpo ainda não lido: quem chama faz o streaming para o disco.\n */\n async fetchFile(url: string, signal: AbortSignal): Promise<Response> {\n const response = await fetchWithRetry(() => fetch(url, { redirect: 'error', method: 'GET', signal }), {\n delays: FILE_RETRY_DELAYS_MS,\n logger: this.logger,\n label: 'download de arquivo',\n signal,\n });\n if (!response.ok) {\n throw new TasksApiError(`download de arquivo falhou (HTTP ${response.status})`, response.status);\n }\n return response;\n }\n\n /**\n * Confirma o download: o servidor apaga o objeto do S3 na hora. Idempotente (204);\n * 404/410 também significam \"não há mais nada a apagar\" e contam como confirmado.\n */\n async confirmFileDownload(runId: string, fileId: string): Promise<void> {\n const response = await fetchWithRetry(\n () =>\n fetch(`${this.baseUrl}/${encodeURIComponent(runId)}/files/${encodeURIComponent(fileId)}`, {\n redirect: 'error',\n method: 'DELETE',\n headers: this.headers(),\n signal: AbortSignal.timeout(UPDATE_TIMEOUT_MS),\n }),\n { delays: FILE_RETRY_DELAYS_MS, logger: this.logger, label: `confirmação do arquivo ${fileId}` }\n );\n if (!response.ok && response.status !== 404 && response.status !== 410) {\n throw new TasksApiError(`confirmação de download rejeitada (HTTP ${response.status})`, response.status);\n }\n }\n}\n","import { TasksApiError } from './api';\nimport { jitter, type Logger } from '../utils';\n\nconst RETRY_DELAYS_MS = [1_000, 4_000, 16_000];\nconst AUTH_FAILURE_INTERVAL_MS = 30_000;\n\n/**\n * Espera entre tentativas de uma chamada que o agente repete até dar certo (poll,\n * criação da run no modo start): ladder 1s/4s/16s com jitter, e 401 (chave\n * desativada/rotacionada) ou 402 (agente fora do limite do plano) em ritmo lento,\n * com erro logado na 1ª falha e a cada 10 — os dois podem voltar sozinhos.\n */\nexport class Backoff {\n private failures = 0;\n private authFailures = 0;\n\n constructor(\n private readonly logger: Logger,\n private readonly label: string,\n /** Piso da espera (o intervalo normal do poll); no modo start, 0. */\n private readonly floorMs = 0\n ) {}\n\n reset(): void {\n this.failures = 0;\n this.authFailures = 0;\n }\n\n next(error: unknown): number {\n if (error instanceof TasksApiError && (error.status === 401 || error.status === 402)) {\n this.authFailures++;\n if (this.authFailures === 1 || this.authFailures % 10 === 0) {\n this.logger.error(\n error.status === 402\n ? 'agente fora do limite do plano (402) — faça upgrade em Plano e cobrança para reativá-lo'\n : 'chave rejeitada (401) — verifique o Client Secret na Central: abra o agente → Configurações → agente → aba credenciais'\n );\n }\n return Math.max(this.floorMs, AUTH_FAILURE_INTERVAL_MS);\n }\n this.failures++;\n const ladder = RETRY_DELAYS_MS[Math.min(this.failures - 1, RETRY_DELAYS_MS.length - 1)]!;\n const delay = Math.min(Math.max(jitter(ladder), 0), Math.max(this.floorMs, 16_000));\n this.logger.warn(`${this.label} falhou (${String(error)}), próxima tentativa em ${delay}ms`);\n return delay;\n }\n}\n","import type { ImageInput } from './attachments';\n\n/** Erros de controle do ciclo de vida de uma run — identificados pelo `name`, nunca pela classe. */\n\n/**\n * Ocorrência de negócio lançada de dentro do handler de `hobots.items.each`: o item vira\n * `occurrence` com esta mensagem (e `payload`/`image`, se vierem), a etapa do item vira\n * `warning` e o loop segue — **sem nova tentativa**: o retry do `each` é só para falha\n * técnica (qualquer outro erro). Use para regra de negócio: \"nota já cadastrada\",\n * \"cliente sem pendência\", \"produto fora do cardápio\".\n *\n * throw new Occurrence('nota já cadastrada', { situacao: 'já cadastrada' });\n *\n * Fora do `each` (handler de `register()`/`start()` sem loop) é um erro comum: a run falha\n * com ele como com qualquer outro.\n */\nexport class Occurrence extends Error {\n readonly payload: Record<string, unknown> | undefined;\n /** Print do item (bytes/caminho ou `hobots.image(...)`) — o `each` pendura no item. */\n readonly image: ImageInput | undefined;\n\n constructor(message: string, payload?: Record<string, unknown>, options?: { image?: ImageInput }) {\n super(message);\n this.name = 'Occurrence';\n this.payload = payload;\n this.image = options?.image;\n }\n}\n\n/** Ocorrência de negócio — pelo `name`, como os demais erros de controle. */\nexport function isOccurrence(error: unknown): error is Occurrence {\n return error instanceof Error && error.name === 'Occurrence';\n}\n\n/** A run foi cancelada (no app, por timeout ou no shutdown). */\nexport function runCanceledError(): Error {\n return Object.assign(new Error('execução cancelada'), { name: 'RunCanceled' });\n}\n\n/** O handler estourou `timeoutMs` — terminal: não há nova tentativa. */\nexport function taskTimeoutError(timeoutMs: number): Error {\n return Object.assign(new Error(`timeout após ${timeoutMs}ms (o handler pode continuar em background)`), {\n name: 'TaskTimeout',\n });\n}\n\n/** Erros que encerram a run de vez — o retry nunca insiste depois de um deles. */\nconst TERMINAL_ERROR_NAMES: ReadonlySet<string> = new Set(['RunCanceled', 'AbortError', 'TaskTimeout']);\n\nexport function isTerminalError(error: unknown): boolean {\n return error instanceof Error && TERMINAL_ERROR_NAMES.has(error.name);\n}\n\n/** Cancelamento (no app, no shutdown ou pelo signal) — encerra a run, mas não é defeito do bot. */\nexport function isCancellation(error: unknown): boolean {\n return error instanceof Error && (error.name === 'RunCanceled' || error.name === 'AbortError');\n}\n","import type { RunAttachmentContentType } from './protocol';\nimport { isNode } from '../utils';\nimport { WIRE_LIMITS } from '../wire-limits';\n\n/** Tamanho máximo de um anexo. O servidor aplica o mesmo teto (WIRE_LIMITS). */\nexport const MAX_ATTACHMENT_BYTES = WIRE_LIMITS.MAX_ATTACHMENT_BYTES;\n/** Teto de anexos por execução. O servidor aplica o mesmo teto (429). */\nexport const MAX_ATTACHMENTS_PER_RUN = WIRE_LIMITS.MAX_ATTACHMENTS_PER_RUN;\n/** Anexos por linha de log — o servidor rejeita a linha acima disto. */\nexport const MAX_ATTACHMENTS_PER_LOG_ENTRY = WIRE_LIMITS.MAX_ATTACHMENTS_PER_LOG_ENTRY;\n/** Uploads simultâneos por run — o resto fica na fila. */\nexport const MAX_CONCURRENT_UPLOADS = 3;\nexport const MAX_CAPTION_CHARS = WIRE_LIMITS.MAX_CAPTION_CHARS;\n/** Tempo máximo que a run espera pelos uploads pendentes antes do PATCH terminal. */\nexport const ATTACHMENT_DRAIN_MS = 15_000;\n\nexport type AttachFailureReason =\n /** A instalação do Hobots não tem anexos habilitados (ou a API é anterior ao recurso) */\n | 'unsupported'\n | 'too-large'\n | 'quota'\n | 'read-failed'\n /** Formato não reconhecido ou fora de PNG/JPEG/WEBP */\n | 'unsupported-format'\n | 'upload-failed'\n | 'canceled';\n\n/** Aceita tudo que o handler pode ter em mãos: bytes ou um caminho de arquivo (só Node). */\nexport type AttachInput = Uint8Array | ArrayBuffer | string;\n\nexport interface ImageOptions {\n /** Legenda curta, exibida junto da imagem no app. Passa pelo scrub de segredos. */\n caption?: string;\n /** Informe quando os magic bytes não bastarem (o SDK sempre prefere o que detectar). */\n contentType?: RunAttachmentContentType;\n}\n\nconst IMAGE_BRAND: unique symbol = Symbol.for('hobots.image');\n\n/**\n * Uma imagem pronta para ser pendurada num evento da run — o retorno de `hobots.image()`.\n * É só um envelope (bytes/caminho + legenda); nenhum I/O acontece até o evento ser\n * registrado por `hobots.log.*`, `hobots.items.*` ou `step.setStatus/failed`.\n */\nexport class ImageAttachment {\n readonly [IMAGE_BRAND] = true;\n\n constructor(\n readonly input: AttachInput,\n readonly caption?: string,\n readonly contentType?: RunAttachmentContentType\n ) {}\n}\n\n/** O que os métodos com imagem aceitam: bytes/caminho crus ou o envelope de `hobots.image()`. */\nexport type ImageInput = AttachInput | ImageAttachment;\n\n/**\n * `hobots.image(bytes, { caption })`: embrulha um print para ir junto de um log, item ou\n * step. Puro — a leitura/validação/upload acontecem só quando o evento é registrado.\n */\nexport function image(input: AttachInput, options: ImageOptions = {}): ImageAttachment {\n return new ImageAttachment(input, options.caption, options.contentType);\n}\n\n/** Reconhece o envelope mesmo vindo de outra cópia do pacote (brand por `Symbol.for`). */\nexport function isImageAttachment(value: unknown): value is ImageAttachment {\n return typeof value === 'object' && value !== null && (value as Record<symbol, unknown>)[IMAGE_BRAND] === true;\n}\n\n/** Normaliza bytes/caminho crus para o envelope. */\nexport function toImageAttachment(value: ImageInput): ImageAttachment {\n return isImageAttachment(value) ? value : new ImageAttachment(value);\n}\n\n/**\n * Lê um arquivo de imagem do disco. Import dinâmico de `node:fs/promises` — nada de\n * import estático de builtin do Node, que quebraria o bundle neutro/browser.\n */\nexport async function readImageFile(path: string): Promise<Uint8Array> {\n if (!isNode()) {\n throw new Error('caminho de arquivo só é suportado em Node');\n }\n const { readFile } = await import('node:fs/promises');\n return new Uint8Array(await readFile(path));\n}\n\nfunction startsWith(bytes: Uint8Array, signature: readonly number[], offset = 0): boolean {\n if (bytes.length < offset + signature.length) return false;\n return signature.every((byte, index) => bytes[offset + index] === byte);\n}\n\nconst PNG_MAGIC = [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a] as const;\nexport const MAX_PNG_DIMENSION = WIRE_LIMITS.MAX_IMAGE_DIMENSION_PX;\nconst JPEG_MAGIC = [0xff, 0xd8, 0xff] as const;\nconst RIFF_MAGIC = [0x52, 0x49, 0x46, 0x46] as const; // \"RIFF\"\nconst WEBP_MAGIC = [0x57, 0x45, 0x42, 0x50] as const; // \"WEBP\" no offset 8\n\n/** Detecta o formato pelos magic bytes. `undefined` quando não é PNG/JPEG/WEBP. */\nexport function sniffContentType(bytes: Uint8Array): RunAttachmentContentType | undefined {\n if (startsWith(bytes, PNG_MAGIC)) return 'image/png';\n if (startsWith(bytes, JPEG_MAGIC)) return 'image/jpeg';\n if (startsWith(bytes, RIFF_MAGIC) && startsWith(bytes, WEBP_MAGIC, 8)) return 'image/webp';\n return undefined;\n}\n\n/**\n * Dimensões pelo chunk IHDR de um PNG (bytes 16..23). Só PNG: é o formato de print\n * mais comum e o único que dá pra ler sem parser. Sem dimensões o app apenas não\n * reserva o espaço da miniatura antes do carregamento.\n */\nexport function readPngDimensions(bytes: Uint8Array): { width: number; height: number } | undefined {\n if (!startsWith(bytes, PNG_MAGIC) || bytes.length < 24) return undefined;\n const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);\n const width = view.getUint32(16);\n const height = view.getUint32(20);\n if (width === 0 || height === 0) return undefined;\n // o servidor valida 1..20_000 por dimensão\n if (width > MAX_PNG_DIMENSION || height > MAX_PNG_DIMENSION) return undefined;\n return { width, height };\n}\n\n/** Normaliza a entrada do handler para bytes, lendo do disco quando for um caminho. */\nexport async function toBytes(input: AttachInput): Promise<Uint8Array> {\n if (typeof input === 'string') return readImageFile(input);\n if (input instanceof Uint8Array) return input;\n return new Uint8Array(input);\n}\n","import type { AsyncLocalStorage } from 'node:async_hooks';\n\nimport { isNode } from '../utils';\nimport type { RunReporter } from './context';\nimport type { Step, Transaction } from '../transaction';\n\ninterface RunStore {\n /** Reporter da run em execução — a fonte de tudo que `hobots.*` expõe (log, items, progress…). */\n reporter: RunReporter;\n}\n\n/** A etapa corrente de uma transaction: `hobots.step` dentro dela vira filha. */\nexport interface StepScope {\n transaction: Transaction;\n step: Step;\n}\n\n// Inicializado sob demanda só em Node (import dinâmico → não entra no bundle do browser).\n// import type acima é apagado em compilação, então não há import estático de node:async_hooks.\nlet storage: AsyncLocalStorage<RunStore> | undefined;\nlet stepStorage: AsyncLocalStorage<StepScope> | undefined;\nlet initPromise: Promise<void> | undefined;\n\nasync function ensureStorage(): Promise<void> {\n if (storage || !isNode()) return;\n initPromise ??= import('node:async_hooks').then(({ AsyncLocalStorage: ALS }) => {\n storage = new ALS<RunStore>();\n stepStorage = new ALS<StepScope>();\n });\n await initPromise;\n}\n\n/**\n * Executa `fn` com a run ativa no contexto async atual. Qualquer acesso a `hobots.*`\n * por dentro (em qualquer módulo, timer ou promise criada aqui) resolve para esta run —\n * é o que permite `concurrency > 1` sem passar o contexto de mão em mão.\n */\nexport async function runWithRunContext<T>(store: RunStore, fn: () => Promise<T>): Promise<T> {\n await ensureStorage();\n return storage ? storage.run(store, fn) : fn();\n}\n\n/** Reporter da run em execução no contexto async atual, se houver. */\nexport function currentRunReporter(): RunReporter | undefined {\n return storage?.getStore()?.reporter;\n}\n\n/**\n * Executa `fn` com `scope.step` como a etapa corrente da transaction no contexto async atual —\n * é o que faz `hobots.step` dentro de outra etapa (ou do handler de `items.each`) aninhar nela.\n */\nexport async function runWithStepScope<T>(scope: StepScope, fn: () => Promise<T>): Promise<T> {\n await ensureStorage();\n return stepStorage ? stepStorage.run(scope, fn) : fn();\n}\n\n/** A etapa corrente de `transaction` no contexto async atual, se houver. */\nexport function currentStep(transaction: Transaction): Step | undefined {\n const scope = stepStorage?.getStore();\n return scope?.transaction === transaction ? scope.step : undefined;\n}\n","import { isTerminalError, runCanceledError } from './tasks/errors';\nimport { sleep } from './utils';\n\n/** Espera entre tentativas: ms fixo ou função do número da tentativa que acabou de falhar (1-based). */\nexport type RetryDelay = number | ((attempt: number) => number);\n\nexport interface RetryOptions {\n /** Tentativas extras depois da primeira falha. Default: 3 */\n retries?: number;\n /** Espera entre tentativas. Default: 1_000 */\n delayMs?: RetryDelay;\n /** Filtro adicional: retorne false para desistir na hora. Cancelamento e timeout nunca são re-tentados. */\n shouldRetry?: (error: unknown) => boolean;\n}\n\n/** Opções internas do runner — não fazem parte da API pública. */\nexport interface RetryInternalOptions extends RetryOptions {\n /** Cancelamento: aborta antes da próxima tentativa (lança RunCanceled). */\n signal?: AbortSignal;\n /** Sleep a usar entre tentativas (o ctx.sleep cancelável dentro de uma run). Default: sleep unref'd. */\n wait?: (ms: number) => Promise<void>;\n /** Chamado antes de esperar pela próxima tentativa — o runner loga no run aqui. */\n onRetry?: (error: unknown, attempt: number, delayMs: number) => void;\n}\n\nconst DEFAULT_RETRIES = 3;\nconst DEFAULT_DELAY_MS = 1_000;\n\n/** Resolve o delay de uma tentativa; valores inválidos/negativos viram 0. */\nexport function resolveDelay(delay: RetryDelay | undefined, attempt: number, fallbackMs: number): number {\n const value = typeof delay === 'function' ? delay(attempt) : (delay ?? fallbackMs);\n return Number.isFinite(value) && value > 0 ? Math.floor(value) : 0;\n}\n\n/**\n * async-retry do SDK: executa `fn` até dar certo ou esgotar `retries`. Ciente de\n * cancelamento — com o signal abortado, lança RunCanceled em vez de tentar de novo;\n * erros terminais (RunCanceled/AbortError/TaskTimeout) nunca são re-tentados.\n */\nexport async function retryWithBackoff<T>(\n fn: (attempt: number) => T | Promise<T>,\n options: RetryInternalOptions = {}\n): Promise<T> {\n // `Number.isFinite`: um `retries: NaN` deixava `attempt > retries` sempre falso → retry infinito\n const requested = options.retries ?? DEFAULT_RETRIES;\n const retries = Number.isFinite(requested) ? Math.max(0, Math.floor(requested)) : DEFAULT_RETRIES;\n const wait = options.wait ?? sleep;\n for (let attempt = 1; ; attempt++) {\n if (options.signal?.aborted) throw runCanceledError();\n try {\n return await fn(attempt);\n } catch (error) {\n const exhausted = attempt > retries;\n const retriable = !isTerminalError(error) && !options.signal?.aborted && (options.shouldRetry?.(error) ?? true);\n if (exhausted || !retriable) throw error;\n const delay = resolveDelay(options.delayMs, attempt, DEFAULT_DELAY_MS);\n options.onRetry?.(error, attempt, delay);\n await wait(delay);\n }\n }\n}\n","/**\n * Etapas (steps) de uma execução: a transaction da run e as etapas que o bot abre nela.\n *\n * O bot só conhece `hobots.step(nome, fn, { retries })`: o SDK abre a transaction da run em\n * `register()`/`start()`, registra cada etapa (com tentativas) no waterfall da Central e\n * fecha tudo no fim. `Transaction` é interna — nada aqui é chamado pelo código do bot\n * além do handle (`StepHandle`) que `fn` recebe.\n */\nimport type { StepData, StepStatus, TransactionPayload } from './protocol';\nimport type { RunLogLevel } from './tasks/protocol';\nimport { MAX_ATTACHMENTS_PER_LOG_ENTRY, type ImageInput } from './tasks/attachments';\nimport { isTerminalError } from './tasks/errors';\nimport { currentStep, runWithStepScope } from './tasks/run-context-store';\nimport { MAX_STEPS, MAX_STEP_DESCRIPTION_CHARS, MAX_STEP_OP_CHARS, type Client } from './client';\nimport { resolveDelay, retryWithBackoff } from './retry';\nimport { scrubSecrets } from './scrub';\nimport type { StepFn, StepHandle, StepOptions } from './types';\nimport { clip, colorize, nowISO, safeString, truncate, uuid4 } from './utils';\n\n/** `op` das transactions parciais enviadas por `flush()` — a Central as distingue da final. */\nexport const FLUSH_TRANSACTION_OP = 'hobots.run.flush';\n/** Tentativas extras de uma etapa por padrão (`retries: 0` desliga). */\nexport const DEFAULT_STEP_RETRIES = 1;\n/** Espera entre as tentativas de uma etapa (ms) — a mesma do retry do trabalho inteiro. */\nexport const DEFAULT_STEP_RETRY_DELAY_MS = 5_000;\nexport { MAX_STEP_DESCRIPTION_CHARS, MAX_STEP_OP_CHARS } from './client';\n\n/** Teto do motivo de uma etapa (data.message / data.error.message). */\nconst MAX_STEP_MESSAGE_CHARS = 2_000;\nconst MAX_BACKLOG = 100;\n\nfunction stepMessage(text: string): string {\n return clip(scrubSecrets(text), MAX_STEP_MESSAGE_CHARS);\n}\n\nfunction stepId(): string {\n return uuid4().slice(0, 16);\n}\n\n/** Recebe os eventos de lifecycle da transaction para espelhá-los nos logs da run. */\nexport type LifecycleSink = (level: RunLogLevel, message: string) => void;\n\n/**\n * Recebe a imagem de uma etapa e dispara o upload pela run; devolve o id do anexo\n * (já referenciável em `data.attachments`) ou undefined quando descartada.\n */\nexport type AttachmentSink = (image: ImageInput, ts: string) => string | undefined;\n\n/** Opções internas de `Transaction.step` — o RunContext liga o cancelamento e o log da run. */\nexport interface StepInternalOptions {\n /** Cancelamento da run: abortado, não há nova tentativa. */\n signal?: AbortSignal;\n /** Espera entre tentativas (o `ctx.sleep` cancelável dentro de uma run). */\n wait?: (ms: number) => Promise<void>;\n /** Aviso de tentativa falhada — vai para o log da run. */\n warn?: (message: string) => void;\n}\n\n/** Rótulo legível de uma etapa a partir de op/description. */\nfunction stepLabel(op?: string, description?: string): string {\n return [op, description].filter(Boolean).join(' — ') || '(sem nome)';\n}\n\n/** Mensagem legível de qualquer valor lançado — só a mensagem, sem o tipo. */\nfunction errorText(error: unknown): string {\n if (error instanceof Error) return error.message || error.name;\n return safeString(error);\n}\n\n/** `Tipo: mensagem`, como no aviso de retry do trabalho inteiro. */\nexport function errorReason(error: unknown): string {\n return error instanceof Error ? `${error.name}: ${errorText(error)}` : errorText(error);\n}\n\n/** Mapeia o status de finalização (etapa/transaction) para o nível de log da run. */\nfunction levelForStatus(status: StepStatus | string): RunLogLevel {\n switch (status) {\n case 'warning':\n return 'warning';\n case 'error':\n return 'error';\n case 'cancelled':\n return 'warning';\n default:\n return 'success';\n }\n}\n\n/** Mapeia o status de finalização para a cor ANSI usada no eco do terminal. */\nfunction colorForStatus(status: StepStatus | string): Parameters<typeof colorize>[1] {\n switch (status) {\n case 'warning':\n return 'yellow';\n case 'error':\n return 'red';\n case 'cancelled':\n return 'gray';\n default:\n return 'green';\n }\n}\n\n/**\n * A etapa em andamento — o handle que a função de `hobots.step(nome, fn)` recebe (classe\n * interna: o bot vê só a interface `StepHandle`). Abrir, repetir e fechar é do SDK.\n */\nexport class Step implements StepHandle {\n readonly stepId = stepId();\n readonly startTimestamp = nowISO();\n status: StepStatus = 'ok';\n endTimestamp?: string;\n private _data?: Record<string, unknown>;\n\n constructor(\n private readonly transaction: Transaction,\n readonly parentStepId: string,\n readonly op?: string,\n readonly description?: string\n ) {}\n\n // ── API do bot ────────────────────────────────────────────────────────────\n\n warning(message: string, options?: { image?: ImageInput }): this {\n if (this.status !== 'error') this._setStatus('warning', message);\n if (options?.image !== undefined) this.attachImage(options.image);\n return this;\n }\n\n image(image: ImageInput): this {\n this.attachImage(image);\n return this;\n }\n\n data(key: string, value: unknown): this {\n if (key === 'attachments') return this;\n this._setData(key, value);\n return this;\n }\n\n // ── Internos (chamados pelo SDK) ──────────────────────────────────────────\n\n /** `data` da etapa como vai no wire (undefined quando vazio). */\n get payload(): Record<string, unknown> | undefined {\n return this._data;\n }\n\n _setStatus(status: StepStatus, message?: string): this {\n this.status = status;\n if (message) this._setData('message', stepMessage(safeString(message)));\n return this;\n }\n\n /**\n * Marca `error` guardando `{ type, message }` em `data.error` e fecha a etapa. Aceita qualquer\n * valor lançado; `message` sobrescreve a mensagem do erro. Numa etapa já fechada não faz nada.\n */\n _failed(error: unknown, message?: string): this {\n if (this.endTimestamp) return this;\n this.status = 'error';\n const type = error instanceof Error ? error.name : typeof error === 'object' && error !== null ? 'Error' : undefined;\n const raw = message ?? errorText(error);\n this._setData('error', { ...(type ? { type } : {}), message: stepMessage(safeString(raw)) });\n this._close();\n return this;\n }\n\n _setData(key: string, value: unknown): void {\n this._data = { ...this._data, [key]: value };\n }\n\n _deleteData(key: string): void {\n if (!this._data || !(key in this._data)) return;\n const rest = { ...this._data };\n delete rest[key];\n this._data = Object.keys(rest).length > 0 ? rest : undefined;\n }\n\n /**\n * Dispara o upload pela run (sink do RunReporter) e referencia o anexo em\n * `data.attachments` (chave reservada; teto igual ao das linhas de log). Fora de uma\n * run não há onde pendurar a imagem — descarta com aviso único.\n */\n private attachImage(image: ImageInput): void {\n const current = Array.isArray(this._data?.attachments) ? (this._data.attachments as string[]) : [];\n if (current.length >= MAX_ATTACHMENTS_PER_LOG_ENTRY) return;\n const id = this.transaction.attachImage(image);\n if (!id) return;\n this._setData('attachments', [...current, id]);\n }\n\n /** Motivo registrado (warning/erro) — usado no log de FINISH. */\n private reason(): string | undefined {\n const error = this._data?.error as { message?: unknown } | undefined;\n const text = typeof error?.message === 'string' ? error.message : this._data?.message;\n return typeof text === 'string' && text ? text : undefined;\n }\n\n /** Fecha a etapa mantendo o status que estiver. Idempotente. */\n _close(): void {\n if (this.endTimestamp) return;\n this.endTimestamp = nowISO();\n this.transaction.emit(\n 'step',\n 'finish',\n stepLabel(this.op, this.description),\n this.startTimestamp,\n this.endTimestamp,\n this.status,\n this.reason()\n );\n }\n\n toJSON(): StepData {\n return {\n step_id: this.stepId,\n ...(this.parentStepId ? { parent_step_id: this.parentStepId } : {}),\n ...(this.op ? { op: clip(this.op, MAX_STEP_OP_CHARS) } : {}),\n ...(this.description ? { description: clip(this.description, MAX_STEP_DESCRIPTION_CHARS) } : {}),\n status: this.status,\n start_timestamp: this.startTimestamp,\n timestamp: this.endTimestamp ?? nowISO(),\n ...(this._data ? { data: this._data } : {}),\n };\n }\n}\n\n/**\n * A transaction de performance de uma execução (interna ao SDK). O runner cria uma por run\n * (`name` `run`, `op` `hobots.run`), o `RunReporter` liga os sinks, e `step()` registra as\n * etapas do bot nela. Fora de uma run existe só para dar um handle inerte à função da etapa.\n */\nexport class Transaction {\n readonly eventId = uuid4();\n readonly stepId = stepId();\n readonly startTimestamp = nowISO();\n status = 'ok';\n private readonly steps: Step[] = [];\n private finished = false;\n private lifecycleSink?: LifecycleSink;\n private attachmentSink?: AttachmentSink;\n private warnedNoAttachmentSink = false;\n // instalado pelo RunReporter: abrir uma etapa é um ponto de parada cooperativo (lança RunCanceled)\n private stepGuard?: () => void;\n // modo local (sem client): o FINISH de cada etapa sai no terminal, como `[hobots:item]`\n private readonly echo: boolean;\n // eventos emitidos antes do sink existir (o START da transaction sai no construtor,\n // antes do RunReporter conectar) — replay no setLifecycleSink\n private lifecycleBacklog: Array<[RunLogLevel, string]> = [];\n\n constructor(\n private readonly client: Client | undefined,\n readonly name: string,\n readonly op?: string,\n /** Correlaciona a uma execução do agente — preenchido pelo runner */\n private readonly runId?: string,\n options: { echo?: boolean } = {}\n ) {\n this.echo = options.echo ?? false;\n this.emit('transaction', 'start', op ? `${name} (${op})` : name);\n }\n\n // ── Lifecycle / eco ───────────────────────────────────────────────────────\n\n /**\n * Registra o início/fim de uma etapa ou da transaction: espelha a linha no sink de\n * lifecycle, se conectado (é assim que os eventos de performance aparecem nos logs da\n * run no app), e ecoa no terminal com `debug: true` — ou, no modo local, só o FINISH das\n * etapas (`[hobots:step] FINISH …`), para o Studio e o dev verem.\n */\n emit(\n kind: 'transaction' | 'step',\n phase: 'start' | 'finish',\n label: string,\n startTs?: string,\n endTs?: string,\n status?: StepStatus | string,\n reason?: string\n ): void {\n const durationMs = startTs && endTs ? new Date(endTs).getTime() - new Date(startTs).getTime() : undefined;\n const suffix = (durationMs != null ? ` (${durationMs}ms)` : '') + (reason ? `: ${reason}` : '');\n\n const localFinish = this.echo && kind === 'step' && phase === 'finish';\n if (this.client?.debug || localFinish) {\n const tag = colorize(`[hobots:${kind}] ${phase.toUpperCase()}`, phase === 'finish' ? colorForStatus(status ?? 'ok') : 'cyan');\n console.log(`${tag} ${label}${suffix}`);\n }\n\n const level: RunLogLevel = phase === 'finish' ? levelForStatus(status ?? 'ok') : 'info';\n const message = `[${kind}] ${phase.toUpperCase()} ${label}${suffix}`;\n if (this.lifecycleSink) this.lifecycleSink(level, message);\n // sem sink (transaction fora de run): backlog capado — nunca vai ser drenado\n else if (this.lifecycleBacklog.length < MAX_BACKLOG) this.lifecycleBacklog.push([level, message]);\n }\n\n /** Conecta o espelho de lifecycle (RunReporter) e faz replay do backlog em ordem. */\n setLifecycleSink(sink: LifecycleSink): void {\n this.lifecycleSink = sink;\n const backlog = this.lifecycleBacklog;\n this.lifecycleBacklog = [];\n for (const [level, message] of backlog) sink(level, message);\n }\n\n /** Conecta o pipeline de anexos da run — é o que dá imagem às etapas. */\n setAttachmentSink(sink: AttachmentSink): void {\n this.attachmentSink = sink;\n }\n\n /** Imagem de uma etapa → id do anexo pela run; sem run, descarta com aviso único. */\n attachImage(image: ImageInput): string | undefined {\n if (this.attachmentSink) return this.attachmentSink(image, nowISO());\n if (!this.warnedNoAttachmentSink) {\n this.warnedNoAttachmentSink = true;\n console.warn('[hobots] imagem de etapa descartada — só é suportada dentro de uma execução');\n }\n return undefined;\n }\n\n // ── Etapas ────────────────────────────────────────────────────────────────\n\n /**\n * Conecta a checagem de cancelamento chamada antes de cada etapa nova (inclusive antes de\n * cada nova tentativa) — é assim que `hobots.step()` para uma run cancelada.\n */\n setStepGuard(guard: () => void): void {\n this.stepGuard = guard;\n }\n\n /** A etapa aberta por `step()` (ou `items.each`) no contexto async atual, se houver. */\n currentStep(): Step | undefined {\n return currentStep(this);\n }\n\n /** Faz de `step` a etapa corrente durante `fn` (filhas aninham nela). Sem etapa, só roda `fn`. */\n scope<T>(step: Step | undefined, fn: () => Promise<T>): Promise<T> {\n if (!step) return fn();\n return runWithStepScope({ transaction: this, step }, fn);\n }\n\n /** Abre uma etapa sob a corrente (ou direta da transaction). Interno: o bot usa `step()`. */\n start(op?: string, description?: string): Step {\n this.stepGuard?.();\n const parent = this.currentStep();\n const step = new Step(this, parent ? parent.stepId : this.stepId, op, description);\n this.steps.push(step);\n this.emit('step', 'start', stepLabel(op, description));\n return step;\n }\n\n /**\n * Registra a etapa `name` executando `fn(etapa)` até dar certo ou esgotar `retries`\n * tentativas extras (default 1), esperando `retryDelayMs` entre elas (default 5 000).\n * Resolve com o retorno de `fn`.\n *\n * Uma etapa só no waterfall, cobrindo todas as tentativas: `data.attempts` quando houve\n * mais de uma; `warning` com o motivo quando a última deu certo; `error` (e a exceção\n * sobe) quando esgotou; `cancelled` em cancelamento/timeout, que nunca repetem.\n */\n async step<T>(name: string, fn: StepFn<T>, options: StepOptions & StepInternalOptions = {}): Promise<T> {\n const requested = options.retries ?? DEFAULT_STEP_RETRIES;\n const totalRetries = Number.isFinite(requested) ? Math.max(0, Math.floor(requested)) : DEFAULT_STEP_RETRIES;\n const step = this.start(undefined, safeString(name));\n let attempts = 0;\n let lastFailure: { error: unknown } | undefined;\n\n try {\n const result = await retryWithBackoff(\n attempt => {\n attempts = attempt;\n return this.scope(step, async () => fn(step));\n },\n {\n retries: totalRetries,\n delayMs: attempt => resolveDelay(options.retryDelayMs, attempt, DEFAULT_STEP_RETRY_DELAY_MS),\n signal: options.signal,\n wait: options.wait,\n onRetry: (error, attempt, delayMs) => {\n lastFailure = { error };\n options.warn?.(\n `etapa \"${step.description}\": tentativa ${attempt}/${totalRetries + 1} falhou: ${truncate(errorReason(error), 500)} — nova tentativa em ${delayMs}ms`\n );\n },\n }\n );\n this.noteAttempts(step, attempts);\n if (lastFailure && step.status === 'ok') {\n step._setStatus('warning', `tentativa ${attempts - 1}/${totalRetries + 1} falhou: ${errorReason(lastFailure.error)}`);\n }\n step._close();\n return result;\n } catch (error) {\n this.noteAttempts(step, attempts);\n // cancelamento/timeout/shutdown: não é falha da etapa — a run para aqui\n if (isTerminalError(error)) step._setStatus('cancelled')._close();\n else step._failed(error);\n throw error;\n }\n }\n\n private noteAttempts(step: Step, attempts: number): void {\n if (attempts > 1) step._setData('attempts', attempts);\n }\n\n // ── Metadados ─────────────────────────────────────────────────────────────\n\n setStatus(status: string): this {\n this.status = status;\n return this;\n }\n\n // ── Encerramento ──────────────────────────────────────────────────────────\n\n /**\n * Envia já as etapas raiz finalizadas (e todas as descendentes, fechando as que\n * ficaram abertas) como transactions parciais da mesma run (`op` hobots.run.flush,\n * `event_id` novo, até 200 etapas cada) e as tira da memória. Etapas raiz ainda abertas\n * ficam para o próximo flush ou para o `finish()`. É assim que um agente sempre\n * ligado (`start()`), cuja run não termina, entrega as etapas enquanto processa.\n * Devolve quantas etapas foram enviadas (0 sem client, sem nada terminado ou depois do `finish()`).\n */\n flush(): number {\n if (!this.client || this.finished) return 0;\n const ready = new Set<string>();\n for (const step of this.steps) {\n if (step.parentStepId === this.stepId && step.endTimestamp) ready.add(step.stepId);\n }\n if (ready.size === 0) return 0;\n\n // descendentes das raízes prontas (as etapas estão em ordem de criação: o pai vem antes)\n const batch: Step[] = [];\n const remaining: Step[] = [];\n for (const step of this.steps) {\n if (ready.has(step.stepId) || ready.has(step.parentStepId)) {\n ready.add(step.stepId);\n batch.push(step);\n } else {\n remaining.push(step);\n }\n }\n for (const step of batch) step._close();\n this.steps.splice(0, this.steps.length, ...remaining);\n\n for (let i = 0; i < batch.length; i += MAX_STEPS) {\n const chunk = batch.slice(i, i + MAX_STEPS);\n const startTimestamp = chunk.reduce((min, step) => (step.startTimestamp < min ? step.startTimestamp : min), chunk[0]!.startTimestamp);\n const status = chunk.some(step => step.status === 'error') ? 'error' : 'ok';\n this.client.sendTransaction(this.payload(uuid4(), FLUSH_TRANSACTION_OP, status, startTimestamp, nowISO(), chunk));\n }\n return batch.length;\n }\n\n /** Entrega já (com teto) o que está na fila do transport — as transactions parciais inclusive. */\n async drain(timeoutMs: number): Promise<void> {\n await this.client?.flush(timeoutMs);\n }\n\n private payload(eventId: string, op: string | undefined, status: string, startTimestamp: string, timestamp: string, steps: Step[]): TransactionPayload {\n return {\n event_id: eventId,\n name: this.name,\n op,\n status,\n start_timestamp: startTimestamp,\n timestamp,\n steps: steps.map(step => step.toJSON()),\n // sem tags próprias: o client mescla as do processo\n tags: undefined,\n run_id: this.runId,\n };\n }\n\n finish(): void {\n if (this.finished) return;\n this.finished = true;\n\n for (const step of this.steps) step._close();\n\n const endTimestamp = nowISO();\n this.emit(\n 'transaction',\n 'finish',\n this.op ? `${this.name} (${this.op})` : this.name,\n this.startTimestamp,\n endTimestamp,\n this.status\n );\n\n if (!this.client) return;\n // o que sobrou depois dos flushes; acima de 200 etapas, o excedente vai em transactions\n // parciais antes — a final (event_id original) fecha a run com o restante\n const steps = this.steps;\n let first = 0;\n while (steps.length - first > MAX_STEPS) {\n const chunk = steps.slice(first, first + MAX_STEPS);\n const status = chunk.some(step => step.status === 'error') ? 'error' : 'ok';\n this.client.sendTransaction(this.payload(uuid4(), FLUSH_TRANSACTION_OP, status, chunk[0]!.startTimestamp, endTimestamp, chunk));\n first += MAX_STEPS;\n }\n this.client.sendTransaction(this.payload(this.eventId, this.op, this.status, this.startTimestamp, endTimestamp, steps.slice(first)));\n }\n}\n","import type { RunItemStatus } from './protocol';\nimport type { RunItemHandle, RunItemImageOptions, RunItemsEachHandler, RunItemsEachOptions, RunItemsEachResult } from './types';\nimport type { ImageInput } from './attachments';\nimport { isOccurrence, isTerminalError, type Occurrence } from './errors';\nimport { DEFAULT_STEP_RETRY_DELAY_MS, errorReason, type Step } from '../transaction';\nimport { resolveDelay, retryWithBackoff } from '../retry';\nimport { safeString, truncate, uuid4 } from '../utils';\n\n/** Campo lido por padrão quando `options.id` não é informado (ausente no elemento = sem id). */\nexport const DEFAULT_ITEM_ID_FIELD = 'id';\n/** Tentativas extras por elemento por padrão (`retries: 0` desliga). */\nexport const DEFAULT_EACH_RETRIES = 1;\n/** Separador dos campos de uma chave composta. */\nconst ID_SEPARATOR = '|';\n\n/**\n * O que o loop de `items.each` precisa do reporter. Dentro de uma run o RunReporter\n * liga tudo (itens, steps, progresso, cancelamento); fora dela o `hobots` global passa\n * um sink inerte — o handler roda igual, só não reporta.\n */\nexport interface EachSink {\n report(\n status: RunItemStatus,\n message: string | undefined,\n payload: Record<string, unknown> | undefined,\n id: string | undefined,\n image: ImageInput | undefined\n ): void;\n startStep(op: string, description: string): Step | undefined;\n /** Roda `fn` com `step` como etapa corrente — `hobots.step` no handler do item aninha nela. */\n stepScope(step: Step | undefined, fn: () => Promise<unknown>): Promise<unknown>;\n /** Declara o total só se o bot ainda não declarou um (o dele vence). */\n declareTotal(total: number): void;\n advance(): void;\n checkCanceled(): void;\n isAborted(): boolean;\n logInfo(message: string): void;\n logWarning(message: string): void;\n logError(message: string): void;\n /** Espera cancelável entre as tentativas de um elemento (o `ctx.sleep` da run). */\n sleep(ms: number): Promise<void>;\n /** Ids já concluídos neste trabalho (reexecução); undefined = sem consulta/falhou. Nunca lança. */\n doneItemIds(): Promise<Set<string> | undefined>;\n /** `hobots.flush()` da run — chamado ao fim de cada ciclo (opção `flush`). Nunca lança. */\n flush(): Promise<void>;\n}\n\n/** Mensagem legível de qualquer valor lançado (o `addItem` trunca/scrubba depois). */\nexport function thrownMessage(error: unknown): string {\n if (error instanceof Error) return error.message || error.name;\n return safeString(error);\n}\n\nclass ItemHandle<T> implements RunItemHandle<T> {\n /** A identidade resolvida por `options.id` ou, sem ela, uma gerada — a mesma em todas as tentativas. */\n readonly id: string;\n reported = false;\n status: RunItemStatus | undefined;\n attempt = 1;\n private accumulated: Record<string, unknown> = {};\n\n constructor(\n readonly value: T,\n readonly index: number,\n id: string | undefined,\n readonly step: Step | undefined,\n private readonly basePayload: Record<string, unknown> | undefined,\n private readonly sink: EachSink\n ) {\n this.id = id ?? uuid4();\n }\n\n data(payload: Record<string, unknown>): void {\n Object.assign(this.accumulated, payload);\n }\n\n succeeded(payload?: Record<string, unknown>, options?: RunItemImageOptions): void {\n this.record('succeeded', undefined, payload, options?.image);\n }\n\n failed(message: string, payload?: Record<string, unknown>, options?: RunItemImageOptions): void {\n this.record('failed', message, payload, options?.image);\n // o handler decidiu que é falha sem lançar: a etapa acompanha com o motivo\n // (a imagem fica só no item — um upload por print, sem duplicar na etapa)\n if (this.step && this.step.status !== 'error') this.step._setStatus('error', message);\n }\n\n occurrence(message: string, payload?: Record<string, unknown>, options?: RunItemImageOptions): void {\n this.record('occurrence', message, payload, options?.image);\n if (this.step && this.step.status === 'ok') this.step._setStatus('warning', message);\n }\n\n /** Nova tentativa: o desfecho da anterior não vale (o id é o mesmo, o último reporte vence). */\n _nextAttempt(attempt: number): void {\n this.attempt = attempt;\n this.reported = false;\n this.status = undefined;\n this.accumulated = {};\n if (this.step && (this.step.status === 'error' || this.step.status === 'warning')) {\n this.step._setStatus('ok');\n this.step._deleteData('message');\n }\n }\n\n private record(\n status: RunItemStatus,\n message: string | undefined,\n payload: Record<string, unknown> | undefined,\n image: ImageInput | undefined\n ): void {\n this.reported = true;\n this.status = status;\n const merged = { ...(this.basePayload ?? {}), ...this.accumulated, ...(payload ?? {}) };\n this.sink.report(status, message, Object.keys(merged).length > 0 ? merged : undefined, this.id, image);\n }\n}\n\n/**\n * Payload base padrão (sem `options.payload`): os campos do elemento quando ele é um objeto simples —\n * protótipo `Object.prototype` ou `null`. Instância de classe (Locator, ElementHandle, Date…), array,\n * Map e primitivo ficam de fora: não viram colunas nem arriscam serializar um objeto do navegador.\n */\nexport function defaultPayload(element: unknown): Record<string, unknown> | undefined {\n if (typeof element !== 'object' || element === null) return undefined;\n const proto = Object.getPrototypeOf(element) as unknown;\n if (proto !== Object.prototype && proto !== null) return undefined;\n const copy = { ...(element as Record<string, unknown>) };\n return Object.keys(copy).length > 0 ? copy : undefined;\n}\n\nfunction basePayload<T>(spec: RunItemsEachOptions<T>['payload'], element: T, index: number): Record<string, unknown> | undefined {\n if (spec === false) return undefined;\n if (spec === undefined) return defaultPayload(element);\n return spec(element, index);\n}\n\nfunction field(element: unknown, name: string): { present: boolean; value: unknown } {\n if (typeof element !== 'object' || element === null) return { present: false, value: undefined };\n const record = element as Record<string, unknown>;\n return { present: name in record, value: record[name] };\n}\n\n/**\n * `options.id` → identidade do item (undefined = o SDK gera uma, e o item nunca é pulado).\n * Campo (ou campos) inexistente(s) no elemento: com `id` explícito é erro do bot (lança, fora\n * da proteção do loop — como já valia para a função de `id`); com o padrão (`id` do\n * elemento) é só \"sem id\".\n */\nexport function resolveId<T>(spec: RunItemsEachOptions<T>['id'], element: T, index: number, explicit: boolean): string | undefined {\n if (spec === null) return undefined;\n let raw: unknown;\n if (typeof spec === 'function') {\n raw = spec(element, index);\n } else {\n const fields = spec === undefined ? [DEFAULT_ITEM_ID_FIELD] : typeof spec === 'string' ? [spec] : spec;\n const parts: string[] = [];\n for (const name of fields) {\n const { present, value } = field(element, name);\n if (!present || value === null || value === undefined) {\n if (explicit) {\n throw new Error(\n `items.each: elemento #${index + 1} não tem o campo \"${name}\" informado em id — passe o nome certo, uma lista de campos ou uma função (elemento, índice) => id`\n );\n }\n return undefined;\n }\n parts.push(safeString(value));\n }\n raw = parts.join(ID_SEPARATOR);\n }\n if (raw === null || raw === undefined) return undefined;\n const text = safeString(raw);\n return text.length > 0 ? text : undefined;\n}\n\n/** `length` numérica (array, lista) vira o total do progresso; iteráveis sem tamanho não declaram nada. */\nfunction knownLength(list: unknown): number | undefined {\n const length = (list as { length?: unknown } | null)?.length;\n return typeof length === 'number' && Number.isInteger(length) && length >= 1 ? length : undefined;\n}\n\nfunction skippedMessage(count: number): string {\n if (count === 1) return '1 item pulado: já concluído neste trabalho numa execução anterior';\n return `${count} itens pulados: já concluídos neste trabalho numa execução anterior`;\n}\n\n/**\n * Processa uma lista item a item com o contrato da plataforma garantido pelo SDK:\n * cada elemento vira uma etapa e um item. O handler recebe `(item, index)`: o elemento\n * em `item.value` (seus campos viram o payload base do item, salvo `options.payload`). O handler **retornou** → `succeeded`; **lançou**\n * → nova tentativa (`retries`, default 1; `0` desliga; `retryDelayMs` entre elas, default\n * 5 000) e, esgotadas, item `failed` com a mensagem do erro, etapa `error`, e o loop\n * **segue para o próximo**; lançou `Occurrence` → item `occurrence` na hora, sem nova\n * tentativa. A lista inteira é processada e o progresso avança a cada elemento. Só o\n * cancelamento (RunCanceled/abort), o timeout e o shutdown interrompem o loop.\n *\n * Com `options.id` (campo, chave composta ou função; default: o campo `id` do elemento),\n * a reexecução do mesmo trabalho pula o item que já deu `succeeded`/`occurrence` — só\n * `failed` roda de novo (`skipDone: false` desliga). Ao fim de cada ciclo faz o flush da\n * run (`flush: false` desliga).\n */\nexport async function eachItem<T>(\n list: Iterable<T> | AsyncIterable<T>,\n handler: RunItemsEachHandler<T>,\n options: RunItemsEachOptions<T>,\n sink: EachSink\n): Promise<RunItemsEachResult> {\n const result: RunItemsEachResult = { total: 0, succeeded: 0, failed: 0, occurrence: 0, skipped: 0 };\n const requested = options.retries ?? DEFAULT_EACH_RETRIES;\n const totalRetries = Number.isFinite(requested) ? Math.max(0, Math.floor(requested)) : DEFAULT_EACH_RETRIES;\n const explicitId = options.id !== undefined;\n const length = options.progress === false ? undefined : knownLength(list);\n if (length !== undefined) sink.declareTotal(length);\n // o que já deu certo neste trabalho (reexecução) — consulta única; undefined = sem consulta/falhou\n const done = options.skipDone === false ? undefined : await sink.doneItemIds();\n\n let index = 0;\n for await (const element of list) {\n sink.checkCanceled();\n const id = resolveId(options.id, element, index, explicitId);\n if (done?.size && id !== undefined && done.has(id)) {\n // já concluído (succeeded/occurrence) numa execução anterior deste trabalho\n result.total += 1;\n result.skipped += 1;\n if (options.progress !== false) sink.advance();\n index += 1;\n continue;\n }\n const description = options.description?.(element, index) ?? id ?? `#${index + 1}`;\n const step = sink.startStep(options.op ?? 'item', description);\n const handle = new ItemHandle(element, index, id, step, basePayload(options.payload, element, index), sink);\n const current = index;\n let attempts = 0;\n let lastFailure: { error: unknown } | undefined;\n\n try {\n await retryWithBackoff(\n attempt => {\n attempts = attempt;\n if (attempt > 1) handle._nextAttempt(attempt);\n return sink.stepScope(step, async () => handler(handle, current));\n },\n {\n retries: totalRetries,\n delayMs: attempt => resolveDelay(options.retryDelayMs, attempt, DEFAULT_STEP_RETRY_DELAY_MS),\n // sem nova tentativa: ocorrência (regra de negócio), desfecho já registrado pelo\n // handler (ele decidiu) ou run abortada (o erro é efeito do cancelamento)\n shouldRetry: error => !isOccurrence(error) && !handle.reported && !sink.isAborted(),\n wait: ms => sink.sleep(ms),\n onRetry: (error, attempt, delayMs) => {\n lastFailure = { error };\n sink.logWarning(\n `item ${description}: tentativa ${attempt}/${totalRetries + 1} falhou: ${truncate(errorReason(error), 500)} — nova tentativa em ${delayMs}ms`\n );\n },\n }\n );\n if (!handle.reported) handle.succeeded();\n if (step) {\n noteAttempts(step, attempts);\n if (lastFailure && step.status === 'ok') {\n step._setStatus('warning', `tentativa ${attempts - 1}/${totalRetries + 1} falhou: ${errorReason(lastFailure.error)}`);\n }\n }\n } catch (error) {\n if (isTerminalError(error) || sink.isAborted()) {\n // cancelamento/timeout/shutdown: não é falha do item — a run para aqui\n step?._setStatus('cancelled')._close();\n throw error;\n }\n if (step) noteAttempts(step, attempts);\n if (isOccurrence(error)) {\n // regra de negócio: ocorrência, sem log de erro — a etapa vira warning pelo handle\n const occurrence = error as Occurrence;\n if (!handle.reported) handle.occurrence(occurrence.message, occurrence.payload, { image: occurrence.image });\n } else {\n const message = thrownMessage(error);\n if (!handle.reported) handle.failed(message);\n // lançou: a etapa é erro mesmo que o handler já tenha registrado ocorrência\n step?._failed(error);\n sink.logError(`item ${description} falhou: ${message}`);\n }\n }\n\n step?._close();\n if (options.progress !== false) sink.advance();\n result.total += 1;\n /* v8 ignore start -- o handle sempre está reportado aqui (succeeded/failed/occurrence acima); o ?? só satisfaz o tipo */\n result[handle.status ?? 'succeeded'] += 1;\n /* v8 ignore stop */\n index += 1;\n // fim do ciclo: a etapa do item, o item e os logs saem agora, não no fim da run\n if (options.flush !== false) await sink.flush();\n }\n if (result.skipped > 0) sink.logInfo(skippedMessage(result.skipped));\n return result;\n}\n\nfunction noteAttempts(step: Step, attempts: number): void {\n if (attempts > 1) step._setData('attempts', attempts);\n}\n","import type { FileRef } from './protocol';\nimport { TasksApiError, type RunTransport } from './api';\nimport { runCanceledError } from './errors';\nimport { isLocalRun } from '../env';\n\n/** Pasta onde o Studio deixa os arquivos escolhidos localmente: `<dir>/<id>/<nome>`. */\nexport const LOCAL_FILES_DIR_ENV = 'HOBOTS_LOCAL_FILES_DIR';\n/**\n * Sem nenhum byte novo por este tempo, o download é abortado (e pode ser tentado de novo).\n * Não é um teto total — arquivo grande em rede lenta não morre por isso. Espelha o timeout\n * de socket do SDK Python.\n */\nexport const FILE_DOWNLOAD_IDLE_TIMEOUT_MS = 60_000;\n\nconst UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\n\nexport interface FileDownloadOptions {\n /**\n * Destino da cópia: uma pasta existente (ou terminada em `/`) recebe o arquivo com o nome\n * original; qualquer outro caminho é o arquivo final. Omitido: pasta temporária da\n * execução, apagada quando ela termina.\n */\n dest?: string;\n}\n\n/**\n * Arquivos dos campos de upload do formulário (`hobots.files`). O valor do campo nos\n * params é um `FileRef` (ou uma lista deles); `download` traz o arquivo para o disco\n * desta máquina — do S3 (enviado pela Central) ou da pasta do Studio (mesmo computador)\n * — e o consome na origem: cada arquivo é baixado uma vez.\n */\nexport interface RunFiles {\n /** Todos os arquivos dos params (campos de topo, valor único ou lista), na ordem dos campos. */\n list(): FileRef[];\n /** O arquivo do campo (campo único), a lista (campo \"vários arquivos\") ou undefined. */\n get(field: string): FileRef | FileRef[] | undefined;\n /**\n * Baixa um arquivo e resolve com o caminho local. Aceita o `FileRef` ou o nome de um\n * campo de arquivo único (para campo com vários arquivos, use `downloadAll`). Só depois\n * da cópia completa e conferida o arquivo é consumido na origem — uma falha não perde\n * nada e pode ser tentada de novo. Respeita o cancelamento da execução.\n */\n download(refOrField: FileRef | string, options?: FileDownloadOptions): Promise<string>;\n /** Baixa todos os arquivos do campo (único ou lista), em ordem. `dest` aqui é uma pasta. */\n downloadAll(field: string, options?: FileDownloadOptions): Promise<string[]>;\n /** Conteúdo do arquivo em memória — baixa, lê e apaga a cópia temporária. */\n read(refOrField: FileRef | string): Promise<Buffer>;\n}\n\n/** O valor tem a forma de um arquivo de campo de upload (mesma regra do `@workspace/task-forms`). */\nexport function isFileRef(value: unknown): value is FileRef {\n if (!value || typeof value !== 'object' || Array.isArray(value)) return false;\n const ref = value as Record<string, unknown>;\n return (\n typeof ref.id === 'string' &&\n typeof ref.name === 'string' &&\n typeof ref.size === 'number' &&\n typeof ref.contentType === 'string' &&\n (ref.storage === 's3' || ref.storage === 'local')\n );\n}\n\n/** Valor de um campo de arquivo: FileRef, lista só de FileRef (vazia inclusive) ou undefined. */\nexport function fileField(params: Record<string, unknown>, field: string): FileRef | FileRef[] | undefined {\n if (!Object.prototype.hasOwnProperty.call(params, field)) return undefined;\n const value = params[field];\n if (isFileRef(value)) return value;\n if (Array.isArray(value) && value.every(isFileRef)) return value;\n return undefined;\n}\n\nexport function collectFileRefs(params: Record<string, unknown>): FileRef[] {\n const refs: FileRef[] = [];\n for (const field of Object.keys(params)) {\n const value = fileField(params, field);\n if (value !== undefined) refs.push(...(Array.isArray(value) ? value : [value]));\n }\n return refs;\n}\n\n/** Nome seguro para o disco: só o último segmento, sem caracteres proibidos no Windows. */\nexport function safeFileName(name: string, fallback: string): string {\n // eslint-disable-next-line no-control-regex\n const cleaned = name.replace(/^.*[\\\\/]/, '').replace(/[\\u0000-\\u001f<>:\"|?*]/g, '_').trim();\n return cleaned === '' || cleaned === '.' || cleaned === '..' ? fallback : cleaned;\n}\n\n/** `candidate` resolvido fica estritamente dentro de `root` (nunca a própria raiz, nunca acima). */\nexport function isInsideDir(root: string, candidate: string, sep: string): boolean {\n const base = root.endsWith(sep) ? root : root + sep;\n return candidate.startsWith(base) && candidate.length > base.length;\n}\n\nfunction unavailableLocal(ref: FileRef): Error {\n return new Error(`arquivo \"${ref.name}\" enviado pelo Studio de outro computador ou já consumido`);\n}\n\n/**\n * Modo local (`HOBOTS_LOCAL_RUN=1`): o FileRef `local` pode trazer a chave extra `path` — o\n * caminho do próprio arquivo (a CLI `hobots run --file` monta assim). Fora do modo local a\n * chave é ignorada e vale só o formato `<HOBOTS_LOCAL_FILES_DIR>/<uuid>/<nome>`.\n */\nfunction localRunPath(ref: FileRef): string | undefined {\n if (!isLocalRun()) return undefined;\n const path = (ref as { path?: unknown }).path;\n return typeof path === 'string' && path.trim() !== '' ? path : undefined;\n}\n\n/** Erro `.code` do Node (ENOENT…) sem depender do tipo. */\nfunction errorCode(error: unknown): unknown {\n return (error as { code?: unknown } | null)?.code;\n}\n\nexport interface RunFileStoreDeps {\n api: RunTransport;\n runId: string;\n params: Record<string, unknown>;\n signal: AbortSignal;\n /** Aviso na linha de log da execução (ex.: confirmação que não chegou ao servidor). */\n warn: (message: string) => void;\n /** Só para testes: default `FILE_DOWNLOAD_IDLE_TIMEOUT_MS`. */\n idleTimeoutMs?: number;\n}\n\n/**\n * Estado dos arquivos de UMA execução: a pasta temporária (criada sob demanda) e a\n * implementação de `RunFiles`. O runner chama `cleanup()` no fim da execução.\n */\nexport class RunFileStore {\n readonly files: RunFiles;\n private tempDir: Promise<string> | undefined;\n\n constructor(private readonly deps: RunFileStoreDeps) {\n this.files = {\n list: () => collectFileRefs(deps.params),\n get: field => fileField(deps.params, field),\n // async: erro de uso (campo sem arquivo, valor inválido) chega como Promise rejeitada, nunca síncrono\n download: async (refOrField, options) => this.download(this.single(refOrField), options?.dest),\n downloadAll: async (field, options) => this.downloadAll(field, options?.dest),\n read: async refOrField => this.read(this.single(refOrField)),\n };\n }\n\n /** Apaga a pasta temporária da execução (cópias que o bot não levou para `dest`). Nunca lança. */\n async cleanup(): Promise<void> {\n const pending = this.tempDir;\n this.tempDir = undefined;\n if (!pending) return;\n try {\n const { rm } = await import('node:fs/promises');\n await rm(await pending, { recursive: true, force: true });\n } catch {\n // limpeza é conforto: o sistema operacional recolhe a pasta temporária\n }\n }\n\n private field(field: string): FileRef | FileRef[] {\n const value = fileField(this.deps.params, field);\n if (value === undefined) throw new Error(`campo \"${field}\" não tem arquivo nos params`);\n return value;\n }\n\n private single(refOrField: FileRef | string): FileRef {\n if (typeof refOrField === 'string') {\n const value = this.field(refOrField);\n if (Array.isArray(value)) {\n throw new Error(`campo \"${refOrField}\" tem vários arquivos — use downloadAll(\"${refOrField}\") ou passe um item da lista`);\n }\n return value;\n }\n if (!isFileRef(refOrField)) throw new TypeError('esperado um FileRef ou o nome de um campo de arquivo');\n return refOrField;\n }\n\n private async downloadAll(field: string, dest: string | undefined): Promise<string[]> {\n const value = this.field(field);\n const refs = Array.isArray(value) ? value : [value];\n const paths: string[] = [];\n // aqui `dest` é sempre pasta: cada arquivo entra com o próprio nome\n for (const ref of refs) paths.push(await this.download(ref, dest, true));\n return paths;\n }\n\n private async read(ref: FileRef): Promise<Buffer> {\n const { readFile, rm } = await import('node:fs/promises');\n const { dirname } = await import('node:path');\n const path = await this.download(ref, undefined);\n try {\n return await readFile(path);\n } finally {\n // sem `dest`, a cópia mora numa subpasta só dela dentro da pasta temporária da run\n await rm(dirname(path), { recursive: true, force: true });\n }\n }\n\n private async download(ref: FileRef, dest: string | undefined, destIsDir = false): Promise<string> {\n this.checkCanceled();\n const target = await this.resolveTarget(ref, dest, destIsDir);\n if (ref.storage === 'local') await this.copyLocal(ref, target);\n else await this.downloadS3(ref, target); // no modo local o transporte recusa com o nome do arquivo\n return target;\n }\n\n private checkCanceled(): void {\n if (this.deps.signal.aborted) throw runCanceledError();\n }\n\n private runTempDir(): Promise<string> {\n this.tempDir ??= (async () => {\n const { mkdtemp } = await import('node:fs/promises');\n const { tmpdir } = await import('node:os');\n const { join } = await import('node:path');\n return mkdtemp(join(tmpdir(), 'hobots-files-'));\n })();\n return this.tempDir;\n }\n\n private async resolveTarget(ref: FileRef, dest: string | undefined, destIsDir: boolean): Promise<string> {\n const { mkdir, mkdtemp, stat } = await import('node:fs/promises');\n const { dirname, join, resolve } = await import('node:path');\n const name = safeFileName(ref.name, 'arquivo');\n if (dest === undefined) {\n // uma subpasta por download: dois arquivos com o mesmo nome não colidem\n return join(await mkdtemp(join(await this.runTempDir(), 'f-')), name);\n }\n const isDir =\n destIsDir || dest.endsWith('/') || dest.endsWith('\\\\') || (await stat(dest).catch(() => undefined))?.isDirectory() === true;\n if (isDir) {\n await mkdir(dest, { recursive: true });\n return resolve(dest, name);\n }\n await mkdir(dirname(resolve(dest)), { recursive: true });\n return resolve(dest);\n }\n\n /** storage 's3': URL pré-assinada → GET em streaming → confere o tamanho → só então DELETE. */\n private async downloadS3(ref: FileRef, target: string): Promise<void> {\n const { api, runId, signal } = this.deps;\n let expected: number;\n let url: string;\n try {\n const info = await api.requestFileDownload(runId, ref.id, signal);\n expected = info.size >= 0 ? info.size : ref.size;\n url = info.url;\n } catch (error) {\n throw this.translate(error, ref);\n }\n\n const { open, rename, rm } = await import('node:fs/promises');\n const part = `${target}.part`;\n const idleTimeoutMs = this.deps.idleTimeoutMs ?? FILE_DOWNLOAD_IDLE_TIMEOUT_MS;\n const controller = new AbortController();\n let timedOut = false;\n let timer: ReturnType<typeof setTimeout> | undefined;\n const arm = (): void => {\n clearTimeout(timer);\n timer = setTimeout(() => {\n timedOut = true;\n controller.abort();\n }, idleTimeoutMs);\n };\n const onCancel = (): void => controller.abort();\n signal.addEventListener('abort', onCancel, { once: true });\n try {\n arm();\n const response = await api.fetchFile(url, controller.signal);\n const handle = await open(part, 'w');\n let written = 0;\n try {\n const reader = response.body?.getReader();\n // cancelamento/ociosidade param a leitura mesmo onde o fetch não liga o signal ao corpo\n const stopReading = (): void => void reader?.cancel().catch(() => undefined);\n controller.signal.addEventListener('abort', stopReading, { once: true });\n for (;;) {\n const chunk = reader ? await reader.read() : { done: true as const, value: undefined };\n if (chunk.done) break;\n arm();\n written += chunk.value.byteLength;\n if (written > expected) {\n // maior que o anunciado: não enche o disco à toa\n stopReading();\n break;\n }\n await handle.write(chunk.value);\n }\n } finally {\n await handle.close();\n }\n if (written !== expected) {\n throw new Error(`tamanho divergente no download de \"${ref.name}\": recebidos ${written} bytes, esperados ${expected}`);\n }\n await rename(part, target);\n } catch (error) {\n await rm(part, { force: true });\n if (signal.aborted) throw runCanceledError();\n if (timedOut) {\n throw new Error(`download de \"${ref.name}\" parado há ${idleTimeoutMs / 1000}s — tente de novo`);\n }\n throw this.translate(error, ref);\n } finally {\n clearTimeout(timer);\n signal.removeEventListener('abort', onCancel);\n }\n\n try {\n await api.confirmFileDownload(runId, ref.id);\n } catch (error) {\n // o arquivo já está no disco: a falha só adia a limpeza (o servidor apaga quando expirar)\n this.deps.warn(`arquivo \"${ref.name}\" baixado, mas a confirmação ao servidor falhou: ${String(error)}`);\n }\n }\n\n /**\n * storage 'local': copia o único arquivo de `$HOBOTS_LOCAL_FILES_DIR/<id>/` e apaga a pasta de\n * origem. No modo local, um FileRef com `path` copia direto desse caminho, sem apagar a origem.\n */\n private async copyLocal(ref: FileRef, target: string): Promise<void> {\n const direct = localRunPath(ref);\n if (direct !== undefined) {\n await this.copyFromPath(ref, direct, target);\n return;\n }\n const base = process.env[LOCAL_FILES_DIR_ENV];\n if (!base) throw unavailableLocal(ref);\n const { copyFile, readdir, rename, rm, stat } = await import('node:fs/promises');\n const { join, resolve, sep } = await import('node:path');\n const root = resolve(base);\n const folder = resolve(root, ref.id);\n // duas travas: a pasta resolvida fica DENTRO do diretório (pega `..`, caminho absoluto)\n // e o id tem a forma que o Studio gera (uuid) — nada além disso vira caminho no disco\n if (!isInsideDir(root, folder, sep) || !UUID_RE.test(ref.id)) {\n throw new Error(`id de arquivo local inválido: ${JSON.stringify(ref.id)}`);\n }\n\n let names: string[];\n try {\n // só arquivos regulares: link simbólico não conta (não copia nada de fora da pasta)\n names = (await readdir(folder, { withFileTypes: true })).filter(entry => entry.isFile()).map(entry => entry.name);\n } catch (error) {\n if (errorCode(error) === 'ENOENT' || errorCode(error) === 'ENOTDIR') throw unavailableLocal(ref);\n throw error;\n }\n if (names.length === 0) throw unavailableLocal(ref);\n if (names.length > 1) throw new Error(`pasta do arquivo \"${ref.name}\" tem ${names.length} arquivos — esperado 1`);\n\n this.checkCanceled();\n const part = `${target}.part`;\n try {\n await copyFile(join(folder, names[0]!), part);\n const { size } = await stat(part);\n if (size !== ref.size) {\n throw new Error(`tamanho divergente na cópia de \"${ref.name}\": copiados ${size} bytes, esperados ${ref.size}`);\n }\n await rename(part, target);\n } catch (error) {\n await rm(part, { force: true });\n throw error;\n }\n await rm(folder, { recursive: true, force: true });\n }\n\n /**\n * Modo local: cópia do arquivo apontado por `path` (teste roda várias vezes — a fonte fica).\n * Sem conferência de tamanho: o `size` do FileRef é informativo aqui.\n */\n private async copyFromPath(ref: FileRef, path: string, target: string): Promise<void> {\n const { copyFile, rename, rm, stat } = await import('node:fs/promises');\n const { resolve } = await import('node:path');\n const source = resolve(path);\n const info = await stat(source).catch(() => undefined);\n if (!info?.isFile()) throw new Error(`arquivo \"${ref.name}\" não encontrado em ${path}`);\n this.checkCanceled();\n const part = `${target}.part`;\n try {\n await copyFile(source, part);\n await rename(part, target);\n } catch (error) {\n await rm(part, { force: true });\n throw error;\n }\n }\n\n private translate(error: unknown, ref: FileRef): unknown {\n if (this.deps.signal.aborted) return runCanceledError();\n if (error instanceof TasksApiError && error.status === 410) {\n return new TasksApiError(`arquivo \"${ref.name}\" já baixado ou expirado`, 410);\n }\n if (error instanceof TasksApiError && error.status === 404) {\n return new TasksApiError(`arquivo \"${ref.name}\" não encontrado nesta execução`, 404);\n }\n return error;\n }\n}\n","import type {\n RunAttachmentContentType,\n RunError,\n RunItemInput,\n RunItemsDoneResponse,\n RunItemStatus,\n RunProgress,\n RunUpdateRequest,\n RunLogEntry,\n RunLogLevel,\n} from './protocol';\nimport type { RunContext, RunItems, RunLogger, RunProgressReporter } from './types';\nimport { TasksApiError, type RunTransport } from './api';\nimport { eachItem, thrownMessage, type EachSink } from './each';\nimport { RunFileStore } from './files';\nimport { runCanceledError } from './errors';\nimport { retryWithBackoff, type RetryOptions } from '../retry';\nimport {\n ATTACHMENT_DRAIN_MS,\n MAX_ATTACHMENTS_PER_RUN,\n MAX_ATTACHMENT_BYTES,\n MAX_CAPTION_CHARS,\n MAX_CONCURRENT_UPLOADS,\n readPngDimensions,\n sniffContentType,\n toBytes,\n toImageAttachment,\n isImageAttachment,\n type AttachFailureReason,\n type AttachInput,\n type ImageAttachment,\n type ImageInput,\n} from './attachments';\nimport { colorize, nowISO, safeString, truncate, unrefTimer, uuid4, type Logger } from '../utils';\nimport { scrubSecrets } from '../scrub';\nimport type { Transaction } from '../transaction';\nimport { WIRE_LIMITS } from '../wire-limits';\n\nconst LOG_LEVEL_COLOR = {\n debug: 'gray',\n info: 'cyan',\n warning: 'yellow',\n error: 'red',\n success: 'green',\n} as const;\n\n/** `hobots.log.info('a', 1, {b: 2})` → `'a 1 {\"b\":2}'` (estilo `console.log`), sem lançar. */\nexport function joinLogArgs(message: unknown, rest: unknown[]): string {\n if (rest.length === 0) return safeString(message);\n return [message, ...rest].map(safeString).join(' ');\n}\n\n/**\n * Separa o `hobots.image(...)` passado como último argumento do texto da linha. Só a\n * imagem, sem texto (`log.info(hobots.image(png, { caption }))`): a legenda vira a\n * mensagem, como o antigo `attach` fazia.\n */\nexport function splitLogArgs(message: unknown, rest: unknown[]): { text: string; image?: ImageAttachment } {\n const args = [message, ...rest];\n const last = args[args.length - 1];\n if (!isImageAttachment(last)) return { text: joinLogArgs(message, rest) };\n const text = args.slice(0, -1);\n if (text.length === 0) return { text: last.caption !== undefined ? safeString(last.caption) : 'captura de tela', image: last };\n return { text: joinLogArgs(text[0], text.slice(1)), image: last };\n}\n\n/** Ecoa o log da run no terminal local, colorido por nível — o buffer/envio ao servidor é independente disso. */\nexport function printRunLog(level: RunLogLevel, message: string): void {\n const line = colorize(`[hobots] ${level.toUpperCase()}`, LOG_LEVEL_COLOR[level]);\n const method = level === 'warning' ? 'warn' : level === 'success' ? 'info' : level;\n console[method](line, message);\n}\n\n/** Prefixo da linha de progresso legível por máquina no stdout. */\nexport const PROGRESS_LINE_PREFIX = '[hobots:progress]';\n/** Entre dois ecos de progresso intermediários (o total novo e o último valor saem sempre). */\nconst PROGRESS_PRINT_THROTTLE_MS = 250;\n\n/**\n * Linha de progresso no stdout, sem cor: `[hobots:progress] 10/100`. O Hobots Studio lê esta\n * linha para mostrar barra e estimativa quando o bot roda localmente; o envio ao servidor é\n * independente. Espelha o `print_run_progress` do SDK Python.\n */\nexport function printRunProgress(current: number, total: number): void {\n console.log(`${PROGRESS_LINE_PREFIX} ${current}/${total}`);\n}\n\n/**\n * Sleep que respeita o ctx.signal — rejeita com RunCanceled no abort.\n * O timer NÃO é unref'd de propósito: uma run em execução é trabalho legítimo e\n * deve segurar o processo vivo mesmo com o polling já parado (shutdown gracioso).\n */\nfunction cancelableSleep(ms: number, signal: AbortSignal): Promise<void> {\n return new Promise<void>((resolve, reject) => {\n if (signal.aborted) {\n reject(runCanceledError());\n return;\n }\n const onAbort = (): void => {\n clearTimeout(timer);\n reject(runCanceledError());\n };\n const timer = setTimeout(() => {\n signal.removeEventListener('abort', onAbort);\n resolve();\n }, ms);\n signal.addEventListener('abort', onAbort, { once: true });\n });\n}\n\nconst DEFAULT_LOG_FLUSH_INTERVAL_MS = 2_000;\nconst DEFAULT_CANCEL_CHECK_INTERVAL_MS = 5_000;\nconst MIN_CANCEL_CHECK_INTERVAL_MS = 1_000;\n// teto: o PATCH periódico é o sinal de vida da run — o servidor marca como\n// encerrada inesperadamente após ~120s sem reporte, então o intervalo não pode chegar perto disso\nconst MAX_CANCEL_CHECK_INTERVAL_MS = 15_000;\nconst MAX_LOG_MESSAGE_CHARS = WIRE_LIMITS.MAX_LOG_MESSAGE_CHARS;\nconst MAX_LOGS_PER_PATCH = WIRE_LIMITS.MAX_LOGS_PER_PATCH;\nconst FLUSH_AT_BUFFERED = 20;\n\n// Itens de execução — os MESMOS limites do servidor (WIRE_LIMITS; a api importa de hobots/protocol)\nconst MAX_ITEMS_PER_REQUEST = WIRE_LIMITS.MAX_ITEMS_PER_REQUEST;\nconst MAX_ITEMS_DONE_PER_PAGE = WIRE_LIMITS.MAX_ITEMS_DONE_PER_PAGE;\nconst MAX_ITEM_MESSAGE_CHARS = WIRE_LIMITS.MAX_ITEM_MESSAGE_CHARS;\nconst MAX_ITEM_PAYLOAD_BYTES = WIRE_LIMITS.MAX_ITEM_PAYLOAD_BYTES;\nconst ITEMS_FLUSH_AT_BUFFERED = 100;\n/** Teto do dreno de itens antes do PATCH terminal — como o dreno de anexos. */\nconst ITEMS_DRAIN_MS = 15_000;\n\n/**\n * Progresso: `advance()` num loop apertado não pode virar um PATCH por item. O\n * snapshot pega carona em qualquer PATCH que saia (logs, heartbeat, terminal) e,\n * se nada mais estiver a caminho, um flush dedicado dispara depois deste intervalo.\n */\nconst PROGRESS_FLUSH_MS = 1_000;\n\n/** Scrub recursivo das strings do payload (profundidade capada — payload é raso por natureza). */\nfunction scrubPayloadValue(value: unknown, depth: number): unknown {\n if (typeof value === 'string') return scrubSecrets(value);\n if (depth >= 4 || value === null || typeof value !== 'object') return value;\n if (Array.isArray(value)) return value.map(entry => scrubPayloadValue(entry, depth + 1));\n const out: Record<string, unknown> = {};\n for (const [key, entry] of Object.entries(value as Record<string, unknown>)) {\n out[key] = scrubPayloadValue(entry, depth + 1);\n }\n return out;\n}\n\n/**\n * Reporter de uma run: bufferiza logs (flush incremental com throttle) e encadeia\n * todos os PATCHes numa fila única — a ordem running → logs → terminal é garantida.\n * Um 409/404 mata o reporter (run cancelada/finalizada no servidor): o handler não\n * pode ser morto, mas status posterior é suprimido e ctx.signal dispara para abort\n * cooperativo. Logs nunca são descartados em silêncio: falha de rede devolve ao\n * buffer, e depois da morte eles seguem best-effort como \"log tardio\" (o servidor\n * anexa logs a runs terminais mesmo respondendo 409).\n */\nexport class RunReporter {\n readonly context: RunContext;\n\n private buffer: RunLogEntry[] = [];\n private dead = false;\n private chain: Promise<void> = Promise.resolve();\n private pendingUpdates = 0;\n private timer: ReturnType<typeof setTimeout> | undefined;\n private watchTimer: ReturnType<typeof setInterval> | undefined;\n private readonly abortController = new AbortController();\n private readonly flushIntervalMs: number;\n private readonly cancelCheckIntervalMs: number;\n\n // Itens de execução vivem FORA de `this.chain` (status/liveness não pode ficar\n // atrás de milhares de itens), mas têm cadeia própria serializada — ordem de\n // envio preservada e sem lotes sobrepostos.\n private itemsBuffer: RunItemInput[] = [];\n private itemsChain: Promise<void> = Promise.resolve();\n private itemsTimer: ReturnType<typeof setTimeout> | undefined;\n private itemSeq = 0;\n /** Servidor sem o recurso (404) — para de tentar (e de avisar) nesta run. */\n private itemsUnsupported = false;\n /**\n * Cota de itens por run do servidor (429, legado — hoje a api não tem teto de itens) —\n * degrada com um aviso só.\n */\n private itemsQuotaExceeded = false;\n /**\n * Armazenamento do plano cheio (402 `storage_limit`): o lote é descartado e o aviso sai\n * uma vez por episódio. Os envios continuam — num agente `start()` o espaço pode ser\n * liberado (ou o plano trocado) sem reiniciar; um lote aceito rearma o aviso.\n */\n private itemsStorageFull = false;\n /**\n * Só o kill() do exit path fecha os itens — `dead` (run cancelada/finalizada no\n * servidor) NÃO fecha: o servidor aceita itens de run terminal (trabalho já feito).\n */\n private itemsClosed = false;\n\n // Uploads de anexo vivem FORA de `this.chain`: a cadeia é um FIFO puro de\n // status/logs e não pode ficar bloqueada esperando um binário subir.\n private readonly pendingAttachments = new Set<Promise<void>>();\n private attachmentCount = 0;\n private uploadSlots = MAX_CONCURRENT_UPLOADS;\n private uploadQueue: Array<() => void> = [];\n /** Uma vez que a instalação recusa anexos, para de tentar (e de avisar) nesta run. */\n private attachmentsUnsupported = false;\n\n // Progresso (ctx.progress): snapshot absoluto, enviado com throttle via piggyback\n // em `enqueue()` — nunca gera tráfego próprio enquanto logs/heartbeat já fluem.\n private progressCurrent = 0;\n private progressTotal: number | null = null;\n /** Snapshot ainda não entregue ao servidor. */\n private progressDirty = false;\n private progressTimer: ReturnType<typeof setTimeout> | undefined;\n private progressWarned = false;\n /** Relógio do último eco `[hobots:progress]` no terminal (throttle do eco, não do wire). */\n private progressLastPrint = 0;\n\n /** Arquivos do formulário desta run (`ctx.files`) — a pasta temporária é apagada no fim. */\n private readonly fileStore: RunFileStore;\n\n constructor(\n private readonly api: RunTransport,\n readonly runId: string,\n private readonly logger: Logger,\n private readonly tx: Transaction,\n flushIntervalMs?: number,\n cancelCheckIntervalMs?: number,\n params: Record<string, unknown> = {}\n ) {\n this.flushIntervalMs = flushIntervalMs ?? DEFAULT_LOG_FLUSH_INTERVAL_MS;\n this.cancelCheckIntervalMs = Math.min(\n MAX_CANCEL_CHECK_INTERVAL_MS,\n Math.max(MIN_CANCEL_CHECK_INTERVAL_MS, cancelCheckIntervalMs ?? DEFAULT_CANCEL_CHECK_INTERVAL_MS)\n );\n const logAt =\n (level: RunLogLevel) =>\n (message: unknown, ...rest: unknown[]): void => {\n const { text, image } = splitLogArgs(message, rest);\n this.log(level, text, image);\n };\n const log: RunLogger = {\n debug: logAt('debug'),\n info: logAt('info'),\n warn: logAt('warning'),\n error: logAt('error'),\n success: logAt('success'),\n };\n // eventos de transaction/step da run espelham nos logs (o terminal já foi\n // ecoado pelo próprio emit da Transaction — aqui é só buffer/envio)\n tx.setLifecycleSink((level, message) => this.push(level, message));\n // imagem de etapa (`etapa.image`/`etapa.warning({ image })`) sobe pelo pipeline de anexos desta run\n tx.setAttachmentSink((image, ts) => this.queueAttachment(image, ts));\n // pontos de parada cooperativos: registrar um item, avançar o progresso ou abrir uma\n // etapa são fronteiras naturais de trabalho — uma run cancelada para aqui sozinha\n const checkCanceled = (): void => this.checkCanceled();\n tx.setStepGuard(checkCanceled);\n // sink do items.each: itens, etapas, progresso e cancelamento desta run\n const eachSink: EachSink = {\n report: (status, message, payload, id, image) => this.addItem(status, message, payload, id, image),\n startStep: (op, description) => tx.start(op, description),\n stepScope: (step, fn) => tx.scope(step, fn),\n declareTotal: total => {\n if (this.progressTotal == null) this.setProgress(this.progressCurrent, total);\n },\n advance: () => this.setProgress(this.progressCurrent + 1, this.progressTotal),\n checkCanceled,\n isAborted: () => this.abortController.signal.aborted,\n logInfo: message => this.log('info', message),\n logWarning: message => this.log('warning', message),\n logError: message => this.log('error', message),\n sleep: ms => cancelableSleep(ms, this.abortController.signal),\n doneItemIds: () => this.listDoneItemIds(),\n flush: () => this.flush(),\n };\n const items: RunItems = {\n add: item => {\n checkCanceled();\n this.addItem(item.status, item.message, item.payload, item.id, item.image);\n },\n succeeded: (payload, options) => {\n checkCanceled();\n this.addItem('succeeded', undefined, payload, options?.id, options?.image);\n },\n failed: (message, payload, options) => {\n checkCanceled();\n this.addItem('failed', message, payload, options?.id, options?.image);\n },\n occurrence: (message, payload, options) => {\n checkCanceled();\n this.addItem('occurrence', message, payload, options?.id, options?.image);\n },\n each: (list, handler, options = {}) => eachItem(list, handler, options, eachSink),\n };\n const progress = Object.defineProperties(\n {\n total: (total: number) => {\n checkCanceled();\n this.setProgress(this.progressCurrent, total);\n },\n advance: (count = 1) => {\n checkCanceled();\n this.setProgress(this.progressCurrent + count, this.progressTotal);\n },\n set: (current: number, total?: number) => {\n checkCanceled();\n this.setProgress(current, total ?? this.progressTotal);\n },\n },\n {\n current: { enumerable: true, get: () => this.progressCurrent },\n snapshot: {\n enumerable: true,\n get: () => (this.progressTotal == null ? null : { current: this.progressCurrent, total: this.progressTotal }),\n },\n }\n // defineProperties não tipa os getters adicionados — a interface é a fonte de verdade\n ) as unknown as RunProgressReporter;\n const signal = this.abortController.signal;\n const sleep = (ms: number): Promise<void> => cancelableSleep(ms, signal);\n this.fileStore = new RunFileStore({ api, runId, params, signal, warn: message => this.log('warning', message) });\n this.context = {\n runId,\n params,\n log,\n items,\n progress,\n files: this.fileStore.files,\n step: async (name, fn, options) => {\n // só a raiz faz flush: o flush das etapas envia raízes terminadas, sub-etapa vai junto da mãe\n const root = tx.currentStep() === undefined;\n try {\n return await tx.step(name, fn, { ...options, signal, wait: sleep, warn: message => this.log('warning', message) });\n } finally {\n // cancelada: o dreno final da run cuida, não vale segurar o handler aqui\n if (options?.flush !== false && root && !signal.aborted) await this.flush();\n }\n },\n flush: (timeoutMs?: number) => this.flush(timeoutMs),\n signal,\n throwIfCanceled: checkCanceled,\n sleep,\n retry: (fn, options?: RetryOptions) => retryWithBackoff(fn, { ...options, signal, wait: sleep }),\n };\n }\n\n /** Apaga as cópias de arquivo que ficaram na pasta temporária da run. Nunca lança. */\n cleanupFiles(): Promise<void> {\n return this.fileStore.cleanup();\n }\n\n get isDead(): boolean {\n return this.dead;\n }\n\n /** Lança `RunCanceled` se o signal desta run já disparou. */\n checkCanceled(): void {\n if (this.abortController.signal.aborted) throw runCanceledError();\n }\n\n /** Aborta o ctx.signal sem matar o reporter (timeout/shutdown ainda reportam o terminal). */\n abort(): void {\n this.stopCancelWatch(); // o heartbeat só existe para disparar o signal\n if (!this.abortController.signal.aborted) this.abortController.abort();\n }\n\n /**\n * Mata o reporter de vez: aborta o signal e suprime todo reporte futuro.\n * Usado no exit path — depois que o agente reportou AgentTerminated por fora\n * da fila, um handler zumbi não pode reenviar status por cima.\n */\n kill(): void {\n this.abort();\n this.dead = true;\n this.clearFlushTimer();\n this.clearProgressTimer();\n this.buffer = [];\n // exit path: diferente dos logs, o volume de itens não justifica salvage best-effort\n this.itemsClosed = true;\n this.clearItemsTimer();\n if (this.itemsBuffer.length > 0) {\n this.logger.warn(`${this.itemsBuffer.length} item(ns) de execução descartados (processo encerrando)`);\n this.itemsBuffer = [];\n }\n // uploads na fila nunca vão rodar: solta quem espera slot para não vazar promises\n const waiting = this.uploadQueue.splice(0, this.uploadQueue.length);\n for (const resume of waiting) resume();\n }\n\n /**\n * Drena o buffer pendente para o PATCH único do exit path (chame ANTES de kill,\n * que descarta o buffer). Capado em um chunk — o exit path não tem retry nem fila,\n * então preserva os logs mais recentes, os mais valiosos na morte do processo.\n */\n drainLogs(): RunLogEntry[] {\n this.clearFlushTimer();\n return this.takeLogs().slice(-MAX_LOGS_PER_PATCH);\n }\n\n /**\n * Linha de log da run com eco no terminal. `image` (opcional) vira o anexo da linha:\n * o id entra na entrada ANTES de qualquer I/O — é isso que mantém a ordem dos logs\n * intacta e o handler livre da latência do upload. Devolve o id do anexo (quando houve\n * imagem e ela não foi descartada) — o `captureException` o leva ao evento da issue.\n */\n log(level: RunLogLevel, message: string, image?: ImageInput): string | undefined {\n if (this.dead) return undefined;\n const scrubbed = scrubSecrets(safeString(message));\n const ts = nowISO();\n const attachmentId = image === undefined ? undefined : this.queueAttachment(image, ts);\n printRunLog(level, attachmentId ? `${scrubbed} [imagem]` : scrubbed);\n this.push(level, scrubbed, true, attachmentId ? [attachmentId] : undefined, ts);\n return attachmentId;\n }\n\n /** Bufferiza uma entrada de log sem eco no terminal (cap, truncate, flush). */\n private push(level: RunLogLevel, message: string, alreadyScrubbed = false, attachments?: string[], ts = nowISO()): string {\n if (this.dead) return ts;\n const scrubbed = alreadyScrubbed ? message : scrubSecrets(message);\n this.buffer.push({\n ts,\n level,\n message: truncate(scrubbed, MAX_LOG_MESSAGE_CHARS),\n ...(attachments && attachments.length > 0 ? { attachments: attachments.slice(0, WIRE_LIMITS.MAX_ATTACHMENTS_PER_LOG_ENTRY) } : {}),\n });\n\n if (this.buffer.length >= FLUSH_AT_BUFFERED) {\n this.flushLogs();\n } else {\n this.scheduleFlush();\n }\n return ts;\n }\n\n private scheduleFlush(): void {\n if (this.timer) return;\n this.timer = setTimeout(() => {\n this.timer = undefined;\n this.flushLogs();\n }, this.flushIntervalMs);\n unrefTimer(this.timer);\n }\n\n private clearFlushTimer(): void {\n if (this.timer) {\n clearTimeout(this.timer);\n this.timer = undefined;\n }\n }\n\n private takeLogs(): RunLogEntry[] {\n return this.buffer.splice(0, this.buffer.length);\n }\n\n /** Flush incremental: envia o buffer como status 'running' (em chunks). */\n private flushLogs(): void {\n this.clearFlushTimer();\n if (this.dead || this.buffer.length === 0) return;\n const logs = this.buffer.splice(0, this.buffer.length);\n for (let i = 0; i < logs.length; i += MAX_LOGS_PER_PATCH) {\n this.enqueue({ status: 'running', logs: logs.slice(i, i + MAX_LOGS_PER_PATCH) });\n }\n }\n\n /**\n * `hobots.flush()`: o bot decide quando entregar o que já fez — etapas raiz finalizadas\n * viram transactions parciais da run, e itens, logs e progresso pendentes saem já, sem\n * esperar o throttle. Aguarda a entrega com teto. Nunca lança (pode ir num `finally`).\n */\n async flush(timeoutMs = ITEMS_DRAIN_MS): Promise<void> {\n this.tx.flush();\n this.flushItems();\n if (this.progressDirty) this.flushProgress();\n else this.flushLogs();\n await Promise.race([\n Promise.all([this.itemsChain, this.chain, this.tx.drain(timeoutMs)]).catch(() => undefined),\n new Promise<void>(resolve => unrefTimer(setTimeout(resolve, timeoutMs))),\n ]);\n }\n\n /** Primeiro PATCH (claimed → running). Retorna false se a run já morreu (cancelada). */\n async reportRunning(): Promise<boolean> {\n this.enqueue({ status: 'running' });\n await this.chain;\n if (!this.dead) this.startCancelWatch();\n return !this.dead;\n }\n\n reportSuccess(): void {\n this.stopCancelWatch();\n this.clearFlushTimer();\n this.forceFinalProgress();\n this.enqueue({ status: 'succeeded', logs: this.takeLogsForTerminal() });\n }\n\n reportFailure(error: RunError): void {\n this.stopCancelWatch();\n this.clearFlushTimer();\n this.forceFinalProgress();\n this.enqueue({ status: 'failed', error, logs: this.takeLogsForTerminal() });\n }\n\n /**\n * Esvazia o buffer para o PATCH terminal respeitando o teto de 100 logs por PATCH:\n * o excedente sai antes, em PATCHes `running` na mesma cadeia (a ordem se mantém).\n */\n private takeLogsForTerminal(): RunLogEntry[] {\n let logs = this.takeLogs();\n while (logs.length > MAX_LOGS_PER_PATCH) {\n this.enqueue({ status: 'running', logs: logs.slice(0, MAX_LOGS_PER_PATCH) });\n logs = logs.slice(MAX_LOGS_PER_PATCH);\n }\n return logs;\n }\n\n // ── Progresso ────────────────────────────────────────────────────────────────\n\n /** Valida, clampa e marca o snapshot como pendente; agenda flush só se nada mais vai sair. */\n private setProgress(current: number, total: number | null): void {\n if (this.dead) return;\n if (total != null && (!Number.isInteger(total) || total < 1)) {\n if (!this.progressWarned) {\n this.progressWarned = true;\n this.logger.warn(`ctx.progress: total inválido (${String(total)}) — precisa ser inteiro >= 1; ignorado`);\n }\n return;\n }\n const safeCurrent = Number.isFinite(current) ? Math.max(0, Math.floor(current)) : this.progressCurrent;\n const next = total == null ? safeCurrent : Math.min(safeCurrent, total);\n const totalChanged = total !== this.progressTotal;\n if (next === this.progressCurrent && !totalChanged) return;\n this.progressCurrent = next;\n this.progressTotal = total;\n // sem total declarado não há wire: guarda o contador e espera o total()\n if (total == null) return;\n // eco no terminal: total novo e valor final saem sempre; o meio do caminho, no máximo 4×/s\n const now = Date.now();\n if (totalChanged || next >= total || now - this.progressLastPrint >= PROGRESS_PRINT_THROTTLE_MS) {\n this.progressLastPrint = now;\n printRunProgress(next, total);\n }\n this.progressDirty = true;\n // um PATCH que saia antes (logs/heartbeat) leva o snapshot e cancela este timer\n if (this.progressTimer) return;\n this.progressTimer = setTimeout(() => {\n this.progressTimer = undefined;\n this.flushProgress();\n }, PROGRESS_FLUSH_MS);\n unrefTimer(this.progressTimer);\n }\n\n private flushProgress(): void {\n this.clearProgressTimer();\n if (this.dead || !this.progressDirty) return;\n // logs esperando flush: um PATCH só leva logs + progresso\n if (this.buffer.length > 0) this.flushLogs();\n else this.enqueue({ status: 'running' });\n }\n\n private clearProgressTimer(): void {\n if (this.progressTimer) {\n clearTimeout(this.progressTimer);\n this.progressTimer = undefined;\n }\n }\n\n /** O PATCH terminal sempre leva o snapshot final (o app mostra \"87/100\" numa run que falhou). */\n private forceFinalProgress(): void {\n this.clearProgressTimer();\n this.progressDirty = this.progressTotal != null;\n }\n\n /** Consome o snapshot pendente para pegar carona no próximo PATCH. */\n private takeProgress(): RunProgress | undefined {\n if (!this.progressDirty || this.progressTotal == null) return undefined;\n this.progressDirty = false;\n return { current: this.progressCurrent, total: this.progressTotal };\n }\n\n /**\n * Heartbeat de cancelamento: enquanto o handler roda, um PATCH 'running' vazio\n * periódico faz o servidor responder 409 se a run foi cancelada no app — o que\n * mata o reporter e dispara ctx.signal, mesmo em handlers que nunca logam.\n */\n private startCancelWatch(): void {\n if (this.watchTimer) return;\n this.watchTimer = setInterval(() => {\n // já há tráfego a caminho (logs/updates) — ele mesmo detecta o cancelamento\n if (this.dead || this.pendingUpdates > 0 || this.buffer.length > 0) return;\n this.enqueue({ status: 'running' });\n }, this.cancelCheckIntervalMs);\n unrefTimer(this.watchTimer);\n }\n\n private stopCancelWatch(): void {\n if (this.watchTimer) {\n clearInterval(this.watchTimer);\n this.watchTimer = undefined;\n }\n }\n\n /** Aguarda a fila de PATCHes esvaziar (chame depois do terminal). */\n finalize(): Promise<void> {\n return this.chain;\n }\n\n // ── Itens de execução ────────────────────────────────────────────────────────\n\n /**\n * Bufferiza um item (síncrono — a chamada nunca espera rede). Diferente do PATCH\n * de status, o servidor aceita itens mesmo com a run cancelada (trabalho já feito),\n * então um reporter morto não descarta: só um kill() de exit path descarta.\n */\n private addItem(\n status: RunItemStatus,\n message: string | undefined,\n payload: Record<string, unknown> | undefined,\n id: string | undefined,\n image?: ImageInput\n ): void {\n if (this.itemsClosed || this.itemsUnsupported) return;\n\n let scrubbedPayload: Record<string, unknown> | undefined;\n if (payload) {\n scrubbedPayload = scrubPayloadValue(payload, 0) as Record<string, unknown>;\n let serializedLength: number | undefined;\n try {\n serializedLength = JSON.stringify(scrubbedPayload).length;\n } catch {\n // payload circular/não-serializável — sem ele o item ainda vale pelo status\n }\n if (serializedLength === undefined || serializedLength > MAX_ITEM_PAYLOAD_BYTES) {\n this.logger.warn(\n `payload do item descartado (${serializedLength === undefined ? 'não serializável' : `${serializedLength} bytes > ${MAX_ITEM_PAYLOAD_BYTES}`}) — o item foi mantido`\n );\n scrubbedPayload = undefined;\n }\n }\n\n const ts = nowISO();\n const attachmentId = image === undefined ? undefined : this.queueAttachment(image, ts);\n this.itemsBuffer.push({\n id: id ? truncate(String(id), 255) : uuid4(),\n seq: this.itemSeq++,\n status,\n ...(message ? { message: truncate(scrubSecrets(safeString(message)), MAX_ITEM_MESSAGE_CHARS) } : {}),\n ...(scrubbedPayload ? { payload: scrubbedPayload } : {}),\n ts,\n ...(attachmentId ? { attachments: [attachmentId] } : {}),\n });\n\n if (this.itemsBuffer.length >= ITEMS_FLUSH_AT_BUFFERED) {\n this.flushItems();\n } else {\n this.scheduleItemsFlush();\n }\n }\n\n /**\n * Ids já concluídos (`succeeded`/`occurrence`) neste trabalho — a run e suas reexecuções.\n * Pagina até o fim. undefined quando a consulta falha (servidor antigo, rede): o `each`\n * avisa e processa tudo, nunca trava a run por isso.\n */\n async listDoneItemIds(): Promise<Set<string> | undefined> {\n const ids = new Set<string>();\n let cursor: string | null = null;\n try {\n do {\n const page: RunItemsDoneResponse = await this.api.listDoneItems(this.runId, {\n limit: MAX_ITEMS_DONE_PER_PAGE,\n ...(cursor ? { cursor } : {}),\n });\n for (const id of page.ids) ids.add(id);\n cursor = page.next;\n } while (cursor);\n return ids;\n } catch (error) {\n this.log('warning', `não foi possível consultar os itens já concluídos deste trabalho — todos serão processados (${thrownMessage(error)})`);\n return undefined;\n }\n }\n\n private scheduleItemsFlush(): void {\n if (this.itemsTimer) return;\n this.itemsTimer = setTimeout(() => {\n this.itemsTimer = undefined;\n this.flushItems();\n }, this.flushIntervalMs);\n unrefTimer(this.itemsTimer);\n }\n\n private clearItemsTimer(): void {\n if (this.itemsTimer) {\n clearTimeout(this.itemsTimer);\n this.itemsTimer = undefined;\n }\n }\n\n /** Envia o buffer de itens em lotes serializados na cadeia própria. */\n private flushItems(): void {\n this.clearItemsTimer();\n if (this.itemsBuffer.length === 0 || this.itemsUnsupported) return;\n const items = this.itemsBuffer.splice(0, this.itemsBuffer.length);\n for (let i = 0; i < items.length; i += MAX_ITEMS_PER_REQUEST) {\n const batch = items.slice(i, i + MAX_ITEMS_PER_REQUEST);\n this.itemsChain = this.itemsChain.then(() => this.sendItems(batch));\n }\n }\n\n private async sendItems(batch: RunItemInput[]): Promise<void> {\n if (this.itemsUnsupported) return;\n try {\n await this.api.createItems(this.runId, { items: batch });\n this.itemsStorageFull = false;\n } catch (error) {\n if (error instanceof TasksApiError && error.status === 404) {\n // servidor anterior ao recurso (ou run apagada) — degrada em silêncio daqui em diante\n this.itemsUnsupported = true;\n this.logger.warn('itens de execução não são suportados por este servidor Hobots — descartados');\n return;\n }\n if (error instanceof TasksApiError && error.status === 429) {\n if (!this.itemsQuotaExceeded) {\n this.itemsQuotaExceeded = true;\n this.log('warning', 'itens descartados: limite de itens por execução atingido no servidor');\n }\n return;\n }\n if (error instanceof TasksApiError && error.status === 402) {\n if (!this.itemsStorageFull) {\n this.itemsStorageFull = true;\n this.log('warning', 'itens descartados: armazenamento do plano cheio — libere espaço ou faça upgrade em Plano e cobrança');\n }\n return;\n }\n if (error instanceof TasksApiError) {\n // 4xx definitivo (payload rejeitado) — reenviar não vai mudar o resultado; vai pro\n // log da run para o descarte aparecer na Central, não só no stderr da máquina\n this.logger.error(`lote de ${batch.length} item(ns) rejeitado pelo servidor:`, error);\n this.log('warning', `${batch.length} item(ns) descartado(s): envio rejeitado pelo servidor (HTTP ${error.status})`);\n return;\n }\n // rede/5xx com retries esgotados: devolve ao buffer para a próxima tentativa\n this.itemsBuffer.unshift(...batch);\n this.scheduleItemsFlush();\n this.logger.error(`lote de ${batch.length} item(ns) não enviado (devolvido ao buffer):`, error);\n }\n }\n\n /**\n * Dreno final de itens antes do PATCH terminal (com teto): garante que os\n * totalizadores estejam completos quando a run vira succeeded/failed. Como o\n * servidor aceita itens tardios, perder a corrida aqui não perde dados.\n */\n async finalizeItems(timeoutMs = ITEMS_DRAIN_MS): Promise<void> {\n this.flushItems();\n await Promise.race([\n this.itemsChain,\n new Promise<void>(resolve => unrefTimer(setTimeout(resolve, timeoutMs))),\n ]);\n if (this.itemsBuffer.length > 0 && !this.itemsUnsupported && !this.itemsQuotaExceeded) {\n // sobrou lote devolvido por falha de rede — última tentativa antes do terminal\n this.flushItems();\n await Promise.race([\n this.itemsChain,\n new Promise<void>(resolve => unrefTimer(setTimeout(resolve, timeoutMs))),\n ]);\n }\n }\n\n // ── Anexos ───────────────────────────────────────────────────────────────────\n\n /**\n * Pendura uma imagem num evento da run (log, item ou etapa): faz as checagens que não\n * dependem de I/O (reporter morto, instalação sem anexos, cota), reserva o id e dispara\n * o upload em segundo plano. Devolve o id — já referenciável pelo evento — ou undefined\n * quando a imagem foi descartada (sempre com aviso no log da run). Nunca lança: todo\n * caminho de erro do upload vira aviso. O hint `attachment` de `hobots.captureException`\n * também cai aqui via `log()`.\n */\n queueAttachment(imageIn: ImageInput, ts: string): string | undefined {\n if (this.dead) return undefined;\n const image = toImageAttachment(imageIn);\n if (this.attachmentsUnsupported) return undefined; // já avisamos uma vez nesta run\n if (this.attachmentCount >= MAX_ATTACHMENTS_PER_RUN) {\n if (this.attachmentCount === MAX_ATTACHMENTS_PER_RUN) {\n this.attachmentCount++; // aviso único por run\n this.log('warning', `imagem descartada: limite de ${MAX_ATTACHMENTS_PER_RUN} por execução atingido`);\n }\n return undefined;\n }\n this.attachmentCount++;\n\n const id = uuid4();\n const rawCaption = image.caption !== undefined ? safeString(image.caption) : undefined;\n const caption = rawCaption ? truncate(scrubSecrets(rawCaption), MAX_CAPTION_CHARS) : undefined;\n const work = this.uploadAttachment(id, image.input, { caption, logTs: ts, contentType: image.contentType })\n .then(() => undefined)\n .catch(() => undefined);\n this.pendingAttachments.add(work);\n void work.finally(() => this.pendingAttachments.delete(work));\n return id;\n }\n\n /** Retorna o motivo da falha, ou undefined em sucesso. */\n private async uploadAttachment(\n id: string,\n image: AttachInput,\n meta: { caption?: string; logTs: string; contentType?: RunAttachmentContentType }\n ): Promise<AttachFailureReason | undefined> {\n let bytes: Uint8Array;\n try {\n bytes = await toBytes(image);\n } catch (error) {\n this.log('warning', `imagem não pôde ser lida: ${String(error)}`);\n return 'read-failed';\n }\n\n // magic bytes ganham do que o chamador declarou — o S3 rejeita a assinatura se divergir\n const contentType = sniffContentType(bytes) ?? meta.contentType;\n if (!contentType) {\n this.log('warning', 'imagem descartada: formato não reconhecido (aceitos: PNG, JPEG, WEBP)');\n return 'unsupported-format';\n }\n if (bytes.byteLength > MAX_ATTACHMENT_BYTES) {\n this.log(\n 'warning',\n `imagem descartada: ${Math.round(bytes.byteLength / 1024)} KB excede o limite de ${MAX_ATTACHMENT_BYTES / 1024 / 1024} MB`\n );\n return 'too-large';\n }\n\n const dimensions = readPngDimensions(bytes);\n const release = await this.acquireUploadSlot();\n try {\n if (this.abortController.signal.aborted || this.dead) return 'canceled';\n const created = await this.api.createAttachment(\n this.runId,\n {\n id,\n content_type: contentType,\n size_bytes: bytes.byteLength,\n log_ts: meta.logTs,\n ...(meta.caption ? { caption: meta.caption } : {}),\n ...(dimensions ?? {}),\n },\n this.abortController.signal\n );\n await this.api.uploadAttachment(created.upload_url, created.headers, bytes, this.abortController.signal);\n // confirmação é conforto de UX (some o placeholder \"enviando…\"): falha não invalida o upload\n await this.api\n .confirmAttachment(this.runId, id, { status: 'uploaded', size_bytes: bytes.byteLength, ...(dimensions ?? {}) })\n .catch(() => {});\n return undefined;\n } catch (error) {\n if (this.isUnsupported(error)) {\n this.attachmentsUnsupported = true;\n this.log('warning', 'anexos não estão habilitados nesta instalação do Hobots — imagem não enviada');\n return 'unsupported';\n }\n if (error instanceof TasksApiError && error.status === 429) {\n this.log('warning', 'imagem descartada: limite de anexos por execução atingido no servidor');\n return 'quota';\n }\n if (this.abortController.signal.aborted) return 'canceled';\n this.log('warning', `falha ao enviar a imagem: ${String(error)}`);\n void this.api.confirmAttachment(this.runId, id, { status: 'failed' }).catch(() => {});\n return 'upload-failed';\n } finally {\n release();\n }\n }\n\n /** 404 = API anterior ao recurso; 501/503 = instalação sem S3 configurado. */\n private isUnsupported(error: unknown): boolean {\n return error instanceof TasksApiError && (error.status === 404 || error.status === 501 || error.status === 503);\n }\n\n /** Semáforo simples: no máximo MAX_CONCURRENT_UPLOADS binários em voo por run. */\n private acquireUploadSlot(): Promise<() => void> {\n const release = (): void => {\n const next = this.uploadQueue.shift();\n if (next) next();\n else this.uploadSlots++;\n };\n if (this.uploadSlots > 0) {\n this.uploadSlots--;\n return Promise.resolve(release);\n }\n return new Promise<() => void>(resolve => {\n this.uploadQueue.push(() => resolve(release));\n });\n }\n\n /**\n * Espera os uploads pendentes antes do PATCH terminal, para a run não terminar\n * exibindo miniaturas em \"enviando…\". Capado: um upload lento não segura a run.\n */\n async finalizeAttachments(timeoutMs = ATTACHMENT_DRAIN_MS): Promise<void> {\n if (this.pendingAttachments.size === 0) return;\n await Promise.race([\n Promise.allSettled([...this.pendingAttachments]),\n new Promise<void>(resolve => unrefTimer(setTimeout(resolve, timeoutMs))),\n ]);\n }\n\n private enqueue(updateIn: RunUpdateRequest): void {\n if (this.dead) {\n this.salvageLogs(updateIn.logs);\n return;\n }\n // ponto único de piggyback: qualquer PATCH que saia leva o progresso mais recente\n this.clearProgressTimer();\n const progress = this.takeProgress();\n const update: RunUpdateRequest = progress ? { ...updateIn, progress } : updateIn;\n this.pendingUpdates++;\n this.chain = this.chain.then(async () => {\n if (this.dead) {\n // update enfileirado atrás do PATCH que morreu (ex.: chunks de flush): logs seguem tardios\n this.salvageLogs(update.logs);\n return;\n }\n const payload = update.logs && update.logs.length === 0 ? { ...update, logs: undefined } : update;\n try {\n await this.api.updateRun(this.runId, payload);\n } catch (error) {\n if (error instanceof TasksApiError && (error.status === 409 || error.status === 404)) {\n this.dead = true;\n this.stopCancelWatch();\n this.abort();\n // os logs deste payload já foram anexados pelo servidor (append tardio no 409);\n // o que resta no buffer segue best-effort pelo mesmo caminho\n const pending = this.buffer.splice(0, this.buffer.length);\n this.salvageLogs(pending);\n this.logger.warn(\n `run ${this.runId} cancelada/finalizada no servidor — status suprimido` +\n (pending.length > 0 ? `, ${pending.length} log(s) enviados como log tardio` : '')\n );\n return;\n }\n // rede/5xx com retries esgotados: devolve os logs ao buffer para o próximo PATCH\n if (update.logs && update.logs.length > 0) {\n this.buffer.unshift(...update.logs);\n this.scheduleFlush();\n }\n // o snapshot perdido é ≤ o atual: basta marcar como pendente de novo\n if (update.progress && this.progressTotal != null) this.progressDirty = true;\n this.logger.error(`update da run ${this.runId} perdido:`, error);\n }\n }).finally(() => {\n this.pendingUpdates--;\n });\n }\n\n /**\n * Best-effort de log tardio: envia logs para uma run já terminal, fora da fila.\n * O servidor anexa os logs mesmo respondendo 409; erros são engolidos — este é\n * o último recurso, não um canal confiável.\n */\n private salvageLogs(logs: RunLogEntry[] | undefined): void {\n if (!logs || logs.length === 0) return;\n for (let i = 0; i < logs.length; i += MAX_LOGS_PER_PATCH) {\n void this.api\n .updateRunOnce(this.runId, { status: 'running', logs: logs.slice(i, i + MAX_LOGS_PER_PATCH) })\n .catch(() => {});\n }\n }\n}\n","import type { RunDescriptor, RunError } from './protocol';\nimport type { AgentHandler, RunHandler } from './types';\nimport type { RunTransport } from './api';\nimport { RunReporter } from './context';\nimport { isCancellation, taskTimeoutError } from './errors';\nimport type { RunTracker } from './registry';\nimport { runWithRunContext } from './run-context-store';\nimport { resolveDelay, retryWithBackoff } from '../retry';\nimport { Transaction } from '../transaction';\nimport { scrubSecrets } from '../scrub';\nimport { sleep, truncate, type Logger } from '../utils';\nimport { wasCaptured, type Client } from '../client';\nimport { WIRE_LIMITS } from '../wire-limits';\n\nexport interface ExecuteRunInput {\n run: RunDescriptor;\n handler: AgentHandler;\n api: RunTransport;\n client: Client | undefined;\n logger: Logger;\n tracker: RunTracker;\n}\n\nconst DEFAULT_RETRY_DELAY_MS = 5_000;\n\n/**\n * Pipeline de UMA run, compartilhado por todos os modos (poll, start, run anexada e modo local): transaction →\n * reporter → running → handler (com retry) → drenos → terminal. O handler roda dentro\n * do contexto async da run, então `hobots.*` em qualquer módulo resolve para ela.\n */\nexport async function executeRun(input: ExecuteRunInput): Promise<void> {\n const { run, handler, api, client, logger, tracker } = input;\n const options = handler.options;\n // correlacionada à run via run_id — as etapas que o handler abrir com hobots.step() viram o\n // waterfall de performance da execução na Central; no modo local (sem client) o FINISH ecoa no terminal\n const tx = new Transaction(client, 'run', 'hobots.run', run.id, { echo: !client });\n const reporter = new RunReporter(\n api,\n run.id,\n logger,\n tx,\n options.logFlushIntervalMs,\n options.cancelCheckIntervalMs,\n run.params\n );\n tracker.add(reporter);\n\n try {\n const ok = await reporter.reportRunning();\n if (!ok) {\n logger.debug(`run ${run.id} cancelada antes de iniciar — handler não executado`);\n tx.setStatus('cancelled');\n tx.finish();\n return;\n }\n\n logger.debug(`executando run ${run.id}`);\n try {\n await runWithRunContext({ reporter }, () => invokeWithRetry(handler, run, reporter, logger));\n // anexos disparados sem await (fire-and-forget) ainda podem estar subindo:\n // espera (com teto) para a run não terminar com miniaturas em \"enviando…\"\n await reporter.finalizeAttachments();\n // dreno dos itens antes do terminal: os totalizadores da run ficam completos\n // quando ela vira succeeded (itens tardios ainda são aceitos se perder a corrida)\n await reporter.finalizeItems();\n warnIncompleteProgress(reporter);\n // finish antes do terminal: as linhas FINISH de tx/steps entram no mesmo PATCH\n tx.setStatus('ok');\n tx.finish();\n reporter.reportSuccess();\n logger.debug(`run ${run.id} concluída`);\n } catch (error) {\n // uma falha é justamente quando o print importa — vale esperar o upload aqui também\n await reporter.finalizeAttachments();\n // itens já processados antes da falha fazem parte da entrega — drena antes do terminal\n await reporter.finalizeItems();\n tx.setStatus('error');\n tx.finish();\n captureRunFailure(client, error, reporter);\n reporter.reportFailure(toRunError(error));\n logger.debug(`run ${run.id} falhou: ${String(error)}`);\n }\n await reporter.finalize();\n } finally {\n // as cópias sem `dest` só valem durante a run — arquivo de cliente não fica no disco\n await reporter.cleanupFiles();\n tracker.remove(reporter);\n }\n}\n\n/**\n * O erro que escapou do handler (depois do retry) é um erro não tratado do bot: além\n * de falhar a run, vira issue ligada a ela. Cancelamento não é defeito, e o erro que o\n * próprio bot já enviou com captureException e relançou não é enviado de novo.\n */\nfunction captureRunFailure(client: Client | undefined, error: unknown, reporter: RunReporter): void {\n if (!client?.options.captureRunErrors) return;\n // reporter morto = run cancelada no app: o erro é consequência do cancelamento\n if (reporter.isDead || isCancellation(error) || wasCaptured(error)) return;\n client.captureException(error, { type: 'error', tags: { mechanism: 'run_handler', run_id: reporter.runId } });\n}\n\n/**\n * Handler retornou normalmente com o progresso declarado parado antes do total: a run\n * vai virar `succeeded`, mas nem tudo que o bot previu foi processado (ou avançado) —\n * fica registrado no log da run, onde a Central também sinaliza o desencontro.\n */\nfunction warnIncompleteProgress(reporter: RunReporter): void {\n const snapshot = reporter.context.progress.snapshot;\n if (!snapshot || snapshot.current >= snapshot.total) return;\n reporter.context.log.warn(\n `execução concluída com progresso incompleto: ${snapshot.current}/${snapshot.total} — ` +\n 'o handler terminou sem processar (ou sem avançar) todos os itens previstos'\n );\n}\n\n/**\n * Tentativas do handler na MESMA run: falha comum → aviso no log da run, espera\n * cancelável, re-invoca com os mesmos params (itens/progresso já enviados permanecem).\n * Cancelamento, timeout e reporter morto (run cancelada no app) são terminais.\n */\nfunction invokeWithRetry(agent: AgentHandler, run: RunDescriptor, reporter: RunReporter, logger: Logger): Promise<void> {\n const { retries, retryDelayMs } = agent.options;\n const total = retries + 1;\n const ctx = reporter.context;\n return retryWithBackoff(() => invokeWithTimeout(agent, run, reporter, logger), {\n retries,\n delayMs: attempt => resolveDelay(retryDelayMs, attempt, DEFAULT_RETRY_DELAY_MS),\n shouldRetry: () => !reporter.isDead,\n signal: ctx.signal,\n wait: ms => ctx.sleep(ms),\n onRetry: (error, attempt, delayMs) => {\n const reason = error instanceof Error ? `${error.name}: ${error.message}` : String(error);\n ctx.log.warn(`tentativa ${attempt}/${total} falhou: ${truncate(reason, 500)} — nova tentativa em ${delayMs}ms`);\n },\n });\n}\n\nconst TIMEOUT_SENTINEL = Symbol('task-timeout');\nconst CANCEL_SENTINEL = Symbol('task-canceled');\n\nasync function invokeWithTimeout(agent: AgentHandler, run: RunDescriptor, reporter: RunReporter, logger: Logger): Promise<void> {\n const { timeoutMs, cancelGraceMs } = agent.options;\n const handler: RunHandler = agent.handler;\n const invocation = Promise.resolve().then(() => handler(run.params, reporter.context));\n const races: Promise<typeof TIMEOUT_SENTINEL | typeof CANCEL_SENTINEL>[] = [];\n if (timeoutMs && timeoutMs > 0) {\n races.push(sleep(timeoutMs).then(() => TIMEOUT_SENTINEL));\n }\n if (cancelGraceMs > 0) {\n races.push(waitForCancelGrace(reporter.context.signal, cancelGraceMs).then(() => CANCEL_SENTINEL));\n }\n if (races.length === 0) {\n await invocation;\n return;\n }\n\n const outcome = await Promise.race([invocation, ...races]);\n if (outcome !== TIMEOUT_SENTINEL && outcome !== CANCEL_SENTINEL) return; // invocation venceu a corrida\n\n if (outcome === CANCEL_SENTINEL) {\n // run já cancelada no app (409) há cancelGraceMs — o handler não respondeu ao\n // signal a tempo; não dá para matar o código do usuário, então o agente\n // para de esperar e libera o slot. Reportes subsequentes são no-op (reporter morto).\n logger.warn(\n `run ${run.id} cancelada — handler não respondeu a hobots.signal em ${cancelGraceMs}ms, ` +\n 'liberando o slot (o handler pode continuar rodando em segundo plano)'\n );\n return;\n }\n\n // TIMEOUT_SENTINEL: não dá para matar o código do usuário — reporta, aborta o signal e libera o slot\n reporter.abort();\n invocation\n .then(() => logger.warn(`run ${run.id} terminou depois do timeout de ${timeoutMs}ms`))\n .catch(() => logger.warn(`run ${run.id} falhou depois do timeout de ${timeoutMs}ms (erro descartado)`));\n throw taskTimeoutError(timeoutMs!);\n}\n\n/** Resolve só depois que `signal` abortar + `graceMs` — nunca resolve se o signal nunca disparar. */\nfunction waitForCancelGrace(signal: AbortSignal, graceMs: number): Promise<void> {\n return new Promise<void>(resolve => {\n /* v8 ignore start -- defensivo: o retryWithBackoff checa o abort e chama o handler no mesmo tick */\n if (signal.aborted) {\n setTimeout(resolve, graceMs);\n return;\n }\n /* v8 ignore stop */\n signal.addEventListener('abort', () => setTimeout(resolve, graceMs), { once: true });\n });\n}\n\nconst MAX_ERROR_MESSAGE_CHARS = WIRE_LIMITS.MAX_ERROR_MESSAGE_CHARS;\nconst MAX_ERROR_STACK_CHARS = WIRE_LIMITS.MAX_ERROR_STACK_CHARS;\n\nexport function toRunError(error: unknown): RunError {\n if (error instanceof Error) {\n return {\n type: error.name,\n message: scrubSecrets(truncate(error.message, MAX_ERROR_MESSAGE_CHARS)),\n stack: error.stack ? scrubSecrets(truncate(error.stack, MAX_ERROR_STACK_CHARS)) : undefined,\n };\n }\n return { message: scrubSecrets(truncate(String(error), MAX_ERROR_MESSAGE_CHARS)) };\n}\n\n","import type { TasksApi } from './api';\nimport { Backoff } from './backoff';\nimport type { InstanceInfo, RunDescriptor } from './protocol';\nimport type { RunTracker } from './registry';\nimport { executeRun } from './runner';\nimport type { AgentHandler } from './types';\nimport type { Client } from '../client';\nimport { sleep, type Logger } from '../utils';\nimport { WIRE_LIMITS } from '../wire-limits';\n\n// 2s: uma solicitação nova aparece como 'executando' no app quase na hora; o poll é\n// um UPDATE indexado (SKIP LOCKED) e a presença da instância é throttled no servidor\nexport const DEFAULT_POLL_INTERVAL_MS = 2_000;\nconst MIN_POLL_INTERVAL_MS = 1_000;\nconst MAX_CLAIM_PER_POLL = WIRE_LIMITS.MAX_CLAIM_PER_POLL;\n\ntype AgentState = 'idle' | 'started' | 'stopping';\n\nexport interface TaskAgentOptions {\n api: TasksApi;\n client: Client | undefined;\n logger: Logger;\n /** O handler sob demanda do agente (modo remote). */\n handler: AgentHandler;\n tracker: RunTracker;\n /** Presença da instância enviada em cada poll (identidade, versão, ambiente, modo, máquina). */\n instanceInfo: () => InstanceInfo;\n pollIntervalMs?: number;\n}\n\n/**\n * Loop de polling do modo sob demanda (register): busca runs pendentes do agente e\n * executa o handler. O timer NÃO é unref'd — um agente iniciado mantém o processo vivo\n * até stop(). O poll só pede tantas runs quantos slots livres houver (`concurrency`).\n */\nexport class TaskAgent {\n readonly logger: Logger;\n readonly pollIntervalMs: number;\n\n private readonly api: TasksApi;\n private readonly client: Client | undefined;\n private readonly handler: AgentHandler;\n private readonly tracker: RunTracker;\n private readonly backoff: Backoff;\n\n private state: AgentState = 'idle';\n private timer: ReturnType<typeof setTimeout> | undefined;\n private pollAbort: AbortController | undefined;\n private readonly activeRuns = new Set<Promise<void>>();\n\n constructor(private readonly options: TaskAgentOptions) {\n this.logger = options.logger;\n this.api = options.api;\n this.client = options.client;\n this.handler = options.handler;\n this.tracker = options.tracker;\n this.pollIntervalMs = Math.max(MIN_POLL_INTERVAL_MS, options.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS);\n this.backoff = new Backoff(this.logger, 'poll', this.pollIntervalMs);\n }\n\n get activeCount(): number {\n return this.activeRuns.size;\n }\n\n start(): void {\n if (this.state === 'started') return;\n if (this.state === 'stopping') {\n throw new Error('[hobots] start do agente durante o stop — aguarde o stop terminar');\n }\n this.state = 'started';\n this.logger.debug(`polling iniciado (concorrência ${this.handler.options.concurrency})`);\n this.schedule(0);\n }\n\n /** Antecipa o próximo poll para já. */\n wake(): void {\n if (this.state !== 'started') return;\n if (this.timer) {\n clearTimeout(this.timer);\n this.timer = undefined;\n }\n this.schedule(0);\n }\n\n /** Para o polling e aguarda as runs ativas (até timeoutMs). Retorna true se tudo terminou a tempo. */\n async stop(timeoutMs = 30_000): Promise<boolean> {\n if (this.state === 'idle') return true;\n this.state = 'stopping';\n if (this.timer) {\n clearTimeout(this.timer);\n this.timer = undefined;\n }\n this.pollAbort?.abort();\n\n const all = Promise.allSettled([...this.activeRuns]).then(() => true);\n const finished = timeoutMs > 0 ? await Promise.race([all, sleep(timeoutMs).then(() => false)]) : this.activeRuns.size === 0;\n this.state = 'idle';\n return finished;\n }\n\n /** Timer intencionalmente NÃO unref'd: o agente é a razão do processo existir. */\n private schedule(delayMs: number): void {\n if (this.state !== 'started' || this.timer) return;\n this.timer = setTimeout(() => {\n this.timer = undefined;\n void this.tick();\n }, delayMs);\n }\n\n /** Slots livres do agente — vira o `max` do poll (nunca reivindica trabalho para deixar parado). */\n private freeSlots(): number {\n const free = this.handler.options.concurrency - this.tracker.activeCount;\n return Math.min(MAX_CLAIM_PER_POLL, Math.max(0, free));\n }\n\n private async tick(): Promise<void> {\n /* v8 ignore start -- defensivo: o timer só existe com o agente started e o stop() o limpa */\n if (this.state !== 'started') return;\n /* v8 ignore stop */\n const max = this.freeSlots();\n if (max === 0) {\n this.schedule(this.pollIntervalMs);\n return;\n }\n\n this.pollAbort = new AbortController();\n try {\n const response = await this.api.poll(\n {\n // identidade canônica do agente no painel — o mesmo instanceId do heartbeat,\n // então os dois canais convergem em um agente\n instance: this.options.instanceInfo(),\n max,\n },\n this.pollAbort.signal\n );\n this.backoff.reset();\n\n for (const run of response.runs) {\n this.dispatch(run);\n }\n // com trabalho entregue, re-poll imediato (modo drain); sem trabalho, espera o intervalo\n this.schedule(response.runs.length > 0 ? 0 : this.pollIntervalMs);\n } catch (error) {\n if (this.state !== 'started') return; // stop() abortou o poll\n this.schedule(this.backoff.next(error));\n } finally {\n this.pollAbort = undefined;\n }\n }\n\n private dispatch(run: RunDescriptor): void {\n const promise = this.executeClaimed(run)\n .catch(error => this.logger.error(`erro inesperado na run ${run.id}:`, error))\n .finally(() => {\n this.activeRuns.delete(promise);\n if (this.state === 'started') this.schedule(0);\n });\n this.activeRuns.add(promise);\n }\n\n private async executeClaimed(run: RunDescriptor): Promise<void> {\n await executeRun({ run, handler: this.handler, api: this.api, client: this.client, logger: this.logger, tracker: this.tracker });\n }\n}\n","import type { RunTransport } from './api';\nimport type { RunDescriptor } from './protocol';\nimport type { RunTracker } from './registry';\nimport { executeRun } from './runner';\nimport type { AgentHandler } from './types';\nimport type { Client } from '../client';\nimport type { Logger } from '../utils';\n\n/** O que qualquer runner de UMA run precisa para executar o pipeline (`executeRun`). */\nexport interface SingleRunDeps {\n api: RunTransport;\n client: Client | undefined;\n logger: Logger;\n tracker: RunTracker;\n}\n\n/**\n * Uma run por processo: obtém o descritor (abre na plataforma, anexa-se a uma run já\n * reivindicada ou monta localmente) e executa o handler UMA vez pelo pipeline normal.\n * `done` resolve em qualquer desfecho — inclusive quando não houve o que executar.\n */\nexport abstract class SingleRunRunner<D extends SingleRunDeps = SingleRunDeps> {\n protected readonly abort = new AbortController();\n /** Resolve quando a run terminou (ou não pôde começar, ou o runner foi parado antes). */\n readonly done: Promise<void>;\n private resolveDone!: () => void;\n\n constructor(\n protected readonly handler: AgentHandler,\n protected readonly deps: D\n ) {\n this.done = new Promise<void>(resolve => {\n this.resolveDone = resolve;\n });\n }\n\n async run(): Promise<void> {\n try {\n const run = await this.openRun();\n if (!run) return;\n this.deps.logger.debug(this.opened(run));\n await executeRun({\n run,\n handler: this.handler,\n api: this.deps.api,\n client: this.deps.client,\n logger: this.deps.logger,\n tracker: this.deps.tracker,\n });\n } catch (error) {\n this.deps.logger.error('erro inesperado na execução do agente:', error);\n } finally {\n this.resolveDone();\n }\n }\n\n /** Desiste de obter a run (close() antes dela existir). Uma run já em execução segue pelo tracker. */\n stop(): void {\n this.abort.abort();\n }\n\n /** O descritor da run a executar — `undefined` quando não há o que executar (parado, recusado). */\n protected abstract openRun(): Promise<RunDescriptor | undefined>;\n\n /** Linha de debug quando a run foi obtida. */\n protected abstract opened(run: RunDescriptor): string;\n}\n","import { TasksApiError } from './api';\nimport type { LocalRunnerDeps } from './local';\nimport type { RunDescriptor } from './protocol';\nimport { SingleRunRunner } from './single-run';\nimport type { AgentHandler } from './types';\nimport { abortableSleep, jitter } from '../utils';\n\n/** Esperas entre tentativas do início da run — limitadas: esgotadas, o processo desiste e sai. */\nconst START_RETRY_DELAYS_MS: readonly number[] = [1_000, 4_000, 16_000];\n\n/** Rede, timeout, 5xx e 429 são transitórios; qualquer outra rejeição (404, 409, 401…) é definitiva. */\nfunction isTransient(error: unknown): boolean {\n if (!(error instanceof TasksApiError)) return true;\n return error.status >= 500 || error.status === 429;\n}\n\nfunction describeRejection(runId: string, error: unknown): string {\n if (error instanceof TasksApiError && error.status === 404) {\n return `run ${runId} não existe na plataforma (404) — nada a executar`;\n }\n if (error instanceof TasksApiError && error.status === 409) {\n return `run ${runId} não pode ser iniciada (409: cancelada, já iniciada ou de outra instância) — nada a executar`;\n }\n return `não foi possível iniciar a run ${runId} (${String(error)}) — nada a executar`;\n}\n\n/**\n * register() com HOBOTS_RUN_ID: a run já foi criada reivindicada para esta instância\n * (o Studio sobe o bot para executá-la). Em vez do poll, anexa-se a ela\n * (POST /v1/runs/:id/start) e executa o handler UMA vez pelo pipeline normal. Falha\n * transitória tem retry limitado; 404/409 encerram sem executar. `done` resolve em\n * qualquer desfecho — o runtime então faz close() para o processo sair.\n */\nexport class AttachedRunner extends SingleRunRunner<LocalRunnerDeps> {\n constructor(\n private readonly runId: string,\n handler: AgentHandler,\n deps: LocalRunnerDeps\n ) {\n super(handler, deps);\n }\n\n protected opened(run: RunDescriptor): string {\n return `run ${run.id} iniciada (HOBOTS_RUN_ID)`;\n }\n\n protected async openRun(): Promise<RunDescriptor | undefined> {\n for (let attempt = 0; ; attempt++) {\n if (this.abort.signal.aborted) return undefined;\n try {\n return await this.deps.api.startRun(this.runId, { instance: this.deps.instanceInfo() }, this.abort.signal);\n } catch (error) {\n if (this.abort.signal.aborted) return undefined;\n if (!isTransient(error)) {\n this.deps.logger.error(describeRejection(this.runId, error));\n return undefined;\n }\n const delay = START_RETRY_DELAYS_MS[attempt];\n if (delay === undefined) {\n this.deps.logger.error(\n `não foi possível iniciar a run ${this.runId} após ${attempt + 1} tentativas (${String(error)}) — desistindo`\n );\n return undefined;\n }\n const wait = jitter(delay);\n this.deps.logger.warn(`início da run ${this.runId} falhou (${String(error)}), próxima tentativa em ${wait}ms`);\n await abortableSleep(wait, this.abort.signal);\n }\n }\n }\n}\n","import type { ItemColumn } from './protocol';\nimport type { Logger } from '../utils';\nimport { WIRE_LIMITS } from '../wire-limits';\n\n// mesmas regras da plataforma (@workspace/utils/item-columns; limites de WIRE_LIMITS) — coluna fora delas é descartada aqui\nconst KEY_RE = /^[a-zA-Z0-9_.-]{1,100}$/;\nconst MAX_COLUMNS = WIRE_LIMITS.MAX_ITEM_COLUMNS;\nconst MAX_LABEL_CHARS = WIRE_LIMITS.MAX_ITEM_COLUMN_LABEL_CHARS;\n\n/** Coluna de itens como o dev declara: só a chave, ou chave + rótulo. */\nexport type ItemColumnInput = string | { key: string; label?: string };\n\n/**\n * Normaliza `items.columns` do register/start. Nunca lança: coluna inválida,\n * repetida ou além do teto é descartada com aviso (visível com `debug`).\n * Devolve undefined quando não há declaração utilizável.\n */\nexport function normalizeItemColumns(input: unknown, logger: Logger): ItemColumn[] | undefined {\n if (input === undefined || input === null) return undefined;\n const columns = (input as { columns?: unknown }).columns;\n if (typeof input !== 'object' || !Array.isArray(columns)) {\n logger.warn(`items.columns precisa ser uma lista — declaração de colunas ignorada`);\n return undefined;\n }\n\n const result: ItemColumn[] = [];\n const seen = new Set<string>();\n for (const entry of columns as unknown[]) {\n const rawKey = typeof entry === 'string' ? entry : (entry as { key?: unknown } | null)?.key;\n const rawLabel = typeof entry === 'object' && entry !== null ? (entry as { label?: unknown }).label : undefined;\n const key = typeof rawKey === 'string' ? rawKey.trim() : '';\n if (!KEY_RE.test(key)) {\n logger.warn(`coluna de item inválida ignorada (${JSON.stringify(rawKey)}) — use letras, números, ponto, hífen e underline`);\n continue;\n }\n if (seen.has(key)) {\n logger.warn(`coluna de item \"${key}\" repetida ignorada`);\n continue;\n }\n if (result.length >= MAX_COLUMNS) {\n logger.warn(`no máximo ${MAX_COLUMNS} colunas de item — \"${key}\" em diante ignoradas`);\n break;\n }\n seen.add(key);\n const label = typeof rawLabel === 'string' ? rawLabel.trim().slice(0, MAX_LABEL_CHARS) : '';\n result.push(label ? { key, label } : { key });\n }\n return result.length > 0 ? result : undefined;\n}\n","import type { TasksApi } from './api';\nimport { Backoff } from './backoff';\nimport type { InstanceInfo, RunDescriptor } from './protocol';\nimport { SingleRunRunner, type SingleRunDeps } from './single-run';\nimport type { AgentHandler } from './types';\nimport { abortableSleep } from '../utils';\n\n/** Deps dos runners que falam com a plataforma (modo start e run anexada). */\nexport interface LocalRunnerDeps extends SingleRunDeps {\n api: TasksApi;\n /** Presença da instância no momento da criação (modo, colunas de itens, máquina). */\n instanceInfo: () => InstanceInfo;\n}\n\n/**\n * Modo start: o bot abre a própria run na plataforma (POST /v1/runs) e executa\n * o handler UMA vez dentro dela — logs, itens, progresso e anexos fluem pelo mesmo\n * reporter de uma run reivindicada no poll. Enquanto a plataforma não responde, insiste\n * com o ladder do poll: o handler só começa quando a run existe.\n */\nexport class LocalRunner extends SingleRunRunner<LocalRunnerDeps> {\n private readonly backoff: Backoff;\n\n constructor(handler: AgentHandler, deps: LocalRunnerDeps) {\n super(handler, deps);\n this.backoff = new Backoff(deps.logger, 'criação da run');\n }\n\n protected opened(run: RunDescriptor): string {\n return `run ${run.id} aberta (modo start)`;\n }\n\n protected async openRun(): Promise<RunDescriptor | undefined> {\n for (;;) {\n if (this.abort.signal.aborted) return undefined;\n try {\n return await this.deps.api.createRun({ instance: this.deps.instanceInfo() }, this.abort.signal);\n } catch (error) {\n if (this.abort.signal.aborted) return undefined;\n await abortableSleep(this.backoff.next(error), this.abort.signal);\n }\n }\n }\n}\n","import type { RunTransport } from './api';\nimport { printRunLog } from './context';\nimport { collectFileRefs } from './files';\nimport type {\n FileDownloadResponse,\n RunAttachmentCreateRequest,\n RunAttachmentCreateResponse,\n RunItemsCreateRequest,\n RunItemsCreateResponse,\n RunItemsDoneResponse,\n RunItemStatus,\n RunUpdateRequest,\n} from './protocol';\n\n/** Id da run no modo local — nunca chega ao servidor. */\nexport const LOCAL_RUN_ID = 'local';\n/** Prefixo da linha por item no stdout: `[hobots:item] <status>\\t<id>\\t<message>`. */\nexport const ITEM_LINE_PREFIX = '[hobots:item]';\n/** Prefixo da linha de totais no stdout, impressa uma vez no fim da run. */\nexport const SUMMARY_LINE_PREFIX = '[hobots:summary]';\nexport const ATTACHMENTS_DISCARDED_WARNING = 'imagens e anexos não são enviados no modo local (descartados)';\n\n/** Desfecho da run no modo local — vira o exit code do processo (0 / 1 / 130). */\nexport type LocalRunOutcome = 'succeeded' | 'failed' | 'canceled';\n\nfunction unavailable(name: string): Error {\n return new Error(`arquivo \"${name}\" enviado pela Central não está disponível no modo local`);\n}\n\n/** Tab e quebra de linha quebrariam o formato de uma linha por item — viram espaço. */\nfunction cell(value: string | undefined): string {\n // igual ao Python: `\\r\\n` vira UM espaço\n return (value ?? '').replace(/\\r\\n|[\\t\\r\\n]/g, ' ');\n}\n\n/**\n * Transporte do modo local (`HOBOTS_LOCAL_RUN=1`): a mesma superfície que o `RunReporter`\n * e o `RunFileStore` usam da `TasksApi`, sem nenhuma rede. Status e logs são descartados\n * (o eco no terminal já saiu pelo reporter); itens viram uma linha `[hobots:item]` cada e\n * são contados para o `[hobots:summary]` do fim; imagens e anexos são descartados com um\n * aviso único; arquivos enviados pela Central não existem aqui.\n */\nexport class LocalRunTransport implements RunTransport {\n private readonly counts: Record<RunItemStatus, number> = { succeeded: 0, occurrence: 0, failed: 0 };\n private warnedAttachments = false;\n /** Status terminal que o pipeline reportou — `undefined` enquanto a run corre (ou se ela nem reportou). */\n terminalStatus: 'succeeded' | 'failed' | undefined;\n\n constructor(\n /** Params da run — para citar o nome do arquivo da Central que o bot tentou baixar. */\n private readonly params: Record<string, unknown> = {},\n private readonly out: (line: string) => void = line => void process.stdout.write(`${line}\\n`)\n ) {}\n\n async updateRun(_runId: string, update: RunUpdateRequest): Promise<void> {\n if (update.status === 'running') return;\n this.terminalStatus = update.status;\n // sem Central para mostrar o erro, ele sai no stderr: resumo + stack completa; cancelamento não é defeito\n if (update.status === 'failed' && update.error && update.error.type !== 'RunCanceled') {\n printRunLog('error', `execução falhou — ${update.error.type ?? 'Error'}: ${update.error.message}`);\n if (update.error.stack) console.error(update.error.stack);\n }\n }\n\n async updateRunOnce(): Promise<void> {\n // exit path: nada a reportar sem Central\n }\n\n async createItems(_runId: string, request: RunItemsCreateRequest): Promise<RunItemsCreateResponse> {\n for (const item of request.items) {\n this.counts[item.status]++;\n this.out(`${ITEM_LINE_PREFIX} ${item.status}\\t${cell(item.id)}\\t${cell(item.message)}`);\n }\n return { accepted: request.items.length, duplicates: 0 };\n }\n\n // modo local não tem trabalho anterior: nada a pular\n async listDoneItems(): Promise<RunItemsDoneResponse> {\n return { ids: [], next: null };\n }\n\n /** Totais por status — chame uma vez, no fim da run, antes da linha de conclusão. */\n printSummary(): void {\n const { succeeded, occurrence, failed } = this.counts;\n this.out(\n `${SUMMARY_LINE_PREFIX} total=${succeeded + occurrence + failed} ok=${succeeded} avisos=${occurrence} falhas=${failed} pulados=0`\n );\n }\n\n async createAttachment(_runId: string, request: RunAttachmentCreateRequest): Promise<RunAttachmentCreateResponse> {\n if (!this.warnedAttachments) {\n this.warnedAttachments = true;\n printRunLog('warning', ATTACHMENTS_DISCARDED_WARNING);\n }\n // o reporter segue o fluxo normal (upload → confirmação) contra estes no-ops: nenhum outro aviso\n return { id: request.id, upload_url: '', headers: {}, expires_in: 0 };\n }\n\n async uploadAttachment(): Promise<void> {\n // descartado\n }\n\n async confirmAttachment(): Promise<void> {\n // descartado\n }\n\n /** Nome do arquivo pelo id (nos params); sem ele, o próprio id. */\n private fileName(fileId: string): string {\n return collectFileRefs(this.params).find(ref => ref.id === fileId)?.name ?? fileId;\n }\n\n async requestFileDownload(_runId: string, fileId: string): Promise<FileDownloadResponse> {\n throw unavailable(this.fileName(fileId));\n }\n\n async fetchFile(url: string): Promise<Response> {\n throw unavailable(url);\n }\n\n async confirmFileDownload(_runId: string, fileId: string): Promise<void> {\n throw unavailable(this.fileName(fileId));\n }\n}\n","import { printRunLog } from './context';\nimport { LOCAL_RUN_ID, type LocalRunOutcome, type LocalRunTransport } from './local-transport';\nimport type { RunDescriptor } from './protocol';\nimport { SingleRunRunner, type SingleRunDeps } from './single-run';\nimport type { AgentHandler } from './types';\nimport { nowISO } from '../utils';\n\nexport interface LocalRunDeps extends SingleRunDeps {\n api: LocalRunTransport;\n}\n\n/** Exit code do processo por desfecho (SIGINT/SIGTERM = 130, como o shell). */\nexport const LOCAL_RUN_EXIT_CODES: Record<LocalRunOutcome, number> = { succeeded: 0, failed: 1, canceled: 130 };\n/** Depois de SIGINT/SIGTERM, quanto o processo espera o handler parar antes de encerrar mesmo assim. */\nexport const LOCAL_RUN_CANCEL_GRACE_MS = 4_000;\nexport const LOCAL_RUN_BANNER = 'modo local — execução sem a Central; params de HOBOTS_RUN_PARAMS';\n\n/**\n * Modo local (`HOBOTS_LOCAL_RUN=1`): sem Central, a run é montada aqui mesmo (`id` \"local\",\n * params de `HOBOTS_RUN_PARAMS`) e o handler roda UMA vez pelo pipeline normal — o bot testa\n * o mesmo código de produção; só o transporte é o `LocalRunTransport`. `register()` e\n * `start()` se comportam igual neste modo.\n */\nexport class LocalRunRunner extends SingleRunRunner<LocalRunDeps> {\n private canceled = false;\n private startedAt = Date.now();\n private finished = false;\n\n constructor(\n private readonly params: Record<string, unknown>,\n handler: AgentHandler,\n deps: LocalRunDeps\n ) {\n super(handler, deps);\n }\n\n override run(): Promise<void> {\n this.startedAt = Date.now();\n return super.run();\n }\n\n protected opened(): string {\n return 'run local iniciada (HOBOTS_LOCAL_RUN)';\n }\n\n protected async openRun(): Promise<RunDescriptor | undefined> {\n if (this.abort.signal.aborted) return undefined;\n return { id: LOCAL_RUN_ID, params: this.params, form: null, source: 'local', created_at: nowISO() };\n }\n\n /** SIGINT/SIGTERM: dispara o `ctx.signal` da run em voo — o handler para no próximo ponto de parada. */\n cancel(): void {\n this.canceled = true;\n this.deps.tracker.singleActive()?.abort();\n }\n\n /** Desfecho da run: cancelada pelo sinal, senão o status terminal reportado (sem reporte = falha). */\n get outcome(): LocalRunOutcome {\n if (this.canceled) return 'canceled';\n return this.deps.api.terminalStatus ?? 'failed';\n }\n\n /**\n * Fecha o relato no terminal — `[hobots:summary]` e a linha de conclusão — e devolve o\n * desfecho. Idempotente: o runtime chama ao fim da run ou quando a graça do cancelamento\n * esgota com o handler ainda rodando.\n */\n finish(): LocalRunOutcome {\n const outcome = this.outcome;\n if (this.finished) return outcome;\n this.finished = true;\n this.deps.api.printSummary();\n const seconds = Math.round((Date.now() - this.startedAt) / 1000);\n printRunLog('info', `execução local concluída (${outcome}) em ${seconds}s`);\n return outcome;\n }\n}\n","import type { RunTransport } from './api';\nimport type { RunReporter } from './context';\nimport { sleep } from '../utils';\n\n/**\n * Runs em execução no processo, nos dois modos: base do fallback de `hobots.*`\n * fora de um contexto async (run única) e do reporte de emergência no exit path.\n */\nexport class RunTracker {\n private readonly reporters = new Set<RunReporter>();\n private readonly waiters = new Set<() => void>();\n\n constructor(private readonly api: RunTransport) {}\n\n add(reporter: RunReporter): void {\n this.reporters.add(reporter);\n }\n\n remove(reporter: RunReporter): void {\n this.reporters.delete(reporter);\n if (this.reporters.size === 0) {\n for (const resolve of this.waiters) resolve();\n this.waiters.clear();\n }\n }\n\n get activeCount(): number {\n return this.reporters.size;\n }\n\n /** A única run ativa, quando há exatamente uma — o que `hobots.*` usa fora de um contexto async. */\n singleActive(): RunReporter | undefined {\n if (this.reporters.size !== 1) return undefined;\n return this.reporters.values().next().value as RunReporter;\n }\n\n /** Resolve quando não houver mais runs ativas (ou após timeoutMs, devolvendo false). */\n async waitIdle(timeoutMs: number): Promise<boolean> {\n if (this.reporters.size === 0) return true;\n const idle = new Promise<boolean>(resolve => this.waiters.add(() => resolve(true)));\n if (timeoutMs <= 0) return false;\n return Promise.race([idle, sleep(timeoutMs).then(() => false)]);\n }\n\n /**\n * Best-effort do exit path: reporta 'failed'/AgentTerminated para as runs ativas\n * antes do processo morrer, fora da fila do reporter e com timeout curto. Runs já\n * canceladas no app (reporter morto) são puladas; erros de rede são engolidos —\n * o sweep server-side é o backstop.\n */\n async reportAgentTerminated(message: string, timeoutMs = 2_500): Promise<void> {\n const pending: Promise<void>[] = [];\n for (const reporter of this.reporters) {\n if (reporter.isDead) continue;\n // drena os logs pendentes antes do kill (que descarta o buffer) e mata o\n // reporter: o handler zumbi não pode reenviar status por cima do failed\n const logs = reporter.drainLogs();\n reporter.kill();\n pending.push(\n this.api\n .updateRunOnce(\n reporter.context.runId,\n { status: 'failed', error: { type: 'AgentTerminated', message }, logs: logs.length > 0 ? logs : undefined },\n timeoutMs\n )\n .catch(() => {})\n );\n }\n if (pending.length === 0) return;\n await Promise.race([Promise.allSettled(pending), sleep(timeoutMs)]);\n }\n}\n","import { hasInstalledGlobalHandlers } from '../instrument';\nimport { addEmergencyTask, externalListenerCount, markInternal } from '../internal-handlers';\nimport { isNode } from '../utils';\n\nconst WATCHED_SIGNALS = ['SIGINT', 'SIGTERM'] as const;\ntype WatchedSignal = (typeof WATCHED_SIGNALS)[number];\n\n/** O que o exit path precisa saber das runs ativas — implementado pelo RunTracker (poll + start). */\nexport interface ShutdownTarget {\n readonly activeCount: number;\n reportAgentTerminated(message: string): Promise<void>;\n}\n\n/**\n * Rede de segurança do agente: quando o processo morre (sinal ou erro não tratado)\n * com runs em execução, tenta reportar 'failed'/AgentTerminated antes de sair —\n * assim o app mostra a falha na hora, sem esperar o sweep server-side (~120s sem reporte).\n *\n * Nunca interfere no shutdown gracioso: se o programa tem handler próprio para o\n * sinal (ex: SIGINT → close()), o SDK fica quieto e deixa o caminho normal reportar.\n */\nexport function installShutdownHandlers(agent: ShutdownTarget): () => void {\n if (!isNode()) return () => {};\n\n let signaled = false;\n const signalHandlers = new Map<WatchedSignal, () => void>();\n\n for (const signal of WATCHED_SIGNALS) {\n const handler = markInternal(() => {\n // o programa tem handler próprio (shutdown gracioso) — o caminho normal reporta\n if (externalListenerCount(signal) > 0) return;\n if (signaled) return;\n signaled = true;\n\n const reraise = (): void => {\n process.removeListener(signal, handler);\n process.kill(process.pid, signal); // exit default do sinal (código 130/143)\n };\n if (agent.activeCount === 0) {\n reraise();\n return;\n }\n const report = agent.reportAgentTerminated(`o processo do agente recebeu ${signal} durante a execução`);\n addEmergencyTask(report);\n void report.finally(reraise);\n });\n process.on(signal, handler);\n signalHandlers.set(signal, handler);\n }\n\n const onFatal = markInternal((error: Error) => {\n const report =\n agent.activeCount > 0\n ? agent.reportAgentTerminated('o processo do agente morreu com um erro não tratado durante a execução')\n : Promise.resolve();\n addEmergencyTask(report);\n // o exit é decidido pelo instrument (captureUnhandled) ou pelo handler do programa;\n // sem nenhum dos dois, preservamos o comportamento default do Node aqui\n if (!hasInstalledGlobalHandlers() && externalListenerCount('uncaughtException') === 0) {\n void report.finally(() => {\n console.error(error);\n process.exit(1);\n });\n }\n });\n process.on('uncaughtException', onFatal);\n\n return () => {\n for (const [signal, handler] of signalHandlers) process.removeListener(signal, handler);\n process.removeListener('uncaughtException', onFatal);\n };\n}\n","import { Client } from './client';\nimport { resolveConfig } from './config';\nimport {\n fallbackInstanceId,\n INSTANCE_ID_ENV,\n isLocalRun,\n loadDotenv,\n resolveEnvironmentOption,\n resolveInstanceId,\n resolveLocalRunParams,\n resolveRunId,\n} from './env';\nimport { Heartbeat } from './heartbeat';\nimport { installGlobalHandlers } from './instrument';\nimport { externalListenerCount, markInternal } from './internal-handlers';\nimport { MachineSampler } from './machine';\nimport type { EnvironmentInput, EventType } from './protocol';\nimport { TasksApi, type RunTransport } from './tasks/api';\nimport { TaskAgent } from './tasks/agent';\nimport { AttachedRunner } from './tasks/attached';\nimport { image, isImageAttachment, type ImageInput } from './tasks/attachments';\nimport { printRunLog, type RunReporter } from './tasks/context';\nimport { normalizeItemColumns } from './tasks/item-columns';\nimport { LocalRunner } from './tasks/local';\nimport { LOCAL_RUN_BANNER, LOCAL_RUN_CANCEL_GRACE_MS, LOCAL_RUN_EXIT_CODES, LocalRunRunner } from './tasks/local-run';\nimport { LocalRunTransport } from './tasks/local-transport';\nimport type { InstanceInfo, RunLogLevel } from './tasks/protocol';\nimport { RunTracker } from './tasks/registry';\nimport { currentRunReporter } from './tasks/run-context-store';\nimport { installShutdownHandlers } from './tasks/shutdown';\nimport type { AgentHandler, AgentMode, ResolvedRunOptions, RunHandler } from './tasks/types';\nimport type { CaptureAttachment, CaptureHint, HobotsOptions, RegisterOptions, RunOptions, StartOptions } from './types';\nimport { isNode, makeLogger, SDK_VERSION, sleep, type Logger } from './utils';\n\nconst HEARTBEAT_INTERVAL_MS = 30_000;\nconst DEFAULT_RETRIES = 1;\nconst DEFAULT_RETRY_DELAY_MS = 5_000;\nconst DEFAULT_CANCEL_GRACE_MS = 10_000;\nconst MAX_CONCURRENCY = 5;\n\ninterface Runtime {\n options: HobotsOptions;\n /** Telemetria (issues, transactions, heartbeat) — ausente no modo local, que não fala com a Central. */\n client: Client | undefined;\n logger: Logger;\n /** `TasksApi` (rede) ou `LocalRunTransport` (modo local). */\n api: RunTransport;\n /** O handler do agente — um por processo (o agente é a própria tarefa). */\n handler: AgentHandler;\n tracker: RunTracker;\n sampler: MachineSampler | undefined;\n heartbeat: Heartbeat | undefined;\n agent: TaskAgent | undefined;\n local: LocalRunner | undefined;\n /** register() com HOBOTS_RUN_ID: executa só essa run, sem poll. */\n attached: AttachedRunner | undefined;\n /** HOBOTS_LOCAL_RUN=1: handler uma vez, sem Central, e o processo encerra com o exit code do desfecho. */\n localRun: LocalRunRunner | undefined;\n /** Run a que o register() se anexa (opção runId → env HOBOTS_RUN_ID); undefined = poll. */\n runId: string | undefined;\n instanceId: string | undefined;\n environment: EnvironmentInput | undefined;\n pollIntervalMs: number | undefined;\n booted: boolean;\n bootScheduled: boolean;\n bootPromise: Promise<void> | undefined;\n uninstallGlobalHandlers: (() => void) | undefined;\n uninstallShutdown: (() => void) | undefined;\n}\n\nlet runtime: Runtime | undefined;\nlet warnedNoRuntime = false;\n\n/** Hostname da máquina — telemetria (campo `host`), distinto da identidade do agente. */\nfunction hostname(): string | undefined {\n if (!isNode()) return undefined;\n return process.env.HOSTNAME || process.env.COMPUTERNAME || undefined;\n}\n\nfunction baseRuntime(options: HobotsOptions, handler: AgentHandler, logger: Logger, api: RunTransport): Runtime {\n return {\n options: { ...options, clientSecret: undefined },\n client: undefined,\n logger,\n api,\n handler,\n tracker: new RunTracker(api),\n sampler: undefined,\n heartbeat: undefined,\n agent: undefined,\n local: undefined,\n attached: undefined,\n localRun: undefined,\n runId: undefined,\n instanceId: resolveInstanceId(options.instanceId),\n environment: undefined,\n pollIntervalMs: undefined,\n booted: false,\n bootScheduled: false,\n bootPromise: undefined,\n uninstallGlobalHandlers: undefined,\n uninstallShutdown: undefined,\n };\n}\n\n/**\n * Cria o runtime do processo (config, client, handlers globais). `resolveConfig` vem\n * antes de qualquer estado: um secret ausente/inválido lança sem deixar rastro.\n */\nfunction createRuntime(options: HobotsOptions, handler: AgentHandler, logger: Logger): Runtime {\n const config = resolveConfig({ clientSecret: options.clientSecret });\n const environment = resolveEnvironmentOption(options.environment);\n const client = new Client(\n {\n environment,\n release: options.release,\n tags: options.tags,\n debug: options.debug,\n captureRunErrors: options.captureUnhandled !== false,\n },\n config\n );\n const api = new TasksApi({ baseUrl: config.runsBaseUrl, key: config.key, logger });\n const rt = baseRuntime(options, handler, logger, api);\n rt.client = client;\n rt.environment = environment;\n rt.uninstallGlobalHandlers = options.captureUnhandled !== false ? installGlobalHandlers(client) : undefined;\n logger.debug('inicializado', { endpoint: config.ingestEndpoint });\n return rt;\n}\n\n/**\n * Modo local (`HOBOTS_LOCAL_RUN=1`): sem secret, sem rede, sem telemetria. Os params vêm de\n * `HOBOTS_RUN_PARAMS`; inválidos, o processo encerra com código 2 antes de qualquer estado.\n */\nfunction createLocalRunRuntime(options: HobotsOptions, handler: AgentHandler, logger: Logger): Runtime {\n let params: Record<string, unknown>;\n try {\n params = resolveLocalRunParams();\n } catch (error) {\n printRunLog('error', error instanceof Error ? error.message : String(error));\n process.exit(2);\n // só com process.exit substituído (testes) a execução chega aqui — nada é iniciado\n throw error;\n }\n const transport = new LocalRunTransport(params);\n const rt = baseRuntime(options, handler, logger, transport);\n rt.localRun = new LocalRunRunner(params, handler, { api: transport, client: undefined, logger, tracker: rt.tracker });\n printRunLog('info', LOCAL_RUN_BANNER);\n return rt;\n}\n\nfunction validateHandler(handler: unknown, fn: string): void {\n if (typeof handler !== 'function') {\n throw new Error(`[hobots] ${fn}(): o handler precisa ser uma função — ${fn}(async (params) => { ... })`);\n }\n}\n\nfunction clampConcurrency(value: number | undefined): number {\n if (value === undefined || !Number.isFinite(value)) return 1;\n return Math.min(MAX_CONCURRENCY, Math.max(1, Math.floor(value)));\n}\n\nfunction resolveRunOptions(options: RegisterOptions, mode: AgentMode, logger: Logger): ResolvedRunOptions {\n const retries = options.retries === undefined || !Number.isFinite(options.retries) ? DEFAULT_RETRIES : Math.max(0, Math.floor(options.retries));\n return {\n retries,\n retryDelayMs: options.retryDelayMs ?? DEFAULT_RETRY_DELAY_MS,\n timeoutMs: options.timeoutMs && options.timeoutMs > 0 ? options.timeoutMs : undefined,\n concurrency: mode === 'remote' ? clampConcurrency(options.concurrency) : 1,\n logFlushIntervalMs: options.logFlushIntervalMs,\n cancelCheckIntervalMs: options.cancelCheckIntervalMs,\n cancelGraceMs: options.cancelGraceMs ?? DEFAULT_CANCEL_GRACE_MS,\n itemColumns: normalizeItemColumns(options.items, logger),\n };\n}\n\n/** Presença da instância — a mesma nos polls e na criação de runs do modo start. */\nfunction instanceInfo(rt: Runtime): InstanceInfo {\n return {\n /* v8 ignore start -- defensivo: o boot define o instanceId antes de qualquer poll/criação de run */\n instance_id: rt.instanceId ?? 'unknown',\n /* v8 ignore stop */\n version: SDK_VERSION,\n host: hostname(),\n // ambiente da instância: junto do heartbeat, é como o servidor sabe onde o robô roda\n environment: rt.environment,\n // como esta instância trabalha — o painel mostra \"sob demanda\" / \"sempre ligado\"\n mode: rt.handler.mode === 'remote' ? 'on_demand' : 'always_on',\n // colunas da aba \"itens\" declaradas no código — a plataforma usa enquanto o usuário não personalizar\n items: rt.handler.options.itemColumns ? { attributes: rt.handler.options.itemColumns } : undefined,\n // o servidor calcula a tolerância de offline (3×) a partir disto em agentes que fazem\n // poll; clampado à faixa aceita pelo schema (1s..15min)\n poll_interval_ms: rt.agent ? Math.min(Math.max(rt.agent.pollIntervalMs, 1_000), 900_000) : undefined,\n // recursos da máquina — alimenta a série da instância (o servidor grava no máx. 1 ponto/30s)\n machine: rt.sampler?.sample(),\n };\n}\n\n/** A API da plataforma — só fora do modo local (que não tem `TasksApi`). */\nfunction platformApi(rt: Runtime): TasksApi {\n return rt.api as TasksApi;\n}\n\nfunction ensureAgent(rt: Runtime): TaskAgent {\n rt.agent ??= new TaskAgent({\n api: platformApi(rt),\n client: rt.client,\n logger: rt.logger,\n handler: rt.handler,\n tracker: rt.tracker,\n instanceInfo: () => instanceInfo(rt),\n pollIntervalMs: rt.pollIntervalMs,\n });\n return rt.agent;\n}\n\nfunction launchLocal(rt: Runtime): void {\n const runner = new LocalRunner(rt.handler, {\n api: platformApi(rt),\n client: rt.client,\n logger: rt.logger,\n tracker: rt.tracker,\n instanceInfo: () => instanceInfo(rt),\n });\n rt.local = runner;\n void runner.run();\n}\n\n/**\n * Executa a run de HOBOTS_RUN_ID e, terminada (ou recusada), encerra o SDK: sem poll nem\n * outro trabalho, o processo do bot sai sozinho. Se close() já correu (ou outro runtime\n * assumiu), não fecha nada.\n */\nfunction launchAttached(rt: Runtime, runId: string): void {\n const runner = new AttachedRunner(runId, rt.handler, {\n api: platformApi(rt),\n client: rt.client,\n logger: rt.logger,\n tracker: rt.tracker,\n instanceInfo: () => instanceInfo(rt),\n });\n rt.attached = runner;\n void runner.run();\n void runner.done.then(() => {\n if (runtime === rt) void close();\n });\n}\n\n/**\n * Modo local: roda a run e encerra o processo com o exit code do desfecho (0 ok, 1 falha,\n * 130 cancelada). SIGINT/SIGTERM cancelam a run em voo (ctx.signal) e esperam o handler\n * parar por até LOCAL_RUN_CANCEL_GRACE_MS — depois disso o processo encerra mesmo assim.\n * As linhas finais saem antes do exit: o stdout é drenado (write com callback) e só então\n * o processo morre, para um pipe não perder o `[hobots:summary]`.\n */\nfunction launchLocalRun(rt: Runtime, runner: LocalRunRunner): void {\n let finished = false;\n const finish = (): void => {\n if (finished) return;\n finished = true;\n rt.uninstallShutdown?.();\n rt.uninstallShutdown = undefined;\n const code = LOCAL_RUN_EXIT_CODES[runner.finish()];\n if (runtime === rt) void close(0);\n process.stdout.write('', () => process.exit(code));\n };\n if (rt.options.installExitHandlers !== false) {\n let signaled = false;\n const onSignal = (signal: 'SIGINT' | 'SIGTERM'): void => {\n // o programa tem handler próprio para o sinal: ele decide (chame hobots.close() nele)\n if (externalListenerCount(signal) > 0 || signaled) return;\n signaled = true;\n runner.cancel();\n void Promise.race([runner.done, sleep(LOCAL_RUN_CANCEL_GRACE_MS)]).then(finish);\n };\n const onInt = markInternal((): void => onSignal('SIGINT'));\n const onTerm = markInternal((): void => onSignal('SIGTERM'));\n process.on('SIGINT', onInt);\n process.on('SIGTERM', onTerm);\n rt.uninstallShutdown = () => {\n process.off('SIGINT', onInt);\n process.off('SIGTERM', onTerm);\n };\n }\n void runner.run();\n void runner.done.then(finish);\n}\n\n/**\n * Boot único do processo, num microtask depois do register()/start(): o chamador\n * ainda pode instalar handlers de sinal na mesma volta do event loop antes do primeiro\n * poll sair. Se close() correu antes, o runtime já não é este e o boot não faz nada.\n */\nasync function boot(rt: Runtime): Promise<void> {\n if (rt.localRun) {\n // sem Central não há identidade a resolver, métricas, heartbeat nem exit path a instalar\n rt.booted = true;\n launchLocalRun(rt, rt.localRun);\n return;\n }\n if (!rt.instanceId) {\n const id = await fallbackInstanceId();\n if (runtime !== rt) return;\n rt.instanceId = id;\n rt.logger.debug(`instanceId não informado (env ${INSTANCE_ID_ENV}) — usando o hostname \"${id}\"`);\n }\n if (runtime !== rt) return;\n rt.booted = true;\n\n // CPU/memória/disco: no heartbeat e no poll (série da instância) e em contexts.machine\n // dos eventos. start() é assíncrono (import dinâmico de node:os) — até completar,\n // sample() devolve undefined e o SDK segue normalmente.\n if (rt.options.machineMetrics !== false) {\n rt.sampler = new MachineSampler(rt.instanceId, rt.logger);\n void rt.sampler.start();\n rt.client!.attachMachineSampler(rt.sampler);\n }\n\n // heartbeat sempre ligado e ref'd: é ele que mantém o processo vivo no modo start\n // depois que o handler retornou — o SDK fica sempre vivo até close()\n rt.heartbeat = new Heartbeat(rt.client!, { intervalMs: HEARTBEAT_INTERVAL_MS, keepAlive: true }, rt.instanceId, rt.sampler);\n rt.heartbeat.start();\n\n if (rt.options.installExitHandlers !== false) {\n rt.uninstallShutdown = installShutdownHandlers(rt.tracker);\n }\n\n if (rt.handler.mode === 'local') launchLocal(rt);\n else if (rt.runId) launchAttached(rt, rt.runId);\n else ensureAgent(rt).start();\n}\n\nfunction scheduleBoot(rt: Runtime): void {\n /* v8 ignore start -- defensivo: startAgent agenda o boot uma vez, num runtime recém-criado */\n if (rt.bootScheduled) return;\n /* v8 ignore stop */\n rt.bootScheduled = true;\n queueMicrotask(() => {\n rt.bootPromise = boot(rt).catch(error => rt.logger.error('falha ao iniciar o SDK:', error));\n });\n}\n\n/**\n * O agente é a própria tarefa: UM register() ou start() por processo. A segunda chamada\n * lança — não há como um processo ser dois agentes, nem rodar nos dois modos.\n */\nfunction startAgent(fn: 'register' | 'start', mode: AgentMode, handler: RunHandler, options: RegisterOptions): void {\n validateHandler(handler, fn);\n if (runtime) {\n throw new Error(`[hobots] ${fn}(): o agente já foi iniciado — register()/start() só pode ser chamado uma vez por processo (chame hobots.close() antes de iniciar de novo)`);\n }\n const logger = makeLogger(options.debug ?? false);\n const agentHandler: AgentHandler = { mode, handler, options: resolveRunOptions(options, mode, logger) };\n // idempotente: o import do pacote já carregou; aqui cobre bundler que descartou o efeito do import\n // (e a decisão do modo local lê a env antes de qualquer outra coisa)\n loadDotenv();\n // modo local ignora o secret e a HOBOTS_RUN_ID; fora dele, resolveConfig (dentro de createRuntime)\n // lança com secret ausente/inválido ANTES de qualquer estado\n const rt = isLocalRun() ? createLocalRunRuntime(options, agentHandler, logger) : createRuntime(options, agentHandler, logger);\n if (!rt.localRun && mode === 'remote') {\n if (options.pollIntervalMs !== undefined) rt.pollIntervalMs = options.pollIntervalMs;\n rt.runId = resolveRunId(options.runId);\n }\n runtime = rt;\n scheduleBoot(rt);\n}\n\n/**\n * Agente sob demanda: o handler roda a cada solicitação do app (formulário/agendamento), via polling.\n * Com HOBOTS_RUN_ID (ou a opção runId), executa só essa run e encerra — sem poll.\n */\nexport function register<P = Record<string, unknown>>(handler: RunHandler<P>, options: RegisterOptions = {}): void {\n startAgent('register', 'remote', handler as RunHandler, options);\n}\n\n/** Agente sempre ligado: abre a própria run e roda o handler uma vez; a plataforma recebe logs, itens e progresso. */\nexport function start(handler: RunHandler, options: StartOptions = {}): void {\n startAgent('start', 'local', handler, options as RunOptions);\n}\n\n/** Reporter da run atual: contexto async → única run ativa → nenhum. */\nexport function currentReporter(): RunReporter | undefined {\n return currentRunReporter() ?? runtime?.tracker.singleActive();\n}\n\nexport function activeLogger(): Logger | undefined {\n return runtime?.logger;\n}\n\n/** O log da run não tem 'fatal' — rebaixa para 'error'. */\nfunction toRunLogLevel(type: EventType): RunLogLevel {\n return type === 'fatal' ? 'error' : type;\n}\n\n/**\n * Encaminha o `attachment` de um captureException para o pipeline de anexos da run\n * atual (fire-and-forget): a imagem vira anexo da linha de log que espelha o evento.\n * Fora de uma execução não há onde pendurar a imagem — descarta com aviso.\n */\nfunction forwardAttachment(rt: Runtime, attachment: ImageInput | CaptureAttachment, message: string, type: EventType): string | undefined {\n const reporter = currentReporter();\n if (!reporter) {\n rt.logger.warn('attachment descartado — só é suportado dentro de uma execução');\n return undefined;\n }\n const withMeta =\n typeof attachment === 'object' && !isImageAttachment(attachment) && 'image' in attachment\n ? image(attachment.image, { caption: attachment.caption, contentType: attachment.contentType })\n : attachment;\n return reporter.log(toRunLogLevel(type), message, withMeta);\n}\n\n/**\n * Captura uma exceção como issue e retorna o event_id (undefined antes de register()/start()). `hint.attachment` envia um print junto — dentro de uma execução, ele\n * aparece na linha de log da run correspondente ao erro e na própria issue (`contexts.run.attachments`).\n */\nexport function captureException(error: unknown, hint?: CaptureHint): string | undefined {\n const rt = runtime;\n if (!rt) {\n if (!warnedNoRuntime) {\n warnedNoRuntime = true;\n console.warn('[hobots] captureException antes de iniciar o agente (register/start) — evento descartado');\n }\n return undefined;\n }\n let attachmentId: string | undefined;\n if (hint?.attachment) {\n const message = error instanceof Error ? `${error.name}: ${error.message}` : String(error);\n attachmentId = forwardAttachment(rt, hint.attachment, message, hint.type ?? 'error');\n }\n // modo local: sem Central não há issue — o erro já apareceu no terminal pelo próprio bot\n if (!rt.client) {\n rt.logger.debug('captureException ignorado no modo local (sem Central)');\n return undefined;\n }\n // dentro de uma execução, a issue fica ligada a ela (a tag do bot, se houver, vence)\n const runId = currentReporter()?.runId;\n const withRun = runId ? { ...hint, tags: { run_id: runId, ...hint?.tags } } : hint;\n // o print vai junto do evento por referência (o binário é anexo da run): a Central o mostra na issue\n const contexts = runId && attachmentId ? { run: { id: runId, attachments: [attachmentId] } } : undefined;\n return rt.client.captureException(error, withRun, contexts);\n}\n\n/**\n * Encerra tudo: para o polling, aguarda as runs em voo (até timeoutMs), para o\n * heartbeat (libera o processo) e faz o flush final. Um register()/start() depois\n * disto inicia um runtime novo.\n */\nexport async function close(timeoutMs = 30_000): Promise<boolean> {\n const rt = runtime;\n if (!rt) return true;\n runtime = undefined;\n await rt.bootPromise;\n\n // stop(0): só para o polling — a espera pelas runs (dos dois modos) é do tracker, abaixo\n if (rt.agent) await rt.agent.stop(0);\n rt.local?.stop();\n rt.attached?.stop();\n rt.localRun?.stop();\n\n const idle = await rt.tracker.waitIdle(timeoutMs);\n if (!idle) {\n rt.logger.warn(`${rt.tracker.activeCount} run(s) ainda em execução após ${timeoutMs}ms — abandonando a espera`);\n // o processo vai morrer com as runs no meio: falha imediata no app em vez\n // de esperar o sweep server-side marcar o encerramento inesperado\n await rt.tracker.reportAgentTerminated('agente encerrado durante a execução (shutdown excedeu o tempo de espera)');\n }\n\n rt.heartbeat?.stop();\n rt.uninstallShutdown?.();\n rt.uninstallGlobalHandlers?.();\n const flushed = rt.client ? await rt.client.close(timeoutMs) : true;\n return idle && flushed;\n}\n\n/**\n * Apenas para testes internos: zera o singleton sem esperar nada. Não é reexportado\n * por `index.ts` — fora da superfície pública.\n */\nexport function _resetForTesting(): void {\n const rt = runtime;\n runtime = undefined;\n warnedNoRuntime = false;\n if (!rt) return;\n rt.heartbeat?.stop();\n if (rt.agent) void rt.agent.stop(0);\n rt.local?.stop();\n rt.attached?.stop();\n rt.localRun?.stop();\n rt.uninstallShutdown?.();\n rt.uninstallGlobalHandlers?.();\n}\n\n/** Apenas para testes internos: estado interno do runtime atual. */\nexport function _runtimeForTesting():\n | {\n handler: AgentHandler;\n tracker: RunTracker;\n agent: TaskAgent | undefined;\n heartbeat: Heartbeat | undefined;\n localRun: LocalRunRunner | undefined;\n instanceId: string | undefined;\n booted: boolean;\n bootPromise: Promise<void> | undefined;\n client: Client | undefined;\n }\n | undefined {\n return runtime;\n}\n","import * as runtime from './runtime';\nimport { retryWithBackoff, type RetryOptions } from './retry';\nimport { image as makeImage, type AttachInput, type ImageAttachment, type ImageOptions } from './tasks/attachments';\nimport { printRunLog, splitLogArgs } from './tasks/context';\nimport { eachItem, type EachSink } from './tasks/each';\nimport { isFileRef as isFileRefImpl, type RunFiles } from './tasks/files';\nimport type { FileRef, RunLogLevel } from './tasks/protocol';\nimport type { RunContext, RunHandler, RunItems, RunLogger, RunProgressReporter } from './tasks/types';\nimport { Transaction } from './transaction';\nimport type { CaptureHint, RegisterOptions, StartOptions, StepFn, StepOptions } from './types';\nimport { sleep } from './utils';\n\n/**\n * O objeto global do SDK: as funções do processo (register/start/close/captureException/\n * retry) e o contexto da execução ATUAL (log, items, progress, step, signal…),\n * resolvido a cada acesso — funciona de qualquer módulo, sem passar `ctx` de mão em mão.\n */\nexport interface Hobots extends RunContext {\n /**\n * Agente sob demanda: o handler roda a cada solicitação do app (formulário/agendamento), via polling.\n * O agente é a própria tarefa: uma chamada por processo (register OU start).\n */\n register<P = Record<string, unknown>>(handler: RunHandler<P>, options?: RegisterOptions): void;\n /** Agente sempre ligado: abre a própria run e roda o handler; a plataforma recebe logs, itens e progresso. */\n start(handler: RunHandler, options?: StartOptions): void;\n /** Encerra tudo (polling, runs em voo, heartbeat, flush final). Chame antes do processo terminar. */\n close(timeoutMs?: number): Promise<boolean>;\n /** Captura uma exceção como issue (módulo Issues). Retorna o event_id. */\n captureException(error: unknown, hint?: CaptureHint): string | undefined;\n /**\n * Embrulha um print para ir junto de um log, item ou etapa — `hobots.log.error('x', hobots.image(png))`,\n * `hobots.items.failed('x', payload, { image: hobots.image(png, { caption }) })`,\n * `etapa.warning('x', { image: png })`. Puro: nenhum I/O até o evento ser registrado.\n */\n image(input: AttachInput, options?: ImageOptions): ImageAttachment;\n /** O valor tem a forma de um arquivo de campo de upload (`FileRef`) — puro, sem I/O. */\n isFileRef(value: unknown): value is FileRef;\n}\n\ndeclare global {\n // `var` é obrigatório numa declaração global de variável (let/const não viram globalThis.hobots)\n var hobots: Hobots;\n}\n\n// ── fallbacks fora de uma execução ────────────────────────────────────────────\n\nconst warned = new Set<string>();\n\nfunction warnOutsideRun(member: string): void {\n if (warned.has(member)) return;\n warned.add(member);\n const message = `hobots.${member} usado fora de uma execução — ignorado (inicie o agente com register()/start() e use dentro do handler)`;\n const logger = runtime.activeLogger();\n if (logger) logger.warn(message);\n else console.warn(`[hobots] ${message}`);\n}\n\n/** Fora de uma run o log ainda aparece no terminal — só não vai para a plataforma (a imagem é descartada). */\nconst fallbackLogAt =\n (level: RunLogLevel) =>\n (message: unknown, ...rest: unknown[]): void => {\n const { text, image: dropped } = splitLogArgs(message, rest);\n printRunLog(level, dropped ? `${text} [imagem descartada]` : text);\n };\nconst fallbackLog: RunLogger = {\n debug: fallbackLogAt('debug'),\n info: fallbackLogAt('info'),\n warn: fallbackLogAt('warning'),\n error: fallbackLogAt('error'),\n success: fallbackLogAt('success'),\n};\n\nconst noop = (): void => undefined;\n// fora de uma run o `each` ainda percorre a lista (o handler é código do bot) — só não reporta\nconst fallbackEachSink: EachSink = {\n report: noop,\n startStep: () => undefined,\n stepScope: (_step, fn) => fn(),\n declareTotal: noop,\n advance: noop,\n checkCanceled: noop,\n isAborted: () => false,\n /* v8 ignore start -- fora de uma run não há consulta de concluídos, logo nunca há item pulado para anunciar */\n logInfo: message => printRunLog('info', message),\n /* v8 ignore stop */\n logWarning: message => printRunLog('warning', message),\n logError: message => printRunLog('error', message),\n sleep,\n doneItemIds: () => Promise.resolve(undefined),\n flush: () => Promise.resolve(),\n};\nconst fallbackItems: RunItems = {\n add: noop,\n succeeded: noop,\n failed: noop,\n occurrence: noop,\n each: (list, handler, options = {}) => eachItem(list, handler, options, fallbackEachSink),\n};\nconst fallbackProgress: RunProgressReporter = { total: noop, advance: noop, set: noop, current: 0, snapshot: null };\n// fora de uma run não há params (logo, nenhum arquivo) nem run para confirmar o download\nconst outsideRunFiles = (): Promise<never> =>\n Promise.reject(new Error('hobots.files só baixa arquivos dentro de uma execução (handler do register()/start())'));\nconst fallbackFiles: RunFiles = {\n list: () => [],\n get: () => undefined,\n download: outsideRunFiles,\n downloadAll: outsideRunFiles,\n read: outsideRunFiles,\n};\nconst neverAborts = new AbortController().signal;\n\nfunction resolve(member: string): RunContext | undefined {\n const reporter = runtime.currentReporter();\n if (reporter) return reporter.context;\n warnOutsideRun(member);\n return undefined;\n}\n\nfunction getter<K extends keyof RunContext>(member: K, fallback: () => RunContext[K]): PropertyDescriptor {\n return { enumerable: true, get: () => resolve(member)?.[member] ?? fallback() };\n}\n\nfunction method(value: unknown): PropertyDescriptor {\n return { enumerable: true, writable: false, value };\n}\n\nexport const hobots: Hobots = Object.defineProperties({} as Hobots, {\n // ── contexto da run atual (getters) ─────────────────────────────────────────\n runId: getter('runId', () => ''),\n params: getter('params', () => ({})),\n log: getter('log', () => fallbackLog),\n items: getter('items', () => fallbackItems),\n progress: getter('progress', () => fallbackProgress),\n files: getter('files', () => fallbackFiles),\n signal: getter('signal', () => neverAborts),\n step: method(<T>(name: string, fn: StepFn<T>, options?: StepOptions): Promise<T> => {\n const ctx = resolve('step');\n if (ctx) return ctx.step(name, fn, options);\n // fora de uma run: roda `fn` com o mesmo retry, num handle inerte — nada é registrado\n return new Transaction(undefined, 'hobots.detached').step(name, fn, options);\n }),\n throwIfCanceled: method((): void => resolve('throwIfCanceled')?.throwIfCanceled()),\n sleep: method((ms: number): Promise<void> => resolve('sleep')?.sleep(ms) ?? sleep(ms)),\n flush: method((timeoutMs?: number): Promise<void> => resolve('flush')?.flush(timeoutMs) ?? Promise.resolve()),\n retry: method(<T>(fn: (attempt: number) => T | Promise<T>, options?: RetryOptions): Promise<T> => {\n // fora de uma run o retry funciona igual, só sem cancelamento — não é erro de uso\n const reporter = runtime.currentReporter();\n return reporter ? reporter.context.retry(fn, options) : retryWithBackoff(fn, options);\n }),\n // ── processo ────────────────────────────────────────────────────────────────\n register: method(<P>(handler: RunHandler<P>, options?: RegisterOptions): void => {\n runtime.register(handler, options);\n installGlobalHobots();\n }),\n start: method((handler: RunHandler, options?: StartOptions): void => {\n runtime.start(handler, options);\n installGlobalHobots();\n }),\n close: method((timeoutMs?: number): Promise<boolean> => runtime.close(timeoutMs)),\n captureException: method((error: unknown, hint?: CaptureHint): string | undefined => runtime.captureException(error, hint)),\n image: method(makeImage),\n isFileRef: method(isFileRefImpl),\n});\n\n/**\n * Define `globalThis.hobots` — só no register()/start(), nunca na importação,\n * para o pacote continuar sem efeitos colaterais (`sideEffects: false`).\n */\nexport function installGlobalHobots(): void {\n if ((globalThis as { hobots?: unknown }).hobots === hobots) return;\n Object.defineProperty(globalThis, 'hobots', { value: hobots, configurable: true, writable: true, enumerable: false });\n}\n\n/** Apenas para testes internos. */\nexport function _uninstallGlobalHobots(): void {\n warned.clear();\n if ((globalThis as { hobots?: unknown }).hobots === hobots) {\n delete (globalThis as { hobots?: unknown }).hobots;\n }\n}\n\nexport const register = hobots.register;\nexport const start = hobots.start;\nexport const close = hobots.close;\nexport const captureException = hobots.captureException;\nexport const retry = hobots.retry;\nexport const image = hobots.image;\nexport const isFileRef = hobots.isFileRef;\n","import { loadDotenv } from './env';\nimport { hobots } from './hobots';\n\n// no import, antes do código do bot: `process.env.X` no topo do módulo do bot já enxerga o .env\nloadDotenv();\n\nexport { hobots, register, start, close, captureException, retry, image, isFileRef } from './hobots';\nexport { Occurrence } from './tasks/errors';\nexport default hobots;\n\nexport type { Hobots } from './hobots';\nexport type {\n HobotsOptions,\n RunOptions,\n RegisterOptions,\n StartOptions,\n ItemsOptions,\n RetryDelay,\n RetryOptions,\n CaptureHint,\n CaptureAttachment,\n StepOptions,\n StepHandle,\n StepFn,\n} from './types';\nexport type { ItemColumnInput } from './tasks/item-columns';\nexport type {\n RunHandler,\n RunContext,\n RunLogger,\n RunItems,\n RunItemOptions,\n RunItemImageOptions,\n RunItemHandle,\n RunItemsEachHandler,\n RunItemsEachOptions,\n RunItemsEachResult,\n RunProgressReporter,\n} from './tasks/types';\nexport type { AttachInput, ImageInput, ImageOptions, ImageAttachment } from './tasks/attachments';\nexport type { RunFiles, FileDownloadOptions } from './tasks/files';\n\nexport type {\n EventType,\n BreadcrumbLevel,\n StackFrame,\n Breadcrumb,\n ExceptionData,\n EventUser,\n EventPayload,\n StepData,\n StepStatus,\n TransactionPayload,\n HeartbeatPayload,\n MachineProcess,\n MachineSnapshot,\n Environment,\n EnvironmentInput,\n EnvelopeItem,\n Envelope,\n} from './protocol';\n\nexport type {\n RunStatus,\n RunUpdateStatus,\n RunLogLevel,\n RunLogEntry,\n InstanceInfo,\n PollRequest,\n RunDescriptor,\n PollResponse,\n RunCreateRequest,\n RunCreateResponse,\n RunStartRequest,\n RunStartResponse,\n RunError,\n RunProgress,\n RunUpdateRequest,\n RunUpdateResponse,\n RunItemStatus,\n RunItemInput,\n RunItemsCreateRequest,\n RunItemsCreateResponse,\n RunItemsDoneRequest,\n RunItemsDoneResponse,\n ItemColumn,\n ItemsDeclaration,\n InstanceMode,\n RunAttachmentContentType,\n RunAttachmentCreateRequest,\n RunAttachmentCreateResponse,\n RunAttachmentConfirmRequest,\n RunAttachmentConfirmResponse,\n FileStorage,\n FileRef,\n FileDownloadResponse,\n} from './tasks/protocol';\n"],"mappings":"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","names":["resolve","hostname","image","basePayload","image","field","resolve","method","resolve","image","sleep","resolve","resolve","resolve","DEFAULT_RETRIES","DEFAULT_RETRY_DELAY_MS","register","start","close","captureException","image","isFileRef"]}
|
|
1
|
+
{"version":3,"sources":["../src/utils.ts","../src/env.ts","../src/stacktrace.ts","../src/scrub.ts","../src/eventbuilder.ts","../src/transport.ts","../src/client.ts","../src/config.ts","../src/heartbeat.ts","../src/internal-handlers.ts","../src/instrument.ts","../src/machine.ts","../src/tasks/api.ts","../src/tasks/backoff.ts","../src/tasks/errors.ts","../src/tasks/attachments.ts","../src/tasks/run-context-store.ts","../src/retry.ts","../src/transaction.ts","../src/tasks/each.ts","../src/tasks/files.ts","../src/tasks/context.ts","../src/tasks/runner.ts","../src/tasks/agent.ts","../src/tasks/single-run.ts","../src/tasks/attached.ts","../src/tasks/item-columns.ts","../src/tasks/local.ts","../src/tasks/local-transport.ts","../src/tasks/local-run.ts","../src/tasks/registry.ts","../src/tasks/shutdown.ts","../src/runtime.ts","../src/hobots.ts","../src/index.ts"],"sourcesContent":["/** Injetada pelo `define` do tsup a partir da versão do package.json. */\ndeclare const __SDK_VERSION__: string | undefined;\n\nexport const SDK_NAME = 'hobots';\n/* v8 ignore start -- o `define` do tsup/vitest sempre injeta a versão; o fallback é só para builds sem define */\nexport const SDK_VERSION = typeof __SDK_VERSION__ === 'string' ? __SDK_VERSION__ : '0.0.0-dev';\n/* v8 ignore stop */\n\nexport function isNode(): boolean {\n return typeof process !== 'undefined' && typeof process.versions?.node === 'string';\n}\n\n/** uuid v4 sem hífens (32 hex). Fallback para contextos sem crypto.randomUUID. */\nexport function uuid4(): string {\n const cryptoRef = (globalThis as { crypto?: Crypto }).crypto;\n if (cryptoRef && typeof cryptoRef.randomUUID === 'function') {\n return cryptoRef.randomUUID().replace(/-/g, '');\n }\n if (cryptoRef && typeof cryptoRef.getRandomValues === 'function') {\n const bytes = cryptoRef.getRandomValues(new Uint8Array(16));\n bytes[6] = (bytes[6]! & 0x0f) | 0x40;\n bytes[8] = (bytes[8]! & 0x3f) | 0x80;\n return Array.from(bytes, b => b.toString(16).padStart(2, '0')).join('');\n }\n // último recurso (runtimes sem crypto algum) — ids aqui são só de correlação\n let out = '';\n for (let i = 0; i < 32; i++) {\n out += Math.floor(Math.random() * 16).toString(16);\n }\n return out;\n}\n\nexport function nowISO(): string {\n return new Date().toISOString();\n}\n\n/** Timers não devem segurar o processo Node aberto. */\nexport function unrefTimer(timer: unknown): void {\n (timer as { unref?: () => void } | undefined)?.unref?.();\n}\n\nexport function sleep(ms: number): Promise<void> {\n return new Promise(resolve => {\n const timer = setTimeout(resolve, ms);\n unrefTimer(timer);\n });\n}\n\n/**\n * Sleep que RESOLVE (não rejeita) quando `signal` aborta antes do prazo. Timer não\n * unref'd: quem espera assim está no meio de trabalho legítimo (ex.: abrindo a run\n * do modo start) e deve segurar o processo vivo.\n */\nexport function abortableSleep(ms: number, signal?: AbortSignal): Promise<void> {\n return new Promise(resolve => {\n if (signal?.aborted) {\n resolve();\n return;\n }\n const onAbort = (): void => {\n clearTimeout(timer);\n resolve();\n };\n const timer = setTimeout(() => {\n signal?.removeEventListener('abort', onAbort);\n resolve();\n }, ms);\n signal?.addEventListener('abort', onAbort, { once: true });\n });\n}\n\n/** Equal jitter: metade fixa + metade aleatória, evita thundering herd nos retries. */\nexport function jitter(baseMs: number): number {\n return Math.floor(baseMs / 2 + Math.random() * (baseMs / 2));\n}\n\nexport const TRUNCATION_SUFFIX = '… [truncado]';\n\nexport function truncate(value: string, max: number): string {\n return value.length > max ? `${value.slice(0, max)}${TRUNCATION_SUFFIX}` : value;\n}\n\n/**\n * Como `truncate`, mas o resultado (sufixo incluído) **cabe** em `max` — para os tetos do\n * servidor, onde um caractere a mais recusa o envelope inteiro.\n */\nexport function clip(value: string, max: number): string {\n if (value.length <= max) return value;\n return `${value.slice(0, Math.max(0, max - TRUNCATION_SUFFIX.length))}${TRUNCATION_SUFFIX}`;\n}\n\n/**\n * Converte qualquer valor para `string` sem lançar — usado nos pontos de entrada\n * de `hobots.*` que aceitam \"mensagem\" do usuário (log, attach, items, transaction)\n * e são documentados como \"nunca lança\": tipagem estática não impede alguém de\n * passar um `number`, um `Error` ou um objeto onde o contrato pede `string`.\n */\nexport function safeString(value: unknown): string {\n if (typeof value === 'string') return value;\n try {\n const json = JSON.stringify(value);\n if (json && json !== '{}') return json;\n } catch {\n // objetos circulares etc. caem no String()\n }\n return String(value);\n}\n\nexport const DEFAULT_RETRY_DELAYS_MS: readonly number[] = [1_000, 4_000, 16_000];\n\n/**\n * Executa `send` com retry em falha de rede/5xx/429 (respeitando Retry-After + jitter).\n * Devolve a Response tanto em ok quanto em 4xx≠429 — a rejeição definitiva é decisão\n * do chamador (o transport descarta logando; a API de tasks lança erro tipado).\n * Lança o último erro quando o ladder de retries esgota.\n */\nexport async function fetchWithRetry(\n send: () => Promise<Response>,\n options: {\n delays?: readonly number[];\n logger: Logger;\n label: string;\n /**\n * Códigos que normalmente seriam retriáveis mas que neste endpoint são PERMANENTES —\n * devolvidos como Response, sem insistir (anexos: 503 = instalação sem S3, 429 = cota\n * da execução; itens: 429 = cap por run). Insistir só faria o handler esperar a ladder.\n */\n noRetryStatuses?: readonly number[];\n /**\n * Cancelamento (ex.: `ctx.signal` da run): depois que dispara, a falha atual sobe na\n * hora — sem esperar o resto da ladder — e a espera entre tentativas é interrompida\n * sem disparar nova tentativa.\n */\n signal?: AbortSignal;\n }\n): Promise<Response> {\n const delays = options.delays ?? DEFAULT_RETRY_DELAYS_MS;\n const noRetry = options.noRetryStatuses ?? [];\n for (let attempt = 0; ; attempt++) {\n let retriable: unknown;\n let serverDelay: number | undefined;\n try {\n const response = await send();\n if (response.ok) return response;\n if (response.status >= 400 && response.status < 500 && response.status !== 429) return response;\n if (noRetry.includes(response.status)) return response;\n if (response.status === 429) serverDelay = retryAfterMs(response);\n retriable = new Error(`HTTP ${response.status}`);\n } catch (error) {\n retriable = error;\n }\n const failure = retriable instanceof Error ? retriable : new Error(String(retriable));\n const base = delays[attempt];\n if (base === undefined || options.signal?.aborted) throw failure;\n const delay = serverDelay ?? jitter(base);\n options.logger.warn(`${options.label}: falha (${String(retriable)}), retry em ${delay}ms`);\n await (options.signal ? abortableSleep(delay, options.signal) : sleep(delay));\n // abortado durante a espera: a falha atual sobe sem gastar mais uma requisição\n if (options.signal?.aborted) throw failure;\n }\n}\n\nconst MAX_RETRY_AFTER_MS = 60_000;\n\n/** Parse do header Retry-After (segundos ou HTTP-date), clampado a [0, 60s]. */\nexport function retryAfterMs(response: Response): number | undefined {\n const header = response.headers.get('retry-after');\n if (!header) return undefined;\n const seconds = Number(header);\n if (Number.isFinite(seconds)) {\n return Math.min(MAX_RETRY_AFTER_MS, Math.max(0, seconds * 1_000));\n }\n const date = Date.parse(header);\n if (Number.isNaN(date)) return undefined;\n return Math.min(MAX_RETRY_AFTER_MS, Math.max(0, date - Date.now()));\n}\n\n/**\n * Signal com timeout composável com um signal externo (stop/cancelamento).\n * Node 18 não tem AbortSignal.any — composição manual; chame cleanup() em finally\n * para não acumular listeners num signal externo reutilizado.\n */\nexport function withTimeoutSignal(timeoutMs: number, external?: AbortSignal): { signal: AbortSignal; cleanup: () => void } {\n const controller = new AbortController();\n const onAbort = (): void => controller.abort(external?.reason);\n if (external?.aborted) {\n onAbort();\n } else {\n external?.addEventListener('abort', onAbort, { once: true });\n }\n const timer = setTimeout(() => {\n controller.abort(Object.assign(new Error(`timeout após ${timeoutMs}ms`), { name: 'TimeoutError' }));\n }, timeoutMs);\n unrefTimer(timer);\n return {\n signal: controller.signal,\n cleanup: () => {\n clearTimeout(timer);\n external?.removeEventListener('abort', onAbort);\n },\n };\n}\n\nexport interface Logger {\n debug: (...args: unknown[]) => void;\n warn: (...args: unknown[]) => void;\n error: (...args: unknown[]) => void;\n}\n\nconst PREFIX = '[hobots]';\n\nexport function makeLogger(enabled: boolean, prefix: string = PREFIX): Logger {\n return {\n debug: (...args) => enabled && console.debug(colorize(prefix, 'gray'), ...args),\n warn: (...args) => enabled && console.warn(colorize(prefix, 'yellow'), ...args),\n error: (...args) => console.error(colorize(prefix, 'red'), ...args),\n };\n}\n\nconst ANSI = {\n reset: '\\x1b[0m',\n gray: '\\x1b[90m',\n cyan: '\\x1b[36m',\n yellow: '\\x1b[33m',\n red: '\\x1b[31m',\n green: '\\x1b[32m',\n} as const;\n\nfunction colorEnabled(): boolean {\n /* v8 ignore start -- ramo de browser: a suíte roda em Node e o isNode() interno não é mockável daqui */\n if (!isNode()) return false;\n /* v8 ignore stop */\n return Boolean(process.stdout?.isTTY) && !process.env.NO_COLOR;\n}\n\n/** Envolve `text` em código ANSI — vira no-op fora de um TTY Node (ou com NO_COLOR definido). */\nexport function colorize(text: string, color: keyof typeof ANSI): string {\n if (!colorEnabled()) return text;\n return `${ANSI[color]}${text}${ANSI.reset}`;\n}\n","import type { EnvironmentInput } from './environment-protocol';\nimport { isNode } from './utils';\n\nexport const INSTANCE_ID_ENV = 'HOBOTS_INSTANCE_ID';\nexport const ENVIRONMENT_ENV = 'HOBOTS_ENVIRONMENT';\nexport const RUN_ID_ENV = 'HOBOTS_RUN_ID';\n/** Modo local (teste sem a Central): `HOBOTS_LOCAL_RUN=1` — handler uma vez, sem rede, params de `HOBOTS_RUN_PARAMS`. */\nexport const LOCAL_RUN_ENV = 'HOBOTS_LOCAL_RUN';\n/** Params da execução no modo local: um objeto JSON (ausente/vazio = `{}`). */\nexport const RUN_PARAMS_ENV = 'HOBOTS_RUN_PARAMS';\n\nlet dotenvLoaded = false;\n\n/**\n * Carrega o `.env` da pasta de trabalho (`process.cwd()`) em `process.env`, uma vez por\n * processo: o bot não precisa de `dotenv` nem de `--env-file` para o SDK (e o próprio\n * código do bot) acharem `HOBOTS_CLIENT_SECRET` & cia. Usa o parser nativo do Node\n * (`process.loadEnvFile`, Node ≥ 20.12) — síncrono, porque `register()`/`start()` resolvem\n * as credenciais na hora. A env já definida no ambiente **vence** o arquivo. Sem `.env`\n * (ou em runtime sem `loadEnvFile`), não faz nada; erro de leitura vira um aviso que cita\n * só o código do erro, nunca o conteúdo do arquivo.\n */\nexport function loadDotenv(): void {\n if (dotenvLoaded) return;\n dotenvLoaded = true;\n if (!isNode() || typeof process.loadEnvFile !== 'function') return;\n try {\n process.loadEnvFile('.env');\n } catch (err) {\n const code = (err as { code?: unknown } | null)?.code;\n if (code === 'ENOENT') return;\n console.warn(`[hobots] não foi possível ler o .env da pasta de trabalho (${typeof code === 'string' ? code : 'erro desconhecido'}) — seguindo só com as variáveis do ambiente`);\n }\n}\n\n/** Só para testes: permite carregar o `.env` de novo. */\nexport function _resetDotenvForTesting(): void {\n dotenvLoaded = false;\n}\n\n/** instanceId da opção ou da env — sem os dois, `undefined` (o fallback é o hostname, assíncrono). */\nexport function resolveInstanceId(option: string | undefined): string | undefined {\n const fromOption = option?.trim();\n if (fromOption) return fromOption;\n if (typeof process === 'undefined' || !process.env) return undefined;\n return process.env[INSTANCE_ID_ENV]?.trim() || undefined;\n}\n\n/**\n * Run a que o register() se anexa (opção → env HOBOTS_RUN_ID). Sem as duas, `undefined`:\n * o agente segue no poll de sempre.\n */\nexport function resolveRunId(option: string | undefined): string | undefined {\n const fromOption = option?.trim();\n if (fromOption) return fromOption;\n if (typeof process === 'undefined' || !process.env) return undefined;\n return process.env[RUN_ID_ENV]?.trim() || undefined;\n}\n\n/** Modo local ligado (`HOBOTS_LOCAL_RUN=1`): sem Central, sem secret, sem rede. */\nexport function isLocalRun(): boolean {\n if (typeof process === 'undefined' || !process.env) return false;\n return process.env[LOCAL_RUN_ENV]?.trim() === '1';\n}\n\n/**\n * Params do modo local: JSON de `HOBOTS_RUN_PARAMS` (ausente ou vazio = `{}`). Lança com o\n * motivo quando o valor não é um objeto JSON válido — quem chama imprime e encerra com código 2.\n */\nexport function resolveLocalRunParams(): Record<string, unknown> {\n const raw = process.env[RUN_PARAMS_ENV]?.trim();\n if (!raw) return {};\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch {\n throw new Error(`${RUN_PARAMS_ENV} inválido: não é JSON válido`);\n }\n if (parsed === null || typeof parsed !== 'object' || Array.isArray(parsed)) {\n throw new Error(`${RUN_PARAMS_ENV} inválido: esperado um objeto JSON`);\n }\n return parsed as Record<string, unknown>;\n}\n\n/** environment da opção ou da env — sem os dois, `undefined` (quem decide o default 'production' é o Client). */\nexport function resolveEnvironmentOption(option: EnvironmentInput | undefined): EnvironmentInput | undefined {\n const fromOption = option?.trim();\n if (fromOption) return fromOption;\n if (typeof process === 'undefined' || !process.env) return undefined;\n return process.env[ENVIRONMENT_ENV]?.trim() || undefined;\n}\n\n/**\n * Último recurso para a identidade da instância: o hostname da máquina. Import dinâmico\n * de node:os (o bundle é neutro); fora de Node, 'browser'.\n */\nexport async function fallbackInstanceId(): Promise<string> {\n if (!isNode()) return 'browser';\n try {\n const os = await import('node:os');\n return os.hostname() || 'unknown-host';\n } catch {\n return 'unknown-host';\n }\n}\n","import type { StackFrame } from './protocol';\n\nconst MAX_FRAMES = 50;\n/** Teto do servidor para `filename` (zod). */\nconst MAX_FILENAME_CHARS = 1_024;\n\n// \" at fn (file:1:2)\" | \" at file:1:2\" | \" at async fn (file:1:2)\"\nconst FRAME_RE = /^\\s*at\\s+(?:async\\s+)?(?:(.+?)\\s+\\()?(.+?)\\)?$/;\nconst LOCATION_RE = /^(.*?):(\\d+):(\\d+)$/;\n\nfunction isInApp(filename: string | undefined): boolean {\n if (!filename) return false;\n if (filename.startsWith('node:')) return false;\n if (filename.startsWith('internal/')) return false;\n if (filename.includes('node_modules')) return false;\n if (filename === '<anonymous>') return false;\n return true;\n}\n\n/** Converte um `error.stack` do V8 em frames (ordem innermost-first, como o V8 imprime). */\nexport function parseStacktrace(stack: string | undefined | null): StackFrame[] {\n if (!stack) return [];\n\n const frames: StackFrame[] = [];\n for (const line of stack.split('\\n')) {\n if (frames.length >= MAX_FRAMES) break;\n const match = FRAME_RE.exec(line);\n if (!match || !line.trimStart().startsWith('at ')) continue;\n\n const [, fn, location] = match;\n /* v8 ignore start -- o grupo 2 do FRAME_RE é obrigatório: `location` nunca é undefined após o match */\n const loc = LOCATION_RE.exec(location ?? '');\n /* v8 ignore stop */\n const filename = loc ? loc[1] : location;\n frames.push({\n function: fn || '<anonymous>',\n filename: filename ? filename.slice(0, MAX_FILENAME_CHARS) : undefined,\n lineno: loc?.[2] ? Number(loc[2]) : undefined,\n colno: loc?.[3] ? Number(loc[3]) : undefined,\n in_app: isInApp(filename),\n });\n }\n return frames;\n}\n","/**\n * Redação de segredos em texto que sai do processo (mensagens de erro, stacks,\n * logs de run). Padrões conservadores — falso positivo é preferível a vazar\n * uma credencial para o painel.\n */\nconst SECRET_PATTERNS: ReadonlyArray<readonly [RegExp, string]> = [\n // client secret da Hobots\n [/hb_[a-f0-9]{16,}/gi, '[REDACTED]'],\n // tokens bearer em headers/mensagens\n [/\\b(authorization:?\\s*)?bearer\\s+[a-z0-9._~+/=-]{8,}/gi, 'Bearer [REDACTED]'],\n // chaves no formato sk-… (OpenAI e afins)\n [/\\bsk-[a-z0-9_-]{16,}\\b/gi, '[REDACTED]'],\n // credenciais embutidas em URL (https://user:pass@host)\n [/\\/\\/[^/\\s:@]+:[^/\\s@]+@/g, '//[REDACTED]@'],\n];\n\nexport function scrubSecrets(text: string): string {\n let out = text;\n for (const [pattern, replacement] of SECRET_PATTERNS) {\n out = out.replace(pattern, replacement);\n }\n return out;\n}\n","import type { EventPayload, EventType } from './protocol';\nimport { parseStacktrace } from './stacktrace';\nimport { scrubSecrets } from './scrub';\nimport { nowISO, safeString, truncate, uuid4 } from './utils';\n\n/** Teto do servidor para `exception.value` (zod). */\nexport const MAX_EXCEPTION_VALUE_CHARS = 8_192;\n\nexport function eventFromException(error: unknown, type: EventType = 'error'): EventPayload {\n let exceptionType: string;\n let value: string;\n let frames = [] as ReturnType<typeof parseStacktrace>;\n\n if (error instanceof Error) {\n exceptionType = error.name || 'Error';\n value = truncate(scrubSecrets(error.message), MAX_EXCEPTION_VALUE_CHARS);\n frames = parseStacktrace(error.stack);\n } else {\n exceptionType = 'NonError';\n value = truncate(scrubSecrets(safeString(error)), MAX_EXCEPTION_VALUE_CHARS);\n }\n\n return {\n event_id: uuid4(),\n timestamp: nowISO(),\n type,\n exception: {\n type: exceptionType,\n value,\n ...(frames.length > 0 ? { stacktrace: { frames } } : {}),\n },\n };\n}\n","import type { Envelope, EnvelopeItem } from './protocol';\nimport { SDK_NAME, SDK_VERSION, fetchWithRetry, nowISO, sleep, unrefTimer, type Logger } from './utils';\nimport { WIRE_LIMITS } from './wire-limits';\n\nconst REQUEST_TIMEOUT_MS = 10_000;\nconst DEFAULT_FLUSH_INTERVAL_MS = 2_000;\nconst DEFAULT_MAX_BATCH_SIZE = 10;\nconst DEFAULT_MAX_QUEUE_SIZE = 200;\n/**\n * Teto de itens por envelope — espelha o `.max(50)` de `envelopeSchema.items`\n * (apps/api/lib/ingest/schemas.ts). Acima disso a API responde 422 e o envelope é\n * descartado sem retry, então a fila é fatiada em envelopes deste tamanho antes de enviar.\n * Ao mudar um dos dois lados, mude o outro.\n */\nconst MAX_ITEMS_PER_ENVELOPE = WIRE_LIMITS.MAX_ITEMS_PER_ENVELOPE;\n\nexport interface TransportOptions {\n endpoint: string;\n /** Chave secreta do agente — enviada como Authorization: Bearer */\n key: string;\n logger: Logger;\n flushIntervalMs?: number;\n maxBatchSize?: number;\n maxQueueSize?: number;\n}\n\n/** Fila em memória com batch + retry. Envia envelopes via fetch (Node 18+/browser). */\nexport class Transport {\n private readonly endpoint: string;\n private readonly key: string;\n private readonly logger: Logger;\n private readonly flushIntervalMs: number;\n private readonly maxBatchSize: number;\n private readonly maxQueueSize: number;\n\n private buffer: EnvelopeItem[] = [];\n private timer: ReturnType<typeof setTimeout> | undefined;\n private pending = new Set<Promise<void>>();\n private closed = false;\n\n constructor(options: TransportOptions) {\n this.endpoint = options.endpoint;\n this.key = options.key;\n this.logger = options.logger;\n this.flushIntervalMs = options.flushIntervalMs ?? DEFAULT_FLUSH_INTERVAL_MS;\n this.maxBatchSize = options.maxBatchSize ?? DEFAULT_MAX_BATCH_SIZE;\n this.maxQueueSize = options.maxQueueSize ?? DEFAULT_MAX_QUEUE_SIZE;\n }\n\n enqueue(item: EnvelopeItem): void {\n if (this.closed) {\n this.logger.warn('transport fechado, item descartado:', item.type);\n return;\n }\n if (this.buffer.length >= this.maxQueueSize) {\n // nunca descarta heartbeat: um burst de erros não pode derrubar a presença —\n // o servidor marcaria offline um agente vivo (e gritando)\n const dropIndex = this.buffer.findIndex(queued => queued.type !== 'heartbeat');\n this.buffer.splice(dropIndex === -1 ? 0 : dropIndex, 1);\n this.logger.warn('fila cheia, item mais antigo descartado');\n }\n this.buffer.push(item);\n\n if (this.buffer.length >= this.maxBatchSize) {\n void this.flushBuffer();\n } else {\n this.schedule();\n }\n }\n\n private schedule(): void {\n if (this.timer) return;\n this.timer = setTimeout(() => {\n this.timer = undefined;\n void this.flushBuffer();\n }, this.flushIntervalMs);\n unrefTimer(this.timer);\n }\n\n private flushBuffer(): Promise<void> {\n if (this.timer) {\n clearTimeout(this.timer);\n this.timer = undefined;\n }\n if (this.buffer.length === 0) return Promise.resolve();\n\n // maxBatchSize decide *quando* flushar, não quanto cabe num envelope: um burst de\n // captures (ou uma janela de rede ruim em que a fila cresceu até maxQueueSize) junta\n // mais itens do que a API aceita, então quebra em lotes de MAX_ITEMS_PER_ENVELOPE.\n const taken = this.buffer.splice(0, this.buffer.length);\n const sends: Promise<void>[] = [];\n for (let offset = 0; offset < taken.length; offset += MAX_ITEMS_PER_ENVELOPE) {\n sends.push(this.send(taken.slice(offset, offset + MAX_ITEMS_PER_ENVELOPE)));\n }\n return Promise.all(sends).then(() => undefined);\n }\n\n /** Registra o envio em `this.pending` para que `flush()` aguarde todos os envelopes. */\n private send(items: EnvelopeItem[]): Promise<void> {\n const envelope: Envelope = {\n sdk: { name: SDK_NAME, version: SDK_VERSION },\n sent_at: nowISO(),\n items,\n };\n\n const request: Promise<void> = this.sendWithRetry(envelope).finally(() => {\n this.pending.delete(request);\n });\n this.pending.add(request);\n return request;\n }\n\n private async sendWithRetry(envelope: Envelope): Promise<void> {\n let response: Response;\n try {\n response = await fetchWithRetry(\n () =>\n fetch(this.endpoint, {\n redirect: 'error',\n method: 'POST',\n headers: { 'content-type': 'application/json', authorization: `Bearer ${this.key}` },\n body: JSON.stringify(envelope),\n signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS),\n }),\n { logger: this.logger, label: 'envio de envelope' }\n );\n } catch (error) {\n this.logger.error('envelope descartado após retries:', error);\n return;\n }\n if (response.ok) {\n this.logger.debug(`envelope enviado (${envelope.items.length} itens)`);\n return;\n }\n // 4xx (exceto 429) não é recuperável — descarta sem retry\n this.logger.error(`envelope rejeitado (HTTP ${response.status}), descartado (${envelope.items.length} itens)`);\n }\n\n /** Envia o que estiver na fila e aguarda envios em andamento (até timeoutMs). */\n async flush(timeoutMs = 5_000): Promise<boolean> {\n void this.flushBuffer();\n const all = Promise.allSettled([...this.pending]).then(() => true);\n return Promise.race([all, sleep(timeoutMs).then(() => false)]);\n }\n\n async close(timeoutMs = 5_000): Promise<boolean> {\n const result = await this.flush(timeoutMs);\n this.closed = true;\n return result;\n }\n}\n","import type { EnvironmentInput, EventPayload, HeartbeatPayload, StepData, TransactionPayload } from './protocol';\nimport type { CaptureHint } from './types';\nimport type { ResolvedConfig } from './config';\nimport { eventFromException } from './eventbuilder';\nimport type { MachineSampler } from './machine';\nimport { Transport } from './transport';\nimport { SDK_NAME, SDK_VERSION, clip, isNode, makeLogger, truncate, type Logger } from './utils';\n\n// Limites do servidor (zod). Um único campo acima do limite devolve 422 para o\n// envelope INTEIRO — que pode carregar até 50 itens. Vale truncar no cliente.\nexport const MAX_TAG_VALUE_CHARS = 512;\nexport const MAX_FINGERPRINT_ITEMS = 10;\nexport const MAX_FINGERPRINT_ITEM_CHARS = 255;\nexport const MAX_TRANSACTION_NAME_CHARS = 500;\nexport const MAX_STEPS = 200;\n/** Teto do nome da etapa (`description`) — acima disso o envelope inteiro era recusado. */\nexport const MAX_STEP_DESCRIPTION_CHARS = 2_048;\n/** Teto do `op` de uma etapa. */\nexport const MAX_STEP_OP_CHARS = 255;\n\nfunction clipTags(tags: Record<string, string>): Record<string, string> {\n return Object.fromEntries(Object.entries(tags).map(([key, value]) => [key, truncate(String(value), MAX_TAG_VALUE_CHARS)]));\n}\n\n/** Tetos do servidor por etapa: uma etapa com nome maior fazia o envelope inteiro ser recusado (422). */\nfunction clipStep(step: StepData): StepData {\n return {\n ...step,\n ...(step.op ? { op: clip(step.op, MAX_STEP_OP_CHARS) } : {}),\n ...(step.description ? { description: clip(step.description, MAX_STEP_DESCRIPTION_CHARS) } : {}),\n };\n}\n\nfunction clipFingerprint(fingerprint: string[] | undefined): string[] | undefined {\n if (fingerprint === undefined) return undefined;\n return fingerprint.slice(0, MAX_FINGERPRINT_ITEMS).map(item => truncate(String(item), MAX_FINGERPRINT_ITEM_CHARS));\n}\n\n/** Opções de telemetria resolvidas pelo runtime a partir do primeiro register()/start(). */\nexport interface ClientOptions {\n environment?: EnvironmentInput;\n release?: string;\n /** Tags aplicadas a todos os eventos e transactions */\n tags?: Record<string, string>;\n debug?: boolean;\n /**\n * O erro final que escapou do handler de uma run também vira issue (além de falhar a run).\n * Ligado pelo runtime junto com `captureUnhandled`; desligado no client cru (testes).\n */\n captureRunErrors?: boolean;\n /** Knobs internos do transport (testes) — não fazem parte da API pública */\n flushIntervalMs?: number;\n maxBatchSize?: number;\n}\n\n// erros já enviados como issue: o runner não reenvia o que o bot capturou e relançou\nconst captured = new WeakSet<object>();\n\n/** O erro já foi enviado por captureException (só objetos são marcáveis). */\nexport function wasCaptured(error: unknown): boolean {\n return typeof error === 'object' && error !== null && captured.has(error);\n}\n\nfunction runtimeContexts(): Record<string, Record<string, unknown>> {\n if (isNode()) {\n return {\n runtime: { name: 'node', version: process.version },\n os: { name: process.platform, arch: process.arch },\n };\n }\n return { runtime: { name: 'browser' } };\n}\n\nexport class Client {\n readonly logger: Logger;\n /** Eco de lifecycle (Transaction.emit) e afins só imprimem no terminal com debug ligado. */\n readonly debug: boolean;\n // campos privados + getters de protótipo: o clientSecret não aparece em\n // JSON.stringify/serialização enumerável do Client (ex.: um objeto capturado\n // que referencie o client), mas client.options/config seguem funcionando\n readonly #options: ClientOptions;\n readonly #config: ResolvedConfig;\n private readonly transport: Transport;\n private machine: MachineSampler | undefined;\n\n constructor(options: ClientOptions, config: ResolvedConfig) {\n this.#options = options;\n this.debug = !!options.debug;\n this.logger = makeLogger(this.debug);\n this.#config = config;\n this.transport = new Transport({\n endpoint: this.#config.ingestEndpoint,\n key: this.#config.key,\n logger: this.logger,\n flushIntervalMs: options.flushIntervalMs,\n maxBatchSize: options.maxBatchSize,\n });\n }\n\n get options(): ClientOptions {\n return this.#options;\n }\n\n get config(): ResolvedConfig {\n return this.#config;\n }\n\n /** Sampler de recursos da máquina — cada evento passa a levar `contexts.machine`. */\n attachMachineSampler(sampler: MachineSampler | undefined): void {\n this.machine = sampler;\n }\n\n /** Serialização explícita nunca inclui o secret. */\n toJSON(): Record<string, unknown> {\n return { sdk: SDK_NAME, version: SDK_VERSION, baseUrl: this.#config.baseUrl };\n }\n\n [Symbol.for('nodejs.util.inspect.custom')](): string {\n return `Client { baseUrl: '${this.#config.baseUrl}' }`;\n }\n\n /** `contexts` é interno ao SDK (ex.: `contexts.run` com o print do captureException) — o evento ainda pode sobrescrever. */\n captureException(error: unknown, hint?: CaptureHint, contexts?: Record<string, Record<string, unknown>>): string {\n if (typeof error === 'object' && error !== null) captured.add(error);\n return this.captureEvent(eventFromException(error, hint?.type ?? 'error'), hint, contexts);\n }\n\n captureEvent(event: EventPayload, hint?: CaptureHint, contexts?: Record<string, Record<string, unknown>>): string {\n const final = this.prepareEvent(contexts ? { ...event, contexts: { ...contexts, ...event.contexts } } : event, hint);\n this.transport.enqueue({ type: 'event', payload: final });\n return final.event_id;\n }\n\n private prepareEvent(event: EventPayload, hint: CaptureHint | undefined): EventPayload {\n const tags = { ...this.options.tags, ...event.tags, ...hint?.tags };\n const extra = { ...event.extra, ...hint?.extra };\n // como estava a máquina no momento do erro — o evento ainda pode sobrescrever.\n // `contexts` é Record<string, Record<string, unknown>>; o snapshot tipado entra como tal.\n const sampled = this.machine?.sample();\n const machine: Record<string, Record<string, unknown>> = sampled ? { machine: sampled as unknown as Record<string, unknown> } : {};\n\n return {\n ...event,\n type: hint?.type ?? event.type ?? 'error',\n release: event.release ?? this.options.release,\n environment: this.resolveEnvironment(event.environment),\n tags: Object.keys(tags).length > 0 ? clipTags(tags) : undefined,\n extra: Object.keys(extra).length > 0 ? extra : undefined,\n contexts: { ...runtimeContexts(), ...machine, ...event.contexts },\n fingerprint: clipFingerprint(hint?.fingerprint ?? event.fingerprint),\n };\n }\n\n sendTransaction(payload: TransactionPayload): void {\n let steps = payload.steps;\n if (steps.length > MAX_STEPS) {\n this.logger.warn(`transaction com ${steps.length} etapas — enviando as primeiras ${MAX_STEPS}`);\n steps = steps.slice(0, MAX_STEPS);\n }\n steps = steps.map(clipStep);\n this.transport.enqueue({\n type: 'transaction',\n payload: {\n ...payload,\n name: clip(payload.name || '(sem nome)', MAX_TRANSACTION_NAME_CHARS),\n steps,\n release: payload.release ?? this.options.release,\n environment: this.resolveEnvironment(payload.environment),\n tags: clipTags({ ...this.options.tags, ...payload.tags }),\n },\n });\n }\n\n sendHeartbeat(payload: HeartbeatPayload): void {\n this.transport.enqueue({\n type: 'heartbeat',\n payload: {\n ...payload,\n release: payload.release ?? this.options.release,\n // o ambiente viaja no beat: é assim que a instância se classifica no app\n environment: this.resolveEnvironment(payload.environment),\n },\n });\n }\n\n /**\n * Ambiente do item: o dele, senão o das opções, senão produção. Centralizado\n * porque evento, transaction e heartbeat precisam responder igual — o servidor\n * normaliza apelidos legados, então aqui basta repassar.\n */\n private resolveEnvironment(value: EnvironmentInput | undefined): EnvironmentInput {\n return value ?? this.options.environment ?? 'production';\n }\n\n flush(timeoutMs?: number): Promise<boolean> {\n return this.transport.flush(timeoutMs);\n }\n\n close(timeoutMs?: number): Promise<boolean> {\n return this.transport.close(timeoutMs);\n }\n}\n","/** API oficial da Hobots — o SDK sempre fala com ela em produção. */\nexport const DEFAULT_BASE_URL = 'https://api2.hobots.app';\n\nexport interface ResolvedConfig {\n /** Client Secret do agente (enviado como Authorization: Bearer, nunca na URL) */\n key: string;\n baseUrl: string;\n /** Ingestão de telemetria: <baseUrl>/v1/ingest */\n ingestEndpoint: string;\n /** API de execuções (poll, runs, itens, anexos): <baseUrl>/v1/runs */\n runsBaseUrl: string;\n}\n\ninterface ConfigInput {\n /** Ausente: lê a env HOBOTS_CLIENT_SECRET (como as libs da AWS fazem com as credenciais). */\n clientSecret?: string;\n}\n\nexport const CLIENT_SECRET_ENV = 'HOBOTS_CLIENT_SECRET';\n\nfunction envClientSecret(): string | undefined {\n if (typeof process === 'undefined' || !process.env) return undefined;\n return process.env[CLIENT_SECRET_ENV]?.trim() || undefined;\n}\n\n/** hb_<64 hex>. */\nconst SECRET_PATTERN = /^hb_[a-f0-9]{64}$/i;\n\n/**\n * Override de desenvolvimento via env HOBOTS_API_URL — a única forma de apontar\n * o SDK para outro host. Em produção a URL é sempre a API oficial.\n */\nfunction envBaseUrl(): string | undefined {\n // browser: `process` pode não existir\n if (typeof process === 'undefined' || !process.env) return undefined;\n return process.env.HOBOTS_API_URL?.trim() || undefined;\n}\n\nfunction isLoopbackHost(hostname: string): boolean {\n return (\n hostname === 'localhost' ||\n hostname.endsWith('.localhost') ||\n hostname.startsWith('127.') ||\n hostname === '[::1]' ||\n hostname === '::1' ||\n hostname === '0.0.0.0'\n );\n}\n\n/**\n * Valida a baseUrl sem nunca ecoar o valor completo em erro/log — a env pode\n * conter credenciais embutidas por engano.\n */\nfunction validateBaseUrl(raw: string, prefix: string): string {\n let url: URL;\n try {\n url = new URL(raw);\n } catch {\n throw new Error(`${prefix} HOBOTS_API_URL inválida — esperado URL http(s), ex.: http://localhost:3001`);\n }\n if (url.protocol !== 'http:' && url.protocol !== 'https:') {\n throw new Error(`${prefix} HOBOTS_API_URL com esquema \"${url.protocol}\" não suportado — use http(s)`);\n }\n if (url.username || url.password) {\n throw new Error(`${prefix} HOBOTS_API_URL não pode conter credenciais na URL — a autenticação é só pelo Client Secret`);\n }\n // http só em loopback: para um host remoto o Client Secret iria em claro na rede — recusa, não avisa\n if (url.protocol === 'http:' && !isLoopbackHost(url.hostname)) {\n throw new Error(`${prefix} HOBOTS_API_URL usa http para o host remoto \"${url.hostname}\" — o Client Secret trafegaria sem TLS; use https`);\n }\n return raw.replace(/\\/+$/, '');\n}\n\n/** Resolve o clientSecret (opção ou env) nos endpoints de telemetria e de execuções. */\nexport function resolveConfig(options: ConfigInput = {}, prefix = '[hobots]'): ResolvedConfig {\n const fromOption = options.clientSecret?.trim();\n const key = fromOption || envClientSecret();\n const origin = fromOption ? 'clientSecret' : `env ${CLIENT_SECRET_ENV}`;\n if (!key) {\n throw new Error(\n `${prefix} Client Secret ausente — defina a env ${CLIENT_SECRET_ENV} (ou passe clientSecret nas opções do register/start); copie o Client Secret na Central: abra o agente → Configurações → agente → aba credenciais`\n );\n }\n if (!SECRET_PATTERN.test(key)) {\n // nunca incluir o valor na mensagem — só o tamanho e a origem, como pista de diagnóstico\n throw new Error(\n `${prefix} ${origin} com formato inválido (${key.length} caracteres) — esperado \"hb_\" + 64 hex; copie o Client Secret na Central: abra o agente → Configurações → agente → aba credenciais`\n );\n }\n\n const baseUrl = validateBaseUrl(envBaseUrl() ?? DEFAULT_BASE_URL, prefix);\n\n return {\n key,\n baseUrl,\n ingestEndpoint: `${baseUrl}/v1/ingest`,\n runsBaseUrl: `${baseUrl}/v1/runs`,\n };\n}\n","import type { Client } from './client';\nimport type { MachineSampler } from './machine';\nimport { nowISO, unrefTimer } from './utils';\nimport { WIRE_LIMITS } from './wire-limits';\n\nconst DEFAULT_INTERVAL_MS = WIRE_LIMITS.HEARTBEAT_DEFAULT_INTERVAL_MS;\n// faixa aceita pelo servidor para interval_ms (WIRE_LIMITS; a api aplica a mesma) — o valor\n// REPORTADO é clampado para o envelope não ser rejeitado; a cadência real fica como configurada.\n// Janelas maiores que 15 min são caso para o timeout de presença do agente, no app.\nconst MIN_REPORTED_INTERVAL_MS = WIRE_LIMITS.HEARTBEAT_MIN_INTERVAL_MS;\nconst MAX_REPORTED_INTERVAL_MS = WIRE_LIMITS.HEARTBEAT_MAX_INTERVAL_MS;\n\nexport interface HeartbeatOptions {\n /** Intervalo entre batimentos. Default: 30_000 */\n intervalMs?: number;\n /** Nome amigável exibido no dashboard. Default: o instanceId */\n name?: string;\n metadata?: Record<string, unknown>;\n /**\n * Timer ref'd: o heartbeat segura o processo vivo até stop(). É o que mantém um bot\n * no modo start rodando depois que o handler retorna — \"o SDK fica sempre vivo\".\n * Default: false (unref'd — não segura o processo).\n */\n keepAlive?: boolean;\n}\n\n/** Batimento periódico \"estou vivo\" — o servidor marca a instância offline quando ele para. */\nexport class Heartbeat {\n private readonly intervalMs: number;\n private readonly instanceId: string;\n private readonly name: string;\n private readonly metadata?: Record<string, unknown>;\n private readonly keepAlive: boolean;\n private timer: ReturnType<typeof setTimeout> | undefined;\n\n constructor(\n private readonly client: Client,\n options: HeartbeatOptions = {},\n instanceId: string,\n private readonly sampler?: MachineSampler\n ) {\n this.intervalMs = options.intervalMs ?? DEFAULT_INTERVAL_MS;\n this.instanceId = instanceId;\n this.name = options.name ?? instanceId;\n this.metadata = options.metadata;\n this.keepAlive = options.keepAlive ?? false;\n }\n\n start(): void {\n if (this.timer) return;\n this.beat();\n this.schedule();\n }\n\n /** Jitter de ±10%: uma frota iniciada junto não sincroniza todos os beats no mesmo segundo. */\n private schedule(): void {\n this.timer = setTimeout(\n () => {\n this.beat();\n this.schedule();\n },\n this.intervalMs * (0.9 + Math.random() * 0.2)\n );\n if (!this.keepAlive) unrefTimer(this.timer);\n }\n\n stop(): void {\n if (this.timer) {\n clearTimeout(this.timer);\n this.timer = undefined;\n }\n }\n\n private beat(): void {\n this.client.sendHeartbeat({\n instance_id: this.instanceId,\n name: this.name,\n interval_ms: Math.min(Math.max(this.intervalMs, MIN_REPORTED_INTERVAL_MS), MAX_REPORTED_INTERVAL_MS),\n timestamp: nowISO(),\n metadata: this.metadata,\n // recursos da máquina a cada beat — a série da instância no app\n machine: this.sampler?.sample(),\n });\n }\n}\n","import { sleep } from './utils';\n\n/**\n * Coordenação entre os handlers de processo do SDK (instrument + tasks/shutdown):\n * marca os listeners internos para que a checagem de \"o programa tem handler próprio?\"\n * não conte os nossos, e agrega os reportes de emergência que o exit precisa aguardar.\n */\nconst INTERNAL = Symbol.for('hobots.sdk.internalListener');\n\ntype Marked = { [INTERNAL]?: true };\n\nexport function markInternal<T extends (...args: never[]) => unknown>(listener: T): T {\n (listener as Marked)[INTERNAL] = true;\n return listener;\n}\n\n/** Listeners do programa (não-SDK) para o evento — decide se o SDK preserva o exit default. */\nexport function externalListenerCount(event: string): number {\n const listeners = process.listeners(event as 'uncaughtException');\n return listeners.filter(listener => !(listener as Marked)[INTERNAL]).length;\n}\n\nconst emergencyTasks: Promise<unknown>[] = [];\n\n/** Reporte best-effort em voo (ex: run → AgentTerminated) que um exit iminente deve aguardar. */\nexport function addEmergencyTask(task: Promise<unknown>): void {\n emergencyTasks.push(task);\n // sai da lista ao resolver/rejeitar: um processo longo não acumula promises já encerradas\n const forget = (): void => {\n const index = emergencyTasks.indexOf(task);\n /* v8 ignore start -- defensivo: cada push tem exatamente um forget, a tarefa sempre está na lista */\n if (index !== -1) emergencyTasks.splice(index, 1);\n /* v8 ignore stop */\n };\n task.then(forget, forget);\n}\n\n/** Apenas para testes: quantas tarefas ainda estão pendentes. */\nexport function _pendingEmergencyTasksForTesting(): number {\n return emergencyTasks.length;\n}\n\nexport async function awaitEmergencyTasks(capMs: number): Promise<void> {\n if (emergencyTasks.length === 0) return;\n await Promise.race([Promise.allSettled(emergencyTasks), sleep(capMs)]);\n}\n","import type { Client } from './client';\nimport { awaitEmergencyTasks, externalListenerCount, markInternal } from './internal-handlers';\nimport { isNode } from './utils';\n\nconst EMERGENCY_REPORT_CAP_MS = 3_000;\n\nlet installed = false;\n\n/** O tasks/shutdown consulta para saber se o exit de uncaughtException já tem dono. */\nexport function hasInstalledGlobalHandlers(): boolean {\n return installed;\n}\n\n/**\n * Registra handlers globais de erro e devolve a função que os remove.\n * Node: preserva a semântica padrão — após capturar e flushar um uncaughtException,\n * o processo encerra com código 1 (a menos que o programa tenha handler próprio).\n */\nexport function installGlobalHandlers(client: Client): () => void {\n if (installed) return () => undefined;\n installed = true;\n\n if (isNode()) {\n const onUncaught = markInternal((error: Error) => {\n client.captureException(error, { type: 'fatal', tags: { mechanism: 'uncaughtException' } });\n void client.flush(2_000).then(async () => {\n // conta só handlers do programa — os do próprio SDK (este e o de tasks) não\n // impedem o exit default\n if (externalListenerCount('uncaughtException') === 0) {\n // aguarda o reporte de emergência do agente de tasks (runs → AgentTerminated), se houver\n await awaitEmergencyTasks(EMERGENCY_REPORT_CAP_MS);\n console.error(error);\n process.exit(1);\n }\n });\n });\n\n const onRejection = markInternal((reason: unknown) => {\n client.captureException(reason, { type: 'error', tags: { mechanism: 'unhandledRejection' } });\n // fetch em andamento segura o processo aberto até o envio terminar\n void client.flush(2_000);\n });\n\n // rede de segurança: envia o que restou na fila quando o event loop esvazia\n const onBeforeExit = markInternal(() => {\n void client.flush(2_000);\n });\n\n process.on('uncaughtException', onUncaught);\n process.on('unhandledRejection', onRejection);\n process.on('beforeExit', onBeforeExit);\n\n return () => {\n process.off('uncaughtException', onUncaught);\n process.off('unhandledRejection', onRejection);\n process.off('beforeExit', onBeforeExit);\n installed = false;\n };\n }\n\n if (typeof window !== 'undefined') {\n const onError = (event: ErrorEvent): void => {\n client.captureException(event.error ?? event.message, { tags: { mechanism: 'onerror' } });\n };\n const onRejection = (event: PromiseRejectionEvent): void => {\n client.captureException(event.reason, { tags: { mechanism: 'onunhandledrejection' } });\n };\n const onPageHide = (): void => {\n void client.flush(1_000);\n };\n window.addEventListener('error', onError);\n window.addEventListener('unhandledrejection', onRejection);\n window.addEventListener('pagehide', onPageHide);\n\n return () => {\n window.removeEventListener('error', onError);\n window.removeEventListener('unhandledrejection', onRejection);\n window.removeEventListener('pagehide', onPageHide);\n installed = false;\n };\n }\n\n return () => {\n installed = false;\n };\n}\n\n/** Apenas para testes internos. */\nexport function resetGlobalHandlersForTesting(): void {\n installed = false;\n}\n","import type { MachineSnapshot } from './machine-protocol';\nimport { isNode, nowISO, type Logger } from './utils';\n\ntype OsModule = typeof import('node:os');\n/** `fs.statfsSync` só existe a partir do Node 18.15 — tipado à parte para não depender da versão dos @types. */\ntype StatFs = { bsize: number; blocks: number; bavail: number };\ntype FsModule = { statfsSync?: (path: string) => StatFs };\n\n/** Janela mínima entre duas leituras de CPU: abaixo disso o delta é ruído e reutilizamos a última média. */\nconst MIN_CPU_WINDOW_MS = 1_000;\n\ninterface CpuTotals {\n busy: number;\n total: number;\n}\n\nconst round1 = (value: number): number => Math.round(value * 10) / 10;\nconst clampPercent = (value: number): number => Math.min(100, Math.max(0, value));\n\n/**\n * Coleta CPU/memória/disco da máquina e do processo — só em Node (no browser é no-op).\n *\n * Os módulos `node:*` entram por import dinâmico (o bundle é `platform: neutral`), e\n * `sample()` é síncrono e barato: `os.cpus()` + `statfsSync` + `process.memoryUsage()`.\n * Nunca lança — telemetria de recurso não pode derrubar o bot nem o capture de um erro.\n */\nexport class MachineSampler {\n private os: OsModule | undefined;\n private fs: FsModule | undefined;\n private ready = false;\n\n private prevCpu: CpuTotals | undefined;\n private prevProcessCpu: NodeJS.CpuUsage | undefined;\n private prevAt = 0;\n private lastCpuPercent: number | null = null;\n private lastProcessCpuPercent: number | null = null;\n\n constructor(\n private readonly instanceId: string,\n private readonly logger: Logger\n ) {}\n\n /** Carrega os módulos e tira a leitura-base de CPU (a primeira amostra ainda sai com cpu_percent null). */\n async start(): Promise<void> {\n if (!isNode()) return;\n try {\n this.os = await import('node:os');\n this.fs = (await import('node:fs')) as unknown as FsModule;\n this.prevCpu = this.cpuTotals();\n this.prevProcessCpu = process.cpuUsage();\n this.prevAt = Date.now();\n this.ready = true;\n } catch (error) {\n this.logger.debug('métricas de máquina indisponíveis neste runtime', error);\n }\n }\n\n sample(): MachineSnapshot | undefined {\n if (!this.ready || !this.os) return undefined;\n try {\n const os = this.os;\n const cpuCount = Math.max(1, os.cpus().length);\n this.updateCpu(cpuCount);\n\n const snapshot: MachineSnapshot = {\n sampled_at: nowISO(),\n instance_id: this.instanceId,\n hostname: os.hostname(),\n os: process.platform,\n arch: process.arch,\n cpu_count: cpuCount,\n cpu_percent: this.lastCpuPercent,\n process: {\n pid: process.pid,\n uptime_s: Math.round(process.uptime()),\n cpu_percent: this.lastProcessCpuPercent,\n },\n source: 'stdlib',\n };\n\n // load average só faz sentido em POSIX — no Windows o Node devolve [0,0,0]\n if (process.platform !== 'win32') {\n const load = os.loadavg()[0];\n if (typeof load === 'number' && Number.isFinite(load)) snapshot.load_1 = round1(load);\n }\n\n const memTotal = os.totalmem();\n const memFree = os.freemem();\n if (memTotal > 0) {\n snapshot.mem_total_bytes = memTotal;\n snapshot.mem_available_bytes = memFree;\n snapshot.mem_percent = round1(clampPercent(((memTotal - memFree) / memTotal) * 100));\n }\n\n const disk = this.diskUsage();\n if (disk) Object.assign(snapshot, disk);\n\n const mem = process.memoryUsage();\n snapshot.process.rss_bytes = mem.rss;\n snapshot.process.heap_used_bytes = mem.heapUsed;\n\n return snapshot;\n } catch (error) {\n this.logger.debug('falha ao coletar métricas de máquina', error);\n return undefined;\n }\n }\n\n private cpuTotals(): CpuTotals {\n let busy = 0;\n let total = 0;\n for (const cpu of this.os!.cpus()) {\n const t = cpu.times;\n const cpuBusy = t.user + t.nice + t.sys + t.irq;\n busy += cpuBusy;\n total += cpuBusy + t.idle;\n }\n return { busy, total };\n }\n\n /** Média desde a leitura anterior; leituras com menos de 1s de janela reutilizam a última média. */\n private updateCpu(cpuCount: number): void {\n const now = Date.now();\n const elapsedMs = now - this.prevAt;\n if (elapsedMs < MIN_CPU_WINDOW_MS) return;\n\n const cpu = this.cpuTotals();\n if (this.prevCpu) {\n const total = cpu.total - this.prevCpu.total;\n if (total > 0) this.lastCpuPercent = round1(clampPercent(((cpu.busy - this.prevCpu.busy) / total) * 100));\n }\n this.prevCpu = cpu;\n\n const usage = process.cpuUsage(this.prevProcessCpu);\n const usedMicros = usage.user + usage.system;\n this.lastProcessCpuPercent = round1(clampPercent((usedMicros / (elapsedMs * 1_000 * cpuCount)) * 100));\n this.prevProcessCpu = process.cpuUsage();\n this.prevAt = now;\n }\n\n private diskUsage(): Pick<MachineSnapshot, 'disk_path' | 'disk_total_bytes' | 'disk_free_bytes' | 'disk_percent'> | undefined {\n const statfs = this.fs?.statfsSync;\n if (typeof statfs !== 'function') return undefined;\n try {\n const path = process.cwd();\n const stat = statfs(path);\n const total = stat.bsize * stat.blocks;\n const free = stat.bsize * stat.bavail;\n if (total <= 0) return undefined;\n return {\n disk_path: path,\n disk_total_bytes: total,\n disk_free_bytes: free,\n disk_percent: round1(clampPercent(((total - free) / total) * 100)),\n };\n } catch {\n return undefined;\n }\n }\n}\n","import type {\n FileDownloadResponse,\n PollRequest,\n PollResponse,\n RunAttachmentConfirmRequest,\n RunCreateRequest,\n RunAttachmentCreateRequest,\n RunAttachmentCreateResponse,\n RunDescriptor,\n RunItemsCreateRequest,\n RunItemsCreateResponse,\n RunItemsDoneRequest,\n RunItemsDoneResponse,\n RunStartRequest,\n RunUpdateRequest,\n} from './protocol';\nimport { fetchWithRetry, withTimeoutSignal, type Logger } from '../utils';\n\nconst POLL_TIMEOUT_MS = 30_000;\nconst UPDATE_TIMEOUT_MS = 10_000;\n/**\n * No registro de anexo estes códigos são PERMANENTES, não falha transitória: 429 = cota\n * de 20 por execução, 501/503 = instalação sem bucket S3. Sem isto o handler esperaria\n * a ladder inteira (~21s) por um erro definitivo — e o `isUnsupported`/`quota` do\n * RunReporter nunca era acionado (chegava um TimeoutError genérico).\n */\nexport const ATTACHMENT_TERMINAL_STATUSES: readonly number[] = [429, 501, 503];\n/** No envio de itens o 429 é o cap de itens da run — permanente, sem retry. */\nexport const ITEMS_TERMINAL_STATUSES: readonly number[] = [429];\n/** O PUT carrega o binário inteiro — ladder mais curta e timeout mais folgado que os PATCHes. */\nconst UPLOAD_TIMEOUT_MS = 30_000;\nconst UPLOAD_RETRY_DELAYS_MS: readonly number[] = [1_000, 4_000];\n/**\n * Arquivos do formulário: 404 (não existe nesta run) e 410 (já baixado/expirado) são\n * definitivos por natureza (4xx); 429 aqui seria rate limit — retriável, como nos updates.\n */\nconst FILE_RETRY_DELAYS_MS: readonly number[] = [1_000, 4_000];\n\nexport class TasksApiError extends Error {\n constructor(\n message: string,\n readonly status: number\n ) {\n super(message);\n this.name = 'TasksApiError';\n }\n}\n\nexport interface TasksApiOptions {\n baseUrl: string;\n key: string;\n logger: Logger;\n}\n\n/**\n * O que UMA run em execução precisa do transporte — reporter (status, logs, itens, anexos),\n * arquivos do formulário e o exit path do tracker. A `TasksApi` (rede) e o\n * `LocalRunTransport` (modo local, sem rede) implementam a mesma superfície: o pipeline\n * da run não sabe em qual dos dois está.\n */\nexport interface RunTransport {\n updateRun(runId: string, update: RunUpdateRequest): Promise<void>;\n updateRunOnce(runId: string, update: RunUpdateRequest, timeoutMs?: number): Promise<void>;\n createItems(runId: string, request: RunItemsCreateRequest): Promise<RunItemsCreateResponse>;\n listDoneItems(runId: string, request: RunItemsDoneRequest): Promise<RunItemsDoneResponse>;\n createAttachment(runId: string, request: RunAttachmentCreateRequest, signal?: AbortSignal): Promise<RunAttachmentCreateResponse>;\n uploadAttachment(url: string, headers: Record<string, string>, body: Uint8Array, signal?: AbortSignal): Promise<void>;\n confirmAttachment(runId: string, attachmentId: string, request: RunAttachmentConfirmRequest): Promise<void>;\n requestFileDownload(runId: string, fileId: string, signal?: AbortSignal): Promise<FileDownloadResponse>;\n fetchFile(url: string, signal: AbortSignal): Promise<Response>;\n confirmFileDownload(runId: string, fileId: string): Promise<void>;\n}\n\n/** Cliente HTTP do agente — bearer auth, retry com backoff nos updates. */\n/** Um `withTimeoutSignal` por tentativa, sempre limpo — composto com o signal externo (stop/cancelamento). */\nasync function withRequestTimeout(\n timeoutMs: number,\n external: AbortSignal | undefined,\n send: (signal: AbortSignal) => Promise<Response>\n): Promise<Response> {\n const { signal, cleanup } = withTimeoutSignal(timeoutMs, external);\n try {\n return await send(signal);\n } finally {\n cleanup();\n }\n}\n\nexport class TasksApi implements RunTransport {\n private readonly baseUrl: string;\n private readonly key: string;\n private readonly logger: Logger;\n\n constructor(options: TasksApiOptions) {\n this.baseUrl = options.baseUrl;\n this.key = options.key;\n this.logger = options.logger;\n }\n\n private headers(): Record<string, string> {\n return {\n 'content-type': 'application/json',\n authorization: `Bearer ${this.key}`,\n };\n }\n\n /** Um request só — o loop de polling é quem decide o backoff entre tentativas. */\n async poll(request: PollRequest, signal?: AbortSignal): Promise<PollResponse> {\n const { signal: timeoutSignal, cleanup } = withTimeoutSignal(POLL_TIMEOUT_MS, signal);\n let response: Response;\n try {\n response = await fetch(`${this.baseUrl}/poll`, {\n redirect: 'error',\n method: 'POST',\n headers: this.headers(),\n body: JSON.stringify(request),\n signal: timeoutSignal,\n });\n } finally {\n cleanup();\n }\n if (!response.ok) {\n throw new TasksApiError(`poll falhou (HTTP ${response.status})`, response.status);\n }\n return this.parsePollResponse(await response.json(), request.max ?? 1);\n }\n\n /**\n * Abre uma run por conta própria (modo start). Um request só — como no poll, o\n * ladder de espera entre tentativas é decisão do chamador (LocalRunner).\n * 4xx (401 = chave rejeitada) vira TasksApiError com o status.\n */\n async createRun(request: RunCreateRequest, signal?: AbortSignal): Promise<RunDescriptor> {\n const { signal: timeoutSignal, cleanup } = withTimeoutSignal(UPDATE_TIMEOUT_MS, signal);\n let response: Response;\n try {\n response = await fetch(`${this.baseUrl}`, {\n redirect: 'error',\n method: 'POST',\n headers: this.headers(),\n body: JSON.stringify(request),\n signal: timeoutSignal,\n });\n } finally {\n cleanup();\n }\n if (!response.ok) {\n throw new TasksApiError(`criação da run falhou (HTTP ${response.status})`, response.status);\n }\n const body = (await response.json().catch(() => null)) as Record<string, unknown> | null;\n if (typeof body?.id !== 'string') {\n throw new TasksApiError('resposta inválida da criação de run (id ausente)', 0);\n }\n return {\n id: body.id,\n params: body.params && typeof body.params === 'object' && !Array.isArray(body.params) ? (body.params as Record<string, unknown>) : {},\n form: null,\n source: typeof body.source === 'string' ? body.source : 'agent',\n created_at: typeof body.created_at === 'string' ? body.created_at : new Date().toISOString(),\n };\n }\n\n /**\n * Anexa o processo a uma run já reivindicada para esta instância (env HOBOTS_RUN_ID):\n * POST /v1/runs/:id/start. Um request só — quem decide o retry é o AttachedRunner.\n * 404 (não existe) e 409 (cancelada, já iniciada ou de outra instância) viram\n * TasksApiError com o status.\n */\n async startRun(runId: string, request: RunStartRequest, signal?: AbortSignal): Promise<RunDescriptor> {\n const { signal: timeoutSignal, cleanup } = withTimeoutSignal(UPDATE_TIMEOUT_MS, signal);\n let response: Response;\n try {\n response = await fetch(`${this.baseUrl}/${encodeURIComponent(runId)}/start`, {\n redirect: 'error',\n method: 'POST',\n headers: this.headers(),\n body: JSON.stringify(request),\n signal: timeoutSignal,\n });\n } finally {\n cleanup();\n }\n if (!response.ok) {\n throw new TasksApiError(`início da run falhou (HTTP ${response.status})`, response.status);\n }\n const body = (await response.json().catch(() => null)) as Record<string, unknown> | null;\n if (typeof body?.id !== 'string') {\n throw new TasksApiError('resposta inválida do início da run (id ausente)', 0);\n }\n const form = body.form as Record<string, unknown> | null | undefined;\n return {\n id: body.id,\n params: body.params && typeof body.params === 'object' && !Array.isArray(body.params) ? (body.params as Record<string, unknown>) : {},\n form: typeof form?.id === 'string' && typeof form.name === 'string' ? { id: form.id, name: form.name } : null,\n source: typeof body.source === 'string' ? body.source : 'hobots',\n created_at: typeof body.created_at === 'string' ? body.created_at : new Date().toISOString(),\n };\n }\n\n /** Nunca confia no shape da resposta: runs malformadas são descartadas e o `max` é respeitado. */\n private parsePollResponse(body: unknown, max: number): PollResponse {\n const runs = (body as { runs?: unknown } | null)?.runs;\n if (!Array.isArray(runs)) {\n throw new TasksApiError('resposta inválida do poll (campo runs ausente)', 0);\n }\n const valid: RunDescriptor[] = [];\n for (const run of runs.slice(0, Math.max(0, max)) as Array<Record<string, unknown> | null>) {\n if (typeof run?.id !== 'string') continue;\n const params = run.params && typeof run.params === 'object' && !Array.isArray(run.params) ? run.params : {};\n valid.push({ ...run, id: run.id, params } as RunDescriptor);\n }\n if (valid.length < runs.length) {\n this.logger.warn(`poll retornou ${runs.length - valid.length} run(s) inválida(s)/excedente(s) — descartadas`);\n }\n return { runs: valid };\n }\n\n /**\n * PATCH de status/logs com retry em falha de rede/5xx/429.\n * 4xx é definitivo e vira TasksApiError imediato (409 = run cancelada/transição inválida).\n */\n async updateRun(runId: string, update: RunUpdateRequest): Promise<void> {\n let response: Response;\n try {\n response = await fetchWithRetry(\n () =>\n fetch(`${this.baseUrl}/${encodeURIComponent(runId)}`, {\n redirect: 'error',\n method: 'PATCH',\n headers: this.headers(),\n body: JSON.stringify(update),\n signal: AbortSignal.timeout(UPDATE_TIMEOUT_MS),\n }),\n { logger: this.logger, label: `update da run ${runId}` }\n );\n } catch (error) {\n throw new Error(`update da run ${runId} descartado após retries: ${String(error)}`);\n }\n if (!response.ok) {\n // 4xx definitivo (409 = run cancelada/transição inválida) — o RunReporter trata por status\n throw new TasksApiError(`update rejeitado (HTTP ${response.status})`, response.status);\n }\n }\n\n /**\n * Um único PATCH com timeout curto — exit path (o processo está morrendo, o retry\n * ladder do updateRun é proibido aqui). Status HTTP é ignorado: 409/404 significa\n * que a run já foi cancelada/finalizada, o que é aceitável nesse caminho.\n */\n async updateRunOnce(runId: string, update: RunUpdateRequest, timeoutMs = 2_000): Promise<void> {\n await fetch(`${this.baseUrl}/${encodeURIComponent(runId)}`, {\n redirect: 'error',\n method: 'PATCH',\n headers: this.headers(),\n body: JSON.stringify(update),\n signal: AbortSignal.timeout(timeoutMs),\n });\n }\n\n /**\n * Envia um lote de itens de execução. Retry em falha de rede/5xx/429-transporte;\n * 4xx é definitivo (404 = servidor sem o recurso, 429 = cap de itens por run) —\n * o RunReporter trata por status.\n */\n async createItems(runId: string, request: RunItemsCreateRequest): Promise<RunItemsCreateResponse> {\n let response: Response;\n try {\n response = await fetchWithRetry(\n () =>\n fetch(`${this.baseUrl}/${encodeURIComponent(runId)}/items`, {\n redirect: 'error',\n method: 'POST',\n headers: this.headers(),\n body: JSON.stringify(request),\n signal: AbortSignal.timeout(UPDATE_TIMEOUT_MS),\n }),\n { logger: this.logger, label: `itens da run ${runId}`, noRetryStatuses: ITEMS_TERMINAL_STATUSES }\n );\n } catch (error) {\n throw new Error(`envio de itens da run ${runId} descartado após retries: ${String(error)}`);\n }\n if (!response.ok) {\n throw new TasksApiError(`envio de itens rejeitado (HTTP ${response.status})`, response.status);\n }\n const body = (await response.json().catch(() => null)) as Partial<RunItemsCreateResponse> | null;\n return {\n accepted: typeof body?.accepted === 'number' ? body.accepted : request.items.length,\n duplicates: typeof body?.duplicates === 'number' ? body.duplicates : 0,\n };\n }\n\n /**\n * Uma página dos ids já concluídos neste trabalho (`items.each` pula). Retry em falha\n * de rede/5xx; 4xx é definitivo (404 = servidor sem o recurso).\n */\n async listDoneItems(runId: string, request: RunItemsDoneRequest): Promise<RunItemsDoneResponse> {\n let response: Response;\n try {\n response = await fetchWithRetry(\n () =>\n fetch(`${this.baseUrl}/${encodeURIComponent(runId)}/items/done`, {\n redirect: 'error',\n method: 'POST',\n headers: this.headers(),\n body: JSON.stringify(request),\n signal: AbortSignal.timeout(UPDATE_TIMEOUT_MS),\n }),\n { logger: this.logger, label: `itens concluídos da run ${runId}` }\n );\n } catch (error) {\n throw new Error(`consulta de itens concluídos da run ${runId} descartada após retries: ${String(error)}`);\n }\n if (!response.ok) {\n throw new TasksApiError(`consulta de itens concluídos rejeitada (HTTP ${response.status})`, response.status);\n }\n const body = (await response.json().catch(() => null)) as Partial<RunItemsDoneResponse> | null;\n if (!Array.isArray(body?.ids)) throw new TasksApiError('consulta de itens concluídos: resposta malformada', 0);\n return {\n ids: body.ids.map(id => String(id)),\n next: typeof body.next === 'string' && body.next.length > 0 ? body.next : null,\n };\n }\n\n /**\n * Registra o anexo e obtém a URL presignada de upload. 404/501/503 significam\n * \"esta instalação não tem anexos\" — o RunReporter degrada em silêncio a partir daí.\n */\n async createAttachment(\n runId: string,\n request: RunAttachmentCreateRequest,\n signal?: AbortSignal\n ): Promise<RunAttachmentCreateResponse> {\n // timeout POR requisição (não um só cobrindo a ladder inteira: os 1s+4s+16s de\n // espera já passariam de 10s e todo retry chegaria como TimeoutError)\n const response = await fetchWithRetry(\n () =>\n withRequestTimeout(UPDATE_TIMEOUT_MS, signal, timeoutSignal =>\n fetch(`${this.baseUrl}/${encodeURIComponent(runId)}/attachments`, {\n redirect: 'error',\n method: 'POST',\n headers: this.headers(),\n body: JSON.stringify(request),\n signal: timeoutSignal,\n })\n ),\n {\n logger: this.logger,\n label: `anexo da run ${runId}`,\n noRetryStatuses: ATTACHMENT_TERMINAL_STATUSES,\n // run abortada (timeout, 409, kill): o create em voo rejeita por abort e não entra na ladder\n signal,\n }\n );\n if (!response.ok) {\n throw new TasksApiError(`criação de anexo rejeitada (HTTP ${response.status})`, response.status);\n }\n const body = (await response.json()) as Partial<RunAttachmentCreateResponse> | null;\n if (typeof body?.upload_url !== 'string') {\n throw new TasksApiError('resposta inválida do anexo (upload_url ausente)', 0);\n }\n return {\n id: body.id ?? request.id,\n upload_url: body.upload_url,\n headers: body.headers ?? { 'content-type': request.content_type },\n expires_in: body.expires_in ?? 900,\n };\n }\n\n /**\n * PUT do binário direto no S3. Deliberadamente sem `authorization`: a autorização\n * está na assinatura da URL, e mandar o client secret para fora da API seria vazamento.\n */\n async uploadAttachment(\n url: string,\n headers: Record<string, string>,\n body: Uint8Array,\n signal?: AbortSignal\n ): Promise<void> {\n const response = await fetchWithRetry(\n () =>\n withRequestTimeout(UPLOAD_TIMEOUT_MS, signal, timeoutSignal =>\n fetch(url, {\n redirect: 'error',\n method: 'PUT',\n headers,\n // BodyInit não aceita Uint8Array<ArrayBufferLike> em todos os lib.dom; o buffer é o mesmo\n body: body as BodyInit,\n signal: timeoutSignal,\n })\n ),\n { delays: UPLOAD_RETRY_DELAYS_MS, logger: this.logger, label: 'upload de anexo', signal }\n );\n if (!response.ok) {\n throw new TasksApiError(`upload de anexo rejeitado (HTTP ${response.status})`, response.status);\n }\n }\n\n /** Marca o anexo como enviado (ou falho). Best-effort — a leitura não depende disso. */\n async confirmAttachment(\n runId: string,\n attachmentId: string,\n request: RunAttachmentConfirmRequest\n ): Promise<void> {\n const response = await fetch(\n `${this.baseUrl}/${encodeURIComponent(runId)}/attachments/${encodeURIComponent(attachmentId)}`,\n {\n redirect: 'error',\n method: 'PATCH',\n headers: this.headers(),\n body: JSON.stringify(request),\n signal: AbortSignal.timeout(UPDATE_TIMEOUT_MS),\n }\n );\n if (!response.ok) {\n throw new TasksApiError(`confirmação de anexo rejeitada (HTTP ${response.status})`, response.status);\n }\n }\n\n /**\n * Pede a URL pré-assinada de GET de um arquivo do formulário. 404 (não existe nesta run)\n * e 410 (já baixado/expirado) viram `TasksApiError` com o status — quem chama traduz.\n */\n async requestFileDownload(runId: string, fileId: string, signal?: AbortSignal): Promise<FileDownloadResponse> {\n const response = await fetchWithRetry(\n () =>\n withRequestTimeout(UPDATE_TIMEOUT_MS, signal, timeoutSignal =>\n fetch(`${this.baseUrl}/${encodeURIComponent(runId)}/files/${encodeURIComponent(fileId)}/download`, {\n redirect: 'error',\n method: 'POST',\n headers: this.headers(),\n signal: timeoutSignal,\n })\n ),\n { delays: FILE_RETRY_DELAYS_MS, logger: this.logger, label: `download do arquivo ${fileId}`, signal }\n );\n if (!response.ok) {\n throw new TasksApiError(`download de arquivo rejeitado (HTTP ${response.status})`, response.status);\n }\n const body = (await response.json().catch(() => null)) as Partial<FileDownloadResponse> | null;\n if (typeof body?.url !== 'string') {\n throw new TasksApiError('resposta inválida do download de arquivo (url ausente)', 0);\n }\n return {\n url: body.url,\n expires_in: typeof body.expires_in === 'number' ? body.expires_in : 0,\n name: typeof body.name === 'string' ? body.name : '',\n size: typeof body.size === 'number' ? body.size : -1,\n content_type: typeof body.content_type === 'string' ? body.content_type : '',\n };\n }\n\n /**\n * GET do binário direto no S3 — deliberadamente sem `authorization` (a autorização\n * está na assinatura da URL; mandar o client secret para fora da API seria vazamento).\n * Devolve a Response com o corpo ainda não lido: quem chama faz o streaming para o disco.\n */\n async fetchFile(url: string, signal: AbortSignal): Promise<Response> {\n const response = await fetchWithRetry(() => fetch(url, { redirect: 'error', method: 'GET', signal }), {\n delays: FILE_RETRY_DELAYS_MS,\n logger: this.logger,\n label: 'download de arquivo',\n signal,\n });\n if (!response.ok) {\n throw new TasksApiError(`download de arquivo falhou (HTTP ${response.status})`, response.status);\n }\n return response;\n }\n\n /**\n * Confirma o download: o servidor apaga o objeto do S3 na hora. Idempotente (204);\n * 404/410 também significam \"não há mais nada a apagar\" e contam como confirmado.\n */\n async confirmFileDownload(runId: string, fileId: string): Promise<void> {\n const response = await fetchWithRetry(\n () =>\n fetch(`${this.baseUrl}/${encodeURIComponent(runId)}/files/${encodeURIComponent(fileId)}`, {\n redirect: 'error',\n method: 'DELETE',\n headers: this.headers(),\n signal: AbortSignal.timeout(UPDATE_TIMEOUT_MS),\n }),\n { delays: FILE_RETRY_DELAYS_MS, logger: this.logger, label: `confirmação do arquivo ${fileId}` }\n );\n if (!response.ok && response.status !== 404 && response.status !== 410) {\n throw new TasksApiError(`confirmação de download rejeitada (HTTP ${response.status})`, response.status);\n }\n }\n}\n","import { TasksApiError } from './api';\nimport { jitter, type Logger } from '../utils';\n\nconst RETRY_DELAYS_MS = [1_000, 4_000, 16_000];\nconst AUTH_FAILURE_INTERVAL_MS = 30_000;\n\n/**\n * Espera entre tentativas de uma chamada que o agente repete até dar certo (poll,\n * criação da run no modo start): ladder 1s/4s/16s com jitter, e 401 (chave\n * desativada/rotacionada) ou 402 (agente fora do limite do plano) em ritmo lento,\n * com erro logado na 1ª falha e a cada 10 — os dois podem voltar sozinhos.\n */\nexport class Backoff {\n private failures = 0;\n private authFailures = 0;\n\n constructor(\n private readonly logger: Logger,\n private readonly label: string,\n /** Piso da espera (o intervalo normal do poll); no modo start, 0. */\n private readonly floorMs = 0\n ) {}\n\n reset(): void {\n this.failures = 0;\n this.authFailures = 0;\n }\n\n next(error: unknown): number {\n if (error instanceof TasksApiError && (error.status === 401 || error.status === 402)) {\n this.authFailures++;\n if (this.authFailures === 1 || this.authFailures % 10 === 0) {\n this.logger.error(\n error.status === 402\n ? 'agente fora do limite do plano (402) — faça upgrade em Plano e cobrança para reativá-lo'\n : 'chave rejeitada (401) — verifique o Client Secret na Central: abra o agente → Configurações → agente → aba credenciais'\n );\n }\n return Math.max(this.floorMs, AUTH_FAILURE_INTERVAL_MS);\n }\n this.failures++;\n const ladder = RETRY_DELAYS_MS[Math.min(this.failures - 1, RETRY_DELAYS_MS.length - 1)]!;\n const delay = Math.min(Math.max(jitter(ladder), 0), Math.max(this.floorMs, 16_000));\n this.logger.warn(`${this.label} falhou (${String(error)}), próxima tentativa em ${delay}ms`);\n return delay;\n }\n}\n","import type { ImageInput } from './attachments';\n\n/** Erros de controle do ciclo de vida de uma run — identificados pelo `name`, nunca pela classe. */\n\n/**\n * Ocorrência de negócio lançada de dentro do handler de `hobots.items.each`: o item vira\n * `occurrence` com esta mensagem (e `payload`/`image`, se vierem), a etapa do item vira\n * `warning` e o loop segue — **sem nova tentativa**: o retry do `each` é só para falha\n * técnica (qualquer outro erro). Use para regra de negócio: \"nota já cadastrada\",\n * \"cliente sem pendência\", \"produto fora do cardápio\".\n *\n * throw new Occurrence('nota já cadastrada', { situacao: 'já cadastrada' });\n *\n * Fora do `each` (handler de `register()`/`start()` sem loop) é um erro comum: a run falha\n * com ele como com qualquer outro.\n */\nexport class Occurrence extends Error {\n readonly payload: Record<string, unknown> | undefined;\n /** Print do item (bytes/caminho ou `hobots.image(...)`) — o `each` pendura no item. */\n readonly image: ImageInput | undefined;\n\n constructor(message: string, payload?: Record<string, unknown>, options?: { image?: ImageInput }) {\n super(message);\n this.name = 'Occurrence';\n this.payload = payload;\n this.image = options?.image;\n }\n}\n\n/** Ocorrência de negócio — pelo `name`, como os demais erros de controle. */\nexport function isOccurrence(error: unknown): error is Occurrence {\n return error instanceof Error && error.name === 'Occurrence';\n}\n\n/** A run foi cancelada (no app, por timeout ou no shutdown). */\nexport function runCanceledError(): Error {\n return Object.assign(new Error('execução cancelada'), { name: 'RunCanceled' });\n}\n\n/** O handler estourou `timeoutMs` — terminal: não há nova tentativa. */\nexport function taskTimeoutError(timeoutMs: number): Error {\n return Object.assign(new Error(`timeout após ${timeoutMs}ms (o handler pode continuar em background)`), {\n name: 'TaskTimeout',\n });\n}\n\n/** Erros que encerram a run de vez — o retry nunca insiste depois de um deles. */\nconst TERMINAL_ERROR_NAMES: ReadonlySet<string> = new Set(['RunCanceled', 'AbortError', 'TaskTimeout']);\n\nexport function isTerminalError(error: unknown): boolean {\n return error instanceof Error && TERMINAL_ERROR_NAMES.has(error.name);\n}\n\n/** Cancelamento (no app, no shutdown ou pelo signal) — encerra a run, mas não é defeito do bot. */\nexport function isCancellation(error: unknown): boolean {\n return error instanceof Error && (error.name === 'RunCanceled' || error.name === 'AbortError');\n}\n","import type { RunAttachmentContentType } from './protocol';\nimport { isNode } from '../utils';\nimport { WIRE_LIMITS } from '../wire-limits';\n\n/** Tamanho máximo de um anexo. O servidor aplica o mesmo teto (WIRE_LIMITS). */\nexport const MAX_ATTACHMENT_BYTES = WIRE_LIMITS.MAX_ATTACHMENT_BYTES;\n/** Teto de anexos por execução. O servidor aplica o mesmo teto (429). */\nexport const MAX_ATTACHMENTS_PER_RUN = WIRE_LIMITS.MAX_ATTACHMENTS_PER_RUN;\n/** Anexos por linha de log — o servidor rejeita a linha acima disto. */\nexport const MAX_ATTACHMENTS_PER_LOG_ENTRY = WIRE_LIMITS.MAX_ATTACHMENTS_PER_LOG_ENTRY;\n/** Uploads simultâneos por run — o resto fica na fila. */\nexport const MAX_CONCURRENT_UPLOADS = 3;\nexport const MAX_CAPTION_CHARS = WIRE_LIMITS.MAX_CAPTION_CHARS;\n/** Tempo máximo que a run espera pelos uploads pendentes antes do PATCH terminal. */\nexport const ATTACHMENT_DRAIN_MS = 15_000;\n\nexport type AttachFailureReason =\n /** A instalação do Hobots não tem anexos habilitados (ou a API é anterior ao recurso) */\n | 'unsupported'\n | 'too-large'\n | 'quota'\n | 'read-failed'\n /** Formato não reconhecido ou fora de PNG/JPEG/WEBP */\n | 'unsupported-format'\n | 'upload-failed'\n | 'canceled';\n\n/** Aceita tudo que o handler pode ter em mãos: bytes ou um caminho de arquivo (só Node). */\nexport type AttachInput = Uint8Array | ArrayBuffer | string;\n\nexport interface ImageOptions {\n /** Legenda curta, exibida junto da imagem no app. Passa pelo scrub de segredos. */\n caption?: string;\n /** Informe quando os magic bytes não bastarem (o SDK sempre prefere o que detectar). */\n contentType?: RunAttachmentContentType;\n}\n\nconst IMAGE_BRAND: unique symbol = Symbol.for('hobots.image');\n\n/**\n * Uma imagem pronta para ser pendurada num evento da run — o retorno de `hobots.image()`.\n * É só um envelope (bytes/caminho + legenda); nenhum I/O acontece até o evento ser\n * registrado por `hobots.log.*`, `hobots.items.*` ou `step.setStatus/failed`.\n */\nexport class ImageAttachment {\n readonly [IMAGE_BRAND] = true;\n\n constructor(\n readonly input: AttachInput,\n readonly caption?: string,\n readonly contentType?: RunAttachmentContentType\n ) {}\n}\n\n/** O que os métodos com imagem aceitam: bytes/caminho crus ou o envelope de `hobots.image()`. */\nexport type ImageInput = AttachInput | ImageAttachment;\n\n/**\n * `hobots.image(bytes, { caption })`: embrulha um print para ir junto de um log, item ou\n * step. Puro — a leitura/validação/upload acontecem só quando o evento é registrado.\n */\nexport function image(input: AttachInput, options: ImageOptions = {}): ImageAttachment {\n return new ImageAttachment(input, options.caption, options.contentType);\n}\n\n/** Reconhece o envelope mesmo vindo de outra cópia do pacote (brand por `Symbol.for`). */\nexport function isImageAttachment(value: unknown): value is ImageAttachment {\n return typeof value === 'object' && value !== null && (value as Record<symbol, unknown>)[IMAGE_BRAND] === true;\n}\n\n/** Normaliza bytes/caminho crus para o envelope. */\nexport function toImageAttachment(value: ImageInput): ImageAttachment {\n return isImageAttachment(value) ? value : new ImageAttachment(value);\n}\n\n/**\n * Lê um arquivo de imagem do disco. Import dinâmico de `node:fs/promises` — nada de\n * import estático de builtin do Node, que quebraria o bundle neutro/browser.\n */\nexport async function readImageFile(path: string): Promise<Uint8Array> {\n if (!isNode()) {\n throw new Error('caminho de arquivo só é suportado em Node');\n }\n const { readFile } = await import('node:fs/promises');\n return new Uint8Array(await readFile(path));\n}\n\nfunction startsWith(bytes: Uint8Array, signature: readonly number[], offset = 0): boolean {\n if (bytes.length < offset + signature.length) return false;\n return signature.every((byte, index) => bytes[offset + index] === byte);\n}\n\nconst PNG_MAGIC = [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a] as const;\nexport const MAX_PNG_DIMENSION = WIRE_LIMITS.MAX_IMAGE_DIMENSION_PX;\nconst JPEG_MAGIC = [0xff, 0xd8, 0xff] as const;\nconst RIFF_MAGIC = [0x52, 0x49, 0x46, 0x46] as const; // \"RIFF\"\nconst WEBP_MAGIC = [0x57, 0x45, 0x42, 0x50] as const; // \"WEBP\" no offset 8\n\n/** Detecta o formato pelos magic bytes. `undefined` quando não é PNG/JPEG/WEBP. */\nexport function sniffContentType(bytes: Uint8Array): RunAttachmentContentType | undefined {\n if (startsWith(bytes, PNG_MAGIC)) return 'image/png';\n if (startsWith(bytes, JPEG_MAGIC)) return 'image/jpeg';\n if (startsWith(bytes, RIFF_MAGIC) && startsWith(bytes, WEBP_MAGIC, 8)) return 'image/webp';\n return undefined;\n}\n\n/**\n * Dimensões pelo chunk IHDR de um PNG (bytes 16..23). Só PNG: é o formato de print\n * mais comum e o único que dá pra ler sem parser. Sem dimensões o app apenas não\n * reserva o espaço da miniatura antes do carregamento.\n */\nexport function readPngDimensions(bytes: Uint8Array): { width: number; height: number } | undefined {\n if (!startsWith(bytes, PNG_MAGIC) || bytes.length < 24) return undefined;\n const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);\n const width = view.getUint32(16);\n const height = view.getUint32(20);\n if (width === 0 || height === 0) return undefined;\n // o servidor valida 1..20_000 por dimensão\n if (width > MAX_PNG_DIMENSION || height > MAX_PNG_DIMENSION) return undefined;\n return { width, height };\n}\n\n/** Normaliza a entrada do handler para bytes, lendo do disco quando for um caminho. */\nexport async function toBytes(input: AttachInput): Promise<Uint8Array> {\n if (typeof input === 'string') return readImageFile(input);\n if (input instanceof Uint8Array) return input;\n return new Uint8Array(input);\n}\n","import type { AsyncLocalStorage } from 'node:async_hooks';\n\nimport { isNode } from '../utils';\nimport type { RunReporter } from './context';\nimport type { Step, Transaction } from '../transaction';\n\ninterface RunStore {\n /** Reporter da run em execução — a fonte de tudo que `hobots.*` expõe (log, items, progress…). */\n reporter: RunReporter;\n}\n\n/** A etapa corrente de uma transaction: `hobots.step` dentro dela vira filha. */\nexport interface StepScope {\n transaction: Transaction;\n step: Step;\n}\n\n// Inicializado sob demanda só em Node (import dinâmico → não entra no bundle do browser).\n// import type acima é apagado em compilação, então não há import estático de node:async_hooks.\nlet storage: AsyncLocalStorage<RunStore> | undefined;\nlet stepStorage: AsyncLocalStorage<StepScope> | undefined;\nlet initPromise: Promise<void> | undefined;\n\nasync function ensureStorage(): Promise<void> {\n if (storage || !isNode()) return;\n initPromise ??= import('node:async_hooks').then(({ AsyncLocalStorage: ALS }) => {\n storage = new ALS<RunStore>();\n stepStorage = new ALS<StepScope>();\n });\n await initPromise;\n}\n\n/**\n * Executa `fn` com a run ativa no contexto async atual. Qualquer acesso a `hobots.*`\n * por dentro (em qualquer módulo, timer ou promise criada aqui) resolve para esta run —\n * é o que permite `concurrency > 1` sem passar o contexto de mão em mão.\n */\nexport async function runWithRunContext<T>(store: RunStore, fn: () => Promise<T>): Promise<T> {\n await ensureStorage();\n return storage ? storage.run(store, fn) : fn();\n}\n\n/** Reporter da run em execução no contexto async atual, se houver. */\nexport function currentRunReporter(): RunReporter | undefined {\n return storage?.getStore()?.reporter;\n}\n\n/**\n * Executa `fn` com `scope.step` como a etapa corrente da transaction no contexto async atual —\n * é o que faz `hobots.step` dentro de outra etapa (ou do handler de `items.each`) aninhar nela.\n */\nexport async function runWithStepScope<T>(scope: StepScope, fn: () => Promise<T>): Promise<T> {\n await ensureStorage();\n return stepStorage ? stepStorage.run(scope, fn) : fn();\n}\n\n/** A etapa corrente de `transaction` no contexto async atual, se houver. */\nexport function currentStep(transaction: Transaction): Step | undefined {\n const scope = stepStorage?.getStore();\n return scope?.transaction === transaction ? scope.step : undefined;\n}\n","import { isTerminalError, runCanceledError } from './tasks/errors';\nimport { sleep } from './utils';\n\n/** Espera entre tentativas: ms fixo ou função do número da tentativa que acabou de falhar (1-based). */\nexport type RetryDelay = number | ((attempt: number) => number);\n\nexport interface RetryOptions {\n /** Tentativas extras depois da primeira falha. Default: 3 */\n retries?: number;\n /** Espera entre tentativas. Default: 1_000 */\n delayMs?: RetryDelay;\n /** Filtro adicional: retorne false para desistir na hora. Cancelamento e timeout nunca são re-tentados. */\n shouldRetry?: (error: unknown) => boolean;\n}\n\n/** Opções internas do runner — não fazem parte da API pública. */\nexport interface RetryInternalOptions extends RetryOptions {\n /** Cancelamento: aborta antes da próxima tentativa (lança RunCanceled). */\n signal?: AbortSignal;\n /** Sleep a usar entre tentativas (o ctx.sleep cancelável dentro de uma run). Default: sleep unref'd. */\n wait?: (ms: number) => Promise<void>;\n /** Chamado antes de esperar pela próxima tentativa — o runner loga no run aqui. */\n onRetry?: (error: unknown, attempt: number, delayMs: number) => void;\n}\n\nconst DEFAULT_RETRIES = 3;\nconst DEFAULT_DELAY_MS = 1_000;\n\n/** Resolve o delay de uma tentativa; valores inválidos/negativos viram 0. */\nexport function resolveDelay(delay: RetryDelay | undefined, attempt: number, fallbackMs: number): number {\n const value = typeof delay === 'function' ? delay(attempt) : (delay ?? fallbackMs);\n return Number.isFinite(value) && value > 0 ? Math.floor(value) : 0;\n}\n\n/**\n * async-retry do SDK: executa `fn` até dar certo ou esgotar `retries`. Ciente de\n * cancelamento — com o signal abortado, lança RunCanceled em vez de tentar de novo;\n * erros terminais (RunCanceled/AbortError/TaskTimeout) nunca são re-tentados.\n */\nexport async function retryWithBackoff<T>(\n fn: (attempt: number) => T | Promise<T>,\n options: RetryInternalOptions = {}\n): Promise<T> {\n // `Number.isFinite`: um `retries: NaN` deixava `attempt > retries` sempre falso → retry infinito\n const requested = options.retries ?? DEFAULT_RETRIES;\n const retries = Number.isFinite(requested) ? Math.max(0, Math.floor(requested)) : DEFAULT_RETRIES;\n const wait = options.wait ?? sleep;\n for (let attempt = 1; ; attempt++) {\n if (options.signal?.aborted) throw runCanceledError();\n try {\n return await fn(attempt);\n } catch (error) {\n const exhausted = attempt > retries;\n const retriable = !isTerminalError(error) && !options.signal?.aborted && (options.shouldRetry?.(error) ?? true);\n if (exhausted || !retriable) throw error;\n const delay = resolveDelay(options.delayMs, attempt, DEFAULT_DELAY_MS);\n options.onRetry?.(error, attempt, delay);\n await wait(delay);\n }\n }\n}\n","/**\n * Etapas (steps) de uma execução: a transaction da run e as etapas que o bot abre nela.\n *\n * O bot só conhece `hobots.step(nome, fn, { retries })`: o SDK abre a transaction da run em\n * `register()`/`start()`, registra cada etapa (com tentativas) no waterfall da Central e\n * fecha tudo no fim. `Transaction` é interna — nada aqui é chamado pelo código do bot\n * além do handle (`StepHandle`) que `fn` recebe.\n */\nimport type { StepData, StepStatus, TransactionPayload } from './protocol';\nimport type { RunLogLevel } from './tasks/protocol';\nimport { MAX_ATTACHMENTS_PER_LOG_ENTRY, type ImageInput } from './tasks/attachments';\nimport { isTerminalError } from './tasks/errors';\nimport { currentStep, runWithStepScope } from './tasks/run-context-store';\nimport { MAX_STEPS, MAX_STEP_DESCRIPTION_CHARS, MAX_STEP_OP_CHARS, type Client } from './client';\nimport { resolveDelay, retryWithBackoff } from './retry';\nimport { scrubSecrets } from './scrub';\nimport type { StepFn, StepHandle, StepOptions } from './types';\nimport { clip, colorize, nowISO, safeString, truncate, uuid4 } from './utils';\n\n/** `op` das transactions parciais enviadas por `flush()` — a Central as distingue da final. */\nexport const FLUSH_TRANSACTION_OP = 'hobots.run.flush';\n/** Tentativas extras de uma etapa por padrão (`retries: 0` desliga). */\nexport const DEFAULT_STEP_RETRIES = 1;\n/** Espera entre as tentativas de uma etapa (ms) — a mesma do retry do trabalho inteiro. */\nexport const DEFAULT_STEP_RETRY_DELAY_MS = 5_000;\nexport { MAX_STEP_DESCRIPTION_CHARS, MAX_STEP_OP_CHARS } from './client';\n\n/** Teto do motivo de uma etapa (data.message / data.error.message). */\nconst MAX_STEP_MESSAGE_CHARS = 2_000;\nconst MAX_BACKLOG = 100;\n\nfunction stepMessage(text: string): string {\n return clip(scrubSecrets(text), MAX_STEP_MESSAGE_CHARS);\n}\n\nfunction stepId(): string {\n return uuid4().slice(0, 16);\n}\n\n/** Recebe os eventos de lifecycle da transaction para espelhá-los nos logs da run. */\nexport type LifecycleSink = (level: RunLogLevel, message: string) => void;\n\n/**\n * Recebe a imagem de uma etapa e dispara o upload pela run; devolve o id do anexo\n * (já referenciável em `data.attachments`) ou undefined quando descartada.\n */\nexport type AttachmentSink = (image: ImageInput, ts: string) => string | undefined;\n\n/** Opções internas de `Transaction.step` — o RunContext liga o cancelamento e o log da run. */\nexport interface StepInternalOptions {\n /** Cancelamento da run: abortado, não há nova tentativa. */\n signal?: AbortSignal;\n /** Espera entre tentativas (o `ctx.sleep` cancelável dentro de uma run). */\n wait?: (ms: number) => Promise<void>;\n /** Aviso de tentativa falhada — vai para o log da run. */\n warn?: (message: string) => void;\n}\n\n/** Rótulo legível de uma etapa a partir de op/description. */\nfunction stepLabel(op?: string, description?: string): string {\n return [op, description].filter(Boolean).join(' — ') || '(sem nome)';\n}\n\n/** `op` padrão da etapa de um item do `items.each` — some do rótulo das linhas `[item]`. */\nexport const ITEM_OP = 'item';\n\n/**\n * Tipo da etapa nas linhas de log: `step` (`hobots.step`) ou `item` (etapa de um elemento do\n * `items.each`, cujo FINISH segue o desfecho do item).\n */\nexport type StepKind = 'step' | 'item';\n\n/** Rótulo das linhas START/FINISH: na etapa de item o `op` padrão (`item`) já está no prefixo. */\nfunction lifecycleLabel(kind: StepKind, op?: string, description?: string): string {\n return stepLabel(kind === 'item' && op === ITEM_OP ? undefined : op, description);\n}\n\n/** Mensagem legível de qualquer valor lançado — só a mensagem, sem o tipo. */\nfunction errorText(error: unknown): string {\n if (error instanceof Error) return error.message || error.name;\n return safeString(error);\n}\n\n/** `Tipo: mensagem`, como no aviso de retry do trabalho inteiro. */\nexport function errorReason(error: unknown): string {\n return error instanceof Error ? `${error.name}: ${errorText(error)}` : errorText(error);\n}\n\n/** Mapeia o status de finalização (etapa/transaction) para o nível de log da run. */\nfunction levelForStatus(status: StepStatus | string): RunLogLevel {\n switch (status) {\n case 'warning':\n return 'warning';\n case 'error':\n return 'error';\n case 'cancelled':\n return 'warning';\n default:\n return 'success';\n }\n}\n\n/** Mapeia o status de finalização para a cor ANSI usada no eco do terminal. */\nfunction colorForStatus(status: StepStatus | string): Parameters<typeof colorize>[1] {\n switch (status) {\n case 'warning':\n return 'yellow';\n case 'error':\n return 'red';\n case 'cancelled':\n return 'gray';\n default:\n return 'green';\n }\n}\n\n/**\n * A etapa em andamento — o handle que a função de `hobots.step(nome, fn)` recebe (classe\n * interna: o bot vê só a interface `StepHandle`). Abrir, repetir e fechar é do SDK.\n */\nexport class Step implements StepHandle {\n readonly stepId = stepId();\n readonly startTimestamp = nowISO();\n status: StepStatus = 'ok';\n endTimestamp?: string;\n private _data?: Record<string, unknown>;\n // desfecho que a linha de FINISH reporta no lugar do status da etapa (item do `each`)\n private outcome?: { status: StepStatus; reason?: string };\n\n constructor(\n private readonly transaction: Transaction,\n readonly parentStepId: string,\n readonly op?: string,\n readonly description?: string,\n readonly kind: StepKind = 'step'\n ) {}\n\n // ── API do bot ────────────────────────────────────────────────────────────\n\n warning(message: string, options?: { image?: ImageInput }): this {\n if (this.status !== 'error') this._setStatus('warning', message);\n if (options?.image !== undefined) this.attachImage(options.image);\n return this;\n }\n\n image(image: ImageInput): this {\n this.attachImage(image);\n return this;\n }\n\n data(key: string, value: unknown): this {\n if (key === 'attachments') return this;\n this._setData(key, value);\n return this;\n }\n\n // ── Internos (chamados pelo SDK) ──────────────────────────────────────────\n\n /** `data` da etapa como vai no wire (undefined quando vazio). */\n get payload(): Record<string, unknown> | undefined {\n return this._data;\n }\n\n _setStatus(status: StepStatus, message?: string): this {\n this.status = status;\n if (message) this._setData('message', stepMessage(safeString(message)));\n return this;\n }\n\n /**\n * Marca `error` guardando `{ type, message }` em `data.error` e fecha a etapa. Aceita qualquer\n * valor lançado; `message` sobrescreve a mensagem do erro. Numa etapa já fechada não faz nada.\n */\n _failed(error: unknown, message?: string): this {\n if (this.endTimestamp) return this;\n this.status = 'error';\n const type = error instanceof Error ? error.name : typeof error === 'object' && error !== null ? 'Error' : undefined;\n const raw = message ?? errorText(error);\n this._setData('error', { ...(type ? { type } : {}), message: stepMessage(safeString(raw)) });\n this._close();\n return this;\n }\n\n /**\n * Faz a linha de FINISH reportar `status`/`reason` em vez do status da etapa — o\n * `items.each` usa para o log do item seguir o desfecho dele (sucesso/falha/ocorrência).\n */\n _setOutcome(status: StepStatus, reason?: string): void {\n this.outcome = { status, reason };\n }\n\n _setData(key: string, value: unknown): void {\n this._data = { ...this._data, [key]: value };\n }\n\n _deleteData(key: string): void {\n if (!this._data || !(key in this._data)) return;\n const rest = { ...this._data };\n delete rest[key];\n this._data = Object.keys(rest).length > 0 ? rest : undefined;\n }\n\n /**\n * Dispara o upload pela run (sink do RunReporter) e referencia o anexo em\n * `data.attachments` (chave reservada; teto igual ao das linhas de log). Fora de uma\n * run não há onde pendurar a imagem — descarta com aviso único.\n */\n private attachImage(image: ImageInput): void {\n const current = Array.isArray(this._data?.attachments) ? (this._data.attachments as string[]) : [];\n if (current.length >= MAX_ATTACHMENTS_PER_LOG_ENTRY) return;\n const id = this.transaction.attachImage(image);\n if (!id) return;\n this._setData('attachments', [...current, id]);\n }\n\n /** Motivo registrado (warning/erro) — usado no log de FINISH. */\n private reason(): string | undefined {\n const error = this._data?.error as { message?: unknown } | undefined;\n const text = typeof error?.message === 'string' ? error.message : this._data?.message;\n return typeof text === 'string' && text ? text : undefined;\n }\n\n /** Fecha a etapa mantendo o status que estiver. Idempotente. */\n _close(): void {\n if (this.endTimestamp) return;\n this.endTimestamp = nowISO();\n const { status, reason } = this.outcome ?? { status: this.status, reason: this.reason() };\n this.transaction.emit(\n this.kind,\n 'finish',\n lifecycleLabel(this.kind, this.op, this.description),\n this.startTimestamp,\n this.endTimestamp,\n status,\n reason\n );\n }\n\n toJSON(): StepData {\n return {\n step_id: this.stepId,\n ...(this.parentStepId ? { parent_step_id: this.parentStepId } : {}),\n ...(this.op ? { op: clip(this.op, MAX_STEP_OP_CHARS) } : {}),\n ...(this.description ? { description: clip(this.description, MAX_STEP_DESCRIPTION_CHARS) } : {}),\n status: this.status,\n start_timestamp: this.startTimestamp,\n timestamp: this.endTimestamp ?? nowISO(),\n ...(this._data ? { data: this._data } : {}),\n };\n }\n}\n\n/**\n * A transaction de performance de uma execução (interna ao SDK). O runner cria uma por run\n * (`name` `run`, `op` `hobots.run`), o `RunReporter` liga os sinks, e `step()` registra as\n * etapas do bot nela. Fora de uma run existe só para dar um handle inerte à função da etapa.\n */\nexport class Transaction {\n readonly eventId = uuid4();\n readonly stepId = stepId();\n readonly startTimestamp = nowISO();\n status = 'ok';\n private readonly steps: Step[] = [];\n private finished = false;\n private lifecycleSink?: LifecycleSink;\n private attachmentSink?: AttachmentSink;\n private warnedNoAttachmentSink = false;\n // instalado pelo RunReporter: abrir uma etapa é um ponto de parada cooperativo (lança RunCanceled)\n private stepGuard?: () => void;\n // modo local (sem client): o FINISH de cada etapa sai no terminal, como `[hobots:item]`\n private readonly echo: boolean;\n // eventos emitidos antes do sink existir (o START da transaction sai no construtor,\n // antes do RunReporter conectar) — replay no setLifecycleSink\n private lifecycleBacklog: Array<[RunLogLevel, string]> = [];\n\n constructor(\n private readonly client: Client | undefined,\n readonly name: string,\n readonly op?: string,\n /** Correlaciona a uma execução do agente — preenchido pelo runner */\n private readonly runId?: string,\n options: { echo?: boolean } = {}\n ) {\n this.echo = options.echo ?? false;\n this.emit('transaction', 'start', op ? `${name} (${op})` : name);\n }\n\n // ── Lifecycle / eco ───────────────────────────────────────────────────────\n\n /**\n * Registra o início/fim de uma etapa ou da transaction: espelha a linha no sink de\n * lifecycle, se conectado (é assim que os eventos de performance aparecem nos logs da\n * run no app), e ecoa no terminal com `debug: true` — ou, no modo local, só o FINISH das\n * etapas (`[hobots:step] FINISH …`), para o Studio e o dev verem.\n */\n emit(\n kind: 'transaction' | StepKind,\n phase: 'start' | 'finish',\n label: string,\n startTs?: string,\n endTs?: string,\n status?: StepStatus | string,\n reason?: string\n ): void {\n const durationMs = startTs && endTs ? new Date(endTs).getTime() - new Date(startTs).getTime() : undefined;\n const suffix = (durationMs != null ? ` (${durationMs}ms)` : '') + (reason ? `: ${reason}` : '');\n\n const localFinish = this.echo && kind !== 'transaction' && phase === 'finish';\n if (this.client?.debug || localFinish) {\n const tag = colorize(`[hobots:${kind}] ${phase.toUpperCase()}`, phase === 'finish' ? colorForStatus(status ?? 'ok') : 'cyan');\n console.log(`${tag} ${label}${suffix}`);\n }\n\n const level: RunLogLevel = phase === 'finish' ? levelForStatus(status ?? 'ok') : 'info';\n const message = `[${kind}] ${phase.toUpperCase()} ${label}${suffix}`;\n if (this.lifecycleSink) this.lifecycleSink(level, message);\n // sem sink (transaction fora de run): backlog capado — nunca vai ser drenado\n else if (this.lifecycleBacklog.length < MAX_BACKLOG) this.lifecycleBacklog.push([level, message]);\n }\n\n /** Conecta o espelho de lifecycle (RunReporter) e faz replay do backlog em ordem. */\n setLifecycleSink(sink: LifecycleSink): void {\n this.lifecycleSink = sink;\n const backlog = this.lifecycleBacklog;\n this.lifecycleBacklog = [];\n for (const [level, message] of backlog) sink(level, message);\n }\n\n /** Conecta o pipeline de anexos da run — é o que dá imagem às etapas. */\n setAttachmentSink(sink: AttachmentSink): void {\n this.attachmentSink = sink;\n }\n\n /** Imagem de uma etapa → id do anexo pela run; sem run, descarta com aviso único. */\n attachImage(image: ImageInput): string | undefined {\n if (this.attachmentSink) return this.attachmentSink(image, nowISO());\n if (!this.warnedNoAttachmentSink) {\n this.warnedNoAttachmentSink = true;\n console.warn('[hobots] imagem de etapa descartada — só é suportada dentro de uma execução');\n }\n return undefined;\n }\n\n // ── Etapas ────────────────────────────────────────────────────────────────\n\n /**\n * Conecta a checagem de cancelamento chamada antes de cada etapa nova (inclusive antes de\n * cada nova tentativa) — é assim que `hobots.step()` para uma run cancelada.\n */\n setStepGuard(guard: () => void): void {\n this.stepGuard = guard;\n }\n\n /** A etapa aberta por `step()` (ou `items.each`) no contexto async atual, se houver. */\n currentStep(): Step | undefined {\n return currentStep(this);\n }\n\n /** Faz de `step` a etapa corrente durante `fn` (filhas aninham nela). Sem etapa, só roda `fn`. */\n scope<T>(step: Step | undefined, fn: () => Promise<T>): Promise<T> {\n if (!step) return fn();\n return runWithStepScope({ transaction: this, step }, fn);\n }\n\n /**\n * Abre uma etapa sob a corrente (ou direta da transaction). Interno: o bot usa `step()`; o\n * `items.each` abre com `kind: 'item'` (linhas `[item] START/FINISH`).\n */\n start(op?: string, description?: string, kind: StepKind = 'step'): Step {\n this.stepGuard?.();\n const parent = this.currentStep();\n const step = new Step(this, parent ? parent.stepId : this.stepId, op, description, kind);\n this.steps.push(step);\n this.emit(kind, 'start', lifecycleLabel(kind, op, description));\n return step;\n }\n\n /**\n * Registra a etapa `name` executando `fn(etapa)` até dar certo ou esgotar `retries`\n * tentativas extras (default 1), esperando `retryDelayMs` entre elas (default 5 000).\n * Resolve com o retorno de `fn`.\n *\n * Uma etapa só no waterfall, cobrindo todas as tentativas: `data.attempts` quando houve\n * mais de uma; `warning` com o motivo quando a última deu certo; `error` (e a exceção\n * sobe) quando esgotou; `cancelled` em cancelamento/timeout, que nunca repetem.\n */\n async step<T>(name: string, fn: StepFn<T>, options: StepOptions & StepInternalOptions = {}): Promise<T> {\n const requested = options.retries ?? DEFAULT_STEP_RETRIES;\n const totalRetries = Number.isFinite(requested) ? Math.max(0, Math.floor(requested)) : DEFAULT_STEP_RETRIES;\n const step = this.start(undefined, safeString(name));\n let attempts = 0;\n let lastFailure: { error: unknown } | undefined;\n\n try {\n const result = await retryWithBackoff(\n attempt => {\n attempts = attempt;\n return this.scope(step, async () => fn(step));\n },\n {\n retries: totalRetries,\n delayMs: attempt => resolveDelay(options.retryDelayMs, attempt, DEFAULT_STEP_RETRY_DELAY_MS),\n signal: options.signal,\n wait: options.wait,\n onRetry: (error, attempt, delayMs) => {\n lastFailure = { error };\n options.warn?.(\n `etapa \"${step.description}\": tentativa ${attempt}/${totalRetries + 1} falhou: ${truncate(errorReason(error), 500)} — nova tentativa em ${delayMs}ms`\n );\n },\n }\n );\n this.noteAttempts(step, attempts);\n if (lastFailure && step.status === 'ok') {\n step._setStatus('warning', `tentativa ${attempts - 1}/${totalRetries + 1} falhou: ${errorReason(lastFailure.error)}`);\n }\n step._close();\n return result;\n } catch (error) {\n this.noteAttempts(step, attempts);\n // cancelamento/timeout/shutdown: não é falha da etapa — a run para aqui\n if (isTerminalError(error)) step._setStatus('cancelled')._close();\n else step._failed(error);\n throw error;\n }\n }\n\n private noteAttempts(step: Step, attempts: number): void {\n if (attempts > 1) step._setData('attempts', attempts);\n }\n\n // ── Metadados ─────────────────────────────────────────────────────────────\n\n setStatus(status: string): this {\n this.status = status;\n return this;\n }\n\n // ── Encerramento ──────────────────────────────────────────────────────────\n\n /**\n * Envia já as etapas raiz finalizadas (e todas as descendentes, fechando as que\n * ficaram abertas) como transactions parciais da mesma run (`op` hobots.run.flush,\n * `event_id` novo, até 200 etapas cada) e as tira da memória. Etapas raiz ainda abertas\n * ficam para o próximo flush ou para o `finish()`. É assim que um agente sempre\n * ligado (`start()`), cuja run não termina, entrega as etapas enquanto processa.\n * Devolve quantas etapas foram enviadas (0 sem client, sem nada terminado ou depois do `finish()`).\n */\n flush(): number {\n if (!this.client || this.finished) return 0;\n const ready = new Set<string>();\n for (const step of this.steps) {\n if (step.parentStepId === this.stepId && step.endTimestamp) ready.add(step.stepId);\n }\n if (ready.size === 0) return 0;\n\n // descendentes das raízes prontas (as etapas estão em ordem de criação: o pai vem antes)\n const batch: Step[] = [];\n const remaining: Step[] = [];\n for (const step of this.steps) {\n if (ready.has(step.stepId) || ready.has(step.parentStepId)) {\n ready.add(step.stepId);\n batch.push(step);\n } else {\n remaining.push(step);\n }\n }\n for (const step of batch) step._close();\n this.steps.splice(0, this.steps.length, ...remaining);\n\n for (let i = 0; i < batch.length; i += MAX_STEPS) {\n const chunk = batch.slice(i, i + MAX_STEPS);\n const startTimestamp = chunk.reduce((min, step) => (step.startTimestamp < min ? step.startTimestamp : min), chunk[0]!.startTimestamp);\n const status = chunk.some(step => step.status === 'error') ? 'error' : 'ok';\n this.client.sendTransaction(this.payload(uuid4(), FLUSH_TRANSACTION_OP, status, startTimestamp, nowISO(), chunk));\n }\n return batch.length;\n }\n\n /** Entrega já (com teto) o que está na fila do transport — as transactions parciais inclusive. */\n async drain(timeoutMs: number): Promise<void> {\n await this.client?.flush(timeoutMs);\n }\n\n private payload(eventId: string, op: string | undefined, status: string, startTimestamp: string, timestamp: string, steps: Step[]): TransactionPayload {\n return {\n event_id: eventId,\n name: this.name,\n op,\n status,\n start_timestamp: startTimestamp,\n timestamp,\n steps: steps.map(step => step.toJSON()),\n // sem tags próprias: o client mescla as do processo\n tags: undefined,\n run_id: this.runId,\n };\n }\n\n finish(): void {\n if (this.finished) return;\n this.finished = true;\n\n for (const step of this.steps) step._close();\n\n const endTimestamp = nowISO();\n this.emit(\n 'transaction',\n 'finish',\n this.op ? `${this.name} (${this.op})` : this.name,\n this.startTimestamp,\n endTimestamp,\n this.status\n );\n\n if (!this.client) return;\n // o que sobrou depois dos flushes; acima de 200 etapas, o excedente vai em transactions\n // parciais antes — a final (event_id original) fecha a run com o restante\n const steps = this.steps;\n let first = 0;\n while (steps.length - first > MAX_STEPS) {\n const chunk = steps.slice(first, first + MAX_STEPS);\n const status = chunk.some(step => step.status === 'error') ? 'error' : 'ok';\n this.client.sendTransaction(this.payload(uuid4(), FLUSH_TRANSACTION_OP, status, chunk[0]!.startTimestamp, endTimestamp, chunk));\n first += MAX_STEPS;\n }\n this.client.sendTransaction(this.payload(this.eventId, this.op, this.status, this.startTimestamp, endTimestamp, steps.slice(first)));\n }\n}\n","import type { RunItemStatus } from './protocol';\nimport type { RunItemHandle, RunItemImageOptions, RunItemsEachHandler, RunItemsEachOptions, RunItemsEachResult } from './types';\nimport type { ImageInput } from './attachments';\nimport { isOccurrence, isTerminalError, type Occurrence } from './errors';\nimport type { StepStatus } from '../protocol';\nimport { DEFAULT_STEP_RETRY_DELAY_MS, errorReason, type Step } from '../transaction';\nimport { resolveDelay, retryWithBackoff } from '../retry';\nimport { safeString, truncate, uuid4 } from '../utils';\n\n/** Campo lido por padrão quando `options.id` não é informado (ausente no elemento = sem id). */\nexport const DEFAULT_ITEM_ID_FIELD = 'id';\n/** Tentativas extras por elemento por padrão (`retries: 0` desliga). */\nexport const DEFAULT_EACH_RETRIES = 1;\n/** Separador dos campos de uma chave composta. */\nconst ID_SEPARATOR = '|';\n\n/**\n * O que o loop de `items.each` precisa do reporter. Dentro de uma run o RunReporter\n * liga tudo (itens, steps, progresso, cancelamento); fora dela o `hobots` global passa\n * um sink inerte — o handler roda igual, só não reporta.\n */\nexport interface EachSink {\n report(\n status: RunItemStatus,\n message: string | undefined,\n payload: Record<string, unknown> | undefined,\n id: string | undefined,\n image: ImageInput | undefined\n ): void;\n startStep(op: string, description: string): Step | undefined;\n /** Roda `fn` com `step` como etapa corrente — `hobots.step` no handler do item aninha nela. */\n stepScope(step: Step | undefined, fn: () => Promise<unknown>): Promise<unknown>;\n /** Declara o total só se o bot ainda não declarou um (o dele vence). */\n declareTotal(total: number): void;\n advance(): void;\n checkCanceled(): void;\n isAborted(): boolean;\n logInfo(message: string): void;\n logWarning(message: string): void;\n logError(message: string): void;\n /** Espera cancelável entre as tentativas de um elemento (o `ctx.sleep` da run). */\n sleep(ms: number): Promise<void>;\n /** Ids já concluídos neste trabalho (reexecução); undefined = sem consulta/falhou. Nunca lança. */\n doneItemIds(): Promise<Set<string> | undefined>;\n /** `hobots.flush()` da run — chamado ao fim de cada ciclo (opção `flush`). Nunca lança. */\n flush(): Promise<void>;\n}\n\n/** Mensagem legível de qualquer valor lançado (o `addItem` trunca/scrubba depois). */\nexport function thrownMessage(error: unknown): string {\n if (error instanceof Error) return error.message || error.name;\n return safeString(error);\n}\n\nclass ItemHandle<T> implements RunItemHandle<T> {\n /** A identidade resolvida por `options.id` ou, sem ela, uma gerada — a mesma em todas as tentativas. */\n readonly id: string;\n reported = false;\n status: RunItemStatus | undefined;\n message: string | undefined;\n attempt = 1;\n private accumulated: Record<string, unknown> = {};\n\n constructor(\n readonly value: T,\n readonly index: number,\n id: string | undefined,\n readonly step: Step | undefined,\n private readonly basePayload: Record<string, unknown> | undefined,\n private readonly sink: EachSink\n ) {\n this.id = id ?? uuid4();\n }\n\n data(payload: Record<string, unknown>): void {\n Object.assign(this.accumulated, payload);\n }\n\n succeeded(payload?: Record<string, unknown>, options?: RunItemImageOptions): void {\n this.record('succeeded', undefined, payload, options?.image);\n }\n\n failed(message: string, payload?: Record<string, unknown>, options?: RunItemImageOptions): void {\n this.record('failed', message, payload, options?.image);\n // o handler decidiu que é falha sem lançar: a etapa acompanha com o motivo\n // (a imagem fica só no item — um upload por print, sem duplicar na etapa)\n if (this.step && this.step.status !== 'error') this.step._setStatus('error', message);\n }\n\n occurrence(message: string, payload?: Record<string, unknown>, options?: RunItemImageOptions): void {\n this.record('occurrence', message, payload, options?.image);\n if (this.step && this.step.status === 'ok') this.step._setStatus('warning', message);\n }\n\n /** Nova tentativa: o desfecho da anterior não vale (o id é o mesmo, o último reporte vence). */\n _nextAttempt(attempt: number): void {\n this.attempt = attempt;\n this.reported = false;\n this.status = undefined;\n this.message = undefined;\n this.accumulated = {};\n if (this.step && (this.step.status === 'error' || this.step.status === 'warning')) {\n this.step._setStatus('ok');\n this.step._deleteData('message');\n }\n }\n\n private record(\n status: RunItemStatus,\n message: string | undefined,\n payload: Record<string, unknown> | undefined,\n image: ImageInput | undefined\n ): void {\n this.reported = true;\n this.status = status;\n this.message = message;\n const merged = { ...(this.basePayload ?? {}), ...this.accumulated, ...(payload ?? {}) };\n this.sink.report(status, message, Object.keys(merged).length > 0 ? merged : undefined, this.id, image);\n }\n}\n\n/**\n * Payload base padrão (sem `options.payload`): os campos do elemento quando ele é um objeto simples —\n * protótipo `Object.prototype` ou `null`. Instância de classe (Locator, ElementHandle, Date…), array,\n * Map e primitivo ficam de fora: não viram colunas nem arriscam serializar um objeto do navegador.\n */\nexport function defaultPayload(element: unknown): Record<string, unknown> | undefined {\n if (typeof element !== 'object' || element === null) return undefined;\n const proto = Object.getPrototypeOf(element) as unknown;\n if (proto !== Object.prototype && proto !== null) return undefined;\n const copy = { ...(element as Record<string, unknown>) };\n return Object.keys(copy).length > 0 ? copy : undefined;\n}\n\nfunction basePayload<T>(spec: RunItemsEachOptions<T>['payload'], element: T, index: number): Record<string, unknown> | undefined {\n if (spec === false) return undefined;\n if (spec === undefined) return defaultPayload(element);\n return spec(element, index);\n}\n\nfunction field(element: unknown, name: string): { present: boolean; value: unknown } {\n if (typeof element !== 'object' || element === null) return { present: false, value: undefined };\n const record = element as Record<string, unknown>;\n return { present: name in record, value: record[name] };\n}\n\n/**\n * `options.id` → identidade do item (undefined = o SDK gera uma, e o item nunca é pulado).\n * Campo (ou campos) inexistente(s) no elemento: com `id` explícito é erro do bot (lança, fora\n * da proteção do loop — como já valia para a função de `id`); com o padrão (`id` do\n * elemento) é só \"sem id\".\n */\nexport function resolveId<T>(spec: RunItemsEachOptions<T>['id'], element: T, index: number, explicit: boolean): string | undefined {\n if (spec === null) return undefined;\n let raw: unknown;\n if (typeof spec === 'function') {\n raw = spec(element, index);\n } else {\n const fields = spec === undefined ? [DEFAULT_ITEM_ID_FIELD] : typeof spec === 'string' ? [spec] : spec;\n const parts: string[] = [];\n for (const name of fields) {\n const { present, value } = field(element, name);\n if (!present || value === null || value === undefined) {\n if (explicit) {\n throw new Error(\n `items.each: elemento #${index + 1} não tem o campo \"${name}\" informado em id — passe o nome certo, uma lista de campos ou uma função (elemento, índice) => id`\n );\n }\n return undefined;\n }\n parts.push(safeString(value));\n }\n raw = parts.join(ID_SEPARATOR);\n }\n if (raw === null || raw === undefined) return undefined;\n const text = safeString(raw);\n return text.length > 0 ? text : undefined;\n}\n\n/** `length` numérica (array, lista) vira o total do progresso; iteráveis sem tamanho não declaram nada. */\nfunction knownLength(list: unknown): number | undefined {\n const length = (list as { length?: unknown } | null)?.length;\n return typeof length === 'number' && Number.isInteger(length) && length >= 1 ? length : undefined;\n}\n\n/**\n * Desfecho do item → status da linha `[item] FINISH`: sucesso sai em `success`, ocorrência em\n * `warning` e falha em `error` (os mesmos níveis do FINISH de uma etapa).\n */\nconst ITEM_LOG_STATUS: Record<RunItemStatus, StepStatus> = { succeeded: 'ok', occurrence: 'warning', failed: 'error' };\n\n/** A linha de fim do item segue o desfecho dele, não o status da etapa. */\nfunction setItemOutcome(step: Step, status: RunItemStatus, message: string | undefined): void {\n step._setOutcome(ITEM_LOG_STATUS[status], status === 'succeeded' ? undefined : message);\n}\n\nfunction skippedMessage(count: number): string {\n if (count === 1) return '1 item pulado: já concluído neste trabalho numa execução anterior';\n return `${count} itens pulados: já concluídos neste trabalho numa execução anterior`;\n}\n\n/**\n * Processa uma lista item a item com o contrato da plataforma garantido pelo SDK:\n * cada elemento vira uma etapa e um item. O handler recebe `(item, index)`: o elemento\n * em `item.value` (seus campos viram o payload base do item, salvo `options.payload`). O handler **retornou** → `succeeded`; **lançou**\n * → nova tentativa (`retries`, default 1; `0` desliga; `retryDelayMs` entre elas, default\n * 5 000) e, esgotadas, item `failed` com a mensagem do erro, etapa `error`, e o loop\n * **segue para o próximo**; lançou `Occurrence` → item `occurrence` na hora, sem nova\n * tentativa. A lista inteira é processada e o progresso avança a cada elemento. Só o\n * cancelamento (RunCanceled/abort), o timeout e o shutdown interrompem o loop.\n *\n * Com `options.id` (campo, chave composta ou função; default: o campo `id` do elemento),\n * a reexecução do mesmo trabalho pula o item que já deu `succeeded`/`occurrence` — só\n * `failed` roda de novo (`skipDone: false` desliga). O pulado não entra no progresso: com\n * tamanho conhecido a lista é filtrada antes e o total é só o que vai rodar (a Central não\n * mostra \"sem reporte\" para o que já terminou antes). Ao fim de cada ciclo faz o flush da\n * run (`flush: false` desliga).\n */\nexport async function eachItem<T>(\n list: Iterable<T> | AsyncIterable<T>,\n handler: RunItemsEachHandler<T>,\n options: RunItemsEachOptions<T>,\n sink: EachSink\n): Promise<RunItemsEachResult> {\n const result: RunItemsEachResult = { total: 0, succeeded: 0, failed: 0, occurrence: 0, skipped: 0 };\n const requested = options.retries ?? DEFAULT_EACH_RETRIES;\n const totalRetries = Number.isFinite(requested) ? Math.max(0, Math.floor(requested)) : DEFAULT_EACH_RETRIES;\n const explicitId = options.id !== undefined;\n // o que já deu certo neste trabalho (reexecução) — consulta única; undefined = sem consulta/falhou\n const done = options.skipDone === false ? undefined : await sink.doneItemIds();\n const isDone = (id: string | undefined): boolean => id !== undefined && done !== undefined && done.has(id);\n const length = knownLength(list);\n\n // O pulado (já concluído numa execução anterior deste trabalho) fica FORA do progresso: a\n // Central conta \"sem reporte\" = progresso - itens reportados, e o pulado não reporta nesta run.\n let entries: Iterable<EachEntry<T>> | AsyncIterable<EachEntry<T>>;\n if (length !== undefined && done !== undefined && done.size > 0) {\n // tamanho conhecido: filtra antes do loop e o total da barra é só o que vai rodar\n const pending: EachEntry<T>[] = [];\n let position = 0;\n for await (const element of list) {\n const id = resolveId(options.id, element, position, explicitId);\n if (isDone(id)) result.skipped += 1;\n else pending.push({ element, index: position, id });\n position += 1;\n }\n if (options.progress !== false && pending.length > 0) sink.declareTotal(pending.length);\n entries = pending;\n } else {\n // sem tamanho (gerador, stream): segue preguiçoso, o pulado só não avança o progresso\n if (options.progress !== false && length !== undefined) sink.declareTotal(length);\n entries = lazyEntries(list, options.id, explicitId);\n }\n\n for await (const { element, index, id } of entries) {\n sink.checkCanceled();\n if (isDone(id)) {\n result.skipped += 1;\n continue;\n }\n const description = options.description?.(element, index) ?? id ?? `#${index + 1}`;\n const step = sink.startStep(options.op ?? 'item', description);\n const handle = new ItemHandle(element, index, id, step, basePayload(options.payload, element, index), sink);\n const current = index;\n let attempts = 0;\n let lastFailure: { error: unknown } | undefined;\n\n try {\n await retryWithBackoff(\n attempt => {\n attempts = attempt;\n if (attempt > 1) handle._nextAttempt(attempt);\n return sink.stepScope(step, async () => handler(handle, current));\n },\n {\n retries: totalRetries,\n delayMs: attempt => resolveDelay(options.retryDelayMs, attempt, DEFAULT_STEP_RETRY_DELAY_MS),\n // sem nova tentativa: ocorrência (regra de negócio), desfecho já registrado pelo\n // handler (ele decidiu) ou run abortada (o erro é efeito do cancelamento)\n shouldRetry: error => !isOccurrence(error) && !handle.reported && !sink.isAborted(),\n wait: ms => sink.sleep(ms),\n onRetry: (error, attempt, delayMs) => {\n lastFailure = { error };\n sink.logWarning(\n `item ${description}: tentativa ${attempt}/${totalRetries + 1} falhou: ${truncate(errorReason(error), 500)} — nova tentativa em ${delayMs}ms`\n );\n },\n }\n );\n if (!handle.reported) handle.succeeded();\n if (step) {\n noteAttempts(step, attempts);\n if (lastFailure && step.status === 'ok') {\n step._setStatus('warning', `tentativa ${attempts - 1}/${totalRetries + 1} falhou: ${errorReason(lastFailure.error)}`);\n }\n }\n } catch (error) {\n if (isTerminalError(error) || sink.isAborted()) {\n // cancelamento/timeout/shutdown: não é falha do item — a run para aqui\n step?._setStatus('cancelled')._close();\n throw error;\n }\n if (step) noteAttempts(step, attempts);\n if (isOccurrence(error)) {\n // regra de negócio: ocorrência, sem log de erro — a etapa vira warning pelo handle\n const occurrence = error as Occurrence;\n if (!handle.reported) handle.occurrence(occurrence.message, occurrence.payload, { image: occurrence.image });\n } else {\n const message = thrownMessage(error);\n if (!handle.reported) handle.failed(message);\n // lançou: a etapa é erro mesmo que o handler já tenha registrado ocorrência\n // (o `_failed` fecha a etapa: a linha de fim do item sai aqui, com o desfecho dele)\n if (step) {\n /* v8 ignore start -- o handle sempre está reportado aqui (failed/occurrence acima); o ?? só satisfaz o tipo */\n setItemOutcome(step, handle.status ?? 'failed', handle.message);\n /* v8 ignore stop */\n step._failed(error);\n }\n sink.logError(`item ${description} falhou: ${message}`);\n }\n }\n\n /* v8 ignore start -- o handle sempre está reportado aqui (succeeded/failed/occurrence acima); o ?? só satisfaz o tipo */\n const final: RunItemStatus = handle.status ?? 'succeeded';\n /* v8 ignore stop */\n if (step) {\n setItemOutcome(step, final, handle.message);\n step._close();\n }\n if (options.progress !== false) sink.advance();\n result.total += 1;\n result[final] += 1;\n // fim do ciclo: a etapa do item, o item e os logs saem agora, não no fim da run\n if (options.flush !== false) await sink.flush();\n }\n // os pulados também contam no total do resultado (não no progresso)\n result.total += result.skipped;\n if (result.skipped > 0) sink.logInfo(skippedMessage(result.skipped));\n return result;\n}\n\n/** Elemento da lista com a posição ORIGINAL (`item.index`) e o id resolvido uma única vez. */\ninterface EachEntry<T> {\n element: T;\n index: number;\n id: string | undefined;\n}\n\nasync function* lazyEntries<T>(\n list: Iterable<T> | AsyncIterable<T>,\n spec: RunItemsEachOptions<T>['id'],\n explicit: boolean\n): AsyncGenerator<EachEntry<T>> {\n let index = 0;\n for await (const element of list) {\n yield { element, index, id: resolveId(spec, element, index, explicit) };\n index += 1;\n }\n}\n\nfunction noteAttempts(step: Step, attempts: number): void {\n if (attempts > 1) step._setData('attempts', attempts);\n}\n","import type { FileRef } from './protocol';\nimport { TasksApiError, type RunTransport } from './api';\nimport { runCanceledError } from './errors';\nimport { isLocalRun } from '../env';\n\n/** Pasta onde o Studio deixa os arquivos escolhidos localmente: `<dir>/<id>/<nome>`. */\nexport const LOCAL_FILES_DIR_ENV = 'HOBOTS_LOCAL_FILES_DIR';\n/**\n * Sem nenhum byte novo por este tempo, o download é abortado (e pode ser tentado de novo).\n * Não é um teto total — arquivo grande em rede lenta não morre por isso. Espelha o timeout\n * de socket do SDK Python.\n */\nexport const FILE_DOWNLOAD_IDLE_TIMEOUT_MS = 60_000;\n\nconst UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\n\nexport interface FileDownloadOptions {\n /**\n * Destino da cópia: uma pasta existente (ou terminada em `/`) recebe o arquivo com o nome\n * original; qualquer outro caminho é o arquivo final. Omitido: pasta temporária da\n * execução, apagada quando ela termina.\n */\n dest?: string;\n}\n\n/**\n * Arquivos dos campos de upload do formulário (`hobots.files`). O valor do campo nos\n * params é um `FileRef` (ou uma lista deles); `download` traz o arquivo para o disco\n * desta máquina — do S3 (enviado pela Central) ou da pasta do Studio (mesmo computador)\n * — e o consome na origem: cada arquivo é baixado uma vez.\n */\nexport interface RunFiles {\n /** Todos os arquivos dos params (campos de topo, valor único ou lista), na ordem dos campos. */\n list(): FileRef[];\n /** O arquivo do campo (campo único), a lista (campo \"vários arquivos\") ou undefined. */\n get(field: string): FileRef | FileRef[] | undefined;\n /**\n * Baixa um arquivo e resolve com o caminho local. Aceita o `FileRef` ou o nome de um\n * campo de arquivo único (para campo com vários arquivos, use `downloadAll`). Só depois\n * da cópia completa e conferida o arquivo é consumido na origem — uma falha não perde\n * nada e pode ser tentada de novo. Respeita o cancelamento da execução.\n */\n download(refOrField: FileRef | string, options?: FileDownloadOptions): Promise<string>;\n /** Baixa todos os arquivos do campo (único ou lista), em ordem. `dest` aqui é uma pasta. */\n downloadAll(field: string, options?: FileDownloadOptions): Promise<string[]>;\n /** Conteúdo do arquivo em memória — baixa, lê e apaga a cópia temporária. */\n read(refOrField: FileRef | string): Promise<Buffer>;\n}\n\n/** O valor tem a forma de um arquivo de campo de upload (mesma regra do `@workspace/task-forms`). */\nexport function isFileRef(value: unknown): value is FileRef {\n if (!value || typeof value !== 'object' || Array.isArray(value)) return false;\n const ref = value as Record<string, unknown>;\n return (\n typeof ref.id === 'string' &&\n typeof ref.name === 'string' &&\n typeof ref.size === 'number' &&\n typeof ref.contentType === 'string' &&\n (ref.storage === 's3' || ref.storage === 'local')\n );\n}\n\n/** Valor de um campo de arquivo: FileRef, lista só de FileRef (vazia inclusive) ou undefined. */\nexport function fileField(params: Record<string, unknown>, field: string): FileRef | FileRef[] | undefined {\n if (!Object.prototype.hasOwnProperty.call(params, field)) return undefined;\n const value = params[field];\n if (isFileRef(value)) return value;\n if (Array.isArray(value) && value.every(isFileRef)) return value;\n return undefined;\n}\n\nexport function collectFileRefs(params: Record<string, unknown>): FileRef[] {\n const refs: FileRef[] = [];\n for (const field of Object.keys(params)) {\n const value = fileField(params, field);\n if (value !== undefined) refs.push(...(Array.isArray(value) ? value : [value]));\n }\n return refs;\n}\n\n/** Nome seguro para o disco: só o último segmento, sem caracteres proibidos no Windows. */\nexport function safeFileName(name: string, fallback: string): string {\n // eslint-disable-next-line no-control-regex\n const cleaned = name.replace(/^.*[\\\\/]/, '').replace(/[\\u0000-\\u001f<>:\"|?*]/g, '_').trim();\n return cleaned === '' || cleaned === '.' || cleaned === '..' ? fallback : cleaned;\n}\n\n/** `candidate` resolvido fica estritamente dentro de `root` (nunca a própria raiz, nunca acima). */\nexport function isInsideDir(root: string, candidate: string, sep: string): boolean {\n const base = root.endsWith(sep) ? root : root + sep;\n return candidate.startsWith(base) && candidate.length > base.length;\n}\n\nfunction unavailableLocal(ref: FileRef): Error {\n return new Error(`arquivo \"${ref.name}\" enviado pelo Studio de outro computador ou já consumido`);\n}\n\n/**\n * Modo local (`HOBOTS_LOCAL_RUN=1`): o FileRef `local` pode trazer a chave extra `path` — o\n * caminho do próprio arquivo (a CLI `hobots run --file` monta assim). Fora do modo local a\n * chave é ignorada e vale só o formato `<HOBOTS_LOCAL_FILES_DIR>/<uuid>/<nome>`.\n */\nfunction localRunPath(ref: FileRef): string | undefined {\n if (!isLocalRun()) return undefined;\n const path = (ref as { path?: unknown }).path;\n return typeof path === 'string' && path.trim() !== '' ? path : undefined;\n}\n\n/** Erro `.code` do Node (ENOENT…) sem depender do tipo. */\nfunction errorCode(error: unknown): unknown {\n return (error as { code?: unknown } | null)?.code;\n}\n\nexport interface RunFileStoreDeps {\n api: RunTransport;\n runId: string;\n params: Record<string, unknown>;\n signal: AbortSignal;\n /** Aviso na linha de log da execução (ex.: confirmação que não chegou ao servidor). */\n warn: (message: string) => void;\n /** Só para testes: default `FILE_DOWNLOAD_IDLE_TIMEOUT_MS`. */\n idleTimeoutMs?: number;\n}\n\n/**\n * Estado dos arquivos de UMA execução: a pasta temporária (criada sob demanda) e a\n * implementação de `RunFiles`. O runner chama `cleanup()` no fim da execução.\n */\nexport class RunFileStore {\n readonly files: RunFiles;\n private tempDir: Promise<string> | undefined;\n\n constructor(private readonly deps: RunFileStoreDeps) {\n this.files = {\n list: () => collectFileRefs(deps.params),\n get: field => fileField(deps.params, field),\n // async: erro de uso (campo sem arquivo, valor inválido) chega como Promise rejeitada, nunca síncrono\n download: async (refOrField, options) => this.download(this.single(refOrField), options?.dest),\n downloadAll: async (field, options) => this.downloadAll(field, options?.dest),\n read: async refOrField => this.read(this.single(refOrField)),\n };\n }\n\n /** Apaga a pasta temporária da execução (cópias que o bot não levou para `dest`). Nunca lança. */\n async cleanup(): Promise<void> {\n const pending = this.tempDir;\n this.tempDir = undefined;\n if (!pending) return;\n try {\n const { rm } = await import('node:fs/promises');\n await rm(await pending, { recursive: true, force: true });\n } catch {\n // limpeza é conforto: o sistema operacional recolhe a pasta temporária\n }\n }\n\n private field(field: string): FileRef | FileRef[] {\n const value = fileField(this.deps.params, field);\n if (value === undefined) throw new Error(`campo \"${field}\" não tem arquivo nos params`);\n return value;\n }\n\n private single(refOrField: FileRef | string): FileRef {\n if (typeof refOrField === 'string') {\n const value = this.field(refOrField);\n if (Array.isArray(value)) {\n throw new Error(`campo \"${refOrField}\" tem vários arquivos — use downloadAll(\"${refOrField}\") ou passe um item da lista`);\n }\n return value;\n }\n if (!isFileRef(refOrField)) throw new TypeError('esperado um FileRef ou o nome de um campo de arquivo');\n return refOrField;\n }\n\n private async downloadAll(field: string, dest: string | undefined): Promise<string[]> {\n const value = this.field(field);\n const refs = Array.isArray(value) ? value : [value];\n const paths: string[] = [];\n // aqui `dest` é sempre pasta: cada arquivo entra com o próprio nome\n for (const ref of refs) paths.push(await this.download(ref, dest, true));\n return paths;\n }\n\n private async read(ref: FileRef): Promise<Buffer> {\n const { readFile, rm } = await import('node:fs/promises');\n const { dirname } = await import('node:path');\n const path = await this.download(ref, undefined);\n try {\n return await readFile(path);\n } finally {\n // sem `dest`, a cópia mora numa subpasta só dela dentro da pasta temporária da run\n await rm(dirname(path), { recursive: true, force: true });\n }\n }\n\n private async download(ref: FileRef, dest: string | undefined, destIsDir = false): Promise<string> {\n this.checkCanceled();\n const target = await this.resolveTarget(ref, dest, destIsDir);\n if (ref.storage === 'local') await this.copyLocal(ref, target);\n else await this.downloadS3(ref, target); // no modo local o transporte recusa com o nome do arquivo\n return target;\n }\n\n private checkCanceled(): void {\n if (this.deps.signal.aborted) throw runCanceledError();\n }\n\n private runTempDir(): Promise<string> {\n this.tempDir ??= (async () => {\n const { mkdtemp } = await import('node:fs/promises');\n const { tmpdir } = await import('node:os');\n const { join } = await import('node:path');\n return mkdtemp(join(tmpdir(), 'hobots-files-'));\n })();\n return this.tempDir;\n }\n\n private async resolveTarget(ref: FileRef, dest: string | undefined, destIsDir: boolean): Promise<string> {\n const { mkdir, mkdtemp, stat } = await import('node:fs/promises');\n const { dirname, join, resolve } = await import('node:path');\n const name = safeFileName(ref.name, 'arquivo');\n if (dest === undefined) {\n // uma subpasta por download: dois arquivos com o mesmo nome não colidem\n return join(await mkdtemp(join(await this.runTempDir(), 'f-')), name);\n }\n const isDir =\n destIsDir || dest.endsWith('/') || dest.endsWith('\\\\') || (await stat(dest).catch(() => undefined))?.isDirectory() === true;\n if (isDir) {\n await mkdir(dest, { recursive: true });\n return resolve(dest, name);\n }\n await mkdir(dirname(resolve(dest)), { recursive: true });\n return resolve(dest);\n }\n\n /** storage 's3': URL pré-assinada → GET em streaming → confere o tamanho → só então DELETE. */\n private async downloadS3(ref: FileRef, target: string): Promise<void> {\n const { api, runId, signal } = this.deps;\n let expected: number;\n let url: string;\n try {\n const info = await api.requestFileDownload(runId, ref.id, signal);\n expected = info.size >= 0 ? info.size : ref.size;\n url = info.url;\n } catch (error) {\n throw this.translate(error, ref);\n }\n\n const { open, rename, rm } = await import('node:fs/promises');\n const part = `${target}.part`;\n const idleTimeoutMs = this.deps.idleTimeoutMs ?? FILE_DOWNLOAD_IDLE_TIMEOUT_MS;\n const controller = new AbortController();\n let timedOut = false;\n let timer: ReturnType<typeof setTimeout> | undefined;\n const arm = (): void => {\n clearTimeout(timer);\n timer = setTimeout(() => {\n timedOut = true;\n controller.abort();\n }, idleTimeoutMs);\n };\n const onCancel = (): void => controller.abort();\n signal.addEventListener('abort', onCancel, { once: true });\n try {\n arm();\n const response = await api.fetchFile(url, controller.signal);\n const handle = await open(part, 'w');\n let written = 0;\n try {\n const reader = response.body?.getReader();\n // cancelamento/ociosidade param a leitura mesmo onde o fetch não liga o signal ao corpo\n const stopReading = (): void => void reader?.cancel().catch(() => undefined);\n controller.signal.addEventListener('abort', stopReading, { once: true });\n for (;;) {\n const chunk = reader ? await reader.read() : { done: true as const, value: undefined };\n if (chunk.done) break;\n arm();\n written += chunk.value.byteLength;\n if (written > expected) {\n // maior que o anunciado: não enche o disco à toa\n stopReading();\n break;\n }\n await handle.write(chunk.value);\n }\n } finally {\n await handle.close();\n }\n if (written !== expected) {\n throw new Error(`tamanho divergente no download de \"${ref.name}\": recebidos ${written} bytes, esperados ${expected}`);\n }\n await rename(part, target);\n } catch (error) {\n await rm(part, { force: true });\n if (signal.aborted) throw runCanceledError();\n if (timedOut) {\n throw new Error(`download de \"${ref.name}\" parado há ${idleTimeoutMs / 1000}s — tente de novo`);\n }\n throw this.translate(error, ref);\n } finally {\n clearTimeout(timer);\n signal.removeEventListener('abort', onCancel);\n }\n\n try {\n await api.confirmFileDownload(runId, ref.id);\n } catch (error) {\n // o arquivo já está no disco: a falha só adia a limpeza (o servidor apaga quando expirar)\n this.deps.warn(`arquivo \"${ref.name}\" baixado, mas a confirmação ao servidor falhou: ${String(error)}`);\n }\n }\n\n /**\n * storage 'local': copia o único arquivo de `$HOBOTS_LOCAL_FILES_DIR/<id>/` e apaga a pasta de\n * origem. No modo local, um FileRef com `path` copia direto desse caminho, sem apagar a origem.\n */\n private async copyLocal(ref: FileRef, target: string): Promise<void> {\n const direct = localRunPath(ref);\n if (direct !== undefined) {\n await this.copyFromPath(ref, direct, target);\n return;\n }\n const base = process.env[LOCAL_FILES_DIR_ENV];\n if (!base) throw unavailableLocal(ref);\n const { copyFile, readdir, rename, rm, stat } = await import('node:fs/promises');\n const { join, resolve, sep } = await import('node:path');\n const root = resolve(base);\n const folder = resolve(root, ref.id);\n // duas travas: a pasta resolvida fica DENTRO do diretório (pega `..`, caminho absoluto)\n // e o id tem a forma que o Studio gera (uuid) — nada além disso vira caminho no disco\n if (!isInsideDir(root, folder, sep) || !UUID_RE.test(ref.id)) {\n throw new Error(`id de arquivo local inválido: ${JSON.stringify(ref.id)}`);\n }\n\n let names: string[];\n try {\n // só arquivos regulares: link simbólico não conta (não copia nada de fora da pasta)\n names = (await readdir(folder, { withFileTypes: true })).filter(entry => entry.isFile()).map(entry => entry.name);\n } catch (error) {\n if (errorCode(error) === 'ENOENT' || errorCode(error) === 'ENOTDIR') throw unavailableLocal(ref);\n throw error;\n }\n if (names.length === 0) throw unavailableLocal(ref);\n if (names.length > 1) throw new Error(`pasta do arquivo \"${ref.name}\" tem ${names.length} arquivos — esperado 1`);\n\n this.checkCanceled();\n const part = `${target}.part`;\n try {\n await copyFile(join(folder, names[0]!), part);\n const { size } = await stat(part);\n if (size !== ref.size) {\n throw new Error(`tamanho divergente na cópia de \"${ref.name}\": copiados ${size} bytes, esperados ${ref.size}`);\n }\n await rename(part, target);\n } catch (error) {\n await rm(part, { force: true });\n throw error;\n }\n await rm(folder, { recursive: true, force: true });\n }\n\n /**\n * Modo local: cópia do arquivo apontado por `path` (teste roda várias vezes — a fonte fica).\n * Sem conferência de tamanho: o `size` do FileRef é informativo aqui.\n */\n private async copyFromPath(ref: FileRef, path: string, target: string): Promise<void> {\n const { copyFile, rename, rm, stat } = await import('node:fs/promises');\n const { resolve } = await import('node:path');\n const source = resolve(path);\n const info = await stat(source).catch(() => undefined);\n if (!info?.isFile()) throw new Error(`arquivo \"${ref.name}\" não encontrado em ${path}`);\n this.checkCanceled();\n const part = `${target}.part`;\n try {\n await copyFile(source, part);\n await rename(part, target);\n } catch (error) {\n await rm(part, { force: true });\n throw error;\n }\n }\n\n private translate(error: unknown, ref: FileRef): unknown {\n if (this.deps.signal.aborted) return runCanceledError();\n if (error instanceof TasksApiError && error.status === 410) {\n return new TasksApiError(`arquivo \"${ref.name}\" já baixado ou expirado`, 410);\n }\n if (error instanceof TasksApiError && error.status === 404) {\n return new TasksApiError(`arquivo \"${ref.name}\" não encontrado nesta execução`, 404);\n }\n return error;\n }\n}\n","import type {\n RunAttachmentContentType,\n RunError,\n RunItemInput,\n RunItemsDoneResponse,\n RunItemStatus,\n RunProgress,\n RunUpdateRequest,\n RunLogEntry,\n RunLogLevel,\n} from './protocol';\nimport type { RunContext, RunItems, RunLogger, RunProgressReporter } from './types';\nimport { TasksApiError, type RunTransport } from './api';\nimport { eachItem, thrownMessage, type EachSink } from './each';\nimport { RunFileStore } from './files';\nimport { runCanceledError } from './errors';\nimport { retryWithBackoff, type RetryOptions } from '../retry';\nimport {\n ATTACHMENT_DRAIN_MS,\n MAX_ATTACHMENTS_PER_RUN,\n MAX_ATTACHMENT_BYTES,\n MAX_CAPTION_CHARS,\n MAX_CONCURRENT_UPLOADS,\n readPngDimensions,\n sniffContentType,\n toBytes,\n toImageAttachment,\n isImageAttachment,\n type AttachFailureReason,\n type AttachInput,\n type ImageAttachment,\n type ImageInput,\n} from './attachments';\nimport { colorize, nowISO, safeString, truncate, unrefTimer, uuid4, type Logger } from '../utils';\nimport { scrubSecrets } from '../scrub';\nimport type { Transaction } from '../transaction';\nimport { WIRE_LIMITS } from '../wire-limits';\n\nconst LOG_LEVEL_COLOR = {\n debug: 'gray',\n info: 'cyan',\n warning: 'yellow',\n error: 'red',\n success: 'green',\n} as const;\n\n/** `hobots.log.info('a', 1, {b: 2})` → `'a 1 {\"b\":2}'` (estilo `console.log`), sem lançar. */\nexport function joinLogArgs(message: unknown, rest: unknown[]): string {\n if (rest.length === 0) return safeString(message);\n return [message, ...rest].map(safeString).join(' ');\n}\n\n/**\n * Separa o `hobots.image(...)` passado como último argumento do texto da linha. Só a\n * imagem, sem texto (`log.info(hobots.image(png, { caption }))`): a legenda vira a\n * mensagem, como o antigo `attach` fazia.\n */\nexport function splitLogArgs(message: unknown, rest: unknown[]): { text: string; image?: ImageAttachment } {\n const args = [message, ...rest];\n const last = args[args.length - 1];\n if (!isImageAttachment(last)) return { text: joinLogArgs(message, rest) };\n const text = args.slice(0, -1);\n if (text.length === 0) return { text: last.caption !== undefined ? safeString(last.caption) : 'captura de tela', image: last };\n return { text: joinLogArgs(text[0], text.slice(1)), image: last };\n}\n\n/** Ecoa o log da run no terminal local, colorido por nível — o buffer/envio ao servidor é independente disso. */\nexport function printRunLog(level: RunLogLevel, message: string): void {\n const line = colorize(`[hobots] ${level.toUpperCase()}`, LOG_LEVEL_COLOR[level]);\n const method = level === 'warning' ? 'warn' : level === 'success' ? 'info' : level;\n console[method](line, message);\n}\n\n/** Prefixo da linha de progresso legível por máquina no stdout. */\nexport const PROGRESS_LINE_PREFIX = '[hobots:progress]';\n/** Entre dois ecos de progresso intermediários (o total novo e o último valor saem sempre). */\nconst PROGRESS_PRINT_THROTTLE_MS = 250;\n\n/**\n * Linha de progresso no stdout, sem cor: `[hobots:progress] 10/100`. O Hobots Studio lê esta\n * linha para mostrar barra e estimativa quando o bot roda localmente; o envio ao servidor é\n * independente. Espelha o `print_run_progress` do SDK Python.\n */\nexport function printRunProgress(current: number, total: number): void {\n console.log(`${PROGRESS_LINE_PREFIX} ${current}/${total}`);\n}\n\n/**\n * Sleep que respeita o ctx.signal — rejeita com RunCanceled no abort.\n * O timer NÃO é unref'd de propósito: uma run em execução é trabalho legítimo e\n * deve segurar o processo vivo mesmo com o polling já parado (shutdown gracioso).\n */\nfunction cancelableSleep(ms: number, signal: AbortSignal): Promise<void> {\n return new Promise<void>((resolve, reject) => {\n if (signal.aborted) {\n reject(runCanceledError());\n return;\n }\n const onAbort = (): void => {\n clearTimeout(timer);\n reject(runCanceledError());\n };\n const timer = setTimeout(() => {\n signal.removeEventListener('abort', onAbort);\n resolve();\n }, ms);\n signal.addEventListener('abort', onAbort, { once: true });\n });\n}\n\nconst DEFAULT_LOG_FLUSH_INTERVAL_MS = 2_000;\nconst DEFAULT_CANCEL_CHECK_INTERVAL_MS = 5_000;\nconst MIN_CANCEL_CHECK_INTERVAL_MS = 1_000;\n// teto: o PATCH periódico é o sinal de vida da run — o servidor marca como\n// encerrada inesperadamente após ~120s sem reporte, então o intervalo não pode chegar perto disso\nconst MAX_CANCEL_CHECK_INTERVAL_MS = 15_000;\nconst MAX_LOG_MESSAGE_CHARS = WIRE_LIMITS.MAX_LOG_MESSAGE_CHARS;\nconst MAX_LOGS_PER_PATCH = WIRE_LIMITS.MAX_LOGS_PER_PATCH;\nconst FLUSH_AT_BUFFERED = 20;\n\n// Itens de execução — os MESMOS limites do servidor (WIRE_LIMITS; a api importa de hobots/protocol)\nconst MAX_ITEMS_PER_REQUEST = WIRE_LIMITS.MAX_ITEMS_PER_REQUEST;\nconst MAX_ITEMS_DONE_PER_PAGE = WIRE_LIMITS.MAX_ITEMS_DONE_PER_PAGE;\nconst MAX_ITEM_MESSAGE_CHARS = WIRE_LIMITS.MAX_ITEM_MESSAGE_CHARS;\nconst MAX_ITEM_PAYLOAD_BYTES = WIRE_LIMITS.MAX_ITEM_PAYLOAD_BYTES;\nconst ITEMS_FLUSH_AT_BUFFERED = 100;\n/** Teto do dreno de itens antes do PATCH terminal — como o dreno de anexos. */\nconst ITEMS_DRAIN_MS = 15_000;\n\n/**\n * Progresso: `advance()` num loop apertado não pode virar um PATCH por item. O\n * snapshot pega carona em qualquer PATCH que saia (logs, heartbeat, terminal) e,\n * se nada mais estiver a caminho, um flush dedicado dispara depois deste intervalo.\n */\nconst PROGRESS_FLUSH_MS = 1_000;\n\n/** Scrub recursivo das strings do payload (profundidade capada — payload é raso por natureza). */\nfunction scrubPayloadValue(value: unknown, depth: number): unknown {\n if (typeof value === 'string') return scrubSecrets(value);\n if (depth >= 4 || value === null || typeof value !== 'object') return value;\n if (Array.isArray(value)) return value.map(entry => scrubPayloadValue(entry, depth + 1));\n const out: Record<string, unknown> = {};\n for (const [key, entry] of Object.entries(value as Record<string, unknown>)) {\n out[key] = scrubPayloadValue(entry, depth + 1);\n }\n return out;\n}\n\n/**\n * Reporter de uma run: bufferiza logs (flush incremental com throttle) e encadeia\n * todos os PATCHes numa fila única — a ordem running → logs → terminal é garantida.\n * Um 409/404 mata o reporter (run cancelada/finalizada no servidor): o handler não\n * pode ser morto, mas status posterior é suprimido e ctx.signal dispara para abort\n * cooperativo. Logs nunca são descartados em silêncio: falha de rede devolve ao\n * buffer, e depois da morte eles seguem best-effort como \"log tardio\" (o servidor\n * anexa logs a runs terminais mesmo respondendo 409).\n */\nexport class RunReporter {\n readonly context: RunContext;\n\n private buffer: RunLogEntry[] = [];\n private dead = false;\n private chain: Promise<void> = Promise.resolve();\n private pendingUpdates = 0;\n private timer: ReturnType<typeof setTimeout> | undefined;\n private watchTimer: ReturnType<typeof setInterval> | undefined;\n private readonly abortController = new AbortController();\n private readonly flushIntervalMs: number;\n private readonly cancelCheckIntervalMs: number;\n\n // Itens de execução vivem FORA de `this.chain` (status/liveness não pode ficar\n // atrás de milhares de itens), mas têm cadeia própria serializada — ordem de\n // envio preservada e sem lotes sobrepostos.\n private itemsBuffer: RunItemInput[] = [];\n private itemsChain: Promise<void> = Promise.resolve();\n private itemsTimer: ReturnType<typeof setTimeout> | undefined;\n private itemSeq = 0;\n /** Servidor sem o recurso (404) — para de tentar (e de avisar) nesta run. */\n private itemsUnsupported = false;\n /**\n * Cota de itens por run do servidor (429, legado — hoje a api não tem teto de itens) —\n * degrada com um aviso só.\n */\n private itemsQuotaExceeded = false;\n /**\n * Armazenamento do plano cheio (402 `storage_limit`): o lote é descartado e o aviso sai\n * uma vez por episódio. Os envios continuam — num agente `start()` o espaço pode ser\n * liberado (ou o plano trocado) sem reiniciar; um lote aceito rearma o aviso.\n */\n private itemsStorageFull = false;\n /**\n * Só o kill() do exit path fecha os itens — `dead` (run cancelada/finalizada no\n * servidor) NÃO fecha: o servidor aceita itens de run terminal (trabalho já feito).\n */\n private itemsClosed = false;\n\n // Uploads de anexo vivem FORA de `this.chain`: a cadeia é um FIFO puro de\n // status/logs e não pode ficar bloqueada esperando um binário subir.\n private readonly pendingAttachments = new Set<Promise<void>>();\n private attachmentCount = 0;\n private uploadSlots = MAX_CONCURRENT_UPLOADS;\n private uploadQueue: Array<() => void> = [];\n /** Uma vez que a instalação recusa anexos, para de tentar (e de avisar) nesta run. */\n private attachmentsUnsupported = false;\n\n // Progresso (ctx.progress): snapshot absoluto, enviado com throttle via piggyback\n // em `enqueue()` — nunca gera tráfego próprio enquanto logs/heartbeat já fluem.\n private progressCurrent = 0;\n private progressTotal: number | null = null;\n /** Snapshot ainda não entregue ao servidor. */\n private progressDirty = false;\n private progressTimer: ReturnType<typeof setTimeout> | undefined;\n private progressWarned = false;\n /** Relógio do último eco `[hobots:progress]` no terminal (throttle do eco, não do wire). */\n private progressLastPrint = 0;\n\n /** Arquivos do formulário desta run (`ctx.files`) — a pasta temporária é apagada no fim. */\n private readonly fileStore: RunFileStore;\n\n constructor(\n private readonly api: RunTransport,\n readonly runId: string,\n private readonly logger: Logger,\n private readonly tx: Transaction,\n flushIntervalMs?: number,\n cancelCheckIntervalMs?: number,\n params: Record<string, unknown> = {}\n ) {\n this.flushIntervalMs = flushIntervalMs ?? DEFAULT_LOG_FLUSH_INTERVAL_MS;\n this.cancelCheckIntervalMs = Math.min(\n MAX_CANCEL_CHECK_INTERVAL_MS,\n Math.max(MIN_CANCEL_CHECK_INTERVAL_MS, cancelCheckIntervalMs ?? DEFAULT_CANCEL_CHECK_INTERVAL_MS)\n );\n const logAt =\n (level: RunLogLevel) =>\n (message: unknown, ...rest: unknown[]): void => {\n const { text, image } = splitLogArgs(message, rest);\n this.log(level, text, image);\n };\n const log: RunLogger = {\n debug: logAt('debug'),\n info: logAt('info'),\n warn: logAt('warning'),\n error: logAt('error'),\n success: logAt('success'),\n };\n // eventos de transaction/step da run espelham nos logs (o terminal já foi\n // ecoado pelo próprio emit da Transaction — aqui é só buffer/envio)\n tx.setLifecycleSink((level, message) => this.push(level, message));\n // imagem de etapa (`etapa.image`/`etapa.warning({ image })`) sobe pelo pipeline de anexos desta run\n tx.setAttachmentSink((image, ts) => this.queueAttachment(image, ts));\n // pontos de parada cooperativos: registrar um item, avançar o progresso ou abrir uma\n // etapa são fronteiras naturais de trabalho — uma run cancelada para aqui sozinha\n const checkCanceled = (): void => this.checkCanceled();\n tx.setStepGuard(checkCanceled);\n // sink do items.each: itens, etapas, progresso e cancelamento desta run\n const eachSink: EachSink = {\n report: (status, message, payload, id, image) => this.addItem(status, message, payload, id, image),\n startStep: (op, description) => tx.start(op, description, 'item'),\n stepScope: (step, fn) => tx.scope(step, fn),\n declareTotal: total => {\n if (this.progressTotal == null) this.setProgress(this.progressCurrent, total);\n },\n advance: () => this.setProgress(this.progressCurrent + 1, this.progressTotal),\n checkCanceled,\n isAborted: () => this.abortController.signal.aborted,\n logInfo: message => this.log('info', message),\n logWarning: message => this.log('warning', message),\n logError: message => this.log('error', message),\n sleep: ms => cancelableSleep(ms, this.abortController.signal),\n doneItemIds: () => this.listDoneItemIds(),\n flush: () => this.flush(),\n };\n const items: RunItems = {\n add: item => {\n checkCanceled();\n this.addItem(item.status, item.message, item.payload, item.id, item.image);\n },\n succeeded: (payload, options) => {\n checkCanceled();\n this.addItem('succeeded', undefined, payload, options?.id, options?.image);\n },\n failed: (message, payload, options) => {\n checkCanceled();\n this.addItem('failed', message, payload, options?.id, options?.image);\n },\n occurrence: (message, payload, options) => {\n checkCanceled();\n this.addItem('occurrence', message, payload, options?.id, options?.image);\n },\n each: (list, handler, options = {}) => eachItem(list, handler, options, eachSink),\n };\n const progress = Object.defineProperties(\n {\n total: (total: number) => {\n checkCanceled();\n this.setProgress(this.progressCurrent, total);\n },\n advance: (count = 1) => {\n checkCanceled();\n this.setProgress(this.progressCurrent + count, this.progressTotal);\n },\n set: (current: number, total?: number) => {\n checkCanceled();\n this.setProgress(current, total ?? this.progressTotal);\n },\n },\n {\n current: { enumerable: true, get: () => this.progressCurrent },\n snapshot: {\n enumerable: true,\n get: () => (this.progressTotal == null ? null : { current: this.progressCurrent, total: this.progressTotal }),\n },\n }\n // defineProperties não tipa os getters adicionados — a interface é a fonte de verdade\n ) as unknown as RunProgressReporter;\n const signal = this.abortController.signal;\n const sleep = (ms: number): Promise<void> => cancelableSleep(ms, signal);\n this.fileStore = new RunFileStore({ api, runId, params, signal, warn: message => this.log('warning', message) });\n this.context = {\n runId,\n params,\n log,\n items,\n progress,\n files: this.fileStore.files,\n step: async (name, fn, options) => {\n // só a raiz faz flush: o flush das etapas envia raízes terminadas, sub-etapa vai junto da mãe\n const root = tx.currentStep() === undefined;\n try {\n return await tx.step(name, fn, { ...options, signal, wait: sleep, warn: message => this.log('warning', message) });\n } finally {\n // cancelada: o dreno final da run cuida, não vale segurar o handler aqui\n if (options?.flush !== false && root && !signal.aborted) await this.flush();\n }\n },\n flush: (timeoutMs?: number) => this.flush(timeoutMs),\n signal,\n throwIfCanceled: checkCanceled,\n sleep,\n retry: (fn, options?: RetryOptions) => retryWithBackoff(fn, { ...options, signal, wait: sleep }),\n };\n }\n\n /** Apaga as cópias de arquivo que ficaram na pasta temporária da run. Nunca lança. */\n cleanupFiles(): Promise<void> {\n return this.fileStore.cleanup();\n }\n\n get isDead(): boolean {\n return this.dead;\n }\n\n /** Lança `RunCanceled` se o signal desta run já disparou. */\n checkCanceled(): void {\n if (this.abortController.signal.aborted) throw runCanceledError();\n }\n\n /** Aborta o ctx.signal sem matar o reporter (timeout/shutdown ainda reportam o terminal). */\n abort(): void {\n this.stopCancelWatch(); // o heartbeat só existe para disparar o signal\n if (!this.abortController.signal.aborted) this.abortController.abort();\n }\n\n /**\n * Mata o reporter de vez: aborta o signal e suprime todo reporte futuro.\n * Usado no exit path — depois que o agente reportou AgentTerminated por fora\n * da fila, um handler zumbi não pode reenviar status por cima.\n */\n kill(): void {\n this.abort();\n this.dead = true;\n this.clearFlushTimer();\n this.clearProgressTimer();\n this.buffer = [];\n // exit path: diferente dos logs, o volume de itens não justifica salvage best-effort\n this.itemsClosed = true;\n this.clearItemsTimer();\n if (this.itemsBuffer.length > 0) {\n this.logger.warn(`${this.itemsBuffer.length} item(ns) de execução descartados (processo encerrando)`);\n this.itemsBuffer = [];\n }\n // uploads na fila nunca vão rodar: solta quem espera slot para não vazar promises\n const waiting = this.uploadQueue.splice(0, this.uploadQueue.length);\n for (const resume of waiting) resume();\n }\n\n /**\n * Drena o buffer pendente para o PATCH único do exit path (chame ANTES de kill,\n * que descarta o buffer). Capado em um chunk — o exit path não tem retry nem fila,\n * então preserva os logs mais recentes, os mais valiosos na morte do processo.\n */\n drainLogs(): RunLogEntry[] {\n this.clearFlushTimer();\n return this.takeLogs().slice(-MAX_LOGS_PER_PATCH);\n }\n\n /**\n * Linha de log da run com eco no terminal. `image` (opcional) vira o anexo da linha:\n * o id entra na entrada ANTES de qualquer I/O — é isso que mantém a ordem dos logs\n * intacta e o handler livre da latência do upload. Devolve o id do anexo (quando houve\n * imagem e ela não foi descartada) — o `captureException` o leva ao evento da issue.\n */\n log(level: RunLogLevel, message: string, image?: ImageInput): string | undefined {\n if (this.dead) return undefined;\n const scrubbed = scrubSecrets(safeString(message));\n const ts = nowISO();\n const attachmentId = image === undefined ? undefined : this.queueAttachment(image, ts);\n printRunLog(level, attachmentId ? `${scrubbed} [imagem]` : scrubbed);\n this.push(level, scrubbed, true, attachmentId ? [attachmentId] : undefined, ts);\n return attachmentId;\n }\n\n /** Bufferiza uma entrada de log sem eco no terminal (cap, truncate, flush). */\n private push(level: RunLogLevel, message: string, alreadyScrubbed = false, attachments?: string[], ts = nowISO()): string {\n if (this.dead) return ts;\n const scrubbed = alreadyScrubbed ? message : scrubSecrets(message);\n this.buffer.push({\n ts,\n level,\n message: truncate(scrubbed, MAX_LOG_MESSAGE_CHARS),\n ...(attachments && attachments.length > 0 ? { attachments: attachments.slice(0, WIRE_LIMITS.MAX_ATTACHMENTS_PER_LOG_ENTRY) } : {}),\n });\n\n if (this.buffer.length >= FLUSH_AT_BUFFERED) {\n this.flushLogs();\n } else {\n this.scheduleFlush();\n }\n return ts;\n }\n\n private scheduleFlush(): void {\n if (this.timer) return;\n this.timer = setTimeout(() => {\n this.timer = undefined;\n this.flushLogs();\n }, this.flushIntervalMs);\n unrefTimer(this.timer);\n }\n\n private clearFlushTimer(): void {\n if (this.timer) {\n clearTimeout(this.timer);\n this.timer = undefined;\n }\n }\n\n private takeLogs(): RunLogEntry[] {\n return this.buffer.splice(0, this.buffer.length);\n }\n\n /** Flush incremental: envia o buffer como status 'running' (em chunks). */\n private flushLogs(): void {\n this.clearFlushTimer();\n if (this.dead || this.buffer.length === 0) return;\n const logs = this.buffer.splice(0, this.buffer.length);\n for (let i = 0; i < logs.length; i += MAX_LOGS_PER_PATCH) {\n this.enqueue({ status: 'running', logs: logs.slice(i, i + MAX_LOGS_PER_PATCH) });\n }\n }\n\n /**\n * `hobots.flush()`: o bot decide quando entregar o que já fez — etapas raiz finalizadas\n * viram transactions parciais da run, e itens, logs e progresso pendentes saem já, sem\n * esperar o throttle. Aguarda a entrega com teto. Nunca lança (pode ir num `finally`).\n */\n async flush(timeoutMs = ITEMS_DRAIN_MS): Promise<void> {\n this.tx.flush();\n this.flushItems();\n if (this.progressDirty) this.flushProgress();\n else this.flushLogs();\n await Promise.race([\n Promise.all([this.itemsChain, this.chain, this.tx.drain(timeoutMs)]).catch(() => undefined),\n new Promise<void>(resolve => unrefTimer(setTimeout(resolve, timeoutMs))),\n ]);\n }\n\n /** Primeiro PATCH (claimed → running). Retorna false se a run já morreu (cancelada). */\n async reportRunning(): Promise<boolean> {\n this.enqueue({ status: 'running' });\n await this.chain;\n if (!this.dead) this.startCancelWatch();\n return !this.dead;\n }\n\n reportSuccess(): void {\n this.stopCancelWatch();\n this.clearFlushTimer();\n this.forceFinalProgress();\n this.enqueue({ status: 'succeeded', logs: this.takeLogsForTerminal() });\n }\n\n reportFailure(error: RunError): void {\n this.stopCancelWatch();\n this.clearFlushTimer();\n this.forceFinalProgress();\n this.enqueue({ status: 'failed', error, logs: this.takeLogsForTerminal() });\n }\n\n /**\n * Esvazia o buffer para o PATCH terminal respeitando o teto de 100 logs por PATCH:\n * o excedente sai antes, em PATCHes `running` na mesma cadeia (a ordem se mantém).\n */\n private takeLogsForTerminal(): RunLogEntry[] {\n let logs = this.takeLogs();\n while (logs.length > MAX_LOGS_PER_PATCH) {\n this.enqueue({ status: 'running', logs: logs.slice(0, MAX_LOGS_PER_PATCH) });\n logs = logs.slice(MAX_LOGS_PER_PATCH);\n }\n return logs;\n }\n\n // ── Progresso ────────────────────────────────────────────────────────────────\n\n /** Valida, clampa e marca o snapshot como pendente; agenda flush só se nada mais vai sair. */\n private setProgress(current: number, total: number | null): void {\n if (this.dead) return;\n if (total != null && (!Number.isInteger(total) || total < 1)) {\n if (!this.progressWarned) {\n this.progressWarned = true;\n this.logger.warn(`ctx.progress: total inválido (${String(total)}) — precisa ser inteiro >= 1; ignorado`);\n }\n return;\n }\n const safeCurrent = Number.isFinite(current) ? Math.max(0, Math.floor(current)) : this.progressCurrent;\n const next = total == null ? safeCurrent : Math.min(safeCurrent, total);\n const totalChanged = total !== this.progressTotal;\n if (next === this.progressCurrent && !totalChanged) return;\n this.progressCurrent = next;\n this.progressTotal = total;\n // sem total declarado não há wire: guarda o contador e espera o total()\n if (total == null) return;\n // eco no terminal: total novo e valor final saem sempre; o meio do caminho, no máximo 4×/s\n const now = Date.now();\n if (totalChanged || next >= total || now - this.progressLastPrint >= PROGRESS_PRINT_THROTTLE_MS) {\n this.progressLastPrint = now;\n printRunProgress(next, total);\n }\n this.progressDirty = true;\n // um PATCH que saia antes (logs/heartbeat) leva o snapshot e cancela este timer\n if (this.progressTimer) return;\n this.progressTimer = setTimeout(() => {\n this.progressTimer = undefined;\n this.flushProgress();\n }, PROGRESS_FLUSH_MS);\n unrefTimer(this.progressTimer);\n }\n\n private flushProgress(): void {\n this.clearProgressTimer();\n if (this.dead || !this.progressDirty) return;\n // logs esperando flush: um PATCH só leva logs + progresso\n if (this.buffer.length > 0) this.flushLogs();\n else this.enqueue({ status: 'running' });\n }\n\n private clearProgressTimer(): void {\n if (this.progressTimer) {\n clearTimeout(this.progressTimer);\n this.progressTimer = undefined;\n }\n }\n\n /** O PATCH terminal sempre leva o snapshot final (o app mostra \"87/100\" numa run que falhou). */\n private forceFinalProgress(): void {\n this.clearProgressTimer();\n this.progressDirty = this.progressTotal != null;\n }\n\n /** Consome o snapshot pendente para pegar carona no próximo PATCH. */\n private takeProgress(): RunProgress | undefined {\n if (!this.progressDirty || this.progressTotal == null) return undefined;\n this.progressDirty = false;\n return { current: this.progressCurrent, total: this.progressTotal };\n }\n\n /**\n * Heartbeat de cancelamento: enquanto o handler roda, um PATCH 'running' vazio\n * periódico faz o servidor responder 409 se a run foi cancelada no app — o que\n * mata o reporter e dispara ctx.signal, mesmo em handlers que nunca logam.\n */\n private startCancelWatch(): void {\n if (this.watchTimer) return;\n this.watchTimer = setInterval(() => {\n // já há tráfego a caminho (logs/updates) — ele mesmo detecta o cancelamento\n if (this.dead || this.pendingUpdates > 0 || this.buffer.length > 0) return;\n this.enqueue({ status: 'running' });\n }, this.cancelCheckIntervalMs);\n unrefTimer(this.watchTimer);\n }\n\n private stopCancelWatch(): void {\n if (this.watchTimer) {\n clearInterval(this.watchTimer);\n this.watchTimer = undefined;\n }\n }\n\n /** Aguarda a fila de PATCHes esvaziar (chame depois do terminal). */\n finalize(): Promise<void> {\n return this.chain;\n }\n\n // ── Itens de execução ────────────────────────────────────────────────────────\n\n /**\n * Bufferiza um item (síncrono — a chamada nunca espera rede). Diferente do PATCH\n * de status, o servidor aceita itens mesmo com a run cancelada (trabalho já feito),\n * então um reporter morto não descarta: só um kill() de exit path descarta.\n */\n private addItem(\n status: RunItemStatus,\n message: string | undefined,\n payload: Record<string, unknown> | undefined,\n id: string | undefined,\n image?: ImageInput\n ): void {\n if (this.itemsClosed || this.itemsUnsupported) return;\n\n let scrubbedPayload: Record<string, unknown> | undefined;\n if (payload) {\n scrubbedPayload = scrubPayloadValue(payload, 0) as Record<string, unknown>;\n let serializedLength: number | undefined;\n try {\n serializedLength = JSON.stringify(scrubbedPayload).length;\n } catch {\n // payload circular/não-serializável — sem ele o item ainda vale pelo status\n }\n if (serializedLength === undefined || serializedLength > MAX_ITEM_PAYLOAD_BYTES) {\n this.logger.warn(\n `payload do item descartado (${serializedLength === undefined ? 'não serializável' : `${serializedLength} bytes > ${MAX_ITEM_PAYLOAD_BYTES}`}) — o item foi mantido`\n );\n scrubbedPayload = undefined;\n }\n }\n\n const ts = nowISO();\n const attachmentId = image === undefined ? undefined : this.queueAttachment(image, ts);\n this.itemsBuffer.push({\n id: id ? truncate(String(id), 255) : uuid4(),\n seq: this.itemSeq++,\n status,\n ...(message ? { message: truncate(scrubSecrets(safeString(message)), MAX_ITEM_MESSAGE_CHARS) } : {}),\n ...(scrubbedPayload ? { payload: scrubbedPayload } : {}),\n ts,\n ...(attachmentId ? { attachments: [attachmentId] } : {}),\n });\n\n if (this.itemsBuffer.length >= ITEMS_FLUSH_AT_BUFFERED) {\n this.flushItems();\n } else {\n this.scheduleItemsFlush();\n }\n }\n\n /**\n * Ids já concluídos (`succeeded`/`occurrence`) neste trabalho — a run e suas reexecuções.\n * Pagina até o fim. undefined quando a consulta falha (servidor antigo, rede): o `each`\n * avisa e processa tudo, nunca trava a run por isso.\n */\n async listDoneItemIds(): Promise<Set<string> | undefined> {\n const ids = new Set<string>();\n let cursor: string | null = null;\n try {\n do {\n const page: RunItemsDoneResponse = await this.api.listDoneItems(this.runId, {\n limit: MAX_ITEMS_DONE_PER_PAGE,\n ...(cursor ? { cursor } : {}),\n });\n for (const id of page.ids) ids.add(id);\n cursor = page.next;\n } while (cursor);\n return ids;\n } catch (error) {\n this.log('warning', `não foi possível consultar os itens já concluídos deste trabalho — todos serão processados (${thrownMessage(error)})`);\n return undefined;\n }\n }\n\n private scheduleItemsFlush(): void {\n if (this.itemsTimer) return;\n this.itemsTimer = setTimeout(() => {\n this.itemsTimer = undefined;\n this.flushItems();\n }, this.flushIntervalMs);\n unrefTimer(this.itemsTimer);\n }\n\n private clearItemsTimer(): void {\n if (this.itemsTimer) {\n clearTimeout(this.itemsTimer);\n this.itemsTimer = undefined;\n }\n }\n\n /** Envia o buffer de itens em lotes serializados na cadeia própria. */\n private flushItems(): void {\n this.clearItemsTimer();\n if (this.itemsBuffer.length === 0 || this.itemsUnsupported) return;\n const items = this.itemsBuffer.splice(0, this.itemsBuffer.length);\n for (let i = 0; i < items.length; i += MAX_ITEMS_PER_REQUEST) {\n const batch = items.slice(i, i + MAX_ITEMS_PER_REQUEST);\n this.itemsChain = this.itemsChain.then(() => this.sendItems(batch));\n }\n }\n\n private async sendItems(batch: RunItemInput[]): Promise<void> {\n if (this.itemsUnsupported) return;\n try {\n await this.api.createItems(this.runId, { items: batch });\n this.itemsStorageFull = false;\n } catch (error) {\n if (error instanceof TasksApiError && error.status === 404) {\n // servidor anterior ao recurso (ou run apagada) — degrada em silêncio daqui em diante\n this.itemsUnsupported = true;\n this.logger.warn('itens de execução não são suportados por este servidor Hobots — descartados');\n return;\n }\n if (error instanceof TasksApiError && error.status === 429) {\n if (!this.itemsQuotaExceeded) {\n this.itemsQuotaExceeded = true;\n this.log('warning', 'itens descartados: limite de itens por execução atingido no servidor');\n }\n return;\n }\n if (error instanceof TasksApiError && error.status === 402) {\n if (!this.itemsStorageFull) {\n this.itemsStorageFull = true;\n this.log('warning', 'itens descartados: armazenamento do plano cheio — libere espaço ou faça upgrade em Plano e cobrança');\n }\n return;\n }\n if (error instanceof TasksApiError) {\n // 4xx definitivo (payload rejeitado) — reenviar não vai mudar o resultado; vai pro\n // log da run para o descarte aparecer na Central, não só no stderr da máquina\n this.logger.error(`lote de ${batch.length} item(ns) rejeitado pelo servidor:`, error);\n this.log('warning', `${batch.length} item(ns) descartado(s): envio rejeitado pelo servidor (HTTP ${error.status})`);\n return;\n }\n // rede/5xx com retries esgotados: devolve ao buffer para a próxima tentativa\n this.itemsBuffer.unshift(...batch);\n this.scheduleItemsFlush();\n this.logger.error(`lote de ${batch.length} item(ns) não enviado (devolvido ao buffer):`, error);\n }\n }\n\n /**\n * Dreno final de itens antes do PATCH terminal (com teto): garante que os\n * totalizadores estejam completos quando a run vira succeeded/failed. Como o\n * servidor aceita itens tardios, perder a corrida aqui não perde dados.\n */\n async finalizeItems(timeoutMs = ITEMS_DRAIN_MS): Promise<void> {\n this.flushItems();\n await Promise.race([\n this.itemsChain,\n new Promise<void>(resolve => unrefTimer(setTimeout(resolve, timeoutMs))),\n ]);\n if (this.itemsBuffer.length > 0 && !this.itemsUnsupported && !this.itemsQuotaExceeded) {\n // sobrou lote devolvido por falha de rede — última tentativa antes do terminal\n this.flushItems();\n await Promise.race([\n this.itemsChain,\n new Promise<void>(resolve => unrefTimer(setTimeout(resolve, timeoutMs))),\n ]);\n }\n }\n\n // ── Anexos ───────────────────────────────────────────────────────────────────\n\n /**\n * Pendura uma imagem num evento da run (log, item ou etapa): faz as checagens que não\n * dependem de I/O (reporter morto, instalação sem anexos, cota), reserva o id e dispara\n * o upload em segundo plano. Devolve o id — já referenciável pelo evento — ou undefined\n * quando a imagem foi descartada (sempre com aviso no log da run). Nunca lança: todo\n * caminho de erro do upload vira aviso. O hint `attachment` de `hobots.captureException`\n * também cai aqui via `log()`.\n */\n queueAttachment(imageIn: ImageInput, ts: string): string | undefined {\n if (this.dead) return undefined;\n const image = toImageAttachment(imageIn);\n if (this.attachmentsUnsupported) return undefined; // já avisamos uma vez nesta run\n if (this.attachmentCount >= MAX_ATTACHMENTS_PER_RUN) {\n if (this.attachmentCount === MAX_ATTACHMENTS_PER_RUN) {\n this.attachmentCount++; // aviso único por run\n this.log('warning', `imagem descartada: limite de ${MAX_ATTACHMENTS_PER_RUN} por execução atingido`);\n }\n return undefined;\n }\n this.attachmentCount++;\n\n const id = uuid4();\n const rawCaption = image.caption !== undefined ? safeString(image.caption) : undefined;\n const caption = rawCaption ? truncate(scrubSecrets(rawCaption), MAX_CAPTION_CHARS) : undefined;\n const work = this.uploadAttachment(id, image.input, { caption, logTs: ts, contentType: image.contentType })\n .then(() => undefined)\n .catch(() => undefined);\n this.pendingAttachments.add(work);\n void work.finally(() => this.pendingAttachments.delete(work));\n return id;\n }\n\n /** Retorna o motivo da falha, ou undefined em sucesso. */\n private async uploadAttachment(\n id: string,\n image: AttachInput,\n meta: { caption?: string; logTs: string; contentType?: RunAttachmentContentType }\n ): Promise<AttachFailureReason | undefined> {\n let bytes: Uint8Array;\n try {\n bytes = await toBytes(image);\n } catch (error) {\n this.log('warning', `imagem não pôde ser lida: ${String(error)}`);\n return 'read-failed';\n }\n\n // magic bytes ganham do que o chamador declarou — o S3 rejeita a assinatura se divergir\n const contentType = sniffContentType(bytes) ?? meta.contentType;\n if (!contentType) {\n this.log('warning', 'imagem descartada: formato não reconhecido (aceitos: PNG, JPEG, WEBP)');\n return 'unsupported-format';\n }\n if (bytes.byteLength > MAX_ATTACHMENT_BYTES) {\n this.log(\n 'warning',\n `imagem descartada: ${Math.round(bytes.byteLength / 1024)} KB excede o limite de ${MAX_ATTACHMENT_BYTES / 1024 / 1024} MB`\n );\n return 'too-large';\n }\n\n const dimensions = readPngDimensions(bytes);\n const release = await this.acquireUploadSlot();\n try {\n if (this.abortController.signal.aborted || this.dead) return 'canceled';\n const created = await this.api.createAttachment(\n this.runId,\n {\n id,\n content_type: contentType,\n size_bytes: bytes.byteLength,\n log_ts: meta.logTs,\n ...(meta.caption ? { caption: meta.caption } : {}),\n ...(dimensions ?? {}),\n },\n this.abortController.signal\n );\n await this.api.uploadAttachment(created.upload_url, created.headers, bytes, this.abortController.signal);\n // confirmação é conforto de UX (some o placeholder \"enviando…\"): falha não invalida o upload\n await this.api\n .confirmAttachment(this.runId, id, { status: 'uploaded', size_bytes: bytes.byteLength, ...(dimensions ?? {}) })\n .catch(() => {});\n return undefined;\n } catch (error) {\n if (this.isUnsupported(error)) {\n this.attachmentsUnsupported = true;\n this.log('warning', 'anexos não estão habilitados nesta instalação do Hobots — imagem não enviada');\n return 'unsupported';\n }\n if (error instanceof TasksApiError && error.status === 429) {\n this.log('warning', 'imagem descartada: limite de anexos por execução atingido no servidor');\n return 'quota';\n }\n if (this.abortController.signal.aborted) return 'canceled';\n this.log('warning', `falha ao enviar a imagem: ${String(error)}`);\n void this.api.confirmAttachment(this.runId, id, { status: 'failed' }).catch(() => {});\n return 'upload-failed';\n } finally {\n release();\n }\n }\n\n /** 404 = API anterior ao recurso; 501/503 = instalação sem S3 configurado. */\n private isUnsupported(error: unknown): boolean {\n return error instanceof TasksApiError && (error.status === 404 || error.status === 501 || error.status === 503);\n }\n\n /** Semáforo simples: no máximo MAX_CONCURRENT_UPLOADS binários em voo por run. */\n private acquireUploadSlot(): Promise<() => void> {\n const release = (): void => {\n const next = this.uploadQueue.shift();\n if (next) next();\n else this.uploadSlots++;\n };\n if (this.uploadSlots > 0) {\n this.uploadSlots--;\n return Promise.resolve(release);\n }\n return new Promise<() => void>(resolve => {\n this.uploadQueue.push(() => resolve(release));\n });\n }\n\n /**\n * Espera os uploads pendentes antes do PATCH terminal, para a run não terminar\n * exibindo miniaturas em \"enviando…\". Capado: um upload lento não segura a run.\n */\n async finalizeAttachments(timeoutMs = ATTACHMENT_DRAIN_MS): Promise<void> {\n if (this.pendingAttachments.size === 0) return;\n await Promise.race([\n Promise.allSettled([...this.pendingAttachments]),\n new Promise<void>(resolve => unrefTimer(setTimeout(resolve, timeoutMs))),\n ]);\n }\n\n private enqueue(updateIn: RunUpdateRequest): void {\n if (this.dead) {\n this.salvageLogs(updateIn.logs);\n return;\n }\n // ponto único de piggyback: qualquer PATCH que saia leva o progresso mais recente\n this.clearProgressTimer();\n const progress = this.takeProgress();\n const update: RunUpdateRequest = progress ? { ...updateIn, progress } : updateIn;\n this.pendingUpdates++;\n this.chain = this.chain.then(async () => {\n if (this.dead) {\n // update enfileirado atrás do PATCH que morreu (ex.: chunks de flush): logs seguem tardios\n this.salvageLogs(update.logs);\n return;\n }\n const payload = update.logs && update.logs.length === 0 ? { ...update, logs: undefined } : update;\n try {\n await this.api.updateRun(this.runId, payload);\n } catch (error) {\n if (error instanceof TasksApiError && (error.status === 409 || error.status === 404)) {\n this.dead = true;\n this.stopCancelWatch();\n this.abort();\n // os logs deste payload já foram anexados pelo servidor (append tardio no 409);\n // o que resta no buffer segue best-effort pelo mesmo caminho\n const pending = this.buffer.splice(0, this.buffer.length);\n this.salvageLogs(pending);\n this.logger.warn(\n `run ${this.runId} cancelada/finalizada no servidor — status suprimido` +\n (pending.length > 0 ? `, ${pending.length} log(s) enviados como log tardio` : '')\n );\n return;\n }\n // rede/5xx com retries esgotados: devolve os logs ao buffer para o próximo PATCH\n if (update.logs && update.logs.length > 0) {\n this.buffer.unshift(...update.logs);\n this.scheduleFlush();\n }\n // o snapshot perdido é ≤ o atual: basta marcar como pendente de novo\n if (update.progress && this.progressTotal != null) this.progressDirty = true;\n this.logger.error(`update da run ${this.runId} perdido:`, error);\n }\n }).finally(() => {\n this.pendingUpdates--;\n });\n }\n\n /**\n * Best-effort de log tardio: envia logs para uma run já terminal, fora da fila.\n * O servidor anexa os logs mesmo respondendo 409; erros são engolidos — este é\n * o último recurso, não um canal confiável.\n */\n private salvageLogs(logs: RunLogEntry[] | undefined): void {\n if (!logs || logs.length === 0) return;\n for (let i = 0; i < logs.length; i += MAX_LOGS_PER_PATCH) {\n void this.api\n .updateRunOnce(this.runId, { status: 'running', logs: logs.slice(i, i + MAX_LOGS_PER_PATCH) })\n .catch(() => {});\n }\n }\n}\n","import type { RunDescriptor, RunError } from './protocol';\nimport type { AgentHandler, RunHandler } from './types';\nimport type { RunTransport } from './api';\nimport { RunReporter } from './context';\nimport { isCancellation, taskTimeoutError } from './errors';\nimport type { RunTracker } from './registry';\nimport { runWithRunContext } from './run-context-store';\nimport { resolveDelay, retryWithBackoff } from '../retry';\nimport { Transaction } from '../transaction';\nimport { scrubSecrets } from '../scrub';\nimport { sleep, truncate, type Logger } from '../utils';\nimport { wasCaptured, type Client } from '../client';\nimport { WIRE_LIMITS } from '../wire-limits';\n\nexport interface ExecuteRunInput {\n run: RunDescriptor;\n handler: AgentHandler;\n api: RunTransport;\n client: Client | undefined;\n logger: Logger;\n tracker: RunTracker;\n}\n\nconst DEFAULT_RETRY_DELAY_MS = 5_000;\n\n/**\n * Pipeline de UMA run, compartilhado por todos os modos (poll, start, run anexada e modo local): transaction →\n * reporter → running → handler (com retry) → drenos → terminal. O handler roda dentro\n * do contexto async da run, então `hobots.*` em qualquer módulo resolve para ela.\n */\nexport async function executeRun(input: ExecuteRunInput): Promise<void> {\n const { run, handler, api, client, logger, tracker } = input;\n const options = handler.options;\n // correlacionada à run via run_id — as etapas que o handler abrir com hobots.step() viram o\n // waterfall de performance da execução na Central; no modo local (sem client) o FINISH ecoa no terminal\n const tx = new Transaction(client, 'run', 'hobots.run', run.id, { echo: !client });\n const reporter = new RunReporter(\n api,\n run.id,\n logger,\n tx,\n options.logFlushIntervalMs,\n options.cancelCheckIntervalMs,\n run.params\n );\n tracker.add(reporter);\n\n try {\n const ok = await reporter.reportRunning();\n if (!ok) {\n logger.debug(`run ${run.id} cancelada antes de iniciar — handler não executado`);\n tx.setStatus('cancelled');\n tx.finish();\n return;\n }\n\n logger.debug(`executando run ${run.id}`);\n try {\n await runWithRunContext({ reporter }, () => invokeWithRetry(handler, run, reporter, logger));\n // anexos disparados sem await (fire-and-forget) ainda podem estar subindo:\n // espera (com teto) para a run não terminar com miniaturas em \"enviando…\"\n await reporter.finalizeAttachments();\n // dreno dos itens antes do terminal: os totalizadores da run ficam completos\n // quando ela vira succeeded (itens tardios ainda são aceitos se perder a corrida)\n await reporter.finalizeItems();\n warnIncompleteProgress(reporter);\n // finish antes do terminal: as linhas FINISH de tx/steps entram no mesmo PATCH\n tx.setStatus('ok');\n tx.finish();\n reporter.reportSuccess();\n logger.debug(`run ${run.id} concluída`);\n } catch (error) {\n // uma falha é justamente quando o print importa — vale esperar o upload aqui também\n await reporter.finalizeAttachments();\n // itens já processados antes da falha fazem parte da entrega — drena antes do terminal\n await reporter.finalizeItems();\n tx.setStatus('error');\n tx.finish();\n captureRunFailure(client, error, reporter);\n reporter.reportFailure(toRunError(error));\n logger.debug(`run ${run.id} falhou: ${String(error)}`);\n }\n await reporter.finalize();\n } finally {\n // as cópias sem `dest` só valem durante a run — arquivo de cliente não fica no disco\n await reporter.cleanupFiles();\n tracker.remove(reporter);\n }\n}\n\n/**\n * O erro que escapou do handler (depois do retry) é um erro não tratado do bot: além\n * de falhar a run, vira issue ligada a ela. Cancelamento não é defeito, e o erro que o\n * próprio bot já enviou com captureException e relançou não é enviado de novo.\n */\nfunction captureRunFailure(client: Client | undefined, error: unknown, reporter: RunReporter): void {\n if (!client?.options.captureRunErrors) return;\n // reporter morto = run cancelada no app: o erro é consequência do cancelamento\n if (reporter.isDead || isCancellation(error) || wasCaptured(error)) return;\n client.captureException(error, { type: 'error', tags: { mechanism: 'run_handler', run_id: reporter.runId } });\n}\n\n/**\n * Handler retornou normalmente com o progresso declarado parado antes do total: a run\n * vai virar `succeeded`, mas nem tudo que o bot previu foi processado (ou avançado) —\n * fica registrado no log da run, onde a Central também sinaliza o desencontro.\n */\nfunction warnIncompleteProgress(reporter: RunReporter): void {\n const snapshot = reporter.context.progress.snapshot;\n if (!snapshot || snapshot.current >= snapshot.total) return;\n reporter.context.log.warn(\n `execução concluída com progresso incompleto: ${snapshot.current}/${snapshot.total} — ` +\n 'o handler terminou sem processar (ou sem avançar) todos os itens previstos'\n );\n}\n\n/**\n * Tentativas do handler na MESMA run: falha comum → aviso no log da run, espera\n * cancelável, re-invoca com os mesmos params (itens/progresso já enviados permanecem).\n * Cancelamento, timeout e reporter morto (run cancelada no app) são terminais.\n */\nfunction invokeWithRetry(agent: AgentHandler, run: RunDescriptor, reporter: RunReporter, logger: Logger): Promise<void> {\n const { retries, retryDelayMs } = agent.options;\n const total = retries + 1;\n const ctx = reporter.context;\n return retryWithBackoff(() => invokeWithTimeout(agent, run, reporter, logger), {\n retries,\n delayMs: attempt => resolveDelay(retryDelayMs, attempt, DEFAULT_RETRY_DELAY_MS),\n shouldRetry: () => !reporter.isDead,\n signal: ctx.signal,\n wait: ms => ctx.sleep(ms),\n onRetry: (error, attempt, delayMs) => {\n const reason = error instanceof Error ? `${error.name}: ${error.message}` : String(error);\n ctx.log.warn(`tentativa ${attempt}/${total} falhou: ${truncate(reason, 500)} — nova tentativa em ${delayMs}ms`);\n },\n });\n}\n\nconst TIMEOUT_SENTINEL = Symbol('task-timeout');\nconst CANCEL_SENTINEL = Symbol('task-canceled');\n\nasync function invokeWithTimeout(agent: AgentHandler, run: RunDescriptor, reporter: RunReporter, logger: Logger): Promise<void> {\n const { timeoutMs, cancelGraceMs } = agent.options;\n const handler: RunHandler = agent.handler;\n const invocation = Promise.resolve().then(() => handler(run.params, reporter.context));\n const races: Promise<typeof TIMEOUT_SENTINEL | typeof CANCEL_SENTINEL>[] = [];\n if (timeoutMs && timeoutMs > 0) {\n races.push(sleep(timeoutMs).then(() => TIMEOUT_SENTINEL));\n }\n if (cancelGraceMs > 0) {\n races.push(waitForCancelGrace(reporter.context.signal, cancelGraceMs).then(() => CANCEL_SENTINEL));\n }\n if (races.length === 0) {\n await invocation;\n return;\n }\n\n const outcome = await Promise.race([invocation, ...races]);\n if (outcome !== TIMEOUT_SENTINEL && outcome !== CANCEL_SENTINEL) return; // invocation venceu a corrida\n\n if (outcome === CANCEL_SENTINEL) {\n // run já cancelada no app (409) há cancelGraceMs — o handler não respondeu ao\n // signal a tempo; não dá para matar o código do usuário, então o agente\n // para de esperar e libera o slot. Reportes subsequentes são no-op (reporter morto).\n logger.warn(\n `run ${run.id} cancelada — handler não respondeu a hobots.signal em ${cancelGraceMs}ms, ` +\n 'liberando o slot (o handler pode continuar rodando em segundo plano)'\n );\n return;\n }\n\n // TIMEOUT_SENTINEL: não dá para matar o código do usuário — reporta, aborta o signal e libera o slot\n reporter.abort();\n invocation\n .then(() => logger.warn(`run ${run.id} terminou depois do timeout de ${timeoutMs}ms`))\n .catch(() => logger.warn(`run ${run.id} falhou depois do timeout de ${timeoutMs}ms (erro descartado)`));\n throw taskTimeoutError(timeoutMs!);\n}\n\n/** Resolve só depois que `signal` abortar + `graceMs` — nunca resolve se o signal nunca disparar. */\nfunction waitForCancelGrace(signal: AbortSignal, graceMs: number): Promise<void> {\n return new Promise<void>(resolve => {\n /* v8 ignore start -- defensivo: o retryWithBackoff checa o abort e chama o handler no mesmo tick */\n if (signal.aborted) {\n setTimeout(resolve, graceMs);\n return;\n }\n /* v8 ignore stop */\n signal.addEventListener('abort', () => setTimeout(resolve, graceMs), { once: true });\n });\n}\n\nconst MAX_ERROR_MESSAGE_CHARS = WIRE_LIMITS.MAX_ERROR_MESSAGE_CHARS;\nconst MAX_ERROR_STACK_CHARS = WIRE_LIMITS.MAX_ERROR_STACK_CHARS;\n\nexport function toRunError(error: unknown): RunError {\n if (error instanceof Error) {\n return {\n type: error.name,\n message: scrubSecrets(truncate(error.message, MAX_ERROR_MESSAGE_CHARS)),\n stack: error.stack ? scrubSecrets(truncate(error.stack, MAX_ERROR_STACK_CHARS)) : undefined,\n };\n }\n return { message: scrubSecrets(truncate(String(error), MAX_ERROR_MESSAGE_CHARS)) };\n}\n\n","import type { TasksApi } from './api';\nimport { Backoff } from './backoff';\nimport type { InstanceInfo, RunDescriptor } from './protocol';\nimport type { RunTracker } from './registry';\nimport { executeRun } from './runner';\nimport type { AgentHandler } from './types';\nimport type { Client } from '../client';\nimport { sleep, type Logger } from '../utils';\nimport { WIRE_LIMITS } from '../wire-limits';\n\n// 2s: uma solicitação nova aparece como 'executando' no app quase na hora; o poll é\n// um UPDATE indexado (SKIP LOCKED) e a presença da instância é throttled no servidor\nexport const DEFAULT_POLL_INTERVAL_MS = 2_000;\nconst MIN_POLL_INTERVAL_MS = 1_000;\nconst MAX_CLAIM_PER_POLL = WIRE_LIMITS.MAX_CLAIM_PER_POLL;\n\ntype AgentState = 'idle' | 'started' | 'stopping';\n\nexport interface TaskAgentOptions {\n api: TasksApi;\n client: Client | undefined;\n logger: Logger;\n /** O handler sob demanda do agente (modo remote). */\n handler: AgentHandler;\n tracker: RunTracker;\n /** Presença da instância enviada em cada poll (identidade, versão, ambiente, modo, máquina). */\n instanceInfo: () => InstanceInfo;\n pollIntervalMs?: number;\n}\n\n/**\n * Loop de polling do modo sob demanda (register): busca runs pendentes do agente e\n * executa o handler. O timer NÃO é unref'd — um agente iniciado mantém o processo vivo\n * até stop(). O poll só pede tantas runs quantos slots livres houver (`concurrency`).\n */\nexport class TaskAgent {\n readonly logger: Logger;\n readonly pollIntervalMs: number;\n\n private readonly api: TasksApi;\n private readonly client: Client | undefined;\n private readonly handler: AgentHandler;\n private readonly tracker: RunTracker;\n private readonly backoff: Backoff;\n\n private state: AgentState = 'idle';\n private timer: ReturnType<typeof setTimeout> | undefined;\n private pollAbort: AbortController | undefined;\n private readonly activeRuns = new Set<Promise<void>>();\n\n constructor(private readonly options: TaskAgentOptions) {\n this.logger = options.logger;\n this.api = options.api;\n this.client = options.client;\n this.handler = options.handler;\n this.tracker = options.tracker;\n this.pollIntervalMs = Math.max(MIN_POLL_INTERVAL_MS, options.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS);\n this.backoff = new Backoff(this.logger, 'poll', this.pollIntervalMs);\n }\n\n get activeCount(): number {\n return this.activeRuns.size;\n }\n\n start(): void {\n if (this.state === 'started') return;\n if (this.state === 'stopping') {\n throw new Error('[hobots] start do agente durante o stop — aguarde o stop terminar');\n }\n this.state = 'started';\n this.logger.debug(`polling iniciado (concorrência ${this.handler.options.concurrency})`);\n this.schedule(0);\n }\n\n /** Antecipa o próximo poll para já. */\n wake(): void {\n if (this.state !== 'started') return;\n if (this.timer) {\n clearTimeout(this.timer);\n this.timer = undefined;\n }\n this.schedule(0);\n }\n\n /** Para o polling e aguarda as runs ativas (até timeoutMs). Retorna true se tudo terminou a tempo. */\n async stop(timeoutMs = 30_000): Promise<boolean> {\n if (this.state === 'idle') return true;\n this.state = 'stopping';\n if (this.timer) {\n clearTimeout(this.timer);\n this.timer = undefined;\n }\n this.pollAbort?.abort();\n\n const all = Promise.allSettled([...this.activeRuns]).then(() => true);\n const finished = timeoutMs > 0 ? await Promise.race([all, sleep(timeoutMs).then(() => false)]) : this.activeRuns.size === 0;\n this.state = 'idle';\n return finished;\n }\n\n /** Timer intencionalmente NÃO unref'd: o agente é a razão do processo existir. */\n private schedule(delayMs: number): void {\n if (this.state !== 'started' || this.timer) return;\n this.timer = setTimeout(() => {\n this.timer = undefined;\n void this.tick();\n }, delayMs);\n }\n\n /** Slots livres do agente — vira o `max` do poll (nunca reivindica trabalho para deixar parado). */\n private freeSlots(): number {\n const free = this.handler.options.concurrency - this.tracker.activeCount;\n return Math.min(MAX_CLAIM_PER_POLL, Math.max(0, free));\n }\n\n private async tick(): Promise<void> {\n /* v8 ignore start -- defensivo: o timer só existe com o agente started e o stop() o limpa */\n if (this.state !== 'started') return;\n /* v8 ignore stop */\n const max = this.freeSlots();\n if (max === 0) {\n this.schedule(this.pollIntervalMs);\n return;\n }\n\n this.pollAbort = new AbortController();\n try {\n const response = await this.api.poll(\n {\n // identidade canônica do agente no painel — o mesmo instanceId do heartbeat,\n // então os dois canais convergem em um agente\n instance: this.options.instanceInfo(),\n max,\n },\n this.pollAbort.signal\n );\n this.backoff.reset();\n\n for (const run of response.runs) {\n this.dispatch(run);\n }\n // com trabalho entregue, re-poll imediato (modo drain); sem trabalho, espera o intervalo\n this.schedule(response.runs.length > 0 ? 0 : this.pollIntervalMs);\n } catch (error) {\n if (this.state !== 'started') return; // stop() abortou o poll\n this.schedule(this.backoff.next(error));\n } finally {\n this.pollAbort = undefined;\n }\n }\n\n private dispatch(run: RunDescriptor): void {\n const promise = this.executeClaimed(run)\n .catch(error => this.logger.error(`erro inesperado na run ${run.id}:`, error))\n .finally(() => {\n this.activeRuns.delete(promise);\n if (this.state === 'started') this.schedule(0);\n });\n this.activeRuns.add(promise);\n }\n\n private async executeClaimed(run: RunDescriptor): Promise<void> {\n await executeRun({ run, handler: this.handler, api: this.api, client: this.client, logger: this.logger, tracker: this.tracker });\n }\n}\n","import type { RunTransport } from './api';\nimport type { RunDescriptor } from './protocol';\nimport type { RunTracker } from './registry';\nimport { executeRun } from './runner';\nimport type { AgentHandler } from './types';\nimport type { Client } from '../client';\nimport type { Logger } from '../utils';\n\n/** O que qualquer runner de UMA run precisa para executar o pipeline (`executeRun`). */\nexport interface SingleRunDeps {\n api: RunTransport;\n client: Client | undefined;\n logger: Logger;\n tracker: RunTracker;\n}\n\n/**\n * Uma run por processo: obtém o descritor (abre na plataforma, anexa-se a uma run já\n * reivindicada ou monta localmente) e executa o handler UMA vez pelo pipeline normal.\n * `done` resolve em qualquer desfecho — inclusive quando não houve o que executar.\n */\nexport abstract class SingleRunRunner<D extends SingleRunDeps = SingleRunDeps> {\n protected readonly abort = new AbortController();\n /** Resolve quando a run terminou (ou não pôde começar, ou o runner foi parado antes). */\n readonly done: Promise<void>;\n private resolveDone!: () => void;\n\n constructor(\n protected readonly handler: AgentHandler,\n protected readonly deps: D\n ) {\n this.done = new Promise<void>(resolve => {\n this.resolveDone = resolve;\n });\n }\n\n async run(): Promise<void> {\n try {\n const run = await this.openRun();\n if (!run) return;\n this.deps.logger.debug(this.opened(run));\n await executeRun({\n run,\n handler: this.handler,\n api: this.deps.api,\n client: this.deps.client,\n logger: this.deps.logger,\n tracker: this.deps.tracker,\n });\n } catch (error) {\n this.deps.logger.error('erro inesperado na execução do agente:', error);\n } finally {\n this.resolveDone();\n }\n }\n\n /** Desiste de obter a run (close() antes dela existir). Uma run já em execução segue pelo tracker. */\n stop(): void {\n this.abort.abort();\n }\n\n /** O descritor da run a executar — `undefined` quando não há o que executar (parado, recusado). */\n protected abstract openRun(): Promise<RunDescriptor | undefined>;\n\n /** Linha de debug quando a run foi obtida. */\n protected abstract opened(run: RunDescriptor): string;\n}\n","import { TasksApiError } from './api';\nimport type { LocalRunnerDeps } from './local';\nimport type { RunDescriptor } from './protocol';\nimport { SingleRunRunner } from './single-run';\nimport type { AgentHandler } from './types';\nimport { abortableSleep, jitter } from '../utils';\n\n/** Esperas entre tentativas do início da run — limitadas: esgotadas, o processo desiste e sai. */\nconst START_RETRY_DELAYS_MS: readonly number[] = [1_000, 4_000, 16_000];\n\n/** Rede, timeout, 5xx e 429 são transitórios; qualquer outra rejeição (404, 409, 401…) é definitiva. */\nfunction isTransient(error: unknown): boolean {\n if (!(error instanceof TasksApiError)) return true;\n return error.status >= 500 || error.status === 429;\n}\n\nfunction describeRejection(runId: string, error: unknown): string {\n if (error instanceof TasksApiError && error.status === 404) {\n return `run ${runId} não existe na plataforma (404) — nada a executar`;\n }\n if (error instanceof TasksApiError && error.status === 409) {\n return `run ${runId} não pode ser iniciada (409: cancelada, já iniciada ou de outra instância) — nada a executar`;\n }\n return `não foi possível iniciar a run ${runId} (${String(error)}) — nada a executar`;\n}\n\n/**\n * register() com HOBOTS_RUN_ID: a run já foi criada reivindicada para esta instância\n * (o Studio sobe o bot para executá-la). Em vez do poll, anexa-se a ela\n * (POST /v1/runs/:id/start) e executa o handler UMA vez pelo pipeline normal. Falha\n * transitória tem retry limitado; 404/409 encerram sem executar. `done` resolve em\n * qualquer desfecho — o runtime então faz close() para o processo sair.\n */\nexport class AttachedRunner extends SingleRunRunner<LocalRunnerDeps> {\n constructor(\n private readonly runId: string,\n handler: AgentHandler,\n deps: LocalRunnerDeps\n ) {\n super(handler, deps);\n }\n\n protected opened(run: RunDescriptor): string {\n return `run ${run.id} iniciada (HOBOTS_RUN_ID)`;\n }\n\n protected async openRun(): Promise<RunDescriptor | undefined> {\n for (let attempt = 0; ; attempt++) {\n if (this.abort.signal.aborted) return undefined;\n try {\n return await this.deps.api.startRun(this.runId, { instance: this.deps.instanceInfo() }, this.abort.signal);\n } catch (error) {\n if (this.abort.signal.aborted) return undefined;\n if (!isTransient(error)) {\n this.deps.logger.error(describeRejection(this.runId, error));\n return undefined;\n }\n const delay = START_RETRY_DELAYS_MS[attempt];\n if (delay === undefined) {\n this.deps.logger.error(\n `não foi possível iniciar a run ${this.runId} após ${attempt + 1} tentativas (${String(error)}) — desistindo`\n );\n return undefined;\n }\n const wait = jitter(delay);\n this.deps.logger.warn(`início da run ${this.runId} falhou (${String(error)}), próxima tentativa em ${wait}ms`);\n await abortableSleep(wait, this.abort.signal);\n }\n }\n }\n}\n","import type { ItemColumn } from './protocol';\nimport type { Logger } from '../utils';\nimport { WIRE_LIMITS } from '../wire-limits';\n\n// mesmas regras da plataforma (@workspace/utils/item-columns; limites de WIRE_LIMITS) — coluna fora delas é descartada aqui\nconst KEY_RE = /^[a-zA-Z0-9_.-]{1,100}$/;\nconst MAX_COLUMNS = WIRE_LIMITS.MAX_ITEM_COLUMNS;\nconst MAX_LABEL_CHARS = WIRE_LIMITS.MAX_ITEM_COLUMN_LABEL_CHARS;\n\n/** Coluna de itens como o dev declara: só a chave, ou chave + rótulo. */\nexport type ItemColumnInput = string | { key: string; label?: string };\n\n/**\n * Normaliza `items.columns` do register/start. Nunca lança: coluna inválida,\n * repetida ou além do teto é descartada com aviso (visível com `debug`).\n * Devolve undefined quando não há declaração utilizável.\n */\nexport function normalizeItemColumns(input: unknown, logger: Logger): ItemColumn[] | undefined {\n if (input === undefined || input === null) return undefined;\n const columns = (input as { columns?: unknown }).columns;\n if (typeof input !== 'object' || !Array.isArray(columns)) {\n logger.warn(`items.columns precisa ser uma lista — declaração de colunas ignorada`);\n return undefined;\n }\n\n const result: ItemColumn[] = [];\n const seen = new Set<string>();\n for (const entry of columns as unknown[]) {\n const rawKey = typeof entry === 'string' ? entry : (entry as { key?: unknown } | null)?.key;\n const rawLabel = typeof entry === 'object' && entry !== null ? (entry as { label?: unknown }).label : undefined;\n const key = typeof rawKey === 'string' ? rawKey.trim() : '';\n if (!KEY_RE.test(key)) {\n logger.warn(`coluna de item inválida ignorada (${JSON.stringify(rawKey)}) — use letras, números, ponto, hífen e underline`);\n continue;\n }\n if (seen.has(key)) {\n logger.warn(`coluna de item \"${key}\" repetida ignorada`);\n continue;\n }\n if (result.length >= MAX_COLUMNS) {\n logger.warn(`no máximo ${MAX_COLUMNS} colunas de item — \"${key}\" em diante ignoradas`);\n break;\n }\n seen.add(key);\n const label = typeof rawLabel === 'string' ? rawLabel.trim().slice(0, MAX_LABEL_CHARS) : '';\n result.push(label ? { key, label } : { key });\n }\n return result.length > 0 ? result : undefined;\n}\n","import type { TasksApi } from './api';\nimport { Backoff } from './backoff';\nimport type { InstanceInfo, RunDescriptor } from './protocol';\nimport { SingleRunRunner, type SingleRunDeps } from './single-run';\nimport type { AgentHandler } from './types';\nimport { abortableSleep } from '../utils';\n\n/** Deps dos runners que falam com a plataforma (modo start e run anexada). */\nexport interface LocalRunnerDeps extends SingleRunDeps {\n api: TasksApi;\n /** Presença da instância no momento da criação (modo, colunas de itens, máquina). */\n instanceInfo: () => InstanceInfo;\n}\n\n/**\n * Modo start: o bot abre a própria run na plataforma (POST /v1/runs) e executa\n * o handler UMA vez dentro dela — logs, itens, progresso e anexos fluem pelo mesmo\n * reporter de uma run reivindicada no poll. Enquanto a plataforma não responde, insiste\n * com o ladder do poll: o handler só começa quando a run existe.\n */\nexport class LocalRunner extends SingleRunRunner<LocalRunnerDeps> {\n private readonly backoff: Backoff;\n\n constructor(handler: AgentHandler, deps: LocalRunnerDeps) {\n super(handler, deps);\n this.backoff = new Backoff(deps.logger, 'criação da run');\n }\n\n protected opened(run: RunDescriptor): string {\n return `run ${run.id} aberta (modo start)`;\n }\n\n protected async openRun(): Promise<RunDescriptor | undefined> {\n for (;;) {\n if (this.abort.signal.aborted) return undefined;\n try {\n return await this.deps.api.createRun({ instance: this.deps.instanceInfo() }, this.abort.signal);\n } catch (error) {\n if (this.abort.signal.aborted) return undefined;\n await abortableSleep(this.backoff.next(error), this.abort.signal);\n }\n }\n }\n}\n","import type { RunTransport } from './api';\nimport { printRunLog } from './context';\nimport { collectFileRefs } from './files';\nimport type {\n FileDownloadResponse,\n RunAttachmentCreateRequest,\n RunAttachmentCreateResponse,\n RunItemsCreateRequest,\n RunItemsCreateResponse,\n RunItemsDoneResponse,\n RunItemStatus,\n RunUpdateRequest,\n} from './protocol';\n\n/** Id da run no modo local — nunca chega ao servidor. */\nexport const LOCAL_RUN_ID = 'local';\n/** Prefixo da linha por item no stdout: `[hobots:item] <status>\\t<id>\\t<message>`. */\nexport const ITEM_LINE_PREFIX = '[hobots:item]';\n/** Prefixo da linha de totais no stdout, impressa uma vez no fim da run. */\nexport const SUMMARY_LINE_PREFIX = '[hobots:summary]';\nexport const ATTACHMENTS_DISCARDED_WARNING = 'imagens e anexos não são enviados no modo local (descartados)';\n\n/** Desfecho da run no modo local — vira o exit code do processo (0 / 1 / 130). */\nexport type LocalRunOutcome = 'succeeded' | 'failed' | 'canceled';\n\nfunction unavailable(name: string): Error {\n return new Error(`arquivo \"${name}\" enviado pela Central não está disponível no modo local`);\n}\n\n/** Tab e quebra de linha quebrariam o formato de uma linha por item — viram espaço. */\nfunction cell(value: string | undefined): string {\n // igual ao Python: `\\r\\n` vira UM espaço\n return (value ?? '').replace(/\\r\\n|[\\t\\r\\n]/g, ' ');\n}\n\n/**\n * Transporte do modo local (`HOBOTS_LOCAL_RUN=1`): a mesma superfície que o `RunReporter`\n * e o `RunFileStore` usam da `TasksApi`, sem nenhuma rede. Status e logs são descartados\n * (o eco no terminal já saiu pelo reporter); itens viram uma linha `[hobots:item]` cada e\n * são contados para o `[hobots:summary]` do fim; imagens e anexos são descartados com um\n * aviso único; arquivos enviados pela Central não existem aqui.\n */\nexport class LocalRunTransport implements RunTransport {\n private readonly counts: Record<RunItemStatus, number> = { succeeded: 0, occurrence: 0, failed: 0 };\n private warnedAttachments = false;\n /** Status terminal que o pipeline reportou — `undefined` enquanto a run corre (ou se ela nem reportou). */\n terminalStatus: 'succeeded' | 'failed' | undefined;\n\n constructor(\n /** Params da run — para citar o nome do arquivo da Central que o bot tentou baixar. */\n private readonly params: Record<string, unknown> = {},\n private readonly out: (line: string) => void = line => void process.stdout.write(`${line}\\n`)\n ) {}\n\n async updateRun(_runId: string, update: RunUpdateRequest): Promise<void> {\n if (update.status === 'running') return;\n this.terminalStatus = update.status;\n // sem Central para mostrar o erro, ele sai no stderr: resumo + stack completa; cancelamento não é defeito\n if (update.status === 'failed' && update.error && update.error.type !== 'RunCanceled') {\n printRunLog('error', `execução falhou — ${update.error.type ?? 'Error'}: ${update.error.message}`);\n if (update.error.stack) console.error(update.error.stack);\n }\n }\n\n async updateRunOnce(): Promise<void> {\n // exit path: nada a reportar sem Central\n }\n\n async createItems(_runId: string, request: RunItemsCreateRequest): Promise<RunItemsCreateResponse> {\n for (const item of request.items) {\n this.counts[item.status]++;\n this.out(`${ITEM_LINE_PREFIX} ${item.status}\\t${cell(item.id)}\\t${cell(item.message)}`);\n }\n return { accepted: request.items.length, duplicates: 0 };\n }\n\n // modo local não tem trabalho anterior: nada a pular\n async listDoneItems(): Promise<RunItemsDoneResponse> {\n return { ids: [], next: null };\n }\n\n /** Totais por status — chame uma vez, no fim da run, antes da linha de conclusão. */\n printSummary(): void {\n const { succeeded, occurrence, failed } = this.counts;\n this.out(\n `${SUMMARY_LINE_PREFIX} total=${succeeded + occurrence + failed} ok=${succeeded} avisos=${occurrence} falhas=${failed} pulados=0`\n );\n }\n\n async createAttachment(_runId: string, request: RunAttachmentCreateRequest): Promise<RunAttachmentCreateResponse> {\n if (!this.warnedAttachments) {\n this.warnedAttachments = true;\n printRunLog('warning', ATTACHMENTS_DISCARDED_WARNING);\n }\n // o reporter segue o fluxo normal (upload → confirmação) contra estes no-ops: nenhum outro aviso\n return { id: request.id, upload_url: '', headers: {}, expires_in: 0 };\n }\n\n async uploadAttachment(): Promise<void> {\n // descartado\n }\n\n async confirmAttachment(): Promise<void> {\n // descartado\n }\n\n /** Nome do arquivo pelo id (nos params); sem ele, o próprio id. */\n private fileName(fileId: string): string {\n return collectFileRefs(this.params).find(ref => ref.id === fileId)?.name ?? fileId;\n }\n\n async requestFileDownload(_runId: string, fileId: string): Promise<FileDownloadResponse> {\n throw unavailable(this.fileName(fileId));\n }\n\n async fetchFile(url: string): Promise<Response> {\n throw unavailable(url);\n }\n\n async confirmFileDownload(_runId: string, fileId: string): Promise<void> {\n throw unavailable(this.fileName(fileId));\n }\n}\n","import { printRunLog } from './context';\nimport { LOCAL_RUN_ID, type LocalRunOutcome, type LocalRunTransport } from './local-transport';\nimport type { RunDescriptor } from './protocol';\nimport { SingleRunRunner, type SingleRunDeps } from './single-run';\nimport type { AgentHandler } from './types';\nimport { nowISO } from '../utils';\n\nexport interface LocalRunDeps extends SingleRunDeps {\n api: LocalRunTransport;\n}\n\n/** Exit code do processo por desfecho (SIGINT/SIGTERM = 130, como o shell). */\nexport const LOCAL_RUN_EXIT_CODES: Record<LocalRunOutcome, number> = { succeeded: 0, failed: 1, canceled: 130 };\n/** Depois de SIGINT/SIGTERM, quanto o processo espera o handler parar antes de encerrar mesmo assim. */\nexport const LOCAL_RUN_CANCEL_GRACE_MS = 4_000;\nexport const LOCAL_RUN_BANNER = 'modo local — execução sem a Central; params de HOBOTS_RUN_PARAMS';\n\n/**\n * Modo local (`HOBOTS_LOCAL_RUN=1`): sem Central, a run é montada aqui mesmo (`id` \"local\",\n * params de `HOBOTS_RUN_PARAMS`) e o handler roda UMA vez pelo pipeline normal — o bot testa\n * o mesmo código de produção; só o transporte é o `LocalRunTransport`. `register()` e\n * `start()` se comportam igual neste modo.\n */\nexport class LocalRunRunner extends SingleRunRunner<LocalRunDeps> {\n private canceled = false;\n private startedAt = Date.now();\n private finished = false;\n\n constructor(\n private readonly params: Record<string, unknown>,\n handler: AgentHandler,\n deps: LocalRunDeps\n ) {\n super(handler, deps);\n }\n\n override run(): Promise<void> {\n this.startedAt = Date.now();\n return super.run();\n }\n\n protected opened(): string {\n return 'run local iniciada (HOBOTS_LOCAL_RUN)';\n }\n\n protected async openRun(): Promise<RunDescriptor | undefined> {\n if (this.abort.signal.aborted) return undefined;\n return { id: LOCAL_RUN_ID, params: this.params, form: null, source: 'local', created_at: nowISO() };\n }\n\n /** SIGINT/SIGTERM: dispara o `ctx.signal` da run em voo — o handler para no próximo ponto de parada. */\n cancel(): void {\n this.canceled = true;\n this.deps.tracker.singleActive()?.abort();\n }\n\n /** Desfecho da run: cancelada pelo sinal, senão o status terminal reportado (sem reporte = falha). */\n get outcome(): LocalRunOutcome {\n if (this.canceled) return 'canceled';\n return this.deps.api.terminalStatus ?? 'failed';\n }\n\n /**\n * Fecha o relato no terminal — `[hobots:summary]` e a linha de conclusão — e devolve o\n * desfecho. Idempotente: o runtime chama ao fim da run ou quando a graça do cancelamento\n * esgota com o handler ainda rodando.\n */\n finish(): LocalRunOutcome {\n const outcome = this.outcome;\n if (this.finished) return outcome;\n this.finished = true;\n this.deps.api.printSummary();\n const seconds = Math.round((Date.now() - this.startedAt) / 1000);\n printRunLog('info', `execução local concluída (${outcome}) em ${seconds}s`);\n return outcome;\n }\n}\n","import type { RunTransport } from './api';\nimport type { RunReporter } from './context';\nimport { sleep } from '../utils';\n\n/**\n * Runs em execução no processo, nos dois modos: base do fallback de `hobots.*`\n * fora de um contexto async (run única) e do reporte de emergência no exit path.\n */\nexport class RunTracker {\n private readonly reporters = new Set<RunReporter>();\n private readonly waiters = new Set<() => void>();\n\n constructor(private readonly api: RunTransport) {}\n\n add(reporter: RunReporter): void {\n this.reporters.add(reporter);\n }\n\n remove(reporter: RunReporter): void {\n this.reporters.delete(reporter);\n if (this.reporters.size === 0) {\n for (const resolve of this.waiters) resolve();\n this.waiters.clear();\n }\n }\n\n get activeCount(): number {\n return this.reporters.size;\n }\n\n /** A única run ativa, quando há exatamente uma — o que `hobots.*` usa fora de um contexto async. */\n singleActive(): RunReporter | undefined {\n if (this.reporters.size !== 1) return undefined;\n return this.reporters.values().next().value as RunReporter;\n }\n\n /** Resolve quando não houver mais runs ativas (ou após timeoutMs, devolvendo false). */\n async waitIdle(timeoutMs: number): Promise<boolean> {\n if (this.reporters.size === 0) return true;\n const idle = new Promise<boolean>(resolve => this.waiters.add(() => resolve(true)));\n if (timeoutMs <= 0) return false;\n return Promise.race([idle, sleep(timeoutMs).then(() => false)]);\n }\n\n /**\n * Best-effort do exit path: reporta 'failed'/AgentTerminated para as runs ativas\n * antes do processo morrer, fora da fila do reporter e com timeout curto. Runs já\n * canceladas no app (reporter morto) são puladas; erros de rede são engolidos —\n * o sweep server-side é o backstop.\n */\n async reportAgentTerminated(message: string, timeoutMs = 2_500): Promise<void> {\n const pending: Promise<void>[] = [];\n for (const reporter of this.reporters) {\n if (reporter.isDead) continue;\n // drena os logs pendentes antes do kill (que descarta o buffer) e mata o\n // reporter: o handler zumbi não pode reenviar status por cima do failed\n const logs = reporter.drainLogs();\n reporter.kill();\n pending.push(\n this.api\n .updateRunOnce(\n reporter.context.runId,\n { status: 'failed', error: { type: 'AgentTerminated', message }, logs: logs.length > 0 ? logs : undefined },\n timeoutMs\n )\n .catch(() => {})\n );\n }\n if (pending.length === 0) return;\n await Promise.race([Promise.allSettled(pending), sleep(timeoutMs)]);\n }\n}\n","import { hasInstalledGlobalHandlers } from '../instrument';\nimport { addEmergencyTask, externalListenerCount, markInternal } from '../internal-handlers';\nimport { isNode } from '../utils';\n\nconst WATCHED_SIGNALS = ['SIGINT', 'SIGTERM'] as const;\ntype WatchedSignal = (typeof WATCHED_SIGNALS)[number];\n\n/** O que o exit path precisa saber das runs ativas — implementado pelo RunTracker (poll + start). */\nexport interface ShutdownTarget {\n readonly activeCount: number;\n reportAgentTerminated(message: string): Promise<void>;\n}\n\n/**\n * Rede de segurança do agente: quando o processo morre (sinal ou erro não tratado)\n * com runs em execução, tenta reportar 'failed'/AgentTerminated antes de sair —\n * assim o app mostra a falha na hora, sem esperar o sweep server-side (~120s sem reporte).\n *\n * Nunca interfere no shutdown gracioso: se o programa tem handler próprio para o\n * sinal (ex: SIGINT → close()), o SDK fica quieto e deixa o caminho normal reportar.\n */\nexport function installShutdownHandlers(agent: ShutdownTarget): () => void {\n if (!isNode()) return () => {};\n\n let signaled = false;\n const signalHandlers = new Map<WatchedSignal, () => void>();\n\n for (const signal of WATCHED_SIGNALS) {\n const handler = markInternal(() => {\n // o programa tem handler próprio (shutdown gracioso) — o caminho normal reporta\n if (externalListenerCount(signal) > 0) return;\n if (signaled) return;\n signaled = true;\n\n const reraise = (): void => {\n process.removeListener(signal, handler);\n process.kill(process.pid, signal); // exit default do sinal (código 130/143)\n };\n if (agent.activeCount === 0) {\n reraise();\n return;\n }\n const report = agent.reportAgentTerminated(`o processo do agente recebeu ${signal} durante a execução`);\n addEmergencyTask(report);\n void report.finally(reraise);\n });\n process.on(signal, handler);\n signalHandlers.set(signal, handler);\n }\n\n const onFatal = markInternal((error: Error) => {\n const report =\n agent.activeCount > 0\n ? agent.reportAgentTerminated('o processo do agente morreu com um erro não tratado durante a execução')\n : Promise.resolve();\n addEmergencyTask(report);\n // o exit é decidido pelo instrument (captureUnhandled) ou pelo handler do programa;\n // sem nenhum dos dois, preservamos o comportamento default do Node aqui\n if (!hasInstalledGlobalHandlers() && externalListenerCount('uncaughtException') === 0) {\n void report.finally(() => {\n console.error(error);\n process.exit(1);\n });\n }\n });\n process.on('uncaughtException', onFatal);\n\n return () => {\n for (const [signal, handler] of signalHandlers) process.removeListener(signal, handler);\n process.removeListener('uncaughtException', onFatal);\n };\n}\n","import { Client } from './client';\nimport { resolveConfig } from './config';\nimport {\n fallbackInstanceId,\n INSTANCE_ID_ENV,\n isLocalRun,\n loadDotenv,\n resolveEnvironmentOption,\n resolveInstanceId,\n resolveLocalRunParams,\n resolveRunId,\n} from './env';\nimport { Heartbeat } from './heartbeat';\nimport { installGlobalHandlers } from './instrument';\nimport { externalListenerCount, markInternal } from './internal-handlers';\nimport { MachineSampler } from './machine';\nimport type { EnvironmentInput, EventType } from './protocol';\nimport { TasksApi, type RunTransport } from './tasks/api';\nimport { TaskAgent } from './tasks/agent';\nimport { AttachedRunner } from './tasks/attached';\nimport { image, isImageAttachment, type ImageInput } from './tasks/attachments';\nimport { printRunLog, type RunReporter } from './tasks/context';\nimport { normalizeItemColumns } from './tasks/item-columns';\nimport { LocalRunner } from './tasks/local';\nimport { LOCAL_RUN_BANNER, LOCAL_RUN_CANCEL_GRACE_MS, LOCAL_RUN_EXIT_CODES, LocalRunRunner } from './tasks/local-run';\nimport { LocalRunTransport } from './tasks/local-transport';\nimport type { InstanceInfo, RunLogLevel } from './tasks/protocol';\nimport { RunTracker } from './tasks/registry';\nimport { currentRunReporter } from './tasks/run-context-store';\nimport { installShutdownHandlers } from './tasks/shutdown';\nimport type { AgentHandler, AgentMode, ResolvedRunOptions, RunHandler } from './tasks/types';\nimport type { CaptureAttachment, CaptureHint, HobotsOptions, RegisterOptions, RunOptions, StartOptions } from './types';\nimport { isNode, makeLogger, SDK_VERSION, sleep, type Logger } from './utils';\n\nconst HEARTBEAT_INTERVAL_MS = 30_000;\nconst DEFAULT_RETRIES = 1;\nconst DEFAULT_RETRY_DELAY_MS = 5_000;\nconst DEFAULT_CANCEL_GRACE_MS = 10_000;\nconst MAX_CONCURRENCY = 5;\n\ninterface Runtime {\n options: HobotsOptions;\n /** Telemetria (issues, transactions, heartbeat) — ausente no modo local, que não fala com a Central. */\n client: Client | undefined;\n logger: Logger;\n /** `TasksApi` (rede) ou `LocalRunTransport` (modo local). */\n api: RunTransport;\n /** O handler do agente — um por processo (o agente é a própria tarefa). */\n handler: AgentHandler;\n tracker: RunTracker;\n sampler: MachineSampler | undefined;\n heartbeat: Heartbeat | undefined;\n agent: TaskAgent | undefined;\n local: LocalRunner | undefined;\n /** register() com HOBOTS_RUN_ID: executa só essa run, sem poll. */\n attached: AttachedRunner | undefined;\n /** HOBOTS_LOCAL_RUN=1: handler uma vez, sem Central, e o processo encerra com o exit code do desfecho. */\n localRun: LocalRunRunner | undefined;\n /** Run a que o register() se anexa (opção runId → env HOBOTS_RUN_ID); undefined = poll. */\n runId: string | undefined;\n instanceId: string | undefined;\n environment: EnvironmentInput | undefined;\n pollIntervalMs: number | undefined;\n booted: boolean;\n bootScheduled: boolean;\n bootPromise: Promise<void> | undefined;\n uninstallGlobalHandlers: (() => void) | undefined;\n uninstallShutdown: (() => void) | undefined;\n}\n\nlet runtime: Runtime | undefined;\nlet warnedNoRuntime = false;\n\n/** Hostname da máquina — telemetria (campo `host`), distinto da identidade do agente. */\nfunction hostname(): string | undefined {\n if (!isNode()) return undefined;\n return process.env.HOSTNAME || process.env.COMPUTERNAME || undefined;\n}\n\nfunction baseRuntime(options: HobotsOptions, handler: AgentHandler, logger: Logger, api: RunTransport): Runtime {\n return {\n options: { ...options, clientSecret: undefined },\n client: undefined,\n logger,\n api,\n handler,\n tracker: new RunTracker(api),\n sampler: undefined,\n heartbeat: undefined,\n agent: undefined,\n local: undefined,\n attached: undefined,\n localRun: undefined,\n runId: undefined,\n instanceId: resolveInstanceId(options.instanceId),\n environment: undefined,\n pollIntervalMs: undefined,\n booted: false,\n bootScheduled: false,\n bootPromise: undefined,\n uninstallGlobalHandlers: undefined,\n uninstallShutdown: undefined,\n };\n}\n\n/**\n * Cria o runtime do processo (config, client, handlers globais). `resolveConfig` vem\n * antes de qualquer estado: um secret ausente/inválido lança sem deixar rastro.\n */\nfunction createRuntime(options: HobotsOptions, handler: AgentHandler, logger: Logger): Runtime {\n const config = resolveConfig({ clientSecret: options.clientSecret });\n const environment = resolveEnvironmentOption(options.environment);\n const client = new Client(\n {\n environment,\n release: options.release,\n tags: options.tags,\n debug: options.debug,\n captureRunErrors: options.captureUnhandled !== false,\n },\n config\n );\n const api = new TasksApi({ baseUrl: config.runsBaseUrl, key: config.key, logger });\n const rt = baseRuntime(options, handler, logger, api);\n rt.client = client;\n rt.environment = environment;\n rt.uninstallGlobalHandlers = options.captureUnhandled !== false ? installGlobalHandlers(client) : undefined;\n logger.debug('inicializado', { endpoint: config.ingestEndpoint });\n return rt;\n}\n\n/**\n * Modo local (`HOBOTS_LOCAL_RUN=1`): sem secret, sem rede, sem telemetria. Os params vêm de\n * `HOBOTS_RUN_PARAMS`; inválidos, o processo encerra com código 2 antes de qualquer estado.\n */\nfunction createLocalRunRuntime(options: HobotsOptions, handler: AgentHandler, logger: Logger): Runtime {\n let params: Record<string, unknown>;\n try {\n params = resolveLocalRunParams();\n } catch (error) {\n printRunLog('error', error instanceof Error ? error.message : String(error));\n process.exit(2);\n // só com process.exit substituído (testes) a execução chega aqui — nada é iniciado\n throw error;\n }\n const transport = new LocalRunTransport(params);\n const rt = baseRuntime(options, handler, logger, transport);\n rt.localRun = new LocalRunRunner(params, handler, { api: transport, client: undefined, logger, tracker: rt.tracker });\n printRunLog('info', LOCAL_RUN_BANNER);\n return rt;\n}\n\nfunction validateHandler(handler: unknown, fn: string): void {\n if (typeof handler !== 'function') {\n throw new Error(`[hobots] ${fn}(): o handler precisa ser uma função — ${fn}(async (params) => { ... })`);\n }\n}\n\nfunction clampConcurrency(value: number | undefined): number {\n if (value === undefined || !Number.isFinite(value)) return 1;\n return Math.min(MAX_CONCURRENCY, Math.max(1, Math.floor(value)));\n}\n\nfunction resolveRunOptions(options: RegisterOptions, mode: AgentMode, logger: Logger): ResolvedRunOptions {\n const retries = options.retries === undefined || !Number.isFinite(options.retries) ? DEFAULT_RETRIES : Math.max(0, Math.floor(options.retries));\n return {\n retries,\n retryDelayMs: options.retryDelayMs ?? DEFAULT_RETRY_DELAY_MS,\n timeoutMs: options.timeoutMs && options.timeoutMs > 0 ? options.timeoutMs : undefined,\n concurrency: mode === 'remote' ? clampConcurrency(options.concurrency) : 1,\n logFlushIntervalMs: options.logFlushIntervalMs,\n cancelCheckIntervalMs: options.cancelCheckIntervalMs,\n cancelGraceMs: options.cancelGraceMs ?? DEFAULT_CANCEL_GRACE_MS,\n itemColumns: normalizeItemColumns(options.items, logger),\n };\n}\n\n/** Presença da instância — a mesma nos polls e na criação de runs do modo start. */\nfunction instanceInfo(rt: Runtime): InstanceInfo {\n return {\n /* v8 ignore start -- defensivo: o boot define o instanceId antes de qualquer poll/criação de run */\n instance_id: rt.instanceId ?? 'unknown',\n /* v8 ignore stop */\n version: SDK_VERSION,\n host: hostname(),\n // ambiente da instância: junto do heartbeat, é como o servidor sabe onde o robô roda\n environment: rt.environment,\n // como esta instância trabalha — o painel mostra \"sob demanda\" / \"sempre ligado\"\n mode: rt.handler.mode === 'remote' ? 'on_demand' : 'always_on',\n // colunas da aba \"itens\" declaradas no código — a plataforma usa enquanto o usuário não personalizar\n items: rt.handler.options.itemColumns ? { attributes: rt.handler.options.itemColumns } : undefined,\n // o servidor calcula a tolerância de offline (3×) a partir disto em agentes que fazem\n // poll; clampado à faixa aceita pelo schema (1s..15min)\n poll_interval_ms: rt.agent ? Math.min(Math.max(rt.agent.pollIntervalMs, 1_000), 900_000) : undefined,\n // recursos da máquina — alimenta a série da instância (o servidor grava no máx. 1 ponto/30s)\n machine: rt.sampler?.sample(),\n };\n}\n\n/** A API da plataforma — só fora do modo local (que não tem `TasksApi`). */\nfunction platformApi(rt: Runtime): TasksApi {\n return rt.api as TasksApi;\n}\n\nfunction ensureAgent(rt: Runtime): TaskAgent {\n rt.agent ??= new TaskAgent({\n api: platformApi(rt),\n client: rt.client,\n logger: rt.logger,\n handler: rt.handler,\n tracker: rt.tracker,\n instanceInfo: () => instanceInfo(rt),\n pollIntervalMs: rt.pollIntervalMs,\n });\n return rt.agent;\n}\n\nfunction launchLocal(rt: Runtime): void {\n const runner = new LocalRunner(rt.handler, {\n api: platformApi(rt),\n client: rt.client,\n logger: rt.logger,\n tracker: rt.tracker,\n instanceInfo: () => instanceInfo(rt),\n });\n rt.local = runner;\n void runner.run();\n}\n\n/**\n * Executa a run de HOBOTS_RUN_ID e, terminada (ou recusada), encerra o SDK: sem poll nem\n * outro trabalho, o processo do bot sai sozinho. Se close() já correu (ou outro runtime\n * assumiu), não fecha nada.\n */\nfunction launchAttached(rt: Runtime, runId: string): void {\n const runner = new AttachedRunner(runId, rt.handler, {\n api: platformApi(rt),\n client: rt.client,\n logger: rt.logger,\n tracker: rt.tracker,\n instanceInfo: () => instanceInfo(rt),\n });\n rt.attached = runner;\n void runner.run();\n void runner.done.then(() => {\n if (runtime === rt) void close();\n });\n}\n\n/**\n * Modo local: roda a run e encerra o processo com o exit code do desfecho (0 ok, 1 falha,\n * 130 cancelada). SIGINT/SIGTERM cancelam a run em voo (ctx.signal) e esperam o handler\n * parar por até LOCAL_RUN_CANCEL_GRACE_MS — depois disso o processo encerra mesmo assim.\n * As linhas finais saem antes do exit: o stdout é drenado (write com callback) e só então\n * o processo morre, para um pipe não perder o `[hobots:summary]`.\n */\nfunction launchLocalRun(rt: Runtime, runner: LocalRunRunner): void {\n let finished = false;\n const finish = (): void => {\n if (finished) return;\n finished = true;\n rt.uninstallShutdown?.();\n rt.uninstallShutdown = undefined;\n const code = LOCAL_RUN_EXIT_CODES[runner.finish()];\n if (runtime === rt) void close(0);\n process.stdout.write('', () => process.exit(code));\n };\n if (rt.options.installExitHandlers !== false) {\n let signaled = false;\n const onSignal = (signal: 'SIGINT' | 'SIGTERM'): void => {\n // o programa tem handler próprio para o sinal: ele decide (chame hobots.close() nele)\n if (externalListenerCount(signal) > 0 || signaled) return;\n signaled = true;\n runner.cancel();\n void Promise.race([runner.done, sleep(LOCAL_RUN_CANCEL_GRACE_MS)]).then(finish);\n };\n const onInt = markInternal((): void => onSignal('SIGINT'));\n const onTerm = markInternal((): void => onSignal('SIGTERM'));\n process.on('SIGINT', onInt);\n process.on('SIGTERM', onTerm);\n rt.uninstallShutdown = () => {\n process.off('SIGINT', onInt);\n process.off('SIGTERM', onTerm);\n };\n }\n void runner.run();\n void runner.done.then(finish);\n}\n\n/**\n * Boot único do processo, num microtask depois do register()/start(): o chamador\n * ainda pode instalar handlers de sinal na mesma volta do event loop antes do primeiro\n * poll sair. Se close() correu antes, o runtime já não é este e o boot não faz nada.\n */\nasync function boot(rt: Runtime): Promise<void> {\n if (rt.localRun) {\n // sem Central não há identidade a resolver, métricas, heartbeat nem exit path a instalar\n rt.booted = true;\n launchLocalRun(rt, rt.localRun);\n return;\n }\n if (!rt.instanceId) {\n const id = await fallbackInstanceId();\n if (runtime !== rt) return;\n rt.instanceId = id;\n rt.logger.debug(`instanceId não informado (env ${INSTANCE_ID_ENV}) — usando o hostname \"${id}\"`);\n }\n if (runtime !== rt) return;\n rt.booted = true;\n\n // CPU/memória/disco: no heartbeat e no poll (série da instância) e em contexts.machine\n // dos eventos. start() é assíncrono (import dinâmico de node:os) — até completar,\n // sample() devolve undefined e o SDK segue normalmente.\n if (rt.options.machineMetrics !== false) {\n rt.sampler = new MachineSampler(rt.instanceId, rt.logger);\n void rt.sampler.start();\n rt.client!.attachMachineSampler(rt.sampler);\n }\n\n // heartbeat sempre ligado e ref'd: é ele que mantém o processo vivo no modo start\n // depois que o handler retornou — o SDK fica sempre vivo até close()\n rt.heartbeat = new Heartbeat(rt.client!, { intervalMs: HEARTBEAT_INTERVAL_MS, keepAlive: true }, rt.instanceId, rt.sampler);\n rt.heartbeat.start();\n\n if (rt.options.installExitHandlers !== false) {\n rt.uninstallShutdown = installShutdownHandlers(rt.tracker);\n }\n\n if (rt.handler.mode === 'local') launchLocal(rt);\n else if (rt.runId) launchAttached(rt, rt.runId);\n else ensureAgent(rt).start();\n}\n\nfunction scheduleBoot(rt: Runtime): void {\n /* v8 ignore start -- defensivo: startAgent agenda o boot uma vez, num runtime recém-criado */\n if (rt.bootScheduled) return;\n /* v8 ignore stop */\n rt.bootScheduled = true;\n queueMicrotask(() => {\n rt.bootPromise = boot(rt).catch(error => rt.logger.error('falha ao iniciar o SDK:', error));\n });\n}\n\n/**\n * O agente é a própria tarefa: UM register() ou start() por processo. A segunda chamada\n * lança — não há como um processo ser dois agentes, nem rodar nos dois modos.\n */\nfunction startAgent(fn: 'register' | 'start', mode: AgentMode, handler: RunHandler, options: RegisterOptions): void {\n validateHandler(handler, fn);\n if (runtime) {\n throw new Error(`[hobots] ${fn}(): o agente já foi iniciado — register()/start() só pode ser chamado uma vez por processo (chame hobots.close() antes de iniciar de novo)`);\n }\n const logger = makeLogger(options.debug ?? false);\n const agentHandler: AgentHandler = { mode, handler, options: resolveRunOptions(options, mode, logger) };\n // idempotente: o import do pacote já carregou; aqui cobre bundler que descartou o efeito do import\n // (e a decisão do modo local lê a env antes de qualquer outra coisa)\n loadDotenv();\n // modo local ignora o secret e a HOBOTS_RUN_ID; fora dele, resolveConfig (dentro de createRuntime)\n // lança com secret ausente/inválido ANTES de qualquer estado\n const rt = isLocalRun() ? createLocalRunRuntime(options, agentHandler, logger) : createRuntime(options, agentHandler, logger);\n if (!rt.localRun && mode === 'remote') {\n if (options.pollIntervalMs !== undefined) rt.pollIntervalMs = options.pollIntervalMs;\n rt.runId = resolveRunId(options.runId);\n }\n runtime = rt;\n scheduleBoot(rt);\n}\n\n/**\n * Agente sob demanda: o handler roda a cada solicitação do app (formulário/agendamento), via polling.\n * Com HOBOTS_RUN_ID (ou a opção runId), executa só essa run e encerra — sem poll.\n */\nexport function register<P = Record<string, unknown>>(handler: RunHandler<P>, options: RegisterOptions = {}): void {\n startAgent('register', 'remote', handler as RunHandler, options);\n}\n\n/** Agente sempre ligado: abre a própria run e roda o handler uma vez; a plataforma recebe logs, itens e progresso. */\nexport function start(handler: RunHandler, options: StartOptions = {}): void {\n startAgent('start', 'local', handler, options as RunOptions);\n}\n\n/** Reporter da run atual: contexto async → única run ativa → nenhum. */\nexport function currentReporter(): RunReporter | undefined {\n return currentRunReporter() ?? runtime?.tracker.singleActive();\n}\n\nexport function activeLogger(): Logger | undefined {\n return runtime?.logger;\n}\n\n/** O log da run não tem 'fatal' — rebaixa para 'error'. */\nfunction toRunLogLevel(type: EventType): RunLogLevel {\n return type === 'fatal' ? 'error' : type;\n}\n\n/**\n * Encaminha o `attachment` de um captureException para o pipeline de anexos da run\n * atual (fire-and-forget): a imagem vira anexo da linha de log que espelha o evento.\n * Fora de uma execução não há onde pendurar a imagem — descarta com aviso.\n */\nfunction forwardAttachment(rt: Runtime, attachment: ImageInput | CaptureAttachment, message: string, type: EventType): string | undefined {\n const reporter = currentReporter();\n if (!reporter) {\n rt.logger.warn('attachment descartado — só é suportado dentro de uma execução');\n return undefined;\n }\n const withMeta =\n typeof attachment === 'object' && !isImageAttachment(attachment) && 'image' in attachment\n ? image(attachment.image, { caption: attachment.caption, contentType: attachment.contentType })\n : attachment;\n return reporter.log(toRunLogLevel(type), message, withMeta);\n}\n\n/**\n * Captura uma exceção como issue e retorna o event_id (undefined antes de register()/start()). `hint.attachment` envia um print junto — dentro de uma execução, ele\n * aparece na linha de log da run correspondente ao erro e na própria issue (`contexts.run.attachments`).\n */\nexport function captureException(error: unknown, hint?: CaptureHint): string | undefined {\n const rt = runtime;\n if (!rt) {\n if (!warnedNoRuntime) {\n warnedNoRuntime = true;\n console.warn('[hobots] captureException antes de iniciar o agente (register/start) — evento descartado');\n }\n return undefined;\n }\n let attachmentId: string | undefined;\n if (hint?.attachment) {\n const message = error instanceof Error ? `${error.name}: ${error.message}` : String(error);\n attachmentId = forwardAttachment(rt, hint.attachment, message, hint.type ?? 'error');\n }\n // modo local: sem Central não há issue — o erro já apareceu no terminal pelo próprio bot\n if (!rt.client) {\n rt.logger.debug('captureException ignorado no modo local (sem Central)');\n return undefined;\n }\n // dentro de uma execução, a issue fica ligada a ela (a tag do bot, se houver, vence)\n const runId = currentReporter()?.runId;\n const withRun = runId ? { ...hint, tags: { run_id: runId, ...hint?.tags } } : hint;\n // o print vai junto do evento por referência (o binário é anexo da run): a Central o mostra na issue\n const contexts = runId && attachmentId ? { run: { id: runId, attachments: [attachmentId] } } : undefined;\n return rt.client.captureException(error, withRun, contexts);\n}\n\n/**\n * Encerra tudo: para o polling, aguarda as runs em voo (até timeoutMs), para o\n * heartbeat (libera o processo) e faz o flush final. Um register()/start() depois\n * disto inicia um runtime novo.\n */\nexport async function close(timeoutMs = 30_000): Promise<boolean> {\n const rt = runtime;\n if (!rt) return true;\n runtime = undefined;\n await rt.bootPromise;\n\n // stop(0): só para o polling — a espera pelas runs (dos dois modos) é do tracker, abaixo\n if (rt.agent) await rt.agent.stop(0);\n rt.local?.stop();\n rt.attached?.stop();\n rt.localRun?.stop();\n\n const idle = await rt.tracker.waitIdle(timeoutMs);\n if (!idle) {\n rt.logger.warn(`${rt.tracker.activeCount} run(s) ainda em execução após ${timeoutMs}ms — abandonando a espera`);\n // o processo vai morrer com as runs no meio: falha imediata no app em vez\n // de esperar o sweep server-side marcar o encerramento inesperado\n await rt.tracker.reportAgentTerminated('agente encerrado durante a execução (shutdown excedeu o tempo de espera)');\n }\n\n rt.heartbeat?.stop();\n rt.uninstallShutdown?.();\n rt.uninstallGlobalHandlers?.();\n const flushed = rt.client ? await rt.client.close(timeoutMs) : true;\n return idle && flushed;\n}\n\n/**\n * Apenas para testes internos: zera o singleton sem esperar nada. Não é reexportado\n * por `index.ts` — fora da superfície pública.\n */\nexport function _resetForTesting(): void {\n const rt = runtime;\n runtime = undefined;\n warnedNoRuntime = false;\n if (!rt) return;\n rt.heartbeat?.stop();\n if (rt.agent) void rt.agent.stop(0);\n rt.local?.stop();\n rt.attached?.stop();\n rt.localRun?.stop();\n rt.uninstallShutdown?.();\n rt.uninstallGlobalHandlers?.();\n}\n\n/** Apenas para testes internos: estado interno do runtime atual. */\nexport function _runtimeForTesting():\n | {\n handler: AgentHandler;\n tracker: RunTracker;\n agent: TaskAgent | undefined;\n heartbeat: Heartbeat | undefined;\n localRun: LocalRunRunner | undefined;\n instanceId: string | undefined;\n booted: boolean;\n bootPromise: Promise<void> | undefined;\n client: Client | undefined;\n }\n | undefined {\n return runtime;\n}\n","import * as runtime from './runtime';\nimport { retryWithBackoff, type RetryOptions } from './retry';\nimport { image as makeImage, type AttachInput, type ImageAttachment, type ImageOptions } from './tasks/attachments';\nimport { printRunLog, splitLogArgs } from './tasks/context';\nimport { eachItem, type EachSink } from './tasks/each';\nimport { isFileRef as isFileRefImpl, type RunFiles } from './tasks/files';\nimport type { FileRef, RunLogLevel } from './tasks/protocol';\nimport type { RunContext, RunHandler, RunItems, RunLogger, RunProgressReporter } from './tasks/types';\nimport { Transaction } from './transaction';\nimport type { CaptureHint, RegisterOptions, StartOptions, StepFn, StepOptions } from './types';\nimport { sleep } from './utils';\n\n/**\n * O objeto global do SDK: as funções do processo (register/start/close/captureException/\n * retry) e o contexto da execução ATUAL (log, items, progress, step, signal…),\n * resolvido a cada acesso — funciona de qualquer módulo, sem passar `ctx` de mão em mão.\n */\nexport interface Hobots extends RunContext {\n /**\n * Agente sob demanda: o handler roda a cada solicitação do app (formulário/agendamento), via polling.\n * O agente é a própria tarefa: uma chamada por processo (register OU start).\n */\n register<P = Record<string, unknown>>(handler: RunHandler<P>, options?: RegisterOptions): void;\n /** Agente sempre ligado: abre a própria run e roda o handler; a plataforma recebe logs, itens e progresso. */\n start(handler: RunHandler, options?: StartOptions): void;\n /** Encerra tudo (polling, runs em voo, heartbeat, flush final). Chame antes do processo terminar. */\n close(timeoutMs?: number): Promise<boolean>;\n /** Captura uma exceção como issue (módulo Issues). Retorna o event_id. */\n captureException(error: unknown, hint?: CaptureHint): string | undefined;\n /**\n * Embrulha um print para ir junto de um log, item ou etapa — `hobots.log.error('x', hobots.image(png))`,\n * `hobots.items.failed('x', payload, { image: hobots.image(png, { caption }) })`,\n * `etapa.warning('x', { image: png })`. Puro: nenhum I/O até o evento ser registrado.\n */\n image(input: AttachInput, options?: ImageOptions): ImageAttachment;\n /** O valor tem a forma de um arquivo de campo de upload (`FileRef`) — puro, sem I/O. */\n isFileRef(value: unknown): value is FileRef;\n}\n\ndeclare global {\n // `var` é obrigatório numa declaração global de variável (let/const não viram globalThis.hobots)\n var hobots: Hobots;\n}\n\n// ── fallbacks fora de uma execução ────────────────────────────────────────────\n\nconst warned = new Set<string>();\n\nfunction warnOutsideRun(member: string): void {\n if (warned.has(member)) return;\n warned.add(member);\n const message = `hobots.${member} usado fora de uma execução — ignorado (inicie o agente com register()/start() e use dentro do handler)`;\n const logger = runtime.activeLogger();\n if (logger) logger.warn(message);\n else console.warn(`[hobots] ${message}`);\n}\n\n/** Fora de uma run o log ainda aparece no terminal — só não vai para a plataforma (a imagem é descartada). */\nconst fallbackLogAt =\n (level: RunLogLevel) =>\n (message: unknown, ...rest: unknown[]): void => {\n const { text, image: dropped } = splitLogArgs(message, rest);\n printRunLog(level, dropped ? `${text} [imagem descartada]` : text);\n };\nconst fallbackLog: RunLogger = {\n debug: fallbackLogAt('debug'),\n info: fallbackLogAt('info'),\n warn: fallbackLogAt('warning'),\n error: fallbackLogAt('error'),\n success: fallbackLogAt('success'),\n};\n\nconst noop = (): void => undefined;\n// fora de uma run o `each` ainda percorre a lista (o handler é código do bot) — só não reporta\nconst fallbackEachSink: EachSink = {\n report: noop,\n startStep: () => undefined,\n stepScope: (_step, fn) => fn(),\n declareTotal: noop,\n advance: noop,\n checkCanceled: noop,\n isAborted: () => false,\n /* v8 ignore start -- fora de uma run não há consulta de concluídos, logo nunca há item pulado para anunciar */\n logInfo: message => printRunLog('info', message),\n /* v8 ignore stop */\n logWarning: message => printRunLog('warning', message),\n logError: message => printRunLog('error', message),\n sleep,\n doneItemIds: () => Promise.resolve(undefined),\n flush: () => Promise.resolve(),\n};\nconst fallbackItems: RunItems = {\n add: noop,\n succeeded: noop,\n failed: noop,\n occurrence: noop,\n each: (list, handler, options = {}) => eachItem(list, handler, options, fallbackEachSink),\n};\nconst fallbackProgress: RunProgressReporter = { total: noop, advance: noop, set: noop, current: 0, snapshot: null };\n// fora de uma run não há params (logo, nenhum arquivo) nem run para confirmar o download\nconst outsideRunFiles = (): Promise<never> =>\n Promise.reject(new Error('hobots.files só baixa arquivos dentro de uma execução (handler do register()/start())'));\nconst fallbackFiles: RunFiles = {\n list: () => [],\n get: () => undefined,\n download: outsideRunFiles,\n downloadAll: outsideRunFiles,\n read: outsideRunFiles,\n};\nconst neverAborts = new AbortController().signal;\n\nfunction resolve(member: string): RunContext | undefined {\n const reporter = runtime.currentReporter();\n if (reporter) return reporter.context;\n warnOutsideRun(member);\n return undefined;\n}\n\nfunction getter<K extends keyof RunContext>(member: K, fallback: () => RunContext[K]): PropertyDescriptor {\n return { enumerable: true, get: () => resolve(member)?.[member] ?? fallback() };\n}\n\nfunction method(value: unknown): PropertyDescriptor {\n return { enumerable: true, writable: false, value };\n}\n\nexport const hobots: Hobots = Object.defineProperties({} as Hobots, {\n // ── contexto da run atual (getters) ─────────────────────────────────────────\n runId: getter('runId', () => ''),\n params: getter('params', () => ({})),\n log: getter('log', () => fallbackLog),\n items: getter('items', () => fallbackItems),\n progress: getter('progress', () => fallbackProgress),\n files: getter('files', () => fallbackFiles),\n signal: getter('signal', () => neverAborts),\n step: method(<T>(name: string, fn: StepFn<T>, options?: StepOptions): Promise<T> => {\n const ctx = resolve('step');\n if (ctx) return ctx.step(name, fn, options);\n // fora de uma run: roda `fn` com o mesmo retry, num handle inerte — nada é registrado\n return new Transaction(undefined, 'hobots.detached').step(name, fn, options);\n }),\n throwIfCanceled: method((): void => resolve('throwIfCanceled')?.throwIfCanceled()),\n sleep: method((ms: number): Promise<void> => resolve('sleep')?.sleep(ms) ?? sleep(ms)),\n flush: method((timeoutMs?: number): Promise<void> => resolve('flush')?.flush(timeoutMs) ?? Promise.resolve()),\n retry: method(<T>(fn: (attempt: number) => T | Promise<T>, options?: RetryOptions): Promise<T> => {\n // fora de uma run o retry funciona igual, só sem cancelamento — não é erro de uso\n const reporter = runtime.currentReporter();\n return reporter ? reporter.context.retry(fn, options) : retryWithBackoff(fn, options);\n }),\n // ── processo ────────────────────────────────────────────────────────────────\n register: method(<P>(handler: RunHandler<P>, options?: RegisterOptions): void => {\n runtime.register(handler, options);\n installGlobalHobots();\n }),\n start: method((handler: RunHandler, options?: StartOptions): void => {\n runtime.start(handler, options);\n installGlobalHobots();\n }),\n close: method((timeoutMs?: number): Promise<boolean> => runtime.close(timeoutMs)),\n captureException: method((error: unknown, hint?: CaptureHint): string | undefined => runtime.captureException(error, hint)),\n image: method(makeImage),\n isFileRef: method(isFileRefImpl),\n});\n\n/**\n * Define `globalThis.hobots` — só no register()/start(), nunca na importação,\n * para o pacote continuar sem efeitos colaterais (`sideEffects: false`).\n */\nexport function installGlobalHobots(): void {\n if ((globalThis as { hobots?: unknown }).hobots === hobots) return;\n Object.defineProperty(globalThis, 'hobots', { value: hobots, configurable: true, writable: true, enumerable: false });\n}\n\n/** Apenas para testes internos. */\nexport function _uninstallGlobalHobots(): void {\n warned.clear();\n if ((globalThis as { hobots?: unknown }).hobots === hobots) {\n delete (globalThis as { hobots?: unknown }).hobots;\n }\n}\n\nexport const register = hobots.register;\nexport const start = hobots.start;\nexport const close = hobots.close;\nexport const captureException = hobots.captureException;\nexport const retry = hobots.retry;\nexport const image = hobots.image;\nexport const isFileRef = hobots.isFileRef;\n","import { loadDotenv } from './env';\nimport { hobots } from './hobots';\n\n// no import, antes do código do bot: `process.env.X` no topo do módulo do bot já enxerga o .env\nloadDotenv();\n\nexport { hobots, register, start, close, captureException, retry, image, isFileRef } from './hobots';\nexport { Occurrence } from './tasks/errors';\nexport default hobots;\n\nexport type { Hobots } from './hobots';\nexport type {\n HobotsOptions,\n RunOptions,\n RegisterOptions,\n StartOptions,\n ItemsOptions,\n RetryDelay,\n RetryOptions,\n CaptureHint,\n CaptureAttachment,\n StepOptions,\n StepHandle,\n StepFn,\n} from './types';\nexport type { ItemColumnInput } from './tasks/item-columns';\nexport type {\n RunHandler,\n RunContext,\n RunLogger,\n RunItems,\n RunItemOptions,\n RunItemImageOptions,\n RunItemHandle,\n RunItemsEachHandler,\n RunItemsEachOptions,\n RunItemsEachResult,\n RunProgressReporter,\n} from './tasks/types';\nexport type { AttachInput, ImageInput, ImageOptions, ImageAttachment } from './tasks/attachments';\nexport type { RunFiles, FileDownloadOptions } from './tasks/files';\n\nexport type {\n EventType,\n BreadcrumbLevel,\n StackFrame,\n Breadcrumb,\n ExceptionData,\n EventUser,\n EventPayload,\n StepData,\n StepStatus,\n TransactionPayload,\n HeartbeatPayload,\n MachineProcess,\n MachineSnapshot,\n Environment,\n EnvironmentInput,\n EnvelopeItem,\n Envelope,\n} from './protocol';\n\nexport type {\n RunStatus,\n RunUpdateStatus,\n RunLogLevel,\n RunLogEntry,\n InstanceInfo,\n PollRequest,\n RunDescriptor,\n PollResponse,\n RunCreateRequest,\n RunCreateResponse,\n RunStartRequest,\n RunStartResponse,\n RunError,\n RunProgress,\n RunUpdateRequest,\n RunUpdateResponse,\n RunItemStatus,\n RunItemInput,\n RunItemsCreateRequest,\n RunItemsCreateResponse,\n RunItemsDoneRequest,\n RunItemsDoneResponse,\n ItemColumn,\n ItemsDeclaration,\n InstanceMode,\n RunAttachmentContentType,\n RunAttachmentCreateRequest,\n RunAttachmentCreateResponse,\n RunAttachmentConfirmRequest,\n RunAttachmentConfirmResponse,\n FileStorage,\n FileRef,\n FileDownloadResponse,\n} from './tasks/protocol';\n"],"mappings":";;;;;AAGO,IAAM,WAAW;AAEjB,IAAM,cAAc,OAAsC,UAAkB;AAG5E,SAAS,SAAkB;AAChC,SAAO,OAAO,YAAY,eAAe,OAAO,QAAQ,UAAU,SAAS;AAC7E;AAGO,SAAS,QAAgB;AAC9B,QAAM,YAAa,WAAmC;AACtD,MAAI,aAAa,OAAO,UAAU,eAAe,YAAY;AAC3D,WAAO,UAAU,WAAW,EAAE,QAAQ,MAAM,EAAE;AAAA,EAChD;AACA,MAAI,aAAa,OAAO,UAAU,oBAAoB,YAAY;AAChE,UAAM,QAAQ,UAAU,gBAAgB,IAAI,WAAW,EAAE,CAAC;AAC1D,UAAM,CAAC,IAAK,MAAM,CAAC,IAAK,KAAQ;AAChC,UAAM,CAAC,IAAK,MAAM,CAAC,IAAK,KAAQ;AAChC,WAAO,MAAM,KAAK,OAAO,OAAK,EAAE,SAAS,EAAE,EAAE,SAAS,GAAG,GAAG,CAAC,EAAE,KAAK,EAAE;AAAA,EACxE;AAEA,MAAI,MAAM;AACV,WAAS,IAAI,GAAG,IAAI,IAAI,KAAK;AAC3B,WAAO,KAAK,MAAM,KAAK,OAAO,IAAI,EAAE,EAAE,SAAS,EAAE;AAAA,EACnD;AACA,SAAO;AACT;AAEO,SAAS,SAAiB;AAC/B,UAAO,oBAAI,KAAK,GAAE,YAAY;AAChC;AAGO,SAAS,WAAW,OAAsB;AAC/C,EAAC,OAA8C,QAAQ;AACzD;AAEO,SAAS,MAAM,IAA2B;AAC/C,SAAO,IAAI,QAAQ,CAAAA,aAAW;AAC5B,UAAM,QAAQ,WAAWA,UAAS,EAAE;AACpC,eAAW,KAAK;AAAA,EAClB,CAAC;AACH;AAOO,SAAS,eAAe,IAAY,QAAqC;AAC9E,SAAO,IAAI,QAAQ,CAAAA,aAAW;AAC5B,QAAI,QAAQ,SAAS;AACnB,MAAAA,SAAQ;AACR;AAAA,IACF;AACA,UAAM,UAAU,MAAY;AAC1B,mBAAa,KAAK;AAClB,MAAAA,SAAQ;AAAA,IACV;AACA,UAAM,QAAQ,WAAW,MAAM;AAC7B,cAAQ,oBAAoB,SAAS,OAAO;AAC5C,MAAAA,SAAQ;AAAA,IACV,GAAG,EAAE;AACL,YAAQ,iBAAiB,SAAS,SAAS,EAAE,MAAM,KAAK,CAAC;AAAA,EAC3D,CAAC;AACH;AAGO,SAAS,OAAO,QAAwB;AAC7C,SAAO,KAAK,MAAM,SAAS,IAAI,KAAK,OAAO,KAAK,SAAS,EAAE;AAC7D;AAEO,IAAM,oBAAoB;AAE1B,SAAS,SAAS,OAAe,KAAqB;AAC3D,SAAO,MAAM,SAAS,MAAM,GAAG,MAAM,MAAM,GAAG,GAAG,CAAC,GAAG,iBAAiB,KAAK;AAC7E;AAMO,SAAS,KAAK,OAAe,KAAqB;AACvD,MAAI,MAAM,UAAU,IAAK,QAAO;AAChC,SAAO,GAAG,MAAM,MAAM,GAAG,KAAK,IAAI,GAAG,MAAM,kBAAkB,MAAM,CAAC,CAAC,GAAG,iBAAiB;AAC3F;AAQO,SAAS,WAAW,OAAwB;AACjD,MAAI,OAAO,UAAU,SAAU,QAAO;AACtC,MAAI;AACF,UAAM,OAAO,KAAK,UAAU,KAAK;AACjC,QAAI,QAAQ,SAAS,KAAM,QAAO;AAAA,EACpC,QAAQ;AAAA,EAER;AACA,SAAO,OAAO,KAAK;AACrB;AAEO,IAAM,0BAA6C,CAAC,KAAO,KAAO,IAAM;AAQ/E,eAAsB,eACpB,MACA,SAiBmB;AACnB,QAAM,SAAS,QAAQ,UAAU;AACjC,QAAM,UAAU,QAAQ,mBAAmB,CAAC;AAC5C,WAAS,UAAU,KAAK,WAAW;AACjC,QAAI;AACJ,QAAI;AACJ,QAAI;AACF,YAAM,WAAW,MAAM,KAAK;AAC5B,UAAI,SAAS,GAAI,QAAO;AACxB,UAAI,SAAS,UAAU,OAAO,SAAS,SAAS,OAAO,SAAS,WAAW,IAAK,QAAO;AACvF,UAAI,QAAQ,SAAS,SAAS,MAAM,EAAG,QAAO;AAC9C,UAAI,SAAS,WAAW,IAAK,eAAc,aAAa,QAAQ;AAChE,kBAAY,IAAI,MAAM,QAAQ,SAAS,MAAM,EAAE;AAAA,IACjD,SAAS,OAAO;AACd,kBAAY;AAAA,IACd;AACA,UAAM,UAAU,qBAAqB,QAAQ,YAAY,IAAI,MAAM,OAAO,SAAS,CAAC;AACpF,UAAM,OAAO,OAAO,OAAO;AAC3B,QAAI,SAAS,UAAa,QAAQ,QAAQ,QAAS,OAAM;AACzD,UAAM,QAAQ,eAAe,OAAO,IAAI;AACxC,YAAQ,OAAO,KAAK,GAAG,QAAQ,KAAK,YAAY,OAAO,SAAS,CAAC,eAAe,KAAK,IAAI;AACzF,WAAO,QAAQ,SAAS,eAAe,OAAO,QAAQ,MAAM,IAAI,MAAM,KAAK;AAE3E,QAAI,QAAQ,QAAQ,QAAS,OAAM;AAAA,EACrC;AACF;AAEA,IAAM,qBAAqB;AAGpB,SAAS,aAAa,UAAwC;AACnE,QAAM,SAAS,SAAS,QAAQ,IAAI,aAAa;AACjD,MAAI,CAAC,OAAQ,QAAO;AACpB,QAAM,UAAU,OAAO,MAAM;AAC7B,MAAI,OAAO,SAAS,OAAO,GAAG;AAC5B,WAAO,KAAK,IAAI,oBAAoB,KAAK,IAAI,GAAG,UAAU,GAAK,CAAC;AAAA,EAClE;AACA,QAAM,OAAO,KAAK,MAAM,MAAM;AAC9B,MAAI,OAAO,MAAM,IAAI,EAAG,QAAO;AAC/B,SAAO,KAAK,IAAI,oBAAoB,KAAK,IAAI,GAAG,OAAO,KAAK,IAAI,CAAC,CAAC;AACpE;AAOO,SAAS,kBAAkB,WAAmB,UAAsE;AACzH,QAAM,aAAa,IAAI,gBAAgB;AACvC,QAAM,UAAU,MAAY,WAAW,MAAM,UAAU,MAAM;AAC7D,MAAI,UAAU,SAAS;AACrB,YAAQ;AAAA,EACV,OAAO;AACL,cAAU,iBAAiB,SAAS,SAAS,EAAE,MAAM,KAAK,CAAC;AAAA,EAC7D;AACA,QAAM,QAAQ,WAAW,MAAM;AAC7B,eAAW,MAAM,OAAO,OAAO,IAAI,MAAM,mBAAgB,SAAS,IAAI,GAAG,EAAE,MAAM,eAAe,CAAC,CAAC;AAAA,EACpG,GAAG,SAAS;AACZ,aAAW,KAAK;AAChB,SAAO;AAAA,IACL,QAAQ,WAAW;AAAA,IACnB,SAAS,MAAM;AACb,mBAAa,KAAK;AAClB,gBAAU,oBAAoB,SAAS,OAAO;AAAA,IAChD;AAAA,EACF;AACF;AAQA,IAAM,SAAS;AAER,SAAS,WAAW,SAAkB,SAAiB,QAAgB;AAC5E,SAAO;AAAA,IACL,OAAO,IAAI,SAAS,WAAW,QAAQ,MAAM,SAAS,QAAQ,MAAM,GAAG,GAAG,IAAI;AAAA,IAC9E,MAAM,IAAI,SAAS,WAAW,QAAQ,KAAK,SAAS,QAAQ,QAAQ,GAAG,GAAG,IAAI;AAAA,IAC9E,OAAO,IAAI,SAAS,QAAQ,MAAM,SAAS,QAAQ,KAAK,GAAG,GAAG,IAAI;AAAA,EACpE;AACF;AAEA,IAAM,OAAO;AAAA,EACX,OAAO;AAAA,EACP,MAAM;AAAA,EACN,MAAM;AAAA,EACN,QAAQ;AAAA,EACR,KAAK;AAAA,EACL,OAAO;AACT;AAEA,SAAS,eAAwB;AAE/B,MAAI,CAAC,OAAO,EAAG,QAAO;AAEtB,SAAO,QAAQ,QAAQ,QAAQ,KAAK,KAAK,CAAC,QAAQ,IAAI;AACxD;AAGO,SAAS,SAAS,MAAc,OAAkC;AACvE,MAAI,CAAC,aAAa,EAAG,QAAO;AAC5B,SAAO,GAAG,KAAK,KAAK,CAAC,GAAG,IAAI,GAAG,KAAK,KAAK;AAC3C;;;AC5OO,IAAM,kBAAkB;AACxB,IAAM,kBAAkB;AACxB,IAAM,aAAa;AAEnB,IAAM,gBAAgB;AAEtB,IAAM,iBAAiB;AAE9B,IAAI,eAAe;AAWZ,SAAS,aAAmB;AACjC,MAAI,aAAc;AAClB,iBAAe;AACf,MAAI,CAAC,OAAO,KAAK,OAAO,QAAQ,gBAAgB,WAAY;AAC5D,MAAI;AACF,YAAQ,YAAY,MAAM;AAAA,EAC5B,SAAS,KAAK;AACZ,UAAM,OAAQ,KAAmC;AACjD,QAAI,SAAS,SAAU;AACvB,YAAQ,KAAK,oEAA8D,OAAO,SAAS,WAAW,OAAO,mBAAmB,yDAA8C;AAAA,EAChL;AACF;AAQO,SAAS,kBAAkB,QAAgD;AAChF,QAAM,aAAa,QAAQ,KAAK;AAChC,MAAI,WAAY,QAAO;AACvB,MAAI,OAAO,YAAY,eAAe,CAAC,QAAQ,IAAK,QAAO;AAC3D,SAAO,QAAQ,IAAI,eAAe,GAAG,KAAK,KAAK;AACjD;AAMO,SAAS,aAAa,QAAgD;AAC3E,QAAM,aAAa,QAAQ,KAAK;AAChC,MAAI,WAAY,QAAO;AACvB,MAAI,OAAO,YAAY,eAAe,CAAC,QAAQ,IAAK,QAAO;AAC3D,SAAO,QAAQ,IAAI,UAAU,GAAG,KAAK,KAAK;AAC5C;AAGO,SAAS,aAAsB;AACpC,MAAI,OAAO,YAAY,eAAe,CAAC,QAAQ,IAAK,QAAO;AAC3D,SAAO,QAAQ,IAAI,aAAa,GAAG,KAAK,MAAM;AAChD;AAMO,SAAS,wBAAiD;AAC/D,QAAM,MAAM,QAAQ,IAAI,cAAc,GAAG,KAAK;AAC9C,MAAI,CAAC,IAAK,QAAO,CAAC;AAClB,MAAI;AACJ,MAAI;AACF,aAAS,KAAK,MAAM,GAAG;AAAA,EACzB,QAAQ;AACN,UAAM,IAAI,MAAM,GAAG,cAAc,0CAA8B;AAAA,EACjE;AACA,MAAI,WAAW,QAAQ,OAAO,WAAW,YAAY,MAAM,QAAQ,MAAM,GAAG;AAC1E,UAAM,IAAI,MAAM,GAAG,cAAc,uCAAoC;AAAA,EACvE;AACA,SAAO;AACT;AAGO,SAAS,yBAAyB,QAAoE;AAC3G,QAAM,aAAa,QAAQ,KAAK;AAChC,MAAI,WAAY,QAAO;AACvB,MAAI,OAAO,YAAY,eAAe,CAAC,QAAQ,IAAK,QAAO;AAC3D,SAAO,QAAQ,IAAI,eAAe,GAAG,KAAK,KAAK;AACjD;AAMA,eAAsB,qBAAsC;AAC1D,MAAI,CAAC,OAAO,EAAG,QAAO;AACtB,MAAI;AACF,UAAM,KAAK,MAAM,OAAO,IAAS;AACjC,WAAO,GAAG,SAAS,KAAK;AAAA,EAC1B,QAAQ;AACN,WAAO;AAAA,EACT;AACF;;;ACtGA,IAAM,aAAa;AAEnB,IAAM,qBAAqB;AAG3B,IAAM,WAAW;AACjB,IAAM,cAAc;AAEpB,SAAS,QAAQ,UAAuC;AACtD,MAAI,CAAC,SAAU,QAAO;AACtB,MAAI,SAAS,WAAW,OAAO,EAAG,QAAO;AACzC,MAAI,SAAS,WAAW,WAAW,EAAG,QAAO;AAC7C,MAAI,SAAS,SAAS,cAAc,EAAG,QAAO;AAC9C,MAAI,aAAa,cAAe,QAAO;AACvC,SAAO;AACT;AAGO,SAAS,gBAAgB,OAAgD;AAC9E,MAAI,CAAC,MAAO,QAAO,CAAC;AAEpB,QAAM,SAAuB,CAAC;AAC9B,aAAW,QAAQ,MAAM,MAAM,IAAI,GAAG;AACpC,QAAI,OAAO,UAAU,WAAY;AACjC,UAAM,QAAQ,SAAS,KAAK,IAAI;AAChC,QAAI,CAAC,SAAS,CAAC,KAAK,UAAU,EAAE,WAAW,KAAK,EAAG;AAEnD,UAAM,CAAC,EAAE,IAAI,QAAQ,IAAI;AAEzB,UAAM,MAAM,YAAY,KAAK,YAAY,EAAE;AAE3C,UAAM,WAAW,MAAM,IAAI,CAAC,IAAI;AAChC,WAAO,KAAK;AAAA,MACV,UAAU,MAAM;AAAA,MAChB,UAAU,WAAW,SAAS,MAAM,GAAG,kBAAkB,IAAI;AAAA,MAC7D,QAAQ,MAAM,CAAC,IAAI,OAAO,IAAI,CAAC,CAAC,IAAI;AAAA,MACpC,OAAO,MAAM,CAAC,IAAI,OAAO,IAAI,CAAC,CAAC,IAAI;AAAA,MACnC,QAAQ,QAAQ,QAAQ;AAAA,IAC1B,CAAC;AAAA,EACH;AACA,SAAO;AACT;;;ACtCA,IAAM,kBAA4D;AAAA;AAAA,EAEhE,CAAC,sBAAsB,YAAY;AAAA;AAAA,EAEnC,CAAC,yDAAyD,mBAAmB;AAAA;AAAA,EAE7E,CAAC,4BAA4B,YAAY;AAAA;AAAA,EAEzC,CAAC,4BAA4B,eAAe;AAC9C;AAEO,SAAS,aAAa,MAAsB;AACjD,MAAI,MAAM;AACV,aAAW,CAAC,SAAS,WAAW,KAAK,iBAAiB;AACpD,UAAM,IAAI,QAAQ,SAAS,WAAW;AAAA,EACxC;AACA,SAAO;AACT;;;AChBO,IAAM,4BAA4B;AAElC,SAAS,mBAAmB,OAAgB,OAAkB,SAAuB;AAC1F,MAAI;AACJ,MAAI;AACJ,MAAI,SAAS,CAAC;AAEd,MAAI,iBAAiB,OAAO;AAC1B,oBAAgB,MAAM,QAAQ;AAC9B,YAAQ,SAAS,aAAa,MAAM,OAAO,GAAG,yBAAyB;AACvE,aAAS,gBAAgB,MAAM,KAAK;AAAA,EACtC,OAAO;AACL,oBAAgB;AAChB,YAAQ,SAAS,aAAa,WAAW,KAAK,CAAC,GAAG,yBAAyB;AAAA,EAC7E;AAEA,SAAO;AAAA,IACL,UAAU,MAAM;AAAA,IAChB,WAAW,OAAO;AAAA,IAClB;AAAA,IACA,WAAW;AAAA,MACT,MAAM;AAAA,MACN;AAAA,MACA,GAAI,OAAO,SAAS,IAAI,EAAE,YAAY,EAAE,OAAO,EAAE,IAAI,CAAC;AAAA,IACxD;AAAA,EACF;AACF;;;AC5BA,IAAM,qBAAqB;AAC3B,IAAM,4BAA4B;AAClC,IAAM,yBAAyB;AAC/B,IAAM,yBAAyB;AAO/B,IAAM,yBAAyB,YAAY;AAapC,IAAM,YAAN,MAAgB;AAAA,EACJ;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAET,SAAyB,CAAC;AAAA,EAC1B;AAAA,EACA,UAAU,oBAAI,IAAmB;AAAA,EACjC,SAAS;AAAA,EAEjB,YAAY,SAA2B;AACrC,SAAK,WAAW,QAAQ;AACxB,SAAK,MAAM,QAAQ;AACnB,SAAK,SAAS,QAAQ;AACtB,SAAK,kBAAkB,QAAQ,mBAAmB;AAClD,SAAK,eAAe,QAAQ,gBAAgB;AAC5C,SAAK,eAAe,QAAQ,gBAAgB;AAAA,EAC9C;AAAA,EAEA,QAAQ,MAA0B;AAChC,QAAI,KAAK,QAAQ;AACf,WAAK,OAAO,KAAK,uCAAuC,KAAK,IAAI;AACjE;AAAA,IACF;AACA,QAAI,KAAK,OAAO,UAAU,KAAK,cAAc;AAG3C,YAAM,YAAY,KAAK,OAAO,UAAU,YAAU,OAAO,SAAS,WAAW;AAC7E,WAAK,OAAO,OAAO,cAAc,KAAK,IAAI,WAAW,CAAC;AACtD,WAAK,OAAO,KAAK,yCAAyC;AAAA,IAC5D;AACA,SAAK,OAAO,KAAK,IAAI;AAErB,QAAI,KAAK,OAAO,UAAU,KAAK,cAAc;AAC3C,WAAK,KAAK,YAAY;AAAA,IACxB,OAAO;AACL,WAAK,SAAS;AAAA,IAChB;AAAA,EACF;AAAA,EAEQ,WAAiB;AACvB,QAAI,KAAK,MAAO;AAChB,SAAK,QAAQ,WAAW,MAAM;AAC5B,WAAK,QAAQ;AACb,WAAK,KAAK,YAAY;AAAA,IACxB,GAAG,KAAK,eAAe;AACvB,eAAW,KAAK,KAAK;AAAA,EACvB;AAAA,EAEQ,cAA6B;AACnC,QAAI,KAAK,OAAO;AACd,mBAAa,KAAK,KAAK;AACvB,WAAK,QAAQ;AAAA,IACf;AACA,QAAI,KAAK,OAAO,WAAW,EAAG,QAAO,QAAQ,QAAQ;AAKrD,UAAM,QAAQ,KAAK,OAAO,OAAO,GAAG,KAAK,OAAO,MAAM;AACtD,UAAM,QAAyB,CAAC;AAChC,aAAS,SAAS,GAAG,SAAS,MAAM,QAAQ,UAAU,wBAAwB;AAC5E,YAAM,KAAK,KAAK,KAAK,MAAM,MAAM,QAAQ,SAAS,sBAAsB,CAAC,CAAC;AAAA,IAC5E;AACA,WAAO,QAAQ,IAAI,KAAK,EAAE,KAAK,MAAM,MAAS;AAAA,EAChD;AAAA;AAAA,EAGQ,KAAK,OAAsC;AACjD,UAAM,WAAqB;AAAA,MACzB,KAAK,EAAE,MAAM,UAAU,SAAS,YAAY;AAAA,MAC5C,SAAS,OAAO;AAAA,MAChB;AAAA,IACF;AAEA,UAAM,UAAyB,KAAK,cAAc,QAAQ,EAAE,QAAQ,MAAM;AACxE,WAAK,QAAQ,OAAO,OAAO;AAAA,IAC7B,CAAC;AACD,SAAK,QAAQ,IAAI,OAAO;AACxB,WAAO;AAAA,EACT;AAAA,EAEA,MAAc,cAAc,UAAmC;AAC7D,QAAI;AACJ,QAAI;AACF,iBAAW,MAAM;AAAA,QACf,MACE,MAAM,KAAK,UAAU;AAAA,UACnB,UAAU;AAAA,UACV,QAAQ;AAAA,UACR,SAAS,EAAE,gBAAgB,oBAAoB,eAAe,UAAU,KAAK,GAAG,GAAG;AAAA,UACnF,MAAM,KAAK,UAAU,QAAQ;AAAA,UAC7B,QAAQ,YAAY,QAAQ,kBAAkB;AAAA,QAChD,CAAC;AAAA,QACH,EAAE,QAAQ,KAAK,QAAQ,OAAO,oBAAoB;AAAA,MACpD;AAAA,IACF,SAAS,OAAO;AACd,WAAK,OAAO,MAAM,wCAAqC,KAAK;AAC5D;AAAA,IACF;AACA,QAAI,SAAS,IAAI;AACf,WAAK,OAAO,MAAM,qBAAqB,SAAS,MAAM,MAAM,SAAS;AACrE;AAAA,IACF;AAEA,SAAK,OAAO,MAAM,4BAA4B,SAAS,MAAM,kBAAkB,SAAS,MAAM,MAAM,SAAS;AAAA,EAC/G;AAAA;AAAA,EAGA,MAAM,MAAM,YAAY,KAAyB;AAC/C,SAAK,KAAK,YAAY;AACtB,UAAM,MAAM,QAAQ,WAAW,CAAC,GAAG,KAAK,OAAO,CAAC,EAAE,KAAK,MAAM,IAAI;AACjE,WAAO,QAAQ,KAAK,CAAC,KAAK,MAAM,SAAS,EAAE,KAAK,MAAM,KAAK,CAAC,CAAC;AAAA,EAC/D;AAAA,EAEA,MAAM,MAAM,YAAY,KAAyB;AAC/C,UAAM,SAAS,MAAM,KAAK,MAAM,SAAS;AACzC,SAAK,SAAS;AACd,WAAO;AAAA,EACT;AACF;;;AC5IO,IAAM,sBAAsB;AAC5B,IAAM,wBAAwB;AAC9B,IAAM,6BAA6B;AACnC,IAAM,6BAA6B;AACnC,IAAM,YAAY;AAElB,IAAM,6BAA6B;AAEnC,IAAM,oBAAoB;AAEjC,SAAS,SAAS,MAAsD;AACtE,SAAO,OAAO,YAAY,OAAO,QAAQ,IAAI,EAAE,IAAI,CAAC,CAAC,KAAK,KAAK,MAAM,CAAC,KAAK,SAAS,OAAO,KAAK,GAAG,mBAAmB,CAAC,CAAC,CAAC;AAC3H;AAGA,SAAS,SAAS,MAA0B;AAC1C,SAAO;AAAA,IACL,GAAG;AAAA,IACH,GAAI,KAAK,KAAK,EAAE,IAAI,KAAK,KAAK,IAAI,iBAAiB,EAAE,IAAI,CAAC;AAAA,IAC1D,GAAI,KAAK,cAAc,EAAE,aAAa,KAAK,KAAK,aAAa,0BAA0B,EAAE,IAAI,CAAC;AAAA,EAChG;AACF;AAEA,SAAS,gBAAgB,aAAyD;AAChF,MAAI,gBAAgB,OAAW,QAAO;AACtC,SAAO,YAAY,MAAM,GAAG,qBAAqB,EAAE,IAAI,UAAQ,SAAS,OAAO,IAAI,GAAG,0BAA0B,CAAC;AACnH;AAoBA,IAAM,WAAW,oBAAI,QAAgB;AAG9B,SAAS,YAAY,OAAyB;AACnD,SAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,SAAS,IAAI,KAAK;AAC1E;AAEA,SAAS,kBAA2D;AAClE,MAAI,OAAO,GAAG;AACZ,WAAO;AAAA,MACL,SAAS,EAAE,MAAM,QAAQ,SAAS,QAAQ,QAAQ;AAAA,MAClD,IAAI,EAAE,MAAM,QAAQ,UAAU,MAAM,QAAQ,KAAK;AAAA,IACnD;AAAA,EACF;AACA,SAAO,EAAE,SAAS,EAAE,MAAM,UAAU,EAAE;AACxC;AAEO,IAAM,SAAN,MAAa;AAAA,EACT;AAAA;AAAA,EAEA;AAAA;AAAA;AAAA;AAAA,EAIA;AAAA,EACA;AAAA,EACQ;AAAA,EACT;AAAA,EAER,YAAY,SAAwB,QAAwB;AAC1D,SAAK,WAAW;AAChB,SAAK,QAAQ,CAAC,CAAC,QAAQ;AACvB,SAAK,SAAS,WAAW,KAAK,KAAK;AACnC,SAAK,UAAU;AACf,SAAK,YAAY,IAAI,UAAU;AAAA,MAC7B,UAAU,KAAK,QAAQ;AAAA,MACvB,KAAK,KAAK,QAAQ;AAAA,MAClB,QAAQ,KAAK;AAAA,MACb,iBAAiB,QAAQ;AAAA,MACzB,cAAc,QAAQ;AAAA,IACxB,CAAC;AAAA,EACH;AAAA,EAEA,IAAI,UAAyB;AAC3B,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,IAAI,SAAyB;AAC3B,WAAO,KAAK;AAAA,EACd;AAAA;AAAA,EAGA,qBAAqB,SAA2C;AAC9D,SAAK,UAAU;AAAA,EACjB;AAAA;AAAA,EAGA,SAAkC;AAChC,WAAO,EAAE,KAAK,UAAU,SAAS,aAAa,SAAS,KAAK,QAAQ,QAAQ;AAAA,EAC9E;AAAA,EAEA,CAAC,uBAAO,IAAI,4BAA4B,CAAC,IAAY;AACnD,WAAO,sBAAsB,KAAK,QAAQ,OAAO;AAAA,EACnD;AAAA;AAAA,EAGA,iBAAiB,OAAgB,MAAoB,UAA4D;AAC/G,QAAI,OAAO,UAAU,YAAY,UAAU,KAAM,UAAS,IAAI,KAAK;AACnE,WAAO,KAAK,aAAa,mBAAmB,OAAO,MAAM,QAAQ,OAAO,GAAG,MAAM,QAAQ;AAAA,EAC3F;AAAA,EAEA,aAAa,OAAqB,MAAoB,UAA4D;AAChH,UAAM,QAAQ,KAAK,aAAa,WAAW,EAAE,GAAG,OAAO,UAAU,EAAE,GAAG,UAAU,GAAG,MAAM,SAAS,EAAE,IAAI,OAAO,IAAI;AACnH,SAAK,UAAU,QAAQ,EAAE,MAAM,SAAS,SAAS,MAAM,CAAC;AACxD,WAAO,MAAM;AAAA,EACf;AAAA,EAEQ,aAAa,OAAqB,MAA6C;AACrF,UAAM,OAAO,EAAE,GAAG,KAAK,QAAQ,MAAM,GAAG,MAAM,MAAM,GAAG,MAAM,KAAK;AAClE,UAAM,QAAQ,EAAE,GAAG,MAAM,OAAO,GAAG,MAAM,MAAM;AAG/C,UAAM,UAAU,KAAK,SAAS,OAAO;AACrC,UAAM,UAAmD,UAAU,EAAE,SAAS,QAA8C,IAAI,CAAC;AAEjI,WAAO;AAAA,MACL,GAAG;AAAA,MACH,MAAM,MAAM,QAAQ,MAAM,QAAQ;AAAA,MAClC,SAAS,MAAM,WAAW,KAAK,QAAQ;AAAA,MACvC,aAAa,KAAK,mBAAmB,MAAM,WAAW;AAAA,MACtD,MAAM,OAAO,KAAK,IAAI,EAAE,SAAS,IAAI,SAAS,IAAI,IAAI;AAAA,MACtD,OAAO,OAAO,KAAK,KAAK,EAAE,SAAS,IAAI,QAAQ;AAAA,MAC/C,UAAU,EAAE,GAAG,gBAAgB,GAAG,GAAG,SAAS,GAAG,MAAM,SAAS;AAAA,MAChE,aAAa,gBAAgB,MAAM,eAAe,MAAM,WAAW;AAAA,IACrE;AAAA,EACF;AAAA,EAEA,gBAAgB,SAAmC;AACjD,QAAI,QAAQ,QAAQ;AACpB,QAAI,MAAM,SAAS,WAAW;AAC5B,WAAK,OAAO,KAAK,mBAAmB,MAAM,MAAM,wCAAmC,SAAS,EAAE;AAC9F,cAAQ,MAAM,MAAM,GAAG,SAAS;AAAA,IAClC;AACA,YAAQ,MAAM,IAAI,QAAQ;AAC1B,SAAK,UAAU,QAAQ;AAAA,MACrB,MAAM;AAAA,MACN,SAAS;AAAA,QACP,GAAG;AAAA,QACH,MAAM,KAAK,QAAQ,QAAQ,cAAc,0BAA0B;AAAA,QACnE;AAAA,QACA,SAAS,QAAQ,WAAW,KAAK,QAAQ;AAAA,QACzC,aAAa,KAAK,mBAAmB,QAAQ,WAAW;AAAA,QACxD,MAAM,SAAS,EAAE,GAAG,KAAK,QAAQ,MAAM,GAAG,QAAQ,KAAK,CAAC;AAAA,MAC1D;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEA,cAAc,SAAiC;AAC7C,SAAK,UAAU,QAAQ;AAAA,MACrB,MAAM;AAAA,MACN,SAAS;AAAA,QACP,GAAG;AAAA,QACH,SAAS,QAAQ,WAAW,KAAK,QAAQ;AAAA;AAAA,QAEzC,aAAa,KAAK,mBAAmB,QAAQ,WAAW;AAAA,MAC1D;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,mBAAmB,OAAuD;AAChF,WAAO,SAAS,KAAK,QAAQ,eAAe;AAAA,EAC9C;AAAA,EAEA,MAAM,WAAsC;AAC1C,WAAO,KAAK,UAAU,MAAM,SAAS;AAAA,EACvC;AAAA,EAEA,MAAM,WAAsC;AAC1C,WAAO,KAAK,UAAU,MAAM,SAAS;AAAA,EACvC;AACF;;;ACxMO,IAAM,mBAAmB;AAiBzB,IAAM,oBAAoB;AAEjC,SAAS,kBAAsC;AAC7C,MAAI,OAAO,YAAY,eAAe,CAAC,QAAQ,IAAK,QAAO;AAC3D,SAAO,QAAQ,IAAI,iBAAiB,GAAG,KAAK,KAAK;AACnD;AAGA,IAAM,iBAAiB;AAMvB,SAAS,aAAiC;AAExC,MAAI,OAAO,YAAY,eAAe,CAAC,QAAQ,IAAK,QAAO;AAC3D,SAAO,QAAQ,IAAI,gBAAgB,KAAK,KAAK;AAC/C;AAEA,SAAS,eAAeC,WAA2B;AACjD,SACEA,cAAa,eACbA,UAAS,SAAS,YAAY,KAC9BA,UAAS,WAAW,MAAM,KAC1BA,cAAa,WACbA,cAAa,SACbA,cAAa;AAEjB;AAMA,SAAS,gBAAgB,KAAa,QAAwB;AAC5D,MAAI;AACJ,MAAI;AACF,UAAM,IAAI,IAAI,GAAG;AAAA,EACnB,QAAQ;AACN,UAAM,IAAI,MAAM,GAAG,MAAM,qFAA6E;AAAA,EACxG;AACA,MAAI,IAAI,aAAa,WAAW,IAAI,aAAa,UAAU;AACzD,UAAM,IAAI,MAAM,GAAG,MAAM,gCAAgC,IAAI,QAAQ,uCAA+B;AAAA,EACtG;AACA,MAAI,IAAI,YAAY,IAAI,UAAU;AAChC,UAAM,IAAI,MAAM,GAAG,MAAM,iHAA6F;AAAA,EACxH;AAEA,MAAI,IAAI,aAAa,WAAW,CAAC,eAAe,IAAI,QAAQ,GAAG;AAC7D,UAAM,IAAI,MAAM,GAAG,MAAM,gDAAgD,IAAI,QAAQ,wDAAmD;AAAA,EAC1I;AACA,SAAO,IAAI,QAAQ,QAAQ,EAAE;AAC/B;AAGO,SAAS,cAAc,UAAuB,CAAC,GAAG,SAAS,YAA4B;AAC5F,QAAM,aAAa,QAAQ,cAAc,KAAK;AAC9C,QAAM,MAAM,cAAc,gBAAgB;AAC1C,QAAM,SAAS,aAAa,iBAAiB,OAAO,iBAAiB;AACrE,MAAI,CAAC,KAAK;AACR,UAAM,IAAI;AAAA,MACR,GAAG,MAAM,8CAAyC,iBAAiB;AAAA,IACrE;AAAA,EACF;AACA,MAAI,CAAC,eAAe,KAAK,GAAG,GAAG;AAE7B,UAAM,IAAI;AAAA,MACR,GAAG,MAAM,IAAI,MAAM,6BAA0B,IAAI,MAAM;AAAA,IACzD;AAAA,EACF;AAEA,QAAM,UAAU,gBAAgB,WAAW,KAAK,kBAAkB,MAAM;AAExE,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,gBAAgB,GAAG,OAAO;AAAA,IAC1B,aAAa,GAAG,OAAO;AAAA,EACzB;AACF;;;AC7FA,IAAM,sBAAsB,YAAY;AAIxC,IAAM,2BAA2B,YAAY;AAC7C,IAAM,2BAA2B,YAAY;AAiBtC,IAAM,YAAN,MAAgB;AAAA,EAQrB,YACmB,QACjB,UAA4B,CAAC,GAC7B,YACiB,SACjB;AAJiB;AAGA;AAEjB,SAAK,aAAa,QAAQ,cAAc;AACxC,SAAK,aAAa;AAClB,SAAK,OAAO,QAAQ,QAAQ;AAC5B,SAAK,WAAW,QAAQ;AACxB,SAAK,YAAY,QAAQ,aAAa;AAAA,EACxC;AAAA,EAVmB;AAAA,EAGA;AAAA,EAXF;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACT;AAAA,EAeR,QAAc;AACZ,QAAI,KAAK,MAAO;AAChB,SAAK,KAAK;AACV,SAAK,SAAS;AAAA,EAChB;AAAA;AAAA,EAGQ,WAAiB;AACvB,SAAK,QAAQ;AAAA,MACX,MAAM;AACJ,aAAK,KAAK;AACV,aAAK,SAAS;AAAA,MAChB;AAAA,MACA,KAAK,cAAc,MAAM,KAAK,OAAO,IAAI;AAAA,IAC3C;AACA,QAAI,CAAC,KAAK,UAAW,YAAW,KAAK,KAAK;AAAA,EAC5C;AAAA,EAEA,OAAa;AACX,QAAI,KAAK,OAAO;AACd,mBAAa,KAAK,KAAK;AACvB,WAAK,QAAQ;AAAA,IACf;AAAA,EACF;AAAA,EAEQ,OAAa;AACnB,SAAK,OAAO,cAAc;AAAA,MACxB,aAAa,KAAK;AAAA,MAClB,MAAM,KAAK;AAAA,MACX,aAAa,KAAK,IAAI,KAAK,IAAI,KAAK,YAAY,wBAAwB,GAAG,wBAAwB;AAAA,MACnG,WAAW,OAAO;AAAA,MAClB,UAAU,KAAK;AAAA;AAAA,MAEf,SAAS,KAAK,SAAS,OAAO;AAAA,IAChC,CAAC;AAAA,EACH;AACF;;;AC7EA,IAAM,WAAW,uBAAO,IAAI,6BAA6B;AAIlD,SAAS,aAAsD,UAAgB;AACpF,EAAC,SAAoB,QAAQ,IAAI;AACjC,SAAO;AACT;AAGO,SAAS,sBAAsB,OAAuB;AAC3D,QAAM,YAAY,QAAQ,UAAU,KAA4B;AAChE,SAAO,UAAU,OAAO,cAAY,CAAE,SAAoB,QAAQ,CAAC,EAAE;AACvE;AAEA,IAAM,iBAAqC,CAAC;AAGrC,SAAS,iBAAiB,MAA8B;AAC7D,iBAAe,KAAK,IAAI;AAExB,QAAM,SAAS,MAAY;AACzB,UAAM,QAAQ,eAAe,QAAQ,IAAI;AAEzC,QAAI,UAAU,GAAI,gBAAe,OAAO,OAAO,CAAC;AAAA,EAElD;AACA,OAAK,KAAK,QAAQ,MAAM;AAC1B;AAOA,eAAsB,oBAAoB,OAA8B;AACtE,MAAI,eAAe,WAAW,EAAG;AACjC,QAAM,QAAQ,KAAK,CAAC,QAAQ,WAAW,cAAc,GAAG,MAAM,KAAK,CAAC,CAAC;AACvE;;;ACzCA,IAAM,0BAA0B;AAEhC,IAAI,YAAY;AAGT,SAAS,6BAAsC;AACpD,SAAO;AACT;AAOO,SAAS,sBAAsB,QAA4B;AAChE,MAAI,UAAW,QAAO,MAAM;AAC5B,cAAY;AAEZ,MAAI,OAAO,GAAG;AACZ,UAAM,aAAa,aAAa,CAAC,UAAiB;AAC9C,aAAO,iBAAiB,OAAO,EAAE,MAAM,SAAS,MAAM,EAAE,WAAW,oBAAoB,EAAE,CAAC;AAC1F,WAAK,OAAO,MAAM,GAAK,EAAE,KAAK,YAAY;AAGxC,YAAI,sBAAsB,mBAAmB,MAAM,GAAG;AAEpD,gBAAM,oBAAoB,uBAAuB;AACjD,kBAAQ,MAAM,KAAK;AACnB,kBAAQ,KAAK,CAAC;AAAA,QAChB;AAAA,MACF,CAAC;AAAA,IACH,CAAC;AAEH,UAAM,cAAc,aAAa,CAAC,WAAoB;AACpD,aAAO,iBAAiB,QAAQ,EAAE,MAAM,SAAS,MAAM,EAAE,WAAW,qBAAqB,EAAE,CAAC;AAE5F,WAAK,OAAO,MAAM,GAAK;AAAA,IACzB,CAAC;AAGD,UAAM,eAAe,aAAa,MAAM;AACtC,WAAK,OAAO,MAAM,GAAK;AAAA,IACzB,CAAC;AAED,YAAQ,GAAG,qBAAqB,UAAU;AAC1C,YAAQ,GAAG,sBAAsB,WAAW;AAC5C,YAAQ,GAAG,cAAc,YAAY;AAErC,WAAO,MAAM;AACX,cAAQ,IAAI,qBAAqB,UAAU;AAC3C,cAAQ,IAAI,sBAAsB,WAAW;AAC7C,cAAQ,IAAI,cAAc,YAAY;AACtC,kBAAY;AAAA,IACd;AAAA,EACF;AAEA,MAAI,OAAO,WAAW,aAAa;AACjC,UAAM,UAAU,CAAC,UAA4B;AAC3C,aAAO,iBAAiB,MAAM,SAAS,MAAM,SAAS,EAAE,MAAM,EAAE,WAAW,UAAU,EAAE,CAAC;AAAA,IAC1F;AACA,UAAM,cAAc,CAAC,UAAuC;AAC1D,aAAO,iBAAiB,MAAM,QAAQ,EAAE,MAAM,EAAE,WAAW,uBAAuB,EAAE,CAAC;AAAA,IACvF;AACA,UAAM,aAAa,MAAY;AAC7B,WAAK,OAAO,MAAM,GAAK;AAAA,IACzB;AACA,WAAO,iBAAiB,SAAS,OAAO;AACxC,WAAO,iBAAiB,sBAAsB,WAAW;AACzD,WAAO,iBAAiB,YAAY,UAAU;AAE9C,WAAO,MAAM;AACX,aAAO,oBAAoB,SAAS,OAAO;AAC3C,aAAO,oBAAoB,sBAAsB,WAAW;AAC5D,aAAO,oBAAoB,YAAY,UAAU;AACjD,kBAAY;AAAA,IACd;AAAA,EACF;AAEA,SAAO,MAAM;AACX,gBAAY;AAAA,EACd;AACF;;;AC5EA,IAAM,oBAAoB;AAO1B,IAAM,SAAS,CAAC,UAA0B,KAAK,MAAM,QAAQ,EAAE,IAAI;AACnE,IAAM,eAAe,CAAC,UAA0B,KAAK,IAAI,KAAK,KAAK,IAAI,GAAG,KAAK,CAAC;AASzE,IAAM,iBAAN,MAAqB;AAAA,EAW1B,YACmB,YACA,QACjB;AAFiB;AACA;AAAA,EAChB;AAAA,EAFgB;AAAA,EACA;AAAA,EAZX;AAAA,EACA;AAAA,EACA,QAAQ;AAAA,EAER;AAAA,EACA;AAAA,EACA,SAAS;AAAA,EACT,iBAAgC;AAAA,EAChC,wBAAuC;AAAA;AAAA,EAQ/C,MAAM,QAAuB;AAC3B,QAAI,CAAC,OAAO,EAAG;AACf,QAAI;AACF,WAAK,KAAK,MAAM,OAAO,IAAS;AAChC,WAAK,KAAM,MAAM,OAAO,IAAS;AACjC,WAAK,UAAU,KAAK,UAAU;AAC9B,WAAK,iBAAiB,QAAQ,SAAS;AACvC,WAAK,SAAS,KAAK,IAAI;AACvB,WAAK,QAAQ;AAAA,IACf,SAAS,OAAO;AACd,WAAK,OAAO,MAAM,4DAAmD,KAAK;AAAA,IAC5E;AAAA,EACF;AAAA,EAEA,SAAsC;AACpC,QAAI,CAAC,KAAK,SAAS,CAAC,KAAK,GAAI,QAAO;AACpC,QAAI;AACF,YAAM,KAAK,KAAK;AAChB,YAAM,WAAW,KAAK,IAAI,GAAG,GAAG,KAAK,EAAE,MAAM;AAC7C,WAAK,UAAU,QAAQ;AAEvB,YAAM,WAA4B;AAAA,QAChC,YAAY,OAAO;AAAA,QACnB,aAAa,KAAK;AAAA,QAClB,UAAU,GAAG,SAAS;AAAA,QACtB,IAAI,QAAQ;AAAA,QACZ,MAAM,QAAQ;AAAA,QACd,WAAW;AAAA,QACX,aAAa,KAAK;AAAA,QAClB,SAAS;AAAA,UACP,KAAK,QAAQ;AAAA,UACb,UAAU,KAAK,MAAM,QAAQ,OAAO,CAAC;AAAA,UACrC,aAAa,KAAK;AAAA,QACpB;AAAA,QACA,QAAQ;AAAA,MACV;AAGA,UAAI,QAAQ,aAAa,SAAS;AAChC,cAAM,OAAO,GAAG,QAAQ,EAAE,CAAC;AAC3B,YAAI,OAAO,SAAS,YAAY,OAAO,SAAS,IAAI,EAAG,UAAS,SAAS,OAAO,IAAI;AAAA,MACtF;AAEA,YAAM,WAAW,GAAG,SAAS;AAC7B,YAAM,UAAU,GAAG,QAAQ;AAC3B,UAAI,WAAW,GAAG;AAChB,iBAAS,kBAAkB;AAC3B,iBAAS,sBAAsB;AAC/B,iBAAS,cAAc,OAAO,cAAe,WAAW,WAAW,WAAY,GAAG,CAAC;AAAA,MACrF;AAEA,YAAM,OAAO,KAAK,UAAU;AAC5B,UAAI,KAAM,QAAO,OAAO,UAAU,IAAI;AAEtC,YAAM,MAAM,QAAQ,YAAY;AAChC,eAAS,QAAQ,YAAY,IAAI;AACjC,eAAS,QAAQ,kBAAkB,IAAI;AAEvC,aAAO;AAAA,IACT,SAAS,OAAO;AACd,WAAK,OAAO,MAAM,8CAAwC,KAAK;AAC/D,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEQ,YAAuB;AAC7B,QAAI,OAAO;AACX,QAAI,QAAQ;AACZ,eAAW,OAAO,KAAK,GAAI,KAAK,GAAG;AACjC,YAAM,IAAI,IAAI;AACd,YAAM,UAAU,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE;AAC5C,cAAQ;AACR,eAAS,UAAU,EAAE;AAAA,IACvB;AACA,WAAO,EAAE,MAAM,MAAM;AAAA,EACvB;AAAA;AAAA,EAGQ,UAAU,UAAwB;AACxC,UAAM,MAAM,KAAK,IAAI;AACrB,UAAM,YAAY,MAAM,KAAK;AAC7B,QAAI,YAAY,kBAAmB;AAEnC,UAAM,MAAM,KAAK,UAAU;AAC3B,QAAI,KAAK,SAAS;AAChB,YAAM,QAAQ,IAAI,QAAQ,KAAK,QAAQ;AACvC,UAAI,QAAQ,EAAG,MAAK,iBAAiB,OAAO,cAAe,IAAI,OAAO,KAAK,QAAQ,QAAQ,QAAS,GAAG,CAAC;AAAA,IAC1G;AACA,SAAK,UAAU;AAEf,UAAM,QAAQ,QAAQ,SAAS,KAAK,cAAc;AAClD,UAAM,aAAa,MAAM,OAAO,MAAM;AACtC,SAAK,wBAAwB,OAAO,aAAc,cAAc,YAAY,MAAQ,YAAa,GAAG,CAAC;AACrG,SAAK,iBAAiB,QAAQ,SAAS;AACvC,SAAK,SAAS;AAAA,EAChB;AAAA,EAEQ,YAAsH;AAC5H,UAAM,SAAS,KAAK,IAAI;AACxB,QAAI,OAAO,WAAW,WAAY,QAAO;AACzC,QAAI;AACF,YAAM,OAAO,QAAQ,IAAI;AACzB,YAAM,OAAO,OAAO,IAAI;AACxB,YAAM,QAAQ,KAAK,QAAQ,KAAK;AAChC,YAAM,OAAO,KAAK,QAAQ,KAAK;AAC/B,UAAI,SAAS,EAAG,QAAO;AACvB,aAAO;AAAA,QACL,WAAW;AAAA,QACX,kBAAkB;AAAA,QAClB,iBAAiB;AAAA,QACjB,cAAc,OAAO,cAAe,QAAQ,QAAQ,QAAS,GAAG,CAAC;AAAA,MACnE;AAAA,IACF,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AACF;;;AC7IA,IAAM,kBAAkB;AACxB,IAAM,oBAAoB;AAOnB,IAAM,+BAAkD,CAAC,KAAK,KAAK,GAAG;AAEtE,IAAM,0BAA6C,CAAC,GAAG;AAE9D,IAAM,oBAAoB;AAC1B,IAAM,yBAA4C,CAAC,KAAO,GAAK;AAK/D,IAAM,uBAA0C,CAAC,KAAO,GAAK;AAEtD,IAAM,gBAAN,cAA4B,MAAM;AAAA,EACvC,YACE,SACS,QACT;AACA,UAAM,OAAO;AAFJ;AAGT,SAAK,OAAO;AAAA,EACd;AAAA,EAJW;AAKb;AA6BA,eAAe,mBACb,WACA,UACA,MACmB;AACnB,QAAM,EAAE,QAAQ,QAAQ,IAAI,kBAAkB,WAAW,QAAQ;AACjE,MAAI;AACF,WAAO,MAAM,KAAK,MAAM;AAAA,EAC1B,UAAE;AACA,YAAQ;AAAA,EACV;AACF;AAEO,IAAM,WAAN,MAAuC;AAAA,EAC3B;AAAA,EACA;AAAA,EACA;AAAA,EAEjB,YAAY,SAA0B;AACpC,SAAK,UAAU,QAAQ;AACvB,SAAK,MAAM,QAAQ;AACnB,SAAK,SAAS,QAAQ;AAAA,EACxB;AAAA,EAEQ,UAAkC;AACxC,WAAO;AAAA,MACL,gBAAgB;AAAA,MAChB,eAAe,UAAU,KAAK,GAAG;AAAA,IACnC;AAAA,EACF;AAAA;AAAA,EAGA,MAAM,KAAK,SAAsB,QAA6C;AAC5E,UAAM,EAAE,QAAQ,eAAe,QAAQ,IAAI,kBAAkB,iBAAiB,MAAM;AACpF,QAAI;AACJ,QAAI;AACF,iBAAW,MAAM,MAAM,GAAG,KAAK,OAAO,SAAS;AAAA,QAC7C,UAAU;AAAA,QACV,QAAQ;AAAA,QACR,SAAS,KAAK,QAAQ;AAAA,QACtB,MAAM,KAAK,UAAU,OAAO;AAAA,QAC5B,QAAQ;AAAA,MACV,CAAC;AAAA,IACH,UAAE;AACA,cAAQ;AAAA,IACV;AACA,QAAI,CAAC,SAAS,IAAI;AAChB,YAAM,IAAI,cAAc,qBAAqB,SAAS,MAAM,KAAK,SAAS,MAAM;AAAA,IAClF;AACA,WAAO,KAAK,kBAAkB,MAAM,SAAS,KAAK,GAAG,QAAQ,OAAO,CAAC;AAAA,EACvE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,UAAU,SAA2B,QAA8C;AACvF,UAAM,EAAE,QAAQ,eAAe,QAAQ,IAAI,kBAAkB,mBAAmB,MAAM;AACtF,QAAI;AACJ,QAAI;AACF,iBAAW,MAAM,MAAM,GAAG,KAAK,OAAO,IAAI;AAAA,QACxC,UAAU;AAAA,QACV,QAAQ;AAAA,QACR,SAAS,KAAK,QAAQ;AAAA,QACtB,MAAM,KAAK,UAAU,OAAO;AAAA,QAC5B,QAAQ;AAAA,MACV,CAAC;AAAA,IACH,UAAE;AACA,cAAQ;AAAA,IACV;AACA,QAAI,CAAC,SAAS,IAAI;AAChB,YAAM,IAAI,cAAc,qCAA+B,SAAS,MAAM,KAAK,SAAS,MAAM;AAAA,IAC5F;AACA,UAAM,OAAQ,MAAM,SAAS,KAAK,EAAE,MAAM,MAAM,IAAI;AACpD,QAAI,OAAO,MAAM,OAAO,UAAU;AAChC,YAAM,IAAI,cAAc,6DAAoD,CAAC;AAAA,IAC/E;AACA,WAAO;AAAA,MACL,IAAI,KAAK;AAAA,MACT,QAAQ,KAAK,UAAU,OAAO,KAAK,WAAW,YAAY,CAAC,MAAM,QAAQ,KAAK,MAAM,IAAK,KAAK,SAAqC,CAAC;AAAA,MACpI,MAAM;AAAA,MACN,QAAQ,OAAO,KAAK,WAAW,WAAW,KAAK,SAAS;AAAA,MACxD,YAAY,OAAO,KAAK,eAAe,WAAW,KAAK,cAAa,oBAAI,KAAK,GAAE,YAAY;AAAA,IAC7F;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,SAAS,OAAe,SAA0B,QAA8C;AACpG,UAAM,EAAE,QAAQ,eAAe,QAAQ,IAAI,kBAAkB,mBAAmB,MAAM;AACtF,QAAI;AACJ,QAAI;AACF,iBAAW,MAAM,MAAM,GAAG,KAAK,OAAO,IAAI,mBAAmB,KAAK,CAAC,UAAU;AAAA,QAC3E,UAAU;AAAA,QACV,QAAQ;AAAA,QACR,SAAS,KAAK,QAAQ;AAAA,QACtB,MAAM,KAAK,UAAU,OAAO;AAAA,QAC5B,QAAQ;AAAA,MACV,CAAC;AAAA,IACH,UAAE;AACA,cAAQ;AAAA,IACV;AACA,QAAI,CAAC,SAAS,IAAI;AAChB,YAAM,IAAI,cAAc,iCAA8B,SAAS,MAAM,KAAK,SAAS,MAAM;AAAA,IAC3F;AACA,UAAM,OAAQ,MAAM,SAAS,KAAK,EAAE,MAAM,MAAM,IAAI;AACpD,QAAI,OAAO,MAAM,OAAO,UAAU;AAChC,YAAM,IAAI,cAAc,yDAAmD,CAAC;AAAA,IAC9E;AACA,UAAM,OAAO,KAAK;AAClB,WAAO;AAAA,MACL,IAAI,KAAK;AAAA,MACT,QAAQ,KAAK,UAAU,OAAO,KAAK,WAAW,YAAY,CAAC,MAAM,QAAQ,KAAK,MAAM,IAAK,KAAK,SAAqC,CAAC;AAAA,MACpI,MAAM,OAAO,MAAM,OAAO,YAAY,OAAO,KAAK,SAAS,WAAW,EAAE,IAAI,KAAK,IAAI,MAAM,KAAK,KAAK,IAAI;AAAA,MACzG,QAAQ,OAAO,KAAK,WAAW,WAAW,KAAK,SAAS;AAAA,MACxD,YAAY,OAAO,KAAK,eAAe,WAAW,KAAK,cAAa,oBAAI,KAAK,GAAE,YAAY;AAAA,IAC7F;AAAA,EACF;AAAA;AAAA,EAGQ,kBAAkB,MAAe,KAA2B;AAClE,UAAM,OAAQ,MAAoC;AAClD,QAAI,CAAC,MAAM,QAAQ,IAAI,GAAG;AACxB,YAAM,IAAI,cAAc,qDAAkD,CAAC;AAAA,IAC7E;AACA,UAAM,QAAyB,CAAC;AAChC,eAAW,OAAO,KAAK,MAAM,GAAG,KAAK,IAAI,GAAG,GAAG,CAAC,GAA4C;AAC1F,UAAI,OAAO,KAAK,OAAO,SAAU;AACjC,YAAM,SAAS,IAAI,UAAU,OAAO,IAAI,WAAW,YAAY,CAAC,MAAM,QAAQ,IAAI,MAAM,IAAI,IAAI,SAAS,CAAC;AAC1G,YAAM,KAAK,EAAE,GAAG,KAAK,IAAI,IAAI,IAAI,OAAO,CAAkB;AAAA,IAC5D;AACA,QAAI,MAAM,SAAS,KAAK,QAAQ;AAC9B,WAAK,OAAO,KAAK,iBAAiB,KAAK,SAAS,MAAM,MAAM,wDAAgD;AAAA,IAC9G;AACA,WAAO,EAAE,MAAM,MAAM;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,UAAU,OAAe,QAAyC;AACtE,QAAI;AACJ,QAAI;AACF,iBAAW,MAAM;AAAA,QACf,MACE,MAAM,GAAG,KAAK,OAAO,IAAI,mBAAmB,KAAK,CAAC,IAAI;AAAA,UACpD,UAAU;AAAA,UACV,QAAQ;AAAA,UACR,SAAS,KAAK,QAAQ;AAAA,UACtB,MAAM,KAAK,UAAU,MAAM;AAAA,UAC3B,QAAQ,YAAY,QAAQ,iBAAiB;AAAA,QAC/C,CAAC;AAAA,QACH,EAAE,QAAQ,KAAK,QAAQ,OAAO,iBAAiB,KAAK,GAAG;AAAA,MACzD;AAAA,IACF,SAAS,OAAO;AACd,YAAM,IAAI,MAAM,iBAAiB,KAAK,gCAA6B,OAAO,KAAK,CAAC,EAAE;AAAA,IACpF;AACA,QAAI,CAAC,SAAS,IAAI;AAEhB,YAAM,IAAI,cAAc,0BAA0B,SAAS,MAAM,KAAK,SAAS,MAAM;AAAA,IACvF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,cAAc,OAAe,QAA0B,YAAY,KAAsB;AAC7F,UAAM,MAAM,GAAG,KAAK,OAAO,IAAI,mBAAmB,KAAK,CAAC,IAAI;AAAA,MAC1D,UAAU;AAAA,MACV,QAAQ;AAAA,MACR,SAAS,KAAK,QAAQ;AAAA,MACtB,MAAM,KAAK,UAAU,MAAM;AAAA,MAC3B,QAAQ,YAAY,QAAQ,SAAS;AAAA,IACvC,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,YAAY,OAAe,SAAiE;AAChG,QAAI;AACJ,QAAI;AACF,iBAAW,MAAM;AAAA,QACf,MACE,MAAM,GAAG,KAAK,OAAO,IAAI,mBAAmB,KAAK,CAAC,UAAU;AAAA,UAC1D,UAAU;AAAA,UACV,QAAQ;AAAA,UACR,SAAS,KAAK,QAAQ;AAAA,UACtB,MAAM,KAAK,UAAU,OAAO;AAAA,UAC5B,QAAQ,YAAY,QAAQ,iBAAiB;AAAA,QAC/C,CAAC;AAAA,QACH,EAAE,QAAQ,KAAK,QAAQ,OAAO,gBAAgB,KAAK,IAAI,iBAAiB,wBAAwB;AAAA,MAClG;AAAA,IACF,SAAS,OAAO;AACd,YAAM,IAAI,MAAM,yBAAyB,KAAK,gCAA6B,OAAO,KAAK,CAAC,EAAE;AAAA,IAC5F;AACA,QAAI,CAAC,SAAS,IAAI;AAChB,YAAM,IAAI,cAAc,kCAAkC,SAAS,MAAM,KAAK,SAAS,MAAM;AAAA,IAC/F;AACA,UAAM,OAAQ,MAAM,SAAS,KAAK,EAAE,MAAM,MAAM,IAAI;AACpD,WAAO;AAAA,MACL,UAAU,OAAO,MAAM,aAAa,WAAW,KAAK,WAAW,QAAQ,MAAM;AAAA,MAC7E,YAAY,OAAO,MAAM,eAAe,WAAW,KAAK,aAAa;AAAA,IACvE;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,cAAc,OAAe,SAA6D;AAC9F,QAAI;AACJ,QAAI;AACF,iBAAW,MAAM;AAAA,QACf,MACE,MAAM,GAAG,KAAK,OAAO,IAAI,mBAAmB,KAAK,CAAC,eAAe;AAAA,UAC/D,UAAU;AAAA,UACV,QAAQ;AAAA,UACR,SAAS,KAAK,QAAQ;AAAA,UACtB,MAAM,KAAK,UAAU,OAAO;AAAA,UAC5B,QAAQ,YAAY,QAAQ,iBAAiB;AAAA,QAC/C,CAAC;AAAA,QACH,EAAE,QAAQ,KAAK,QAAQ,OAAO,8BAA2B,KAAK,GAAG;AAAA,MACnE;AAAA,IACF,SAAS,OAAO;AACd,YAAM,IAAI,MAAM,0CAAuC,KAAK,gCAA6B,OAAO,KAAK,CAAC,EAAE;AAAA,IAC1G;AACA,QAAI,CAAC,SAAS,IAAI;AAChB,YAAM,IAAI,cAAc,mDAAgD,SAAS,MAAM,KAAK,SAAS,MAAM;AAAA,IAC7G;AACA,UAAM,OAAQ,MAAM,SAAS,KAAK,EAAE,MAAM,MAAM,IAAI;AACpD,QAAI,CAAC,MAAM,QAAQ,MAAM,GAAG,EAAG,OAAM,IAAI,cAAc,wDAAqD,CAAC;AAC7G,WAAO;AAAA,MACL,KAAK,KAAK,IAAI,IAAI,QAAM,OAAO,EAAE,CAAC;AAAA,MAClC,MAAM,OAAO,KAAK,SAAS,YAAY,KAAK,KAAK,SAAS,IAAI,KAAK,OAAO;AAAA,IAC5E;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,iBACJ,OACA,SACA,QACsC;AAGtC,UAAM,WAAW,MAAM;AAAA,MACrB,MACE;AAAA,QAAmB;AAAA,QAAmB;AAAA,QAAQ,mBAC5C,MAAM,GAAG,KAAK,OAAO,IAAI,mBAAmB,KAAK,CAAC,gBAAgB;AAAA,UAChE,UAAU;AAAA,UACV,QAAQ;AAAA,UACR,SAAS,KAAK,QAAQ;AAAA,UACtB,MAAM,KAAK,UAAU,OAAO;AAAA,UAC5B,QAAQ;AAAA,QACV,CAAC;AAAA,MACH;AAAA,MACF;AAAA,QACE,QAAQ,KAAK;AAAA,QACb,OAAO,gBAAgB,KAAK;AAAA,QAC5B,iBAAiB;AAAA;AAAA,QAEjB;AAAA,MACF;AAAA,IACF;AACA,QAAI,CAAC,SAAS,IAAI;AAChB,YAAM,IAAI,cAAc,0CAAoC,SAAS,MAAM,KAAK,SAAS,MAAM;AAAA,IACjG;AACA,UAAM,OAAQ,MAAM,SAAS,KAAK;AAClC,QAAI,OAAO,MAAM,eAAe,UAAU;AACxC,YAAM,IAAI,cAAc,sDAAmD,CAAC;AAAA,IAC9E;AACA,WAAO;AAAA,MACL,IAAI,KAAK,MAAM,QAAQ;AAAA,MACvB,YAAY,KAAK;AAAA,MACjB,SAAS,KAAK,WAAW,EAAE,gBAAgB,QAAQ,aAAa;AAAA,MAChE,YAAY,KAAK,cAAc;AAAA,IACjC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,iBACJ,KACA,SACA,MACA,QACe;AACf,UAAM,WAAW,MAAM;AAAA,MACrB,MACE;AAAA,QAAmB;AAAA,QAAmB;AAAA,QAAQ,mBAC5C,MAAM,KAAK;AAAA,UACT,UAAU;AAAA,UACV,QAAQ;AAAA,UACR;AAAA;AAAA,UAEA;AAAA,UACA,QAAQ;AAAA,QACV,CAAC;AAAA,MACH;AAAA,MACF,EAAE,QAAQ,wBAAwB,QAAQ,KAAK,QAAQ,OAAO,mBAAmB,OAAO;AAAA,IAC1F;AACA,QAAI,CAAC,SAAS,IAAI;AAChB,YAAM,IAAI,cAAc,mCAAmC,SAAS,MAAM,KAAK,SAAS,MAAM;AAAA,IAChG;AAAA,EACF;AAAA;AAAA,EAGA,MAAM,kBACJ,OACA,cACA,SACe;AACf,UAAM,WAAW,MAAM;AAAA,MACrB,GAAG,KAAK,OAAO,IAAI,mBAAmB,KAAK,CAAC,gBAAgB,mBAAmB,YAAY,CAAC;AAAA,MAC5F;AAAA,QACE,UAAU;AAAA,QACV,QAAQ;AAAA,QACR,SAAS,KAAK,QAAQ;AAAA,QACtB,MAAM,KAAK,UAAU,OAAO;AAAA,QAC5B,QAAQ,YAAY,QAAQ,iBAAiB;AAAA,MAC/C;AAAA,IACF;AACA,QAAI,CAAC,SAAS,IAAI;AAChB,YAAM,IAAI,cAAc,8CAAwC,SAAS,MAAM,KAAK,SAAS,MAAM;AAAA,IACrG;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,oBAAoB,OAAe,QAAgB,QAAqD;AAC5G,UAAM,WAAW,MAAM;AAAA,MACrB,MACE;AAAA,QAAmB;AAAA,QAAmB;AAAA,QAAQ,mBAC5C,MAAM,GAAG,KAAK,OAAO,IAAI,mBAAmB,KAAK,CAAC,UAAU,mBAAmB,MAAM,CAAC,aAAa;AAAA,UACjG,UAAU;AAAA,UACV,QAAQ;AAAA,UACR,SAAS,KAAK,QAAQ;AAAA,UACtB,QAAQ;AAAA,QACV,CAAC;AAAA,MACH;AAAA,MACF,EAAE,QAAQ,sBAAsB,QAAQ,KAAK,QAAQ,OAAO,uBAAuB,MAAM,IAAI,OAAO;AAAA,IACtG;AACA,QAAI,CAAC,SAAS,IAAI;AAChB,YAAM,IAAI,cAAc,uCAAuC,SAAS,MAAM,KAAK,SAAS,MAAM;AAAA,IACpG;AACA,UAAM,OAAQ,MAAM,SAAS,KAAK,EAAE,MAAM,MAAM,IAAI;AACpD,QAAI,OAAO,MAAM,QAAQ,UAAU;AACjC,YAAM,IAAI,cAAc,6DAA0D,CAAC;AAAA,IACrF;AACA,WAAO;AAAA,MACL,KAAK,KAAK;AAAA,MACV,YAAY,OAAO,KAAK,eAAe,WAAW,KAAK,aAAa;AAAA,MACpE,MAAM,OAAO,KAAK,SAAS,WAAW,KAAK,OAAO;AAAA,MAClD,MAAM,OAAO,KAAK,SAAS,WAAW,KAAK,OAAO;AAAA,MAClD,cAAc,OAAO,KAAK,iBAAiB,WAAW,KAAK,eAAe;AAAA,IAC5E;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,UAAU,KAAa,QAAwC;AACnE,UAAM,WAAW,MAAM,eAAe,MAAM,MAAM,KAAK,EAAE,UAAU,SAAS,QAAQ,OAAO,OAAO,CAAC,GAAG;AAAA,MACpG,QAAQ;AAAA,MACR,QAAQ,KAAK;AAAA,MACb,OAAO;AAAA,MACP;AAAA,IACF,CAAC;AACD,QAAI,CAAC,SAAS,IAAI;AAChB,YAAM,IAAI,cAAc,oCAAoC,SAAS,MAAM,KAAK,SAAS,MAAM;AAAA,IACjG;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,oBAAoB,OAAe,QAA+B;AACtE,UAAM,WAAW,MAAM;AAAA,MACrB,MACE,MAAM,GAAG,KAAK,OAAO,IAAI,mBAAmB,KAAK,CAAC,UAAU,mBAAmB,MAAM,CAAC,IAAI;AAAA,QACxF,UAAU;AAAA,QACV,QAAQ;AAAA,QACR,SAAS,KAAK,QAAQ;AAAA,QACtB,QAAQ,YAAY,QAAQ,iBAAiB;AAAA,MAC/C,CAAC;AAAA,MACH,EAAE,QAAQ,sBAAsB,QAAQ,KAAK,QAAQ,OAAO,gCAA0B,MAAM,GAAG;AAAA,IACjG;AACA,QAAI,CAAC,SAAS,MAAM,SAAS,WAAW,OAAO,SAAS,WAAW,KAAK;AACtE,YAAM,IAAI,cAAc,iDAA2C,SAAS,MAAM,KAAK,SAAS,MAAM;AAAA,IACxG;AAAA,EACF;AACF;;;ACreA,IAAM,kBAAkB,CAAC,KAAO,KAAO,IAAM;AAC7C,IAAM,2BAA2B;AAQ1B,IAAM,UAAN,MAAc;AAAA,EAInB,YACmB,QACA,OAEA,UAAU,GAC3B;AAJiB;AACA;AAEA;AAAA,EAChB;AAAA,EAJgB;AAAA,EACA;AAAA,EAEA;AAAA,EAPX,WAAW;AAAA,EACX,eAAe;AAAA,EASvB,QAAc;AACZ,SAAK,WAAW;AAChB,SAAK,eAAe;AAAA,EACtB;AAAA,EAEA,KAAK,OAAwB;AAC3B,QAAI,iBAAiB,kBAAkB,MAAM,WAAW,OAAO,MAAM,WAAW,MAAM;AACpF,WAAK;AACL,UAAI,KAAK,iBAAiB,KAAK,KAAK,eAAe,OAAO,GAAG;AAC3D,aAAK,OAAO;AAAA,UACV,MAAM,WAAW,MACb,0GACA;AAAA,QACN;AAAA,MACF;AACA,aAAO,KAAK,IAAI,KAAK,SAAS,wBAAwB;AAAA,IACxD;AACA,SAAK;AACL,UAAM,SAAS,gBAAgB,KAAK,IAAI,KAAK,WAAW,GAAG,gBAAgB,SAAS,CAAC,CAAC;AACtF,UAAM,QAAQ,KAAK,IAAI,KAAK,IAAI,OAAO,MAAM,GAAG,CAAC,GAAG,KAAK,IAAI,KAAK,SAAS,IAAM,CAAC;AAClF,SAAK,OAAO,KAAK,GAAG,KAAK,KAAK,YAAY,OAAO,KAAK,CAAC,8BAA2B,KAAK,IAAI;AAC3F,WAAO;AAAA,EACT;AACF;;;AC9BO,IAAM,aAAN,cAAyB,MAAM;AAAA,EAC3B;AAAA;AAAA,EAEA;AAAA,EAET,YAAY,SAAiB,SAAmC,SAAkC;AAChG,UAAM,OAAO;AACb,SAAK,OAAO;AACZ,SAAK,UAAU;AACf,SAAK,QAAQ,SAAS;AAAA,EACxB;AACF;AAGO,SAAS,aAAa,OAAqC;AAChE,SAAO,iBAAiB,SAAS,MAAM,SAAS;AAClD;AAGO,SAAS,mBAA0B;AACxC,SAAO,OAAO,OAAO,IAAI,MAAM,0BAAoB,GAAG,EAAE,MAAM,cAAc,CAAC;AAC/E;AAGO,SAAS,iBAAiB,WAA0B;AACzD,SAAO,OAAO,OAAO,IAAI,MAAM,mBAAgB,SAAS,6CAA6C,GAAG;AAAA,IACtG,MAAM;AAAA,EACR,CAAC;AACH;AAGA,IAAM,uBAA4C,oBAAI,IAAI,CAAC,eAAe,cAAc,aAAa,CAAC;AAE/F,SAAS,gBAAgB,OAAyB;AACvD,SAAO,iBAAiB,SAAS,qBAAqB,IAAI,MAAM,IAAI;AACtE;AAGO,SAAS,eAAe,OAAyB;AACtD,SAAO,iBAAiB,UAAU,MAAM,SAAS,iBAAiB,MAAM,SAAS;AACnF;;;ACnDO,IAAM,uBAAuB,YAAY;AAEzC,IAAM,0BAA0B,YAAY;AAE5C,IAAM,gCAAgC,YAAY;AAElD,IAAM,yBAAyB;AAC/B,IAAM,oBAAoB,YAAY;AAEtC,IAAM,sBAAsB;AAuBnC,IAAM,cAA6B,uBAAO,IAAI,cAAc;AAOrD,IAAM,kBAAN,MAAsB;AAAA,EAG3B,YACW,OACA,SACA,aACT;AAHS;AACA;AACA;AAAA,EACR;AAAA,EAHQ;AAAA,EACA;AAAA,EACA;AAAA,EALX,CAAU,WAAW,IAAI;AAO3B;AASO,SAAS,MAAM,OAAoB,UAAwB,CAAC,GAAoB;AACrF,SAAO,IAAI,gBAAgB,OAAO,QAAQ,SAAS,QAAQ,WAAW;AACxE;AAGO,SAAS,kBAAkB,OAA0C;AAC1E,SAAO,OAAO,UAAU,YAAY,UAAU,QAAS,MAAkC,WAAW,MAAM;AAC5G;AAGO,SAAS,kBAAkB,OAAoC;AACpE,SAAO,kBAAkB,KAAK,IAAI,QAAQ,IAAI,gBAAgB,KAAK;AACrE;AAMA,eAAsB,cAAc,MAAmC;AACrE,MAAI,CAAC,OAAO,GAAG;AACb,UAAM,IAAI,MAAM,iDAA2C;AAAA,EAC7D;AACA,QAAM,EAAE,SAAS,IAAI,MAAM,OAAO,aAAkB;AACpD,SAAO,IAAI,WAAW,MAAM,SAAS,IAAI,CAAC;AAC5C;AAEA,SAAS,WAAW,OAAmB,WAA8B,SAAS,GAAY;AACxF,MAAI,MAAM,SAAS,SAAS,UAAU,OAAQ,QAAO;AACrD,SAAO,UAAU,MAAM,CAAC,MAAM,UAAU,MAAM,SAAS,KAAK,MAAM,IAAI;AACxE;AAEA,IAAM,YAAY,CAAC,KAAM,IAAM,IAAM,IAAM,IAAM,IAAM,IAAM,EAAI;AAC1D,IAAM,oBAAoB,YAAY;AAC7C,IAAM,aAAa,CAAC,KAAM,KAAM,GAAI;AACpC,IAAM,aAAa,CAAC,IAAM,IAAM,IAAM,EAAI;AAC1C,IAAM,aAAa,CAAC,IAAM,IAAM,IAAM,EAAI;AAGnC,SAAS,iBAAiB,OAAyD;AACxF,MAAI,WAAW,OAAO,SAAS,EAAG,QAAO;AACzC,MAAI,WAAW,OAAO,UAAU,EAAG,QAAO;AAC1C,MAAI,WAAW,OAAO,UAAU,KAAK,WAAW,OAAO,YAAY,CAAC,EAAG,QAAO;AAC9E,SAAO;AACT;AAOO,SAAS,kBAAkB,OAAkE;AAClG,MAAI,CAAC,WAAW,OAAO,SAAS,KAAK,MAAM,SAAS,GAAI,QAAO;AAC/D,QAAM,OAAO,IAAI,SAAS,MAAM,QAAQ,MAAM,YAAY,MAAM,UAAU;AAC1E,QAAM,QAAQ,KAAK,UAAU,EAAE;AAC/B,QAAM,SAAS,KAAK,UAAU,EAAE;AAChC,MAAI,UAAU,KAAK,WAAW,EAAG,QAAO;AAExC,MAAI,QAAQ,qBAAqB,SAAS,kBAAmB,QAAO;AACpE,SAAO,EAAE,OAAO,OAAO;AACzB;AAGA,eAAsB,QAAQ,OAAyC;AACrE,MAAI,OAAO,UAAU,SAAU,QAAO,cAAc,KAAK;AACzD,MAAI,iBAAiB,WAAY,QAAO;AACxC,SAAO,IAAI,WAAW,KAAK;AAC7B;;;AC5GA,IAAI;AACJ,IAAI;AACJ,IAAI;AAEJ,eAAe,gBAA+B;AAC5C,MAAI,WAAW,CAAC,OAAO,EAAG;AAC1B,kBAAgB,OAAO,aAAkB,EAAE,KAAK,CAAC,EAAE,mBAAmB,IAAI,MAAM;AAC9E,cAAU,IAAI,IAAc;AAC5B,kBAAc,IAAI,IAAe;AAAA,EACnC,CAAC;AACD,QAAM;AACR;AAOA,eAAsB,kBAAqB,OAAiB,IAAkC;AAC5F,QAAM,cAAc;AACpB,SAAO,UAAU,QAAQ,IAAI,OAAO,EAAE,IAAI,GAAG;AAC/C;AAGO,SAAS,qBAA8C;AAC5D,SAAO,SAAS,SAAS,GAAG;AAC9B;AAMA,eAAsB,iBAAoB,OAAkB,IAAkC;AAC5F,QAAM,cAAc;AACpB,SAAO,cAAc,YAAY,IAAI,OAAO,EAAE,IAAI,GAAG;AACvD;AAGO,SAAS,YAAY,aAA4C;AACtE,QAAM,QAAQ,aAAa,SAAS;AACpC,SAAO,OAAO,gBAAgB,cAAc,MAAM,OAAO;AAC3D;;;ACnCA,IAAM,kBAAkB;AACxB,IAAM,mBAAmB;AAGlB,SAAS,aAAa,OAA+B,SAAiB,YAA4B;AACvG,QAAM,QAAQ,OAAO,UAAU,aAAa,MAAM,OAAO,IAAK,SAAS;AACvE,SAAO,OAAO,SAAS,KAAK,KAAK,QAAQ,IAAI,KAAK,MAAM,KAAK,IAAI;AACnE;AAOA,eAAsB,iBACpB,IACA,UAAgC,CAAC,GACrB;AAEZ,QAAM,YAAY,QAAQ,WAAW;AACrC,QAAM,UAAU,OAAO,SAAS,SAAS,IAAI,KAAK,IAAI,GAAG,KAAK,MAAM,SAAS,CAAC,IAAI;AAClF,QAAM,OAAO,QAAQ,QAAQ;AAC7B,WAAS,UAAU,KAAK,WAAW;AACjC,QAAI,QAAQ,QAAQ,QAAS,OAAM,iBAAiB;AACpD,QAAI;AACF,aAAO,MAAM,GAAG,OAAO;AAAA,IACzB,SAAS,OAAO;AACd,YAAM,YAAY,UAAU;AAC5B,YAAM,YAAY,CAAC,gBAAgB,KAAK,KAAK,CAAC,QAAQ,QAAQ,YAAY,QAAQ,cAAc,KAAK,KAAK;AAC1G,UAAI,aAAa,CAAC,UAAW,OAAM;AACnC,YAAM,QAAQ,aAAa,QAAQ,SAAS,SAAS,gBAAgB;AACrE,cAAQ,UAAU,OAAO,SAAS,KAAK;AACvC,YAAM,KAAK,KAAK;AAAA,IAClB;AAAA,EACF;AACF;;;ACxCO,IAAM,uBAAuB;AAE7B,IAAM,uBAAuB;AAE7B,IAAM,8BAA8B;AAI3C,IAAM,yBAAyB;AAC/B,IAAM,cAAc;AAEpB,SAAS,YAAY,MAAsB;AACzC,SAAO,KAAK,aAAa,IAAI,GAAG,sBAAsB;AACxD;AAEA,SAAS,SAAiB;AACxB,SAAO,MAAM,EAAE,MAAM,GAAG,EAAE;AAC5B;AAsBA,SAAS,UAAU,IAAa,aAA8B;AAC5D,SAAO,CAAC,IAAI,WAAW,EAAE,OAAO,OAAO,EAAE,KAAK,UAAK,KAAK;AAC1D;AAGO,IAAM,UAAU;AASvB,SAAS,eAAe,MAAgB,IAAa,aAA8B;AACjF,SAAO,UAAU,SAAS,UAAU,OAAO,UAAU,SAAY,IAAI,WAAW;AAClF;AAGA,SAAS,UAAU,OAAwB;AACzC,MAAI,iBAAiB,MAAO,QAAO,MAAM,WAAW,MAAM;AAC1D,SAAO,WAAW,KAAK;AACzB;AAGO,SAAS,YAAY,OAAwB;AAClD,SAAO,iBAAiB,QAAQ,GAAG,MAAM,IAAI,KAAK,UAAU,KAAK,CAAC,KAAK,UAAU,KAAK;AACxF;AAGA,SAAS,eAAe,QAA0C;AAChE,UAAQ,QAAQ;AAAA,IACd,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT;AACE,aAAO;AAAA,EACX;AACF;AAGA,SAAS,eAAe,QAA6D;AACnF,UAAQ,QAAQ;AAAA,IACd,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT;AACE,aAAO;AAAA,EACX;AACF;AAMO,IAAM,OAAN,MAAiC;AAAA,EAStC,YACmB,aACR,cACA,IACA,aACA,OAAiB,QAC1B;AALiB;AACR;AACA;AACA;AACA;AAAA,EACR;AAAA,EALgB;AAAA,EACR;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAbF,SAAS,OAAO;AAAA,EAChB,iBAAiB,OAAO;AAAA,EACjC,SAAqB;AAAA,EACrB;AAAA,EACQ;AAAA;AAAA,EAEA;AAAA;AAAA,EAYR,QAAQ,SAAiB,SAAwC;AAC/D,QAAI,KAAK,WAAW,QAAS,MAAK,WAAW,WAAW,OAAO;AAC/D,QAAI,SAAS,UAAU,OAAW,MAAK,YAAY,QAAQ,KAAK;AAChE,WAAO;AAAA,EACT;AAAA,EAEA,MAAMC,QAAyB;AAC7B,SAAK,YAAYA,MAAK;AACtB,WAAO;AAAA,EACT;AAAA,EAEA,KAAK,KAAa,OAAsB;AACtC,QAAI,QAAQ,cAAe,QAAO;AAClC,SAAK,SAAS,KAAK,KAAK;AACxB,WAAO;AAAA,EACT;AAAA;AAAA;AAAA,EAKA,IAAI,UAA+C;AACjD,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,WAAW,QAAoB,SAAwB;AACrD,SAAK,SAAS;AACd,QAAI,QAAS,MAAK,SAAS,WAAW,YAAY,WAAW,OAAO,CAAC,CAAC;AACtE,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,QAAQ,OAAgB,SAAwB;AAC9C,QAAI,KAAK,aAAc,QAAO;AAC9B,SAAK,SAAS;AACd,UAAM,OAAO,iBAAiB,QAAQ,MAAM,OAAO,OAAO,UAAU,YAAY,UAAU,OAAO,UAAU;AAC3G,UAAM,MAAM,WAAW,UAAU,KAAK;AACtC,SAAK,SAAS,SAAS,EAAE,GAAI,OAAO,EAAE,KAAK,IAAI,CAAC,GAAI,SAAS,YAAY,WAAW,GAAG,CAAC,EAAE,CAAC;AAC3F,SAAK,OAAO;AACZ,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,YAAY,QAAoB,QAAuB;AACrD,SAAK,UAAU,EAAE,QAAQ,OAAO;AAAA,EAClC;AAAA,EAEA,SAAS,KAAa,OAAsB;AAC1C,SAAK,QAAQ,EAAE,GAAG,KAAK,OAAO,CAAC,GAAG,GAAG,MAAM;AAAA,EAC7C;AAAA,EAEA,YAAY,KAAmB;AAC7B,QAAI,CAAC,KAAK,SAAS,EAAE,OAAO,KAAK,OAAQ;AACzC,UAAM,OAAO,EAAE,GAAG,KAAK,MAAM;AAC7B,WAAO,KAAK,GAAG;AACf,SAAK,QAAQ,OAAO,KAAK,IAAI,EAAE,SAAS,IAAI,OAAO;AAAA,EACrD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,YAAYA,QAAyB;AAC3C,UAAM,UAAU,MAAM,QAAQ,KAAK,OAAO,WAAW,IAAK,KAAK,MAAM,cAA2B,CAAC;AACjG,QAAI,QAAQ,UAAU,8BAA+B;AACrD,UAAM,KAAK,KAAK,YAAY,YAAYA,MAAK;AAC7C,QAAI,CAAC,GAAI;AACT,SAAK,SAAS,eAAe,CAAC,GAAG,SAAS,EAAE,CAAC;AAAA,EAC/C;AAAA;AAAA,EAGQ,SAA6B;AACnC,UAAM,QAAQ,KAAK,OAAO;AAC1B,UAAM,OAAO,OAAO,OAAO,YAAY,WAAW,MAAM,UAAU,KAAK,OAAO;AAC9E,WAAO,OAAO,SAAS,YAAY,OAAO,OAAO;AAAA,EACnD;AAAA;AAAA,EAGA,SAAe;AACb,QAAI,KAAK,aAAc;AACvB,SAAK,eAAe,OAAO;AAC3B,UAAM,EAAE,QAAQ,OAAO,IAAI,KAAK,WAAW,EAAE,QAAQ,KAAK,QAAQ,QAAQ,KAAK,OAAO,EAAE;AACxF,SAAK,YAAY;AAAA,MACf,KAAK;AAAA,MACL;AAAA,MACA,eAAe,KAAK,MAAM,KAAK,IAAI,KAAK,WAAW;AAAA,MACnD,KAAK;AAAA,MACL,KAAK;AAAA,MACL;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EAEA,SAAmB;AACjB,WAAO;AAAA,MACL,SAAS,KAAK;AAAA,MACd,GAAI,KAAK,eAAe,EAAE,gBAAgB,KAAK,aAAa,IAAI,CAAC;AAAA,MACjE,GAAI,KAAK,KAAK,EAAE,IAAI,KAAK,KAAK,IAAI,iBAAiB,EAAE,IAAI,CAAC;AAAA,MAC1D,GAAI,KAAK,cAAc,EAAE,aAAa,KAAK,KAAK,aAAa,0BAA0B,EAAE,IAAI,CAAC;AAAA,MAC9F,QAAQ,KAAK;AAAA,MACb,iBAAiB,KAAK;AAAA,MACtB,WAAW,KAAK,gBAAgB,OAAO;AAAA,MACvC,GAAI,KAAK,QAAQ,EAAE,MAAM,KAAK,MAAM,IAAI,CAAC;AAAA,IAC3C;AAAA,EACF;AACF;AAOO,IAAM,cAAN,MAAkB;AAAA,EAkBvB,YACmB,QACR,MACA,IAEQ,OACjB,UAA8B,CAAC,GAC/B;AANiB;AACR;AACA;AAEQ;AAGjB,SAAK,OAAO,QAAQ,QAAQ;AAC5B,SAAK,KAAK,eAAe,SAAS,KAAK,GAAG,IAAI,KAAK,EAAE,MAAM,IAAI;AAAA,EACjE;AAAA,EATmB;AAAA,EACR;AAAA,EACA;AAAA,EAEQ;AAAA,EAtBV,UAAU,MAAM;AAAA,EAChB,SAAS,OAAO;AAAA,EAChB,iBAAiB,OAAO;AAAA,EACjC,SAAS;AAAA,EACQ,QAAgB,CAAC;AAAA,EAC1B,WAAW;AAAA,EACX;AAAA,EACA;AAAA,EACA,yBAAyB;AAAA;AAAA,EAEzB;AAAA;AAAA,EAES;AAAA;AAAA;AAAA,EAGT,mBAAiD,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAsB1D,KACE,MACA,OACA,OACA,SACA,OACA,QACA,QACM;AACN,UAAM,aAAa,WAAW,QAAQ,IAAI,KAAK,KAAK,EAAE,QAAQ,IAAI,IAAI,KAAK,OAAO,EAAE,QAAQ,IAAI;AAChG,UAAM,UAAU,cAAc,OAAO,KAAK,UAAU,QAAQ,OAAO,SAAS,KAAK,MAAM,KAAK;AAE5F,UAAM,cAAc,KAAK,QAAQ,SAAS,iBAAiB,UAAU;AACrE,QAAI,KAAK,QAAQ,SAAS,aAAa;AACrC,YAAM,MAAM,SAAS,WAAW,IAAI,KAAK,MAAM,YAAY,CAAC,IAAI,UAAU,WAAW,eAAe,UAAU,IAAI,IAAI,MAAM;AAC5H,cAAQ,IAAI,GAAG,GAAG,IAAI,KAAK,GAAG,MAAM,EAAE;AAAA,IACxC;AAEA,UAAM,QAAqB,UAAU,WAAW,eAAe,UAAU,IAAI,IAAI;AACjF,UAAM,UAAU,IAAI,IAAI,KAAK,MAAM,YAAY,CAAC,IAAI,KAAK,GAAG,MAAM;AAClE,QAAI,KAAK,cAAe,MAAK,cAAc,OAAO,OAAO;AAAA,aAEhD,KAAK,iBAAiB,SAAS,YAAa,MAAK,iBAAiB,KAAK,CAAC,OAAO,OAAO,CAAC;AAAA,EAClG;AAAA;AAAA,EAGA,iBAAiB,MAA2B;AAC1C,SAAK,gBAAgB;AACrB,UAAM,UAAU,KAAK;AACrB,SAAK,mBAAmB,CAAC;AACzB,eAAW,CAAC,OAAO,OAAO,KAAK,QAAS,MAAK,OAAO,OAAO;AAAA,EAC7D;AAAA;AAAA,EAGA,kBAAkB,MAA4B;AAC5C,SAAK,iBAAiB;AAAA,EACxB;AAAA;AAAA,EAGA,YAAYA,QAAuC;AACjD,QAAI,KAAK,eAAgB,QAAO,KAAK,eAAeA,QAAO,OAAO,CAAC;AACnE,QAAI,CAAC,KAAK,wBAAwB;AAChC,WAAK,yBAAyB;AAC9B,cAAQ,KAAK,8FAA6E;AAAA,IAC5F;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,aAAa,OAAyB;AACpC,SAAK,YAAY;AAAA,EACnB;AAAA;AAAA,EAGA,cAAgC;AAC9B,WAAO,YAAY,IAAI;AAAA,EACzB;AAAA;AAAA,EAGA,MAAS,MAAwB,IAAkC;AACjE,QAAI,CAAC,KAAM,QAAO,GAAG;AACrB,WAAO,iBAAiB,EAAE,aAAa,MAAM,KAAK,GAAG,EAAE;AAAA,EACzD;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,IAAa,aAAsB,OAAiB,QAAc;AACtE,SAAK,YAAY;AACjB,UAAM,SAAS,KAAK,YAAY;AAChC,UAAM,OAAO,IAAI,KAAK,MAAM,SAAS,OAAO,SAAS,KAAK,QAAQ,IAAI,aAAa,IAAI;AACvF,SAAK,MAAM,KAAK,IAAI;AACpB,SAAK,KAAK,MAAM,SAAS,eAAe,MAAM,IAAI,WAAW,CAAC;AAC9D,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MAAM,KAAQ,MAAc,IAAe,UAA6C,CAAC,GAAe;AACtG,UAAM,YAAY,QAAQ,WAAW;AACrC,UAAM,eAAe,OAAO,SAAS,SAAS,IAAI,KAAK,IAAI,GAAG,KAAK,MAAM,SAAS,CAAC,IAAI;AACvF,UAAM,OAAO,KAAK,MAAM,QAAW,WAAW,IAAI,CAAC;AACnD,QAAI,WAAW;AACf,QAAI;AAEJ,QAAI;AACF,YAAM,SAAS,MAAM;AAAA,QACnB,aAAW;AACT,qBAAW;AACX,iBAAO,KAAK,MAAM,MAAM,YAAY,GAAG,IAAI,CAAC;AAAA,QAC9C;AAAA,QACA;AAAA,UACE,SAAS;AAAA,UACT,SAAS,aAAW,aAAa,QAAQ,cAAc,SAAS,2BAA2B;AAAA,UAC3F,QAAQ,QAAQ;AAAA,UAChB,MAAM,QAAQ;AAAA,UACd,SAAS,CAAC,OAAO,SAAS,YAAY;AACpC,0BAAc,EAAE,MAAM;AACtB,oBAAQ;AAAA,cACN,UAAU,KAAK,WAAW,gBAAgB,OAAO,IAAI,eAAe,CAAC,YAAY,SAAS,YAAY,KAAK,GAAG,GAAG,CAAC,6BAAwB,OAAO;AAAA,YACnJ;AAAA,UACF;AAAA,QACF;AAAA,MACF;AACA,WAAK,aAAa,MAAM,QAAQ;AAChC,UAAI,eAAe,KAAK,WAAW,MAAM;AACvC,aAAK,WAAW,WAAW,aAAa,WAAW,CAAC,IAAI,eAAe,CAAC,YAAY,YAAY,YAAY,KAAK,CAAC,EAAE;AAAA,MACtH;AACA,WAAK,OAAO;AACZ,aAAO;AAAA,IACT,SAAS,OAAO;AACd,WAAK,aAAa,MAAM,QAAQ;AAEhC,UAAI,gBAAgB,KAAK,EAAG,MAAK,WAAW,WAAW,EAAE,OAAO;AAAA,UAC3D,MAAK,QAAQ,KAAK;AACvB,YAAM;AAAA,IACR;AAAA,EACF;AAAA,EAEQ,aAAa,MAAY,UAAwB;AACvD,QAAI,WAAW,EAAG,MAAK,SAAS,YAAY,QAAQ;AAAA,EACtD;AAAA;AAAA,EAIA,UAAU,QAAsB;AAC9B,SAAK,SAAS;AACd,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,QAAgB;AACd,QAAI,CAAC,KAAK,UAAU,KAAK,SAAU,QAAO;AAC1C,UAAM,QAAQ,oBAAI,IAAY;AAC9B,eAAW,QAAQ,KAAK,OAAO;AAC7B,UAAI,KAAK,iBAAiB,KAAK,UAAU,KAAK,aAAc,OAAM,IAAI,KAAK,MAAM;AAAA,IACnF;AACA,QAAI,MAAM,SAAS,EAAG,QAAO;AAG7B,UAAM,QAAgB,CAAC;AACvB,UAAM,YAAoB,CAAC;AAC3B,eAAW,QAAQ,KAAK,OAAO;AAC7B,UAAI,MAAM,IAAI,KAAK,MAAM,KAAK,MAAM,IAAI,KAAK,YAAY,GAAG;AAC1D,cAAM,IAAI,KAAK,MAAM;AACrB,cAAM,KAAK,IAAI;AAAA,MACjB,OAAO;AACL,kBAAU,KAAK,IAAI;AAAA,MACrB;AAAA,IACF;AACA,eAAW,QAAQ,MAAO,MAAK,OAAO;AACtC,SAAK,MAAM,OAAO,GAAG,KAAK,MAAM,QAAQ,GAAG,SAAS;AAEpD,aAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK,WAAW;AAChD,YAAM,QAAQ,MAAM,MAAM,GAAG,IAAI,SAAS;AAC1C,YAAM,iBAAiB,MAAM,OAAO,CAAC,KAAK,SAAU,KAAK,iBAAiB,MAAM,KAAK,iBAAiB,KAAM,MAAM,CAAC,EAAG,cAAc;AACpI,YAAM,SAAS,MAAM,KAAK,UAAQ,KAAK,WAAW,OAAO,IAAI,UAAU;AACvE,WAAK,OAAO,gBAAgB,KAAK,QAAQ,MAAM,GAAG,sBAAsB,QAAQ,gBAAgB,OAAO,GAAG,KAAK,CAAC;AAAA,IAClH;AACA,WAAO,MAAM;AAAA,EACf;AAAA;AAAA,EAGA,MAAM,MAAM,WAAkC;AAC5C,UAAM,KAAK,QAAQ,MAAM,SAAS;AAAA,EACpC;AAAA,EAEQ,QAAQ,SAAiB,IAAwB,QAAgB,gBAAwB,WAAmB,OAAmC;AACrJ,WAAO;AAAA,MACL,UAAU;AAAA,MACV,MAAM,KAAK;AAAA,MACX;AAAA,MACA;AAAA,MACA,iBAAiB;AAAA,MACjB;AAAA,MACA,OAAO,MAAM,IAAI,UAAQ,KAAK,OAAO,CAAC;AAAA;AAAA,MAEtC,MAAM;AAAA,MACN,QAAQ,KAAK;AAAA,IACf;AAAA,EACF;AAAA,EAEA,SAAe;AACb,QAAI,KAAK,SAAU;AACnB,SAAK,WAAW;AAEhB,eAAW,QAAQ,KAAK,MAAO,MAAK,OAAO;AAE3C,UAAM,eAAe,OAAO;AAC5B,SAAK;AAAA,MACH;AAAA,MACA;AAAA,MACA,KAAK,KAAK,GAAG,KAAK,IAAI,KAAK,KAAK,EAAE,MAAM,KAAK;AAAA,MAC7C,KAAK;AAAA,MACL;AAAA,MACA,KAAK;AAAA,IACP;AAEA,QAAI,CAAC,KAAK,OAAQ;AAGlB,UAAM,QAAQ,KAAK;AACnB,QAAI,QAAQ;AACZ,WAAO,MAAM,SAAS,QAAQ,WAAW;AACvC,YAAM,QAAQ,MAAM,MAAM,OAAO,QAAQ,SAAS;AAClD,YAAM,SAAS,MAAM,KAAK,UAAQ,KAAK,WAAW,OAAO,IAAI,UAAU;AACvE,WAAK,OAAO,gBAAgB,KAAK,QAAQ,MAAM,GAAG,sBAAsB,QAAQ,MAAM,CAAC,EAAG,gBAAgB,cAAc,KAAK,CAAC;AAC9H,eAAS;AAAA,IACX;AACA,SAAK,OAAO,gBAAgB,KAAK,QAAQ,KAAK,SAAS,KAAK,IAAI,KAAK,QAAQ,KAAK,gBAAgB,cAAc,MAAM,MAAM,KAAK,CAAC,CAAC;AAAA,EACrI;AACF;;;ACtgBO,IAAM,wBAAwB;AAE9B,IAAM,uBAAuB;AAEpC,IAAM,eAAe;AAmCd,SAAS,cAAc,OAAwB;AACpD,MAAI,iBAAiB,MAAO,QAAO,MAAM,WAAW,MAAM;AAC1D,SAAO,WAAW,KAAK;AACzB;AAEA,IAAM,aAAN,MAAgD;AAAA,EAS9C,YACW,OACA,OACT,IACS,MACQC,cACA,MACjB;AANS;AACA;AAEA;AACQ,uBAAAA;AACA;AAEjB,SAAK,KAAK,MAAM,MAAM;AAAA,EACxB;AAAA,EARW;AAAA,EACA;AAAA,EAEA;AAAA,EACQ;AAAA,EACA;AAAA;AAAA,EAbV;AAAA,EACT,WAAW;AAAA,EACX;AAAA,EACA;AAAA,EACA,UAAU;AAAA,EACF,cAAuC,CAAC;AAAA,EAahD,KAAK,SAAwC;AAC3C,WAAO,OAAO,KAAK,aAAa,OAAO;AAAA,EACzC;AAAA,EAEA,UAAU,SAAmC,SAAqC;AAChF,SAAK,OAAO,aAAa,QAAW,SAAS,SAAS,KAAK;AAAA,EAC7D;AAAA,EAEA,OAAO,SAAiB,SAAmC,SAAqC;AAC9F,SAAK,OAAO,UAAU,SAAS,SAAS,SAAS,KAAK;AAGtD,QAAI,KAAK,QAAQ,KAAK,KAAK,WAAW,QAAS,MAAK,KAAK,WAAW,SAAS,OAAO;AAAA,EACtF;AAAA,EAEA,WAAW,SAAiB,SAAmC,SAAqC;AAClG,SAAK,OAAO,cAAc,SAAS,SAAS,SAAS,KAAK;AAC1D,QAAI,KAAK,QAAQ,KAAK,KAAK,WAAW,KAAM,MAAK,KAAK,WAAW,WAAW,OAAO;AAAA,EACrF;AAAA;AAAA,EAGA,aAAa,SAAuB;AAClC,SAAK,UAAU;AACf,SAAK,WAAW;AAChB,SAAK,SAAS;AACd,SAAK,UAAU;AACf,SAAK,cAAc,CAAC;AACpB,QAAI,KAAK,SAAS,KAAK,KAAK,WAAW,WAAW,KAAK,KAAK,WAAW,YAAY;AACjF,WAAK,KAAK,WAAW,IAAI;AACzB,WAAK,KAAK,YAAY,SAAS;AAAA,IACjC;AAAA,EACF;AAAA,EAEQ,OACN,QACA,SACA,SACAC,QACM;AACN,SAAK,WAAW;AAChB,SAAK,SAAS;AACd,SAAK,UAAU;AACf,UAAM,SAAS,EAAE,GAAI,KAAK,eAAe,CAAC,GAAI,GAAG,KAAK,aAAa,GAAI,WAAW,CAAC,EAAG;AACtF,SAAK,KAAK,OAAO,QAAQ,SAAS,OAAO,KAAK,MAAM,EAAE,SAAS,IAAI,SAAS,QAAW,KAAK,IAAIA,MAAK;AAAA,EACvG;AACF;AAOO,SAAS,eAAe,SAAuD;AACpF,MAAI,OAAO,YAAY,YAAY,YAAY,KAAM,QAAO;AAC5D,QAAM,QAAQ,OAAO,eAAe,OAAO;AAC3C,MAAI,UAAU,OAAO,aAAa,UAAU,KAAM,QAAO;AACzD,QAAM,OAAO,EAAE,GAAI,QAAoC;AACvD,SAAO,OAAO,KAAK,IAAI,EAAE,SAAS,IAAI,OAAO;AAC/C;AAEA,SAAS,YAAe,MAAyC,SAAY,OAAoD;AAC/H,MAAI,SAAS,MAAO,QAAO;AAC3B,MAAI,SAAS,OAAW,QAAO,eAAe,OAAO;AACrD,SAAO,KAAK,SAAS,KAAK;AAC5B;AAEA,SAAS,MAAM,SAAkB,MAAoD;AACnF,MAAI,OAAO,YAAY,YAAY,YAAY,KAAM,QAAO,EAAE,SAAS,OAAO,OAAO,OAAU;AAC/F,QAAM,SAAS;AACf,SAAO,EAAE,SAAS,QAAQ,QAAQ,OAAO,OAAO,IAAI,EAAE;AACxD;AAQO,SAAS,UAAa,MAAoC,SAAY,OAAe,UAAuC;AACjI,MAAI,SAAS,KAAM,QAAO;AAC1B,MAAI;AACJ,MAAI,OAAO,SAAS,YAAY;AAC9B,UAAM,KAAK,SAAS,KAAK;AAAA,EAC3B,OAAO;AACL,UAAM,SAAS,SAAS,SAAY,CAAC,qBAAqB,IAAI,OAAO,SAAS,WAAW,CAAC,IAAI,IAAI;AAClG,UAAM,QAAkB,CAAC;AACzB,eAAW,QAAQ,QAAQ;AACzB,YAAM,EAAE,SAAS,MAAM,IAAI,MAAM,SAAS,IAAI;AAC9C,UAAI,CAAC,WAAW,UAAU,QAAQ,UAAU,QAAW;AACrD,YAAI,UAAU;AACZ,gBAAM,IAAI;AAAA,YACR,yBAAyB,QAAQ,CAAC,wBAAqB,IAAI;AAAA,UAC7D;AAAA,QACF;AACA,eAAO;AAAA,MACT;AACA,YAAM,KAAK,WAAW,KAAK,CAAC;AAAA,IAC9B;AACA,UAAM,MAAM,KAAK,YAAY;AAAA,EAC/B;AACA,MAAI,QAAQ,QAAQ,QAAQ,OAAW,QAAO;AAC9C,QAAM,OAAO,WAAW,GAAG;AAC3B,SAAO,KAAK,SAAS,IAAI,OAAO;AAClC;AAGA,SAAS,YAAY,MAAmC;AACtD,QAAM,SAAU,MAAsC;AACtD,SAAO,OAAO,WAAW,YAAY,OAAO,UAAU,MAAM,KAAK,UAAU,IAAI,SAAS;AAC1F;AAMA,IAAM,kBAAqD,EAAE,WAAW,MAAM,YAAY,WAAW,QAAQ,QAAQ;AAGrH,SAAS,eAAe,MAAY,QAAuB,SAAmC;AAC5F,OAAK,YAAY,gBAAgB,MAAM,GAAG,WAAW,cAAc,SAAY,OAAO;AACxF;AAEA,SAAS,eAAe,OAAuB;AAC7C,MAAI,UAAU,EAAG,QAAO;AACxB,SAAO,GAAG,KAAK;AACjB;AAmBA,eAAsB,SACpB,MACA,SACA,SACA,MAC6B;AAC7B,QAAM,SAA6B,EAAE,OAAO,GAAG,WAAW,GAAG,QAAQ,GAAG,YAAY,GAAG,SAAS,EAAE;AAClG,QAAM,YAAY,QAAQ,WAAW;AACrC,QAAM,eAAe,OAAO,SAAS,SAAS,IAAI,KAAK,IAAI,GAAG,KAAK,MAAM,SAAS,CAAC,IAAI;AACvF,QAAM,aAAa,QAAQ,OAAO;AAElC,QAAM,OAAO,QAAQ,aAAa,QAAQ,SAAY,MAAM,KAAK,YAAY;AAC7E,QAAM,SAAS,CAAC,OAAoC,OAAO,UAAa,SAAS,UAAa,KAAK,IAAI,EAAE;AACzG,QAAM,SAAS,YAAY,IAAI;AAI/B,MAAI;AACJ,MAAI,WAAW,UAAa,SAAS,UAAa,KAAK,OAAO,GAAG;AAE/D,UAAM,UAA0B,CAAC;AACjC,QAAI,WAAW;AACf,qBAAiB,WAAW,MAAM;AAChC,YAAM,KAAK,UAAU,QAAQ,IAAI,SAAS,UAAU,UAAU;AAC9D,UAAI,OAAO,EAAE,EAAG,QAAO,WAAW;AAAA,UAC7B,SAAQ,KAAK,EAAE,SAAS,OAAO,UAAU,GAAG,CAAC;AAClD,kBAAY;AAAA,IACd;AACA,QAAI,QAAQ,aAAa,SAAS,QAAQ,SAAS,EAAG,MAAK,aAAa,QAAQ,MAAM;AACtF,cAAU;AAAA,EACZ,OAAO;AAEL,QAAI,QAAQ,aAAa,SAAS,WAAW,OAAW,MAAK,aAAa,MAAM;AAChF,cAAU,YAAY,MAAM,QAAQ,IAAI,UAAU;AAAA,EACpD;AAEA,mBAAiB,EAAE,SAAS,OAAO,GAAG,KAAK,SAAS;AAClD,SAAK,cAAc;AACnB,QAAI,OAAO,EAAE,GAAG;AACd,aAAO,WAAW;AAClB;AAAA,IACF;AACA,UAAM,cAAc,QAAQ,cAAc,SAAS,KAAK,KAAK,MAAM,IAAI,QAAQ,CAAC;AAChF,UAAM,OAAO,KAAK,UAAU,QAAQ,MAAM,QAAQ,WAAW;AAC7D,UAAM,SAAS,IAAI,WAAW,SAAS,OAAO,IAAI,MAAM,YAAY,QAAQ,SAAS,SAAS,KAAK,GAAG,IAAI;AAC1G,UAAM,UAAU;AAChB,QAAI,WAAW;AACf,QAAI;AAEJ,QAAI;AACF,YAAM;AAAA,QACJ,aAAW;AACT,qBAAW;AACX,cAAI,UAAU,EAAG,QAAO,aAAa,OAAO;AAC5C,iBAAO,KAAK,UAAU,MAAM,YAAY,QAAQ,QAAQ,OAAO,CAAC;AAAA,QAClE;AAAA,QACA;AAAA,UACE,SAAS;AAAA,UACT,SAAS,aAAW,aAAa,QAAQ,cAAc,SAAS,2BAA2B;AAAA;AAAA;AAAA,UAG3F,aAAa,WAAS,CAAC,aAAa,KAAK,KAAK,CAAC,OAAO,YAAY,CAAC,KAAK,UAAU;AAAA,UAClF,MAAM,QAAM,KAAK,MAAM,EAAE;AAAA,UACzB,SAAS,CAAC,OAAO,SAAS,YAAY;AACpC,0BAAc,EAAE,MAAM;AACtB,iBAAK;AAAA,cACH,QAAQ,WAAW,eAAe,OAAO,IAAI,eAAe,CAAC,YAAY,SAAS,YAAY,KAAK,GAAG,GAAG,CAAC,6BAAwB,OAAO;AAAA,YAC3I;AAAA,UACF;AAAA,QACF;AAAA,MACF;AACA,UAAI,CAAC,OAAO,SAAU,QAAO,UAAU;AACvC,UAAI,MAAM;AACR,qBAAa,MAAM,QAAQ;AAC3B,YAAI,eAAe,KAAK,WAAW,MAAM;AACvC,eAAK,WAAW,WAAW,aAAa,WAAW,CAAC,IAAI,eAAe,CAAC,YAAY,YAAY,YAAY,KAAK,CAAC,EAAE;AAAA,QACtH;AAAA,MACF;AAAA,IACF,SAAS,OAAO;AACd,UAAI,gBAAgB,KAAK,KAAK,KAAK,UAAU,GAAG;AAE9C,cAAM,WAAW,WAAW,EAAE,OAAO;AACrC,cAAM;AAAA,MACR;AACA,UAAI,KAAM,cAAa,MAAM,QAAQ;AACrC,UAAI,aAAa,KAAK,GAAG;AAEvB,cAAM,aAAa;AACnB,YAAI,CAAC,OAAO,SAAU,QAAO,WAAW,WAAW,SAAS,WAAW,SAAS,EAAE,OAAO,WAAW,MAAM,CAAC;AAAA,MAC7G,OAAO;AACL,cAAM,UAAU,cAAc,KAAK;AACnC,YAAI,CAAC,OAAO,SAAU,QAAO,OAAO,OAAO;AAG3C,YAAI,MAAM;AAER,yBAAe,MAAM,OAAO,UAAU,UAAU,OAAO,OAAO;AAE9D,eAAK,QAAQ,KAAK;AAAA,QACpB;AACA,aAAK,SAAS,QAAQ,WAAW,YAAY,OAAO,EAAE;AAAA,MACxD;AAAA,IACF;AAGA,UAAM,QAAuB,OAAO,UAAU;AAE9C,QAAI,MAAM;AACR,qBAAe,MAAM,OAAO,OAAO,OAAO;AAC1C,WAAK,OAAO;AAAA,IACd;AACA,QAAI,QAAQ,aAAa,MAAO,MAAK,QAAQ;AAC7C,WAAO,SAAS;AAChB,WAAO,KAAK,KAAK;AAEjB,QAAI,QAAQ,UAAU,MAAO,OAAM,KAAK,MAAM;AAAA,EAChD;AAEA,SAAO,SAAS,OAAO;AACvB,MAAI,OAAO,UAAU,EAAG,MAAK,QAAQ,eAAe,OAAO,OAAO,CAAC;AACnE,SAAO;AACT;AASA,gBAAgB,YACd,MACA,MACA,UAC8B;AAC9B,MAAI,QAAQ;AACZ,mBAAiB,WAAW,MAAM;AAChC,UAAM,EAAE,SAAS,OAAO,IAAI,UAAU,MAAM,SAAS,OAAO,QAAQ,EAAE;AACtE,aAAS;AAAA,EACX;AACF;AAEA,SAAS,aAAa,MAAY,UAAwB;AACxD,MAAI,WAAW,EAAG,MAAK,SAAS,YAAY,QAAQ;AACtD;;;ACpWO,IAAM,sBAAsB;AAM5B,IAAM,gCAAgC;AAE7C,IAAM,UAAU;AAoCT,SAAS,UAAU,OAAkC;AAC1D,MAAI,CAAC,SAAS,OAAO,UAAU,YAAY,MAAM,QAAQ,KAAK,EAAG,QAAO;AACxE,QAAM,MAAM;AACZ,SACE,OAAO,IAAI,OAAO,YAClB,OAAO,IAAI,SAAS,YACpB,OAAO,IAAI,SAAS,YACpB,OAAO,IAAI,gBAAgB,aAC1B,IAAI,YAAY,QAAQ,IAAI,YAAY;AAE7C;AAGO,SAAS,UAAU,QAAiCC,QAAgD;AACzG,MAAI,CAAC,OAAO,UAAU,eAAe,KAAK,QAAQA,MAAK,EAAG,QAAO;AACjE,QAAM,QAAQ,OAAOA,MAAK;AAC1B,MAAI,UAAU,KAAK,EAAG,QAAO;AAC7B,MAAI,MAAM,QAAQ,KAAK,KAAK,MAAM,MAAM,SAAS,EAAG,QAAO;AAC3D,SAAO;AACT;AAEO,SAAS,gBAAgB,QAA4C;AAC1E,QAAM,OAAkB,CAAC;AACzB,aAAWA,UAAS,OAAO,KAAK,MAAM,GAAG;AACvC,UAAM,QAAQ,UAAU,QAAQA,MAAK;AACrC,QAAI,UAAU,OAAW,MAAK,KAAK,GAAI,MAAM,QAAQ,KAAK,IAAI,QAAQ,CAAC,KAAK,CAAE;AAAA,EAChF;AACA,SAAO;AACT;AAGO,SAAS,aAAa,MAAc,UAA0B;AAEnE,QAAM,UAAU,KAAK,QAAQ,YAAY,EAAE,EAAE,QAAQ,2BAA2B,GAAG,EAAE,KAAK;AAC1F,SAAO,YAAY,MAAM,YAAY,OAAO,YAAY,OAAO,WAAW;AAC5E;AAGO,SAAS,YAAY,MAAc,WAAmB,KAAsB;AACjF,QAAM,OAAO,KAAK,SAAS,GAAG,IAAI,OAAO,OAAO;AAChD,SAAO,UAAU,WAAW,IAAI,KAAK,UAAU,SAAS,KAAK;AAC/D;AAEA,SAAS,iBAAiB,KAAqB;AAC7C,SAAO,IAAI,MAAM,YAAY,IAAI,IAAI,8DAA2D;AAClG;AAOA,SAAS,aAAa,KAAkC;AACtD,MAAI,CAAC,WAAW,EAAG,QAAO;AAC1B,QAAM,OAAQ,IAA2B;AACzC,SAAO,OAAO,SAAS,YAAY,KAAK,KAAK,MAAM,KAAK,OAAO;AACjE;AAGA,SAAS,UAAU,OAAyB;AAC1C,SAAQ,OAAqC;AAC/C;AAiBO,IAAM,eAAN,MAAmB;AAAA,EAIxB,YAA6B,MAAwB;AAAxB;AAC3B,SAAK,QAAQ;AAAA,MACX,MAAM,MAAM,gBAAgB,KAAK,MAAM;AAAA,MACvC,KAAK,CAAAA,WAAS,UAAU,KAAK,QAAQA,MAAK;AAAA;AAAA,MAE1C,UAAU,OAAO,YAAY,YAAY,KAAK,SAAS,KAAK,OAAO,UAAU,GAAG,SAAS,IAAI;AAAA,MAC7F,aAAa,OAAOA,QAAO,YAAY,KAAK,YAAYA,QAAO,SAAS,IAAI;AAAA,MAC5E,MAAM,OAAM,eAAc,KAAK,KAAK,KAAK,OAAO,UAAU,CAAC;AAAA,IAC7D;AAAA,EACF;AAAA,EAT6B;AAAA,EAHpB;AAAA,EACD;AAAA;AAAA,EAcR,MAAM,UAAyB;AAC7B,UAAM,UAAU,KAAK;AACrB,SAAK,UAAU;AACf,QAAI,CAAC,QAAS;AACd,QAAI;AACF,YAAM,EAAE,GAAG,IAAI,MAAM,OAAO,aAAkB;AAC9C,YAAM,GAAG,MAAM,SAAS,EAAE,WAAW,MAAM,OAAO,KAAK,CAAC;AAAA,IAC1D,QAAQ;AAAA,IAER;AAAA,EACF;AAAA,EAEQ,MAAMA,QAAoC;AAChD,UAAM,QAAQ,UAAU,KAAK,KAAK,QAAQA,MAAK;AAC/C,QAAI,UAAU,OAAW,OAAM,IAAI,MAAM,UAAUA,MAAK,iCAA8B;AACtF,WAAO;AAAA,EACT;AAAA,EAEQ,OAAO,YAAuC;AACpD,QAAI,OAAO,eAAe,UAAU;AAClC,YAAM,QAAQ,KAAK,MAAM,UAAU;AACnC,UAAI,MAAM,QAAQ,KAAK,GAAG;AACxB,cAAM,IAAI,MAAM,UAAU,UAAU,oDAA4C,UAAU,8BAA8B;AAAA,MAC1H;AACA,aAAO;AAAA,IACT;AACA,QAAI,CAAC,UAAU,UAAU,EAAG,OAAM,IAAI,UAAU,sDAAsD;AACtG,WAAO;AAAA,EACT;AAAA,EAEA,MAAc,YAAYA,QAAe,MAA6C;AACpF,UAAM,QAAQ,KAAK,MAAMA,MAAK;AAC9B,UAAM,OAAO,MAAM,QAAQ,KAAK,IAAI,QAAQ,CAAC,KAAK;AAClD,UAAM,QAAkB,CAAC;AAEzB,eAAW,OAAO,KAAM,OAAM,KAAK,MAAM,KAAK,SAAS,KAAK,MAAM,IAAI,CAAC;AACvE,WAAO;AAAA,EACT;AAAA,EAEA,MAAc,KAAK,KAA+B;AAChD,UAAM,EAAE,UAAU,GAAG,IAAI,MAAM,OAAO,aAAkB;AACxD,UAAM,EAAE,QAAQ,IAAI,MAAM,OAAO,MAAW;AAC5C,UAAM,OAAO,MAAM,KAAK,SAAS,KAAK,MAAS;AAC/C,QAAI;AACF,aAAO,MAAM,SAAS,IAAI;AAAA,IAC5B,UAAE;AAEA,YAAM,GAAG,QAAQ,IAAI,GAAG,EAAE,WAAW,MAAM,OAAO,KAAK,CAAC;AAAA,IAC1D;AAAA,EACF;AAAA,EAEA,MAAc,SAAS,KAAc,MAA0B,YAAY,OAAwB;AACjG,SAAK,cAAc;AACnB,UAAM,SAAS,MAAM,KAAK,cAAc,KAAK,MAAM,SAAS;AAC5D,QAAI,IAAI,YAAY,QAAS,OAAM,KAAK,UAAU,KAAK,MAAM;AAAA,QACxD,OAAM,KAAK,WAAW,KAAK,MAAM;AACtC,WAAO;AAAA,EACT;AAAA,EAEQ,gBAAsB;AAC5B,QAAI,KAAK,KAAK,OAAO,QAAS,OAAM,iBAAiB;AAAA,EACvD;AAAA,EAEQ,aAA8B;AACpC,SAAK,aAAa,YAAY;AAC5B,YAAM,EAAE,QAAQ,IAAI,MAAM,OAAO,aAAkB;AACnD,YAAM,EAAE,OAAO,IAAI,MAAM,OAAO,IAAS;AACzC,YAAM,EAAE,KAAK,IAAI,MAAM,OAAO,MAAW;AACzC,aAAO,QAAQ,KAAK,OAAO,GAAG,eAAe,CAAC;AAAA,IAChD,GAAG;AACH,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,MAAc,cAAc,KAAc,MAA0B,WAAqC;AACvG,UAAM,EAAE,OAAO,SAAS,KAAK,IAAI,MAAM,OAAO,aAAkB;AAChE,UAAM,EAAE,SAAS,MAAM,SAAAC,SAAQ,IAAI,MAAM,OAAO,MAAW;AAC3D,UAAM,OAAO,aAAa,IAAI,MAAM,SAAS;AAC7C,QAAI,SAAS,QAAW;AAEtB,aAAO,KAAK,MAAM,QAAQ,KAAK,MAAM,KAAK,WAAW,GAAG,IAAI,CAAC,GAAG,IAAI;AAAA,IACtE;AACA,UAAM,QACJ,aAAa,KAAK,SAAS,GAAG,KAAK,KAAK,SAAS,IAAI,MAAM,MAAM,KAAK,IAAI,EAAE,MAAM,MAAM,MAAS,IAAI,YAAY,MAAM;AACzH,QAAI,OAAO;AACT,YAAM,MAAM,MAAM,EAAE,WAAW,KAAK,CAAC;AACrC,aAAOA,SAAQ,MAAM,IAAI;AAAA,IAC3B;AACA,UAAM,MAAM,QAAQA,SAAQ,IAAI,CAAC,GAAG,EAAE,WAAW,KAAK,CAAC;AACvD,WAAOA,SAAQ,IAAI;AAAA,EACrB;AAAA;AAAA,EAGA,MAAc,WAAW,KAAc,QAA+B;AACpE,UAAM,EAAE,KAAK,OAAO,OAAO,IAAI,KAAK;AACpC,QAAI;AACJ,QAAI;AACJ,QAAI;AACF,YAAM,OAAO,MAAM,IAAI,oBAAoB,OAAO,IAAI,IAAI,MAAM;AAChE,iBAAW,KAAK,QAAQ,IAAI,KAAK,OAAO,IAAI;AAC5C,YAAM,KAAK;AAAA,IACb,SAAS,OAAO;AACd,YAAM,KAAK,UAAU,OAAO,GAAG;AAAA,IACjC;AAEA,UAAM,EAAE,MAAM,QAAQ,GAAG,IAAI,MAAM,OAAO,aAAkB;AAC5D,UAAM,OAAO,GAAG,MAAM;AACtB,UAAM,gBAAgB,KAAK,KAAK,iBAAiB;AACjD,UAAM,aAAa,IAAI,gBAAgB;AACvC,QAAI,WAAW;AACf,QAAI;AACJ,UAAM,MAAM,MAAY;AACtB,mBAAa,KAAK;AAClB,cAAQ,WAAW,MAAM;AACvB,mBAAW;AACX,mBAAW,MAAM;AAAA,MACnB,GAAG,aAAa;AAAA,IAClB;AACA,UAAM,WAAW,MAAY,WAAW,MAAM;AAC9C,WAAO,iBAAiB,SAAS,UAAU,EAAE,MAAM,KAAK,CAAC;AACzD,QAAI;AACF,UAAI;AACJ,YAAM,WAAW,MAAM,IAAI,UAAU,KAAK,WAAW,MAAM;AAC3D,YAAM,SAAS,MAAM,KAAK,MAAM,GAAG;AACnC,UAAI,UAAU;AACd,UAAI;AACF,cAAM,SAAS,SAAS,MAAM,UAAU;AAExC,cAAM,cAAc,MAAY,KAAK,QAAQ,OAAO,EAAE,MAAM,MAAM,MAAS;AAC3E,mBAAW,OAAO,iBAAiB,SAAS,aAAa,EAAE,MAAM,KAAK,CAAC;AACvE,mBAAS;AACP,gBAAM,QAAQ,SAAS,MAAM,OAAO,KAAK,IAAI,EAAE,MAAM,MAAe,OAAO,OAAU;AACrF,cAAI,MAAM,KAAM;AAChB,cAAI;AACJ,qBAAW,MAAM,MAAM;AACvB,cAAI,UAAU,UAAU;AAEtB,wBAAY;AACZ;AAAA,UACF;AACA,gBAAM,OAAO,MAAM,MAAM,KAAK;AAAA,QAChC;AAAA,MACF,UAAE;AACA,cAAM,OAAO,MAAM;AAAA,MACrB;AACA,UAAI,YAAY,UAAU;AACxB,cAAM,IAAI,MAAM,sCAAsC,IAAI,IAAI,gBAAgB,OAAO,qBAAqB,QAAQ,EAAE;AAAA,MACtH;AACA,YAAM,OAAO,MAAM,MAAM;AAAA,IAC3B,SAAS,OAAO;AACd,YAAM,GAAG,MAAM,EAAE,OAAO,KAAK,CAAC;AAC9B,UAAI,OAAO,QAAS,OAAM,iBAAiB;AAC3C,UAAI,UAAU;AACZ,cAAM,IAAI,MAAM,gBAAgB,IAAI,IAAI,kBAAe,gBAAgB,GAAI,wBAAmB;AAAA,MAChG;AACA,YAAM,KAAK,UAAU,OAAO,GAAG;AAAA,IACjC,UAAE;AACA,mBAAa,KAAK;AAClB,aAAO,oBAAoB,SAAS,QAAQ;AAAA,IAC9C;AAEA,QAAI;AACF,YAAM,IAAI,oBAAoB,OAAO,IAAI,EAAE;AAAA,IAC7C,SAAS,OAAO;AAEd,WAAK,KAAK,KAAK,YAAY,IAAI,IAAI,0DAAoD,OAAO,KAAK,CAAC,EAAE;AAAA,IACxG;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAc,UAAU,KAAc,QAA+B;AACnE,UAAM,SAAS,aAAa,GAAG;AAC/B,QAAI,WAAW,QAAW;AACxB,YAAM,KAAK,aAAa,KAAK,QAAQ,MAAM;AAC3C;AAAA,IACF;AACA,UAAM,OAAO,QAAQ,IAAI,mBAAmB;AAC5C,QAAI,CAAC,KAAM,OAAM,iBAAiB,GAAG;AACrC,UAAM,EAAE,UAAU,SAAS,QAAQ,IAAI,KAAK,IAAI,MAAM,OAAO,aAAkB;AAC/E,UAAM,EAAE,MAAM,SAAAA,UAAS,IAAI,IAAI,MAAM,OAAO,MAAW;AACvD,UAAM,OAAOA,SAAQ,IAAI;AACzB,UAAM,SAASA,SAAQ,MAAM,IAAI,EAAE;AAGnC,QAAI,CAAC,YAAY,MAAM,QAAQ,GAAG,KAAK,CAAC,QAAQ,KAAK,IAAI,EAAE,GAAG;AAC5D,YAAM,IAAI,MAAM,oCAAiC,KAAK,UAAU,IAAI,EAAE,CAAC,EAAE;AAAA,IAC3E;AAEA,QAAI;AACJ,QAAI;AAEF,eAAS,MAAM,QAAQ,QAAQ,EAAE,eAAe,KAAK,CAAC,GAAG,OAAO,WAAS,MAAM,OAAO,CAAC,EAAE,IAAI,WAAS,MAAM,IAAI;AAAA,IAClH,SAAS,OAAO;AACd,UAAI,UAAU,KAAK,MAAM,YAAY,UAAU,KAAK,MAAM,UAAW,OAAM,iBAAiB,GAAG;AAC/F,YAAM;AAAA,IACR;AACA,QAAI,MAAM,WAAW,EAAG,OAAM,iBAAiB,GAAG;AAClD,QAAI,MAAM,SAAS,EAAG,OAAM,IAAI,MAAM,qBAAqB,IAAI,IAAI,SAAS,MAAM,MAAM,6BAAwB;AAEhH,SAAK,cAAc;AACnB,UAAM,OAAO,GAAG,MAAM;AACtB,QAAI;AACF,YAAM,SAAS,KAAK,QAAQ,MAAM,CAAC,CAAE,GAAG,IAAI;AAC5C,YAAM,EAAE,KAAK,IAAI,MAAM,KAAK,IAAI;AAChC,UAAI,SAAS,IAAI,MAAM;AACrB,cAAM,IAAI,MAAM,sCAAmC,IAAI,IAAI,eAAe,IAAI,qBAAqB,IAAI,IAAI,EAAE;AAAA,MAC/G;AACA,YAAM,OAAO,MAAM,MAAM;AAAA,IAC3B,SAAS,OAAO;AACd,YAAM,GAAG,MAAM,EAAE,OAAO,KAAK,CAAC;AAC9B,YAAM;AAAA,IACR;AACA,UAAM,GAAG,QAAQ,EAAE,WAAW,MAAM,OAAO,KAAK,CAAC;AAAA,EACnD;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAc,aAAa,KAAc,MAAc,QAA+B;AACpF,UAAM,EAAE,UAAU,QAAQ,IAAI,KAAK,IAAI,MAAM,OAAO,aAAkB;AACtE,UAAM,EAAE,SAAAA,SAAQ,IAAI,MAAM,OAAO,MAAW;AAC5C,UAAM,SAASA,SAAQ,IAAI;AAC3B,UAAM,OAAO,MAAM,KAAK,MAAM,EAAE,MAAM,MAAM,MAAS;AACrD,QAAI,CAAC,MAAM,OAAO,EAAG,OAAM,IAAI,MAAM,YAAY,IAAI,IAAI,0BAAuB,IAAI,EAAE;AACtF,SAAK,cAAc;AACnB,UAAM,OAAO,GAAG,MAAM;AACtB,QAAI;AACF,YAAM,SAAS,QAAQ,IAAI;AAC3B,YAAM,OAAO,MAAM,MAAM;AAAA,IAC3B,SAAS,OAAO;AACd,YAAM,GAAG,MAAM,EAAE,OAAO,KAAK,CAAC;AAC9B,YAAM;AAAA,IACR;AAAA,EACF;AAAA,EAEQ,UAAU,OAAgB,KAAuB;AACvD,QAAI,KAAK,KAAK,OAAO,QAAS,QAAO,iBAAiB;AACtD,QAAI,iBAAiB,iBAAiB,MAAM,WAAW,KAAK;AAC1D,aAAO,IAAI,cAAc,YAAY,IAAI,IAAI,+BAA4B,GAAG;AAAA,IAC9E;AACA,QAAI,iBAAiB,iBAAiB,MAAM,WAAW,KAAK;AAC1D,aAAO,IAAI,cAAc,YAAY,IAAI,IAAI,4CAAmC,GAAG;AAAA,IACrF;AACA,WAAO;AAAA,EACT;AACF;;;AClWA,IAAM,kBAAkB;AAAA,EACtB,OAAO;AAAA,EACP,MAAM;AAAA,EACN,SAAS;AAAA,EACT,OAAO;AAAA,EACP,SAAS;AACX;AAGO,SAAS,YAAY,SAAkB,MAAyB;AACrE,MAAI,KAAK,WAAW,EAAG,QAAO,WAAW,OAAO;AAChD,SAAO,CAAC,SAAS,GAAG,IAAI,EAAE,IAAI,UAAU,EAAE,KAAK,GAAG;AACpD;AAOO,SAAS,aAAa,SAAkB,MAA4D;AACzG,QAAM,OAAO,CAAC,SAAS,GAAG,IAAI;AAC9B,QAAM,OAAO,KAAK,KAAK,SAAS,CAAC;AACjC,MAAI,CAAC,kBAAkB,IAAI,EAAG,QAAO,EAAE,MAAM,YAAY,SAAS,IAAI,EAAE;AACxE,QAAM,OAAO,KAAK,MAAM,GAAG,EAAE;AAC7B,MAAI,KAAK,WAAW,EAAG,QAAO,EAAE,MAAM,KAAK,YAAY,SAAY,WAAW,KAAK,OAAO,IAAI,mBAAmB,OAAO,KAAK;AAC7H,SAAO,EAAE,MAAM,YAAY,KAAK,CAAC,GAAG,KAAK,MAAM,CAAC,CAAC,GAAG,OAAO,KAAK;AAClE;AAGO,SAAS,YAAY,OAAoB,SAAuB;AACrE,QAAM,OAAO,SAAS,YAAY,MAAM,YAAY,CAAC,IAAI,gBAAgB,KAAK,CAAC;AAC/E,QAAMC,UAAS,UAAU,YAAY,SAAS,UAAU,YAAY,SAAS;AAC7E,UAAQA,OAAM,EAAE,MAAM,OAAO;AAC/B;AAGO,IAAM,uBAAuB;AAEpC,IAAM,6BAA6B;AAO5B,SAAS,iBAAiB,SAAiB,OAAqB;AACrE,UAAQ,IAAI,GAAG,oBAAoB,IAAI,OAAO,IAAI,KAAK,EAAE;AAC3D;AAOA,SAAS,gBAAgB,IAAY,QAAoC;AACvE,SAAO,IAAI,QAAc,CAACC,UAAS,WAAW;AAC5C,QAAI,OAAO,SAAS;AAClB,aAAO,iBAAiB,CAAC;AACzB;AAAA,IACF;AACA,UAAM,UAAU,MAAY;AAC1B,mBAAa,KAAK;AAClB,aAAO,iBAAiB,CAAC;AAAA,IAC3B;AACA,UAAM,QAAQ,WAAW,MAAM;AAC7B,aAAO,oBAAoB,SAAS,OAAO;AAC3C,MAAAA,SAAQ;AAAA,IACV,GAAG,EAAE;AACL,WAAO,iBAAiB,SAAS,SAAS,EAAE,MAAM,KAAK,CAAC;AAAA,EAC1D,CAAC;AACH;AAEA,IAAM,gCAAgC;AACtC,IAAM,mCAAmC;AACzC,IAAM,+BAA+B;AAGrC,IAAM,+BAA+B;AACrC,IAAM,wBAAwB,YAAY;AAC1C,IAAM,qBAAqB,YAAY;AACvC,IAAM,oBAAoB;AAG1B,IAAM,wBAAwB,YAAY;AAC1C,IAAM,0BAA0B,YAAY;AAC5C,IAAM,yBAAyB,YAAY;AAC3C,IAAM,yBAAyB,YAAY;AAC3C,IAAM,0BAA0B;AAEhC,IAAM,iBAAiB;AAOvB,IAAM,oBAAoB;AAG1B,SAAS,kBAAkB,OAAgB,OAAwB;AACjE,MAAI,OAAO,UAAU,SAAU,QAAO,aAAa,KAAK;AACxD,MAAI,SAAS,KAAK,UAAU,QAAQ,OAAO,UAAU,SAAU,QAAO;AACtE,MAAI,MAAM,QAAQ,KAAK,EAAG,QAAO,MAAM,IAAI,WAAS,kBAAkB,OAAO,QAAQ,CAAC,CAAC;AACvF,QAAM,MAA+B,CAAC;AACtC,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,KAAgC,GAAG;AAC3E,QAAI,GAAG,IAAI,kBAAkB,OAAO,QAAQ,CAAC;AAAA,EAC/C;AACA,SAAO;AACT;AAWO,IAAM,cAAN,MAAkB;AAAA,EA8DvB,YACmB,KACR,OACQ,QACA,IACjB,iBACA,uBACA,SAAkC,CAAC,GACnC;AAPiB;AACR;AACQ;AACA;AAKjB,SAAK,kBAAkB,mBAAmB;AAC1C,SAAK,wBAAwB,KAAK;AAAA,MAChC;AAAA,MACA,KAAK,IAAI,8BAA8B,yBAAyB,gCAAgC;AAAA,IAClG;AACA,UAAM,QACJ,CAAC,UACD,CAAC,YAAqB,SAA0B;AAC9C,YAAM,EAAE,MAAM,OAAAC,OAAM,IAAI,aAAa,SAAS,IAAI;AAClD,WAAK,IAAI,OAAO,MAAMA,MAAK;AAAA,IAC7B;AACF,UAAM,MAAiB;AAAA,MACrB,OAAO,MAAM,OAAO;AAAA,MACpB,MAAM,MAAM,MAAM;AAAA,MAClB,MAAM,MAAM,SAAS;AAAA,MACrB,OAAO,MAAM,OAAO;AAAA,MACpB,SAAS,MAAM,SAAS;AAAA,IAC1B;AAGA,OAAG,iBAAiB,CAAC,OAAO,YAAY,KAAK,KAAK,OAAO,OAAO,CAAC;AAEjE,OAAG,kBAAkB,CAACA,QAAO,OAAO,KAAK,gBAAgBA,QAAO,EAAE,CAAC;AAGnE,UAAM,gBAAgB,MAAY,KAAK,cAAc;AACrD,OAAG,aAAa,aAAa;AAE7B,UAAM,WAAqB;AAAA,MACzB,QAAQ,CAAC,QAAQ,SAAS,SAAS,IAAIA,WAAU,KAAK,QAAQ,QAAQ,SAAS,SAAS,IAAIA,MAAK;AAAA,MACjG,WAAW,CAAC,IAAI,gBAAgB,GAAG,MAAM,IAAI,aAAa,MAAM;AAAA,MAChE,WAAW,CAAC,MAAM,OAAO,GAAG,MAAM,MAAM,EAAE;AAAA,MAC1C,cAAc,WAAS;AACrB,YAAI,KAAK,iBAAiB,KAAM,MAAK,YAAY,KAAK,iBAAiB,KAAK;AAAA,MAC9E;AAAA,MACA,SAAS,MAAM,KAAK,YAAY,KAAK,kBAAkB,GAAG,KAAK,aAAa;AAAA,MAC5E;AAAA,MACA,WAAW,MAAM,KAAK,gBAAgB,OAAO;AAAA,MAC7C,SAAS,aAAW,KAAK,IAAI,QAAQ,OAAO;AAAA,MAC5C,YAAY,aAAW,KAAK,IAAI,WAAW,OAAO;AAAA,MAClD,UAAU,aAAW,KAAK,IAAI,SAAS,OAAO;AAAA,MAC9C,OAAO,QAAM,gBAAgB,IAAI,KAAK,gBAAgB,MAAM;AAAA,MAC5D,aAAa,MAAM,KAAK,gBAAgB;AAAA,MACxC,OAAO,MAAM,KAAK,MAAM;AAAA,IAC1B;AACA,UAAM,QAAkB;AAAA,MACtB,KAAK,UAAQ;AACX,sBAAc;AACd,aAAK,QAAQ,KAAK,QAAQ,KAAK,SAAS,KAAK,SAAS,KAAK,IAAI,KAAK,KAAK;AAAA,MAC3E;AAAA,MACA,WAAW,CAAC,SAAS,YAAY;AAC/B,sBAAc;AACd,aAAK,QAAQ,aAAa,QAAW,SAAS,SAAS,IAAI,SAAS,KAAK;AAAA,MAC3E;AAAA,MACA,QAAQ,CAAC,SAAS,SAAS,YAAY;AACrC,sBAAc;AACd,aAAK,QAAQ,UAAU,SAAS,SAAS,SAAS,IAAI,SAAS,KAAK;AAAA,MACtE;AAAA,MACA,YAAY,CAAC,SAAS,SAAS,YAAY;AACzC,sBAAc;AACd,aAAK,QAAQ,cAAc,SAAS,SAAS,SAAS,IAAI,SAAS,KAAK;AAAA,MAC1E;AAAA,MACA,MAAM,CAAC,MAAM,SAAS,UAAU,CAAC,MAAM,SAAS,MAAM,SAAS,SAAS,QAAQ;AAAA,IAClF;AACA,UAAM,WAAW,OAAO;AAAA,MACtB;AAAA,QACE,OAAO,CAAC,UAAkB;AACxB,wBAAc;AACd,eAAK,YAAY,KAAK,iBAAiB,KAAK;AAAA,QAC9C;AAAA,QACA,SAAS,CAAC,QAAQ,MAAM;AACtB,wBAAc;AACd,eAAK,YAAY,KAAK,kBAAkB,OAAO,KAAK,aAAa;AAAA,QACnE;AAAA,QACA,KAAK,CAAC,SAAiB,UAAmB;AACxC,wBAAc;AACd,eAAK,YAAY,SAAS,SAAS,KAAK,aAAa;AAAA,QACvD;AAAA,MACF;AAAA,MACA;AAAA,QACE,SAAS,EAAE,YAAY,MAAM,KAAK,MAAM,KAAK,gBAAgB;AAAA,QAC7D,UAAU;AAAA,UACR,YAAY;AAAA,UACZ,KAAK,MAAO,KAAK,iBAAiB,OAAO,OAAO,EAAE,SAAS,KAAK,iBAAiB,OAAO,KAAK,cAAc;AAAA,QAC7G;AAAA,MACF;AAAA;AAAA,IAEF;AACA,UAAM,SAAS,KAAK,gBAAgB;AACpC,UAAMC,SAAQ,CAAC,OAA8B,gBAAgB,IAAI,MAAM;AACvE,SAAK,YAAY,IAAI,aAAa,EAAE,KAAK,OAAO,QAAQ,QAAQ,MAAM,aAAW,KAAK,IAAI,WAAW,OAAO,EAAE,CAAC;AAC/G,SAAK,UAAU;AAAA,MACb;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,OAAO,KAAK,UAAU;AAAA,MACtB,MAAM,OAAO,MAAM,IAAI,YAAY;AAEjC,cAAM,OAAO,GAAG,YAAY,MAAM;AAClC,YAAI;AACF,iBAAO,MAAM,GAAG,KAAK,MAAM,IAAI,EAAE,GAAG,SAAS,QAAQ,MAAMA,QAAO,MAAM,aAAW,KAAK,IAAI,WAAW,OAAO,EAAE,CAAC;AAAA,QACnH,UAAE;AAEA,cAAI,SAAS,UAAU,SAAS,QAAQ,CAAC,OAAO,QAAS,OAAM,KAAK,MAAM;AAAA,QAC5E;AAAA,MACF;AAAA,MACA,OAAO,CAAC,cAAuB,KAAK,MAAM,SAAS;AAAA,MACnD;AAAA,MACA,iBAAiB;AAAA,MACjB,OAAAA;AAAA,MACA,OAAO,CAAC,IAAI,YAA2B,iBAAiB,IAAI,EAAE,GAAG,SAAS,QAAQ,MAAMA,OAAM,CAAC;AAAA,IACjG;AAAA,EACF;AAAA,EA1HmB;AAAA,EACR;AAAA,EACQ;AAAA,EACA;AAAA,EAjEV;AAAA,EAED,SAAwB,CAAC;AAAA,EACzB,OAAO;AAAA,EACP,QAAuB,QAAQ,QAAQ;AAAA,EACvC,iBAAiB;AAAA,EACjB;AAAA,EACA;AAAA,EACS,kBAAkB,IAAI,gBAAgB;AAAA,EACtC;AAAA,EACA;AAAA;AAAA;AAAA;AAAA,EAKT,cAA8B,CAAC;AAAA,EAC/B,aAA4B,QAAQ,QAAQ;AAAA,EAC5C;AAAA,EACA,UAAU;AAAA;AAAA,EAEV,mBAAmB;AAAA;AAAA;AAAA;AAAA;AAAA,EAKnB,qBAAqB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMrB,mBAAmB;AAAA;AAAA;AAAA;AAAA;AAAA,EAKnB,cAAc;AAAA;AAAA;AAAA,EAIL,qBAAqB,oBAAI,IAAmB;AAAA,EACrD,kBAAkB;AAAA,EAClB,cAAc;AAAA,EACd,cAAiC,CAAC;AAAA;AAAA,EAElC,yBAAyB;AAAA;AAAA;AAAA,EAIzB,kBAAkB;AAAA,EAClB,gBAA+B;AAAA;AAAA,EAE/B,gBAAgB;AAAA,EAChB;AAAA,EACA,iBAAiB;AAAA;AAAA,EAEjB,oBAAoB;AAAA;AAAA,EAGX;AAAA;AAAA,EAgIjB,eAA8B;AAC5B,WAAO,KAAK,UAAU,QAAQ;AAAA,EAChC;AAAA,EAEA,IAAI,SAAkB;AACpB,WAAO,KAAK;AAAA,EACd;AAAA;AAAA,EAGA,gBAAsB;AACpB,QAAI,KAAK,gBAAgB,OAAO,QAAS,OAAM,iBAAiB;AAAA,EAClE;AAAA;AAAA,EAGA,QAAc;AACZ,SAAK,gBAAgB;AACrB,QAAI,CAAC,KAAK,gBAAgB,OAAO,QAAS,MAAK,gBAAgB,MAAM;AAAA,EACvE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAa;AACX,SAAK,MAAM;AACX,SAAK,OAAO;AACZ,SAAK,gBAAgB;AACrB,SAAK,mBAAmB;AACxB,SAAK,SAAS,CAAC;AAEf,SAAK,cAAc;AACnB,SAAK,gBAAgB;AACrB,QAAI,KAAK,YAAY,SAAS,GAAG;AAC/B,WAAK,OAAO,KAAK,GAAG,KAAK,YAAY,MAAM,+DAAyD;AACpG,WAAK,cAAc,CAAC;AAAA,IACtB;AAEA,UAAM,UAAU,KAAK,YAAY,OAAO,GAAG,KAAK,YAAY,MAAM;AAClE,eAAW,UAAU,QAAS,QAAO;AAAA,EACvC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,YAA2B;AACzB,SAAK,gBAAgB;AACrB,WAAO,KAAK,SAAS,EAAE,MAAM,CAAC,kBAAkB;AAAA,EAClD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,IAAI,OAAoB,SAAiBD,QAAwC;AAC/E,QAAI,KAAK,KAAM,QAAO;AACtB,UAAM,WAAW,aAAa,WAAW,OAAO,CAAC;AACjD,UAAM,KAAK,OAAO;AAClB,UAAM,eAAeA,WAAU,SAAY,SAAY,KAAK,gBAAgBA,QAAO,EAAE;AACrF,gBAAY,OAAO,eAAe,GAAG,QAAQ,cAAc,QAAQ;AACnE,SAAK,KAAK,OAAO,UAAU,MAAM,eAAe,CAAC,YAAY,IAAI,QAAW,EAAE;AAC9E,WAAO;AAAA,EACT;AAAA;AAAA,EAGQ,KAAK,OAAoB,SAAiB,kBAAkB,OAAO,aAAwB,KAAK,OAAO,GAAW;AACxH,QAAI,KAAK,KAAM,QAAO;AACtB,UAAM,WAAW,kBAAkB,UAAU,aAAa,OAAO;AACjE,SAAK,OAAO,KAAK;AAAA,MACf;AAAA,MACA;AAAA,MACA,SAAS,SAAS,UAAU,qBAAqB;AAAA,MACjD,GAAI,eAAe,YAAY,SAAS,IAAI,EAAE,aAAa,YAAY,MAAM,GAAG,YAAY,6BAA6B,EAAE,IAAI,CAAC;AAAA,IAClI,CAAC;AAED,QAAI,KAAK,OAAO,UAAU,mBAAmB;AAC3C,WAAK,UAAU;AAAA,IACjB,OAAO;AACL,WAAK,cAAc;AAAA,IACrB;AACA,WAAO;AAAA,EACT;AAAA,EAEQ,gBAAsB;AAC5B,QAAI,KAAK,MAAO;AAChB,SAAK,QAAQ,WAAW,MAAM;AAC5B,WAAK,QAAQ;AACb,WAAK,UAAU;AAAA,IACjB,GAAG,KAAK,eAAe;AACvB,eAAW,KAAK,KAAK;AAAA,EACvB;AAAA,EAEQ,kBAAwB;AAC9B,QAAI,KAAK,OAAO;AACd,mBAAa,KAAK,KAAK;AACvB,WAAK,QAAQ;AAAA,IACf;AAAA,EACF;AAAA,EAEQ,WAA0B;AAChC,WAAO,KAAK,OAAO,OAAO,GAAG,KAAK,OAAO,MAAM;AAAA,EACjD;AAAA;AAAA,EAGQ,YAAkB;AACxB,SAAK,gBAAgB;AACrB,QAAI,KAAK,QAAQ,KAAK,OAAO,WAAW,EAAG;AAC3C,UAAM,OAAO,KAAK,OAAO,OAAO,GAAG,KAAK,OAAO,MAAM;AACrD,aAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK,oBAAoB;AACxD,WAAK,QAAQ,EAAE,QAAQ,WAAW,MAAM,KAAK,MAAM,GAAG,IAAI,kBAAkB,EAAE,CAAC;AAAA,IACjF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,MAAM,YAAY,gBAA+B;AACrD,SAAK,GAAG,MAAM;AACd,SAAK,WAAW;AAChB,QAAI,KAAK,cAAe,MAAK,cAAc;AAAA,QACtC,MAAK,UAAU;AACpB,UAAM,QAAQ,KAAK;AAAA,MACjB,QAAQ,IAAI,CAAC,KAAK,YAAY,KAAK,OAAO,KAAK,GAAG,MAAM,SAAS,CAAC,CAAC,EAAE,MAAM,MAAM,MAAS;AAAA,MAC1F,IAAI,QAAc,CAAAD,aAAW,WAAW,WAAWA,UAAS,SAAS,CAAC,CAAC;AAAA,IACzE,CAAC;AAAA,EACH;AAAA;AAAA,EAGA,MAAM,gBAAkC;AACtC,SAAK,QAAQ,EAAE,QAAQ,UAAU,CAAC;AAClC,UAAM,KAAK;AACX,QAAI,CAAC,KAAK,KAAM,MAAK,iBAAiB;AACtC,WAAO,CAAC,KAAK;AAAA,EACf;AAAA,EAEA,gBAAsB;AACpB,SAAK,gBAAgB;AACrB,SAAK,gBAAgB;AACrB,SAAK,mBAAmB;AACxB,SAAK,QAAQ,EAAE,QAAQ,aAAa,MAAM,KAAK,oBAAoB,EAAE,CAAC;AAAA,EACxE;AAAA,EAEA,cAAc,OAAuB;AACnC,SAAK,gBAAgB;AACrB,SAAK,gBAAgB;AACrB,SAAK,mBAAmB;AACxB,SAAK,QAAQ,EAAE,QAAQ,UAAU,OAAO,MAAM,KAAK,oBAAoB,EAAE,CAAC;AAAA,EAC5E;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,sBAAqC;AAC3C,QAAI,OAAO,KAAK,SAAS;AACzB,WAAO,KAAK,SAAS,oBAAoB;AACvC,WAAK,QAAQ,EAAE,QAAQ,WAAW,MAAM,KAAK,MAAM,GAAG,kBAAkB,EAAE,CAAC;AAC3E,aAAO,KAAK,MAAM,kBAAkB;AAAA,IACtC;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA,EAKQ,YAAY,SAAiB,OAA4B;AAC/D,QAAI,KAAK,KAAM;AACf,QAAI,SAAS,SAAS,CAAC,OAAO,UAAU,KAAK,KAAK,QAAQ,IAAI;AAC5D,UAAI,CAAC,KAAK,gBAAgB;AACxB,aAAK,iBAAiB;AACtB,aAAK,OAAO,KAAK,oCAAiC,OAAO,KAAK,CAAC,6CAAwC;AAAA,MACzG;AACA;AAAA,IACF;AACA,UAAM,cAAc,OAAO,SAAS,OAAO,IAAI,KAAK,IAAI,GAAG,KAAK,MAAM,OAAO,CAAC,IAAI,KAAK;AACvF,UAAM,OAAO,SAAS,OAAO,cAAc,KAAK,IAAI,aAAa,KAAK;AACtE,UAAM,eAAe,UAAU,KAAK;AACpC,QAAI,SAAS,KAAK,mBAAmB,CAAC,aAAc;AACpD,SAAK,kBAAkB;AACvB,SAAK,gBAAgB;AAErB,QAAI,SAAS,KAAM;AAEnB,UAAM,MAAM,KAAK,IAAI;AACrB,QAAI,gBAAgB,QAAQ,SAAS,MAAM,KAAK,qBAAqB,4BAA4B;AAC/F,WAAK,oBAAoB;AACzB,uBAAiB,MAAM,KAAK;AAAA,IAC9B;AACA,SAAK,gBAAgB;AAErB,QAAI,KAAK,cAAe;AACxB,SAAK,gBAAgB,WAAW,MAAM;AACpC,WAAK,gBAAgB;AACrB,WAAK,cAAc;AAAA,IACrB,GAAG,iBAAiB;AACpB,eAAW,KAAK,aAAa;AAAA,EAC/B;AAAA,EAEQ,gBAAsB;AAC5B,SAAK,mBAAmB;AACxB,QAAI,KAAK,QAAQ,CAAC,KAAK,cAAe;AAEtC,QAAI,KAAK,OAAO,SAAS,EAAG,MAAK,UAAU;AAAA,QACtC,MAAK,QAAQ,EAAE,QAAQ,UAAU,CAAC;AAAA,EACzC;AAAA,EAEQ,qBAA2B;AACjC,QAAI,KAAK,eAAe;AACtB,mBAAa,KAAK,aAAa;AAC/B,WAAK,gBAAgB;AAAA,IACvB;AAAA,EACF;AAAA;AAAA,EAGQ,qBAA2B;AACjC,SAAK,mBAAmB;AACxB,SAAK,gBAAgB,KAAK,iBAAiB;AAAA,EAC7C;AAAA;AAAA,EAGQ,eAAwC;AAC9C,QAAI,CAAC,KAAK,iBAAiB,KAAK,iBAAiB,KAAM,QAAO;AAC9D,SAAK,gBAAgB;AACrB,WAAO,EAAE,SAAS,KAAK,iBAAiB,OAAO,KAAK,cAAc;AAAA,EACpE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,mBAAyB;AAC/B,QAAI,KAAK,WAAY;AACrB,SAAK,aAAa,YAAY,MAAM;AAElC,UAAI,KAAK,QAAQ,KAAK,iBAAiB,KAAK,KAAK,OAAO,SAAS,EAAG;AACpE,WAAK,QAAQ,EAAE,QAAQ,UAAU,CAAC;AAAA,IACpC,GAAG,KAAK,qBAAqB;AAC7B,eAAW,KAAK,UAAU;AAAA,EAC5B;AAAA,EAEQ,kBAAwB;AAC9B,QAAI,KAAK,YAAY;AACnB,oBAAc,KAAK,UAAU;AAC7B,WAAK,aAAa;AAAA,IACpB;AAAA,EACF;AAAA;AAAA,EAGA,WAA0B;AACxB,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASQ,QACN,QACA,SACA,SACA,IACAC,QACM;AACN,QAAI,KAAK,eAAe,KAAK,iBAAkB;AAE/C,QAAI;AACJ,QAAI,SAAS;AACX,wBAAkB,kBAAkB,SAAS,CAAC;AAC9C,UAAI;AACJ,UAAI;AACF,2BAAmB,KAAK,UAAU,eAAe,EAAE;AAAA,MACrD,QAAQ;AAAA,MAER;AACA,UAAI,qBAAqB,UAAa,mBAAmB,wBAAwB;AAC/E,aAAK,OAAO;AAAA,UACV,+BAA+B,qBAAqB,SAAY,2BAAqB,GAAG,gBAAgB,YAAY,sBAAsB,EAAE;AAAA,QAC9I;AACA,0BAAkB;AAAA,MACpB;AAAA,IACF;AAEA,UAAM,KAAK,OAAO;AAClB,UAAM,eAAeA,WAAU,SAAY,SAAY,KAAK,gBAAgBA,QAAO,EAAE;AACrF,SAAK,YAAY,KAAK;AAAA,MACpB,IAAI,KAAK,SAAS,OAAO,EAAE,GAAG,GAAG,IAAI,MAAM;AAAA,MAC3C,KAAK,KAAK;AAAA,MACV;AAAA,MACA,GAAI,UAAU,EAAE,SAAS,SAAS,aAAa,WAAW,OAAO,CAAC,GAAG,sBAAsB,EAAE,IAAI,CAAC;AAAA,MAClG,GAAI,kBAAkB,EAAE,SAAS,gBAAgB,IAAI,CAAC;AAAA,MACtD;AAAA,MACA,GAAI,eAAe,EAAE,aAAa,CAAC,YAAY,EAAE,IAAI,CAAC;AAAA,IACxD,CAAC;AAED,QAAI,KAAK,YAAY,UAAU,yBAAyB;AACtD,WAAK,WAAW;AAAA,IAClB,OAAO;AACL,WAAK,mBAAmB;AAAA,IAC1B;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,kBAAoD;AACxD,UAAM,MAAM,oBAAI,IAAY;AAC5B,QAAI,SAAwB;AAC5B,QAAI;AACF,SAAG;AACD,cAAM,OAA6B,MAAM,KAAK,IAAI,cAAc,KAAK,OAAO;AAAA,UAC1E,OAAO;AAAA,UACP,GAAI,SAAS,EAAE,OAAO,IAAI,CAAC;AAAA,QAC7B,CAAC;AACD,mBAAW,MAAM,KAAK,IAAK,KAAI,IAAI,EAAE;AACrC,iBAAS,KAAK;AAAA,MAChB,SAAS;AACT,aAAO;AAAA,IACT,SAAS,OAAO;AACd,WAAK,IAAI,WAAW,mHAA+F,cAAc,KAAK,CAAC,GAAG;AAC1I,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEQ,qBAA2B;AACjC,QAAI,KAAK,WAAY;AACrB,SAAK,aAAa,WAAW,MAAM;AACjC,WAAK,aAAa;AAClB,WAAK,WAAW;AAAA,IAClB,GAAG,KAAK,eAAe;AACvB,eAAW,KAAK,UAAU;AAAA,EAC5B;AAAA,EAEQ,kBAAwB;AAC9B,QAAI,KAAK,YAAY;AACnB,mBAAa,KAAK,UAAU;AAC5B,WAAK,aAAa;AAAA,IACpB;AAAA,EACF;AAAA;AAAA,EAGQ,aAAmB;AACzB,SAAK,gBAAgB;AACrB,QAAI,KAAK,YAAY,WAAW,KAAK,KAAK,iBAAkB;AAC5D,UAAM,QAAQ,KAAK,YAAY,OAAO,GAAG,KAAK,YAAY,MAAM;AAChE,aAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK,uBAAuB;AAC5D,YAAM,QAAQ,MAAM,MAAM,GAAG,IAAI,qBAAqB;AACtD,WAAK,aAAa,KAAK,WAAW,KAAK,MAAM,KAAK,UAAU,KAAK,CAAC;AAAA,IACpE;AAAA,EACF;AAAA,EAEA,MAAc,UAAU,OAAsC;AAC5D,QAAI,KAAK,iBAAkB;AAC3B,QAAI;AACF,YAAM,KAAK,IAAI,YAAY,KAAK,OAAO,EAAE,OAAO,MAAM,CAAC;AACvD,WAAK,mBAAmB;AAAA,IAC1B,SAAS,OAAO;AACd,UAAI,iBAAiB,iBAAiB,MAAM,WAAW,KAAK;AAE1D,aAAK,mBAAmB;AACxB,aAAK,OAAO,KAAK,8FAA6E;AAC9F;AAAA,MACF;AACA,UAAI,iBAAiB,iBAAiB,MAAM,WAAW,KAAK;AAC1D,YAAI,CAAC,KAAK,oBAAoB;AAC5B,eAAK,qBAAqB;AAC1B,eAAK,IAAI,WAAW,4EAAsE;AAAA,QAC5F;AACA;AAAA,MACF;AACA,UAAI,iBAAiB,iBAAiB,MAAM,WAAW,KAAK;AAC1D,YAAI,CAAC,KAAK,kBAAkB;AAC1B,eAAK,mBAAmB;AACxB,eAAK,IAAI,WAAW,mHAAqG;AAAA,QAC3H;AACA;AAAA,MACF;AACA,UAAI,iBAAiB,eAAe;AAGlC,aAAK,OAAO,MAAM,WAAW,MAAM,MAAM,sCAAsC,KAAK;AACpF,aAAK,IAAI,WAAW,GAAG,MAAM,MAAM,gEAAgE,MAAM,MAAM,GAAG;AAClH;AAAA,MACF;AAEA,WAAK,YAAY,QAAQ,GAAG,KAAK;AACjC,WAAK,mBAAmB;AACxB,WAAK,OAAO,MAAM,WAAW,MAAM,MAAM,mDAAgD,KAAK;AAAA,IAChG;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,cAAc,YAAY,gBAA+B;AAC7D,SAAK,WAAW;AAChB,UAAM,QAAQ,KAAK;AAAA,MACjB,KAAK;AAAA,MACL,IAAI,QAAc,CAAAD,aAAW,WAAW,WAAWA,UAAS,SAAS,CAAC,CAAC;AAAA,IACzE,CAAC;AACD,QAAI,KAAK,YAAY,SAAS,KAAK,CAAC,KAAK,oBAAoB,CAAC,KAAK,oBAAoB;AAErF,WAAK,WAAW;AAChB,YAAM,QAAQ,KAAK;AAAA,QACjB,KAAK;AAAA,QACL,IAAI,QAAc,CAAAA,aAAW,WAAW,WAAWA,UAAS,SAAS,CAAC,CAAC;AAAA,MACzE,CAAC;AAAA,IACH;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,gBAAgB,SAAqB,IAAgC;AACnE,QAAI,KAAK,KAAM,QAAO;AACtB,UAAMC,SAAQ,kBAAkB,OAAO;AACvC,QAAI,KAAK,uBAAwB,QAAO;AACxC,QAAI,KAAK,mBAAmB,yBAAyB;AACnD,UAAI,KAAK,oBAAoB,yBAAyB;AACpD,aAAK;AACL,aAAK,IAAI,WAAW,gCAAgC,uBAAuB,8BAAwB;AAAA,MACrG;AACA,aAAO;AAAA,IACT;AACA,SAAK;AAEL,UAAM,KAAK,MAAM;AACjB,UAAM,aAAaA,OAAM,YAAY,SAAY,WAAWA,OAAM,OAAO,IAAI;AAC7E,UAAM,UAAU,aAAa,SAAS,aAAa,UAAU,GAAG,iBAAiB,IAAI;AACrF,UAAM,OAAO,KAAK,iBAAiB,IAAIA,OAAM,OAAO,EAAE,SAAS,OAAO,IAAI,aAAaA,OAAM,YAAY,CAAC,EACvG,KAAK,MAAM,MAAS,EACpB,MAAM,MAAM,MAAS;AACxB,SAAK,mBAAmB,IAAI,IAAI;AAChC,SAAK,KAAK,QAAQ,MAAM,KAAK,mBAAmB,OAAO,IAAI,CAAC;AAC5D,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,MAAc,iBACZ,IACAA,QACA,MAC0C;AAC1C,QAAI;AACJ,QAAI;AACF,cAAQ,MAAM,QAAQA,MAAK;AAAA,IAC7B,SAAS,OAAO;AACd,WAAK,IAAI,WAAW,mCAA6B,OAAO,KAAK,CAAC,EAAE;AAChE,aAAO;AAAA,IACT;AAGA,UAAM,cAAc,iBAAiB,KAAK,KAAK,KAAK;AACpD,QAAI,CAAC,aAAa;AAChB,WAAK,IAAI,WAAW,0EAAuE;AAC3F,aAAO;AAAA,IACT;AACA,QAAI,MAAM,aAAa,sBAAsB;AAC3C,WAAK;AAAA,QACH;AAAA,QACA,sBAAsB,KAAK,MAAM,MAAM,aAAa,IAAI,CAAC,0BAA0B,uBAAuB,OAAO,IAAI;AAAA,MACvH;AACA,aAAO;AAAA,IACT;AAEA,UAAM,aAAa,kBAAkB,KAAK;AAC1C,UAAM,UAAU,MAAM,KAAK,kBAAkB;AAC7C,QAAI;AACF,UAAI,KAAK,gBAAgB,OAAO,WAAW,KAAK,KAAM,QAAO;AAC7D,YAAM,UAAU,MAAM,KAAK,IAAI;AAAA,QAC7B,KAAK;AAAA,QACL;AAAA,UACE;AAAA,UACA,cAAc;AAAA,UACd,YAAY,MAAM;AAAA,UAClB,QAAQ,KAAK;AAAA,UACb,GAAI,KAAK,UAAU,EAAE,SAAS,KAAK,QAAQ,IAAI,CAAC;AAAA,UAChD,GAAI,cAAc,CAAC;AAAA,QACrB;AAAA,QACA,KAAK,gBAAgB;AAAA,MACvB;AACA,YAAM,KAAK,IAAI,iBAAiB,QAAQ,YAAY,QAAQ,SAAS,OAAO,KAAK,gBAAgB,MAAM;AAEvG,YAAM,KAAK,IACR,kBAAkB,KAAK,OAAO,IAAI,EAAE,QAAQ,YAAY,YAAY,MAAM,YAAY,GAAI,cAAc,CAAC,EAAG,CAAC,EAC7G,MAAM,MAAM;AAAA,MAAC,CAAC;AACjB,aAAO;AAAA,IACT,SAAS,OAAO;AACd,UAAI,KAAK,cAAc,KAAK,GAAG;AAC7B,aAAK,yBAAyB;AAC9B,aAAK,IAAI,WAAW,kGAA8E;AAClG,eAAO;AAAA,MACT;AACA,UAAI,iBAAiB,iBAAiB,MAAM,WAAW,KAAK;AAC1D,aAAK,IAAI,WAAW,6EAAuE;AAC3F,eAAO;AAAA,MACT;AACA,UAAI,KAAK,gBAAgB,OAAO,QAAS,QAAO;AAChD,WAAK,IAAI,WAAW,6BAA6B,OAAO,KAAK,CAAC,EAAE;AAChE,WAAK,KAAK,IAAI,kBAAkB,KAAK,OAAO,IAAI,EAAE,QAAQ,SAAS,CAAC,EAAE,MAAM,MAAM;AAAA,MAAC,CAAC;AACpF,aAAO;AAAA,IACT,UAAE;AACA,cAAQ;AAAA,IACV;AAAA,EACF;AAAA;AAAA,EAGQ,cAAc,OAAyB;AAC7C,WAAO,iBAAiB,kBAAkB,MAAM,WAAW,OAAO,MAAM,WAAW,OAAO,MAAM,WAAW;AAAA,EAC7G;AAAA;AAAA,EAGQ,oBAAyC;AAC/C,UAAM,UAAU,MAAY;AAC1B,YAAM,OAAO,KAAK,YAAY,MAAM;AACpC,UAAI,KAAM,MAAK;AAAA,UACV,MAAK;AAAA,IACZ;AACA,QAAI,KAAK,cAAc,GAAG;AACxB,WAAK;AACL,aAAO,QAAQ,QAAQ,OAAO;AAAA,IAChC;AACA,WAAO,IAAI,QAAoB,CAAAD,aAAW;AACxC,WAAK,YAAY,KAAK,MAAMA,SAAQ,OAAO,CAAC;AAAA,IAC9C,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,oBAAoB,YAAY,qBAAoC;AACxE,QAAI,KAAK,mBAAmB,SAAS,EAAG;AACxC,UAAM,QAAQ,KAAK;AAAA,MACjB,QAAQ,WAAW,CAAC,GAAG,KAAK,kBAAkB,CAAC;AAAA,MAC/C,IAAI,QAAc,CAAAA,aAAW,WAAW,WAAWA,UAAS,SAAS,CAAC,CAAC;AAAA,IACzE,CAAC;AAAA,EACH;AAAA,EAEQ,QAAQ,UAAkC;AAChD,QAAI,KAAK,MAAM;AACb,WAAK,YAAY,SAAS,IAAI;AAC9B;AAAA,IACF;AAEA,SAAK,mBAAmB;AACxB,UAAM,WAAW,KAAK,aAAa;AACnC,UAAM,SAA2B,WAAW,EAAE,GAAG,UAAU,SAAS,IAAI;AACxE,SAAK;AACL,SAAK,QAAQ,KAAK,MAAM,KAAK,YAAY;AACvC,UAAI,KAAK,MAAM;AAEb,aAAK,YAAY,OAAO,IAAI;AAC5B;AAAA,MACF;AACA,YAAM,UAAU,OAAO,QAAQ,OAAO,KAAK,WAAW,IAAI,EAAE,GAAG,QAAQ,MAAM,OAAU,IAAI;AAC3F,UAAI;AACF,cAAM,KAAK,IAAI,UAAU,KAAK,OAAO,OAAO;AAAA,MAC9C,SAAS,OAAO;AACd,YAAI,iBAAiB,kBAAkB,MAAM,WAAW,OAAO,MAAM,WAAW,MAAM;AACpF,eAAK,OAAO;AACZ,eAAK,gBAAgB;AACrB,eAAK,MAAM;AAGX,gBAAM,UAAU,KAAK,OAAO,OAAO,GAAG,KAAK,OAAO,MAAM;AACxD,eAAK,YAAY,OAAO;AACxB,eAAK,OAAO;AAAA,YACV,OAAO,KAAK,KAAK,+DACd,QAAQ,SAAS,IAAI,KAAK,QAAQ,MAAM,qCAAqC;AAAA,UAClF;AACA;AAAA,QACF;AAEA,YAAI,OAAO,QAAQ,OAAO,KAAK,SAAS,GAAG;AACzC,eAAK,OAAO,QAAQ,GAAG,OAAO,IAAI;AAClC,eAAK,cAAc;AAAA,QACrB;AAEA,YAAI,OAAO,YAAY,KAAK,iBAAiB,KAAM,MAAK,gBAAgB;AACxE,aAAK,OAAO,MAAM,iBAAiB,KAAK,KAAK,aAAa,KAAK;AAAA,MACjE;AAAA,IACF,CAAC,EAAE,QAAQ,MAAM;AACf,WAAK;AAAA,IACP,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,YAAY,MAAuC;AACzD,QAAI,CAAC,QAAQ,KAAK,WAAW,EAAG;AAChC,aAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK,oBAAoB;AACxD,WAAK,KAAK,IACP,cAAc,KAAK,OAAO,EAAE,QAAQ,WAAW,MAAM,KAAK,MAAM,GAAG,IAAI,kBAAkB,EAAE,CAAC,EAC5F,MAAM,MAAM;AAAA,MAAC,CAAC;AAAA,IACnB;AAAA,EACF;AACF;;;AC96BA,IAAM,yBAAyB;AAO/B,eAAsB,WAAW,OAAuC;AACtE,QAAM,EAAE,KAAK,SAAS,KAAK,QAAQ,QAAQ,QAAQ,IAAI;AACvD,QAAM,UAAU,QAAQ;AAGxB,QAAM,KAAK,IAAI,YAAY,QAAQ,OAAO,cAAc,IAAI,IAAI,EAAE,MAAM,CAAC,OAAO,CAAC;AACjF,QAAM,WAAW,IAAI;AAAA,IACnB;AAAA,IACA,IAAI;AAAA,IACJ;AAAA,IACA;AAAA,IACA,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,IAAI;AAAA,EACN;AACA,UAAQ,IAAI,QAAQ;AAEpB,MAAI;AACF,UAAM,KAAK,MAAM,SAAS,cAAc;AACxC,QAAI,CAAC,IAAI;AACP,aAAO,MAAM,OAAO,IAAI,EAAE,6DAAqD;AAC/E,SAAG,UAAU,WAAW;AACxB,SAAG,OAAO;AACV;AAAA,IACF;AAEA,WAAO,MAAM,kBAAkB,IAAI,EAAE,EAAE;AACvC,QAAI;AACF,YAAM,kBAAkB,EAAE,SAAS,GAAG,MAAM,gBAAgB,SAAS,KAAK,UAAU,MAAM,CAAC;AAG3F,YAAM,SAAS,oBAAoB;AAGnC,YAAM,SAAS,cAAc;AAC7B,6BAAuB,QAAQ;AAE/B,SAAG,UAAU,IAAI;AACjB,SAAG,OAAO;AACV,eAAS,cAAc;AACvB,aAAO,MAAM,OAAO,IAAI,EAAE,eAAY;AAAA,IACxC,SAAS,OAAO;AAEd,YAAM,SAAS,oBAAoB;AAEnC,YAAM,SAAS,cAAc;AAC7B,SAAG,UAAU,OAAO;AACpB,SAAG,OAAO;AACV,wBAAkB,QAAQ,OAAO,QAAQ;AACzC,eAAS,cAAc,WAAW,KAAK,CAAC;AACxC,aAAO,MAAM,OAAO,IAAI,EAAE,YAAY,OAAO,KAAK,CAAC,EAAE;AAAA,IACvD;AACA,UAAM,SAAS,SAAS;AAAA,EAC1B,UAAE;AAEA,UAAM,SAAS,aAAa;AAC5B,YAAQ,OAAO,QAAQ;AAAA,EACzB;AACF;AAOA,SAAS,kBAAkB,QAA4B,OAAgB,UAA6B;AAClG,MAAI,CAAC,QAAQ,QAAQ,iBAAkB;AAEvC,MAAI,SAAS,UAAU,eAAe,KAAK,KAAK,YAAY,KAAK,EAAG;AACpE,SAAO,iBAAiB,OAAO,EAAE,MAAM,SAAS,MAAM,EAAE,WAAW,eAAe,QAAQ,SAAS,MAAM,EAAE,CAAC;AAC9G;AAOA,SAAS,uBAAuB,UAA6B;AAC3D,QAAM,WAAW,SAAS,QAAQ,SAAS;AAC3C,MAAI,CAAC,YAAY,SAAS,WAAW,SAAS,MAAO;AACrD,WAAS,QAAQ,IAAI;AAAA,IACnB,yDAAgD,SAAS,OAAO,IAAI,SAAS,KAAK;AAAA,EAEpF;AACF;AAOA,SAAS,gBAAgB,OAAqB,KAAoB,UAAuB,QAA+B;AACtH,QAAM,EAAE,SAAS,aAAa,IAAI,MAAM;AACxC,QAAM,QAAQ,UAAU;AACxB,QAAM,MAAM,SAAS;AACrB,SAAO,iBAAiB,MAAM,kBAAkB,OAAO,KAAK,UAAU,MAAM,GAAG;AAAA,IAC7E;AAAA,IACA,SAAS,aAAW,aAAa,cAAc,SAAS,sBAAsB;AAAA,IAC9E,aAAa,MAAM,CAAC,SAAS;AAAA,IAC7B,QAAQ,IAAI;AAAA,IACZ,MAAM,QAAM,IAAI,MAAM,EAAE;AAAA,IACxB,SAAS,CAAC,OAAO,SAAS,YAAY;AACpC,YAAM,SAAS,iBAAiB,QAAQ,GAAG,MAAM,IAAI,KAAK,MAAM,OAAO,KAAK,OAAO,KAAK;AACxF,UAAI,IAAI,KAAK,aAAa,OAAO,IAAI,KAAK,YAAY,SAAS,QAAQ,GAAG,CAAC,6BAAwB,OAAO,IAAI;AAAA,IAChH;AAAA,EACF,CAAC;AACH;AAEA,IAAM,mBAAmB,uBAAO,cAAc;AAC9C,IAAM,kBAAkB,uBAAO,eAAe;AAE9C,eAAe,kBAAkB,OAAqB,KAAoB,UAAuB,QAA+B;AAC9H,QAAM,EAAE,WAAW,cAAc,IAAI,MAAM;AAC3C,QAAM,UAAsB,MAAM;AAClC,QAAM,aAAa,QAAQ,QAAQ,EAAE,KAAK,MAAM,QAAQ,IAAI,QAAQ,SAAS,OAAO,CAAC;AACrF,QAAM,QAAqE,CAAC;AAC5E,MAAI,aAAa,YAAY,GAAG;AAC9B,UAAM,KAAK,MAAM,SAAS,EAAE,KAAK,MAAM,gBAAgB,CAAC;AAAA,EAC1D;AACA,MAAI,gBAAgB,GAAG;AACrB,UAAM,KAAK,mBAAmB,SAAS,QAAQ,QAAQ,aAAa,EAAE,KAAK,MAAM,eAAe,CAAC;AAAA,EACnG;AACA,MAAI,MAAM,WAAW,GAAG;AACtB,UAAM;AACN;AAAA,EACF;AAEA,QAAM,UAAU,MAAM,QAAQ,KAAK,CAAC,YAAY,GAAG,KAAK,CAAC;AACzD,MAAI,YAAY,oBAAoB,YAAY,gBAAiB;AAEjE,MAAI,YAAY,iBAAiB;AAI/B,WAAO;AAAA,MACL,OAAO,IAAI,EAAE,iEAAyD,aAAa;AAAA,IAErF;AACA;AAAA,EACF;AAGA,WAAS,MAAM;AACf,aACG,KAAK,MAAM,OAAO,KAAK,OAAO,IAAI,EAAE,kCAAkC,SAAS,IAAI,CAAC,EACpF,MAAM,MAAM,OAAO,KAAK,OAAO,IAAI,EAAE,gCAAgC,SAAS,sBAAsB,CAAC;AACxG,QAAM,iBAAiB,SAAU;AACnC;AAGA,SAAS,mBAAmB,QAAqB,SAAgC;AAC/E,SAAO,IAAI,QAAc,CAAAG,aAAW;AAElC,QAAI,OAAO,SAAS;AAClB,iBAAWA,UAAS,OAAO;AAC3B;AAAA,IACF;AAEA,WAAO,iBAAiB,SAAS,MAAM,WAAWA,UAAS,OAAO,GAAG,EAAE,MAAM,KAAK,CAAC;AAAA,EACrF,CAAC;AACH;AAEA,IAAM,0BAA0B,YAAY;AAC5C,IAAM,wBAAwB,YAAY;AAEnC,SAAS,WAAW,OAA0B;AACnD,MAAI,iBAAiB,OAAO;AAC1B,WAAO;AAAA,MACL,MAAM,MAAM;AAAA,MACZ,SAAS,aAAa,SAAS,MAAM,SAAS,uBAAuB,CAAC;AAAA,MACtE,OAAO,MAAM,QAAQ,aAAa,SAAS,MAAM,OAAO,qBAAqB,CAAC,IAAI;AAAA,IACpF;AAAA,EACF;AACA,SAAO,EAAE,SAAS,aAAa,SAAS,OAAO,KAAK,GAAG,uBAAuB,CAAC,EAAE;AACnF;;;AChMO,IAAM,2BAA2B;AACxC,IAAM,uBAAuB;AAC7B,IAAM,qBAAqB,YAAY;AAqBhC,IAAM,YAAN,MAAgB;AAAA,EAerB,YAA6B,SAA2B;AAA3B;AAC3B,SAAK,SAAS,QAAQ;AACtB,SAAK,MAAM,QAAQ;AACnB,SAAK,SAAS,QAAQ;AACtB,SAAK,UAAU,QAAQ;AACvB,SAAK,UAAU,QAAQ;AACvB,SAAK,iBAAiB,KAAK,IAAI,sBAAsB,QAAQ,kBAAkB,wBAAwB;AACvG,SAAK,UAAU,IAAI,QAAQ,KAAK,QAAQ,QAAQ,KAAK,cAAc;AAAA,EACrE;AAAA,EAR6B;AAAA,EAdpB;AAAA,EACA;AAAA,EAEQ;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAET,QAAoB;AAAA,EACpB;AAAA,EACA;AAAA,EACS,aAAa,oBAAI,IAAmB;AAAA,EAYrD,IAAI,cAAsB;AACxB,WAAO,KAAK,WAAW;AAAA,EACzB;AAAA,EAEA,QAAc;AACZ,QAAI,KAAK,UAAU,UAAW;AAC9B,QAAI,KAAK,UAAU,YAAY;AAC7B,YAAM,IAAI,MAAM,wEAAmE;AAAA,IACrF;AACA,SAAK,QAAQ;AACb,SAAK,OAAO,MAAM,qCAAkC,KAAK,QAAQ,QAAQ,WAAW,GAAG;AACvF,SAAK,SAAS,CAAC;AAAA,EACjB;AAAA;AAAA,EAGA,OAAa;AACX,QAAI,KAAK,UAAU,UAAW;AAC9B,QAAI,KAAK,OAAO;AACd,mBAAa,KAAK,KAAK;AACvB,WAAK,QAAQ;AAAA,IACf;AACA,SAAK,SAAS,CAAC;AAAA,EACjB;AAAA;AAAA,EAGA,MAAM,KAAK,YAAY,KAA0B;AAC/C,QAAI,KAAK,UAAU,OAAQ,QAAO;AAClC,SAAK,QAAQ;AACb,QAAI,KAAK,OAAO;AACd,mBAAa,KAAK,KAAK;AACvB,WAAK,QAAQ;AAAA,IACf;AACA,SAAK,WAAW,MAAM;AAEtB,UAAM,MAAM,QAAQ,WAAW,CAAC,GAAG,KAAK,UAAU,CAAC,EAAE,KAAK,MAAM,IAAI;AACpE,UAAM,WAAW,YAAY,IAAI,MAAM,QAAQ,KAAK,CAAC,KAAK,MAAM,SAAS,EAAE,KAAK,MAAM,KAAK,CAAC,CAAC,IAAI,KAAK,WAAW,SAAS;AAC1H,SAAK,QAAQ;AACb,WAAO;AAAA,EACT;AAAA;AAAA,EAGQ,SAAS,SAAuB;AACtC,QAAI,KAAK,UAAU,aAAa,KAAK,MAAO;AAC5C,SAAK,QAAQ,WAAW,MAAM;AAC5B,WAAK,QAAQ;AACb,WAAK,KAAK,KAAK;AAAA,IACjB,GAAG,OAAO;AAAA,EACZ;AAAA;AAAA,EAGQ,YAAoB;AAC1B,UAAM,OAAO,KAAK,QAAQ,QAAQ,cAAc,KAAK,QAAQ;AAC7D,WAAO,KAAK,IAAI,oBAAoB,KAAK,IAAI,GAAG,IAAI,CAAC;AAAA,EACvD;AAAA,EAEA,MAAc,OAAsB;AAElC,QAAI,KAAK,UAAU,UAAW;AAE9B,UAAM,MAAM,KAAK,UAAU;AAC3B,QAAI,QAAQ,GAAG;AACb,WAAK,SAAS,KAAK,cAAc;AACjC;AAAA,IACF;AAEA,SAAK,YAAY,IAAI,gBAAgB;AACrC,QAAI;AACF,YAAM,WAAW,MAAM,KAAK,IAAI;AAAA,QAC9B;AAAA;AAAA;AAAA,UAGE,UAAU,KAAK,QAAQ,aAAa;AAAA,UACpC;AAAA,QACF;AAAA,QACA,KAAK,UAAU;AAAA,MACjB;AACA,WAAK,QAAQ,MAAM;AAEnB,iBAAW,OAAO,SAAS,MAAM;AAC/B,aAAK,SAAS,GAAG;AAAA,MACnB;AAEA,WAAK,SAAS,SAAS,KAAK,SAAS,IAAI,IAAI,KAAK,cAAc;AAAA,IAClE,SAAS,OAAO;AACd,UAAI,KAAK,UAAU,UAAW;AAC9B,WAAK,SAAS,KAAK,QAAQ,KAAK,KAAK,CAAC;AAAA,IACxC,UAAE;AACA,WAAK,YAAY;AAAA,IACnB;AAAA,EACF;AAAA,EAEQ,SAAS,KAA0B;AACzC,UAAM,UAAU,KAAK,eAAe,GAAG,EACpC,MAAM,WAAS,KAAK,OAAO,MAAM,0BAA0B,IAAI,EAAE,KAAK,KAAK,CAAC,EAC5E,QAAQ,MAAM;AACb,WAAK,WAAW,OAAO,OAAO;AAC9B,UAAI,KAAK,UAAU,UAAW,MAAK,SAAS,CAAC;AAAA,IAC/C,CAAC;AACH,SAAK,WAAW,IAAI,OAAO;AAAA,EAC7B;AAAA,EAEA,MAAc,eAAe,KAAmC;AAC9D,UAAM,WAAW,EAAE,KAAK,SAAS,KAAK,SAAS,KAAK,KAAK,KAAK,QAAQ,KAAK,QAAQ,QAAQ,KAAK,QAAQ,SAAS,KAAK,QAAQ,CAAC;AAAA,EACjI;AACF;;;AC/IO,IAAe,kBAAf,MAAwE;AAAA,EAM7E,YACqB,SACA,MACnB;AAFmB;AACA;AAEnB,SAAK,OAAO,IAAI,QAAc,CAAAC,aAAW;AACvC,WAAK,cAAcA;AAAA,IACrB,CAAC;AAAA,EACH;AAAA,EANqB;AAAA,EACA;AAAA,EAPF,QAAQ,IAAI,gBAAgB;AAAA;AAAA,EAEtC;AAAA,EACD;AAAA,EAWR,MAAM,MAAqB;AACzB,QAAI;AACF,YAAM,MAAM,MAAM,KAAK,QAAQ;AAC/B,UAAI,CAAC,IAAK;AACV,WAAK,KAAK,OAAO,MAAM,KAAK,OAAO,GAAG,CAAC;AACvC,YAAM,WAAW;AAAA,QACf;AAAA,QACA,SAAS,KAAK;AAAA,QACd,KAAK,KAAK,KAAK;AAAA,QACf,QAAQ,KAAK,KAAK;AAAA,QAClB,QAAQ,KAAK,KAAK;AAAA,QAClB,SAAS,KAAK,KAAK;AAAA,MACrB,CAAC;AAAA,IACH,SAAS,OAAO;AACd,WAAK,KAAK,OAAO,MAAM,gDAA0C,KAAK;AAAA,IACxE,UAAE;AACA,WAAK,YAAY;AAAA,IACnB;AAAA,EACF;AAAA;AAAA,EAGA,OAAa;AACX,SAAK,MAAM,MAAM;AAAA,EACnB;AAOF;;;AC1DA,IAAM,wBAA2C,CAAC,KAAO,KAAO,IAAM;AAGtE,SAAS,YAAY,OAAyB;AAC5C,MAAI,EAAE,iBAAiB,eAAgB,QAAO;AAC9C,SAAO,MAAM,UAAU,OAAO,MAAM,WAAW;AACjD;AAEA,SAAS,kBAAkB,OAAe,OAAwB;AAChE,MAAI,iBAAiB,iBAAiB,MAAM,WAAW,KAAK;AAC1D,WAAO,OAAO,KAAK;AAAA,EACrB;AACA,MAAI,iBAAiB,iBAAiB,MAAM,WAAW,KAAK;AAC1D,WAAO,OAAO,KAAK;AAAA,EACrB;AACA,SAAO,wCAAkC,KAAK,KAAK,OAAO,KAAK,CAAC;AAClE;AASO,IAAM,iBAAN,cAA6B,gBAAiC;AAAA,EACnE,YACmB,OACjB,SACA,MACA;AACA,UAAM,SAAS,IAAI;AAJF;AAAA,EAKnB;AAAA,EALmB;AAAA,EAOT,OAAO,KAA4B;AAC3C,WAAO,OAAO,IAAI,EAAE;AAAA,EACtB;AAAA,EAEA,MAAgB,UAA8C;AAC5D,aAAS,UAAU,KAAK,WAAW;AACjC,UAAI,KAAK,MAAM,OAAO,QAAS,QAAO;AACtC,UAAI;AACF,eAAO,MAAM,KAAK,KAAK,IAAI,SAAS,KAAK,OAAO,EAAE,UAAU,KAAK,KAAK,aAAa,EAAE,GAAG,KAAK,MAAM,MAAM;AAAA,MAC3G,SAAS,OAAO;AACd,YAAI,KAAK,MAAM,OAAO,QAAS,QAAO;AACtC,YAAI,CAAC,YAAY,KAAK,GAAG;AACvB,eAAK,KAAK,OAAO,MAAM,kBAAkB,KAAK,OAAO,KAAK,CAAC;AAC3D,iBAAO;AAAA,QACT;AACA,cAAM,QAAQ,sBAAsB,OAAO;AAC3C,YAAI,UAAU,QAAW;AACvB,eAAK,KAAK,OAAO;AAAA,YACf,wCAAkC,KAAK,KAAK,YAAS,UAAU,CAAC,gBAAgB,OAAO,KAAK,CAAC;AAAA,UAC/F;AACA,iBAAO;AAAA,QACT;AACA,cAAM,OAAO,OAAO,KAAK;AACzB,aAAK,KAAK,OAAO,KAAK,oBAAiB,KAAK,KAAK,YAAY,OAAO,KAAK,CAAC,8BAA2B,IAAI,IAAI;AAC7G,cAAM,eAAe,MAAM,KAAK,MAAM,MAAM;AAAA,MAC9C;AAAA,IACF;AAAA,EACF;AACF;;;ACjEA,IAAM,SAAS;AACf,IAAM,cAAc,YAAY;AAChC,IAAM,kBAAkB,YAAY;AAU7B,SAAS,qBAAqB,OAAgB,QAA0C;AAC7F,MAAI,UAAU,UAAa,UAAU,KAAM,QAAO;AAClD,QAAM,UAAW,MAAgC;AACjD,MAAI,OAAO,UAAU,YAAY,CAAC,MAAM,QAAQ,OAAO,GAAG;AACxD,WAAO,KAAK,iFAAsE;AAClF,WAAO;AAAA,EACT;AAEA,QAAM,SAAuB,CAAC;AAC9B,QAAM,OAAO,oBAAI,IAAY;AAC7B,aAAW,SAAS,SAAsB;AACxC,UAAM,SAAS,OAAO,UAAU,WAAW,QAAS,OAAoC;AACxF,UAAM,WAAW,OAAO,UAAU,YAAY,UAAU,OAAQ,MAA8B,QAAQ;AACtG,UAAM,MAAM,OAAO,WAAW,WAAW,OAAO,KAAK,IAAI;AACzD,QAAI,CAAC,OAAO,KAAK,GAAG,GAAG;AACrB,aAAO,KAAK,wCAAqC,KAAK,UAAU,MAAM,CAAC,8DAAmD;AAC1H;AAAA,IACF;AACA,QAAI,KAAK,IAAI,GAAG,GAAG;AACjB,aAAO,KAAK,mBAAmB,GAAG,qBAAqB;AACvD;AAAA,IACF;AACA,QAAI,OAAO,UAAU,aAAa;AAChC,aAAO,KAAK,gBAAa,WAAW,4BAAuB,GAAG,uBAAuB;AACrF;AAAA,IACF;AACA,SAAK,IAAI,GAAG;AACZ,UAAM,QAAQ,OAAO,aAAa,WAAW,SAAS,KAAK,EAAE,MAAM,GAAG,eAAe,IAAI;AACzF,WAAO,KAAK,QAAQ,EAAE,KAAK,MAAM,IAAI,EAAE,IAAI,CAAC;AAAA,EAC9C;AACA,SAAO,OAAO,SAAS,IAAI,SAAS;AACtC;;;AC5BO,IAAM,cAAN,cAA0B,gBAAiC;AAAA,EAC/C;AAAA,EAEjB,YAAY,SAAuB,MAAuB;AACxD,UAAM,SAAS,IAAI;AACnB,SAAK,UAAU,IAAI,QAAQ,KAAK,QAAQ,sBAAgB;AAAA,EAC1D;AAAA,EAEU,OAAO,KAA4B;AAC3C,WAAO,OAAO,IAAI,EAAE;AAAA,EACtB;AAAA,EAEA,MAAgB,UAA8C;AAC5D,eAAS;AACP,UAAI,KAAK,MAAM,OAAO,QAAS,QAAO;AACtC,UAAI;AACF,eAAO,MAAM,KAAK,KAAK,IAAI,UAAU,EAAE,UAAU,KAAK,KAAK,aAAa,EAAE,GAAG,KAAK,MAAM,MAAM;AAAA,MAChG,SAAS,OAAO;AACd,YAAI,KAAK,MAAM,OAAO,QAAS,QAAO;AACtC,cAAM,eAAe,KAAK,QAAQ,KAAK,KAAK,GAAG,KAAK,MAAM,MAAM;AAAA,MAClE;AAAA,IACF;AAAA,EACF;AACF;;;AC5BO,IAAM,eAAe;AAErB,IAAM,mBAAmB;AAEzB,IAAM,sBAAsB;AAC5B,IAAM,gCAAgC;AAK7C,SAAS,YAAY,MAAqB;AACxC,SAAO,IAAI,MAAM,YAAY,IAAI,mEAA0D;AAC7F;AAGA,SAAS,KAAK,OAAmC;AAE/C,UAAQ,SAAS,IAAI,QAAQ,kBAAkB,GAAG;AACpD;AASO,IAAM,oBAAN,MAAgD;AAAA,EAMrD,YAEmB,SAAkC,CAAC,GACnC,MAA8B,UAAQ,KAAK,QAAQ,OAAO,MAAM,GAAG,IAAI;AAAA,CAAI,GAC5F;AAFiB;AACA;AAAA,EAChB;AAAA,EAFgB;AAAA,EACA;AAAA,EARF,SAAwC,EAAE,WAAW,GAAG,YAAY,GAAG,QAAQ,EAAE;AAAA,EAC1F,oBAAoB;AAAA;AAAA,EAE5B;AAAA,EAQA,MAAM,UAAU,QAAgB,QAAyC;AACvE,QAAI,OAAO,WAAW,UAAW;AACjC,SAAK,iBAAiB,OAAO;AAE7B,QAAI,OAAO,WAAW,YAAY,OAAO,SAAS,OAAO,MAAM,SAAS,eAAe;AACrF,kBAAY,SAAS,gCAAqB,OAAO,MAAM,QAAQ,OAAO,KAAK,OAAO,MAAM,OAAO,EAAE;AACjG,UAAI,OAAO,MAAM,MAAO,SAAQ,MAAM,OAAO,MAAM,KAAK;AAAA,IAC1D;AAAA,EACF;AAAA,EAEA,MAAM,gBAA+B;AAAA,EAErC;AAAA,EAEA,MAAM,YAAY,QAAgB,SAAiE;AACjG,eAAW,QAAQ,QAAQ,OAAO;AAChC,WAAK,OAAO,KAAK,MAAM;AACvB,WAAK,IAAI,GAAG,gBAAgB,IAAI,KAAK,MAAM,IAAK,KAAK,KAAK,EAAE,CAAC,IAAK,KAAK,KAAK,OAAO,CAAC,EAAE;AAAA,IACxF;AACA,WAAO,EAAE,UAAU,QAAQ,MAAM,QAAQ,YAAY,EAAE;AAAA,EACzD;AAAA;AAAA,EAGA,MAAM,gBAA+C;AACnD,WAAO,EAAE,KAAK,CAAC,GAAG,MAAM,KAAK;AAAA,EAC/B;AAAA;AAAA,EAGA,eAAqB;AACnB,UAAM,EAAE,WAAW,YAAY,OAAO,IAAI,KAAK;AAC/C,SAAK;AAAA,MACH,GAAG,mBAAmB,UAAU,YAAY,aAAa,MAAM,OAAO,SAAS,WAAW,UAAU,WAAW,MAAM;AAAA,IACvH;AAAA,EACF;AAAA,EAEA,MAAM,iBAAiB,QAAgB,SAA2E;AAChH,QAAI,CAAC,KAAK,mBAAmB;AAC3B,WAAK,oBAAoB;AACzB,kBAAY,WAAW,6BAA6B;AAAA,IACtD;AAEA,WAAO,EAAE,IAAI,QAAQ,IAAI,YAAY,IAAI,SAAS,CAAC,GAAG,YAAY,EAAE;AAAA,EACtE;AAAA,EAEA,MAAM,mBAAkC;AAAA,EAExC;AAAA,EAEA,MAAM,oBAAmC;AAAA,EAEzC;AAAA;AAAA,EAGQ,SAAS,QAAwB;AACvC,WAAO,gBAAgB,KAAK,MAAM,EAAE,KAAK,SAAO,IAAI,OAAO,MAAM,GAAG,QAAQ;AAAA,EAC9E;AAAA,EAEA,MAAM,oBAAoB,QAAgB,QAA+C;AACvF,UAAM,YAAY,KAAK,SAAS,MAAM,CAAC;AAAA,EACzC;AAAA,EAEA,MAAM,UAAU,KAAgC;AAC9C,UAAM,YAAY,GAAG;AAAA,EACvB;AAAA,EAEA,MAAM,oBAAoB,QAAgB,QAA+B;AACvE,UAAM,YAAY,KAAK,SAAS,MAAM,CAAC;AAAA,EACzC;AACF;;;AC9GO,IAAM,uBAAwD,EAAE,WAAW,GAAG,QAAQ,GAAG,UAAU,IAAI;AAEvG,IAAM,4BAA4B;AAClC,IAAM,mBAAmB;AAQzB,IAAM,iBAAN,cAA6B,gBAA8B;AAAA,EAKhE,YACmB,QACjB,SACA,MACA;AACA,UAAM,SAAS,IAAI;AAJF;AAAA,EAKnB;AAAA,EALmB;AAAA,EALX,WAAW;AAAA,EACX,YAAY,KAAK,IAAI;AAAA,EACrB,WAAW;AAAA,EAUV,MAAqB;AAC5B,SAAK,YAAY,KAAK,IAAI;AAC1B,WAAO,MAAM,IAAI;AAAA,EACnB;AAAA,EAEU,SAAiB;AACzB,WAAO;AAAA,EACT;AAAA,EAEA,MAAgB,UAA8C;AAC5D,QAAI,KAAK,MAAM,OAAO,QAAS,QAAO;AACtC,WAAO,EAAE,IAAI,cAAc,QAAQ,KAAK,QAAQ,MAAM,MAAM,QAAQ,SAAS,YAAY,OAAO,EAAE;AAAA,EACpG;AAAA;AAAA,EAGA,SAAe;AACb,SAAK,WAAW;AAChB,SAAK,KAAK,QAAQ,aAAa,GAAG,MAAM;AAAA,EAC1C;AAAA;AAAA,EAGA,IAAI,UAA2B;AAC7B,QAAI,KAAK,SAAU,QAAO;AAC1B,WAAO,KAAK,KAAK,IAAI,kBAAkB;AAAA,EACzC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,SAA0B;AACxB,UAAM,UAAU,KAAK;AACrB,QAAI,KAAK,SAAU,QAAO;AAC1B,SAAK,WAAW;AAChB,SAAK,KAAK,IAAI,aAAa;AAC3B,UAAM,UAAU,KAAK,OAAO,KAAK,IAAI,IAAI,KAAK,aAAa,GAAI;AAC/D,gBAAY,QAAQ,sCAA6B,OAAO,QAAQ,OAAO,GAAG;AAC1E,WAAO;AAAA,EACT;AACF;;;ACpEO,IAAM,aAAN,MAAiB;AAAA,EAItB,YAA6B,KAAmB;AAAnB;AAAA,EAAoB;AAAA,EAApB;AAAA,EAHZ,YAAY,oBAAI,IAAiB;AAAA,EACjC,UAAU,oBAAI,IAAgB;AAAA,EAI/C,IAAI,UAA6B;AAC/B,SAAK,UAAU,IAAI,QAAQ;AAAA,EAC7B;AAAA,EAEA,OAAO,UAA6B;AAClC,SAAK,UAAU,OAAO,QAAQ;AAC9B,QAAI,KAAK,UAAU,SAAS,GAAG;AAC7B,iBAAWC,YAAW,KAAK,QAAS,CAAAA,SAAQ;AAC5C,WAAK,QAAQ,MAAM;AAAA,IACrB;AAAA,EACF;AAAA,EAEA,IAAI,cAAsB;AACxB,WAAO,KAAK,UAAU;AAAA,EACxB;AAAA;AAAA,EAGA,eAAwC;AACtC,QAAI,KAAK,UAAU,SAAS,EAAG,QAAO;AACtC,WAAO,KAAK,UAAU,OAAO,EAAE,KAAK,EAAE;AAAA,EACxC;AAAA;AAAA,EAGA,MAAM,SAAS,WAAqC;AAClD,QAAI,KAAK,UAAU,SAAS,EAAG,QAAO;AACtC,UAAM,OAAO,IAAI,QAAiB,CAAAA,aAAW,KAAK,QAAQ,IAAI,MAAMA,SAAQ,IAAI,CAAC,CAAC;AAClF,QAAI,aAAa,EAAG,QAAO;AAC3B,WAAO,QAAQ,KAAK,CAAC,MAAM,MAAM,SAAS,EAAE,KAAK,MAAM,KAAK,CAAC,CAAC;AAAA,EAChE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,sBAAsB,SAAiB,YAAY,MAAsB;AAC7E,UAAM,UAA2B,CAAC;AAClC,eAAW,YAAY,KAAK,WAAW;AACrC,UAAI,SAAS,OAAQ;AAGrB,YAAM,OAAO,SAAS,UAAU;AAChC,eAAS,KAAK;AACd,cAAQ;AAAA,QACN,KAAK,IACF;AAAA,UACC,SAAS,QAAQ;AAAA,UACjB,EAAE,QAAQ,UAAU,OAAO,EAAE,MAAM,mBAAmB,QAAQ,GAAG,MAAM,KAAK,SAAS,IAAI,OAAO,OAAU;AAAA,UAC1G;AAAA,QACF,EACC,MAAM,MAAM;AAAA,QAAC,CAAC;AAAA,MACnB;AAAA,IACF;AACA,QAAI,QAAQ,WAAW,EAAG;AAC1B,UAAM,QAAQ,KAAK,CAAC,QAAQ,WAAW,OAAO,GAAG,MAAM,SAAS,CAAC,CAAC;AAAA,EACpE;AACF;;;ACnEA,IAAM,kBAAkB,CAAC,UAAU,SAAS;AAiBrC,SAAS,wBAAwB,OAAmC;AACzE,MAAI,CAAC,OAAO,EAAG,QAAO,MAAM;AAAA,EAAC;AAE7B,MAAI,WAAW;AACf,QAAM,iBAAiB,oBAAI,IAA+B;AAE1D,aAAW,UAAU,iBAAiB;AACpC,UAAM,UAAU,aAAa,MAAM;AAEjC,UAAI,sBAAsB,MAAM,IAAI,EAAG;AACvC,UAAI,SAAU;AACd,iBAAW;AAEX,YAAM,UAAU,MAAY;AAC1B,gBAAQ,eAAe,QAAQ,OAAO;AACtC,gBAAQ,KAAK,QAAQ,KAAK,MAAM;AAAA,MAClC;AACA,UAAI,MAAM,gBAAgB,GAAG;AAC3B,gBAAQ;AACR;AAAA,MACF;AACA,YAAM,SAAS,MAAM,sBAAsB,gCAAgC,MAAM,2BAAqB;AACtG,uBAAiB,MAAM;AACvB,WAAK,OAAO,QAAQ,OAAO;AAAA,IAC7B,CAAC;AACD,YAAQ,GAAG,QAAQ,OAAO;AAC1B,mBAAe,IAAI,QAAQ,OAAO;AAAA,EACpC;AAEA,QAAM,UAAU,aAAa,CAAC,UAAiB;AAC7C,UAAM,SACJ,MAAM,cAAc,IAChB,MAAM,sBAAsB,iFAAwE,IACpG,QAAQ,QAAQ;AACtB,qBAAiB,MAAM;AAGvB,QAAI,CAAC,2BAA2B,KAAK,sBAAsB,mBAAmB,MAAM,GAAG;AACrF,WAAK,OAAO,QAAQ,MAAM;AACxB,gBAAQ,MAAM,KAAK;AACnB,gBAAQ,KAAK,CAAC;AAAA,MAChB,CAAC;AAAA,IACH;AAAA,EACF,CAAC;AACD,UAAQ,GAAG,qBAAqB,OAAO;AAEvC,SAAO,MAAM;AACX,eAAW,CAAC,QAAQ,OAAO,KAAK,eAAgB,SAAQ,eAAe,QAAQ,OAAO;AACtF,YAAQ,eAAe,qBAAqB,OAAO;AAAA,EACrD;AACF;;;ACrCA,IAAM,wBAAwB;AAC9B,IAAMC,mBAAkB;AACxB,IAAMC,0BAAyB;AAC/B,IAAM,0BAA0B;AAChC,IAAM,kBAAkB;AAgCxB,IAAI;AACJ,IAAI,kBAAkB;AAGtB,SAAS,WAA+B;AACtC,MAAI,CAAC,OAAO,EAAG,QAAO;AACtB,SAAO,QAAQ,IAAI,YAAY,QAAQ,IAAI,gBAAgB;AAC7D;AAEA,SAAS,YAAY,SAAwB,SAAuB,QAAgB,KAA4B;AAC9G,SAAO;AAAA,IACL,SAAS,EAAE,GAAG,SAAS,cAAc,OAAU;AAAA,IAC/C,QAAQ;AAAA,IACR;AAAA,IACA;AAAA,IACA;AAAA,IACA,SAAS,IAAI,WAAW,GAAG;AAAA,IAC3B,SAAS;AAAA,IACT,WAAW;AAAA,IACX,OAAO;AAAA,IACP,OAAO;AAAA,IACP,UAAU;AAAA,IACV,UAAU;AAAA,IACV,OAAO;AAAA,IACP,YAAY,kBAAkB,QAAQ,UAAU;AAAA,IAChD,aAAa;AAAA,IACb,gBAAgB;AAAA,IAChB,QAAQ;AAAA,IACR,eAAe;AAAA,IACf,aAAa;AAAA,IACb,yBAAyB;AAAA,IACzB,mBAAmB;AAAA,EACrB;AACF;AAMA,SAAS,cAAc,SAAwB,SAAuB,QAAyB;AAC7F,QAAM,SAAS,cAAc,EAAE,cAAc,QAAQ,aAAa,CAAC;AACnE,QAAM,cAAc,yBAAyB,QAAQ,WAAW;AAChE,QAAM,SAAS,IAAI;AAAA,IACjB;AAAA,MACE;AAAA,MACA,SAAS,QAAQ;AAAA,MACjB,MAAM,QAAQ;AAAA,MACd,OAAO,QAAQ;AAAA,MACf,kBAAkB,QAAQ,qBAAqB;AAAA,IACjD;AAAA,IACA;AAAA,EACF;AACA,QAAM,MAAM,IAAI,SAAS,EAAE,SAAS,OAAO,aAAa,KAAK,OAAO,KAAK,OAAO,CAAC;AACjF,QAAM,KAAK,YAAY,SAAS,SAAS,QAAQ,GAAG;AACpD,KAAG,SAAS;AACZ,KAAG,cAAc;AACjB,KAAG,0BAA0B,QAAQ,qBAAqB,QAAQ,sBAAsB,MAAM,IAAI;AAClG,SAAO,MAAM,gBAAgB,EAAE,UAAU,OAAO,eAAe,CAAC;AAChE,SAAO;AACT;AAMA,SAAS,sBAAsB,SAAwB,SAAuB,QAAyB;AACrG,MAAI;AACJ,MAAI;AACF,aAAS,sBAAsB;AAAA,EACjC,SAAS,OAAO;AACd,gBAAY,SAAS,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;AAC3E,YAAQ,KAAK,CAAC;AAEd,UAAM;AAAA,EACR;AACA,QAAM,YAAY,IAAI,kBAAkB,MAAM;AAC9C,QAAM,KAAK,YAAY,SAAS,SAAS,QAAQ,SAAS;AAC1D,KAAG,WAAW,IAAI,eAAe,QAAQ,SAAS,EAAE,KAAK,WAAW,QAAQ,QAAW,QAAQ,SAAS,GAAG,QAAQ,CAAC;AACpH,cAAY,QAAQ,gBAAgB;AACpC,SAAO;AACT;AAEA,SAAS,gBAAgB,SAAkB,IAAkB;AAC3D,MAAI,OAAO,YAAY,YAAY;AACjC,UAAM,IAAI,MAAM,YAAY,EAAE,qDAA0C,EAAE,6BAA6B;AAAA,EACzG;AACF;AAEA,SAAS,iBAAiB,OAAmC;AAC3D,MAAI,UAAU,UAAa,CAAC,OAAO,SAAS,KAAK,EAAG,QAAO;AAC3D,SAAO,KAAK,IAAI,iBAAiB,KAAK,IAAI,GAAG,KAAK,MAAM,KAAK,CAAC,CAAC;AACjE;AAEA,SAAS,kBAAkB,SAA0B,MAAiB,QAAoC;AACxG,QAAM,UAAU,QAAQ,YAAY,UAAa,CAAC,OAAO,SAAS,QAAQ,OAAO,IAAID,mBAAkB,KAAK,IAAI,GAAG,KAAK,MAAM,QAAQ,OAAO,CAAC;AAC9I,SAAO;AAAA,IACL;AAAA,IACA,cAAc,QAAQ,gBAAgBC;AAAA,IACtC,WAAW,QAAQ,aAAa,QAAQ,YAAY,IAAI,QAAQ,YAAY;AAAA,IAC5E,aAAa,SAAS,WAAW,iBAAiB,QAAQ,WAAW,IAAI;AAAA,IACzE,oBAAoB,QAAQ;AAAA,IAC5B,uBAAuB,QAAQ;AAAA,IAC/B,eAAe,QAAQ,iBAAiB;AAAA,IACxC,aAAa,qBAAqB,QAAQ,OAAO,MAAM;AAAA,EACzD;AACF;AAGA,SAAS,aAAa,IAA2B;AAC/C,SAAO;AAAA;AAAA,IAEL,aAAa,GAAG,cAAc;AAAA;AAAA,IAE9B,SAAS;AAAA,IACT,MAAM,SAAS;AAAA;AAAA,IAEf,aAAa,GAAG;AAAA;AAAA,IAEhB,MAAM,GAAG,QAAQ,SAAS,WAAW,cAAc;AAAA;AAAA,IAEnD,OAAO,GAAG,QAAQ,QAAQ,cAAc,EAAE,YAAY,GAAG,QAAQ,QAAQ,YAAY,IAAI;AAAA;AAAA;AAAA,IAGzF,kBAAkB,GAAG,QAAQ,KAAK,IAAI,KAAK,IAAI,GAAG,MAAM,gBAAgB,GAAK,GAAG,GAAO,IAAI;AAAA;AAAA,IAE3F,SAAS,GAAG,SAAS,OAAO;AAAA,EAC9B;AACF;AAGA,SAAS,YAAY,IAAuB;AAC1C,SAAO,GAAG;AACZ;AAEA,SAAS,YAAY,IAAwB;AAC3C,KAAG,UAAU,IAAI,UAAU;AAAA,IACzB,KAAK,YAAY,EAAE;AAAA,IACnB,QAAQ,GAAG;AAAA,IACX,QAAQ,GAAG;AAAA,IACX,SAAS,GAAG;AAAA,IACZ,SAAS,GAAG;AAAA,IACZ,cAAc,MAAM,aAAa,EAAE;AAAA,IACnC,gBAAgB,GAAG;AAAA,EACrB,CAAC;AACD,SAAO,GAAG;AACZ;AAEA,SAAS,YAAY,IAAmB;AACtC,QAAM,SAAS,IAAI,YAAY,GAAG,SAAS;AAAA,IACzC,KAAK,YAAY,EAAE;AAAA,IACnB,QAAQ,GAAG;AAAA,IACX,QAAQ,GAAG;AAAA,IACX,SAAS,GAAG;AAAA,IACZ,cAAc,MAAM,aAAa,EAAE;AAAA,EACrC,CAAC;AACD,KAAG,QAAQ;AACX,OAAK,OAAO,IAAI;AAClB;AAOA,SAAS,eAAe,IAAa,OAAqB;AACxD,QAAM,SAAS,IAAI,eAAe,OAAO,GAAG,SAAS;AAAA,IACnD,KAAK,YAAY,EAAE;AAAA,IACnB,QAAQ,GAAG;AAAA,IACX,QAAQ,GAAG;AAAA,IACX,SAAS,GAAG;AAAA,IACZ,cAAc,MAAM,aAAa,EAAE;AAAA,EACrC,CAAC;AACD,KAAG,WAAW;AACd,OAAK,OAAO,IAAI;AAChB,OAAK,OAAO,KAAK,KAAK,MAAM;AAC1B,QAAI,YAAY,GAAI,MAAK,MAAM;AAAA,EACjC,CAAC;AACH;AASA,SAAS,eAAe,IAAa,QAA8B;AACjE,MAAI,WAAW;AACf,QAAM,SAAS,MAAY;AACzB,QAAI,SAAU;AACd,eAAW;AACX,OAAG,oBAAoB;AACvB,OAAG,oBAAoB;AACvB,UAAM,OAAO,qBAAqB,OAAO,OAAO,CAAC;AACjD,QAAI,YAAY,GAAI,MAAK,MAAM,CAAC;AAChC,YAAQ,OAAO,MAAM,IAAI,MAAM,QAAQ,KAAK,IAAI,CAAC;AAAA,EACnD;AACA,MAAI,GAAG,QAAQ,wBAAwB,OAAO;AAC5C,QAAI,WAAW;AACf,UAAM,WAAW,CAAC,WAAuC;AAEvD,UAAI,sBAAsB,MAAM,IAAI,KAAK,SAAU;AACnD,iBAAW;AACX,aAAO,OAAO;AACd,WAAK,QAAQ,KAAK,CAAC,OAAO,MAAM,MAAM,yBAAyB,CAAC,CAAC,EAAE,KAAK,MAAM;AAAA,IAChF;AACA,UAAM,QAAQ,aAAa,MAAY,SAAS,QAAQ,CAAC;AACzD,UAAM,SAAS,aAAa,MAAY,SAAS,SAAS,CAAC;AAC3D,YAAQ,GAAG,UAAU,KAAK;AAC1B,YAAQ,GAAG,WAAW,MAAM;AAC5B,OAAG,oBAAoB,MAAM;AAC3B,cAAQ,IAAI,UAAU,KAAK;AAC3B,cAAQ,IAAI,WAAW,MAAM;AAAA,IAC/B;AAAA,EACF;AACA,OAAK,OAAO,IAAI;AAChB,OAAK,OAAO,KAAK,KAAK,MAAM;AAC9B;AAOA,eAAe,KAAK,IAA4B;AAC9C,MAAI,GAAG,UAAU;AAEf,OAAG,SAAS;AACZ,mBAAe,IAAI,GAAG,QAAQ;AAC9B;AAAA,EACF;AACA,MAAI,CAAC,GAAG,YAAY;AAClB,UAAM,KAAK,MAAM,mBAAmB;AACpC,QAAI,YAAY,GAAI;AACpB,OAAG,aAAa;AAChB,OAAG,OAAO,MAAM,oCAAiC,eAAe,+BAA0B,EAAE,GAAG;AAAA,EACjG;AACA,MAAI,YAAY,GAAI;AACpB,KAAG,SAAS;AAKZ,MAAI,GAAG,QAAQ,mBAAmB,OAAO;AACvC,OAAG,UAAU,IAAI,eAAe,GAAG,YAAY,GAAG,MAAM;AACxD,SAAK,GAAG,QAAQ,MAAM;AACtB,OAAG,OAAQ,qBAAqB,GAAG,OAAO;AAAA,EAC5C;AAIA,KAAG,YAAY,IAAI,UAAU,GAAG,QAAS,EAAE,YAAY,uBAAuB,WAAW,KAAK,GAAG,GAAG,YAAY,GAAG,OAAO;AAC1H,KAAG,UAAU,MAAM;AAEnB,MAAI,GAAG,QAAQ,wBAAwB,OAAO;AAC5C,OAAG,oBAAoB,wBAAwB,GAAG,OAAO;AAAA,EAC3D;AAEA,MAAI,GAAG,QAAQ,SAAS,QAAS,aAAY,EAAE;AAAA,WACtC,GAAG,MAAO,gBAAe,IAAI,GAAG,KAAK;AAAA,MACzC,aAAY,EAAE,EAAE,MAAM;AAC7B;AAEA,SAAS,aAAa,IAAmB;AAEvC,MAAI,GAAG,cAAe;AAEtB,KAAG,gBAAgB;AACnB,iBAAe,MAAM;AACnB,OAAG,cAAc,KAAK,EAAE,EAAE,MAAM,WAAS,GAAG,OAAO,MAAM,2BAA2B,KAAK,CAAC;AAAA,EAC5F,CAAC;AACH;AAMA,SAAS,WAAW,IAA0B,MAAiB,SAAqB,SAAgC;AAClH,kBAAgB,SAAS,EAAE;AAC3B,MAAI,SAAS;AACX,UAAM,IAAI,MAAM,YAAY,EAAE,uJAA4I;AAAA,EAC5K;AACA,QAAM,SAAS,WAAW,QAAQ,SAAS,KAAK;AAChD,QAAM,eAA6B,EAAE,MAAM,SAAS,SAAS,kBAAkB,SAAS,MAAM,MAAM,EAAE;AAGtG,aAAW;AAGX,QAAM,KAAK,WAAW,IAAI,sBAAsB,SAAS,cAAc,MAAM,IAAI,cAAc,SAAS,cAAc,MAAM;AAC5H,MAAI,CAAC,GAAG,YAAY,SAAS,UAAU;AACrC,QAAI,QAAQ,mBAAmB,OAAW,IAAG,iBAAiB,QAAQ;AACtE,OAAG,QAAQ,aAAa,QAAQ,KAAK;AAAA,EACvC;AACA,YAAU;AACV,eAAa,EAAE;AACjB;AAMO,SAAS,SAAsC,SAAwB,UAA2B,CAAC,GAAS;AACjH,aAAW,YAAY,UAAU,SAAuB,OAAO;AACjE;AAGO,SAAS,MAAM,SAAqB,UAAwB,CAAC,GAAS;AAC3E,aAAW,SAAS,SAAS,SAAS,OAAqB;AAC7D;AAGO,SAAS,kBAA2C;AACzD,SAAO,mBAAmB,KAAK,SAAS,QAAQ,aAAa;AAC/D;AAEO,SAAS,eAAmC;AACjD,SAAO,SAAS;AAClB;AAGA,SAAS,cAAc,MAA8B;AACnD,SAAO,SAAS,UAAU,UAAU;AACtC;AAOA,SAAS,kBAAkB,IAAa,YAA4C,SAAiB,MAAqC;AACxI,QAAM,WAAW,gBAAgB;AACjC,MAAI,CAAC,UAAU;AACb,OAAG,OAAO,KAAK,gFAA+D;AAC9E,WAAO;AAAA,EACT;AACA,QAAM,WACJ,OAAO,eAAe,YAAY,CAAC,kBAAkB,UAAU,KAAK,WAAW,aAC3E,MAAM,WAAW,OAAO,EAAE,SAAS,WAAW,SAAS,aAAa,WAAW,YAAY,CAAC,IAC5F;AACN,SAAO,SAAS,IAAI,cAAc,IAAI,GAAG,SAAS,QAAQ;AAC5D;AAMO,SAAS,iBAAiB,OAAgB,MAAwC;AACvF,QAAM,KAAK;AACX,MAAI,CAAC,IAAI;AACP,QAAI,CAAC,iBAAiB;AACpB,wBAAkB;AAClB,cAAQ,KAAK,+FAA0F;AAAA,IACzG;AACA,WAAO;AAAA,EACT;AACA,MAAI;AACJ,MAAI,MAAM,YAAY;AACpB,UAAM,UAAU,iBAAiB,QAAQ,GAAG,MAAM,IAAI,KAAK,MAAM,OAAO,KAAK,OAAO,KAAK;AACzF,mBAAe,kBAAkB,IAAI,KAAK,YAAY,SAAS,KAAK,QAAQ,OAAO;AAAA,EACrF;AAEA,MAAI,CAAC,GAAG,QAAQ;AACd,OAAG,OAAO,MAAM,uDAAuD;AACvE,WAAO;AAAA,EACT;AAEA,QAAM,QAAQ,gBAAgB,GAAG;AACjC,QAAM,UAAU,QAAQ,EAAE,GAAG,MAAM,MAAM,EAAE,QAAQ,OAAO,GAAG,MAAM,KAAK,EAAE,IAAI;AAE9E,QAAM,WAAW,SAAS,eAAe,EAAE,KAAK,EAAE,IAAI,OAAO,aAAa,CAAC,YAAY,EAAE,EAAE,IAAI;AAC/F,SAAO,GAAG,OAAO,iBAAiB,OAAO,SAAS,QAAQ;AAC5D;AAOA,eAAsB,MAAM,YAAY,KAA0B;AAChE,QAAM,KAAK;AACX,MAAI,CAAC,GAAI,QAAO;AAChB,YAAU;AACV,QAAM,GAAG;AAGT,MAAI,GAAG,MAAO,OAAM,GAAG,MAAM,KAAK,CAAC;AACnC,KAAG,OAAO,KAAK;AACf,KAAG,UAAU,KAAK;AAClB,KAAG,UAAU,KAAK;AAElB,QAAM,OAAO,MAAM,GAAG,QAAQ,SAAS,SAAS;AAChD,MAAI,CAAC,MAAM;AACT,OAAG,OAAO,KAAK,GAAG,GAAG,QAAQ,WAAW,2CAAkC,SAAS,gCAA2B;AAG9G,UAAM,GAAG,QAAQ,sBAAsB,gFAA0E;AAAA,EACnH;AAEA,KAAG,WAAW,KAAK;AACnB,KAAG,oBAAoB;AACvB,KAAG,0BAA0B;AAC7B,QAAM,UAAU,GAAG,SAAS,MAAM,GAAG,OAAO,MAAM,SAAS,IAAI;AAC/D,SAAO,QAAQ;AACjB;;;AC5aA,IAAM,SAAS,oBAAI,IAAY;AAE/B,SAAS,eAAe,QAAsB;AAC5C,MAAI,OAAO,IAAI,MAAM,EAAG;AACxB,SAAO,IAAI,MAAM;AACjB,QAAM,UAAU,UAAU,MAAM;AAChC,QAAM,SAAiB,aAAa;AACpC,MAAI,OAAQ,QAAO,KAAK,OAAO;AAAA,MAC1B,SAAQ,KAAK,YAAY,OAAO,EAAE;AACzC;AAGA,IAAM,gBACJ,CAAC,UACD,CAAC,YAAqB,SAA0B;AAC9C,QAAM,EAAE,MAAM,OAAO,QAAQ,IAAI,aAAa,SAAS,IAAI;AAC3D,cAAY,OAAO,UAAU,GAAG,IAAI,yBAAyB,IAAI;AACnE;AACF,IAAM,cAAyB;AAAA,EAC7B,OAAO,cAAc,OAAO;AAAA,EAC5B,MAAM,cAAc,MAAM;AAAA,EAC1B,MAAM,cAAc,SAAS;AAAA,EAC7B,OAAO,cAAc,OAAO;AAAA,EAC5B,SAAS,cAAc,SAAS;AAClC;AAEA,IAAM,OAAO,MAAY;AAEzB,IAAM,mBAA6B;AAAA,EACjC,QAAQ;AAAA,EACR,WAAW,MAAM;AAAA,EACjB,WAAW,CAAC,OAAO,OAAO,GAAG;AAAA,EAC7B,cAAc;AAAA,EACd,SAAS;AAAA,EACT,eAAe;AAAA,EACf,WAAW,MAAM;AAAA;AAAA,EAEjB,SAAS,aAAW,YAAY,QAAQ,OAAO;AAAA;AAAA,EAE/C,YAAY,aAAW,YAAY,WAAW,OAAO;AAAA,EACrD,UAAU,aAAW,YAAY,SAAS,OAAO;AAAA,EACjD;AAAA,EACA,aAAa,MAAM,QAAQ,QAAQ,MAAS;AAAA,EAC5C,OAAO,MAAM,QAAQ,QAAQ;AAC/B;AACA,IAAM,gBAA0B;AAAA,EAC9B,KAAK;AAAA,EACL,WAAW;AAAA,EACX,QAAQ;AAAA,EACR,YAAY;AAAA,EACZ,MAAM,CAAC,MAAM,SAAS,UAAU,CAAC,MAAM,SAAS,MAAM,SAAS,SAAS,gBAAgB;AAC1F;AACA,IAAM,mBAAwC,EAAE,OAAO,MAAM,SAAS,MAAM,KAAK,MAAM,SAAS,GAAG,UAAU,KAAK;AAElH,IAAM,kBAAkB,MACtB,QAAQ,OAAO,IAAI,MAAM,gGAAuF,CAAC;AACnH,IAAM,gBAA0B;AAAA,EAC9B,MAAM,MAAM,CAAC;AAAA,EACb,KAAK,MAAM;AAAA,EACX,UAAU;AAAA,EACV,aAAa;AAAA,EACb,MAAM;AACR;AACA,IAAM,cAAc,IAAI,gBAAgB,EAAE;AAE1C,SAAS,QAAQ,QAAwC;AACvD,QAAM,WAAmB,gBAAgB;AACzC,MAAI,SAAU,QAAO,SAAS;AAC9B,iBAAe,MAAM;AACrB,SAAO;AACT;AAEA,SAAS,OAAmC,QAAW,UAAmD;AACxG,SAAO,EAAE,YAAY,MAAM,KAAK,MAAM,QAAQ,MAAM,IAAI,MAAM,KAAK,SAAS,EAAE;AAChF;AAEA,SAAS,OAAO,OAAoC;AAClD,SAAO,EAAE,YAAY,MAAM,UAAU,OAAO,MAAM;AACpD;AAEO,IAAM,SAAiB,OAAO,iBAAiB,CAAC,GAAa;AAAA;AAAA,EAElE,OAAO,OAAO,SAAS,MAAM,EAAE;AAAA,EAC/B,QAAQ,OAAO,UAAU,OAAO,CAAC,EAAE;AAAA,EACnC,KAAK,OAAO,OAAO,MAAM,WAAW;AAAA,EACpC,OAAO,OAAO,SAAS,MAAM,aAAa;AAAA,EAC1C,UAAU,OAAO,YAAY,MAAM,gBAAgB;AAAA,EACnD,OAAO,OAAO,SAAS,MAAM,aAAa;AAAA,EAC1C,QAAQ,OAAO,UAAU,MAAM,WAAW;AAAA,EAC1C,MAAM,OAAO,CAAI,MAAc,IAAe,YAAsC;AAClF,UAAM,MAAM,QAAQ,MAAM;AAC1B,QAAI,IAAK,QAAO,IAAI,KAAK,MAAM,IAAI,OAAO;AAE1C,WAAO,IAAI,YAAY,QAAW,iBAAiB,EAAE,KAAK,MAAM,IAAI,OAAO;AAAA,EAC7E,CAAC;AAAA,EACD,iBAAiB,OAAO,MAAY,QAAQ,iBAAiB,GAAG,gBAAgB,CAAC;AAAA,EACjF,OAAO,OAAO,CAAC,OAA8B,QAAQ,OAAO,GAAG,MAAM,EAAE,KAAK,MAAM,EAAE,CAAC;AAAA,EACrF,OAAO,OAAO,CAAC,cAAsC,QAAQ,OAAO,GAAG,MAAM,SAAS,KAAK,QAAQ,QAAQ,CAAC;AAAA,EAC5G,OAAO,OAAO,CAAI,IAAyC,YAAuC;AAEhG,UAAM,WAAmB,gBAAgB;AACzC,WAAO,WAAW,SAAS,QAAQ,MAAM,IAAI,OAAO,IAAI,iBAAiB,IAAI,OAAO;AAAA,EACtF,CAAC;AAAA;AAAA,EAED,UAAU,OAAO,CAAI,SAAwB,YAAoC;AAC/E,IAAQ,SAAS,SAAS,OAAO;AACjC,wBAAoB;AAAA,EACtB,CAAC;AAAA,EACD,OAAO,OAAO,CAAC,SAAqB,YAAiC;AACnE,IAAQ,MAAM,SAAS,OAAO;AAC9B,wBAAoB;AAAA,EACtB,CAAC;AAAA,EACD,OAAO,OAAO,CAAC,cAAiD,MAAM,SAAS,CAAC;AAAA,EAChF,kBAAkB,OAAO,CAAC,OAAgB,SAAmD,iBAAiB,OAAO,IAAI,CAAC;AAAA,EAC1H,OAAO,OAAO,KAAS;AAAA,EACvB,WAAW,OAAO,SAAa;AACjC,CAAC;AAMM,SAAS,sBAA4B;AAC1C,MAAK,WAAoC,WAAW,OAAQ;AAC5D,SAAO,eAAe,YAAY,UAAU,EAAE,OAAO,QAAQ,cAAc,MAAM,UAAU,MAAM,YAAY,MAAM,CAAC;AACtH;AAUO,IAAMC,YAAW,OAAO;AACxB,IAAMC,SAAQ,OAAO;AACrB,IAAMC,SAAQ,OAAO;AACrB,IAAMC,oBAAmB,OAAO;AAChC,IAAM,QAAQ,OAAO;AACrB,IAAMC,SAAQ,OAAO;AACrB,IAAMC,aAAY,OAAO;;;ACvLhC,WAAW;AAIX,IAAO,cAAQ;","names":["resolve","hostname","image","basePayload","image","field","resolve","method","resolve","image","sleep","resolve","resolve","resolve","DEFAULT_RETRIES","DEFAULT_RETRY_DELAY_MS","register","start","close","captureException","image","isFileRef"]}
|