@fonoster/autopilot 0.22.11 → 0.22.12

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.
@@ -16,11 +16,9 @@
16
16
  * See the License for the specific language governing permissions and
17
17
  * limitations under the License.
18
18
  */
19
- export { greetUser } from "./greetUser";
20
19
  export { goodbye } from "./goodbye";
21
20
  export { announceSystemError } from "./announceSystemError";
22
21
  export { interruptPlayback } from "./interruptPlayback";
23
- export { announceIdleTimeout } from "./announceIdleTimeout";
24
22
  export { increaseIdleTimeoutCount } from "./increaseIdleTimeoutCount";
25
23
  export { cleanSpeech } from "./cleanSpeech";
26
24
  export { appendSpeech } from "./appendSpeech";
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.resetState = exports.resetIdleTimeoutCount = exports.appendSpeech = exports.cleanSpeech = exports.increaseIdleTimeoutCount = exports.announceIdleTimeout = exports.interruptPlayback = exports.announceSystemError = exports.goodbye = exports.greetUser = void 0;
3
+ exports.resetState = exports.resetIdleTimeoutCount = exports.appendSpeech = exports.cleanSpeech = exports.increaseIdleTimeoutCount = exports.interruptPlayback = exports.announceSystemError = exports.goodbye = void 0;
4
4
  /**
5
5
  * Copyright (C) 2025 by Fonoster Inc (https://fonoster.com)
6
6
  * http://github.com/fonoster/fonoster
@@ -19,16 +19,12 @@ exports.resetState = exports.resetIdleTimeoutCount = exports.appendSpeech = expo
19
19
  * See the License for the specific language governing permissions and
20
20
  * limitations under the License.
21
21
  */
22
- var greetUser_1 = require("./greetUser");
23
- Object.defineProperty(exports, "greetUser", { enumerable: true, get: function () { return greetUser_1.greetUser; } });
24
22
  var goodbye_1 = require("./goodbye");
25
23
  Object.defineProperty(exports, "goodbye", { enumerable: true, get: function () { return goodbye_1.goodbye; } });
26
24
  var announceSystemError_1 = require("./announceSystemError");
27
25
  Object.defineProperty(exports, "announceSystemError", { enumerable: true, get: function () { return announceSystemError_1.announceSystemError; } });
28
26
  var interruptPlayback_1 = require("./interruptPlayback");
29
27
  Object.defineProperty(exports, "interruptPlayback", { enumerable: true, get: function () { return interruptPlayback_1.interruptPlayback; } });
30
- var announceIdleTimeout_1 = require("./announceIdleTimeout");
31
- Object.defineProperty(exports, "announceIdleTimeout", { enumerable: true, get: function () { return announceIdleTimeout_1.announceIdleTimeout; } });
32
28
  var increaseIdleTimeoutCount_1 = require("./increaseIdleTimeoutCount");
33
29
  Object.defineProperty(exports, "increaseIdleTimeoutCount", { enumerable: true, get: function () { return increaseIdleTimeoutCount_1.increaseIdleTimeoutCount; } });
34
30
  var cleanSpeech_1 = require("./cleanSpeech");
@@ -0,0 +1,4 @@
1
+ import { AutopilotContext } from "../types";
2
+ export declare const doAnnounceIdleTimeout: import("xstate").PromiseActorLogic<void, {
3
+ context: AutopilotContext;
4
+ }, import("xstate").EventObject>;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.announceIdleTimeout = void 0;
3
+ exports.doAnnounceIdleTimeout = void 0;
4
4
  /**
5
5
  * Copyright (C) 2025 by Fonoster Inc (https://fonoster.com)
6
6
  * http://github.com/fonoster/fonoster
@@ -20,11 +20,22 @@ exports.announceIdleTimeout = void 0;
20
20
  * limitations under the License.
21
21
  */
22
22
  const logger_1 = require("@fonoster/logger");
23
+ const xstate_1 = require("xstate");
23
24
  const logger = (0, logger_1.getLogger)({ service: "autopilot", filePath: __filename });
