@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.
- package/dist/agents/skip-sdk.d.ts.map +1 -1
- package/dist/agents/skip-sdk.js +80 -72
- package/dist/agents/skip-sdk.js.map +1 -1
- package/dist/generated/generated.d.ts +160 -11
- package/dist/generated/generated.d.ts.map +1 -1
- package/dist/generated/generated.js +1015 -70
- package/dist/generated/generated.js.map +1 -1
- package/dist/resolvers/AskSkipResolver.d.ts +1 -14
- package/dist/resolvers/AskSkipResolver.d.ts.map +1 -1
- package/dist/resolvers/AskSkipResolver.js +3 -452
- package/dist/resolvers/AskSkipResolver.js.map +1 -1
- package/dist/scheduler/LearningCycleScheduler.d.ts +0 -40
- package/dist/scheduler/LearningCycleScheduler.d.ts.map +1 -1
- package/dist/scheduler/LearningCycleScheduler.js +0 -192
- package/dist/scheduler/LearningCycleScheduler.js.map +1 -1
- package/package.json +43 -38
- package/src/agents/skip-sdk.ts +102 -89
- package/src/generated/generated.ts +642 -54
- package/src/resolvers/AskSkipResolver.ts +612 -612
- package/src/scheduler/LearningCycleScheduler.ts +261 -261
|
@@ -358,77 +358,77 @@ export class StopLearningCycleResultType {
|
|
|
358
358
|
CycleDetails: CycleDetailsType;
|
|
359
359
|
}
|
|
360
360
|
|
|
361
|
-
/**
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
function initializeSkipLearningCycleScheduler() {
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
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
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
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
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
391
|
+
// const dataSources = event.args.dataSources;
|
|
392
|
+
// if (dataSources && dataSources.length > 0) {
|
|
393
|
+
// // Initialize the scheduler
|
|
394
|
+
// const scheduler = LearningCycleScheduler.Instance;
|
|
395
395
|
|
|
396
|
-
|
|
397
|
-
|
|
396
|
+
// // Set the data sources for the scheduler
|
|
397
|
+
// scheduler.setDataSources(dataSources);
|
|
398
398
|
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
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
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
@Mutation(() => AskSkipResultType)
|
|
578
|
-
async ExecuteAskSkipLearningCycle(
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
) {
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
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
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
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
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
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
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
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
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
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
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
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
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
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
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
}
|
|
731
|
-
|
|
732
|
-
/**
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
protected async handleSimpleSkipLearningPostRequest(
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
): Promise<SkipAPILearningCycleResponse> {
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
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
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
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
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
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
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
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
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
cycle.`);
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
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
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
protected async BuildSkipAgentNotes(contextUser: UserInfo, filterUserNotesToContextUser: boolean): Promise<{notes: SkipAPIAgentNote[], noteTypes: SkipAPIAgentNoteType[]}> {
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
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
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
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
|
-
|
|
3262
|
-
|
|
3263
|
-
|
|
3264
|
-
|
|
3265
|
-
|
|
3266
|
-
|
|
3267
|
-
@Mutation(() => ManualLearningCycleResultType)
|
|
3268
|
-
async ManuallyExecuteSkipLearningCycle(
|
|
3269
|
-
|
|
3270
|
-
): Promise<ManualLearningCycleResultType> {
|
|
3271
|
-
|
|
3272
|
-
|
|
3273
|
-
|
|
3274
|
-
|
|
3275
|
-
|
|
3276
|
-
|
|
3277
|
-
|
|
3278
|
-
|
|
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
|
-
|
|
3283
|
-
|
|
3284
|
-
|
|
3285
|
-
|
|
3286
|
-
|
|
3287
|
-
|
|
3288
|
-
|
|
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
|
-
|
|
3293
|
-
|
|
3292
|
+
// // Use the organization ID from config if not provided
|
|
3293
|
+
// const orgId = OrganizationId || skipConfigInfo.orgID;
|
|
3294
3294
|
|
|
3295
|
-
|
|
3296
|
-
|
|
3295
|
+
// // Call the scheduler's manual execution method with org ID
|
|
3296
|
+
// const result = await LearningCycleScheduler.Instance.manuallyExecuteLearningCycle(orgId);
|
|
3297
3297
|
|
|
3298
|
-
|
|
3299
|
-
|
|
3300
|
-
|
|
3301
|
-
|
|
3302
|
-
|
|
3303
|
-
|
|
3304
|
-
|
|
3305
|
-
|
|
3306
|
-
|
|
3307
|
-
|
|
3308
|
-
|
|
3309
|
-
|
|
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
|
-
|
|
3316
|
-
|
|
3317
|
-
|
|
3318
|
-
|
|
3319
|
-
|
|
3320
|
-
@Query(() => LearningCycleStatusType)
|
|
3321
|
-
async GetLearningCycleStatus(): Promise<LearningCycleStatusType> {
|
|
3322
|
-
|
|
3323
|
-
|
|
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
|
-
|
|
3326
|
-
|
|
3327
|
-
|
|
3328
|
-
|
|
3329
|
-
|
|
3330
|
-
|
|
3331
|
-
|
|
3332
|
-
|
|
3333
|
-
|
|
3334
|
-
|
|
3335
|
-
|
|
3336
|
-
|
|
3337
|
-
|
|
3338
|
-
|
|
3339
|
-
|
|
3340
|
-
|
|
3341
|
-
|
|
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
|
-
|
|
3348
|
-
|
|
3349
|
-
|
|
3350
|
-
|
|
3351
|
-
|
|
3352
|
-
|
|
3353
|
-
@Query(() => RunningOrganizationType, { nullable: true })
|
|
3354
|
-
async IsOrganizationRunningLearningCycle(
|
|
3355
|
-
|
|
3356
|
-
): Promise<RunningOrganizationType | null> {
|
|
3357
|
-
|
|
3358
|
-
|
|
3359
|
-
|
|
3360
|
-
|
|
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
|
-
|
|
3362
|
+
// const status = LearningCycleScheduler.Instance.isOrganizationRunningCycle(orgId);
|
|
3363
3363
|
|
|
3364
|
-
|
|
3365
|
-
|
|
3366
|
-
|
|
3364
|
+
// if (!status.isRunning) {
|
|
3365
|
+
// return null;
|
|
3366
|
+
// }
|
|
3367
3367
|
|
|
3368
|
-
|
|
3369
|
-
|
|
3370
|
-
|
|
3371
|
-
|
|
3372
|
-
|
|
3373
|
-
|
|
3374
|
-
|
|
3375
|
-
|
|
3376
|
-
|
|
3377
|
-
|
|
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
|
-
|
|
3383
|
-
|
|
3384
|
-
|
|
3385
|
-
|
|
3386
|
-
|
|
3387
|
-
|
|
3388
|
-
@Mutation(() => StopLearningCycleResultType)
|
|
3389
|
-
async StopLearningCycleForOrganization(
|
|
3390
|
-
|
|
3391
|
-
): Promise<StopLearningCycleResultType> {
|
|
3392
|
-
|
|
3393
|
-
|
|
3394
|
-
|
|
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
|
-
|
|
3396
|
+
// const result = LearningCycleScheduler.Instance.stopLearningCycleForOrganization(orgId);
|
|
3397
3397
|
|
|
3398
|
-
|
|
3399
|
-
|
|
3400
|
-
|
|
3401
|
-
|
|
3402
|
-
|
|
3403
|
-
|
|
3404
|
-
|
|
3405
|
-
|
|
3406
|
-
|
|
3407
|
-
|
|
3408
|
-
|
|
3409
|
-
|
|
3410
|
-
|
|
3411
|
-
|
|
3412
|
-
|
|
3413
|
-
|
|
3414
|
-
|
|
3415
|
-
|
|
3416
|
-
|
|
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
|
|