@fonoster/autopilot 0.4.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/LICENSE +21 -0
  2. package/dist/cerebro/cerebro.d.ts +26 -0
  3. package/dist/cerebro/cerebro.js +155 -0
  4. package/dist/cerebro/effects.d.ts +11 -0
  5. package/dist/cerebro/effects.js +91 -0
  6. package/dist/cerebro/helper.d.ts +5 -0
  7. package/dist/cerebro/helper.js +43 -0
  8. package/dist/cerebro/index.d.ts +2 -0
  9. package/dist/cerebro/index.js +36 -0
  10. package/dist/cerebro/types.d.ts +40 -0
  11. package/dist/cerebro/types.js +9 -0
  12. package/dist/events/emitter.d.ts +7 -0
  13. package/dist/events/emitter.js +13 -0
  14. package/dist/events/server.d.ts +12 -0
  15. package/dist/events/server.js +67 -0
  16. package/dist/events/types.d.ts +20 -0
  17. package/dist/events/types.js +29 -0
  18. package/dist/file-retention/cron.d.ts +2 -0
  19. package/dist/file-retention/cron.js +23 -0
  20. package/dist/file-retention/index.d.ts +1 -0
  21. package/dist/file-retention/index.js +35 -0
  22. package/dist/file-retention/task.d.ts +6 -0
  23. package/dist/file-retention/task.js +56 -0
  24. package/dist/index.d.ts +1 -0
  25. package/dist/index.js +29 -0
  26. package/dist/intents/df_utils.d.ts +3 -0
  27. package/dist/intents/df_utils.js +39 -0
  28. package/dist/intents/dialogflow_cx.d.ts +15 -0
  29. package/dist/intents/dialogflow_cx.js +87 -0
  30. package/dist/intents/dialogflow_es.d.ts +15 -0
  31. package/dist/intents/dialogflow_es.js +172 -0
  32. package/dist/intents/engines.d.ts +3 -0
  33. package/dist/intents/engines.js +32 -0
  34. package/dist/intents/types.d.ts +26 -0
  35. package/dist/intents/types.js +2 -0
  36. package/dist/pilot.d.ts +3 -0
  37. package/dist/pilot.js +131 -0
  38. package/dist/types.d.ts +36 -0
  39. package/dist/types.js +2 -0
  40. package/dist/util.d.ts +6 -0
  41. package/dist/util.js +26 -0
  42. package/dist/voice.d.ts +3 -0
  43. package/dist/voice.js +154 -0
  44. package/package.json +41 -0
