import * as ThingTalk from 'thingtalk'; import * as Tp from 'thingpedia'; import * as I18n from '../i18n'; import * as DB from './db'; import DeviceDatabase from './devices/database'; import SyncManager from './sync/manager'; import AppDatabase from './apps/database'; import type AppExecutor from './apps/app_executor'; import AudioController from '../dialogue-agent/audio/controller'; import AssistantDispatcher from '../dialogue-agent/assistant_dispatcher'; import { NotificationConfig } from '../dialogue-agent/notifications'; import { ActivityMonitor, ActivityMonitorStatus } from './activity_monitor'; export { DB, DeviceDatabase, SyncManager, AppDatabase, AppExecutor, ActivityMonitor, ActivityMonitorStatus }; interface DeviceState { kind: string; accessToken?: string; refreshToken?: string; [key: string]: unknown; } /** * Information about a running ThingTalk program (app). */ export interface AppInfo { /** * The unique ID of the app. */ uniqueId: string; /** * A short string identifying the app. */ name: string; /** * A longer description of the code in the app. */ description: string; code: string; /** * The icon associated with the app (as a Thingpedia class ID). */ icon: string | null; /** * Whether the app is currently running (executing ThingTalk code). */ isRunning: boolean; /** * Whether the app is set to run in the background. */ isEnabled: boolean; /** * The last error reported by the app. */ error: string | null; /** * Configuration related to how notifications should be reported by the app. */ notifications?: { /** * Identifier of the backend to use for notifications. */ backend: string; /** * Backend-specific information, such as the phone number or email * address to send notifications to. */ config: Record; }; } /** * Information about a configured Thingpedia device. */ export interface DeviceInfo { /** * The unique ID of the device. */ uniqueId: string; /** * A short, human-readable string identifying the device. */ name: string; /** * A longer string describing the device. */ description: string; /** * The Thingpedia class ID this device belongs to (suitable to select an icon). */ kind: string; /** * The version of the class this device belongs to. */ version: number; /** * The coarse categorization of the device: `physical`, `online`, `data`, or `system`. */ class: 'physical' | 'online' | 'data' | 'system'; /** * The ID of the engine that configured this device (for purposes of cloud sync). */ ownerTier: string; /** * `true` if this device was created on the fly by some discovery module, `false` * if it was configured manually and is stored on disk. */ isTransient: boolean; /** * A string identifying the type of authentication used by this device. */ authType: string; } export interface AppResult { raw: Record; type: string; formatted: Tp.FormatObjects.FormattedObject[]; } /** * The core Genie engine. * * There is one engine instance per user. Multiple engine instances * can run in the same process, but they must be associated with * different platform objects. * */ export default class AssistantEngine extends Tp.BaseEngine { readonly _: (x: string) => string; private _db; _sync: SyncManager; private _modules; private _langPack; private _devices; private _appdb; private _assistant; private _audio; private _activityMonitor; private _running; private _stopCallback; /** * Construct a new engine. * * @param {external:thingpedia.BasePlatform} platform - the platform associated with this engine * @param {Object} options - additional options; this is also passed to the parent class * @param {string} [options.cloudSyncUrl] - URL to use for cloud sync */ constructor(platform: Tp.BasePlatform, options?: { cloudSyncUrl?: string; nluModelUrl?: string; thingpediaUrl?: string; notifications?: NotificationConfig; activityMonitorOptions?: { idleTimeoutMillis?: number; quiesceTimeoutMillis?: number; }; }); get platform(): Tp.BasePlatform; get langPack(): I18n.LanguagePack; get db(): DB.AbstractDatabase; /** * Return a unique identifier associated with this engine. * * This is a string composed of two parts: the high-level tier type * (phone, cloud, server, desktop), and a unique identifier. The tier * is used by the cloud sync subsystem, and can be used by devices * that use local communication to distinguish which engine configured them. */ get ownTier(): string; /** * Access the device database of this engine. */ get devices(): DeviceDatabase; /** * Access the app database of this engine. */ get apps(): AppDatabase; /** * Access the assistant dispatcher of this engine. */ get assistant(): AssistantDispatcher; /** * Access the audio controller to coordinate access to audio. */ get audio(): AudioController; /** * Access the activity monitor for this engine. */ get activityMonitor(): ActivityMonitor; updateActivity(): void; private _loadBuiltins; private _openSequential; private _closeSequential; /** * Initialize this engine. * * This will initialize all modules sequentially in the right * order. It must be called before {@link run}. */ open(): Promise; /** * Deinitialize this engine. * * This will sequentially close all modules, save the database * and release all resources. * * This should not be called if {@link start} fails. After * this method succeed, the engine is in undefined state and must * not be used. */ close(): Promise; /** * Run ThingTalk rules. * * Kick start the engine by returning a promise that will * run each rule in sequence, forever, without ever being * fulfilled until {@link stop} is called. */ run(): Promise; /** * Stop any rule execution at the next available moment. * * This will cause the {@link run} promise to be fulfilled. * * This method can be called multiple times and is idempotent. * It can also be called before {@link run}. */ stop(): void; /** * Begin configuring a device with an OAuth-like flow. * * @param {string} kind - the Thingpedia class ID of the device to configure. * @return {Array} a tuple with the redirect URL and the session object. */ startOAuth(kind: string): Promise<[string, Record]>; /** * Complete OAuth-like configuration for a device. * * @param {string} kind - the Thingpedia class ID of the device to configure. * @param {string} redirectUri - the OAuth redirect URI that was called at the end of the OAuth flow. * @param {Object.} session - an object with session information. * @return {external:thingpedia.BaseDevice} the configured device, or null if configuration failed */ completeOAuth(kind: string, redirectUri: string, session: Record): Promise; /** * Configure a simple device with no configuration information needed. * * @param {string} kind - the Thingpedia class ID of the device to configure. * @return {external:thingpedia.BaseDevice} the configured device */ createSimpleDevice(kind: string): Promise; /** * Configure a device with direct configuration information. * * @param {Object} state - the configured device parameters. * @param {string} state.kind - the Thingpedia class ID of the device to configure. * @return {external:thingpedia.BaseDevice} the configured device */ createDevice(state: DeviceState): Promise; /** * Delete a device by ID. * * Deleting a device removes any stored credentials and configuration about that device. * * @param {string} uniqueId - the ID of the device to delete * @return {boolean} true if the device was deleted successfully, false if it did not exist */ deleteDevice(uniqueId: string): Promise; /** * Update all devices of the given type to the latest version in Thingpedia. * * @param {string} kind - the Thingpedia class ID of the devices to update */ upgradeDevice(kind: string): Promise; /** * Returns the list of all device classes that have been previously cached. */ getCachedDeviceClasses(): Promise; /** * Returns whether a specific device has been configured or not. * * @param {string} uniqueId - the device ID to check * @return {boolean} true if the device exists, false otherwise */ hasDevice(uniqueId: string): boolean; private _toDeviceInfo; /** * Get information about all configured devices. * * @param {string} [kind] - filter only devices that have the specified kind * @return {Array} a list of device info objects, one per device */ getDeviceInfos(kind?: string): DeviceInfo[]; /** * Get information about one configured device by ID. * * @param {string} uniqueId - the ID of the device to return info for * @return information about that device */ getDeviceInfo(uniqueId: string): DeviceInfo; /** * Asynchronously check whether a device is available. * * @param {string} uniqueId - the ID of the device to check * @return {external:thingpedia.Availability} whether the device is available */ checkDeviceAvailable(uniqueId: string): Promise; private _toAppInfo; /** * Get information about all running ThingTalk programs (apps). * * @return {Array} a list of app info objects, one per app */ getAppInfos(): AppInfo[]; /** * Get information about one running ThingTalk program (app) by ID. * * @param {string} uniqueId - the ID of the app to return info for * @param {boolean} [throw_=true] - throw an error if there is no such app * @return {AppInfo} information about that app */ getAppInfo(uniqueId: string, throw_?: true): AppInfo; getAppInfo(uniqueId: string, throw_: boolean): AppInfo | undefined; /** * Stop (delete) the ThingTalk program (app) with the given ID. * * @param {string} uniqueId - the ID of the app to delete * @return {boolean} true if the deletion occurred, false otherwise */ deleteApp(uniqueId: string): Promise; /** * Create a new ThingTalk app. * * This is the main entry point to execute ThingTalk code. * * @param {string|external:thingtalk.Ast.Program} program - the ThingTalk code to execute, * or the parsed ThingTalk program (AST) * @param {Object} options * @param {string} [options.uniqueId] - the ID to assign to the new app * @param {string} [options.name] - the name of the new app * @param {string} [options.description] - the human-readable description of the code * being executed * @param {string} [options.icon] - the icon of the new app (as a Thingpedia class ID) * @param {string} [options.conversation] - the ID of the conversation associated with the new app * @return {AppExecutor} the newly created program */ createApp(programOrString: ThingTalk.Ast.Program | string, options?: { uniqueId?: string; name?: string; description?: string; icon?: string; conversation?: string; notifications?: { backend: string; config: Record; }; }): Promise; /** * Create a new ThingTalk app, and execute it to compute all results. * * This is a convenience wrapper over {@link createApp} that also * iterates the results of the app and formats them. * * @param {string|external:thingtalk.Ast.Program} program - the ThingTalk code to execute, * or the parsed ThingTalk program (AST) * @param {Object} options * @param {string} [options.uniqueId] - the ID to assign to the new app * @param {string} [options.name] - the name of the new app * @param {string} [options.description] - the human-readable description of the code * being executed * @param {string} [options.icon] - the icon of the new app (as a Thingpedia class ID) * @param {string} [options.conversation] - the ID of the conversation associated with the new app */ createAppAndReturnResults(programOrString: ThingTalk.Ast.Program | string, options?: { uniqueId?: string; name?: string; description?: string; icon?: string; conversation?: string; notifications?: { backend: string; config: Record; }; }): Promise<{ uniqueId: string; description: string; code: string; icon: string | null; results: AppResult[]; errors: Error[]; }>; /** * Configure cloud synchronization. * * This method can be called in non-cloud Almond to start synchronization * with the cloud. * * @param {string} cloudId - the ID of the user in Web Almond * @param {string} authToken - the access token */ setCloudId(cloudId: string, authToken: string): Promise; /** * Configure synchronization with a local server. * * This method can be called in a phone or desktop Almond to synchronize * with a locally-setup home server Almond . * * @param {string} serverHost - the IP address or hostname of the server to connect to * @param {number} serverPort - the port at which server is reachable * @param {string} authToken - the access token */ addServerAddress(serverHost: string, serverPort: number, authToken: string): Promise; }