@fonoster/autopilot 0.27.0 → 0.30.0

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 (138) hide show
  1. package/README.md +14 -51
  2. package/dist/index.d.ts +0 -5
  3. package/dist/index.js +0 -5
  4. package/dist/knowledge/AbstractKnowledgeBase.d.ts +3 -2
  5. package/dist/knowledge/AbstractKnowledgeBase.js +2 -7
  6. package/dist/knowledge/FilesKnowledgeBase.d.ts +1 -1
  7. package/dist/knowledge/types.d.ts +1 -1
  8. package/dist/models/LanguageModelFactory.d.ts +5 -24
  9. package/dist/models/LanguageModelFactory.js +0 -1
  10. package/dist/models/createLanguageModel.d.ts +2 -2
  11. package/dist/models/evaluations/createEvalEffectiveConfig.d.ts +10 -106
  12. package/dist/models/evaluations/createEvalEffectiveConfig.js +47 -7
  13. package/dist/models/evaluations/createEvaluateIntelligence.d.ts +10 -20
  14. package/dist/models/evaluations/createEvaluateIntelligence.js +32 -23
  15. package/dist/models/evaluations/evalTestCases.d.ts +2 -2
  16. package/dist/models/evaluations/extractAiResponse.d.ts +2 -3
  17. package/dist/models/evaluations/index.d.ts +1 -0
  18. package/dist/models/evaluations/index.js +1 -0
  19. package/dist/models/evaluations/runEval.d.ts +2 -20
  20. package/dist/models/evaluations/session/EvalSession.d.ts +73 -0
  21. package/dist/models/evaluations/session/EvalSession.js +134 -0
  22. package/dist/models/evaluations/session/evaluateSessionScenario.d.ts +58 -0
  23. package/dist/models/evaluations/session/evaluateSessionScenario.js +182 -0
  24. package/dist/{vad → models/evaluations/session}/index.d.ts +3 -2
  25. package/dist/{vad → models/evaluations/session}/index.js +3 -2
  26. package/dist/models/evaluations/session/runSessionEval.d.ts +17 -0
  27. package/dist/models/evaluations/session/runSessionEval.js +59 -0
  28. package/dist/models/evaluations/types.d.ts +7 -6
  29. package/dist/models/types.d.ts +19 -1
  30. package/dist/session/Agent.d.ts +138 -0
  31. package/dist/session/Agent.js +474 -0
  32. package/dist/{loadAssistantFromAPI.d.ts → session/AsyncQueue.d.ts} +12 -7
  33. package/dist/session/AsyncQueue.js +67 -0
  34. package/dist/{machine/guards/index.d.ts → session/config.d.ts} +2 -2
  35. package/dist/session/config.js +27 -0
  36. package/dist/session/convertLegacyAssistant.d.ts +77 -0
  37. package/dist/session/convertLegacyAssistant.js +118 -0
  38. package/dist/session/createAutopilot.d.ts +47 -0
  39. package/dist/session/createAutopilot.js +119 -0
  40. package/dist/session/hosted.d.ts +456 -0
  41. package/dist/session/hosted.js +506 -0
  42. package/dist/{assistants → session}/index.d.ts +11 -2
  43. package/dist/{machine/actors → session}/index.js +11 -3
  44. package/dist/{machine/actions/appendSpeech.js → session/knowledge.d.ts} +14 -17
  45. package/dist/session/knowledge.js +10 -0
  46. package/dist/session/llm.d.ts +86 -0
  47. package/dist/session/llm.js +83 -0
  48. package/dist/session/machine.d.ts +206 -0
  49. package/dist/session/machine.js +126 -0
  50. package/dist/session/main.js +44 -0
  51. package/dist/session/sentences.d.ts +5 -0
  52. package/dist/session/sentences.js +53 -0
  53. package/dist/{machine/actors/index.d.ts → session/think.d.ts} +2 -3
  54. package/dist/{machine/actions/announceSystemError.js → session/think.js} +8 -10
  55. package/dist/session/tools.d.ts +22 -0
  56. package/dist/session/tools.js +83 -0
  57. package/dist/tools/builtin/transferToolDefinition.js +1 -1
  58. package/dist/voice/index.d.ts +0 -1
  59. package/dist/voice/index.js +0 -1
  60. package/dist/voice/types.d.ts +5 -18
  61. package/package.json +13 -14
  62. package/dist/Autopilot.d.ts +0 -14
  63. package/dist/Autopilot.js +0 -133
  64. package/dist/assistants/index.js +0 -36
  65. package/dist/assistants/loadAndValidateAssistant.d.ts +0 -3
  66. package/dist/assistants/loadAndValidateAssistant.js +0 -49
  67. package/dist/assistants/types.d.ts +0 -24
  68. package/dist/assistants/types.js +0 -2
  69. package/dist/envs.d.ts +0 -15
  70. package/dist/envs.js +0 -78
  71. package/dist/handleVoiceRequest.d.ts +0 -3
  72. package/dist/handleVoiceRequest.js +0 -167
  73. package/dist/loadAssistantConfigFromFile.d.ts +0 -3
  74. package/dist/loadAssistantConfigFromFile.js +0 -68
  75. package/dist/loadAssistantFromAPI.js +0 -98
  76. package/dist/machine/actions/announceSystemError.d.ts +0 -4
  77. package/dist/machine/actions/appendSpeech.d.ts +0 -1
  78. package/dist/machine/actions/cleanSpeech.d.ts +0 -1
  79. package/dist/machine/actions/cleanSpeech.js +0 -23
  80. package/dist/machine/actions/goodbye.d.ts +0 -4
  81. package/dist/machine/actions/goodbye.js +0 -31
  82. package/dist/machine/actions/increaseIdleTimeoutCount.d.ts +0 -1
  83. package/dist/machine/actions/increaseIdleTimeoutCount.js +0 -31
  84. package/dist/machine/actions/index.d.ts +0 -26
  85. package/dist/machine/actions/index.js +0 -37
  86. package/dist/machine/actions/interruptPlayback.d.ts +0 -4
  87. package/dist/machine/actions/interruptPlayback.js +0 -43
  88. package/dist/machine/actions/resetIdleTimeoutCount.d.ts +0 -1
  89. package/dist/machine/actions/resetIdleTimeoutCount.js +0 -31
  90. package/dist/machine/actions/resetState.d.ts +0 -1
  91. package/dist/machine/actions/resetState.js +0 -32
  92. package/dist/machine/actors/doAnnounceIdleTimeout.d.ts +0 -4
  93. package/dist/machine/actors/doAnnounceIdleTimeout.js +0 -41
  94. package/dist/machine/actors/doGreetUser.d.ts +0 -4
  95. package/dist/machine/actors/doGreetUser.js +0 -45
  96. package/dist/machine/actors/doProcessUserRequest.d.ts +0 -4
  97. package/dist/machine/actors/doProcessUserRequest.js +0 -75
  98. package/dist/machine/context.d.ts +0 -52
  99. package/dist/machine/context.js +0 -28
  100. package/dist/machine/delays.d.ts +0 -30
  101. package/dist/machine/delays.js +0 -37
  102. package/dist/machine/guards/hasSpeechResult.d.ts +0 -4
  103. package/dist/machine/guards/hasSpeechResult.js +0 -30
  104. package/dist/machine/guards/idleTimeoutCountExceedsMax.d.ts +0 -4
  105. package/dist/machine/guards/idleTimeoutCountExceedsMax.js +0 -31
  106. package/dist/machine/guards/index.js +0 -25
  107. package/dist/machine/index.d.ts +0 -19
  108. package/dist/machine/index.js +0 -23
  109. package/dist/machine/machine.d.ts +0 -408
  110. package/dist/machine/machine.js +0 -206
  111. package/dist/machine/setup.d.ts +0 -328
  112. package/dist/machine/setup.js +0 -116
  113. package/dist/machine/types.d.ts +0 -54
  114. package/dist/machine/types.js +0 -2
  115. package/dist/sendConversationEndedEvent.d.ts +0 -32
  116. package/dist/sendConversationEndedEvent.js +0 -66
  117. package/dist/sendConversationStartedEvent.d.ts +0 -6
  118. package/dist/sendConversationStartedEvent.js +0 -63
  119. package/dist/server.d.ts +0 -2
  120. package/dist/server.js +0 -25
  121. package/dist/types.d.ts +0 -40
  122. package/dist/types.js +0 -8
  123. package/dist/vad/SileroVad.d.ts +0 -18
  124. package/dist/vad/SileroVad.js +0 -40
  125. package/dist/vad/SileroVadModel.d.ts +0 -14
  126. package/dist/vad/SileroVadModel.js +0 -83
  127. package/dist/vad/chunkToFloat32Array.d.ts +0 -20
  128. package/dist/vad/chunkToFloat32Array.js +0 -34
  129. package/dist/vad/createVad.d.ts +0 -3
  130. package/dist/vad/createVad.js +0 -126
  131. package/dist/vad/types.d.ts +0 -60
  132. package/dist/vad/types.js +0 -2
  133. package/dist/vadWorker.js +0 -36
  134. package/dist/voice/Voice.d.ts +0 -61
  135. package/dist/voice/Voice.js +0 -96
  136. package/dist/voiceServerSetup.d.ts +0 -2
  137. package/dist/voiceServerSetup.js +0 -29
  138. /package/dist/{vadWorker.d.ts → session/main.d.ts} +0 -0
