import type { FlameNode, HotFrame } from './types.js';
/**
 * The slice of `inspector.Session` we depend on. Declared structurally so the
 * profiler can be unit-tested with a fake and — crucially — so the real
 * `node:inspector` module is NEVER imported at module load. It is required
 * lazily by {@link defaultSessionFactory} ONLY when a capture actually starts.
 */
export interface InspectorSessionLike {
    connect(): void;
    disconnect(): void;
    post(method: string, paramsOrCallback?: unknown | ((err: Error | null, result?: unknown) => void), callback?: (err: Error | null, result?: unknown) => void): void;
}
export type SessionFactory = () => InspectorSessionLike;
export interface CpuProfilerOptions {
    /**
     * V8 sampling interval in microseconds. Lower = finer-grained but more
     * overhead. V8's default is 1000µs (1ms); we keep that default.
     */
    samplingIntervalMicros?: number;
}
export interface CpuProfilerResult {
    tree: FlameNode;
    durationMs: number;
    sampleCount: number;
    hot: HotFrame[];
}
/**
 * Wraps a V8 CPU profiling session over the inspector protocol. A single
 * profiler instance captures ONE profile at a time (`start` then `stop`).
 *
 * OVERHEAD GUARANTEE: constructing a profiler does no work and creates no
 * session. The inspector session is created (and `node:inspector` is required)
 * only inside `start()`. When profiling is disabled the controller never
 * constructs one, so there is provably zero inspector activity.
 */
export declare class CpuProfiler {
    private readonly sessionFactory;
    private session;
    private running;
    private readonly intervalMicros;
    constructor(sessionFactory?: SessionFactory, options?: CpuProfilerOptions);
    get isRunning(): boolean;
    /** Begin a CPU profile. No-op if one is already running. */
    start(): Promise<void>;
    /**
     * Stop the profile and aggregate it into a flame tree. Returns `null` when no
     * profile is running. Always disconnects the session, even on error.
     */
    stop(): Promise<CpuProfilerResult | null>;
    private postAsync;
}
/**
 * Lazily require `node:inspector` and return a fresh Session. Kept out of the
 * module's import graph so that importing this file (or the whole package) does
 * NOT load the inspector binding — that only happens the first time a capture
 * starts, i.e. only when profiling is enabled AND a request is sampled.
 */
export declare function defaultSessionFactory(): InspectorSessionLike;
//# sourceMappingURL=cpu-profiler.d.ts.map