24
- const announceIdleTimeout = async ({ context }) => {
25
- logger.verbose("called the announceIdleTimeout action", {
26
- idleMessage: context.idleMessage
25
+ // Invoked (not fired-and-forgotten) so the machine stays in
26
+ // "announcingIdleTimeout" until the idle message has been fully played. The
27
+ // idle clock is re-armed only when the machine returns to "idle", so the time
28
+ // the assistant spends talking never counts as user silence.
29
+ exports.doAnnounceIdleTimeout = (0, xstate_1.fromPromise)(async ({ input }) => {
30
+ const { context } = input;
31
+ logger.verbose("called the doAnnounceIdleTimeout actor", {
32
+ idleMessage: context.idleMessage,
33
+ idleTimeoutCount: context.idleTimeoutCount
27
34
  });
28
- await context.voice.say(context.idleMessage);
29
- };
30
- exports.announceIdleTimeout = announceIdleTimeout;
35
+ try {
36
+ await context.voice.say(context.idleMessage);
37
+ }
38
+ catch (error) {
39
+ logger.error("error while announcing the idle timeout", { error });
40
+ }
41
+ });
@@ -0,0 +1,4 @@
1
+ import { AutopilotContext } from "../types";
2
+ export declare const doGreetUser: import("xstate").PromiseActorLogic<void, {
3
+ context: AutopilotContext;
4
+ }, import("xstate").EventObject>;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.greetUser = void 0;
3
+ exports.doGreetUser = void 0;
4
4
  /**
5
5
  * Copyright (C) 2025 by Fonoster Inc (https://fonoster.com)
6
6
  * http://github.com/fonoster/fonoster
@@ -20,17 +20,26 @@ exports.greetUser = void 0;
20
20
  * limitations under the License.
21
21
  */
22
22
  const logger_1 = require("@fonoster/logger");
23
+ const xstate_1 = require("xstate");
23
24
  const logger = (0, logger_1.getLogger)({ service: "autopilot", filePath: __filename });
24
- const greetUser = async ({ context }) => {
25
- logger.verbose("called the greetUser action", {
25
+ // Invoked (not fired-and-forgotten) so the machine stays in "greeting" until
26
+ // the first message has been fully played. Otherwise the idle clock would start
27
+ // while the assistant is still talking.
28
+ exports.doGreetUser = (0, xstate_1.fromPromise)(async ({ input }) => {
29
+ const { context } = input;
30
+ logger.verbose("called the doGreetUser actor", {
26
31
  firstMessage: context.firstMessage
27
32
  });
28
- await context.voice.answer();
29
- if (context.initialDtmf) {
30
- await context.voice.playDtmf(context.initialDtmf);
33
+ try {
34
+ await context.voice.answer();
35
+ if (context.initialDtmf) {
36
+ await context.voice.playDtmf(context.initialDtmf);
37
+ }
38
+ if (context.firstMessage) {
39
+ await context.voice.say(context.firstMessage);
40
+ }
31
41
  }
32
- if (context.firstMessage) {
33
- await context.voice.say(context.firstMessage);
42
+ catch (error) {
43
+ logger.error("error while greeting the user", { error });
34
44
  }
35
- };
36
- exports.greetUser = greetUser;
45
+ });
@@ -17,3 +17,5 @@
17
17
  * limitations under the License.
18
18
  */
19
19
  export * from "./doProcessUserRequest";
20
+ export * from "./doGreetUser";
21
+ export * from "./doAnnounceIdleTimeout";
@@ -33,3 +33,5 @@ Object.defineProperty(exports, "__esModule", { value: true });
33
33
  * limitations under the License.
34
34
  */
35
35
  __exportStar(require("./doProcessUserRequest"), exports);
36
+ __exportStar(require("./doGreetUser"), exports);
37
+ __exportStar(require("./doAnnounceIdleTimeout"), exports);
@@ -1,14 +1,34 @@
1
1
  declare const machine: import("xstate").StateMachine<any, import("./types").AutopilotEvents, {
2
2
  [x: string]: import("xstate").ActorRefFromLogic<import("xstate").PromiseActorLogic<void, {
3
3
  context: import("./types").AutopilotContext;
4
- }, import("xstate").EventObject>>;
5
- }, {
6
- src: "doProcessUserRequest";
7
- logic: import("xstate").PromiseActorLogic<void, {
4
+ }, import("xstate").EventObject>> | import("xstate").ActorRefFromLogic<import("xstate").PromiseActorLogic<void, {
5
+ context: import("./types").AutopilotContext;
6
+ }, import("xstate").EventObject>> | import("xstate").ActorRefFromLogic<import("xstate").PromiseActorLogic<void, {
8
7
  context: import("./types").AutopilotContext;
9
- }, import("xstate").EventObject>;
10
- id: string;
8
+ }, import("xstate").EventObject>>;
11
9
  }, import("xstate").Values<{
10
+ doProcessUserRequest: {
11
+ src: "doProcessUserRequest";
12
+ logic: import("xstate").PromiseActorLogic<void, {
13
+ context: import("./types").AutopilotContext;
14
+ }, import("xstate").EventObject>;
15
+ id: string;
16
+ };
17
+ doGreetUser: {
18
+ src: "doGreetUser";
19
+ logic: import("xstate").PromiseActorLogic<void, {
20
+ context: import("./types").AutopilotContext;
21
+ }, import("xstate").EventObject>;
22
+ id: string;
23
+ };
24
+ doAnnounceIdleTimeout: {
25
+ src: "doAnnounceIdleTimeout";
26
+ logic: import("xstate").PromiseActorLogic<void, {
27
+ context: import("./types").AutopilotContext;
28
+ }, import("xstate").EventObject>;
29
+ id: string;
30
+ };
31
+ }>, import("xstate").Values<{
12
32
  appendSpeech: {
13
33
  type: "appendSpeech";
14
34
  params: unknown;
@@ -29,10 +49,6 @@ declare const machine: import("xstate").StateMachine<any, import("./types").Auto
29
49
  type: "resetState";
30
50
  params: unknown;
31
51
  };
32
- greetUser: {
33
- type: "greetUser";
34
- params: unknown;
35
- };
36
52
  goodbye: {
37
53
  type: "goodbye";
38
54
  params: unknown;
@@ -45,10 +61,6 @@ declare const machine: import("xstate").StateMachine<any, import("./types").Auto
45
61
  type: "interruptPlayback";
46
62
  params: unknown;
47
63
  };
48
- announceIdleTimeout: {
49
- type: "announceIdleTimeout";
50
- params: unknown;
51
- };
52
64
  }>, import("xstate").Values<{
53
65
  idleTimeoutCountExceedsMax: {
54
66
  type: "idleTimeoutCountExceedsMax";
@@ -58,12 +70,11 @@ declare const machine: import("xstate").StateMachine<any, import("./types").Auto
58
70
  type: "hasSpeechResult";
59
71
  params: unknown;
60
72
  };
61
- }>, "IDLE_TIMEOUT" | "MAX_SPEECH_WAIT_TIMEOUT" | "MAX_SESSION_DURATION", "hangup" | "greeting" | "idle" | "listeningToUser" | "waitingForSpeechTimeout" | "processingUserRequest", string, {
73
+ }>, "IDLE_TIMEOUT" | "MAX_SPEECH_WAIT_TIMEOUT" | "MAX_SESSION_DURATION", "hangup" | "greeting" | "idle" | "listeningToUser" | "announcingIdleTimeout" | "waitingForSpeechTimeout" | "processingUserRequest", string, {
62
74
  conversationSettings: import("..").ConversationSettings;
63
75
  languageModel: import("..").LanguageModel;
64
76
  voice: import("..").Voice;
65
77
  }, {}, import("xstate").EventObject, import("xstate").MetaObject, {
66
- /** @xstate-layout N4IgpgJg5mDOIC5QDMB2BBAkgYgB6wBcBDAsAOiOVICcAKAWXQA0B9AZQFE23MB5AORYARAKoAldABU+-AJTY0WANoAGALqJQABwD2sAJYF9O1JpC5EAWgDMADgDsZFQDYATAFYAnLevuAjPYALIF+ADQgAJ6IHoFkrp5B9s6ezn6pzu7uAL5Z4YqYZFDUYGBGqFDYqhpIILoGRiZmFgh+tn5k1vYp9tauti7Obc7hUQievmQJzm5efq6uvvY5eRgF+hAANmDYbAAKHBwAwgAS7JLoYpJVZnWGxqY1zZ4qjrbuC-Z9gT3O9vYjiHstlckxcnXsKlaXUCrmWIHyZHWWzwhBI5EoNFomCEABkOCxpPQOLwRJJ5AikWBrjVbg0HqBmu5AipJu42t5PM8VNYMgCWtY-O05p4-F5XMyVIF3NY4RTNtt8MRSBQqGA6Ni8QTMESSWSFKtEfKlH5qto9HdGo9ENZArYyAF-P5fra+q4+YKFmQgv13EF-DypbKDRt9IQwKh9OVJDoRLA1Tt9kdTmIuCIcVd1DdzXSmohnLayLZnNZPIFi5zkkE+TyWZz7Ez4ipJX5mTLcvDg6HSBGozG49QUUr0ar1bj8YTiaTyZ2wz2oNHY2rqWb6vdcy1BXa-r5gYFnh56+6VMCvX4VF5uf7Pm2VlgyAB3Ih3coAMR01DYWhKAGMABaSfQAFswB0ABXAgEwOE4zguDNTVqbM1ytFoIQ6ZsgU5BZXC6YZIkQLx3ELIJXBUV0-kCIM70fZ8oDfD8vzAP8AOAsCIL2KDk1TdNlwQ1dLQZKwpUmOxviSFxmUFdw+Q+JxvilWw90WB1KIKaiylo99Px-f8gJA8DBzRFVMUYVh2KTFgAHUsEkLUdSnfUqKfdS6K0xidJY8CeNpJCBI3Wwtw+NJxl+YE3TwhBxRBbxbG8dxpji7xWhUsgtGoHRvzgAxykXagxDAABHUC4AgiATHISMADcdAAa3IBFUvSzLIygHK8sK4qEEq9KSHuKovMQ-jzEQOZ3g6QY-HGc9xjaPkLzIZk+m3ToQiCZKGoy2Aspa-s2qKwhIPMthzkufq+PpIb+R5e1rDsYtRR6SVPD5DCyCdYJnEhSFkgo9t6rSjattagq9rYxNoJTNg0zgrMzvXAIFK9CFBlLcTj2rPd7WvTpOm8Y9SxydtUB0CA4DMfIYYtc7mksQIJhcDxvF8AJgjCcKW08V65Liss5h6bxkqKEp1IpnNkMsX44krEiSxIotBj5TxXGcea-kVyVuXrXxkspEWfIu30QVSNJ4lSYIIWsBWlZVroSNbTXsl+mdu2ahd+11wbmgcFl2Wsc8BWLTJAlm1JC36Y8eWmtlkrU5qXIYpjdNY92qeGiXUiLPoPqVssg-CksOc+EIlfGewz1+B3bwKX8iHKUCtGT9dLBIwi3AFEVSMSMLRj8G72l8A3bTihKfsrlL-qa7KduB4qG+Q0VpTGwUgQyUibtmhxQ6bBSeWlRWlgJoA */
67
78
  readonly context: ({ input }: {
68
79
  input: {
69
80
  voice: import("..").Voice;
@@ -98,12 +109,29 @@ declare const machine: import("xstate").StateMachine<any, import("./types").Auto
98
109
  readonly initial: "greeting";
99
110
  readonly states: {
100
111
  readonly greeting: {
101
- readonly always: {
102
- readonly target: "idle";
103
- readonly description: "Transition to idle after the initial greeting.";
112
+ readonly invoke: {
113
+ readonly src: "doGreetUser";
114
+ readonly description: "Answer the call and play the first message";
115
+ readonly input: ({ context }: {
116
+ context: any;
117
+ event: import("./types").AutopilotEvents;
118
+ self: import("xstate").ActorRef<import("xstate").MachineSnapshot<any, import("./types").AutopilotEvents, Record<string, import("xstate").AnyActorRef>, import("xstate").StateValue, string, unknown, any, any>, import("./types").AutopilotEvents, import("xstate").AnyEventObject>;
119
+ }) => {
120
+ context: any;
121
+ };
122
+ readonly onDone: {
123
+ readonly target: "idle";
124
+ readonly description: "Transition to idle after the initial greeting.";
125
+ };
126
+ readonly onError: {
127
+ readonly target: "idle";
128
+ };
104
129
  };
105
- readonly entry: {
106
- readonly type: "greetUser";
130
+ readonly on: {
131
+ readonly SPEECH_START: {
132
+ readonly target: "listeningToUser";
133
+ readonly description: "The user barged in during the greeting.";
134
+ };
107
135
  };
108
136
  };
109
137
  readonly idle: {
@@ -127,28 +155,67 @@ declare const machine: import("xstate").StateMachine<any, import("./types").Auto
127
155
  params: undefined;
128
156
  }>;
129
157
  }, {
130
- readonly target: "idle";
131
- readonly actions: readonly [{
132
- readonly type: "increaseIdleTimeoutCount";
133
- }, {
134
- readonly type: "announceIdleTimeout";
135
- }];
136
- readonly reenter: true;
158
+ readonly target: "announcingIdleTimeout";
137
159
  }];
138
160
  };
139
161
  };
162
+ readonly announcingIdleTimeout: {
163
+ readonly entry: readonly [{
164
+ readonly type: "increaseIdleTimeoutCount";
165
+ }];
166
+ readonly invoke: {
167
+ readonly src: "doAnnounceIdleTimeout";
168
+ readonly description: "Play the idle message";
169
+ readonly input: ({ context }: {
170
+ context: any;
171
+ event: import("./types").AutopilotEvents;
172
+ self: import("xstate").ActorRef<import("xstate").MachineSnapshot<any, import("./types").AutopilotEvents, Record<string, import("xstate").AnyActorRef>, import("xstate").StateValue, string, unknown, any, any>, import("./types").AutopilotEvents, import("xstate").AnyEventObject>;
173
+ }) => {
174
+ context: any;
175
+ };
176
+ readonly onDone: {
177
+ readonly target: "idle";
178
+ readonly description: "Re-arm the idle clock once the idle message finishes.";
179
+ };
180
+ readonly onError: {
181
+ readonly target: "idle";
182
+ };
183
+ };
184
+ readonly on: {
185
+ readonly SPEECH_START: {
186
+ readonly target: "listeningToUser";
187
+ readonly description: "The user spoke while the idle message was playing.";
188
+ };
189
+ };
190
+ };
140
191
  readonly listeningToUser: {
141
192
  readonly entry: readonly [{
142
193
  readonly type: "interruptPlayback";
143
194
  }, {
144
195
  readonly type: "resetIdleTimeoutCount";
145
- }, import("xstate").ActionFunction<any, import("./types").AutopilotEvents, import("./types").AutopilotEvents, undefined, {
146
- src: "doProcessUserRequest";
147
- logic: import("xstate").PromiseActorLogic<void, {
148
- context: import("./types").AutopilotContext;
149
- }, import("xstate").EventObject>;
150
- id: string;
151
- }, never, never, never, never>];
196
+ }, import("xstate").ActionFunction<any, import("./types").AutopilotEvents, import("./types").AutopilotEvents, undefined, import("xstate").Values<{
197
+ doProcessUserRequest: {
198
+ src: "doProcessUserRequest";
199
+ logic: import("xstate").PromiseActorLogic<void, {
200
+ context: import("./types").AutopilotContext;
201
+ }, import("xstate").EventObject>;
202
+ id: string;
203
+ };
204
+ doGreetUser: {
205
+ src: "doGreetUser";
206
+ logic: import("xstate").PromiseActorLogic<void, {
207
+ context: import("./types").AutopilotContext;
208
+ }, import("xstate").EventObject>;
209
+ id: string;
210
+ };
211
+ doAnnounceIdleTimeout: {
212
+ src: "doAnnounceIdleTimeout";
213
+ logic: import("xstate").PromiseActorLogic<void, {
214
+ context: import("./types").AutopilotContext;
215
+ }, import("xstate").EventObject>;
216
+ id: string;
217
+ };
218
+ }>, never, never, never, never>];
152
219
  readonly on: {
153
220
  readonly SPEECH_RESULT: {
154
221
  readonly target: "waitingForSpeechTimeout";
@@ -161,12 +228,16 @@ declare const machine: import("xstate").StateMachine<any, import("./types").Auto
161
228
  };
162
229
  readonly after: {
163
230
  readonly IDLE_TIMEOUT: readonly [{
164
- readonly target: "idle";
165
- readonly actions: readonly [{
166
- readonly type: "increaseIdleTimeoutCount";
167
- }, {
168
- readonly type: "announceIdleTimeout";
169
- }];
231
+ readonly target: "hangup";
232
+ readonly actions: {
233
+ readonly type: "goodbye";
234
+ };
235
+ readonly guard: import("xstate/dist/declarations/src/guards").GuardPredicate<any, import("./types").AutopilotEvents, unknown, {
236
+ type: "idleTimeoutCountExceedsMax";
237
+ params: undefined;
238
+ }>;
239
+ }, {
240
+ readonly target: "announcingIdleTimeout";
170
241
  }];
171
242
  };
172
243
  };
@@ -193,13 +264,29 @@ declare const machine: import("xstate").StateMachine<any, import("./types").Auto
193
264
  type: "SPEECH_RESULT";
194
265
  speech: string;
195
266
  responseTime: number;
196
- }, import("./types").AutopilotEvents, undefined, {
197
- src: "doProcessUserRequest";
198
- logic: import("xstate").PromiseActorLogic<void, {
199
- context: import("./types").AutopilotContext;
200
- }, import("xstate").EventObject>;
201
- id: string;
202
- }, never, never, never, never>];
267
+ }, import("./types").AutopilotEvents, undefined, import("xstate").Values<{
268
+ doProcessUserRequest: {
269
+ src: "doProcessUserRequest";
270
+ logic: import("xstate").PromiseActorLogic<void, {
271
+ context: import("./types").AutopilotContext;
272
+ }, import("xstate").EventObject>;
273
+ id: string;
274
+ };
275
+ doGreetUser: {
276
+ src: "doGreetUser";
277
+ logic: import("xstate").PromiseActorLogic<void, {
278
+ context: import("./types").AutopilotContext;
279
+ }, import("xstate").EventObject>;
280
+ id: string;
281
+ };
282
+ doAnnounceIdleTimeout: {
283
+ src: "doAnnounceIdleTimeout";
284
+ logic: import("xstate").PromiseActorLogic<void, {
285
+ context: import("./types").AutopilotContext;
286
+ }, import("xstate").EventObject>;
287
+ id: string;
288
+ };
289
+ }>, never, never, never, never>];
203
290
  };
204
291
  };
205
292
  readonly after: {
@@ -241,13 +328,29 @@ declare const machine: import("xstate").StateMachine<any, import("./types").Auto
241
328
  type: "SPEECH_RESULT";
242
329
  speech: string;
243
330
  responseTime: number;
244
- }, import("./types").AutopilotEvents, undefined, {
245
- src: "doProcessUserRequest";
246
- logic: import("xstate").PromiseActorLogic<void, {
247
- context: import("./types").AutopilotContext;
248
- }, import("xstate").EventObject>;
249
- id: string;
250
- }, never, never, never, never>];
331
+ }, import("./types").AutopilotEvents, undefined, import("xstate").Values<{
332
+ doProcessUserRequest: {
333
+ src: "doProcessUserRequest";
334
+ logic: import("xstate").PromiseActorLogic<void, {
335
+ context: import("./types").AutopilotContext;
336
+ }, import("xstate").EventObject>;
337
+ id: string;
338
+ };
339
+ doGreetUser: {
340
+ src: "doGreetUser";
341
+ logic: import("xstate").PromiseActorLogic<void, {
342
+ context: import("./types").AutopilotContext;
343
+ }, import("xstate").EventObject>;
344
+ id: string;
345
+ };
346
+ doAnnounceIdleTimeout: {
347
+ src: "doAnnounceIdleTimeout";
348
+ logic: import("xstate").PromiseActorLogic<void, {
349
+ context: import("./types").AutopilotContext;
350
+ }, import("xstate").EventObject>;
351
+ id: string;
352
+ };
353
+ }>, never, never, never, never>];
251
354
  readonly reenter: true;
