@memberjunction/server 2.117.0 → 2.118.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.
@@ -19,7 +19,7 @@ import { mj_core_schema } from '../config.js';
19
19
 
20
20
 
21
21
 
22
- import { ScheduledActionEntity, ScheduledActionParamEntity, ExplorerNavigationItemEntity, GeneratedCodeCategoryEntity, AIAgentModelEntity, ComponentRegistryEntity, AIAgentNoteTypeEntity, ComponentDependencyEntity, AIAgentRunEntity, AIVendorEntity, TaskTypeEntity, AIConfigurationEntity, AIAgentEntity, AIAgentStepEntity, AIModelCostEntity, AIPromptModelEntity, AIAgentTypeEntity, AIAgentNoteEntity, EnvironmentEntity, ArtifactPermissionEntity, AIAgentActionEntity, TaskDependencyEntity, CollectionArtifactEntity, AIModelPriceTypeEntity, CollectionEntity, RecordLinkEntity, AIPromptEntity, AIResultCacheEntity, AIPromptCategoryEntity, AIPromptTypeEntity, CompanyEntity, EmployeeEntity, UserFavoriteEntity, EmployeeCompanyIntegrationEntity, EmployeeRoleEntity, EmployeeSkillEntity, RoleEntity, SkillEntity, IntegrationURLFormatEntity, IntegrationEntity, CompanyIntegrationEntity, EntityFieldEntity, EntityEntity, UserEntity, EntityRelationshipEntity, UserRecordLogEntity, UserViewEntity, CompanyIntegrationRunEntity, CompanyIntegrationRunDetailEntity, ErrorLogEntity, ApplicationEntity, ApplicationEntityEntity, EntityPermissionEntity, UserApplicationEntityEntity, UserApplicationEntity, CompanyIntegrationRunAPILogEntity, ListEntity, ListDetailEntity, UserViewRunEntity, UserViewRunDetailEntity, WorkflowRunEntity, WorkflowEntity, WorkflowEngineEntity, RecordChangeEntity, UserRoleEntity, RowLevelSecurityFilterEntity, AuditLogEntity, AuthorizationEntity, AuthorizationRoleEntity, AuditLogTypeEntity, EntityFieldValueEntity, AIModelEntity, AIActionEntity, AIModelActionEntity, EntityAIActionEntity, AIModelTypeEntity, QueueTypeEntity, QueueEntity, QueueTaskEntity, DashboardEntity, OutputTriggerTypeEntity, OutputFormatTypeEntity, OutputDeliveryTypeEntity, ReportEntity, ReportSnapshotEntity, ResourceTypeEntity, TagEntity, TaggedItemEntity, WorkspaceEntity, WorkspaceItemEntity, DatasetEntity, DatasetItemEntity, ConversationDetailEntity, ConversationEntity, UserNotificationEntity, SchemaInfoEntity, CompanyIntegrationRecordMapEntity, RecordMergeLogEntity, RecordMergeDeletionLogEntity, QueryFieldEntity, QueryCategoryEntity, QueryEntity, QueryPermissionEntity, VectorIndexEntity, EntityDocumentTypeEntity, EntityDocumentRunEntity, VectorDatabaseEntity, EntityRecordDocumentEntity, EntityDocumentEntity, DataContextItemEntity, DataContextEntity, UserViewCategoryEntity, DashboardCategoryEntity, ReportCategoryEntity, FileStorageProviderEntity, FileEntity, FileCategoryEntity, FileEntityRecordLinkEntity, VersionInstallationEntity, DuplicateRunDetailMatchEntity, EntityDocumentSettingEntity, EntitySettingEntity, DuplicateRunEntity, DuplicateRunDetailEntity, ApplicationSettingEntity, ActionCategoryEntity, EntityActionEntity, EntityActionInvocationEntity, ActionAuthorizationEntity, EntityActionInvocationTypeEntity, ActionEntity, EntityActionFilterEntity, ActionFilterEntity, ActionContextTypeEntity, ActionResultCodeEntity, ActionContextEntity, ActionExecutionLogEntity, ActionParamEntity, ActionLibraryEntity, LibraryEntity, ListCategoryEntity, CommunicationProviderEntity, CommunicationRunEntity, CommunicationProviderMessageTypeEntity, CommunicationLogEntity, CommunicationBaseMessageTypeEntity, TemplateEntity, TemplateCategoryEntity, TemplateContentEntity, TemplateParamEntity, TemplateContentTypeEntity, RecommendationEntity, RecommendationProviderEntity, RecommendationRunEntity, RecommendationItemEntity, EntityCommunicationMessageTypeEntity, EntityCommunicationFieldEntity, RecordChangeReplayRunEntity, LibraryItemEntity, EntityRelationshipDisplayComponentEntity, EntityActionParamEntity, ResourcePermissionEntity, ResourceLinkEntity, AIAgentArtifactTypeEntity, ConversationArtifactVersionEntity, AIAgentRequestEntity, AIModelVendorEntity, AIVendorTypeDefinitionEntity, ReportUserStateEntity, QueryEntityEntity, ScheduledJobRunEntity, DashboardUserStateEntity, ComponentEntity, AccessControlRuleEntity, ArtifactUseEntity, PublicLinkEntity, ArtifactTypeEntity, AIVendorTypeEntity, ArtifactEntity, AIAgentExampleEntity, ConversationArtifactEntity, CollectionPermissionEntity, AIAgentPromptEntity, ComponentLibraryEntity, ScheduledJobTypeEntity, DashboardUserPreferenceEntity, QueryParameterEntity, ConversationDetailRatingEntity, AIAgentPermissionEntity, AIAgentRelationshipEntity, ComponentLibraryLinkEntity, ContentProcessRunEntity, ContentSourceEntity, ContentSourceParamEntity, ContentSourceTypeEntity, ContentSourceTypeParamEntity, ContentTypeEntity, ContentTypeAttributeEntity, ContentFileTypeEntity, ContentItemEntity, ContentItemAttributeEntity, ContentItemTagEntity, GeneratedCodeEntity, ScheduledJobEntity, AIPromptRunEntity, AIAgentRunStepEntity, ConversationDetailArtifactEntity, TaskEntity, ProjectEntity, ConversationArtifactPermissionEntity, AIModelPriceUnitTypeEntity, ArtifactVersionEntity, AIAgentStepPathEntity, AIAgentLearningCycleEntity, ReportVersionEntity, AIConfigurationParamEntity, ArtifactVersionAttributeEntity, AIAgentDataSourceEntity } from '@memberjunction/core-entities';
22
+ import { ScheduledActionEntity, ScheduledActionParamEntity, ExplorerNavigationItemEntity, TestRunFeedbackEntity, GeneratedCodeCategoryEntity, AIAgentModelEntity, ComponentRegistryEntity, AIAgentNoteTypeEntity, ComponentDependencyEntity, AIAgentRunEntity, TestEntity, TestTypeEntity, AIVendorEntity, TaskTypeEntity, AIConfigurationEntity, AIAgentEntity, AIAgentStepEntity, AIModelCostEntity, AIPromptModelEntity, AIAgentTypeEntity, AIAgentConfigurationEntity, TestSuiteTestEntity, AIAgentNoteEntity, EnvironmentEntity, ArtifactPermissionEntity, AIAgentActionEntity, TestRubricEntity, TaskDependencyEntity, CollectionArtifactEntity, AIModelPriceTypeEntity, CollectionEntity, RecordLinkEntity, AIPromptEntity, AIResultCacheEntity, AIPromptCategoryEntity, AIPromptTypeEntity, CompanyEntity, EmployeeEntity, UserFavoriteEntity, EmployeeCompanyIntegrationEntity, EmployeeRoleEntity, EmployeeSkillEntity, RoleEntity, SkillEntity, IntegrationURLFormatEntity, IntegrationEntity, CompanyIntegrationEntity, EntityFieldEntity, EntityEntity, UserEntity, EntityRelationshipEntity, UserRecordLogEntity, UserViewEntity, CompanyIntegrationRunEntity, CompanyIntegrationRunDetailEntity, ErrorLogEntity, ApplicationEntity, ApplicationEntityEntity, EntityPermissionEntity, UserApplicationEntityEntity, UserApplicationEntity, CompanyIntegrationRunAPILogEntity, ListEntity, ListDetailEntity, UserViewRunEntity, UserViewRunDetailEntity, WorkflowRunEntity, WorkflowEntity, WorkflowEngineEntity, RecordChangeEntity, UserRoleEntity, RowLevelSecurityFilterEntity, AuditLogEntity, AuthorizationEntity, AuthorizationRoleEntity, AuditLogTypeEntity, EntityFieldValueEntity, AIModelEntity, AIActionEntity, AIModelActionEntity, EntityAIActionEntity, AIModelTypeEntity, QueueTypeEntity, QueueEntity, QueueTaskEntity, DashboardEntity, OutputTriggerTypeEntity, OutputFormatTypeEntity, OutputDeliveryTypeEntity, ReportEntity, ReportSnapshotEntity, ResourceTypeEntity, TagEntity, TaggedItemEntity, WorkspaceEntity, WorkspaceItemEntity, DatasetEntity, DatasetItemEntity, ConversationDetailEntity, ConversationEntity, UserNotificationEntity, SchemaInfoEntity, CompanyIntegrationRecordMapEntity, RecordMergeLogEntity, RecordMergeDeletionLogEntity, QueryFieldEntity, QueryCategoryEntity, QueryEntity, QueryPermissionEntity, VectorIndexEntity, EntityDocumentTypeEntity, EntityDocumentRunEntity, VectorDatabaseEntity, EntityRecordDocumentEntity, EntityDocumentEntity, DataContextItemEntity, DataContextEntity, UserViewCategoryEntity, DashboardCategoryEntity, ReportCategoryEntity, FileStorageProviderEntity, FileEntity, FileCategoryEntity, FileEntityRecordLinkEntity, VersionInstallationEntity, DuplicateRunDetailMatchEntity, EntityDocumentSettingEntity, EntitySettingEntity, DuplicateRunEntity, DuplicateRunDetailEntity, ApplicationSettingEntity, ActionCategoryEntity, EntityActionEntity, EntityActionInvocationEntity, ActionAuthorizationEntity, EntityActionInvocationTypeEntity, ActionEntity, EntityActionFilterEntity, ActionFilterEntity, ActionContextTypeEntity, ActionResultCodeEntity, ActionContextEntity, ActionExecutionLogEntity, ActionParamEntity, ActionLibraryEntity, LibraryEntity, ListCategoryEntity, CommunicationProviderEntity, CommunicationRunEntity, CommunicationProviderMessageTypeEntity, CommunicationLogEntity, CommunicationBaseMessageTypeEntity, TemplateEntity, TemplateCategoryEntity, TemplateContentEntity, TemplateParamEntity, TemplateContentTypeEntity, RecommendationEntity, RecommendationProviderEntity, RecommendationRunEntity, RecommendationItemEntity, EntityCommunicationMessageTypeEntity, EntityCommunicationFieldEntity, RecordChangeReplayRunEntity, LibraryItemEntity, EntityRelationshipDisplayComponentEntity, EntityActionParamEntity, ResourcePermissionEntity, ResourceLinkEntity, TestRunEntity, AIAgentArtifactTypeEntity, ConversationArtifactVersionEntity, AIAgentRequestEntity, AIModelVendorEntity, AIVendorTypeDefinitionEntity, ReportUserStateEntity, QueryEntityEntity, ScheduledJobRunEntity, DashboardUserStateEntity, ComponentEntity, AccessControlRuleEntity, ArtifactUseEntity, PublicLinkEntity, ArtifactTypeEntity, AIVendorTypeEntity, ArtifactEntity, AIAgentExampleEntity, TestSuiteEntity, ConversationArtifactEntity, CollectionPermissionEntity, AIAgentPromptEntity, ComponentLibraryEntity, ScheduledJobTypeEntity, DashboardUserPreferenceEntity, QueryParameterEntity, ConversationDetailRatingEntity, AIAgentPermissionEntity, AIAgentRelationshipEntity, ComponentLibraryLinkEntity, TestSuiteRunEntity, ContentProcessRunEntity, ContentSourceEntity, ContentSourceParamEntity, ContentSourceTypeEntity, ContentSourceTypeParamEntity, ContentTypeEntity, ContentTypeAttributeEntity, ContentFileTypeEntity, ContentItemEntity, ContentItemAttributeEntity, ContentItemTagEntity, GeneratedCodeEntity, ScheduledJobEntity, AIPromptRunEntity, AIAgentRunStepEntity, ConversationDetailArtifactEntity, TaskEntity, ProjectEntity, ConversationArtifactPermissionEntity, AIModelPriceUnitTypeEntity, ArtifactVersionEntity, AIAgentStepPathEntity, AIAgentLearningCycleEntity, ReportVersionEntity, AIConfigurationParamEntity, ArtifactVersionAttributeEntity, AIAgentDataSourceEntity } from '@memberjunction/core-entities';
23
23
 
24
24
 
25
25
  //****************************************************************************
@@ -695,6 +695,204 @@ export class MJExplorerNavigationItemResolver extends ResolverBase {
695
695
 
696
696
  }
697
697
 
698
+ //****************************************************************************
699
+ // ENTITY CLASS for MJ: Test Run Feedbacks
700
+ //****************************************************************************
701
+ @ObjectType({ description: `Human-in-the-loop feedback on test run results. Allows human reviewers to validate, correct, or override automated test results. Essential for training and improving automated evaluation criteria.` })
702
+ export class MJTestRunFeedback_ {
703
+ @Field()
704
+ @MaxLength(16)
705
+ ID: string;
706
+
707
+ @Field({description: `Foreign Key - The test run being reviewed`})
708
+ @MaxLength(16)
709
+ TestRunID: string;
710
+
711
+ @Field({description: `Foreign Key - The user providing the feedback`})
712
+ @MaxLength(16)
713
+ ReviewerUserID: string;
714
+
715
+ @Field(() => Int, {nullable: true, description: `Numeric rating from 1 (poor) to 10 (excellent). Allows quantitative tracking of result quality.`})
716
+ Rating?: number;
717
+
718
+ @Field(() => Boolean, {nullable: true, description: `Boolean indicating if the automated test result was correct. Can override automated Pass/Fail status.`})
719
+ IsCorrect?: boolean;
720
+
721
+ @Field({nullable: true, description: `Summary of corrections or adjustments made by the human reviewer`})
722
+ CorrectionSummary?: string;
723
+
724
+ @Field({nullable: true, description: `Free-form comments from the reviewer about the test result, quality, or issues found`})
725
+ Comments?: string;
726
+
727
+ @Field({description: `Timestamp when the feedback was provided`})
728
+ @MaxLength(8)
729
+ ReviewedAt: Date;
730
+
731
+ @Field()
732
+ @MaxLength(10)
733
+ _mj__CreatedAt: Date;
734
+
735
+ @Field()
736
+ @MaxLength(10)
737
+ _mj__UpdatedAt: Date;
738
+
739
+ @Field()
740
+ @MaxLength(200)
741
+ ReviewerUser: string;
742
+
743
+ }
744
+
745
+ //****************************************************************************
746
+ // INPUT TYPE for MJ: Test Run Feedbacks
747
+ //****************************************************************************
748
+ @InputType()
749
+ export class CreateMJTestRunFeedbackInput {
750
+ @Field({ nullable: true })
751
+ ID?: string;
752
+
753
+ @Field({ nullable: true })
754
+ TestRunID?: string;
755
+
756
+ @Field({ nullable: true })
757
+ ReviewerUserID?: string;
758
+
759
+ @Field(() => Int, { nullable: true })
760
+ Rating: number | null;
761
+
762
+ @Field(() => Boolean, { nullable: true })
763
+ IsCorrect: boolean | null;
764
+
765
+ @Field({ nullable: true })
766
+ CorrectionSummary: string | null;
767
+
768
+ @Field({ nullable: true })
769
+ Comments: string | null;
770
+
771
+ @Field({ nullable: true })
772
+ ReviewedAt?: Date;
773
+ }
774
+
775
+
776
+ //****************************************************************************
777
+ // INPUT TYPE for MJ: Test Run Feedbacks
778
+ //****************************************************************************
779
+ @InputType()
780
+ export class UpdateMJTestRunFeedbackInput {
781
+ @Field()
782
+ ID: string;
783
+
784
+ @Field({ nullable: true })
785
+ TestRunID?: string;
786
+
787
+ @Field({ nullable: true })
788
+ ReviewerUserID?: string;
789
+
790
+ @Field(() => Int, { nullable: true })
791
+ Rating?: number | null;
792
+
793
+ @Field(() => Boolean, { nullable: true })
794
+ IsCorrect?: boolean | null;
795
+
796
+ @Field({ nullable: true })
797
+ CorrectionSummary?: string | null;
798
+
799
+ @Field({ nullable: true })
800
+ Comments?: string | null;
801
+
802
+ @Field({ nullable: true })
803
+ ReviewedAt?: Date;
804
+
805
+ @Field(() => [KeyValuePairInput], { nullable: true })
806
+ OldValues___?: KeyValuePairInput[];
807
+ }
808
+
809
+ //****************************************************************************
810
+ // RESOLVER for MJ: Test Run Feedbacks
811
+ //****************************************************************************
812
+ @ObjectType()
813
+ export class RunMJTestRunFeedbackViewResult {
814
+ @Field(() => [MJTestRunFeedback_])
815
+ Results: MJTestRunFeedback_[];
816
+
817
+ @Field(() => String, {nullable: true})
818
+ UserViewRunID?: string;
819
+
820
+ @Field(() => Int, {nullable: true})
821
+ RowCount: number;
822
+
823
+ @Field(() => Int, {nullable: true})
824
+ TotalRowCount: number;
825
+
826
+ @Field(() => Int, {nullable: true})
827
+ ExecutionTime: number;
828
+
829
+ @Field({nullable: true})
830
+ ErrorMessage?: string;
831
+
832
+ @Field(() => Boolean, {nullable: false})
833
+ Success: boolean;
834
+ }
835
+
836
+ @Resolver(MJTestRunFeedback_)
837
+ export class MJTestRunFeedbackResolver extends ResolverBase {
838
+ @Query(() => RunMJTestRunFeedbackViewResult)
839
+ async RunMJTestRunFeedbackViewByID(@Arg('input', () => RunViewByIDInput) input: RunViewByIDInput, @Ctx() { providers, userPayload }: AppContext, @PubSub() pubSub: PubSubEngine) {
840
+ const provider = GetReadOnlyProvider(providers, { allowFallbackToReadWrite: true });
841
+ return super.RunViewByIDGeneric(input, provider, userPayload, pubSub);
842
+ }
843
+
844
+ @Query(() => RunMJTestRunFeedbackViewResult)
845
+ async RunMJTestRunFeedbackViewByName(@Arg('input', () => RunViewByNameInput) input: RunViewByNameInput, @Ctx() { providers, userPayload }: AppContext, @PubSub() pubSub: PubSubEngine) {
846
+ const provider = GetReadOnlyProvider(providers, { allowFallbackToReadWrite: true });
847
+ return super.RunViewByNameGeneric(input, provider, userPayload, pubSub);
848
+ }
849
+
850
+ @Query(() => RunMJTestRunFeedbackViewResult)
851
+ async RunMJTestRunFeedbackDynamicView(@Arg('input', () => RunDynamicViewInput) input: RunDynamicViewInput, @Ctx() { providers, userPayload }: AppContext, @PubSub() pubSub: PubSubEngine) {
852
+ const provider = GetReadOnlyProvider(providers, { allowFallbackToReadWrite: true });
853
+ input.EntityName = 'MJ: Test Run Feedbacks';
854
+ return super.RunDynamicViewGeneric(input, provider, userPayload, pubSub);
855
+ }
856
+ @Query(() => MJTestRunFeedback_, { nullable: true })
857
+ async MJTestRunFeedback(@Arg('ID', () => String) ID: string, @Ctx() { dataSources, userPayload, providers }: AppContext, @PubSub() pubSub: PubSubEngine): Promise<MJTestRunFeedback_ | null> {
858
+ this.CheckUserReadPermissions('MJ: Test Run Feedbacks', userPayload);
859
+ const provider = GetReadOnlyProvider(providers, { allowFallbackToReadWrite: true });
860
+ const connPool = GetReadOnlyDataSource(dataSources, { allowFallbackToReadWrite: true });
861
+ const sSQL = `SELECT * FROM [${Metadata.Provider.ConfigData.MJCoreSchemaName}].[vwTestRunFeedbacks] WHERE [ID]='${ID}' ` + this.getRowLevelSecurityWhereClause(provider, 'MJ: Test Run Feedbacks', userPayload, EntityPermissionType.Read, 'AND');
862
+ const rows = await SQLServerDataProvider.ExecuteSQLWithPool(connPool, sSQL, undefined, this.GetUserFromPayload(userPayload));
863
+ const result = this.MapFieldNamesToCodeNames('MJ: Test Run Feedbacks', rows && rows.length > 0 ? rows[0] : {})
864
+ return result;
865
+ }
866
+
867
+ @Mutation(() => MJTestRunFeedback_)
868
+ async CreateMJTestRunFeedback(
869
+ @Arg('input', () => CreateMJTestRunFeedbackInput) input: CreateMJTestRunFeedbackInput,
870
+ @Ctx() { providers, userPayload }: AppContext,
871
+ @PubSub() pubSub: PubSubEngine
872
+ ) {
873
+ const provider = GetReadWriteProvider(providers);
874
+ return this.CreateRecord('MJ: Test Run Feedbacks', input, provider, userPayload, pubSub)
875
+ }
876
+
877
+ @Mutation(() => MJTestRunFeedback_)
878
+ async UpdateMJTestRunFeedback(
879
+ @Arg('input', () => UpdateMJTestRunFeedbackInput) input: UpdateMJTestRunFeedbackInput,
880
+ @Ctx() { providers, userPayload }: AppContext,
881
+ @PubSub() pubSub: PubSubEngine
882
+ ) {
883
+ const provider = GetReadWriteProvider(providers);
884
+ return this.UpdateRecord('MJ: Test Run Feedbacks', input, provider, userPayload, pubSub);
885
+ }
886
+
887
+ @Mutation(() => MJTestRunFeedback_)
888
+ async DeleteMJTestRunFeedback(@Arg('ID', () => String) ID: string, @Arg('options___', () => DeleteOptionsInput) options: DeleteOptionsInput, @Ctx() { providers, userPayload }: AppContext, @PubSub() pubSub: PubSubEngine) {
889
+ const provider = GetReadWriteProvider(providers);
890
+ const key = new CompositeKey([{FieldName: 'ID', Value: ID}]);
891
+ return this.DeleteRecord('MJ: Test Run Feedbacks', key, options, provider, userPayload, pubSub);
892
+ }
893
+
894
+ }
895
+
698
896
  //****************************************************************************
