@fonoster/autopilot 0.7.4 → 0.7.6

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 (102) hide show
  1. package/README.md +156 -2
  2. package/dist/Autopilot.d.ts +3 -7
  3. package/dist/Autopilot.js +19 -36
  4. package/dist/assistants/AssistantSchema.d.ts +575 -30
  5. package/dist/assistants/AssistantSchema.js +41 -13
  6. package/dist/assistants/index.d.ts +1 -3
  7. package/dist/assistants/index.js +1 -6
  8. package/dist/assistants/loadAndValidateAssistant.d.ts +2 -2
  9. package/dist/assistants/loadAndValidateAssistant.js +3 -3
  10. package/dist/assistants/types.d.ts +6 -24
  11. package/dist/assistants/types.js +0 -25
  12. package/dist/createLanguageModel.d.ts +3 -0
  13. package/dist/createLanguageModel.js +40 -0
  14. package/dist/envs.d.ts +1 -0
  15. package/dist/envs.js +2 -1
  16. package/dist/handleVoiceRequest.d.ts +3 -0
  17. package/dist/handleVoiceRequest.js +66 -0
  18. package/dist/index.d.ts +9 -1
  19. package/dist/index.js +23 -3
  20. package/dist/knowledge/AbstractKnowledgeBase.d.ts +13 -0
  21. package/dist/knowledge/AbstractKnowledgeBase.js +18 -0
  22. package/dist/knowledge/FilesKnowledgeBase.d.ts +12 -0
  23. package/dist/knowledge/FilesKnowledgeBase.js +50 -0
  24. package/dist/knowledge/index.d.ts +3 -0
  25. package/dist/knowledge/index.js +37 -0
  26. package/dist/knowledge/types.d.ts +4 -0
  27. package/dist/knowledge/types.js +2 -0
  28. package/dist/loadAssistantConfig.d.ts +3 -0
  29. package/dist/loadAssistantConfig.js +26 -0
  30. package/dist/loadKnowledgeBase.d.ts +3 -0
  31. package/dist/loadKnowledgeBase.js +29 -0
  32. package/dist/machine/machine.d.ts +27 -28
  33. package/dist/machine/machine.js +44 -30
  34. package/dist/models/AbstractLanguageModel.d.ts +11 -0
  35. package/dist/models/AbstractLanguageModel.js +78 -0
  36. package/dist/models/LanguageModelFactory.d.ts +16 -0
  37. package/dist/models/LanguageModelFactory.js +44 -0
  38. package/dist/models/chatHistory.d.ts +6 -0
  39. package/dist/models/chatHistory.js +32 -0
  40. package/dist/models/createChain.d.ts +7 -0
  41. package/dist/models/createChain.js +15 -0
  42. package/dist/models/createPromptTemplate.d.ts +2 -0
  43. package/dist/{assistants/assistants.js → models/createPromptTemplate.js} +7 -16
  44. package/dist/models/groq/Groq.d.ts +7 -0
  45. package/dist/models/groq/Groq.js +22 -0
  46. package/dist/models/groq/index.d.ts +2 -0
  47. package/dist/models/groq/index.js +36 -0
  48. package/dist/models/groq/types.d.ts +13 -0
  49. package/dist/models/groq/types.js +9 -0
  50. package/dist/models/index.d.ts +2 -0
  51. package/dist/models/index.js +36 -0
  52. package/dist/models/openai/OpenAI.d.ts +7 -0
  53. package/dist/models/openai/OpenAI.js +22 -0
  54. package/dist/models/openai/index.d.ts +2 -0
  55. package/dist/models/openai/index.js +36 -0
  56. package/dist/models/openai/types.d.ts +12 -0
  57. package/dist/models/openai/types.js +8 -0
  58. package/dist/models/types.d.ts +19 -0
  59. package/dist/models/types.js +2 -0
  60. package/dist/server.js +23 -0
  61. package/dist/tools/ToolSchema.d.ts +107 -0
  62. package/dist/tools/ToolSchema.js +64 -0
  63. package/dist/tools/ToolsCatalog.d.ts +11 -0
  64. package/dist/tools/ToolsCatalog.js +52 -0
  65. package/dist/tools/builtin/hangupToolDefinition.d.ts +3 -0
  66. package/dist/tools/builtin/hangupToolDefinition.js +35 -0
  67. package/dist/tools/builtin/transferToolDefinition.d.ts +3 -0
  68. package/dist/tools/builtin/transferToolDefinition.js +35 -0
  69. package/dist/tools/convertToolToOpenAITool.d.ts +3 -0
  70. package/dist/tools/convertToolToOpenAITool.js +11 -0
  71. package/dist/tools/index.d.ts +4 -0
  72. package/dist/tools/index.js +38 -0
  73. package/dist/tools/sendRequest.d.ts +11 -0
  74. package/dist/tools/sendRequest.js +43 -0
  75. package/dist/tools/type.d.ts +8 -0
  76. package/dist/tools/type.js +2 -0
  77. package/dist/types.d.ts +14 -6
  78. package/dist/types.js +6 -0
  79. package/dist/vad/SileroVad.d.ts +8 -0
  80. package/dist/vad/SileroVad.js +39 -0
  81. package/dist/vad/index.d.ts +1 -2
  82. package/dist/vad/index.js +1 -2
  83. package/dist/vad/makeVad.d.ts +1 -1
  84. package/dist/vad/makeVad.js +2 -2
  85. package/dist/vad/types.d.ts +4 -2
  86. package/dist/voice/Voice.d.ts +25 -0
  87. package/dist/voice/Voice.js +81 -0
  88. package/dist/voice/index.d.ts +2 -0
  89. package/dist/voice/index.js +36 -0
  90. package/dist/voice/types.d.ts +23 -0
  91. package/dist/voice/types.js +2 -0
  92. package/dist/voiceServerSetup.d.ts +2 -0
  93. package/dist/{runner.js → voiceServerSetup.js} +5 -22
  94. package/package.json +15 -7
  95. package/dist/assistants/assistants.d.ts +0 -4
  96. package/dist/machine/machinev0.d.ts +0 -163
  97. package/dist/machine/machinev0.js +0 -142
  98. package/dist/machine/types.d.ts +0 -29
  99. package/dist/machine/types.js +0 -9
  100. package/dist/runner.d.ts +0 -2
  101. package/dist/vad/micVadTest.js +0 -48
  102. /package/dist/{vad/micVadTest.d.ts → server.d.ts} +0 -0