@@ -32,5 +32,4 @@ Object.defineProperty(exports, "__esModule", { value: true });
32
32
  * See the License for the specific language governing permissions and
33
33
  * limitations under the License.
34
34
  */
35
- __exportStar(require("./Voice"), exports);
36
35
  __exportStar(require("./types"), exports);
@@ -16,33 +16,20 @@
16
16
  * See the License for the specific language governing permissions and
17
17
  * limitations under the License.
18
18
  */
19
- import { AudioFilterConfig } from "@fonoster/common";
20
- type GatherStream = {
21
- stop: () => Promise<void>;
22
- onData: (cb: (payload: {
23
- speech: string;
24
- responseTime: number;
25
- }) => void) => void;
26
- };
27
- type Stream = {
28
- stop: () => Promise<void>;
29
- onData: (cb: (chunk: Uint8Array) => void) => void;
30
- };
31
19
  type TransferOptions = {
32
20
  timeout?: number;
33
21
  record?: boolean;
34
22
  };
23
+ /**
24
+ * The call controls the LangChain models' built-in tools (hangup, transfer) use. Only the
25
+ * evaluations (createEvaluateIntelligence) drive these models now, with a stand-in; the hosted
26
+ * engine in ../session talks to the session SDK instead.
27
+ */
35
28
  type Voice = {
36
- mediaSessionRef: string;
37
29
  answer: () => Promise<void>;
38
- setAudioFilters: (filters: AudioFilterConfig[]) => Promise<void>;
39
30
  hangup: () => Promise<void>;
40
31
  say: (text: string) => Promise<void>;
41
32
  playDtmf: (dtmf: string) => Promise<void>;
42
- sgather: () => Promise<GatherStream>;
43
33
  transfer: (destination: string, options?: TransferOptions) => Promise<void>;
44
- stream: () => Promise<Stream>;
45
- stopSpeech: () => Promise<void>;
46
- stopStreams: () => Promise<void>;
47
34
  };