699
897
  // ENTITY CLASS for Generated Code Categories
700
898
  //****************************************************************************
@@ -1744,10 +1942,18 @@ each time the agent processes a prompt step.`})
1744
1942
  @MaxLength(16)
1745
1943
  ScheduledJobRunID?: string;
1746
1944
 
1945
+ @Field({nullable: true, description: `Optional Foreign Key - Links this agent run to a test run if this execution was part of a test. Allows navigation from agent execution to test context.`})
1946
+ @MaxLength(16)
1947
+ TestRunID?: string;
1948
+
1747
1949
  @Field({nullable: true})
1748
1950
  @MaxLength(510)
1749
1951
  Agent?: string;
1750
1952
 
1953
+ @Field({nullable: true})
1954
+ @MaxLength(510)
1955
+ ParentRun?: string;
1956
+
1751
1957
  @Field({nullable: true})
1752
1958
  @MaxLength(510)
1753
1959
  Conversation?: string;
@@ -1756,6 +1962,13 @@ each time the agent processes a prompt step.`})
1756
1962
  @MaxLength(200)
1757
1963
  User?: string;
1758
1964
 
1965
+ @Field({nullable: true})
1966
+ ConversationDetail?: string;
1967
+
1968
+ @Field({nullable: true})
1969
+ @MaxLength(510)
1970
+ LastRun?: string;
1971
+
1759
1972
  @Field({nullable: true})
1760
1973
  @MaxLength(200)
1761
1974
  Configuration?: string;
@@ -1768,6 +1981,10 @@ each time the agent processes a prompt step.`})
1768
1981
  @MaxLength(100)
1769
1982
  OverrideVendor?: string;
1770
1983
 
1984
+ @Field({nullable: true})
1985
+ @MaxLength(400)
1986
+ ScheduledJobRun?: string;
1987
+
1771
1988
  @Field({nullable: true})
1772
1989
  @MaxLength(16)
1773
1990
  RootParentRunID?: string;
@@ -1911,6 +2128,9 @@ export class CreateMJAIAgentRunInput {
1911
2128
 
1912
2129
  @Field({ nullable: true })
1913
2130
  ScheduledJobRunID: string | null;
2131
+
2132
+ @Field({ nullable: true })
2133
+ TestRunID: string | null;
1914
2134
  }
1915
2135
 
1916
2136
 
@@ -2033,6 +2253,9 @@ export class UpdateMJAIAgentRunInput {
2033
2253
  @Field({ nullable: true })
2034
2254
  ScheduledJobRunID?: string | null;
2035
2255
 
2256
+ @Field({ nullable: true })
2257
+ TestRunID?: string | null;
2258
+
2036
2259
  @Field(() => [KeyValuePairInput], { nullable: true })
2037
2260
  OldValues___?: KeyValuePairInput[];
2038
2261
  }
@@ -2179,6 +2402,472 @@ export class MJAIAgentRunResolver extends ResolverBase {
2179
2402
 
2180
2403
  }
2181
2404
 
2405
+ //****************************************************************************
2406
+ // ENTITY CLASS for MJ: Tests
2407
+ //****************************************************************************
2408
+ @ObjectType({ description: `Individual test definitions. Each test has a specific type (via TypeID) which determines how it executes. Tests store their inputs, expected outcomes, and configuration as JSON, allowing flexibility for different test types while maintaining a common schema.` })
2409
+ export class MJTest_ {
2410
+ @Field()
2411
+ @MaxLength(16)
2412
+ ID: string;
2413
+
2414
+ @Field({description: `Foreign Key - The type of test (e.g., Agent Eval, Workflow Test). Determines which driver class handles execution.`})
2415
+ @MaxLength(16)
2416
+ TypeID: string;
2417
+
2418
+ @Field({description: `Name of the test (e.g., "Pie Chart with Drilldown", "Memory Recall Accuracy")`})
2419
+ @MaxLength(510)
2420
+ Name: string;
2421
+
2422
+ @Field({nullable: true, description: `Detailed description of what this test validates and why it matters`})
2423
+ Description?: string;
2424
+
2425
+ @Field({description: `Status of the test: Pending (being configured), Active (ready to run), Disabled (archived/not in use)`})
2426
+ @MaxLength(40)
2427
+ Status: string;
2428
+
2429
+ @Field({nullable: true, description: `JSON object defining the inputs/parameters for the test. Structure varies by test type (e.g., for Agent Eval: {prompt, context, conversationHistory})`})
2430
+ InputDefinition?: string;
2431
+
2432
+ @Field({nullable: true, description: `JSON object defining what success looks like. Structure varies by test type (e.g., for Agent Eval: {toolCalls, outputFormat, semanticGoals, dataAssertions})`})
2433
+ ExpectedOutcomes?: string;
2434
+
2435
+ @Field({nullable: true, description: `JSON object for test-specific configuration (e.g., oracles to use, rubrics, retry policies, timeout settings)`})
2436
+ Configuration?: string;
2437
+
2438
+ @Field({nullable: true, description: `JSON array of tags for categorization and filtering (e.g., ["smoke", "agent-quality", "performance"])`})
2439
+ Tags?: string;
2440
+
2441
+ @Field(() => Int, {nullable: true, description: `Priority for execution ordering. Lower numbers run first. Useful for dependencies or critical path tests.`})
2442
+ Priority?: number;
2443
+
2444
+ @Field(() => Int, {nullable: true, description: `Estimated execution time in seconds. Used for scheduling and timeout calculations.`})
2445
+ EstimatedDurationSeconds?: number;
2446
+
2447
+ @Field(() => Float, {nullable: true, description: `Estimated cost in USD for running this test (e.g., LLM token costs, compute resources). Used for budgeting and optimization.`})
2448
+ EstimatedCostUSD?: number;
2449
+
2450
+ @Field()
2451
+ @MaxLength(10)
2452
+ _mj__CreatedAt: Date;
2453
+
2454
+ @Field()
2455
+ @MaxLength(10)
2456
+ _mj__UpdatedAt: Date;
2457
+
2458
+ @Field(() => Int, {nullable: true, description: `Number of times to repeat this test execution. NULL or 1 = single execution. Values > 1 will create multiple test runs for statistical analysis.`})
2459
+ RepeatCount?: number;
2460
+
2461
+ @Field()
2462
+ @MaxLength(200)
2463
+ Type: string;
2464
+
2465
+ @Field(() => [MJTestRun_])
2466
+ MJ_TestRuns_TestIDArray: MJTestRun_[]; // Link to MJ_TestRuns
2467
+
2468
+ @Field(() => [MJTestSuiteTest_])
2469
+ MJ_TestSuiteTests_TestIDArray: MJTestSuiteTest_[]; // Link to MJ_TestSuiteTests
2470
+
2471
+ }
2472
+
2473
+ //****************************************************************************
2474
+ // INPUT TYPE for MJ: Tests
2475
+ //****************************************************************************
2476
+ @InputType()
2477
+ export class CreateMJTestInput {
2478
+ @Field({ nullable: true })
2479
+ ID?: string;
2480
+
2481
+ @Field({ nullable: true })
2482
+ TypeID?: string;
2483
+
2484
+ @Field({ nullable: true })
2485
+ Name?: string;
2486
+
2487
+ @Field({ nullable: true })
2488
+ Description: string | null;
2489
+
2490
+ @Field({ nullable: true })
2491
+ Status?: string;
2492
+
2493
+ @Field({ nullable: true })
2494
+ InputDefinition: string | null;
2495
+
2496
+ @Field({ nullable: true })
2497
+ ExpectedOutcomes: string | null;
2498
+
2499
+ @Field({ nullable: true })
2500
+ Configuration: string | null;
2501
+
2502
+ @Field({ nullable: true })
2503
+ Tags: string | null;
2504
+
2505
+ @Field(() => Int, { nullable: true })
2506
+ Priority?: number | null;
2507
+
2508
+ @Field(() => Int, { nullable: true })
2509
+ EstimatedDurationSeconds: number | null;
2510
+
2511
+ @Field(() => Float, { nullable: true })
2512
+ EstimatedCostUSD: number | null;
2513
+
2514
+ @Field(() => Int, { nullable: true })
2515
+ RepeatCount: number | null;
2516
+ }
2517
+
2518
+
2519
+ //****************************************************************************
2520
+ // INPUT TYPE for MJ: Tests
2521
+ //****************************************************************************
2522
+ @InputType()
2523
+ export class UpdateMJTestInput {
2524
+ @Field()
2525
+ ID: string;
2526
+
2527
+ @Field({ nullable: true })
2528
+ TypeID?: string;
2529
+
2530
+ @Field({ nullable: true })
2531
+ Name?: string;
2532
+
2533
+ @Field({ nullable: true })
2534
+ Description?: string | null;
2535
+
2536
+ @Field({ nullable: true })
2537
+ Status?: string;
2538
+
2539
+ @Field({ nullable: true })
2540
+ InputDefinition?: string | null;
2541
+
2542
+ @Field({ nullable: true })
2543
+ ExpectedOutcomes?: string | null;
2544
+
2545
+ @Field({ nullable: true })
2546
+ Configuration?: string | null;
2547
+
2548
+ @Field({ nullable: true })
2549
+ Tags?: string | null;
2550
+
2551
+ @Field(() => Int, { nullable: true })
2552
+ Priority?: number | null;
2553
+
2554
+ @Field(() => Int, { nullable: true })
2555
+ EstimatedDurationSeconds?: number | null;
2556
+
2557
+ @Field(() => Float, { nullable: true })
2558
+ EstimatedCostUSD?: number | null;
2559
+
2560
+ @Field(() => Int, { nullable: true })
2561
+ RepeatCount?: number | null;
2562
+
2563
+ @Field(() => [KeyValuePairInput], { nullable: true })
2564
+ OldValues___?: KeyValuePairInput[];
2565
+ }
2566
+
2567
+ //****************************************************************************
2568
+ // RESOLVER for MJ: Tests
2569
+ //****************************************************************************
2570
+ @ObjectType()
2571
+ export class RunMJTestViewResult {
2572
+ @Field(() => [MJTest_])
2573
+ Results: MJTest_[];
2574
+
2575
+ @Field(() => String, {nullable: true})
2576
+ UserViewRunID?: string;
2577
+
2578
+ @Field(() => Int, {nullable: true})
2579
+ RowCount: number;
2580
+
2581
+ @Field(() => Int, {nullable: true})
2582
+ TotalRowCount: number;
2583
+
2584
+ @Field(() => Int, {nullable: true})
2585
+ ExecutionTime: number;
2586
+
2587
+ @Field({nullable: true})
2588
+ ErrorMessage?: string;
2589
+
2590
+ @Field(() => Boolean, {nullable: false})
2591
+ Success: boolean;
2592
+ }
2593
+
2594
+ @Resolver(MJTest_)
2595
+ export class MJTestResolver extends ResolverBase {
2596
+ @Query(() => RunMJTestViewResult)
2597
+ async RunMJTestViewByID(@Arg('input', () => RunViewByIDInput) input: RunViewByIDInput, @Ctx() { providers, userPayload }: AppContext, @PubSub() pubSub: PubSubEngine) {
2598
+ const provider = GetReadOnlyProvider(providers, { allowFallbackToReadWrite: true });
2599
+ return super.RunViewByIDGeneric(input, provider, userPayload, pubSub);
2600
+ }
2601
+
2602
+ @Query(() => RunMJTestViewResult)
2603
+ async RunMJTestViewByName(@Arg('input', () => RunViewByNameInput) input: RunViewByNameInput, @Ctx() { providers, userPayload }: AppContext, @PubSub() pubSub: PubSubEngine) {
2604
+ const provider = GetReadOnlyProvider(providers, { allowFallbackToReadWrite: true });
2605
+ return super.RunViewByNameGeneric(input, provider, userPayload, pubSub);
2606
+ }
2607
+
2608
+ @Query(() => RunMJTestViewResult)
2609
+ async RunMJTestDynamicView(@Arg('input', () => RunDynamicViewInput) input: RunDynamicViewInput, @Ctx() { providers, userPayload }: AppContext, @PubSub() pubSub: PubSubEngine) {
2610
+ const provider = GetReadOnlyProvider(providers, { allowFallbackToReadWrite: true });
2611
+ input.EntityName = 'MJ: Tests';
2612
+ return super.RunDynamicViewGeneric(input, provider, userPayload, pubSub);
2613
+ }
2614
+ @Query(() => MJTest_, { nullable: true })
2615
+ async MJTest(@Arg('ID', () => String) ID: string, @Ctx() { dataSources, userPayload, providers }: AppContext, @PubSub() pubSub: PubSubEngine): Promise<MJTest_ | null> {
2616
+ this.CheckUserReadPermissions('MJ: Tests', userPayload);
2617
+ const provider = GetReadOnlyProvider(providers, { allowFallbackToReadWrite: true });
2618
+ const connPool = GetReadOnlyDataSource(dataSources, { allowFallbackToReadWrite: true });
2619
+ const sSQL = `SELECT * FROM [${Metadata.Provider.ConfigData.MJCoreSchemaName}].[vwTests] WHERE [ID]='${ID}' ` + this.getRowLevelSecurityWhereClause(provider, 'MJ: Tests', userPayload, EntityPermissionType.Read, 'AND');
2620
+ const rows = await SQLServerDataProvider.ExecuteSQLWithPool(connPool, sSQL, undefined, this.GetUserFromPayload(userPayload));
2621
+ const result = this.MapFieldNamesToCodeNames('MJ: Tests', rows && rows.length > 0 ? rows[0] : {})
2622
+ return result;
2623
+ }
2624
+
2625
+ @FieldResolver(() => [MJTestRun_])
2626
+ async MJ_TestRuns_TestIDArray(@Root() mjtest_: MJTest_, @Ctx() { dataSources, userPayload, providers }: AppContext, @PubSub() pubSub: PubSubEngine) {
2627
+ this.CheckUserReadPermissions('MJ: Test Runs', userPayload);
2628
+ const provider = GetReadOnlyProvider(providers, { allowFallbackToReadWrite: true });
2629
+ const connPool = GetReadOnlyDataSource(dataSources, { allowFallbackToReadWrite: true });
2630
+ const sSQL = `SELECT * FROM [${Metadata.Provider.ConfigData.MJCoreSchemaName}].[vwTestRuns] WHERE [TestID]='${mjtest_.ID}' ` + this.getRowLevelSecurityWhereClause(provider, 'MJ: Test Runs', userPayload, EntityPermissionType.Read, 'AND');
2631
+ const rows = await SQLServerDataProvider.ExecuteSQLWithPool(connPool, sSQL, undefined, this.GetUserFromPayload(userPayload));
2632
+ const result = this.ArrayMapFieldNamesToCodeNames('MJ: Test Runs', rows);
2633
+ return result;
2634
+ }
2635
+
2636
+ @FieldResolver(() => [MJTestSuiteTest_])
2637
+ async MJ_TestSuiteTests_TestIDArray(@Root() mjtest_: MJTest_, @Ctx() { dataSources, userPayload, providers }: AppContext, @PubSub() pubSub: PubSubEngine) {
2638
+ this.CheckUserReadPermissions('MJ: Test Suite Tests', userPayload);
2639
+ const provider = GetReadOnlyProvider(providers, { allowFallbackToReadWrite: true });
2640
+ const connPool = GetReadOnlyDataSource(dataSources, { allowFallbackToReadWrite: true });
2641
+ const sSQL = `SELECT * FROM [${Metadata.Provider.ConfigData.MJCoreSchemaName}].[vwTestSuiteTests] WHERE [TestID]='${mjtest_.ID}' ` + this.getRowLevelSecurityWhereClause(provider, 'MJ: Test Suite Tests', userPayload, EntityPermissionType.Read, 'AND');
2642
+ const rows = await SQLServerDataProvider.ExecuteSQLWithPool(connPool, sSQL, undefined, this.GetUserFromPayload(userPayload));
2643
+ const result = this.ArrayMapFieldNamesToCodeNames('MJ: Test Suite Tests', rows);
2644
+ return result;
2645
+ }
2646
+
2647
+ @Mutation(() => MJTest_)
2648
+ async CreateMJTest(
2649
+ @Arg('input', () => CreateMJTestInput) input: CreateMJTestInput,
2650
+ @Ctx() { providers, userPayload }: AppContext,
2651
+ @PubSub() pubSub: PubSubEngine
2652
+ ) {
2653
+ const provider = GetReadWriteProvider(providers);
2654
+ return this.CreateRecord('MJ: Tests', input, provider, userPayload, pubSub)
2655
+ }
2656
+
2657
+ @Mutation(() => MJTest_)
2658
+ async UpdateMJTest(
2659
+ @Arg('input', () => UpdateMJTestInput) input: UpdateMJTestInput,
2660
+ @Ctx() { providers, userPayload }: AppContext,
2661
+ @PubSub() pubSub: PubSubEngine
2662
+ ) {
2663
+ const provider = GetReadWriteProvider(providers);
2664
+ return this.UpdateRecord('MJ: Tests', input, provider, userPayload, pubSub);
2665
+ }
2666
+
2667
+ @Mutation(() => MJTest_)
2668
+ async DeleteMJTest(@Arg('ID', () => String) ID: string, @Arg('options___', () => DeleteOptionsInput) options: DeleteOptionsInput, @Ctx() { providers, userPayload }: AppContext, @PubSub() pubSub: PubSubEngine) {
2669
+ const provider = GetReadWriteProvider(providers);
2670
+ const key = new CompositeKey([{FieldName: 'ID', Value: ID}]);
2671
+ return this.DeleteRecord('MJ: Tests', key, options, provider, userPayload, pubSub);
2672
+ }
2673
+
2674
+ }
2675
+
2676
+ //****************************************************************************
2677
+ // ENTITY CLASS for MJ: Test Types
2678
+ //****************************************************************************
2679
+ @ObjectType({ description: `Defines test type drivers that can be dynamically instantiated via MJGlobal.Instance.ClassFactory.CreateInstance(BaseTestDriver, DriverClass). Each test type represents a different category of testing (e.g., Agent Evals, Workflow Tests, Code Generation Tests).` })
2680
+ export class MJTestType_ {
2681
+ @Field()
2682
+ @MaxLength(16)
2683
+ ID: string;
2684
+
2685
+ @Field({description: `Unique name for the test type (e.g., "Agent Eval", "Workflow Test", "Code Generation Test")`})
2686
+ @MaxLength(200)
2687
+ Name: string;
2688
+
2689
+ @Field({nullable: true, description: `Detailed description of what this test type validates and how it works`})
2690
+ Description?: string;
2691
+
2692
+ @Field({description: `Class name for the driver implementation (e.g., "AgentEvalDriver"). Used with ClassFactory to instantiate the appropriate BaseTestDriver subclass.`})
2693
+ @MaxLength(510)
2694
+ DriverClass: string;
2695
+
2696
+ @Field({description: `Status of the test type: Pending (under development), Active (available for use), Disabled (no longer available)`})
2697
+ @MaxLength(40)
2698
+ Status: string;
2699
+
2700
+ @Field()
2701
+ @MaxLength(10)
2702
+ _mj__CreatedAt: Date;
2703
+
2704
+ @Field()
2705
+ @MaxLength(10)
2706
+ _mj__UpdatedAt: Date;
2707
+
2708
+ @Field(() => [MJTestRubric_])
2709
+ MJ_TestRubrics_TypeIDArray: MJTestRubric_[]; // Link to MJ_TestRubrics
2710
+
2711
+ @Field(() => [MJTest_])
2712
+ MJ_Tests_TypeIDArray: MJTest_[]; // Link to MJ_Tests
2713
+
2714
+ }
2715
+
2716
+ //****************************************************************************
2717
+ // INPUT TYPE for MJ: Test Types
2718
+ //****************************************************************************
2719
+ @InputType()
2720
+ export class CreateMJTestTypeInput {
2721
+ @Field({ nullable: true })
2722
+ ID?: string;
2723
+
2724
+ @Field({ nullable: true })
2725
+ Name?: string;
2726
+
2727
+ @Field({ nullable: true })
2728
+ Description: string | null;
2729
+
2730
+ @Field({ nullable: true })
2731
+ DriverClass?: string;
2732
+
2733
+ @Field({ nullable: true })
2734
+ Status?: string;
2735
+ }
2736
+
2737
+
2738
+ //****************************************************************************
2739
+ // INPUT TYPE for MJ: Test Types
2740
+ //****************************************************************************
2741
+ @InputType()
2742
+ export class UpdateMJTestTypeInput {
2743
+ @Field()
2744
+ ID: string;
2745
+
2746
+ @Field({ nullable: true })
2747
+ Name?: string;
2748
+
2749
+ @Field({ nullable: true })
2750
+ Description?: string | null;
2751
+
2752
+ @Field({ nullable: true })
2753
+ DriverClass?: string;
2754
+
2755
+ @Field({ nullable: true })
2756
+ Status?: string;
2757
+
2758
+ @Field(() => [KeyValuePairInput], { nullable: true })
2759
+ OldValues___?: KeyValuePairInput[];
2760
+ }
2761
+
2762
+ //****************************************************************************
2763
+ // RESOLVER for MJ: Test Types
2764
+ //****************************************************************************
2765
+ @ObjectType()
2766
+ export class RunMJTestTypeViewResult {
2767
+ @Field(() => [MJTestType_])
2768
+ Results: MJTestType_[];
2769
+
2770
+ @Field(() => String, {nullable: true})
2771
+ UserViewRunID?: string;
2772
+
2773
+ @Field(() => Int, {nullable: true})
2774
+ RowCount: number;
2775
+
2776
+ @Field(() => Int, {nullable: true})
2777
+ TotalRowCount: number;
2778
+
2779
+ @Field(() => Int, {nullable: true})
2780
+ ExecutionTime: number;
2781
+
2782
+ @Field({nullable: true})
2783
+ ErrorMessage?: string;
2784
+
2785
+ @Field(() => Boolean, {nullable: false})
2786
+ Success: boolean;
2787
+ }
2788
+
2789
+ @Resolver(MJTestType_)
2790
+ export class MJTestTypeResolver extends ResolverBase {
2791
+ @Query(() => RunMJTestTypeViewResult)
2792
+ async RunMJTestTypeViewByID(@Arg('input', () => RunViewByIDInput) input: RunViewByIDInput, @Ctx() { providers, userPayload }: AppContext, @PubSub() pubSub: PubSubEngine) {
2793
+ const provider = GetReadOnlyProvider(providers, { allowFallbackToReadWrite: true });
2794
+ return super.RunViewByIDGeneric(input, provider, userPayload, pubSub);
2795
+ }
2796
+
2797
+ @Query(() => RunMJTestTypeViewResult)
2798
+ async RunMJTestTypeViewByName(@Arg('input', () => RunViewByNameInput) input: RunViewByNameInput, @Ctx() { providers, userPayload }: AppContext, @PubSub() pubSub: PubSubEngine) {
2799
+ const provider = GetReadOnlyProvider(providers, { allowFallbackToReadWrite: true });
2800
+ return super.RunViewByNameGeneric(input, provider, userPayload, pubSub);
2801
+ }
2802
+
2803
+ @Query(() => RunMJTestTypeViewResult)
2804
+ async RunMJTestTypeDynamicView(@Arg('input', () => RunDynamicViewInput) input: RunDynamicViewInput, @Ctx() { providers, userPayload }: AppContext, @PubSub() pubSub: PubSubEngine) {
2805
+ const provider = GetReadOnlyProvider(providers, { allowFallbackToReadWrite: true });
2806
+ input.EntityName = 'MJ: Test Types';
2807
+ return super.RunDynamicViewGeneric(input, provider, userPayload, pubSub);
2808
+ }
2809
+ @Query(() => MJTestType_, { nullable: true })
2810
+ async MJTestType(@Arg('ID', () => String) ID: string, @Ctx() { dataSources, userPayload, providers }: AppContext, @PubSub() pubSub: PubSubEngine): Promise<MJTestType_ | null> {
2811
+ this.CheckUserReadPermissions('MJ: Test Types', userPayload);
2812
+ const provider = GetReadOnlyProvider(providers, { allowFallbackToReadWrite: true });
2813
+ const connPool = GetReadOnlyDataSource(dataSources, { allowFallbackToReadWrite: true });
2814
+ const sSQL = `SELECT * FROM [${Metadata.Provider.ConfigData.MJCoreSchemaName}].[vwTestTypes] WHERE [ID]='${ID}' ` + this.getRowLevelSecurityWhereClause(provider, 'MJ: Test Types', userPayload, EntityPermissionType.Read, 'AND');
2815
+ const rows = await SQLServerDataProvider.ExecuteSQLWithPool(connPool, sSQL, undefined, this.GetUserFromPayload(userPayload));
2816
+ const result = this.MapFieldNamesToCodeNames('MJ: Test Types', rows && rows.length > 0 ? rows[0] : {})
2817
+ return result;
2818
+ }
2819
+
2820
+ @FieldResolver(() => [MJTestRubric_])
2821
+ async MJ_TestRubrics_TypeIDArray(@Root() mjtesttype_: MJTestType_, @Ctx() { dataSources, userPayload, providers }: AppContext, @PubSub() pubSub: PubSubEngine) {
2822
+ this.CheckUserReadPermissions('MJ: Test Rubrics', userPayload);
2823
+ const provider = GetReadOnlyProvider(providers, { allowFallbackToReadWrite: true });
2824
+ const connPool = GetReadOnlyDataSource(dataSources, { allowFallbackToReadWrite: true });
2825
+ const sSQL = `SELECT * FROM [${Metadata.Provider.ConfigData.MJCoreSchemaName}].[vwTestRubrics] WHERE [TypeID]='${mjtesttype_.ID}' ` + this.getRowLevelSecurityWhereClause(provider, 'MJ: Test Rubrics', userPayload, EntityPermissionType.Read, 'AND');
2826
+ const rows = await SQLServerDataProvider.ExecuteSQLWithPool(connPool, sSQL, undefined, this.GetUserFromPayload(userPayload));
2827
+ const result = this.ArrayMapFieldNamesToCodeNames('MJ: Test Rubrics', rows);
2828
+ return result;
2829
+ }
2830
+
2831
+ @FieldResolver(() => [MJTest_])
2832
+ async MJ_Tests_TypeIDArray(@Root() mjtesttype_: MJTestType_, @Ctx() { dataSources, userPayload, providers }: AppContext, @PubSub() pubSub: PubSubEngine) {
2833
+ this.CheckUserReadPermissions('MJ: Tests', userPayload);
2834
+ const provider = GetReadOnlyProvider(providers, { allowFallbackToReadWrite: true });
2835
+ const connPool = GetReadOnlyDataSource(dataSources, { allowFallbackToReadWrite: true });
2836
+ const sSQL = `SELECT * FROM [${Metadata.Provider.ConfigData.MJCoreSchemaName}].[vwTests] WHERE [TypeID]='${mjtesttype_.ID}' ` + this.getRowLevelSecurityWhereClause(provider, 'MJ: Tests', userPayload, EntityPermissionType.Read, 'AND');
2837
+ const rows = await SQLServerDataProvider.ExecuteSQLWithPool(connPool, sSQL, undefined, this.GetUserFromPayload(userPayload));
2838
+ const result = this.ArrayMapFieldNamesToCodeNames('MJ: Tests', rows);
2839
+ return result;
2840
+ }
2841
+
2842
+ @Mutation(() => MJTestType_)
2843
+ async CreateMJTestType(
2844
+ @Arg('input', () => CreateMJTestTypeInput) input: CreateMJTestTypeInput,
2845
+ @Ctx() { providers, userPayload }: AppContext,
2846
+ @PubSub() pubSub: PubSubEngine
2847
+ ) {
2848
+ const provider = GetReadWriteProvider(providers);
2849
+ return this.CreateRecord('MJ: Test Types', input, provider, userPayload, pubSub)
2850
+ }
2851
+
2852
+ @Mutation(() => MJTestType_)
2853
+ async UpdateMJTestType(
2854
+ @Arg('input', () => UpdateMJTestTypeInput) input: UpdateMJTestTypeInput,
2855
+ @Ctx() { providers, userPayload }: AppContext,
2856
+ @PubSub() pubSub: PubSubEngine
2857
+ ) {
2858
+ const provider = GetReadWriteProvider(providers);
2859
+ return this.UpdateRecord('MJ: Test Types', input, provider, userPayload, pubSub);
2860
+ }
2861
+
2862
+ @Mutation(() => MJTestType_)
2863
+ async DeleteMJTestType(@Arg('ID', () => String) ID: string, @Arg('options___', () => DeleteOptionsInput) options: DeleteOptionsInput, @Ctx() { providers, userPayload }: AppContext, @PubSub() pubSub: PubSubEngine) {
2864
+ const provider = GetReadWriteProvider(providers);
2865
+ const key = new CompositeKey([{FieldName: 'ID', Value: ID}]);
2866
+ return this.DeleteRecord('MJ: Test Types', key, options, provider, userPayload, pubSub);
2867
+ }
2868
+
2869
+ }
2870
+
2182
2871
  //****************************************************************************
2183
2872
  // ENTITY CLASS for MJ: AI Vendors
2184
2873
  //****************************************************************************
@@ -2638,6 +3327,9 @@ export class MJAIConfiguration_ {
2638
3327
  @Field(() => [MJAIAgentPrompt_])
2639
3328
  MJ_AIAgentPrompts_ConfigurationIDArray: MJAIAgentPrompt_[]; // Link to MJ_AIAgentPrompts
2640
3329
 
3330
+ @Field(() => [MJAIAgentConfiguration_])
3331
+ MJ_AIAgentConfigurations_AIConfigurationIDArray: MJAIAgentConfiguration_[]; // Link to MJ_AIAgentConfigurations
3332
+
2641
3333
  @Field(() => [MJAIPromptModel_])
2642
3334
  MJ_AIPromptModels_ConfigurationIDArray: MJAIPromptModel_[]; // Link to MJ_AIPromptModels
2643
3335
 
@@ -2790,6 +3482,17 @@ export class MJAIConfigurationResolver extends ResolverBase {
2790
3482
  return result;
2791
3483
  }
2792
3484
 
3485
+ @FieldResolver(() => [MJAIAgentConfiguration_])
3486
+ async MJ_AIAgentConfigurations_AIConfigurationIDArray(@Root() mjaiconfiguration_: MJAIConfiguration_, @Ctx() { dataSources, userPayload, providers }: AppContext, @PubSub() pubSub: PubSubEngine) {
3487
+ this.CheckUserReadPermissions('MJ: AI Agent Configurations', userPayload);
3488
+ const provider = GetReadOnlyProvider(providers, { allowFallbackToReadWrite: true });
3489
+ const connPool = GetReadOnlyDataSource(dataSources, { allowFallbackToReadWrite: true });
3490
+ const sSQL = `SELECT * FROM [${Metadata.Provider.ConfigData.MJCoreSchemaName}].[vwAIAgentConfigurations] WHERE [AIConfigurationID]='${mjaiconfiguration_.ID}' ` + this.getRowLevelSecurityWhereClause(provider, 'MJ: AI Agent Configurations', userPayload, EntityPermissionType.Read, 'AND');
3491
+ const rows = await SQLServerDataProvider.ExecuteSQLWithPool(connPool, sSQL, undefined, this.GetUserFromPayload(userPayload));
3492
+ const result = this.ArrayMapFieldNamesToCodeNames('MJ: AI Agent Configurations', rows);
3493
+ return result;
3494
+ }
3495
+
2793
3496
  @FieldResolver(() => [MJAIPromptModel_])
2794
3497
  async MJ_AIPromptModels_ConfigurationIDArray(@Root() mjaiconfiguration_: MJAIConfiguration_, @Ctx() { dataSources, userPayload, providers }: AppContext, @PubSub() pubSub: PubSubEngine) {
2795
3498
  this.CheckUserReadPermissions('MJ: AI Prompt Models', userPayload);
@@ -3126,6 +3829,9 @@ if this limit is exceeded.`})
3126
3829
  @Field(() => [MJAIAgentExample_])
