import type { RunEvent, RunResult } from "../engine/types.ts"; import { type RunBlockedPayload, type WorkflowEventPayload } from "./telemetry-events.ts"; import type { RunStore } from "./types.ts"; /** How an event leaves this package. Structurally the harness bus's `emit` — see the module header. */ export type PublishTelemetry = (channel: string, data: unknown) => void; export interface TelemetryOptions { /** Injected so a test can freeze the one timestamp the log cannot supply (see {@link TelemetryMapper.blocked}). */ readonly now?: () => Date; /** Where the single self-disabling warning goes. Default: stderr, tagged. */ readonly warn?: (message: string) => void; } /** * The pure half: `RunEvent` in, telemetry event out, plus the small amount of per-run state a * self-contained event needs (the run's name, and the start timestamps durations are measured from). * * Stateful but deterministic — no clock, no I/O — so the whole translation is unit-testable by feeding * it a sequence of events. */ export interface TelemetryMapper { /** Translate one event, or return `undefined` for the ones this iteration does not map. */ observe(event: RunEvent): WorkflowEventPayload | undefined; /** * Learn from a log read off disk WITHOUT publishing any of it: those events were already reported by * whichever invocation wrote them. This is how a resumed run still knows its workflow name and its * original start time — neither of which `run-resumed` carries. * * Folding a log that overlaps events already observed live is harmless: the fold is idempotent over * any prefix of the same log. */ seed(events: readonly RunEvent[]): void; /** * Produce a `run_blocked` payload for a `blocked` result; `undefined` for any other status. * * Blocking is the one run state with no `RunEvent` behind it — it is the absence of a terminal event — * so it is observed where a `RunResult` is, and its timestamp is the only one in the contract that * comes from a clock rather than from the log. */ blocked(result: RunResult): RunBlockedPayload | undefined; /** Drop a run's state (its log is gone, spec §6.5). */ forget(runId: string): void; } /** A `RunStore` that also publishes what passes through it. */ export interface TelemetryStore extends RunStore { /** * Report one execution's outcome (`runGuarded`'s return). Only a `blocked` one publishes anything — * every terminal status already arrived as an event through {@link RunStore.appendEvent}. */ observeResult(result: RunResult): void; } export declare function createTelemetryMapper(options?: TelemetryOptions): TelemetryMapper; /** * Wrap a store so everything appended through it is also published (spec R5/R6). * * The decoration is total — all four methods forward — and only two of them do anything extra: * `appendEvent` publishes after the write, and `loadEvents` lets the mapper learn from history it must * not re-publish. */ export declare function withTelemetry(store: RunStore, publish: PublishTelemetry, options?: TelemetryOptions): TelemetryStore; //# sourceMappingURL=telemetry-bridge.d.ts.map