import type { ProtocolNamespace } from "./protocol-table.js";
/** The provider's tool-name pattern is `^[a-zA-Z0-9_-]{1,64}$` — the limit applies to the ASSEMBLED name,
 *  not to its segments (design/116 W5-5, CC 2.1.187 parity `buildMcpToolName`). */
export declare const TOOL_NAME_MAX_CHARS = 64;
/** Reserved for the tool segment when budgeting the peer segment: a peer kept at the full name budget
 *  overflows the assembled name on its own (prefix + 64 + separator = 71 > 64), which is how the tool
 *  segment used to be handed a NEGATIVE budget. A tool name shorter than this is not recognizable. */
export declare const MINTED_TOOL_SEGMENT_MIN_CHARS = 16;
/**
 * design/116 W5-5 (CC 2.1.187 parity) — normalize a peer/tool segment to the API tool-name charset by
 * replacing every other character with `_`. CC does exactly this on BOTH segments when composing
 * `mcp__<server>__<tool>` (services/mcp/normalization.ts `normalizeNameForMCP` + mcpStringUtils.ts
 * `buildMcpToolName`), so a peer advertising a dotted/spaced/unicode name can't mint a name the provider
 * rejects. NOTE: only the MODEL-FACING namespaced name is normalized — the raw remote name still goes on
 * the wire and still keys the caller-facing maps (`allowTools`/`toolAxes`). The collision property is
 * inherent (two remote names that normalize to the same string mint the same string; CC accepts this at
 * the same layer) — what this engine does NOT accept is two PEERS colliding, because a peer prefix is a
 * live domain key here (the refresh splice). That case is decided by
 * {@link findNamespacePrefixCollision} and refused at the mount, loudly; the mint stays total.
 *
 * The pattern this enforces is `{1,64}`, and only the charset half was
 * enforced. Both other halves matter for the same reason the charset does — an over-long or empty segment
 * produces a name the provider rejects, which 400s the WHOLE model request, the exact failure the intake
 * gate exists to contain ("a single misconfigured server never bricks the whole task").
 */
export declare function normalizeNameSegment(name: string): string;
/** Force a normalized segment into `{1,max}`, keeping long names distinct via a stable digest. */
export declare function clampNameSegment(seg: string, max?: number): string;
/**
 * The registered-name prefix for `peer` in `ns` — i.e. the set `name.startsWith(prefix)` that a consumer
 * uses as its splice domain when swapping one peer's tools wholesale.
 *
 * The peer segment is kept as long as the assembled name allows (it is how an operator recognizes which
 * peer a tool came from) and absorbs the clamp, digest-suffixed, when it does not fit.
 *
 * NOT `ns.makeName`: that leg REFUSES a peer carrying the separator, while this pipeline SANITIZES its
 * inputs (the peer name is deployment/remote data, not a caller-authored identifier) and must not turn a
 * long or exotic peer name into a materialization failure. SANITIZE, however, means the sanitized result
 * must be sound: {@link settlePeerSegment} owes the same round-trip guarantee `makeName` gets by refusing
 * (ticket #10), and the property test holds the two legs to the identical law.
 */
export declare function mintNamespacePrefix(ns: ProtocolNamespace, peer: string): string;
/**
 * The first pair of peers in `peers` that mint the SAME {@link mintNamespacePrefix} — i.e. that would
 * register into one indistinguishable namespace domain — or `undefined` when every peer owns its own.
 *
 * Two spellings collide whenever charset normalization, the length clamp or the separator fold maps
 * them together: `"prod.db"` and `"prod_db"` both mint `mcp__prod_db__`, and the same name listed twice
 * collides trivially. The mint itself cannot refuse (its input is deployment/remote data and a dotted
 * name must not become a materialization failure — see {@link normalizeNameSegment}), so the refusal
 * belongs to the MOUNT, which is the layer that knows the whole peer list. This function is that
 * layer's decision procedure: pure name arithmetic, decidable before any I/O.
 *
 * Why a collision cannot be tolerated downstream: the prefix IS the domain key. A refresh splices
 * `name.startsWith(prefix)` out and re-inserts only the refreshed peer's listing, so refreshing one of
 * two colliding peers silently unmounts the other's tools; equal tool names additionally shadow each
 * other last-write-wins in the harness map. Both failures are invisible at the moment they happen.
 */
export declare function findNamespacePrefixCollision(ns: ProtocolNamespace, peers: readonly string[]): {
    prefix: string;
    peers: [string, string];
} | undefined;
/**
 * The full registered name for `(peer, tool)` in `ns`. Always starts with {@link mintNamespacePrefix}'s
 * answer for the same peer (the invariant ticket #9's pins hold), and never exceeds
 * {@link TOOL_NAME_MAX_CHARS}: whatever the peer segment leaves over is the tool segment's budget.
 */
export declare function mintNamespacedToolName(ns: ProtocolNamespace, peer: string, tool: string): string;