3127
3830
  MJ_AIAgentExamples_AgentIDArray: MJAIAgentExample_[]; // Link to MJ_AIAgentExamples
3128
3831
 
3832
+ @Field(() => [MJAIAgentConfiguration_])
3833
+ MJ_AIAgentConfigurations_AgentIDArray: MJAIAgentConfiguration_[]; // Link to MJ_AIAgentConfigurations
3834
+
3129
3835
  @Field(() => [MJAIResultCache_])
3130
3836
  AIResultCache_AgentIDArray: MJAIResultCache_[]; // Link to AIResultCache
3131
3837
 
@@ -3690,6 +4396,17 @@ export class MJAIAgentResolver extends ResolverBase {
3690
4396
  return result;
3691
4397
  }
3692
4398
 
4399
+ @FieldResolver(() => [MJAIAgentConfiguration_])
4400
+ async MJ_AIAgentConfigurations_AgentIDArray(@Root() mjaiagent_: MJAIAgent_, @Ctx() { dataSources, userPayload, providers }: AppContext, @PubSub() pubSub: PubSubEngine) {
4401
+ this.CheckUserReadPermissions('MJ: AI Agent Configurations', userPayload);
4402
+ const provider = GetReadOnlyProvider(providers, { allowFallbackToReadWrite: true });
4403
+ const connPool = GetReadOnlyDataSource(dataSources, { allowFallbackToReadWrite: true });
4404
+ const sSQL = `SELECT * FROM [${Metadata.Provider.ConfigData.MJCoreSchemaName}].[vwAIAgentConfigurations] WHERE [AgentID]='${mjaiagent_.ID}' ` + this.getRowLevelSecurityWhereClause(provider, 'MJ: AI Agent Configurations', userPayload, EntityPermissionType.Read, 'AND');
4405
+ const rows = await SQLServerDataProvider.ExecuteSQLWithPool(connPool, sSQL, undefined, this.GetUserFromPayload(userPayload));
4406
+ const result = this.ArrayMapFieldNamesToCodeNames('MJ: AI Agent Configurations', rows);
4407
+ return result;
4408
+ }
4409
+
3693
4410
  @FieldResolver(() => [MJAIResultCache_])
