@fonoster/autopilot 0.9.28 → 0.9.32

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.
package/dist/Autopilot.js CHANGED
@@ -91,7 +91,11 @@ class Autopilot {
91
91
  const stream = await voice.sgather();
92
92
  stream.onData((payload) => {
93
93
  const { speech, responseTime } = payload;
94
- logger.verbose("received speech result", { speech, responseTime });
94
+ logger.verbose("received speech result", {
95
+ event: "SPEECH_RESULT",
96
+ speech,
97
+ responseTime
98
+ });
95
99
  if (payload.speech) {
96
100
  this.actor.send({
97
101
  type: "SPEECH_RESULT",
@@ -38,8 +38,7 @@ exports.doProcessUserRequest = (0, xstate_1.fromPromise)(async ({ input }) => {
38
38
  return;
39
39
  }
40
40
  else if (response.type === "hangup") {
41
- const message = context.goodbyeMessage;
42
- await context.voice.say(message);
41
+ await context.voice.say(context.goodbyeMessage);
43
42
  await context.voice.hangup();
44
43
  return;
45
44
  }
@@ -47,12 +46,11 @@ exports.doProcessUserRequest = (0, xstate_1.fromPromise)(async ({ input }) => {
47
46
  logger.verbose("transferring call to a number in the PSTN", {
48
47
  phoneNumber: context.transferPhoneNumber
49
48
  });
50
- const message = context.transferMessage;
51
- await context.voice.say(message);
49
+ await context.voice.say(context.transferMessage);
52
50
  await context.voice.stopStreams();
53
51
  await context.voice.transfer(context.transferPhoneNumber, {
54
52
  record: true,
55
- timeout: 30
53
+ timeout: context.transferTimeout / 1000
56
54
  });
57
55
  return;
58
56
  }
@@ -16,25 +16,33 @@
16
16
  * See the License for the specific language governing permissions and
17
17
  * limitations under the License.
18
18
  */
19
+ import { ConversationSettings } from "../assistants";
20
+ import { LanguageModel } from "../models";
21
+ import { Voice } from "../voice";
19
22
  declare const context: ({ input }: {
20
- input: any;
23
+ input: {
24
+ voice: Voice;
25
+ languageModel: LanguageModel;
26
+ conversationSettings: ConversationSettings;
27
+ };
21
28
  }) => {
22
- sessionRef: any;
23
- voice: any;
24
- languageModel: any;
29
+ sessionRef: string;
30
+ voice: Voice;
31
+ languageModel: LanguageModel;
25
32
  speechBuffer: string;
26
- firstMessage: any;
27
- goodbyeMessage: any;
28
- transferMessage: any;
29
- transferPhoneNumber: any;
30
- systemErrorMessage: any;
31
- idleMessage: any;
32
- idleTimeout: any;
33
- maxIdleTimeoutCount: any;
33
+ firstMessage: string;
34
+ goodbyeMessage: string;
35
+ transferMessage: string;
36
+ transferPhoneNumber: string;
37
+ transferTimeout: number;
38
+ systemErrorMessage: string;
39
+ idleMessage: string;
40
+ idleTimeout: number;
41
+ maxIdleTimeoutCount: number;
34
42
  idleTimeoutCount: number;
35
- maxSpeechWaitTimeout: any;
43
+ maxSpeechWaitTimeout: number;
36
44
  isSpeaking: boolean;
37
45
  sessionStartTime: number;
38
- maxSessionDuration: any;
46
+ maxSessionDuration: number;
39
47
  };
40
48
  export { context };
@@ -1,24 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.context = void 0;
4
- /**
5
- * Copyright (C) 2025 by Fonoster Inc (https://fonoster.com)
6
- * http://github.com/fonoster/fonoster
7
- *
8
- * This file is part of Fonoster
9
- *
10
- * Licensed under the MIT License (the "License");
11
- * you may not use this file except in compliance with
12
- * the License. You may obtain a copy of the License at
13
- *
14
- * https://opensource.org/licenses/MIT
15
- *
16
- * Unless required by applicable law or agreed to in writing, software
17
- * distributed under the License is distributed on an "AS IS" BASIS,
18
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19
- * See the License for the specific language governing permissions and
20
- * limitations under the License.
21
- */
22
4
  const context = ({ input }) => ({
23
5
  sessionRef: input.voice.sessionRef,
24
6
  voice: input.voice,
@@ -28,10 +10,11 @@ const context = ({ input }) => ({
28
10
  goodbyeMessage: input.conversationSettings.goodbyeMessage,
29
11
  transferMessage: input.conversationSettings.transferOptions?.message,
30
12
  transferPhoneNumber: input.conversationSettings.transferOptions?.phoneNumber,
13
+ transferTimeout: input.conversationSettings.transferOptions?.timeout,
31
14
  systemErrorMessage: input.conversationSettings.systemErrorMessage,
32
- idleMessage: input.conversationSettings.idleOptions?.message || "",
33
- idleTimeout: input.conversationSettings.idleOptions?.timeout || 10000,
34
- maxIdleTimeoutCount: input.conversationSettings.idleOptions?.maxTimeoutCount || 3,
15
+ idleMessage: input.conversationSettings.idleOptions.message,
16
+ idleTimeout: input.conversationSettings.idleOptions.timeout,
17
+ maxIdleTimeoutCount: input.conversationSettings.idleOptions.maxTimeoutCount,
35
18
  idleTimeoutCount: 0,
36
19
  maxSpeechWaitTimeout: input.conversationSettings.maxSpeechWaitTimeout,
37
20
  isSpeaking: false,
@@ -70,32 +70,37 @@ declare const machine: import("xstate").StateMachine<any, import("./types").Auto
70
70
  type: "hasSpeechResult";
71
71
  params: unknown;
72
72
  };
73
- }>, "IDLE_TIMEOUT" | "MAX_SPEECH_WAIT_TIMEOUT" | "SESSION_TIMEOUT", "hangup" | "greeting" | "idle" | "listeningToUser" | "transitioningToIdle" | "processingUserRequest" | "waitingForSpeechTimeout", string, {
73
+ }>, "IDLE_TIMEOUT" | "MAX_SPEECH_WAIT_TIMEOUT" | "SESSION_TIMEOUT", "hangup" | "greeting" | "idle" | "listeningToUser" | "transitioningToIdle" | "waitingForSpeechTimeout" | "processingUserRequest", string, {
74
74
  conversationSettings: import("..").ConversationSettings;
75
75
  languageModel: import("..").LanguageModel;
76
76
  voice: import("..").Voice;
77
77
  }, {}, import("xstate").EventObject, import("xstate").MetaObject, {
78
- /** @xstate-layout N4IgpgJg5mDOIC5QDMB2BBAkgOigJzDABcBLVKAYgG0AGAXUVAAcB7WE0l1RkAD0QCMADgHYAzAHYAnADYJYgExCaMmSJkAaEAE9EUsQFZsUiaoUGpAhQsMSAvna1os2EhAA2YCgGUACgFF-AGEACQB9bwAVdAAlSNoGJBBWdk5uJP4EAQMAFiFxHLkJbLEaAxkBCS1dLIEcnPFFZSkpHIklQwcnDBw3Tx8A4PCY-28AVQAZePoeFI4SLh5MyzFsBUrzHJMrAxtqxAkcoxyFHMqt0pbsrpBnXo8vXlgiAEMiMGwX5He8AApMAAiE38YUimAAsv4APJjSIASgod1cDwSszY80WGUQMgMRgEUhokgMYjyMlKAn2WQUJmwEnK23a5jEQhuSL6j2ebw+Xx+-yBILBkJh8MRPWRnioAkSzHRaSWgjqNGwQnkNAU0iEYi1VR0emy2Bk+iOpU1bRkrLFRDwL1QqQWqDIUEiLEwD2oMySczlWIQygUtOyORohX0uLJlKkBlE7WJNEqZJVKgtLncJGeYAd5GdY1gYDwA0CoTC-gAcgDUZ7Zfb5VkNdgDMUVAZTYGDJSxDjjMShLGJNI+wJzY5bmLU+nM06WDm8wWhsWy5Lpckq5jQJkBGVRKdTKozhZLO2o8qtQY44dynSysmcGP3hPs7n835C8NRpNpkuvdWfZUpPkGwIVjWJquQKBGg7GB2ZQ0CYYhSDY17YAA7i88zkAAYiweDeEwhAAMYABaRCQAC2YAsAArkQs5FlEsQfmidqrnwggduIzYKCopw0DQdLlJSuISNgbRBpY1LrKcOSIShaFQJh2G4WAhHEWRlHUc+c4jOMUwVjKTHpGuiBiHU9YqFs6y8SqFSUiI4jWJYBKamSJIGNJqGkBhWE4fhRGkeRVEUE8rzvJ83x5r84LoAAGhEgxFgA6lgkSghC0KwgiSIyR5cleYpyl+WpunLvpNZ5A0Hb1AmwaSZS5iiLsWpklYwg9hILLDpl7mOvJ3lKb5qkBUFXKhbykUxRpCVJSlQrpaKLhZd1uU+Sp-lEIujEYgZLEIKeeK4lsgFtW1pRtrqO0CKswZRsGZJBsIQ7dC4TB4CweFwOw5DTngMRgAAjhRcDURAXAfGQABuLAANYfEiz2ve9jpfT9-2Awg4OvW89oJEVX7MeuuwyNgarNpU8akqdNRWPUxg8TQQjrDI9lSR1Ypw29sAfVASN-QDzw0eEdFxDjK5beuPYNJqhyWGamp05SchGHIvEXUIhrGQIDjDqgLAQHAPB3Bt3qGQgAC0F2E8SphCH+GqHEolIm0YLTO-T1u5Gq9SIfghDZYb37GybQj-pIag2zbJxCBGCiE200ikko9TyIh7J+3jiANv6FSDtSFSJ4SUcx328HBoSdKdCzLhWja+mOs6rqeKnot6kY5JRpIzIkh2EZbMq8GM8ISjwQ2iG3hmtdTo+jc1tkEEcXBKzWzIvGUhIKjGNS0iAcyZ6uRXOALZ5CnLQVVFTz60fYC1JxFzxOL8Wd8+0qcViEtH8inIhBE2lAFFMGfxuARMiIP8eQ6Z00MJHM6F1rDCVMDBOkcCVAPRHE9F67NObcxRs8f+21rBHiOvBQcZwWianlgScQJho7kkULkXeDggA */
78
+ /** @xstate-layout N4IgpgJg5mDOIC5QDMB2BBAkgOigJzDABcBLVKAYgG0AGAXUVAAcB7WE0l1RkAD0QCMADgHYAzAHYAnADYJYgExCaMmSJkAaEAE9EUsQFZsUiaoUGpAhQsMSAvna1os2EhAA2YCgGUACgFF-AGEACQB9bwAVdAAlSNoGJBBWdk5uJP4EKRoJbCEDGwklABZ5OQktXQQJIQVjFUkJGmFpYoUHJwwcN08KXlgiAEMiMGxB5BG8AApMABEAGX8wyMwAWX8AeQBVSIBKCmdujzAEnhSOEi4eTINi4uwaYuyisVkBYubKwQUJUSEpKQGGiSAwCAyKIQdECHVzHPoDYajcaTGYLJYrdbbPYHLqwzxUASJZhsC5XDKIV7YNQmGrFAQ0BQ0AwyMRfBACYRSKnFArWWS1O4GKEwoh4QaoVKXVBkKCRFiYOGnJLnNLXClCe6yRQyAwaoRiYpiR5sjk0LlNGpSBQc6TSYW49wkAZgaXkOVbWBgPA+ALBcIxfzeLbzeL0M4k1XkhAyYpCPIsqTFBOyEzFNliGQ0YwmW4KbKPd7A+0uR3O12ylger3woYjMYTL2oxbLNabHb7GGlkbl92evBK4mSsmgTICV73cy3ZoCGTCSQKE00IRxmhM5p5pNvGTFnAAd0GF3IADEWHhvExCABjAAWkRIAFswCwAK5EH2BUIRaJxAfJCNStV2Qke55FTMQMykZQ8zZAwCmwAwmgUO4eXBQxIUcaFcX3Q8oBPM8LzAG870fF8336WskQbaZVnQAANCJfU-AB1LBIhbTF2xxFxsNIY9T3PK9bwfJ9X1-FUAKjWN7gzO4WWUNo7jZcxRAKcCWSsYR8hqHdsCYPAWEvOB2HIKs8BiMAAEdnzgN8IC4UYyAANxYABrUYYT0gyjJlUzzKsmyECcgzhilBIxP-Yc+EEekZAeSQjVqJRlwzNlZDqK0rUNQEZBMMEdM8wzYGMqBfMs6yBnfP0v1iUMiT-Id0hHaL-ji2QCjBK0bE0HREBqURshkawnjUCxtyhVAWAgOAeEOcMGsAgBaDkjAUHKimBK0l1UIQTRjB4bEMdS6RERMdPwQheKgObSUaqKEAWuRsFWkxGVeRkhG21LVuwUppEZD4QUMHSejAa7IyahAELqWcZzzWc7iaVkeqyb7fs2gGJHBIUMJFMUJRumU5QVTwwYkiHsng2RHkeW5BtjAQTXpONGRqHVINjUF2hxh0nW7QnKz7UnIsyIQmjyAR9CZMQZ0MW4YNnPJlCXCCxHydDOm4g9LrwgTCKEkjXyF27R0e2cPqUTNVqTNNkdec0kKsHLJBizGdOvcUoGfJgjcAj6-l1W5fmOukDBNPM6kdnIniebJDXy-TCuK0r-IGH2ozBcFxBh1mgQOmDRcV1cNQzcErXsBw7CAA */
79
79
  readonly context: ({ input }: {
80
- input: any;
80
+ input: {
81
+ voice: import("..").Voice;
82
+ languageModel: import("..").LanguageModel;
83
+ conversationSettings: import("..").ConversationSettings;
84
+ };
81
85
  }) => {
82
- sessionRef: any;
83
- voice: any;
84
- languageModel: any;
86
+ sessionRef: string;
87
+ voice: import("..").Voice;
88
+ languageModel: import("..").LanguageModel;
85
89
  speechBuffer: string;
86
- firstMessage: any;
87
- goodbyeMessage: any;
88
- transferMessage: any;
89
- transferPhoneNumber: any;
90
- systemErrorMessage: any;
91
- idleMessage: any;
92
- idleTimeout: any;
93
- maxIdleTimeoutCount: any;
90
+ firstMessage: string;
91
+ goodbyeMessage: string;
92
+ transferMessage: string;
93
+ transferPhoneNumber: string;
94
+ transferTimeout: number;
95
+ systemErrorMessage: string;
96
+ idleMessage: string;
97
+ idleTimeout: number;
98
+ maxIdleTimeoutCount: number;
94
99
  idleTimeoutCount: number;
95
- maxSpeechWaitTimeout: any;
100
+ maxSpeechWaitTimeout: number;
96
101
  isSpeaking: boolean;
97
102
  sessionStartTime: number;
98
- maxSessionDuration: any;
103
+ maxSessionDuration: number;
99
104
  };
100
105
  readonly id: "fnAI";
101
106
  readonly initial: "greeting";
@@ -110,21 +115,16 @@ declare const machine: import("xstate").StateMachine<any, import("./types").Auto
110
115
  };
111
116
  };
112
117
  readonly idle: {
113
- readonly entry: {
118
+ readonly entry: readonly [{
114
119
  readonly type: "cleanSpeech";
115
- };
120
+ }, {
121
+ readonly type: "setSpeakingDone";
122
+ }];
116
123
  readonly on: {
117
124
  readonly SPEECH_START: {
118
125
  readonly target: "listeningToUser";
119
126
  readonly description: "Event from VAD system.";
120
127
  };
121
- readonly SPEECH_RESULT: {
122
- readonly target: "listeningToUser";
123
- readonly description: "Detected speech before SPEECH_START event.";
124
- readonly actions: readonly [{
125
- readonly type: "appendSpeech";
126
- }];
127
- };
128
128
  };
129
129
  readonly after: {
130
130
  readonly IDLE_TIMEOUT: readonly [{
@@ -160,32 +160,23 @@ declare const machine: import("xstate").StateMachine<any, import("./types").Auto
160
160
  readonly type: "setSpeaking";
161
161
  }];
162
162
  readonly on: {
163
- readonly SPEECH_END: readonly [{
164
- readonly target: "processingUserRequest";
165
- readonly guard: "hasSpeechResult";
166
- readonly actions: readonly [{
167
- readonly type: "setSpeakingDone";
168
- }];
169
- readonly description: "Process the request immediately since we already speech.";
170
- }, {
163
+ readonly SPEECH_RESULT: {
171
164
  readonly target: "waitingForSpeechTimeout";
172
- readonly guard: import("xstate/dist/declarations/src/guards").GuardPredicate<any, {
173
- type: "SPEECH_END";
174
- }, unknown, {
175
- type: "hasSpeechResult";
176
- params: undefined;
177
- }>;
178
- readonly actions: readonly [{
179
- readonly type: "setSpeakingDone";
180
- }];
181
- readonly description: "Wait for more speech since we don't have any speech yet.";
182
- }];
183
- readonly SPEECH_RESULT: readonly [{
184
165
  readonly actions: {
185
166
  readonly type: "appendSpeech";
186
167
  };
187
- readonly guard: "isSpeaking";
188
- readonly description: "The user is still speaking. With only want to append the speech.";
168
+ readonly description: "Append final speech and process the request.";
169
+ readonly reenter: true;
170
+ };
171
+ };
172
+ readonly after: {
173
+ readonly IDLE_TIMEOUT: readonly [{
174
+ readonly target: "transitioningToIdle";
175
+ readonly actions: readonly [{
176
+ readonly type: "increaseIdleTimeoutCount";
177
+ }, {
178
+ readonly type: "announceIdleTimeout";
179
+ }];
189
180
  }];
190
181
  };
191
182
  };
@@ -195,23 +186,13 @@ declare const machine: import("xstate").StateMachine<any, import("./types").Auto
195
186
  readonly target: "listeningToUser";
196
187
  readonly description: "User started speaking again.";
197
188
  };
198
- readonly SPEECH_RESULT: {
199
- readonly target: "processingUserRequest";
200
- readonly actions: {
201
- readonly type: "appendSpeech";
202
- };
203
- readonly description: "Append final speech and process the request.";
204
- };
205
189
  };
206
190
  readonly after: {
207
- readonly MAX_SPEECH_WAIT_TIMEOUT: readonly [{
191
+ readonly MAX_SPEECH_WAIT_TIMEOUT: {
208
192
  readonly target: "processingUserRequest";
209
- readonly description: "Proceed to process the request as we have speech and the user is not speaking.";
210
- readonly guard: "hasSpeechResult";
211
- }, {
212
- readonly target: "idle";
213
- readonly description: "We have no speech and the user is not speaking. Return to idle.";
214
- }];
193
+ readonly description: "This will give the person time to breathe and speak again.";
194
+ readonly reenter: true;
195
+ };
215
196
  };
216
197
  };
217
198
  readonly hangup: {
@@ -23,7 +23,7 @@ const xstate_1 = require("xstate");
23
23
  const context_1 = require("./context");
24
24
  const setup_1 = require("./setup");
25
25
  const machine = setup_1.machineSetup.createMachine({
26
- /** @xstate-layout N4IgpgJg5mDOIC5QDMB2BBAkgOigJzDABcBLVKAYgG0AGAXUVAAcB7WE0l1RkAD0QCMADgHYAzAHYAnADYJYgExCaMmSJkAaEAE9EUsQFZsUiaoUGpAhQsMSAvna1os2EhAA2YCgGUACgFF-AGEACQB9bwAVdAAlSNoGJBBWdk5uJP4EAQMAFiFxHLkJbLEaAxkBCS1dLIEcnPFFZSkpHIklQwcnDBw3Tx8A4PCY-28AVQAZePoeFI4SLh5MyzFsBUrzHJMrAxtqxAkcoxyFHMqt0pbsrpBnXo8vXlgiAEMiMGwX5He8AApMAAiE38YUimAAsv4APJjSIASgod1cDwSszY80WGUQMgMRgEUhokgMYjyMlKAn2WQUJmwEnK23a5jEQhuSL6j2ebw+Xx+-yBILBkJh8MRPWRnioAkSzHRaSWgjqNGwQnkNAU0iEYi1VR0emy2Bk+iOpU1bRkrLFRDwL1QqQWqDIUEiLEwD2oMySczlWIQygUtOyORohX0uLJlKkBlE7WJNEqZJVKgtLncJGeYAd5GdY1gYDwA0CoTC-gAcgDUZ7Zfb5VkNdgDMUVAZTYGDJSxDjjMShLGJNI+wJzY5bmLU+nM06WDm8wWhsWy5Lpckq5jQJkBGVRKdTKozhZLO2o8qtQY44dynSysmcGP3hPs7n835C8NRpNpkuvdWfZUpPkGwIVjWJquQKBGg7GB2ZQ0CYYhSDY17YAA7i88zkAAYiweDeEwhAAMYABaRCQAC2YAsAArkQs5FlEsQfmidqrnwggduIzYKCopw0DQdLlJSuISNgbRBpY1LrKcOSIShaFQJh2G4WAhHEWRlHUc+c4jOMUwVjKTHpGuiBiHU9YqFs6y8SqFSUiI4jWJYBKamSJIGNJqGkBhWE4fhRGkeRVEUE8rzvJ83x5r84LoAAGhEgxFgA6lgkSghC0KwgiSIyR5cleYpyl+WpunLvpNZ5A0Hb1AmwaSZS5iiLsWpklYwg9hILLDpl7mOvJ3lKb5qkBUFXKhbykUxRpCVJSlQrpaKLhZd1uU+Sp-lEIujEYgZLEIKeeK4lsgFtW1pRtrqO0CKswZRsGZJBsIQ7dC4TB4CweFwOw5DTngMRgAAjhRcDURAXAfGQABuLAANYfEiz2ve9jpfT9-2Awg4OvW89oJEVX7MeuuwyNgarNpU8akqdNRWPUxg8TQQjrDI9lSR1Ypw29sAfVASN-QDzw0eEdFxDjK5beuPYNJqhyWGamp05SchGHIvEXUIhrGQIDjDqgLAQHAPB3Bt3qGQgAC0F2E8SphCH+GqHEolIm0YLTO-T1u5Gq9SIfghDZYb37GybQj-pIag2zbJxCBGCiE200ikko9TyIh7J+3jiANv6FSDtSFSJ4SUcx328HBoSdKdCzLhWja+mOs6rqeKnot6kY5JRpIzIkh2EZbMq8GM8ISjwQ2iG3hmtdTo+jc1tkEEcXBKzWzIvGUhIKjGNS0iAcyZ6uRXOALZ5CnLQVVFTz60fYC1JxFzxOL8Wd8+0qcViEtH8inIhBE2lAFFMGfxuARMiIP8eQ6Z00MJHM6F1rDCVMDBOkcCVAPRHE9F67NObcxRs8f+21rBHiOvBQcZwWianlgScQJho7kkULkXeDggA */
26
+ /** @xstate-layout N4IgpgJg5mDOIC5QDMB2BBAkgOigJzDABcBLVKAYgG0AGAXUVAAcB7WE0l1RkAD0QCMADgHYAzAHYAnADYJYgExCaMmSJkAaEAE9EUsQFZsUiaoUGpAhQsMSAvna1os2EhAA2YCgGUACgFF-AGEACQB9bwAVdAAlSNoGJBBWdk5uJP4EKRoJbCEDGwklABZ5OQktXQQJIQVjFUkJGmFpYoUHJwwcN08KXlgiAEMiMGxB5BG8AApMABEAGX8wyMwAWX8AeQBVSIBKCmdujzAEnhSOEi4eTINi4uwaYuyisVkBYubKwQUJUSEpKQGGiSAwCAyKIQdECHVzHPoDYajcaTGYLJYrdbbPYHLqwzxUASJZhsC5XDKIV7YNQmGrFAQ0BQ0AwyMRfBACYRSKnFArWWS1O4GKEwoh4QaoVKXVBkKCRFiYOGnJLnNLXClCe6yRQyAwaoRiYpiR5sjk0LlNGpSBQc6TSYW49wkAZgaXkOVbWBgPA+ALBcIxfzeLbzeL0M4k1XkhAyYpCPIsqTFBOyEzFNliGQ0YwmW4KbKPd7A+0uR3O12ylger3woYjMYTL2oxbLNabHb7GGlkbl92evBK4mSsmgTICV73cy3ZoCGTCSQKE00IRxmhM5p5pNvGTFnAAd0GF3IADEWHhvExCABjAAWkRIAFswCwAK5EH2BUIRaJxAfJCNStV2Qke55FTMQMykZQ8zZAwCmwAwmgUO4eXBQxIUcaFcX3Q8oBPM8LzAG870fF8336WskQbaZVnQAANCJfU-AB1LBIhbTF2xxFxsNIY9T3PK9bwfJ9X1-FUAKjWN7gzO4WWUNo7jZcxRAKcCWSsYR8hqHdsCYPAWEvOB2HIKs8BiMAAEdnzgN8IC4UYyAANxYABrUYYT0gyjJlUzzKsmyECcgzhilBIxP-Yc+EEekZAeSQjVqJRlwzNlZDqK0rUNQEZBMMEdM8wzYGMqBfMs6yBnfP0v1iUMiT-Id0hHaL-ji2QCjBK0bE0HREBqURshkawnjUCxtyhVAWAgOAeEOcMGsAgBaDkjAUHKimBK0l1UIQTRjB4bEMdS6RERMdPwQheKgObSUaqKEAWuRsFWkxGVeRkhG21LVuwUppEZD4QUMHSejAa7IyahAELqWcZzzWc7iaVkeqyb7fs2gGJHBIUMJFMUJRumU5QVTwwYkiHsng2RHkeW5BtjAQTXpONGRqHVINjUF2hxh0nW7QnKz7UnIsyIQmjyAR9CZMQZ0MW4YNnPJlCXCCxHydDOm4g9LrwgTCKEkjXyF27R0e2cPqUTNVqTNNkdec0kKsHLJBizGdOvcUoGfJgjcAj6-l1W5fmOukDBNPM6kdnIniebJDXy-TCuK0r-IGH2ozBcFxBh1mgQOmDRcV1cNQzcErXsBw7CAA */
27
27
  context: context_1.context,
28
28
  id: "fnAI",
29
29
  initial: "greeting",
@@ -38,16 +38,11 @@ const machine = setup_1.machineSetup.createMachine({
38
38
  }
39
39
  },
40
40
  idle: {
41
- entry: { type: "cleanSpeech" },
41
+ entry: [{ type: "cleanSpeech" }, { type: "setSpeakingDone" }],
42
42
  on: {
43
43
  SPEECH_START: {
44
44
  target: "listeningToUser",
45
45
  description: "Event from VAD system."
46
- },
47
- SPEECH_RESULT: {
48
- target: "listeningToUser",
49
- description: "Detected speech before SPEECH_START event.",
50
- actions: [{ type: "appendSpeech" }]
51
46
  }
52
47
  },
53
48
  after: {
@@ -55,7 +50,7 @@ const machine = setup_1.machineSetup.createMachine({
55
50
  {
56
51
  target: "hangup",
57
52
  actions: { type: "goodbye" },
58
- guard: (0, xstate_1.and)(["idleTimeoutCountExceedsMax", (0, xstate_1.not)("isSpeaking")])
53
+ guard: (0, xstate_1.and)(["idleTimeoutCountExceedsMax"])
59
54
  },
60
55
  {
61
56
  target: "transitioningToIdle",
@@ -82,25 +77,23 @@ const machine = setup_1.machineSetup.createMachine({
82
77
  { type: "setSpeaking" }
83
78
  ],
84
79
  on: {
85
- SPEECH_END: [
86
- {
87
- target: "processingUserRequest",
88
- guard: "hasSpeechResult",
89
- actions: [{ type: "setSpeakingDone" }],
90
- description: "Process the request immediately since we already speech."
80
+ SPEECH_RESULT: {
81
+ target: "waitingForSpeechTimeout",
82
+ actions: {
83
+ type: "appendSpeech"
91
84
  },
85
+ description: "Append final speech and process the request.",
86
+ reenter: true
87
+ }
88
+ },
89
+ after: {
90
+ IDLE_TIMEOUT: [
92
91
  {
93
- target: "waitingForSpeechTimeout",
94
- guard: (0, xstate_1.not)("hasSpeechResult"),
95
- actions: [{ type: "setSpeakingDone" }],
96
- description: "Wait for more speech since we don't have any speech yet."
97
- }
98
- ],
99
- SPEECH_RESULT: [
100
- {
101
- actions: { type: "appendSpeech" },
102
- guard: "isSpeaking",
103
- description: "The user is still speaking. With only want to append the speech."
92
+ target: "transitioningToIdle",
93
+ actions: [
94
+ { type: "increaseIdleTimeoutCount" },
95
+ { type: "announceIdleTimeout" }
96
+ ]
104
97
  }
105
98
  ]
106
99
  }
@@ -110,27 +103,14 @@ const machine = setup_1.machineSetup.createMachine({
110
103
  SPEECH_START: {
111
104
  target: "listeningToUser",
112
105
  description: "User started speaking again."
113
- },
114
- SPEECH_RESULT: {
115
- target: "processingUserRequest",
116
- actions: {
117
- type: "appendSpeech"
118
- },
119
- description: "Append final speech and process the request."
120
106
  }
121
107
  },
122
108
  after: {
123
- MAX_SPEECH_WAIT_TIMEOUT: [
124
- {
125
- target: "processingUserRequest",
126
- description: "Proceed to process the request as we have speech and the user is not speaking.",
127
- guard: "hasSpeechResult"
128
- },
129
- {
130
- target: "idle",
131
- description: "We have no speech and the user is not speaking. Return to idle."
132
- }
133
- ]
109
+ MAX_SPEECH_WAIT_TIMEOUT: {
110
+ target: "processingUserRequest",
111
+ description: "This will give the person time to breathe and speak again.",
112
+ reenter: true
113
+ }
134
114
  }
135
115
  },
136
116
  hangup: {
@@ -80,6 +80,9 @@ const machineSetup = (0, xstate_1.setup)({
80
80
  context.speechBuffer = ((context.speechBuffer ?? "") +
81
81
  " " +
82
82
  speech).trimStart();
83
+ logger.verbose("appended speech to the buffer", {
84
+ speechBuffer: context.speechBuffer
85
+ });
83
86
  return context;
84
87
  }),
85
88
  cleanSpeech: (0, xstate_1.assign)({ speechBuffer: "" }),
@@ -26,6 +26,7 @@ type AutopilotContext = {
26
26
  goodbyeMessage: string;
27
27
  transferMessage?: string;
28
28
  transferPhoneNumber?: string;
29
+ transferTimeout?: number;
29
30
  systemErrorMessage: string;
30
31
  idleMessage: string;
31
32
  idleTimeout: number;
@@ -42,6 +42,11 @@ async function sendConversationEndedEvent(eventsHook, chatHistory) {
42
42
  });
43
43
  }
44
44
  catch (e) {
45
- logger.error("error sending event", e);
45
+ logger.error("error sending event", {
46
+ url: parsedEventsHook.url,
47
+ method: common_1.AllowedHttpMethod.POST,
48
+ waitForResponse: false,
49
+ body
50
+ });
46
51
  }
47
52
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fonoster/autopilot",
3
- "version": "0.9.28",
3
+ "version": "0.9.32",
4
4
  "description": "Voice AI for the Fonoster platform",
5
5
  "author": "Pedro Sanders <psanders@fonoster.com>",
6
6
  "homepage": "https://github.com/fonoster/fonoster#readme",
@@ -33,17 +33,17 @@
33
33
  },
34
34
  "dependencies": {
35
35
  "@aws-sdk/client-s3": "^3.712.0",
36
- "@fonoster/common": "^0.9.24",
37
- "@fonoster/logger": "^0.9.22",
38
- "@fonoster/sdk": "^0.9.24",
39
- "@fonoster/types": "^0.9.22",
40
- "@fonoster/voice": "^0.9.28",
36
+ "@fonoster/common": "^0.9.31",
37
+ "@fonoster/logger": "^0.9.30",
38
+ "@fonoster/sdk": "^0.9.31",
39
+ "@fonoster/types": "^0.9.30",
40
+ "@fonoster/voice": "^0.9.31",
41
41
  "@langchain/community": "^0.3.32",
42
42
  "@langchain/core": "^0.3.40",
43
43
  "@langchain/groq": "^0.1.3",
44
44
  "@langchain/ollama": "^0.1.6",
45
45
  "@langchain/openai": "^0.4.4",
46
- "chalk": "^5.4.1",
46
+ "chalk": "^4.1.2",
47
47
  "cheerio": "^1.0.0",
48
48
  "cli-table3": "^0.6.5",
49
49
  "dotenv": "^16.4.5",
@@ -56,5 +56,5 @@
56
56
  "xstate": "^5.17.3",
57
57
  "zod": "^3.23.8"
58
58
  },
59
- "gitHead": "2670941d018a5470efd4b835a3a31954585afc39"
59
+ "gitHead": "8d324aaed02811c1b143e60fbd4a6a8091ec164e"
60
60
  }