252
355
  };
253
356
  };
@@ -266,13 +369,29 @@ declare const machine: import("xstate").StateMachine<any, import("./types").Auto
266
369
  readonly reenter: true;
267
370
  readonly actions: readonly [{
268
371
  readonly type: "cleanSpeech";
269
- }, import("xstate").ActionFunction<any, import("xstate").DoneActorEvent<void, string>, import("./types").AutopilotEvents, undefined, {
270
- src: "doProcessUserRequest";
271
- logic: import("xstate").PromiseActorLogic<void, {
272
- context: import("./types").AutopilotContext;
273
- }, import("xstate").EventObject>;
274
- id: string;
275
- }, never, never, never, never>];
372
+ }, import("xstate").ActionFunction<any, import("xstate").DoneActorEvent<void, string>, import("./types").AutopilotEvents, undefined, import("xstate").Values<{
373
+ doProcessUserRequest: {
374
+ src: "doProcessUserRequest";
375
+ logic: import("xstate").PromiseActorLogic<void, {
376
+ context: import("./types").AutopilotContext;
377
+ }, import("xstate").EventObject>;
378
+ id: string;
379
+ };
380
+ doGreetUser: {
381
+ src: "doGreetUser";
382
+ logic: import("xstate").PromiseActorLogic<void, {
383
+ context: import("./types").AutopilotContext;
384
+ }, import("xstate").EventObject>;
385
+ id: string;
386
+ };
387
+ doAnnounceIdleTimeout: {
388
+ src: "doAnnounceIdleTimeout";
389
+ logic: import("xstate").PromiseActorLogic<void, {
390
+ context: import("./types").AutopilotContext;
391
+ }, import("xstate").EventObject>;
392
+ id: string;
393
+ };
394
+ }>, never, never, never, never>];
276
395
  };
