@memberjunction/server 2.110.0 → 2.111.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -358,77 +358,77 @@ export class StopLearningCycleResultType {
358
358
  CycleDetails: CycleDetailsType;
359
359
  }
360
360
 
361
- /**
362
- * This function initializes the Skip learning cycle scheduler. It sets up an event listener for the server's setup complete event and starts the scheduler if learning cycles are enabled and a valid API endpoint is configured.
363
- */
364
- function initializeSkipLearningCycleScheduler() {
365
- try {
366
- // Set up event listener for server initialization
367
- const eventListener = MJGlobal.Instance.GetEventListener(true);
368
- eventListener.subscribe(event => {
369
- // Filter for our server's setup complete event
370
- if (event.eventCode === MJ_SERVER_EVENT_CODE && event.args?.type === 'setupComplete') {
371
- try {
372
- const skipConfigInfo = configInfo.askSkip;
373
- if (!skipConfigInfo) {
374
- LogStatus('Skip AI Learning Cycle Scheduler not started: Skip configuration not found');
375
- return;
376
- }
377
- if (!skipConfigInfo.learningCycleEnabled) {
378
- // Skip AI Learning Cycles not enabled - disabled logging to reduce startup noise
379
- // LogStatus('Skip AI Learning Cycles not enabled in configuration');
380
- return;
381
- }
361
+ // /**
362
+ // * This function initializes the Skip learning cycle scheduler. It sets up an event listener for the server's setup complete event and starts the scheduler if learning cycles are enabled and a valid API endpoint is configured.
363
+ // */
364
+ // function initializeSkipLearningCycleScheduler() {
365
+ // try {
366
+ // // Set up event listener for server initialization
367
+ // const eventListener = MJGlobal.Instance.GetEventListener(true);
368
+ // eventListener.subscribe(event => {
369
+ // // Filter for our server's setup complete event
370
+ // if (event.eventCode === MJ_SERVER_EVENT_CODE && event.args?.type === 'setupComplete') {
371
+ // try {
372
+ // const skipConfigInfo = configInfo.askSkip;
373
+ // if (!skipConfigInfo) {
374
+ // LogStatus('Skip AI Learning Cycle Scheduler not started: Skip configuration not found');
375
+ // return;
376
+ // }
377
+ // if (!skipConfigInfo.learningCycleEnabled) {
378
+ // // Skip AI Learning Cycles not enabled - disabled logging to reduce startup noise
379
+ // // LogStatus('Skip AI Learning Cycles not enabled in configuration');
380
+ // return;
381
+ // }
382
382
 
383
- // Check if we have a valid endpoint when cycles are enabled
384
- const hasLearningEndpoint = (skipConfigInfo.url && skipConfigInfo.url.trim().length > 0) ||
385
- (skipConfigInfo.learningCycleURL && skipConfigInfo.learningCycleURL.trim().length > 0);
386
- if (!hasLearningEndpoint) {
387
- LogError('Skip AI Learning cycle scheduler not started: Learning cycles are enabled but no Learning Cycle API endpoint is configured');
388
- return;
389
- }
383
+ // // Check if we have a valid endpoint when cycles are enabled
384
+ // const hasLearningEndpoint = (skipConfigInfo.url && skipConfigInfo.url.trim().length > 0) ||
385
+ // (skipConfigInfo.learningCycleURL && skipConfigInfo.learningCycleURL.trim().length > 0);
386
+ // if (!hasLearningEndpoint) {
387
+ // LogError('Skip AI Learning cycle scheduler not started: Learning cycles are enabled but no Learning Cycle API endpoint is configured');
388
+ // return;
389
+ // }
390
390
 
391
- const dataSources = event.args.dataSources;
392
- if (dataSources && dataSources.length > 0) {
393
- // Initialize the scheduler
394
- const scheduler = LearningCycleScheduler.Instance;
391
+ // const dataSources = event.args.dataSources;
392
+ // if (dataSources && dataSources.length > 0) {
393
+ // // Initialize the scheduler
394
+ // const scheduler = LearningCycleScheduler.Instance;
395
395
 
396
- // Set the data sources for the scheduler
397
- scheduler.setDataSources(dataSources);
396
+ // // Set the data sources for the scheduler
397
+ // scheduler.setDataSources(dataSources);
398
398
 
399
- // Default is 60 minutes, if the interval is not set in the config, use 60 minutes
400
- const interval = skipConfigInfo.learningCycleIntervalInMinutes ?? 60;
401
-
402
-
403
- if (skipConfigInfo.learningCycleRunUponStartup) {
404
- // If configured to run immediately, run the learning cycle
405
- LogStatus('Skip API Learning Cycle: Run Upon Startup is enabled, running learning cycle immediately');
406
- // Start the scheduler
407
- scheduler.start(interval);
408
- }
409
- else {
410
- // not asked to start right away, just start the scheduler after the interval
411
- LogStatus(`Skip API Learning Cycle: Scheduler first run will start after interval of ${interval} minutes. If you want a learing cycle to run immediately, set the learningCycleRunUponStartup property in the config file to true.`);
412
-
413
- // create a one time timer to start the scheduler
414
- setTimeout(() => {
415
- LogStatus(`Skip API Learning Cycle: Starting scheduler after ${interval} minutes. If you want a learing cycle to run immediately, set the learningCycleRunUponStartup property in the config file to true.`);
416
- scheduler.start(interval);
417
- }, interval * 60 * 1000); // convert minutes to milliseconds
418
- }
419
- } else {
420
- LogError('Cannot initialize Skip learning cycle scheduler: No data sources available');
421
- }
422
- } catch (error) {
423
- LogError(`Error initializing Skip learning cycle scheduler: ${error}`);
424
- }
425
- }
426
- });
427
- } catch (error) {
428
- // Handle any errors from the static initializer
429
- LogError(`Failed to initialize Skip learning cycle scheduler: ${error}`);
430
- }
431
- }
399
+ // // Default is 60 minutes, if the interval is not set in the config, use 60 minutes
400
+ // const interval = skipConfigInfo.learningCycleIntervalInMinutes ?? 60;
401
+
402
+
403
+ // if (skipConfigInfo.learningCycleRunUponStartup) {
404
+ // // If configured to run immediately, run the learning cycle
405
+ // LogStatus('Skip API Learning Cycle: Run Upon Startup is enabled, running learning cycle immediately');
406
+ // // Start the scheduler
407
+ // scheduler.start(interval);
408
+ // }
409
+ // else {
410
+ // // not asked to start right away, just start the scheduler after the interval
411
+ // LogStatus(`Skip API Learning Cycle: Scheduler first run will start after interval of ${interval} minutes. If you want a learing cycle to run immediately, set the learningCycleRunUponStartup property in the config file to true.`);
412
+
413
+ // // create a one time timer to start the scheduler
414
+ // setTimeout(() => {
415
+ // LogStatus(`Skip API Learning Cycle: Starting scheduler after ${interval} minutes. If you want a learing cycle to run immediately, set the learningCycleRunUponStartup property in the config file to true.`);
416
+ // scheduler.start(interval);
417
+ // }, interval * 60 * 1000); // convert minutes to milliseconds
418
+ // }
419
+ // } else {
420
+ // LogError('Cannot initialize Skip learning cycle scheduler: No data sources available');
421
+ // }
422
+ // } catch (error) {
423
+ // LogError(`Error initializing Skip learning cycle scheduler: ${error}`);
424
+ // }
425
+ // }
426
+ // });
427
+ // } catch (error) {
428
+ // // Handle any errors from the static initializer
429
+ // LogError(`Failed to initialize Skip learning cycle scheduler: ${error}`);
430
+ // }
431
+ // }
432
432
  // Disabled: Skip AI Learning Cycles no longer used - commented out to prevent startup initialization
