@futdevpro/nts-dynamo 1.14.35 → 1.14.37

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/build/_modules/ai/_models/ai-input-interfaces.d.ts +20 -28
  2. package/build/_modules/ai/_models/ai-input-interfaces.d.ts.map +1 -1
  3. package/build/_modules/ai/_models/ai-input-interfaces.js +3 -0
  4. package/build/_modules/ai/_models/ai-input-interfaces.js.map +1 -1
  5. package/build/_modules/ai/_modules/open-ai/_services/oai-llm-chat.service-base.d.ts +14 -58
  6. package/build/_modules/ai/_modules/open-ai/_services/oai-llm-chat.service-base.d.ts.map +1 -1
  7. package/build/_modules/ai/_modules/open-ai/_services/oai-llm-chat.service-base.js +138 -147
  8. package/build/_modules/ai/_modules/open-ai/_services/oai-llm-chat.service-base.js.map +1 -1
  9. package/build/_modules/ai/_modules/open-ai/_services/oai-llm.service-base.d.ts +27 -180
  10. package/build/_modules/ai/_modules/open-ai/_services/oai-llm.service-base.d.ts.map +1 -1
  11. package/build/_modules/ai/_modules/open-ai/_services/oai-llm.service-base.js +147 -328
  12. package/build/_modules/ai/_modules/open-ai/_services/oai-llm.service-base.js.map +1 -1
  13. package/build/_modules/ai/_services/ai-llm-chat.service-base.d.ts +22 -14
  14. package/build/_modules/ai/_services/ai-llm-chat.service-base.d.ts.map +1 -1
  15. package/build/_modules/ai/_services/ai-llm-chat.service-base.js.map +1 -1
  16. package/build/_modules/ai/_services/ai-llm.service-base.d.ts +52 -21
  17. package/build/_modules/ai/_services/ai-llm.service-base.d.ts.map +1 -1
  18. package/build/_modules/ai/_services/ai-llm.service-base.js +171 -0
  19. package/build/_modules/ai/_services/ai-llm.service-base.js.map +1 -1
  20. package/build/_modules/ai/_services/ai-provider.service-base.d.ts +1 -1
  21. package/build/_modules/ai/_services/ai-provider.service-base.d.ts.map +1 -1
  22. package/build/_modules/assistant/_services/ass-io.control-service.js +2 -2
  23. package/build/_modules/assistant/_services/ass-io.control-service.js.map +1 -1
  24. package/build/_modules/bot/_models/bot-channel-wrapper.interface.d.ts +8 -2
  25. package/build/_modules/bot/_models/bot-channel-wrapper.interface.d.ts.map +1 -1
  26. package/build/_modules/bot/_models/bot-channel-wrapper.interface.js +31 -0
  27. package/build/_modules/bot/_models/bot-channel-wrapper.interface.js.map +1 -1
  28. package/build/_modules/bot/_models/bot-message-wrapper.interface.d.ts +6 -1
  29. package/build/_modules/bot/_models/bot-message-wrapper.interface.d.ts.map +1 -1
  30. package/build/_modules/bot/_models/bot-message-wrapper.interface.js +39 -0
  31. package/build/_modules/bot/_models/bot-message-wrapper.interface.js.map +1 -1
  32. package/build/_modules/bot/_models/bot-user-wrapper.interface.d.ts +2 -1
  33. package/build/_modules/bot/_models/bot-user-wrapper.interface.d.ts.map +1 -1
  34. package/build/_modules/bot/_models/bot-user-wrapper.interface.js +18 -0
  35. package/build/_modules/bot/_models/bot-user-wrapper.interface.js.map +1 -1
  36. package/build/_modules/bot/_modules/discord-bot/_services/dib-messaging-provider.control-service.js +9 -6
  37. package/build/_modules/bot/_modules/discord-bot/_services/dib-messaging-provider.control-service.js.map +1 -1
  38. package/build/_modules/bot/_modules/dynamo-bot/_services/dyb-messaging-provider.control-service.js +9 -6
  39. package/build/_modules/bot/_modules/dynamo-bot/_services/dyb-messaging-provider.control-service.js.map +1 -1
  40. package/build/_modules/discord-assistant/_services/dias-chunk.data-service.js +9 -9
  41. package/build/_modules/discord-assistant/_services/dias-chunk.data-service.js.map +1 -1
  42. package/build/_modules/discord-assistant/_services/dias-io.control-service.js +2 -2
  43. package/build/_modules/discord-assistant/_services/dias-io.control-service.js.map +1 -1
  44. package/package.json +1 -1
  45. package/src/_modules/ai/_models/ai-input-interfaces.ts +63 -26
  46. package/src/_modules/ai/_modules/open-ai/_services/oai-llm-chat.service-base.ts +99 -139
  47. package/src/_modules/ai/_modules/open-ai/_services/oai-llm.service-base.ts +246 -294
  48. package/src/_modules/ai/_services/ai-llm-chat.service-base.ts +36 -16
  49. package/src/_modules/ai/_services/ai-llm.service-base.ts +272 -28
  50. package/src/_modules/ai/_services/ai-provider.service-base.ts +1 -1
  51. package/src/_modules/assistant/_services/ass-io.control-service.ts +2 -2
  52. package/src/_modules/bot/_models/bot-channel-wrapper.interface.ts +30 -4
  53. package/src/_modules/bot/_models/bot-message-wrapper.interface.ts +24 -2
  54. package/src/_modules/bot/_models/bot-user-wrapper.interface.ts +8 -2
  55. package/src/_modules/bot/_modules/discord-bot/_services/dib-messaging-provider.control-service.ts +6 -6
  56. package/src/_modules/bot/_modules/dynamo-bot/_services/dyb-messaging-provider.control-service.ts +6 -6
  57. package/src/_modules/discord-assistant/_services/dias-chunk.data-service.ts +9 -9
  58. package/src/_modules/discord-assistant/_services/dias-io.control-service.ts +2 -2
