@futdevpro/nts-dynamo 1.11.26 → 1.11.28

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 (80) hide show
  1. package/build/_modules/discord-assistant/_collections/dias-global-settings.const.js +1 -1
  2. package/build/_modules/discord-assistant/_collections/dias-global-settings.const.js.map +1 -1
  3. package/build/_modules/discord-assistant/_collections/dias.util.d.ts +1 -0
  4. package/build/_modules/discord-assistant/_collections/dias.util.d.ts.map +1 -1
  5. package/build/_modules/discord-assistant/_collections/dias.util.js +1 -0
  6. package/build/_modules/discord-assistant/_collections/dias.util.js.map +1 -1
  7. package/build/_modules/discord-assistant/_models/dias-global-settings.interface.d.ts +1 -1
  8. package/build/_modules/discord-assistant/_services/dias-io.control-service.d.ts.map +1 -1
  9. package/build/_modules/discord-assistant/_services/dias-io.control-service.js +4 -2
  10. package/build/_modules/discord-assistant/_services/dias-io.control-service.js.map +1 -1
  11. package/build/_modules/discord-assistant/_services/dias-main.control-service.d.ts +0 -3
  12. package/build/_modules/discord-assistant/_services/dias-main.control-service.d.ts.map +1 -1
  13. package/build/_modules/discord-assistant/_services/dias.service-base.d.ts +6 -2
  14. package/build/_modules/discord-assistant/_services/dias.service-base.d.ts.map +1 -1
  15. package/build/_modules/discord-assistant/_services/dias.service-base.js +6 -4
  16. package/build/_modules/discord-assistant/_services/dias.service-base.js.map +1 -1
  17. package/build/_modules/discord-bot/_collections/dibo-global-settings.conts.js +1 -1
  18. package/build/_modules/discord-bot/_collections/dibo-global-settings.conts.js.map +1 -1
  19. package/build/_modules/discord-bot/_collections/dibo-operations.util.js +10 -10
  20. package/build/_modules/discord-bot/_collections/dibo-operations.util.js.map +1 -1
  21. package/build/_modules/discord-bot/_services/dibo-commands.control-service.d.ts +1 -1
  22. package/build/_modules/discord-bot/_services/dibo-commands.control-service.d.ts.map +1 -1
  23. package/build/_modules/discord-bot/_services/dibo-commands.control-service.js +3 -3
  24. package/build/_modules/discord-bot/_services/dibo-commands.control-service.js.map +1 -1
  25. package/build/_modules/discord-bot/_services/dibo-io.control-service.d.ts +1 -0
  26. package/build/_modules/discord-bot/_services/dibo-io.control-service.d.ts.map +1 -1
  27. package/build/_modules/discord-bot/_services/dibo-io.control-service.js +8 -6
  28. package/build/_modules/discord-bot/_services/dibo-io.control-service.js.map +1 -1
  29. package/build/_modules/discord-bot/_services/dibo-main.control-service.d.ts +1 -1
  30. package/build/_modules/discord-bot/_services/dibo-main.control-service.d.ts.map +1 -1
  31. package/build/_modules/discord-bot/_services/dibo-main.control-service.js +27 -2
  32. package/build/_modules/discord-bot/_services/dibo-main.control-service.js.map +1 -1
  33. package/build/_modules/mock/socket-server.mock.d.ts +4 -0
  34. package/build/_modules/mock/socket-server.mock.d.ts.map +1 -1
  35. package/build/_modules/mock/socket-server.mock.js +11 -1
  36. package/build/_modules/mock/socket-server.mock.js.map +1 -1
  37. package/build/_modules/mock/socket-server.mock.spec.js +1 -1
  38. package/build/_modules/mock/socket-server.mock.spec.js.map +1 -1
  39. package/build/_modules/oauth2/_services/oauth2.control-service.d.ts.map +1 -1
  40. package/build/_modules/oauth2/_services/oauth2.control-service.js +7 -4
  41. package/build/_modules/oauth2/_services/oauth2.control-service.js.map +1 -1
  42. package/build/_modules/oauth2/index.js +1 -1
  43. package/build/_modules/oauth2/index.js.map +1 -1
  44. package/build/_modules/open-ai/_services/oai-chunk.service-base.d.ts.map +1 -1
  45. package/build/_modules/open-ai/_services/oai-chunk.service-base.js +21 -0
  46. package/build/_modules/open-ai/_services/oai-chunk.service-base.js.map +1 -1
  47. package/build/_modules/open-ai/_services/oai-llm-chat.service-base.d.ts +16 -141
  48. package/build/_modules/open-ai/_services/oai-llm-chat.service-base.d.ts.map +1 -1
  49. package/build/_modules/open-ai/_services/oai-llm-chat.service-base.js +9 -6
  50. package/build/_modules/open-ai/_services/oai-llm-chat.service-base.js.map +1 -1
  51. package/build/_modules/open-ai/_services/oai-llm.service-base.d.ts +1 -22
  52. package/build/_modules/open-ai/_services/oai-llm.service-base.d.ts.map +1 -1
  53. package/build/_modules/open-ai/_services/oai-llm.service-base.js +28 -75
  54. package/build/_modules/open-ai/_services/oai-llm.service-base.js.map +1 -1
  55. package/build/_modules/socket/_services/socket-server.service.d.ts.map +1 -1
  56. package/build/_modules/socket/_services/socket-server.service.js +12 -3
  57. package/build/_modules/socket/_services/socket-server.service.js.map +1 -1
  58. package/build/_modules/socket/app-extended.server.spec.js +44 -7
  59. package/build/_modules/socket/app-extended.server.spec.js.map +1 -1
  60. package/package.json +3 -3
  61. package/src/_modules/discord-assistant/_collections/dias-global-settings.const.ts +1 -1
  62. package/src/_modules/discord-assistant/_collections/dias.util.ts +3 -1
  63. package/src/_modules/discord-assistant/_models/dias-global-settings.interface.ts +1 -1
  64. package/src/_modules/discord-assistant/_services/dias-io.control-service.ts +4 -2
  65. package/src/_modules/discord-assistant/_services/dias-main.control-service.ts +2 -2
  66. package/src/_modules/discord-assistant/_services/dias.service-base.ts +13 -6
  67. package/src/_modules/discord-bot/_collections/dibo-global-settings.conts.ts +1 -1
  68. package/src/_modules/discord-bot/_collections/dibo-operations.util.ts +10 -10
  69. package/src/_modules/discord-bot/_services/dibo-commands.control-service.ts +3 -3
  70. package/src/_modules/discord-bot/_services/dibo-io.control-service.ts +7 -5
  71. package/src/_modules/discord-bot/_services/dibo-main.control-service.ts +23 -2
  72. package/src/_modules/mock/socket-server.mock.spec.ts +1 -1
  73. package/src/_modules/mock/socket-server.mock.ts +13 -3
  74. package/src/_modules/oauth2/_services/oauth2.control-service.ts +7 -4
  75. package/src/_modules/oauth2/index.ts +1 -1
  76. package/src/_modules/open-ai/_services/oai-chunk.service-base.ts +27 -0
  77. package/src/_modules/open-ai/_services/oai-llm-chat.service-base.ts +28 -23
  78. package/src/_modules/open-ai/_services/oai-llm.service-base.ts +31 -96
  79. package/src/_modules/socket/_services/socket-server.service.ts +15 -6
  80. package/src/_modules/socket/app-extended.server.spec.ts +50 -18