@@ -0,0 +1,81 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.VoiceImpl = void 0;
4
+ /*
5
+ * Copyright (C) 2024 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
+ const common_1 = require("@fonoster/common");
23
+ const uuid_1 = require("uuid");
24
+ class VoiceImpl {
25
+ constructor(sessionRef, voice) {
26
+ this.voice = voice;
27
+ this.sessionRef = sessionRef;
28
+ this.playbackRef = (0, uuid_1.v4)();
29
+ }
30
+ async answer() {
31
+ await this.voice.answer();
32
+ }
33
+ async hangup() {
34
+ await this.voice.hangup();
35
+ }
36
+ async say(text) {
37
+ await this.voice.say(text, { playbackRef: this.playbackRef });
38
+ }
39
+ async sgather() {
40
+ const stream = await this.voice.sgather({
41
+ source: common_1.StreamGatherSource.SPEECH
42
+ });
43
+ return {
44
+ stop: async () => {
45
+ stream.close();
46
+ stream.cleanup(() => { });
47
+ },
48
+ onData: (cb) => {
49
+ stream.onPayload((payload) => {
50
+ cb(payload.speech);
51
+ });
52
+ }
53
+ };
54
+ }
55
+ async stream() {
56
+ const stream = await this.voice.stream();
57
+ return {
58
+ stop: async () => {
59
+ stream.close();
60
+ stream.cleanup(() => { });
61
+ },
62
+ onData: (cb) => {
63
+ stream.onPayload((payload) => {
64
+ cb(payload.data);
65
+ });
66
+ }
67
+ };
68
+ }
69
+ async transfer(to, options) {
70
+ const { record, timeout } = options;
71
+ const effectiveOptions = {
72
+ recordDirection: record ? common_1.DialRecordDirection.BOTH : undefined,
73
+ timeout
74
+ };
75
+ await this.voice.dial(to, effectiveOptions);
76
+ }
77
+ async stopSpeech() {
78
+ await this.voice.playbackControl(this.playbackRef, common_1.PlaybackControlAction.STOP);
79
+ }
80
+ }
81
+ exports.VoiceImpl = VoiceImpl;
@@ -0,0 +1,2 @@
1
+ export * from "./Voice";
2
+ export * from "./types";
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./Voice"), exports);
18
+ /*
19
+ * Copyright (C) 2024 by Fonoster Inc (https://fonoster.com)
20
+ * http://github.com/fonoster/fonoster
21
+ *
22
+ * This file is part of Fonoster
23
+ *
24
+ * Licensed under the MIT License (the "License");
25
+ * you may not use this file except in compliance with
26
+ * the License. You may obtain a copy of the License at
27
+ *
28
+ * https://opensource.org/licenses/MIT
29
+ *
30
+ * Unless required by applicable law or agreed to in writing, software
31
+ * distributed under the License is distributed on an "AS IS" BASIS,
32
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
33
+ * See the License for the specific language governing permissions and
34
+ * limitations under the License.
35
+ */
36
+ __exportStar(require("./types"), exports);
@@ -0,0 +1,23 @@
1
+ type GatherStream = {
2
+ stop: () => Promise<void>;
3
+ onData: (cb: (speech: string) => void) => void;
4
+ };
5
+ type Stream = {
6
+ stop: () => Promise<void>;
7
+ onData: (cb: (chunk: Uint8Array) => void) => void;
8
+ };
9
+ type TransferOptions = {
10
+ timeout?: number;
11
+ record?: boolean;
12
+ };
13
+ type Voice = {
14
+ sessionRef: string;
15
+ answer: () => Promise<void>;
16
+ hangup: () => Promise<void>;
17
+ say: (text: string) => Promise<void>;
18
+ sgather: () => Promise<GatherStream>;
19
+ transfer: (destination: string, options?: TransferOptions) => Promise<void>;
20
+ stream: () => Promise<Stream>;
21
+ stopSpeech: () => Promise<void>;
22
+ };
23
+ export { TransferOptions, Voice };
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,2 @@
1
+ declare function startVoiceServer(skipIdentity: boolean): void;
2
+ export { startVoiceServer };
@@ -1,9 +1,9 @@
1
- #!/usr/bin/env node
2
1
  "use strict";
