/**
 * Output shaping for MCP tool results.
 *
 * MCP tool results land directly in the AI client's context window, so we keep
 * them compact and curated. Field names below match the live BFF payloads
 * (catalog router mounted as `catalog`, security as `security`):
 *   - search items wrap a cross-store cluster: `{ id, slug, snapshots[], availableStores, security }`
 *     where the human-facing fields (name, rating, users, store) live on each snapshot.
 *   - `getExtensionById` returns the cluster with aggregated `latest*` fields.
 *   - `getSecurityData` returns `{ riskAssessment, scanExecution, findings:{ total, groupTotal, bySeverity } }`.
 *   - `getRiskSummary` is already a compact summary (or null if never scanned).
 *
 * `compact()` is a defensive fallback that bounds array length / string length /
 * depth so a tool can never blow up the context even if a shape drifts.
 */
interface CompactOpts {
    maxArray?: number;
    maxString?: number;
    maxDepth?: number;
}
/** Recursively bound a value's size: cap arrays, truncate strings, limit depth. */
export declare function compact(value: unknown, opts?: CompactOpts, depth?: number): unknown;
type Obj = Record<string, unknown>;
/** Compact a search result down to a count + curated items. */
export declare function shapeSearch(result: unknown, limit: number): Obj;
/** Curate a single extension detail (`getExtensionById`). */
export declare function shapeExtension(result: unknown): unknown;
/**
 * Curate a page of store user reviews (`get_reviews`). Passes through the
 * keyset `nextCursor` so the model can page, a `count` for quick sizing, and the
 * store-level `aggregate` (rating / count / snapshot date + reviews link) — the
 * bare facts that stay public even for Chrome.
 */
export declare function shapeReviews(result: unknown, limit: number): Obj;
/**
 * Curate the install-dialog preview — the consolidated permission prompt the
 * browser shows at install (computed server-side by catalog-api from the
 * manifest's required permissions; source of truth: shared-types/permission-warnings.ts).
 * Reduces each browser's warnings to their human-readable lines for terseness.
 */
export declare function shapeInstallDialog(preview: unknown): Obj | undefined;
/** Capability phrase for a scanner key; unknown keys get a generic phrase, never the raw name. */
export declare function scannerPhrase(scanner: unknown): string | undefined;
/**
 * Some rule ids carry the scanner key as a namespace (`jstap:document-cookie-access`);
 * the same string is often the finding title. Drop a known scanner prefix so the
 * tool name never leaks through the rule or title either.
 */
export declare function stripScannerPrefix(value: unknown): unknown;
/** Curate the security view: risk summary + grouped findings (top N per severity). */
export declare function shapeSecurity(security: unknown, riskSummary: unknown, installDialogPreview?: unknown): Obj;
/**
 * Shape one row of `security.getSecuritySummaryBatch` for the risk-by-store-id
 * tool.
 *
 * Two things this deliberately does NOT hide:
 *  - `scoredStore` / `scoredVariantId` — the batch resolves a store id through
 *    its cross-store cluster to the record the extension page renders, and
 *    cluster members are scanned independently (the same extension scored 78.55
 *    HIGH on its Chrome record and 80.47 CRITICAL on its Edge one). An agent
 *    reporting a number to a developer must be able to say which listing it
 *    describes.
 *  - a `null` score — "not scanned" is an expected state, not an error, and
 *    must never be flattened into a reassuring 100.
 *
 * `catalogUrl` uses the CANONICAL id so the link lands on the page the score
 * came from without a redirect hop.
 */
export declare function shapeStoreRiskRow(row: unknown): Obj;
/**
 * Shape a whole risk-by-store-id batch, and say which requested ids the catalog
 * had no listing for — an agent that cannot tell "safe" from "unknown" will
 * report the wrong thing.
 */
export declare function shapeStoreRiskBatch(rows: unknown, requested: Array<{
    storeId: string;
    store: string;
}>): Obj;
/** Facet groups `market_overview` can return, selectable via its `facets` argument. */
export declare const MARKET_FACETS: readonly ["stats", "stores", "categories", "extended", "questionnaire", "downloads"];
export type MarketFacet = (typeof MARKET_FACETS)[number];
/** Default number of entries kept per open-ended facet list (categories, permissions, sites). */
export declare const DEFAULT_MARKET_TOP_N = 10;
export declare const MAX_MARKET_TOP_N = 100;
export interface MarketOverviewInput {
    scope: 'search' | 'catalog-wide';
    stats?: unknown;
    /** Raw facets as the BFF returns them (search facets, or the catalog-wide assembly). */
    facets?: unknown;
    note?: string;
}
export interface MarketShapeOpts {
    facets?: readonly string[];
    topN?: number;
}
/**
 * Trim a market_overview payload for the model's context: pick the requested
 * facet groups (default: all), cut open-ended lists to the `topN` largest
 * entries, and reduce category nodes to name/slug/count. Counts are passed
 * through unchanged — this shapes the response, it does not recompute data.
 * A `truncated` map says how many entries each trimmed list dropped, so the
 * caller knows when a larger `top_n` would reveal more.
 */
export declare function shapeMarketOverview(input: MarketOverviewInput, opts?: MarketShapeOpts): Obj;
export {};
//# sourceMappingURL=shape.d.ts.map