import { SkillDetailDataPayload, SkillSummaryPayload } from '../aiCfoViewPayload'; import { Skill, SkillDetail, SkillVisibility } from '../aiCfoViewState'; /** * A wire string narrowed to {@link SkillVisibility}, or null. * * A converter rather than passing the raw string through, because `Skill.visibility` is a * union on the state type and this is the boundary where an unvalidated payload becomes * it — the repo's rule about explicit converters at scalar boundaries instead of a bare * cast. * * Unrecognised maps to NULL, not to `'private'`. Null already means "does not apply" for a * Zeni default, and consumers show no audience badge for it — so an unknown tier renders * as no badge. Defaulting to `'private'` would instead label a skill the whole tenant can * run as author-only, which is a confident lie rather than a visible gap. */ export declare const toSkillVisibility: (raw: string | null | undefined) => SkillVisibility | null; /** * What the version-body read needs, and nothing more. * * A `Pick` of the payload rather than a type of its own: `SkillDetailDataPayload` now * marks the three unchecked fields optional itself, the same way `SkillSummaryPayload` * does, so there is one idiom for "this endpoint is not schema-validated" instead of two. */ type PromptBody = Pick; /** * Everything about a skill summary EXCEPT `exampleHints`, which no shared mapper can * honestly supply. * * Only the LIST route returns `parameter_hints`; the detail and write routes do not. A * shared mapper hardcoding `exampleHints: []` would put a "try: …" line under a skill * that has hints, or drop them from the menu — so the field is `Omit`ted and each caller * spreads in what its own route actually knows. * * Returning `Omit` rather than duplicating the mapper is what * makes a new `Skill` field land in one place: this function stops compiling until the * field is mapped, and both callers inherit it. The previous shape — two full copies — * is how `isMine` was nearly added to only one of them, which would have silently * withheld the edit and delete controls on whichever surface was missed. */ export declare const toBaseSkill: (payload: SkillSummaryPayload) => Omit; /** * Whether a 2xx body carries a prompt. * * Narrows to {@link PromptBody} and NOT to the whole payload, because the only consumer — * the version-body read — dereferences `instructions` and nothing else. Asserting the * whole shape here would claim `skill` was checked when it was not, and tying the read to * it would fail a response whose prompt was fine and whose `skill` block was malformed, * which is exactly what happened when this was one predicate instead of two. * * Takes `unknown`: the input is an unvalidated network body, and typing the parameter as * the payload interface would assume the very thing being checked. */ export declare const hasPromptBody: (data: unknown) => data is PromptBody; /** * Whether a 2xx body can build a whole {@link SkillDetail}. * * Narrows to the payload type itself, which is now truthful: the two fields this checks * are the two the interface still declares required, and the other three are optional * there. Stricter than {@link hasPromptBody} by exactly one field. Four epics read this shape * and each used to guard it differently — `data != null`, `data?.skill != null`, and a * real `instructions` check — so one malformed response became a failure in one place, an * empty prompt in another, and `undefined` in a third. */ export declare const isSkillDetailPayload: (data: unknown) => data is SkillDetailDataPayload; /** * The detail payload every write route answers with. * * Shared because three epics need it — save, visibility, and the detail read — and a * fourth copy is how one of them quietly stops carrying a field the others do. * * The coercions are not defensive habit; the payload type makes them mandatory — the * three optional fields cannot be assigned to a non-optional `SkillDetail` without one. * Which fields get coerced and which do not is the deliberate part: * * - `instructions` is load-bearing and already proven, so it passes through. Defaulting a * missing prompt to `''` is the one thing this module exists to prevent: the user * cannot tell an empty prompt from a skill that has one, and may save over the real * thing. * - `instructionsCharCount` falls back to the prompt's own length, NOT to 0. A 12,000 * character prompt displayed as "0 characters" is a lie the user can see, and the * prompt is right here to measure. Approximate only for astral-plane characters, where * UTF-16 units and the server's count differ — a rounding error, against a guaranteed * wrong answer. * - `artifact` and `artifactTitle` degrade to empty. They render a preview card, so * losing them costs a card; failing the whole read would cost the user the skill. */ export declare const toSkillDetail: (payload: SkillDetailDataPayload) => SkillDetail; export {};