/**
 * Local helpers for the github plugin — server-module bridge.
 * Mirrors the lazy-import pattern from plugins/publish/src/helpers.ts.
 */
export interface ServerModules {
    getDataDir: () => string;
    readConfig: () => any;
    saveConfig: (patch: Record<string, any>) => void;
    save: () => void;
    cancelDebouncedSave: () => void;
    getDocument: () => any;
    getTitle: () => string;
    getMetadata: () => Record<string, any>;
    getDocId: () => string;
    setMetadata: (updates: Record<string, any>) => void;
    bumpDocVersion: () => number;
    broadcastSyncStatus: (status: any) => void;
    broadcastMetadataChanged: (metadata: Record<string, any>) => void;
    broadcastDocumentsChanged: () => void;
    broadcastToast: (message: string, kind?: 'info' | 'error', durationMs?: number) => void;
    tiptapToMarkdown: (doc: any, title: string, metadata?: Record<string, any>) => string;
    validateBlogFrontmatter: (opts: {
        repoRoot: string;
        contentDir: string;
        frontmatter: string;
    }) => Promise<BlogFrontmatterValidation>;
}
/** Result of the pre-commit schema gate. Mirrors server/blog-schema-gate.ts. */
export interface BlogFrontmatterValidation {
    ok: boolean;
    skipped?: boolean;
    reason?: string;
    configPath?: string;
    collection?: string;
    issues?: Array<{
        field: string;
        code: string;
        message: string;
    }>;
    summary?: string;
}
export declare function getServerModules(): Promise<ServerModules>;
export interface PluginConfigField {
    type: 'string' | 'number' | 'boolean';
    required?: boolean;
    env?: string;
    description?: string;
}
export interface PluginRouteContext {
    app: import('express').Router;
    config: Record<string, string>;
    dataDir: string;
}
export interface PluginMcpTool {
    name: string;
    description: string;
    inputSchema: Record<string, unknown>;
    handler: (params: Record<string, unknown>) => Promise<unknown>;
}
export interface OpenWriterPlugin {
    name: string;
    version: string;
    description?: string;
    category?: 'writing' | 'social-media' | 'image-generation' | 'publishing' | 'productivity' | 'analytics';
    configSchema?: Record<string, PluginConfigField>;
    registerRoutes?(ctx: PluginRouteContext): void | Promise<void>;
    mcpTools?(config: Record<string, string>): PluginMcpTool[];
}
export interface BlogSite {
    id: string;
    label: string;
    owner: string;
    repo: string;
    branch: string;
    content_dir: string;
    image_dir: string;
    image_public_prefix: string;
    framework: 'astro' | 'next' | 'jekyll' | 'hugo' | 'unknown';
    /** Constant frontmatter fields applied to every post (e.g. layout, author, prerender). */
    frontmatter_defaults?: Record<string, any>;
    /**
     * Map openwriter blogContext key → site frontmatter key.
     * e.g. { date: "publishedDate" } for sites that use a non-standard date field.
     */
    frontmatter_field_map?: Record<string, string>;
    /**
     * Schema of frontmatter fields the site's posts use (from inspection).
     * Surfaced in the panel so users can see what the site expects.
     * Not used as a filter — only the defaults + blogContext determine output.
     */
    frontmatter_schema?: string[];
    /**
     * Public base URL of the site (e.g. "https://example.com"). Used by
     * post_to_blog to construct the live URL stamped on `blogContext.lastPublish.publishedUrl`
     * so the file-tree right-click menu can surface "View Post" after a publish.
     * inspect_blog_repo proposes this from `CNAME` / `public/CNAME` when present.
     */
    site_url?: string;
    /**
     * URL path pattern for a blog post, with `{slug}` as the placeholder.
     * Default: `/blog/{slug}/`. Used together with `site_url` to build the live URL.
     */
    blog_url_pattern?: string;
    /**
     * How image paths are written into frontmatter + body:
     *   "relative" — no leading slash (`images/og/x.png`); the site's template
     *                prepends the slash (e.g. Astro `<img src={`/${image}`}>`).
     *   "absolute" — leading slash (`/images/og/x.png`); value used verbatim.
     * Inferred by inspect_blog_repo from existing posts' image values. Absent ⇒
     * "absolute" — the legacy behavior the plugin always had before this field.
     * adr: adr/blog-image-contract.md
     */
    image_path_style?: 'relative' | 'absolute';
    /**
     * Filename template the published COVER image is copied under. Placeholders:
     *   `{slug}` — the post slug
     *   `{ext}`  — the source file's extension, no dot (preserved from the
     *              `/_images/` original)
     * Default `og-{slug}.{ext}`. Deterministic: same doc + same slug ⇒ same
     * cover filename on every republish (idempotent overwrite, no orphaned
     * cover files). Inferred by inspect_blog_repo from existing posts.
     * adr: adr/blog-image-contract.md
     */
    image_naming?: string;
}
export declare function listBlogSites(): Promise<BlogSite[]>;
export declare function writeBlogSites(sites: BlogSite[]): Promise<void>;
