/**
 * The SINGLE content-href authority for every embeddable surface — the
 * `ChatRuntime.composeContentUrl` seam. Page views (onboarding catalog/detail,
 * product releases) AND chat surfaces (entity cards, source chips, search
 * results) all resolve a content link through this one function, so a given
 * content type lands in the SAME place no matter where it's rendered.
 *
 * ## Why this exists
 *
 * Before unification there were two link builders: `composeContentUrl` (pages)
 * and `resolveSourceRowCTA` (chat), and only the former honored the embedder's
 * in-app routing config — so the same `product_release` soft-navigated in-app on
 * the releases page but opened OUT to the hub as a chat card. Now `resolveSource-
 * RowCTA` delegates its href to this seam, so one config (`hostedTypes` /
 * `overrides`) governs internal-vs-external for pages and chat alike.
 *
 * `makeComposeContentUrl` builds the embedder default from a small config: the
 * set of types THIS host serves in-app (→ relative href, soft-navigates) vs.
 * everything else (→ the canonical hub URL, opens out). The hub wires its own
 * composer (`composeContentUrlFromPlatforms` — cross-platform topology) to the
 * same seam. Pure + server-safe (no React, no browser APIs).
 *
 *   composeContentUrl: makeComposeContentUrl({
 *     hostedTypes: new Set(['onboarding_guide', 'product_release']),
 *     contentOrigin: VITE_HUB_ORIGIN,
 *   })
 */
/**
 * Type → in-app route suffix. The public-hostable subset of the hub's
 * `PUBLIC_URL_PATHS` (`lib/utils/content-url-builder.ts`); the hub keeps
 * its own copy, this is the embedder default and must stay in sync. (The
 * cross-repo boundary makes a shared import impossible; the lib test pins this
 * constant against a literal copy of itself, so it does NOT detect hub-side
 * drift — values match today and are kept aligned by hand.)
 */
export declare const DEFAULT_CONTENT_SUFFIXES: Record<string, string>;
/** Input to the unified content-href seam. ONE object covers both callers:
 *  page views pass `type` + `identifier` (the slug); chat rows pass `type` +
 *  `identifier` (the primary-key id) + `externalUrl` (the canonical hub URL,
 *  from which the slug is recovered for in-app routing). */
export interface ComposeContentUrlInput {
    /** The content's documentType (e.g. `'product_release'`, `'blog_post'`). */
    type: string;
    /** Content identifier. Page views pass the slug; chat rows pass the
     *  primary-key id (the slug is recovered from `externalUrl` when hosted). */
    identifier: string;
    /** Hydrated platform junction (page views). Unused by the embedder default
     *  — `hostedTypes` membership decides in-vs-out — but threaded for the hub
     *  composer's cross-platform topology. */
    platforms?: Array<{
        name?: string;
    }>;
    /** The canonical hub URL when the caller already has it (chat entity rows
     *  carry it from the RAG mapper). Hosted types relativize it to an in-app
     *  path; non-hosted types use it verbatim (authoritative). Absent for pages. */
    externalUrl?: string | null;
    /** Platform that owns `externalUrl` (chat rows). Passed through on the
     *  non-hosted branch. */
    targetPlatform?: string | null;
}
export interface ContentHrefOptions {
    /** Types THIS host serves in-app → relative href (soft-nav). Everything
     *  else resolves to the row's `externalUrl` / `contentOrigin` (opens out). */
    hostedTypes: ReadonlySet<string>;
    /** Hub origin for non-hosted types with no `externalUrl` (e.g.
     *  `https://openframe.app`). */
    contentOrigin: string;
    /** Per-type route suffix. Defaults to {@link DEFAULT_CONTENT_SUFFIXES}. */
    suffixes?: Record<string, string>;
    /** Per-type full override — wins over the suffix logic. Receives the same
     *  `identifier` the seam was called with. */
    overrides?: Record<string, (identifier: string) => {
        href: string;
        targetPlatform: string | null;
    }>;
}
/** The unified `composeContentUrl` seam shape on `ChatRuntime`. ALWAYS returns
 *  a tuple (never null) — the seam type is non-nullable and callers read
 *  `.href` unconditionally. */
export type ComposeContentUrl = (input: ComposeContentUrlInput) => {
    href: string;
    targetPlatform: string | null;
};
/**
 * Build the embedder's `composeContentUrl` for the unified seam.
 *
 * Resolution order (the merged rule used by BOTH page views and chat cards):
 *   1. `overrides[type]` — explicit per-type href.
 *   2. `hostedTypes.has(type)` → relative `/<suffix>/<slug>` (in-app, soft-nav).
 *      Chat rows carry the hub URL not the slug, so the slug is recovered from
 *      `externalUrl`; page views pass the slug as `identifier`.
 *   3. `externalUrl` present → use it verbatim (RAG-authoritative hub URL; the
 *      chat non-hosted case).
 *   4. else → `${contentOrigin}/<suffix>/<identifier>` (page-view non-hosted).
 *
 * In-vs-out is decided by `hostedTypes` membership — NOT platform equality,
 * since an embedder has a free-form `source`. The `platforms` arg is part of the
 * seam signature but unused here.
 */
export declare function makeComposeContentUrl(opts: ContentHrefOptions): ComposeContentUrl;
/**
 * Default href shape when `runtime.composeContentUrl` is NOT wired
 * (single-platform embedders without cross-platform topology). Shared by
 * every catalog/detail view that composes a content link (onboarding guides,
 * product releases, …) so the no-composer fallback has ONE source — both
 * views pass their `basePath`-derived shape through here.
 */
export declare function buildDefaultHref(basePath: string, slug: string): {
    href: string;
    targetPlatform: string | null;
};
/**
 * Resolve a content link via the host's `composeContentUrl` when wired, else the
 * same-origin `buildDefaultHref` fallback — the exact ternary every catalog/detail page
 * VIEW repeated. Centralizes the `composeContentUrl` input shape + the fallback in one
 * place so a future input-shape change lands once, not per view.
 */
export declare function resolveContentHref(composeContentUrl: ComposeContentUrl | undefined, args: {
    type: string;
    slug: string;
    basePath: string;
    platforms?: ComposeContentUrlInput['platforms'];
}): {
    href: string;
    targetPlatform: string | null;
};
//# sourceMappingURL=content-href.d.ts.map