/**
 * displayName — the ONE rule for a tool's `displayName` (the app's own words
 * for what a call of the tool does, read by a person), and the ONE way the
 * library names a set of calls in those words: the declared ones named, the
 * rest counted.
 *
 * Pattern: two pure functions and one small reader, no state.
 * Role:    Leaf. Asked for the RULE by `tools/tools.ts` · `defineTool` and by
 *          the registration funnel (`core/agent/buildToolRegistry.ts`), and for
 *          the NAMING by the two texts the library appends after an answer —
 *          the standing line (`core/agent/assessment/compose.ts`) and the
 *          limits block (`semantics/coverage/answer.ts`). Those two cannot
 *          import each other, so the naming lives here and they cannot name
 *          the same calls in two different ways.
 * Emits:   N/A.
 *
 * ## Why only the app's words
 *
 * A tool's registered name is the MODEL's vocabulary (`load_attachment`), and
 * an app may forbid showing it to the people it serves. This module never
 * prints it: a call is named only by the words its tool declared, and a call
 * whose tool declared none is counted ("and 1 other call"), never named. A
 * caller that gets `undefined` back says what it always said. Not every
 * surface asks this module yet — the time layer's limits lines and the
 * answer account's rows still print the registered name (a known follow-up).
 *
 * ## Why the plain-line rule
 *
 * The words reach a person verbatim, after an answer, so they are held to the
 * rule every declared label a report prints is held to (`lib/plainLine.ts` ·
 * `plainLineProblem`: no control, line or paragraph separator, or invisible
 * format character — a bidi override would reverse what the person reads),
 * judged BEFORE the length, and capped at the 60 characters a skill's `title`
 * and an account label are capped at.
 */
/** The longest display name a person reads — the cap every declared label a report prints has. */
export declare const MAX_DISPLAY_NAME_CHARS = 60;
/**
 * At most this many declared names in one phrase; any further call is counted
 * with the calls whose tools declared none. A line for a person, not a list.
 */
export declare const MAX_NAMED_CALLS = 3;
/**
 * Why `value` is not a display name, or `undefined` when it is — judged on the
 * trimmed text (the text a person would read). `label` names the field in the
 * sentence, so a refusal says where it was written.
 */
export declare function displayNameProblem(label: string, value: unknown): string | undefined;
/**
 * The display name a person may read — trimmed — or `undefined`. A value the
 * rule refuses is never printed: a tool assembled by hand, or served by a
 * ToolProvider after the agent was built, is read through this too.
 */
export declare function readDisplayName(value: unknown): string | undefined;
/**
 * The calls, named in the app's words — each distinct declared name once, in
 * the calls' order, at most {@link MAX_NAMED_CALLS}; every other call counted,
 * with `alsoUnnamed` (calls the record does not name at all). `calls` holds one
 * entry per CALL (the caller has already said each call once), each with its
 * tool's registered name — the key a declared name is looked up by, never
 * printed:
 *
 * - `loading the attached data`
 * - `loading the attached data and searching the catalog`
 * - `loading the attached data and 1 other call`
 *
 * `undefined` when no call's tool declared a name: the caller then says what
 * it always said — the registered name is never the fallback.
 *
 * @example
 * ```ts
 * namedCalls(
 *   [{ toolCallId: 'c1', toolName: 'load_attachment' }, { toolCallId: 'c2', toolName: 'list_runs' }],
 *   0,
 *   (tool) => (tool === 'load_attachment' ? 'loading the attached data' : undefined),
 * ); // 'loading the attached data and 1 other call'
 * ```
 */
export declare function namedCalls(calls: readonly {
    readonly toolName: string;
}[], alsoUnnamed: number, displayNameOf: (toolName: string) => string | undefined): string | undefined;
//# sourceMappingURL=displayName.d.ts.map