/** * Single publish channel + module-level "current flow" stack. The * `@lensmcp/client-runtime` injected into the served HTML sets * `window.__LENSMCP_PUBLISH__` to a function that takes a partial event * and forwards it to the LensMCP bus (via WebSocket in dev, or via the * FrontMCP server transport in production). * * If the channel isn't installed we silently no-op — this keeps the * library safe to import from any React tree (tests, SSR, etc). */ import type { ReactPublishPayload } from './types.js'; export type PublishCategory = 'render' | 'state' | 'runtime' | 'network' | 'visual' | 'trace'; export interface FlowSpec { flowId: string; originType?: string; originNodeId?: string; causedByNodeId?: string; } export interface PublishEnvelope { source: 'react' | 'valtio' | 'client-runtime' | 'visual'; category: PublishCategory; severity?: 'debug' | 'info' | 'warning' | 'error'; title: string; message?: string; fingerprint?: string; /** Optional context overrides; auto-stamped flow context is merged underneath. */ context?: Partial<{ flowId: string; originType: string; originNodeId: string; causedByNodeId: string; route: string; url: string; }>; raw: ReactPublishPayload | Record; } type PublishFn = (event: PublishEnvelope) => void; declare global { var __LENSMCP_PUBLISH__: PublishFn | undefined; } export declare function extendFlowWindow(spec?: FlowSpec): void; /** The flow that owns work happening NOW: sync stack first, else the window. */ export declare function activeFlow(): FlowSpec | undefined; /** * Start a flow with no synchronous handler to wrap — page loads, timers, * websocket pushes. Opens the causality window (so the async work that * follows inherits the flow) and publishes the origin event that makes the * flow exist in the reducer. */ export declare function beginBackgroundFlow(origin: { originType: string; originNodeId?: string; }): FlowSpec; export declare function setPublisher(fn: PublishFn | undefined): void; /** * Push a flow onto the module-level stack for the duration of `fn`. Any * `publish()` calls inside `fn` (including transitively triggered * Valtio subscribers and React Profiler callbacks that fire synchronously) * will inherit the flow context. * * NB: only synchronous propagation. For async chains (`fetch().then`, * `setTimeout`, promises) the caller must re-enter the flow with * `runInFlow` at the continuation site. The Phase 6.5 carryover adds * automatic continuation tracking via an async-context shim. */ export declare function runInFlow(spec: FlowSpec, fn: () => T): T; export declare function currentFlow(): FlowSpec | undefined; /** * Wrap a React event handler so every call runs inside a fresh flow. * The flowId is generated per invocation; `originType` defaults to * `'user-click'`. Pass `originNodeId` from the component identity * (typically the `data-agent-component` value). * * The babel transform wraps `on*` JSX values blindly, so this must be * total: non-function values (e.g. `onClick={maybeUndefined}`) pass * through unchanged, and an already-flowed handler is returned as-is — * layered components forwarding the same prop would otherwise nest a * flow per layer and crash on the inner non-function (`handler is not * a function`). */ export declare function withFlow(handler: (...args: TArgs) => TResult, spec?: { originType?: string; originNodeId?: string; }): (...args: TArgs) => TResult; export declare function publish(env: PublishEnvelope): void; /** Test hook — only useful in unit tests / smokes. */ export declare function drainQueue(): PublishEnvelope[]; export {};