48
35
  export { TransferOptions, Voice };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fonoster/autopilot",
3
- "version": "0.27.0",
3
+ "version": "0.30.0",
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",
@@ -16,11 +16,10 @@
16
16
  "build": "tsc -b tsconfig.json",
17
17
  "clean": "rimraf ./dist node_modules tsconfig.tsbuildinfo",
18
18
  "generate:readme": "node ../../.scripts/gen-readme.cjs",
19
- "start:dev": "nodemon --exec tsx --watch src src/server.ts"
19
+ "start:hosted": "node dist/session/main.js"
20
20
  },
21
21
  "files": [
22
- "dist",
23
- "silero_vad.onnx"
22
+ "dist"
24
23
  ],
25
24
  "publishConfig": {
26
25
  "access": "public"
@@ -35,11 +34,12 @@
35
34
  "dependencies": {
36
35
  "@aws-sdk/client-s3": "^3.958.0",
37
36
  "@dmitryrechkin/json-schema-to-zod": "^1.0.1",
38
- "@fonoster/common": "^0.27.0",
39
- "@fonoster/logger": "^0.27.0",
40
- "@fonoster/sdk": "^0.27.0",
41
- "@fonoster/types": "^0.27.0",
42
- "@fonoster/voice": "^0.27.0",
37
+ "@fonoster/common": "^0.30.0",
38
+ "@fonoster/community": "^0.30.0",
39
+ "@fonoster/logger": "^0.30.0",
40
+ "@fonoster/types": "^0.30.0",
41
+ "@fonoster/voice": "^0.30.0",
42
+ "@grpc/grpc-js": "~1.14.6",
43
43
  "@langchain/anthropic": "^1.3.3",
44
44
  "@langchain/community": "^1.1.1",
45
45
  "@langchain/core": "^1.1.8",
@@ -49,15 +49,14 @@
49
49
  "@langchain/openai": "^1.2.0",
50
50
  "@langchain/textsplitters": "^1.0.1",
51
51
  "cheerio": "^1.1.2",
52
- "dotenv": "^16.6.1",
53
52
  "js-yaml": "^4.1.1",
54
53
  "langchain": "^1.2.3",
55
- "moment": "^2.30.1",
56
- "onnxruntime-node": "1.21.1",
57
54
  "pdf-parse": "^1.1.1",
58
- "uuid": "^11.0.3",
59
55
  "xstate": "^5.17.3",
60
56
  "zod": "^3.25.76"
61
57
  },
62
- "gitHead": "1191b34677b51a36000177887ff82303ef2693e1"
58
+ "gitHead": "b59b06a3ef325abe3f188c0fb87cc22d50ed5471",
59
+ "devDependencies": {
60
+ "yaml": "^2.9.0"
61
+ }
63
62
  }
