@fonoster/autopilot 0.16.11 → 0.17.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.
package/README.md CHANGED
@@ -183,13 +183,19 @@ For example:
183
183
 
184
184
  Please use the following environment variables to configure the Autopilot:
185
185
 
186
- - `ASSISTANTS`: The path to the configuration file.
187
- - `OPEN_API_KEY`: The OpenAI API key for embeddings support.
188
- - `KNOWLEDGE_BASE_ENABLED`: Enable knowledge base powered by AWS S3 and Unstructured API.
189
- - `AWS_S3_ACCESS_KEY_ID`: The AWS S3 access key.
190
- - `AWS_S3_SECRET_ACCESS_KEY`: The AWS S3 secret access key.
191
- - `UNSTRUCTURED_API_KEY`: The Unstructured API key.
192
- - `UNSTRUCTURED_API_URL`: The Unstructured API URL. Default is `https://api.unstructured.com`.
186
+ - `AUTOPILOT_AWS_S3_ACCESS_KEY_ID`: The AWS S3 access key.
187
+ - `AUTOPILOT_AWS_S3_ENDPOINT`: The AWS S3 endpoint.
188
+ - `AUTOPILOT_AWS_S3_REGION`: The AWS S3 region.
189
+ - `AUTOPILOT_AWS_S3_SECRET_ACCESS_KEY`: The AWS S3 secret access key.
190
+ - `AUTOPILOT_CONVERSATION_PROVIDER`: The conversation provider.
191
+ - `AUTOPILOT_KNOWLEDGE_BASE_ENABLED`: Enable knowledge base powered by AWS S3 and Unstructured API.
192
+ - `AUTOPILOT_LOGS_FORMAT`: The logs format.
193
+ - `AUTOPILOT_LOGS_LEVEL`: The logs level.
194
+ - `AUTOPILOT_LOGS_TRANSPORT`: The logs transport.
195
+ - `AUTOPILOT_OPENAI_API_KEY`: The OpenAI API key needed for embeddings support.
196
+ - `AUTOPILOT_UNSTRUCTURED_API_KEY`: The Unstructured API key.
197
+ - `AUTOPILOT_UNSTRUCTURED_API_URL`: The Unstructured API URL. Default is `https://api.unstructured.com`.
198
+ - `AUTOPILOT_RECORDING_BASE_URL`: The recording base URL. Default is `http://localhost:9876/api/recordings`.
193
199
 
194
200
  ## What's Next
195
201
 
package/dist/envs.d.ts CHANGED
@@ -12,3 +12,4 @@ export declare const APISERVER_ENDPOINT: string;
12
12
  export declare const INTEGRATIONS_FILE: string;
13
13
  export declare const OPENAI_API_KEY: string;
14
14
  export declare const SKIP_IDENTITY: boolean;
