@wabot-dev/framework 0.5.14 → 0.6.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/dist/src/addon/chat-bot/anthropic/AnthropicChatAdapter.js +63 -2
- package/dist/src/addon/chat-bot/deepseek/DeepSeekChatAdapter.js +9 -2
- package/dist/src/addon/chat-bot/google/GoogleChatAdapter.js +53 -2
- package/dist/src/addon/chat-bot/openia/OpenaiChatAdapter.js +35 -4
- package/dist/src/addon/chat-bot/openrouter/OpenRouterChatAdapter.js +178 -0
- package/dist/src/addon/chat-controller/telegram/TelegramChannel.js +1 -0
- package/dist/src/core/validation/validators/is-boolean/@isBoolean.js +1 -1
- package/dist/src/feature/chat-bot/extractChatMessageText.js +18 -2
- package/dist/src/feature/chat-bot/isChatMessageEmpty.js +5 -0
- package/dist/src/feature/mindset/MindsetOperator.js +15 -2
- package/dist/src/feature/pg/PgCrudRepository.js +2 -2
- package/dist/src/index.d.ts +34 -5
- package/dist/src/index.js +2 -0
- package/package.json +4 -3
- package/dist/src/addon/chat-controller/whatsapp-by-wasender/@whatsAppByWasender.js +0 -20
- package/dist/src/addon/chat-controller/whatsapp-by-wasender/WhatsAppByWasenderChannel.js +0 -52
- package/dist/src/addon/chat-controller/whatsapp-by-wasender/WhatsAppByWasenderChannelConfig.js +0 -16
- package/dist/src/addon/chat-controller/whatsapp-by-wasender/WhatsAppReceiverByWasender.js +0 -106
- package/dist/src/addon/chat-controller/whatsapp-by-wasender/WhatsAppSenderByWasender.js +0 -40
- package/dist/src/addon/chat-controller/whatsapp-by-wasender/extractNumberFromWasenderKey.js +0 -5
|
@@ -7,8 +7,16 @@ import 'uuid';
|
|
|
7
7
|
import '../../../feature/chat-bot/metadata/ChatBotMetadataStore.js';
|
|
8
8
|
import { safeJsonParse } from '../../../feature/chat-bot/safeJsonParse.js';
|
|
9
9
|
import { extractChatMessageText } from '../../../feature/chat-bot/extractChatMessageText.js';
|
|
10
|
+
import { isChatMessageEmpty } from '../../../feature/chat-bot/isChatMessageEmpty.js';
|
|
10
11
|
import { Anthropic } from '@anthropic-ai/sdk';
|
|
11
12
|
|
|
13
|
+
const ANTHROPIC_SUPPORTED_IMAGE_MIME_TYPES = [
|
|
14
|
+
'image/png',
|
|
15
|
+
'image/jpeg',
|
|
16
|
+
'image/gif',
|
|
17
|
+
'image/webp',
|
|
18
|
+
];
|
|
19
|
+
const ANTHROPIC_SUPPORTED_DOCUMENT_MIME_TYPES = ['application/pdf', 'text/plain'];
|
|
12
20
|
let AnthropicChatAdapter = class AnthropicChatAdapter {
|
|
13
21
|
env;
|
|
14
22
|
anthropic;
|
|
@@ -50,10 +58,59 @@ let AnthropicChatAdapter = class AnthropicChatAdapter {
|
|
|
50
58
|
return messages;
|
|
51
59
|
}
|
|
52
60
|
mapHumanMessage(item) {
|
|
53
|
-
if (
|
|
61
|
+
if (isChatMessageEmpty(item)) {
|
|
54
62
|
throw new Error('User message content is empty');
|
|
55
63
|
}
|
|
56
|
-
|
|
64
|
+
const blocks = [];
|
|
65
|
+
blocks.push({
|
|
66
|
+
type: 'text',
|
|
67
|
+
text: extractChatMessageText(item, {
|
|
68
|
+
supportedImageMimeTypes: ANTHROPIC_SUPPORTED_IMAGE_MIME_TYPES,
|
|
69
|
+
supportedDocumentMimeTypes: ANTHROPIC_SUPPORTED_DOCUMENT_MIME_TYPES,
|
|
70
|
+
}),
|
|
71
|
+
});
|
|
72
|
+
if (item.images) {
|
|
73
|
+
for (const image of item.images) {
|
|
74
|
+
if (!ANTHROPIC_SUPPORTED_IMAGE_MIME_TYPES.includes(image.mimeType))
|
|
75
|
+
continue;
|
|
76
|
+
blocks.push({ type: 'image', source: this.toAnthropicImageSource(image) });
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
if (item.documents) {
|
|
80
|
+
for (const doc of item.documents) {
|
|
81
|
+
if (!ANTHROPIC_SUPPORTED_DOCUMENT_MIME_TYPES.includes(doc.mimeType))
|
|
82
|
+
continue;
|
|
83
|
+
blocks.push({ type: 'document', source: this.toAnthropicDocumentSource(doc) });
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return { role: 'user', content: blocks };
|
|
87
|
+
}
|
|
88
|
+
toAnthropicImageSource(image) {
|
|
89
|
+
if (image.publicUrl) {
|
|
90
|
+
return { type: 'url', url: image.publicUrl };
|
|
91
|
+
}
|
|
92
|
+
return {
|
|
93
|
+
type: 'base64',
|
|
94
|
+
media_type: image.mimeType,
|
|
95
|
+
data: stripDataUrlPrefix(image.base64Url),
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
toAnthropicDocumentSource(doc) {
|
|
99
|
+
if (doc.publicUrl) {
|
|
100
|
+
return { type: 'url', url: doc.publicUrl };
|
|
101
|
+
}
|
|
102
|
+
if (doc.mimeType === 'text/plain') {
|
|
103
|
+
return {
|
|
104
|
+
type: 'text',
|
|
105
|
+
media_type: 'text/plain',
|
|
106
|
+
data: Buffer.from(stripDataUrlPrefix(doc.base64Url), 'base64').toString('utf-8'),
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
return {
|
|
110
|
+
type: 'base64',
|
|
111
|
+
media_type: 'application/pdf',
|
|
112
|
+
data: stripDataUrlPrefix(doc.base64Url),
|
|
113
|
+
};
|
|
57
114
|
}
|
|
58
115
|
mapBotMessage(item) {
|
|
59
116
|
if (!item.text) {
|
|
@@ -134,5 +191,9 @@ AnthropicChatAdapter = __decorate([
|
|
|
134
191
|
singleton(),
|
|
135
192
|
__metadata("design:paramtypes", [Env])
|
|
136
193
|
], AnthropicChatAdapter);
|
|
194
|
+
function stripDataUrlPrefix(dataUrl) {
|
|
195
|
+
const commaIndex = dataUrl.indexOf(',');
|
|
196
|
+
return commaIndex >= 0 && dataUrl.startsWith('data:') ? dataUrl.slice(commaIndex + 1) : dataUrl;
|
|
197
|
+
}
|
|
137
198
|
|
|
138
199
|
export { AnthropicChatAdapter };
|
|
@@ -5,6 +5,7 @@ import 'uuid';
|
|
|
5
5
|
import '../../../feature/chat-bot/metadata/ChatBotMetadataStore.js';
|
|
6
6
|
import '../../../core/error/setupErrorHandlers.js';
|
|
7
7
|
import { extractChatMessageText } from '../../../feature/chat-bot/extractChatMessageText.js';
|
|
8
|
+
import { isChatMessageEmpty } from '../../../feature/chat-bot/isChatMessageEmpty.js';
|
|
8
9
|
import { OpenAI } from 'openai';
|
|
9
10
|
|
|
10
11
|
class DeepSeekChatAdapter {
|
|
@@ -55,10 +56,16 @@ class DeepSeekChatAdapter {
|
|
|
55
56
|
return deepSeekInput;
|
|
56
57
|
}
|
|
57
58
|
mapHumanMessage(item) {
|
|
58
|
-
if (
|
|
59
|
+
if (isChatMessageEmpty(item)) {
|
|
59
60
|
throw new Error('User message content is empty');
|
|
60
61
|
}
|
|
61
|
-
return {
|
|
62
|
+
return {
|
|
63
|
+
role: 'user',
|
|
64
|
+
content: extractChatMessageText(item, {
|
|
65
|
+
supportedImageMimeTypes: [],
|
|
66
|
+
supportedDocumentMimeTypes: [],
|
|
67
|
+
}),
|
|
68
|
+
};
|
|
62
69
|
}
|
|
63
70
|
mapBotMessage(item) {
|
|
64
71
|
if (!item.text) {
|
|
@@ -8,8 +8,26 @@ import 'uuid';
|
|
|
8
8
|
import '../../../feature/chat-bot/metadata/ChatBotMetadataStore.js';
|
|
9
9
|
import { safeJsonParse } from '../../../feature/chat-bot/safeJsonParse.js';
|
|
10
10
|
import { extractChatMessageText } from '../../../feature/chat-bot/extractChatMessageText.js';
|
|
11
|
+
import { isChatMessageEmpty } from '../../../feature/chat-bot/isChatMessageEmpty.js';
|
|
11
12
|
import { GoogleGenAI } from '@google/genai';
|
|
12
13
|
|
|
14
|
+
const GOOGLE_SUPPORTED_IMAGE_MIME_TYPES = [
|
|
15
|
+
'image/png',
|
|
16
|
+
'image/jpeg',
|
|
17
|
+
'image/webp',
|
|
18
|
+
'image/heic',
|
|
19
|
+
'image/heif',
|
|
20
|
+
];
|
|
21
|
+
const GOOGLE_SUPPORTED_DOCUMENT_MIME_TYPES = [
|
|
22
|
+
'application/pdf',
|
|
23
|
+
'text/plain',
|
|
24
|
+
'text/csv',
|
|
25
|
+
'text/html',
|
|
26
|
+
'text/markdown',
|
|
27
|
+
'text/xml',
|
|
28
|
+
'text/rtf',
|
|
29
|
+
'application/json',
|
|
30
|
+
];
|
|
13
31
|
let GoogleChatAdapter = class GoogleChatAdapter {
|
|
14
32
|
ai;
|
|
15
33
|
logger = new Logger('wabot:google-chat-adapter-v2');
|
|
@@ -46,10 +64,39 @@ let GoogleChatAdapter = class GoogleChatAdapter {
|
|
|
46
64
|
return contents;
|
|
47
65
|
}
|
|
48
66
|
mapHumanMessage(item) {
|
|
49
|
-
if (
|
|
67
|
+
if (isChatMessageEmpty(item)) {
|
|
50
68
|
throw new Error('User message content is empty');
|
|
51
69
|
}
|
|
52
|
-
|
|
70
|
+
const parts = [];
|
|
71
|
+
parts.push({
|
|
72
|
+
text: extractChatMessageText(item, {
|
|
73
|
+
supportedImageMimeTypes: GOOGLE_SUPPORTED_IMAGE_MIME_TYPES,
|
|
74
|
+
supportedDocumentMimeTypes: GOOGLE_SUPPORTED_DOCUMENT_MIME_TYPES,
|
|
75
|
+
}),
|
|
76
|
+
});
|
|
77
|
+
if (item.images) {
|
|
78
|
+
for (const image of item.images) {
|
|
79
|
+
if (!GOOGLE_SUPPORTED_IMAGE_MIME_TYPES.includes(image.mimeType))
|
|
80
|
+
continue;
|
|
81
|
+
parts.push(this.toGoogleFilePart(image));
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
if (item.documents) {
|
|
85
|
+
for (const doc of item.documents) {
|
|
86
|
+
if (!GOOGLE_SUPPORTED_DOCUMENT_MIME_TYPES.includes(doc.mimeType))
|
|
87
|
+
continue;
|
|
88
|
+
parts.push(this.toGoogleFilePart(doc));
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
return { role: 'user', parts };
|
|
92
|
+
}
|
|
93
|
+
toGoogleFilePart(file) {
|
|
94
|
+
if (file.publicUrl) {
|
|
95
|
+
return { fileData: { fileUri: file.publicUrl, mimeType: file.mimeType } };
|
|
96
|
+
}
|
|
97
|
+
return {
|
|
98
|
+
inlineData: { data: stripDataUrlPrefix(file.base64Url), mimeType: file.mimeType },
|
|
99
|
+
};
|
|
53
100
|
}
|
|
54
101
|
mapBotMessage(item) {
|
|
55
102
|
if (!item.text) {
|
|
@@ -144,5 +191,9 @@ GoogleChatAdapter = __decorate([
|
|
|
144
191
|
singleton(),
|
|
145
192
|
__metadata("design:paramtypes", [Env])
|
|
146
193
|
], GoogleChatAdapter);
|
|
194
|
+
function stripDataUrlPrefix(dataUrl) {
|
|
195
|
+
const commaIndex = dataUrl.indexOf(',');
|
|
196
|
+
return commaIndex >= 0 && dataUrl.startsWith('data:') ? dataUrl.slice(commaIndex + 1) : dataUrl;
|
|
197
|
+
}
|
|
147
198
|
|
|
148
199
|
export { GoogleChatAdapter };
|
|
@@ -5,9 +5,17 @@ import 'uuid';
|
|
|
5
5
|
import '../../../feature/chat-bot/metadata/ChatBotMetadataStore.js';
|
|
6
6
|
import '../../../core/error/setupErrorHandlers.js';
|
|
7
7
|
import { extractChatMessageText } from '../../../feature/chat-bot/extractChatMessageText.js';
|
|
8
|
+
import { isChatMessageEmpty } from '../../../feature/chat-bot/isChatMessageEmpty.js';
|
|
8
9
|
import { Logger } from '../../../core/logger/Logger.js';
|
|
9
10
|
import { OpenAI } from 'openai';
|
|
10
11
|
|
|
12
|
+
const OPENAI_SUPPORTED_IMAGE_MIME_TYPES = [
|
|
13
|
+
'image/png',
|
|
14
|
+
'image/jpeg',
|
|
15
|
+
'image/webp',
|
|
16
|
+
'image/gif',
|
|
17
|
+
];
|
|
18
|
+
const OPENAI_SUPPORTED_DOCUMENT_MIME_TYPES = ['application/pdf'];
|
|
11
19
|
let OpenaiChatAdapter = class OpenaiChatAdapter {
|
|
12
20
|
openai = new OpenAI();
|
|
13
21
|
logger = new Logger('wabot:openai-chat-adapter');
|
|
@@ -41,11 +49,21 @@ let OpenaiChatAdapter = class OpenaiChatAdapter {
|
|
|
41
49
|
return openIaInput;
|
|
42
50
|
}
|
|
43
51
|
mapConectionMessage(item) {
|
|
52
|
+
if (isChatMessageEmpty(item)) {
|
|
53
|
+
throw new Error('User message content is empty');
|
|
54
|
+
}
|
|
44
55
|
const content = [];
|
|
45
|
-
|
|
46
|
-
|
|
56
|
+
content.push({
|
|
57
|
+
type: 'input_text',
|
|
58
|
+
text: extractChatMessageText(item, {
|
|
59
|
+
supportedImageMimeTypes: OPENAI_SUPPORTED_IMAGE_MIME_TYPES,
|
|
60
|
+
supportedDocumentMimeTypes: OPENAI_SUPPORTED_DOCUMENT_MIME_TYPES,
|
|
61
|
+
}),
|
|
62
|
+
});
|
|
47
63
|
if (item.images) {
|
|
48
64
|
for (const image of item.images) {
|
|
65
|
+
if (!OPENAI_SUPPORTED_IMAGE_MIME_TYPES.includes(image.mimeType))
|
|
66
|
+
continue;
|
|
49
67
|
content.push({
|
|
50
68
|
type: 'input_image',
|
|
51
69
|
image_url: image.publicUrl ?? image.base64Url,
|
|
@@ -53,8 +71,21 @@ let OpenaiChatAdapter = class OpenaiChatAdapter {
|
|
|
53
71
|
});
|
|
54
72
|
}
|
|
55
73
|
}
|
|
56
|
-
if (
|
|
57
|
-
|
|
74
|
+
if (item.documents) {
|
|
75
|
+
for (const doc of item.documents) {
|
|
76
|
+
if (!OPENAI_SUPPORTED_DOCUMENT_MIME_TYPES.includes(doc.mimeType))
|
|
77
|
+
continue;
|
|
78
|
+
if (doc.publicUrl) {
|
|
79
|
+
content.push({ type: 'input_file', file_url: doc.publicUrl });
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
content.push({
|
|
83
|
+
type: 'input_file',
|
|
84
|
+
file_data: doc.base64Url,
|
|
85
|
+
filename: doc.name ?? `${doc.id}.pdf`,
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
}
|
|
58
89
|
}
|
|
59
90
|
return { role: 'user', content };
|
|
60
91
|
}
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
import { __decorate, __metadata } from 'tslib';
|
|
2
|
+
import { Env } from '../../../core/env/Env.js';
|
|
3
|
+
import { singleton } from '../../../core/injection/index.js';
|
|
4
|
+
import { Logger } from '../../../core/logger/Logger.js';
|
|
5
|
+
import '../../../feature/chat-bot/ChatBot.js';
|
|
6
|
+
import 'uuid';
|
|
7
|
+
import '../../../feature/chat-bot/metadata/ChatBotMetadataStore.js';
|
|
8
|
+
import '../../../core/error/setupErrorHandlers.js';
|
|
9
|
+
import { extractChatMessageText } from '../../../feature/chat-bot/extractChatMessageText.js';
|
|
10
|
+
import { isChatMessageEmpty } from '../../../feature/chat-bot/isChatMessageEmpty.js';
|
|
11
|
+
import { OpenRouter } from '@openrouter/sdk';
|
|
12
|
+
|
|
13
|
+
const OPENROUTER_SUPPORTED_IMAGE_MIME_TYPES = [
|
|
14
|
+
'image/png',
|
|
15
|
+
'image/jpeg',
|
|
16
|
+
'image/webp',
|
|
17
|
+
'image/gif',
|
|
18
|
+
];
|
|
19
|
+
const OPENROUTER_SUPPORTED_DOCUMENT_MIME_TYPES = ['application/pdf'];
|
|
20
|
+
let OpenRouterChatAdapter = class OpenRouterChatAdapter {
|
|
21
|
+
env;
|
|
22
|
+
openRouter;
|
|
23
|
+
logger = new Logger('wabot:openrouter-chat-adapter');
|
|
24
|
+
constructor(env) {
|
|
25
|
+
this.env = env;
|
|
26
|
+
const apiKey = this.env.requireString('OPENROUTER_API_KEY');
|
|
27
|
+
this.openRouter = new OpenRouter({ apiKey });
|
|
28
|
+
}
|
|
29
|
+
async nextItems(req) {
|
|
30
|
+
const messages = [];
|
|
31
|
+
messages.push({ role: 'system', content: req.systemPrompt });
|
|
32
|
+
messages.push(...this.mapChatItems(req.prevItems));
|
|
33
|
+
const tools = req.tools.map((x) => this.mapTool(x));
|
|
34
|
+
this.logger.debug(`Call OpenRouter with model: ${req.model}, messages: ${messages.length}, tools: ${tools.length}`);
|
|
35
|
+
const response = await this.openRouter.chat.send({
|
|
36
|
+
chatRequest: {
|
|
37
|
+
model: req.model,
|
|
38
|
+
messages,
|
|
39
|
+
tools: tools.length > 0 ? tools : undefined,
|
|
40
|
+
},
|
|
41
|
+
});
|
|
42
|
+
return this.mapResponse(response);
|
|
43
|
+
}
|
|
44
|
+
mapChatItems(chatItems) {
|
|
45
|
+
const messages = [];
|
|
46
|
+
for (const chatItem of chatItems) {
|
|
47
|
+
switch (chatItem.type) {
|
|
48
|
+
case 'humanMessage':
|
|
49
|
+
messages.push(this.mapHumanMessage(chatItem.humanMessage));
|
|
50
|
+
break;
|
|
51
|
+
case 'botMessage':
|
|
52
|
+
messages.push(this.mapBotMessage(chatItem.botMessage));
|
|
53
|
+
break;
|
|
54
|
+
case 'functionCall':
|
|
55
|
+
messages.push(...this.mapFunctionCall(chatItem.functionCall));
|
|
56
|
+
break;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return messages;
|
|
60
|
+
}
|
|
61
|
+
mapHumanMessage(item) {
|
|
62
|
+
if (isChatMessageEmpty(item)) {
|
|
63
|
+
throw new Error('User message content is empty');
|
|
64
|
+
}
|
|
65
|
+
const contentParts = [];
|
|
66
|
+
contentParts.push(extractChatMessageText(item, {
|
|
67
|
+
supportedImageMimeTypes: OPENROUTER_SUPPORTED_IMAGE_MIME_TYPES,
|
|
68
|
+
supportedDocumentMimeTypes: OPENROUTER_SUPPORTED_DOCUMENT_MIME_TYPES,
|
|
69
|
+
}));
|
|
70
|
+
if (item.images) {
|
|
71
|
+
for (const image of item.images) {
|
|
72
|
+
if (!OPENROUTER_SUPPORTED_IMAGE_MIME_TYPES.includes(image.mimeType))
|
|
73
|
+
continue;
|
|
74
|
+
const imageUrl = image.publicUrl ?? image.base64Url;
|
|
75
|
+
if (imageUrl)
|
|
76
|
+
contentParts.push(imageUrl);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
if (item.documents) {
|
|
80
|
+
for (const doc of item.documents) {
|
|
81
|
+
if (!OPENROUTER_SUPPORTED_DOCUMENT_MIME_TYPES.includes(doc.mimeType))
|
|
82
|
+
continue;
|
|
83
|
+
const docUrl = doc.publicUrl ?? doc.base64Url;
|
|
84
|
+
if (docUrl)
|
|
85
|
+
contentParts.push(docUrl);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
return { role: 'user', content: contentParts.join('\n') };
|
|
89
|
+
}
|
|
90
|
+
mapBotMessage(item) {
|
|
91
|
+
if (!item.text) {
|
|
92
|
+
throw new Error('Assistant message content is empty');
|
|
93
|
+
}
|
|
94
|
+
return { role: 'assistant', content: item.text };
|
|
95
|
+
}
|
|
96
|
+
mapFunctionCall(item) {
|
|
97
|
+
return [
|
|
98
|
+
{
|
|
99
|
+
role: 'assistant',
|
|
100
|
+
toolCalls: [
|
|
101
|
+
{
|
|
102
|
+
id: item.id,
|
|
103
|
+
type: 'function',
|
|
104
|
+
function: {
|
|
105
|
+
name: item.name,
|
|
106
|
+
arguments: item.arguments || '{}',
|
|
107
|
+
},
|
|
108
|
+
},
|
|
109
|
+
],
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
role: 'tool',
|
|
113
|
+
toolCallId: item.id,
|
|
114
|
+
content: item.result ?? 'No result',
|
|
115
|
+
},
|
|
116
|
+
];
|
|
117
|
+
}
|
|
118
|
+
mapTool(tool) {
|
|
119
|
+
return {
|
|
120
|
+
type: 'function',
|
|
121
|
+
function: {
|
|
122
|
+
name: tool.name,
|
|
123
|
+
description: tool.description,
|
|
124
|
+
parameters: {
|
|
125
|
+
type: 'object',
|
|
126
|
+
properties: tool.parameters.reduce((prev, param) => ({
|
|
127
|
+
...prev,
|
|
128
|
+
[param.name]: { type: param.type, description: param.description },
|
|
129
|
+
}), {}),
|
|
130
|
+
required: tool.parameters.map((param) => param.name),
|
|
131
|
+
additionalProperties: false,
|
|
132
|
+
},
|
|
133
|
+
strict: true,
|
|
134
|
+
},
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
mapResponse(response) {
|
|
138
|
+
const { toolCalls: responseToolCalls, content: responseText } = response.choices?.[0]?.message ?? {};
|
|
139
|
+
const nextItems = [];
|
|
140
|
+
if (responseText) {
|
|
141
|
+
nextItems.push({ type: 'botMessage', botMessage: { text: responseText } });
|
|
142
|
+
}
|
|
143
|
+
if (responseToolCalls && responseToolCalls.length > 0) {
|
|
144
|
+
for (const toolCall of responseToolCalls) {
|
|
145
|
+
if (toolCall.type === 'function') {
|
|
146
|
+
nextItems.push({
|
|
147
|
+
type: 'functionCall',
|
|
148
|
+
functionCall: {
|
|
149
|
+
id: toolCall.id,
|
|
150
|
+
name: toolCall.function.name,
|
|
151
|
+
arguments: toolCall.function.arguments,
|
|
152
|
+
},
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
if (nextItems.length === 0) {
|
|
158
|
+
throw new Error('Not supported OpenRouter Response');
|
|
159
|
+
}
|
|
160
|
+
let usage;
|
|
161
|
+
if (response.usage) {
|
|
162
|
+
usage = {
|
|
163
|
+
inputTokens: response.usage.promptTokens,
|
|
164
|
+
outputTokens: response.usage.completionTokens,
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
else {
|
|
168
|
+
throw new Error('Unable to found usage info');
|
|
169
|
+
}
|
|
170
|
+
return { nextItems, usage };
|
|
171
|
+
}
|
|
172
|
+
};
|
|
173
|
+
OpenRouterChatAdapter = __decorate([
|
|
174
|
+
singleton(),
|
|
175
|
+
__metadata("design:paramtypes", [Env])
|
|
176
|
+
], OpenRouterChatAdapter);
|
|
177
|
+
|
|
178
|
+
export { OpenRouterChatAdapter };
|
|
@@ -1,13 +1,29 @@
|
|
|
1
|
-
function extractChatMessageText(message) {
|
|
1
|
+
function extractChatMessageText(message, options = {}) {
|
|
2
2
|
const messageData = {
|
|
3
3
|
senderId: message.senderId,
|
|
4
4
|
senderName: message.senderName,
|
|
5
5
|
text: message.text,
|
|
6
6
|
object: message.object,
|
|
7
7
|
metadata: message.metadata,
|
|
8
|
-
images: message.images?.map((x) => ({
|
|
8
|
+
images: message.images?.map((x) => ({
|
|
9
|
+
id: x.id,
|
|
10
|
+
name: x.name,
|
|
11
|
+
mimeType: x.mimeType,
|
|
12
|
+
notAnalyzed: isAnalyzed(x.mimeType, options.supportedImageMimeTypes) ? undefined : true,
|
|
13
|
+
})),
|
|
14
|
+
documents: message.documents?.map((x) => ({
|
|
15
|
+
id: x.id,
|
|
16
|
+
name: x.name,
|
|
17
|
+
mimeType: x.mimeType,
|
|
18
|
+
notAnalyzed: isAnalyzed(x.mimeType, options.supportedDocumentMimeTypes) ? undefined : true,
|
|
19
|
+
})),
|
|
9
20
|
};
|
|
10
21
|
return JSON.stringify(messageData);
|
|
11
22
|
}
|
|
23
|
+
function isAnalyzed(mimeType, supported) {
|
|
24
|
+
if (supported === undefined)
|
|
25
|
+
return true;
|
|
26
|
+
return supported.includes(mimeType);
|
|
27
|
+
}
|
|
12
28
|
|
|
13
29
|
export { extractChatMessageText };
|
|
@@ -4,13 +4,15 @@ import { Mindset } from './IMindset.js';
|
|
|
4
4
|
import { MindsetMetadataStore } from './metadata/MindsetMetadataStore.js';
|
|
5
5
|
import { validateModel } from '../../core/validation/core/validateModel.js';
|
|
6
6
|
import '../../core/validation/metadata/ValidationMetadataStore.js';
|
|
7
|
-
import { CustomError } from '../../core/error/CustomError.js';
|
|
7
|
+
import { CustomError, errorToPlainObject } from '../../core/error/CustomError.js';
|
|
8
8
|
import '../../core/error/setupErrorHandlers.js';
|
|
9
|
+
import { Logger } from '../../core/logger/Logger.js';
|
|
9
10
|
import { Container } from '../../core/injection/Container.js';
|
|
10
11
|
|
|
11
12
|
let MindsetOperator = class MindsetOperator {
|
|
12
13
|
mindset;
|
|
13
14
|
container;
|
|
15
|
+
logger = new Logger('wabot:mindset-operator');
|
|
14
16
|
metadata;
|
|
15
17
|
constructor(mindset, container, metadataStore) {
|
|
16
18
|
this.mindset = mindset;
|
|
@@ -139,7 +141,14 @@ let MindsetOperator = class MindsetOperator {
|
|
|
139
141
|
return await this.functionResponseToString(response);
|
|
140
142
|
}
|
|
141
143
|
catch (error) {
|
|
142
|
-
|
|
144
|
+
const aiResponse = await this.functionErrorToString(error);
|
|
145
|
+
if (error instanceof Error) {
|
|
146
|
+
this.logger.error(`Function '${name}' threw an exception`, error, { aiResponse });
|
|
147
|
+
}
|
|
148
|
+
else {
|
|
149
|
+
this.logger.error(`Function '${name}' threw a non-Error value`, { error, aiResponse });
|
|
150
|
+
}
|
|
151
|
+
return aiResponse;
|
|
143
152
|
}
|
|
144
153
|
}
|
|
145
154
|
async functionResponseToString(response) {
|
|
@@ -181,6 +190,10 @@ let MindsetOperator = class MindsetOperator {
|
|
|
181
190
|
body: typeof data === 'object' ? data : { message: data?.toString?.() || 'Unknown error' },
|
|
182
191
|
});
|
|
183
192
|
}
|
|
193
|
+
if (error instanceof Error) {
|
|
194
|
+
const { stack: _stack, ...plain } = errorToPlainObject(error);
|
|
195
|
+
return JSON.stringify(plain);
|
|
196
|
+
}
|
|
184
197
|
if (error?.message) {
|
|
185
198
|
return error.message;
|
|
186
199
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { generate } from 'short-uuid';
|
|
2
2
|
import { PgRepositoryBase } from './PgRepositoryBase.js';
|
|
3
3
|
import { CustomError } from '../../core/error/CustomError.js';
|
|
4
4
|
import '../../core/error/setupErrorHandlers.js';
|
|
@@ -54,7 +54,7 @@ class PgCrudRepository extends PgRepositoryBase {
|
|
|
54
54
|
if (item.wasCreated()) {
|
|
55
55
|
throw new Error('Item already created');
|
|
56
56
|
}
|
|
57
|
-
item['data'].id =
|
|
57
|
+
item['data'].id = generate();
|
|
58
58
|
item['data'].createdAt = new Date().getTime();
|
|
59
59
|
item.validate();
|
|
60
60
|
const sql = `
|
package/dist/src/index.d.ts
CHANGED
|
@@ -805,6 +805,7 @@ interface IMindsetTool {
|
|
|
805
805
|
declare class MindsetOperator implements IMindset {
|
|
806
806
|
private mindset;
|
|
807
807
|
private container;
|
|
808
|
+
private logger;
|
|
808
809
|
private metadata;
|
|
809
810
|
constructor(mindset: Mindset, container: Container, metadataStore: MindsetMetadataStore);
|
|
810
811
|
context(): Promise<string>;
|
|
@@ -822,27 +823,32 @@ declare class MindsetOperator implements IMindset {
|
|
|
822
823
|
functionErrorToString(error: any): Promise<string>;
|
|
823
824
|
}
|
|
824
825
|
|
|
825
|
-
interface
|
|
826
|
+
interface IChatMessagesPublicFile {
|
|
826
827
|
name?: string;
|
|
827
828
|
publicUrl: string;
|
|
828
829
|
base64Url?: undefined;
|
|
829
830
|
mimeType: string;
|
|
830
831
|
id: string;
|
|
831
832
|
}
|
|
832
|
-
interface
|
|
833
|
+
interface IChatMessagesPrivateFile {
|
|
833
834
|
name?: string;
|
|
834
835
|
publicUrl?: undefined;
|
|
835
836
|
base64Url: string;
|
|
836
837
|
mimeType: string;
|
|
837
838
|
id: string;
|
|
838
839
|
}
|
|
839
|
-
type
|
|
840
|
+
type IChatMessageFile = IChatMessagesPrivateFile | IChatMessagesPublicFile;
|
|
841
|
+
|
|
842
|
+
type IChatMessageDocument = IChatMessageFile;
|
|
843
|
+
|
|
844
|
+
type IChatMessageImage = IChatMessageFile;
|
|
840
845
|
|
|
841
846
|
interface IChatMessage {
|
|
842
847
|
senderId?: string;
|
|
843
848
|
senderName?: string;
|
|
844
849
|
text?: string;
|
|
845
850
|
images?: IChatMessageImage[];
|
|
851
|
+
documents?: IChatMessageDocument[];
|
|
846
852
|
object?: object;
|
|
847
853
|
metadata?: Record<string, string>;
|
|
848
854
|
}
|
|
@@ -963,7 +969,13 @@ declare class ChatBotMetadataStore {
|
|
|
963
969
|
|
|
964
970
|
declare function safeJsonParse<T = unknown>(json: string | undefined | null, context?: string): T;
|
|
965
971
|
|
|
966
|
-
|
|
972
|
+
interface IExtractChatMessageTextOptions {
|
|
973
|
+
supportedImageMimeTypes?: readonly string[];
|
|
974
|
+
supportedDocumentMimeTypes?: readonly string[];
|
|
975
|
+
}
|
|
976
|
+
declare function extractChatMessageText(message: IChatMessage, options?: IExtractChatMessageTextOptions): string;
|
|
977
|
+
|
|
978
|
+
declare function isChatMessageEmpty(message: IChatMessage): boolean;
|
|
967
979
|
|
|
968
980
|
interface IchatControllerConfig {
|
|
969
981
|
}
|
|
@@ -1513,6 +1525,8 @@ declare class AnthropicChatAdapter implements IChatAdapter {
|
|
|
1513
1525
|
nextItems(req: IChatAdapterNextItemsReq): Promise<IChatAdapterNextItemsRes>;
|
|
1514
1526
|
private mapChatItems;
|
|
1515
1527
|
private mapHumanMessage;
|
|
1528
|
+
private toAnthropicImageSource;
|
|
1529
|
+
private toAnthropicDocumentSource;
|
|
1516
1530
|
private mapBotMessage;
|
|
1517
1531
|
private mapFunctionCall;
|
|
1518
1532
|
private mapTool;
|
|
@@ -1542,6 +1556,7 @@ declare class GoogleChatAdapter implements IChatAdapter {
|
|
|
1542
1556
|
nextItems(req: IChatAdapterNextItemsReq): Promise<IChatAdapterNextItemsRes>;
|
|
1543
1557
|
private mapChatItems;
|
|
1544
1558
|
private mapHumanMessage;
|
|
1559
|
+
private toGoogleFilePart;
|
|
1545
1560
|
private mapBotMessage;
|
|
1546
1561
|
private mapFunctionCall;
|
|
1547
1562
|
private mapTool;
|
|
@@ -1560,6 +1575,20 @@ declare class OpenaiChatAdapter implements IChatAdapter {
|
|
|
1560
1575
|
private mapResponse;
|
|
1561
1576
|
}
|
|
1562
1577
|
|
|
1578
|
+
declare class OpenRouterChatAdapter implements IChatAdapter {
|
|
1579
|
+
private env;
|
|
1580
|
+
private openRouter;
|
|
1581
|
+
private logger;
|
|
1582
|
+
constructor(env: Env);
|
|
1583
|
+
nextItems(req: IChatAdapterNextItemsReq): Promise<IChatAdapterNextItemsRes>;
|
|
1584
|
+
private mapChatItems;
|
|
1585
|
+
private mapHumanMessage;
|
|
1586
|
+
private mapBotMessage;
|
|
1587
|
+
private mapFunctionCall;
|
|
1588
|
+
private mapTool;
|
|
1589
|
+
private mapResponse;
|
|
1590
|
+
}
|
|
1591
|
+
|
|
1563
1592
|
declare class PgChatRepository extends PgCrudRepository<Chat> implements IChatRepository {
|
|
1564
1593
|
constructor(pool: Pool);
|
|
1565
1594
|
findByConnection(query: IChatConnection): Promise<Chat | null>;
|
|
@@ -2164,4 +2193,4 @@ declare function HtmlModule(options: IHtmlModuleOptions): {
|
|
|
2164
2193
|
new (): {};
|
|
2165
2194
|
};
|
|
2166
2195
|
|
|
2167
|
-
export { AnthropicChatAdapter, ApiKey, ApiKeyGuardMiddleware, ApiKeyHandshakeGuardMiddleware, ApiKeyRepository, Async, AsyncMetadataStore, Auth, Chat, ChatAdapter, ChatBot, ChatBotMetadataStore, ChatItem, ChatMemory, ChatRepository, ChatResolver, type ClientMap, CmdChannel, Container, ControllerMetadataStore, CronJob, CronJobRepository, CustomError, DeepSeekChatAdapter, DescriptionMetadataStore, EXPRESS_REQ, EXPRESS_RES, Entity, Env, EnvWhatsAppRepository, type ErrorSeverity, ExpressProvider, GoogleChatAdapter, type GoogleChatAdapterV2Options, HtmlModule, HttpServerProvider, type IApiKeyData, type IApiKeyRepository, type IArrayValidationError, type IArrayValidationResult, type IBotMessageItem, type IChannelMessage, type IChannelMetadata, type IChatAdapter, type IChatAdapterNextItemsReq, type IChatAdapterNextItemsRes, type IChatAssociation, type IChatBot, type IChatBotMetadata, type IChatChannel, type IChatConnection, type IChatControllerMetadata, type IChatData, type IChatItem, type IChatItemData, type IChatItemType, type IChatMemory, type IChatMessage, type IChatRepository, type IChatType, type ICmdChannelMessage, type ICmdReceivedMessage, type ICommandConfig, type ICommandHandler, type ICommandHandlerConfig, type IConstructor, type ICronConfig, type ICronJobData, type ICrudRepository, type ICustomErrorData, type IDescriptionMetadata, type IEndPointConfig, type IEndPointMetadata, type IEntityData, type IEnvType, type IErrorHandlersConfig, type IErrorMonitor, type IErrorMonitorContext, type IFunctionCall, type IFunctionCallItem, type IGenerateApiKeyReq, type IGenerateApiKeyRes, type IGetWhatsAppTemplateRequest, type IHandshakeMiddleware, type IHandshakeMiddlewareMetadata, type IHtmlModuleOptions, type IHumanMessageItem, type IJobData, type IJobRepository, type IJwtRefreshTokenData, type IJwtRefreshTokenRepository, type ILanguageModelUsage, type IListenWhatsAppMessageRequest, type ILockKey, type ILocker, type ILockerKey, type IMessageContext, type IMiddleware, type IMiddlewareMetadata, type IMindset, type IMindsetConfig, type IMindsetIdentity, type IMindsetLlm, type IMindsetMetadata, type IMindsetModuleConfig, type IMindsetModuleMetadata, type IMindsetTool, type IMindsetToolParameter, type IModelValidationError, type IModelValidationResult, type IModelValidatorsInfo, type IMoneyData, type IPersistentData, type IPgRepositoryConfig, type IPropertyValidatorInfo, type IReceivedMessage, type IRemoteApiKeyFetcher, type IRestControllerConfig, type IRestControllerMetadata, type IScheduleAt, type IScheduleDelay, type ISendByWasenderRequest, type ISendWhatsAppRequest, type ISendWhatsAppTemplateRequest, type ISocketChannelConfig, type ISocketChannelMessage, type ISocketChannelReceivedMessage, type ISocketControllerConfig, type ISocketControllerMetadata, type ISocketEventConfig, type ISocketEventMetadata, type ISocketReceivedMessage, type IStorableData, type ITelegramChannelConfig, type ITelegramChannelMessage, type ITelegramReceivedMessage, type IValidateArrayOptions, type IValidateArrayOptionsWithItemsValidators, type IValidateInputShape, type IValidateIsInOptions, type IValidateIsRecordOptions, type IValidateMaxOptions, type IValidateMinOptions, type IValidationError, type IValidationResult, type IValidator, type IValidatorMetadata, type IWasenderChannelMessageListener, type IWasenderDeviceListMetadata, type IWasenderEvent, type IWasenderMessageContent, type IWasenderMessageContextInfo, type IWasenderMessageKey, type IWasenderMessageReceivedData, type IWasenderMessageReceivedEvent, type IWasenderQrUpdatedEvent, type IWhatsAppBusinessAccount, type IWhatsAppBusinessNumber, type IWhatsAppByWasenderChannelConfig, type IWhatsAppByWasenderReceivedMessage, type IWhatsAppChannelMessage, type IWhatsAppCloudContact, type IWhatsAppCloudMessage, type IWhatsAppCloudMessageMetadata, type IWhatsAppCloudTemplate, type IWhatsAppCloudTemplateComponent, type IWhatsAppCloudTemplateMessage, type IWhatsAppCloudTemplateParameter, type IWhatsAppCloudTemplateResponse, type IWhatsAppCloudWebhookPayload, type IWhatsAppData, type IWhatsAppMessageListener, type IWhatsAppProxyListenMessageEventData, type IWhatsAppProxyListenMessageEventReq, type IWhatsAppProxyMessage, type IWhatsAppProxyMessageContent, type IWhatsAppProxyMessageEventReq, type IWhatsAppProxySendMessageEventReq, type IWhatsAppReceivedMessage, type IWhatsAppRepository, type IWhatsAppSenderOptions, type IWhatsappChannelConfig, type IchatControllerConfig, Job, JobRepository, JobRunner, Jwt, JwtAccessAndRefreshTokenDto, JwtConfig, JwtGuardMiddleware, JwtHandshakeGuardMiddleware, JwtRefreshToken, JwtRefreshTokenRepository, JwtSigner, JwtTokenDto, Lifecycle, Locker, Logger, Mapper, Mindset, MindsetMetadataStore, MindsetOperator, Money, MoneyDto, OpenaiChatAdapter, Password, type PasswordHashOptions, Persistent, PgApiKeyRepository, PgChatMemory, PgChatRepository, PgCronJobRepository, PgCrudRepository, PgJobRepository, PgJwtRefreshTokenRepository, PgLockKey, PgLocker, PgRepositoryBase, PgWhatsAppRepository, RamChatMemory, RamChatRepository, Random, RemoteApiKeyRepository, RestControllerMetadataStore, RestRequest, SocketChannel, SocketChannelConfig, SocketChannelReceivedMessage, SocketControllerMetadataStore, SocketServerConfig, SocketServerProvider, Storable, TelegramChannel, TelegramChannelConfig, ValidationMetadataStore, WHATSAPP_MESSAGE_EVENT, WHATSAPP_PROXY_LISTEN_MESSAGE_EVENT, WHATSAPP_PROXY_SEND_MESSAGE_EVENT, WabotChatAdapter, WasenderWebhookController, WhatsApp, WhatsAppByWasenderChannel, WhatsAppByWasenderChannelConfig, WhatsAppChannel, WhatsAppReceiver, WhatsAppReceiverByCloudApi, WhatsAppReceiverByWabotProxy, WhatsAppReceiverByWasender, WhatsAppRepository, WhatsAppSender, WhatsAppSenderByCloudApi, WhatsAppSenderByWabotProxy, WhatsAppSenderByWasender, WhatsAppWabotProxyConnection, WhatsappChannelConfig, apiKeyGuard, apiKeyHandshakeGuard, chatBot, chatController, chatItemTypeOptions, cmd, cmdChannelName, command, commandHandler, container, cron, description, errorToPlainObject, extractChatMessageText, extractNumberFromWasenderMessageKey, getClientMap, getPgClient, handshakeMiddlewares, inject, injectable, isArray, isBoolean, isDate, isIn, isModel, isNotEmpty, isNumber, isOptional, isPresent, isRecord, isString, jwtGuard, jwtHandshakeGuard, max, middleware, min, mindset, mindsetModule, modelInfo, onDelete, onGet, onPost, onPut, onSocketEvent, pgStorage, readJsonFromFile, restController, runChatControllers, runCommandHandlers, runCronHandlers, runRestControllers, runSocketControllers, safeJsonParse, scoped, setupErrorHandlers, singleton, socket, socketChannelName, socketController, stopCommandHandlers, stopCronHandlers, telegram, telegramChannelName, validateAndTransform, validateArray, validateIsBoolean, validateIsDate, validateIsIn, validateIsNotEmpty, validateIsNumber, validateIsPresent, validateIsRecord, validateIsString, validateMax, validateMin, validateModel, whatsApp, whatsAppByWasender, whatsAppByWasenderChannelName, whatsAppChannelName, withPgClient, withPgTransaction, writeJsonToFile };
|
|
2196
|
+
export { AnthropicChatAdapter, ApiKey, ApiKeyGuardMiddleware, ApiKeyHandshakeGuardMiddleware, ApiKeyRepository, Async, AsyncMetadataStore, Auth, Chat, ChatAdapter, ChatBot, ChatBotMetadataStore, ChatItem, ChatMemory, ChatRepository, ChatResolver, type ClientMap, CmdChannel, Container, ControllerMetadataStore, CronJob, CronJobRepository, CustomError, DeepSeekChatAdapter, DescriptionMetadataStore, EXPRESS_REQ, EXPRESS_RES, Entity, Env, EnvWhatsAppRepository, type ErrorSeverity, ExpressProvider, GoogleChatAdapter, type GoogleChatAdapterV2Options, HtmlModule, HttpServerProvider, type IApiKeyData, type IApiKeyRepository, type IArrayValidationError, type IArrayValidationResult, type IBotMessageItem, type IChannelMessage, type IChannelMetadata, type IChatAdapter, type IChatAdapterNextItemsReq, type IChatAdapterNextItemsRes, type IChatAssociation, type IChatBot, type IChatBotMetadata, type IChatChannel, type IChatConnection, type IChatControllerMetadata, type IChatData, type IChatItem, type IChatItemData, type IChatItemType, type IChatMemory, type IChatMessage, type IChatMessageDocument, type IChatMessageFile, type IChatMessageImage, type IChatMessagesPrivateFile, type IChatMessagesPublicFile, type IChatRepository, type IChatType, type ICmdChannelMessage, type ICmdReceivedMessage, type ICommandConfig, type ICommandHandler, type ICommandHandlerConfig, type IConstructor, type ICronConfig, type ICronJobData, type ICrudRepository, type ICustomErrorData, type IDescriptionMetadata, type IEndPointConfig, type IEndPointMetadata, type IEntityData, type IEnvType, type IErrorHandlersConfig, type IErrorMonitor, type IErrorMonitorContext, type IExtractChatMessageTextOptions, type IFunctionCall, type IFunctionCallItem, type IGenerateApiKeyReq, type IGenerateApiKeyRes, type IGetWhatsAppTemplateRequest, type IHandshakeMiddleware, type IHandshakeMiddlewareMetadata, type IHtmlModuleOptions, type IHumanMessageItem, type IJobData, type IJobRepository, type IJwtRefreshTokenData, type IJwtRefreshTokenRepository, type ILanguageModelUsage, type IListenWhatsAppMessageRequest, type ILockKey, type ILocker, type ILockerKey, type IMessageContext, type IMiddleware, type IMiddlewareMetadata, type IMindset, type IMindsetConfig, type IMindsetIdentity, type IMindsetLlm, type IMindsetMetadata, type IMindsetModuleConfig, type IMindsetModuleMetadata, type IMindsetTool, type IMindsetToolParameter, type IModelValidationError, type IModelValidationResult, type IModelValidatorsInfo, type IMoneyData, type IPersistentData, type IPgRepositoryConfig, type IPropertyValidatorInfo, type IReceivedMessage, type IRemoteApiKeyFetcher, type IRestControllerConfig, type IRestControllerMetadata, type IScheduleAt, type IScheduleDelay, type ISendByWasenderRequest, type ISendWhatsAppRequest, type ISendWhatsAppTemplateRequest, type ISocketChannelConfig, type ISocketChannelMessage, type ISocketChannelReceivedMessage, type ISocketControllerConfig, type ISocketControllerMetadata, type ISocketEventConfig, type ISocketEventMetadata, type ISocketReceivedMessage, type IStorableData, type ITelegramChannelConfig, type ITelegramChannelMessage, type ITelegramReceivedMessage, type IValidateArrayOptions, type IValidateArrayOptionsWithItemsValidators, type IValidateInputShape, type IValidateIsInOptions, type IValidateIsRecordOptions, type IValidateMaxOptions, type IValidateMinOptions, type IValidationError, type IValidationResult, type IValidator, type IValidatorMetadata, type IWasenderChannelMessageListener, type IWasenderDeviceListMetadata, type IWasenderEvent, type IWasenderMessageContent, type IWasenderMessageContextInfo, type IWasenderMessageKey, type IWasenderMessageReceivedData, type IWasenderMessageReceivedEvent, type IWasenderQrUpdatedEvent, type IWhatsAppBusinessAccount, type IWhatsAppBusinessNumber, type IWhatsAppByWasenderChannelConfig, type IWhatsAppByWasenderReceivedMessage, type IWhatsAppChannelMessage, type IWhatsAppCloudContact, type IWhatsAppCloudMessage, type IWhatsAppCloudMessageMetadata, type IWhatsAppCloudTemplate, type IWhatsAppCloudTemplateComponent, type IWhatsAppCloudTemplateMessage, type IWhatsAppCloudTemplateParameter, type IWhatsAppCloudTemplateResponse, type IWhatsAppCloudWebhookPayload, type IWhatsAppData, type IWhatsAppMessageListener, type IWhatsAppProxyListenMessageEventData, type IWhatsAppProxyListenMessageEventReq, type IWhatsAppProxyMessage, type IWhatsAppProxyMessageContent, type IWhatsAppProxyMessageEventReq, type IWhatsAppProxySendMessageEventReq, type IWhatsAppReceivedMessage, type IWhatsAppRepository, type IWhatsAppSenderOptions, type IWhatsappChannelConfig, type IchatControllerConfig, Job, JobRepository, JobRunner, Jwt, JwtAccessAndRefreshTokenDto, JwtConfig, JwtGuardMiddleware, JwtHandshakeGuardMiddleware, JwtRefreshToken, JwtRefreshTokenRepository, JwtSigner, JwtTokenDto, Lifecycle, Locker, Logger, Mapper, Mindset, MindsetMetadataStore, MindsetOperator, Money, MoneyDto, OpenRouterChatAdapter, OpenaiChatAdapter, Password, type PasswordHashOptions, Persistent, PgApiKeyRepository, PgChatMemory, PgChatRepository, PgCronJobRepository, PgCrudRepository, PgJobRepository, PgJwtRefreshTokenRepository, PgLockKey, PgLocker, PgRepositoryBase, PgWhatsAppRepository, RamChatMemory, RamChatRepository, Random, RemoteApiKeyRepository, RestControllerMetadataStore, RestRequest, SocketChannel, SocketChannelConfig, SocketChannelReceivedMessage, SocketControllerMetadataStore, SocketServerConfig, SocketServerProvider, Storable, TelegramChannel, TelegramChannelConfig, ValidationMetadataStore, WHATSAPP_MESSAGE_EVENT, WHATSAPP_PROXY_LISTEN_MESSAGE_EVENT, WHATSAPP_PROXY_SEND_MESSAGE_EVENT, WabotChatAdapter, WasenderWebhookController, WhatsApp, WhatsAppByWasenderChannel, WhatsAppByWasenderChannelConfig, WhatsAppChannel, WhatsAppReceiver, WhatsAppReceiverByCloudApi, WhatsAppReceiverByWabotProxy, WhatsAppReceiverByWasender, WhatsAppRepository, WhatsAppSender, WhatsAppSenderByCloudApi, WhatsAppSenderByWabotProxy, WhatsAppSenderByWasender, WhatsAppWabotProxyConnection, WhatsappChannelConfig, apiKeyGuard, apiKeyHandshakeGuard, chatBot, chatController, chatItemTypeOptions, cmd, cmdChannelName, command, commandHandler, container, cron, description, errorToPlainObject, extractChatMessageText, extractNumberFromWasenderMessageKey, getClientMap, getPgClient, handshakeMiddlewares, inject, injectable, isArray, isBoolean, isChatMessageEmpty, isDate, isIn, isModel, isNotEmpty, isNumber, isOptional, isPresent, isRecord, isString, jwtGuard, jwtHandshakeGuard, max, middleware, min, mindset, mindsetModule, modelInfo, onDelete, onGet, onPost, onPut, onSocketEvent, pgStorage, readJsonFromFile, restController, runChatControllers, runCommandHandlers, runCronHandlers, runRestControllers, runSocketControllers, safeJsonParse, scoped, setupErrorHandlers, singleton, socket, socketChannelName, socketController, stopCommandHandlers, stopCronHandlers, telegram, telegramChannelName, validateAndTransform, validateArray, validateIsBoolean, validateIsDate, validateIsIn, validateIsNotEmpty, validateIsNumber, validateIsPresent, validateIsRecord, validateIsString, validateMax, validateMin, validateModel, whatsApp, whatsAppByWasender, whatsAppByWasenderChannelName, whatsAppChannelName, withPgClient, withPgTransaction, writeJsonToFile };
|
package/dist/src/index.js
CHANGED
|
@@ -63,6 +63,7 @@ export { chatBot } from './feature/chat-bot/metadata/@chatBot.js';
|
|
|
63
63
|
export { ChatBotMetadataStore } from './feature/chat-bot/metadata/ChatBotMetadataStore.js';
|
|
64
64
|
export { safeJsonParse } from './feature/chat-bot/safeJsonParse.js';
|
|
65
65
|
export { extractChatMessageText } from './feature/chat-bot/extractChatMessageText.js';
|
|
66
|
+
export { isChatMessageEmpty } from './feature/chat-bot/isChatMessageEmpty.js';
|
|
66
67
|
export { chatController } from './feature/chat-controller/metadata/controller/@chatController.js';
|
|
67
68
|
export { ControllerMetadataStore } from './feature/chat-controller/metadata/ControllerMetadataStore.js';
|
|
68
69
|
export { ChatResolver } from './feature/chat-controller/ChatResolver.js';
|
|
@@ -126,6 +127,7 @@ export { AnthropicChatAdapter } from './addon/chat-bot/anthropic/AnthropicChatAd
|
|
|
126
127
|
export { DeepSeekChatAdapter } from './addon/chat-bot/deepseek/DeepSeekChatAdapter.js';
|
|
127
128
|
export { GoogleChatAdapter } from './addon/chat-bot/google/GoogleChatAdapter.js';
|
|
128
129
|
export { OpenaiChatAdapter } from './addon/chat-bot/openia/OpenaiChatAdapter.js';
|
|
130
|
+
export { OpenRouterChatAdapter } from './addon/chat-bot/openrouter/OpenRouterChatAdapter.js';
|
|
129
131
|
export { PgChatRepository } from './addon/chat-bot/pg/PgChatRepository.js';
|
|
130
132
|
export { PgChatMemory } from './addon/chat-bot/pg/PgChatMemory.js';
|
|
131
133
|
export { RamChatMemory } from './addon/chat-bot/ram/RamChatMemory.js';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wabot-dev/framework",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "Framework for IA Chat Bots",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/src/index.js",
|
|
@@ -40,6 +40,7 @@
|
|
|
40
40
|
"peerDependencies": {
|
|
41
41
|
"@anthropic-ai/sdk": "^0.60.0",
|
|
42
42
|
"@google/genai": "^1.16.0",
|
|
43
|
+
"@openrouter/sdk": "^0.12.2",
|
|
43
44
|
"@types/big.js": "^6.2.2",
|
|
44
45
|
"@types/debug": "^4.1.12",
|
|
45
46
|
"@types/express": "^5.0.1",
|
|
@@ -60,12 +61,12 @@
|
|
|
60
61
|
"openai": "^6.10.0",
|
|
61
62
|
"pg": "^8.15.6",
|
|
62
63
|
"reflect-metadata": "^0.2.2",
|
|
63
|
-
"short-uuid": "^
|
|
64
|
+
"short-uuid": "^6.0.3",
|
|
64
65
|
"socket.io": "^4.8.1",
|
|
65
66
|
"socket.io-client": "^4.8.1",
|
|
66
67
|
"tslib": "^2.8.1",
|
|
67
68
|
"tsyringe": "^4.9.1",
|
|
68
|
-
"uuid": "^
|
|
69
|
+
"uuid": "^14.0.0",
|
|
69
70
|
"wasenderapi": "^0.1.5"
|
|
70
71
|
}
|
|
71
72
|
}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { container } from '../../../core/injection/index.js';
|
|
2
|
-
import { WhatsAppByWasenderChannelConfig } from './WhatsAppByWasenderChannelConfig.js';
|
|
3
|
-
import { ControllerMetadataStore } from '../../../feature/chat-controller/metadata/ControllerMetadataStore.js';
|
|
4
|
-
import '../../../feature/chat-controller/ChatResolver.js';
|
|
5
|
-
import '../../../feature/chat-controller/runChatControllers.js';
|
|
6
|
-
import { WhatsAppByWasenderChannel } from './WhatsAppByWasenderChannel.js';
|
|
7
|
-
|
|
8
|
-
function whatsAppByWasender(config) {
|
|
9
|
-
return function (target, propertyKey) {
|
|
10
|
-
const store = container.resolve(ControllerMetadataStore);
|
|
11
|
-
store.saveChannelMetadata({
|
|
12
|
-
channelConstructor: WhatsAppByWasenderChannel,
|
|
13
|
-
functionName: propertyKey.toString(),
|
|
14
|
-
controllerConstructor: target.constructor,
|
|
15
|
-
channelConfig: new WhatsAppByWasenderChannelConfig(config),
|
|
16
|
-
});
|
|
17
|
-
};
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export { whatsAppByWasender };
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
import { __decorate, __metadata } from 'tslib';
|
|
2
|
-
import { injectable } from '../../../core/injection/index.js';
|
|
3
|
-
import { Logger } from '../../../core/logger/Logger.js';
|
|
4
|
-
import { WhatsAppByWasenderChannelConfig } from './WhatsAppByWasenderChannelConfig.js';
|
|
5
|
-
import { WhatsAppReceiverByWasender } from './WhatsAppReceiverByWasender.js';
|
|
6
|
-
import { WhatsAppSenderByWasender } from './WhatsAppSenderByWasender.js';
|
|
7
|
-
|
|
8
|
-
let WhatsAppByWasenderChannel = class WhatsAppByWasenderChannel {
|
|
9
|
-
config;
|
|
10
|
-
sender;
|
|
11
|
-
receiver;
|
|
12
|
-
logger = new Logger('wabot:whatsapp-by-wasender-channel');
|
|
13
|
-
constructor(config, sender, receiver) {
|
|
14
|
-
this.config = config;
|
|
15
|
-
this.sender = sender;
|
|
16
|
-
this.receiver = receiver;
|
|
17
|
-
}
|
|
18
|
-
listen(callback) {
|
|
19
|
-
this.receiver.listenMessage(async (message) => {
|
|
20
|
-
try {
|
|
21
|
-
await callback({
|
|
22
|
-
chatConnection: message.chatConnection,
|
|
23
|
-
message: message.message,
|
|
24
|
-
reply: async (replyMessage) => {
|
|
25
|
-
await this.sender.send({
|
|
26
|
-
from: this.config.phoneNumber,
|
|
27
|
-
to: message.chatConnection.id,
|
|
28
|
-
message: replyMessage,
|
|
29
|
-
});
|
|
30
|
-
},
|
|
31
|
-
});
|
|
32
|
-
}
|
|
33
|
-
catch (err) {
|
|
34
|
-
this.logger.error('Failed to handle WhatsApp message', err);
|
|
35
|
-
}
|
|
36
|
-
});
|
|
37
|
-
}
|
|
38
|
-
connect() {
|
|
39
|
-
this.receiver.connect();
|
|
40
|
-
}
|
|
41
|
-
disconnect() {
|
|
42
|
-
this.receiver.disconnect();
|
|
43
|
-
}
|
|
44
|
-
};
|
|
45
|
-
WhatsAppByWasenderChannel = __decorate([
|
|
46
|
-
injectable(),
|
|
47
|
-
__metadata("design:paramtypes", [WhatsAppByWasenderChannelConfig,
|
|
48
|
-
WhatsAppSenderByWasender,
|
|
49
|
-
WhatsAppReceiverByWasender])
|
|
50
|
-
], WhatsAppByWasenderChannel);
|
|
51
|
-
|
|
52
|
-
export { WhatsAppByWasenderChannel };
|
package/dist/src/addon/chat-controller/whatsapp-by-wasender/WhatsAppByWasenderChannelConfig.js
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
class WhatsAppByWasenderChannelConfig {
|
|
2
|
-
apiKey;
|
|
3
|
-
webhookSecret;
|
|
4
|
-
phoneNumber;
|
|
5
|
-
webhookPath;
|
|
6
|
-
retryOptions;
|
|
7
|
-
constructor(config) {
|
|
8
|
-
this.apiKey = config.apiKey;
|
|
9
|
-
this.webhookSecret = config.webhookSecret;
|
|
10
|
-
this.phoneNumber = config.phoneNumber;
|
|
11
|
-
this.webhookPath = config.webhookPath ?? '/wasender/hook';
|
|
12
|
-
this.retryOptions = config.retryOptions ?? { enabled: true, maxRetries: 3 };
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export { WhatsAppByWasenderChannelConfig };
|
|
@@ -1,106 +0,0 @@
|
|
|
1
|
-
import { __decorate, __metadata } from 'tslib';
|
|
2
|
-
import { Logger } from '../../../core/logger/Logger.js';
|
|
3
|
-
import { injectable } from '../../../core/injection/index.js';
|
|
4
|
-
import { ExpressProvider } from '../../../feature/express/ExpressProvider.js';
|
|
5
|
-
import { createWasender } from '../../../node_modules/wasenderapi/dist/index.js';
|
|
6
|
-
import { WhatsAppByWasenderChannelConfig } from './WhatsAppByWasenderChannelConfig.js';
|
|
7
|
-
import { extractNumberFromWasenderMessageKey } from './extractNumberFromWasenderKey.js';
|
|
8
|
-
|
|
9
|
-
let WhatsAppReceiverByWasender = class WhatsAppReceiverByWasender {
|
|
10
|
-
expressProvider;
|
|
11
|
-
config;
|
|
12
|
-
wasender;
|
|
13
|
-
listener = null;
|
|
14
|
-
logger = new Logger('wabot:whatsapp-receiver-by-wasender');
|
|
15
|
-
constructor(expressProvider, config) {
|
|
16
|
-
this.expressProvider = expressProvider;
|
|
17
|
-
this.config = config;
|
|
18
|
-
this.wasender = createWasender(config.apiKey, undefined, undefined, undefined, config.retryOptions, config.webhookSecret);
|
|
19
|
-
}
|
|
20
|
-
listenMessage(listener) {
|
|
21
|
-
this.listener = listener;
|
|
22
|
-
}
|
|
23
|
-
connect() {
|
|
24
|
-
const expressApp = this.expressProvider.getExpress();
|
|
25
|
-
expressApp.post(this.config.webhookPath, async (req, res) => {
|
|
26
|
-
try {
|
|
27
|
-
const rawBody = await this.getRawBody(req);
|
|
28
|
-
const event = await this.parseEvent(req, rawBody);
|
|
29
|
-
this.logger.trace(`received event ${event.event}`);
|
|
30
|
-
switch (event.event) {
|
|
31
|
-
case 'messages.received':
|
|
32
|
-
const messages = Array.isArray(event.data.messages)
|
|
33
|
-
? event.data.messages
|
|
34
|
-
: [event.data.messages];
|
|
35
|
-
await this.handleMessages(messages);
|
|
36
|
-
break;
|
|
37
|
-
default:
|
|
38
|
-
this.logger.warn(`unhandled event type ${event.event}`);
|
|
39
|
-
}
|
|
40
|
-
res.sendStatus(200);
|
|
41
|
-
}
|
|
42
|
-
catch (err) {
|
|
43
|
-
this.logger.error('Failed to handle Wasender webhook', err);
|
|
44
|
-
res.sendStatus(500);
|
|
45
|
-
}
|
|
46
|
-
});
|
|
47
|
-
this.expressProvider.listen();
|
|
48
|
-
}
|
|
49
|
-
disconnect() {
|
|
50
|
-
// Nothing to disconnect
|
|
51
|
-
}
|
|
52
|
-
async handleMessages(messages) {
|
|
53
|
-
if (!this.listener) {
|
|
54
|
-
this.logger.warn('No listener registered, ignoring messages');
|
|
55
|
-
return;
|
|
56
|
-
}
|
|
57
|
-
for (const message of messages) {
|
|
58
|
-
const from = extractNumberFromWasenderMessageKey(message.key);
|
|
59
|
-
this.logger.trace(`new message from '${from}' to '${this.config.phoneNumber}'`);
|
|
60
|
-
if (message.message.conversation) {
|
|
61
|
-
const chatConnection = {
|
|
62
|
-
chatType: 'PRIVATE',
|
|
63
|
-
channelName: 'WhatsAppByWasenderChannel',
|
|
64
|
-
id: from,
|
|
65
|
-
};
|
|
66
|
-
await this.listener({
|
|
67
|
-
chatConnection,
|
|
68
|
-
message: {
|
|
69
|
-
text: message.message.conversation,
|
|
70
|
-
senderName: message.pushName,
|
|
71
|
-
senderId: from,
|
|
72
|
-
},
|
|
73
|
-
});
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
async parseEvent(req, rawBody) {
|
|
78
|
-
const adapter = {
|
|
79
|
-
getHeader: (name) => req.header(name),
|
|
80
|
-
getRawBody: () => rawBody,
|
|
81
|
-
};
|
|
82
|
-
const event = await this.wasender.handleWebhookEvent(adapter);
|
|
83
|
-
return event;
|
|
84
|
-
}
|
|
85
|
-
getRawBody(req) {
|
|
86
|
-
return new Promise((resolve, reject) => {
|
|
87
|
-
let data = '';
|
|
88
|
-
req.on('data', (chunk) => {
|
|
89
|
-
data += chunk;
|
|
90
|
-
});
|
|
91
|
-
req.on('end', () => {
|
|
92
|
-
resolve(data);
|
|
93
|
-
});
|
|
94
|
-
req.on('error', (err) => {
|
|
95
|
-
reject(err);
|
|
96
|
-
});
|
|
97
|
-
});
|
|
98
|
-
}
|
|
99
|
-
};
|
|
100
|
-
WhatsAppReceiverByWasender = __decorate([
|
|
101
|
-
injectable(),
|
|
102
|
-
__metadata("design:paramtypes", [ExpressProvider,
|
|
103
|
-
WhatsAppByWasenderChannelConfig])
|
|
104
|
-
], WhatsAppReceiverByWasender);
|
|
105
|
-
|
|
106
|
-
export { WhatsAppReceiverByWasender };
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import { __decorate, __metadata } from 'tslib';
|
|
2
|
-
import { Logger } from '../../../core/logger/Logger.js';
|
|
3
|
-
import { injectable } from '../../../core/injection/index.js';
|
|
4
|
-
import { createWasender } from '../../../node_modules/wasenderapi/dist/index.js';
|
|
5
|
-
import { WhatsAppByWasenderChannelConfig } from './WhatsAppByWasenderChannelConfig.js';
|
|
6
|
-
|
|
7
|
-
let WhatsAppSenderByWasender = class WhatsAppSenderByWasender {
|
|
8
|
-
wasender;
|
|
9
|
-
logger = new Logger('wabot:whatsapp-sender-by-wasender');
|
|
10
|
-
constructor(config) {
|
|
11
|
-
this.wasender = createWasender(config.apiKey, undefined, undefined, undefined, config.retryOptions, undefined);
|
|
12
|
-
}
|
|
13
|
-
async send(request) {
|
|
14
|
-
try {
|
|
15
|
-
const textPayload = {
|
|
16
|
-
messageType: 'text',
|
|
17
|
-
to: `+${request.to.replace(/\D+/g, '')}`,
|
|
18
|
-
text: request.message.text ?? 'No Text',
|
|
19
|
-
};
|
|
20
|
-
const result = await this.wasender.send(textPayload);
|
|
21
|
-
this.logger.trace(`message sent from '${request.from}' to '${request.to}'`);
|
|
22
|
-
this.logger.trace(`rate limit remaining: ${result.rateLimit?.remaining}`);
|
|
23
|
-
}
|
|
24
|
-
catch (error) {
|
|
25
|
-
this.logger.error(`Failed to send message from '${request.from}' to '${request.to}'`, error);
|
|
26
|
-
if (error instanceof Error) {
|
|
27
|
-
throw new Error(error.message, { cause: error });
|
|
28
|
-
}
|
|
29
|
-
else {
|
|
30
|
-
throw new Error('error sending message');
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
};
|
|
35
|
-
WhatsAppSenderByWasender = __decorate([
|
|
36
|
-
injectable(),
|
|
37
|
-
__metadata("design:paramtypes", [WhatsAppByWasenderChannelConfig])
|
|
38
|
-
], WhatsAppSenderByWasender);
|
|
39
|
-
|
|
40
|
-
export { WhatsAppSenderByWasender };
|