/**
 * Asset-embed extraction + diffing.
 *
 * Entry bodies reference binary assets two ways:
 *   - Obsidian-style transclusion embeds:  ![[Foo.png]]  /  ![[Foo.png|alt]]
 *   - Standard markdown images:            ![alt](/api/assets/asset/<id>/<file>)
 *
 * Asset *binaries* live outside git (the workspace `.studiograph/assets/`
 * tree for the local backend, or Cloudflare R2), so git history can only ever
 * recover the *reference* — the embed text in the body, not the bytes. These
 * helpers let the write path detect when a whole-body rewrite would drop a
 * reference the prior body had, and let the history tools report which embeds
 * exist at a given revision.
 *
 * Callers pass the markdown body (post-frontmatter). Embed syntax is a body
 * construct; frontmatter is not scanned.
 */
/**
 * Extract every embedded asset reference from a markdown body,
 * de-duplicated, transclusions first then markdown images. Returns the raw
 * target (transclusion target or image URL) so callers can compare
 * references across revisions and surface them to users/agents.
 */
export declare function extractAssetEmbeds(body: string): string[];
/**
 * The canonical, render-safe markdown embed for an asset: `![filename](url)`.
 * This is exactly what the editor inserts on drop/paste
 * (web FormattingPalette), so any agent-placed embed that uses this form is
 * guaranteed to render. Agents must NOT invent `![[filename]]` transclusion
 * placeholders — those don't resolve to a stored asset and render as dead text.
 */
export declare function assetEmbed(filename: string, url: string): string;
/**
 * Derive a human display name from a filename: drop the extension, turn
 * `_`/`-` runs into spaces, and Title-Case each word
 * (`haneya_sake.jpg` → `Haneya Sake`). Shared by every free-standing-asset
 * creation path (manager upload, presign finalize, chat-image promote) so the
 * label rule never drifts. Returns "" for an extension-only name; callers add
 * their own fallback (filename / assetId).
 */
export declare function deriveAssetDisplayName(filename: string): string;
/**
 * References present in `before` but absent from `after` — i.e. embeds a
 * body rewrite would drop. Set semantics on the CANONICALIZED reference
 * (decoded asset identity — see {@link canonicalAssetRef}); the returned
 * strings are the original `before` refs so messages show what the body said.
 */
export declare function droppedAssetEmbeds(before: string, after: string): string[];
/**
 * Strip a leading YAML frontmatter block (`---\n…\n---`) so embed extraction
 * runs against the body only. Returns the input unchanged when there is no
 * frontmatter. Mirrors the lightweight frontmatter sniff the history tools
 * already use, avoiding a full markdown parse for a read-only report.
 */
export declare function stripFrontmatter(fileContent: string): string;
export interface LegacyAssetRef {
    /** Full matched URL, e.g. /api/assets/note/critique/172-shot.png */
    url: string;
    /** Storage key {type}/{id}/{filename} the blob lives at today. */
    oldKey: string;
    type: string;
    id: string;
    filename: string;
}
/** Every legacy `/api/assets/{type}/{id}/{filename}` reference in a file,
 *  de-duplicated by URL. Pass the RAW file (frontmatter + body). */
export declare function extractLegacyAssetUrls(fileContent: string): LegacyAssetRef[];
/**
 * Rewrite every immutable `/api/assets/{assetId}/{filename}` reference in a
 * body via `replace(assetId, filename)`. Legacy three-segment URLs and
 * `![[transclusions]]` are left untouched. Used by the public share read to
 * point embedded images at the token-scoped `/api/share/{token}/asset/...`
 * surface without leaking the authed `/api/assets` URLs to guests.
 *
 * D5 identity contract: `filename` reaches the callback DECODED (the raw
 * stored name). A callback that emits a URL must percent-encode the segment
 * it splices (`encodeAssetFilename`) — emitting the raw name breaks markdown/
 * HTML URL parsing on spaces and parens.
 */
export declare function rewriteImmutableAssetUrls(body: string, replace: (assetId: string, filename: string) => string): string;
/**
 * Every immutable `/api/assets/{assetId}/{filename}` reference embedded in a
 * body, de-duplicated by `{assetId}/{filename}`. Uses the SAME grammar as
 * `rewriteImmutableAssetUrls` (the public share read rewrites exactly these
 * URLs), so the public asset handler can scope itself to the assets a shared
 * entry actually embeds — not every asset that merely shares its repo. Legacy
 * three-segment URLs and `![[transclusions]]` are intentionally ignored, the
 * same way the rewrite leaves them untouched.
 *
 * D5 identity contract: `filename` is the DECODED raw stored name, directly
 * comparable to `assets.db.filename` and to a Fastify-decoded route param —
 * comparing the encoded URL segment against either was the latent
 * special-char 404 on public shares (share-api embedded-asset check).
 */
export declare function extractImmutableAssetRefs(body: string): Array<{
    assetId: string;
    filename: string;
}>;
/**
 * Every immutable assetId an entity embeds — in its markdown `body` OR any
 * string frontmatter value (e.g. a `thumbnail` / `link` url, or an array of
 * urls). De-duplicated. This is the single definition of "what assets does this
 * entry embed", shared by the caption fold (`VectorService.resolveEmbeddedCaptions`,
 * which reads each embedded image's caption into the entry's search text) and
 * the caption sweep's embedder re-index — so the two never disagree on coverage.
 * A cheap substring pre-check skips the regex for the common no-asset entry.
 */
export declare function embeddedAssetIds(body: string, frontmatter: Record<string, unknown>): Set<string>;
