import * as Tp from 'thingpedia'; import { Ast, SchemaRetriever } from 'thingtalk'; import { Contact } from './entity-linking/contact_search'; import { EntityRecord } from './entity-linking/entity-finder'; import ValueCategory from './value-category'; interface AbstractDialogueAgentOptions { locale: string; timezone: string; debug: boolean; } export interface NewProgramRecord { uniqueId: string; name: string; code: string; results: Array>; errors: string[]; icon: string | null; } export interface NotificationConfig { backend: string; config: Record; } export declare type RawExecutionResult = Array<[string, Record]>; interface AbstractStatementExecutor { executeStatement(stmt: Ast.ExpressionStatement, privateState: PrivateStateType | undefined, notificationConfig: NotificationConfig | undefined): Promise<[Ast.DialogueHistoryResultList, RawExecutionResult, NewProgramRecord | undefined, PrivateStateType, Ast.AnnotationSpec]>; } export interface DisambiguationHints { devices: Map; idEntities: Map; previousLocations: Ast.AbsoluteLocation[]; } export interface DeviceInfo { kind: string; uniqueId: string; name: string; } interface ExecutionResult { newDialogueState: Ast.DialogueState; newExecutorState: PrivateStateType | undefined; newResults: Array<[string, Record]>; newPrograms: NewProgramRecord[]; anyChange: boolean; } /** * Base class of a dialogue agent. * * The class contains the code that is common between execution (aka inference time) * and simulation (aka training time). * Because it is used for simulation, the class is completely stateless * * The public API of this class is used by the entity linking & device choice code * (during the "prepare for execution" step) to abstract the access to the "user". * * There are two subclasses, one used during simulation, and one used for execution. */ export default abstract class AbstractDialogueAgent { protected _tpClient: Tp.BaseClient; protected _schemas: SchemaRetriever; protected _debug: boolean; private _langPack; locale: string; timezone: string; constructor(tpClient: Tp.BaseClient, schemas: SchemaRetriever, options: AbstractDialogueAgentOptions); /** * Execute the query or action implied by the current dialogue state. * * This method should return a new dialogue state with filled information * about the result. It should not modify the state in-place. * * This is the only public method in this class. * * @param {Ast.DialogueState} state - the current state, representing the query or action to execute * @param {any} privateState - additional state carried by the dialogue agent (per dialogue) * @return {Ast.DialogueState} - the new state, with information about the returned query or action */ execute(state: Ast.DialogueState, privateState: PrivateStateType | undefined): Promise>; private _collectDisambiguationHintsForState; /** * Ensure that notifications are configured for the user, and gather * all the information we need. */ protected abstract configureNotifications(): Promise; /** * Check that a given statement is permitted for the current user. * * This is the hook to prevent running unsafe statements in anonymous mode. */ protected abstract checkForPermission(stmt: Ast.ExpressionStatement): Promise; /** * Prepare a statement for being executed. * * This will resolve all ThingTalk values that are relative to the user, such as * `$context.location.current_location`, and will assign device IDs to all Thingpedia * function calls. * * The statement is modified in place. * * @param {thingtalk.Ast.Statement} stmt - the statement to prepare * @param {any} hints - hints to use to resolve any ambiguity */ protected _prepareForExecution(stmt: Ast.ExpressionStatement, hints: DisambiguationHints): Promise; /** * Show a debug message. * * @param {any} msg - what to show */ debug(...args: unknown[]): void; private _chooseDevice; private _addDisplayToDevice; private _maybeAddDisplayToValue; private _concretizeValue; /** * Retrieve the executor to use for each statement. */ protected get executor(): AbstractStatementExecutor; /** * List all configured devices that implement the given ThingTalk kind. * * @param {string} kind - the kind to check * @returns {Array} - the list of configured devices */ protected getAllDevicesOfKind(kind: string): Promise; /** * Attempt to automatically configure a device of the given kind. * * @param {string} kind - the kind to configure * @returns {DeviceInfo} - the newly configured device */ protected tryConfigureDevice(kind: string): Promise; /** * Disambiguate an entity by explicitly asking the user. * * @param {string} type - the type of disambiguation to perform, either `device`, `contact`, * or `entity` * @param {string} name - the name to disambiguate * @param {string[]} choices - the choices among which to disambiguate * @param {string} hint - a type-specific hint to show to the user * @returns {number} - the index of the provided choice */ disambiguate(type: 'device' | 'device-missing' | 'contact', name: string | null, choices: string[], hint?: string): Promise; /** * Lookup a contact in the address book. * * @param {ValueCategory} category - the category of information to look up * @param {string} name - the name to look up * @returns {string[]} - the list of resolved information of all contacts matching the name */ lookupContact(category: ValueCategory, name: string): Promise; /** * Add the display field to a phone or email entity, by looking up the contact in the address book. * * @param {thingtalk.Ast.Value} contact - the entity to look up */ protected addDisplayToContact(contact: Ast.EntityValue): Promise; /** * Ask the user about a contact that is not in the address book. * * @param {ValueCategory} category - the category of information to look up * @param {string} name - the name to look up * @returns {thingtalk.Ast.Value.Entity} - the entity corresponding to the picked up information */ askMissingContact(category: ValueCategory.EmailAddress | ValueCategory.PhoneNumber | ValueCategory.Contact, name: string): Promise; /** * Resolve a location name to a specific point on Earth. * * @param {string} searchKey - the location name to look up * @param {thingtalk.Ast.Location[]} previousLocations - recently mentioned locations * @returns {thingtalk.Ast.Value} - the best match for the given name */ protected lookupLocation(searchKey: string, previousLocations: Ast.AbsoluteLocation[]): Promise; /** * Resolve an entity using the Thingpedia database or by calling the underlying API. * * @param entityType - the type of entity to look up * @param entityDisplay - the display name of the entity look up * @param hints - hints to use to resolve any ambiguity * @returns - the entity that matched the given name, in Thingpedia API format */ protected abstract resolveEntity(entityType: string, entityDisplay: string, hints: DisambiguationHints): Promise; /** * Resolve a `$context` variable to a concrete value. * * @param {string} variable - the variable name to lookup, including the `$context.` prefix * @returns {thingtalk.Ast.Value} - the resolved value */ protected resolveUserContext(variable: string): Promise; /** * Compute the user's preferred unit to use when the program specifies an ambiguous unit * such as "degrees". * * @param {string} type - the type of unit to retrieve (e.g. "temperature"), or undefined * if the user has no preference * @returns {string} - the preferred unit */ getPreferredUnit(type: string): string | undefined; } export {};