433
433
  // If needed in the future, uncomment the line below:
434
434
  // initializeSkipLearningCycleScheduler();
@@ -565,228 +565,228 @@ export class AskSkipResolver {
565
565
  return this.handleSimpleSkipChatPostRequest(input, convoEntity, convoDetailEntity, true, user, userPayload);
566
566
  }
567
567
 
568
- /**
569
- * Executes a Skip learning cycle
570
- * Learning cycles allow Skip to analyze conversations and improve its knowledge and capabilities
571
- *
572
- * @param dataSource Database connection
573
- * @param userPayload Information about the authenticated user
574
- * @param ForceEntityRefresh Whether to force a refresh of entity metadata
575
- * @returns Result of the learning cycle execution
576
- */
577
- @Mutation(() => AskSkipResultType)
578
- async ExecuteAskSkipLearningCycle(
579
- @Ctx() { dataSource, userPayload, providers }: AppContext,
580
- @Arg('ForceEntityRefresh', () => Boolean, { nullable: true }) ForceEntityRefresh?: boolean
581
- ) {
582
- const skipConfigInfo = configInfo.askSkip;
583
- // First check if learning cycles are enabled in configuration
584
- if (!skipConfigInfo.learningCycleEnabled) {
585
- return {
586
- success: false,
587
- error: 'Learning cycles are not enabled in configuration',
588
- elapsedTime: 0,
589
- noteChanges: [],
590
- queryChanges: [],
591
- requestChanges: []
592
- };
593
- }
568
+ // /**
569
+ // * Executes a Skip learning cycle
570
+ // * Learning cycles allow Skip to analyze conversations and improve its knowledge and capabilities
571
+ // *
572
+ // * @param dataSource Database connection
573
+ // * @param userPayload Information about the authenticated user
574
+ // * @param ForceEntityRefresh Whether to force a refresh of entity metadata
575
+ // * @returns Result of the learning cycle execution
576
+ // */
577
+ // @Mutation(() => AskSkipResultType)
578
+ // async ExecuteAskSkipLearningCycle(
579
+ // @Ctx() { dataSource, userPayload, providers }: AppContext,
580
+ // @Arg('ForceEntityRefresh', () => Boolean, { nullable: true }) ForceEntityRefresh?: boolean
581
+ // ) {
582
+ // const skipConfigInfo = configInfo.askSkip;
583
+ // // First check if learning cycles are enabled in configuration
584
+ // if (!skipConfigInfo.learningCycleEnabled) {
585
+ // return {
586
+ // success: false,
587
+ // error: 'Learning cycles are not enabled in configuration',
588
+ // elapsedTime: 0,
589
+ // noteChanges: [],
590
+ // queryChanges: [],
591
+ // requestChanges: []
592
+ // };
593
+ // }
594
594
 
595
- // Check if we have a valid endpoint when cycles are enabled
596
- const hasLearningEndpoint = (skipConfigInfo.url && skipConfigInfo.url.trim().length > 0) ||
597
- (skipConfigInfo.learningCycleURL && skipConfigInfo.learningCycleURL.trim().length > 0);
598
- if (!hasLearningEndpoint) {
599
- return {
600
- success: false,
601
- error: 'Learning cycle API endpoint is not configured',
602
- elapsedTime: 0,
603
- noteChanges: [],
604
- queryChanges: [],
605
- requestChanges: []
606
- };
607
- }
595
+ // // Check if we have a valid endpoint when cycles are enabled
596
+ // const hasLearningEndpoint = (skipConfigInfo.url && skipConfigInfo.url.trim().length > 0) ||
597
+ // (skipConfigInfo.learningCycleURL && skipConfigInfo.learningCycleURL.trim().length > 0);
598
+ // if (!hasLearningEndpoint) {
599
+ // return {
600
+ // success: false,
601
+ // error: 'Learning cycle API endpoint is not configured',
602
+ // elapsedTime: 0,
603
+ // noteChanges: [],
604
+ // queryChanges: [],
605
+ // requestChanges: []
606
+ // };
607
+ // }
608
608
 
609
- const startTime = new Date();
610
- // First, get the user from the cache
611
- const user = UserCache.Instance.Users.find((u) => u.Email.trim().toLowerCase() === userPayload.email.trim().toLowerCase());
612
- if (!user) throw new Error(`User ${userPayload.email} not found in UserCache`);
613
-
614
- // if already configured this does nothing, just makes sure we're configured
615
- await AIEngine.Instance.Config(false, user);
616
-
617
- // Check if this organization is already running a learning cycle using their organization ID
618
- const organizationId = skipConfigInfo.orgID;
619
- const scheduler = LearningCycleScheduler.Instance;
620
- const runningStatus = scheduler.isOrganizationRunningCycle(organizationId);
609
+ // const startTime = new Date();
610
+ // // First, get the user from the cache
611
+ // const user = UserCache.Instance.Users.find((u) => u.Email.trim().toLowerCase() === userPayload.email.trim().toLowerCase());
612
+ // if (!user) throw new Error(`User ${userPayload.email} not found in UserCache`);
613
+
614
+ // // if already configured this does nothing, just makes sure we're configured
615
+ // await AIEngine.Instance.Config(false, user);
616
+
617
+ // // Check if this organization is already running a learning cycle using their organization ID
618
+ // const organizationId = skipConfigInfo.orgID;
619
+ // const scheduler = LearningCycleScheduler.Instance;
620
+ // const runningStatus = scheduler.isOrganizationRunningCycle(organizationId);
621
621
 
622
- if (runningStatus.isRunning) {
623
- LogStatus(`Learning cycle already in progress for organization ${organizationId}, started at ${runningStatus.startTime.toISOString()}`);
624
- return {
625
- success: false,
626
- error: `Learning cycle already in progress for this organization (started ${Math.round(runningStatus.runningForMinutes)} minutes ago)`,
627
- elapsedTime: 0,
628
- noteChanges: [],
629
- queryChanges: [],
630
- requestChanges: []
631
- };
632
- }
633
-
634
- // Get the Skip agent ID
635
- const md = GetReadWriteProvider(providers);
636
- const skipAgent = AIEngine.Instance.GetAgentByName('Skip');
637
- if (!skipAgent) {
638
- throw new Error("Skip agent not found in AIEngine");
639
- }
640
-
641
- const agentID = skipAgent.ID;
642
-
643
- // Get last complete learning cycle start date for this agent
644
- const lastCompleteLearningCycleDate = await this.GetLastCompleteLearningCycleDate(agentID, user);
645
-
646
- // Create a new learning cycle record for this run
647
- const learningCycleEntity = await md.GetEntityObject<AIAgentLearningCycleEntity>('AI Agent Learning Cycles', user);
648
- learningCycleEntity.NewRecord();
649
- learningCycleEntity.AgentID = skipAgent.ID;
650
- learningCycleEntity.Status = 'In-Progress';
651
- learningCycleEntity.StartedAt = startTime;
652
-
653
- if (!(await learningCycleEntity.Save())) {
654
- throw new Error(`Failed to create learning cycle record: ${learningCycleEntity.LatestResult.Error}`);
655
- }
656
-
657
- const learningCycleId = learningCycleEntity.ID;
658
- LogStatus(`Created new learning cycle with ID: ${learningCycleId}`);
659
-
660
- // Register this organization as running a learning cycle
661
- scheduler.registerRunningCycle(organizationId, learningCycleId);
622
+ // if (runningStatus.isRunning) {
623
+ // LogStatus(`Learning cycle already in progress for organization ${organizationId}, started at ${runningStatus.startTime.toISOString()}`);
624
+ // return {
625
+ // success: false,
626
+ // error: `Learning cycle already in progress for this organization (started ${Math.round(runningStatus.runningForMinutes)} minutes ago)`,
627
+ // elapsedTime: 0,
628
+ // noteChanges: [],
629
+ // queryChanges: [],
630
+ // requestChanges: []
631
+ // };
632
+ // }
633
+
634
+ // // Get the Skip agent ID
635
+ // const md = GetReadWriteProvider(providers);
636
+ // const skipAgent = AIEngine.Instance.GetAgentByName('Skip');
637
+ // if (!skipAgent) {
638
+ // throw new Error("Skip agent not found in AIEngine");
639
+ // }
640
+
641
+ // const agentID = skipAgent.ID;
642
+
643
+ // // Get last complete learning cycle start date for this agent
644
+ // const lastCompleteLearningCycleDate = await this.GetLastCompleteLearningCycleDate(agentID, user);
645
+
646
+ // // Create a new learning cycle record for this run
647
+ // const learningCycleEntity = await md.GetEntityObject<AIAgentLearningCycleEntity>('AI Agent Learning Cycles', user);
648
+ // learningCycleEntity.NewRecord();
649
+ // learningCycleEntity.AgentID = skipAgent.ID;
650
+ // learningCycleEntity.Status = 'In-Progress';
651
+ // learningCycleEntity.StartedAt = startTime;
652
+
653
+ // if (!(await learningCycleEntity.Save())) {
654
+ // throw new Error(`Failed to create learning cycle record: ${learningCycleEntity.LatestResult.Error}`);
655
+ // }
656
+
657
+ // const learningCycleId = learningCycleEntity.ID;
658
+ // LogStatus(`Created new learning cycle with ID: ${learningCycleId}`);
659
+
660
+ // // Register this organization as running a learning cycle
661
+ // scheduler.registerRunningCycle(organizationId, learningCycleId);
662
662
 
663
- try {
664
- // Build the request to Skip learning API
665
- LogStatus(`Building Skip Learning API request`);
666
- const input = await this.buildSkipLearningAPIRequest(learningCycleId, lastCompleteLearningCycleDate, true, true, true, false, dataSource, user, ForceEntityRefresh || false);
667
- if (input.newConversations.length === 0) {
668
- // no new conversations to process
669
- LogStatus(` Skip Learning Cycles: No new conversations to process for learning cycle`);
670
- learningCycleEntity.Status = 'Complete';
671
- learningCycleEntity.AgentSummary = 'No new conversations to process, learning cycle skipped, but recorded for audit purposes.';
672
- learningCycleEntity.EndedAt = new Date();
673
- if (!(await learningCycleEntity.Save())) {
674
- LogError(`Failed to update learning cycle record: ${learningCycleEntity.LatestResult.Error}`);
675
- }
676
- const result: SkipAPILearningCycleResponse = {
677
- success: true,
678
- learningCycleSkipped: true,
679
- elapsedTime: 0,
680
- noteChanges: [],
681
- queryChanges: [],
682
- requestChanges: [],
683
- }
684
- return result;
685
- }
686
- else {
687
- // Make the API request
688
- const response = await this.handleSimpleSkipLearningPostRequest(input, user, learningCycleId, agentID, userPayload);
689
-
690
- // Update learning cycle to completed
691
- const endTime = new Date();
692
- const elapsedTimeMs = endTime.getTime() - startTime.getTime();
693
-
694
- LogStatus(`Learning cycle finished with status: ${response.success ? 'Success' : 'Failed'} in ${elapsedTimeMs / 1000} seconds`);
695
-
696
- learningCycleEntity.Status = response.success ? 'Complete' : 'Failed';
697
- learningCycleEntity.EndedAt = endTime;
698
-
699
- if (!(await learningCycleEntity.Save())) {
700
- LogError(`Failed to update learning cycle record: ${learningCycleEntity.LatestResult.Error}`);
701
- }
663
+ // try {
664
+ // // Build the request to Skip learning API
665
+ // LogStatus(`Building Skip Learning API request`);
666
+ // const input = await this.buildSkipLearningAPIRequest(learningCycleId, lastCompleteLearningCycleDate, true, true, true, false, dataSource, user, ForceEntityRefresh || false);
667
+ // if (input.newConversations.length === 0) {
668
+ // // no new conversations to process
669
+ // LogStatus(` Skip Learning Cycles: No new conversations to process for learning cycle`);
670
+ // learningCycleEntity.Status = 'Complete';
671
+ // learningCycleEntity.AgentSummary = 'No new conversations to process, learning cycle skipped, but recorded for audit purposes.';
672
+ // learningCycleEntity.EndedAt = new Date();
673
+ // if (!(await learningCycleEntity.Save())) {
674
+ // LogError(`Failed to update learning cycle record: ${learningCycleEntity.LatestResult.Error}`);
675
+ // }
676
+ // const result: SkipAPILearningCycleResponse = {
677
+ // success: true,
678
+ // learningCycleSkipped: true,
679
+ // elapsedTime: 0,
680
+ // noteChanges: [],
681
+ // queryChanges: [],
682
+ // requestChanges: [],
683
+ // }
684
+ // return result;
685
+ // }
686
+ // else {
687
+ // // Make the API request
688
+ // const response = await this.handleSimpleSkipLearningPostRequest(input, user, learningCycleId, agentID, userPayload);
689
+
690
+ // // Update learning cycle to completed
691
+ // const endTime = new Date();
692
+ // const elapsedTimeMs = endTime.getTime() - startTime.getTime();
693
+
694
+ // LogStatus(`Learning cycle finished with status: ${response.success ? 'Success' : 'Failed'} in ${elapsedTimeMs / 1000} seconds`);
695
+
696
+ // learningCycleEntity.Status = response.success ? 'Complete' : 'Failed';
697
+ // learningCycleEntity.EndedAt = endTime;
698
+
699
+ // if (!(await learningCycleEntity.Save())) {
700
+ // LogError(`Failed to update learning cycle record: ${learningCycleEntity.LatestResult.Error}`);
701
+ // }
702
702
 
703
- return response;
704
- }
705
- }
706
- catch (error) {
707
- // Make sure to update the learning cycle record as failed
708
- learningCycleEntity.Status = 'Failed';
709
- learningCycleEntity.EndedAt = new Date();
703
+ // return response;
704
+ // }
705
+ // }
706
+ // catch (error) {
707
+ // // Make sure to update the learning cycle record as failed
708
+ // learningCycleEntity.Status = 'Failed';
709
+ // learningCycleEntity.EndedAt = new Date();
710
710
 
711
- try {
712
- await learningCycleEntity.Save();
713
- }
714
- catch (saveError) {
715
- LogError(`Failed to update learning cycle record after error: ${saveError}`);
716
- }
711
+ // try {
712
+ // await learningCycleEntity.Save();
713
+ // }
714
+ // catch (saveError) {
715
+ // LogError(`Failed to update learning cycle record after error: ${saveError}`);
716
+ // }
717
717
 
718
- // Re-throw the original error
719
- throw error;
720
- }
721
- finally {
722
- // Unregister the cycle/organizationId safely
723
- try {
724
- scheduler.unregisterRunningCycle(organizationId);
725
- }
726
- catch (error) {
727
- LogError(`Failed to unregister organization ${organizationId} from running cycles: ${error}`);
728
- }
729
- }
730
- }
731
-
732
- /**
733
- * Handles the HTTP POST request to the Skip learning cycle API
734
- * Sends the learning cycle request and processes the response
735
- *
736
- * @param input The learning cycle request payload
737
- * @param user User context for the request
738
- * @param learningCycleId ID of the current learning cycle
739
- * @param agentID ID of the Skip agent
740
- * @returns Response from the Skip learning cycle API
741
- */
742
- protected async handleSimpleSkipLearningPostRequest(
743
- input: SkipAPILearningCycleRequest,
744
- user: UserInfo,
745
- learningCycleId: string,
746
- agentID: string,
747
- userPayload: UserPayload
748
- ): Promise<SkipAPILearningCycleResponse> {
749
- const skipConfigInfo = configInfo.askSkip;
750
- const learningURL = skipConfigInfo.url ? `${skipConfigInfo.url}${SKIP_API_ENDPOINTS.LEARNING}` : skipConfigInfo.learningCycleURL;
751
- LogStatus(` >>> HandleSimpleSkipLearningPostRequest Sending request to Skip API: ${learningURL}`);
752
-
753
- const response = await sendPostRequest(learningURL, input, true, this.buildSkipPostHeaders());
754
-
755
- if (response && response.length > 0) {
756
- // the last object in the response array is the final response from the Skip API
757
- const apiResponse = <SkipAPILearningCycleResponse>response[response.length - 1].value;
758
- LogStatus(` Skip API response: ${apiResponse.success}`);
759
-
760
- // Process any note changes, if any
761
- if (apiResponse.noteChanges && apiResponse.noteChanges.length > 0) {
762
- await this.processLearningCycleNoteChanges(apiResponse.noteChanges, agentID, user, userPayload);
763
- }
764
-
765
- // Not yet implemented
766
-
767
- // // Process any query changes, if any
768
- // if (apiResponse.queryChanges && apiResponse.queryChanges.length > 0) {
769
- // await this.processLearningCycleQueryChanges(apiResponse.queryChanges, user);
770
- // }
771
-
772
- // // Process any request changes, if any
773
- // if (apiResponse.requestChanges && apiResponse.requestChanges.length > 0) {
774
- // await this.processLearningCycleRequestChanges(apiResponse.requestChanges, user);
775
- // }
718
+ // // Re-throw the original error
719
+ // throw error;
720
+ // }
721
+ // finally {
722
+ // // Unregister the cycle/organizationId safely
723
+ // try {
724
+ // scheduler.unregisterRunningCycle(organizationId);
725
+ // }
726
+ // catch (error) {
727
+ // LogError(`Failed to unregister organization ${organizationId} from running cycles: ${error}`);
728
+ // }
729
+ // }
730
+ // }
731
+
732
+ // /**
733
+ // * Handles the HTTP POST request to the Skip learning cycle API
734
+ // * Sends the learning cycle request and processes the response
735
+ // *
736
+ // * @param input The learning cycle request payload
737
+ // * @param user User context for the request
738
+ // * @param learningCycleId ID of the current learning cycle
739
+ // * @param agentID ID of the Skip agent
740
+ // * @returns Response from the Skip learning cycle API
741
+ // */
742
+ // protected async handleSimpleSkipLearningPostRequest(
743
+ // input: SkipAPILearningCycleRequest,
744
+ // user: UserInfo,
745
+ // learningCycleId: string,
746
+ // agentID: string,
747
+ // userPayload: UserPayload
748
+ // ): Promise<SkipAPILearningCycleResponse> {
749
+ // const skipConfigInfo = configInfo.askSkip;
750
+ // const learningURL = skipConfigInfo.url ? `${skipConfigInfo.url}${SKIP_API_ENDPOINTS.LEARNING}` : skipConfigInfo.learningCycleURL;
751
+ // LogStatus(` >>> HandleSimpleSkipLearningPostRequest Sending request to Skip API: ${learningURL}`);
752
+
753
+ // const response = await sendPostRequest(learningURL, input, true, this.buildSkipPostHeaders());
754
+
755
+ // if (response && response.length > 0) {
756
+ // // the last object in the response array is the final response from the Skip API
757
+ // const apiResponse = <SkipAPILearningCycleResponse>response[response.length - 1].value;
758
+ // LogStatus(` Skip API response: ${apiResponse.success}`);
759
+
760
+ // // Process any note changes, if any
761
+ // if (apiResponse.noteChanges && apiResponse.noteChanges.length > 0) {
762
+ // await this.processLearningCycleNoteChanges(apiResponse.noteChanges, agentID, user, userPayload);
763
+ // }
764
+
765
+ // // Not yet implemented
766
+
767
+ // // // Process any query changes, if any
768
+ // // if (apiResponse.queryChanges && apiResponse.queryChanges.length > 0) {
769
+ // // await this.processLearningCycleQueryChanges(apiResponse.queryChanges, user);
770
+ // // }
771
+
772
+ // // // Process any request changes, if any
773
+ // // if (apiResponse.requestChanges && apiResponse.requestChanges.length > 0) {
774
+ // // await this.processLearningCycleRequestChanges(apiResponse.requestChanges, user);
775
+ // // }
776
776
 
777
- return apiResponse;
778
- } else {
779
- return {
780
- success: false,
781
- error: 'Error',
782
- elapsedTime: 0,
783
- noteChanges: [],
784
- queryChanges: [],
785
- requestChanges: [],
786
- };
787
-
788
- }
789
- }
777
+ // return apiResponse;
778
+ // } else {
779
+ // return {
780
+ // success: false,
781
+ // error: 'Error',
782
+ // elapsedTime: 0,
783
+ // noteChanges: [],
784
+ // queryChanges: [],
785
+ // requestChanges: [],
786
+ // };
787
+
788
+ // }
789
+ // }
790
790
 