3694
4411
  async AIResultCache_AgentIDArray(@Root() mjaiagent_: MJAIAgent_, @Ctx() { dataSources, userPayload, providers }: AppContext, @PubSub() pubSub: PubSubEngine) {
3695
4412
  this.CheckUserReadPermissions('AI Result Cache', userPayload);
@@ -4868,6 +5585,403 @@ export class MJAIAgentTypeResolver extends ResolverBase {
4868
5585
 
4869
5586
  }
4870
5587
 
5588
+ //****************************************************************************
5589
+ // ENTITY CLASS for MJ: AI Agent Configurations
5590
+ //****************************************************************************
5591
+ @ObjectType({ description: `Defines semantic configuration presets for agents, allowing users to select between different AI model configurations (e.g., Fast, Balanced, High Quality) when executing an agent. Each preset maps to an AI Configuration which controls model selection across all prompts.` })
5592
+ export class MJAIAgentConfiguration_ {
5593
+ @Field({description: `Primary Key - Unique identifier for the agent configuration preset`})
5594
+ @MaxLength(16)
5595
+ ID: string;
5596
+
5597
+ @Field({description: `Foreign Key - The agent this configuration preset belongs to`})
5598
+ @MaxLength(16)
5599
+ AgentID: string;
5600
+
5601
+ @Field({description: `Code-friendly name for the preset (e.g., HighPower, Fast, Balanced). Used in API calls and metadata references.`})
5602
+ @MaxLength(200)
5603
+ Name: string;
5604
+
5605
+ @Field({description: `User-friendly display name shown in UI (e.g., "High Quality", "Quick Draft", "Maximum Detail")`})
5606
+ @MaxLength(400)
5607
+ DisplayName: string;
5608
+
5609
+ @Field({nullable: true, description: `Description shown to users explaining what this configuration does (e.g., "Uses Claude Opus for highest quality results")`})
5610
+ Description?: string;
5611
+
5612
+ @Field({nullable: true, description: `Foreign Key - Optional AI Configuration to use for this preset. If NULL, uses default configuration (prompts with ConfigurationID IS NULL)`})
5613
+ @MaxLength(16)
5614
+ AIConfigurationID?: string;
5615
+
5616
+ @Field(() => Boolean, {description: `Whether this is the default preset for the agent. Should have exactly one default per agent.`})
5617
+ IsDefault: boolean;
5618
+
5619
+ @Field(() => Int, {description: `Display order for UI. Lower numbers appear first. Typical values: 100 (Default), 200 (Fast), 300 (Balanced), 400 (High Quality)`})
5620
+ Priority: number;
5621
+
5622
+ @Field({description: `Status of the preset: Pending (being configured), Active (available for use), Revoked (no longer available)`})
5623
+ @MaxLength(40)
5624
+ Status: string;
5625
+
5626
+ @Field()
5627
+ @MaxLength(10)
5628
+ _mj__CreatedAt: Date;
5629
+
5630
+ @Field()
5631
+ @MaxLength(10)
5632
+ _mj__UpdatedAt: Date;
5633
+
5634
+ @Field({nullable: true})
5635
+ @MaxLength(510)
5636
+ Agent?: string;
5637
+
5638
+ @Field({nullable: true})
5639
+ @MaxLength(200)
5640
+ AIConfiguration?: string;
5641
+
5642
+ }
5643
+
5644
+ //****************************************************************************
5645
+ // INPUT TYPE for MJ: AI Agent Configurations
5646
+ //****************************************************************************
5647
+ @InputType()
5648
+ export class CreateMJAIAgentConfigurationInput {
5649
+ @Field({ nullable: true })
5650
+ ID?: string;
5651
+
5652
+ @Field({ nullable: true })
5653
+ AgentID?: string;
5654
+
5655
+ @Field({ nullable: true })
5656
+ Name?: string;
5657
+
5658
+ @Field({ nullable: true })
5659
+ DisplayName?: string;
5660
+
5661
+ @Field({ nullable: true })
5662
+ Description: string | null;
5663
+
5664
+ @Field({ nullable: true })
5665
+ AIConfigurationID: string | null;
5666
+
5667
+ @Field(() => Boolean, { nullable: true })
5668
+ IsDefault?: boolean;
5669
+
5670
+ @Field(() => Int, { nullable: true })
5671
+ Priority?: number;
5672
+
5673
+ @Field({ nullable: true })
5674
+ Status?: string;
5675
+ }
5676
+
5677
+
5678
+ //****************************************************************************
5679
+ // INPUT TYPE for MJ: AI Agent Configurations
5680
+ //****************************************************************************
5681
+ @InputType()
5682
+ export class UpdateMJAIAgentConfigurationInput {
5683
+ @Field()
5684
+ ID: string;
5685
+
5686
+ @Field({ nullable: true })
5687
+ AgentID?: string;
5688
+
5689
+ @Field({ nullable: true })
5690
+ Name?: string;
5691
+
5692
+ @Field({ nullable: true })
5693
+ DisplayName?: string;
5694
+
5695
+ @Field({ nullable: true })
5696
+ Description?: string | null;
5697
+
5698
+ @Field({ nullable: true })
5699
+ AIConfigurationID?: string | null;
5700
+
5701
+ @Field(() => Boolean, { nullable: true })
5702
+ IsDefault?: boolean;
5703
+
5704
+ @Field(() => Int, { nullable: true })
5705
+ Priority?: number;
5706
+
5707
+ @Field({ nullable: true })
5708
+ Status?: string;
5709
+
5710
+ @Field(() => [KeyValuePairInput], { nullable: true })
5711
+ OldValues___?: KeyValuePairInput[];
5712
+ }
5713
+
5714
+ //****************************************************************************
5715
+ // RESOLVER for MJ: AI Agent Configurations
5716
+ //****************************************************************************
5717
+ @ObjectType()
5718
+ export class RunMJAIAgentConfigurationViewResult {
5719
+ @Field(() => [MJAIAgentConfiguration_])
5720
+ Results: MJAIAgentConfiguration_[];
5721
+
5722
+ @Field(() => String, {nullable: true})
5723
+ UserViewRunID?: string;
5724
+
5725
+ @Field(() => Int, {nullable: true})
5726
+ RowCount: number;
5727
+
5728
+ @Field(() => Int, {nullable: true})
5729
+ TotalRowCount: number;
5730
+
5731
+ @Field(() => Int, {nullable: true})
5732
+ ExecutionTime: number;
5733
+
5734
+ @Field({nullable: true})
5735
+ ErrorMessage?: string;
5736
+
5737
+ @Field(() => Boolean, {nullable: false})
5738
+ Success: boolean;
5739
+ }
5740
+
5741
+ @Resolver(MJAIAgentConfiguration_)
5742
+ export class MJAIAgentConfigurationResolver extends ResolverBase {
5743
+ @Query(() => RunMJAIAgentConfigurationViewResult)
5744
+ async RunMJAIAgentConfigurationViewByID(@Arg('input', () => RunViewByIDInput) input: RunViewByIDInput, @Ctx() { providers, userPayload }: AppContext, @PubSub() pubSub: PubSubEngine) {
5745
+ const provider = GetReadOnlyProvider(providers, { allowFallbackToReadWrite: true });
5746
+ return super.RunViewByIDGeneric(input, provider, userPayload, pubSub);
5747
+ }
5748
+
5749
+ @Query(() => RunMJAIAgentConfigurationViewResult)
5750
+ async RunMJAIAgentConfigurationViewByName(@Arg('input', () => RunViewByNameInput) input: RunViewByNameInput, @Ctx() { providers, userPayload }: AppContext, @PubSub() pubSub: PubSubEngine) {
5751
+ const provider = GetReadOnlyProvider(providers, { allowFallbackToReadWrite: true });
5752
+ return super.RunViewByNameGeneric(input, provider, userPayload, pubSub);
5753
+ }
5754
+
5755
+ @Query(() => RunMJAIAgentConfigurationViewResult)
5756
+ async RunMJAIAgentConfigurationDynamicView(@Arg('input', () => RunDynamicViewInput) input: RunDynamicViewInput, @Ctx() { providers, userPayload }: AppContext, @PubSub() pubSub: PubSubEngine) {
5757
+ const provider = GetReadOnlyProvider(providers, { allowFallbackToReadWrite: true });
5758
+ input.EntityName = 'MJ: AI Agent Configurations';
5759
+ return super.RunDynamicViewGeneric(input, provider, userPayload, pubSub);
5760
+ }
5761
+ @Query(() => MJAIAgentConfiguration_, { nullable: true })
5762
+ async MJAIAgentConfiguration(@Arg('ID', () => String) ID: string, @Ctx() { dataSources, userPayload, providers }: AppContext, @PubSub() pubSub: PubSubEngine): Promise<MJAIAgentConfiguration_ | null> {
5763
+ this.CheckUserReadPermissions('MJ: AI Agent Configurations', userPayload);
5764
+ const provider = GetReadOnlyProvider(providers, { allowFallbackToReadWrite: true });
5765
+ const connPool = GetReadOnlyDataSource(dataSources, { allowFallbackToReadWrite: true });
5766
+ const sSQL = `SELECT * FROM [${Metadata.Provider.ConfigData.MJCoreSchemaName}].[vwAIAgentConfigurations] WHERE [ID]='${ID}' ` + this.getRowLevelSecurityWhereClause(provider, 'MJ: AI Agent Configurations', userPayload, EntityPermissionType.Read, 'AND');
5767
+ const rows = await SQLServerDataProvider.ExecuteSQLWithPool(connPool, sSQL, undefined, this.GetUserFromPayload(userPayload));
5768
+ const result = this.MapFieldNamesToCodeNames('MJ: AI Agent Configurations', rows && rows.length > 0 ? rows[0] : {})
5769
+ return result;
5770
+ }
5771
+
5772
+ @Mutation(() => MJAIAgentConfiguration_)
5773
+ async CreateMJAIAgentConfiguration(
5774
+ @Arg('input', () => CreateMJAIAgentConfigurationInput) input: CreateMJAIAgentConfigurationInput,
5775
+ @Ctx() { providers, userPayload }: AppContext,
5776
+ @PubSub() pubSub: PubSubEngine
5777
+ ) {
5778
+ const provider = GetReadWriteProvider(providers);
5779
+ return this.CreateRecord('MJ: AI Agent Configurations', input, provider, userPayload, pubSub)
5780
+ }
5781
+
5782
+ @Mutation(() => MJAIAgentConfiguration_)
5783
+ async UpdateMJAIAgentConfiguration(
5784
+ @Arg('input', () => UpdateMJAIAgentConfigurationInput) input: UpdateMJAIAgentConfigurationInput,
5785
+ @Ctx() { providers, userPayload }: AppContext,
5786
+ @PubSub() pubSub: PubSubEngine
5787
+ ) {
5788
+ const provider = GetReadWriteProvider(providers);
5789
+ return this.UpdateRecord('MJ: AI Agent Configurations', input, provider, userPayload, pubSub);
5790
+ }
5791
+
5792
+ @Mutation(() => MJAIAgentConfiguration_)
5793
+ async DeleteMJAIAgentConfiguration(@Arg('ID', () => String) ID: string, @Arg('options___', () => DeleteOptionsInput) options: DeleteOptionsInput, @Ctx() { providers, userPayload }: AppContext, @PubSub() pubSub: PubSubEngine) {
5794
+ const provider = GetReadWriteProvider(providers);
5795
+ const key = new CompositeKey([{FieldName: 'ID', Value: ID}]);
5796
+ return this.DeleteRecord('MJ: AI Agent Configurations', key, options, provider, userPayload, pubSub);
5797
+ }
5798
+
5799
+ }
5800
+
5801
+ //****************************************************************************
5802
+ // ENTITY CLASS for MJ: Test Suite Tests
5803
+ //****************************************************************************
5804
+ @ObjectType({ description: `Junction table linking tests to test suites. Allows many-to-many relationship where a test can belong to multiple suites and a suite can contain multiple tests. Includes sequence for execution order and configuration overrides specific to this suite-test pairing.` })
5805
+ export class MJTestSuiteTest_ {
5806
+ @Field()
5807
+ @MaxLength(16)
5808
+ ID: string;
5809
+
5810
+ @Field({description: `Foreign Key - The test suite this relationship belongs to`})
5811
+ @MaxLength(16)
5812
+ SuiteID: string;
5813
+
5814
+ @Field({description: `Foreign Key - The test included in this suite`})
5815
+ @MaxLength(16)
5816
+ TestID: string;
5817
+
5818
+ @Field(() => Int, {description: `Execution sequence within the suite. Lower numbers run first. Tests with same sequence may run in parallel.`})
5819
+ Sequence: number;
5820
+
5821
+ @Field({description: `Status of this test within this suite: Active (will run), Disabled (temporarily excluded), Skip (documented exclusion)`})
5822
+ @MaxLength(40)
5823
+ Status: string;
5824
+
5825
+ @Field({nullable: true, description: `JSON object to override test configuration for this specific suite. Allows same test to run with different parameters in different suites.`})
5826
+ Configuration?: string;
5827
+
5828
+ @Field()
5829
+ @MaxLength(10)
5830
+ _mj__CreatedAt: Date;
5831
+
5832
+ @Field()
5833
+ @MaxLength(10)
5834
+ _mj__UpdatedAt: Date;
5835
+
5836
+ @Field()
5837
+ @MaxLength(510)
5838
+ Suite: string;
5839
+
5840
+ @Field()
5841
+ @MaxLength(510)
5842
+ Test: string;
5843
+
5844
+ }
5845
+
5846
+ //****************************************************************************
5847
+ // INPUT TYPE for MJ: Test Suite Tests
5848
+ //****************************************************************************
5849
+ @InputType()
5850
+ export class CreateMJTestSuiteTestInput {
5851
+ @Field({ nullable: true })
5852
+ ID?: string;
5853
+
5854
+ @Field({ nullable: true })
5855
+ SuiteID?: string;
5856
+
5857
+ @Field({ nullable: true })
5858
+ TestID?: string;
5859
+
5860
+ @Field(() => Int, { nullable: true })
5861
+ Sequence?: number;
5862
+
5863
+ @Field({ nullable: true })
5864
+ Status?: string;
5865
+
5866
+ @Field({ nullable: true })
5867
+ Configuration: string | null;
5868
+ }
5869
+
5870
+
5871
+ //****************************************************************************
5872
+ // INPUT TYPE for MJ: Test Suite Tests
5873
+ //****************************************************************************
5874
+ @InputType()
5875
+ export class UpdateMJTestSuiteTestInput {
5876
+ @Field()
5877
+ ID: string;
5878
+
5879
+ @Field({ nullable: true })
5880
+ SuiteID?: string;
5881
+
5882
+ @Field({ nullable: true })
5883
+ TestID?: string;
5884
+
5885
+ @Field(() => Int, { nullable: true })
5886
+ Sequence?: number;
5887
+
5888
+ @Field({ nullable: true })
5889
+ Status?: string;
5890
+
5891
+ @Field({ nullable: true })
5892
+ Configuration?: string | null;
5893
+
5894
+ @Field(() => [KeyValuePairInput], { nullable: true })
5895
+ OldValues___?: KeyValuePairInput[];
5896
+ }
5897
+
5898
+ //****************************************************************************
5899
+ // RESOLVER for MJ: Test Suite Tests
5900
+ //****************************************************************************
5901
+ @ObjectType()
5902
+ export class RunMJTestSuiteTestViewResult {
5903
+ @Field(() => [MJTestSuiteTest_])
5904
+ Results: MJTestSuiteTest_[];
5905
+
5906
+ @Field(() => String, {nullable: true})
5907
+ UserViewRunID?: string;
5908
+
5909
+ @Field(() => Int, {nullable: true})
5910
+ RowCount: number;
5911
+
5912
+ @Field(() => Int, {nullable: true})
5913
+ TotalRowCount: number;
5914
+
5915
+ @Field(() => Int, {nullable: true})
5916
+ ExecutionTime: number;
5917
+
5918
+ @Field({nullable: true})
5919
+ ErrorMessage?: string;
5920
+
5921
+ @Field(() => Boolean, {nullable: false})
5922
+ Success: boolean;
5923
+ }
5924
+
5925
+ @Resolver(MJTestSuiteTest_)
5926
+ export class MJTestSuiteTestResolver extends ResolverBase {
5927
+ @Query(() => RunMJTestSuiteTestViewResult)
5928
+ async RunMJTestSuiteTestViewByID(@Arg('input', () => RunViewByIDInput) input: RunViewByIDInput, @Ctx() { providers, userPayload }: AppContext, @PubSub() pubSub: PubSubEngine) {
5929
+ const provider = GetReadOnlyProvider(providers, { allowFallbackToReadWrite: true });
5930
+ return super.RunViewByIDGeneric(input, provider, userPayload, pubSub);
5931
+ }
5932
+
5933
+ @Query(() => RunMJTestSuiteTestViewResult)
5934
+ async RunMJTestSuiteTestViewByName(@Arg('input', () => RunViewByNameInput) input: RunViewByNameInput, @Ctx() { providers, userPayload }: AppContext, @PubSub() pubSub: PubSubEngine) {
5935
+ const provider = GetReadOnlyProvider(providers, { allowFallbackToReadWrite: true });
5936
+ return super.RunViewByNameGeneric(input, provider, userPayload, pubSub);
5937
+ }
5938
+
5939
+ @Query(() => RunMJTestSuiteTestViewResult)
5940
+ async RunMJTestSuiteTestDynamicView(@Arg('input', () => RunDynamicViewInput) input: RunDynamicViewInput, @Ctx() { providers, userPayload }: AppContext, @PubSub() pubSub: PubSubEngine) {
5941
+ const provider = GetReadOnlyProvider(providers, { allowFallbackToReadWrite: true });
5942
+ input.EntityName = 'MJ: Test Suite Tests';
5943
+ return super.RunDynamicViewGeneric(input, provider, userPayload, pubSub);
5944
+ }
5945
+ @Query(() => MJTestSuiteTest_, { nullable: true })
5946
+ async MJTestSuiteTest(@Arg('ID', () => String) ID: string, @Ctx() { dataSources, userPayload, providers }: AppContext, @PubSub() pubSub: PubSubEngine): Promise<MJTestSuiteTest_ | null> {
5947
+ this.CheckUserReadPermissions('MJ: Test Suite Tests', userPayload);
5948
+ const provider = GetReadOnlyProvider(providers, { allowFallbackToReadWrite: true });
5949
+ const connPool = GetReadOnlyDataSource(dataSources, { allowFallbackToReadWrite: true });
5950
+ const sSQL = `SELECT * FROM [${Metadata.Provider.ConfigData.MJCoreSchemaName}].[vwTestSuiteTests] WHERE [ID]='${ID}' ` + this.getRowLevelSecurityWhereClause(provider, 'MJ: Test Suite Tests', userPayload, EntityPermissionType.Read, 'AND');
5951
+ const rows = await SQLServerDataProvider.ExecuteSQLWithPool(connPool, sSQL, undefined, this.GetUserFromPayload(userPayload));
5952
+ const result = this.MapFieldNamesToCodeNames('MJ: Test Suite Tests', rows && rows.length > 0 ? rows[0] : {})
5953
+ return result;
5954
+ }
5955
+
5956
+ @Mutation(() => MJTestSuiteTest_)
5957
+ async CreateMJTestSuiteTest(
5958
+ @Arg('input', () => CreateMJTestSuiteTestInput) input: CreateMJTestSuiteTestInput,
5959
+ @Ctx() { providers, userPayload }: AppContext,
5960
+ @PubSub() pubSub: PubSubEngine
5961
+ ) {
5962
+ const provider = GetReadWriteProvider(providers);
5963
+ return this.CreateRecord('MJ: Test Suite Tests', input, provider, userPayload, pubSub)
5964
+ }
5965
+
5966
+ @Mutation(() => MJTestSuiteTest_)
5967
+ async UpdateMJTestSuiteTest(
5968
+ @Arg('input', () => UpdateMJTestSuiteTestInput) input: UpdateMJTestSuiteTestInput,
5969
+ @Ctx() { providers, userPayload }: AppContext,
5970
+ @PubSub() pubSub: PubSubEngine
5971
+ ) {
5972
+ const provider = GetReadWriteProvider(providers);
5973
+ return this.UpdateRecord('MJ: Test Suite Tests', input, provider, userPayload, pubSub);
5974
+ }
5975
+
5976
+ @Mutation(() => MJTestSuiteTest_)
5977
+ async DeleteMJTestSuiteTest(@Arg('ID', () => String) ID: string, @Arg('options___', () => DeleteOptionsInput) options: DeleteOptionsInput, @Ctx() { providers, userPayload }: AppContext, @PubSub() pubSub: PubSubEngine) {
5978
+ const provider = GetReadWriteProvider(providers);
5979
+ const key = new CompositeKey([{FieldName: 'ID', Value: ID}]);
5980
+ return this.DeleteRecord('MJ: Test Suite Tests', key, options, provider, userPayload, pubSub);
5981
+ }
5982
+
5983
+ }
5984
+
4871
5985
  //****************************************************************************
4872
5986
  // ENTITY CLASS for AI Agent Notes
4873
5987
  //****************************************************************************
@@ -5186,21 +6300,21 @@ export class MJEnvironment_ {
5186
6300
  @MaxLength(10)
5187
6301
  _mj__UpdatedAt: Date;
5188
6302
 
5189
- @Field(() => [MJCollection_])
5190
- MJ_Collections_EnvironmentIDArray: MJCollection_[]; // Link to MJ_Collections
5191
-
5192
6303
  @Field(() => [MJProject_])
5193
6304
  MJ_Projects_EnvironmentIDArray: MJProject_[]; // Link to MJ_Projects
5194
6305
 
6306
+ @Field(() => [MJCollection_])
6307
+ MJ_Collections_EnvironmentIDArray: MJCollection_[]; // Link to MJ_Collections
6308
+
5195
6309
  @Field(() => [MJArtifact_])
5196
6310
  MJ_Artifacts_EnvironmentIDArray: MJArtifact_[]; // Link to MJ_Artifacts
5197
6311
 
5198
- @Field(() => [MJDashboard_])
5199
- Dashboards_EnvironmentIDArray: MJDashboard_[]; // Link to Dashboards
5200
-
5201
6312
  @Field(() => [MJTask_])
5202
6313
  MJ_Tasks_EnvironmentIDArray: MJTask_[]; // Link to MJ_Tasks
5203
6314
 
6315
+ @Field(() => [MJDashboard_])
6316
+ Dashboards_EnvironmentIDArray: MJDashboard_[]; // Link to Dashboards
6317
+
5204
6318
  @Field(() => [MJReport_])
5205
6319
  Reports_EnvironmentIDArray: MJReport_[]; // Link to Reports
5206
6320
 
@@ -5313,25 +6427,25 @@ export class MJEnvironmentResolver extends ResolverBase {
5313
6427
  return result;
5314
6428
  }
5315
6429
 
5316
- @FieldResolver(() => [MJCollection_])
5317
- async MJ_Collections_EnvironmentIDArray(@Root() mjenvironment_: MJEnvironment_, @Ctx() { dataSources, userPayload, providers }: AppContext, @PubSub() pubSub: PubSubEngine) {
5318
- this.CheckUserReadPermissions('MJ: Collections', userPayload);
6430
+ @FieldResolver(() => [MJProject_])
6431
+ async MJ_Projects_EnvironmentIDArray(@Root() mjenvironment_: MJEnvironment_, @Ctx() { dataSources, userPayload, providers }: AppContext, @PubSub() pubSub: PubSubEngine) {
6432
+ this.CheckUserReadPermissions('MJ: Projects', userPayload);
5319
6433
  const provider = GetReadOnlyProvider(providers, { allowFallbackToReadWrite: true });
5320
6434
  const connPool = GetReadOnlyDataSource(dataSources, { allowFallbackToReadWrite: true });
5321
- const sSQL = `SELECT * FROM [${Metadata.Provider.ConfigData.MJCoreSchemaName}].[vwCollections] WHERE [EnvironmentID]='${mjenvironment_.ID}' ` + this.getRowLevelSecurityWhereClause(provider, 'MJ: Collections', userPayload, EntityPermissionType.Read, 'AND');
6435
+ const sSQL = `SELECT * FROM [${Metadata.Provider.ConfigData.MJCoreSchemaName}].[vwProjects] WHERE [EnvironmentID]='${mjenvironment_.ID}' ` + this.getRowLevelSecurityWhereClause(provider, 'MJ: Projects', userPayload, EntityPermissionType.Read, 'AND');
5322
6436
  const rows = await SQLServerDataProvider.ExecuteSQLWithPool(connPool, sSQL, undefined, this.GetUserFromPayload(userPayload));
5323
- const result = this.ArrayMapFieldNamesToCodeNames('MJ: Collections', rows);
6437
+ const result = this.ArrayMapFieldNamesToCodeNames('MJ: Projects', rows);
5324
6438
  return result;
5325
6439
  }
5326
6440
 
5327
- @FieldResolver(() => [MJProject_])
5328
- async MJ_Projects_EnvironmentIDArray(@Root() mjenvironment_: MJEnvironment_, @Ctx() { dataSources, userPayload, providers }: AppContext, @PubSub() pubSub: PubSubEngine) {
5329
- this.CheckUserReadPermissions('MJ: Projects', userPayload);
6441
+ @FieldResolver(() => [MJCollection_])
6442
+ async MJ_Collections_EnvironmentIDArray(@Root() mjenvironment_: MJEnvironment_, @Ctx() { dataSources, userPayload, providers }: AppContext, @PubSub() pubSub: PubSubEngine) {
6443
+ this.CheckUserReadPermissions('MJ: Collections', userPayload);
5330
6444
  const provider = GetReadOnlyProvider(providers, { allowFallbackToReadWrite: true });
5331
6445
  const connPool = GetReadOnlyDataSource(dataSources, { allowFallbackToReadWrite: true });
5332
- const sSQL = `SELECT * FROM [${Metadata.Provider.ConfigData.MJCoreSchemaName}].[vwProjects] WHERE [EnvironmentID]='${mjenvironment_.ID}' ` + this.getRowLevelSecurityWhereClause(provider, 'MJ: Projects', userPayload, EntityPermissionType.Read, 'AND');
6446
+ const sSQL = `SELECT * FROM [${Metadata.Provider.ConfigData.MJCoreSchemaName}].[vwCollections] WHERE [EnvironmentID]='${mjenvironment_.ID}' ` + this.getRowLevelSecurityWhereClause(provider, 'MJ: Collections', userPayload, EntityPermissionType.Read, 'AND');
5333
6447
  const rows = await SQLServerDataProvider.ExecuteSQLWithPool(connPool, sSQL, undefined, this.GetUserFromPayload(userPayload));
5334
- const result = this.ArrayMapFieldNamesToCodeNames('MJ: Projects', rows);
6448
+ const result = this.ArrayMapFieldNamesToCodeNames('MJ: Collections', rows);
5335
6449
  return result;
5336
6450
  }
5337
6451
 
@@ -5346,25 +6460,25 @@ export class MJEnvironmentResolver extends ResolverBase {
5346
6460
  return result;
5347
6461
  }
5348
6462
 
5349
- @FieldResolver(() => [MJDashboard_])
5350
- async Dashboards_EnvironmentIDArray(@Root() mjenvironment_: MJEnvironment_, @Ctx() { dataSources, userPayload, providers }: AppContext, @PubSub() pubSub: PubSubEngine) {
5351
- this.CheckUserReadPermissions('Dashboards', userPayload);
6463
+ @FieldResolver(() => [MJTask_])
6464
+ async MJ_Tasks_EnvironmentIDArray(@Root() mjenvironment_: MJEnvironment_, @Ctx() { dataSources, userPayload, providers }: AppContext, @PubSub() pubSub: PubSubEngine) {
6465
+ this.CheckUserReadPermissions('MJ: Tasks', userPayload);
5352
6466
  const provider = GetReadOnlyProvider(providers, { allowFallbackToReadWrite: true });
5353
6467
  const connPool = GetReadOnlyDataSource(dataSources, { allowFallbackToReadWrite: true });
5354
- const sSQL = `SELECT * FROM [${Metadata.Provider.ConfigData.MJCoreSchemaName}].[vwDashboards] WHERE [EnvironmentID]='${mjenvironment_.ID}' ` + this.getRowLevelSecurityWhereClause(provider, 'Dashboards', userPayload, EntityPermissionType.Read, 'AND');
6468
+ const sSQL = `SELECT * FROM [${Metadata.Provider.ConfigData.MJCoreSchemaName}].[vwTasks] WHERE [EnvironmentID]='${mjenvironment_.ID}' ` + this.getRowLevelSecurityWhereClause(provider, 'MJ: Tasks', userPayload, EntityPermissionType.Read, 'AND');
5355
6469
  const rows = await SQLServerDataProvider.ExecuteSQLWithPool(connPool, sSQL, undefined, this.GetUserFromPayload(userPayload));
5356
- const result = this.ArrayMapFieldNamesToCodeNames('Dashboards', rows);
6470
+ const result = this.ArrayMapFieldNamesToCodeNames('MJ: Tasks', rows);
5357
6471
  return result;
5358
6472
  }
5359
6473
 
5360
- @FieldResolver(() => [MJTask_])
5361
- async MJ_Tasks_EnvironmentIDArray(@Root() mjenvironment_: MJEnvironment_, @Ctx() { dataSources, userPayload, providers }: AppContext, @PubSub() pubSub: PubSubEngine) {
5362
- this.CheckUserReadPermissions('MJ: Tasks', userPayload);
6474
+ @FieldResolver(() => [MJDashboard_])
6475
+ async Dashboards_EnvironmentIDArray(@Root() mjenvironment_: MJEnvironment_, @Ctx() { dataSources, userPayload, providers }: AppContext, @PubSub() pubSub: PubSubEngine) {
6476
+ this.CheckUserReadPermissions('Dashboards', userPayload);
5363
6477
  const provider = GetReadOnlyProvider(providers, { allowFallbackToReadWrite: true });
5364
6478
  const connPool = GetReadOnlyDataSource(dataSources, { allowFallbackToReadWrite: true });
5365
- const sSQL = `SELECT * FROM [${Metadata.Provider.ConfigData.MJCoreSchemaName}].[vwTasks] WHERE [EnvironmentID]='${mjenvironment_.ID}' ` + this.getRowLevelSecurityWhereClause(provider, 'MJ: Tasks', userPayload, EntityPermissionType.Read, 'AND');
6479
+ const sSQL = `SELECT * FROM [${Metadata.Provider.ConfigData.MJCoreSchemaName}].[vwDashboards] WHERE [EnvironmentID]='${mjenvironment_.ID}' ` + this.getRowLevelSecurityWhereClause(provider, 'Dashboards', userPayload, EntityPermissionType.Read, 'AND');
5366
6480
  const rows = await SQLServerDataProvider.ExecuteSQLWithPool(connPool, sSQL, undefined, this.GetUserFromPayload(userPayload));
5367
- const result = this.ArrayMapFieldNamesToCodeNames('MJ: Tasks', rows);
6481
+ const result = this.ArrayMapFieldNamesToCodeNames('Dashboards', rows);
5368
6482
  return result;
5369
6483
  }
5370
6484
 
@@ -5861,6 +6975,205 @@ export class MJAIAgentActionResolver extends ResolverBase {
5861
6975
 
5862
6976
  }
5863
6977
 
6978
+ //****************************************************************************
6979
+ // ENTITY CLASS for MJ: Test Rubrics
6980
+ //****************************************************************************
6981
+ @ObjectType({ description: `Reusable evaluation criteria (rubrics) for consistent scoring across tests. Rubrics define structured evaluation dimensions and can include LLM prompts for automated judgment. Particularly useful for LLM-as-judge patterns where consistent evaluation criteria are critical.` })
6982
+ export class MJTestRubric_ {
6983
+ @Field()
6984
+ @MaxLength(16)
6985
+ ID: string;
6986
+
6987
+ @Field({description: `Foreign Key - The test type this rubric applies to (e.g., Agent Eval, Code Generation)`})
6988
+ @MaxLength(16)
6989
+ TypeID: string;
6990
+
6991
+ @Field({description: `Unique name for the rubric (e.g., "Component Quality Rubric v1", "Agent Response Quality")`})
6992
+ @MaxLength(510)
6993
+ Name: string;
6994
+
6995
+ @Field({nullable: true, description: `Description of what this rubric evaluates and when to use it`})
6996
+ Description?: string;
6997
+
6998
+ @Field({nullable: true, description: `LLM prompt template for automated judgment. Can include placeholders for test inputs/outputs (e.g., "Evaluate the following React component for correctness, UX, and maintainability...")`})
6999
+ PromptTemplate?: string;
7000
+
7001
+ @Field({nullable: true, description: `JSON object defining structured evaluation criteria with dimensions, weights, and scoring guidance (e.g., {correctness: {weight: 0.4, description: "..."}, ux: {weight: 0.3, description: "..."}})`})
7002
+ Criteria?: string;
7003
+
7004
+ @Field({nullable: true, description: `Version identifier for the rubric. Allows tracking changes and comparing results across rubric versions.`})
7005
+ @MaxLength(100)
7006
+ Version?: string;
7007
+
7008
+ @Field({description: `Status of the rubric: Pending (under development), Active (available for use), Disabled (deprecated)`})
7009
+ @MaxLength(40)
7010
+ Status: string;
7011
+
7012
+ @Field()
7013
+ @MaxLength(10)
7014
+ _mj__CreatedAt: Date;
7015
+
7016
+ @Field()
7017
+ @MaxLength(10)
7018
+ _mj__UpdatedAt: Date;
7019
+
7020
+ @Field()
7021
+ @MaxLength(200)
7022
+ Type: string;
7023
+
7024
+ }
7025
+
7026
+ //****************************************************************************
7027
+ // INPUT TYPE for MJ: Test Rubrics
7028
+ //****************************************************************************
7029
+ @InputType()
7030
+ export class CreateMJTestRubricInput {
7031
+ @Field({ nullable: true })
7032
+ ID?: string;
7033
+
7034
+ @Field({ nullable: true })
7035
+ TypeID?: string;
7036
+
7037
+ @Field({ nullable: true })
7038
+ Name?: string;
7039
+
7040
+ @Field({ nullable: true })
7041
+ Description: string | null;
7042
+
7043
+ @Field({ nullable: true })
7044
+ PromptTemplate: string | null;
7045
+
7046
+ @Field({ nullable: true })
7047
+ Criteria: string | null;
7048
+
7049
+ @Field({ nullable: true })
7050
+ Version: string | null;
7051
+
7052
+ @Field({ nullable: true })
7053
+ Status?: string;
7054
+ }
7055
+
7056
+
7057
+ //****************************************************************************
7058
+ // INPUT TYPE for MJ: Test Rubrics
7059
+ //****************************************************************************
7060
+ @InputType()
7061
+ export class UpdateMJTestRubricInput {
7062
+ @Field()
7063
+ ID: string;
7064
+
7065
+ @Field({ nullable: true })
7066
+ TypeID?: string;
7067
+
7068
+ @Field({ nullable: true })
7069
+ Name?: string;
7070
+
7071
+ @Field({ nullable: true })
7072
+ Description?: string | null;
7073
+
7074
+ @Field({ nullable: true })
7075
+ PromptTemplate?: string | null;
7076
+
7077
+ @Field({ nullable: true })
7078
+ Criteria?: string | null;
7079
+
7080
+ @Field({ nullable: true })
7081
+ Version?: string | null;
7082
+
7083
+ @Field({ nullable: true })
7084
+ Status?: string;
7085
+
7086
+ @Field(() => [KeyValuePairInput], { nullable: true })
7087
+ OldValues___?: KeyValuePairInput[];
7088
+ }
7089
+
7090
+ //****************************************************************************
7091
+ // RESOLVER for MJ: Test Rubrics
7092
+ //****************************************************************************
7093
+ @ObjectType()
7094
+ export class RunMJTestRubricViewResult {
7095
+ @Field(() => [MJTestRubric_])
7096
+ Results: MJTestRubric_[];
7097
+
7098
+ @Field(() => String, {nullable: true})
7099
+ UserViewRunID?: string;
7100
+
7101
+ @Field(() => Int, {nullable: true})
7102
+ RowCount: number;
7103
+
7104
+ @Field(() => Int, {nullable: true})
7105
+ TotalRowCount: number;
7106
+
7107
+ @Field(() => Int, {nullable: true})
7108
+ ExecutionTime: number;
7109
+
7110
+ @Field({nullable: true})
7111
+ ErrorMessage?: string;
7112
+
7113
+ @Field(() => Boolean, {nullable: false})
7114
+ Success: boolean;
7115
+ }
7116
+
7117
+ @Resolver(MJTestRubric_)
7118
+ export class MJTestRubricResolver extends ResolverBase {
7119
+ @Query(() => RunMJTestRubricViewResult)
7120
+ async RunMJTestRubricViewByID(@Arg('input', () => RunViewByIDInput) input: RunViewByIDInput, @Ctx() { providers, userPayload }: AppContext, @PubSub() pubSub: PubSubEngine) {
7121
+ const provider = GetReadOnlyProvider(providers, { allowFallbackToReadWrite: true });
7122
+ return super.RunViewByIDGeneric(input, provider, userPayload, pubSub);
7123
+ }
7124
+
7125
+ @Query(() => RunMJTestRubricViewResult)
7126
+ async RunMJTestRubricViewByName(@Arg('input', () => RunViewByNameInput) input: RunViewByNameInput, @Ctx() { providers, userPayload }: AppContext, @PubSub() pubSub: PubSubEngine) {
7127
+ const provider = GetReadOnlyProvider(providers, { allowFallbackToReadWrite: true });
7128
+ return super.RunViewByNameGeneric(input, provider, userPayload, pubSub);
7129
+ }
7130
+
7131
+ @Query(() => RunMJTestRubricViewResult)
7132
+ async RunMJTestRubricDynamicView(@Arg('input', () => RunDynamicViewInput) input: RunDynamicViewInput, @Ctx() { providers, userPayload }: AppContext, @PubSub() pubSub: PubSubEngine) {
7133
+ const provider = GetReadOnlyProvider(providers, { allowFallbackToReadWrite: true });
7134
+ input.EntityName = 'MJ: Test Rubrics';
7135
+ return super.RunDynamicViewGeneric(input, provider, userPayload, pubSub);
7136
+ }
7137
+ @Query(() => MJTestRubric_, { nullable: true })
7138
+ async MJTestRubric(@Arg('ID', () => String) ID: string, @Ctx() { dataSources, userPayload, providers }: AppContext, @PubSub() pubSub: PubSubEngine): Promise<MJTestRubric_ | null> {
7139
+ this.CheckUserReadPermissions('MJ: Test Rubrics', userPayload);
7140
+ const provider = GetReadOnlyProvider(providers, { allowFallbackToReadWrite: true });
7141
+ const connPool = GetReadOnlyDataSource(dataSources, { allowFallbackToReadWrite: true });
7142
+ const sSQL = `SELECT * FROM [${Metadata.Provider.ConfigData.MJCoreSchemaName}].[vwTestRubrics] WHERE [ID]='${ID}' ` + this.getRowLevelSecurityWhereClause(provider, 'MJ: Test Rubrics', userPayload, EntityPermissionType.Read, 'AND');
7143
+ const rows = await SQLServerDataProvider.ExecuteSQLWithPool(connPool, sSQL, undefined, this.GetUserFromPayload(userPayload));
7144
+ const result = this.MapFieldNamesToCodeNames('MJ: Test Rubrics', rows && rows.length > 0 ? rows[0] : {})
7145
+ return result;
7146
+ }
7147
+
7148
+ @Mutation(() => MJTestRubric_)
7149
+ async CreateMJTestRubric(
7150
+ @Arg('input', () => CreateMJTestRubricInput) input: CreateMJTestRubricInput,
7151
+ @Ctx() { providers, userPayload }: AppContext,
7152
+ @PubSub() pubSub: PubSubEngine
7153
+ ) {
7154
+ const provider = GetReadWriteProvider(providers);
7155
+ return this.CreateRecord('MJ: Test Rubrics', input, provider, userPayload, pubSub)
7156
+ }
7157
+
7158
+ @Mutation(() => MJTestRubric_)
7159
+ async UpdateMJTestRubric(
7160
+ @Arg('input', () => UpdateMJTestRubricInput) input: UpdateMJTestRubricInput,
7161
+ @Ctx() { providers, userPayload }: AppContext,
7162
+ @PubSub() pubSub: PubSubEngine
7163
+ ) {
7164
+ const provider = GetReadWriteProvider(providers);
7165
+ return this.UpdateRecord('MJ: Test Rubrics', input, provider, userPayload, pubSub);
7166
+ }
7167
+
7168
+ @Mutation(() => MJTestRubric_)
7169
+ async DeleteMJTestRubric(@Arg('ID', () => String) ID: string, @Arg('options___', () => DeleteOptionsInput) options: DeleteOptionsInput, @Ctx() { providers, userPayload }: AppContext, @PubSub() pubSub: PubSubEngine) {
7170
+ const provider = GetReadWriteProvider(providers);
7171
+ const key = new CompositeKey([{FieldName: 'ID', Value: ID}]);
7172
+ return this.DeleteRecord('MJ: Test Rubrics', key, options, provider, userPayload, pubSub);
7173
+ }
7174
+
7175
+ }
7176
+
5864
7177
  //****************************************************************************
5865
7178
  // ENTITY CLASS for MJ: Task Dependencies
5866
7179
  //****************************************************************************
@@ -12647,12 +13960,12 @@ export class MJUser_ {
12647
13960
  @Field(() => [MJReportUserState_])
12648
13961
  MJ_ReportUserStates_UserIDArray: MJReportUserState_[]; // Link to MJ_ReportUserStates
12649
13962
 
12650
- @Field(() => [MJDashboardUserState_])
12651
- MJ_DashboardUserStates_UserIDArray: MJDashboardUserState_[]; // Link to MJ_DashboardUserStates
12652
-
12653
13963
  @Field(() => [MJDashboardUserPreference_])
12654
13964
  MJ_DashboardUserPreferences_UserIDArray: MJDashboardUserPreference_[]; // Link to MJ_DashboardUserPreferences
12655
13965
 
13966
+ @Field(() => [MJDashboardUserState_])
13967
+ MJ_DashboardUserStates_UserIDArray: MJDashboardUserState_[]; // Link to MJ_DashboardUserStates
13968
+
12656
13969
  @Field(() => [MJArtifactVersion_])
12657
13970
  MJ_ArtifactVersions_UserIDArray: MJArtifactVersion_[]; // Link to MJ_ArtifactVersions
12658
13971
 
@@ -12674,6 +13987,12 @@ export class MJUser_ {
12674
13987
  @Field(() => [MJConversationDetailRating_])
12675
13988
  MJ_ConversationDetailRatings_UserIDArray: MJConversationDetailRating_[]; // Link to MJ_ConversationDetailRatings
12676
13989
 
13990
+ @Field(() => [MJTestRunFeedback_])
13991
+ MJ_TestRunFeedbacks_ReviewerUserIDArray: MJTestRunFeedback_[]; // Link to MJ_TestRunFeedbacks
13992
+
13993
+ @Field(() => [MJTestSuiteRun_])
13994
+ MJ_TestSuiteRuns_RunByUserIDArray: MJTestSuiteRun_[]; // Link to MJ_TestSuiteRuns
13995
+
12677
13996
  @Field(() => [MJResourcePermission_])
12678
13997
  ResourcePermissions_UserIDArray: MJResourcePermission_[]; // Link to ResourcePermissions
12679
13998
 
@@ -12698,6 +14017,9 @@ export class MJUser_ {
12698
14017
  @Field(() => [MJArtifactPermission_])
12699
14018
  MJ_ArtifactPermissions_SharedByUserIDArray: MJArtifactPermission_[]; // Link to MJ_ArtifactPermissions
12700
14019
 
14020
+ @Field(() => [MJTestRun_])
14021
+ MJ_TestRuns_RunByUserIDArray: MJTestRun_[]; // Link to MJ_TestRuns
14022
+
12701
14023
  @Field(() => [MJAIAgentRun_])
12702
14024
  MJ_AIAgentRuns_UserIDArray: MJAIAgentRun_[]; // Link to MJ_AIAgentRuns
12703
14025
 
@@ -13286,25 +14608,25 @@ export class MJUserResolverBase extends ResolverBase {
13286
14608
  return result;
13287
14609
  }
13288
14610
 
13289
- @FieldResolver(() => [MJDashboardUserState_])
13290
- async MJ_DashboardUserStates_UserIDArray(@Root() mjuser_: MJUser_, @Ctx() { dataSources, userPayload, providers }: AppContext, @PubSub() pubSub: PubSubEngine) {
13291
- this.CheckUserReadPermissions('MJ: Dashboard User States', userPayload);
14611
+ @FieldResolver(() => [MJDashboardUserPreference_])
14612
+ async MJ_DashboardUserPreferences_UserIDArray(@Root() mjuser_: MJUser_, @Ctx() { dataSources, userPayload, providers }: AppContext, @PubSub() pubSub: PubSubEngine) {
14613
+ this.CheckUserReadPermissions('MJ: Dashboard User Preferences', userPayload);
13292
14614
  const provider = GetReadOnlyProvider(providers, { allowFallbackToReadWrite: true });
13293
14615
  const connPool = GetReadOnlyDataSource(dataSources, { allowFallbackToReadWrite: true });
13294
- const sSQL = `SELECT * FROM [${Metadata.Provider.ConfigData.MJCoreSchemaName}].[vwDashboardUserStates] WHERE [UserID]='${mjuser_.ID}' ` + this.getRowLevelSecurityWhereClause(provider, 'MJ: Dashboard User States', userPayload, EntityPermissionType.Read, 'AND');
14616
+ const sSQL = `SELECT * FROM [${Metadata.Provider.ConfigData.MJCoreSchemaName}].[vwDashboardUserPreferences] WHERE [UserID]='${mjuser_.ID}' ` + this.getRowLevelSecurityWhereClause(provider, 'MJ: Dashboard User Preferences', userPayload, EntityPermissionType.Read, 'AND');
13295
14617
  const rows = await SQLServerDataProvider.ExecuteSQLWithPool(connPool, sSQL, undefined, this.GetUserFromPayload(userPayload));
13296
- const result = this.ArrayMapFieldNamesToCodeNames('MJ: Dashboard User States', rows);
14618
+ const result = this.ArrayMapFieldNamesToCodeNames('MJ: Dashboard User Preferences', rows);
13297
14619
  return result;
13298
14620
  }
13299
14621
 
13300
- @FieldResolver(() => [MJDashboardUserPreference_])
13301
- async MJ_DashboardUserPreferences_UserIDArray(@Root() mjuser_: MJUser_, @Ctx() { dataSources, userPayload, providers }: AppContext, @PubSub() pubSub: PubSubEngine) {
13302
- this.CheckUserReadPermissions('MJ: Dashboard User Preferences', userPayload);
14622
+ @FieldResolver(() => [MJDashboardUserState_])
14623
+ async MJ_DashboardUserStates_UserIDArray(@Root() mjuser_: MJUser_, @Ctx() { dataSources, userPayload, providers }: AppContext, @PubSub() pubSub: PubSubEngine) {
14624
+ this.CheckUserReadPermissions('MJ: Dashboard User States', userPayload);
13303
14625
  const provider = GetReadOnlyProvider(providers, { allowFallbackToReadWrite: true });
13304
14626
  const connPool = GetReadOnlyDataSource(dataSources, { allowFallbackToReadWrite: true });
13305
- const sSQL = `SELECT * FROM [${Metadata.Provider.ConfigData.MJCoreSchemaName}].[vwDashboardUserPreferences] WHERE [UserID]='${mjuser_.ID}' ` + this.getRowLevelSecurityWhereClause(provider, 'MJ: Dashboard User Preferences', userPayload, EntityPermissionType.Read, 'AND');
14627
+ const sSQL = `SELECT * FROM [${Metadata.Provider.ConfigData.MJCoreSchemaName}].[vwDashboardUserStates] WHERE [UserID]='${mjuser_.ID}' ` + this.getRowLevelSecurityWhereClause(provider, 'MJ: Dashboard User States', userPayload, EntityPermissionType.Read, 'AND');
13306
14628
  const rows = await SQLServerDataProvider.ExecuteSQLWithPool(connPool, sSQL, undefined, this.GetUserFromPayload(userPayload));
13307
- const result = this.ArrayMapFieldNamesToCodeNames('MJ: Dashboard User Preferences', rows);
14629
+ const result = this.ArrayMapFieldNamesToCodeNames('MJ: Dashboard User States', rows);
13308
14630
  return result;
13309
14631
  }
13310
14632
 
@@ -13385,6 +14707,28 @@ export class MJUserResolverBase extends ResolverBase {
13385
14707
  return result;
13386
14708
  }
13387
14709
 
14710
+ @FieldResolver(() => [MJTestRunFeedback_])
14711
+ async MJ_TestRunFeedbacks_ReviewerUserIDArray(@Root() mjuser_: MJUser_, @Ctx() { dataSources, userPayload, providers }: AppContext, @PubSub() pubSub: PubSubEngine) {
14712
+ this.CheckUserReadPermissions('MJ: Test Run Feedbacks', userPayload);
14713
+ const provider = GetReadOnlyProvider(providers, { allowFallbackToReadWrite: true });
14714
+ const connPool = GetReadOnlyDataSource(dataSources, { allowFallbackToReadWrite: true });
14715
+ const sSQL = `SELECT * FROM [${Metadata.Provider.ConfigData.MJCoreSchemaName}].[vwTestRunFeedbacks] WHERE [ReviewerUserID]='${mjuser_.ID}' ` + this.getRowLevelSecurityWhereClause(provider, 'MJ: Test Run Feedbacks', userPayload, EntityPermissionType.Read, 'AND');
14716
+ const rows = await SQLServerDataProvider.ExecuteSQLWithPool(connPool, sSQL, undefined, this.GetUserFromPayload(userPayload));
14717
+ const result = this.ArrayMapFieldNamesToCodeNames('MJ: Test Run Feedbacks', rows);
14718
+ return result;
14719
+ }
14720
+
14721
+ @FieldResolver(() => [MJTestSuiteRun_])
14722
+ async MJ_TestSuiteRuns_RunByUserIDArray(@Root() mjuser_: MJUser_, @Ctx() { dataSources, userPayload, providers }: AppContext, @PubSub() pubSub: PubSubEngine) {
14723
+ this.CheckUserReadPermissions('MJ: Test Suite Runs', userPayload);
14724
+ const provider = GetReadOnlyProvider(providers, { allowFallbackToReadWrite: true });
14725
+ const connPool = GetReadOnlyDataSource(dataSources, { allowFallbackToReadWrite: true });
14726
+ const sSQL = `SELECT * FROM [${Metadata.Provider.ConfigData.MJCoreSchemaName}].[vwTestSuiteRuns] WHERE [RunByUserID]='${mjuser_.ID}' ` + this.getRowLevelSecurityWhereClause(provider, 'MJ: Test Suite Runs', userPayload, EntityPermissionType.Read, 'AND');
14727
+ const rows = await SQLServerDataProvider.ExecuteSQLWithPool(connPool, sSQL, undefined, this.GetUserFromPayload(userPayload));
14728
+ const result = this.ArrayMapFieldNamesToCodeNames('MJ: Test Suite Runs', rows);
14729
+ return result;
14730
+ }
14731
+
13388
14732
  @FieldResolver(() => [MJResourcePermission_])
13389
14733
  async ResourcePermissions_UserIDArray(@Root() mjuser_: MJUser_, @Ctx() { dataSources, userPayload, providers }: AppContext, @PubSub() pubSub: PubSubEngine) {
13390
14734
  this.CheckUserReadPermissions('Resource Permissions', userPayload);
@@ -13473,6 +14817,17 @@ export class MJUserResolverBase extends ResolverBase {
13473
14817
  return result;
13474
14818
  }
13475
14819
 
14820
+ @FieldResolver(() => [MJTestRun_])
14821
+ async MJ_TestRuns_RunByUserIDArray(@Root() mjuser_: MJUser_, @Ctx() { dataSources, userPayload, providers }: AppContext, @PubSub() pubSub: PubSubEngine) {
14822
+ this.CheckUserReadPermissions('MJ: Test Runs', userPayload);
14823
+ const provider = GetReadOnlyProvider(providers, { allowFallbackToReadWrite: true });
14824
+ const connPool = GetReadOnlyDataSource(dataSources, { allowFallbackToReadWrite: true });
14825
+ const sSQL = `SELECT * FROM [${Metadata.Provider.ConfigData.MJCoreSchemaName}].[vwTestRuns] WHERE [RunByUserID]='${mjuser_.ID}' ` + this.getRowLevelSecurityWhereClause(provider, 'MJ: Test Runs', userPayload, EntityPermissionType.Read, 'AND');
14826
+ const rows = await SQLServerDataProvider.ExecuteSQLWithPool(connPool, sSQL, undefined, this.GetUserFromPayload(userPayload));
14827
+ const result = this.ArrayMapFieldNamesToCodeNames('MJ: Test Runs', rows);
14828
+ return result;
14829
+ }
14830
+
13476
14831
  @FieldResolver(() => [MJAIAgentRun_])
13477
14832
  async MJ_AIAgentRuns_UserIDArray(@Root() mjuser_: MJUser_, @Ctx() { dataSources, userPayload, providers }: AppContext, @PubSub() pubSub: PubSubEngine) {
13478
14833
  this.CheckUserReadPermissions('MJ: AI Agent Runs', userPayload);
@@ -24362,9 +25717,22 @@ export class MJConversationDetail_ {
24362
25717
  @MaxLength(40)
24363
25718
  Status: string;
24364
25719
 
24365
- @Field({nullable: true, description: `JSON array of suggested responses that can be displayed to the user for quick replies. Each response object contains: text (display text), allowInput (boolean), iconClass (optional Font Awesome class), and data (optional payload).`})
25720
+ @Field({nullable: true, description: `DEPRECATED: Use ResponseForm, ActionableCommands, and AutomaticCommands instead. Legacy field for simple text-based suggested responses. Replaced in v2.118 by more powerful structured forms and commands system. Retained for historical data only.`})
24366
25721
  SuggestedResponses?: string;
24367
25722
 
25723
+ @Field({nullable: true, description: `Optional Foreign Key - Links this conversation detail to a test run if this message was part of a test conversation. Allows filtering and analyzing test-specific conversation turns.`})
25724
+ @MaxLength(16)
25725
+ TestRunID?: string;
25726
+
25727
+ @Field({nullable: true, description: `JSON object containing agent response form definition with questions and validation rules. Supports 8 question types: text, textarea, email, number, currency, date, datetime, choices (buttongroup/radio/dropdown/checkbox). Used for collecting structured user input with proper validation.`})
25728
+ ResponseForm?: string;
25729
+
25730
+ @Field({nullable: true, description: `JSON array of actionable commands that user can trigger (shown as clickable buttons/links). Supports open:resource (navigate to records/dashboards/reports/forms) and open:url (external links). Typically used after completing work to provide easy navigation to created/modified resources.`})
25731
+ ActionableCommands?: string;
25732
+
25733
+ @Field({nullable: true, description: `JSON array of automatic commands that execute immediately when received (no user interaction). Supports refresh:data (refresh entity data or caches) and notification (show toast messages). Used for keeping UI in sync after agent makes changes and providing user feedback.`})
25734
+ AutomaticCommands?: string;
25735
+
24368
25736
  @Field({nullable: true})
24369
25737
  @MaxLength(510)
24370
25738
  Conversation?: string;
@@ -24377,6 +25745,13 @@ export class MJConversationDetail_ {
24377
25745
  @MaxLength(510)
24378
25746
  Artifact?: string;
24379
25747
 
25748
+ @Field({nullable: true})
25749
+ @MaxLength(510)
25750
+ ArtifactVersion?: string;
25751
+
25752
+ @Field({nullable: true})
25753
+ Parent?: string;
25754
+
24380
25755
  @Field({nullable: true})
24381
25756
  @MaxLength(510)
24382
25757
  Agent?: string;
@@ -24475,6 +25850,18 @@ export class CreateMJConversationDetailInput {
24475
25850
 
24476
25851
  @Field({ nullable: true })
24477
25852
  SuggestedResponses: string | null;
25853
+
25854
+ @Field({ nullable: true })
25855
+ TestRunID: string | null;
25856
+
25857
+ @Field({ nullable: true })
25858
+ ResponseForm: string | null;
25859
+
25860
+ @Field({ nullable: true })
25861
+ ActionableCommands: string | null;
25862
+
25863
+ @Field({ nullable: true })
25864
+ AutomaticCommands: string | null;
24478
25865
  }
24479
25866
 
24480
25867
 
@@ -24543,6 +25930,18 @@ export class UpdateMJConversationDetailInput {
24543
25930
  @Field({ nullable: true })
24544
25931
  SuggestedResponses?: string | null;
24545
25932
 
25933
+ @Field({ nullable: true })
25934
+ TestRunID?: string | null;
25935
+
25936
+ @Field({ nullable: true })
25937
+ ResponseForm?: string | null;
25938
+
25939
+ @Field({ nullable: true })
25940
+ ActionableCommands?: string | null;
25941
+
25942
+ @Field({ nullable: true })
25943
+ AutomaticCommands?: string | null;
25944
+
24546
25945
  @Field(() => [KeyValuePairInput], { nullable: true })
24547
25946
  OldValues___?: KeyValuePairInput[];
24548
25947
  }
@@ -24788,6 +26187,10 @@ export class MJConversation_ {
24788
26187
  @Field(() => Boolean, {description: `Indicates if this conversation is pinned to the top of lists`})
24789
26188
  IsPinned: boolean;
24790
26189
 
26190
+ @Field({nullable: true, description: `Optional Foreign Key - Links this conversation to a test run if this conversation was generated as part of a test. Enables tracking test conversations separately from production conversations.`})
26191
+ @MaxLength(16)
26192
+ TestRunID?: string;
26193
+
24791
26194
  @Field()
24792
26195
  @MaxLength(200)
24793
26196
  User: string;
@@ -24874,6 +26277,9 @@ export class CreateMJConversationInput {
24874
26277
 
24875
26278
  @Field(() => Boolean, { nullable: true })
24876
26279
  IsPinned?: boolean;
26280
+
26281
+ @Field({ nullable: true })
26282
+ TestRunID: string | null;
24877
26283
  }
24878
26284
 
24879
26285
 
@@ -24924,6 +26330,9 @@ export class UpdateMJConversationInput {
24924
26330
  @Field(() => Boolean, { nullable: true })
24925
26331
  IsPinned?: boolean;
24926
26332
 
26333
+ @Field({ nullable: true })
26334
+ TestRunID?: string | null;
26335
+
24927
26336
  @Field(() => [KeyValuePairInput], { nullable: true })
24928
26337
  OldValues___?: KeyValuePairInput[];
24929
26338
  }
@@ -39221,6 +40630,400 @@ export class MJResourceLinkResolver extends ResolverBase {
39221
40630
 
39222
40631
  }
39223
40632
 
40633
+ //****************************************************************************
40634
+ // ENTITY CLASS for MJ: Test Runs
40635
+ //****************************************************************************
40636
+ @ObjectType({ description: `Execution instance of a single test. Captures inputs, outputs, results, and links to the target being tested (e.g., Agent Run). Can be part of a suite run or standalone. The TargetLogID links to type-specific execution logs (AgentRun, WorkflowRun, etc.) which contain the detailed trace information.` })
40637
+ export class MJTestRun_ {
40638
+ @Field()
40639
+ @MaxLength(16)
40640
+ ID: string;
40641
+
40642
+ @Field({description: `Foreign Key - The test definition that was executed`})
40643
+ @MaxLength(16)
40644
+ TestID: string;
40645
+
40646
+ @Field({nullable: true, description: `Foreign Key - Optional parent suite run if this test was part of a suite execution. NULL for standalone test runs.`})
40647
+ @MaxLength(16)
40648
+ TestSuiteRunID?: string;
40649
+
40650
+ @Field({description: `Foreign Key - The user who triggered the test run (could be system user for automated runs)`})
40651
+ @MaxLength(16)
40652
+ RunByUserID: string;
40653
+
40654
+ @Field(() => Int, {nullable: true, description: `Execution sequence within the suite run. Indicates order of execution for tests in the same suite.`})
40655
+ Sequence?: number;
40656
+
40657
+ @Field({nullable: true, description: `Type of the target being tested (e.g., "Agent Run", "Workflow Run", "Code Generation"). Polymorphic discriminator for TargetLogID.`})
40658
+ @MaxLength(200)
40659
+ TargetType?: string;
40660
+
40661
+ @Field({nullable: true, description: `ID of the target execution log (e.g., AIAgentRun.ID, WorkflowRun.ID). This is a soft FK - the actual entity depends on TargetType. The target entity should have a reverse FK back to TestRun for bidirectional navigation.`})
40662
+ @MaxLength(16)
40663
+ TargetLogID?: string;
40664
+
40665
+ @Field({description: `Current status of the test run: Pending (queued), Running (in progress), Passed (all checks passed), Failed (at least one check failed), Skipped (not executed), Error (execution error before validation)`})
40666
+ @MaxLength(40)
40667
+ Status: string;
40668
+
40669
+ @Field({nullable: true, description: `Timestamp when the test run started execution`})
40670
+ @MaxLength(8)
40671
+ StartedAt?: Date;
40672
+
40673
+ @Field({nullable: true, description: `Timestamp when the test run completed`})
40674
+ @MaxLength(8)
40675
+ CompletedAt?: Date;
40676
+
40677
+ @Field(() => Float, {nullable: true, description: `Execution time in seconds for this test`})
40678
+ DurationSeconds?: number;
40679
+
40680
+ @Field({nullable: true, description: `JSON object with the actual inputs used for this test run (may differ from test definition if parameterized)`})
40681
+ InputData?: string;
40682
+
40683
+ @Field({nullable: true, description: `JSON object with the expected outputs/outcomes for this test run`})
40684
+ ExpectedOutputData?: string;
40685
+
40686
+ @Field({nullable: true, description: `JSON object with the actual outputs produced by the test execution`})
40687
+ ActualOutputData?: string;
40688
+
40689
+ @Field(() => Int, {nullable: true, description: `Number of validation checks that passed`})
40690
+ PassedChecks?: number;
40691
+
40692
+ @Field(() => Int, {nullable: true, description: `Number of validation checks that failed`})
40693
+ FailedChecks?: number;
40694
+
40695
+ @Field(() => Int, {nullable: true, description: `Total number of validation checks performed`})
40696
+ TotalChecks?: number;
40697
+
40698
+ @Field(() => Float, {nullable: true, description: `Overall test score from 0.0000 to 1.0000 (0-100%). Calculated by test driver based on passed/failed checks and weights.`})
40699
+ Score?: number;
40700
+
40701
+ @Field(() => Float, {nullable: true, description: `Cost in USD for running this test (e.g., LLM token costs, compute resources)`})
40702
+ CostUSD?: number;
40703
+
40704
+ @Field({nullable: true, description: `Error message if the test encountered an execution error`})
40705
+ ErrorMessage?: string;
40706
+
40707
+ @Field({nullable: true, description: `JSON object with detailed results including individual check results, metrics, oracle outputs, and diagnostic information`})
40708
+ ResultDetails?: string;
40709
+
40710
+ @Field()
40711
+ @MaxLength(10)
40712
+ _mj__CreatedAt: Date;
40713
+
40714
+ @Field()
40715
+ @MaxLength(10)
40716
+ _mj__UpdatedAt: Date;
40717
+
40718
+ @Field()
40719
+ @MaxLength(510)
40720
+ Test: string;
40721
+
40722
+ @Field()
40723
+ @MaxLength(200)
40724
+ RunByUser: string;
40725
+
40726
+ @Field(() => [MJTestRunFeedback_])
40727
+ MJ_TestRunFeedbacks_TestRunIDArray: MJTestRunFeedback_[]; // Link to MJ_TestRunFeedbacks
40728
+
40729
+ @Field(() => [MJAIPromptRun_])
40730
+ MJ_AIPromptRuns_TestRunIDArray: MJAIPromptRun_[]; // Link to MJ_AIPromptRuns
40731
+
40732
+ @Field(() => [MJAIAgentRun_])
40733
+ MJ_AIAgentRuns_TestRunIDArray: MJAIAgentRun_[]; // Link to MJ_AIAgentRuns
40734
+
40735
+ @Field(() => [MJConversation_])
40736
+ Conversations_TestRunIDArray: MJConversation_[]; // Link to Conversations
40737
+
40738
+ @Field(() => [MJConversationDetail_])
40739
+ ConversationDetails_TestRunIDArray: MJConversationDetail_[]; // Link to ConversationDetails
40740
+
40741
+ }
40742
+
40743
+ //****************************************************************************
40744
+ // INPUT TYPE for MJ: Test Runs
40745
+ //****************************************************************************
40746
+ @InputType()
40747
+ export class CreateMJTestRunInput {
40748
+ @Field({ nullable: true })
40749
+ ID?: string;
40750
+
40751
+ @Field({ nullable: true })
40752
+ TestID?: string;
40753
+
40754
+ @Field({ nullable: true })
40755
+ TestSuiteRunID: string | null;
40756
+
40757
+ @Field({ nullable: true })
40758
+ RunByUserID?: string;
40759
+
40760
+ @Field(() => Int, { nullable: true })
40761
+ Sequence: number | null;
40762
+
40763
+ @Field({ nullable: true })
40764
+ TargetType: string | null;
40765
+
40766
+ @Field({ nullable: true })
40767
+ TargetLogID: string | null;
40768
+
40769
+ @Field({ nullable: true })
40770
+ Status?: string;
40771
+
40772
+ @Field({ nullable: true })
40773
+ StartedAt: Date | null;
40774
+
40775
+ @Field({ nullable: true })
40776
+ CompletedAt: Date | null;
40777
+
40778
+ @Field(() => Float, { nullable: true })
40779
+ DurationSeconds: number | null;
40780
+
40781
+ @Field({ nullable: true })
40782
+ InputData: string | null;
40783
+
40784
+ @Field({ nullable: true })
40785
+ ExpectedOutputData: string | null;
40786
+
40787
+ @Field({ nullable: true })
40788
+ ActualOutputData: string | null;
40789
+
40790
+ @Field(() => Int, { nullable: true })
40791
+ PassedChecks: number | null;
40792
+
40793
+ @Field(() => Int, { nullable: true })
40794
+ FailedChecks: number | null;
40795
+
40796
+ @Field(() => Int, { nullable: true })
40797
+ TotalChecks: number | null;
40798
+
40799
+ @Field(() => Float, { nullable: true })
40800
+ Score: number | null;
40801
+
40802
+ @Field(() => Float, { nullable: true })
40803
+ CostUSD: number | null;
40804
+
40805
+ @Field({ nullable: true })
40806
+ ErrorMessage: string | null;
40807
+
40808
+ @Field({ nullable: true })
40809
+ ResultDetails: string | null;
40810
+ }
40811
+
40812
+
40813
+ //****************************************************************************
40814
+ // INPUT TYPE for MJ: Test Runs
40815
+ //****************************************************************************
40816
+ @InputType()
40817
+ export class UpdateMJTestRunInput {
40818
+ @Field()
40819
+ ID: string;
40820
+
40821
+ @Field({ nullable: true })
40822
+ TestID?: string;
40823
+
40824
+ @Field({ nullable: true })
40825
+ TestSuiteRunID?: string | null;
40826
+
40827
+ @Field({ nullable: true })
40828
+ RunByUserID?: string;
40829
+
40830
+ @Field(() => Int, { nullable: true })
40831
+ Sequence?: number | null;
40832
+
40833
+ @Field({ nullable: true })
40834
+ TargetType?: string | null;
40835
+
40836
+ @Field({ nullable: true })
40837
+ TargetLogID?: string | null;
40838
+
40839
+ @Field({ nullable: true })
40840
+ Status?: string;
40841
+
40842
+ @Field({ nullable: true })
40843
+ StartedAt?: Date | null;
40844
+
40845
+ @Field({ nullable: true })
40846
+ CompletedAt?: Date | null;
40847
+
40848
+ @Field(() => Float, { nullable: true })
40849
+ DurationSeconds?: number | null;
40850
+
40851
+ @Field({ nullable: true })
40852
+ InputData?: string | null;
40853
+
40854
+ @Field({ nullable: true })
40855
+ ExpectedOutputData?: string | null;
40856
+
40857
+ @Field({ nullable: true })
40858
+ ActualOutputData?: string | null;
40859
+
40860
+ @Field(() => Int, { nullable: true })
40861
+ PassedChecks?: number | null;
40862
+
40863
+ @Field(() => Int, { nullable: true })
40864
+ FailedChecks?: number | null;
40865
+
40866
+ @Field(() => Int, { nullable: true })
40867
+ TotalChecks?: number | null;
40868
+
40869
+ @Field(() => Float, { nullable: true })
40870
+ Score?: number | null;
40871
+
40872
+ @Field(() => Float, { nullable: true })
40873
+ CostUSD?: number | null;
40874
+
40875
+ @Field({ nullable: true })
40876
+ ErrorMessage?: string | null;
40877
+
40878
+ @Field({ nullable: true })
40879
+ ResultDetails?: string | null;
40880
+
40881
+ @Field(() => [KeyValuePairInput], { nullable: true })
40882
+ OldValues___?: KeyValuePairInput[];
40883
+ }
40884
+
40885
+ //****************************************************************************
40886
+ // RESOLVER for MJ: Test Runs
40887
+ //****************************************************************************
40888
+ @ObjectType()
40889
+ export class RunMJTestRunViewResult {
40890
+ @Field(() => [MJTestRun_])
40891
+ Results: MJTestRun_[];
40892
+
40893
+ @Field(() => String, {nullable: true})
40894
+ UserViewRunID?: string;
40895
+
40896
+ @Field(() => Int, {nullable: true})
40897
+ RowCount: number;
40898
+
40899
+ @Field(() => Int, {nullable: true})
40900
+ TotalRowCount: number;
40901
+
40902
+ @Field(() => Int, {nullable: true})
40903
+ ExecutionTime: number;
40904
+
40905
+ @Field({nullable: true})
40906
+ ErrorMessage?: string;
40907
+
40908
+ @Field(() => Boolean, {nullable: false})
40909
+ Success: boolean;
40910
+ }
40911
+
40912
+ @Resolver(MJTestRun_)
40913
+ export class MJTestRunResolver extends ResolverBase {
40914
+ @Query(() => RunMJTestRunViewResult)
40915
+ async RunMJTestRunViewByID(@Arg('input', () => RunViewByIDInput) input: RunViewByIDInput, @Ctx() { providers, userPayload }: AppContext, @PubSub() pubSub: PubSubEngine) {
40916
+ const provider = GetReadOnlyProvider(providers, { allowFallbackToReadWrite: true });
40917
+ return super.RunViewByIDGeneric(input, provider, userPayload, pubSub);
40918
+ }
40919
+
40920
+ @Query(() => RunMJTestRunViewResult)
40921
+ async RunMJTestRunViewByName(@Arg('input', () => RunViewByNameInput) input: RunViewByNameInput, @Ctx() { providers, userPayload }: AppContext, @PubSub() pubSub: PubSubEngine) {
40922
+ const provider = GetReadOnlyProvider(providers, { allowFallbackToReadWrite: true });
40923
+ return super.RunViewByNameGeneric(input, provider, userPayload, pubSub);
40924
+ }
40925
+
40926
+ @Query(() => RunMJTestRunViewResult)
40927
+ async RunMJTestRunDynamicView(@Arg('input', () => RunDynamicViewInput) input: RunDynamicViewInput, @Ctx() { providers, userPayload }: AppContext, @PubSub() pubSub: PubSubEngine) {
40928
+ const provider = GetReadOnlyProvider(providers, { allowFallbackToReadWrite: true });
40929
+ input.EntityName = 'MJ: Test Runs';
40930
+ return super.RunDynamicViewGeneric(input, provider, userPayload, pubSub);
40931
+ }
40932
+ @Query(() => MJTestRun_, { nullable: true })
40933
+ async MJTestRun(@Arg('ID', () => String) ID: string, @Ctx() { dataSources, userPayload, providers }: AppContext, @PubSub() pubSub: PubSubEngine): Promise<MJTestRun_ | null> {
40934
+ this.CheckUserReadPermissions('MJ: Test Runs', userPayload);
40935
+ const provider = GetReadOnlyProvider(providers, { allowFallbackToReadWrite: true });
40936
+ const connPool = GetReadOnlyDataSource(dataSources, { allowFallbackToReadWrite: true });
40937
+ const sSQL = `SELECT * FROM [${Metadata.Provider.ConfigData.MJCoreSchemaName}].[vwTestRuns] WHERE [ID]='${ID}' ` + this.getRowLevelSecurityWhereClause(provider, 'MJ: Test Runs', userPayload, EntityPermissionType.Read, 'AND');
40938
+ const rows = await SQLServerDataProvider.ExecuteSQLWithPool(connPool, sSQL, undefined, this.GetUserFromPayload(userPayload));
40939
+ const result = this.MapFieldNamesToCodeNames('MJ: Test Runs', rows && rows.length > 0 ? rows[0] : {})
40940
+ return result;
40941
+ }
40942
+
40943
+ @FieldResolver(() => [MJTestRunFeedback_])
40944
+ async MJ_TestRunFeedbacks_TestRunIDArray(@Root() mjtestrun_: MJTestRun_, @Ctx() { dataSources, userPayload, providers }: AppContext, @PubSub() pubSub: PubSubEngine) {
40945
+ this.CheckUserReadPermissions('MJ: Test Run Feedbacks', userPayload);
40946
+ const provider = GetReadOnlyProvider(providers, { allowFallbackToReadWrite: true });
40947
+ const connPool = GetReadOnlyDataSource(dataSources, { allowFallbackToReadWrite: true });
40948
+ const sSQL = `SELECT * FROM [${Metadata.Provider.ConfigData.MJCoreSchemaName}].[vwTestRunFeedbacks] WHERE [TestRunID]='${mjtestrun_.ID}' ` + this.getRowLevelSecurityWhereClause(provider, 'MJ: Test Run Feedbacks', userPayload, EntityPermissionType.Read, 'AND');
40949
+ const rows = await SQLServerDataProvider.ExecuteSQLWithPool(connPool, sSQL, undefined, this.GetUserFromPayload(userPayload));
40950
+ const result = this.ArrayMapFieldNamesToCodeNames('MJ: Test Run Feedbacks', rows);
40951
+ return result;
40952
+ }
40953
+
40954
+ @FieldResolver(() => [MJAIPromptRun_])
40955
+ async MJ_AIPromptRuns_TestRunIDArray(@Root() mjtestrun_: MJTestRun_, @Ctx() { dataSources, userPayload, providers }: AppContext, @PubSub() pubSub: PubSubEngine) {
40956
+ this.CheckUserReadPermissions('MJ: AI Prompt Runs', userPayload);
40957
+ const provider = GetReadOnlyProvider(providers, { allowFallbackToReadWrite: true });
40958
+ const connPool = GetReadOnlyDataSource(dataSources, { allowFallbackToReadWrite: true });
40959
+ const sSQL = `SELECT * FROM [${Metadata.Provider.ConfigData.MJCoreSchemaName}].[vwAIPromptRuns] WHERE [TestRunID]='${mjtestrun_.ID}' ` + this.getRowLevelSecurityWhereClause(provider, 'MJ: AI Prompt Runs', userPayload, EntityPermissionType.Read, 'AND');
40960
+ const rows = await SQLServerDataProvider.ExecuteSQLWithPool(connPool, sSQL, undefined, this.GetUserFromPayload(userPayload));
40961
+ const result = this.ArrayMapFieldNamesToCodeNames('MJ: AI Prompt Runs', rows);
40962
+ return result;
40963
+ }
40964
+
40965
+ @FieldResolver(() => [MJAIAgentRun_])
40966
+ async MJ_AIAgentRuns_TestRunIDArray(@Root() mjtestrun_: MJTestRun_, @Ctx() { dataSources, userPayload, providers }: AppContext, @PubSub() pubSub: PubSubEngine) {
40967
+ this.CheckUserReadPermissions('MJ: AI Agent Runs', userPayload);
40968
+ const provider = GetReadOnlyProvider(providers, { allowFallbackToReadWrite: true });
40969
+ const connPool = GetReadOnlyDataSource(dataSources, { allowFallbackToReadWrite: true });
40970
+ const sSQL = `SELECT * FROM [${Metadata.Provider.ConfigData.MJCoreSchemaName}].[vwAIAgentRuns] WHERE [TestRunID]='${mjtestrun_.ID}' ` + this.getRowLevelSecurityWhereClause(provider, 'MJ: AI Agent Runs', userPayload, EntityPermissionType.Read, 'AND');
40971
+ const rows = await SQLServerDataProvider.ExecuteSQLWithPool(connPool, sSQL, undefined, this.GetUserFromPayload(userPayload));
40972
+ const result = this.ArrayMapFieldNamesToCodeNames('MJ: AI Agent Runs', rows);
40973
+ return result;
40974
+ }
40975
+
40976
+ @FieldResolver(() => [MJConversation_])
40977
+ async Conversations_TestRunIDArray(@Root() mjtestrun_: MJTestRun_, @Ctx() { dataSources, userPayload, providers }: AppContext, @PubSub() pubSub: PubSubEngine) {
40978
+ this.CheckUserReadPermissions('Conversations', userPayload);
40979
+ const provider = GetReadOnlyProvider(providers, { allowFallbackToReadWrite: true });
40980
+ const connPool = GetReadOnlyDataSource(dataSources, { allowFallbackToReadWrite: true });
40981
+ const sSQL = `SELECT * FROM [${Metadata.Provider.ConfigData.MJCoreSchemaName}].[vwConversations] WHERE [TestRunID]='${mjtestrun_.ID}' ` + this.getRowLevelSecurityWhereClause(provider, 'Conversations', userPayload, EntityPermissionType.Read, 'AND');
40982
+ const rows = await SQLServerDataProvider.ExecuteSQLWithPool(connPool, sSQL, undefined, this.GetUserFromPayload(userPayload));
40983
+ const result = this.ArrayMapFieldNamesToCodeNames('Conversations', rows);
40984
+ return result;
40985
+ }
40986
+
40987
+ @FieldResolver(() => [MJConversationDetail_])
40988
+ async ConversationDetails_TestRunIDArray(@Root() mjtestrun_: MJTestRun_, @Ctx() { dataSources, userPayload, providers }: AppContext, @PubSub() pubSub: PubSubEngine) {
40989
+ this.CheckUserReadPermissions('Conversation Details', userPayload);
40990
+ const provider = GetReadOnlyProvider(providers, { allowFallbackToReadWrite: true });
40991
+ const connPool = GetReadOnlyDataSource(dataSources, { allowFallbackToReadWrite: true });
40992
+ const sSQL = `SELECT * FROM [${Metadata.Provider.ConfigData.MJCoreSchemaName}].[vwConversationDetails] WHERE [TestRunID]='${mjtestrun_.ID}' ` + this.getRowLevelSecurityWhereClause(provider, 'Conversation Details', userPayload, EntityPermissionType.Read, 'AND');
40993
+ const rows = await SQLServerDataProvider.ExecuteSQLWithPool(connPool, sSQL, undefined, this.GetUserFromPayload(userPayload));
40994
+ const result = this.ArrayMapFieldNamesToCodeNames('Conversation Details', rows);
40995
+ return result;
40996
+ }
40997
+
40998
+ @Mutation(() => MJTestRun_)
40999
+ async CreateMJTestRun(
41000
+ @Arg('input', () => CreateMJTestRunInput) input: CreateMJTestRunInput,
41001
+ @Ctx() { providers, userPayload }: AppContext,
41002
+ @PubSub() pubSub: PubSubEngine
41003
+ ) {
41004
+ const provider = GetReadWriteProvider(providers);
41005
+ return this.CreateRecord('MJ: Test Runs', input, provider, userPayload, pubSub)
41006
+ }
41007
+
41008
+ @Mutation(() => MJTestRun_)
41009
+ async UpdateMJTestRun(
41010
+ @Arg('input', () => UpdateMJTestRunInput) input: UpdateMJTestRunInput,
41011
+ @Ctx() { providers, userPayload }: AppContext,
41012
+ @PubSub() pubSub: PubSubEngine
41013
+ ) {
41014
+ const provider = GetReadWriteProvider(providers);
41015
+ return this.UpdateRecord('MJ: Test Runs', input, provider, userPayload, pubSub);
41016
+ }
41017
+
41018
+ @Mutation(() => MJTestRun_)
41019
+ async DeleteMJTestRun(@Arg('ID', () => String) ID: string, @Arg('options___', () => DeleteOptionsInput) options: DeleteOptionsInput, @Ctx() { providers, userPayload }: AppContext, @PubSub() pubSub: PubSubEngine) {
41020
+ const provider = GetReadWriteProvider(providers);
41021
+ const key = new CompositeKey([{FieldName: 'ID', Value: ID}]);
41022
+ return this.DeleteRecord('MJ: Test Runs', key, options, provider, userPayload, pubSub);
41023
+ }
41024
+
41025
+ }
41026
+
39224
41027
  //****************************************************************************
39225
41028
  // ENTITY CLASS for MJ: AI Agent Artifact Types
39226
41029
  //****************************************************************************
@@ -42083,6 +43886,10 @@ export class MJArtifactType_ {
42083
43886
  @MaxLength(510)
42084
43887
  DriverClass?: string;
42085
43888
 
43889
+ @Field({nullable: true, description: `Font Awesome icon class name for displaying this artifact type in the UI (e.g., fa-file-code, fa-chart-line)`})
43890
+ @MaxLength(510)
43891
+ Icon?: string;
43892
+
42086
43893
  @Field({nullable: true})
42087
43894
  @MaxLength(200)
42088
43895
  Parent?: string;
@@ -42136,6 +43943,9 @@ export class CreateMJArtifactTypeInput {
42136
43943
 
42137
43944
  @Field({ nullable: true })
42138
43945
  DriverClass: string | null;
43946
+
43947
+ @Field({ nullable: true })
43948
+ Icon: string | null;
42139
43949
  }
42140
43950
 
42141
43951
 
@@ -42168,6 +43978,9 @@ export class UpdateMJArtifactTypeInput {
42168
43978
  @Field({ nullable: true })
42169
43979
  DriverClass?: string | null;
42170
43980
 
43981
+ @Field({ nullable: true })
43982
+ Icon?: string | null;
43983
+
42171
43984
  @Field(() => [KeyValuePairInput], { nullable: true })
42172
43985
  OldValues___?: KeyValuePairInput[];
42173
43986
  }
@@ -43031,6 +44844,241 @@ export class MJAIAgentExampleResolver extends ResolverBase {
43031
44844
 
43032
44845
  }
43033
44846
 
44847
+ //****************************************************************************
44848
+ // ENTITY CLASS for MJ: Test Suites
44849
+ //****************************************************************************
44850
+ @ObjectType({ description: `Hierarchical organization of tests into suites. Test suites can contain other suites (via ParentID) and tests (via TestSuiteTest junction table). Suites provide logical grouping for running batches of related tests.` })
44851
+ export class MJTestSuite_ {
44852
+ @Field()
44853
+ @MaxLength(16)
44854
+ ID: string;
44855
+
44856
+ @Field({nullable: true, description: `Optional parent suite ID for hierarchical organization. NULL for root-level suites.`})
44857
+ @MaxLength(16)
44858
+ ParentID?: string;
44859
+
44860
+ @Field({description: `Name of the test suite (e.g., "Skip Component Generation Suite", "Agent Memory Tests")`})
44861
+ @MaxLength(510)
44862
+ Name: string;
44863
+
44864
+ @Field({nullable: true, description: `Detailed description of what this suite tests and its purpose`})
44865
+ Description?: string;
44866
+
44867
+ @Field({description: `Status of the suite: Pending (being configured), Active (available for use), Disabled (archived/not in use)`})
44868
+ @MaxLength(40)
44869
+ Status: string;
44870
+
44871
+ @Field({nullable: true, description: `JSON array of tags for categorization and filtering (e.g., ["smoke", "regression", "nightly"])`})
44872
+ Tags?: string;
44873
+
44874
+ @Field({nullable: true, description: `JSON configuration object for suite-level settings (e.g., environment defaults, retry policies, notification settings)`})
44875
+ Configuration?: string;
44876
+
44877
+ @Field()
44878
+ @MaxLength(10)
44879
+ _mj__CreatedAt: Date;
44880
+
44881
+ @Field()
44882
+ @MaxLength(10)
44883
+ _mj__UpdatedAt: Date;
44884
+
44885
+ @Field({nullable: true})
44886
+ @MaxLength(510)
44887
+ Parent?: string;
44888
+
44889
+ @Field({nullable: true})
44890
+ @MaxLength(16)
44891
+ RootParentID?: string;
44892
+
44893
+ @Field(() => [MJTestSuite_])
44894
+ MJ_TestSuites_ParentIDArray: MJTestSuite_[]; // Link to MJ_TestSuites
44895
+
44896
+ @Field(() => [MJTestSuiteRun_])
44897
+ MJ_TestSuiteRuns_SuiteIDArray: MJTestSuiteRun_[]; // Link to MJ_TestSuiteRuns
44898
+
44899
+ @Field(() => [MJTestSuiteTest_])
44900
+ MJ_TestSuiteTests_SuiteIDArray: MJTestSuiteTest_[]; // Link to MJ_TestSuiteTests
44901
+
44902
+ }
44903
+
44904
+ //****************************************************************************
44905
+ // INPUT TYPE for MJ: Test Suites
44906
+ //****************************************************************************
44907
+ @InputType()
44908
+ export class CreateMJTestSuiteInput {
44909
+ @Field({ nullable: true })
44910
+ ID?: string;
44911
+
44912
+ @Field({ nullable: true })
44913
+ ParentID: string | null;
44914
+
44915
+ @Field({ nullable: true })
44916
+ Name?: string;
44917
+
44918
+ @Field({ nullable: true })
44919
+ Description: string | null;
44920
+
44921
+ @Field({ nullable: true })
44922
+ Status?: string;
44923
+
44924
+ @Field({ nullable: true })
44925
+ Tags: string | null;
44926
+
44927
+ @Field({ nullable: true })
44928
+ Configuration: string | null;
44929
+ }
44930
+
44931
+
44932
+ //****************************************************************************
44933
+ // INPUT TYPE for MJ: Test Suites
44934
+ //****************************************************************************
44935
+ @InputType()
44936
+ export class UpdateMJTestSuiteInput {
44937
+ @Field()
44938
+ ID: string;
44939
+
44940
+ @Field({ nullable: true })
44941
+ ParentID?: string | null;
44942
+
44943
+ @Field({ nullable: true })
44944
+ Name?: string;
44945
+
44946
+ @Field({ nullable: true })
44947
+ Description?: string | null;
44948
+
44949
+ @Field({ nullable: true })
44950
+ Status?: string;
44951
+
44952
+ @Field({ nullable: true })
44953
+ Tags?: string | null;
44954
+
44955
+ @Field({ nullable: true })
44956
+ Configuration?: string | null;
44957
+
44958
+ @Field(() => [KeyValuePairInput], { nullable: true })
44959
+ OldValues___?: KeyValuePairInput[];
44960
+ }
44961
+
44962
+ //****************************************************************************
44963
+ // RESOLVER for MJ: Test Suites
44964
+ //****************************************************************************
44965
+ @ObjectType()
44966
+ export class RunMJTestSuiteViewResult {
44967
+ @Field(() => [MJTestSuite_])
44968
+ Results: MJTestSuite_[];
44969
+
44970
+ @Field(() => String, {nullable: true})
44971
+ UserViewRunID?: string;
44972
+
44973
+ @Field(() => Int, {nullable: true})
44974
+ RowCount: number;
44975
+
44976
+ @Field(() => Int, {nullable: true})
44977
+ TotalRowCount: number;
44978
+
44979
+ @Field(() => Int, {nullable: true})
44980
+ ExecutionTime: number;
44981
+
44982
+ @Field({nullable: true})
44983
+ ErrorMessage?: string;
44984
+
44985
+ @Field(() => Boolean, {nullable: false})
44986
+ Success: boolean;
44987
+ }
44988
+
44989
+ @Resolver(MJTestSuite_)
44990
+ export class MJTestSuiteResolver extends ResolverBase {
44991
+ @Query(() => RunMJTestSuiteViewResult)
44992
+ async RunMJTestSuiteViewByID(@Arg('input', () => RunViewByIDInput) input: RunViewByIDInput, @Ctx() { providers, userPayload }: AppContext, @PubSub() pubSub: PubSubEngine) {
44993
+ const provider = GetReadOnlyProvider(providers, { allowFallbackToReadWrite: true });
44994
+ return super.RunViewByIDGeneric(input, provider, userPayload, pubSub);
44995
+ }
44996
+
44997
+ @Query(() => RunMJTestSuiteViewResult)
44998
+ async RunMJTestSuiteViewByName(@Arg('input', () => RunViewByNameInput) input: RunViewByNameInput, @Ctx() { providers, userPayload }: AppContext, @PubSub() pubSub: PubSubEngine) {
44999
+ const provider = GetReadOnlyProvider(providers, { allowFallbackToReadWrite: true });
45000
+ return super.RunViewByNameGeneric(input, provider, userPayload, pubSub);
45001
+ }
45002
+
45003
+ @Query(() => RunMJTestSuiteViewResult)
45004
+ async RunMJTestSuiteDynamicView(@Arg('input', () => RunDynamicViewInput) input: RunDynamicViewInput, @Ctx() { providers, userPayload }: AppContext, @PubSub() pubSub: PubSubEngine) {
45005
+ const provider = GetReadOnlyProvider(providers, { allowFallbackToReadWrite: true });
45006
+ input.EntityName = 'MJ: Test Suites';
45007
+ return super.RunDynamicViewGeneric(input, provider, userPayload, pubSub);
45008
+ }
45009
+ @Query(() => MJTestSuite_, { nullable: true })
45010
+ async MJTestSuite(@Arg('ID', () => String) ID: string, @Ctx() { dataSources, userPayload, providers }: AppContext, @PubSub() pubSub: PubSubEngine): Promise<MJTestSuite_ | null> {
45011
+ this.CheckUserReadPermissions('MJ: Test Suites', userPayload);
45012
+ const provider = GetReadOnlyProvider(providers, { allowFallbackToReadWrite: true });
45013
+ const connPool = GetReadOnlyDataSource(dataSources, { allowFallbackToReadWrite: true });
45014
+ const sSQL = `SELECT * FROM [${Metadata.Provider.ConfigData.MJCoreSchemaName}].[vwTestSuites] WHERE [ID]='${ID}' ` + this.getRowLevelSecurityWhereClause(provider, 'MJ: Test Suites', userPayload, EntityPermissionType.Read, 'AND');
45015
+ const rows = await SQLServerDataProvider.ExecuteSQLWithPool(connPool, sSQL, undefined, this.GetUserFromPayload(userPayload));
45016
+ const result = this.MapFieldNamesToCodeNames('MJ: Test Suites', rows && rows.length > 0 ? rows[0] : {})
45017
+ return result;
45018
+ }
45019
+
45020
+ @FieldResolver(() => [MJTestSuite_])
45021
+ async MJ_TestSuites_ParentIDArray(@Root() mjtestsuite_: MJTestSuite_, @Ctx() { dataSources, userPayload, providers }: AppContext, @PubSub() pubSub: PubSubEngine) {
45022
+ this.CheckUserReadPermissions('MJ: Test Suites', userPayload);
45023
+ const provider = GetReadOnlyProvider(providers, { allowFallbackToReadWrite: true });
45024
+ const connPool = GetReadOnlyDataSource(dataSources, { allowFallbackToReadWrite: true });
45025
+ const sSQL = `SELECT * FROM [${Metadata.Provider.ConfigData.MJCoreSchemaName}].[vwTestSuites] WHERE [ParentID]='${mjtestsuite_.ID}' ` + this.getRowLevelSecurityWhereClause(provider, 'MJ: Test Suites', userPayload, EntityPermissionType.Read, 'AND');
45026
+ const rows = await SQLServerDataProvider.ExecuteSQLWithPool(connPool, sSQL, undefined, this.GetUserFromPayload(userPayload));
45027
+ const result = this.ArrayMapFieldNamesToCodeNames('MJ: Test Suites', rows);
45028
+ return result;
45029
+ }
45030
+
45031
+ @FieldResolver(() => [MJTestSuiteRun_])
45032
+ async MJ_TestSuiteRuns_SuiteIDArray(@Root() mjtestsuite_: MJTestSuite_, @Ctx() { dataSources, userPayload, providers }: AppContext, @PubSub() pubSub: PubSubEngine) {
45033
+ this.CheckUserReadPermissions('MJ: Test Suite Runs', userPayload);
45034
+ const provider = GetReadOnlyProvider(providers, { allowFallbackToReadWrite: true });
45035
+ const connPool = GetReadOnlyDataSource(dataSources, { allowFallbackToReadWrite: true });
45036
+ const sSQL = `SELECT * FROM [${Metadata.Provider.ConfigData.MJCoreSchemaName}].[vwTestSuiteRuns] WHERE [SuiteID]='${mjtestsuite_.ID}' ` + this.getRowLevelSecurityWhereClause(provider, 'MJ: Test Suite Runs', userPayload, EntityPermissionType.Read, 'AND');
45037
+ const rows = await SQLServerDataProvider.ExecuteSQLWithPool(connPool, sSQL, undefined, this.GetUserFromPayload(userPayload));
45038
+ const result = this.ArrayMapFieldNamesToCodeNames('MJ: Test Suite Runs', rows);
45039
+ return result;
45040
+ }
45041
+
45042
+ @FieldResolver(() => [MJTestSuiteTest_])
45043
+ async MJ_TestSuiteTests_SuiteIDArray(@Root() mjtestsuite_: MJTestSuite_, @Ctx() { dataSources, userPayload, providers }: AppContext, @PubSub() pubSub: PubSubEngine) {
45044
+ this.CheckUserReadPermissions('MJ: Test Suite Tests', userPayload);
45045
+ const provider = GetReadOnlyProvider(providers, { allowFallbackToReadWrite: true });
45046
+ const connPool = GetReadOnlyDataSource(dataSources, { allowFallbackToReadWrite: true });
45047
+ const sSQL = `SELECT * FROM [${Metadata.Provider.ConfigData.MJCoreSchemaName}].[vwTestSuiteTests] WHERE [SuiteID]='${mjtestsuite_.ID}' ` + this.getRowLevelSecurityWhereClause(provider, 'MJ: Test Suite Tests', userPayload, EntityPermissionType.Read, 'AND');
45048
+ const rows = await SQLServerDataProvider.ExecuteSQLWithPool(connPool, sSQL, undefined, this.GetUserFromPayload(userPayload));
45049
+ const result = this.ArrayMapFieldNamesToCodeNames('MJ: Test Suite Tests', rows);
45050
+ return result;
45051
+ }
45052
+
45053
+ @Mutation(() => MJTestSuite_)
45054
+ async CreateMJTestSuite(
45055
+ @Arg('input', () => CreateMJTestSuiteInput) input: CreateMJTestSuiteInput,
45056
+ @Ctx() { providers, userPayload }: AppContext,
45057
+ @PubSub() pubSub: PubSubEngine
45058
+ ) {
45059
+ const provider = GetReadWriteProvider(providers);
45060
+ return this.CreateRecord('MJ: Test Suites', input, provider, userPayload, pubSub)
45061
+ }
45062
+
45063
+ @Mutation(() => MJTestSuite_)
45064
+ async UpdateMJTestSuite(
45065
+ @Arg('input', () => UpdateMJTestSuiteInput) input: UpdateMJTestSuiteInput,
45066
+ @Ctx() { providers, userPayload }: AppContext,
45067
+ @PubSub() pubSub: PubSubEngine
45068
+ ) {
45069
+ const provider = GetReadWriteProvider(providers);
45070
+ return this.UpdateRecord('MJ: Test Suites', input, provider, userPayload, pubSub);
45071
+ }
45072
+
45073
+ @Mutation(() => MJTestSuite_)
45074
+ async DeleteMJTestSuite(@Arg('ID', () => String) ID: string, @Arg('options___', () => DeleteOptionsInput) options: DeleteOptionsInput, @Ctx() { providers, userPayload }: AppContext, @PubSub() pubSub: PubSubEngine) {
45075
+ const provider = GetReadWriteProvider(providers);
45076
+ const key = new CompositeKey([{FieldName: 'ID', Value: ID}]);
45077
+ return this.DeleteRecord('MJ: Test Suites', key, options, provider, userPayload, pubSub);
45078
+ }
45079
+
45080
+ }
45081
+
43034
45082
  //****************************************************************************
43035
45083
  // ENTITY CLASS for MJ: Conversation Artifacts
43036
45084
  //****************************************************************************
@@ -45327,6 +47375,336 @@ export class MJComponentLibraryLinkResolver extends ResolverBase {
45327
47375
 
45328
47376
  }
45329
47377
 
47378
+ //****************************************************************************
47379
+ // ENTITY CLASS for MJ: Test Suite Runs
47380
+ //****************************************************************************
47381
+ @ObjectType({ description: `Execution instance of a test suite. Captures who ran it, when, in what environment, and aggregates results from all tests in the suite. Supports versioning via GitCommit and AgentVersion fields to track system state during execution.` })
47382
+ export class MJTestSuiteRun_ {
47383
+ @Field()
47384
+ @MaxLength(16)
47385
+ ID: string;
47386
+
47387
+ @Field({description: `Foreign Key - The test suite that was executed`})
47388
+ @MaxLength(16)
47389
+ SuiteID: string;
47390
+
47391
+ @Field({description: `Foreign Key - The user who triggered the suite run (could be system user for automated runs)`})
47392
+ @MaxLength(16)
47393
+ RunByUserID: string;
47394
+
47395
+ @Field({nullable: true, description: `Environment where tests were executed (e.g., "dev", "staging", "prod", "ci")`})
47396
+ @MaxLength(100)
47397
+ Environment?: string;
47398
+
47399
+ @Field({nullable: true, description: `How the run was triggered (e.g., "manual", "ci", "scheduled", "shadow", "release")`})
47400
+ @MaxLength(100)
47401
+ TriggerType?: string;
47402
+
47403
+ @Field({nullable: true, description: `Git commit SHA of the code version being tested. Enables correlation between test results and code changes.`})
47404
+ @MaxLength(200)
47405
+ GitCommit?: string;
47406
+
47407
+ @Field({nullable: true, description: `Version of the agent or system being tested (e.g., "skip-agent-2.1.0", "workflow-engine-3.4.2"). Enables version comparison and regression detection.`})
47408
+ @MaxLength(200)
47409
+ AgentVersion?: string;
47410
+
47411
+ @Field({description: `Current status of the suite run: Pending (queued), Running (in progress), Completed (finished successfully), Failed (suite-level failure), Cancelled (stopped by user)`})
47412
+ @MaxLength(40)
47413
+ Status: string;
47414
+
47415
+ @Field({nullable: true, description: `Timestamp when the suite run started execution`})
47416
+ @MaxLength(8)
47417
+ StartedAt?: Date;
47418
+
47419
+ @Field({nullable: true, description: `Timestamp when the suite run completed (successfully or with failures)`})
47420
+ @MaxLength(8)
47421
+ CompletedAt?: Date;
47422
+
47423
+ @Field(() => Int, {nullable: true, description: `Total number of tests executed in this suite run`})
47424
+ TotalTests?: number;
47425
+
47426
+ @Field(() => Int, {nullable: true, description: `Number of tests that passed all checks`})
47427
+ PassedTests?: number;
47428
+
47429
+ @Field(() => Int, {nullable: true, description: `Number of tests that failed at least one check`})
47430
+ FailedTests?: number;
47431
+
47432
+ @Field(() => Int, {nullable: true, description: `Number of tests that were skipped (not executed)`})
47433
+ SkippedTests?: number;
47434
+
47435
+ @Field(() => Int, {nullable: true, description: `Number of tests that encountered execution errors (different from failing validation)`})
47436
+ ErrorTests?: number;
47437
+
47438
+ @Field(() => Float, {nullable: true, description: `Total execution time in seconds for the entire suite`})
47439
+ TotalDurationSeconds?: number;
47440
+
47441
+ @Field(() => Float, {nullable: true, description: `Total cost in USD for running the entire suite (sum of all test costs)`})
47442
+ TotalCostUSD?: number;
47443
+
47444
+ @Field({nullable: true, description: `JSON snapshot of the runtime configuration used for this suite run`})
47445
+ Configuration?: string;
47446
+
47447
+ @Field({nullable: true, description: `JSON object with aggregated results and statistics from the suite run`})
47448
+ ResultSummary?: string;
47449
+
47450
+ @Field({nullable: true, description: `Error message if the suite-level execution failed (before individual tests could run)`})
47451
+ ErrorMessage?: string;
47452
+
47453
+ @Field()
47454
+ @MaxLength(10)
47455
+ _mj__CreatedAt: Date;
47456
+
47457
+ @Field()
47458
+ @MaxLength(10)
47459
+ _mj__UpdatedAt: Date;
47460
+
47461
+ @Field()
47462
+ @MaxLength(510)
47463
+ Suite: string;
47464
+
47465
+ @Field()
47466
+ @MaxLength(200)
47467
+ RunByUser: string;
47468
+
47469
+ @Field(() => [MJTestRun_])
47470
+ MJ_TestRuns_TestSuiteRunIDArray: MJTestRun_[]; // Link to MJ_TestRuns
47471
+
47472
+ }
47473
+
47474
+ //****************************************************************************
47475
+ // INPUT TYPE for MJ: Test Suite Runs
47476
+ //****************************************************************************
47477
+ @InputType()
47478
+ export class CreateMJTestSuiteRunInput {
47479
+ @Field({ nullable: true })
47480
+ ID?: string;
47481
+
47482
+ @Field({ nullable: true })
47483
+ SuiteID?: string;
47484
+
47485
+ @Field({ nullable: true })
47486
+ RunByUserID?: string;
47487
+
47488
+ @Field({ nullable: true })
47489
+ Environment: string | null;
47490
+
47491
+ @Field({ nullable: true })
47492
+ TriggerType: string | null;
47493
+
47494
+ @Field({ nullable: true })
47495
+ GitCommit: string | null;
47496
+
47497
+ @Field({ nullable: true })
47498
+ AgentVersion: string | null;
47499
+
47500
+ @Field({ nullable: true })
47501
+ Status?: string;
47502
+
47503
+ @Field({ nullable: true })
47504
+ StartedAt: Date | null;
47505
+
47506
+ @Field({ nullable: true })
47507
+ CompletedAt: Date | null;
47508
+
47509
+ @Field(() => Int, { nullable: true })
47510
+ TotalTests: number | null;
47511
+
47512
+ @Field(() => Int, { nullable: true })
47513
+ PassedTests: number | null;
47514
+
47515
+ @Field(() => Int, { nullable: true })
47516
+ FailedTests: number | null;
47517
+
47518
+ @Field(() => Int, { nullable: true })
47519
+ SkippedTests: number | null;
47520
+
47521
+ @Field(() => Int, { nullable: true })
47522
+ ErrorTests: number | null;
47523
+
47524
+ @Field(() => Float, { nullable: true })
47525
+ TotalDurationSeconds: number | null;
47526
+
47527
+ @Field(() => Float, { nullable: true })
47528
+ TotalCostUSD: number | null;
47529
+
47530
+ @Field({ nullable: true })
47531
+ Configuration: string | null;
47532
+
47533
+ @Field({ nullable: true })
47534
+ ResultSummary: string | null;
47535
+
47536
+ @Field({ nullable: true })
47537
+ ErrorMessage: string | null;
47538
+ }
47539
+
47540
+
47541
+ //****************************************************************************
47542
+ // INPUT TYPE for MJ: Test Suite Runs
47543
+ //****************************************************************************
47544
+ @InputType()
47545
+ export class UpdateMJTestSuiteRunInput {
47546
+ @Field()
47547
+ ID: string;
47548
+
47549
+ @Field({ nullable: true })
47550
+ SuiteID?: string;
47551
+
47552
+ @Field({ nullable: true })
47553
+ RunByUserID?: string;
47554
+
47555
+ @Field({ nullable: true })
47556
+ Environment?: string | null;
47557
+
47558
+ @Field({ nullable: true })
47559
+ TriggerType?: string | null;
47560
+
47561
+ @Field({ nullable: true })
47562
+ GitCommit?: string | null;
47563
+
47564
+ @Field({ nullable: true })
47565
+ AgentVersion?: string | null;
47566
+
47567
+ @Field({ nullable: true })
47568
+ Status?: string;
47569
+
47570
+ @Field({ nullable: true })
47571
+ StartedAt?: Date | null;
47572
+
47573
+ @Field({ nullable: true })
47574
+ CompletedAt?: Date | null;
47575
+
47576
+ @Field(() => Int, { nullable: true })
47577
+ TotalTests?: number | null;
47578
+
47579
+ @Field(() => Int, { nullable: true })
47580
+ PassedTests?: number | null;
47581
+
47582
+ @Field(() => Int, { nullable: true })
47583
+ FailedTests?: number | null;
47584
+
47585
+ @Field(() => Int, { nullable: true })
47586
+ SkippedTests?: number | null;
47587
+
47588
+ @Field(() => Int, { nullable: true })
47589
+ ErrorTests?: number | null;
47590
+
47591
+ @Field(() => Float, { nullable: true })
47592
+ TotalDurationSeconds?: number | null;
47593
+
47594
+ @Field(() => Float, { nullable: true })
47595
+ TotalCostUSD?: number | null;
47596
+
47597
+ @Field({ nullable: true })
47598
+ Configuration?: string | null;
47599
+
47600
+ @Field({ nullable: true })
47601
+ ResultSummary?: string | null;
47602
+
47603
+ @Field({ nullable: true })
47604
+ ErrorMessage?: string | null;
47605
+
47606
+ @Field(() => [KeyValuePairInput], { nullable: true })
47607
+ OldValues___?: KeyValuePairInput[];
47608
+ }
47609
+
47610
+ //****************************************************************************
47611
+ // RESOLVER for MJ: Test Suite Runs
47612
+ //****************************************************************************
47613
+ @ObjectType()
47614
+ export class RunMJTestSuiteRunViewResult {
47615
+ @Field(() => [MJTestSuiteRun_])
47616
+ Results: MJTestSuiteRun_[];
47617
+
47618
+ @Field(() => String, {nullable: true})
47619
+ UserViewRunID?: string;
47620
+
47621
+ @Field(() => Int, {nullable: true})
47622
+ RowCount: number;
47623
+
47624
+ @Field(() => Int, {nullable: true})
47625
+ TotalRowCount: number;
47626
+
47627
+ @Field(() => Int, {nullable: true})
47628
+ ExecutionTime: number;
47629
+
47630
+ @Field({nullable: true})
47631
+ ErrorMessage?: string;
47632
+
47633
+ @Field(() => Boolean, {nullable: false})
47634
+ Success: boolean;
47635
+ }
47636
+
47637
+ @Resolver(MJTestSuiteRun_)
47638
+ export class MJTestSuiteRunResolver extends ResolverBase {
47639
+ @Query(() => RunMJTestSuiteRunViewResult)
47640
+ async RunMJTestSuiteRunViewByID(@Arg('input', () => RunViewByIDInput) input: RunViewByIDInput, @Ctx() { providers, userPayload }: AppContext, @PubSub() pubSub: PubSubEngine) {
47641
+ const provider = GetReadOnlyProvider(providers, { allowFallbackToReadWrite: true });
47642
+ return super.RunViewByIDGeneric(input, provider, userPayload, pubSub);
47643
+ }
47644
+
47645
+ @Query(() => RunMJTestSuiteRunViewResult)
47646
+ async RunMJTestSuiteRunViewByName(@Arg('input', () => RunViewByNameInput) input: RunViewByNameInput, @Ctx() { providers, userPayload }: AppContext, @PubSub() pubSub: PubSubEngine) {
47647
+ const provider = GetReadOnlyProvider(providers, { allowFallbackToReadWrite: true });
47648
+ return super.RunViewByNameGeneric(input, provider, userPayload, pubSub);
47649
+ }
47650
+
47651
+ @Query(() => RunMJTestSuiteRunViewResult)
47652
+ async RunMJTestSuiteRunDynamicView(@Arg('input', () => RunDynamicViewInput) input: RunDynamicViewInput, @Ctx() { providers, userPayload }: AppContext, @PubSub() pubSub: PubSubEngine) {
47653
+ const provider = GetReadOnlyProvider(providers, { allowFallbackToReadWrite: true });
47654
+ input.EntityName = 'MJ: Test Suite Runs';
47655
+ return super.RunDynamicViewGeneric(input, provider, userPayload, pubSub);
47656
+ }
47657
+ @Query(() => MJTestSuiteRun_, { nullable: true })
47658
+ async MJTestSuiteRun(@Arg('ID', () => String) ID: string, @Ctx() { dataSources, userPayload, providers }: AppContext, @PubSub() pubSub: PubSubEngine): Promise<MJTestSuiteRun_ | null> {
47659
+ this.CheckUserReadPermissions('MJ: Test Suite Runs', userPayload);
47660
+ const provider = GetReadOnlyProvider(providers, { allowFallbackToReadWrite: true });
47661
+ const connPool = GetReadOnlyDataSource(dataSources, { allowFallbackToReadWrite: true });
47662
+ const sSQL = `SELECT * FROM [${Metadata.Provider.ConfigData.MJCoreSchemaName}].[vwTestSuiteRuns] WHERE [ID]='${ID}' ` + this.getRowLevelSecurityWhereClause(provider, 'MJ: Test Suite Runs', userPayload, EntityPermissionType.Read, 'AND');
47663
+ const rows = await SQLServerDataProvider.ExecuteSQLWithPool(connPool, sSQL, undefined, this.GetUserFromPayload(userPayload));
47664
+ const result = this.MapFieldNamesToCodeNames('MJ: Test Suite Runs', rows && rows.length > 0 ? rows[0] : {})
47665
+ return result;
47666
+ }
47667
+
47668
+ @FieldResolver(() => [MJTestRun_])
47669
+ async MJ_TestRuns_TestSuiteRunIDArray(@Root() mjtestsuiterun_: MJTestSuiteRun_, @Ctx() { dataSources, userPayload, providers }: AppContext, @PubSub() pubSub: PubSubEngine) {
47670
+ this.CheckUserReadPermissions('MJ: Test Runs', userPayload);
47671
+ const provider = GetReadOnlyProvider(providers, { allowFallbackToReadWrite: true });
47672
+ const connPool = GetReadOnlyDataSource(dataSources, { allowFallbackToReadWrite: true });
47673
+ const sSQL = `SELECT * FROM [${Metadata.Provider.ConfigData.MJCoreSchemaName}].[vwTestRuns] WHERE [TestSuiteRunID]='${mjtestsuiterun_.ID}' ` + this.getRowLevelSecurityWhereClause(provider, 'MJ: Test Runs', userPayload, EntityPermissionType.Read, 'AND');
47674
+ const rows = await SQLServerDataProvider.ExecuteSQLWithPool(connPool, sSQL, undefined, this.GetUserFromPayload(userPayload));
47675
+ const result = this.ArrayMapFieldNamesToCodeNames('MJ: Test Runs', rows);
47676
+ return result;
47677
+ }
47678
+
47679
+ @Mutation(() => MJTestSuiteRun_)
47680
+ async CreateMJTestSuiteRun(
47681
+ @Arg('input', () => CreateMJTestSuiteRunInput) input: CreateMJTestSuiteRunInput,
47682
+ @Ctx() { providers, userPayload }: AppContext,
47683
+ @PubSub() pubSub: PubSubEngine
47684
+ ) {
47685
+ const provider = GetReadWriteProvider(providers);
47686
+ return this.CreateRecord('MJ: Test Suite Runs', input, provider, userPayload, pubSub)
47687
+ }
47688
+
47689
+ @Mutation(() => MJTestSuiteRun_)
47690
+ async UpdateMJTestSuiteRun(
47691
+ @Arg('input', () => UpdateMJTestSuiteRunInput) input: UpdateMJTestSuiteRunInput,
47692
+ @Ctx() { providers, userPayload }: AppContext,
47693
+ @PubSub() pubSub: PubSubEngine
47694
+ ) {
47695
+ const provider = GetReadWriteProvider(providers);
47696
+ return this.UpdateRecord('MJ: Test Suite Runs', input, provider, userPayload, pubSub);
47697
+ }
47698
+
47699
+ @Mutation(() => MJTestSuiteRun_)
47700
+ async DeleteMJTestSuiteRun(@Arg('ID', () => String) ID: string, @Arg('options___', () => DeleteOptionsInput) options: DeleteOptionsInput, @Ctx() { providers, userPayload }: AppContext, @PubSub() pubSub: PubSubEngine) {
47701
+ const provider = GetReadWriteProvider(providers);
47702
+ const key = new CompositeKey([{FieldName: 'ID', Value: ID}]);
47703
+ return this.DeleteRecord('MJ: Test Suite Runs', key, options, provider, userPayload, pubSub);
47704
+ }
47705
+
47706
+ }
47707
+
45330
47708
  //****************************************************************************
45331
47709
  // ENTITY CLASS for Content Process Runs
45332
47710
  //****************************************************************************
@@ -48299,6 +50677,10 @@ export class MJAIPromptRun_ {
48299
50677
  @Field({nullable: true, description: `Human-readable notes and comments about this prompt run`})
48300
50678
  Comments?: string;
48301
50679
 
50680
+ @Field({nullable: true, description: `Optional Foreign Key - Links this prompt run to a test run if this prompt execution was part of a test. Enables testing individual prompts for quality and consistency before agent integration.`})
50681
+ @MaxLength(16)
50682
+ TestRunID?: string;
50683
+
48302
50684
  @Field()
48303
50685
  @MaxLength(510)
48304
50686
  Prompt: string;
@@ -48319,10 +50701,22 @@ export class MJAIPromptRun_ {
48319
50701
  @MaxLength(200)
48320
50702
  Configuration?: string;
48321
50703
 
50704
+ @Field({nullable: true})
50705
+ @MaxLength(510)
50706
+ Parent?: string;
50707
+
50708
+ @Field({nullable: true})
50709
+ @MaxLength(510)
50710
+ AgentRun?: string;
50711
+
48322
50712
  @Field({nullable: true})
48323
50713
  @MaxLength(100)
48324
50714
  OriginalModel?: string;
48325
50715
 
50716
+ @Field({nullable: true})
50717
+ @MaxLength(510)
50718
+ RerunFromPromptRun?: string;
50719
+
48326
50720
  @Field({nullable: true})
48327
50721
  @MaxLength(510)
48328
50722
  Judge?: string;
@@ -48594,6 +50988,9 @@ export class CreateMJAIPromptRunInput {
48594
50988
 
48595
50989
  @Field({ nullable: true })
48596
50990
  Comments: string | null;
50991
+
50992
+ @Field({ nullable: true })
50993
+ TestRunID: string | null;
48597
50994
  }
48598
50995
 
48599
50996
 
@@ -48845,6 +51242,9 @@ export class UpdateMJAIPromptRunInput {
48845
51242
  @Field({ nullable: true })
48846
51243
  Comments?: string | null;
48847
51244
 
51245
+ @Field({ nullable: true })
51246
+ TestRunID?: string | null;
51247
+
48848
51248
  @Field(() => [KeyValuePairInput], { nullable: true })
48849
51249
  OldValues___?: KeyValuePairInput[];
48850
51250
  }