@@ -1,21 +1,23 @@
1
1
  import { DyNTS_AI_LLM_ServiceBase } from './ai-llm.service-base';
2
- import { DyFM_AI_Message } from '@futdevpro/fsm-dynamo/ai';
2
+ import { DyFM_AI_Message, DyFM_AI_CallSettings } from '@futdevpro/fsm-dynamo/ai';
3
3
  import {
4
- DyFM_AI_ConversationQuestion_Input,
4
+ DyFM_AI_ConversationBase_Input,
5
5
  DyFM_AI_ConversationSelect_Input,
6
6
  DyFM_AI_ConversationGenericSelect_Input,
7
7
  DyFM_AI_ConversationMultiSelect_Input,
8
8
  DyFM_AI_ConversationGenericMultiSelect_Input,
9
9
  DyFM_AI_ConversationJSONKeysDescription_Input,
10
10
  DyFM_AI_ConversationJSONExactKeys_Input,
11
- DyFM_AI_ConversationGetAnswer_Input
12
11
  } from '../_models/ai-input-interfaces';
12
+ import { DyFM_getLocalStackLocation, DyFM_Log } from '@futdevpro/fsm-dynamo';
13
13
 
14
14
  /**
15
15
  * Abstract base class for LLM Chat services
16
16
  * Extends LLM service with conversation management capabilities
17
17
  */