791
791
  /**
792
792
  * Handles the HTTP POST request to the Skip chat API
@@ -861,132 +861,132 @@ export class AskSkipResolver {
861
861
  }
862
862
  }
863
863
 
864
- /**
865
- * Processes note changes received from the Skip API learning cycle
866
- * Applies changes to agent notes based on the learning cycle response
867
- *
868
- * @param noteChanges Changes to agent notes
869
- * @param agentID ID of the Skip agent
870
- * @param user User context for the request
871
- * @returns Promise that resolves when processing is complete
872
- */
873
- protected async processLearningCycleNoteChanges(
874
- noteChanges: SkipLearningCycleNoteChange[],
875
- agentID: string,
876
- user: UserInfo,
877
- userPayload: UserPayload
878
- ): Promise<void> {
879
- const md = new Metadata();
880
-
881
- // Filter out any operations on "Human" notes
882
- const validNoteChanges = noteChanges.filter(change => {
883
- // Check if the note is of type "Human"
884
- if (change.note.agentNoteType === "Human") {
885
- LogStatus(`WARNING: Ignoring ${change.changeType} operation on Human note with ID ${change.note.id}. Human notes cannot be modified by the
886
- learning cycle.`);
887
- return false;
888
- }
889
- return true;
890
- });
864
+ // /**
865
+ // * Processes note changes received from the Skip API learning cycle
866
+ // * Applies changes to agent notes based on the learning cycle response
867
+ // *
868
+ // * @param noteChanges Changes to agent notes
869
+ // * @param agentID ID of the Skip agent
870
+ // * @param user User context for the request
871
+ // * @returns Promise that resolves when processing is complete
872
+ // */
873
+ // protected async processLearningCycleNoteChanges(
874
+ // noteChanges: SkipLearningCycleNoteChange[],
875
+ // agentID: string,
876
+ // user: UserInfo,
877
+ // userPayload: UserPayload
878
+ // ): Promise<void> {
879
+ // const md = new Metadata();
880
+
881
+ // // Filter out any operations on "Human" notes
882
+ // const validNoteChanges = noteChanges.filter(change => {
883
+ // // Check if the note is of type "Human"
884
+ // if (change.note.agentNoteType === "Human") {
885
+ // LogStatus(`WARNING: Ignoring ${change.changeType} operation on Human note with ID ${change.note.id}. Human notes cannot be modified by the
886
+ // learning cycle.`);
887
+ // return false;
888
+ // }
889
+ // return true;
890
+ // });
891
891
 
892
- // Process all valid note changes in parallel
893
- await Promise.all(validNoteChanges.map(async (change) => {
894
- try {
895
- if (change.changeType === 'add' || change.changeType === 'update') {
896
- await this.processAddOrUpdateSkipNote(change, agentID, user, userPayload);
897
- } else if (change.changeType === 'delete') {
898
- await this.processDeleteSkipNote(change, user, userPayload);
899
- }
900
- } catch (e) {
901
- LogError(`Error processing note change: ${e}`);
902
- }
903
- }));
904
- }
905
-
906
- /**
907
- * Processes an add or update operation for a Skip agent note
908
- * Creates a new note or updates an existing one based on the change type
909
- *
910
- * @param change The note change information
911
- * @param agentID ID of the Skip agent
912
- * @param user User context for the operation
913
- * @returns Whether the operation was successful
914
- */
915
- protected async processAddOrUpdateSkipNote(change: SkipLearningCycleNoteChange, agentID: string, user: UserInfo, userPayload: UserPayload): Promise<boolean> {
916
- try {
917
- // Get the note entity object
918
- const md = new Metadata();
919
- const noteEntity = await md.GetEntityObject<AIAgentNoteEntity>('AI Agent Notes', user);
892
+ // // Process all valid note changes in parallel
893
+ // await Promise.all(validNoteChanges.map(async (change) => {
894
+ // try {
895
+ // if (change.changeType === 'add' || change.changeType === 'update') {
896
+ // await this.processAddOrUpdateSkipNote(change, agentID, user, userPayload);
897
+ // } else if (change.changeType === 'delete') {
898
+ // await this.processDeleteSkipNote(change, user, userPayload);
899
+ // }
900
+ // } catch (e) {
901
+ // LogError(`Error processing note change: ${e}`);
902
+ // }
903
+ // }));
904
+ // }
905
+
906
+ // /**
907
+ // * Processes an add or update operation for a Skip agent note
908
+ // * Creates a new note or updates an existing one based on the change type
909
+ // *
910
+ // * @param change The note change information
911
+ // * @param agentID ID of the Skip agent
912
+ // * @param user User context for the operation
913
+ // * @returns Whether the operation was successful
914
+ // */
915
+ // protected async processAddOrUpdateSkipNote(change: SkipLearningCycleNoteChange, agentID: string, user: UserInfo, userPayload: UserPayload): Promise<boolean> {
916
+ // try {
917
+ // // Get the note entity object
918
+ // const md = new Metadata();
919
+ // const noteEntity = await md.GetEntityObject<AIAgentNoteEntity>('AI Agent Notes', user);
920
920
 
921
- if (change.changeType === 'update') {
922
- // Load existing note
923
- const loadResult = await noteEntity.Load(change.note.id);
924
- if (!loadResult) {
925
- LogError(`Could not load note with ID ${change.note.id}`);
926
- return false;
927
- }
928
- } else {
929
- // Create a new note
930
- noteEntity.NewRecord();
931
- noteEntity.AgentID = agentID;
932
- }
933
- noteEntity.AgentNoteTypeID = this.getAgentNoteTypeIDByName('AI'); // always set to AI
934
- noteEntity.Note = change.note.note;
935
- noteEntity.Type = change.note.type;
936
-
937
- if (change.note.type === 'User') {
938
- noteEntity.UserID = change.note.userId;
939
- }
940
-
941
- // Save the note
942
- if (!(await noteEntity.Save())) {
943
- LogError(`Error saving AI Agent Note: ${noteEntity.LatestResult.Error}`);
944
- return false;
945
- }
946
-
947
- return true;
948
- } catch (e) {
949
- LogError(`Error processing note change: ${e}`);
950
- return false;
951
- }
952
- }
953
-
954
- /**
955
- * Processes a delete operation for a Skip agent note
956
- * Removes the specified note from the database
957
- *
958
- * @param change The note change information
959
- * @param user User context for the operation
960
- * @returns Whether the deletion was successful
961
- */
962
- protected async processDeleteSkipNote(change: SkipLearningCycleNoteChange, user: UserInfo, userPayload: UserPayload): Promise<boolean> {
963
- // Get the note entity object
964
- const md = new Metadata();
965
- const noteEntity = await md.GetEntityObject<AIAgentNoteEntity>('AI Agent Notes', user);
966
-
967
- // Load the note first
968
- const loadResult = await noteEntity.Load(change.note.id);
969
-
970
- if (!loadResult) {
971
- LogError(`Could not load note with ID ${change.note.id} for deletion`);
972
- return false;
973
- }
974
-
975
- // Double-check if the loaded note is of type "Human"
976
- if (change.note.agentNoteType === "Human") {
977
- LogStatus(`WARNING: Ignoring delete operation on Human note with ID ${change.note.id}. Human notes cannot be deleted by the learning
978
- cycle.`);
979
- return false;
980
- }
981
-
982
- // Proceed with deletion
983
- if (!(await noteEntity.Delete())) {
984
- LogError(`Error deleting AI Agent Note: ${noteEntity.LatestResult.Error}`);
985
- return false;
986
- }
987
-
988
- return true;
989
- }
921
+ // if (change.changeType === 'update') {
922
+ // // Load existing note
923
+ // const loadResult = await noteEntity.Load(change.note.id);
924
+ // if (!loadResult) {
925
+ // LogError(`Could not load note with ID ${change.note.id}`);
926
+ // return false;
927
+ // }
928
+ // } else {
929
+ // // Create a new note
930
+ // noteEntity.NewRecord();
931
+ // noteEntity.AgentID = agentID;
932
+ // }
933
+ // noteEntity.AgentNoteTypeID = this.getAgentNoteTypeIDByName('AI'); // always set to AI
934
+ // noteEntity.Note = change.note.note;
935
+ // noteEntity.Type = change.note.type;
936
+
937
+ // if (change.note.type === 'User') {
938
+ // noteEntity.UserID = change.note.userId;
939
+ // }
940
+
941
+ // // Save the note
942
+ // if (!(await noteEntity.Save())) {
943
+ // LogError(`Error saving AI Agent Note: ${noteEntity.LatestResult.Error}`);
944
+ // return false;
945
+ // }
946
+
947
+ // return true;
948
+ // } catch (e) {
949
+ // LogError(`Error processing note change: ${e}`);
950
+ // return false;
951
+ // }
952
+ // }
953
+
954
+ // /**
955
+ // * Processes a delete operation for a Skip agent note
956
+ // * Removes the specified note from the database
957
+ // *
958
+ // * @param change The note change information
959
+ // * @param user User context for the operation
960
+ // * @returns Whether the deletion was successful
961
+ // */
962
+ // protected async processDeleteSkipNote(change: SkipLearningCycleNoteChange, user: UserInfo, userPayload: UserPayload): Promise<boolean> {
963
+ // // Get the note entity object
964
+ // const md = new Metadata();
965
+ // const noteEntity = await md.GetEntityObject<AIAgentNoteEntity>('AI Agent Notes', user);
966
+
967
+ // // Load the note first
968
+ // const loadResult = await noteEntity.Load(change.note.id);
969
+
970
+ // if (!loadResult) {
971
+ // LogError(`Could not load note with ID ${change.note.id} for deletion`);
972
+ // return false;
973
+ // }
974
+
975
+ // // Double-check if the loaded note is of type "Human"
976
+ // if (change.note.agentNoteType === "Human") {
977
+ // LogStatus(`WARNING: Ignoring delete operation on Human note with ID ${change.note.id}. Human notes cannot be deleted by the learning
978
+ // cycle.`);
979
+ // return false;
980
+ // }
981
+
982
+ // // Proceed with deletion
983
+ // if (!(await noteEntity.Delete())) {
984
+ // LogError(`Error deleting AI Agent Note: ${noteEntity.LatestResult.Error}`);
985
+ // return false;
986
+ // }
987
+
988
+ // return true;
989
+ // }
990
990
 