@@ -1,14 +0,0 @@
1
- import { AutopilotParams } from "./types";
2
- declare class Autopilot {
3
- private readonly params;
4
- private readonly actor;
5
- private vad;
6
- constructor(params: AutopilotParams);
7
- start(): Promise<void>;
8
- stop(): void;
9
- private setupAudioFilters;
10
- private setupVoiceStream;
11
- private handleVoicePayload;
12
- private setupSpeechGathering;
13
- }
14
- export { Autopilot };
package/dist/Autopilot.js DELETED
@@ -1,133 +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
- exports.Autopilot = void 0;
7
- /**
8
- * Copyright (C) 2025 by Fonoster Inc (https://fonoster.com)
9
- * http://github.com/fonoster/fonoster
10
- *
11
- * This file is part of Fonoster
12
- *
13
- * Licensed under the MIT License (the "License");
14
- * you may not use this file except in compliance with
15
- * the License. You may obtain a copy of the License at
16
- *
17
- * https://opensource.org/licenses/MIT
18
- *
19
- * Unless required by applicable law or agreed to in writing, software
20
- * distributed under the License is distributed on an "AS IS" BASIS,
21
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22
- * See the License for the specific language governing permissions and
23
- * limitations under the License.
24
- */
25
- const path_1 = __importDefault(require("path"));
26
- const logger_1 = require("@fonoster/logger");
27
- const xstate_1 = require("xstate");
28
- const machine_1 = require("./machine/machine");
29
- const vad_1 = require("./vad");
30
- const logger = (0, logger_1.getLogger)({ service: "autopilot", filePath: __filename });
31
- class Autopilot {
32
- constructor(params) {
33
- this.params = params;
34
- const { voice, languageModel, conversationSettings } = this.params;
35
- this.actor = (0, xstate_1.createActor)(machine_1.machine, {
36
- input: {
37
- conversationSettings,
38
- languageModel,
39
- voice
40
- }
41
- });
42
- }
43
- async start() {
44
- await this.setupAudioFilters();
45
- const vadParams = this.params.conversationSettings.vad;
46
- const sileroVad = new vad_1.SileroVad({
47
- pathToModel: vadParams.pathToModel ||
48
- path_1.default.resolve(__dirname, "..", "silero_vad_v5.onnx"),
49
- activationThreshold: vadParams.activationThreshold,
50
- deactivationThreshold: vadParams.deactivationThreshold,
51
- debounceFrames: vadParams.debounceFrames
52
- });
53
- await sileroVad.init();
54
- this.vad = sileroVad;
55
- await this.setupVoiceStream();
56
- await this.setupSpeechGathering();
57
- this.actor.start();
58
- logger.verbose("autopilot is ready");
59
- this.actor.subscribe((state) => {
60
- logger.verbose("actor's new state is", { state: state.value });
61
- });
62
- }
63
- stop() {
64
- logger.verbose("stopping autopilot");
65
- this.actor.stop();
66
- }
67
- // Asked for before the audio stream is opened, so voice activity detection
68
- // and speech recognition both see filtered audio from the first frame. A
69
- // refusal is logged and the call continues unfiltered.
70
- async setupAudioFilters() {
71
- const { voice, audioFilters } = this.params;
72
- if (!audioFilters?.length) {
73
- return;
74
- }
75
- try {
76
- await voice.setAudioFilters(audioFilters);
77
- logger.verbose("audio filters requested", {
78
- filters: audioFilters.map((filter) => filter.name)
79
- });
80
- }
81
- catch (err) {
82
- logger.warn("could not set audio filters; continuing unfiltered", {
83
- error: err?.message
84
- });
85
- }
86
- }
87
- async setupVoiceStream() {
88
- const { voice } = this.params;
89
- const stream = await voice.stream();
90
- stream.onData(this.handleVoicePayload.bind(this));
91
- }
92
- handleVoicePayload(chunk) {
93
- try {
94
- if (!this.vad) {
95
- logger.error("VAD not initialized");
96
- return;
97
- }
98
- // Process the audio chunk with the VAD directly
99
- this.vad.processChunk(chunk, (event) => {
100
- logger.verbose("received speech event from vad", { event });
101
- if (event === "SPEECH_START") {
102
- this.actor.send({ type: "SPEECH_START" });
103
- }
104
- else if (event === "SPEECH_END") {
105
- this.actor.send({ type: "SPEECH_END" });
106
- }
107
- });
108
- }
109
- catch (err) {
110
- logger.error("an error occurred while processing vad", err);
111
- }
112
- }
113
- async setupSpeechGathering() {
114
- const { voice } = this.params;
115
- const stream = await voice.sgather();
116
- stream.onData((payload) => {
117
- const { speech, responseTime } = payload;
118
- logger.verbose("received speech result", {
119
- event: "SPEECH_RESULT",
120
- speech,
121
- responseTime
122
- });
123
- if (payload.speech) {
124
- this.actor.send({
125
- type: "SPEECH_RESULT",
126
- speech: payload.speech ?? "",
127
- responseTime
128
- });
129
- }
130
- });
131
- }
132
- }
133
- exports.Autopilot = Autopilot;
@@ -1,36 +0,0 @@
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
- /**
18
- * Copyright (C) 2025 by Fonoster Inc (https://fonoster.com)
19
- * http://github.com/fonoster/fonoster
20
- *
21
- * This file is part of Fonoster
22
- *
23
- * Licensed under the MIT License (the "License");
24
- * you may not use this file except in compliance with
25
- * the License. You may obtain a copy of the License at
26
- *
27
- * https://opensource.org/licenses/MIT
28
- *
29
- * Unless required by applicable law or agreed to in writing, software
30
- * distributed under the License is distributed on an "AS IS" BASIS,
31
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
32
- * See the License for the specific language governing permissions and
33
- * limitations under the License.
34
- */
35
- __exportStar(require("./loadAndValidateAssistant"), exports);
36
- __exportStar(require("./types"), exports);
@@ -1,3 +0,0 @@
1
- import { AssistantConfig } from "./types";
2
- declare function loadAndValidateAssistant(assistantPath: string): AssistantConfig;
3
- export { loadAndValidateAssistant };
@@ -1,49 +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
- exports.loadAndValidateAssistant = loadAndValidateAssistant;
7
- /**
8
- * Copyright (C) 2025 by Fonoster Inc (https://fonoster.com)
9
- * http://github.com/fonoster/fonoster
10
- *
11
- * This file is part of Fonoster
12
- *
13
- * Licensed under the MIT License (the "License");
14
- * you may not use this file except in compliance with
15
- * the License. You may obtain a copy of the License at
16
- *
17
- * https://opensource.org/licenses/MIT
18
- *
19
- * Unless required by applicable law or agreed to in writing, software
20
- * distributed under the License is distributed on an "AS IS" BASIS,
21
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22
- * See the License for the specific language governing permissions and
23
- * limitations under the License.
24
- */
25
- const fs_1 = __importDefault(require("fs"));
26
- const path_1 = __importDefault(require("path"));
27
- const common_1 = require("@fonoster/common");
28
- const logger_1 = require("@fonoster/logger");
29
- const js_yaml_1 = require("js-yaml");
30
- const logger = (0, logger_1.getLogger)({ service: "autopilot", filePath: __filename });
31
- function loadAndValidateAssistant(assistantPath) {
32
- if (!fs_1.default.existsSync(assistantPath)) {
33
- logger.error("assistant file not found", { path: assistantPath });
34
- process.exit(1);
35
- }
36
- try {
37
- const fileContent = fs_1.default.readFileSync(assistantPath, "utf8");
38
- const isYaml = [".yaml", ".yml"].includes(path_1.default.extname(assistantPath).toLowerCase());
39
- const assistant = (isYaml ? (0, js_yaml_1.load)(fileContent) : JSON.parse(fileContent));
40
- return common_1.assistantSchema.parse(assistant);
41
- }
42
- catch (e) {
43
- logger.error("error parsing or validating assistant file", {
44
- path: assistantPath,
45
- error: e
46
- });
47
- process.exit(1);
48
- }
49
- }
@@ -1,24 +0,0 @@
1
- /**
2
- * Copyright (C) 2025 by Fonoster Inc (https://fonoster.com)
3
- * http://github.com/fonoster/fonoster
4
- *
5
- * This file is part of Fonoster
6
- *
7
- * Licensed under the MIT License (the "License");
8
- * you may not use this file except in compliance with
9
- * the License. You may obtain a copy of the License at
10
- *
11
- * https://opensource.org/licenses/MIT
12
- *
13
- * Unless required by applicable law or agreed to in writing, software
14
- * distributed under the License is distributed on an "AS IS" BASIS,
15
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
- * See the License for the specific language governing permissions and
17
- * limitations under the License.
18
- */
19
- import { assistantSchema, conversationSettingsSchema, languageModelConfigSchema } from "@fonoster/common";
20
- import { z } from "zod";
21
- type ConversationSettings = z.infer<typeof conversationSettingsSchema>;
22
- type LanguageModelConfig = z.infer<typeof languageModelConfigSchema>;
23
- type AssistantConfig = z.infer<typeof assistantSchema>;
24
- export { AssistantConfig, ConversationSettings, LanguageModelConfig };
@@ -1,2 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
package/dist/envs.d.ts DELETED
@@ -1,15 +0,0 @@
1
- export declare const AWS_S3_ACCESS_KEY_ID: string;
2
- export declare const AWS_S3_ENDPOINT: string;
3
- export declare const AWS_S3_REGION: string;
4
- export declare const AWS_S3_SECRET_ACCESS_KEY: string;
5
- export declare const KNOWLEDGE_BASE_ENABLED: boolean;
6
- export declare const NODE_ENV: string;
7
- export declare const UNSTRUCTURED_API_KEY: string;
8
- export declare const UNSTRUCTURED_API_URL: string;
9
- export declare const CONVERSATION_PROVIDER: string;
10
- export declare const CONVERSATION_PROVIDER_FILE: string;
11
- export declare const APISERVER_ENDPOINT: string;
12
- export declare const INTEGRATIONS_FILE: string;
13
- export declare const OPENAI_API_KEY: string;
14
- export declare const SKIP_IDENTITY: boolean;
15
- export declare const RECORDING_BASE_URL: string;
package/dist/envs.js DELETED
@@ -1,78 +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
- exports.RECORDING_BASE_URL = exports.SKIP_IDENTITY = exports.OPENAI_API_KEY = exports.INTEGRATIONS_FILE = exports.APISERVER_ENDPOINT = exports.CONVERSATION_PROVIDER_FILE = exports.CONVERSATION_PROVIDER = exports.UNSTRUCTURED_API_URL = exports.UNSTRUCTURED_API_KEY = exports.NODE_ENV = exports.KNOWLEDGE_BASE_ENABLED = exports.AWS_S3_SECRET_ACCESS_KEY = exports.AWS_S3_REGION = exports.AWS_S3_ENDPOINT = exports.AWS_S3_ACCESS_KEY_ID = void 0;
7
- /**
8
- * Copyright (C) 2025 by Fonoster Inc (https://fonoster.com)
9
- * http://github.com/fonoster/fonoster
10
- *
11
- * This file is part of Fonoster
12
- *
13
- * Licensed under the MIT License (the "License");
14
- * you may not use this file except in compliance with
15
- * the License. You may obtain a copy of the License at
16
- *
17
- * https://opensource.org/licenses/MIT
18
- *
19
- * Unless required by applicable law or agreed to in writing, software
20
- * distributed under the License is distributed on an "AS IS" BASIS,
21
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22
- * See the License for the specific language governing permissions and
23
- * limitations under the License.
24
- */
25
- const path_1 = require("path");
26
- const common_1 = require("@fonoster/common");
27
- const logger_1 = __importDefault(require("@fonoster/logger"));
28
- const dotenv_1 = __importDefault(require("dotenv"));
29
- const types_1 = require("./types");
30
- if (process.env.NODE_ENV === "development") {
31
- dotenv_1.default.config({ path: (0, path_1.join)(__dirname, "..", "..", "..", ".env") });
32
- }
33
- const e = process.env;
34
- exports.AWS_S3_ACCESS_KEY_ID = e.AUTOPILOT_AWS_S3_ACCESS_KEY_ID ?? "";
35
- exports.AWS_S3_ENDPOINT = e.AUTOPILOT_AWS_S3_ENDPOINT || undefined;
36
- exports.AWS_S3_REGION = e.AUTOPILOT_AWS_S3_REGION ?? "us-east-1";
37
- exports.AWS_S3_SECRET_ACCESS_KEY = e.AUTOPILOT_AWS_S3_SECRET_ACCESS_KEY ?? "";
38
- exports.KNOWLEDGE_BASE_ENABLED = e.AUTOPILOT_KNOWLEDGE_BASE_ENABLED === "true";
39
- exports.NODE_ENV = e.NODE_ENV || "production";
40
- exports.UNSTRUCTURED_API_KEY = e.AUTOPILOT_UNSTRUCTURED_API_KEY ?? "";
41
- exports.UNSTRUCTURED_API_URL = e.AUTOPILOT_UNSTRUCTURED_API_URL ??
42
- "https://api.unstructuredapp.io/general/v0/general";
43
- exports.CONVERSATION_PROVIDER = e.AUTOPILOT_CONVERSATION_PROVIDER
44
- ? e.AUTOPILOT_CONVERSATION_PROVIDER
45
- : types_1.ConversationProvider.FILE;
46
- exports.CONVERSATION_PROVIDER_FILE = e.AUTOPILOT_CONVERSATION_PROVIDER_FILE
47
- ? e.AUTOPILOT_CONVERSATION_PROVIDER_FILE
48
- : `${process.cwd()}/config/assistant.json`;
49
- exports.APISERVER_ENDPOINT = e.AUTOPILOT_APISERVER_ENDPOINT
50
- ? e.AUTOPILOT_APISERVER_ENDPOINT
51
- : "apiserver:50051";
52
- exports.INTEGRATIONS_FILE = e.AUTOPILOT_INTEGRATIONS_FILE
53
- ? e.AUTOPILOT_INTEGRATIONS_FILE
54
- : "/opt/fonoster/integrations.json";
55
- exports.OPENAI_API_KEY = e.AUTOPILOT_OPENAI_API_KEY;
56
- exports.SKIP_IDENTITY = e.AUTOPILOT_SKIP_IDENTITY === "true";
57
- exports.RECORDING_BASE_URL = e.AUTOPILOT_RECORDING_BASE_URL
58
- ? e.AUTOPILOT_RECORDING_BASE_URL
59
- : "http://localhost:9876/api/recordings";
60
- if (exports.CONVERSATION_PROVIDER.toLocaleLowerCase() !== types_1.ConversationProvider.API &&
61
- exports.CONVERSATION_PROVIDER.toLocaleLowerCase() !== types_1.ConversationProvider.FILE) {
62
- console.error("CONVERSATION_PROVIDER must be set to 'api' or 'file'");
63
- process.exit(1);
64
- }
65
- if (exports.CONVERSATION_PROVIDER.toLocaleLowerCase() === types_1.ConversationProvider.API) {
66
- (0, common_1.assertFileExists)(exports.INTEGRATIONS_FILE);
67
- }
68
- if (exports.KNOWLEDGE_BASE_ENABLED) {
69
- (0, common_1.assertEnvsAreSet)([
70
- "AUTOPILOT_AWS_S3_ACCESS_KEY_ID",
71
- "AUTOPILOT_AWS_S3_SECRET_ACCESS_KEY",
72
- "AUTOPILOT_UNSTRUCTURED_API_KEY"
73
- ]);
74
- if (!exports.AWS_S3_ENDPOINT && !exports.AWS_S3_REGION) {
75
- logger_1.default.error("Knowledge base configuration error: Either AUTOPILOT_AWS_S3_ENDPOINT or AUTOPILOT_AWS_S3_REGION must be set when using AWS S3");
76
- process.exit(1);
77
- }
78
- }
@@ -1,3 +0,0 @@
1
- import { VoiceRequest, VoiceResponse } from "@fonoster/voice";
2
- declare function handleVoiceRequest(req: VoiceRequest, res: VoiceResponse): Promise<void>;
3
- export { handleVoiceRequest };
@@ -1,167 +0,0 @@
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 __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || (function () {
19
- var ownKeys = function(o) {
20
- ownKeys = Object.getOwnPropertyNames || function (o) {
21
- var ar = [];
22
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
- return ar;
24
- };
25
- return ownKeys(o);
26
- };
27
- return function (mod) {
28
- if (mod && mod.__esModule) return mod;
29
- var result = {};
30
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
- __setModuleDefault(result, mod);
32
- return result;
33
- };
34
- })();
35
- var __importDefault = (this && this.__importDefault) || function (mod) {
36
- return (mod && mod.__esModule) ? mod : { "default": mod };
37
- };
38
- Object.defineProperty(exports, "__esModule", { value: true });
39
- exports.handleVoiceRequest = handleVoiceRequest;
40
- /**
41
- * Copyright (C) 2025 by Fonoster Inc (https://fonoster.com)
42
- * http://github.com/fonoster/fonoster
43
- *
44
- * This file is part of Fonoster
45
- *
46
- * Licensed under the MIT License (the "License");
47
- * you may not use this file except in compliance with
48
- * the License. You may obtain a copy of the License at
49
- *
50
- * https://opensource.org/licenses/MIT
51
- *
52
- * Unless required by applicable law or agreed to in writing, software
53
- * distributed under the License is distributed on an "AS IS" BASIS,
54
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
55
- * See the License for the specific language governing permissions and
56
- * limitations under the License.
57
- */
58
- const fs_1 = __importDefault(require("fs"));
59
- const common_1 = require("@fonoster/common");
60
- const logger_1 = require("@fonoster/logger");
61
- const envs_1 = require("./envs");
62
- const loadAssistantConfigFromFile_1 = require("./loadAssistantConfigFromFile");
63
- const loadAssistantFromAPI_1 = require("./loadAssistantFromAPI");
64
- const createLanguageModel_1 = require("./models/createLanguageModel");
65
- const sendConversationEndedEvent_1 = require("./sendConversationEndedEvent");
66
- const sendConversationStartedEvent_1 = require("./sendConversationStartedEvent");
67
- const _1 = __importStar(require("."));
68
- const logger = (0, logger_1.getLogger)({ service: "autopilot", filePath: __filename });
69
- async function handleVoiceRequest(req, res) {
70
- const { accessKeyId, callerNumber, ingressNumber, mediaSessionRef, appRef, callRef, callDirection, metadata, amd } = req;
71
- logger.verbose("voice request", {
72
- accessKeyId,
73
- ingressNumber,
74
- mediaSessionRef,
75
- appRef,
76
- callRef,
77
- metadata
78
- });
79
- const assistantConfig = envs_1.CONVERSATION_PROVIDER === _1.ConversationProvider.FILE
80
- ? (0, loadAssistantConfigFromFile_1.loadAssistantConfigFromFile)(envs_1.CONVERSATION_PROVIDER_FILE)
81
- : await (0, loadAssistantFromAPI_1.loadAssistantFromAPI)(req, JSON.parse(fs_1.default.readFileSync(envs_1.INTEGRATIONS_FILE, "utf8")));
82
- let knowledgeBase;
83
- if (envs_1.KNOWLEDGE_BASE_ENABLED) {
84
- const documents = assistantConfig.languageModel?.knowledgeBase?.map((doc) => doc.document);
85
- logger.verbose("loading knowledge base", {
86
- documents,
87
- bucket: req.accessKeyId.toLowerCase()
88
- });
89
- knowledgeBase = new _1.S3KnowledgeBase({
90
- bucket: req.accessKeyId.toLowerCase(),
91
- documents,
92
- s3Config: {
93
- endpoint: envs_1.AWS_S3_ENDPOINT,
94
- region: envs_1.AWS_S3_REGION,
95
- credentials: {
96
- accessKeyId: envs_1.AWS_S3_ACCESS_KEY_ID,
97
- secretAccessKey: envs_1.AWS_S3_SECRET_ACCESS_KEY
98
- },
99
- forcePathStyle: true
100
- },
101
- unstructuredAPIURL: envs_1.UNSTRUCTURED_API_URL,
102
- unstructuredAPIKey: envs_1.UNSTRUCTURED_API_KEY
103
- });
104
- }
105
- knowledgeBase?.load().then(() => {
106
- logger.verbose("knowledge base loaded");
107
- });
108
- const voice = new _1.VoiceImpl(mediaSessionRef, res);
109
- const languageModel = (0, createLanguageModel_1.createLanguageModel)({
110
- voice,
111
- assistantConfig,
112
- knowledgeBase,
113
- telephonyContext: {
114
- callDirection,
115
- ingressNumber,
116
- callerNumber,
117
- metadata
118
- }
119
- });
120
- const { conversationSettings } = assistantConfig;
121
- try {
122
- const autopilot = new _1.default({
123
- audioFilters: assistantConfig.audioFilters,
124
- conversationSettings: conversationSettings,
125
- voice: voice,
126
- languageModel: languageModel
127
- });
128
- await autopilot.start();
129
- if (assistantConfig.eventsHook?.url) {
130
- await (0, sendConversationStartedEvent_1.sendConversationStartedEvent)(assistantConfig.eventsHook, {
131
- appRef,
132
- callRef,
133
- phone: ingressNumber
134
- });
135
- }
136
- res.on(common_1.StreamEvent.END, async () => {
137
- autopilot.stop();
138
- const rawChatHistory = await languageModel.getChatHistoryMessages();
139
- const chatHistory = rawChatHistory
140
- .map((msg) => {
141
- if (msg.constructor.name === "HumanMessage") {
142
- return { human: msg.content };
143
- }
144
- else if (msg.constructor.name === "AIMessage") {
145
- return { ai: msg.content };
146
- }
147
- return null;
148
- })
149
- .filter(Boolean);
150
- if (assistantConfig.eventsHook?.url) {
151
- // Construct recording URL: baseUrl + appRef + mediaSessionRef
152
- const recordingUrl = `${envs_1.RECORDING_BASE_URL}/${appRef}_${mediaSessionRef}.wav`;
153
- await (0, sendConversationEndedEvent_1.sendConversationEndedEvent)(assistantConfig.eventsHook, {
154
- appRef,
155
- callRef,
156
- phone: ingressNumber,
157
- chatHistory: chatHistory,
158
- recordingUrl,
159
- amd
160
- });
161
- }
162
- });
163
- }
164
- catch (error) {
165
- logger.error("error handling voice request", { error });
166
- }
167
- }
@@ -1,3 +0,0 @@
1
- import { AssistantConfig } from ".";
2
- declare function loadAssistantConfigFromFile(pathToAssistantConfig: string): AssistantConfig;
3
- export { loadAssistantConfigFromFile };