@futdevpro/nts-dynamo 1.11.26 → 1.11.27
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/build/_modules/discord-assistant/_collections/dias-global-settings.const.js +1 -1
- package/build/_modules/discord-assistant/_collections/dias-global-settings.const.js.map +1 -1
- package/build/_modules/discord-assistant/_collections/dias.util.d.ts +1 -0
- package/build/_modules/discord-assistant/_collections/dias.util.d.ts.map +1 -1
- package/build/_modules/discord-assistant/_collections/dias.util.js +1 -0
- package/build/_modules/discord-assistant/_collections/dias.util.js.map +1 -1
- package/build/_modules/discord-assistant/_models/dias-global-settings.interface.d.ts +1 -1
- package/build/_modules/discord-assistant/_services/dias-io.control-service.d.ts.map +1 -1
- package/build/_modules/discord-assistant/_services/dias-io.control-service.js +4 -2
- package/build/_modules/discord-assistant/_services/dias-io.control-service.js.map +1 -1
- package/build/_modules/discord-assistant/_services/dias-main.control-service.d.ts +0 -3
- package/build/_modules/discord-assistant/_services/dias-main.control-service.d.ts.map +1 -1
- package/build/_modules/discord-assistant/_services/dias.service-base.d.ts +6 -2
- package/build/_modules/discord-assistant/_services/dias.service-base.d.ts.map +1 -1
- package/build/_modules/discord-assistant/_services/dias.service-base.js +6 -4
- package/build/_modules/discord-assistant/_services/dias.service-base.js.map +1 -1
- package/build/_modules/discord-bot/_collections/dibo-global-settings.conts.js +1 -1
- package/build/_modules/discord-bot/_collections/dibo-global-settings.conts.js.map +1 -1
- package/build/_modules/discord-bot/_collections/dibo-operations.util.js +10 -10
- package/build/_modules/discord-bot/_collections/dibo-operations.util.js.map +1 -1
- package/build/_modules/discord-bot/_services/dibo-commands.control-service.d.ts +1 -1
- package/build/_modules/discord-bot/_services/dibo-commands.control-service.d.ts.map +1 -1
- package/build/_modules/discord-bot/_services/dibo-commands.control-service.js +3 -3
- package/build/_modules/discord-bot/_services/dibo-commands.control-service.js.map +1 -1
- package/build/_modules/discord-bot/_services/dibo-io.control-service.d.ts +1 -0
- package/build/_modules/discord-bot/_services/dibo-io.control-service.d.ts.map +1 -1
- package/build/_modules/discord-bot/_services/dibo-io.control-service.js +3 -2
- package/build/_modules/discord-bot/_services/dibo-io.control-service.js.map +1 -1
- package/build/_modules/discord-bot/_services/dibo-main.control-service.d.ts.map +1 -1
- package/build/_modules/discord-bot/_services/dibo-main.control-service.js +25 -0
- package/build/_modules/discord-bot/_services/dibo-main.control-service.js.map +1 -1
- package/build/_modules/mock/socket-server.mock.d.ts +4 -0
- package/build/_modules/mock/socket-server.mock.d.ts.map +1 -1
- package/build/_modules/mock/socket-server.mock.js +11 -1
- package/build/_modules/mock/socket-server.mock.js.map +1 -1
- package/build/_modules/mock/socket-server.mock.spec.js +1 -1
- package/build/_modules/mock/socket-server.mock.spec.js.map +1 -1
- package/build/_modules/open-ai/_services/oai-llm-chat.service-base.d.ts +16 -141
- package/build/_modules/open-ai/_services/oai-llm-chat.service-base.d.ts.map +1 -1
- package/build/_modules/open-ai/_services/oai-llm-chat.service-base.js +9 -6
- package/build/_modules/open-ai/_services/oai-llm-chat.service-base.js.map +1 -1
- package/build/_modules/open-ai/_services/oai-llm.service-base.d.ts +1 -22
- package/build/_modules/open-ai/_services/oai-llm.service-base.d.ts.map +1 -1
- package/build/_modules/open-ai/_services/oai-llm.service-base.js +28 -75
- package/build/_modules/open-ai/_services/oai-llm.service-base.js.map +1 -1
- package/build/_modules/socket/_services/socket-server.service.d.ts.map +1 -1
- package/build/_modules/socket/_services/socket-server.service.js +12 -3
- package/build/_modules/socket/_services/socket-server.service.js.map +1 -1
- package/build/_modules/socket/app-extended.server.spec.js +44 -7
- package/build/_modules/socket/app-extended.server.spec.js.map +1 -1
- package/package.json +3 -3
- package/src/_modules/discord-assistant/_collections/dias-global-settings.const.ts +1 -1
- package/src/_modules/discord-assistant/_collections/dias.util.ts +3 -1
- package/src/_modules/discord-assistant/_models/dias-global-settings.interface.ts +1 -1
- package/src/_modules/discord-assistant/_services/dias-io.control-service.ts +4 -2
- package/src/_modules/discord-assistant/_services/dias-main.control-service.ts +2 -2
- package/src/_modules/discord-assistant/_services/dias.service-base.ts +13 -6
- package/src/_modules/discord-bot/_collections/dibo-global-settings.conts.ts +1 -1
- package/src/_modules/discord-bot/_collections/dibo-operations.util.ts +10 -10
- package/src/_modules/discord-bot/_services/dibo-commands.control-service.ts +3 -3
- package/src/_modules/discord-bot/_services/dibo-io.control-service.ts +4 -2
- package/src/_modules/discord-bot/_services/dibo-main.control-service.ts +21 -0
- package/src/_modules/mock/socket-server.mock.spec.ts +1 -1
- package/src/_modules/mock/socket-server.mock.ts +13 -3
- package/src/_modules/open-ai/_services/oai-llm-chat.service-base.ts +28 -23
- package/src/_modules/open-ai/_services/oai-llm.service-base.ts +31 -96
- package/src/_modules/socket/_services/socket-server.service.ts +15 -6
- package/src/_modules/socket/app-extended.server.spec.ts +50 -18
|
@@ -9,8 +9,8 @@ import { DyNTS_global_settings } from '../../..';
|
|
|
9
9
|
|
|
10
10
|
export abstract class DyNTS_DiAs_Main_ControlService extends DyNTS_DiAs_ServiceBase {
|
|
11
11
|
|
|
12
|
-
protected abstract override botIO_CS: DyNTS_DiAs_IO_ControlService;
|
|
13
|
-
protected abstract override getBotIOControlService(): DyNTS_DiAs_IO_ControlService;
|
|
12
|
+
/* protected abstract override botIO_CS: DyNTS_DiAs_IO_ControlService;
|
|
13
|
+
protected abstract override getBotIOControlService(): DyNTS_DiAs_IO_ControlService; */
|
|
14
14
|
|
|
15
15
|
/* override async start(issuer: string): Promise<void> {
|
|
16
16
|
try {
|
|
@@ -8,6 +8,7 @@ import { DyNTS_global_settings } from '../../../_collections/global-settings.con
|
|
|
8
8
|
import { DyNTS_OAI_GPT_Message } from '../../open-ai/_models/interfaces/oai-gpt-message.interface';
|
|
9
9
|
import { DyNTS_OAI_GPT_Message_Role } from '../../open-ai/_enums/oai-gpt-message-role.enum';
|
|
10
10
|
import { DyNTS_DiAs_Util } from '../_collections/dias.util';
|
|
11
|
+
import { DyNTS_DiAs_IO_ControlService } from './dias-io.control-service';
|
|
11
12
|
|
|
12
13
|
|
|
13
14
|
export abstract class DyNTS_DiAs_ServiceBase extends DyNTS_DiBo_Main_ControlService {
|
|
@@ -17,10 +18,15 @@ export abstract class DyNTS_DiAs_ServiceBase extends DyNTS_DiBo_Main_ControlServ
|
|
|
17
18
|
}
|
|
18
19
|
readonly llmChat_CS: DyNTS_OAI_LLMChat_ServiceBase = this.getLLMChatControlService();
|
|
19
20
|
|
|
21
|
+
protected abstract override botIO_CS: DyNTS_DiAs_IO_ControlService;
|
|
22
|
+
protected abstract override getBotIOControlService(): DyNTS_DiAs_IO_ControlService;
|
|
23
|
+
|
|
20
24
|
defaultSystemPrompt: string = DyNTS_DiAs_global_settings.defaultSystemPrompt;
|
|
21
25
|
|
|
22
|
-
protected constructor(
|
|
23
|
-
|
|
26
|
+
protected constructor(
|
|
27
|
+
dontSetupAutomatically?: boolean,
|
|
28
|
+
) {
|
|
29
|
+
super(dontSetupAutomatically);
|
|
24
30
|
|
|
25
31
|
DyNTS_global_settings.dias_settings ??= DyNTS_DiAs_global_settings;
|
|
26
32
|
|
|
@@ -28,9 +34,10 @@ export abstract class DyNTS_DiAs_ServiceBase extends DyNTS_DiBo_Main_ControlServ
|
|
|
28
34
|
}
|
|
29
35
|
|
|
30
36
|
async gatherDiscordMessagesForMessage(message: Message, limit: number = 100): Promise<Message[]> {
|
|
31
|
-
|
|
32
|
-
|
|
37
|
+
return this.gatherDiscordMessagesForChannel(message.channel as TextChannel, message.author.id, limit);
|
|
38
|
+
}
|
|
33
39
|
|
|
40
|
+
async gatherDiscordMessagesForChannel(channel: TextChannel, userId: string, limit: number = 100): Promise<Message[]> {
|
|
34
41
|
const messages: Message[] = await channel.messages.fetch({ limit: limit }).then(
|
|
35
42
|
messages => messages.filter(
|
|
36
43
|
msg => !DyNTS_DiAs_global_settings.skipConversationMessagesFlags.some(
|
|
@@ -54,13 +61,13 @@ export abstract class DyNTS_DiAs_ServiceBase extends DyNTS_DiBo_Main_ControlServ
|
|
|
54
61
|
message: Message,
|
|
55
62
|
issuer: string,
|
|
56
63
|
): Promise<DyNTS_OAI_GPT_Message[]> {
|
|
57
|
-
|
|
58
|
-
const messages = await this.gatherDiscordMessagesForMessage(message);
|
|
64
|
+
const messages: Message[] = await this.gatherDiscordMessagesForMessage(message);
|
|
59
65
|
|
|
60
66
|
return DyNTS_DiAs_Util.convertDiscordMessagesToOAIConversation({
|
|
61
67
|
messages: messages,
|
|
62
68
|
botClientId: this.botClientId,
|
|
63
69
|
botDisplayName: this.botDisplayName,
|
|
70
|
+
issuer: issuer,
|
|
64
71
|
});
|
|
65
72
|
}
|
|
66
73
|
}
|
|
@@ -19,7 +19,7 @@ export class DyNTS_DiBo_Operations_Util {
|
|
|
19
19
|
)
|
|
20
20
|
|
|
21
21
|
if (!channel) {
|
|
22
|
-
DyFM_Log.error(
|
|
22
|
+
DyFM_Log.error(`No text channel found with name "${name}"`)
|
|
23
23
|
return
|
|
24
24
|
}
|
|
25
25
|
|
|
@@ -30,7 +30,7 @@ export class DyNTS_DiBo_Operations_Util {
|
|
|
30
30
|
const channel = this.findChannelByName(channels, name)
|
|
31
31
|
|
|
32
32
|
if (!channel.isTextBased()) {
|
|
33
|
-
throw new Error(
|
|
33
|
+
throw new Error(`Channel is not text based with name "${name}"`)
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
return channel as TextChannel
|
|
@@ -40,7 +40,7 @@ export class DyNTS_DiBo_Operations_Util {
|
|
|
40
40
|
const channel = this.findChannelByName(channels, name)
|
|
41
41
|
|
|
42
42
|
if (!channel.isVoiceBased()) {
|
|
43
|
-
throw new Error(
|
|
43
|
+
throw new Error(`Channel is not voice based with name "${name}"`)
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
return channel as VoiceChannel
|
|
@@ -55,7 +55,7 @@ export class DyNTS_DiBo_Operations_Util {
|
|
|
55
55
|
const reportMessage = `${client.user?.username} report for duty! ` +
|
|
56
56
|
`(v${DyNTS_global_settings.systemVersion} ${DyNTS_global_settings.env_settings?.environment})`;
|
|
57
57
|
|
|
58
|
-
if (lastReportMessage
|
|
58
|
+
if (lastReportMessage?.content === reportMessage) {
|
|
59
59
|
await this.deleteMessage(lastReportMessage).catch((error) => {
|
|
60
60
|
DyFM_Log.error('Failed to delete message', error);
|
|
61
61
|
});
|
|
@@ -78,7 +78,7 @@ export class DyNTS_DiBo_Operations_Util {
|
|
|
78
78
|
channel.send(message)
|
|
79
79
|
DyFM_Log.success('Message sent to channel', channel.name)
|
|
80
80
|
} else {
|
|
81
|
-
DyFM_Log.error(
|
|
81
|
+
DyFM_Log.error(`Channel is not text based "${channelName}"`)
|
|
82
82
|
}
|
|
83
83
|
}
|
|
84
84
|
|
|
@@ -140,7 +140,7 @@ export class DyNTS_DiBo_Operations_Util {
|
|
|
140
140
|
const channel = this.findChannelByName(guild.channels, channelName)
|
|
141
141
|
|
|
142
142
|
if (!channel?.isTextBased()) {
|
|
143
|
-
DyFM_Log.error(
|
|
143
|
+
DyFM_Log.error(`Channel is not text based "${channelName}"`)
|
|
144
144
|
return
|
|
145
145
|
}
|
|
146
146
|
|
|
@@ -232,7 +232,7 @@ export class DyNTS_DiBo_Operations_Util {
|
|
|
232
232
|
const channel = this.findChannelByName(guild.channels, channelName)
|
|
233
233
|
|
|
234
234
|
if (!channel?.isTextBased()) {
|
|
235
|
-
DyFM_Log.error(
|
|
235
|
+
DyFM_Log.error(`Channel is not text based "${channelName}"`)
|
|
236
236
|
return []
|
|
237
237
|
}
|
|
238
238
|
|
|
@@ -331,7 +331,7 @@ export class DyNTS_DiBo_Operations_Util {
|
|
|
331
331
|
const channel = this.findChannelByName(guild.channels, channelName)
|
|
332
332
|
|
|
333
333
|
if (!channel?.isTextBased()) {
|
|
334
|
-
DyFM_Log.error(
|
|
334
|
+
DyFM_Log.error(`Channel is not text based with name "${channelName}"`)
|
|
335
335
|
return
|
|
336
336
|
}
|
|
337
337
|
|
|
@@ -347,7 +347,7 @@ export class DyNTS_DiBo_Operations_Util {
|
|
|
347
347
|
const channel = this.findChannelByName(guild.channels, channelName)
|
|
348
348
|
|
|
349
349
|
if (!channel?.isTextBased()) {
|
|
350
|
-
DyFM_Log.error(
|
|
350
|
+
DyFM_Log.error(`Channel is not text based with name "${channelName}"`)
|
|
351
351
|
return
|
|
352
352
|
}
|
|
353
353
|
|
|
@@ -369,6 +369,6 @@ export class DyNTS_DiBo_Operations_Util {
|
|
|
369
369
|
DyFM_Log.error('Failed to delete message', error);
|
|
370
370
|
});
|
|
371
371
|
|
|
372
|
-
DyFM_Log.success('Message deleted', message.
|
|
372
|
+
DyFM_Log.success('Message deleted:', message.content);
|
|
373
373
|
}
|
|
374
374
|
}
|
|
@@ -16,11 +16,11 @@ export abstract class DyNTS_DiBo_Commands_ControlService extends DyNTS_Singleton
|
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
protected abstract getMainDiscordBotControlService(): DyNTS_DiBo_Main_ControlService;
|
|
19
|
-
protected readonly
|
|
19
|
+
protected readonly diAs_CS: DyNTS_DiBo_Main_ControlService =
|
|
20
20
|
this.getMainDiscordBotControlService();
|
|
21
21
|
|
|
22
22
|
get discordServer(): Guild {
|
|
23
|
-
return this.
|
|
23
|
+
return this.diAs_CS?.discordServer;
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
protected constructor() {
|
|
@@ -45,7 +45,7 @@ export abstract class DyNTS_DiBo_Commands_ControlService extends DyNTS_Singleton
|
|
|
45
45
|
try {
|
|
46
46
|
let haveCommandOperator = false;
|
|
47
47
|
let msg = message.content.replace(
|
|
48
|
-
`<@${this.
|
|
48
|
+
`<@${this.diAs_CS.client.user.id}>`, ''
|
|
49
49
|
).trim();
|
|
50
50
|
|
|
51
51
|
if (!DyNTS_DiBo_global_settings.commandSettings.commandOperator) {
|
|
@@ -32,6 +32,8 @@ export abstract class DyNTS_DiBo_IO_ControlService extends DyNTS_SingletonServic
|
|
|
32
32
|
protected abstract getCommandsControlService(): DyNTS_DiBo_Commands_ControlService;
|
|
33
33
|
protected commands_CS: DyNTS_DiBo_Commands_ControlService;
|
|
34
34
|
|
|
35
|
+
dontSendErrorReply?: boolean;
|
|
36
|
+
|
|
35
37
|
/* protected constructor() {
|
|
36
38
|
super();
|
|
37
39
|
} */
|
|
@@ -86,9 +88,9 @@ export abstract class DyNTS_DiBo_IO_ControlService extends DyNTS_SingletonServic
|
|
|
86
88
|
} catch (error) {
|
|
87
89
|
DyFM_Error.logSimple('❌❌ Error handleNewMessage:', error);
|
|
88
90
|
|
|
89
|
-
if (DyNTS_DiBo_global_settings.debugLevel >= 1) {
|
|
91
|
+
if (!this.dontSendErrorReply && DyNTS_DiBo_global_settings.debugLevel >= 1) {
|
|
90
92
|
await message.reply(
|
|
91
|
-
`[SYSTEM|ERROR] Error occurred while handling the message:\n` +
|
|
93
|
+
`[SYSTEM|ERROR|${DyNTS_global_settings.systemShortCodeName}|DyNTS-DiBo-IO-H0] Error occurred while handling the message:\n` +
|
|
92
94
|
DyFM_Error.getAnyMessage(error)
|
|
93
95
|
).catch(error => {
|
|
94
96
|
DyFM_Error.logSimple('❌❌ Error sending message to report channel:', error);
|
|
@@ -102,6 +102,7 @@ export abstract class DyNTS_DiBo_Main_ControlService extends DyNTS_SingletonServ
|
|
|
102
102
|
intents: DyNTS_global_settings.bot_settings.intents,
|
|
103
103
|
partials: DyNTS_global_settings.bot_settings.partials,
|
|
104
104
|
})
|
|
105
|
+
DyFM_Log.success('Discord client initialized');
|
|
105
106
|
|
|
106
107
|
if (!dontSetupAutomatically) {
|
|
107
108
|
this.setup('system-init');
|
|
@@ -172,6 +173,11 @@ export abstract class DyNTS_DiBo_Main_ControlService extends DyNTS_SingletonServ
|
|
|
172
173
|
DyNTS_GlobalService.globalErrorHandler(error);
|
|
173
174
|
reject(error);
|
|
174
175
|
});
|
|
176
|
+
if (this.debugLog) {
|
|
177
|
+
DyFM_Log.info('Error event registered\n\n', new Error().stack);
|
|
178
|
+
} else {
|
|
179
|
+
DyFM_Log.info('Error event registered');
|
|
180
|
+
}
|
|
175
181
|
|
|
176
182
|
this.client.on('ready', async () => {
|
|
177
183
|
if (DyNTS_DiBo_global_settings.debugLevel >= 1) {
|
|
@@ -193,6 +199,11 @@ export abstract class DyNTS_DiBo_Main_ControlService extends DyNTS_SingletonServ
|
|
|
193
199
|
DyFM_Log.success('Discord Bot setup complete')
|
|
194
200
|
resolve();
|
|
195
201
|
});
|
|
202
|
+
if (this.debugLog) {
|
|
203
|
+
DyFM_Log.info('Ready event registered\n\n', new Error().stack);
|
|
204
|
+
} else {
|
|
205
|
+
DyFM_Log.info('Ready event registered');
|
|
206
|
+
}
|
|
196
207
|
|
|
197
208
|
this.client.on('messageCreate', (message: Message) => {
|
|
198
209
|
try {
|
|
@@ -201,6 +212,11 @@ export abstract class DyNTS_DiBo_Main_ControlService extends DyNTS_SingletonServ
|
|
|
201
212
|
DyFM_Log.error('Error handling new message:', error);
|
|
202
213
|
}
|
|
203
214
|
});
|
|
215
|
+
if (this.debugLog) {
|
|
216
|
+
DyFM_Log.info('Message create event registered\n\n', new Error().stack);
|
|
217
|
+
} else {
|
|
218
|
+
DyFM_Log.info('Message create event registered');
|
|
219
|
+
}
|
|
204
220
|
|
|
205
221
|
process.on('exit', () => {
|
|
206
222
|
try {
|
|
@@ -214,6 +230,11 @@ export abstract class DyNTS_DiBo_Main_ControlService extends DyNTS_SingletonServ
|
|
|
214
230
|
DyFM_Log.error('Error sending message to report channel:', error);
|
|
215
231
|
}
|
|
216
232
|
});
|
|
233
|
+
if (this.debugLog) {
|
|
234
|
+
DyFM_Log.info('Exit event registered\n\n', new Error().stack);
|
|
235
|
+
} else {
|
|
236
|
+
DyFM_Log.info('Exit event registered');
|
|
237
|
+
}
|
|
217
238
|
|
|
218
239
|
this.client.login(DyNTS_global_settings.env_settings.discord.token).catch((error) => {
|
|
219
240
|
reject(error);
|
|
@@ -20,7 +20,7 @@ describe('| DyNTS_SocketServer_Mock', () => {
|
|
|
20
20
|
|
|
21
21
|
expect(params).toBeInstanceOf(DyNTS_SocketServerService_Params);
|
|
22
22
|
expect(params.name).toBe('test');
|
|
23
|
-
expect(params.port).toBe(
|
|
23
|
+
expect(params.port).toBe(19393); // Updated from 9393 to 19393
|
|
24
24
|
});
|
|
25
25
|
|
|
26
26
|
it('| should return an empty array for incoming events', () => {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { DyFM_SocketEvent } from '@futdevpro/fsm-dynamo/socket';
|
|
2
2
|
import { Socket } from 'socket.io';
|
|
3
|
+
import * as net from 'net';
|
|
3
4
|
|
|
4
5
|
import {
|
|
5
6
|
DyNTS_SocketPresence
|
|
@@ -9,8 +10,17 @@ import {
|
|
|
9
10
|
} from '../socket/_models/socket-server-service-params.control-model';
|
|
10
11
|
import { DyNTS_SocketServerService } from '../socket/_services/socket-server.service';
|
|
11
12
|
|
|
12
|
-
|
|
13
|
-
|
|
13
|
+
/**
|
|
14
|
+
* Utility function to find an available port starting from a base port
|
|
15
|
+
*/
|
|
16
|
+
const findAvailablePort = (basePort: number): number => {
|
|
17
|
+
return basePort; // For now, return the base port, but this could be enhanced
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Mock Socket Server Service for testing purposes
|
|
22
|
+
* Uses a non-privileged port to avoid EACCES errors on Windows
|
|
23
|
+
*/
|
|
14
24
|
export class DyNTS_SocketServer_Mock extends
|
|
15
25
|
DyNTS_SocketServerService<DyNTS_SocketPresence> {
|
|
16
26
|
|
|
@@ -21,7 +31,7 @@ export class DyNTS_SocketServer_Mock extends
|
|
|
21
31
|
getServiceParams(): DyNTS_SocketServerService_Params<any> {
|
|
22
32
|
return new DyNTS_SocketServerService_Params({
|
|
23
33
|
name: 'test',
|
|
24
|
-
port: 9393
|
|
34
|
+
port: findAvailablePort(19393), // Changed from 9393 to 19393 (non-privileged port)
|
|
25
35
|
});
|
|
26
36
|
}
|
|
27
37
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { OpenAI } from 'openai';
|
|
2
2
|
|
|
3
3
|
import { DyFM_OpenAI_Settings, DyFM_OpenAIModel, DyFM_GPTCall_Settings } from '@futdevpro/fsm-dynamo/open-ai';
|
|
4
|
-
import { DyFM_AnyError, DyFM_clone, DyFM_Error, DyFM_Error_Settings, DyFM_Log, DyFM_notNull } from '@futdevpro/fsm-dynamo';
|
|
4
|
+
import { DyFM_AnyError, DyFM_clone, DyFM_Error, DyFM_Error_Settings, DyFM_getLocalStackLocation, DyFM_Log, DyFM_notNull, DyFM_Shared } from '@futdevpro/fsm-dynamo';
|
|
5
5
|
|
|
6
6
|
import { DyNTS_global_settings } from '../../../_collections/global-settings.const';
|
|
7
7
|
import { DyNTS_OAI_GPT_Message } from '../_models/interfaces/oai-gpt-message.interface';
|
|
@@ -9,7 +9,7 @@ import { ChatCompletion } from 'openai/resources';
|
|
|
9
9
|
import { ChatCompletionCreateParamsBase, ChatCompletionMessageParam } from 'openai/resources/chat/completions';
|
|
10
10
|
import { DyNTS_OAI_GPT_Message_Role } from '../_enums/oai-gpt-message-role.enum';
|
|
11
11
|
import { DyNTS_OAI_LLM_Predefined_Requests } from '../_models/interfaces/oai-llm-predefined-requests.interface';
|
|
12
|
-
import {
|
|
12
|
+
import { DyNTS_OAI_LLM_ServiceBase } from './oai-llm.service-base';
|
|
13
13
|
import { DyNTS_OAI_global_settings } from '../_collections/oai-global-settings.const';
|
|
14
14
|
|
|
15
15
|
|
|
@@ -50,7 +50,7 @@ export class DyNTS_OAI_LLMChat_ServiceBase extends DyNTS_OAI_LLM_ServiceBase {
|
|
|
50
50
|
|
|
51
51
|
return answer.toUpperCase().includes(this.predefinedRequests.yesNo.upperCaseYes);
|
|
52
52
|
}
|
|
53
|
-
askYesNoQuestionInConversation = this.yesNoQuestionInConversation;
|
|
53
|
+
askYesNoQuestionInConversation: typeof this.yesNoQuestionInConversation = this.yesNoQuestionInConversation;
|
|
54
54
|
|
|
55
55
|
/**
|
|
56
56
|
* Asks the AI to answer a simple question
|
|
@@ -72,7 +72,7 @@ export class DyNTS_OAI_LLMChat_ServiceBase extends DyNTS_OAI_LLM_ServiceBase {
|
|
|
72
72
|
|
|
73
73
|
return await this.getQuestionAnswerInConversation(set);
|
|
74
74
|
}
|
|
75
|
-
askSimpleQuestionInConversation = this.simpleQuestionInConversation;
|
|
75
|
+
askSimpleQuestionInConversation: typeof this.simpleQuestionInConversation = this.simpleQuestionInConversation;
|
|
76
76
|
|
|
77
77
|
/**
|
|
78
78
|
* Asks the AI to answer a percentage question
|
|
@@ -107,7 +107,7 @@ export class DyNTS_OAI_LLMChat_ServiceBase extends DyNTS_OAI_LLM_ServiceBase {
|
|
|
107
107
|
|
|
108
108
|
return +answer;
|
|
109
109
|
}
|
|
110
|
-
askPercentageQuestionInConversation = this.percentageQuestionInConversation;
|
|
110
|
+
askPercentageQuestionInConversation: typeof this.percentageQuestionInConversation = this.percentageQuestionInConversation;
|
|
111
111
|
|
|
112
112
|
|
|
113
113
|
/**
|
|
@@ -146,7 +146,7 @@ export class DyNTS_OAI_LLMChat_ServiceBase extends DyNTS_OAI_LLM_ServiceBase {
|
|
|
146
146
|
|
|
147
147
|
return null;
|
|
148
148
|
}
|
|
149
|
-
askSelectQuestionInConversation = this.selectQuestionInConversation;
|
|
149
|
+
askSelectQuestionInConversation: typeof this.selectQuestionInConversation = this.selectQuestionInConversation;
|
|
150
150
|
|
|
151
151
|
/**
|
|
152
152
|
* Asks the AI to select one of the options from the list
|
|
@@ -177,9 +177,9 @@ export class DyNTS_OAI_LLMChat_ServiceBase extends DyNTS_OAI_LLM_ServiceBase {
|
|
|
177
177
|
|
|
178
178
|
const answer = await this.getQuestionAnswerInConversation(set);
|
|
179
179
|
|
|
180
|
-
return
|
|
180
|
+
return DyFM_Shared.safeParseJSON<T>(answer);
|
|
181
181
|
}
|
|
182
|
-
askRequestSelectInConversation = this.requestSelectInConversation;
|
|
182
|
+
askRequestSelectInConversation: typeof this.requestSelectInConversation = this.requestSelectInConversation;
|
|
183
183
|
|
|
184
184
|
/**
|
|
185
185
|
* Asks the AI to select one or more of the options from the list
|
|
@@ -218,7 +218,7 @@ export class DyNTS_OAI_LLMChat_ServiceBase extends DyNTS_OAI_LLM_ServiceBase {
|
|
|
218
218
|
|
|
219
219
|
return result;
|
|
220
220
|
}
|
|
221
|
-
askMultipleSelectQuestionWithOptionsInConversation = this.multipleSelectQuestionWithOptionsInConversation;
|
|
221
|
+
askMultipleSelectQuestionWithOptionsInConversation: typeof this.multipleSelectQuestionWithOptionsInConversation = this.multipleSelectQuestionWithOptionsInConversation;
|
|
222
222
|
|
|
223
223
|
/**
|
|
224
224
|
* Asks the AI to select one or more of the options from the list
|
|
@@ -249,9 +249,9 @@ export class DyNTS_OAI_LLMChat_ServiceBase extends DyNTS_OAI_LLM_ServiceBase {
|
|
|
249
249
|
|
|
250
250
|
const answer = await this.getQuestionAnswerInConversation(set);
|
|
251
251
|
|
|
252
|
-
return
|
|
252
|
+
return DyFM_Shared.safeParseList<T[]>(answer);
|
|
253
253
|
}
|
|
254
|
-
askRequestMultipleSelectInConversation = this.requestMultipleSelectInConversation;
|
|
254
|
+
askRequestMultipleSelectInConversation: typeof this.requestMultipleSelectInConversation = this.requestMultipleSelectInConversation;
|
|
255
255
|
|
|
256
256
|
/**
|
|
257
257
|
* Asks the AI to answer a question that must result a JSON object
|
|
@@ -279,9 +279,9 @@ export class DyNTS_OAI_LLMChat_ServiceBase extends DyNTS_OAI_LLM_ServiceBase {
|
|
|
279
279
|
|
|
280
280
|
const answer = await this.getQuestionAnswerInConversation(set);
|
|
281
281
|
|
|
282
|
-
return
|
|
282
|
+
return DyFM_Shared.safeParseJSON<T>(answer);
|
|
283
283
|
}
|
|
284
|
-
askJsonQuestionInConversation = this.jsonQuestionInConversation;
|
|
284
|
+
askJsonQuestionInConversation: typeof this.jsonQuestionInConversation = this.jsonQuestionInConversation;
|
|
285
285
|
|
|
286
286
|
/**
|
|
287
287
|
* Asks the AI to answer a question that must result a JSON object with specific key descriptions
|
|
@@ -314,9 +314,9 @@ export class DyNTS_OAI_LLMChat_ServiceBase extends DyNTS_OAI_LLM_ServiceBase {
|
|
|
314
314
|
|
|
315
315
|
const answer = await this.getQuestionAnswerInConversation(set);
|
|
316
316
|
|
|
317
|
-
return
|
|
317
|
+
return DyFM_Shared.safeParseJSON<T>(answer);
|
|
318
318
|
}
|
|
319
|
-
askJsonQuestionWithKeysDescriptionInConversation = this.jsonQuestionWithKeysDescriptionInConversation;
|
|
319
|
+
askJsonQuestionWithKeysDescriptionInConversation: typeof this.jsonQuestionWithKeysDescriptionInConversation = this.jsonQuestionWithKeysDescriptionInConversation;
|
|
320
320
|
|
|
321
321
|
/**
|
|
322
322
|
* Asks the AI to answer a question that must result a JSON object with specific keys
|
|
@@ -349,9 +349,9 @@ export class DyNTS_OAI_LLMChat_ServiceBase extends DyNTS_OAI_LLM_ServiceBase {
|
|
|
349
349
|
|
|
350
350
|
const answer = await this.getQuestionAnswerInConversation(set);
|
|
351
351
|
|
|
352
|
-
return
|
|
352
|
+
return DyFM_Shared.safeParseJSON<T>(answer);
|
|
353
353
|
}
|
|
354
|
-
askJsonQuestionWithExactKeysInConversation = this.jsonQuestionWithExactKeysInConversation;
|
|
354
|
+
askJsonQuestionWithExactKeysInConversation: typeof this.jsonQuestionWithExactKeysInConversation = this.jsonQuestionWithExactKeysInConversation;
|
|
355
355
|
|
|
356
356
|
/**
|
|
357
357
|
* Asks the AI to answer a question that must result a list of strings
|
|
@@ -379,9 +379,9 @@ export class DyNTS_OAI_LLMChat_ServiceBase extends DyNTS_OAI_LLM_ServiceBase {
|
|
|
379
379
|
|
|
380
380
|
const answer = await this.getQuestionAnswerInConversation(set);
|
|
381
381
|
|
|
382
|
-
return
|
|
382
|
+
return DyFM_Shared.safeParseList(answer);
|
|
383
383
|
}
|
|
384
|
-
askListQuestionInConversation = this.listQuestionInConversation;
|
|
384
|
+
askListQuestionInConversation: typeof this.listQuestionInConversation = this.listQuestionInConversation;
|
|
385
385
|
|
|
386
386
|
/**
|
|
387
387
|
* Asks the AI to answer a question
|
|
@@ -412,7 +412,7 @@ export class DyNTS_OAI_LLMChat_ServiceBase extends DyNTS_OAI_LLM_ServiceBase {
|
|
|
412
412
|
async getQuestionAnswerInConversation(
|
|
413
413
|
set: {
|
|
414
414
|
conversation: DyNTS_OAI_GPT_Message[],
|
|
415
|
-
question
|
|
415
|
+
question?: string,
|
|
416
416
|
issuer: string,
|
|
417
417
|
settings?: DyFM_GPTCall_Settings,
|
|
418
418
|
debugLog?: boolean,
|
|
@@ -426,8 +426,9 @@ export class DyNTS_OAI_LLMChat_ServiceBase extends DyNTS_OAI_LLM_ServiceBase {
|
|
|
426
426
|
});
|
|
427
427
|
}
|
|
428
428
|
/* getQuestionAnswerInConversation = this.getAnswerInConversation; */
|
|
429
|
-
getQuestionInConversation = this.getQuestionAnswerInConversation;
|
|
430
|
-
askQuestionInConversation = this.getQuestionAnswerInConversation;
|
|
429
|
+
getQuestionInConversation: typeof this.getQuestionAnswerInConversation = this.getQuestionAnswerInConversation;
|
|
430
|
+
askQuestionInConversation: typeof this.getQuestionAnswerInConversation = this.getQuestionAnswerInConversation;
|
|
431
|
+
getConversationAnswer: typeof this.getAnswerInConversation = this.getAnswerInConversation;
|
|
431
432
|
|
|
432
433
|
/**
|
|
433
434
|
* Asks the AI to answer a question using the whole conversation
|
|
@@ -500,6 +501,8 @@ export class DyNTS_OAI_LLMChat_ServiceBase extends DyNTS_OAI_LLM_ServiceBase {
|
|
|
500
501
|
|
|
501
502
|
// conversation shortening
|
|
502
503
|
const shortenedConversation = this.shortenConversation(set);
|
|
504
|
+
|
|
505
|
+
this.validateConversation(shortenedConversation);
|
|
503
506
|
|
|
504
507
|
this.logConversation({
|
|
505
508
|
...set,
|
|
@@ -526,7 +529,7 @@ export class DyNTS_OAI_LLMChat_ServiceBase extends DyNTS_OAI_LLM_ServiceBase {
|
|
|
526
529
|
});
|
|
527
530
|
}
|
|
528
531
|
}
|
|
529
|
-
resolveSimpleUserMessageInConversation = this.resolveConversation;
|
|
532
|
+
resolveSimpleUserMessageInConversation: typeof this.resolveConversation = this.resolveConversation;
|
|
530
533
|
|
|
531
534
|
protected shortenConversation(
|
|
532
535
|
set: {
|
|
@@ -599,6 +602,8 @@ export class DyNTS_OAI_LLMChat_ServiceBase extends DyNTS_OAI_LLM_ServiceBase {
|
|
|
599
602
|
}
|
|
600
603
|
) {
|
|
601
604
|
if (set.debugLog || this.debugLog) {
|
|
605
|
+
DyFM_Log.info('Conversation', DyFM_getLocalStackLocation());
|
|
606
|
+
|
|
602
607
|
set.conversation.forEach(message => {
|
|
603
608
|
console.log(
|
|
604
609
|
` - ${message.role}: ${message.content.replace(set.replaceThisInLog, this.defaultLogReplacer)}`
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { OpenAI } from 'openai';
|
|
2
2
|
|
|
3
3
|
import { DyFM_OpenAI_Settings, DyFM_OpenAIModel, DyFM_GPTCall_Settings } from '@futdevpro/fsm-dynamo/open-ai';
|
|
4
|
-
import { DyFM_AnyError, DyFM_Error, DyFM_Error_Settings, DyFM_Log, DyFM_notNull } from '@futdevpro/fsm-dynamo';
|
|
4
|
+
import { DyFM_AnyError, DyFM_Error, DyFM_Error_Settings, DyFM_Log, DyFM_notNull, DyFM_Shared } from '@futdevpro/fsm-dynamo';
|
|
5
5
|
|
|
6
6
|
import { DyNTS_global_settings } from '../../../_collections/global-settings.const';
|
|
7
7
|
import { DyNTS_OAI_GPT_Message } from '../_models/interfaces/oai-gpt-message.interface';
|
|
@@ -193,7 +193,7 @@ export class DyNTS_OAI_LLM_ServiceBase {
|
|
|
193
193
|
|
|
194
194
|
const answer = await this.askQuestion(set);
|
|
195
195
|
|
|
196
|
-
return
|
|
196
|
+
return DyFM_Shared.safeParseJSON<T>(answer);
|
|
197
197
|
}
|
|
198
198
|
/** the exact same as {@link requestSelect} */
|
|
199
199
|
selectRequest = this.requestSelect;
|
|
@@ -263,7 +263,7 @@ export class DyNTS_OAI_LLM_ServiceBase {
|
|
|
263
263
|
|
|
264
264
|
const answer = await this.askQuestion(set);
|
|
265
265
|
|
|
266
|
-
return
|
|
266
|
+
return DyFM_Shared.safeParseList<T[]>(answer);
|
|
267
267
|
}
|
|
268
268
|
/** the exact same as {@link requestMultipleSelect} */
|
|
269
269
|
multipleSelectRequest = this.requestMultipleSelect;
|
|
@@ -291,7 +291,7 @@ export class DyNTS_OAI_LLM_ServiceBase {
|
|
|
291
291
|
|
|
292
292
|
const answer = await this.askQuestion(set);
|
|
293
293
|
|
|
294
|
-
return
|
|
294
|
+
return DyFM_Shared.safeParseJSON<T>(answer);
|
|
295
295
|
}
|
|
296
296
|
/** the exact same as {@link askJSONQuestion} */
|
|
297
297
|
jsonQuestion = this.askJSONQuestion;
|
|
@@ -324,7 +324,7 @@ export class DyNTS_OAI_LLM_ServiceBase {
|
|
|
324
324
|
|
|
325
325
|
const answer = await this.askQuestion(set);
|
|
326
326
|
|
|
327
|
-
return
|
|
327
|
+
return DyFM_Shared.safeParseJSON<T>(answer);
|
|
328
328
|
}
|
|
329
329
|
/** the exact same as {@link askJSONQuestionWithKeysDescription} */
|
|
330
330
|
jsonQuestionWithKeysDescription = this.askJSONQuestionWithKeysDescription;
|
|
@@ -357,7 +357,7 @@ export class DyNTS_OAI_LLM_ServiceBase {
|
|
|
357
357
|
|
|
358
358
|
const answer = await this.askQuestion(set);
|
|
359
359
|
|
|
360
|
-
return
|
|
360
|
+
return DyFM_Shared.safeParseJSON<T>(answer);
|
|
361
361
|
}
|
|
362
362
|
/** the exact same as {@link askJSONQuestionWithExactKeys} */
|
|
363
363
|
jsonQuestionWithExactKeys = this.askJSONQuestionWithExactKeys;
|
|
@@ -385,7 +385,7 @@ export class DyNTS_OAI_LLM_ServiceBase {
|
|
|
385
385
|
|
|
386
386
|
const answer = await this.askQuestion(set);
|
|
387
387
|
|
|
388
|
-
return
|
|
388
|
+
return DyFM_Shared.safeParseList<string[]>(answer);
|
|
389
389
|
}
|
|
390
390
|
/** the exact same as {@link askListQuestion} */
|
|
391
391
|
listQuestion = this.askListQuestion;
|
|
@@ -597,6 +597,30 @@ export class DyNTS_OAI_LLM_ServiceBase {
|
|
|
597
597
|
content: settings?.systemPrompt || this.defaultSystemPrompt,
|
|
598
598
|
};
|
|
599
599
|
}
|
|
600
|
+
|
|
601
|
+
protected validateConversation(conversation: DyNTS_OAI_GPT_Message[]): void {
|
|
602
|
+
conversation.forEach((message: DyNTS_OAI_GPT_Message, index: number) => {
|
|
603
|
+
if (!message.role) {
|
|
604
|
+
throw new DyFM_Error({
|
|
605
|
+
message: `Message has no role at index ${index}`,
|
|
606
|
+
additionalContent: {
|
|
607
|
+
invalidMessage: message,
|
|
608
|
+
conversation: conversation,
|
|
609
|
+
}
|
|
610
|
+
});
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
if (!message.content) {
|
|
614
|
+
throw new DyFM_Error({
|
|
615
|
+
message: `Message has no content at index ${index}`,
|
|
616
|
+
additionalContent: {
|
|
617
|
+
invalidMessage: message,
|
|
618
|
+
conversation: conversation,
|
|
619
|
+
}
|
|
620
|
+
});
|
|
621
|
+
}
|
|
622
|
+
});
|
|
623
|
+
}
|
|
600
624
|
|
|
601
625
|
protected getDefaultErrorSettings(
|
|
602
626
|
fnName: string,
|
|
@@ -618,92 +642,3 @@ export class DyNTS_OAI_LLM_ServiceBase {
|
|
|
618
642
|
|
|
619
643
|
//#endregion
|
|
620
644
|
}
|
|
621
|
-
|
|
622
|
-
/**
|
|
623
|
-
* parses the JSON list, if it fails, it returns the answer as a single item in an array
|
|
624
|
-
*
|
|
625
|
-
* (uses {@link DyFM_safeParseJSON})
|
|
626
|
-
* @deprecated use {@link DyFM_Shared.safeParseList} instead
|
|
627
|
-
*/
|
|
628
|
-
export function DyFM_safeParseList<T extends Array<any>>(
|
|
629
|
-
textedJSON: string,
|
|
630
|
-
disableErrorLog?: boolean
|
|
631
|
-
): T {
|
|
632
|
-
const parsed = DyFM_safeParseJSON<T>(textedJSON, true);
|
|
633
|
-
|
|
634
|
-
if (Array.isArray(parsed)) {
|
|
635
|
-
return parsed;
|
|
636
|
-
} else if (typeof parsed === 'object') {
|
|
637
|
-
if (!disableErrorLog) {
|
|
638
|
-
DyFM_Log.warn(
|
|
639
|
-
'DyFM_safeParseList result is an object, returning its values',
|
|
640
|
-
{
|
|
641
|
-
parsed: parsed,
|
|
642
|
-
}
|
|
643
|
-
);
|
|
644
|
-
}
|
|
645
|
-
|
|
646
|
-
return Object.values(parsed) as T;
|
|
647
|
-
} else {
|
|
648
|
-
|
|
649
|
-
if (!disableErrorLog) {
|
|
650
|
-
DyFM_Log.warn(
|
|
651
|
-
'DyFM_safeParseList result is not an array or object, returning it as a single item',
|
|
652
|
-
{
|
|
653
|
-
parsed: parsed,
|
|
654
|
-
}
|
|
655
|
-
);
|
|
656
|
-
}
|
|
657
|
-
|
|
658
|
-
return [ parsed ] as string[] as T;
|
|
659
|
-
}
|
|
660
|
-
}
|
|
661
|
-
|
|
662
|
-
/**
|
|
663
|
-
* parses the JSON, if it fails, it returns { unparsableResult: textedJSON }
|
|
664
|
-
*
|
|
665
|
-
* (uses {@link DyFM_failableSafeParseJSON})
|
|
666
|
-
* @deprecated use {@link DyFM_Shared.safeParseJSON} instead
|
|
667
|
-
*/
|
|
668
|
-
export function DyFM_safeParseJSON<T = any>(
|
|
669
|
-
textedJSON: string,
|
|
670
|
-
disableErrorLog?: boolean
|
|
671
|
-
): T | { unparsableResult: string } {
|
|
672
|
-
try {
|
|
673
|
-
return DyFM_failableSafeParseJSON(textedJSON);
|
|
674
|
-
} catch (error) {
|
|
675
|
-
if (!disableErrorLog) {
|
|
676
|
-
DyFM_Log.error(
|
|
677
|
-
'Unable to parse JSON answer:',
|
|
678
|
-
{
|
|
679
|
-
unparsedJSON: textedJSON,
|
|
680
|
-
error: error,
|
|
681
|
-
}
|
|
682
|
-
);
|
|
683
|
-
}
|
|
684
|
-
|
|
685
|
-
return { unparsableResult: textedJSON };
|
|
686
|
-
}
|
|
687
|
-
}
|
|
688
|
-
|
|
689
|
-
/**
|
|
690
|
-
* parses the JSON, if it fails, it throws an error
|
|
691
|
-
* (also will extract the JSON from "```json ... ```" wrapper)
|
|
692
|
-
* @deprecated use {@link DyFM_Shared.failableSafeParseJSON} instead
|
|
693
|
-
*/
|
|
694
|
-
export function DyFM_failableSafeParseJSON<T = any>(textedJSON: string): T {
|
|
695
|
-
if (!textedJSON) {
|
|
696
|
-
throw new Error(`No content provided to JSON parse ("${textedJSON}")`);
|
|
697
|
-
}
|
|
698
|
-
|
|
699
|
-
const match = textedJSON.match(/```json(.*)```/s);
|
|
700
|
-
textedJSON = textedJSON.replaceAll('\n', '');
|
|
701
|
-
|
|
702
|
-
if (match) {
|
|
703
|
-
return JSON.parse(match[1].replaceAll('\n', ''));
|
|
704
|
-
} else {
|
|
705
|
-
return JSON.parse(
|
|
706
|
-
textedJSON.replaceAll('```json', '').replaceAll('```', '')
|
|
707
|
-
);
|
|
708
|
-
}
|
|
709
|
-
}
|