@@ -0,0 +1,36 @@
1
+ export interface ServerConfig {
2
+ port: number;
3
+ defaultLanguageCode: string;
4
+ eventsServerEnabled: boolean;
5
+ /**
6
+ * Enable file retention policy
7
+ *
8
+ * @default true
9
+ */
10
+ fileRetentionPolicyEnabled?: boolean;
11
+ /**
12
+ * Directory where the file retention policy will be executed
13
+ *
14
+ * @default os.tmpdir()
15
+ */
16
+ fileRetentionPolicyDirectory?: string;
17
+ /**
18
+ * Cron expression to run the file retention policy
19
+ *
20
+ * @default 0 0 * * *
21
+ * @see https://crontab.guru/#0_0_*_*_*
22
+ */
23
+ fileRetentionPolicyCronExpression?: string;
24
+ /**
25
+ * Max age in hours to keep files
26
+ *
27
+ * @default 24
28
+ */
29
+ fileRetentionPolicyMaxAge?: number;
30
+ /**
31
+ * File extension to be deleted
32
+ *
33
+ * @default .sln24
34
+ */
35
+ fileRetentionPolicyExtension?: string;
36
+ }
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
package/dist/util.d.ts ADDED
@@ -0,0 +1,6 @@
1
+ import { EventsClient } from "./events/emitter";
2
+ import { ClientEvent } from "./events/types";
3
+ export declare const getEnvOrDefault: (envName: string, def: number) => number;
4
+ export declare const getEnvOrBool: (envName: string) => boolean;
5
+ export declare const removeEmpty: (obj: any) => {};
6
+ export declare const sendClientEvent: (eventsClient: EventsClient | null, event: ClientEvent) => void;
package/dist/util.js ADDED
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.sendClientEvent = exports.removeEmpty = exports.getEnvOrBool = exports.getEnvOrDefault = void 0;
4
+ const getEnvOrDefault = (envName, def) => process.env[envName] ? parseInt(process.env[envName] || "") : def;
5
+ exports.getEnvOrDefault = getEnvOrDefault;
6
+ const getEnvOrBool = (envName) => process.env[envName]
7
+ ? (process.env[envName] || "false").toLowerCase() === "true"
8
+ : false;
9
+ exports.getEnvOrBool = getEnvOrBool;
10
+ const removeEmpty = (obj) => {
11
+ const newObj = {};
12
+ Object.keys(obj).forEach((key) => {
13
+ if (obj[key] === Object(obj[key]))
14
+ newObj[key] = (0, exports.removeEmpty)(obj[key]);
15
+ else if (obj[key] !== undefined)
16
+ newObj[key] = obj[key];
17
+ });
18
+ return newObj;
19
+ };
20
+ exports.removeEmpty = removeEmpty;
21
+ const sendClientEvent = (eventsClient, event) => {
22
+ if (eventsClient) {
23
+ eventsClient.send(event);
24
+ }
25
+ };
26
+ exports.sendClientEvent = sendClientEvent;
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ import { ServerConfig } from "./types";
3
+ export declare function voice(config: ServerConfig): void;
package/dist/voice.js ADDED
@@ -0,0 +1,154 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
4
+ if (k2 === undefined) k2 = k;
5
+ var desc = Object.getOwnPropertyDescriptor(m, k);
6
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
7
+ desc = { enumerable: true, get: function() { return m[k]; } };
8
+ }
9
+ Object.defineProperty(o, k2, desc);
10
+ }) : (function(o, m, k, k2) {
11
+ if (k2 === undefined) k2 = k;
12
+ o[k2] = m[k];
13
+ }));
14
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
15
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
16
+ }) : function(o, v) {
17
+ o["default"] = v;
18
+ });
19
+ var __importStar = (this && this.__importStar) || function (mod) {
20
+ if (mod && mod.__esModule) return mod;
21
+ var result = {};
22
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
23
+ __setModuleDefault(result, mod);
24
+ return result;
25
+ };
26
+ var __importDefault = (this && this.__importDefault) || function (mod) {
27
+ return (mod && mod.__esModule) ? mod : { "default": mod };
28
+ };
29
+ Object.defineProperty(exports, "__esModule", { value: true });
30
+ exports.voice = void 0;
31
+ /* eslint-disable require-jsdoc */
32
+ /*
33
+ * Copyright (C) 2023 by Fonoster Inc (https://fonoster.com)
34
+ * http://github.com/fonoster/rox
35
+ *
36
+ * This file is part of Rox AI
37
+ *
38
+ * Licensed under the MIT License (the "License");
39
+ * you may not use this file except in compliance with
40
+ * the License. You may obtain a copy of the License at
41
+ *
42
+ * https://opensource.org/licenses/MIT
43
+ *
44
+ * Unless required by applicable law or agreed to in writing, software
45
+ * distributed under the License is distributed on an "AS IS" BASIS,
46
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
47
+ * See the License for the specific language governing permissions and
48
+ * limitations under the License.
49
+ */
50
+ const types_1 = require("./events/types");
51
+ const voice_1 = require("@fonoster/voice");
52
+ const cerebro_1 = require("./cerebro");
53
+ const server_1 = require("./events/server");
54
+ const nanoid_1 = require("nanoid");
55
+ const engines_1 = require("./intents/engines");
56
+ const util_1 = require("./util");
57
+ const logger_1 = __importStar(require("@fonoster/logger"));
58
+ const apps_1 = __importDefault(require("@fonoster/apps"));
59
+ const secrets_1 = __importDefault(require("@fonoster/secrets"));
60
+ const googletts_1 = __importDefault(require("@fonoster/googletts"));
61
+ const googleasr_1 = __importDefault(require("@fonoster/googleasr"));
62
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
63
+ const { version } = require("../../lerna.json");
64
+ function voice(config) {
65
+ logger_1.default.info(`autopilot v${version}`);
66
+ const voiceServer = new voice_1.VoiceServer({});
67
+ if (config.eventsServerEnabled)
68
+ server_1.eventsServer.start();
69
+ logger_1.default.verbose("events server enabled = " + config.eventsServerEnabled);
70
+ voiceServer.listen(async (voiceRequest, voiceResponse) => {
71
+ logger_1.default.verbose(`new request [sessionId: ${voiceRequest.sessionId}]`, {
72
+ voiceRequest
73
+ });
74
+ try {
75
+ if (!voiceRequest.appRef)
76
+ throw new Error("invalid voice request: missing appRef");
77
+ // If set, we overwrite the configuration with the values obtain from the webhook
78
+ const serviceCredentials = {
79
+ accessKeyId: voiceRequest.accessKeyId,
80
+ accessKeySecret: voiceRequest.sessionToken
81
+ };
82
+ const apps = new apps_1.default(serviceCredentials);
83
+ const secrets = new secrets_1.default(serviceCredentials);
84
+ const app = await apps.getApp(voiceRequest.appRef);
85
+ logger_1.default.verbose(`requested app [ref: ${app.ref}]`, { app });
86
+ const ieSecret = await secrets.getSecret(app.intentsEngineConfig.secretName);
87
+ const intentsEngine = (0, engines_1.getIntentsEngine)(app)(JSON.parse(ieSecret.secret));
88
+ intentsEngine?.setProjectId(app.intentsEngineConfig.projectId);
89
+ const voiceConfig = {
90
+ name: app.speechConfig.voice,
91
+ playbackId: (0, nanoid_1.nanoid)()
92
+ };
93
+ const speechSecret = await secrets.getSecret(app.speechConfig.secretName);
94
+ const speechCredentials = {
95
+ private_key: JSON.parse(speechSecret.secret).private_key,
96
+ client_email: JSON.parse(speechSecret.secret).client_email
97
+ };
98
+ voiceResponse.use(new googletts_1.default({
99
+ credentials: speechCredentials,
100
+ languageCode: config.defaultLanguageCode,
101
+ path: config.fileRetentionPolicyDirectory
102
+ }));
103
+ voiceResponse.use(new googleasr_1.default({
104
+ credentials: speechCredentials,
105
+ languageCode: config.defaultLanguageCode
106
+ }));
107
+ await voiceResponse.answer();
108
+ const eventsClient = app.enableEvents && config.eventsServerEnabled
109
+ ? server_1.eventsServer.getConnection(voiceRequest.callerNumber)
110
+ : null;
111
+ (0, util_1.sendClientEvent)(eventsClient, {
112
+ eventName: types_1.CLIENT_EVENTS.ANSWERED
113
+ });
114
+ if (app.initialDtmf)
115
+ await voiceResponse.dtmf({ dtmf: app.initialDtmf });
116
+ if (app.intentsEngineConfig.welcomeIntentId &&
117
+ intentsEngine.findIntentWithEvent) {
118
+ const response = await intentsEngine.findIntentWithEvent(app.intentsEngineConfig.welcomeIntentId, {
119
+ telephony: {
120
+ caller_id: voiceRequest.callerNumber
121
+ }
122
+ });
123
+ if (response.effects.length > 0) {
124
+ await voiceResponse.say(response.effects[0].parameters["response"], voiceConfig);
125
+ }
126
+ else {
127
+ logger_1.default.warn(`no effects found for welcome intent: trigger '${app.intentsEngineConfig.welcomeIntentId}'`);
128
+ }
129
+ }
130
+ const cerebro = new cerebro_1.Cerebro({
131
+ voiceRequest,
132
+ voiceResponse,
133
+ eventsClient,
134
+ voiceConfig,
135
+ intentsEngine,
136
+ activationIntentId: app.activationIntentId,
137
+ activationTimeout: app.activationTimeout,
138
+ transfer: app.transferConfig,
139
+ alternativeLanguageCode: app.speechConfig.languageCode
140
+ });
141
+ // Open for bussiness
142
+ await cerebro.wake();
143
+ }
144
+ catch (e) {
145
+ (0, logger_1.ulogger)({
146
+ accessKeyId: voiceRequest.accessKeyId,
147
+ eventType: logger_1.ULogType.APP,
148
+ level: "error",
149
+ message: e.message
150
+ });
151
+ }
152
+ });
153
+ }
154
+ exports.voice = voice;
package/package.json ADDED
@@ -0,0 +1,41 @@
1
+ {
2
+ "name": "@fonoster/autopilot",
3
+ "version": "0.4.15",
4
+ "license": "MIT",
5
+ "main": "dist/index",
6
+ "types": "dist/index",
7
+ "bin": {
8
+ "run": "./bin/run",
9
+ "rox": "./bin/run"
10
+ },
11
+ "scripts": {
12
+ "build": "tsc --build ./tsconfig.json"
13
+ },
14
+ "dependencies": {
15
+ "@fonoster/apps": "^0.4.15",
16
+ "@fonoster/googleasr": "^0.4.15",
17
+ "@fonoster/googletts": "^0.4.15",
18
+ "@fonoster/logger": "^0.4.15",
19
+ "@fonoster/secrets": "^0.4.15",
20
+ "@fonoster/voice": "^0.4.15",
21
+ "@google-cloud/dialogflow": "^4.3.1",
22
+ "@google-cloud/dialogflow-cx": "^2.13.0",
23
+ "date-fns": "^2.29.3",
24
+ "nanoid": "^3.1.25",
25
+ "node-cron": "^3.0.2",
26
+ "pb-util": "^1.0.2",
27
+ "uuid": "^8.3.2",
28
+ "ws": "^8.1.0"
29
+ },
30
+ "devDependencies": {
31
+ "@types/ws": "^7.4.7"
32
+ },
33
+ "files": [
34
+ "/bin",
35
+ "/dist"
36
+ ],
37
+ "publishConfig": {
38
+ "access": "public"
39
+ },
40
+ "gitHead": "f9f898c4f174662564976e5c392bb8549cd53529"
41
+ }