/**
 * Blog publishing MCP tools — local git ops, no Worker, no PAT.
 *
 * Auth: piggybacks on the user's existing `gh auth login`.
 * Persistence: blogSites in plugins['@openwriter/plugin-github'].blogSites.
 */
import { type BlogSite, type PluginMcpTool } from './helpers.js';
/**
 * Derive the per-site image contract from sampled posts:
 *  - `image_field`        — which frontmatter key holds the cover
 *  - `image_path_style`   — do values carry a leading slash?
 *  - `image_public_prefix`— the dominant directory the images live under
 *                           (relative, no leading slash)
 *  - `image_naming`       — `og-{slug}` vs `{slug}` filename convention
 *                           (detected by the dominant basename shape)
 * Conservative: only the dominant local-path field is analyzed; full URLs
 * are ignored. Anything not confidently detected is left undefined so
 * post_to_blog falls back to its documented defaults.
 */
export declare function inferImageConventions(samples: Array<{
    fm: Record<string, string>;
    slug: string;
}>): {
    image_field?: string;
    image_path_style?: 'relative' | 'absolute';
    image_public_prefix?: string;
    image_naming?: string;
};
/** Site's effective path style. Absent ⇒ legacy "absolute". */
export declare function pathStyleOf(site: Pick<BlogSite, 'image_path_style'>): 'relative' | 'absolute';
/**
 * Public reference for one image file under the site's prefix, honoring the
 * site's path style. The prefix is normalized (leading + trailing slashes
 * stripped) so storage is style-agnostic — `style` alone decides the leading
 * slash, which makes the contract unambiguous regardless of how the prefix
 * was saved (`/images/og` vs `images/og` both behave identically).
 *   relative → "images/og/x.png"   absolute → "/images/og/x.png"
 */
export declare function imageRef(publicPrefix: string, file: string, style: 'relative' | 'absolute'): string;
/**
 * Resolve the deterministic cover filename from the site's naming template.
 *   `{slug}` → post slug
 *   `{ext}`  → source extension, no dot (preserved from the original)
 * A template carrying a literal extension and no `{ext}` placeholder
 * (e.g. `og-{slug}.png`) is respected as authored. Absent template ⇒
 * `og-{slug}.{ext}`.
 */
export declare function coverFilename(template: string | undefined, slug: string, sourceExt: string): string;
/**
 * Build the YAML frontmatter from blogContext + site defaults.
 *
 * Order of precedence (low → high):
 *   1. Site `frontmatter_defaults` (e.g. `layout`, `author`, `prerender`)
 *   2. Generated `title` (from document title — always present)
 *   3. blogContext fields (description, date, author, tags, slug, draft, coverImage)
 *
 * Field-name mapping: blogContext keys are renamed via `site.frontmatter_field_map`
 * before emit (e.g. `date` → `publishedDate` for Astro sites).
 *
 * Top-level openwriter metadata (status, enrichmentStale, tags-as-content-type,
 * etc.) is NEVER passed through. Frontmatter is built ONLY from blogContext +
 * defaults — this is the design contract from server/blog-routes.ts.
 */
export declare function buildFrontmatter(title: string, blogCtx: Record<string, any>, site: BlogSite, coverImagePath?: string): string;
export declare function blogTools(): PluginMcpTool[];