18
- export abstract class DyNTS_AI_LLMChat_ServiceBase extends DyNTS_AI_LLM_ServiceBase {
18
+ export abstract class DyNTS_AI_LLMChat_ServiceBase<
19
+ T_AISettings extends DyFM_AI_CallSettings = DyFM_AI_CallSettings
20
+ > extends DyNTS_AI_LLM_ServiceBase<T_AISettings> {
19
21
  // History management
20
22
  /**
21
23
  * Add a message to the conversation history
@@ -33,16 +35,34 @@ export abstract class DyNTS_AI_LLMChat_ServiceBase extends DyNTS_AI_LLM_ServiceB
33
35
  /* abstract getHistory(issuer: string): DyFM_AI_Message[]; */
34
36
 
35
37
  // Conversation methods (from OAI_LLMChat_ServiceBase)
36
- abstract yesNoQuestionInConversation(set: DyFM_AI_ConversationQuestion_Input): Promise<boolean>;
37
- abstract simpleQuestionInConversation(set: DyFM_AI_ConversationQuestion_Input): Promise<string>;
38
- abstract percentageQuestionInConversation(set: DyFM_AI_ConversationQuestion_Input): Promise<number>;
39
- abstract selectQuestionInConversation(set: DyFM_AI_ConversationSelect_Input): Promise<string>;
40
- abstract requestSelectInConversation<T>(set: DyFM_AI_ConversationGenericSelect_Input<T>): Promise<T | { unparsableResult: string }>;
41
- abstract multipleSelectQuestionInConversationWithOptions(set: DyFM_AI_ConversationMultiSelect_Input): Promise<string[]>;
42
- abstract requestMultiselectInConversation<T>(set: DyFM_AI_ConversationGenericMultiSelect_Input<T>): Promise<T[]>;
43
- abstract JSONQuestionInConversationWithKeysDescription(set: DyFM_AI_ConversationJSONKeysDescription_Input): Promise<object>;
44
- abstract JSONQuestionInConversationWithExactKeys(set: DyFM_AI_ConversationJSONExactKeys_Input): Promise<object>;
45
- abstract requestJSONInConversationWithExactKeys<T>(set: DyFM_AI_ConversationJSONExactKeys_Input): Promise<T>;
46
- abstract getQuestionAnswerInConversation(set: DyFM_AI_ConversationQuestion_Input): Promise<string>;
47
- abstract getAnswerInConversation(set: DyFM_AI_ConversationGetAnswer_Input): Promise<string>;
38
+ abstract requestSimpleMessageInConversation(set: DyFM_AI_ConversationBase_Input<T_AISettings>): Promise<string>;
39
+ abstract requestYesNoInConversation(set: DyFM_AI_ConversationBase_Input<T_AISettings>): Promise<boolean>;
40
+ abstract requestPercentageInConversation(set: DyFM_AI_ConversationBase_Input<T_AISettings>): Promise<number>;
41
+
42
+ /* abstract selectQuestionInConversation(set: DyFM_AI_ConversationSelect_Input): Promise<string>; */
43
+ abstract requestSelectInConversation<T>(
44
+ set: DyFM_AI_ConversationGenericSelect_Input<T, T_AISettings>
45
+ ): Promise<T | { unparsableResult: string }>;
46
+ /* abstract multipleSelectQuestionInConversationWithOptions(
47
+ set: DyFM_AI_ConversationMultiSelect_Input<T_AISettings>
48
+ ): Promise<string[]>; */
49
+ abstract requestMultiselectInConversation<T>(
50
+ set: DyFM_AI_ConversationGenericMultiSelect_Input<T, T_AISettings>
51
+ ): Promise<T[] | { unparsableResult: string }>;
52
+
53
+ abstract requestJSONInConversation<T = any>(
54
+ set: DyFM_AI_ConversationBase_Input<T_AISettings>
55
+ ): Promise<T | { unparsableResult: string }>;
56
+ abstract requestJSONInConversationWithKeysDescription<T>(
57
+ set: DyFM_AI_ConversationJSONKeysDescription_Input<T_AISettings>
58
+ ): Promise<T | { unparsableResult: string }>;
59
+ abstract requestJSONInConversationWithExactKeys<T>(
60
+ set: DyFM_AI_ConversationJSONExactKeys_Input<T_AISettings>
61
+ ): Promise<T | { unparsableResult: string }>;
62
+ //abstract getQuestionAnswerInConversation(set: DyFM_AI_ConversationQuestion_Input): Promise<string>;
63
+ //abstract getAnswerInConversation(set: DyFM_AI_ConversationGetAnswer_Input): Promise<string>;
64
+
65
+ abstract requestListInConversation(
66
+ set: DyFM_AI_ConversationBase_Input<T_AISettings>
67
+ ): Promise<string[] | { unparsableResult: string }>;
48
68
  }
@@ -1,72 +1,101 @@
1
1
  import { DyNTS_AI_Provider_ServiceBase } from './ai-provider.service-base';
2
- import { DyFM_AI_CallSettings, DyFM_AI_Message, DyFM_AI_LLM_Response } from '@futdevpro/fsm-dynamo/ai';
3
- import { DyFM_Error_Settings } from '@futdevpro/fsm-dynamo';
2
+ import { DyFM_AI_CallSettings, DyFM_AI_Message, DyFM_AI_LLM_Response, DyFM_AI_MessageRole } from '@futdevpro/fsm-dynamo/ai';
3
+ import { DyFM_Error, DyFM_Error_Settings, DyFM_getLocalStackLocation, DyFM_Log, DyFM_Object } from '@futdevpro/fsm-dynamo';
4
4
  import {
5
- DyFM_AI_Question_Input,
6
- DyFM_AI_ListSelect_Input,
7
5
  DyFM_AI_GenericSelect_Input,
8
- DyFM_AI_MultiSelect_Input,
9
6
  DyFM_AI_GenericMultiSelect_Input,
10
7
  DyFM_AI_JSONKeysDescription_Input,
11
8
  DyFM_AI_JSONExactKeys_Input,
12
- DyFM_AI_SimpleMessage_Input
9
+ DyFM_AI_Message_Input,
13
10
  } from '../_models/ai-input-interfaces';
11
+ import { Items } from 'openai/resources/conversations/items';
14
12
 
15
13
  /**
16
14
  * Abstract base class for LLM services
17
15
  * Defines all methods that must be implemented by AI providers
18
16
  */
19
- export abstract class DyNTS_AI_LLM_ServiceBase extends DyNTS_AI_Provider_ServiceBase {
17
+ export abstract class DyNTS_AI_LLM_ServiceBase<
18
+ T_AISettings extends DyFM_AI_CallSettings = DyFM_AI_CallSettings
19
+ > extends DyNTS_AI_Provider_ServiceBase {
20
20
  /** Default settings for LLM calls */
21
- abstract readonly defaultSettings: DyFM_AI_CallSettings;
21
+ abstract readonly defaultSettings: T_AISettings;
22
22
 
23
23
  /** Default model to use for LLM calls */
24
- abstract readonly defaultModel: string;
24
+ /* abstract readonly defaultModel: string; */
25
25
 
26
26
  /** Provider-specific predefined requests */
27
27
  abstract readonly predefinedRequests: any;
28
+
29
+ _debugLog: boolean = false;
30
+ get debugLog(): boolean {
31
+ return this.defaultSettings?.debugLog ?? this._debugLog;
32
+ }
33
+
34
+ get defaultSystemPrompt(): string {
35
+ return this.defaultSettings.systemPrompt;
36
+ }
37
+
38
+ get defaultModel(): string {
39
+ return this.defaultSettings.useModel;
40
+ }
41
+
42
+ defaultLogReplacer: string = '...long-context...';
28
43
 
29
44
  // Core abstract methods
30
45
  /**
31
46
  * Call LLM with system and user messages
32
47
  */
33
- abstract callLLM(
48
+ /* abstract callLLM(
34
49
  systemMessage: string,
35
50
  userMessage: string,
36
51
  settings?: DyFM_AI_CallSettings,
37
52
  issuer?: string
38
- ): Promise<string>;
53
+ ): Promise<string>; */
39
54
 
40
55
  /**
41
56
  * Call LLM with message history
42
57
  */
43
- abstract callLLMWithHistory(
58
+ /* abstract callLLMWithHistory(
44
59
  messages: DyFM_AI_Message[],
45
60
  settings?: DyFM_AI_CallSettings,
46
61
  issuer?: string
47
- ): Promise<string>;
62
+ ): Promise<string>; */
48
63
 
49
64
  /**
50
65
  * Call LLM and return raw response
51
66
  */
52
- abstract callLLMRaw(
67
+ /* abstract callLLMRaw(
53
68
  messages: DyFM_AI_Message[],
54
69
  settings?: DyFM_AI_CallSettings,
55
70
  issuer?: string
56
- ): Promise<DyFM_AI_LLM_Response>;
71
+ ): Promise<DyFM_AI_LLM_Response>; */
57
72
 
58
73
  // Question methods (from OAI_LLM_ServiceBase)
59
- abstract askQuestion(set: DyFM_AI_Question_Input): Promise<string>;
60
- abstract askYesNoQuestion(set: DyFM_AI_Question_Input): Promise<boolean>;
61
- abstract askPercentageQuestion(set: DyFM_AI_Question_Input): Promise<number>;
62
- abstract askSelectQuestion(set: DyFM_AI_ListSelect_Input): Promise<string>;
63
- abstract requestSelect<T>(set: DyFM_AI_GenericSelect_Input<T>): Promise<T | { unparsableResult: string }>;
64
- abstract askMultipleSelectQuestionWithOptions(set: DyFM_AI_MultiSelect_Input): Promise<string[]>;
65
- abstract requestMultiselect<T>(set: DyFM_AI_GenericMultiSelect_Input<T>): Promise<T[]>;
66
- abstract askJSONQuestionWithKeysDescription(set: DyFM_AI_JSONKeysDescription_Input): Promise<object>;
67
- abstract askJSONQuestionWithExactKeys(set: DyFM_AI_JSONExactKeys_Input): Promise<object>;
68
- abstract requestJSONWithExactKeys<T>(set: DyFM_AI_JSONExactKeys_Input): Promise<T>;
69
- abstract sendMessage(set: DyFM_AI_SimpleMessage_Input): Promise<string>;
74
+ abstract requestSimpleMessage(set: DyFM_AI_Message_Input<T_AISettings>): Promise<string>;
75
+ abstract requestYesNo(set: DyFM_AI_Message_Input<T_AISettings>): Promise<boolean>;
76
+ abstract requestPercentage(set: DyFM_AI_Message_Input<T_AISettings>): Promise<number>;
77
+
78
+ /* abstract askSelectQuestion(set: DyFM_AI_ListSelect_Input): Promise<string>; */
79
+ abstract requestSelect<T>(
80
+ set: DyFM_AI_GenericSelect_Input<T, T_AISettings>
81
+ ): Promise<T | { unparsableResult: string }>;
82
+ /* abstract askMultipleSelectQuestionWithOptions(set: DyFM_AI_MultiSelect_Input): Promise<string[]>; */
83
+ abstract requestMultiselect<T>(
84
+ set: DyFM_AI_GenericMultiSelect_Input<T, T_AISettings>
85
+ ): Promise<T[] | { unparsableResult: string }>;
86
+
87
+ abstract requestJSON<T>(set: DyFM_AI_Message_Input<T_AISettings>): Promise<T | { unparsableResult: string }>;
88
+ abstract requestJSONQuestionWithKeysDescription<T>(
89
+ set: DyFM_AI_JSONKeysDescription_Input<T_AISettings>
90
+ ): Promise<T | { unparsableResult: string }>;
91
+ /* abstract askJSONQuestionWithExactKeys(set: DyFM_AI_JSONExactKeys_Input): Promise<object>; */
92
+ abstract requestJSONWithExactKeys<T>(
93
+ set: DyFM_AI_JSONExactKeys_Input<T_AISettings>
94
+ ): Promise<T | { unparsableResult: string }>;
95
+ /* abstract sendMessage(set: DyFM_AI_SimpleMessage_Input): Promise<string>; */
96
+
97
+ /* abstract requestStringList(set: DyFM_AI_Base_Input<T_AISettings>): Promise<string[] | { unparsableResult: string }>; */
98
+ abstract requestList<T>(set: DyFM_AI_Message_Input<T_AISettings>): Promise<T[] | { unparsableResult: string }>;
70
99
 
71
100
  // Helper methods
72
101
  /* protected abstract getDefaultErrorSettings(
@@ -75,7 +104,222 @@ export abstract class DyNTS_AI_LLM_ServiceBase extends DyNTS_AI_Provider_Service
75
104
  issuer?: string
76
105
  ): DyFM_Error_Settings; */
77
106
 
78
- protected abstract getTextListAsText(list: string[]): string;
107
+ /* protected abstract getTextListAsText(list: string[]): string; */
79
108
 
80
- protected abstract logQuestion(set: any): void;
109
+ /* protected abstract logQuestion(set: DyFM_AI_Base_Input<T_AISettings>): void; */
110
+
111
+ protected convertAnswerToBoolean(answer: string): boolean {
112
+ return answer.toUpperCase().includes(this.predefinedRequests.yesNo.upperCaseYes);
113
+ }
114
+
115
+ protected convertAnswerToNumber(answer: string, message: string): number {
116
+ if (this.isAnswerValid(answer, message)) {
117
+ return null;
118
+ }
119
+
120
+ if (isNaN(+answer)) {
121
+ DyFM_Log.T_error(
122
+ 'DyNTS_AI_LLMChat_ServiceBase.convertAnswerToNumber got an invalid answer',
123
+ {
124
+ question: message,
125
+ answer: answer,
126
+ }
127
+ );
128
+
129
+ return null;
130
+ }
131
+
132
+ return +answer;
133
+ }
134
+
135
+ protected convertAnswerToSelectOption<T>(answer: string, message: string, options: T[]): T {
136
+ if (this.isAnswerValid(answer, message)) {
137
+ return null;
138
+ }
139
+
140
+ answer = answer.toLocaleUpperCase();
141
+
142
+ const stringifiedOptions: string[] = this.stringifySelectOptions(options);
143
+ for (const stringifiedItem of stringifiedOptions) {
144
+ if (answer.includes(stringifiedItem.toLocaleUpperCase())) {
145
+ const parsedItem: T | { unparsableResult: string } = DyFM_Object.safeParseJSON<T>(stringifiedItem);
146
+
147
+ if ((parsedItem as { unparsableResult: string }).unparsableResult) {
148
+ DyFM_Log.T_error(
149
+ 'DyNTS_AI_LLMChat_ServiceBase.convertAnswerToSelectOption got an invalid answer',
150
+ {
151
+ question: message,
152
+ answer: answer,
153
+ }
154
+ );
155
+
156
+ return stringifiedItem as T;
157
+ } else {
158
+ return parsedItem as T;
159
+ }
160
+ }
161
+ }
162
+
163
+ return null;
164
+ }
165
+
166
+ protected convertAnswerToSelectOptions<T>(answer: string, message: string, options: T[]): T[] {
167
+ if (this.isAnswerValid(answer, message)) {
168
+ return null;
169
+ }
170
+
171
+ const enrichedOptions: { stringifiedOption: string, parsedOption: T }[] = options.map(
172
+ (option: T) => ({
173
+ stringifiedOption: this.stringifySelectOption(option),
174
+ parsedOption: option
175
+ })
176
+ );
177
+ const result: T[] = [];
178
+
179
+ for (const item of enrichedOptions) {
180
+ if (answer.includes(item.stringifiedOption)) {
181
+ result.push(item.parsedOption);
182
+ }
183
+ }
184
+
185
+ return result;
186
+ }
187
+
188
+ protected convertAnswerToJSON<T>(answer: string, message: string): T {
189
+ if (this.isAnswerValid(answer, message)) {
190
+ return null;
191
+ }
192
+
193
+ const parsedItem: T | { unparsableResult: string } = DyFM_Object.safeParseJSON<T>(answer);
194
+ if ((parsedItem as { unparsableResult: string }).unparsableResult) {
195
+ DyFM_Log.T_error(
196
+ 'DyNTS_AI_LLMChat_ServiceBase.convertAnswerToJSON got an invalid answer',
197
+ {
198
+ question: message,
199
+ answer: answer,
200
+ }
201
+ );
202
+
203
+ return null;
204
+ }
205
+
206
+ return parsedItem as T;
207
+ }
208
+
209
+ protected convertAnswerToList<T>(answer: string, message: string): T[] {
210
+ if (this.isAnswerValid(answer, message)) {
211
+ return null;
212
+ }
213
+
214
+ return DyFM_Object.safeParseList<T[]>(answer);
215
+ }
216
+
217
+ protected stringifySelectOptions<T>(options: T[]): string[] {
218
+ return options.map(item => this.stringifySelectOption(item));
219
+ }
220
+
221
+ protected stringifySelectOption<T>(option: T): string {
222
+ return JSON.stringify(option);
223
+ }
224
+
225
+ protected isAnswerValid(answer: string, message: string): boolean {
226
+ if (!answer?.trim?.()?.length) {
227
+ DyFM_Log.T_error(
228
+ 'DyNTS_AI_LLMChat_ServiceBase.convertAnswerToSelectOption got an invalid answer',
229
+ {
230
+ question: message,
231
+ answer: answer,
232
+ }
233
+ );
234
+
235
+ return true;
236
+ }
237
+
238
+ return false;
239
+ }
240
+
241
+ /**
242
+ * olvasható mondatszerű-listaszerű formába teszi a listaelemeket
243
+ * pl.: ['a', 'b', 'c'] -> '"a", "b" or "c"'
244
+ */
245
+ protected getTextListAsText(list: string[]): string {
246
+ list = list.filter(item => item?.trim()).map(item => `"${item}"`);
247
+
248
+ /* list = list.map(item => item.toLocaleLowerCase()); */
249
+
250
+ list.push(list.pop() + ' or ' + list.pop());
251
+
252
+ return list.join(', ');
253
+ }
254
+
255
+ protected logQuestion(
256
+ set: DyFM_AI_Message_Input<T_AISettings>
257
+ ): void {
258
+ if (set.settings?.debugLog ?? this._debugLog) {
259
+ console.log('\n - ', set.message);
260
+ }
261
+ }
262
+
263
+ protected getDefaultSystemMessage(settings: T_AISettings): DyFM_AI_Message {
264
+ return {
265
+ role: DyFM_AI_MessageRole.system,
266
+ content: settings?.systemPrompt || this.defaultSystemPrompt,
267
+ };
268
+ }
269
+
270
+ protected validateConversation(conversation: DyFM_AI_Message[]): void {
271
+ conversation.forEach((message: DyFM_AI_Message, index: number) => {
272
+ if (!message.role) {
273
+ throw new DyFM_Error({
274
+ message: `Message has no role at index ${index}`,
275
+ additionalContent: {
276
+ invalidMessage: message,
277
+ conversation: conversation,
278
+ }
279
+ });
280
+ }
281
+
282
+ if (!message.content) {
283
+ throw new DyFM_Error({
284
+ message: `Message has no content at index ${index}`,
285
+ additionalContent: {
286
+ invalidMessage: message,
287
+ conversation: conversation,
288
+ }
289
+ });
290
+ }
291
+ });
292
+ }
293
+
294
+ protected logAnswer(answer: string): void {
295
+ if (this._debugLog) {
296
+ console.log(' - answer: ', answer);
297
+ }
298
+ }
299
+
300
+
301
+
302
+ //////////////////////////////////////////////////////////////////////////////////////////
303
+ // LLM CHAT METHODS //
304
+ //////////////////////////////////////////////////////////////////////////////////////////
305
+
306
+
307
+ protected logConversation(
308
+ set: {
309
+ conversation: DyFM_AI_Message[],
310
+ debugLog?: boolean,
311
+ /** this is used to readably replace too long contents to eg '...' in logs */
312
+ replaceThisInLog?: string,
313
+ }
314
+ ) {
315
+ if (set.debugLog || this._debugLog) {
316
+ DyFM_Log.info('Conversation log at', DyFM_getLocalStackLocation());
317
+
318
+ set.conversation.forEach(message => {
319
+ console.log(
320
+ ` - ${message.role}: ${message.content.replace(set.replaceThisInLog, this.defaultLogReplacer)}`
321
+ );
322
+ });
323
+ }
324
+ }
81
325
  }
@@ -18,7 +18,7 @@ export abstract class DyNTS_AI_Provider_ServiceBase extends DyNTS_SingletonServi
18
18
  * Initialize the provider with configuration
19
19
  * @param config - Provider-specific configuration
20
20
  */
21
- abstract initialize(config: DyFM_AI_Config): void;
21
+ abstract setup(config: DyFM_AI_Config): void;
22
22
 
23
23
  /**
24
24
  * Test the connection to the AI provider
@@ -44,12 +44,12 @@ export abstract class DyNTS_Ass_IO_ControlService extends DyNTS_Bot_IO_ControlSe
44
44
  });
45
45
 
46
46
  // Get AI response using EXISTING getAnswerInConversation method
47
- const aiResult: string = await this.aiProvider.getAnswerInConversation({
47
+ const aiResult: string = await this.aiProvider.requestSimpleMessageInConversation({
48
48
  conversation: aiMessages,
49
- issuer: issuer,
50
49
  settings: {
51
50
  systemPrompt: this.mainBot_CS.defaultSystemPrompt,
52
51
  },
52
+ issuer: issuer,
53
53
  });
54
54
 
55
55
  // Reply via same provider the message came from
@@ -1,25 +1,51 @@
1
1
  import { DyNTS_Bot_MessagingProvider_ServiceBase } from '../_services/bot-messaging-provider.service-base';
2
+ import { DyNTS_Bot_MessageWrapper } from './bot-message-wrapper.interface';
2
3
 
3
4
  /**
4
5
  * Wraps a bot channel with provider context
5
6
  * This ensures channels include the provider information needed for platform-specific operations
6
7
  */
7
- export interface DyNTS_Bot_ChannelWrapper<
8
- T_MessagingPlatformChannel extends any = any
8
+ export class DyNTS_Bot_ChannelWrapper<
9
+ T_MessagingPlatformChannel extends any = any,
10
+ T_MessagingPlatformMessage extends any = any,
9
11
  > {
10
12
  id: string;
11
13
  name: string;
12
14
  isTextBased: boolean;
13
15
  isDM: boolean;
14
-
16
+
15
17
  rawPlatformChannel: T_MessagingPlatformChannel;
16
18
 
17
19
  /** Reference to the provider instance for platform-specific operations */
18
20
  provider: DyNTS_Bot_MessagingProvider_ServiceBase<
19
21
  T_MessagingPlatformChannel,
20
- any, //DyNTS_Bot_MessageWrapper<any>,
22
+ T_MessagingPlatformMessage, //DyNTS_Bot_MessageWrapper<any>,
21
23
  any, //DyNTS_Bot_UserWrapper<any>,
22
24
  any
23
25
  >;
26
+
27
+ constructor(
28
+ set: Partial<DyNTS_Bot_ChannelWrapper<T_MessagingPlatformChannel, T_MessagingPlatformMessage>>
29
+ ) {
30
+ Object.assign(this, set);
31
+ }
32
+
33
+ async sendMessage(content: string, issuer: string): Promise<DyNTS_Bot_MessageWrapper<T_MessagingPlatformMessage>> {
34
+ return await this.provider.sendMessageToChannel(this, content, issuer);
35
+ }
36
+
37
+ async sendTyping(): Promise<void> {
38
+ await this.provider.sendTyping(this);
39
+ }
40
+
41
+ async fetchMessages(limit: number): Promise<DyNTS_Bot_MessageWrapper<T_MessagingPlatformMessage>[]> {
42
+ return await this.provider.fetchMessages(this, limit);
43
+ }
44
+
45
+ /* async fetchAllMessagesWi */
46
+
47
+ async clear(): Promise<void> {
48
+ await this.provider.clearChannel(this);
49
+ }
24
50
  }
25
51
 
@@ -5,7 +5,7 @@ import { DyNTS_Bot_MessagingProvider_ServiceBase } from '../_services/bot-messag
5
5
  * This ensures messages include the provider information needed to send replies
6
6
  * back through the correct platform
7
7
  */
8
- export interface DyNTS_Bot_MessageWrapper<
8
+ export class DyNTS_Bot_MessageWrapper<
9
9
  T_MessagingPlatformMessage extends any = any,
10
10
  > {
11
11
  id: string;
@@ -20,7 +20,7 @@ export interface DyNTS_Bot_MessageWrapper<
20
20
  replyToMessageId?: string;
21
21
  mentions: string[]; // user IDs
22
22
  issuer: string;
23
-
23
+
24
24
  rawPlatformMessage: T_MessagingPlatformMessage; // Original platform message for platform-specific operations
25
25
 
26
26
  /** Reference to the provider instance for sending replies */
@@ -30,5 +30,27 @@ export interface DyNTS_Bot_MessageWrapper<
30
30
  any, //DyNTS_Bot_ChannelWrapper<any>,
31
31
  any //DyNTS_Bot_UserWrapper<any>
32
32
  >;
33
+
34
+ constructor(
35
+ set: Partial<DyNTS_Bot_MessageWrapper<T_MessagingPlatformMessage>>
36
+ ) {
37
+ Object.assign(this, set);
38
+ }
39
+
40
+ async reply(content: string): Promise<DyNTS_Bot_MessageWrapper<T_MessagingPlatformMessage>> {
41
+ return await this.provider.replyToMessage(this, content);
42
+ }
43
+
44
+ async sendTyping(): Promise<void> {
45
+ await this.provider.sendTypingForMessage(this);
46
+ }
47
+
48
+ async fetchMessages(limit: number): Promise<DyNTS_Bot_MessageWrapper<T_MessagingPlatformMessage>[]> {
49
+ return await this.provider.fetchMessagesForMessage(this, limit);
50
+ }
51
+
52
+ async delete(): Promise<void> {
53
+ await this.provider.deleteMessage(this);
54
+ }
33
55
  }
34
56
 
@@ -4,7 +4,7 @@ import { DyNTS_Bot_MessagingProvider_ServiceBase } from '../_services/bot-messag
4
4
  * Wraps a bot user with provider context
5
5
  * This ensures users include the provider information needed for platform-specific operations
6
6
  */
7
- export interface DyNTS_Bot_UserWrapper<
7
+ export class DyNTS_Bot_UserWrapper<
8
8
  T_MessagingPlatformUser extends any = any,
9
9
  /* T_MessagingPlatformService extends DyNTS_Bot_MessagingProvider_ServiceBase<
10
10
  any, //DyNTS_Bot_ChannelWrapper<any> ,
@@ -23,7 +23,7 @@ export interface DyNTS_Bot_UserWrapper<
23
23
  username: string;
24
24
  displayName: string;
25
25
  isBot: boolean;
26
-
26
+
27
27
  rawPlatformUser: T_MessagingPlatformUser;
28
28
 
29
29
  /** Reference to the provider instance for platform-specific operations */
@@ -32,5 +32,11 @@ export interface DyNTS_Bot_UserWrapper<
32
32
  any, //DyNTS_Bot_MessageWrapper<any> ,
33
33
  T_MessagingPlatformUser
34
34
  >;
35
+
36
+ constructor(
37
+ set: Partial<DyNTS_Bot_UserWrapper<T_MessagingPlatformUser>>
38
+ ) {
39
+ Object.assign(this, set);
40
+ }
35
41
  }
36
42
 
@@ -486,7 +486,7 @@ export class DyNTS_DiB_MessagingProvider_ControlService extends DyNTS_Bot_Messag
486
486
  }
487
487
 
488
488
  wrapMessage(message: Message): DyNTS_DiB_Message {
489
- return {
489
+ return new DyNTS_Bot_MessageWrapper<Message>({
490
490
  id: message.id,
491
491
  content: message.content,
492
492
  authorId: message.author.id,
@@ -503,11 +503,11 @@ export class DyNTS_DiB_MessagingProvider_ControlService extends DyNTS_Bot_Messag
503
503
  issuer: message.author.id,
504
504
 
505
505
  provider: this,
506
- };
506
+ });
507
507
  }
508
508
 
509
509
  wrapChannel(channel: Channel): DyNTS_DiB_Channel {
510
- return {
510
+ return new DyNTS_Bot_ChannelWrapper<Channel>({
511
511
  id: channel.id,
512
512
  name: (channel as TextChannel).name || ('DM Channel with ' + (channel as DMChannel).recipient.username),
513
513
  isTextBased: channel.isTextBased(),
@@ -515,11 +515,11 @@ export class DyNTS_DiB_MessagingProvider_ControlService extends DyNTS_Bot_Messag
515
515
  rawPlatformChannel: channel,
516
516
 
517
517
  provider: this,
518
- };
518
+ });
519
519
  }
520
520
 
521
521
  wrapUser(user: GuildMember): DyNTS_DiB_User {
522
- return {
522
+ return new DyNTS_Bot_UserWrapper<GuildMember>({
523
523
  id: user.user.id,
524
524
  username: user.user.username,
525
525
  displayName: user.displayName,
@@ -527,6 +527,6 @@ export class DyNTS_DiB_MessagingProvider_ControlService extends DyNTS_Bot_Messag
527
527
  rawPlatformUser: user,
528
528
 
529
529
  provider: this,
530
- };
530
+ });
531
531
  }
532
532
  }
@@ -386,7 +386,7 @@ export class DyNTS_DyB_MessagingProvider_ControlService extends DyNTS_Bot_Messag
386
386
  }
387
387
 
388
388
  wrapMessage(msgMessage: any): DyNTS_Bot_MessageWrapper<DyFM_Msg_Message> {
389
- return {
389
+ return new DyNTS_Bot_MessageWrapper<DyFM_Msg_Message>({
390
390
  id: msgMessage._id || msgMessage.id,
391
391
  content: msgMessage.content || '',
392
392
  authorId: msgMessage.senderId || msgMessage.authorId,
@@ -403,28 +403,28 @@ export class DyNTS_DyB_MessagingProvider_ControlService extends DyNTS_Bot_Messag
403
403
  issuer: msgMessage.issuer || 'unknown',
404
404
 
405
405
  provider: this,
406
- };
406
+ });
407
407
  }
408
408
 
409
409
  wrapChannel(conversation: any): DyNTS_Bot_ChannelWrapper<DyFM_Msg_Conversation> {
410
- return {
410
+ return new DyNTS_Bot_ChannelWrapper<DyFM_Msg_Conversation>({
411
411
  id: conversation._id || conversation.id,
412
412
  name: conversation.name || conversation.platformChannelId || 'unknown',
413
413
  isTextBased: true,
414
414
  isDM: conversation.type === 'direct',
415
415
  rawPlatformChannel: conversation,
416
416
  provider: this
417
- };
417
+ });
418
418
  }
419
419
 
420
420
  wrapUser(user: any): DyNTS_Bot_UserWrapper<DyFM_Msg_Participant> {
421
- return {
421
+ return new DyNTS_Bot_UserWrapper<DyFM_Msg_Participant>({
422
422
  id: user.userId || user.id,
423
423
  username: user.username || user.userId || user.id,
424
424
  displayName: user.displayName || user.username || user.userId,
425
425
  isBot: user.isBot || false,
426
426
  rawPlatformUser: user,
427
427
  provider: this
428
- };
428
+ });
429
429
  }
430
430
  }