991
991
  /**
992
992
  * Creates a conversation detail entry for an AI message
@@ -1050,7 +1050,7 @@ cycle.`);
1050
1050
  const skipConfigInfo = configInfo.askSkip;
1051
1051
  const entities = includeEntities ? await this.BuildSkipEntities(dataSource, forceEntitiesRefresh) : [];
1052
1052
  const queries = includeQueries ? this.BuildSkipQueries() : [];
1053
- const {notes, noteTypes} = includeNotes ? await this.BuildSkipAgentNotes(contextUser, filterUserNotesToContextUser) : {notes: [], noteTypes: []};
1053
+ //const {notes, noteTypes} = includeNotes ? await this.BuildSkipAgentNotes(contextUser, filterUserNotesToContextUser) : {notes: [], noteTypes: []};
1054
1054
  const requests = includeRequests ? await this.BuildSkipRequests(contextUser) : [];
1055
1055
 
1056
1056
  // Setup access token if needed
@@ -1074,8 +1074,8 @@ cycle.`);
1074
1074
  return {
1075
1075
  entities,
1076
1076
  queries,
1077
- notes,
1078
- noteTypes,
1077
+ notes: undefined,
1078
+ noteTypes: undefined,
1079
1079
  userEmail: contextUser.Email,
1080
1080
  requests,
1081
1081
  accessToken,
@@ -1748,64 +1748,64 @@ cycle.`);
1748
1748
  });
1749
1749
  }
1750
1750
 
1751
- /**
1752
- * Builds up the array of notes and note types for Skip
1753
- * These notes are used to provide Skip with domain knowledge and context
1754
- *
1755
- * @param contextUser User context for the request
1756
- * @returns Object containing arrays of notes and note types
1757
- */
1758
- protected async BuildSkipAgentNotes(contextUser: UserInfo, filterUserNotesToContextUser: boolean): Promise<{notes: SkipAPIAgentNote[], noteTypes: SkipAPIAgentNoteType[]}> {
1759
- try {
1760
- // if already configured this does nothing, just makes sure we're configured
1761
- await AIEngine.Instance.Config(false, contextUser);
1762
-
1763
- const agent: AIAgentEntityExtended = AIEngine.Instance.GetAgentByName('Skip');
1764
- if (agent) {
1765
- let notes: SkipAPIAgentNote[] = [];
1766
- let noteTypes: SkipAPIAgentNoteType[] = [];
1751
+ // /**
1752
+ // * Builds up the array of notes and note types for Skip
1753
+ // * These notes are used to provide Skip with domain knowledge and context
1754
+ // *
1755
+ // * @param contextUser User context for the request
1756
+ // * @returns Object containing arrays of notes and note types
1757
+ // */
1758
+ // protected async BuildSkipAgentNotes(contextUser: UserInfo, filterUserNotesToContextUser: boolean): Promise<{notes: SkipAPIAgentNote[], noteTypes: SkipAPIAgentNoteType[]}> {
1759
+ // try {
1760
+ // // if already configured this does nothing, just makes sure we're configured
1761
+ // await AIEngine.Instance.Config(false, contextUser);
1762
+
1763
+ // const agent: AIAgentEntityExtended = AIEngine.Instance.GetAgentByName('Skip');
1764
+ // if (agent) {
1765
+ // let notes: SkipAPIAgentNote[] = [];
1766
+ // let noteTypes: SkipAPIAgentNoteType[] = [];
1767
1767
 
1768
- notes = agent.Notes.map((r) => {
1769
- return {
1770
- id: r.ID,
1771
- agentNoteTypeId: r.AgentNoteTypeID,
1772
- agentNoteType: r.AgentNoteType,
1773
- note: r.Note,
1774
- type: r.Type,
1775
- userId: r.UserID,
1776
- user: r.User,
1777
- createdAt: r.__mj_CreatedAt,
1778
- updatedAt: r.__mj_UpdatedAt,
1779
- }
1780
- });
1781
-
1782
- if (filterUserNotesToContextUser){
1783
- // filter out any notes that are not for this user
1784
- notes = notes.filter((n) => n.type === 'Global' ||
1785
- (n.type === 'User' && n.userId === contextUser.ID));
1786
- }
1787
-
1788
- noteTypes = AIEngine.Instance.AgentNoteTypes.map((r) => {
1789
- return {
1790
- id: r.ID,
1791
- name: r.Name,
1792
- description: r.Description
1793
- }
1794
- });
1795
-
1796
- // now return the notes and note types
1797
- return {notes, noteTypes};
1798
- }
1799
- else {
1800
- console.warn(`No AI Agent found with the name 'Skip' in the AI Engine, so no notes will be sent to Skip`);
1801
- return {notes: [], noteTypes: []}; // no agent found, so nothing to do
1802
- }
1803
- }
1804
- catch (e) {
1805
- LogError(`AskSkipResolver::BuildSkipAgentNotes: ${e}`);
1806
- return {notes: [], noteTypes: []}; // non- fatal error just return empty arrays
1807
- }
1808
- }
1768
+ // notes = agent.Notes.map((r) => {
1769
+ // return {
1770
+ // id: r.ID,
1771
+ // agentNoteTypeId: r.AgentNoteTypeID,
1772
+ // agentNoteType: r.AgentNoteType,
1773
+ // note: r.Note,
1774
+ // type: r.Type,
1775
+ // userId: r.UserID,
1776
+ // user: r.User,
1777
+ // createdAt: r.__mj_CreatedAt,
1778
+ // updatedAt: r.__mj_UpdatedAt,
1779
+ // }
1780
+ // });
1781
+
1782
+ // if (filterUserNotesToContextUser){
1783
+ // // filter out any notes that are not for this user
1784
+ // notes = notes.filter((n) => n.type === 'Global' ||
1785
+ // (n.type === 'User' && n.userId === contextUser.ID));
1786
+ // }
1787
+
1788
+ // noteTypes = AIEngine.Instance.AgentNoteTypes.map((r) => {
1789
+ // return {
1790
+ // id: r.ID,
1791
+ // name: r.Name,
1792
+ // description: r.Description
1793
+ // }
1794
+ // });
1795
+
1796
+ // // now return the notes and note types
1797
+ // return {notes, noteTypes};
1798
+ // }
1799
+ // else {
1800
+ // console.warn(`No AI Agent found with the name 'Skip' in the AI Engine, so no notes will be sent to Skip`);
1801
+ // return {notes: [], noteTypes: []}; // no agent found, so nothing to do
1802
+ // }
1803
+ // }
1804
+ // catch (e) {
1805
+ // LogError(`AskSkipResolver::BuildSkipAgentNotes: ${e}`);
1806
+ // return {notes: [], noteTypes: []}; // non- fatal error just return empty arrays
1807
+ // }
1808
+ // }
1809
1809
 
