/** * @file Grammar Builder Interfaces * @description Language-agnostic interfaces for defining grammar rules */ import { IEntity } from '@sharpee/core'; /** * Slot types for grammar patterns * Controls how the parser handles slot matching */ export declare enum SlotType { /** Default: resolve slot text to an entity via vocabulary lookup */ ENTITY = "entity", /** Capture raw text without entity resolution (single token) */ TEXT = "text", /** Capture raw text until next pattern element or end (greedy) */ TEXT_GREEDY = "text_greedy", /** Resolve entity but mark as instrument for the action */ INSTRUMENT = "instrument", /** Match cardinal/ordinal direction (n, s, e, w, ne, up, down, etc.) */ DIRECTION = "direction", /** Match integer (digits or words: 1, 29, one, twenty) */ NUMBER = "number", /** Match ordinal (1st, first, 2nd, second, etc.) */ ORDINAL = "ordinal", /** Match time expression (10:40, 6:00) */ TIME = "time", /** Match manner adverb (carefully, quickly, forcefully) - feeds intention.manner */ MANNER = "manner", /** Match text enclosed in double quotes */ QUOTED_TEXT = "quoted_text", /** Match conversation topic (one or more words) */ TOPIC = "topic", /** Match word from a story-defined vocabulary category */ VOCABULARY = "vocabulary", /** @deprecated Use VOCABULARY with .fromVocabulary() instead */ ADJECTIVE = "adjective", /** @deprecated Use VOCABULARY with .fromVocabulary() instead */ NOUN = "noun" } /** * Constraint types for slot matching */ export type PropertyConstraint = Record; export type FunctionConstraint = (entity: IEntity, context: GrammarContext) => boolean; export type ScopeConstraintBuilder = (scope: ScopeBuilder) => ScopeBuilder; export type Constraint = PropertyConstraint | FunctionConstraint | ScopeConstraintBuilder; /** * Context provided to constraint functions */ export interface GrammarContext { world: any; actorId: string; actionId?: string; currentLocation: string; slots: Map; } /** * Scope builder for constraint definitions */ export interface ScopeBuilder { visible(): ScopeBuilder; touchable(): ScopeBuilder; carried(): ScopeBuilder; nearby(): ScopeBuilder; matching(constraint: PropertyConstraint | FunctionConstraint): ScopeBuilder; kind(kind: string): ScopeBuilder; orExplicitly(entityIds: string[]): ScopeBuilder; orRule(ruleId: string): ScopeBuilder; /** * Require the entity to have a specific trait * @param traitType The trait type constant (e.g., TraitType.PORTABLE) */ hasTrait(traitType: string): ScopeBuilder; build(): ScopeConstraint; } /** * Internal scope constraint representation */ export interface ScopeConstraint { base: 'visible' | 'touchable' | 'carried' | 'nearby' | 'all'; filters: Array; /** Required trait types the entity must have */ traitFilters: string[]; explicitEntities: string[]; includeRules: string[]; } /** * ADR-082: Typed slot value for non-entity slots * Each variant carries the parsed/typed value from the input */ export type TypedSlotValue = { type: 'direction'; direction: string; canonical: string; } | { type: 'number'; value: number; word: string; } | { type: 'ordinal'; value: number; word: string; } | { type: 'time'; hours: number; minutes: number; text: string; } | { type: 'manner'; word: string; } | { type: 'quoted_text'; text: string; } | { type: 'topic'; words: string[]; } | { type: 'vocabulary'; word: string; category: string; } | { type: 'adjective'; word: string; } | { type: 'noun'; word: string; }; /** * Pattern builder for defining grammar rules */ export interface PatternBuilder { /** * Require a slot's entity to have a specific trait * This is the primary method for semantic constraints in grammar. * @param slot The slot name from the pattern * @param traitType The trait type constant (e.g., TraitType.CONTAINER) * * @example * ```typescript * grammar.define('board :target') * .hasTrait('target', TraitType.ENTERABLE) * .mapsTo('if.action.entering') * .build(); * ``` */ hasTrait(slot: string, traitType: string): PatternBuilder; /** * Define a constraint for a slot (advanced use) * Prefer .hasTrait() for trait-based constraints. * @param slot The slot name from the pattern * @param constraint The constraint to apply */ where(slot: string, constraint: Constraint): PatternBuilder; /** * Mark a slot as capturing raw text (single token) instead of resolving to entity * For greedy text capture, use :slot... syntax in the pattern * @param slot The slot name from the pattern */ text(slot: string): PatternBuilder; /** * Mark a slot as an instrument for the action * The slot will still resolve to an entity, but be stored in command.instrument * @param slot The slot name from the pattern */ instrument(slot: string): PatternBuilder; /** * Map this pattern to an action * @param action The action identifier */ mapsTo(action: string): PatternBuilder; /** * Set the priority for this pattern (higher = preferred) * @param priority The priority value */ withPriority(priority: number): PatternBuilder; /** * Add semantic mappings for verbs * @param verbs Map of verb text to semantic properties */ withSemanticVerbs(verbs: Record>): PatternBuilder; /** * Add semantic mappings for prepositions * @param prepositions Map of preposition text to spatial relations */ withSemanticPrepositions(prepositions: Record): PatternBuilder; /** * Add semantic mappings for directions * @param directions Map of direction text to normalized directions */ withSemanticDirections(directions: Record): PatternBuilder; /** * Set default semantic properties * @param defaults Default semantic properties */ withDefaultSemantics(defaults: Partial): PatternBuilder; /** * Mark a slot as a number (integer) * Matches digits (1, 29, 100) or words (one, twenty) * @param slot The slot name from the pattern */ number(slot: string): PatternBuilder; /** * Mark a slot as an ordinal * Matches ordinal words (first, second) or suffixed numbers (1st, 2nd) * @param slot The slot name from the pattern */ ordinal(slot: string): PatternBuilder; /** * Mark a slot as a time expression * Matches HH:MM format (10:40, 6:00) * @param slot The slot name from the pattern */ time(slot: string): PatternBuilder; /** * Mark a slot as a direction * Matches built-in direction vocabulary (n, north, up, etc.) * @param slot The slot name from the pattern */ direction(slot: string): PatternBuilder; /** * Mark a slot as a manner adverb * Matches built-in manner vocabulary (carefully, quickly, forcefully, etc.) * The matched word is stored in command.intention.manner * @param slot The slot name from the pattern */ manner(slot: string): PatternBuilder; /** * Mark a slot as matching a story-defined vocabulary category * The category must be registered via world.getVocabularyProvider().define() * * @param slot The slot name from the pattern * @param category The vocabulary category name * * @example * ```typescript * // Register vocabulary * vocab.define('panel-colors', { * words: ['red', 'yellow', 'mahogany', 'pine'], * when: (ctx) => ctx.currentLocation === insideMirrorId * }); * * // Use in grammar * grammar * .define('push :color panel') * .fromVocabulary('color', 'panel-colors') * .mapsTo('push_panel') * .build(); * ``` */ fromVocabulary(slot: string, category: string): PatternBuilder; /** * @deprecated Use fromVocabulary() with a named category instead * Mark a slot as an adjective from story vocabulary */ adjective(slot: string): PatternBuilder; /** * @deprecated Use fromVocabulary() with a named category instead * Mark a slot as a noun from story vocabulary */ noun(slot: string): PatternBuilder; /** * Mark a slot as quoted text * Matches text enclosed in double quotes * @param slot The slot name from the pattern */ quotedText(slot: string): PatternBuilder; /** * Mark a slot as a conversation topic * Consumes one or more words as a topic * @param slot The slot name from the pattern */ topic(slot: string): PatternBuilder; /** * Build the final grammar rule */ build(): GrammarRule; } /** * Main grammar builder interface */ export interface GrammarBuilder { /** * Define a new grammar pattern * @param pattern The pattern string (e.g., "put :item in|into :container") */ define(pattern: string): PatternBuilder; /** * ADR-087: Define grammar patterns for an action with verb aliases * @param actionId The action identifier to map patterns to * @returns An ActionGrammarBuilder for fluent configuration * * @example * ```typescript * grammar * .forAction('if.action.pushing') * .verbs(['push', 'press', 'shove', 'move']) * .pattern(':target') * .where('target', scope => scope.touchable()) * .build(); * ``` */ forAction(actionId: string): ActionGrammarBuilder; /** * Get all defined rules */ getRules(): GrammarRule[]; /** * Clear all rules */ clear(): void; } /** * ADR-087: Action-centric grammar builder * Allows defining multiple patterns for an action with verb aliases */ export interface ActionGrammarBuilder { /** * Define verb aliases for this action * Each verb will generate a separate pattern * @param verbs Array of verb strings (e.g., ['push', 'press', 'shove']) */ verbs(verbs: string[]): ActionGrammarBuilder; /** * Define a pattern template (without verb) * Will be combined with each verb to create full patterns * @param pattern Pattern template (e.g., ':target' becomes 'push :target', 'press :target', etc.) */ pattern(pattern: string): ActionGrammarBuilder; /** * Define multiple pattern templates * Each pattern will be combined with each verb * @param patterns Array of pattern templates * * @example * ```typescript * grammar * .forAction('if.action.pushing') * .verbs(['push', 'press']) * .patterns([':target', ':target :direction']) * .build(); * // Generates: push :target, press :target, push :target :direction, press :target :direction * ``` */ patterns(patterns: string[]): ActionGrammarBuilder; /** * Define direction patterns with aliases * Creates standalone direction patterns (no verb prefix) * @param directionMap Map of canonical direction to aliases * * @example * ```typescript * grammar * .forAction('if.action.going') * .directions({ * 'north': ['north', 'n'], * 'south': ['south', 's'], * }) * .build(); * // Generates patterns 'north', 'n', 'south', 's' each with direction semantics * ``` */ directions(directionMap: Record): ActionGrammarBuilder; /** * Require a slot's entity to have a specific trait (applies to all generated patterns) * This is the primary method for semantic constraints in grammar. * @param slot The slot name from the pattern * @param traitType The trait type constant (e.g., TraitType.CONTAINER) */ hasTrait(slot: string, traitType: string): ActionGrammarBuilder; /** * Define a constraint for a slot (applies to all generated patterns) * Prefer .hasTrait() for trait-based constraints. * @param slot The slot name from the pattern * @param constraint The constraint to apply */ where(slot: string, constraint: Constraint): ActionGrammarBuilder; /** * Set priority for all generated patterns * @param priority The priority value (higher = preferred) */ withPriority(priority: number): ActionGrammarBuilder; /** * Set default semantic properties for all generated patterns * @param defaults Default semantic properties */ withDefaultSemantics(defaults: Partial): ActionGrammarBuilder; /** * Mark a slot as a specific type (applies to all generated patterns) * @param slot The slot name * @param slotType The slot type */ slotType(slot: string, slotType: SlotType): ActionGrammarBuilder; /** * Build all patterns and add them to the grammar * Generates patterns from: verbs × patterns combinations */ build(): void; } /** * A compiled grammar rule */ export interface GrammarRule { id: string; pattern: string; compiledPattern?: CompiledPattern; slots: Map; action: string; priority: number; semantics?: SemanticMapping; defaultSemantics?: Partial; experimentalConfidence?: number; } /** * Semantic properties that can be derived from grammar */ export interface SemanticProperties { /** How an action is performed */ manner?: 'normal' | 'careful' | 'careless' | 'forceful' | 'stealthy' | 'quick'; /** Spatial relationship for placement actions */ spatialRelation?: 'in' | 'on' | 'under' | 'behind' | 'beside' | 'above' | 'below'; /** Direction for movement */ direction?: 'north' | 'south' | 'east' | 'west' | 'up' | 'down' | 'northeast' | 'northwest' | 'southeast' | 'southwest' | 'in' | 'out'; /** Whether the preposition was implicit */ implicitPreposition?: boolean; /** Whether a direction was implicit */ implicitDirection?: boolean; /** Custom properties for specific actions */ [key: string]: any; } /** * Mapping from text variations to semantic properties */ export interface SemanticMapping { /** Map verb variations to properties */ verbs?: Record>; /** Map preposition variations to spatial relations */ prepositions?: Record; /** Map direction variations to normalized directions */ directions?: Record; /** Function to compute dynamic semantics based on match */ compute?: (match: any) => Partial; } /** * Slot constraint definition */ export interface SlotConstraint { name: string; constraints: Constraint[]; /** Required trait types the entity must have (from .hasTrait()) */ traitFilters?: string[]; /** How the parser should handle this slot (default: ENTITY) */ slotType?: SlotType; /** For VOCABULARY slots: the category name to match against */ vocabularyCategory?: string; } /** * Token in a pattern */ export interface PatternToken { type: 'literal' | 'slot' | 'alternates'; value: string; alternates?: string[]; optional?: boolean; slotType?: SlotType; greedy?: boolean; vocabularyCategory?: string; } /** * Compiled pattern for efficient matching */ export interface CompiledPattern { tokens: PatternToken[]; slots: Map; minTokens: number; maxTokens: number; } /** * Slot match data with multi-object support */ export interface SlotMatch { tokens: number[]; text: string; slotType?: SlotType; confidence?: number; isAll?: boolean; isList?: boolean; items?: SlotMatch[]; excluded?: SlotMatch[]; category?: string; matchedWord?: string; manner?: string; isPronoun?: boolean; entityId?: string; resolvedText?: string; } /** * Result of pattern matching */ export interface PatternMatch { rule: GrammarRule; confidence: number; slots: Map; consumed: number; semantics?: SemanticProperties; matchedTokens?: { verb?: string; preposition?: string; direction?: string; }; } //# sourceMappingURL=grammar-builder.d.ts.map