3
2
  var __importDefault = (this && this.__importDefault) || function (mod) {
4
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
5
4
  };
6
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.startVoiceServer = startVoiceServer;
7
7
  /*
8
8
  * Copyright (C) 2024 by Fonoster Inc (https://fonoster.com)
9
9
  * http://github.com/fonoster/fonoster
@@ -22,25 +22,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
22
22
  * See the License for the specific language governing permissions and
23
23
  * limitations under the License.
24
24
  */
25
- const logger_1 = require("@fonoster/logger");
26
25
  const voice_1 = __importDefault(require("@fonoster/voice"));
27
- const assistants_1 = require("./assistants");
28
- const Autopilot_1 = require("./Autopilot");
29
- const envs_1 = require("./envs");
30
- const logger = (0, logger_1.getLogger)({ service: "autopilot", filePath: __filename });
31
- const skipIdentity = process.env.NODE_ENV === "dev";
32
- new voice_1.default({ skipIdentity }).listen(async (req, voice) => {
33
- const { ingressNumber, sessionRef, appRef } = req;
34
- logger.verbose("voice request", { ingressNumber, sessionRef, appRef });
35
- const assistantPath = process.argv[2];
36
- const assistant = (0, assistants_1.loadAndValidateAssistant)(assistantPath);
37
- logger.verbose("interacting with assistant", { name: assistant.name });
38
- const autopilot = new Autopilot_1.Autopilot({
39
- voice,
40
- assistantConfig: {
41
- ...assistant,
42
- apiKey: envs_1.OPENAI_API_KEY
43
- }
44
- });
45
- autopilot.start();
46
- });
26
+ const handleVoiceRequest_1 = require("./handleVoiceRequest");
27
+ function startVoiceServer(skipIdentity) {
28
+ new voice_1.default({ skipIdentity }).listen(handleVoiceRequest_1.handleVoiceRequest);
29
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fonoster/autopilot",
3
- "version": "0.7.4",
3
+ "version": "0.7.6",
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",
@@ -14,7 +14,8 @@
14
14
  "scripts": {
15
15
  "prebuild": "rimraf ./dist tsconfig.tsbuildinfo",
16
16
  "build": "tsc -b tsconfig.json",
17
- "clean": "rimraf ./dist node_modules tsconfig.tsbuildinfo"
17
+ "clean": "rimraf ./dist node_modules tsconfig.tsbuildinfo",
18
+ "generate:readme": "node ../../.scripts/gen-readme.js"
18
19
  },
19
20
  "bin": {
20
21
  "autopilot": "./dist/runner.js"
@@ -34,17 +35,24 @@
34
35
  "url": "https://github.com/fonoster/fonoster/issues"
35
36
  },
36
37
  "dependencies": {
37
- "@fonoster/logger": "^0.7.4",
38
- "@fonoster/voice": "^0.7.4",
39
- "@langchain/openai": "^0.2.7",
38
+ "@fonoster/common": "^0.7.5",
39
+ "@fonoster/logger": "^0.7.5",
40
+ "@fonoster/voice": "^0.7.5",
41
+ "@langchain/community": "^0.2.31",
42
+ "@langchain/core": "^0.2.31",
43
+ "@langchain/groq": "^0.0.17",
44
+ "@langchain/openai": "^0.2.8",
45
+ "cheerio": "^1.0.0",
40
46
  "dotenv": "^16.4.5",
47
+ "langchain": "^0.2.17",
41
48
  "onnxruntime-node": "^1.19.0",
49
+ "pdf-parse": "^1.1.1",
50
+ "uuid": "^10.0.0",
42
51
  "xstate": "^5.17.3",
43
52
  "zod": "^3.23.8"
44
53
  },
45
54
  "devDependencies": {
46
- "node-record-lpcm16": "^1.0.1",
47
55
  "typescript": "^5.5.4"
48
56
  },
49
- "gitHead": "e550aa46c1a9087a70157496365b64afd5aea11d"
57
+ "gitHead": "a02de2f037aaa9bc197e97c147ac9affe6cc69bb"
50
58
  }
