@fonoster/autopilot 0.8.59 → 0.8.65

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.
@@ -64,6 +64,7 @@ const loadAssistantConfigFromFile_1 = require("./loadAssistantConfigFromFile");
64
64
  const _1 = __importStar(require("."));
65
65
  const loadAssistantFromAPI_1 = require("./loadAssistantFromAPI");
66
66
  const fs_1 = __importDefault(require("fs"));
67
+ const sendConversationEndedEvent_1 = require("./sendConversationEndedEvent");
67
68
  const logger = (0, logger_1.getLogger)({ service: "autopilot", filePath: __filename });
68
69
  async function handleVoiceRequest(req, res) {
69
70
  const { accessKeyId, callerNumber, ingressNumber, sessionRef, appRef, callDirection } = req;
@@ -116,7 +117,20 @@ async function handleVoiceRequest(req, res) {
116
117
  languageModel
117
118
  });
118
119
  autopilot.start();
119
- res.on(common_1.StreamEvent.END, () => {
120
+ res.on(common_1.StreamEvent.END, async () => {
120
121
  autopilot.stop();
122
+ const rawChatHistory = await languageModel.getChatHistoryMessages();
123
+ const chatHistory = rawChatHistory
124
+ .map((msg) => {
125
+ if (msg.constructor.name === "HumanMessage") {
126
+ return { human: msg.content };
127
+ }
128
+ else if (msg.constructor.name === "AIMessage") {
129
+ return { ai: msg.content };
130
+ }
131
+ return null;
132
+ })
133
+ .filter(Boolean);
134
+ await (0, sendConversationEndedEvent_1.sendConversationEndedEvent)(assistantConfig.eventsHook, chatHistory);
121
135
  });
122
136
  }
@@ -5,7 +5,11 @@ declare abstract class AbstractLanguageModel implements LanguageModel {
5
5
  private readonly chatHistory;
6
6
  private readonly toolsCatalog;
7
7
  private readonly voice;
8
+ private readonly goodbyeMessage;
9
+ private readonly firstMessage;
10
+ private readonly transferOptions;
8
11
  constructor(params: LanguageModelParams, voice: Voice, telephonyContext: TelephonyContext);
9
12
  invoke(text: string): Promise<InvocationResult>;
13
+ getChatHistoryMessages(): Promise<import("@langchain/core/messages").BaseMessage[]>;
10
14
  }
11
15
  export { AbstractLanguageModel };
@@ -28,12 +28,14 @@ const tools_1 = require("../tools");
28
28
  const logger = (0, logger_1.getLogger)({ service: "autopilot", filePath: __filename });
29
29
  class AbstractLanguageModel {
30
30
  constructor(params, voice, telephonyContext) {
31
- const { model, firstMessage, systemPrompt, knowledgeBase, tools } = params;
31
+ const { model, firstMessage, transferOptions, systemPrompt, goodbyeMessage, knowledgeBase, tools } = params;
32
32
  this.chatHistory = (0, chatHistory_1.createChatHistory)();
33
33
  this.toolsCatalog = new tools_1.ToolsCatalog(tools);
34
34
  this.voice = voice;
35
+ this.firstMessage = firstMessage;
36
+ this.goodbyeMessage = goodbyeMessage;
37
+ this.transferOptions = transferOptions;
35
38
  const promptTemplate = (0, createPromptTemplate_1.createPromptTemplate)({
36
- firstMessage,
37
39
  systemPrompt,
38
40
  telephonyContext
39
41
  });
@@ -43,12 +45,16 @@ class AbstractLanguageModel {
43
45
  const { chain, chatHistory, toolsCatalog } = this;
44
46
  const response = (await chain.invoke({ text }));
45
47
  let isFirstTool = true;
46
- logger.verbose("invoke", { text });
47
- logger.verbose("response", { content: response.content });
48
- logger.verbose("tools?", {
48
+ logger.verbose("invoke", {
49
+ text,
50
+ response: response.content,
49
51
  hasTools: response.tool_calls?.length > 0,
50
52
  tools: response.tool_calls?.map((tool) => tool.name)
51
53
  });
54
+ // Begin the conversation with the first message
55
+ if ((await chatHistory.getMessages()).length === 0 && this.firstMessage) {
56
+ await chatHistory.addAIMessage(this.firstMessage);
57
+ }
52
58
  if (response.tool_calls && response.tool_calls.length > 0) {
53
59
  // eslint-disable-next-line no-loops/no-loops
54
60
  for (const toolCall of response.tool_calls) {
@@ -58,17 +64,19 @@ class AbstractLanguageModel {
58
64
  });
59
65
  switch (toolName) {
60
66
  case "hangup":
61
- await chatHistory.addAIMessage("tool result: call hangup initiated");
67
+ await chatHistory.addUserMessage(text);
68
+ await chatHistory.addAIMessage(this.goodbyeMessage);
62
69
  return {
63
70
  type: "hangup",
64
- content: "tool result: call hangup initiated",
71
+ content: "tool_result: call hangup initiated",
65
72
  toolCalls: response.tool_calls
66
73
  };
67
74
  case "transfer":
68
- await chatHistory.addAIMessage("tool result: call transfer initiated");
75
+ await chatHistory.addUserMessage(text);
76
+ await chatHistory.addAIMessage(this.transferOptions.message);
69
77
  return {
70
78
  type: "transfer",
71
- content: "tool result: call transfer initiated",
79
+ content: "tool_result: call transfer initiated",
72
80
  toolCalls: response.tool_calls
73
81
  };
74
82
  default:
@@ -101,5 +109,8 @@ class AbstractLanguageModel {
101
109
  toolCalls: response.tool_calls
102
110
  };
103
111
  }
112
+ async getChatHistoryMessages() {
113
+ return this.chatHistory.getMessages();
114
+ }
104
115
  }
105
116
  exports.AbstractLanguageModel = AbstractLanguageModel;
@@ -1 +1 @@
1
- export declare const textSimilaryPrompt = "\nYou are a text similarity evaluator for a Voice Assistant application. \n\nGive Text1 and Text2, you use the following process to evaluate the similarity between the two texts:\n\n- Take the first text and determmine the intent of the text.\n- Take the second text and determine the intent of the text.\n- Compare the intents of the two texts ignoring the actual text content and the entities, and length of the text.\n\n## Example 1\n\nText1: \"You're welcome. Have a great day!\"\nText2: \"You're welcome [name]. Your appointment is confirmed. Goodbye!\"\n\nAnswer: true\n\n=== \n\nAre the intents of the two texts the same? Respond with true.\n";
1
+ export declare const textSimilaryPrompt = "\nYou are a text similarity evaluator for a Voice Assistant application. \n\nGive Text1 and Text2, you use the following process to evaluate the similarity between the two texts:\n\n- Take the first text and determmine the intent of the text.\n- Take the second text and determine the intent of the text.\n- Compare the intents of the two texts ignoring the actual text content, the entities, and length of the text.\n\n## Example 1\n\nText1: \"You're welcome. Have a great day!\"\nText2: \"You're welcome [name]. Your appointment is confirmed. Goodbye!\"\n\nAnswer: true\n\n=== \n\nAre the intents of the two texts the same? Respond with true.\n";
@@ -26,7 +26,7 @@ Give Text1 and Text2, you use the following process to evaluate the similarity b
26
26
 
27
27
  - Take the first text and determmine the intent of the text.
28
28
  - Take the second text and determine the intent of the text.
29
- - Compare the intents of the two texts ignoring the actual text content and the entities, and length of the text.
29
+ - Compare the intents of the two texts ignoring the actual text content, the entities, and length of the text.
30
30
 
31
31
  ## Example 1
32
32
 
@@ -1,13 +1,17 @@
1
1
  import { CallDirection } from "@fonoster/types";
2
2
  import { BaseChatModel } from "@langchain/core/language_models/chat_models";
3
- import { KnowledgeBase } from "../knowledge";
4
3
  import { Tool } from "../tools/type";
5
4
  import { ToolCall } from "@langchain/core/messages/tool";
5
+ import { KnowledgeBase } from "../knowledge";
6
6
  type LanguageModel = {
7
7
  invoke: (text: string) => Promise<InvocationResult>;
8
8
  };
9
9
  type BaseModelParams = {
10
10
  firstMessage?: string;
11
+ goodbyeMessage?: string;
12
+ transferOptions: {
13
+ message: string;
14
+ };
11
15
  systemPrompt: string;
12
16
  knowledgeBase: KnowledgeBase;
13
17
  tools: Tool[];
@@ -0,0 +1,8 @@
1
+ import { EventsHookAllowedEvents } from "@fonoster/common";
2
+ type EventsHook = {
3
+ url: string;
4
+ events: EventsHookAllowedEvents[];
5
+ headers?: Record<string, string>;
6
+ };
7
+ export declare function sendConversationEndedEvent(eventsHook: EventsHook, chatHistory: Record<string, string>[]): Promise<void>;
8
+ export {};
@@ -0,0 +1,47 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.sendConversationEndedEvent = sendConversationEndedEvent;
4
+ /*
5
+ * Copyright (C) 2025 by Fonoster Inc (https://fonoster.com)
6
+ * http://github.com/fonoster/fonoster
7
+ *
8
+ * This file is part of Fonoster
9
+ *
10
+ * Licensed under the MIT License (the "License");
11
+ * you may not use this file except in compliance with
12
+ * the License. You may obtain a copy of the License at
13
+ *
14
+ * https://opensource.org/licenses/MIT
15
+ *
16
+ * Unless required by applicable law or agreed to in writing, software
17
+ * distributed under the License is distributed on an "AS IS" BASIS,
18
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19
+ * See the License for the specific language governing permissions and
20
+ * limitations under the License.
21
+ */
22
+ const common_1 = require("@fonoster/common");
23
+ const logger_1 = require("@fonoster/logger");
24
+ const logger = (0, logger_1.getLogger)({ service: "autopilot", filePath: __filename });
25
+ async function sendConversationEndedEvent(eventsHook, chatHistory) {
26
+ if (!eventsHook?.events.includes(common_1.EventsHookAllowedEvents.CONVERSATION_ENDED) &&
27
+ !eventsHook?.events.includes(common_1.EventsHookAllowedEvents.ALL)) {
28
+ return;
29
+ }
30
+ const parsedEventsHook = common_1.eventsHookSchema.parse(eventsHook);
31
+ const body = {
32
+ eventType: common_1.EventsHookAllowedEvents.CONVERSATION_ENDED,
33
+ chatHistory
34
+ };
35
+ try {
36
+ await (0, common_1.sendHttpRequest)({
37
+ url: parsedEventsHook.url,
38
+ method: common_1.AllowedHttpMethod.POST,
39
+ headers: parsedEventsHook.headers,
40
+ waitForResponse: false,
41
+ body
42
+ });
43
+ }
44
+ catch (e) {
45
+ logger.error("error sending event", e);
46
+ }
47
+ }
@@ -20,7 +20,7 @@ exports.ToolsCatalog = void 0;
20
20
  * limitations under the License.
21
21
  */
22
22
  const logger_1 = require("@fonoster/logger");
23
- const sendRequest_1 = require("./sendRequest");
23
+ const common_1 = require("@fonoster/common");
24
24
  const logger = (0, logger_1.getLogger)({ service: "autopilot", filePath: __filename });
25
25
  class ToolsCatalog {
26
26
  constructor(tools) {
@@ -35,11 +35,13 @@ class ToolsCatalog {
35
35
  if (!tool) {
36
36
  throw new Error(`Tool '${toolName}' not found in the catalog`);
37
37
  }
38
- return await (0, sendRequest_1.sendRequest)({
39
- method: tool.operation.type,
40
- url: tool.operation.url,
41
- waitForResponse: tool.operation.waitForResponse,
42
- headers: tool.operation.headers,
38
+ const parsedTool = common_1.toolSchema.parse(tool);
39
+ // FIXME: We shouldn't have to check the nullability of the operation
40
+ return await (0, common_1.sendHttpRequest)({
41
+ method: parsedTool.operation?.method,
42
+ url: parsedTool.operation?.url,
43
+ waitForResponse: parsedTool.operation?.waitForResponse,
44
+ headers: parsedTool.operation?.headers,
43
45
  body: args
44
46
  });
45
47
  }
@@ -1,3 +1,3 @@
1
- import { Tool } from "../type";
2
- declare const hangupToolDefinition: Tool;
1
+ import { BuiltInTool } from "../type";
2
+ declare const hangupToolDefinition: BuiltInTool;
3
3
  export { hangupToolDefinition };
@@ -1,25 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.hangupToolDefinition = void 0;
4
- /*
5
- * Copyright (C) 2025 by Fonoster Inc (https://fonoster.com)
6
- * http://github.com/fonoster/fonoster
7
- *
8
- * This file is part of Fonoster
9
- *
10
- * Licensed under the MIT License (the "License");
11
- * you may not use this file except in compliance with
12
- * the License. You may obtain a copy of the License at
13
- *
14
- * https://opensource.org/licenses/MIT
15
- *
16
- * Unless required by applicable law or agreed to in writing, software
17
- * distributed under the License is distributed on an "AS IS" BASIS,
18
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19
- * See the License for the specific language governing permissions and
20
- * limitations under the License.
21
- */
22
- const ToolSchema_1 = require("../ToolSchema");
23
4
  const hangupToolDefinition = {
24
5
  name: "hangup",
25
6
  description: "Hangup the call and end the conversation",
@@ -27,9 +8,6 @@ const hangupToolDefinition = {
27
8
  type: "object",
28
9
  properties: {},
29
10
  required: []
30
- },
31
- operation: {
32
- type: ToolSchema_1.AllowedOperations.BUILT_IN
33
11
  }
34
12
  };
35
13
  exports.hangupToolDefinition = hangupToolDefinition;
@@ -1,3 +1,3 @@
1
- import { Tool } from "../type";
2
- declare const transferToolDefinition: Tool;
1
+ import { BuiltInTool } from "../type";
2
+ declare const transferToolDefinition: BuiltInTool;
3
3
  export { transferToolDefinition };
@@ -1,25 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.transferToolDefinition = void 0;
4
- /*
5
- * Copyright (C) 2025 by Fonoster Inc (https://fonoster.com)
6
- * http://github.com/fonoster/fonoster
7
- *
8
- * This file is part of Fonoster
9
- *
10
- * Licensed under the MIT License (the "License");
11
- * you may not use this file except in compliance with
12
- * the License. You may obtain a copy of the License at
13
- *
14
- * https://opensource.org/licenses/MIT
15
- *
16
- * Unless required by applicable law or agreed to in writing, software
17
- * distributed under the License is distributed on an "AS IS" BASIS,
18
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19
- * See the License for the specific language governing permissions and
20
- * limitations under the License.
21
- */
22
- const ToolSchema_1 = require("../ToolSchema");
23
4
  const transferToolDefinition = {
24
5
  name: "transfer",
25
6
  description: "Transfer the call to a live agent",
@@ -27,9 +8,6 @@ const transferToolDefinition = {
27
8
  type: "object",
28
9
  properties: {},
29
10
  required: []
30
- },
31
- operation: {
32
- type: ToolSchema_1.AllowedOperations.BUILT_IN
33
11
  }
34
12
  };
35
13
  exports.transferToolDefinition = transferToolDefinition;
@@ -1,8 +1,9 @@
1
1
  import { z } from "zod";
2
- import { toolSchema } from "./ToolSchema";
2
+ import { toolSchema } from "@fonoster/common";
3
3
  type Tool = z.infer<typeof toolSchema>;
4
+ type BuiltInTool = Omit<Tool, "operation">;
4
5
  type OpenAITool = {
5
6
  type: "function";
6
7
  function: Omit<Tool, "operation">;
7
8
  };
8
- export { OpenAITool, Tool };
9
+ export { OpenAITool, Tool, BuiltInTool };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fonoster/autopilot",
3
- "version": "0.8.59",
3
+ "version": "0.8.65",
4
4
  "description": "Voice AI for the Fonoster platform",
5
5
  "author": "Pedro Sanders <psanders@fonoster.com>",
6
6
  "homepage": "https://github.com/fonoster/fonoster#readme",
@@ -33,11 +33,11 @@
33
33
  },
34
34
  "dependencies": {
35
35
  "@aws-sdk/client-s3": "^3.712.0",
36
- "@fonoster/common": "^0.8.59",
36
+ "@fonoster/common": "^0.8.64",
37
37
  "@fonoster/logger": "^0.8.59",
38
- "@fonoster/sdk": "^0.8.59",
38
+ "@fonoster/sdk": "^0.8.65",
39
39
  "@fonoster/types": "^0.8.59",
40
- "@fonoster/voice": "^0.8.59",
40
+ "@fonoster/voice": "^0.8.65",
41
41
  "@langchain/community": "^0.3.29",
42
42
  "@langchain/core": "^0.3.39",
43
43
  "@langchain/groq": "^0.1.3",
@@ -57,5 +57,5 @@
57
57
  "devDependencies": {
58
58
  "typescript": "^5.5.4"
59
59
  },
60
- "gitHead": "6a5255febb9e4bcd9184d93abe72281f945c8c4d"
60
+ "gitHead": "eebe765c78a8a39a1254fceca416e919d0415c3d"
61
61
  }
@@ -1,117 +0,0 @@
1
- import { z } from "zod";
2
- declare enum AllowedOperations {
3
- GET = "get",
4
- POST = "post",
5
- BUILT_IN = "built-in"
6
- }
7
- declare const toolSchema: z.ZodObject<{
8
- name: z.ZodString;
9
- description: z.ZodString;
10
- parameters: z.ZodObject<{
11
- type: z.ZodEnum<["object", "array"]>;
12
- properties: z.ZodRecord<z.ZodString, z.ZodEffects<z.ZodObject<{
13
- type: z.ZodString;
14
- format: z.ZodOptional<z.ZodString>;
15
- pattern: z.ZodOptional<z.ZodString>;
16
- }, "strip", z.ZodTypeAny, {
17
- type: string;
18
- format?: string | undefined;
19
- pattern?: string | undefined;
20
- }, {
21
- type: string;
22
- format?: string | undefined;
23
- pattern?: string | undefined;
24
- }>, {
25
- type: string;
26
- format?: string | undefined;
27
- pattern?: string | undefined;
28
- }, {
29
- type: string;
30
- format?: string | undefined;
31
- pattern?: string | undefined;
32
- }>>;
33
- required: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
34
- }, "strip", z.ZodTypeAny, {
35
- type: "object" | "array";
36
- properties: Record<string, {
37
- type: string;
38
- format?: string | undefined;
39
- pattern?: string | undefined;
40
- }>;
41
- required?: string[] | undefined;
42
- }, {
43
- type: "object" | "array";
44
- properties: Record<string, {
45
- type: string;
46
- format?: string | undefined;
47
- pattern?: string | undefined;
48
- }>;
49
- required?: string[] | undefined;
50
- }>;
51
- requestStartMessage: z.ZodOptional<z.ZodString>;
52
- operation: z.ZodEffects<z.ZodObject<{
53
- type: z.ZodNativeEnum<typeof AllowedOperations>;
54
- url: z.ZodOptional<z.ZodString>;
55
- waitForResponse: z.ZodOptional<z.ZodBoolean>;
56
- headers: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
57
- }, "strip", z.ZodTypeAny, {
58
- type: AllowedOperations;
59
- url?: string | undefined;
60
- waitForResponse?: boolean | undefined;
61
- headers?: Record<string, string> | undefined;
62
- }, {
63
- type: AllowedOperations;
64
- url?: string | undefined;
65
- waitForResponse?: boolean | undefined;
66
- headers?: Record<string, string> | undefined;
67
- }>, {
68
- type: AllowedOperations;
69
- url?: string | undefined;
70
- waitForResponse?: boolean | undefined;
71
- headers?: Record<string, string> | undefined;
72
- }, {
73
- type: AllowedOperations;
74
- url?: string | undefined;
75
- waitForResponse?: boolean | undefined;
76
- headers?: Record<string, string> | undefined;
77
- }>;
78
- }, "strip", z.ZodTypeAny, {
79
- name: string;
80
- description: string;
81
- parameters: {
82
- type: "object" | "array";
83
- properties: Record<string, {
84
- type: string;
85
- format?: string | undefined;
86
- pattern?: string | undefined;
87
- }>;
88
- required?: string[] | undefined;
89
- };
90
- operation: {
91
- type: AllowedOperations;
92
- url?: string | undefined;
93
- waitForResponse?: boolean | undefined;
94
- headers?: Record<string, string> | undefined;
95
- };
96
- requestStartMessage?: string | undefined;
97
- }, {
98
- name: string;
99
- description: string;
100
- parameters: {
101
- type: "object" | "array";
102
- properties: Record<string, {
103
- type: string;
104
- format?: string | undefined;
105
- pattern?: string | undefined;
106
- }>;
107
- required?: string[] | undefined;
108
- };
109
- operation: {
110
- type: AllowedOperations;
111
- url?: string | undefined;
112
- waitForResponse?: boolean | undefined;
113
- headers?: Record<string, string> | undefined;
114
- };
115
- requestStartMessage?: string | undefined;
116
- }>;
117
- export { AllowedOperations, toolSchema };
@@ -1,69 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.toolSchema = exports.AllowedOperations = void 0;
4
- /*
5
- * Copyright (C) 2025 by Fonoster Inc (https://fonoster.com)
6
- * http://github.com/fonoster/fonoster
7
- *
8
- * This file is part of Fonoster
9
- *
10
- * Licensed under the MIT License (the "License");
11
- * you may not use this file except in compliance with
12
- * the License. You may obtain a copy of the License at
13
- *
14
- * https://opensource.org/licenses/MIT
15
- *
16
- * Unless required by applicable law or agreed to in writing, software
17
- * distributed under the License is distributed on an "AS IS" BASIS,
18
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19
- * See the License for the specific language governing permissions and
20
- * limitations under the License.
21
- */
22
- const common_1 = require("@fonoster/common");
23
- const zod_1 = require("zod");
24
- var AllowedOperations;
25
- (function (AllowedOperations) {
26
- AllowedOperations["GET"] = "get";
27
- AllowedOperations["POST"] = "post";
28
- AllowedOperations["BUILT_IN"] = "built-in";
29
- })(AllowedOperations || (exports.AllowedOperations = AllowedOperations = {}));
30
- const propertySchema = zod_1.z
31
- .object({
32
- type: zod_1.z.string(),
33
- format: zod_1.z.string().optional(),
34
- pattern: zod_1.z.string().optional()
35
- })
36
- .refine((data) => {
37
- return !("format" in data && "pattern" in data);
38
- }, {
39
- message: "Property can only have either 'format' or 'pattern', not both."
40
- });
41
- const toolSchema = zod_1.z.object({
42
- name: zod_1.z.string(),
43
- description: zod_1.z.string(),
44
- parameters: zod_1.z.object({
45
- type: zod_1.z.enum(["object", "array"]),
46
- properties: zod_1.z.record(propertySchema),
47
- required: zod_1.z.array(zod_1.z.string()).optional()
48
- }),
49
- requestStartMessage: zod_1.z.string().optional(),
50
- operation: zod_1.z
51
- .object({
52
- type: zod_1.z.nativeEnum(AllowedOperations, {
53
- message: "Invalid operation type"
54
- }),
55
- // Make url required if operation type is not built-in
56
- url: zod_1.z.string().url({ message: common_1.Messages.VALID_URL }).optional(),
57
- waitForResponse: zod_1.z.boolean().optional(),
58
- headers: zod_1.z.record(zod_1.z.string()).optional()
59
- })
60
- .superRefine(({ url, type }, ctx) => {
61
- if (type !== AllowedOperations.BUILT_IN && !url) {
62
- ctx.addIssue({
63
- code: zod_1.z.ZodIssueCode.custom,
64
- message: "Url is required for non built-in operations."
65
- });
66
- }
67
- })
68
- });
69
- exports.toolSchema = toolSchema;
@@ -1,11 +0,0 @@
1
- import { AllowedOperations } from "./ToolSchema";
2
- declare function sendRequest(input: {
3
- method: AllowedOperations;
4
- url: string;
5
- waitForResponse: boolean;
6
- headers?: Record<string, string>;
7
- body?: Record<string, unknown>;
8
- }): Promise<{
9
- result: string;
10
- }>;
11
- export { sendRequest };
@@ -1,54 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.sendRequest = sendRequest;
4
- /*
5
- * Copyright (C) 2025 by Fonoster Inc (https://fonoster.com)
6
- * http://github.com/fonoster/fonoster
7
- *
8
- * This file is part of Fonoster
9
- *
10
- * Licensed under the MIT License (the "License");
11
- * you may not use this file except in compliance with
12
- * the License. You may obtain a copy of the License at
13
- *
14
- * https://opensource.org/licenses/MIT
15
- *
16
- * Unless required by applicable law or agreed to in writing, software
17
- * distributed under the License is distributed on an "AS IS" BASIS,
18
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19
- * See the License for the specific language governing permissions and
20
- * limitations under the License.
21
- */
22
- const logger_1 = require("@fonoster/logger");
23
- const zod_1 = require("zod");
24
- const ToolSchema_1 = require("./ToolSchema");
25
- const responseSchema = zod_1.z.object({
26
- result: zod_1.z.string()
27
- });
28
- const logger = (0, logger_1.getLogger)({ service: "autopilot", filePath: __filename });
29
- async function sendRequest(input) {
30
- const { url, method, body, headers, waitForResponse } = input;
31
- const options = {
32
- method,
33
- headers: {
34
- "Content-Type": "application/json",
35
- ...headers
36
- },
37
- body: method === ToolSchema_1.AllowedOperations.POST ? JSON.stringify(body) : undefined
38
- };
39
- logger.verbose(`sending request to ${url}`, { body, method });
40
- if (waitForResponse && method === ToolSchema_1.AllowedOperations.POST) {
41
- setTimeout(() => fetch(url, options), 0);
42
- return { result: "request sent" };
43
- }
44
- else {
45
- const response = await fetch(url, options);
46
- const data = await response.json();
47
- try {
48
- return responseSchema.parse(data);
49
- }
50
- catch (error) {
51
- throw new Error(`Invalid response: expected ${JSON.stringify(responseSchema, null, 2)}, got ${JSON.stringify(data, null, 2)}`);
52
- }
53
- }
54
- }