/**
 * Artifact reading primitives shared by every backend and every reader.
 *
 * Two readers exist — the model's `retrieve_context({ artifactId })` and the
 * host's `readArtifact()` — and two shipped backends. Everything they agree
 * on lives here so it is agreed on exactly once:
 *
 *  - `readArtifactWindow` is THE paged read. It asks a backend for a window
 *    when the backend can produce one (`retrieveRange`), and otherwise reads
 *    the whole payload and slices. A reader never has to know which.
 *  - `searchArtifactContent` is the literal search over an artifact. It
 *    returns bounded snippets with character offsets, never whole lines:
 *    an MCP artifact is usually one compact JSON line, so "the matching line"
 *    would be the payload the search was meant to avoid reading.
 *  - `isSafeArtifactId` is the shape check every backend applies before an
 *    id reaches a path or a key. Ids arrive from the model.
 *
 * @module artifacts/artifactReader
 */
import type { ArtifactPageRequest, ArtifactSearchResult, ArtifactStore, ArtifactWindow } from "../types/index.js";
/** Characters used for the quick preview embedded in surrogate results. */
export declare const DEFAULT_PREVIEW_CHARS = 500;
/** Matches returned by one artifact search; the rest are counted, not sent. */
export declare const MAX_ARTIFACT_SEARCH_MATCHES = 50;
/** Longest search pattern accepted — bounds the work per call. */
export declare const MAX_SEARCH_PATTERN_CHARS = 200;
/** True when `id` is shaped like something a backend may look up. */
export declare function isSafeArtifactId(id: string): boolean;
/** Head slice of a payload for surrogate headers, ellipsised when cut. */
export declare function generateArtifactPreview(payload: string, chars?: number): string;
/** Cut one window out of a payload already in memory. */
export declare function sliceArtifactWindow(content: string, page?: ArtifactPageRequest): ArtifactWindow;
/**
 * Read one window of an artifact through whatever the backend supports.
 *
 * With a `page` and a backend that implements `retrieveRange`, only the
 * window crosses the wire. Otherwise the whole payload is fetched and cut
 * here. Without a `page` the whole payload is always fetched — a caller that
 * omits the window is asking for the artifact.
 *
 * Returns `null` when the id is unknown, unsafe, or expired.
 */
export declare function readArtifactWindow(store: ArtifactStore, id: string, page?: ArtifactPageRequest): Promise<ArtifactWindow | null>;
/**
 * Why a search pattern cannot be used, or `undefined` when it can.
 *
 * Empty would match at every position; over-long bounds the scan. Both are
 * reported to the model rather than silently ignored — the whole point of
 * the artifact search is that "search did not happen" is never invisible.
 */
export declare function validateSearchPattern(pattern: string): string | undefined;
/**
 * Literal, case-insensitive search over an artifact.
 *
 * Regex metacharacters in `pattern` are matched literally — the model's
 * input is never compiled as a regex, so it cannot be made catastrophic.
 * Each hit carries the character `offset` of the match (what to pass back as
 * `offset` for a targeted read), its 1-based line, and a bounded snippet.
 *
 * Scanning starts at `from`, so a caller can walk a long payload by passing
 * `nextSearchOffset` back in. Every match after `from` is counted in
 * `totalMatches`; only the first `maxMatches` are returned.
 *
 * `pattern` must already have passed {@link validateSearchPattern}.
 */
export declare function searchArtifactContent(content: string, pattern: string, options?: {
    from?: number;
    maxMatches?: number;
}): ArtifactSearchResult;