1810
1810
  /**
1811
1811
  * Packs entity rows for inclusion in Skip requests
@@ -3257,166 +3257,166 @@ cycle.`);
3257
3257
  else throw new Error(`Error running view ${ViewId}`);
3258
3258
  }
3259
3259
 
3260
- /**
3261
- * Manually executes the Skip AI learning cycle
3262
- * Allows triggering a learning cycle on demand rather than waiting for scheduled execution
3263
- *
3264
- * @param OrganizationId Optional organization ID to register for this run
3265
- * @returns Result of the manual learning cycle execution
3266
- */
3267
- @Mutation(() => ManualLearningCycleResultType)
3268
- async ManuallyExecuteSkipLearningCycle(
3269
- @Arg('OrganizationId', () => String, { nullable: true }) OrganizationId?: string
3270
- ): Promise<ManualLearningCycleResultType> {
3271
- try {
3272
- LogStatus('Manual execution of Skip learning cycle requested via API');
3273
- const skipConfigInfo = configInfo.askSkip;
3274
- // First check if learning cycles are enabled in configuration
3275
- if (!skipConfigInfo.learningCycleEnabled) {
3276
- return {
3277
- Success: false,
3278
- Message: 'Learning cycles are not enabled in configuration'
3279
- };
3280
- }
3260
+ // /**
3261
+ // * Manually executes the Skip AI learning cycle
3262
+ // * Allows triggering a learning cycle on demand rather than waiting for scheduled execution
3263
+ // *
3264
+ // * @param OrganizationId Optional organization ID to register for this run
3265
+ // * @returns Result of the manual learning cycle execution
3266
+ // */
3267
+ // @Mutation(() => ManualLearningCycleResultType)
3268
+ // async ManuallyExecuteSkipLearningCycle(
3269
+ // @Arg('OrganizationId', () => String, { nullable: true }) OrganizationId?: string
3270
+ // ): Promise<ManualLearningCycleResultType> {
3271
+ // try {
3272
+ // LogStatus('Manual execution of Skip learning cycle requested via API');
3273
+ // const skipConfigInfo = configInfo.askSkip;
3274
+ // // First check if learning cycles are enabled in configuration
3275
+ // if (!skipConfigInfo.learningCycleEnabled) {
3276
+ // return {
3277
+ // Success: false,
3278
+ // Message: 'Learning cycles are not enabled in configuration'
3279
+ // };
3280
+ // }
3281
3281
 
3282
- // Check if we have a valid endpoint when cycles are enabled
3283
- const hasLearningEndpoint = (skipConfigInfo.url && skipConfigInfo.url.trim().length > 0) ||
3284
- (skipConfigInfo.learningCycleURL && skipConfigInfo.learningCycleURL.trim().length > 0);
3285
- if (!hasLearningEndpoint) {
3286
- return {
3287
- Success: false,
3288
- Message: 'Learning cycle API endpoint is not configured'
3289
- };
3290
- }
3282
+ // // Check if we have a valid endpoint when cycles are enabled
3283
+ // const hasLearningEndpoint = (skipConfigInfo.url && skipConfigInfo.url.trim().length > 0) ||
3284
+ // (skipConfigInfo.learningCycleURL && skipConfigInfo.learningCycleURL.trim().length > 0);
3285
+ // if (!hasLearningEndpoint) {
3286
+ // return {
3287
+ // Success: false,
3288
+ // Message: 'Learning cycle API endpoint is not configured'
3289
+ // };
3290
+ // }
3291
3291
 
3292
- // Use the organization ID from config if not provided
3293
- const orgId = OrganizationId || skipConfigInfo.orgID;
3292
+ // // Use the organization ID from config if not provided
3293
+ // const orgId = OrganizationId || skipConfigInfo.orgID;
3294
3294
 
3295
- // Call the scheduler's manual execution method with org ID
3296
- const result = await LearningCycleScheduler.Instance.manuallyExecuteLearningCycle(orgId);
3295
+ // // Call the scheduler's manual execution method with org ID
3296
+ // const result = await LearningCycleScheduler.Instance.manuallyExecuteLearningCycle(orgId);
3297
3297
 
3298
- return {
3299
- Success: result,
3300
- Message: result
3301
- ? `Learning cycle was successfully executed manually for organization ${orgId}`
3302
- : `Learning cycle execution failed for organization ${orgId}. Check server logs for details.`
3303
- };
3304
- }
3305
- catch (e) {
3306
- LogError(`Error in ManuallyExecuteSkipLearningCycle: ${e}`);
3307
- return {
3308
- Success: false,
3309
- Message: `Error executing learning cycle: ${e}`
3310
- };
3311
- }
3312
- }
3298
+ // return {
3299
+ // Success: result,
3300
+ // Message: result
3301
+ // ? `Learning cycle was successfully executed manually for organization ${orgId}`
3302
+ // : `Learning cycle execution failed for organization ${orgId}. Check server logs for details.`
3303
+ // };
3304
+ // }
3305
+ // catch (e) {
3306
+ // LogError(`Error in ManuallyExecuteSkipLearningCycle: ${e}`);
3307
+ // return {
3308
+ // Success: false,
3309
+ // Message: `Error executing learning cycle: ${e}`
3310
+ // };
3311
+ // }
3312
+ // }
3313
3313
 