@@ -1,5 +1,5 @@
1
1
  try {
2
- require('crypto');
2
+ require('crypto-js');
3
3
  } catch (error) {
4
4
  console.log(
5
5
  '❌ CryptoJS package not found, please install it with: pnpm add crypto-js'
@@ -90,6 +90,10 @@ export class DyNTS_OAI_Chunk_DataServiceBase<
90
90
 
91
91
  async comparePage(page: T_Page, issuer: string): Promise<DyNTS_OAI_PageCompareResult<T_Chunk, T_Page>> {
92
92
  try {
93
+ if (this.debugLog) {
94
+ DyFM_Log.info(`🔍 Comparing page: ${page.name}`);
95
+ }
96
+
93
97
  if (!page?.allFlaggedParentsMerged) {
94
98
  DyFM_Log.T_error(
95
99
  `❌ allFlaggedParentsMerged is not set (${page.name})`, JSON.stringify(page, null, 2)
@@ -125,6 +129,10 @@ export class DyNTS_OAI_Chunk_DataServiceBase<
125
129
  if (
126
130
  compareResults.every(result => result.result === DyNTS_OAI_CompareResult_Type.equal)
127
131
  ) {
132
+ if (this.debugLog) {
133
+ DyFM_Log.info(`✅ Page is equal: ${page.name}`);
134
+ }
135
+
128
136
  return {
129
137
  result: DyNTS_OAI_CompareResult_Type.equal,
130
138
  subjectPage: page,
@@ -138,6 +146,10 @@ export class DyNTS_OAI_Chunk_DataServiceBase<
138
146
  if (
139
147
  compareResults.every(result => result.result === DyNTS_OAI_CompareResult_Type.new)
140
148
  ) {
149
+ if (this.debugLog) {
150
+ DyFM_Log.info(`✅ Page is new: ${page.name}`);
151
+ }
152
+
141
153
  return {
142
154
  result: DyNTS_OAI_CompareResult_Type.new,
143
155
  subjectPage: page,
@@ -148,6 +160,10 @@ export class DyNTS_OAI_Chunk_DataServiceBase<
148
160
  };
149
161
  }
150
162
 
163
+ if (this.debugLog) {
164
+ DyFM_Log.info(`✅ Page is modified: ${page.name}`);
165
+ }
166
+
151
167
  return {
152
168
  result: DyNTS_OAI_CompareResult_Type.modified,
153
169
  subjectPage: page,
@@ -172,6 +188,10 @@ export class DyNTS_OAI_Chunk_DataServiceBase<
172
188
  oldChunks?: T_Chunk[]
173
189
  ): Promise<DyNTS_OAI_ChunkCompareResult<T_Chunk>[]> {
174
190
  try {
191
+ if (this.debugLog) {
192
+ DyFM_Log.info(`🔍 Comparing chunks: ${chunks.length}`);
193
+ }
194
+
175
195
  if (chunks.length === 0) {
176
196
  return [];
177
197
  }
@@ -209,6 +229,10 @@ export class DyNTS_OAI_Chunk_DataServiceBase<
209
229
  oldChunk?: T_Chunk
210
230
  ): Promise<DyNTS_OAI_ChunkCompareResult<T_Chunk>> {
211
231
  try {
232
+ if (this.debugLog) {
233
+ DyFM_Log.info(`🔍 Comparing chunk: ${newChunk.chunkIndex}`);
234
+ }
235
+
212
236
  oldChunk ??= await this.findData({
213
237
  path: newChunk.path,
214
238
  chunkIndex: newChunk.chunkIndex,
@@ -223,6 +247,9 @@ export class DyNTS_OAI_Chunk_DataServiceBase<
223
247
  }); */
224
248
 
225
249
  if (!oldChunk) {
250
+ // itt kéne vektor search-el utána keresni,
251
+ // hogy a page link-je megtalálható-e (avagy csak átnevezésre került-e)
252
+ // hogy az adott tartalom, nem-e csak átnevezésre, szétbontásra vagy összevonásra került-e
226
253
  return {
227
254
  result: DyNTS_OAI_CompareResult_Type.new,
228
255
  oldChunk: null,
@@ -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 { DyFM_safeParseJSON, DyFM_safeParseList, DyNTS_OAI_LLM_ServiceBase } from './oai-llm.service-base';
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 DyFM_safeParseJSON<T>(answer);
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 DyFM_safeParseList<T[]>(answer);
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 DyFM_safeParseJSON<T>(answer);
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 DyFM_safeParseJSON<T>(answer);
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 DyFM_safeParseJSON<T>(answer);
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 DyFM_safeParseList(answer);
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: string,
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 DyFM_safeParseJSON<T>(answer);
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 DyFM_safeParseList<T[]>(answer);
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 DyFM_safeParseJSON<T>(answer);
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 DyFM_safeParseJSON<T>(answer);
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 DyFM_safeParseJSON<T>(answer);
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 DyFM_safeParseList(answer);
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
- }
@@ -498,12 +498,21 @@ export abstract class DyNTS_SocketServerService<
498
498
  }
499
499
  });
500
500
 
501
- newSocketServer.listen(this.params.port);
502
-
503
- DyFM_Log.success(
504
- `\nsocket server setup finished: "${this.params.name}"` +
505
- `\nsocket server listening on port: "${this.params.port}"`
506
- );
501
+ try {
502
+ newSocketServer.listen(this.params.port);
503
+
504
+ DyFM_Log.success(
505
+ `\nsocket server setup finished: "${this.params.name}"` +
506
+ `\nsocket server listening on port: "${this.params.port}"`
507
+ );
508
+ } catch (listenError) {
509
+ const errorMessage = `Failed to bind socket server "${this.params.name}" to port ${this.params.port}. ` +
510
+ `This could be due to port already in use or insufficient permissions. ` +
511
+ `Please ensure the port is available and try again.`;
512
+
513
+ DyFM_Log.error(errorMessage, listenError);
514
+ throw new Error(errorMessage);
515
+ }
507
516
 
508
517
  successCallback();
509
518
 
@@ -9,17 +9,42 @@ describe('| DyNTS_AppExtended;', (): void => {
9
9
  process.setMaxListeners(20);
10
10
  let app: DyNTS_AppExtended;
11
11
 
12
+ // Helper function to safely stop and cleanup app
13
+ const safeStopApp = async (): Promise<void> => {
14
+ if (app) {
15
+ try {
16
+ await app.stop();
17
+ } catch (error) {
18
+ DyFM_Log.testWarn('Error stopping app:', error);
19
+ }
20
+ app = null;
21
+ }
22
+ };
23
+
24
+ // Helper function to wait for app to be ready with timeout
25
+ const waitForAppReady = async (appInstance: DyNTS_AppExtended, timeoutMs: number = 10000): Promise<void> => {
26
+ const startTime = Date.now();
27
+ while (!appInstance.started && (Date.now() - startTime) < timeoutMs) {
28
+ await DyFM_delay(100);
29
+ }
30
+
31
+ if (!appInstance.started) {
32
+ throw new Error(`App failed to start within ${timeoutMs}ms`);
33
+ }
34
+ };
35
+
12
36
  describe('| a extended-base instance;', (): void => {
13
37
  beforeEach(async (): Promise<void> => {
14
38
  try {
15
39
  await DyFM_waitUntil((): boolean => !app, second);
40
+ await DyFM_delay(100); // Ensure previous instance is fully cleaned up
16
41
 
17
42
  app = new DyNTS_AppExtendedBase_Mock();
18
-
19
43
  await DyFM_delay(100);
20
44
 
21
45
  await app.ready();
22
-
46
+ await waitForAppReady(app);
47
+
23
48
  await DyFM_delay(100);
24
49
  } catch (error) {
25
50
  DyFM_Log.testError(
@@ -35,16 +60,15 @@ describe('| DyNTS_AppExtended;', (): void => {
35
60
  (new Error()).stack,
36
61
  (error as DyFM_Error)?.additionalContent?.errors?.reverse()?.unshift()?.stack
37
62
  );
63
+ throw error; // Re-throw to fail the test
38
64
  }
39
65
  });
40
66
 
41
67
  afterEach(async (): Promise<void> => {
42
68
  try {
43
69
  await DyFM_delay(100);
44
-
45
- await app.stop();
46
-
47
- app = null;
70
+ await safeStopApp();
71
+ await DyFM_delay(100);
48
72
  } catch (error) {
49
73
  DyFM_Log.testError(
50
74
  '| DyNTS_AppExtended; | a extended-base instance; test afterEach error:\n',
@@ -64,10 +88,12 @@ describe('| DyNTS_AppExtended;', (): void => {
64
88
 
65
89
  it('| should be created', (): void => {
66
90
  expect(app).toBeDefined();
91
+ expect(app).toBeInstanceOf(DyNTS_AppExtendedBase_Mock);
67
92
  });
68
93
 
69
- it('| should be started', (): void => {
94
+ it('| should be started', async (): Promise<void> => {
70
95
  expect(app.started).toBeTrue();
96
+ expect(app).toBeDefined();
71
97
  });
72
98
  });
73
99
 
@@ -75,13 +101,14 @@ describe('| DyNTS_AppExtended;', (): void => {
75
101
  beforeEach(async (): Promise<void> => {
76
102
  try {
77
103
  await DyFM_waitUntil((): boolean => !app, second);
104
+ await DyFM_delay(100); // Ensure previous instance is fully cleaned up
78
105
 
79
106
  app = new DyNTS_AppExtendedFull_Mock();
80
-
81
107
  await DyFM_delay(100);
82
108
 
83
109
  await app.ready();
84
-
110
+ await waitForAppReady(app);
111
+
85
112
  await DyFM_delay(100);
86
113
  } catch (error) {
87
114
  DyFM_Log.testError(
@@ -97,16 +124,15 @@ describe('| DyNTS_AppExtended;', (): void => {
97
124
  (new Error()).stack,
98
125
  (error as DyFM_Error)?.additionalContent?.errors?.reverse()?.unshift()?.stack
99
126
  );
127
+ throw error; // Re-throw to fail the test
100
128
  }
101
129
  });
102
130
 
103
131
  afterEach(async (): Promise<void> => {
104
132
  try {
105
133
  await DyFM_delay(100);
106
-
107
- await app.stop();
108
-
109
- app = null;
134
+ await safeStopApp();
135
+ await DyFM_delay(100);
110
136
  } catch (error) {
111
137
  DyFM_Log.testError(
112
138
  '| DyNTS_AppExtended; | a extended-full instance; test afterEach error:\n',
@@ -126,10 +152,12 @@ describe('| DyNTS_AppExtended;', (): void => {
126
152
 
127
153
  it('| should be created', async (): Promise<void> => {
128
154
  expect(app).toBeDefined();
155
+ expect(app).toBeInstanceOf(DyNTS_AppExtendedFull_Mock);
129
156
  });
130
157
 
131
158
  it('| should be started', async (): Promise<void> => {
132
159
  expect(app.started).toBeTrue();
160
+ expect(app).toBeDefined();
133
161
  });
134
162
  });
135
163
 
@@ -137,12 +165,14 @@ describe('| DyNTS_AppExtended;', (): void => {
137
165
  beforeEach(async (): Promise<void> => {
138
166
  try {
139
167
  await DyFM_waitUntil((): boolean => !app, second);
168
+ await DyFM_delay(100); // Ensure previous instance is fully cleaned up
140
169
 
141
170
  app = new DyNTS_AppWbMock_Mock();
142
171
  await DyFM_delay(100);
143
172
 
144
173
  await app.ready();
145
-
174
+ await waitForAppReady(app);
175
+
146
176
  await DyFM_delay(100);
147
177
  } catch (error) {
148
178
  DyFM_Log.testError(
@@ -158,15 +188,15 @@ describe('| DyNTS_AppExtended;', (): void => {
158
188
  (new Error()).stack,
159
189
  (error as DyFM_Error)?.additionalContent?.errors?.reverse()?.unshift()?.stack
160
190
  );
191
+ throw error; // Re-throw to fail the test
161
192
  }
162
193
  });
194
+
163
195
  afterEach(async (): Promise<void> => {
164
196
  try {
165
197
  await DyFM_delay(100);
166
-
167
- await app.stop();
168
-
169
- app = null;
198
+ await safeStopApp();
199
+ await DyFM_delay(100);
170
200
  } catch (error) {
171
201
  DyFM_Log.testError(
172
202
  '| DyNTS_AppExtended; | a wb-mock instance; test afterEach error:\n',
@@ -186,10 +216,12 @@ describe('| DyNTS_AppExtended;', (): void => {
186
216
 
187
217
  it('| should be created', async (): Promise<void> => {
188
218
  expect(app).toBeDefined();
219
+ expect(app).toBeInstanceOf(DyNTS_AppWbMock_Mock);
189
220
  });
190
221
 
191
222
  it('| should be started', async (): Promise<void> => {
192
223
  expect(app.started).toBeTrue();
224
+ expect(app).toBeDefined();
193
225
  });
194
226
  });
195
227
  });