277
396
  };
278
397
  };
@@ -24,18 +24,31 @@ const xstate_2 = require("xstate");
24
24
  const context_1 = require("./context");
25
25
  const setup_1 = require("./setup");
26
26
  const machine = setup_1.machineSetup.createMachine({
27
- /** @xstate-layout N4IgpgJg5mDOIC5QDMB2BBAkgYgB6wBcBDAsAOiOVICcAKAWXQA0B9AZQFE23MB5AORYARAKoAldABU+-AJTY0WANoAGALqJQABwD2sAJYF9O1JpC5EAWgDMADgDsZFQDYATAFYAnLevuAjPYALIF+ADQgAJ6IHoFkrp5B9s6ezn6pzu7uAL5Z4YqYZFDUYGBGqFDYqhpIILoGRiZmFgh+tn5k1vYp9tauti7Obc7hUQievmQJzm5efq6uvvY5eRgF+hAANmDYbAAKHBwAwgAS7JLoYpJVZnWGxqY1zZ4qjrbuC-Z9gT3O9vYjiHstlckxcnXsKlaXUCrmWIHyZHWWzwhBI5EoNFomCEABkOCxpPQOLwRJJ5AikWBrjVbg0HqBmu5AipJu42t5PM8VNYMgCWtY-O05p4-F5XMyVIF3NY4RTNtt8MRSBQqGA6Ni8QTMESSWSFKtEfKlH5qto9HdGo9ENZArYyAF-P5fra+q4+YKFmQgv13EF-DypbKDRt9IQwKh9OVJDoRLA1Tt9kdTmIuCIcVd1DdzXSmohnLayLZnNZPIFi5zkkE+TyWZz7Ez4ipJX5mTLcvDg6HSBGozG49QUUr0ar1bj8YTiaTyZ2wz2oNHY2rqWb6vdcy1BXa-r5gYFnh56+6VMCvX4VF5uf7Pm2VlgyAB3Ih3coAMR01DYWhKAGMABaSfQAFswB0ABXAgEwOE4zguDNTVqbM1ytFoIQ6ZsgU5BZXC6YZIkQLx3ELIJXBUV0-kCIM70fZ8oDfD8vzAP8AOAsCIL2KDk1TdNlwQ1dLQZKwpUmOxviSFxmUFdw+Q+JxvilWw90WB1KIKaiylo99Px-f8gJA8DBzRFVMUYVh2KTFgAHUsEkLUdSnfUqKfdS6K0xidJY8CeNpJCBI3Wwtw+NJxl+YE3TwhBxRBbxbG8dxpji7xWhUsgtGoHRvzgAxykXagxDAABHUC4AgiATHISMADcdAAa3IBFUvSzLIygHK8sK4qEEq9KSHuKovMQ-jzEQOZ3g6QY-HGc9xjaPkLzIZk+m3ToQiCZKGoy2Aspa-s2qKwhIPMthzkufq+PpIb+R5e1rDsYtRR6SVPD5DCyCdYJnEhSFkgo9t6rSjattagq9rYxNoJTNg0zgrMzvXAIFK9CFBlLcTj2rPd7WvTpOm8Y9SxydtUB0CA4DMfIYYtc7mksQIJhcDxvF8AJgjCcKW08V65Liss5h6bxkqKEp1IpnNkMsX44krEiSxIotBj5TxXGcea-kVyVuXrXxkspEWfIu30QVSNJ4lSYIIWsBWlZVroSNbTXsl+mdu2ahd+11wbmgcFl2Wsc8BWLTJAlm1JC36Y8eWmtlkrU5qXIYpjdNY92qeGiXUiLPoPqVssg-CksOc+EIlfGewz1+B3bwKX8iHKUCtGT9dLBIwi3AFEVSMSMLRj8G72l8A3bTihKfsrlL-qa7KduB4qG+Q0VpTGwUgQyUibtmhxQ6bBSeWlRWlgJoA */
28
27
  context: context_1.context,
29
28
  id: "fnAI",
30
29
  initial: "greeting",
31
30
  states: {
32
31
  greeting: {
33
- always: {
34
- target: "idle",
35
- description: "Transition to idle after the initial greeting."
32
+ // The greeting is invoked (not fired-and-forgotten) so the machine only
33
+ // moves to "idle", and therefore only arms the idle clock, once the
34
+ // first message has been fully played.
35
+ invoke: {
36
+ src: "doGreetUser",
37
+ description: "Answer the call and play the first message",
38
+ input: ({ context }) => ({ context }),
39
+ onDone: {
40
+ target: "idle",
41
+ description: "Transition to idle after the initial greeting."
42
+ },
43
+ onError: {
44
+ target: "idle"
45
+ }
36
46
  },
37
- entry: {
38
- type: "greetUser"
47
+ on: {
48
+ SPEECH_START: {
49
+ target: "listeningToUser",
50
+ description: "The user barged in during the greeting."
51
+ }
39
52
  }
40
53
  },
41
54
  idle: {
@@ -54,16 +67,37 @@ const machine = setup_1.machineSetup.createMachine({
54
67
  guard: (0, xstate_1.and)(["idleTimeoutCountExceedsMax"])
55
68
  },
56
69
  {
57
- target: "idle",
58
- actions: [
59
- { type: "increaseIdleTimeoutCount" },
60
- { type: "announceIdleTimeout" }
61
- ],
62
- reenter: true
70
+ target: "announcingIdleTimeout"
63
71
  }
64
72
  ]
65
73
  }
66
74
  },
75
+ announcingIdleTimeout: {
76
+ // A dedicated state, with no IDLE_TIMEOUT of its own, so the idle clock
77
+ // is stopped while the idle message plays. It is re-armed only when the
78
+ // message finishes and the machine goes back to "idle". This prevents
79
+ // back-to-back idle announcements (and a premature hangup) when the
80
+ // idle timeout is short relative to the message duration.
81
+ entry: [{ type: "increaseIdleTimeoutCount" }],
82
+ invoke: {
83
+ src: "doAnnounceIdleTimeout",
84
+ description: "Play the idle message",
85
+ input: ({ context }) => ({ context }),
86
+ onDone: {
87
+ target: "idle",
88
+ description: "Re-arm the idle clock once the idle message finishes."
89
+ },
90
+ onError: {
91
+ target: "idle"
92
+ }
93
+ },
94
+ on: {
95
+ SPEECH_START: {
96
+ target: "listeningToUser",
97
+ description: "The user spoke while the idle message was playing."
98
+ }
99
+ }
100
+ },
67
101
  listeningToUser: {
68
102
  entry: [
69
103
  { type: "interruptPlayback" },
@@ -83,11 +117,12 @@ const machine = setup_1.machineSetup.createMachine({
83
117
  after: {
84
118
  IDLE_TIMEOUT: [
85
119
  {
86
- target: "idle",
87
- actions: [
88
- { type: "increaseIdleTimeoutCount" },
89
- { type: "announceIdleTimeout" }
90
- ]
120
+ target: "hangup",
121
+ actions: { type: "goodbye" },
122
+ guard: (0, xstate_1.and)(["idleTimeoutCountExceedsMax"])
123
+ },
124
+ {
125
+ target: "announcingIdleTimeout"
91
126
  }
92
127
  ]
93
128
  }
@@ -3,13 +3,29 @@ import { LanguageModel } from "../models";
3
3
  import { Voice } from "../voice";
4
4
  import { AutopilotContext, AutopilotEvents } from "./types";
5
5
  declare const machineSetup: {
6
- createMachine: <const TConfig extends import("xstate").MachineConfig<any, AutopilotEvents, {
7
- src: "doProcessUserRequest";
8
- logic: import("xstate").PromiseActorLogic<void, {
9
- context: AutopilotContext;
10
- }, import("xstate").EventObject>;
11
- id: string;
12
- }, import("xstate").Values<{
6
+ createMachine: <const TConfig extends import("xstate").MachineConfig<any, AutopilotEvents, import("xstate").Values<{
7
+ doProcessUserRequest: {
8
+ src: "doProcessUserRequest";
9
+ logic: import("xstate").PromiseActorLogic<void, {
10
+ context: AutopilotContext;
11
+ }, import("xstate").EventObject>;
12
+ id: string;
13
+ };
14
+ doGreetUser: {
15
+ src: "doGreetUser";
16
+ logic: import("xstate").PromiseActorLogic<void, {
17
+ context: AutopilotContext;
18
+ }, import("xstate").EventObject>;
19
+ id: string;
20
+ };
21
+ doAnnounceIdleTimeout: {
22
+ src: "doAnnounceIdleTimeout";
23
+ logic: import("xstate").PromiseActorLogic<void, {
24
+ context: AutopilotContext;
25
+ }, import("xstate").EventObject>;
26
+ id: string;
27
+ };
28
+ }>, import("xstate").Values<{
13
29
  appendSpeech: {
14
30
  type: "appendSpeech";
15
31
  params: unknown;
@@ -30,10 +46,6 @@ declare const machineSetup: {
30
46
  type: "resetState";
31
47
  params: unknown;
32
48
  };
33
- greetUser: {
34
- type: "greetUser";
35
- params: unknown;
36
- };
37
49
  goodbye: {
38
50
  type: "goodbye";
39
51
  params: unknown;
@@ -46,10 +58,6 @@ declare const machineSetup: {
46
58
  type: "interruptPlayback";
47
59
  params: unknown;
48
60
  };
49
- announceIdleTimeout: {
50
- type: "announceIdleTimeout";
51
- params: unknown;
52
- };
53
61
  }>, import("xstate").Values<{
54
62
  idleTimeoutCountExceedsMax: {
55
63
  type: "idleTimeoutCountExceedsMax";
@@ -66,14 +74,34 @@ declare const machineSetup: {
66
74
  }, {}, import("xstate").EventObject, import("xstate").MetaObject>>(config: TConfig) => import("xstate").StateMachine<any, AutopilotEvents, {
67
75
  [x: string]: import("xstate").ActorRefFromLogic<import("xstate").PromiseActorLogic<void, {
68
76
  context: AutopilotContext;
69
- }, import("xstate").EventObject>>;
70
- }, {
71
- src: "doProcessUserRequest";
72
- logic: import("xstate").PromiseActorLogic<void, {
77
+ }, import("xstate").EventObject>> | import("xstate").ActorRefFromLogic<import("xstate").PromiseActorLogic<void, {
73
78
  context: AutopilotContext;
74
- }, import("xstate").EventObject>;
75
- id: string;
79
+ }, import("xstate").EventObject>> | import("xstate").ActorRefFromLogic<import("xstate").PromiseActorLogic<void, {
80
+ context: AutopilotContext;
81
+ }, import("xstate").EventObject>>;
76
82
  }, import("xstate").Values<{
83
+ doProcessUserRequest: {
84
+ src: "doProcessUserRequest";
85
+ logic: import("xstate").PromiseActorLogic<void, {
86
+ context: AutopilotContext;
87
+ }, import("xstate").EventObject>;
88
+ id: string;
89
+ };
90
+ doGreetUser: {
91
+ src: "doGreetUser";
92
+ logic: import("xstate").PromiseActorLogic<void, {
93
+ context: AutopilotContext;
94
+ }, import("xstate").EventObject>;
95
+ id: string;
96
+ };
97
+ doAnnounceIdleTimeout: {
98
+ src: "doAnnounceIdleTimeout";
99
+ logic: import("xstate").PromiseActorLogic<void, {
100
+ context: AutopilotContext;
101
+ }, import("xstate").EventObject>;
102
+ id: string;
103
+ };
104
+ }>, import("xstate").Values<{
77
105
  appendSpeech: {
78
106
  type: "appendSpeech";
79
107
  params: unknown;
@@ -94,10 +122,6 @@ declare const machineSetup: {
94
122
  type: "resetState";
95
123
  params: unknown;
96
124
  };
97
- greetUser: {
98
- type: "greetUser";
99
- params: unknown;
100
- };
101
125
  goodbye: {
102
126
  type: "goodbye";
103
127
  params: unknown;
@@ -110,10 +134,6 @@ declare const machineSetup: {
110
134
  type: "interruptPlayback";
111
135
  params: unknown;
112
136
  };
113
- announceIdleTimeout: {
114
- type: "announceIdleTimeout";
115
- params: unknown;
116
- };
117
137
  }>, import("xstate").Values<{
118
138
  idleTimeoutCountExceedsMax: {
119
139
  type: "idleTimeoutCountExceedsMax";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fonoster/autopilot",
3
- "version": "0.22.11",
3
+ "version": "0.22.12",
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",
@@ -59,5 +59,5 @@
59
59
  "xstate": "^5.17.3",
60
60
  "zod": "^3.25.76"
61
61
  },
62
- "gitHead": "d4425a19b1971da1edb6ea717e96bf2fddaefcc4"
62
+ "gitHead": "facc2ea4a1d403afe29ce62f8f8dab3eaedbf015"
63
63
  }
@@ -1,4 +0,0 @@
1
- import { AutopilotContext } from "../types";
2
- export declare const announceIdleTimeout: ({ context }: {
3
- context: AutopilotContext;
4
- }) => Promise<void>;
@@ -1,4 +0,0 @@
1
- import { AutopilotContext } from "../types";
2
- export declare const greetUser: ({ context }: {
3
- context: AutopilotContext;
4
- }) => Promise<void>;