3314
- /**
3315
- * Gets the current status of the learning cycle scheduler
3316
- * Provides information about the scheduler state and any running cycles
3317
- *
3318
- * @returns Status information about the learning cycle scheduler
3319
- */
3320
- @Query(() => LearningCycleStatusType)
3321
- async GetLearningCycleStatus(): Promise<LearningCycleStatusType> {
3322
- try {
3323
- const status = LearningCycleScheduler.Instance.getStatus();
3314
+ // /**
3315
+ // * Gets the current status of the learning cycle scheduler
3316
+ // * Provides information about the scheduler state and any running cycles
3317
+ // *
3318
+ // * @returns Status information about the learning cycle scheduler
3319
+ // */
3320
+ // @Query(() => LearningCycleStatusType)
3321
+ // async GetLearningCycleStatus(): Promise<LearningCycleStatusType> {
3322
+ // try {
3323
+ // const status = LearningCycleScheduler.Instance.getStatus();
3324
3324
 
3325
- return {
3326
- IsSchedulerRunning: status.isSchedulerRunning,
3327
- LastRunTime: status.lastRunTime ? status.lastRunTime.toISOString() : null,
3328
- RunningOrganizations: status.runningOrganizations ? status.runningOrganizations.map(org => ({
3329
- OrganizationId: org.organizationId,
3330
- LearningCycleId: org.learningCycleId,
3331
- StartTime: org.startTime.toISOString(),
3332
- RunningForMinutes: org.runningForMinutes
3333
- })) : []
3334
- };
3335
- }
3336
- catch (e) {
3337
- LogError(`Error in GetLearningCycleStatus: ${e}`);
3338
- return {
3339
- IsSchedulerRunning: false,
3340
- LastRunTime: null,
3341
- RunningOrganizations: []
3342
- };
3343
- }
3344
- }
3325
+ // return {
3326
+ // IsSchedulerRunning: status.isSchedulerRunning,
3327
+ // LastRunTime: status.lastRunTime ? status.lastRunTime.toISOString() : null,
3328
+ // RunningOrganizations: status.runningOrganizations ? status.runningOrganizations.map(org => ({
3329
+ // OrganizationId: org.organizationId,
3330
+ // LearningCycleId: org.learningCycleId,
3331
+ // StartTime: org.startTime.toISOString(),
3332
+ // RunningForMinutes: org.runningForMinutes
3333
+ // })) : []
3334
+ // };
3335
+ // }
3336
+ // catch (e) {
3337
+ // LogError(`Error in GetLearningCycleStatus: ${e}`);
3338
+ // return {
3339
+ // IsSchedulerRunning: false,
3340
+ // LastRunTime: null,
3341
+ // RunningOrganizations: []
3342
+ // };
3343
+ // }
3344
+ // }
3345
3345
 