@@ -1,4 +0,0 @@
1
- import { AssistantConfig } from "./types";
2
- type Assistant = ReturnType<typeof makeAssistant>;
3
- declare function makeAssistant(config: AssistantConfig): import("@langchain/core/runnables").Runnable<any, string, import("@langchain/core/runnables").RunnableConfig>;
4
- export { makeAssistant, Assistant };
@@ -1,163 +0,0 @@
1
- declare const machine: import("xstate").StateMachine<{
2
- firstMessage: string;
3
- voice: import("@fonoster/voice").VoiceResponse;
4
- assistant: import("../assistants/assistants").Assistant;
5
- playbackRef: string;
6
- speechBuffer: string;
7
- speechResponseStartTime: number;
8
- speechResponseTime: number;
9
- }, {
10
- type: "SPEECH_START";
11
- } | {
12
- type: "SPEECH_END";
13
- } | {
14
- type: "SESSION_END";
15
- } | {
16
- type: "HUMAN_PROMPT";
17
- speech: string;
18
- }, {}, never, import("xstate").Values<{
19
- appendSpeech: {
20
- type: "appendSpeech";
21
- params: unknown;
22
- };
23
- hangup: {
24
- type: "hangup";
25
- params: unknown;
26
- };
27
- sendGreeting: {
28
- type: "sendGreeting";
29
- params: unknown;
30
- };
31
- interruptMachineSpeaking: {
32
- type: "interruptMachineSpeaking";
33
- params: unknown;
34
- };
35
- processHumanRequest: {
36
- type: "processHumanRequest";
37
- params: unknown;
38
- };
39
- }>, {
40
- type: "hasSpeechBuffer";
41
- params: unknown;
42
- }, never, "hangup" | "welcome" | "machineListening" | "humanSpeaking", string, {
43
- firstMessage: string;
44
- voice: import("@fonoster/voice").VoiceResponse;
45
- assistant: import("../assistants/assistants").Assistant;
46
- }, import("xstate").NonReducibleUnknown, import("xstate").EventObject, import("xstate").MetaObject, {
47
- readonly context: ({ input }: {
48
- spawn: {
49
- <TSrc extends never>(logic: TSrc, ...[options]: never): import("xstate").ActorRefFromLogic<never>;
50
- <TLogic extends import("xstate").AnyActorLogic>(src: TLogic, options?: {
51
- id?: never;
52
- systemId?: string;
53
- input?: import("xstate").InputFrom<TLogic> | undefined;
54
- syncSnapshot?: boolean;
55
- } | undefined): import("xstate").ActorRefFromLogic<TLogic>;
56
- };
57
- input: {
58
- firstMessage: string;
59
- voice: import("@fonoster/voice").VoiceResponse;
60
- assistant: import("../assistants/assistants").Assistant;
61
- };
62
- self: import("xstate").ActorRef<import("xstate").MachineSnapshot<{
63
- firstMessage: string;
64
- voice: import("@fonoster/voice").VoiceResponse;
65
- assistant: import("../assistants/assistants").Assistant;
66
- playbackRef: string;
67
- speechBuffer: string;
68
- speechResponseStartTime: number;
69
- speechResponseTime: number;
70
- }, {
71
- type: "SPEECH_START";
72
- } | {
73
- type: "SPEECH_END";
74
- } | {
75
- type: "SESSION_END";
76
- } | {
77
- type: "HUMAN_PROMPT";
78
- speech: string;
79
- }, Record<string, import("xstate").AnyActorRef | undefined>, import("xstate").StateValue, string, unknown, any, any>, {
80
- type: "SPEECH_START";
81
- } | {
82
- type: "SPEECH_END";
83
- } | {
84
- type: "SESSION_END";
85
- } | {
86
- type: "HUMAN_PROMPT";
87
- speech: string;
88
- }, import("xstate").AnyEventObject>;
89
- }) => {
90
- firstMessage: string;
91
- voice: import("@fonoster/voice").VoiceResponse;
92
- assistant: import("@langchain/core/runnables").Runnable<any, string, import("@langchain/core/runnables").RunnableConfig>;
93
- playbackRef: string;
94
- speechBuffer: string;
95
- speechResponseStartTime: number;
96
- speechResponseTime: number;
97
- };
98
- readonly id: "fnAI_v0";
99
- readonly initial: "welcome";
100
- readonly states: {
101
- readonly welcome: {
102
- readonly entry: {
103
- readonly type: "sendGreeting";
104
- };
105
- readonly always: {
106
- readonly target: "machineListening";
107
- };
108
- readonly description: "The initial state where the AI greets the Human.";
109
- };
110
- readonly machineListening: {
111
- readonly on: {
112
- readonly SPEECH_START: {
113
- readonly target: "humanSpeaking";
114
- readonly description: "This must be triggered by a VAD or similar system.";
115
- };
116
- readonly HUMAN_PROMPT: {
117
- readonly actions: {
118
- readonly type: "appendSpeech";
119
- };
120
- readonly description: "Appends the speech to the buffer.";
121
- };
122
- };
123
- readonly description: "The state where the AI is actively listening in conversation.";
124
- };
125
- readonly humanSpeaking: {
126
- readonly entry: {
127
- readonly type: "interruptMachineSpeaking";
128
- };
129
- readonly on: {
130
- readonly HUMAN_PROMPT: {
131
- readonly actions: {
132
- readonly type: "appendSpeech";
133
- };
134
- readonly description: "Appends the speech to the buffer.";
135
- };
136
- readonly SPEECH_END: {
137
- readonly target: "machineListening";
138
- readonly actions: {
139
- readonly type: "processHumanRequest";
140
- };
141
- readonly guard: {
142
- readonly type: "hasSpeechBuffer";
143
- };
144
- readonly description: "This must be triggered by a VAD or similar system.";
145
- };
146
- };
147
- readonly description: "The state where the AI detects Human speech while it is speaking.";
148
- };
149
- readonly hangup: {
150
- readonly type: "final";
151
- readonly entry: {
152
- readonly type: "hangup";
153
- };
154
- readonly on: {
155
- readonly SESSION_END: {
156
- readonly target: "hangup";
157
- };
158
- };
159
- readonly description: "The final state where the AI terminates the conversation due to inactivity.";
160
- };
161
- };
162
- }>;
163
- export { machine };
@@ -1,142 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.machine = void 0;
4
- /*
5
- * Copyright (C) 2024 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
- const common_1 = require("@fonoster/common");
23
- const logger_1 = require("@fonoster/logger");
24
- const uuid_1 = require("uuid");
25
- const xstate_1 = require("xstate");
26
- const types_1 = require("./types");
27
- const logger = (0, logger_1.getLogger)({ service: "autopilot", filePath: __filename });
28
- const machine = (0, xstate_1.setup)({
29
- types: types_1.types,
30
- actions: {
31
- sendGreeting: async function ({ context }) {
32
- await context.voice.answer();
33
- await context.voice.say(context.firstMessage, {
34
- playbackRef: context.playbackRef
35
- });
36
- },
37
- interruptMachineSpeaking: async function ({ context }) {
38
- logger.verbose("interrupting the machine", {
39
- playbackRef: context.playbackRef
40
- });
41
- await context.voice.playbackControl(context.playbackRef, common_1.PlaybackControlAction.STOP);
42
- },
43
- appendSpeech: function ({ context, event }) {
44
- const speech = event.speech;
45
- context.speechBuffer = (context.speechBuffer || "") + " " + speech;
46
- context.speechResponseStartTime = Date.now();
47
- logger.verbose("appended speech", { speechBuffer: context.speechBuffer });
48
- },
49
- processHumanRequest: async function ({ context }) {
50
- const speech = context.speechBuffer.trim();
51
- logger.verbose("processing human request", { speech });
52
- const response = await context.assistant.invoke({
53
- text: speech
54
- });
55
- const speechResponseTime = Date.now() - context.speechResponseStartTime;
56
- context.speechResponseTime = speechResponseTime;
57
- logger.verbose("assistant response", {
58
- response,
59
- responseTime: speechResponseTime
60
- });
61
- await context.voice.say(response, { playbackRef: context.playbackRef });
62
- // Clear the speech buffer and reset response timing
63
- context.speechBuffer = "";
64
- context.speechResponseStartTime = 0;
65
- },
66
- hangup: async function ({ context }) {
67
- await context.voice.hangup();
68
- }
69
- },
70
- guards: {
71
- hasSpeechBuffer: function ({ context }) {
72
- return context.speechBuffer?.trim().length > 0;
73
- }
74
- }
75
- }).createMachine({
76
- context: ({ input }) => ({
77
- firstMessage: input.firstMessage,
78
- voice: input.voice,
79
- assistant: input.assistant,
80
- playbackRef: (0, uuid_1.v4)(),
81
- speechBuffer: "",
82
- speechResponseStartTime: 0,
83
- speechResponseTime: 0
84
- }),
85
- id: "fnAI_v0",
86
- initial: "welcome",
87
- states: {
88
- welcome: {
89
- entry: {
90
- type: "sendGreeting"
91
- },
92
- always: {
93
- target: "machineListening"
94
- },
95
- description: "The initial state where the AI greets the Human."
96
- },
97
- machineListening: {
98
- on: {
99
- SPEECH_START: {
100
- target: "humanSpeaking",
101
- description: "This must be triggered by a VAD or similar system."
102
- },
103
- HUMAN_PROMPT: {
104
- actions: { type: "appendSpeech" },
105
- description: "Appends the speech to the buffer."
106
- }
107
- },
108
- description: "The state where the AI is actively listening in conversation."
109
- },
110
- humanSpeaking: {
111
- entry: {
112
- type: "interruptMachineSpeaking"
113
- },
114
- on: {
115
- HUMAN_PROMPT: {
116
- actions: { type: "appendSpeech" },
117
- description: "Appends the speech to the buffer."
118
- },
119
- SPEECH_END: {
120
- target: "machineListening",
121
- actions: { type: "processHumanRequest" },
122
- guard: { type: "hasSpeechBuffer" },
123
- description: "This must be triggered by a VAD or similar system."
124
- }
125
- },
126
- description: "The state where the AI detects Human speech while it is speaking."
127
- },
128
- hangup: {
129
- type: "final",
130
- entry: {
131
- type: "hangup"
132
- },
133
- on: {
134
- SESSION_END: {
135
- target: "hangup"
136
- }
137
- },
138
- description: "The final state where the AI terminates the conversation due to inactivity."
139
- }
140
- }
141
- });
142
- exports.machine = machine;
@@ -1,29 +0,0 @@
1
- import { VoiceResponse } from "@fonoster/voice";
2
- import { Assistant } from "../assistants/assistants";
3
- declare const types: {
4
- context: {
5
- firstMessage: string;
6
- voice: VoiceResponse;
7
- assistant: Assistant;
8
- playbackRef: string;
9
- speechBuffer: string;
10
- speechResponseStartTime: number;
11
- speechResponseTime: number;
12
- };
13
- input: {
14
- firstMessage: string;
15
- voice: VoiceResponse;
16
- assistant: Assistant;
17
- };
18
- events: {
19
- type: "SPEECH_START";
20
- } | {
21
- type: "SPEECH_END";
22
- } | {
23
- type: "SESSION_END";
24
- } | {
25
- type: "HUMAN_PROMPT";
26
- speech: string;
27
- };
28
- };
29
- export { types };
@@ -1,9 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.types = void 0;
4
- const types = {
5
- context: {},
6
- input: {},
7
- events: {}
8
- };
9
- exports.types = types;
package/dist/runner.d.ts DELETED
@@ -1,2 +0,0 @@
1
- #!/usr/bin/env node
2
- export {};
@@ -1,48 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- /*
7
- * Copyright (C) 2024 by Fonoster Inc (https://fonoster.com)
8
- * http://github.com/fonoster/fonoster
9
- *
10
- * This file is part of Fonoster
11
- *
12
- * Licensed under the MIT License (the "License");
13
- * you may not use this file except in compliance with
14
- * the License. You may obtain a copy of the License at
15
- *
16
- * https://opensource.org/licenses/MIT
17
- *
18
- * Unless required by applicable law or agreed to in writing, software
19
- * distributed under the License is distributed on an "AS IS" BASIS,
20
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21
- * See the License for the specific language governing permissions and
22
- * limitations under the License.
23
- */
24
- const logger_1 = require("@fonoster/logger");
25
- const node_record_lpcm16_1 = __importDefault(require("node-record-lpcm16"));
26
- const makeVad_1 = require("./makeVad");
27
- const logger = (0, logger_1.getLogger)({ service: "autopilot", filePath: __filename });
28
- async function main() {
29
- const vad = await (0, makeVad_1.makeVad)();
30
- // Start recording from the default microphone
31
- const mic = node_record_lpcm16_1.default
32
- .record({
33
- sampleRate: 16000, // 16 kHz sample rate
34
- channels: 1,
35
- threshold: 0.5
36
- })
37
- .stream();
38
- mic.on("data", async (data) => {
39
- const chunk = new Uint8Array(data.buffer);
40
- await vad(chunk, (event, _data) => {
41
- logger.info("vad event:", { event, data: _data });
42
- });
43
- });
44
- mic.on("error", (err) => {
45
- logger.error("an error occurred:", { err });
46
- });
47
- }
48
- main().catch(logger.error);
File without changes