Saxonberg Server API
    Preparing search index...

    Interface FieldDefinition

    interface FieldDefinition {
        cardinality?: CardinalitySpec;
        default?: string;
        greedy?: boolean;
        multiple?: boolean;
        onExcess?: OnExcessPolicy;
        onShortage?: "error";
        prepositions?: string[];
        required?: boolean;
        schema?: Record<string, unknown>;
        scope?: string | string[];
        type?: "string" | "number" | "boolean" | "object" | "struct" | "objects";
        updates_focus?: "replace" | "none" | "extend";
        validators?: string[];
    }

    Hierarchy (View Summary)

    Index

    Properties

    cardinality?: CardinalitySpec

    Cardinality constraint for objects fields. Ignored on other field types. Defaults to { min: 0, max: Infinity }.

    default?: string

    Value the matcher fills when the player provides no input for this field. The default runs through shell-side variable interpolation just like player-typed text — default: "$focus" resolves to the giver's current focus at bind time.

    required: true + default: is allowed: the default replaces the missing input, no shape error. The "missing required arg" message only fires when the field is required AND has no default AND the player supplied nothing.

    greedy?: boolean

    Greedy positional: consumes the remainder of the original input verbatim (whitespace preserved, escapes processed, quotes literal). Must be the last positional in its block.

    multiple?: boolean
    onExcess?: OnExcessPolicy

    Policy when MQL resolves too many results.

    • 'object' field default: 'top' (preserves pre-cardinality behavior; pick the highest-scored match).
    • 'objects' field default: 'prompt' if cardinality.max is set, 'take-all' otherwise.

    'top' and 'take-all' are mutually exclusive between field types (schema validation rejects 'top' on objects, 'take-all' on object, etc.).

    onShortage?: "error"

    Policy when MQL resolves fewer results than cardinality.min. v1 only value: 'error'. Future values land additively.

    prepositions?: string[]

    Optional list of prepositions the matcher will consume as a leading boundary marker for this positional field. Lowercased. Typing look at flower against prepositions: [at] consumes the at and binds target = "flower"; typing look flower binds target = "flower" directly. The consumed preposition lands on ctx.prep[fieldName].

    For multi-field commands, later fields' declared prepositions also serve as termination boundaries for an earlier greedy field — give the red flower to bob splits correctly because recipient: prepositions: [to] tells the matcher to stop the greedy gift at to.

    Prepositions are always optional: declaring prepositions: [to] means "consume to if it appears here," not "require to."

    required?: boolean
    schema?: Record<string, unknown>

    Optional JSON Schema fragment for type: 'struct' fields. Run by ajv during the structured-input coercion step; failure yields a friendly error pointing at the offending property.

    scope?: string | string[]

    MQL scope fragment(s) the dispatcher tries when resolving this field. Each fragment runs through ShellApi.expandVariables (so $focus / stored vars expand at resolve time) and is tried in order; first non-empty result wins.

    The YAML/spec record accepts string | string[]. After CommandDefinition construction, the runtime value is always string[] | undefinednormaliseShape coerces a bare string into a singleton array, so consumers don't have to branch.

    The array form is the explicit fallback chain — a verb that wants drill-first-then-broad declares scope: ['$focus', 'reachable'] so a drilled player searches the focus first with the room as fallback. Verbs that should ignore drill declare a non-$focus fragment (e.g. scope: 'inventory' for drop, scope: 'peers' for get).

    Default when omitted: ['$focus'] — the drill chain IS the scope. The resolver's empty-scope fallback to reachable stays as the safety net for when the focus chain stops resolving (typically after movement into a different room). Only meaningful for type: object / type: objects fields.

    type?: "string" | "number" | "boolean" | "object" | "struct" | "objects"
    • string / number / boolean — primitive coerce-on-bind.
    • object — singular MQL field; the dispatcher resolves the bound text via MqlApi.resolveOne (when onExcess: 'top') or MqlApi.resolveMany (otherwise — full list needed for counting / prompting). Implicit cardinality { exactly: 1 }.
    • objects — plural MQL field; the dispatcher resolves via MqlApi.resolveMany. multiple: true is NOT used for MQL fields — the cardinality is the type plus the optional cardinality knob.
    • struct — structured-input-only blob (Record<string, unknown>). Cannot be bound from text — msh returns a clear error if a verb's positional or option of this type appears in tokenised input. Used by widget/editor clients via assembleFromStructured. Validated against the optional schema (JSON Schema) before user-defined validators fire.
    updates_focus?: "replace" | "none" | "extend"

    Focus management policy for this field. Three modes:

    • extend — append the post-desugar input fragment to the giver's current focus with : as the separator. With same-anchor + via.detailPath compaction (re-resolving the same target doesn't double-add). The drill-additive default for inspection-shaped verbs (look, examine, read, open, close).

    • replace — set focus to the post-desugar input fragment wholesale. For navigation/anchoring verbs that should reset the trail rather than extend it.

    • none (default) — focus unchanged. Most commands (get, drop, say) don't manage focus.

    Pronoun substitution applies in all extending paths: when raw is itself a pronoun (it/him/her/them/$$), the stored fragment from pronoun memory replaces the literal pronoun string before the focus is updated, so the trail tracks the actual referent rather than the unstable pronoun.

    Empty resolutions never touch focus regardless of mode — the resolveAndValidate gate is "if resolved.stuff is non-null".

    Renamed from the v1 updates_scope?: boolean field — the field manages focus, not scope. The boolean's true setting is equivalent to 'extend' under the new drill-additive default.

    validators?: string[]