3346
- /**
3347
- * Checks if a specific organization is running a learning cycle
3348
- * Used to determine if a new learning cycle can be started for an organization
3349
- *
3350
- * @param OrganizationId The organization ID to check
3351
- * @returns Information about the running cycle, or null if no cycle is running
3352
- */
3353
- @Query(() => RunningOrganizationType, { nullable: true })
3354
- async IsOrganizationRunningLearningCycle(
3355
- @Arg('OrganizationId', () => String) OrganizationId: string
3356
- ): Promise<RunningOrganizationType | null> {
3357
- try {
3358
- const skipConfigInfo = configInfo.askSkip;
3359
- // Use the organization ID from config if not provided
3360
- const orgId = OrganizationId || skipConfigInfo.orgID;
3346
+ // /**
3347
+ // * Checks if a specific organization is running a learning cycle
3348
+ // * Used to determine if a new learning cycle can be started for an organization
3349
+ // *
3350
+ // * @param OrganizationId The organization ID to check
3351
+ // * @returns Information about the running cycle, or null if no cycle is running
3352
+ // */
3353
+ // @Query(() => RunningOrganizationType, { nullable: true })
3354
+ // async IsOrganizationRunningLearningCycle(
3355
+ // @Arg('OrganizationId', () => String) OrganizationId: string
3356
+ // ): Promise<RunningOrganizationType | null> {
3357
+ // try {
3358
+ // const skipConfigInfo = configInfo.askSkip;
3359
+ // // Use the organization ID from config if not provided
3360
+ // const orgId = OrganizationId || skipConfigInfo.orgID;
3361
3361
 
3362
- const status = LearningCycleScheduler.Instance.isOrganizationRunningCycle(orgId);
3362
+ // const status = LearningCycleScheduler.Instance.isOrganizationRunningCycle(orgId);
3363
3363
 
3364
- if (!status.isRunning) {
3365
- return null;
3366
- }
3364
+ // if (!status.isRunning) {
3365
+ // return null;
3366
+ // }
3367
3367
 
3368
- return {
3369
- OrganizationId: orgId,
3370
- LearningCycleId: status.learningCycleId,
3371
- StartTime: status.startTime.toISOString(),
3372
- RunningForMinutes: status.runningForMinutes
3373
- };
3374
- }
3375
- catch (e) {
3376
- LogError(`Error in IsOrganizationRunningLearningCycle: ${e}`);
3377
- return null;
3378
- }
3379
- }
3368
+ // return {
3369
+ // OrganizationId: orgId,
3370
+ // LearningCycleId: status.learningCycleId,
3371
+ // StartTime: status.startTime.toISOString(),
3372
+ // RunningForMinutes: status.runningForMinutes
3373
+ // };
3374
+ // }
3375
+ // catch (e) {
3376
+ // LogError(`Error in IsOrganizationRunningLearningCycle: ${e}`);
3377
+ // return null;
3378
+ // }
3379
+ // }
3380
3380
 