15
+ export declare const RECORDING_BASE_URL: string;
package/dist/envs.js CHANGED
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- 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;
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
7
  /**
8
8
  * Copyright (C) 2025 by Fonoster Inc (https://fonoster.com)
9
9
  * http://github.com/fonoster/fonoster
@@ -54,6 +54,9 @@ exports.INTEGRATIONS_FILE = e.AUTOPILOT_INTEGRATIONS_FILE
54
54
  : "/opt/fonoster/integrations.json";
55
55
  exports.OPENAI_API_KEY = e.AUTOPILOT_OPENAI_API_KEY;
56
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";
57
60
  if (exports.CONVERSATION_PROVIDER.toLocaleLowerCase() !== types_1.ConversationProvider.API &&
58
61
  exports.CONVERSATION_PROVIDER.toLocaleLowerCase() !== types_1.ConversationProvider.FILE) {
59
62
  console.error("CONVERSATION_PROVIDER must be set to 'api' or 'file'");
@@ -66,12 +66,13 @@ const sendConversationEndedEvent_1 = require("./sendConversationEndedEvent");
66
66
  const _1 = __importStar(require("."));
67
67
  const logger = (0, logger_1.getLogger)({ service: "autopilot", filePath: __filename });
68
68
  async function handleVoiceRequest(req, res) {
69
- const { accessKeyId, callerNumber, ingressNumber, sessionRef, appRef, callDirection, metadata } = req;
69
+ const { accessKeyId, callerNumber, ingressNumber, mediaSessionRef, appRef, callRef, callDirection, metadata } = req;
70
70
  logger.verbose("voice request", {
71
71
  accessKeyId,
72
72
  ingressNumber,
73
- sessionRef,
73
+ mediaSessionRef,
74
74
  appRef,
75
+ callRef,
75
76
  metadata
76
77
  });
77
78
  const assistantConfig = envs_1.CONVERSATION_PROVIDER === _1.ConversationProvider.FILE
@@ -103,7 +104,7 @@ async function handleVoiceRequest(req, res) {
103
104
  knowledgeBase?.load().then(() => {
104
105
  logger.verbose("knowledge base loaded");
105
106
  });
106
- const voice = new _1.VoiceImpl(sessionRef, res);
107
+ const voice = new _1.VoiceImpl(mediaSessionRef, res);
107
108
  const languageModel = (0, createLanguageModel_1.createLanguageModel)({
108
109
  voice,
109
110
  assistantConfig,
@@ -138,11 +139,14 @@ async function handleVoiceRequest(req, res) {
138
139
  })
139
140
  .filter(Boolean);
140
141
  if (assistantConfig.eventsHook?.url) {
142
+ // Construct recording URL: baseUrl + appRef + mediaSessionRef
143
+ const recordingUrl = `${envs_1.RECORDING_BASE_URL}/${appRef}_${mediaSessionRef}.wav`;
141
144
  await (0, sendConversationEndedEvent_1.sendConversationEndedEvent)(assistantConfig.eventsHook, {
142
- chatHistory: chatHistory,
143
- phone: ingressNumber,
144
145
  appRef,
145
- sessionRef
146
+ callRef,
147
+ phone: ingressNumber,
148
+ chatHistory: chatHistory,
149
+ recordingUrl
146
150
  });
147
151
  }
148
152
  });
@@ -23,7 +23,7 @@ const logger_1 = require("@fonoster/logger");
23
23
  const logger = (0, logger_1.getLogger)({ service: "autopilot", filePath: __filename });
24
24
  const interruptPlayback = async ({ context }) => {
25
25
  logger.verbose("called the interruptPlayback action", {
26
- sessionRef: context.sessionRef
26
+ mediaSessionRef: context.mediaSessionRef
27
27
  });
28
28
  await context.voice.stopSpeech();
29
29
  };
@@ -26,7 +26,7 @@ declare const context: ({ input }: {
26
26
  conversationSettings: ConversationSettings;
27
27
  };
28
28
  }) => {
29
- sessionRef: string;
29
+ mediaSessionRef: string;
30
30
  voice: Voice;
31
31
  languageModel: LanguageModel;
32
32
  speechBuffer: string;
@@ -2,7 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.context = void 0;
4
4
  const context = ({ input }) => ({
5
- sessionRef: input.voice.sessionRef,
5
+ mediaSessionRef: input.voice.mediaSessionRef,
6
6
  voice: input.voice,
7
7
  languageModel: input.languageModel,
8
8
  speechBuffer: "",
@@ -71,7 +71,7 @@ declare const machine: import("xstate").StateMachine<any, import("./types").Auto
71
71
  conversationSettings: import("..").ConversationSettings;
72
72
  };
73
73
  }) => {
74
- sessionRef: string;
74
+ mediaSessionRef: string;
75
75
  voice: import("..").Voice;
76
76
  languageModel: import("..").LanguageModel;
77
77
  speechBuffer: string;
@@ -19,7 +19,7 @@
19
19
  import { LanguageModel } from "../models";
20
20
  import { Voice } from "../voice";
21
21
  type AutopilotContext = {
22
- sessionRef: string;
22
+ mediaSessionRef: string;
23
23
  languageModel: LanguageModel;
24
24
  voice: Voice;
25
25
  firstMessage?: string;
@@ -23,8 +23,9 @@ export type EventsHook = {
23
23
  headers?: Record<string, string>;
24
24
  };
25
25
  export declare function sendConversationEndedEvent(eventsHook: EventsHook, data: {
26
- chatHistory: Record<string, string>[];
27
- phone: string;
28
26
  appRef: string;
29
- sessionRef: string;
27
+ callRef: string;
28
+ phone: string;
29
+ chatHistory: Record<string, string>[];
30
+ recordingUrl: string;
30
31
  }): Promise<void>;
@@ -23,7 +23,7 @@ const common_1 = require("@fonoster/common");
23
23
  const logger_1 = require("@fonoster/logger");
24
24
  const logger = (0, logger_1.getLogger)({ service: "autopilot", filePath: __filename });
25
25
  async function sendConversationEndedEvent(eventsHook, data) {
26
- const { chatHistory, phone, appRef, sessionRef } = data;
26
+ const { chatHistory, phone, appRef, callRef, recordingUrl } = data;
27
27
  if (!eventsHook?.events.includes(common_1.EventsHookAllowedEvents.CONVERSATION_ENDED) &&
28
28
  !eventsHook?.events.includes(common_1.EventsHookAllowedEvents.ALL)) {
29
29
  return;
@@ -32,9 +32,10 @@ async function sendConversationEndedEvent(eventsHook, data) {
32
32
  const params = {
33
33
  eventType: common_1.EventsHookAllowedEvents.CONVERSATION_ENDED,
34
34
  appRef,
35
- sessionRef,
35
+ callRef,
36
36
  phone,
37
- chatHistory
37
+ chatHistory,
38
+ ...(recordingUrl && { recordingUrl })
38
39
  };
39
40
  try {
40
41
  await (0, common_1.sendHttpRequest)({
@@ -3,7 +3,7 @@ import { Voice } from "./types";
3
3
  declare class VoiceImpl implements Voice {
4
4
  private readonly voice;
5
5
  private readonly playbackRef;
6
- sessionRef: string;
6
+ mediaSessionRef: string;
7
7
  sgatherStream: {
8
8
  stop: () => Promise<void>;
9
9
  onData: (cb: (payload: {
@@ -15,7 +15,7 @@ declare class VoiceImpl implements Voice {
15
15
  stop: () => Promise<void>;
16
16
  onData: (cb: (chunk: Uint8Array) => void) => void;
17
17
  };
18
- constructor(sessionRef: string, voice: VoiceResponse);
18
+ constructor(mediaSessionRef: string, voice: VoiceResponse);
19
19
  answer(): Promise<void>;
20
20
  hangup(): Promise<void>;
21
21
  say(text: string): Promise<void>;
@@ -22,9 +22,9 @@ exports.VoiceImpl = void 0;
22
22
  const common_1 = require("@fonoster/common");
23
23
  const uuid_1 = require("uuid");
24
24
  class VoiceImpl {
25
- constructor(sessionRef, voice) {
25
+ constructor(mediaSessionRef, voice) {
26
26
  this.voice = voice;
27
- this.sessionRef = sessionRef;
27
+ this.mediaSessionRef = mediaSessionRef;
28
28
  this.playbackRef = (0, uuid_1.v4)();
29
29
  }
30
30
  async answer() {
@@ -32,7 +32,7 @@ type TransferOptions = {
32
32
  record?: boolean;
33
33
  };
34
34
  type Voice = {
35
- sessionRef: string;
35
+ mediaSessionRef: string;
36
36
  answer: () => Promise<void>;
37
37
  hangup: () => Promise<void>;
38
38
  say: (text: string) => Promise<void>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fonoster/autopilot",
3
- "version": "0.16.11",
3
+ "version": "0.17.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",
@@ -35,11 +35,11 @@
35
35
  "dependencies": {
36
36
  "@aws-sdk/client-s3": "^3.958.0",
37
37
  "@dmitryrechkin/json-schema-to-zod": "^1.0.1",
38
- "@fonoster/common": "^0.16.8",
39
- "@fonoster/logger": "^0.16.7",
40
- "@fonoster/sdk": "^0.16.8",
41
- "@fonoster/types": "^0.16.7",
42
- "@fonoster/voice": "^0.16.10",
38
+ "@fonoster/common": "^0.17.0",
39
+ "@fonoster/logger": "^0.17.0",
40
+ "@fonoster/sdk": "^0.17.0",
41
+ "@fonoster/types": "^0.17.0",
42
+ "@fonoster/voice": "^0.17.0",
43
43
  "@langchain/anthropic": "^1.3.3",
44
44
  "@langchain/community": "^1.1.1",
45
45
  "@langchain/core": "^1.1.8",
@@ -59,5 +59,5 @@
59
59
  "xstate": "^5.17.3",
60
60
  "zod": "^3.25.76"
61
61
  },
62
- "gitHead": "680281a11296cb509f64823461a30de237960a05"
62
+ "gitHead": "4d1a9afaec6f294184386e009d1a4e292fb3583b"
63
63
  }