3381
- /**
3382
- * Stops a running learning cycle for a specific organization
3383
- * Allows manual intervention to stop a learning cycle that is taking too long or causing issues
3384
- *
3385
- * @param OrganizationId The organization ID to stop the cycle for
3386
- * @returns Result of the stop operation, including details about the stopped cycle
3387
- */
3388
- @Mutation(() => StopLearningCycleResultType)
3389
- async StopLearningCycleForOrganization(
3390
- @Arg('OrganizationId', () => String) OrganizationId: string
3391
- ): Promise<StopLearningCycleResultType> {
3392
- try {
3393
- // Use the organization ID from config if not provided
3394
- const orgId = OrganizationId || configInfo.askSkip.orgID;
3381
+ // /**
3382
+ // * Stops a running learning cycle for a specific organization
3383
+ // * Allows manual intervention to stop a learning cycle that is taking too long or causing issues
3384
+ // *
3385
+ // * @param OrganizationId The organization ID to stop the cycle for
3386
+ // * @returns Result of the stop operation, including details about the stopped cycle
3387
+ // */
3388
+ // @Mutation(() => StopLearningCycleResultType)
3389
+ // async StopLearningCycleForOrganization(
3390
+ // @Arg('OrganizationId', () => String) OrganizationId: string
3391
+ // ): Promise<StopLearningCycleResultType> {
3392
+ // try {
3393
+ // // Use the organization ID from config if not provided
3394
+ // const orgId = OrganizationId || configInfo.askSkip.orgID;
3395
3395
 
3396
- const result = LearningCycleScheduler.Instance.stopLearningCycleForOrganization(orgId);
3396
+ // const result = LearningCycleScheduler.Instance.stopLearningCycleForOrganization(orgId);
3397
3397
 
3398
- // Transform the result to match our GraphQL type
3399
- return {
3400
- Success: result.success,
3401
- Message: result.message,
3402
- WasRunning: result.wasRunning,
3403
- CycleDetails: result.cycleDetails ? {
3404
- LearningCycleId: result.cycleDetails.learningCycleId,
3405
- StartTime: result.cycleDetails.startTime.toISOString(),
3406
- RunningForMinutes: result.cycleDetails.runningForMinutes
3407
- } : null
3408
- };
3409
- }
3410
- catch (e) {
3411
- LogError(`Error in StopLearningCycleForOrganization: ${e}`);
3412
- return {
3413
- Success: false,
3414
- Message: `Error stopping learning cycle: ${e}`,
3415
- WasRunning: false,
3416
- CycleDetails: null
3417
- };
3418
- }
3419
- }
3398
+ // // Transform the result to match our GraphQL type
3399
+ // return {
3400
+ // Success: result.success,
3401
+ // Message: result.message,
3402
+ // WasRunning: result.wasRunning,
3403
+ // CycleDetails: result.cycleDetails ? {
3404
+ // LearningCycleId: result.cycleDetails.learningCycleId,
3405
+ // StartTime: result.cycleDetails.startTime.toISOString(),
3406
+ // RunningForMinutes: result.cycleDetails.runningForMinutes
3407
+ // } : null
3408
+ // };
3409
+ // }
3410
+ // catch (e) {
3411
+ // LogError(`Error in StopLearningCycleForOrganization: ${e}`);
3412
+ // return {
3413
+ // Success: false,
3414
+ // Message: `Error stopping learning cycle: ${e}`,
3415
+ // WasRunning: false,
3416
+ // CycleDetails: null
3417
+ // };
3418
+ // }
3419
+ // }
3420
3420
 
3421
3421
  }
3422
3422